diff --git a/.codecov.yml b/.codecov.yml index f2482097c10a9..07178456a6804 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -43,4 +43,5 @@ ignore: - "executor/seqtest/.*" - "metrics/.*" - "expression/generator/.*" + - "br/pkg/mock/.*" diff --git a/.github/licenserc.yml b/.github/licenserc.yml index 52976b36f8686..97565bdc1c476 100644 --- a/.github/licenserc.yml +++ b/.github/licenserc.yml @@ -10,6 +10,7 @@ header: - '.golangci.yml' - '.golangci_br.yml' - 'LICENSES/' + - '**/*.key' - '**/*.md' - '**/*.json' - '**/*.pem' @@ -28,4 +29,6 @@ header: - '.github/' - 'parser/' - 'dumpling/' + - 'tidb-binlog/driver/example' + - 'tidb-binlog/proto/go-binlog/secondary_binlog.pb.go' comment: on-failure diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3eef4ea0a6587..f67985fd41669 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,6 +9,16 @@ PR Title Format: --> ### What problem does this PR solve? + Issue Number: close #xxx @@ -41,7 +51,9 @@ Documentation ### Release note - + + +Please refer to [Release Notes Language Style Guide](https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/release-notes-style-guide.html) to write a quality release note. ```release-note None diff --git a/.github/workflows/br_compatible_test.yml b/.github/workflows/br_compatible_test.yml index aeccfb0a2eff0..149b70db1b068 100644 --- a/.github/workflows/br_compatible_test.yml +++ b/.github/workflows/br_compatible_test.yml @@ -46,7 +46,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - name: Generate compatibility test backup data timeout-minutes: 15 diff --git a/.github/workflows/bug-closed.yml b/.github/workflows/bug-closed.yml deleted file mode 100644 index 36e8574f00e19..0000000000000 --- a/.github/workflows/bug-closed.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Bug Closed - -on: - issues: - types: - - closed - -jobs: - label_issues: - if: | - contains(github.event.issue.labels.*.name, 'type/bug') && - !(contains(join(github.event.issue.labels.*.name, ', '), 'affects-') && - contains(join(github.event.issue.labels.*.name, ', '), 'fixes-')) - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Label issues - uses: andymckay/labeler@1.0.3 - with: - add-labels: "needs-more-info" - repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Add comment - uses: peter-evans/create-or-update-comment@v1.4.5 - with: - issue-number: ${{ github.event.issue.number }} - body: | - Please check whether the issue should be labeled with 'affects-x.y' or 'fixes-x.y.z', and then remove 'needs-more-info' label. diff --git a/.github/workflows/compile_br.yaml b/.github/workflows/compile_br.yaml index acfbc2d27bad5..3d6ae87beea7c 100644 --- a/.github/workflows/compile_br.yaml +++ b/.github/workflows/compile_br.yaml @@ -48,7 +48,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - name: Run build run: make build_tools @@ -73,7 +73,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - name: Run build run: make build_tools @@ -88,7 +88,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - name: Compile for FreeBSD run: GOOS=freebsd make build_tools diff --git a/.github/workflows/dumpling_integration_test.yml b/.github/workflows/dumpling_integration_test.yml index 8390ef961f44d..75395b9e271ef 100644 --- a/.github/workflows/dumpling_integration_test.yml +++ b/.github/workflows/dumpling_integration_test.yml @@ -50,10 +50,10 @@ jobs: - uses: actions/checkout@v2 - name: Shutdown Ubuntu MySQL (SUDO) run: sudo service mysql stop # Shutdown the Default MySQL, "sudo" is necessary, please not remove it - - name: Set up Go 1.16 + - name: Set up Go 1.18 uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - uses: actions/cache@v2 with: path: ~/go/pkg/mod @@ -87,10 +87,10 @@ jobs: - uses: actions/checkout@v2 - name: Shutdown Ubuntu MySQL (SUDO) run: sudo service mysql stop # Shutdown the Default MySQL, "sudo" is necessary, please not remove it - - name: Set up Go 1.16 + - name: Set up Go 1.18 uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - uses: actions/cache@v2 with: path: ~/go/pkg/mod @@ -124,10 +124,10 @@ jobs: - uses: actions/checkout@v2 - name: Shutdown Ubuntu MySQL (SUDO) run: sudo service mysql stop # Shutdown the Default MySQL, "sudo" is necessary, please not remove it - - name: Set up Go 1.16 + - name: Set up Go 1.18 uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.18 - uses: actions/cache@v2 with: path: ~/go/pkg/mod diff --git a/.gitignore b/.gitignore index c71bd34b114bd..ec864762068de 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ coverage.out *.iml *.swp *.log +*.test.bin tags profile.coverprofile explain_test @@ -26,3 +27,5 @@ fix.sql export-20*/ *-coverage.xml *-junit-report.xml +# Files generated when testing +out diff --git a/.golangci.yml b/.golangci.yml index 60670adf3c311..f82bace0fbd8c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,12 +23,19 @@ linters: - unconvert - makezero - durationcheck + - prealloc + - predeclared linters-settings: staticcheck: checks: ["S1002","S1004","S1007","S1009","S1010","S1012","S1019","S1020","S1021","S1024","S1030","SA2*","SA3*","SA4009","SA5*","SA6000","SA6001","SA6005", "-SA2002"] stylecheck: checks: ["-ST1003"] + gosec: + severity: "low" + confidence: "low" + excludes: + - G101 issues: exclude-rules: - path: _test\.go diff --git a/.golangci_br.yml b/.golangci_br.yml deleted file mode 100644 index 28bbba74f749f..0000000000000 --- a/.golangci_br.yml +++ /dev/null @@ -1,83 +0,0 @@ -run: - concurrency: 4 - timeout: 7m - -output: - format: colored-line-number - print-issued-lines: true - print-linter-name: true - -linters: - enable-all: true - disable: - - gochecknoglobals - - gci - - wsl - - funlen - - gocognit - - godox - - gomnd - - testpackage - - nestif - - goerr113 - - lll - - paralleltest - - nlreturn - - exhaustivestruct - - exhaustive - - godot - - gosec - - errorlint - - wrapcheck - - gomoddirectives - - bodyclose - - unused - - unparam - - wastedassign - - tagliatelle - - thelper - - nolintlint - - ineffassign - - nilerr - - noctx - - rowserrcheck - - predeclared - - ifshort - - cyclop - - whitespace - - unconvert - - forcetypeassert - - sqlclosecheck - - errcheck - - gocritic - - golint - - gocyclo - - promlinter - - forbidigo - - gochecknoinits - - scopelint - - revive - - misspell - - maligned - - makezero - - interfacer - - gofumpt - - goconst - - prealloc - - govet - - dupl - - deadcode - - varcheck - - nakedret - -linters-settings: - staticcheck: - checks: ["S1002","S1004","S1007","S1009","S1010","S1012","S1019","S1020","S1021","S1024","S1030","SA2*","SA3*","SA4009","SA5*","SA6000","SA6001","SA6005", "-SA2002"] - stylecheck: - checks: ["-ST1003"] - gosec: - excludes: - - G601 - -issues: - exclude-rules: diff --git a/Makefile b/Makefile index 3e7fb1f5be216..7cb288823fefb 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ include Makefile.common -.PHONY: all clean test gotest server dev benchkv benchraw check checklist parser tidy ddltest build_br build_lightning build_lightning-ctl build_dumpling +.PHONY: all clean test gotest server dev benchkv benchraw check checklist parser tidy ddltest build_br build_lightning build_lightning-ctl build_dumpling ut default: server buildsucc @@ -28,13 +28,13 @@ all: dev server benchkv parser: @echo "remove this command later, when our CI script doesn't call it" -dev: checklist check explaintest devgotest gogenerate br_unit_test test_part_parser_dev +dev: checklist check explaintest gogenerate br_unit_test test_part_parser_dev ut @>&2 echo "Great, all tests passed." # Install the check tools. check-setup:tools/bin/revive tools/bin/goword -check: fmt unconvert lint tidy testSuite check-static vet errdoc +check: fmt check-parallel unconvert lint tidy testSuite check-static vet errdoc fmt: @echo "gofmt (simplify)" @@ -44,11 +44,10 @@ goword:tools/bin/goword tools/bin/goword $(FILES) 2>&1 | $(FAIL_ON_STDOUT) check-static: tools/bin/golangci-lint - GO111MODULE=on CGO_ENABLED=0 tools/bin/golangci-lint run -v $$($(PACKAGE_DIRECTORIES_TIDB_TESTS)) --config .golangci.yml - GO111MODULE=on CGO_ENABLED=0 tools/bin/golangci-lint run -v $$($(BR_PACKAGE_DIRECTORIES)) --config .golangci_br.yml + GO111MODULE=on CGO_ENABLED=0 tools/bin/golangci-lint run -v $$($(PACKAGE_DIRECTORIES)) --config .golangci.yml unconvert:tools/bin/unconvert - @echo "unconvert check(skip check the genenrated or copied code in lightning)" + @echo "unconvert check(skip check the generated or copied code in lightning)" @GO111MODULE=on tools/bin/unconvert $(UNCONVERT_PACKAGES) gogenerate: @@ -75,6 +74,13 @@ testSuite: @echo "testSuite" ./tools/check/check_testSuite.sh +check-parallel: +# Make sure no tests are run in parallel to prevent possible unstable tests. +# See https://github.com/pingcap/tidb/pull/30692. + @! find . -name "*_test.go" -not -path "./vendor/*" -print0 | \ + xargs -0 grep -F -n "t.Parallel()" || \ + ! echo "Error: all the go tests should be run in serial." + clean: failpoint-disable $(GO) clean -i ./... @@ -109,15 +115,12 @@ explaintest: server_check ddltest: @cd cmd/ddltest && $(GO) test -o ../../bin/ddltest -c -devgotest: failpoint-enable -# grep regex: Filter out all tidb logs starting with: -# - '[20' (like [2021/09/15 ...] [INFO]..) -# - 'PASS:' to ignore passed tests -# - 'ok ' to ignore passed directories - @echo "Running in native mode." - @export log_level=info; export TZ='Asia/Shanghai'; \ - $(GOTEST) -ldflags '$(TEST_LDFLAGS)' $(EXTRA_TEST_ARGS) -cover $(PACKAGES_TIDB_TESTS) -check.p true > gotest.log || { $(FAILPOINT_DISABLE); grep -v '^\([[]20\|PASS:\|ok \)' 'gotest.log'; exit 1; } +CLEAN_UT_BINARY := find . -name '*.test.bin'| xargs rm + +ut: tools/bin/ut tools/bin/xprog failpoint-enable + tools/bin/ut $(X) || { $(FAILPOINT_DISABLE); exit 1; } @$(FAILPOINT_DISABLE) + @$(CLEAN_UT_BINARY) gotest: failpoint-enable @echo "Running in native mode." @@ -125,30 +128,28 @@ gotest: failpoint-enable $(GOTEST) -ldflags '$(TEST_LDFLAGS)' $(EXTRA_TEST_ARGS) -timeout 20m -cover $(PACKAGES_TIDB_TESTS) -coverprofile=coverage.txt -check.p true > gotest.log || { $(FAILPOINT_DISABLE); cat 'gotest.log'; exit 1; } @$(FAILPOINT_DISABLE) -gotest_in_verify_ci_part_1: failpoint-enable tools/bin/gotestsum tools/bin/gocov tools/bin/gocov-xml - @echo "Running gotest_in_verify_ci_part_1." +gotest_in_verify_ci: tools/bin/xprog tools/bin/ut failpoint-enable + @echo "Running gotest_in_verify_ci" @mkdir -p $(TEST_COVERAGE_DIR) - @export log_level=info; export TZ='Asia/Shanghai'; \ - CGO_ENABLED=1 tools/bin/gotestsum --junitfile "$(TEST_COVERAGE_DIR)/tidb-junit-report.xml" -- -v -p $(P) --race \ - -ldflags '$(TEST_LDFLAGS)' $(EXTRA_TEST_ARGS) -coverprofile="$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" \ - $(PACKAGES_TIDB_TESTS_EXPENSIVE) -check.p true || { $(FAILPOINT_DISABLE); exit 1; } - tools/bin/gocov convert "$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" | tools/bin/gocov-xml > "$(TEST_COVERAGE_DIR)/tidb-coverage.xml" + @export TZ='Asia/Shanghai'; \ + tools/bin/ut --junitfile "$(TEST_COVERAGE_DIR)/tidb-junit-report.xml" --coverprofile "$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" --except unstable.txt || { $(FAILPOINT_DISABLE); exit 1; } @$(FAILPOINT_DISABLE) + @$(CLEAN_UT_BINARY) -gotest_in_verify_ci_part_2: failpoint-enable tools/bin/gotestsum tools/bin/gocov tools/bin/gocov-xml - @echo "Running gotest_in_verify_ci_part_2." +gotest_unstable_in_verify_ci: tools/bin/xprog tools/bin/ut failpoint-enable + @echo "Running gotest_in_verify_ci" @mkdir -p $(TEST_COVERAGE_DIR) - @export log_level=info; export TZ='Asia/Shanghai'; \ - CGO_ENABLED=1 tools/bin/gotestsum --junitfile "$(TEST_COVERAGE_DIR)/tidb-junit-report.xml" -- -v -p $(P) --race \ - -ldflags '$(TEST_LDFLAGS)' $(EXTRA_TEST_ARGS) -coverprofile="$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" \ - $(PACKAGES_TIDB_TESTS_OTHERS) -check.p true || { $(FAILPOINT_DISABLE); exit 1; } - tools/bin/gocov convert "$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" | tools/bin/gocov-xml > "$(TEST_COVERAGE_DIR)/tidb-coverage.xml" + @export TZ='Asia/Shanghai'; \ + tools/bin/ut --junitfile "$(TEST_COVERAGE_DIR)/tidb-junit-report.xml" --coverprofile "$(TEST_COVERAGE_DIR)/tidb_cov.unit_test.out" --only unstable.txt || { $(FAILPOINT_DISABLE); exit 1; } @$(FAILPOINT_DISABLE) + @$(CLEAN_UT_BINARY) race: failpoint-enable - @export log_level=debug; \ - $(GOTEST) -timeout 25m -race $(PACKAGES) || { $(FAILPOINT_DISABLE); exit 1; } + @mkdir -p $(TEST_COVERAGE_DIR) + @export TZ='Asia/Shanghai'; \ + tools/bin/ut --race --junitfile "$(TEST_COVERAGE_DIR)/tidb-junit-report.xml" --coverprofile "$(TEST_COVERAGE_DIR)/tidb_cov.unit_test" --except unstable.txt || { $(FAILPOINT_DISABLE); exit 1; } @$(FAILPOINT_DISABLE) + @$(CLEAN_UT_BINARY) leak: failpoint-enable @export log_level=debug; \ @@ -213,6 +214,14 @@ failpoint-disable: tools/bin/failpoint-ctl # Restoring gofail failpoints... @$(FAILPOINT_DISABLE) +tools/bin/ut: tools/check/ut.go + cd tools/check; \ + $(GO) build -o ../bin/ut ut.go + +tools/bin/xprog: tools/check/xprog.go + cd tools/check; \ + $(GO) build -o ../bin/xprog xprog.go + tools/bin/megacheck: tools/check/go.mod cd tools/check; \ $(GO) build -o ../bin/megacheck honnef.co/go/tools/cmd/megacheck @@ -238,7 +247,11 @@ tools/bin/errdoc-gen: tools/check/go.mod $(GO) build -o ../bin/errdoc-gen github.com/pingcap/errors/errdoc-gen tools/bin/golangci-lint: - curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b ./tools/bin v1.41.1 + cd tools/check; \ + $(GO) build -o ../bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint + # Build from source is not recommand. See https://golangci-lint.run/usage/install/ + # But the following script from their website doesn't work with Go1.18: + # curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b ./tools/bin v1.44.2 tools/bin/vfsgendev: tools/check/go.mod cd tools/check; \ @@ -326,13 +339,12 @@ br_unit_test: $(GOTEST) $(RACE_FLAG) -ldflags '$(LDFLAGS)' -tags leak $(ARGS) -coverprofile=coverage.txt || ( make failpoint-disable && exit 1 ) @make failpoint-disable br_unit_test_in_verify_ci: export ARGS=$$($(BR_PACKAGES)) -br_unit_test_in_verify_ci: tools/bin/gotestsum tools/bin/gocov tools/bin/gocov-xml +br_unit_test_in_verify_ci: tools/bin/gotestsum @make failpoint-enable @export TZ='Asia/Shanghai'; @mkdir -p $(TEST_COVERAGE_DIR) CGO_ENABLED=1 tools/bin/gotestsum --junitfile "$(TEST_COVERAGE_DIR)/br-junit-report.xml" -- $(RACE_FLAG) -ldflags '$(LDFLAGS)' \ -tags leak $(ARGS) -coverprofile="$(TEST_COVERAGE_DIR)/br_cov.unit_test.out" || ( make failpoint-disable && exit 1 ) - tools/bin/gocov convert "$(TEST_COVERAGE_DIR)/br_cov.unit_test.out" | tools/bin/gocov-xml > "$(TEST_COVERAGE_DIR)/br-coverage.xml" @make failpoint-disable br_integration_test: br_bins build_br build_for_br_integration_test @@ -392,11 +404,10 @@ dumpling_unit_test: failpoint-enable $(DUMPLING_GOTEST) $(RACE_FLAG) -coverprofile=coverage.txt -covermode=atomic -tags leak $(DUMPLING_ARGS) || ( make failpoint-disable && exit 1 ) @make failpoint-disable dumpling_unit_test_in_verify_ci: export DUMPLING_ARGS=$$($(DUMPLING_PACKAGES)) -dumpling_unit_test_in_verify_ci: failpoint-enable tools/bin/gotestsum tools/bin/gocov tools/bin/gocov-xml +dumpling_unit_test_in_verify_ci: failpoint-enable tools/bin/gotestsum @mkdir -p $(TEST_COVERAGE_DIR) CGO_ENABLED=1 tools/bin/gotestsum --junitfile "$(TEST_COVERAGE_DIR)/dumpling-junit-report.xml" -- -tags leak $(DUMPLING_ARGS) \ $(RACE_FLAG) -coverprofile="$(TEST_COVERAGE_DIR)/dumpling_cov.unit_test.out" || ( make failpoint-disable && exit 1 ) - tools/bin/gocov convert "$(TEST_COVERAGE_DIR)/dumpling_cov.unit_test.out" | tools/bin/gocov-xml > "$(TEST_COVERAGE_DIR)/dumpling-coverage.xml" @make failpoint-disable dumpling_integration_test: dumpling_bins failpoint-enable build_dumpling @@ -421,8 +432,5 @@ dumpling_bins: tools/bin/gotestsum: tools/check/go.mod cd tools/check && $(GO) build -o ../bin/gotestsum gotest.tools/gotestsum -tools/bin/gocov: tools/check/go.mod - cd tools/check && $(GO) build -o ../bin/gocov github.com/axw/gocov/gocov - -tools/bin/gocov-xml: tools/check/go.mod - cd tools/check && $(GO) build -o ../bin/gocov-xml github.com/AlekSi/gocov-xml +generate_grafana_scripts: + @cd metrics/grafana && mv tidb_summary.json tidb_summary.json.committed && ./generate_json.sh && diff -u tidb_summary.json.committed tidb_summary.json && rm tidb_summary.json.committed diff --git a/Makefile.common b/Makefile.common index 2a8ea369521b1..163c901861fd1 100644 --- a/Makefile.common +++ b/Makefile.common @@ -47,17 +47,14 @@ MAC := "Darwin" PACKAGE_LIST := go list ./... PACKAGE_LIST_TIDB_TESTS := go list ./... | grep -vE "github.com\/pingcap\/tidb\/br|github.com\/pingcap\/tidb\/cmd|github.com\/pingcap\/tidb\/dumpling" -PACKAGE_LIST_TEST_OTHERS := go list ./... | grep -vE "github.com\/pingcap\/tidb\/br|github.com\/pingcap\/tidb\/cmd|github.com\/pingcap\/tidb\/dumpling|github.com\/pingcap\/tidb\/executor|github.com\/pingcap\/tidb\/cmd|github.com\/pingcap\/tidb\/ddl" PACKAGES ?= $$($(PACKAGE_LIST)) PACKAGES_TIDB_TESTS ?= $$($(PACKAGE_LIST_TIDB_TESTS)) -PACKAGES_TIDB_TESTS_EXPENSIVE ?= "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/ddl" -PACKAGES_TIDB_TESTS_OTHERS ?= $$($(PACKAGE_LIST_TEST_OTHERS)) PACKAGE_DIRECTORIES := $(PACKAGE_LIST) | sed 's|github.com/pingcap/$(PROJECT)/||' PACKAGE_DIRECTORIES_TIDB_TESTS := $(PACKAGE_LIST_TIDB_TESTS) | sed 's|github.com/pingcap/$(PROJECT)/||' FILES := $$(find $$($(PACKAGE_DIRECTORIES)) -name "*.go") FILES_TIDB_TESTS := $$(find $$($(PACKAGE_DIRECTORIES_TIDB_TESTS)) -name "*.go") -UNCONVERT_PACKAGES_LIST := go list ./...| grep -vE "lightning\/checkpoints|lightning\/manual|lightning\/common" +UNCONVERT_PACKAGES_LIST := go list ./...| grep -vE "lightning\/checkpoints|lightning\/manual|lightning\/common|tidb-binlog\/proto\/go-binlog" UNCONVERT_PACKAGES := $$($(UNCONVERT_PACKAGES_LIST)) FAILPOINT_ENABLE := find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl enable diff --git a/README.md b/README.md index 8d14579d316e6..d6323c0efc494 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,12 @@ For support, please contact [PingCAP](http://bit.ly/contact_us_via_github). ## Quick start +### To start using TiDB Cloud + +We provide TiDB Cloud - a fully-managed Database as a Service for you. You can [sign up](https://tidbcloud.com/signup) and get started with TiDB Cloud Developer Tier for free. + +See [TiDB Cloud Quick Start](https://docs.pingcap.com/tidbcloud/tidb-cloud-quickstart). + ### To start using TiDB See [Quick Start Guide](https://docs.pingcap.com/tidb/stable/quick-start-with-tidb). diff --git a/bindinfo/bind_cache.go b/bindinfo/bind_cache.go new file mode 100644 index 0000000000000..aa9f0079a2903 --- /dev/null +++ b/bindinfo/bind_cache.go @@ -0,0 +1,251 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bindinfo + +import ( + "errors" + "sync" + + "github.com/cznic/mathutil" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/hack" + "github.com/pingcap/tidb/util/kvcache" + "github.com/pingcap/tidb/util/memory" +) + +// bindCache uses the LRU cache to store the bindRecord. +// The key of the LRU cache is original sql, the value is a slice of BindRecord. +// Note: The bindCache should be accessed with lock. +type bindCache struct { + lock sync.Mutex + cache *kvcache.SimpleLRUCache + memCapacity int64 + memTracker *memory.Tracker // track memory usage. +} + +type bindCacheKey string + +func (key bindCacheKey) Hash() []byte { + return hack.Slice(string(key)) +} + +func calcBindCacheKVMem(key bindCacheKey, value []*BindRecord) int64 { + var valMem int64 + for _, bindRecord := range value { + valMem += int64(bindRecord.size()) + } + return int64(len(key.Hash())) + valMem +} + +func newBindCache() *bindCache { + // since bindCache controls the memory usage by itself, set the capacity of + // the underlying LRUCache to max to close its memory control + cache := kvcache.NewSimpleLRUCache(mathutil.MaxUint, 0, 0) + c := bindCache{ + cache: cache, + memCapacity: variable.MemQuotaBindingCache.Load(), + memTracker: memory.NewTracker(memory.LabelForBindCache, -1), + } + return &c +} + +// get gets a cache item according to cache key. It's not thread-safe. +// Note: Only other functions of the bindCache file can use this function. +// Don't use this function directly in other files in bindinfo package. +// The return value is not read-only, but it is only can be used in other functions which are also in the bind_cache.go. +func (c *bindCache) get(key bindCacheKey) []*BindRecord { + value, hit := c.cache.Get(key) + if !hit { + return nil + } + typedValue := value.([]*BindRecord) + return typedValue +} + +// getCopiedVal gets a copied cache item according to cache key. +// The return value can be modified. +// If you want to modify the return value, use the 'getCopiedVal' function rather than 'get' function. +// We use the copy on write way to operate the bindRecord in cache for safety and accuracy of memory usage. +func (c *bindCache) getCopiedVal(key bindCacheKey) []*BindRecord { + bindRecords := c.get(key) + if bindRecords != nil { + copiedRecords := make([]*BindRecord, len(bindRecords)) + for i, bindRecord := range bindRecords { + copiedRecords[i] = bindRecord.shallowCopy() + } + return copiedRecords + } + return bindRecords +} + +// set inserts an item to the cache. It's not thread-safe. +// Only other functions of the bindCache can use this function. +// The set operation will return error message when the memory usage of binding_cache exceeds its capacity. +func (c *bindCache) set(key bindCacheKey, value []*BindRecord) (ok bool, err error) { + mem := calcBindCacheKVMem(key, value) + if mem > c.memCapacity { // ignore this kv pair if its size is too large + err = errors.New("The memory usage of all available bindings exceeds the cache's mem quota. As a result, all available bindings cannot be held on the cache. Please increase the value of the system variable 'tidb_mem_quota_binding_cache' and execute 'admin reload bindings' to ensure that all bindings exist in the cache and can be used normally") + return + } + bindRecords := c.get(key) + if bindRecords != nil { + // Remove the origin key-value pair. + mem -= calcBindCacheKVMem(key, bindRecords) + } + for mem+c.memTracker.BytesConsumed() > c.memCapacity { + err = errors.New("The memory usage of all available bindings exceeds the cache's mem quota. As a result, all available bindings cannot be held on the cache. Please increase the value of the system variable 'tidb_mem_quota_binding_cache' and execute 'admin reload bindings' to ensure that all bindings exist in the cache and can be used normally") + evictedKey, evictedValue, evicted := c.cache.RemoveOldest() + if !evicted { + return + } + c.memTracker.Consume(-calcBindCacheKVMem(evictedKey.(bindCacheKey), evictedValue.([]*BindRecord))) + } + c.memTracker.Consume(mem) + c.cache.Put(key, value) + ok = true + return +} + +// delete remove an item from the cache. It's not thread-safe. +// Only other functions of the bindCache can use this function. +func (c *bindCache) delete(key bindCacheKey) bool { + bindRecords := c.get(key) + if bindRecords != nil { + mem := calcBindCacheKVMem(key, bindRecords) + c.cache.Delete(key) + c.memTracker.Consume(-mem) + return true + } + return false +} + +// GetBindRecord gets the BindRecord from the cache. +// The return value is not read-only, but it shouldn't be changed in the caller functions. +// The function is thread-safe. +func (c *bindCache) GetBindRecord(hash, normdOrigSQL, db string) *BindRecord { + c.lock.Lock() + defer c.lock.Unlock() + bindRecords := c.get(bindCacheKey(hash)) + for _, bindRecord := range bindRecords { + if bindRecord.OriginalSQL == normdOrigSQL { + return bindRecord + } + } + return nil +} + +// GetAllBindRecords return all the bindRecords from the bindCache. +// The return value is not read-only, but it shouldn't be changed in the caller functions. +// The function is thread-safe. +func (c *bindCache) GetAllBindRecords() []*BindRecord { + c.lock.Lock() + defer c.lock.Unlock() + values := c.cache.Values() + var bindRecords []*BindRecord + for _, vals := range values { + bindRecords = append(bindRecords, vals.([]*BindRecord)...) + } + return bindRecords +} + +// SetBindRecord sets the BindRecord to the cache. +// The function is thread-safe. +func (c *bindCache) SetBindRecord(hash string, meta *BindRecord) (err error) { + c.lock.Lock() + defer c.lock.Unlock() + cacheKey := bindCacheKey(hash) + metas := c.getCopiedVal(cacheKey) + for i := range metas { + if metas[i].OriginalSQL == meta.OriginalSQL { + metas[i] = meta + } + } + _, err = c.set(cacheKey, []*BindRecord{meta}) + return +} + +// RemoveBindRecord removes the BindRecord which has same originSQL with specified BindRecord. +// The function is thread-safe. +func (c *bindCache) RemoveBindRecord(hash string, meta *BindRecord) { + c.lock.Lock() + defer c.lock.Unlock() + metas := c.getCopiedVal(bindCacheKey(hash)) + if metas == nil { + return + } + + for i := len(metas) - 1; i >= 0; i-- { + if metas[i].isSame(meta) { + metas[i] = metas[i].remove(meta) + if len(metas[i].Bindings) == 0 { + metas = append(metas[:i], metas[i+1:]...) + } + if len(metas) == 0 { + c.delete(bindCacheKey(hash)) + return + } + } + } + // This function can guarantee the memory usage for the cache will never grow up. + // So we don't need to handle the return value here. + _, _ = c.set(bindCacheKey(hash), metas) +} + +// SetMemCapacity sets the memory capacity for the cache. +// The function is thread-safe. +func (c *bindCache) SetMemCapacity(capacity int64) { + c.lock.Lock() + defer c.lock.Unlock() + // Only change the capacity size without affecting the cached bindRecord + c.memCapacity = capacity +} + +// GetMemUsage get the memory Usage for the cache. +// The function is thread-safe. +func (c *bindCache) GetMemUsage() int64 { + c.lock.Lock() + defer c.lock.Unlock() + return c.memTracker.BytesConsumed() +} + +// GetMemCapacity get the memory capacity for the cache. +// The function is thread-safe. +func (c *bindCache) GetMemCapacity() int64 { + c.lock.Lock() + defer c.lock.Unlock() + return c.memCapacity +} + +// Copy copies a new bindCache from the origin cache. +// The function is thread-safe. +func (c *bindCache) Copy() (newCache *bindCache, err error) { + c.lock.Lock() + defer c.lock.Unlock() + newCache = newBindCache() + if c.memTracker.BytesConsumed() > newCache.GetMemCapacity() { + err = errors.New("The memory usage of all available bindings exceeds the cache's mem quota. As a result, all available bindings cannot be held on the cache. Please increase the value of the system variable 'tidb_mem_quota_binding_cache' and execute 'admin reload bindings' to ensure that all bindings exist in the cache and can be used normally") + } + keys := c.cache.Keys() + for _, key := range keys { + cacheKey := key.(bindCacheKey) + v := c.get(cacheKey) + bindRecords := make([]*BindRecord, len(v)) + copy(bindRecords, v) + // The memory usage of cache has been handled at the beginning of this function. + // So we don't need to handle the return value here. + _, _ = newCache.set(cacheKey, bindRecords) + } + return newCache, err +} diff --git a/bindinfo/bind_cache_test.go b/bindinfo/bind_cache_test.go new file mode 100644 index 0000000000000..7234038f40acf --- /dev/null +++ b/bindinfo/bind_cache_test.go @@ -0,0 +1,79 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bindinfo + +import ( + "strconv" + "strings" + "testing" + + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/hack" + "github.com/stretchr/testify/require" +) + +func TestBindCache(t *testing.T) { + variable.MemQuotaBindingCache.Store(200) + bindCache := newBindCache() + + value := make([][]*BindRecord, 3) + key := make([]bindCacheKey, 3) + var bigKey string + for i := 0; i < 3; i++ { + cacheKey := strings.Repeat(strconv.Itoa(i), 50) + key[i] = bindCacheKey(hack.Slice(cacheKey)) + record := &BindRecord{OriginalSQL: cacheKey, Db: ""} + value[i] = []*BindRecord{record} + bigKey += cacheKey + + require.Equal(t, int64(100), calcBindCacheKVMem(key[i], value[i])) + } + + ok, err := bindCache.set(key[0], value[0]) + require.True(t, ok) + require.Nil(t, err) + result := bindCache.get(key[0]) + require.NotNil(t, result) + + ok, err = bindCache.set(key[1], value[1]) + require.True(t, ok) + require.Nil(t, err) + result = bindCache.get(key[1]) + require.NotNil(t, result) + + ok, err = bindCache.set(key[2], value[2]) + require.True(t, ok) + require.NotNil(t, err) + result = bindCache.get(key[2]) + require.NotNil(t, result) + + // key[0] is not in the cache + result = bindCache.get(key[0]) + require.Nil(t, result) + + // key[1] is still in the cache + result = bindCache.get(key[1]) + require.NotNil(t, result) + + bigBindCacheKey := bindCacheKey(hack.Slice(bigKey)) + bigRecord := &BindRecord{OriginalSQL: bigKey, Db: ""} + bigBindCacheValue := []*BindRecord{bigRecord} + require.Equal(t, int64(300), calcBindCacheKVMem(bigBindCacheKey, bigBindCacheValue)) + ok, err = bindCache.set(bigBindCacheKey, bigBindCacheValue) + require.False(t, ok) + require.NotNil(t, err) + result = bindCache.get(bigBindCacheKey) + require.Nil(t, result) +} diff --git a/bindinfo/cache.go b/bindinfo/bind_record.go similarity index 78% rename from bindinfo/cache.go rename to bindinfo/bind_record.go index 9cdff845c9e6b..bdb8301befb0f 100644 --- a/bindinfo/cache.go +++ b/bindinfo/bind_record.go @@ -22,11 +22,20 @@ import ( "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/hint" ) const ( + // Enabled is the bind info's in enabled status. + // It is the same as the previous 'Using' status. + // Only use 'Enabled' status in the future, not the 'Using' status. + // The 'Using' status is preserved for compatibility. + Enabled = "enabled" + // Disabled is the bind info's in disabled status. + Disabled = "disabled" // Using is the bind info's in use status. + // The 'Using' status is preserved for compatibility. Using = "using" // deleted is the bind info's deleted status. deleted = "deleted" @@ -52,7 +61,7 @@ type Binding struct { BindSQL string // Status represents the status of the binding. It can only be one of the following values: // 1. deleted: BindRecord is deleted, can not be used anymore. - // 2. using: Binding is in the normal active mode. + // 2. enabled, using: Binding is in the normal active mode. Status string CreateTime types.Time UpdateTime types.Time @@ -73,6 +82,18 @@ func (b *Binding) isSame(rb *Binding) bool { return b.BindSQL == rb.BindSQL } +// IsBindingEnabled returns whether the binding is enabled. +func (b *Binding) IsBindingEnabled() bool { + return b.Status == Enabled || b.Status == Using +} + +// IsBindingAvailable returns whether the binding is available. +// The available means the binding can be used or can be converted into a usable status. +// It includes the 'Enabled', 'Using' and 'Disabled' status. +func (b *Binding) IsBindingAvailable() bool { + return b.IsBindingEnabled() || b.Status == Disabled +} + // SinceUpdateTime returns the duration since last update time. Export for test. func (b *Binding) SinceUpdateTime() (time.Duration, error) { updateTime, err := b.UpdateTime.GoTime(time.Local) @@ -82,9 +103,6 @@ func (b *Binding) SinceUpdateTime() (time.Duration, error) { return time.Since(updateTime), nil } -// cache is a k-v map, key is original sql, value is a slice of BindRecord. -type cache map[string][]*BindRecord - // BindRecord represents a sql bind record retrieved from the storage. type BindRecord struct { OriginalSQL string @@ -93,16 +111,39 @@ type BindRecord struct { Bindings []Binding } -// HasUsingBinding checks if there are any using bindings in bind record. -func (br *BindRecord) HasUsingBinding() bool { +// HasEnabledBinding checks if there are any enabled bindings in bind record. +func (br *BindRecord) HasEnabledBinding() bool { + for _, binding := range br.Bindings { + if binding.IsBindingEnabled() { + return true + } + } + return false +} + +// HasAvailableBinding checks if there are any available bindings in bind record. +// The available means the binding can be used or can be converted into a usable status. +// It includes the 'Enabled', 'Using' and 'Disabled' status. +func (br *BindRecord) HasAvailableBinding() bool { for _, binding := range br.Bindings { - if binding.Status == Using { + if binding.IsBindingAvailable() { return true } } return false } +// FindEnabledBinding gets the enabled binding. +// There is at most one binding that can be used now. +func (br *BindRecord) FindEnabledBinding() *Binding { + for _, binding := range br.Bindings { + if binding.IsBindingEnabled() { + return &binding + } + } + return nil +} + // FindBinding find bindings in BindRecord. func (br *BindRecord) FindBinding(hint string) *Binding { for i := range br.Bindings { @@ -223,8 +264,17 @@ func (br *BindRecord) isSame(other *BindRecord) bool { return br.OriginalSQL == other.OriginalSQL } +// size calculates the memory size of a BindRecord. +func (br *BindRecord) size() float64 { + mem := float64(len(hack.Slice(br.OriginalSQL)) + len(hack.Slice(br.Db))) + for _, binding := range br.Bindings { + mem += binding.size() + } + return mem +} + var statusIndex = map[string]int{ - Using: 0, + Enabled: 0, deleted: 1, Invalid: 2, } @@ -253,7 +303,7 @@ func (br *BindRecord) metrics() ([]float64, []int) { // size calculates the memory size of a bind info. func (b *Binding) size() float64 { - res := len(b.BindSQL) + len(b.Status) + 2*int(unsafe.Sizeof(b.CreateTime)) + len(b.Charset) + len(b.Collation) + res := len(b.BindSQL) + len(b.Status) + 2*int(unsafe.Sizeof(b.CreateTime)) + len(b.Charset) + len(b.Collation) + len(b.ID) return float64(res) } diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 53b674a8ec715..1aaf349d5490e 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -76,6 +76,14 @@ func (msm *mockSessionManager1) ServerID() uint64 { return 1 } +func (msm *mockSessionManager1) StoreInternalSession(se interface{}) {} + +func (msm *mockSessionManager1) DeleteInternalSession(se interface{}) {} + +func (msm *mockSessionManager1) GetInternalSessionStartTSList() []uint64 { + return nil +} + func TestPrepareCacheWithBinding(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -406,7 +414,7 @@ func TestBindingSymbolList(t *testing.T) { bind := bindData.Bindings[0] require.Equal(t, "SELECT `a`,`b` FROM `test`.`t` USE INDEX (`ib`) WHERE `a` = 1 LIMIT 0,1", bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.NotNil(t, bind.Charset) require.NotNil(t, bind.Collation) require.NotNil(t, bind.CreateTime) @@ -498,7 +506,7 @@ func TestBestPlanInBaselines(t *testing.T) { bind := bindData.Bindings[0] require.Equal(t, "SELECT /*+ use_index(@`sel_1` `test`.`t` `ia`)*/ `a`,`b` FROM `test`.`t` WHERE `a` = 1 LIMIT 0,1", bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) tk.MustQuery("select a, b from t where a = 3 limit 1, 10") require.Equal(t, "t:ia", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) @@ -532,7 +540,7 @@ func TestErrorBind(t *testing.T) { bind := bindData.Bindings[0] require.Equal(t, "SELECT * FROM `test`.`t` USE INDEX (`index_t`) WHERE `i` > 100", bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.NotNil(t, bind.Charset) require.NotNil(t, bind.Collation) require.NotNil(t, bind.CreateTime) @@ -651,7 +659,7 @@ func TestAddEvolveTasks(t *testing.T) { require.Len(t, rows, 2) require.Equal(t, "SELECT /*+ use_index(@`sel_1` `test`.`t` )*/ * FROM `test`.`t` WHERE `a` >= 4 AND `b` >= 1 AND `c` = 0", rows[0][1]) status := rows[0][3].(string) - require.True(t, status == "using" || status == "rejected") + require.True(t, status == bindinfo.Enabled || status == bindinfo.Rejected) } func TestRuntimeHintsInEvolveTasks(t *testing.T) { @@ -707,40 +715,26 @@ func TestCaptureBaselinesScope(t *testing.T) { tk1.MustQuery(`show global variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( "tidb_capture_plan_baselines OFF", )) - tk1.MustQuery(`select @@session.tidb_capture_plan_baselines`).Check(testkit.Rows( - "0", - )) tk1.MustQuery(`select @@global.tidb_capture_plan_baselines`).Check(testkit.Rows( "0", )) - tk1.MustExec("set @@session.tidb_capture_plan_baselines = on") + tk1.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk1.MustExec(" set @@session.tidb_capture_plan_baselines = off") + tk1.MustExec(" set GLOBAL tidb_capture_plan_baselines = off") }() - tk1.MustQuery(`show session variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( + + tk1.MustQuery(`show variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( "tidb_capture_plan_baselines ON", )) tk1.MustQuery(`show global variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( - "tidb_capture_plan_baselines OFF", - )) - tk1.MustQuery(`select @@session.tidb_capture_plan_baselines`).Check(testkit.Rows( - "1", - )) - tk1.MustQuery(`select @@global.tidb_capture_plan_baselines`).Check(testkit.Rows( - "0", - )) - tk2.MustQuery(`show session variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( "tidb_capture_plan_baselines ON", )) tk2.MustQuery(`show global variables like "tidb_capture_plan_baselines"`).Check(testkit.Rows( - "tidb_capture_plan_baselines OFF", - )) - tk2.MustQuery(`select @@session.tidb_capture_plan_baselines`).Check(testkit.Rows( - "1", + "tidb_capture_plan_baselines ON", )) tk2.MustQuery(`select @@global.tidb_capture_plan_baselines`).Check(testkit.Rows( - "0", + "1", )) } @@ -924,7 +918,7 @@ func TestNotEvolvePlanForReadStorageHint(t *testing.T) { // None evolve task, because of the origin binding is a read_from_storage binding. require.Len(t, rows, 1) require.Equal(t, "SELECT /*+ read_from_storage(tiflash[`t`])*/ * FROM `test`.`t` WHERE `a` >= 1 AND `b` >= 1", rows[0][1]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) } func TestBindingWithIsolationRead(t *testing.T) { @@ -1052,6 +1046,10 @@ func TestSPMHitInfo(t *testing.T) { require.True(t, tk.HasPlan("SELECT * from t1,t2 where t1.id = t2.id", "MergeJoin")) tk.MustExec("SELECT * from t1,t2 where t1.id = t2.id") tk.MustQuery(`select @@last_plan_from_binding;`).Check(testkit.Rows("1")) + tk.MustExec("set binding disabled for SELECT * from t1,t2 where t1.id = t2.id") + tk.MustExec("SELECT * from t1,t2 where t1.id = t2.id") + tk.MustQuery(`select @@last_plan_from_binding;`).Check(testkit.Rows("0")) + tk.MustExec("drop global binding for SELECT * from t1,t2 where t1.id = t2.id") } @@ -1069,23 +1067,23 @@ func TestReCreateBind(t *testing.T) { tk.MustExec("create global binding for select * from t using select * from t") tk.MustQuery("select original_sql, status from mysql.bind_info where source != 'builtin';").Check(testkit.Rows( - "select * from `test` . `t` using", + "select * from `test` . `t` enabled", )) rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 1) require.Equal(t, "select * from `test` . `t`", rows[0][0]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) tk.MustExec("create global binding for select * from t using select * from t") rows = tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 1) require.Equal(t, "select * from `test` . `t`", rows[0][0]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) rows = tk.MustQuery("select original_sql, status from mysql.bind_info where source != 'builtin';").Rows() require.Len(t, rows, 2) require.Equal(t, "deleted", rows[0][1]) - require.Equal(t, "using", rows[1][1]) + require.Equal(t, bindinfo.Enabled, rows[1][1]) } func TestExplainShowBindSQL(t *testing.T) { @@ -1179,6 +1177,9 @@ func TestSPMWithoutUseDatabase(t *testing.T) { require.True(t, tk1.MustUseIndex("select * from test.t", "a")) tk1.MustExec("select * from test.t") tk1.MustQuery(`select @@last_plan_from_binding;`).Check(testkit.Rows("1")) + tk1.MustExec("set binding disabled for select * from test.t") + tk1.MustExec("select * from test.t") + tk1.MustQuery(`select @@last_plan_from_binding;`).Check(testkit.Rows("0")) } func TestBindingWithoutCharset(t *testing.T) { @@ -1232,9 +1233,9 @@ func TestGCBindRecord(t *testing.T) { rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 1) require.Equal(t, "select * from `test` . `t` where `a` = ?", rows[0][0]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) tk.MustQuery("select status from mysql.bind_info where original_sql = 'select * from `test` . `t` where `a` = ?'").Check(testkit.Rows( - "using", + bindinfo.Enabled, )) h := dom.BindHandle() @@ -1243,9 +1244,9 @@ func TestGCBindRecord(t *testing.T) { rows = tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 1) require.Equal(t, "select * from `test` . `t` where `a` = ?", rows[0][0]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) tk.MustQuery("select status from mysql.bind_info where original_sql = 'select * from `test` . `t` where `a` = ?'").Check(testkit.Rows( - "using", + bindinfo.Enabled, )) tk.MustExec("drop global binding for select * from t where a = 1") diff --git a/bindinfo/capture_test.go b/bindinfo/capture_test.go index e65697c3f2a21..7ebb419a8adaf 100644 --- a/bindinfo/capture_test.go +++ b/bindinfo/capture_test.go @@ -16,6 +16,7 @@ package bindinfo_test import ( "fmt" + "strings" "testing" "github.com/pingcap/tidb/bindinfo" @@ -35,9 +36,9 @@ func TestDMLCapturePlanBaseline(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec(" set @@tidb_capture_plan_baselines = on") + tk.MustExec(" SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk.MustExec(" set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -94,9 +95,9 @@ func TestCapturePlanBaseline(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec(" set @@tidb_capture_plan_baselines = on") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk.MustExec(" set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -119,6 +120,66 @@ func TestCapturePlanBaseline(t *testing.T) { require.Equal(t, "SELECT /*+ use_index(@`sel_1` `test`.`t` )*/ * FROM `test`.`t` WHERE `a` > 10", rows[0][1]) } +func TestCapturePlanBaseline4DisabledStatus(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") + defer func() { + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") + }() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, index idx_a(a))") + dom.BindHandle().CaptureBaselines() + tk.MustQuery("show global bindings").Check(testkit.Rows()) + tk.MustExec("select /*+ USE_INDEX(t, idx_a) */ * from t where a > 10") + tk.MustExec("select /*+ USE_INDEX(t, idx_a) */ * from t where a > 10") + tk.MustExec("admin capture bindings") + rows := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 0) + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("select * from t where a > 10") + tk.MustExec("select * from t where a > 10") + tk.MustExec("admin capture bindings") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + require.Equal(t, bindinfo.Capture, rows[0][8]) + + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + + tk.MustExec("set binding disabled for select * from t where a > 10") + + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Disabled, rows[0][3]) + + tk.MustExec("select * from t where a > 10") + tk.MustExec("select * from t where a > 10") + tk.MustExec("admin capture bindings") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Disabled, rows[0][3]) + + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + + tk.MustExec("drop global binding for select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 0) + + utilCleanBindingEnv(tk, dom) +} + func TestCaptureDBCaseSensitivity(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -150,9 +211,9 @@ func TestCaptureBaselinesDefaultDB(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec(" set @@tidb_capture_plan_baselines = on") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk.MustExec(" set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") tk.MustExec("drop database if exists spm") @@ -166,7 +227,7 @@ func TestCaptureBaselinesDefaultDB(t *testing.T) { require.Len(t, rows, 1) // Default DB should be "" when all columns have explicit database name. require.Equal(t, "", rows[0][2]) - require.Equal(t, "using", rows[0][3]) + require.Equal(t, bindinfo.Enabled, rows[0][3]) tk.MustExec("use spm") tk.MustExec("select * from spm.t where a > 10") // Should use TableScan because of the "ignore index" binding. @@ -293,9 +354,9 @@ func TestBindingSource(t *testing.T) { // Test Source for captured sqls stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec("set @@tidb_capture_plan_baselines = on") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk.MustExec("set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) @@ -344,7 +405,7 @@ func TestConcurrentCapture(t *testing.T) { // Simulate an existing binding generated by concurrent CREATE BINDING, which has not been synchronized to current tidb-server yet. // Actually, it is more common to be generated by concurrent baseline capture, I use Manual just for simpler test verification. - tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t`', 'select * from `test` . `t`', '', 'using', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t`', 'select * from `test` . `t`', '', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + bindinfo.Manual + "')") tk.MustQuery("select original_sql, source from mysql.bind_info where source != 'builtin'").Check(testkit.Rows( "select * from `test` . `t` manual", @@ -359,7 +420,7 @@ func TestConcurrentCapture(t *testing.T) { tk.MustExec("admin capture bindings") tk.MustQuery("select original_sql, source, status from mysql.bind_info where source != 'builtin'").Check(testkit.Rows( "select * from `test` . `t` manual deleted", - "select * from `test` . `t` capture using", + "select * from `test` . `t` capture enabled", )) } @@ -426,7 +487,7 @@ func TestIssue20417(t *testing.T) { // Test for capture baseline utilCleanBindingEnv(tk, dom) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec("set @@tidb_capture_plan_baselines = on") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") dom.BindHandle().CaptureBaselines() require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) tk.MustExec("select * from t where b=2 and c=213124") @@ -436,7 +497,7 @@ func TestIssue20417(t *testing.T) { require.Len(t, rows, 1) require.Equal(t, "select * from `test` . `t` where `b` = ? and `c` = ?", rows[0][0]) require.Equal(t, "SELECT /*+ use_index(@`sel_1` `test`.`t` `idxb`)*/ * FROM `test`.`t` WHERE `b` = 2 AND `c` = 213124", rows[0][1]) - tk.MustExec("set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") // Test for evolve baseline utilCleanBindingEnv(tk, dom) @@ -460,7 +521,7 @@ func TestIssue20417(t *testing.T) { require.Equal(t, "select * from `test` . `t` where `c` = ?", rows[0][0]) require.Equal(t, "SELECT /*+ use_index(@`sel_1` `test`.`t` `idxc`)*/ * FROM `test`.`t` WHERE `c` = 3924541", rows[0][1]) status := rows[0][3].(string) - require.True(t, status == "using" || status == "rejected") + require.True(t, status == bindinfo.Enabled || status == bindinfo.Rejected) tk.MustExec("set @@tidb_evolve_plan_baselines=0") } @@ -555,6 +616,200 @@ func TestIssue25505(t *testing.T) { } } +func TestCaptureUserFilter(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") + defer func() { + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") + }() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("select * from t where a > 10") + tk.MustExec("select * from t where a > 10") + tk.MustExec("admin capture bindings") + rows := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, "select * from `test` . `t` where `a` > ?", rows[0][0]) + + // test user filter + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('user', 'root')") + tk.MustExec("select * from t where a > 10") + tk.MustExec("select * from t where a > 10") + tk.MustExec("admin capture bindings") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 0) // cannot capture the stmt + + // change another user + tk.MustExec(`create user usr1`) + tk.MustExec(`grant all on *.* to usr1 with grant option`) + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + require.True(t, tk2.Session().Auth(&auth.UserIdentity{Username: "usr1", Hostname: "%"}, nil, nil)) + tk2.MustExec("select * from t where a > 10") + tk2.MustExec("select * from t where a > 10") + tk2.MustExec("admin capture bindings") + rows = tk2.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) // can capture the stmt + + // use user-filter with other types of filter together + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('user', 'root')") + tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'test.t')") + tk2.MustExec("select * from t where a > 10") + tk2.MustExec("select * from t where a > 10") + tk2.MustExec("admin capture bindings") + rows = tk2.MustQuery("show global bindings").Rows() + require.Len(t, rows, 0) // filtered by the table filter +} + +func TestCaptureTableFilterValid(t *testing.T) { + type matchCase struct { + table string + matched bool + } + type filterCase struct { + filter string + valid bool + mcases []matchCase + } + filterCases := []filterCase{ + {"*.*", true, []matchCase{{"db.t", true}}}, + {"***.***", true, []matchCase{{"db.t", true}}}, + {"d*.*", true, []matchCase{{"db.t", true}}}, + {"*.t", true, []matchCase{{"db.t", true}}}, + {"?.t*", true, []matchCase{{"d.t", true}, {"d.tb", true}, {"db.t", false}}}, + {"db.t[1-3]", true, []matchCase{{"db.t1", true}, {"db.t2", true}, {"db.t4", false}}}, + {"!db.table", false, nil}, + {"@db.table", false, nil}, + {"table", false, nil}, + {"", false, nil}, + {"\t ", false, nil}, + } + for _, fc := range filterCases { + f, valid := bindinfo.ParseCaptureTableFilter(fc.filter) + require.Equal(t, fc.valid, valid) + if valid { + for _, mc := range fc.mcases { + tmp := strings.Split(mc.table, ".") + require.Equal(t, mc.matched, f.MatchTable(tmp[0], tmp[1])) + } + } + } +} + +func TestCaptureWildcardFilter(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") + defer func() { + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") + }() + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + dbs := []string{"db11", "db12", "db2"} + tbls := []string{"t11", "t12", "t2"} + for _, db := range dbs { + tk.MustExec(fmt.Sprintf(`drop database if exists %v`, db)) + tk.MustExec(fmt.Sprintf(`create database %v`, db)) + tk.MustExec(fmt.Sprintf(`use %v`, db)) + for _, tbl := range tbls { + tk.MustExec(fmt.Sprintf(`create table %v(a int)`, tbl)) + } + } + mustExecTwice := func() { + for _, db := range dbs { + for _, tbl := range tbls { + tk.MustExec(fmt.Sprintf(`select * from %v.%v where a>10`, db, tbl)) + tk.MustExec(fmt.Sprintf(`select * from %v.%v where a>10`, db, tbl)) + } + } + } + checkBindings := func(dbTbls ...string) { + m := make(map[string]bool) // map[query]existed + for _, dbTbl := range dbTbls { + tmp := strings.Split(dbTbl, ".") + q := fmt.Sprintf("select * from `%v` . `%v` where `a` > ?", tmp[0], tmp[1]) + m[q] = false + } + + tk.MustExec("admin capture bindings") + rows := tk.MustQuery("show global bindings").Sort().Rows() + require.Len(t, rows, len(dbTbls)) + for _, r := range rows { + q := r[0].(string) + if _, exist := m[q]; !exist { // encounter an unexpected binding + t.Fatalf("unexpected binding %v", q) + } + m[q] = true + } + for q, exist := range m { + if !exist { // a expected binding is not existed + t.Fatalf("missed binding %v", q) + } + } + } + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'db11.t1*')`) + mustExecTwice() + checkBindings("db11.t2", "db12.t11", "db12.t12", "db12.t2", "db2.t11", "db2.t12", "db2.t2") // db11.t11 and db11.t12 are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'db1*.t11')`) + mustExecTwice() + checkBindings("db11.t12", "db11.t2", "db12.t12", "db12.t2", "db2.t11", "db2.t12", "db2.t2") // db11.t11 and db12.t11 are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'db1*.t1*')`) + mustExecTwice() + checkBindings("db11.t2", "db12.t2", "db2.t11", "db2.t12", "db2.t2") // db11.t11 / db12.t11 / db11.t12 / db12.t12 are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'db1*.*')`) + mustExecTwice() + checkBindings("db2.t11", "db2.t12", "db2.t2") // db11.* / db12.* are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', '*.t1*')`) + mustExecTwice() + checkBindings("db11.t2", "db12.t2", "db2.t2") // *.t11 and *.t12 are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + tk.MustExec(`insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'db*.t*')`) + mustExecTwice() + checkBindings() // all are filtered + + utilCleanBindingEnv(tk, dom) + stmtsummary.StmtSummaryByDigestMap.Clear() + tk.MustExec("delete from mysql.capture_plan_baselines_blacklist") + mustExecTwice() + checkBindings("db11.t11", "db11.t12", "db11.t2", "db12.t11", "db12.t12", "db12.t2", "db2.t11", "db2.t12", "db2.t2") // no filter, all can be captured +} + func TestCaptureFilter(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() @@ -562,9 +817,9 @@ func TestCaptureFilter(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec(" set @@tidb_capture_plan_baselines = on") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") defer func() { - tk.MustExec(" set @@tidb_capture_plan_baselines = off") + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -615,7 +870,7 @@ func TestCaptureFilter(t *testing.T) { // Valid database filter. utilCleanBindingEnv(tk, dom) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('db', 'mysql')") + tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'mysql.*')") tk.MustExec("select * from mysql.capture_plan_baselines_blacklist") tk.MustExec("select * from mysql.capture_plan_baselines_blacklist") tk.MustExec("admin capture bindings") @@ -698,7 +953,7 @@ func TestCaptureFilter(t *testing.T) { utilCleanBindingEnv(tk, dom) stmtsummary.StmtSummaryByDigestMap.Clear() - tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('Db', 'mySQl')") + tk.MustExec("insert into mysql.capture_plan_baselines_blacklist(filter_type, filter_value) values('table', 'mySQl.*')") tk.MustExec("select * from mysql.capture_plan_baselines_blacklist") tk.MustExec("select * from mysql.capture_plan_baselines_blacklist") tk.MustExec("admin capture bindings") @@ -711,3 +966,66 @@ func TestCaptureFilter(t *testing.T) { require.Len(t, rows, 1) require.Equal(t, "select * from `mysql` . `capture_plan_baselines_blacklist`", rows[0][0]) } + +func TestCaptureHints(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") + defer func() { + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") + }() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int primary key, a int, b int, key(a), key(b))") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + captureCases := []struct { + query string + hint string + }{ + // agg hints + {"select /*+ hash_agg() */ count(1) from t", "hash_agg"}, + {"select /*+ stream_agg() */ count(1) from t", "stream_agg"}, + // join hints + {"select /*+ merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "merge_join"}, + {"select /*+ tidb_smj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "merge_join"}, + {"select /*+ hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "hash_join"}, + {"select /*+ tidb_hj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "hash_join"}, + {"select /*+ inl_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "inl_join"}, + {"select /*+ tidb_inlj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "inl_join"}, + {"select /*+ inl_hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", "inl_hash_join"}, + // index hints + {"select * from t use index(primary)", "use_index(@`sel_1` `test`.`t` )"}, + {"select /*+ use_index(primary) */ * from t", "use_index(@`sel_1` `test`.`t` )"}, + {"select * from t use index(a)", "use_index(@`sel_1` `test`.`t` `a`)"}, + {"select /*+ use_index(a) */ * from t use index(a)", "use_index(@`sel_1` `test`.`t` `a`)"}, + {"select * from t use index(b)", "use_index(@`sel_1` `test`.`t` `b`)"}, + {"select /*+ use_index(b) */ * from t use index(b)", "use_index(@`sel_1` `test`.`t` `b`)"}, + {"select /*+ use_index_merge(t, a, b) */ a, b from t where a=1 or b=1", "use_index_merge(@`sel_1` `t` `a`, `b`)"}, + {"select /*+ ignore_index(t, a) */ * from t where a=1", "ignore_index(`t` `a`)"}, + // push-down hints + {"select /*+ limit_to_cop() */ * from t limit 10", "limit_to_cop()"}, + {"select /*+ agg_to_cop() */ a, count(*) from t group by a", "agg_to_cop()"}, + // index-merge hints + {"select /*+ no_index_merge() */ a, b from t where a>1 or b>1", "no_index_merge()"}, + {"select /*+ use_index_merge(t, a, b) */ a, b from t where a>1 or b>1", "use_index_merge(@`sel_1` `t` `a`, `b`)"}, + // runtime hints + {"select /*+ memory_quota(1024 MB) */ * from t", "memory_quota(1024 mb)"}, + {"select /*+ max_execution_time(1000) */ * from t", "max_execution_time(1000)"}, + // storage hints + {"select /*+ read_from_storage(tikv[t]) */ * from t", "read_from_storage(tikv[`t`])"}, + // others + {"select /*+ use_toja(true) */ t1.a, t1.b from t t1 where t1.a in (select t2.a from t t2)", "use_toja(true)"}, + } + for _, capCase := range captureCases { + stmtsummary.StmtSummaryByDigestMap.Clear() + utilCleanBindingEnv(tk, dom) + tk.MustExec(capCase.query) + tk.MustExec(capCase.query) + tk.MustExec("admin capture bindings") + res := tk.MustQuery(`show global bindings`).Rows() + require.Equal(t, len(res), 1) // this query is captured, and + require.True(t, strings.Contains(res[0][1].(string), capCase.hint)) // the binding contains the expected hint + } +} diff --git a/bindinfo/handle.go b/bindinfo/handle.go index b1920047a20b6..dc25baff5250e 100644 --- a/bindinfo/handle.go +++ b/bindinfo/handle.go @@ -41,6 +41,7 @@ import ( utilparser "github.com/pingcap/tidb/util/parser" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/stmtsummary" + tablefilter "github.com/pingcap/tidb/util/table-filter" "github.com/pingcap/tidb/util/timeutil" "go.uber.org/zap" ) @@ -106,7 +107,7 @@ type bindRecordUpdate struct { func NewBindHandle(ctx sessionctx.Context) *BindHandle { handle := &BindHandle{} handle.sctx.Context = ctx - handle.bindInfo.Value.Store(make(cache, 32)) + handle.bindInfo.Value.Store(newBindCache()) handle.bindInfo.parser = parser.New() handle.invalidBindRecordMap.Value.Store(make(map[string]*bindRecordUpdate)) handle.invalidBindRecordMap.flushFunc = func(record *BindRecord) error { @@ -131,22 +132,18 @@ func (h *BindHandle) Update(fullLoad bool) (err error) { } exec := h.sctx.Context.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), `SELECT original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation, source - FROM mysql.bind_info WHERE update_time > %? ORDER BY update_time, create_time`, updateTime) - if err != nil { - return err - } - // No need to acquire the session context lock for ExecRestrictedStmt, it + // No need to acquire the session context lock for ExecRestrictedSQL, it // uses another background session. - rows, _, err := exec.ExecRestrictedStmt(context.Background(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, `SELECT original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation, source + FROM mysql.bind_info WHERE update_time > %? ORDER BY update_time, create_time`, updateTime) if err != nil { h.bindInfo.Unlock() return err } - newCache := h.bindInfo.Value.Load().(cache).copy() + newCache, memExceededErr := h.bindInfo.Value.Load().(*bindCache).Copy() defer func() { h.bindInfo.lastUpdateTime = lastUpdateTime h.bindInfo.Value.Store(newCache) @@ -154,28 +151,44 @@ func (h *BindHandle) Update(fullLoad bool) (err error) { }() for _, row := range rows { + // If the memory usage of the binding_cache exceeds its capacity, we will break and do not handle. + if memExceededErr != nil { + break + } // Skip the builtin record which is designed for binding synchronization. if row.GetString(0) == BuiltinPseudoSQL4BindLock { continue } hash, meta, err := h.newBindRecord(row) - if err != nil { - logutil.BgLogger().Debug("[sql-bind] failed to generate bind record from data row", zap.Error(err)) - continue - } + // Update lastUpdateTime to the newest one. + // Even if this one is an invalid bind. if meta.Bindings[0].UpdateTime.Compare(lastUpdateTime) > 0 { lastUpdateTime = meta.Bindings[0].UpdateTime } - oldRecord := newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db) + if err != nil { + logutil.BgLogger().Debug("[sql-bind] failed to generate bind record from data row", zap.Error(err)) + continue + } + + oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db) newRecord := merge(oldRecord, meta).removeDeletedBindings() if len(newRecord.Bindings) > 0 { - newCache.setBindRecord(hash, newRecord) + err = newCache.SetBindRecord(hash, newRecord) + if err != nil { + memExceededErr = err + } } else { - newCache.removeDeletedBindRecord(hash, newRecord) + newCache.RemoveBindRecord(hash, newRecord) } - updateMetrics(metrics.ScopeGlobal, oldRecord, newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db), true) + updateMetrics(metrics.ScopeGlobal, oldRecord, newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db), true) + } + if memExceededErr != nil { + // When the memory capacity of bing_cache is not enough, + // there will be some memory-related errors in multiple places. + // Only needs to be handled once. + logutil.BgLogger().Warn("[sql-bind] BindHandle.Update", zap.Error(memExceededErr)) } return nil } @@ -267,7 +280,7 @@ func (h *BindHandle) AddBindRecord(sctx sessionctx.Context, record *BindRecord) if oldRecord != nil { binding := oldRecord.FindBinding(record.Bindings[0].ID) if binding != nil { - // There is already a binding with status `Using`, `PendingVerify` or `Rejected`, we could directly cancel the job. + // There is already a binding with status `Enabled`, `Disabled`, `PendingVerify` or `Rejected`, we could directly cancel the job. if record.Bindings[0].Status == PendingVerify { return nil } @@ -395,6 +408,92 @@ func (h *BindHandle) DropBindRecord(originalSQL, db string, binding *Binding) (e return err } +// SetBindRecordStatus set a BindRecord's status to the storage and bind cache. +func (h *BindHandle) SetBindRecordStatus(originalSQL string, binding *Binding, newStatus string) (ok bool, err error) { + h.bindInfo.Lock() + h.sctx.Lock() + defer func() { + h.sctx.Unlock() + h.bindInfo.Unlock() + }() + exec, _ := h.sctx.Context.(sqlexec.SQLExecutor) + _, err = exec.ExecuteInternal(context.TODO(), "BEGIN PESSIMISTIC") + if err != nil { + return + } + var ( + updateTs types.Time + oldStatus0, oldStatus1 string + affectRows int + ) + if newStatus == Disabled { + // For compatibility reasons, when we need to 'set binding disabled for ', + // we need to consider both the 'enabled' and 'using' status. + oldStatus0 = Using + oldStatus1 = Enabled + } else if newStatus == Enabled { + // In order to unify the code, two identical old statuses are set. + oldStatus0 = Disabled + oldStatus1 = Disabled + } + defer func() { + if err != nil { + _, err1 := exec.ExecuteInternal(context.TODO(), "ROLLBACK") + terror.Log(err1) + return + } + + _, err = exec.ExecuteInternal(context.TODO(), "COMMIT") + if err != nil { + return + } + if affectRows == 0 { + return + } + + // The set binding status operation is success. + ok = true + record := &BindRecord{OriginalSQL: originalSQL} + sqlDigest := parser.DigestNormalized(record.OriginalSQL) + oldRecord := h.GetBindRecord(sqlDigest.String(), originalSQL, "") + setBindingStatusInCacheSucc := false + if oldRecord != nil && len(oldRecord.Bindings) > 0 { + record.Bindings = make([]Binding, len(oldRecord.Bindings)) + copy(record.Bindings, oldRecord.Bindings) + for ind, oldBinding := range record.Bindings { + if oldBinding.Status == oldStatus0 || oldBinding.Status == oldStatus1 { + if binding == nil || (binding != nil && oldBinding.isSame(binding)) { + setBindingStatusInCacheSucc = true + record.Bindings[ind].Status = newStatus + record.Bindings[ind].UpdateTime = updateTs + } + } + } + } + if setBindingStatusInCacheSucc { + h.setBindRecord(sqlDigest.String(), record) + } + }() + + // Lock mysql.bind_info to synchronize with SetBindingStatus on other tidb instances. + if err = h.lockBindInfoTable(); err != nil { + return + } + + updateTs = types.NewTime(types.FromGoTime(time.Now()), mysql.TypeTimestamp, 3) + updateTsStr := updateTs.String() + + if binding == nil { + _, err = exec.ExecuteInternal(context.TODO(), `UPDATE mysql.bind_info SET status = %?, update_time = %? WHERE original_sql = %? AND update_time < %? AND status IN (%?, %?)`, + newStatus, updateTsStr, originalSQL, updateTsStr, oldStatus0, oldStatus1) + } else { + _, err = exec.ExecuteInternal(context.TODO(), `UPDATE mysql.bind_info SET status = %?, update_time = %? WHERE original_sql = %? AND update_time < %? AND bind_sql = %? AND status IN (%?, %?)`, + newStatus, updateTsStr, originalSQL, updateTsStr, binding.BindSQL, oldStatus0, oldStatus1) + } + affectRows = int(h.sctx.Context.GetSessionVars().StmtCtx.AffectedRows()) + return +} + // GCBindRecord physically removes the deleted bind records in mysql.bind_info. func (h *BindHandle) GCBindRecord() (err error) { h.bindInfo.Lock() @@ -518,32 +617,46 @@ func (h *BindHandle) AddDropInvalidBindTask(invalidBindRecord *BindRecord) { // Size returns the size of bind info cache. func (h *BindHandle) Size() int { - size := 0 - for _, bindRecords := range h.bindInfo.Load().(cache) { - size += len(bindRecords) - } + size := len(h.bindInfo.Load().(*bindCache).GetAllBindRecords()) return size } // GetBindRecord returns the BindRecord of the (normdOrigSQL,db) if BindRecord exist. func (h *BindHandle) GetBindRecord(hash, normdOrigSQL, db string) *BindRecord { - return h.bindInfo.Load().(cache).getBindRecord(hash, normdOrigSQL, db) + return h.bindInfo.Load().(*bindCache).GetBindRecord(hash, normdOrigSQL, db) } // GetAllBindRecord returns all bind records in cache. func (h *BindHandle) GetAllBindRecord() (bindRecords []*BindRecord) { - bindRecordMap := h.bindInfo.Load().(cache) - for _, bindRecord := range bindRecordMap { - bindRecords = append(bindRecords, bindRecord...) - } - return bindRecords + return h.bindInfo.Load().(*bindCache).GetAllBindRecords() +} + +// SetBindCacheCapacity reset the capacity for the bindCache. +// It will not affect already cached BindRecords. +func (h *BindHandle) SetBindCacheCapacity(capacity int64) { + h.bindInfo.Load().(*bindCache).SetMemCapacity(capacity) +} + +// GetMemUsage returns the memory usage for the bind cache. +func (h *BindHandle) GetMemUsage() (memUsage int64) { + return h.bindInfo.Load().(*bindCache).GetMemUsage() +} + +// GetMemCapacity returns the memory capacity for the bind cache. +func (h *BindHandle) GetMemCapacity() (memCapacity int64) { + return h.bindInfo.Load().(*bindCache).GetMemCapacity() } // newBindRecord builds BindRecord from a tuple in storage. func (h *BindHandle) newBindRecord(row chunk.Row) (string, *BindRecord, error) { + status := row.GetString(3) + // For compatibility, the 'Using' status binding will be converted to the 'Enabled' status binding. + if status == Using { + status = Enabled + } hint := Binding{ BindSQL: row.GetString(1), - Status: row.GetString(3), + Status: status, CreateTime: row.GetTime(4), UpdateTime: row.GetTime(5), Charset: row.GetString(6), @@ -566,74 +679,47 @@ func (h *BindHandle) newBindRecord(row chunk.Row) (string, *BindRecord, error) { // setBindRecord sets the BindRecord to the cache, if there already exists a BindRecord, // it will be overridden. func (h *BindHandle) setBindRecord(hash string, meta *BindRecord) { - newCache := h.bindInfo.Value.Load().(cache).copy() - oldRecord := newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db) - newCache.setBindRecord(hash, meta) + newCache, err0 := h.bindInfo.Value.Load().(*bindCache).Copy() + if err0 != nil { + logutil.BgLogger().Warn("[sql-bind] BindHandle.setBindRecord", zap.Error(err0)) + } + oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db) + err1 := newCache.SetBindRecord(hash, meta) + if err1 != nil && err0 == nil { + logutil.BgLogger().Warn("[sql-bind] BindHandle.setBindRecord", zap.Error(err1)) + } h.bindInfo.Value.Store(newCache) updateMetrics(metrics.ScopeGlobal, oldRecord, meta, false) } -// appendBindRecord addes the BindRecord to the cache, all the stale BindRecords are +// appendBindRecord adds the BindRecord to the cache, all the stale BindRecords are // removed from the cache after this operation. func (h *BindHandle) appendBindRecord(hash string, meta *BindRecord) { - newCache := h.bindInfo.Value.Load().(cache).copy() - oldRecord := newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db) + newCache, err0 := h.bindInfo.Value.Load().(*bindCache).Copy() + if err0 != nil { + logutil.BgLogger().Warn("[sql-bind] BindHandle.appendBindRecord", zap.Error(err0)) + } + oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db) newRecord := merge(oldRecord, meta) - newCache.setBindRecord(hash, newRecord) + err1 := newCache.SetBindRecord(hash, newRecord) + if err1 != nil && err0 == nil { + // Only need to handle the error once. + logutil.BgLogger().Warn("[sql-bind] BindHandle.appendBindRecord", zap.Error(err1)) + } h.bindInfo.Value.Store(newCache) updateMetrics(metrics.ScopeGlobal, oldRecord, newRecord, false) } // removeBindRecord removes the BindRecord from the cache. func (h *BindHandle) removeBindRecord(hash string, meta *BindRecord) { - newCache := h.bindInfo.Value.Load().(cache).copy() - oldRecord := newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db) - newCache.removeDeletedBindRecord(hash, meta) - h.bindInfo.Value.Store(newCache) - updateMetrics(metrics.ScopeGlobal, oldRecord, newCache.getBindRecord(hash, meta.OriginalSQL, meta.Db), false) -} - -// removeDeletedBindRecord removes the BindRecord which has same originSQL and db with specified BindRecord. -func (c cache) removeDeletedBindRecord(hash string, meta *BindRecord) { - metas, ok := c[hash] - if !ok { - return - } - - for i := len(metas) - 1; i >= 0; i-- { - if metas[i].isSame(meta) { - metas[i] = metas[i].remove(meta) - if len(metas[i].Bindings) == 0 { - metas = append(metas[:i], metas[i+1:]...) - } - if len(metas) == 0 { - delete(c, hash) - return - } - } - } - c[hash] = metas -} - -func (c cache) setBindRecord(hash string, meta *BindRecord) { - metas := c[hash] - for i := range metas { - if metas[i].OriginalSQL == meta.OriginalSQL { - metas[i] = meta - return - } - } - c[hash] = append(c[hash], meta) -} - -func (c cache) copy() cache { - newCache := make(cache, len(c)) - for k, v := range c { - bindRecords := make([]*BindRecord, len(v)) - copy(bindRecords, v) - newCache[k] = bindRecords + newCache, err := h.bindInfo.Value.Load().(*bindCache).Copy() + if err != nil { + logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err)) } - return newCache + oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db) + newCache.RemoveBindRecord(hash, meta) + h.bindInfo.Value.Store(newCache) + updateMetrics(metrics.ScopeGlobal, oldRecord, newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db), false) } func copyBindRecordUpdateMap(oldMap map[string]*bindRecordUpdate) map[string]*bindRecordUpdate { @@ -644,20 +730,10 @@ func copyBindRecordUpdateMap(oldMap map[string]*bindRecordUpdate) map[string]*bi return newMap } -func (c cache) getBindRecord(hash, normdOrigSQL, db string) *BindRecord { - bindRecords := c[hash] - for _, bindRecord := range bindRecords { - if bindRecord.OriginalSQL == normdOrigSQL { - return bindRecord - } - } - return nil -} - type captureFilter struct { - dbs map[string]struct{} frequency int64 - tables map[stmtctx.TableEntry]struct{} + tables []tablefilter.Filter // `schema.table` + users map[string]struct{} fail bool currentDB string @@ -673,10 +749,10 @@ func (cf *captureFilter) Enter(in ast.Node) (out ast.Node, skipChildren bool) { if x.Schema.L == "" { tblEntry.DB = cf.currentDB } - if _, ok := cf.dbs[tblEntry.DB]; ok { - cf.fail = true - } else if _, ok := cf.tables[tblEntry]; ok { - cf.fail = true + for _, tableFilter := range cf.tables { + if tableFilter.MatchTable(tblEntry.DB, tblEntry.Table) { + cf.fail = true // some filter is matched + } } } return in, cf.fail @@ -687,24 +763,37 @@ func (cf *captureFilter) Leave(in ast.Node) (out ast.Node, ok bool) { } func (cf *captureFilter) isEmpty() bool { - return len(cf.dbs) == 0 && len(cf.tables) == 0 + return len(cf.tables) == 0 && len(cf.users) == 0 +} + +// ParseCaptureTableFilter checks whether this filter is valid and parses it. +func ParseCaptureTableFilter(tableFilter string) (f tablefilter.Filter, valid bool) { + // forbid wildcards '!' and '@' for safety, + // please see https://github.com/pingcap/tidb-tools/tree/master/pkg/table-filter for more details. + tableFilter = strings.TrimLeft(tableFilter, " \t") + if tableFilter == "" { + return nil, false + } + if tableFilter[0] == '!' || tableFilter[0] == '@' { + return nil, false + } + var err error + f, err = tablefilter.Parse([]string{tableFilter}) + if err != nil { + return nil, false + } + return f, true } func (h *BindHandle) extractCaptureFilterFromStorage() (filter *captureFilter) { filter = &captureFilter{ - dbs: make(map[string]struct{}), frequency: 1, - tables: make(map[stmtctx.TableEntry]struct{}), + users: make(map[string]struct{}), } exec := h.sctx.Context.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), `SELECT filter_type, filter_value FROM mysql.capture_plan_baselines_blacklist order by filter_type`) - if err != nil { - logutil.BgLogger().Warn("[sql-bind] failed to parse query for mysql.capture_plan_baselines_blacklist load", zap.Error(err)) - return - } - // No need to acquire the session context lock for ExecRestrictedStmt, it + // No need to acquire the session context lock for ExecRestrictedSQL, it // uses another background session. - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, `SELECT filter_type, filter_value FROM mysql.capture_plan_baselines_blacklist order by filter_type`) if err != nil { logutil.BgLogger().Warn("[sql-bind] failed to load mysql.capture_plan_baselines_blacklist", zap.Error(err)) return @@ -713,19 +802,15 @@ func (h *BindHandle) extractCaptureFilterFromStorage() (filter *captureFilter) { filterTp := strings.ToLower(row.GetString(0)) valStr := strings.ToLower(row.GetString(1)) switch filterTp { - case "db": - filter.dbs[valStr] = struct{}{} case "table": - strs := strings.Split(valStr, ".") - if len(strs) != 2 { - logutil.BgLogger().Warn("[sql-bind] failed to parse table name, ignore it", zap.String("filter_value", valStr)) + tfilter, valid := ParseCaptureTableFilter(valStr) + if !valid { + logutil.BgLogger().Warn("[sql-bind] capture table filter is invalid, ignore it", zap.String("filter_value", valStr)) continue } - tblEntry := stmtctx.TableEntry{ - DB: strs[0], - Table: strs[1], - } - filter.tables[tblEntry] = struct{}{} + filter.tables = append(filter.tables, tfilter) + case "user": + filter.users[valStr] = struct{}{} case "frequency": f, err := strconv.ParseInt(valStr, 10, 64) if err != nil { @@ -768,10 +853,23 @@ func (h *BindHandle) CaptureBaselines() { if captureFilter.fail { continue } + + if len(captureFilter.users) > 0 { + filteredByUser := true + for user := range bindableStmt.Users { + if _, ok := captureFilter.users[user]; !ok { + filteredByUser = false // some user not in the black-list has processed this stmt + break + } + } + if filteredByUser { + continue + } + } } dbName := utilparser.GetDefaultDB(stmt, bindableStmt.Schema) normalizedSQL, digest := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(stmt, dbName, bindableStmt.Query)) - if r := h.GetBindRecord(digest.String(), normalizedSQL, dbName); r != nil && r.HasUsingBinding() { + if r := h.GetBindRecord(digest.String(), normalizedSQL, dbName); r != nil && r.HasAvailableBinding() { continue } bindSQL := GenerateBindSQL(context.TODO(), stmt, bindableStmt.PlanHint, true, dbName) @@ -781,7 +879,7 @@ func (h *BindHandle) CaptureBaselines() { charset, collation := h.sctx.GetSessionVars().GetCharsetInfo() binding := Binding{ BindSQL: bindSQL, - Status: Using, + Status: Enabled, Charset: charset, Collation: collation, Source: Capture, @@ -923,8 +1021,9 @@ func (h *BindHandle) SaveEvolveTasksToStore() { } func getEvolveParameters(ctx sessionctx.Context) (time.Duration, time.Time, time.Time, error) { - stmt, err := ctx.(sqlexec.RestrictedSQLExecutor).ParseWithParams( + rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL( context.TODO(), + nil, "SELECT variable_name, variable_value FROM mysql.global_variables WHERE variable_name IN (%?, %?, %?)", variable.TiDBEvolvePlanTaskMaxTime, variable.TiDBEvolvePlanTaskStartTime, @@ -933,10 +1032,6 @@ func getEvolveParameters(ctx sessionctx.Context) (time.Duration, time.Time, time if err != nil { return 0, time.Time{}, time.Time{}, err } - rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(context.TODO(), stmt) - if err != nil { - return 0, time.Time{}, time.Time{}, err - } maxTime, startTimeStr, endTimeStr := int64(variable.DefTiDBEvolvePlanTaskMaxTime), variable.DefTiDBEvolvePlanTaskStartTime, variable.DefAutoAnalyzeEndTime for _, row := range rows { switch row.GetString(0) { @@ -976,25 +1071,23 @@ const ( ) func (h *BindHandle) getOnePendingVerifyJob() (string, string, Binding) { - cache := h.bindInfo.Value.Load().(cache) - for _, bindRecords := range cache { - for _, bindRecord := range bindRecords { - for _, bind := range bindRecord.Bindings { - if bind.Status == PendingVerify { - return bindRecord.OriginalSQL, bindRecord.Db, bind - } - if bind.Status != Rejected { - continue - } - dur, err := bind.SinceUpdateTime() - // Should not happen. - if err != nil { - continue - } - // Rejected and retry it now. - if dur > nextVerifyDuration { - return bindRecord.OriginalSQL, bindRecord.Db, bind - } + cache := h.bindInfo.Value.Load().(*bindCache) + for _, bindRecord := range cache.GetAllBindRecords() { + for _, bind := range bindRecord.Bindings { + if bind.Status == PendingVerify { + return bindRecord.OriginalSQL, bindRecord.Db, bind + } + if bind.Status != Rejected { + continue + } + dur, err := bind.SinceUpdateTime() + // Should not happen. + if err != nil { + continue + } + // Rejected and retry it now. + if dur > nextVerifyDuration { + return bindRecord.OriginalSQL, bindRecord.Db, bind } } } @@ -1098,7 +1191,7 @@ func (h *BindHandle) HandleEvolvePlanTask(sctx sessionctx.Context, adminEvolve b zap.String("digestText", digestText), ) } else { - binding.Status = Using + binding.Status = Enabled } // We don't need to pass the `sctx` because the BindSQL has been validated already. return h.AddBindRecord(nil, &BindRecord{OriginalSQL: originalSQL, Db: db, Bindings: []Binding{binding}}) @@ -1107,7 +1200,7 @@ func (h *BindHandle) HandleEvolvePlanTask(sctx sessionctx.Context, adminEvolve b // Clear resets the bind handle. It is only used for test. func (h *BindHandle) Clear() { h.bindInfo.Lock() - h.bindInfo.Store(make(cache)) + h.bindInfo.Store(newBindCache()) h.bindInfo.lastUpdateTime = types.ZeroTimestamp h.bindInfo.Unlock() h.invalidBindRecordMap.Store(make(map[string]*bindRecordUpdate)) @@ -1125,7 +1218,7 @@ func (h *BindHandle) FlushBindings() error { // It is used to maintain consistency between cache and mysql.bind_info if the table is deleted or truncated. func (h *BindHandle) ReloadBindings() error { h.bindInfo.Lock() - h.bindInfo.Store(make(cache)) + h.bindInfo.Store(newBindCache()) h.bindInfo.lastUpdateTime = types.ZeroTimestamp h.bindInfo.Unlock() return h.Update(true) diff --git a/bindinfo/handle_test.go b/bindinfo/handle_test.go index 398b0641579ca..10b401c2292d6 100644 --- a/bindinfo/handle_test.go +++ b/bindinfo/handle_test.go @@ -38,7 +38,7 @@ func utilCleanBindingEnv(tk *testkit.TestKit, dom *domain.Domain) { func utilNormalizeWithDefaultDB(t *testing.T, sql, db string) (string, string) { testParser := parser.New() stmt, err := testParser.ParseOneStmt(sql, "", "") - require.Nil(t, err) + require.NoError(t, err) normalized, digest := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(stmt, "test", "")) return normalized, digest.String() } @@ -82,7 +82,7 @@ func TestBindingLastUpdateTime(t *testing.T) { bindHandle := bindinfo.NewBindHandle(tk.Session()) err := bindHandle.Update(true) - require.Nil(t, err) + require.NoError(t, err) sql, hash := parser.NormalizeDigest("select * from test . t0") bindData := bindHandle.GetBindRecord(hash.String(), sql, "test") require.Equal(t, 1, len(bindData.Bindings)) @@ -99,6 +99,31 @@ func TestBindingLastUpdateTime(t *testing.T) { tk.MustQuery(`show global status like 'last_plan_binding_update_time';`).Check(testkit.Rows()) } +func TestBindingLastUpdateTimeWithInvalidBind(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + + rows0 := tk.MustQuery("show status like 'last_plan_binding_update_time';").Rows() + updateTime0 := rows0[0][1] + require.Equal(t, updateTime0, "0000-00-00 00:00:00") + + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t`', 'select * from `test` . `t` use index(`idx`)', 'test', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + bindinfo.Manual + "')") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec("admin reload bindings;") + + rows1 := tk.MustQuery("show status like 'last_plan_binding_update_time';").Rows() + updateTime1 := rows1[0][1] + require.Equal(t, updateTime1, "2000-01-01 09:00:00.000") + + rows2 := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows2, 0) +} + func TestBindParse(t *testing.T) { store, _, clean := testkit.CreateMockStoreAndDomain(t) defer clean() @@ -112,7 +137,7 @@ func TestBindParse(t *testing.T) { originSQL := "select * from `test` . `t`" bindSQL := "select * from `test` . `t` use index(index_t)" defaultDb := "test" - status := "using" + status := bindinfo.Enabled charset := "utf8mb4" collation := "utf8mb4_bin" source := bindinfo.Manual @@ -121,7 +146,7 @@ func TestBindParse(t *testing.T) { tk.MustExec(sql) bindHandle := bindinfo.NewBindHandle(tk.Session()) err := bindHandle.Update(true) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 1, bindHandle.Size()) sql, hash := parser.NormalizeDigest("select * from test . t") @@ -131,13 +156,13 @@ func TestBindParse(t *testing.T) { bind := bindData.Bindings[0] require.Equal(t, "select * from `test` . `t` use index(index_t)", bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.Equal(t, "utf8mb4", bind.Charset) require.Equal(t, "utf8mb4_bin", bind.Collation) require.NotNil(t, bind.CreateTime) require.NotNil(t, bind.UpdateTime) dur, err := bind.SinceUpdateTime() - require.Nil(t, err) + require.NoError(t, err) require.GreaterOrEqual(t, int64(dur), int64(0)) // Test fields with quotes or slashes. @@ -203,7 +228,7 @@ func TestEvolveInvalidBindings(t *testing.T) { tk.MustExec("insert into mysql.bind_info values('select * from test . t where a > ?', 'SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10', 'test', 'rejected', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + bindinfo.Manual + "')") tk.MustQuery("select bind_sql, status from mysql.bind_info where source != 'builtin'").Sort().Check(testkit.Rows( - "SELECT /*+ USE_INDEX(`t` )*/ * FROM `test`.`t` WHERE `a` > 10 using", + "SELECT /*+ USE_INDEX(`t` )*/ * FROM `test`.`t` WHERE `a` > 10 enabled", "SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10 rejected", )) // Reload cache from mysql.bind_info. @@ -215,13 +240,118 @@ func TestEvolveInvalidBindings(t *testing.T) { require.Nil(t, dom.BindHandle().Update(false)) rows := tk.MustQuery("show global bindings").Sort().Rows() require.Equal(t, 2, len(rows)) - // Make sure this "using" binding is not overrided. + // Make sure this "enabled" binding is not overrided. require.Equal(t, "SELECT /*+ USE_INDEX(`t` )*/ * FROM `test`.`t` WHERE `a` > 10", rows[0][1]) status := rows[0][3].(string) - require.True(t, status == "using") + require.True(t, status == bindinfo.Enabled) require.Equal(t, "SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10", rows[1][1]) status = rows[1][3].(string) - require.True(t, status == "using" || status == "rejected") + require.True(t, status == bindinfo.Enabled || status == bindinfo.Rejected) +} + +func TestSetBindingStatus(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, index idx_a(a))") + tk.MustQuery("show global bindings").Check(testkit.Rows()) + tk.MustExec("create global binding for select * from t where a > 10 using select /*+ USE_INDEX(t, idx_a) */ * from t where a > 10") + rows := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + + tk.MustExec("set binding disabled for select * from t where a > 10 using select * from t where a > 10") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 There are no bindings can be set the status. Please check the SQL text")) + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + + tk.MustExec("set binding disabled for select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Disabled, rows[0][3]) + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + + tk.MustExec("set binding enabled for select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + + tk.MustExec("set binding disabled for select * from t where a > 10") + tk.MustExec("create global binding for select * from t where a > 10 using select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + + tk.MustExec("set binding disabled for select * from t where a > 10 using select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Disabled, rows[0][3]) + tk.MustExec("select * from t where a > 10") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + + tk.MustExec("set binding enabled for select * from t where a > 10 using select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + + tk.MustExec("set binding disabled for select * from t where a > 10 using select * from t where a > 10") + tk.MustExec("drop global binding for select * from t where a > 10 using select * from t where a > 10") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 0) +} + +func TestSetBindingStatusWithoutBindingInCache(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, index idx_a(a))") + utilCleanBindingEnv(tk, dom) + tk.MustQuery("show global bindings").Check(testkit.Rows()) + + // Simulate creating bindings on other machines + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` > 10', 'test', 'deleted', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + bindinfo.Manual + "')") + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` > 10', 'test', 'enabled', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" + + bindinfo.Manual + "')") + dom.BindHandle().Clear() + tk.MustExec("set binding disabled for select * from t where a > 10") + tk.MustExec("admin reload bindings") + rows := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Disabled, rows[0][3]) + + // clear the mysql.bind_info + utilCleanBindingEnv(tk, dom) + + // Simulate creating bindings on other machines + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT * FROM `test`.`t` WHERE `a` > 10', 'test', 'deleted', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + bindinfo.Manual + "')") + tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT * FROM `test`.`t` WHERE `a` > 10', 'test', 'disabled', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" + + bindinfo.Manual + "')") + dom.BindHandle().Clear() + tk.MustExec("set binding enabled for select * from t where a > 10") + tk.MustExec("admin reload bindings") + rows = tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + require.Equal(t, bindinfo.Enabled, rows[0][3]) + + utilCleanBindingEnv(tk, dom) } var testSQLs = []struct { @@ -240,7 +370,7 @@ var testSQLs = []struct { originSQL: "select * from `test` . `t` where `i` > ?", bindSQL: "SELECT * FROM `test`.`t` USE INDEX (`index_t`) WHERE `i` > 99", dropSQL: "binding for select * from t where i>100", - memoryUsage: float64(144), + memoryUsage: float64(167), }, { createSQL: "binding for select * from t union all select * from t using select * from t use index(index_t) union all select * from t use index()", @@ -249,7 +379,7 @@ var testSQLs = []struct { originSQL: "select * from `test` . `t` union all select * from `test` . `t`", bindSQL: "SELECT * FROM `test`.`t` USE INDEX (`index_t`) UNION ALL SELECT * FROM `test`.`t` USE INDEX ()", dropSQL: "binding for select * from t union all select * from t", - memoryUsage: float64(200), + memoryUsage: float64(237), }, { createSQL: "binding for (select * from t) union all (select * from t) using (select * from t use index(index_t)) union all (select * from t use index())", @@ -258,7 +388,7 @@ var testSQLs = []struct { originSQL: "( select * from `test` . `t` ) union all ( select * from `test` . `t` )", bindSQL: "(SELECT * FROM `test`.`t` USE INDEX (`index_t`)) UNION ALL (SELECT * FROM `test`.`t` USE INDEX ())", dropSQL: "binding for (select * from t) union all (select * from t)", - memoryUsage: float64(212), + memoryUsage: float64(249), }, { createSQL: "binding for select * from t intersect select * from t using select * from t use index(index_t) intersect select * from t use index()", @@ -267,7 +397,7 @@ var testSQLs = []struct { originSQL: "select * from `test` . `t` intersect select * from `test` . `t`", bindSQL: "SELECT * FROM `test`.`t` USE INDEX (`index_t`) INTERSECT SELECT * FROM `test`.`t` USE INDEX ()", dropSQL: "binding for select * from t intersect select * from t", - memoryUsage: float64(200), + memoryUsage: float64(237), }, { createSQL: "binding for select * from t except select * from t using select * from t use index(index_t) except select * from t use index()", @@ -276,7 +406,7 @@ var testSQLs = []struct { originSQL: "select * from `test` . `t` except select * from `test` . `t`", bindSQL: "SELECT * FROM `test`.`t` USE INDEX (`index_t`) EXCEPT SELECT * FROM `test`.`t` USE INDEX ()", dropSQL: "binding for select * from t except select * from t", - memoryUsage: float64(194), + memoryUsage: float64(231), }, { createSQL: "binding for select * from t using select /*+ use_index(t,index_t)*/ * from t", @@ -285,7 +415,7 @@ var testSQLs = []struct { originSQL: "select * from `test` . `t`", bindSQL: "SELECT /*+ use_index(`t` `index_t`)*/ * FROM `test`.`t`", dropSQL: "binding for select * from t", - memoryUsage: float64(124), + memoryUsage: float64(166), }, { createSQL: "binding for delete from t where i = 1 using delete /*+ use_index(t,index_t) */ from t where i = 1", @@ -294,7 +424,7 @@ var testSQLs = []struct { originSQL: "delete from `test` . `t` where `i` = ?", bindSQL: "DELETE /*+ use_index(`t` `index_t`)*/ FROM `test`.`t` WHERE `i` = 1", dropSQL: "binding for delete from t where i = 1", - memoryUsage: float64(148), + memoryUsage: float64(190), }, { createSQL: "binding for delete t, t1 from t inner join t1 on t.s = t1.s where t.i = 1 using delete /*+ use_index(t,index_t), hash_join(t,t1) */ t, t1 from t inner join t1 on t.s = t1.s where t.i = 1", @@ -303,7 +433,7 @@ var testSQLs = []struct { originSQL: "delete `test` . `t` , `test` . `t1` from `test` . `t` join `test` . `t1` on `t` . `s` = `t1` . `s` where `t` . `i` = ?", bindSQL: "DELETE /*+ use_index(`t` `index_t`) hash_join(`t`, `t1`)*/ `test`.`t`,`test`.`t1` FROM `test`.`t` JOIN `test`.`t1` ON `t`.`s` = `t1`.`s` WHERE `t`.`i` = 1", dropSQL: "binding for delete t, t1 from t inner join t1 on t.s = t1.s where t.i = 1", - memoryUsage: float64(315), + memoryUsage: float64(402), }, { createSQL: "binding for update t set s = 'a' where i = 1 using update /*+ use_index(t,index_t) */ t set s = 'a' where i = 1", @@ -312,7 +442,7 @@ var testSQLs = []struct { originSQL: "update `test` . `t` set `s` = ? where `i` = ?", bindSQL: "UPDATE /*+ use_index(`t` `index_t`)*/ `test`.`t` SET `s`='a' WHERE `i` = 1", dropSQL: "binding for update t set s = 'a' where i = 1", - memoryUsage: float64(162), + memoryUsage: float64(204), }, { createSQL: "binding for update t, t1 set t.s = 'a' where t.i = t1.i using update /*+ inl_join(t1) */ t, t1 set t.s = 'a' where t.i = t1.i", @@ -321,7 +451,7 @@ var testSQLs = []struct { originSQL: "update ( `test` . `t` ) join `test` . `t1` set `t` . `s` = ? where `t` . `i` = `t1` . `i`", bindSQL: "UPDATE /*+ inl_join(`t1`)*/ (`test`.`t`) JOIN `test`.`t1` SET `t`.`s`='a' WHERE `t`.`i` = `t1`.`i`", dropSQL: "binding for update t, t1 set t.s = 'a' where t.i = t1.i", - memoryUsage: float64(230), + memoryUsage: float64(262), }, { createSQL: "binding for insert into t1 select * from t where t.i = 1 using insert into t1 select /*+ use_index(t,index_t) */ * from t where t.i = 1", @@ -330,7 +460,7 @@ var testSQLs = []struct { originSQL: "insert into `test` . `t1` select * from `test` . `t` where `t` . `i` = ?", bindSQL: "INSERT INTO `test`.`t1` SELECT /*+ use_index(`t` `index_t`)*/ * FROM `test`.`t` WHERE `t`.`i` = 1", dropSQL: "binding for insert into t1 select * from t where t.i = 1", - memoryUsage: float64(212), + memoryUsage: float64(254), }, { createSQL: "binding for replace into t1 select * from t where t.i = 1 using replace into t1 select /*+ use_index(t,index_t) */ * from t where t.i = 1", @@ -339,7 +469,7 @@ var testSQLs = []struct { originSQL: "replace into `test` . `t1` select * from `test` . `t` where `t` . `i` = ?", bindSQL: "REPLACE INTO `test`.`t1` SELECT /*+ use_index(`t` `index_t`)*/ * FROM `test`.`t` WHERE `t`.`i` = 1", dropSQL: "binding for replace into t1 select * from t where t.i = 1", - memoryUsage: float64(214), + memoryUsage: float64(256), }, } @@ -362,19 +492,19 @@ func TestGlobalBinding(t *testing.T) { metrics.BindMemoryUsage.Reset() _, err := tk.Exec("create global " + testSQL.createSQL) - require.Nil(t, err, "err %v", err) + require.NoError(t, err, "err %v", err) if testSQL.overlaySQL != "" { _, err = tk.Exec("create global " + testSQL.overlaySQL) - require.Nil(t, err) + require.NoError(t, err) } pb := &dto.Metric{} - err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeGlobal, bindinfo.Using).Write(pb) - require.Nil(t, err) + err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeGlobal, bindinfo.Enabled).Write(pb) + require.NoError(t, err) require.Equal(t, float64(1), pb.GetGauge().GetValue()) - err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeGlobal, bindinfo.Using).Write(pb) - require.Nil(t, err) + err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeGlobal, bindinfo.Enabled).Write(pb) + require.NoError(t, err) require.Equal(t, testSQL.memoryUsage, pb.GetGauge().GetValue()) sql, hash := utilNormalizeWithDefaultDB(t, testSQL.querySQL, "test") @@ -385,23 +515,23 @@ func TestGlobalBinding(t *testing.T) { bind := bindData.Bindings[0] require.Equal(t, testSQL.bindSQL, bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.NotNil(t, bind.Charset) require.NotNil(t, bind.Collation) require.NotNil(t, bind.CreateTime) require.NotNil(t, bind.UpdateTime) rs, err := tk.Exec("show global bindings") - require.Nil(t, err) + require.NoError(t, err) chk := rs.NewChunk(nil) err = rs.Next(context.TODO(), chk) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 1, chk.NumRows()) row := chk.GetRow(0) require.Equal(t, testSQL.originSQL, row.GetString(0)) require.Equal(t, testSQL.bindSQL, row.GetString(1)) require.Equal(t, "test", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.NotNil(t, row.GetTime(4)) require.NotNil(t, row.GetTime(5)) require.NotNil(t, row.GetString(6)) @@ -409,7 +539,7 @@ func TestGlobalBinding(t *testing.T) { bindHandle := bindinfo.NewBindHandle(tk.Session()) err = bindHandle.Update(true) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 1, bindHandle.Size()) bindData = bindHandle.GetBindRecord(hash, sql, "test") @@ -418,42 +548,42 @@ func TestGlobalBinding(t *testing.T) { bind = bindData.Bindings[0] require.Equal(t, testSQL.bindSQL, bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.NotNil(t, bind.Charset) require.NotNil(t, bind.Collation) require.NotNil(t, bind.CreateTime) require.NotNil(t, bind.UpdateTime) _, err = tk.Exec("drop global " + testSQL.dropSQL) - require.Nil(t, err) + require.NoError(t, err) bindData = dom.BindHandle().GetBindRecord(hash, sql, "test") require.Nil(t, bindData) - err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeGlobal, bindinfo.Using).Write(pb) - require.Nil(t, err) + err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeGlobal, bindinfo.Enabled).Write(pb) + require.NoError(t, err) require.Equal(t, float64(0), pb.GetGauge().GetValue()) - err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeGlobal, bindinfo.Using).Write(pb) - require.Nil(t, err) + err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeGlobal, bindinfo.Enabled).Write(pb) + require.NoError(t, err) // From newly created global bind handle. require.Equal(t, testSQL.memoryUsage, pb.GetGauge().GetValue()) bindHandle = bindinfo.NewBindHandle(tk.Session()) err = bindHandle.Update(true) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 0, bindHandle.Size()) bindData = bindHandle.GetBindRecord(hash, sql, "test") require.Nil(t, bindData) rs, err = tk.Exec("show global bindings") - require.Nil(t, err) + require.NoError(t, err) chk = rs.NewChunk(nil) err = rs.Next(context.TODO(), chk) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 0, chk.NumRows()) _, err = tk.Exec("delete from mysql.bind_info where source != 'builtin'") - require.Nil(t, err) + require.NoError(t, err) } } diff --git a/bindinfo/main_test.go b/bindinfo/main_test.go index 85151366ea0ef..3b69fc67ec943 100644 --- a/bindinfo/main_test.go +++ b/bindinfo/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/bindinfo/session_handle.go b/bindinfo/session_handle.go index adf7a6704624d..742a45473c096 100644 --- a/bindinfo/session_handle.go +++ b/bindinfo/session_handle.go @@ -23,26 +23,31 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/logutil" + "go.uber.org/zap" ) // SessionHandle is used to handle all session sql bind operations. type SessionHandle struct { - ch cache + ch *bindCache parser *parser.Parser } // NewSessionBindHandle creates a new SessionBindHandle. func NewSessionBindHandle(parser *parser.Parser) *SessionHandle { sessionHandle := &SessionHandle{parser: parser} - sessionHandle.ch = make(cache) + sessionHandle.ch = newBindCache() return sessionHandle } // appendBindRecord adds the BindRecord to the cache, all the stale bindMetas are // removed from the cache after this operation. func (h *SessionHandle) appendBindRecord(hash string, meta *BindRecord) { - oldRecord := h.ch.getBindRecord(hash, meta.OriginalSQL, meta.Db) - h.ch.setBindRecord(hash, meta) + oldRecord := h.ch.GetBindRecord(hash, meta.OriginalSQL, meta.Db) + err := h.ch.SetBindRecord(hash, meta) + if err != nil { + logutil.BgLogger().Warn("[sql-bind] SessionHandle.appendBindRecord", zap.Error(err)) + } updateMetrics(metrics.ScopeSession, oldRecord, meta, false) } @@ -68,7 +73,8 @@ func (h *SessionHandle) CreateBindRecord(sctx sessionctx.Context, record *BindRe // DropBindRecord drops a BindRecord in the cache. func (h *SessionHandle) DropBindRecord(originalSQL, db string, binding *Binding) error { db = strings.ToLower(db) - oldRecord := h.GetBindRecord(originalSQL, db) + hash := parser.DigestNormalized(originalSQL).String() + oldRecord := h.GetBindRecord(hash, originalSQL, db) var newRecord *BindRecord record := &BindRecord{OriginalSQL: originalSQL, Db: db} if binding != nil { @@ -79,37 +85,29 @@ func (h *SessionHandle) DropBindRecord(originalSQL, db string, binding *Binding) } else { newRecord = record } - h.ch.setBindRecord(parser.DigestNormalized(record.OriginalSQL).String(), newRecord) + err := h.ch.SetBindRecord(hash, newRecord) + if err != nil { + // Should never reach here, just return an error for safety + return err + } updateMetrics(metrics.ScopeSession, oldRecord, newRecord, false) return nil } // GetBindRecord return the BindMeta of the (normdOrigSQL,db) if BindMeta exist. -func (h *SessionHandle) GetBindRecord(normdOrigSQL, db string) *BindRecord { - hash := parser.DigestNormalized(normdOrigSQL).String() - bindRecords := h.ch[hash] - for _, bindRecord := range bindRecords { - if bindRecord.OriginalSQL == normdOrigSQL { - return bindRecord - } - } - return nil +func (h *SessionHandle) GetBindRecord(hash, normdOrigSQL, db string) *BindRecord { + return h.ch.GetBindRecord(hash, normdOrigSQL, db) } // GetAllBindRecord return all session bind info. func (h *SessionHandle) GetAllBindRecord() (bindRecords []*BindRecord) { - for _, bindRecord := range h.ch { - bindRecords = append(bindRecords, bindRecord...) - } - return bindRecords + return h.ch.GetAllBindRecords() } // Close closes the session handle. func (h *SessionHandle) Close() { - for _, bindRecords := range h.ch { - for _, bindRecord := range bindRecords { - updateMetrics(metrics.ScopeSession, bindRecord, nil, false) - } + for _, bindRecord := range h.ch.GetAllBindRecords() { + updateMetrics(metrics.ScopeSession, bindRecord, nil, false) } } diff --git a/bindinfo/session_handle_test.go b/bindinfo/session_handle_test.go index 86fa4d4542fe6..402f9574d911e 100644 --- a/bindinfo/session_handle_test.go +++ b/bindinfo/session_handle_test.go @@ -24,6 +24,7 @@ import ( "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/metrics" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/auth" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session/txninfo" @@ -105,7 +106,7 @@ func TestSessionBinding(t *testing.T) { metrics.BindMemoryUsage.Reset() _, err := tk.Exec("create session " + testSQL.createSQL) - require.Nil(t, err, "err %v", err) + require.NoError(t, err, "err %v", err) if testSQL.overlaySQL != "" { _, err = tk.Exec("create session " + testSQL.overlaySQL) @@ -113,21 +114,22 @@ func TestSessionBinding(t *testing.T) { } pb := &dto.Metric{} - err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeSession, bindinfo.Using).Write(pb) + err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeSession, bindinfo.Enabled).Write(pb) require.NoError(t, err) require.Equal(t, float64(1), pb.GetGauge().GetValue()) - err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeSession, bindinfo.Using).Write(pb) + err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeSession, bindinfo.Enabled).Write(pb) require.NoError(t, err) require.Equal(t, testSQL.memoryUsage, pb.GetGauge().GetValue()) handle := tk.Session().Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle) - bindData := handle.GetBindRecord(testSQL.originSQL, "test") + hash := parser.DigestNormalized(testSQL.originSQL).String() + bindData := handle.GetBindRecord(hash, testSQL.originSQL, "test") require.NotNil(t, bindData) require.Equal(t, testSQL.originSQL, bindData.OriginalSQL) bind := bindData.Bindings[0] require.Equal(t, testSQL.bindSQL, bind.BindSQL) require.Equal(t, "test", bindData.Db) - require.Equal(t, "using", bind.Status) + require.Equal(t, bindinfo.Enabled, bind.Status) require.NotNil(t, bind.Charset) require.NotNil(t, bind.Collation) require.NotNil(t, bind.CreateTime) @@ -150,7 +152,7 @@ func TestSessionBinding(t *testing.T) { require.Equal(t, testSQL.originSQL, row.GetString(0)) require.Equal(t, testSQL.bindSQL, row.GetString(1)) require.Equal(t, "test", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.NotNil(t, row.GetTime(4)) require.NotNil(t, row.GetTime(5)) require.NotNil(t, row.GetString(6)) @@ -158,15 +160,15 @@ func TestSessionBinding(t *testing.T) { _, err = tk.Exec("drop session " + testSQL.dropSQL) require.NoError(t, err) - bindData = handle.GetBindRecord(testSQL.originSQL, "test") + bindData = handle.GetBindRecord(hash, testSQL.originSQL, "test") require.NotNil(t, bindData) require.Equal(t, testSQL.originSQL, bindData.OriginalSQL) require.Len(t, bindData.Bindings, 0) - err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeSession, bindinfo.Using).Write(pb) + err = metrics.BindTotalGauge.WithLabelValues(metrics.ScopeSession, bindinfo.Enabled).Write(pb) require.NoError(t, err) require.Equal(t, float64(0), pb.GetGauge().GetValue()) - err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeSession, bindinfo.Using).Write(pb) + err = metrics.BindMemoryUsage.WithLabelValues(metrics.ScopeSession, bindinfo.Enabled).Write(pb) require.NoError(t, err) require.Equal(t, float64(0), pb.GetGauge().GetValue()) } @@ -222,7 +224,7 @@ func TestBaselineDBLowerCase(t *testing.T) { utilCleanBindingEnv(tk, dom) // Simulate existing bindings with upper case default_db. - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t`', 'SPM', 'using', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t`', 'SPM', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + bindinfo.Manual + "')") tk.MustQuery("select original_sql, default_db from mysql.bind_info where original_sql = 'select * from `spm` . `t`'").Check(testkit.Rows( "select * from `spm` . `t` SPM", @@ -240,7 +242,7 @@ func TestBaselineDBLowerCase(t *testing.T) { utilCleanBindingEnv(tk, dom) // Simulate existing bindings with upper case default_db. - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t`', 'SPM', 'using', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t`', 'SPM', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + bindinfo.Manual + "')") tk.MustQuery("select original_sql, default_db from mysql.bind_info where original_sql = 'select * from `spm` . `t`'").Check(testkit.Rows( "select * from `spm` . `t` SPM", @@ -259,7 +261,7 @@ func TestBaselineDBLowerCase(t *testing.T) { require.Equal(t, "spm", rows[0][2]) tk.MustQuery("select original_sql, default_db, status from mysql.bind_info where original_sql = 'select * from `spm` . `t`'").Check(testkit.Rows( "select * from `spm` . `t` SPM deleted", - "select * from `spm` . `t` spm using", + "select * from `spm` . `t` spm enabled", )) } @@ -278,13 +280,13 @@ func TestShowGlobalBindings(t *testing.T) { rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) // Simulate existing bindings in the mysql.bind_info. - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t` USE INDEX (`a`)', 'SPM', 'using', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select * from `spm` . `t` USE INDEX (`a`)', 'SPM', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" + bindinfo.Manual + "')") - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t0`', 'select * from `spm` . `t0` USE INDEX (`a`)', 'SPM', 'using', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t0`', 'select * from `spm` . `t0` USE INDEX (`a`)', 'SPM', 'enabled', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" + bindinfo.Manual + "')") - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select /*+ use_index(`t` `a`)*/ * from `spm` . `t`', 'SPM', 'using', '2000-01-03 09:00:00', '2000-01-03 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t`', 'select /*+ use_index(`t` `a`)*/ * from `spm` . `t`', 'SPM', 'enabled', '2000-01-03 09:00:00', '2000-01-03 09:00:00', '', '','" + bindinfo.Manual + "')") - tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t0`', 'select /*+ use_index(`t0` `a`)*/ * from `spm` . `t0`', 'SPM', 'using', '2000-01-04 09:00:00', '2000-01-04 09:00:00', '', '','" + + tk.MustExec("insert into mysql.bind_info values('select * from `spm` . `t0`', 'select /*+ use_index(`t0` `a`)*/ * from `spm` . `t0`', 'SPM', 'enabled', '2000-01-04 09:00:00', '2000-01-04 09:00:00', '', '','" + bindinfo.Manual + "')") tk.MustExec("admin reload bindings") rows = tk.MustQuery("show global bindings").Rows() @@ -404,6 +406,14 @@ func (msm *mockSessionManager) ServerID() uint64 { return 1 } +func (msm *mockSessionManager) StoreInternalSession(se interface{}) {} + +func (msm *mockSessionManager) DeleteInternalSession(se interface{}) {} + +func (msm *mockSessionManager) GetInternalSessionStartTSList() []uint64 { + return nil +} + func TestIssue19836(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/br/cmd/br/backup.go b/br/cmd/br/backup.go index 442672fad871e..c6b49b43f21b1 100644 --- a/br/cmd/br/backup.go +++ b/br/cmd/br/backup.go @@ -105,7 +105,7 @@ func newFullBackupCommand() *cobra.Command { Args: cobra.NoArgs, RunE: func(command *cobra.Command, _ []string) error { // empty db/table means full backup. - return runBackupCommand(command, "Full backup") + return runBackupCommand(command, task.FullBackupCmd) }, } task.DefineFilterFlags(command, acceptAllTables) @@ -119,7 +119,7 @@ func newDBBackupCommand() *cobra.Command { Short: "backup a database", Args: cobra.NoArgs, RunE: func(command *cobra.Command, _ []string) error { - return runBackupCommand(command, "Database backup") + return runBackupCommand(command, task.DBBackupCmd) }, } task.DefineDatabaseFlags(command) @@ -133,7 +133,7 @@ func newTableBackupCommand() *cobra.Command { Short: "backup a table", Args: cobra.NoArgs, RunE: func(command *cobra.Command, _ []string) error { - return runBackupCommand(command, "Table backup") + return runBackupCommand(command, task.TableBackupCmd) }, } task.DefineTableFlags(command) @@ -148,7 +148,7 @@ func newRawBackupCommand() *cobra.Command { Short: "(experimental) backup a raw kv range from TiKV cluster", Args: cobra.NoArgs, RunE: func(command *cobra.Command, _ []string) error { - return runBackupRawCommand(command, "Raw backup") + return runBackupRawCommand(command, task.RawBackupCmd) }, } diff --git a/br/cmd/br/cmd.go b/br/cmd/br/cmd.go index 8a1a03a93464b..81e2093381b0a 100644 --- a/br/cmd/br/cmd.go +++ b/br/cmd/br/cmd.go @@ -13,13 +13,14 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/log" - tidbutils "github.com/pingcap/tidb-tools/pkg/utils" "github.com/pingcap/tidb/br/pkg/gluetidb" "github.com/pingcap/tidb/br/pkg/redact" "github.com/pingcap/tidb/br/pkg/summary" "github.com/pingcap/tidb/br/pkg/task" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/br/pkg/version/build" + "github.com/pingcap/tidb/config" + tidbutils "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" "github.com/spf13/cobra" ) @@ -111,9 +112,8 @@ func Init(cmd *cobra.Command) (err error) { // otherwise the info will be print in stdout... tidbLogCfg.File.Filename = timestampLogFileName() } else { - // Disable annoying TiDB Log. - // TODO: some error logs outputs randomly, we need to fix them in TiDB. - tidbLogCfg.Level = "fatal" + // Don't print slow log in br + config.GetGlobalConfig().Log.EnableSlowLog.Store(false) } e = logutil.InitLogger(&tidbLogCfg) if e != nil { diff --git a/br/cmd/br/restore.go b/br/cmd/br/restore.go index c57712ba8bddc..32d04994c793e 100644 --- a/br/cmd/br/restore.go +++ b/br/cmd/br/restore.go @@ -95,7 +95,7 @@ func newFullRestoreCommand() *cobra.Command { Short: "restore all tables", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return runRestoreCommand(cmd, "Full restore") + return runRestoreCommand(cmd, task.FullRestoreCmd) }, } task.DefineFilterFlags(command, filterOutSysAndMemTables) @@ -108,7 +108,7 @@ func newDBRestoreCommand() *cobra.Command { Short: "restore tables in a database from the backup data", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return runRestoreCommand(cmd, "Database restore") + return runRestoreCommand(cmd, task.DBRestoreCmd) }, } task.DefineDatabaseFlags(command) @@ -121,7 +121,7 @@ func newTableRestoreCommand() *cobra.Command { Short: "restore a table from the backup data", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return runRestoreCommand(cmd, "Table restore") + return runRestoreCommand(cmd, task.TableRestoreCmd) }, } task.DefineTableFlags(command) @@ -134,7 +134,7 @@ func newRawRestoreCommand() *cobra.Command { Short: "(experimental) restore a raw kv range to TiKV cluster", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return runRestoreRawCommand(cmd, "Raw restore") + return runRestoreRawCommand(cmd, task.RawRestoreCmd) }, } diff --git a/br/cmd/tidb-lightning-ctl/main.go b/br/cmd/tidb-lightning-ctl/main.go index 43891c8fb0fb3..b877fecb2f3c9 100644 --- a/br/cmd/tidb-lightning-ctl/main.go +++ b/br/cmd/tidb-lightning-ctl/main.go @@ -254,7 +254,7 @@ func checkpointDump(ctx context.Context, cfg *config.Config, dumpFolder string) } defer cpdb.Close() - if err := os.MkdirAll(dumpFolder, 0o755); err != nil { + if err := os.MkdirAll(dumpFolder, 0o750); err != nil { return errors.Trace(err) } diff --git a/br/cmd/tidb-lightning/main.go b/br/cmd/tidb-lightning/main.go index 84362433f222c..079182ce0863e 100644 --- a/br/cmd/tidb-lightning/main.go +++ b/br/cmd/tidb-lightning/main.go @@ -23,8 +23,10 @@ import ( "syscall" "github.com/pingcap/tidb/br/pkg/lightning" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/log" + "github.com/pingcap/tidb/br/pkg/lightning/web" "go.uber.org/zap" ) @@ -77,6 +79,9 @@ func main() { fmt.Fprintln(os.Stderr, "failed to start HTTP server:", err) return } + if len(globalCfg.App.StatusAddr) > 0 { + web.EnableCurrentProgress() + } err = func() error { if globalCfg.App.ServerMode { @@ -86,15 +91,24 @@ func main() { if err := cfg.LoadFromGlobal(globalCfg); err != nil { return err } - return app.RunOnce(context.Background(), cfg, nil) + return app.RunOnceWithOptions(context.Background(), cfg) }() + finished := true + if common.IsContextCanceledError(err) { + err = nil + finished = false + } if err != nil { logger.Error("tidb lightning encountered error stack info", zap.Error(err)) - fmt.Fprintln(os.Stderr, "tidb lightning encountered error: ", err) + fmt.Fprintln(os.Stderr, "tidb lightning encountered error:", err) } else { - logger.Info("tidb lightning exit") - fmt.Fprintln(os.Stdout, "tidb lightning exit") + logger.Info("tidb lightning exit", zap.Bool("finished", finished)) + exitMsg := "tidb lightning exit successfully" + if !finished { + exitMsg = "tidb lightning canceled" + } + fmt.Fprintln(os.Stdout, exitMsg) } // call Sync() with log to stdout may return error in some case, so just skip it diff --git a/br/metrics/grafana/br.json b/br/metrics/grafana/br.json index 5a2d0ad5d771f..3b48947f0eab1 100644 --- a/br/metrics/grafana/br.json +++ b/br/metrics/grafana/br.json @@ -123,7 +123,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"(backup-worker|bkwkr).*\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"(backup-worker|bkwkr).*\"}[1m])) by (instance)", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -133,7 +133,7 @@ "step": 4 }, { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"backup_endpoint\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"backup_endpoint\"}[1m])) by (instance)", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -143,7 +143,7 @@ "step": 4 }, { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"(backup-worker|bkwkr).*\"}[1m])) by (instance, tid) > 0", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"(backup-worker|bkwkr).*\"}[1m])) by (instance, tid) > 0", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -153,7 +153,7 @@ "step": 4 }, { - "expr": "sum(tikv_backup_thread_pool_size{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) by(instance)", + "expr": "sum(tikv_backup_thread_pool_size{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) by(instance)", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -253,7 +253,7 @@ ], "targets": [ { - "expr": "sum(tikv_backup_thread_pool_size{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) by(instance)", + "expr": "sum(tikv_backup_thread_pool_size{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) by(instance)", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -308,7 +308,7 @@ "steppedLine": false, "targets": [ { - "expr": "delta(tikv_backup_error_counter{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])", + "expr": "delta(tikv_backup_error_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -401,7 +401,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_backup_range_size_bytes_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", cf=\"write\"}[1m])) by (le)", + "expr": "max(rate(tikv_backup_range_size_bytes_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", cf=\"write\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -478,7 +478,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_backup_range_size_bytes_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", cf=\"default\"}[1m])) by (le)", + "expr": "max(rate(tikv_backup_range_size_bytes_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", cf=\"default\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -560,7 +560,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_backup_range_size_bytes_sum{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]))", + "expr": "sum(rate(tikv_backup_range_size_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]))", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -570,7 +570,7 @@ "step": 4 }, { - "expr": "rate(tikv_backup_range_size_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tikv_backup_range_size_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -666,7 +666,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"snapshot\"}[1m])) by (le)", + "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"snapshot\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -743,7 +743,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"scan\"}[1m])) by (le)", + "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"scan\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -820,7 +820,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=~\"save.*\"}[1m])) by (le)", + "expr": "max(rate(tikv_backup_range_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=~\"save.*\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -897,7 +897,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tikv_backup_range_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_backup_range_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}} - 99%", @@ -906,7 +906,7 @@ "step": 4 }, { - "expr": "histogram_quantile(0.95, sum(rate(tikv_backup_range_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.95, sum(rate(tikv_backup_range_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}} - 95%", @@ -914,7 +914,7 @@ "step": 4 }, { - "expr": "sum(rate(tikv_backup_range_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (type) / sum(rate(tikv_backup_range_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (type)", + "expr": "sum(rate(tikv_backup_range_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (type) / sum(rate(tikv_backup_range_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}} - avg", @@ -1008,7 +1008,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_external_storage_create_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le)", + "expr": "max(rate(tikv_external_storage_create_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -1089,14 +1089,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tikv_external_storage_create_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le,type))", + "expr": "histogram_quantile(1, sum(rate(tikv_external_storage_create_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le,type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-100%", "refId": "E" }, { - "expr": "histogram_quantile(0.99, sum(rate(tikv_external_storage_create_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le,type))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_external_storage_create_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le,type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-99%", @@ -1195,14 +1195,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", + "expr": "histogram_quantile(1, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-100%", "refId": "E" }, { - "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-99%", @@ -1300,7 +1300,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(node_disk_io_time_seconds_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(node_disk_io_time_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{device}}", @@ -1400,7 +1400,7 @@ }, "lines": true, "linewidth": 1, - "links": [], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -1417,7 +1417,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -1427,7 +1427,7 @@ "step": 4 }, { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance, tid) > 0", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance, tid) > 0", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -1437,7 +1437,7 @@ "step": 4 }, { - "expr": "count(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", + "expr": "count(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -1537,7 +1537,7 @@ ], "targets": [ { - "expr": "count(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", + "expr": "count(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", name=~\"sst_.*\"}[1m])) by (instance)", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -1593,7 +1593,7 @@ "steppedLine": false, "targets": [ { - "expr": "delta(tikv_import_error_counter{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])", + "expr": "delta(tikv_import_error_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1681,7 +1681,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tikv_import_rpc_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, request))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_import_rpc_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le, request))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1777,7 +1777,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(node_disk_io_time_seconds_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(node_disk_io_time_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{device}}", @@ -1872,7 +1872,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_rpc_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", request=~\"download|write\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_rpc_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", request=~\"download|write\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -1949,7 +1949,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_download_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"queue\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_download_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"queue\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2026,7 +2026,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_download_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"read\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_download_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"read\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2103,7 +2103,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_download_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"rewrite\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_download_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"rewrite\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2180,7 +2180,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_rpc_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", request=~\"ingest\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_rpc_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", request=~\"ingest\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2257,7 +2257,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_ingest_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=~\"ingest\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_ingest_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=~\"ingest\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2334,7 +2334,7 @@ "reverseYBuckets": false, "targets": [ { - "expr": "max(rate(tikv_import_ingest_byte{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le)", + "expr": "max(rate(tikv_import_ingest_byte{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m])) by (le)", "format": "heatmap", "instant": false, "intervalFactor": 2, @@ -2406,14 +2406,14 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_import_download_bytes_sum{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]))", + "expr": "sum(rate(tikv_import_download_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "total", "refId": "A" }, { - "expr": "rate(tikv_import_download_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tikv_import_download_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}", @@ -2513,7 +2513,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"leader\"}) by (instance)", + "expr": "sum(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"leader\"}) by (instance)", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -2522,7 +2522,7 @@ "step": 10 }, { - "expr": "delta(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"leader\"}[30s]) < -10", + "expr": "delta(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"leader\"}[30s]) < -10", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -2619,7 +2619,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"region\"}) by (instance)", + "expr": "sum(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", type=\"region\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2717,14 +2717,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", + "expr": "histogram_quantile(1, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-100%", "refId": "E" }, { - "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", req=~\"checksum.*|analyze.*\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-99%", @@ -2822,7 +2822,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(node_disk_io_time_seconds_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(node_disk_io_time_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{device}}", @@ -2884,6 +2884,26 @@ "tags": [], "templating": { "list": [ + { + "allValue": null, + "current": { }, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [ ], + "query": "label_values(tikv_engine_size_bytes, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, { "allValue": null, "current": { @@ -2897,7 +2917,7 @@ "options": [ ], - "query": "label_values(tikv_engine_size_bytes, tidb_cluster)", + "query": "label_values(tikv_engine_size_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster)", "refresh": 2, "regex": "", "sort": 1, diff --git a/br/metrics/grafana/lightning.json b/br/metrics/grafana/lightning.json index d842f9f523a4c..624fc3e91c953 100644 --- a/br/metrics/grafana/lightning.json +++ b/br/metrics/grafana/lightning.json @@ -100,14 +100,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tikv_import_write_chunk_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tikv_import_write_chunk_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "write from lightning", "refId": "B" }, { - "expr": "sum(rate(tikv_import_upload_chunk_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tikv_import_upload_chunk_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "upload to tikv", @@ -182,7 +182,7 @@ "steppedLine": false, "targets": [ { - "expr": "1/rate(lightning_chunks{tidb_cluster=\"$tidb_cluster\", state=\"finished\"}[1m]) ", + "expr": "1/rate(lightning_chunks{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", state=\"finished\"}[1m]) ", "format": "time_series", "intervalFactor": 2, "legendFormat": "", @@ -294,7 +294,7 @@ "tableColumn": "", "targets": [ { - "expr": "lightning_chunks{tidb_cluster=\"$tidb_cluster\", state=\"finished\"} / ignoring(state) lightning_chunks{tidb_cluster=\"$tidb_cluster\", state=\"estimated\"}", + "expr": "lightning_chunks{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", state=\"finished\"} / ignoring(state) lightning_chunks{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", state=\"estimated\"}", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -370,7 +370,7 @@ "tableColumn": "", "targets": [ { - "expr": "lightning_tables{tidb_cluster=\"$tidb_cluster\", state=\"completed\"} / ignoring(state) lightning_tables{tidb_cluster=\"$tidb_cluster\", state=\"pending\"}", + "expr": "lightning_tables{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", state=\"completed\"} / ignoring(state) lightning_tables{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", state=\"pending\"}", "format": "time_series", "instant": false, "intervalFactor": 1, @@ -454,7 +454,7 @@ ], "targets": [ { - "expr": "lightning_tables{tidb_cluster=\"$tidb_cluster\", result=\"failure\"}", + "expr": "lightning_tables{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", result=\"failure\"}", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -510,14 +510,14 @@ "steppedLine": false, "targets": [ { - "expr": "process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tikv-importer\"}", + "expr": "process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tikv-importer\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "importer RSS", "refId": "A" }, { - "expr": "go_memstats_heap_inuse_bytes{tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}", + "expr": "go_memstats_heap_inuse_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "lightning heap", @@ -592,7 +592,7 @@ "steppedLine": false, "targets": [ { - "expr": "go_goroutines{tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}", + "expr": "go_goroutines{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -671,14 +671,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(process_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}[30s])*100", + "expr": "rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"lightning\"}[30s])*100", "format": "time_series", "intervalFactor": 2, "legendFormat": "Lightning", "refId": "A" }, { - "expr": "rate(process_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", job=\"tikv-importer\"}[30s])*100", + "expr": "rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tikv-importer\"}[30s])*100", "format": "time_series", "intervalFactor": 2, "legendFormat": "Importer", @@ -766,7 +766,7 @@ "steppedLine": true, "targets": [ { - "expr": "lightning_idle_workers{tidb_cluster=\"$tidb_cluster\"}", + "expr": "lightning_idle_workers{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{name}}", @@ -842,21 +842,21 @@ "steppedLine": true, "targets": [ { - "expr": "lightning_kv_encoder{tidb_cluster=\"$tidb_cluster\", type=\"open\"} - ignoring(type) lightning_kv_encoder{tidb_cluster=\"$tidb_cluster\", type=\"closed\"}", + "expr": "lightning_kv_encoder{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"open\"} - ignoring(type) lightning_kv_encoder{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"closed\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "KV Encoder", "refId": "A" }, { - "expr": "lightning_importer_engine{tidb_cluster=\"$tidb_cluster\", type=\"open\"} - ignoring(type) lightning_importer_engine{tidb_cluster=\"$tidb_cluster\", type=\"closed\"}", + "expr": "lightning_importer_engine{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"open\"} - ignoring(type) lightning_importer_engine{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"closed\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "Importer Engines (via Lightning)", "refId": "B" }, { - "expr": "tikv_import_rpc_duration_count{tidb_cluster=\"$tidb_cluster\", request=\"open_engine\",result=\"ok\"} - ignoring(request) tikv_import_rpc_duration_count{tidb_cluster=\"$tidb_cluster\", request=\"close_engine\",result=\"ok\"}", + "expr": "tikv_import_rpc_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", request=\"open_engine\",result=\"ok\"} - ignoring(request) tikv_import_rpc_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", request=\"close_engine\",result=\"ok\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "Importer Engines (via Importer)", @@ -958,7 +958,7 @@ ], "targets": [ { - "expr": "min(tikv_config_rocksdb{tidb_cluster=\"$tidb_cluster\", name=\"hard_pending_compaction_bytes_limit\"}) by (instance)", + "expr": "min(tikv_config_rocksdb{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", name=\"hard_pending_compaction_bytes_limit\"}) by (instance)", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -1014,14 +1014,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(lightning_chunk_parser_read_block_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_chunk_parser_read_block_seconds_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(lightning_chunk_parser_read_block_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_chunk_parser_read_block_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "read block", "refId": "A" }, { - "expr": "rate(lightning_apply_worker_seconds_sum{tidb_cluster=\"$tidb_cluster\", name = \"io\"}[30s]) /rate(lightning_apply_worker_seconds_count{tidb_cluster=\"$tidb_cluster\", name = \"io\"}[30s]) ", + "expr": "rate(lightning_apply_worker_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", name = \"io\"}[30s]) /rate(lightning_apply_worker_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", name = \"io\"}[30s]) ", "format": "time_series", "intervalFactor": 2, "legendFormat": "apply worker", @@ -1096,14 +1096,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(lightning_row_encode_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_row_encode_seconds_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(lightning_row_encode_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_row_encode_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "row encode", "refId": "A" }, { - "expr": "rate(lightning_block_deliver_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_block_deliver_seconds_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(lightning_block_deliver_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(lightning_block_deliver_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "block deliver", @@ -1190,14 +1190,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(lightning_block_deliver_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(lightning_block_deliver_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{kind}} deliver rate", "refId": "B" }, { - "expr": "sum(rate(lightning_block_deliver_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[30s]))", + "expr": "sum(rate(lightning_block_deliver_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "total deliver rate", @@ -1272,21 +1272,21 @@ "steppedLine": false, "targets": [ { - "expr": "lightning_row_read_bytes_sum{tidb_cluster=\"$tidb_cluster\"}", + "expr": "lightning_row_read_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "parser read size", "refId": "A" }, { - "expr": "lightning_block_deliver_bytes_sum{tidb_cluster=\"$tidb_cluster\"}", + "expr": "lightning_block_deliver_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{kind}} deliver size", "refId": "B" }, { - "expr": "pd_cluster_status{tidb_cluster=\"$tidb_cluster\", type=\"storage_size\"} / ignoring(type) pd_config_status{tidb_cluster=\"$tidb_cluster\", type=\"max_replicas\"}", + "expr": "pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"storage_size\"} / ignoring(type) pd_config_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"max_replicas\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "storage_size / replicas", @@ -1373,14 +1373,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tikv_import_range_delivery_duration_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_range_delivery_duration_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_range_delivery_duration_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_range_delivery_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "range deliver", "refId": "A" }, { - "expr": "rate(tikv_import_sst_delivery_duration_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_delivery_duration_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_sst_delivery_duration_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_delivery_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "SST file deliver", @@ -1461,14 +1461,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tikv_import_split_sst_duration_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_split_sst_duration_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_split_sst_duration_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_split_sst_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "Split SST", "refId": "C" }, { - "expr": "rate(tikv_import_sst_upload_duration_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_upload_duration_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_sst_upload_duration_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_upload_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -1476,7 +1476,7 @@ "refId": "D" }, { - "expr": "rate(tikv_import_sst_ingest_duration_sum{tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_ingest_duration_count{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_sst_ingest_duration_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]) / rate(tikv_import_sst_ingest_duration_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -1484,7 +1484,7 @@ "refId": "E" }, { - "expr": "rate(tikv_import_sst_chunk_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tikv_import_sst_chunk_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 2, "legendFormat": "SST size", @@ -1541,6 +1541,26 @@ "tags": [], "templating": { "list": [ + { + "allValue": null, + "current": { }, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [ ], + "query": "label_values(lightning_chunks, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, { "allValue": null, "current": { @@ -1554,7 +1574,7 @@ "options": [ ], - "query": "label_values(lightning_chunks, tidb_cluster)", + "query": "label_values(lightning_chunks{k8s_cluster=\"$k8s_cluster\"}, tidb_cluster)", "refresh": 2, "regex": "", "sort": 1, diff --git a/br/pkg/backup/client.go b/br/pkg/backup/client.go index 12a4344a432fe..72730293c230f 100644 --- a/br/pkg/backup/client.go +++ b/br/pkg/backup/client.go @@ -18,9 +18,9 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/log" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" "github.com/pingcap/tidb/br/pkg/conn" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/logutil" @@ -38,6 +38,7 @@ import ( "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/ranger" + filter "github.com/pingcap/tidb/util/table-filter" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/txnkv/txnlock" @@ -82,8 +83,9 @@ type Client struct { mgr ClientMgr clusterID uint64 - storage storage.ExternalStorage - backend *backuppb.StorageBackend + storage storage.ExternalStorage + backend *backuppb.StorageBackend + apiVersion kvrpcpb.APIVersion gcTTL int64 } @@ -158,6 +160,11 @@ func (bc *Client) GetGCTTL() int64 { return bc.gcTTL } +// GetStorageBackend gets storage backupend field in client. +func (bc *Client) GetStorageBackend() *backuppb.StorageBackend { + return bc.backend +} + // GetStorage gets storage for this backup. func (bc *Client) GetStorage() storage.ExternalStorage { return bc.storage @@ -193,6 +200,16 @@ func (bc *Client) GetClusterID() uint64 { return bc.clusterID } +// GetApiVersion sets api version of the TiKV storage +func (bc *Client) GetApiVersion() kvrpcpb.APIVersion { + return bc.apiVersion +} + +// SetApiVersion sets api version of the TiKV storage +func (bc *Client) SetApiVersion(v kvrpcpb.APIVersion) { + bc.apiVersion = v +} + // CheckBackupStorageIsLocked checks whether backups is locked. // which means we found other backup progress already write // some data files into the same backup directory or cloud prefix. @@ -270,15 +287,34 @@ func BuildBackupRangeAndSchema( storage kv.Storage, tableFilter filter.Filter, backupTS uint64, -) ([]rtree.Range, *Schemas, error) { + isFullBackup bool, +) ([]rtree.Range, *Schemas, []*backuppb.PlacementPolicy, error) { snapshot := storage.GetSnapshot(kv.NewVersion(backupTS)) m := meta.NewSnapshotMeta(snapshot) + var policies []*backuppb.PlacementPolicy + if isFullBackup { + // according to https://github.com/pingcap/tidb/issues/32290 + // only full backup will record policies in backupMeta. + policyList, err := m.ListPolicies() + if err != nil { + return nil, nil, nil, errors.Trace(err) + } + policies = make([]*backuppb.PlacementPolicy, 0, len(policies)) + for _, policyInfo := range policyList { + p, err := json.Marshal(policyInfo) + if err != nil { + return nil, nil, nil, errors.Trace(err) + } + policies = append(policies, &backuppb.PlacementPolicy{Info: p}) + } + } + ranges := make([]rtree.Range, 0) backupSchemas := newBackupSchemas() dbs, err := m.ListDatabases() if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, nil, errors.Trace(err) } for _, dbInfo := range dbs { @@ -289,7 +325,7 @@ func BuildBackupRangeAndSchema( tables, err := m.ListTables(dbInfo.ID) if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, nil, errors.Trace(err) } if len(tables) == 0 { @@ -298,6 +334,12 @@ func BuildBackupRangeAndSchema( continue } + if !isFullBackup { + // according to https://github.com/pingcap/tidb/issues/32290. + // ignore placement policy when not in full backup + dbInfo.PlacementPolicyRef = nil + } + for _, tableInfo := range tables { if !tableFilter.MatchTable(dbInfo.Name.O, tableInfo.Name.O) { // Skip tables other than the given table. @@ -324,16 +366,21 @@ func BuildBackupRangeAndSchema( globalAutoID, err = idAlloc.NextGlobalAutoID() } if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, nil, errors.Trace(err) } tableInfo.AutoIncID = globalAutoID + if !isFullBackup { + // according to https://github.com/pingcap/tidb/issues/32290. + // ignore placement policy when not in full backup + tableInfo.ClearPlacement() + } if tableInfo.PKIsHandle && tableInfo.ContainsAutoRandomBits() { // this table has auto_random id, we need backup and rebase in restoration var globalAutoRandID int64 globalAutoRandID, err = randAlloc.NextGlobalAutoID() if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, nil, errors.Trace(err) } tableInfo.AutoRandID = globalAutoRandID logger.Debug("change table AutoRandID", @@ -356,7 +403,7 @@ func BuildBackupRangeAndSchema( tableRanges, err := BuildTableRanges(tableInfo) if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, nil, errors.Trace(err) } for _, r := range tableRanges { ranges = append(ranges, rtree.Range{ @@ -369,9 +416,9 @@ func BuildBackupRangeAndSchema( if backupSchemas.Len() == 0 { log.Info("nothing to backup") - return nil, nil, nil + return nil, nil, nil, nil } - return ranges, backupSchemas, nil + return ranges, backupSchemas, policies, nil } func skipUnsupportedDDLJob(job *model.Job) bool { @@ -430,11 +477,22 @@ func WriteBackupDDLJobs(metaWriter *metautil.MetaWriter, store kv.Storage, lastB if (job.State == model.JobStateDone || job.State == model.JobStateSynced) && (job.BinlogInfo != nil && job.BinlogInfo.SchemaVersion > lastSchemaVersion) { + if job.BinlogInfo.DBInfo != nil { + // ignore all placement policy info during incremental backup for now. + job.BinlogInfo.DBInfo.PlacementPolicyRef = nil + } + if job.BinlogInfo.TableInfo != nil { + // ignore all placement policy info during incremental backup for now. + job.BinlogInfo.TableInfo.ClearPlacement() + } jobBytes, err := json.Marshal(job) if err != nil { return errors.Trace(err) } - metaWriter.Send(jobBytes, metautil.AppendDDL) + err = metaWriter.Send(jobBytes, metautil.AppendDDL) + if err != nil { + return errors.Trace(err) + } count++ } } @@ -446,7 +504,7 @@ func WriteBackupDDLJobs(metaWriter *metautil.MetaWriter, store kv.Storage, lastB func (bc *Client) BackupRanges( ctx context.Context, ranges []rtree.Range, - req backuppb.BackupRequest, + request backuppb.BackupRequest, concurrency uint, metaWriter *metautil.MetaWriter, progressCallBack func(ProgressUnit), @@ -465,12 +523,19 @@ func (bc *Client) BackupRanges( eg, ectx := errgroup.WithContext(ctx) for id, r := range ranges { id := id - sk, ek := r.StartKey, r.EndKey + req := request + req.StartKey, req.EndKey = r.StartKey, r.EndKey + workerPool.ApplyOnErrorGroup(eg, func() error { elctx := logutil.ContextWithField(ectx, logutil.RedactAny("range-sn", id)) - err := bc.BackupRange(elctx, sk, ek, req, metaWriter, progressCallBack) + err := bc.BackupRange(elctx, req, metaWriter, progressCallBack) if err != nil { - return errors.Trace(err) + // The error due to context cancel, stack trace is meaningless, the stack shall be suspended (also clear) + if errors.Cause(err) == context.Canceled { + return errors.SuspendStack(err) + } else { + return errors.Trace(err) + } } return nil }) @@ -482,7 +547,6 @@ func (bc *Client) BackupRanges( // Returns an array of files backed up. func (bc *Client) BackupRange( ctx context.Context, - startKey, endKey []byte, req backuppb.BackupRequest, metaWriter *metautil.MetaWriter, progressCallBack func(ProgressUnit), @@ -491,13 +555,13 @@ func (bc *Client) BackupRange( defer func() { elapsed := time.Since(start) logutil.CL(ctx).Info("backup range finished", zap.Duration("take", elapsed)) - key := "range start:" + hex.EncodeToString(startKey) + " end:" + hex.EncodeToString(endKey) + key := "range start:" + hex.EncodeToString(req.StartKey) + " end:" + hex.EncodeToString(req.EndKey) if err != nil { summary.CollectFailureUnit(key, err) } }() logutil.CL(ctx).Info("backup started", - logutil.Key("startKey", startKey), logutil.Key("endKey", endKey), + logutil.Key("startKey", req.StartKey), logutil.Key("endKey", req.EndKey), zap.Uint64("rateLimit", req.RateLimit), zap.Uint32("concurrency", req.Concurrency)) @@ -507,14 +571,8 @@ func (bc *Client) BackupRange( return errors.Trace(err) } - req.StartKey = startKey - req.EndKey = endKey - req.StorageBackend = bc.backend - push := newPushDown(bc.mgr, len(allStores)) - - var results rtree.RangeTree - results, err = push.pushBackup(ctx, req, allStores, progressCallBack) + results, err := push.pushBackup(ctx, req, allStores, progressCallBack) if err != nil { return errors.Trace(err) } @@ -522,10 +580,7 @@ func (bc *Client) BackupRange( // Find and backup remaining ranges. // TODO: test fine grained backup. - err = bc.fineGrainedBackup( - ctx, startKey, endKey, req.StartVersion, req.EndVersion, req.CompressionType, req.CompressionLevel, - req.RateLimit, req.Concurrency, results, progressCallBack) - if err != nil { + if err := bc.fineGrainedBackup(ctx, req, results, progressCallBack); err != nil { return errors.Trace(err) } @@ -534,8 +589,8 @@ func (bc *Client) BackupRange( if req.IsRawKv { logutil.CL(ctx).Info("raw ranges backed up", - logutil.Key("startKey", startKey), - logutil.Key("endKey", endKey), + logutil.Key("startKey", req.StartKey), + logutil.Key("endKey", req.EndKey), zap.String("cf", req.Cf)) } else { logutil.CL(ctx).Info("time range backed up", @@ -568,10 +623,12 @@ func (bc *Client) BackupRange( return nil } -func (bc *Client) findRegionLeader(ctx context.Context, key []byte) (*metapb.Peer, error) { +func (bc *Client) findRegionLeader(ctx context.Context, key []byte, isRawKv bool) (*metapb.Peer, error) { // Keys are saved in encoded format in TiKV, so the key must be encoded // in order to find the correct region. - key = codec.EncodeBytes([]byte{}, key) + if !isRawKv { + key = codec.EncodeBytes([]byte{}, key) + } for i := 0; i < 5; i++ { // better backoff. region, err := bc.mgr.GetPDClient().GetRegion(ctx, key) @@ -595,13 +652,7 @@ func (bc *Client) findRegionLeader(ctx context.Context, key []byte) (*metapb.Pee func (bc *Client) fineGrainedBackup( ctx context.Context, - startKey, endKey []byte, - lastBackupTS uint64, - backupTS uint64, - compressType backuppb.CompressionType, - compressLevel int32, - rateLimit uint64, - concurrency uint32, + req backuppb.BackupRequest, rangeTree rtree.RangeTree, progressCallBack func(ProgressUnit), ) error { @@ -629,7 +680,7 @@ func (bc *Client) fineGrainedBackup( bo := tikv.NewBackoffer(ctx, backupFineGrainedMaxBackoff) for { // Step1, check whether there is any incomplete range - incomplete := rangeTree.GetIncompleteRange(startKey, endKey) + incomplete := rangeTree.GetIncompleteRange(req.StartKey, req.EndKey) if len(incomplete) == 0 { return nil } @@ -650,9 +701,9 @@ func (bc *Client) fineGrainedBackup( go func(boFork *tikv.Backoffer) { defer wg.Done() for rg := range retry { - backoffMs, err := - bc.handleFineGrained(ctx, boFork, rg, lastBackupTS, backupTS, - compressType, compressLevel, rateLimit, concurrency, respCh) + subReq := req + subReq.StartKey, subReq.EndKey = rg.StartKey, rg.EndKey + backoffMs, err := bc.handleFineGrained(ctx, boFork, subReq, respCh) if err != nil { errCh <- err return @@ -698,6 +749,8 @@ func (bc *Client) fineGrainedBackup( logutil.Key("fine-grained-range-end", resp.EndKey), ) rangeTree.Put(resp.StartKey, resp.EndKey, resp.Files) + apiVersion := resp.ApiVersion + bc.SetApiVersion(apiVersion) // Update progress progressCallBack(RegionUnit) @@ -790,33 +843,14 @@ func OnBackupResponse( func (bc *Client) handleFineGrained( ctx context.Context, bo *tikv.Backoffer, - rg rtree.Range, - lastBackupTS uint64, - backupTS uint64, - compressType backuppb.CompressionType, - compressionLevel int32, - rateLimit uint64, - concurrency uint32, + req backuppb.BackupRequest, respCh chan<- *backuppb.BackupResponse, ) (int, error) { - leader, pderr := bc.findRegionLeader(ctx, rg.StartKey) + leader, pderr := bc.findRegionLeader(ctx, req.StartKey, req.IsRawKv) if pderr != nil { return 0, errors.Trace(pderr) } storeID := leader.GetStoreId() - - req := backuppb.BackupRequest{ - ClusterId: bc.clusterID, - StartKey: rg.StartKey, // TODO: the range may cross region. - EndKey: rg.EndKey, - StartVersion: lastBackupTS, - EndVersion: backupTS, - StorageBackend: bc.backend, - RateLimit: rateLimit, - Concurrency: concurrency, - CompressionType: compressType, - CompressionLevel: compressionLevel, - } lockResolver := bc.mgr.GetLockResolver() client, err := bc.mgr.GetBackupClient(ctx, storeID) if err != nil { @@ -837,7 +871,7 @@ func (bc *Client) handleFineGrained( // Handle responses with the same backoffer. func(resp *backuppb.BackupResponse) error { response, shouldBackoff, err1 := - OnBackupResponse(storeID, bo, backupTS, lockResolver, resp) + OnBackupResponse(storeID, bo, req.EndVersion, lockResolver, resp) if err1 != nil { return err1 } @@ -878,6 +912,69 @@ func (bc *Client) handleFineGrained( return backoffMill, nil } +func doSendBackup( + ctx context.Context, + client backuppb.BackupClient, + req backuppb.BackupRequest, + respFn func(*backuppb.BackupResponse) error, +) error { + failpoint.Inject("hint-backup-start", func(v failpoint.Value) { + logutil.CL(ctx).Info("failpoint hint-backup-start injected, " + + "process will notify the shell.") + if sigFile, ok := v.(string); ok { + file, err := os.Create(sigFile) + if err != nil { + log.Warn("failed to create file for notifying, skipping notify", zap.Error(err)) + } + if file != nil { + file.Close() + } + } + time.Sleep(3 * time.Second) + }) + bCli, err := client.Backup(ctx, &req) + failpoint.Inject("reset-retryable-error", func(val failpoint.Value) { + if val.(bool) { + logutil.CL(ctx).Debug("failpoint reset-retryable-error injected.") + err = status.Error(codes.Unavailable, "Unavailable error") + } + }) + failpoint.Inject("reset-not-retryable-error", func(val failpoint.Value) { + if val.(bool) { + logutil.CL(ctx).Debug("failpoint reset-not-retryable-error injected.") + err = status.Error(codes.Unknown, "Your server was haunted hence doesn't work, meow :3") + } + }) + if err != nil { + return err + } + defer func() { + _ = bCli.CloseSend() + }() + + for { + resp, err := bCli.Recv() + if err != nil { + if errors.Cause(err) == io.EOF { // nolint:errorlint + logutil.CL(ctx).Debug("backup streaming finish", + logutil.Key("backup-start-key", req.GetStartKey()), + logutil.Key("backup-end-key", req.GetEndKey())) + return nil + } + return err + } + // TODO: handle errors in the resp. + logutil.CL(ctx).Debug("range backed up", + logutil.Key("small-range-start-key", resp.GetStartKey()), + logutil.Key("small-range-end-key", resp.GetEndKey()), + zap.Int("api-version", int(resp.ApiVersion))) + err = respFn(resp) + if err != nil { + return errors.Trace(err) + } + } +} + // SendBackup send backup request to the given store. // Stop receiving response if respFn returns error. func SendBackup( @@ -899,40 +996,15 @@ func SendBackup( } var errReset error -backupLoop: + var errBackup error + for retry := 0; retry < backupRetryTimes; retry++ { logutil.CL(ctx).Info("try backup", zap.Int("retry time", retry), ) - failpoint.Inject("hint-backup-start", func(v failpoint.Value) { - logutil.CL(ctx).Info("failpoint hint-backup-start injected, " + - "process will notify the shell.") - if sigFile, ok := v.(string); ok { - file, err := os.Create(sigFile) - if err != nil { - log.Warn("failed to create file for notifying, skipping notify", zap.Error(err)) - } - if file != nil { - file.Close() - } - } - time.Sleep(3 * time.Second) - }) - bcli, err := client.Backup(ctx, &req) - failpoint.Inject("reset-retryable-error", func(val failpoint.Value) { - if val.(bool) { - logutil.CL(ctx).Debug("failpoint reset-retryable-error injected.") - err = status.Error(codes.Unavailable, "Unavailable error") - } - }) - failpoint.Inject("reset-not-retryable-error", func(val failpoint.Value) { - if val.(bool) { - logutil.CL(ctx).Debug("failpoint reset-not-retryable-error injected.") - err = status.Error(codes.Unknown, "Your server was haunted hence doesn't work, meow :3") - } - }) - if err != nil { - if isRetryableError(err) { + errBackup = doSendBackup(ctx, client, req, respFn) + if errBackup != nil { + if isRetryableError(errBackup) { time.Sleep(3 * time.Second) client, errReset = resetFn() if errReset != nil { @@ -941,41 +1013,11 @@ backupLoop: } continue } - logutil.CL(ctx).Error("fail to backup", zap.Uint64("StoreID", storeID), - zap.Int("retry time", retry)) - return berrors.ErrFailedToConnect.Wrap(err).GenWithStack("failed to create backup stream to store %d", storeID) - } - defer bcli.CloseSend() - - for { - resp, err := bcli.Recv() - if err != nil { - if errors.Cause(err) == io.EOF { // nolint:errorlint - logutil.CL(ctx).Info("backup streaming finish", - zap.Int("retry-time", retry)) - break backupLoop - } - if isRetryableError(err) { - time.Sleep(3 * time.Second) - // current tikv is unavailable - client, errReset = resetFn() - if errReset != nil { - return errors.Annotatef(errReset, "failed to reset recv connection on store:%d "+ - "please check the tikv status", storeID) - } - break - } - return berrors.ErrFailedToConnect.Wrap(err).GenWithStack("failed to connect to store: %d with retry times:%d", storeID, retry) - } - - // TODO: handle errors in the resp. - logutil.CL(ctx).Info("range backed up", - logutil.Key("small-range-start-key", resp.GetStartKey()), - logutil.Key("small-range-end-key", resp.GetEndKey())) - err = respFn(resp) - if err != nil { - return errors.Trace(err) - } + logutil.CL(ctx).Error("fail to backup", zap.Uint64("StoreID", storeID), zap.Int("retry", retry)) + return berrors.ErrFailedToConnect.Wrap(errBackup).GenWithStack("failed to create backup stream to store %d", storeID) + } else { + // finish backup + break } } return nil diff --git a/br/pkg/backup/client_test.go b/br/pkg/backup/client_test.go index e341f15417f55..19a0d0b78f2ae 100644 --- a/br/pkg/backup/client_test.go +++ b/br/pkg/backup/client_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/golang/protobuf/proto" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/encryptionpb" "github.com/pingcap/kvproto/pkg/errorpb" @@ -23,9 +22,10 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" @@ -44,92 +44,90 @@ type testBackup struct { storage storage.ExternalStorage } -var _ = Suite(&testBackup{}) - -func TestT(t *testing.T) { - TestingT(t) -} - -func (r *testBackup) SetUpSuite(c *C) { - _, _, pdClient, err := testutils.NewMockTiKV("", nil) - c.Assert(err, IsNil) - r.mockPDClient = pdClient - r.ctx, r.cancel = context.WithCancel(context.Background()) +func createBackupSuite(t *testing.T) (s *testBackup, clean func()) { + tikvClient, _, pdClient, err := testutils.NewMockTiKV("", nil) + require.NoError(t, err) + s = new(testBackup) + s.mockPDClient = pdClient + s.ctx, s.cancel = context.WithCancel(context.Background()) mockMgr := &conn.Mgr{PdController: &pdutil.PdController{}} - mockMgr.SetPDClient(r.mockPDClient) + mockMgr.SetPDClient(s.mockPDClient) mockMgr.SetHTTP([]string{"test"}, nil) - r.backupClient, err = backup.NewBackupClient(r.ctx, mockMgr) - c.Assert(err, IsNil) - - r.cluster, err = mock.NewCluster() - c.Assert(err, IsNil) - base := c.MkDir() - r.storage, err = storage.NewLocalStorage(base) - c.Assert(err, IsNil) - //c.Assert(r.cluster.Start(), IsNil) - + s.backupClient, err = backup.NewBackupClient(s.ctx, mockMgr) + require.NoError(t, err) + + s.cluster, err = mock.NewCluster() + require.NoError(t, err) + base := t.TempDir() + s.storage, err = storage.NewLocalStorage(base) + require.NoError(t, err) + require.NoError(t, s.cluster.Start()) + + clean = func() { + mockMgr.Close() + s.cluster.Stop() + tikvClient.Close() + pdClient.Close() + } + return } -func (r *testBackup) resetStorage(c *C) { - var err error - base := c.MkDir() - r.storage, err = storage.NewLocalStorage(base) - c.Assert(err, IsNil) -} +func TestGetTS(t *testing.T) { + s, clean := createBackupSuite(t) + defer clean() -func (r *testBackup) TestGetTS(c *C) { - var ( - err error - // mockPDClient' physical ts and current ts will have deviation - // so make this deviation tolerance 100ms - deviation = 100 - ) + // mockPDClient' physical ts and current ts will have deviation + // so make this deviation tolerance 100ms + deviation := 100 // timeago not work expectedDuration := 0 currentTS := time.Now().UnixNano() / int64(time.Millisecond) - ts, err := r.backupClient.GetTS(r.ctx, 0, 0) - c.Assert(err, IsNil) + ts, err := s.backupClient.GetTS(s.ctx, 0, 0) + require.NoError(t, err) pdTS := oracle.ExtractPhysical(ts) duration := int(currentTS - pdTS) - c.Assert(duration, Greater, expectedDuration-deviation) - c.Assert(duration, Less, expectedDuration+deviation) + require.Greater(t, duration, expectedDuration-deviation) + require.Less(t, duration, expectedDuration+deviation) // timeago = "1.5m" expectedDuration = 90000 currentTS = time.Now().UnixNano() / int64(time.Millisecond) - ts, err = r.backupClient.GetTS(r.ctx, 90*time.Second, 0) - c.Assert(err, IsNil) + ts, err = s.backupClient.GetTS(s.ctx, 90*time.Second, 0) + require.NoError(t, err) pdTS = oracle.ExtractPhysical(ts) duration = int(currentTS - pdTS) - c.Assert(duration, Greater, expectedDuration-deviation) - c.Assert(duration, Less, expectedDuration+deviation) + require.Greater(t, duration, expectedDuration-deviation) + require.Less(t, duration, expectedDuration+deviation) // timeago = "-1m" - _, err = r.backupClient.GetTS(r.ctx, -time.Minute, 0) - c.Assert(err, ErrorMatches, "negative timeago is not allowed.*") + _, err = s.backupClient.GetTS(s.ctx, -time.Minute, 0) + require.Error(t, err) + require.Regexp(t, "negative timeago is not allowed.*", err.Error()) // timeago = "1000000h" overflows - _, err = r.backupClient.GetTS(r.ctx, 1000000*time.Hour, 0) - c.Assert(err, ErrorMatches, ".*backup ts overflow.*") + _, err = s.backupClient.GetTS(s.ctx, 1000000*time.Hour, 0) + require.Error(t, err) + require.Regexp(t, ".*backup ts overflow.*", err.Error()) // timeago = "10h" exceed GCSafePoint - p, l, err := r.mockPDClient.GetTS(r.ctx) - c.Assert(err, IsNil) + p, l, err := s.mockPDClient.GetTS(s.ctx) + require.NoError(t, err) now := oracle.ComposeTS(p, l) - _, err = r.mockPDClient.UpdateGCSafePoint(r.ctx, now) - c.Assert(err, IsNil) - _, err = r.backupClient.GetTS(r.ctx, 10*time.Hour, 0) - c.Assert(err, ErrorMatches, ".*GC safepoint [0-9]+ exceed TS [0-9]+.*") + _, err = s.mockPDClient.UpdateGCSafePoint(s.ctx, now) + require.NoError(t, err) + _, err = s.backupClient.GetTS(s.ctx, 10*time.Hour, 0) + require.Error(t, err) + require.Regexp(t, ".*GC safepoint [0-9]+ exceed TS [0-9]+.*", err.Error()) // timeago and backupts both exists, use backupts backupts := oracle.ComposeTS(p+10, l) - ts, err = r.backupClient.GetTS(r.ctx, time.Minute, backupts) - c.Assert(err, IsNil) - c.Assert(ts, Equals, backupts) + ts, err = s.backupClient.GetTS(s.ctx, time.Minute, backupts) + require.NoError(t, err) + require.Equal(t, backupts, ts) } -func (r *testBackup) TestBuildTableRangeIntHandle(c *C) { +func TestBuildTableRangeIntHandle(t *testing.T) { type Case struct { ids []int64 trs []kv.KeyRange @@ -151,34 +149,34 @@ func (r *testBackup) TestBuildTableRangeIntHandle(c *C) { }}, } for _, cs := range cases { - c.Log(cs) + t.Log(cs) tbl := &model.TableInfo{Partition: &model.PartitionInfo{Enable: true}} for _, id := range cs.ids { tbl.Partition.Definitions = append(tbl.Partition.Definitions, model.PartitionDefinition{ID: id}) } ranges, err := backup.BuildTableRanges(tbl) - c.Assert(err, IsNil) - c.Assert(ranges, DeepEquals, cs.trs) + require.NoError(t, err) + require.Equal(t, cs.trs, ranges) } tbl := &model.TableInfo{ID: 7} ranges, err := backup.BuildTableRanges(tbl) - c.Assert(err, IsNil) - c.Assert(ranges, DeepEquals, []kv.KeyRange{ + require.NoError(t, err) + require.Equal(t, []kv.KeyRange{ {StartKey: tablecodec.EncodeRowKey(7, low), EndKey: tablecodec.EncodeRowKey(7, high)}, - }) + }, ranges) } -func (r *testBackup) TestBuildTableRangeCommonHandle(c *C) { +func TestBuildTableRangeCommonHandle(t *testing.T) { type Case struct { ids []int64 trs []kv.KeyRange } low, err_l := codec.EncodeKey(nil, nil, []types.Datum{types.MinNotNullDatum()}...) - c.Assert(err_l, IsNil) + require.NoError(t, err_l) high, err_h := codec.EncodeKey(nil, nil, []types.Datum{types.MaxValueDatum()}...) - c.Assert(err_h, IsNil) + require.NoError(t, err_h) high = kv.Key(high).PrefixNext() cases := []Case{ {ids: []int64{1}, trs: []kv.KeyRange{ @@ -195,26 +193,26 @@ func (r *testBackup) TestBuildTableRangeCommonHandle(c *C) { }}, } for _, cs := range cases { - c.Log(cs) + t.Log(cs) tbl := &model.TableInfo{Partition: &model.PartitionInfo{Enable: true}, IsCommonHandle: true} for _, id := range cs.ids { tbl.Partition.Definitions = append(tbl.Partition.Definitions, model.PartitionDefinition{ID: id}) } ranges, err := backup.BuildTableRanges(tbl) - c.Assert(err, IsNil) - c.Assert(ranges, DeepEquals, cs.trs) + require.NoError(t, err) + require.Equal(t, cs.trs, ranges) } tbl := &model.TableInfo{ID: 7, IsCommonHandle: true} ranges, err_r := backup.BuildTableRanges(tbl) - c.Assert(err_r, IsNil) - c.Assert(ranges, DeepEquals, []kv.KeyRange{ + require.NoError(t, err_r) + require.Equal(t, []kv.KeyRange{ {StartKey: tablecodec.EncodeRowKey(7, low), EndKey: tablecodec.EncodeRowKey(7, high)}, - }) + }, ranges) } -func (r *testBackup) TestOnBackupRegionErrorResponse(c *C) { +func TestOnBackupRegionErrorResponse(t *testing.T) { type Case struct { storeID uint64 bo *tikv.Backoffer @@ -241,18 +239,21 @@ func (r *testBackup) TestOnBackupRegionErrorResponse(c *C) { {storeID: 1, backupTS: 421123291611137, resp: newBackupRegionErrorResp(&errorpb.Error{ProposalInMergingMode: &errorpb.ProposalInMergingMode{}}), exceptedBackoffMs: 1000, exceptedErr: false}, } for _, cs := range cases { - c.Log(cs) + t.Log(cs) _, backoffMs, err := backup.OnBackupResponse(cs.storeID, cs.bo, cs.backupTS, cs.lockResolver, cs.resp) - c.Assert(backoffMs, Equals, cs.exceptedBackoffMs) + require.Equal(t, cs.exceptedBackoffMs, backoffMs) if cs.exceptedErr { - c.Assert(err, NotNil) + require.Error(t, err) } else { - c.Assert(err, IsNil) + require.NoError(t, err) } } } -func (r *testBackup) TestSendCreds(c *C) { +func TestSendCreds(t *testing.T) { + s, clean := createBackupSuite(t) + defer clean() + accessKey := "ab" secretAccessKey := "cd" backendOpt := storage.BackendOptions{ @@ -262,16 +263,16 @@ func (r *testBackup) TestSendCreds(c *C) { }, } backend, err := storage.ParseBackend("s3://bucket/prefix/", &backendOpt) - c.Assert(err, IsNil) + require.NoError(t, err) opts := &storage.ExternalStorageOptions{ SendCredentials: true, } - _, err = storage.New(r.ctx, backend, opts) - c.Assert(err, IsNil) + _, err = storage.New(s.ctx, backend, opts) + require.NoError(t, err) access_key := backend.GetS3().AccessKey - c.Assert(access_key, Equals, "ab") + require.Equal(t, "ab", access_key) secret_access_key := backend.GetS3().SecretAccessKey - c.Assert(secret_access_key, Equals, "cd") + require.Equal(t, "cd", secret_access_key) backendOpt = storage.BackendOptions{ S3: storage.S3BackendOptions{ @@ -280,24 +281,27 @@ func (r *testBackup) TestSendCreds(c *C) { }, } backend, err = storage.ParseBackend("s3://bucket/prefix/", &backendOpt) - c.Assert(err, IsNil) + require.NoError(t, err) opts = &storage.ExternalStorageOptions{ SendCredentials: false, } - _, err = storage.New(r.ctx, backend, opts) - c.Assert(err, IsNil) + _, err = storage.New(s.ctx, backend, opts) + require.NoError(t, err) access_key = backend.GetS3().AccessKey - c.Assert(access_key, Equals, "") + require.Equal(t, "", access_key) secret_access_key = backend.GetS3().SecretAccessKey - c.Assert(secret_access_key, Equals, "") + require.Equal(t, "", secret_access_key) } -func (r *testBackup) TestskipUnsupportedDDLJob(c *C) { - tk := testkit.NewTestKit(c, r.cluster.Storage) +func TestSkipUnsupportedDDLJob(t *testing.T) { + s, clean := createBackupSuite(t) + defer clean() + + tk := testkit.NewTestKit(t, s.cluster.Storage) tk.MustExec("CREATE DATABASE IF NOT EXISTS test_db;") tk.MustExec("CREATE TABLE IF NOT EXISTS test_db.test_table (c1 INT);") - lastTS, err := r.cluster.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get last ts: %s", err)) + lastTS, err := s.cluster.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) + require.NoErrorf(t, err, "Error get last ts: %s", err) tk.MustExec("RENAME TABLE test_db.test_table to test_db.test_table1;") tk.MustExec("DROP TABLE test_db.test_table1;") tk.MustExec("DROP DATABASE test_db;") @@ -312,58 +316,61 @@ func (r *testBackup) TestskipUnsupportedDDLJob(c *C) { tk.MustExec("ALTER TABLE tb attributes \"merge_option=allow\"") tk.MustExec("ALTER TABLE tb PARTITION p0 attributes \"merge_option=deny\"") - ts, err := r.cluster.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get ts: %s", err)) + ts, err := s.cluster.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) + require.NoErrorf(t, err, "Error get ts: %s", err) cipher := backuppb.CipherInfo{CipherType: encryptionpb.EncryptionMethod_PLAINTEXT} - metaWriter := metautil.NewMetaWriter(r.storage, metautil.MetaFileSize, false, &cipher) + metaWriter := metautil.NewMetaWriter(s.storage, metautil.MetaFileSize, false, &cipher) ctx := context.Background() metaWriter.StartWriteMetasAsync(ctx, metautil.AppendDDL) - err = backup.WriteBackupDDLJobs(metaWriter, r.cluster.Storage, lastTS, ts) - c.Assert(err, IsNil, Commentf("Error get ddl jobs: %s", err)) + err = backup.WriteBackupDDLJobs(metaWriter, s.cluster.Storage, lastTS, ts) + require.NoErrorf(t, err, "Error get ddl jobs: %s", err) err = metaWriter.FinishWriteMetas(ctx, metautil.AppendDDL) - c.Assert(err, IsNil, Commentf("Flush failed", err)) + require.NoError(t, err, "Flush failed", err) err = metaWriter.FlushBackupMeta(ctx) - c.Assert(err, IsNil, Commentf("Finially flush backupmeta failed", err)) + require.NoError(t, err, "Finally flush backup meta failed", err) - metaBytes, err := r.storage.ReadFile(ctx, metautil.MetaFile) - c.Assert(err, IsNil) + metaBytes, err := s.storage.ReadFile(ctx, metautil.MetaFile) + require.NoError(t, err) mockMeta := &backuppb.BackupMeta{} err = proto.Unmarshal(metaBytes, mockMeta) - c.Assert(err, IsNil) + require.NoError(t, err) // check the schema version - metaReader := metautil.NewMetaReader(mockMeta, r.storage, &cipher) + metaReader := metautil.NewMetaReader(mockMeta, s.storage, &cipher) allDDLJobsBytes, err := metaReader.ReadDDLs(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) var allDDLJobs []*model.Job err = json.Unmarshal(allDDLJobsBytes, &allDDLJobs) - c.Assert(err, IsNil) - c.Assert(len(allDDLJobs), Equals, 8) + require.NoError(t, err) + require.Len(t, allDDLJobs, 8) } -func (r *testBackup) TestCheckBackupIsLocked(c *C) { +func TestCheckBackupIsLocked(t *testing.T) { + s, clean := createBackupSuite(t) + defer clean() + ctx := context.Background() - r.resetStorage(c) // check passed with an empty storage - err := backup.CheckBackupStorageIsLocked(ctx, r.storage) - c.Assert(err, IsNil) + err := backup.CheckBackupStorageIsLocked(ctx, s.storage) + require.NoError(t, err) // check passed with only a lock file - err = r.storage.WriteFile(ctx, metautil.LockFile, nil) - c.Assert(err, IsNil) - err = backup.CheckBackupStorageIsLocked(ctx, r.storage) - c.Assert(err, IsNil) + err = s.storage.WriteFile(ctx, metautil.LockFile, nil) + require.NoError(t, err) + err = backup.CheckBackupStorageIsLocked(ctx, s.storage) + require.NoError(t, err) // check passed with a lock file and other non-sst files. - err = r.storage.WriteFile(ctx, "1.txt", nil) - c.Assert(err, IsNil) - err = backup.CheckBackupStorageIsLocked(ctx, r.storage) - c.Assert(err, IsNil) + err = s.storage.WriteFile(ctx, "1.txt", nil) + require.NoError(t, err) + err = backup.CheckBackupStorageIsLocked(ctx, s.storage) + require.NoError(t, err) // check failed - err = r.storage.WriteFile(ctx, "1.sst", nil) - c.Assert(err, IsNil) - err = backup.CheckBackupStorageIsLocked(ctx, r.storage) - c.Assert(err, ErrorMatches, "backup lock file and sst file exist in(.+)") + err = s.storage.WriteFile(ctx, "1.sst", nil) + require.NoError(t, err) + err = backup.CheckBackupStorageIsLocked(ctx, s.storage) + require.Error(t, err) + require.Regexp(t, "backup lock file and sst file exist in(.+)", err.Error()) } diff --git a/br/pkg/backup/main_test.go b/br/pkg/backup/main_test.go new file mode 100644 index 0000000000000..e47b44847e9f7 --- /dev/null +++ b/br/pkg/backup/main_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package backup + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), + goleak.IgnoreTopFunction("github.com/pingcap/goleveldb/leveldb.(*DB).mpoolDrain"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) +} diff --git a/br/pkg/backup/push.go b/br/pkg/backup/push.go index c365eaaa96921..3fd3aeb8adfed 100644 --- a/br/pkg/backup/push.go +++ b/br/pkg/backup/push.go @@ -11,6 +11,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/pingcap/kvproto/pkg/errorpb" "github.com/pingcap/kvproto/pkg/metapb" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/logutil" @@ -41,11 +42,11 @@ func (r responseAndStore) GetStore() *metapb.Store { } // newPushDown creates a push down backup. -func newPushDown(mgr ClientMgr, cap int) *pushDown { +func newPushDown(mgr ClientMgr, capacity int) *pushDown { return &pushDown{ mgr: mgr, - respCh: make(chan responseAndStore, cap), - errCh: make(chan error, cap), + respCh: make(chan responseAndStore, capacity), + errCh: make(chan error, capacity), } } @@ -116,6 +117,7 @@ func (push *pushDown) pushBackup( close(push.respCh) }() + regionErrorIngestedOnce := false for { select { case respAndStore, ok := <-push.respCh: @@ -139,6 +141,21 @@ func (push *pushDown) pushBackup( Msg: msg, } }) + failpoint.Inject("tikv-region-error", func(val failpoint.Value) { + if !regionErrorIngestedOnce { + msg := val.(string) + logutil.CL(ctx).Debug("failpoint tikv-regionh-error injected.", zap.String("msg", msg)) + resp.Error = &backuppb.Error{ + // Msg: msg, + Detail: &backuppb.Error_RegionError{ + RegionError: &errorpb.Error{ + Message: msg, + }, + }, + } + } + regionErrorIngestedOnce = true + }) if resp.GetError() == nil { // None error means range has been backuped successfully. res.Put( @@ -163,20 +180,28 @@ func (push *pushDown) pushBackup( logutil.CL(ctx).Warn("backup occur storage error", zap.String("error", errPb.GetMsg())) continue } + var errMsg string if utils.MessageIsNotFoundStorageError(errPb.GetMsg()) { - errMsg := fmt.Sprintf("File or directory not found error occurs on TiKV Node(store id: %v; Address: %s)", store.GetId(), redact.String(store.GetAddress())) - logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg), - zap.String("work around", "please ensure br and tikv node share a same disk and the user of br and tikv has same uid.")) + errMsg = fmt.Sprintf("File or directory not found on TiKV Node (store id: %v; Address: %s). "+ + "work around:please ensure br and tikv nodes share a same storage and the user of br and tikv has same uid.", + store.GetId(), redact.String(store.GetAddress())) + logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg)) } if utils.MessageIsPermissionDeniedStorageError(errPb.GetMsg()) { - errMsg := fmt.Sprintf("I/O permission denied error occurs on TiKV Node(store id: %v; Address: %s)", store.GetId(), redact.String(store.GetAddress())) - logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg), - zap.String("work around", "please ensure tikv has permission to read from & write to the storage.")) + errMsg = fmt.Sprintf("I/O permission denied error occurs on TiKV Node(store id: %v; Address: %s). "+ + "work around:please ensure tikv has permission to read from & write to the storage.", + store.GetId(), redact.String(store.GetAddress())) + logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg)) + } + + if len(errMsg) <= 0 { + errMsg = errPb.Msg } - return res, errors.Annotatef(berrors.ErrKVStorage, "error happen in store %v at %s: %s", + return res, errors.Annotatef(berrors.ErrKVStorage, "error happen in store %v at %s: %s %s", store.GetId(), redact.String(store.GetAddress()), - errPb.Msg, + req.StorageBackend.String(), + errMsg, ) } } diff --git a/br/pkg/backup/schema_test.go b/br/pkg/backup/schema_test.go index c858d556f98d0..303eb318b2ed3 100644 --- a/br/pkg/backup/schema_test.go +++ b/br/pkg/backup/schema_test.go @@ -8,54 +8,47 @@ import ( "math" "strings" "sync/atomic" + "testing" "github.com/golang/protobuf/proto" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/encryptionpb" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" "github.com/pingcap/tidb/br/pkg/backup" "github.com/pingcap/tidb/br/pkg/metautil" "github.com/pingcap/tidb/br/pkg/mock" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" + "github.com/pingcap/tidb/testkit" + filter "github.com/pingcap/tidb/util/table-filter" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testBackupSchemaSuite{}) - -type testBackupSchemaSuite struct { - mock *mock.Cluster -} - -func (s *testBackupSchemaSuite) SetUpSuite(c *C) { +func createMockCluster(t *testing.T) (m *mock.Cluster, clean func()) { var err error - s.mock, err = mock.NewCluster() - c.Assert(err, IsNil) - c.Assert(s.mock.Start(), IsNil) -} - -func (s *testBackupSchemaSuite) TearDownSuite(c *C) { - s.mock.Stop() - testleak.AfterTest(c)() + m, err = mock.NewCluster() + require.NoError(t, err) + require.NoError(t, m.Start()) + clean = func() { + m.Stop() + } + return } -func (s *testBackupSchemaSuite) GetRandomStorage(c *C) storage.ExternalStorage { - base := c.MkDir() +func GetRandomStorage(t *testing.T) storage.ExternalStorage { + base := t.TempDir() es, err := storage.NewLocalStorage(base) - c.Assert(err, IsNil) + require.NoError(t, err) return es } -func (s *testBackupSchemaSuite) GetSchemasFromMeta(c *C, es storage.ExternalStorage) []*metautil.Table { +func GetSchemasFromMeta(t *testing.T, es storage.ExternalStorage) []*metautil.Table { ctx := context.Background() metaBytes, err := es.ReadFile(ctx, metautil.MetaFile) - c.Assert(err, IsNil) + require.NoError(t, err) mockMeta := &backuppb.BackupMeta{} err = proto.Unmarshal(metaBytes, mockMeta) - c.Assert(err, IsNil) + require.NoError(t, err) metaReader := metautil.NewMetaReader(mockMeta, es, &backuppb.CipherInfo{ @@ -66,7 +59,7 @@ func (s *testBackupSchemaSuite) GetSchemasFromMeta(c *C, es storage.ExternalStor output := make(chan *metautil.Table, 4) go func() { err = metaReader.ReadSchemasFiles(ctx, output) - c.Assert(err, IsNil) + require.NoError(t, err) close(output) }() @@ -95,99 +88,111 @@ func (sp *simpleProgress) get() int64 { return atomic.LoadInt64(&sp.counter) } -func (s *testBackupSchemaSuite) TestBuildBackupRangeAndSchema(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) +func TestBuildBackupRangeAndSchema(t *testing.T) { + m, clean := createMockCluster(t) + defer clean() + + tk := testkit.NewTestKit(t, m.Storage) // Table t1 is not exist. testFilter, err := filter.Parse([]string{"test.t1"}) - c.Assert(err, IsNil) - _, backupSchemas, err := backup.BuildBackupRangeAndSchema( - s.mock.Storage, testFilter, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas, IsNil) + require.NoError(t, err) + _, backupSchemas, _, err := backup.BuildBackupRangeAndSchema( + m.Storage, testFilter, math.MaxUint64, false) + require.NoError(t, err) + require.Nil(t, backupSchemas) // Database is not exist. fooFilter, err := filter.Parse([]string{"foo.t1"}) - c.Assert(err, IsNil) - _, backupSchemas, err = backup.BuildBackupRangeAndSchema( - s.mock.Storage, fooFilter, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas, IsNil) + require.NoError(t, err) + _, backupSchemas, _, err = backup.BuildBackupRangeAndSchema( + m.Storage, fooFilter, math.MaxUint64, false) + require.NoError(t, err) + require.Nil(t, backupSchemas) // Empty database. // Filter out system tables manually. noFilter, err := filter.Parse([]string{"*.*", "!mysql.*"}) - c.Assert(err, IsNil) - _, backupSchemas, err = backup.BuildBackupRangeAndSchema( - s.mock.Storage, noFilter, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas, IsNil) + require.NoError(t, err) + _, backupSchemas, _, err = backup.BuildBackupRangeAndSchema( + m.Storage, noFilter, math.MaxUint64, false) + require.NoError(t, err) + require.Nil(t, backupSchemas) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1 (a int);") tk.MustExec("insert into t1 values (10);") - - _, backupSchemas, err = backup.BuildBackupRangeAndSchema( - s.mock.Storage, testFilter, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas.Len(), Equals, 1) + tk.MustExec("create placement policy fivereplicas followers=4;") + + var policies []*backuppb.PlacementPolicy + _, backupSchemas, policies, err = backup.BuildBackupRangeAndSchema( + m.Storage, testFilter, math.MaxUint64, false) + require.NoError(t, err) + require.Equal(t, 1, backupSchemas.Len()) + // we expect no policies collected, because it's not full backup. + require.Equal(t, 0, len(policies)) updateCh := new(simpleProgress) skipChecksum := false - es := s.GetRandomStorage(c) + es := GetRandomStorage(t) cipher := backuppb.CipherInfo{ CipherType: encryptionpb.EncryptionMethod_PLAINTEXT, } metaWriter := metautil.NewMetaWriter(es, metautil.MetaFileSize, false, &cipher) ctx := context.Background() err = backupSchemas.BackupSchemas( - ctx, metaWriter, s.mock.Storage, nil, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) - c.Assert(updateCh.get(), Equals, int64(1)) - c.Assert(err, IsNil) + ctx, metaWriter, m.Storage, nil, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) + require.Equal(t, int64(1), updateCh.get()) + require.NoError(t, err) err = metaWriter.FlushBackupMeta(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - schemas := s.GetSchemasFromMeta(c, es) - c.Assert(len(schemas), Equals, 1) + schemas := GetSchemasFromMeta(t, es) + require.Len(t, schemas, 1) // Cluster returns a dummy checksum (all fields are 1). - c.Assert(schemas[0].Crc64Xor, Not(Equals), 0, Commentf("%v", schemas[0])) - c.Assert(schemas[0].TotalKvs, Not(Equals), 0, Commentf("%v", schemas[0])) - c.Assert(schemas[0].TotalBytes, Not(Equals), 0, Commentf("%v", schemas[0])) + require.NotZerof(t, schemas[0].Crc64Xor, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalKvs, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalBytes, "%v", schemas[0]) tk.MustExec("drop table if exists t2;") tk.MustExec("create table t2 (a int);") tk.MustExec("insert into t2 values (10);") tk.MustExec("insert into t2 values (11);") - _, backupSchemas, err = backup.BuildBackupRangeAndSchema( - s.mock.Storage, noFilter, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas.Len(), Equals, 2) + _, backupSchemas, policies, err = backup.BuildBackupRangeAndSchema( + m.Storage, noFilter, math.MaxUint64, true) + require.NoError(t, err) + require.Equal(t, 2, backupSchemas.Len()) + // we expect the policy fivereplicas collected in full backup. + require.Equal(t, 1, len(policies)) updateCh.reset() - es2 := s.GetRandomStorage(c) + es2 := GetRandomStorage(t) metaWriter2 := metautil.NewMetaWriter(es2, metautil.MetaFileSize, false, &cipher) err = backupSchemas.BackupSchemas( - ctx, metaWriter2, s.mock.Storage, nil, math.MaxUint64, 2, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) - c.Assert(updateCh.get(), Equals, int64(2)) - c.Assert(err, IsNil) + ctx, metaWriter2, m.Storage, nil, math.MaxUint64, 2, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) + require.Equal(t, int64(2), updateCh.get()) + require.NoError(t, err) err = metaWriter2.FlushBackupMeta(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - schemas = s.GetSchemasFromMeta(c, es2) + schemas = GetSchemasFromMeta(t, es2) - c.Assert(len(schemas), Equals, 2) + require.Len(t, schemas, 2) // Cluster returns a dummy checksum (all fields are 1). - c.Assert(schemas[0].Crc64Xor, Not(Equals), 0, Commentf("%v", schemas[0])) - c.Assert(schemas[0].TotalKvs, Not(Equals), 0, Commentf("%v", schemas[0])) - c.Assert(schemas[0].TotalBytes, Not(Equals), 0, Commentf("%v", schemas[0])) - c.Assert(schemas[1].Crc64Xor, Not(Equals), 0, Commentf("%v", schemas[1])) - c.Assert(schemas[1].TotalKvs, Not(Equals), 0, Commentf("%v", schemas[1])) - c.Assert(schemas[1].TotalBytes, Not(Equals), 0, Commentf("%v", schemas[1])) + require.NotZerof(t, schemas[0].Crc64Xor, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalKvs, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalBytes, "%v", schemas[0]) + require.NotZerof(t, schemas[1].Crc64Xor, "%v", schemas[1]) + require.NotZerof(t, schemas[1].TotalKvs, "%v", schemas[1]) + require.NotZerof(t, schemas[1].TotalBytes, "%v", schemas[1]) } -func (s *testBackupSchemaSuite) TestBuildBackupRangeAndSchemaWithBrokenStats(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) +func TestBuildBackupRangeAndSchemaWithBrokenStats(t *testing.T) { + m, clean := createMockCluster(t) + defer clean() + + tk := testkit.NewTestKit(t, m.Storage) tk.MustExec("use test") tk.MustExec("drop table if exists t3;") tk.MustExec("create table t3 (a char(1));") @@ -203,11 +208,11 @@ func (s *testBackupSchemaSuite) TestBuildBackupRangeAndSchemaWithBrokenStats(c * `) f, err := filter.Parse([]string{"test.t3"}) - c.Assert(err, IsNil) + require.NoError(t, err) - _, backupSchemas, err := backup.BuildBackupRangeAndSchema(s.mock.Storage, f, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas.Len(), Equals, 1) + _, backupSchemas, _, err := backup.BuildBackupRangeAndSchema(m.Storage, f, math.MaxUint64, false) + require.NoError(t, err) + require.Equal(t, 1, backupSchemas.Len()) skipChecksum := false updateCh := new(simpleProgress) @@ -216,57 +221,60 @@ func (s *testBackupSchemaSuite) TestBuildBackupRangeAndSchemaWithBrokenStats(c * CipherType: encryptionpb.EncryptionMethod_PLAINTEXT, } - es := s.GetRandomStorage(c) + es := GetRandomStorage(t) metaWriter := metautil.NewMetaWriter(es, metautil.MetaFileSize, false, &cipher) ctx := context.Background() err = backupSchemas.BackupSchemas( - ctx, metaWriter, s.mock.Storage, nil, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) - c.Assert(err, IsNil) + ctx, metaWriter, m.Storage, nil, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) + require.NoError(t, err) err = metaWriter.FlushBackupMeta(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - schemas := s.GetSchemasFromMeta(c, es) - c.Assert(err, IsNil) - c.Assert(schemas, HasLen, 1) + schemas := GetSchemasFromMeta(t, es) + require.NoError(t, err) + require.Len(t, schemas, 1) // the stats should be empty, but other than that everything should be backed up. - c.Assert(schemas[0].Stats, IsNil) - c.Assert(schemas[0].Crc64Xor, Not(Equals), 0) - c.Assert(schemas[0].TotalKvs, Not(Equals), 0) - c.Assert(schemas[0].TotalBytes, Not(Equals), 0) - c.Assert(schemas[0].Info, NotNil) - c.Assert(schemas[0].DB, NotNil) + require.Nil(t, schemas[0].Stats) + require.NotZerof(t, schemas[0].Crc64Xor, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalKvs, "%v", schemas[0]) + require.NotZerof(t, schemas[0].TotalBytes, "%v", schemas[0]) + require.NotNil(t, schemas[0].Info) + require.NotNil(t, schemas[0].DB) // recover the statistics. tk.MustExec("analyze table t3;") - _, backupSchemas, err = backup.BuildBackupRangeAndSchema(s.mock.Storage, f, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas.Len(), Equals, 1) + _, backupSchemas, _, err = backup.BuildBackupRangeAndSchema(m.Storage, f, math.MaxUint64, false) + require.NoError(t, err) + require.Equal(t, 1, backupSchemas.Len()) updateCh.reset() - statsHandle := s.mock.Domain.StatsHandle() - es2 := s.GetRandomStorage(c) + statsHandle := m.Domain.StatsHandle() + es2 := GetRandomStorage(t) metaWriter2 := metautil.NewMetaWriter(es2, metautil.MetaFileSize, false, &cipher) err = backupSchemas.BackupSchemas( - ctx, metaWriter2, s.mock.Storage, statsHandle, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) - c.Assert(err, IsNil) + ctx, metaWriter2, m.Storage, statsHandle, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, skipChecksum, updateCh) + require.NoError(t, err) err = metaWriter2.FlushBackupMeta(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - schemas2 := s.GetSchemasFromMeta(c, es2) - c.Assert(schemas2, HasLen, 1) + schemas2 := GetSchemasFromMeta(t, es2) + require.Len(t, schemas2, 1) // the stats should now be filled, and other than that the result should be equivalent to the first backup. - c.Assert(schemas2[0].Stats, NotNil) - c.Assert(schemas2[0].Crc64Xor, Equals, schemas[0].Crc64Xor) - c.Assert(schemas2[0].TotalKvs, Equals, schemas[0].TotalKvs) - c.Assert(schemas2[0].TotalBytes, Equals, schemas[0].TotalBytes) - c.Assert(schemas2[0].Info, DeepEquals, schemas[0].Info) - c.Assert(schemas2[0].DB, DeepEquals, schemas[0].DB) + require.NotNil(t, schemas2[0].Stats) + require.Equal(t, schemas[0].Crc64Xor, schemas2[0].Crc64Xor) + require.Equal(t, schemas[0].TotalKvs, schemas2[0].TotalKvs) + require.Equal(t, schemas[0].TotalBytes, schemas2[0].TotalBytes) + require.Equal(t, schemas[0].Info, schemas2[0].Info) + require.Equal(t, schemas[0].DB, schemas2[0].DB) } -func (s *testBackupSchemaSuite) TestBackupSchemasForSystemTable(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) - es2 := s.GetRandomStorage(c) +func TestBackupSchemasForSystemTable(t *testing.T) { + m, clean := createMockCluster(t) + defer clean() + + tk := testkit.NewTestKit(t, m.Storage) + es2 := GetRandomStorage(t) systemTablesCount := 32 tablePrefix := "systable" @@ -277,10 +285,10 @@ func (s *testBackupSchemaSuite) TestBackupSchemasForSystemTable(c *C) { } f, err := filter.Parse([]string{"mysql.systable*"}) - c.Assert(err, IsNil) - _, backupSchemas, err := backup.BuildBackupRangeAndSchema(s.mock.Storage, f, math.MaxUint64) - c.Assert(err, IsNil) - c.Assert(backupSchemas.Len(), Equals, systemTablesCount) + require.NoError(t, err) + _, backupSchemas, _, err := backup.BuildBackupRangeAndSchema(m.Storage, f, math.MaxUint64, false) + require.NoError(t, err) + require.Equal(t, systemTablesCount, backupSchemas.Len()) ctx := context.Background() cipher := backuppb.CipherInfo{ @@ -289,16 +297,16 @@ func (s *testBackupSchemaSuite) TestBackupSchemasForSystemTable(c *C) { updateCh := new(simpleProgress) metaWriter2 := metautil.NewMetaWriter(es2, metautil.MetaFileSize, false, &cipher) - err = backupSchemas.BackupSchemas(ctx, metaWriter2, s.mock.Storage, nil, + err = backupSchemas.BackupSchemas(ctx, metaWriter2, m.Storage, nil, math.MaxUint64, 1, variable.DefChecksumTableConcurrency, true, updateCh) - c.Assert(err, IsNil) + require.NoError(t, err) err = metaWriter2.FlushBackupMeta(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - schemas2 := s.GetSchemasFromMeta(c, es2) - c.Assert(schemas2, HasLen, systemTablesCount) + schemas2 := GetSchemasFromMeta(t, es2) + require.Len(t, schemas2, systemTablesCount) for _, schema := range schemas2 { - c.Assert(schema.DB.Name, Equals, utils.TemporaryDBName("mysql")) - c.Assert(strings.HasPrefix(schema.Info.Name.O, tablePrefix), Equals, true) + require.Equal(t, utils.TemporaryDBName("mysql"), schema.DB.Name) + require.Equal(t, true, strings.HasPrefix(schema.Info.Name.O, tablePrefix)) } } diff --git a/br/pkg/checksum/executor_test.go b/br/pkg/checksum/executor_test.go index 9bab165f6ab46..adcaed9c314f9 100644 --- a/br/pkg/checksum/executor_test.go +++ b/br/pkg/checksum/executor_test.go @@ -7,7 +7,6 @@ import ( "math" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/backup" "github.com/pingcap/tidb/br/pkg/checksum" "github.com/pingcap/tidb/br/pkg/metautil" @@ -15,116 +14,98 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func TestT(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&testChecksumSuite{}) - -type testChecksumSuite struct { - mock *mock.Cluster -} - -func (s *testChecksumSuite) SetUpSuite(c *C) { - var err error - s.mock, err = mock.NewCluster() - c.Assert(err, IsNil) -} - -func (s *testChecksumSuite) TearDownSuite(c *C) { - testleak.AfterTest(c)() -} - -func (s *testChecksumSuite) getTableInfo(c *C, db, table string) *model.TableInfo { - info, err := s.mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) - c.Assert(err, IsNil) +func getTableInfo(t *testing.T, mock *mock.Cluster, db, table string) *model.TableInfo { + info, err := mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) + require.NoError(t, err) cDBName := model.NewCIStr(db) cTableName := model.NewCIStr(table) tableInfo, err := info.TableByName(cDBName, cTableName) - c.Assert(err, IsNil) + require.NoError(t, err) return tableInfo.Meta() } -func (s *testChecksumSuite) TestChecksum(c *C) { - c.Assert(s.mock.Start(), IsNil) - defer s.mock.Stop() +func TestChecksum(t *testing.T) { + mock, err := mock.NewCluster() + require.NoError(t, err) + require.NoError(t, mock.Start()) + defer mock.Stop() - tk := testkit.NewTestKit(c, s.mock.Storage) + tk := testkit.NewTestKit(t, mock.Storage) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1 (a int);") tk.MustExec("insert into t1 values (10);") - tableInfo1 := s.getTableInfo(c, "test", "t1") + tableInfo1 := getTableInfo(t, mock, "test", "t1") exe1, err := checksum.NewExecutorBuilder(tableInfo1, math.MaxUint64). SetConcurrency(variable.DefChecksumTableConcurrency). Build() - c.Assert(err, IsNil) - c.Assert(exe1.Each(func(r *kv.Request) error { - c.Assert(r.NotFillCache, IsTrue) - c.Assert(r.Concurrency, Equals, variable.DefChecksumTableConcurrency) + require.NoError(t, err) + require.NoError(t, exe1.Each(func(r *kv.Request) error { + require.True(t, r.NotFillCache) + require.Equal(t, variable.DefChecksumTableConcurrency, r.Concurrency) return nil - }), IsNil) - c.Assert(exe1.Len(), Equals, 1) - resp, err := exe1.Execute(context.TODO(), s.mock.Storage.GetClient(), func() {}) - c.Assert(err, IsNil) + })) + require.Equal(t, 1, exe1.Len()) + resp, err := exe1.Execute(context.TODO(), mock.Storage.GetClient(), func() {}) + require.NoError(t, err) // Cluster returns a dummy checksum (all fields are 1). - c.Assert(resp.Checksum, Equals, uint64(1), Commentf("%v", resp)) - c.Assert(resp.TotalKvs, Equals, uint64(1), Commentf("%v", resp)) - c.Assert(resp.TotalBytes, Equals, uint64(1), Commentf("%v", resp)) + require.Equalf(t, uint64(1), resp.Checksum, "%v", resp) + require.Equalf(t, uint64(1), resp.TotalKvs, "%v", resp) + require.Equalf(t, uint64(1), resp.TotalBytes, "%v", resp) tk.MustExec("drop table if exists t2;") tk.MustExec("create table t2 (a int);") tk.MustExec("alter table t2 add index i2(a);") tk.MustExec("insert into t2 values (10);") - tableInfo2 := s.getTableInfo(c, "test", "t2") + tableInfo2 := getTableInfo(t, mock, "test", "t2") exe2, err := checksum.NewExecutorBuilder(tableInfo2, math.MaxUint64).Build() - c.Assert(err, IsNil) - c.Assert(exe2.Len(), Equals, 2, Commentf("%v", tableInfo2)) - resp2, err := exe2.Execute(context.TODO(), s.mock.Storage.GetClient(), func() {}) - c.Assert(err, IsNil) - c.Assert(resp2.Checksum, Equals, uint64(0), Commentf("%v", resp2)) - c.Assert(resp2.TotalKvs, Equals, uint64(2), Commentf("%v", resp2)) - c.Assert(resp2.TotalBytes, Equals, uint64(2), Commentf("%v", resp2)) + require.NoError(t, err) + require.Equalf(t, 2, exe2.Len(), "%v", tableInfo2) + resp2, err := exe2.Execute(context.TODO(), mock.Storage.GetClient(), func() {}) + require.NoError(t, err) + require.Equalf(t, uint64(0), resp2.Checksum, "%v", resp2) + require.Equalf(t, uint64(2), resp2.TotalKvs, "%v", resp2) + require.Equalf(t, uint64(2), resp2.TotalBytes, "%v", resp2) // Test rewrite rules tk.MustExec("alter table t1 add index i2(a);") - tableInfo1 = s.getTableInfo(c, "test", "t1") + tableInfo1 = getTableInfo(t, mock, "test", "t1") oldTable := metautil.Table{Info: tableInfo1} exe2, err = checksum.NewExecutorBuilder(tableInfo2, math.MaxUint64). SetOldTable(&oldTable).Build() - c.Assert(err, IsNil) - c.Assert(exe2.Len(), Equals, 2) + require.NoError(t, err) + require.Equal(t, 2, exe2.Len()) rawReqs, err := exe2.RawRequests() - c.Assert(err, IsNil) - c.Assert(rawReqs, HasLen, 2) + require.NoError(t, err) + require.Len(t, rawReqs, 2) for _, rawReq := range rawReqs { - c.Assert(rawReq.Rule, NotNil) + require.NotNil(t, rawReq.Rule) } - resp2, err = exe2.Execute(context.TODO(), s.mock.Storage.GetClient(), func() {}) - c.Assert(err, IsNil) - c.Assert(resp2, NotNil) + resp2, err = exe2.Execute(context.TODO(), mock.Storage.GetClient(), func() {}) + require.NoError(t, err) + require.NotNil(t, resp2) // Test commonHandle ranges tk.MustExec("drop table if exists t3;") tk.MustExec("create table t3 (a char(255), b int, primary key(a) CLUSTERED);") tk.MustExec("insert into t3 values ('fffffffff', 1), ('010101010', 2), ('394393fj39efefe', 3);") - tableInfo3 := s.getTableInfo(c, "test", "t3") + tableInfo3 := getTableInfo(t, mock, "test", "t3") exe3, err := checksum.NewExecutorBuilder(tableInfo3, math.MaxUint64).Build() - c.Assert(err, IsNil) + require.NoError(t, err) first := true - c.Assert(exe3.Each(func(req *kv.Request) error { + require.NoError(t, exe3.Each(func(req *kv.Request) error { if first { first = false ranges, err := backup.BuildTableRanges(tableInfo3) - c.Assert(err, IsNil) - c.Assert(req.KeyRanges, DeepEquals, ranges[:1], Commentf("%v", req.KeyRanges)) + require.NoError(t, err) + require.Equalf(t, ranges[:1], req.KeyRanges, "%v", req.KeyRanges) } return nil - }), IsNil) + })) } diff --git a/br/pkg/checksum/main_test.go b/br/pkg/checksum/main_test.go new file mode 100644 index 0000000000000..801f0a62c4f06 --- /dev/null +++ b/br/pkg/checksum/main_test.go @@ -0,0 +1,33 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package checksum + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + testbridge.SetupForCommonTest() + goleak.VerifyTestMain(m, opts...) +} diff --git a/br/pkg/conn/conn.go b/br/pkg/conn/conn.go index 67db05219e510..9ddba2a7ed3cc 100755 --- a/br/pkg/conn/conn.go +++ b/br/pkg/conn/conn.go @@ -90,10 +90,10 @@ func (p *Pool) Get(ctx context.Context) (*grpc.ClientConn, error) { } // NewConnPool creates a new Pool by the specified conn factory function and capacity. -func NewConnPool(cap int, newConn func(ctx context.Context) (*grpc.ClientConn, error)) *Pool { +func NewConnPool(capacity int, newConn func(ctx context.Context) (*grpc.ClientConn, error)) *Pool { return &Pool{ - cap: cap, - conns: make([]*grpc.ClientConn, 0, cap), + cap: capacity, + conns: make([]*grpc.ClientConn, 0, capacity), newConn: newConn, mu: sync.Mutex{}, diff --git a/br/pkg/conn/main_test.go b/br/pkg/conn/main_test.go index b1299da7358de..512c52a3fc985 100644 --- a/br/pkg/conn/main_test.go +++ b/br/pkg/conn/main_test.go @@ -23,9 +23,10 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/glue/glue.go b/br/pkg/glue/glue.go index 7f2be30a60d34..24b0852d31290 100644 --- a/br/pkg/glue/glue.go +++ b/br/pkg/glue/glue.go @@ -36,7 +36,14 @@ type Session interface { ExecuteInternal(ctx context.Context, sql string, args ...interface{}) error CreateDatabase(ctx context.Context, schema *model.DBInfo) error CreateTable(ctx context.Context, dbName model.CIStr, table *model.TableInfo) error + CreatePlacementPolicy(ctx context.Context, policy *model.PolicyInfo) error Close() + GetGlobalVariable(name string) (string, error) +} + +// BatchCreateTableSession is an interface to batch create table parallelly +type BatchCreateTableSession interface { + CreateTables(ctx context.Context, tables map[string][]*model.TableInfo) error } // Progress is an interface recording the current execution progress. diff --git a/br/pkg/gluetidb/glue.go b/br/pkg/gluetidb/glue.go index c2cb64d21328a..d17a098613648 100644 --- a/br/pkg/gluetidb/glue.go +++ b/br/pkg/gluetidb/glue.go @@ -5,6 +5,7 @@ package gluetidb import ( "bytes" "context" + "strings" "github.com/pingcap/errors" "github.com/pingcap/log" @@ -21,6 +22,7 @@ import ( "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" pd "github.com/tikv/pd/client" + "go.uber.org/zap" ) const ( @@ -125,7 +127,57 @@ func (gs *tidbSession) CreateDatabase(ctx context.Context, schema *model.DBInfo) if len(schema.Charset) == 0 { schema.Charset = mysql.DefaultCharset } - return d.CreateSchemaWithInfo(gs.se, schema, ddl.OnExistIgnore, true) + return d.CreateSchemaWithInfo(gs.se, schema, ddl.OnExistIgnore) + +} + +// CreatePlacementPolicy implements glue.Session. +func (gs *tidbSession) CreatePlacementPolicy(ctx context.Context, policy *model.PolicyInfo) error { + d := domain.GetDomain(gs.se).DDL() + gs.se.SetValue(sessionctx.QueryString, gs.showCreatePlacementPolicy(policy)) + // the default behaviour is ignoring duplicated policy during restore. + return d.CreatePlacementPolicyWithInfo(gs.se, policy, ddl.OnExistIgnore) +} + +// CreateTables implements glue.BatchCreateTableSession. +func (gs *tidbSession) CreateTables(ctx context.Context, tables map[string][]*model.TableInfo) error { + d := domain.GetDomain(gs.se).DDL() + var dbName model.CIStr + + for db, tablesInDB := range tables { + dbName = model.NewCIStr(db) + queryBuilder := strings.Builder{} + cloneTables := make([]*model.TableInfo, 0, len(tablesInDB)) + for _, table := range tablesInDB { + query, err := gs.showCreateTable(table) + if err != nil { + return errors.Trace(err) + } + + queryBuilder.WriteString(query) + queryBuilder.WriteString(";") + + table = table.Clone() + // Clone() does not clone partitions yet :( + if table.Partition != nil { + newPartition := *table.Partition + newPartition.Definitions = append([]model.PartitionDefinition{}, table.Partition.Definitions...) + table.Partition = &newPartition + } + cloneTables = append(cloneTables, table) + } + gs.se.SetValue(sessionctx.QueryString, queryBuilder.String()) + err := d.BatchCreateTableWithInfo(gs.se, dbName, cloneTables, ddl.OnExistIgnore) + if err != nil { + //It is possible to failure when TiDB does not support model.ActionCreateTables. + //In this circumstance, BatchCreateTableWithInfo returns errno.ErrInvalidDDLJob, + //we fall back to old way that creating table one by one + log.Warn("batch create table from tidb failure", zap.Error(err)) + return err + } + } + + return nil } // CreateTable implements glue.Session. @@ -143,7 +195,7 @@ func (gs *tidbSession) CreateTable(ctx context.Context, dbName model.CIStr, tabl newPartition.Definitions = append([]model.PartitionDefinition{}, table.Partition.Definitions...) table.Partition = &newPartition } - return d.CreateTableWithInfo(gs.se, dbName, table, ddl.OnExistIgnore, true) + return d.CreateTableWithInfo(gs.se, dbName, table, ddl.OnExistIgnore) } // Close implements glue.Session. @@ -151,6 +203,11 @@ func (gs *tidbSession) Close() { gs.se.Close() } +// GetGlobalVariables implements glue.Session. +func (gs *tidbSession) GetGlobalVariable(name string) (string, error) { + return gs.se.GetSessionVars().GlobalVarsAccessor.GetTiDBTableValue(name) +} + // showCreateTable shows the result of SHOW CREATE TABLE from a TableInfo. func (gs *tidbSession) showCreateTable(tbl *model.TableInfo) (string, error) { table := tbl.Clone() @@ -174,3 +231,7 @@ func (gs *tidbSession) showCreateDatabase(db *model.DBInfo) (string, error) { } return result.String(), nil } + +func (gs *tidbSession) showCreatePlacementPolicy(policy *model.PolicyInfo) string { + return executor.ConstructResultOfShowCreatePlacementPolicy(policy) +} diff --git a/br/pkg/kv/checksum.go b/br/pkg/kv/checksum.go deleted file mode 100644 index dbfed41aa0edc..0000000000000 --- a/br/pkg/kv/checksum.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kv - -import ( - "fmt" - "hash/crc64" - - "go.uber.org/zap/zapcore" -) - -var ecmaTable = crc64.MakeTable(crc64.ECMA) - -// Checksum represents the field needs checksum. -type Checksum struct { - bytes uint64 - kvs uint64 - checksum uint64 -} - -// NewKVChecksum creates Checksum. -func NewKVChecksum(checksum uint64) *Checksum { - return &Checksum{ - checksum: checksum, - } -} - -// MakeKVChecksum creates Checksum. -func MakeKVChecksum(bytes uint64, kvs uint64, checksum uint64) Checksum { - return Checksum{ - bytes: bytes, - kvs: kvs, - checksum: checksum, - } -} - -// UpdateOne add kv with its values. -func (c *Checksum) UpdateOne(kv Pair) { - sum := crc64.Update(0, ecmaTable, kv.Key) - sum = crc64.Update(sum, ecmaTable, kv.Val) - - c.bytes += uint64(len(kv.Key) + len(kv.Val)) - c.kvs++ - c.checksum ^= sum -} - -// Update add batch of kvs with their values. -func (c *Checksum) Update(kvs []Pair) { - var ( - checksum uint64 - sum uint64 - kvNum int - bytes int - ) - - for _, pair := range kvs { - sum = crc64.Update(0, ecmaTable, pair.Key) - sum = crc64.Update(sum, ecmaTable, pair.Val) - checksum ^= sum - kvNum++ - bytes += (len(pair.Key) + len(pair.Val)) - } - - c.bytes += uint64(bytes) - c.kvs += uint64(kvNum) - c.checksum ^= checksum -} - -// Add other checksum. -func (c *Checksum) Add(other *Checksum) { - c.bytes += other.bytes - c.kvs += other.kvs - c.checksum ^= other.checksum -} - -// Sum returns the checksum. -func (c *Checksum) Sum() uint64 { - return c.checksum -} - -// SumSize returns the bytes. -func (c *Checksum) SumSize() uint64 { - return c.bytes -} - -// SumKVS returns the kv count. -func (c *Checksum) SumKVS() uint64 { - return c.kvs -} - -// MarshalLogObject implements the zapcore.ObjectMarshaler interface. -func (c *Checksum) MarshalLogObject(encoder zapcore.ObjectEncoder) error { - encoder.AddUint64("cksum", c.checksum) - encoder.AddUint64("size", c.bytes) - encoder.AddUint64("kvs", c.kvs) - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (c Checksum) MarshalJSON() ([]byte, error) { - result := fmt.Sprintf(`{"checksum":%d,"size":%d,"kvs":%d}`, c.checksum, c.bytes, c.kvs) - return []byte(result), nil -} diff --git a/br/pkg/kv/checksum_test.go b/br/pkg/kv/checksum_test.go deleted file mode 100644 index 8b594f23f698c..0000000000000 --- a/br/pkg/kv/checksum_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kv_test - -import ( - "encoding/json" - "testing" - - "github.com/pingcap/tidb/br/pkg/kv" - "github.com/stretchr/testify/require" -) - -func uint64NotEqual(a uint64, b uint64) bool { return a != b } - -func TestChecksum(t *testing.T) { - checksum := kv.NewKVChecksum(0) - require.Equal(t, uint64(0), checksum.Sum()) - - // checksum on nothing - checksum.Update([]kv.Pair{}) - require.Equal(t, uint64(0), checksum.Sum()) - - checksum.Update(nil) - require.Equal(t, uint64(0), checksum.Sum()) - - // checksum on real data - expectChecksum := uint64(4850203904608948940) - - kvs := []kv.Pair{ - { - Key: []byte("Cop"), - Val: []byte("PingCAP"), - }, - { - Key: []byte("Introduction"), - Val: []byte("Inspired by Google Spanner/F1, PingCAP develops TiDB."), - }, - } - - checksum.Update(kvs) - - var kvBytes uint64 - for _, kv := range kvs { - kvBytes += uint64(len(kv.Key) + len(kv.Val)) - } - require.Equal(t, kvBytes, checksum.SumSize()) - require.Equal(t, uint64(len(kvs)), checksum.SumKVS()) - require.Equal(t, expectChecksum, checksum.Sum()) - - // recompute on same key-value - checksum.Update(kvs) - require.Equal(t, kvBytes<<1, checksum.SumSize()) - require.Equal(t, uint64(len(kvs))<<1, checksum.SumKVS()) - require.True(t, uint64NotEqual(checksum.Sum(), expectChecksum)) -} - -func TestChecksumJSON(t *testing.T) { - testStruct := &struct { - Checksum kv.Checksum - }{ - Checksum: kv.MakeKVChecksum(123, 456, 7890), - } - - res, err := json.Marshal(testStruct) - - require.NoError(t, err) - require.Equal(t, []byte(`{"Checksum":{"checksum":7890,"size":123,"kvs":456}}`), res) -} diff --git a/br/pkg/kv/kv.go b/br/pkg/kv/kv.go deleted file mode 100644 index 02c9457fb7fbb..0000000000000 --- a/br/pkg/kv/kv.go +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kv - -import ( - "bytes" - "context" - "fmt" - "math" - "sort" - - "github.com/pingcap/errors" - sst "github.com/pingcap/kvproto/pkg/import_sstpb" - "github.com/pingcap/log" - "github.com/pingcap/tidb/br/pkg/logutil" - "github.com/pingcap/tidb/br/pkg/redact" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/meta/autoid" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/tablecodec" - "github.com/pingcap/tidb/types" - "go.uber.org/zap" -) - -var extraHandleColumnInfo = model.NewExtraHandleColInfo() - -// Iter abstract iterator method for Ingester. -type Iter interface { - // Seek seek to specify position. - // if key not found, seeks next key position in iter. - Seek(key []byte) bool - // Error return current error on this iter. - Error() error - // First moves this iter to the first key. - First() bool - // Last moves this iter to the last key. - Last() bool - // Valid check this iter reach the end. - Valid() bool - // Next moves this iter forward. - Next() bool - // Key represents current position pair's key. - Key() []byte - // Value represents current position pair's Value. - Value() []byte - // Close close this iter. - Close() error - // OpType represents operations of pair. currently we have two types. - // 1. Put - // 2. Delete - OpType() sst.Pair_OP -} - -// IterProducer produces iterator with given range. -type IterProducer interface { - // Produce produces iterator with given range [start, end). - Produce(start []byte, end []byte) Iter -} - -// SimpleKVIterProducer represents kv iter producer. -type SimpleKVIterProducer struct { - pairs Pairs -} - -// NewSimpleKVIterProducer creates SimpleKVIterProducer. -func NewSimpleKVIterProducer(pairs Pairs) IterProducer { - return &SimpleKVIterProducer{ - pairs: pairs, - } -} - -// Produce implements Iter.Producer.Produce. -func (p *SimpleKVIterProducer) Produce(start []byte, end []byte) Iter { - startIndex := sort.Search(len(p.pairs), func(i int) bool { - return bytes.Compare(start, p.pairs[i].Key) < 1 - }) - endIndex := sort.Search(len(p.pairs), func(i int) bool { - return bytes.Compare(end, p.pairs[i].Key) < 1 - }) - if startIndex >= endIndex { - log.Warn("produce failed due to start key is large than end key", - zap.Binary("start", start), zap.Binary("end", end)) - return nil - } - return newSimpleKVIter(p.pairs[startIndex:endIndex]) -} - -// SimpleKVIter represents simple pair iterator. -// which is used for log restore. -type SimpleKVIter struct { - index int - pairs Pairs -} - -// newSimpleKVIter creates SimpleKVIter. -func newSimpleKVIter(pairs Pairs) Iter { - return &SimpleKVIter{ - index: -1, - pairs: pairs, - } -} - -// Seek implements Iter.Seek. -func (s *SimpleKVIter) Seek(key []byte) bool { - s.index = sort.Search(len(s.pairs), func(i int) bool { - return bytes.Compare(key, s.pairs[i].Key) < 1 - }) - return s.index < len(s.pairs) -} - -// Error implements Iter.Error. -func (s *SimpleKVIter) Error() error { - return nil -} - -// First implements Iter.First. -func (s *SimpleKVIter) First() bool { - if len(s.pairs) == 0 { - return false - } - s.index = 0 - return true -} - -// Last implements Iter.Last. -func (s *SimpleKVIter) Last() bool { - if len(s.pairs) == 0 { - return false - } - s.index = len(s.pairs) - 1 - return true -} - -// Valid implements Iter.Valid. -func (s *SimpleKVIter) Valid() bool { - return s.index >= 0 && s.index < len(s.pairs) -} - -// Next implements Iter.Next. -func (s *SimpleKVIter) Next() bool { - s.index++ - return s.index < len(s.pairs) -} - -// Key implements Iter.Key. -func (s *SimpleKVIter) Key() []byte { - if s.index >= 0 && s.index < len(s.pairs) { - return s.pairs[s.index].Key - } - return nil -} - -// Value implements Iter.Value. -func (s *SimpleKVIter) Value() []byte { - if s.index >= 0 && s.index < len(s.pairs) { - return s.pairs[s.index].Val - } - return nil -} - -// Close implements Iter.Close. -func (s *SimpleKVIter) Close() error { - return nil -} - -// OpType implements Iter.KeyIsDelete. -func (s *SimpleKVIter) OpType() sst.Pair_OP { - if s.Valid() && s.pairs[s.index].IsDelete { - return sst.Pair_Delete - } - return sst.Pair_Put -} - -// Encoder encodes a row of SQL values into some opaque type which can be -// consumed by OpenEngine.WriteEncoded. -type Encoder interface { - // Close the encoder. - Close() - - // AddRecord encode encodes a row of SQL values into a backend-friendly format. - AddRecord( - row []types.Datum, - rowID int64, - columnPermutation []int, - ) (Row, int, error) - - // RemoveRecord encode encodes a row of SQL delete values into a backend-friendly format. - RemoveRecord( - row []types.Datum, - rowID int64, - columnPermutation []int, - ) (Row, int, error) -} - -// Row represents a single encoded row. -type Row interface { - // ClassifyAndAppend separates the data-like and index-like parts of the - // encoded row, and appends these parts into the existing buffers and - // checksums. - ClassifyAndAppend( - data *Pairs, - dataChecksum *Checksum, - indices *Pairs, - indexChecksum *Checksum, - ) -} - -type tableKVEncoder struct { - tbl table.Table - se *session - recordCache []types.Datum -} - -// NewTableKVEncoder creates the Encoder. -func NewTableKVEncoder(tbl table.Table, options *SessionOptions) Encoder { - se := newSession(options) - // Set CommonAddRecordCtx to session to reuse the slices and BufStore in AddRecord - recordCtx := tables.NewCommonAddRecordCtx(len(tbl.Cols())) - tables.SetAddRecordCtx(se, recordCtx) - return &tableKVEncoder{ - tbl: tbl, - se: se, - } -} - -var kindStr = [...]string{ - types.KindNull: "null", - types.KindInt64: "int64", - types.KindUint64: "uint64", - types.KindFloat32: "float32", - types.KindFloat64: "float64", - types.KindString: "string", - types.KindBytes: "bytes", - types.KindBinaryLiteral: "binary", - types.KindMysqlDecimal: "decimal", - types.KindMysqlDuration: "duration", - types.KindMysqlEnum: "enum", - types.KindMysqlBit: "bit", - types.KindMysqlSet: "set", - types.KindMysqlTime: "time", - types.KindInterface: "interface", - types.KindMinNotNull: "min", - types.KindMaxValue: "max", - types.KindRaw: "raw", - types.KindMysqlJSON: "json", -} - -// MarshalLogArray implements the zapcore.ArrayMarshaler interface. -func zapRow(key string, row []types.Datum) zap.Field { - return logutil.AbbreviatedArray(key, row, func(input interface{}) []string { - row := input.([]types.Datum) - vals := make([]string, 0, len(row)) - for _, datum := range row { - kind := datum.Kind() - var str string - var err error - switch kind { - case types.KindNull: - str = "NULL" - case types.KindMinNotNull: - str = "-inf" - case types.KindMaxValue: - str = "+inf" - default: - str, err = datum.ToString() - if err != nil { - vals = append(vals, err.Error()) - continue - } - } - vals = append(vals, - fmt.Sprintf("kind: %s, val: %s", kindStr[kind], redact.String(str))) - } - return vals - }) -} - -// Pairs represents the slice of Pair. -type Pairs []Pair - -// Close ... -func (kvcodec *tableKVEncoder) Close() { -} - -// AddRecord encode a row of data into KV pairs. -// -// See comments in `(*TableRestore).initializeColumns` for the meaning of the -// `columnPermutation` parameter. -func (kvcodec *tableKVEncoder) AddRecord( - row []types.Datum, - rowID int64, - columnPermutation []int, -) (Row, int, error) { - cols := kvcodec.tbl.Cols() - - var value types.Datum - var err error - - record := kvcodec.recordCache - if record == nil { - record = make([]types.Datum, 0, len(cols)+1) - } - - isAutoRandom := false - if kvcodec.tbl.Meta().PKIsHandle && kvcodec.tbl.Meta().ContainsAutoRandomBits() { - isAutoRandom = true - } - - for i, col := range cols { - j := columnPermutation[i] - isAutoIncCol := mysql.HasAutoIncrementFlag(col.Flag) - isPk := mysql.HasPriKeyFlag(col.Flag) - switch { - case j >= 0 && j < len(row): - value, err = table.CastValue(kvcodec.se, row[j], col.ToInfo(), false, false) - if err == nil { - err = col.HandleBadNull(&value, kvcodec.se.vars.StmtCtx) - } - case isAutoIncCol: - // we still need a conversion, e.g. to catch overflow with a TINYINT column. - value, err = table.CastValue(kvcodec.se, types.NewIntDatum(rowID), col.ToInfo(), false, false) - default: - value, err = table.GetColDefaultValue(kvcodec.se, col.ToInfo()) - } - if err != nil { - return nil, 0, errors.Trace(err) - } - - record = append(record, value) - - if isAutoRandom && isPk { - typeBitsLength := uint64(mysql.DefaultLengthOfMysqlTypes[col.Tp] * 8) - incrementalBits := typeBitsLength - kvcodec.tbl.Meta().AutoRandomBits - hasSignBit := !mysql.HasUnsignedFlag(col.Flag) - if hasSignBit { - incrementalBits-- - } - alloc := kvcodec.tbl.Allocators(kvcodec.se).Get(autoid.AutoRandomType) - _ = alloc.Rebase(context.Background(), value.GetInt64()&((1<= 0 && j < len(row) { - value, err = table.CastValue(kvcodec.se, row[j], extraHandleColumnInfo, false, false) - } else { - value, err = types.NewIntDatum(rowID), nil - } - if err != nil { - return nil, 0, errors.Trace(err) - } - record = append(record, value) - alloc := kvcodec.tbl.Allocators(kvcodec.se).Get(autoid.RowIDAllocType) - _ = alloc.Rebase(context.Background(), value.GetInt64(), false) - } - _, err = kvcodec.tbl.AddRecord(kvcodec.se, record) - if err != nil { - log.Error("kv add Record failed", - zapRow("originalRow", row), - zapRow("convertedRow", record), - zap.Error(err), - ) - return nil, 0, errors.Trace(err) - } - - pairs, size := kvcodec.se.takeKvPairs() - kvcodec.recordCache = record[:0] - return Pairs(pairs), size, nil -} - -// get record value for auto-increment field -// -// See: https://github.com/pingcap/tidb/blob/47f0f15b14ed54fc2222f3e304e29df7b05e6805/executor/insert_common.go#L781-L852 -// TODO: merge this with pkg/lightning/backend/kv/sql2kv.go -func getAutoRecordID(d types.Datum, target *types.FieldType) int64 { - switch target.Tp { - case mysql.TypeFloat, mysql.TypeDouble: - return int64(math.Round(d.GetFloat64())) - case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: - return d.GetInt64() - default: - panic(fmt.Sprintf("unsupported auto-increment field type '%d'", target.Tp)) - } -} - -// RemoveRecord encode a row of data into KV pairs. -func (kvcodec *tableKVEncoder) RemoveRecord( - row []types.Datum, - rowID int64, - columnPermutation []int, -) (Row, int, error) { - cols := kvcodec.tbl.Cols() - - var value types.Datum - var err error - - record := kvcodec.recordCache - if record == nil { - record = make([]types.Datum, 0, len(cols)+1) - } - - for i, col := range cols { - j := columnPermutation[i] - isAutoIncCol := mysql.HasAutoIncrementFlag(col.Flag) - switch { - case j >= 0 && j < len(row): - value, err = table.CastValue(kvcodec.se, row[j], col.ToInfo(), false, false) - if err == nil { - err = col.HandleBadNull(&value, kvcodec.se.vars.StmtCtx) - } - case isAutoIncCol: - // we still need a conversion, e.g. to catch overflow with a TINYINT column. - value, err = table.CastValue(kvcodec.se, types.NewIntDatum(rowID), col.ToInfo(), false, false) - default: - value, err = table.GetColDefaultValue(kvcodec.se, col.ToInfo()) - } - if err != nil { - return nil, 0, errors.Trace(err) - } - record = append(record, value) - } - err = kvcodec.tbl.RemoveRecord(kvcodec.se, kv.IntHandle(rowID), record) - if err != nil { - log.Error("kv remove record failed", - zapRow("originalRow", row), - zapRow("convertedRow", record), - zap.Error(err), - ) - return nil, 0, errors.Trace(err) - } - - pairs, size := kvcodec.se.takeKvPairs() - kvcodec.recordCache = record[:0] - return Pairs(pairs), size, nil -} - -// ClassifyAndAppend split Pairs to data rows and index rows. -func (kvs Pairs) ClassifyAndAppend( - data *Pairs, - dataChecksum *Checksum, - indices *Pairs, - indexChecksum *Checksum, -) { - dataKVs := *data - indexKVs := *indices - - for _, kv := range kvs { - if kv.Key[tablecodec.TableSplitKeyLen+1] == 'r' { - dataKVs = append(dataKVs, kv) - dataChecksum.UpdateOne(kv) - } else { - indexKVs = append(indexKVs, kv) - indexChecksum.UpdateOne(kv) - } - } - - *data = dataKVs - *indices = indexKVs -} - -// Clear resets the Pairs. -func (kvs Pairs) Clear() Pairs { - return kvs[:0] -} - -// NextKey return the smallest []byte that is bigger than current bytes. -// special case when key is empty, empty bytes means infinity in our context, so directly return itself. -func NextKey(key []byte) []byte { - if len(key) == 0 { - return []byte{} - } - - // in tikv <= 4.x, tikv will truncate the row key, so we should fetch the next valid row key - // See: https://github.com/tikv/tikv/blob/f7f22f70e1585d7ca38a59ea30e774949160c3e8/components/raftstore/src/coprocessor/split_observer.rs#L36-L41 - if tablecodec.IsRecordKey(key) { - tableID, handle, _ := tablecodec.DecodeRecordKey(key) - return tablecodec.EncodeRowKeyWithHandle(tableID, handle.Next()) - } - - // if key is an index, directly append a 0x00 to the key. - res := make([]byte, 0, len(key)+1) - res = append(res, key...) - res = append(res, 0) - return res -} diff --git a/br/pkg/kv/kv_test.go b/br/pkg/kv/kv_test.go deleted file mode 100644 index ddf32247e03b2..0000000000000 --- a/br/pkg/kv/kv_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2020 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kv - -import ( - "bytes" - "strings" - "testing" - - "github.com/pingcap/tidb/types" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -func TestMarshal(t *testing.T) { - dats := make([]types.Datum, 4) - dats[0].SetInt64(1) - dats[1].SetNull() - dats[2] = types.MaxValueDatum() - dats[3] = types.MinNotNullDatum() - - encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{}) - out, err := encoder.EncodeEntry(zapcore.Entry{}, []zap.Field{zapRow("row", dats)}) - require.NoError(t, err) - require.Equal(t, - `{"row": ["kind: int64, val: 1", "kind: null, val: NULL", "kind: max, val: +inf", "kind: min, val: -inf"]}`, - strings.TrimRight(out.String(), "\n")) -} - -func TestSimplePairIter(t *testing.T) { - pairs := []Pair{ - {Key: []byte("1"), Val: []byte("a")}, - {Key: []byte("2"), Val: []byte("b")}, - {Key: []byte("3"), Val: []byte("c")}, - {Key: []byte("5"), Val: []byte("d")}, - } - expectCount := 4 - iter := newSimpleKVIter(pairs) - count := 0 - for iter.Next() { - count++ - } - require.Equal(t, expectCount, count) - - require.True(t, iter.First()) - require.True(t, iter.Last()) - - require.True(t, iter.Seek([]byte("1"))) - require.True(t, bytes.Equal(iter.Key(), []byte("1"))) - require.True(t, bytes.Equal(iter.Value(), []byte("a"))) - require.True(t, iter.Valid()) - - require.True(t, iter.Seek([]byte("2"))) - require.True(t, bytes.Equal(iter.Key(), []byte("2"))) - require.True(t, bytes.Equal(iter.Value(), []byte("b"))) - require.True(t, iter.Valid()) - - require.True(t, iter.Seek([]byte("3"))) - require.True(t, bytes.Equal(iter.Key(), []byte("3"))) - require.True(t, bytes.Equal(iter.Value(), []byte("c"))) - require.True(t, iter.Valid()) - - // 4 not exists, so seek position will move to 5. - require.True(t, iter.Seek([]byte("4"))) - require.True(t, bytes.Equal(iter.Key(), []byte("5"))) - require.True(t, bytes.Equal(iter.Value(), []byte("d"))) - require.True(t, iter.Valid()) - - // 6 not exists, so seek position will not valid. - require.False(t, iter.Seek([]byte("6"))) - require.False(t, iter.Valid()) -} diff --git a/br/pkg/kv/session.go b/br/pkg/kv/session.go deleted file mode 100644 index 663627d3dd440..0000000000000 --- a/br/pkg/kv/session.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2019 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kv - -import ( - "context" - "fmt" - "strconv" - - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/sessionctx/variable" -) - -// Pair is a pair of key and value. -type Pair struct { - // Key is the key of the KV pair - Key []byte - // Val is the value of the KV pair - Val []byte - // IsDelete represents whether we should remove this KV pair. - IsDelete bool -} - -// invalidIterator is a trimmed down Iterator type which is invalid. -type invalidIterator struct { - kv.Iterator -} - -// TableHasAutoRowID return whether table has auto generated row id. -func TableHasAutoRowID(info *model.TableInfo) bool { - return !info.PKIsHandle && !info.IsCommonHandle -} - -// Valid implements the kv.Iterator interface. -func (*invalidIterator) Valid() bool { - return false -} - -// Close implements the kv.Iterator interface. -func (*invalidIterator) Close() { -} - -type kvMemBuf struct { - kv.MemBuffer - kvPairs []Pair - size int -} - -func (mb *kvMemBuf) Set(k kv.Key, v []byte) error { - mb.kvPairs = append(mb.kvPairs, Pair{ - Key: k.Clone(), - Val: append([]byte{}, v...), - }) - mb.size += len(k) + len(v) - return nil -} - -func (mb *kvMemBuf) SetWithFlags(k kv.Key, v []byte, ops ...kv.FlagsOp) error { - return mb.Set(k, v) -} - -func (mb *kvMemBuf) Delete(k kv.Key) error { - mb.kvPairs = append(mb.kvPairs, Pair{ - Key: k.Clone(), - Val: []byte{}, - IsDelete: true, - }) - mb.size += len(k) - return nil -} - -func (mb *kvMemBuf) DeleteWithFlags(k kv.Key, ops ...kv.FlagsOp) error { - return mb.Delete(k) -} - -// Release publish all modifications in the latest staging buffer to upper level. -func (mb *kvMemBuf) Release(h kv.StagingHandle) { -} - -func (mb *kvMemBuf) Staging() kv.StagingHandle { - return 0 -} - -// Cleanup cleanup the resources referenced by the StagingHandle. -// If the changes are not published by `Release`, they will be discarded. -func (mb *kvMemBuf) Cleanup(h kv.StagingHandle) {} - -// Size returns sum of keys and values length. -func (mb *kvMemBuf) Size() int { - return mb.size -} - -// Len returns the number of entries in the DB. -func (t *transaction) Len() int { - return t.GetMemBuffer().Len() -} - -type kvUnionStore struct { - kvMemBuf -} - -func (s *kvUnionStore) GetMemBuffer() kv.MemBuffer { - return &s.kvMemBuf -} - -func (s *kvUnionStore) GetIndexName(tableID, indexID int64) string { - panic("Unsupported Operation") -} - -func (s *kvUnionStore) CacheIndexName(tableID, indexID int64, name string) { -} - -func (s *kvUnionStore) CacheTableInfo(id int64, info *model.TableInfo) { -} - -// transaction is a trimmed down Transaction type which only supports adding a -// new KV pair. -type transaction struct { - kv.Transaction - kvUnionStore -} - -func (t *transaction) GetMemBuffer() kv.MemBuffer { - return &t.kvUnionStore.kvMemBuf -} - -func (t *transaction) Discard() { - // do nothing -} - -func (t *transaction) Flush() (int, error) { - // do nothing - return 0, nil -} - -// Reset implements the kv.MemBuffer interface. -func (t *transaction) Reset() {} - -// Get implements the kv.Retriever interface. -func (t *transaction) Get(ctx context.Context, key kv.Key) ([]byte, error) { - return nil, kv.ErrNotExist -} - -// Iter implements the kv.Retriever interface. -func (t *transaction) Iter(k kv.Key, upperBound kv.Key) (kv.Iterator, error) { - return &invalidIterator{}, nil -} - -// Set implements the kv.Mutator interface. -func (t *transaction) Set(k kv.Key, v []byte) error { - return t.kvMemBuf.Set(k, v) -} - -// Delete implements the kv.Mutator interface. -func (t *transaction) Delete(k kv.Key) error { - return t.kvMemBuf.Delete(k) -} - -// GetTableInfo implements the kv.Transaction interface. -func (t *transaction) GetTableInfo(id int64) *model.TableInfo { - return nil -} - -// CacheTableInfo implements the kv.Transaction interface. -func (t *transaction) CacheTableInfo(id int64, info *model.TableInfo) { -} - -// session is a trimmed down Session type which only wraps our own trimmed-down -// transaction type and provides the session variables to the TiDB library -// optimized for Lightning. -type session struct { - sessionctx.Context - txn transaction - vars *variable.SessionVars - // currently, we only set `CommonAddRecordCtx` - values map[fmt.Stringer]interface{} -} - -// SessionOptions is the initial configuration of the session. -type SessionOptions struct { - SQLMode mysql.SQLMode - Timestamp int64 - RowFormatVersion string -} - -func newSession(options *SessionOptions) *session { - sqlMode := options.SQLMode - vars := variable.NewSessionVars() - vars.SkipUTF8Check = true - vars.StmtCtx.InInsertStmt = true - vars.StmtCtx.BatchCheck = true - vars.StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode() - vars.StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode() - vars.StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode() - vars.StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode() - vars.StmtCtx.IgnoreZeroInDate = !sqlMode.HasStrictMode() || sqlMode.HasAllowInvalidDatesMode() - vars.StmtCtx.TimeZone = vars.Location() - _ = vars.SetSystemVar("timestamp", strconv.FormatInt(options.Timestamp, 10)) - _ = vars.SetSystemVar(variable.TiDBRowFormatVersion, options.RowFormatVersion) - vars.TxnCtx = nil - - s := &session{ - vars: vars, - values: make(map[fmt.Stringer]interface{}, 1), - } - return s -} - -func (se *session) takeKvPairs() ([]Pair, int) { - pairs := se.txn.kvMemBuf.kvPairs - size := se.txn.kvMemBuf.Size() - se.txn.kvMemBuf.kvPairs = make([]Pair, 0, len(pairs)) - se.txn.kvMemBuf.size = 0 - return pairs, size -} - -// Txn implements the sessionctx.Context interface. -func (se *session) Txn(active bool) (kv.Transaction, error) { - return &se.txn, nil -} - -// GetSessionVars implements the sessionctx.Context interface. -func (se *session) GetSessionVars() *variable.SessionVars { - return se.vars -} - -// SetValue saves a value associated with this context for key. -func (se *session) SetValue(key fmt.Stringer, value interface{}) { - se.values[key] = value -} - -// Value returns the value associated with this context for key. -func (se *session) Value(key fmt.Stringer) interface{} { - return se.values[key] -} - -// StmtAddDirtyTableOP implements the sessionctx.Context interface. -func (se *session) StmtAddDirtyTableOP(op int, physicalID int64, handle kv.Handle) {} diff --git a/br/pkg/lightning/backend/importer/importer_test.go b/br/pkg/lightning/backend/importer/importer_test.go index dd65db3ee4d5a..b73128d186e44 100644 --- a/br/pkg/lightning/backend/importer/importer_test.go +++ b/br/pkg/lightning/backend/importer/importer_test.go @@ -282,12 +282,12 @@ func TestCheckTiDBVersion(t *testing.T) { require.Error(t, err) require.Regexp(t, "^TiDB version too new", err.Error()) - version = "5.7.25-TiDB-v6.0.0" + version = "5.7.25-TiDB-v7.0.0" err = checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) require.Error(t, err) require.Regexp(t, "^TiDB version too new", err.Error()) - version = "5.7.25-TiDB-v6.0.0-beta" + version = "5.7.25-TiDB-v7.0.0-beta" err = checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion) require.Error(t, err) require.Regexp(t, "^TiDB version too new", err.Error()) diff --git a/br/pkg/lightning/backend/kv/kv2sql.go b/br/pkg/lightning/backend/kv/kv2sql.go index a3c188a81eea7..47b9aa5393b2d 100644 --- a/br/pkg/lightning/backend/kv/kv2sql.go +++ b/br/pkg/lightning/backend/kv/kv2sql.go @@ -17,7 +17,6 @@ package kv import ( "fmt" - "github.com/pingcap/tidb/br/pkg/lightning/metric" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/table" @@ -38,15 +37,10 @@ func (t *TableKVDecoder) Name() string { return t.tableName } -func (t *TableKVDecoder) DecodeHandleFromTable(key []byte) (kv.Handle, error) { +func (t *TableKVDecoder) DecodeHandleFromRowKey(key []byte) (kv.Handle, error) { return tablecodec.DecodeRowKey(key) } -func (t *TableKVDecoder) EncodeHandleKey(tableID int64, h kv.Handle) kv.Key { - // do not ever ever use tbl.Meta().ID, we need to deal with partitioned tables! - return tablecodec.EncodeRowKeyWithHandle(tableID, h) -} - func (t *TableKVDecoder) DecodeHandleFromIndex(indexInfo *model.IndexInfo, key []byte, value []byte) (kv.Handle, error) { cols := tables.BuildRowcodecColInfoForIndexColumns(indexInfo, t.tbl.Meta()) return tablecodec.DecodeIndexHandle(key, value, len(cols)) @@ -111,7 +105,6 @@ func (t *TableKVDecoder) IterRawIndexKeys(h kv.Handle, rawRow []byte, fn func([] } func NewTableKVDecoder(tbl table.Table, tableName string, options *SessionOptions) (*TableKVDecoder, error) { - metric.KvEncoderCounter.WithLabelValues("open").Inc() se := newSession(options) cols := tbl.Cols() // Set CommonAddRecordCtx to session to reuse the slices and BufStore in AddRecord diff --git a/br/pkg/lightning/backend/kv/session.go b/br/pkg/lightning/backend/kv/session.go index bab10d97be600..2756cc23b70d0 100644 --- a/br/pkg/lightning/backend/kv/session.go +++ b/br/pkg/lightning/backend/kv/session.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/topsql/stmtstats" "go.uber.org/zap" ) @@ -218,6 +219,11 @@ func (t *transaction) GetTableInfo(id int64) *model.TableInfo { func (t *transaction) CacheTableInfo(id int64, info *model.TableInfo) { } +// SetAssertion implements the kv.Transaction interface. +func (t *transaction) SetAssertion(key []byte, assertion ...kv.FlagsOp) error { + return nil +} + // session is a trimmed down Session type which only wraps our own trimmed-down // transaction type and provides the session variables to the TiDB library // optimized for Lightning. @@ -324,6 +330,15 @@ func (se *session) GetBuiltinFunctionUsage() map[string]uint32 { return make(map[string]uint32) } +// BuiltinFunctionUsageInc implements the sessionctx.Context interface. +func (se *session) BuiltinFunctionUsageInc(scalarFuncSigName string) { +} + +// GetStmtStats implements the sessionctx.Context interface. +func (se *session) GetStmtStats() *stmtstats.StatementStats { + return nil +} + func (se *session) Close() { memBuf := &se.txn.kvMemBuf if memBuf.buf != nil { diff --git a/br/pkg/lightning/backend/kv/session_test.go b/br/pkg/lightning/backend/kv/session_test.go index 2917a6afa747e..9703390afb2ec 100644 --- a/br/pkg/lightning/backend/kv/session_test.go +++ b/br/pkg/lightning/backend/kv/session_test.go @@ -17,20 +17,12 @@ package kv import ( "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser/mysql" + "github.com/stretchr/testify/require" ) -type kvSuite struct{} - -var _ = Suite(&kvSuite{}) - -func TestKV(t *testing.T) { - TestingT(t) -} - -func (s *kvSuite) TestSession(c *C) { +func TestSession(t *testing.T) { session := newSession(&SessionOptions{SQLMode: mysql.ModeNone, Timestamp: 1234567890}) _, err := session.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) } diff --git a/br/pkg/lightning/backend/kv/sql2kv.go b/br/pkg/lightning/backend/kv/sql2kv.go index 45fd0ab664f50..62eba924575d9 100644 --- a/br/pkg/lightning/backend/kv/sql2kv.go +++ b/br/pkg/lightning/backend/kv/sql2kv.go @@ -79,7 +79,7 @@ func NewTableKVEncoder(tbl table.Table, options *SessionOptions) (Encoder, error for _, col := range cols { if mysql.HasPriKeyFlag(col.Flag) { incrementalBits := autoRandomIncrementBits(col, int(meta.AutoRandomBits)) - autoRandomBits := rand.New(rand.NewSource(options.AutoRandomSeed)).Int63n(1< 0 { - rd := rand.New(rand.NewSource(options.AutoRandomSeed)) + rd := rand.New(rand.NewSource(options.AutoRandomSeed)) // nolint:gosec mask := int64(1)<. c1 := &model.ColumnInfo{ID: 1, Name: model.NewCIStr("c1"), State: model.StatePublic, Offset: 0, FieldType: *types.NewFieldType(mysql.TypeTiny)} cols := []*model.ColumnInfo{c1} tblInfo := &model.TableInfo{ID: 1, Columns: cols, PKIsHandle: false, State: model.StatePublic} tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) logger := log.Logger{Logger: zap.NewNop()} rows := []types.Datum{ @@ -246,10 +248,10 @@ func (s *kvSuite) TestEncodeRowFormatV2(c *C) { Timestamp: 1234567892, SysVars: map[string]string{"tidb_row_format_version": "2"}, }) - c.Assert(err, IsNil) + require.NoError(t, err) pairs, err := noneMode.Encode(logger, rows, 1, []int{0, 1}, "1.csv", 1234) - c.Assert(err, IsNil) - c.Assert(pairs, DeepEquals, &KvPairs{pairs: []common.KvPair{ + require.NoError(t, err) + require.Equal(t, pairs, &KvPairs{pairs: []common.KvPair{ { // the key should be the same as TestEncode() Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, @@ -262,13 +264,12 @@ func (s *kvSuite) TestEncodeRowFormatV2(c *C) { 0x1, 0x0, // not null offsets = [1] 0x7f, // column version = 127 (10000000 clamped to TINYINT) }, - RowID: 1, - Offset: 1234, + RowID: 1, }, }}) } -func (s *kvSuite) TestEncodeTimestamp(c *C) { +func TestEncodeTimestamp(t *testing.T) { ty := *types.NewFieldType(mysql.TypeDatetime) ty.Flag |= mysql.NotNullFlag c1 := &model.ColumnInfo{ @@ -283,7 +284,7 @@ func (s *kvSuite) TestEncodeTimestamp(c *C) { cols := []*model.ColumnInfo{c1} tblInfo := &model.TableInfo{ID: 1, Columns: cols, PKIsHandle: false, State: model.StatePublic} tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) logger := log.Logger{Logger: zap.NewNop()} @@ -295,23 +296,22 @@ func (s *kvSuite) TestEncodeTimestamp(c *C) { "time_zone": "+08:00", }, }) - c.Assert(err, IsNil) + require.NoError(t, err) pairs, err := encoder.Encode(logger, nil, 70, []int{-1, 1}, "1.csv", 1234) - c.Assert(err, IsNil) - c.Assert(pairs, DeepEquals, &KvPairs{pairs: []common.KvPair{ + require.NoError(t, err) + require.Equal(t, pairs, &KvPairs{pairs: []common.KvPair{ { - Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, - Val: []uint8{0x8, 0x2, 0x9, 0x80, 0x80, 0x80, 0xf0, 0xfd, 0x8e, 0xf7, 0xc0, 0x19}, - RowID: 70, - Offset: 1234, + Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, + Val: []uint8{0x8, 0x2, 0x9, 0x80, 0x80, 0x80, 0xf0, 0xfd, 0x8e, 0xf7, 0xc0, 0x19}, + RowID: 70, }, }}) } -func (s *kvSuite) TestEncodeDoubleAutoIncrement(c *C) { - tblInfo := mockTableInfo(c, "create table t (id double not null auto_increment, unique key `u_id` (`id`));") +func TestEncodeDoubleAutoIncrement(t *testing.T) { + tblInfo := mockTableInfo(t, "create table t (id double not null auto_increment, unique key `u_id` (`id`));") tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) logger := log.Logger{Logger: zap.NewNop()} @@ -321,150 +321,142 @@ func (s *kvSuite) TestEncodeDoubleAutoIncrement(c *C) { "tidb_row_format_version": "2", }, }) - c.Assert(err, IsNil) + require.NoError(t, err) pairs, err := encoder.Encode(logger, []types.Datum{ types.NewStringDatum("1"), }, 70, []int{0, -1}, "1.csv", 1234) - c.Assert(err, IsNil) - c.Assert(pairs, DeepEquals, &KvPairs{pairs: []common.KvPair{ + require.NoError(t, err) + require.Equal(t, pairs, &KvPairs{pairs: []common.KvPair{ { - Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, - Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - RowID: 70, - Offset: 1234, + Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, + Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + RowID: 70, }, { - Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - Val: []uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, - RowID: 70, - Offset: 1234, + Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + Val: []uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, + RowID: 70, }, }}) - c.Assert(tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoIncrementType).Base(), Equals, int64(70)) + require.Equal(t, tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoIncrementType).Base(), int64(70)) } -func mockTableInfo(c *C, createSQL string) *model.TableInfo { +func mockTableInfo(t *testing.T, createSQL string) *model.TableInfo { parser := parser.New() node, err := parser.ParseOneStmt(createSQL, "", "") - c.Assert(err, IsNil) + require.NoError(t, err) sctx := mock.NewContext() info, err := ddl.MockTableInfo(sctx, node.(*ast.CreateTableStmt), 1) - c.Assert(err, IsNil) + require.NoError(t, err) info.State = model.StatePublic return info } -func (s *kvSuite) TestDefaultAutoRandoms(c *C) { - tblInfo := mockTableInfo(c, "create table t (id bigint unsigned NOT NULL auto_random primary key clustered, a varchar(100));") +func TestDefaultAutoRandoms(t *testing.T) { + tblInfo := mockTableInfo(t, "create table t (id bigint unsigned NOT NULL auto_random primary key clustered, a varchar(100));") // seems parser can't parse auto_random properly. tblInfo.AutoRandomBits = 5 tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) encoder, err := NewTableKVEncoder(tbl, &SessionOptions{ SQLMode: mysql.ModeStrictAllTables, Timestamp: 1234567893, SysVars: map[string]string{"tidb_row_format_version": "2"}, AutoRandomSeed: 456, }) - c.Assert(err, IsNil) + require.NoError(t, err) logger := log.Logger{Logger: zap.NewNop()} pairs, err := encoder.Encode(logger, []types.Datum{types.NewStringDatum("")}, 70, []int{-1, 0}, "1.csv", 1234) - c.Assert(err, IsNil) - c.Assert(pairs, DeepEquals, &KvPairs{pairs: []common.KvPair{ + require.NoError(t, err) + require.Equal(t, pairs, &KvPairs{pairs: []common.KvPair{ { - Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, - Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}, - RowID: 70, - Offset: 1234, + Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}, + Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}, + RowID: 70, }, }}) - c.Assert(tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoRandomType).Base(), Equals, int64(70)) + require.Equal(t, tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoRandomType).Base(), int64(70)) pairs, err = encoder.Encode(logger, []types.Datum{types.NewStringDatum("")}, 71, []int{-1, 0}, "1.csv", 1234) - c.Assert(err, IsNil) - c.Assert(pairs, DeepEquals, &KvPairs{pairs: []common.KvPair{ + require.NoError(t, err) + require.Equal(t, pairs, &KvPairs{pairs: []common.KvPair{ { - Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47}, - Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}, - RowID: 71, - Offset: 1234, + Key: []uint8{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5f, 0x72, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47}, + Val: []uint8{0x80, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}, + RowID: 71, }, }}) - c.Assert(tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoRandomType).Base(), Equals, int64(71)) + require.Equal(t, tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.AutoRandomType).Base(), int64(71)) } -func (s *kvSuite) TestShardRowId(c *C) { - tblInfo := mockTableInfo(c, "create table t (s varchar(16)) shard_row_id_bits = 3;") +func TestShardRowId(t *testing.T) { + tblInfo := mockTableInfo(t, "create table t (s varchar(16)) shard_row_id_bits = 3;") tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) encoder, err := NewTableKVEncoder(tbl, &SessionOptions{ SQLMode: mysql.ModeStrictAllTables, Timestamp: 1234567893, SysVars: map[string]string{"tidb_row_format_version": "2"}, AutoRandomSeed: 456, }) - c.Assert(err, IsNil) + require.NoError(t, err) logger := log.Logger{Logger: zap.NewNop()} keyMap := make(map[int64]struct{}, 16) for i := int64(1); i <= 32; i++ { pairs, err := encoder.Encode(logger, []types.Datum{types.NewStringDatum(fmt.Sprintf("%d", i))}, i, []int{0, -1}, "1.csv", i*32) - c.Assert(err, IsNil) + require.NoError(t, err) kvs := pairs.(*KvPairs) - c.Assert(len(kvs.pairs), Equals, 1) + require.Len(t, kvs.pairs, 1) _, h, err := tablecodec.DecodeRecordKey(kvs.pairs[0].Key) - c.Assert(err, IsNil) + require.NoError(t, err) rowID := h.IntValue() - c.Assert(rowID&((1<<60)-1), Equals, i) + require.Equal(t, rowID&((1<<60)-1), i) keyMap[rowID>>60] = struct{}{} } - c.Assert(len(keyMap), Equals, 8) - c.Assert(tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.RowIDAllocType).Base(), Equals, int64(32)) + require.Len(t, keyMap, 8) + require.Equal(t, tbl.Allocators(encoder.(*tableKVEncoder).se).Get(autoid.RowIDAllocType).Base(), int64(32)) } -func (s *kvSuite) TestSplitIntoChunks(c *C) { +func TestSplitIntoChunks(t *testing.T) { pairs := []common.KvPair{ { - Key: []byte{1, 2, 3}, - Val: []byte{4, 5, 6}, - Offset: 1000, + Key: []byte{1, 2, 3}, + Val: []byte{4, 5, 6}, }, { - Key: []byte{7, 8}, - Val: []byte{9, 0}, - Offset: 2000, + Key: []byte{7, 8}, + Val: []byte{9, 0}, }, { - Key: []byte{1, 2, 3, 4}, - Val: []byte{5, 6, 7, 8}, - Offset: 3000, + Key: []byte{1, 2, 3, 4}, + Val: []byte{5, 6, 7, 8}, }, { - Key: []byte{9, 0}, - Val: []byte{1, 2}, - Offset: 4000, + Key: []byte{9, 0}, + Val: []byte{1, 2}, }, } splitBy10 := MakeRowsFromKvPairs(pairs).SplitIntoChunks(10) - c.Assert(splitBy10, DeepEquals, []Rows{ + require.Equal(t, splitBy10, []Rows{ MakeRowsFromKvPairs(pairs[0:2]), MakeRowsFromKvPairs(pairs[2:3]), MakeRowsFromKvPairs(pairs[3:4]), }) splitBy12 := MakeRowsFromKvPairs(pairs).SplitIntoChunks(12) - c.Assert(splitBy12, DeepEquals, []Rows{ + require.Equal(t, splitBy12, []Rows{ MakeRowsFromKvPairs(pairs[0:2]), MakeRowsFromKvPairs(pairs[2:4]), }) splitBy1000 := MakeRowsFromKvPairs(pairs).SplitIntoChunks(1000) - c.Assert(splitBy1000, DeepEquals, []Rows{ + require.Equal(t, splitBy1000, []Rows{ MakeRowsFromKvPairs(pairs[0:4]), }) splitBy1 := MakeRowsFromKvPairs(pairs).SplitIntoChunks(1) - c.Assert(splitBy1, DeepEquals, []Rows{ + require.Equal(t, splitBy1, []Rows{ MakeRowsFromKvPairs(pairs[0:1]), MakeRowsFromKvPairs(pairs[1:2]), MakeRowsFromKvPairs(pairs[2:3]), @@ -472,7 +464,7 @@ func (s *kvSuite) TestSplitIntoChunks(c *C) { }) } -func (s *kvSuite) TestClassifyAndAppend(c *C) { +func TestClassifyAndAppend(t *testing.T) { kvs := MakeRowFromKvPairs([]common.KvPair{ { Key: []byte("txxxxxxxx_ryyyyyyyy"), @@ -495,7 +487,7 @@ func (s *kvSuite) TestClassifyAndAppend(c *C) { kvs.ClassifyAndAppend(&data, &dataChecksum, &indices, &indexChecksum) - c.Assert(data, DeepEquals, MakeRowsFromKvPairs([]common.KvPair{ + require.Equal(t, data, MakeRowsFromKvPairs([]common.KvPair{ { Key: []byte("txxxxxxxx_ryyyyyyyy"), Val: []byte("value1"), @@ -505,14 +497,14 @@ func (s *kvSuite) TestClassifyAndAppend(c *C) { Val: []byte("value2"), }, })) - c.Assert(indices, DeepEquals, MakeRowsFromKvPairs([]common.KvPair{ + require.Equal(t, indices, MakeRowsFromKvPairs([]common.KvPair{ { Key: []byte("txxxxxxxx_izzzzzzzz"), Val: []byte("index1"), }, })) - c.Assert(dataChecksum.SumKVS(), Equals, uint64(2)) - c.Assert(indexChecksum.SumKVS(), Equals, uint64(1)) + require.Equal(t, dataChecksum.SumKVS(), uint64(2)) + require.Equal(t, indexChecksum.SumKVS(), uint64(1)) } type benchSQL2KVSuite struct { @@ -522,9 +514,7 @@ type benchSQL2KVSuite struct { logger log.Logger } -var _ = Suite(&benchSQL2KVSuite{}) - -func (s *benchSQL2KVSuite) SetUpTest(c *C) { +func SetUpTest(b *testing.B) *benchSQL2KVSuite { // First, create the table info corresponding to TPC-C's "CUSTOMER" table. p := parser.New() se := mock.NewContext() @@ -554,20 +544,20 @@ func (s *benchSQL2KVSuite) SetUpTest(c *C) { primary key (c_w_id, c_d_id, c_id) ); `, "", "") - c.Assert(err, IsNil) + require.NoError(b, err) tableInfo, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 123456) - c.Assert(err, IsNil) + require.NoError(b, err) tableInfo.State = model.StatePublic // Construct the corresponding KV encoder. tbl, err := tables.TableFromMeta(NewPanickingAllocators(0), tableInfo) - c.Assert(err, IsNil) - s.encoder, err = NewTableKVEncoder(tbl, &SessionOptions{SysVars: map[string]string{"tidb_row_format_version": "2"}}) - c.Assert(err, IsNil) - s.logger = log.Logger{Logger: zap.NewNop()} + require.NoError(b, err) + encoder, err := NewTableKVEncoder(tbl, &SessionOptions{SysVars: map[string]string{"tidb_row_format_version": "2"}}) + require.NoError(b, err) + logger := log.Logger{Logger: zap.NewNop()} // Prepare the row to insert. - s.row = []types.Datum{ + row := []types.Datum{ types.NewIntDatum(15), types.NewIntDatum(10), types.NewIntDatum(3000), @@ -590,14 +580,23 @@ func (s *benchSQL2KVSuite) SetUpTest(c *C) { types.NewStringDatum("OE"), types.NewStringDatum("H5p3dpjp7uu8n1l3j0o1buecfV6FngNNgftpNALDhOzJaSzMCMlrQwXuvLAFPIFg215D3wAYB62kiixIuasfbD729oq8TwgKzPPsx8kHE1b4AdhHwpCml3ELKiwuNGQl7CcBQOiq6aFEMMHzjGwQyXwGey0wutjp2KP3Nd4qj3FHtmHbsD8cJ0pH9TswNmdQBgXsFPZeJJhsG3rTimQpS9Tmn3vNeI9fFas3ClDZuQtBjqoTJlyzmBIYT8HeV3TuS93TNFDaXZpQqh8HsvlPq4uTTLOO9CguiY29zlSmIjkZYtva3iscG3YDOQVLeGpP9dtqEJwlRvJ4oe9jWkvRMlCeslSNEuzLxjUBtJBnGRFAzJF6RMlIWCkdCpIhcnIy3jUEsxTuiAU3hsZxUjLg2dnOG62h5qR"), } - s.colPerm = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1} + colPerm := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1} + s := &benchSQL2KVSuite{ + encoder: encoder, + logger: logger, + row: row, + colPerm: colPerm, + } + return s } -// Run `go test github.com/pingcap/tidb/br/pkg/lightning/backend -check.b -test.v` to get benchmark result. -func (s *benchSQL2KVSuite) BenchmarkSQL2KV(c *C) { - for i := 0; i < c.N; i++ { +// BenchmarkSQL2KV Run `go test -benchmem -run=^$ -bench ^BenchmarkSQL2KV$ github.com/pingcap/tidb/br/pkg/lightning/backend/kv` to get benchmark result. +func BenchmarkSQL2KV(b *testing.B) { + s := SetUpTest(b) + for i := 0; i < b.N; i++ { rows, err := s.encoder.Encode(s.logger, s.row, 1, s.colPerm, "", 0) - c.Assert(err, IsNil) - c.Assert(rows, HasLen, 2) + require.NoError(b, err) + l := reflect.ValueOf(rows).Elem().Field(0).Len() + require.Equal(b, l, 2) } } diff --git a/br/pkg/lightning/backend/local/duplicate.go b/br/pkg/lightning/backend/local/duplicate.go index fc88055c40c61..983ae33fcfd68 100644 --- a/br/pkg/lightning/backend/local/duplicate.go +++ b/br/pkg/lightning/backend/local/duplicate.go @@ -19,14 +19,15 @@ import ( "context" "io" "math" - "sort" - "time" + "sync" "github.com/cockroachdb/pebble" + "github.com/docker/go-units" + "github.com/google/btree" "github.com/pingcap/errors" + "github.com/pingcap/kvproto/pkg/errorpb" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/kvrpcpb" - "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/errormanager" @@ -40,42 +41,19 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/ranger" - tikvclient "github.com/tikv/client-go/v2/tikv" + "github.com/tikv/client-go/v2/tikv" "go.uber.org/atomic" "go.uber.org/zap" - "go.uber.org/zap/zapcore" "golang.org/x/sync/errgroup" - "google.golang.org/grpc" - "google.golang.org/grpc/backoff" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/keepalive" ) const ( - maxGetRequestKeyCount = 1024 + maxDupCollectAttemptTimes = 5 + defaultRecordConflictErrorBatch = 1024 ) -type DuplicateRequest struct { - tableID int64 - start tidbkv.Key - end tidbkv.Key - indexInfo *model.IndexInfo -} - -type DuplicateManager struct { - errorMgr *errormanager.ErrorManager - splitCli restore.SplitClient - tikvCli *tikvclient.KVStore - regionConcurrency int - connPool common.GRPCConns - tls *common.TLS - ts uint64 - keyAdapter KeyAdapter - remoteWorkerPool *utils.WorkerPool - opts *kv.SessionOptions -} - type pendingIndexHandles struct { // all 4 slices should have exactly the same length. // we use a struct-of-arrays instead of array-of-structs @@ -88,12 +66,12 @@ type pendingIndexHandles struct { // makePendingIndexHandlesWithCapacity makes the pendingIndexHandles struct-of-arrays with the given // capacity for every internal array. -func makePendingIndexHandlesWithCapacity(cap int) pendingIndexHandles { +func makePendingIndexHandlesWithCapacity(capacity int) pendingIndexHandles { return pendingIndexHandles{ - dataConflictInfos: make([]errormanager.DataConflictInfo, 0, cap), - indexNames: make([]string, 0, cap), - handles: make([]tidbkv.Handle, 0, cap), - rawHandles: make([][]byte, 0, cap), + dataConflictInfos: make([]errormanager.DataConflictInfo, 0, capacity), + indexNames: make([]string, 0, capacity), + handles: make([]tidbkv.Handle, 0, capacity), + rawHandles: make([][]byte, 0, capacity), } } @@ -110,27 +88,6 @@ func (indexHandles *pendingIndexHandles) append( indexHandles.rawHandles = append(indexHandles.rawHandles, rawHandle) } -// appendAt pushes `other[i]` to the end of indexHandles. -func (indexHandles *pendingIndexHandles) appendAt( - other *pendingIndexHandles, - i int, -) { - indexHandles.append( - other.dataConflictInfos[i], - other.indexNames[i], - other.handles[i], - other.rawHandles[i], - ) -} - -// extends concatenates `other` to the end of indexHandles. -func (indexHandles *pendingIndexHandles) extend(other *pendingIndexHandles) { - indexHandles.dataConflictInfos = append(indexHandles.dataConflictInfos, other.dataConflictInfos...) - indexHandles.indexNames = append(indexHandles.indexNames, other.indexNames...) - indexHandles.handles = append(indexHandles.handles, other.handles...) - indexHandles.rawHandles = append(indexHandles.rawHandles, other.rawHandles...) -} - // truncate resets all arrays in indexHandles to length zero, but keeping the allocated capacity. func (indexHandles *pendingIndexHandles) truncate() { indexHandles.dataConflictInfos = indexHandles.dataConflictInfos[:0] @@ -157,12 +114,85 @@ func (indexHandles *pendingIndexHandles) Swap(i, j int) { indexHandles.rawHandles[i], indexHandles.rawHandles[j] = indexHandles.rawHandles[j], indexHandles.rawHandles[i] } -// searchSortedRawHandle looks up for the index i such that `rawHandles[i] == rawHandle`. -// This function assumes indexHandles is already sorted, and rawHandle does exist in it. -func (indexHandles *pendingIndexHandles) searchSortedRawHandle(rawHandle []byte) int { - return sort.Search(indexHandles.Len(), func(i int) bool { - return bytes.Compare(indexHandles.rawHandles[i], rawHandle) >= 0 +type pendingKeyRange tidbkv.KeyRange + +func (kr pendingKeyRange) Less(other btree.Item) bool { + return bytes.Compare(kr.EndKey, other.(pendingKeyRange).EndKey) < 0 +} + +type pendingKeyRanges struct { + mu sync.Mutex + tree *btree.BTree +} + +func newPendingKeyRanges(keyRange tidbkv.KeyRange) *pendingKeyRanges { + tree := btree.New(32) + tree.ReplaceOrInsert(pendingKeyRange(keyRange)) + return &pendingKeyRanges{tree: tree} +} + +func (p *pendingKeyRanges) list() []tidbkv.KeyRange { + p.mu.Lock() + defer p.mu.Unlock() + + var keyRanges []tidbkv.KeyRange + p.tree.Ascend(func(item btree.Item) bool { + keyRanges = append(keyRanges, tidbkv.KeyRange(item.(pendingKeyRange))) + return true }) + return keyRanges +} + +func (p *pendingKeyRanges) empty() bool { + return p.tree.Len() == 0 +} + +func (p *pendingKeyRanges) finish(keyRange tidbkv.KeyRange) { + p.mu.Lock() + defer p.mu.Unlock() + + var ( + pendingAdd []btree.Item + pendingRemove []btree.Item + ) + startKey := keyRange.StartKey + endKey := keyRange.EndKey + p.tree.AscendGreaterOrEqual( + pendingKeyRange(tidbkv.KeyRange{EndKey: startKey}), + func(item btree.Item) bool { + kr := item.(pendingKeyRange) + if bytes.Compare(startKey, kr.EndKey) >= 0 { + return true + } + if bytes.Compare(endKey, kr.StartKey) <= 0 { + return false + } + pendingRemove = append(pendingRemove, kr) + if bytes.Compare(startKey, kr.StartKey) > 0 { + pendingAdd = append(pendingAdd, + pendingKeyRange(tidbkv.KeyRange{ + StartKey: kr.StartKey, + EndKey: startKey, + }), + ) + } + if bytes.Compare(endKey, kr.EndKey) < 0 { + pendingAdd = append(pendingAdd, + pendingKeyRange(tidbkv.KeyRange{ + StartKey: endKey, + EndKey: kr.EndKey, + }), + ) + } + return true + }, + ) + for _, item := range pendingRemove { + p.tree.Delete(item) + } + for _, item := range pendingAdd { + p.tree.ReplaceOrInsert(item) + } } // physicalTableIDs returns all physical table IDs associated with the tableInfo. @@ -180,645 +210,632 @@ func physicalTableIDs(tableInfo *model.TableInfo) []int64 { return []int64{tableInfo.ID} } -// NewDuplicateManager creates a new *DuplicateManager. -// -// This object provides methods to collect and decode duplicated KV pairs into row data. The results -// are stored into the errorMgr. -func NewDuplicateManager(local *local, ts uint64, opts *kv.SessionOptions) (*DuplicateManager, error) { - return &DuplicateManager{ - errorMgr: local.errorMgr, - tls: local.tls, - regionConcurrency: local.tcpConcurrency, - splitCli: local.splitCli, - tikvCli: local.tikvCli, - keyAdapter: duplicateKeyAdapter{}, - ts: ts, - connPool: common.NewGRPCConns(), - // TODO: not sure what is the correct concurrency value. - remoteWorkerPool: utils.NewWorkerPool(uint(local.tcpConcurrency), "duplicates"), - opts: opts, - }, nil -} - -// CollectDuplicateRowsFromTiKV collects duplicated rows already imported into TiKV. -// -// Collection result are saved into the ErrorManager. -func (manager *DuplicateManager) CollectDuplicateRowsFromTiKV( - ctx context.Context, - tbl table.Table, - tableName string, -) (hasDupe bool, err error) { - logTask := log.With(zap.String("table", tableName)).Begin(zapcore.InfoLevel, "collect duplicate data from remote TiKV") - defer func() { - logTask.End(zapcore.InfoLevel, err) - }() - - reqs, err := buildDuplicateRequests(tbl.Meta()) - if err != nil { - return false, err +// tableHandleKeyRanges returns all key ranges associated with the tableInfo. +func tableHandleKeyRanges(tableInfo *model.TableInfo) ([]tidbkv.KeyRange, error) { + ranges := ranger.FullIntRange(false) + if tableInfo.IsCommonHandle { + ranges = ranger.FullRange() } + tableIDs := physicalTableIDs(tableInfo) + return distsql.TableHandleRangesToKVRanges(nil, tableIDs, tableInfo.IsCommonHandle, ranges, nil) +} - // TODO: reuse the *kv.SessionOptions from NewEncoder for picking the correct time zone. - decoder, err := kv.NewTableKVDecoder(tbl, tableName, manager.opts) - if err != nil { - return false, err - } - g, rpcctx := errgroup.WithContext(ctx) - atomicHasDupe := atomic.NewBool(false) - for _, r := range reqs { - req := r - manager.remoteWorkerPool.ApplyOnErrorGroup(g, func() error { - err := manager.sendRequestToTiKV(rpcctx, decoder, req, atomicHasDupe) - if err != nil { - log.L().Error("error occur when collect duplicate data from TiKV", zap.Error(err)) - } - return err - }) +// tableIndexKeyRanges returns all key ranges associated with the tableInfo and indexInfo. +func tableIndexKeyRanges(tableInfo *model.TableInfo, indexInfo *model.IndexInfo) ([]tidbkv.KeyRange, error) { + tableIDs := physicalTableIDs(tableInfo) + var keyRanges []tidbkv.KeyRange + for _, tid := range tableIDs { + partitionKeysRanges, err := distsql.IndexRangesToKVRanges(nil, tid, indexInfo.ID, ranger.FullRange(), nil) + if err != nil { + return nil, errors.Trace(err) + } + keyRanges = append(keyRanges, partitionKeysRanges...) } - err = errors.Trace(g.Wait()) - return atomicHasDupe.Load(), err + return keyRanges, nil } -func (manager *DuplicateManager) sendRequestToTiKV(ctx context.Context, - decoder *kv.TableKVDecoder, - req *DuplicateRequest, - hasDupe *atomic.Bool, -) error { - logger := log.With( - zap.String("table", decoder.Name()), - zap.Int64("tableID", req.tableID), - logutil.Key("startKey", req.start), - logutil.Key("endKey", req.end)) +// DupKVStream is a streaming interface for collecting duplicate key-value pairs. +type DupKVStream interface { + // Next returns the next key-value pair or any error it encountered. + // At the end of the stream, the error is io.EOF. + Next() (key, val []byte, err error) + // Close closes the stream. + Close() error +} - startKey := codec.EncodeBytes([]byte{}, req.start) - endKey := codec.EncodeBytes([]byte{}, req.end) +// LocalDupKVStream implements the interface of DupKVStream. +// It collects duplicate key-value pairs from a pebble.DB. +//goland:noinspection GoNameStartsWithPackageName +type LocalDupKVStream struct { + iter Iter +} - regions, err := restore.PaginateScanRegion(ctx, manager.splitCli, startKey, endKey, scanRegionLimit) - if err != nil { - return err +// NewLocalDupKVStream creates a new LocalDupKVStream with the given duplicate db and key range. +func NewLocalDupKVStream(dupDB *pebble.DB, keyAdapter KeyAdapter, keyRange tidbkv.KeyRange) *LocalDupKVStream { + opts := &pebble.IterOptions{ + LowerBound: keyRange.StartKey, + UpperBound: keyRange.EndKey, } - tryTimes := 0 - indexHandles := makePendingIndexHandlesWithCapacity(0) - for len(regions) > 0 { - if tryTimes > maxRetryTimes { - return errors.Errorf("retry time exceed limit") - } - unfinishedRegions := make([]*restore.RegionInfo, 0) - waitingClients := make([]import_sstpb.ImportSST_DuplicateDetectClient, 0) - watingRegions := make([]*restore.RegionInfo, 0) - for idx, region := range regions { - if len(waitingClients) > manager.regionConcurrency { - r := regions[idx:] - unfinishedRegions = append(unfinishedRegions, r...) - break - } - _, start, _ := codec.DecodeBytes(region.Region.StartKey, []byte{}) - _, end, _ := codec.DecodeBytes(region.Region.EndKey, []byte{}) - if bytes.Compare(startKey, region.Region.StartKey) > 0 { - start = req.start - } - if region.Region.EndKey == nil || len(region.Region.EndKey) == 0 || bytes.Compare(endKey, region.Region.EndKey) < 0 { - end = req.end - } - - logger.Debug("[detect-dupe] get duplicate stream", - zap.Int("localStreamID", idx), - logutil.Region(region.Region), - logutil.Leader(region.Leader), - logutil.Key("regionStartKey", start), - logutil.Key("regionEndKey", end)) - cli, err := manager.getDuplicateStream(ctx, region, start, end) - if err != nil { - r, err := manager.splitCli.GetRegionByID(ctx, region.Region.GetId()) - if err != nil { - unfinishedRegions = append(unfinishedRegions, region) - } else { - unfinishedRegions = append(unfinishedRegions, r) - } - } else { - waitingClients = append(waitingClients, cli) - watingRegions = append(watingRegions, region) - } - } + iter := newDupDBIter(dupDB, keyAdapter, opts) + iter.First() + return &LocalDupKVStream{iter: iter} +} - if indexHandles.Len() > 0 { - handles := manager.getValues(ctx, decoder, indexHandles) - if handles.Len() > 0 { - indexHandles = handles - } else { - indexHandles.truncate() - } +func (s *LocalDupKVStream) Next() (key, val []byte, err error) { + if !s.iter.Valid() { + err = s.iter.Error() + if err == nil { + err = io.EOF } + return + } + key = append(key, s.iter.Key()...) + val = append(val, s.iter.Value()...) + s.iter.Next() + return +} - for idx, cli := range waitingClients { - region := watingRegions[idx] - cliLogger := logger.With( - zap.Int("localStreamID", idx), - logutil.Region(region.Region), - logutil.Leader(region.Leader)) - for { - resp, reqErr := cli.Recv() - hasErr := false - if reqErr != nil { - if errors.Cause(reqErr) == io.EOF { - cliLogger.Debug("[detect-dupe] exhausted duplication stream") - break - } - hasErr = true - } - - if hasErr || resp.GetKeyError() != nil { - r, err := manager.splitCli.GetRegionByID(ctx, region.Region.GetId()) - if err != nil { - unfinishedRegions = append(unfinishedRegions, region) - } else { - unfinishedRegions = append(unfinishedRegions, r) - } - } - if hasErr { - cliLogger.Warn("[detect-dupe] meet error when recving duplicate detect response from TiKV, retry again", - zap.Error(reqErr)) - break - } - if resp.GetKeyError() != nil { - cliLogger.Warn("[detect-dupe] meet key error in duplicate detect response from TiKV, retry again ", - zap.String("KeyError", resp.GetKeyError().GetMessage())) - break - } +func (s *LocalDupKVStream) Close() error { + return s.iter.Close() +} - if resp.GetRegionError() != nil { - cliLogger.Warn("[detect-dupe] meet key error in duplicate detect response from TiKV, retry again ", - zap.String("RegionError", resp.GetRegionError().GetMessage())) - - r, err := restore.PaginateScanRegion(ctx, manager.splitCli, watingRegions[idx].Region.GetStartKey(), watingRegions[idx].Region.GetEndKey(), scanRegionLimit) - if err != nil { - unfinishedRegions = append(unfinishedRegions, watingRegions[idx]) - } else { - unfinishedRegions = append(unfinishedRegions, r...) - } - break - } +type regionError struct { + inner *errorpb.Error +} - if len(resp.Pairs) > 0 { - hasDupe.Store(true) - } +func (r regionError) Error() string { + return r.inner.String() +} - handles, err := manager.storeDuplicateData(ctx, resp, decoder, req) - if err != nil { - return err - } - if handles.Len() > 0 { - indexHandles.extend(&handles) - } - } - } +// RemoteDupKVStream implements the interface of DupKVStream. +// It collects duplicate key-value pairs from a TiKV region. +type RemoteDupKVStream struct { + cli import_sstpb.ImportSST_DuplicateDetectClient + kvs []*import_sstpb.KvPair + atEOF bool + cancel context.CancelFunc +} - // it means that all the regions sent to TiKV fail, so we must sleep for a while to avoid retrying too frequently. - if len(unfinishedRegions) == len(regions) { - tryTimes += 1 - time.Sleep(defaultRetryBackoffTime) - } - regions = unfinishedRegions +func getDupDetectClient( + ctx context.Context, + region *restore.RegionInfo, + keyRange tidbkv.KeyRange, + importClientFactory ImportClientFactory, +) (import_sstpb.ImportSST_DuplicateDetectClient, error) { + leader := region.Leader + if leader == nil { + leader = region.Region.GetPeers()[0] } - return nil + importClient, err := importClientFactory.Create(ctx, leader.GetStoreId()) + if err != nil { + return nil, errors.Trace(err) + } + reqCtx := &kvrpcpb.Context{ + RegionId: region.Region.GetId(), + RegionEpoch: region.Region.GetRegionEpoch(), + Peer: leader, + } + req := &import_sstpb.DuplicateDetectRequest{ + Context: reqCtx, + StartKey: keyRange.StartKey, + EndKey: keyRange.EndKey, + } + cli, err := importClient.DuplicateDetect(ctx, req) + if err != nil { + return nil, errors.Trace(err) + } + return cli, nil } -func (manager *DuplicateManager) storeDuplicateData( +// NewRemoteDupKVStream creates a new RemoteDupKVStream. +func NewRemoteDupKVStream( ctx context.Context, - resp *import_sstpb.DuplicateDetectResponse, - decoder *kv.TableKVDecoder, - req *DuplicateRequest, -) (pendingIndexHandles, error) { - var err error - var dataConflictInfos []errormanager.DataConflictInfo - indexHandles := makePendingIndexHandlesWithCapacity(len(resp.Pairs)) - - loggerIndexName := "PRIMARY" - if req.indexInfo != nil { - loggerIndexName = req.indexInfo.Name.O + region *restore.RegionInfo, + keyRange tidbkv.KeyRange, + importClientFactory ImportClientFactory, +) (*RemoteDupKVStream, error) { + subCtx, cancel := context.WithCancel(ctx) + cli, err := getDupDetectClient(subCtx, region, keyRange, importClientFactory) + if err != nil { + cancel() + return nil, errors.Trace(err) } - superLogger := log.With( - zap.String("table", decoder.Name()), - zap.Int64("tableID", req.tableID), - zap.String("index", loggerIndexName)) - - for _, kv := range resp.Pairs { - logger := superLogger.With( - logutil.Key("key", kv.Key), logutil.Key("value", kv.Value), - zap.Uint64("commit-ts", kv.CommitTs)) + s := &RemoteDupKVStream{cli: cli, cancel: cancel} + // call tryRecv to see if there are some region errors. + if err := s.tryRecv(); err != nil && errors.Cause(err) != io.EOF { + cancel() + return nil, errors.Trace(err) + } + return s, nil +} - var h tidbkv.Handle - if req.indexInfo != nil { - h, err = decoder.DecodeHandleFromIndex(req.indexInfo, kv.Key, kv.Value) - } else { - h, err = decoder.DecodeHandleFromTable(kv.Key) - } - if err != nil { - logger.Error("decode handle error", log.ShortError(err)) - continue +func (s *RemoteDupKVStream) tryRecv() error { + resp, err := s.cli.Recv() + if err != nil { + if errors.Cause(err) == io.EOF { + s.atEOF = true + err = io.EOF } - logger.Debug("[detect-dupe] remote dupe response", - logutil.Redact(zap.Stringer("handle", h))) + return err + } + if resp.RegionError != nil { + return errors.Cause(regionError{inner: resp.RegionError}) + } + if resp.KeyError != nil { + return errors.Errorf("meet key error in duplicate detect response: %s", resp.KeyError.Message) + } + s.kvs = resp.Pairs + return nil +} - conflictInfo := errormanager.DataConflictInfo{ - RawKey: kv.Key, - RawValue: kv.Value, - KeyData: h.String(), +func (s *RemoteDupKVStream) Next() (key, val []byte, err error) { + for len(s.kvs) == 0 { + if s.atEOF { + return nil, nil, io.EOF } - - if req.indexInfo != nil { - indexHandles.append( - conflictInfo, - req.indexInfo.Name.O, - h, decoder.EncodeHandleKey(req.tableID, h)) - } else { - conflictInfo.Row = decoder.DecodeRawRowDataAsStr(h, kv.Value) - dataConflictInfos = append(dataConflictInfos, conflictInfo) + if err := s.tryRecv(); err != nil { + return nil, nil, errors.Trace(err) } } + key, val = s.kvs[0].Key, s.kvs[0].Value + s.kvs = s.kvs[1:] + return +} - err = manager.errorMgr.RecordDataConflictError(ctx, log.L(), decoder.Name(), dataConflictInfos) - if err != nil { - return indexHandles, err - } +func (s *RemoteDupKVStream) Close() error { + s.cancel() + return nil +} - if len(indexHandles.dataConflictInfos) == 0 { - return indexHandles, nil - } - return manager.getValues(ctx, decoder, indexHandles), nil +// DuplicateManager provides methods to collect and decode duplicated KV pairs into row data. The results +// are stored into the errorMgr. +type DuplicateManager struct { + tbl table.Table + tableName string + splitCli restore.SplitClient + tikvCli *tikv.KVStore + errorMgr *errormanager.ErrorManager + decoder *kv.TableKVDecoder + logger log.Logger + concurrency int + hasDupe *atomic.Bool } -// CollectDuplicateRowsFromLocalIndex collects rows by read the index in db. -func (manager *DuplicateManager) CollectDuplicateRowsFromLocalIndex( - ctx context.Context, +// NewDuplicateManager creates a new DuplicateManager. +func NewDuplicateManager( tbl table.Table, tableName string, - db *pebble.DB, -) (bool, error) { - // TODO: reuse the *kv.SessionOptions from NewEncoder for picking the correct time zone. - decoder, err := kv.NewTableKVDecoder(tbl, tableName, manager.opts) + splitCli restore.SplitClient, + tikvCli *tikv.KVStore, + errMgr *errormanager.ErrorManager, + sessOpts *kv.SessionOptions, + concurrency int, + hasDupe *atomic.Bool, +) (*DuplicateManager, error) { + decoder, err := kv.NewTableKVDecoder(tbl, tableName, sessOpts) if err != nil { - return false, errors.Trace(err) + return nil, errors.Trace(err) } + logger := log.With(zap.String("tableName", tableName)) + return &DuplicateManager{ + tbl: tbl, + tableName: tableName, + splitCli: splitCli, + tikvCli: tikvCli, + errorMgr: errMgr, + decoder: decoder, + logger: logger, + concurrency: concurrency, + hasDupe: hasDupe, + }, nil +} - logger := log.With(zap.String("table", tableName)) - - allRanges := make([]tidbkv.KeyRange, 0) - tableIDs := physicalTableIDs(tbl.Meta()) - // Collect row handle duplicates. +// RecordDataConflictError records data conflicts to errorMgr. The key received from stream must be a row key. +func (m *DuplicateManager) RecordDataConflictError(ctx context.Context, stream DupKVStream) error { + defer stream.Close() var dataConflictInfos []errormanager.DataConflictInfo - hasDataConflict := false - { - ranges := ranger.FullIntRange(false) - if tbl.Meta().IsCommonHandle { - ranges = ranger.FullRange() + for { + key, val, err := stream.Next() + if errors.Cause(err) == io.EOF { + break } - keyRanges, err := distsql.TableHandleRangesToKVRanges(nil, tableIDs, tbl.Meta().IsCommonHandle, ranges, nil) if err != nil { - return false, errors.Trace(err) + return errors.Trace(err) } - allRanges = append(allRanges, keyRanges...) - for _, r := range keyRanges { - logger.Debug("[detect-dupe] collect local range", - logutil.Key("startKey", r.StartKey), - logutil.Key("endKey", r.EndKey)) - startKey := codec.EncodeBytes([]byte{}, r.StartKey) - endKey := codec.EncodeBytes([]byte{}, r.EndKey) - opts := &pebble.IterOptions{ - LowerBound: startKey, - UpperBound: endKey, - } + m.hasDupe.Store(true) - if err := func() error { - iter := db.NewIter(opts) - defer iter.Close() - - for iter.First(); iter.Valid(); iter.Next() { - hasDataConflict = true - rawKey, _, _, err := manager.keyAdapter.Decode(nil, iter.Key()) - if err != nil { - return err - } - rawValue := make([]byte, len(iter.Value())) - copy(rawValue, iter.Value()) - - h, err := decoder.DecodeHandleFromTable(rawKey) - if err != nil { - return err - } - logger.Debug("[detect-dupe] found local data conflict", - logutil.Key("key", rawKey), - logutil.Key("value", rawValue), - logutil.Redact(zap.Stringer("handle", h))) - - conflictInfo := errormanager.DataConflictInfo{ - RawKey: rawKey, - RawValue: rawValue, - KeyData: h.String(), - Row: decoder.DecodeRawRowDataAsStr(h, rawValue), - } - dataConflictInfos = append(dataConflictInfos, conflictInfo) - } - if err := iter.Error(); err != nil { - return err - } - if err := manager.errorMgr.RecordDataConflictError(ctx, log.L(), decoder.Name(), dataConflictInfos); err != nil { - return err - } - dataConflictInfos = dataConflictInfos[:0] - return nil - }(); err != nil { - return false, errors.Trace(err) - } - db.DeleteRange(startKey, endKey, &pebble.WriteOptions{Sync: false}) - } - } - handles := makePendingIndexHandlesWithCapacity(0) - for _, indexInfo := range tbl.Meta().Indices { - if indexInfo.State != model.StatePublic { - continue + h, err := m.decoder.DecodeHandleFromRowKey(key) + if err != nil { + return errors.Trace(err) } - ranges := ranger.FullRange() - var keysRanges []tidbkv.KeyRange - for _, id := range tableIDs { - partitionKeysRanges, err := distsql.IndexRangesToKVRanges(nil, id, indexInfo.ID, ranges, nil) - if err != nil { - return false, err - } - keysRanges = append(keysRanges, partitionKeysRanges...) + conflictInfo := errormanager.DataConflictInfo{ + RawKey: key, + RawValue: val, + KeyData: h.String(), + Row: m.decoder.DecodeRawRowDataAsStr(h, val), } - allRanges = append(allRanges, keysRanges...) - for _, r := range keysRanges { - tableID := tablecodec.DecodeTableID(r.StartKey) - startKey := codec.EncodeBytes([]byte{}, r.StartKey) - endKey := codec.EncodeBytes([]byte{}, r.EndKey) - opts := &pebble.IterOptions{ - LowerBound: startKey, - UpperBound: endKey, - } - indexLogger := logger.With( - zap.Int64("tableID", tableID), - zap.String("index", indexInfo.Name.O), - zap.Int64("indexID", indexInfo.ID), - logutil.Key("startKey", startKey), - logutil.Key("endKey", endKey)) - indexLogger.Info("[detect-dupe] collect index from db") - - if err := func() error { - iter := db.NewIter(opts) - defer iter.Close() - - for iter.First(); iter.Valid(); iter.Next() { - hasDataConflict = true - rawKey, _, _, err := manager.keyAdapter.Decode(nil, iter.Key()) - if err != nil { - indexLogger.Error( - "[detect-dupe] decode key error when query handle for duplicate index", - zap.Binary("key", iter.Key()), - ) - return err - } - rawValue := make([]byte, len(iter.Value())) - copy(rawValue, iter.Value()) - h, err := decoder.DecodeHandleFromIndex(indexInfo, rawKey, rawValue) - if err != nil { - indexLogger.Error("[detect-dupe] decode handle error from index for duplicatedb", - zap.Error(err), logutil.Key("rawKey", rawKey), - logutil.Key("value", rawValue)) - return err - } - indexLogger.Debug("[detect-dupe] found local index conflict, stashing", - logutil.Key("key", rawKey), - logutil.Key("value", rawValue), - logutil.Redact(zap.Stringer("handle", h))) - handles.append( - errormanager.DataConflictInfo{ - RawKey: rawKey, - RawValue: rawValue, - KeyData: h.String(), - }, - indexInfo.Name.O, - h, - decoder.EncodeHandleKey(tableID, h)) - if handles.Len() > maxGetRequestKeyCount { - handles = manager.getValues(ctx, decoder, handles) - } - } - if handles.Len() > 0 { - handles = manager.getValues(ctx, decoder, handles) - } - if handles.Len() == 0 { - db.DeleteRange(startKey, endKey, &pebble.WriteOptions{Sync: false}) - } - return nil - }(); err != nil { - return false, errors.Trace(err) + dataConflictInfos = append(dataConflictInfos, conflictInfo) + if len(dataConflictInfos) >= defaultRecordConflictErrorBatch { + if err := m.errorMgr.RecordDataConflictError(ctx, m.logger, m.tableName, dataConflictInfos); err != nil { + return errors.Trace(err) } + dataConflictInfos = dataConflictInfos[:0] } } - - for i := 0; i < maxRetryTimes && handles.Len() > 0; i++ { - handles = manager.getValues(ctx, decoder, handles) - } - if handles.Len() > 0 { - return false, errors.Errorf("retry getValues time exceed limit") - } - for _, r := range allRanges { - startKey := codec.EncodeBytes([]byte{}, r.StartKey) - endKey := codec.EncodeBytes([]byte{}, r.EndKey) - db.DeleteRange(startKey, endKey, &pebble.WriteOptions{Sync: false}) + if len(dataConflictInfos) > 0 { + if err := m.errorMgr.RecordDataConflictError(ctx, m.logger, m.tableName, dataConflictInfos); err != nil { + return errors.Trace(err) + } } - return hasDataConflict, nil + return nil } -func (manager *DuplicateManager) getValues( - ctx context.Context, - decoder *kv.TableKVDecoder, - handles pendingIndexHandles, -) pendingIndexHandles { - var finalErr error - logger := log.With( - zap.String("table", decoder.Name()), - zap.Int("handlesCount", handles.Len()), - ).Begin(zap.DebugLevel, "[detect-dupe] collect values from TiKV") - defer func() { - logger.End(zap.ErrorLevel, finalErr) - }() - - // TODO: paginate the handles. - snapshot := manager.tikvCli.GetSnapshot(math.MaxUint64) +func (m *DuplicateManager) saveIndexHandles(ctx context.Context, handles pendingIndexHandles) error { + snapshot := m.tikvCli.GetSnapshot(math.MaxUint64) batchGetMap, err := snapshot.BatchGet(ctx, handles.rawHandles) if err != nil { - finalErr = err - return handles + return errors.Trace(err) } - retryHandles := makePendingIndexHandlesWithCapacity(0) - batch := makePendingIndexHandlesWithCapacity(handles.Len()) - rawRows := make([][]byte, 0, handles.Len()) + rawRows := make([][]byte, handles.Len()) for i, rawHandle := range handles.rawHandles { - rawValue, ok := batchGetMap[string(rawHandle)] + rawValue, ok := batchGetMap[string(hack.String(rawHandle))] if ok { - logger.Debug("[detect-dupe] retrieved value from TiKV", - logutil.Key("rawHandle", rawHandle), - logutil.Key("row", rawValue)) - rawRows = append(rawRows, rawValue) - handles.dataConflictInfos[i].Row = decoder.DecodeRawRowDataAsStr(handles.handles[i], rawValue) - batch.appendAt(&handles, i) + rawRows[i] = rawValue + handles.dataConflictInfos[i].Row = m.decoder.DecodeRawRowDataAsStr(handles.handles[i], rawValue) } else { - logger.Warn("[detect-dupe] missing value from TiKV, will retry", + m.logger.Warn("[detect-dupe] can not found row data corresponding to the handle", logutil.Key("rawHandle", rawHandle)) - retryHandles.appendAt(&handles, i) } } - finalErr = manager.errorMgr.RecordIndexConflictError( - ctx, log.L(), - decoder.Name(), - batch.indexNames, - batch.dataConflictInfos, - batch.rawHandles, - rawRows) - if finalErr != nil { - return handles - } - - return retryHandles + err = m.errorMgr.RecordIndexConflictError(ctx, m.logger, m.tableName, + handles.indexNames, handles.dataConflictInfos, handles.rawHandles, rawRows) + return errors.Trace(err) } -func (manager *DuplicateManager) getDuplicateStream(ctx context.Context, - region *restore.RegionInfo, - start []byte, end []byte) (import_sstpb.ImportSST_DuplicateDetectClient, error) { - leader := region.Leader - if leader == nil { - leader = region.Region.GetPeers()[0] - } +// RecordIndexConflictError records index conflicts to errorMgr. The key received from stream must be an index key. +func (m *DuplicateManager) RecordIndexConflictError(ctx context.Context, stream DupKVStream, tableID int64, indexInfo *model.IndexInfo) error { + defer stream.Close() + indexHandles := makePendingIndexHandlesWithCapacity(0) + for { + key, val, err := stream.Next() + if errors.Cause(err) == io.EOF { + break + } + if err != nil { + return errors.Trace(err) + } + m.hasDupe.Store(true) - cli, err := manager.getImportClient(ctx, leader) - if err != nil { - return nil, err - } + h, err := m.decoder.DecodeHandleFromIndex(indexInfo, key, val) + if err != nil { + return errors.Trace(err) + } + conflictInfo := errormanager.DataConflictInfo{ + RawKey: key, + RawValue: val, + KeyData: h.String(), + } + indexHandles.append(conflictInfo, indexInfo.Name.O, + h, tablecodec.EncodeRowKeyWithHandle(tableID, h)) - reqCtx := &kvrpcpb.Context{ - RegionId: region.Region.GetId(), - RegionEpoch: region.Region.GetRegionEpoch(), - Peer: leader, + if indexHandles.Len() >= defaultRecordConflictErrorBatch { + if err := m.saveIndexHandles(ctx, indexHandles); err != nil { + return errors.Trace(err) + } + indexHandles.truncate() + } } - req := &import_sstpb.DuplicateDetectRequest{ - Context: reqCtx, - StartKey: start, - EndKey: end, - KeyOnly: false, + if indexHandles.Len() > 0 { + if err := m.saveIndexHandles(ctx, indexHandles); err != nil { + return errors.Trace(err) + } } - stream, err := cli.DuplicateDetect(ctx, req) - return stream, err + return nil } -func (manager *DuplicateManager) getImportClient(ctx context.Context, peer *metapb.Peer) (import_sstpb.ImportSSTClient, error) { - conn, err := manager.connPool.GetGrpcConn(ctx, peer.GetStoreId(), 1, func(ctx context.Context) (*grpc.ClientConn, error) { - return manager.makeConn(ctx, peer.GetStoreId()) - }) - if err != nil { - return nil, err - } - return import_sstpb.NewImportSSTClient(conn), nil +type dupTask struct { + tidbkv.KeyRange + tableID int64 + indexInfo *model.IndexInfo } -func (manager *DuplicateManager) makeConn(ctx context.Context, storeID uint64) (*grpc.ClientConn, error) { - store, err := manager.splitCli.GetStore(ctx, storeID) +func (m *DuplicateManager) buildDupTasks() ([]dupTask, error) { + keyRanges, err := tableHandleKeyRanges(m.tbl.Meta()) if err != nil { return nil, errors.Trace(err) } - opt := grpc.WithInsecure() - if manager.tls.TLSConfig() != nil { - opt = grpc.WithTransportCredentials(credentials.NewTLS(manager.tls.TLSConfig())) - } - ctx, cancel := context.WithTimeout(ctx, dialTimeout) - - bfConf := backoff.DefaultConfig - bfConf.MaxDelay = gRPCBackOffMaxDelay - // we should use peer address for tiflash. for tikv, peer address is empty - addr := store.GetPeerAddress() - if addr == "" { - addr = store.GetAddress() - } - conn, err := grpc.DialContext( - ctx, - addr, - opt, - grpc.WithConnectParams(grpc.ConnectParams{Backoff: bfConf}), - grpc.WithKeepaliveParams(keepalive.ClientParameters{ - Time: gRPCKeepAliveTime, - Timeout: gRPCKeepAliveTimeout, - PermitWithoutStream: true, - }), - ) - cancel() + tasks := make([]dupTask, 0, len(keyRanges)) + for _, kr := range keyRanges { + tableID := tablecodec.DecodeTableID(kr.StartKey) + tasks = append(tasks, dupTask{ + KeyRange: kr, + tableID: tableID, + }) + } + for _, indexInfo := range m.tbl.Meta().Indices { + if indexInfo.State != model.StatePublic { + continue + } + keyRanges, err = tableIndexKeyRanges(m.tbl.Meta(), indexInfo) + if err != nil { + return nil, errors.Trace(err) + } + for _, kr := range keyRanges { + tableID := tablecodec.DecodeTableID(kr.StartKey) + tasks = append(tasks, dupTask{ + KeyRange: kr, + tableID: tableID, + indexInfo: indexInfo, + }) + } + } + return tasks, nil +} + +func (m *DuplicateManager) splitLocalDupTaskByKeys( + task dupTask, + dupDB *pebble.DB, + keyAdapter KeyAdapter, + sizeLimit int64, + keysLimit int64, +) ([]dupTask, error) { + sizeProps, err := getSizeProperties(m.logger, dupDB, keyAdapter) if err != nil { return nil, errors.Trace(err) } - return conn, nil + ranges := splitRangeBySizeProps(Range{start: task.StartKey, end: task.EndKey}, sizeProps, sizeLimit, keysLimit) + newDupTasks := make([]dupTask, 0, len(ranges)) + for _, r := range ranges { + newDupTasks = append(newDupTasks, dupTask{ + KeyRange: tidbkv.KeyRange{ + StartKey: r.start, + EndKey: r.end, + }, + tableID: task.tableID, + indexInfo: task.indexInfo, + }) + } + return newDupTasks, nil } -func buildDuplicateRequests(tableInfo *model.TableInfo) ([]*DuplicateRequest, error) { - var reqs []*DuplicateRequest - for _, id := range physicalTableIDs(tableInfo) { - tableReqs, err := buildTableRequests(id, tableInfo.IsCommonHandle) +func (m *DuplicateManager) buildLocalDupTasks(dupDB *pebble.DB, keyAdapter KeyAdapter) ([]dupTask, error) { + tasks, err := m.buildDupTasks() + if err != nil { + return nil, errors.Trace(err) + } + var newTasks []dupTask + for _, task := range tasks { + // FIXME: Do not hardcode sizeLimit and keysLimit. + subTasks, err := m.splitLocalDupTaskByKeys(task, dupDB, keyAdapter, 32*units.MiB, 1*units.MiB) if err != nil { return nil, errors.Trace(err) } - reqs = append(reqs, tableReqs...) - for _, indexInfo := range tableInfo.Indices { - if indexInfo.State != model.StatePublic { - continue + newTasks = append(newTasks, subTasks...) + } + return newTasks, nil +} + +// CollectDuplicateRowsFromDupDB collects duplicates from the duplicate DB and records all duplicate row info into errorMgr. +func (m *DuplicateManager) CollectDuplicateRowsFromDupDB(ctx context.Context, dupDB *pebble.DB, keyAdapter KeyAdapter) error { + tasks, err := m.buildLocalDupTasks(dupDB, keyAdapter) + if err != nil { + return errors.Trace(err) + } + logger := m.logger + logger.Info("[detect-dupe] collect duplicate rows from local duplicate db", zap.Int("tasks", len(tasks))) + + pool := utils.NewWorkerPool(uint(m.concurrency), "collect duplicate rows from duplicate db") + g, gCtx := errgroup.WithContext(ctx) + for _, task := range tasks { + task := task + pool.ApplyOnErrorGroup(g, func() error { + if err := common.Retry("collect local duplicate rows", logger, func() error { + stream := NewLocalDupKVStream(dupDB, keyAdapter, task.KeyRange) + var err error + if task.indexInfo == nil { + err = m.RecordDataConflictError(gCtx, stream) + } else { + err = m.RecordIndexConflictError(gCtx, stream, task.tableID, task.indexInfo) + } + return errors.Trace(err) + }); err != nil { + return errors.Trace(err) + } + + // Delete the key range in duplicate DB since we have the duplicates have been collected. + rawStartKey := keyAdapter.Encode(nil, task.StartKey, math.MinInt64) + rawEndKey := keyAdapter.Encode(nil, task.EndKey, math.MinInt64) + err = dupDB.DeleteRange(rawStartKey, rawEndKey, nil) + return errors.Trace(err) + }) + } + return errors.Trace(g.Wait()) +} + +func (m *DuplicateManager) splitKeyRangeByRegions( + ctx context.Context, keyRange tidbkv.KeyRange, +) ([]*restore.RegionInfo, []tidbkv.KeyRange, error) { + rawStartKey := codec.EncodeBytes(nil, keyRange.StartKey) + rawEndKey := codec.EncodeBytes(nil, keyRange.EndKey) + allRegions, err := restore.PaginateScanRegion(ctx, m.splitCli, rawStartKey, rawEndKey, 1024) + if err != nil { + return nil, nil, errors.Trace(err) + } + regions := make([]*restore.RegionInfo, 0, len(allRegions)) + keyRanges := make([]tidbkv.KeyRange, 0, len(allRegions)) + for _, region := range allRegions { + startKey := keyRange.StartKey + endKey := keyRange.EndKey + if len(region.Region.StartKey) > 0 { + _, regionStartKey, err := codec.DecodeBytes(region.Region.StartKey, nil) + if err != nil { + return nil, nil, errors.Trace(err) + } + if bytes.Compare(startKey, regionStartKey) < 0 { + startKey = regionStartKey } - indexReqs, err := buildIndexRequests(id, indexInfo) + } + if len(region.Region.EndKey) > 0 { + _, regionEndKey, err := codec.DecodeBytes(region.Region.EndKey, nil) if err != nil { - return nil, errors.Trace(err) + return nil, nil, errors.Trace(err) + } + if bytes.Compare(endKey, regionEndKey) > 0 { + endKey = regionEndKey } - reqs = append(reqs, indexReqs...) + } + if bytes.Compare(startKey, endKey) < 0 { + regions = append(regions, region) + keyRanges = append(keyRanges, tidbkv.KeyRange{ + StartKey: startKey, + EndKey: endKey, + }) } } - return reqs, nil + return regions, keyRanges, nil } -func buildTableRequests(tableID int64, isCommonHandle bool) ([]*DuplicateRequest, error) { - ranges := ranger.FullIntRange(false) - if isCommonHandle { - ranges = ranger.FullRange() +func (m *DuplicateManager) processRemoteDupTaskOnce( + ctx context.Context, + task dupTask, + logger log.Logger, + importClientFactory ImportClientFactory, + regionPool *utils.WorkerPool, + remainKeyRanges *pendingKeyRanges, +) (madeProgress bool, err error) { + var ( + regions []*restore.RegionInfo + keyRanges []tidbkv.KeyRange + ) + for _, kr := range remainKeyRanges.list() { + subRegions, subKeyRanges, err := m.splitKeyRangeByRegions(ctx, kr) + if err != nil { + return false, errors.Trace(err) + } + regions = append(regions, subRegions...) + keyRanges = append(keyRanges, subKeyRanges...) } - keysRanges, err := distsql.TableHandleRangesToKVRanges(nil, []int64{tableID}, isCommonHandle, ranges, nil) - if err != nil { - return nil, errors.Trace(err) + + var metErr common.OnceError + wg := &sync.WaitGroup{} + atomicMadeProgress := atomic.NewBool(false) + for i := 0; i < len(regions); i++ { + if ctx.Err() != nil { + metErr.Set(ctx.Err()) + break + } + region := regions[i] + kr := keyRanges[i] + wg.Add(1) + regionPool.Apply(func() { + defer wg.Done() + + logger := logger.With( + zap.Uint64("regionID", region.Region.Id), + logutil.Key("dupDetectStartKey", kr.StartKey), + logutil.Key("dupDetectEndKey", kr.EndKey), + ) + err := func() error { + stream, err := NewRemoteDupKVStream(ctx, region, kr, importClientFactory) + if err != nil { + return errors.Annotatef(err, "failed to create remote duplicate kv stream") + } + if task.indexInfo == nil { + err = m.RecordDataConflictError(ctx, stream) + } else { + err = m.RecordIndexConflictError(ctx, stream, task.tableID, task.indexInfo) + } + if err != nil { + return errors.Annotatef(err, "failed to record conflict errors") + } + return nil + }() + if err != nil { + if regionErr, ok := errors.Cause(err).(regionError); ok { + logger.Debug("[detect-dupe] collect duplicate rows from region failed due to region error", zap.Error(regionErr)) + } else { + logger.Warn("[detect-dupe] collect duplicate rows from region failed", log.ShortError(err)) + } + metErr.Set(err) + } else { + logger.Debug("[detect-dupe] collect duplicate rows from region completed") + remainKeyRanges.finish(kr) + atomicMadeProgress.Store(true) + } + }) } - reqs := make([]*DuplicateRequest, 0) - for _, r := range keysRanges { - req := &DuplicateRequest{ - start: r.StartKey, - end: r.EndKey, - tableID: tableID, - indexInfo: nil, + wg.Wait() + return atomicMadeProgress.Load(), errors.Trace(metErr.Get()) +} + +// processRemoteDupTask processes a remoteDupTask. A task contains a key range. +// A key range is associated with multiple regions. processRemoteDupTask tries +// to collect duplicates from each region. +func (m *DuplicateManager) processRemoteDupTask( + ctx context.Context, + task dupTask, + logger log.Logger, + importClientFactory ImportClientFactory, + regionPool *utils.WorkerPool, +) error { + remainAttempts := maxDupCollectAttemptTimes + remainKeyRanges := newPendingKeyRanges(task.KeyRange) + for { + madeProgress, err := m.processRemoteDupTaskOnce(ctx, task, logger, importClientFactory, regionPool, remainKeyRanges) + if err == nil { + if !remainKeyRanges.empty() { + remainKeyRanges.list() + logger.Panic("[detect-dupe] there are still some key ranges that haven't been processed, which is unexpected", + zap.Any("remainKeyRanges", remainKeyRanges.list())) + } + return nil + } + if log.IsContextCanceledError(err) { + return errors.Trace(err) } - reqs = append(reqs, req) + if !madeProgress { + remainAttempts-- + if remainAttempts <= 0 { + logger.Error("[detect-dupe] all attempts to process the remote dupTask have failed", log.ShortError(err)) + return errors.Trace(err) + } + } + logger.Warn("[detect-dupe] process remote dupTask encounters error, retrying", + log.ShortError(err), zap.Int("remainAttempts", remainAttempts)) } - return reqs, nil } -func buildIndexRequests(tableID int64, indexInfo *model.IndexInfo) ([]*DuplicateRequest, error) { - ranges := ranger.FullRange() - keysRanges, err := distsql.IndexRangesToKVRanges(nil, tableID, indexInfo.ID, ranges, nil) +// CollectDuplicateRowsFromTiKV collects duplicates from the remote TiKV and records all duplicate row info into errorMgr. +func (m *DuplicateManager) CollectDuplicateRowsFromTiKV(ctx context.Context, importClientFactory ImportClientFactory) error { + tasks, err := m.buildDupTasks() if err != nil { - return nil, errors.Trace(err) - } - reqs := make([]*DuplicateRequest, 0) - for _, r := range keysRanges { - req := &DuplicateRequest{ - start: r.StartKey, - end: r.EndKey, - tableID: tableID, - indexInfo: indexInfo, - } - reqs = append(reqs, req) + return errors.Trace(err) + } + logger := m.logger + logger.Info("[detect-dupe] collect duplicate rows from tikv", zap.Int("tasks", len(tasks))) + + taskPool := utils.NewWorkerPool(uint(m.concurrency), "collect duplicate rows from tikv") + regionPool := utils.NewWorkerPool(uint(m.concurrency), "collect duplicate rows from tikv by region") + g, gCtx := errgroup.WithContext(ctx) + for _, task := range tasks { + task := task + taskPool.ApplyOnErrorGroup(g, func() error { + taskLogger := logger.With( + logutil.Key("startKey", task.StartKey), + logutil.Key("endKey", task.EndKey), + zap.Int64("tableID", task.tableID), + ) + if task.indexInfo != nil { + taskLogger = taskLogger.With( + zap.String("indexName", task.indexInfo.Name.O), + zap.Int64("indexID", task.indexInfo.ID), + ) + } + err := m.processRemoteDupTask(gCtx, task, taskLogger, importClientFactory, regionPool) + return errors.Trace(err) + }) } - return reqs, nil + return errors.Trace(g.Wait()) } diff --git a/br/pkg/lightning/backend/local/engine.go b/br/pkg/lightning/backend/local/engine.go index 1091bb7a58c0e..82ebc4c4c3e65 100644 --- a/br/pkg/lightning/backend/local/engine.go +++ b/br/pkg/lightning/backend/local/engine.go @@ -72,10 +72,6 @@ type engineMeta struct { Length atomic.Int64 `json:"length"` // TotalSize is the total pre-compressed KV byte size stored by engine. TotalSize atomic.Int64 `json:"total_size"` - // Duplicates is the number of duplicates kv pairs detected when importing. Note that the value is - // probably larger than real value, because we may import same range more than once. For accurate - // information, you should iterate the duplicate db after import is finished. - Duplicates atomic.Int64 `json:"duplicates"` } type syncedRanges struct { @@ -256,28 +252,6 @@ var _ btree.Item = &rangeProperty{} type rangeProperties []rangeProperty -func decodeRangeProperties(data []byte) (rangeProperties, error) { - r := make(rangeProperties, 0, 16) - for len(data) > 0 { - if len(data) < 4 { - return nil, io.ErrUnexpectedEOF - } - keyLen := int(binary.BigEndian.Uint32(data[:4])) - data = data[4:] - if len(data) < keyLen+8*2 { - return nil, io.ErrUnexpectedEOF - } - key := data[:keyLen] - data = data[keyLen:] - size := binary.BigEndian.Uint64(data[:8]) - keys := binary.BigEndian.Uint64(data[8:]) - data = data[16:] - r = append(r, rangeProperty{Key: key, rangeOffsets: rangeOffsets{Size: size, Keys: keys}}) - } - - return r, nil -} - func (r rangeProperties) Encode() []byte { b := make([]byte, 0, 1024) idx := 0 @@ -299,13 +273,6 @@ func (r rangeProperties) Encode() []byte { return b } -func (r rangeProperties) get(key []byte) rangeOffsets { - idx := sort.Search(len(r), func(i int) bool { - return bytes.Compare(r[i].Key, key) >= 0 - }) - return r[idx].rangeOffsets -} - type RangePropertiesCollector struct { props rangeProperties lastOffsets rangeOffsets @@ -339,6 +306,9 @@ func (c *RangePropertiesCollector) insertNewPoint(key []byte) { // Add implements `pebble.TablePropertyCollector`. // Add implements `TablePropertyCollector.Add`. func (c *RangePropertiesCollector) Add(key pebble.InternalKey, value []byte) error { + if key.Kind() != pebble.InternalKeyKindSet || bytes.Equal(key.UserKey, engineMetaKey) { + return nil + } c.currentOffsets.Size += uint64(len(value)) + uint64(len(key.UserKey)) c.currentOffsets.Keys++ if len(c.lastKey) == 0 || c.sizeInLastRange() >= c.propSizeIdxDistance || @@ -389,7 +359,7 @@ func (s *sizeProperties) addAll(props rangeProperties) { prevRange = r.rangeOffsets } if len(props) > 0 { - s.totalSize = props[len(props)-1].Size + s.totalSize += props[len(props)-1].Size } } @@ -401,10 +371,38 @@ func (s *sizeProperties) iter(f func(p *rangeProperty) bool) { }) } -func (e *Engine) getSizeProperties() (*sizeProperties, error) { - sstables, err := e.db.SSTables(pebble.WithProperties()) +func decodeRangeProperties(data []byte, keyAdapter KeyAdapter) (rangeProperties, error) { + r := make(rangeProperties, 0, 16) + for len(data) > 0 { + if len(data) < 4 { + return nil, io.ErrUnexpectedEOF + } + keyLen := int(binary.BigEndian.Uint32(data[:4])) + data = data[4:] + if len(data) < keyLen+8*2 { + return nil, io.ErrUnexpectedEOF + } + key := data[:keyLen] + data = data[keyLen:] + size := binary.BigEndian.Uint64(data[:8]) + keys := binary.BigEndian.Uint64(data[8:]) + data = data[16:] + if !bytes.Equal(key, engineMetaKey) { + userKey, err := keyAdapter.Decode(nil, key) + if err != nil { + return nil, errors.Annotate(err, "failed to decode key with keyAdapter") + } + r = append(r, rangeProperty{Key: userKey, rangeOffsets: rangeOffsets{Size: size, Keys: keys}}) + } + } + + return r, nil +} + +func getSizeProperties(logger log.Logger, db *pebble.DB, keyAdapter KeyAdapter) (*sizeProperties, error) { + sstables, err := db.SSTables(pebble.WithProperties()) if err != nil { - log.L().Warn("get table properties failed", zap.Stringer("engine", e.UUID), log.ShortError(err)) + logger.Warn("get sst table properties failed", log.ShortError(err)) return nil, errors.Trace(err) } @@ -413,31 +411,12 @@ func (e *Engine) getSizeProperties() (*sizeProperties, error) { for _, info := range level { if prop, ok := info.Properties.UserProperties[propRangeIndex]; ok { data := hack.Slice(prop) - rangeProps, err := decodeRangeProperties(data) + rangeProps, err := decodeRangeProperties(data, keyAdapter) if err != nil { - log.L().Warn("decodeRangeProperties failed", zap.Stringer("engine", e.UUID), + logger.Warn("decodeRangeProperties failed", zap.Stringer("fileNum", info.FileNum), log.ShortError(err)) return nil, errors.Trace(err) } - if e.duplicateDetection { - newRangeProps := make(rangeProperties, 0, len(rangeProps)) - for _, p := range rangeProps { - if !bytes.Equal(p.Key, engineMetaKey) { - p.Key, _, _, err = e.keyAdapter.Decode(nil, p.Key) - if err != nil { - log.L().Warn( - "decodeRangeProperties failed because the props key is invalid", - zap.Stringer("engine", e.UUID), - zap.Stringer("fileNum", info.FileNum), - zap.Binary("key", p.Key), - ) - return nil, errors.Trace(err) - } - newRangeProps = append(newRangeProps, p) - } - } - rangeProps = newRangeProps - } sizeProps.addAll(rangeProps) } } @@ -447,8 +426,15 @@ func (e *Engine) getSizeProperties() (*sizeProperties, error) { } func (e *Engine) getEngineFileSize() backend.EngineFileSize { - metrics := e.db.Metrics() - total := metrics.Total() + e.mutex.RLock() + db := e.db + e.mutex.RUnlock() + + var total pebble.LevelMetrics + if db != nil { + metrics := db.Metrics() + total = metrics.Total() + } var memSize int64 e.localWriters.Range(func(k, v interface{}) bool { w := k.(*Writer) @@ -545,7 +531,6 @@ func (e *Engine) ingestSSTLoop() { for i := 0; i < concurrency; i++ { e.wg.Add(1) go func() { - defer e.wg.Done() defer func() { if e.ingestErr.Get() != nil { seqLock.Lock() @@ -555,6 +540,7 @@ func (e *Engine) ingestSSTLoop() { flushQueue = flushQueue[:0] seqLock.Unlock() } + e.wg.Done() }() for { select { @@ -965,6 +951,22 @@ func (e *Engine) unfinishedRanges(ranges []Range) []Range { return filterOverlapRange(ranges, e.finishedRanges.ranges) } +func (e *Engine) newKVIter(ctx context.Context, opts *pebble.IterOptions) Iter { + if bytes.Compare(opts.LowerBound, normalIterStartKey) < 0 { + newOpts := *opts + newOpts.LowerBound = normalIterStartKey + opts = &newOpts + } + if !e.duplicateDetection { + return pebbleIter{Iterator: e.db.NewIter(opts)} + } + logger := log.With( + zap.String("table", common.UniqueTable(e.tableInfo.DB, e.tableInfo.Name)), + zap.Int64("tableID", e.tableInfo.ID), + zap.Stringer("engineUUID", e.UUID)) + return newDupDetectIter(ctx, e.db, e.keyAdapter, opts, e.duplicateDB, logger) +} + type sstMeta struct { path string minKey []byte @@ -992,11 +994,10 @@ type Writer struct { // if the kvs in writeBatch are in order, we can avoid doing a `sort.Slice` which // is quite slow. in our bench, the sort operation eats about 5% of total CPU isWriteBatchSorted bool + sortedKeyBuf []byte batchCount int batchSize int64 - totalSize int64 - totalCount int64 lastMetaSeq int32 } @@ -1008,25 +1009,32 @@ func (w *Writer) appendRowsSorted(kvs []common.KvPair) error { return errors.Trace(err) } w.writer = writer - w.writer.minKey = append([]byte{}, kvs[0].Key...) } - totalKeyLen := 0 + keyAdapter := w.engine.keyAdapter + totalKeySize := 0 for i := 0; i < len(kvs); i++ { - totalKeyLen += w.engine.keyAdapter.EncodedLen(kvs[i].Key) - } - buf := make([]byte, totalKeyLen) - encodedKvs := make([]common.KvPair, len(kvs)) - for i := 0; i < len(kvs); i++ { - encodedKey := w.engine.keyAdapter.Encode(buf, kvs[i].Key, kvs[i].RowID, kvs[i].Offset) - buf = buf[len(encodedKey):] - encodedKvs[i] = common.KvPair{Key: encodedKey, Val: kvs[i].Val} - w.batchSize += int64(len(encodedKvs[i].Key) + len(encodedKvs[i].Val)) + keySize := keyAdapter.EncodedLen(kvs[i].Key) + w.batchSize += int64(keySize + len(kvs[i].Val)) + totalKeySize += keySize + } + w.batchCount += len(kvs) + // noopKeyAdapter doesn't really change the key, + // skipping the encoding to avoid unnecessary alloc and copy. + if _, ok := keyAdapter.(noopKeyAdapter); !ok { + if cap(w.sortedKeyBuf) < totalKeySize { + w.sortedKeyBuf = make([]byte, totalKeySize) + } + buf := w.sortedKeyBuf[:0] + newKvs := make([]common.KvPair, len(kvs)) + for i := 0; i < len(kvs); i++ { + buf = keyAdapter.Encode(buf, kvs[i].Key, kvs[i].RowID) + newKvs[i] = common.KvPair{Key: buf, Val: kvs[i].Val} + buf = buf[len(buf):] + } + kvs = newKvs } - - w.batchCount += len(encodedKvs) - w.totalCount += int64(len(encodedKvs)) - return w.writer.writeKVs(encodedKvs) + return w.writer.writeKVs(kvs) } func (w *Writer) appendRowsUnsorted(ctx context.Context, kvs []common.KvPair) error { @@ -1036,14 +1044,15 @@ func (w *Writer) appendRowsUnsorted(ctx context.Context, kvs []common.KvPair) er if cnt > 0 { lastKey = w.writeBatch[cnt-1].Key } + keyAdapter := w.engine.keyAdapter for _, pair := range kvs { if w.isWriteBatchSorted && bytes.Compare(lastKey, pair.Key) > 0 { w.isWriteBatchSorted = false } lastKey = pair.Key w.batchSize += int64(len(pair.Key) + len(pair.Val)) - buf := w.kvBuffer.AllocBytes(w.engine.keyAdapter.EncodedLen(pair.Key)) - key := w.engine.keyAdapter.Encode(buf, pair.Key, pair.RowID, pair.Offset) + buf := w.kvBuffer.AllocBytes(keyAdapter.EncodedLen(pair.Key)) + key := keyAdapter.Encode(buf[:0], pair.Key, pair.RowID) val := w.kvBuffer.AddBytes(pair.Val) if cnt < l { w.writeBatch[cnt].Key = key @@ -1060,7 +1069,6 @@ func (w *Writer) appendRowsUnsorted(ctx context.Context, kvs []common.KvPair) er return err } } - w.totalCount += int64(len(kvs)) return nil } @@ -1099,7 +1107,6 @@ func (w *Writer) flush(ctx context.Context) error { return nil } - w.totalSize += w.batchSize if len(w.writeBatch) > 0 { if err := w.flushKVs(ctx); err != nil { return errors.Trace(err) @@ -1157,7 +1164,6 @@ func (w *Writer) flushKVs(ctx context.Context) error { w.isWriteBatchSorted = true } - writer.minKey = append(writer.minKey[:0], w.writeBatch[0].Key...) err = writer.writeKVs(w.writeBatch[:w.batchCount]) if err != nil { return errors.Trace(err) @@ -1171,7 +1177,6 @@ func (w *Writer) flushKVs(ctx context.Context) error { return errors.Trace(err) } - w.totalSize += w.batchSize w.batchSize = 0 w.batchCount = 0 w.kvBuffer.Reset() @@ -1222,7 +1227,9 @@ func (sw *sstWriter) writeKVs(kvs []common.KvPair) error { if len(kvs) == 0 { return nil } - + if len(sw.minKey) == 0 { + sw.minKey = append([]byte{}, kvs[0].Key...) + } if bytes.Compare(kvs[0].Key, sw.maxKey) <= 0 { return errorUnorderedSSTInsertion } @@ -1241,9 +1248,10 @@ func (sw *sstWriter) writeKVs(kvs []common.KvPair) error { return errors.Trace(err) } sw.totalSize += int64(len(p.Key)) + int64(len(p.Val)) + lastKey = p.Key } sw.totalCount += int64(len(kvs)) - sw.maxKey = append(sw.maxKey[:0], kvs[len(kvs)-1].Key...) + sw.maxKey = append(sw.maxKey[:0], lastKey...) return nil } @@ -1470,5 +1478,8 @@ func (i dbSSTIngester) ingest(metas []*sstMeta) error { for _, m := range metas { paths = append(paths, m.path) } + if i.e.db == nil { + return errorEngineClosed + } return i.e.db.Ingest(paths) } diff --git a/br/pkg/lightning/backend/local/engine_test.go b/br/pkg/lightning/backend/local/engine_test.go new file mode 100644 index 0000000000000..d78aa29ee1c36 --- /dev/null +++ b/br/pkg/lightning/backend/local/engine_test.go @@ -0,0 +1,85 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package local + +import ( + "context" + "fmt" + "math" + "os" + "path" + "path/filepath" + "testing" + + "github.com/cockroachdb/pebble" + "github.com/cockroachdb/pebble/sstable" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + + "github.com/pingcap/tidb/br/pkg/lightning/backend" +) + +func TestIngestSSTWithClosedEngine(t *testing.T) { + dir := t.TempDir() + opt := &pebble.Options{ + MemTableSize: 1024 * 1024, + MaxConcurrentCompactions: 16, + L0CompactionThreshold: math.MaxInt32, // set to max try to disable compaction + L0StopWritesThreshold: math.MaxInt32, // set to max try to disable compaction + DisableWAL: true, + ReadOnly: false, + } + db, err := pebble.Open(filepath.Join(dir, "test"), opt) + require.NoError(t, err) + tmpPath := filepath.Join(dir, "test.sst") + err = os.Mkdir(tmpPath, 0o755) + require.NoError(t, err) + + _, engineUUID := backend.MakeUUID("ww", 0) + engineCtx, cancel := context.WithCancel(context.Background()) + f := &Engine{ + db: db, + UUID: engineUUID, + sstDir: tmpPath, + ctx: engineCtx, + cancel: cancel, + sstMetasChan: make(chan metaOrFlush, 64), + keyAdapter: noopKeyAdapter{}, + } + f.sstIngester = dbSSTIngester{e: f} + sstPath := path.Join(tmpPath, uuid.New().String()+".sst") + file, err := os.Create(sstPath) + require.NoError(t, err) + w := sstable.NewWriter(file, sstable.WriterOptions{}) + for i := 0; i < 10; i++ { + require.NoError(t, w.Add(sstable.InternalKey{ + Trailer: uint64(sstable.InternalKeyKindSet), + UserKey: []byte(fmt.Sprintf("key%d", i)), + }, nil)) + } + require.NoError(t, w.Close()) + + require.NoError(t, f.ingestSSTs([]*sstMeta{ + { + path: sstPath, + }, + })) + require.NoError(t, f.Close()) + require.ErrorIs(t, f.ingestSSTs([]*sstMeta{ + { + path: sstPath, + }, + }), errorEngineClosed) +} diff --git a/br/pkg/lightning/backend/local/iterator.go b/br/pkg/lightning/backend/local/iterator.go index 0495c6f4075a7..16c9b647e4f24 100644 --- a/br/pkg/lightning/backend/local/iterator.go +++ b/br/pkg/lightning/backend/local/iterator.go @@ -17,19 +17,42 @@ package local import ( "bytes" "context" + "math" "github.com/cockroachdb/pebble" sst "github.com/pingcap/kvproto/pkg/import_sstpb" - "go.uber.org/multierr" - "go.uber.org/zap" - - "github.com/pingcap/tidb/br/pkg/kv" - "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/logutil" - "github.com/pingcap/tidb/util/codec" + "go.uber.org/multierr" ) +// Iter abstract iterator method for Ingester. +type Iter interface { + // Seek seek to specify position. + // if key not found, seeks next key position in iter. + Seek(key []byte) bool + // Error return current error on this iter. + Error() error + // First moves this iter to the first key. + First() bool + // Last moves this iter to the last key. + Last() bool + // Valid check this iter reach the end. + Valid() bool + // Next moves this iter forward. + Next() bool + // Key represents current position pair's key. + Key() []byte + // Value represents current position pair's Value. + Value() []byte + // Close close this iter. + Close() error + // OpType represents operations of pair. currently we have two types. + // 1. Put + // 2. Delete + OpType() sst.Pair_OP +} + type pebbleIter struct { *pebble.Iterator } @@ -42,11 +65,11 @@ func (p pebbleIter) OpType() sst.Pair_OP { return sst.Pair_Put } -var _ kv.Iter = pebbleIter{} +var _ Iter = pebbleIter{} const maxDuplicateBatchSize = 4 << 20 -type duplicateIter struct { +type dupDetectIter struct { ctx context.Context iter *pebble.Iterator curKey []byte @@ -55,23 +78,22 @@ type duplicateIter struct { nextKey []byte err error - engine *Engine keyAdapter KeyAdapter writeBatch *pebble.Batch writeBatchSize int64 logger log.Logger } -func (d *duplicateIter) Seek(key []byte) bool { - encodedKey := d.keyAdapter.Encode(nil, key, 0, 0) - if d.err != nil || !d.iter.SeekGE(encodedKey) { +func (d *dupDetectIter) Seek(key []byte) bool { + rawKey := d.keyAdapter.Encode(nil, key, 0) + if d.err != nil || !d.iter.SeekGE(rawKey) { return false } d.fill() return d.err == nil } -func (d *duplicateIter) First() bool { +func (d *dupDetectIter) First() bool { if d.err != nil || !d.iter.First() { return false } @@ -79,7 +101,7 @@ func (d *duplicateIter) First() bool { return d.err == nil } -func (d *duplicateIter) Last() bool { +func (d *dupDetectIter) Last() bool { if d.err != nil || !d.iter.Last() { return false } @@ -87,34 +109,37 @@ func (d *duplicateIter) Last() bool { return d.err == nil } -func (d *duplicateIter) fill() { - d.curKey, _, _, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) +func (d *dupDetectIter) fill() { + d.curKey, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) d.curRawKey = append(d.curRawKey[:0], d.iter.Key()...) d.curVal = append(d.curVal[:0], d.iter.Value()...) } -func (d *duplicateIter) flush() { +func (d *dupDetectIter) flush() { d.err = d.writeBatch.Commit(pebble.Sync) d.writeBatch.Reset() d.writeBatchSize = 0 } -func (d *duplicateIter) record(key []byte, val []byte) { - d.engine.Duplicates.Inc() - d.err = d.writeBatch.Set(key, val, nil) +func (d *dupDetectIter) record(rawKey, key, val []byte) { + d.logger.Debug("[detect-dupe] local duplicate key detected", + logutil.Key("key", key), + logutil.Key("value", val), + logutil.Key("rawKey", rawKey)) + d.err = d.writeBatch.Set(rawKey, val, nil) if d.err != nil { return } - d.writeBatchSize += int64(len(key) + len(val)) + d.writeBatchSize += int64(len(rawKey) + len(val)) if d.writeBatchSize >= maxDuplicateBatchSize { d.flush() } } -func (d *duplicateIter) Next() bool { +func (d *dupDetectIter) Next() bool { recordFirst := false for d.err == nil && d.ctx.Err() == nil && d.iter.Next() { - d.nextKey, _, _, d.err = d.keyAdapter.Decode(d.nextKey[:0], d.iter.Key()) + d.nextKey, d.err = d.keyAdapter.Decode(d.nextKey[:0], d.iter.Key()) if d.err != nil { return false } @@ -124,15 +149,11 @@ func (d *duplicateIter) Next() bool { d.curVal = append(d.curVal[:0], d.iter.Value()...) return true } - d.logger.Debug("[detect-dupe] local duplicate key detected", - logutil.Key("key", d.curKey), - logutil.Key("prevValue", d.curVal), - logutil.Key("value", d.iter.Value())) if !recordFirst { - d.record(d.curRawKey, d.curVal) + d.record(d.curRawKey, d.curKey, d.curVal) recordFirst = true } - d.record(d.iter.Key(), d.iter.Value()) + d.record(d.iter.Key(), d.nextKey, d.iter.Value()) } if d.err == nil { d.err = d.ctx.Err() @@ -140,23 +161,23 @@ func (d *duplicateIter) Next() bool { return false } -func (d *duplicateIter) Key() []byte { +func (d *dupDetectIter) Key() []byte { return d.curKey } -func (d *duplicateIter) Value() []byte { +func (d *dupDetectIter) Value() []byte { return d.curVal } -func (d *duplicateIter) Valid() bool { +func (d *dupDetectIter) Valid() bool { return d.err == nil && d.iter.Valid() } -func (d *duplicateIter) Error() error { +func (d *dupDetectIter) Error() error { return multierr.Combine(d.iter.Error(), d.err) } -func (d *duplicateIter) Close() error { +func (d *dupDetectIter) Close() error { if d.err == nil { d.flush() } @@ -164,42 +185,109 @@ func (d *duplicateIter) Close() error { return d.iter.Close() } -func (d *duplicateIter) OpType() sst.Pair_OP { +func (d *dupDetectIter) OpType() sst.Pair_OP { return sst.Pair_Put } -var _ kv.Iter = &duplicateIter{} +var _ Iter = &dupDetectIter{} -func newDuplicateIter(ctx context.Context, engine *Engine, opts *pebble.IterOptions) kv.Iter { +func newDupDetectIter(ctx context.Context, db *pebble.DB, keyAdapter KeyAdapter, + opts *pebble.IterOptions, dupDB *pebble.DB, logger log.Logger) *dupDetectIter { newOpts := &pebble.IterOptions{TableFilter: opts.TableFilter} if len(opts.LowerBound) > 0 { - newOpts.LowerBound = codec.EncodeBytes(nil, opts.LowerBound) + newOpts.LowerBound = keyAdapter.Encode(nil, opts.LowerBound, math.MinInt64) } if len(opts.UpperBound) > 0 { - newOpts.UpperBound = codec.EncodeBytes(nil, opts.UpperBound) + newOpts.UpperBound = keyAdapter.Encode(nil, opts.UpperBound, math.MinInt64) } - logger := log.With( - zap.String("table", common.UniqueTable(engine.tableInfo.DB, engine.tableInfo.Name)), - zap.Int64("tableID", engine.tableInfo.ID), - zap.Stringer("engineUUID", engine.UUID)) - return &duplicateIter{ + return &dupDetectIter{ ctx: ctx, - iter: engine.db.NewIter(newOpts), - engine: engine, - keyAdapter: engine.keyAdapter, - writeBatch: engine.duplicateDB.NewBatch(), + iter: db.NewIter(newOpts), + keyAdapter: keyAdapter, + writeBatch: dupDB.NewBatch(), logger: logger, } } -func newKVIter(ctx context.Context, engine *Engine, opts *pebble.IterOptions) kv.Iter { - if bytes.Compare(opts.LowerBound, normalIterStartKey) < 0 { - newOpts := *opts - newOpts.LowerBound = normalIterStartKey - opts = &newOpts +type dupDBIter struct { + iter *pebble.Iterator + keyAdapter KeyAdapter + curKey []byte + err error +} + +func (d *dupDBIter) Seek(key []byte) bool { + rawKey := d.keyAdapter.Encode(nil, key, 0) + if d.err != nil || !d.iter.SeekGE(rawKey) { + return false + } + d.curKey, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) + return d.err == nil +} + +func (d *dupDBIter) Error() error { + if d.err != nil { + return d.err + } + return d.iter.Error() +} + +func (d *dupDBIter) First() bool { + if d.err != nil || !d.iter.First() { + return false + } + d.curKey, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) + return d.err == nil +} + +func (d *dupDBIter) Last() bool { + if d.err != nil || !d.iter.Last() { + return false + } + d.curKey, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) + return d.err == nil +} + +func (d *dupDBIter) Valid() bool { + return d.err == nil && d.iter.Valid() +} + +func (d *dupDBIter) Next() bool { + if d.err != nil || !d.iter.Next() { + return false + } + d.curKey, d.err = d.keyAdapter.Decode(d.curKey[:0], d.iter.Key()) + return d.err == nil +} + +func (d *dupDBIter) Key() []byte { + return d.curKey +} + +func (d *dupDBIter) Value() []byte { + return d.iter.Value() +} + +func (d *dupDBIter) Close() error { + return d.iter.Close() +} + +func (d *dupDBIter) OpType() sst.Pair_OP { + return sst.Pair_Put +} + +var _ Iter = &dupDBIter{} + +func newDupDBIter(dupDB *pebble.DB, keyAdapter KeyAdapter, opts *pebble.IterOptions) *dupDBIter { + newOpts := &pebble.IterOptions{TableFilter: opts.TableFilter} + if len(opts.LowerBound) > 0 { + newOpts.LowerBound = keyAdapter.Encode(nil, opts.LowerBound, math.MinInt64) + } + if len(opts.UpperBound) > 0 { + newOpts.UpperBound = keyAdapter.Encode(nil, opts.UpperBound, math.MinInt64) } - if !engine.duplicateDetection { - return pebbleIter{Iterator: engine.db.NewIter(opts)} + return &dupDBIter{ + iter: dupDB.NewIter(newOpts), + keyAdapter: keyAdapter, } - return newDuplicateIter(ctx, engine, opts) } diff --git a/br/pkg/lightning/backend/local/iterator_test.go b/br/pkg/lightning/backend/local/iterator_test.go index 864d504844da1..3abb6fbc3b06c 100644 --- a/br/pkg/lightning/backend/local/iterator_test.go +++ b/br/pkg/lightning/backend/local/iterator_test.go @@ -20,28 +20,24 @@ import ( "math/rand" "path/filepath" "sort" + "testing" "time" "github.com/cockroachdb/pebble" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/pingcap/tidb/br/pkg/lightning/log" + "github.com/stretchr/testify/require" ) -type iteratorSuite struct{} - -var _ = Suite(&iteratorSuite{}) - -func (s *iteratorSuite) TestDuplicateIterator(c *C) { +func TestDupDetectIterator(t *testing.T) { var pairs []common.KvPair prevRowMax := int64(0) // Unique pairs. for i := 0; i < 20; i++ { pairs = append(pairs, common.KvPair{ - Key: randBytes(32), - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1234), + Key: randBytes(32), + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ } @@ -49,17 +45,15 @@ func (s *iteratorSuite) TestDuplicateIterator(c *C) { for i := 20; i < 40; i++ { key := randBytes(32) pairs = append(pairs, common.KvPair{ - Key: key, - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1234), + Key: key, + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ pairs = append(pairs, common.KvPair{ - Key: key, - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1235), + Key: key, + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ } @@ -67,30 +61,27 @@ func (s *iteratorSuite) TestDuplicateIterator(c *C) { for i := 40; i < 50; i++ { key := randBytes(32) pairs = append(pairs, common.KvPair{ - Key: key, - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1234), + Key: key, + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ pairs = append(pairs, common.KvPair{ - Key: key, - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1235), + Key: key, + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ pairs = append(pairs, common.KvPair{ - Key: key, - Val: randBytes(128), - RowID: prevRowMax, - Offset: int64(i * 1236), + Key: key, + Val: randBytes(128), + RowID: prevRowMax, }) prevRowMax++ } // Find duplicates from the generated pairs. - var duplicatePairs []common.KvPair + var dupPairs []common.KvPair sort.Slice(pairs, func(i, j int) bool { return bytes.Compare(pairs[i].Key, pairs[j].Key) < 0 }) @@ -106,158 +97,133 @@ func (s *iteratorSuite) TestDuplicateIterator(c *C) { continue } for k := i; k < j; k++ { - duplicatePairs = append(duplicatePairs, pairs[k]) + dupPairs = append(dupPairs, pairs[k]) } i = j } - keyAdapter := duplicateKeyAdapter{} + keyAdapter := dupDetectKeyAdapter{} // Write pairs to db after shuffling the pairs. rnd := rand.New(rand.NewSource(time.Now().UnixNano())) rnd.Shuffle(len(pairs), func(i, j int) { pairs[i], pairs[j] = pairs[j], pairs[i] }) - storeDir := c.MkDir() + storeDir := t.TempDir() db, err := pebble.Open(filepath.Join(storeDir, "kv"), &pebble.Options{}) - c.Assert(err, IsNil) + require.NoError(t, err) wb := db.NewBatch() for _, p := range pairs { - key := keyAdapter.Encode(nil, p.Key, 1, p.Offset) - c.Assert(wb.Set(key, p.Val, nil), IsNil) + key := keyAdapter.Encode(nil, p.Key, p.RowID) + require.NoError(t, wb.Set(key, p.Val, nil)) } - c.Assert(wb.Commit(pebble.Sync), IsNil) + require.NoError(t, wb.Commit(pebble.Sync)) - duplicateDB, err := pebble.Open(filepath.Join(storeDir, "duplicates"), &pebble.Options{}) - c.Assert(err, IsNil) - engine := &Engine{ - ctx: context.Background(), - db: db, - keyAdapter: keyAdapter, - duplicateDB: duplicateDB, - tableInfo: &checkpoints.TidbTableInfo{ - DB: "db", - Name: "name", - }, - } - iter := newDuplicateIter(context.Background(), engine, &pebble.IterOptions{}) + dupDB, err := pebble.Open(filepath.Join(storeDir, "duplicates"), &pebble.Options{}) + require.NoError(t, err) + var iter Iter + iter = newDupDetectIter(context.Background(), db, keyAdapter, &pebble.IterOptions{}, dupDB, log.L()) sort.Slice(pairs, func(i, j int) bool { - key1 := keyAdapter.Encode(nil, pairs[i].Key, pairs[i].RowID, pairs[i].Offset) - key2 := keyAdapter.Encode(nil, pairs[j].Key, pairs[j].RowID, pairs[j].Offset) + key1 := keyAdapter.Encode(nil, pairs[i].Key, pairs[i].RowID) + key2 := keyAdapter.Encode(nil, pairs[j].Key, pairs[j].RowID) return bytes.Compare(key1, key2) < 0 }) // Verify first pair. - c.Assert(iter.First(), IsTrue) - c.Assert(iter.Valid(), IsTrue) - c.Assert(iter.Key(), BytesEquals, pairs[0].Key) - c.Assert(iter.Value(), BytesEquals, pairs[0].Val) + require.True(t, iter.First()) + require.True(t, iter.Valid()) + require.Equal(t, pairs[0].Key, iter.Key()) + require.Equal(t, pairs[0].Val, iter.Value()) // Verify last pair. - c.Assert(iter.Last(), IsTrue) - c.Assert(iter.Valid(), IsTrue) - c.Assert(iter.Key(), BytesEquals, pairs[len(pairs)-1].Key) - c.Assert(iter.Value(), BytesEquals, pairs[len(pairs)-1].Val) + require.True(t, iter.Last()) + require.True(t, iter.Valid()) + require.Equal(t, pairs[len(pairs)-1].Key, iter.Key()) + require.Equal(t, pairs[len(pairs)-1].Val, iter.Value()) // Iterate all keys and check the count of unique keys. for iter.First(); iter.Valid(); iter.Next() { - c.Assert(iter.Key(), BytesEquals, uniqueKeys[0]) + require.Equal(t, uniqueKeys[0], iter.Key()) uniqueKeys = uniqueKeys[1:] } - c.Assert(iter.Error(), IsNil) - c.Assert(len(uniqueKeys), Equals, 0) - c.Assert(iter.Close(), IsNil) - c.Assert(engine.Close(), IsNil) + require.NoError(t, iter.Error()) + require.Equal(t, 0, len(uniqueKeys)) + require.NoError(t, iter.Close()) + require.NoError(t, db.Close()) - // Check duplicates detected by duplicate iterator. - iter = pebbleIter{Iterator: duplicateDB.NewIter(&pebble.IterOptions{})} + // Check duplicates detected by dupDetectIter. + iter = newDupDBIter(dupDB, keyAdapter, &pebble.IterOptions{}) var detectedPairs []common.KvPair for iter.First(); iter.Valid(); iter.Next() { - key, _, _, err := keyAdapter.Decode(nil, iter.Key()) - c.Assert(err, IsNil) detectedPairs = append(detectedPairs, common.KvPair{ - Key: key, + Key: append([]byte{}, iter.Key()...), Val: append([]byte{}, iter.Value()...), }) } - c.Assert(iter.Error(), IsNil) - c.Assert(iter.Close(), IsNil) - c.Assert(duplicateDB.Close(), IsNil) - c.Assert(len(detectedPairs), Equals, len(duplicatePairs)) - - sort.Slice(duplicatePairs, func(i, j int) bool { - keyCmp := bytes.Compare(duplicatePairs[i].Key, duplicatePairs[j].Key) - return keyCmp < 0 || keyCmp == 0 && bytes.Compare(duplicatePairs[i].Val, duplicatePairs[j].Val) < 0 + require.NoError(t, iter.Error()) + require.NoError(t, iter.Close()) + require.NoError(t, dupDB.Close()) + require.Equal(t, len(dupPairs), len(detectedPairs)) + + sort.Slice(dupPairs, func(i, j int) bool { + keyCmp := bytes.Compare(dupPairs[i].Key, dupPairs[j].Key) + return keyCmp < 0 || keyCmp == 0 && bytes.Compare(dupPairs[i].Val, dupPairs[j].Val) < 0 }) sort.Slice(detectedPairs, func(i, j int) bool { keyCmp := bytes.Compare(detectedPairs[i].Key, detectedPairs[j].Key) return keyCmp < 0 || keyCmp == 0 && bytes.Compare(detectedPairs[i].Val, detectedPairs[j].Val) < 0 }) for i := 0; i < len(detectedPairs); i++ { - c.Assert(detectedPairs[i].Key, BytesEquals, duplicatePairs[i].Key) - c.Assert(detectedPairs[i].Val, BytesEquals, duplicatePairs[i].Val) + require.Equal(t, dupPairs[i].Key, detectedPairs[i].Key) + require.Equal(t, dupPairs[i].Val, detectedPairs[i].Val) } } -func (s *iteratorSuite) TestDuplicateIterSeek(c *C) { +func TestDupDetectIterSeek(t *testing.T) { pairs := []common.KvPair{ { - Key: []byte{1, 2, 3, 0}, - Val: randBytes(128), - RowID: 1, - Offset: 0, + Key: []byte{1, 2, 3, 0}, + Val: randBytes(128), + RowID: 1, }, { - Key: []byte{1, 2, 3, 1}, - Val: randBytes(128), - RowID: 2, - Offset: 100, + Key: []byte{1, 2, 3, 1}, + Val: randBytes(128), + RowID: 2, }, { - Key: []byte{1, 2, 3, 1}, - Val: randBytes(128), - RowID: 3, - Offset: 200, + Key: []byte{1, 2, 3, 1}, + Val: randBytes(128), + RowID: 3, }, { - Key: []byte{1, 2, 3, 2}, - Val: randBytes(128), - RowID: 4, - Offset: 300, + Key: []byte{1, 2, 3, 2}, + Val: randBytes(128), + RowID: 4, }, } - storeDir := c.MkDir() + storeDir := t.TempDir() db, err := pebble.Open(filepath.Join(storeDir, "kv"), &pebble.Options{}) - c.Assert(err, IsNil) + require.NoError(t, err) - keyAdapter := duplicateKeyAdapter{} + keyAdapter := dupDetectKeyAdapter{} wb := db.NewBatch() for _, p := range pairs { - key := keyAdapter.Encode(nil, p.Key, p.RowID, p.Offset) - c.Assert(wb.Set(key, p.Val, nil), IsNil) + key := keyAdapter.Encode(nil, p.Key, p.RowID) + require.NoError(t, wb.Set(key, p.Val, nil)) } - c.Assert(wb.Commit(pebble.Sync), IsNil) - - duplicateDB, err := pebble.Open(filepath.Join(storeDir, "duplicates"), &pebble.Options{}) - c.Assert(err, IsNil) - engine := &Engine{ - ctx: context.Background(), - db: db, - keyAdapter: keyAdapter, - duplicateDB: duplicateDB, - tableInfo: &checkpoints.TidbTableInfo{ - DB: "db", - Name: "name", - }, - } - iter := newDuplicateIter(context.Background(), engine, &pebble.IterOptions{}) - - c.Assert(iter.Seek([]byte{1, 2, 3, 1}), IsTrue) - c.Assert(iter.Value(), BytesEquals, pairs[1].Val) - c.Assert(iter.Next(), IsTrue) - c.Assert(iter.Value(), BytesEquals, pairs[3].Val) - c.Assert(iter.Close(), IsNil) - c.Assert(engine.Close(), IsNil) - c.Assert(duplicateDB.Close(), IsNil) + require.NoError(t, wb.Commit(pebble.Sync)) + + dupDB, err := pebble.Open(filepath.Join(storeDir, "duplicates"), &pebble.Options{}) + require.NoError(t, err) + iter := newDupDetectIter(context.Background(), db, keyAdapter, &pebble.IterOptions{}, dupDB, log.L()) + + require.True(t, iter.Seek([]byte{1, 2, 3, 1})) + require.Equal(t, pairs[1].Val, iter.Value()) + require.True(t, iter.Next()) + require.Equal(t, pairs[3].Val, iter.Value()) + require.NoError(t, iter.Close()) + require.NoError(t, db.Close()) + require.NoError(t, dupDB.Close()) } diff --git a/br/pkg/lightning/backend/local/key_adapter.go b/br/pkg/lightning/backend/local/key_adapter.go index 0a1bb296aeec0..7a767cbc04f62 100644 --- a/br/pkg/lightning/backend/local/key_adapter.go +++ b/br/pkg/lightning/backend/local/key_adapter.go @@ -23,14 +23,12 @@ import ( // KeyAdapter is used to encode and decode keys. type KeyAdapter interface { - // Encode encodes key with rowID and offset. It guarantees the encoded key is in ascending order for comparison. - // `buf` is used to buffer data to avoid the cost of make slice. - // Implementations of Encode must not reuse the key for encoding. - Encode(buf []byte, key []byte, rowID int64, offset int64) []byte + // Encode encodes the key with its corresponding rowID. It appends the encoded key to dst and returns the + // resulting slice. The encoded key is guaranteed to be in ascending order for comparison. + Encode(dst []byte, key []byte, rowID int64) []byte - // Decode decodes the original key. `buf` is used to buffer data to avoid the cost of make slice. - // Implementations of Decode must not reuse the data for decoding. - Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error) + // Decode decodes the original key to dst. It appends the encoded key to dst and returns the resulting slice. + Decode(dst []byte, data []byte) ([]byte, error) // EncodedLen returns the encoded key length. EncodedLen(key []byte) int @@ -48,13 +46,12 @@ func reallocBytes(b []byte, n int) []byte { type noopKeyAdapter struct{} -func (noopKeyAdapter) Encode(buf []byte, key []byte, _ int64, _ int64) []byte { - return append(buf[:0], key...) +func (noopKeyAdapter) Encode(dst []byte, key []byte, _ int64) []byte { + return append(dst, key...) } -func (noopKeyAdapter) Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error) { - key = append(buf[:0], data...) - return +func (noopKeyAdapter) Decode(dst []byte, data []byte) ([]byte, error) { + return append(dst, data...), nil } func (noopKeyAdapter) EncodedLen(key []byte) int { @@ -63,33 +60,38 @@ func (noopKeyAdapter) EncodedLen(key []byte) int { var _ KeyAdapter = noopKeyAdapter{} -type duplicateKeyAdapter struct{} +type dupDetectKeyAdapter struct{} -func (duplicateKeyAdapter) Encode(buf []byte, key []byte, rowID int64, offset int64) []byte { - buf = codec.EncodeBytes(buf[:0], key) - buf = reallocBytes(buf, 16) - n := len(buf) - buf = buf[:n+16] - binary.BigEndian.PutUint64(buf[n:n+8], uint64(rowID)) - binary.BigEndian.PutUint64(buf[n+8:], uint64(offset)) - return buf +func (dupDetectKeyAdapter) Encode(dst []byte, key []byte, rowID int64) []byte { + dst = codec.EncodeBytes(dst, key) + dst = reallocBytes(dst, 8) + n := len(dst) + dst = dst[:n+8] + binary.BigEndian.PutUint64(dst[n:n+8], codec.EncodeIntToCmpUint(rowID)) + return dst } -func (duplicateKeyAdapter) Decode(buf []byte, data []byte) (key []byte, rowID int64, offset int64, err error) { - if len(data) < 16 { - return nil, 0, 0, errors.New("insufficient bytes to decode value") +func (dupDetectKeyAdapter) Decode(dst []byte, data []byte) ([]byte, error) { + if len(data) < 8 { + return nil, errors.New("insufficient bytes to decode value") } - _, key, err = codec.DecodeBytes(data[:len(data)-16], buf) + _, key, err := codec.DecodeBytes(data[:len(data)-8], dst[len(dst):cap(dst)]) if err != nil { - return + return nil, err } - rowID = int64(binary.BigEndian.Uint64(data[len(data)-16 : len(data)-8])) - offset = int64(binary.BigEndian.Uint64(data[len(data)-8:])) - return + if len(dst) == 0 { + return key, nil + } + if len(dst)+len(key) <= cap(dst) { + dst = dst[:len(dst)+len(key)] + return dst, nil + } + // New slice is allocated, append key to dst manually. + return append(dst, key...), nil } -func (duplicateKeyAdapter) EncodedLen(key []byte) int { - return codec.EncodedBytesLength(len(key)) + 16 +func (dupDetectKeyAdapter) EncodedLen(key []byte) int { + return codec.EncodedBytesLength(len(key)) + 8 } -var _ KeyAdapter = duplicateKeyAdapter{} +var _ KeyAdapter = dupDetectKeyAdapter{} diff --git a/br/pkg/lightning/backend/local/key_adapter_test.go b/br/pkg/lightning/backend/local/key_adapter_test.go index 9892fef4f0e06..4b9abe1c25c3f 100644 --- a/br/pkg/lightning/backend/local/key_adapter_test.go +++ b/br/pkg/lightning/backend/local/key_adapter_test.go @@ -19,8 +19,10 @@ import ( "crypto/rand" "math" "sort" + "testing" + "unsafe" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) func randBytes(n int) []byte { @@ -29,83 +31,54 @@ func randBytes(n int) []byte { return b } -type noopKeyAdapterSuite struct { - keyAdapter KeyAdapter -} - -var _ = Suite(&noopKeyAdapterSuite{}) - -func (s *noopKeyAdapterSuite) SetUpSuite(c *C) { - s.keyAdapter = noopKeyAdapter{} -} - -func (s *noopKeyAdapterSuite) TestBasic(c *C) { +func TestNoopKeyAdapter(t *testing.T) { + keyAdapter := noopKeyAdapter{} key := randBytes(32) - c.Assert(s.keyAdapter.EncodedLen(key), Equals, len(key)) - encodedKey := s.keyAdapter.Encode(nil, key, 0, 0) - c.Assert(encodedKey, BytesEquals, key) - - decodedKey, _, _, err := s.keyAdapter.Decode(nil, encodedKey) - c.Assert(err, IsNil) - c.Assert(decodedKey, BytesEquals, key) -} + require.Len(t, key, keyAdapter.EncodedLen(key)) + encodedKey := keyAdapter.Encode(nil, key, 0) + require.Equal(t, key, encodedKey) -type duplicateKeyAdapterSuite struct { - keyAdapter KeyAdapter + decodedKey, err := keyAdapter.Decode(nil, encodedKey) + require.NoError(t, err) + require.Equal(t, key, decodedKey) } -var _ = Suite(&duplicateKeyAdapterSuite{}) - -func (s *duplicateKeyAdapterSuite) SetUpSuite(c *C) { - s.keyAdapter = duplicateKeyAdapter{} -} - -func (s *duplicateKeyAdapterSuite) TestBasic(c *C) { +func TestDupDetectKeyAdapter(t *testing.T) { inputs := []struct { - key []byte - rowID int64 - offset int64 + key []byte + rowID int64 }{ { []byte{0x0}, 0, - 0, - }, - { - randBytes(32), - 1, - -2034, }, { randBytes(32), 1, - math.MaxInt64, }, { randBytes(32), math.MaxInt32, - math.MinInt64, }, { randBytes(32), math.MinInt32, - 2345678, }, } + keyAdapter := dupDetectKeyAdapter{} for _, input := range inputs { - result := s.keyAdapter.Encode(nil, input.key, input.rowID, input.offset) + result := keyAdapter.Encode(nil, input.key, input.rowID) + require.Equal(t, keyAdapter.EncodedLen(input.key), len(result)) // Decode the result. - key, rowID, offset, err := s.keyAdapter.Decode(nil, result) - c.Assert(err, IsNil) - c.Assert(key, BytesEquals, input.key) - c.Assert(rowID, Equals, input.rowID) - c.Assert(offset, Equals, input.offset) + key, err := keyAdapter.Decode(nil, result) + require.NoError(t, err) + require.Equal(t, input.key, key) } } -func (s *duplicateKeyAdapterSuite) TestKeyOrder(c *C) { +func TestDupDetectKeyOrder(t *testing.T) { keys := [][]byte{ {0x0, 0x1, 0x2}, {0x0, 0x1, 0x3}, @@ -113,43 +86,75 @@ func (s *duplicateKeyAdapterSuite) TestKeyOrder(c *C) { {0x0, 0x1, 0x3, 0x4, 0x0}, {0x0, 0x1, 0x3, 0x4, 0x0, 0x0, 0x0}, } - keyAdapter := duplicateKeyAdapter{} - var encodedKeys [][]byte - for i, key := range keys { - encodedKeys = append(encodedKeys, keyAdapter.Encode(nil, key, 1, int64(i*1234))) + keyAdapter := dupDetectKeyAdapter{} + encodedKeys := make([][]byte, 0, len(keys)) + for _, key := range keys { + encodedKeys = append(encodedKeys, keyAdapter.Encode(nil, key, 1)) } sorted := sort.SliceIsSorted(encodedKeys, func(i, j int) bool { return bytes.Compare(encodedKeys[i], encodedKeys[j]) < 0 }) - c.Assert(sorted, IsTrue) + require.True(t, sorted) } -func (s *duplicateKeyAdapterSuite) TestEncodeKeyWithBuf(c *C) { +func TestDupDetectEncodeDupKey(t *testing.T) { + keyAdapter := dupDetectKeyAdapter{} key := randBytes(32) - buf := make([]byte, 256) - buf2 := s.keyAdapter.Encode(buf, key, 1, 1234) - // Verify the encode result first. - key2, _, _, err := s.keyAdapter.Decode(nil, buf2) - c.Assert(err, IsNil) - c.Assert(key2, BytesEquals, key) - // There should be no new slice allocated. - // If we change a byte in `buf`, `buf2` can read the new byte. - c.Assert(buf[:len(buf2)], BytesEquals, buf2) - buf[0]++ - c.Assert(buf[0], Equals, buf2[0]) + result1 := keyAdapter.Encode(nil, key, 10) + result2 := keyAdapter.Encode(nil, key, 20) + require.NotEqual(t, result1, result2) +} + +func startWithSameMemory(x []byte, y []byte) bool { + return cap(x) > 0 && cap(y) > 0 && uintptr(unsafe.Pointer(&x[:cap(x)][0])) == uintptr(unsafe.Pointer(&y[:cap(y)][0])) +} + +func TestEncodeKeyToPreAllocatedBuf(t *testing.T) { + keyAdapters := []KeyAdapter{noopKeyAdapter{}, dupDetectKeyAdapter{}} + for _, keyAdapter := range keyAdapters { + key := randBytes(32) + buf := make([]byte, 256) + buf2 := keyAdapter.Encode(buf[:4], key, 1) + require.True(t, startWithSameMemory(buf, buf2)) + // Verify the encoded result first. + key2, err := keyAdapter.Decode(nil, buf2[4:]) + require.NoError(t, err) + require.Equal(t, key, key2) + } +} + +func TestDecodeKeyToPreAllocatedBuf(t *testing.T) { + data := []byte{ + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf7, + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, + } + keyAdapters := []KeyAdapter{noopKeyAdapter{}, dupDetectKeyAdapter{}} + for _, keyAdapter := range keyAdapters { + key, err := keyAdapter.Decode(nil, data) + require.NoError(t, err) + buf := make([]byte, 4+len(data)) + buf2, err := keyAdapter.Decode(buf[:4], data) + require.NoError(t, err) + require.True(t, startWithSameMemory(buf, buf2)) + require.Equal(t, key, buf2[4:]) + } } -func (s *duplicateKeyAdapterSuite) TestDecodeKeyWithBuf(c *C) { +func TestDecodeKeyDstIsInsufficient(t *testing.T) { data := []byte{ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, } - buf := make([]byte, len(data)) - key, _, _, err := s.keyAdapter.Decode(buf, data) - c.Assert(err, IsNil) - // There should be no new slice allocated. - // If we change a byte in `buf`, `buf2` can read the new byte. - c.Assert(buf, BytesEquals, key[:len(buf)]) - buf[0]++ - c.Assert(buf[0], Equals, key[0]) + keyAdapters := []KeyAdapter{noopKeyAdapter{}, dupDetectKeyAdapter{}} + for _, keyAdapter := range keyAdapters { + key, err := keyAdapter.Decode(nil, data) + require.NoError(t, err) + buf := make([]byte, 4, 6) + copy(buf, []byte{'a', 'b', 'c', 'd'}) + buf2, err := keyAdapter.Decode(buf[:4], data) + require.NoError(t, err) + require.False(t, startWithSameMemory(buf, buf2)) + require.Equal(t, buf[:4], buf2[:4]) + require.Equal(t, key, buf2[4:]) + } } diff --git a/br/pkg/lightning/backend/local/local.go b/br/pkg/lightning/backend/local/local.go index f4921da0fa55e..ae5d292d04dc7 100644 --- a/br/pkg/lightning/backend/local/local.go +++ b/br/pkg/lightning/backend/local/local.go @@ -57,6 +57,7 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + tikverror "github.com/tikv/client-go/v2/error" "github.com/tikv/client-go/v2/oracle" tikvclient "github.com/tikv/client-go/v2/tikv" pd "github.com/tikv/pd/client" @@ -64,6 +65,7 @@ import ( "go.uber.org/multierr" "go.uber.org/zap" "golang.org/x/sync/errgroup" + "golang.org/x/time/rate" "google.golang.org/grpc" "google.golang.org/grpc/backoff" "google.golang.org/grpc/codes" @@ -76,13 +78,18 @@ const ( dialTimeout = 5 * time.Minute maxRetryTimes = 5 defaultRetryBackoffTime = 3 * time.Second + // maxWriteAndIngestRetryTimes is the max retry times for write and ingest. + // A large retry times is for tolerating tikv cluster failures. + maxWriteAndIngestRetryTimes = 30 + maxRetryBackoffTime = 30 * time.Second gRPCKeepAliveTime = 10 * time.Minute gRPCKeepAliveTimeout = 5 * time.Minute gRPCBackOffMaxDelay = 10 * time.Minute // See: https://github.com/tikv/tikv/blob/e030a0aae9622f3774df89c62f21b2171a72a69e/etc/config-template.toml#L360 - regionMaxKeyCount = 1_440_000 + // lower the max-key-count to avoid tikv trigger region auto split + regionMaxKeyCount = 1_280_000 defaultRegionSplitSize = 96 * units.MiB propRangeIndex = "tikv.range_index" @@ -110,8 +117,82 @@ var ( errorEngineClosed = errors.New("engine is closed") ) -// getImportClientFn is a variable alias for getImportClient used for unit test. -var getImportClientFn = getImportClient +// ImportClientFactory is factory to create new import client for specific store. +type ImportClientFactory interface { + Create(ctx context.Context, storeID uint64) (sst.ImportSSTClient, error) + Close() +} + +type importClientFactoryImpl struct { + conns *common.GRPCConns + splitCli split.SplitClient + tls *common.TLS + tcpConcurrency int +} + +func newImportClientFactoryImpl(splitCli split.SplitClient, tls *common.TLS, tcpConcurrency int) *importClientFactoryImpl { + return &importClientFactoryImpl{ + conns: common.NewGRPCConns(), + splitCli: splitCli, + tls: tls, + tcpConcurrency: tcpConcurrency, + } +} + +func (f *importClientFactoryImpl) makeConn(ctx context.Context, storeID uint64) (*grpc.ClientConn, error) { + store, err := f.splitCli.GetStore(ctx, storeID) + if err != nil { + return nil, errors.Trace(err) + } + opt := grpc.WithInsecure() + if f.tls.TLSConfig() != nil { + opt = grpc.WithTransportCredentials(credentials.NewTLS(f.tls.TLSConfig())) + } + ctx, cancel := context.WithTimeout(ctx, dialTimeout) + + bfConf := backoff.DefaultConfig + bfConf.MaxDelay = gRPCBackOffMaxDelay + // we should use peer address for tiflash. for tikv, peer address is empty + addr := store.GetPeerAddress() + if addr == "" { + addr = store.GetAddress() + } + conn, err := grpc.DialContext( + ctx, + addr, + opt, + grpc.WithConnectParams(grpc.ConnectParams{Backoff: bfConf}), + grpc.WithKeepaliveParams(keepalive.ClientParameters{ + Time: gRPCKeepAliveTime, + Timeout: gRPCKeepAliveTimeout, + PermitWithoutStream: true, + }), + ) + cancel() + if err != nil { + return nil, errors.Trace(err) + } + return conn, nil +} + +func (f *importClientFactoryImpl) getGrpcConn(ctx context.Context, storeID uint64) (*grpc.ClientConn, error) { + return f.conns.GetGrpcConn(ctx, storeID, f.tcpConcurrency, + func(ctx context.Context) (*grpc.ClientConn, error) { + return f.makeConn(ctx, storeID) + }) +} + +func (f *importClientFactoryImpl) Create(ctx context.Context, storeID uint64) (sst.ImportSSTClient, error) { + conn, err := f.getGrpcConn(ctx, storeID) + if err != nil { + return nil, err + } + return sst.NewImportSSTClient(conn), nil +} + +func (f *importClientFactoryImpl) Close() { + f.conns.Close() +} // Range record start and end key for localStoreDir.DB // so we can write it to tikv in streaming @@ -124,7 +205,6 @@ type local struct { engines sync.Map // sync version of map[uuid.UUID]*Engine pdCtl *pdutil.PdController - conns common.GRPCConns splitCli split.SplitClient tikvCli *tikvclient.KVStore tls *common.TLS @@ -138,20 +218,22 @@ type local struct { batchWriteKVPairs int checkpointEnabled bool - tcpConcurrency int - maxOpenFiles int + dupeConcurrency int + maxOpenFiles int engineMemCacheSize int localWriterMemCacheSize int64 supportMultiIngest bool - checkTiKVAvaliable bool - duplicateDetection bool - duplicateDB *pebble.DB - errorMgr *errormanager.ErrorManager -} + checkTiKVAvaliable bool + duplicateDetection bool + duplicateDB *pebble.DB + keyAdapter KeyAdapter + errorMgr *errormanager.ErrorManager + importClientFactory ImportClientFactory -var bufferPool = membuf.NewPool(1024, manual.Allocator{}) + bufferPool *membuf.Pool +} func openDuplicateDB(storeDir string) (*pebble.DB, error) { dbPath := filepath.Join(storeDir, duplicateDBName) @@ -178,9 +260,9 @@ func NewLocalBackend( pdCtl, err := pdutil.NewPdController(ctx, cfg.TiDB.PdAddr, tls.TLSConfig(), tls.ToPDSecurityOption()) if err != nil { - return backend.MakeBackend(nil), errors.Annotate(err, "construct pd client failed") + return backend.MakeBackend(nil), common.NormalizeOrWrapErr(common.ErrCreatePDClient, err) } - splitCli := split.NewSplitClient(pdCtl.GetPDClient(), tls.TLSConfig()) + splitCli := split.NewSplitClient(pdCtl.GetPDClient(), tls.TLSConfig(), false) shouldCreate := true if cfg.Checkpoint.Enable { @@ -196,7 +278,7 @@ func NewLocalBackend( if shouldCreate { err = os.Mkdir(localFile, 0o700) if err != nil { - return backend.MakeBackend(nil), errors.Annotate(err, "invalid sorted-kv-dir for local backend, please change the config or delete the path") + return backend.MakeBackend(nil), common.ErrInvalidSortedKVDir.Wrap(err).GenWithStackByArgs(localFile) } } @@ -204,22 +286,27 @@ func NewLocalBackend( if cfg.TikvImporter.DuplicateResolution != config.DupeResAlgNone { duplicateDB, err = openDuplicateDB(localFile) if err != nil { - return backend.MakeBackend(nil), errors.Annotate(err, "open duplicate db failed") + return backend.MakeBackend(nil), common.ErrOpenDuplicateDB.Wrap(err).GenWithStackByArgs() } } // The following copies tikv.NewTxnClient without creating yet another pdClient. spkv, err := tikvclient.NewEtcdSafePointKV(strings.Split(cfg.TiDB.PdAddr, ","), tls.TLSConfig()) if err != nil { - return backend.MakeBackend(nil), err + return backend.MakeBackend(nil), common.ErrCreateKVClient.Wrap(err).GenWithStackByArgs() } rpcCli := tikvclient.NewRPCClient(tikvclient.WithSecurity(tls.ToTiKVSecurityConfig())) pdCliForTiKV := &tikvclient.CodecPDClient{Client: pdCtl.GetPDClient()} tikvCli, err := tikvclient.NewKVStore("lightning-local-backend", pdCliForTiKV, spkv, rpcCli) if err != nil { - return backend.MakeBackend(nil), err + return backend.MakeBackend(nil), common.ErrCreateKVClient.Wrap(err).GenWithStackByArgs() + } + importClientFactory := newImportClientFactoryImpl(splitCli, tls, rangeConcurrency) + duplicateDetection := cfg.TikvImporter.DuplicateResolution != config.DupeResAlgNone + keyAdapter := KeyAdapter(noopKeyAdapter{}) + if duplicateDetection { + keyAdapter = dupDetectKeyAdapter{} } - local := &local{ engines: sync.Map{}, pdCtl: pdCtl, @@ -232,21 +319,23 @@ func NewLocalBackend( localStoreDir: localFile, rangeConcurrency: worker.NewPool(ctx, rangeConcurrency, "range"), ingestConcurrency: worker.NewPool(ctx, rangeConcurrency*2, "ingest"), - tcpConcurrency: rangeConcurrency, + dupeConcurrency: rangeConcurrency * 2, batchWriteKVPairs: cfg.TikvImporter.SendKVPairs, checkpointEnabled: cfg.Checkpoint.Enable, maxOpenFiles: utils.MaxInt(maxOpenFiles, openFilesLowerThreshold), engineMemCacheSize: int(cfg.TikvImporter.EngineMemCacheSize), localWriterMemCacheSize: int64(cfg.TikvImporter.LocalWriterMemCacheSize), - duplicateDetection: cfg.TikvImporter.DuplicateResolution != config.DupeResAlgNone, + duplicateDetection: duplicateDetection, checkTiKVAvaliable: cfg.App.CheckRequirements, duplicateDB: duplicateDB, + keyAdapter: keyAdapter, errorMgr: errorMgr, + importClientFactory: importClientFactory, + bufferPool: membuf.NewPool(membuf.WithAllocator(manual.Allocator{})), } - local.conns = common.NewGRPCConns() if err = local.checkMultiIngestSupport(ctx); err != nil { - return backend.MakeBackend(nil), err + return backend.MakeBackend(nil), common.ErrCheckMultiIngest.Wrap(err).GenWithStackByArgs() } return backend.MakeBackend(local), nil @@ -369,49 +458,6 @@ func (local *local) lockAllEnginesUnless(newState, ignoreStateMask importMutexSt return allEngines } -func (local *local) makeConn(ctx context.Context, storeID uint64) (*grpc.ClientConn, error) { - store, err := local.splitCli.GetStore(ctx, storeID) - if err != nil { - return nil, errors.Trace(err) - } - opt := grpc.WithInsecure() - if local.tls.TLSConfig() != nil { - opt = grpc.WithTransportCredentials(credentials.NewTLS(local.tls.TLSConfig())) - } - ctx, cancel := context.WithTimeout(ctx, dialTimeout) - - bfConf := backoff.DefaultConfig - bfConf.MaxDelay = gRPCBackOffMaxDelay - // we should use peer address for tiflash. for tikv, peer address is empty - addr := store.GetPeerAddress() - if addr == "" { - addr = store.GetAddress() - } - conn, err := grpc.DialContext( - ctx, - addr, - opt, - grpc.WithConnectParams(grpc.ConnectParams{Backoff: bfConf}), - grpc.WithKeepaliveParams(keepalive.ClientParameters{ - Time: gRPCKeepAliveTime, - Timeout: gRPCKeepAliveTimeout, - PermitWithoutStream: true, - }), - ) - cancel() - if err != nil { - return nil, errors.Trace(err) - } - return conn, nil -} - -func (local *local) getGrpcConn(ctx context.Context, storeID uint64) (*grpc.ClientConn, error) { - return local.conns.GetGrpcConn(ctx, storeID, local.tcpConcurrency, - func(ctx context.Context) (*grpc.ClientConn, error) { - return local.makeConn(ctx, storeID) - }) -} - // Close the local backend. func (local *local) Close() { allEngines := local.lockAllEnginesUnless(importMutexStateClose, 0) @@ -421,10 +467,11 @@ func (local *local) Close() { engine.Close() engine.unlock() } - local.conns.Close() + local.importClientFactory.Close() + local.bufferPool.Destroy() if local.duplicateDB != nil { - // Check whether there are duplicates. + // Check if there are duplicates that are not collected. iter := local.duplicateDB.NewIter(&pebble.IterOptions{}) hasDuplicates := iter.First() allIsWell := true @@ -440,7 +487,7 @@ func (local *local) Close() { log.L().Warn("close duplicate db failed", zap.Error(err)) allIsWell = false } - // If checkpoint is disabled or we don't detect any duplicate, then this duplicate + // If checkpoint is disabled, or we don't detect any duplicate, then this duplicate // db dir will be useless, so we clean up this dir. if allIsWell && (!local.checkpointEnabled || !hasDuplicates) { if err := os.RemoveAll(filepath.Join(local.localStoreDir, duplicateDBName)); err != nil { @@ -549,16 +596,12 @@ func (local *local) OpenEngine(ctx context.Context, cfg *backend.EngineConfig, e return errors.Trace(err) } if !common.IsDirExists(sstDir) { - if err := os.Mkdir(sstDir, 0o755); err != nil { + if err := os.Mkdir(sstDir, 0o750); err != nil { return errors.Trace(err) } } engineCtx, cancel := context.WithCancel(ctx) - keyAdapter := KeyAdapter(noopKeyAdapter{}) - if local.duplicateDetection { - keyAdapter = duplicateKeyAdapter{} - } e, _ := local.engines.LoadOrStore(engineUUID, &Engine{ UUID: engineUUID, sstDir: sstDir, @@ -570,7 +613,7 @@ func (local *local) OpenEngine(ctx context.Context, cfg *backend.EngineConfig, e duplicateDetection: local.duplicateDetection, duplicateDB: local.duplicateDB, errorMgr: local.errorMgr, - keyAdapter: keyAdapter, + keyAdapter: local.keyAdapter, }) engine := e.(*Engine) engine.db = db @@ -615,16 +658,12 @@ func (local *local) CloseEngine(ctx context.Context, cfg *backend.EngineConfig, db: db, sstMetasChan: make(chan metaOrFlush), tableInfo: cfg.TableInfo, + keyAdapter: local.keyAdapter, duplicateDetection: local.duplicateDetection, duplicateDB: local.duplicateDB, errorMgr: local.errorMgr, } engine.sstIngester = dbSSTIngester{e: engine} - keyAdapter := KeyAdapter(noopKeyAdapter{}) - if local.duplicateDetection { - keyAdapter = duplicateKeyAdapter{} - } - engine.keyAdapter = keyAdapter if err = engine.loadEngineMeta(); err != nil { return err } @@ -656,15 +695,7 @@ func (local *local) CloseEngine(ctx context.Context, cfg *backend.EngineConfig, } func (local *local) getImportClient(ctx context.Context, storeID uint64) (sst.ImportSSTClient, error) { - return getImportClientFn(local, ctx, storeID) -} - -func getImportClient(local *local, ctx context.Context, storeID uint64) (sst.ImportSSTClient, error) { - conn, err := local.getGrpcConn(ctx, storeID) - if err != nil { - return nil, err - } - return sst.NewImportSSTClient(conn), nil + return local.importClientFactory.Create(ctx, storeID) } type rangeStats struct { @@ -710,7 +741,7 @@ func (local *local) WriteToTiKV( begin := time.Now() regionRange := intersectRange(region.Region, Range{start: start, end: end}) opt := &pebble.IterOptions{LowerBound: regionRange.start, UpperBound: regionRange.end} - iter := newKVIter(ctx, engine, opt) + iter := engine.newKVIter(ctx, opt) defer iter.Close() stats := rangeStats{} @@ -775,14 +806,19 @@ func (local *local) WriteToTiKV( requests = append(requests, req) } - bytesBuf := bufferPool.NewBuffer() + bytesBuf := local.bufferPool.NewBuffer() defer bytesBuf.Destroy() pairs := make([]*sst.Pair, 0, local.batchWriteKVPairs) count := 0 size := int64(0) totalCount := int64(0) firstLoop := true - regionMaxSize := regionSplitSize * 4 / 3 + // if region-split-size <= 96MiB, we bump the threshold a bit to avoid too many retry split + // because the range-properties is not 100% accurate + regionMaxSize := regionSplitSize + if regionSplitSize <= defaultRegionSplitSize { + regionMaxSize = regionSplitSize * 4 / 3 + } for iter.First(); iter.Valid(); iter.Next() { size += int64(len(iter.Key()) + len(iter.Value())) @@ -915,36 +951,38 @@ func splitRangeBySizeProps(fullRange Range, sizeProps *sizeProperties, sizeLimit curSize := uint64(0) curKeys := uint64(0) curKey := fullRange.start + sizeProps.iter(func(p *rangeProperty) bool { - if bytes.Equal(p.Key, engineMetaKey) { + if bytes.Compare(p.Key, curKey) <= 0 { return true } + if bytes.Compare(p.Key, fullRange.end) > 0 { + return false + } curSize += p.Size curKeys += p.Keys if int64(curSize) >= sizeLimit || int64(curKeys) >= keysLimit { - // in case the sizeLimit or keysLimit is too small - endKey := p.Key - if bytes.Equal(curKey, endKey) { - endKey = nextKey(endKey) - } - ranges = append(ranges, Range{start: curKey, end: endKey}) - curKey = endKey + ranges = append(ranges, Range{start: curKey, end: p.Key}) + curKey = p.Key curSize = 0 curKeys = 0 } return true }) - if curKeys > 0 { - ranges = append(ranges, Range{start: curKey, end: fullRange.end}) - } else { - ranges[len(ranges)-1].end = fullRange.end + if bytes.Compare(curKey, fullRange.end) < 0 { + // If the remaining range is too small, append it to last range. + if len(ranges) > 0 && curKeys == 0 { + ranges[len(ranges)-1].end = fullRange.end + } else { + ranges = append(ranges, Range{start: curKey, end: fullRange.end}) + } } return ranges } func (local *local) readAndSplitIntoRange(ctx context.Context, engine *Engine, regionSplitSize int64, regionSplitKeys int64) ([]Range, error) { - iter := newKVIter(ctx, engine, &pebble.IterOptions{}) + iter := engine.newKVIter(ctx, &pebble.IterOptions{}) defer iter.Close() iterError := func(e string) error { @@ -977,7 +1015,8 @@ func (local *local) readAndSplitIntoRange(ctx context.Context, engine *Engine, r return ranges, nil } - sizeProps, err := engine.getSizeProperties() + logger := log.With(zap.Stringer("engine", engine.UUID)) + sizeProps, err := getSizeProperties(logger, engine.db, local.keyAdapter) if err != nil { return nil, errors.Trace(err) } @@ -985,7 +1024,7 @@ func (local *local) readAndSplitIntoRange(ctx context.Context, engine *Engine, r ranges := splitRangeBySizeProps(Range{start: firstKey, end: endKey}, sizeProps, regionSplitSize, regionSplitKeys) - log.L().Info("split engine key ranges", zap.Stringer("engine", engine.UUID), + logger.Info("split engine key ranges", zap.Int64("totalSize", engineFileTotalSize), zap.Int64("totalCount", engineFileLength), logutil.Key("firstKey", firstKey), logutil.Key("lastKey", lastKey), zap.Int("ranges", len(ranges))) @@ -1005,7 +1044,7 @@ func (local *local) writeAndIngestByRange( UpperBound: end, } - iter := newKVIter(ctxt, engine, ito) + iter := engine.newKVIter(ctxt, ito) defer iter.Close() // Needs seek to first because NewIter returns an iterator that is unpositioned hasKey := iter.First() @@ -1241,9 +1280,9 @@ func (local *local) writeAndIngestByRanges(ctx context.Context, engine *Engine, wg.Done() }() var err error - // max retry backoff time: 2+4+8+16=30s + // max retry backoff time: 2+4+8+16+30*26=810s backOffTime := time.Second - for i := 0; i < maxRetryTimes; i++ { + for i := 0; i < maxWriteAndIngestRetryTimes; i++ { err = local.writeAndIngestByRange(ctx, engine, startKey, endKey, regionSplitSize, regionSplitKeys) if err == nil || common.IsContextCanceledError(err) { return @@ -1251,6 +1290,9 @@ func (local *local) writeAndIngestByRanges(ctx context.Context, engine *Engine, log.L().Warn("write and ingest by range failed", zap.Int("retry time", i+1), log.ShortError(err)) backOffTime *= 2 + if backOffTime > maxRetryBackoffTime { + backOffTime = maxRetryBackoffTime + } select { case <-time.After(backOffTime): case <-ctx.Done(): @@ -1270,6 +1312,9 @@ func (local *local) writeAndIngestByRanges(ctx context.Context, engine *Engine, // wait for all sub tasks finish to avoid panic. if we return on the first error, // the outer tasks may close the pebble db but some sub tasks still read from the db wg.Wait() + if allErr == nil { + return ctx.Err() + } return allErr } @@ -1333,16 +1378,6 @@ func (local *local) ImportEngine(ctx context.Context, engineUUID uuid.UUID, regi } } - if lf.Duplicates.Load() > 0 { - if err := lf.saveEngineMeta(); err != nil { - log.L().Error("failed to save engine meta", log.ShortError(err)) - return err - } - log.L().Warn("duplicate detected during import engine", zap.Stringer("uuid", engineUUID), - zap.Int64("size", lfTotalSize), zap.Int64("kvs", lfLength), zap.Int64("duplicate-kvs", lf.Duplicates.Load()), - zap.Int64("importedSize", lf.importedKVSize.Load()), zap.Int64("importedCount", lf.importedKVCount.Load())) - } - log.L().Info("import engine success", zap.Stringer("uuid", engineUUID), zap.Int64("size", lfTotalSize), zap.Int64("kvs", lfLength), zap.Int64("importedSize", lf.importedKVSize.Load()), zap.Int64("importedCount", lf.importedKVCount.Load())) @@ -1350,48 +1385,39 @@ func (local *local) ImportEngine(ctx context.Context, engineUUID uuid.UUID, regi } func (local *local) CollectLocalDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (hasDupe bool, err error) { - if local.duplicateDB == nil { - return false, nil - } - - logger := log.With(zap.String("table", tableName)).Begin(zap.InfoLevel, "[detect-dupe] collect duplicate local keys") + logger := log.With(zap.String("table", tableName)).Begin(zap.InfoLevel, "[detect-dupe] collect local duplicate keys") defer func() { logger.End(zap.ErrorLevel, err) }() - physicalTS, logicalTS, err := local.pdCtl.GetPDClient().GetTS(ctx) + atomicHasDupe := atomic.NewBool(false) + duplicateManager, err := NewDuplicateManager(tbl, tableName, local.splitCli, local.tikvCli, + local.errorMgr, opts, local.dupeConcurrency, atomicHasDupe) if err != nil { - return false, err + return false, errors.Trace(err) } - ts := oracle.ComposeTS(physicalTS, logicalTS) - duplicateManager, err := NewDuplicateManager(local, ts, opts) - if err != nil { - return false, errors.Annotate(err, "open duplicatemanager failed") - } - hasDupe, err = duplicateManager.CollectDuplicateRowsFromLocalIndex(ctx, tbl, tableName, local.duplicateDB) - if err != nil { - return false, errors.Annotate(err, "collect local duplicate rows failed") + if err := duplicateManager.CollectDuplicateRowsFromDupDB(ctx, local.duplicateDB, local.keyAdapter); err != nil { + return false, errors.Trace(err) } - return hasDupe, nil + return atomicHasDupe.Load(), nil } -func (local *local) CollectRemoteDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (bool, error) { - log.L().Info("Begin collect remote duplicate keys", zap.String("table", tableName)) - physicalTS, logicalTS, err := local.pdCtl.GetPDClient().GetTS(ctx) - if err != nil { - return false, err - } - ts := oracle.ComposeTS(physicalTS, logicalTS) +func (local *local) CollectRemoteDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (hasDupe bool, err error) { + logger := log.With(zap.String("table", tableName)).Begin(zap.InfoLevel, "[detect-dupe] collect remote duplicate keys") + defer func() { + logger.End(zap.ErrorLevel, err) + }() - duplicateManager, err := NewDuplicateManager(local, ts, opts) + atomicHasDupe := atomic.NewBool(false) + duplicateManager, err := NewDuplicateManager(tbl, tableName, local.splitCli, local.tikvCli, + local.errorMgr, opts, local.dupeConcurrency, atomicHasDupe) if err != nil { - return false, errors.Annotate(err, "open duplicatemanager failed") + return false, errors.Trace(err) } - hasDupe, err := duplicateManager.CollectDuplicateRowsFromTiKV(ctx, tbl, tableName) - if err != nil { - return false, errors.Annotate(err, "collect remote duplicate rows failed") + if err := duplicateManager.CollectDuplicateRowsFromTiKV(ctx, local.importClientFactory); err != nil { + return false, errors.Trace(err) } - return hasDupe, nil + return atomicHasDupe.Load(), nil } func (local *local) ResolveDuplicateRows(ctx context.Context, tbl table.Table, tableName string, algorithm config.DuplicateResolutionAlgorithm) (err error) { @@ -1418,21 +1444,29 @@ func (local *local) ResolveDuplicateRows(ctx context.Context, tbl table.Table, t return err } - preRowID := int64(0) - for { - handleRows, lastRowID, err := local.errorMgr.GetConflictKeys(ctx, tableName, preRowID, 1000) - if err != nil { - return errors.Annotate(err, "cannot query conflict keys") - } - if len(handleRows) == 0 { - break - } - if err := local.deleteDuplicateRows(ctx, logger, handleRows, decoder); err != nil { - return errors.Annotate(err, "cannot delete duplicated entries") - } - preRowID = lastRowID - } - return nil + errLimiter := rate.NewLimiter(1, 1) + pool := utils.NewWorkerPool(uint(local.dupeConcurrency), "resolve duplicate rows") + err = local.errorMgr.ResolveAllConflictKeys( + ctx, tableName, pool, + func(ctx context.Context, handleRows [][2][]byte) error { + for { + err := local.deleteDuplicateRows(ctx, logger, handleRows, decoder) + if err == nil { + return nil + } + if log.IsContextCanceledError(err) { + return err + } + if !tikverror.IsErrWriteConflict(errors.Cause(err)) { + logger.Warn("delete duplicate rows encounter error", log.ShortError(err)) + } + if err = errLimiter.Wait(ctx); err != nil { + return err + } + } + }, + ) + return errors.Trace(err) } func (local *local) deleteDuplicateRows(ctx context.Context, logger *log.Task, handleRows [][2][]byte, decoder *kv.TableKVDecoder) (err error) { @@ -1441,7 +1475,6 @@ func (local *local) deleteDuplicateRows(ctx context.Context, logger *log.Task, h if err != nil { return err } - txn.SetPessimistic(true) defer func() { if err == nil { err = txn.Commit(ctx) @@ -1469,7 +1502,7 @@ func (local *local) deleteDuplicateRows(ctx context.Context, logger *log.Task, h return err } - handle, err := decoder.DecodeHandleFromTable(handleRow[0]) + handle, err := decoder.DecodeHandleFromRowKey(handleRow[0]) if err != nil { return err } @@ -1480,7 +1513,7 @@ func (local *local) deleteDuplicateRows(ctx context.Context, logger *log.Task, h } } - logger.Info("[resolve-dupe] number of KV pairs to be deleted", zap.Int("count", txn.Len())) + logger.Debug("[resolve-dupe] number of KV pairs to be deleted", zap.Int("count", txn.Len())) return nil } @@ -1500,17 +1533,10 @@ func (local *local) ResetEngine(ctx context.Context, engineUUID uuid.UUID) error } db, err := local.openEngineDB(engineUUID, false) if err == nil { - // Reset engineMeta except `Duplicates`. - meta := engineMeta{ - Duplicates: *atomic.NewInt64(localEngine.engineMeta.Duplicates.Load()), - } - if err := saveEngineMetaToDB(&meta, db); err != nil { - return errors.Trace(err) - } localEngine.db = db - localEngine.engineMeta = meta + localEngine.engineMeta = engineMeta{} if !common.IsDirExists(localEngine.sstDir) { - if err := os.Mkdir(localEngine.sstDir, 0o755); err != nil { + if err := os.Mkdir(localEngine.sstDir, 0o750); err != nil { return errors.Trace(err) } } @@ -1658,14 +1684,14 @@ func (local *local) LocalWriter(ctx context.Context, cfg *backend.LocalWriterCon return nil, errors.Errorf("could not find engine for %s", engineUUID.String()) } engine := e.(*Engine) - return openLocalWriter(cfg, engine, local.localWriterMemCacheSize) + return openLocalWriter(cfg, engine, local.localWriterMemCacheSize, local.bufferPool.NewBuffer()) } -func openLocalWriter(cfg *backend.LocalWriterConfig, engine *Engine, cacheSize int64) (*Writer, error) { +func openLocalWriter(cfg *backend.LocalWriterConfig, engine *Engine, cacheSize int64, kvBuffer *membuf.Buffer) (*Writer, error) { w := &Writer{ engine: engine, memtableSizeLimit: cacheSize, - kvBuffer: bufferPool.NewBuffer(), + kvBuffer: kvBuffer, isKVSorted: cfg.IsKVSorted, isWriteBatchSorted: true, } diff --git a/br/pkg/lightning/backend/local/local_test.go b/br/pkg/lightning/backend/local/local_test.go index 747034068c463..179ae09e1023c 100644 --- a/br/pkg/lightning/backend/local/local_test.go +++ b/br/pkg/lightning/backend/local/local_test.go @@ -32,20 +32,15 @@ import ( "github.com/docker/go-units" "github.com/golang/mock/gomock" "github.com/google/uuid" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/errorpb" sst "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/metapb" - pd "github.com/tikv/pd/client" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "github.com/pingcap/tidb/br/pkg/lightning/backend" "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/mydump" + "github.com/pingcap/tidb/br/pkg/membuf" "github.com/pingcap/tidb/br/pkg/mock" "github.com/pingcap/tidb/br/pkg/pdutil" "github.com/pingcap/tidb/br/pkg/restore" @@ -56,19 +51,15 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/hack" + "github.com/stretchr/testify/require" + pd "github.com/tikv/pd/client" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -type localSuite struct{} - -var _ = Suite(&localSuite{}) -var _ = SerialSuites(&testMultiIngestSuite{}) - -func Test(t *testing.T) { - TestingT(t) -} - -func (s *localSuite) TestNextKey(c *C) { - c.Assert(nextKey([]byte{}), DeepEquals, []byte{}) +func TestNextKey(t *testing.T) { + require.Equal(t, []byte{}, nextKey([]byte{})) cases := [][]byte{ {0}, @@ -77,29 +68,29 @@ func (s *localSuite) TestNextKey(c *C) { } for _, b := range cases { next := nextKey(b) - c.Assert(next, DeepEquals, append(b, 0)) + require.Equal(t, append(b, 0), next) } // in the old logic, this should return []byte{} which is not the actually smallest eky next := nextKey([]byte{1, 255}) - c.Assert(bytes.Compare(next, []byte{2}), Equals, -1) + require.Equal(t, -1, bytes.Compare(next, []byte{2})) // another test case, nextkey()'s return should be smaller than key with a prefix of the origin key next = nextKey([]byte{1, 255}) - c.Assert(bytes.Compare(next, []byte{1, 255, 0, 1, 2}), Equals, -1) + require.Equal(t, -1, bytes.Compare(next, []byte{1, 255, 0, 1, 2})) // test recode key // key with int handle for _, handleID := range []int64{math.MinInt64, 1, 255, math.MaxInt32 - 1} { key := tablecodec.EncodeRowKeyWithHandle(1, tidbkv.IntHandle(handleID)) - c.Assert(nextKey(key), DeepEquals, []byte(tablecodec.EncodeRowKeyWithHandle(1, tidbkv.IntHandle(handleID+1)))) + require.Equal(t, []byte(tablecodec.EncodeRowKeyWithHandle(1, tidbkv.IntHandle(handleID+1))), nextKey(key)) } // overflowed key := tablecodec.EncodeRowKeyWithHandle(1, tidbkv.IntHandle(math.MaxInt64)) next = tablecodec.EncodeTablePrefix(2) - c.Assert([]byte(key), Less, next) - c.Assert(nextKey(key), DeepEquals, next) + require.Less(t, string(key), string(next)) + require.Equal(t, next, nextKey(key)) testDatums := [][]types.Datum{ {types.NewIntDatum(1), types.NewIntDatum(2)}, @@ -112,27 +103,27 @@ func (s *localSuite) TestNextKey(c *C) { stmtCtx := new(stmtctx.StatementContext) for _, datums := range testDatums { keyBytes, err := codec.EncodeKey(stmtCtx, nil, types.NewIntDatum(123), datums[0]) - c.Assert(err, IsNil) + require.NoError(t, err) h, err := tidbkv.NewCommonHandle(keyBytes) - c.Assert(err, IsNil) + require.NoError(t, err) key := tablecodec.EncodeRowKeyWithHandle(1, h) nextKeyBytes, err := codec.EncodeKey(stmtCtx, nil, types.NewIntDatum(123), datums[1]) - c.Assert(err, IsNil) + require.NoError(t, err) nextHdl, err := tidbkv.NewCommonHandle(nextKeyBytes) - c.Assert(err, IsNil) + require.NoError(t, err) expectNextKey := []byte(tablecodec.EncodeRowKeyWithHandle(1, nextHdl)) - c.Assert(nextKey(key), DeepEquals, expectNextKey) + require.Equal(t, expectNextKey, nextKey(key)) } // dIAAAAAAAAD/PV9pgAAAAAD/AAABA4AAAAD/AAAAAQOAAAD/AAAAAAEAAAD8 // a index key with: table: 61, index: 1, int64: 1, int64: 1 a := []byte{116, 128, 0, 0, 0, 0, 0, 0, 255, 61, 95, 105, 128, 0, 0, 0, 0, 255, 0, 0, 1, 3, 128, 0, 0, 0, 255, 0, 0, 0, 1, 3, 128, 0, 0, 255, 0, 0, 0, 0, 1, 0, 0, 0, 252} - c.Assert(nextKey(a), DeepEquals, append(a, 0)) + require.Equal(t, append(a, 0), nextKey(a)) } // The first half of this test is same as the test in tikv: // https://github.com/tikv/tikv/blob/dbfe7730dd0fddb34cb8c3a7f8a079a1349d2d41/components/engine_rocks/src/properties.rs#L572 -func (s *localSuite) TestRangeProperties(c *C) { +func TestRangeProperties(t *testing.T) { type testCase struct { key []byte vLen int @@ -167,36 +158,21 @@ func (s *localSuite) TestRangeProperties(c *C) { for _, p := range cases { v := make([]byte, p.vLen) for i := 0; i < p.count; i++ { - _ = collector.Add(pebble.InternalKey{UserKey: p.key}, v) + _ = collector.Add(pebble.InternalKey{UserKey: p.key, Trailer: pebble.InternalKeyKindSet}, v) } } userProperties := make(map[string]string, 1) _ = collector.Finish(userProperties) - props, err := decodeRangeProperties(hack.Slice(userProperties[propRangeIndex])) - c.Assert(err, IsNil) + props, err := decodeRangeProperties(hack.Slice(userProperties[propRangeIndex]), noopKeyAdapter{}) + require.NoError(t, err) // Smallest key in props. - c.Assert(props[0].Key, DeepEquals, cases[0].key) + require.Equal(t, cases[0].key, props[0].Key) // Largest key in props. - c.Assert(props[len(props)-1].Key, DeepEquals, cases[len(cases)-1].key) - c.Assert(len(props), Equals, 7) - - a := props.get([]byte("a")) - c.Assert(a.Size, Equals, uint64(1)) - e := props.get([]byte("e")) - c.Assert(e.Size, Equals, uint64(defaultPropSizeIndexDistance+5)) - i := props.get([]byte("i")) - c.Assert(i.Size, Equals, uint64(defaultPropSizeIndexDistance/8*17+9)) - k := props.get([]byte("k")) - c.Assert(k.Size, Equals, uint64(defaultPropSizeIndexDistance/8*25+11)) - m := props.get([]byte("m")) - c.Assert(m.Keys, Equals, uint64(defaultPropKeysIndexDistance+11)) - n := props.get([]byte("n")) - c.Assert(n.Keys, Equals, uint64(defaultPropKeysIndexDistance*2+11)) - o := props.get([]byte("o")) - c.Assert(o.Keys, Equals, uint64(defaultPropKeysIndexDistance*2+12)) + require.Equal(t, cases[len(cases)-1].key, props[len(props)-1].Key) + require.Len(t, props, 7) props2 := rangeProperties([]rangeProperty{ {[]byte("b"), rangeOffsets{defaultPropSizeIndexDistance + 10, defaultPropKeysIndexDistance / 2}}, @@ -226,10 +202,10 @@ func (s *localSuite) TestRangeProperties(c *C) { {[]byte("y"), rangeOffsets{100, 1000}}, } - c.Assert(sizeProps.indexHandles.Len(), Equals, 12) + require.Equal(t, 12, sizeProps.indexHandles.Len()) idx := 0 sizeProps.iter(func(p *rangeProperty) bool { - c.Assert(p, DeepEquals, res[idx]) + require.Equal(t, res[idx], p) idx++ return true }) @@ -237,16 +213,16 @@ func (s *localSuite) TestRangeProperties(c *C) { fullRange := Range{start: []byte("a"), end: []byte("z")} ranges := splitRangeBySizeProps(fullRange, sizeProps, 2*defaultPropSizeIndexDistance, defaultPropKeysIndexDistance*5/2) - c.Assert(ranges, DeepEquals, []Range{ + require.Equal(t, []Range{ {start: []byte("a"), end: []byte("e")}, {start: []byte("e"), end: []byte("k")}, {start: []byte("k"), end: []byte("mm")}, {start: []byte("mm"), end: []byte("q")}, {start: []byte("q"), end: []byte("z")}, - }) + }, ranges) ranges = splitRangeBySizeProps(fullRange, sizeProps, 2*defaultPropSizeIndexDistance, defaultPropKeysIndexDistance) - c.Assert(ranges, DeepEquals, []Range{ + require.Equal(t, []Range{ {start: []byte("a"), end: []byte("e")}, {start: []byte("e"), end: []byte("h")}, {start: []byte("h"), end: []byte("k")}, @@ -255,11 +231,11 @@ func (s *localSuite) TestRangeProperties(c *C) { {start: []byte("mm"), end: []byte("n")}, {start: []byte("n"), end: []byte("q")}, {start: []byte("q"), end: []byte("z")}, - }) + }, ranges) } -func (s *localSuite) TestRangePropertiesWithPebble(c *C) { - dir := c.MkDir() +func TestRangePropertiesWithPebble(t *testing.T) { + dir := t.TempDir() sizeDistance := uint64(500) keysDistance := uint64(20) @@ -282,7 +258,7 @@ func (s *localSuite) TestRangePropertiesWithPebble(c *C) { }, } db, err := pebble.Open(filepath.Join(dir, "test"), opt) - c.Assert(err, IsNil) + require.NoError(t, err) defer db.Close() // local collector @@ -300,33 +276,33 @@ func (s *localSuite) TestRangePropertiesWithPebble(c *C) { valueLen := rand.Intn(50) binary.BigEndian.PutUint64(key, uint64(i*100+j)) err = wb.Set(key, value[:valueLen], writeOpt) - c.Assert(err, IsNil) - err = collector.Add(pebble.InternalKey{UserKey: key}, value[:valueLen]) - c.Assert(err, IsNil) + require.NoError(t, err) + err = collector.Add(pebble.InternalKey{UserKey: key, Trailer: pebble.InternalKeyKindSet}, value[:valueLen]) + require.NoError(t, err) } - c.Assert(wb.Commit(writeOpt), IsNil) + require.NoError(t, wb.Commit(writeOpt)) } // flush one sst - c.Assert(db.Flush(), IsNil) + require.NoError(t, db.Flush()) props := make(map[string]string, 1) - c.Assert(collector.Finish(props), IsNil) + require.NoError(t, collector.Finish(props)) sstMetas, err := db.SSTables(pebble.WithProperties()) - c.Assert(err, IsNil) + require.NoError(t, err) for i, level := range sstMetas { if i == 0 { - c.Assert(len(level), Equals, 1) + require.Equal(t, 1, len(level)) } else { - c.Assert(len(level), Equals, 0) + require.Empty(t, level) } } - c.Assert(sstMetas[0][0].Properties.UserProperties, DeepEquals, props) + require.Equal(t, props, sstMetas[0][0].Properties.UserProperties) } -func testLocalWriter(c *C, needSort bool, partitialSort bool) { - dir := c.MkDir() +func testLocalWriter(t *testing.T, needSort bool, partitialSort bool) { + dir := t.TempDir() opt := &pebble.Options{ MemTableSize: 1024 * 1024, MaxConcurrentCompactions: 16, @@ -336,11 +312,11 @@ func testLocalWriter(c *C, needSort bool, partitialSort bool) { ReadOnly: false, } db, err := pebble.Open(filepath.Join(dir, "test"), opt) - c.Assert(err, IsNil) + require.NoError(t, err) defer db.Close() tmpPath := filepath.Join(dir, "test.sst") err = os.Mkdir(tmpPath, 0o755) - c.Assert(err, IsNil) + require.NoError(t, err) _, engineUUID := backend.MakeUUID("ww", 0) engineCtx, cancel := context.WithCancel(context.Background()) @@ -357,8 +333,11 @@ func testLocalWriter(c *C, needSort bool, partitialSort bool) { f.wg.Add(1) go f.ingestSSTLoop() sorted := needSort && !partitialSort - w, err := openLocalWriter(&backend.LocalWriterConfig{IsKVSorted: sorted}, f, 1024) - c.Assert(err, IsNil) + pool := membuf.NewPool() + defer pool.Destroy() + kvBuffer := pool.NewBuffer() + w, err := openLocalWriter(&backend.LocalWriterConfig{IsKVSorted: sorted}, f, 1024, kvBuffer) + require.NoError(t, err) ctx := context.Background() var kvs []common.KvPair @@ -400,43 +379,43 @@ func testLocalWriter(c *C, needSort bool, partitialSort bool) { rows3 = kvs[12000:] } err = w.AppendRows(ctx, "", []string{}, kv.MakeRowsFromKvPairs(rows1)) - c.Assert(err, IsNil) + require.NoError(t, err) err = w.AppendRows(ctx, "", []string{}, kv.MakeRowsFromKvPairs(rows2)) - c.Assert(err, IsNil) + require.NoError(t, err) err = w.AppendRows(ctx, "", []string{}, kv.MakeRowsFromKvPairs(rows3)) - c.Assert(err, IsNil) + require.NoError(t, err) flushStatus, err := w.Close(context.Background()) - c.Assert(err, IsNil) - c.Assert(f.flushEngineWithoutLock(ctx), IsNil) - c.Assert(flushStatus.Flushed(), IsTrue) + require.NoError(t, err) + require.NoError(t, f.flushEngineWithoutLock(ctx)) + require.True(t, flushStatus.Flushed()) o := &pebble.IterOptions{} it := db.NewIter(o) sort.Slice(keys, func(i, j int) bool { return bytes.Compare(keys[i], keys[j]) < 0 }) - c.Assert(int(f.Length.Load()), Equals, 20000) - c.Assert(int(f.TotalSize.Load()), Equals, 144*20000) + require.Equal(t, 20000, int(f.Length.Load())) + require.Equal(t, 144*20000, int(f.TotalSize.Load())) valid := it.SeekGE(keys[0]) - c.Assert(valid, IsTrue) + require.True(t, valid) for _, k := range keys { - c.Assert(it.Key(), DeepEquals, k) + require.Equal(t, k, it.Key()) it.Next() } close(f.sstMetasChan) f.wg.Wait() } -func (s *localSuite) TestLocalWriterWithSort(c *C) { - testLocalWriter(c, false, false) +func TestLocalWriterWithSort(t *testing.T) { + testLocalWriter(t, false, false) } -func (s *localSuite) TestLocalWriterWithIngest(c *C) { - testLocalWriter(c, true, false) +func TestLocalWriterWithIngest(t *testing.T) { + testLocalWriter(t, true, false) } -func (s *localSuite) TestLocalWriterWithIngestUnsort(c *C) { - testLocalWriter(c, true, true) +func TestLocalWriterWithIngestUnsort(t *testing.T) { + testLocalWriter(t, true, true) } type mockSplitClient struct { @@ -453,7 +432,7 @@ func (c *mockSplitClient) GetRegion(ctx context.Context, key []byte) (*restore.R }, nil } -func (s *localSuite) TestIsIngestRetryable(c *C) { +func TestIsIngestRetryable(t *testing.T) { local := &local{ splitCli: &mockSplitClient{}, } @@ -493,9 +472,9 @@ func (s *localSuite) TestIsIngestRetryable(c *C) { }, } retryType, newRegion, err := local.isIngestRetryable(ctx, resp, region, metas) - c.Assert(retryType, Equals, retryWrite) - c.Assert(newRegion.Leader.Id, Equals, uint64(2)) - c.Assert(err, NotNil) + require.Equal(t, retryWrite, retryType) + require.Equal(t, uint64(2), newRegion.Leader.Id) + require.Error(t, err) resp.Error = &errorpb.Error{ EpochNotMatch: &errorpb.EpochNotMatch{ @@ -514,19 +493,19 @@ func (s *localSuite) TestIsIngestRetryable(c *C) { }, } retryType, newRegion, err = local.isIngestRetryable(ctx, resp, region, metas) - c.Assert(retryType, Equals, retryWrite) - c.Assert(newRegion.Region.RegionEpoch.Version, Equals, uint64(2)) - c.Assert(err, NotNil) + require.Equal(t, retryWrite, retryType) + require.Equal(t, uint64(2), newRegion.Region.RegionEpoch.Version) + require.Error(t, err) resp.Error = &errorpb.Error{Message: "raft: proposal dropped"} retryType, _, err = local.isIngestRetryable(ctx, resp, region, metas) - c.Assert(retryType, Equals, retryWrite) - c.Assert(err, NotNil) + require.Equal(t, retryWrite, retryType) + require.Error(t, err) resp.Error = &errorpb.Error{Message: "unknown error"} retryType, _, err = local.isIngestRetryable(ctx, resp, region, metas) - c.Assert(retryType, Equals, retryNone) - c.Assert(err, ErrorMatches, "non-retryable error: unknown error") + require.Equal(t, retryNone, retryType) + require.EqualError(t, err, "non-retryable error: unknown error") } type testIngester struct{} @@ -555,8 +534,8 @@ func (i testIngester) ingest([]*sstMeta) error { return nil } -func (s *localSuite) TestLocalIngestLoop(c *C) { - dir := c.MkDir() +func TestLocalIngestLoop(t *testing.T) { + dir := t.TempDir() opt := &pebble.Options{ MemTableSize: 1024 * 1024, MaxConcurrentCompactions: 16, @@ -566,11 +545,11 @@ func (s *localSuite) TestLocalIngestLoop(c *C) { ReadOnly: false, } db, err := pebble.Open(filepath.Join(dir, "test"), opt) - c.Assert(err, IsNil) + require.NoError(t, err) defer db.Close() tmpPath := filepath.Join(dir, "test.sst") err = os.Mkdir(tmpPath, 0o755) - c.Assert(err, IsNil) + require.NoError(t, err) _, engineUUID := backend.MakeUUID("ww", 0) engineCtx, cancel := context.WithCancel(context.Background()) f := Engine{ @@ -608,11 +587,11 @@ func (s *localSuite) TestLocalIngestLoop(c *C) { m := &sstMeta{totalSize: size, totalCount: 1} atomic.AddInt64(&totalSize, size) metaSeq, err := f.addSST(engineCtx, m) - c.Assert(err, IsNil) + require.NoError(t, err) if int32(i) >= flushCnt { f.mutex.RLock() err = f.flushEngineWithoutLock(engineCtx) - c.Assert(err, IsNil) + require.NoError(t, err) f.mutex.RUnlock() flushCnt += rand.Int31n(10) + 1 } @@ -629,19 +608,19 @@ func (s *localSuite) TestLocalIngestLoop(c *C) { f.mutex.RLock() err = f.flushEngineWithoutLock(engineCtx) - c.Assert(err, IsNil) + require.NoError(t, err) f.mutex.RUnlock() close(f.sstMetasChan) f.wg.Wait() - c.Assert(f.ingestErr.Get(), IsNil) - c.Assert(totalSize, Equals, f.TotalSize.Load()) - c.Assert(f.Length.Load(), Equals, int64(concurrency*count)) - c.Assert(f.finishedMetaSeq.Load(), Equals, atomic.LoadInt32(&maxMetaSeq)) + require.NoError(t, f.ingestErr.Get()) + require.Equal(t, f.TotalSize.Load(), totalSize) + require.Equal(t, int64(concurrency*count), f.Length.Load()) + require.Equal(t, atomic.LoadInt32(&maxMetaSeq), f.finishedMetaSeq.Load()) } -func (s *localSuite) TestCheckRequirementsTiFlash(c *C) { - controller := gomock.NewController(c) +func TestCheckRequirementsTiFlash(t *testing.T) { + controller := gomock.NewController(t) defer controller.Finish() glue := mock.NewMockGlue(controller) exec := mock.NewMockSQLExecutor(controller) @@ -686,7 +665,7 @@ func (s *localSuite) TestCheckRequirementsTiFlash(c *C) { Return([][]string{{"db", "tbl"}, {"test", "t1"}, {"test1", "tbl"}}, nil) err := checkTiFlashVersion(ctx, glue, checkCtx, *semver.New("4.0.2")) - c.Assert(err, ErrorMatches, "lightning local backend doesn't support TiFlash in this TiDB version. conflict tables: \\[`test`.`t1`, `test1`.`tbl`\\].*") + require.Regexp(t, "^lightning local backend doesn't support TiFlash in this TiDB version. conflict tables: \\[`test`.`t1`, `test1`.`tbl`\\]", err.Error()) } func makeRanges(input []string) []Range { @@ -697,7 +676,7 @@ func makeRanges(input []string) []Range { return ranges } -func (s *localSuite) TestDedupAndMergeRanges(c *C) { +func TestDedupAndMergeRanges(t *testing.T) { cases := [][]string{ // empty {}, @@ -725,11 +704,11 @@ func (s *localSuite) TestDedupAndMergeRanges(c *C) { input := makeRanges(cases[i]) output := makeRanges(cases[i+1]) - c.Assert(sortAndMergeRanges(input), DeepEquals, output) + require.Equal(t, output, sortAndMergeRanges(input)) } } -func (s *localSuite) TestFilterOverlapRange(c *C) { +func TestFilterOverlapRange(t *testing.T) { cases := [][]string{ // both empty input {}, @@ -767,12 +746,12 @@ func (s *localSuite) TestFilterOverlapRange(c *C) { finished := makeRanges(cases[i+1]) output := makeRanges(cases[i+2]) - c.Assert(filterOverlapRange(input, finished), DeepEquals, output) + require.Equal(t, output, filterOverlapRange(input, finished)) } } -func (s *localSuite) testMergeSSTs(c *C, kvs [][]common.KvPair, meta *sstMeta) { - dir := c.MkDir() +func testMergeSSTs(t *testing.T, kvs [][]common.KvPair, meta *sstMeta) { + dir := t.TempDir() opt := &pebble.Options{ MemTableSize: 1024 * 1024, MaxConcurrentCompactions: 16, @@ -782,11 +761,11 @@ func (s *localSuite) testMergeSSTs(c *C, kvs [][]common.KvPair, meta *sstMeta) { ReadOnly: false, } db, err := pebble.Open(filepath.Join(dir, "test"), opt) - c.Assert(err, IsNil) + require.NoError(t, err) defer db.Close() tmpPath := filepath.Join(dir, "test.sst") err = os.Mkdir(tmpPath, 0o755) - c.Assert(err, IsNil) + require.NoError(t, err) _, engineUUID := backend.MakeUUID("ww", 0) engineCtx, cancel := context.WithCancel(context.Background()) @@ -818,24 +797,24 @@ func (s *localSuite) testMergeSSTs(c *C, kvs [][]common.KvPair, meta *sstMeta) { for _, kv := range kvs { w, err := createSSTWriter() - c.Assert(err, IsNil) + require.NoError(t, err) err = w.writeKVs(kv) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(w.writer.Close(), IsNil) + require.NoError(t, w.writer.Close()) metas = append(metas, w.sstMeta) } i := dbSSTIngester{e: f} newMeta, err := i.mergeSSTs(metas, tmpPath) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(newMeta.totalCount, Equals, meta.totalCount) - c.Assert(newMeta.totalSize, Equals, meta.totalSize) + require.Equal(t, meta.totalCount, newMeta.totalCount) + require.Equal(t, meta.totalSize, newMeta.totalSize) } -func (s *localSuite) TestMergeSSTs(c *C) { +func TestMergeSSTs(t *testing.T) { kvs := make([][]common.KvPair, 0, 5) for i := 0; i < 5; i++ { @@ -851,10 +830,10 @@ func (s *localSuite) TestMergeSSTs(c *C) { kvs = append(kvs, pairs) } - s.testMergeSSTs(c, kvs, &sstMeta{totalCount: 50, totalSize: 800}) + testMergeSSTs(t, kvs, &sstMeta{totalCount: 50, totalSize: 800}) } -func (s *localSuite) TestMergeSSTsDuplicated(c *C) { +func TestMergeSSTsDuplicated(t *testing.T) { kvs := make([][]common.KvPair, 0, 5) for i := 0; i < 4; i++ { var pairs []common.KvPair @@ -872,7 +851,7 @@ func (s *localSuite) TestMergeSSTsDuplicated(c *C) { // make a duplication kvs = append(kvs, kvs[0]) - s.testMergeSSTs(c, kvs, &sstMeta{totalCount: 40, totalSize: 640}) + testMergeSSTs(t, kvs, &sstMeta{totalCount: 40, totalSize: 640}) } type mockPdClient struct { @@ -896,8 +875,7 @@ func (e mockGrpcErr) Error() string { type mockImportClient struct { sst.ImportSSTClient - stores []*metapb.Store - curStore *metapb.Store + store *metapb.Store err error retry int cnt int @@ -912,32 +890,29 @@ func (c *mockImportClient) MultiIngest(context.Context, *sst.MultiIngestRequest, return nil, c.err } - if !c.multiIngestCheckFn(c.curStore) { + if !c.multiIngestCheckFn(c.store) { return nil, mockGrpcErr{} } return nil, nil } -type testMultiIngestSuite struct { - local *local - pdCli *mockPdClient +type mockImportClientFactory struct { + stores []*metapb.Store + createClientFn func(store *metapb.Store) sst.ImportSSTClient } -func (s *testMultiIngestSuite) SetUpSuite(c *C) { - local := &local{ - pdCtl: &pdutil.PdController{}, +func (f *mockImportClientFactory) Create(_ context.Context, storeID uint64) (sst.ImportSSTClient, error) { + for _, store := range f.stores { + if store.Id == storeID { + return f.createClientFn(store), nil + } } - pdCli := &mockPdClient{} - local.pdCtl.SetPDClient(pdCli) - s.local = local - s.pdCli = pdCli + return nil, errors.New("store not found") } -func (s *testMultiIngestSuite) TestMultiIngest(c *C) { - defer func() { - getImportClientFn = getImportClient - }() +func (f *mockImportClientFactory) Close() {} +func TestMultiIngest(t *testing.T) { allStores := []*metapb.Store{ { Id: 1, @@ -1187,30 +1162,29 @@ func (s *testMultiIngestSuite) TestMultiIngest(c *C) { } importCli := &mockImportClient{ - stores: allStores, cnt: 0, retry: testCase.retry, err: testCase.err, multiIngestCheckFn: testCase.multiIngestSupport, } - s.pdCli.stores = stores - - getImportClientFn = func(local *local, ctx context.Context, storeID uint64) (sst.ImportSSTClient, error) { - for _, store := range importCli.stores { - if store.Id == storeID { - importCli.curStore = store - break - } - } - return importCli, nil + pdCtl := &pdutil.PdController{} + pdCtl.SetPDClient(&mockPdClient{stores: stores}) + + local := &local{ + pdCtl: pdCtl, + importClientFactory: &mockImportClientFactory{ + stores: allStores, + createClientFn: func(store *metapb.Store) sst.ImportSSTClient { + importCli.store = store + return importCli + }, + }, } - s.local.supportMultiIngest = false - - err := s.local.checkMultiIngestSupport(context.Background()) + err := local.checkMultiIngestSupport(context.Background()) if err != nil { - c.Assert(err, ErrorMatches, testCase.retErr) + require.Contains(t, err.Error(), testCase.retErr) } else { - c.Assert(s.local.supportMultiIngest, Equals, testCase.supportMutliIngest) + require.Equal(t, testCase.supportMutliIngest, local.supportMultiIngest) } } } diff --git a/br/pkg/lightning/backend/local/localhelper.go b/br/pkg/lightning/backend/local/localhelper.go index bc7a7a65d2a4c..d2ea78c6a80b0 100644 --- a/br/pkg/lightning/backend/local/localhelper.go +++ b/br/pkg/lightning/backend/local/localhelper.go @@ -43,7 +43,6 @@ import ( ) const ( - SplitRetryTimes = 8 retrySplitMaxWaitTime = 4 * time.Second ) @@ -56,6 +55,8 @@ var ( // the base exponential backoff time // the variable is only changed in unit test for running test faster. splitRegionBaseBackOffTime = time.Second + // the max retry times to split regions. + splitRetryTimes = 8 ) // TODO remove this file and use br internal functions @@ -85,7 +86,7 @@ func (local *local) SplitAndScatterRegionByRanges( var retryKeys [][]byte waitTime := splitRegionBaseBackOffTime skippedKeys := 0 - for i := 0; i < SplitRetryTimes; i++ { + for i := 0; i < splitRetryTimes; i++ { log.L().Info("split and scatter region", logutil.Key("minKey", minKey), logutil.Key("maxKey", maxKey), diff --git a/br/pkg/lightning/backend/local/localhelper_test.go b/br/pkg/lightning/backend/local/localhelper_test.go index d901b3c2711e6..dd52b71493507 100644 --- a/br/pkg/lightning/backend/local/localhelper_test.go +++ b/br/pkg/lightning/backend/local/localhelper_test.go @@ -21,9 +21,9 @@ import ( "math/rand" "sort" "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/kvproto/pkg/pdpb" @@ -32,19 +32,25 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" - "github.com/tikv/pd/server/core" - "github.com/tikv/pd/server/schedule/placement" + "github.com/stretchr/testify/require" "go.uber.org/atomic" ) +func init() { + // Reduce the time cost for test cases. + restore.ScanRegionAttemptTimes = 2 + splitRetryTimes = 2 +} + type testClient struct { mu sync.RWMutex stores map[uint64]*metapb.Store regions map[uint64]*restore.RegionInfo - regionsInfo *core.RegionsInfo // For now it's only used in ScanRegions + regionsInfo *pdtypes.RegionTree // For now it's only used in ScanRegions nextRegionID uint64 splitCount atomic.Int32 hook clientHook @@ -56,9 +62,9 @@ func newTestClient( nextRegionID uint64, hook clientHook, ) *testClient { - regionsInfo := core.NewRegionsInfo() + regionsInfo := &pdtypes.RegionTree{} for _, regionInfo := range regions { - regionsInfo.SetRegion(core.NewRegionInfo(regionInfo.Region, regionInfo.Leader)) + regionsInfo.SetRegion(pdtypes.NewRegionInfo(regionInfo.Region, regionInfo.Leader)) } return &testClient{ stores: stores, @@ -69,6 +75,11 @@ func newTestClient( } } +// ScatterRegions scatters regions in a batch. +func (c *testClient) ScatterRegions(ctx context.Context, regionInfo []*restore.RegionInfo) error { + return nil +} + func (c *testClient) GetAllRegions() map[uint64]*restore.RegionInfo { c.mu.RLock() defer c.mu.RUnlock() @@ -138,12 +149,12 @@ func (c *testClient) SplitRegion( }, } c.regions[c.nextRegionID] = newRegion - c.regionsInfo.SetRegion(core.NewRegionInfo(newRegion.Region, newRegion.Leader)) + c.regionsInfo.SetRegion(pdtypes.NewRegionInfo(newRegion.Region, newRegion.Leader)) c.nextRegionID++ target.Region.StartKey = splitKey target.Region.RegionEpoch.ConfVer++ c.regions[target.Region.Id] = target - c.regionsInfo.SetRegion(core.NewRegionInfo(target.Region, target.Leader)) + c.regionsInfo.SetRegion(pdtypes.NewRegionInfo(target.Region, target.Leader)) return newRegion, nil } @@ -199,7 +210,7 @@ func (c *testClient) BatchSplitRegionsWithOrigin( }, } c.regions[c.nextRegionID] = newRegion - c.regionsInfo.SetRegion(core.NewRegionInfo(newRegion.Region, newRegion.Leader)) + c.regionsInfo.SetRegion(pdtypes.NewRegionInfo(newRegion.Region, newRegion.Leader)) c.nextRegionID++ startKey = key newRegions = append(newRegions, newRegion) @@ -207,7 +218,7 @@ func (c *testClient) BatchSplitRegionsWithOrigin( if !bytes.Equal(target.Region.StartKey, startKey) { target.Region.StartKey = startKey c.regions[target.Region.Id] = target - c.regionsInfo.SetRegion(core.NewRegionInfo(target.Region, target.Leader)) + c.regionsInfo.SetRegion(pdtypes.NewRegionInfo(target.Region, target.Leader)) } if len(newRegions) == 0 { @@ -248,8 +259,8 @@ func (c *testClient) ScanRegions(ctx context.Context, key, endKey []byte, limit regions := make([]*restore.RegionInfo, 0, len(infos)) for _, info := range infos { regions = append(regions, &restore.RegionInfo{ - Region: info.GetMeta(), - Leader: info.GetLeader(), + Region: info.Meta, + Leader: info.Leader, }) } @@ -260,11 +271,11 @@ func (c *testClient) ScanRegions(ctx context.Context, key, endKey []byte, limit return regions, err } -func (c *testClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (r placement.Rule, err error) { +func (c *testClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (r pdtypes.Rule, err error) { return } -func (c *testClient) SetPlacementRule(ctx context.Context, rule placement.Rule) error { +func (c *testClient) SetPlacementRule(ctx context.Context, rule pdtypes.Rule) error { return nil } @@ -325,12 +336,12 @@ func initTestClient(keys [][]byte, hook clientHook) *testClient { return newTestClient(stores, regions, uint64(len(keys)), hook) } -func checkRegionRanges(c *C, regions []*restore.RegionInfo, keys [][]byte) { +func checkRegionRanges(t *testing.T, regions []*restore.RegionInfo, keys [][]byte) { for i, r := range regions { _, regionStart, _ := codec.DecodeBytes(r.Region.StartKey, []byte{}) _, regionEnd, _ := codec.DecodeBytes(r.Region.EndKey, []byte{}) - c.Assert(regionStart, DeepEquals, keys[i]) - c.Assert(regionEnd, DeepEquals, keys[i+1]) + require.Equal(t, keys[i], regionStart) + require.Equal(t, keys[i+1], regionEnd) } } @@ -362,13 +373,13 @@ func (h *noopHook) AfterScanRegions(res []*restore.RegionInfo, err error) ([]*re } type batchSplitHook interface { - setup(c *C) func() - check(c *C, cli *testClient) + setup(t *testing.T) func() + check(t *testing.T, cli *testClient) } type defaultHook struct{} -func (d defaultHook) setup(*C) func() { +func (d defaultHook) setup(t *testing.T) func() { oldLimit := maxBatchSplitKeys oldSplitBackoffTime := splitRegionBaseBackOffTime maxBatchSplitKeys = 4 @@ -379,7 +390,7 @@ func (d defaultHook) setup(*C) func() { } } -func (d defaultHook) check(c *C, cli *testClient) { +func (d defaultHook) check(t *testing.T, cli *testClient) { // so with a batch split size of 4, there will be 7 time batch split // 1. region: [aay, bba), keys: [b, ba, bb] // 2. region: [bbh, cca), keys: [bc, bd, be, bf] @@ -390,14 +401,14 @@ func (d defaultHook) check(c *C, cli *testClient) { // 7. region: [bv, cca), keys: [bw, bx, by, bz] // since it may encounter error retries, here only check the lower threshold. - c.Assert(cli.splitCount.Load() >= 7, IsTrue) + require.GreaterOrEqual(t, cli.splitCount.Load(), int32(7)) } -func (s *localSuite) doTestBatchSplitRegionByRanges(ctx context.Context, c *C, hook clientHook, errPat string, splitHook batchSplitHook) { +func doTestBatchSplitRegionByRanges(ctx context.Context, t *testing.T, hook clientHook, errPat string, splitHook batchSplitHook) { if splitHook == nil { splitHook = defaultHook{} } - deferFunc := splitHook.setup(c) + deferFunc := splitHook.setup(t) defer deferFunc() keys := [][]byte{[]byte(""), []byte("aay"), []byte("bba"), []byte("bbh"), []byte("cca"), []byte("")} @@ -411,9 +422,9 @@ func (s *localSuite) doTestBatchSplitRegionByRanges(ctx context.Context, c *C, h rangeStart := codec.EncodeBytes([]byte{}, []byte("b")) rangeEnd := codec.EncodeBytes([]byte{}, []byte("c")) regions, err := restore.PaginateScanRegion(ctx, client, rangeStart, rangeEnd, 5) - c.Assert(err, IsNil) + require.NoError(t, err) // regions is: [aay, bba), [bba, bbh), [bbh, cca) - checkRegionRanges(c, regions, [][]byte{[]byte("aay"), []byte("bba"), []byte("bbh"), []byte("cca")}) + checkRegionRanges(t, regions, [][]byte{[]byte("aay"), []byte("bba"), []byte("bbh"), []byte("cca")}) // generate: ranges [b, ba), [ba, bb), [bb, bc), ... [by, bz) ranges := make([]Range, 0) @@ -426,17 +437,18 @@ func (s *localSuite) doTestBatchSplitRegionByRanges(ctx context.Context, c *C, h err = local.SplitAndScatterRegionByRanges(ctx, ranges, nil, true, 1000) if len(errPat) == 0 { - c.Assert(err, IsNil) + require.NoError(t, err) } else { - c.Assert(err, ErrorMatches, errPat) + require.Error(t, err) + require.Regexp(t, errPat, err.Error()) return } - splitHook.check(c, client) + splitHook.check(t, client) // check split ranges regions, err = restore.PaginateScanRegion(ctx, client, rangeStart, rangeEnd, 5) - c.Assert(err, IsNil) + require.NoError(t, err) result := [][]byte{ []byte("b"), []byte("ba"), []byte("bb"), []byte("bba"), []byte("bbh"), []byte("bc"), []byte("bd"), []byte("be"), []byte("bf"), []byte("bg"), []byte("bh"), []byte("bi"), []byte("bj"), @@ -444,16 +456,16 @@ func (s *localSuite) doTestBatchSplitRegionByRanges(ctx context.Context, c *C, h []byte("br"), []byte("bs"), []byte("bt"), []byte("bu"), []byte("bv"), []byte("bw"), []byte("bx"), []byte("by"), []byte("bz"), []byte("cca"), } - checkRegionRanges(c, regions, result) + checkRegionRanges(t, regions, result) } -func (s *localSuite) TestBatchSplitRegionByRanges(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, nil, "", nil) +func TestBatchSplitRegionByRanges(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, nil, "", nil) } type batchSizeHook struct{} -func (h batchSizeHook) setup(c *C) func() { +func (h batchSizeHook) setup(t *testing.T) func() { oldSizeLimit := maxBatchSplitSize oldSplitBackoffTime := splitRegionBaseBackOffTime maxBatchSplitSize = 6 @@ -464,7 +476,7 @@ func (h batchSizeHook) setup(c *C) func() { } } -func (h batchSizeHook) check(c *C, cli *testClient) { +func (h batchSizeHook) check(t *testing.T, cli *testClient) { // so with a batch split key size of 6, there will be 9 time batch split // 1. region: [aay, bba), keys: [b, ba, bb] // 2. region: [bbh, cca), keys: [bc, bd, be] @@ -477,11 +489,11 @@ func (h batchSizeHook) check(c *C, cli *testClient) { // 10. region: [bv, cca), keys: [bx, by, bz] // since it may encounter error retries, here only check the lower threshold. - c.Assert(cli.splitCount.Load(), Equals, int32(9)) + require.Equal(t, int32(9), cli.splitCount.Load()) } -func (s *localSuite) TestBatchSplitRegionByRangesKeySizeLimit(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, nil, "", batchSizeHook{}) +func TestBatchSplitRegionByRangesKeySizeLimit(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, nil, "", batchSizeHook{}) } type scanRegionEmptyHook struct { @@ -498,8 +510,8 @@ func (h *scanRegionEmptyHook) AfterScanRegions(res []*restore.RegionInfo, err er return nil, err } -func (s *localSuite) TestBatchSplitRegionByRangesScanFailed(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, &scanRegionEmptyHook{}, ".*scan region return empty result.*", defaultHook{}) +func TestBatchSplitRegionByRangesScanFailed(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, &scanRegionEmptyHook{}, "scan region return empty result", defaultHook{}) } type splitRegionEpochNotMatchHook struct { @@ -514,8 +526,8 @@ func (h *splitRegionEpochNotMatchHook) BeforeSplitRegion(ctx context.Context, re return regionInfo, keys } -func (s *localSuite) TestBatchSplitByRangesEpochNotMatch(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, &splitRegionEpochNotMatchHook{}, "batch split regions failed: epoch not match.*", defaultHook{}) +func TestBatchSplitByRangesEpochNotMatch(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, &splitRegionEpochNotMatchHook{}, "batch split regions failed: epoch not match", defaultHook{}) } // return epoch not match error in every other call @@ -535,8 +547,8 @@ func (h *splitRegionEpochNotMatchHookRandom) BeforeSplitRegion(ctx context.Conte return regionInfo, keys } -func (s *localSuite) TestBatchSplitByRangesEpochNotMatchOnce(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, &splitRegionEpochNotMatchHookRandom{}, "", defaultHook{}) +func TestBatchSplitByRangesEpochNotMatchOnce(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, &splitRegionEpochNotMatchHookRandom{}, "", defaultHook{}) } type splitRegionNoValidKeyHook struct { @@ -554,12 +566,12 @@ func (h *splitRegionNoValidKeyHook) BeforeSplitRegion(ctx context.Context, regio return regionInfo, keys } -func (s *localSuite) TestBatchSplitByRangesNoValidKeysOnce(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, &splitRegionNoValidKeyHook{returnErrTimes: 1}, "", defaultHook{}) +func TestBatchSplitByRangesNoValidKeysOnce(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, &splitRegionNoValidKeyHook{returnErrTimes: 1}, "", defaultHook{}) } -func (s *localSuite) TestBatchSplitByRangesNoValidKeys(c *C) { - s.doTestBatchSplitRegionByRanges(context.Background(), c, &splitRegionNoValidKeyHook{returnErrTimes: math.MaxInt32}, ".*no valid key.*", defaultHook{}) +func TestBatchSplitByRangesNoValidKeys(t *testing.T) { + doTestBatchSplitRegionByRanges(context.Background(), t, &splitRegionNoValidKeyHook{returnErrTimes: math.MaxInt32}, "no valid key", defaultHook{}) } type reportAfterSplitHook struct { @@ -572,7 +584,7 @@ func (h *reportAfterSplitHook) AfterSplitRegion(ctx context.Context, region *res return resultRegions, err } -func (s *localSuite) TestBatchSplitByRangeCtxCanceled(c *C) { +func TestBatchSplitByRangeCtxCanceled(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) ch := make(chan struct{}) // cancel ctx after the first region split success. @@ -586,11 +598,11 @@ func (s *localSuite) TestBatchSplitByRangeCtxCanceled(c *C) { } }() - s.doTestBatchSplitRegionByRanges(ctx, c, &reportAfterSplitHook{ch: ch}, ".*context canceled.*", defaultHook{}) + doTestBatchSplitRegionByRanges(ctx, t, &reportAfterSplitHook{ch: ch}, "context canceled", defaultHook{}) close(ch) } -func (s *localSuite) doTestBatchSplitByRangesWithClusteredIndex(c *C, hook clientHook) { +func doTestBatchSplitByRangesWithClusteredIndex(t *testing.T, hook clientHook) { oldLimit := maxBatchSplitKeys oldSplitBackoffTime := splitRegionBaseBackOffTime maxBatchSplitKeys = 10 @@ -609,9 +621,9 @@ func (s *localSuite) doTestBatchSplitByRangesWithClusteredIndex(c *C, hook clien // pre split 2 regions for i := int64(0); i < 2; i++ { keyBytes, err := codec.EncodeKey(stmtCtx, nil, types.NewIntDatum(i)) - c.Assert(err, IsNil) + require.NoError(t, err) h, err := kv.NewCommonHandle(keyBytes) - c.Assert(err, IsNil) + require.NoError(t, err) key := tablecodec.EncodeRowKeyWithHandle(tableID, h) keys = append(keys, key) } @@ -628,9 +640,9 @@ func (s *localSuite) doTestBatchSplitByRangesWithClusteredIndex(c *C, hook clien for i := int64(0); i < 2; i++ { for j := int64(0); j < 10; j++ { keyBytes, err := codec.EncodeKey(stmtCtx, nil, types.NewIntDatum(i), types.NewIntDatum(j*10000)) - c.Assert(err, IsNil) + require.NoError(t, err) h, err := kv.NewCommonHandle(keyBytes) - c.Assert(err, IsNil) + require.NoError(t, err) key := tablecodec.EncodeRowKeyWithHandle(tableID, h) rangeKeys = append(rangeKeys, key) } @@ -644,30 +656,30 @@ func (s *localSuite) doTestBatchSplitByRangesWithClusteredIndex(c *C, hook clien } err := local.SplitAndScatterRegionByRanges(ctx, ranges, nil, true, 1000) - c.Assert(err, IsNil) + require.NoError(t, err) startKey := codec.EncodeBytes([]byte{}, rangeKeys[0]) endKey := codec.EncodeBytes([]byte{}, rangeKeys[len(rangeKeys)-1]) // check split ranges regions, err := restore.PaginateScanRegion(ctx, client, startKey, endKey, 5) - c.Assert(err, IsNil) - c.Assert(len(regions), Equals, len(ranges)+1) + require.NoError(t, err) + require.Equal(t, len(ranges)+1, len(regions)) checkKeys := append([][]byte{}, rangeKeys[:10]...) checkKeys = append(checkKeys, keys[3]) checkKeys = append(checkKeys, rangeKeys[10:]...) - checkRegionRanges(c, regions, checkKeys) + checkRegionRanges(t, regions, checkKeys) } -func (s *localSuite) TestBatchSplitByRangesWithClusteredIndex(c *C) { - s.doTestBatchSplitByRangesWithClusteredIndex(c, nil) +func TestBatchSplitByRangesWithClusteredIndex(t *testing.T) { + doTestBatchSplitByRangesWithClusteredIndex(t, nil) } -func (s *localSuite) TestBatchSplitByRangesWithClusteredIndexEpochNotMatch(c *C) { - s.doTestBatchSplitByRangesWithClusteredIndex(c, &splitRegionEpochNotMatchHookRandom{}) +func TestBatchSplitByRangesWithClusteredIndexEpochNotMatch(t *testing.T) { + doTestBatchSplitByRangesWithClusteredIndex(t, &splitRegionEpochNotMatchHookRandom{}) } -func (s *localSuite) TestNeedSplit(c *C) { +func TestNeedSplit(t *testing.T) { tableID := int64(1) peers := make([]*metapb.Peer, 1) peers[0] = &metapb.Peer{ @@ -712,9 +724,9 @@ func (s *localSuite) TestNeedSplit(c *C) { checkKey := tablecodec.EncodeRowKeyWithHandle(tableID, kv.IntHandle(hdl)) res := needSplit(checkKey, regions) if idx < 0 { - c.Assert(res, IsNil) + require.Nil(t, res) } else { - c.Assert(res, DeepEquals, regions[idx]) + require.Equal(t, regions[idx], res) } } } diff --git a/br/pkg/lightning/backend/noop/noop.go b/br/pkg/lightning/backend/noop/noop.go index ac02ab9482e1f..430c4c5a83e8c 100644 --- a/br/pkg/lightning/backend/noop/noop.go +++ b/br/pkg/lightning/backend/noop/noop.go @@ -140,7 +140,7 @@ func (b noopBackend) ResetEngine(ctx context.Context, engineUUID uuid.UUID) erro // LocalWriter obtains a thread-local EngineWriter for writing rows into the given engine. func (b noopBackend) LocalWriter(context.Context, *backend.LocalWriterConfig, uuid.UUID) (backend.EngineWriter, error) { - return noopWriter{}, nil + return Writer{}, nil } func (b noopBackend) CollectLocalDuplicateRows(ctx context.Context, tbl table.Table, tableName string, opts *kv.SessionOptions) (bool, error) { @@ -174,16 +174,23 @@ func (r noopRow) Size() uint64 { func (r noopRow) ClassifyAndAppend(*kv.Rows, *verification.KVChecksum, *kv.Rows, *verification.KVChecksum) { } -type noopWriter struct{} +// Writer define a local writer that do nothing. +type Writer struct{} -func (w noopWriter) AppendRows(context.Context, string, []string, kv.Rows) error { +func (w Writer) AppendRows(context.Context, string, []string, kv.Rows) error { return nil } -func (w noopWriter) IsSynced() bool { +func (w Writer) IsSynced() bool { return true } -func (w noopWriter) Close(context.Context) (backend.ChunkFlushStatus, error) { - return nil, nil +func (w Writer) Close(context.Context) (backend.ChunkFlushStatus, error) { + return trueStatus{}, nil +} + +type trueStatus struct{} + +func (s trueStatus) Flushed() bool { + return true } diff --git a/br/pkg/lightning/backend/tidb/tidb_test.go b/br/pkg/lightning/backend/tidb/tidb_test.go index 9ab3e3ab9feaa..e31ef43bd29e5 100644 --- a/br/pkg/lightning/backend/tidb/tidb_test.go +++ b/br/pkg/lightning/backend/tidb/tidb_test.go @@ -214,7 +214,7 @@ func TestWriteRowsErrorOnDup(t *testing.T) { } // TODO: temporarily disable this test before we fix strict mode -//nolint:unused +//nolint:unused,deadcode func testStrictMode(t *testing.T) { s := createMysqlSuite(t) defer s.TearDownTest(t) diff --git a/br/pkg/lightning/checkpoints/checkpoints.go b/br/pkg/lightning/checkpoints/checkpoints.go index d903c99982aa1..d2d5320595999 100644 --- a/br/pkg/lightning/checkpoints/checkpoints.go +++ b/br/pkg/lightning/checkpoints/checkpoints.go @@ -21,8 +21,9 @@ import ( "fmt" "io" "math" - "os" + "path" "sort" + "strings" "sync" "github.com/joho/sqltocsv" @@ -33,6 +34,7 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/mydump" verify "github.com/pingcap/tidb/br/pkg/lightning/verification" + "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/version/build" "go.uber.org/zap" "modernc.org/mathutil" @@ -513,7 +515,7 @@ func OpenCheckpointsDB(ctx context.Context, cfg *config.Config) (DB, error) { switch cfg.Checkpoint.Driver { case config.CheckpointDriverMySQL: - db, err := sql.Open("mysql", cfg.Checkpoint.DSN) + db, err := common.ConnectMySQL(cfg.Checkpoint.DSN) if err != nil { return nil, errors.Trace(err) } @@ -525,10 +527,14 @@ func OpenCheckpointsDB(ctx context.Context, cfg *config.Config) (DB, error) { return cpdb, nil case config.CheckpointDriverFile: - return NewFileCheckpointsDB(cfg.Checkpoint.DSN), nil + cpdb, err := NewFileCheckpointsDB(ctx, cfg.Checkpoint.DSN) + if err != nil { + return nil, errors.Trace(err) + } + return cpdb, nil default: - return nil, errors.Errorf("Unknown checkpoint driver %s", cfg.Checkpoint.Driver) + return nil, common.ErrUnknownCheckpointDriver.GenWithStackByArgs(cfg.Checkpoint.Driver) } } @@ -556,16 +562,18 @@ func IsCheckpointsDBExists(ctx context.Context, cfg *config.Config) (bool, error return result, nil case config.CheckpointDriverFile: - _, err := os.Stat(cfg.Checkpoint.DSN) - if err == nil { - return true, err - } else if os.IsNotExist(err) { - return false, nil + s, fileName, err := createExstorageByCompletePath(ctx, cfg.Checkpoint.DSN) + if err != nil { + return false, errors.Trace(err) + } + result, err := s.FileExists(ctx, fileName) + if err != nil { + return false, errors.Trace(err) } - return false, errors.Trace(err) + return result, nil default: - return false, errors.Errorf("Unknown checkpoint driver %s", cfg.Checkpoint.Driver) + return false, common.ErrUnknownCheckpointDriver.GenWithStackByArgs(cfg.Checkpoint.Driver) } } @@ -940,63 +948,143 @@ func (cpdb *MySQLCheckpointsDB) Update(checkpointDiffs map[string]*TableCheckpoi type FileCheckpointsDB struct { lock sync.Mutex // we need to ensure only a thread can access to `checkpoints` at a time checkpoints checkpointspb.CheckpointsModel + ctx context.Context path string + fileName string + exStorage storage.ExternalStorage } -func NewFileCheckpointsDB(path string) *FileCheckpointsDB { +func newFileCheckpointsDB( + ctx context.Context, + path string, + exStorage storage.ExternalStorage, + fileName string, +) (*FileCheckpointsDB, error) { cpdb := &FileCheckpointsDB{ - path: path, checkpoints: checkpointspb.CheckpointsModel{ TaskCheckpoint: &checkpointspb.TaskCheckpointModel{}, Checkpoints: map[string]*checkpointspb.TableCheckpointModel{}, }, + ctx: ctx, + path: path, + fileName: fileName, + exStorage: exStorage, } - // ignore all errors -- file maybe not created yet (and it is fine). - content, err := os.ReadFile(path) - if err == nil { - err2 := cpdb.checkpoints.Unmarshal(content) - if err2 != nil { - log.L().Error("checkpoint file is broken", zap.String("path", path), zap.Error(err2)) - } - // FIXME: patch for empty map may need initialize manually, because currently - // FIXME: a map of zero size -> marshall -> unmarshall -> become nil, see checkpoint_test.go - if cpdb.checkpoints.Checkpoints == nil { - cpdb.checkpoints.Checkpoints = map[string]*checkpointspb.TableCheckpointModel{} - } - for _, table := range cpdb.checkpoints.Checkpoints { - if table.Engines == nil { - table.Engines = map[int32]*checkpointspb.EngineCheckpointModel{} - } - for _, engine := range table.Engines { - if engine.Chunks == nil { - engine.Chunks = map[string]*checkpointspb.ChunkCheckpointModel{} - } - } - } - } else { + + if cpdb.fileName == "" { + return nil, errors.Errorf("the checkpoint DSN '%s' must not be a directory", path) + } + + exist, err := cpdb.exStorage.FileExists(ctx, cpdb.fileName) + if err != nil { + return nil, errors.Trace(err) + } + if !exist { log.L().Info("open checkpoint file failed, going to create a new one", zap.String("path", path), log.ShortError(err), ) + return cpdb, nil } - return cpdb + content, err := cpdb.exStorage.ReadFile(ctx, cpdb.fileName) + if err != nil { + return nil, errors.Trace(err) + } + err = cpdb.checkpoints.Unmarshal(content) + if err != nil { + log.L().Error("checkpoint file is broken", zap.String("path", path), zap.Error(err)) + } + // FIXME: patch for empty map may need initialize manually, because currently + // FIXME: a map of zero size -> marshall -> unmarshall -> become nil, see checkpoint_test.go + if cpdb.checkpoints.Checkpoints == nil { + cpdb.checkpoints.Checkpoints = map[string]*checkpointspb.TableCheckpointModel{} + } + for _, table := range cpdb.checkpoints.Checkpoints { + if table.Engines == nil { + table.Engines = map[int32]*checkpointspb.EngineCheckpointModel{} + } + for _, engine := range table.Engines { + if engine.Chunks == nil { + engine.Chunks = map[string]*checkpointspb.ChunkCheckpointModel{} + } + } + } + return cpdb, nil } -func (cpdb *FileCheckpointsDB) save() error { - serialized, err := cpdb.checkpoints.Marshal() +func NewFileCheckpointsDB(ctx context.Context, path string) (*FileCheckpointsDB, error) { + // init ExternalStorage + s, fileName, err := createExstorageByCompletePath(ctx, path) if err != nil { - return errors.Trace(err) + return nil, errors.Trace(err) } - // because `os.WriteFile` is not atomic, directly write into it may reset the file - // to an empty file if write is not finished. - tmpPath := cpdb.path + ".tmp" - if err := os.WriteFile(tmpPath, serialized, 0o644); err != nil { - return errors.Trace(err) + return newFileCheckpointsDB(ctx, path, s, fileName) +} + +func NewFileCheckpointsDBWithExstorageFileName( + ctx context.Context, + path string, + s storage.ExternalStorage, + fileName string, +) (*FileCheckpointsDB, error) { + return newFileCheckpointsDB(ctx, path, s, fileName) +} + +// createExstorageByCompletePath create ExternalStorage by completePath and return fileName. +func createExstorageByCompletePath(ctx context.Context, completePath string) (storage.ExternalStorage, string, error) { + if completePath == "" { + return nil, "", nil + } + fileName, newPath, err := separateCompletePath(completePath) + if err != nil { + return nil, "", errors.Trace(err) + } + u, err := storage.ParseBackend(newPath, nil) + if err != nil { + return nil, "", errors.Trace(err) + } + s, err := storage.New(ctx, u, &storage.ExternalStorageOptions{}) + if err != nil { + return nil, "", errors.Trace(err) + } + return s, fileName, nil +} + +// separateCompletePath separates fileName from completePath, returns fileName and newPath. +func separateCompletePath(completePath string) (string, string, error) { + if completePath == "" { + return "", "", nil } - if err := os.Rename(tmpPath, cpdb.path); err != nil { + var fileName, newPath string + purl, err := storage.ParseRawURL(completePath) + if err != nil { + return "", "", errors.Trace(err) + } + // not url format, we don't use url library to avoid being escaped or unescaped + if purl.Scheme == "" { + // no fileName, just path + if strings.HasSuffix(completePath, "/") { + return "", completePath, nil + } + fileName = path.Base(completePath) + newPath = path.Dir(completePath) + } else { + if strings.HasSuffix(purl.Path, "/") { + return "", completePath, nil + } + fileName = path.Base(purl.Path) + purl.Path = path.Dir(purl.Path) + newPath = purl.String() + } + return fileName, newPath, nil +} + +func (cpdb *FileCheckpointsDB) save() error { + serialized, err := cpdb.checkpoints.Marshal() + if err != nil { return errors.Trace(err) } - return nil + return cpdb.exStorage.WriteFile(cpdb.ctx, cpdb.fileName, serialized) } func (cpdb *FileCheckpointsDB) Initialize(ctx context.Context, cfg *config.Config, dbInfo map[string]*TidbDBInfo) error { @@ -1301,6 +1389,7 @@ func (cpdb *MySQLCheckpointsDB) GetLocalStoringTables(ctx context.Context) (map[ // 1. table status is earlier than CheckpointStatusIndexImported, and // 2. engine status is earlier than CheckpointStatusImported, and // 3. chunk has been read + query := fmt.Sprintf(` SELECT DISTINCT t.table_name, c.engine_id FROM %s.%s t, %s.%s c, %s.%s e @@ -1314,7 +1403,7 @@ func (cpdb *MySQLCheckpointsDB) GetLocalStoringTables(ctx context.Context) (map[ err := common.Retry("get local storing tables", log.L(), func() error { targetTables = make(map[string][]int32) - rows, err := cpdb.db.QueryContext(ctx, query) + rows, err := cpdb.db.QueryContext(ctx, query) // #nosec G201 if err != nil { return errors.Trace(err) } @@ -1351,9 +1440,12 @@ func (cpdb *MySQLCheckpointsDB) IgnoreErrorCheckpoint(ctx context.Context, table colName = columnTableName } + // nolint:gosec engineQuery := fmt.Sprintf(` UPDATE %s.%s SET status = %d WHERE %s = ? AND status <= %d; `, cpdb.schema, CheckpointTableNameEngine, CheckpointStatusLoaded, colName, CheckpointStatusMaxInvalid) + + // nolint:gosec tableQuery := fmt.Sprintf(` UPDATE %s.%s SET status = %d WHERE %s = ? AND status <= %d; `, cpdb.schema, CheckpointTableNameTable, CheckpointStatusLoaded, colName, CheckpointStatusMaxInvalid) @@ -1397,12 +1489,18 @@ func (cpdb *MySQLCheckpointsDB) DestroyErrorCheckpoint(ctx context.Context, tabl WHERE %[2]s = ? AND t.status <= %[3]d GROUP BY t.table_name; `, cpdb.schema, aliasedColName, CheckpointStatusMaxInvalid, CheckpointTableNameTable, CheckpointTableNameEngine) + + // nolint:gosec deleteChunkQuery := fmt.Sprintf(` DELETE FROM %[1]s.%[4]s WHERE table_name IN (SELECT table_name FROM %[1]s.%[5]s WHERE %[2]s = ? AND status <= %[3]d) `, cpdb.schema, colName, CheckpointStatusMaxInvalid, CheckpointTableNameChunk, CheckpointTableNameTable) + + // nolint:gosec deleteEngineQuery := fmt.Sprintf(` DELETE FROM %[1]s.%[4]s WHERE table_name IN (SELECT table_name FROM %[1]s.%[5]s WHERE %[2]s = ? AND status <= %[3]d) `, cpdb.schema, colName, CheckpointStatusMaxInvalid, CheckpointTableNameEngine, CheckpointTableNameTable) + + // nolint:gosec deleteTableQuery := fmt.Sprintf(` DELETE FROM %s.%s WHERE %s = ? AND status <= %d `, cpdb.schema, CheckpointTableNameTable, colName, CheckpointStatusMaxInvalid) @@ -1416,7 +1514,7 @@ func (cpdb *MySQLCheckpointsDB) DestroyErrorCheckpoint(ctx context.Context, tabl err := s.Transact(ctx, "destroy error checkpoints", func(c context.Context, tx *sql.Tx) error { // Obtain the list of tables targetTables = nil - rows, e := tx.QueryContext(c, selectQuery, tableName) + rows, e := tx.QueryContext(c, selectQuery, tableName) // #nosec G201 if e != nil { return errors.Trace(e) } @@ -1528,7 +1626,7 @@ func (cpdb *FileCheckpointsDB) RemoveCheckpoint(_ context.Context, tableName str if tableName == allTables { cpdb.checkpoints.Reset() - return errors.Trace(os.Remove(cpdb.path)) + return errors.Trace(cpdb.exStorage.DeleteFile(cpdb.ctx, cpdb.fileName)) } delete(cpdb.checkpoints.Checkpoints, tableName) @@ -1539,8 +1637,8 @@ func (cpdb *FileCheckpointsDB) MoveCheckpoints(ctx context.Context, taskID int64 cpdb.lock.Lock() defer cpdb.lock.Unlock() - newPath := fmt.Sprintf("%s.%d.bak", cpdb.path, taskID) - return errors.Trace(os.Rename(cpdb.path, newPath)) + newFileName := fmt.Sprintf("%s.%d.bak", cpdb.fileName, taskID) + return cpdb.exStorage.Rename(cpdb.ctx, cpdb.fileName, newFileName) } func (cpdb *FileCheckpointsDB) GetLocalStoringTables(_ context.Context) (map[string][]int32, error) { diff --git a/br/pkg/lightning/checkpoints/checkpoints_file_test.go b/br/pkg/lightning/checkpoints/checkpoints_file_test.go index bb3a374ad176d..5911b9952a1c2 100644 --- a/br/pkg/lightning/checkpoints/checkpoints_file_test.go +++ b/br/pkg/lightning/checkpoints/checkpoints_file_test.go @@ -6,24 +6,14 @@ import ( "sort" "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/verification" + "github.com/stretchr/testify/require" ) -func Test(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&cpFileSuite{}) - -type cpFileSuite struct { - cpdb *checkpoints.FileCheckpointsDB -} - func newTestConfig() *config.Config { cfg := config.NewConfig() cfg.Mydumper.SourceDir = "/data" @@ -36,16 +26,15 @@ func newTestConfig() *config.Config { return cfg } -func (s *cpFileSuite) SetUpTest(c *C) { - dir := c.MkDir() - s.cpdb = checkpoints.NewFileCheckpointsDB(filepath.Join(dir, "cp.pb")) - +func newFileCheckpointsDB(t *testing.T) (*checkpoints.FileCheckpointsDB, func()) { + dir := t.TempDir() ctx := context.Background() - cpdb := s.cpdb + cpdb, err := checkpoints.NewFileCheckpointsDB(ctx, filepath.Join(dir, "cp.pb")) + require.NoError(t, err) // 2. initialize with checkpoint data. cfg := newTestConfig() - err := cpdb.Initialize(ctx, cfg, map[string]*checkpoints.TidbDBInfo{ + err = cpdb.Initialize(ctx, cfg, map[string]*checkpoints.TidbDBInfo{ "db1": { Name: "db1", Tables: map[string]*checkpoints.TidbTableInfo{ @@ -60,7 +49,7 @@ func (s *cpFileSuite) SetUpTest(c *C) { }, }, }) - c.Assert(err, IsNil) + require.NoError(t, err) // 3. set some checkpoints @@ -90,7 +79,7 @@ func (s *cpFileSuite) SetUpTest(c *C) { Chunks: nil, }, }) - c.Assert(err, IsNil) + require.NoError(t, err) err = cpdb.InsertEngineCheckpoints(ctx, "`db2`.`t3`", map[int32]*checkpoints.EngineCheckpoint{ -1: { @@ -98,7 +87,7 @@ func (s *cpFileSuite) SetUpTest(c *C) { Chunks: nil, }, }) - c.Assert(err, IsNil) + require.NoError(t, err) // 4. update some checkpoints @@ -131,13 +120,13 @@ func (s *cpFileSuite) SetUpTest(c *C) { ccm.MergeInto(cpd) cpdb.Update(map[string]*checkpoints.TableCheckpointDiff{"`db1`.`t2`": cpd}) + return cpdb, func() { + err := cpdb.Close() + require.NoError(t, err) + } } -func (s *cpFileSuite) TearDownTest(c *C) { - c.Assert(s.cpdb.Close(), IsNil) -} - -func (s *cpFileSuite) setInvalidStatus() { +func setInvalidStatus(cpdb *checkpoints.FileCheckpointsDB) { cpd := checkpoints.NewTableCheckpointDiff() scm := checkpoints.StatusCheckpointMerger{ EngineID: -1, @@ -146,20 +135,22 @@ func (s *cpFileSuite) setInvalidStatus() { scm.SetInvalid() scm.MergeInto(cpd) - s.cpdb.Update(map[string]*checkpoints.TableCheckpointDiff{ + cpdb.Update(map[string]*checkpoints.TableCheckpointDiff{ "`db1`.`t2`": cpd, "`db2`.`t3`": cpd, }) } -func (s *cpFileSuite) TestGet(c *C) { +func TestGet(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() // 5. get back the checkpoints - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(cp, DeepEquals, &checkpoints.TableCheckpoint{ + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.NoError(t, err) + expect := &checkpoints.TableCheckpoint{ Status: checkpoints.CheckpointStatusAllWritten, AllocBase: 132861, Checksum: verification.MakeKVChecksum(4492, 686, 486070148910), @@ -191,11 +182,12 @@ func (s *cpFileSuite) TestGet(c *C) { }}, }, }, - }) + } + require.Equal(t, expect, cp) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(err, IsNil) - c.Assert(cp, DeepEquals, &checkpoints.TableCheckpoint{ + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.NoError(t, err) + expect = &checkpoints.TableCheckpoint{ Status: checkpoints.CheckpointStatusLoaded, Engines: map[int32]*checkpoints.EngineCheckpoint{ -1: { @@ -203,86 +195,97 @@ func (s *cpFileSuite) TestGet(c *C) { Chunks: []*checkpoints.ChunkCheckpoint{}, }, }, - }) + } + require.Equal(t, expect, cp) - cp, err = s.cpdb.Get(ctx, "`db3`.`not-exists`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err = cpdb.Get(ctx, "`db3`.`not-exists`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) } -func (s *cpFileSuite) TestRemoveAllCheckpoints(c *C) { +func TestRemoveAllCheckpoints(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - err := s.cpdb.RemoveCheckpoint(ctx, "all") - c.Assert(err, IsNil) + err := cpdb.RemoveCheckpoint(ctx, "all") + require.NoError(t, err) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) } -func (s *cpFileSuite) TestRemoveOneCheckpoint(c *C) { +func TestRemoveOneCheckpoint(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - err := s.cpdb.RemoveCheckpoint(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) + err := cpdb.RemoveCheckpoint(ctx, "`db1`.`t2`") + require.NoError(t, err) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusLoaded) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusLoaded, cp.Status) } -func (s *cpFileSuite) TestIgnoreAllErrorCheckpoints(c *C) { +func TestIgnoreAllErrorCheckpoints(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - s.setInvalidStatus() + setInvalidStatus(cpdb) - err := s.cpdb.IgnoreErrorCheckpoint(ctx, "all") - c.Assert(err, IsNil) + err := cpdb.IgnoreErrorCheckpoint(ctx, "all") + require.NoError(t, err) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusLoaded) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusLoaded, cp.Status) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusLoaded) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusLoaded, cp.Status) } -func (s *cpFileSuite) TestIgnoreOneErrorCheckpoints(c *C) { +func TestIgnoreOneErrorCheckpoints(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - s.setInvalidStatus() + setInvalidStatus(cpdb) - err := s.cpdb.IgnoreErrorCheckpoint(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) + err := cpdb.IgnoreErrorCheckpoint(ctx, "`db1`.`t2`") + require.NoError(t, err) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusLoaded) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusLoaded, cp.Status) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusAllWritten/10) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusAllWritten/10, cp.Status) } -func (s *cpFileSuite) TestDestroyAllErrorCheckpoints(c *C) { +func TestDestroyAllErrorCheckpoints(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - s.setInvalidStatus() + setInvalidStatus(cpdb) - dtc, err := s.cpdb.DestroyErrorCheckpoint(ctx, "all") - c.Assert(err, IsNil) + dtc, err := cpdb.DestroyErrorCheckpoint(ctx, "all") + require.NoError(t, err) sort.Slice(dtc, func(i, j int) bool { return dtc[i].TableName < dtc[j].TableName }) - c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{ + expect := []checkpoints.DestroyedTableCheckpoint{ { TableName: "`db1`.`t2`", MinEngineID: -1, @@ -293,37 +296,41 @@ func (s *cpFileSuite) TestDestroyAllErrorCheckpoints(c *C) { MinEngineID: -1, MaxEngineID: -1, }, - }) + } + require.Equal(t, expect, dtc) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) } -func (s *cpFileSuite) TestDestroyOneErrorCheckpoint(c *C) { +func TestDestroyOneErrorCheckpoint(t *testing.T) { ctx := context.Background() + cpdb, clean := newFileCheckpointsDB(t) + defer clean() - s.setInvalidStatus() + setInvalidStatus(cpdb) - dtc, err := s.cpdb.DestroyErrorCheckpoint(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{ + dtc, err := cpdb.DestroyErrorCheckpoint(ctx, "`db1`.`t2`") + require.NoError(t, err) + expect := []checkpoints.DestroyedTableCheckpoint{ { TableName: "`db1`.`t2`", MinEngineID: -1, MaxEngineID: 0, }, - }) + } + require.Equal(t, expect, dtc) - cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + cp, err := cpdb.Get(ctx, "`db1`.`t2`") + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) - cp, err = s.cpdb.Get(ctx, "`db2`.`t3`") - c.Assert(err, IsNil) - c.Assert(cp.Status, Equals, checkpoints.CheckpointStatusAllWritten/10) + cp, err = cpdb.Get(ctx, "`db2`.`t3`") + require.NoError(t, err) + require.Equal(t, checkpoints.CheckpointStatusAllWritten/10, cp.Status) } diff --git a/br/pkg/lightning/checkpoints/checkpoints_sql_test.go b/br/pkg/lightning/checkpoints/checkpoints_sql_test.go index a27f62c72a3eb..85a23f379fec9 100644 --- a/br/pkg/lightning/checkpoints/checkpoints_sql_test.go +++ b/br/pkg/lightning/checkpoints/checkpoints_sql_test.go @@ -4,28 +4,28 @@ import ( "context" "database/sql" "strings" + "testing" "time" "github.com/DATA-DOG/go-sqlmock" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/verification" "github.com/pingcap/tidb/br/pkg/version/build" + "github.com/stretchr/testify/require" ) -var _ = Suite(&cpSQLSuite{}) - type cpSQLSuite struct { db *sql.DB mock sqlmock.Sqlmock cpdb *checkpoints.MySQLCheckpointsDB } -func (s *cpSQLSuite) SetUpTest(c *C) { +func newCPSQLSuite(t *testing.T) (*cpSQLSuite, func()) { + var s cpSQLSuite db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) s.db = db s.mock = mock @@ -47,19 +47,20 @@ func (s *cpSQLSuite) SetUpTest(c *C) { WillReturnResult(sqlmock.NewResult(5, 1)) cpdb, err := checkpoints.NewMySQLCheckpointsDB(context.Background(), s.db, "mock-schema") - c.Assert(err, IsNil) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) + require.NoError(t, err) + require.Nil(t, s.mock.ExpectationsWereMet()) s.cpdb = cpdb + return &s, func() { + s.mock.ExpectClose() + require.Nil(t, s.cpdb.Close()) + require.Nil(t, s.mock.ExpectationsWereMet()) + } } -func (s *cpSQLSuite) TearDownTest(c *C) { - s.mock.ExpectClose() - c.Assert(s.cpdb.Close(), IsNil) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) -} - -func (s *cpSQLSuite) TestNormalOperations(c *C) { +func TestNormalOperations(t *testing.T) { ctx := context.Background() + s, clean := newCPSQLSuite(t) + defer clean() cpdb := s.cpdb // 2. initialize with checkpoint data. @@ -101,8 +102,8 @@ func (s *cpSQLSuite) TestNormalOperations(c *C) { }, }) s.mock.MatchExpectationsInOrder(true) - c.Assert(err, IsNil) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) + require.NoError(t, err) + require.Nil(t, s.mock.ExpectationsWereMet()) // 3. set some checkpoints @@ -154,8 +155,8 @@ func (s *cpSQLSuite) TestNormalOperations(c *C) { }, }) s.mock.MatchExpectationsInOrder(true) - c.Assert(err, IsNil) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) + require.NoError(t, err) + require.Nil(t, s.mock.ExpectationsWereMet()) // 4. update some checkpoints @@ -222,7 +223,7 @@ func (s *cpSQLSuite) TestNormalOperations(c *C) { s.mock.MatchExpectationsInOrder(false) cpdb.Update(map[string]*checkpoints.TableCheckpointDiff{"`db1`.`t2`": cpd}) s.mock.MatchExpectationsInOrder(true) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) + require.Nil(t, s.mock.ExpectationsWereMet()) // 5. get back the checkpoints @@ -260,8 +261,8 @@ func (s *cpSQLSuite) TestNormalOperations(c *C) { s.mock.ExpectCommit() cp, err := cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(cp, DeepEquals, &checkpoints.TableCheckpoint{ + require.Nil(t, err) + require.Equal(t, &checkpoints.TableCheckpoint{ Status: checkpoints.CheckpointStatusAllWritten, AllocBase: 132861, TableID: int64(2), @@ -292,17 +293,20 @@ func (s *cpSQLSuite) TestNormalOperations(c *C) { }, }, Checksum: verification.MakeKVChecksum(4492, 686, 486070148910), - }) - c.Assert(s.mock.ExpectationsWereMet(), IsNil) + }, cp) + require.Nil(t, s.mock.ExpectationsWereMet()) } -func (s *cpSQLSuite) TestRemoveAllCheckpoints(c *C) { +func TestRemoveAllCheckpoints_SQL(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectExec("DROP SCHEMA `mock-schema`").WillReturnResult(sqlmock.NewResult(0, 1)) ctx := context.Background() err := s.cpdb.RemoveCheckpoint(ctx, "all") - c.Assert(err, IsNil) + require.NoError(t, err) s.mock.ExpectBegin() s.mock. @@ -325,11 +329,14 @@ func (s *cpSQLSuite) TestRemoveAllCheckpoints(c *C) { s.mock.ExpectRollback() cp, err := s.cpdb.Get(ctx, "`db1`.`t2`") - c.Assert(cp, IsNil) - c.Assert(errors.IsNotFound(err), IsTrue) + require.Nil(t, cp) + require.True(t, errors.IsNotFound(err)) } -func (s *cpSQLSuite) TestRemoveOneCheckpoint(c *C) { +func TestRemoveOneCheckpoint_SQL(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectBegin() s.mock. ExpectExec("DELETE FROM `mock-schema`\\.chunk_v\\d+ WHERE table_name = \\?"). @@ -346,10 +353,13 @@ func (s *cpSQLSuite) TestRemoveOneCheckpoint(c *C) { s.mock.ExpectCommit() err := s.cpdb.RemoveCheckpoint(context.Background(), "`db1`.`t2`") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *cpSQLSuite) TestIgnoreAllErrorCheckpoints(c *C) { +func TestIgnoreAllErrorCheckpoints_SQL(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectBegin() s.mock. ExpectExec("UPDATE `mock-schema`\\.engine_v\\d+ SET status = 30 WHERE 'all' = \\? AND status <= 25"). @@ -362,10 +372,13 @@ func (s *cpSQLSuite) TestIgnoreAllErrorCheckpoints(c *C) { s.mock.ExpectCommit() err := s.cpdb.IgnoreErrorCheckpoint(context.Background(), "all") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *cpSQLSuite) TestIgnoreOneErrorCheckpoint(c *C) { +func TestIgnoreOneErrorCheckpoint(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectBegin() s.mock. ExpectExec("UPDATE `mock-schema`\\.engine_v\\d+ SET status = 30 WHERE table_name = \\? AND status <= 25"). @@ -378,10 +391,13 @@ func (s *cpSQLSuite) TestIgnoreOneErrorCheckpoint(c *C) { s.mock.ExpectCommit() err := s.cpdb.IgnoreErrorCheckpoint(context.Background(), "`db1`.`t2`") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *cpSQLSuite) TestDestroyAllErrorCheckpoints(c *C) { +func TestDestroyAllErrorCheckpoints_SQL(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectBegin() s.mock. ExpectQuery("SELECT (?s:.+)'all' = \\?"). @@ -405,15 +421,18 @@ func (s *cpSQLSuite) TestDestroyAllErrorCheckpoints(c *C) { s.mock.ExpectCommit() dtc, err := s.cpdb.DestroyErrorCheckpoint(context.Background(), "all") - c.Assert(err, IsNil) - c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{{ + require.NoError(t, err) + require.Equal(t, []checkpoints.DestroyedTableCheckpoint{{ TableName: "`db1`.`t2`", MinEngineID: -1, MaxEngineID: 0, - }}) + }}, dtc) } -func (s *cpSQLSuite) TestDestroyOneErrorCheckpoints(c *C) { +func TestDestroyOneErrorCheckpoints(t *testing.T) { + s, clean := newCPSQLSuite(t) + defer clean() + s.mock.ExpectBegin() s.mock. ExpectQuery("SELECT (?s:.+)table_name = \\?"). @@ -437,17 +456,19 @@ func (s *cpSQLSuite) TestDestroyOneErrorCheckpoints(c *C) { s.mock.ExpectCommit() dtc, err := s.cpdb.DestroyErrorCheckpoint(context.Background(), "`db1`.`t2`") - c.Assert(err, IsNil) - c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{{ + require.NoError(t, err) + require.Equal(t, []checkpoints.DestroyedTableCheckpoint{{ TableName: "`db1`.`t2`", MinEngineID: -1, MaxEngineID: 0, - }}) + }}, dtc) } -func (s *cpSQLSuite) TestDump(c *C) { +func TestDump(t *testing.T) { ctx := context.Background() - t := time.Unix(1555555555, 0).UTC() + s, clean := newCPSQLSuite(t) + defer clean() + tm := time.Unix(1555555555, 0).UTC() s.mock. ExpectQuery("SELECT (?s:.+) FROM `mock-schema`\\.chunk_v\\d+"). @@ -461,53 +482,55 @@ func (s *cpSQLSuite) TestDump(c *C) { "`db1`.`t2`", "/tmp/path/1.sql", 0, mydump.SourceTypeSQL, mydump.CompressionNone, "", 456, "[]", 55904, 102400, 681, 5000, 4491, 586, 486070148917, - t, t, + tm, tm, ), ) var csvBuilder strings.Builder err := s.cpdb.DumpChunks(ctx, &csvBuilder) - c.Assert(err, IsNil) - c.Assert(csvBuilder.String(), Equals, + require.NoError(t, err) + require.Equal(t, "table_name,path,offset,type,compression,sort_key,file_size,columns,pos,end_offset,prev_rowid_max,rowid_max,kvc_bytes,kvc_kvs,kvc_checksum,create_time,update_time\n"+ "`db1`.`t2`,/tmp/path/1.sql,0,3,0,,456,[],55904,102400,681,5000,4491,586,486070148917,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n", + csvBuilder.String(), ) s.mock. ExpectQuery("SELECT .+ FROM `mock-schema`\\.engine_v\\d+"). WillReturnRows( sqlmock.NewRows([]string{"table_name", "engine_id", "status", "create_time", "update_time"}). - AddRow("`db1`.`t2`", -1, 30, t, t). - AddRow("`db1`.`t2`", 0, 120, t, t), + AddRow("`db1`.`t2`", -1, 30, tm, tm). + AddRow("`db1`.`t2`", 0, 120, tm, tm), ) csvBuilder.Reset() err = s.cpdb.DumpEngines(ctx, &csvBuilder) - c.Assert(err, IsNil) - c.Assert(csvBuilder.String(), Equals, - "table_name,engine_id,status,create_time,update_time\n"+ - "`db1`.`t2`,-1,30,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n"+ - "`db1`.`t2`,0,120,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n", - ) + require.NoError(t, err) + require.Equal(t, "table_name,engine_id,status,create_time,update_time\n"+ + "`db1`.`t2`,-1,30,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n"+ + "`db1`.`t2`,0,120,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n", + csvBuilder.String()) s.mock. ExpectQuery("SELECT .+ FROM `mock-schema`\\.table_v\\d+"). WillReturnRows( sqlmock.NewRows([]string{"task_id", "table_name", "hash", "status", "alloc_base", "create_time", "update_time"}). - AddRow(1555555555, "`db1`.`t2`", 0, 90, 132861, t, t), + AddRow(1555555555, "`db1`.`t2`", 0, 90, 132861, tm, tm), ) csvBuilder.Reset() err = s.cpdb.DumpTables(ctx, &csvBuilder) - c.Assert(err, IsNil) - c.Assert(csvBuilder.String(), Equals, - "task_id,table_name,hash,status,alloc_base,create_time,update_time\n"+ - "1555555555,`db1`.`t2`,0,90,132861,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n", + require.NoError(t, err) + require.Equal(t, "task_id,table_name,hash,status,alloc_base,create_time,update_time\n"+ + "1555555555,`db1`.`t2`,0,90,132861,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n", + csvBuilder.String(), ) } -func (s *cpSQLSuite) TestMoveCheckpoints(c *C) { +func TestMoveCheckpoints(t *testing.T) { ctx := context.Background() + s, clean := newCPSQLSuite(t) + defer clean() s.mock. ExpectExec("CREATE SCHEMA IF NOT EXISTS `mock-schema\\.12345678\\.bak`"). @@ -526,5 +549,5 @@ func (s *cpSQLSuite) TestMoveCheckpoints(c *C) { WillReturnResult(sqlmock.NewResult(0, 1)) err := s.cpdb.MoveCheckpoints(ctx, 12345678) - c.Assert(err, IsNil) + require.NoError(t, err) } diff --git a/br/pkg/lightning/checkpoints/checkpoints_test.go b/br/pkg/lightning/checkpoints/checkpoints_test.go index e386fb59d2965..7676809312d56 100644 --- a/br/pkg/lightning/checkpoints/checkpoints_test.go +++ b/br/pkg/lightning/checkpoints/checkpoints_test.go @@ -1,31 +1,23 @@ package checkpoints import ( + "context" "path/filepath" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints/checkpointspb" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/verification" + "github.com/stretchr/testify/require" ) -func Test(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&checkpointSuite{}) - -type checkpointSuite struct { -} - -func (s *checkpointSuite) TestMergeStatusCheckpoint(c *C) { +func TestMergeStatusCheckpoint(t *testing.T) { cpd := NewTableCheckpointDiff() m := StatusCheckpointMerger{EngineID: 0, Status: CheckpointStatusImported} m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasStatus: false, engines: map[int32]engineCheckpointDiff{ 0: { @@ -34,12 +26,12 @@ func (s *checkpointSuite) TestMergeStatusCheckpoint(c *C) { chunks: make(map[ChunkCheckpointKey]chunkCheckpointDiff), }, }, - }) + }, cpd) m = StatusCheckpointMerger{EngineID: -1, Status: CheckpointStatusLoaded} m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasStatus: false, engines: map[int32]engineCheckpointDiff{ 0: { @@ -53,12 +45,12 @@ func (s *checkpointSuite) TestMergeStatusCheckpoint(c *C) { chunks: make(map[ChunkCheckpointKey]chunkCheckpointDiff), }, }, - }) + }, cpd) m = StatusCheckpointMerger{EngineID: WholeTableEngineID, Status: CheckpointStatusClosed} m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasStatus: true, status: CheckpointStatusClosed, engines: map[int32]engineCheckpointDiff{ @@ -73,12 +65,12 @@ func (s *checkpointSuite) TestMergeStatusCheckpoint(c *C) { chunks: make(map[ChunkCheckpointKey]chunkCheckpointDiff), }, }, - }) + }, cpd) m = StatusCheckpointMerger{EngineID: -1, Status: CheckpointStatusAllWritten} m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasStatus: true, status: CheckpointStatusClosed, engines: map[int32]engineCheckpointDiff{ @@ -93,10 +85,10 @@ func (s *checkpointSuite) TestMergeStatusCheckpoint(c *C) { chunks: make(map[ChunkCheckpointKey]chunkCheckpointDiff), }, }, - }) + }, cpd) } -func (s *checkpointSuite) TestMergeInvalidStatusCheckpoint(c *C) { +func TestMergeInvalidStatusCheckpoint(t *testing.T) { cpd := NewTableCheckpointDiff() m := StatusCheckpointMerger{EngineID: 0, Status: CheckpointStatusLoaded} @@ -106,7 +98,7 @@ func (s *checkpointSuite) TestMergeInvalidStatusCheckpoint(c *C) { m.SetInvalid() m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasStatus: true, status: CheckpointStatusAllWritten / 10, engines: map[int32]engineCheckpointDiff{ @@ -121,10 +113,10 @@ func (s *checkpointSuite) TestMergeInvalidStatusCheckpoint(c *C) { chunks: make(map[ChunkCheckpointKey]chunkCheckpointDiff), }, }, - }) + }, cpd) } -func (s *checkpointSuite) TestMergeChunkCheckpoint(c *C) { +func TestMergeChunkCheckpoint(t *testing.T) { cpd := NewTableCheckpointDiff() key := ChunkCheckpointKey{Path: "/tmp/path/1.sql", Offset: 0} @@ -138,7 +130,7 @@ func (s *checkpointSuite) TestMergeChunkCheckpoint(c *C) { } m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ engines: map[int32]engineCheckpointDiff{ 2: { chunks: map[ChunkCheckpointKey]chunkCheckpointDiff{ @@ -150,7 +142,7 @@ func (s *checkpointSuite) TestMergeChunkCheckpoint(c *C) { }, }, }, - }) + }, cpd) m = ChunkCheckpointMerger{ EngineID: 2, @@ -161,7 +153,7 @@ func (s *checkpointSuite) TestMergeChunkCheckpoint(c *C) { } m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ engines: map[int32]engineCheckpointDiff{ 2: { chunks: map[ChunkCheckpointKey]chunkCheckpointDiff{ @@ -173,23 +165,23 @@ func (s *checkpointSuite) TestMergeChunkCheckpoint(c *C) { }, }, }, - }) + }, cpd) } -func (s *checkpointSuite) TestRebaseCheckpoint(c *C) { +func TestRebaseCheckpoint(t *testing.T) { cpd := NewTableCheckpointDiff() m := RebaseCheckpointMerger{AllocBase: 10000} m.MergeInto(cpd) - c.Assert(cpd, DeepEquals, &TableCheckpointDiff{ + require.Equal(t, &TableCheckpointDiff{ hasRebase: true, allocBase: 10000, engines: make(map[int32]engineCheckpointDiff), - }) + }, cpd) } -func (s *checkpointSuite) TestApplyDiff(c *C) { +func TestApplyDiff(t *testing.T) { cp := TableCheckpoint{ Status: CheckpointStatusLoaded, AllocBase: 123, @@ -256,7 +248,7 @@ func (s *checkpointSuite) TestApplyDiff(c *C) { cp.Apply(cpd) - c.Assert(cp, DeepEquals, TableCheckpoint{ + require.Equal(t, TableCheckpoint{ Status: CheckpointStatusAllWritten, AllocBase: 11111, Engines: map[int32]*EngineCheckpoint{ @@ -288,19 +280,62 @@ func (s *checkpointSuite) TestApplyDiff(c *C) { }, }, }, - }) + }, cp) } -func (s *checkpointSuite) TestCheckpointMarshallUnmarshall(c *C) { - path := filepath.Join(c.MkDir(), "filecheckpoint") - fileChkp := NewFileCheckpointsDB(path) +func TestCheckpointMarshallUnmarshall(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "filecheckpoint") + ctx := context.Background() + fileChkp, err := NewFileCheckpointsDB(ctx, path) + require.NoError(t, err) fileChkp.checkpoints.Checkpoints["a"] = &checkpointspb.TableCheckpointModel{ Status: uint32(CheckpointStatusLoaded), Engines: map[int32]*checkpointspb.EngineCheckpointModel{}, } - fileChkp.Close() + err = fileChkp.Close() + require.NoError(t, err) - fileChkp2 := NewFileCheckpointsDB(path) + fileChkp2, err := NewFileCheckpointsDB(ctx, path) + require.NoError(t, err) // if not recover empty map explicitly, it will become nil - c.Assert(fileChkp2.checkpoints.Checkpoints["a"].Engines, NotNil) + require.NotNil(t, fileChkp2.checkpoints.Checkpoints["a"].Engines) +} + +func TestSeparateCompletePath(t *testing.T) { + + testCases := []struct { + complete string + expectFileName string + expectPath string + }{ + {"", "", ""}, + {"/a/", "", "/a/"}, + {"test.log", "test.log", "."}, + {"./test.log", "test.log", "."}, + {"./tmp/test.log", "test.log", "tmp"}, + {"tmp/test.log", "test.log", "tmp"}, + {"/test.log", "test.log", "/"}, + {"/tmp/test.log", "test.log", "/tmp"}, + {"/a%3F%2Fbc/a%3F%2Fbc.log", "a%3F%2Fbc.log", "/a%3F%2Fbc"}, + {"/a??bc/a??bc.log", "a??bc.log", "/a??bc"}, + {"/t-%C3%8B%21s%60t/t-%C3%8B%21s%60t.log", "t-%C3%8B%21s%60t.log", "/t-%C3%8B%21s%60t"}, + {"/t-Ë!s`t/t-Ë!s`t.log", "t-Ë!s`t.log", "/t-Ë!s`t"}, + {"file:///a%3F%2Fbc/a%3F%2Fcd.log", "cd.log", "file:///a%3F/bc/a%3F"}, + {"file:///a?/bc/a?/cd.log", "a", "file:///?/bc/a?/cd.log"}, + {"file:///a/?/bc/a?/cd.log", "", "file:///a/?/bc/a?/cd.log"}, + {"file:///t-%C3%8B%21s%60t/t-%C3%8B%21s%60t.log", "t-Ë!s`t.log", "file:///t-%C3%8B%21s%60t"}, + {"file:///t-Ë!s`t/t-Ë!s`t.log", "t-Ë!s`t.log", "file:///t-%C3%8B%21s%60t"}, + {"s3://bucket2/test.log", "test.log", "s3://bucket2/"}, + {"s3://bucket2/test/test.log", "test.log", "s3://bucket2/test"}, + {"s3://bucket3/prefix/test.log?access-key=NXN7IPIOSAAKDEEOLMAF&secret-access-key=nREY/7Dt+PaIbYKrKlEEMMF/ExCiJEX=XMLPUANw", "test.log", + "s3://bucket3/prefix?access-key=NXN7IPIOSAAKDEEOLMAF&secret-access-key=nREY/7Dt%2BPaIbYKrKlEEMMF/ExCiJEX=XMLPUANw"}, + } + + for _, testCase := range testCases { + fileName, newPath, err := separateCompletePath(testCase.complete) + require.NoError(t, err) + require.Equal(t, testCase.expectFileName, fileName) + require.Equal(t, testCase.expectPath, newPath) + } } diff --git a/br/pkg/lightning/checkpoints/main_test.go b/br/pkg/lightning/checkpoints/main_test.go new file mode 100644 index 0000000000000..a12dce75ecf1b --- /dev/null +++ b/br/pkg/lightning/checkpoints/main_test.go @@ -0,0 +1,32 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package checkpoints_test + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) +} diff --git a/br/pkg/lightning/common/conn.go b/br/pkg/lightning/common/conn.go index 0dc011e88b7fa..eb9b598e64c55 100644 --- a/br/pkg/lightning/common/conn.go +++ b/br/pkg/lightning/common/conn.go @@ -24,7 +24,7 @@ import ( "google.golang.org/grpc" ) -// connPool is a lazy pool of gRPC channels. +// ConnPool is a lazy pool of gRPC channels. // When `Get` called, it lazily allocates new connection if connection not full. // If it's full, then it will return allocated channels round-robin. type ConnPool struct { @@ -71,11 +71,11 @@ func (p *ConnPool) get(ctx context.Context) (*grpc.ClientConn, error) { return conn, nil } -// newConnPool creates a new connPool by the specified conn factory function and capacity. -func NewConnPool(cap int, newConn func(ctx context.Context) (*grpc.ClientConn, error)) *ConnPool { +// NewConnPool creates a new connPool by the specified conn factory function and capacity. +func NewConnPool(capacity int, newConn func(ctx context.Context) (*grpc.ClientConn, error)) *ConnPool { return &ConnPool{ - cap: cap, - conns: make([]*grpc.ClientConn, 0, cap), + cap: capacity, + conns: make([]*grpc.ClientConn, 0, capacity), newConn: newConn, mu: sync.Mutex{}, @@ -105,7 +105,7 @@ func (conns *GRPCConns) GetGrpcConn(ctx context.Context, storeID uint64, tcpConc return conns.conns[storeID].get(ctx) } -func NewGRPCConns() GRPCConns { - cons := GRPCConns{conns: make(map[uint64]*ConnPool)} - return cons +func NewGRPCConns() *GRPCConns { + conns := &GRPCConns{conns: make(map[uint64]*ConnPool)} + return conns } diff --git a/br/pkg/lightning/common/errors.go b/br/pkg/lightning/common/errors.go new file mode 100644 index 0000000000000..da9efab5b3087 --- /dev/null +++ b/br/pkg/lightning/common/errors.go @@ -0,0 +1,211 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + "io" + "strings" + + "github.com/pingcap/errors" + berrors "github.com/pingcap/tidb/br/pkg/errors" +) + +var ( + ErrUnknown = errors.Normalize("unknown error", errors.RFCCodeText("Lightning:Common:ErrUnknown")) + ErrInvalidArgument = errors.Normalize("invalid argument", errors.RFCCodeText("Lightning:Common:ErrInvalidArgument")) + ErrVersionMismatch = errors.Normalize("version mismatch", errors.RFCCodeText("Lightning:Common:ErrVersionMismatch")) + + ErrReadConfigFile = errors.Normalize("cannot read config file '%s'", errors.RFCCodeText("Lightning:Config:ErrReadConfigFile")) + ErrParseConfigFile = errors.Normalize("cannot parse config file '%s'", errors.RFCCodeText("Lightning:Config:ErrParseConfigFile")) + ErrInvalidConfig = errors.Normalize("invalid config", errors.RFCCodeText("Lightning:Config:ErrInvalidConfig")) + ErrInvalidTLSConfig = errors.Normalize("invalid tls config", errors.RFCCodeText("Lightning:Config:ErrInvalidTLSConfig")) + ErrInvalidSortedKVDir = errors.Normalize("invalid sorted-kv-dir '%s' for local backend, please change the config or delete the path", errors.RFCCodeText("Lightning:Config:ErrInvalidSortedKVDir")) + + ErrStorageUnknown = errors.Normalize("unknown storage error", errors.RFCCodeText("Lightning:Storage:ErrStorageUnknown")) + ErrInvalidPermission = errors.Normalize("invalid permission", errors.RFCCodeText("Lightning:Storage:ErrInvalidPermission")) + ErrInvalidStorageConfig = errors.Normalize("invalid data-source-dir", errors.RFCCodeText("Lightning:Storage:ErrInvalidStorageConfig")) + ErrEmptySourceDir = errors.Normalize("data-source-dir '%s' doesn't exist or contains no files", errors.RFCCodeText("Lightning:Storage:ErrEmptySourceDir")) + + ErrTableRoute = errors.Normalize("table route error", errors.RFCCodeText("Lightning:Loader:ErrTableRoute")) + ErrInvalidSchemaFile = errors.Normalize("invalid schema file", errors.RFCCodeText("Lightning:Loader:ErrInvalidSchemaFile")) + + ErrSystemRequirementNotMet = errors.Normalize("system requirement not met", errors.RFCCodeText("Lightning:PreCheck:ErrSystemRequirementNotMet")) + ErrCheckpointSchemaConflict = errors.Normalize("checkpoint schema conflict", errors.RFCCodeText("Lightning:PreCheck:ErrCheckpointSchemaConflict")) + ErrPreCheckFailed = errors.Normalize("tidb-lightning pre-check failed: %s", errors.RFCCodeText("Lightning:PreCheck:ErrPreCheckFailed")) + ErrCheckClusterRegion = errors.Normalize("check tikv cluster region error", errors.RFCCodeText("Lightning:PreCheck:ErrCheckClusterRegion")) + ErrCheckLocalResource = errors.Normalize("check local storage resource error", errors.RFCCodeText("Lightning:PreCheck:ErrCheckLocalResource")) + ErrCheckTableEmpty = errors.Normalize("check table empty error", errors.RFCCodeText("Lightning:PreCheck:ErrCheckTableEmpty")) + ErrCheckCSVHeader = errors.Normalize("check csv header error", errors.RFCCodeText("Lightning:PreCheck:ErrCheckCSVHeader")) + ErrCheckDataSource = errors.Normalize("check data source error", errors.RFCCodeText("Lightning:PreCheck:ErrCheckDataSource")) + + ErrOpenCheckpoint = errors.Normalize("open checkpoint error", errors.RFCCodeText("Lightning:Checkpoint:ErrOpenCheckpoint")) + ErrReadCheckpoint = errors.Normalize("read checkpoint error", errors.RFCCodeText("Lightning:Checkpoint:ErrReadCheckpoint")) + ErrUpdateCheckpoint = errors.Normalize("update checkpoint error", errors.RFCCodeText("Lightning:Checkpoint:ErrUpdateCheckpoint")) + ErrUnknownCheckpointDriver = errors.Normalize("unknown checkpoint driver '%s'", errors.RFCCodeText("Lightning:Checkpoint:ErrUnknownCheckpointDriver")) + ErrInvalidCheckpoint = errors.Normalize("invalid checkpoint", errors.RFCCodeText("Lightning:Checkpoint:ErrInvalidCheckpoint")) + ErrCheckpointNotFound = errors.Normalize("checkpoint not found", errors.RFCCodeText("Lightning:Checkpoint:ErrCheckpointNotFound")) + ErrInitCheckpoint = errors.Normalize("init checkpoint error", errors.RFCCodeText("Lightning:Checkpoint:ErrInitCheckpoint")) + ErrCleanCheckpoint = errors.Normalize("clean checkpoint error", errors.RFCCodeText("Lightning:Checkpoint:ErrCleanCheckpoint")) + + ErrMetaMgrUnknown = errors.Normalize("unknown error occur on meta manager", errors.RFCCodeText("Lightning:MetaMgr:ErrMetaMgrUnknown")) + + ErrDBConnect = errors.Normalize("failed to connect database", errors.RFCCodeText("Lightning:DB:ErrDBConnect")) + ErrInitErrManager = errors.Normalize("init error manager error", errors.RFCCodeText("Lightning:DB:ErrInitErrManager")) + ErrInitMetaManager = errors.Normalize("init meta manager error", errors.RFCCodeText("Lightning:DB:ErrInitMetaManager")) + + ErrUpdatePD = errors.Normalize("update pd error", errors.RFCCodeText("Lightning:PD:ErrUpdatePD")) + ErrCreatePDClient = errors.Normalize("create pd client error", errors.RFCCodeText("Lightning:PD:ErrCreatePDClient")) + ErrPauseGC = errors.Normalize("pause gc error", errors.RFCCodeText("Lightning:PD:ErrPauseGC")) + + ErrCheckKVVersion = errors.Normalize("check tikv version error", errors.RFCCodeText("Lightning:KV:ErrCheckKVVersion")) + ErrCreateKVClient = errors.Normalize("create kv client error", errors.RFCCodeText("Lightning:KV:ErrCreateKVClient")) + ErrCheckMultiIngest = errors.Normalize("check multi-ingest support error", errors.RFCCodeText("Lightning:KV:ErrCheckMultiIngest")) + + ErrUnknownBackend = errors.Normalize("unknown backend %s", errors.RFCCodeText("Lightning:Restore:ErrUnknownBackend")) + ErrCheckLocalFile = errors.Normalize("cannot find local file for table: %s engineDir: %s", errors.RFCCodeText("Lightning:Restore:ErrCheckLocalFile")) + ErrOpenDuplicateDB = errors.Normalize("open duplicate db error", errors.RFCCodeText("Lightning:Restore:ErrOpenDuplicateDB")) + ErrSchemaNotExists = errors.Normalize("table `%s`.`%s` schema not found", errors.RFCCodeText("Lightning:Restore:ErrSchemaNotExists")) + ErrInvalidSchemaStmt = errors.Normalize("invalid schema statement: '%s'", errors.RFCCodeText("Lightning:Restore:ErrInvalidSchemaStmt")) + ErrCreateSchema = errors.Normalize("create schema failed, table: %s, stmt: %s", errors.RFCCodeText("Lightning:Restore:ErrCreateSchema")) + ErrUnknownColumns = errors.Normalize("unknown columns in header (%s) for table %s", errors.RFCCodeText("Lightning:Restore:ErrUnknownColumns")) + ErrChecksumMismatch = errors.Normalize("checksum mismatched remote vs local => (checksum: %d vs %d) (total_kvs: %d vs %d) (total_bytes:%d vs %d)", errors.RFCCodeText("Lighting:Restore:ErrChecksumMismatch")) + ErrRestoreTable = errors.Normalize("restore table %s failed", errors.RFCCodeText("Lightning:Restore:ErrRestoreTable")) + ErrEncodeKV = errors.Normalize("encode kv error in file %s at offset %d", errors.RFCCodeText("Lightning:Restore:ErrEncodeKV")) + ErrAllocTableRowIDs = errors.Normalize("allocate table row id error", errors.RFCCodeText("Lightning:Restore:ErrAllocTableRowIDs")) + ErrInvalidMetaStatus = errors.Normalize("invalid meta status: '%s'", errors.RFCCodeText("Lightning:Restore:ErrInvalidMetaStatus")) + ErrTableIsChecksuming = errors.Normalize("table '%s' is checksuming", errors.RFCCodeText("Lightning:Restore:ErrTableIsChecksuming")) +) + +type withStack struct { + error + errors.StackTracer +} + +func (w *withStack) Cause() error { + return w.error +} + +func (w *withStack) Unwrap() error { + return w.error +} + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.StackTrace().Format(s, verb) + return + } + fallthrough + case 's': + _, _ = io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// NormalizeError converts an arbitrary error to *errors.Error based above predefined errors. +// If the underlying err is already an *error.Error which is prefixed by "Lightning:", leave +// error ID unchanged. Otherwise, converts the error ID to Lightning's predefined error IDs. +func NormalizeError(err error) error { + if err == nil { + return nil + } + if IsContextCanceledError(err) { + return err + } + + // Retain the original stack tracer. + stackTracker, hasStack := err.(errors.StackTracer) + maybeAddStack := func(err error) error { + if !hasStack { + return err + } + return &withStack{error: err, StackTracer: stackTracker} + } + + // Find the underlying expectErr. + var normalizedErr *errors.Error + foundErr := errors.Find(err, func(e error) bool { + _, ok := e.(*errors.Error) + return ok + }) + if foundErr != nil { + normalizedErr = foundErr.(*errors.Error) + errMsg := err.Error() + nErrMsg := normalizedErr.Error() + // A workaround for https://github.com/pingcap/tidb/issues/32133. + // Ensure that error code description is always placed at the beginning of the error string. + if errMsg != nErrMsg && strings.HasSuffix(errMsg, ": "+nErrMsg) { + errMsg = errMsg[:len(errMsg)-len(nErrMsg)-2] + causeErr := normalizedErr.Unwrap() + normalizedErr = errors.Normalize(errMsg, errors.RFCCodeText(string(normalizedErr.RFCCode()))) + if causeErr != nil { + normalizedErr = normalizedErr.Wrap(causeErr) + } + err = maybeAddStack(normalizedErr) + } + } + + if normalizedErr != nil { + if strings.HasPrefix(string(normalizedErr.ID()), "Lightning:") { + return err + } + // Convert BR error id to Lightning error id. + var errID errors.ErrorID + switch normalizedErr.ID() { + case berrors.ErrStorageUnknown.ID(): + errID = ErrStorageUnknown.ID() + case berrors.ErrStorageInvalidConfig.ID(): + errID = ErrInvalidStorageConfig.ID() + case berrors.ErrStorageInvalidPermission.ID(): + errID = ErrInvalidPermission.ID() + case berrors.ErrPDUpdateFailed.ID(): + errID = ErrUpdatePD.ID() + case berrors.ErrVersionMismatch.ID(): + errID = ErrVersionMismatch.ID() + default: + errID = ErrUnknown.ID() + } + causeErr := normalizedErr.Unwrap() + normalizedErr = errors.Normalize(normalizedErr.GetMsg(), errors.RFCCodeText(string(errID))) + if causeErr != nil { + normalizedErr = normalizedErr.Wrap(causeErr) + } + err = maybeAddStack(normalizedErr) + } else { + err = ErrUnknown.Wrap(err) + } + // TODO: Do we need to optimize the output error messages for aws errors or gRPC errors. + return err +} + +// NormalizeOrWrapErr tries to normalize err. If the returned error is ErrUnknown, wraps it with the given rfcErr. +func NormalizeOrWrapErr(rfcErr *errors.Error, err error, args ...interface{}) error { + if err == nil { + return nil + } + if IsContextCanceledError(err) { + return err + } + normalizedErr := NormalizeError(err) + if berrors.Is(normalizedErr, ErrUnknown) { + return rfcErr.Wrap(err).GenWithStackByArgs(args...) + } else { + return normalizedErr + } +} diff --git a/br/pkg/lightning/common/errors_test.go b/br/pkg/lightning/common/errors_test.go new file mode 100644 index 0000000000000..f5dcff0ada801 --- /dev/null +++ b/br/pkg/lightning/common/errors_test.go @@ -0,0 +1,94 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + "io" + "testing" + + "github.com/pingcap/errors" + berrors "github.com/pingcap/tidb/br/pkg/errors" + "github.com/stretchr/testify/require" +) + +func TestNormalizeError(t *testing.T) { + err := NormalizeError(nil) + require.NoError(t, err) + err = NormalizeError(io.EOF) + require.True(t, berrors.Is(err, ErrUnknown)) + + testCases := []struct { + rfcErr *errors.Error + errMsg string + expectErr *errors.Error + expectErrMsg string + }{ + { + rfcErr: berrors.ErrStorageUnknown, + errMsg: "ContentRange is empty", + expectErr: ErrStorageUnknown, + expectErrMsg: "[Lightning:Storage:ErrStorageUnknown]ContentRange is empty", + }, + { + rfcErr: berrors.ErrStorageInvalidConfig, + errMsg: "host not found in endpoint", + expectErr: ErrInvalidStorageConfig, + expectErrMsg: "[Lightning:Storage:ErrInvalidStorageConfig]host not found in endpoint", + }, + { + rfcErr: berrors.ErrStorageInvalidPermission, + errMsg: "check permission failed", + expectErr: ErrInvalidPermission, + expectErrMsg: "[Lightning:Storage:ErrInvalidPermission]check permission failed", + }, + { + rfcErr: berrors.ErrPDUpdateFailed, + errMsg: "create pd client failed", + expectErr: ErrUpdatePD, + expectErrMsg: "[Lightning:PD:ErrUpdatePD]create pd client failed", + }, + { + rfcErr: ErrInvalidConfig, + errMsg: "tikv-importer.backend must not be empty!", + expectErr: ErrInvalidConfig, + expectErrMsg: "[Lightning:Config:ErrInvalidConfig]tikv-importer.backend must not be empty!", + }, + } + + for _, tc := range testCases { + err = errors.Annotate(tc.rfcErr, tc.errMsg) + normalizedErr := NormalizeError(err) + require.Error(t, normalizedErr) + require.True(t, berrors.Is(normalizedErr, tc.expectErr)) + require.EqualError(t, normalizedErr, tc.expectErrMsg) + stackTrace, ok := normalizedErr.(errors.StackTracer) + require.True(t, ok) + errStack := fmt.Sprintf("%+v", err.(errors.StackTracer).StackTrace()) + errStack2 := fmt.Sprintf("%+v", stackTrace.StackTrace()) + require.Equal(t, errStack, errStack2) + } +} + +func TestNormalizeOrWrapErr(t *testing.T) { + err := NormalizeOrWrapErr(ErrInvalidArgument, nil) + require.NoError(t, err) + err = NormalizeOrWrapErr(ErrInvalidArgument, ErrInvalidConfig.GenWithStack("tikv-importer.backend must not be empty!")) + require.Error(t, err) + require.True(t, berrors.Is(err, ErrInvalidConfig)) + err = NormalizeOrWrapErr(ErrInvalidArgument, io.EOF) + require.Error(t, err) + require.True(t, berrors.Is(err, ErrInvalidArgument)) +} diff --git a/br/pkg/lightning/common/main_test.go b/br/pkg/lightning/common/main_test.go new file mode 100644 index 0000000000000..716589aa28a7c --- /dev/null +++ b/br/pkg/lightning/common/main_test.go @@ -0,0 +1,31 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common_test + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) +} diff --git a/br/pkg/lightning/common/once_error_test.go b/br/pkg/lightning/common/once_error_test.go index 3e4ae41121a11..1ba86d0a8b2e9 100644 --- a/br/pkg/lightning/common/once_error_test.go +++ b/br/pkg/lightning/common/once_error_test.go @@ -18,36 +18,28 @@ import ( "errors" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/stretchr/testify/require" ) -func TestCommon(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&onceErrorSuite{}) - -type onceErrorSuite struct{} - -func (s *onceErrorSuite) TestOnceError(c *C) { +func TestOnceError(t *testing.T) { var err common.OnceError - c.Assert(err.Get(), IsNil) + require.Nil(t, err.Get()) err.Set(nil) - c.Assert(err.Get(), IsNil) + require.Nil(t, err.Get()) e := errors.New("1") err.Set(e) - c.Assert(err.Get(), Equals, e) + require.Equal(t, e, err.Get()) e2 := errors.New("2") err.Set(e2) - c.Assert(err.Get(), Equals, e) // e, not e2. + require.Equal(t, e, err.Get()) // e, not e2. err.Set(nil) - c.Assert(err.Get(), Equals, e) + require.Equal(t, e, err.Get()) ch := make(chan struct{}) go func() { @@ -55,5 +47,5 @@ func (s *onceErrorSuite) TestOnceError(c *C) { ch <- struct{}{} }() <-ch - c.Assert(err.Get(), Equals, e) + require.Equal(t, e, err.Get()) } diff --git a/br/pkg/lightning/common/pause_test.go b/br/pkg/lightning/common/pause_test.go index 34ee124b7026a..8676482dc738b 100644 --- a/br/pkg/lightning/common/pause_test.go +++ b/br/pkg/lightning/common/pause_test.go @@ -17,27 +17,15 @@ package common_test import ( "context" "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -// unblocksAfter is a checker which ensures the WaitGroup's Wait() method -// returns between the given durations. -var unblocksBetween Checker = &unblocksChecker{ - &CheckerInfo{Name: "unblocksBetween", Params: []string{"waitGroupPtr", "min", "max"}}, -} - -type unblocksChecker struct { - *CheckerInfo -} - -func (checker *unblocksChecker) Check(params []interface{}, names []string) (bool, string) { - wg := params[0].(*sync.WaitGroup) - min := params[1].(time.Duration) - max := params[2].(time.Duration) - +func assertUnblocksBetween(t *testing.T, wg *sync.WaitGroup, min, max time.Duration) { ch := make(chan time.Duration) start := time.Now() go func() { @@ -47,24 +35,19 @@ func (checker *unblocksChecker) Check(params []interface{}, names []string) (boo select { case dur := <-ch: if dur < min { - return false, "WaitGroup unblocked before minimum duration, it was " + dur.String() + t.Fatal("WaitGroup unblocked before minimum duration, it was " + dur.String()) } - return true, "" case <-time.After(max): select { case dur := <-ch: - return false, "WaitGroup did not unblock after maximum duration, it was " + dur.String() + t.Fatal("WaitGroup did not unblock after maximum duration, it was " + dur.String()) case <-time.After(1 * time.Second): - return false, "WaitGroup did not unblock after maximum duration" + t.Fatal("WaitGroup did not unblock after maximum duration") } } } -var _ = Suite(&pauseSuite{}) - -type pauseSuite struct{} - -func (s *pauseSuite) TestPause(c *C) { +func TestPause(t *testing.T) { var wg sync.WaitGroup p := common.NewPauser() @@ -75,12 +58,12 @@ func (s *pauseSuite) TestPause(c *C) { go func() { defer wg.Done() err := p.Wait(context.Background()) - c.Assert(err, IsNil) + assert.NoError(t, err) }() } // Give them more time to unblock in case of time exceeding due to high pressure of CI. - c.Assert(&wg, unblocksBetween, 0*time.Millisecond, 100*time.Millisecond) + assertUnblocksBetween(t, &wg, 0*time.Millisecond, 100*time.Millisecond) // after calling Pause(), these should be blocking... @@ -91,7 +74,7 @@ func (s *pauseSuite) TestPause(c *C) { go func() { defer wg.Done() err := p.Wait(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) }() } @@ -103,7 +86,7 @@ func (s *pauseSuite) TestPause(c *C) { }() // Give them more time to unblock in case of time exceeding due to high pressure of CI. - c.Assert(&wg, unblocksBetween, 500*time.Millisecond, 800*time.Millisecond) + assertUnblocksBetween(t, &wg, 500*time.Millisecond, 800*time.Millisecond) // if the context is canceled, Wait() should immediately unblock... @@ -116,13 +99,13 @@ func (s *pauseSuite) TestPause(c *C) { go func() { defer wg.Done() err := p.Wait(ctx) - c.Assert(err, Equals, context.Canceled) + require.ErrorIs(t, err, context.Canceled) }() } cancel() // Give them more time to unblock in case of time exceeding due to high pressure of CI. - c.Assert(&wg, unblocksBetween, 0*time.Millisecond, 100*time.Millisecond) + assertUnblocksBetween(t, &wg, 0*time.Millisecond, 100*time.Millisecond) // canceling the context does not affect the state of the pauser @@ -130,7 +113,7 @@ func (s *pauseSuite) TestPause(c *C) { go func() { defer wg.Done() err := p.Wait(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) }() go func() { @@ -139,29 +122,29 @@ func (s *pauseSuite) TestPause(c *C) { }() // Give them more time to unblock in case of time exceeding due to high pressure of CI. - c.Assert(&wg, unblocksBetween, 500*time.Millisecond, 800*time.Millisecond) + assertUnblocksBetween(t, &wg, 500*time.Millisecond, 800*time.Millisecond) } // Run `go test github.com/pingcap/tidb/br/pkg/lightning/common -check.b -test.v` to get benchmark result. -func (s *pauseSuite) BenchmarkWaitNoOp(c *C) { +func BenchmarkWaitNoOp(b *testing.B) { p := common.NewPauser() ctx := context.Background() - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { _ = p.Wait(ctx) } } -func (s *pauseSuite) BenchmarkWaitCtxCanceled(c *C) { +func BenchmarkWaitCtxCanceled(b *testing.B) { p := common.NewPauser() p.Pause() ctx, cancel := context.WithCancel(context.Background()) cancel() - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { _ = p.Wait(ctx) } } -func (s *pauseSuite) BenchmarkWaitContended(c *C) { +func BenchmarkWaitContended(b *testing.B) { p := common.NewPauser() done := make(chan struct{}) @@ -184,7 +167,7 @@ func (s *pauseSuite) BenchmarkWaitContended(c *C) { }() ctx := context.Background() - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { _ = p.Wait(ctx) } } diff --git a/br/pkg/lightning/common/security.go b/br/pkg/lightning/common/security.go index 2e7739512bba1..9db53f78a5115 100644 --- a/br/pkg/lightning/common/security.go +++ b/br/pkg/lightning/common/security.go @@ -76,6 +76,7 @@ func ToTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) { Certificates: certificates, RootCAs: certPool, NextProtos: []string{"h2", "http/1.1"}, // specify `h2` to let Go use HTTP/2. + MinVersion: tls.VersionTLS12, }, nil } diff --git a/br/pkg/lightning/common/security_test.go b/br/pkg/lightning/common/security_test.go index 1eec0ef9f72ce..a68b8e1f4437a 100644 --- a/br/pkg/lightning/common/security_test.go +++ b/br/pkg/lightning/common/security_test.go @@ -22,42 +22,39 @@ import ( "net/url" "os" "path/filepath" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/stretchr/testify/require" ) -type securitySuite struct{} - -var _ = Suite(&securitySuite{}) - func respondPathHandler(w http.ResponseWriter, req *http.Request) { _, _ = io.WriteString(w, `{"path":"`) _, _ = io.WriteString(w, req.URL.Path) _, _ = io.WriteString(w, `"}`) } -func (s *securitySuite) TestGetJSONInsecure(c *C) { +func TestGetJSONInsecure(t *testing.T) { mockServer := httptest.NewServer(http.HandlerFunc(respondPathHandler)) defer mockServer.Close() ctx := context.Background() u, err := url.Parse(mockServer.URL) - c.Assert(err, IsNil) + require.NoError(t, err) tls, err := common.NewTLS("", "", "", u.Host) - c.Assert(err, IsNil) + require.NoError(t, err) var result struct{ Path string } err = tls.GetJSON(ctx, "/aaa", &result) - c.Assert(err, IsNil) - c.Assert(result.Path, Equals, "/aaa") + require.NoError(t, err) + require.Equal(t, "/aaa", result.Path) err = tls.GetJSON(ctx, "/bbbb", &result) - c.Assert(err, IsNil) - c.Assert(result.Path, Equals, "/bbbb") + require.NoError(t, err) + require.Equal(t, "/bbbb", result.Path) } -func (s *securitySuite) TestGetJSONSecure(c *C) { +func TestGetJSONSecure(t *testing.T) { mockServer := httptest.NewTLSServer(http.HandlerFunc(respondPathHandler)) defer mockServer.Close() @@ -66,34 +63,33 @@ func (s *securitySuite) TestGetJSONSecure(c *C) { var result struct{ Path string } err := tls.GetJSON(ctx, "/ccc", &result) - c.Assert(err, IsNil) - c.Assert(result.Path, Equals, "/ccc") + require.NoError(t, err) + require.Equal(t, "/ccc", result.Path) err = tls.GetJSON(ctx, "/dddd", &result) - c.Assert(err, IsNil) - c.Assert(result.Path, Equals, "/dddd") + require.NoError(t, err) + require.Equal(t, "/dddd", result.Path) } -func (s *securitySuite) TestInvalidTLS(c *C) { - tempDir := c.MkDir() - +func TestInvalidTLS(t *testing.T) { + tempDir := t.TempDir() caPath := filepath.Join(tempDir, "ca.pem") _, err := common.NewTLS(caPath, "", "", "localhost") - c.Assert(err, ErrorMatches, "could not read ca certificate:.*") + require.Regexp(t, "could not read ca certificate:.*", err.Error()) err = os.WriteFile(caPath, []byte("invalid ca content"), 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = common.NewTLS(caPath, "", "", "localhost") - c.Assert(err, ErrorMatches, "failed to append ca certs") + require.Regexp(t, "failed to append ca certs", err.Error()) certPath := filepath.Join(tempDir, "test.pem") keyPath := filepath.Join(tempDir, "test.key") _, err = common.NewTLS(caPath, certPath, keyPath, "localhost") - c.Assert(err, ErrorMatches, "could not load client key pair: open.*") + require.Regexp(t, "could not load client key pair: open.*", err.Error()) err = os.WriteFile(certPath, []byte("invalid cert content"), 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) err = os.WriteFile(keyPath, []byte("invalid key content"), 0o600) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = common.NewTLS(caPath, certPath, keyPath, "localhost") - c.Assert(err, ErrorMatches, "could not load client key pair: tls.*") + require.Regexp(t, "could not load client key pair: tls.*", err.Error()) } diff --git a/br/pkg/lightning/common/storage_test.go b/br/pkg/lightning/common/storage_test.go index db46269149a4c..11dc364c52e13 100644 --- a/br/pkg/lightning/common/storage_test.go +++ b/br/pkg/lightning/common/storage_test.go @@ -15,20 +15,17 @@ package common_test import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testStorageSuite{}) - -type testStorageSuite struct { -} - -func (t *testStorageSuite) TestGetStorageSize(c *C) { +func TestGetStorageSize(t *testing.T) { // only ensure we can get storage size. - d := c.MkDir() + d := t.TempDir() size, err := common.GetStorageSize(d) - c.Assert(err, IsNil) - c.Assert(size.Capacity, Greater, uint64(0)) - c.Assert(size.Available, Greater, uint64(0)) + require.NoError(t, err) + require.Greater(t, size.Capacity, uint64(0)) + require.Greater(t, size.Available, uint64(0)) } diff --git a/br/pkg/lightning/common/storage_unix.go b/br/pkg/lightning/common/storage_unix.go index 465bc912a373b..e779aeb2ea57c 100644 --- a/br/pkg/lightning/common/storage_unix.go +++ b/br/pkg/lightning/common/storage_unix.go @@ -24,13 +24,18 @@ import ( "syscall" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "golang.org/x/sys/unix" ) // GetStorageSize gets storage's capacity and available size func GetStorageSize(dir string) (size StorageSize, err error) { - var stat unix.Statfs_t + failpoint.Inject("GetStorageSize", func(val failpoint.Value) { + injectedSize := val.(int) + failpoint.Return(StorageSize{Capacity: uint64(injectedSize), Available: uint64(injectedSize)}, nil) + }) + var stat unix.Statfs_t err = unix.Statfs(dir, &stat) if err != nil { return size, errors.Annotatef(err, "cannot get disk capacity at %s", dir) @@ -52,7 +57,7 @@ func GetStorageSize(dir string) (size StorageSize, err error) { } // Available blocks * size per block = available space in bytes - size.Available = uint64(stat.Bavail) * bSize + size.Available = stat.Bavail * bSize size.Capacity = stat.Blocks * bSize return diff --git a/br/pkg/lightning/common/storage_windows.go b/br/pkg/lightning/common/storage_windows.go index 737f21acf8c44..8617e28d30893 100644 --- a/br/pkg/lightning/common/storage_windows.go +++ b/br/pkg/lightning/common/storage_windows.go @@ -24,6 +24,7 @@ import ( "unsafe" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" ) var ( @@ -33,6 +34,10 @@ var ( // GetStorageSize gets storage's capacity and available size func GetStorageSize(dir string) (size StorageSize, err error) { + failpoint.Inject("GetStorageSize", func(val failpoint.Value) { + injectedSize := val.(int) + failpoint.Return(StorageSize{Capacity: uint64(injectedSize), Available: uint64(injectedSize)}, nil) + }) r, _, e := getDiskFreeSpaceExW.Call( uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(dir))), uintptr(unsafe.Pointer(&size.Available)), diff --git a/br/pkg/lightning/common/util.go b/br/pkg/lightning/common/util.go index f8345b22e6500..054edcbb17d90 100644 --- a/br/pkg/lightning/common/util.go +++ b/br/pkg/lightning/common/util.go @@ -17,6 +17,7 @@ package common import ( "context" "database/sql" + "encoding/base64" "encoding/json" "fmt" "io" @@ -27,9 +28,12 @@ import ( "syscall" "time" + "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/utils" + tmysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/model" "go.uber.org/zap" ) @@ -58,19 +62,61 @@ func (param *MySQLConnectParam) ToDSN() string { param.SQLMode, param.MaxAllowedPacket, param.TLS) for k, v := range param.Vars { - dsn += fmt.Sprintf("&%s=%s", k, url.QueryEscape(v)) + dsn += fmt.Sprintf("&%s='%s'", k, url.QueryEscape(v)) } return dsn } -func (param *MySQLConnectParam) Connect() (*sql.DB, error) { - db, err := sql.Open("mysql", param.ToDSN()) +func tryConnectMySQL(dsn string) (*sql.DB, error) { + driverName := "mysql" + failpoint.Inject("MockMySQLDriver", func(val failpoint.Value) { + driverName = val.(string) + }) + db, err := sql.Open(driverName, dsn) + if err != nil { + return nil, errors.Trace(err) + } + if err = db.Ping(); err != nil { + _ = db.Close() + return nil, errors.Trace(err) + } + return db, nil +} + +// ConnectMySQL connects MySQL with the dsn. If access is denied and the password is a valid base64 encoding, +// we will try to connect MySQL with the base64 decoding of the password. +func ConnectMySQL(dsn string) (*sql.DB, error) { + cfg, err := mysql.ParseDSN(dsn) if err != nil { return nil, errors.Trace(err) } + // Try plain password first. + db, firstErr := tryConnectMySQL(dsn) + if firstErr == nil { + return db, nil + } + // If access is denied and password is encoded by base64, try the decoded string as well. + if mysqlErr, ok := errors.Cause(firstErr).(*mysql.MySQLError); ok && mysqlErr.Number == tmysql.ErrAccessDenied { + // If password is encoded by base64, try the decoded string as well. + if password, decodeErr := base64.StdEncoding.DecodeString(cfg.Passwd); decodeErr == nil && string(password) != cfg.Passwd { + cfg.Passwd = string(password) + db, err = tryConnectMySQL(cfg.FormatDSN()) + if err == nil { + return db, nil + } + } + } + // If we can't connect successfully, return the first error. + return nil, errors.Trace(firstErr) +} - return db, errors.Trace(db.Ping()) +func (param *MySQLConnectParam) Connect() (*sql.DB, error) { + db, err := ConnectMySQL(param.ToDSN()) + if err != nil { + return nil, errors.Trace(err) + } + return db, nil } // IsDirExists checks if dir exists. @@ -315,8 +361,6 @@ type KvPair struct { Val []byte // RowID is the row id of the KV pair. RowID int64 - // Offset is the row's offset in file. - Offset int64 } // TableHasAutoRowID return whether table has auto generated row id diff --git a/br/pkg/lightning/common/util_test.go b/br/pkg/lightning/common/util_test.go index 60812841ff259..3b6ff5f92ef62 100644 --- a/br/pkg/lightning/common/util_test.go +++ b/br/pkg/lightning/common/util_test.go @@ -16,29 +16,36 @@ package common_test import ( "context" + "database/sql" + "database/sql/driver" + "encoding/base64" "encoding/json" + "fmt" "io" + "math/rand" "net/http" "net/http/httptest" + "strconv" + "testing" "time" - sqlmock "github.com/DATA-DOG/go-sqlmock" - . "github.com/pingcap/check" + "github.com/DATA-DOG/go-sqlmock" + "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/log" + tmysql "github.com/pingcap/tidb/errno" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -type utilSuite struct{} - -var _ = Suite(&utilSuite{}) - -func (s *utilSuite) TestDirNotExist(c *C) { - c.Assert(common.IsDirExists("."), IsTrue) - c.Assert(common.IsDirExists("not-exists"), IsFalse) +func TestDirNotExist(t *testing.T) { + require.True(t, common.IsDirExists(".")) + require.False(t, common.IsDirExists("not-exists")) } -func (s *utilSuite) TestGetJSON(c *C) { +func TestGetJSON(t *testing.T) { type TestPayload struct { Username string `json:"username"` Password string `json:"password"` @@ -53,7 +60,7 @@ func (s *utilSuite) TestGetJSON(c *C) { handle := func(res http.ResponseWriter, _ *http.Request) { res.WriteHeader(http.StatusOK) err := json.NewEncoder(res).Encode(request) - c.Assert(err, IsNil) + require.NoError(t, err) } testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { handle(res, req) @@ -64,21 +71,21 @@ func (s *utilSuite) TestGetJSON(c *C) { response := TestPayload{} err := common.GetJSON(ctx, client, "http://not-exists", &response) - c.Assert(err, NotNil) + require.Error(t, err) err = common.GetJSON(ctx, client, testServer.URL, &response) - c.Assert(err, IsNil) - c.Assert(request, DeepEquals, response) + require.NoError(t, err) + require.Equal(t, request, response) // Mock `StatusNoContent` response handle = func(res http.ResponseWriter, _ *http.Request) { res.WriteHeader(http.StatusNoContent) } err = common.GetJSON(ctx, client, testServer.URL, &response) - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, ".*http status code != 200.*") + require.Error(t, err) + require.Regexp(t, ".*http status code != 200.*", err.Error()) } -func (s *utilSuite) TestToDSN(c *C) { +func TestToDSN(t *testing.T) { param := common.MySQLConnectParam{ Host: "127.0.0.1", Port: 4000, @@ -91,25 +98,86 @@ func (s *utilSuite) TestToDSN(c *C) { "tidb_distsql_scan_concurrency": "1", }, } - c.Assert(param.ToDSN(), Equals, "root:123456@tcp(127.0.0.1:4000)/?charset=utf8mb4&sql_mode='strict'&maxAllowedPacket=1234&tls=cluster&tidb_distsql_scan_concurrency=1") + require.Equal(t, "root:123456@tcp(127.0.0.1:4000)/?charset=utf8mb4&sql_mode='strict'&maxAllowedPacket=1234&tls=cluster&tidb_distsql_scan_concurrency='1'", param.ToDSN()) +} + +type mockDriver struct { + driver.Driver + plainPsw string +} + +func (m *mockDriver) Open(dsn string) (driver.Conn, error) { + cfg, err := mysql.ParseDSN(dsn) + if err != nil { + return nil, err + } + accessDenied := cfg.Passwd != m.plainPsw + return &mockConn{accessDenied: accessDenied}, nil +} + +type mockConn struct { + driver.Conn + driver.Pinger + accessDenied bool +} + +func (c *mockConn) Ping(ctx context.Context) error { + if c.accessDenied { + return &mysql.MySQLError{Number: tmysql.ErrAccessDenied, Message: "access denied"} + } + return nil +} + +func (c *mockConn) Close() error { + return nil +} + +func TestConnect(t *testing.T) { + plainPsw := "dQAUoDiyb1ucWZk7" + driverName := "mysql-mock-" + strconv.Itoa(rand.Int()) + sql.Register(driverName, &mockDriver{plainPsw: plainPsw}) + + require.NoError(t, failpoint.Enable( + "github.com/pingcap/tidb/br/pkg/lightning/common/MockMySQLDriver", + fmt.Sprintf("return(\"%s\")", driverName))) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/common/MockMySQLDriver")) + }() + + param := common.MySQLConnectParam{ + Host: "127.0.0.1", + Port: 4000, + User: "root", + Password: plainPsw, + SQLMode: "strict", + MaxAllowedPacket: 1234, + } + db, err := param.Connect() + require.NoError(t, err) + require.NoError(t, db.Close()) + param.Password = base64.StdEncoding.EncodeToString([]byte(plainPsw)) + db, err = param.Connect() + require.NoError(t, err) + require.NoError(t, db.Close()) } -func (s *utilSuite) TestIsContextCanceledError(c *C) { - c.Assert(common.IsContextCanceledError(context.Canceled), IsTrue) - c.Assert(common.IsContextCanceledError(io.EOF), IsFalse) +func TestIsContextCanceledError(t *testing.T) { + require.True(t, common.IsContextCanceledError(context.Canceled)) + require.False(t, common.IsContextCanceledError(io.EOF)) } -func (s *utilSuite) TestUniqueTable(c *C) { +func TestUniqueTable(t *testing.T) { tableName := common.UniqueTable("test", "t1") - c.Assert(tableName, Equals, "`test`.`t1`") + require.Equal(t, "`test`.`t1`", tableName) tableName = common.UniqueTable("test", "t`1") - c.Assert(tableName, Equals, "`test`.`t``1`") + require.Equal(t, "`test`.`t``1`", tableName) } -func (s *utilSuite) TestSQLWithRetry(c *C) { +func TestSQLWithRetry(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + defer db.Close() sqlWithRetry := &common.SQLWithRetry{ DB: db, @@ -122,48 +190,48 @@ func (s *utilSuite) TestSQLWithRetry(c *C) { mock.ExpectQuery("select a from test.t1").WillReturnError(errors.New("mock error")) } err = sqlWithRetry.QueryRow(context.Background(), "", "select a from test.t1", aValue) - c.Assert(err, ErrorMatches, ".*mock error") + require.Regexp(t, ".*mock error", err.Error()) // meet unretryable error and will return directly mock.ExpectQuery("select a from test.t1").WillReturnError(context.Canceled) err = sqlWithRetry.QueryRow(context.Background(), "", "select a from test.t1", aValue) - c.Assert(err, ErrorMatches, ".*context canceled") + require.Regexp(t, ".*context canceled", err.Error()) // query success rows := sqlmock.NewRows([]string{"a"}).AddRow("1") mock.ExpectQuery("select a from test.t1").WillReturnRows(rows) err = sqlWithRetry.QueryRow(context.Background(), "", "select a from test.t1", aValue) - c.Assert(err, IsNil) - c.Assert(*aValue, Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, *aValue) // test Exec mock.ExpectExec("delete from").WillReturnError(context.Canceled) err = sqlWithRetry.Exec(context.Background(), "", "delete from test.t1 where id = ?", 2) - c.Assert(err, ErrorMatches, ".*context canceled") + require.Regexp(t, ".*context canceled", err.Error()) mock.ExpectExec("delete from").WillReturnResult(sqlmock.NewResult(0, 1)) err = sqlWithRetry.Exec(context.Background(), "", "delete from test.t1 where id = ?", 2) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(mock.ExpectationsWereMet(), IsNil) + require.Nil(t, mock.ExpectationsWereMet()) } -func (s *utilSuite) TestStringSliceEqual(c *C) { - c.Assert(common.StringSliceEqual(nil, nil), IsTrue) - c.Assert(common.StringSliceEqual(nil, []string{}), IsTrue) - c.Assert(common.StringSliceEqual(nil, []string{"a"}), IsFalse) - c.Assert(common.StringSliceEqual([]string{"a"}, nil), IsFalse) - c.Assert(common.StringSliceEqual([]string{"a"}, []string{"a"}), IsTrue) - c.Assert(common.StringSliceEqual([]string{"a"}, []string{"b"}), IsFalse) - c.Assert(common.StringSliceEqual([]string{"a", "b", "c"}, []string{"a", "b", "c"}), IsTrue) - c.Assert(common.StringSliceEqual([]string{"a"}, []string{"a", "b", "c"}), IsFalse) - c.Assert(common.StringSliceEqual([]string{"a", "b", "c"}, []string{"a", "b"}), IsFalse) - c.Assert(common.StringSliceEqual([]string{"a", "x", "y"}, []string{"a", "y", "x"}), IsFalse) +func TestStringSliceEqual(t *testing.T) { + assert.True(t, common.StringSliceEqual(nil, nil)) + assert.True(t, common.StringSliceEqual(nil, []string{})) + assert.False(t, common.StringSliceEqual(nil, []string{"a"})) + assert.False(t, common.StringSliceEqual([]string{"a"}, nil)) + assert.True(t, common.StringSliceEqual([]string{"a"}, []string{"a"})) + assert.False(t, common.StringSliceEqual([]string{"a"}, []string{"b"})) + assert.True(t, common.StringSliceEqual([]string{"a", "b", "c"}, []string{"a", "b", "c"})) + assert.False(t, common.StringSliceEqual([]string{"a"}, []string{"a", "b", "c"})) + assert.False(t, common.StringSliceEqual([]string{"a", "b", "c"}, []string{"a", "b"})) + assert.False(t, common.StringSliceEqual([]string{"a", "x", "y"}, []string{"a", "y", "x"})) } -func (s *utilSuite) TestInterpolateMySQLString(c *C) { - c.Assert(common.InterpolateMySQLString("123"), Equals, "'123'") - c.Assert(common.InterpolateMySQLString("1'23"), Equals, "'1''23'") - c.Assert(common.InterpolateMySQLString("1'2''3"), Equals, "'1''2''''3'") +func TestInterpolateMySQLString(t *testing.T) { + assert.Equal(t, "'123'", common.InterpolateMySQLString("123")) + assert.Equal(t, "'1''23'", common.InterpolateMySQLString("1'23")) + assert.Equal(t, "'1''2''''3'", common.InterpolateMySQLString("1'2''3")) } diff --git a/br/pkg/lightning/config/bytesize_test.go b/br/pkg/lightning/config/bytesize_test.go index 5e8d07785561a..56637486275a4 100644 --- a/br/pkg/lightning/config/bytesize_test.go +++ b/br/pkg/lightning/config/bytesize_test.go @@ -16,18 +16,16 @@ package config_test import ( "encoding/json" + "fmt" "strings" + "testing" "github.com/BurntSushi/toml" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/stretchr/testify/require" ) -type byteSizeTestSuite struct{} - -var _ = Suite(&byteSizeTestSuite{}) - -func (s *byteSizeTestSuite) TestByteSizeTOMLDecode(c *C) { +func TestByteSizeTOMLDecode(t *testing.T) { testCases := []struct { input string output config.ByteSize @@ -100,19 +98,20 @@ func (s *byteSizeTestSuite) TestByteSizeTOMLDecode(c *C) { } for _, tc := range testCases { - comment := Commentf("input: `%s`", tc.input) + comment := fmt.Sprintf("input: `%s`", tc.input) var output struct{ X config.ByteSize } err := toml.Unmarshal([]byte(tc.input), &output) if tc.err != "" { - c.Assert(err, ErrorMatches, tc.err, comment) + require.Error(t, err) + require.Regexp(t, tc.err, err.Error(), comment) } else { - c.Assert(err, IsNil, comment) - c.Assert(output.X, Equals, tc.output, comment) + require.NoError(t, err) + require.Equal(t, tc.output, output.X, comment) } } } -func (s *byteSizeTestSuite) TestByteSizeTOMLAndJSONEncode(c *C) { +func TestByteSizeTOMLAndJSONEncode(t *testing.T) { var input struct { X config.ByteSize `toml:"x" json:"x"` } @@ -120,10 +119,10 @@ func (s *byteSizeTestSuite) TestByteSizeTOMLAndJSONEncode(c *C) { var output strings.Builder err := toml.NewEncoder(&output).Encode(input) - c.Assert(err, IsNil) - c.Assert(output.String(), Equals, "x = 1048576\n") + require.NoError(t, err) + require.Equal(t, "x = 1048576\n", output.String()) js, err := json.Marshal(input) - c.Assert(err, IsNil) - c.Assert(string(js), Equals, `{"x":1048576}`) + require.NoError(t, err) + require.Equal(t, `{"x":1048576}`, string(js)) } diff --git a/br/pkg/lightning/config/config.go b/br/pkg/lightning/config/config.go index d080d1bad16cf..7af314d55950d 100644 --- a/br/pkg/lightning/config/config.go +++ b/br/pkg/lightning/config/config.go @@ -33,12 +33,12 @@ import ( "github.com/docker/go-units" gomysql "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - router "github.com/pingcap/tidb-tools/pkg/table-router" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/log" tidbcfg "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/parser/mysql" + filter "github.com/pingcap/tidb/util/table-filter" + router "github.com/pingcap/tidb/util/table-router" "go.uber.org/atomic" "go.uber.org/zap" ) @@ -70,7 +70,6 @@ const ( ErrorOnDup = "error" defaultDistSQLScanConcurrency = 15 - distSQLScanConcurrencyPerStore = 4 defaultBuildStatsConcurrency = 20 defaultIndexSerialScanConcurrency = 20 defaultChecksumTableConcurrency = 2 @@ -88,20 +87,16 @@ const ( // // With cron.check-disk-quota = 1m, region-concurrency = 40, this should // contribute 2.3 GiB to the reserved size. - autoDiskQuotaLocalReservedSpeed uint64 = 1 * units.KiB - defaultEngineMemCacheSize = 512 * units.MiB - defaultLocalWriterMemCacheSize = 128 * units.MiB - - maxRetryTimes = 4 - defaultRetryBackoffTime = 100 * time.Millisecond - pdStores = "/pd/api/v1/stores" + // autoDiskQuotaLocalReservedSpeed uint64 = 1 * units.KiB + defaultEngineMemCacheSize = 512 * units.MiB + defaultLocalWriterMemCacheSize = 128 * units.MiB defaultCSVDataCharacterSet = "binary" defaultCSVDataInvalidCharReplace = utf8.RuneError ) var ( - supportedStorageTypes = []string{"file", "local", "s3", "noop", "gcs"} + supportedStorageTypes = []string{"file", "local", "s3", "noop", "gcs", "gs"} DefaultFilter = []string{ "*.*", @@ -342,6 +337,10 @@ type MaxError struct { func (cfg *MaxError) UnmarshalTOML(v interface{}) error { switch val := v.(type) { case int64: + // ignore val that is smaller than 0 + if val < 0 { + val = 0 + } cfg.Syntax.Store(0) cfg.Charset.Store(math.MaxInt64) cfg.Type.Store(val) @@ -493,7 +492,7 @@ func (igCols AllIgnoreColumns) GetIgnoreColumns(db string, table string, caseSen } f, err := filter.Parse(ig.TableFilter) if err != nil { - return nil, errors.Trace(err) + return nil, common.ErrInvalidConfig.GenWithStack("invalid table filter %s in ignore columns", strings.Join(ig.TableFilter, ",")) } if f.MatchTable(db, table) { return igCols[i], nil @@ -510,8 +509,10 @@ type FileRouteRule struct { Type string `json:"type" toml:"type" yaml:"type"` Key string `json:"key" toml:"key" yaml:"key"` Compression string `json:"compression" toml:"compression" yaml:"compression"` - // TODO: DataCharacterSet here can overide the same field in [mydumper.csv] with a higher level. - // This could provide users a more flexable usage to configure different files with + // unescape the schema/table name only used in lightning's internal logic now. + Unescape bool `json:"-" toml:"-" yaml:"-"` + // TODO: DataCharacterSet here can override the same field in [mydumper.csv] with a higher level. + // This could provide users a more flexible usage to configure different files with // different data charsets. // DataCharacterSet string `toml:"data-character-set" json:"data-character-set"` } @@ -527,6 +528,7 @@ type TikvImporter struct { DiskQuota ByteSize `toml:"disk-quota" json:"disk-quota"` RangeConcurrency int `toml:"range-concurrency" json:"range-concurrency"` DuplicateResolution DuplicateResolutionAlgorithm `toml:"duplicate-resolution" json:"duplicate-resolution"` + IncrementalImport bool `toml:"incremental-import" json:"incremental-import"` EngineMemCacheSize ByteSize `toml:"engine-mem-cache-size" json:"engine-mem-cache-size"` LocalWriterMemCacheSize ByteSize `toml:"local-writer-mem-cache-size" json:"local-writer-mem-cache-size"` @@ -804,22 +806,22 @@ func (cfg *Config) Adjust(ctx context.Context) error { // Reject problematic CSV configurations. csv := &cfg.Mydumper.CSV if len(csv.Separator) == 0 { - return errors.New("invalid config: `mydumper.csv.separator` must not be empty") + return common.ErrInvalidConfig.GenWithStack("`mydumper.csv.separator` must not be empty") } if len(csv.Delimiter) > 0 && (strings.HasPrefix(csv.Separator, csv.Delimiter) || strings.HasPrefix(csv.Delimiter, csv.Separator)) { - return errors.New("invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other") + return common.ErrInvalidConfig.GenWithStack("`mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other") } if csv.BackslashEscape { if csv.Separator == `\` { - return errors.New("invalid config: cannot use '\\' as CSV separator when `mydumper.csv.backslash-escape` is true") + return common.ErrInvalidConfig.GenWithStack("cannot use '\\' as CSV separator when `mydumper.csv.backslash-escape` is true") } if csv.Delimiter == `\` { - return errors.New("invalid config: cannot use '\\' as CSV delimiter when `mydumper.csv.backslash-escape` is true") + return common.ErrInvalidConfig.GenWithStack("cannot use '\\' as CSV delimiter when `mydumper.csv.backslash-escape` is true") } if csv.Terminator == `\` { - return errors.New("invalid config: cannot use '\\' as CSV terminator when `mydumper.csv.backslash-escape` is true") + return common.ErrInvalidConfig.GenWithStack("cannot use '\\' as CSV terminator when `mydumper.csv.backslash-escape` is true") } } @@ -828,11 +830,13 @@ func (cfg *Config) Adjust(ctx context.Context) error { if filepath.IsAbs(rule.Path) { relPath, err := filepath.Rel(cfg.Mydumper.SourceDir, rule.Path) if err != nil { - return errors.Trace(err) + return common.ErrInvalidConfig.Wrap(err). + GenWithStack("cannot find relative path for file route path %s", rule.Path) } // ".." means that this path is not in source dir, so we should return an error if strings.HasPrefix(relPath, "..") { - return errors.Errorf("file route path '%s' is not in source dir '%s'", rule.Path, cfg.Mydumper.SourceDir) + return common.ErrInvalidConfig.GenWithStack( + "file route path '%s' is not in source dir '%s'", rule.Path, cfg.Mydumper.SourceDir) } rule.Path = relPath } @@ -848,7 +852,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { } charset, err1 := ParseCharset(cfg.Mydumper.DataCharacterSet) if err1 != nil { - return err1 + return common.ErrInvalidConfig.Wrap(err1).GenWithStack("invalid `mydumper.data-character-set`") } if charset == GBK || charset == GB18030 { log.L().Warn( @@ -858,7 +862,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { } if cfg.TikvImporter.Backend == "" { - return errors.New("tikv-importer.backend must not be empty!") + return common.ErrInvalidConfig.GenWithStack("tikv-importer.backend must not be empty!") } cfg.TikvImporter.Backend = strings.ToLower(cfg.TikvImporter.Backend) mustHaveInternalConnections := true @@ -877,7 +881,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { } cfg.DefaultVarsForImporterAndLocalBackend() default: - return errors.Errorf("invalid config: unsupported `tikv-importer.backend` (%s)", cfg.TikvImporter.Backend) + return common.ErrInvalidConfig.GenWithStack("unsupported `tikv-importer.backend` (%s)", cfg.TikvImporter.Backend) } // TODO calculate these from the machine's free memory. @@ -901,14 +905,15 @@ func (cfg *Config) Adjust(ctx context.Context) error { switch cfg.TikvImporter.OnDuplicate { case ReplaceOnDup, IgnoreOnDup, ErrorOnDup: default: - return errors.Errorf("invalid config: unsupported `tikv-importer.on-duplicate` (%s)", cfg.TikvImporter.OnDuplicate) + return common.ErrInvalidConfig.GenWithStack( + "unsupported `tikv-importer.on-duplicate` (%s)", cfg.TikvImporter.OnDuplicate) } } var err error cfg.TiDB.SQLMode, err = mysql.GetSQLMode(cfg.TiDB.StrSQLMode) if err != nil { - return errors.Annotate(err, "invalid config: `mydumper.tidb.sql_mode` must be a valid SQL_MODE") + return common.ErrInvalidConfig.Wrap(err).GenWithStack("`mydumper.tidb.sql_mode` must be a valid SQL_MODE") } if err := cfg.CheckAndAdjustSecurity(); err != nil { @@ -919,7 +924,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { if cfg.HasLegacyBlackWhiteList() { log.L().Warn("the config `black-white-list` has been deprecated, please replace with `mydumper.filter`") if !common.StringSliceEqual(cfg.Mydumper.Filter, DefaultFilter) { - return errors.New("invalid config: `mydumper.filter` and `black-white-list` cannot be simultaneously defined") + return common.ErrInvalidConfig.GenWithStack("`mydumper.filter` and `black-white-list` cannot be simultaneously defined") } } @@ -928,7 +933,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { rule.ToLower() } if err := rule.Valid(); err != nil { - return errors.Trace(err) + return common.ErrInvalidConfig.Wrap(err).GenWithStack("file route rule is invalid") } } @@ -942,7 +947,7 @@ func (cfg *Config) Adjust(ctx context.Context) error { func (cfg *Config) CheckAndAdjustForLocalBackend() error { if len(cfg.TikvImporter.SortedKVDir) == 0 { - return errors.Errorf("tikv-importer.sorted-kv-dir must not be empty!") + return common.ErrInvalidConfig.GenWithStack("tikv-importer.sorted-kv-dir must not be empty!") } storageSizeDir := filepath.Clean(cfg.TikvImporter.SortedKVDir) @@ -950,15 +955,14 @@ func (cfg *Config) CheckAndAdjustForLocalBackend() error { switch { case os.IsNotExist(err): - // the sorted-kv-dir does not exist, meaning we will create it automatically. - // so we extract the storage size from its parent directory. - storageSizeDir = filepath.Dir(storageSizeDir) + return nil case err == nil: if !sortedKVDirInfo.IsDir() { - return errors.Errorf("tikv-importer.sorted-kv-dir ('%s') is not a directory", storageSizeDir) + return common.ErrInvalidConfig. + GenWithStack("tikv-importer.sorted-kv-dir ('%s') is not a directory", storageSizeDir) } default: - return errors.Annotate(err, "invalid tikv-importer.sorted-kv-dir") + return common.ErrInvalidConfig.Wrap(err).GenWithStack("invalid tikv-importer.sorted-kv-dir") } return nil @@ -1009,7 +1013,7 @@ func (cfg *Config) CheckAndAdjustTiDBPort(ctx context.Context, mustHaveInternalC var settings tidbcfg.Config err = tls.GetJSON(ctx, "/settings", &settings) if err != nil { - return errors.Annotate(err, "cannot fetch settings from TiDB, please manually fill in `tidb.port` and `tidb.pd-addr`") + return common.ErrInvalidConfig.Wrap(err).GenWithStack("cannot fetch settings from TiDB, please manually fill in `tidb.port` and `tidb.pd-addr`") } if cfg.TiDB.Port <= 0 { cfg.TiDB.Port = int(settings.Port) @@ -1021,10 +1025,11 @@ func (cfg *Config) CheckAndAdjustTiDBPort(ctx context.Context, mustHaveInternalC } if cfg.TiDB.Port <= 0 { - return errors.New("invalid `tidb.port` setting") + return common.ErrInvalidConfig.GenWithStack("invalid `tidb.port` setting") } + if mustHaveInternalConnections && len(cfg.TiDB.PdAddr) == 0 { - return errors.New("invalid `tidb.pd-addr` setting") + return common.ErrInvalidConfig.GenWithStack("invalid `tidb.pd-addr` setting") } return nil } @@ -1044,7 +1049,7 @@ func (cfg *Config) CheckAndAdjustFilePath() error { var err error u, err = url.Parse(cfg.Mydumper.SourceDir) if err != nil { - return errors.Trace(err) + return common.ErrInvalidConfig.Wrap(err).GenWithStack("cannot parse `mydumper.data-source-dir` %s", cfg.Mydumper.SourceDir) } } else { u = &url.URL{} @@ -1052,16 +1057,19 @@ func (cfg *Config) CheckAndAdjustFilePath() error { // convert path and relative path to a valid file url if u.Scheme == "" { + if cfg.Mydumper.SourceDir == "" { + return common.ErrInvalidConfig.GenWithStack("`mydumper.data-source-dir` is not set") + } if !common.IsDirExists(cfg.Mydumper.SourceDir) { - return errors.Errorf("%s: mydumper dir does not exist", cfg.Mydumper.SourceDir) + return common.ErrInvalidConfig.GenWithStack("'%s': `mydumper.data-source-dir` does not exist", cfg.Mydumper.SourceDir) } absPath, err := filepath.Abs(cfg.Mydumper.SourceDir) if err != nil { - return errors.Annotatef(err, "covert data-source-dir '%s' to absolute path failed", cfg.Mydumper.SourceDir) + return common.ErrInvalidConfig.Wrap(err).GenWithStack("covert data-source-dir '%s' to absolute path failed", cfg.Mydumper.SourceDir) } - cfg.Mydumper.SourceDir = "file://" + filepath.ToSlash(absPath) - u.Path = absPath + u.Path = filepath.ToSlash(absPath) u.Scheme = "file" + cfg.Mydumper.SourceDir = u.String() } found := false @@ -1072,7 +1080,9 @@ func (cfg *Config) CheckAndAdjustFilePath() error { } } if !found { - return errors.Errorf("Unsupported data-source-dir url '%s'", cfg.Mydumper.SourceDir) + return common.ErrInvalidConfig.GenWithStack( + "unsupported data-source-dir url '%s', supported storage types are %s", + cfg.Mydumper.SourceDir, strings.Join(supportedStorageTypes, ",")) } return nil } @@ -1143,12 +1153,12 @@ func (cfg *Config) CheckAndAdjustSecurity() error { } case "cluster": if len(cfg.Security.CAPath) == 0 { - return errors.New("invalid config: cannot set `tidb.tls` to 'cluster' without a [security] section") + return common.ErrInvalidConfig.GenWithStack("cannot set `tidb.tls` to 'cluster' without a [security] section") } case "false", "skip-verify", "preferred": break default: - return errors.Errorf("invalid config: unsupported `tidb.tls` config %s", cfg.TiDB.TLS) + return common.ErrInvalidConfig.GenWithStack("unsupported `tidb.tls` config %s", cfg.TiDB.TLS) } return nil } diff --git a/br/pkg/lightning/config/config_test.go b/br/pkg/lightning/config/config_test.go index 07dd7a922da4e..ce2d910102db4 100644 --- a/br/pkg/lightning/config/config_test.go +++ b/br/pkg/lightning/config/config_test.go @@ -23,38 +23,30 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" "path/filepath" - "regexp" "strconv" "testing" "time" "github.com/BurntSushi/toml" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/parser/mysql" + "github.com/stretchr/testify/require" ) -func Test(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&configTestSuite{}) - -type configTestSuite struct{} - -func startMockServer(c *C, statusCode int, content string) (*httptest.Server, string, int) { +func startMockServer(t *testing.T, statusCode int, content string) (*httptest.Server, string, int) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(statusCode) - fmt.Fprint(w, content) + _, _ = fmt.Fprint(w, content) })) url, err := url.Parse(ts.URL) - c.Assert(err, IsNil) + require.NoError(t, err) host, portString, err := net.SplitHostPort(url.Host) - c.Assert(err, IsNil) + require.NoError(t, err) port, err := strconv.Atoi(portString) - c.Assert(err, IsNil) + require.NoError(t, err) return ts, host, port } @@ -70,8 +62,8 @@ func assignMinimalLegalValue(cfg *config.Config) { cfg.TikvImporter.DiskQuota = 1 } -func (s *configTestSuite) TestAdjustPdAddrAndPort(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, +func TestAdjustPdAddrAndPort(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, `{"port":4444,"advertise-address":"","path":"123.45.67.89:1234,56.78.90.12:3456"}`, ) defer ts.Close() @@ -85,13 +77,13 @@ func (s *configTestSuite) TestAdjustPdAddrAndPort(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.TiDB.Port, Equals, 4444) - c.Assert(cfg.TiDB.PdAddr, Equals, "123.45.67.89:1234") + require.NoError(t, err) + require.Equal(t, 4444, cfg.TiDB.Port) + require.Equal(t, "123.45.67.89:1234", cfg.TiDB.PdAddr) } -func (s *configTestSuite) TestAdjustPdAddrAndPortViaAdvertiseAddr(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, +func TestAdjustPdAddrAndPortViaAdvertiseAddr(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, `{"port":6666,"advertise-address":"121.212.121.212:5555","path":"34.34.34.34:3434"}`, ) defer ts.Close() @@ -105,13 +97,13 @@ func (s *configTestSuite) TestAdjustPdAddrAndPortViaAdvertiseAddr(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.TiDB.Port, Equals, 6666) - c.Assert(cfg.TiDB.PdAddr, Equals, "34.34.34.34:3434") + require.NoError(t, err) + require.Equal(t, 6666, cfg.TiDB.Port) + require.Equal(t, "34.34.34.34:3434", cfg.TiDB.PdAddr) } -func (s *configTestSuite) TestAdjustPageNotFound(c *C) { - ts, host, port := startMockServer(c, http.StatusNotFound, "{}") +func TestAdjustPageNotFound(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusNotFound, "{}") defer ts.Close() cfg := config.NewConfig() @@ -122,11 +114,12 @@ func (s *configTestSuite) TestAdjustPageNotFound(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") + require.Error(t, err) + require.Regexp(t, "cannot fetch settings from TiDB.*", err.Error()) } -func (s *configTestSuite) TestAdjustConnectRefused(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, "{}") +func TestAdjustConnectRefused(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, "{}") cfg := config.NewConfig() cfg.TiDB.Host = host @@ -138,47 +131,88 @@ func (s *configTestSuite) TestAdjustConnectRefused(c *C) { ts.Close() // immediately close to ensure connection refused. err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") + require.Error(t, err) + require.Regexp(t, "cannot fetch settings from TiDB.*", err.Error()) } -func (s *configTestSuite) TestAdjustBackendNotSet(c *C) { +func TestAdjustBackendNotSet(t *testing.T) { cfg := config.NewConfig() cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "tikv-importer.backend must not be empty!") + require.EqualError(t, err, "[Lightning:Config:ErrInvalidConfig]tikv-importer.backend must not be empty!") } -func (s *configTestSuite) TestAdjustInvalidBackend(c *C) { +func TestAdjustInvalidBackend(t *testing.T) { cfg := config.NewConfig() cfg.TikvImporter.Backend = "no_such_backend" cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "invalid config: unsupported `tikv-importer\\.backend` \\(no_such_backend\\)") + require.EqualError(t, err, "[Lightning:Config:ErrInvalidConfig]unsupported `tikv-importer.backend` (no_such_backend)") } -func (s *configTestSuite) TestAdjustFileRoutePath(c *C) { +func TestCheckAndAdjustFilePath(t *testing.T) { + tmpDir := t.TempDir() + // use slashPath in url to be compatible with windows + slashPath := filepath.ToSlash(tmpDir) + pwd, err := os.Getwd() + require.NoError(t, err) + specialDir, err := os.MkdirTemp(tmpDir, "abc??bcd") + require.NoError(t, err) + specialDir1, err := os.MkdirTemp(tmpDir, "abc%3F%3F%3Fbcd") + require.NoError(t, err) + + cfg := config.NewConfig() + + cases := []struct { + test string + expect string + }{ + {tmpDir, tmpDir}, + {".", filepath.ToSlash(pwd)}, + {specialDir, specialDir}, + {specialDir1, specialDir1}, + {"file://" + slashPath, slashPath}, + {"local://" + slashPath, slashPath}, + {"s3://bucket_name", ""}, + {"s3://bucket_name/path/to/dir", "/path/to/dir"}, + {"gcs://bucketname/path/to/dir", "/path/to/dir"}, + {"gs://bucketname/path/to/dir", "/path/to/dir"}, + {"noop:///", "/"}, + } + for _, testCase := range cases { + cfg.Mydumper.SourceDir = testCase.test + err = cfg.CheckAndAdjustFilePath() + require.NoError(t, err) + u, err := url.Parse(cfg.Mydumper.SourceDir) + require.NoError(t, err) + require.Equal(t, testCase.expect, u.Path) + } +} + +func TestAdjustFileRoutePath(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) ctx := context.Background() - tmpDir := c.MkDir() + tmpDir := t.TempDir() cfg.Mydumper.SourceDir = tmpDir invalidPath := filepath.Join(tmpDir, "../test123/1.sql") rule := &config.FileRouteRule{Path: invalidPath, Type: "sql", Schema: "test", Table: "tbl"} cfg.Mydumper.FileRouters = []*config.FileRouteRule{rule} cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(ctx) - c.Assert(err, ErrorMatches, fmt.Sprintf("\\Qfile route path '%s' is not in source dir '%s'\\E", invalidPath, tmpDir)) + require.Error(t, err) + require.Regexp(t, fmt.Sprintf("\\Qfile route path '%s' is not in source dir '%s'\\E", invalidPath, tmpDir), err.Error()) relPath := filepath.FromSlash("test_dir/1.sql") rule.Path = filepath.Join(tmpDir, relPath) err = cfg.Adjust(ctx) - c.Assert(err, IsNil) - c.Assert(cfg.Mydumper.FileRouters[0].Path, Equals, relPath) + require.NoError(t, err) + require.Equal(t, relPath, cfg.Mydumper.FileRouters[0].Path) } -func (s *configTestSuite) TestDecodeError(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, "invalid-string") +func TestDecodeError(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, "invalid-string") defer ts.Close() cfg := config.NewConfig() @@ -189,11 +223,12 @@ func (s *configTestSuite) TestDecodeError(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "cannot fetch settings from TiDB.*") + require.Error(t, err) + require.Regexp(t, "cannot fetch settings from TiDB.*", err.Error()) } -func (s *configTestSuite) TestInvalidSetting(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, `{"port": 0}`) +func TestInvalidSetting(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, `{"port": 0}`) defer ts.Close() cfg := config.NewConfig() @@ -204,11 +239,11 @@ func (s *configTestSuite) TestInvalidSetting(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "invalid `tidb.port` setting") + require.EqualError(t, err, "[Lightning:Config:ErrInvalidConfig]invalid `tidb.port` setting") } -func (s *configTestSuite) TestInvalidPDAddr(c *C) { - ts, host, port := startMockServer(c, http.StatusOK, `{"port": 1234, "path": ",,"}`) +func TestInvalidPDAddr(t *testing.T) { + ts, host, port := startMockServer(t, http.StatusOK, `{"port": 1234, "path": ",,"}`) defer ts.Close() cfg := config.NewConfig() @@ -219,31 +254,31 @@ func (s *configTestSuite) TestInvalidPDAddr(c *C) { cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, ErrorMatches, "invalid `tidb.pd-addr` setting") + require.EqualError(t, err, "[Lightning:Config:ErrInvalidConfig]invalid `tidb.pd-addr` setting") } -func (s *configTestSuite) TestAdjustWillNotContactServerIfEverythingIsDefined(c *C) { +func TestAdjustWillNotContactServerIfEverythingIsDefined(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.TiDB.Port, Equals, 4567) - c.Assert(cfg.TiDB.PdAddr, Equals, "234.56.78.90:12345") + require.NoError(t, err) + require.Equal(t, 4567, cfg.TiDB.Port) + require.Equal(t, "234.56.78.90:12345", cfg.TiDB.PdAddr) } -func (s *configTestSuite) TestAdjustWillBatchImportRatioInvalid(c *C) { +func TestAdjustWillBatchImportRatioInvalid(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.Mydumper.BatchImportRatio = -1 cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.Mydumper.BatchImportRatio, Equals, 0.75) + require.NoError(t, err) + require.Equal(t, 0.75, cfg.Mydumper.BatchImportRatio) } -func (s *configTestSuite) TestAdjustSecuritySection(c *C) { +func TestAdjustSecuritySection(t *testing.T) { testCases := []struct { input string expectedCA string @@ -310,29 +345,29 @@ func (s *configTestSuite) TestAdjustSecuritySection(c *C) { } for _, tc := range testCases { - comment := Commentf("input = %s", tc.input) + comment := fmt.Sprintf("input = %s", tc.input) cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.LoadFromTOML([]byte(tc.input)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) err = cfg.Adjust(context.Background()) - c.Assert(err, IsNil, comment) - c.Assert(cfg.TiDB.Security.CAPath, Equals, tc.expectedCA, comment) - c.Assert(cfg.TiDB.TLS, Equals, tc.expectedTLS, comment) + require.NoError(t, err, comment) + require.Equal(t, tc.expectedCA, cfg.TiDB.Security.CAPath, comment) + require.Equal(t, tc.expectedTLS, cfg.TiDB.TLS, comment) } // test different tls config name cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.Security.CAPath = "/path/to/ca.pem" cfg.Security.TLSConfigName = "tidb-tls" - c.Assert(cfg.Adjust(context.Background()), IsNil) - c.Assert(cfg.TiDB.Security.TLSConfigName, Equals, cfg.TiDB.TLS) + require.NoError(t, cfg.Adjust(context.Background())) + require.Equal(t, cfg.TiDB.TLS, cfg.TiDB.Security.TLSConfigName) } -func (s *configTestSuite) TestInvalidCSV(c *C) { +func TestInvalidCSV(t *testing.T) { testCases := []struct { input string err string @@ -342,7 +377,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { [mydumper.csv] separator = '' `, - err: "invalid config: `mydumper.csv.separator` must not be empty", + err: "[Lightning:Config:ErrInvalidConfig]`mydumper.csv.separator` must not be empty", }, { input: ` @@ -350,7 +385,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { separator = 'hello' delimiter = 'hel' `, - err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", + err: "[Lightning:Config:ErrInvalidConfig]`mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", }, { input: ` @@ -358,7 +393,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { separator = 'hel' delimiter = 'hello' `, - err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", + err: "[Lightning:Config:ErrInvalidConfig]`mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", }, { input: ` @@ -411,7 +446,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { separator = '|' delimiter = '|' `, - err: "invalid config: `mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", + err: "[Lightning:Config:ErrInvalidConfig]`mydumper.csv.separator` and `mydumper.csv.delimiter` must not be prefix of each other", }, { input: ` @@ -419,7 +454,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { separator = '\' backslash-escape = true `, - err: "invalid config: cannot use '\\' as CSV separator when `mydumper.csv.backslash-escape` is true", + err: "[Lightning:Config:ErrInvalidConfig]cannot use '\\' as CSV separator when `mydumper.csv.backslash-escape` is true", }, { input: ` @@ -427,14 +462,14 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { delimiter = '\' backslash-escape = true `, - err: "invalid config: cannot use '\\' as CSV delimiter when `mydumper.csv.backslash-escape` is true", + err: "[Lightning:Config:ErrInvalidConfig]cannot use '\\' as CSV delimiter when `mydumper.csv.backslash-escape` is true", }, { input: ` [tidb] sql-mode = "invalid-sql-mode" `, - err: "invalid config: `mydumper.tidb.sql_mode` must be a valid SQL_MODE: ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'invalid-sql-mode'", + err: "[Lightning:Config:ErrInvalidConfig]`mydumper.tidb.sql_mode` must be a valid SQL_MODE: ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'invalid-sql-mode'", }, { input: ` @@ -442,7 +477,7 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { schema-pattern = "" table-pattern = "shard_table_*" `, - err: "schema pattern of table route rule should not be empty", + err: "[Lightning:Config:ErrInvalidConfig]file route rule is invalid: schema pattern of table route rule should not be empty", }, { input: ` @@ -450,13 +485,12 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { schema-pattern = "schema_*" table-pattern = "" `, - err: "target schema of table route rule should not be empty", + err: "[Lightning:Config:ErrInvalidConfig]file route rule is invalid: target schema of table route rule should not be empty", }, } for _, tc := range testCases { - comment := Commentf("input = %s", tc.input) - + comment := fmt.Sprintf("input = %s", tc.input) cfg := config.NewConfig() cfg.Mydumper.SourceDir = "file://." cfg.TiDB.Port = 4000 @@ -465,85 +499,87 @@ func (s *configTestSuite) TestInvalidCSV(c *C) { cfg.TikvImporter.SortedKVDir = "." cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.LoadFromTOML([]byte(tc.input)) - c.Assert(err, IsNil) + require.NoError(t, err) err = cfg.Adjust(context.Background()) if tc.err != "" { - c.Assert(err, ErrorMatches, regexp.QuoteMeta(tc.err), comment) + require.EqualError(t, err, tc.err, comment) } else { - c.Assert(err, IsNil, comment) + require.NoError(t, err) } } } -func (s *configTestSuite) TestInvalidTOML(c *C) { +func TestInvalidTOML(t *testing.T) { cfg := &config.Config{} err := cfg.LoadFromTOML([]byte(` invalid[mydumper.csv] delimiter = '\' backslash-escape = true `)) - c.Assert(err, ErrorMatches, regexp.QuoteMeta("Near line 0 (last key parsed ''): bare keys cannot contain '['")) + require.EqualError(t, err, "Near line 0 (last key parsed ''): bare keys cannot contain '['") } -func (s *configTestSuite) TestTOMLUnusedKeys(c *C) { +func TestTOMLUnusedKeys(t *testing.T) { cfg := &config.Config{} err := cfg.LoadFromTOML([]byte(` [lightning] typo = 123 `)) - c.Assert(err, ErrorMatches, regexp.QuoteMeta("config file contained unknown configuration options: lightning.typo")) + require.EqualError(t, err, "config file contained unknown configuration options: lightning.typo") } -func (s *configTestSuite) TestDurationUnmarshal(c *C) { +func TestDurationUnmarshal(t *testing.T) { duration := config.Duration{} err := duration.UnmarshalText([]byte("13m20s")) - c.Assert(err, IsNil) - c.Assert(duration.Duration.Seconds(), Equals, 13*60+20.0) + require.NoError(t, err) + require.Equal(t, 13*60+20.0, duration.Duration.Seconds()) err = duration.UnmarshalText([]byte("13x20s")) - c.Assert(err, ErrorMatches, "time: unknown unit .?x.? in duration .?13x20s.?") + require.Error(t, err) + require.Regexp(t, "time: unknown unit .?x.? in duration .?13x20s.?", err.Error()) } -func (s *configTestSuite) TestDurationMarshalJSON(c *C) { +func TestDurationMarshalJSON(t *testing.T) { duration := config.Duration{} err := duration.UnmarshalText([]byte("13m20s")) - c.Assert(err, IsNil) - c.Assert(duration.Duration.Seconds(), Equals, 13*60+20.0) + require.NoError(t, err) + require.Equal(t, 13*60+20.0, duration.Duration.Seconds()) result, err := duration.MarshalJSON() - c.Assert(err, IsNil) - c.Assert(string(result), Equals, `"13m20s"`) + require.NoError(t, err) + require.Equal(t, `"13m20s"`, string(result)) } -func (s *configTestSuite) TestDuplicateResolutionAlgorithm(c *C) { +func TestDuplicateResolutionAlgorithm(t *testing.T) { var dra config.DuplicateResolutionAlgorithm - dra.FromStringValue("record") - c.Assert(dra, Equals, config.DupeResAlgRecord) - dra.FromStringValue("none") - c.Assert(dra, Equals, config.DupeResAlgNone) - dra.FromStringValue("remove") - c.Assert(dra, Equals, config.DupeResAlgRemove) + require.NoError(t, dra.FromStringValue("record")) + require.Equal(t, config.DupeResAlgRecord, dra) + require.NoError(t, dra.FromStringValue("none")) + require.Equal(t, config.DupeResAlgNone, dra) + require.NoError(t, dra.FromStringValue("remove")) + require.Equal(t, config.DupeResAlgRemove, dra) - c.Assert(config.DupeResAlgRecord.String(), Equals, "record") - c.Assert(config.DupeResAlgNone.String(), Equals, "none") - c.Assert(config.DupeResAlgRemove.String(), Equals, "remove") + require.Equal(t, "record", config.DupeResAlgRecord.String()) + require.Equal(t, "none", config.DupeResAlgNone.String()) + require.Equal(t, "remove", config.DupeResAlgRemove.String()) } -func (s *configTestSuite) TestLoadConfig(c *C) { +func TestLoadConfig(t *testing.T) { cfg, err := config.LoadGlobalConfig([]string{"-tidb-port", "sss"}, nil) - c.Assert(err, ErrorMatches, `invalid value "sss" for flag -tidb-port: parse error`) - c.Assert(cfg, IsNil) + require.EqualError(t, err, `[Lightning:Common:ErrInvalidArgument]invalid argument: invalid value "sss" for flag -tidb-port: parse error`) + require.Nil(t, cfg) cfg, err = config.LoadGlobalConfig([]string{"-V"}, nil) - c.Assert(err, Equals, flag.ErrHelp) - c.Assert(cfg, IsNil) + require.Equal(t, flag.ErrHelp, err) + require.Nil(t, cfg) cfg, err = config.LoadGlobalConfig([]string{"-config", "not-exists"}, nil) - c.Assert(err, ErrorMatches, ".*(no such file or directory|The system cannot find the file specified).*") - c.Assert(cfg, IsNil) + require.Error(t, err) + require.Regexp(t, ".*(no such file or directory|The system cannot find the file specified).*", err.Error()) + require.Nil(t, cfg) cfg, err = config.LoadGlobalConfig([]string{"--server-mode"}, nil) - c.Assert(err, ErrorMatches, "If server-mode is enabled, the status-addr must be a valid listen address") - c.Assert(cfg, IsNil) + require.EqualError(t, err, "[Lightning:Config:ErrInvalidConfig]If server-mode is enabled, the status-addr must be a valid listen address") + require.Nil(t, cfg) path, _ := filepath.Abs(".") cfg, err = config.LoadGlobalConfig([]string{ @@ -559,67 +595,67 @@ func (s *configTestSuite) TestLoadConfig(c *C) { "-sorted-kv-dir", ".", "-checksum=false", }, nil) - c.Assert(err, IsNil) - c.Assert(cfg.App.Config.Level, Equals, "debug") - c.Assert(cfg.App.Config.File, Equals, "/path/to/file.log") - c.Assert(cfg.TiDB.Host, Equals, "172.16.30.11") - c.Assert(cfg.TiDB.Port, Equals, 4001) - c.Assert(cfg.TiDB.User, Equals, "guest") - c.Assert(cfg.TiDB.Psw, Equals, "12345") - c.Assert(cfg.TiDB.PdAddr, Equals, "172.16.30.11:2379,172.16.30.12:2379") - c.Assert(cfg.Mydumper.SourceDir, Equals, path) - c.Assert(cfg.TikvImporter.Backend, Equals, config.BackendLocal) - c.Assert(cfg.TikvImporter.SortedKVDir, Equals, ".") - c.Assert(cfg.PostRestore.Checksum, Equals, config.OpLevelOff) - c.Assert(cfg.PostRestore.Analyze, Equals, config.OpLevelOptional) + require.NoError(t, err) + require.Equal(t, "debug", cfg.App.Config.Level) + require.Equal(t, "/path/to/file.log", cfg.App.Config.File) + require.Equal(t, "172.16.30.11", cfg.TiDB.Host) + require.Equal(t, 4001, cfg.TiDB.Port) + require.Equal(t, "guest", cfg.TiDB.User) + require.Equal(t, "12345", cfg.TiDB.Psw) + require.Equal(t, "172.16.30.11:2379,172.16.30.12:2379", cfg.TiDB.PdAddr) + require.Equal(t, path, cfg.Mydumper.SourceDir) + require.Equal(t, config.BackendLocal, cfg.TikvImporter.Backend) + require.Equal(t, ".", cfg.TikvImporter.SortedKVDir) + require.Equal(t, config.OpLevelOff, cfg.PostRestore.Checksum) + require.Equal(t, config.OpLevelOptional, cfg.PostRestore.Analyze) taskCfg := config.NewConfig() err = taskCfg.LoadFromGlobal(cfg) - c.Assert(err, IsNil) - c.Assert(taskCfg.PostRestore.Checksum, Equals, config.OpLevelOff) - c.Assert(taskCfg.PostRestore.Analyze, Equals, config.OpLevelOptional) + require.NoError(t, err) + require.Equal(t, config.OpLevelOff, taskCfg.PostRestore.Checksum) + require.Equal(t, config.OpLevelOptional, taskCfg.PostRestore.Analyze) taskCfg.Checkpoint.DSN = "" taskCfg.Checkpoint.Driver = config.CheckpointDriverMySQL taskCfg.TiDB.DistSQLScanConcurrency = 1 err = taskCfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(taskCfg.Checkpoint.DSN, Equals, "guest:12345@tcp(172.16.30.11:4001)/?charset=utf8mb4&sql_mode='"+mysql.DefaultSQLMode+"'&maxAllowedPacket=67108864&tls=false") + require.NoError(t, err) + require.Equal(t, "guest:12345@tcp(172.16.30.11:4001)/?charset=utf8mb4&sql_mode='"+mysql.DefaultSQLMode+"'&maxAllowedPacket=67108864&tls=false", taskCfg.Checkpoint.DSN) result := taskCfg.String() - c.Assert(result, Matches, `.*"pd-addr":"172.16.30.11:2379,172.16.30.12:2379".*`) + require.Regexp(t, `.*"pd-addr":"172.16.30.11:2379,172.16.30.12:2379".*`, result) cfg, err = config.LoadGlobalConfig([]string{}, nil) - c.Assert(err, IsNil) - c.Assert(cfg.App.Config.File, Matches, ".*lightning.log.*") + require.NoError(t, err) + require.Regexp(t, ".*lightning.log.*", cfg.App.Config.File) cfg, err = config.LoadGlobalConfig([]string{"--log-file", "-"}, nil) - c.Assert(err, IsNil) - c.Assert(cfg.App.Config.File, Equals, "-") + require.NoError(t, err) + require.Equal(t, "-", cfg.App.Config.File) } -func (s *configTestSuite) TestDefaultImporterBackendValue(c *C) { +func TestDefaultImporterBackendValue(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.TikvImporter.Backend = "importer" cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.App.IndexConcurrency, Equals, 2) - c.Assert(cfg.App.TableConcurrency, Equals, 6) + require.NoError(t, err) + require.Equal(t, 2, cfg.App.IndexConcurrency) + require.Equal(t, 6, cfg.App.TableConcurrency) } -func (s *configTestSuite) TestDefaultTidbBackendValue(c *C) { +func TestDefaultTidbBackendValue(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.TikvImporter.Backend = "tidb" cfg.App.RegionConcurrency = 123 cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.App.TableConcurrency, Equals, 123) + require.NoError(t, err) + require.Equal(t, 123, cfg.App.TableConcurrency) } -func (s *configTestSuite) TestDefaultCouldBeOverwritten(c *C) { +func TestDefaultCouldBeOverwritten(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) cfg.TikvImporter.Backend = "importer" @@ -627,32 +663,33 @@ func (s *configTestSuite) TestDefaultCouldBeOverwritten(c *C) { cfg.App.TableConcurrency = 60 cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.Adjust(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg.App.IndexConcurrency, Equals, 20) - c.Assert(cfg.App.TableConcurrency, Equals, 60) + require.NoError(t, err) + require.Equal(t, 20, cfg.App.IndexConcurrency) + require.Equal(t, 60, cfg.App.TableConcurrency) } -func (s *configTestSuite) TestLoadFromInvalidConfig(c *C) { +func TestLoadFromInvalidConfig(t *testing.T) { taskCfg := config.NewConfig() err := taskCfg.LoadFromGlobal(&config.GlobalConfig{ ConfigFileContent: []byte("invalid toml"), }) - c.Assert(err, ErrorMatches, "Near line 1.*") + require.Error(t, err) + require.Regexp(t, "Near line 1.*", err.Error()) } -func (s *configTestSuite) TestTomlPostRestore(c *C) { +func TestTomlPostRestore(t *testing.T) { cfg := &config.Config{} err := cfg.LoadFromTOML([]byte(` [post-restore] checksum = "req" `)) - c.Assert(err, ErrorMatches, regexp.QuoteMeta("invalid op level 'req', please choose valid option between ['off', 'optional', 'required']")) + require.EqualError(t, err, "invalid op level 'req', please choose valid option between ['off', 'optional', 'required']") err = cfg.LoadFromTOML([]byte(` [post-restore] analyze = 123 `)) - c.Assert(err, ErrorMatches, regexp.QuoteMeta("invalid op level '123', please choose valid option between ['off', 'optional', 'required']")) + require.EqualError(t, err, "invalid op level '123', please choose valid option between ['off', 'optional', 'required']") kvMap := map[string]config.PostOpLevel{ `"off"`: config.OpLevelOff, @@ -669,77 +706,77 @@ func (s *configTestSuite) TestTomlPostRestore(c *C) { cfg := &config.Config{} confStr := fmt.Sprintf("[post-restore]\r\nchecksum= %s\r\n", k) err := cfg.LoadFromTOML([]byte(confStr)) - c.Assert(err, IsNil) - c.Assert(cfg.PostRestore.Checksum, Equals, v) + require.NoError(t, err) + require.Equal(t, v, cfg.PostRestore.Checksum) b.Reset() - c.Assert(enc.Encode(cfg.PostRestore), IsNil) - c.Assert(&b, Matches, fmt.Sprintf(`(?s).*checksum = "\Q%s\E".*`, v)) + require.NoError(t, enc.Encode(cfg.PostRestore)) + require.Regexp(t, fmt.Sprintf(`(?s).*checksum = "\Q%s\E".*`, v), &b) } for k, v := range kvMap { cfg := &config.Config{} confStr := fmt.Sprintf("[post-restore]\r\nanalyze= %s\r\n", k) err := cfg.LoadFromTOML([]byte(confStr)) - c.Assert(err, IsNil) - c.Assert(cfg.PostRestore.Analyze, Equals, v) + require.NoError(t, err) + require.Equal(t, v, cfg.PostRestore.Analyze) b.Reset() - c.Assert(enc.Encode(cfg.PostRestore), IsNil) - c.Assert(&b, Matches, fmt.Sprintf(`(?s).*analyze = "\Q%s\E".*`, v)) + require.NoError(t, enc.Encode(cfg.PostRestore)) + require.Regexp(t, fmt.Sprintf(`(?s).*analyze = "\Q%s\E".*`, v), &b) } } -func (s *configTestSuite) TestCronEncodeDecode(c *C) { +func TestCronEncodeDecode(t *testing.T) { cfg := &config.Config{} cfg.Cron.SwitchMode.Duration = 1 * time.Minute cfg.Cron.LogProgress.Duration = 2 * time.Minute cfg.Cron.CheckDiskQuota.Duration = 3 * time.Second var b bytes.Buffer - c.Assert(toml.NewEncoder(&b).Encode(cfg.Cron), IsNil) - c.Assert(b.String(), Equals, "switch-mode = \"1m0s\"\nlog-progress = \"2m0s\"\ncheck-disk-quota = \"3s\"\n") + require.NoError(t, toml.NewEncoder(&b).Encode(cfg.Cron)) + require.Equal(t, "switch-mode = \"1m0s\"\nlog-progress = \"2m0s\"\ncheck-disk-quota = \"3s\"\n", b.String()) confStr := "[cron]\r\n" + b.String() cfg2 := &config.Config{} - c.Assert(cfg2.LoadFromTOML([]byte(confStr)), IsNil) - c.Assert(cfg2.Cron, DeepEquals, cfg.Cron) + require.NoError(t, cfg2.LoadFromTOML([]byte(confStr))) + require.Equal(t, cfg.Cron, cfg2.Cron) } -func (s *configTestSuite) TestAdjustWithLegacyBlackWhiteList(c *C) { +func TestAdjustWithLegacyBlackWhiteList(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) - c.Assert(cfg.Mydumper.Filter, DeepEquals, config.DefaultFilter) - c.Assert(cfg.HasLegacyBlackWhiteList(), IsFalse) + require.Equal(t, config.DefaultFilter, cfg.Mydumper.Filter) + require.False(t, cfg.HasLegacyBlackWhiteList()) ctx := context.Background() cfg.Mydumper.Filter = []string{"test.*"} cfg.TiDB.DistSQLScanConcurrency = 1 - c.Assert(cfg.Adjust(ctx), IsNil) - c.Assert(cfg.HasLegacyBlackWhiteList(), IsFalse) + require.NoError(t, cfg.Adjust(ctx)) + require.False(t, cfg.HasLegacyBlackWhiteList()) cfg.BWList.DoDBs = []string{"test"} - c.Assert(cfg.Adjust(ctx), ErrorMatches, "invalid config: `mydumper\\.filter` and `black-white-list` cannot be simultaneously defined") + require.EqualError(t, cfg.Adjust(ctx), "[Lightning:Config:ErrInvalidConfig]`mydumper.filter` and `black-white-list` cannot be simultaneously defined") cfg.Mydumper.Filter = config.DefaultFilter - c.Assert(cfg.Adjust(ctx), IsNil) - c.Assert(cfg.HasLegacyBlackWhiteList(), IsTrue) + require.NoError(t, cfg.Adjust(ctx)) + require.True(t, cfg.HasLegacyBlackWhiteList()) } -func (s *configTestSuite) TestAdjustDiskQuota(c *C) { +func TestAdjustDiskQuota(t *testing.T) { cfg := config.NewConfig() assignMinimalLegalValue(cfg) - base := c.MkDir() + base := t.TempDir() ctx := context.Background() cfg.TikvImporter.Backend = config.BackendLocal cfg.TikvImporter.DiskQuota = 0 cfg.TikvImporter.SortedKVDir = base cfg.TiDB.DistSQLScanConcurrency = 1 - c.Assert(cfg.Adjust(ctx), IsNil) - c.Assert(int64(cfg.TikvImporter.DiskQuota), Equals, int64(0)) + require.NoError(t, cfg.Adjust(ctx)) + require.Equal(t, int64(0), int64(cfg.TikvImporter.DiskQuota)) } -func (s *configTestSuite) TestDataCharacterSet(c *C) { +func TestDataCharacterSet(t *testing.T) { testCases := []struct { input string err string @@ -803,8 +840,7 @@ func (s *configTestSuite) TestDataCharacterSet(c *C) { } for _, tc := range testCases { - comment := Commentf("input = %s", tc.input) - + comment := fmt.Sprintf("input = %s", tc.input) cfg := config.NewConfig() cfg.Mydumper.SourceDir = "file://." cfg.TiDB.Port = 4000 @@ -813,17 +849,17 @@ func (s *configTestSuite) TestDataCharacterSet(c *C) { cfg.TikvImporter.SortedKVDir = "." cfg.TiDB.DistSQLScanConcurrency = 1 err := cfg.LoadFromTOML([]byte(tc.input)) - c.Assert(err, IsNil) + require.NoError(t, err) err = cfg.Adjust(context.Background()) if tc.err != "" { - c.Assert(err, ErrorMatches, regexp.QuoteMeta(tc.err), comment) + require.EqualError(t, err, tc.err, comment) } else { - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) } } } -func (s *configTestSuite) TestCheckpointKeepStrategy(c *C) { +func TestCheckpointKeepStrategy(t *testing.T) { tomlCases := map[interface{}]config.CheckpointKeepStrategy{ true: config.CheckpointRename, false: config.CheckpointRemove, @@ -834,15 +870,15 @@ func (s *configTestSuite) TestCheckpointKeepStrategy(c *C) { var cp config.CheckpointKeepStrategy for key, strategy := range tomlCases { err := cp.UnmarshalTOML(key) - c.Assert(err, IsNil) - c.Assert(cp, Equals, strategy) + require.NoError(t, err) + require.Equal(t, strategy, cp) } defaultCp := "enable = true\r\n" cpCfg := &config.Checkpoint{} _, err := toml.Decode(defaultCp, cpCfg) - c.Assert(err, IsNil) - c.Assert(cpCfg.KeepAfterSuccess, Equals, config.CheckpointRemove) + require.NoError(t, err) + require.Equal(t, config.CheckpointRemove, cpCfg.KeepAfterSuccess) cpFmt := "keep-after-success = %v\r\n" for key, strategy := range tomlCases { @@ -853,8 +889,8 @@ func (s *configTestSuite) TestCheckpointKeepStrategy(c *C) { tomlStr := fmt.Sprintf(cpFmt, cpValue) cpCfg := &config.Checkpoint{} _, err := toml.Decode(tomlStr, cpCfg) - c.Assert(err, IsNil) - c.Assert(cpCfg.KeepAfterSuccess, Equals, strategy) + require.NoError(t, err) + require.Equal(t, strategy, cpCfg.KeepAfterSuccess) } marshalTextCases := map[config.CheckpointKeepStrategy]string{ @@ -864,12 +900,12 @@ func (s *configTestSuite) TestCheckpointKeepStrategy(c *C) { } for strategy, value := range marshalTextCases { res, err := strategy.MarshalText() - c.Assert(err, IsNil) - c.Assert(res, DeepEquals, []byte(value)) + require.NoError(t, err) + require.Equal(t, []byte(value), res) } } -func (s configTestSuite) TestLoadCharsetFromConfig(c *C) { +func TestLoadCharsetFromConfig(t *testing.T) { cases := map[string]config.Charset{ "binary": config.Binary, "BINARY": config.Binary, @@ -881,10 +917,36 @@ func (s configTestSuite) TestLoadCharsetFromConfig(c *C) { } for k, v := range cases { charset, err := config.ParseCharset(k) - c.Assert(err, IsNil) - c.Assert(charset, Equals, v) + require.NoError(t, err) + require.Equal(t, v, charset) } _, err := config.ParseCharset("Unknown") - c.Assert(err, ErrorMatches, "found unsupported data-character-set: Unknown") + require.EqualError(t, err, "found unsupported data-character-set: Unknown") +} + +func TestCheckAndAdjustForLocalBackend(t *testing.T) { + cfg := config.NewConfig() + assignMinimalLegalValue(cfg) + + cfg.TikvImporter.Backend = config.BackendLocal + cfg.TikvImporter.SortedKVDir = "" + require.EqualError(t, cfg.CheckAndAdjustForLocalBackend(), "[Lightning:Config:ErrInvalidConfig]tikv-importer.sorted-kv-dir must not be empty!") + + // non exists dir is legal + cfg.TikvImporter.SortedKVDir = "./not-exists" + require.NoError(t, cfg.CheckAndAdjustForLocalBackend()) + + base := t.TempDir() + // create empty file + file := filepath.Join(base, "file") + require.NoError(t, os.WriteFile(file, []byte(""), 0644)) + cfg.TikvImporter.SortedKVDir = file + err := cfg.CheckAndAdjustForLocalBackend() + require.Error(t, err) + require.Regexp(t, "tikv-importer.sorted-kv-dir (.*) is not a directory", err.Error()) + + // legal dir + cfg.TikvImporter.SortedKVDir = base + require.NoError(t, cfg.CheckAndAdjustForLocalBackend()) } diff --git a/br/pkg/lightning/config/configlist_test.go b/br/pkg/lightning/config/configlist_test.go index 48deed74817ab..c5b3e449b2759 100644 --- a/br/pkg/lightning/config/configlist_test.go +++ b/br/pkg/lightning/config/configlist_test.go @@ -16,17 +16,14 @@ package config_test import ( "context" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/stretchr/testify/require" ) -var _ = Suite(&configListTestSuite{}) - -type configListTestSuite struct{} - -func (s *configListTestSuite) TestNormalPushPop(c *C) { +func TestNormalPushPop(t *testing.T) { cl := config.NewConfigList() cl.Push(&config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}}) @@ -34,15 +31,15 @@ func (s *configListTestSuite) TestNormalPushPop(c *C) { startTime := time.Now() cfg, err := cl.Pop(context.Background()) // these two should never block. - c.Assert(time.Since(startTime), Less, 100*time.Millisecond) - c.Assert(err, IsNil) - c.Assert(cfg.TikvImporter.Addr, Equals, "1.1.1.1:1111") + require.Less(t, time.Since(startTime), 100*time.Millisecond) + require.NoError(t, err) + require.Equal(t, "1.1.1.1:1111", cfg.TikvImporter.Addr) startTime = time.Now() cfg, err = cl.Pop(context.Background()) - c.Assert(time.Since(startTime), Less, 100*time.Millisecond) - c.Assert(err, IsNil) - c.Assert(cfg.TikvImporter.Addr, Equals, "2.2.2.2:2222") + require.Less(t, time.Since(startTime), 100*time.Millisecond) + require.NoError(t, err) + require.Equal(t, "2.2.2.2:2222", cfg.TikvImporter.Addr) startTime = time.Now() @@ -52,12 +49,12 @@ func (s *configListTestSuite) TestNormalPushPop(c *C) { }() cfg, err = cl.Pop(context.Background()) // this should block for ≥400ms - c.Assert(time.Since(startTime), GreaterEqual, 400*time.Millisecond) - c.Assert(err, IsNil) - c.Assert(cfg.TikvImporter.Addr, Equals, "3.3.3.3:3333") + require.GreaterOrEqual(t, time.Since(startTime), 400*time.Millisecond) + require.NoError(t, err) + require.Equal(t, "3.3.3.3:3333", cfg.TikvImporter.Addr) } -func (s *configListTestSuite) TestContextCancel(c *C) { +func TestContextCancel(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cl := config.NewConfigList() @@ -68,11 +65,11 @@ func (s *configListTestSuite) TestContextCancel(c *C) { startTime := time.Now() _, err := cl.Pop(ctx) - c.Assert(time.Since(startTime), GreaterEqual, 400*time.Millisecond) - c.Assert(err, Equals, context.Canceled) + require.GreaterOrEqual(t, time.Since(startTime), 400*time.Millisecond) + require.Equal(t, context.Canceled, err) } -func (s *configListTestSuite) TestGetRemove(c *C) { +func TestGetRemove(t *testing.T) { cl := config.NewConfigList() cfg1 := &config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}} @@ -83,29 +80,29 @@ func (s *configListTestSuite) TestGetRemove(c *C) { cl.Push(cfg3) cfg, ok := cl.Get(cfg2.TaskID) - c.Assert(ok, IsTrue) - c.Assert(cfg, Equals, cfg2) + require.True(t, ok) + require.Equal(t, cfg2, cfg) _, ok = cl.Get(cfg3.TaskID + 1000) - c.Assert(ok, IsFalse) + require.False(t, ok) ok = cl.Remove(cfg2.TaskID) - c.Assert(ok, IsTrue) + require.True(t, ok) ok = cl.Remove(cfg3.TaskID + 1000) - c.Assert(ok, IsFalse) + require.False(t, ok) _, ok = cl.Get(cfg2.TaskID) - c.Assert(ok, IsFalse) + require.False(t, ok) var err error cfg, err = cl.Pop(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg, Equals, cfg1) + require.NoError(t, err) + require.Equal(t, cfg1, cfg) cfg, err = cl.Pop(context.Background()) - c.Assert(err, IsNil) - c.Assert(cfg, Equals, cfg3) + require.NoError(t, err) + require.Equal(t, cfg3, cfg) } -func (s *configListTestSuite) TestMoveFrontBack(c *C) { +func TestMoveFrontBack(t *testing.T) { cl := config.NewConfigList() cfg1 := &config.Config{TikvImporter: config.TikvImporter{Addr: "1.1.1.1:1111"}} @@ -115,19 +112,19 @@ func (s *configListTestSuite) TestMoveFrontBack(c *C) { cfg3 := &config.Config{TikvImporter: config.TikvImporter{Addr: "3.3.3.3:3333"}} cl.Push(cfg3) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg1.TaskID, cfg2.TaskID, cfg3.TaskID}) - - c.Assert(cl.MoveToFront(cfg2.TaskID), IsTrue) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}) - c.Assert(cl.MoveToFront(cfg2.TaskID), IsTrue) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}) - c.Assert(cl.MoveToFront(123456), IsFalse) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}) - - c.Assert(cl.MoveToBack(cfg2.TaskID), IsTrue) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}) - c.Assert(cl.MoveToBack(cfg2.TaskID), IsTrue) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}) - c.Assert(cl.MoveToBack(123456), IsFalse) - c.Assert(cl.AllIDs(), DeepEquals, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}) + require.Equal(t, []int64{cfg1.TaskID, cfg2.TaskID, cfg3.TaskID}, cl.AllIDs()) + + require.True(t, cl.MoveToFront(cfg2.TaskID)) + require.Equal(t, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}, cl.AllIDs()) + require.True(t, cl.MoveToFront(cfg2.TaskID)) + require.Equal(t, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}, cl.AllIDs()) + require.False(t, cl.MoveToFront(123456)) + require.Equal(t, []int64{cfg2.TaskID, cfg1.TaskID, cfg3.TaskID}, cl.AllIDs()) + + require.True(t, cl.MoveToBack(cfg2.TaskID)) + require.Equal(t, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}, cl.AllIDs()) + require.True(t, cl.MoveToBack(cfg2.TaskID)) + require.Equal(t, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}, cl.AllIDs()) + require.False(t, cl.MoveToBack(123456)) + require.Equal(t, []int64{cfg1.TaskID, cfg3.TaskID, cfg2.TaskID}, cl.AllIDs()) } diff --git a/br/pkg/lightning/config/global.go b/br/pkg/lightning/config/global.go index d9bd80ef4139a..5bba95ae3d4d4 100644 --- a/br/pkg/lightning/config/global.go +++ b/br/pkg/lightning/config/global.go @@ -24,6 +24,7 @@ import ( "github.com/BurntSushi/toml" "github.com/carlmjohnson/flagext" "github.com/pingcap/errors" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/version/build" ) @@ -120,7 +121,7 @@ func Must(cfg *GlobalConfig, err error) *GlobalConfig { case flag.ErrHelp: os.Exit(0) default: - fmt.Println("Failed to parse command flags: ", err) + fmt.Println(err) os.Exit(2) } return cfg @@ -176,7 +177,7 @@ func LoadGlobalConfig(args []string, extraFlags func(*flag.FlagSet)) (*GlobalCon } if err := fs.Parse(args); err != nil { - return nil, errors.Trace(err) + return nil, common.ErrInvalidArgument.Wrap(err).GenWithStackByArgs() } if *printVersion { fmt.Println(build.Info()) @@ -186,10 +187,10 @@ func LoadGlobalConfig(args []string, extraFlags func(*flag.FlagSet)) (*GlobalCon if len(configFilePath) > 0 { data, err := os.ReadFile(configFilePath) if err != nil { - return nil, errors.Annotatef(err, "Cannot read config file `%s`", configFilePath) + return nil, common.ErrReadConfigFile.Wrap(err).GenWithStackByArgs(configFilePath) } if err = toml.Unmarshal(data, cfg); err != nil { - return nil, errors.Annotatef(err, "Cannot parse config file `%s`", configFilePath) + return nil, common.ErrParseConfigFile.Wrap(err).GenWithStackByArgs(configFilePath) } cfg.ConfigFileContent = data } @@ -274,7 +275,7 @@ func LoadGlobalConfig(args []string, extraFlags func(*flag.FlagSet)) (*GlobalCon } if cfg.App.StatusAddr == "" && cfg.App.ServerMode { - return nil, errors.New("If server-mode is enabled, the status-addr must be a valid listen address") + return nil, common.ErrInvalidConfig.GenWithStack("If server-mode is enabled, the status-addr must be a valid listen address") } cfg.App.Config.Adjust() diff --git a/br/pkg/lightning/errormanager/errormanager.go b/br/pkg/lightning/errormanager/errormanager.go index 4d1e7c0fedf60..965191373688e 100644 --- a/br/pkg/lightning/errormanager/errormanager.go +++ b/br/pkg/lightning/errormanager/errormanager.go @@ -18,15 +18,22 @@ import ( "context" "database/sql" "fmt" + "math" "strings" + "sync" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/jedib0t/go-pretty/v6/text" "github.com/pingcap/errors" + "go.uber.org/multierr" + "go.uber.org/zap" + "golang.org/x/sync/errgroup" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/redact" - "go.uber.org/multierr" - "go.uber.org/zap" + "github.com/pingcap/tidb/br/pkg/utils" ) const ( @@ -87,19 +94,23 @@ const ( insertIntoConflictErrorData = ` INSERT INTO %s.` + conflictErrorTableName + ` (task_id, table_name, index_name, key_data, row_data, raw_key, raw_value, raw_handle, raw_row) - VALUES (?, ?, 'PRIMARY', ?, ?, ?, ?, raw_key, raw_value); + VALUES ` + sqlValuesConflictErrorData = "(?,?,'PRIMARY',?,?,?,?,raw_key,raw_value)" + insertIntoConflictErrorIndex = ` INSERT INTO %s.` + conflictErrorTableName + ` (task_id, table_name, index_name, key_data, row_data, raw_key, raw_value, raw_handle, raw_row) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?); + VALUES ` + sqlValuesConflictErrorIndex = "(?,?,?,?,?,?,?,?,?)" + selectConflictKeys = ` SELECT _tidb_rowid, raw_handle, raw_row FROM %s.` + conflictErrorTableName + ` - WHERE table_name = ? AND _tidb_rowid > ? + WHERE table_name = ? AND _tidb_rowid >= ? and _tidb_rowid < ? ORDER BY _tidb_rowid LIMIT ?; ` ) @@ -108,6 +119,7 @@ type ErrorManager struct { db *sql.DB taskID int64 schemaEscaped string + configError *config.MaxError remainingError config.MaxError dupResolution config.DuplicateResolutionAlgorithm } @@ -120,6 +132,7 @@ func (em *ErrorManager) TypeErrorsRemain() int64 { func New(db *sql.DB, cfg *config.Config) *ErrorManager { em := &ErrorManager{ taskID: cfg.TaskID, + configError: &cfg.App.MaxError, remainingError: cfg.App.MaxError, dupResolution: cfg.TikvImporter.DuplicateResolution, } @@ -177,6 +190,11 @@ func (em *ErrorManager) RecordTypeError( ) error { // elide the encode error if needed. if em.remainingError.Type.Dec() < 0 { + threshold := em.configError.Type.Load() + if threshold > 0 { + encodeErr = errors.Annotatef(encodeErr, "meet errors exceed the max-error.type threshold '%d'", + em.configError.Type.Load()) + } return encodeErr } @@ -221,6 +239,15 @@ func (em *ErrorManager) RecordDataConflictError( tableName string, conflictInfos []DataConflictInfo, ) error { + if len(conflictInfos) == 0 { + return nil + } + + if em.remainingError.Conflict.Sub(int64(len(conflictInfos))) < 0 { + threshold := em.configError.Conflict.Load() + return errors.Errorf(" meet errors exceed the max-error.conflict threshold '%d'", threshold) + } + if em.db == nil { return nil } @@ -231,13 +258,15 @@ func (em *ErrorManager) RecordDataConflictError( HideQueryLog: redact.NeedRedact(), } return exec.Transact(ctx, "insert data conflict error record", func(c context.Context, txn *sql.Tx) error { - stmt, err := txn.PrepareContext(c, fmt.Sprintf(insertIntoConflictErrorData, em.schemaEscaped)) - if err != nil { - return err - } - defer stmt.Close() - for _, conflictInfo := range conflictInfos { - _, err = stmt.ExecContext(c, + sb := &strings.Builder{} + fmt.Fprintf(sb, insertIntoConflictErrorData, em.schemaEscaped) + var sqlArgs []interface{} + for i, conflictInfo := range conflictInfos { + if i > 0 { + sb.WriteByte(',') + } + sb.WriteString(sqlValuesConflictErrorData) + sqlArgs = append(sqlArgs, em.taskID, tableName, conflictInfo.KeyData, @@ -245,11 +274,9 @@ func (em *ErrorManager) RecordDataConflictError( conflictInfo.RawKey, conflictInfo.RawValue, ) - if err != nil { - return err - } } - return nil + _, err := txn.ExecContext(c, sb.String(), sqlArgs...) + return err }) } @@ -261,6 +288,15 @@ func (em *ErrorManager) RecordIndexConflictError( conflictInfos []DataConflictInfo, rawHandles, rawRows [][]byte, ) error { + if len(conflictInfos) == 0 { + return nil + } + + if em.remainingError.Conflict.Sub(int64(len(conflictInfos))) < 0 { + threshold := em.configError.Conflict.Load() + return errors.Errorf(" meet errors exceed the max-error.conflict threshold %d", threshold) + } + if em.db == nil { return nil } @@ -271,13 +307,15 @@ func (em *ErrorManager) RecordIndexConflictError( HideQueryLog: redact.NeedRedact(), } return exec.Transact(ctx, "insert index conflict error record", func(c context.Context, txn *sql.Tx) error { - stmt, err := txn.PrepareContext(c, fmt.Sprintf(insertIntoConflictErrorIndex, em.schemaEscaped)) - if err != nil { - return err - } - defer stmt.Close() + sb := &strings.Builder{} + fmt.Fprintf(sb, insertIntoConflictErrorIndex, em.schemaEscaped) + var sqlArgs []interface{} for i, conflictInfo := range conflictInfos { - _, err = stmt.ExecContext(c, + if i > 0 { + sb.WriteByte(',') + } + sb.WriteString(sqlValuesConflictErrorIndex) + sqlArgs = append(sqlArgs, em.taskID, tableName, indexNames[i], @@ -288,38 +326,195 @@ func (em *ErrorManager) RecordIndexConflictError( rawHandles[i], rawRows[i], ) - if err != nil { - return err - } } - return nil + _, err := txn.ExecContext(c, sb.String(), sqlArgs...) + return err }) } -// GetConflictKeys obtains all (distinct) conflicting rows (handle and their -// values) from the current error report. -func (em *ErrorManager) GetConflictKeys(ctx context.Context, tableName string, prevRowID int64, limit int) (handleRows [][2][]byte, lastRowID int64, err error) { +// ResolveAllConflictKeys query all conflicting rows (handle and their +// values) from the current error report and resolve them concurrently. +func (em *ErrorManager) ResolveAllConflictKeys( + ctx context.Context, + tableName string, + pool *utils.WorkerPool, + fn func(ctx context.Context, handleRows [][2][]byte) error, +) error { if em.db == nil { - return nil, 0, nil + return nil + } + + const rowLimit = 1000 + taskCh := make(chan [2]int64) + taskWg := &sync.WaitGroup{} + g, gCtx := errgroup.WithContext(ctx) + + go func() { + //nolint:staticcheck + taskWg.Add(1) + taskCh <- [2]int64{0, math.MaxInt64} + taskWg.Wait() + close(taskCh) + }() + + for t := range taskCh { + start, end := t[0], t[1] + pool.ApplyOnErrorGroup(g, func() error { + defer taskWg.Done() + + var handleRows [][2][]byte + for start < end { + rows, err := em.db.QueryContext( + gCtx, fmt.Sprintf(selectConflictKeys, em.schemaEscaped), + tableName, start, end, rowLimit) + if err != nil { + return errors.Trace(err) + } + var lastRowID int64 + for rows.Next() { + var handleRow [2][]byte + if err := rows.Scan(&lastRowID, &handleRow[0], &handleRow[1]); err != nil { + return errors.Trace(err) + } + handleRows = append(handleRows, handleRow) + } + if err := rows.Err(); err != nil { + return errors.Trace(err) + } + if err := rows.Close(); err != nil { + return errors.Trace(err) + } + if len(handleRows) == 0 { + break + } + if err := fn(gCtx, handleRows); err != nil { + return errors.Trace(err) + } + start = lastRowID + 1 + // If the remaining tasks cannot be processed at once, split the task + // into two subtasks and send one of them to the other idle worker if possible. + if end-start > rowLimit { + mid := start + (end-start)/2 + taskWg.Add(1) + select { + case taskCh <- [2]int64{mid, end}: + end = mid + default: + taskWg.Done() + } + } + handleRows = handleRows[:0] + } + return nil + }) } - rows, err := em.db.QueryContext( - ctx, - fmt.Sprintf(selectConflictKeys, em.schemaEscaped), - tableName, - prevRowID, - limit, - ) - if err != nil { - return nil, 0, errors.Trace(err) + return errors.Trace(g.Wait()) +} + +func (em *ErrorManager) errorCount(typeVal func(*config.MaxError) int64) int64 { + cfgVal := typeVal(em.configError) + val := typeVal(&em.remainingError) + if val < 0 { + val = 0 } - defer rows.Close() + return cfgVal - val +} - for rows.Next() { - var handleRow [2][]byte - if err := rows.Scan(&lastRowID, &handleRow[0], &handleRow[1]); err != nil { - return nil, 0, errors.Trace(err) - } - handleRows = append(handleRows, handleRow) +func (em *ErrorManager) typeErrors() int64 { + return em.errorCount(func(maxError *config.MaxError) int64 { + return maxError.Type.Load() + }) +} + +func (em *ErrorManager) syntaxError() int64 { + return em.errorCount(func(maxError *config.MaxError) int64 { + return maxError.Syntax.Load() + }) +} + +func (em *ErrorManager) conflictError() int64 { + return em.errorCount(func(maxError *config.MaxError) int64 { + return maxError.Conflict.Load() + }) +} + +func (em *ErrorManager) charsetError() int64 { + return em.errorCount(func(maxError *config.MaxError) int64 { + return maxError.Charset.Load() + }) +} + +func (em *ErrorManager) HasError() bool { + return em.typeErrors() > 0 || em.syntaxError() > 0 || + em.charsetError() > 0 || em.conflictError() > 0 +} + +// GenErrorLogFields return a slice of zap.Field for each error type +func (em *ErrorManager) LogErrorDetails() { + fmtErrMsg := func(cnt int64, errType, tblName string) string { + return fmt.Sprintf("Detect %d %s errors in total, please refer to table %s for more details", + cnt, errType, em.fmtTableName(tblName)) } - return handleRows, lastRowID, errors.Trace(rows.Err()) + if errCnt := em.typeErrors(); errCnt > 0 { + log.L().Warn(fmtErrMsg(errCnt, "data type", typeErrorTableName)) + } + if errCnt := em.syntaxError(); errCnt > 0 { + log.L().Warn(fmtErrMsg(errCnt, "data type", syntaxErrorTableName)) + } + if errCnt := em.charsetError(); errCnt > 0 { + // TODO: add charset table name + log.L().Warn(fmtErrMsg(errCnt, "data type", "")) + } + if errCnt := em.conflictError(); errCnt > 0 { + log.L().Warn(fmtErrMsg(errCnt, "data type", conflictErrorTableName)) + } +} + +func (em *ErrorManager) fmtTableName(t string) string { + return fmt.Sprintf("%s.`%s`", em.schemaEscaped, t) +} + +// Output renders a table which contains error summery for each error type. +func (em *ErrorManager) Output() string { + if !em.HasError() { + return "" + } + + t := table.NewWriter() + t.AppendHeader(table.Row{"#", "Error Type", "Error Count", "Error Data Table"}) + t.SetColumnConfigs([]table.ColumnConfig{ + {Name: "#", WidthMax: 6}, + {Name: "Error Type", WidthMax: 20}, + {Name: "Error Count", WidthMax: 12}, + {Name: "Error Data Table", WidthMax: 42}, + }) + t.SetAllowedRowLength(80) + t.SetRowPainter(func(row table.Row) text.Colors { + return text.Colors{text.FgRed} + }) + + count := 0 + if errCnt := em.typeErrors(); errCnt > 0 { + count++ + t.AppendRow(table.Row{count, "Data Type", errCnt, em.fmtTableName(typeErrorTableName)}) + } + if errCnt := em.syntaxError(); errCnt > 0 { + count++ + t.AppendRow(table.Row{count, "Data Syntax", errCnt, em.fmtTableName(syntaxErrorTableName)}) + } + if errCnt := em.charsetError(); errCnt > 0 { + count++ + // do not support record charset error now. + t.AppendRow(table.Row{count, "Charset Error", errCnt, ""}) + } + if errCnt := em.conflictError(); errCnt > 0 { + count++ + t.AppendRow(table.Row{count, "Unique Key Conflict", errCnt, em.fmtTableName(conflictErrorTableName)}) + } + + res := "\nImport Data Error Summary: \n" + res += t.Render() + res += "\n" + + return res } diff --git a/br/pkg/lightning/errormanager/errormanager_test.go b/br/pkg/lightning/errormanager/errormanager_test.go index 2b5aba0e07605..63446cdd4c573 100644 --- a/br/pkg/lightning/errormanager/errormanager_test.go +++ b/br/pkg/lightning/errormanager/errormanager_test.go @@ -16,24 +16,25 @@ package errormanager import ( "context" + "database/sql" + "database/sql/driver" + "io" + "math/rand" + "strconv" + "strings" "testing" "github.com/DATA-DOG/go-sqlmock" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" + "go.uber.org/atomic" + "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/utils" ) -var _ = Suite(errorManagerSuite{}) - -func TestErrorManager(t *testing.T) { - TestingT(t) -} - -type errorManagerSuite struct{} - -func (e errorManagerSuite) TestInit(c *C) { +func TestInit(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) cfg := config.NewConfig() cfg.TikvImporter.DuplicateResolution = config.DupeResAlgRecord @@ -41,15 +42,15 @@ func (e errorManagerSuite) TestInit(c *C) { cfg.App.TaskInfoSchemaName = "lightning_errors" em := New(db, cfg) - c.Assert(em.dupResolution, Equals, cfg.TikvImporter.DuplicateResolution) - c.Assert(em.remainingError.Type.Load(), Equals, cfg.App.MaxError.Type.Load()) - c.Assert(em.remainingError.Conflict.Load(), Equals, cfg.App.MaxError.Conflict.Load()) + require.Equal(t, cfg.TikvImporter.DuplicateResolution, em.dupResolution) + require.Equal(t, cfg.App.MaxError.Type.Load(), em.remainingError.Type.Load()) + require.Equal(t, cfg.App.MaxError.Conflict.Load(), em.remainingError.Conflict.Load()) em.remainingError.Type.Store(0) em.dupResolution = config.DupeResAlgNone ctx := context.Background() err = em.Init(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) em.dupResolution = config.DupeResAlgRecord mock.ExpectExec("CREATE SCHEMA IF NOT EXISTS `lightning_errors`;"). @@ -57,7 +58,7 @@ func (e errorManagerSuite) TestInit(c *C) { mock.ExpectExec("CREATE TABLE IF NOT EXISTS `lightning_errors`\\.conflict_error_v1.*"). WillReturnResult(sqlmock.NewResult(2, 1)) err = em.Init(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) em.dupResolution = config.DupeResAlgNone em.remainingError.Type.Store(1) @@ -66,8 +67,7 @@ func (e errorManagerSuite) TestInit(c *C) { mock.ExpectExec("CREATE TABLE IF NOT EXISTS `lightning_errors`\\.type_error_v1.*"). WillReturnResult(sqlmock.NewResult(4, 1)) err = em.Init(ctx) - c.Assert(err, IsNil) - + require.NoError(t, err) em.dupResolution = config.DupeResAlgRecord em.remainingError.Type.Store(1) mock.ExpectExec("CREATE SCHEMA IF NOT EXISTS `lightning_errors`.*"). @@ -77,7 +77,189 @@ func (e errorManagerSuite) TestInit(c *C) { mock.ExpectExec("CREATE TABLE IF NOT EXISTS `lightning_errors`\\.conflict_error_v1.*"). WillReturnResult(sqlmock.NewResult(7, 1)) err = em.Init(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(mock.ExpectationsWereMet(), IsNil) + require.NoError(t, mock.ExpectationsWereMet()) +} + +type mockDriver struct { + driver.Driver + totalRows int64 +} + +func (m mockDriver) Open(_ string) (driver.Conn, error) { + return mockConn{totalRows: m.totalRows}, nil +} + +type mockConn struct { + driver.Conn + driver.ExecerContext + driver.QueryerContext + totalRows int64 +} + +func (c mockConn) ExecContext(_ context.Context, _ string, _ []driver.NamedValue) (driver.Result, error) { + return sqlmock.NewResult(1, 1), nil +} + +func (mockConn) Close() error { return nil } + +type mockRows struct { + driver.Rows + start int64 + end int64 +} + +func (r *mockRows) Columns() []string { + return []string{"_tidb_rowid", "raw_handle", "raw_row"} +} + +func (r *mockRows) Close() error { return nil } + +func (r *mockRows) Next(dest []driver.Value) error { + if r.start >= r.end { + return io.EOF + } + dest[0] = r.start // _tidb_rowid + dest[1] = []byte{} // raw_handle + dest[2] = []byte{} // raw_row + r.start++ + return nil +} + +func (c mockConn) QueryContext(_ context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + expectedQuery := "SELECT _tidb_rowid, raw_handle, raw_row.*" + if err := sqlmock.QueryMatcherRegexp.Match(expectedQuery, query); err != nil { + return &mockRows{}, nil + } + if len(args) != 4 { + return &mockRows{}, nil + } + // args are tableName, start, end, and limit. + start := args[1].Value.(int64) + if start < 1 { + start = 1 + } + end := args[2].Value.(int64) + if end > c.totalRows+1 { + end = c.totalRows + 1 + } + limit := args[3].Value.(int64) + if start+limit < end { + end = start + limit + } + return &mockRows{start: start, end: end}, nil +} + +func TestResolveAllConflictKeys(t *testing.T) { + const totalRows = int64(1 << 18) + driverName := "errmgr-mock-" + strconv.Itoa(rand.Int()) + sql.Register(driverName, mockDriver{totalRows: totalRows}) + db, err := sql.Open(driverName, "") + require.NoError(t, err) + defer db.Close() + + cfg := config.NewConfig() + cfg.TikvImporter.DuplicateResolution = config.DupeResAlgRemove + cfg.App.TaskInfoSchemaName = "lightning_errors" + em := New(db, cfg) + ctx := context.Background() + err = em.Init(ctx) + require.NoError(t, err) + + resolved := atomic.NewInt64(0) + pool := utils.NewWorkerPool(16, "resolve duplicate rows") + err = em.ResolveAllConflictKeys( + ctx, "test", pool, + func(ctx context.Context, handleRows [][2][]byte) error { + resolved.Add(int64(len(handleRows))) + return nil + }, + ) + require.NoError(t, err) + require.Equal(t, totalRows, resolved.Load()) +} + +func TestErrorMgrHasError(t *testing.T) { + cfg := &config.Config{} + cfg.App.MaxError = config.MaxError{ + Syntax: *atomic.NewInt64(100), + Charset: *atomic.NewInt64(100), + Type: *atomic.NewInt64(100), + Conflict: *atomic.NewInt64(100), + } + em := &ErrorManager{ + configError: &cfg.App.MaxError, + remainingError: cfg.App.MaxError, + } + + // no field changes, should return false + require.False(t, em.HasError()) + + // change single field + em.remainingError.Syntax.Sub(1) + require.True(t, em.HasError()) + + em.remainingError = cfg.App.MaxError + em.remainingError.Charset.Sub(1) + require.True(t, em.HasError()) + + em.remainingError = cfg.App.MaxError + em.remainingError.Type.Sub(1) + require.True(t, em.HasError()) + + em.remainingError = cfg.App.MaxError + em.remainingError.Conflict.Sub(1) + require.True(t, em.HasError()) + + // change multiple keys + em.remainingError = cfg.App.MaxError + em.remainingError.Syntax.Store(0) + em.remainingError.Charset.Store(0) + em.remainingError.Type.Store(0) + em.remainingError.Conflict.Store(0) + require.True(t, em.HasError()) +} + +func TestErrorMgrErrorOutput(t *testing.T) { + cfg := &config.Config{} + cfg.App.MaxError = config.MaxError{ + Syntax: *atomic.NewInt64(100), + Charset: *atomic.NewInt64(100), + Type: *atomic.NewInt64(100), + Conflict: *atomic.NewInt64(100), + } + em := &ErrorManager{ + configError: &cfg.App.MaxError, + remainingError: cfg.App.MaxError, + schemaEscaped: "`error_info`", + } + + output := em.Output() + require.Equal(t, output, "") + + em.remainingError.Syntax.Sub(1) + output = em.Output() + checkStr := strings.ReplaceAll(output, "\n", "") + expected := "Import Data Error Summary: +---+-------------+-------------+--------------------------------+| # | ERROR TYPE | ERROR COUNT | ERROR DATA TABLE |+---+-------------+-------------+--------------------------------+|\x1b[31m 1 \x1b[0m|\x1b[31m Data Syntax \x1b[0m|\x1b[31m 1 \x1b[0m|\x1b[31m `error_info`.`syntax_error_v1` \x1b[0m|+---+-------------+-------------+--------------------------------+" + require.Equal(t, expected, checkStr) + + em.remainingError = cfg.App.MaxError + em.remainingError.Syntax.Sub(10) + em.remainingError.Type.Store(10) + output = em.Output() + checkStr = strings.ReplaceAll(output, "\n", "") + expected = "Import Data Error Summary: +---+-------------+-------------+--------------------------------+| # | ERROR TYPE | ERROR COUNT | ERROR DATA TABLE |+---+-------------+-------------+--------------------------------+|\x1b[31m 1 \x1b[0m|\x1b[31m Data Type \x1b[0m|\x1b[31m 90 \x1b[0m|\x1b[31m `error_info`.`type_error_v1` \x1b[0m||\x1b[31m 2 \x1b[0m|\x1b[31m Data Syntax \x1b[0m|\x1b[31m 10 \x1b[0m|\x1b[31m `error_info`.`syntax_error_v1` \x1b[0m|+---+-------------+-------------+--------------------------------+" + require.Equal(t, expected, checkStr) + + // change multiple keys + em.remainingError = cfg.App.MaxError + em.remainingError.Syntax.Store(0) + em.remainingError.Charset.Store(0) + em.remainingError.Type.Store(0) + em.remainingError.Conflict.Store(0) + output = em.Output() + checkStr = strings.ReplaceAll(output, "\n", "") + expected = "Import Data Error Summary: +---+---------------------+-------------+----------------------------------+| # | ERROR TYPE | ERROR COUNT | ERROR DATA TABLE |+---+---------------------+-------------+----------------------------------+|\x1b[31m 1 \x1b[0m|\x1b[31m Data Type \x1b[0m|\x1b[31m 100 \x1b[0m|\x1b[31m `error_info`.`type_error_v1` \x1b[0m||\x1b[31m 2 \x1b[0m|\x1b[31m Data Syntax \x1b[0m|\x1b[31m 100 \x1b[0m|\x1b[31m `error_info`.`syntax_error_v1` \x1b[0m||\x1b[31m 3 \x1b[0m|\x1b[31m Charset Error \x1b[0m|\x1b[31m 100 \x1b[0m|\x1b[31m \x1b[0m||\x1b[31m 4 \x1b[0m|\x1b[31m Unique Key Conflict \x1b[0m|\x1b[31m 100 \x1b[0m|\x1b[31m `error_info`.`conflict_error_v1` \x1b[0m|+---+---------------------+-------------+----------------------------------+" + require.Equal(t, expected, checkStr) } diff --git a/br/pkg/lightning/lightning.go b/br/pkg/lightning/lightning.go index 9fc40cdf77144..4ad8622c8d5fb 100644 --- a/br/pkg/lightning/lightning.go +++ b/br/pkg/lightning/lightning.go @@ -30,6 +30,7 @@ import ( "sync" "time" + "github.com/google/uuid" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/import_sstpb" @@ -49,8 +50,6 @@ import ( "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/br/pkg/version/build" - - "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/shurcooL/httpgzip" "go.uber.org/zap" @@ -188,6 +187,7 @@ func (l *Lightning) goServe(statusAddr string, realAddrWriter io.Writer) error { // use a default glue later. // - for lightning as a library, taskCtx could be a meaningful context that get canceled outside, and glue could be a // caller implemented glue. +// deprecated: use RunOnceWithOptions instead. func (l *Lightning) RunOnce(taskCtx context.Context, taskCfg *config.Config, glue glue.Glue) error { if err := taskCfg.Adjust(taskCtx); err != nil { return err @@ -198,7 +198,7 @@ func (l *Lightning) RunOnce(taskCtx context.Context, taskCfg *config.Config, glu taskCfg.TaskID = int64(val.(int)) }) - return l.run(taskCtx, taskCfg, glue) + return l.run(taskCtx, taskCfg, &options{glue: glue}) } func (l *Lightning) RunServer() error { @@ -216,19 +216,70 @@ func (l *Lightning) RunServer() error { return err } err = l.run(context.Background(), task, nil) - if err != nil { + if err != nil && !common.IsContextCanceledError(err) { restore.DeliverPauser.Pause() // force pause the progress on error log.L().Error("tidb lightning encountered error", zap.Error(err)) } } } +// RunOnceWithOptions is used by binary lightning and host when using lightning as a library. +// - for binary lightning, taskCtx could be context.Background which means taskCtx wouldn't be canceled directly by its +// cancel function, but only by Lightning.Stop or HTTP DELETE using l.cancel. No need to set Options +// - for lightning as a library, taskCtx could be a meaningful context that get canceled outside, and there Options may +// be used: +// - WithGlue: set a caller implemented glue. Otherwise, lightning will use a default glue later. +// - WithDumpFileStorage: caller has opened an external storage for lightning. Otherwise, lightning will open a +// storage by config +// - WithCheckpointStorage: caller has opened an external storage for lightning and want to save checkpoint +// in it. Otherwise, lightning will save checkpoint by the Checkpoint.DSN in config +func (l *Lightning) RunOnceWithOptions(taskCtx context.Context, taskCfg *config.Config, opts ...Option) error { + o := &options{} + for _, opt := range opts { + opt(o) + } + + failpoint.Inject("setExtStorage", func(val failpoint.Value) { + path := val.(string) + b, err := storage.ParseBackend(path, nil) + if err != nil { + panic(err) + } + s, err := storage.New(context.Background(), b, &storage.ExternalStorageOptions{}) + if err != nil { + panic(err) + } + o.dumpFileStorage = s + o.checkpointStorage = s + }) + failpoint.Inject("setCheckpointName", func(val failpoint.Value) { + file := val.(string) + o.checkpointName = file + }) + + if o.dumpFileStorage != nil { + // we don't use it, set a value to pass Adjust + taskCfg.Mydumper.SourceDir = "noop://" + } + + if err := taskCfg.Adjust(taskCtx); err != nil { + return err + } + + taskCfg.TaskID = time.Now().UnixNano() + failpoint.Inject("SetTaskID", func(val failpoint.Value) { + taskCfg.TaskID = int64(val.(int)) + }) + + return l.run(taskCtx, taskCfg, o) +} + var ( taskRunNotifyKey = "taskRunNotifyKey" taskCfgRecorderKey = "taskCfgRecorderKey" ) -func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue.Glue) (err error) { +func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, o *options) (err error) { build.LogInfo(build.Lightning) log.L().Info("cfg", zap.Stringer("cfg", taskCfg)) @@ -267,7 +318,7 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue. }) if err := taskCfg.TiDB.Security.RegisterMySQL(); err != nil { - return err + return common.ErrInvalidTLSConfig.Wrap(err) } defer func() { // deregister TLS config with name "cluster" @@ -279,21 +330,25 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue. // initiation of default glue should be after RegisterMySQL, which is ready to be called after taskCfg.Adjust // and also put it here could avoid injecting another two SkipRunTask failpoint to caller + g := o.glue if g == nil { db, err := restore.DBFromConfig(ctx, taskCfg.TiDB) if err != nil { - return err + return common.ErrDBConnect.Wrap(err) } g = glue.NewExternalTiDBGlue(db, taskCfg.TiDB.SQLMode) } - u, err := storage.ParseBackend(taskCfg.Mydumper.SourceDir, nil) - if err != nil { - return errors.Annotate(err, "parse backend failed") - } - s, err := storage.New(ctx, u, &storage.ExternalStorageOptions{}) - if err != nil { - return errors.Annotate(err, "create storage failed") + s := o.dumpFileStorage + if s == nil { + u, err := storage.ParseBackend(taskCfg.Mydumper.SourceDir, nil) + if err != nil { + return common.NormalizeError(err) + } + s, err = storage.New(ctx, u, &storage.ExternalStorageOptions{}) + if err != nil { + return common.NormalizeError(err) + } } // return expectedErr means at least meet one file @@ -304,9 +359,9 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue. }) if !errors.ErrorEqual(walkErr, expectedErr) { if walkErr == nil { - return errors.Errorf("data-source-dir '%s' doesn't exist or contains no files", taskCfg.Mydumper.SourceDir) + return common.ErrEmptySourceDir.GenWithStackByArgs(taskCfg.Mydumper.SourceDir) } - return errors.Annotatef(walkErr, "visit data-source-dir '%s' failed", taskCfg.Mydumper.SourceDir) + return common.NormalizeOrWrapErr(common.ErrStorageUnknown, walkErr) } loadTask := log.L().Begin(zap.InfoLevel, "load data source") @@ -319,7 +374,7 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue. err = checkSystemRequirement(taskCfg, mdl.GetDatabases()) if err != nil { log.L().Error("check system requirements failed", zap.Error(err)) - return errors.Trace(err) + return common.ErrSystemRequirementNotMet.Wrap(err).GenWithStackByArgs() } // check table schema conflicts err = checkSchemaConflict(taskCfg, mdl.GetDatabases()) @@ -333,7 +388,17 @@ func (l *Lightning) run(taskCtx context.Context, taskCfg *config.Config, g glue. var procedure *restore.Controller - procedure, err = restore.NewRestoreController(ctx, dbMetas, taskCfg, &l.status, s, g) + param := &restore.ControllerParam{ + DBMetas: dbMetas, + Status: &l.status, + DumpFileStorage: s, + OwnExtStorage: o.dumpFileStorage == nil, + Glue: g, + CheckpointStorage: o.checkpointStorage, + CheckpointName: o.checkpointName, + } + + procedure, err = restore.NewRestoreController(ctx, taskCfg, param) if err != nil { log.L().Error("restore failed", log.ShortError(err)) return errors.Trace(err) @@ -727,7 +792,7 @@ func checkSchemaConflict(cfg *config.Config, dbsMeta []*mydump.MDDatabaseMeta) e if db.Name == cfg.Checkpoint.Schema { for _, tb := range db.Tables { if checkpoints.IsCheckpointTable(tb.Name) { - return errors.Errorf("checkpoint table `%s`.`%s` conflict with data files. Please change the `checkpoint.schema` config or set `checkpoint.driver` to \"file\" instead", db.Name, tb.Name) + return common.ErrCheckpointSchemaConflict.GenWithStack("checkpoint table `%s`.`%s` conflict with data files. Please change the `checkpoint.schema` config or set `checkpoint.driver` to \"file\" instead", db.Name, tb.Name) } } } @@ -793,7 +858,7 @@ func UnsafeCloseEngine(ctx context.Context, importer backend.Backend, engine str if err != nil { return nil, errors.Trace(err) } - ce, err := importer.UnsafeCloseEngine(ctx, nil, tableName, int32(engineID)) + ce, err := importer.UnsafeCloseEngine(ctx, nil, tableName, int32(engineID)) // #nosec G109 return ce, errors.Trace(err) } diff --git a/br/pkg/lightning/lightning_serial_test.go b/br/pkg/lightning/lightning_serial_test.go index bd268c3d3c39f..1a9b0c9692495 100644 --- a/br/pkg/lightning/lightning_serial_test.go +++ b/br/pkg/lightning/lightning_serial_test.go @@ -54,13 +54,14 @@ func TestRun(t *testing.T) { cfg := config.NewConfig() err := cfg.LoadFromGlobal(globalConfig) require.NoError(t, err) - err = lightning.RunOnce(context.Background(), cfg, nil) + err = lightning.RunOnceWithOptions(context.Background(), cfg) require.Error(t, err) - require.Regexp(t, "mydumper dir does not exist$", err.Error()) + require.Regexp(t, "`mydumper.data-source-dir` does not exist$", err.Error()) path, _ := filepath.Abs(".") ctx := context.Background() invalidGlue := glue.NewExternalTiDBGlue(nil, 0) + o := &options{glue: invalidGlue} err = lightning.run(ctx, &config.Config{ Mydumper: config.MydumperRuntime{ SourceDir: "file://" + filepath.ToSlash(path), @@ -71,8 +72,8 @@ func TestRun(t *testing.T) { Enable: true, Driver: "invalid", }, - }, invalidGlue) - require.EqualError(t, err, "open checkpoint db failed: Unknown checkpoint driver invalid") + }, o) + require.EqualError(t, err, "[Lightning:Checkpoint:ErrUnknownCheckpointDriver]unknown checkpoint driver 'invalid'") err = lightning.run(ctx, &config.Config{ Mydumper: config.MydumperRuntime{ @@ -84,7 +85,7 @@ func TestRun(t *testing.T) { Driver: "file", DSN: "any-file", }, - }, invalidGlue) + }, o) require.Error(t, err) } diff --git a/br/pkg/lightning/lightning_server_serial_test.go b/br/pkg/lightning/lightning_server_serial_test.go index 099299f7f7d4e..478dafdcac68a 100644 --- a/br/pkg/lightning/lightning_server_serial_test.go +++ b/br/pkg/lightning/lightning_server_serial_test.go @@ -24,14 +24,19 @@ import ( "fmt" "net/http" "strings" + "sync" "testing" "time" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/web" "github.com/stretchr/testify/require" ) +// initProgressOnce is used to ensure init progress once to avoid data race. +var initProgressOnce sync.Once + type lightningServerSuite struct { lightning *Lightning taskCfgCh chan *config.Config @@ -39,6 +44,8 @@ type lightningServerSuite struct { } func createSuite(t *testing.T) (s *lightningServerSuite, clean func()) { + initProgressOnce.Do(web.EnableCurrentProgress) + cfg := config.NewGlobalConfig() cfg.TiDB.Host = "test.invalid" cfg.TiDB.Port = 4000 @@ -310,7 +317,7 @@ func TestHTTPAPIOutsideServerMode(t *testing.T) { err := cfg.LoadFromGlobal(s.lightning.globalCfg) require.NoError(t, err) go func() { - errCh <- s.lightning.RunOnce(s.lightning.ctx, cfg, nil) + errCh <- s.lightning.RunOnceWithOptions(s.lightning.ctx, cfg) }() time.Sleep(600 * time.Millisecond) diff --git a/br/pkg/lightning/log/filter_test.go b/br/pkg/lightning/log/filter_test.go index 6d1530ce9ee45..1d0344f8db9d2 100644 --- a/br/pkg/lightning/log/filter_test.go +++ b/br/pkg/lightning/log/filter_test.go @@ -5,60 +5,48 @@ package log_test import ( "regexp" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/log" + "github.com/stretchr/testify/require" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) -var _ = Suite(&testFilterSuite{}) - -type testFilterSuite struct{} - -func (s *testFilterSuite) TestFilter(c *C) { +func TestFilter(t *testing.T) { logger, buffer := log.MakeTestLogger() logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9})) - c.Assert( - buffer.Stripped(), Equals, - `{"$lvl":"WARN","$msg":"the message","number":123456,"array":[7,8,9]}`, - ) + + require.Equal(t, `{"$lvl":"WARN","$msg":"the message","number":123456,"array":[7,8,9]}`, buffer.Stripped()) logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core { return log.NewFilterCore(c, "github.com/pingcap/br/") }), zap.AddCaller()) logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9})) - c.Assert(buffer.Stripped(), HasLen, 0) + require.Len(t, buffer.Stripped(), 0) logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core { return log.NewFilterCore(c, "github.com/pingcap/tidb/br/").With([]zap.Field{zap.String("a", "b")}) }), zap.AddCaller()) logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9})) - c.Assert( - buffer.Stripped(), Equals, - `{"$lvl":"WARN","$msg":"the message","a":"b","number":123456,"array":[7,8,9]}`, - ) + require.Equal(t, `{"$lvl":"WARN","$msg":"the message","a":"b","number":123456,"array":[7,8,9]}`, buffer.Stripped()) logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core { return log.NewFilterCore(c, "github.com/pingcap/br/").With([]zap.Field{zap.String("a", "b")}) }), zap.AddCaller()) logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9})) - c.Assert(buffer.Stripped(), HasLen, 0) + require.Len(t, buffer.Stripped(), 0) - // Fields won't trigger filter. - logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core { - return log.NewFilterCore(c, "github.com/pingcap/check/").With([]zap.Field{zap.String("a", "b")}) - }), zap.AddCaller()) logger.Warn("the message", zap.String("stack", "github.com/pingcap/tidb/br/")) - c.Assert(buffer.Stripped(), HasLen, 0) + require.Len(t, buffer.Stripped(), 0) } -// PASS: filter_test.go:82: testFilterSuite.BenchmarkFilterRegexMatchString 1000000 1163 ns/op -// PASS: filter_test.go:64: testFilterSuite.BenchmarkFilterStringsContains 10000000 159 ns/op +// BenchmarkFilterStringsContains-16 16693887 66.68 ns/op +// BenchmarkFilterRegexMatchString-16 2350828 510.6 ns/op // -// Run `go test github.com/pingcap/tidb/br/pkg/lightning/log -check.b -test.v` to get benchmark result. -func (s *testFilterSuite) BenchmarkFilterStringsContains(c *C) { - c.ResetTimer() +// Run `go test -run='^$' -bench=. -v github.com/pingcap/tidb/br/pkg/lightning/log` to get benchmark result. +func BenchmarkFilterStringsContains(b *testing.B) { + b.ResetTimer() inputs := []string{ "github.com/pingcap/tidb/some/package/path", @@ -66,7 +54,7 @@ func (s *testFilterSuite) BenchmarkFilterStringsContains(c *C) { "github.com/pingcap/tidb/br/some/package/path", } filters := []string{"github.com/pingcap/tidb/", "github.com/tikv/pd/"} - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { for i := range inputs { for j := range filters { _ = strings.Contains(inputs[i], filters[j]) @@ -75,8 +63,8 @@ func (s *testFilterSuite) BenchmarkFilterStringsContains(c *C) { } } -func (s *testFilterSuite) BenchmarkFilterRegexMatchString(c *C) { - c.ResetTimer() +func BenchmarkFilterRegexMatchString(b *testing.B) { + b.ResetTimer() inputs := []string{ "github.com/pingcap/tidb/some/package/path", @@ -84,7 +72,7 @@ func (s *testFilterSuite) BenchmarkFilterRegexMatchString(c *C) { "github.com/pingcap/tidb/br/some/package/path", } filters := regexp.MustCompile(`github.com/(pingcap/tidb|tikv/pd)/`) - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { for i := range inputs { _ = filters.MatchString(inputs[i]) } diff --git a/br/pkg/lightning/log/log.go b/br/pkg/lightning/log/log.go index 97cbfdd8c0457..aa61023a29cc9 100644 --- a/br/pkg/lightning/log/log.go +++ b/br/pkg/lightning/log/log.go @@ -91,7 +91,7 @@ func InitLogger(cfg *Config, tidbLoglevel string) error { } filterTiDBLog := zap.WrapCore(func(core zapcore.Core) zapcore.Core { // Filter logs from TiDB and PD. - return NewFilterCore(core, "github.com/pingcap/tidb/br/") + return NewFilterCore(core, "github.com/pingcap/tidb/br/", "main.main") }) // "-" is a special config for log to stdout. if len(cfg.File) > 0 && cfg.File != "-" { diff --git a/br/pkg/lightning/log/log_serial_test.go b/br/pkg/lightning/log/log_serial_test.go deleted file mode 100644 index 63ef2bf321ab1..0000000000000 --- a/br/pkg/lightning/log/log_serial_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package log_test - -import ( - "io" - "os" - "testing" - - "github.com/pingcap/tidb/br/pkg/lightning/log" - "github.com/stretchr/testify/require" -) - -func TestInitStdoutLogger(t *testing.T) { - r, w, err := os.Pipe() - require.NoError(t, err) - oldStdout := os.Stdout - os.Stdout = w - - msg := "logger is initialized to stdout" - outputC := make(chan string, 1) - go func() { - buf := make([]byte, 4096) - n := 0 - for { - nn, err := r.Read(buf[n:]) - if nn == 0 || err == io.EOF { - break - } - require.NoError(t, err) - n += nn - } - outputC <- string(buf[:n]) - }() - - logCfg := &log.Config{File: "-"} - log.InitLogger(logCfg, "info") - log.L().Info(msg) - - os.Stdout = oldStdout - require.NoError(t, w.Close()) - output := <-outputC - require.NoError(t, r.Close()) - require.Contains(t, output, msg) -} diff --git a/br/pkg/lightning/log/log_test.go b/br/pkg/lightning/log/log_test.go index 8024b5fa50df9..42d4c0b0aaf21 100644 --- a/br/pkg/lightning/log/log_test.go +++ b/br/pkg/lightning/log/log_test.go @@ -15,37 +15,61 @@ package log_test import ( + "io" + "os" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/log" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) -func TestLog(t *testing.T) { - TestingT(t) -} - -type logSuite struct{} - -var _ = Suite(&logSuite{}) - -func (s *logSuite) TestConfigAdjust(c *C) { +func TestConfigAdjust(t *testing.T) { cfg := &log.Config{} cfg.Adjust() - c.Assert(cfg.Level, Equals, "info") + require.Equal(t, "info", cfg.Level) cfg.File = "." err := log.InitLogger(cfg, "info") - c.Assert(err, ErrorMatches, "can't use directory as log file name") - log.L().Named("xx") + require.EqualError(t, err, "can't use directory as log file name") } -func (s *logSuite) TestTestLogger(c *C) { +func TestTestLogger(t *testing.T) { logger, buffer := log.MakeTestLogger() logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9})) - c.Assert( - buffer.Stripped(), Equals, - `{"$lvl":"WARN","$msg":"the message","number":123456,"array":[7,8,9]}`, - ) + require.Equal(t, `{"$lvl":"WARN","$msg":"the message","number":123456,"array":[7,8,9]}`, buffer.Stripped()) +} + +func TestInitStdoutLogger(t *testing.T) { + r, w, err := os.Pipe() + require.NoError(t, err) + oldStdout := os.Stdout + os.Stdout = w + + msg := "logger is initialized to stdout" + outputC := make(chan string, 1) + go func() { + buf := make([]byte, 4096) + n := 0 + for { + nn, err := r.Read(buf[n:]) + if nn == 0 || err == io.EOF { + break + } + require.NoError(t, err) + n += nn + } + outputC <- string(buf[:n]) + }() + + logCfg := &log.Config{File: "-"} + err = log.InitLogger(logCfg, "info") + require.NoError(t, err) + log.L().Info(msg) + + os.Stdout = oldStdout + require.NoError(t, w.Close()) + output := <-outputC + require.NoError(t, r.Close()) + require.Contains(t, output, msg) } diff --git a/br/pkg/lightning/metric/metric_test.go b/br/pkg/lightning/metric/metric_test.go index 18bc94e8517b2..65c81d8eaa8e8 100644 --- a/br/pkg/lightning/metric/metric_test.go +++ b/br/pkg/lightning/metric/metric_test.go @@ -18,43 +18,32 @@ import ( "errors" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/metric" "github.com/prometheus/client_golang/prometheus" + "github.com/stretchr/testify/require" ) -type testMetricSuite struct{} - -func (s *testMetricSuite) SetUpSuite(c *C) {} -func (s *testMetricSuite) TearDownSuite(c *C) {} - -var _ = Suite(&testMetricSuite{}) - -func TestMetric(t *testing.T) { - TestingT(t) -} - -func (s *testMetricSuite) TestReadCounter(c *C) { +func TestReadCounter(t *testing.T) { counter := prometheus.NewCounter(prometheus.CounterOpts{}) counter.Add(1256.0) counter.Add(2214.0) - c.Assert(metric.ReadCounter(counter), Equals, 3470.0) + require.Equal(t, 3470.0, metric.ReadCounter(counter)) } -func (s *testMetricSuite) TestReadHistogramSum(c *C) { +func TestReadHistogramSum(t *testing.T) { histogram := prometheus.NewHistogram(prometheus.HistogramOpts{}) histogram.Observe(11131.5) histogram.Observe(15261.0) - c.Assert(metric.ReadHistogramSum(histogram), Equals, 26392.5) + require.Equal(t, 26392.5, metric.ReadHistogramSum(histogram)) } -func (s *testMetricSuite) TestRecordEngineCount(c *C) { +func TestRecordEngineCount(t *testing.T) { metric.RecordEngineCount("table1", nil) metric.RecordEngineCount("table1", errors.New("mock error")) successCounter, err := metric.ProcessedEngineCounter.GetMetricWithLabelValues("table1", "success") - c.Assert(err, IsNil) - c.Assert(metric.ReadCounter(successCounter), Equals, 1.0) + require.NoError(t, err) + require.Equal(t, 1.0, metric.ReadCounter(successCounter)) failureCount, err := metric.ProcessedEngineCounter.GetMetricWithLabelValues("table1", "failure") - c.Assert(err, IsNil) - c.Assert(metric.ReadCounter(failureCount), Equals, 1.0) + require.NoError(t, err) + require.Equal(t, 1.0, metric.ReadCounter(failureCount)) } diff --git a/br/pkg/lightning/mydump/charset_convertor.go b/br/pkg/lightning/mydump/charset_convertor.go index 81e57be681a18..53a77816bb5e3 100644 --- a/br/pkg/lightning/mydump/charset_convertor.go +++ b/br/pkg/lightning/mydump/charset_convertor.go @@ -87,8 +87,6 @@ func (cc *CharsetConvertor) initEncoder() error { return errors.Errorf("not support %s as the conversion source yet", cc.sourceCharacterSet) } -var utf8RuneErrorStr = string(utf8.RuneError) - // Decode does the charset conversion work from sourceCharacterSet to utf8mb4. // It will return a string as the conversion result whose length may be less or greater // than the original string `src`. diff --git a/br/pkg/lightning/mydump/charset_convertor_test.go b/br/pkg/lightning/mydump/charset_convertor_test.go index cf091c09b142e..5165ec2b63175 100644 --- a/br/pkg/lightning/mydump/charset_convertor_test.go +++ b/br/pkg/lightning/mydump/charset_convertor_test.go @@ -17,17 +17,11 @@ package mydump import ( "io" "os" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testCharsetConvertorSuite{}) - -type testCharsetConvertorSuite struct{} - -func (s *testCharsetConvertorSuite) SetUpSuite(c *C) {} -func (s *testCharsetConvertorSuite) TearDownSuite(c *C) {} - const ( testUTF8DataFile = "./csv/utf8_test_file.csv" testGBKDataFile = "./csv/gb18030_test_file.csv" @@ -40,28 +34,28 @@ var ( invalidChar = []byte{0xff} // Invalid gb18030 char ) -func (s testCharsetConvertorSuite) TestCharsetConvertor(c *C) { +func TestCharsetConvertor(t *testing.T) { utf8Reader, err := os.Open(testUTF8DataFile) - c.Assert(err, IsNil) + require.NoError(t, err) utf8Data, err := io.ReadAll(utf8Reader) - c.Assert(err, IsNil) + require.NoError(t, err) gbkReader, err := os.Open(testGBKDataFile) - c.Assert(err, IsNil) + require.NoError(t, err) gbkData, err := io.ReadAll(gbkReader) - c.Assert(err, IsNil) + require.NoError(t, err) cc, err := NewCharsetConvertor("gb18030", "\ufffd") - c.Assert(err, IsNil) + require.NoError(t, err) gbkToUTF8Data, err := cc.Decode(string(gbkData)) - c.Assert(err, IsNil) - c.Assert(gbkToUTF8Data, DeepEquals, string(utf8Data)) + require.NoError(t, err) + require.Equal(t, string(utf8Data), gbkToUTF8Data) utf8ToGBKData, err := cc.Encode(string(normalCharUTF8MB4)) - c.Assert(err, IsNil) - c.Assert(utf8ToGBKData, DeepEquals, string(normalCharGB18030)) + require.NoError(t, err) + require.Equal(t, string(normalCharGB18030), utf8ToGBKData) } -func (s testCharsetConvertorSuite) TestInvalidCharReplace(c *C) { +func TestInvalidCharReplace(t *testing.T) { dataInvalidCharReplace := "😅😅😅" // Input: 你好invalid char你好 inputData := append(normalCharGB18030, invalidChar...) @@ -71,16 +65,16 @@ func (s testCharsetConvertorSuite) TestInvalidCharReplace(c *C) { expectedData = append(expectedData, normalCharUTF8MB4...) // Prepare the file data. - c.Assert(os.WriteFile(testTempDataFile, inputData, 0666), IsNil) - defer func() { c.Assert(os.Remove(testTempDataFile), IsNil) }() + require.NoError(t, os.WriteFile(testTempDataFile, inputData, 0666)) + defer func() { require.NoError(t, os.Remove(testTempDataFile)) }() gbkReader, err := os.Open(testTempDataFile) - c.Assert(err, IsNil) + require.NoError(t, err) gbkData, err := io.ReadAll(gbkReader) - c.Assert(err, IsNil) + require.NoError(t, err) cc, err := NewCharsetConvertor("gb18030", dataInvalidCharReplace) - c.Assert(err, IsNil) + require.NoError(t, err) gbkToUTF8Data, err := cc.Decode(string(gbkData)) - c.Assert(err, IsNil) - c.Assert(gbkToUTF8Data, DeepEquals, string(expectedData)) + require.NoError(t, err) + require.Equal(t, string(expectedData), gbkToUTF8Data) } diff --git a/br/pkg/lightning/mydump/csv_parser.go b/br/pkg/lightning/mydump/csv_parser.go index 87cbdcfa0d16a..9f6ae18a07c59 100644 --- a/br/pkg/lightning/mydump/csv_parser.go +++ b/br/pkg/lightning/mydump/csv_parser.go @@ -552,12 +552,6 @@ func (parser *CSVParser) ReadColumns() error { return nil } -var newLineASCIISet = makeByteSet([]byte{'\r', '\n'}) - -func indexOfNewLine(b []byte) int { - return IndexAnyByte(b, &newLineASCIISet) -} - // ReadUntilTerminator seeks the file until the terminator token is found, and // returns the file offset beyond the terminator. // This function is used in strict-format dividing a CSV file. diff --git a/br/pkg/lightning/mydump/csv_parser_test.go b/br/pkg/lightning/mydump/csv_parser_test.go index de183ed5fd5d0..8b712865cfed2 100644 --- a/br/pkg/lightning/mydump/csv_parser_test.go +++ b/br/pkg/lightning/mydump/csv_parser_test.go @@ -3,47 +3,31 @@ package mydump_test import ( "context" "encoding/csv" + "fmt" "io" "os" "path/filepath" "strings" + "testing" "unicode/utf8" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) -var _ = Suite(&testMydumpCSVParserSuite{}) +var ioWorkers = worker.NewPool(context.Background(), 5, "test_csv") -type testMydumpCSVParserSuite struct { - ioWorkers *worker.Pool -} - -func (s *testMydumpCSVParserSuite) SetUpSuite(c *C) { - s.ioWorkers = worker.NewPool(context.Background(), 5, "test_csv") -} -func (s *testMydumpCSVParserSuite) TearDownSuite(c *C) {} - -type assertPosEq struct { - *CheckerInfo -} - -var posEq = &assertPosEq{ - &CheckerInfo{Name: "posEq", Params: []string{"parser", "pos", "rowID"}}, -} - -func (checker *assertPosEq) Check(params []interface{}, names []string) (result bool, error string) { - parser := params[0].(mydump.Parser) +func assertPosEqual(t *testing.T, parser mydump.Parser, expectPos, expectRowID int64) { pos, rowID := parser.Pos() - expectedPos := int64(params[1].(int)) - expectedRowID := int64(params[2].(int)) - return pos == expectedPos && rowID == expectedRowID, "" + require.Equal(t, expectPos, pos) + require.Equal(t, expectRowID, rowID) } var nullDatum types.Datum @@ -53,32 +37,31 @@ type testCase struct { expected [][]types.Datum } -func (s *testMydumpCSVParserSuite) runTestCases(c *C, cfg *config.MydumperRuntime, blockBufSize int64, cases []testCase) { +func runTestCasesCSV(t *testing.T, cfg *config.MydumperRuntime, blockBufSize int64, cases []testCase) { for _, tc := range cases { charsetConvertor, err := mydump.NewCharsetConvertor(cfg.DataCharacterSet, cfg.DataInvalidCharReplace) - c.Assert(err, IsNil) - parser, err := mydump.NewCSVParser(&cfg.CSV, mydump.NewStringReader(tc.input), blockBufSize, s.ioWorkers, false, charsetConvertor) - c.Assert(err, IsNil) + assert.NoError(t, err) + parser, err := mydump.NewCSVParser(&cfg.CSV, mydump.NewStringReader(tc.input), blockBufSize, ioWorkers, false, charsetConvertor) + assert.NoError(t, err) for i, row := range tc.expected { - comment := Commentf("input = %q, row = %d", tc.input, i+1) + comment := fmt.Sprintf("input = %q, row = %d", tc.input, i+1) e := parser.ReadRow() - c.Assert(e, IsNil, Commentf("input = %q, row = %d, error = %s", tc.input, i+1, errors.ErrorStack(e))) - c.Assert(parser.LastRow().RowID, DeepEquals, int64(i)+1, comment) - c.Assert(parser.LastRow().Row, DeepEquals, row, comment) - + assert.NoErrorf(t, e, "input = %q, row = %d, error = %s", tc.input, i+1, errors.ErrorStack(e)) + assert.Equal(t, int64(i)+1, parser.LastRow().RowID, comment) + assert.Equal(t, row, parser.LastRow().Row, comment) } - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF, Commentf("input = %q", tc.input)) + assert.ErrorIsf(t, errors.Cause(parser.ReadRow()), io.EOF, "input = %q", tc.input) } } -func (s *testMydumpCSVParserSuite) runFailingTestCases(c *C, cfg *config.MydumperRuntime, blockBufSize int64, cases []string) { +func runFailingTestCasesCSV(t *testing.T, cfg *config.MydumperRuntime, blockBufSize int64, cases []string) { for _, tc := range cases { charsetConvertor, err := mydump.NewCharsetConvertor(cfg.DataCharacterSet, cfg.DataInvalidCharReplace) - c.Assert(err, IsNil) - parser, err := mydump.NewCSVParser(&cfg.CSV, mydump.NewStringReader(tc), blockBufSize, s.ioWorkers, false, charsetConvertor) - c.Assert(err, IsNil) + assert.NoError(t, err) + parser, err := mydump.NewCSVParser(&cfg.CSV, mydump.NewStringReader(tc), blockBufSize, ioWorkers, false, charsetConvertor) + require.NoError(t, err) e := parser.ReadRow() - c.Assert(e, ErrorMatches, "syntax error.*", Commentf("input = %q / %s", tc, errors.ErrorStack(e))) + assert.Regexpf(t, "syntax error.*", e.Error(), "input = %q / %s", tc, errors.ErrorStack(e)) } } @@ -143,7 +126,7 @@ func datumsToString(datums [][]types.Datum, delimitor string, quote string, last return b.String() } -func (s *testMydumpCSVParserSuite) TestTPCH(c *C) { +func TestTPCH(t *testing.T) { datums := tpchDatums() input := datumsToString(datums, "|", "", true) reader := mydump.NewStringReader(input) @@ -154,37 +137,36 @@ func (s *testMydumpCSVParserSuite) TestTPCH(c *C) { TrimLastSep: true, } - parser, err := mydump.NewCSVParser(&cfg, reader, int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) - - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + parser, err := mydump.NewCSVParser(&cfg, reader, int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: datums[0], Length: 116, - }) - c.Assert(parser, posEq, 126, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 126, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: datums[1], Length: 104, - }) - c.Assert(parser, posEq, 241, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 241, 2) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 3, Row: datums[2], Length: 117, - }) - c.Assert(parser, posEq, 369, 3) + }, parser.LastRow()) + assertPosEqual(t, parser, 369, 3) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestTPCHMultiBytes(c *C) { +func TestTPCHMultiBytes(t *testing.T) { datums := tpchDatums() sepsAndQuotes := [][2]string{ {",", ""}, @@ -224,7 +206,7 @@ func (s *testMydumpCSVParserSuite) TestTPCHMultiBytes(c *C) { } allExpectedParserPos = append(allExpectedParserPos, last+pos+1) } - c.Assert(allExpectedParserPos, HasLen, len(datums)) + require.Len(t, allExpectedParserPos, len(datums)) cfg := config.CSVConfig{ Separator: SepAndQuote[0], @@ -233,22 +215,21 @@ func (s *testMydumpCSVParserSuite) TestTPCHMultiBytes(c *C) { } reader := mydump.NewStringReader(inputStr) - parser, err := mydump.NewCSVParser(&cfg, reader, int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err := mydump.NewCSVParser(&cfg, reader, int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) for i, expectedParserPos := range allExpectedParserPos { - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow().RowID, DeepEquals, int64(i+1)) - c.Assert(parser.LastRow().Row, DeepEquals, datums[i]) - - c.Assert(parser, posEq, expectedParserPos, i+1) + require.Nil(t, parser.ReadRow()) + require.Equal(t, int64(i+1), parser.LastRow().RowID) + require.Equal(t, datums[i], parser.LastRow().Row) + assertPosEqual(t, parser, int64(expectedParserPos), int64(i+1)) } - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } } -func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { +func TestRFC4180(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, @@ -256,11 +237,11 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { // example 1, trailing new lines - parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader("aaa,bbb,ccc\nzzz,yyy,xxx\n"), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader("aaa,bbb,ccc\nzzz,yyy,xxx\n"), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("aaa"), @@ -268,11 +249,11 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("ccc"), }, Length: 9, - }) - c.Assert(parser, posEq, 12, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 12, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("zzz"), @@ -280,18 +261,18 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("xxx"), }, Length: 9, - }) - c.Assert(parser, posEq, 24, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 24, 2) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) // example 2, no trailing new lines - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader("aaa,bbb,ccc\nzzz,yyy,xxx"), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader("aaa,bbb,ccc\nzzz,yyy,xxx"), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("aaa"), @@ -299,11 +280,11 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("ccc"), }, Length: 9, - }) - c.Assert(parser, posEq, 12, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 12, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("zzz"), @@ -311,18 +292,18 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("xxx"), }, Length: 9, - }) - c.Assert(parser, posEq, 23, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 23, 2) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) // example 5, quoted fields - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"aaa","bbb","ccc"`+"\nzzz,yyy,xxx"), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"aaa","bbb","ccc"`+"\nzzz,yyy,xxx"), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("aaa"), @@ -330,11 +311,11 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("ccc"), }, Length: 9, - }) - c.Assert(parser, posEq, 18, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 18, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("zzz"), @@ -342,20 +323,20 @@ func (s *testMydumpCSVParserSuite) TestRFC4180(c *C) { types.NewStringDatum("xxx"), }, Length: 9, - }) - c.Assert(parser, posEq, 29, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 29, 2) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) // example 6, line breaks within fields parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"aaa","b bb","ccc" -zzz,yyy,xxx`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) +zzz,yyy,xxx`), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("aaa"), @@ -363,11 +344,11 @@ zzz,yyy,xxx`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) types.NewStringDatum("ccc"), }, Length: 10, - }) - c.Assert(parser, posEq, 19, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 19, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("zzz"), @@ -375,18 +356,18 @@ zzz,yyy,xxx`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) types.NewStringDatum("xxx"), }, Length: 9, - }) - c.Assert(parser, posEq, 30, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 30, 2) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) // example 7, quote escaping - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"aaa","b""bb","ccc"`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"aaa","b""bb","ccc"`), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("aaa"), @@ -394,13 +375,13 @@ zzz,yyy,xxx`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) types.NewStringDatum("ccc"), }, Length: 10, - }) - c.Assert(parser, posEq, 19, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 19, 1) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestMySQL(c *C) { +func TestMySQL(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, @@ -411,11 +392,11 @@ func (s *testMydumpCSVParserSuite) TestMySQL(c *C) { parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(`"\"","\\","\?" "\ -",\N,\\N`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) +",\N,\\N`), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum(`"`), @@ -423,11 +404,11 @@ func (s *testMydumpCSVParserSuite) TestMySQL(c *C) { types.NewStringDatum("?"), }, Length: 6, - }) - c.Assert(parser, posEq, 15, 1) + }, parser.LastRow()) + assertPosEqual(t, parser, 15, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("\n"), @@ -435,13 +416,13 @@ func (s *testMydumpCSVParserSuite) TestMySQL(c *C) { types.NewStringDatum(`\N`), }, Length: 7, - }) - c.Assert(parser, posEq, 26, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 26, 2) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestSyntaxError(c *C) { +func TestSyntaxErrorCSV(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: ",", @@ -462,13 +443,13 @@ func (s *testMydumpCSVParserSuite) TestSyntaxError(c *C) { "\"\x01", } - s.runFailingTestCases(c, &cfg, int64(config.ReadBlockSize), inputs) + runFailingTestCasesCSV(t, &cfg, int64(config.ReadBlockSize), inputs) cfg.CSV.BackslashEscape = false - s.runFailingTestCases(c, &cfg, int64(config.ReadBlockSize), []string{`"\`}) + runFailingTestCasesCSV(t, &cfg, int64(config.ReadBlockSize), []string{`"\`}) } -func (s *testMydumpCSVParserSuite) TestTSV(c *C) { +func TestTSV(t *testing.T) { cfg := config.CSVConfig{ Separator: "\t", Delimiter: "", @@ -481,11 +462,11 @@ func (s *testMydumpCSVParserSuite) TestTSV(c *C) { parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(`a b c d e f 0 foo 0000-00-00 0 foo 0000-00-00 -0 abc def ghi bar 1999-12-31`), int64(config.ReadBlockSize), s.ioWorkers, true, nil) - c.Assert(err, IsNil) +0 abc def ghi bar 1999-12-31`), int64(config.ReadBlockSize), ioWorkers, true, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("0"), @@ -496,12 +477,12 @@ func (s *testMydumpCSVParserSuite) TestTSV(c *C) { types.NewStringDatum("0000-00-00"), }, Length: 14, - }) - c.Assert(parser, posEq, 32, 1) - c.Assert(parser.Columns(), DeepEquals, []string{"a", "b", "c", "d", "e", "f"}) + }, parser.LastRow()) + assertPosEqual(t, parser, 32, 1) + require.Equal(t, []string{"a", "b", "c", "d", "e", "f"}, parser.Columns()) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("0"), @@ -512,11 +493,11 @@ func (s *testMydumpCSVParserSuite) TestTSV(c *C) { types.NewStringDatum("0000-00-00"), }, Length: 14, - }) - c.Assert(parser, posEq, 52, 2) + }, parser.LastRow()) + assertPosEqual(t, parser, 52, 2) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 3, Row: []types.Datum{ types.NewStringDatum("0"), @@ -527,22 +508,22 @@ func (s *testMydumpCSVParserSuite) TestTSV(c *C) { types.NewStringDatum("1999-12-31"), }, Length: 23, - }) - c.Assert(parser, posEq, 80, 3) + }, parser.LastRow()) + assertPosEqual(t, parser, 80, 3) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestCsvWithWhiteSpaceLine(c *C) { +func TestCsvWithWhiteSpaceLine(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, } data := " \r\n\r\n0,,abc\r\n \r\n123,1999-12-31,test\r\n" - parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(data), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(data), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("0"), @@ -550,11 +531,11 @@ func (s *testMydumpCSVParserSuite) TestCsvWithWhiteSpaceLine(c *C) { types.NewStringDatum("abc"), }, Length: 4, - }) + }, parser.LastRow()) - c.Assert(parser, posEq, 12, 1) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + assertPosEqual(t, parser, 12, 1) + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewStringDatum("123"), @@ -562,16 +543,16 @@ func (s *testMydumpCSVParserSuite) TestCsvWithWhiteSpaceLine(c *C) { types.NewStringDatum("test"), }, Length: 17, - }) - c.Assert(parser.Close(), IsNil) + }, parser.LastRow()) + require.Nil(t, parser.Close()) cfg.Header = true data = " \r\na,b,c\r\n0,,abc\r\n" - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(data), int64(config.ReadBlockSize), s.ioWorkers, true, nil) - c.Assert(err, IsNil) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.Columns(), DeepEquals, []string{"a", "b", "c"}) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(data), int64(config.ReadBlockSize), ioWorkers, true, nil) + require.NoError(t, err) + require.Nil(t, parser.ReadRow()) + require.Equal(t, []string{"a", "b", "c"}, parser.Columns()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum("0"), @@ -579,84 +560,84 @@ func (s *testMydumpCSVParserSuite) TestCsvWithWhiteSpaceLine(c *C) { types.NewStringDatum("abc"), }, Length: 4, - }) + }, parser.LastRow()) - c.Assert(parser, posEq, 17, 1) - c.Assert(parser.Close(), IsNil) + assertPosEqual(t, parser, 17, 1) + require.Nil(t, parser.Close()) } -func (s *testMydumpCSVParserSuite) TestEmpty(c *C) { +func TestEmpty(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, } - parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(""), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(""), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) // Try again with headers. cfg.Header = true - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(""), int64(config.ReadBlockSize), s.ioWorkers, true, nil) - c.Assert(err, IsNil) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader(""), int64(config.ReadBlockSize), ioWorkers, true, nil) + require.NoError(t, err) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) - parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader("h\n"), int64(config.ReadBlockSize), s.ioWorkers, true, nil) - c.Assert(err, IsNil) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + parser, err = mydump.NewCSVParser(&cfg, mydump.NewStringReader("h\n"), int64(config.ReadBlockSize), ioWorkers, true, nil) + require.NoError(t, err) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestCRLF(c *C) { +func TestCRLF(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, } - parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader("a\rb\r\nc\n\n\n\nd"), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader("a\rb\r\nc\n\n\n\nd"), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{types.NewStringDatum("a")}, Length: 1, - }) + }, parser.LastRow()) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{types.NewStringDatum("b")}, Length: 1, - }) + }, parser.LastRow()) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 3, Row: []types.Datum{types.NewStringDatum("c")}, Length: 1, - }) + }, parser.LastRow()) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 4, Row: []types.Datum{types.NewStringDatum("d")}, Length: 1, - }) + }, parser.LastRow()) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestQuotedSeparator(c *C) { +func TestQuotedSeparator(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, } - parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(`",",','`), int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + parser, err := mydump.NewCSVParser(&cfg, mydump.NewStringReader(`",",','`), int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) + require.Nil(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewStringDatum(","), @@ -664,12 +645,12 @@ func (s *testMydumpCSVParserSuite) TestQuotedSeparator(c *C) { types.NewStringDatum("'"), }, Length: 3, - }) + }, parser.LastRow()) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpCSVParserSuite) TestConsecutiveFields(c *C) { +func TestConsecutiveFields(t *testing.T) { // Note: the behavior of reading `"xxx"yyy` here is undefined in RFC 4180. // Python's CSV module returns `xxxyyy`. // Rust's CSV package returns `xxxyyy`. @@ -691,15 +672,15 @@ func (s *testMydumpCSVParserSuite) TestConsecutiveFields(c *C) { `abc""`, } - s.runFailingTestCases(c, &cfg, int64(config.ReadBlockSize), testCases) + runFailingTestCasesCSV(t, &cfg, int64(config.ReadBlockSize), testCases) cfg.CSV.Delimiter = "|+|" - s.runFailingTestCases(c, &cfg, int64(config.ReadBlockSize), []string{ + runFailingTestCasesCSV(t, &cfg, int64(config.ReadBlockSize), []string{ "abc|1|+||+|\r\n", }) } -func (s *testMydumpCSVParserSuite) TestSpecialChars(c *C) { +func TestSpecialChars(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{Separator: ",", Delimiter: `"`}, } @@ -734,10 +715,10 @@ func (s *testMydumpCSVParserSuite) TestSpecialChars(c *C) { }, } - s.runTestCases(c, &cfg, int64(config.ReadBlockSize), testCases) + runTestCasesCSV(t, &cfg, int64(config.ReadBlockSize), testCases) } -func (s *testMydumpCSVParserSuite) TestContinuation(c *C) { +func TestContinuationCSV(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: ",", @@ -769,10 +750,10 @@ func (s *testMydumpCSVParserSuite) TestContinuation(c *C) { }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) } -func (s *testMydumpCSVParserSuite) TestBackslashAsSep(c *C) { +func TestBackslashAsSep(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: `\`, @@ -791,15 +772,15 @@ func (s *testMydumpCSVParserSuite) TestBackslashAsSep(c *C) { }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) failingInputs := []string{ `"\`, } - s.runFailingTestCases(c, &cfg, 1, failingInputs) + runFailingTestCasesCSV(t, &cfg, 1, failingInputs) } -func (s *testMydumpCSVParserSuite) TestBackslashAsDelim(c *C) { +func TestBackslashAsDelim(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: ",", @@ -813,12 +794,12 @@ func (s *testMydumpCSVParserSuite) TestBackslashAsDelim(c *C) { expected: [][]types.Datum{{nullDatum}}, }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) failingInputs := []string{ `"\`, } - s.runFailingTestCases(c, &cfg, 1, failingInputs) + runFailingTestCasesCSV(t, &cfg, 1, failingInputs) } // errorReader implements the Reader interface which always returns an error. @@ -836,19 +817,19 @@ func (*errorReader) Close() error { return errors.New("fake close error") } -func (s *testMydumpCSVParserSuite) TestReadError(c *C) { +func TestReadError(t *testing.T) { cfg := config.CSVConfig{ Separator: ",", Delimiter: `"`, } - parser, err := mydump.NewCSVParser(&cfg, &errorReader{}, int64(config.ReadBlockSize), s.ioWorkers, false, nil) - c.Assert(err, IsNil) - c.Assert(parser.ReadRow(), ErrorMatches, "fake read error") + parser, err := mydump.NewCSVParser(&cfg, &errorReader{}, int64(config.ReadBlockSize), ioWorkers, false, nil) + require.NoError(t, err) + require.Regexp(t, "fake read error", parser.ReadRow().Error()) } // TestSyntaxErrorLog checks that a syntax error won't dump huge strings into the log. -func (s *testMydumpCSVParserSuite) TestSyntaxErrorLog(c *C) { +func TestSyntaxErrorLog(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: "\t", @@ -857,21 +838,21 @@ func (s *testMydumpCSVParserSuite) TestSyntaxErrorLog(c *C) { } tc := mydump.NewStringReader("x'" + strings.Repeat("y", 50000)) - parser, err := mydump.NewCSVParser(&cfg.CSV, tc, 50000, s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err := mydump.NewCSVParser(&cfg.CSV, tc, 50000, ioWorkers, false, nil) + require.NoError(t, err) logger, buffer := log.MakeTestLogger() parser.SetLogger(logger) - c.Assert(parser.ReadRow(), ErrorMatches, "syntax error.*") - c.Assert(logger.Sync(), IsNil) + require.Regexp(t, "syntax error.*", parser.ReadRow().Error()) + require.Nil(t, logger.Sync()) - c.Assert( - buffer.Stripped(), Equals, + require.Equal(t, `{"$lvl":"ERROR","$msg":"syntax error","pos":2,"content":"`+strings.Repeat("y", 256)+`"}`, + buffer.Stripped(), ) } // TestTrimLastSep checks that set `TrimLastSep` to true trim only the last empty filed. -func (s *testMydumpCSVParserSuite) TestTrimLastSep(c *C) { +func TestTrimLastSep(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: ",", @@ -883,19 +864,19 @@ func (s *testMydumpCSVParserSuite) TestTrimLastSep(c *C) { &cfg.CSV, mydump.NewStringReader("123,456,789,\r\na,b,,\r\n,,,\r\n\"a\",\"\",\"\",\r\n"), int64(config.ReadBlockSize), - s.ioWorkers, + ioWorkers, false, nil, ) - c.Assert(err, IsNil) + require.NoError(t, err) for i := 0; i < 4; i++ { - c.Assert(parser.ReadRow(), IsNil) - c.Assert(len(parser.LastRow().Row), Equals, 3) + require.Nil(t, parser.ReadRow()) + require.Len(t, parser.LastRow().Row, 3) } } // TestTerminator checks for customized terminators. -func (s *testMydumpCSVParserSuite) TestTerminator(c *C) { +func TestTerminator(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: "|+|", @@ -913,7 +894,7 @@ func (s *testMydumpCSVParserSuite) TestTerminator(c *C) { }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) cfg.CSV.Delimiter = "|+>" @@ -926,10 +907,10 @@ func (s *testMydumpCSVParserSuite) TestTerminator(c *C) { }, }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) } -func (s *testMydumpCSVParserSuite) TestCharsetConversion(c *C) { +func TestCharsetConversion(t *testing.T) { cfg := config.MydumperRuntime{ CSV: config.CSVConfig{ Separator: ",", @@ -939,14 +920,14 @@ func (s *testMydumpCSVParserSuite) TestCharsetConversion(c *C) { DataInvalidCharReplace: string(utf8.RuneError), } charsetConvertor, err := mydump.NewCharsetConvertor(cfg.DataCharacterSet, cfg.DataInvalidCharReplace) - c.Assert(err, IsNil) + require.NoError(t, err) originalInputPart1 := `ä¸è¦æ¸©é©¯åœ°èµ°è¿›é‚£ä¸ªè‰¯å¤œï¼Œè€å¹´åº”当在日暮时燃烧咆哮,怒斥,怒斥光明的消é€ã€‚ ` originalInputPart2 := `虽然智慧的人临终时懂得黑暗有ç†ï¼Œå› ä¸ºä»–们的è¯æ²¡æœ‰è¿¸å‘出闪电,他们也并ä¸æ¸©é©¯åœ°èµ°è¿›é‚£ä¸ªè‰¯å¤œã€‚ ` // Insert an invalid char to test DataInvalidCharReplace. rawInput, err := charsetConvertor.Encode(originalInputPart1 + string([]byte{0x99}) + originalInputPart2) - c.Assert(err, IsNil) + require.NoError(t, err) testCases := []testCase{ { @@ -963,7 +944,7 @@ func (s *testMydumpCSVParserSuite) TestCharsetConversion(c *C) { }, } - s.runTestCases(c, &cfg, 1, testCases) + runTestCasesCSV(t, &cfg, 1, testCases) } // Run `go test github.com/pingcap/br/pkg/lightning/mydump -check.b -check.bmem -test.v` to get benchmark result. @@ -974,37 +955,35 @@ type benchCSVParserSuite struct { ioWorkers *worker.Pool } -var _ = Suite(&benchCSVParserSuite{}) - -func (s *benchCSVParserSuite) setupTest(c *C) { +func newBenchCSVParserSuite(b *testing.B) *benchCSVParserSuite { + var s benchCSVParserSuite s.ioWorkers = worker.NewPool(context.Background(), 5, "bench_csv") - - dir := c.MkDir() + dir := b.TempDir() s.csvPath = filepath.Join(dir, "input.csv") file, err := os.Create(s.csvPath) - c.Assert(err, IsNil) + require.NoError(b, err) defer func() { - c.Assert(file.Close(), IsNil) + require.NoError(b, file.Close()) }() - for i := 0; i < c.N; i++ { + for i := 0; i < b.N; i++ { _, err = file.WriteString("18,1,1,0.3650,GC,BARBARBAR,rw9AOV1AjoI1,50000.00,-10.00,10.00,1,1,djj3Q2XaIPoYVy1FuF,gc80Q2o82Au3C9xv,PYOolSxG3w,DI,265111111,7586538936787184,2020-02-26 20:06:00.193,OE,YCkSPBVqoJ2V5F8zWs87V5XzbaIY70aWCD4dgcB6bjUzCr5wOJCJ2TYH49J7yWyysbudJIxlTAEWSJahY7hswLtTsqyjEkrlsN8iDMAa9Poj29miJ08tnn2G8mL64IlyywvnRGbLbyGvWDdrOSF42RyUFTWVyqlDWc6Gr5wyMPYgvweKemzFDVD3kro5JsmBmJY08EK54nQoyfo2sScyb34zcM9GFo9ZQTwloINfPYQKXQm32m0XvU7jiNmYpFTFJQjdqA825SEvQqMMefG2WG4jVu9UPdhdUjRsFRd0Gw7YPKByOlcuY0eKxT7sAzMKXx2000RR6dqHNXe47oVYd\n") - c.Assert(err, IsNil) + require.NoError(b, err) } - c.ResetTimer() + return &s } -func (s *benchCSVParserSuite) BenchmarkReadRowUsingMydumpCSVParser(c *C) { - s.setupTest(c) +func BenchmarkReadRowUsingMydumpCSVParser(b *testing.B) { + s := newBenchCSVParserSuite(b) file, err := os.Open(s.csvPath) - c.Assert(err, IsNil) + require.NoError(b, err) defer func() { - c.Assert(file.Close(), IsNil) + require.NoError(b, file.Close()) }() cfg := config.CSVConfig{Separator: ","} - parser, err := mydump.NewCSVParser(&cfg, file, 65536, s.ioWorkers, false, nil) - c.Assert(err, IsNil) + parser, err := mydump.NewCSVParser(&cfg, file, 65536, ioWorkers, false, nil) + require.NoError(b, err) parser.SetLogger(log.Logger{Logger: zap.NewNop()}) rowsCount := 0 @@ -1018,18 +997,18 @@ func (s *benchCSVParserSuite) BenchmarkReadRowUsingMydumpCSVParser(c *C) { if errors.Cause(err) == io.EOF { break } - c.Fatal(err) + b.Fatal(err) } - c.Assert(rowsCount, Equals, c.N) + require.Equal(b, b.N, rowsCount) } -func (s *benchCSVParserSuite) BenchmarkReadRowUsingEncodingCSV(c *C) { - s.setupTest(c) +func BenchmarkReadRowUsingEncodingCSV(b *testing.B) { + s := newBenchCSVParserSuite(b) file, err := os.Open(s.csvPath) - c.Assert(err, IsNil) + require.NoError(b, err) defer func() { - c.Assert(file.Close(), IsNil) + require.Nil(b, file.Close()) }() csvParser := csv.NewReader(file) @@ -1050,7 +1029,7 @@ func (s *benchCSVParserSuite) BenchmarkReadRowUsingEncodingCSV(c *C) { if errors.Cause(err) == io.EOF { break } - c.Fatal(err) + b.Fatal(err) } - c.Assert(rowsCount, Equals, c.N) + require.Equal(b, b.N, rowsCount) } diff --git a/br/pkg/lightning/mydump/loader.go b/br/pkg/lightning/mydump/loader.go index 27bab8fa5cf7b..14f9071e916c7 100644 --- a/br/pkg/lightning/mydump/loader.go +++ b/br/pkg/lightning/mydump/loader.go @@ -18,24 +18,44 @@ import ( "context" "path/filepath" "sort" + "strings" "github.com/pingcap/errors" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - router "github.com/pingcap/tidb-tools/pkg/table-router" + "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/storage" + regexprrouter "github.com/pingcap/tidb/util/regexpr-router" + filter "github.com/pingcap/tidb/util/table-filter" "go.uber.org/zap" ) type MDDatabaseMeta struct { Name string - SchemaFile string + SchemaFile FileInfo Tables []*MDTableMeta Views []*MDTableMeta charSet string } +func (m *MDDatabaseMeta) GetSchema(ctx context.Context, store storage.ExternalStorage) string { + schema, err := ExportStatement(ctx, store, m.SchemaFile, m.charSet) + if err != nil { + log.L().Warn("failed to extract table schema", + zap.String("Path", m.SchemaFile.FileMeta.Path), + log.ShortError(err), + ) + schema = nil + } + schemaStr := strings.TrimSpace(string(schema)) + // set default if schema sql is empty + if len(schemaStr) == 0 { + schemaStr = "CREATE DATABASE IF NOT EXISTS " + common.EscapeIdentifier(m.Name) + } + + return schemaStr +} + type MDTableMeta struct { DB string Name string @@ -71,10 +91,11 @@ func (m *MDTableMeta) GetSchema(ctx context.Context, store storage.ExternalStora Mydumper File Loader */ type MDLoader struct { - store storage.ExternalStorage - dbs []*MDDatabaseMeta - filter filter.Filter - router *router.Table + store storage.ExternalStorage + dbs []*MDDatabaseMeta + filter filter.Filter + // router *router.Table + router *regexprrouter.RouteTable fileRouter FileRouter charSet string } @@ -92,28 +113,28 @@ type mdLoaderSetup struct { func NewMyDumpLoader(ctx context.Context, cfg *config.Config) (*MDLoader, error) { u, err := storage.ParseBackend(cfg.Mydumper.SourceDir, nil) if err != nil { - return nil, errors.Trace(err) + return nil, common.NormalizeError(err) } s, err := storage.New(ctx, u, &storage.ExternalStorageOptions{}) if err != nil { - return nil, errors.Trace(err) + return nil, common.NormalizeError(err) } return NewMyDumpLoaderWithStore(ctx, cfg, s) } func NewMyDumpLoaderWithStore(ctx context.Context, cfg *config.Config, store storage.ExternalStorage) (*MDLoader, error) { - var r *router.Table + var r *regexprrouter.RouteTable var err error if len(cfg.Routes) > 0 && len(cfg.Mydumper.FileRouters) > 0 { - return nil, errors.New("table route is deprecated, can't config both [routes] and [mydumper.files]") + return nil, common.ErrInvalidConfig.GenWithStack("table route is deprecated, can't config both [routes] and [mydumper.files]") } if len(cfg.Routes) > 0 { - r, err = router.NewTableRouter(cfg.Mydumper.CaseSensitive, cfg.Routes) + r, err = regexprrouter.NewRegExprRouter(cfg.Mydumper.CaseSensitive, cfg.Routes) if err != nil { - return nil, errors.Trace(err) + return nil, common.ErrInvalidConfig.Wrap(err).GenWithStack("invalid table route rule") } } @@ -125,7 +146,7 @@ func NewMyDumpLoaderWithStore(ctx context.Context, cfg *config.Config, store sto f, err = filter.Parse(cfg.Mydumper.Filter) } if err != nil { - return nil, errors.Annotate(err, "parse filter failed") + return nil, common.ErrInvalidConfig.Wrap(err).GenWithStack("parse filter failed") } if !cfg.Mydumper.CaseSensitive { f = filter.CaseInsensitive(f) @@ -138,7 +159,7 @@ func NewMyDumpLoaderWithStore(ctx context.Context, cfg *config.Config, store sto fileRouter, err := NewFileRouter(fileRouteRules) if err != nil { - return nil, errors.Annotate(err, "parser file routing rule failed") + return nil, common.ErrInvalidConfig.Wrap(err).GenWithStack("parse file routing rule failed") } mdl := &MDLoader{ @@ -210,17 +231,17 @@ func (s *mdLoaderSetup) setup(ctx context.Context, store storage.ExternalStorage sql —— {db}.{table}.{part}.sql / {db}.{table}.sql */ if err := s.listFiles(ctx, store); err != nil { - return errors.Annotate(err, "list file failed") + return common.ErrStorageUnknown.Wrap(err).GenWithStack("list file failed") } if err := s.route(); err != nil { - return errors.Trace(err) + return common.ErrTableRoute.Wrap(err).GenWithStackByArgs() } // setup database schema if len(s.dbSchemas) != 0 { for _, fileInfo := range s.dbSchemas { - if _, dbExists := s.insertDB(fileInfo.TableName.Schema, fileInfo.FileMeta.Path); dbExists && s.loader.router == nil { - return errors.Errorf("invalid database schema file, duplicated item - %s", fileInfo.FileMeta.Path) + if _, dbExists := s.insertDB(fileInfo); dbExists && s.loader.router == nil { + return common.ErrInvalidSchemaFile.GenWithStack("invalid database schema file, duplicated item - %s", fileInfo.FileMeta.Path) } } } @@ -229,7 +250,7 @@ func (s *mdLoaderSetup) setup(ctx context.Context, store storage.ExternalStorage // setup table schema for _, fileInfo := range s.tableSchemas { if _, _, tableExists := s.insertTable(fileInfo); tableExists && s.loader.router == nil { - return errors.Errorf("invalid table schema file, duplicated item - %s", fileInfo.FileMeta.Path) + return common.ErrInvalidSchemaFile.GenWithStack("invalid table schema file, duplicated item - %s", fileInfo.FileMeta.Path) } } } @@ -241,7 +262,7 @@ func (s *mdLoaderSetup) setup(ctx context.Context, store storage.ExternalStorage if !tableExists { // we are not expect the user only has view schema without table schema when user use dumpling to get view. // remove the last `-view.sql` from path as the relate table schema file path - return errors.Errorf("invalid view schema file, miss host table schema for view '%s'", fileInfo.TableName.Name) + return common.ErrInvalidSchemaFile.GenWithStack("invalid view schema file, miss host table schema for view '%s'", fileInfo.TableName.Name) } } } @@ -406,15 +427,15 @@ func (s *mdLoaderSetup) route() error { return nil } -func (s *mdLoaderSetup) insertDB(dbName string, path string) (*MDDatabaseMeta, bool) { - dbIndex, ok := s.dbIndexMap[dbName] +func (s *mdLoaderSetup) insertDB(f FileInfo) (*MDDatabaseMeta, bool) { + dbIndex, ok := s.dbIndexMap[f.TableName.Schema] if ok { return s.loader.dbs[dbIndex], true } - s.dbIndexMap[dbName] = len(s.loader.dbs) + s.dbIndexMap[f.TableName.Schema] = len(s.loader.dbs) ptr := &MDDatabaseMeta{ - Name: dbName, - SchemaFile: path, + Name: f.TableName.Schema, + SchemaFile: f, charSet: s.loader.charSet, } s.loader.dbs = append(s.loader.dbs, ptr) @@ -422,7 +443,13 @@ func (s *mdLoaderSetup) insertDB(dbName string, path string) (*MDDatabaseMeta, b } func (s *mdLoaderSetup) insertTable(fileInfo FileInfo) (*MDTableMeta, bool, bool) { - dbMeta, dbExists := s.insertDB(fileInfo.TableName.Schema, "") + dbFileInfo := FileInfo{ + TableName: filter.Table{ + Schema: fileInfo.TableName.Schema, + }, + FileMeta: SourceFileMeta{Type: SourceTypeSchemaSchema}, + } + dbMeta, dbExists := s.insertDB(dbFileInfo) tableIndex, ok := s.tableIndexMap[fileInfo.TableName] if ok { return dbMeta.Tables[tableIndex], dbExists, true @@ -442,7 +469,13 @@ func (s *mdLoaderSetup) insertTable(fileInfo FileInfo) (*MDTableMeta, bool, bool } func (s *mdLoaderSetup) insertView(fileInfo FileInfo) (bool, bool) { - dbMeta, dbExists := s.insertDB(fileInfo.TableName.Schema, "") + dbFileInfo := FileInfo{ + TableName: filter.Table{ + Schema: fileInfo.TableName.Schema, + }, + FileMeta: SourceFileMeta{Type: SourceTypeSchemaSchema}, + } + dbMeta, dbExists := s.insertDB(dbFileInfo) _, ok := s.tableIndexMap[fileInfo.TableName] if ok { meta := &MDTableMeta{ diff --git a/br/pkg/lightning/mydump/loader_test.go b/br/pkg/lightning/mydump/loader_test.go index 76bc50eba2793..23561dd6edae2 100644 --- a/br/pkg/lightning/mydump/loader_test.go +++ b/br/pkg/lightning/mydump/loader_test.go @@ -20,28 +20,20 @@ import ( "path/filepath" "testing" - . "github.com/pingcap/check" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - router "github.com/pingcap/tidb-tools/pkg/table-router" "github.com/pingcap/tidb/br/pkg/lightning/config" md "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/storage" + filter "github.com/pingcap/tidb/util/table-filter" + router "github.com/pingcap/tidb/util/table-router" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMydumpLoaderSuite{}) - -func TestMydumps(t *testing.T) { - TestingT(t) -} - type testMydumpLoaderSuite struct { cfg *config.Config sourceDir string } -func (s *testMydumpLoaderSuite) SetUpSuite(c *C) {} -func (s *testMydumpLoaderSuite) TearDownSuite(c *C) {} - func newConfigWithSourceDir(sourceDir string) *config.Config { path, _ := filepath.Abs(sourceDir) return &config.Config{ @@ -53,42 +45,46 @@ func newConfigWithSourceDir(sourceDir string) *config.Config { } } -func (s *testMydumpLoaderSuite) SetUpTest(c *C) { - s.sourceDir = c.MkDir() +func newTestMydumpLoaderSuite(t *testing.T) *testMydumpLoaderSuite { + var s testMydumpLoaderSuite + var err error + s.sourceDir = t.TempDir() + require.Nil(t, err) s.cfg = newConfigWithSourceDir(s.sourceDir) + return &s } -func (s *testMydumpLoaderSuite) touch(c *C, filename ...string) { +func (s *testMydumpLoaderSuite) touch(t *testing.T, filename ...string) { components := make([]string, len(filename)+1) components = append(components, s.sourceDir) components = append(components, filename...) path := filepath.Join(components...) err := os.WriteFile(path, nil, 0o644) - c.Assert(err, IsNil) + require.Nil(t, err) } -func (s *testMydumpLoaderSuite) mkdir(c *C, dirname string) { +func (s *testMydumpLoaderSuite) mkdir(t *testing.T, dirname string) { path := filepath.Join(s.sourceDir, dirname) err := os.Mkdir(path, 0o755) - c.Assert(err, IsNil) + require.Nil(t, err) } -func (s *testMydumpLoaderSuite) TestLoader(c *C) { +func TestLoader(t *testing.T) { ctx := context.Background() cfg := newConfigWithSourceDir("./not-exists") _, err := md.NewMyDumpLoader(ctx, cfg) // will check schema in tidb and data file later in DataCheck. - c.Assert(err, IsNil) + require.NoError(t, err) cfg = newConfigWithSourceDir("./examples") mdl, err := md.NewMyDumpLoader(ctx, cfg) - c.Assert(err, IsNil) + require.NoError(t, err) dbMetas := mdl.GetDatabases() - c.Assert(len(dbMetas), Equals, 1) + require.Len(t, dbMetas, 1) dbMeta := dbMetas[0] - c.Assert(dbMeta.Name, Equals, "mocker_test") - c.Assert(len(dbMeta.Tables), Equals, 4) + require.Equal(t, "mocker_test", dbMeta.Name) + require.Len(t, dbMeta.Tables, 4) expected := []struct { name string @@ -101,18 +97,19 @@ func (s *testMydumpLoaderSuite) TestLoader(c *C) { } for i, table := range expected { - c.Assert(dbMeta.Tables[i].Name, Equals, table.name) - c.Assert(len(dbMeta.Tables[i].DataFiles), Equals, table.dataFiles) + assert.Equal(t, table.name, dbMeta.Tables[i].Name) + assert.Equal(t, table.dataFiles, len(dbMeta.Tables[i].DataFiles)) } } -func (s *testMydumpLoaderSuite) TestEmptyDB(c *C) { +func TestEmptyDB(t *testing.T) { + s := newTestMydumpLoaderSuite(t) _, err := md.NewMyDumpLoader(context.Background(), s.cfg) // will check schema in tidb and data file later in DataCheck. - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testMydumpLoaderSuite) TestDuplicatedDB(c *C) { +func TestDuplicatedDB(t *testing.T) { /* Path/ a/ @@ -120,33 +117,35 @@ func (s *testMydumpLoaderSuite) TestDuplicatedDB(c *C) { b/ db-schema-create.sql */ - s.mkdir(c, "a") - s.touch(c, "a", "db-schema-create.sql") - s.mkdir(c, "b") - s.touch(c, "b", "db-schema-create.sql") + s := newTestMydumpLoaderSuite(t) + s.mkdir(t, "a") + s.touch(t, "a", "db-schema-create.sql") + s.mkdir(t, "b") + s.touch(t, "b", "db-schema-create.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, ErrorMatches, `invalid database schema file, duplicated item - .*[/\\]db-schema-create\.sql`) + require.Regexp(t, `invalid database schema file, duplicated item - .*[/\\]db-schema-create\.sql`, err) } -func (s *testMydumpLoaderSuite) TestTableNoHostDB(c *C) { +func TestTableNoHostDB(t *testing.T) { /* Path/ notdb-schema-create.sql db.tbl-schema.sql */ + s := newTestMydumpLoaderSuite(t) dir := s.sourceDir err := os.WriteFile(filepath.Join(dir, "notdb-schema-create.sql"), nil, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) err = os.WriteFile(filepath.Join(dir, "db.tbl-schema.sql"), nil, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testMydumpLoaderSuite) TestDuplicatedTable(c *C) { +func TestDuplicatedTable(t *testing.T) { /* Path/ db-schema-create.sql @@ -155,125 +154,144 @@ func (s *testMydumpLoaderSuite) TestDuplicatedTable(c *C) { b/ db.tbl-schema.sql */ + s := newTestMydumpLoaderSuite(t) - s.touch(c, "db-schema-create.sql") - s.mkdir(c, "a") - s.touch(c, "a", "db.tbl-schema.sql") - s.mkdir(c, "b") - s.touch(c, "b", "db.tbl-schema.sql") + s.touch(t, "db-schema-create.sql") + s.mkdir(t, "a") + s.touch(t, "a", "db.tbl-schema.sql") + s.mkdir(t, "b") + s.touch(t, "b", "db.tbl-schema.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, ErrorMatches, `invalid table schema file, duplicated item - .*db\.tbl-schema\.sql`) + require.Regexp(t, `invalid table schema file, duplicated item - .*db\.tbl-schema\.sql`, err) } -func (s *testMydumpLoaderSuite) TestTableInfoNotFound(c *C) { +func TestTableInfoNotFound(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + s.cfg.Mydumper.CharacterSet = "auto" - s.touch(c, "db-schema-create.sql") - s.touch(c, "db.tbl-schema.sql") + s.touch(t, "db-schema-create.sql") + s.touch(t, "db.tbl-schema.sql") ctx := context.Background() store, err := storage.NewLocalStorage(s.sourceDir) - c.Assert(err, IsNil) + require.NoError(t, err) loader, err := md.NewMyDumpLoader(ctx, s.cfg) - c.Assert(err, IsNil) + require.NoError(t, err) for _, dbMeta := range loader.GetDatabases() { + dbSQL := dbMeta.GetSchema(ctx, store) + require.Equal(t, "CREATE DATABASE IF NOT EXISTS `db`", dbSQL) for _, tblMeta := range dbMeta.Tables { sql, err := tblMeta.GetSchema(ctx, store) - c.Assert(sql, Equals, "") - c.Assert(err, IsNil) + require.Equal(t, "", sql) + require.NoError(t, err) } } } -func (s *testMydumpLoaderSuite) TestTableUnexpectedError(c *C) { - s.touch(c, "db-schema-create.sql") - s.touch(c, "db.tbl-schema.sql") +func TestTableUnexpectedError(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + s.touch(t, "db-schema-create.sql") + s.touch(t, "db.tbl-schema.sql") ctx := context.Background() store, err := storage.NewLocalStorage(s.sourceDir) - c.Assert(err, IsNil) + require.NoError(t, err) loader, err := md.NewMyDumpLoader(ctx, s.cfg) - c.Assert(err, IsNil) + require.NoError(t, err) for _, dbMeta := range loader.GetDatabases() { for _, tblMeta := range dbMeta.Tables { sql, err := tblMeta.GetSchema(ctx, store) - c.Assert(sql, Equals, "") - c.Assert(err, ErrorMatches, "failed to decode db.tbl-schema.sql as : Unsupported encoding ") + require.Equal(t, "", sql) + require.Contains(t, err.Error(), "failed to decode db.tbl-schema.sql as : Unsupported encoding ") } } } -func (s *testMydumpLoaderSuite) TestDataNoHostDB(c *C) { +func TestDataNoHostDB(t *testing.T) { /* Path/ notdb-schema-create.sql db.tbl.sql */ + s := newTestMydumpLoaderSuite(t) - s.touch(c, "notdb-schema-create.sql") - s.touch(c, "db.tbl.sql") + s.touch(t, "notdb-schema-create.sql") + s.touch(t, "db.tbl.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) // will check schema in tidb and data file later in DataCheck. - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testMydumpLoaderSuite) TestDataNoHostTable(c *C) { +func TestDataNoHostTable(t *testing.T) { /* Path/ db-schema-create.sql db.tbl.sql */ + s := newTestMydumpLoaderSuite(t) - s.touch(c, "db-schema-create.sql") - s.touch(c, "db.tbl.sql") + s.touch(t, "db-schema-create.sql") + s.touch(t, "db.tbl.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) // will check schema in tidb and data file later in DataCheck. - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testMydumpLoaderSuite) TestViewNoHostDB(c *C) { +func TestViewNoHostDB(t *testing.T) { /* Path/ notdb-schema-create.sql db.tbl-schema-view.sql */ - s.touch(c, "notdb-schema-create.sql") - s.touch(c, "db.tbl-schema-view.sql") + s := newTestMydumpLoaderSuite(t) + + s.touch(t, "notdb-schema-create.sql") + s.touch(t, "db.tbl-schema-view.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, ErrorMatches, `invalid view schema file, miss host table schema for view 'tbl'`) + require.Contains(t, err.Error(), `invalid view schema file, miss host table schema for view 'tbl'`) } -func (s *testMydumpLoaderSuite) TestViewNoHostTable(c *C) { +func TestViewNoHostTable(t *testing.T) { /* Path/ db-schema-create.sql db.tbl-schema-view.sql */ + s := newTestMydumpLoaderSuite(t) - s.touch(c, "db-schema-create.sql") - s.touch(c, "db.tbl-schema-view.sql") + s.touch(t, "db-schema-create.sql") + s.touch(t, "db.tbl-schema-view.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, ErrorMatches, `invalid view schema file, miss host table schema for view 'tbl'`) + require.Contains(t, err.Error(), `invalid view schema file, miss host table schema for view 'tbl'`) } -func (s *testMydumpLoaderSuite) TestDataWithoutSchema(c *C) { +func TestDataWithoutSchema(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + dir := s.sourceDir p := filepath.Join(dir, "db.tbl.sql") err := os.WriteFile(p, nil, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, IsNil) - c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{ - Name: "db", - SchemaFile: "", + require.NoError(t, err) + require.Equal(t, []*md.MDDatabaseMeta{{ + Name: "db", + SchemaFile: md.FileInfo{ + TableName: filter.Table{ + Schema: "db", + Name: "", + }, + FileMeta: md.SourceFileMeta{Type: md.SourceTypeSchemaSchema}, + }, Tables: []*md.MDTableMeta{{ DB: "db", Name: "tbl", @@ -282,27 +300,29 @@ func (s *testMydumpLoaderSuite) TestDataWithoutSchema(c *C) { IsRowOrdered: true, IndexRatio: 0.0, }}, - }}) + }}, mdl.GetDatabases()) } -func (s *testMydumpLoaderSuite) TestTablesWithDots(c *C) { - s.touch(c, "db-schema-create.sql") - s.touch(c, "db.tbl.with.dots-schema.sql") - s.touch(c, "db.tbl.with.dots.0001.sql") - s.touch(c, "db.0002-schema.sql") - s.touch(c, "db.0002.sql") +func TestTablesWithDots(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + + s.touch(t, "db-schema-create.sql") + s.touch(t, "db.tbl.with.dots-schema.sql") + s.touch(t, "db.tbl.with.dots.0001.sql") + s.touch(t, "db.0002-schema.sql") + s.touch(t, "db.0002.sql") // insert some tables with file name structures which we're going to ignore. - s.touch(c, "db.v-schema-trigger.sql") - s.touch(c, "db.v-schema-post.sql") - s.touch(c, "db.sql") - s.touch(c, "db-schema.sql") + s.touch(t, "db.v-schema-trigger.sql") + s.touch(t, "db.v-schema-post.sql") + s.touch(t, "db.sql") + s.touch(t, "db-schema.sql") mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, IsNil) - c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{ + require.NoError(t, err) + require.Equal(t, []*md.MDDatabaseMeta{{ Name: "db", - SchemaFile: "db-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: ""}, FileMeta: md.SourceFileMeta{Path: "db-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "db", @@ -321,10 +341,11 @@ func (s *testMydumpLoaderSuite) TestTablesWithDots(c *C) { IndexRatio: 0.0, }, }, - }}) + }}, mdl.GetDatabases()) } -func (s *testMydumpLoaderSuite) TestRouter(c *C) { +func TestRouter(t *testing.T) { + s := newTestMydumpLoaderSuite(t) s.cfg.Routes = []*router.TableRule{ { SchemaPattern: "a*", @@ -342,6 +363,16 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { TargetSchema: "v", TargetTable: "vv", }, + { + SchemaPattern: "~.*regexpr[1-9]+", + TablePattern: "~.*regexprtable", + TargetSchema: "downstream_db", + TargetTable: "downstream_table", + }, + { + SchemaPattern: "~.bdb.*", + TargetSchema: "db", + }, } /* @@ -365,38 +396,52 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { e0-schema-create.sql e0.f0-schema.sql e0.f0-schema-view.sql + test_regexpr1-schema-create.sql + test_regexpr1.test_regexprtable-schema.sql + test_regexpr1.test_regexprtable.1.sql + zbdb-schema-create.sql + zbdb.table-schema.sql + zbdb.table.1.sql */ - s.touch(c, "a0-schema-create.sql") - s.touch(c, "a0.t0-schema.sql") - s.touch(c, "a0.t0.1.sql") - s.touch(c, "a0.t1-schema.sql") - s.touch(c, "a0.t1.1.sql") + s.touch(t, "a0-schema-create.sql") + s.touch(t, "a0.t0-schema.sql") + s.touch(t, "a0.t0.1.sql") + s.touch(t, "a0.t1-schema.sql") + s.touch(t, "a0.t1.1.sql") - s.touch(c, "a1-schema-create.sql") - s.touch(c, "a1.s1-schema.sql") - s.touch(c, "a1.s1.1.sql") - s.touch(c, "a1.t2-schema.sql") - s.touch(c, "a1.t2.1.sql") - s.touch(c, "a1.v1-schema.sql") - s.touch(c, "a1.v1-schema-view.sql") + s.touch(t, "a1-schema-create.sql") + s.touch(t, "a1.s1-schema.sql") + s.touch(t, "a1.s1.1.sql") + s.touch(t, "a1.t2-schema.sql") + s.touch(t, "a1.t2.1.sql") + s.touch(t, "a1.v1-schema.sql") + s.touch(t, "a1.v1-schema-view.sql") - s.touch(c, "c0-schema-create.sql") - s.touch(c, "c0.t3-schema.sql") - s.touch(c, "c0.t3.1.sql") + s.touch(t, "c0-schema-create.sql") + s.touch(t, "c0.t3-schema.sql") + s.touch(t, "c0.t3.1.sql") - s.touch(c, "d0-schema-create.sql") + s.touch(t, "d0-schema-create.sql") - s.touch(c, "e0-schema-create.sql") - s.touch(c, "e0.f0-schema.sql") - s.touch(c, "e0.f0-schema-view.sql") + s.touch(t, "e0-schema-create.sql") + s.touch(t, "e0.f0-schema.sql") + s.touch(t, "e0.f0-schema-view.sql") + + s.touch(t, "test_regexpr1-schema-create.sql") + s.touch(t, "test_regexpr1.test_regexprtable-schema.sql") + s.touch(t, "test_regexpr1.test_regexprtable.1.sql") + + s.touch(t, "zbdb-schema-create.sql") + s.touch(t, "zbdb.table-schema.sql") + s.touch(t, "zbdb.table.1.sql") mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, IsNil) - c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{ + require.NoError(t, err) + require.Equal(t, []*md.MDDatabaseMeta{ { Name: "a1", - SchemaFile: "a1-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: ""}, FileMeta: md.SourceFileMeta{Path: "a1-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "a1", @@ -427,11 +472,11 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { }, { Name: "d0", - SchemaFile: "d0-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "d0", Name: ""}, FileMeta: md.SourceFileMeta{Path: "d0-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, }, { Name: "b", - SchemaFile: "a0-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "b", Name: ""}, FileMeta: md.SourceFileMeta{Path: "a0-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "b", @@ -449,7 +494,7 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { }, { Name: "c", - SchemaFile: "c0-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "c", Name: ""}, FileMeta: md.SourceFileMeta{Path: "c0-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "c", @@ -463,7 +508,7 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { }, { Name: "v", - SchemaFile: "e0-schema-create.sql", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "v", Name: ""}, FileMeta: md.SourceFileMeta{Path: "e0-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "v", @@ -484,22 +529,55 @@ func (s *testMydumpLoaderSuite) TestRouter(c *C) { }, }, }, - }) + + { + Name: "downstream_db", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "downstream_db", Name: ""}, FileMeta: md.SourceFileMeta{Path: "test_regexpr1-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, + Tables: []*md.MDTableMeta{ + { + DB: "downstream_db", + Name: "downstream_table", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "downstream_db", Name: "downstream_table"}, FileMeta: md.SourceFileMeta{Path: "test_regexpr1.test_regexprtable-schema.sql", Type: md.SourceTypeTableSchema}}, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "downstream_db", Name: "downstream_table"}, FileMeta: md.SourceFileMeta{Path: "test_regexpr1.test_regexprtable.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}}, + IndexRatio: 0.0, + IsRowOrdered: true, + }, + }, + }, + { + Name: "db", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: ""}, FileMeta: md.SourceFileMeta{Path: "zbdb-schema-create.sql", Type: md.SourceTypeSchemaSchema}}, + Tables: []*md.MDTableMeta{ + { + DB: "db", + Name: "table", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "table"}, FileMeta: md.SourceFileMeta{Path: "zbdb.table-schema.sql", Type: md.SourceTypeTableSchema}}, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "table"}, FileMeta: md.SourceFileMeta{Path: "zbdb.table.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}}, + IndexRatio: 0.0, + IsRowOrdered: true, + }, + }, + }, + }, mdl.GetDatabases()) } -func (s *testMydumpLoaderSuite) TestBadRouterRule(c *C) { +func TestBadRouterRule(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + s.cfg.Routes = []*router.TableRule{{ SchemaPattern: "a*b", TargetSchema: "ab", }} - s.touch(c, "a1b-schema-create.sql") + s.touch(t, "a1b-schema-create.sql") _, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, ErrorMatches, `.*pattern a\*b not valid`) + require.Regexp(t, `.*pattern a\*b not valid`, err.Error()) } -func (s *testMydumpLoaderSuite) TestFileRouting(c *C) { +func TestFileRouting(t *testing.T) { + s := newTestMydumpLoaderSuite(t) + s.cfg.Mydumper.DefaultFileRules = false s.cfg.Mydumper.FileRouters = []*config.FileRouteRule{ { @@ -533,26 +611,26 @@ func (s *testMydumpLoaderSuite) TestFileRouting(c *C) { }, } - s.mkdir(c, "d1") - s.mkdir(c, "d2") - s.touch(c, "d1/schema.sql") - s.touch(c, "d1/test-table.sql") - s.touch(c, "d1/test0.sql") - s.touch(c, "d1/test1.sql") - s.touch(c, "d1/test2.001.sql") - s.touch(c, "d1/v1-table.sql") - s.touch(c, "d1/v1-view.sql") - s.touch(c, "d1/t1-schema-create.sql") - s.touch(c, "d2/schema.sql") - s.touch(c, "d2/abc-table.sql") - s.touch(c, "abc.1.sql") + s.mkdir(t, "d1") + s.mkdir(t, "d2") + s.touch(t, "d1/schema.sql") + s.touch(t, "d1/test-table.sql") + s.touch(t, "d1/test0.sql") + s.touch(t, "d1/test1.sql") + s.touch(t, "d1/test2.001.sql") + s.touch(t, "d1/v1-table.sql") + s.touch(t, "d1/v1-view.sql") + s.touch(t, "d1/t1-schema-create.sql") + s.touch(t, "d2/schema.sql") + s.touch(t, "d2/abc-table.sql") + s.touch(t, "abc.1.sql") mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) - c.Assert(err, IsNil) - c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{ + require.NoError(t, err) + require.Equal(t, []*md.MDDatabaseMeta{ { Name: "d1", - SchemaFile: filepath.FromSlash("d1/schema.sql"), + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "d1", Name: ""}, FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/schema.sql"), Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "d1", @@ -605,7 +683,7 @@ func (s *testMydumpLoaderSuite) TestFileRouting(c *C) { }, { Name: "d2", - SchemaFile: filepath.FromSlash("d2/schema.sql"), + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "d2", Name: ""}, FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d2/schema.sql"), Type: md.SourceTypeSchemaSchema}}, Tables: []*md.MDTableMeta{ { DB: "d2", @@ -620,5 +698,115 @@ func (s *testMydumpLoaderSuite) TestFileRouting(c *C) { }, }, }, - }) + }, mdl.GetDatabases()) +} + +func TestInputWithSpecialChars(t *testing.T) { + /* + Path/ + test-schema-create.sql + test.t%22-schema.sql + test.t%22.0.sql + test.t%2522-schema.sql + test.t%2522.0.csv + test.t%gg-schema.sql + test.t%gg.csv + test.t+gg-schema.sql + test.t+gg.csv + + db%22.t%2522-schema.sql + db%22.t%2522.0.csv + */ + s := newTestMydumpLoaderSuite(t) + + s.touch(t, "test-schema-create.sql") + s.touch(t, "test.t%22-schema.sql") + s.touch(t, "test.t%22.sql") + s.touch(t, "test.t%2522-schema.sql") + s.touch(t, "test.t%2522.csv") + s.touch(t, "test.t%gg-schema.sql") + s.touch(t, "test.t%gg.csv") + s.touch(t, "test.t+gg-schema.sql") + s.touch(t, "test.t+gg.csv") + + s.touch(t, "db%22-schema-create.sql") + s.touch(t, "db%22.t%2522-schema.sql") + s.touch(t, "db%22.t%2522.0.csv") + + mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) + require.NoError(t, err) + require.Equal(t, []*md.MDDatabaseMeta{ + { + Name: `db"`, + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: `db"`, Name: ""}, FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("db%22-schema-create.sql"), Type: md.SourceTypeSchemaSchema}}, + Tables: []*md.MDTableMeta{ + { + DB: `db"`, + Name: "t%22", + SchemaFile: md.FileInfo{ + TableName: filter.Table{Schema: `db"`, Name: "t%22"}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("db%22.t%2522-schema.sql"), Type: md.SourceTypeTableSchema}, + }, + DataFiles: []md.FileInfo{ + { + TableName: filter.Table{Schema: `db"`, Name: "t%22"}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("db%22.t%2522.0.csv"), Type: md.SourceTypeCSV, SortKey: "0"}, + }, + }, + IndexRatio: 0, + IsRowOrdered: true, + }, + }, + }, + { + Name: "test", + SchemaFile: md.FileInfo{TableName: filter.Table{Schema: `test`, Name: ""}, FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("test-schema-create.sql"), Type: md.SourceTypeSchemaSchema}}, + Tables: []*md.MDTableMeta{ + { + DB: "test", + Name: `t"`, + SchemaFile: md.FileInfo{ + TableName: filter.Table{Schema: "test", Name: `t"`}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("test.t%22-schema.sql"), Type: md.SourceTypeTableSchema}, + }, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "test", Name: `t"`}, FileMeta: md.SourceFileMeta{Path: "test.t%22.sql", Type: md.SourceTypeSQL}}}, + IndexRatio: 0, + IsRowOrdered: true, + }, + { + DB: "test", + Name: "t%22", + SchemaFile: md.FileInfo{ + TableName: filter.Table{Schema: "test", Name: "t%22"}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("test.t%2522-schema.sql"), Type: md.SourceTypeTableSchema}, + }, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "test", Name: "t%22"}, FileMeta: md.SourceFileMeta{Path: "test.t%2522.csv", Type: md.SourceTypeCSV}}}, + IndexRatio: 0, + IsRowOrdered: true, + }, + { + DB: "test", + Name: "t%gg", + SchemaFile: md.FileInfo{ + TableName: filter.Table{Schema: "test", Name: "t%gg"}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("test.t%gg-schema.sql"), Type: md.SourceTypeTableSchema}, + }, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "test", Name: "t%gg"}, FileMeta: md.SourceFileMeta{Path: "test.t%gg.csv", Type: md.SourceTypeCSV}}}, + IndexRatio: 0, + IsRowOrdered: true, + }, + { + DB: "test", + Name: "t+gg", + SchemaFile: md.FileInfo{ + TableName: filter.Table{Schema: "test", Name: "t+gg"}, + FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("test.t+gg-schema.sql"), Type: md.SourceTypeTableSchema}, + }, + DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "test", Name: "t+gg"}, FileMeta: md.SourceFileMeta{Path: "test.t+gg.csv", Type: md.SourceTypeCSV}}}, + IndexRatio: 0, + IsRowOrdered: true, + }, + }, + }, + }, mdl.GetDatabases()) } diff --git a/br/pkg/lightning/mydump/main_test.go b/br/pkg/lightning/mydump/main_test.go new file mode 100644 index 0000000000000..12be83040f259 --- /dev/null +++ b/br/pkg/lightning/mydump/main_test.go @@ -0,0 +1,32 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mydump + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), + } + goleak.VerifyTestMain(m, opts...) +} diff --git a/br/pkg/lightning/mydump/parquet_parser_test.go b/br/pkg/lightning/mydump/parquet_parser_test.go index 2962e6cb1c5c7..0231c2b4e1e6d 100644 --- a/br/pkg/lightning/mydump/parquet_parser_test.go +++ b/br/pkg/lightning/mydump/parquet_parser_test.go @@ -5,82 +5,80 @@ import ( "io" "path/filepath" "strconv" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/xitongsys/parquet-go-source/local" writer2 "github.com/xitongsys/parquet-go/writer" ) -type testParquetParserSuite struct{} - -var _ = Suite(testParquetParserSuite{}) - -func (s testParquetParserSuite) TestParquetParser(c *C) { +func TestParquetParser(t *testing.T) { type Test struct { S string `parquet:"name=sS, type=UTF8, encoding=PLAIN_DICTIONARY"` A int32 `parquet:"name=a_A, type=INT32"` } - dir := c.MkDir() + dir := t.TempDir() // prepare data name := "test123.parquet" testPath := filepath.Join(dir, name) pf, err := local.NewLocalFileWriter(testPath) - c.Assert(err, IsNil) + require.NoError(t, err) test := &Test{} writer, err := writer2.NewParquetWriter(pf, test, 2) - c.Assert(err, IsNil) + require.NoError(t, err) for i := 0; i < 100; i++ { test.A = int32(i) test.S = strconv.Itoa(i) - c.Assert(writer.Write(test), IsNil) + require.NoError(t, writer.Write(test)) } - c.Assert(writer.WriteStop(), IsNil) - c.Assert(pf.Close(), IsNil) + require.NoError(t, writer.WriteStop()) + require.NoError(t, pf.Close()) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) r, err := store.Open(context.TODO(), name) - c.Assert(err, IsNil) + require.NoError(t, err) reader, err := NewParquetParser(context.TODO(), store, r, name) - c.Assert(err, IsNil) + require.NoError(t, err) defer reader.Close() - c.Assert(reader.Columns(), DeepEquals, []string{"ss", "a_a"}) + require.Equal(t, []string{"ss", "a_a"}, reader.Columns()) verifyRow := func(i int) { - c.Assert(reader.lastRow.RowID, Equals, int64(i+1)) - c.Assert(len(reader.lastRow.Row), Equals, 2) - c.Assert(reader.lastRow.Row[0], DeepEquals, types.NewCollationStringDatum(strconv.Itoa(i), "")) - c.Assert(reader.lastRow.Row[1], DeepEquals, types.NewIntDatum(int64(i))) + require.Equal(t, int64(i+1), reader.lastRow.RowID) + require.Len(t, reader.lastRow.Row, 2) + require.Equal(t, types.NewCollationStringDatum(strconv.Itoa(i), ""), reader.lastRow.Row[0]) + require.Equal(t, types.NewIntDatum(int64(i)), reader.lastRow.Row[1]) } // test read some rows for i := 0; i < 10; i++ { - c.Assert(reader.ReadRow(), IsNil) + require.NoError(t, reader.ReadRow()) verifyRow(i) } // test set pos to pos < curpos + batchReadRowSize - c.Assert(reader.SetPos(15, 15), IsNil) - c.Assert(reader.ReadRow(), IsNil) + require.NoError(t, reader.SetPos(15, 15)) + require.NoError(t, reader.ReadRow()) verifyRow(15) // test set pos to pos > curpos + batchReadRowSize - c.Assert(reader.SetPos(80, 80), IsNil) + require.NoError(t, reader.SetPos(80, 80)) for i := 80; i < 100; i++ { - c.Assert(reader.ReadRow(), IsNil) + require.NoError(t, reader.ReadRow()) verifyRow(i) } - c.Assert(reader.ReadRow(), Equals, io.EOF) + require.ErrorIs(t, reader.ReadRow(), io.EOF) } -func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { +func TestParquetVariousTypes(t *testing.T) { type Test struct { Date int32 `parquet:"name=date, type=DATE"` TimeMillis int32 `parquet:"name=timemillis, type=TIME_MILLIS"` @@ -94,15 +92,15 @@ func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { Decimal6 int32 `parquet:"name=decimal6, type=DECIMAL, scale=4, precision=4, basetype=INT32"` } - dir := c.MkDir() + dir := t.TempDir() // prepare data name := "test123.parquet" testPath := filepath.Join(dir, name) pf, err := local.NewLocalFileWriter(testPath) - c.Assert(err, IsNil) + require.NoError(t, err) test := &Test{} writer, err := writer2.NewParquetWriter(pf, test, 2) - c.Assert(err, IsNil) + require.NoError(t, err) v := &Test{ Date: 18564, // 2020-10-29 @@ -115,30 +113,30 @@ func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { Decimal3: 123456789012345678, // 1234567890123456.78 Decimal6: -1, // -0.0001 } - c.Assert(writer.Write(v), IsNil) - c.Assert(writer.WriteStop(), IsNil) - c.Assert(pf.Close(), IsNil) + require.NoError(t, writer.Write(v)) + require.NoError(t, writer.WriteStop()) + require.NoError(t, pf.Close()) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) r, err := store.Open(context.TODO(), name) - c.Assert(err, IsNil) + require.NoError(t, err) reader, err := NewParquetParser(context.TODO(), store, r, name) - c.Assert(err, IsNil) + require.NoError(t, err) defer reader.Close() - c.Assert(len(reader.columns), Equals, 9) + require.Len(t, reader.columns, 9) - c.Assert(reader.ReadRow(), IsNil) + require.NoError(t, reader.ReadRow()) rowValue := []string{ "2020-10-29", "17:26:15.123Z", "17:26:15.123456Z", "2020-10-29 09:27:52.356Z", "2020-10-29 09:27:52.356956Z", "-123456.78", "0.0456", "1234567890123456.78", "-0.0001", } row := reader.lastRow.Row - c.Assert(len(rowValue), Equals, len(row)) + require.Len(t, rowValue, len(row)) for i := 0; i < len(row); i++ { - c.Assert(row[i].Kind(), Equals, types.KindString) - c.Assert(rowValue[i], Equals, row[i].GetString()) + assert.Equal(t, types.KindString, row[i].Kind()) + assert.Equal(t, row[i].GetString(), rowValue[i]) } type TestDecimal struct { @@ -160,9 +158,9 @@ func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { testPath = filepath.Join(dir, fileName) pf, err = local.NewLocalFileWriter(testPath) td := &TestDecimal{} - c.Assert(err, IsNil) + require.NoError(t, err) writer, err = writer2.NewParquetWriter(pf, td, 2) - c.Assert(err, IsNil) + require.NoError(t, err) for i, testCase := range cases { val := testCase[0].(int32) td.Decimal1 = val @@ -171,19 +169,19 @@ func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { } else { td.DecimalRef = nil } - c.Assert(writer.Write(td), IsNil) + assert.NoError(t, writer.Write(td)) } - c.Assert(writer.WriteStop(), IsNil) - c.Assert(pf.Close(), IsNil) + require.NoError(t, writer.WriteStop()) + require.NoError(t, pf.Close()) r, err = store.Open(context.TODO(), fileName) - c.Assert(err, IsNil) + require.NoError(t, err) reader, err = NewParquetParser(context.TODO(), store, r, fileName) - c.Assert(err, IsNil) + require.NoError(t, err) defer reader.Close() for i, testCase := range cases { - c.Assert(reader.ReadRow(), IsNil) + assert.NoError(t, reader.ReadRow()) vals := []types.Datum{types.NewCollationStringDatum(testCase[1].(string), "")} if i%2 == 0 { vals = append(vals, vals[0]) @@ -192,25 +190,25 @@ func (s testParquetParserSuite) TestParquetVariousTypes(c *C) { } // because we always reuse the datums in reader.lastRow.Row, so we can't directly // compare will `DeepEqual` here - c.Assert(len(reader.lastRow.Row), Equals, len(vals)) + assert.Len(t, reader.lastRow.Row, len(vals)) for i, val := range vals { - c.Assert(reader.lastRow.Row[i].Kind(), Equals, val.Kind()) - c.Assert(reader.lastRow.Row[i].GetValue(), Equals, val.GetValue()) + assert.Equal(t, val.Kind(), reader.lastRow.Row[i].Kind()) + assert.Equal(t, val.GetValue(), reader.lastRow.Row[i].GetValue()) } } } -func (s testParquetParserSuite) TestParquetAurora(c *C) { +func TestParquetAurora(t *testing.T) { store, err := storage.NewLocalStorage("examples") - c.Assert(err, IsNil) + require.NoError(t, err) fileName := "test.parquet" r, err := store.Open(context.TODO(), fileName) - c.Assert(err, IsNil) + require.NoError(t, err) parser, err := NewParquetParser(context.TODO(), store, r, fileName) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(parser.Columns(), DeepEquals, []string{"id", "val1", "val2", "d1", "d2", "d3", "d4", "d5", "d6"}) + require.Equal(t, []string{"id", "val1", "val2", "d1", "d2", "d3", "d4", "d5", "d6"}, parser.Columns()) expectedRes := [][]interface{}{ {int64(1), int64(1), "0", int64(123), "1.23", "0.00000001", "1234567890", "123", "1.23000000"}, @@ -238,21 +236,21 @@ func (s testParquetParserSuite) TestParquetAurora(c *C) { for i := 0; i < len(expectedRes); i++ { err = parser.ReadRow() - c.Assert(err, IsNil) + assert.NoError(t, err) expectedValues := expectedRes[i] row := parser.LastRow().Row - c.Assert(len(expectedValues), Equals, len(row)) + assert.Len(t, expectedValues, len(row)) for j := 0; j < len(row); j++ { switch v := expectedValues[j].(type) { case int64: - c.Assert(v, Equals, row[j].GetInt64()) + assert.Equal(t, row[j].GetInt64(), v) case string: - c.Assert(v, Equals, row[j].GetString()) + assert.Equal(t, row[j].GetString(), v) default: - c.Error("unexpected value: ", expectedValues[j]) + t.Fatal("unexpected value: ", expectedValues[j]) } } } - c.Assert(parser.ReadRow(), Equals, io.EOF) + require.ErrorIs(t, parser.ReadRow(), io.EOF) } diff --git a/br/pkg/lightning/mydump/parser_test.go b/br/pkg/lightning/mydump/parser_test.go index 53242022daae7..80dfcdc17c675 100644 --- a/br/pkg/lightning/mydump/parser_test.go +++ b/br/pkg/lightning/mydump/parser_test.go @@ -15,51 +15,41 @@ package mydump_test import ( - "context" + "fmt" "io" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/mydump" - "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMydumpParserSuite{}) - -type testMydumpParserSuite struct { - ioWorkers *worker.Pool -} - -func (s *testMydumpParserSuite) SetUpSuite(c *C) { - s.ioWorkers = worker.NewPool(context.Background(), 5, "test_sql") -} -func (s *testMydumpParserSuite) TearDownSuite(c *C) {} - -func (s *testMydumpParserSuite) runTestCases(c *C, mode mysql.SQLMode, blockBufSize int64, cases []testCase) { +func runTestCases(t *testing.T, mode mysql.SQLMode, blockBufSize int64, cases []testCase) { for _, tc := range cases { - parser := mydump.NewChunkParser(mode, mydump.NewStringReader(tc.input), blockBufSize, s.ioWorkers) + parser := mydump.NewChunkParser(mode, mydump.NewStringReader(tc.input), blockBufSize, ioWorkers) for i, row := range tc.expected { e := parser.ReadRow() - comment := Commentf("input = %q, row = %d, err = %s", tc.input, i+1, errors.ErrorStack(e)) - c.Assert(e, IsNil, comment) - c.Assert(parser.LastRow().RowID, DeepEquals, int64(i)+1) - c.Assert(parser.LastRow().Row, DeepEquals, row) + comment := fmt.Sprintf("input = %q, row = %d, err = %s", tc.input, i+1, errors.ErrorStack(e)) + assert.NoError(t, e, comment) + assert.Equal(t, int64(i)+1, parser.LastRow().RowID, comment) + assert.Equal(t, row, parser.LastRow().Row, comment) } - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF, Commentf("input = %q", tc.input)) + assert.ErrorIsf(t, errors.Cause(parser.ReadRow()), io.EOF, "input = %q", tc.input) } } -func (s *testMydumpParserSuite) runFailingTestCases(c *C, mode mysql.SQLMode, blockBufSize int64, cases []string) { +func runFailingTestCases(t *testing.T, mode mysql.SQLMode, blockBufSize int64, cases []string) { for _, tc := range cases { - parser := mydump.NewChunkParser(mode, mydump.NewStringReader(tc), blockBufSize, s.ioWorkers) - c.Assert(parser.ReadRow(), ErrorMatches, "syntax error.*", Commentf("input = %q", tc)) + parser := mydump.NewChunkParser(mode, mydump.NewStringReader(tc), blockBufSize, ioWorkers) + assert.Regexpf(t, "syntax error.*", parser.ReadRow().Error(), "input = %q", tc) } } -func (s *testMydumpParserSuite) TestReadRow(c *C) { +func TestReadRow(t *testing.T) { reader := mydump.NewStringReader( "/* whatever pragmas */;" + "INSERT INTO `namespaced`.`table` (columns, more, columns) VALUES (1,-2, 3),\n(4,5., 6);" + @@ -67,10 +57,10 @@ func (s *testMydumpParserSuite) TestReadRow(c *C) { "insert another_table values (10,11e1,12, '(13)', '(', 14, ')');", ) - parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), s.ioWorkers) + parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), ioWorkers) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.NoError(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 1, Row: []types.Datum{ types.NewUintDatum(1), @@ -78,14 +68,14 @@ func (s *testMydumpParserSuite) TestReadRow(c *C) { types.NewUintDatum(3), }, Length: 62, - }) - c.Assert(parser.Columns(), DeepEquals, []string{"columns", "more", "columns"}) + }, parser.LastRow()) + require.Equal(t, []string{"columns", "more", "columns"}, parser.Columns()) offset, rowID := parser.Pos() - c.Assert(offset, Equals, int64(97)) - c.Assert(rowID, Equals, int64(1)) + require.Equal(t, int64(97), offset) + require.Equal(t, int64(1), rowID) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.NoError(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 2, Row: []types.Datum{ types.NewUintDatum(4), @@ -93,14 +83,14 @@ func (s *testMydumpParserSuite) TestReadRow(c *C) { types.NewUintDatum(6), }, Length: 6, - }) - c.Assert(parser.Columns(), DeepEquals, []string{"columns", "more", "columns"}) + }, parser.LastRow()) + require.Equal(t, []string{"columns", "more", "columns"}, parser.Columns()) offset, rowID = parser.Pos() - c.Assert(offset, Equals, int64(108)) - c.Assert(rowID, Equals, int64(2)) + require.Equal(t, int64(108), offset) + require.Equal(t, int64(2), rowID) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.NoError(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 3, Row: []types.Datum{ types.NewUintDatum(7), @@ -108,14 +98,14 @@ func (s *testMydumpParserSuite) TestReadRow(c *C) { types.NewUintDatum(9), }, Length: 42, - }) - c.Assert(parser.Columns(), DeepEquals, []string{"x", "y", "z"}) + }, parser.LastRow()) + require.Equal(t, []string{"x", "y", "z"}, parser.Columns()) offset, rowID = parser.Pos() - c.Assert(offset, Equals, int64(159)) - c.Assert(rowID, Equals, int64(3)) + require.Equal(t, int64(159), offset) + require.Equal(t, int64(3), rowID) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.LastRow(), DeepEquals, mydump.Row{ + require.NoError(t, parser.ReadRow()) + require.Equal(t, mydump.Row{ RowID: 4, Row: []types.Datum{ types.NewUintDatum(10), @@ -127,27 +117,27 @@ func (s *testMydumpParserSuite) TestReadRow(c *C) { types.NewStringDatum(")"), }, Length: 49, - }) - c.Assert(parser.Columns(), IsNil) + }, parser.LastRow()) + require.Nil(t, parser.Columns()) offset, rowID = parser.Pos() - c.Assert(offset, Equals, int64(222)) - c.Assert(rowID, Equals, int64(4)) + require.Equal(t, int64(222), offset) + require.Equal(t, int64(4), rowID) - c.Assert(errors.Cause(parser.ReadRow()), Equals, io.EOF) + require.ErrorIs(t, errors.Cause(parser.ReadRow()), io.EOF) } -func (s *testMydumpParserSuite) TestReadChunks(c *C) { +func TestReadChunks(t *testing.T) { reader := mydump.NewStringReader(` INSERT foo VALUES (1,2,3,4),(5,6,7,8),(9,10,11,12); INSERT foo VALUES (13,14,15,16),(17,18,19,20),(21,22,23,24),(25,26,27,28); INSERT foo VALUES (29,30,31,32),(33,34,35,36); `) - parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), s.ioWorkers) + parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), ioWorkers) chunks, err := mydump.ReadChunks(parser, 32) - c.Assert(err, IsNil) - c.Assert(chunks, DeepEquals, []mydump.Chunk{ + require.NoError(t, err) + require.Equal(t, []mydump.Chunk{ { Offset: 0, EndOffset: 40, @@ -178,10 +168,10 @@ func (s *testMydumpParserSuite) TestReadChunks(c *C) { PrevRowIDMax: 8, RowIDMax: 9, }, - }) + }, chunks) } -func (s *testMydumpParserSuite) TestNestedRow(c *C) { +func TestNestedRow(t *testing.T) { reader := mydump.NewStringReader(` INSERT INTO exam_detail VALUES ("123",CONVERT("{}" USING UTF8MB4)), @@ -189,11 +179,11 @@ func (s *testMydumpParserSuite) TestNestedRow(c *C) { ("789",CONVERT("[]" USING UTF8MB4)); `) - parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), s.ioWorkers) + parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), ioWorkers) chunks, err := mydump.ReadChunks(parser, 96) - c.Assert(err, IsNil) - c.Assert(chunks, DeepEquals, []mydump.Chunk{ + require.NoError(t, err) + require.Equal(t, []mydump.Chunk{ { Offset: 0, EndOffset: 117, @@ -206,10 +196,10 @@ func (s *testMydumpParserSuite) TestNestedRow(c *C) { PrevRowIDMax: 2, RowIDMax: 3, }, - }) + }, chunks) } -func (s *testMydumpParserSuite) TestVariousSyntax(c *C) { +func TestVariousSyntax(t *testing.T) { testCases := []testCase{ { input: "INSERT INTO foobar VALUES (1, 2);", @@ -356,10 +346,10 @@ func (s *testMydumpParserSuite) TestVariousSyntax(c *C) { }, } - s.runTestCases(c, mysql.ModeNone, int64(config.ReadBlockSize), testCases) + runTestCases(t, mysql.ModeNone, int64(config.ReadBlockSize), testCases) } -func (s *testMydumpParserSuite) TestContinuation(c *C) { +func TestContinuation(t *testing.T) { testCases := []testCase{ { input: ` @@ -377,10 +367,10 @@ func (s *testMydumpParserSuite) TestContinuation(c *C) { }, } - s.runTestCases(c, mysql.ModeNone, 1, testCases) + runTestCases(t, mysql.ModeNone, 1, testCases) } -func (s *testMydumpParserSuite) TestPseudoKeywords(c *C) { +func TestPseudoKeywords(t *testing.T) { reader := mydump.NewStringReader(` INSERT INTO t ( c, C, @@ -422,9 +412,9 @@ func (s *testMydumpParserSuite) TestPseudoKeywords(c *C) { ) VALUES (); `) - parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), s.ioWorkers) - c.Assert(parser.ReadRow(), IsNil) - c.Assert(parser.Columns(), DeepEquals, []string{ + parser := mydump.NewChunkParser(mysql.ModeNone, reader, int64(config.ReadBlockSize), ioWorkers) + require.NoError(t, parser.ReadRow()) + require.Equal(t, []string{ "c", "c", "co", "co", "con", "con", @@ -461,10 +451,10 @@ func (s *testMydumpParserSuite) TestPseudoKeywords(c *C) { "ins", "ins", "inse", "inse", "inser", "inser", - }) + }, parser.Columns()) } -func (s *testMydumpParserSuite) TestSyntaxError(c *C) { +func TestSyntaxError(t *testing.T) { inputs := []string{ "('xxx)", `("xxx)`, @@ -489,13 +479,13 @@ func (s *testMydumpParserSuite) TestSyntaxError(c *C) { "/* ...", } - s.runFailingTestCases(c, mysql.ModeNone, int64(config.ReadBlockSize), inputs) + runFailingTestCases(t, mysql.ModeNone, int64(config.ReadBlockSize), inputs) } // Various syntax error cases collected via fuzzing. // These cover most of the tokenizer branches. -func (s *testMydumpParserSuite) TestMoreSyntaxError(c *C) { +func TestMoreSyntaxError(t *testing.T) { inputs := []string{ " usin0", "- ", @@ -862,11 +852,11 @@ func (s *testMydumpParserSuite) TestMoreSyntaxError(c *C) { "x00`0`Valu0", } - s.runFailingTestCases(c, mysql.ModeNone, 1, inputs) - s.runFailingTestCases(c, mysql.ModeNoBackslashEscapes, 1, inputs) + runFailingTestCases(t, mysql.ModeNone, 1, inputs) + runFailingTestCases(t, mysql.ModeNoBackslashEscapes, 1, inputs) } -func (s *testMydumpParserSuite) TestMoreEmptyFiles(c *C) { +func TestMoreEmptyFiles(t *testing.T) { testCases := []testCase{ {input: ""}, {input: "--\t"}, @@ -884,6 +874,6 @@ func (s *testMydumpParserSuite) TestMoreEmptyFiles(c *C) { {input: "--\r"}, } - s.runTestCases(c, mysql.ModeNone, 1, testCases) - s.runTestCases(c, mysql.ModeNoBackslashEscapes, 1, testCases) + runTestCases(t, mysql.ModeNone, 1, testCases) + runTestCases(t, mysql.ModeNoBackslashEscapes, 1, testCases) } diff --git a/br/pkg/lightning/mydump/reader_test.go b/br/pkg/lightning/mydump/reader_test.go index 0ff37ad666747..e7506ea869782 100644 --- a/br/pkg/lightning/mydump/reader_test.go +++ b/br/pkg/lightning/mydump/reader_test.go @@ -19,45 +19,39 @@ import ( "errors" "os" "path/filepath" + "testing" "github.com/golang/mock/gomock" - . "github.com/pingcap/check" . "github.com/pingcap/tidb/br/pkg/lightning/mydump" mockstorage "github.com/pingcap/tidb/br/pkg/mock/storage" "github.com/pingcap/tidb/br/pkg/storage" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMydumpReaderSuite{}) - -type testMydumpReaderSuite struct{} - -func (s *testMydumpReaderSuite) SetUpSuite(c *C) {} -func (s *testMydumpReaderSuite) TearDownSuite(c *C) {} - -func (s *testMydumpReaderSuite) TestExportStatementNoTrailingNewLine(c *C) { - dir := c.MkDir() +func TestExportStatementNoTrailingNewLine(t *testing.T) { + dir := t.TempDir() file, err := os.Create(filepath.Join(dir, "tidb_lightning_test_reader")) - c.Assert(err, IsNil) + require.NoError(t, err) defer os.Remove(file.Name()) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = file.Write([]byte("CREATE DATABASE whatever;")) - c.Assert(err, IsNil) + require.NoError(t, err) stat, err := file.Stat() - c.Assert(err, IsNil) + require.NoError(t, err) err = file.Close() - c.Assert(err, IsNil) + require.NoError(t, err) f := FileInfo{FileMeta: SourceFileMeta{Path: stat.Name(), FileSize: stat.Size()}} data, err := ExportStatement(context.TODO(), store, f, "auto") - c.Assert(err, IsNil) - c.Assert(data, DeepEquals, []byte("CREATE DATABASE whatever;")) + require.NoError(t, err) + require.Equal(t, []byte("CREATE DATABASE whatever;"), data) } -func (s *testMydumpReaderSuite) TestExportStatementWithComment(c *C) { - s.exportStatmentShouldBe(c, ` +func TestExportStatementWithComment(t *testing.T) { + exportStatmentShouldBe(t, ` /* whatever blabla multiple lines comment multiple lines comment @@ -69,8 +63,8 @@ func (s *testMydumpReaderSuite) TestExportStatementWithComment(c *C) { `, "CREATE DATABASE whatever;") } -func (s *testMydumpReaderSuite) TestExportStatementWithCommentNoTrailingNewLine(c *C) { - s.exportStatmentShouldBe(c, ` +func TestExportStatementWithCommentNoTrailingNewLine(t *testing.T) { + exportStatmentShouldBe(t, ` /* whatever blabla multiple lines comment multiple lines comment @@ -81,73 +75,73 @@ func (s *testMydumpReaderSuite) TestExportStatementWithCommentNoTrailingNewLine( CREATE DATABASE whatever;`, "CREATE DATABASE whatever;") } -func (s *testMydumpReaderSuite) exportStatmentShouldBe(c *C, stmt string, expected string) { - dir := c.MkDir() +func exportStatmentShouldBe(t *testing.T, stmt string, expected string) { + dir := t.TempDir() file, err := os.Create(filepath.Join(dir, "tidb_lightning_test_reader")) - c.Assert(err, IsNil) + require.NoError(t, err) defer os.Remove(file.Name()) _, err = file.Write([]byte(stmt)) - c.Assert(err, IsNil) + require.NoError(t, err) stat, err := file.Stat() - c.Assert(err, IsNil) + require.NoError(t, err) err = file.Close() - c.Assert(err, IsNil) + require.NoError(t, err) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) f := FileInfo{FileMeta: SourceFileMeta{Path: stat.Name(), FileSize: stat.Size()}} data, err := ExportStatement(context.TODO(), store, f, "auto") - c.Assert(err, IsNil) - c.Assert(data, DeepEquals, []byte(expected)) + require.NoError(t, err) + require.Equal(t, []byte(expected), data) } -func (s *testMydumpReaderSuite) TestExportStatementGBK(c *C) { - dir := c.MkDir() +func TestExportStatementGBK(t *testing.T) { + dir := t.TempDir() file, err := os.Create(filepath.Join(dir, "tidb_lightning_test_reader")) - c.Assert(err, IsNil) + require.NoError(t, err) defer os.Remove(file.Name()) _, err = file.Write([]byte("CREATE TABLE a (b int(11) COMMENT '")) - c.Assert(err, IsNil) + require.NoError(t, err) // "D7 DC B0 B8 C0 FD" is the GBK encoding of "总案例". _, err = file.Write([]byte{0xD7, 0xDC, 0xB0, 0xB8, 0xC0, 0xFD}) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = file.Write([]byte("');\n")) - c.Assert(err, IsNil) + require.NoError(t, err) stat, err := file.Stat() - c.Assert(err, IsNil) + require.NoError(t, err) err = file.Close() - c.Assert(err, IsNil) + require.NoError(t, err) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) f := FileInfo{FileMeta: SourceFileMeta{Path: stat.Name(), FileSize: stat.Size()}} data, err := ExportStatement(context.TODO(), store, f, "auto") - c.Assert(err, IsNil) - c.Assert(data, DeepEquals, []byte("CREATE TABLE a (b int(11) COMMENT '总案例');")) + require.NoError(t, err) + require.Equal(t, []byte("CREATE TABLE a (b int(11) COMMENT '总案例');"), data) } -func (s *testMydumpReaderSuite) TestExportStatementGibberishError(c *C) { - dir := c.MkDir() +func TestExportStatementGibberishError(t *testing.T) { + dir := t.TempDir() file, err := os.Create(filepath.Join(dir, "tidb_lightning_test_reader")) - c.Assert(err, IsNil) + require.NoError(t, err) defer os.Remove(file.Name()) _, err = file.Write([]byte("\x9e\x02\xdc\xfbZ/=n\xf3\xf2N8\xc1\xf2\xe9\xaa\xd0\x85\xc5}\x97\x07\xae6\x97\x99\x9c\x08\xcb\xe8;")) - c.Assert(err, IsNil) + require.NoError(t, err) stat, err := file.Stat() - c.Assert(err, IsNil) + require.NoError(t, err) err = file.Close() - c.Assert(err, IsNil) + require.NoError(t, err) store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) f := FileInfo{FileMeta: SourceFileMeta{Path: stat.Name(), FileSize: stat.Size()}} data, err := ExportStatement(context.TODO(), store, f, "auto") - c.Assert(data, HasLen, 0) - c.Assert(err, ErrorMatches, `failed to decode \w* as auto: invalid schema encoding`) + require.Len(t, data, 0) + require.Regexp(t, `failed to decode \w* as auto: invalid schema encoding`, err.Error()) } type AlwaysErrorReadSeekCloser struct{} @@ -164,8 +158,8 @@ func (AlwaysErrorReadSeekCloser) Close() error { return nil } -func (s *testMydumpReaderSuite) TestExportStatementHandleNonEOFError(c *C) { - controller := gomock.NewController(c) +func TestExportStatementHandleNonEOFError(t *testing.T) { + controller := gomock.NewController(t) defer controller.Finish() ctx := context.TODO() @@ -177,5 +171,5 @@ func (s *testMydumpReaderSuite) TestExportStatementHandleNonEOFError(c *C) { f := FileInfo{FileMeta: SourceFileMeta{Path: "no-perm-file", FileSize: 1}} _, err := ExportStatement(ctx, mockStorage, f, "auto") - c.Assert(err, ErrorMatches, "read error") + require.Contains(t, err.Error(), "read error") } diff --git a/br/pkg/lightning/mydump/region.go b/br/pkg/lightning/mydump/region.go index e694f25f743b1..73456d461bb0b 100644 --- a/br/pkg/lightning/mydump/region.go +++ b/br/pkg/lightning/mydump/region.go @@ -169,6 +169,7 @@ func MakeTableRegions( break } if err != nil { + log.L().Error("make source file region error", zap.Error(err), zap.String("file_path", info.FileMeta.Path)) break } } diff --git a/br/pkg/lightning/mydump/region_test.go b/br/pkg/lightning/mydump/region_test.go index 6ee26692d4e8c..a1dbb9f290a69 100644 --- a/br/pkg/lightning/mydump/region_test.go +++ b/br/pkg/lightning/mydump/region_test.go @@ -18,21 +18,16 @@ import ( "context" "os" "path/filepath" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/config" . "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/br/pkg/storage" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMydumpRegionSuite{}) - -type testMydumpRegionSuite struct{} - -func (s *testMydumpRegionSuite) SetUpSuite(c *C) {} -func (s *testMydumpRegionSuite) TearDownSuite(c *C) {} - // var expectedTuplesCount = map[string]int64{ // "i": 1, // "report_case_high_risk": 1, @@ -43,7 +38,7 @@ func (s *testMydumpRegionSuite) TearDownSuite(c *C) {} /* TODO : test with specified 'regionBlockSize' ... */ -func (s *testMydumpRegionSuite) TestTableRegion(c *C) { +func TestTableRegion(t *testing.T) { cfg := newConfigWithSourceDir("./examples") loader, _ := NewMyDumpLoader(context.Background(), cfg) dbMeta := loader.GetDatabases()[0] @@ -51,7 +46,7 @@ func (s *testMydumpRegionSuite) TestTableRegion(c *C) { ioWorkers := worker.NewPool(context.Background(), 1, "io") for _, meta := range dbMeta.Tables { regions, err := MakeTableRegions(context.Background(), meta, 1, cfg, ioWorkers, loader.GetStore()) - c.Assert(err, IsNil) + require.NoError(t, err) // check - region-size vs file-size var tolFileSize int64 = 0 @@ -62,7 +57,7 @@ func (s *testMydumpRegionSuite) TestTableRegion(c *C) { for _, region := range regions { tolRegionSize += region.Size() } - c.Assert(tolRegionSize, Equals, tolFileSize) + require.Equal(t, tolFileSize, tolRegionSize) // // check - rows num // var tolRows int64 = 0 @@ -77,18 +72,18 @@ func (s *testMydumpRegionSuite) TestTableRegion(c *C) { for i := 1; i < regionNum; i++ { reg := regions[i] if preReg.FileMeta.Path == reg.FileMeta.Path { - c.Assert(reg.Offset(), Equals, preReg.Offset()+preReg.Size()) - c.Assert(reg.RowIDMin(), Equals, preReg.RowIDMin()+preReg.Rows()) + require.Equal(t, preReg.Offset()+preReg.Size(), reg.Offset()) + require.Equal(t, preReg.RowIDMin()+preReg.Rows(), reg.RowIDMin()) } else { - c.Assert(reg.Offset, Equals, 0) - c.Assert(reg.RowIDMin(), Equals, 1) + require.Equal(t, 0, reg.Offset()) + require.Equal(t, 1, reg.RowIDMin()) } preReg = reg } } } -func (s *testMydumpRegionSuite) TestAllocateEngineIDs(c *C) { +func TestAllocateEngineIDs(t *testing.T) { dataFileSizes := make([]float64, 700) for i := range dataFileSizes { dataFileSizes[i] = 1.0 @@ -103,7 +98,7 @@ func (s *testMydumpRegionSuite) TestAllocateEngineIDs(c *C) { for _, region := range filesRegions { actual[region.EngineID]++ } - c.Assert(actual, DeepEquals, expected, Commentf("%s", what)) + require.Equal(t, expected, actual, what) } // Batch size > Total size => Everything in the zero batch. @@ -169,7 +164,7 @@ func (s *testMydumpRegionSuite) TestAllocateEngineIDs(c *C) { }) } -func (s *testMydumpRegionSuite) TestSplitLargeFile(c *C) { +func TestSplitLargeFile(t *testing.T) { meta := &MDTableMeta{ DB: "csv", Name: "large_csv_file", @@ -192,7 +187,7 @@ func (s *testMydumpRegionSuite) TestSplitLargeFile(c *C) { } filePath := "./csv/split_large_file.csv" dataFileInfo, err := os.Stat(filePath) - c.Assert(err, IsNil) + require.NoError(t, err) fileSize := dataFileInfo.Size() fileInfo := FileInfo{FileMeta: SourceFileMeta{Path: filePath, Type: SourceTypeCSV, FileSize: fileSize}} colCnt := int64(3) @@ -214,20 +209,20 @@ func (s *testMydumpRegionSuite) TestSplitLargeFile(c *C) { ioWorker := worker.NewPool(context.Background(), 4, "io") store, err := storage.NewLocalStorage(".") - c.Assert(err, IsNil) + assert.NoError(t, err) _, regions, _, err := SplitLargeFile(context.Background(), meta, cfg, fileInfo, colCnt, prevRowIdxMax, ioWorker, store) - c.Assert(err, IsNil) - c.Assert(regions, HasLen, len(tc.offsets)) + assert.NoError(t, err) + assert.Len(t, regions, len(tc.offsets)) for i := range tc.offsets { - c.Assert(regions[i].Chunk.Offset, Equals, tc.offsets[i][0]) - c.Assert(regions[i].Chunk.EndOffset, Equals, tc.offsets[i][1]) - c.Assert(regions[i].Chunk.Columns, DeepEquals, columns) + assert.Equal(t, tc.offsets[i][0], regions[i].Chunk.Offset) + assert.Equal(t, tc.offsets[i][1], regions[i].Chunk.EndOffset) + assert.Equal(t, columns, regions[i].Chunk.Columns) } } } -func (s *testMydumpRegionSuite) TestSplitLargeFileNoNewLineAtEOF(c *C) { +func TestSplitLargeFileNoNewLineAtEOF(t *testing.T) { meta := &MDTableMeta{ DB: "csv", Name: "large_csv_file", @@ -250,17 +245,17 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileNoNewLineAtEOF(c *C) { }, } - dir := c.MkDir() + dir := t.TempDir() fileName := "test.csv" filePath := filepath.Join(dir, fileName) content := []byte("a,b\r\n123,456\r\n789,101") err := os.WriteFile(filePath, content, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) dataFileInfo, err := os.Stat(filePath) - c.Assert(err, IsNil) + require.NoError(t, err) fileSize := dataFileInfo.Size() fileInfo := FileInfo{FileMeta: SourceFileMeta{Path: fileName, Type: SourceTypeCSV, FileSize: fileSize}} colCnt := int64(2) @@ -269,21 +264,21 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileNoNewLineAtEOF(c *C) { ioWorker := worker.NewPool(context.Background(), 4, "io") store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) offsets := [][]int64{{4, 13}, {13, 21}} _, regions, _, err := SplitLargeFile(context.Background(), meta, cfg, fileInfo, colCnt, prevRowIdxMax, ioWorker, store) - c.Assert(err, IsNil) - c.Assert(regions, HasLen, len(offsets)) + require.NoError(t, err) + require.Len(t, regions, len(offsets)) for i := range offsets { - c.Assert(regions[i].Chunk.Offset, Equals, offsets[i][0]) - c.Assert(regions[i].Chunk.EndOffset, Equals, offsets[i][1]) - c.Assert(regions[i].Chunk.Columns, DeepEquals, columns) + require.Equal(t, offsets[i][0], regions[i].Chunk.Offset) + require.Equal(t, offsets[i][1], regions[i].Chunk.EndOffset) + require.Equal(t, columns, regions[i].Chunk.Columns) } } -func (s *testMydumpRegionSuite) TestSplitLargeFileWithCustomTerminator(c *C) { +func TestSplitLargeFileWithCustomTerminator(t *testing.T) { meta := &MDTableMeta{ DB: "csv", Name: "large_csv_with_custom_terminator", @@ -301,17 +296,17 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileWithCustomTerminator(c *C) { }, } - dir := c.MkDir() + dir := t.TempDir() fileName := "test2.csv" filePath := filepath.Join(dir, fileName) content := []byte("5|+|abc\ndef\nghi|+|6|+|\n7|+|xyz|+|8|+|\n9|+||+|10") err := os.WriteFile(filePath, content, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) dataFileInfo, err := os.Stat(filePath) - c.Assert(err, IsNil) + require.NoError(t, err) fileSize := dataFileInfo.Size() fileInfo := FileInfo{FileMeta: SourceFileMeta{Path: fileName, Type: SourceTypeCSV, FileSize: fileSize}} colCnt := int64(3) @@ -319,20 +314,20 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileWithCustomTerminator(c *C) { ioWorker := worker.NewPool(context.Background(), 4, "io") store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) offsets := [][]int64{{0, 23}, {23, 38}, {38, 47}} _, regions, _, err := SplitLargeFile(context.Background(), meta, cfg, fileInfo, colCnt, prevRowIdxMax, ioWorker, store) - c.Assert(err, IsNil) - c.Assert(regions, HasLen, len(offsets)) + require.NoError(t, err) + require.Len(t, regions, len(offsets)) for i := range offsets { - c.Assert(regions[i].Chunk.Offset, Equals, offsets[i][0]) - c.Assert(regions[i].Chunk.EndOffset, Equals, offsets[i][1]) + require.Equal(t, offsets[i][0], regions[i].Chunk.Offset) + require.Equal(t, offsets[i][1], regions[i].Chunk.EndOffset) } } -func (s *testMydumpRegionSuite) TestSplitLargeFileOnlyOneChunk(c *C) { +func TestSplitLargeFileOnlyOneChunk(t *testing.T) { meta := &MDTableMeta{ DB: "csv", Name: "large_csv_file", @@ -355,17 +350,17 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileOnlyOneChunk(c *C) { }, } - dir := c.MkDir() + dir := t.TempDir() fileName := "test.csv" filePath := filepath.Join(dir, fileName) content := []byte("field1,field2\r\n123,456\r\n") err := os.WriteFile(filePath, content, 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) dataFileInfo, err := os.Stat(filePath) - c.Assert(err, IsNil) + require.NoError(t, err) fileSize := dataFileInfo.Size() fileInfo := FileInfo{FileMeta: SourceFileMeta{Path: fileName, Type: SourceTypeCSV, FileSize: fileSize}} colCnt := int64(2) @@ -374,16 +369,16 @@ func (s *testMydumpRegionSuite) TestSplitLargeFileOnlyOneChunk(c *C) { ioWorker := worker.NewPool(context.Background(), 4, "io") store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) offsets := [][]int64{{14, 24}} _, regions, _, err := SplitLargeFile(context.Background(), meta, cfg, fileInfo, colCnt, prevRowIdxMax, ioWorker, store) - c.Assert(err, IsNil) - c.Assert(regions, HasLen, len(offsets)) + require.NoError(t, err) + require.Len(t, regions, len(offsets)) for i := range offsets { - c.Assert(regions[i].Chunk.Offset, Equals, offsets[i][0]) - c.Assert(regions[i].Chunk.EndOffset, Equals, offsets[i][1]) - c.Assert(regions[i].Chunk.Columns, DeepEquals, columns) + require.Equal(t, offsets[i][0], regions[i].Chunk.Offset) + require.Equal(t, offsets[i][1], regions[i].Chunk.EndOffset) + require.Equal(t, columns, regions[i].Chunk.Columns) } } diff --git a/br/pkg/lightning/mydump/router.go b/br/pkg/lightning/mydump/router.go index dc9eba5b8454c..519644a8b9421 100644 --- a/br/pkg/lightning/mydump/router.go +++ b/br/pkg/lightning/mydump/router.go @@ -1,14 +1,18 @@ package mydump import ( + "net/url" "regexp" "strconv" "strings" "github.com/pingcap/errors" - "github.com/pingcap/tidb-tools/pkg/filter" - "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/util/filter" "github.com/pingcap/tidb/util/slice" + "go.uber.org/zap" + + "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/log" ) type SourceType int @@ -106,13 +110,13 @@ var defaultFileRouteRules = []*config.FileRouteRule{ // ignore *-schema-trigger.sql, *-schema-post.sql files {Pattern: `(?i).*(-schema-trigger|-schema-post)\.sql$`, Type: "ignore"}, // db schema create file pattern, matches files like '{schema}-schema-create.sql' - {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)-schema-create\.sql$`, Schema: "$1", Table: "", Type: SchemaSchema}, + {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)-schema-create\.sql$`, Schema: "$1", Table: "", Type: SchemaSchema, Unescape: true}, // table schema create file pattern, matches files like '{schema}.{table}-schema.sql' - {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)-schema\.sql$`, Schema: "$1", Table: "$2", Type: TableSchema}, + {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)-schema\.sql$`, Schema: "$1", Table: "$2", Type: TableSchema, Unescape: true}, // view schema create file pattern, matches files like '{schema}.{table}-schema-view.sql' - {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)-schema-view\.sql$`, Schema: "$1", Table: "$2", Type: ViewSchema}, + {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)-schema-view\.sql$`, Schema: "$1", Table: "$2", Type: ViewSchema, Unescape: true}, // source file pattern, matches files like '{schema}.{table}.0001.{sql|csv}' - {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)(?:\.([0-9]+))?\.(sql|csv|parquet)$`, Schema: "$1", Table: "$2", Type: "$4", Key: "$3"}, + {Pattern: `(?i)^(?:[^/]*/)*([^/.]+)\.(.*?)(?:\.([0-9]+))?\.(sql|csv|parquet)$`, Schema: "$1", Table: "$2", Type: "$4", Key: "$3", Unescape: true}, } // // RouteRule is a rule to route file path to target schema/table @@ -217,8 +221,21 @@ func (p regexRouterParser) Parse(r *config.FileRouteRule) (*RegexRouter, error) return rule, nil } + setValue := func(target *string, value string, unescape bool) { + if unescape { + val, err := url.PathUnescape(value) + if err != nil { + log.L().Warn("unescape string failed, will be ignored", zap.String("value", value), + zap.Error(err)) + } else { + value = val + } + } + *target = value + } + err = p.parseFieldExtractor(rule, "schema", r.Schema, func(result *RouteResult, value string) error { - result.Schema = value + setValue(&result.Schema, value, r.Unescape) return nil }) if err != nil { @@ -228,7 +245,7 @@ func (p regexRouterParser) Parse(r *config.FileRouteRule) (*RegexRouter, error) // special case: when the pattern is for db schema, should not parse table name if r.Type != SchemaSchema { err = p.parseFieldExtractor(rule, "table", r.Table, func(result *RouteResult, value string) error { - result.Name = value + setValue(&result.Name, value, r.Unescape) return nil }) if err != nil { diff --git a/br/pkg/lightning/mydump/router_test.go b/br/pkg/lightning/mydump/router_test.go index bbb504ef98b77..fd239688e72db 100644 --- a/br/pkg/lightning/mydump/router_test.go +++ b/br/pkg/lightning/mydump/router_test.go @@ -2,17 +2,15 @@ package mydump import ( "strings" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb-tools/pkg/filter" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/util/filter" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testFileRouterSuite{}) - -type testFileRouterSuite struct{} - -func (t *testFileRouterSuite) TestRouteParser(c *C) { +func TestRouteParser(t *testing.T) { // valid rules rules := []*config.FileRouteRule{ {Pattern: `^(?:[^/]*/)*([^/.]+)\.([^./]+)(?:\.[0-9]+)?\.(csv|sql)`, Schema: "$1", Table: "$2", Type: "$3"}, @@ -24,7 +22,7 @@ func (t *testFileRouterSuite) TestRouteParser(c *C) { } for _, r := range rules { _, err := NewFileRouter([]*config.FileRouteRule{r}) - c.Assert(err, IsNil) + assert.NoError(t, err) } // invalid rules @@ -35,48 +33,48 @@ func (t *testFileRouterSuite) TestRouteParser(c *C) { } for _, r := range invalidRules { _, err := NewFileRouter([]*config.FileRouteRule{r}) - c.Assert(err, NotNil) + assert.Error(t, err) } } -func (t *testFileRouterSuite) TestInvalidRouteRule(c *C) { +func TestInvalidRouteRule(t *testing.T) { rule := &config.FileRouteRule{} rules := []*config.FileRouteRule{rule} _, err := NewFileRouter(rules) - c.Assert(err, ErrorMatches, "`path` and `pattern` must not be both empty in \\[\\[mydumper.files\\]\\]") + require.Regexp(t, "`path` and `pattern` must not be both empty in \\[\\[mydumper.files\\]\\]", err.Error()) rule.Pattern = `^(?:[^/]*/)*([^/.]+)\.(?P[^./]+)(?:\.(?P[0-9]+))?\.(?Pcsv|sql)(?:\.(?P[A-Za-z0-9]+))?$` _, err = NewFileRouter(rules) - c.Assert(err, ErrorMatches, "field 'type' match pattern can't be empty") + require.Regexp(t, "field 'type' match pattern can't be empty", err.Error()) rule.Type = "$type" _, err = NewFileRouter(rules) - c.Assert(err, ErrorMatches, "field 'schema' match pattern can't be empty") + require.Regexp(t, "field 'schema' match pattern can't be empty", err.Error()) rule.Schema = "$schema" _, err = NewFileRouter(rules) - c.Assert(err, ErrorMatches, "invalid named capture '\\$schema'") + require.Regexp(t, "invalid named capture '\\$schema'", err.Error()) rule.Schema = "$1" _, err = NewFileRouter(rules) - c.Assert(err, ErrorMatches, "field 'table' match pattern can't be empty") + require.Regexp(t, "field 'table' match pattern can't be empty", err.Error()) rule.Table = "$table" _, err = NewFileRouter(rules) - c.Assert(err, IsNil) + require.NoError(t, err) rule.Path = "/tmp/1.sql" _, err = NewFileRouter(rules) - c.Assert(err, ErrorMatches, "can't set both `path` and `pattern` field in \\[\\[mydumper.files\\]\\]") + require.Regexp(t, "can't set both `path` and `pattern` field in \\[\\[mydumper.files\\]\\]", err.Error()) } -func (t *testFileRouterSuite) TestSingleRouteRule(c *C) { +func TestSingleRouteRule(t *testing.T) { rules := []*config.FileRouteRule{ {Pattern: `^(?:[^/]*/)*([^/.]+)\.(?P
[^./]+)(?:\.(?P[0-9]+))?\.(?Pcsv|sql)(?:\.(?P[A-Za-z0-9]+))?$`, Schema: "$1", Table: "$table", Type: "$type", Key: "$key", Compression: "$cp"}, } r, err := NewFileRouter(rules) - c.Assert(err, IsNil) + require.NoError(t, err) inputOutputMap := map[string][]string{ "my_schema.my_table.sql": {"my_schema", "my_table", "", "", "sql"}, @@ -86,13 +84,13 @@ func (t *testFileRouterSuite) TestSingleRouteRule(c *C) { } for path, fields := range inputOutputMap { res, err := r.Route(path) - c.Assert(err, IsNil) + assert.NoError(t, err) compress, e := parseCompressionType(fields[3]) - c.Assert(e, IsNil) + assert.NoError(t, e) ty, e := parseSourceType(fields[4]) - c.Assert(e, IsNil) + assert.NoError(t, e) exp := &RouteResult{filter.Table{Schema: fields[0], Name: fields[1]}, fields[2], compress, ty} - c.Assert(res, DeepEquals, exp) + assert.Equal(t, exp, res) } notMatchPaths := []string{ @@ -104,14 +102,14 @@ func (t *testFileRouterSuite) TestSingleRouteRule(c *C) { } for _, p := range notMatchPaths { res, err := r.Route(p) - c.Assert(res, IsNil) - c.Assert(err, IsNil) + assert.Nil(t, res) + assert.NoError(t, err) } rule := &config.FileRouteRule{Pattern: `^(?:[^/]*/)*([^/.]+)\.(?P
[^./]+)(?:\.(?P[0-9]+))?\.(?P\w+)(?:\.(?P[A-Za-z0-9]+))?$`, Schema: "$1", Table: "$table", Type: "$type", Key: "$key", Compression: "$cp"} r, err = NewFileRouter([]*config.FileRouteRule{rule}) - c.Assert(err, IsNil) - c.Assert(r, NotNil) + require.NoError(t, err) + require.NotNil(t, r) invalidMatchPaths := []string{ "my_schema.my_table.sql.gz", "my_schema.my_table.sql.rar", @@ -119,12 +117,12 @@ func (t *testFileRouterSuite) TestSingleRouteRule(c *C) { } for _, p := range invalidMatchPaths { res, err := r.Route(p) - c.Assert(res, IsNil) - c.Assert(err, NotNil) + assert.Nil(t, res) + assert.Error(t, err) } } -func (t *testFileRouterSuite) TestMultiRouteRule(c *C) { +func TestMultiRouteRule(t *testing.T) { // multi rule don't intersect with each other rules := []*config.FileRouteRule{ {Pattern: `(?:[^/]*/)*([^/.]+)-schema-create\.sql`, Schema: "$1", Type: SchemaSchema}, @@ -134,7 +132,7 @@ func (t *testFileRouterSuite) TestMultiRouteRule(c *C) { } r, err := NewFileRouter(rules) - c.Assert(err, IsNil) + require.NoError(t, err) inputOutputMap := map[string][]string{ "test-schema-create.sql": {"test", "", "", "", SchemaSchema}, @@ -148,16 +146,16 @@ func (t *testFileRouterSuite) TestMultiRouteRule(c *C) { } for path, fields := range inputOutputMap { res, err := r.Route(path) - c.Assert(err, IsNil) + assert.NoError(t, err) if len(fields) == 0 { - c.Assert(res, IsNil) + assert.Nil(t, res) } else { compress, e := parseCompressionType(fields[3]) - c.Assert(e, IsNil) + assert.NoError(t, e) ty, e := parseSourceType(fields[4]) - c.Assert(e, IsNil) + assert.NoError(t, e) exp := &RouteResult{filter.Table{Schema: fields[0], Name: fields[1]}, fields[2], compress, ty} - c.Assert(res, DeepEquals, exp) + assert.Equal(t, exp, res) } } @@ -166,24 +164,24 @@ func (t *testFileRouterSuite) TestMultiRouteRule(c *C) { p := &config.FileRouteRule{Pattern: `^(?P[^/.]+)\.(?P
[^./]+)(?:\.(?P[0-9]+))?\.(?Pcsv|sql)(?:\.(?P[A-Za-z0-9]+))?$`, Schema: "test_schema", Table: "test_table", Type: "$type", Key: "$key", Compression: "$cp"} rules = append(rules, p) r, err = NewFileRouter(rules) - c.Assert(err, IsNil) + require.NoError(t, err) for path, fields := range inputOutputMap { res, err := r.Route(path) - c.Assert(err, IsNil) + assert.NoError(t, err) if len(fields) == 0 { - c.Assert(res, IsNil) + assert.Nil(t, res) } else { compress, e := parseCompressionType(fields[3]) - c.Assert(e, IsNil) + assert.NoError(t, e) ty, e := parseSourceType(fields[4]) - c.Assert(e, IsNil) + assert.NoError(t, e) exp := &RouteResult{filter.Table{Schema: fields[0], Name: fields[1]}, fields[2], compress, ty} - c.Assert(res, DeepEquals, exp) + assert.Equal(t, exp, res) } } } -func (t *testFileRouterSuite) TestRouteExpanding(c *C) { +func TestRouteExpanding(t *testing.T) { rule := &config.FileRouteRule{ Pattern: `^(?:[^/]*/)*(?P[^/.]+)\.(?P[^./]+)(?:\.(?P[0-9]+))?\.(?Pcsv|sql)(?:\.(?P[A-Za-z0-9]+))?$`, Schema: "$schema", @@ -212,22 +210,22 @@ func (t *testFileRouterSuite) TestRouteExpanding(c *C) { for pat, value := range tablePatternResMap { rule.Table = pat router, err := NewFileRouter([]*config.FileRouteRule{rule}) - c.Assert(err, IsNil) + assert.NoError(t, err) res, err := router.Route(path) - c.Assert(err, IsNil) - c.Assert(res, NotNil) - c.Assert(res.Name, Equals, value) + assert.NoError(t, err) + assert.NotNil(t, res) + assert.Equal(t, value, res.Name) } invalidPatterns := []string{"$1_$schema", "$schema_$table_name", "$6"} for _, pat := range invalidPatterns { rule.Table = pat _, err := NewFileRouter([]*config.FileRouteRule{rule}) - c.Assert(err, NotNil) + assert.Error(t, err) } } -func (t *testFileRouterSuite) TestRouteWithPath(c *C) { +func TestRouteWithPath(t *testing.T) { fileName := "myschema.(my_table$1).000.sql" rule := &config.FileRouteRule{ Path: fileName, @@ -238,18 +236,18 @@ func (t *testFileRouterSuite) TestRouteWithPath(c *C) { } r := *rule router, err := NewFileRouter([]*config.FileRouteRule{&r}) - c.Assert(err, IsNil) + require.NoError(t, err) res, err := router.Route(fileName) - c.Assert(err, IsNil) - c.Assert(res, NotNil) - c.Assert(res.Schema, Equals, rule.Schema) - c.Assert(res.Name, Equals, rule.Table) + require.NoError(t, err) + require.NotNil(t, res) + require.Equal(t, rule.Schema, res.Schema) + require.Equal(t, rule.Table, res.Name) ty, _ := parseSourceType(rule.Type) - c.Assert(res.Type, Equals, ty) - c.Assert(res.Key, Equals, rule.Key) + require.Equal(t, ty, res.Type) + require.Equal(t, rule.Key, res.Key) // replace all '.' by '-', if with plain regex pattern, will still match res, err = router.Route(strings.ReplaceAll(fileName, ".", "-")) - c.Assert(err, IsNil) - c.Assert(res, IsNil) + require.NoError(t, err) + require.Nil(t, res) } diff --git a/br/pkg/lightning/restore/check_info.go b/br/pkg/lightning/restore/check_info.go index 49a8a8a9427d1..98c2c3b720fc0 100644 --- a/br/pkg/lightning/restore/check_info.go +++ b/br/pkg/lightning/restore/check_info.go @@ -17,6 +17,7 @@ package restore import ( "bytes" "context" + "database/sql" "fmt" "io" "path/filepath" @@ -24,6 +25,7 @@ import ( "sort" "strconv" "strings" + "sync" "github.com/docker/go-units" "github.com/pingcap/errors" @@ -34,19 +36,20 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/errormanager" "github.com/pingcap/tidb/br/pkg/lightning/log" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/verification" "github.com/pingcap/tidb/br/pkg/storage" + "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" - "github.com/tikv/pd/server/api" - pdconfig "github.com/tikv/pd/server/config" - "go.uber.org/zap" + "golang.org/x/sync/errgroup" "modernc.org/mathutil" ) @@ -73,7 +76,7 @@ func (rc *Controller) isSourceInLocal() bool { } func (rc *Controller) getReplicaCount(ctx context.Context) (uint64, error) { - result := &pdconfig.ReplicationConfig{} + result := &pdtypes.ReplicationConfig{} err := rc.tls.WithHost(rc.cfg.TiDB.PdAddr).GetJSON(ctx, pdReplicate, &result) if err != nil { return 0, errors.Trace(err) @@ -82,7 +85,7 @@ func (rc *Controller) getReplicaCount(ctx context.Context) (uint64, error) { } func (rc *Controller) getClusterAvail(ctx context.Context) (uint64, error) { - result := &api.StoresInfo{} + result := &pdtypes.StoresInfo{} if err := rc.tls.WithHost(rc.cfg.TiDB.PdAddr).GetJSON(ctx, pdStores, result); err != nil { return 0, errors.Trace(err) } @@ -162,7 +165,7 @@ func (rc *Controller) clusterResource(ctx context.Context, localSource int64) er } // ClusterIsAvailable check cluster is available to import data. this test can be skipped. -func (rc *Controller) ClusterIsAvailable(ctx context.Context) error { +func (rc *Controller) ClusterIsAvailable(ctx context.Context) { passed := true message := "Cluster is available" defer func() { @@ -172,13 +175,13 @@ func (rc *Controller) ClusterIsAvailable(ctx context.Context) error { DBMetas: rc.dbMetas, } if err := rc.backend.CheckRequirements(ctx, checkCtx); err != nil { + err = common.NormalizeError(err) passed = false message = fmt.Sprintf("cluster available check failed: %s", err.Error()) } - return nil } -func isTiFlash(store *api.MetaStore) bool { +func isTiFlash(store *pdtypes.MetaStore) bool { for _, label := range store.Labels { if label.Key == "engine" && label.Value == "tiflash" { return true @@ -193,7 +196,7 @@ func (rc *Controller) checkEmptyRegion(ctx context.Context) error { defer func() { rc.checkTemplate.Collect(Critical, passed, message) }() - storeInfo := &api.StoresInfo{} + storeInfo := &pdtypes.StoresInfo{} err := rc.tls.WithHost(rc.cfg.TiDB.PdAddr).GetJSON(ctx, pdStores, storeInfo) if err != nil { return errors.Trace(err) @@ -202,19 +205,19 @@ func (rc *Controller) checkEmptyRegion(ctx context.Context) error { return nil } - var result api.RegionsInfo + var result pdtypes.RegionsInfo if err := rc.tls.WithHost(rc.cfg.TiDB.PdAddr).GetJSON(ctx, pdEmptyRegions, &result); err != nil { return errors.Trace(err) } regions := make(map[uint64]int) - stores := make(map[uint64]*api.StoreInfo) + stores := make(map[uint64]*pdtypes.StoreInfo) for _, region := range result.Regions { for _, peer := range region.Peers { regions[peer.StoreId]++ } } for _, store := range storeInfo.Stores { - stores[store.Store.StoreID] = store + stores[store.Store.GetId()] = store } tableCount := 0 for _, db := range rc.dbMetas { @@ -270,12 +273,12 @@ func (rc *Controller) checkRegionDistribution(ctx context.Context) error { rc.checkTemplate.Collect(Critical, passed, message) }() - result := &api.StoresInfo{} + result := &pdtypes.StoresInfo{} err := rc.tls.WithHost(rc.cfg.TiDB.PdAddr).GetJSON(ctx, pdStores, result) if err != nil { return errors.Trace(err) } - stores := make([]*api.StoreInfo, 0, len(result.Stores)) + stores := make([]*pdtypes.StoreInfo, 0, len(result.Stores)) for _, store := range result.Stores { if metapb.StoreState(metapb.StoreState_value[store.Store.StateName]) != metapb.StoreState_Up { continue @@ -310,11 +313,11 @@ func (rc *Controller) checkRegionDistribution(ctx context.Context) error { passed = false message = fmt.Sprintf("Region distribution is unbalanced, the ratio of the regions count of the store(%v) "+ "with least regions(%v) to the store(%v) with most regions(%v) is %v, but we expect it must not be less than %v", - minStore.Store.StoreID, minStore.Status.RegionCount, maxStore.Store.StoreID, maxStore.Status.RegionCount, ratio, errorRegionCntMinMaxRatio) + minStore.Store.GetId(), minStore.Status.RegionCount, maxStore.Store.GetId(), maxStore.Status.RegionCount, ratio, errorRegionCntMinMaxRatio) } else if ratio < warnRegionCntMinMaxRatio { message = fmt.Sprintf("Region distribution is unbalanced, the ratio of the regions count of the store(%v) "+ "with least regions(%v) to the store(%v) with most regions(%v) is %v, but we expect it should not be less than %v", - minStore.Store.StoreID, minStore.Status.RegionCount, maxStore.Store.StoreID, maxStore.Status.RegionCount, ratio, warnRegionCntMinMaxRatio) + minStore.Store.GetId(), minStore.Status.RegionCount, maxStore.Store.GetId(), maxStore.Status.RegionCount, ratio, warnRegionCntMinMaxRatio) } return nil } @@ -344,7 +347,6 @@ func (rc *Controller) checkClusterRegion(ctx context.Context) error { } // StoragePermission checks whether Lightning has enough permission to storage. -// this test cannot be skipped. func (rc *Controller) StoragePermission(ctx context.Context) error { passed := true message := "Lightning has the correct storage permission" @@ -354,7 +356,7 @@ func (rc *Controller) StoragePermission(ctx context.Context) error { u, err := storage.ParseBackend(rc.cfg.Mydumper.SourceDir, nil) if err != nil { - return errors.Annotate(err, "parse backend failed") + return common.NormalizeError(err) } _, err = storage.New(ctx, u, &storage.ExternalStorageOptions{ CheckPermissions: []storage.Permission{ @@ -372,7 +374,7 @@ func (rc *Controller) StoragePermission(ctx context.Context) error { // HasLargeCSV checks whether input csvs is fit for Lightning import. // If strictFormat is false, and csv file is large. Lightning will have performance issue. // this test cannot be skipped. -func (rc *Controller) HasLargeCSV(dbMetas []*mydump.MDDatabaseMeta) error { +func (rc *Controller) HasLargeCSV(dbMetas []*mydump.MDDatabaseMeta) { passed := true message := "Source csv files size is proper" defer func() { @@ -392,7 +394,6 @@ func (rc *Controller) HasLargeCSV(dbMetas []*mydump.MDDatabaseMeta) error { } else { message = "Skip the csv size check, because config.StrictFormat is true" } - return nil } func (rc *Controller) estimateSourceData(ctx context.Context) (int64, error) { @@ -401,6 +402,7 @@ func (rc *Controller) estimateSourceData(ctx context.Context) (int64, error) { bigTableCount := 0 tableCount := 0 unSortedTableCount := 0 + errMgr := errormanager.New(nil, rc.cfg) for _, db := range rc.dbMetas { info, ok := rc.dbInfos[db.Name] if !ok { @@ -417,10 +419,17 @@ func (rc *Controller) estimateSourceData(ctx context.Context) (int64, error) { tbl.IndexRatio = 1.0 tbl.IsRowOrdered = false } else { - if err := rc.sampleDataFromTable(ctx, db.Name, tbl, tableInfo.Core); err != nil { + if err := rc.sampleDataFromTable(ctx, db.Name, tbl, tableInfo.Core, errMgr); err != nil { return sourceSize, errors.Trace(err) } - sourceSize += int64(float64(tbl.TotalSize) * tbl.IndexRatio) + + if tbl.IndexRatio > 0 { + sourceSize += int64(float64(tbl.TotalSize) * tbl.IndexRatio) + } else { + // if sample data failed due to max-error, fallback to use source size + sourceSize += tbl.TotalSize + } + if tbl.TotalSize > int64(config.DefaultBatchSize)*2 { bigTableCount += 1 if !tbl.IsRowOrdered { @@ -464,51 +473,49 @@ func (rc *Controller) localResource(sourceSize int64) error { if err != nil { return errors.Trace(err) } - localAvailable := storageSize.Available + localAvailable := int64(storageSize.Available) var message string var passed bool switch { - case localAvailable > uint64(sourceSize): + case localAvailable > sourceSize: message = fmt.Sprintf("local disk resources are rich, estimate sorted data size %s, local available is %s", units.BytesSize(float64(sourceSize)), units.BytesSize(float64(localAvailable))) passed = true + case int64(rc.cfg.TikvImporter.DiskQuota) > localAvailable: + message = fmt.Sprintf("local disk space may not enough to finish import, estimate sorted data size is %s,"+ + " but local available is %s, please set `tikv-importer.disk-quota` to a smaller value than %s"+ + " or change `mydumper.sorted-kv-dir` to another disk with enough space to finish imports", + units.BytesSize(float64(sourceSize)), + units.BytesSize(float64(localAvailable)), units.BytesSize(float64(localAvailable))) + passed = false + log.L().Error(message) default: - if int64(rc.cfg.TikvImporter.DiskQuota) > int64(localAvailable) { - message = fmt.Sprintf("local disk space may not enough to finish import"+ - "estimate sorted data size is %s, but local available is %s,"+ - "you need a smaller number for tikv-importer.disk-quota (%s) to finish imports", - units.BytesSize(float64(sourceSize)), - units.BytesSize(float64(localAvailable)), units.BytesSize(float64(rc.cfg.TikvImporter.DiskQuota))) - passed = false - log.L().Error(message) - } else { - message = fmt.Sprintf("local disk space may not enough to finish import, "+ - "estimate sorted data size is %s, but local available is %s,"+ - "we will use disk-quota (size: %s) to finish imports, which may slow down import", - units.BytesSize(float64(sourceSize)), - units.BytesSize(float64(localAvailable)), units.BytesSize(float64(rc.cfg.TikvImporter.DiskQuota))) - passed = true - log.L().Warn(message) - } + message = fmt.Sprintf("local disk space may not enough to finish import, "+ + "estimate sorted data size is %s, but local available is %s,"+ + "we will use disk-quota (size: %s) to finish imports, which may slow down import", + units.BytesSize(float64(sourceSize)), + units.BytesSize(float64(localAvailable)), units.BytesSize(float64(rc.cfg.TikvImporter.DiskQuota))) + passed = true + log.L().Warn(message) } rc.checkTemplate.Collect(Critical, passed, message) return nil } // CheckpointIsValid checks whether we can start this import with this checkpoint. -func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.MDTableMeta) ([]string, bool, error) { +func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.MDTableMeta) ([]string, bool) { msgs := make([]string, 0) uniqueName := common.UniqueTable(tableInfo.DB, tableInfo.Name) tableCheckPoint, err := rc.checkpointsDB.Get(ctx, uniqueName) if err != nil { // there is no checkpoint log.L().Debug("no checkpoint detected", zap.String("table", uniqueName)) - return nil, true, nil + return nil, true } // if checkpoint enable and not missing, we skip the check table empty progress. if tableCheckPoint.Status <= checkpoints.CheckpointStatusMissing { - return nil, false, nil + return nil, false } if tableCheckPoint.Status <= checkpoints.CheckpointStatusMaxInvalid { @@ -530,7 +537,7 @@ func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.M "You may also run `./tidb-lightning-ctl --checkpoint-error-destroy=all --config=...` to start from scratch,"+ "For details of this failure, read the log file from the PREVIOUS run", uniqueName, failedStep.MetricName(), action.String())) - return msgs, false, nil + return msgs, false } dbInfo, ok := rc.dbInfos[tableInfo.DB] @@ -543,7 +550,7 @@ func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.M "You may also run `./tidb-lightning-ctl --checkpoint-error-destroy=all --config=...` to start from scratch,"+ "For details of this failure, read the log file from the PREVIOUS run", uniqueName)) - return msgs, false, nil + return msgs, false } } } @@ -564,7 +571,7 @@ func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.M } if len(columns) == 0 { log.L().Debug("no valid checkpoint detected", zap.String("table", uniqueName)) - return nil, false, nil + return nil, false } info := rc.dbInfos[tableInfo.DB].Tables[tableInfo.Name] if info != nil { @@ -578,7 +585,7 @@ func (rc *Controller) CheckpointIsValid(ctx context.Context, tableInfo *mydump.M "consider remove this checkpoint, and start import again.", uniqueName)) } } - return msgs, false, nil + return msgs, false } // hasDefault represents col has default value. @@ -739,8 +746,8 @@ func (rc *Controller) SchemaIsValid(ctx context.Context, tableInfo *mydump.MDTab if _, ok := defaultCols[col]; ok { continue } - msgs = append(msgs, fmt.Sprintf("TiDB schema `%s`.`%s` doesn't have the default value for %s"+ - "please give a default value for %s or choose another column to ignore or add this column in data file", + msgs = append(msgs, fmt.Sprintf("TiDB schema `%s`.`%s` doesn't have the default value for %s. "+ + "Please add default value for column '%s' or choose another column to ignore or add this column in data file", tableInfo.DB, tableInfo.Name, col, col)) } return msgs, nil @@ -795,8 +802,6 @@ outer: if tableCSVCount >= 2 && hasUniqueIdx { tableMeta = tblMeta - csvCount = tableCSVCount - hasUniqueIdx = tableHasUniqueIdx // if a perfect table source is found, we can stop check more tables break outer } @@ -925,7 +930,13 @@ func checkFieldCompatibility(tbl *model.TableInfo, ignoreCols map[string]struct{ return true } -func (rc *Controller) sampleDataFromTable(ctx context.Context, dbName string, tableMeta *mydump.MDTableMeta, tableInfo *model.TableInfo) error { +func (rc *Controller) sampleDataFromTable( + ctx context.Context, + dbName string, + tableMeta *mydump.MDTableMeta, + tableInfo *model.TableInfo, + errMgr *errormanager.ErrorManager, +) error { if len(tableMeta.DataFiles) == 0 { return nil } @@ -942,13 +953,18 @@ func (rc *Controller) sampleDataFromTable(ctx context.Context, dbName string, ta } idAlloc := kv.NewPanickingAllocators(0) tbl, err := tables.TableFromMeta(idAlloc, tableInfo) - + if err != nil { + return errors.Trace(err) + } kvEncoder, err := rc.backend.NewEncoder(tbl, &kv.SessionOptions{ SQLMode: rc.cfg.TiDB.SQLMode, Timestamp: 0, SysVars: rc.sysVars, AutoRandomSeed: 0, }) + if err != nil { + return errors.Trace(err) + } blockBufSize := int64(rc.cfg.Mydumper.ReadBlockSize) var parser mydump.Parser @@ -981,7 +997,7 @@ func (rc *Controller) sampleDataFromTable(ctx context.Context, dbName string, ta return errors.Trace(err) } - initializedColumns, reachEOF := false, false + initializedColumns := false var columnPermutation []int var kvSize uint64 = 0 var rowSize uint64 = 0 @@ -992,7 +1008,7 @@ func (rc *Controller) sampleDataFromTable(ctx context.Context, dbName string, ta tableMeta.IsRowOrdered = true tableMeta.IndexRatio = 1.0 outloop: - for !reachEOF { + for { offset, _ := parser.Pos() err = parser.ReadRow() columnNames := parser.Columns() @@ -1009,22 +1025,27 @@ outloop: initializedColumns = true } case io.EOF: - reachEOF = true break outloop default: err = errors.Annotatef(err, "in file offset %d", offset) return errors.Trace(err) } lastRow := parser.LastRow() - rowSize += uint64(lastRow.Length) rowCount += 1 var dataChecksum, indexChecksum verification.KVChecksum kvs, encodeErr := kvEncoder.Encode(logTask.Logger, lastRow.Row, lastRow.RowID, columnPermutation, sampleFile.Path, offset) - parser.RecycleRow(lastRow) if encodeErr != nil { - err = errors.Annotatef(encodeErr, "in file at offset %d", offset) - return errors.Trace(err) + encodeErr = errMgr.RecordTypeError(ctx, log.L(), tableInfo.Name.O, sampleFile.Path, offset, + "" /* use a empty string here because we don't actually record */, encodeErr) + if encodeErr != nil { + return errors.Annotatef(encodeErr, "in file at offset %d", offset) + } + if rowCount < maxSampleRowCount { + continue + } else { + break + } } if tableMeta.IsRowOrdered { kvs.ClassifyAndAppend(&dataKVs, &dataChecksum, &indexKVs, &indexChecksum) @@ -1040,11 +1061,13 @@ outloop: indexKVs = indexKVs.Clear() } kvSize += kvs.Size() + rowSize += uint64(lastRow.Length) + parser.RecycleRow(lastRow) failpoint.Inject("mock-kv-size", func(val failpoint.Value) { kvSize += uint64(val.(int)) }) - if rowSize > maxSampleDataSize && rowCount > maxSampleRowCount { + if rowSize > maxSampleDataSize || rowCount > maxSampleRowCount { break } } @@ -1055,3 +1078,98 @@ outloop: log.L().Info("Sample source data", zap.String("table", tableMeta.Name), zap.Float64("IndexRatio", tableMeta.IndexRatio), zap.Bool("IsSourceOrder", tableMeta.IsRowOrdered)) return nil } + +func (rc *Controller) checkTableEmpty(ctx context.Context) error { + if rc.cfg.TikvImporter.Backend == config.BackendTiDB || rc.cfg.TikvImporter.IncrementalImport { + return nil + } + db, _ := rc.tidbGlue.GetDB() + + tableCount := 0 + for _, db := range rc.dbMetas { + tableCount += len(db.Tables) + } + + var lock sync.Mutex + tableNames := make([]string, 0) + concurrency := utils.MinInt(tableCount, rc.cfg.App.RegionConcurrency) + ch := make(chan string, concurrency) + eg, gCtx := errgroup.WithContext(ctx) + + for i := 0; i < concurrency; i++ { + eg.Go(func() error { + for tblName := range ch { + // skip tables that have checkpoint + if rc.cfg.Checkpoint.Enable { + _, err := rc.checkpointsDB.Get(gCtx, tblName) + switch { + case err == nil: + continue + case errors.IsNotFound(err): + default: + return errors.Trace(err) + } + } + + hasData, err1 := tableContainsData(gCtx, db, tblName) + if err1 != nil { + return err1 + } + if hasData { + lock.Lock() + tableNames = append(tableNames, tblName) + lock.Unlock() + } + } + return nil + }) + } +loop: + for _, db := range rc.dbMetas { + for _, tbl := range db.Tables { + select { + case ch <- common.UniqueTable(tbl.DB, tbl.Name): + case <-gCtx.Done(): + break loop + } + + } + } + close(ch) + if err := eg.Wait(); err != nil { + if common.IsContextCanceledError(err) { + return nil + } + return errors.Annotate(err, "check table contains data failed") + } + + if len(tableNames) > 0 { + // sort the failed names + sort.Strings(tableNames) + msg := fmt.Sprintf("table(s) [%s] are not empty", strings.Join(tableNames, ", ")) + rc.checkTemplate.Collect(Critical, false, msg) + } + return nil +} + +func tableContainsData(ctx context.Context, db utils.DBExecutor, tableName string) (bool, error) { + failpoint.Inject("CheckTableEmptyFailed", func() { + failpoint.Return(false, errors.New("mock error")) + }) + query := "select 1 from " + tableName + " limit 1" + exec := common.SQLWithRetry{ + DB: db, + Logger: log.L(), + } + var dump int + err := exec.QueryRow(ctx, "check table empty", query, &dump) + + switch { + case errors.ErrorEqual(err, sql.ErrNoRows): + return false, nil + case err != nil: + return false, errors.Trace(err) + default: + return true, nil + } +} diff --git a/br/pkg/lightning/restore/check_info_test.go b/br/pkg/lightning/restore/check_info_test.go index e1dd939d9c2b1..cfd9a00adc53a 100644 --- a/br/pkg/lightning/restore/check_info_test.go +++ b/br/pkg/lightning/restore/check_info_test.go @@ -16,18 +16,24 @@ package restore import ( "context" + "database/sql" "fmt" "os" "path/filepath" + "testing" - . "github.com/pingcap/check" + "github.com/DATA-DOG/go-sqlmock" + "github.com/pingcap/failpoint" + "github.com/stretchr/testify/require" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/glue" "github.com/pingcap/tidb/br/pkg/lightning/mydump" "github.com/pingcap/tidb/br/pkg/lightning/worker" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" @@ -35,17 +41,14 @@ import ( tmock "github.com/pingcap/tidb/util/mock" ) -var _ = Suite(&checkInfoSuite{}) - -type checkInfoSuite struct{} - const passed CheckType = "pass" -func (s *checkInfoSuite) TestCheckCSVHeader(c *C) { - dir := c.MkDir() +func TestCheckCSVHeader(t *testing.T) { + dir := t.TempDir() + ctx := context.Background() mockStore, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) + require.NoError(t, err) type tableSource struct { Name string @@ -359,9 +362,9 @@ func (s *checkInfoSuite) TestCheckCSVHeader(c *C) { for _, tbl := range tbls { node, err := p.ParseOneStmt(tbl.SQL, "", "") - c.Assert(err, IsNil) + require.NoError(t, err) core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) - c.Assert(err, IsNil) + require.NoError(t, err) core.State = model.StatePublic dbInfo.Tables[tbl.Name] = &checkpoints.TidbTableInfo{ ID: core.ID, @@ -374,7 +377,7 @@ func (s *checkInfoSuite) TestCheckCSVHeader(c *C) { for i, s := range tbl.Sources { fileName := fmt.Sprintf("%s.%s.%d.csv", db, tbl.Name, i) err = os.WriteFile(filepath.Join(dir, fileName), []byte(s), 0o644) - c.Assert(err, IsNil) + require.NoError(t, err) fileInfos = append(fileInfos, mydump.FileInfo{ FileMeta: mydump.SourceFileMeta{ Path: fileName, @@ -396,10 +399,215 @@ func (s *checkInfoSuite) TestCheckCSVHeader(c *C) { } err := rc.checkCSVHeader(ctx, dbMetas) - c.Assert(err, IsNil) + require.NoError(t, err) if ca.level != passed { - c.Assert(rc.checkTemplate.FailedCount(ca.level), Equals, 1) + require.Equal(t, 1, rc.checkTemplate.FailedCount(ca.level)) } } +} + +func TestCheckTableEmpty(t *testing.T) { + dir := t.TempDir() + + cfg := config.NewConfig() + cfg.Checkpoint.Enable = false + dbMetas := []*mydump.MDDatabaseMeta{ + { + Name: "test1", + Tables: []*mydump.MDTableMeta{ + { + DB: "test1", + Name: "tbl1", + }, + { + DB: "test1", + Name: "tbl2", + }, + }, + }, + { + Name: "test2", + Tables: []*mydump.MDTableMeta{ + { + DB: "test2", + Name: "tbl1", + }, + }, + }, + } + + rc := &Controller{ + cfg: cfg, + dbMetas: dbMetas, + checkpointsDB: checkpoints.NewNullCheckpointsDB(), + } + + ctx := context.Background() + + // test tidb will do nothing + rc.cfg.TikvImporter.Backend = config.BackendTiDB + err := rc.checkTableEmpty(ctx) + require.NoError(t, err) + + // test incremental mode + rc.cfg.TikvImporter.Backend = config.BackendLocal + rc.cfg.TikvImporter.IncrementalImport = true + err = rc.checkTableEmpty(ctx) + require.NoError(t, err) + + rc.cfg.TikvImporter.IncrementalImport = false + db, mock, err := sqlmock.New() + require.NoError(t, err) + mock.MatchExpectationsInOrder(false) + rc.tidbGlue = glue.NewExternalTiDBGlue(db, mysql.ModeNone) + mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + mock.ExpectQuery("select 1 from `test1`.`tbl2` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + mock.ExpectQuery("select 1 from `test2`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + // not error, need not to init check template + err = rc.checkTableEmpty(ctx) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) + + // single table contains data + db, mock, err = sqlmock.New() + require.NoError(t, err) + rc.tidbGlue = glue.NewExternalTiDBGlue(db, mysql.ModeNone) + mock.MatchExpectationsInOrder(false) + // test auto retry retryable error + mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). + WillReturnError(mysql.NewErr(errno.ErrPDServerTimeout)) + mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + mock.ExpectQuery("select 1 from `test1`.`tbl2` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + mock.ExpectQuery("select 1 from `test2`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).AddRow(1)) + rc.checkTemplate = NewSimpleTemplate() + err = rc.checkTableEmpty(ctx) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) + + tmpl := rc.checkTemplate.(*SimpleTemplate) + require.Equal(t, 1, len(tmpl.criticalMsgs)) + require.Equal(t, "table(s) [`test2`.`tbl1`] are not empty", tmpl.criticalMsgs[0]) + + // multi tables contains data + db, mock, err = sqlmock.New() + require.NoError(t, err) + rc.tidbGlue = glue.NewExternalTiDBGlue(db, mysql.ModeNone) + mock.MatchExpectationsInOrder(false) + mock.ExpectQuery("select 1 from `test1`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).AddRow(1)) + mock.ExpectQuery("select 1 from `test1`.`tbl2` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + mock.ExpectQuery("select 1 from `test2`.`tbl1` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).AddRow(1)) + rc.checkTemplate = NewSimpleTemplate() + err = rc.checkTableEmpty(ctx) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) + + tmpl = rc.checkTemplate.(*SimpleTemplate) + require.Equal(t, 1, len(tmpl.criticalMsgs)) + require.Equal(t, "table(s) [`test1`.`tbl1`, `test2`.`tbl1`] are not empty", tmpl.criticalMsgs[0]) + + // init checkpoint with only two of the three tables + dbInfos := map[string]*checkpoints.TidbDBInfo{ + "test1": { + Name: "test1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "tbl1": { + Name: "tbl1", + }, + }, + }, + "test2": { + Name: "test2", + Tables: map[string]*checkpoints.TidbTableInfo{ + "tbl1": { + Name: "tbl1", + }, + }, + }, + } + rc.cfg.Checkpoint.Enable = true + rc.checkpointsDB, err = checkpoints.NewFileCheckpointsDB(ctx, filepath.Join(dir, "cp.pb")) + require.NoError(t, err) + err = rc.checkpointsDB.Initialize(ctx, cfg, dbInfos) + require.NoError(t, err) + db, mock, err = sqlmock.New() + require.NoError(t, err) + rc.tidbGlue = glue.NewExternalTiDBGlue(db, mysql.ModeNone) + // only need to check the one that is not in checkpoint + mock.ExpectQuery("select 1 from `test1`.`tbl2` limit 1"). + WillReturnRows(sqlmock.NewRows([]string{""}).RowError(0, sql.ErrNoRows)) + err = rc.checkTableEmpty(ctx) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) + + err = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/CheckTableEmptyFailed", `return`) + require.NoError(t, err) + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/CheckTableEmptyFailed") + }() + + // restrict the concurrency to ensure there are more tables than workers + rc.cfg.App.RegionConcurrency = 1 + // test check tables not stuck but return the right error + err = rc.checkTableEmpty(ctx) + require.Regexp(t, ".*check table contains data failed: mock error.*", err.Error()) +} + +func TestLocalResource(t *testing.T) { + dir := t.TempDir() + + mockStore, err := storage.NewLocalStorage(dir) + require.NoError(t, err) + + err = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/common/GetStorageSize", "return(2048)") + require.NoError(t, err) + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/common/GetStorageSize") + }() + + cfg := config.NewConfig() + cfg.Mydumper.SourceDir = dir + cfg.TikvImporter.SortedKVDir = dir + cfg.TikvImporter.Backend = "local" + rc := &Controller{ + cfg: cfg, + store: mockStore, + ioWorkers: worker.NewPool(context.Background(), 1, "io"), + } + + // 1. source-size is smaller than disk-size, won't trigger error information + rc.checkTemplate = NewSimpleTemplate() + err = rc.localResource(1000) + require.NoError(t, err) + tmpl := rc.checkTemplate.(*SimpleTemplate) + require.Equal(t, 1, tmpl.warnFailedCount) + require.Equal(t, 0, tmpl.criticalFailedCount) + require.Equal(t, "local disk resources are rich, estimate sorted data size 1000B, local available is 2KiB", tmpl.normalMsgs[1]) + + // 2. source-size is bigger than disk-size, with default disk-quota will trigger a critical error + rc.checkTemplate = NewSimpleTemplate() + err = rc.localResource(4096) + require.NoError(t, err) + tmpl = rc.checkTemplate.(*SimpleTemplate) + require.Equal(t, 1, tmpl.warnFailedCount) + require.Equal(t, 1, tmpl.criticalFailedCount) + require.Equal(t, "local disk space may not enough to finish import, estimate sorted data size is 4KiB, but local available is 2KiB, please set `tikv-importer.disk-quota` to a smaller value than 2KiB or change `mydumper.sorted-kv-dir` to another disk with enough space to finish imports", tmpl.criticalMsgs[0]) + // 3. source-size is bigger than disk-size, with a vaild disk-quota will trigger a warning + rc.checkTemplate = NewSimpleTemplate() + rc.cfg.TikvImporter.DiskQuota = config.ByteSize(1024) + err = rc.localResource(4096) + require.NoError(t, err) + tmpl = rc.checkTemplate.(*SimpleTemplate) + require.Equal(t, 1, tmpl.warnFailedCount) + require.Equal(t, 0, tmpl.criticalFailedCount) + require.Equal(t, "local disk space may not enough to finish import, estimate sorted data size is 4KiB, but local available is 2KiB,we will use disk-quota (size: 1KiB) to finish imports, which may slow down import", tmpl.normalMsgs[1]) } diff --git a/br/pkg/lightning/restore/check_template.go b/br/pkg/lightning/restore/check_template.go index 3fb8c22904caa..f02410116b3dd 100644 --- a/br/pkg/lightning/restore/check_template.go +++ b/br/pkg/lightning/restore/check_template.go @@ -15,7 +15,6 @@ package restore import ( - "fmt" "strings" "github.com/jedib0t/go-pretty/v6/table" @@ -51,7 +50,8 @@ type SimpleTemplate struct { count int warnFailedCount int criticalFailedCount int - failedMsg []string + normalMsgs []string // only used in unit test now + criticalMsgs []string t table.Writer } @@ -65,16 +65,12 @@ func NewSimpleTemplate() Template { {Name: "Passed", WidthMax: 6}, }) return &SimpleTemplate{ - 0, - 0, - 0, - make([]string, 0), - t, + t: t, } } func (c *SimpleTemplate) FailedMsg() string { - return strings.Join(c.failedMsg, ";\n") + return strings.Join(c.criticalMsgs, ";\n") } func (c *SimpleTemplate) Collect(t CheckType, passed bool, msg string) { @@ -87,7 +83,11 @@ func (c *SimpleTemplate) Collect(t CheckType, passed bool, msg string) { c.warnFailedCount++ } } - c.failedMsg = append(c.failedMsg, msg) + if !passed && t == Critical { + c.criticalMsgs = append(c.criticalMsgs, msg) + } else { + c.normalMsgs = append(c.normalMsgs, msg) + } c.t.AppendRow(table.Row{c.count, msg, t, passed}) c.t.AppendSeparator() } @@ -108,7 +108,7 @@ func (c *SimpleTemplate) FailedCount(t CheckType) int { func (c *SimpleTemplate) Output() string { c.t.SetAllowedRowLength(170) - c.t.SetRowPainter(table.RowPainter(func(row table.Row) text.Colors { + c.t.SetRowPainter(func(row table.Row) text.Colors { if passed, ok := row[3].(bool); ok { if !passed { if typ, ok := row[2].(CheckType); ok { @@ -122,18 +122,6 @@ func (c *SimpleTemplate) Output() string { } } return nil - })) - res := c.t.Render() - summary := "\n" - if c.criticalFailedCount > 0 { - summary += fmt.Sprintf("%d critical check failed", c.criticalFailedCount) - } - if c.warnFailedCount > 0 { - msg := fmt.Sprintf("%d performance check failed", c.warnFailedCount) - if len(summary) > 1 { - msg = "," + msg - } - summary += msg - } - return res + summary + }) + return c.t.Render() + "\n" } diff --git a/br/pkg/lightning/restore/checksum.go b/br/pkg/lightning/restore/checksum.go index 5b7a5b1501af4..2bac40505cdc0 100644 --- a/br/pkg/lightning/restore/checksum.go +++ b/br/pkg/lightning/restore/checksum.go @@ -20,7 +20,6 @@ import ( "database/sql" "fmt" "sync" - "sync/atomic" "time" "github.com/google/uuid" @@ -40,6 +39,7 @@ import ( "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" + "go.uber.org/atomic" "go.uber.org/zap" ) @@ -279,12 +279,8 @@ func newTiKVChecksumManager(client kv.Client, pdClient pd.Client, distSQLScanCon } } -func (e *tikvChecksumManager) checksumDB(ctx context.Context, tableInfo *checkpoints.TidbTableInfo) (*RemoteChecksum, error) { - physicalTS, logicalTS, err := e.manager.pdClient.GetTS(ctx) - if err != nil { - return nil, errors.Annotate(err, "fetch tso from pd failed") - } - executor, err := checksum.NewExecutorBuilder(tableInfo.Core, oracle.ComposeTS(physicalTS, logicalTS)). +func (e *tikvChecksumManager) checksumDB(ctx context.Context, tableInfo *checkpoints.TidbTableInfo, ts uint64) (*RemoteChecksum, error) { + executor, err := checksum.NewExecutorBuilder(tableInfo.Core, ts). SetConcurrency(e.distSQLScanConcurrency). Build() if err != nil { @@ -327,12 +323,17 @@ func (e *tikvChecksumManager) checksumDB(ctx context.Context, tableInfo *checkpo func (e *tikvChecksumManager) Checksum(ctx context.Context, tableInfo *checkpoints.TidbTableInfo) (*RemoteChecksum, error) { tbl := common.UniqueTable(tableInfo.DB, tableInfo.Name) - err := e.manager.addOneJob(ctx, tbl, oracle.ComposeTS(time.Now().Unix()*1000, 0)) + physicalTS, logicalTS, err := e.manager.pdClient.GetTS(ctx) if err != nil { + return nil, errors.Annotate(err, "fetch tso from pd failed") + } + ts := oracle.ComposeTS(physicalTS, logicalTS) + if err := e.manager.addOneJob(ctx, tbl, ts); err != nil { return nil, errors.Trace(err) } + defer e.manager.removeOneJob(tbl) - return e.checksumDB(ctx, tableInfo) + return e.checksumDB(ctx, tableInfo, ts) } type tableChecksumTS struct { @@ -372,7 +373,7 @@ type gcTTLManager struct { currentTS uint64 serviceID string // 0 for not start, otherwise started - started uint32 + started atomic.Bool } func newGCTTLManager(pdClient pd.Client) gcTTLManager { @@ -384,7 +385,7 @@ func newGCTTLManager(pdClient pd.Client) gcTTLManager { func (m *gcTTLManager) addOneJob(ctx context.Context, table string, ts uint64) error { // start gc ttl loop if not started yet. - if atomic.CompareAndSwapUint32(&m.started, 0, 1) { + if m.started.CAS(false, true) { m.start(ctx) } m.lock.Lock() diff --git a/br/pkg/lightning/restore/checksum_test.go b/br/pkg/lightning/restore/checksum_test.go index 6a9f334b31f9a..3954c12672c4f 100644 --- a/br/pkg/lightning/restore/checksum_test.go +++ b/br/pkg/lightning/restore/checksum_test.go @@ -7,11 +7,10 @@ import ( "sort" "strings" "sync" - "sync/atomic" + "testing" "time" "github.com/DATA-DOG/go-sqlmock" - . "github.com/pingcap/check" "github.com/pingcap/errors" . "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/ddl" @@ -19,27 +18,27 @@ import ( "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/memory" tmock "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/trxevents" "github.com/pingcap/tipb/go-tipb" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" + "go.uber.org/atomic" ) -var _ = Suite(&checksumSuite{}) - -type checksumSuite struct{} - func MockDoChecksumCtx(db *sql.DB) context.Context { ctx := context.Background() manager := newTiDBChecksumExecutor(db) return context.WithValue(ctx, &checksumManagerKey, manager) } -func (s *checksumSuite) TestDoChecksum(c *C) { +func TestDoChecksum(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, mock.ExpectationsWereMet()) + }() mock.ExpectQuery("\\QSELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E"). WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) @@ -58,22 +57,23 @@ func (s *checksumSuite) TestDoChecksum(c *C) { ctx := MockDoChecksumCtx(db) checksum, err := DoChecksum(ctx, &TidbTableInfo{DB: "test", Name: "t"}) - c.Assert(err, IsNil) - c.Assert(*checksum, DeepEquals, RemoteChecksum{ + require.NoError(t, err) + require.Equal(t, RemoteChecksum{ Schema: "test", Table: "t", Checksum: 8520875019404689597, TotalKVs: 7296873, TotalBytes: 357601387, - }) - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) + }, *checksum) } -func (s *checksumSuite) TestDoChecksumParallel(c *C) { +func TestDoChecksumParallel(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, mock.ExpectationsWereMet()) + }() mock.ExpectQuery("\\QSELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E"). WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) @@ -101,25 +101,26 @@ func (s *checksumSuite) TestDoChecksumParallel(c *C) { for i := 0; i < 5; i++ { wg.Run(func() { checksum, err := DoChecksum(ctx, &TidbTableInfo{DB: "test", Name: "t"}) - c.Assert(err, IsNil) - c.Assert(*checksum, DeepEquals, RemoteChecksum{ + require.NoError(t, err) + require.Equal(t, RemoteChecksum{ Schema: "test", Table: "t", Checksum: 8520875019404689597, TotalKVs: 7296873, TotalBytes: 357601387, - }) + }, *checksum) }) } wg.Wait() - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) } -func (s *checksumSuite) TestIncreaseGCLifeTimeFail(c *C) { +func TestIncreaseGCLifeTimeFail(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, mock.ExpectationsWereMet()) + }() for i := 0; i < 5; i++ { mock.ExpectQuery("\\QSELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E"). @@ -140,19 +141,16 @@ func (s *checksumSuite) TestIncreaseGCLifeTimeFail(c *C) { for i := 0; i < 5; i++ { wg.Run(func() { _, errChecksum := DoChecksum(ctx, &TidbTableInfo{DB: "test", Name: "t"}) - c.Assert(errChecksum, ErrorMatches, "update GC lifetime failed: update gc error: context canceled") + require.Equal(t, "update GC lifetime failed: update gc error: context canceled", errChecksum.Error()) }) } wg.Wait() _, err = db.Exec("\\QUPDATE mysql.tidb SET VARIABLE_VALUE = ? WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E", "10m") - c.Assert(err, IsNil) - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) + require.NoError(t, err) } -func (s *checksumSuite) TestDoChecksumWithTikv(c *C) { +func TestDoChecksumWithTikv(t *testing.T) { // set up mock tikv checksum manager pdClient := &testPDClient{} resp := tipb.ChecksumResponse{Checksum: 123, TotalKvs: 10, TotalBytes: 1000} @@ -162,39 +160,52 @@ func (s *checksumSuite) TestDoChecksumWithTikv(c *C) { p := parser.New() se := tmock.NewContext() node, err := p.ParseOneStmt("CREATE TABLE `t1` (`c1` varchar(5) NOT NULL)", "utf8mb4", "utf8mb4_bin") - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 999) - c.Assert(err, IsNil) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() for i := 0; i <= maxErrorRetryCount; i++ { kvClient.maxErrCount = i kvClient.curErrCount = 0 + var checksumTS uint64 + kvClient.onSendReq = func(req *kv.Request) { + checksumTS = req.StartTs + } checksumExec := &tikvChecksumManager{manager: newGCTTLManager(pdClient), client: kvClient} - startTS := oracle.ComposeTS(time.Now().Unix()*1000, 0) - ctx := context.WithValue(context.Background(), &checksumManagerKey, checksumExec) - _, err = DoChecksum(ctx, &TidbTableInfo{DB: "test", Name: "t", Core: tableInfo}) + physicalTS, logicalTS, err := pdClient.GetTS(ctx) + require.NoError(t, err) + subCtx := context.WithValue(ctx, &checksumManagerKey, checksumExec) + _, err = DoChecksum(subCtx, &TidbTableInfo{DB: "test", Name: "t", Core: tableInfo}) // with max error retry < maxErrorRetryCount, the checksum can success if i >= maxErrorRetryCount { - c.Assert(err, ErrorMatches, "tikv timeout") + require.Equal(t, "tikv timeout", err.Error()) continue } else { - c.Assert(err, IsNil) + require.NoError(t, err) } // after checksum, safepint should be small than start ts ts := pdClient.currentSafePoint() // 1ms for the schedule deviation - c.Assert(ts <= startTS+1, IsTrue) - c.Assert(atomic.LoadUint32(&checksumExec.manager.started) > 0, IsTrue) + startTS := oracle.ComposeTS(physicalTS+1, logicalTS) + require.True(t, ts <= startTS+1) + require.GreaterOrEqual(t, checksumTS, ts) + require.True(t, checksumExec.manager.started.Load()) + require.Zero(t, checksumExec.manager.currentTS) + require.Equal(t, 0, len(checksumExec.manager.tableGCSafeTS)) } } -func (s *checksumSuite) TestDoChecksumWithTikvErrRetry(c *C) { -} - -func (s *checksumSuite) TestDoChecksumWithErrorAndLongOriginalLifetime(c *C) { +func TestDoChecksumWithErrorAndLongOriginalLifetime(t *testing.T) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, mock.ExpectationsWereMet()) + }() mock.ExpectQuery("\\QSELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E"). WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("300h")) @@ -207,23 +218,20 @@ func (s *checksumSuite) TestDoChecksumWithErrorAndLongOriginalLifetime(c *C) { ctx := MockDoChecksumCtx(db) _, err = DoChecksum(ctx, &TidbTableInfo{DB: "test", Name: "t"}) - c.Assert(err, ErrorMatches, "compute remote checksum failed: mock syntax error.*") - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) + require.Regexp(t, "compute remote checksum failed: mock syntax error.*", err.Error()) } type safePointTTL struct { safePoint uint64 - // ttl is the last timestamp this safe point is valid - ttl int64 + expiredAt int64 } type testPDClient struct { sync.Mutex pd.Client - count int32 - gcSafePoint []safePointTTL + count atomic.Int32 + gcSafePoint []safePointTTL + logicalTSCounter atomic.Uint64 } func (c *testPDClient) currentSafePoint() uint64 { @@ -231,7 +239,7 @@ func (c *testPDClient) currentSafePoint() uint64 { c.Lock() defer c.Unlock() for _, s := range c.gcSafePoint { - if s.ttl > ts { + if s.expiredAt > ts { return s.safePoint } } @@ -239,27 +247,29 @@ func (c *testPDClient) currentSafePoint() uint64 { } func (c *testPDClient) GetTS(ctx context.Context) (int64, int64, error) { - return time.Now().Unix(), 0, nil + physicalTS := time.Now().UnixNano() / 1e6 + logicalTS := oracle.ExtractLogical(c.logicalTSCounter.Inc()) + return physicalTS, logicalTS, nil } func (c *testPDClient) UpdateServiceGCSafePoint(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { if !strings.HasPrefix(serviceID, "lightning") { panic("service ID must start with 'lightning'") } - atomic.AddInt32(&c.count, 1) + c.count.Add(1) c.Lock() idx := sort.Search(len(c.gcSafePoint), func(i int) bool { return c.gcSafePoint[i].safePoint >= safePoint }) sp := c.gcSafePoint ttlEnd := time.Now().Unix() + ttl - spTTL := safePointTTL{safePoint: safePoint, ttl: ttlEnd} + spTTL := safePointTTL{safePoint: safePoint, expiredAt: ttlEnd} switch { case idx >= len(sp): c.gcSafePoint = append(c.gcSafePoint, spTTL) case sp[idx].safePoint == safePoint: - if ttlEnd > sp[idx].ttl { - sp[idx].ttl = ttlEnd + if ttlEnd > sp[idx].expiredAt { + sp[idx].expiredAt = ttlEnd } default: c.gcSafePoint = append(append(sp[:idx], spTTL), sp[idx:]...) @@ -268,10 +278,10 @@ func (c *testPDClient) UpdateServiceGCSafePoint(ctx context.Context, serviceID s return c.currentSafePoint(), nil } -func (s *checksumSuite) TestGcTTLManagerSingle(c *C) { +func TestGcTTLManagerSingle(t *testing.T) { pdClient := &testPDClient{} manager := newGCTTLManager(pdClient) - c.Assert(manager.serviceID, Not(Equals), "") + require.NotEqual(t, "", manager.serviceID) ctx, cancel := context.WithCancel(context.Background()) defer cancel() oldTTL := serviceSafePointTTL @@ -282,56 +292,56 @@ func (s *checksumSuite) TestGcTTLManagerSingle(c *C) { }() err := manager.addOneJob(ctx, "test", uint64(time.Now().Unix())) - c.Assert(err, IsNil) + require.NoError(t, err) time.Sleep(2*time.Second + 10*time.Millisecond) // after 2 seconds, must at least update 5 times - val := atomic.LoadInt32(&pdClient.count) - c.Assert(val, GreaterEqual, int32(5)) + val := pdClient.count.Load() + require.GreaterOrEqual(t, val, int32(5)) // after remove the job, there are no job remain, gc ttl needn't to be updated manager.removeOneJob("test") time.Sleep(10 * time.Millisecond) - val = atomic.LoadInt32(&pdClient.count) + val = pdClient.count.Load() time.Sleep(1*time.Second + 10*time.Millisecond) - c.Assert(atomic.LoadInt32(&pdClient.count), Equals, val) + require.Equal(t, val, pdClient.count.Load()) } -func (s *checksumSuite) TestGcTTLManagerMulti(c *C) { +func TestGcTTLManagerMulti(t *testing.T) { manager := newGCTTLManager(&testPDClient{}) ctx := context.Background() for i := uint64(1); i <= 5; i++ { err := manager.addOneJob(ctx, fmt.Sprintf("test%d", i), i) - c.Assert(err, IsNil) - c.Assert(manager.currentTS, Equals, uint64(1)) + require.NoError(t, err) + require.Equal(t, uint64(1), manager.currentTS) } manager.removeOneJob("test2") - c.Assert(manager.currentTS, Equals, uint64(1)) + require.Equal(t, uint64(1), manager.currentTS) manager.removeOneJob("test1") - c.Assert(manager.currentTS, Equals, uint64(3)) + require.Equal(t, uint64(3), manager.currentTS) manager.removeOneJob("test3") - c.Assert(manager.currentTS, Equals, uint64(4)) + require.Equal(t, uint64(4), manager.currentTS) manager.removeOneJob("test4") - c.Assert(manager.currentTS, Equals, uint64(5)) + require.Equal(t, uint64(5), manager.currentTS) manager.removeOneJob("test5") - c.Assert(manager.currentTS, Equals, uint64(0)) + require.Equal(t, uint64(0), manager.currentTS) } -func (s *checksumSuite) TestPdServiceID(c *C) { +func TestPdServiceID(t *testing.T) { pdCli := &testPDClient{} gcTTLManager1 := newGCTTLManager(pdCli) - c.Assert(gcTTLManager1.serviceID, Matches, "lightning-.*") + require.Regexp(t, "lightning-.*", gcTTLManager1.serviceID) gcTTLManager2 := newGCTTLManager(pdCli) - c.Assert(gcTTLManager2.serviceID, Matches, "lightning-.*") + require.Regexp(t, "lightning-.*", gcTTLManager2.serviceID) - c.Assert(gcTTLManager1.serviceID != gcTTLManager2.serviceID, IsTrue) + require.True(t, gcTTLManager1.serviceID != gcTTLManager2.serviceID) } type mockResponse struct { @@ -385,15 +395,19 @@ func (r *mockResultSubset) RespTime() time.Duration { type mockChecksumKVClient struct { kv.Client - checksum tipb.ChecksumResponse - respDur time.Duration + checksum tipb.ChecksumResponse + respDur time.Duration + onSendReq func(req *kv.Request) // return error count before return success maxErrCount int curErrCount int } // a mock client for checksum request -func (c *mockChecksumKVClient) Send(ctx context.Context, req *kv.Request, vars interface{}, sessionMemTracker *memory.Tracker, enabledRateLimitAction bool, eventCb trxevents.EventCallback) kv.Response { +func (c *mockChecksumKVClient) Send(ctx context.Context, req *kv.Request, vars interface{}, option *kv.ClientSendOption) kv.Response { + if c.onSendReq != nil { + c.onSendReq(req) + } if c.curErrCount < c.maxErrCount { c.curErrCount++ return &mockErrorResponse{err: "tikv timeout"} diff --git a/br/pkg/lightning/restore/chunk_restore_test.go b/br/pkg/lightning/restore/chunk_restore_test.go new file mode 100644 index 0000000000000..bc683e8a1c36e --- /dev/null +++ b/br/pkg/lightning/restore/chunk_restore_test.go @@ -0,0 +1,568 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package restore + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/golang/mock/gomock" + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/kvproto/pkg/import_kvpb" + "github.com/pingcap/tidb/br/pkg/lightning/backend" + "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" + "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" + "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" + "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" + "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/errormanager" + "github.com/pingcap/tidb/br/pkg/lightning/mydump" + "github.com/pingcap/tidb/br/pkg/lightning/worker" + "github.com/pingcap/tidb/br/pkg/mock" + "github.com/pingcap/tidb/br/pkg/storage" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type chunkRestoreSuite struct { + suite.Suite + tableRestoreSuiteBase + cr *chunkRestore +} + +func TestChunkRestoreSuite(t *testing.T) { + suite.Run(t, new(chunkRestoreSuite)) +} + +func (s *chunkRestoreSuite) SetupSuite() { + s.setupSuite(s.T()) +} + +func (s *chunkRestoreSuite) SetupTest() { + s.setupTest(s.T()) + + ctx := context.Background() + w := worker.NewPool(ctx, 5, "io") + + chunk := checkpoints.ChunkCheckpoint{ + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[1].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 18, + RowIDMax: 36, + }, + } + + var err error + s.cr, err = newChunkRestore(context.Background(), 1, s.cfg, &chunk, w, s.store, nil) + require.NoError(s.T(), err) +} + +func (s *chunkRestoreSuite) TearDownTest() { + s.cr.close() +} + +func (s *chunkRestoreSuite) TestDeliverLoopCancel() { + rc := &Controller{backend: importer.NewMockImporter(nil, "")} + + ctx, cancel := context.WithCancel(context.Background()) + kvsCh := make(chan []deliveredKVs) + go cancel() + _, err := s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, nil, nil, rc) + require.Equal(s.T(), context.Canceled, errors.Cause(err)) +} + +func (s *chunkRestoreSuite) TestDeliverLoopEmptyData() { + ctx := context.Background() + + // Open two mock engines. + + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + importer := backend.MakeBackend(mockBackend) + + mockBackend.EXPECT().OpenEngine(ctx, gomock.Any(), gomock.Any()).Return(nil).Times(2) + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).AnyTimes() + mockWriter := mock.NewMockEngineWriter(controller) + mockBackend.EXPECT().LocalWriter(ctx, gomock.Any(), gomock.Any()).Return(mockWriter, nil).AnyTimes() + mockWriter.EXPECT(). + AppendRows(ctx, gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil).AnyTimes() + + dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) + require.NoError(s.T(), err) + dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) + require.NoError(s.T(), err) + indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + + // Deliver nothing. + + cfg := &config.Config{} + rc := &Controller{cfg: cfg, backend: importer, diskQuotaLock: newDiskQuotaLock()} + + kvsCh := make(chan []deliveredKVs, 1) + kvsCh <- []deliveredKVs{} + _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) + require.NoError(s.T(), err) +} + +func (s *chunkRestoreSuite) TestDeliverLoop() { + ctx := context.Background() + kvsCh := make(chan []deliveredKVs) + mockCols := []string{"c1", "c2"} + + // Open two mock engines. + + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + importer := backend.MakeBackend(mockBackend) + + mockBackend.EXPECT().OpenEngine(ctx, gomock.Any(), gomock.Any()).Return(nil).Times(2) + // avoid return the same object at each call + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) + mockWriter := mock.NewMockEngineWriter(controller) + mockBackend.EXPECT().LocalWriter(ctx, gomock.Any(), gomock.Any()).Return(mockWriter, nil).AnyTimes() + mockWriter.EXPECT().IsSynced().Return(true).AnyTimes() + + dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) + require.NoError(s.T(), err) + indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) + require.NoError(s.T(), err) + + dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + + // Set up the expected API calls to the data engine... + + mockWriter.EXPECT(). + AppendRows(ctx, s.tr.tableName, mockCols, kv.MakeRowsFromKvPairs([]common.KvPair{ + { + Key: []byte("txxxxxxxx_ryyyyyyyy"), + Val: []byte("value1"), + }, + { + Key: []byte("txxxxxxxx_rwwwwwwww"), + Val: []byte("value2"), + }, + })). + Return(nil) + + // ... and the index engine. + // + // Note: This test assumes data engine is written before the index engine. + + mockWriter.EXPECT(). + AppendRows(ctx, s.tr.tableName, mockCols, kv.MakeRowsFromKvPairs([]common.KvPair{ + { + Key: []byte("txxxxxxxx_izzzzzzzz"), + Val: []byte("index1"), + }, + })). + Return(nil) + + // Now actually start the delivery loop. + + saveCpCh := make(chan saveCp, 2) + go func() { + kvsCh <- []deliveredKVs{ + { + kvs: kv.MakeRowFromKvPairs([]common.KvPair{ + { + Key: []byte("txxxxxxxx_ryyyyyyyy"), + Val: []byte("value1"), + }, + { + Key: []byte("txxxxxxxx_rwwwwwwww"), + Val: []byte("value2"), + }, + { + Key: []byte("txxxxxxxx_izzzzzzzz"), + Val: []byte("index1"), + }, + }), + columns: mockCols, + offset: 12, + rowID: 76, + }, + } + kvsCh <- []deliveredKVs{} + close(kvsCh) + }() + + cfg := &config.Config{} + rc := &Controller{cfg: cfg, saveCpCh: saveCpCh, backend: importer, diskQuotaLock: newDiskQuotaLock()} + + _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) + require.NoError(s.T(), err) + require.Len(s.T(), saveCpCh, 2) + require.Equal(s.T(), int64(12), s.cr.chunk.Chunk.Offset) + require.Equal(s.T(), int64(76), s.cr.chunk.Chunk.PrevRowIDMax) + require.Equal(s.T(), uint64(3), s.cr.chunk.Checksum.SumKVS()) +} + +func (s *chunkRestoreSuite) TestEncodeLoop() { + ctx := context.Background() + kvsCh := make(chan []deliveredKVs, 2) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567895, + }) + require.NoError(s.T(), err) + cfg := config.NewConfig() + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.NoError(s.T(), err) + require.Len(s.T(), kvsCh, 2) + + kvs := <-kvsCh + require.Len(s.T(), kvs, 1) + require.Equal(s.T(), int64(19), kvs[0].rowID) + require.Equal(s.T(), int64(36), kvs[0].offset) + require.Equal(s.T(), []string(nil), kvs[0].columns) + + kvs = <-kvsCh + require.Equal(s.T(), 0, len(kvs)) +} + +func (s *chunkRestoreSuite) TestEncodeLoopCanceled() { + ctx, cancel := context.WithCancel(context.Background()) + kvsCh := make(chan []deliveredKVs) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567896, + }) + require.NoError(s.T(), err) + + go cancel() + cfg := config.NewConfig() + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.Equal(s.T(), context.Canceled, errors.Cause(err)) + require.Len(s.T(), kvsCh, 0) +} + +func (s *chunkRestoreSuite) TestEncodeLoopForcedError() { + ctx := context.Background() + kvsCh := make(chan []deliveredKVs, 2) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567897, + }) + require.NoError(s.T(), err) + + // close the chunk so reading it will result in the "file already closed" error. + s.cr.parser.Close() + + cfg := config.NewConfig() + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.Regexp(s.T(), `in file .*[/\\]?db\.table\.2\.sql:0 at offset 0:.*file already closed`, err.Error()) + require.Len(s.T(), kvsCh, 0) +} + +func (s *chunkRestoreSuite) TestEncodeLoopDeliverLimit() { + ctx := context.Background() + kvsCh := make(chan []deliveredKVs, 4) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567898, + }) + require.NoError(s.T(), err) + + dir := s.T().TempDir() + + fileName := "db.limit.000.csv" + err = os.WriteFile(filepath.Join(dir, fileName), []byte("1,2,3\r\n4,5,6\r\n7,8,9\r"), 0o644) + require.NoError(s.T(), err) + + store, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + cfg := config.NewConfig() + + reader, err := store.Open(ctx, fileName) + require.NoError(s.T(), err) + w := worker.NewPool(ctx, 1, "io") + p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, false, nil) + require.NoError(s.T(), err) + s.cr.parser = p + + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + require.NoError(s.T(), failpoint.Enable( + "github.com/pingcap/tidb/br/pkg/lightning/restore/mock-kv-size", "return(110000000)")) + defer failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/mock-kv-size") + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.NoError(s.T(), err) + + // we have 3 kvs total. after the failpoint injected. + // we will send one kv each time. + count := 0 + for { + kvs, ok := <-kvsCh + if !ok { + break + } + count += 1 + if count <= 3 { + require.Len(s.T(), kvs, 1) + } + if count == 4 { + // we will send empty kvs before encodeLoop exists + // so, we can receive 4 batch and 1 is empty + require.Len(s.T(), kvs, 0) + break + } + } +} + +func (s *chunkRestoreSuite) TestEncodeLoopDeliverErrored() { + ctx := context.Background() + kvsCh := make(chan []deliveredKVs) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567898, + }) + require.NoError(s.T(), err) + + go func() { + deliverCompleteCh <- deliverResult{ + err: errors.New("fake deliver error"), + } + }() + cfg := config.NewConfig() + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.Equal(s.T(), "fake deliver error", err.Error()) + require.Len(s.T(), kvsCh, 0) +} + +func (s *chunkRestoreSuite) TestEncodeLoopColumnsMismatch() { + dir := s.T().TempDir() + + fileName := "db.table.000.csv" + err := os.WriteFile(filepath.Join(dir, fileName), []byte("1,2\r\n4,5,6,7\r\n"), 0o644) + require.NoError(s.T(), err) + + store, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + + ctx := context.Background() + cfg := config.NewConfig() + errorMgr := errormanager.New(nil, cfg) + rc := &Controller{pauser: DeliverPauser, cfg: cfg, errorMgr: errorMgr} + + reader, err := store.Open(ctx, fileName) + require.NoError(s.T(), err) + w := worker.NewPool(ctx, 5, "io") + p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, false, nil) + require.NoError(s.T(), err) + + err = s.cr.parser.Close() + require.NoError(s.T(), err) + s.cr.parser = p + + kvsCh := make(chan []deliveredKVs, 2) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := tidb.NewTiDBBackend(nil, config.ReplaceOnDup, errorMgr).NewEncoder( + s.tr.encTable, + &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567895, + }) + require.NoError(s.T(), err) + defer kvEncoder.Close() + + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.Equal(s.T(), "[Lightning:Restore:ErrEncodeKV]encode kv error in file db.table.2.sql:0 at offset 4: column count mismatch, expected 3, got 2", err.Error()) + require.Len(s.T(), kvsCh, 0) +} + +func (s *chunkRestoreSuite) TestEncodeLoopIgnoreColumnsCSV() { + cases := []struct { + s string + ignoreColumns []*config.IgnoreColumns + kvs deliveredKVs + header bool + }{ + { + "1,2,3\r\n4,5,6\r\n", + []*config.IgnoreColumns{ + { + DB: "db", + Table: "table", + Columns: []string{"a"}, + }, + }, + deliveredKVs{ + rowID: 1, + offset: 6, + columns: []string{"b", "c"}, + }, + false, + }, + { + "b,c\r\n2,3\r\n5,6\r\n", + []*config.IgnoreColumns{ + { + TableFilter: []string{"db*.tab*"}, + Columns: []string{"b"}, + }, + }, + deliveredKVs{ + rowID: 1, + offset: 9, + columns: []string{"c"}, + }, + true, + }, + } + + for _, cs := range cases { + // reset test + s.SetupTest() + s.testEncodeLoopIgnoreColumnsCSV(cs.s, cs.ignoreColumns, cs.kvs, cs.header) + } +} + +func (s *chunkRestoreSuite) testEncodeLoopIgnoreColumnsCSV( + f string, + ignoreColumns []*config.IgnoreColumns, + deliverKV deliveredKVs, + header bool, +) { + dir := s.T().TempDir() + + fileName := "db.table.000.csv" + err := os.WriteFile(filepath.Join(dir, fileName), []byte(f), 0o644) + require.NoError(s.T(), err) + + store, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + + ctx := context.Background() + cfg := config.NewConfig() + cfg.Mydumper.IgnoreColumns = ignoreColumns + cfg.Mydumper.CSV.Header = header + rc := &Controller{pauser: DeliverPauser, cfg: cfg} + + reader, err := store.Open(ctx, fileName) + require.NoError(s.T(), err) + w := worker.NewPool(ctx, 5, "io") + p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, cfg.Mydumper.CSV.Header, nil) + require.NoError(s.T(), err) + + err = s.cr.parser.Close() + require.NoError(s.T(), err) + s.cr.parser = p + + kvsCh := make(chan []deliveredKVs, 2) + deliverCompleteCh := make(chan deliverResult) + kvEncoder, err := tidb.NewTiDBBackend(nil, config.ReplaceOnDup, errormanager.New(nil, config.NewConfig())).NewEncoder( + s.tr.encTable, + &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 1234567895, + }) + require.NoError(s.T(), err) + defer kvEncoder.Close() + + _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) + require.NoError(s.T(), err) + require.Len(s.T(), kvsCh, 2) + + kvs := <-kvsCh + require.Len(s.T(), kvs, 2) + require.Equal(s.T(), deliverKV.rowID, kvs[0].rowID) + require.Equal(s.T(), deliverKV.offset, kvs[0].offset) + require.Equal(s.T(), deliverKV.columns, kvs[0].columns) + + kvs = <-kvsCh + require.Equal(s.T(), 0, len(kvs)) +} + +func (s *chunkRestoreSuite) TestRestore() { + ctx := context.Background() + + // Open two mock engines + + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockClient := mock.NewMockImportKVClient(controller) + mockDataWriter := mock.NewMockImportKV_WriteEngineClient(controller) + mockIndexWriter := mock.NewMockImportKV_WriteEngineClient(controller) + importer := importer.NewMockImporter(mockClient, "127.0.0.1:2379") + + mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) + mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) + + dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) + require.NoError(s.T(), err) + indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) + require.NoError(s.T(), err) + dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) + require.NoError(s.T(), err) + + // Expected API sequence + // (we don't care about the actual content, this would be checked in the integrated tests) + + mockClient.EXPECT().WriteEngine(ctx).Return(mockDataWriter, nil) + mockDataWriter.EXPECT().Send(gomock.Any()).Return(nil) + mockDataWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { + require.Len(s.T(), req.GetBatch().GetMutations(), 1) + return nil + }) + mockDataWriter.EXPECT().CloseAndRecv().Return(nil, nil) + + mockClient.EXPECT().WriteEngine(ctx).Return(mockIndexWriter, nil) + mockIndexWriter.EXPECT().Send(gomock.Any()).Return(nil) + mockIndexWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { + require.Len(s.T(), req.GetBatch().GetMutations(), 1) + return nil + }) + mockIndexWriter.EXPECT().CloseAndRecv().Return(nil, nil) + + // Now actually start the restore loop. + + saveCpCh := make(chan saveCp, 2) + err = s.cr.restore(ctx, s.tr, 0, dataWriter, indexWriter, &Controller{ + cfg: s.cfg, + saveCpCh: saveCpCh, + backend: importer, + pauser: DeliverPauser, + diskQuotaLock: newDiskQuotaLock(), + }) + require.NoError(s.T(), err) + require.Len(s.T(), saveCpCh, 2) +} diff --git a/br/pkg/lightning/restore/meta_manager.go b/br/pkg/lightning/restore/meta_manager.go index 544b91c0b5f90..6c009279e9e0f 100644 --- a/br/pkg/lightning/restore/meta_manager.go +++ b/br/pkg/lightning/restore/meta_manager.go @@ -156,7 +156,7 @@ func parseMetaStatus(s string) (metaStatus, error) { case "finish": return metaStatusFinished, nil default: - return metaStatusInitial, errors.Errorf("invalid meta status '%s'", s) + return metaStatusInitial, common.ErrInvalidMetaStatus.GenWithStackByArgs(s) } } @@ -180,8 +180,11 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 } needAutoID := common.TableHasAutoRowID(m.tr.tableInfo.Core) || m.tr.tableInfo.Core.GetAutoIncrementColInfo() != nil || m.tr.tableInfo.Core.ContainsAutoRandomBits() err = exec.Transact(ctx, "init table allocator base", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id, row_id_base, row_id_max, total_kvs_base, total_bytes_base, checksum_base, status from %s WHERE table_id = ? FOR UPDATE", m.tableName) - rows, err := tx.QueryContext(ctx, query, m.tr.tableInfo.ID) + rows, err := tx.QueryContext( + ctx, + fmt.Sprintf("SELECT task_id, row_id_base, row_id_max, total_kvs_base, total_bytes_base, checksum_base, status from %s WHERE table_id = ? FOR UPDATE", m.tableName), + m.tr.tableInfo.ID, + ) if err != nil { return errors.Trace(err) } @@ -197,7 +200,7 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 } status, err := parseMetaStatus(statusValue) if err != nil { - return errors.Annotatef(err, "invalid meta status '%s'", statusValue) + return err } // skip finished meta @@ -206,7 +209,7 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 } if status == metaStatusChecksuming { - return errors.New("target table is calculating checksum, please wait unit the checksum is finished and try again.") + return common.ErrAllocTableRowIDs.GenWithStack("Target table is calculating checksum. Please wait until the checksum is finished and try again.") } if metaTaskID == m.taskID { @@ -216,7 +219,7 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 baseTotalBytes = totalBytes if status >= metaStatusRowIDAllocated { if rowIDMax-rowIDBase != rawRowIDMax { - return errors.Errorf("verify allocator base failed. local: '%d', meta: '%d'", rawRowIDMax, rowIDMax-rowIDBase) + return common.ErrAllocTableRowIDs.GenWithStack("verify allocator base failed. local: '%d', meta: '%d'", rawRowIDMax, rowIDMax-rowIDBase) } newRowIDBase = rowIDBase newRowIDMax = rowIDMax @@ -257,7 +260,7 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 autoIDField = model.ExtraHandleName.L } if len(autoIDField) == 0 { - return errors.Errorf("table %s contains auto increment id or _tidb_rowid, but target field not found", m.tr.tableName) + return common.ErrAllocTableRowIDs.GenWithStack("table %s contains auto increment id or _tidb_rowid, but target field not found", m.tr.tableName) } autoIDInfos, err := tidb.FetchTableAutoIDInfos(ctx, tx, m.tr.tableName) @@ -273,7 +276,7 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 } } if !found { - return errors.Errorf("can't fetch previous auto id base for table %s field '%s'", m.tr.tableName, autoIDField) + return common.ErrAllocTableRowIDs.GenWithStack("can't fetch previous auto id base for table %s field '%s'", m.tr.tableName, autoIDField) } } newRowIDBase = maxRowIDMax @@ -282,7 +285,9 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64 if needAutoID && newRowIDBase == 0 && newStatus < metaStatusRestoreStarted { newStatus = metaStatusRestoreStarted } - query = fmt.Sprintf("update %s set row_id_base = ?, row_id_max = ?, status = ? where table_id = ? and task_id = ?", m.tableName) + + // nolint:gosec + query := fmt.Sprintf("update %s set row_id_base = ?, row_id_max = ?, status = ? where table_id = ? and task_id = ?", m.tableName) _, err := tx.ExecContext(ctx, query, newRowIDBase, newRowIDMax, newStatus.String(), m.tr.tableInfo.ID, m.taskID) if err != nil { return errors.Trace(err) @@ -381,8 +386,11 @@ func (m *dbTableMetaMgr) CheckAndUpdateLocalChecksum(ctx context.Context, checks needChecksum = true needRemoteDupe = true err = exec.Transact(ctx, "checksum pre-check", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id, total_kvs_base, total_bytes_base, checksum_base, total_kvs, total_bytes, checksum, status, has_duplicates from %s WHERE table_id = ? FOR UPDATE", m.tableName) - rows, err := tx.QueryContext(ctx, query, m.tr.tableInfo.ID) + rows, err := tx.QueryContext( + ctx, + fmt.Sprintf("SELECT task_id, total_kvs_base, total_bytes_base, checksum_base, total_kvs, total_bytes, checksum, status, has_duplicates from %s WHERE table_id = ? FOR UPDATE", m.tableName), + m.tr.tableInfo.ID, + ) if err != nil { return errors.Annotate(err, "fetch task meta failed") } @@ -402,7 +410,7 @@ func (m *dbTableMetaMgr) CheckAndUpdateLocalChecksum(ctx context.Context, checks } status, err := parseMetaStatus(statusValue) if err != nil { - return errors.Annotatef(err, "invalid meta status '%s'", statusValue) + return err } if taskHasDuplicates { @@ -431,7 +439,7 @@ func (m *dbTableMetaMgr) CheckAndUpdateLocalChecksum(ctx context.Context, checks needRemoteDupe = false break } else if status == metaStatusChecksuming { - return errors.New("another task is checksuming, there must be something wrong!") + return common.ErrTableIsChecksuming.GenWithStackByArgs(m.tableName) } totalBytes += baseTotalBytes @@ -448,7 +456,8 @@ func (m *dbTableMetaMgr) CheckAndUpdateLocalChecksum(ctx context.Context, checks return errors.Trace(rows.Err()) } - query = fmt.Sprintf("update %s set total_kvs = ?, total_bytes = ?, checksum = ?, status = ?, has_duplicates = ? where table_id = ? and task_id = ?", m.tableName) + // nolint:gosec + query := fmt.Sprintf("update %s set total_kvs = ?, total_bytes = ?, checksum = ?, status = ?, has_duplicates = ? where table_id = ? and task_id = ?", m.tableName) _, err = tx.ExecContext(ctx, query, checksum.SumKVS(), checksum.SumSize(), checksum.Sum(), newStatus.String(), hasLocalDupes, m.tr.tableInfo.ID, m.taskID) return errors.Annotate(err, "update local checksum failed") }) @@ -556,7 +565,7 @@ func parseTaskMetaStatus(s string) (taskMetaStatus, error) { case "switched": return taskMetaStatusSwitchBack, nil default: - return taskMetaStatusInitial, errors.Errorf("invalid meta status '%s'", s) + return taskMetaStatusInitial, common.ErrInvalidMetaStatus.GenWithStackByArgs(s) } } @@ -593,8 +602,10 @@ func (m *dbTaskMetaMgr) CheckTaskExist(ctx context.Context) (bool, error) { // avoid override existing metadata if the meta is already inserted. exist := false err := exec.Transact(ctx, "check whether this task has started before", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id from %s WHERE task_id = %d", m.tableName, m.taskID) - rows, err := tx.QueryContext(ctx, query) + rows, err := tx.QueryContext(ctx, + fmt.Sprintf("SELECT task_id from %s WHERE task_id = ?", m.tableName), + m.taskID, + ) if err != nil { return errors.Annotate(err, "fetch task meta failed") } @@ -635,8 +646,10 @@ func (m *dbTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(t return errors.Annotate(err, "enable pessimistic transaction failed") } return exec.Transact(ctx, "check tasks exclusively", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id, pd_cfgs, status, state, source_bytes, cluster_avail from %s FOR UPDATE", m.tableName) - rows, err := tx.QueryContext(ctx, query) + rows, err := tx.QueryContext( + ctx, + fmt.Sprintf("SELECT task_id, pd_cfgs, status, state, source_bytes, cluster_avail from %s FOR UPDATE", m.tableName), + ) if err != nil { return errors.Annotate(err, "fetch task metas failed") } @@ -651,7 +664,7 @@ func (m *dbTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(t } status, err := parseTaskMetaStatus(statusValue) if err != nil { - return errors.Annotatef(err, "invalid task meta status '%s'", statusValue) + return err } task.status = status tasks = append(tasks, task) @@ -664,6 +677,7 @@ func (m *dbTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(t return errors.Trace(err) } for _, task := range newTasks { + // nolint:gosec query := fmt.Sprintf("REPLACE INTO %s (task_id, pd_cfgs, status, state, source_bytes, cluster_avail) VALUES(?, ?, ?, ?, ?, ?)", m.tableName) if _, err = tx.ExecContext(ctx, query, task.taskID, task.pdCfgs, task.status.String(), task.state, task.sourceBytes, task.clusterAvail); err != nil { return errors.Trace(err) @@ -695,8 +709,10 @@ func (m *dbTaskMetaMgr) CheckAndPausePdSchedulers(ctx context.Context) (pdutil.U paused := false var pausedCfg storedCfgs err = exec.Transact(ctx, "check and pause schedulers", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id, pd_cfgs, status, state from %s FOR UPDATE", m.tableName) - rows, err := tx.QueryContext(ctx, query) + rows, err := tx.QueryContext( + ctx, + fmt.Sprintf("SELECT task_id, pd_cfgs, status, state from %s FOR UPDATE", m.tableName), + ) if err != nil { return errors.Annotate(err, "fetch task meta failed") } @@ -719,7 +735,7 @@ func (m *dbTaskMetaMgr) CheckAndPausePdSchedulers(ctx context.Context) (pdutil.U } status, err := parseTaskMetaStatus(statusValue) if err != nil { - return errors.Annotatef(err, "invalid task meta status '%s'", statusValue) + return err } if status == taskMetaStatusInitial { @@ -769,7 +785,8 @@ func (m *dbTaskMetaMgr) CheckAndPausePdSchedulers(ctx context.Context) (pdutil.U return errors.Trace(err) } - query = fmt.Sprintf("update %s set pd_cfgs = ?, status = ? where task_id = ?", m.tableName) + // nolint:gosec + query := fmt.Sprintf("update %s set pd_cfgs = ?, status = ? where task_id = ?", m.tableName) _, err = tx.ExecContext(ctx, query, string(jsonByts), taskMetaStatusScheduleSet.String(), m.taskID) return errors.Annotate(err, "update task pd configs failed") @@ -821,8 +838,7 @@ func (m *dbTaskMetaMgr) CheckAndFinishRestore(ctx context.Context, finished bool switchBack := true allFinished := finished err = exec.Transact(ctx, "check and finish schedulers", func(ctx context.Context, tx *sql.Tx) error { - query := fmt.Sprintf("SELECT task_id, status, state from %s FOR UPDATE", m.tableName) - rows, err := tx.QueryContext(ctx, query) + rows, err := tx.QueryContext(ctx, fmt.Sprintf("SELECT task_id, status, state from %s FOR UPDATE", m.tableName)) if err != nil { return errors.Annotate(err, "fetch task meta failed") } @@ -845,7 +861,7 @@ func (m *dbTaskMetaMgr) CheckAndFinishRestore(ctx context.Context, finished bool } status, err := parseTaskMetaStatus(statusValue) if err != nil { - return errors.Annotatef(err, "invalid task meta status '%s'", statusValue) + return err } if taskID == m.taskID { @@ -882,7 +898,8 @@ func (m *dbTaskMetaMgr) CheckAndFinishRestore(ctx context.Context, finished bool newStatus = taskMetaStatusSwitchSkipped } - query = fmt.Sprintf("update %s set status = ?, state = ? where task_id = ?", m.tableName) + // nolint:gosec + query := fmt.Sprintf("update %s set status = ?, state = ? where task_id = ?", m.tableName) if _, err = tx.ExecContext(ctx, query, newStatus.String(), newState, m.taskID); err != nil { return errors.Trace(err) } @@ -1027,9 +1044,65 @@ func (m noopTableMetaMgr) UpdateTableBaseChecksum(ctx context.Context, checksum } func (m noopTableMetaMgr) CheckAndUpdateLocalChecksum(ctx context.Context, checksum *verify.KVChecksum, hasLocalDupes bool) (bool, bool, *verify.KVChecksum, error) { - return false, false, nil, nil + return true, true, &verify.KVChecksum{}, nil } func (m noopTableMetaMgr) FinishTable(ctx context.Context) error { return nil } + +type singleMgrBuilder struct{} + +func (b singleMgrBuilder) Init(context.Context) error { + return nil +} + +func (b singleMgrBuilder) TaskMetaMgr(pd *pdutil.PdController) taskMetaMgr { + return &singleTaskMetaMgr{ + pd: pd, + } +} + +func (b singleMgrBuilder) TableMetaMgr(tr *TableRestore) tableMetaMgr { + return noopTableMetaMgr{} +} + +type singleTaskMetaMgr struct { + pd *pdutil.PdController +} + +func (m *singleTaskMetaMgr) InitTask(ctx context.Context, source int64) error { + return nil +} + +func (m *singleTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(tasks []taskMeta) ([]taskMeta, error)) error { + _, err := action(nil) + return err +} + +func (m *singleTaskMetaMgr) CheckAndPausePdSchedulers(ctx context.Context) (pdutil.UndoFunc, error) { + return m.pd.RemoveSchedulers(ctx) +} + +func (m *singleTaskMetaMgr) CheckTaskExist(ctx context.Context) (bool, error) { + return true, nil +} + +func (m *singleTaskMetaMgr) CheckAndFinishRestore(context.Context, bool) (shouldSwitchBack bool, shouldCleanupMeta bool, err error) { + return true, true, nil +} + +func (m *singleTaskMetaMgr) Cleanup(ctx context.Context) error { + return nil +} + +func (m *singleTaskMetaMgr) CleanupTask(ctx context.Context) error { + return nil +} + +func (m *singleTaskMetaMgr) CleanupAllMetas(ctx context.Context) error { + return nil +} + +func (m *singleTaskMetaMgr) Close() { +} diff --git a/br/pkg/lightning/restore/meta_manager_test.go b/br/pkg/lightning/restore/meta_manager_test.go index 31a3c35569c67..571a9d6cd5844 100644 --- a/br/pkg/lightning/restore/meta_manager_test.go +++ b/br/pkg/lightning/restore/meta_manager_test.go @@ -6,9 +6,9 @@ import ( "context" "database/sql/driver" "sort" + "testing" "github.com/DATA-DOG/go-sqlmock" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/log" @@ -18,26 +18,24 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" tmock "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) -var _ = Suite(&metaMgrSuite{}) - type metaMgrSuite struct { mockDB sqlmock.Sqlmock - tr *TableRestore mgr *dbTableMetaMgr checksumMgr *testChecksumMgr } -func (s *metaMgrSuite) SetUpSuite(c *C) { +func newTableRestore(t *testing.T) *TableRestore { p := parser.New() se := tmock.NewContext() node, err := p.ParseOneStmt("CREATE TABLE `t1` (`c1` varchar(5) NOT NULL)", "utf8mb4", "utf8mb4_bin") - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), int64(1)) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo.State = model.StatePublic schema := "test" @@ -51,33 +49,36 @@ func (s *metaMgrSuite) SetUpSuite(c *C) { tableName := common.UniqueTable(schema, tb) logger := log.With(zap.String("table", tableName)) - s.tr = &TableRestore{ + return &TableRestore{ tableName: tableName, tableInfo: ti, logger: logger, } } -func (s *metaMgrSuite) SetUpTest(c *C) { +func newMetaMgrSuite(t *testing.T) (*metaMgrSuite, func()) { db, m, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + var s metaMgrSuite s.mgr = &dbTableMetaMgr{ session: db, taskID: 1, - tr: s.tr, + tr: newTableRestore(t), tableName: common.UniqueTable("test", TableMetaTableName), needChecksum: true, } s.mockDB = m s.checksumMgr = &testChecksumMgr{} + return &s, func() { + require.NoError(t, s.mockDB.ExpectationsWereMet()) + } } -func (s *metaMgrSuite) TearDownTest(c *C) { - c.Assert(s.mockDB.ExpectationsWereMet(), IsNil) -} +func TestAllocTableRowIDsSingleTable(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() -func (s *metaMgrSuite) TestAllocTableRowIDsSingleTable(c *C) { ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -88,13 +89,16 @@ func (s *metaMgrSuite) TestAllocTableRowIDsSingleTable(c *C) { s.prepareMock(rows, &nextID, updateArgs, nil, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(0)) - c.Assert(ck, IsNil) - c.Assert(s.checksumMgr.callCnt, Equals, 0) + require.NoError(t, err) + require.Equal(t, int64(0), rowIDBase) + require.Nil(t, ck) + + require.Equal(t, 0, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableAutoIDNot0(c *C) { +func TestAllocTableRowIDsSingleTableAutoIDNot0(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -106,13 +110,17 @@ func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableAutoIDNot0(c *C) { s.prepareMock(rows, &nextID, updateArgs, nil, &newStatus) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(998)) - c.Assert(ck, IsNil) - c.Assert(s.checksumMgr.callCnt, Equals, 1) + require.NoError(t, err) + require.Equal(t, int64(998), rowIDBase) + require.Nil(t, ck) + + require.Equal(t, 1, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableContainsData(c *C) { +func TestAllocTableRowIDsSingleTableContainsData(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() + ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -124,13 +132,16 @@ func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableContainsData(c *C) { s.prepareMock(rows, &nextID, updateArgs, &checksum, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(998)) - c.Assert(ck, DeepEquals, &checksum) - c.Assert(s.checksumMgr.callCnt, Equals, 1) + require.NoError(t, err) + require.Equal(t, int64(998), rowIDBase) + require.Equal(t, &checksum, ck) + require.Equal(t, 1, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableSkipChecksum(c *C) { +func TestAllocTableRowIDsSingleTableSkipChecksum(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() + s.mgr.needChecksum = false defer func() { s.mgr.needChecksum = true @@ -146,13 +157,17 @@ func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableSkipChecksum(c *C) { s.prepareMock(rows, &nextID, updateArgs, nil, &newStatus) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(998)) - c.Assert(ck, IsNil) - c.Assert(s.checksumMgr.callCnt, Equals, 0) + require.NoError(t, err) + require.Equal(t, int64(998), rowIDBase) + require.Nil(t, ck) + + require.Equal(t, 0, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsAllocated(c *C) { +func TestAllocTableRowIDsAllocated(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() + ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -162,13 +177,16 @@ func (s *metaMgrSuite) TestAllocTableRowIDsAllocated(c *C) { s.prepareMock(rows, nil, nil, &checksum, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(998)) - c.Assert(ck, DeepEquals, &checksum) - c.Assert(s.checksumMgr.callCnt, Equals, 1) + require.NoError(t, err) + require.Equal(t, int64(998), rowIDBase) + require.Equal(t, &checksum, ck) + require.Equal(t, 1, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsFinished(c *C) { +func TestAllocTableRowIDsFinished(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() + ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -178,13 +196,15 @@ func (s *metaMgrSuite) TestAllocTableRowIDsFinished(c *C) { s.prepareMock(rows, nil, nil, nil, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(998)) - c.Assert(ck, DeepEquals, &checksum) - c.Assert(s.checksumMgr.callCnt, Equals, 0) + require.NoError(t, err) + require.Equal(t, int64(998), rowIDBase) + require.Equal(t, &checksum, ck) + require.Equal(t, 0, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksInit(c *C) { +func TestAllocTableRowIDsMultiTasksInit(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -196,13 +216,16 @@ func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksInit(c *C) { s.prepareMock(rows, &nextID, updateArgs, nil, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(0)) - c.Assert(ck, IsNil) - c.Assert(s.checksumMgr.callCnt, Equals, 0) + require.NoError(t, err) + require.Equal(t, int64(0), rowIDBase) + require.Nil(t, ck) + + require.Equal(t, 0, s.checksumMgr.callCnt) } -func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksAllocated(c *C) { +func TestAllocTableRowIDsMultiTasksAllocated(t *testing.T) { + s, clean := newMetaMgrSuite(t) + defer clean() ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) rows := [][]driver.Value{ @@ -213,10 +236,11 @@ func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksAllocated(c *C) { s.prepareMock(rows, nil, updateArgs, nil, nil) ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) - c.Assert(err, IsNil) - c.Assert(rowIDBase, Equals, int64(100)) - c.Assert(ck, IsNil) - c.Assert(s.checksumMgr.callCnt, Equals, 0) + require.NoError(t, err) + require.Equal(t, int64(100), rowIDBase) + require.Nil(t, ck) + + require.Equal(t, 0, s.checksumMgr.callCnt) } func (s *metaMgrSuite) prepareMock(rowsVal [][]driver.Value, nextRowID *int64, updateArgs []driver.Value, checksum *verification.KVChecksum, updateStatus *string) { @@ -264,26 +288,27 @@ func (s *metaMgrSuite) prepareMock(rowsVal [][]driver.Value, nextRowID *int64, u } } -var _ = Suite(&taskMetaMgrSuite{}) - type taskMetaMgrSuite struct { mgr *dbTaskMetaMgr mockDB sqlmock.Sqlmock } -func (s *taskMetaMgrSuite) SetUpTest(c *C) { +func newTaskMetaMgrSuite(t *testing.T) *taskMetaMgrSuite { db, m, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) + var s taskMetaMgrSuite s.mgr = &dbTaskMetaMgr{ session: db, taskID: 1, tableName: common.UniqueTable("test", "t1"), } s.mockDB = m + return &s } -func (s *taskMetaMgrSuite) TestCheckTasksExclusively(c *C) { +func TestCheckTasksExclusively(t *testing.T) { + s := newTaskMetaMgrSuite(t) s.mockDB.ExpectExec("SET SESSION tidb_txn_mode = 'pessimistic';"). WillReturnResult(sqlmock.NewResult(int64(0), int64(0))) s.mockDB.ExpectBegin() @@ -304,12 +329,12 @@ func (s *taskMetaMgrSuite) TestCheckTasksExclusively(c *C) { s.mockDB.ExpectCommit() err := s.mgr.CheckTasksExclusively(context.Background(), func(tasks []taskMeta) ([]taskMeta, error) { - c.Assert(len(tasks), Equals, 5) + require.Equal(t, 5, len(tasks)) sort.Slice(tasks, func(i, j int) bool { return tasks[i].taskID < tasks[j].taskID }) for j := 0; j < 5; j++ { - c.Assert(tasks[j].taskID, Equals, int64(j)) + require.Equal(t, int64(j), tasks[j].taskID) } var newTasks []taskMeta @@ -320,6 +345,16 @@ func (s *taskMetaMgrSuite) TestCheckTasksExclusively(c *C) { } return newTasks, nil }) - c.Assert(err, IsNil) + require.NoError(t, err) + +} + +type testChecksumMgr struct { + checksum RemoteChecksum + callCnt int +} +func (t *testChecksumMgr) Checksum(ctx context.Context, tableInfo *checkpoints.TidbTableInfo) (*RemoteChecksum, error) { + t.callCnt++ + return &t.checksum, nil } diff --git a/br/pkg/lightning/restore/restore.go b/br/pkg/lightning/restore/restore.go index 777350a855d7b..d181b0882f209 100644 --- a/br/pkg/lightning/restore/restore.go +++ b/br/pkg/lightning/restore/restore.go @@ -262,6 +262,7 @@ type Controller struct { closedEngineLimit *worker.Pool store storage.ExternalStorage + ownStore bool metaMgrBuilder metaMgrBuilder errorMgr *errormanager.ErrorManager taskMgr taskMetaMgr @@ -277,39 +278,65 @@ type LightningStatus struct { TotalFileSize atomic.Int64 } +// ControllerParam contains many parameters for creating a Controller. +type ControllerParam struct { + // databases that dumper created + DBMetas []*mydump.MDDatabaseMeta + // a pointer to status to report it to caller + Status *LightningStatus + // storage interface to read the dump data + DumpFileStorage storage.ExternalStorage + // true if DumpFileStorage is created by lightning. In some cases where lightning is a library, the framework may pass an DumpFileStorage + OwnExtStorage bool + // used by lightning server mode to pause tasks + Pauser *common.Pauser + // lightning via SQL will implement its glue, to let lightning use host TiDB's environment + Glue glue.Glue + // storage interface to write file checkpoints + CheckpointStorage storage.ExternalStorage + // when CheckpointStorage is not nil, save file checkpoint to it with this name + CheckpointName string +} + func NewRestoreController( ctx context.Context, - dbMetas []*mydump.MDDatabaseMeta, cfg *config.Config, - status *LightningStatus, - s storage.ExternalStorage, - g glue.Glue, + param *ControllerParam, ) (*Controller, error) { - return NewRestoreControllerWithPauser(ctx, dbMetas, cfg, status, s, DeliverPauser, g) + param.Pauser = DeliverPauser + return NewRestoreControllerWithPauser(ctx, cfg, param) } func NewRestoreControllerWithPauser( ctx context.Context, - dbMetas []*mydump.MDDatabaseMeta, cfg *config.Config, - status *LightningStatus, - s storage.ExternalStorage, - pauser *common.Pauser, - g glue.Glue, + p *ControllerParam, ) (*Controller, error) { tls, err := cfg.ToTLS() if err != nil { return nil, err } - cpdb, err := g.OpenCheckpointsDB(ctx, cfg) - if err != nil { - return nil, errors.Annotate(err, "open checkpoint db failed") + var cpdb checkpoints.DB + // if CheckpointStorage is set, we should use given ExternalStorage to create checkpoints. + if p.CheckpointStorage != nil { + cpdb, err = checkpoints.NewFileCheckpointsDBWithExstorageFileName(ctx, p.CheckpointStorage.URI(), p.CheckpointStorage, p.CheckpointName) + if err != nil { + return nil, common.ErrOpenCheckpoint.Wrap(err).GenWithStackByArgs() + } + } else { + cpdb, err = p.Glue.OpenCheckpointsDB(ctx, cfg) + if err != nil { + if berrors.Is(err, common.ErrUnknownCheckpointDriver) { + return nil, err + } + return nil, common.ErrOpenCheckpoint.Wrap(err).GenWithStackByArgs() + } } taskCp, err := cpdb.TaskCheckpoint(ctx) if err != nil { - return nil, errors.Annotate(err, "get task checkpoint failed") + return nil, common.ErrReadCheckpoint.Wrap(err).GenWithStack("get task checkpoint failed") } if err := verifyCheckpoint(cfg, taskCp); err != nil { return nil, errors.Trace(err) @@ -320,13 +347,13 @@ func NewRestoreControllerWithPauser( } // TODO: support Lightning via SQL - db, err := g.GetDB() + db, err := p.Glue.GetDB() if err != nil { return nil, errors.Trace(err) } errorMgr := errormanager.New(db, cfg) if err := errorMgr.Init(ctx); err != nil { - return nil, errors.Annotate(err, "failed to init error manager") + return nil, common.ErrInitErrManager.Wrap(err).GenWithStackByArgs() } var backend backend.Backend @@ -338,10 +365,6 @@ func NewRestoreControllerWithPauser( return nil, errors.Annotate(err, "open importer backend failed") } case config.BackendTiDB: - db, err := g.GetDB() - if err != nil { - return nil, errors.Annotate(err, "open tidb backend failed") - } backend = tidb.NewTiDBBackend(db, cfg.TikvImporter.OnDuplicate, errorMgr) case config.BackendLocal: var rLimit local.Rlim_t @@ -361,47 +384,50 @@ func NewRestoreControllerWithPauser( log.L().Warn("TiKV version doesn't support duplicate resolution. The resolution algorithm will fall back to 'none'", zap.Error(err)) cfg.TikvImporter.DuplicateResolution = config.DupeResAlgNone } else { - return nil, errors.Annotate(err, "check TiKV version for duplicate resolution failed") + return nil, common.ErrCheckKVVersion.Wrap(err).GenWithStackByArgs() } } } - backend, err = local.NewLocalBackend(ctx, tls, cfg, g, maxOpenFiles, errorMgr) + backend, err = local.NewLocalBackend(ctx, tls, cfg, p.Glue, maxOpenFiles, errorMgr) if err != nil { - return nil, errors.Annotate(err, "build local backend failed") + return nil, common.NormalizeOrWrapErr(common.ErrUnknown, err) } err = verifyLocalFile(ctx, cpdb, cfg.TikvImporter.SortedKVDir) if err != nil { return nil, err } default: - return nil, errors.New("unknown backend: " + cfg.TikvImporter.Backend) + return nil, common.ErrUnknownBackend.GenWithStackByArgs(cfg.TikvImporter.Backend) } var metaBuilder metaMgrBuilder - switch cfg.TikvImporter.Backend { - case config.BackendLocal, config.BackendImporter: + isSSTImport := cfg.TikvImporter.Backend == config.BackendLocal || cfg.TikvImporter.Backend == config.BackendImporter + switch { + case isSSTImport && cfg.TikvImporter.IncrementalImport: metaBuilder = &dbMetaMgrBuilder{ db: db, taskID: cfg.TaskID, schema: cfg.App.MetaSchemaName, needChecksum: cfg.PostRestore.Checksum != config.OpLevelOff, } + case isSSTImport: + metaBuilder = singleMgrBuilder{} default: metaBuilder = noopMetaMgrBuilder{} } rc := &Controller{ cfg: cfg, - dbMetas: dbMetas, + dbMetas: p.DBMetas, tableWorkers: nil, indexWorkers: nil, regionWorkers: worker.NewPool(ctx, cfg.App.RegionConcurrency, "region"), ioWorkers: worker.NewPool(ctx, cfg.App.IOConcurrency, "io"), checksumWorks: worker.NewPool(ctx, cfg.TiDB.ChecksumTableConcurrency, "checksum"), - pauser: pauser, + pauser: p.Pauser, backend: backend, - tidbGlue: g, + tidbGlue: p.Glue, sysVars: defaultImportantVariables, tls: tls, checkTemplate: NewSimpleTemplate(), @@ -411,11 +437,12 @@ func NewRestoreControllerWithPauser( saveCpCh: make(chan saveCp), closedEngineLimit: worker.NewPool(ctx, cfg.App.TableConcurrency*2, "closed-engine"), - store: s, + store: p.DumpFileStorage, + ownStore: p.OwnExtStorage, metaMgrBuilder: metaBuilder, errorMgr: errorMgr, diskQuotaLock: newDiskQuotaLock(), - status: status, + status: p.Status, taskMgr: nil, } @@ -432,6 +459,7 @@ func (rc *Controller) Run(ctx context.Context) error { rc.setGlobalVariables, rc.restoreSchema, rc.preCheckRequirements, + rc.initCheckpoint, rc.restoreTables, rc.fullCompact, rc.cleanCheckpoints, @@ -453,7 +481,6 @@ outside: case err == nil: case log.IsContextCanceledError(err): logger.Info("task canceled") - err = nil break outside default: logger.Error("run failed") @@ -468,6 +495,7 @@ outside: } task.End(zap.ErrorLevel, err) + rc.errorMgr.LogErrorDetails() rc.errorSummaries.emitLog() return errors.Trace(err) @@ -497,11 +525,7 @@ type schemaJob struct { dbName string tblName string // empty for create db jobs stmtType schemaStmtType - stmts []*schemaStmt -} - -type schemaStmt struct { - sql string + stmts []string } type restoreSchemaWorker struct { @@ -514,6 +538,15 @@ type restoreSchemaWorker struct { store storage.ExternalStorage } +func (worker *restoreSchemaWorker) addJob(sqlStr string, job *schemaJob) error { + stmts, err := createIfNotExistsStmt(worker.glue.GetParser(), sqlStr, job.dbName, job.tblName) + if err != nil { + return err + } + job.stmts = stmts + return worker.appendJob(job) +} + func (worker *restoreSchemaWorker) makeJobs( dbMetas []*mydump.MDDatabaseMeta, getTables func(context.Context, string) ([]*model.TableInfo, error), @@ -525,15 +558,12 @@ func (worker *restoreSchemaWorker) makeJobs( var err error // 1. restore databases, execute statements concurrency for _, dbMeta := range dbMetas { - restoreSchemaJob := &schemaJob{ + sql := dbMeta.GetSchema(worker.ctx, worker.store) + err = worker.addJob(sql, &schemaJob{ dbName: dbMeta.Name, + tblName: "", stmtType: schemaCreateDatabase, - stmts: make([]*schemaStmt, 0, 1), - } - restoreSchemaJob.stmts = append(restoreSchemaJob.stmts, &schemaStmt{ - sql: createDatabaseIfNotExistStmt(dbMeta.Name), }) - err = worker.appendJob(restoreSchemaJob) if err != nil { return err } @@ -556,33 +586,22 @@ func (worker *restoreSchemaWorker) makeJobs( // we should skip ddl job and let SchemaValid check. continue } else if tblMeta.SchemaFile.FileMeta.Path == "" { - return errors.Errorf("table `%s`.`%s` schema not found", dbMeta.Name, tblMeta.Name) + return common.ErrSchemaNotExists.GenWithStackByArgs(dbMeta.Name, tblMeta.Name) } sql, err := tblMeta.GetSchema(worker.ctx, worker.store) + if err != nil { + return err + } if sql != "" { - stmts, err := createTableIfNotExistsStmt(worker.glue.GetParser(), sql, dbMeta.Name, tblMeta.Name) - if err != nil { - return err - } - restoreSchemaJob := &schemaJob{ + err = worker.addJob(sql, &schemaJob{ dbName: dbMeta.Name, tblName: tblMeta.Name, stmtType: schemaCreateTable, - stmts: make([]*schemaStmt, 0, len(stmts)), - } - for _, sql := range stmts { - restoreSchemaJob.stmts = append(restoreSchemaJob.stmts, &schemaStmt{ - sql: sql, - }) - } - err = worker.appendJob(restoreSchemaJob) + }) if err != nil { return err } } - if err != nil { - return err - } } } err = worker.wait() @@ -594,22 +613,11 @@ func (worker *restoreSchemaWorker) makeJobs( for _, viewMeta := range dbMeta.Views { sql, err := viewMeta.GetSchema(worker.ctx, worker.store) if sql != "" { - stmts, err := createTableIfNotExistsStmt(worker.glue.GetParser(), sql, dbMeta.Name, viewMeta.Name) - if err != nil { - return err - } - restoreSchemaJob := &schemaJob{ + err = worker.addJob(sql, &schemaJob{ dbName: dbMeta.Name, tblName: viewMeta.Name, stmtType: schemaCreateView, - stmts: make([]*schemaStmt, 0, len(stmts)), - } - for _, sql := range stmts { - restoreSchemaJob.stmts = append(restoreSchemaJob.stmts, &schemaStmt{ - sql: sql, - }) - } - err = worker.appendJob(restoreSchemaJob) + }) if err != nil { return err } @@ -670,11 +678,11 @@ loop: DB: session, } for _, stmt := range job.stmts { - task := logger.Begin(zap.DebugLevel, fmt.Sprintf("execute SQL: %s", stmt.sql)) - err = sqlWithRetry.Exec(worker.ctx, "run create schema job", stmt.sql) + task := logger.Begin(zap.DebugLevel, fmt.Sprintf("execute SQL: %s", stmt)) + err = sqlWithRetry.Exec(worker.ctx, "run create schema job", stmt) task.End(zap.ErrorLevel, err) if err != nil { - err = errors.Annotatef(err, "%s %s failed", job.stmtType.String(), common.UniqueTable(job.dbName, job.tblName)) + err = common.ErrCreateSchema.Wrap(err).GenWithStackByArgs(common.UniqueTable(job.dbName, job.tblName), job.stmtType.String()) worker.wg.Done() worker.throw(err) // don't return @@ -731,7 +739,7 @@ func (worker *restoreSchemaWorker) appendJob(job *schemaJob) error { case <-worker.ctx.Done(): // cancel the job worker.wg.Done() - return worker.ctx.Err() + return errors.Trace(worker.ctx.Err()) case worker.jobCh <- job: return nil } @@ -771,16 +779,22 @@ func (rc *Controller) restoreSchema(ctx context.Context) error { } rc.dbInfos = dbInfos - if rc.tidbGlue.OwnsSQLExecutor() { - if err = rc.DataCheck(ctx); err != nil { - return errors.Trace(err) - } + sysVars := ObtainImportantVariables(ctx, rc.tidbGlue.GetSQLExecutor(), !rc.isTiDBBackend()) + // override by manually set vars + for k, v := range rc.cfg.TiDB.Vars { + sysVars[k] = v } + rc.sysVars = sysVars + + return nil +} +// initCheckpoint initializes all tables' checkpoint data +func (rc *Controller) initCheckpoint(ctx context.Context) error { // Load new checkpoints - err = rc.checkpointsDB.Initialize(ctx, rc.cfg, dbInfos) + err := rc.checkpointsDB.Initialize(ctx, rc.cfg, rc.dbInfos) if err != nil { - return errors.Trace(err) + return common.ErrInitCheckpoint.Wrap(err).GenWithStackByArgs() } failpoint.Inject("InitializeCheckpointExit", func() { log.L().Warn("exit triggered", zap.String("failpoint", "InitializeCheckpointExit")) @@ -790,20 +804,8 @@ func (rc *Controller) restoreSchema(ctx context.Context) error { rc.checkpointsWg.Add(1) // checkpointsWg will be done in `rc.listenCheckpointUpdates` go rc.listenCheckpointUpdates() - sysVars := ObtainImportantVariables(ctx, rc.tidbGlue.GetSQLExecutor(), !rc.isTiDBBackend()) - // override by manually set vars - for k, v := range rc.cfg.TiDB.Vars { - sysVars[k] = v - } - rc.sysVars = sysVars - // Estimate the number of chunks for progress reporting - err = rc.estimateChunkCountIntoMetrics(ctx) - if err != nil { - return errors.Trace(err) - } - - return nil + return rc.estimateChunkCountIntoMetrics(ctx) } // verifyCheckpoint check whether previous task checkpoint is compatible with task config @@ -819,7 +821,7 @@ func verifyCheckpoint(cfg *config.Config, taskCp *checkpoints.TaskCheckpoint) er retryUsage += " and remove all restored tables and try again" if cfg.TikvImporter.Backend != taskCp.Backend { - return errors.Errorf("config 'tikv-importer.backend' value '%s' different from checkpoint value '%s', please %s", cfg.TikvImporter.Backend, taskCp.Backend, retryUsage) + return common.ErrInvalidCheckpoint.GenWithStack("config 'tikv-importer.backend' value '%s' different from checkpoint value '%s', please %s", cfg.TikvImporter.Backend, taskCp.Backend, retryUsage) } if cfg.App.CheckRequirements { @@ -830,32 +832,32 @@ func verifyCheckpoint(cfg *config.Config, taskCp *checkpoints.TaskCheckpoint) er } else { displayVer = "before v4.0.6/v3.0.19" } - return errors.Errorf("lightning version is '%s', but checkpoint was created %s, please %s", build.ReleaseVersion, displayVer, retryUsage) + return common.ErrInvalidCheckpoint.GenWithStack("lightning version is '%s', but checkpoint was created %s, please %s", build.ReleaseVersion, displayVer, retryUsage) } errorFmt := "config '%s' value '%s' different from checkpoint value '%s'. You may set 'check-requirements = false' to skip this check or " + retryUsage if cfg.Mydumper.SourceDir != taskCp.SourceDir { - return errors.Errorf(errorFmt, "mydumper.data-source-dir", cfg.Mydumper.SourceDir, taskCp.SourceDir) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "mydumper.data-source-dir", cfg.Mydumper.SourceDir, taskCp.SourceDir) } if cfg.TikvImporter.Backend == config.BackendLocal && cfg.TikvImporter.SortedKVDir != taskCp.SortedKVDir { - return errors.Errorf(errorFmt, "mydumper.sorted-kv-dir", cfg.TikvImporter.SortedKVDir, taskCp.SortedKVDir) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "mydumper.sorted-kv-dir", cfg.TikvImporter.SortedKVDir, taskCp.SortedKVDir) } if cfg.TikvImporter.Backend == config.BackendImporter && cfg.TikvImporter.Addr != taskCp.ImporterAddr { - return errors.Errorf(errorFmt, "tikv-importer.addr", cfg.TikvImporter.Backend, taskCp.Backend) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tikv-importer.addr", cfg.TikvImporter.Backend, taskCp.Backend) } if cfg.TiDB.Host != taskCp.TiDBHost { - return errors.Errorf(errorFmt, "tidb.host", cfg.TiDB.Host, taskCp.TiDBHost) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tidb.host", cfg.TiDB.Host, taskCp.TiDBHost) } if cfg.TiDB.Port != taskCp.TiDBPort { - return errors.Errorf(errorFmt, "tidb.port", cfg.TiDB.Port, taskCp.TiDBPort) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tidb.port", cfg.TiDB.Port, taskCp.TiDBPort) } if cfg.TiDB.PdAddr != taskCp.PdAddr { - return errors.Errorf(errorFmt, "tidb.pd-addr", cfg.TiDB.PdAddr, taskCp.PdAddr) + return common.ErrInvalidCheckpoint.GenWithStack(errorFmt, "tidb.pd-addr", cfg.TiDB.PdAddr, taskCp.PdAddr) } } @@ -877,7 +879,12 @@ func verifyLocalFile(ctx context.Context, cpdb checkpoints.DB, dir string) error log.L().Error("can't find local file", zap.String("table name", tableName), zap.Int32("engine ID", engineID)) - return errors.Trace(err) + if os.IsNotExist(err) { + err = common.ErrCheckLocalFile.GenWithStackByArgs(tableName, dir) + } else { + err = common.ErrCheckLocalFile.Wrap(err).GenWithStackByArgs(tableName, dir) + } + return err } } } @@ -965,11 +972,14 @@ func (rc *Controller) saveStatusCheckpoint(ctx context.Context, tableName string switch { case err == nil: break - case !common.IsContextCanceledError(err): + case utils.MessageIsRetryableStorageError(err.Error()), common.IsContextCanceledError(err): + // recoverable error, should not be recorded in checkpoint + // which will prevent lightning from automatically recovering + return nil + default: + // unrecoverable error merger.SetInvalid() rc.errorSummaries.record(tableName, err, statusIfSucceed) - default: - return nil } if engineID == checkpoints.WholeTableEngineID { @@ -1018,7 +1028,7 @@ func (rc *Controller) listenCheckpointUpdates() { if len(cpd) > 0 { err := rc.checkpointsDB.Update(cpd) for _, w := range ws { - w <- err + w <- common.NormalizeOrWrapErr(common.ErrUpdateCheckpoint, err) } web.BroadcastCheckpointDiff(cpd) } @@ -1300,7 +1310,7 @@ func (rc *Controller) keepPauseGCForDupeRes(ctx context.Context) (<-chan struct{ } if !paused { pdCli.Close() - return nil, errors.New("failed to pause GC for duplicate resolution after all retries") + return nil, common.ErrPauseGC.GenWithStack("failed to pause GC for duplicate resolution after all retries") } exitCh := make(chan struct{}) @@ -1339,7 +1349,10 @@ func (rc *Controller) keepPauseGCForDupeRes(ctx context.Context) (<-chan struct{ return exitCh, nil } -func (rc *Controller) restoreTables(ctx context.Context) error { +func (rc *Controller) restoreTables(ctx context.Context) (finalErr error) { + // output error summary + defer rc.outpuErrorSummary() + if rc.cfg.TikvImporter.DuplicateResolution != config.DupeResAlgNone { subCtx, cancel := context.WithCancel(ctx) exitCh, err := rc.keepPauseGCForDupeRes(subCtx) @@ -1368,16 +1381,21 @@ func (rc *Controller) restoreTables(ctx context.Context) error { finishSchedulers := func() {} // if one lightning failed abnormally, and can't determine whether it needs to switch back, // we do not do switch back automatically - cleanupFunc := func() {} switchBack := false - taskFinished := false + cleanup := false + postProgress := func() error { return nil } if rc.cfg.TikvImporter.Backend == config.BackendLocal { logTask.Info("removing PD leader®ion schedulers") restoreFn, err := rc.taskMgr.CheckAndPausePdSchedulers(ctx) + if err != nil { + return errors.Trace(err) + } + finishSchedulers = func() { if restoreFn != nil { + taskFinished := finalErr == nil // use context.Background to make sure this restore function can still be executed even if ctx is canceled restoreCtx := context.Background() needSwitchBack, needCleanup, err := rc.taskMgr.CheckAndFinishRestore(restoreCtx, taskFinished) @@ -1387,39 +1405,17 @@ func (rc *Controller) restoreTables(ctx context.Context) error { } switchBack = needSwitchBack if needSwitchBack { + logTask.Info("add back PD leader®ion schedulers") if restoreE := restoreFn(restoreCtx); restoreE != nil { logTask.Warn("failed to restore removed schedulers, you may need to restore them manually", zap.Error(restoreE)) } - - logTask.Info("add back PD leader®ion schedulers") - // clean up task metas - if needCleanup { - logTask.Info("cleanup task metas") - if cleanupErr := rc.taskMgr.Cleanup(restoreCtx); cleanupErr != nil { - logTask.Warn("failed to clean task metas, you may need to restore them manually", zap.Error(cleanupErr)) - } - // cleanup table meta and schema db if needed. - cleanupFunc = func() { - if e := rc.taskMgr.CleanupAllMetas(restoreCtx); err != nil { - logTask.Warn("failed to clean table task metas, you may need to restore them manually", zap.Error(e)) - } - } - } } + cleanup = needCleanup } rc.taskMgr.Close() } - - if err != nil { - return errors.Trace(err) - } } - defer func() { - if switchBack { - cleanupFunc() - } - }() type task struct { tr *TableRestore @@ -1439,17 +1435,31 @@ func (rc *Controller) restoreTables(ctx context.Context) error { periodicActions, cancelFunc := rc.buildRunPeriodicActionAndCancelFunc(ctx, stopPeriodicActions) go periodicActions() - finishFuncCalled := false + + defer close(stopPeriodicActions) + defer func() { - if !finishFuncCalled { - finishSchedulers() - cancelFunc(switchBack) - finishFuncCalled = true + finishSchedulers() + cancelFunc(switchBack) + + if err := postProgress(); err != nil { + logTask.End(zap.ErrorLevel, err) + finalErr = err + return + } + // clean up task metas + if cleanup { + logTask.Info("cleanup task metas") + if cleanupErr := rc.taskMgr.Cleanup(context.Background()); cleanupErr != nil { + logTask.Warn("failed to clean task metas, you may need to restore them manually", zap.Error(cleanupErr)) + } + // cleanup table meta and schema db if needed. + if err := rc.taskMgr.CleanupAllMetas(context.Background()); err != nil { + logTask.Warn("failed to clean table task metas, you may need to restore them manually", zap.Error(err)) + } } }() - defer close(stopPeriodicActions) - taskCh := make(chan task, rc.cfg.App.IndexConcurrency) defer close(taskCh) @@ -1464,7 +1474,7 @@ func (rc *Controller) restoreTables(ctx context.Context) error { tableLogTask := task.tr.logger.Begin(zap.InfoLevel, "restore table") web.BroadcastTableCheckpoint(task.tr.tableName, task.cp) needPostProcess, err := task.tr.restoreTable(ctx2, rc, task.cp) - err = errors.Annotatef(err, "restore table %s failed", task.tr.tableName) + err = common.NormalizeOrWrapErr(common.ErrRestoreTable, err, task.tr.tableName) tableLogTask.End(zap.ErrorLevel, err) web.BroadcastError(task.tr.tableName, err) metric.RecordTableCount("completed", err) @@ -1486,6 +1496,9 @@ func (rc *Controller) restoreTables(ctx context.Context) error { if err != nil { return errors.Trace(err) } + if cp.Status < checkpoints.CheckpointStatusAllWritten && len(tableMeta.DataFiles) == 0 { + continue + } igCols, err := rc.cfg.Mydumper.IgnoreColumns.GetIgnoreColumns(dbInfo.Name, tableInfo.Name, rc.cfg.Mydumper.CaseSensitive) if err != nil { return errors.Trace(err) @@ -1517,32 +1530,26 @@ func (rc *Controller) restoreTables(ctx context.Context) error { default: } - // stop periodic tasks for restore table such as pd schedulers and switch-mode tasks. - // this can help make cluster switching back to normal state more quickly. - // finishSchedulers() - // cancelFunc(switchBack) - // finishFuncCalled = true - taskFinished = true - - close(postProcessTaskChan) - // otherwise, we should run all tasks in the post-process task chan - for i := 0; i < rc.cfg.App.TableConcurrency; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for task := range postProcessTaskChan { - metaMgr := rc.metaMgrBuilder.TableMetaMgr(task.tr) - // force all the remain post-process tasks to be executed - _, err = task.tr.postProcess(ctx2, rc, task.cp, true, metaMgr) - restoreErr.Set(err) - } - }() + postProgress = func() error { + close(postProcessTaskChan) + // otherwise, we should run all tasks in the post-process task chan + for i := 0; i < rc.cfg.App.TableConcurrency; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for task := range postProcessTaskChan { + metaMgr := rc.metaMgrBuilder.TableMetaMgr(task.tr) + // force all the remain post-process tasks to be executed + _, err2 := task.tr.postProcess(ctx2, rc, task.cp, true, metaMgr) + restoreErr.Set(err2) + } + }() + } + wg.Wait() + return restoreErr.Get() } - wg.Wait() - err = restoreErr.Get() - logTask.End(zap.ErrorLevel, err) - return err + return nil } func (tr *TableRestore) restoreTable( @@ -1551,7 +1558,6 @@ func (tr *TableRestore) restoreTable( cp *checkpoints.TableCheckpoint, ) (bool, error) { // 1. Load the table info. - select { case <-ctx.Done(): return false, ctx.Err() @@ -1652,6 +1658,12 @@ func (tr *TableRestore) restoreTable( return tr.postProcess(ctx, rc, cp, false /* force-analyze */, metaMgr) } +func (rc *Controller) outpuErrorSummary() { + if rc.errorMgr.HasError() { + fmt.Println(rc.errorMgr.Output()) + } +} + // do full compaction for the whole data. func (rc *Controller) fullCompact(ctx context.Context) error { if !rc.cfg.PostRestore.Compact { @@ -1682,12 +1694,10 @@ func (rc *Controller) doCompact(ctx context.Context, level int32) error { } func (rc *Controller) switchToImportMode(ctx context.Context) { - log.L().Info("switch to import mode") rc.switchTiKVMode(ctx, sstpb.SwitchMode_Import) } func (rc *Controller) switchToNormalMode(ctx context.Context) { - log.L().Info("switch to normal mode") rc.switchTiKVMode(ctx, sstpb.SwitchMode_Normal) } @@ -1697,6 +1707,8 @@ func (rc *Controller) switchTiKVMode(ctx context.Context, mode sstpb.SwitchMode) return } + log.L().Info("switch import mode", zap.Stringer("mode", mode)) + // It is fine if we miss some stores which did not switch to Import mode, // since we're running it periodically, so we exclude disconnected stores. // But it is essential all stores be switched back to Normal mode to allow @@ -1812,10 +1824,14 @@ func (rc *Controller) setGlobalVariables(ctx context.Context) error { return nil } // set new collation flag base on tidb config - enabled := ObtainNewCollationEnabled(ctx, rc.tidbGlue.GetSQLExecutor()) + enabled, err := ObtainNewCollationEnabled(ctx, rc.tidbGlue.GetSQLExecutor()) + if err != nil { + return err + } // we should enable/disable new collation here since in server mode, tidb config // may be different in different tasks collate.SetNewCollationEnabledForTest(enabled) + log.L().Info("new_collation_enabled", zap.Bool("enabled", enabled)) return nil } @@ -1847,7 +1863,10 @@ func (rc *Controller) cleanCheckpoints(ctx context.Context) error { err = rc.checkpointsDB.RemoveCheckpoint(ctx, "all") } task.End(zap.ErrorLevel, err) - return errors.Annotate(err, "clean checkpoints") + if err != nil { + return common.ErrCleanCheckpoint.Wrap(err).GenWithStackByArgs() + } + return nil } func (rc *Controller) isLocalBackend() bool { @@ -1865,18 +1884,22 @@ func (rc *Controller) isTiDBBackend() bool { // 4. Lightning configuration // before restore tables start. func (rc *Controller) preCheckRequirements(ctx context.Context) error { + if err := rc.DataCheck(ctx); err != nil { + return errors.Trace(err) + } + if rc.cfg.App.CheckRequirements { - if err := rc.ClusterIsAvailable(ctx); err != nil { - return errors.Trace(err) - } + rc.ClusterIsAvailable(ctx) - if err := rc.StoragePermission(ctx); err != nil { - return errors.Trace(err) + if rc.ownStore { + if err := rc.StoragePermission(ctx); err != nil { + return errors.Trace(err) + } } } if err := rc.metaMgrBuilder.Init(ctx); err != nil { - return err + return common.ErrInitMetaManager.Wrap(err).GenWithStackByArgs() } taskExist := false @@ -1884,50 +1907,54 @@ func (rc *Controller) preCheckRequirements(ctx context.Context) error { // source is in order as row key to decide how to sort local data. source, err := rc.estimateSourceData(ctx) if err != nil { - return errors.Trace(err) + return common.ErrCheckDataSource.Wrap(err).GenWithStackByArgs() } if rc.isLocalBackend() { pdController, err := pdutil.NewPdController(ctx, rc.cfg.TiDB.PdAddr, rc.tls.TLSConfig(), rc.tls.ToPDSecurityOption()) if err != nil { - return errors.Trace(err) + return common.NormalizeOrWrapErr(common.ErrCreatePDClient, err) } // PdController will be closed when `taskMetaMgr` closes. rc.taskMgr = rc.metaMgrBuilder.TaskMetaMgr(pdController) taskExist, err = rc.taskMgr.CheckTaskExist(ctx) if err != nil { - return errors.Trace(err) + return common.ErrMetaMgrUnknown.Wrap(err).GenWithStackByArgs() } if !taskExist { if err = rc.taskMgr.InitTask(ctx, source); err != nil { - return errors.Trace(err) + return common.ErrMetaMgrUnknown.Wrap(err).GenWithStackByArgs() } if rc.cfg.App.CheckRequirements { err = rc.localResource(source) if err != nil { - return errors.Trace(err) + return common.ErrCheckLocalResource.Wrap(err).GenWithStackByArgs() } if err := rc.clusterResource(ctx, source); err != nil { - rc.taskMgr.CleanupTask(ctx) - return errors.Trace(err) + if err1 := rc.taskMgr.CleanupTask(ctx); err1 != nil { + log.L().Warn("cleanup task failed", zap.Error(err1)) + return common.ErrMetaMgrUnknown.Wrap(err).GenWithStackByArgs() + } } if err := rc.checkClusterRegion(ctx); err != nil { - return errors.Trace(err) + return common.ErrCheckClusterRegion.Wrap(err).GenWithStackByArgs() } } } } if rc.tidbGlue.OwnsSQLExecutor() && rc.cfg.App.CheckRequirements { - fmt.Print(rc.checkTemplate.Output()) + fmt.Println(rc.checkTemplate.Output()) } if !rc.checkTemplate.Success() { if !taskExist && rc.taskMgr != nil { - rc.taskMgr.CleanupTask(ctx) + err := rc.taskMgr.CleanupTask(ctx) + if err != nil { + log.L().Warn("cleanup task failed", zap.Error(err)) + } } - return errors.Errorf("tidb-lightning check failed."+ - " Please fix the failed check(s):\n %s", rc.checkTemplate.FailedMsg()) + return common.ErrPreCheckFailed.GenWithStackByArgs(rc.checkTemplate.FailedMsg()) } return nil } @@ -1936,10 +1963,7 @@ func (rc *Controller) preCheckRequirements(ctx context.Context) error { func (rc *Controller) DataCheck(ctx context.Context) error { var err error if rc.cfg.App.CheckRequirements { - err = rc.HasLargeCSV(rc.dbMetas) - if err != nil { - return errors.Trace(err) - } + rc.HasLargeCSV(rc.dbMetas) } checkPointCriticalMsgs := make([]string, 0, len(rc.dbMetas)) schemaCriticalMsgs := make([]string, 0, len(rc.dbMetas)) @@ -1950,9 +1974,7 @@ func (rc *Controller) DataCheck(ctx context.Context) error { // so we can skip TableHasDataInCluster and SchemaIsValid check. noCheckpoint := true if rc.cfg.Checkpoint.Enable { - if msgs, noCheckpoint, err = rc.CheckpointIsValid(ctx, tableInfo); err != nil { - return errors.Trace(err) - } + msgs, noCheckpoint = rc.CheckpointIsValid(ctx, tableInfo) if len(msgs) != 0 { checkPointCriticalMsgs = append(checkPointCriticalMsgs, msgs...) } @@ -1968,11 +1990,6 @@ func (rc *Controller) DataCheck(ctx context.Context) error { } } } - err = rc.checkCSVHeader(ctx, rc.dbMetas) - if err != nil { - return err - } - if len(checkPointCriticalMsgs) != 0 { rc.checkTemplate.Collect(Critical, false, strings.Join(checkPointCriticalMsgs, "\n")) } else { @@ -1983,6 +2000,14 @@ func (rc *Controller) DataCheck(ctx context.Context) error { } else { rc.checkTemplate.Collect(Critical, true, "table schemas are valid") } + + if err := rc.checkTableEmpty(ctx); err != nil { + return common.ErrCheckTableEmpty.Wrap(err).GenWithStackByArgs() + } + if err = rc.checkCSVHeader(ctx, rc.dbMetas); err != nil { + return common.ErrCheckCSVHeader.Wrap(err).GenWithStackByArgs() + } + return nil } @@ -2372,7 +2397,7 @@ func (cr *chunkRestore) encodeLoop( reachEOF = true break outLoop default: - err = errors.Annotatef(err, "in file %s at offset %d", &cr.chunk.Key, newOffset) + err = common.ErrEncodeKV.Wrap(err).GenWithStackByArgs(&cr.chunk.Key, newOffset) return } readDur += time.Since(readDurStart) @@ -2386,7 +2411,9 @@ func (cr *chunkRestore) encodeLoop( if encodeErr != nil { rowText := tidb.EncodeRowForRecord(t.encTable, rc.cfg.TiDB.SQLMode, lastRow.Row, cr.chunk.ColumnPermutation) encodeErr = rc.errorMgr.RecordTypeError(ctx, logger, t.tableName, cr.chunk.Key.Path, newOffset, rowText, encodeErr) - err = errors.Annotatef(encodeErr, "in file %s at offset %d", &cr.chunk.Key, newOffset) + if encodeErr != nil { + err = common.ErrEncodeKV.Wrap(encodeErr).GenWithStackByArgs(&cr.chunk.Key, newOffset) + } hasIgnoredEncodeErr = true } cr.parser.RecycleRow(lastRow) diff --git a/br/pkg/lightning/restore/restore_schema_test.go b/br/pkg/lightning/restore/restore_schema_test.go new file mode 100644 index 0000000000000..7bce917eb828c --- /dev/null +++ b/br/pkg/lightning/restore/restore_schema_test.go @@ -0,0 +1,276 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package restore + +import ( + "context" + stderrors "errors" + "fmt" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/golang/mock/gomock" + "github.com/pingcap/errors" + filter "github.com/pingcap/tidb/util/table-filter" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/pingcap/tidb/br/pkg/lightning/backend" + "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" + "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/mydump" + "github.com/pingcap/tidb/br/pkg/mock" + "github.com/pingcap/tidb/br/pkg/storage" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + tmock "github.com/pingcap/tidb/util/mock" +) + +type restoreSchemaSuite struct { + suite.Suite + ctx context.Context + rc *Controller + controller *gomock.Controller + tableInfos []*model.TableInfo +} + +func TestRestoreSchemaSuite(t *testing.T) { + suite.Run(t, new(restoreSchemaSuite)) +} + +func (s *restoreSchemaSuite) SetupSuite() { + ctx := context.Background() + fakeDataDir := s.T().TempDir() + + store, err := storage.NewLocalStorage(fakeDataDir) + require.NoError(s.T(), err) + // restore database schema file + fakeDBName := "fakedb" + // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}-schema-create.sql' + fakeFileName := fmt.Sprintf("%s-schema-create.sql", fakeDBName) + err = store.WriteFile(ctx, fakeFileName, []byte(fmt.Sprintf("CREATE DATABASE %s;", fakeDBName))) + require.NoError(s.T(), err) + // restore table schema files + fakeTableFilesCount := 8 + + p := parser.New() + p.SetSQLMode(mysql.ModeANSIQuotes) + se := tmock.NewContext() + + tableInfos := make([]*model.TableInfo, 0, fakeTableFilesCount) + for i := 1; i <= fakeTableFilesCount; i++ { + fakeTableName := fmt.Sprintf("tbl%d", i) + // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}.{table}-schema.sql' + fakeFileName := fmt.Sprintf("%s.%s-schema.sql", fakeDBName, fakeTableName) + fakeFileContent := fmt.Sprintf("CREATE TABLE %s(i TINYINT);", fakeTableName) + err = store.WriteFile(ctx, fakeFileName, []byte(fakeFileContent)) + require.NoError(s.T(), err) + + node, err := p.ParseOneStmt(fakeFileContent, "", "") + require.NoError(s.T(), err) + core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) + require.NoError(s.T(), err) + core.State = model.StatePublic + tableInfos = append(tableInfos, core) + } + s.tableInfos = tableInfos + // restore view schema files + fakeViewFilesCount := 8 + for i := 1; i <= fakeViewFilesCount; i++ { + fakeViewName := fmt.Sprintf("tbl%d", i) + // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}.{table}-schema-view.sql' + fakeFileName := fmt.Sprintf("%s.%s-schema-view.sql", fakeDBName, fakeViewName) + fakeFileContent := []byte(fmt.Sprintf("CREATE ALGORITHM=UNDEFINED VIEW `%s` (`i`) AS SELECT `i` FROM `%s`.`%s`;", fakeViewName, fakeDBName, fmt.Sprintf("tbl%d", i))) + err = store.WriteFile(ctx, fakeFileName, fakeFileContent) + require.NoError(s.T(), err) + } + config := config.NewConfig() + config.Mydumper.DefaultFileRules = true + config.Mydumper.CharacterSet = "utf8mb4" + config.App.RegionConcurrency = 8 + mydumpLoader, err := mydump.NewMyDumpLoaderWithStore(ctx, config, store) + require.NoError(s.T(), err) + s.rc = &Controller{ + checkTemplate: NewSimpleTemplate(), + cfg: config, + store: store, + dbMetas: mydumpLoader.GetDatabases(), + checkpointsDB: &checkpoints.NullCheckpointsDB{}, + } +} + +//nolint:interfacer // change test case signature might cause Check failed to find this test case? +func (s *restoreSchemaSuite) SetupTest() { + s.controller, s.ctx = gomock.WithContext(context.Background(), s.T()) + mockBackend := mock.NewMockBackend(s.controller) + mockBackend.EXPECT(). + FetchRemoteTableModels(gomock.Any(), gomock.Any()). + AnyTimes(). + Return(s.tableInfos, nil) + mockBackend.EXPECT().Close() + s.rc.backend = backend.MakeBackend(mockBackend) + + mockDB, sqlMock, err := sqlmock.New() + require.NoError(s.T(), err) + for i := 0; i < 17; i++ { + sqlMock.ExpectExec(".*").WillReturnResult(sqlmock.NewResult(int64(i), 1)) + } + mockTiDBGlue := mock.NewMockGlue(s.controller) + mockTiDBGlue.EXPECT().GetDB().AnyTimes().Return(mockDB, nil) + mockTiDBGlue.EXPECT(). + OwnsSQLExecutor(). + AnyTimes(). + Return(true) + parser := parser.New() + mockTiDBGlue.EXPECT(). + GetParser(). + AnyTimes(). + Return(parser) + s.rc.tidbGlue = mockTiDBGlue +} + +func (s *restoreSchemaSuite) TearDownTest() { + exec := mock.NewMockSQLExecutor(s.controller) + exec.EXPECT().Close() + mockTiDBGlue := mock.NewMockGlue(s.controller) + mockTiDBGlue.EXPECT(). + GetSQLExecutor(). + AnyTimes(). + Return(exec) + s.rc.tidbGlue = mockTiDBGlue + + s.rc.Close() + s.controller.Finish() +} + +func (s *restoreSchemaSuite) TestRestoreSchemaSuccessful() { + // before restore, if sysVars is initialized by other test, the time_zone should be default value + if len(s.rc.sysVars) > 0 { + tz, ok := s.rc.sysVars["time_zone"] + require.True(s.T(), ok) + require.Equal(s.T(), "SYSTEM", tz) + } + + exec := mock.NewMockSQLExecutor(s.controller) + exec.EXPECT(). + QueryStringsWithLog(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + AnyTimes(). + Return([][]string{{"time_zone", "SYSTEM"}}, nil) + mockTiDBGlue := s.rc.tidbGlue.(*mock.MockGlue) + mockTiDBGlue.EXPECT(). + GetSQLExecutor(). + AnyTimes(). + Return(exec) + + s.rc.cfg.TiDB.Vars = map[string]string{ + "time_zone": "UTC", + } + err := s.rc.restoreSchema(s.ctx) + require.NoError(s.T(), err) + + // test after restore schema, sysVars has been updated + tz, ok := s.rc.sysVars["time_zone"] + require.True(s.T(), ok) + require.Equal(s.T(), "UTC", tz) +} + +func (s *restoreSchemaSuite) TestRestoreSchemaFailed() { + // use injectErr which cannot be retried + injectErr := stderrors.New("could not match actual sql") + mockDB, sqlMock, err := sqlmock.New() + require.NoError(s.T(), err) + sqlMock.ExpectExec(".*").WillReturnError(injectErr) + for i := 0; i < 16; i++ { + sqlMock.ExpectExec(".*").WillReturnResult(sqlmock.NewResult(int64(i), 1)) + } + + mockTiDBGlue := mock.NewMockGlue(s.controller) + mockTiDBGlue.EXPECT(). + GetDB(). + AnyTimes(). + Return(mockDB, nil) + mockTiDBGlue.EXPECT(). + OwnsSQLExecutor(). + AnyTimes(). + Return(true) + parser := parser.New() + mockTiDBGlue.EXPECT(). + GetParser(). + AnyTimes(). + Return(parser) + s.rc.tidbGlue = mockTiDBGlue + err = s.rc.restoreSchema(s.ctx) + require.Error(s.T(), err) + require.True(s.T(), errors.ErrorEqual(err, injectErr)) +} + +// When restoring a CSV with `-no-schema` and the target table doesn't exist +// then we can't restore the schema as the `Path` is empty. This is to make +// sure this results in the correct error. +// https://github.com/pingcap/br/issues/1394 +func (s *restoreSchemaSuite) TestNoSchemaPath() { + fakeTable := mydump.MDTableMeta{ + DB: "fakedb", + Name: "fake1", + SchemaFile: mydump.FileInfo{ + TableName: filter.Table{ + Schema: "fakedb", + Name: "fake1", + }, + FileMeta: mydump.SourceFileMeta{ + Path: "", + }, + }, + DataFiles: []mydump.FileInfo{}, + TotalSize: 0, + } + s.rc.dbMetas[0].Tables = append(s.rc.dbMetas[0].Tables, &fakeTable) + err := s.rc.restoreSchema(s.ctx) + require.Error(s.T(), err) + require.Regexp(s.T(), `table .* schema not found`, err.Error()) + s.rc.dbMetas[0].Tables = s.rc.dbMetas[0].Tables[:len(s.rc.dbMetas[0].Tables)-1] +} + +func (s *restoreSchemaSuite) TestRestoreSchemaContextCancel() { + childCtx, cancel := context.WithCancel(s.ctx) + mockDB, sqlMock, err := sqlmock.New() + require.NoError(s.T(), err) + for i := 0; i < 17; i++ { + sqlMock.ExpectExec(".*").WillReturnResult(sqlmock.NewResult(int64(i), 1)) + } + mockTiDBGlue := mock.NewMockGlue(s.controller) + mockTiDBGlue.EXPECT(). + GetDB(). + AnyTimes(). + Do(func() { cancel() }). + Return(mockDB, nil) + mockTiDBGlue.EXPECT(). + OwnsSQLExecutor(). + AnyTimes(). + Return(true) + parser := parser.New() + mockTiDBGlue.EXPECT(). + GetParser(). + AnyTimes(). + Return(parser) + s.rc.tidbGlue = mockTiDBGlue + err = s.rc.restoreSchema(childCtx) + cancel() + require.Error(s.T(), err) + require.Equal(s.T(), childCtx.Err(), err) +} diff --git a/br/pkg/lightning/restore/restore_test.go b/br/pkg/lightning/restore/restore_test.go index b710a6627a668..a879ac43934f3 100644 --- a/br/pkg/lightning/restore/restore_test.go +++ b/br/pkg/lightning/restore/restore_test.go @@ -16,63 +16,32 @@ package restore import ( "context" - "encoding/json" "fmt" - "net/http" - "net/http/httptest" - "os" "path/filepath" "sort" - "strings" "sync/atomic" + "testing" "time" - "unicode/utf8" "github.com/DATA-DOG/go-sqlmock" - "github.com/docker/go-units" - "github.com/golang/mock/gomock" - "github.com/google/uuid" - . "github.com/pingcap/check" "github.com/pingcap/errors" - "github.com/pingcap/failpoint" - "github.com/pingcap/kvproto/pkg/import_kvpb" - "github.com/pingcap/kvproto/pkg/metapb" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - "github.com/pingcap/tidb/br/pkg/lightning/backend" - "github.com/pingcap/tidb/br/pkg/lightning/backend/importer" - "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" - "github.com/pingcap/tidb/br/pkg/lightning/backend/noop" - "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/config" "github.com/pingcap/tidb/br/pkg/lightning/errormanager" "github.com/pingcap/tidb/br/pkg/lightning/glue" "github.com/pingcap/tidb/br/pkg/lightning/log" - "github.com/pingcap/tidb/br/pkg/lightning/metric" - "github.com/pingcap/tidb/br/pkg/lightning/mydump" - "github.com/pingcap/tidb/br/pkg/lightning/verification" - "github.com/pingcap/tidb/br/pkg/lightning/web" - "github.com/pingcap/tidb/br/pkg/lightning/worker" - "github.com/pingcap/tidb/br/pkg/mock" - "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/version/build" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/types" - "github.com/pingcap/tidb/table/tables" tmock "github.com/pingcap/tidb/util/mock" - "github.com/tikv/pd/server/api" + "github.com/stretchr/testify/require" ) -var _ = Suite(&restoreSuite{}) - -type restoreSuite struct{} - -func (s *restoreSuite) TestNewTableRestore(c *C) { +func TestNewTableRestore(t *testing.T) { testCases := []struct { name string createStmt string @@ -88,9 +57,9 @@ func (s *restoreSuite) TestNewTableRestore(c *C) { dbInfo := &checkpoints.TidbDBInfo{Name: "mockdb", Tables: map[string]*checkpoints.TidbTableInfo{}} for i, tc := range testCases { node, err := p.ParseOneStmt(tc.createStmt, "utf8mb4", "utf8mb4_bin") - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), int64(i+1)) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo.State = model.StatePublic dbInfo.Tables[tc.name] = &checkpoints.TidbTableInfo{ @@ -103,12 +72,12 @@ func (s *restoreSuite) TestNewTableRestore(c *C) { tableInfo := dbInfo.Tables[tc.name] tableName := common.UniqueTable("mockdb", tableInfo.Name) tr, err := NewTableRestore(tableName, nil, dbInfo, tableInfo, &checkpoints.TableCheckpoint{}, nil) - c.Assert(tr, NotNil) - c.Assert(err, IsNil) + require.NotNil(t, tr) + require.NoError(t, err) } } -func (s *restoreSuite) TestNewTableRestoreFailure(c *C) { +func TestNewTableRestoreFailure(t *testing.T) { tableInfo := &checkpoints.TidbTableInfo{ Name: "failure", Core: &model.TableInfo{}, @@ -119,10 +88,10 @@ func (s *restoreSuite) TestNewTableRestoreFailure(c *C) { tableName := common.UniqueTable("mockdb", "failure") _, err := NewTableRestore(tableName, nil, dbInfo, tableInfo, &checkpoints.TableCheckpoint{}, nil) - c.Assert(err, ErrorMatches, `failed to tables\.TableFromMeta.*`) + require.Regexp(t, `failed to tables\.TableFromMeta.*`, err.Error()) } -func (s *restoreSuite) TestErrorSummaries(c *C) { +func TestErrorSummaries(t *testing.T) { logger, buffer := log.MakeTestLogger() es := makeErrorSummaries(logger) @@ -132,27 +101,27 @@ func (s *restoreSuite) TestErrorSummaries(c *C) { lines := buffer.Lines() sort.Strings(lines[1:]) - c.Assert(lines, DeepEquals, []string{ + require.Equal(t, []string{ `{"$lvl":"ERROR","$msg":"tables failed to be imported","count":2}`, `{"$lvl":"ERROR","$msg":"-","table":"first","status":"analyzed","error":"a1 error"}`, `{"$lvl":"ERROR","$msg":"-","table":"second","status":"written","error":"b2 error"}`, - }) + }, lines) } -func (s *restoreSuite) TestVerifyCheckpoint(c *C) { - dir := c.MkDir() - cpdb := checkpoints.NewFileCheckpointsDB(filepath.Join(dir, "cp.pb")) - defer cpdb.Close() +func TestVerifyCheckpoint(t *testing.T) { + dir := t.TempDir() ctx := context.Background() - + cpdb, err := checkpoints.NewFileCheckpointsDB(ctx, filepath.Join(dir, "cp.pb")) + require.NoError(t, err) + defer cpdb.Close() actualReleaseVersion := build.ReleaseVersion defer func() { build.ReleaseVersion = actualReleaseVersion }() taskCp, err := cpdb.TaskCheckpoint(ctx) - c.Assert(err, IsNil) - c.Assert(taskCp, IsNil) + require.NoError(t, err) + require.Nil(t, taskCp) newCfg := func() *config.Config { cfg := config.NewConfig() @@ -168,7 +137,7 @@ func (s *restoreSuite) TestVerifyCheckpoint(c *C) { } err = cpdb.Initialize(ctx, newCfg(), map[string]*checkpoints.TidbDBInfo{}) - c.Assert(err, IsNil) + require.NoError(t, err) adjustFuncs := map[string]func(cfg *config.Config){ "tikv-importer.backend": func(cfg *config.Config) { @@ -196,16 +165,16 @@ func (s *restoreSuite) TestVerifyCheckpoint(c *C) { // default mode, will return error taskCp, err = cpdb.TaskCheckpoint(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) for conf, fn := range adjustFuncs { cfg := newCfg() fn(cfg) err := verifyCheckpoint(cfg, taskCp) if conf == "version" { build.ReleaseVersion = actualReleaseVersion - c.Assert(err, ErrorMatches, "lightning version is 'some newer version', but checkpoint was created at '"+actualReleaseVersion+"'.*") + require.Regexp(t, "lightning version is 'some newer version', but checkpoint was created at '"+actualReleaseVersion+"'.*", err.Error()) } else { - c.Assert(err, ErrorMatches, fmt.Sprintf("config '%s' value '.*' different from checkpoint value .*", conf)) + require.Regexp(t, fmt.Sprintf("config '%s' value '.*' different from checkpoint value .*", conf), err.Error()) } } @@ -217,18 +186,18 @@ func (s *restoreSuite) TestVerifyCheckpoint(c *C) { cfg.App.CheckRequirements = false fn(cfg) err := cpdb.Initialize(context.Background(), cfg, map[string]*checkpoints.TidbDBInfo{}) - c.Assert(err, IsNil) + require.NoError(t, err) } } -func (s *restoreSuite) TestDiskQuotaLock(c *C) { +func TestDiskQuotaLock(t *testing.T) { lock := newDiskQuotaLock() lock.Lock() - c.Assert(lock.TryRLock(), IsFalse) + require.False(t, lock.TryRLock()) lock.Unlock() - c.Assert(lock.TryRLock(), IsTrue) - c.Assert(lock.TryRLock(), IsTrue) + require.True(t, lock.TryRLock()) + require.True(t, lock.TryRLock()) rLocked := 2 lockHeld := make(chan struct{}) @@ -242,7 +211,7 @@ func (s *restoreSuite) TestDiskQuotaLock(c *C) { } select { case <-lockHeld: - c.Fatal("write lock is held before all read locks are released") + t.Fatal("write lock is held before all read locks are released") case <-time.NewTimer(10 * time.Millisecond).C: } for ; rLocked > 0; rLocked-- { @@ -300,2401 +269,60 @@ func (s *restoreSuite) TestDiskQuotaLock(c *C) { } } -var _ = Suite(&tableRestoreSuite{}) - -type tableRestoreSuiteBase struct { - tr *TableRestore - cfg *config.Config - - tableInfo *checkpoints.TidbTableInfo - dbInfo *checkpoints.TidbDBInfo - tableMeta *mydump.MDTableMeta - - store storage.ExternalStorage +// failMetaMgrBuilder mocks meta manager init failure +type failMetaMgrBuilder struct { + metaMgrBuilder } -type tableRestoreSuite struct { - tableRestoreSuiteBase +func (b failMetaMgrBuilder) Init(context.Context) error { + return errors.New("mock init meta failure") } -func (s *tableRestoreSuiteBase) SetUpSuite(c *C) { - // Produce a mock table info - - p := parser.New() - p.SetSQLMode(mysql.ModeANSIQuotes) - se := tmock.NewContext() - node, err := p.ParseOneStmt(` - CREATE TABLE "table" ( - a INT, - b INT, - c INT, - KEY (b) - ) - `, "", "") - c.Assert(err, IsNil) - core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) - c.Assert(err, IsNil) - core.State = model.StatePublic - - s.tableInfo = &checkpoints.TidbTableInfo{Name: "table", DB: "db", Core: core} - s.dbInfo = &checkpoints.TidbDBInfo{ - Name: "db", - Tables: map[string]*checkpoints.TidbTableInfo{"table": s.tableInfo}, - } - - // Write some sample SQL dump - - fakeDataDir := c.MkDir() - - store, err := storage.NewLocalStorage(fakeDataDir) - c.Assert(err, IsNil) - s.store = store - - fakeDataFilesCount := 6 - fakeDataFilesContent := []byte("INSERT INTO `table` VALUES (1, 2, 3);") - c.Assert(len(fakeDataFilesContent), Equals, 37) - fakeDataFiles := make([]mydump.FileInfo, 0, fakeDataFilesCount) - for i := 1; i <= fakeDataFilesCount; i++ { - fakeFileName := fmt.Sprintf("db.table.%d.sql", i) - fakeDataPath := filepath.Join(fakeDataDir, fakeFileName) - err = os.WriteFile(fakeDataPath, fakeDataFilesContent, 0o644) - c.Assert(err, IsNil) - fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ - TableName: filter.Table{Schema: "db", Name: "table"}, - FileMeta: mydump.SourceFileMeta{ - Path: fakeFileName, - Type: mydump.SourceTypeSQL, - SortKey: fmt.Sprintf("%d", i), - FileSize: 37, - }, - }) - } - - fakeCsvContent := []byte("1,2,3\r\n4,5,6\r\n") - csvName := "db.table.99.csv" - err = os.WriteFile(filepath.Join(fakeDataDir, csvName), fakeCsvContent, 0o644) - c.Assert(err, IsNil) - fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ - TableName: filter.Table{Schema: "db", Name: "table"}, - FileMeta: mydump.SourceFileMeta{ - Path: csvName, - Type: mydump.SourceTypeCSV, - SortKey: "99", - FileSize: 14, - }, - }) - - s.tableMeta = &mydump.MDTableMeta{ - DB: "db", - Name: "table", - TotalSize: 222, - SchemaFile: mydump.FileInfo{ - TableName: filter.Table{Schema: "db", Name: "table"}, - FileMeta: mydump.SourceFileMeta{ - Path: "db.table-schema.sql", - Type: mydump.SourceTypeTableSchema, - }, - }, - DataFiles: fakeDataFiles, - } +type panicCheckpointDB struct { + checkpoints.DB } -func (s *tableRestoreSuiteBase) SetUpTest(c *C) { - // Collect into the test TableRestore structure - var err error - s.tr, err = NewTableRestore("`db`.`table`", s.tableMeta, s.dbInfo, s.tableInfo, &checkpoints.TableCheckpoint{}, nil) - c.Assert(err, IsNil) - - s.cfg = config.NewConfig() - s.cfg.Mydumper.BatchSize = 111 - s.cfg.App.TableConcurrency = 2 +func (cp panicCheckpointDB) Initialize(context.Context, *config.Config, map[string]*checkpoints.TidbDBInfo) error { + panic("should not reach here") } -func (s *tableRestoreSuite) TestPopulateChunks(c *C) { - _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp", "return(1234567897)") - defer func() { - _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp") - }() - - cp := &checkpoints.TableCheckpoint{ - Engines: make(map[int32]*checkpoints.EngineCheckpoint), - } - - rc := &Controller{cfg: s.cfg, ioWorkers: worker.NewPool(context.Background(), 1, "io"), store: s.store} - err := s.tr.populateChunks(context.Background(), rc, cp) - c.Assert(err, IsNil) - //nolint:dupl // false positive. - c.Assert(cp.Engines, DeepEquals, map[int32]*checkpoints.EngineCheckpoint{ - -1: { - Status: checkpoints.CheckpointStatusLoaded, - }, - 0: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[0].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[0].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 0, - RowIDMax: 7, // 37 bytes with 3 columns can store at most 7 rows. - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[1].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 7, - RowIDMax: 14, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[2].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[2].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 14, - RowIDMax: 21, - }, - Timestamp: 1234567897, - }, - }, - }, - 1: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[3].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[3].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 21, - RowIDMax: 28, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[4].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[4].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 28, - RowIDMax: 35, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[5].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[5].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 35, - RowIDMax: 42, - }, - Timestamp: 1234567897, - }, - }, - }, - 2: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[6].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[6].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 14, - PrevRowIDMax: 42, - RowIDMax: 46, - }, - Timestamp: 1234567897, - }, - }, - }, - }) - - // set csv header to true, this will cause check columns fail - s.cfg.Mydumper.CSV.Header = true - s.cfg.Mydumper.StrictFormat = true - regionSize := s.cfg.Mydumper.MaxRegionSize - s.cfg.Mydumper.MaxRegionSize = 5 - err = s.tr.populateChunks(context.Background(), rc, cp) - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, `.*unknown columns in header \[1 2 3\]`) - s.cfg.Mydumper.MaxRegionSize = regionSize - s.cfg.Mydumper.CSV.Header = false -} - -func (s *tableRestoreSuite) TestPopulateChunksCSVHeader(c *C) { - fakeDataDir := c.MkDir() - store, err := storage.NewLocalStorage(fakeDataDir) - c.Assert(err, IsNil) - - fakeDataFiles := make([]mydump.FileInfo, 0) - - fakeCsvContents := []string{ - // small full header - "a,b,c\r\n1,2,3\r\n", - // small partial header - "b,c\r\n2,3\r\n", - // big full header - "a,b,c\r\n90000,80000,700000\r\n1000,2000,3000\r\n11,22,33\r\n3,4,5\r\n", - // big full header unordered - "c,a,b\r\n,1000,2000,3000\r\n11,22,33\r\n1000,2000,404\r\n3,4,5\r\n90000,80000,700000\r\n7999999,89999999,9999999\r\n", - // big partial header - "b,c\r\n2000001,30000001\r\n35231616,462424626\r\n62432,434898934\r\n", - } - total := 0 - for i, s := range fakeCsvContents { - csvName := fmt.Sprintf("db.table.%02d.csv", i) - err := os.WriteFile(filepath.Join(fakeDataDir, csvName), []byte(s), 0o644) - c.Assert(err, IsNil) - fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ - TableName: filter.Table{Schema: "db", Name: "table"}, - FileMeta: mydump.SourceFileMeta{Path: csvName, Type: mydump.SourceTypeCSV, SortKey: fmt.Sprintf("%02d", i), FileSize: int64(len(s))}, - }) - total += len(s) - } - tableMeta := &mydump.MDTableMeta{ - DB: "db", - Name: "table", - TotalSize: int64(total), - SchemaFile: mydump.FileInfo{TableName: filter.Table{Schema: "db", Name: "table"}, FileMeta: mydump.SourceFileMeta{Path: "db.table-schema.sql", Type: mydump.SourceTypeTableSchema}}, - DataFiles: fakeDataFiles, - } - - _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp", "return(1234567897)") - defer func() { - _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp") - }() - - cp := &checkpoints.TableCheckpoint{ - Engines: make(map[int32]*checkpoints.EngineCheckpoint), - } - +func TestPreCheckFailed(t *testing.T) { cfg := config.NewConfig() - cfg.Mydumper.BatchSize = 100 - cfg.Mydumper.MaxRegionSize = 40 - - cfg.Mydumper.CSV.Header = true - cfg.Mydumper.StrictFormat = true - rc := &Controller{cfg: cfg, ioWorkers: worker.NewPool(context.Background(), 1, "io"), store: store} - - tr, err := NewTableRestore("`db`.`table`", tableMeta, s.dbInfo, s.tableInfo, &checkpoints.TableCheckpoint{}, nil) - c.Assert(err, IsNil) - c.Assert(tr.populateChunks(context.Background(), rc, cp), IsNil) - - c.Assert(cp.Engines, DeepEquals, map[int32]*checkpoints.EngineCheckpoint{ - -1: { - Status: checkpoints.CheckpointStatusLoaded, - }, - 0: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[0].FileMeta.Path, Offset: 0}, - FileMeta: tableMeta.DataFiles[0].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 14, - PrevRowIDMax: 0, - RowIDMax: 4, // 37 bytes with 3 columns can store at most 7 rows. - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, - FileMeta: tableMeta.DataFiles[1].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 10, - PrevRowIDMax: 4, - RowIDMax: 7, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[2].FileMeta.Path, Offset: 6}, - FileMeta: tableMeta.DataFiles[2].FileMeta, - ColumnPermutation: []int{0, 1, 2, -1}, - Chunk: mydump.Chunk{ - Offset: 6, - EndOffset: 52, - PrevRowIDMax: 7, - RowIDMax: 20, - Columns: []string{"a", "b", "c"}, - }, - - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[2].FileMeta.Path, Offset: 52}, - FileMeta: tableMeta.DataFiles[2].FileMeta, - ColumnPermutation: []int{0, 1, 2, -1}, - Chunk: mydump.Chunk{ - Offset: 52, - EndOffset: 60, - PrevRowIDMax: 20, - RowIDMax: 22, - Columns: []string{"a", "b", "c"}, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 6}, - FileMeta: tableMeta.DataFiles[3].FileMeta, - ColumnPermutation: []int{1, 2, 0, -1}, - Chunk: mydump.Chunk{ - Offset: 6, - EndOffset: 48, - PrevRowIDMax: 22, - RowIDMax: 35, - Columns: []string{"c", "a", "b"}, - }, - Timestamp: 1234567897, - }, - }, - }, - 1: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 48}, - FileMeta: tableMeta.DataFiles[3].FileMeta, - ColumnPermutation: []int{1, 2, 0, -1}, - Chunk: mydump.Chunk{ - Offset: 48, - EndOffset: 101, - PrevRowIDMax: 35, - RowIDMax: 48, - Columns: []string{"c", "a", "b"}, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 101}, - FileMeta: tableMeta.DataFiles[3].FileMeta, - ColumnPermutation: []int{1, 2, 0, -1}, - Chunk: mydump.Chunk{ - Offset: 101, - EndOffset: 102, - PrevRowIDMax: 48, - RowIDMax: 48, - Columns: []string{"c", "a", "b"}, - }, - Timestamp: 1234567897, - }, - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[4].FileMeta.Path, Offset: 4}, - FileMeta: tableMeta.DataFiles[4].FileMeta, - ColumnPermutation: []int{-1, 0, 1, -1}, - Chunk: mydump.Chunk{ - Offset: 4, - EndOffset: 59, - PrevRowIDMax: 48, - RowIDMax: 61, - Columns: []string{"b", "c"}, - }, - Timestamp: 1234567897, - }, - }, - }, - 2: { - Status: checkpoints.CheckpointStatusLoaded, - Chunks: []*checkpoints.ChunkCheckpoint{ - { - Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[4].FileMeta.Path, Offset: 59}, - FileMeta: tableMeta.DataFiles[4].FileMeta, - ColumnPermutation: []int{-1, 0, 1, -1}, - Chunk: mydump.Chunk{ - Offset: 59, - EndOffset: 60, - PrevRowIDMax: 61, - RowIDMax: 61, - Columns: []string{"b", "c"}, - }, - Timestamp: 1234567897, - }, - }, - }, - }) -} - -func (s *tableRestoreSuite) TestGetColumnsNames(c *C) { - c.Assert(getColumnNames(s.tableInfo.Core, []int{0, 1, 2, -1}), DeepEquals, []string{"a", "b", "c"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{1, 0, 2, -1}), DeepEquals, []string{"b", "a", "c"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{-1, 0, 1, -1}), DeepEquals, []string{"b", "c"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{0, 1, -1, -1}), DeepEquals, []string{"a", "b"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{1, -1, 0, -1}), DeepEquals, []string{"c", "a"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{-1, 0, -1, -1}), DeepEquals, []string{"b"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{1, 2, 3, 0}), DeepEquals, []string{"_tidb_rowid", "a", "b", "c"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{1, 0, 2, 3}), DeepEquals, []string{"b", "a", "c", "_tidb_rowid"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{-1, 0, 2, 1}), DeepEquals, []string{"b", "_tidb_rowid", "c"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{2, -1, 0, 1}), DeepEquals, []string{"c", "_tidb_rowid", "a"}) - c.Assert(getColumnNames(s.tableInfo.Core, []int{-1, 1, -1, 0}), DeepEquals, []string{"_tidb_rowid", "b"}) -} - -func (s *tableRestoreSuite) TestInitializeColumns(c *C) { - ccp := &checkpoints.ChunkCheckpoint{} - - defer func() { - s.tr.ignoreColumns = nil - }() - - cases := []struct { - columns []string - ignoreColumns map[string]struct{} - expectedPermutation []int - errPat string - }{ - { - nil, - nil, - []int{0, 1, 2, -1}, - "", - }, - { - nil, - map[string]struct{}{"b": {}}, - []int{0, -1, 2, -1}, - "", - }, - { - []string{"b", "c", "a"}, - nil, - []int{2, 0, 1, -1}, - "", - }, - { - []string{"b", "c", "a"}, - map[string]struct{}{"b": {}}, - []int{2, -1, 1, -1}, - "", - }, - { - []string{"b"}, - nil, - []int{-1, 0, -1, -1}, - "", - }, - { - []string{"_tidb_rowid", "b", "a", "c"}, - nil, - []int{2, 1, 3, 0}, - "", - }, - { - []string{"_tidb_rowid", "b", "a", "c"}, - map[string]struct{}{"b": {}, "_tidb_rowid": {}}, - []int{2, -1, 3, -1}, - "", - }, - { - []string{"_tidb_rowid", "b", "a", "c", "d"}, - nil, - nil, - `unknown columns in header \[d\]`, - }, - { - []string{"e", "b", "c", "d"}, - nil, - nil, - `unknown columns in header \[e d\]`, - }, - } - - for _, testCase := range cases { - ccp.ColumnPermutation = nil - s.tr.ignoreColumns = testCase.ignoreColumns - err := s.tr.initializeColumns(testCase.columns, ccp) - if len(testCase.errPat) > 0 { - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, testCase.errPat) - } else { - c.Assert(ccp.ColumnPermutation, DeepEquals, testCase.expectedPermutation) - } - } -} - -func (s *tableRestoreSuite) TestInitializeColumnsGenerated(c *C) { - p := parser.New() - p.SetSQLMode(mysql.ModeANSIQuotes) - se := tmock.NewContext() - - cases := []struct { - schema string - columns []string - expectedPermutation []int - }{ - { - "CREATE TABLE `table` (a INT, b INT, C INT, d INT AS (a * 2))", - []string{"b", "c", "a"}, - []int{2, 0, 1, -1, -1}, - }, - // all generated columns and none input columns - { - "CREATE TABLE `table` (a bigint as (1 + 2) stored, b text as (sha1(repeat('x', a))) stored)", - []string{}, - []int{-1, -1, -1}, - }, - } - - for _, testCase := range cases { - node, err := p.ParseOneStmt(testCase.schema, "", "") - c.Assert(err, IsNil) - core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) - c.Assert(err, IsNil) - core.State = model.StatePublic - tableInfo := &checkpoints.TidbTableInfo{Name: "table", DB: "db", Core: core} - s.tr, err = NewTableRestore("`db`.`table`", s.tableMeta, s.dbInfo, tableInfo, &checkpoints.TableCheckpoint{}, nil) - c.Assert(err, IsNil) - ccp := &checkpoints.ChunkCheckpoint{} - - err = s.tr.initializeColumns(testCase.columns, ccp) - c.Assert(err, IsNil) - c.Assert(ccp.ColumnPermutation, DeepEquals, testCase.expectedPermutation) - } -} - -func (s *tableRestoreSuite) TestCompareChecksumSuccess(c *C) { - db, mock, err := sqlmock.New() - c.Assert(err, IsNil) - - mock.ExpectQuery("SELECT.*tikv_gc_life_time.*"). - WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) - mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). - WithArgs("100h0m0s"). - WillReturnResult(sqlmock.NewResult(1, 1)) - mock.ExpectQuery("ADMIN CHECKSUM.*"). - WillReturnRows( - sqlmock.NewRows([]string{"Db_name", "Table_name", "Checksum_crc64_xor", "Total_kvs", "Total_bytes"}). - AddRow("db", "table", 1234567890, 12345, 1234567), - ) - mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). - WithArgs("10m"). - WillReturnResult(sqlmock.NewResult(2, 1)) - mock.ExpectClose() - - ctx := MockDoChecksumCtx(db) - remoteChecksum, err := DoChecksum(ctx, s.tr.tableInfo) - c.Assert(err, IsNil) - err = s.tr.compareChecksum(remoteChecksum, verification.MakeKVChecksum(1234567, 12345, 1234567890)) - c.Assert(err, IsNil) - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) -} - -func (s *tableRestoreSuite) TestCompareChecksumFailure(c *C) { - db, mock, err := sqlmock.New() - c.Assert(err, IsNil) - - mock.ExpectQuery("SELECT.*tikv_gc_life_time.*"). - WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) - mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). - WithArgs("100h0m0s"). - WillReturnResult(sqlmock.NewResult(1, 1)) - mock.ExpectQuery("ADMIN CHECKSUM TABLE `db`\\.`table`"). - WillReturnRows( - sqlmock.NewRows([]string{"Db_name", "Table_name", "Checksum_crc64_xor", "Total_kvs", "Total_bytes"}). - AddRow("db", "table", 1234567890, 12345, 1234567), - ) - mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). - WithArgs("10m"). - WillReturnResult(sqlmock.NewResult(2, 1)) - mock.ExpectClose() - - ctx := MockDoChecksumCtx(db) - remoteChecksum, err := DoChecksum(ctx, s.tr.tableInfo) - c.Assert(err, IsNil) - err = s.tr.compareChecksum(remoteChecksum, verification.MakeKVChecksum(9876543, 54321, 1357924680)) - c.Assert(err, ErrorMatches, "checksum mismatched.*") - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) -} + cfg.TikvImporter.Backend = config.BackendTiDB + cfg.App.CheckRequirements = false -func (s *tableRestoreSuite) TestAnalyzeTable(c *C) { db, mock, err := sqlmock.New() - c.Assert(err, IsNil) - - mock.ExpectExec("ANALYZE TABLE `db`\\.`table`"). - WillReturnResult(sqlmock.NewResult(1, 1)) - mock.ExpectClose() - - ctx := context.Background() - defaultSQLMode, err := mysql.GetSQLMode(mysql.DefaultSQLMode) - c.Assert(err, IsNil) - g := glue.NewExternalTiDBGlue(db, defaultSQLMode) - err = s.tr.analyzeTable(ctx, g) - c.Assert(err, IsNil) - - c.Assert(db.Close(), IsNil) - c.Assert(mock.ExpectationsWereMet(), IsNil) -} - -func (s *tableRestoreSuite) TestImportKVSuccess(c *C) { - controller := gomock.NewController(c) - defer controller.Finish() - mockBackend := mock.NewMockBackend(controller) - importer := backend.MakeBackend(mockBackend) - chptCh := make(chan saveCp) - defer close(chptCh) - rc := &Controller{saveCpCh: chptCh, cfg: config.NewConfig()} - go func() { - for scp := range chptCh { - if scp.waitCh != nil { - scp.waitCh <- nil - } - } - }() - - ctx := context.Background() - engineUUID := uuid.New() - - mockBackend.EXPECT(). - CloseEngine(ctx, nil, engineUUID). - Return(nil) - mockBackend.EXPECT(). - ImportEngine(ctx, engineUUID, gomock.Any()). - Return(nil) - mockBackend.EXPECT(). - CleanupEngine(ctx, engineUUID). - Return(nil) - - closedEngine, err := importer.UnsafeCloseEngineWithUUID(ctx, nil, "tag", engineUUID) - c.Assert(err, IsNil) - err = s.tr.importKV(ctx, closedEngine, rc, 1) - c.Assert(err, IsNil) -} - -func (s *tableRestoreSuite) TestImportKVFailure(c *C) { - controller := gomock.NewController(c) - defer controller.Finish() - mockBackend := mock.NewMockBackend(controller) - importer := backend.MakeBackend(mockBackend) - chptCh := make(chan saveCp) - defer close(chptCh) - rc := &Controller{saveCpCh: chptCh, cfg: config.NewConfig()} - go func() { - for scp := range chptCh { - if scp.waitCh != nil { - scp.waitCh <- nil - } - } - }() - - ctx := context.Background() - engineUUID := uuid.New() - - mockBackend.EXPECT(). - CloseEngine(ctx, nil, engineUUID). - Return(nil) - mockBackend.EXPECT(). - ImportEngine(ctx, engineUUID, gomock.Any()). - Return(errors.Annotate(context.Canceled, "fake import error")) - - closedEngine, err := importer.UnsafeCloseEngineWithUUID(ctx, nil, "tag", engineUUID) - c.Assert(err, IsNil) - err = s.tr.importKV(ctx, closedEngine, rc, 1) - c.Assert(err, ErrorMatches, "fake import error.*") -} - -func (s *tableRestoreSuite) TestTableRestoreMetrics(c *C) { - controller := gomock.NewController(c) - defer controller.Finish() - - chunkPendingBase := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) - chunkFinishedBase := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) - engineFinishedBase := metric.ReadCounter(metric.ProcessedEngineCounter.WithLabelValues("imported", metric.TableResultSuccess)) - tableFinishedBase := metric.ReadCounter(metric.TableCounter.WithLabelValues("index_imported", metric.TableResultSuccess)) - - ctx := context.Background() - chptCh := make(chan saveCp) - defer close(chptCh) - cfg := config.NewConfig() - cfg.Mydumper.BatchSize = 1 - cfg.PostRestore.Checksum = config.OpLevelOff - - cfg.Checkpoint.Enable = false - cfg.TiDB.Host = "127.0.0.1" - cfg.TiDB.StatusPort = 10080 - cfg.TiDB.Port = 4000 - cfg.TiDB.PdAddr = "127.0.0.1:2379" - - cfg.Mydumper.SourceDir = "." - cfg.Mydumper.CSV.Header = false - cfg.TikvImporter.Backend = config.BackendImporter - tls, err := cfg.ToTLS() - c.Assert(err, IsNil) - - err = cfg.Adjust(ctx) - c.Assert(err, IsNil) - - cpDB := checkpoints.NewNullCheckpointsDB() - g := mock.NewMockGlue(controller) - rc := &Controller{ - cfg: cfg, - dbMetas: []*mydump.MDDatabaseMeta{ - { - Name: s.tableInfo.DB, - Tables: []*mydump.MDTableMeta{s.tableMeta}, - }, - }, - dbInfos: map[string]*checkpoints.TidbDBInfo{ - s.tableInfo.DB: s.dbInfo, - }, - tableWorkers: worker.NewPool(ctx, 6, "table"), - ioWorkers: worker.NewPool(ctx, 5, "io"), - indexWorkers: worker.NewPool(ctx, 2, "index"), - regionWorkers: worker.NewPool(ctx, 10, "region"), - checksumWorks: worker.NewPool(ctx, 2, "region"), - saveCpCh: chptCh, - pauser: DeliverPauser, - backend: noop.NewNoopBackend(), - tidbGlue: g, - errorSummaries: makeErrorSummaries(log.L()), - tls: tls, - checkpointsDB: cpDB, - closedEngineLimit: worker.NewPool(ctx, 1, "closed_engine"), - store: s.store, - metaMgrBuilder: noopMetaMgrBuilder{}, - diskQuotaLock: newDiskQuotaLock(), - } - go func() { - for scp := range chptCh { - if scp.waitCh != nil { - scp.waitCh <- nil - } - } - }() - db, sqlMock, err := sqlmock.New() - c.Assert(err, IsNil) - g.EXPECT().GetDB().Return(db, nil).AnyTimes() - sqlMock.ExpectQuery("SELECT tidb_version\\(\\);").WillReturnRows(sqlmock.NewRows([]string{"tidb_version()"}). - AddRow("Release Version: v5.2.1\nEdition: Community\n")) - - web.BroadcastInitProgress(rc.dbMetas) - - err = rc.restoreTables(ctx) - c.Assert(err, IsNil) - - chunkPending := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) - chunkFinished := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) - c.Assert(chunkPending-chunkPendingBase, Equals, float64(7)) - c.Assert(chunkFinished-chunkFinishedBase, Equals, chunkPending) - - engineFinished := metric.ReadCounter(metric.ProcessedEngineCounter.WithLabelValues("imported", metric.TableResultSuccess)) - c.Assert(engineFinished-engineFinishedBase, Equals, float64(8)) - - tableFinished := metric.ReadCounter(metric.TableCounter.WithLabelValues("index_imported", metric.TableResultSuccess)) - c.Assert(tableFinished-tableFinishedBase, Equals, float64(1)) -} - -func (s *tableRestoreSuite) TestSaveStatusCheckpoint(c *C) { - _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownCheckpointUpdate", "sleep(100)") - defer func() { - _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownCheckpointUpdate") - }() - - web.BroadcastInitProgress([]*mydump.MDDatabaseMeta{{ - Name: "test", - Tables: []*mydump.MDTableMeta{{DB: "test", Name: "tbl"}}, - }}) - web.BroadcastTableCheckpoint(common.UniqueTable("test", "tbl"), &checkpoints.TableCheckpoint{}) - - saveCpCh := make(chan saveCp) - - rc := &Controller{ - saveCpCh: saveCpCh, - checkpointsDB: checkpoints.NewNullCheckpointsDB(), - } - rc.checkpointsWg.Add(1) - go rc.listenCheckpointUpdates() - - start := time.Now() - err := rc.saveStatusCheckpoint(context.Background(), common.UniqueTable("test", "tbl"), indexEngineID, nil, checkpoints.CheckpointStatusImported) - c.Assert(err, IsNil) - elapsed := time.Since(start) - c.Assert(elapsed, GreaterEqual, time.Millisecond*100) - - close(saveCpCh) - rc.checkpointsWg.Wait() -} - -var _ = Suite(&chunkRestoreSuite{}) - -type chunkRestoreSuite struct { - tableRestoreSuiteBase - cr *chunkRestore -} - -func (s *chunkRestoreSuite) SetUpTest(c *C) { - s.tableRestoreSuiteBase.SetUpTest(c) - - ctx := context.Background() - w := worker.NewPool(ctx, 5, "io") - - chunk := checkpoints.ChunkCheckpoint{ - Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, - FileMeta: s.tr.tableMeta.DataFiles[1].FileMeta, - Chunk: mydump.Chunk{ - Offset: 0, - EndOffset: 37, - PrevRowIDMax: 18, - RowIDMax: 36, - }, - } - - var err error - s.cr, err = newChunkRestore(context.Background(), 1, s.cfg, &chunk, w, s.store, nil) - c.Assert(err, IsNil) -} - -func (s *chunkRestoreSuite) TearDownTest(c *C) { - s.cr.close() -} - -func (s *chunkRestoreSuite) TestDeliverLoopCancel(c *C) { - rc := &Controller{backend: importer.NewMockImporter(nil, "")} - - ctx, cancel := context.WithCancel(context.Background()) - kvsCh := make(chan []deliveredKVs) - go cancel() - _, err := s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, nil, nil, rc) - c.Assert(errors.Cause(err), Equals, context.Canceled) -} - -func (s *chunkRestoreSuite) TestDeliverLoopEmptyData(c *C) { - ctx := context.Background() - - // Open two mock engines. - - controller := gomock.NewController(c) - defer controller.Finish() - mockBackend := mock.NewMockBackend(controller) - importer := backend.MakeBackend(mockBackend) - - mockBackend.EXPECT().OpenEngine(ctx, gomock.Any(), gomock.Any()).Return(nil).Times(2) - mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).AnyTimes() - mockWriter := mock.NewMockEngineWriter(controller) - mockBackend.EXPECT().LocalWriter(ctx, gomock.Any(), gomock.Any()).Return(mockWriter, nil).AnyTimes() - mockWriter.EXPECT(). - AppendRows(ctx, gomock.Any(), gomock.Any(), gomock.Any()). - Return(nil).AnyTimes() - - dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) - c.Assert(err, IsNil) - dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) - c.Assert(err, IsNil) - indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - - // Deliver nothing. - - cfg := &config.Config{} - rc := &Controller{cfg: cfg, backend: importer, diskQuotaLock: newDiskQuotaLock()} - - kvsCh := make(chan []deliveredKVs, 1) - kvsCh <- []deliveredKVs{} - _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) - c.Assert(err, IsNil) -} - -func (s *chunkRestoreSuite) TestDeliverLoop(c *C) { - ctx := context.Background() - kvsCh := make(chan []deliveredKVs) - mockCols := []string{"c1", "c2"} - - // Open two mock engines. - - controller := gomock.NewController(c) - defer controller.Finish() - mockBackend := mock.NewMockBackend(controller) - importer := backend.MakeBackend(mockBackend) - - mockBackend.EXPECT().OpenEngine(ctx, gomock.Any(), gomock.Any()).Return(nil).Times(2) - // avoid return the same object at each call - mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) - mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).Times(1) - mockWriter := mock.NewMockEngineWriter(controller) - mockBackend.EXPECT().LocalWriter(ctx, gomock.Any(), gomock.Any()).Return(mockWriter, nil).AnyTimes() - mockWriter.EXPECT().IsSynced().Return(true).AnyTimes() - - dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) - c.Assert(err, IsNil) - indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) - c.Assert(err, IsNil) - - dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - - // Set up the expected API calls to the data engine... - - mockWriter.EXPECT(). - AppendRows(ctx, s.tr.tableName, mockCols, kv.MakeRowsFromKvPairs([]common.KvPair{ - { - Key: []byte("txxxxxxxx_ryyyyyyyy"), - Val: []byte("value1"), - }, - { - Key: []byte("txxxxxxxx_rwwwwwwww"), - Val: []byte("value2"), - }, - })). - Return(nil) - - // ... and the index engine. - // - // Note: This test assumes data engine is written before the index engine. - - mockWriter.EXPECT(). - AppendRows(ctx, s.tr.tableName, mockCols, kv.MakeRowsFromKvPairs([]common.KvPair{ - { - Key: []byte("txxxxxxxx_izzzzzzzz"), - Val: []byte("index1"), - }, - })). - Return(nil) - - // Now actually start the delivery loop. - - saveCpCh := make(chan saveCp, 2) - go func() { - kvsCh <- []deliveredKVs{ - { - kvs: kv.MakeRowFromKvPairs([]common.KvPair{ - { - Key: []byte("txxxxxxxx_ryyyyyyyy"), - Val: []byte("value1"), - }, - { - Key: []byte("txxxxxxxx_rwwwwwwww"), - Val: []byte("value2"), - }, - { - Key: []byte("txxxxxxxx_izzzzzzzz"), - Val: []byte("index1"), - }, - }), - columns: mockCols, - offset: 12, - rowID: 76, - }, - } - kvsCh <- []deliveredKVs{} - close(kvsCh) - }() - - cfg := &config.Config{} - rc := &Controller{cfg: cfg, saveCpCh: saveCpCh, backend: importer, diskQuotaLock: newDiskQuotaLock()} - - _, err = s.cr.deliverLoop(ctx, kvsCh, s.tr, 0, dataWriter, indexWriter, rc) - c.Assert(err, IsNil) - c.Assert(saveCpCh, HasLen, 2) - c.Assert(s.cr.chunk.Chunk.Offset, Equals, int64(12)) - c.Assert(s.cr.chunk.Chunk.PrevRowIDMax, Equals, int64(76)) - c.Assert(s.cr.chunk.Checksum.SumKVS(), Equals, uint64(3)) -} - -func (s *chunkRestoreSuite) TestEncodeLoop(c *C) { - ctx := context.Background() - kvsCh := make(chan []deliveredKVs, 2) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567895, - }) - c.Assert(err, IsNil) - cfg := config.NewConfig() - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, IsNil) - c.Assert(kvsCh, HasLen, 2) - - kvs := <-kvsCh - c.Assert(kvs, HasLen, 1) - c.Assert(kvs[0].rowID, Equals, int64(19)) - c.Assert(kvs[0].offset, Equals, int64(36)) - c.Assert(kvs[0].columns, DeepEquals, []string(nil)) - - kvs = <-kvsCh - c.Assert(len(kvs), Equals, 0) -} - -func (s *chunkRestoreSuite) TestEncodeLoopCanceled(c *C) { - ctx, cancel := context.WithCancel(context.Background()) - kvsCh := make(chan []deliveredKVs) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567896, - }) - c.Assert(err, IsNil) - - go cancel() - cfg := config.NewConfig() - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(errors.Cause(err), Equals, context.Canceled) - c.Assert(kvsCh, HasLen, 0) -} - -func (s *chunkRestoreSuite) TestEncodeLoopForcedError(c *C) { - ctx := context.Background() - kvsCh := make(chan []deliveredKVs, 2) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567897, - }) - c.Assert(err, IsNil) - - // close the chunk so reading it will result in the "file already closed" error. - s.cr.parser.Close() - - cfg := config.NewConfig() - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, ErrorMatches, `in file .*[/\\]?db\.table\.2\.sql:0 at offset 0:.*file already closed`) - c.Assert(kvsCh, HasLen, 0) -} - -func (s *chunkRestoreSuite) TestEncodeLoopDeliverLimit(c *C) { - ctx := context.Background() - kvsCh := make(chan []deliveredKVs, 4) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567898, - }) - c.Assert(err, IsNil) - - dir := c.MkDir() - fileName := "db.limit.000.csv" - err = os.WriteFile(filepath.Join(dir, fileName), []byte("1,2,3\r\n4,5,6\r\n7,8,9\r"), 0o644) - c.Assert(err, IsNil) - - store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - cfg := config.NewConfig() - - reader, err := store.Open(ctx, fileName) - c.Assert(err, IsNil) - w := worker.NewPool(ctx, 1, "io") - p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, false, nil) - c.Assert(err, IsNil) - s.cr.parser = p - - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - c.Assert(failpoint.Enable( - "github.com/pingcap/tidb/br/pkg/lightning/restore/mock-kv-size", "return(110000000)"), IsNil) - defer failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/mock-kv-size") - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, IsNil) - - // we have 3 kvs total. after the failpoint injected. - // we will send one kv each time. - count := 0 - for { - kvs, ok := <-kvsCh - if !ok { - break - } - count += 1 - if count <= 3 { - c.Assert(kvs, HasLen, 1) - } - if count == 4 { - // we will send empty kvs before encodeLoop exists - // so, we can receive 4 batch and 1 is empty - c.Assert(kvs, HasLen, 0) - break - } - } -} - -func (s *chunkRestoreSuite) TestEncodeLoopDeliverErrored(c *C) { - ctx := context.Background() - kvsCh := make(chan []deliveredKVs) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := kv.NewTableKVEncoder(s.tr.encTable, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567898, - }) - c.Assert(err, IsNil) - - go func() { - deliverCompleteCh <- deliverResult{ - err: errors.New("fake deliver error"), - } - }() - cfg := config.NewConfig() - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, ErrorMatches, "fake deliver error") - c.Assert(kvsCh, HasLen, 0) -} - -func (s *chunkRestoreSuite) TestEncodeLoopColumnsMismatch(c *C) { - dir := c.MkDir() - fileName := "db.table.000.csv" - err := os.WriteFile(filepath.Join(dir, fileName), []byte("1,2\r\n4,5,6,7\r\n"), 0o644) - c.Assert(err, IsNil) - - store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - - ctx := context.Background() - cfg := config.NewConfig() - errorMgr := errormanager.New(nil, cfg) - rc := &Controller{pauser: DeliverPauser, cfg: cfg, errorMgr: errorMgr} - - reader, err := store.Open(ctx, fileName) - c.Assert(err, IsNil) - w := worker.NewPool(ctx, 5, "io") - p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, false, nil) - c.Assert(err, IsNil) - - err = s.cr.parser.Close() - c.Assert(err, IsNil) - s.cr.parser = p - - kvsCh := make(chan []deliveredKVs, 2) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := tidb.NewTiDBBackend(nil, config.ReplaceOnDup, errorMgr).NewEncoder( - s.tr.encTable, - &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567895, - }) - c.Assert(err, IsNil) - defer kvEncoder.Close() - - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, ErrorMatches, "in file db.table.2.sql:0 at offset 4: column count mismatch, expected 3, got 2") - c.Assert(kvsCh, HasLen, 0) -} - -func (s *chunkRestoreSuite) TestEncodeLoopIgnoreColumnsCSV(c *C) { - cases := []struct { - s string - ignoreColumns []*config.IgnoreColumns - kvs deliveredKVs - header bool - }{ - { - "1,2,3\r\n4,5,6\r\n", - []*config.IgnoreColumns{ - { - DB: "db", - Table: "table", - Columns: []string{"a"}, - }, - }, - deliveredKVs{ - rowID: 1, - offset: 6, - columns: []string{"b", "c"}, - }, - false, - }, - { - "b,c\r\n2,3\r\n5,6\r\n", - []*config.IgnoreColumns{ - { - TableFilter: []string{"db*.tab*"}, - Columns: []string{"b"}, - }, - }, - deliveredKVs{ - rowID: 1, - offset: 9, - columns: []string{"c"}, - }, - true, - }, - } - - for _, cs := range cases { - // reset test - s.SetUpTest(c) - s.testEncodeLoopIgnoreColumnsCSV(c, cs.s, cs.ignoreColumns, cs.kvs, cs.header) - } -} - -func (s *chunkRestoreSuite) testEncodeLoopIgnoreColumnsCSV( - c *C, - f string, - ignoreColumns []*config.IgnoreColumns, - deliverKV deliveredKVs, - header bool, -) { - dir := c.MkDir() - fileName := "db.table.000.csv" - err := os.WriteFile(filepath.Join(dir, fileName), []byte(f), 0o644) - c.Assert(err, IsNil) - - store, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - - ctx := context.Background() - cfg := config.NewConfig() - cfg.Mydumper.IgnoreColumns = ignoreColumns - cfg.Mydumper.CSV.Header = header - rc := &Controller{pauser: DeliverPauser, cfg: cfg} - - reader, err := store.Open(ctx, fileName) - c.Assert(err, IsNil) - w := worker.NewPool(ctx, 5, "io") - p, err := mydump.NewCSVParser(&cfg.Mydumper.CSV, reader, 111, w, cfg.Mydumper.CSV.Header, nil) - c.Assert(err, IsNil) - - err = s.cr.parser.Close() - c.Assert(err, IsNil) - s.cr.parser = p - - kvsCh := make(chan []deliveredKVs, 2) - deliverCompleteCh := make(chan deliverResult) - kvEncoder, err := tidb.NewTiDBBackend(nil, config.ReplaceOnDup, errormanager.New(nil, config.NewConfig())).NewEncoder( - s.tr.encTable, - &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 1234567895, - }) - c.Assert(err, IsNil) - defer kvEncoder.Close() - - _, _, err = s.cr.encodeLoop(ctx, kvsCh, s.tr, s.tr.logger, kvEncoder, deliverCompleteCh, rc) - c.Assert(err, IsNil) - c.Assert(kvsCh, HasLen, 2) - - kvs := <-kvsCh - c.Assert(kvs, HasLen, 2) - c.Assert(kvs[0].rowID, Equals, deliverKV.rowID) - c.Assert(kvs[0].offset, Equals, deliverKV.offset) - c.Assert(kvs[0].columns, DeepEquals, deliverKV.columns) - - kvs = <-kvsCh - c.Assert(len(kvs), Equals, 0) -} - -func (s *chunkRestoreSuite) TestRestore(c *C) { - ctx := context.Background() - - // Open two mock engines - - controller := gomock.NewController(c) - defer controller.Finish() - mockClient := mock.NewMockImportKVClient(controller) - mockDataWriter := mock.NewMockImportKV_WriteEngineClient(controller) - mockIndexWriter := mock.NewMockImportKV_WriteEngineClient(controller) - importer := importer.NewMockImporter(mockClient, "127.0.0.1:2379") - - mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) - mockClient.EXPECT().OpenEngine(ctx, gomock.Any()).Return(nil, nil) - - dataEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, 0) - c.Assert(err, IsNil) - indexEngine, err := importer.OpenEngine(ctx, &backend.EngineConfig{}, s.tr.tableName, -1) - c.Assert(err, IsNil) - dataWriter, err := dataEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) - c.Assert(err, IsNil) - - // Expected API sequence - // (we don't care about the actual content, this would be checked in the integrated tests) - - mockClient.EXPECT().WriteEngine(ctx).Return(mockDataWriter, nil) - mockDataWriter.EXPECT().Send(gomock.Any()).Return(nil) - mockDataWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { - c.Assert(req.GetBatch().GetMutations(), HasLen, 1) - return nil - }) - mockDataWriter.EXPECT().CloseAndRecv().Return(nil, nil) - - mockClient.EXPECT().WriteEngine(ctx).Return(mockIndexWriter, nil) - mockIndexWriter.EXPECT().Send(gomock.Any()).Return(nil) - mockIndexWriter.EXPECT().Send(gomock.Any()).DoAndReturn(func(req *import_kvpb.WriteEngineRequest) error { - c.Assert(req.GetBatch().GetMutations(), HasLen, 1) - return nil - }) - mockIndexWriter.EXPECT().CloseAndRecv().Return(nil, nil) - - // Now actually start the restore loop. - - saveCpCh := make(chan saveCp, 2) - err = s.cr.restore(ctx, s.tr, 0, dataWriter, indexWriter, &Controller{ - cfg: s.cfg, - saveCpCh: saveCpCh, - backend: importer, - pauser: DeliverPauser, - diskQuotaLock: newDiskQuotaLock(), - }) - c.Assert(err, IsNil) - c.Assert(saveCpCh, HasLen, 2) -} - -var _ = Suite(&restoreSchemaSuite{}) - -type restoreSchemaSuite struct { - ctx context.Context - rc *Controller - controller *gomock.Controller - tableInfos []*model.TableInfo -} - -func (s *restoreSchemaSuite) SetUpSuite(c *C) { - ctx := context.Background() - fakeDataDir := c.MkDir() - store, err := storage.NewLocalStorage(fakeDataDir) - c.Assert(err, IsNil) - // restore database schema file - fakeDBName := "fakedb" - // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}-schema-create.sql' - fakeFileName := fmt.Sprintf("%s-schema-create.sql", fakeDBName) - err = store.WriteFile(ctx, fakeFileName, []byte(fmt.Sprintf("CREATE DATABASE %s;", fakeDBName))) - c.Assert(err, IsNil) - // restore table schema files - fakeTableFilesCount := 8 - - p := parser.New() - p.SetSQLMode(mysql.ModeANSIQuotes) - se := tmock.NewContext() - - tableInfos := make([]*model.TableInfo, 0, fakeTableFilesCount) - for i := 1; i <= fakeTableFilesCount; i++ { - fakeTableName := fmt.Sprintf("tbl%d", i) - // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}.{table}-schema.sql' - fakeFileName := fmt.Sprintf("%s.%s-schema.sql", fakeDBName, fakeTableName) - fakeFileContent := fmt.Sprintf("CREATE TABLE %s(i TINYINT);", fakeTableName) - err = store.WriteFile(ctx, fakeFileName, []byte(fakeFileContent)) - c.Assert(err, IsNil) - - node, err := p.ParseOneStmt(fakeFileContent, "", "") - c.Assert(err, IsNil) - core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) - c.Assert(err, IsNil) - core.State = model.StatePublic - tableInfos = append(tableInfos, core) - } - s.tableInfos = tableInfos - // restore view schema files - fakeViewFilesCount := 8 - for i := 1; i <= fakeViewFilesCount; i++ { - fakeViewName := fmt.Sprintf("tbl%d", i) - // please follow the `mydump.defaultFileRouteRules`, matches files like '{schema}.{table}-schema-view.sql' - fakeFileName := fmt.Sprintf("%s.%s-schema-view.sql", fakeDBName, fakeViewName) - fakeFileContent := []byte(fmt.Sprintf("CREATE ALGORITHM=UNDEFINED VIEW `%s` (`i`) AS SELECT `i` FROM `%s`.`%s`;", fakeViewName, fakeDBName, fmt.Sprintf("tbl%d", i))) - err = store.WriteFile(ctx, fakeFileName, fakeFileContent) - c.Assert(err, IsNil) - } - config := config.NewConfig() - config.Mydumper.DefaultFileRules = true - config.Mydumper.CharacterSet = "utf8mb4" - config.App.RegionConcurrency = 8 - mydumpLoader, err := mydump.NewMyDumpLoaderWithStore(ctx, config, store) - c.Assert(err, IsNil) - s.rc = &Controller{ - checkTemplate: NewSimpleTemplate(), - cfg: config, - store: store, - dbMetas: mydumpLoader.GetDatabases(), - checkpointsDB: &checkpoints.NullCheckpointsDB{}, - } -} - -//nolint:interfacer // change test case signature might cause Check failed to find this test case? -func (s *restoreSchemaSuite) SetUpTest(c *C) { - s.controller, s.ctx = gomock.WithContext(context.Background(), c) - mockBackend := mock.NewMockBackend(s.controller) - mockBackend.EXPECT(). - FetchRemoteTableModels(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(s.tableInfos, nil) - mockBackend.EXPECT().Close() - s.rc.backend = backend.MakeBackend(mockBackend) - - mockDB, sqlMock, err := sqlmock.New() - c.Assert(err, IsNil) - for i := 0; i < 17; i++ { - sqlMock.ExpectExec(".*").WillReturnResult(sqlmock.NewResult(int64(i), 1)) - } - mockTiDBGlue := mock.NewMockGlue(s.controller) - mockTiDBGlue.EXPECT().GetDB().AnyTimes().Return(mockDB, nil) - mockTiDBGlue.EXPECT(). - OwnsSQLExecutor(). - AnyTimes(). - Return(true) - parser := parser.New() - mockTiDBGlue.EXPECT(). - GetParser(). - AnyTimes(). - Return(parser) - s.rc.tidbGlue = mockTiDBGlue -} - -func (s *restoreSchemaSuite) TearDownTest(c *C) { - s.rc.Close() - s.controller.Finish() -} - -func (s *restoreSchemaSuite) TestRestoreSchemaSuccessful(c *C) { - // before restore, if sysVars is initialized by other test, the time_zone should be default value - if len(s.rc.sysVars) > 0 { - tz, ok := s.rc.sysVars["time_zone"] - c.Assert(ok, IsTrue) - c.Assert(tz, Equals, "SYSTEM") - } - - s.rc.cfg.TiDB.Vars = map[string]string{ - "time_zone": "UTC", - } - err := s.rc.restoreSchema(s.ctx) - c.Assert(err, IsNil) - - // test after restore schema, sysVars has been updated - tz, ok := s.rc.sysVars["time_zone"] - c.Assert(ok, IsTrue) - c.Assert(tz, Equals, "UTC") -} - -func (s *restoreSchemaSuite) TestRestoreSchemaFailed(c *C) { - injectErr := errors.New("Something wrong") - mockSession := mock.NewMockSession(s.controller) - mockSession.EXPECT(). - Close(). - AnyTimes(). - Return() - mockSession.EXPECT(). - Execute(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil, injectErr) - mockTiDBGlue := mock.NewMockGlue(s.controller) - mockTiDBGlue.EXPECT(). - GetSession(gomock.Any()). - AnyTimes(). - Return(mockSession, nil) - s.rc.tidbGlue = mockTiDBGlue - err := s.rc.restoreSchema(s.ctx) - c.Assert(err, NotNil) - c.Assert(errors.ErrorEqual(err, injectErr), IsTrue) -} - -// When restoring a CSV with `-no-schema` and the target table doesn't exist -// then we can't restore the schema as the `Path` is empty. This is to make -// sure this results in the correct error. -// https://github.com/pingcap/br/issues/1394 -func (s *restoreSchemaSuite) TestNoSchemaPath(c *C) { - fakeTable := mydump.MDTableMeta{ - DB: "fakedb", - Name: "fake1", - SchemaFile: mydump.FileInfo{ - TableName: filter.Table{ - Schema: "fakedb", - Name: "fake1", - }, - FileMeta: mydump.SourceFileMeta{ - Path: "", - }, - }, - DataFiles: []mydump.FileInfo{}, - TotalSize: 0, - } - s.rc.dbMetas[0].Tables = append(s.rc.dbMetas[0].Tables, &fakeTable) - err := s.rc.restoreSchema(s.ctx) - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, `table .* schema not found`) - s.rc.dbMetas[0].Tables = s.rc.dbMetas[0].Tables[:len(s.rc.dbMetas[0].Tables)-1] -} - -func (s *restoreSchemaSuite) TestRestoreSchemaContextCancel(c *C) { - childCtx, cancel := context.WithCancel(s.ctx) - mockSession := mock.NewMockSession(s.controller) - mockSession.EXPECT(). - Close(). - AnyTimes(). - Return() - mockSession.EXPECT(). - Execute(gomock.Any(), gomock.Any()). - AnyTimes(). - Do(func(context.Context, string) { cancel() }). - Return(nil, nil) - mockTiDBGlue := mock.NewMockGlue(s.controller) - mockTiDBGlue.EXPECT(). - GetSession(gomock.Any()). - AnyTimes(). - Return(mockSession, nil) - s.rc.tidbGlue = mockTiDBGlue - err := s.rc.restoreSchema(childCtx) - cancel() - c.Assert(err, NotNil) - c.Assert(err, Equals, childCtx.Err()) -} - -func (s *tableRestoreSuite) TestCheckClusterResource(c *C) { - cases := []struct { - mockStoreResponse []byte - mockReplicaResponse []byte - expectMsg string - expectResult bool - expectErrorCount int - }{ - { - []byte(`{ - "count": 1, - "stores": [ - { - "store": { - "id": 2 - }, - "status": { - "available": "24" - } - } - ] - }`), - []byte(`{ - "max-replicas": 1 - }`), - "(.*)Cluster available is rich(.*)", - true, - 0, - }, - { - []byte(`{ - "count": 1, - "stores": [ - { - "store": { - "id": 2 - }, - "status": { - "available": "15" - } - } - ] - }`), - []byte(`{ - "max-replicas": 1 - }`), - "(.*)Cluster doesn't have enough space(.*)", - false, - 1, - }, - } - - ctx := context.Background() - dir := c.MkDir() - file := filepath.Join(dir, "tmp") - f, err := os.Create(file) - c.Assert(err, IsNil) - buf := make([]byte, 16) - // write 16 bytes file into local storage - for i := range buf { - buf[i] = byte('A' + i) - } - _, err = f.Write(buf) - c.Assert(err, IsNil) - mockStore, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - for _, ca := range cases { - server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var err error - if strings.HasSuffix(req.URL.Path, "stores") { - _, err = w.Write(ca.mockStoreResponse) - } else { - _, err = w.Write(ca.mockReplicaResponse) - } - c.Assert(err, IsNil) - })) - - tls := common.NewTLSFromMockServer(server) - template := NewSimpleTemplate() - - url := strings.TrimPrefix(server.URL, "https://") - cfg := &config.Config{TiDB: config.DBStore{PdAddr: url}} - rc := &Controller{cfg: cfg, tls: tls, store: mockStore, checkTemplate: template} - var sourceSize int64 - err = rc.store.WalkDir(ctx, &storage.WalkOption{}, func(path string, size int64) error { - sourceSize += size - return nil - }) - err = rc.clusterResource(ctx, sourceSize) - c.Assert(err, IsNil) - - c.Assert(template.FailedCount(Critical), Equals, ca.expectErrorCount) - c.Assert(template.Success(), Equals, ca.expectResult) - c.Assert(strings.ReplaceAll(template.Output(), "\n", ""), Matches, ca.expectMsg) - - server.Close() - } -} - -type mockTaskMetaMgr struct { - taskMetaMgr -} - -func (mockTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(tasks []taskMeta) ([]taskMeta, error)) error { - _, err := action([]taskMeta{{ - taskID: 1, - pdCfgs: "", - status: taskMetaStatusInitial, - state: taskStateNormal, - }}) - return err -} - -func (s *tableRestoreSuite) TestCheckClusterRegion(c *C) { - type testCase struct { - stores api.StoresInfo - emptyRegions api.RegionsInfo - expectMsgs []string - expectResult bool - expectErrorCnt int - } - - makeRegions := func(regionCnt int, storeID uint64) []api.RegionInfo { - var regions []api.RegionInfo - for i := 0; i < regionCnt; i++ { - regions = append(regions, api.RegionInfo{Peers: []api.MetaPeer{{Peer: &metapb.Peer{StoreId: storeID}}}}) - } - return regions - } - - testCases := []testCase{ - { - stores: api.StoresInfo{Stores: []*api.StoreInfo{ - {Store: &api.MetaStore{StoreID: 1}, Status: &api.StoreStatus{RegionCount: 200}}, - }}, - emptyRegions: api.RegionsInfo{ - Regions: append([]api.RegionInfo(nil), makeRegions(100, 1)...), - }, - expectMsgs: []string{".*Cluster doesn't have too many empty regions.*", ".*Cluster region distribution is balanced.*"}, - expectResult: true, - expectErrorCnt: 0, - }, - { - stores: api.StoresInfo{Stores: []*api.StoreInfo{ - {Store: &api.MetaStore{StoreID: 1}, Status: &api.StoreStatus{RegionCount: 2000}}, - {Store: &api.MetaStore{StoreID: 2}, Status: &api.StoreStatus{RegionCount: 3100}}, - {Store: &api.MetaStore{StoreID: 3}, Status: &api.StoreStatus{RegionCount: 2500}}, - }}, - emptyRegions: api.RegionsInfo{ - Regions: append(append(append([]api.RegionInfo(nil), - makeRegions(600, 1)...), - makeRegions(300, 2)...), - makeRegions(1200, 3)...), - }, - expectMsgs: []string{ - ".*TiKV stores \\(3\\) contains more than 1000 empty regions respectively.*", - ".*TiKV stores \\(1\\) contains more than 500 empty regions respectively.*", - ".*Region distribution is unbalanced.*but we expect it should not be less than 0.75.*", - }, - expectResult: false, - expectErrorCnt: 1, - }, - { - stores: api.StoresInfo{Stores: []*api.StoreInfo{ - {Store: &api.MetaStore{StoreID: 1}, Status: &api.StoreStatus{RegionCount: 1200}}, - {Store: &api.MetaStore{StoreID: 2}, Status: &api.StoreStatus{RegionCount: 3000}}, - {Store: &api.MetaStore{StoreID: 3}, Status: &api.StoreStatus{RegionCount: 2500}}, - }}, - expectMsgs: []string{".*Region distribution is unbalanced.*but we expect it must not be less than 0.5.*"}, - expectResult: false, - expectErrorCnt: 1, - }, - { - stores: api.StoresInfo{Stores: []*api.StoreInfo{ - {Store: &api.MetaStore{StoreID: 1}, Status: &api.StoreStatus{RegionCount: 0}}, - {Store: &api.MetaStore{StoreID: 2}, Status: &api.StoreStatus{RegionCount: 2800}}, - {Store: &api.MetaStore{StoreID: 3}, Status: &api.StoreStatus{RegionCount: 2500}}, - }}, - expectMsgs: []string{".*Region distribution is unbalanced.*but we expect it must not be less than 0.5.*"}, - expectResult: false, - expectErrorCnt: 1, - }, - } - - mustMarshal := func(v interface{}) []byte { - data, err := json.Marshal(v) - c.Assert(err, IsNil) - return data - } - - for _, ca := range testCases { - server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var err error - if req.URL.Path == pdStores { - _, err = w.Write(mustMarshal(ca.stores)) - } else if req.URL.Path == pdEmptyRegions { - _, err = w.Write(mustMarshal(ca.emptyRegions)) - } else { - w.WriteHeader(http.StatusNotFound) - } - c.Assert(err, IsNil) - })) - - tls := common.NewTLSFromMockServer(server) - template := NewSimpleTemplate() - - url := strings.TrimPrefix(server.URL, "https://") - cfg := &config.Config{TiDB: config.DBStore{PdAddr: url}} - rc := &Controller{cfg: cfg, tls: tls, taskMgr: mockTaskMetaMgr{}, checkTemplate: template} - - err := rc.checkClusterRegion(context.Background()) - c.Assert(err, IsNil) - c.Assert(template.FailedCount(Critical), Equals, ca.expectErrorCnt) - c.Assert(template.Success(), Equals, ca.expectResult) - - for _, expectMsg := range ca.expectMsgs { - c.Assert(strings.ReplaceAll(template.Output(), "\n", ""), Matches, expectMsg) - } - - server.Close() - } -} - -func (s *tableRestoreSuite) TestCheckHasLargeCSV(c *C) { - cases := []struct { - strictFormat bool - expectMsg string - expectResult bool - expectWarnCount int - dbMetas []*mydump.MDDatabaseMeta - }{ - { - true, - "(.*)Skip the csv size check, because config.StrictFormat is true(.*)", - true, - 0, - nil, - }, - { - false, - "(.*)Source csv files size is proper(.*)", - true, - 0, - []*mydump.MDDatabaseMeta{ - { - Tables: []*mydump.MDTableMeta{ - { - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.KiB, - }, - }, - }, - }, - }, - }, - }, - }, - { - false, - "(.*)large csv: /testPath file exists(.*)", - true, - 1, - []*mydump.MDDatabaseMeta{ - { - Tables: []*mydump.MDTableMeta{ - { - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: "/testPath", - }, - }, - }, - }, - }, - }, - }, - }, - } - dir := c.MkDir() - mockStore, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - - for _, ca := range cases { - template := NewSimpleTemplate() - cfg := &config.Config{Mydumper: config.MydumperRuntime{StrictFormat: ca.strictFormat}} - rc := &Controller{cfg: cfg, checkTemplate: template, store: mockStore} - err := rc.HasLargeCSV(ca.dbMetas) - c.Assert(err, IsNil) - c.Assert(template.FailedCount(Warn), Equals, ca.expectWarnCount) - c.Assert(template.Success(), Equals, ca.expectResult) - c.Assert(strings.ReplaceAll(template.Output(), "\n", ""), Matches, ca.expectMsg) - } -} -func (s *tableRestoreSuite) TestEstimate(c *C) { - ctx := context.Background() - controller := gomock.NewController(c) - defer controller.Finish() - mockBackend := mock.NewMockBackend(controller) - idAlloc := kv.NewPanickingAllocators(0) - tbl, err := tables.TableFromMeta(idAlloc, s.tableInfo.Core) - c.Assert(err, IsNil) - - mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).AnyTimes() - mockBackend.EXPECT().NewEncoder(gomock.Any(), gomock.Any()).Return(kv.NewTableKVEncoder(tbl, &kv.SessionOptions{ - SQLMode: s.cfg.TiDB.SQLMode, - Timestamp: 0, - AutoRandomSeed: 0, - })).AnyTimes() - importer := backend.MakeBackend(mockBackend) - s.cfg.TikvImporter.Backend = config.BackendLocal - - template := NewSimpleTemplate() - rc := &Controller{ - cfg: s.cfg, - checkTemplate: template, - store: s.store, - backend: importer, - dbMetas: []*mydump.MDDatabaseMeta{ - { - Name: "db1", - Tables: []*mydump.MDTableMeta{s.tableMeta}, - }, - }, - dbInfos: map[string]*checkpoints.TidbDBInfo{ - "db1": s.dbInfo, - }, - ioWorkers: worker.NewPool(context.Background(), 1, "io"), - } - source, err := rc.estimateSourceData(ctx) - // Because this file is small than region split size so we does not sample it. - c.Assert(err, IsNil) - c.Assert(source, Equals, s.tableMeta.TotalSize) - s.tableMeta.TotalSize = int64(config.SplitRegionSize) - source, err = rc.estimateSourceData(ctx) - c.Assert(err, IsNil) - c.Assert(source, Greater, s.tableMeta.TotalSize) - rc.cfg.TikvImporter.Backend = config.BackendTiDB - source, err = rc.estimateSourceData(ctx) - c.Assert(err, IsNil) - c.Assert(source, Equals, s.tableMeta.TotalSize) -} - -func (s *tableRestoreSuite) TestSchemaIsValid(c *C) { - dir := c.MkDir() - ctx := context.Background() - - case1File := "db1.table1.csv" - mockStore, err := storage.NewLocalStorage(dir) - c.Assert(err, IsNil) - err = mockStore.WriteFile(ctx, case1File, []byte(`"a"`)) - c.Assert(err, IsNil) - - case2File := "db1.table2.csv" - err = mockStore.WriteFile(ctx, case2File, []byte("\"colA\",\"colB\"\n\"a\",\"b\"")) - c.Assert(err, IsNil) - - cases := []struct { - ignoreColumns []*config.IgnoreColumns - expectMsg string - // MsgNum == 0 means the check passed. - MsgNum int - hasHeader bool - dbInfos map[string]*checkpoints.TidbDBInfo - tableMeta *mydump.MDTableMeta - }{ - // Case 1: - // csv has one column without header. - // tidb has the two columns but the second column doesn't have the default value. - // we expect the check failed. - { - nil, - "TiDB schema `db1`.`table1` has 2 columns,and data file has 1 columns, but column colb are missing(.*)", - 1, - false, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table1": { - ID: 1, - DB: "db1", - Name: "table1", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colA has the default value - Name: model.NewCIStr("colA"), - DefaultIsExpr: true, - }, - { - // colB doesn't have the default value - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - // not null flag - Flag: 1, - }, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table1", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case1File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 2.1: - // csv has two columns(colA, colB) with the header. - // tidb only has one column(colB). - // we expect the check failed. - { - nil, - "TiDB schema `db1`.`table2` doesn't have column cola,(.*)use tables.ignoreColumns to ignore(.*)", - 1, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table2": { - ID: 1, - DB: "db1", - Name: "table2", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colB has the default value - Name: model.NewCIStr("colB"), - DefaultIsExpr: true, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table2", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 2.2: - // csv has two columns(colA, colB) with the header. - // tidb only has one column(colB). - // we ignore colA by set config tables.IgnoreColumns - // we expect the check success. - { - []*config.IgnoreColumns{ - { - DB: "db1", - Table: "table2", - Columns: []string{"cola"}, - }, - }, - "", - 0, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table2": { - ID: 1, - DB: "db1", - Name: "table2", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colB has the default value - Name: model.NewCIStr("colB"), - DefaultIsExpr: true, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table2", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 2.3: - // csv has two columns(colA, colB) with the header. - // tidb has two columns(colB, colC). - // we ignore colA by set config tables.IgnoreColumns - // colC doesn't have the default value. - // we expect the check failed. - { - []*config.IgnoreColumns{ - { - DB: "db1", - Table: "table2", - Columns: []string{"cola"}, - }, - }, - "TiDB schema `db1`.`table2` doesn't have the default value for colc(.*)", - 1, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table2": { - ID: 1, - DB: "db1", - Name: "table2", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colB has the default value - Name: model.NewCIStr("colB"), - DefaultIsExpr: true, - }, - { - // colC doesn't have the default value - Name: model.NewCIStr("colC"), - FieldType: types.FieldType{ - Flag: 1, - }, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table2", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 2.4: - // csv has two columns(colA, colB) with the header. - // tidb has two columns(colB, colC). - // we ignore colB by set config tables.IgnoreColumns - // colB doesn't have the default value. - // we expect the check failed. - { - []*config.IgnoreColumns{ - { - TableFilter: []string{"`db1`.`table2`"}, - Columns: []string{"colb"}, - }, - }, - "TiDB schema `db1`.`table2`'s column colb cannot be ignored(.*)", - 2, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table2": { - ID: 1, - DB: "db1", - Name: "table2", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colB doesn't have the default value - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - Flag: 1, - }, - }, - { - // colC has the default value - Name: model.NewCIStr("colC"), - DefaultIsExpr: true, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table2", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 3: - // table3's schema file not found. - // tidb has no table3. - // we expect the check failed. - { - []*config.IgnoreColumns{ - { - TableFilter: []string{"`db1`.`table2`"}, - Columns: []string{"colb"}, - }, - }, - "TiDB schema `db1`.`table3` doesn't exists(.*)", - 1, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "": {}, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table3", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }, - }, - // Case 4: - // table4 has two datafiles for table. we only check the first file. - // we expect the check success. - { - []*config.IgnoreColumns{ - { - DB: "db1", - Table: "table2", - Columns: []string{"cola"}, - }, - }, - "", - 0, - true, - map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "table2": { - ID: 1, - DB: "db1", - Name: "table2", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - // colB has the default value - Name: model.NewCIStr("colB"), - DefaultIsExpr: true, - }, - }, - }, - }, - }, - }, - }, - &mydump.MDTableMeta{ - DB: "db1", - Name: "table2", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - Type: mydump.SourceTypeCSV, - }, - }, - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: case2File, - // This type will make the check failed. - // but it's the second file for table. - // so it's unreachable so this case will success. - Type: mydump.SourceTypeIgnore, - }, - }, - }, - }, - }, - } - - for _, ca := range cases { - template := NewSimpleTemplate() - cfg := &config.Config{ - Mydumper: config.MydumperRuntime{ - ReadBlockSize: config.ReadBlockSize, - CSV: config.CSVConfig{ - Separator: ",", - Delimiter: `"`, - Header: ca.hasHeader, - NotNull: false, - Null: `\N`, - BackslashEscape: true, - TrimLastSep: false, - }, - IgnoreColumns: ca.ignoreColumns, - }, - } - rc := &Controller{ - cfg: cfg, - checkTemplate: template, - store: mockStore, - dbInfos: ca.dbInfos, - ioWorkers: worker.NewPool(context.Background(), 1, "io"), - } - msgs, err := rc.SchemaIsValid(ctx, ca.tableMeta) - c.Assert(err, IsNil) - c.Assert(msgs, HasLen, ca.MsgNum) - if len(msgs) > 0 { - c.Assert(msgs[0], Matches, ca.expectMsg) - } - } -} - -func (s *tableRestoreSuite) TestGBKEncodedSchemaIsValid(c *C) { - cfg := &config.Config{ - Mydumper: config.MydumperRuntime{ - ReadBlockSize: config.ReadBlockSize, - DataCharacterSet: "gb18030", - DataInvalidCharReplace: string(utf8.RuneError), - CSV: config.CSVConfig{ - Separator: ",", - Delimiter: `"`, - Header: true, - NotNull: false, - Null: `\N`, - BackslashEscape: true, - TrimLastSep: false, - }, - IgnoreColumns: nil, - }, - } - charsetConvertor, err := mydump.NewCharsetConvertor(cfg.Mydumper.DataCharacterSet, cfg.Mydumper.DataInvalidCharReplace) - c.Assert(err, IsNil) - mockStore, err := storage.NewLocalStorage(c.MkDir()) - c.Assert(err, IsNil) - csvContent, err := charsetConvertor.Encode(string([]byte("\"colA\",\"colB\"\n\"a\",\"b\""))) - c.Assert(err, IsNil) - ctx := context.Background() - csvFile := "db1.gbk_table.csv" - err = mockStore.WriteFile(ctx, csvFile, []byte(csvContent)) - c.Assert(err, IsNil) - - rc := &Controller{ - cfg: cfg, - checkTemplate: NewSimpleTemplate(), - store: mockStore, - dbInfos: map[string]*checkpoints.TidbDBInfo{ - "db1": { - Name: "db1", - Tables: map[string]*checkpoints.TidbTableInfo{ - "gbk_table": { - ID: 1, - DB: "db1", - Name: "gbk_table", - Core: &model.TableInfo{ - Columns: []*model.ColumnInfo{ - { - Name: model.NewCIStr("colA"), - FieldType: types.FieldType{ - Flag: 1, - }, - }, - { - Name: model.NewCIStr("colB"), - FieldType: types.FieldType{ - Flag: 1, - }, - }, - }, - }, - }, - }, - }, - }, - ioWorkers: worker.NewPool(ctx, 1, "io"), - } - msgs, err := rc.SchemaIsValid(ctx, &mydump.MDTableMeta{ - DB: "db1", - Name: "gbk_table", - DataFiles: []mydump.FileInfo{ - { - FileMeta: mydump.SourceFileMeta{ - FileSize: 1 * units.TiB, - Path: csvFile, - Type: mydump.SourceTypeCSV, - }, - }, - }, - }) - c.Assert(err, IsNil) - c.Assert(msgs, HasLen, 0) -} - -type testChecksumMgr struct { - checksum RemoteChecksum - callCnt int -} - -func (t *testChecksumMgr) Checksum(ctx context.Context, tableInfo *checkpoints.TidbTableInfo) (*RemoteChecksum, error) { - t.callCnt++ - return &t.checksum, nil + require.NoError(t, err) + g := glue.NewExternalTiDBGlue(db, mysql.ModeNone) + + ctl := &Controller{ + cfg: cfg, + saveCpCh: make(chan saveCp), + checkpointsDB: panicCheckpointDB{}, + metaMgrBuilder: failMetaMgrBuilder{}, + checkTemplate: NewSimpleTemplate(), + tidbGlue: g, + errorMgr: errormanager.New(nil, cfg), + } + + mock.ExpectBegin() + mock.ExpectQuery("SHOW VARIABLES WHERE Variable_name IN .*"). + WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}). + AddRow("tidb_row_format_version", "2")) + mock.ExpectCommit() + // precheck failed, will not do init checkpoint. + err = ctl.Run(context.Background()) + require.Regexp(t, ".*mock init meta failure", err.Error()) + require.NoError(t, mock.ExpectationsWereMet()) + + mock.ExpectBegin() + mock.ExpectQuery("SHOW VARIABLES WHERE Variable_name IN .*"). + WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}). + AddRow("tidb_row_format_version", "2")) + mock.ExpectCommit() + ctl.saveCpCh = make(chan saveCp) + // precheck failed, will not do init checkpoint. + err1 := ctl.Run(context.Background()) + require.Equal(t, err.Error(), err1.Error()) + require.NoError(t, mock.ExpectationsWereMet()) } diff --git a/br/pkg/lightning/restore/table_restore.go b/br/pkg/lightning/restore/table_restore.go index 8664943e75199..9c3048d9518d6 100644 --- a/br/pkg/lightning/restore/table_restore.go +++ b/br/pkg/lightning/restore/table_restore.go @@ -17,6 +17,7 @@ package restore import ( "context" "sort" + "strings" "sync" "time" @@ -200,18 +201,7 @@ func (tr *TableRestore) restoreEngines(pCtx context.Context, rc *Controller, cp indexEngineCp := cp.Engines[indexEngineID] if indexEngineCp == nil { tr.logger.Error("fail to restoreEngines because indexengine is nil") - return errors.Errorf("table %v index engine checkpoint not found", tr.tableName) - } - // If there is an index engine only, it indicates no data needs to restore. - // So we can change status to imported directly and avoid opening engine. - if len(cp.Engines) == 1 { - if err := rc.saveStatusCheckpoint(pCtx, tr.tableName, indexEngineID, nil, checkpoints.CheckpointStatusImported); err != nil { - return errors.Trace(err) - } - if err := rc.saveStatusCheckpoint(pCtx, tr.tableName, checkpoints.WholeTableEngineID, nil, checkpoints.CheckpointStatusIndexImported); err != nil { - return errors.Trace(err) - } - return nil + return common.ErrCheckpointNotFound.GenWithStack("table %v index engine checkpoint not found", tr.tableName) } ctx, cancel := context.WithCancel(pCtx) @@ -369,12 +359,11 @@ func (tr *TableRestore) restoreEngines(pCtx context.Context, rc *Controller, cp var err error if indexEngineCp.Status < checkpoints.CheckpointStatusImported { err = tr.importKV(ctx, closedIndexEngine, rc, indexEngineID) + failpoint.Inject("FailBeforeIndexEngineImported", func() { + panic("forcing failure due to FailBeforeIndexEngineImported") + }) } - failpoint.Inject("FailBeforeIndexEngineImported", func() { - panic("forcing failure due to FailBeforeIndexEngineImported") - }) - saveCpErr := rc.saveStatusCheckpoint(ctx, tr.tableName, checkpoints.WholeTableEngineID, err, checkpoints.CheckpointStatusIndexImported) if err = firstErr(err, saveCpErr); err != nil { return errors.Trace(err) @@ -462,6 +451,11 @@ func (tr *TableRestore) restoreEngine( } }() + setError := func(err error) { + chunkErr.Set(err) + cancel() + } + // Restore table data for chunkIndex, chunk := range cp.Chunks { if chunk.Chunk.Offset >= chunk.Chunk.EndOffset { @@ -500,7 +494,8 @@ func (tr *TableRestore) restoreEngine( // 4. flush kvs data (into tikv node) cr, err := newChunkRestore(ctx, chunkIndex, rc.cfg, chunk, rc.ioWorkers, rc.store, tr.tableInfo) if err != nil { - return nil, errors.Trace(err) + setError(err) + break } var remainChunkCnt float64 if chunk.Chunk.Offset < chunk.Chunk.EndOffset { @@ -508,19 +503,23 @@ func (tr *TableRestore) restoreEngine( metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending).Add(remainChunkCnt) } - restoreWorker := rc.regionWorkers.Apply() - wg.Add(1) - dataWriter, err := dataEngine.LocalWriter(ctx, dataWriterCfg) if err != nil { - return nil, errors.Trace(err) + cr.close() + setError(err) + break } indexWriter, err := indexEngine.LocalWriter(ctx, &backend.LocalWriterConfig{}) if err != nil { - return nil, errors.Trace(err) + _, _ = dataWriter.Close(ctx) + cr.close() + setError(err) + break } + restoreWorker := rc.regionWorkers.Apply() + wg.Add(1) go func(w *worker.Worker, cr *chunkRestore) { // Restore a chunk. defer func() { @@ -555,8 +554,7 @@ func (tr *TableRestore) restoreEngine( } } else { metric.ChunkCounter.WithLabelValues(metric.ChunkStateFailed).Add(remainChunkCnt) - chunkErr.Set(err) - cancel() + setError(err) } }(restoreWorker, cr) } @@ -675,10 +673,7 @@ func (tr *TableRestore) postProcess( forcePostProcess bool, metaMgr tableMetaMgr, ) (bool, error) { - // there are no data in this table, no need to do post process - // this is important for tables that are just the dump table of views - // because at this stage, the table was already deleted and replaced by the related view - if !rc.backend.ShouldPostProcess() || len(cp.Engines) == 1 { + if !rc.backend.ShouldPostProcess() { return false, nil } @@ -702,8 +697,8 @@ func (tr *TableRestore) postProcess( } // tidb backend don't need checksum & analyze - if !rc.backend.ShouldPostProcess() { - tr.logger.Debug("skip checksum & analyze, not supported by this backend") + if rc.cfg.PostRestore.Checksum == config.OpLevelOff && rc.cfg.PostRestore.Analyze == config.OpLevelOff { + tr.logger.Debug("skip checksum & analyze, either because not supported by this backend or manually disabled") err := rc.saveStatusCheckpoint(ctx, tr.tableName, checkpoints.WholeTableEngineID, nil, checkpoints.CheckpointStatusAnalyzeSkipped) return false, errors.Trace(err) } @@ -803,7 +798,7 @@ func (tr *TableRestore) postProcess( } // Don't call FinishTable when other lightning will calculate checksum. - if err == nil && !hasDupe && needChecksum { + if err == nil && needChecksum { err = metaMgr.FinishTable(ctx) } @@ -869,7 +864,7 @@ func parseColumnPermutations(tableInfo *model.TableInfo, columns []string, ignor } if len(unknownCols) > 0 { - return colPerm, errors.Errorf("unknown columns in header %s", unknownCols) + return colPerm, common.ErrUnknownColumns.GenWithStackByArgs(strings.Join(unknownCols, ","), tableInfo.Name) } for _, colInfo := range tableInfo.Columns { @@ -919,12 +914,14 @@ func (tr *TableRestore) importKV( regionSplitSize := int64(rc.cfg.TikvImporter.RegionSplitSize) if regionSplitSize == 0 && rc.taskMgr != nil { regionSplitSize = int64(config.SplitRegionSize) - rc.taskMgr.CheckTasksExclusively(ctx, func(tasks []taskMeta) ([]taskMeta, error) { + if err := rc.taskMgr.CheckTasksExclusively(ctx, func(tasks []taskMeta) ([]taskMeta, error) { if len(tasks) > 0 { regionSplitSize = int64(config.SplitRegionSize) * int64(utils.MinInt(len(tasks), config.MaxSplitRegionSizeRatio)) } return nil, nil - }) + }); err != nil { + return errors.Trace(err) + } } err := closedEngine.Import(ctx, regionSplitSize) saveCpErr := rc.saveStatusCheckpoint(ctx, tr.tableName, engineID, err, checkpoints.CheckpointStatusImported) @@ -952,7 +949,7 @@ func (tr *TableRestore) compareChecksum(remoteChecksum *RemoteChecksum, localChe if remoteChecksum.Checksum != localChecksum.Sum() || remoteChecksum.TotalKVs != localChecksum.SumKVS() || remoteChecksum.TotalBytes != localChecksum.SumSize() { - return errors.Errorf("checksum mismatched remote vs local => (checksum: %d vs %d) (total_kvs: %d vs %d) (total_bytes:%d vs %d)", + return common.ErrChecksumMismatch.GenWithStackByArgs( remoteChecksum.Checksum, localChecksum.Sum(), remoteChecksum.TotalKVs, localChecksum.SumKVS(), remoteChecksum.TotalBytes, localChecksum.SumSize(), @@ -998,8 +995,8 @@ func estimateCompactionThreshold(cp *checkpoints.TableCheckpoint, factor int64) threshold := totalRawFileSize / 512 threshold = utils.NextPowerOfTwo(threshold) if threshold < compactionLowerThreshold { - // disable compaction if threshold is smaller than lower bound - threshold = 0 + // too may small SST files will cause inaccuracy of region range estimation, + threshold = compactionLowerThreshold } else if threshold > compactionUpperThreshold { threshold = compactionUpperThreshold } diff --git a/br/pkg/lightning/restore/table_restore_test.go b/br/pkg/lightning/restore/table_restore_test.go new file mode 100644 index 0000000000000..77ae288ab3e30 --- /dev/null +++ b/br/pkg/lightning/restore/table_restore_test.go @@ -0,0 +1,1863 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package restore + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + "unicode/utf8" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/docker/go-units" + "github.com/golang/mock/gomock" + "github.com/google/uuid" + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/kvproto/pkg/metapb" + "github.com/pingcap/tidb/br/pkg/lightning/backend" + "github.com/pingcap/tidb/br/pkg/lightning/backend/kv" + "github.com/pingcap/tidb/br/pkg/lightning/backend/noop" + "github.com/pingcap/tidb/br/pkg/lightning/backend/tidb" + "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" + "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/pingcap/tidb/br/pkg/lightning/config" + "github.com/pingcap/tidb/br/pkg/lightning/errormanager" + "github.com/pingcap/tidb/br/pkg/lightning/glue" + "github.com/pingcap/tidb/br/pkg/lightning/log" + "github.com/pingcap/tidb/br/pkg/lightning/metric" + "github.com/pingcap/tidb/br/pkg/lightning/mydump" + "github.com/pingcap/tidb/br/pkg/lightning/verification" + "github.com/pingcap/tidb/br/pkg/lightning/web" + "github.com/pingcap/tidb/br/pkg/lightning/worker" + "github.com/pingcap/tidb/br/pkg/mock" + "github.com/pingcap/tidb/br/pkg/storage" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/store/pdtypes" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/types" + tmock "github.com/pingcap/tidb/util/mock" + filter "github.com/pingcap/tidb/util/table-filter" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type tableRestoreSuiteBase struct { + tr *TableRestore + cfg *config.Config + + tableInfo *checkpoints.TidbTableInfo + dbInfo *checkpoints.TidbDBInfo + tableMeta *mydump.MDTableMeta + + store storage.ExternalStorage +} + +func (s *tableRestoreSuiteBase) setupSuite(t *testing.T) { + web.EnableCurrentProgress() + // Produce a mock table info + + p := parser.New() + p.SetSQLMode(mysql.ModeANSIQuotes) + se := tmock.NewContext() + node, err := p.ParseOneStmt(` + CREATE TABLE "table" ( + a INT, + b INT, + c INT, + KEY (b) + ) +`, "", "") + require.NoError(t, err) + core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) + require.NoError(t, err) + core.State = model.StatePublic + + s.tableInfo = &checkpoints.TidbTableInfo{Name: "table", DB: "db", Core: core} + s.dbInfo = &checkpoints.TidbDBInfo{ + Name: "db", + Tables: map[string]*checkpoints.TidbTableInfo{"table": s.tableInfo}, + } + + // Write some sample SQL dump + + fakeDataDir := t.TempDir() + store, err := storage.NewLocalStorage(fakeDataDir) + require.NoError(t, err) + s.store = store + + fakeDataFilesCount := 6 + fakeDataFilesContent := []byte("INSERT INTO `table` VALUES (1, 2, 3);") + require.Equal(t, 37, len(fakeDataFilesContent)) + fakeDataFiles := make([]mydump.FileInfo, 0, fakeDataFilesCount) + for i := 1; i <= fakeDataFilesCount; i++ { + fakeFileName := fmt.Sprintf("db.table.%d.sql", i) + fakeDataPath := filepath.Join(fakeDataDir, fakeFileName) + err = os.WriteFile(fakeDataPath, fakeDataFilesContent, 0o644) + require.NoError(t, err) + fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ + TableName: filter.Table{Schema: "db", Name: "table"}, + FileMeta: mydump.SourceFileMeta{ + Path: fakeFileName, + Type: mydump.SourceTypeSQL, + SortKey: strconv.Itoa(i), + FileSize: 37, + }, + }) + } + + fakeCsvContent := []byte("1,2,3\r\n4,5,6\r\n") + csvName := "db.table.99.csv" + err = os.WriteFile(filepath.Join(fakeDataDir, csvName), fakeCsvContent, 0o644) + require.NoError(t, err) + fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ + TableName: filter.Table{Schema: "db", Name: "table"}, + FileMeta: mydump.SourceFileMeta{ + Path: csvName, + Type: mydump.SourceTypeCSV, + SortKey: "99", + FileSize: 14, + }, + }) + + s.tableMeta = &mydump.MDTableMeta{ + DB: "db", + Name: "table", + TotalSize: 222, + SchemaFile: mydump.FileInfo{ + TableName: filter.Table{Schema: "db", Name: "table"}, + FileMeta: mydump.SourceFileMeta{ + Path: "db.table-schema.sql", + Type: mydump.SourceTypeTableSchema, + }, + }, + DataFiles: fakeDataFiles, + } +} + +func (s *tableRestoreSuiteBase) setupTest(t *testing.T) { + // Collect into the test TableRestore structure + var err error + s.tr, err = NewTableRestore("`db`.`table`", s.tableMeta, s.dbInfo, s.tableInfo, &checkpoints.TableCheckpoint{}, nil) + require.NoError(t, err) + + s.cfg = config.NewConfig() + s.cfg.Mydumper.BatchSize = 111 + s.cfg.App.TableConcurrency = 2 +} + +type tableRestoreSuite struct { + suite.Suite + tableRestoreSuiteBase +} + +func TestTableRestoreSuite(t *testing.T) { + suite.Run(t, new(tableRestoreSuite)) +} + +func (s *tableRestoreSuite) SetupSuite() { + s.setupSuite(s.T()) +} + +func (s *tableRestoreSuite) SetupTest() { + s.setupTest(s.T()) +} + +func (s *tableRestoreSuite) TestPopulateChunks() { + _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp", "return(1234567897)") + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp") + }() + + cp := &checkpoints.TableCheckpoint{ + Engines: make(map[int32]*checkpoints.EngineCheckpoint), + } + + rc := &Controller{cfg: s.cfg, ioWorkers: worker.NewPool(context.Background(), 1, "io"), store: s.store} + err := s.tr.populateChunks(context.Background(), rc, cp) + require.NoError(s.T(), err) + //nolint:dupl // false positive. + require.Equal(s.T(), map[int32]*checkpoints.EngineCheckpoint{ + -1: { + Status: checkpoints.CheckpointStatusLoaded, + }, + 0: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[0].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[0].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 0, + RowIDMax: 7, // 37 bytes with 3 columns can store at most 7 rows. + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[1].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 7, + RowIDMax: 14, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[2].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[2].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 14, + RowIDMax: 21, + }, + Timestamp: 1234567897, + }, + }, + }, + 1: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[3].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[3].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 21, + RowIDMax: 28, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[4].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[4].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 28, + RowIDMax: 35, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[5].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[5].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 37, + PrevRowIDMax: 35, + RowIDMax: 42, + }, + Timestamp: 1234567897, + }, + }, + }, + 2: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: s.tr.tableMeta.DataFiles[6].FileMeta.Path, Offset: 0}, + FileMeta: s.tr.tableMeta.DataFiles[6].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 14, + PrevRowIDMax: 42, + RowIDMax: 46, + }, + Timestamp: 1234567897, + }, + }, + }, + }, cp.Engines) + + // set csv header to true, this will cause check columns fail + s.cfg.Mydumper.CSV.Header = true + s.cfg.Mydumper.StrictFormat = true + regionSize := s.cfg.Mydumper.MaxRegionSize + s.cfg.Mydumper.MaxRegionSize = 5 + err = s.tr.populateChunks(context.Background(), rc, cp) + require.Error(s.T(), err) + require.Regexp(s.T(), `.*unknown columns in header \(1,2,3\)`, err.Error()) + s.cfg.Mydumper.MaxRegionSize = regionSize + s.cfg.Mydumper.CSV.Header = false +} + +type errorLocalWriter struct{} + +func (w errorLocalWriter) AppendRows(context.Context, string, []string, kv.Rows) error { + return errors.New("mock write rows failed") +} + +func (w errorLocalWriter) IsSynced() bool { + return true +} + +func (w errorLocalWriter) Close(context.Context) (backend.ChunkFlushStatus, error) { + return nil, nil +} + +func (s *tableRestoreSuite) TestRestoreEngineFailed() { + ctx := context.Background() + ctrl := gomock.NewController(s.T()) + mockBackend := mock.NewMockBackend(ctrl) + rc := &Controller{ + cfg: s.cfg, + pauser: DeliverPauser, + ioWorkers: worker.NewPool(ctx, 1, "io"), + regionWorkers: worker.NewPool(ctx, 10, "region"), + store: s.store, + backend: backend.MakeBackend(mockBackend), + errorSummaries: makeErrorSummaries(log.L()), + saveCpCh: make(chan saveCp, 1), + diskQuotaLock: newDiskQuotaLock(), + } + defer close(rc.saveCpCh) + go func() { + for cp := range rc.saveCpCh { + cp.waitCh <- nil + } + }() + + cp := &checkpoints.TableCheckpoint{ + Engines: make(map[int32]*checkpoints.EngineCheckpoint), + } + err := s.tr.populateChunks(ctx, rc, cp) + require.NoError(s.T(), err) + + tbl, err := tables.TableFromMeta(kv.NewPanickingAllocators(0), s.tableInfo.Core) + require.NoError(s.T(), err) + _, indexUUID := backend.MakeUUID("`db`.`table`", -1) + _, dataUUID := backend.MakeUUID("`db`.`table`", 0) + realBackend := tidb.NewTiDBBackend(nil, "replace", nil) + mockBackend.EXPECT().OpenEngine(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBackend.EXPECT().OpenEngine(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBackend.EXPECT().CloseEngine(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockBackend.EXPECT().NewEncoder(gomock.Any(), gomock.Any()). + Return(realBackend.NewEncoder(tbl, &kv.SessionOptions{})). + AnyTimes() + mockBackend.EXPECT().MakeEmptyRows().Return(realBackend.MakeEmptyRows()).AnyTimes() + mockBackend.EXPECT().LocalWriter(gomock.Any(), gomock.Any(), dataUUID).Return(noop.Writer{}, nil) + mockBackend.EXPECT().LocalWriter(gomock.Any(), gomock.Any(), indexUUID). + Return(nil, errors.New("mock open index local writer failed")) + openedIdxEngine, err := rc.backend.OpenEngine(ctx, nil, "`db`.`table`", -1) + require.NoError(s.T(), err) + + // open the first engine meet error, should directly return the error + _, err = s.tr.restoreEngine(ctx, rc, openedIdxEngine, 0, cp.Engines[0]) + require.Equal(s.T(), "mock open index local writer failed", err.Error()) + + localWriter := func(ctx context.Context, cfg *backend.LocalWriterConfig, engineUUID uuid.UUID) (backend.EngineWriter, error) { + time.Sleep(20 * time.Millisecond) + select { + case <-ctx.Done(): + return nil, errors.New("mock open index local writer failed after ctx.Done") + default: + return noop.Writer{}, nil + } + } + mockBackend.EXPECT().OpenEngine(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBackend.EXPECT().OpenEngine(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mockBackend.EXPECT().LocalWriter(gomock.Any(), gomock.Any(), dataUUID).Return(errorLocalWriter{}, nil).AnyTimes() + mockBackend.EXPECT().LocalWriter(gomock.Any(), gomock.Any(), indexUUID). + DoAndReturn(localWriter).AnyTimes() + + openedIdxEngine, err = rc.backend.OpenEngine(ctx, nil, "`db`.`table`", -1) + require.NoError(s.T(), err) + + // open engine failed after write rows failed, should return write rows error + _, err = s.tr.restoreEngine(ctx, rc, openedIdxEngine, 0, cp.Engines[0]) + require.Equal(s.T(), "mock write rows failed", err.Error()) +} + +func (s *tableRestoreSuite) TestPopulateChunksCSVHeader() { + fakeDataDir := s.T().TempDir() + + store, err := storage.NewLocalStorage(fakeDataDir) + require.NoError(s.T(), err) + + fakeDataFiles := make([]mydump.FileInfo, 0) + + fakeCsvContents := []string{ + // small full header + "a,b,c\r\n1,2,3\r\n", + // small partial header + "b,c\r\n2,3\r\n", + // big full header + "a,b,c\r\n90000,80000,700000\r\n1000,2000,3000\r\n11,22,33\r\n3,4,5\r\n", + // big full header unordered + "c,a,b\r\n,1000,2000,3000\r\n11,22,33\r\n1000,2000,404\r\n3,4,5\r\n90000,80000,700000\r\n7999999,89999999,9999999\r\n", + // big partial header + "b,c\r\n2000001,30000001\r\n35231616,462424626\r\n62432,434898934\r\n", + } + total := 0 + for i, str := range fakeCsvContents { + csvName := fmt.Sprintf("db.table.%02d.csv", i) + err := os.WriteFile(filepath.Join(fakeDataDir, csvName), []byte(str), 0o644) + require.NoError(s.T(), err) + fakeDataFiles = append(fakeDataFiles, mydump.FileInfo{ + TableName: filter.Table{Schema: "db", Name: "table"}, + FileMeta: mydump.SourceFileMeta{Path: csvName, Type: mydump.SourceTypeCSV, SortKey: fmt.Sprintf("%02d", i), FileSize: int64(len(str))}, + }) + total += len(str) + } + tableMeta := &mydump.MDTableMeta{ + DB: "db", + Name: "table", + TotalSize: int64(total), + SchemaFile: mydump.FileInfo{TableName: filter.Table{Schema: "db", Name: "table"}, FileMeta: mydump.SourceFileMeta{Path: "db.table-schema.sql", Type: mydump.SourceTypeTableSchema}}, + DataFiles: fakeDataFiles, + } + + _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp", "return(1234567897)") + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/PopulateChunkTimestamp") + }() + + cp := &checkpoints.TableCheckpoint{ + Engines: make(map[int32]*checkpoints.EngineCheckpoint), + } + + cfg := config.NewConfig() + cfg.Mydumper.BatchSize = 100 + cfg.Mydumper.MaxRegionSize = 40 + + cfg.Mydumper.CSV.Header = true + cfg.Mydumper.StrictFormat = true + rc := &Controller{cfg: cfg, ioWorkers: worker.NewPool(context.Background(), 1, "io"), store: store} + + tr, err := NewTableRestore("`db`.`table`", tableMeta, s.dbInfo, s.tableInfo, &checkpoints.TableCheckpoint{}, nil) + require.NoError(s.T(), err) + require.NoError(s.T(), tr.populateChunks(context.Background(), rc, cp)) + + require.Equal(s.T(), map[int32]*checkpoints.EngineCheckpoint{ + -1: { + Status: checkpoints.CheckpointStatusLoaded, + }, + 0: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[0].FileMeta.Path, Offset: 0}, + FileMeta: tableMeta.DataFiles[0].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 14, + PrevRowIDMax: 0, + RowIDMax: 4, // 37 bytes with 3 columns can store at most 7 rows. + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[1].FileMeta.Path, Offset: 0}, + FileMeta: tableMeta.DataFiles[1].FileMeta, + Chunk: mydump.Chunk{ + Offset: 0, + EndOffset: 10, + PrevRowIDMax: 4, + RowIDMax: 7, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[2].FileMeta.Path, Offset: 6}, + FileMeta: tableMeta.DataFiles[2].FileMeta, + ColumnPermutation: []int{0, 1, 2, -1}, + Chunk: mydump.Chunk{ + Offset: 6, + EndOffset: 52, + PrevRowIDMax: 7, + RowIDMax: 20, + Columns: []string{"a", "b", "c"}, + }, + + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[2].FileMeta.Path, Offset: 52}, + FileMeta: tableMeta.DataFiles[2].FileMeta, + ColumnPermutation: []int{0, 1, 2, -1}, + Chunk: mydump.Chunk{ + Offset: 52, + EndOffset: 60, + PrevRowIDMax: 20, + RowIDMax: 22, + Columns: []string{"a", "b", "c"}, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 6}, + FileMeta: tableMeta.DataFiles[3].FileMeta, + ColumnPermutation: []int{1, 2, 0, -1}, + Chunk: mydump.Chunk{ + Offset: 6, + EndOffset: 48, + PrevRowIDMax: 22, + RowIDMax: 35, + Columns: []string{"c", "a", "b"}, + }, + Timestamp: 1234567897, + }, + }, + }, + 1: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 48}, + FileMeta: tableMeta.DataFiles[3].FileMeta, + ColumnPermutation: []int{1, 2, 0, -1}, + Chunk: mydump.Chunk{ + Offset: 48, + EndOffset: 101, + PrevRowIDMax: 35, + RowIDMax: 48, + Columns: []string{"c", "a", "b"}, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[3].FileMeta.Path, Offset: 101}, + FileMeta: tableMeta.DataFiles[3].FileMeta, + ColumnPermutation: []int{1, 2, 0, -1}, + Chunk: mydump.Chunk{ + Offset: 101, + EndOffset: 102, + PrevRowIDMax: 48, + RowIDMax: 48, + Columns: []string{"c", "a", "b"}, + }, + Timestamp: 1234567897, + }, + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[4].FileMeta.Path, Offset: 4}, + FileMeta: tableMeta.DataFiles[4].FileMeta, + ColumnPermutation: []int{-1, 0, 1, -1}, + Chunk: mydump.Chunk{ + Offset: 4, + EndOffset: 59, + PrevRowIDMax: 48, + RowIDMax: 61, + Columns: []string{"b", "c"}, + }, + Timestamp: 1234567897, + }, + }, + }, + 2: { + Status: checkpoints.CheckpointStatusLoaded, + Chunks: []*checkpoints.ChunkCheckpoint{ + { + Key: checkpoints.ChunkCheckpointKey{Path: tableMeta.DataFiles[4].FileMeta.Path, Offset: 59}, + FileMeta: tableMeta.DataFiles[4].FileMeta, + ColumnPermutation: []int{-1, 0, 1, -1}, + Chunk: mydump.Chunk{ + Offset: 59, + EndOffset: 60, + PrevRowIDMax: 61, + RowIDMax: 61, + Columns: []string{"b", "c"}, + }, + Timestamp: 1234567897, + }, + }, + }, + }, cp.Engines) +} + +func (s *tableRestoreSuite) TestGetColumnsNames() { + require.Equal(s.T(), []string{"a", "b", "c"}, getColumnNames(s.tableInfo.Core, []int{0, 1, 2, -1})) + require.Equal(s.T(), []string{"b", "a", "c"}, getColumnNames(s.tableInfo.Core, []int{1, 0, 2, -1})) + require.Equal(s.T(), []string{"b", "c"}, getColumnNames(s.tableInfo.Core, []int{-1, 0, 1, -1})) + require.Equal(s.T(), []string{"a", "b"}, getColumnNames(s.tableInfo.Core, []int{0, 1, -1, -1})) + require.Equal(s.T(), []string{"c", "a"}, getColumnNames(s.tableInfo.Core, []int{1, -1, 0, -1})) + require.Equal(s.T(), []string{"b"}, getColumnNames(s.tableInfo.Core, []int{-1, 0, -1, -1})) + require.Equal(s.T(), []string{"_tidb_rowid", "a", "b", "c"}, getColumnNames(s.tableInfo.Core, []int{1, 2, 3, 0})) + require.Equal(s.T(), []string{"b", "a", "c", "_tidb_rowid"}, getColumnNames(s.tableInfo.Core, []int{1, 0, 2, 3})) + require.Equal(s.T(), []string{"b", "_tidb_rowid", "c"}, getColumnNames(s.tableInfo.Core, []int{-1, 0, 2, 1})) + require.Equal(s.T(), []string{"c", "_tidb_rowid", "a"}, getColumnNames(s.tableInfo.Core, []int{2, -1, 0, 1})) + require.Equal(s.T(), []string{"_tidb_rowid", "b"}, getColumnNames(s.tableInfo.Core, []int{-1, 1, -1, 0})) +} + +func (s *tableRestoreSuite) TestInitializeColumns() { + ccp := &checkpoints.ChunkCheckpoint{} + + defer func() { + s.tr.ignoreColumns = nil + }() + + cases := []struct { + columns []string + ignoreColumns map[string]struct{} + expectedPermutation []int + errPat string + }{ + { + nil, + nil, + []int{0, 1, 2, -1}, + "", + }, + { + nil, + map[string]struct{}{"b": {}}, + []int{0, -1, 2, -1}, + "", + }, + { + []string{"b", "c", "a"}, + nil, + []int{2, 0, 1, -1}, + "", + }, + { + []string{"b", "c", "a"}, + map[string]struct{}{"b": {}}, + []int{2, -1, 1, -1}, + "", + }, + { + []string{"b"}, + nil, + []int{-1, 0, -1, -1}, + "", + }, + { + []string{"_tidb_rowid", "b", "a", "c"}, + nil, + []int{2, 1, 3, 0}, + "", + }, + { + []string{"_tidb_rowid", "b", "a", "c"}, + map[string]struct{}{"b": {}, "_tidb_rowid": {}}, + []int{2, -1, 3, -1}, + "", + }, + { + []string{"_tidb_rowid", "b", "a", "c", "d"}, + nil, + nil, + `\[Lightning:Restore:ErrUnknownColumns\]unknown columns in header \(d\) for table table`, + }, + { + []string{"e", "b", "c", "d"}, + nil, + nil, + `\[Lightning:Restore:ErrUnknownColumns\]unknown columns in header \(e,d\) for table table`, + }, + } + + for _, testCase := range cases { + ccp.ColumnPermutation = nil + s.tr.ignoreColumns = testCase.ignoreColumns + err := s.tr.initializeColumns(testCase.columns, ccp) + if len(testCase.errPat) > 0 { + require.Error(s.T(), err) + require.Regexp(s.T(), testCase.errPat, err.Error()) + } else { + require.Equal(s.T(), testCase.expectedPermutation, ccp.ColumnPermutation) + } + } +} +func (s *tableRestoreSuite) TestInitializeColumnsGenerated() { + p := parser.New() + p.SetSQLMode(mysql.ModeANSIQuotes) + se := tmock.NewContext() + + cases := []struct { + schema string + columns []string + expectedPermutation []int + }{ + { + "CREATE TABLE `table` (a INT, b INT, C INT, d INT AS (a * 2))", + []string{"b", "c", "a"}, + []int{2, 0, 1, -1, -1}, + }, + // all generated columns and none input columns + { + "CREATE TABLE `table` (a bigint as (1 + 2) stored, b text as (sha1(repeat('x', a))) stored)", + []string{}, + []int{-1, -1, -1}, + }, + } + + for _, testCase := range cases { + node, err := p.ParseOneStmt(testCase.schema, "", "") + require.NoError(s.T(), err) + core, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 0xabcdef) + require.NoError(s.T(), err) + core.State = model.StatePublic + tableInfo := &checkpoints.TidbTableInfo{Name: "table", DB: "db", Core: core} + s.tr, err = NewTableRestore("`db`.`table`", s.tableMeta, s.dbInfo, tableInfo, &checkpoints.TableCheckpoint{}, nil) + require.NoError(s.T(), err) + ccp := &checkpoints.ChunkCheckpoint{} + + err = s.tr.initializeColumns(testCase.columns, ccp) + require.NoError(s.T(), err) + require.Equal(s.T(), testCase.expectedPermutation, ccp.ColumnPermutation) + } +} + +func (s *tableRestoreSuite) TestCompareChecksumSuccess() { + db, mock, err := sqlmock.New() + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), db.Close()) + require.NoError(s.T(), mock.ExpectationsWereMet()) + }() + + mock.ExpectQuery("SELECT.*tikv_gc_life_time.*"). + WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) + mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). + WithArgs("100h0m0s"). + WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectQuery("ADMIN CHECKSUM.*"). + WillReturnRows( + sqlmock.NewRows([]string{"Db_name", "Table_name", "Checksum_crc64_xor", "Total_kvs", "Total_bytes"}). + AddRow("db", "table", 1234567890, 12345, 1234567), + ) + mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). + WithArgs("10m"). + WillReturnResult(sqlmock.NewResult(2, 1)) + mock.ExpectClose() + + ctx := MockDoChecksumCtx(db) + remoteChecksum, err := DoChecksum(ctx, s.tr.tableInfo) + require.NoError(s.T(), err) + err = s.tr.compareChecksum(remoteChecksum, verification.MakeKVChecksum(1234567, 12345, 1234567890)) + require.NoError(s.T(), err) +} + +func (s *tableRestoreSuite) TestCompareChecksumFailure() { + db, mock, err := sqlmock.New() + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), db.Close()) + require.NoError(s.T(), mock.ExpectationsWereMet()) + }() + + mock.ExpectQuery("SELECT.*tikv_gc_life_time.*"). + WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m")) + mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). + WithArgs("100h0m0s"). + WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectQuery("ADMIN CHECKSUM TABLE `db`\\.`table`"). + WillReturnRows( + sqlmock.NewRows([]string{"Db_name", "Table_name", "Checksum_crc64_xor", "Total_kvs", "Total_bytes"}). + AddRow("db", "table", 1234567890, 12345, 1234567), + ) + mock.ExpectExec("UPDATE.*tikv_gc_life_time.*"). + WithArgs("10m"). + WillReturnResult(sqlmock.NewResult(2, 1)) + mock.ExpectClose() + + ctx := MockDoChecksumCtx(db) + remoteChecksum, err := DoChecksum(ctx, s.tr.tableInfo) + require.NoError(s.T(), err) + err = s.tr.compareChecksum(remoteChecksum, verification.MakeKVChecksum(9876543, 54321, 1357924680)) + require.Regexp(s.T(), "checksum mismatched.*", err.Error()) +} + +func (s *tableRestoreSuite) TestAnalyzeTable() { + db, mock, err := sqlmock.New() + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), db.Close()) + require.NoError(s.T(), mock.ExpectationsWereMet()) + }() + + mock.ExpectExec("ANALYZE TABLE `db`\\.`table`"). + WillReturnResult(sqlmock.NewResult(1, 1)) + mock.ExpectClose() + + ctx := context.Background() + defaultSQLMode, err := mysql.GetSQLMode(mysql.DefaultSQLMode) + require.NoError(s.T(), err) + g := glue.NewExternalTiDBGlue(db, defaultSQLMode) + err = s.tr.analyzeTable(ctx, g) + require.NoError(s.T(), err) +} + +func (s *tableRestoreSuite) TestImportKVSuccess() { + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + importer := backend.MakeBackend(mockBackend) + chptCh := make(chan saveCp) + defer close(chptCh) + rc := &Controller{saveCpCh: chptCh, cfg: config.NewConfig()} + go func() { + for scp := range chptCh { + if scp.waitCh != nil { + scp.waitCh <- nil + } + } + }() + + ctx := context.Background() + engineUUID := uuid.New() + + mockBackend.EXPECT(). + CloseEngine(ctx, nil, engineUUID). + Return(nil) + mockBackend.EXPECT(). + ImportEngine(ctx, engineUUID, gomock.Any()). + Return(nil) + mockBackend.EXPECT(). + CleanupEngine(ctx, engineUUID). + Return(nil) + + closedEngine, err := importer.UnsafeCloseEngineWithUUID(ctx, nil, "tag", engineUUID) + require.NoError(s.T(), err) + err = s.tr.importKV(ctx, closedEngine, rc, 1) + require.NoError(s.T(), err) +} + +func (s *tableRestoreSuite) TestImportKVFailure() { + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + importer := backend.MakeBackend(mockBackend) + chptCh := make(chan saveCp) + defer close(chptCh) + rc := &Controller{saveCpCh: chptCh, cfg: config.NewConfig()} + go func() { + for scp := range chptCh { + if scp.waitCh != nil { + scp.waitCh <- nil + } + } + }() + + ctx := context.Background() + engineUUID := uuid.New() + + mockBackend.EXPECT(). + CloseEngine(ctx, nil, engineUUID). + Return(nil) + mockBackend.EXPECT(). + ImportEngine(ctx, engineUUID, gomock.Any()). + Return(errors.Annotate(context.Canceled, "fake import error")) + + closedEngine, err := importer.UnsafeCloseEngineWithUUID(ctx, nil, "tag", engineUUID) + require.NoError(s.T(), err) + err = s.tr.importKV(ctx, closedEngine, rc, 1) + require.Regexp(s.T(), "fake import error.*", err.Error()) +} + +func (s *tableRestoreSuite) TestTableRestoreMetrics() { + controller := gomock.NewController(s.T()) + defer controller.Finish() + + chunkPendingBase := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) + chunkFinishedBase := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) + engineFinishedBase := metric.ReadCounter(metric.ProcessedEngineCounter.WithLabelValues("imported", metric.TableResultSuccess)) + tableFinishedBase := metric.ReadCounter(metric.TableCounter.WithLabelValues("index_imported", metric.TableResultSuccess)) + + ctx := context.Background() + chptCh := make(chan saveCp) + defer close(chptCh) + cfg := config.NewConfig() + cfg.Mydumper.BatchSize = 1 + cfg.PostRestore.Checksum = config.OpLevelOff + + cfg.Checkpoint.Enable = false + cfg.TiDB.Host = "127.0.0.1" + cfg.TiDB.StatusPort = 10080 + cfg.TiDB.Port = 4000 + cfg.TiDB.PdAddr = "127.0.0.1:2379" + + cfg.Mydumper.SourceDir = "." + cfg.Mydumper.CSV.Header = false + cfg.TikvImporter.Backend = config.BackendImporter + tls, err := cfg.ToTLS() + require.NoError(s.T(), err) + + err = cfg.Adjust(ctx) + require.NoError(s.T(), err) + + cpDB := checkpoints.NewNullCheckpointsDB() + g := mock.NewMockGlue(controller) + rc := &Controller{ + cfg: cfg, + dbMetas: []*mydump.MDDatabaseMeta{ + { + Name: s.tableInfo.DB, + Tables: []*mydump.MDTableMeta{s.tableMeta}, + }, + }, + dbInfos: map[string]*checkpoints.TidbDBInfo{ + s.tableInfo.DB: s.dbInfo, + }, + tableWorkers: worker.NewPool(ctx, 6, "table"), + ioWorkers: worker.NewPool(ctx, 5, "io"), + indexWorkers: worker.NewPool(ctx, 2, "index"), + regionWorkers: worker.NewPool(ctx, 10, "region"), + checksumWorks: worker.NewPool(ctx, 2, "region"), + saveCpCh: chptCh, + pauser: DeliverPauser, + backend: noop.NewNoopBackend(), + tidbGlue: g, + errorSummaries: makeErrorSummaries(log.L()), + tls: tls, + checkpointsDB: cpDB, + closedEngineLimit: worker.NewPool(ctx, 1, "closed_engine"), + store: s.store, + metaMgrBuilder: noopMetaMgrBuilder{}, + diskQuotaLock: newDiskQuotaLock(), + errorMgr: errormanager.New(nil, cfg), + } + go func() { + for scp := range chptCh { + if scp.waitCh != nil { + scp.waitCh <- nil + } + } + }() + db, sqlMock, err := sqlmock.New() + require.NoError(s.T(), err) + g.EXPECT().GetDB().Return(db, nil).AnyTimes() + sqlMock.ExpectQuery("SELECT tidb_version\\(\\);").WillReturnRows(sqlmock.NewRows([]string{"tidb_version()"}). + AddRow("Release Version: v5.2.1\nEdition: Community\n")) + + web.BroadcastInitProgress(rc.dbMetas) + + err = rc.restoreTables(ctx) + require.NoError(s.T(), err) + + chunkPending := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) + chunkFinished := metric.ReadCounter(metric.ChunkCounter.WithLabelValues(metric.ChunkStatePending)) + require.Equal(s.T(), float64(7), chunkPending-chunkPendingBase) + require.Equal(s.T(), chunkPending-chunkPendingBase, chunkFinished-chunkFinishedBase) + + engineFinished := metric.ReadCounter(metric.ProcessedEngineCounter.WithLabelValues("imported", metric.TableResultSuccess)) + require.Equal(s.T(), float64(8), engineFinished-engineFinishedBase) + + tableFinished := metric.ReadCounter(metric.TableCounter.WithLabelValues("index_imported", metric.TableResultSuccess)) + require.Equal(s.T(), float64(1), tableFinished-tableFinishedBase) +} + +func (s *tableRestoreSuite) TestSaveStatusCheckpoint() { + _ = failpoint.Enable("github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownCheckpointUpdate", "sleep(100)") + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownCheckpointUpdate") + }() + + web.BroadcastInitProgress([]*mydump.MDDatabaseMeta{{ + Name: "test", + Tables: []*mydump.MDTableMeta{{DB: "test", Name: "tbl"}}, + }}) + web.BroadcastTableCheckpoint(common.UniqueTable("test", "tbl"), &checkpoints.TableCheckpoint{}) + + saveCpCh := make(chan saveCp) + + rc := &Controller{ + saveCpCh: saveCpCh, + checkpointsDB: checkpoints.NewNullCheckpointsDB(), + } + rc.checkpointsWg.Add(1) + go rc.listenCheckpointUpdates() + + rc.errorSummaries = makeErrorSummaries(log.L()) + + err := rc.saveStatusCheckpoint(context.Background(), common.UniqueTable("test", "tbl"), indexEngineID, errors.New("connection refused"), checkpoints.CheckpointStatusImported) + require.NoError(s.T(), err) + require.Equal(s.T(), 0, len(rc.errorSummaries.summary)) + + err = rc.saveStatusCheckpoint( + context.Background(), + common.UniqueTable("test", "tbl"), indexEngineID, + common.ErrChecksumMismatch.GenWithStackByArgs(0, 0, 0, 0, 0, 0), + checkpoints.CheckpointStatusImported, + ) + require.NoError(s.T(), err) + require.Equal(s.T(), 1, len(rc.errorSummaries.summary)) + + start := time.Now() + err = rc.saveStatusCheckpoint(context.Background(), common.UniqueTable("test", "tbl"), indexEngineID, nil, checkpoints.CheckpointStatusImported) + require.NoError(s.T(), err) + elapsed := time.Since(start) + require.GreaterOrEqual(s.T(), elapsed, time.Millisecond*100) + + close(saveCpCh) + rc.checkpointsWg.Wait() +} + +func (s *tableRestoreSuite) TestCheckClusterResource() { + cases := []struct { + mockStoreResponse []byte + mockReplicaResponse []byte + expectMsg string + expectResult bool + expectErrorCount int + }{ + { + []byte(`{ + "count": 1, + "stores": [ + { + "store": { + "id": 2 + }, + "status": { + "available": "24" + } + } + ] + }`), + []byte(`{ + "max-replicas": 1 + }`), + "(.*)Cluster available is rich(.*)", + true, + 0, + }, + { + []byte(`{ + "count": 1, + "stores": [ + { + "store": { + "id": 2 + }, + "status": { + "available": "15" + } + } + ] + }`), + []byte(`{ + "max-replicas": 1 + }`), + "(.*)Cluster doesn't have enough space(.*)", + false, + 1, + }, + } + + ctx := context.Background() + dir := s.T().TempDir() + + file := filepath.Join(dir, "tmp") + f, err := os.Create(file) + require.NoError(s.T(), err) + buf := make([]byte, 16) + // write 16 bytes file into local storage + for i := range buf { + buf[i] = byte('A' + i) + } + _, err = f.Write(buf) + require.NoError(s.T(), err) + mockStore, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + for _, ca := range cases { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + var err error + if strings.HasSuffix(req.URL.Path, "stores") { + _, err = w.Write(ca.mockStoreResponse) + } else { + _, err = w.Write(ca.mockReplicaResponse) + } + require.NoError(s.T(), err) + })) + + tls := common.NewTLSFromMockServer(server) + template := NewSimpleTemplate() + + url := strings.TrimPrefix(server.URL, "https://") + cfg := &config.Config{TiDB: config.DBStore{PdAddr: url}} + rc := &Controller{cfg: cfg, tls: tls, store: mockStore, checkTemplate: template} + var sourceSize int64 + err = rc.store.WalkDir(ctx, &storage.WalkOption{}, func(path string, size int64) error { + sourceSize += size + return nil + }) + require.NoError(s.T(), err) + err = rc.clusterResource(ctx, sourceSize) + require.NoError(s.T(), err) + + require.Equal(s.T(), ca.expectErrorCount, template.FailedCount(Critical)) + require.Equal(s.T(), ca.expectResult, template.Success()) + require.Regexp(s.T(), ca.expectMsg, strings.ReplaceAll(template.Output(), "\n", "")) + + server.Close() + } +} + +type mockTaskMetaMgr struct { + taskMetaMgr +} + +func (mockTaskMetaMgr) CheckTasksExclusively(ctx context.Context, action func(tasks []taskMeta) ([]taskMeta, error)) error { + _, err := action([]taskMeta{{ + taskID: 1, + pdCfgs: "", + status: taskMetaStatusInitial, + state: taskStateNormal, + }}) + return err +} + +func (s *tableRestoreSuite) TestCheckClusterRegion() { + type testCase struct { + stores pdtypes.StoresInfo + emptyRegions pdtypes.RegionsInfo + expectMsgs []string + expectResult bool + expectErrorCnt int + } + + makeRegions := func(regionCnt int, storeID uint64) []pdtypes.RegionInfo { + var regions []pdtypes.RegionInfo + for i := 0; i < regionCnt; i++ { + regions = append(regions, pdtypes.RegionInfo{Peers: []pdtypes.MetaPeer{{Peer: &metapb.Peer{StoreId: storeID}}}}) + } + return regions + } + + testCases := []testCase{ + { + stores: pdtypes.StoresInfo{Stores: []*pdtypes.StoreInfo{ + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 1}}, Status: &pdtypes.StoreStatus{RegionCount: 200}}, + }}, + emptyRegions: pdtypes.RegionsInfo{ + Regions: append([]pdtypes.RegionInfo(nil), makeRegions(100, 1)...), + }, + expectMsgs: []string{".*Cluster doesn't have too many empty regions.*", ".*Cluster region distribution is balanced.*"}, + expectResult: true, + expectErrorCnt: 0, + }, + { + stores: pdtypes.StoresInfo{Stores: []*pdtypes.StoreInfo{ + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 1}}, Status: &pdtypes.StoreStatus{RegionCount: 2000}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 2}}, Status: &pdtypes.StoreStatus{RegionCount: 3100}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 3}}, Status: &pdtypes.StoreStatus{RegionCount: 2500}}, + }}, + emptyRegions: pdtypes.RegionsInfo{ + Regions: append(append(append([]pdtypes.RegionInfo(nil), + makeRegions(600, 1)...), + makeRegions(300, 2)...), + makeRegions(1200, 3)...), + }, + expectMsgs: []string{ + ".*TiKV stores \\(3\\) contains more than 1000 empty regions respectively.*", + ".*TiKV stores \\(1\\) contains more than 500 empty regions respectively.*", + ".*Region distribution is unbalanced.*but we expect it should not be less than 0.75.*", + }, + expectResult: false, + expectErrorCnt: 1, + }, + { + stores: pdtypes.StoresInfo{Stores: []*pdtypes.StoreInfo{ + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 1}}, Status: &pdtypes.StoreStatus{RegionCount: 1200}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 2}}, Status: &pdtypes.StoreStatus{RegionCount: 3000}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 3}}, Status: &pdtypes.StoreStatus{RegionCount: 2500}}, + }}, + expectMsgs: []string{".*Region distribution is unbalanced.*but we expect it must not be less than 0.5.*"}, + expectResult: false, + expectErrorCnt: 1, + }, + { + stores: pdtypes.StoresInfo{Stores: []*pdtypes.StoreInfo{ + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 1}}, Status: &pdtypes.StoreStatus{RegionCount: 0}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 2}}, Status: &pdtypes.StoreStatus{RegionCount: 2800}}, + {Store: &pdtypes.MetaStore{Store: &metapb.Store{Id: 3}}, Status: &pdtypes.StoreStatus{RegionCount: 2500}}, + }}, + expectMsgs: []string{".*Region distribution is unbalanced.*but we expect it must not be less than 0.5.*"}, + expectResult: false, + expectErrorCnt: 1, + }, + } + + mustMarshal := func(v interface{}) []byte { + data, err := json.Marshal(v) + require.NoError(s.T(), err) + return data + } + + for _, ca := range testCases { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + var err error + if req.URL.Path == pdStores { + _, err = w.Write(mustMarshal(ca.stores)) + } else if req.URL.Path == pdEmptyRegions { + _, err = w.Write(mustMarshal(ca.emptyRegions)) + } else { + w.WriteHeader(http.StatusNotFound) + } + require.NoError(s.T(), err) + })) + + tls := common.NewTLSFromMockServer(server) + template := NewSimpleTemplate() + + url := strings.TrimPrefix(server.URL, "https://") + cfg := &config.Config{TiDB: config.DBStore{PdAddr: url}} + rc := &Controller{cfg: cfg, tls: tls, taskMgr: mockTaskMetaMgr{}, checkTemplate: template} + + err := rc.checkClusterRegion(context.Background()) + require.NoError(s.T(), err) + require.Equal(s.T(), ca.expectErrorCnt, template.FailedCount(Critical)) + require.Equal(s.T(), ca.expectResult, template.Success()) + + for _, expectMsg := range ca.expectMsgs { + require.Regexp(s.T(), expectMsg, strings.ReplaceAll(template.Output(), "\n", "")) + } + + server.Close() + } +} + +func (s *tableRestoreSuite) TestCheckHasLargeCSV() { + cases := []struct { + strictFormat bool + expectMsg string + expectResult bool + expectWarnCount int + dbMetas []*mydump.MDDatabaseMeta + }{ + { + true, + "(.*)Skip the csv size check, because config.StrictFormat is true(.*)", + true, + 0, + nil, + }, + { + false, + "(.*)Source csv files size is proper(.*)", + true, + 0, + []*mydump.MDDatabaseMeta{ + { + Tables: []*mydump.MDTableMeta{ + { + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.KiB, + }, + }, + }, + }, + }, + }, + }, + }, + { + false, + "(.*)large csv: /testPath file exists(.*)", + true, + 1, + []*mydump.MDDatabaseMeta{ + { + Tables: []*mydump.MDTableMeta{ + { + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: "/testPath", + }, + }, + }, + }, + }, + }, + }, + }, + } + dir := s.T().TempDir() + + mockStore, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + + for _, ca := range cases { + template := NewSimpleTemplate() + cfg := &config.Config{Mydumper: config.MydumperRuntime{StrictFormat: ca.strictFormat}} + rc := &Controller{cfg: cfg, checkTemplate: template, store: mockStore} + rc.HasLargeCSV(ca.dbMetas) + require.Equal(s.T(), ca.expectWarnCount, template.FailedCount(Warn)) + require.Equal(s.T(), ca.expectResult, template.Success()) + require.Regexp(s.T(), ca.expectMsg, strings.ReplaceAll(template.Output(), "\n", "")) + } +} + +func (s *tableRestoreSuite) TestEstimate() { + ctx := context.Background() + controller := gomock.NewController(s.T()) + defer controller.Finish() + mockBackend := mock.NewMockBackend(controller) + idAlloc := kv.NewPanickingAllocators(0) + tbl, err := tables.TableFromMeta(idAlloc, s.tableInfo.Core) + require.NoError(s.T(), err) + + mockBackend.EXPECT().MakeEmptyRows().Return(kv.MakeRowsFromKvPairs(nil)).AnyTimes() + mockBackend.EXPECT().NewEncoder(gomock.Any(), gomock.Any()).Return(kv.NewTableKVEncoder(tbl, &kv.SessionOptions{ + SQLMode: s.cfg.TiDB.SQLMode, + Timestamp: 0, + AutoRandomSeed: 0, + })).AnyTimes() + importer := backend.MakeBackend(mockBackend) + s.cfg.TikvImporter.Backend = config.BackendLocal + + template := NewSimpleTemplate() + rc := &Controller{ + cfg: s.cfg, + checkTemplate: template, + store: s.store, + backend: importer, + dbMetas: []*mydump.MDDatabaseMeta{ + { + Name: "db1", + Tables: []*mydump.MDTableMeta{s.tableMeta}, + }, + }, + dbInfos: map[string]*checkpoints.TidbDBInfo{ + "db1": s.dbInfo, + }, + ioWorkers: worker.NewPool(context.Background(), 1, "io"), + } + source, err := rc.estimateSourceData(ctx) + // Because this file is small than region split size so we does not sample it. + require.NoError(s.T(), err) + require.Equal(s.T(), s.tableMeta.TotalSize, source) + s.tableMeta.TotalSize = int64(config.SplitRegionSize) + source, err = rc.estimateSourceData(ctx) + require.NoError(s.T(), err) + require.Greater(s.T(), source, s.tableMeta.TotalSize) + rc.cfg.TikvImporter.Backend = config.BackendTiDB + source, err = rc.estimateSourceData(ctx) + require.NoError(s.T(), err) + require.Equal(s.T(), s.tableMeta.TotalSize, source) +} + +func (s *tableRestoreSuite) TestSchemaIsValid() { + dir := s.T().TempDir() + + ctx := context.Background() + + case1File := "db1.table1.csv" + mockStore, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + err = mockStore.WriteFile(ctx, case1File, []byte(`"a"`)) + require.NoError(s.T(), err) + + case2File := "db1.table2.csv" + err = mockStore.WriteFile(ctx, case2File, []byte("\"colA\",\"colB\"\n\"a\",\"b\"")) + require.NoError(s.T(), err) + + cases := []struct { + ignoreColumns []*config.IgnoreColumns + expectMsg string + // MsgNum == 0 means the check passed. + MsgNum int + hasHeader bool + dbInfos map[string]*checkpoints.TidbDBInfo + tableMeta *mydump.MDTableMeta + }{ + // Case 1: + // csv has one column without header. + // tidb has the two columns but the second column doesn't have the default value. + // we expect the check failed. + { + nil, + "TiDB schema `db1`.`table1` has 2 columns,and data file has 1 columns, but column colb are missing(.*)", + 1, + false, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table1": { + ID: 1, + DB: "db1", + Name: "table1", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colA has the default value + Name: model.NewCIStr("colA"), + DefaultIsExpr: true, + }, + { + // colB doesn't have the default value + Name: model.NewCIStr("colB"), + FieldType: types.FieldType{ + // not null flag + Flag: 1, + }, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table1", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case1File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 2.1: + // csv has two columns(colA, colB) with the header. + // tidb only has one column(colB). + // we expect the check failed. + { + nil, + "TiDB schema `db1`.`table2` doesn't have column cola,(.*)use tables.ignoreColumns to ignore(.*)", + 1, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table2": { + ID: 1, + DB: "db1", + Name: "table2", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colB has the default value + Name: model.NewCIStr("colB"), + DefaultIsExpr: true, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table2", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 2.2: + // csv has two columns(colA, colB) with the header. + // tidb only has one column(colB). + // we ignore colA by set config tables.IgnoreColumns + // we expect the check success. + { + []*config.IgnoreColumns{ + { + DB: "db1", + Table: "table2", + Columns: []string{"cola"}, + }, + }, + "", + 0, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table2": { + ID: 1, + DB: "db1", + Name: "table2", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colB has the default value + Name: model.NewCIStr("colB"), + DefaultIsExpr: true, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table2", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 2.3: + // csv has two columns(colA, colB) with the header. + // tidb has two columns(colB, colC). + // we ignore colA by set config tables.IgnoreColumns + // colC doesn't have the default value. + // we expect the check failed. + { + []*config.IgnoreColumns{ + { + DB: "db1", + Table: "table2", + Columns: []string{"cola"}, + }, + }, + "TiDB schema `db1`.`table2` doesn't have the default value for colc(.*)", + 1, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table2": { + ID: 1, + DB: "db1", + Name: "table2", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colB has the default value + Name: model.NewCIStr("colB"), + DefaultIsExpr: true, + }, + { + // colC doesn't have the default value + Name: model.NewCIStr("colC"), + FieldType: types.FieldType{ + Flag: 1, + }, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table2", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 2.4: + // csv has two columns(colA, colB) with the header. + // tidb has two columns(colB, colC). + // we ignore colB by set config tables.IgnoreColumns + // colB doesn't have the default value. + // we expect the check failed. + { + []*config.IgnoreColumns{ + { + TableFilter: []string{"`db1`.`table2`"}, + Columns: []string{"colb"}, + }, + }, + "TiDB schema `db1`.`table2`'s column colb cannot be ignored(.*)", + 2, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table2": { + ID: 1, + DB: "db1", + Name: "table2", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colB doesn't have the default value + Name: model.NewCIStr("colB"), + FieldType: types.FieldType{ + Flag: 1, + }, + }, + { + // colC has the default value + Name: model.NewCIStr("colC"), + DefaultIsExpr: true, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table2", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 3: + // table3's schema file not found. + // tidb has no table3. + // we expect the check failed. + { + []*config.IgnoreColumns{ + { + TableFilter: []string{"`db1`.`table2`"}, + Columns: []string{"colb"}, + }, + }, + "TiDB schema `db1`.`table3` doesn't exists(.*)", + 1, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "": {}, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table3", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }, + }, + // Case 4: + // table4 has two datafiles for table. we only check the first file. + // we expect the check success. + { + []*config.IgnoreColumns{ + { + DB: "db1", + Table: "table2", + Columns: []string{"cola"}, + }, + }, + "", + 0, + true, + map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "table2": { + ID: 1, + DB: "db1", + Name: "table2", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + // colB has the default value + Name: model.NewCIStr("colB"), + DefaultIsExpr: true, + }, + }, + }, + }, + }, + }, + }, + &mydump.MDTableMeta{ + DB: "db1", + Name: "table2", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + Type: mydump.SourceTypeCSV, + }, + }, + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: case2File, + // This type will make the check failed. + // but it's the second file for table. + // so it's unreachable so this case will success. + Type: mydump.SourceTypeIgnore, + }, + }, + }, + }, + }, + } + + for _, ca := range cases { + template := NewSimpleTemplate() + cfg := &config.Config{ + Mydumper: config.MydumperRuntime{ + ReadBlockSize: config.ReadBlockSize, + CSV: config.CSVConfig{ + Separator: ",", + Delimiter: `"`, + Header: ca.hasHeader, + NotNull: false, + Null: `\N`, + BackslashEscape: true, + TrimLastSep: false, + }, + IgnoreColumns: ca.ignoreColumns, + }, + } + rc := &Controller{ + cfg: cfg, + checkTemplate: template, + store: mockStore, + dbInfos: ca.dbInfos, + ioWorkers: worker.NewPool(context.Background(), 1, "io"), + } + msgs, err := rc.SchemaIsValid(ctx, ca.tableMeta) + require.NoError(s.T(), err) + require.Len(s.T(), msgs, ca.MsgNum) + if len(msgs) > 0 { + require.Regexp(s.T(), ca.expectMsg, msgs[0]) + } + } +} + +func (s *tableRestoreSuite) TestGBKEncodedSchemaIsValid() { + cfg := &config.Config{ + Mydumper: config.MydumperRuntime{ + ReadBlockSize: config.ReadBlockSize, + DataCharacterSet: "gb18030", + DataInvalidCharReplace: string(utf8.RuneError), + CSV: config.CSVConfig{ + Separator: ",", + Delimiter: `"`, + Header: true, + NotNull: false, + Null: `\N`, + BackslashEscape: true, + TrimLastSep: false, + }, + IgnoreColumns: nil, + }, + } + charsetConvertor, err := mydump.NewCharsetConvertor(cfg.Mydumper.DataCharacterSet, cfg.Mydumper.DataInvalidCharReplace) + require.NoError(s.T(), err) + dir := s.T().TempDir() + mockStore, err := storage.NewLocalStorage(dir) + require.NoError(s.T(), err) + csvContent, err := charsetConvertor.Encode(string([]byte("\"colA\",\"colB\"\n\"a\",\"b\""))) + require.NoError(s.T(), err) + ctx := context.Background() + csvFile := "db1.gbk_table.csv" + err = mockStore.WriteFile(ctx, csvFile, []byte(csvContent)) + require.NoError(s.T(), err) + + rc := &Controller{ + cfg: cfg, + checkTemplate: NewSimpleTemplate(), + store: mockStore, + dbInfos: map[string]*checkpoints.TidbDBInfo{ + "db1": { + Name: "db1", + Tables: map[string]*checkpoints.TidbTableInfo{ + "gbk_table": { + ID: 1, + DB: "db1", + Name: "gbk_table", + Core: &model.TableInfo{ + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("colA"), + FieldType: types.FieldType{ + Flag: 1, + }, + }, + { + Name: model.NewCIStr("colB"), + FieldType: types.FieldType{ + Flag: 1, + }, + }, + }, + }, + }, + }, + }, + }, + ioWorkers: worker.NewPool(ctx, 1, "io"), + } + msgs, err := rc.SchemaIsValid(ctx, &mydump.MDTableMeta{ + DB: "db1", + Name: "gbk_table", + DataFiles: []mydump.FileInfo{ + { + FileMeta: mydump.SourceFileMeta{ + FileSize: 1 * units.TiB, + Path: csvFile, + Type: mydump.SourceTypeCSV, + }, + }, + }, + }) + require.NoError(s.T(), err) + require.Len(s.T(), msgs, 0) +} diff --git a/br/pkg/lightning/restore/tidb.go b/br/pkg/lightning/restore/tidb.go index ee1252fd3862d..e530f8be604a4 100644 --- a/br/pkg/lightning/restore/tidb.go +++ b/br/pkg/lightning/restore/tidb.go @@ -21,7 +21,6 @@ import ( "strconv" "strings" - tmysql "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" @@ -35,7 +34,6 @@ import ( "github.com/pingcap/tidb/parser/format" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" "go.uber.org/zap" ) @@ -64,24 +62,6 @@ type TiDBManager struct { parser *parser.Parser } -// getSQLErrCode returns error code if err is a mysql error -func getSQLErrCode(err error) (terror.ErrCode, bool) { - mysqlErr, ok := errors.Cause(err).(*tmysql.MySQLError) - if !ok { - return -1, false - } - - return terror.ErrCode(mysqlErr.Number), true -} - -func isUnknownSystemVariableErr(err error) bool { - code, ok := getSQLErrCode(err) - if !ok { - return strings.Contains(err.Error(), "Unknown system variable") - } - return code == mysql.ErrUnknownSystemVariable -} - func DBFromConfig(ctx context.Context, dsn config.DBStore) (*sql.DB, error) { param := common.MySQLConnectParam{ Host: dsn.Host, @@ -111,6 +91,8 @@ func DBFromConfig(ctx context.Context, dsn config.DBStore) (*sql.DB, error) { "tidb_opt_write_row_id": "1", // always set auto-commit to ON "autocommit": "1", + // alway set transaction mode to optimistic + "tidb_txn_mode": "optimistic", } if dsn.Vars != nil { @@ -120,7 +102,7 @@ func DBFromConfig(ctx context.Context, dsn config.DBStore) (*sql.DB, error) { } for k, v := range vars { - q := fmt.Sprintf("SET SESSION %s = %s;", k, v) + q := fmt.Sprintf("SET SESSION %s = '%s';", k, v) if _, err1 := db.ExecContext(ctx, q); err1 != nil { log.L().Warn("set session variable failed, will skip this query", zap.String("query", q), zap.Error(err1)) @@ -177,7 +159,7 @@ loopCreate: for tbl, sqlCreateTable := range tablesSchema { task.Debug("create table", zap.String("schema", sqlCreateTable)) - sqlCreateStmts, err = createTableIfNotExistsStmt(g.GetParser(), sqlCreateTable, database, tbl) + sqlCreateStmts, err = createIfNotExistsStmt(g.GetParser(), sqlCreateTable, database, tbl) if err != nil { break } @@ -200,17 +182,10 @@ loopCreate: return errors.Trace(err) } -func createDatabaseIfNotExistStmt(dbName string) string { - var createDatabase strings.Builder - createDatabase.WriteString("CREATE DATABASE IF NOT EXISTS ") - common.WriteMySQLIdentifier(&createDatabase, dbName) - return createDatabase.String() -} - -func createTableIfNotExistsStmt(p *parser.Parser, createTable, dbName, tblName string) ([]string, error) { +func createIfNotExistsStmt(p *parser.Parser, createTable, dbName, tblName string) ([]string, error) { stmts, _, err := p.ParseSQL(createTable) if err != nil { - return []string{}, err + return []string{}, common.ErrInvalidSchemaStmt.Wrap(err).GenWithStackByArgs(createTable) } var res strings.Builder @@ -219,6 +194,9 @@ func createTableIfNotExistsStmt(p *parser.Parser, createTable, dbName, tblName s retStmts := make([]string, 0, len(stmts)) for _, stmt := range stmts { switch node := stmt.(type) { + case *ast.CreateDatabaseStmt: + node.Name = dbName + node.IfNotExists = true case *ast.CreateTableStmt: node.Table.Schema = model.NewCIStr(dbName) node.Table.Name = model.NewCIStr(tblName) @@ -232,7 +210,7 @@ func createTableIfNotExistsStmt(p *parser.Parser, createTable, dbName, tblName s node.IfExists = true } if err := stmt.Restore(ctx); err != nil { - return []string{}, err + return []string{}, common.ErrInvalidSchemaStmt.Wrap(err).GenWithStackByArgs(createTable) } ctx.WritePlain(";") retStmts = append(retStmts, res.String()) @@ -275,7 +253,7 @@ func LoadSchemaInfo( for _, tbl := range schema.Tables { tblInfo, ok := tableMap[strings.ToLower(tbl.Name)] if !ok { - return nil, errors.Errorf("table '%s' schema not found", tbl.Name) + return nil, common.ErrSchemaNotExists.GenWithStackByArgs(tbl.DB, tbl.Name) } tableName := tblInfo.Name.String() if tblInfo.State != model.StatePublic { @@ -287,13 +265,15 @@ func LoadSchemaInfo( if err != nil { return nil, errors.Trace(err) } + // Table names are case-sensitive in mydump.MDTableMeta. + // We should always use the original tbl.Name in checkpoints. tableInfo := &checkpoints.TidbTableInfo{ ID: tblInfo.ID, DB: schema.Name, - Name: tableName, + Name: tbl.Name, Core: tblInfo, } - dbInfo.Tables[tableName] = tableInfo + dbInfo.Tables[tbl.Name] = tableInfo } result[schema.Name] = dbInfo @@ -369,7 +349,7 @@ func ObtainImportantVariables(ctx context.Context, g glue.SQLExecutor, needTiDBV return result } -func ObtainNewCollationEnabled(ctx context.Context, g glue.SQLExecutor) bool { +func ObtainNewCollationEnabled(ctx context.Context, g glue.SQLExecutor) (bool, error) { newCollationEnabled := false newCollationVal, err := g.ObtainStringWithLog( ctx, @@ -379,9 +359,13 @@ func ObtainNewCollationEnabled(ctx context.Context, g glue.SQLExecutor) bool { ) if err == nil && newCollationVal == "True" { newCollationEnabled = true + } else if errors.ErrorEqual(err, sql.ErrNoRows) { + // ignore if target variable is not found, this may happen if tidb < v4.0 + newCollationEnabled = false + err = nil } - return newCollationEnabled + return newCollationEnabled, errors.Trace(err) } // AlterAutoIncrement rebase the table auto increment id diff --git a/br/pkg/lightning/restore/tidb_test.go b/br/pkg/lightning/restore/tidb_test.go index f066f8438581e..89a5b40433797 100644 --- a/br/pkg/lightning/restore/tidb_test.go +++ b/br/pkg/lightning/restore/tidb_test.go @@ -16,11 +16,11 @@ package restore import ( "context" + "database/sql" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/go-sql-driver/mysql" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/glue" @@ -31,151 +31,121 @@ import ( "github.com/pingcap/tidb/parser/model" tmysql "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = Suite(&tidbSuite{}) - type tidbSuite struct { mockDB sqlmock.Sqlmock timgr *TiDBManager tiGlue glue.Glue } -func TestTiDB(t *testing.T) { - TestingT(t) -} - -func (s *tidbSuite) SetUpTest(c *C) { +func newTiDBSuite(t *testing.T) (*tidbSuite, func()) { + var s tidbSuite db, mock, err := sqlmock.New() - c.Assert(err, IsNil) + require.NoError(t, err) s.mockDB = mock defaultSQLMode, err := tmysql.GetSQLMode(tmysql.DefaultSQLMode) - c.Assert(err, IsNil) + require.NoError(t, err) s.timgr = NewTiDBManagerWithDB(db, defaultSQLMode) s.tiGlue = glue.NewExternalTiDBGlue(db, defaultSQLMode) + return &s, func() { + s.timgr.Close() + require.NoError(t, s.mockDB.ExpectationsWereMet()) + } } -func (s *tidbSuite) TearDownTest(c *C) { - s.timgr.Close() - c.Assert(s.mockDB.ExpectationsWereMet(), IsNil) -} +func TestCreateTableIfNotExistsStmt(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() -func (s *tidbSuite) TestCreateTableIfNotExistsStmt(c *C) { dbName := "testdb" - createTableIfNotExistsStmt := func(createTable, tableName string) []string { - res, err := createTableIfNotExistsStmt(s.tiGlue.GetParser(), createTable, dbName, tableName) - c.Assert(err, IsNil) + createSQLIfNotExistsStmt := func(createTable, tableName string) []string { + res, err := createIfNotExistsStmt(s.tiGlue.GetParser(), createTable, dbName, tableName) + require.NoError(t, err) return res } - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` TINYINT(1));", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE DATABASE IF NOT EXISTS `testdb` CHARACTER SET = utf8 COLLATE = utf8_general_ci;"}, + createSQLIfNotExistsStmt("CREATE DATABASE `foo` CHARACTER SET = utf8 COLLATE = utf8_general_ci;", "")) + + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` TINYINT(1));", "foo")) - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE IF NOT EXISTS `foo`(`bar` TINYINT(1));", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"}, + createSQLIfNotExistsStmt("CREATE TABLE IF NOT EXISTS `foo`(`bar` TINYINT(1));", "foo")) // case insensitive - c.Assert( - createTableIfNotExistsStmt("/* cOmmEnt */ creAte tablE `fOo`(`bar` TinyinT(1));", "fOo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`fOo` (`bar` TINYINT(1));"}, - ) - - c.Assert( - createTableIfNotExistsStmt("/* coMMenT */ crEatE tAble If not EXISts `FoO`(`bAR` tiNyInT(1));", "FoO"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`FoO` (`bAR` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`fOo` (`bar` TINYINT(1));"}, + createSQLIfNotExistsStmt("/* cOmmEnt */ creAte tablE `fOo`(`bar` TinyinT(1));", "fOo")) + + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`FoO` (`bAR` TINYINT(1));"}, + createSQLIfNotExistsStmt("/* coMMenT */ crEatE tAble If not EXISts `FoO`(`bAR` tiNyInT(1));", "FoO")) // only one "CREATE TABLE" is replaced - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE');", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE');"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE');"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE');", "foo")) // test clustered index consistency - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY CLUSTERED COMMENT 'CREATE TABLE');", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] CLUSTERED */ COMMENT 'CREATE TABLE');"}, - ) - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) NONCLUSTERED);", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] NONCLUSTERED */);"}, - ) - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');"}, - ) - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) /*T![clustered_index] CLUSTERED */);", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] CLUSTERED */);"}, - ) - - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY AUTO_RANDOM(2) COMMENT 'CREATE TABLE');", "foo"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![auto_rand] AUTO_RANDOM(2) */ COMMENT 'CREATE TABLE');"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] CLUSTERED */ COMMENT 'CREATE TABLE');"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY CLUSTERED COMMENT 'CREATE TABLE');", "foo")) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] NONCLUSTERED */);"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) NONCLUSTERED);", "foo")) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');", "foo")) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] CLUSTERED */);"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) /*T![clustered_index] CLUSTERED */);", "foo")) + + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![auto_rand] AUTO_RANDOM(2) */ COMMENT 'CREATE TABLE');"}, + createSQLIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY AUTO_RANDOM(2) COMMENT 'CREATE TABLE');", "foo")) // upper case becomes shorter - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `Å¿`(`ı` TINYINT(1));", "Å¿"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`Å¿` (`ı` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`Å¿` (`ı` TINYINT(1));"}, + createSQLIfNotExistsStmt("CREATE TABLE `Å¿`(`ı` TINYINT(1));", "Å¿")) // upper case becomes longer - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `É‘`(`È¿` TINYINT(1));", "É‘"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`É‘` (`È¿` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`É‘` (`È¿` TINYINT(1));"}, + createSQLIfNotExistsStmt("CREATE TABLE `É‘`(`È¿` TINYINT(1));", "É‘")) // non-utf-8 - c.Assert( - createTableIfNotExistsStmt("CREATE TABLE `\xcc\xcc\xcc`(`\xdd\xdd\xdd` TINYINT(1));", "\xcc\xcc\xcc"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`\xcc\xcc\xcc` (`ÃÃÃ` TINYINT(1));"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`\xcc\xcc\xcc` (`???` TINYINT(1));"}, + createSQLIfNotExistsStmt("CREATE TABLE `\xcc\xcc\xcc`(`\xdd\xdd\xdd` TINYINT(1));", "\xcc\xcc\xcc")) // renaming a table - c.Assert( - createTableIfNotExistsStmt("create table foo(x int);", "ba`r"), - DeepEquals, - []string{"CREATE TABLE IF NOT EXISTS `testdb`.`ba``r` (`x` INT);"}, - ) + require.Equal(t, []string{"CREATE TABLE IF NOT EXISTS `testdb`.`ba``r` (`x` INT);"}, + createSQLIfNotExistsStmt("create table foo(x int);", "ba`r")) // conditional comments - c.Assert( - createTableIfNotExistsStmt(` + require.Equal(t, []string{ + "SET NAMES 'binary';", + "SET @@SESSION.`FOREIGN_KEY_CHECKS`=0;", + "CREATE TABLE IF NOT EXISTS `testdb`.`m` (`z` DOUBLE) ENGINE = InnoDB AUTO_INCREMENT = 8343230 DEFAULT CHARACTER SET = UTF8;", + }, + createSQLIfNotExistsStmt(` /*!40101 SET NAMES binary*/; /*!40014 SET FOREIGN_KEY_CHECKS=0*/; CREATE TABLE x.y (z double) ENGINE=InnoDB AUTO_INCREMENT=8343230 DEFAULT CHARSET=utf8; - `, "m"), - DeepEquals, - []string{ - "SET NAMES 'binary';", - "SET @@SESSION.`FOREIGN_KEY_CHECKS`=0;", - "CREATE TABLE IF NOT EXISTS `testdb`.`m` (`z` DOUBLE) ENGINE = InnoDB AUTO_INCREMENT = 8343230 DEFAULT CHARACTER SET = UTF8;", - }, - ) + `, "m")) // create view - c.Assert( - createTableIfNotExistsStmt(` + require.Equal(t, []string{ + "SET NAMES 'binary';", + "DROP TABLE IF EXISTS `testdb`.`m`;", + "DROP VIEW IF EXISTS `testdb`.`m`;", + "SET @`PREV_CHARACTER_SET_CLIENT`=@@`character_set_client`;", + "SET @`PREV_CHARACTER_SET_RESULTS`=@@`character_set_results`;", + "SET @`PREV_COLLATION_CONNECTION`=@@`collation_connection`;", + "SET @@SESSION.`character_set_client`=`utf8`;", + "SET @@SESSION.`character_set_results`=`utf8`;", + "SET @@SESSION.`collation_connection`=`utf8_general_ci`;", + "CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`192.168.198.178` SQL SECURITY DEFINER VIEW `testdb`.`m` (`s`) AS SELECT `s` FROM `db1`.`v1` WHERE `i`<2;", + "SET @@SESSION.`character_set_client`=@`PREV_CHARACTER_SET_CLIENT`;", + "SET @@SESSION.`character_set_results`=@`PREV_CHARACTER_SET_RESULTS`;", + "SET @@SESSION.`collation_connection`=@`PREV_COLLATION_CONNECTION`;", + }, + createSQLIfNotExistsStmt(` /*!40101 SET NAMES binary*/; DROP TABLE IF EXISTS v2; DROP VIEW IF EXISTS v2; @@ -189,27 +159,12 @@ func (s *tidbSuite) TestCreateTableIfNotExistsStmt(c *C) { SET character_set_client = @PREV_CHARACTER_SET_CLIENT; SET character_set_results = @PREV_CHARACTER_SET_RESULTS; SET collation_connection = @PREV_COLLATION_CONNECTION; - `, "m"), - DeepEquals, - []string{ - "SET NAMES 'binary';", - "DROP TABLE IF EXISTS `testdb`.`m`;", - "DROP VIEW IF EXISTS `testdb`.`m`;", - "SET @`PREV_CHARACTER_SET_CLIENT`=@@`character_set_client`;", - "SET @`PREV_CHARACTER_SET_RESULTS`=@@`character_set_results`;", - "SET @`PREV_COLLATION_CONNECTION`=@@`collation_connection`;", - "SET @@SESSION.`character_set_client`=`utf8`;", - "SET @@SESSION.`character_set_results`=`utf8`;", - "SET @@SESSION.`collation_connection`=`utf8_general_ci`;", - "CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`192.168.198.178` SQL SECURITY DEFINER VIEW `testdb`.`m` (`s`) AS SELECT `s` FROM `db1`.`v1` WHERE `i`<2;", - "SET @@SESSION.`character_set_client`=@`PREV_CHARACTER_SET_CLIENT`;", - "SET @@SESSION.`character_set_results`=@`PREV_CHARACTER_SET_RESULTS`;", - "SET @@SESSION.`collation_connection`=@`PREV_COLLATION_CONNECTION`;", - }, - ) + `, "m")) } -func (s *tidbSuite) TestInitSchema(c *C) { +func TestInitSchema(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -233,10 +188,12 @@ func (s *tidbSuite) TestInitSchema(c *C) { "t2": "/*!40014 SET FOREIGN_KEY_CHECKS=0*/;CREATE TABLE `db`.`t2` (xx TEXT) AUTO_INCREMENT=11203;", }) s.mockDB.MatchExpectationsInOrder(true) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *tidbSuite) TestInitSchemaSyntaxError(c *C) { +func TestInitSchemaSyntaxError(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -248,10 +205,12 @@ func (s *tidbSuite) TestInitSchemaSyntaxError(c *C) { err := InitSchema(ctx, s.tiGlue, "db", map[string]string{ "t1": "create table `t1` with invalid syntax;", }) - c.Assert(err, NotNil) + require.Error(t, err) } -func (s *tidbSuite) TestInitSchemaErrorLost(c *C) { +func TestInitSchemaErrorLost(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -272,10 +231,12 @@ func (s *tidbSuite) TestInitSchemaErrorLost(c *C) { "t1": "create table `t1` (a int);", "t2": "create table t2 (a int primary key, b varchar(200));", }) - c.Assert(err, ErrorMatches, ".*Column length too big.*") + require.Regexp(t, ".*Column length too big.*", err.Error()) } -func (s *tidbSuite) TestInitSchemaUnsupportedSchemaError(c *C) { +func TestInitSchemaUnsupportedSchemaError(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -293,10 +254,12 @@ func (s *tidbSuite) TestInitSchemaUnsupportedSchemaError(c *C) { err := InitSchema(ctx, s.tiGlue, "db", map[string]string{ "t1": "create table `t1` (a VARCHAR(999999999));", }) - c.Assert(err, ErrorMatches, ".*Column length too big.*") + require.Regexp(t, ".*Column length too big.*", err.Error()) } -func (s *tidbSuite) TestDropTable(c *C) { +func TestDropTable(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -306,10 +269,12 @@ func (s *tidbSuite) TestDropTable(c *C) { ExpectClose() err := s.timgr.DropTable(ctx, "`db`.`table`") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *tidbSuite) TestLoadSchemaInfo(c *C) { +func TestLoadSchemaInfo(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() tableCntBefore := metric.ReadCounter(metric.TableCounter.WithLabelValues(metric.TableStatePending, metric.TableResultSuccess)) @@ -319,15 +284,16 @@ func (s *tidbSuite) TestLoadSchemaInfo(c *C) { "CREATE TABLE `t1` (`a` INT PRIMARY KEY);"+ "CREATE TABLE `t2` (`b` VARCHAR(20), `c` BOOL, KEY (`b`, `c`));"+ // an extra table that not exists in dbMetas - "CREATE TABLE `t3` (`d` VARCHAR(20), `e` BOOL);", + "CREATE TABLE `t3` (`d` VARCHAR(20), `e` BOOL);"+ + "CREATE TABLE `T4` (`f` BIGINT PRIMARY KEY);", "", "") - c.Assert(err, IsNil) + require.NoError(t, err) tableInfos := make([]*model.TableInfo, 0, len(nodes)) sctx := mock.NewContext() for i, node := range nodes { - c.Assert(node, FitsTypeOf, &ast.CreateTableStmt{}) + require.IsType(t, node, &ast.CreateTableStmt{}) info, err := ddl.MockTableInfo(sctx, node.(*ast.CreateTableStmt), int64(i+100)) - c.Assert(err, IsNil) + require.NoError(t, err) info.State = model.StatePublic tableInfos = append(tableInfos, info) } @@ -344,16 +310,20 @@ func (s *tidbSuite) TestLoadSchemaInfo(c *C) { DB: "db", Name: "t2", }, + { + DB: "db", + Name: "t4", + }, }, }, } loaded, err := LoadSchemaInfo(ctx, dbMetas, func(ctx context.Context, schema string) ([]*model.TableInfo, error) { - c.Assert(schema, Equals, "db") + require.Equal(t, "db", schema) return tableInfos, nil }) - c.Assert(err, IsNil) - c.Assert(loaded, DeepEquals, map[string]*checkpoints.TidbDBInfo{ + require.NoError(t, err) + require.Equal(t, map[string]*checkpoints.TidbDBInfo{ "db": { Name: "db", Tables: map[string]*checkpoints.TidbTableInfo{ @@ -369,25 +339,33 @@ func (s *tidbSuite) TestLoadSchemaInfo(c *C) { Name: "t2", Core: tableInfos[1], }, + "t4": { + ID: 103, + DB: "db", + Name: "t4", + Core: tableInfos[3], + }, }, }, - }) + }, loaded) tableCntAfter := metric.ReadCounter(metric.TableCounter.WithLabelValues(metric.TableStatePending, metric.TableResultSuccess)) - c.Assert(tableCntAfter-tableCntBefore, Equals, 2.0) + require.Equal(t, 3.0, tableCntAfter-tableCntBefore) } -func (s *tidbSuite) TestLoadSchemaInfoMissing(c *C) { +func TestLoadSchemaInfoMissing(t *testing.T) { ctx := context.Background() _, err := LoadSchemaInfo(ctx, []*mydump.MDDatabaseMeta{{Name: "asdjalsjdlas"}}, func(ctx context.Context, schema string) ([]*model.TableInfo, error) { return nil, errors.Errorf("[schema:1049]Unknown database '%s'", schema) }) - c.Assert(err, ErrorMatches, ".*Unknown database.*") + require.Regexp(t, ".*Unknown database.*", err.Error()) } -func (s *tidbSuite) TestGetGCLifetime(c *C) { +func TestGetGCLifetime(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -397,11 +375,13 @@ func (s *tidbSuite) TestGetGCLifetime(c *C) { ExpectClose() res, err := ObtainGCLifeTime(ctx, s.timgr.db) - c.Assert(err, IsNil) - c.Assert(res, Equals, "10m") + require.NoError(t, err) + require.Equal(t, "10m", res) } -func (s *tidbSuite) TestSetGCLifetime(c *C) { +func TestSetGCLifetime(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -412,10 +392,12 @@ func (s *tidbSuite) TestSetGCLifetime(c *C) { ExpectClose() err := UpdateGCLifeTime(ctx, s.timgr.db, "12m") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *tidbSuite) TestAlterAutoInc(c *C) { +func TestAlterAutoInc(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -425,10 +407,12 @@ func (s *tidbSuite) TestAlterAutoInc(c *C) { ExpectClose() err := AlterAutoIncrement(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *tidbSuite) TestAlterAutoRandom(c *C) { +func TestAlterAutoRandom(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -438,10 +422,12 @@ func (s *tidbSuite) TestAlterAutoRandom(c *C) { ExpectClose() err := AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *tidbSuite) TestObtainRowFormatVersionSucceed(c *C) { +func TestObtainRowFormatVersionSucceed(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -463,7 +449,7 @@ func (s *tidbSuite) TestObtainRowFormatVersionSucceed(c *C) { ExpectClose() sysVars := ObtainImportantVariables(ctx, s.tiGlue.GetSQLExecutor(), true) - c.Assert(sysVars, DeepEquals, map[string]string{ + require.Equal(t, map[string]string{ "tidb_row_format_version": "2", "max_allowed_packet": "1073741824", "div_precision_increment": "10", @@ -472,10 +458,12 @@ func (s *tidbSuite) TestObtainRowFormatVersionSucceed(c *C) { "default_week_format": "1", "block_encryption_mode": "aes-256-cbc", "group_concat_max_len": "1073741824", - }) + }, sysVars) } -func (s *tidbSuite) TestObtainRowFormatVersionFailure(c *C) { +func TestObtainRowFormatVersionFailure(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. @@ -489,7 +477,7 @@ func (s *tidbSuite) TestObtainRowFormatVersionFailure(c *C) { ExpectClose() sysVars := ObtainImportantVariables(ctx, s.tiGlue.GetSQLExecutor(), true) - c.Assert(sysVars, DeepEquals, map[string]string{ + require.Equal(t, map[string]string{ "tidb_row_format_version": "1", "max_allowed_packet": "67108864", "div_precision_increment": "4", @@ -498,16 +486,32 @@ func (s *tidbSuite) TestObtainRowFormatVersionFailure(c *C) { "default_week_format": "0", "block_encryption_mode": "aes-128-ecb", "group_concat_max_len": "1024", - }) + }, sysVars) } -func (s *tidbSuite) TestObtainNewCollationEnabled(c *C) { +func TestObtainNewCollationEnabled(t *testing.T) { + s, clean := newTiDBSuite(t) + defer clean() ctx := context.Background() s.mockDB. - ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E") - version := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) - c.Assert(version, Equals, false) + ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). + WillReturnError(errors.New("mock permission deny")) + s.mockDB. + ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). + WillReturnError(errors.New("mock permission deny")) + s.mockDB. + ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). + WillReturnError(errors.New("mock permission deny")) + _, err := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) + require.Equal(t, "obtain new collation enabled failed: mock permission deny", err.Error()) + + s.mockDB. + ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). + WillReturnRows(sqlmock.NewRows([]string{"variable_value"}).RowError(0, sql.ErrNoRows)) + version, err := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) + require.NoError(t, err) + require.Equal(t, false, version) kvMap := map[string]bool{ "True": true, @@ -518,8 +522,9 @@ func (s *tidbSuite) TestObtainNewCollationEnabled(c *C) { ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E"). WillReturnRows(sqlmock.NewRows([]string{"variable_value"}).AddRow(k)) - version := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) - c.Assert(version, Equals, v) + version, err = ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor()) + require.NoError(t, err) + require.Equal(t, v, version) } s.mockDB. ExpectClose() diff --git a/br/pkg/lightning/run_options.go b/br/pkg/lightning/run_options.go new file mode 100644 index 0000000000000..8182794df3eaa --- /dev/null +++ b/br/pkg/lightning/run_options.go @@ -0,0 +1,54 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lightning + +import ( + "github.com/pingcap/tidb/br/pkg/lightning/glue" + "github.com/pingcap/tidb/br/pkg/storage" +) + +type options struct { + glue glue.Glue + dumpFileStorage storage.ExternalStorage + checkpointStorage storage.ExternalStorage + checkpointName string +} + +type Option func(*options) + +// WithGlue sets the glue to a lightning task. +// Typically, the glue is set when lightning is integrated with a TiDB. +func WithGlue(g glue.Glue) Option { + return func(o *options) { + o.glue = g + } +} + +// WithDumpFileStorage sets the external storage to a lightning task. +// Typically, the external storage is set when lightning is integrated with dataflow engine by DM. +func WithDumpFileStorage(s storage.ExternalStorage) Option { + return func(o *options) { + o.dumpFileStorage = s + } +} + +// WithCheckpointStorage sets the checkpoint name in external storage to a lightning task. +// Typically, the checkpoint name is set when lightning is integrated with dataflow engine by DM. +func WithCheckpointStorage(s storage.ExternalStorage, cpName string) Option { + return func(o *options) { + o.checkpointStorage = s + o.checkpointName = cpName + } +} diff --git a/br/pkg/lightning/tikv/tikv_test.go b/br/pkg/lightning/tikv/tikv_test.go index f74b20c5ce57e..6c8d7a976f1d4 100644 --- a/br/pkg/lightning/tikv/tikv_test.go +++ b/br/pkg/lightning/tikv/tikv_test.go @@ -1,3 +1,17 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package tikv_test import ( @@ -9,18 +23,15 @@ import ( "net/url" "sort" "sync" + "testing" "github.com/coreos/go-semver/semver" - . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/tidb/br/pkg/lightning/common" kv "github.com/pingcap/tidb/br/pkg/lightning/tikv" + "github.com/stretchr/testify/require" ) -type tikvSuite struct{} - -var _ = Suite(&tikvSuite{}) - var ( // Samples from importer backend for testing the Check***Version functions. // No need keep these versions in sync. @@ -30,7 +41,7 @@ var ( requiredMaxTiKVVersion = *semver.New("6.0.0") ) -func (s *tikvSuite) TestForAllStores(c *C) { +func TestForAllStores(t *testing.T) { server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { _, err := w.Write([]byte(` { @@ -84,7 +95,7 @@ func (s *tikvSuite) TestForAllStores(c *C) { ] } `)) - c.Assert(err, IsNil) + require.NoError(t, err) })) defer server.Close() @@ -100,11 +111,10 @@ func (s *tikvSuite) TestForAllStores(c *C) { allStoresLock.Unlock() return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) sort.Slice(allStores, func(i, j int) bool { return allStores[i].Address < allStores[j].Address }) - - c.Assert(allStores, DeepEquals, []*kv.Store{ + require.Equal(t, []*kv.Store{ { Address: "127.0.0.1:20160", Version: "3.0.0-beta.1", @@ -125,10 +135,10 @@ func (s *tikvSuite) TestForAllStores(c *C) { Version: "3.0.1", State: kv.StoreStateOffline, }, - }) + }, allStores) } -func (s *tikvSuite) TestFetchModeFromMetrics(c *C) { +func TestFetchModeFromMetrics(t *testing.T) { testCases := []struct { metrics string mode import_sstpb.SwitchMode @@ -149,69 +159,77 @@ func (s *tikvSuite) TestFetchModeFromMetrics(c *C) { } for _, tc := range testCases { - comment := Commentf("test case '%s'", tc.metrics) + comment := fmt.Sprintf("test case '%s'", tc.metrics) mode, err := kv.FetchModeFromMetrics(tc.metrics) if tc.isErr { - c.Assert(err, NotNil, comment) + require.Error(t, err, comment) } else { - c.Assert(err, IsNil, comment) - c.Assert(mode, Equals, tc.mode, comment) + require.NoError(t, err, comment) + require.Equal(t, tc.mode, mode, comment) } } } -func (s *tikvSuite) TestCheckPDVersion(c *C) { +func TestCheckPDVersion(t *testing.T) { var version string ctx := context.Background() mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - c.Assert(req.URL.Path, Equals, "/pd/api/v1/version") + require.Equal(t, "/pd/api/v1/version", req.URL.Path) w.WriteHeader(http.StatusOK) _, err := w.Write([]byte(version)) - c.Assert(err, IsNil) + require.NoError(t, err) })) mockURL, err := url.Parse(mockServer.URL) - c.Assert(err, IsNil) + require.NoError(t, err) tls := common.NewTLSFromMockServer(mockServer) version = `{ "version": "v4.0.0-rc.2-451-g760fb650" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), IsNil) + require.NoError(t, kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion)) version = `{ "version": "v4.0.0" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), IsNil) + require.NoError(t, kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion)) version = `{ "version": "v9999.0.0" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*") + err = kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, "PD version too new.*", err.Error()) version = `{ "version": "v6.0.0" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*") + err = kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, "PD version too new.*", err.Error()) version = `{ "version": "v6.0.0-beta" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*") + err = kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, "PD version too new.*", err.Error()) version = `{ "version": "v1.0.0" }` - c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too old.*") + err = kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, "PD version too old.*", err.Error()) } -func (s *tikvSuite) TestCheckTiKVVersion(c *C) { +func TestCheckTiKVVersion(t *testing.T) { var versions []string ctx := context.Background() mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - c.Assert(req.URL.Path, Equals, "/pd/api/v1/stores") + require.Equal(t, "/pd/api/v1/stores", req.URL.Path) w.WriteHeader(http.StatusOK) stores := make([]map[string]interface{}, 0, len(versions)) @@ -227,25 +245,33 @@ func (s *tikvSuite) TestCheckTiKVVersion(c *C) { "count": len(versions), "stores": stores, }) - c.Assert(err, IsNil) + require.NoError(t, err) })) mockURL, err := url.Parse(mockServer.URL) - c.Assert(err, IsNil) + require.NoError(t, err) tls := common.NewTLSFromMockServer(mockServer) versions = []string{"4.1.0", "v4.1.0-alpha-9-ga27a7dd"} - c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), IsNil) + require.NoError(t, kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion)) versions = []string{"9999.0.0", "4.0.0"} - c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`) + err = kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, `TiKV \(at tikv0\.test:20160\) version too new.*`, err.Error()) versions = []string{"4.0.0", "1.0.0"} - c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv1\.test:20160\) version too old.*`) + err = kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, `TiKV \(at tikv1\.test:20160\) version too old.*`, err.Error()) versions = []string{"6.0.0"} - c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`) + err = kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, `TiKV \(at tikv0\.test:20160\) version too new.*`, err.Error()) versions = []string{"6.0.0-beta"} - c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`) + err = kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion) + require.Error(t, err) + require.Regexp(t, `TiKV \(at tikv0\.test:20160\) version too new.*`, err.Error()) } diff --git a/br/pkg/lightning/verification/checksum_test.go b/br/pkg/lightning/verification/checksum_test.go index fb9c714c7a736..58484eecfea16 100644 --- a/br/pkg/lightning/verification/checksum_test.go +++ b/br/pkg/lightning/verification/checksum_test.go @@ -18,34 +18,23 @@ import ( "encoding/json" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/verification" + "github.com/stretchr/testify/require" ) -type testKVChcksumSuite struct{} - -func (s *testKVChcksumSuite) SetUpSuite(c *C) {} -func (s *testKVChcksumSuite) TearDownSuite(c *C) {} - -var _ = Suite(&testKVChcksumSuite{}) - -func TestKVChcksum(t *testing.T) { - TestingT(t) -} - func uint64NotEqual(a uint64, b uint64) bool { return a != b } -func (s *testKVChcksumSuite) TestChcksum(c *C) { +func TestChcksum(t *testing.T) { checksum := verification.NewKVChecksum(0) - c.Assert(checksum.Sum(), Equals, uint64(0)) + require.Equal(t, uint64(0), checksum.Sum()) // checksum on nothing checksum.Update([]common.KvPair{}) - c.Assert(checksum.Sum(), Equals, uint64(0)) + require.Equal(t, uint64(0), checksum.Sum()) checksum.Update(nil) - c.Assert(checksum.Sum(), Equals, uint64(0)) + require.Equal(t, uint64(0), checksum.Sum()) // checksum on real data excpectChecksum := uint64(4850203904608948940) @@ -67,18 +56,18 @@ func (s *testKVChcksumSuite) TestChcksum(c *C) { for _, kv := range kvs { kvBytes += uint64(len(kv.Key) + len(kv.Val)) } - c.Assert(checksum.SumSize(), Equals, kvBytes) - c.Assert(checksum.SumKVS(), Equals, uint64(len(kvs))) - c.Assert(checksum.Sum(), Equals, excpectChecksum) + require.Equal(t, kvBytes, checksum.SumSize()) + require.Equal(t, uint64(len(kvs)), checksum.SumKVS()) + require.Equal(t, excpectChecksum, checksum.Sum()) // recompute on same key-value checksum.Update(kvs) - c.Assert(checksum.SumSize(), Equals, kvBytes<<1) - c.Assert(checksum.SumKVS(), Equals, uint64(len(kvs))<<1) - c.Assert(uint64NotEqual(checksum.Sum(), excpectChecksum), IsTrue) + require.Equal(t, kvBytes<<1, checksum.SumSize()) + require.Equal(t, uint64(len(kvs))<<1, checksum.SumKVS()) + require.True(t, uint64NotEqual(checksum.Sum(), excpectChecksum)) } -func (s *testKVChcksumSuite) TestChecksumJSON(c *C) { +func TestChecksumJSON(t *testing.T) { testStruct := &struct { Checksum verification.KVChecksum }{ @@ -87,6 +76,6 @@ func (s *testKVChcksumSuite) TestChecksumJSON(c *C) { res, err := json.Marshal(testStruct) - c.Assert(err, IsNil) - c.Assert(res, BytesEquals, []byte(`{"Checksum":{"checksum":7890,"size":123,"kvs":456}}`)) + require.NoError(t, err) + require.Equal(t, []byte(`{"Checksum":{"checksum":7890,"size":123,"kvs":456}}`), res) } diff --git a/br/pkg/lightning/web/progress.go b/br/pkg/lightning/web/progress.go index 0acbae865dd53..8a3412087b94f 100644 --- a/br/pkg/lightning/web/progress.go +++ b/br/pkg/lightning/web/progress.go @@ -8,6 +8,7 @@ import ( "github.com/pingcap/tidb/br/pkg/lightning/checkpoints" "github.com/pingcap/tidb/br/pkg/lightning/common" "github.com/pingcap/tidb/br/pkg/lightning/mydump" + "go.uber.org/atomic" ) // checkpointsMap is a concurrent map (table name → checkpoints). @@ -108,11 +109,25 @@ type taskProgress struct { checkpoints checkpointsMap } -var currentProgress = taskProgress{ - checkpoints: makeCheckpointsMap(), +var ( + currentProgress *taskProgress + // whether progress is enabled + progressEnabled = atomic.NewBool(false) +) + +// EnableCurrentProgress init current progress struct on demand. +// NOTE: this call is not thread safe, so it should only be inited once at the very beginning of progress start. +func EnableCurrentProgress() { + currentProgress = &taskProgress{ + checkpoints: makeCheckpointsMap(), + } + progressEnabled.Store(true) } func BroadcastStartTask() { + if !progressEnabled.Load() { + return + } currentProgress.mu.Lock() currentProgress.Status = taskStatusRunning currentProgress.mu.Unlock() @@ -121,6 +136,9 @@ func BroadcastStartTask() { } func BroadcastEndTask(err error) { + if !progressEnabled.Load() { + return + } errString := errors.ErrorStack(err) currentProgress.mu.Lock() @@ -130,6 +148,9 @@ func BroadcastEndTask(err error) { } func BroadcastInitProgress(databases []*mydump.MDDatabaseMeta) { + if !progressEnabled.Load() { + return + } tables := make(map[string]*tableInfo, len(databases)) for _, db := range databases { @@ -145,6 +166,9 @@ func BroadcastInitProgress(databases []*mydump.MDDatabaseMeta) { } func BroadcastTableCheckpoint(tableName string, cp *checkpoints.TableCheckpoint) { + if !progressEnabled.Load() { + return + } currentProgress.mu.Lock() currentProgress.Tables[tableName].Status = taskStatusRunning currentProgress.mu.Unlock() @@ -154,6 +178,9 @@ func BroadcastTableCheckpoint(tableName string, cp *checkpoints.TableCheckpoint) } func BroadcastCheckpointDiff(diffs map[string]*checkpoints.TableCheckpointDiff) { + if !progressEnabled.Load() { + return + } totalWrittens := currentProgress.checkpoints.update(diffs) currentProgress.mu.Lock() @@ -164,6 +191,9 @@ func BroadcastCheckpointDiff(diffs map[string]*checkpoints.TableCheckpointDiff) } func BroadcastError(tableName string, err error) { + if !progressEnabled.Load() { + return + } errString := errors.ErrorStack(err) currentProgress.mu.Lock() @@ -175,11 +205,17 @@ func BroadcastError(tableName string, err error) { } func MarshalTaskProgress() ([]byte, error) { + if !progressEnabled.Load() { + return nil, errors.New("progress is not enabled") + } currentProgress.mu.RLock() defer currentProgress.mu.RUnlock() return json.Marshal(¤tProgress) } func MarshalTableCheckpoints(tableName string) ([]byte, error) { + if !progressEnabled.Load() { + return nil, errors.New("progress is not enabled") + } return currentProgress.checkpoints.marshal(tableName) } diff --git a/br/pkg/lightning/worker/worker_test.go b/br/pkg/lightning/worker/worker_test.go index 11a09fd849569..dd1eccda1552d 100644 --- a/br/pkg/lightning/worker/worker_test.go +++ b/br/pkg/lightning/worker/worker_test.go @@ -18,39 +18,28 @@ import ( "context" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/br/pkg/lightning/worker" + "github.com/stretchr/testify/require" ) -type testWorkerPool struct{} - -func (s *testWorkerPool) SetUpSuite(c *C) {} -func (s *testWorkerPool) TearDownSuite(c *C) {} - -var _ = Suite(&testWorkerPool{}) - -func TestNewRestoreWorkerPool(t *testing.T) { - TestingT(t) -} - -func (s *testWorkerPool) TestApplyRecycle(c *C) { +func TestApplyRecycle(t *testing.T) { pool := worker.NewPool(context.Background(), 3, "test") w1, w2, w3 := pool.Apply(), pool.Apply(), pool.Apply() - c.Assert(w1.ID, Equals, int64(1)) - c.Assert(w2.ID, Equals, int64(2)) - c.Assert(w3.ID, Equals, int64(3)) - c.Assert(pool.HasWorker(), Equals, false) + require.Equal(t, int64(1), w1.ID) + require.Equal(t, int64(2), w2.ID) + require.Equal(t, int64(3), w3.ID) + require.Equal(t, false, pool.HasWorker()) pool.Recycle(w3) - c.Assert(pool.HasWorker(), Equals, true) - c.Assert(pool.Apply(), Equals, w3) + require.Equal(t, true, pool.HasWorker()) + require.Equal(t, w3, pool.Apply()) pool.Recycle(w2) - c.Assert(pool.Apply(), Equals, w2) + require.Equal(t, w2, pool.Apply()) pool.Recycle(w1) - c.Assert(pool.Apply(), Equals, w1) + require.Equal(t, w1, pool.Apply()) - c.Assert(pool.HasWorker(), Equals, false) + require.Equal(t, false, pool.HasWorker()) - c.Assert(func() { pool.Recycle(nil) }, PanicMatches, "invalid restore worker") + require.PanicsWithValue(t, "invalid restore worker", func() { pool.Recycle(nil) }) } diff --git a/br/pkg/logutil/logging_test.go b/br/pkg/logutil/logging_test.go index fc4b415a89735..ff3fc14da8ddc 100644 --- a/br/pkg/logutil/logging_test.go +++ b/br/pkg/logutil/logging_test.go @@ -5,6 +5,7 @@ package logutil_test import ( "context" "fmt" + "strconv" "strings" "testing" "time" @@ -31,15 +32,15 @@ func assertTrimEqual(t *testing.T, f zapcore.Field, expect string) { func newFile(j int) *backuppb.File { return &backuppb.File{ - Name: fmt.Sprint(j), - StartKey: []byte(fmt.Sprint(j)), - EndKey: []byte(fmt.Sprint(j + 1)), + Name: strconv.Itoa(j), + StartKey: []byte(strconv.Itoa(j)), + EndKey: []byte(strconv.Itoa(j + 1)), TotalKvs: uint64(j), TotalBytes: uint64(j), StartVersion: uint64(j), EndVersion: uint64(j + 1), Crc64Xor: uint64(j), - Sha256: []byte(fmt.Sprint(j)), + Sha256: []byte(strconv.Itoa(j)), Cf: "write", Size_: uint64(j), } diff --git a/br/pkg/membuf/buffer.go b/br/pkg/membuf/buffer.go index 172d99baec9aa..49ffbae8afdf3 100644 --- a/br/pkg/membuf/buffer.go +++ b/br/pkg/membuf/buffer.go @@ -14,9 +14,11 @@ package membuf -const bigValueSize = 1 << 16 // 64K - -var allocBufLen = 1 << 20 // 1M +const ( + defaultPoolSize = 1024 + defaultBlockSize = 1 << 20 // 1M + defaultLargeAllocThreshold = 1 << 16 // 64K +) // Allocator is the abstract interface for allocating and freeing memory. type Allocator interface { @@ -38,30 +40,71 @@ func (stdAllocator) Free(_ []byte) {} // garbage collector which always release the memory so late. Use a fixed size chan to reuse // can decrease the memory usage to 1/3 compare with sync.Pool. type Pool struct { - allocator Allocator - recycleCh chan []byte + allocator Allocator + blockSize int + blockCache chan []byte + largeAllocThreshold int +} + +// Option configures a pool. +type Option func(p *Pool) + +// WithPoolSize configures how many blocks cached by this pool. +func WithPoolSize(size int) Option { + return func(p *Pool) { + p.blockCache = make(chan []byte, size) + } +} + +// WithBlockSize configures the size of each block. +func WithBlockSize(size int) Option { + return func(p *Pool) { + p.blockSize = size + } +} + +// WithAllocator specifies the allocator used by pool to allocate and free memory. +func WithAllocator(allocator Allocator) Option { + return func(p *Pool) { + p.allocator = allocator + } +} + +// WithLargeAllocThreshold configures the threshold for large allocation of a Buffer. +// If allocate size is larger than this threshold, bytes will be allocated directly +// by the make built-in function and won't be tracked by the pool. +func WithLargeAllocThreshold(threshold int) Option { + return func(p *Pool) { + p.largeAllocThreshold = threshold + } } // NewPool creates a new pool. -func NewPool(size int, allocator Allocator) *Pool { - return &Pool{ - allocator: allocator, - recycleCh: make(chan []byte, size), +func NewPool(opts ...Option) *Pool { + p := &Pool{ + allocator: stdAllocator{}, + blockSize: defaultBlockSize, + blockCache: make(chan []byte, defaultPoolSize), + largeAllocThreshold: defaultLargeAllocThreshold, + } + for _, opt := range opts { + opt(p) } + return p } func (p *Pool) acquire() []byte { select { - case b := <-p.recycleCh: + case b := <-p.blockCache: return b default: - return p.allocator.Alloc(allocBufLen) + return p.allocator.Alloc(p.blockSize) } } func (p *Pool) release(b []byte) { select { - case p.recycleCh <- b: + case p.blockCache <- b: default: p.allocator.Free(b) } @@ -72,10 +115,12 @@ func (p *Pool) NewBuffer() *Buffer { return &Buffer{pool: p, bufs: make([][]byte, 0, 128), curBufIdx: -1} } -var globalPool = NewPool(1024, stdAllocator{}) - -// NewBuffer creates a new buffer in global pool. -func NewBuffer() *Buffer { return globalPool.NewBuffer() } +func (p *Pool) Destroy() { + close(p.blockCache) + for b := range p.blockCache { + p.allocator.Free(b) + } +} // Buffer represents the reuse buffer. type Buffer struct { @@ -123,12 +168,12 @@ func (b *Buffer) Destroy() { // TotalSize represents the total memory size of this Buffer. func (b *Buffer) TotalSize() int64 { - return int64(len(b.bufs) * allocBufLen) + return int64(len(b.bufs) * b.pool.blockSize) } // AllocBytes allocates bytes with the given length. func (b *Buffer) AllocBytes(n int) []byte { - if n > bigValueSize { + if n > b.pool.largeAllocThreshold { return make([]byte, n) } if b.curIdx+n > b.curBufLen { diff --git a/br/pkg/membuf/buffer_test.go b/br/pkg/membuf/buffer_test.go index c5d095d299f9c..0d8e3ba06e609 100644 --- a/br/pkg/membuf/buffer_test.go +++ b/br/pkg/membuf/buffer_test.go @@ -21,10 +21,6 @@ import ( "github.com/stretchr/testify/require" ) -func init() { - allocBufLen = 1024 -} - type testAllocator struct { allocs int frees int @@ -41,7 +37,13 @@ func (t *testAllocator) Free(_ []byte) { func TestBufferPool(t *testing.T) { allocator := &testAllocator{} - pool := NewPool(2, allocator) + pool := NewPool( + WithPoolSize(2), + WithAllocator(allocator), + WithBlockSize(1024), + WithLargeAllocThreshold(512), + ) + defer pool.Destroy() bytesBuf := pool.NewBuffer() bytesBuf.AllocBytes(256) @@ -53,6 +55,10 @@ func TestBufferPool(t *testing.T) { bytesBuf.AllocBytes(767) require.Equal(t, 2, allocator.allocs) + largeBytes := bytesBuf.AllocBytes(513) + require.Equal(t, 513, len(largeBytes)) + require.Equal(t, 2, allocator.allocs) + require.Equal(t, 0, allocator.frees) bytesBuf.Destroy() require.Equal(t, 0, allocator.frees) @@ -67,17 +73,20 @@ func TestBufferPool(t *testing.T) { } func TestBufferIsolation(t *testing.T) { - bytesBuf := NewBuffer() + pool := NewPool(WithBlockSize(1024)) + defer pool.Destroy() + bytesBuf := pool.NewBuffer() defer bytesBuf.Destroy() b1 := bytesBuf.AllocBytes(16) b2 := bytesBuf.AllocBytes(16) - require.Equal(t, len(b1), cap(b1)) - require.Equal(t, len(b2), cap(b2)) + require.Len(t, b1, cap(b1)) + require.Len(t, b2, cap(b2)) _, err := rand.Read(b2) require.NoError(t, err) b3 := append([]byte(nil), b2...) b1 = append(b1, 0, 1, 2, 3) require.Equal(t, b3, b2) + require.NotEqual(t, b2, b1) } diff --git a/br/pkg/metautil/main_test.go b/br/pkg/metautil/main_test.go index e73ef73e16f2d..facb4e32cb101 100644 --- a/br/pkg/metautil/main_test.go +++ b/br/pkg/metautil/main_test.go @@ -23,8 +23,9 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/metautil/metafile_test.go b/br/pkg/metautil/metafile_test.go index 6fe79a2b8e610..70ebe5df90c89 100644 --- a/br/pkg/metautil/metafile_test.go +++ b/br/pkg/metautil/metafile_test.go @@ -187,18 +187,18 @@ func TestEncryptAndDecrypt(t *testing.T) { if v.method == encryptionpb.EncryptionMethod_UNKNOWN { require.Error(t, err) } else if v.method == encryptionpb.EncryptionMethod_PLAINTEXT { - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, originalData, encryptData) decryptData, err := Decrypt(encryptData, &cipher, iv) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, decryptData, originalData) } else { - require.Nil(t, err) + require.NoError(t, err) require.NotEqual(t, originalData, encryptData) decryptData, err := Decrypt(encryptData, &cipher, iv) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, decryptData, originalData) wrongCipher := backuppb.CipherInfo{ @@ -209,7 +209,7 @@ func TestEncryptAndDecrypt(t *testing.T) { if len(v.rightKey) != len(v.wrongKey) { require.Error(t, err) } else { - require.Nil(t, err) + require.NoError(t, err) require.NotEqual(t, decryptData, originalData) } } diff --git a/br/pkg/mock/mock_cluster.go b/br/pkg/mock/mock_cluster.go index d1ece26505d05..86cba3217a596 100644 --- a/br/pkg/mock/mock_cluster.go +++ b/br/pkg/mock/mock_cluster.go @@ -6,11 +6,8 @@ import ( "database/sql" "fmt" "io" - "net" "net/http" "net/http/pprof" - "net/url" - "strconv" "strings" "sync" "time" @@ -27,7 +24,6 @@ import ( "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" pd "github.com/tikv/pd/client" - "github.com/tikv/pd/pkg/tempurl" "go.uber.org/zap" ) @@ -87,52 +83,13 @@ func NewCluster() (*Cluster, error) { // Start runs a mock cluster. func (mock *Cluster) Start() error { - var ( - err error - statusURL *url.URL - addrURL *url.URL - ) - for i := 0; i < 10; i++ { - // retry 10 times to get available port - statusURL, err = url.Parse(tempurl.Alloc()) - if err != nil { - return errors.Trace(err) - } - listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%s", statusURL.Port())) - if err == nil { - // release port listening - listen.Close() - break - } - } - statusPort, err := strconv.ParseInt(statusURL.Port(), 10, 32) - if err != nil { - return errors.Trace(err) - } - - for i := 0; i < 10; i++ { - addrURL, err = url.Parse(tempurl.Alloc()) - if err != nil { - return errors.Trace(err) - } - listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%s", addrURL.Port())) - if err == nil { - // release port listening - listen.Close() - break - } - } - addrPort, err := strconv.ParseInt(addrURL.Port(), 10, 32) - if err != nil { - return errors.Trace(err) - } - _ = addrPort - + server.RunInGoTest = true mock.TiDBDriver = server.NewTiDBDriver(mock.Storage) cfg := config.NewConfig() - cfg.Port = uint(addrPort) + // let tidb random select a port + cfg.Port = 0 cfg.Store = "tikv" - cfg.Status.StatusPort = uint(statusPort) + cfg.Status.StatusPort = 0 cfg.Status.ReportStatus = true cfg.Socket = fmt.Sprintf("/tmp/tidb-mock-%d.sock", time.Now().UnixNano()) @@ -142,11 +99,11 @@ func (mock *Cluster) Start() error { } mock.Server = svr go func() { - if err1 := svr.Run(); err != nil { + if err1 := svr.Run(); err1 != nil { panic(err1) } }() - mock.DSN = waitUntilServerOnline(addrURL.Host, cfg.Status.StatusPort) + mock.DSN = waitUntilServerOnline("127.0.0.1", cfg.Status.StatusPort) return nil } @@ -207,7 +164,7 @@ func waitUntilServerOnline(addr string, statusPort uint) string { // connect http status statusURL := fmt.Sprintf("http://127.0.0.1:%d/status", statusPort) for retry = 0; retry < retryTime; retry++ { - resp, err := http.Get(statusURL) // nolint:noctx + resp, err := http.Get(statusURL) // nolint:noctx,gosec if err == nil { // Ignore errors. _, _ = io.ReadAll(resp.Body) diff --git a/br/pkg/mock/mock_cluster_test.go b/br/pkg/mock/mock_cluster_test.go index 01dde0c158901..8a81c6e1ef6ee 100644 --- a/br/pkg/mock/mock_cluster_test.go +++ b/br/pkg/mock/mock_cluster_test.go @@ -13,8 +13,9 @@ import ( func TestSmoke(t *testing.T) { defer goleak.VerifyNone( t, + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")) m, err := mock.NewCluster() require.NoError(t, err) diff --git a/br/pkg/mock/storage/storage.go b/br/pkg/mock/storage/storage.go index 71b2b72f67b13..32e96c1dd3448 100644 --- a/br/pkg/mock/storage/storage.go +++ b/br/pkg/mock/storage/storage.go @@ -14,30 +14,30 @@ import ( storage "github.com/pingcap/tidb/br/pkg/storage" ) -// MockExternalStorage is a mock of ExternalStorage interface +// MockExternalStorage is a mock of ExternalStorage interface. type MockExternalStorage struct { ctrl *gomock.Controller recorder *MockExternalStorageMockRecorder } -// MockExternalStorageMockRecorder is the mock recorder for MockExternalStorage +// MockExternalStorageMockRecorder is the mock recorder for MockExternalStorage. type MockExternalStorageMockRecorder struct { mock *MockExternalStorage } -// NewMockExternalStorage creates a new mock instance +// NewMockExternalStorage creates a new mock instance. func NewMockExternalStorage(ctrl *gomock.Controller) *MockExternalStorage { mock := &MockExternalStorage{ctrl: ctrl} mock.recorder = &MockExternalStorageMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockExternalStorage) EXPECT() *MockExternalStorageMockRecorder { return m.recorder } -// Create mocks base method +// Create mocks base method. func (m *MockExternalStorage) Create(arg0 context.Context, arg1 string) (storage.ExternalFileWriter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) @@ -46,13 +46,27 @@ func (m *MockExternalStorage) Create(arg0 context.Context, arg1 string) (storage return ret0, ret1 } -// Create indicates an expected call of Create +// Create indicates an expected call of Create. func (mr *MockExternalStorageMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockExternalStorage)(nil).Create), arg0, arg1) } -// FileExists mocks base method +// DeleteFile mocks base method. +func (m *MockExternalStorage) DeleteFile(arg0 context.Context, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteFile", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteFile indicates an expected call of DeleteFile. +func (mr *MockExternalStorageMockRecorder) DeleteFile(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFile", reflect.TypeOf((*MockExternalStorage)(nil).DeleteFile), arg0, arg1) +} + +// FileExists mocks base method. func (m *MockExternalStorage) FileExists(arg0 context.Context, arg1 string) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FileExists", arg0, arg1) @@ -61,13 +75,13 @@ func (m *MockExternalStorage) FileExists(arg0 context.Context, arg1 string) (boo return ret0, ret1 } -// FileExists indicates an expected call of FileExists +// FileExists indicates an expected call of FileExists. func (mr *MockExternalStorageMockRecorder) FileExists(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FileExists", reflect.TypeOf((*MockExternalStorage)(nil).FileExists), arg0, arg1) } -// Open mocks base method +// Open mocks base method. func (m *MockExternalStorage) Open(arg0 context.Context, arg1 string) (storage.ExternalFileReader, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Open", arg0, arg1) @@ -76,13 +90,13 @@ func (m *MockExternalStorage) Open(arg0 context.Context, arg1 string) (storage.E return ret0, ret1 } -// Open indicates an expected call of Open +// Open indicates an expected call of Open. func (mr *MockExternalStorageMockRecorder) Open(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Open", reflect.TypeOf((*MockExternalStorage)(nil).Open), arg0, arg1) } -// ReadFile mocks base method +// ReadFile mocks base method. func (m *MockExternalStorage) ReadFile(arg0 context.Context, arg1 string) ([]byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadFile", arg0, arg1) @@ -91,13 +105,27 @@ func (m *MockExternalStorage) ReadFile(arg0 context.Context, arg1 string) ([]byt return ret0, ret1 } -// ReadFile indicates an expected call of ReadFile +// ReadFile indicates an expected call of ReadFile. func (mr *MockExternalStorageMockRecorder) ReadFile(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadFile", reflect.TypeOf((*MockExternalStorage)(nil).ReadFile), arg0, arg1) } -// URI mocks base method +// Rename mocks base method. +func (m *MockExternalStorage) Rename(arg0 context.Context, arg1, arg2 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Rename", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// Rename indicates an expected call of Rename. +func (mr *MockExternalStorageMockRecorder) Rename(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rename", reflect.TypeOf((*MockExternalStorage)(nil).Rename), arg0, arg1, arg2) +} + +// URI mocks base method. func (m *MockExternalStorage) URI() string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "URI") @@ -105,13 +133,13 @@ func (m *MockExternalStorage) URI() string { return ret0 } -// URI indicates an expected call of URI +// URI indicates an expected call of URI. func (mr *MockExternalStorageMockRecorder) URI() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "URI", reflect.TypeOf((*MockExternalStorage)(nil).URI)) } -// WalkDir mocks base method +// WalkDir mocks base method. func (m *MockExternalStorage) WalkDir(arg0 context.Context, arg1 *storage.WalkOption, arg2 func(string, int64) error) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WalkDir", arg0, arg1, arg2) @@ -119,13 +147,13 @@ func (m *MockExternalStorage) WalkDir(arg0 context.Context, arg1 *storage.WalkOp return ret0 } -// WalkDir indicates an expected call of WalkDir +// WalkDir indicates an expected call of WalkDir. func (mr *MockExternalStorageMockRecorder) WalkDir(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WalkDir", reflect.TypeOf((*MockExternalStorage)(nil).WalkDir), arg0, arg1, arg2) } -// WriteFile mocks base method +// WriteFile mocks base method. func (m *MockExternalStorage) WriteFile(arg0 context.Context, arg1 string, arg2 []byte) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteFile", arg0, arg1, arg2) @@ -133,22 +161,8 @@ func (m *MockExternalStorage) WriteFile(arg0 context.Context, arg1 string, arg2 return ret0 } -// WriteFile indicates an expected call of WriteFile +// WriteFile indicates an expected call of WriteFile. func (mr *MockExternalStorageMockRecorder) WriteFile(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteFile", reflect.TypeOf((*MockExternalStorage)(nil).WriteFile), arg0, arg1, arg2) } - -// DeleteFile mocks base method. -func (m *MockExternalStorage) DeleteFile(ctx context.Context, name string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteFile", ctx, name) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteFile indicates an expected call of DeleteFile. -func (mr *MockExternalStorageMockRecorder) DeleteFile(ctx, name interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFile", reflect.TypeOf((*MockExternalStorage)(nil).DeleteFile), ctx, name) -} diff --git a/br/pkg/pdutil/main_test.go b/br/pkg/pdutil/main_test.go index 861c3921a3eb3..f87dd67ce2d47 100644 --- a/br/pkg/pdutil/main_test.go +++ b/br/pkg/pdutil/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/br/pkg/pdutil/pd.go b/br/pkg/pdutil/pd.go index 3f4c45d1deefa..20809385bb29c 100644 --- a/br/pkg/pdutil/pd.go +++ b/br/pkg/pdutil/pd.go @@ -24,9 +24,9 @@ import ( berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/httputil" "github.com/pingcap/tidb/br/pkg/lightning/common" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/util/codec" pd "github.com/tikv/pd/client" - pdapi "github.com/tikv/pd/server/api" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -350,12 +350,12 @@ func (p *PdController) getRegionCountWith( } // GetStoreInfo returns the info of store with the specified id. -func (p *PdController) GetStoreInfo(ctx context.Context, storeID uint64) (*pdapi.StoreInfo, error) { +func (p *PdController) GetStoreInfo(ctx context.Context, storeID uint64) (*pdtypes.StoreInfo, error) { return p.getStoreInfoWith(ctx, pdRequest, storeID) } func (p *PdController) getStoreInfoWith( - ctx context.Context, get pdHTTPRequest, storeID uint64) (*pdapi.StoreInfo, error) { + ctx context.Context, get pdHTTPRequest, storeID uint64) (*pdtypes.StoreInfo, error) { var err error for _, addr := range p.addrs { query := fmt.Sprintf( @@ -366,7 +366,7 @@ func (p *PdController) getStoreInfoWith( err = e continue } - store := pdapi.StoreInfo{} + store := pdtypes.StoreInfo{} err = json.Unmarshal(v, &store) if err != nil { return nil, errors.Trace(err) @@ -378,7 +378,7 @@ func (p *PdController) getStoreInfoWith( func (p *PdController) doPauseSchedulers(ctx context.Context, schedulers []string, post pdHTTPRequest) ([]string, error) { // pause this scheduler with 300 seconds - body, err := json.Marshal(pauseSchedulerBody{Delay: int64(pauseTimeout)}) + body, err := json.Marshal(pauseSchedulerBody{Delay: int64(pauseTimeout.Seconds())}) if err != nil { return nil, errors.Trace(err) } @@ -703,7 +703,9 @@ func (p *PdController) doRemoveSchedulersWith( // Close close the connection to pd. func (p *PdController) Close() { p.pdClient.Close() - close(p.schedulerPauseCh) + if p.schedulerPauseCh != nil { + close(p.schedulerPauseCh) + } } // FetchPDVersion get pd version diff --git a/br/pkg/pdutil/pd_serial_test.go b/br/pkg/pdutil/pd_serial_test.go index c76e49cd70c61..05f0d34aa2ef2 100644 --- a/br/pkg/pdutil/pd_serial_test.go +++ b/br/pkg/pdutil/pd_serial_test.go @@ -17,12 +17,9 @@ import ( "github.com/coreos/go-semver/semver" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/metapb" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/util/codec" "github.com/stretchr/testify/require" - "github.com/tikv/pd/pkg/typeutil" - "github.com/tikv/pd/server/api" - "github.com/tikv/pd/server/core" - "github.com/tikv/pd/server/statistics" ) func TestScheduler(t *testing.T) { @@ -106,26 +103,26 @@ func TestGetClusterVersion(t *testing.T) { } func TestRegionCount(t *testing.T) { - regions := core.NewRegionsInfo() - regions.SetRegion(core.NewRegionInfo(&metapb.Region{ + regions := &pdtypes.RegionTree{} + regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{ Id: 1, StartKey: codec.EncodeBytes(nil, []byte{1, 1}), EndKey: codec.EncodeBytes(nil, []byte{1, 3}), RegionEpoch: &metapb.RegionEpoch{}, }, nil)) - regions.SetRegion(core.NewRegionInfo(&metapb.Region{ + regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{ Id: 2, StartKey: codec.EncodeBytes(nil, []byte{1, 3}), EndKey: codec.EncodeBytes(nil, []byte{1, 5}), RegionEpoch: &metapb.RegionEpoch{}, }, nil)) - regions.SetRegion(core.NewRegionInfo(&metapb.Region{ + regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{ Id: 3, StartKey: codec.EncodeBytes(nil, []byte{2, 3}), EndKey: codec.EncodeBytes(nil, []byte{3, 4}), RegionEpoch: &metapb.RegionEpoch{}, }, nil)) - require.Equal(t, 3, regions.Len()) + require.Equal(t, 3, len(regions.Regions)) mock := func( _ context.Context, addr string, prefix string, _ *http.Client, _ string, _ io.Reader, @@ -138,7 +135,7 @@ func TestRegionCount(t *testing.T) { t.Log(hex.EncodeToString([]byte(start))) t.Log(hex.EncodeToString([]byte(end))) scanRegions := regions.ScanRange([]byte(start), []byte(end), 0) - stats := statistics.RegionStats{Count: len(scanRegions)} + stats := pdtypes.RegionStats{Count: len(scanRegions)} ret, err := json.Marshal(stats) require.NoError(t, err) return ret, nil @@ -206,12 +203,12 @@ func TestPDRequestRetry(t *testing.T) { } func TestStoreInfo(t *testing.T) { - storeInfo := api.StoreInfo{ - Status: &api.StoreStatus{ - Capacity: typeutil.ByteSize(1024), - Available: typeutil.ByteSize(1024), + storeInfo := pdtypes.StoreInfo{ + Status: &pdtypes.StoreStatus{ + Capacity: pdtypes.ByteSize(1024), + Available: pdtypes.ByteSize(1024), }, - Store: &api.MetaStore{ + Store: &pdtypes.MetaStore{ StateName: "Tombstone", }, } diff --git a/br/pkg/pdutil/utils.go b/br/pkg/pdutil/utils.go index d06ca08891a31..1ea6e8e0d113d 100644 --- a/br/pkg/pdutil/utils.go +++ b/br/pkg/pdutil/utils.go @@ -8,16 +8,16 @@ import ( "crypto/tls" "encoding/hex" "encoding/json" - "fmt" "net/http" + "strconv" "strings" "github.com/pingcap/errors" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/httputil" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/tablecodec" - "github.com/tikv/pd/pkg/codec" - "github.com/tikv/pd/server/schedule/placement" + "github.com/pingcap/tidb/util/codec" ) // UndoFunc is a 'undo' operation of some undoable command. @@ -36,7 +36,7 @@ const ( func ResetTS(ctx context.Context, pdAddr string, ts uint64, tlsConf *tls.Config) error { payload, err := json.Marshal(struct { TSO string `json:"tso,omitempty"` - }{TSO: fmt.Sprintf("%d", ts)}) + }{TSO: strconv.FormatUint(ts, 10)}) if err != nil { return errors.Trace(err) } @@ -65,7 +65,7 @@ func ResetTS(ctx context.Context, pdAddr string, ts uint64, tlsConf *tls.Config) } // GetPlacementRules return the current placement rules. -func GetPlacementRules(ctx context.Context, pdAddr string, tlsConf *tls.Config) ([]placement.Rule, error) { +func GetPlacementRules(ctx context.Context, pdAddr string, tlsConf *tls.Config) ([]pdtypes.Rule, error) { cli := httputil.NewClient(tlsConf) prefix := "http://" if tlsConf != nil { @@ -87,12 +87,12 @@ func GetPlacementRules(ctx context.Context, pdAddr string, tlsConf *tls.Config) return nil, errors.Trace(err) } if resp.StatusCode == http.StatusPreconditionFailed { - return []placement.Rule{}, nil + return []pdtypes.Rule{}, nil } if resp.StatusCode != http.StatusOK { return nil, errors.Annotatef(berrors.ErrPDInvalidResponse, "get placement rules failed: resp=%v, err=%v, code=%d", buf.String(), err, resp.StatusCode) } - var rules []placement.Rule + var rules []pdtypes.Rule err = json.Unmarshal(buf.Bytes(), &rules) if err != nil { return nil, errors.Trace(err) @@ -101,13 +101,13 @@ func GetPlacementRules(ctx context.Context, pdAddr string, tlsConf *tls.Config) } // SearchPlacementRule returns the placement rule matched to the table or nil. -func SearchPlacementRule(tableID int64, placementRules []placement.Rule, role placement.PeerRoleType) *placement.Rule { +func SearchPlacementRule(tableID int64, placementRules []pdtypes.Rule, role pdtypes.PeerRoleType) *pdtypes.Rule { for _, rule := range placementRules { key, err := hex.DecodeString(rule.StartKeyHex) if err != nil { continue } - _, decoded, err := codec.DecodeBytes(key) + _, decoded, err := codec.DecodeBytes(key, nil) if err != nil { continue } diff --git a/br/pkg/restore/batcher_test.go b/br/pkg/restore/batcher_test.go index fca4ec37a9479..2c182cb0351cc 100644 --- a/br/pkg/restore/batcher_test.go +++ b/br/pkg/restore/batcher_test.go @@ -6,9 +6,9 @@ import ( "bytes" "context" "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/log" @@ -16,11 +16,10 @@ import ( "github.com/pingcap/tidb/br/pkg/restore" "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/parser/model" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) -type testBatcherSuite struct{} - type drySender struct { mu *sync.Mutex @@ -151,8 +150,6 @@ func (sender *drySender) BatchCount() int { return sender.nBatch } -var _ = Suite(&testBatcherSuite{}) - func fakeTableWithRange(id int64, rngs []rtree.Range) restore.TableWithRange { tbl := &metautil.Table{ DB: &model.DBInfo{}, @@ -197,7 +194,7 @@ func join(nested [][]rtree.Range) (plain []rtree.Range) { } // TestBasic tests basic workflow of batcher. -func (*testBatcherSuite) TestBasic(c *C) { +func TestBasic(t *testing.T) { ctx := context.Background() errCh := make(chan error, 8) sender := newDrySender() @@ -222,15 +219,15 @@ func (*testBatcherSuite) TestBasic(c *C) { batcher.Close() rngs := sender.Ranges() - c.Assert(join(tableRanges), DeepEquals, rngs) + require.Equal(t, rngs, join(tableRanges)) select { case err := <-errCh: - c.Fatal(errors.Trace(err)) + t.Fatal(errors.Trace(err)) default: } } -func (*testBatcherSuite) TestAutoSend(c *C) { +func TestAutoSend(t *testing.T) { ctx := context.Background() errCh := make(chan error, 8) sender := newDrySender() @@ -241,27 +238,27 @@ func (*testBatcherSuite) TestAutoSend(c *C) { simpleTable := fakeTableWithRange(1, []rtree.Range{fakeRange("caa", "cab"), fakeRange("cac", "cad")}) batcher.Add(simpleTable) - c.Assert(batcher.Len(), Greater, 0) + require.Greater(t, batcher.Len(), 0) // enable auto commit. batcher.EnableAutoCommit(ctx, 100*time.Millisecond) time.Sleep(200 * time.Millisecond) - c.Assert(sender.RangeLen(), Greater, 0) - c.Assert(batcher.Len(), Equals, 0) + require.Greater(t, sender.RangeLen(), 0) + require.Equal(t, 0, batcher.Len()) batcher.Close() rngs := sender.Ranges() - c.Assert(rngs, DeepEquals, simpleTable.Range) + require.Equal(t, simpleTable.Range, rngs) select { case err := <-errCh: - c.Fatal(errors.Trace(err)) + t.Fatal(errors.Trace(err)) default: } } -func (*testBatcherSuite) TestSplitRangeOnSameTable(c *C) { +func TestSplitRangeOnSameTable(t *testing.T) { ctx := context.Background() errCh := make(chan error, 8) sender := newDrySender() @@ -278,18 +275,18 @@ func (*testBatcherSuite) TestSplitRangeOnSameTable(c *C) { batcher.Add(simpleTable) batcher.Close() - c.Assert(sender.BatchCount(), Equals, 4) + require.Equal(t, 4, sender.BatchCount()) rngs := sender.Ranges() - c.Assert(rngs, DeepEquals, simpleTable.Range) + require.Equal(t, simpleTable.Range, rngs) select { case err := <-errCh: - c.Fatal(errors.Trace(err)) + t.Fatal(errors.Trace(err)) default: } } -func (*testBatcherSuite) TestRewriteRules(c *C) { +func TestRewriteRules(t *testing.T) { tableRanges := [][]rtree.Range{ {fakeRange("aaa", "aab")}, {fakeRange("baa", "bab"), fakeRange("bac", "bad")}, @@ -322,28 +319,28 @@ func (*testBatcherSuite) TestRewriteRules(c *C) { batcher.Add(tables[0]) waitForSend() - c.Assert(sender.RangeLen(), Equals, 0) + require.Equal(t, 0, sender.RangeLen()) batcher.Add(tables[1]) waitForSend() - c.Assert(sender.HasRewriteRuleOfKey("a"), IsTrue) - c.Assert(sender.HasRewriteRuleOfKey("b"), IsTrue) - c.Assert(manager.Has(tables[1]), IsTrue) - c.Assert(sender.RangeLen(), Equals, 2) + require.True(t, sender.HasRewriteRuleOfKey("a")) + require.True(t, sender.HasRewriteRuleOfKey("b")) + require.True(t, manager.Has(tables[1])) + require.Equal(t, 2, sender.RangeLen()) batcher.Add(tables[2]) batcher.Close() - c.Assert(sender.HasRewriteRuleOfKey("c"), IsTrue) - c.Assert(sender.Ranges(), DeepEquals, join(tableRanges)) + require.True(t, sender.HasRewriteRuleOfKey("c")) + require.Equal(t, join(tableRanges), sender.Ranges()) select { case err := <-errCh: - c.Fatal(errors.Trace(err)) + t.Fatal(errors.Trace(err)) default: } } -func (*testBatcherSuite) TestBatcherLen(c *C) { +func TestBatcherLen(t *testing.T) { ctx := context.Background() errCh := make(chan error, 8) sender := newDrySender() @@ -367,21 +364,21 @@ func (*testBatcherSuite) TestBatcherLen(c *C) { batcher.Add(simpleTable) waitForSend() - c.Assert(batcher.Len(), Equals, 8) - c.Assert(manager.Has(simpleTable), IsFalse) - c.Assert(manager.Has(simpleTable2), IsFalse) + require.Equal(t, 8, batcher.Len()) + require.False(t, manager.Has(simpleTable)) + require.False(t, manager.Has(simpleTable2)) batcher.Add(simpleTable2) waitForSend() - c.Assert(batcher.Len(), Equals, 1) - c.Assert(manager.Has(simpleTable2), IsTrue) - c.Assert(manager.Has(simpleTable), IsFalse) + require.Equal(t, 1, batcher.Len()) + require.True(t, manager.Has(simpleTable2)) + require.False(t, manager.Has(simpleTable)) batcher.Close() - c.Assert(batcher.Len(), Equals, 0) + require.Equal(t, 0, batcher.Len()) select { case err := <-errCh: - c.Fatal(errors.Trace(err)) + t.Fatal(errors.Trace(err)) default: } } diff --git a/br/pkg/restore/client.go b/br/pkg/restore/client.go index c62eb1c3af6d0..7fa273b827a1c 100644 --- a/br/pkg/restore/client.go +++ b/br/pkg/restore/client.go @@ -17,6 +17,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/metapb" @@ -29,6 +30,7 @@ import ( "github.com/pingcap/tidb/br/pkg/metautil" "github.com/pingcap/tidb/br/pkg/pdutil" "github.com/pingcap/tidb/br/pkg/redact" + "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/summary" "github.com/pingcap/tidb/br/pkg/utils" @@ -36,11 +38,11 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/statistics/handle" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" - "github.com/tikv/pd/server/schedule/placement" "go.uber.org/zap" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -52,6 +54,13 @@ import ( // defaultChecksumConcurrency is the default number of the concurrent // checksum tasks. const defaultChecksumConcurrency = 64 +const defaultDDLConcurrency = 16 +const minBatchDdlSize = 1 + +const ( + strictPlacementPolicyMode = "STRICT" + ignorePlacementPolicyMode = "IGNORE" +) // Client sends requests to restore files. type Client struct { @@ -62,8 +71,10 @@ type Client struct { tlsConf *tls.Config keepaliveConf keepalive.ClientParameters - databases map[string]*utils.Database - ddlJobs []*model.Job + databases map[string]*utils.Database + ddlJobs []*model.Job + // ddlJobsMap record the tables' auto id need to restore after create table + ddlJobsMap map[UniqueTableName]bool backupMeta *backuppb.BackupMeta // TODO Remove this field or replace it with a []*DB, // since https://github.com/pingcap/br/pull/377 needs more DBs to speed up DDL execution. @@ -74,7 +85,10 @@ type Client struct { // Before you do it, you can firstly read discussions at // https://github.com/pingcap/br/pull/377#discussion_r446594501, // this probably isn't as easy as it seems like (however, not hard, too :D) - db *DB + db *DB + + // use db pool to speed up restoration in BR binary mode. + dbPool []*DB rateLimit uint64 isOnline bool noSchema bool @@ -83,8 +97,6 @@ type Client struct { restoreStores []uint64 cipher *backuppb.CipherInfo - storage storage.ExternalStorage - backend *backuppb.StorageBackend switchModeInterval time.Duration switchCh chan struct{} @@ -93,41 +105,87 @@ type Client struct { // and restore stats with #dump.LoadStatsFromJSON statsHandler *handle.Handle dom *domain.Domain + + batchDdlSize uint + + // correspond to --tidb-placement-mode config. + // STRICT(default) means policy related SQL can be executed in tidb. + // IGNORE means policy related SQL will be ignored. + policyMode string + + // policy name -> policy info + policyMap *sync.Map + + supportPolicy bool } // NewRestoreClient returns a new RestoreClient. func NewRestoreClient( - g glue.Glue, pdClient pd.Client, - store kv.Storage, tlsConf *tls.Config, keepaliveConf keepalive.ClientParameters, -) (*Client, error) { - db, err := NewDB(g, store) + isRawKv bool, +) *Client { + return &Client{ + pdClient: pdClient, + toolClient: NewSplitClient(pdClient, tlsConf, isRawKv), + tlsConf: tlsConf, + keepaliveConf: keepaliveConf, + switchCh: make(chan struct{}), + } +} + +// Init create db connection and domain for storage. +func (rc *Client) Init(g glue.Glue, store kv.Storage) error { + // setDB must happen after set PolicyMode. + // we will use policyMode to set session variables. + var err error + rc.db, rc.supportPolicy, err = NewDB(g, store, rc.policyMode) if err != nil { - return nil, errors.Trace(err) + return errors.Trace(err) } - dom, err := g.GetDomain(store) + rc.dom, err = g.GetDomain(store) if err != nil { - return nil, errors.Trace(err) + return errors.Trace(err) } - - var statsHandle *handle.Handle // tikv.Glue will return nil, tidb.Glue will return available domain - if dom != nil { - statsHandle = dom.StatsHandle() + if rc.dom != nil { + rc.statsHandler = rc.dom.StatsHandle() + } + + // Only in binary we can use multi-thread sessions to create tables. + // so use OwnStorage() to tell whether we are use binary or SQL. + if g.OwnsStorage() { + // Maybe allow user modify the DDL concurrency isn't necessary, + // because executing DDL is really I/O bound (or, algorithm bound?), + // and we cost most of time at waiting DDL jobs be enqueued. + // So these jobs won't be faster or slower when machine become faster or slower, + // hence make it a fixed value would be fine. + rc.dbPool, err = makeDBPool(defaultDDLConcurrency, func() (*DB, error) { + db, _, err := NewDB(g, store, rc.policyMode) + return db, err + }) + if err != nil { + log.Warn("create session pool failed, we will send DDLs only by created sessions", + zap.Error(err), + zap.Int("sessionCount", len(rc.dbPool)), + ) + } } + return errors.Trace(err) +} - return &Client{ - pdClient: pdClient, - toolClient: NewSplitClient(pdClient, tlsConf), - db: db, - tlsConf: tlsConf, - keepaliveConf: keepaliveConf, - switchCh: make(chan struct{}), - dom: dom, - statsHandler: statsHandle, - }, nil +// SetPlacementPolicyMode to policy mode. +func (rc *Client) SetPlacementPolicyMode(withPlacementPolicy string) { + switch strings.ToUpper(withPlacementPolicy) { + case strictPlacementPolicyMode: + rc.policyMode = strictPlacementPolicyMode + case ignorePlacementPolicyMode: + rc.policyMode = ignorePlacementPolicyMode + default: + rc.policyMode = strictPlacementPolicyMode + } + log.Info("set placement policy mode", zap.String("mode", rc.policyMode)) } // SetRateLimit to set rateLimit. @@ -139,15 +197,19 @@ func (rc *Client) SetCrypter(crypter *backuppb.CipherInfo) { rc.cipher = crypter } -// SetStorage set ExternalStorage for client. -func (rc *Client) SetStorage(ctx context.Context, backend *backuppb.StorageBackend, opts *storage.ExternalStorageOptions) error { - var err error - rc.storage, err = storage.New(ctx, backend, opts) - if err != nil { - return errors.Trace(err) - } - rc.backend = backend - return nil +// SetPolicyMap set policyMap. +func (rc *Client) SetPolicyMap(p *sync.Map) { + rc.policyMap = p +} + +// GetPolicyMap set policyMap. +func (rc *Client) GetPolicyMap() *sync.Map { + return rc.policyMap +} + +// GetSupportPolicy tells whether target tidb support placement policy. +func (rc *Client) GetSupportPolicy() bool { + return rc.supportPolicy } // GetPDClient returns a pd client. @@ -165,6 +227,14 @@ func (rc *Client) SetSwitchModeInterval(interval time.Duration) { rc.switchModeInterval = interval } +func (rc *Client) SetBatchDdlSize(batchDdlsize uint) { + rc.batchDdlSize = batchDdlsize +} + +func (rc *Client) GetBatchDdlSize() uint { + return rc.batchDdlSize +} + // Close a client. func (rc *Client) Close() { // rc.db can be nil in raw kv mode. @@ -205,7 +275,7 @@ func (rc *Client) InitBackupMeta( rc.backupMeta = backupMeta log.Info("load backupmeta", zap.Int("databases", len(rc.databases)), zap.Int("jobs", len(rc.ddlJobs))) - metaClient := NewSplitClient(rc.pdClient, rc.tlsConf) + metaClient := NewSplitClient(rc.pdClient, rc.tlsConf, rc.backupMeta.IsRawKv) importCli := NewImportClient(metaClient, rc.tlsConf, rc.keepaliveConf) rc.fileImporter = NewFileImporter(metaClient, importCli, backend, rc.backupMeta.IsRawKv, rc.rateLimit) return rc.fileImporter.CheckMultiIngestSupport(c, rc.pdClient) @@ -310,8 +380,8 @@ func (rc *Client) ResetTS(ctx context.Context, pdAddrs []string) error { } // GetPlacementRules return the current placement rules. -func (rc *Client) GetPlacementRules(ctx context.Context, pdAddrs []string) ([]placement.Rule, error) { - var placementRules []placement.Rule +func (rc *Client) GetPlacementRules(ctx context.Context, pdAddrs []string) ([]pdtypes.Rule, error) { + var placementRules []pdtypes.Rule i := 0 errRetry := utils.WithRetry(ctx, func() error { var err error @@ -337,6 +407,20 @@ func (rc *Client) GetDatabase(name string) *utils.Database { return rc.databases[name] } +// GetPlacementPolicies returns policies. +func (rc *Client) GetPlacementPolicies() (*sync.Map, error) { + policies := &sync.Map{} + for _, p := range rc.backupMeta.Policies { + policyInfo := &model.PolicyInfo{} + err := json.Unmarshal(p.Info, policyInfo) + if err != nil { + return nil, errors.Trace(err) + } + policies.Store(policyInfo.Name.L, policyInfo) + } + return policies, nil +} + // GetDDLJobs returns ddl jobs. func (rc *Client) GetDDLJobs() []*model.Job { return rc.ddlJobs @@ -356,12 +440,39 @@ func (rc *Client) GetTableSchema( return table.Meta(), nil } +// CreatePolicies creates all policies in full restore. +func (rc *Client) CreatePolicies(ctx context.Context, policyMap *sync.Map) error { + var err error + policyMap.Range(func(key, value interface{}) bool { + e := rc.db.CreatePlacementPolicy(ctx, value.(*model.PolicyInfo)) + if e != nil { + err = e + return false + } + return true + }) + return err +} + // CreateDatabase creates a database. func (rc *Client) CreateDatabase(ctx context.Context, db *model.DBInfo) error { if rc.IsSkipCreateSQL() { log.Info("skip create database", zap.Stringer("database", db.Name)) return nil } + + if !rc.supportPolicy { + log.Info("set placementPolicyRef to nil when target tidb not support policy", + zap.Stringer("database", db.Name)) + db.PlacementPolicyRef = nil + } + + if db.PlacementPolicyRef != nil { + if err := rc.db.ensurePlacementPolicy(ctx, db.PlacementPolicyRef.Name, rc.policyMap); err != nil { + return errors.Trace(err) + } + } + return rc.db.CreateDatabase(ctx, db) } @@ -380,7 +491,7 @@ func (rc *Client) CreateTables( for i, t := range tables { tbMapping[t.Info.Name.String()] = i } - dataCh := rc.GoCreateTables(context.TODO(), dom, tables, newTS, nil, errCh) + dataCh := rc.GoCreateTables(context.TODO(), dom, tables, newTS, errCh) for et := range dataCh { rules := et.RewriteRule rewriteRules.Data = append(rewriteRules.Data, rules.Data...) @@ -400,6 +511,46 @@ func (rc *Client) CreateTables( } return rewriteRules, newTables, nil } +func (rc *Client) createTables( + ctx context.Context, + db *DB, + dom *domain.Domain, + tables []*metautil.Table, + newTS uint64, +) ([]CreatedTable, error) { + log.Info("client to create tables") + if rc.IsSkipCreateSQL() { + log.Info("skip create table and alter autoIncID") + } else { + err := db.CreateTables(ctx, tables, rc.GetDDLJobsMap(), rc.GetSupportPolicy(), rc.GetPolicyMap()) + if err != nil { + return nil, errors.Trace(err) + } + } + cts := make([]CreatedTable, 0, len(tables)) + for _, table := range tables { + newTableInfo, err := rc.GetTableSchema(dom, table.DB.Name, table.Info.Name) + if err != nil { + return nil, errors.Trace(err) + } + if newTableInfo.IsCommonHandle != table.Info.IsCommonHandle { + return nil, errors.Annotatef(berrors.ErrRestoreModeMismatch, + "Clustered index option mismatch. Restored cluster's @@tidb_enable_clustered_index should be %v (backup table = %v, created table = %v).", + transferBoolToValue(table.Info.IsCommonHandle), + table.Info.IsCommonHandle, + newTableInfo.IsCommonHandle) + } + rules := GetRewriteRules(newTableInfo, table.Info, newTS) + ct := CreatedTable{ + RewriteRule: rules, + Table: newTableInfo, + OldTable: table, + } + log.Debug("new created tables", zap.Any("table", ct)) + cts = append(cts, ct) + } + return cts, nil +} func (rc *Client) createTable( ctx context.Context, @@ -407,12 +558,11 @@ func (rc *Client) createTable( dom *domain.Domain, table *metautil.Table, newTS uint64, - ddlTables map[UniqueTableName]bool, ) (CreatedTable, error) { if rc.IsSkipCreateSQL() { log.Info("skip create table and alter autoIncID", zap.Stringer("table", table.Info.Name)) } else { - err := db.CreateTable(ctx, table, ddlTables) + err := db.CreateTable(ctx, table, rc.GetDDLJobsMap(), rc.GetSupportPolicy(), rc.GetPolicyMap()) if err != nil { return CreatedTable{}, errors.Trace(err) } @@ -445,13 +595,12 @@ func (rc *Client) GoCreateTables( dom *domain.Domain, tables []*metautil.Table, newTS uint64, - dbPool []*DB, errCh chan<- error, ) <-chan CreatedTable { // Could we have a smaller size of tables? log.Info("start create tables") - ddlTables := rc.DDLJobsMap() + rc.GenerateDDLJobsMap() if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { span1 := span.Tracer().StartSpan("Client.GoCreateTables", opentracing.ChildOf(span.Context())) defer span1.Finish() @@ -459,13 +608,36 @@ func (rc *Client) GoCreateTables( } outCh := make(chan CreatedTable, len(tables)) rater := logutil.TraceRateOver(logutil.MetricTableCreatedCounter) + + var err error + + if rc.batchDdlSize > minBatchDdlSize && len(rc.dbPool) > 0 { + + err = rc.createTablesInWorkerPool(ctx, dom, tables, newTS, outCh) + + if err == nil { + defer log.Debug("all tables are created") + close(outCh) + return outCh + // fall back to old create table (sequential create table) + } else if utils.FallBack2CreateTable(err) { + log.Info("fall back to the sequential create table") + } else { + errCh <- err + close(outCh) + return outCh + } + + } + createOneTable := func(c context.Context, db *DB, t *metautil.Table) error { select { case <-c.Done(): return c.Err() default: + } - rt, err := rc.createTable(c, db, dom, t, newTS, ddlTables) + rt, err := rc.createTable(c, db, dom, t, newTS) if err != nil { log.Error("create table failed", zap.Error(err), @@ -488,8 +660,8 @@ func (rc *Client) GoCreateTables( defer close(outCh) defer log.Debug("all tables are created") var err error - if len(dbPool) > 0 { - err = rc.createTablesWithDBPool(ctx, createOneTable, tables, dbPool) + if len(rc.dbPool) > 0 { + err = rc.createTablesWithDBPool(ctx, createOneTable, tables) } else { err = rc.createTablesWithSoleDB(ctx, createOneTable, tables) } @@ -497,6 +669,7 @@ func (rc *Client) GoCreateTables( errCh <- err } }() + return outCh } @@ -513,19 +686,59 @@ func (rc *Client) createTablesWithSoleDB(ctx context.Context, func (rc *Client) createTablesWithDBPool(ctx context.Context, createOneTable func(ctx context.Context, db *DB, t *metautil.Table) error, - tables []*metautil.Table, dbPool []*DB) error { + tables []*metautil.Table) error { eg, ectx := errgroup.WithContext(ctx) - workers := utils.NewWorkerPool(uint(len(dbPool)), "DDL workers") + workers := utils.NewWorkerPool(uint(len(rc.dbPool)), "DDL workers") for _, t := range tables { table := t workers.ApplyWithIDInErrorGroup(eg, func(id uint64) error { - db := dbPool[id%uint64(len(dbPool))] + db := rc.dbPool[id%uint64(len(rc.dbPool))] return createOneTable(ectx, db, table) }) } return eg.Wait() } +func (rc *Client) createTablesInWorkerPool(ctx context.Context, dom *domain.Domain, tables []*metautil.Table, newTS uint64, outCh chan<- CreatedTable) error { + eg, ectx := errgroup.WithContext(ctx) + rater := logutil.TraceRateOver(logutil.MetricTableCreatedCounter) + workers := utils.NewWorkerPool(uint(len(rc.dbPool)), "Create Tables Worker") + numOfTables := len(tables) + + for lastSent := 0; lastSent < numOfTables; lastSent += int(rc.batchDdlSize) { + end := utils.MinInt(lastSent+int(rc.batchDdlSize), len(tables)) + log.Info("create tables", zap.Int("table start", lastSent), zap.Int("table end", end)) + + tableSlice := tables[lastSent:end] + workers.ApplyWithIDInErrorGroup(eg, func(id uint64) error { + db := rc.dbPool[id%uint64(len(rc.dbPool))] + cts, err := rc.createTables(ectx, db, dom, tableSlice, newTS) // ddl job for [lastSent:i) + failpoint.Inject("restore-createtables-error", func(val failpoint.Value) { + if val.(bool) { + err = errors.New("sample error without extra message") + } + }) + if err != nil { + log.Error("create tables fail") + return err + } + for _, ct := range cts { + log.Debug("table created and send to next", + zap.Int("output chan size", len(outCh)), + zap.Stringer("table", ct.OldTable.Info.Name), + zap.Stringer("database", ct.OldTable.DB.Name)) + outCh <- ct + rater.Inc() + rater.L().Info("table created", + zap.Stringer("table", ct.OldTable.Info.Name), + zap.Stringer("database", ct.OldTable.DB.Name)) + } + return err + }) + } + return eg.Wait() +} + // ExecDDLs executes the queries of the ddl jobs. func (rc *Client) ExecDDLs(ctx context.Context, ddlJobs []*model.Job) error { // Sort the ddl jobs by schema version in ascending order. @@ -595,6 +808,15 @@ func drainFilesByRange(files []*backuppb.File, supportMulti bool) ([]*backuppb.F return files[:idx], files[idx:] } +// SplitRanges implements TiKVRestorer. +func (rc *Client) SplitRanges(ctx context.Context, + ranges []rtree.Range, + rewriteRules *RewriteRules, + updateCh glue.Progress, + isRawKv bool) error { + return SplitRanges(ctx, rc, ranges, rewriteRules, updateCh, isRawKv) +} + // RestoreFiles tries to restore the files. func (rc *Client) RestoreFiles( ctx context.Context, @@ -637,7 +859,7 @@ func (rc *Client) RestoreFiles( zap.Duration("take", time.Since(fileStart))) updateCh.Inc() }() - return rc.fileImporter.Import(ectx, filesReplica, rewriteRules, rc.cipher) + return rc.fileImporter.Import(ectx, filesReplica, rewriteRules, rc.cipher, rc.backupMeta.ApiVersion) }) } @@ -678,7 +900,7 @@ func (rc *Client) RestoreRaw( rc.workerPool.ApplyOnErrorGroup(eg, func() error { defer updateCh.Inc() - return rc.fileImporter.Import(ectx, []*backuppb.File{fileReplica}, EmptyRewriteRule(), rc.cipher) + return rc.fileImporter.Import(ectx, []*backuppb.File{fileReplica}, EmptyRewriteRule(), rc.cipher, rc.backupMeta.ApiVersion) }) } if err := eg.Wait(); err != nil { @@ -1001,7 +1223,7 @@ func (rc *Client) SetupPlacementRules(ctx context.Context, tables []*model.Table } rule.Index = 100 rule.Override = true - rule.LabelConstraints = append(rule.LabelConstraints, placement.LabelConstraint{ + rule.LabelConstraints = append(rule.LabelConstraints, pdtypes.LabelConstraint{ Key: restoreLabelKey, Op: "in", Values: []string{restoreLabelValue}, @@ -1119,22 +1341,25 @@ func (rc *Client) IsSkipCreateSQL() bool { return rc.noSchema } -// DDLJobsMap returns a map[UniqueTableName]bool about < db table, hasCreate/hasTruncate DDL >. +// GenerateDDLJobsMap returns a map[UniqueTableName]bool about < db table, hasCreate/hasTruncate DDL >. // if we execute some DDLs before create table. // we may get two situation that need to rebase auto increment/random id. // 1. truncate table: truncate will generate new id cache. // 2. create table/create and rename table: the first create table will lock down the id cache. // because we cannot create onExistReplace table. // so the final create DDL with the correct auto increment/random id won't be executed. -func (rc *Client) DDLJobsMap() map[UniqueTableName]bool { - m := make(map[UniqueTableName]bool) +func (rc *Client) GenerateDDLJobsMap() { + rc.ddlJobsMap = make(map[UniqueTableName]bool) for _, job := range rc.ddlJobs { switch job.Type { case model.ActionTruncateTable, model.ActionCreateTable, model.ActionRenameTable: - m[UniqueTableName{job.SchemaName, job.BinlogInfo.TableInfo.Name.String()}] = true + rc.ddlJobsMap[UniqueTableName{job.SchemaName, job.BinlogInfo.TableInfo.Name.String()}] = true } } - return m +} + +func (rc *Client) GetDDLJobsMap() map[UniqueTableName]bool { + return rc.ddlJobsMap } // PreCheckTableTiFlashReplica checks whether TiFlash replica is less than TiFlash node. diff --git a/br/pkg/restore/client_test.go b/br/pkg/restore/client_test.go index e0709d2f0edd3..492d1324ee1df 100644 --- a/br/pkg/restore/client_test.go +++ b/br/pkg/restore/client_test.go @@ -6,9 +6,9 @@ import ( "context" "math" "strconv" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/br/pkg/gluetidb" "github.com/pingcap/tidb/br/pkg/metautil" @@ -18,43 +18,31 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/types" "github.com/pingcap/tidb/tablecodec" - "github.com/pingcap/tidb/util/testleak" + "github.com/stretchr/testify/require" pd "github.com/tikv/pd/client" "google.golang.org/grpc/keepalive" ) -var _ = Suite(&testRestoreClientSuite{}) +var mc *mock.Cluster var defaultKeepaliveCfg = keepalive.ClientParameters{ Time: 3 * time.Second, Timeout: 10 * time.Second, } -type testRestoreClientSuite struct { - mock *mock.Cluster -} - -func (s *testRestoreClientSuite) SetUpTest(c *C) { - var err error - s.mock, err = mock.NewCluster() - c.Assert(err, IsNil) -} - -func (s *testRestoreClientSuite) TearDownTest(c *C) { - testleak.AfterTest(c)() -} +func TestCreateTables(t *testing.T) { + m := mc + g := gluetidb.New() + client := restore.NewRestoreClient(m.PDClient, nil, defaultKeepaliveCfg, false) + err := client.Init(g, m.Storage) + require.NoError(t, err) -func (s *testRestoreClientSuite) TestCreateTables(c *C) { - c.Assert(s.mock.Start(), IsNil) - defer s.mock.Stop() - client, err := restore.NewRestoreClient(gluetidb.New(), s.mock.PDClient, s.mock.Storage, nil, defaultKeepaliveCfg) - c.Assert(err, IsNil) - - info, err := s.mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) - c.Assert(err, IsNil) + info, err := m.Domain.GetSnapshotInfoSchema(math.MaxUint64) + require.NoError(t, err) dbSchema, isExist := info.SchemaByName(model.NewCIStr("test")) - c.Assert(isExist, IsTrue) + require.True(t, isExist) + client.SetBatchDdlSize(1) tables := make([]*metautil.Table, 4) intField := types.NewFieldType(mysql.TypeLong) intField.Charset = "binary" @@ -75,55 +63,55 @@ func (s *testRestoreClientSuite) TestCreateTables(c *C) { }, } } - rules, newTables, err := client.CreateTables(s.mock.Domain, tables, 0) - c.Assert(err, IsNil) + rules, newTables, err := client.CreateTables(m.Domain, tables, 0) + require.NoError(t, err) // make sure tables and newTables have same order - for i, t := range tables { - c.Assert(newTables[i].Name, Equals, t.Info.Name) + for i, tbl := range tables { + require.Equal(t, tbl.Info.Name, newTables[i].Name) } for _, nt := range newTables { - c.Assert(nt.Name.String(), Matches, "test[0-3]") + require.Regexp(t, "test[0-3]", nt.Name.String()) } oldTableIDExist := make(map[int64]bool) newTableIDExist := make(map[int64]bool) for _, tr := range rules.Data { oldTableID := tablecodec.DecodeTableID(tr.GetOldKeyPrefix()) - c.Assert(oldTableIDExist[oldTableID], IsFalse, Commentf("table rule duplicate old table id")) + require.False(t, oldTableIDExist[oldTableID], "table rule duplicate old table id") oldTableIDExist[oldTableID] = true newTableID := tablecodec.DecodeTableID(tr.GetNewKeyPrefix()) - c.Assert(newTableIDExist[newTableID], IsFalse, Commentf("table rule duplicate new table id")) + require.False(t, newTableIDExist[newTableID], "table rule duplicate new table id") newTableIDExist[newTableID] = true } for i := 0; i < len(tables); i++ { - c.Assert(oldTableIDExist[int64(i)], IsTrue, Commentf("table rule does not exist")) + require.True(t, oldTableIDExist[int64(i)], "table rule does not exist") } } -func (s *testRestoreClientSuite) TestIsOnline(c *C) { - c.Assert(s.mock.Start(), IsNil) - defer s.mock.Stop() - - client, err := restore.NewRestoreClient(gluetidb.New(), s.mock.PDClient, s.mock.Storage, nil, defaultKeepaliveCfg) - c.Assert(err, IsNil) +func TestIsOnline(t *testing.T) { + m := mc + g := gluetidb.New() + client := restore.NewRestoreClient(m.PDClient, nil, defaultKeepaliveCfg, false) + err := client.Init(g, m.Storage) + require.NoError(t, err) - c.Assert(client.IsOnline(), IsFalse) + require.False(t, client.IsOnline()) client.EnableOnline() - c.Assert(client.IsOnline(), IsTrue) + require.True(t, client.IsOnline()) } -func (s *testRestoreClientSuite) TestPreCheckTableClusterIndex(c *C) { - c.Assert(s.mock.Start(), IsNil) - defer s.mock.Stop() +func TestPreCheckTableClusterIndex(t *testing.T) { + m := mc + g := gluetidb.New() + client := restore.NewRestoreClient(m.PDClient, nil, defaultKeepaliveCfg, false) + err := client.Init(g, m.Storage) + require.NoError(t, err) - client, err := restore.NewRestoreClient(gluetidb.New(), s.mock.PDClient, s.mock.Storage, nil, defaultKeepaliveCfg) - c.Assert(err, IsNil) - - info, err := s.mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) - c.Assert(err, IsNil) + info, err := m.Domain.GetSnapshotInfoSchema(math.MaxUint64) + require.NoError(t, err) dbSchema, isExist := info.SchemaByName(model.NewCIStr("test")) - c.Assert(isExist, IsTrue) + require.True(t, isExist) tables := make([]*metautil.Table, 4) intField := types.NewFieldType(mysql.TypeLong) @@ -145,13 +133,14 @@ func (s *testRestoreClientSuite) TestPreCheckTableClusterIndex(c *C) { }, } } - _, _, err = client.CreateTables(s.mock.Domain, tables, 0) - c.Assert(err, IsNil) + _, _, err = client.CreateTables(m.Domain, tables, 0) + require.NoError(t, err) // exist different tables tables[1].Info.IsCommonHandle = true - c.Assert(client.PreCheckTableClusterIndex(tables, nil, s.mock.Domain), - ErrorMatches, `.*@@tidb_enable_clustered_index should be ON \(backup table = true, created table = false\).*`) + err = client.PreCheckTableClusterIndex(tables, nil, m.Domain) + require.Error(t, err) + require.Regexp(t, `.*@@tidb_enable_clustered_index should be ON \(backup table = true, created table = false\).*`, err.Error()) // exist different DDLs jobs := []*model.Job{{ @@ -166,13 +155,14 @@ func (s *testRestoreClientSuite) TestPreCheckTableClusterIndex(c *C) { }, }, }} - c.Assert(client.PreCheckTableClusterIndex(nil, jobs, s.mock.Domain), - ErrorMatches, `.*@@tidb_enable_clustered_index should be ON \(backup table = true, created table = false\).*`) + err = client.PreCheckTableClusterIndex(nil, jobs, m.Domain) + require.Error(t, err) + require.Regexp(t, `.*@@tidb_enable_clustered_index should be ON \(backup table = true, created table = false\).*`, err.Error()) // should pass pre-check cluster index tables[1].Info.IsCommonHandle = false jobs[0].BinlogInfo.TableInfo.IsCommonHandle = false - c.Assert(client.PreCheckTableClusterIndex(tables, jobs, s.mock.Domain), IsNil) + require.Nil(t, client.PreCheckTableClusterIndex(tables, jobs, m.Domain)) } type fakePDClient struct { @@ -184,10 +174,8 @@ func (fpdc fakePDClient) GetAllStores(context.Context, ...pd.GetStoreOption) ([] return append([]*metapb.Store{}, fpdc.stores...), nil } -func (s *testRestoreClientSuite) TestPreCheckTableTiFlashReplicas(c *C) { - c.Assert(s.mock.Start(), IsNil) - defer s.mock.Stop() - +func TestPreCheckTableTiFlashReplicas(t *testing.T) { + m := mc mockStores := []*metapb.Store{ { Id: 1, @@ -209,10 +197,12 @@ func (s *testRestoreClientSuite) TestPreCheckTableTiFlashReplicas(c *C) { }, } - client, err := restore.NewRestoreClient(gluetidb.New(), fakePDClient{ + g := gluetidb.New() + client := restore.NewRestoreClient(fakePDClient{ stores: mockStores, - }, s.mock.Storage, nil, defaultKeepaliveCfg) - c.Assert(err, IsNil) + }, nil, defaultKeepaliveCfg, false) + err := client.Init(g, m.Storage) + require.NoError(t, err) tables := make([]*metautil.Table, 4) for i := 0; i < len(tables); i++ { @@ -233,15 +223,15 @@ func (s *testRestoreClientSuite) TestPreCheckTableTiFlashReplicas(c *C) { } } ctx := context.Background() - c.Assert(client.PreCheckTableTiFlashReplica(ctx, tables), IsNil) + require.Nil(t, client.PreCheckTableTiFlashReplica(ctx, tables)) for i := 0; i < len(tables); i++ { if i == 0 || i > 2 { - c.Assert(tables[i].Info.TiFlashReplica, IsNil) + require.Nil(t, tables[i].Info.TiFlashReplica) } else { - c.Assert(tables[i].Info.TiFlashReplica, NotNil) + require.NotNil(t, tables[i].Info.TiFlashReplica) obtainCount := int(tables[i].Info.TiFlashReplica.Count) - c.Assert(obtainCount, Equals, i) + require.Equal(t, i, obtainCount) } } } diff --git a/br/pkg/restore/db.go b/br/pkg/restore/db.go index 3e9d35a124dfd..6f1d7b36323ba 100644 --- a/br/pkg/restore/db.go +++ b/br/pkg/restore/db.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "sort" + "sync" "github.com/pingcap/errors" "github.com/pingcap/log" @@ -15,6 +16,7 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/variable" "go.uber.org/zap" ) @@ -28,24 +30,50 @@ type UniqueTableName struct { Table string } +type DDLJobFilterRule func(ddlJob *model.Job) bool + +var incrementalRestoreActionBlockList = map[model.ActionType]struct{}{ + model.ActionSetTiFlashReplica: {}, + model.ActionUpdateTiFlashReplicaStatus: {}, + model.ActionLockTable: {}, + model.ActionUnlockTable: {}, +} + // NewDB returns a new DB. -func NewDB(g glue.Glue, store kv.Storage) (*DB, error) { +func NewDB(g glue.Glue, store kv.Storage, policyMode string) (*DB, bool, error) { se, err := g.CreateSession(store) if err != nil { - return nil, errors.Trace(err) + return nil, false, errors.Trace(err) } // The session may be nil in raw kv mode if se == nil { - return nil, nil + return nil, false, nil } // Set SQL mode to None for avoiding SQL compatibility problem err = se.Execute(context.Background(), "set @@sql_mode=''") if err != nil { - return nil, errors.Trace(err) + return nil, false, errors.Trace(err) + } + + supportPolicy := false + if len(policyMode) != 0 { + // Set placement mode for handle placement policy. + err = se.Execute(context.Background(), fmt.Sprintf("set @@tidb_placement_mode='%s';", policyMode)) + if err != nil { + if variable.ErrUnknownSystemVar.Equal(err) { + // not support placement policy, just ignore it + log.Warn("target tidb not support tidb_placement_mode, ignore create policies", zap.Error(err)) + } else { + return nil, false, errors.Trace(err) + } + } else { + log.Info("set tidb_placement_mode success", zap.String("mode", policyMode)) + supportPolicy = true + } } return &DB{ se: se, - }, nil + }, supportPolicy, nil } // ExecDDL executes the query of a ddl job. @@ -71,6 +99,13 @@ func (db *DB) ExecDDL(ctx context.Context, ddlJob *model.Job) error { return errors.Trace(err) } + if ddlJob.Query == "" { + log.Warn("query of ddl job is empty, ignore it", + zap.Stringer("type", ddlJob.Type), + zap.String("db", ddlJob.SchemaName)) + return nil + } + if tableInfo != nil { switchDBSQL := fmt.Sprintf("use %s;", utils.EncloseName(ddlJob.SchemaName)) err = db.se.Execute(ctx, switchDBSQL) @@ -115,6 +150,16 @@ func (db *DB) UpdateStatsMeta(ctx context.Context, tableID int64, restoreTS uint return nil } +// CreatePlacementPolicy check whether cluster support policy and create the policy. +func (db *DB) CreatePlacementPolicy(ctx context.Context, policy *model.PolicyInfo) error { + err := db.se.CreatePlacementPolicy(ctx, policy) + if err != nil { + return errors.Trace(err) + } + log.Info("create placement policy succeed", zap.Stringer("name", policy.Name)) + return nil +} + // CreateDatabase executes a CREATE DATABASE SQL. func (db *DB) CreateDatabase(ctx context.Context, schema *model.DBInfo) error { err := db.se.CreateDatabase(ctx, schema) @@ -124,22 +169,11 @@ func (db *DB) CreateDatabase(ctx context.Context, schema *model.DBInfo) error { return errors.Trace(err) } -// CreateTable executes a CREATE TABLE SQL. -func (db *DB) CreateTable(ctx context.Context, table *metautil.Table, ddlTables map[UniqueTableName]bool) error { - err := db.se.CreateTable(ctx, table.DB.Name, table.Info) - if err != nil { - log.Error("create table failed", - zap.Stringer("db", table.DB.Name), - zap.Stringer("table", table.Info.Name), - zap.Error(err)) - return errors.Trace(err) - } - +// +func (db *DB) restoreSequence(ctx context.Context, table *metautil.Table) error { var restoreMetaSQL string - switch { - case table.Info.IsView(): - return nil - case table.Info.IsSequence(): + var err error + if table.Info.IsSequence() { setValFormat := fmt.Sprintf("do setval(%s.%s, %%d);", utils.EncloseName(table.DB.Name.O), utils.EncloseName(table.Info.Name.O)) @@ -168,7 +202,6 @@ func (db *DB) CreateTable(ctx context.Context, table *metautil.Table, ddlTables zap.Error(err)) return errors.Trace(err) } - // trigger cycle round > 0 err = db.se.Execute(ctx, nextSeqSQL) if err != nil { @@ -182,12 +215,28 @@ func (db *DB) CreateTable(ctx context.Context, table *metautil.Table, ddlTables } restoreMetaSQL = fmt.Sprintf(setValFormat, table.Info.AutoIncID) err = db.se.Execute(ctx, restoreMetaSQL) + } + if err != nil { + log.Error("restore meta sql failed", + zap.String("query", restoreMetaSQL), + zap.Stringer("db", table.DB.Name), + zap.Stringer("table", table.Info.Name), + zap.Error(err)) + return errors.Trace(err) + } + return errors.Trace(err) +} + +func (db *DB) CreateTablePostRestore(ctx context.Context, table *metautil.Table, ddlTables map[UniqueTableName]bool) error { + + var restoreMetaSQL string + var err error + switch { + case table.Info.IsView(): + return nil + case table.Info.IsSequence(): + err = db.restoreSequence(ctx, table) if err != nil { - log.Error("restore meta sql failed", - zap.String("query", restoreMetaSQL), - zap.Stringer("db", table.DB.Name), - zap.Stringer("table", table.Info.Name), - zap.Error(err)) return errors.Trace(err) } // only table exists in ddlJobs during incremental restoration should do alter after creation. @@ -220,7 +269,68 @@ func (db *DB) CreateTable(ctx context.Context, table *metautil.Table, ddlTables return errors.Trace(err) } } - return errors.Trace(err) + return nil +} + +// CreateTables execute a internal CREATE TABLES. +func (db *DB) CreateTables(ctx context.Context, tables []*metautil.Table, + ddlTables map[UniqueTableName]bool, supportPolicy bool, policyMap *sync.Map) error { + if batchSession, ok := db.se.(glue.BatchCreateTableSession); ok { + m := map[string][]*model.TableInfo{} + for _, table := range tables { + m[table.DB.Name.L] = append(m[table.DB.Name.L], table.Info) + if !supportPolicy { + log.Info("set placementPolicyRef to nil when target tidb not support policy", + zap.Stringer("table", table.Info.Name), zap.Stringer("db", table.DB.Name)) + table.Info.ClearPlacement() + } else { + if err := db.ensureTablePlacementPolicies(ctx, table.Info, policyMap); err != nil { + return errors.Trace(err) + } + } + } + if err := batchSession.CreateTables(ctx, m); err != nil { + return err + } + + for _, table := range tables { + err := db.CreateTablePostRestore(ctx, table, ddlTables) + if err != nil { + return errors.Trace(err) + } + } + } + return nil +} + +// CreateTable executes a CREATE TABLE SQL. +func (db *DB) CreateTable(ctx context.Context, table *metautil.Table, + ddlTables map[UniqueTableName]bool, supportPolicy bool, policyMap *sync.Map) error { + if !supportPolicy { + log.Info("set placementPolicyRef to nil when target tidb not support policy", + zap.Stringer("table", table.Info.Name), zap.Stringer("db", table.DB.Name)) + table.Info.ClearPlacement() + } else { + if err := db.ensureTablePlacementPolicies(ctx, table.Info, policyMap); err != nil { + return errors.Trace(err) + } + } + + err := db.se.CreateTable(ctx, table.DB.Name, table.Info) + if err != nil { + log.Error("create table failed", + zap.Stringer("db", table.DB.Name), + zap.Stringer("table", table.Info.Name), + zap.Error(err)) + return errors.Trace(err) + } + + err = db.CreateTablePostRestore(ctx, table, ddlTables) + if err != nil { + return errors.Trace(err) + } + + return err } // Close closes the connection. @@ -228,6 +338,41 @@ func (db *DB) Close() { db.se.Close() } +func (db *DB) ensurePlacementPolicy(ctx context.Context, policyName model.CIStr, policies *sync.Map) error { + if policies == nil { + return nil + } + + if policy, ok := policies.LoadAndDelete(policyName.L); ok { + return db.CreatePlacementPolicy(ctx, policy.(*model.PolicyInfo)) + } + + // This means policy already created + return nil +} + +func (db *DB) ensureTablePlacementPolicies(ctx context.Context, tableInfo *model.TableInfo, policies *sync.Map) error { + if tableInfo.PlacementPolicyRef != nil { + if err := db.ensurePlacementPolicy(ctx, tableInfo.PlacementPolicyRef.Name, policies); err != nil { + return err + } + } + + if tableInfo.Partition != nil { + for _, def := range tableInfo.Partition.Definitions { + if def.PlacementPolicyRef == nil { + continue + } + + if err := db.ensurePlacementPolicy(ctx, def.PlacementPolicyRef.Name, policies); err != nil { + return err + } + } + } + + return nil +} + // FilterDDLJobs filters ddl jobs. func FilterDDLJobs(allDDLJobs []*model.Job, tables []*metautil.Table) (ddlJobs []*model.Job) { // Sort the ddl jobs by schema version in descending order. @@ -280,6 +425,31 @@ func FilterDDLJobs(allDDLJobs []*model.Job, tables []*metautil.Table) (ddlJobs [ return ddlJobs } +// FilterDDLJobByRules if one of rules returns true, the job in srcDDLJobs will be filtered. +func FilterDDLJobByRules(srcDDLJobs []*model.Job, rules ...DDLJobFilterRule) (dstDDLJobs []*model.Job) { + dstDDLJobs = make([]*model.Job, 0, len(srcDDLJobs)) + for _, ddlJob := range srcDDLJobs { + passed := true + for _, rule := range rules { + if rule(ddlJob) { + passed = false + break + } + } + + if passed { + dstDDLJobs = append(dstDDLJobs, ddlJob) + } + } + + return +} + +// DDLJobBlockListRule rule for filter ddl job with type in block list. +func DDLJobBlockListRule(ddlJob *model.Job) bool { + return checkIsInActions(ddlJob.Type, incrementalRestoreActionBlockList) +} + func getDatabases(tables []*metautil.Table) (dbs []*model.DBInfo) { dbIDs := make(map[int64]bool) for _, table := range tables { @@ -290,3 +460,8 @@ func getDatabases(tables []*metautil.Table) (dbs []*model.DBInfo) { } return } + +func checkIsInActions(action model.ActionType, actions map[model.ActionType]struct{}) bool { + _, ok := actions[action] + return ok +} diff --git a/br/pkg/restore/db_test.go b/br/pkg/restore/db_test.go index b9a1c8948f8dd..a7fd2eb82ed78 100644 --- a/br/pkg/restore/db_test.go +++ b/br/pkg/restore/db_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/golang/protobuf/proto" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/encryptionpb" "github.com/pingcap/tidb/br/pkg/backup" @@ -21,39 +20,38 @@ import ( "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/types" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" ) -func TestT(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&testRestoreSchemaSuite{}) - type testRestoreSchemaSuite struct { mock *mock.Cluster storage storage.ExternalStorage } -func (s *testRestoreSchemaSuite) SetUpSuite(c *C) { +func createRestoreSchemaSuite(t *testing.T) (s *testRestoreSchemaSuite, clean func()) { var err error + s = new(testRestoreSchemaSuite) s.mock, err = mock.NewCluster() - c.Assert(err, IsNil) - base := c.MkDir() + require.NoError(t, err) + base := t.TempDir() s.storage, err = storage.NewLocalStorage(base) - c.Assert(err, IsNil) - c.Assert(s.mock.Start(), IsNil) -} - -func (s *testRestoreSchemaSuite) TearDownSuite(c *C) { - s.mock.Stop() - testleak.AfterTest(c)() + require.NoError(t, err) + require.NoError(t, s.mock.Start()) + clean = func() { + s.mock.Stop() + } + return } -func (s *testRestoreSchemaSuite) TestRestoreAutoIncID(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) +func TestRestoreAutoIncID(t *testing.T) { + s, clean := createRestoreSchemaSuite(t) + defer clean() + tk := testkit.NewTestKit(t, s.mock.Storage) tk.MustExec("use test") tk.MustExec("set @@sql_mode=''") tk.MustExec("drop table if exists `\"t\"`;") @@ -65,14 +63,14 @@ func (s *testRestoreSchemaSuite) TestRestoreAutoIncID(c *C) { tk.MustExec("insert into `\"t\"` values (10, '0000-00-00 00:00:00');") // Query the current AutoIncID autoIncID, err := strconv.ParseUint(tk.MustQuery("admin show `\"t\"` next_row_id").Rows()[0][3].(string), 10, 64) - c.Assert(err, IsNil, Commentf("Error query auto inc id: %s", err)) + require.NoErrorf(t, err, "Error query auto inc id: %s", err) // Get schemas of db and table info, err := s.mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) - c.Assert(err, IsNil, Commentf("Error get snapshot info schema: %s", err)) + require.NoErrorf(t, err, "Error get snapshot info schema: %s", err) dbInfo, exists := info.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue, Commentf("Error get db info")) + require.Truef(t, exists, "Error get db info") tableInfo, err := info.TableByName(model.NewCIStr("test"), model.NewCIStr("\"t\"")) - c.Assert(err, IsNil, Commentf("Error get table info: %s", err)) + require.NoErrorf(t, err, "Error get table info: %s", err) table := metautil.Table{ Info: tableInfo.Meta(), DB: dbInfo, @@ -80,59 +78,102 @@ func (s *testRestoreSchemaSuite) TestRestoreAutoIncID(c *C) { // Get the next AutoIncID idAlloc := autoid.NewAllocator(s.mock.Storage, dbInfo.ID, table.Info.ID, false, autoid.RowIDAllocType) globalAutoID, err := idAlloc.NextGlobalAutoID() - c.Assert(err, IsNil, Commentf("Error allocate next auto id")) - c.Assert(autoIncID, Equals, uint64(globalAutoID)) + require.NoErrorf(t, err, "Error allocate next auto id") + require.Equal(t, uint64(globalAutoID), autoIncID) // Alter AutoIncID to the next AutoIncID + 100 table.Info.AutoIncID = globalAutoID + 100 - db, err := restore.NewDB(gluetidb.New(), s.mock.Storage) - c.Assert(err, IsNil, Commentf("Error create DB")) + db, _, err := restore.NewDB(gluetidb.New(), s.mock.Storage, "STRICT") + require.NoErrorf(t, err, "Error create DB") tk.MustExec("drop database if exists test;") // Test empty collate value table.DB.Charset = "utf8mb4" table.DB.Collate = "" err = db.CreateDatabase(context.Background(), table.DB) - c.Assert(err, IsNil, Commentf("Error create empty collate db: %s %s", err, s.mock.DSN)) + require.NoErrorf(t, err, "Error create empty collate db: %s %s", err, s.mock.DSN) tk.MustExec("drop database if exists test;") // Test empty charset value table.DB.Charset = "" table.DB.Collate = "utf8mb4_bin" err = db.CreateDatabase(context.Background(), table.DB) - c.Assert(err, IsNil, Commentf("Error create empty charset db: %s %s", err, s.mock.DSN)) + require.NoErrorf(t, err, "Error create empty charset db: %s %s", err, s.mock.DSN) uniqueMap := make(map[restore.UniqueTableName]bool) - err = db.CreateTable(context.Background(), &table, uniqueMap) - c.Assert(err, IsNil, Commentf("Error create table: %s %s", err, s.mock.DSN)) + err = db.CreateTable(context.Background(), &table, uniqueMap, false, nil) + require.NoErrorf(t, err, "Error create table: %s %s", err, s.mock.DSN) tk.MustExec("use test") autoIncID, err = strconv.ParseUint(tk.MustQuery("admin show `\"t\"` next_row_id").Rows()[0][3].(string), 10, 64) - c.Assert(err, IsNil, Commentf("Error query auto inc id: %s", err)) + require.NoErrorf(t, err, "Error query auto inc id: %s", err) // Check if AutoIncID is altered successfully. - c.Assert(autoIncID, Equals, uint64(globalAutoID+100)) + require.Equal(t, uint64(globalAutoID+100), autoIncID) // try again, failed due to table exists. table.Info.AutoIncID = globalAutoID + 200 - err = db.CreateTable(context.Background(), &table, uniqueMap) + err = db.CreateTable(context.Background(), &table, uniqueMap, false, nil) + require.NoError(t, err) // Check if AutoIncID is not altered. autoIncID, err = strconv.ParseUint(tk.MustQuery("admin show `\"t\"` next_row_id").Rows()[0][3].(string), 10, 64) - c.Assert(err, IsNil, Commentf("Error query auto inc id: %s", err)) - c.Assert(autoIncID, Equals, uint64(globalAutoID+100)) + require.NoErrorf(t, err, "Error query auto inc id: %s", err) + require.Equal(t, uint64(globalAutoID+100), autoIncID) // try again, success because we use alter sql in unique map. table.Info.AutoIncID = globalAutoID + 300 uniqueMap[restore.UniqueTableName{"test", "\"t\""}] = true - err = db.CreateTable(context.Background(), &table, uniqueMap) + err = db.CreateTable(context.Background(), &table, uniqueMap, false, nil) + require.NoError(t, err) // Check if AutoIncID is altered to globalAutoID + 300. autoIncID, err = strconv.ParseUint(tk.MustQuery("admin show `\"t\"` next_row_id").Rows()[0][3].(string), 10, 64) - c.Assert(err, IsNil, Commentf("Error query auto inc id: %s", err)) - c.Assert(autoIncID, Equals, uint64(globalAutoID+300)) + require.NoErrorf(t, err, "Error query auto inc id: %s", err) + require.Equal(t, uint64(globalAutoID+300), autoIncID) } -func (s *testRestoreSchemaSuite) TestFilterDDLJobs(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) +func TestCreateTablesInDb(t *testing.T) { + s, clean := createRestoreSchemaSuite(t) + defer clean() + info, err := s.mock.Domain.GetSnapshotInfoSchema(math.MaxUint64) + require.NoErrorf(t, err, "Error get snapshot info schema: %s", err) + + dbSchema, isExist := info.SchemaByName(model.NewCIStr("test")) + require.True(t, isExist) + + tables := make([]*metautil.Table, 4) + intField := types.NewFieldType(mysql.TypeLong) + intField.Charset = "binary" + ddlJobMap := make(map[restore.UniqueTableName]bool) + for i := len(tables) - 1; i >= 0; i-- { + tables[i] = &metautil.Table{ + DB: dbSchema, + Info: &model.TableInfo{ + ID: int64(i), + Name: model.NewCIStr("test" + strconv.Itoa(i)), + Columns: []*model.ColumnInfo{{ + ID: 1, + Name: model.NewCIStr("id"), + FieldType: *intField, + State: model.StatePublic, + }}, + Charset: "utf8mb4", + Collate: "utf8mb4_bin", + }, + } + ddlJobMap[restore.UniqueTableName{dbSchema.Name.String(), tables[i].Info.Name.String()}] = false + } + db, _, err := restore.NewDB(gluetidb.New(), s.mock.Storage, "STRICT") + require.NoError(t, err) + + err = db.CreateTables(context.Background(), tables, ddlJobMap, false, nil) + require.NoError(t, err) + +} + +func TestFilterDDLJobs(t *testing.T) { + s, clean := createRestoreSchemaSuite(t) + defer clean() + tk := testkit.NewTestKit(t, s.mock.Storage) tk.MustExec("CREATE DATABASE IF NOT EXISTS test_db;") tk.MustExec("CREATE TABLE IF NOT EXISTS test_db.test_table (c1 INT);") lastTS, err := s.mock.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get last ts: %s", err)) + require.NoErrorf(t, err, "Error get last ts: %s", err) tk.MustExec("RENAME TABLE test_db.test_table to test_db.test_table1;") tk.MustExec("DROP TABLE test_db.test_table1;") tk.MustExec("DROP DATABASE test_db;") @@ -143,7 +184,7 @@ func (s *testRestoreSchemaSuite) TestFilterDDLJobs(c *C) { tk.MustExec("TRUNCATE TABLE test_table;") ts, err := s.mock.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get ts: %s", err)) + require.NoErrorf(t, err, "Error get ts: %s", err) cipher := backuppb.CipherInfo{ CipherType: encryptionpb.EncryptionMethod_PLAINTEXT, @@ -153,48 +194,50 @@ func (s *testRestoreSchemaSuite) TestFilterDDLJobs(c *C) { ctx := context.Background() metaWriter.StartWriteMetasAsync(ctx, metautil.AppendDDL) err = backup.WriteBackupDDLJobs(metaWriter, s.mock.Storage, lastTS, ts) - c.Assert(err, IsNil, Commentf("Error get ddl jobs: %s", err)) + require.NoErrorf(t, err, "Error get ddl jobs: %s", err) err = metaWriter.FinishWriteMetas(ctx, metautil.AppendDDL) - c.Assert(err, IsNil, Commentf("Flush failed", err)) + require.NoErrorf(t, err, "Flush failed", err) err = metaWriter.FlushBackupMeta(ctx) - c.Assert(err, IsNil, Commentf("Finially flush backupmeta failed", err)) + require.NoErrorf(t, err, "Finially flush backupmeta failed", err) infoSchema, err := s.mock.Domain.GetSnapshotInfoSchema(ts) - c.Assert(err, IsNil, Commentf("Error get snapshot info schema: %s", err)) + require.NoErrorf(t, err, "Error get snapshot info schema: %s", err) dbInfo, ok := infoSchema.SchemaByName(model.NewCIStr("test_db")) - c.Assert(ok, IsTrue, Commentf("DB info not exist")) + require.Truef(t, ok, "DB info not exist") tableInfo, err := infoSchema.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_table")) - c.Assert(err, IsNil, Commentf("Error get table info: %s", err)) + require.NoErrorf(t, err, "Error get table info: %s", err) tables := []*metautil.Table{{ DB: dbInfo, Info: tableInfo.Meta(), }} metaBytes, err := s.storage.ReadFile(ctx, metautil.MetaFile) - c.Assert(err, IsNil) + require.NoError(t, err) mockMeta := &backuppb.BackupMeta{} err = proto.Unmarshal(metaBytes, mockMeta) - c.Assert(err, IsNil) + require.NoError(t, err) // check the schema version - c.Assert(mockMeta.Version, Equals, int32(metautil.MetaV1)) + require.Equal(t, int32(metautil.MetaV1), mockMeta.Version) metaReader := metautil.NewMetaReader(mockMeta, s.storage, &cipher) allDDLJobsBytes, err := metaReader.ReadDDLs(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) var allDDLJobs []*model.Job err = json.Unmarshal(allDDLJobsBytes, &allDDLJobs) - c.Assert(err, IsNil) + require.NoError(t, err) ddlJobs := restore.FilterDDLJobs(allDDLJobs, tables) for _, job := range ddlJobs { - c.Logf("get ddl job: %s", job.Query) + t.Logf("get ddl job: %s", job.Query) } - c.Assert(len(ddlJobs), Equals, 7) + require.Equal(t, 7, len(ddlJobs)) } -func (s *testRestoreSchemaSuite) TestFilterDDLJobsV2(c *C) { - tk := testkit.NewTestKit(c, s.mock.Storage) +func TestFilterDDLJobsV2(t *testing.T) { + s, clean := createRestoreSchemaSuite(t) + defer clean() + tk := testkit.NewTestKit(t, s.mock.Storage) tk.MustExec("CREATE DATABASE IF NOT EXISTS test_db;") tk.MustExec("CREATE TABLE IF NOT EXISTS test_db.test_table (c1 INT);") lastTS, err := s.mock.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get last ts: %s", err)) + require.NoErrorf(t, err, "Error get last ts: %s", err) tk.MustExec("RENAME TABLE test_db.test_table to test_db.test_table1;") tk.MustExec("DROP TABLE test_db.test_table1;") tk.MustExec("DROP DATABASE test_db;") @@ -205,7 +248,7 @@ func (s *testRestoreSchemaSuite) TestFilterDDLJobsV2(c *C) { tk.MustExec("TRUNCATE TABLE test_table;") ts, err := s.mock.GetOracle().GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope}) - c.Assert(err, IsNil, Commentf("Error get ts: %s", err)) + require.NoErrorf(t, err, "Error get ts: %s", err) cipher := backuppb.CipherInfo{ CipherType: encryptionpb.EncryptionMethod_PLAINTEXT, @@ -215,39 +258,113 @@ func (s *testRestoreSchemaSuite) TestFilterDDLJobsV2(c *C) { ctx := context.Background() metaWriter.StartWriteMetasAsync(ctx, metautil.AppendDDL) err = backup.WriteBackupDDLJobs(metaWriter, s.mock.Storage, lastTS, ts) - c.Assert(err, IsNil, Commentf("Error get ddl jobs: %s", err)) + require.NoErrorf(t, err, "Error get ddl jobs: %s", err) err = metaWriter.FinishWriteMetas(ctx, metautil.AppendDDL) - c.Assert(err, IsNil, Commentf("Flush failed", err)) + require.NoErrorf(t, err, "Flush failed", err) err = metaWriter.FlushBackupMeta(ctx) - c.Assert(err, IsNil, Commentf("Flush BackupMeta failed", err)) + require.NoErrorf(t, err, "Flush BackupMeta failed", err) infoSchema, err := s.mock.Domain.GetSnapshotInfoSchema(ts) - c.Assert(err, IsNil, Commentf("Error get snapshot info schema: %s", err)) + require.NoErrorf(t, err, "Error get snapshot info schema: %s", err) dbInfo, ok := infoSchema.SchemaByName(model.NewCIStr("test_db")) - c.Assert(ok, IsTrue, Commentf("DB info not exist")) + require.Truef(t, ok, "DB info not exist") tableInfo, err := infoSchema.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_table")) - c.Assert(err, IsNil, Commentf("Error get table info: %s", err)) + require.NoErrorf(t, err, "Error get table info: %s", err) tables := []*metautil.Table{{ DB: dbInfo, Info: tableInfo.Meta(), }} metaBytes, err := s.storage.ReadFile(ctx, metautil.MetaFile) - c.Assert(err, IsNil) + require.NoError(t, err) mockMeta := &backuppb.BackupMeta{} err = proto.Unmarshal(metaBytes, mockMeta) - c.Assert(err, IsNil) + require.NoError(t, err) // check the schema version - c.Assert(mockMeta.Version, Equals, int32(metautil.MetaV2)) + require.Equal(t, int32(metautil.MetaV2), mockMeta.Version) metaReader := metautil.NewMetaReader(mockMeta, s.storage, &cipher) allDDLJobsBytes, err := metaReader.ReadDDLs(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) var allDDLJobs []*model.Job err = json.Unmarshal(allDDLJobsBytes, &allDDLJobs) - c.Assert(err, IsNil) + require.NoError(t, err) ddlJobs := restore.FilterDDLJobs(allDDLJobs, tables) for _, job := range ddlJobs { - c.Logf("get ddl job: %s", job.Query) + t.Logf("get ddl job: %s", job.Query) + } + require.Equal(t, 7, len(ddlJobs)) +} + +func TestDB_ExecDDL(t *testing.T) { + s, clean := createRestoreSchemaSuite(t) + defer clean() + + ctx := context.Background() + ddlJobs := []*model.Job{ + { + Type: model.ActionAddIndex, + Query: "CREATE DATABASE IF NOT EXISTS test_db;", + BinlogInfo: &model.HistoryInfo{}, + }, + { + Type: model.ActionAddIndex, + Query: "", + BinlogInfo: &model.HistoryInfo{}, + }, + } + + db, _, err := restore.NewDB(gluetidb.New(), s.mock.Storage, "STRICT") + require.NoError(t, err) + + for _, ddlJob := range ddlJobs { + err = db.ExecDDL(ctx, ddlJob) + assert.NoError(t, err) + } +} + +func TestFilterDDLJobByRules(t *testing.T) { + ddlJobs := []*model.Job{ + { + Type: model.ActionSetTiFlashReplica, + }, + { + Type: model.ActionAddPrimaryKey, + }, + { + Type: model.ActionUpdateTiFlashReplicaStatus, + }, + { + Type: model.ActionCreateTable, + }, + { + Type: model.ActionLockTable, + }, + { + Type: model.ActionAddIndex, + }, + { + Type: model.ActionUnlockTable, + }, + { + Type: model.ActionCreateSchema, + }, + { + Type: model.ActionModifyColumn, + }, + } + + expectedDDLTypes := []model.ActionType{ + model.ActionAddPrimaryKey, + model.ActionCreateTable, + model.ActionAddIndex, + model.ActionCreateSchema, + model.ActionModifyColumn, + } + + ddlJobs = restore.FilterDDLJobByRules(ddlJobs, restore.DDLJobBlockListRule) + + require.Equal(t, len(expectedDDLTypes), len(ddlJobs)) + for i, ddlJob := range ddlJobs { + assert.Equal(t, expectedDDLTypes[i], ddlJob.Type) } - c.Assert(len(ddlJobs), Equals, 7) } diff --git a/br/pkg/restore/import.go b/br/pkg/restore/import.go index aafb144959202..f75489b8398f6 100644 --- a/br/pkg/restore/import.go +++ b/br/pkg/restore/import.go @@ -6,6 +6,7 @@ import ( "bytes" "context" "crypto/tls" + "strings" "sync" "sync/atomic" "time" @@ -259,6 +260,40 @@ func (importer *FileImporter) SetRawRange(startKey, endKey []byte) error { return nil } +// getKeyRangeForFiles gets the maximum range on files. +func (importer *FileImporter) getKeyRangeForFiles( + files []*backuppb.File, + rewriteRules *RewriteRules, +) ([]byte, []byte, error) { + var ( + startKey, endKey []byte + start, end []byte + err error + ) + + for _, f := range files { + if importer.isRawKvMode { + start, end = f.GetStartKey(), f.GetEndKey() + } else { + start, end, err = rewriteFileKeys(f, rewriteRules) + if err != nil { + return nil, nil, errors.Trace(err) + } + } + + if len(startKey) == 0 || bytes.Compare(start, startKey) < 0 { + startKey = start + } + if len(endKey) == 0 || bytes.Compare(endKey, end) < 0 { + endKey = end + } + } + + log.Debug("rewrite file keys", logutil.Files(files), + logutil.Key("startKey", startKey), logutil.Key("endKey", endKey)) + return startKey, endKey, nil +} + // Import tries to import a file. // All rules must contain encoded keys. func (importer *FileImporter) Import( @@ -266,35 +301,18 @@ func (importer *FileImporter) Import( files []*backuppb.File, rewriteRules *RewriteRules, cipher *backuppb.CipherInfo, + apiVersion kvrpcpb.APIVersion, ) error { start := time.Now() log.Debug("import file", logutil.Files(files)) + // Rewrite the start key and end key of file to scan regions - var startKey, endKey []byte - if importer.isRawKvMode { - startKey = files[0].StartKey - endKey = files[0].EndKey - } else { - for _, f := range files { - start, end, err := rewriteFileKeys(f, rewriteRules) - if err != nil { - return errors.Trace(err) - } - if len(startKey) == 0 || bytes.Compare(startKey, start) > 0 { - startKey = start - } - if bytes.Compare(endKey, end) < 0 { - endKey = end - } - } + startKey, endKey, err := importer.getKeyRangeForFiles(files, rewriteRules) + if err != nil { + return errors.Trace(err) } - log.Debug("rewrite file keys", - logutil.Files(files), - logutil.Key("startKey", startKey), - logutil.Key("endKey", endKey)) - - err := utils.WithRetry(ctx, func() error { + err = utils.WithRetry(ctx, func() error { tctx, cancel := context.WithTimeout(ctx, importScanRegionTime) defer cancel() // Scan regions covered by the file range @@ -310,35 +328,7 @@ func (importer *FileImporter) Import( for _, regionInfo := range regionInfos { info := regionInfo // Try to download file. - downloadMetas := make([]*import_sstpb.SSTMeta, 0, len(files)) - remainFiles := files - errDownload := utils.WithRetry(ctx, func() error { - var e error - for i, f := range remainFiles { - var downloadMeta *import_sstpb.SSTMeta - if importer.isRawKvMode { - downloadMeta, e = importer.downloadRawKVSST(ctx, info, f, cipher) - } else { - downloadMeta, e = importer.downloadSST(ctx, info, f, rewriteRules, cipher) - } - failpoint.Inject("restore-storage-error", func(val failpoint.Value) { - msg := val.(string) - log.Debug("failpoint restore-storage-error injected.", zap.String("msg", msg)) - e = errors.Annotate(e, msg) - }) - failpoint.Inject("restore-gRPC-error", func(_ failpoint.Value) { - log.Warn("the connection to TiKV has been cut by a neko, meow :3") - e = status.Error(codes.Unavailable, "the connection to TiKV has been cut by a neko, meow :3") - }) - if e != nil { - remainFiles = remainFiles[i:] - return errors.Trace(e) - } - downloadMetas = append(downloadMetas, downloadMeta) - } - - return nil - }, utils.NewDownloadSSTBackoffer()) + downloadMetas, errDownload := importer.download(ctx, info, files, rewriteRules, cipher, apiVersion) if errDownload != nil { for _, e := range multierr.Errors(errDownload) { switch errors.Cause(e) { // nolint:errorlint @@ -363,67 +353,10 @@ func (importer *FileImporter) Import( logutil.ShortError(errDownload)) return errors.Trace(errDownload) } - log.Debug("download file done", zap.String("file-sample", files[0].Name), zap.Stringer("take", time.Since(start)), - logutil.Key("start", files[0].StartKey), - logutil.Key("end", files[0].EndKey), - ) - ingestResp, errIngest := importer.ingestSSTs(ctx, downloadMetas, info) - ingestRetry: - for errIngest == nil { - errPb := ingestResp.GetError() - if errPb == nil { - // Ingest success - break ingestRetry - } - switch { - case errPb.NotLeader != nil: - // If error is `NotLeader`, update the region info and retry - var newInfo *RegionInfo - if newLeader := errPb.GetNotLeader().GetLeader(); newLeader != nil { - newInfo = &RegionInfo{ - Leader: newLeader, - Region: info.Region, - } - } else { - // Slow path, get region from PD - newInfo, errIngest = importer.metaClient.GetRegion( - ctx, info.Region.GetStartKey()) - if errIngest != nil { - break ingestRetry - } - // do not get region info, wait a second and continue - if newInfo == nil { - log.Warn("get region by key return nil", logutil.Region(info.Region)) - time.Sleep(time.Second) - continue - } - } - log.Debug("ingest sst returns not leader error, retry it", - logutil.Region(info.Region), - zap.Stringer("newLeader", newInfo.Leader)) - - if !checkRegionEpoch(newInfo, info) { - errIngest = errors.Trace(berrors.ErrKVEpochNotMatch) - break ingestRetry - } - ingestResp, errIngest = importer.ingestSSTs(ctx, downloadMetas, newInfo) - case errPb.EpochNotMatch != nil: - // TODO handle epoch not match error - // 1. retry download if needed - // 2. retry ingest - errIngest = errors.Trace(berrors.ErrKVEpochNotMatch) - break ingestRetry - case errPb.KeyNotInRegion != nil: - errIngest = errors.Trace(berrors.ErrKVKeyNotInRegion) - break ingestRetry - default: - // Other errors like `ServerIsBusy`, `RegionNotFound`, etc. should be retryable - errIngest = errors.Annotatef(berrors.ErrKVIngestFailed, "ingest error %s", errPb) - break ingestRetry - } - } - - if errIngest != nil { + log.Debug("download file done", + zap.String("file-sample", files[0].Name), zap.Stringer("take", time.Since(start)), + logutil.Key("start", files[0].StartKey), logutil.Key("end", files[0].EndKey)) + if errIngest := importer.ingest(ctx, info, downloadMetas); errIngest != nil { log.Error("ingest file failed", logutil.Files(files), logutil.SSTMetas(downloadMetas), @@ -432,12 +365,12 @@ func (importer *FileImporter) Import( return errors.Trace(errIngest) } } + log.Debug("ingest file done", zap.String("file-sample", files[0].Name), zap.Stringer("take", time.Since(start))) for _, f := range files { summary.CollectSuccessUnit(summary.TotalKV, 1, f.TotalKvs) summary.CollectSuccessUnit(summary.TotalBytes, 1, f.TotalBytes) } - return nil }, utils.NewImportSSTBackoffer()) return errors.Trace(err) @@ -451,6 +384,60 @@ func (importer *FileImporter) setDownloadSpeedLimit(ctx context.Context, storeID return errors.Trace(err) } +func (importer *FileImporter) download( + ctx context.Context, + regionInfo *RegionInfo, + files []*backuppb.File, + rewriteRules *RewriteRules, + cipher *backuppb.CipherInfo, + apiVersion kvrpcpb.APIVersion, +) ([]*import_sstpb.SSTMeta, error) { + var ( + downloadMetas = make([]*import_sstpb.SSTMeta, 0, len(files)) + remainFiles = files + ) + errDownload := utils.WithRetry(ctx, func() error { + var e error + for i, f := range remainFiles { + var downloadMeta *import_sstpb.SSTMeta + if importer.isRawKvMode { + downloadMeta, e = importer.downloadRawKVSST(ctx, regionInfo, f, cipher, apiVersion) + } else { + downloadMeta, e = importer.downloadSST(ctx, regionInfo, f, rewriteRules, cipher) + } + + failpoint.Inject("restore-storage-error", func(val failpoint.Value) { + msg := val.(string) + log.Debug("failpoint restore-storage-error injected.", zap.String("msg", msg)) + e = errors.Annotate(e, msg) + }) + failpoint.Inject("restore-gRPC-error", func(_ failpoint.Value) { + log.Warn("the connection to TiKV has been cut by a neko, meow :3") + e = status.Error(codes.Unavailable, "the connection to TiKV has been cut by a neko, meow :3") + }) + if isDecryptSstErr(e) { + log.Info("fail to decrypt when download sst, try again with no-crypt", logutil.File(f)) + if importer.isRawKvMode { + downloadMeta, e = importer.downloadRawKVSST(ctx, regionInfo, f, nil, apiVersion) + } else { + downloadMeta, e = importer.downloadSST(ctx, regionInfo, f, rewriteRules, nil) + } + } + + if e != nil { + remainFiles = remainFiles[i:] + return errors.Trace(e) + } + + downloadMetas = append(downloadMetas, downloadMeta) + } + + return nil + }, utils.NewDownloadSSTBackoffer()) + + return downloadMetas, errDownload +} + func (importer *FileImporter) downloadSST( ctx context.Context, regionInfo *RegionInfo, @@ -528,6 +515,7 @@ func (importer *FileImporter) downloadRawKVSST( regionInfo *RegionInfo, file *backuppb.File, cipher *backuppb.CipherInfo, + apiVersion kvrpcpb.APIVersion, ) (*import_sstpb.SSTMeta, error) { uid := uuid.New() id := uid[:] @@ -586,9 +574,71 @@ func (importer *FileImporter) downloadRawKVSST( downloadResp := atomicResp.Load().(*import_sstpb.DownloadResponse) sstMeta.Range.Start = downloadResp.Range.GetStart() sstMeta.Range.End = downloadResp.Range.GetEnd() + sstMeta.ApiVersion = apiVersion return &sstMeta, nil } +func (importer *FileImporter) ingest( + ctx context.Context, + info *RegionInfo, + downloadMetas []*import_sstpb.SSTMeta, +) error { + for { + ingestResp, errIngest := importer.ingestSSTs(ctx, downloadMetas, info) + if errIngest != nil { + return errors.Trace(errIngest) + } + + errPb := ingestResp.GetError() + switch { + case errPb == nil: + return nil + case errPb.NotLeader != nil: + // If error is `NotLeader`, update the region info and retry + var newInfo *RegionInfo + if newLeader := errPb.GetNotLeader().GetLeader(); newLeader != nil { + newInfo = &RegionInfo{ + Leader: newLeader, + Region: info.Region, + } + } else { + for { + // Slow path, get region from PD + newInfo, errIngest = importer.metaClient.GetRegion( + ctx, info.Region.GetStartKey()) + if errIngest != nil { + return errors.Trace(errIngest) + } + if newInfo != nil { + break + } + // do not get region info, wait a second and GetRegion() again. + log.Warn("get region by key return nil", logutil.Region(info.Region)) + time.Sleep(time.Second) + } + } + + if !checkRegionEpoch(newInfo, info) { + return errors.Trace(berrors.ErrKVEpochNotMatch) + } + log.Debug("ingest sst returns not leader error, retry it", + logutil.Region(info.Region), + zap.Stringer("newLeader", newInfo.Leader)) + info = newInfo + case errPb.EpochNotMatch != nil: + // TODO handle epoch not match error + // 1. retry download if needed + // 2. retry ingest + return errors.Trace(berrors.ErrKVEpochNotMatch) + case errPb.KeyNotInRegion != nil: + return errors.Trace(berrors.ErrKVKeyNotInRegion) + default: + // Other errors like `ServerIsBusy`, `RegionNotFound`, etc. should be retryable + return errors.Annotatef(berrors.ErrKVIngestFailed, "ingest error %s", errPb) + } + } +} + func (importer *FileImporter) ingestSSTs( ctx context.Context, sstMetas []*import_sstpb.SSTMeta, @@ -626,3 +676,9 @@ func (importer *FileImporter) ingestSSTs( resp, err := importer.importClient.MultiIngest(ctx, leader.GetStoreId(), req) return resp, errors.Trace(err) } + +func isDecryptSstErr(err error) bool { + return err != nil && + strings.Contains(err.Error(), "Engine Engine") && + strings.Contains(err.Error(), "Corruption: Bad table magic number") +} diff --git a/br/pkg/restore/main_test.go b/br/pkg/restore/main_test.go new file mode 100644 index 0000000000000..7c729307e6584 --- /dev/null +++ b/br/pkg/restore/main_test.go @@ -0,0 +1,54 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package restore_test + +import ( + "fmt" + "os" + "testing" + + "github.com/pingcap/tidb/br/pkg/mock" + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("github.com/klauspost/compress/zstd.(*blockDec).startDecoder"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + + var err error + mc, err = mock.NewCluster() + if err != nil { + panic(err) + } + err = mc.Start() + if err != nil { + panic(err) + } + exitCode := m.Run() + mc.Stop() + if exitCode == 0 { + if err := goleak.Find(opts...); err != nil { + fmt.Fprintf(os.Stderr, "goleak: Errors on successful test run: %v\n", err) + exitCode = 1 + } + } + os.Exit(exitCode) +} diff --git a/br/pkg/restore/merge_test.go b/br/pkg/restore/merge_test.go index eb44a6d07855f..909b3995dcb39 100644 --- a/br/pkg/restore/merge_test.go +++ b/br/pkg/restore/merge_test.go @@ -10,7 +10,6 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" backuppb "github.com/pingcap/kvproto/pkg/brpb" berrors "github.com/pingcap/tidb/br/pkg/errors" @@ -19,12 +18,9 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMergeRangesSuite{}) - -type testMergeRangesSuite struct{} - type fileBulder struct { tableID, startKeyOffset int64 } @@ -88,7 +84,7 @@ func (fb *fileBulder) build(tableID, indexID, num, bytes, kv int) (files []*back return files } -func (s *testMergeRangesSuite) TestMergeRanges(c *C) { +func TestMergeRanges(t *testing.T) { type Case struct { files [][5]int // tableID, indexID num, bytes, kv merged []int // length of each merged range @@ -209,25 +205,23 @@ func (s *testMergeRangesSuite) TestMergeRanges(c *C) { for _, f := range cs.files { files = append(files, fb.build(f[0], f[1], f[2], f[3], f[4])...) } - rngs, stat, err := restore.MergeFileRanges( - files, restore.DefaultMergeRegionSizeBytes, restore.DefaultMergeRegionKeyCount) - c.Assert(err, IsNil, Commentf("%+v", cs)) - c.Assert(stat.TotalRegions, Equals, cs.stat.TotalRegions, Commentf("%+v", cs)) - c.Assert(stat.MergedRegions, Equals, cs.stat.MergedRegions, Commentf("%+v", cs)) - - c.Assert(len(rngs), Equals, len(cs.merged), Commentf("case %d", i)) + rngs, stat, err := restore.MergeFileRanges(files, restore.DefaultMergeRegionSizeBytes, restore.DefaultMergeRegionKeyCount) + require.NoErrorf(t, err, "%+v", cs) + require.Equalf(t, cs.stat.TotalRegions, stat.TotalRegions, "%+v", cs) + require.Equalf(t, cs.stat.MergedRegions, stat.MergedRegions, "%+v", cs) + require.Lenf(t, rngs, len(cs.merged), "case %d", i) for i, rg := range rngs { - c.Assert(len(rg.Files), Equals, cs.merged[i], Commentf("%+v", cs)) + require.Lenf(t, rg.Files, cs.merged[i], "%+v", cs) // Files range must be in [Range.StartKey, Range.EndKey]. for _, f := range rg.Files { - c.Assert(bytes.Compare(rg.StartKey, f.StartKey), LessEqual, 0) - c.Assert(bytes.Compare(rg.EndKey, f.EndKey), GreaterEqual, 0) + require.LessOrEqual(t, bytes.Compare(rg.StartKey, f.StartKey), 0) + require.GreaterOrEqual(t, bytes.Compare(rg.EndKey, f.EndKey), 0) } } } } -func (s *testMergeRangesSuite) TestMergeRawKVRanges(c *C) { +func TestMergeRawKVRanges(t *testing.T) { files := make([]*backuppb.File, 0) fb := fileBulder{} files = append(files, fb.build(1, 0, 2, 1, 1)...) @@ -235,12 +229,12 @@ func (s *testMergeRangesSuite) TestMergeRawKVRanges(c *C) { files = files[1:] _, stat, err := restore.MergeFileRanges( files, restore.DefaultMergeRegionSizeBytes, restore.DefaultMergeRegionKeyCount) - c.Assert(err, IsNil) - c.Assert(stat.TotalRegions, Equals, 1) - c.Assert(stat.MergedRegions, Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, stat.TotalRegions) + require.Equal(t, 1, stat.MergedRegions) } -func (s *testMergeRangesSuite) TestInvalidRanges(c *C) { +func TestInvalidRanges(t *testing.T) { files := make([]*backuppb.File, 0) fb := fileBulder{} files = append(files, fb.build(1, 0, 1, 1, 1)...) @@ -248,8 +242,8 @@ func (s *testMergeRangesSuite) TestInvalidRanges(c *C) { files[0].Cf = "invalid" _, _, err := restore.MergeFileRanges( files, restore.DefaultMergeRegionSizeBytes, restore.DefaultMergeRegionKeyCount) - c.Assert(err, NotNil) - c.Assert(errors.Cause(err), Equals, berrors.ErrRestoreInvalidBackup) + require.Error(t, err) + require.Equal(t, berrors.ErrRestoreInvalidBackup, errors.Cause(err)) } // Benchmark results on Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz diff --git a/br/pkg/restore/pipeline_items.go b/br/pkg/restore/pipeline_items.go index ce476b1963fa5..26da3824b9a4b 100644 --- a/br/pkg/restore/pipeline_items.go +++ b/br/pkg/restore/pipeline_items.go @@ -8,8 +8,10 @@ import ( "time" "github.com/pingcap/errors" + backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/log" "github.com/pingcap/tidb/br/pkg/glue" + "github.com/pingcap/tidb/br/pkg/logutil" "github.com/pingcap/tidb/br/pkg/metautil" "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/br/pkg/summary" @@ -183,8 +185,27 @@ type BatchSender interface { Close() } +// TiKVRestorer is the minimal methods required for restoring. +// It contains the primitive APIs extract from `restore.Client`, so some of arguments may seem redundant. +// Maybe TODO: make a better abstraction? +type TiKVRestorer interface { + // SplitRanges split regions implicated by the ranges and rewrite rules. + // After spliting, it also scatters the fresh regions. + SplitRanges(ctx context.Context, + ranges []rtree.Range, + rewriteRules *RewriteRules, + updateCh glue.Progress, + isRawKv bool) error + // RestoreFiles import the files to the TiKV. + RestoreFiles(ctx context.Context, + files []*backuppb.File, + rewriteRules *RewriteRules, + updateCh glue.Progress) error +} + type tikvSender struct { - client *Client + client TiKVRestorer + updateCh glue.Progress sink TableSink @@ -209,7 +230,7 @@ func (b *tikvSender) RestoreBatch(ranges DrainResult) { // NewTiKVSender make a sender that send restore requests to TiKV. func NewTiKVSender( ctx context.Context, - cli *Client, + cli TiKVRestorer, updateCh glue.Progress, splitConcurrency uint, ) (BatchSender, error) { @@ -252,9 +273,9 @@ func (b *tikvSender) splitWorker(ctx context.Context, b.wg.Done() if err := eg.Wait(); err != nil { b.sink.EmitError(err) - return } close(next) + log.Info("TiKV Sender: split worker exits.") }() start := time.Now() @@ -266,7 +287,7 @@ func (b *tikvSender) splitWorker(ctx context.Context, pool := utils.NewWorkerPool(concurrency, "split") for { select { - case <-ctx.Done(): + case <-ectx.Done(): return case result, ok := <-ranges: if !ok { @@ -289,7 +310,7 @@ func (b *tikvSender) splitWorker(ctx context.Context, // hence the checksum would fail. done := b.registerTableIsRestoring(result.TablesToSend) pool.ApplyOnErrorGroup(eg, func() error { - err := SplitRanges(ectx, b.client, result.Ranges, result.RewriteRules, b.updateCh) + err := b.client.SplitRanges(ectx, result.Ranges, result.RewriteRules, b.updateCh, false) if err != nil { log.Error("failed on split range", rtree.ZapRanges(result.Ranges), zap.Error(err)) return err @@ -338,17 +359,17 @@ func (b *tikvSender) waitTablesDone(ts []CreatedTable) { func (b *tikvSender) restoreWorker(ctx context.Context, ranges <-chan drainResultAndDone) { eg, ectx := errgroup.WithContext(ctx) defer func() { - log.Debug("restore worker closed") + log.Info("TiKV Sender: restore worker prepare to close.") if err := eg.Wait(); err != nil { b.sink.EmitError(err) - return } - b.wg.Done() b.sink.Close() + b.wg.Done() + log.Info("TiKV Sender: restore worker exits.") }() for { select { - case <-ctx.Done(): + case <-ectx.Done(): return case r, ok := <-ranges: if !ok { @@ -360,6 +381,7 @@ func (b *tikvSender) restoreWorker(ctx context.Context, ranges <-chan drainResul eg.Go(func() error { e := b.client.RestoreFiles(ectx, files, r.result.RewriteRules, b.updateCh) if e != nil { + log.Error("restore batch meet error", logutil.ShortError(e), logutil.Files(files)) r.done() return e } diff --git a/br/pkg/restore/range.go b/br/pkg/restore/range.go index cc81ba8423d94..81881e78e8182 100644 --- a/br/pkg/restore/range.go +++ b/br/pkg/restore/range.go @@ -4,8 +4,6 @@ package restore import ( "bytes" - "sort" - "sync" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/import_sstpb" @@ -25,36 +23,6 @@ type Range struct { End []byte } -type syncdRanges struct { - sync.Mutex - ranges []Range -} - -func (r *syncdRanges) add(g Range) { - r.Lock() - r.ranges = append(r.ranges, g) - r.Unlock() -} - -func (r *syncdRanges) take() []Range { - r.Lock() - rg := r.ranges - r.ranges = []Range{} - r.Unlock() - if len(rg) > 0 { - sort.Slice(rg, func(i, j int) bool { - return bytes.Compare(rg[i].Start, rg[j].Start) < 0 - }) - } - return rg -} - -func newSyncdRanges() *syncdRanges { - return &syncdRanges{ - ranges: make([]Range, 0, 128), - } -} - // SortRanges checks if the range overlapped and sort them. func SortRanges(ranges []rtree.Range, rewriteRules *RewriteRules) ([]rtree.Range, error) { rangeTree := rtree.NewRangeTree() @@ -107,8 +75,10 @@ func SortRanges(ranges []rtree.Range, rewriteRules *RewriteRules) ([]rtree.Range // RegionInfo includes a region and the leader of the region. type RegionInfo struct { - Region *metapb.Region - Leader *metapb.Peer + Region *metapb.Region + Leader *metapb.Peer + PendingPeers []*metapb.Peer + DownPeers []*metapb.Peer } // ContainsInterior returns whether the region contains the given key, and also diff --git a/br/pkg/restore/range_test.go b/br/pkg/restore/range_test.go index 7300aa5c88192..362bc0e6398b7 100644 --- a/br/pkg/restore/range_test.go +++ b/br/pkg/restore/range_test.go @@ -3,43 +3,24 @@ package restore_test import ( - "bytes" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/tidb/br/pkg/restore" "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/tablecodec" + "github.com/stretchr/testify/require" ) -type testRangeSuite struct{} - -var _ = Suite(&testRangeSuite{}) - -type rangeEquals struct { - *CheckerInfo -} - -var RangeEquals Checker = &rangeEquals{ - &CheckerInfo{Name: "RangeEquals", Params: []string{"obtained", "expected"}}, -} - -func (checker *rangeEquals) Check(params []interface{}, names []string) (result bool, error string) { - obtained := params[0].([]rtree.Range) - expected := params[1].([]rtree.Range) - if len(obtained) != len(expected) { - return false, "" - } +func rangeEquals(t *testing.T, obtained, expected []rtree.Range) { + require.Equal(t, len(expected), len(obtained)) for i := range obtained { - if !bytes.Equal(obtained[i].StartKey, expected[i].StartKey) || - !bytes.Equal(obtained[i].EndKey, expected[i].EndKey) { - return false, "" - } + require.Equal(t, expected[i].StartKey, obtained[i].StartKey) + require.Equal(t, expected[i].EndKey, obtained[i].EndKey) } - return true, "" } -func (s *testRangeSuite) TestSortRange(c *C) { +func TestSortRange(t *testing.T) { dataRules := []*import_sstpb.RewriteRule{ {OldKeyPrefix: tablecodec.GenTableRecordPrefix(1), NewKeyPrefix: tablecodec.GenTableRecordPrefix(4)}, {OldKeyPrefix: tablecodec.GenTableRecordPrefix(2), NewKeyPrefix: tablecodec.GenTableRecordPrefix(5)}, @@ -54,8 +35,8 @@ func (s *testRangeSuite) TestSortRange(c *C) { }, } rs1, err := restore.SortRanges(ranges1, rewriteRules) - c.Assert(err, IsNil, Commentf("sort range1 failed: %v", err)) - c.Assert(rs1, RangeEquals, []rtree.Range{ + require.NoErrorf(t, err, "sort range1 failed: %v", err) + rangeEquals(t, rs1, []rtree.Range{ { StartKey: append(tablecodec.GenTableRecordPrefix(4), []byte("aaa")...), EndKey: append(tablecodec.GenTableRecordPrefix(4), []byte("bbb")...), Files: nil, @@ -69,13 +50,14 @@ func (s *testRangeSuite) TestSortRange(c *C) { }, } _, err = restore.SortRanges(ranges2, rewriteRules) - c.Assert(err, ErrorMatches, "table id mismatch.*") + require.Error(t, err) + require.Regexp(t, "table id mismatch.*", err.Error()) ranges3 := initRanges() rewriteRules1 := initRewriteRules() rs3, err := restore.SortRanges(ranges3, rewriteRules1) - c.Assert(err, IsNil, Commentf("sort range1 failed: %v", err)) - c.Assert(rs3, RangeEquals, []rtree.Range{ + require.NoErrorf(t, err, "sort range1 failed: %v", err) + rangeEquals(t, rs3, []rtree.Range{ {StartKey: []byte("bbd"), EndKey: []byte("bbf"), Files: nil}, {StartKey: []byte("bbf"), EndKey: []byte("bbj"), Files: nil}, {StartKey: []byte("xxa"), EndKey: []byte("xxe"), Files: nil}, diff --git a/br/pkg/restore/split.go b/br/pkg/restore/split.go index c962a2109aac6..9c28d0f3f9a9c 100644 --- a/br/pkg/restore/split.go +++ b/br/pkg/restore/split.go @@ -13,7 +13,6 @@ import ( "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" sst "github.com/pingcap/kvproto/pkg/import_sstpb" - "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/kvproto/pkg/pdpb" "github.com/pingcap/log" berrors "github.com/pingcap/tidb/br/pkg/errors" @@ -21,9 +20,11 @@ import ( "github.com/pingcap/tidb/br/pkg/redact" "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/br/pkg/utils" - "github.com/tikv/pd/pkg/codec" + "github.com/pingcap/tidb/util/codec" "go.uber.org/multierr" "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // Constants for split retry machinery. @@ -48,6 +49,10 @@ const ( RejectStoreMaxCheckInterval = 2 * time.Second ) +var ( + ScanRegionAttemptTimes = 30 +) + // RegionSplitter is a executor of region split by rules. type RegionSplitter struct { client SplitClient @@ -72,6 +77,7 @@ func (rs *RegionSplitter) Split( ctx context.Context, ranges []rtree.Range, rewriteRules *RewriteRules, + isRawKv bool, onSplit OnSplitFunc, ) error { if len(ranges) == 0 { @@ -91,8 +97,8 @@ func (rs *RegionSplitter) Split( if errSplit != nil { return errors.Trace(errSplit) } - minKey := codec.EncodeBytes(sortedRanges[0].StartKey) - maxKey := codec.EncodeBytes(sortedRanges[len(sortedRanges)-1].EndKey) + minKey := codec.EncodeBytes(nil, sortedRanges[0].StartKey) + maxKey := codec.EncodeBytes(nil, sortedRanges[len(sortedRanges)-1].EndKey) interval := SplitRetryInterval scatterRegions := make([]*RegionInfo, 0) SplitRegions: @@ -106,12 +112,13 @@ SplitRegions: } return errors.Trace(errScan) } - splitKeyMap := getSplitKeys(rewriteRules, sortedRanges, regions) + splitKeyMap := getSplitKeys(rewriteRules, sortedRanges, regions, isRawKv) regionMap := make(map[uint64]*RegionInfo) for _, region := range regions { regionMap[region.Region.GetId()] = region } for regionID, keys := range splitKeyMap { + log.Info("get split keys for region", zap.Int("len", len(keys)), zap.Uint64("region", regionID)) var newRegions []*RegionInfo region := regionMap[regionID] log.Info("split regions", @@ -125,7 +132,7 @@ SplitRegions: log.Error("split regions no valid key", logutil.Key("startKey", region.Region.StartKey), logutil.Key("endKey", region.Region.EndKey), - logutil.Key("key", codec.EncodeBytes(key)), + logutil.Key("key", codec.EncodeBytes(nil, key)), rtree.ZapRanges(ranges)) } return errors.Trace(errSplit) @@ -142,6 +149,7 @@ SplitRegions: logutil.Keys(keys), rtree.ZapRanges(ranges)) continue SplitRegions } + log.Info("scattered regions", zap.Int("count", len(newRegions))) if len(newRegions) != len(keys) { log.Warn("split key count and new region count mismatch", zap.Int("new region count", len(newRegions)), @@ -178,12 +186,27 @@ SplitRegions: return nil } -func (rs *RegionSplitter) hasRegion(ctx context.Context, regionID uint64) (bool, error) { +func (rs *RegionSplitter) hasHealthyRegion(ctx context.Context, regionID uint64) (bool, error) { regionInfo, err := rs.client.GetRegionByID(ctx, regionID) if err != nil { return false, errors.Trace(err) } - return regionInfo != nil, nil + // the region hasn't get ready. + if regionInfo == nil { + return false, nil + } + + // check whether the region is healthy and report. + // TODO: the log may be too verbose. we should use Prometheus metrics once it get ready for BR. + for _, peer := range regionInfo.PendingPeers { + log.Debug("unhealthy region detected", logutil.Peer(peer), zap.String("type", "pending")) + } + for _, peer := range regionInfo.DownPeers { + log.Debug("unhealthy region detected", logutil.Peer(peer), zap.String("type", "down")) + } + // we ignore down peers for they are (normally) hard to be fixed in reasonable time. + // (or once there is a peer down, we may get stuck at waiting region get ready.) + return len(regionInfo.PendingPeers) == 0, nil } func (rs *RegionSplitter) isScatterRegionFinished(ctx context.Context, regionID uint64) (bool, error) { @@ -211,7 +234,7 @@ func (rs *RegionSplitter) isScatterRegionFinished(ctx context.Context, regionID func (rs *RegionSplitter) waitForSplit(ctx context.Context, regionID uint64) { interval := SplitCheckInterval for i := 0; i < SplitCheckMaxRetryTimes; i++ { - ok, err := rs.hasRegion(ctx, regionID) + ok, err := rs.hasHealthyRegion(ctx, regionID) if err != nil { log.Warn("wait for split failed", zap.Error(err)) return @@ -294,11 +317,9 @@ func (rs *RegionSplitter) ScatterRegionsWithBackoffer(ctx context.Context, newRe log.Info("trying to scatter regions...", zap.Int("remain", len(newRegionSet))) var errs error for _, region := range newRegionSet { - // Wait for a while until the regions successfully split. - rs.waitForSplit(ctx, region.Region.Id) err := rs.client.ScatterRegion(ctx, region) if err == nil { - // it is safe accroding to the Go language spec. + // it is safe according to the Go language spec. delete(newRegionSet, region.Region.Id) } else if !pdErrorCanRetry(err) { log.Warn("scatter meet error cannot be retried, skipping", @@ -317,7 +338,7 @@ func (rs *RegionSplitter) ScatterRegionsWithBackoffer(ctx context.Context, newRe logutil.ShortError(err), logutil.AbbreviatedArray("failed-regions", newRegionSet, func(i interface{}) []string { m := i.(map[uint64]*RegionInfo) - result := make([]string, len(m)) + result := make([]string, 0, len(m)) for id := range m { result = append(result, strconv.Itoa(int(id))) } @@ -328,15 +349,54 @@ func (rs *RegionSplitter) ScatterRegionsWithBackoffer(ctx context.Context, newRe } +// isUnsupportedError checks whether we should fallback to ScatterRegion API when meeting the error. +func isUnsupportedError(err error) bool { + s, ok := status.FromError(errors.Cause(err)) + if !ok { + // Not a gRPC error. Something other went wrong. + return false + } + // In two conditions, we fallback to ScatterRegion: + // (1) If the RPC endpoint returns UNIMPLEMENTED. (This is just for making test cases not be so magic.) + // (2) If the Message is "region 0 not found": + // In fact, PD reuses the gRPC endpoint `ScatterRegion` for the batch version of scattering. + // When the request contains the field `regionIDs`, it would use the batch version, + // Otherwise, it uses the old version and scatter the region with `regionID` in the request. + // When facing 4.x, BR(which uses v5.x PD clients and call `ScatterRegions`!) would set `regionIDs` + // which would be ignored by protocol buffers, and leave the `regionID` be zero. + // Then the older version of PD would try to search the region with ID 0. + // (Then it consistently fails, and returns "region 0 not found".) + return s.Code() == codes.Unimplemented || + strings.Contains(s.Message(), "region 0 not found") +} + // ScatterRegions scatter the regions. func (rs *RegionSplitter) ScatterRegions(ctx context.Context, newRegions []*RegionInfo) { - rs.ScatterRegionsWithBackoffer( - ctx, newRegions, - // backoff about 6s, or we give up scattering this region. - &exponentialBackoffer{ - attempt: 7, - baseBackoff: 100 * time.Millisecond, - }) + for _, region := range newRegions { + // Wait for a while until the regions successfully split. + rs.waitForSplit(ctx, region.Region.Id) + } + + err := utils.WithRetry(ctx, func() error { + err := rs.client.ScatterRegions(ctx, newRegions) + if isUnsupportedError(err) { + log.Warn("batch scatter isn't supported, rollback to old method", logutil.ShortError(err)) + rs.ScatterRegionsWithBackoffer( + ctx, newRegions, + // backoff about 6s, or we give up scattering this region. + &exponentialBackoffer{ + attempt: 7, + baseBackoff: 100 * time.Millisecond, + }) + return nil + } + return err + // the retry is for the temporary network errors during sending request. + }, &exponentialBackoffer{attempt: 3, baseBackoff: 500 * time.Millisecond}) + + if err != nil { + log.Warn("failed to batch scatter region", logutil.ShortError(err)) + } } func CheckRegionConsistency(startKey, endKey []byte, regions []*RegionInfo) error { @@ -378,11 +438,18 @@ func PaginateScanRegion( } var regions []*RegionInfo - err := utils.WithRetry(ctx, func() error { + var err error + // we don't need to return multierr. since there only 3 times retry. + // in most case 3 times retry have the same error. so we just return the last error. + // actually we'd better remove all multierr in br/lightning. + // because it's not easy to check multierr equals normal error. + // see https://github.com/pingcap/tidb/issues/33419. + _ = utils.WithRetry(ctx, func() error { regions = []*RegionInfo{} scanStartKey := startKey for { - batch, err := client.ScanRegions(ctx, scanStartKey, endKey, limit) + var batch []*RegionInfo + batch, err = client.ScanRegions(ctx, scanStartKey, endKey, limit) if err != nil { return errors.Trace(err) } @@ -398,7 +465,7 @@ func PaginateScanRegion( break } } - if err := CheckRegionConsistency(startKey, endKey, regions); err != nil { + if err = CheckRegionConsistency(startKey, endKey, regions); err != nil { log.Warn("failed to scan region, retrying", logutil.ShortError(err)) return err } @@ -414,14 +481,14 @@ type scanRegionBackoffer struct { func newScanRegionBackoffer() utils.Backoffer { return &scanRegionBackoffer{ - attempt: 3, + attempt: ScanRegionAttemptTimes, } } // NextBackoff returns a duration to wait before retrying again func (b *scanRegionBackoffer) NextBackoff(err error) time.Duration { if berrors.ErrPDBatchScanRegion.Equal(err) { - // 500ms * 3 could be enough for splitting remain regions in the hole. + // 500ms * 30 could be enough for splitting remain regions in the hole. b.attempt-- return 500 * time.Millisecond } @@ -436,14 +503,14 @@ func (b *scanRegionBackoffer) Attempt() int { // getSplitKeys checks if the regions should be split by the end key of // the ranges, groups the split keys by region id. -func getSplitKeys(rewriteRules *RewriteRules, ranges []rtree.Range, regions []*RegionInfo) map[uint64][][]byte { +func getSplitKeys(rewriteRules *RewriteRules, ranges []rtree.Range, regions []*RegionInfo, isRawKv bool) map[uint64][][]byte { splitKeyMap := make(map[uint64][][]byte) checkKeys := make([][]byte, 0) for _, rg := range ranges { checkKeys = append(checkKeys, rg.EndKey) } for _, key := range checkKeys { - if region := NeedSplit(key, regions); region != nil { + if region := NeedSplit(key, regions, isRawKv); region != nil { splitKeys, ok := splitKeyMap[region.Region.GetId()] if !ok { splitKeys = make([][]byte, 0, 1) @@ -459,12 +526,14 @@ func getSplitKeys(rewriteRules *RewriteRules, ranges []rtree.Range, regions []*R } // NeedSplit checks whether a key is necessary to split, if true returns the split region. -func NeedSplit(splitKey []byte, regions []*RegionInfo) *RegionInfo { +func NeedSplit(splitKey []byte, regions []*RegionInfo, isRawKv bool) *RegionInfo { // If splitKey is the max key. if len(splitKey) == 0 { return nil } - splitKey = codec.EncodeBytes(splitKey) + if !isRawKv { + splitKey = codec.EncodeBytes(nil, splitKey) + } for _, region := range regions { // If splitKey is the boundary of the region if bytes.Equal(splitKey, region.Region.GetStartKey()) { @@ -488,34 +557,3 @@ func replacePrefix(s []byte, rewriteRules *RewriteRules) ([]byte, *sst.RewriteRu return s, nil } - -func beforeEnd(key []byte, end []byte) bool { - return bytes.Compare(key, end) < 0 || len(end) == 0 -} - -func intersectRange(region *metapb.Region, rg Range) Range { - var startKey, endKey []byte - if len(region.StartKey) > 0 { - _, startKey, _ = codec.DecodeBytes(region.StartKey) - } - if bytes.Compare(startKey, rg.Start) < 0 { - startKey = rg.Start - } - if len(region.EndKey) > 0 { - _, endKey, _ = codec.DecodeBytes(region.EndKey) - } - if beforeEnd(rg.End, endKey) { - endKey = rg.End - } - - return Range{Start: startKey, End: endKey} -} - -func insideRegion(region *metapb.Region, meta *sst.SSTMeta) bool { - rg := meta.GetRange() - return keyInsideRegion(region, rg.GetStart()) && keyInsideRegion(region, rg.GetEnd()) -} - -func keyInsideRegion(region *metapb.Region, key []byte) bool { - return bytes.Compare(key, region.GetStartKey()) >= 0 && (beforeEnd(key, region.GetEndKey())) -} diff --git a/br/pkg/restore/split_client.go b/br/pkg/restore/split_client.go index 10a9913d8e683..7c2d5549d6608 100755 --- a/br/pkg/restore/split_client.go +++ b/br/pkg/restore/split_client.go @@ -28,9 +28,8 @@ import ( berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/httputil" "github.com/pingcap/tidb/br/pkg/logutil" + "github.com/pingcap/tidb/store/pdtypes" pd "github.com/tikv/pd/client" - "github.com/tikv/pd/server/config" - "github.com/tikv/pd/server/schedule/placement" "go.uber.org/multierr" "go.uber.org/zap" "google.golang.org/grpc" @@ -60,18 +59,20 @@ type SplitClient interface { BatchSplitRegionsWithOrigin(ctx context.Context, regionInfo *RegionInfo, keys [][]byte) (*RegionInfo, []*RegionInfo, error) // ScatterRegion scatters a specified region. ScatterRegion(ctx context.Context, regionInfo *RegionInfo) error + // ScatterRegions scatters regions in a batch. + ScatterRegions(ctx context.Context, regionInfo []*RegionInfo) error // GetOperator gets the status of operator of the specified region. GetOperator(ctx context.Context, regionID uint64) (*pdpb.GetOperatorResponse, error) - // ScanRegion gets a list of regions, starts from the region that contains key. + // ScanRegions gets a list of regions, starts from the region that contains key. // Limit limits the maximum number of regions returned. ScanRegions(ctx context.Context, key, endKey []byte, limit int) ([]*RegionInfo, error) // GetPlacementRule loads a placement rule from PD. - GetPlacementRule(ctx context.Context, groupID, ruleID string) (placement.Rule, error) + GetPlacementRule(ctx context.Context, groupID, ruleID string) (pdtypes.Rule, error) // SetPlacementRule insert or update a placement rule to PD. - SetPlacementRule(ctx context.Context, rule placement.Rule) error + SetPlacementRule(ctx context.Context, rule pdtypes.Rule) error // DeletePlacementRule removes a placement rule from PD. DeletePlacementRule(ctx context.Context, groupID, ruleID string) error - // SetStoreLabel add or update specified label of stores. If labelValue + // SetStoresLabel add or update specified label of stores. If labelValue // is empty, it clears the label. SetStoresLabel(ctx context.Context, stores []uint64, labelKey, labelValue string) error } @@ -87,14 +88,17 @@ type pdClient struct { // this may mislead the scatter. needScatterVal bool needScatterInit sync.Once + + isRawKv bool } // NewSplitClient returns a client used by RegionSplitter. -func NewSplitClient(client pd.Client, tlsConf *tls.Config) SplitClient { +func NewSplitClient(client pd.Client, tlsConf *tls.Config, isRawKv bool) SplitClient { cli := &pdClient{ client: client, tlsConf: tlsConf, storeCache: make(map[uint64]*metapb.Store), + isRawKv: isRawKv, } return cli } @@ -114,6 +118,24 @@ func (c *pdClient) needScatter(ctx context.Context) bool { return c.needScatterVal } +// ScatterRegions scatters regions in a batch. +func (c *pdClient) ScatterRegions(ctx context.Context, regionInfo []*RegionInfo) error { + c.mu.Lock() + defer c.mu.Unlock() + regionsID := make([]uint64, 0, len(regionInfo)) + for _, v := range regionInfo { + regionsID = append(regionsID, v.Region.Id) + } + resp, err := c.client.ScatterRegions(ctx, regionsID) + if err != nil { + return err + } + if pbErr := resp.GetHeader().GetError(); pbErr.GetType() != pdpb.ErrorType_OK { + return errors.Annotatef(berrors.ErrPDInvalidResponse, "pd returns error during batch scattering: %s", pbErr) + } + return nil +} + func (c *pdClient) GetStore(ctx context.Context, storeID uint64) (*metapb.Store, error) { c.mu.Lock() defer c.mu.Unlock() @@ -152,8 +174,10 @@ func (c *pdClient) GetRegionByID(ctx context.Context, regionID uint64) (*RegionI return nil, nil } return &RegionInfo{ - Region: region.Meta, - Leader: region.Leader, + Region: region.Meta, + Leader: region.Leader, + PendingPeers: region.PendingPeers, + DownPeers: region.DownPeers, }, nil } @@ -235,6 +259,7 @@ func splitRegionWithFailpoint( peer *metapb.Peer, client tikvpb.TikvClient, keys [][]byte, + isRawKv bool, ) (*kvrpcpb.SplitRegionResponse, error) { failpoint.Inject("not-leader-error", func(injectNewLeader failpoint.Value) { log.Debug("failpoint not-leader-error injected.") @@ -265,6 +290,7 @@ func splitRegionWithFailpoint( Peer: peer, }, SplitKeys: keys, + IsRawKv: isRawKv, }) } @@ -273,82 +299,96 @@ func (c *pdClient) sendSplitRegionRequest( ) (*kvrpcpb.SplitRegionResponse, error) { var splitErrors error for i := 0; i < splitRegionMaxRetryTime; i++ { - var peer *metapb.Peer - // scanRegions may return empty Leader in https://github.com/tikv/pd/blob/v4.0.8/server/grpc_service.go#L524 - // so wee also need check Leader.Id != 0 - if regionInfo.Leader != nil && regionInfo.Leader.Id != 0 { - peer = regionInfo.Leader - } else { - if len(regionInfo.Region.Peers) == 0 { - return nil, multierr.Append(splitErrors, - errors.Annotatef(berrors.ErrRestoreNoPeer, "region[%d] doesn't have any peer", regionInfo.Region.GetId())) - } - peer = regionInfo.Region.Peers[0] + retry, result, err := sendSplitRegionRequest(c, ctx, regionInfo, keys, &splitErrors, i) + if retry { + continue } - storeID := peer.GetStoreId() - store, err := c.GetStore(ctx, storeID) if err != nil { return nil, multierr.Append(splitErrors, err) } - opt := grpc.WithInsecure() - if c.tlsConf != nil { - opt = grpc.WithTransportCredentials(credentials.NewTLS(c.tlsConf)) - } - conn, err := grpc.Dial(store.GetAddress(), opt) - if err != nil { - return nil, multierr.Append(splitErrors, err) + if result != nil { + return result, nil } - defer conn.Close() - client := tikvpb.NewTikvClient(conn) - resp, err := splitRegionWithFailpoint(ctx, regionInfo, peer, client, keys) - if err != nil { - return nil, multierr.Append(splitErrors, err) + return nil, errors.Trace(splitErrors) + } + return nil, errors.Trace(splitErrors) +} + +func sendSplitRegionRequest(c *pdClient, ctx context.Context, regionInfo *RegionInfo, keys [][]byte, splitErrors *error, retry int) (bool, *kvrpcpb.SplitRegionResponse, error) { + var peer *metapb.Peer + // scanRegions may return empty Leader in https://github.com/tikv/pd/blob/v4.0.8/server/grpc_service.go#L524 + // so wee also need check Leader.Id != 0 + if regionInfo.Leader != nil && regionInfo.Leader.Id != 0 { + peer = regionInfo.Leader + } else { + if len(regionInfo.Region.Peers) == 0 { + return false, nil, + errors.Annotatef(berrors.ErrRestoreNoPeer, "region[%d] doesn't have any peer", regionInfo.Region.GetId()) } - if resp.RegionError != nil { - log.Warn("fail to split region", - logutil.Region(regionInfo.Region), - zap.Stringer("regionErr", resp.RegionError)) - splitErrors = multierr.Append(splitErrors, - errors.Annotatef(berrors.ErrRestoreSplitFailed, "split region failed: err=%v", resp.RegionError)) - if nl := resp.RegionError.NotLeader; nl != nil { - if leader := nl.GetLeader(); leader != nil { - regionInfo.Leader = leader - } else { - newRegionInfo, findLeaderErr := c.GetRegionByID(ctx, nl.RegionId) - if findLeaderErr != nil { - return nil, multierr.Append(splitErrors, findLeaderErr) - } - if !checkRegionEpoch(newRegionInfo, regionInfo) { - return nil, multierr.Append(splitErrors, berrors.ErrKVEpochNotMatch) - } - log.Info("find new leader", zap.Uint64("new leader", newRegionInfo.Leader.Id)) - regionInfo = newRegionInfo + peer = regionInfo.Region.Peers[0] + } + storeID := peer.GetStoreId() + store, err := c.GetStore(ctx, storeID) + if err != nil { + return false, nil, err + } + opt := grpc.WithInsecure() + if c.tlsConf != nil { + opt = grpc.WithTransportCredentials(credentials.NewTLS(c.tlsConf)) + } + conn, err := grpc.Dial(store.GetAddress(), opt) + if err != nil { + return false, nil, err + } + defer conn.Close() + client := tikvpb.NewTikvClient(conn) + resp, err := splitRegionWithFailpoint(ctx, regionInfo, peer, client, keys, c.isRawKv) + if err != nil { + return false, nil, err + } + if resp.RegionError != nil { + log.Warn("fail to split region", + logutil.Region(regionInfo.Region), + zap.Stringer("regionErr", resp.RegionError)) + *splitErrors = multierr.Append(*splitErrors, + errors.Annotatef(berrors.ErrRestoreSplitFailed, "split region failed: err=%v", resp.RegionError)) + if nl := resp.RegionError.NotLeader; nl != nil { + if leader := nl.GetLeader(); leader != nil { + regionInfo.Leader = leader + } else { + newRegionInfo, findLeaderErr := c.GetRegionByID(ctx, nl.RegionId) + if findLeaderErr != nil { + return false, nil, findLeaderErr } - log.Info("split region meet not leader error, retrying", - zap.Int("retry times", i), - zap.Uint64("regionID", regionInfo.Region.Id), - zap.Any("new leader", regionInfo.Leader), - ) - continue - } - // TODO: we don't handle RegionNotMatch and RegionNotFound here, - // because I think we don't have enough information to retry. - // But maybe we can handle them here by some information the error itself provides. - if resp.RegionError.ServerIsBusy != nil || - resp.RegionError.StaleCommand != nil { - log.Warn("a error occurs on split region", - zap.Int("retry times", i), - zap.Uint64("regionID", regionInfo.Region.Id), - zap.String("error", resp.RegionError.Message), - zap.Any("error verbose", resp.RegionError), - ) - continue + if !checkRegionEpoch(newRegionInfo, regionInfo) { + return false, nil, berrors.ErrKVEpochNotMatch + } + log.Info("find new leader", zap.Uint64("new leader", newRegionInfo.Leader.Id)) + regionInfo = newRegionInfo } - return nil, errors.Trace(splitErrors) + log.Info("split region meet not leader error, retrying", + zap.Int("retry times", retry), + zap.Uint64("regionID", regionInfo.Region.Id), + zap.Any("new leader", regionInfo.Leader), + ) + return true, nil, nil } - return resp, nil + // TODO: we don't handle RegionNotMatch and RegionNotFound here, + // because I think we don't have enough information to retry. + // But maybe we can handle them here by some information the error itself provides. + if resp.RegionError.ServerIsBusy != nil || + resp.RegionError.StaleCommand != nil { + log.Warn("a error occurs on split region", + zap.Int("retry times", retry), + zap.Uint64("regionID", regionInfo.Region.Id), + zap.String("error", resp.RegionError.Message), + zap.Any("error verbose", resp.RegionError), + ) + return true, nil, nil + } + return false, nil, nil } - return nil, errors.Trace(splitErrors) + return false, resp, nil } func (c *pdClient) BatchSplitRegionsWithOrigin( @@ -407,7 +447,7 @@ func (c *pdClient) getStoreCount(ctx context.Context) (int, error) { func (c *pdClient) getMaxReplica(ctx context.Context) (int, error) { api := c.getPDAPIAddr() - configAPI := api + "/pd/api/v1/config" + configAPI := api + "/pd/api/v1/config/replicate" req, err := http.NewRequestWithContext(ctx, "GET", configAPI, nil) if err != nil { return 0, errors.Trace(err) @@ -421,11 +461,11 @@ func (c *pdClient) getMaxReplica(ctx context.Context) (int, error) { log.Error("Response fail to close", zap.Error(err)) } }() - var conf config.Config + var conf pdtypes.ReplicationConfig if err := json.NewDecoder(res.Body).Decode(&conf); err != nil { return 0, errors.Trace(err) } - return int(conf.Replication.MaxReplicas), nil + return int(conf.MaxReplicas), nil } func (c *pdClient) checkNeedScatter(ctx context.Context) (bool, error) { @@ -473,8 +513,8 @@ func (c *pdClient) ScanRegions(ctx context.Context, key, endKey []byte, limit in return regionInfos, nil } -func (c *pdClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (placement.Rule, error) { - var rule placement.Rule +func (c *pdClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (pdtypes.Rule, error) { + var rule pdtypes.Rule addr := c.getPDAPIAddr() if addr == "" { return rule, errors.Annotate(berrors.ErrRestoreSplitFailed, "failed to add stores labels: no leader") @@ -503,7 +543,7 @@ func (c *pdClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) return rule, nil } -func (c *pdClient) SetPlacementRule(ctx context.Context, rule placement.Rule) error { +func (c *pdClient) SetPlacementRule(ctx context.Context, rule pdtypes.Rule) error { addr := c.getPDAPIAddr() if addr == "" { return errors.Annotate(berrors.ErrPDLeaderNotFound, "failed to add stores labels") @@ -574,10 +614,10 @@ func (c *pdClient) getPDAPIAddr() string { return strings.TrimRight(addr, "/") } -func checkRegionEpoch(new, old *RegionInfo) bool { - return new.Region.GetId() == old.Region.GetId() && - new.Region.GetRegionEpoch().GetVersion() == old.Region.GetRegionEpoch().GetVersion() && - new.Region.GetRegionEpoch().GetConfVer() == old.Region.GetRegionEpoch().GetConfVer() +func checkRegionEpoch(_new, _old *RegionInfo) bool { + return _new.Region.GetId() == _old.Region.GetId() && + _new.Region.GetRegionEpoch().GetVersion() == _old.Region.GetRegionEpoch().GetVersion() && + _new.Region.GetRegionEpoch().GetConfVer() == _old.Region.GetRegionEpoch().GetConfVer() } // exponentialBackoffer trivially retry any errors it meets. diff --git a/br/pkg/restore/split_test.go b/br/pkg/restore/split_test.go index 5e43d3378e579..e07946a5b25af 100644 --- a/br/pkg/restore/split_test.go +++ b/br/pkg/restore/split_test.go @@ -9,31 +9,37 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" + backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/kvproto/pkg/pdpb" + "github.com/pingcap/log" + berrors "github.com/pingcap/tidb/br/pkg/errors" + "github.com/pingcap/tidb/br/pkg/glue" + "github.com/pingcap/tidb/br/pkg/logutil" "github.com/pingcap/tidb/br/pkg/restore" "github.com/pingcap/tidb/br/pkg/rtree" "github.com/pingcap/tidb/br/pkg/utils" + "github.com/pingcap/tidb/store/pdtypes" "github.com/pingcap/tidb/util/codec" "github.com/stretchr/testify/require" - "github.com/tikv/pd/server/core" - "github.com/tikv/pd/server/schedule/placement" + "go.uber.org/multierr" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type TestClient struct { - mu sync.RWMutex - stores map[uint64]*metapb.Store - regions map[uint64]*restore.RegionInfo - regionsInfo *core.RegionsInfo // For now it's only used in ScanRegions - nextRegionID uint64 - injectInScatter func(*restore.RegionInfo) error + mu sync.RWMutex + stores map[uint64]*metapb.Store + regions map[uint64]*restore.RegionInfo + regionsInfo *pdtypes.RegionTree // For now it's only used in ScanRegions + nextRegionID uint64 + injectInScatter func(*restore.RegionInfo) error + supportBatchScatter bool scattered map[uint64]bool + InjectErr bool } func NewTestClient( @@ -41,9 +47,9 @@ func NewTestClient( regions map[uint64]*restore.RegionInfo, nextRegionID uint64, ) *TestClient { - regionsInfo := core.NewRegionsInfo() + regionsInfo := &pdtypes.RegionTree{} for _, regionInfo := range regions { - regionsInfo.SetRegion(core.NewRegionInfo(regionInfo.Region, regionInfo.Leader)) + regionsInfo.SetRegion(pdtypes.NewRegionInfo(regionInfo.Region, regionInfo.Leader)) } return &TestClient{ stores: stores, @@ -55,6 +61,36 @@ func NewTestClient( } } +func (c *TestClient) InstallBatchScatterSupport() { + c.supportBatchScatter = true +} + +// ScatterRegions scatters regions in a batch. +func (c *TestClient) ScatterRegions(ctx context.Context, regionInfo []*restore.RegionInfo) error { + if !c.supportBatchScatter { + return status.Error(codes.Unimplemented, "Ah, yep") + } + regions := map[uint64]*restore.RegionInfo{} + for _, region := range regionInfo { + regions[region.Region.Id] = region + } + var err error + for i := 0; i < 3; i++ { + if len(regions) == 0 { + return nil + } + for id, region := range regions { + splitErr := c.ScatterRegion(ctx, region) + if splitErr == nil { + delete(regions, id) + } + err = multierr.Append(err, splitErr) + + } + } + return nil +} + func (c *TestClient) GetAllRegions() map[uint64]*restore.RegionInfo { c.mu.RLock() defer c.mu.RUnlock() @@ -180,22 +216,26 @@ func (c *TestClient) GetOperator(ctx context.Context, regionID uint64) (*pdpb.Ge } func (c *TestClient) ScanRegions(ctx context.Context, key, endKey []byte, limit int) ([]*restore.RegionInfo, error) { + if c.InjectErr { + return nil, errors.New("mock scan error") + } + infos := c.regionsInfo.ScanRange(key, endKey, limit) regions := make([]*restore.RegionInfo, 0, len(infos)) for _, info := range infos { regions = append(regions, &restore.RegionInfo{ - Region: info.GetMeta(), - Leader: info.GetLeader(), + Region: info.Meta, + Leader: info.Leader, }) } return regions, nil } -func (c *TestClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (r placement.Rule, err error) { +func (c *TestClient) GetPlacementRule(ctx context.Context, groupID, ruleID string) (r pdtypes.Rule, err error) { return } -func (c *TestClient) SetPlacementRule(ctx context.Context, rule placement.Rule) error { +func (c *TestClient) SetPlacementRule(ctx context.Context, rule pdtypes.Rule) error { return nil } @@ -243,7 +283,7 @@ func TestScatterFinishInTime(t *testing.T) { regionSplitter := restore.NewRegionSplitter(client) ctx := context.Background() - err := regionSplitter.Split(ctx, ranges, rewriteRules, func(key [][]byte) {}) + err := regionSplitter.Split(ctx, ranges, rewriteRules, false, func(key [][]byte) {}) require.NoError(t, err) regions := client.GetAllRegions() if !validateRegions(regions) { @@ -282,13 +322,24 @@ func TestScatterFinishInTime(t *testing.T) { // [, aay), [aay, bba), [bba, bbf), [bbf, bbh), [bbh, bbj), // [bbj, cca), [cca, xxe), [xxe, xxz), [xxz, ) func TestSplitAndScatter(t *testing.T) { - client := initTestClient() + t.Run("BatchScatter", func(t *testing.T) { + client := initTestClient() + client.InstallBatchScatterSupport() + runTestSplitAndScatterWith(t, client) + }) + t.Run("BackwardCompatibility", func(t *testing.T) { + client := initTestClient() + runTestSplitAndScatterWith(t, client) + }) +} + +func runTestSplitAndScatterWith(t *testing.T, client *TestClient) { ranges := initRanges() rewriteRules := initRewriteRules() regionSplitter := restore.NewRegionSplitter(client) ctx := context.Background() - err := regionSplitter.Split(ctx, ranges, rewriteRules, func(key [][]byte) {}) + err := regionSplitter.Split(ctx, ranges, rewriteRules, false, func(key [][]byte) {}) require.NoError(t, err) regions := client.GetAllRegions() if !validateRegions(regions) { @@ -320,7 +371,6 @@ func TestSplitAndScatter(t *testing.T) { t.Fatalf("region %d has not been scattered: %#v", key, regions[key]) } } - } // region: [, aay), [aay, bba), [bba, bbh), [bbh, cca), [cca, ) @@ -423,30 +473,39 @@ FindRegion: return true } -func (s *testRangeSuite) TestNeedSplit(c *C) { - regions := []*restore.RegionInfo{ - { - Region: &metapb.Region{ - StartKey: codec.EncodeBytes([]byte{}, []byte("b")), - EndKey: codec.EncodeBytes([]byte{}, []byte("d")), +func TestNeedSplit(t *testing.T) { + for _, isRawKv := range []bool{false, true} { + encode := func(in []byte) []byte { + if isRawKv { + return in + } + return codec.EncodeBytes([]byte{}, in) + } + + regions := []*restore.RegionInfo{ + { + Region: &metapb.Region{ + StartKey: encode([]byte("b")), + EndKey: encode([]byte("d")), + }, }, - }, + } + // Out of region + require.Nil(t, restore.NeedSplit([]byte("a"), regions, isRawKv)) + // Region start key + require.Nil(t, restore.NeedSplit([]byte("b"), regions, isRawKv)) + // In region + region := restore.NeedSplit([]byte("c"), regions, isRawKv) + require.Equal(t, 0, bytes.Compare(region.Region.GetStartKey(), encode([]byte("b")))) + require.Equal(t, 0, bytes.Compare(region.Region.GetEndKey(), encode([]byte("d")))) + // Region end key + require.Nil(t, restore.NeedSplit([]byte("d"), regions, isRawKv)) + // Out of region + require.Nil(t, restore.NeedSplit([]byte("e"), regions, isRawKv)) } - // Out of region - c.Assert(restore.NeedSplit([]byte("a"), regions), IsNil) - // Region start key - c.Assert(restore.NeedSplit([]byte("b"), regions), IsNil) - // In region - region := restore.NeedSplit([]byte("c"), regions) - c.Assert(bytes.Compare(region.Region.GetStartKey(), codec.EncodeBytes([]byte{}, []byte("b"))), Equals, 0) - c.Assert(bytes.Compare(region.Region.GetEndKey(), codec.EncodeBytes([]byte{}, []byte("d"))), Equals, 0) - // Region end key - c.Assert(restore.NeedSplit([]byte("d"), regions), IsNil) - // Out of region - c.Assert(restore.NeedSplit([]byte("e"), regions), IsNil) -} - -func (s *testRangeSuite) TestRegionConsistency(c *C) { +} + +func TestRegionConsistency(t *testing.T) { cases := []struct { startKey []byte endKey []byte @@ -506,9 +565,136 @@ func (s *testRangeSuite) TestRegionConsistency(c *C) { }, } for _, ca := range cases { - c.Assert( - restore.CheckRegionConsistency(ca.startKey, ca.endKey, ca.regions), - ErrorMatches, - ca.err) + err := restore.CheckRegionConsistency(ca.startKey, ca.endKey, ca.regions) + require.Error(t, err) + require.Regexp(t, ca.err, err.Error()) + } +} + +type fakeRestorer struct { + mu sync.Mutex + + errorInSplit bool + splitRanges []rtree.Range + restoredFiles []*backuppb.File +} + +func (f *fakeRestorer) SplitRanges(ctx context.Context, ranges []rtree.Range, rewriteRules *restore.RewriteRules, updateCh glue.Progress, isRawKv bool) error { + f.mu.Lock() + defer f.mu.Unlock() + + if ctx.Err() != nil { + return ctx.Err() + } + f.splitRanges = append(f.splitRanges, ranges...) + if f.errorInSplit { + err := errors.Annotatef(berrors.ErrRestoreSplitFailed, + "the key space takes many efforts and finally get together, how dare you split them again... :<") + log.Error("error happens :3", logutil.ShortError(err)) + return err + } + return nil +} + +func (f *fakeRestorer) RestoreFiles(ctx context.Context, files []*backuppb.File, rewriteRules *restore.RewriteRules, updateCh glue.Progress) error { + f.mu.Lock() + defer f.mu.Unlock() + + if ctx.Err() != nil { + return ctx.Err() + } + f.restoredFiles = append(f.restoredFiles, files...) + err := errors.Annotatef(berrors.ErrRestoreWriteAndIngest, "the files to restore are taken by a hijacker, meow :3") + log.Error("error happens :3", logutil.ShortError(err)) + return err +} + +func fakeRanges(keys ...string) (r restore.DrainResult) { + for i := range keys { + if i+1 == len(keys) { + return + } + r.Ranges = append(r.Ranges, rtree.Range{ + StartKey: []byte(keys[i]), + EndKey: []byte(keys[i+1]), + Files: []*backuppb.File{{Name: "fake.sst"}}, + }) + } + return +} + +type errorInTimeSink struct { + ctx context.Context + errCh chan error + t *testing.T +} + +func (e errorInTimeSink) EmitTables(tables ...restore.CreatedTable) {} + +func (e errorInTimeSink) EmitError(err error) { + e.errCh <- err +} + +func (e errorInTimeSink) Close() {} + +func (e errorInTimeSink) Wait() { + select { + case <-e.ctx.Done(): + e.t.Logf("The context is canceled but no error happen") + e.t.FailNow() + case <-e.errCh: + } +} + +func assertErrorEmitInTime(ctx context.Context, t *testing.T) errorInTimeSink { + errCh := make(chan error, 1) + return errorInTimeSink{ + ctx: ctx, + errCh: errCh, + t: t, } } + +func TestRestoreFailed(t *testing.T) { + ranges := []restore.DrainResult{ + fakeRanges("aax", "abx", "abz"), + fakeRanges("abz", "bbz", "bcy"), + fakeRanges("bcy", "cad", "xxy"), + } + r := &fakeRestorer{} + sender, err := restore.NewTiKVSender(context.TODO(), r, nil, 1) + require.NoError(t, err) + dctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sink := assertErrorEmitInTime(dctx, t) + sender.PutSink(sink) + for _, r := range ranges { + sender.RestoreBatch(r) + } + sink.Wait() + sink.Close() + sender.Close() + require.GreaterOrEqual(t, len(r.restoredFiles), 1) +} + +func TestSplitFailed(t *testing.T) { + ranges := []restore.DrainResult{ + fakeRanges("aax", "abx", "abz"), + fakeRanges("abz", "bbz", "bcy"), + fakeRanges("bcy", "cad", "xxy"), + } + r := &fakeRestorer{errorInSplit: true} + sender, err := restore.NewTiKVSender(context.TODO(), r, nil, 1) + require.NoError(t, err) + dctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sink := assertErrorEmitInTime(dctx, t) + sender.PutSink(sink) + for _, r := range ranges { + sender.RestoreBatch(r) + } + sink.Wait() + sender.Close() + require.GreaterOrEqual(t, len(r.splitRanges), 2) + require.Len(t, r.restoredFiles, 0) +} diff --git a/br/pkg/restore/systable_restore.go b/br/pkg/restore/systable_restore.go index f6235d195a850..b0f588fa2286c 100644 --- a/br/pkg/restore/systable_restore.go +++ b/br/pkg/restore/systable_restore.go @@ -8,12 +8,12 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/log" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/logutil" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + filter "github.com/pingcap/tidb/util/table-filter" "go.uber.org/multierr" "go.uber.org/zap" ) diff --git a/br/pkg/restore/util.go b/br/pkg/restore/util.go index 812d87b09cec6..35edb7ec52b50 100644 --- a/br/pkg/restore/util.go +++ b/br/pkg/restore/util.go @@ -137,8 +137,8 @@ func GetSSTMetaFromFile( } } -// MakeDBPool makes a session pool with specficated size by sessionFactory. -func MakeDBPool(size uint, dbFactory func() (*DB, error)) ([]*DB, error) { +// makeDBPool makes a session pool with specficated size by sessionFactory. +func makeDBPool(size uint, dbFactory func() (*DB, error)) ([]*DB, error) { dbPool := make([]*DB, 0, size) for i := uint(0); i < size; i++ { db, e := dbFactory() @@ -345,10 +345,11 @@ func SplitRanges( ranges []rtree.Range, rewriteRules *RewriteRules, updateCh glue.Progress, + isRawKv bool, ) error { - splitter := NewRegionSplitter(NewSplitClient(client.GetPDClient(), client.GetTLSConfig())) + splitter := NewRegionSplitter(NewSplitClient(client.GetPDClient(), client.GetTLSConfig(), isRawKv)) - return splitter.Split(ctx, ranges, rewriteRules, func(keys [][]byte) { + return splitter.Split(ctx, ranges, rewriteRules, isRawKv, func(keys [][]byte) { for range keys { updateCh.Inc() } diff --git a/br/pkg/restore/util_test.go b/br/pkg/restore/util_test.go index e8263c6b8462c..cde804ba89b08 100644 --- a/br/pkg/restore/util_test.go +++ b/br/pkg/restore/util_test.go @@ -5,40 +5,37 @@ package restore_test import ( "context" "encoding/binary" + "testing" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/import_sstpb" "github.com/pingcap/kvproto/pkg/metapb" + berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/restore" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testRestoreUtilSuite{}) - -type testRestoreUtilSuite struct { -} - -func (s *testRestoreUtilSuite) TestParseQuoteName(c *C) { +func TestParseQuoteName(t *testing.T) { schema, table := restore.ParseQuoteName("`a`.`b`") - c.Assert(schema, Equals, "a") - c.Assert(table, Equals, "b") + require.Equal(t, "a", schema) + require.Equal(t, "b", table) schema, table = restore.ParseQuoteName("`a``b`.``````") - c.Assert(schema, Equals, "a`b") - c.Assert(table, Equals, "``") + require.Equal(t, "a`b", schema) + require.Equal(t, "``", table) schema, table = restore.ParseQuoteName("`.`.`.`") - c.Assert(schema, Equals, ".") - c.Assert(table, Equals, ".") + require.Equal(t, ".", schema) + require.Equal(t, ".", table) schema, table = restore.ParseQuoteName("`.``.`.`.`") - c.Assert(schema, Equals, ".`.") - c.Assert(table, Equals, ".") + require.Equal(t, ".`.", schema) + require.Equal(t, ".", table) } -func (s *testRestoreUtilSuite) TestGetSSTMetaFromFile(c *C) { +func TestGetSSTMetaFromFile(t *testing.T) { file := &backuppb.File{ Name: "file_write.sst", StartKey: []byte("t1a"), @@ -53,11 +50,11 @@ func (s *testRestoreUtilSuite) TestGetSSTMetaFromFile(c *C) { EndKey: []byte("t3a"), } sstMeta := restore.GetSSTMetaFromFile([]byte{}, file, region, rule) - c.Assert(string(sstMeta.GetRange().GetStart()), Equals, "t2abc") - c.Assert(string(sstMeta.GetRange().GetEnd()), Equals, "t2\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") + require.Equal(t, "t2abc", string(sstMeta.GetRange().GetStart())) + require.Equal(t, "t2\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", string(sstMeta.GetRange().GetEnd())) } -func (s *testRestoreUtilSuite) TestMapTableToFiles(c *C) { +func TestMapTableToFiles(t *testing.T) { filesOfTable1 := []*backuppb.File{ { Name: "table1-1.sst", @@ -90,11 +87,11 @@ func (s *testRestoreUtilSuite) TestMapTableToFiles(c *C) { result := restore.MapTableToFiles(append(filesOfTable2, filesOfTable1...)) - c.Assert(result[1], DeepEquals, filesOfTable1) - c.Assert(result[2], DeepEquals, filesOfTable2) + require.Equal(t, filesOfTable1, result[1]) + require.Equal(t, filesOfTable2, result[2]) } -func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { +func TestValidateFileRewriteRule(t *testing.T) { rules := &restore.RewriteRules{ Data: []*import_sstpb.RewriteRule{{ OldKeyPrefix: []byte(tablecodec.EncodeTablePrefix(1)), @@ -111,7 +108,8 @@ func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { }, rules, ) - c.Assert(err, ErrorMatches, ".*cannot find rewrite rule.*") + require.Error(t, err) + require.Regexp(t, ".*cannot find rewrite rule.*", err.Error()) // Range is not overlap, no rule found. err = restore.ValidateFileRewriteRule( @@ -122,7 +120,8 @@ func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { }, rules, ) - c.Assert(err, ErrorMatches, ".*cannot find rewrite rule.*") + require.Error(t, err) + require.Regexp(t, ".*cannot find rewrite rule.*", err.Error()) // No rule for end key. err = restore.ValidateFileRewriteRule( @@ -133,7 +132,8 @@ func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { }, rules, ) - c.Assert(err, ErrorMatches, ".*cannot find rewrite rule.*") + require.Error(t, err) + require.Regexp(t, ".*cannot find rewrite rule.*", err.Error()) // Add a rule for end key. rules.Data = append(rules.Data, &import_sstpb.RewriteRule{ @@ -148,7 +148,8 @@ func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { }, rules, ) - c.Assert(err, ErrorMatches, ".*rewrite rule mismatch.*") + require.Error(t, err) + require.Regexp(t, ".*rewrite rule mismatch.*", err.Error()) // Add a bad rule for end key, after rewrite start key > end key. rules.Data = append(rules.Data[:1], &import_sstpb.RewriteRule{ @@ -163,10 +164,11 @@ func (s *testRestoreUtilSuite) TestValidateFileRewriteRule(c *C) { }, rules, ) - c.Assert(err, ErrorMatches, ".*rewrite rule mismatch.*") + require.Error(t, err) + require.Regexp(t, ".*rewrite rule mismatch.*", err.Error()) } -func (s *testRestoreUtilSuite) TestPaginateScanRegion(c *C) { +func TestPaginateScanRegion(t *testing.T) { peers := make([]*metapb.Peer, 1) peers[0] = &metapb.Peer{ Id: 1, @@ -223,53 +225,65 @@ func (s *testRestoreUtilSuite) TestPaginateScanRegion(c *C) { ctx := context.Background() regionMap := make(map[uint64]*restore.RegionInfo) - regions := []*restore.RegionInfo{} - batch, err := restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) - c.Assert(err, ErrorMatches, ".*scan region return empty result.*") + var regions []*restore.RegionInfo + var batch []*restore.RegionInfo + _, err := restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) + require.Error(t, err) + require.True(t, berrors.ErrPDBatchScanRegion.Equal(err)) + require.Regexp(t, ".*scan region return empty result.*", err.Error()) regionMap, regions = makeRegions(1) batch, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions) + require.NoError(t, err) + require.Equal(t, regions, batch) regionMap, regions = makeRegions(2) batch, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions) + require.NoError(t, err) + require.Equal(t, regions, batch) regionMap, regions = makeRegions(3) batch, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions) + require.NoError(t, err) + require.Equal(t, regions, batch) regionMap, regions = makeRegions(8) batch, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{}, []byte{}, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions) + require.NoError(t, err) + require.Equal(t, regions, batch) regionMap, regions = makeRegions(8) batch, err = restore.PaginateScanRegion( ctx, NewTestClient(stores, regionMap, 0), regions[1].Region.StartKey, []byte{}, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions[1:]) + require.NoError(t, err) + require.Equal(t, regions[1:], batch) batch, err = restore.PaginateScanRegion( ctx, NewTestClient(stores, regionMap, 0), []byte{}, regions[6].Region.EndKey, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions[:7]) + require.NoError(t, err) + require.Equal(t, regions[:7], batch) batch, err = restore.PaginateScanRegion( ctx, NewTestClient(stores, regionMap, 0), regions[1].Region.StartKey, regions[1].Region.EndKey, 3) - c.Assert(err, IsNil) - c.Assert(batch, DeepEquals, regions[1:2]) + require.NoError(t, err) + require.Equal(t, regions[1:2], batch) _, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), []byte{2}, []byte{1}, 3) - c.Assert(err, ErrorMatches, ".*startKey >= endKey.*") + require.Error(t, err) + require.True(t, berrors.ErrRestoreInvalidRange.Equal(err)) + require.Regexp(t, ".*startKey >= endKey.*", err.Error()) + + tc := NewTestClient(stores, regionMap, 0) + tc.InjectErr = true + _, err = restore.PaginateScanRegion(ctx, tc, regions[1].Region.EndKey, regions[5].Region.EndKey, 3) + require.Error(t, err) + require.Regexp(t, ".*mock scan error.*", err.Error()) // make the regionMap losing some region, this will cause scan region check fails delete(regionMap, uint64(3)) - _, err = restore.PaginateScanRegion( - ctx, NewTestClient(stores, regionMap, 0), regions[1].Region.EndKey, regions[5].Region.EndKey, 3) - c.Assert(err, ErrorMatches, ".*region endKey not equal to next region startKey.*") + _, err = restore.PaginateScanRegion(ctx, NewTestClient(stores, regionMap, 0), regions[1].Region.EndKey, regions[5].Region.EndKey, 3) + require.Error(t, err) + require.True(t, berrors.ErrPDBatchScanRegion.Equal(err)) + require.Regexp(t, ".*region endKey not equal to next region startKey.*", err.Error()) } diff --git a/br/pkg/rtree/main_test.go b/br/pkg/rtree/main_test.go index 85dc99665acaf..f1dcccc623422 100644 --- a/br/pkg/rtree/main_test.go +++ b/br/pkg/rtree/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/storage/azblob.go b/br/pkg/storage/azblob.go new file mode 100644 index 0000000000000..10b06776772a5 --- /dev/null +++ b/br/pkg/storage/azblob.go @@ -0,0 +1,502 @@ +// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0. + +package storage + +import ( + "bytes" + "context" + "encoding/base64" + "fmt" + "io" + "os" + "path" + "strings" + + "github.com/google/uuid" + "github.com/spf13/pflag" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + "github.com/pingcap/errors" + backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/pingcap/log" + berrors "github.com/pingcap/tidb/br/pkg/errors" + "go.uber.org/zap" +) + +const ( + azblobEndpointOption = "azblob.endpoint" + azblobAccessTierOption = "azblob.access-tier" + azblobAccountName = "azblob.account-name" + azblobAccountKey = "azblob.account-key" +) + +type AzblobBackendOptions struct { + Endpoint string `json:"endpoint" toml:"endpoint"` + AccountName string `json:"account-name" toml:"account-name"` + AccountKey string `json:"account-key" toml:"account-key"` + AccessTier string `json:"access-tier" toml:"access-tier"` +} + +func (options *AzblobBackendOptions) apply(azblob *backuppb.AzureBlobStorage) error { + azblob.Endpoint = options.Endpoint + azblob.StorageClass = options.AccessTier + azblob.AccountName = options.AccountName + azblob.SharedKey = options.AccountKey + return nil +} + +func defineAzblobFlags(flags *pflag.FlagSet) { + flags.String(azblobEndpointOption, "", "(experimental) Set the Azblob endpoint URL") + flags.String(azblobAccessTierOption, "", "Specify the storage class for azblob") + flags.String(azblobAccountName, "", "Specify the account name for azblob") + flags.String(azblobAccountKey, "", "Specify the account key for azblob") +} + +func (options *AzblobBackendOptions) parseFromFlags(flags *pflag.FlagSet) error { + var err error + options.Endpoint, err = flags.GetString(azblobEndpointOption) + if err != nil { + return errors.Trace(err) + } + + options.AccessTier, err = flags.GetString(azblobAccessTierOption) + if err != nil { + return errors.Trace(err) + } + + options.AccountName, err = flags.GetString(azblobAccountName) + if err != nil { + return errors.Trace(err) + } + + options.AccountKey, err = flags.GetString(azblobAccountKey) + if err != nil { + return errors.Trace(err) + } + return nil +} + +type ClientBuilder interface { + // Example of serviceURL: https://.blob.core.windows.net + GetServiceClient() (azblob.ServiceClient, error) + GetAccountName() string +} + +// use shared key to access azure blob storage +type sharedKeyClientBuilder struct { + cred *azblob.SharedKeyCredential + accountName string + serviceURL string +} + +func (b *sharedKeyClientBuilder) GetServiceClient() (azblob.ServiceClient, error) { + return azblob.NewServiceClientWithSharedKey(b.serviceURL, b.cred, nil) +} + +func (b *sharedKeyClientBuilder) GetAccountName() string { + return b.accountName +} + +// use token to access azure blob storage +type tokenClientBuilder struct { + cred *azidentity.ClientSecretCredential + accountName string + serviceURL string +} + +func (b *tokenClientBuilder) GetServiceClient() (azblob.ServiceClient, error) { + return azblob.NewServiceClient(b.serviceURL, b.cred, nil) +} + +func (b *tokenClientBuilder) GetAccountName() string { + return b.accountName +} + +func getAuthorizerFromEnvironment() (clientId, tenantId, clientSecret string) { + return os.Getenv("AZURE_CLIENT_ID"), + os.Getenv("AZURE_TENANT_ID"), + os.Getenv("AZURE_CLIENT_SECRET") +} + +// get azure service client from options and environment +func getAzureServiceClientBuilder(options *backuppb.AzureBlobStorage, opts *ExternalStorageOptions) (ClientBuilder, error) { + if len(options.Bucket) == 0 { + return nil, errors.New("bucket(container) cannot be empty to access azure blob storage") + } + + if len(options.AccountName) > 0 && len(options.SharedKey) > 0 { + serviceURL := options.Endpoint + if len(serviceURL) == 0 { + serviceURL = fmt.Sprintf("https://%s.blob.core.windows.net", options.AccountName) + } + cred, err := azblob.NewSharedKeyCredential(options.AccountName, options.SharedKey) + if err != nil { + return nil, errors.Annotate(err, "Failed to get azure sharedKey credential") + } + return &sharedKeyClientBuilder{ + cred, + options.AccountName, + serviceURL, + }, nil + } + + accountName := options.AccountName + if len(accountName) == 0 { + if val := os.Getenv("AZURE_STORAGE_ACCOUNT"); len(val) > 0 { + accountName = val + } else { + return nil, errors.New("account name cannot be empty to access azure blob storage") + } + } + + serviceURL := options.Endpoint + if len(serviceURL) == 0 { + serviceURL = fmt.Sprintf("https://%s.blob.core.windows.net", accountName) + } + + if clientId, tenantId, clientSecret := getAuthorizerFromEnvironment(); len(clientId) > 0 && len(tenantId) > 0 && len(clientSecret) > 0 { + cred, err := azidentity.NewClientSecretCredential(tenantId, clientId, clientSecret, nil) + if err != nil { + log.Warn("Failed to get azure token credential but environment variables exist, try to use shared key.", zap.String("tenantId", tenantId), zap.String("clientId", clientId), zap.String("clientSecret", "?")) + } else { + // send account-name to TiKV + if opts != nil && opts.SendCredentials { + options.AccountName = accountName + } + return &tokenClientBuilder{ + cred, + accountName, + serviceURL, + }, nil + } + } + + var sharedKey string + if val := os.Getenv("AZURE_STORAGE_KEY"); len(val) > 0 { + log.Info("Get azure sharedKey from environment variable $AZURE_STORAGE_KEY") + sharedKey = val + } else { + return nil, errors.New("cannot find any credential info to access azure blob storage") + } + + cred, err := azblob.NewSharedKeyCredential(accountName, sharedKey) + if err != nil { + return nil, errors.Annotate(err, "Failed to get azure sharedKey credential") + } + // if BR can only get credential info from environment variable `sharedKey`, + // BR will send it to TiKV so that there is no need to set environment variable for TiKV. + if opts != nil && opts.SendCredentials { + options.AccountName = accountName + options.SharedKey = sharedKey + } + return &sharedKeyClientBuilder{ + cred, + accountName, + serviceURL, + }, nil +} + +type AzureBlobStorage struct { + options *backuppb.AzureBlobStorage + + containerClient azblob.ContainerClient + + accessTier azblob.AccessTier +} + +func newAzureBlobStorage(ctx context.Context, options *backuppb.AzureBlobStorage, opts *ExternalStorageOptions) (*AzureBlobStorage, error) { + clientBuilder, err := getAzureServiceClientBuilder(options, opts) + if err != nil { + return nil, errors.Trace(err) + } + + return newAzureBlobStorageWithClientBuilder(ctx, options, clientBuilder) +} + +func newAzureBlobStorageWithClientBuilder(ctx context.Context, options *backuppb.AzureBlobStorage, clientBuilder ClientBuilder) (*AzureBlobStorage, error) { + + serviceClient, err := clientBuilder.GetServiceClient() + if err != nil { + return nil, errors.Annotate(err, "Failed to create azure service client") + } + + containerClient := serviceClient.NewContainerClient(options.Bucket) + _, err = containerClient.Create(ctx, nil) + if err != nil { + var errResp *azblob.StorageError + if internalErr, ok := err.(*azblob.InternalError); ok && internalErr.As(&errResp) { + if errResp.ErrorCode != azblob.StorageErrorCodeContainerAlreadyExists { + return nil, errors.Annotate(err, fmt.Sprintf("Failed to create the container: %s", errResp.ErrorCode)) + } + } else { + return nil, errors.Annotate(err, "Failed to create the container: error can not be parsed") + } + } + + // parse storage access-tier + var accessTier azblob.AccessTier + switch options.StorageClass { + case "Archive", "archive": + accessTier = azblob.AccessTierArchive + case "Cool", "cool": + accessTier = azblob.AccessTierCool + case "Hot", "hot": + accessTier = azblob.AccessTierHot + default: + accessTier = azblob.AccessTier(options.StorageClass) + } + + log.Debug("select accessTier", zap.String("accessTier", string(accessTier))) + + return &AzureBlobStorage{ + options, + containerClient, + accessTier, + }, nil +} + +func (s *AzureBlobStorage) withPrefix(name string) string { + return path.Join(s.options.Prefix, name) +} + +func (s *AzureBlobStorage) WriteFile(ctx context.Context, name string, data []byte) error { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + resp, err := client.UploadBufferToBlockBlob(ctx, data, azblob.HighLevelUploadToBlockBlobOption{AccessTier: &s.accessTier}) + if err != nil { + return errors.Annotatef(err, "Failed to write azure blob file, file info: bucket(container)='%s', key='%s'", s.options.Bucket, s.withPrefix(name)) + } + defer resp.Body.Close() + return nil +} + +func (s *AzureBlobStorage) ReadFile(ctx context.Context, name string) ([]byte, error) { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + resp, err := client.Download(ctx, nil) + if err != nil { + return nil, errors.Annotatef(err, "Failed to download azure blob file, file info: bucket(container)='%s', key='%s'", s.options.Bucket, s.withPrefix(name)) + } + defer resp.RawResponse.Body.Close() + data, err := io.ReadAll(resp.Body(azblob.RetryReaderOptions{})) + if err != nil { + return nil, errors.Annotatef(err, "Failed to read azure blob file, file info: bucket(container)='%s', key='%s'", s.options.Bucket, s.withPrefix(name)) + } + return data, err +} + +func (s *AzureBlobStorage) FileExists(ctx context.Context, name string) (bool, error) { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + _, err := client.GetProperties(ctx, nil) + if err != nil { + var errResp *azblob.StorageError + if internalErr, ok := err.(*azblob.InternalError); ok && internalErr.As(&errResp) { + if errResp.ErrorCode == azblob.StorageErrorCodeBlobNotFound { + return false, nil + } + } + return false, errors.Trace(err) + } + return true, nil +} + +func (s *AzureBlobStorage) DeleteFile(ctx context.Context, name string) error { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + _, err := client.Delete(ctx, nil) + if err != nil { + return errors.Annotatef(err, "Failed to delete azure blob file, file info: bucket(container)='%s', key='%s'", s.options.Bucket, s.withPrefix(name)) + } + return nil +} + +func (s *AzureBlobStorage) Open(ctx context.Context, name string) (ExternalFileReader, error) { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + return &azblobObjectReader{ + blobClient: client, + + pos: 0, + + ctx: ctx, + }, nil +} + +func (s *AzureBlobStorage) WalkDir(ctx context.Context, opt *WalkOption, fn func(path string, size int64) error) error { + if opt == nil { + opt = &WalkOption{} + } + + prefix := path.Join(s.options.Prefix, opt.SubDir) + if len(prefix) > 0 && !strings.HasSuffix(prefix, "/") { + prefix += "/" + } + + prefixLength := len(prefix) + + listOption := &azblob.ContainerListBlobFlatSegmentOptions{Prefix: &prefix} + for { + respIter := s.containerClient.ListBlobsFlat(listOption) + + err := respIter.Err() + if err != nil { + return errors.Annotatef(err, "Failed to list azure blobs, bucket(container)='%s'", s.options.Bucket) + } + + if !respIter.NextPage(ctx) { + err := respIter.Err() + if err != nil { + return errors.Annotatef(err, "Failed to list azure blobs, bucket(container)='%s'", s.options.Bucket) + } + break + } + + for _, blob := range respIter.PageResponse().Segment.BlobItems { + if err := fn((*blob.Name)[prefixLength:], *blob.Properties.ContentLength); err != nil { + return errors.Trace(err) + } + } + + listOption.Marker = respIter.PageResponse().NextMarker + if len(*listOption.Marker) == 0 { + break + } + } + + return nil +} + +func (s *AzureBlobStorage) URI() string { + return "azure://" + s.options.Bucket + "/" + s.options.Prefix +} + +func (s *AzureBlobStorage) Create(ctx context.Context, name string) (ExternalFileWriter, error) { + client := s.containerClient.NewBlockBlobClient(s.withPrefix(name)) + uploader := &azblobUploader{ + blobClient: client, + + blockIDList: make([]string, 0, 4), + + accessTier: s.accessTier, + } + + uploaderWriter := newBufferedWriter(uploader, azblob.BlockBlobMaxUploadBlobBytes, NoCompression) + return uploaderWriter, nil +} + +func (s *AzureBlobStorage) Rename(ctx context.Context, oldFileName, newFileName string) error { + data, err := s.ReadFile(ctx, oldFileName) + if err != nil { + return errors.Trace(err) + } + err = s.WriteFile(ctx, newFileName, data) + if err != nil { + return errors.Trace(err) + } + return s.DeleteFile(ctx, oldFileName) +} + +type azblobObjectReader struct { + blobClient azblob.BlockBlobClient + + pos int64 + + ctx context.Context +} + +// Read implement the io.Reader interface. +func (r *azblobObjectReader) Read(p []byte) (n int, err error) { + count := int64(len(p)) + resp, err := r.blobClient.Download(r.ctx, &azblob.DownloadBlobOptions{Offset: &r.pos, Count: &count}) + if err != nil { + return 0, errors.Annotatef(err, "Failed to read data from azure blob, data info: pos='%d', count='%d'", r.pos, count) + } + n, err = resp.Body(azblob.RetryReaderOptions{}).Read(p) + if err != nil && err != io.EOF { + return 0, errors.Annotatef(err, "Failed to read data from azure blob response, data info: pos='%d', count='%d'", r.pos, count) + } + r.pos += int64(n) + return n, nil +} + +// Close implement the io.Closer interface. +func (r *azblobObjectReader) Close() error { + return nil +} + +func (r *azblobObjectReader) Seek(offset int64, whence int) (int64, error) { + var realOffset int64 + switch whence { + case io.SeekStart: + if offset < 0 { + return 0, errors.Annotatef(berrors.ErrInvalidArgument, "Seek: offset '%v' out of range.", offset) + } + realOffset = offset + case io.SeekCurrent: + realOffset = r.pos + offset + if r.pos < 0 && realOffset >= 0 { + return 0, errors.Annotatef(berrors.ErrInvalidArgument, "Seek: offset '%v' out of range. current pos is '%v'.", offset, r.pos) + } + case io.SeekEnd: + if offset >= 0 { + return 0, errors.Annotatef(berrors.ErrInvalidArgument, "Seek: offset '%v' should be negative.", offset) + } + realOffset = offset + default: + return 0, errors.Annotatef(berrors.ErrStorageUnknown, "Seek: invalid whence '%d'", whence) + } + + if realOffset < 0 { + resp, err := r.blobClient.GetProperties(r.ctx, nil) + if err != nil { + return 0, errors.Annotate(err, "Failed to get properties from the azure blob") + } + + contentLength := *resp.ContentLength + r.pos = contentLength + realOffset + if r.pos < 0 { + return 0, errors.Annotatef(err, "Seek: offset is %d, but length of content is only %d", realOffset, contentLength) + } + } else { + r.pos = realOffset + } + return r.pos, nil +} + +type nopCloser struct { + io.ReadSeeker +} + +func newNopCloser(r io.ReadSeeker) nopCloser { + return nopCloser{r} +} + +func (r nopCloser) Close() error { + return nil +} + +type azblobUploader struct { + blobClient azblob.BlockBlobClient + + blockIDList []string + + accessTier azblob.AccessTier +} + +func (u *azblobUploader) Write(ctx context.Context, data []byte) (int, error) { + generatedUuid, err := uuid.NewUUID() + if err != nil { + return 0, errors.Annotate(err, "Fail to generate uuid") + } + blockId := base64.StdEncoding.EncodeToString([]byte(generatedUuid.String())) + + _, err = u.blobClient.StageBlock(ctx, blockId, newNopCloser(bytes.NewReader(data)), nil) + if err != nil { + return 0, errors.Annotate(err, "Failed to upload block to azure blob") + } + u.blockIDList = append(u.blockIDList, blockId) + + return len(data), nil +} + +func (u *azblobUploader) Close(ctx context.Context) error { + _, err := u.blobClient.CommitBlockList(ctx, u.blockIDList, &azblob.CommitBlockListOptions{Tier: &u.accessTier}) + return errors.Trace(err) +} diff --git a/br/pkg/storage/azblob_test.go b/br/pkg/storage/azblob_test.go new file mode 100644 index 0000000000000..03b0618b04320 --- /dev/null +++ b/br/pkg/storage/azblob_test.go @@ -0,0 +1,301 @@ +// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0. + +package storage + +import ( + "context" + "io" + "os" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/stretchr/testify/require" +) + +// use shared key to access azurite +type sharedKeyAzuriteClientBuilder struct { +} + +func (b *sharedKeyAzuriteClientBuilder) GetServiceClient() (azblob.ServiceClient, error) { + connStr := "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;" + return azblob.NewServiceClientFromConnectionString(connStr, nil) +} + +func (b *sharedKeyAzuriteClientBuilder) GetAccountName() string { + return "devstoreaccount1" +} + +func TestAzblob(t *testing.T) { + ctx := context.Background() + options := &backuppb.AzureBlobStorage{ + Bucket: "test", + Prefix: "a/b/", + } + + azblobStorage, err := newAzureBlobStorageWithClientBuilder(ctx, options, &sharedKeyAzuriteClientBuilder{}) + if err != nil { + if strings.Contains(err.Error(), "connect: connection refused") { + t.Log("azurite is not running, skip test") + return + } + } + require.NoError(t, err) + + err = azblobStorage.WriteFile(ctx, "key", []byte("data")) + require.NoError(t, err) + + err = azblobStorage.WriteFile(ctx, "key1", []byte("data1")) + require.NoError(t, err) + + err = azblobStorage.WriteFile(ctx, "key2", []byte("data22223346757222222222289722222")) + require.NoError(t, err) + + d, err := azblobStorage.ReadFile(ctx, "key") + require.NoError(t, err) + require.Equal(t, []byte("data"), d) + + exist, err := azblobStorage.FileExists(ctx, "key") + require.NoError(t, err) + require.True(t, exist) + + exist, err = azblobStorage.FileExists(ctx, "key_not_exist") + require.NoError(t, err) + require.False(t, exist) + + keyDelete := "key_delete" + exist, err = azblobStorage.FileExists(ctx, keyDelete) + require.NoError(t, err) + require.False(t, exist) + + err = azblobStorage.WriteFile(ctx, keyDelete, []byte("data")) + require.NoError(t, err) + + exist, err = azblobStorage.FileExists(ctx, keyDelete) + require.NoError(t, err) + require.True(t, exist) + + err = azblobStorage.DeleteFile(ctx, keyDelete) + require.NoError(t, err) + + exist, err = azblobStorage.FileExists(ctx, keyDelete) + require.NoError(t, err) + require.False(t, exist) + + list := "" + var totalSize int64 = 0 + err = azblobStorage.WalkDir(ctx, nil, func(name string, size int64) error { + list += name + totalSize += size + return nil + }) + require.NoError(t, err) + require.Equal(t, "keykey1key2", list) + require.Equal(t, int64(42), totalSize) + + efr, err := azblobStorage.Open(ctx, "key2") + require.NoError(t, err) + + p := make([]byte, 10) + n, err := efr.Read(p) + require.NoError(t, err) + require.Equal(t, 10, n) + require.Equal(t, "data222233", string(p)) + + p = make([]byte, 40) + n, err = efr.Read(p) + require.NoError(t, err) + require.Equal(t, 23, n) + require.Equal(t, "46757222222222289722222", string(p[:23])) + + p = make([]byte, 5) + offs, err := efr.Seek(3, io.SeekStart) + require.NoError(t, err) + require.Equal(t, int64(3), offs) + + n, err = efr.Read(p) + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "a2222", string(p)) + + p = make([]byte, 5) + offs, err = efr.Seek(3, io.SeekCurrent) + require.NoError(t, err) + require.Equal(t, int64(11), offs) + + n, err = efr.Read(p) + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "67572", string(p)) + + p = make([]byte, 5) + offs, err = efr.Seek(int64(-7), io.SeekEnd) + require.NoError(t, err) + // Note, change it to maxCnt - offs + require.Equal(t, int64(26), offs) + + n, err = efr.Read(p) + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "97222", string(p)) + + err = efr.Close() + require.NoError(t, err) + + require.Equal(t, "azure://test/a/b/", azblobStorage.URI()) +} + +func TestNewAzblobStorage(t *testing.T) { + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + AccountName: "user", + SharedKey: "cGFzc3dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*sharedKeyClientBuilder) + require.True(t, ok) + require.Equal(t, "user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + + { + options := &backuppb.AzureBlobStorage{ + Bucket: "test", + Prefix: "a/b", + AccountName: "user", + SharedKey: "cGFzc3dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*sharedKeyClientBuilder) + require.True(t, ok) + require.Equal(t, "user", b.GetAccountName()) + require.Equal(t, "https://user.blob.core.windows.net", b.serviceURL) + } + + err := os.Setenv("AZURE_STORAGE_ACCOUNT", "env_user") + require.NoError(t, err) + defer os.Unsetenv("AZURE_STORAGE_ACCOUNT") + + { + options := &backuppb.AzureBlobStorage{ + Bucket: "test", + Prefix: "a/b", + AccountName: "user", + SharedKey: "cGFzc3dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*sharedKeyClientBuilder) + require.True(t, ok) + require.Equal(t, "user", b.GetAccountName()) + require.Equal(t, "https://user.blob.core.windows.net", b.serviceURL) + } + + { + options := &backuppb.AzureBlobStorage{ + Bucket: "test", + Prefix: "a/b", + SharedKey: "cGFzc3dk", + } + _, err := getAzureServiceClientBuilder(options, nil) + require.Error(t, err) + } + + err = os.Setenv("AZURE_STORAGE_KEY", "cGFzc3dk") + require.NoError(t, err) + defer os.Unsetenv("AZURE_STORAGE_KEY") + + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + SharedKey: "cGFzc2dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*sharedKeyClientBuilder) + require.True(t, ok) + require.Equal(t, "env_user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + + err = os.Setenv("AZURE_CLIENT_ID", "321") + require.NoError(t, err) + defer os.Unsetenv("AZURE_CLIENT_ID") + + err = os.Setenv("AZURE_TENANT_ID", "321") + require.NoError(t, err) + defer os.Unsetenv("AZURE_TENANT_ID") + + err = os.Setenv("AZURE_CLIENT_SECRET", "321") + require.NoError(t, err) + defer os.Unsetenv("AZURE_CLIENT_SECRET") + + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*tokenClientBuilder) + require.True(t, ok) + require.Equal(t, "env_user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + SharedKey: "cGFzc2dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*tokenClientBuilder) + require.True(t, ok) + require.Equal(t, "env_user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + AccountName: "user", + SharedKey: "cGFzc3dk", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*sharedKeyClientBuilder) + require.True(t, ok) + require.Equal(t, "user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + + { + options := &backuppb.AzureBlobStorage{ + Endpoint: "http://127.0.0.1:1000", + Bucket: "test", + Prefix: "a/b", + AccountName: "user", + } + builder, err := getAzureServiceClientBuilder(options, nil) + require.NoError(t, err) + b, ok := builder.(*tokenClientBuilder) + require.True(t, ok) + require.Equal(t, "user", b.GetAccountName()) + require.Equal(t, "http://127.0.0.1:1000", b.serviceURL) + } + +} diff --git a/br/pkg/storage/compress.go b/br/pkg/storage/compress.go index fc0976420996b..34e4796b34810 100644 --- a/br/pkg/storage/compress.go +++ b/br/pkg/storage/compress.go @@ -8,6 +8,7 @@ import ( "io" "github.com/pingcap/errors" + berrors "github.com/pingcap/tidb/br/pkg/errors" ) diff --git a/br/pkg/storage/compress_test.go b/br/pkg/storage/compress_test.go index b4222e04af153..4f7d315ebad4a 100644 --- a/br/pkg/storage/compress_test.go +++ b/br/pkg/storage/compress_test.go @@ -8,35 +8,36 @@ import ( "os" "path/filepath" "strings" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -func (r *testStorageSuite) TestWithCompressReadWriteFile(c *C) { - dir := c.MkDir() +func TestWithCompressReadWriteFile(t *testing.T) { + dir := t.TempDir() backend, err := ParseBackend("local://"+filepath.ToSlash(dir), nil) - c.Assert(err, IsNil) + require.NoError(t, err) ctx := context.Background() storage, err := Create(ctx, backend, true) - c.Assert(err, IsNil) + require.NoError(t, err) storage = WithCompression(storage, Gzip) name := "with compress test" content := "hello,world!" fileName := strings.ReplaceAll(name, " ", "-") + ".txt.gz" err = storage.WriteFile(ctx, fileName, []byte(content)) - c.Assert(err, IsNil) + require.NoError(t, err) // make sure compressed file is written correctly file, err := os.Open(filepath.Join(dir, fileName)) - c.Assert(err, IsNil) + require.NoError(t, err) uncompressedFile, err := newCompressReader(Gzip, file) - c.Assert(err, IsNil) + require.NoError(t, err) newContent, err := io.ReadAll(uncompressedFile) - c.Assert(err, IsNil) - c.Assert(string(newContent), Equals, content) + require.NoError(t, err) + require.Equal(t, content, string(newContent)) // test withCompression ReadFile newContent, err = storage.ReadFile(ctx, fileName) - c.Assert(err, IsNil) - c.Assert(string(newContent), Equals, content) + require.NoError(t, err) + require.Equal(t, content, string(newContent)) } diff --git a/br/pkg/storage/flags.go b/br/pkg/storage/flags.go index 4dc54d31f2175..9be015fe37c32 100644 --- a/br/pkg/storage/flags.go +++ b/br/pkg/storage/flags.go @@ -11,6 +11,7 @@ import ( func DefineFlags(flags *pflag.FlagSet) { defineS3Flags(flags) defineGCSFlags(flags) + defineAzblobFlags(flags) } // ParseFromFlags obtains the backend options from the flag set. @@ -18,5 +19,11 @@ func (options *BackendOptions) ParseFromFlags(flags *pflag.FlagSet) error { if err := options.S3.parseFromFlags(flags); err != nil { return errors.Trace(err) } - return options.GCS.parseFromFlags(flags) + if err := options.GCS.parseFromFlags(flags); err != nil { + return errors.Trace(err) + } + if err := options.Azblob.parseFromFlags(flags); err != nil { + return errors.Trace(err) + } + return nil } diff --git a/br/pkg/storage/gcs.go b/br/pkg/storage/gcs.go index c54141b8ee560..9a705a1f855cf 100644 --- a/br/pkg/storage/gcs.go +++ b/br/pkg/storage/gcs.go @@ -187,7 +187,10 @@ func (s *gcsStorage) WalkDir(ctx context.Context, opt *WalkOption, fn func(strin query := &storage.Query{Prefix: prefix} // only need each object's name and size - query.SetAttrSelection([]string{"Name", "Size"}) + err := query.SetAttrSelection([]string{"Name", "Size"}) + if err != nil { + return errors.Trace(err) + } iter := s.bucket.Objects(ctx, query) for { attrs, err := iter.Next() @@ -221,6 +224,19 @@ func (s *gcsStorage) Create(ctx context.Context, name string) (ExternalFileWrite return newFlushStorageWriter(wc, &emptyFlusher{}, wc), nil } +// Rename file name from oldFileName to newFileName. +func (s *gcsStorage) Rename(ctx context.Context, oldFileName, newFileName string) error { + data, err := s.ReadFile(ctx, oldFileName) + if err != nil { + return errors.Trace(err) + } + err = s.WriteFile(ctx, newFileName, data) + if err != nil { + return errors.Trace(err) + } + return s.DeleteFile(ctx, oldFileName) +} + func newGCSStorage(ctx context.Context, gcs *backuppb.GCS, opts *ExternalStorageOptions) (*gcsStorage, error) { var clientOps []option.ClientOption if opts.NoCredentials { diff --git a/br/pkg/storage/gcs_test.go b/br/pkg/storage/gcs_test.go index ccf3927497bea..39578d2258c7d 100644 --- a/br/pkg/storage/gcs_test.go +++ b/br/pkg/storage/gcs_test.go @@ -7,20 +7,21 @@ import ( "fmt" "io" "os" + "testing" "github.com/fsouza/fake-gcs-server/fakestorage" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/stretchr/testify/require" ) -func (r *testStorageSuite) TestGCS(c *C) { +func TestGCS(t *testing.T) { ctx := context.Background() opts := fakestorage.Options{ NoListener: true, } server, err := fakestorage.NewServerWithOptions(opts) - c.Assert(err, IsNil) + require.NoError(t, err) bucketName := "testbucket" server.CreateBucketWithOpts(fakestorage.CreateBucketOpts{Name: bucketName}) @@ -36,54 +37,54 @@ func (r *testStorageSuite) TestGCS(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) + require.NoError(t, err) err = stg.WriteFile(ctx, "key", []byte("data")) - c.Assert(err, IsNil) + require.NoError(t, err) err = stg.WriteFile(ctx, "key1", []byte("data1")) - c.Assert(err, IsNil) + require.NoError(t, err) err = stg.WriteFile(ctx, "key2", []byte("data22223346757222222222289722222")) - c.Assert(err, IsNil) + require.NoError(t, err) rc, err := server.Client().Bucket(bucketName).Object("a/b/key").NewReader(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) d, err := io.ReadAll(rc) - rc.Close() - c.Assert(err, IsNil) - c.Assert(d, DeepEquals, []byte("data")) + require.NoError(t, err) + require.Equal(t, []byte("data"), d) + require.NoError(t, rc.Close()) d, err = stg.ReadFile(ctx, "key") - c.Assert(err, IsNil) - c.Assert(d, DeepEquals, []byte("data")) + require.NoError(t, err) + require.Equal(t, []byte("data"), d) exist, err := stg.FileExists(ctx, "key") - c.Assert(err, IsNil) - c.Assert(exist, IsTrue) + require.NoError(t, err) + require.True(t, exist) exist, err = stg.FileExists(ctx, "key_not_exist") - c.Assert(err, IsNil) - c.Assert(exist, IsFalse) + require.NoError(t, err) + require.False(t, exist) keyDelete := "key_delete" exist, err = stg.FileExists(ctx, keyDelete) - c.Assert(err, IsNil) - c.Assert(exist, IsFalse) + require.NoError(t, err) + require.False(t, exist) err = stg.WriteFile(ctx, keyDelete, []byte("data")) - c.Assert(err, IsNil) + require.NoError(t, err) exist, err = stg.FileExists(ctx, keyDelete) - c.Assert(err, IsNil) - c.Assert(exist, IsTrue) + require.NoError(t, err) + require.True(t, exist) err = stg.DeleteFile(ctx, keyDelete) - c.Assert(err, IsNil) + require.NoError(t, err) exist, err = stg.FileExists(ctx, keyDelete) - c.Assert(err, IsNil) - c.Assert(exist, IsFalse) + require.NoError(t, err) + require.False(t, exist) list := "" var totalSize int64 = 0 @@ -92,15 +93,15 @@ func (r *testStorageSuite) TestGCS(c *C) { totalSize += size return nil }) - c.Assert(err, IsNil) - c.Assert(list, Equals, "keykey1key2") - c.Assert(totalSize, Equals, int64(42)) + require.NoError(t, err) + require.Equal(t, "keykey1key2", list) + require.Equal(t, int64(42), totalSize) // test 1003 files totalSize = 0 for i := 0; i < 1000; i += 1 { err = stg.WriteFile(ctx, fmt.Sprintf("f%d", i), []byte("data")) - c.Assert(err, IsNil) + require.NoError(t, err) } filesSet := make(map[string]struct{}, 1003) err = stg.WalkDir(ctx, nil, func(name string, size int64) error { @@ -108,83 +109,83 @@ func (r *testStorageSuite) TestGCS(c *C) { totalSize += size return nil }) - c.Assert(err, IsNil) - c.Assert(totalSize, Equals, int64(42+4000)) + require.NoError(t, err) + require.Equal(t, int64(42+4000), totalSize) _, ok := filesSet["key"] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = filesSet["key1"] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = filesSet["key2"] - c.Assert(ok, IsTrue) + require.True(t, ok) for i := 0; i < 1000; i += 1 { _, ok = filesSet[fmt.Sprintf("f%d", i)] - c.Assert(ok, IsTrue) + require.True(t, ok) } efr, err := stg.Open(ctx, "key2") - c.Assert(err, IsNil) + require.NoError(t, err) p := make([]byte, 10) n, err := efr.Read(p) - c.Assert(err, IsNil) - c.Assert(n, Equals, 10) - c.Assert(string(p), Equals, "data222233") + require.NoError(t, err) + require.Equal(t, 10, n) + require.Equal(t, "data222233", string(p)) p = make([]byte, 40) n, err = efr.Read(p) - c.Assert(err, IsNil) - c.Assert(n, Equals, 23) - c.Assert(string(p[:23]), Equals, "46757222222222289722222") + require.NoError(t, err) + require.Equal(t, 23, n) + require.Equal(t, "46757222222222289722222", string(p[:23])) p = make([]byte, 5) offs, err := efr.Seek(3, io.SeekStart) - c.Assert(err, IsNil) - c.Assert(offs, Equals, int64(3)) + require.NoError(t, err) + require.Equal(t, int64(3), offs) n, err = efr.Read(p) - c.Assert(err, IsNil) - c.Assert(n, Equals, 5) - c.Assert(string(p), Equals, "a2222") + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "a2222", string(p)) p = make([]byte, 5) offs, err = efr.Seek(3, io.SeekCurrent) - c.Assert(err, IsNil) - c.Assert(offs, Equals, int64(11)) + require.NoError(t, err) + require.Equal(t, int64(11), offs) n, err = efr.Read(p) - c.Assert(err, IsNil) - c.Assert(n, Equals, 5) - c.Assert(string(p), Equals, "67572") + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "67572", string(p)) /* Since fake_gcs_server hasn't support for negative offset yet. p = make([]byte, 5) offs, err = efr.Seek(int64(-7), io.SeekEnd) - c.Assert(err, IsNil) - c.Assert(offs, Equals, int64(-7)) + require.NoError(t, err) + require.Equal(t, int64(-7), offs) n, err = efr.Read(p) - c.Assert(err, IsNil) - c.Assert(n, Equals, 5) - c.Assert(string(p), Equals, "97222") + require.NoError(t, err) + require.Equal(t, 5, n) + require.Equal(t, "97222", string(p)) */ err = efr.Close() - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(stg.URI(), Equals, "gcs://testbucket/a/b/") + require.Equal(t, "gcs://testbucket/a/b/", stg.URI()) } -func (r *testStorageSuite) TestNewGCSStorage(c *C) { +func TestNewGCSStorage(t *testing.T) { ctx := context.Background() opts := fakestorage.Options{ NoListener: true, } - server, err1 := fakestorage.NewServerWithOptions(opts) - c.Assert(err1, IsNil) + server, err := fakestorage.NewServerWithOptions(opts) + require.NoError(t, err) bucketName := "testbucket" server.CreateBucketWithOpts(fakestorage.CreateBucketOpts{Name: bucketName}) - testDir := c.MkDir() + testDir := t.TempDir() { gcs := &backuppb.GCS{ @@ -199,8 +200,8 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) - c.Assert(gcs.CredentialsBlob, Equals, "FakeCredentials") + require.NoError(t, err) + require.Equal(t, "FakeCredentials", gcs.CredentialsBlob) } { @@ -216,22 +217,24 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) - c.Assert(gcs.CredentialsBlob, Equals, "") + require.NoError(t, err) + require.Equal(t, "", gcs.CredentialsBlob) } { fakeCredentialsFile, err := os.CreateTemp(testDir, "fakeCredentialsFile") - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - fakeCredentialsFile.Close() - os.Remove(fakeCredentialsFile.Name()) + require.NoError(t, fakeCredentialsFile.Close()) + require.NoError(t, os.Remove(fakeCredentialsFile.Name())) }() _, err = fakeCredentialsFile.Write([]byte(`{"type": "service_account"}`)) - c.Assert(err, IsNil) + require.NoError(t, err) err = os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", fakeCredentialsFile.Name()) - defer os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS") - c.Assert(err, IsNil) + defer func() { + require.NoError(t, os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS")) + }() + require.NoError(t, err) gcs := &backuppb.GCS{ Bucket: bucketName, @@ -245,22 +248,24 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) - c.Assert(gcs.CredentialsBlob, Equals, `{"type": "service_account"}`) + require.NoError(t, err) + require.Equal(t, `{"type": "service_account"}`, gcs.CredentialsBlob) } { fakeCredentialsFile, err := os.CreateTemp(testDir, "fakeCredentialsFile") - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - fakeCredentialsFile.Close() - os.Remove(fakeCredentialsFile.Name()) + require.NoError(t, fakeCredentialsFile.Close()) + require.NoError(t, os.Remove(fakeCredentialsFile.Name())) }() _, err = fakeCredentialsFile.Write([]byte(`{"type": "service_account"}`)) - c.Assert(err, IsNil) + require.NoError(t, err) err = os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", fakeCredentialsFile.Name()) - defer os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS") - c.Assert(err, IsNil) + defer func() { + require.NoError(t, os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS")) + }() + require.NoError(t, err) gcs := &backuppb.GCS{ Bucket: bucketName, @@ -274,13 +279,13 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) - c.Assert(gcs.CredentialsBlob, Equals, "") - c.Assert(s.objectName("x"), Equals, "a/b/x") + require.NoError(t, err) + require.Equal(t, "", gcs.CredentialsBlob) + require.Equal(t, "a/b/x", s.objectName("x")) } { - os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS") + require.NoError(t, os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS")) gcs := &backuppb.GCS{ Bucket: bucketName, Prefix: "a/b/", @@ -293,7 +298,7 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, NotNil) + require.Error(t, err) } { @@ -309,8 +314,8 @@ func (r *testStorageSuite) TestNewGCSStorage(c *C) { CheckPermissions: []Permission{AccessBuckets}, HTTPClient: server.HTTPClient(), }) - c.Assert(err, IsNil) - c.Assert(gcs.CredentialsBlob, Equals, "") - c.Assert(s.objectName("x"), Equals, "a/b/x") + require.NoError(t, err) + require.Equal(t, "", gcs.CredentialsBlob) + require.Equal(t, "a/b/x", s.objectName("x")) } } diff --git a/br/pkg/storage/hdfs.go b/br/pkg/storage/hdfs.go index cbcc24088292f..3dc8e7a8d6491 100644 --- a/br/pkg/storage/hdfs.go +++ b/br/pkg/storage/hdfs.go @@ -49,6 +49,7 @@ func dfsCommand(args ...string) (*exec.Cmd, error) { } cmd = append(cmd, bin, "dfs") cmd = append(cmd, args...) + //nolint:gosec return exec.Command(cmd[0], cmd[1:]...), nil } @@ -124,3 +125,8 @@ func (s *HDFSStorage) URI() string { func (s *HDFSStorage) Create(ctx context.Context, path string) (ExternalFileWriter, error) { return nil, errors.Annotatef(berrors.ErrUnsupportedOperation, "currently HDFS backend only support rawkv backup") } + +// Rename a file name from oldFileName to newFileName. +func (s *HDFSStorage) Rename(ctx context.Context, oldFileName, newFileName string) error { + return errors.Annotatef(berrors.ErrUnsupportedOperation, "currently HDFS backend only support rawkv backup") +} diff --git a/br/pkg/storage/local.go b/br/pkg/storage/local.go index 65da8efd1d53f..6ba9b50070779 100644 --- a/br/pkg/storage/local.go +++ b/br/pkg/storage/local.go @@ -32,9 +32,16 @@ func (l *LocalStorage) DeleteFile(ctx context.Context, name string) error { // WriteFile writes data to a file to storage. func (l *LocalStorage) WriteFile(ctx context.Context, name string, data []byte) error { - path := filepath.Join(l.base, name) - return os.WriteFile(path, data, localFilePerm) - // the backup meta file _is_ intended to be world-readable. + // because `os.WriteFile` is not atomic, directly write into it may reset the file + // to an empty file if write is not finished. + tmpPath := filepath.Join(l.base, name) + ".tmp" + if err := os.WriteFile(tmpPath, data, localFilePerm); err != nil { + return errors.Trace(err) + } + if err := os.Rename(tmpPath, filepath.Join(l.base, name)); err != nil { + return errors.Trace(err) + } + return nil } // ReadFile reads the file from the storage and returns the contents. @@ -106,6 +113,11 @@ func (l *LocalStorage) Create(ctx context.Context, name string) (ExternalFileWri return newFlushStorageWriter(buf, buf, file), nil } +// Rename implements ExternalStorage interface. +func (l *LocalStorage) Rename(ctx context.Context, oldFileName, newFileName string) error { + return errors.Trace(os.Rename(filepath.Join(l.base, oldFileName), filepath.Join(l.base, newFileName))) +} + func pathExists(_path string) (bool, error) { _, err := os.Stat(_path) if err != nil { diff --git a/br/pkg/storage/local_test.go b/br/pkg/storage/local_test.go index 54eed83cd47bd..ac94476d190b9 100644 --- a/br/pkg/storage/local_test.go +++ b/br/pkg/storage/local_test.go @@ -7,88 +7,85 @@ import ( "os" "path/filepath" "runtime" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -type testLocalSuite struct{} - -var _ = Suite(&testLocalSuite{}) - -func (r *testStorageSuite) TestDeleteFile(c *C) { - dir := c.MkDir() +func TestDeleteFile(t *testing.T) { + dir := t.TempDir() sb, err := ParseBackend("file://"+filepath.ToSlash(dir), &BackendOptions{}) - c.Assert(err, IsNil) + require.NoError(t, err) store, err := Create(context.TODO(), sb, true) - c.Assert(err, IsNil) + require.NoError(t, err) name := "test_delete" ret, err := store.FileExists(context.Background(), name) - c.Assert(err, IsNil) - c.Assert(ret, Equals, false) + require.NoError(t, err) + require.Equal(t, false, ret) _, err = store.Create(context.Background(), name) - c.Assert(err, IsNil) + require.NoError(t, err) ret, err = store.FileExists(context.Background(), name) - c.Assert(err, IsNil) - c.Assert(ret, Equals, true) + require.NoError(t, err) + require.Equal(t, true, ret) err = store.DeleteFile(context.Background(), name) - c.Assert(err, IsNil) + require.NoError(t, err) ret, err = store.FileExists(context.Background(), name) - c.Assert(err, IsNil) - c.Assert(ret, Equals, false) + require.NoError(t, err) + require.Equal(t, false, ret) } -func (r *testStorageSuite) TestWalkDirWithSoftLinkFile(c *C) { +func TestWalkDirWithSoftLinkFile(t *testing.T) { if runtime.GOOS == "windows" { // skip the test on windows. typically windows users don't have symlink permission. return } - dir1 := c.MkDir() + dir1 := t.TempDir() name1 := "test.warehouse.0.sql" path1 := filepath.Join(dir1, name1) f1, err := os.Create(path1) - c.Assert(err, IsNil) + require.NoError(t, err) data := "/* whatever pragmas */;" + "INSERT INTO `namespaced`.`table` (columns, more, columns) VALUES (1,-2, 3),\n(4,5., 6);" + "INSERT `namespaced`.`table` (x,y,z) VALUES (7,8,9);" + "insert another_table values (10,11e1,12, '(13)', '(', 14, ')');" _, err = f1.Write([]byte(data)) - c.Assert(err, IsNil) + require.NoError(t, err) err = f1.Close() - c.Assert(err, IsNil) + require.NoError(t, err) - dir2 := c.MkDir() + dir2 := t.TempDir() name2 := "test.warehouse.1.sql" f2, err := os.Create(filepath.Join(dir2, name2)) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = f2.Write([]byte(data)) - c.Assert(err, IsNil) + require.NoError(t, err) err = f2.Close() - c.Assert(err, IsNil) + require.NoError(t, err) err = os.Symlink(path1, filepath.Join(dir2, name1)) - c.Assert(err, IsNil) + require.NoError(t, err) sb, err := ParseBackend("file://"+filepath.ToSlash(dir2), &BackendOptions{}) - c.Assert(err, IsNil) + require.NoError(t, err) store, err := Create(context.TODO(), sb, true) - c.Assert(err, IsNil) + require.NoError(t, err) i := 0 names := []string{name1, name2} err = store.WalkDir(context.TODO(), &WalkOption{}, func(path string, size int64) error { - c.Assert(path, Equals, names[i]) - c.Assert(size, Equals, int64(len(data))) + require.Equal(t, names[i], path) + require.Equal(t, int64(len(data)), size) i++ return nil }) - c.Assert(err, IsNil) - c.Assert(i, Equals, 2) + require.NoError(t, err) + require.Equal(t, 2, i) } diff --git a/br/pkg/storage/noop.go b/br/pkg/storage/noop.go index ead3c9ed706af..41788a1f37cd4 100644 --- a/br/pkg/storage/noop.go +++ b/br/pkg/storage/noop.go @@ -47,6 +47,11 @@ func (*noopStorage) Create(ctx context.Context, name string) (ExternalFileWriter return &noopWriter{}, nil } +// Rename implements ExternalStorage interface. +func (*noopStorage) Rename(ctx context.Context, oldFileName, newFileName string) error { + return nil +} + func newNoopStorage() *noopStorage { return &noopStorage{} } diff --git a/br/pkg/storage/parse.go b/br/pkg/storage/parse.go index d5c7e5edec48d..39aa8743f6d53 100644 --- a/br/pkg/storage/parse.go +++ b/br/pkg/storage/parse.go @@ -17,8 +17,9 @@ import ( // BackendOptions further configures the storage backend not expressed by the // storage URL. type BackendOptions struct { - S3 S3BackendOptions `json:"s3" toml:"s3"` - GCS GCSBackendOptions `json:"gcs" toml:"gcs"` + S3 S3BackendOptions `json:"s3" toml:"s3"` + GCS GCSBackendOptions `json:"gcs" toml:"gcs"` + Azblob AzblobBackendOptions `json:"azblob" toml:"azblob"` } // ParseRawURL parse raw url to url object. @@ -95,6 +96,20 @@ func ParseBackend(rawURL string, options *BackendOptions) (*backuppb.StorageBack } return &backuppb.StorageBackend{Backend: &backuppb.StorageBackend_Gcs{Gcs: gcs}}, nil + case "azure", "azblob": + if u.Host == "" { + return nil, errors.Annotatef(berrors.ErrStorageInvalidConfig, "please specify the bucket for azblob in %s", rawURL) + } + prefix := strings.Trim(u.Path, "/") + azblob := &backuppb.AzureBlobStorage{Bucket: u.Host, Prefix: prefix} + if options == nil { + options = &BackendOptions{} + } + ExtractQueryParameters(u, &options.Azblob) + if err := options.Azblob.apply(azblob); err != nil { + return nil, errors.Trace(err) + } + return &backuppb.StorageBackend{Backend: &backuppb.StorageBackend_AzureBlobStorage{AzureBlobStorage: azblob}}, nil default: return nil, errors.Annotatef(berrors.ErrStorageInvalidConfig, "storage %s not support yet", u.Scheme) } @@ -170,6 +185,10 @@ func FormatBackendURL(backend *backuppb.StorageBackend) (u url.URL) { u.Scheme = "gcs" u.Host = b.Gcs.Bucket u.Path = b.Gcs.Prefix + case *backuppb.StorageBackend_AzureBlobStorage: + u.Scheme = "azure" + u.Host = b.AzureBlobStorage.Bucket + u.Path = b.AzureBlobStorage.Prefix } return } diff --git a/br/pkg/storage/parse_test.go b/br/pkg/storage/parse_test.go index fc3ee47a095b7..90f72d0778407 100644 --- a/br/pkg/storage/parse_test.go +++ b/br/pkg/storage/parse_test.go @@ -8,43 +8,38 @@ import ( "path/filepath" "testing" - . "github.com/pingcap/check" backuppb "github.com/pingcap/kvproto/pkg/brpb" + "github.com/stretchr/testify/require" ) -func Test(t *testing.T) { - TestingT(t) -} - -type testStorageSuite struct{} - -var _ = Suite(&testStorageSuite{}) - -func (r *testStorageSuite) TestCreateStorage(c *C) { +func TestCreateStorage(t *testing.T) { _, err := ParseBackend("1invalid:", nil) - c.Assert(err, ErrorMatches, "parse (.*)1invalid:(.*): first path segment in URL cannot contain colon") + require.Error(t, err) + require.Regexp(t, "parse (.*)1invalid:(.*): first path segment in URL cannot contain colon", err.Error()) _, err = ParseBackend("net:storage", nil) - c.Assert(err, ErrorMatches, "storage net not support yet.*") + require.Error(t, err) + require.Regexp(t, "storage net not support yet.*", err.Error()) s, err := ParseBackend("local:///tmp/storage", nil) - c.Assert(err, IsNil) - c.Assert(s.GetLocal().GetPath(), Equals, "/tmp/storage") + require.NoError(t, err) + require.Equal(t, "/tmp/storage", s.GetLocal().GetPath()) s, err = ParseBackend("file:///tmp/storage", nil) - c.Assert(err, IsNil) - c.Assert(s.GetLocal().GetPath(), Equals, "/tmp/storage") + require.NoError(t, err) + require.Equal(t, "/tmp/storage", s.GetLocal().GetPath()) s, err = ParseBackend("noop://", nil) - c.Assert(err, IsNil) - c.Assert(s.GetNoop(), NotNil) + require.NoError(t, err) + require.NotNil(t, s.GetNoop()) s, err = ParseBackend("hdfs://127.0.0.1:1231/backup", nil) - c.Assert(err, IsNil) - c.Assert(s.GetHdfs().GetRemote(), Equals, "hdfs://127.0.0.1:1231/backup") + require.NoError(t, err) + require.Equal(t, "hdfs://127.0.0.1:1231/backup", s.GetHdfs().GetRemote()) _, err = ParseBackend("s3:///bucket/more/prefix/", &BackendOptions{}) - c.Assert(err, ErrorMatches, `please specify the bucket for s3 in s3:///bucket/more/prefix/.*`) + require.Error(t, err) + require.Regexp(t, `please specify the bucket for s3 in s3:///bucket/more/prefix/.*`, err.Error()) s3opt := &BackendOptions{ S3: S3BackendOptions{ @@ -52,36 +47,36 @@ func (r *testStorageSuite) TestCreateStorage(c *C) { }, } s, err = ParseBackend("s3://bucket2/prefix/", s3opt) - c.Assert(err, IsNil) + require.NoError(t, err) s3 := s.GetS3() - c.Assert(s3, NotNil) - c.Assert(s3.Bucket, Equals, "bucket2") - c.Assert(s3.Prefix, Equals, "prefix") - c.Assert(s3.Endpoint, Equals, "https://s3.example.com/") - c.Assert(s3.ForcePathStyle, IsFalse) + require.NotNil(t, s3) + require.Equal(t, "bucket2", s3.Bucket) + require.Equal(t, "prefix", s3.Prefix) + require.Equal(t, "https://s3.example.com", s3.Endpoint) + require.False(t, s3.ForcePathStyle) // nolint:lll s, err = ParseBackend(`s3://bucket3/prefix/path?endpoint=https://127.0.0.1:9000&force_path_style=0&SSE=aws:kms&sse-kms-key-id=TestKey&xyz=abc`, nil) - c.Assert(err, IsNil) + require.NoError(t, err) s3 = s.GetS3() - c.Assert(s3, NotNil) - c.Assert(s3.Bucket, Equals, "bucket3") - c.Assert(s3.Prefix, Equals, "prefix/path") - c.Assert(s3.Endpoint, Equals, "https://127.0.0.1:9000") - c.Assert(s3.ForcePathStyle, IsFalse) - c.Assert(s3.Sse, Equals, "aws:kms") - c.Assert(s3.SseKmsKeyId, Equals, "TestKey") + require.NotNil(t, s3) + require.Equal(t, "bucket3", s3.Bucket) + require.Equal(t, "prefix/path", s3.Prefix) + require.Equal(t, "https://127.0.0.1:9000", s3.Endpoint) + require.False(t, s3.ForcePathStyle) + require.Equal(t, "aws:kms", s3.Sse) + require.Equal(t, "TestKey", s3.SseKmsKeyId) // special character in access keys s, err = ParseBackend(`s3://bucket4/prefix/path?access-key=NXN7IPIOSAAKDEEOLMAF&secret-access-key=nREY/7Dt+PaIbYKrKlEEMMF/ExCiJEX=XMLPUANw`, nil) - c.Assert(err, IsNil) + require.NoError(t, err) s3 = s.GetS3() - c.Assert(s3, NotNil) - c.Assert(s3.Bucket, Equals, "bucket4") - c.Assert(s3.Prefix, Equals, "prefix/path") - c.Assert(s3.AccessKey, Equals, "NXN7IPIOSAAKDEEOLMAF") - c.Assert(s3.SecretAccessKey, Equals, "nREY/7Dt+PaIbYKrKlEEMMF/ExCiJEX=XMLPUANw") - c.Assert(s3.ForcePathStyle, IsTrue) + require.NotNil(t, s3) + require.Equal(t, "bucket4", s3.Bucket) + require.Equal(t, "prefix/path", s3.Prefix) + require.Equal(t, "NXN7IPIOSAAKDEEOLMAF", s3.AccessKey) + require.Equal(t, "nREY/7Dt+PaIbYKrKlEEMMF/ExCiJEX=XMLPUANw", s3.SecretAccessKey) + require.True(t, s3.ForcePathStyle) gcsOpt := &BackendOptions{ GCS: GCSBackendOptions{ @@ -89,74 +84,84 @@ func (r *testStorageSuite) TestCreateStorage(c *C) { }, } s, err = ParseBackend("gcs://bucket2/prefix/", gcsOpt) - c.Assert(err, IsNil) + require.NoError(t, err) gcs := s.GetGcs() - c.Assert(gcs, NotNil) - c.Assert(gcs.Bucket, Equals, "bucket2") - c.Assert(gcs.Prefix, Equals, "prefix") - c.Assert(gcs.Endpoint, Equals, "https://gcs.example.com/") - c.Assert(gcs.CredentialsBlob, Equals, "") + require.NotNil(t, gcs) + require.Equal(t, "bucket2", gcs.Bucket) + require.Equal(t, "prefix", gcs.Prefix) + require.Equal(t, "https://gcs.example.com/", gcs.Endpoint) + require.Equal(t, "", gcs.CredentialsBlob) s, err = ParseBackend("gcs://bucket2", gcsOpt) - c.Assert(err, IsNil) + require.NoError(t, err) gcs = s.GetGcs() - c.Assert(gcs, NotNil) - c.Assert(gcs.Bucket, Equals, "bucket2") - c.Assert(gcs.Prefix, Equals, "") - c.Assert(gcs.Endpoint, Equals, "https://gcs.example.com/") - c.Assert(gcs.CredentialsBlob, Equals, "") + require.NotNil(t, gcs) + require.Equal(t, "bucket2", gcs.Bucket) + require.Equal(t, "", gcs.Prefix) + require.Equal(t, "https://gcs.example.com/", gcs.Endpoint) + require.Equal(t, "", gcs.CredentialsBlob) - var credFeilPerm os.FileMode = 0o600 - fakeCredentialsFile := filepath.Join(c.MkDir(), "fakeCredentialsFile") - err = os.WriteFile(fakeCredentialsFile, []byte("fakeCredentials"), credFeilPerm) - c.Assert(err, IsNil) + var credFilePerm os.FileMode = 0o600 + fakeCredentialsFile := filepath.Join(t.TempDir(), "fakeCredentialsFile") + err = os.WriteFile(fakeCredentialsFile, []byte("fakeCredentials"), credFilePerm) + require.NoError(t, err) gcsOpt.GCS.CredentialsFile = fakeCredentialsFile s, err = ParseBackend("gcs://bucket/more/prefix/", gcsOpt) - c.Assert(err, IsNil) + require.NoError(t, err) gcs = s.GetGcs() - c.Assert(gcs, NotNil) - c.Assert(gcs.Bucket, Equals, "bucket") - c.Assert(gcs.Prefix, Equals, "more/prefix") - c.Assert(gcs.Endpoint, Equals, "https://gcs.example.com/") - c.Assert(gcs.CredentialsBlob, Equals, "fakeCredentials") - - err = os.WriteFile(fakeCredentialsFile, []byte("fakeCreds2"), credFeilPerm) - c.Assert(err, IsNil) + require.NotNil(t, gcs) + require.Equal(t, "bucket", gcs.Bucket) + require.Equal(t, "more/prefix", gcs.Prefix) + require.Equal(t, "https://gcs.example.com/", gcs.Endpoint) + require.Equal(t, "fakeCredentials", gcs.CredentialsBlob) + + err = os.WriteFile(fakeCredentialsFile, []byte("fakeCreds2"), credFilePerm) + require.NoError(t, err) s, err = ParseBackend("gs://bucket4/backup/?credentials-file="+url.QueryEscape(fakeCredentialsFile), nil) - c.Assert(err, IsNil) + require.NoError(t, err) gcs = s.GetGcs() - c.Assert(gcs, NotNil) - c.Assert(gcs.Bucket, Equals, "bucket4") - c.Assert(gcs.Prefix, Equals, "backup") - c.Assert(gcs.CredentialsBlob, Equals, "fakeCreds2") + require.NotNil(t, gcs) + require.Equal(t, "bucket4", gcs.Bucket) + require.Equal(t, "backup", gcs.Prefix) + require.Equal(t, "fakeCreds2", gcs.CredentialsBlob) + + s, err = ParseBackend(`azure://bucket1/prefix/path?account-name=user&account-key=cGFzc3dk&endpoint=http://127.0.0.1/user`, nil) + require.NoError(t, err) + azblob := s.GetAzureBlobStorage() + require.NotNil(t, azblob) + require.Equal(t, "bucket1", azblob.Bucket) + require.Equal(t, "prefix/path", azblob.Prefix) + require.Equal(t, "http://127.0.0.1/user", azblob.Endpoint) + require.Equal(t, "user", azblob.AccountName) + require.Equal(t, "cGFzc3dk", azblob.SharedKey) s, err = ParseBackend("/test", nil) - c.Assert(err, IsNil) + require.NoError(t, err) local := s.GetLocal() - c.Assert(local, NotNil) + require.NotNil(t, local) expectedLocalPath, err := filepath.Abs("/test") - c.Assert(err, IsNil) - c.Assert(local.GetPath(), Equals, expectedLocalPath) + require.NoError(t, err) + require.Equal(t, expectedLocalPath, local.GetPath()) } -func (r *testStorageSuite) TestFormatBackendURL(c *C) { - url := FormatBackendURL(&backuppb.StorageBackend{ +func TestFormatBackendURL(t *testing.T) { + backendURL := FormatBackendURL(&backuppb.StorageBackend{ Backend: &backuppb.StorageBackend_Local{ Local: &backuppb.Local{Path: "/tmp/file"}, }, }) - c.Assert(url.String(), Equals, "local:///tmp/file") + require.Equal(t, "local:///tmp/file", backendURL.String()) - url = FormatBackendURL(&backuppb.StorageBackend{ + backendURL = FormatBackendURL(&backuppb.StorageBackend{ Backend: &backuppb.StorageBackend_Noop{ Noop: &backuppb.Noop{}, }, }) - c.Assert(url.String(), Equals, "noop:///") + require.Equal(t, "noop:///", backendURL.String()) - url = FormatBackendURL(&backuppb.StorageBackend{ + backendURL = FormatBackendURL(&backuppb.StorageBackend{ Backend: &backuppb.StorageBackend_S3{ S3: &backuppb.S3{ Bucket: "bucket", @@ -165,9 +170,9 @@ func (r *testStorageSuite) TestFormatBackendURL(c *C) { }, }, }) - c.Assert(url.String(), Equals, "s3://bucket/some%20prefix/") + require.Equal(t, "s3://bucket/some%20prefix/", backendURL.String()) - url = FormatBackendURL(&backuppb.StorageBackend{ + backendURL = FormatBackendURL(&backuppb.StorageBackend{ Backend: &backuppb.StorageBackend_Gcs{ Gcs: &backuppb.GCS{ Bucket: "bucket", @@ -176,5 +181,16 @@ func (r *testStorageSuite) TestFormatBackendURL(c *C) { }, }, }) - c.Assert(url.String(), Equals, "gcs://bucket/some%20prefix/") + require.Equal(t, "gcs://bucket/some%20prefix/", backendURL.String()) + + backendURL = FormatBackendURL(&backuppb.StorageBackend{ + Backend: &backuppb.StorageBackend_AzureBlobStorage{ + AzureBlobStorage: &backuppb.AzureBlobStorage{ + Bucket: "bucket", + Prefix: "/some prefix/", + Endpoint: "https://azure.example.com/", + }, + }, + }) + require.Equal(t, "azure://bucket/some%20prefix/", backendURL.String()) } diff --git a/br/pkg/storage/s3.go b/br/pkg/storage/s3.go index 6accafee7363d..fb07d93de36ad 100644 --- a/br/pkg/storage/s3.go +++ b/br/pkg/storage/s3.go @@ -25,10 +25,11 @@ import ( "github.com/pingcap/errors" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/log" - berrors "github.com/pingcap/tidb/br/pkg/errors" - "github.com/pingcap/tidb/br/pkg/logutil" "github.com/spf13/pflag" "go.uber.org/zap" + + berrors "github.com/pingcap/tidb/br/pkg/errors" + "github.com/pingcap/tidb/br/pkg/logutil" ) const ( @@ -155,7 +156,7 @@ func (options *S3BackendOptions) Apply(s3 *backuppb.S3) error { return errors.Annotate(berrors.ErrStorageInvalidConfig, "secret_access_key not found") } - s3.Endpoint = options.Endpoint + s3.Endpoint = strings.TrimSuffix(options.Endpoint, "/") s3.Region = options.Region // StorageClass, SSE and ACL are acceptable to be empty s3.StorageClass = options.StorageClass @@ -189,6 +190,7 @@ func (options *S3BackendOptions) parseFromFlags(flags *pflag.FlagSet) error { if err != nil { return errors.Trace(err) } + options.Endpoint = strings.TrimSuffix(options.Endpoint, "/") options.Region, err = flags.GetString(s3RegionOption) if err != nil { return errors.Trace(err) @@ -459,14 +461,6 @@ func (rs *S3Storage) WalkDir(ctx context.Context, opt *WalkOption, fn func(strin return errors.Trace(err) } for _, r := range res.Contents { - // when walk on specify directory, the result include storage.Prefix, - // which can not be reuse in other API(Open/Read) directly. - // so we use TrimPrefix to filter Prefix for next Open/Read. - path := strings.TrimPrefix(*r.Key, rs.options.Prefix) - if err = fn(path, *r.Size); err != nil { - return errors.Trace(err) - } - // https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html#AmazonS3-ListObjects-response-NextMarker - // // `res.NextMarker` is populated only if we specify req.Delimiter. @@ -477,6 +471,22 @@ func (rs *S3Storage) WalkDir(ctx context.Context, opt *WalkOption, fn func(strin // you can use the value of the last Key in the response as the marker // in the subsequent request to get the next set of object keys." req.Marker = r.Key + + // when walk on specify directory, the result include storage.Prefix, + // which can not be reuse in other API(Open/Read) directly. + // so we use TrimPrefix to filter Prefix for next Open/Read. + path := strings.TrimPrefix(*r.Key, rs.options.Prefix) + itemSize := *r.Size + + // filter out s3's empty directory items + if itemSize <= 0 && strings.HasSuffix(path, "/") { + log.Info("this path is an empty directory and cannot be opened in S3. Skip it", zap.String("path", path)) + continue + } + if err = fn(path, itemSize); err != nil { + return errors.Trace(err) + } + } if !aws.BoolValue(res.IsTruncated) { break @@ -531,12 +541,21 @@ func (rs *S3Storage) open( Key: aws.String(rs.options.Prefix + path), } - // always set rangeOffset to fetch file size info - // s3 endOffset is inclusive + // If we just open part of the object, we set `Range` in the request. + // If we meant to open the whole object, not just a part of it, + // we do not pass the range in the request, + // so that even if the object is empty, we can still get the response without errors. + // Then this behavior is similar to openning an empty file in local file system. + isFullRangeRequest := false var rangeOffset *string - if endOffset > startOffset { + switch { + case endOffset > startOffset: + // s3 endOffset is inclusive rangeOffset = aws.String(fmt.Sprintf("bytes=%d-%d", startOffset, endOffset-1)) - } else { + case startOffset == 0: + // openning the whole object, no need to fill the `Range` field in the request + isFullRangeRequest = true + default: rangeOffset = aws.String(fmt.Sprintf("bytes=%d-", startOffset)) } input.Range = rangeOffset @@ -545,9 +564,26 @@ func (rs *S3Storage) open( return nil, RangeInfo{}, errors.Trace(err) } - r, err := ParseRangeInfo(result.ContentRange) - if err != nil { - return nil, RangeInfo{}, errors.Trace(err) + var r RangeInfo + // Those requests without a `Range` will have no `ContentRange` in the response, + // In this case, we'll parse the `ContentLength` field instead. + if isFullRangeRequest { + // We must ensure the `ContentLengh` has data even if for empty objects, + // otherwise we have no places to get the object size + if result.ContentLength == nil { + return nil, RangeInfo{}, errors.Annotatef(berrors.ErrStorageUnknown, "open file '%s' failed. The S3 object has no content length", path) + } + objectSize := *(result.ContentLength) + r = RangeInfo{ + Start: 0, + End: objectSize - 1, + Size: objectSize, + } + } else { + r, err = ParseRangeInfo(result.ContentRange) + if err != nil { + return nil, RangeInfo{}, errors.Trace(err) + } } if startOffset != r.Start || (endOffset != 0 && endOffset != r.End+1) { @@ -655,6 +691,9 @@ func (r *s3ObjectReader) Seek(offset int64, whence int) (int64, error) { default: return 0, errors.Annotatef(berrors.ErrStorageUnknown, "Seek: invalid whence '%d'", whence) } + if realOffset < 0 { + return 0, errors.Annotatef(berrors.ErrStorageUnknown, "Seek in '%s': invalid offset to seek '%d'.", r.name, realOffset) + } if realOffset == r.pos { return realOffset, nil @@ -738,6 +777,22 @@ func (rs *S3Storage) Create(ctx context.Context, name string) (ExternalFileWrite return uploaderWriter, nil } +// Rename implements ExternalStorage interface. +func (rs *S3Storage) Rename(ctx context.Context, oldFileName, newFileName string) error { + content, err := rs.ReadFile(ctx, oldFileName) + if err != nil { + return errors.Trace(err) + } + err = rs.WriteFile(ctx, newFileName, content) + if err != nil { + return errors.Trace(err) + } + if err = rs.DeleteFile(ctx, oldFileName); err != nil { + return errors.Trace(err) + } + return nil +} + // retryerWithLog wrappes the client.DefaultRetryer, and logging when retry triggered. type retryerWithLog struct { client.DefaultRetryer diff --git a/br/pkg/storage/s3_test.go b/br/pkg/storage/s3_test.go index cf30828b07c65..4a8a39df67e50 100644 --- a/br/pkg/storage/s3_test.go +++ b/br/pkg/storage/s3_test.go @@ -10,17 +10,18 @@ import ( "io" "math/rand" "os" + "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/s3" "github.com/golang/mock/gomock" - . "github.com/pingcap/check" "github.com/pingcap/errors" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/tidb/br/pkg/mock" . "github.com/pingcap/tidb/br/pkg/storage" + "github.com/stretchr/testify/require" ) type s3Suite struct { @@ -29,17 +30,8 @@ type s3Suite struct { storage *S3Storage } -type s3SuiteCustom struct{} - -var ( - _ = Suite(&s3Suite{}) - _ = Suite(&s3SuiteCustom{}) -) - -// FIXME: Cannot use the real SetUpTest/TearDownTest to set up the mock -// otherwise the mock error will be ignored. - -func (s *s3Suite) setUpTest(c gomock.TestReporter) { +func createS3Suite(c gomock.TestReporter) (s *s3Suite, clean func()) { + s = new(s3Suite) s.controller = gomock.NewController(c) s.s3 = mock.NewMockS3API(s.controller) s.storage = NewS3StorageForTest( @@ -53,26 +45,29 @@ func (s *s3Suite) setUpTest(c gomock.TestReporter) { StorageClass: "sc", }, ) -} -func (s *s3Suite) tearDownTest() { - s.controller.Finish() + clean = func() { + s.controller.Finish() + } + + return } -func (s *s3Suite) TestApply(c *C) { +func TestApply(t *testing.T) { type testcase struct { name string options S3BackendOptions errMsg string errReturn bool } - testFn := func(test *testcase, c *C) { - c.Log(test.name) + testFn := func(test *testcase, t *testing.T) { + t.Log(test.name) _, err := ParseBackend("s3://bucket2/prefix/", &BackendOptions{S3: test.options}) if test.errReturn { - c.Assert(err, ErrorMatches, test.errMsg) + require.Error(t, err) + require.Regexp(t, test.errMsg, err.Error()) } else { - c.Assert(err, IsNil) + require.NoError(t, err) } } tests := []testcase{ @@ -120,27 +115,26 @@ func (s *s3Suite) TestApply(c *C) { }, } for i := range tests { - testFn(&tests[i], c) + testFn(&tests[i], t) } } -func (s *s3Suite) TestApplyUpdate(c *C) { +func TestApplyUpdate(t *testing.T) { type testcase struct { name string options S3BackendOptions setEnv bool s3 *backuppb.S3 } - testFn := func(test *testcase, c *C) { - c.Log(test.name) + testFn := func(test *testcase, t *testing.T) { + t.Log(test.name) if test.setEnv { - os.Setenv("AWS_ACCESS_KEY_ID", "ab") - os.Setenv("AWS_SECRET_ACCESS_KEY", "cd") + require.NoError(t, os.Setenv("AWS_ACCESS_KEY_ID", "ab")) + require.NoError(t, os.Setenv("AWS_SECRET_ACCESS_KEY", "cd")) } u, err := ParseBackend("s3://bucket/prefix/", &BackendOptions{S3: test.options}) - s3 := u.GetS3() - c.Assert(err, IsNil) - c.Assert(s3, DeepEquals, test.s3) + require.NoError(t, err) + require.Equal(t, test.s3, u.GetS3()) } tests := []testcase{ @@ -265,11 +259,11 @@ func (s *s3Suite) TestApplyUpdate(c *C) { }, } for i := range tests { - testFn(&tests[i], c) + testFn(&tests[i], t) } } -func (s *s3Suite) TestS3Storage(c *C) { +func TestS3Storage(t *testing.T) { type testcase struct { name string s3 *backuppb.S3 @@ -277,27 +271,26 @@ func (s *s3Suite) TestS3Storage(c *C) { hackPermission []Permission sendCredential bool } - testFn := func(test *testcase, c *C) { - c.Log(test.name) + testFn := func(test *testcase, t *testing.T) { + t.Log(test.name) ctx := aws.BackgroundContext() - s3 := &backuppb.StorageBackend{ + _, err := New(ctx, &backuppb.StorageBackend{ Backend: &backuppb.StorageBackend_S3{ S3: test.s3, }, - } - _, err := New(ctx, s3, &ExternalStorageOptions{ + }, &ExternalStorageOptions{ SendCredentials: test.sendCredential, CheckPermissions: test.hackPermission, }) if test.errReturn { - c.Assert(err, NotNil) + require.Error(t, err) return } - c.Assert(err, IsNil) + require.NoError(t, err) if test.sendCredential { - c.Assert(len(test.s3.AccessKey), Greater, 0) + require.Greater(t, len(test.s3.AccessKey), 0) } else { - c.Assert(len(test.s3.AccessKey), Equals, 0) + require.Equal(t, 0, len(test.s3.AccessKey)) } } tests := []testcase{ @@ -406,141 +399,139 @@ func (s *s3Suite) TestS3Storage(c *C) { }, } for i := range tests { - testFn(&tests[i], c) + testFn(&tests[i], t) } } -func (s *s3Suite) TestS3URI(c *C) { +func TestS3URI(t *testing.T) { backend, err := ParseBackend("s3://bucket/prefix/", nil) - c.Assert(err, IsNil) + require.NoError(t, err) storage, err := New(context.Background(), backend, &ExternalStorageOptions{}) - c.Assert(err, IsNil) - c.Assert(storage.URI(), Equals, "s3://bucket/prefix/") + require.NoError(t, err) + require.Equal(t, "s3://bucket/prefix/", storage.URI()) } -func (s *s3Suite) TestS3Range(c *C) { +func TestS3Range(t *testing.T) { contentRange := "bytes 0-9/443" ri, err := ParseRangeInfo(&contentRange) - c.Assert(err, IsNil) - c.Assert(ri, Equals, RangeInfo{Start: 0, End: 9, Size: 443}) + require.NoError(t, err) + require.Equal(t, RangeInfo{Start: 0, End: 9, Size: 443}, ri) _, err = ParseRangeInfo(nil) - c.Assert(err, ErrorMatches, "ContentRange is empty.*") + require.Error(t, err) + require.Regexp(t, "ContentRange is empty.*", err.Error()) badRange := "bytes " _, err = ParseRangeInfo(&badRange) - c.Assert(err, ErrorMatches, "invalid content range: 'bytes '.*") + require.Error(t, err) + require.Regexp(t, "invalid content range: 'bytes '.*", err.Error()) } // TestWriteNoError ensures the WriteFile API issues a PutObject request and wait // until the object is available in the S3 bucket. -func (s *s3Suite) TestWriteNoError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestWriteNoError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() putCall := s.s3.EXPECT(). PutObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.PutObjectInput, opt ...request.Option) (*s3.PutObjectOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Key), Equals, "prefix/file") - c.Assert(aws.StringValue(input.ACL), Equals, "acl") - c.Assert(aws.StringValue(input.ServerSideEncryption), Equals, "sse") - c.Assert(aws.StringValue(input.StorageClass), Equals, "sc") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/file", aws.StringValue(input.Key)) + require.Equal(t, "acl", aws.StringValue(input.ACL)) + require.Equal(t, "sse", aws.StringValue(input.ServerSideEncryption)) + require.Equal(t, "sc", aws.StringValue(input.StorageClass)) body, err := io.ReadAll(input.Body) - c.Assert(err, IsNil) - c.Assert(body, DeepEquals, []byte("test")) + require.NoError(t, err) + require.Equal(t, []byte("test"), body) return &s3.PutObjectOutput{}, nil }) s.s3.EXPECT(). WaitUntilObjectExistsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.HeadObjectInput, opt ...request.Option) error { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Key), Equals, "prefix/file") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/file", aws.StringValue(input.Key)) return nil }). After(putCall) err := s.storage.WriteFile(ctx, "file", []byte("test")) - c.Assert(err, IsNil) + require.NoError(t, err) } // TestReadNoError ensures the ReadFile API issues a GetObject request and correctly // read the entire body. -func (s *s3Suite) TestReadNoError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestReadNoError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). GetObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.GetObjectInput, opt ...request.Option) (*s3.GetObjectOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Key), Equals, "prefix/file") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/file", aws.StringValue(input.Key)) return &s3.GetObjectOutput{ Body: io.NopCloser(bytes.NewReader([]byte("test"))), }, nil }) content, err := s.storage.ReadFile(ctx, "file") - c.Assert(err, IsNil) - c.Assert(content, DeepEquals, []byte("test")) + require.NoError(t, err) + require.Equal(t, []byte("test"), content) } // TestFileExistsNoError ensures the FileExists API issues a HeadObject request // and reports a file exists. -func (s *s3Suite) TestFileExistsNoError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestFileExistsNoError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). HeadObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.HeadObjectInput, opt ...request.Option) (*s3.HeadObjectOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Key), Equals, "prefix/file") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/file", aws.StringValue(input.Key)) return &s3.HeadObjectOutput{}, nil }) exists, err := s.storage.FileExists(ctx, "file") - c.Assert(err, IsNil) - c.Assert(exists, IsTrue) + require.NoError(t, err) + require.True(t, exists) } -func (s *s3Suite) TestDeleteFileNoError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestDeleteFileNoError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). DeleteObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.DeleteObjectInput, opt ...request.Option) (*s3.DeleteObjectInput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Key), Equals, "prefix/file") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/file", aws.StringValue(input.Key)) return &s3.DeleteObjectInput{}, nil }) err := s.storage.DeleteFile(ctx, "file") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *s3Suite) TestDeleteFileMissing(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestDeleteFileMissing(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() - awserr := awserr.New(s3.ErrCodeNoSuchKey, "no such key", nil) - s.s3.EXPECT(). - DeleteObjectWithContext(ctx, gomock.Any()). - Return(nil, awserr) - - err := s.storage.DeleteFile(ctx, "file-missing") - c.Assert(err, ErrorMatches, awserr.Error()) + err := awserr.New(s3.ErrCodeNoSuchKey, "no such key", nil) + s.s3.EXPECT().DeleteObjectWithContext(ctx, gomock.Any()).Return(nil, err) + require.EqualError(t, s.storage.DeleteFile(ctx, "file-missing"), err.Error()) } -func (s *s3Suite) TestDeleteFileError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestDeleteFileError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() expectedErr := errors.New("just some unrelated error") @@ -550,14 +541,15 @@ func (s *s3Suite) TestDeleteFileError(c *C) { Return(nil, expectedErr) err := s.storage.DeleteFile(ctx, "file3") - c.Assert(err, ErrorMatches, `\Q`+expectedErr.Error()+`\E`) + require.Error(t, err) + require.Regexp(t, `\Q`+expectedErr.Error()+`\E`, err.Error()) } // TestFileExistsNoSuckKey ensures FileExists API reports file missing if S3's // HeadObject request replied NoSuchKey. -func (s *s3Suite) TestFileExistsMissing(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestFileExistsMissing(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). @@ -565,14 +557,14 @@ func (s *s3Suite) TestFileExistsMissing(c *C) { Return(nil, awserr.New(s3.ErrCodeNoSuchKey, "no such key", nil)) exists, err := s.storage.FileExists(ctx, "file-missing") - c.Assert(err, IsNil) - c.Assert(exists, IsFalse) + require.NoError(t, err) + require.False(t, exists) } // TestWriteError checks that a PutObject error is propagated. -func (s *s3Suite) TestWriteError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestWriteError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() expectedErr := awserr.New(s3.ErrCodeNoSuchBucket, "no such bucket", nil) @@ -582,13 +574,13 @@ func (s *s3Suite) TestWriteError(c *C) { Return(nil, expectedErr) err := s.storage.WriteFile(ctx, "file2", []byte("test")) - c.Assert(err, ErrorMatches, `\Q`+expectedErr.Error()+`\E`) + require.Regexp(t, `\Q`+expectedErr.Error()+`\E`, err.Error()) } // TestWriteError checks that a GetObject error is propagated. -func (s *s3Suite) TestReadError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestReadError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() expectedErr := awserr.New(s3.ErrCodeNoSuchKey, "no such key", nil) @@ -598,15 +590,14 @@ func (s *s3Suite) TestReadError(c *C) { Return(nil, expectedErr) _, err := s.storage.ReadFile(ctx, "file-missing") - - c.Assert(err, ErrorMatches, "failed to read s3 file, file info: "+ - "input.bucket='bucket', input.key='prefix/file-missing': "+expectedErr.Error()) + require.Error(t, err) + require.Regexp(t, "failed to read s3 file, file info: input.bucket='bucket', input.key='prefix/file-missing': ", err.Error()) } // TestFileExistsError checks that a HeadObject error is propagated. -func (s *s3Suite) TestFileExistsError(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestFileExistsError(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() expectedErr := errors.New("just some unrelated error") @@ -616,35 +607,36 @@ func (s *s3Suite) TestFileExistsError(c *C) { Return(nil, expectedErr) _, err := s.storage.FileExists(ctx, "file3") - c.Assert(err, ErrorMatches, `\Q`+expectedErr.Error()+`\E`) + require.Error(t, err) + require.Regexp(t, `\Q`+expectedErr.Error()+`\E`, err.Error()) } // TestOpenAsBufio checks that we can open a file for reading via bufio. -func (s *s3Suite) TestOpenAsBufio(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestOpenAsBufio(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). GetObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.GetObjectInput, opt ...request.Option) (*s3.GetObjectOutput, error) { - c.Assert(aws.StringValue(input.Range), Equals, "bytes=0-") + require.Equal(t, (*string)(nil), input.Range) return &s3.GetObjectOutput{ - Body: io.NopCloser(bytes.NewReader([]byte("plain text\ncontent"))), - ContentRange: aws.String("bytes 0-17/18"), + Body: io.NopCloser(bytes.NewReader([]byte("plain text\ncontent"))), + ContentLength: aws.Int64(18), }, nil }) reader, err := s.storage.Open(ctx, "plain-text-file") - c.Assert(err, IsNil) - defer c.Assert(reader.Close(), IsNil) + require.NoError(t, err) + require.Nil(t, reader.Close()) bufReader := bufio.NewReaderSize(reader, 5) content, err := bufReader.ReadString('\n') - c.Assert(err, IsNil) - c.Assert(content, Equals, "plain text\n") + require.NoError(t, err) + require.Equal(t, "plain text\n", content) content, err = bufReader.ReadString('\n') - c.Assert(err, ErrorMatches, "EOF") - c.Assert(content, Equals, "content") + require.EqualError(t, err, "EOF") + require.Equal(t, "content", content) } // alphabetReader is used in TestOpenReadSlowly. This Reader produces a single @@ -669,84 +661,90 @@ func (r *alphabetReader) Close() error { // TestOpenReadSlowly checks that we can open a file for reading, even if the // reader emits content one byte at a time. -func (s *s3Suite) TestOpenReadSlowly(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestOpenReadSlowly(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() s.s3.EXPECT(). GetObjectWithContext(ctx, gomock.Any()). Return(&s3.GetObjectOutput{ - Body: &alphabetReader{character: 'A'}, - ContentRange: aws.String("bytes 0-25/26"), + Body: &alphabetReader{character: 'A'}, + ContentLength: aws.Int64(26), }, nil) reader, err := s.storage.Open(ctx, "alphabets") - c.Assert(err, IsNil) + require.NoError(t, err) res, err := io.ReadAll(reader) - c.Assert(err, IsNil) - c.Assert(res, DeepEquals, []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + require.NoError(t, err) + require.Equal(t, []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), res) } // TestOpenSeek checks that Seek is implemented correctly. -func (s *s3Suite) TestOpenSeek(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestOpenSeek(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() someRandomBytes := make([]byte, 1000000) rand.Read(someRandomBytes) // ^ we just want some random bytes for testing, we don't care about its security. - s.expectedCalls(ctx, c, someRandomBytes, []int{0, 998000, 990100}, func(data []byte, offset int) io.ReadCloser { + s.expectedCalls(ctx, t, someRandomBytes, []int{0, 998000, 990100}, func(data []byte, offset int) io.ReadCloser { return io.NopCloser(bytes.NewReader(data[offset:])) }) reader, err := s.storage.Open(ctx, "random") - c.Assert(err, IsNil) - defer reader.Close() + require.NoError(t, err) + defer func() { + require.NoError(t, reader.Close()) + }() // first do some simple read... slice := make([]byte, 100) n, err := io.ReadFull(reader, slice) - c.Assert(err, IsNil) - c.Assert(n, Equals, 100) - c.Assert(slice, DeepEquals, someRandomBytes[:100]) + require.NoError(t, err) + require.Equal(t, 100, n) + require.Equal(t, someRandomBytes[:100], slice) // a short seek will not result in a different GetObject request. offset, err := reader.Seek(2000, io.SeekStart) - c.Assert(err, IsNil) - c.Assert(offset, Equals, int64(2000)) + require.NoError(t, err) + require.Equal(t, int64(2000), offset) n, err = io.ReadFull(reader, slice) - c.Assert(err, IsNil) - c.Assert(n, Equals, 100) - c.Assert(slice, DeepEquals, someRandomBytes[2000:2100]) + require.NoError(t, err) + require.Equal(t, 100, n) + require.Equal(t, someRandomBytes[2000:2100], slice) // a long seek will perform a new GetObject request offset, err = reader.Seek(-2000, io.SeekEnd) - c.Assert(err, IsNil) - c.Assert(offset, Equals, int64(998000)) + require.NoError(t, err) + require.Equal(t, int64(998000), offset) n, err = io.ReadFull(reader, slice) - c.Assert(err, IsNil) - c.Assert(n, Equals, 100) - c.Assert(slice, DeepEquals, someRandomBytes[998000:998100]) + require.NoError(t, err) + require.Equal(t, 100, n) + require.Equal(t, someRandomBytes[998000:998100], slice) + + // jumping to a negative position would cause error. + _, err = reader.Seek(-8000, io.SeekStart) + require.Error(t, err) // jumping backward should be fine, but would perform a new GetObject request. offset, err = reader.Seek(-8000, io.SeekCurrent) - c.Assert(err, IsNil) - c.Assert(offset, Equals, int64(990100)) + require.NoError(t, err) + require.Equal(t, int64(990100), offset) n, err = io.ReadFull(reader, slice) - c.Assert(err, IsNil) - c.Assert(n, Equals, 100) - c.Assert(slice, DeepEquals, someRandomBytes[990100:990200]) + require.NoError(t, err) + require.Equal(t, 100, n) + require.Equal(t, someRandomBytes[990100:990200], slice) // test seek to the file end or bigger positions for _, p := range []int64{1000000, 1000001, 2000000} { offset, err = reader.Seek(p, io.SeekStart) - c.Assert(offset, Equals, int64(1000000)) - c.Assert(err, IsNil) + require.Equal(t, int64(1000000), offset) + require.NoError(t, err) _, err := reader.Read(slice) - c.Assert(err, Equals, io.EOF) + require.Equal(t, io.EOF, err) } } @@ -768,18 +766,31 @@ func (r *limitedBytesReader) Read(p []byte) (n int, err error) { return } -func (s *s3Suite) expectedCalls(ctx context.Context, c *C, data []byte, startOffsets []int, newReader func(data []byte, offset int) io.ReadCloser) { +func (s *s3Suite) expectedCalls(ctx context.Context, t *testing.T, data []byte, startOffsets []int, newReader func(data []byte, offset int) io.ReadCloser) { var lastCall *gomock.Call for _, offset := range startOffsets { thisOffset := offset thisCall := s.s3.EXPECT(). GetObjectWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.GetObjectInput, opt ...request.Option) (*s3.GetObjectOutput, error) { - c.Assert(aws.StringValue(input.Range), Equals, fmt.Sprintf("bytes=%d-", thisOffset)) - return &s3.GetObjectOutput{ - Body: newReader(data, thisOffset), - ContentRange: aws.String(fmt.Sprintf("bytes %d-%d/%d", thisOffset, len(data)-1, len(data))), - }, nil + if thisOffset > 0 { + require.Equal(t, fmt.Sprintf("bytes=%d-", thisOffset), aws.StringValue(input.Range)) + } else { + require.Equal(t, (*string)(nil), input.Range) + } + var response *s3.GetObjectOutput + if thisOffset > 0 { + response = &s3.GetObjectOutput{ + Body: newReader(data, thisOffset), + ContentRange: aws.String(fmt.Sprintf("bytes %d-%d/%d", thisOffset, len(data)-1, len(data))), + } + } else { + response = &s3.GetObjectOutput{ + Body: newReader(data, thisOffset), + ContentLength: aws.Int64(int64(len(data))), + } + } + return response, nil }) if lastCall != nil { thisCall = thisCall.After(lastCall) @@ -789,30 +800,32 @@ func (s *s3Suite) expectedCalls(ctx context.Context, c *C, data []byte, startOff } // TestS3ReaderWithRetryEOF check the Read with retry and end with io.EOF. -func (s *s3Suite) TestS3ReaderWithRetryEOF(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestS3ReaderWithRetryEOF(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() someRandomBytes := make([]byte, 100) rand.Read(someRandomBytes) //nolint:gosec // ^ we just want some random bytes for testing, we don't care about its security. - s.expectedCalls(ctx, c, someRandomBytes, []int{0, 20, 50, 75}, func(data []byte, offset int) io.ReadCloser { + s.expectedCalls(ctx, t, someRandomBytes, []int{0, 20, 50, 75}, func(data []byte, offset int) io.ReadCloser { return io.NopCloser(&limitedBytesReader{Reader: bytes.NewReader(data[offset:]), limit: 30}) }) reader, err := s.storage.Open(ctx, "random") - c.Assert(err, IsNil) - defer reader.Close() + require.NoError(t, err) + defer func() { + require.NoError(t, reader.Close()) + }() var n int slice := make([]byte, 30) readAndCheck := func(cnt, offset int) { n, err = io.ReadFull(reader, slice[:cnt]) - c.Assert(err, IsNil) - c.Assert(n, Equals, cnt) - c.Assert(slice[:cnt], DeepEquals, someRandomBytes[offset:offset+cnt]) + require.NoError(t, err) + require.Equal(t, cnt, n) + require.Equal(t, someRandomBytes[offset:offset+cnt], slice[:cnt]) } // first do some simple read... @@ -826,38 +839,40 @@ func (s *s3Suite) TestS3ReaderWithRetryEOF(c *C) { // there only remains 10 bytes n, err = reader.Read(slice) - c.Assert(err, IsNil) - c.Assert(n, Equals, 5) + require.NoError(t, err) + require.Equal(t, 5, n) _, err = reader.Read(slice) - c.Assert(err, Equals, io.EOF) + require.Equal(t, io.EOF, err) } // TestS3ReaderWithRetryFailed check the Read with retry failed after maxRetryTimes. -func (s *s3Suite) TestS3ReaderWithRetryFailed(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestS3ReaderWithRetryFailed(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() someRandomBytes := make([]byte, 100) rand.Read(someRandomBytes) //nolint:gosec // ^ we just want some random bytes for testing, we don't care about its security. - s.expectedCalls(ctx, c, someRandomBytes, []int{0, 20, 40, 60}, func(data []byte, offset int) io.ReadCloser { + s.expectedCalls(ctx, t, someRandomBytes, []int{0, 20, 40, 60}, func(data []byte, offset int) io.ReadCloser { return io.NopCloser(&limitedBytesReader{Reader: bytes.NewReader(data[offset:]), limit: 30}) }) reader, err := s.storage.Open(ctx, "random") - c.Assert(err, IsNil) - defer reader.Close() + require.NoError(t, err) + defer func() { + require.NoError(t, reader.Close()) + }() var n int slice := make([]byte, 20) readAndCheck := func(cnt, offset int) { n, err = io.ReadFull(reader, slice[:cnt]) - c.Assert(err, IsNil) - c.Assert(n, Equals, cnt) - c.Assert(slice[:cnt], DeepEquals, someRandomBytes[offset:offset+cnt]) + require.NoError(t, err) + require.Equal(t, cnt, n) + require.Equal(t, someRandomBytes[offset:offset+cnt], slice[:cnt]) } // we can retry 3 times, so read will succeed for 4 times @@ -866,13 +881,13 @@ func (s *s3Suite) TestS3ReaderWithRetryFailed(c *C) { } _, err = reader.Read(slice) - c.Assert(err, ErrorMatches, "read exceeded limit") + require.EqualError(t, err, "read exceeded limit") } // TestWalkDir checks WalkDir retrieves all directory content under a prefix. -func (s *s3Suite) TestWalkDir(c *C) { - s.setUpTest(c) - defer s.tearDownTest() +func TestWalkDir(t *testing.T) { + s, clean := createS3Suite(t) + defer clean() ctx := aws.BackgroundContext() contents := []*s3.Object{ @@ -902,11 +917,11 @@ func (s *s3Suite) TestWalkDir(c *C) { firstCall := s.s3.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Prefix), Equals, "prefix/sp/") - c.Assert(aws.StringValue(input.Marker), Equals, "") - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(2)) - c.Assert(aws.StringValue(input.Delimiter), Equals, "") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/sp/", aws.StringValue(input.Prefix)) + require.Equal(t, "", aws.StringValue(input.Marker)) + require.Equal(t, int64(2), aws.Int64Value(input.MaxKeys)) + require.Equal(t, "", aws.StringValue(input.Delimiter)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(true), Contents: contents[:2], @@ -915,8 +930,8 @@ func (s *s3Suite) TestWalkDir(c *C) { secondCall := s.s3.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Marker), Equals, aws.StringValue(contents[1].Key)) - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(2)) + require.Equal(t, aws.StringValue(contents[1].Key), aws.StringValue(input.Marker)) + require.Equal(t, int64(2), aws.Int64Value(input.MaxKeys)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(true), Contents: contents[2:4], @@ -926,8 +941,8 @@ func (s *s3Suite) TestWalkDir(c *C) { thirdCall := s.s3.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Marker), Equals, aws.StringValue(contents[3].Key)) - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(2)) + require.Equal(t, aws.StringValue(contents[3].Key), aws.StringValue(input.Marker)) + require.Equal(t, int64(2), aws.Int64Value(input.MaxKeys)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(false), Contents: contents[4:], @@ -937,11 +952,11 @@ func (s *s3Suite) TestWalkDir(c *C) { fourthCall := s.s3.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Prefix), Equals, "prefix/") - c.Assert(aws.StringValue(input.Marker), Equals, "") - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(4)) - c.Assert(aws.StringValue(input.Delimiter), Equals, "") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "prefix/", aws.StringValue(input.Prefix)) + require.Equal(t, "", aws.StringValue(input.Marker)) + require.Equal(t, int64(4), aws.Int64Value(input.MaxKeys)) + require.Equal(t, "", aws.StringValue(input.Delimiter)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(true), Contents: contents[:4], @@ -951,8 +966,8 @@ func (s *s3Suite) TestWalkDir(c *C) { s.s3.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Marker), Equals, aws.StringValue(contents[3].Key)) - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(4)) + require.Equal(t, aws.StringValue(contents[3].Key), aws.StringValue(input.Marker)) + require.Equal(t, int64(4), aws.Int64Value(input.MaxKeys)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(false), Contents: contents[4:], @@ -966,15 +981,14 @@ func (s *s3Suite) TestWalkDir(c *C) { ctx, &WalkOption{SubDir: "sp", ListCount: 2}, func(path string, size int64) error { - comment := Commentf("index = %d", i) - c.Assert("prefix/"+path, Equals, *contents[i].Key, comment) - c.Assert(size, Equals, *contents[i].Size, comment) + require.Equal(t, *contents[i].Key, "prefix/"+path, "index = %d", i) + require.Equal(t, *contents[i].Size, size, "index = %d", i) i++ return nil }, ) - c.Assert(err, IsNil) - c.Assert(i, Equals, len(contents)) + require.NoError(t, err) + require.Len(t, contents, i) // test with empty subDir i = 0 @@ -982,20 +996,19 @@ func (s *s3Suite) TestWalkDir(c *C) { ctx, &WalkOption{ListCount: 4}, func(path string, size int64) error { - comment := Commentf("index = %d", i) - c.Assert("prefix/"+path, Equals, *contents[i].Key, comment) - c.Assert(size, Equals, *contents[i].Size, comment) + require.Equal(t, *contents[i].Key, "prefix/"+path, "index = %d", i) + require.Equal(t, *contents[i].Size, size, "index = %d", i) i++ return nil }, ) - c.Assert(err, IsNil) - c.Assert(i, Equals, len(contents)) + require.NoError(t, err) + require.Len(t, contents, i) } // TestWalkDirBucket checks WalkDir retrieves all directory content under a bucket. -func (s *s3SuiteCustom) TestWalkDirWithEmptyPrefix(c *C) { - controller := gomock.NewController(c) +func TestWalkDirWithEmptyPrefix(t *testing.T) { + controller := gomock.NewController(t) s3API := mock.NewMockS3API(controller) storage := NewS3StorageForTest( s3API, @@ -1024,11 +1037,11 @@ func (s *s3SuiteCustom) TestWalkDirWithEmptyPrefix(c *C) { firstCall := s3API.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Prefix), Equals, "") - c.Assert(aws.StringValue(input.Marker), Equals, "") - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(2)) - c.Assert(aws.StringValue(input.Delimiter), Equals, "") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "", aws.StringValue(input.Prefix)) + require.Equal(t, "", aws.StringValue(input.Marker)) + require.Equal(t, int64(2), aws.Int64Value(input.MaxKeys)) + require.Equal(t, "", aws.StringValue(input.Delimiter)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(false), Contents: contents, @@ -1037,11 +1050,11 @@ func (s *s3SuiteCustom) TestWalkDirWithEmptyPrefix(c *C) { s3API.EXPECT(). ListObjectsWithContext(ctx, gomock.Any()). DoAndReturn(func(_ context.Context, input *s3.ListObjectsInput, opt ...request.Option) (*s3.ListObjectsOutput, error) { - c.Assert(aws.StringValue(input.Bucket), Equals, "bucket") - c.Assert(aws.StringValue(input.Prefix), Equals, "sp/") - c.Assert(aws.StringValue(input.Marker), Equals, "") - c.Assert(aws.Int64Value(input.MaxKeys), Equals, int64(2)) - c.Assert(aws.StringValue(input.Delimiter), Equals, "") + require.Equal(t, "bucket", aws.StringValue(input.Bucket)) + require.Equal(t, "sp/", aws.StringValue(input.Prefix)) + require.Equal(t, "", aws.StringValue(input.Marker)) + require.Equal(t, int64(2), aws.Int64Value(input.MaxKeys)) + require.Equal(t, "", aws.StringValue(input.Delimiter)) return &s3.ListObjectsOutput{ IsTruncated: aws.Bool(false), Contents: contents[:1], @@ -1055,15 +1068,14 @@ func (s *s3SuiteCustom) TestWalkDirWithEmptyPrefix(c *C) { ctx, &WalkOption{SubDir: "", ListCount: 2}, func(path string, size int64) error { - comment := Commentf("index = %d", i) - c.Assert(path, Equals, *contents[i].Key, comment) - c.Assert(size, Equals, *contents[i].Size, comment) + require.Equal(t, *contents[i].Key, path, "index = %d", i) + require.Equal(t, *contents[i].Size, size, "index = %d", i) i++ return nil }, ) - c.Assert(err, IsNil) - c.Assert(i, Equals, len(contents)) + require.NoError(t, err) + require.Len(t, contents, i) // test with non-empty sub-dir i = 0 @@ -1071,13 +1083,12 @@ func (s *s3SuiteCustom) TestWalkDirWithEmptyPrefix(c *C) { ctx, &WalkOption{SubDir: "sp", ListCount: 2}, func(path string, size int64) error { - comment := Commentf("index = %d", i) - c.Assert(path, Equals, *contents[i].Key, comment) - c.Assert(size, Equals, *contents[i].Size, comment) + require.Equal(t, *contents[i].Key, path, "index = %d", i) + require.Equal(t, *contents[i].Size, size, "index = %d", i) i++ return nil }, ) - c.Assert(err, IsNil) - c.Assert(i, Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, i) } diff --git a/br/pkg/storage/storage.go b/br/pkg/storage/storage.go index 177656fc378a0..a32d1ed962fde 100644 --- a/br/pkg/storage/storage.go +++ b/br/pkg/storage/storage.go @@ -71,7 +71,7 @@ type Writer interface { // ExternalStorage represents a kind of file system storage. type ExternalStorage interface { - // WriteFile writes a complete file to storage, similar to os.WriteFile + // WriteFile writes a complete file to storage, similar to os.WriteFile, but WriteFile should be atomic WriteFile(ctx context.Context, name string, data []byte) error // ReadFile reads a complete file from storage, similar to os.ReadFile ReadFile(ctx context.Context, name string) ([]byte, error) @@ -94,6 +94,8 @@ type ExternalStorage interface { // Create opens a file writer by path. path is relative path to storage base path Create(ctx context.Context, path string) (ExternalFileWriter, error) + // Rename file name from oldFileName to newFileName + Rename(ctx context.Context, oldFileName, newFileName string) error } // ExternalFileReader represents the streaming external file reader. @@ -165,6 +167,8 @@ func New(ctx context.Context, backend *backuppb.StorageBackend, opts *ExternalSt return nil, errors.Annotate(berrors.ErrStorageInvalidConfig, "GCS config not found") } return newGCSStorage(ctx, backend.Gcs, opts) + case *backuppb.StorageBackend_AzureBlobStorage: + return newAzureBlobStorage(ctx, backend.AzureBlobStorage, opts) default: return nil, errors.Annotatef(berrors.ErrStorageInvalidConfig, "storage %T is not supported yet", backend) } diff --git a/br/pkg/storage/writer.go b/br/pkg/storage/writer.go index df501c76144c3..e029b553952c2 100644 --- a/br/pkg/storage/writer.go +++ b/br/pkg/storage/writer.go @@ -36,6 +36,7 @@ type interceptBuffer interface { Cap() int Bytes() []byte Reset() + Compressed() bool } func newInterceptBuffer(chunkSize int, compressType CompressType) interceptBuffer { @@ -75,6 +76,10 @@ func (b *noCompressionBuffer) Close() error { return nil } +func (b *noCompressionBuffer) Compressed() bool { + return false +} + func newNoCompressionBuffer(chunkSize int) *noCompressionBuffer { return &noCompressionBuffer{bytes.NewBuffer(make([]byte, 0, chunkSize))} } @@ -87,18 +92,16 @@ type simpleCompressWriter interface { type simpleCompressBuffer struct { *bytes.Buffer compressWriter simpleCompressWriter - len int cap int } func (b *simpleCompressBuffer) Write(p []byte) (int, error) { written, err := b.compressWriter.Write(p) - b.len += written return written, errors.Trace(err) } func (b *simpleCompressBuffer) Len() int { - return b.len + return b.Buffer.Len() } func (b *simpleCompressBuffer) Cap() int { @@ -106,7 +109,6 @@ func (b *simpleCompressBuffer) Cap() int { } func (b *simpleCompressBuffer) Reset() { - b.len = 0 b.Buffer.Reset() } @@ -118,11 +120,14 @@ func (b *simpleCompressBuffer) Close() error { return b.compressWriter.Close() } +func (b *simpleCompressBuffer) Compressed() bool { + return true +} + func newSimpleCompressBuffer(chunkSize int, compressType CompressType) *simpleCompressBuffer { bf := bytes.NewBuffer(make([]byte, 0, chunkSize)) return &simpleCompressBuffer{ Buffer: bf, - len: 0, cap: chunkSize, compressWriter: newCompressWriter(compressType, bf), } @@ -149,6 +154,10 @@ func (u *bufferedWriter) Write(ctx context.Context, p []byte) (int, error) { return bytesWritten, errors.Trace(err) } p = p[w:] + // continue buf because compressed data size may be less than Cap - Len + if u.buf.Compressed() { + continue + } } u.buf.Flush() err := u.uploadChunk(ctx) diff --git a/br/pkg/storage/writer_test.go b/br/pkg/storage/writer_test.go index 68e8beffe347d..c3d4080123f4f 100644 --- a/br/pkg/storage/writer_test.go +++ b/br/pkg/storage/writer_test.go @@ -9,38 +9,39 @@ import ( "os" "path/filepath" "strings" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -func (r *testStorageSuite) TestExternalFileWriter(c *C) { - dir := c.MkDir() +func TestExternalFileWriter(t *testing.T) { + dir := t.TempDir() type testcase struct { name string content []string } - testFn := func(test *testcase, c *C) { - c.Log(test.name) + testFn := func(test *testcase, t *testing.T) { + t.Log(test.name) backend, err := ParseBackend("local://"+filepath.ToSlash(dir), nil) - c.Assert(err, IsNil) + require.NoError(t, err) ctx := context.Background() storage, err := Create(ctx, backend, true) - c.Assert(err, IsNil) + require.NoError(t, err) fileName := strings.ReplaceAll(test.name, " ", "-") + ".txt" writer, err := storage.Create(ctx, fileName) - c.Assert(err, IsNil) + require.NoError(t, err) for _, str := range test.content { p := []byte(str) written, err2 := writer.Write(ctx, p) - c.Assert(err2, IsNil) - c.Assert(written, Equals, len(p)) + require.Nil(t, err2) + require.Len(t, p, written) } err = writer.Close(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) content, err := os.ReadFile(filepath.Join(dir, fileName)) - c.Assert(err, IsNil) - c.Assert(string(content), Equals, strings.Join(test.content, "")) + require.NoError(t, err) + require.Equal(t, strings.Join(test.content, ""), string(content)) } tests := []testcase{ { @@ -82,57 +83,57 @@ func (r *testStorageSuite) TestExternalFileWriter(c *C) { }, } for i := range tests { - testFn(&tests[i], c) + testFn(&tests[i], t) } } -func (r *testStorageSuite) TestCompressReaderWriter(c *C) { - dir := c.MkDir() +func TestCompressReaderWriter(t *testing.T) { + dir := t.TempDir() type testcase struct { name string content []string compressType CompressType } - testFn := func(test *testcase, c *C) { - c.Log(test.name) + testFn := func(test *testcase, t *testing.T) { + t.Log(test.name) backend, err := ParseBackend("local://"+filepath.ToSlash(dir), nil) - c.Assert(err, IsNil) + require.NoError(t, err) ctx := context.Background() storage, err := Create(ctx, backend, true) - c.Assert(err, IsNil) + require.NoError(t, err) storage = WithCompression(storage, Gzip) fileName := strings.ReplaceAll(test.name, " ", "-") + ".txt.gz" writer, err := storage.Create(ctx, fileName) - c.Assert(err, IsNil) + require.NoError(t, err) for _, str := range test.content { p := []byte(str) written, err2 := writer.Write(ctx, p) - c.Assert(err2, IsNil) - c.Assert(written, Equals, len(p)) + require.Nil(t, err2) + require.Len(t, p, written) } err = writer.Close(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) // make sure compressed file is written correctly file, err := os.Open(filepath.Join(dir, fileName)) - c.Assert(err, IsNil) + require.NoError(t, err) r, err := newCompressReader(test.compressType, file) - c.Assert(err, IsNil) + require.NoError(t, err) var bf bytes.Buffer _, err = bf.ReadFrom(r) - c.Assert(err, IsNil) - c.Assert(bf.String(), Equals, strings.Join(test.content, "")) - c.Assert(r.Close(), IsNil) + require.NoError(t, err) + require.Equal(t, strings.Join(test.content, ""), bf.String()) + require.Nil(t, r.Close()) // test withCompression Open r, err = storage.Open(ctx, fileName) - c.Assert(err, IsNil) + require.NoError(t, err) content, err := io.ReadAll(r) - c.Assert(err, IsNil) - c.Assert(string(content), Equals, strings.Join(test.content, "")) + require.NoError(t, err) + require.Equal(t, strings.Join(test.content, ""), string(content)) - c.Assert(file.Close(), IsNil) + require.Nil(t, file.Close()) } compressTypeArr := []CompressType{Gzip} tests := []testcase{ @@ -162,7 +163,7 @@ func (r *testStorageSuite) TestCompressReaderWriter(c *C) { for i := range tests { for _, compressType := range compressTypeArr { tests[i].compressType = compressType - testFn(&tests[i], c) + testFn(&tests[i], t) } } } diff --git a/br/pkg/summary/collector.go b/br/pkg/summary/collector.go index 5493f82f77967..b0a3735db0c88 100644 --- a/br/pkg/summary/collector.go +++ b/br/pkg/summary/collector.go @@ -3,11 +3,13 @@ package summary import ( + "context" "strings" "sync" "time" "github.com/docker/go-units" + berror "github.com/pingcap/errors" "github.com/pingcap/log" "go.uber.org/zap" ) @@ -49,7 +51,7 @@ type LogCollector interface { type logFunc func(msg string, fields ...zap.Field) -var collector LogCollector = NewLogCollector(log.Info) +var collector = NewLogCollector(log.Info) // InitCollector initilize global collector instance. func InitCollector( // revive:disable-line:flag-parameter @@ -188,9 +190,16 @@ func (tc *logCollector) Summary(name string) { } if len(tc.failureReasons) != 0 || !tc.successStatus { + var canceledUnits int for unitName, reason := range tc.failureReasons { - logFields = append(logFields, zap.String("unit-name", unitName), zap.Error(reason)) + if berror.Cause(reason) != context.Canceled { + logFields = append(logFields, zap.String("unit-name", unitName), zap.Error(reason)) + } else { + canceledUnits++ + } } + // only print total number of cancel unit + log.Info("units canceled", zap.Int("cancel-unit", canceledUnits)) tc.log(name+" failed summary", logFields...) return } diff --git a/br/pkg/summary/main_test.go b/br/pkg/summary/main_test.go index e1b89ff3d0a0f..bcf86e1381363 100644 --- a/br/pkg/summary/main_test.go +++ b/br/pkg/summary/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/task/backup.go b/br/pkg/task/backup.go index 87461f53bab74..a94d943577c44 100644 --- a/br/pkg/task/backup.go +++ b/br/pkg/task/backup.go @@ -50,6 +50,13 @@ const ( maxBackupConcurrency = 256 ) +const ( + FullBackupCmd = "Full Backup" + DBBackupCmd = "Database Backup" + TableBackupCmd = "Table Backup" + RawBackupCmd = "Raw Backup" +) + // CompressionConfig is the configuration for sst file compression. type CompressionConfig struct { CompressionType backuppb.CompressionType `json:"compression-type" toml:"compression-type"` @@ -217,6 +224,10 @@ func (cfg *BackupConfig) adjustBackupConfig() { } } +func isFullBackup(cmdName string) bool { + return cmdName == FullBackupCmd +} + // RunBackup starts a backup task inside the current goroutine. func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig) error { cfg.adjustBackupConfig() @@ -250,6 +261,16 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig statsHandle = mgr.GetDomain().StatsHandle() } + se, err := g.CreateSession(mgr.GetStorage()) + if err != nil { + return errors.Trace(err) + } + newCollationEnable, err := se.GetGlobalVariable(tidbNewCollationEnabled) + if err != nil { + return errors.Trace(err) + } + log.Info("get newCollationEnable for check during restore", zap.String("newCollationEnable", newCollationEnable)) + client, err := backup.NewBackupClient(ctx, mgr) if err != nil { return errors.Trace(err) @@ -312,6 +333,7 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig StartVersion: cfg.LastBackupTS, EndVersion: backupTS, RateLimit: cfg.RateLimit, + StorageBackend: client.GetStorageBackend(), Concurrency: defaultBackupConcurrency, CompressionType: cfg.CompressionType, CompressionLevel: cfg.CompressionLevel, @@ -323,7 +345,7 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig return errors.Trace(err) } - ranges, schemas, err := backup.BuildBackupRangeAndSchema(mgr.GetStorage(), cfg.TableFilter, backupTS) + ranges, schemas, policies, err := backup.BuildBackupRangeAndSchema(mgr.GetStorage(), cfg.TableFilter, backupTS, isFullBackup(cmdName)) if err != nil { return errors.Trace(err) } @@ -339,8 +361,16 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig m.ClusterId = req.ClusterId m.ClusterVersion = clusterVersion m.BrVersion = brVersion + m.NewCollationsEnabled = newCollationEnable }) + log.Info("get placement policies", zap.Int("count", len(policies))) + if len(policies) != 0 { + metawriter.Update(func(m *backuppb.BackupMeta) { + m.Policies = policies + }) + } + // nothing to backup if ranges == nil { pdAddress := strings.Join(cfg.PD, ",") diff --git a/br/pkg/task/backup_raw.go b/br/pkg/task/backup_raw.go index febe151218706..3f352b7e6320c 100644 --- a/br/pkg/task/backup_raw.go +++ b/br/pkg/task/backup_raw.go @@ -201,10 +201,13 @@ func RunBackupRaw(c context.Context, g glue.Glue, cmdName string, cfg *RawKvConf req := backuppb.BackupRequest{ ClusterId: client.GetClusterID(), + StartKey: backupRange.StartKey, + EndKey: backupRange.EndKey, StartVersion: 0, EndVersion: 0, RateLimit: cfg.RateLimit, Concurrency: cfg.Concurrency, + StorageBackend: client.GetStorageBackend(), IsRawKv: true, Cf: cfg.CF, CompressionType: cfg.CompressionType, @@ -213,7 +216,7 @@ func RunBackupRaw(c context.Context, g glue.Glue, cmdName string, cfg *RawKvConf } metaWriter := metautil.NewMetaWriter(client.GetStorage(), metautil.MetaFileSize, false, &cfg.CipherInfo) metaWriter.StartWriteMetasAsync(ctx, metautil.AppendDataFile) - err = client.BackupRange(ctx, backupRange.StartKey, backupRange.EndKey, req, metaWriter, progressCallBack) + err = client.BackupRange(ctx, req, metaWriter, progressCallBack) if err != nil { return errors.Trace(err) } @@ -228,6 +231,7 @@ func RunBackupRaw(c context.Context, g glue.Glue, cmdName string, cfg *RawKvConf m.ClusterId = req.ClusterId m.ClusterVersion = clusterVersion m.BrVersion = brVersion + m.ApiVersion = client.GetApiVersion() }) err = metaWriter.FinishWriteMetas(ctx, metautil.AppendDataFile) if err != nil { diff --git a/br/pkg/task/backup_test.go b/br/pkg/task/backup_test.go index 6db001d609ef9..0800b95dbed2c 100644 --- a/br/pkg/task/backup_test.go +++ b/br/pkg/task/backup_test.go @@ -11,8 +11,6 @@ import ( ) func TestParseTSString(t *testing.T) { - t.Parallel() - var ( ts uint64 err error @@ -26,15 +24,16 @@ func TestParseTSString(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(400036290571534337), ts) - _, offset := time.Now().Local().Zone() - ts, err = parseTSString("2018-05-11 01:42:23") + ts, err = parseTSString("2021-01-01 01:42:23") require.NoError(t, err) - require.Equal(t, uint64(400032515489792000-(offset*1000)<<18), ts) + localTime := time.Date(2021, time.Month(1), 1, 1, 42, 23, 0, time.Local) + + localTimestamp := localTime.Unix() + localTSO := uint64((localTimestamp << 18) * 1000) + require.Equal(t, localTSO, ts) } func TestParseCompressionType(t *testing.T) { - t.Parallel() - var ( ct backup.CompressionType err error diff --git a/br/pkg/task/common.go b/br/pkg/task/common.go index 357c7d267e449..969c4fbf00dce 100644 --- a/br/pkg/task/common.go +++ b/br/pkg/task/common.go @@ -20,7 +20,6 @@ import ( backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/encryptionpb" "github.com/pingcap/log" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" "github.com/pingcap/tidb/br/pkg/conn" berrors "github.com/pingcap/tidb/br/pkg/errors" "github.com/pingcap/tidb/br/pkg/glue" @@ -28,10 +27,11 @@ import ( "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/sessionctx/variable" + filter "github.com/pingcap/tidb/util/table-filter" "github.com/spf13/cobra" "github.com/spf13/pflag" pd "github.com/tikv/pd/client" - "go.etcd.io/etcd/pkg/transport" + "go.etcd.io/etcd/client/pkg/v3/transport" "go.uber.org/zap" "google.golang.org/grpc/keepalive" ) @@ -85,6 +85,8 @@ const ( crypterAES128KeyLen = 16 crypterAES192KeyLen = 24 crypterAES256KeyLen = 32 + + tidbNewCollationEnabled = "new_collation_enabled" ) // TLSConfig is the common configuration for TLS connection. diff --git a/br/pkg/task/common_test.go b/br/pkg/task/common_test.go index b85d973dea065..b124f6977b9fa 100644 --- a/br/pkg/task/common_test.go +++ b/br/pkg/task/common_test.go @@ -29,7 +29,6 @@ func (f fakeValue) Type() string { } func TestUrlNoQuery(t *testing.T) { - t.Parallel() flag := &pflag.Flag{ Name: flagStorage, Value: fakeValue("s3://some/what?secret=a123456789&key=987654321"), @@ -40,7 +39,6 @@ func TestUrlNoQuery(t *testing.T) { } func TestTiDBConfigUnchanged(t *testing.T) { - t.Parallel() cfg := config.GetGlobalConfig() restoreConfig := enableTiDBConfig() require.NotEqual(t, config.GetGlobalConfig(), cfg) @@ -49,7 +47,6 @@ func TestTiDBConfigUnchanged(t *testing.T) { } func TestStripingPDURL(t *testing.T) { - t.Parallel() nor1, err := normalizePDURL("https://pd:5432", true) require.NoError(t, err) require.Equal(t, "pd:5432", nor1) @@ -68,7 +65,6 @@ func TestStripingPDURL(t *testing.T) { } func TestCheckCipherKeyMatch(t *testing.T) { - t.Parallel() cases := []struct { CipherType encryptionpb.EncryptionMethod CipherKey string @@ -125,7 +121,6 @@ func TestCheckCipherKeyMatch(t *testing.T) { } func TestCheckCipherKey(t *testing.T) { - t.Parallel() cases := []struct { cipherKey string keyFile string diff --git a/br/pkg/task/restore.go b/br/pkg/task/restore.go index ae46f15b1f6ce..f88440dca6447 100644 --- a/br/pkg/task/restore.go +++ b/br/pkg/task/restore.go @@ -4,6 +4,7 @@ package task import ( "context" + "strings" "time" "github.com/opentracing/opentracing-go" @@ -17,11 +18,11 @@ import ( "github.com/pingcap/tidb/br/pkg/metautil" "github.com/pingcap/tidb/br/pkg/pdutil" "github.com/pingcap/tidb/br/pkg/restore" - "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/summary" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/br/pkg/version" "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/kv" "github.com/spf13/pflag" "go.uber.org/multierr" "go.uber.org/zap" @@ -39,12 +40,24 @@ const ( FlagPDConcurrency = "pd-concurrency" // FlagBatchFlushInterval controls after how long the restore batch would be auto sended. FlagBatchFlushInterval = "batch-flush-interval" + // FlagDdlBatchSize controls batch ddl size to create a batch of tables + FlagDdlBatchSize = "ddl-batch-size" + // FlagWithPlacementPolicy corresponds to tidb config with-tidb-placement-mode + // current only support STRICT or IGNORE, the default is STRICT according to tidb. + FlagWithPlacementPolicy = "with-tidb-placement-mode" defaultRestoreConcurrency = 128 maxRestoreBatchSizeLimit = 10240 defaultPDConcurrency = 1 defaultBatchFlushInterval = 16 * time.Second - defaultDDLConcurrency = 16 + defaultFlagDdlBatchSize = 128 +) + +const ( + FullRestoreCmd = "Full Restore" + DBRestoreCmd = "DataBase Restore" + TableRestoreCmd = "Table Restore" + RawRestoreCmd = "Raw Restore" ) // RestoreCommonConfig is the common configuration for all BR restore tasks. @@ -82,10 +95,13 @@ func DefineRestoreCommonFlags(flags *pflag.FlagSet) { "concurrency pd-relative operations like split & scatter.") flags.Duration(FlagBatchFlushInterval, defaultBatchFlushInterval, "after how long a restore batch would be auto sended.") + flags.Uint(FlagDdlBatchSize, defaultFlagDdlBatchSize, + "batch size for ddl to create a batch of tabes once.") _ = flags.MarkHidden(FlagMergeRegionSizeBytes) _ = flags.MarkHidden(FlagMergeRegionKeyCount) _ = flags.MarkHidden(FlagPDConcurrency) _ = flags.MarkHidden(FlagBatchFlushInterval) + _ = flags.MarkHidden(FlagDdlBatchSize) } // ParseFromFlags parses the config from the flag set. @@ -114,6 +130,10 @@ type RestoreConfig struct { NoSchema bool `json:"no-schema" toml:"no-schema"` PDConcurrency uint `json:"pd-concurrency" toml:"pd-concurrency"` BatchFlushInterval time.Duration `json:"batch-flush-interval" toml:"batch-flush-interval"` + // DdlBatchSize use to define the size of batch ddl to create tables + DdlBatchSize uint `json:"ddl-batch-size" toml:"ddl-batch-size"` + + WithPlacementPolicy string `json:"with-tidb-placement-mode" toml:"with-tidb-placement-mode"` } // DefineRestoreFlags defines common flags for the restore tidb command. @@ -121,6 +141,7 @@ func DefineRestoreFlags(flags *pflag.FlagSet) { flags.Bool(flagNoSchema, false, "skip creating schemas and tables, reuse existing empty ones") // Do not expose this flag _ = flags.MarkHidden(flagNoSchema) + flags.String(FlagWithPlacementPolicy, "STRICT", "correspond to tidb global/session variable with-tidb-placement-mode") DefineRestoreCommonFlags(flags) } @@ -152,11 +173,20 @@ func (cfg *RestoreConfig) ParseFromFlags(flags *pflag.FlagSet) error { if err != nil { return errors.Annotatef(err, "failed to get flag %s", FlagBatchFlushInterval) } + + cfg.DdlBatchSize, err = flags.GetUint(FlagDdlBatchSize) + if err != nil { + return errors.Annotatef(err, "failed to get flag %s", FlagDdlBatchSize) + } + cfg.WithPlacementPolicy, err = flags.GetString(FlagWithPlacementPolicy) + if err != nil { + return errors.Annotatef(err, "failed to get flag %s", FlagWithPlacementPolicy) + } return nil } // adjustRestoreConfig is use for BR(binary) and BR in TiDB. -// When new config was add and not included in parser. +// When new config was added and not included in parser. // we should set proper value in this function. // so that both binary and TiDB will use same default value. func (cfg *RestoreConfig) adjustRestoreConfig() { @@ -175,6 +205,31 @@ func (cfg *RestoreConfig) adjustRestoreConfig() { if cfg.BatchFlushInterval == 0 { cfg.BatchFlushInterval = defaultBatchFlushInterval } + if cfg.DdlBatchSize == 0 { + cfg.DdlBatchSize = defaultFlagDdlBatchSize + } +} + +func configureRestoreClient(ctx context.Context, client *restore.Client, cfg *RestoreConfig) error { + client.SetRateLimit(cfg.RateLimit) + client.SetCrypter(&cfg.CipherInfo) + client.SetConcurrency(uint(cfg.Concurrency)) + if cfg.Online { + client.EnableOnline() + } + if cfg.NoSchema { + client.EnableSkipCreateSQL() + } + client.SetSwitchModeInterval(cfg.SwitchModeInterval) + client.SetBatchDdlSize(cfg.DdlBatchSize) + client.SetPlacementPolicyMode(cfg.WithPlacementPolicy) + + err := client.LoadRestoreStores(ctx) + if err != nil { + return errors.Trace(err) + } + + return nil } // CheckRestoreDBAndTable is used to check whether the restore dbs or tables have been backup @@ -212,6 +267,46 @@ func CheckRestoreDBAndTable(client *restore.Client, cfg *RestoreConfig) error { return nil } +func CheckNewCollationEnable( + backupNewCollationEnable string, + g glue.Glue, + storage kv.Storage, + CheckRequirements bool, +) error { + if backupNewCollationEnable == "" { + if CheckRequirements { + return errors.Annotatef(berrors.ErrUnknown, + "NewCollactionEnable not found in backupmeta. "+ + "if you ensure the NewCollactionEnable config of backup cluster is as same as restore cluster, "+ + "use --check-requirements=false to skip") + } else { + log.Warn("no NewCollactionEnable in backup") + return nil + } + } + + se, err := g.CreateSession(storage) + if err != nil { + return errors.Trace(err) + } + + newCollationEnable, err := se.GetGlobalVariable(tidbNewCollationEnabled) + if err != nil { + return errors.Trace(err) + } + + if !strings.EqualFold(backupNewCollationEnable, newCollationEnable) { + return errors.Annotatef(berrors.ErrUnknown, + "newCollationEnable not match, upstream:%v, downstream: %v", + backupNewCollationEnable, newCollationEnable) + } + return nil +} + +func isFullRestore(cmdName string) bool { + return cmdName == FullRestoreCmd +} + // RunRestore starts a restore task inside the current goroutine. func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConfig) error { cfg.adjustRestoreConfig() @@ -228,46 +323,26 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf // Restore needs domain to do DDL. needDomain := true - mgr, err := NewMgr(ctx, g, cfg.PD, cfg.TLS, GetKeepalive(&cfg.Config), cfg.CheckRequirements, needDomain) + keepaliveCfg := GetKeepalive(&cfg.Config) + mgr, err := NewMgr(ctx, g, cfg.PD, cfg.TLS, keepaliveCfg, cfg.CheckRequirements, needDomain) if err != nil { return errors.Trace(err) } defer mgr.Close() - keepaliveCfg := GetKeepalive(&cfg.Config) keepaliveCfg.PermitWithoutStream = true - client, err := restore.NewRestoreClient(g, mgr.GetPDClient(), mgr.GetStorage(), mgr.GetTLSConfig(), keepaliveCfg) + client := restore.NewRestoreClient(mgr.GetPDClient(), mgr.GetTLSConfig(), keepaliveCfg, false) + err = configureRestoreClient(ctx, client, cfg) if err != nil { return errors.Trace(err) } + // Init DB connection sessions + err = client.Init(g, mgr.GetStorage()) defer client.Close() - u, err := storage.ParseBackend(cfg.Storage, &cfg.BackendOptions) if err != nil { return errors.Trace(err) } - opts := storage.ExternalStorageOptions{ - NoCredentials: cfg.NoCreds, - SendCredentials: cfg.SendCreds, - } - if err = client.SetStorage(ctx, u, &opts); err != nil { - return errors.Trace(err) - } - client.SetRateLimit(cfg.RateLimit) - client.SetCrypter(&cfg.CipherInfo) - client.SetConcurrency(uint(cfg.Concurrency)) - if cfg.Online { - client.EnableOnline() - } - if cfg.NoSchema { - client.EnableSkipCreateSQL() - } - client.SetSwitchModeInterval(cfg.SwitchModeInterval) - err = client.LoadRestoreStores(ctx) - if err != nil { - return errors.Trace(err) - } - u, s, backupMeta, err := ReadBackupMeta(ctx, metautil.MetaFile, &cfg.Config) if err != nil { return errors.Trace(err) @@ -278,6 +353,10 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf return errors.Trace(versionErr) } } + if err = CheckNewCollationEnable(backupMeta.GetNewCollationsEnabled(), g, mgr.GetStorage(), cfg.CheckRequirements); err != nil { + return errors.Trace(err) + } + reader := metautil.NewMetaReader(backupMeta, s, &cfg.CipherInfo) if err = client.InitBackupMeta(c, backupMeta, u, s, reader); err != nil { return errors.Trace(err) @@ -322,6 +401,7 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf newTS = restoreTS } ddlJobs := restore.FilterDDLJobs(client.GetDDLJobs(), tables) + ddlJobs = restore.FilterDDLJobByRules(ddlJobs, restore.DDLJobBlockListRule) err = client.PreCheckTableTiFlashReplica(ctx, tables) if err != nil { @@ -337,6 +417,23 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf restoreDBConfig := enableTiDBConfig() defer restoreDBConfig() + if client.GetSupportPolicy() { + // create policy if backupMeta has policies. + policies, err := client.GetPlacementPolicies() + if err != nil { + return errors.Trace(err) + } + if isFullRestore(cmdName) { + // we should restore all policies during full restoration. + err = client.CreatePolicies(ctx, policies) + if err != nil { + return errors.Trace(err) + } + } else { + client.SetPolicyMap(policies) + } + } + // execute DDL first err = client.ExecDDLs(ctx, ddlJobs) if err != nil { @@ -360,26 +457,7 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf // We make bigger errCh so we won't block on multi-part failed. errCh := make(chan error, 32) - // Maybe allow user modify the DDL concurrency isn't necessary, - // because executing DDL is really I/O bound (or, algorithm bound?), - // and we cost most of time at waiting DDL jobs be enqueued. - // So these jobs won't be faster or slower when machine become faster or slower, - // hence make it a fixed value would be fine. - var dbPool []*restore.DB - if g.OwnsStorage() { - // Only in binary we can use multi-thread sessions to create tables. - // so use OwnStorage() to tell whether we are use binary or SQL. - dbPool, err = restore.MakeDBPool(defaultDDLConcurrency, func() (*restore.DB, error) { - return restore.NewDB(g, mgr.GetStorage()) - }) - } - if err != nil { - log.Warn("create session pool failed, we will send DDLs only by created sessions", - zap.Error(err), - zap.Int("sessionCount", len(dbPool)), - ) - } - tableStream := client.GoCreateTables(ctx, mgr.GetDomain(), tables, newTS, dbPool, errCh) + tableStream := client.GoCreateTables(ctx, mgr.GetDomain(), tables, newTS, errCh) if len(files) == 0 { log.Info("no files, empty databases and tables are restored") summary.SetSuccessStatus(true) @@ -497,6 +575,8 @@ func dropToBlackhole( return outCh } +// filterRestoreFiles filters tables that can't be processed after applying cfg.TableFilter.MatchTable. +// if the db has no table that can be processed, the db will be filtered too. func filterRestoreFiles( client *restore.Client, cfg *RestoreConfig, diff --git a/br/pkg/task/restore_raw.go b/br/pkg/task/restore_raw.go index bb1dfddc9ce2d..621b41c4f25a6 100644 --- a/br/pkg/task/restore_raw.go +++ b/br/pkg/task/restore_raw.go @@ -75,11 +75,7 @@ func RunRestoreRaw(c context.Context, g glue.Glue, cmdName string, cfg *RestoreR // sometimes we have pooled the connections. // sending heartbeats in idle times is useful. keepaliveCfg.PermitWithoutStream = true - client, err := restore.NewRestoreClient(g, mgr.GetPDClient(), mgr.GetStorage(), mgr.GetTLSConfig(), keepaliveCfg) - if err != nil { - return errors.Trace(err) - } - defer client.Close() + client := restore.NewRestoreClient(mgr.GetPDClient(), mgr.GetTLSConfig(), keepaliveCfg, true) client.SetRateLimit(cfg.RateLimit) client.SetCrypter(&cfg.CipherInfo) client.SetConcurrency(uint(cfg.Concurrency)) @@ -87,6 +83,11 @@ func RunRestoreRaw(c context.Context, g glue.Glue, cmdName string, cfg *RestoreR client.EnableOnline() } client.SetSwitchModeInterval(cfg.SwitchModeInterval) + err = client.Init(g, mgr.GetStorage()) + defer client.Close() + if err != nil { + return errors.Trace(err) + } u, s, backupMeta, err := ReadBackupMeta(ctx, metautil.MetaFile, &cfg.Config) if err != nil { @@ -131,7 +132,7 @@ func RunRestoreRaw(c context.Context, g glue.Glue, cmdName string, cfg *RestoreR // RawKV restore does not need to rewrite keys. rewrite := &restore.RewriteRules{} - err = restore.SplitRanges(ctx, client, ranges, rewrite, updateCh) + err = restore.SplitRanges(ctx, client, ranges, rewrite, updateCh, true) if err != nil { return errors.Trace(err) } diff --git a/br/pkg/task/restore_test.go b/br/pkg/task/restore_test.go index 1abadc3ae6ec4..218033859f828 100644 --- a/br/pkg/task/restore_test.go +++ b/br/pkg/task/restore_test.go @@ -3,6 +3,7 @@ package task import ( + "context" "testing" "github.com/pingcap/tidb/br/pkg/restore" @@ -10,8 +11,6 @@ import ( ) func TestRestoreConfigAdjust(t *testing.T) { - t.Parallel() - cfg := &RestoreConfig{} cfg.adjustRestoreConfig() @@ -20,3 +19,24 @@ func TestRestoreConfigAdjust(t *testing.T) { require.Equal(t, restore.DefaultMergeRegionKeyCount, cfg.MergeSmallRegionKeyCount) require.Equal(t, restore.DefaultMergeRegionSizeBytes, cfg.MergeSmallRegionSizeBytes) } + +func TestconfigureRestoreClient(t *testing.T) { + cfg := Config{ + Concurrency: 1024, + } + restoreComCfg := RestoreCommonConfig{ + Online: true, + } + restoreCfg := &RestoreConfig{ + Config: cfg, + RestoreCommonConfig: restoreComCfg, + DdlBatchSize: 128, + } + client := &restore.Client{} + + ctx := context.Background() + err := configureRestoreClient(ctx, client, restoreCfg) + require.NoError(t, err) + require.Equal(t, client.GetBatchDdlSize(), 128) + require.True(t, true, client.IsOnline()) +} diff --git a/br/pkg/trace/main_test.go b/br/pkg/trace/main_test.go index f253ad281ecdb..bf7e3161113fb 100644 --- a/br/pkg/trace/main_test.go +++ b/br/pkg/trace/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/trace/tracing_serial_test.go b/br/pkg/trace/tracing_serial_test.go index 540c73eb38d64..65950d025164d 100644 --- a/br/pkg/trace/tracing_serial_test.go +++ b/br/pkg/trace/tracing_serial_test.go @@ -48,5 +48,5 @@ func TestSpan(t *testing.T) { // possible result: // "jobA 22:02:02.545296 200.621764ms\n" // " └─jobB 22:02:02.545297 100.293444ms\n" - require.Regexp(t, `^jobA.*20[0-9]\.[0-9]+ms\n └─jobB.*10[0-9]\.[0-9]+ms\n$`, s) + require.Regexp(t, `^jobA.*2[0-9][0-9]\.[0-9]+ms\n └─jobB.*1[0-9][0-9]\.[0-9]+ms\n$`, s) } diff --git a/br/pkg/utils/backoff.go b/br/pkg/utils/backoff.go index 5a21ad8f26a98..c69f32dc4827c 100644 --- a/br/pkg/utils/backoff.go +++ b/br/pkg/utils/backoff.go @@ -17,9 +17,10 @@ import ( ) const ( + // importSSTRetryTimes specifies the retry time. Its longest time is about 90s-100s. importSSTRetryTimes = 16 - importSSTWaitInterval = 10 * time.Millisecond - importSSTMaxWaitInterval = 1 * time.Second + importSSTWaitInterval = 40 * time.Millisecond + importSSTMaxWaitInterval = 10 * time.Second downloadSSTRetryTimes = 8 downloadSSTWaitInterval = 1 * time.Second diff --git a/br/pkg/utils/backoff_test.go b/br/pkg/utils/backoff_test.go index 9ee312f24feab..78f329708211b 100644 --- a/br/pkg/utils/backoff_test.go +++ b/br/pkg/utils/backoff_test.go @@ -123,3 +123,39 @@ func TestPdBackoffWithRetryableError(t *testing.T) { gRPCError, }, multierr.Errors(err)) } + +func TestNewImportSSTBackofferWithSucess(t *testing.T) { + var counter int + backoffer := utils.NewImportSSTBackoffer() + err := utils.WithRetry(context.Background(), func() error { + defer func() { counter++ }() + if counter == 15 { + return nil + } else { + return berrors.ErrKVDownloadFailed + } + }, backoffer) + require.Equal(t, 16, counter) + require.NoError(t, err) +} + +func TestNewDownloadSSTBackofferWithCancel(t *testing.T) { + var counter int + backoffer := utils.NewDownloadSSTBackoffer() + err := utils.WithRetry(context.Background(), func() error { + defer func() { counter++ }() + if counter == 3 { + return context.Canceled + } else { + return berrors.ErrKVIngestFailed + } + + }, backoffer) + require.Equal(t, 4, counter) + require.Equal(t, []error{ + berrors.ErrKVIngestFailed, + berrors.ErrKVIngestFailed, + berrors.ErrKVIngestFailed, + context.Canceled, + }, multierr.Errors(err)) +} diff --git a/br/pkg/utils/dyn_pprof_other.go b/br/pkg/utils/dyn_pprof_other.go index 292208db47091..ed094f4a7d08b 100644 --- a/br/pkg/utils/dyn_pprof_other.go +++ b/br/pkg/utils/dyn_pprof_other.go @@ -5,7 +5,7 @@ package utils -import tidbutils "github.com/pingcap/tidb-tools/pkg/utils" +import tidbutils "github.com/pingcap/tidb/util" // StartDynamicPProfListener starts the listener that will enable pprof when received `startPProfSignal` func StartDynamicPProfListener(tls *tidbutils.TLS) { diff --git a/br/pkg/utils/dyn_pprof_unix.go b/br/pkg/utils/dyn_pprof_unix.go index 47a14eab1127e..36084c5853f20 100644 --- a/br/pkg/utils/dyn_pprof_unix.go +++ b/br/pkg/utils/dyn_pprof_unix.go @@ -11,7 +11,7 @@ import ( "syscall" "github.com/pingcap/log" - tidbutils "github.com/pingcap/tidb-tools/pkg/utils" + tidbutils "github.com/pingcap/tidb/util" "go.uber.org/zap" ) diff --git a/br/pkg/utils/main_test.go b/br/pkg/utils/main_test.go index 47d7fd9b63b21..990afd5522d4b 100644 --- a/br/pkg/utils/main_test.go +++ b/br/pkg/utils/main_test.go @@ -23,8 +23,9 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() goleak.VerifyTestMain(m, opts...) } diff --git a/br/pkg/utils/pprof.go b/br/pkg/utils/pprof.go index 684d974174d7d..9df50ce74c00c 100644 --- a/br/pkg/utils/pprof.go +++ b/br/pkg/utils/pprof.go @@ -4,20 +4,20 @@ package utils import ( "fmt" - "net" - "os" - "sync" - + "net" //nolint:goimports // #nosec // register HTTP handler for /debug/pprof "net/http" - _ "net/http/pprof" + // For pprof + _ "net/http/pprof" // #nosec G108 + "os" + "sync" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/log" - tidbutils "github.com/pingcap/tidb-tools/pkg/utils" berrors "github.com/pingcap/tidb/br/pkg/errors" + tidbutils "github.com/pingcap/tidb/util" "go.uber.org/zap" ) diff --git a/br/pkg/utils/retry.go b/br/pkg/utils/retry.go index a076190b953d6..2f8af3a42ed99 100644 --- a/br/pkg/utils/retry.go +++ b/br/pkg/utils/retry.go @@ -16,6 +16,7 @@ import ( "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" tmysql "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/parser/terror" "go.uber.org/multierr" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -117,7 +118,9 @@ func isSingleRetryableError(err error) bool { case *mysql.MySQLError: switch nerr.Number { // ErrLockDeadlock can retry to commit while meet deadlock - case tmysql.ErrUnknown, tmysql.ErrLockDeadlock, tmysql.ErrWriteConflictInTiDB, tmysql.ErrPDServerTimeout, tmysql.ErrTiKVServerTimeout, tmysql.ErrTiKVServerBusy, tmysql.ErrResolveLockTimeout, tmysql.ErrRegionUnavailable: + case tmysql.ErrUnknown, tmysql.ErrLockDeadlock, tmysql.ErrWriteConflict, tmysql.ErrWriteConflictInTiDB, + tmysql.ErrPDServerTimeout, tmysql.ErrTiKVServerTimeout, tmysql.ErrTiKVServerBusy, tmysql.ErrResolveLockTimeout, + tmysql.ErrRegionUnavailable, tmysql.ErrInfoSchemaExpired, tmysql.ErrInfoSchemaChanged, tmysql.ErrTxnRetryable: return true default: return false @@ -136,3 +139,11 @@ func isSingleRetryableError(err error) bool { } } } + +func FallBack2CreateTable(err error) bool { + switch nerr := errors.Cause(err).(type) { + case *terror.Error: + return nerr.Code() == tmysql.ErrInvalidDDLJob + } + return false +} diff --git a/br/pkg/utils/retry_test.go b/br/pkg/utils/retry_test.go index f27698dcf5f9a..eafe233b7d49e 100644 --- a/br/pkg/utils/retry_test.go +++ b/br/pkg/utils/retry_test.go @@ -34,6 +34,10 @@ func TestIsRetryableError(t *testing.T) { require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrResolveLockTimeout})) require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrRegionUnavailable})) require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrWriteConflictInTiDB})) + require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrWriteConflict})) + require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrInfoSchemaExpired})) + require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrInfoSchemaChanged})) + require.True(t, IsRetryableError(&mysql.MySQLError{Number: tmysql.ErrTxnRetryable})) // gRPC Errors require.False(t, IsRetryableError(status.Error(codes.Canceled, ""))) diff --git a/br/pkg/utils/safe_point.go b/br/pkg/utils/safe_point.go index 91f0335f8090b..512c489c42f45 100644 --- a/br/pkg/utils/safe_point.go +++ b/br/pkg/utils/safe_point.go @@ -11,8 +11,8 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/log" berrors "github.com/pingcap/tidb/br/pkg/errors" + "github.com/tikv/client-go/v2/oracle" pd "github.com/tikv/pd/client" - "github.com/tikv/pd/pkg/tsoutil" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -37,7 +37,7 @@ func (sp BRServiceSafePoint) MarshalLogObject(encoder zapcore.ObjectEncoder) err encoder.AddString("ID", sp.ID) ttlDuration := time.Duration(sp.TTL) * time.Second encoder.AddString("TTL", ttlDuration.String()) - backupTime, _ := tsoutil.ParseTS(sp.BackupTS) + backupTime := oracle.GetTimeFromTS(sp.BackupTS) encoder.AddString("BackupTime", backupTime.String()) encoder.AddUint64("BackupTS", sp.BackupTS) return nil diff --git a/br/pkg/version/build/info.go b/br/pkg/version/build/info.go index 01957a7297b83..fae69c6d8a6ae 100644 --- a/br/pkg/version/build/info.go +++ b/br/pkg/version/build/info.go @@ -27,7 +27,7 @@ func getReleaseVersion() string { if mysql.TiDBReleaseVersion != "None" { return mysql.TiDBReleaseVersion } - return "v5.0.0-master" + return "v6.0.0-master" } // AppName is a name of a built binary. diff --git a/br/pkg/version/version.go b/br/pkg/version/version.go index 91c1578574837..17d8bc6728296 100644 --- a/br/pkg/version/version.go +++ b/br/pkg/version/version.go @@ -102,6 +102,7 @@ func CheckClusterVersion(ctx context.Context, client pd.Client, checker VerCheck if err := checkTiFlashVersion(s); err != nil { return errors.Trace(err) } + continue } tikvVersionString := removeVAndHash(s.Version) @@ -119,7 +120,7 @@ func CheckClusterVersion(ctx context.Context, client pd.Client, checker VerCheck // CheckVersionForBackup checks the version for backup and func CheckVersionForBackup(backupVersion *semver.Version) VerChecker { return func(store *metapb.Store, ver *semver.Version) error { - if backupVersion.Major > ver.Major { + if backupVersion.Major > ver.Major && backupVersion.Major-ver.Major > 1 { return errors.Annotatef(berrors.ErrVersionMismatch, "backup with cluster version %s cannot be restored at cluster of version %s: major version mismatches", backupVersion, ver) @@ -140,7 +141,8 @@ func CheckVersionForBR(s *metapb.Store, tikvVersion *semver.Version) error { s.Address, tikvVersion, build.ReleaseVersion) } - if tikvVersion.Major != BRVersion.Major { + // BR 6.x works with TiKV 5.x and not guarantee works with 4.x + if BRVersion.Major < tikvVersion.Major || BRVersion.Major-tikvVersion.Major > 1 { return errors.Annotatef(berrors.ErrVersionMismatch, "TiKV node %s version %s and BR %s major version mismatch, please use the same version of BR", s.Address, tikvVersion, build.ReleaseVersion) } diff --git a/br/pkg/version/version_test.go b/br/pkg/version/version_test.go index f2369c964029c..84ffd74849aaa 100644 --- a/br/pkg/version/version_test.go +++ b/br/pkg/version/version_test.go @@ -148,11 +148,20 @@ func TestCheckClusterVersion(t *testing.T) { } { - // Restore across major version isn't allowed. + // Restore across one major version allowed. mock.getAllStores = func() []*metapb.Store { return []*metapb.Store{{Version: "v4.0.0-rc.1"}} } err := CheckClusterVersion(context.Background(), &mock, CheckVersionForBackup(semver.New("5.0.0-rc"))) + require.NoError(t, err) + } + + { + // Restore across two major versions isn't allowed. + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v4.0.0-rc.1"}} + } + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForBackup(semver.New("6.0.0"))) require.Error(t, err) } @@ -165,6 +174,25 @@ func TestCheckClusterVersion(t *testing.T) { err := CheckClusterVersion(context.Background(), &mock, CheckVersionForBR) require.NoError(t, err) } + + { + build.ReleaseVersion = "v6.0.0" + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v5.4.0"}} + } + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForBR) + require.NoError(t, err) + } + + { + build.ReleaseVersion = "v6.0.0" + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v4.4.0"}} + } + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForBR) + require.Error(t, err) + } + } func TestCompareVersion(t *testing.T) { diff --git a/br/tests/README.md b/br/tests/README.md index ce2cfa63ebab5..53685c967ad24 100644 --- a/br/tests/README.md +++ b/br/tests/README.md @@ -67,7 +67,8 @@ If you have docker installed, you can skip step 1 and step 2 by running ## Running -Run `make br_integration_test` to execute the integration tests. This command will +Link `bin` directory by `cd br && ln -s ../bin bin` and run `make br_integration_test` to execute the integration tests. +This command will 1. Build `br` 2. Check that all 9 required executables and `br` executable exist diff --git a/br/tests/br_azblob/_run.sh b/br/tests/br_azblob/_run.sh new file mode 100644 index 0000000000000..5cc12b6a492cf --- /dev/null +++ b/br/tests/br_azblob/_run.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# +# Copyright 2021 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This test can't be triggered until ci support azurite +exit 0 +set -eux +DB="$TEST_NAME" +TABLE="usertable" +DB_COUNT=3 + +AZBLOB_ENDPOINT="http://127.0.0.1:10000/devstoreaccount1" +# azurite default account +ACCOUNT_NAME="devstoreaccount1" +ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" +CONTAINER="test" + +rm -rf "$TEST_DIR/$DB" +mkdir -p "$TEST_DIR/$DB" + +# Fill in the database +for i in $(seq $DB_COUNT); do + run_sql "CREATE DATABASE $DB${i};" + go-ycsb load mysql -P tests/$TEST_NAME/workload -p mysql.host=$TIDB_IP -p mysql.port=$TIDB_PORT -p mysql.user=root -p mysql.db=$DB${i} +done + +for i in $(seq $DB_COUNT); do + row_count_ori[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') +done + +# new version backup full +echo "backup start..." +run_br --pd $PD_ADDR backup full \ + -s "azure://$CONTAINER/$DB?account-name=$ACCOUNT_NAME&account-key=$ACCOUNT_KEY&endpoint=$AZBLOB_ENDPOINT&access-tier=Cool" + +# clean up +for i in $(seq $DB_COUNT); do + run_sql "DROP DATABASE $DB${i};" +done + +# new version restore full +echo "restore start..." +run_br restore full \ + -s "azure://$CONTAINER/$DB?" \ + --pd $PD_ADDR --azblob.endpoint="$AZBLOB_ENDPOINT" \ + --azblob.account-name="$ACCOUNT_NAME" \ + --azblob.account-key="$ACCOUNT_KEY" + +for i in $(seq $DB_COUNT); do + row_count_new[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') +done + +fail=false +for i in $(seq $DB_COUNT); do + if [ "${row_count_ori[i]}" != "${row_count_new[i]}" ];then + fail=true + echo "TEST: [$TEST_NAME] fail on database $DB${i}" + fi + echo "database $DB${i} [original] row count: ${row_count_ori[i]}, [after br] row count: ${row_count_new[i]}" +done + +if $fail; then + echo "TEST: [$TEST_NAME] failed!" + exit 1 +else + echo "TEST: [$TEST_NAME] succeed!" +fi + +# clean up +for i in $(seq $DB_COUNT); do + run_sql "DROP DATABASE $DB${i};" +done \ No newline at end of file diff --git a/br/tests/br_azblob/workload b/br/tests/br_azblob/workload new file mode 100644 index 0000000000000..406b24afeea19 --- /dev/null +++ b/br/tests/br_azblob/workload @@ -0,0 +1,12 @@ +recordcount=5000 +operationcount=0 +workload=core + +readallfields=true + +readproportion=0 +updateproportion=0 +scanproportion=0 +insertproportion=0 + +requestdistribution=uniform \ No newline at end of file diff --git a/br/tests/br_charset_gbk/run.sh b/br/tests/br_charset_gbk/run.sh new file mode 100755 index 0000000000000..5fba35411142c --- /dev/null +++ b/br/tests/br_charset_gbk/run.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +check_cluster_version 5 4 0 'new collation' || { echo 'TiDB does not support new collation! skipping test'; exit 0; } + +set -eu + +cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +. $cur/../_utils/run_services + +# restart cluster with new collation enabled +start_services --tidb-cfg $cur/tidb-new-collation.toml + +DB="$TEST_NAME" + +run_sql "CREATE DATABASE $DB;" + +run_sql "CREATE TABLE $DB.测试 ( \ + a char(20) DEFAULT NULL, \ + b tinyblob, \ + c binary(100) DEFAULT NULL, \ + d json DEFAULT NULL, \ + e timestamp NULL DEFAULT NULL, \ + f set('a一','b二','c三','då››') DEFAULT NULL, \ + g text, \ + h enum('a一','b二','c三','då››') DEFAULT 'c三' \ +) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci;" + +run_sql "INSERT INTO $DB.测试 VALUES ('你好', '你好', '你好', '{\"测试\": \"你好\"}', '2018-10-13', 1, '你好', 'a一');" +run_sql "INSERT INTO $DB.测试 VALUES ('你好123', '你好', '你好', '{\"测试\": \"你好\"}', '2018-10-13', 1, '你好', 'a一');" + +run_sql "CREATE TABLE $DB.t ( \ + YCSB_KEY varchar(64) NOT NULL, \ + FIELD0 varchar(1) DEFAULT NULL, \ + PRIMARY KEY (YCSB_KEY) \ +) ENGINE=InnoDB DEFAULT CHARSET=gbk;" + +run_sql "INSERT INTO $DB.t VALUES (\"测试\", \"ä½ \");" +run_sql "SET NAMES gbk; INSERT INTO $DB.t VALUES (\"测试\", \"a\"); SET NAMES default;" + +# backup db +echo "backup start..." +run_br --pd $PD_ADDR backup db --db "$DB" -s "local://$TEST_DIR/$DB" + +run_sql "DROP DATABASE $DB;" + +# restore db +echo "restore start..." +run_br restore db --db $DB -s "local://$TEST_DIR/$DB" --pd $PD_ADDR + +table_count=$(run_sql "use $DB; show tables;" | grep "Tables_in" | wc -l) +if [ "$table_count" -ne "2" ];then + echo "TEST: [$TEST_NAME] failed!" + exit 1 +fi + +run_sql "SELECT * from $DB.测试;" +check_contains "{\"测试\": \"你好\"}" +check_contains "你好123" +run_sql "SELECT hex(a) from $DB.测试;" +check_contains "C4E3BAC3" +run_sql "SELECT * from $DB.t;" +check_contains "ä½ " +check_contains "测试" +check_contains "娴嬭瘯" + +# Test BR DDL query string +echo "testing DDL query..." +run_curl https://$TIDB_STATUS_ADDR/ddl/history | grep -E '/\*from\(br\)\*/CREATE TABLE.*CHARSET=gbk' +run_curl https://$TIDB_STATUS_ADDR/ddl/history | grep -E '/\*from\(br\)\*/CREATE DATABASE' + +run_sql "DROP DATABASE $DB;" diff --git a/br/tests/br_charset_gbk/tidb-new-collation.toml b/br/tests/br_charset_gbk/tidb-new-collation.toml new file mode 100644 index 0000000000000..f3a4604c78376 --- /dev/null +++ b/br/tests/br_charset_gbk/tidb-new-collation.toml @@ -0,0 +1,11 @@ +# config of tidb + +new_collations_enabled_on_first_bootstrap = true + +[security] +ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +ssl-key = "/tmp/backup_restore_test/certs/tidb.key" +cluster-ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +cluster-ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +cluster-ssl-key = "/tmp/backup_restore_test/certs/tidb.key" diff --git a/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml new file mode 100644 index 0000000000000..dd82812d27156 --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml @@ -0,0 +1,16 @@ +# config of tidb + +# Schema lease duration +# There are lot of ddl in the tests, setting this +# to 360s to test whether BR is gracefully shutdown. +lease = "360s" + +new_collations_enabled_on_first_bootstrap = false + +[security] +ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +ssl-key = "/tmp/backup_restore_test/certs/tidb.key" +cluster-ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +cluster-ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +cluster-ssl-key = "/tmp/backup_restore_test/certs/tidb.key" diff --git a/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml new file mode 100644 index 0000000000000..d9cb1df6178f0 --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml @@ -0,0 +1,16 @@ +# config of tidb + +# Schema lease duration +# There are lot of ddl in the tests, setting this +# to 360s to test whether BR is gracefully shutdown. +lease = "360s" + +new_collations_enabled_on_first_bootstrap = true + +[security] +ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +ssl-key = "/tmp/backup_restore_test/certs/tidb.key" +cluster-ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +cluster-ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +cluster-ssl-key = "/tmp/backup_restore_test/certs/tidb.key" diff --git a/br/tests/br_check_new_collocation_enable/run.sh b/br/tests/br_check_new_collocation_enable/run.sh new file mode 100755 index 0000000000000..d74262148fb5c --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/run.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Copyright 2019 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu +DB="$TEST_NAME" + +cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +source $cur/../_utils/run_services + +PROGRESS_FILE="$TEST_DIR/progress_unit_file" +rm -rf $PROGRESS_FILE + +run_sql "CREATE DATABASE $DB;" + +run_sql "CREATE TABLE $DB.usertable1 ( \ + YCSB_KEY varchar(64) NOT NULL, \ + FIELD0 varchar(1) DEFAULT NULL, \ + PRIMARY KEY (YCSB_KEY) \ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" + +run_sql "INSERT INTO $DB.usertable1 VALUES (\"a\", \"b\");" +run_sql "INSERT INTO $DB.usertable1 VALUES (\"aa\", \"b\");" + +run_sql "CREATE TABLE $DB.usertable2 ( \ + YCSB_KEY varchar(64) NOT NULL, \ + FIELD0 varchar(1) DEFAULT NULL, \ + PRIMARY KEY (YCSB_KEY) \ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" + +run_sql "INSERT INTO $DB.usertable2 VALUES (\"c\", \"d\");" + +# backup db +echo "backup start ... with brv4.0.8 without NewCollactionEnable" +bin/brv4.0.8 backup db --db "$DB" -s "local://$TEST_DIR/$DB" \ + --ca "$TEST_DIR/certs/ca.pem" \ + --cert "$TEST_DIR/certs/br.pem" \ + --key "$TEST_DIR/certs/br.key" \ + --pd $PD_ADDR \ + --check-requirements=false + +# restore db from v4.0.8 version without `newCollationEnable` +echo "restore start ... without NewCollactionEnable in backupmeta" +restore_fail=0 +error_str="NewCollactionEnable not found in backupmeta" +test_log="new_collotion_enable_test.log" +unset BR_LOG_TO_TERM +run_br restore db --db $DB -s "local://$TEST_DIR/$DB" --pd $PD_ADDR --log-file $test_log || restore_fail=1 +if [ $restore_fail -ne 1 ]; then + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +if ! grep -i "$error_str" $test_log; then + echo "${error_str} not found in log" + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +rm -rf "$test_log" + +# backup with NewCollationEable = false +echo "Restart cluster with new_collation_enable=false" +start_services --tidb-cfg $cur/config/new_collation_enable_false.toml + +echo "backup start ... witch NewCollactionEnable=false in TiDB" +run_br --pd $PD_ADDR backup db --db "$DB" -s "local://$cur/${DB}_2" + +echo "Restart cluster with new_collation_enable=true" +start_services --tidb-cfg $cur/config/new_collation_enable_true.toml + +echo "restore start ... with NewCollactionEnable=True in TiDB" +restore_fail=0 +test_log2="new_collotion_enable_test2.log" +error_str="newCollationEnable not match" +unset BR_LOG_TO_TERM +run_br restore db --db $DB -s "local://$cur/${DB}_2" --pd $PD_ADDR --log-file $test_log2 || restore_fail=1 +if [ $restore_fail -ne 1 ]; then + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +if ! grep -i "$error_str" $test_log2; then + echo "${error_str} not found in log" + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +rm -rf "$test_log2" +rm -rf "$cur/${DB}_2" diff --git a/br/tests/br_crypter2/run.sh b/br/tests/br_crypter2/run.sh new file mode 100755 index 0000000000000..91de74376ebce --- /dev/null +++ b/br/tests/br_crypter2/run.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu +DB="$TEST_NAME" +TABLE="usertable" +DB_COUNT=3 + +function create_db_with_table(){ + for i in $(seq $DB_COUNT); do + run_sql "CREATE DATABASE $DB${i};" + go-ycsb load mysql -P tests/$TEST_NAME/workload -p mysql.host=$TIDB_IP -p mysql.port=$TIDB_PORT -p mysql.user=root -p mysql.db=$DB${i} + done +} + +function drop_db(){ + for i in $(seq $DB_COUNT); do + run_sql "DROP DATABASE $DB${i};" + done +} + +function check_db_row(){ + for i in $(seq $DB_COUNT); do + row_count_new[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') + done + + fail=false + for i in $(seq $DB_COUNT); do + if [ "${row_count_ori[i]}" != "${row_count_new[i]}" ];then + fail=true + echo "TEST: [$TEST_NAME] fail on database $DB${i}" + fi + echo "database $DB${i} [original] row count: ${row_count_ori[i]}, [after br] row count: ${row_count_new[i]}" + done + + if $fail; then + echo "TEST: [$TEST_NAME] failed!" + exit 1 + fi +} + +# Create dbs with table +create_db_with_table + +# Get the original row count from dbs +for i in $(seq $DB_COUNT); do + row_count_ori[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') +done + +# Test backup/restore with crypt for br +CRYPTER_METHOD=aes128-ctr +CRYPTER_KEY="0123456789abcdef0123456789abcdef" + +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/backup/noop-backup=100*return(1)" +run_br --pd $PD_ADDR backup full -s "local://$TEST_DIR/$DB/${CRYPTER_METHOD}_file" \ + --use-backupmeta-v2=true --check-requirements=false --crypter.method $CRYPTER_METHOD --crypter.key $CRYPTER_KEY + +drop_db + +run_br --pd $PD_ADDR restore full -s "local://$TEST_DIR/$DB/${CRYPTER_METHOD}_file" \ + --check-requirements=false --crypter.method $CRYPTER_METHOD --crypter.key $CRYPTER_KEY + +check_db_row + +# Drop dbs finally +drop_db diff --git a/br/tests/br_crypter2/workload b/br/tests/br_crypter2/workload new file mode 100644 index 0000000000000..448ca3c1a477f --- /dev/null +++ b/br/tests/br_crypter2/workload @@ -0,0 +1,12 @@ +recordcount=1000 +operationcount=0 +workload=core + +readallfields=true + +readproportion=0 +updateproportion=0 +scanproportion=0 +insertproportion=0 + +requestdistribution=uniform \ No newline at end of file diff --git a/br/tests/br_full_ddl/run.sh b/br/tests/br_full_ddl/run.sh index ad27e091ef476..9ae563c6b0aef 100755 --- a/br/tests/br_full_ddl/run.sh +++ b/br/tests/br_full_ddl/run.sh @@ -19,6 +19,7 @@ DB="$TEST_NAME" TABLE="usertable" DDL_COUNT=5 LOG=/$TEST_DIR/backup.log +RESTORE_LOG=LOG=/$TEST_DIR/restore.log BACKUP_STAT=/$TEST_DIR/backup_stat RESOTRE_STAT=/$TEST_DIR/restore_stat @@ -110,6 +111,20 @@ fi # clear restore environment run_sql "DROP DATABASE $DB;" +# restore full +echo "restore start..." +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/restore/restore-createtables-error=return(true)" +run_br restore full -s "local://$TEST_DIR/$DB" --pd $PD_ADDR --log-file $RESTORE_LOG --ddl-batch-size=128 || { cat $RESTORE_LOG; } +export GO_FAILPOINTS="" + +panic_count=$(cat $RESTORE_LOG | grep "panic"| wc -l) +if [ "${panic_count}" != "0" ];then + echo "TEST: [$TEST_NAME] fail on batch create tables" + exit 1 +fi + +# clear restore environment +run_sql "DROP DATABASE $DB;" # restore full echo "restore start..." export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/pdutil/PDEnabledPauseConfig=return(true)" diff --git a/br/tests/br_gcs/run.sh b/br/tests/br_gcs/run.sh index a29cbafa8668c..3829bed165ce9 100755 --- a/br/tests/br_gcs/run.sh +++ b/br/tests/br_gcs/run.sh @@ -98,7 +98,7 @@ done # new version restore full echo "restore start..." -run_br restore full -s "gcs://$BUCKET/$DB?" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" +run_br restore full -s "gcs://$BUCKET/$DB?" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" --check-requirements=false for i in $(seq $DB_COUNT); do row_count_new[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') @@ -126,7 +126,7 @@ for i in $(seq $DB_COUNT); do done echo "v4.0.8 version restore start..." -run_br restore full -s "gcs://$BUCKET/${DB}_old" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" +bin/brv4.0.8 restore full -s "gcs://$BUCKET/${DB}_old" --pd $PD_ADDR --gcs.endpoint="http://$GCS_HOST:$GCS_PORT/storage/v1/" for i in $(seq $DB_COUNT); do row_count_new[${i}]=$(run_sql "SELECT COUNT(*) FROM $DB${i}.$TABLE;" | awk '/COUNT/{print $2}') diff --git a/br/tests/br_incompatible_tidb_config/run.sh b/br/tests/br_incompatible_tidb_config/run.sh index 0034dd850249c..a6bdf089ce698 100755 --- a/br/tests/br_incompatible_tidb_config/run.sh +++ b/br/tests/br_incompatible_tidb_config/run.sh @@ -52,10 +52,17 @@ run_br --pd $PD_ADDR backup db --db "$DB" -s "local://$TEST_DIR/$DB$INCREMENTAL_ # restore run_sql "drop schema $DB;" +# restore with ddl(create table) job one by one +run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$TABLE" --ddl-batch-size=1 -run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$TABLE" +run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$INCREMENTAL_TABLE" --ddl-batch-size=1 -run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$INCREMENTAL_TABLE" +# restore +run_sql "drop schema $DB;" +# restore with batch create table +run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$TABLE" --ddl-batch-size=128 + +run_br --pd $PD_ADDR restore db --db "$DB" -s "local://$TEST_DIR/$DB$INCREMENTAL_TABLE" --ddl-batch-size=128 run_sql "drop schema $DB;" run_sql "create schema $DB;" diff --git a/br/tests/br_incremental_ddl/run.sh b/br/tests/br_incremental_ddl/run.sh index 68867a194a2a4..49b825498e2af 100755 --- a/br/tests/br_incremental_ddl/run.sh +++ b/br/tests/br_incremental_ddl/run.sh @@ -79,3 +79,26 @@ run_sql "INSERT INTO ${DB}.${TABLE}(c2) VALUES ('1');" run_sql "INSERT INTO ${DB}.${TABLE}_rename2(c) VALUES ('1');" run_sql "DROP DATABASE $DB;" + +# full restore with batch ddl +echo "full restore start..." +run_br restore table --db $DB --table $TABLE -s "local://$TEST_DIR/$DB/full" --pd $PD_ADDR --ddl-batch-size=128 +row_count_full=$(run_sql "SELECT COUNT(*) FROM $DB.$TABLE;" | awk '/COUNT/{print $2}') +# check full restore +if [ "${row_count_full}" != "${ROW_COUNT}" ];then + echo "TEST: [$TEST_NAME] full restore fail on database $DB" + exit 1 +fi +# incremental restore +echo "incremental restore start..." +run_br restore db --db $DB -s "local://$TEST_DIR/$DB/inc" --pd $PD_ADDR --ddl-batch-size=128 +row_count_inc=$(run_sql "SELECT COUNT(*) FROM $DB.$TABLE;" | awk '/COUNT/{print $2}') +# check full restore +if [ "${row_count_inc}" != "${ROW_COUNT}" ];then + echo "TEST: [$TEST_NAME] incremental restore fail on database $DB" + exit 1 +fi +run_sql "INSERT INTO ${DB}.${TABLE}(c2) VALUES ('1');" +run_sql "INSERT INTO ${DB}.${TABLE}_rename2(c) VALUES ('1');" + +run_sql "DROP DATABASE $DB;" \ No newline at end of file diff --git a/br/tests/br_key_locked/codec.go b/br/tests/br_key_locked/codec.go index d53b92cb68613..b1755f6aa1576 100644 --- a/br/tests/br_key_locked/codec.go +++ b/br/tests/br_key_locked/codec.go @@ -31,13 +31,13 @@ type codecPDClient struct { // GetRegion encodes the key before send requests to pd-server and decodes the // returned StartKey && EndKey from pd-server. -func (c *codecPDClient) GetRegion(ctx context.Context, key []byte) (*pd.Region, error) { +func (c *codecPDClient) GetRegion(ctx context.Context, key []byte, opts ...pd.GetRegionOption) (*pd.Region, error) { encodedKey := codec.EncodeBytes(nil, key) region, err := c.Client.GetRegion(ctx, encodedKey) return processRegionResult(region, err) } -func (c *codecPDClient) GetPrevRegion(ctx context.Context, key []byte) (*pd.Region, error) { +func (c *codecPDClient) GetPrevRegion(ctx context.Context, key []byte, opts ...pd.GetRegionOption) (*pd.Region, error) { encodedKey := codec.EncodeBytes(nil, key) region, err := c.Client.GetPrevRegion(ctx, encodedKey) return processRegionResult(region, err) @@ -45,7 +45,7 @@ func (c *codecPDClient) GetPrevRegion(ctx context.Context, key []byte) (*pd.Regi // GetRegionByID encodes the key before send requests to pd-server and decodes the // returned StartKey && EndKey from pd-server. -func (c *codecPDClient) GetRegionByID(ctx context.Context, regionID uint64) (*pd.Region, error) { +func (c *codecPDClient) GetRegionByID(ctx context.Context, regionID uint64, opts ...pd.GetRegionOption) (*pd.Region, error) { region, err := c.Client.GetRegionByID(ctx, regionID) return processRegionResult(region, err) } diff --git a/br/tests/br_key_locked/locker.go b/br/tests/br_key_locked/locker.go index fc7e72d532093..ec16a4b096e41 100644 --- a/br/tests/br_key_locked/locker.go +++ b/br/tests/br_key_locked/locker.go @@ -28,6 +28,7 @@ import ( "math/rand" "net" "net/http" + "strconv" "time" "github.com/pingcap/errors" @@ -184,6 +185,7 @@ type Locker struct { } // generateLocks sends Prewrite requests to TiKV to generate locks, without committing and rolling back. +//nolint:gosec func (c *Locker) generateLocks(pctx context.Context) error { log.Info("genLock started") @@ -339,11 +341,12 @@ func (c *Locker) lockBatch(ctx context.Context, keys [][]byte, primary []byte) ( } } +//nolint:gosec func randStr() string { length := rand.Intn(128) res := "" for i := 0; i < length; i++ { - res += fmt.Sprint(rand.Intn(10)) + res += strconv.Itoa(rand.Intn(10)) } return res } diff --git a/br/tests/br_rawkv/client.go b/br/tests/br_rawkv/client.go index 6117bc215c3c9..8c63178abb4b6 100644 --- a/br/tests/br_rawkv/client.go +++ b/br/tests/br_rawkv/client.go @@ -123,20 +123,25 @@ func randGen(client *rawkv.Client, startKey, endKey []byte, maxLen int, concurre for i := 0; i < concurrency; i++ { go func() { for { - keys := make([][]byte, 0, batchSize) - values := make([][]byte, 0, batchSize) + // FIXME: because of the incompatibility of `BatchPut`, + // we must use RawPut here. See https://github.com/tikv/client-go/pull/403. + // Once the client get fixed, we'd better use the BatchPut API back. + // keys := make([][]byte, 0, batchSize) + // values := make([][]byte, 0, batchSize) for i := 0; i < batchSize; i++ { key := randKey(startKey, endKey, maxLen) - keys = append(keys, key) value := randValue() - values = append(values, value) - } - err := client.BatchPut(context.TODO(), keys, values, nil) - if err != nil { - errCh <- errors.Trace(err) + // keys = append(keys, key) + // values = append(values, value) + err := client.Put(context.Background(), key, value) + + if err != nil { + errCh <- errors.Trace(err) + } } + } }() } @@ -158,6 +163,7 @@ func testRandKey(startKey, endKey []byte, maxLen int) { } } +//nolint:gosec func randKey(startKey, endKey []byte, maxLen int) []byte { Retry: for { // Regenerate on fail @@ -208,6 +214,7 @@ Retry: } } +//nolint:gosec func randValue() []byte { result := make([]byte, 0, 512) for i := 0; i < 512; i++ { @@ -303,12 +310,17 @@ func put(client *rawkv.Client, dataStr string) error { keys = append(keys, key) values = append(values, value) + // FIXME: because of the incompatibility of `BatchPut`, + // we must use RawPut here. See https://github.com/tikv/client-go/pull/403. + // Once the client get fixed, we'd better use the BatchPut API back. + if err := client.Put(context.Background(), key, value); err != nil { + return err + } } log.Info("Put rawkv data", zap.ByteStrings("keys", keys), zap.ByteStrings("values", values)) - err := client.BatchPut(context.TODO(), keys, values, nil) - return errors.Trace(err) + return nil } const defaultScanBatchSize = 128 diff --git a/br/tests/br_rawkv/run.sh b/br/tests/br_rawkv/run.sh old mode 100644 new mode 100755 index 15de10c42322e..97450d3e65fc7 --- a/br/tests/br_rawkv/run.sh +++ b/br/tests/br_rawkv/run.sh @@ -14,15 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -eu +set -eux # restart service without tiflash source $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/../_utils/run_services start_services --no-tiflash BACKUP_DIR=$TEST_DIR/"raw_backup" - -rm -rf $BACKUP_DIR +BACKUP_FULL=$TEST_DIR/"rawkv-full" checksum() { bin/rawkv --pd $PD_ADDR \ @@ -49,9 +48,12 @@ test_full_rawkv() { check_range_start=00 check_range_end=ff + rm -rf $BACKUP_FULL + checksum_full=$(checksum $check_range_start $check_range_end) # backup current state of key-values - run_br --pd $PD_ADDR backup raw -s "local://$TEST_DIR/rawkv-full" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" + # raw backup is not working with range [nil, nil]. TODO: fix it. + run_br --pd $PD_ADDR backup raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --format hex clean $check_range_start $check_range_end # Ensure the data is deleted @@ -61,7 +63,7 @@ test_full_rawkv() { fail_and_exit fi - run_br --pd $PD_ADDR restore raw -s "local://$TEST_DIR/rawkv-full" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" + run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --format hex checksum_new=$(checksum $check_range_start $check_range_end) if [ "$checksum_new" != "$checksum_full" ];then echo "failed to restore" @@ -71,71 +73,91 @@ test_full_rawkv() { checksum_empty=$(checksum 31 3130303030303030) -# generate raw kv randomly in range[start-key, end-key) in 10s -bin/rawkv --pd $PD_ADDR \ - --ca "$TEST_DIR/certs/ca.pem" \ - --cert "$TEST_DIR/certs/br.pem" \ - --key "$TEST_DIR/certs/br.key" \ - --mode rand-gen --start-key 31 --end-key 3130303030303030 --duration 10 +run_test() { + if [ -z "$1" ];then + echo "run test" + else + export GO_FAILPOINTS="$1" + echo "run test with failpoints: $GO_FAILPOINTS" + fi -# put some keys around 311122 to check the correctness of endKey of restoring -bin/rawkv --pd $PD_ADDR \ - --ca "$TEST_DIR/certs/ca.pem" \ - --cert "$TEST_DIR/certs/br.pem" \ - --key "$TEST_DIR/certs/br.key" \ - --mode put --put-data "311121:31, 31112100:32, 311122:33, 31112200:34, 3111220000:35, 311123:36" + rm -rf $BACKUP_DIR + clean 31 3130303030303030 -checksum_ori=$(checksum 31 3130303030303030) -checksum_partial=$(checksum 311111 311122) + # generate raw kv randomly in range[start-key, end-key) in 10s + bin/rawkv --pd $PD_ADDR \ + --ca "$TEST_DIR/certs/ca.pem" \ + --cert "$TEST_DIR/certs/br.pem" \ + --key "$TEST_DIR/certs/br.key" \ + --mode rand-gen --start-key 31 --end-key 3130303030303030 --duration 10 -# backup rawkv -echo "backup start..." -run_br --pd $PD_ADDR backup raw -s "local://$BACKUP_DIR" --start 31 --end 3130303030303030 --format hex --concurrency 4 --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" + # put some keys around 311122 to check the correctness of endKey of restoring + bin/rawkv --pd $PD_ADDR \ + --ca "$TEST_DIR/certs/ca.pem" \ + --cert "$TEST_DIR/certs/br.pem" \ + --key "$TEST_DIR/certs/br.key" \ + --mode put --put-data "311121:31, 31112100:32, 311122:33, 31112200:34, 3111220000:35, 311123:36" -# delete data in range[start-key, end-key) -clean 31 3130303030303030 -# Ensure the data is deleted -checksum_new=$(checksum 31 3130303030303030) + checksum_ori=$(checksum 31 3130303030303030) + checksum_partial=$(checksum 311111 311122) -if [ "$checksum_new" != "$checksum_empty" ];then - echo "failed to delete data in range" - fail_and_exit -fi + # backup rawkv + echo "backup start..." + run_br --pd $PD_ADDR backup raw -s "local://$BACKUP_DIR" --start 31 --end 3130303030303030 --format hex --concurrency 4 --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" -# restore rawkv -echo "restore start..." -run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_DIR" --start 31 --end 3130303030303030 --format hex --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" + # delete data in range[start-key, end-key) + clean 31 3130303030303030 + # Ensure the data is deleted + checksum_new=$(checksum 31 3130303030303030) -checksum_new=$(checksum 31 3130303030303030) + if [ "$checksum_new" != "$checksum_empty" ];then + echo "failed to delete data in range" + fail_and_exit + fi -if [ "$checksum_new" != "$checksum_ori" ];then - echo "checksum failed after restore" - fail_and_exit -fi + # restore rawkv + echo "restore start..." + run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_DIR" --start 31 --end 3130303030303030 --format hex --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" -test_full_rawkv + checksum_new=$(checksum 31 3130303030303030) -# delete data in range[start-key, end-key) -clean 31 3130303030303030 -# Ensure the data is deleted -checksum_new=$(checksum 31 3130303030303030) + if [ "$checksum_new" != "$checksum_ori" ];then + echo "checksum failed after restore" + fail_and_exit + fi -if [ "$checksum_new" != "$checksum_empty" ];then - echo "failed to delete data in range" - fail_and_exit -fi + test_full_rawkv + + # delete data in range[start-key, end-key) + clean 31 3130303030303030 + # Ensure the data is deleted + checksum_new=$(checksum 31 3130303030303030) + + if [ "$checksum_new" != "$checksum_empty" ];then + echo "failed to delete data in range" + fail_and_exit + fi + + echo "partial restore start..." + run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_DIR" --start 311111 --end 311122 --format hex --concurrency 4 --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" + bin/rawkv --pd $PD_ADDR \ + --ca "$TEST_DIR/certs/ca.pem" \ + --cert "$TEST_DIR/certs/br.pem" \ + --key "$TEST_DIR/certs/br.key" \ + --mode scan --start-key 311121 --end-key 33 + + checksum_new=$(checksum 31 3130303030303030) + + if [ "$checksum_new" != "$checksum_partial" ];then + echo "checksum failed after restore" + fail_and_exit + fi + + export GO_FAILPOINTS="" +} -echo "partial restore start..." -run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_DIR" --start 311111 --end 311122 --format hex --concurrency 4 --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" -bin/rawkv --pd $PD_ADDR \ - --ca "$TEST_DIR/certs/ca.pem" \ - --cert "$TEST_DIR/certs/br.pem" \ - --key "$TEST_DIR/certs/br.key" \ - --mode scan --start-key 311121 --end-key 33 -checksum_new=$(checksum 31 3130303030303030) +run_test "" -if [ "$checksum_new" != "$checksum_partial" ];then - echo "checksum failed after restore" - fail_and_exit -fi +# ingest "region error" to trigger fineGrainedBackup +run_test "github.com/pingcap/tidb/br/pkg/backup/tikv-region-error=return(\"region error\")" diff --git a/br/tests/br_s3/run.sh b/br/tests/br_s3/run.sh index d0c20996db7ef..2357069cb751a 100755 --- a/br/tests/br_s3/run.sh +++ b/br/tests/br_s3/run.sh @@ -37,13 +37,15 @@ start_s3() { bin/minio server --address $S3_ENDPOINT "$TEST_DIR/$DB" & s3_pid=$! i=0 - while ! curl -o /dev/null -v -s "http://$S3_ENDPOINT/"; do + status="$(curl -o /dev/null -v -s "http://$S3_ENDPOINT/" -w '%{http_code}' || true)" + while ! { [ "$status" -gt 0 ] && [ "$status" -lt 500 ]; } ; do i=$(($i+1)) if [ $i -gt 30 ]; then echo 'Failed to start minio' exit 1 fi sleep 2 + status="$(curl -o /dev/null -v -s "http://$S3_ENDPOINT/" -w '%{http_code}' || true)" done } @@ -101,6 +103,12 @@ for p in $(seq 2); do exit 1 fi + target_log="get newCollationEnable for check during restore" + if ! grep -i "$target_log" $BACKUP_LOG; then + echo "${target_log} not found in log" + exit 1 + fi + for i in $(seq $DB_COUNT); do run_sql "DROP DATABASE $DB${i};" done diff --git a/br/tests/br_split_region_fail/run.sh b/br/tests/br_split_region_fail/run.sh index be26823cd6810..13b511313ebfa 100644 --- a/br/tests/br_split_region_fail/run.sh +++ b/br/tests/br_split_region_fail/run.sh @@ -52,7 +52,7 @@ BR_LOG_TO_TERM=1 grep "a error occurs on split region" $LOG && \ grep "split region meet not leader error" $LOG && \ -grep "Full restore success" $LOG && \ +grep "Full Restore success" $LOG && \ grep "find new leader" $LOG if [ $? -ne 0 ]; then diff --git a/br/tests/br_tidb_placement_policy/run.sh b/br/tests/br_tidb_placement_policy/run.sh new file mode 100644 index 0000000000000..dbc81d6f60a9d --- /dev/null +++ b/br/tests/br_tidb_placement_policy/run.sh @@ -0,0 +1,193 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu +DB="$TEST_NAME" +TABLES_COUNT=30 + +PROGRESS_FILE="$TEST_DIR/progress_file" +BACKUPMETAV1_LOG="$TEST_DIR/backup.log" +BACKUPMETAV2_LOG="$TEST_DIR/backupv2.log" +RESTORE_LOG="$TEST_DIR/restore.log" +rm -rf $PROGRESS_FILE + +run_sql "create schema $DB;" +run_sql "create placement policy fivereplicas followers=4;" +run_sql "create placement policy tworeplicas followers=1;" + +# generate 30 tables with 1 row content with policy fivereplicas;. +i=1 +while [ $i -le $TABLES_COUNT ]; do + run_sql "create table $DB.sbtest$i(id int primary key, k int not null, c char(120) not null, pad char(60) not null) placement policy=fivereplicas partition by range(id) (partition p0 values less than (10) placement policy tworeplicas, partition p1 values less than MAXVALUE)" + run_sql "insert into $DB.sbtest$i values ($i, $i, '$i', '$i');" + i=$(($i+1)) +done + +# backup db +echo "full backup meta v2 start..." +unset BR_LOG_TO_TERM +rm -f $BACKUPMETAV2_LOG +run_br backup full --log-file $BACKUPMETAV2_LOG -s "local://$TEST_DIR/${DB}v2" --pd $PD_ADDR --use-backupmeta-v2 + +echo "full backup meta v1 start..." +rm -f $BACKUPMETAV1_LOG +run_br backup full --log-file $BACKUPMETAV1_LOG -s "local://$TEST_DIR/$DB" --pd $PD_ADDR + +# clear data and policy fore restore. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" + +# restore with tidb-placement-policy +echo "restore with tidb-placement start..." +run_br restore db --db $DB -s "local://$TEST_DIR/${DB}v2" --pd $PD_ADDR + +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY fivereplicas" | wc -l) +if [ "$policy_count" -ne "1" ];then + echo "TEST: [$TEST_NAME] failed! due to policy restore failed" + exit 1 +fi + +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY tworeplicas" | wc -l) +if [ "$policy_count" -ne "1" ];then + echo "TEST: [$TEST_NAME] failed! due to policy restore failed" + exit 1 +fi + +# clear data and policy for restore. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" + +# restore without tidb-placement-policy +echo "restore without tidb-placement start..." +run_br restore db --db $DB -s "local://$TEST_DIR/$DB" --pd $PD_ADDR --with-tidb-placement-mode "ignore" + +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | wc -l) +if [ "$policy_count" -ne "0" ];then + echo "TEST: [$TEST_NAME] failed! due to policy should be ignore" + exit 1 +fi + +# clear data and policy for next case. +run_sql "DROP DATABASE $DB;" + +echo "test backup db can ignore placement policy" +run_sql "create schema $DB;" +run_sql "create placement policy fivereplicas followers=4;" +run_sql "create placement policy tworeplicas followers=1;" + +# generate one table with one row content with policy fivereplicas;. +run_sql "create table $DB.sbtest(id int primary key, k int not null, c char(120) not null, pad char(60) not null) placement policy=fivereplicas partition by range(id) (partition p0 values less than (10) placement policy tworeplicas, partition p1 values less than MAXVALUE);" +run_sql "insert into $DB.sbtest values ($i, $i, '$i', '$i');" + +run_br backup db --db $DB -s "local://$TEST_DIR/${DB}_db" --pd $PD_ADDR + +# clear data and policy for restore. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" + +# restore should success and no policy have been restored. +run_br restore db --db $DB -s "local://$TEST_DIR/${DB}_db" --pd $PD_ADDR + +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | wc -l) +if [ "$policy_count" -ne "0" ];then + echo "TEST: [$TEST_NAME] failed! due to policy should be ignore" + exit 1 +fi + +# clear data for next case. +run_sql "DROP DATABASE $DB;" + +echo "test only restore related placement policy..." +run_sql "create schema $DB;" +# we have three policies +run_sql "create placement policy fivereplicas followers=4;" +run_sql "create placement policy tworeplicas followers=1;" +run_sql "create placement policy foureplicas followers=3;" + +# generate one table with one row content with policy fivereplicas;. +run_sql "create table $DB.sbtest(id int primary key, k int not null, c char(120) not null, pad char(60) not null) placement policy=fivereplicas partition by range(id) (partition p0 values less than (10) placement policy tworeplicas, partition p1 values less than MAXVALUE);" +run_sql "insert into $DB.sbtest values ($i, $i, '$i', '$i');" + +# backup table and policies +run_br backup full -s "local://$TEST_DIR/${DB}_related" --pd $PD_ADDR + +# clear data and policies for restore. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" +run_sql "DROP PLACEMENT POLICY foureplicas;" + +# restore table +run_br restore table --db $DB --table sbtest -s "local://$TEST_DIR/${DB}_related" --pd $PD_ADDR + +# verify only one policy has been restored +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | wc -l) +if [ "$policy_count" -ne "2" ];then + echo "TEST: [$TEST_NAME] failed! due to policy should be ignore" + exit 1 +fi + +# which have fivereplicas... +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | grep "fivereplicas" | wc -l) +if [ "$policy_count" -ne "1" ];then + echo "TEST: [$TEST_NAME] failed! due to policy restore failed" + exit 1 +fi + +# which have tworeplicas... +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | grep "tworeplicas" | wc -l) +if [ "$policy_count" -ne "1" ];then + echo "TEST: [$TEST_NAME] failed! due to policy restore failed" + exit 1 +fi + +# clear data and policies for next case. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" + +echo "test restore all placement policies..." +run_sql "create schema $DB;" +# we have three policies +run_sql "create placement policy fivereplicas followers=4;" +run_sql "create placement policy tworeplicas followers=1;" +run_sql "create placement policy foureplicas followers=3;" + +# generate one table with one row content with policy fivereplicas;. +run_sql "create table $DB.sbtest(id int primary key, k int not null, c char(120) not null, pad char(60) not null) placement policy=fivereplicas partition by range(id) (partition p0 values less than (10) placement policy tworeplicas, partition p1 values less than MAXVALUE);" +run_sql "insert into $DB.sbtest values ($i, $i, '$i', '$i');" + +# backup table and policies +run_br backup full -s "local://$TEST_DIR/${DB}_all" --pd $PD_ADDR + +# clear data and policies for restore. +run_sql "DROP DATABASE $DB;" +run_sql "DROP PLACEMENT POLICY fivereplicas;" +run_sql "DROP PLACEMENT POLICY tworeplicas;" +run_sql "DROP PLACEMENT POLICY foureplicas;" + +# restore table +run_br restore full -f "$DB.sbtest" -s "local://$TEST_DIR/${DB}_all" --pd $PD_ADDR + +# verify all policies have been restored even we only restore one table during tableFilter. +policy_count=$(run_sql "use $DB; show placement;" | grep "POLICY" | wc -l) +if [ "$policy_count" -ne "3" ];then + echo "TEST: [$TEST_NAME] failed! due to policy should be ignore" + exit 1 +fi diff --git a/br/tests/lightning_character_sets/run.sh b/br/tests/lightning_character_sets/run.sh index 6750ee08a4838..3d62ed26360ca 100755 --- a/br/tests/lightning_character_sets/run.sh +++ b/br/tests/lightning_character_sets/run.sh @@ -41,7 +41,7 @@ run_sql 'DROP TABLE charsets.gb18030;' run_lightning_expecting_fail --config "tests/$TEST_NAME/utf8mb4.toml" -d "tests/$TEST_NAME/gb18030" run_lightning --config "tests/$TEST_NAME/binary.toml" -d "tests/$TEST_NAME/gb18030" -run_sql 'SELECT sum(`Ö÷¼ü`) AS s FROM charsets.gb18030' +run_sql 'SELECT sum(`????`) AS s FROM charsets.gb18030' check_contains 's: 267' # utf8mb4 diff --git a/br/tests/lightning_checkpoint/config.toml b/br/tests/lightning_checkpoint/config.toml index e4595a6e0f045..9828bd6dea636 100644 --- a/br/tests/lightning_checkpoint/config.toml +++ b/br/tests/lightning_checkpoint/config.toml @@ -1,4 +1,5 @@ [lightning] +index-concurrency = 1 table-concurrency = 1 [checkpoint] diff --git a/br/tests/lightning_checkpoint/run.sh b/br/tests/lightning_checkpoint/run.sh index 41513ba575fc6..7afe980fcd133 100755 --- a/br/tests/lightning_checkpoint/run.sh +++ b/br/tests/lightning_checkpoint/run.sh @@ -83,12 +83,14 @@ for BACKEND in importer local; do set -e export GO_FAILPOINTS="$SLOWDOWN_FAILPOINTS" - set +e - for i in $(seq "$TABLE_COUNT"); do - echo "******** Importing Table Now (step $i/$TABLE_COUNT) ********" - run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 2> /dev/null - done - set -e + # After everything is done, there should be no longer new calls to ImportEngine + # (and thus `kill_lightning_after_one_import` will spare this final check) + echo "******** Verify checkpoint no-op ********" + run_lightning -d "$DBPATH" --backend $BACKEND --enable-checkpoint=1 + run_sql "$PARTIAL_IMPORT_QUERY" + check_contains "s: $(( (1000 * $CHUNK_COUNT + 1001) * $CHUNK_COUNT * $TABLE_COUNT ))" + run_sql 'SELECT count(*) FROM `tidb_lightning_checkpoint_test_cppk`.table_v7 WHERE status >= 200' + check_contains "count(*): $TABLE_COUNT" # Start importing the tables. run_sql 'DROP DATABASE IF EXISTS cppk_tsr' diff --git a/br/tests/lightning_checksum_mismatch/run.sh b/br/tests/lightning_checksum_mismatch/run.sh index d13451d51ec5b..184585cf77116 100755 --- a/br/tests/lightning_checksum_mismatch/run.sh +++ b/br/tests/lightning_checksum_mismatch/run.sh @@ -2,4 +2,4 @@ set -eux -run_lightning 2>&1 | grep -q "Error: checksum mismatched remote vs local" +run_lightning 2>&1 | grep -q "checksum mismatched remote vs local" diff --git a/br/tests/lightning_column_permutation/data/perm-schema-create.sql b/br/tests/lightning_column_permutation/data/perm-schema-create.sql index fe9a5be60a3ff..28138f8d72659 100644 --- a/br/tests/lightning_column_permutation/data/perm-schema-create.sql +++ b/br/tests/lightning_column_permutation/data/perm-schema-create.sql @@ -1 +1 @@ -CREATE DATABASE `perm` IF NOT EXISTS; +CREATE DATABASE IF NOT EXISTS `perm`; diff --git a/br/tests/lightning_distributed_import/config.toml b/br/tests/lightning_distributed_import/config.toml index 200af8e45dfdc..947b16037dd5d 100644 --- a/br/tests/lightning_distributed_import/config.toml +++ b/br/tests/lightning_distributed_import/config.toml @@ -1,6 +1,7 @@ [tikv-importer] backend = 'local' duplicate-resolution = 'none' +incremental-import = true [post-restore] checksum = "required" diff --git a/br/tests/lightning_duplicate_detection/config1.toml b/br/tests/lightning_duplicate_detection/config1.toml index 0b2b6df2a70e8..6497e9e30949b 100644 --- a/br/tests/lightning_duplicate_detection/config1.toml +++ b/br/tests/lightning_duplicate_detection/config1.toml @@ -6,6 +6,7 @@ table-concurrency = 10 [tikv-importer] backend = "local" duplicate-resolution = 'record' +incremental-import = true [checkpoint] enable = true diff --git a/br/tests/lightning_duplicate_detection/config2.toml b/br/tests/lightning_duplicate_detection/config2.toml index e978ffb9cd8b5..760f50168508a 100644 --- a/br/tests/lightning_duplicate_detection/config2.toml +++ b/br/tests/lightning_duplicate_detection/config2.toml @@ -6,6 +6,7 @@ table-concurrency = 10 [tikv-importer] backend = "local" duplicate-resolution = 'record' +incremental-import = true [checkpoint] enable = true diff --git a/br/tests/lightning_error_summary/run.sh b/br/tests/lightning_error_summary/run.sh index dcb06d6bf8c2f..e32ea302d8698 100755 --- a/br/tests/lightning_error_summary/run.sh +++ b/br/tests/lightning_error_summary/run.sh @@ -46,9 +46,9 @@ check_contains 'sum(k): 32' # Verify the log contains the expected messages at the last few lines tail -20 "$TEST_DIR/lightning-error-summary.log" > "$TEST_DIR/lightning-error-summary.tail" grep -Fq '["tables failed to be imported"] [count=2]' "$TEST_DIR/lightning-error-summary.tail" -grep -Fq '[-] [table=`error_summary`.`a`] [status=checksum] [error="checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" -grep -Fq '[-] [table=`error_summary`.`c`] [status=checksum] [error="checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" -! grep -Fq '[-] [table=`error_summary`.`b`] [status=checksum] [error="checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" +grep -Fq '[-] [table=`error_summary`.`a`] [status=checksum] [error="[Lighting:Restore:ErrChecksumMismatch]checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" +grep -Fq '[-] [table=`error_summary`.`c`] [status=checksum] [error="[Lighting:Restore:ErrChecksumMismatch]checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" +! grep -Fq '[-] [table=`error_summary`.`b`] [status=checksum] [error="[Lighting:Restore:ErrChecksumMismatch]checksum mismatched' "$TEST_DIR/lightning-error-summary.tail" # Now check the error log when the checkpoint is not cleaned. diff --git a/br/tests/lightning_fail_fast/run.sh b/br/tests/lightning_fail_fast/run.sh index 8894bd0c5c8f4..a1723b3e2cffd 100755 --- a/br/tests/lightning_fail_fast/run.sh +++ b/br/tests/lightning_fail_fast/run.sh @@ -16,7 +16,7 @@ set -eux -export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownWriteRows=sleep(50);github.com/pingcap/tidb/br/pkg/lightning/restore/SetMinDeliverBytes=return(1)' +export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/restore/SlowDownWriteRows=sleep(100);github.com/pingcap/tidb/br/pkg/lightning/restore/SetMinDeliverBytes=return(1)' for CFG in chunk engine; do rm -f "$TEST_DIR/lightning-tidb.log" diff --git a/br/tests/lightning_incremental/config.toml b/br/tests/lightning_incremental/config.toml index e69de29bb2d1d..761e60b91b804 100644 --- a/br/tests/lightning_incremental/config.toml +++ b/br/tests/lightning_incremental/config.toml @@ -0,0 +1,2 @@ +[tikv-importer] +incremental-import = true diff --git a/br/tests/lightning_incremental/data/incr.empty_table-schema.sql b/br/tests/lightning_incremental/data/incr.empty_table-schema.sql new file mode 100644 index 0000000000000..881156cb99fd5 --- /dev/null +++ b/br/tests/lightning_incremental/data/incr.empty_table-schema.sql @@ -0,0 +1 @@ +CREATE TABLE `empty_table` (id int primary key); diff --git a/br/tests/lightning_incremental/data1/incr.empty_table-schema.sql b/br/tests/lightning_incremental/data1/incr.empty_table-schema.sql new file mode 100644 index 0000000000000..881156cb99fd5 --- /dev/null +++ b/br/tests/lightning_incremental/data1/incr.empty_table-schema.sql @@ -0,0 +1 @@ +CREATE TABLE `empty_table` (id int primary key); diff --git a/br/tests/lightning_incremental/data1/incr.empty_table2-schema.sql b/br/tests/lightning_incremental/data1/incr.empty_table2-schema.sql new file mode 100644 index 0000000000000..610412d940815 --- /dev/null +++ b/br/tests/lightning_incremental/data1/incr.empty_table2-schema.sql @@ -0,0 +1 @@ +CREATE TABLE `empty_table2` (id int primary key, s varchar(16)); diff --git a/br/tests/lightning_incremental/run.sh b/br/tests/lightning_incremental/run.sh index f04630055936a..4cdd5a53ec74b 100644 --- a/br/tests/lightning_incremental/run.sh +++ b/br/tests/lightning_incremental/run.sh @@ -18,60 +18,66 @@ set -eu check_cluster_version 4 0 0 "incremental restore" || exit 0 -DB_NAME=incr +run_lightning_and_check_meta() { + run_lightning --backend local "$@" + # check metadata table is not exist + run_sql "SHOW DATABASES like 'lightning_metadata';" + check_not_contains "Database: lightning_metadata" +} -for backend in importer local; do - run_sql "DROP DATABASE IF EXISTS incr;" - run_lightning --backend $backend +DB_NAME=incr - for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do - run_sql "SELECT count(*) from incr.$tbl" - check_contains "count(*): 3" - done +run_sql "DROP DATABASE IF EXISTS incr;" +run_sql "DROP DATABASE IF EXISTS lightning_metadata;" +run_lightning_and_check_meta - for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do - if [ "$tbl" = "auto_random" ]; then - run_sql "SELECT id & b'000001111111111111111111111111111111111111111111111111111111111' as inc FROM incr.$tbl" - else - run_sql "SELECT id as inc FROM incr.$tbl" - fi - check_contains 'inc: 1' - check_contains 'inc: 2' - check_contains 'inc: 3' - done +for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do + run_sql "SELECT count(*) from incr.$tbl" + check_contains "count(*): 3" +done - for tbl in pk_auto_inc rowid_uk_inc; do - run_sql "SELECT group_concat(v) from incr.$tbl group by 'all';" - check_contains "group_concat(v): a,b,c" - done +for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do + if [ "$tbl" = "auto_random" ]; then + run_sql "SELECT id & b'000001111111111111111111111111111111111111111111111111111111111' as inc FROM incr.$tbl" + else + run_sql "SELECT id as inc FROM incr.$tbl" + fi + check_contains 'inc: 1' + check_contains 'inc: 2' + check_contains 'inc: 3' +done - run_sql "SELECT sum(pk) from incr.uk_auto_inc;" - check_contains "sum(pk): 6" +for tbl in pk_auto_inc rowid_uk_inc; do + run_sql "SELECT group_concat(v) from incr.$tbl group by 'all';" + check_contains "group_concat(v): a,b,c" +done - # incrementally import all data in data1 - run_lightning --backend $backend -d "tests/$TEST_NAME/data1" +run_sql "SELECT sum(pk) from incr.uk_auto_inc;" +check_contains "sum(pk): 6" - for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do - run_sql "SELECT count(*) from incr.$tbl" - check_contains "count(*): 6" - done +# incrementally import all data in data1 +run_lightning_and_check_meta -d "tests/$TEST_NAME/data1" - for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do - if [ "$tbl" = "auto_random" ]; then - run_sql "SELECT id & b'000001111111111111111111111111111111111111111111111111111111111' as inc FROM incr.$tbl" - else - run_sql "SELECT id as inc FROM incr.$tbl" - fi - check_contains 'inc: 4' - check_contains 'inc: 5' - check_contains 'inc: 6' - done +for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do + run_sql "SELECT count(*) from incr.$tbl" + check_contains "count(*): 6" +done - for tbl in pk_auto_inc rowid_uk_inc; do - run_sql "SELECT group_concat(v) from incr.$tbl group by 'all';" - check_contains "group_concat(v): a,b,c,d,e,f" - done +for tbl in auto_random pk_auto_inc rowid_uk_inc uk_auto_inc; do + if [ "$tbl" = "auto_random" ]; then + run_sql "SELECT id & b'000001111111111111111111111111111111111111111111111111111111111' as inc FROM incr.$tbl" + else + run_sql "SELECT id as inc FROM incr.$tbl" + fi + check_contains 'inc: 4' + check_contains 'inc: 5' + check_contains 'inc: 6' +done - run_sql "SELECT sum(pk) from incr.uk_auto_inc;" - check_contains "sum(pk): 21" +for tbl in pk_auto_inc rowid_uk_inc; do + run_sql "SELECT group_concat(v) from incr.$tbl group by 'all';" + check_contains "group_concat(v): a,b,c,d,e,f" done + +run_sql "SELECT sum(pk) from incr.uk_auto_inc;" +check_contains "sum(pk): 21" diff --git a/br/tests/lightning_local_backend/run.sh b/br/tests/lightning_local_backend/run.sh index 6d0e7e9864145..5843210fea738 100755 --- a/br/tests/lightning_local_backend/run.sh +++ b/br/tests/lightning_local_backend/run.sh @@ -20,12 +20,23 @@ check_cluster_version 4 0 0 'local backend' || exit 0 ENGINE_COUNT=6 -# First, verify that inject with not leader error is fine. -rm -f "$TEST_DIR/lightning-local.log" +# Test check table contains data rm -f "/tmp/tidb_lightning_checkpoint_local_backend_test.pb" +rm -rf $TEST_DIR/lightning.log run_sql 'DROP DATABASE IF EXISTS cpeng;' -export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/backend/local/FailIngestMeta=1*return("notleader")' +run_sql 'CREATE DATABASE cpeng;' +run_sql 'CREATE TABLE cpeng.a (c int);' +run_sql 'CREATE TABLE cpeng.b (c int);' +run_sql "INSERT INTO cpeng.a values (1), (2);" +run_sql "INSERT INTO cpeng.b values (3);" +! run_lightning --backend local --enable-checkpoint=0 +grep -Fq 'table(s) [`cpeng`.`a`, `cpeng`.`b`] are not empty' $TEST_DIR/lightning.log + +# First, verify that inject with not leader error is fine. +export GO_FAILPOINTS='github.com/pingcap/tidb/br/pkg/lightning/backend/local/FailIngestMeta=1*return("notleader")' +rm -f "$TEST_DIR/lightning-local.log" +run_sql 'DROP DATABASE IF EXISTS cpeng;' run_lightning --backend local --enable-checkpoint=1 --log-file "$TEST_DIR/lightning-local.log" --config "tests/$TEST_NAME/config.toml" # Check that everything is correctly imported diff --git a/br/tests/lightning_new_collation/data-gbk/nc.gbk_source-schema.sql b/br/tests/lightning_new_collation/data-gbk/nc.gbk_source-schema.sql new file mode 100644 index 0000000000000..5b09ad3ab06b2 --- /dev/null +++ b/br/tests/lightning_new_collation/data-gbk/nc.gbk_source-schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE `gbk_source` ( + `id` BIGINT PRIMARY KEY COMMENT "×ÔÔö ID", + `v` VARCHAR(32) COMMENT "ÖÐÎÄÆÀÂÛ", + KEY `idx_gbk` (`v`, `id`) +) DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci; diff --git a/br/tests/lightning_new_collation/data-gbk/nc.gbk_source.0.csv b/br/tests/lightning_new_collation/data-gbk/nc.gbk_source.0.csv new file mode 100644 index 0000000000000..cef094e48b900 --- /dev/null +++ b/br/tests/lightning_new_collation/data-gbk/nc.gbk_source.0.csv @@ -0,0 +1,4 @@ +id,v +1,°¡°¡ +2,ŶŶ +3,ÌýÌýÌýÌý diff --git a/br/tests/lightning_new_collation/data/nc-schema-create.sql b/br/tests/lightning_new_collation/data/nc-schema-create.sql new file mode 100644 index 0000000000000..6608189c71304 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc-schema-create.sql @@ -0,0 +1 @@ +CREATE DATABASE nc CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci; diff --git a/br/tests/lightning_new_collation/data/nc.ci-schema.sql b/br/tests/lightning_new_collation/data/nc.ci-schema.sql new file mode 100644 index 0000000000000..1e7958a76409c --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.ci-schema.sql @@ -0,0 +1 @@ +CREATE TABLE ci(i INT PRIMARY KEY, v varchar(32)); diff --git a/br/tests/lightning_new_collation/data/nc.ci.0.csv b/br/tests/lightning_new_collation/data/nc.ci.0.csv new file mode 100644 index 0000000000000..a1b4dcff21e40 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.ci.0.csv @@ -0,0 +1,2 @@ +i,v +1,aA diff --git a/br/tests/lightning_new_collation/data/nc.gbk_test-schema.sql b/br/tests/lightning_new_collation/data/nc.gbk_test-schema.sql new file mode 100644 index 0000000000000..db06f9acec6f0 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.gbk_test-schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE `gbk_test` ( + `id` int(11) DEFAULT NULL, + `v` varchar(32) DEFAULT NULL, + `v2` varchar(32) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL, + KEY `idx_v` (`v`, `id`), + KEY `idx_gbk` (`v2`, `id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; diff --git a/br/tests/lightning_new_collation/data/nc.gbk_test.0.csv b/br/tests/lightning_new_collation/data/nc.gbk_test.0.csv new file mode 100644 index 0000000000000..4c6ef69db5517 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.gbk_test.0.csv @@ -0,0 +1,4 @@ +id,v,v2 +1,å•Šå•Š,å•Šå•Š +2,哦哦,哦哦 +3,å¬å¬å¬å¬,å¬å¬å¬å¬ diff --git a/br/tests/lightning_new_collation/data/nc.t-schema.sql b/br/tests/lightning_new_collation/data/nc.t-schema.sql new file mode 100644 index 0000000000000..455c0567d1d07 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.t-schema.sql @@ -0,0 +1 @@ +CREATE TABLE t(i INT PRIMARY KEY, s varchar(32), j TINYINT, KEY s_j (s, i)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; diff --git a/br/tests/lightning_new_collation/data/nc.t.0.sql b/br/tests/lightning_new_collation/data/nc.t.0.sql new file mode 100644 index 0000000000000..97b01b4ab8e6d --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.t.0.sql @@ -0,0 +1,6 @@ +INSERT INTO t (s, i, j) VALUES + ("this_is_test1", 1, 1), + ("this_is_test2", 2, 2), + ("this_is_test3", 3, 3), + ("this_is_test4", 4, 4), + ("this_is_test5", 5, 5); diff --git a/br/tests/lightning_new_collation/data/nc.t.1.sql b/br/tests/lightning_new_collation/data/nc.t.1.sql new file mode 100644 index 0000000000000..734009f6bd4b6 --- /dev/null +++ b/br/tests/lightning_new_collation/data/nc.t.1.sql @@ -0,0 +1 @@ +INSERT INTO t(s, i, j) VALUES ("another test case", 6, 6); diff --git a/br/tests/lightning_new_collation/gbk.toml b/br/tests/lightning_new_collation/gbk.toml new file mode 100644 index 0000000000000..aef935c7ffb81 --- /dev/null +++ b/br/tests/lightning_new_collation/gbk.toml @@ -0,0 +1,3 @@ +[mydumper] +data-character-set = "GBK" +character-set = "gb18030" diff --git a/br/tests/lightning_new_collation/run.sh b/br/tests/lightning_new_collation/run.sh index d4c49e3c61192..fea83277a3206 100644 --- a/br/tests/lightning_new_collation/run.sh +++ b/br/tests/lightning_new_collation/run.sh @@ -24,27 +24,11 @@ cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # restart cluster with new collation enabled start_services --tidb-cfg $cur/tidb-new-collation.toml -# Populate the mydumper source -DBPATH="$TEST_DIR/nc.mydump" -mkdir -p $DBPATH -echo 'CREATE DATABASE nc;' > "$DBPATH/nc-schema-create.sql" -# create table with collate `utf8_general_ci`, the index key will be different between old/new collation -echo "CREATE TABLE t(i INT PRIMARY KEY, s varchar(32), j TINYINT, KEY s_j (s, i)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;" > "$DBPATH/nc.t-schema.sql" -cat > "$DBPATH/nc.t.0.sql" << _EOF_ -INSERT INTO t (s, i, j) VALUES - ("this_is_test1", 1, 1), - ("this_is_test2", 2, 2), - ("this_is_test3", 3, 3), - ("this_is_test4", 4, 4), - ("this_is_test5", 5, 5); -_EOF_ -echo 'INSERT INTO t(s, i, j) VALUES ("another test case", 6, 6);' > "$DBPATH/nc.t.1.sql" - for BACKEND in local importer tidb; do # Start importing the tables. run_sql 'DROP DATABASE IF EXISTS nc' - run_lightning -d "$DBPATH" --backend $BACKEND 2> /dev/null + run_lightning --backend $BACKEND 2> /dev/null run_sql 'SELECT count(*), sum(i) FROM `nc`.t' check_contains "count(*): 6" @@ -54,6 +38,28 @@ for BACKEND in local importer tidb; do run_sql "SELECT j FROM nc.t WHERE s = 'This_Is_Test4'"; check_contains "j: 4" + run_sql 'SELECT id, v from nc.gbk_test order by v limit 1;' + check_contains "id: 3" + check_contains "v: å¬å¬å¬å¬" + + run_sql "SELECT id, v2 from nc.gbk_test order by v2 limit 1;" + check_contains "id: 1" + check_contains "v2: å•Šå•Š" + + run_sql "SELeCT i, v from nc.ci where v = 'aa';" + check_contains "i: 1" + check_contains "v: aA" + + + run_lightning --backend $BACKEND -d "tests/$TEST_NAME/data-gbk" --config "tests/$TEST_NAME/gbk.toml" + + run_sql 'SELECT count(*) from nc.gbk_source;' + check_contains "count(*): 3" + + run_sql 'SELECT id, v from nc.gbk_source order by v limit 1;' + check_contains "id: 1" + check_contains "v: å•Šå•Š" + done # restart with original config diff --git a/br/tests/lightning_new_collation/tidb-new-collation.toml b/br/tests/lightning_new_collation/tidb-new-collation.toml index f3a4604c78376..c6ec963671953 100644 --- a/br/tests/lightning_new_collation/tidb-new-collation.toml +++ b/br/tests/lightning_new_collation/tidb-new-collation.toml @@ -1,5 +1,4 @@ # config of tidb - new_collations_enabled_on_first_bootstrap = true [security] diff --git a/br/tests/lightning_restore/config.toml b/br/tests/lightning_restore/config.toml index 93fb4f55ae45a..fba59357bc7fd 100644 --- a/br/tests/lightning_restore/config.toml +++ b/br/tests/lightning_restore/config.toml @@ -3,3 +3,7 @@ table-concurrency = 4 [tikv-importer] backend = 'local' + +[checkpoint] +enable = true +keep-after-success = "origin" diff --git a/br/tests/lightning_restore/run.sh b/br/tests/lightning_restore/run.sh index 41542acd45f8b..a168bca4a513e 100755 --- a/br/tests/lightning_restore/run.sh +++ b/br/tests/lightning_restore/run.sh @@ -41,3 +41,28 @@ for i in $(seq "$TABLE_COUNT"); do run_sql "SELECT sum(i) FROM restore_tsr.tbl$i;" check_contains 'sum(i): 1' done + +# Reset and test setting external storage from outside +DBPATH2="$TEST_DIR/restore.ext_storage" +mkdir -p $DBPATH2 +echo 'CREATE DATABASE restore_tsr;' > "$DBPATH2/restore_tsr-schema-create.sql" +for i in $(seq "$TABLE_COUNT"); do + echo "CREATE TABLE tbl$i(i TINYINT);" > "$DBPATH2/restore_tsr.tbl$i-schema.sql" + echo "INSERT INTO tbl$i VALUES (1);" > "$DBPATH2/restore_tsr.tbl$i.sql" +done + +export GO_FAILPOINTS="github.com/pingcap/tidb/br/pkg/lightning/setExtStorage=return(\"$DBPATH2\")" +export GO_FAILPOINTS="$GO_FAILPOINTS;github.com/pingcap/tidb/br/pkg/lightning/setCheckpointName=return(\"test_checkpoint.pb\")" + +run_sql 'DROP DATABASE IF EXISTS restore_tsr' +run_lightning +echo "Import finished" + +# Verify all data are imported +for i in $(seq "$TABLE_COUNT"); do + run_sql "SELECT sum(i) FROM restore_tsr.tbl$i;" + check_contains 'sum(i): 1' +done + +# Verify checkpoint file is also created in external storage +[ -f "$DBPATH2/test_checkpoint.pb" ] diff --git a/br/tests/lightning_s3/config_manual_files.toml b/br/tests/lightning_s3/config_manual_files.toml new file mode 100644 index 0000000000000..2d5d2aa128983 --- /dev/null +++ b/br/tests/lightning_s3/config_manual_files.toml @@ -0,0 +1,20 @@ +[mydumper] +default-file-rules = true + +[[mydumper.files]] +pattern = "data-sql/" +schema = "s3_test" +table = "tbl" +type = "sql" + +[[mydumper.files]] +pattern = "data-csv/" +schema = "s3_test" +table = "tbl" +type = "csv" + +[[mydumper.files]] +pattern = "data-parquet/" +schema = "s3_test" +table = "tbl" +type = "parquet" diff --git a/br/tests/lightning_s3/config_s3_checkpoint.toml b/br/tests/lightning_s3/config_s3_checkpoint.toml new file mode 100644 index 0000000000000..f8402f2b7e424 --- /dev/null +++ b/br/tests/lightning_s3/config_s3_checkpoint.toml @@ -0,0 +1,12 @@ +[lightning] +index-concurrency = 1 +table-concurrency = 1 + +[checkpoint] +enable = true +driver = "file" +dsn = "s3://test-bucket/prix/cp_error_destroy.pb/?endpoint=http%3A//127.0.0.1%3A9900&access_key=s3accesskey&secret_access_key=s3secretkey&force_path_style=true" +keep-after-success = "origin" + +[mydumper] +read-block-size = 1 diff --git a/br/tests/lightning_s3/run.sh b/br/tests/lightning_s3/run.sh index 5b2973784fd7e..1d4b80bff3d53 100755 --- a/br/tests/lightning_s3/run.sh +++ b/br/tests/lightning_s3/run.sh @@ -22,6 +22,11 @@ check_cluster_version 4 0 0 'local backend' || exit 0 set -euE +if [[ -z "${TEST_DIR}" ]]; then + echo "TEST_DIR is not set" >&2 + exit 1 +fi + # Populate the mydumper source DBPATH="$TEST_DIR/s3.mydump" @@ -30,12 +35,12 @@ export MINIO_ACCESS_KEY=s3accesskey export MINIO_SECRET_KEY=s3secretkey export MINIO_BROWSER=off export S3_ENDPOINT=127.0.0.1:9900 -rm -rf "$TEST_DIR/$DB" +rm -rf "${TEST_DIR:?}/${DB:?}" mkdir -p "$TEST_DIR/$DB" bin/minio server --address $S3_ENDPOINT "$DBPATH" & i=0 while ! curl -o /dev/null -v -s "http://$S3_ENDPOINT/"; do - i=$(($i+1)) + i=$((i+1)) if [ $i -gt 30 ]; then echo 'Failed to start minio' exit 1 @@ -45,7 +50,7 @@ done BUCKET=test-bucket DATA_PATH=$DBPATH/$BUCKET -mkdir -p $DATA_PATH +mkdir -p "$DATA_PATH" echo 'CREATE DATABASE s3_test;' > "$DATA_PATH/$DB-schema-create.sql" echo "CREATE TABLE t(i INT, s varchar(32));" > "$DATA_PATH/$DB.$TABLE-schema.sql" echo 'INSERT INTO tbl (i, s) VALUES (1, "1"),(2, "test2"), (3, "qqqtest");' > "$DATA_PATH/$DB.$TABLE.sql" @@ -57,27 +62,165 @@ i,s 104,"" _EOF_ -# Fill in the database -# Start importing the tables. -run_sql "DROP DATABASE IF EXISTS $DB;" -run_sql "DROP TABLE IF EXISTS $DB.$TABLE;" +function cleanup_db_and_table() { + if ! run_sql "DROP DATABASE IF EXISTS $DB;"; then + echo "run SQL for drop database error" >&2 + return 1 + fi + if ! run_sql "DROP TABLE IF EXISTS $DB.$TABLE;"; then + echo "run SQL for drop table error" >&2 + return 1 + fi +} # test not exist path -rm -f $TEST_DIR/lightning.log -SOURCE_DIR="s3://$BUCKET/not-exist-path?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" -! run_lightning -d $SOURCE_DIR --backend local 2> /dev/null -grep -Eq "data-source-dir .* doesn't exist or contains no files" $TEST_DIR/lightning.log +function test_import_non_existing_path() { + rm -f "$TEST_DIR/lightning.log" + local SOURCE_DIR="s3://$BUCKET/not-exist-path?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" + if run_lightning -d "$SOURCE_DIR" --backend local 2> /dev/null ; then + echo "this importing should fail" >&2 + return 2 + fi + if ! grep -Eq "data-source-dir .* doesn't exist or contains no files" "$TEST_DIR/lightning.log" ; then + echo "the message is not found in the log" >&2 + return 2 + fi + return 0 +} # test empty dir -rm -f $TEST_DIR/lightning.log -emptyPath=empty-bucket/empty-path -mkdir -p $DBPATH/$emptyPath -SOURCE_DIR="s3://$emptyPath/not-exist-path?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" -! run_lightning -d $SOURCE_DIR --backend local 2> /dev/null -grep -Eq "data-source-dir .* doesn't exist or contains no files" $TEST_DIR/lightning.log - -SOURCE_DIR="s3://$BUCKET/?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" -run_lightning -d $SOURCE_DIR --backend local 2> /dev/null -run_sql "SELECT count(*), sum(i) FROM \`$DB\`.$TABLE" -check_contains "count(*): 7" -check_contains "sum(i): 413" +function test_import_empty_dir() { + rm -f "$TEST_DIR/lightning.log" + local emptyPath=empty-bucket/empty-path + mkdir -p "$DBPATH/$emptyPath" + local SOURCE_DIR="s3://$emptyPath/not-exist-path?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" + if run_lightning -d "$SOURCE_DIR" --backend local 2> /dev/null; then + echo "this importing should fail" >&2 + return 2 + fi + if ! grep -Eq "data-source-dir .* doesn't exist or contains no files" "$TEST_DIR/lightning.log"; then + echo "the message is not found in the log" >&2 + return 2 + fi + return 0 +} + +function test_normal_import() { + rm -f "$TEST_DIR/lightning.log" + if ! cleanup_db_and_table; then + echo "cleanup DB and table before running the test failed" >&2 + return 1 + fi + local SOURCE_DIR="s3://$BUCKET/?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" + if ! run_lightning -d "$SOURCE_DIR" --backend local 2> /dev/null; then + echo "run lightning failed" >&2 + return 2 + fi + if ! run_sql "SELECT count(*), sum(i) FROM \`$DB\`.$TABLE"; then + echo "run SQL on target DB failed" >&2 + return 2 + fi + if ! check_contains "count(*): 7"; then + echo "the record count is not right" >&2 + return 2 + fi + if ! check_contains "sum(i): 413"; then + echo "the sum of record is not right" >&2 + return 2 + fi + return 0 +} + +function test_import_with_checkpoint() { + rm -f "$TEST_DIR/lightning.log" + if ! cleanup_db_and_table; then + echo "cleanup DB and table before running the test failed" >&2 + return 1 + fi + local SOURCE_DIR="s3://$BUCKET/?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" + if ! run_lightning -d "$SOURCE_DIR" --backend local --config "tests/$TEST_NAME/config_s3_checkpoint.toml" 2> /dev/null; then + echo "run lightning failed" >&2 + return 2 + fi + if ! run_sql "SELECT count(*), sum(i) FROM \`$DB\`.$TABLE"; then + echo "run SQL on target DB failed" >&2 + return 2 + fi + if ! check_contains "count(*): 7"; then + echo "the record count is not right" >&2 + return 2 + fi + if ! check_contains "sum(i): 413"; then + echo "the sum of record is not right" >&2 + return 2 + fi +} + +# test manually organized dir with some empty sub-dirs +function test_import_using_manual_path_config() { + rm -f "$TEST_DIR/lightning.log" + if ! cleanup_db_and_table; then + echo "cleanup DB and table before running the test failed" >&2 + return 1 + fi + local bucket_02="test-bucket-02" + local sub_path_02="to-be-imported" + local base_path_02="${DBPATH}/${bucket_02}/${sub_path_02}" + rm -rf "${base_path_02}" + mkdir -p "${base_path_02}" + touch "${base_path_02}/$DB-schema-create.sql" # empty schema file + cp "$DATA_PATH/$DB.$TABLE-schema.sql" "${base_path_02}/" + local sql_data_path_02="${base_path_02}/data-sql" + local csv_data_path_02="${base_path_02}/data-csv" + local parquet_data_path_02="${base_path_02}/data-parquet" + mkdir -p "${sql_data_path_02}/empty-dir" # try to add an empty path into it + cp "$DATA_PATH/$DB.$TABLE.sql" "${sql_data_path_02}/" + touch "${sql_data_path_02}/dummy.sql" # empty file + mkdir -p "${csv_data_path_02}/empty-dir" # try to add an empty path into it + cp "$DATA_PATH/$DB.$TABLE.0.csv" "${csv_data_path_02}/" + touch "${csv_data_path_02}/dummy.csv" # empty file + mkdir -p "${parquet_data_path_02}/empty-dir" # try to add an empty path into it + # no touch empty file for parquet files + + local SOURCE_DIR="s3://${bucket_02}/${sub_path_02}?endpoint=http%3A//127.0.0.1%3A9900&access_key=$MINIO_ACCESS_KEY&secret_access_key=$MINIO_SECRET_KEY&force_path_style=true" + if ! run_lightning -d "${SOURCE_DIR}" --backend local --config "tests/$TEST_NAME/config_manual_files.toml" 2> /dev/null; then + echo "run lightning failed" >&2 + return 2 + fi + if ! run_sql "SELECT count(*), sum(i) FROM \`$DB\`.$TABLE"; then + echo "run SQL on target DB failed" >&2 + return 2 + fi + if ! check_contains "count(*): 7"; then + echo "the record count is not right" >&2 + return 2 + fi + if ! check_contains "sum(i): 413"; then + echo "the sum of record is not right" >&2 + return 2 + fi + return 0 +} + +final_ret_code=0 +if ! test_import_non_existing_path; then + final_ret_code=2 +fi + +if ! test_import_empty_dir; then + final_ret_code=2 +fi + +if ! test_normal_import; then + final_ret_code=2 +fi + +if ! test_import_with_checkpoint; then + final_ret_code=2 +fi + +if ! test_import_using_manual_path_config; then + final_ret_code=2 +fi + +exit "${final_ret_code}" diff --git a/br/tests/lightning_tidb_rowid/data/rowid.pre_rebase-schema.sql b/br/tests/lightning_tidb_rowid/data/rowid.pre_rebase-schema.sql index 887540be58110..1738b64457de6 100644 --- a/br/tests/lightning_tidb_rowid/data/rowid.pre_rebase-schema.sql +++ b/br/tests/lightning_tidb_rowid/data/rowid.pre_rebase-schema.sql @@ -1 +1 @@ -create table pre_rebase (pk varchar(6) primary key) auto_increment=70000; +create table pre_rebase (pk varchar(6) primary key /*T![clustered_index] NONCLUSTERED */) auto_increment=70000; diff --git a/br/tests/lightning_tidb_rowid/run.sh b/br/tests/lightning_tidb_rowid/run.sh index e877f420cf43f..ae762c514d93c 100755 --- a/br/tests/lightning_tidb_rowid/run.sh +++ b/br/tests/lightning_tidb_rowid/run.sh @@ -58,8 +58,13 @@ for BACKEND in local importer tidb; do run_sql 'SELECT count(*), min(_tidb_rowid), max(_tidb_rowid) FROM rowid.pre_rebase' check_contains 'count(*): 1' - check_contains 'min(_tidb_rowid): 70000' - check_contains 'max(_tidb_rowid): 70000' + if [ "$BACKEND" == 'tidb' ]; then + check_contains 'min(_tidb_rowid): 70000' + check_contains 'max(_tidb_rowid): 70000' + else + check_contains 'min(_tidb_rowid): 1' + check_contains 'max(_tidb_rowid): 1' + fi run_sql 'INSERT INTO rowid.pre_rebase VALUES ("?")' run_sql 'SELECT _tidb_rowid > 70000 FROM rowid.pre_rebase WHERE pk = "?"' check_contains '_tidb_rowid > 70000: 1' diff --git a/br/web/package-lock.json b/br/web/package-lock.json index f3ee7ce9f50c3..720dd03b03aba 100644 --- a/br/web/package-lock.json +++ b/br/web/package-lock.json @@ -1699,9 +1699,9 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "node_modules/neo-async": { @@ -3998,9 +3998,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "neo-async": { diff --git a/cmd/ddltest/column_serial_test.go b/cmd/ddltest/column_test.go similarity index 100% rename from cmd/ddltest/column_serial_test.go rename to cmd/ddltest/column_test.go diff --git a/cmd/ddltest/ddl_serial_test.go b/cmd/ddltest/ddl_test.go similarity index 100% rename from cmd/ddltest/ddl_serial_test.go rename to cmd/ddltest/ddl_test.go diff --git a/cmd/ddltest/index_serial_test.go b/cmd/ddltest/index_test.go similarity index 52% rename from cmd/ddltest/index_serial_test.go rename to cmd/ddltest/index_test.go index 28cba8e03ee5f..705e3a13dec03 100644 --- a/cmd/ddltest/index_serial_test.go +++ b/cmd/ddltest/index_test.go @@ -16,20 +16,14 @@ package ddltest import ( "fmt" - "io" "math" "sync" "sync/atomic" "testing" "time" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/store/gcworker" "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" goctx "golang.org/x/net/context" ) @@ -44,90 +38,12 @@ func getIndex(t table.Table, name string) table.Index { return nil } -func (s *ddlSuite) checkAddIndex(t *testing.T, indexInfo *model.IndexInfo) { - ctx := s.ctx - err := ctx.NewTxn(goctx.Background()) - require.NoError(t, err) - tbl := s.getTable(t, "test_index") - - // read handles form table - handles := kv.NewHandleMap() - err = tables.IterRecords(tbl, ctx, tbl.Cols(), - func(h kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - handles.Set(h, struct{}{}) - return true, nil - }) - require.NoError(t, err) - - // read handles from index - idx := tables.NewIndex(tbl.Meta().ID, tbl.Meta(), indexInfo) - err = ctx.NewTxn(goctx.Background()) - require.NoError(t, err) - txn, err := ctx.Txn(false) - require.NoError(t, err) - defer func() { - err = txn.Rollback() - require.NoError(t, err) - }() - - it, err := idx.SeekFirst(txn) - require.NoError(t, err) - defer it.Close() - - for { - _, h, err := it.Next() - if terror.ErrorEqual(err, io.EOF) { - break - } - - require.NoError(t, err) - _, ok := handles.Get(h) - require.True(t, ok) - handles.Delete(h) - } - - require.Equal(t, 0, handles.Len()) -} - -func (s *ddlSuite) checkDropIndex(t *testing.T, indexInfo *model.IndexInfo) { +func (s *ddlSuite) checkDropIndex(t *testing.T, tableName string) { gcWorker, err := gcworker.NewMockGCWorker(s.store) require.NoError(t, err) err = gcWorker.DeleteRanges(goctx.Background(), uint64(math.MaxInt32)) require.NoError(t, err) - - ctx := s.ctx - err = ctx.NewTxn(goctx.Background()) - require.NoError(t, err) - tbl := s.getTable(t, "test_index") - - // read handles from index - idx := tables.NewIndex(tbl.Meta().ID, tbl.Meta(), indexInfo) - err = ctx.NewTxn(goctx.Background()) - require.NoError(t, err) - txn, err := ctx.Txn(false) - require.NoError(t, err) - defer func() { - err := txn.Rollback() - require.NoError(t, err) - }() - - it, err := idx.SeekFirst(txn) - require.NoError(t, err) - defer it.Close() - - handles := kv.NewHandleMap() - for { - _, h, err := it.Next() - if terror.ErrorEqual(err, io.EOF) { - break - } - - require.NoError(t, err) - handles.Set(h, struct{}{}) - } - - // TODO: Uncomment this after apply pool is finished - // c.Assert(handles.Len(), Equals, 0) + s.mustExec(fmt.Sprintf("admin check table %s", tableName)) } // TestIndex operations on table test_index (c int, c1 bigint, c2 double, c3 varchar(256), primary key(c)). @@ -167,39 +83,35 @@ func TestIndex(t *testing.T) { } insertID := int64(*dataNum) - var oldIndex table.Index for _, col := range tbl { - t.Run(col.Query, func(t *testing.T) { - done := s.runDDL(col.Query) - - ticker := time.NewTicker(time.Duration(*lease) * time.Second / 2) - defer ticker.Stop() - LOOP: - for { - select { - case err := <-done: - require.NoError(t, err) - break LOOP - case <-ticker.C: - // add count new data - // delete count old data randomly - // update count old data randomly - count := 10 - s.execIndexOperations(t, workerNum, count, &insertID) - } + done := s.runDDL(col.Query) + + ticker := time.NewTicker(time.Duration(*lease) * time.Second / 2) + defer ticker.Stop() + LOOP: + for { + select { + case err := <-done: + require.NoError(t, err) + break LOOP + case <-ticker.C: + // add count new data + // delete count old data randomly + // update count old data randomly + count := 10 + s.execIndexOperations(t, workerNum, count, &insertID) } + } - tbl := s.getTable(t, "test_index") - index := getIndex(tbl, col.IndexName) - if col.Add { - require.NotNil(t, index) - oldIndex = index - s.checkAddIndex(t, index.Meta()) - } else { - require.Nil(t, index) - s.checkDropIndex(t, oldIndex.Meta()) - } - }) + tbl := s.getTable(t, "test_index") + index := getIndex(tbl, col.IndexName) + if col.Add { + require.NotNil(t, index) + s.mustExec("admin check table test_index") + } else { + require.Nil(t, index) + s.checkDropIndex(t, "test_index") + } } } diff --git a/cmd/ddltest/main_test.go b/cmd/ddltest/main_test.go index 890a52a7f4ab8..9a23dc93c9a52 100644 --- a/cmd/ddltest/main_test.go +++ b/cmd/ddltest/main_test.go @@ -26,14 +26,15 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() err := logutil.InitLogger(&logutil.LogConfig{Config: zaplog.Config{Level: *logLevel}}) if err != nil { fmt.Fprint(os.Stderr, err.Error()) os.Exit(1) } opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), goleak.IgnoreTopFunction("internal/poll.runtime_pollWait"), goleak.IgnoreTopFunction("net/http.(*persistConn).writeLoop"), diff --git a/cmd/ddltest/random.go b/cmd/ddltest/random_test.go similarity index 100% rename from cmd/ddltest/random.go rename to cmd/ddltest/random_test.go diff --git a/cmd/explaintest/disable_new_collation.toml b/cmd/explaintest/disable_new_collation.toml new file mode 100644 index 0000000000000..c66f92d0b30c8 --- /dev/null +++ b/cmd/explaintest/disable_new_collation.toml @@ -0,0 +1,27 @@ +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +lease = "0" +mem-quota-query = 34359738368 +host = "127.0.0.1" +new_collations_enabled_on_first_bootstrap = false + +[status] +status-host = "127.0.0.1" + +[performance] +stats-lease = "0" + +[experimental] +allow-expression-index = true diff --git a/cmd/explaintest/main.go b/cmd/explaintest/main.go index 9276b67a6f893..71c5ef17ab755 100644 --- a/cmd/explaintest/main.go +++ b/cmd/explaintest/main.go @@ -30,7 +30,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/log" "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/util/logutil" @@ -41,11 +40,12 @@ import ( const dbName = "test" var ( - logLevel string - port uint - statusPort uint - record bool - create bool + logLevel string + port uint + statusPort uint + record bool + create bool + collationDisable bool ) func init() { @@ -54,18 +54,7 @@ func init() { flag.UintVar(&statusPort, "status", 10080, "tidb server status port [default: 10080]") flag.BoolVar(&record, "record", false, "record the test output in the result file") flag.BoolVar(&create, "create", false, "create and import data into table, and save json file of stats") - - c := &charset.Charset{ - Name: "gbk", - DefaultCollation: "gbk_bin", - Collations: map[string]*charset.Collation{}, - } - charset.AddCharset(c) - for _, coll := range charset.GetCollations() { - if strings.EqualFold(coll.CharsetName, c.Name) { - charset.AddCollation(coll) - } - } + flag.BoolVar(&collationDisable, "collation-disable", false, "run collation related-test with new-collation disabled") } var mdb *sql.DB @@ -238,6 +227,14 @@ func (t *tester) parserErrorHandle(query query, err error) error { err = nil break } + if strings.Contains(err.Error(), expectedErr) { + if t.enableQueryLog { + t.buf.WriteString(fmt.Sprintf("%s\n", query.Query)) + } + t.buf.WriteString(fmt.Sprintf("%s\n", err)) + err = nil + break + } } if err != nil { @@ -364,12 +361,14 @@ func (t *tester) execute(query query) error { } if err != nil && len(t.expectedErrs) > 0 { - // TODO: check whether this err is expected. - // but now we think it is. - - // output expected err - t.buf.WriteString(fmt.Sprintf("%s\n", err)) - err = nil + for _, expectErr := range t.expectedErrs { + if strings.Contains(err.Error(), expectErr) { + // output expected err + t.buf.WriteString(fmt.Sprintf("%s\n", err)) + err = nil + break + } + } } // clear expected errors after we execute the first query t.expectedErrs = nil @@ -578,7 +577,15 @@ func (t *tester) testFileName() string { func (t *tester) resultFileName() string { // test and result must be in current ./r, the same as MySQL - return fmt.Sprintf("./r/%s.result", t.name) + name := t.name + if strings.HasPrefix(name, "collation") { + if collationDisable { + name = name + "_disabled" + } else { + name = name + "_enabled" + } + } + return fmt.Sprintf("./r/%s.result", name) } func (t *tester) checkLastResult() error { @@ -619,6 +626,9 @@ func loadAllTests() ([]string, error) { // the test file must have a suffix .test name := f.Name() if strings.HasSuffix(name, ".test") { + if collationDisable && !strings.HasPrefix(name, "collation") { + continue + } name = strings.TrimSuffix(name, ".test") if create && !strings.HasSuffix(name, "_stats") { @@ -753,7 +763,7 @@ func main() { log.Info("Explain test passed") } -var queryStmtTable = []string{"explain", "select", "show", "execute", "describe", "desc", "admin", "with"} +var queryStmtTable = []string{"explain", "select", "show", "execute", "describe", "desc", "admin", "with", "trace"} func trimSQL(sql string) string { // Trim space. diff --git a/cmd/explaintest/r/agg_predicate_pushdown.result b/cmd/explaintest/r/agg_predicate_pushdown.result new file mode 100644 index 0000000000000..9caca7aa5bb22 --- /dev/null +++ b/cmd/explaintest/r/agg_predicate_pushdown.result @@ -0,0 +1,54 @@ +drop database if exists agg_predicate_pushdown; +create database agg_predicate_pushdown; +create table t(a int, b int, c int); +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1) and (a > 2) and 1 and (b > 2) and (avg(c) > 3); +id estRows task access object operator info +Projection 711.11 root test.t.a, test.t.b, Column#5 +└─Selection 711.11 root gt(Column#5, 3) + └─HashAgg 888.89 root group by:Column#16, Column#17, Column#18, funcs:avg(Column#13)->Column#5, funcs:firstrow(Column#14)->test.t.a, funcs:firstrow(Column#15)->test.t.b + └─Projection 1111.11 root cast(test.t.c, decimal(15,4) BINARY)->Column#13, test.t.a, test.t.b, test.t.a, test.t.b, test.t.c + └─TableReader 1111.11 root data:Selection + └─Selection 1111.11 cop[tikv] gt(test.t.a, 1), gt(test.t.a, 2), gt(test.t.b, 2) + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 or b > 2) and (a > 2 or b < 1) and 1 and (b > 2) and (avg(c) > 3); +id estRows task access object operator info +Projection 657.65 root test.t.a, test.t.b, Column#5 +└─Selection 657.65 root gt(Column#5, 3) + └─HashAgg 822.06 root group by:Column#16, Column#17, Column#18, funcs:avg(Column#13)->Column#5, funcs:firstrow(Column#14)->test.t.a, funcs:firstrow(Column#15)->test.t.b + └─Projection 1027.57 root cast(test.t.c, decimal(15,4) BINARY)->Column#13, test.t.a, test.t.b, test.t.a, test.t.b, test.t.c + └─TableReader 1027.57 root data:Selection + └─Selection 1027.57 cop[tikv] gt(test.t.b, 2), or(gt(test.t.a, 1), gt(test.t.b, 2)), or(gt(test.t.a, 2), lt(test.t.b, 1)) + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 and b > 2) or (a > 2 and b < 1) or (b > 2 and avg(c) > 3); +id estRows task access object operator info +Projection 3027.54 root test.t.a, test.t.b, Column#5 +└─Selection 3027.54 root or(and(gt(test.t.a, 1), gt(test.t.b, 2)), or(and(gt(test.t.a, 2), lt(test.t.b, 1)), and(gt(test.t.b, 2), gt(Column#5, 3)))) + └─HashAgg 3784.43 root group by:Column#16, Column#17, Column#18, funcs:avg(Column#13)->Column#5, funcs:firstrow(Column#14)->test.t.a, funcs:firstrow(Column#15)->test.t.b + └─Projection 4730.53 root cast(test.t.c, decimal(15,4) BINARY)->Column#13, test.t.a, test.t.b, test.t.a, test.t.b, test.t.c + └─TableReader 4730.53 root data:Selection + └─Selection 4730.53 cop[tikv] or(and(gt(test.t.a, 1), gt(test.t.b, 2)), or(and(gt(test.t.a, 2), lt(test.t.b, 1)), gt(test.t.b, 2))) + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 or avg(c) > 1) and (a < 3); +id estRows task access object operator info +Projection 2126.93 root test.t.a, test.t.b, Column#5 +└─Selection 2126.93 root or(gt(test.t.a, 1), gt(Column#5, 1)) + └─HashAgg 2658.67 root group by:Column#16, Column#17, Column#18, funcs:avg(Column#13)->Column#5, funcs:firstrow(Column#14)->test.t.a, funcs:firstrow(Column#15)->test.t.b + └─Projection 3323.33 root cast(test.t.c, decimal(15,4) BINARY)->Column#13, test.t.a, test.t.b, test.t.a, test.t.b, test.t.c + └─TableReader 3323.33 root data:Selection + └─Selection 3323.33 cop[tikv] lt(test.t.a, 3) + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 and avg(c) > 1) or (a < 3); +id estRows task access object operator info +Projection 6393.60 root test.t.a, test.t.b, Column#5 +└─Selection 6393.60 root or(and(gt(test.t.a, 1), gt(Column#5, 1)), lt(test.t.a, 3)) + └─HashAgg 7992.00 root group by:Column#16, Column#17, Column#18, funcs:avg(Column#13)->Column#5, funcs:firstrow(Column#14)->test.t.a, funcs:firstrow(Column#15)->test.t.b + └─Projection 9990.00 root cast(test.t.c, decimal(15,4) BINARY)->Column#13, test.t.a, test.t.b, test.t.a, test.t.b, test.t.c + └─TableReader 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] or(gt(test.t.a, 1), lt(test.t.a, 3)) + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +use test; diff --git a/cmd/explaintest/r/collation.result b/cmd/explaintest/r/collation.result deleted file mode 100644 index 193915a15d6c9..0000000000000 --- a/cmd/explaintest/r/collation.result +++ /dev/null @@ -1,15 +0,0 @@ -drop table if exists t; -create table t(a char(10) collate utf8mb4_unicode_ci, b char(10) collate utf8mb4_general_ci); -insert into t values ('å•Š', 'æ’’æ—¦'); -select coercibility(concat(a, b)) from t; -coercibility(concat(a, b)) -1 -select coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) from t; -coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) -0 -select coercibility(convert('a' using utf8mb4)); -coercibility(convert('a' using utf8mb4)) -2 -select coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci); -coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci) -0 diff --git a/cmd/explaintest/r/collation_agg_func_disabled.result b/cmd/explaintest/r/collation_agg_func_disabled.result new file mode 100644 index 0000000000000..75ba58783482b --- /dev/null +++ b/cmd/explaintest/r/collation_agg_func_disabled.result @@ -0,0 +1,302 @@ +create database collation_agg_func; +use collation_agg_func; +create table t(id int, value varchar(20) charset utf8mb4 collate utf8mb4_general_ci, value1 varchar(20) charset utf8mb4 collate utf8mb4_bin); +insert into t values (1, 'abc', 'abc '),(4, 'Abc', 'abc'),(3,'def', 'def '), (5, 'abc', 'ABC'); +desc format='brief' select group_concat(value order by 1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(collation_agg_func.t.value order by collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value order by 1) from t; +group_concat(value order by 1) +Abc,abc,abc,def +desc format='brief' select group_concat(value) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value) from t; +group_concat(value) +abc,Abc,def,abc +desc format='brief' select group_concat(value collate utf8mb4_bin) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(Column#6 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value collate utf8mb4_bin) from t; +group_concat(value collate utf8mb4_bin) +abc,Abc,def,abc +desc format='brief' select group_concat(distinct value order by 1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct collation_agg_func.t.value order by collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value order by 1)) from t; +upper(group_concat(distinct value order by 1)) +ABC,ABC,DEF +desc format='brief' select group_concat(distinct value collate utf8mb4_bin order by 1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct Column#6 order by Column#7 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value collate utf8mb4_bin order by 1)) from t; +upper(group_concat(distinct value collate utf8mb4_bin order by 1)) +ABC,ABC,DEF +desc format='brief' select group_concat(distinct value) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value)) from t; +upper(group_concat(distinct value)) +ABC,ABC,DEF +desc format='brief' select group_concat(distinct value collate utf8mb4_bin) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct Column#6 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value collate utf8mb4_bin)) from t; +upper(group_concat(distinct value collate utf8mb4_bin)) +ABC,ABC,DEF +desc format='brief' select count(distinct value) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct collation_agg_func.t.value)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value) from t; +count(distinct value) +3 +desc format='brief' select count(distinct value collate utf8mb4_bin) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct Column#6)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value collate utf8mb4_bin) from t; +count(distinct value collate utf8mb4_bin) +3 +desc format='brief' select count(distinct value, value1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct collation_agg_func.t.value, collation_agg_func.t.value1)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value, value1) from t; +count(distinct value, value1) +4 +desc format='brief' select count(distinct value collate utf8mb4_bin, value1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct Column#6, Column#7)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, collation_agg_func.t.value1 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value collate utf8mb4_bin, value1) from t; +count(distinct value collate utf8mb4_bin, value1) +4 +desc format='brief' select approx_count_distinct(value) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(collation_agg_func.t.value)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value) from t; +approx_count_distinct(value) +3 +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(Column#6)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value collate utf8mb4_bin) from t; +approx_count_distinct(value collate utf8mb4_bin) +3 +desc format='brief' select approx_count_distinct(value, value1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(collation_agg_func.t.value, collation_agg_func.t.value1)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value, value1) from t; +approx_count_distinct(value, value1) +4 +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin, value1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(Column#6, Column#7)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, collation_agg_func.t.value1 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value collate utf8mb4_bin, value1) from t; +approx_count_distinct(value collate utf8mb4_bin, value1) +4 +create table tt(a char(10), b enum('a', 'B', 'c'), c set('a', 'B', 'c'), d json) collate utf8mb4_general_ci; +insert into tt values ("a", "a", "a", JSON_OBJECT("a", "a")); +insert into tt values ("A", "A", "A", JSON_OBJECT("A", "A")); +Error 1265: Data truncated for column 'b' at row 1 +insert into tt values ("b", "b", "b", JSON_OBJECT("b", "b")); +Error 1265: Data truncated for column 'b' at row 1 +insert into tt values ("B", "B", "B", JSON_OBJECT("B", "B")); +insert into tt values ("c", "c", "c", JSON_OBJECT("c", "c")); +insert into tt values ("C", "C", "C", JSON_OBJECT("C", "C")); +Error 1265: Data truncated for column 'b' at row 1 +split table tt by (0), (1), (2), (3), (4), (5); +desc format='brief' select min(a) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(collation_agg_func.tt.a)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.a, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.a, offset:0, count:1 + └─Selection 9990.00 cop[tikv] not(isnull(collation_agg_func.tt.a)) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(a) from tt; +min(a) +B +desc format='brief' select min(a collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.a + └─TopN 1.00 root Column#7, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.a, cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin), offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(a collate utf8mb4_bin) from tt; +min(a collate utf8mb4_bin) +B +desc format='brief' select max(a) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(collation_agg_func.tt.a)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.a:desc, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.a:desc, offset:0, count:1 + └─Selection 9990.00 cop[tikv] not(isnull(collation_agg_func.tt.a)) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(a) from tt; +max(a) +c +desc format='brief' select max(a collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.a + └─TopN 1.00 root Column#7:desc, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.a, cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin):desc, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(a collate utf8mb4_bin) from tt; +max(a collate utf8mb4_bin) +c +desc format='brief' select min(b) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:min(collation_agg_func.tt.b)->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(b) from tt; +min(b) +B +desc format='brief' select min(b collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:min(cast(collation_agg_func.tt.b, enum('a','B','c')))->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select max(b) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:max(collation_agg_func.tt.b)->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(b) from tt; +max(b) +c +desc format='brief' select max(b collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:max(cast(collation_agg_func.tt.b, enum('a','B','c')))->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select min(c) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:min(collation_agg_func.tt.c)->Column#6 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(c) from tt; +min(c) +B +desc format='brief' select min(c collate utf8mb4_bin) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:min(Column#7)->Column#6 +└─Projection 10000.00 root cast(collation_agg_func.tt.c, set('a','B','c'))->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select max(c) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:max(collation_agg_func.tt.c)->Column#6 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(c) from tt; +max(c) +c +desc format='brief' select max(c collate utf8mb4_bin) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:max(Column#7)->Column#6 +└─Projection 10000.00 root cast(collation_agg_func.tt.c, set('a','B','c'))->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select min(d) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(collation_agg_func.tt.d)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.d, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.d, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.d, var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(d) from tt; +min(d) +{"B": "B"} +desc format='brief' select min(d collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.d, json BINARY)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.d + └─TopN 1.00 root Column#7, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.d, cast(collation_agg_func.tt.d, json BINARY)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.d, json BINARY), offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(cast(collation_agg_func.tt.d, json BINARY), var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(d collate utf8mb4_bin) from tt; +min(d collate utf8mb4_bin) +{"B": "B"} +desc format='brief' select max(d) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(collation_agg_func.tt.d)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.d:desc, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.d:desc, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.d, var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(d) from tt; +max(d) +{"c": "c"} +desc format='brief' select max(d collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.d, json BINARY)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.d + └─TopN 1.00 root Column#7:desc, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.d, cast(collation_agg_func.tt.d, json BINARY)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.d, json BINARY):desc, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(cast(collation_agg_func.tt.d, json BINARY), var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(d collate utf8mb4_bin) from tt; +max(d collate utf8mb4_bin) +{"c": "c"} +drop database collation_agg_func; +use test diff --git a/cmd/explaintest/r/collation_agg_func_enabled.result b/cmd/explaintest/r/collation_agg_func_enabled.result new file mode 100644 index 0000000000000..ebc4f51ad36ce --- /dev/null +++ b/cmd/explaintest/r/collation_agg_func_enabled.result @@ -0,0 +1,279 @@ +create database collation_agg_func; +use collation_agg_func; +create table t(id int, value varchar(20) charset utf8mb4 collate utf8mb4_general_ci, value1 varchar(20) charset utf8mb4 collate utf8mb4_bin); +insert into t values (1, 'abc', 'abc '),(4, 'Abc', 'abc'),(3,'def', 'def '), (5, 'abc', 'ABC'); +desc format='brief' select group_concat(value order by 1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(collation_agg_func.t.value order by collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value order by 1) from t; +group_concat(value order by 1) +Abc,abc,abc,def +desc format='brief' select group_concat(value) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value) from t; +group_concat(value) +abc,Abc,def,abc +desc format='brief' select group_concat(value collate utf8mb4_bin) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:group_concat(Column#6 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select group_concat(value collate utf8mb4_bin) from t; +group_concat(value collate utf8mb4_bin) +abc,Abc,def,abc +desc format='brief' select group_concat(distinct value order by 1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct collation_agg_func.t.value order by collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value order by 1)) from t; +upper(group_concat(distinct value order by 1)) +ABC,DEF +desc format='brief' select group_concat(distinct value collate utf8mb4_bin order by 1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct Column#6 order by Column#7 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value collate utf8mb4_bin order by 1)) from t; +upper(group_concat(distinct value collate utf8mb4_bin order by 1)) +ABC,ABC,DEF +desc format='brief' select group_concat(distinct value) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct collation_agg_func.t.value separator ",")->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value)) from t; +upper(group_concat(distinct value)) +ABC,DEF +desc format='brief' select group_concat(distinct value collate utf8mb4_bin) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:group_concat(distinct Column#6 separator ",")->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select upper(group_concat(distinct value collate utf8mb4_bin)) from t; +upper(group_concat(distinct value collate utf8mb4_bin)) +ABC,ABC,DEF +desc format='brief' select count(distinct value) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct collation_agg_func.t.value)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value) from t; +count(distinct value) +2 +desc format='brief' select count(distinct value collate utf8mb4_bin) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct Column#6)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value collate utf8mb4_bin) from t; +count(distinct value collate utf8mb4_bin) +3 +desc format='brief' select count(distinct value, value1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct collation_agg_func.t.value, collation_agg_func.t.value1)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value, value1) from t; +count(distinct value, value1) +3 +desc format='brief' select count(distinct value collate utf8mb4_bin, value1) from t; +id estRows task access object operator info +StreamAgg 1.00 root funcs:count(distinct Column#6, Column#7)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, collation_agg_func.t.value1 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select count(distinct value collate utf8mb4_bin, value1) from t; +count(distinct value collate utf8mb4_bin, value1) +4 +desc format='brief' select approx_count_distinct(value) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(collation_agg_func.t.value)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value) from t; +approx_count_distinct(value) +2 +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(Column#6)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value collate utf8mb4_bin) from t; +approx_count_distinct(value collate utf8mb4_bin) +3 +desc format='brief' select approx_count_distinct(value, value1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(collation_agg_func.t.value, collation_agg_func.t.value1)->Column#5 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value, value1) from t; +approx_count_distinct(value, value1) +3 +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin, value1) from t; +id estRows task access object operator info +HashAgg 1.00 root funcs:approx_count_distinct(Column#6, Column#7)->Column#5 +└─Projection 10000.00 root cast(collation_agg_func.t.value, varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#6, collation_agg_func.t.value1 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select approx_count_distinct(value collate utf8mb4_bin, value1) from t; +approx_count_distinct(value collate utf8mb4_bin, value1) +4 +create table tt(a char(10), b enum('a', 'B', 'c'), c set('a', 'B', 'c'), d json) collate utf8mb4_general_ci; +insert into tt values ("a", "a", "a", JSON_OBJECT("a", "a")); +insert into tt values ("A", "A", "A", JSON_OBJECT("A", "A")); +insert into tt values ("b", "b", "b", JSON_OBJECT("b", "b")); +insert into tt values ("B", "B", "B", JSON_OBJECT("B", "B")); +insert into tt values ("c", "c", "c", JSON_OBJECT("c", "c")); +insert into tt values ("C", "C", "C", JSON_OBJECT("C", "C")); +split table tt by (0), (1), (2), (3), (4), (5); +desc format='brief' select min(a) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(collation_agg_func.tt.a)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.a, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.a, offset:0, count:1 + └─Selection 9990.00 cop[tikv] not(isnull(collation_agg_func.tt.a)) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(a) from tt; +min(a) +a +desc format='brief' select min(a collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.a + └─TopN 1.00 root Column#7, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.a, cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin), offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(a collate utf8mb4_bin) from tt; +min(a collate utf8mb4_bin) +A +desc format='brief' select max(a) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(collation_agg_func.tt.a)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.a:desc, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.a:desc, offset:0, count:1 + └─Selection 9990.00 cop[tikv] not(isnull(collation_agg_func.tt.a)) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(a) from tt; +max(a) +c +desc format='brief' select max(a collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─Projection 1.00 root cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#8 + └─Projection 1.00 root collation_agg_func.tt.a + └─TopN 1.00 root Column#7:desc, offset:0, count:1 + └─Projection 1.00 root collation_agg_func.tt.a, cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin)->Column#7 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin):desc, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.a, char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(a collate utf8mb4_bin) from tt; +max(a collate utf8mb4_bin) +c +desc format='brief' select min(b) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:min(collation_agg_func.tt.b)->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(b) from tt; +min(b) +a +desc format='brief' select min(b collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:min(cast(collation_agg_func.tt.b, enum('a','B','c')))->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select max(b) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:max(collation_agg_func.tt.b)->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(b) from tt; +max(b) +c +desc format='brief' select max(b collate utf8mb4_bin) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(Column#8)->Column#6 +└─TableReader 1.00 root data:StreamAgg + └─StreamAgg 1.00 cop[tikv] funcs:max(cast(collation_agg_func.tt.b, enum('a','B','c')))->Column#8 + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select min(c) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:min(collation_agg_func.tt.c)->Column#6 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(c) from tt; +min(c) +a +desc format='brief' select min(c collate utf8mb4_bin) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:min(Column#7)->Column#6 +└─Projection 10000.00 root cast(collation_agg_func.tt.c, set('a','B','c'))->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select max(c) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:max(collation_agg_func.tt.c)->Column#6 +└─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(c) from tt; +max(c) +c +desc format='brief' select max(c collate utf8mb4_bin) from tt; +id estRows task access object operator info +HashAgg 1.00 root funcs:max(Column#7)->Column#6 +└─Projection 10000.00 root cast(collation_agg_func.tt.c, set('a','B','c'))->Column#7 + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +desc format='brief' select min(d) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:min(collation_agg_func.tt.d)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.d, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.d, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.d, var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select min(d) from tt; +min(d) +{"A": "A"} +desc format='brief' select min(d collate utf8mb4_bin) from tt; +Error 1253: COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'binary' +select min(d collate utf8mb4_bin) from tt; +Error 1253: COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'binary' +desc format='brief' select max(d) from tt; +id estRows task access object operator info +StreamAgg 1.00 root funcs:max(collation_agg_func.tt.d)->Column#6 +└─TopN 1.00 root collation_agg_func.tt.d:desc, offset:0, count:1 + └─TableReader 1.00 root data:TopN + └─TopN 1.00 cop[tikv] collation_agg_func.tt.d:desc, offset:0, count:1 + └─Selection 8000.00 cop[tikv] not(isnull(cast(collation_agg_func.tt.d, var_string(4294967295)))) + └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +select max(d) from tt; +max(d) +{"c": "c"} +desc format='brief' select max(d collate utf8mb4_bin) from tt; +Error 1253: COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'binary' +select max(d collate utf8mb4_bin) from tt; +Error 1253: COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'binary' +drop database collation_agg_func; +use test diff --git a/cmd/explaintest/r/collation_check_use_collation.result b/cmd/explaintest/r/collation_check_use_collation.result deleted file mode 100644 index ffd787a4cef43..0000000000000 --- a/cmd/explaintest/r/collation_check_use_collation.result +++ /dev/null @@ -1,25 +0,0 @@ -create database collation_check_use_collation; -use collation_check_use_collation; -CREATE TABLE `t` ( -`a` char(10) DEFAULT NULL -); -CREATE TABLE `t1` ( -`a` char(10) COLLATE utf8mb4_general_ci DEFAULT NULL -); -insert into t values ("a"); -insert into t1 values ("A"); -select a as a_col from t where t.a = all (select a collate utf8mb4_general_ci from t1); -a_col -a -select a as a_col from t where t.a != any (select a collate utf8mb4_general_ci from t1); -a_col -select a as a_col from t where t.a <= all (select a collate utf8mb4_general_ci from t1); -a_col -a -select a as a_col from t where t.a <= any (select a collate utf8mb4_general_ci from t1); -a_col -a -select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); -a_col -a -use test diff --git a/cmd/explaintest/r/collation_check_use_collation_disabled.result b/cmd/explaintest/r/collation_check_use_collation_disabled.result new file mode 100644 index 0000000000000..5b335fba0a59f --- /dev/null +++ b/cmd/explaintest/r/collation_check_use_collation_disabled.result @@ -0,0 +1,131 @@ +create database collation_check_use_collation; +use collation_check_use_collation; +CREATE TABLE `t` ( +`a` char(10) DEFAULT NULL +); +CREATE TABLE `t1` ( +`a` char(10) COLLATE utf8mb4_general_ci DEFAULT NULL +); +insert into t values ("A"); +insert into t1 values ("a"); +select a as a_col from t where t.a = all (select a collate utf8mb4_general_ci from t1); +a_col +select a as a_col from t where t.a != any (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a <= all (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a <= any (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); +a_col +drop table if exists t; +create table t(a enum('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +a b +a b +drop table if exists t; +create table t(a enum('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +insert into t values ("B", "b"); +Error 1265: Data truncated for column 'a' at row 1 +select * from t where 'B' collate utf8mb4_general_ci in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a, b); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +a b +b c +select * from t where 1 in (a); +a b +select * from t where 2 in (a); +a b +b c +select * from t where 1 in (a, 0); +a b +select * from t where a between 1 and 2; +a b +b c +select * from t where a between 1 and "a"; +a b +select * from t where a between "a" and "b"; +a b +b c +select * from t where 2 between a and "c"; +a b +select * from t where 2 between a and 3; +a b +b c +select * from t where "b" between a and a; +a b +b c +select * from t where "b" collate utf8mb4_bin between a and a; +a b +b c +select * from t where "b" between a and 3; +a b +drop table if exists t; +create table t(a set('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +a b +a b +drop table if exists t; +create table t(a set('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +insert into t values ("B", "b"); +Error 1265: Data truncated for column 'a' at row 1 +select * from t where 'B' collate utf8mb4_general_ci in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a, b); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +a b +b c +select * from t where 1 in (a); +a b +select * from t where 2 in (a); +a b +b c +select * from t where 1 in (a, 0); +a b +select * from t where a between 1 and 2; +a b +b c +select * from t where a between 1 and "a"; +a b +select * from t where a between "a" and "b"; +a b +b c +select * from t where 2 between a and "c"; +a b +select * from t where 2 between a and 3; +a b +b c +select * from t where "b" between a and a; +a b +b c +select * from t where "b" collate utf8mb4_bin between a and a; +a b +b c +select * from t where "b" between a and 3; +a b +drop table if exists tbl_2; +create table tbl_2 ( col_20 bigint not null , col_21 smallint not null , col_22 decimal(24,10) default null , col_23 tinyint default 71 not null , col_24 bigint not null , col_25 tinyint default 18 , col_26 varchar(330) collate utf8_bin not null , col_27 char(77) collate utf8mb4_unicode_ci , col_28 char(46) collate utf8_general_ci not null , col_29 smallint unsigned not null , primary key idx_13 ( col_27(5) ) , key idx_14 ( col_24 ) , unique key idx_15 ( col_23,col_21,col_28,col_29,col_24 ) ) collate utf8_bin ; +insert ignore into tbl_2 values ( 5888267793391993829,5371,94.63,-109,5728076076919247337,89,'WUicqUTgdGJcjbC','SapBPqczTWWSN','xUSwH',49462 ); +select col_25 from tbl_2 where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +select col_25 from tbl_2 use index(primary) where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +use test diff --git a/cmd/explaintest/r/collation_check_use_collation_enabled.result b/cmd/explaintest/r/collation_check_use_collation_enabled.result new file mode 100644 index 0000000000000..7aee634a8f0df --- /dev/null +++ b/cmd/explaintest/r/collation_check_use_collation_enabled.result @@ -0,0 +1,150 @@ +create database collation_check_use_collation; +use collation_check_use_collation; +CREATE TABLE `t` ( +`a` char(10) DEFAULT NULL +); +CREATE TABLE `t1` ( +`a` char(10) COLLATE utf8mb4_general_ci DEFAULT NULL +); +insert into t values ("A"); +insert into t1 values ("a"); +select a as a_col from t where t.a = all (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a != any (select a collate utf8mb4_general_ci from t1); +a_col +select a as a_col from t where t.a <= all (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a <= any (select a collate utf8mb4_general_ci from t1); +a_col +A +select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); +a_col +A +drop table if exists t; +create table t(a enum('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +a b +a b +drop table if exists t; +create table t(a enum('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +insert into t values ("B", "b"); +select * from t where 'B' collate utf8mb4_general_ci in (a); +a b +b c +b b +select * from t where 'B' collate utf8mb4_bin in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a, b); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +a b +b c +b b +select * from t where 1 in (a); +a b +select * from t where 2 in (a); +a b +b c +b b +select * from t where 1 in (a, 0); +a b +select * from t where a between 1 and 2; +a b +b c +b b +select * from t where a between 1 and "a"; +a b +select * from t where a between "a" and "b"; +a b +b c +b b +select * from t where 2 between a and "c"; +a b +select * from t where 2 between a and 3; +a b +b c +b b +select * from t where "b" between a and a; +a b +b c +b b +select * from t where "b" collate utf8mb4_bin between a and a; +a b +b c +b b +select * from t where "b" between a and 3; +a b +drop table if exists t; +create table t(a set('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +a b +a b +drop table if exists t; +create table t(a set('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +insert into t values ("B", "b"); +select * from t where 'B' collate utf8mb4_general_ci in (a); +a b +b c +b b +select * from t where 'B' collate utf8mb4_bin in (a); +a b +select * from t where 'B' collate utf8mb4_bin in (a, b); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +a b +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +a b +b c +b b +select * from t where 1 in (a); +a b +select * from t where 2 in (a); +a b +b c +b b +select * from t where 1 in (a, 0); +a b +select * from t where a between 1 and 2; +a b +b c +b b +select * from t where a between 1 and "a"; +a b +select * from t where a between "a" and "b"; +a b +b c +b b +select * from t where 2 between a and "c"; +a b +select * from t where 2 between a and 3; +a b +b c +b b +select * from t where "b" between a and a; +a b +b c +b b +select * from t where "b" collate utf8mb4_bin between a and a; +a b +b c +b b +select * from t where "b" between a and 3; +a b +drop table if exists tbl_2; +create table tbl_2 ( col_20 bigint not null , col_21 smallint not null , col_22 decimal(24,10) default null , col_23 tinyint default 71 not null , col_24 bigint not null , col_25 tinyint default 18 , col_26 varchar(330) collate utf8_bin not null , col_27 char(77) collate utf8mb4_unicode_ci , col_28 char(46) collate utf8_general_ci not null , col_29 smallint unsigned not null , primary key idx_13 ( col_27(5) ) , key idx_14 ( col_24 ) , unique key idx_15 ( col_23,col_21,col_28,col_29,col_24 ) ) collate utf8_bin ; +insert ignore into tbl_2 values ( 5888267793391993829,5371,94.63,-109,5728076076919247337,89,'WUicqUTgdGJcjbC','SapBPqczTWWSN','xUSwH',49462 ); +select col_25 from tbl_2 where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +89 +select col_25 from tbl_2 use index(primary) where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +89 +use test diff --git a/cmd/explaintest/r/collation_misc_disabled.result b/cmd/explaintest/r/collation_misc_disabled.result new file mode 100644 index 0000000000000..33f0ebe26f701 --- /dev/null +++ b/cmd/explaintest/r/collation_misc_disabled.result @@ -0,0 +1,96 @@ +create database collation_misc; +use collation_misc; +create table t1(a varchar(20) charset utf8); +insert into t1 values ("t1_value"); +alter table t1 collate uTf8mB4_uNiCoDe_Ci charset Utf8mB4 charset uTF8Mb4 collate UTF8MB4_BiN; +alter table t1 modify column a varchar(20) charset utf8mb4; +select * from t1; +a +t1_value +create table t(a varchar(20) charset latin1); +insert into t values ("t_value"); +alter table t modify column a varchar(20) charset latin1; +select * from t; +a +t_value +alter table t modify column a varchar(20) charset utf8; +Error 8200: Unsupported modify charset from latin1 to utf8 +alter table t modify column a varchar(20) charset utf8mb4; +Error 8200: Unsupported modify charset from latin1 to utf8mb4 +alter table t modify column a varchar(20) charset utf8 collate utf8_bin; +Error 8200: Unsupported modify charset from latin1 to utf8 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8mb4_general_ci; +Error 8200: Unsupported modify charset from latin1 to utf8mb4 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8bin; +[ddl:1273]Unknown collation: 'utf8bin' +alter table t collate LATIN1_GENERAL_CI charset utf8 collate utf8_bin; +Error 1302: Conflicting declarations: 'CHARACTER SET latin1' and 'CHARACTER SET utf8' +alter table t collate LATIN1_GENERAL_CI collate UTF8MB4_UNICODE_ci collate utf8_bin; +Error 1253: COLLATION 'utf8mb4_unicode_ci' is not valid for CHARACTER SET 'latin1' +create database if not exists cd_test_utf8 CHARACTER SET utf8 COLLATE utf8_bin; +create database if not exists cd_test_latin1 CHARACTER SET latin1 COLLATE latin1_swedish_ci; +use cd_test_utf8; +select @@character_set_database; +@@character_set_database +utf8 +select @@collation_database; +@@collation_database +utf8_bin +use cd_test_latin1; +select @@character_set_database; +@@character_set_database +latin1 +select @@collation_database; +@@collation_database +latin1_swedish_ci +create database if not exists test_db CHARACTER SET latin1 COLLATE latin1_swedish_ci; +with cte as (select cast('2010-09-09' as date) a union select '2010-09-09 ') select count(*) from cte; +count(*) +2 +set names utf8mb4 collate utf8mb4_general_ci; +select position('a' in 'AA'); +position('a' in 'AA') +0 +select locate('a', 'AA'); +locate('a', 'AA') +0 +select locate('a', 'a'); +locate('a', 'a') +1 +set names utf8mb4; +SELECT default_collate_name, maxlen FROM information_schema.character_sets ORDER BY character_set_name; +default_collate_name maxlen +ascii_bin 1 +binary 1 +gbk_bin 2 +latin1_bin 1 +utf8_bin 3 +utf8mb4_bin 4 +SELECT character_set_name, id, sortlen FROM information_schema.collations ORDER BY collation_name, id; +character_set_name id sortlen +ascii 65 1 +binary 63 1 +gbk 87 1 +latin1 47 1 +utf8 83 1 +utf8mb4 46 1 +select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY where COLLATION_NAME='utf8mb4_bin'; +COLLATION_NAME CHARACTER_SET_NAME +utf8mb4_bin utf8mb4 +show charset; +Charset Description Default collation Maxlen +ascii US ASCII ascii_bin 1 +binary binary binary 1 +gbk Chinese Internal Code Specification gbk_bin 2 +latin1 Latin1 latin1_bin 1 +utf8 UTF-8 Unicode utf8_bin 3 +utf8mb4 UTF-8 Unicode utf8mb4_bin 4 +show collation; +Collation Charset Id Default Compiled Sortlen +utf8mb4_bin utf8mb4 46 Yes Yes 1 +latin1_bin latin1 47 Yes Yes 1 +binary binary 63 Yes Yes 1 +ascii_bin ascii 65 Yes Yes 1 +utf8_bin utf8 83 Yes Yes 1 +gbk_bin gbk 87 Yes Yes 1 +use test; diff --git a/cmd/explaintest/r/collation_misc_enabled.result b/cmd/explaintest/r/collation_misc_enabled.result new file mode 100644 index 0000000000000..8f75d4e18d151 --- /dev/null +++ b/cmd/explaintest/r/collation_misc_enabled.result @@ -0,0 +1,109 @@ +create database collation_misc; +use collation_misc; +create table t1(a varchar(20) charset utf8); +insert into t1 values ("t1_value"); +alter table t1 collate uTf8mB4_uNiCoDe_Ci charset Utf8mB4 charset uTF8Mb4 collate UTF8MB4_BiN; +alter table t1 modify column a varchar(20) charset utf8mb4; +select * from t1; +a +t1_value +create table t(a varchar(20) charset latin1); +insert into t values ("t_value"); +alter table t modify column a varchar(20) charset latin1; +select * from t; +a +t_value +alter table t modify column a varchar(20) charset utf8; +Error 8200: Unsupported modify charset from latin1 to utf8 +alter table t modify column a varchar(20) charset utf8mb4; +Error 8200: Unsupported modify charset from latin1 to utf8mb4 +alter table t modify column a varchar(20) charset utf8 collate utf8_bin; +Error 8200: Unsupported modify charset from latin1 to utf8 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8mb4_general_ci; +Error 8200: Unsupported modify charset from latin1 to utf8mb4 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8bin; +[ddl:1273]Unknown collation: 'utf8bin' +alter table t collate LATIN1_GENERAL_CI charset utf8 collate utf8_bin; +Error 1273: Unsupported collation when new collation is enabled: 'latin1_general_ci' +alter table t collate LATIN1_GENERAL_CI collate UTF8MB4_UNICODE_ci collate utf8_bin; +Error 1273: Unsupported collation when new collation is enabled: 'latin1_general_ci' +create database if not exists cd_test_utf8 CHARACTER SET utf8 COLLATE utf8_bin; +create database if not exists cd_test_latin1 CHARACTER SET latin1 COLLATE latin1_swedish_ci; +Error 1273: Unsupported collation when new collation is enabled: 'latin1_swedish_ci' +use cd_test_utf8; +select @@character_set_database; +@@character_set_database +utf8 +select @@collation_database; +@@collation_database +utf8_bin +use cd_test_latin1; +Error 1049: Unknown database 'cd_test_latin1' +select @@character_set_database; +@@character_set_database +utf8 +select @@collation_database; +@@collation_database +utf8_bin +create database if not exists test_db CHARACTER SET latin1 COLLATE latin1_swedish_ci; +Error 1273: Unsupported collation when new collation is enabled: 'latin1_swedish_ci' +with cte as (select cast('2010-09-09' as date) a union select '2010-09-09 ') select count(*) from cte; +count(*) +1 +set names utf8mb4 collate utf8mb4_general_ci; +select position('a' in 'AA'); +position('a' in 'AA') +1 +select locate('a', 'AA'); +locate('a', 'AA') +1 +select locate('a', 'a'); +locate('a', 'a') +1 +set names utf8mb4; +SELECT default_collate_name, maxlen FROM information_schema.character_sets ORDER BY character_set_name; +default_collate_name maxlen +ascii_bin 1 +binary 1 +gbk_chinese_ci 2 +latin1_bin 1 +utf8_bin 3 +utf8mb4_bin 4 +SELECT character_set_name, id, sortlen FROM information_schema.collations ORDER BY collation_name, id; +character_set_name id sortlen +ascii 65 1 +binary 63 1 +gbk 87 1 +gbk 28 1 +latin1 47 1 +utf8 83 1 +utf8 33 1 +utf8 192 1 +utf8mb4 46 1 +utf8mb4 45 1 +utf8mb4 224 1 +select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY where COLLATION_NAME='utf8mb4_bin'; +COLLATION_NAME CHARACTER_SET_NAME +utf8mb4_bin utf8mb4 +show charset; +Charset Description Default collation Maxlen +ascii US ASCII ascii_bin 1 +binary binary binary 1 +gbk Chinese Internal Code Specification gbk_chinese_ci 2 +latin1 Latin1 latin1_bin 1 +utf8 UTF-8 Unicode utf8_bin 3 +utf8mb4 UTF-8 Unicode utf8mb4_bin 4 +show collation; +Collation Charset Id Default Compiled Sortlen +ascii_bin ascii 65 Yes Yes 1 +binary binary 63 Yes Yes 1 +gbk_bin gbk 87 Yes 1 +gbk_chinese_ci gbk 28 Yes Yes 1 +latin1_bin latin1 47 Yes Yes 1 +utf8_bin utf8 83 Yes Yes 1 +utf8_general_ci utf8 33 Yes 1 +utf8_unicode_ci utf8 192 Yes 1 +utf8mb4_bin utf8mb4 46 Yes Yes 1 +utf8mb4_general_ci utf8mb4 45 Yes 1 +utf8mb4_unicode_ci utf8mb4 224 Yes 1 +use test; diff --git a/cmd/explaintest/r/collation_pointget_disabled.result b/cmd/explaintest/r/collation_pointget_disabled.result new file mode 100644 index 0000000000000..96b2a7aa58ca5 --- /dev/null +++ b/cmd/explaintest/r/collation_pointget_disabled.result @@ -0,0 +1,192 @@ +create database collation_point_get; +use collation_point_get; +drop table if exists t; +create table t(a char(2), b char(2), index idx_1(a)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +select * from t tmp where a = "aa"; +a b +aa bb +select * from t tmp where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +select * from t where a = "a "; +a b +drop table if exists t; +create table t(a char(2) binary, b char(2), index idx_1(a)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +select * from t where a = "a "; +a b +select * from t where a = ""; +a b + +select * from t where a = " "; +a b +select * from t where a = " "; +a b +select * from t where a = " "; +a b +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select * from t tmp where a = "aa"; +a b +aa bb +select * from t tmp where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +a b +a b +select * from t tmp where a = "a "; +a b +select * from t tmp where a = "a "; +a b +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +a b +a b +select * from t tmp where a = "a "; +a b +select * from t tmp where a = "a "; +a b +select * from t tmp where a = ""; +a b + +select * from t tmp where a = " "; +a b +select * from t tmp where a = " "; +a b +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select *, a from t tmp where a = "aa"; +a b a +aa bb aa +select tmp.* from t tmp where a = "aa"; +a b +aa bb +select tmp.a, tmp.b from t tmp where a = "aa"; +a b +aa bb +select tmp.*, tmp.a, tmp.b from t tmp where a = "aa"; +a b a b +aa bb aa bb +select tmp.* from t tmp where a = "aab"; +a b +select tmp.a, tmp.b from t tmp where a = "aab"; +a b +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +a b a b +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +a b a b +select * from t tmp where tmp.a = "aa"; +a b +aa bb +select a, b from t tmp where tmp.a = "aa"; +a b +aa bb +select *, a, b from t tmp where tmp.a = "aa"; +a b a b +aa bb aa bb +select a from t where xxxxx.a = "aa"; +Error 1054: Unknown column 'xxxxx.a' in 'where clause' +select xxxxx.a from t where a = "aa"; +Error 1054: Unknown column 'xxxxx.a' in 'field list' +select a from t tmp where t.a = "aa"; +Error 1054: Unknown column 't.a' in 'where clause' +select t.a from t tmp where a = "aa"; +Error 1054: Unknown column 't.a' in 'field list' +select t.* from t tmp where a = "aa"; +Error 1051: Unknown table 't' +drop table if exists t; +create table t(a char(4) primary key, b char(4)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +select * from t where a = "a "; +a b +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +select * from t where a = "a "; +a b +select * from t where a = ""; +a b + +select * from t where a = " "; +a b +select * from t where a = " "; +a b +drop table if exists t; +create table t(a varchar(2) primary key, b varchar(2)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +drop table if exists t; +create table t(a varchar(2) binary primary key, b varchar(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +select * from t where a = ""; +a b +select * from t where a = " "; +a b + +select * from t where a = " "; +a b +use mysql; diff --git a/cmd/explaintest/r/collation_pointget_enabled.result b/cmd/explaintest/r/collation_pointget_enabled.result new file mode 100644 index 0000000000000..c5bcd58c15ba2 --- /dev/null +++ b/cmd/explaintest/r/collation_pointget_enabled.result @@ -0,0 +1,217 @@ +create database collation_point_get; +use collation_point_get; +drop table if exists t; +create table t(a char(2), b char(2), index idx_1(a)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +select * from t tmp where a = "aa"; +a b +aa bb +select * from t tmp where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +drop table if exists t; +create table t(a char(2) binary, b char(2), index idx_1(a)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = ""; +a b + +select * from t where a = " "; +a b + +select * from t where a = " "; +a b + +select * from t where a = " "; +a b + +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select * from t tmp where a = "aa"; +a b +aa bb +select * from t tmp where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +a b +a b +select * from t tmp where a = "a "; +a b +a b +select * from t tmp where a = "a "; +a b +a b +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +a b +a b +select * from t tmp where a = "a "; +a b +a b +select * from t tmp where a = "a "; +a b +a b +select * from t tmp where a = ""; +a b + +select * from t tmp where a = " "; +a b + +select * from t tmp where a = " "; +a b + +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select *, a from t tmp where a = "aa"; +a b a +aa bb aa +select tmp.* from t tmp where a = "aa"; +a b +aa bb +select tmp.a, tmp.b from t tmp where a = "aa"; +a b +aa bb +select tmp.*, tmp.a, tmp.b from t tmp where a = "aa"; +a b a b +aa bb aa bb +select tmp.* from t tmp where a = "aab"; +a b +select tmp.a, tmp.b from t tmp where a = "aab"; +a b +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +a b a b +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +a b a b +select * from t tmp where tmp.a = "aa"; +a b +aa bb +select a, b from t tmp where tmp.a = "aa"; +a b +aa bb +select *, a, b from t tmp where tmp.a = "aa"; +a b a b +aa bb aa bb +select a from t where xxxxx.a = "aa"; +Error 1054: Unknown column 'xxxxx.a' in 'where clause' +select xxxxx.a from t where a = "aa"; +Error 1054: Unknown column 'xxxxx.a' in 'field list' +select a from t tmp where t.a = "aa"; +Error 1054: Unknown column 't.a' in 'where clause' +select t.a from t tmp where a = "aa"; +Error 1054: Unknown column 't.a' in 'field list' +select t.* from t tmp where a = "aa"; +Error 1051: Unknown table 't' +drop table if exists t; +create table t(a char(4) primary key, b char(4)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = ""; +a b + +select * from t where a = " "; +a b + +select * from t where a = " "; +a b + +drop table if exists t; +create table t(a varchar(2) primary key, b varchar(2)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +a b +aa bb +select * from t where a = "aab"; +a b +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +drop table if exists t; +create table t(a varchar(2) binary primary key, b varchar(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = "a "; +a b +a b +select * from t where a = ""; +a b + +select * from t where a = " "; +a b + +select * from t where a = " "; +a b + +use mysql; diff --git a/cmd/explaintest/r/common_collation.result b/cmd/explaintest/r/common_collation.result new file mode 100644 index 0000000000000..235ce7fce3d0d --- /dev/null +++ b/cmd/explaintest/r/common_collation.result @@ -0,0 +1,52 @@ +drop table if exists t; +create table t(a char(10) collate utf8mb4_unicode_ci, b char(10) collate utf8mb4_general_ci); +insert into t values ('å•Š', 'æ’’æ—¦'); +select coercibility(concat(a, b)) from t; +coercibility(concat(a, b)) +1 +select coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) from t; +coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) +0 +select coercibility(convert('a' using utf8mb4)); +coercibility(convert('a' using utf8mb4)) +2 +select coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci); +coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci) +0 +drop table if exists t; +create table t (a char(20), b blob(100), c text, d json, e timestamp, f set('a一','b二','c三','då››'), g text, h enum('a一','b二','c三','då››') default 'c三'); +insert into t values ('你好', '你好', '你好', '{\"测试\": \"你好\"}', '2018-10-13', 1, '你好', 'a一'); +select coercibility(a), coercibility(b), coercibility(c), coercibility(d), coercibility(e), coercibility(f), coercibility(g), coercibility(h) from t; +coercibility(a) coercibility(b) coercibility(c) coercibility(d) coercibility(e) coercibility(f) coercibility(g) coercibility(h) +2 2 2 2 5 2 2 2 +select collation(d), collation(upper(d)), collation(elt(1, d, 0x12)), collation(elt(1, elt(1, d, 0x12), 0x12)), collation(elt(1, d, b)) from t; +collation(d) collation(upper(d)) collation(elt(1, d, 0x12)) collation(elt(1, elt(1, d, 0x12), 0x12)) collation(elt(1, d, b)) +binary utf8mb4_bin utf8mb4_bin utf8mb4_bin binary +drop table t; +create table t(a binary, b json, c char charset gbk); +insert into t values ('a', '{"a":"b"}', 'a'); +select collation(concat(a, b)), collation(concat(b, a)), collation(concat(0x61, b)), collation(concat(b, 0x61)), collation(concat(c, b)), collation(concat(b, c)) from t; +collation(concat(a, b)) collation(concat(b, a)) collation(concat(0x61, b)) collation(concat(b, 0x61)) collation(concat(c, b)) collation(concat(b, c)) +binary binary utf8mb4_bin utf8mb4_bin utf8mb4_bin utf8mb4_bin +DROP TABLE IF EXISTS t2; +CREATE TABLE t2 ( +id INT NOT NULL PRIMARY KEY auto_increment, +`col_91` char(47) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, +`col_92` int(10) unsigned DEFAULT '2478966067', +`col_97` char(32) COLLATE utf8mb4_bin NOT NULL +) collate utf8mb4_general_ci; +INSERT INTO `t2` VALUES (17,'UUtJeaV',497551109,'snRXXCZHBPW'); +SET names utf8mb4 collate utf8mb4_bin; +SELECT greatest( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +expr1 +snRXXCZHBPW +SELECT least( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +expr1 +UUtJeaV +SET names utf8mb4 collate utf8mb4_general_ci; +SELECT greatest( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +expr1 +snRXXCZHBPW +SELECT least( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +expr1 +UUtJeaV diff --git a/cmd/explaintest/r/cte.result b/cmd/explaintest/r/cte.result index 4f3d979c45001..6c1da3d121e77 100644 --- a/cmd/explaintest/r/cte.result +++ b/cmd/explaintest/r/cte.result @@ -387,17 +387,18 @@ insert into tpk values(1), (2), (3); // Expect a Sort operator on CTE. explain with cte1 as (select c1 from t1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; id estRows task access object operator info -MergeJoin_26 10000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 -├─Sort_24(Build) 8000.00 root test.t1.c1 -│ └─Selection_22 8000.00 root not(isnull(test.t1.c1)) -│ └─CTEFullScan_23 10000.00 root CTE:dt2 data:CTE_0 -└─Sort_20(Probe) 9990.00 root test.t1.c1 - └─TableReader_19 9990.00 root data:Selection_18 - └─Selection_18 9990.00 cop[tikv] not(isnull(test.t1.c1)) - └─TableFullScan_17 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_12(Seed Part) 10000.00 root data:TableFullScan_11 - └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +MergeJoin_28 8000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 +├─Sort_26(Build) 6400.00 root test.t1.c1 +│ └─Selection_24 6400.00 root not(isnull(test.t1.c1)) +│ └─CTEFullScan_25 8000.00 root CTE:dt2 data:CTE_0 +└─Sort_22(Probe) 9990.00 root test.t1.c1 + └─TableReader_21 9990.00 root data:Selection_20 + └─Selection_20 9990.00 cop[tikv] not(isnull(test.t1.c1)) + └─TableFullScan_19 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_11(Seed Part) 8000.00 root not(isnull(test.t1.c1)) + └─TableReader_14 10000.00 root data:TableFullScan_13 + └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo with cte1 as (select c1 from t1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; c1 c1 1 1 @@ -411,15 +412,16 @@ c1 c1 // Sort should not exist, because tpk.c1 is pk. Not the best plan for now(#25674). explain with cte1 as (select c1 from tpk) select /*+ MERGE_JOIN(dt1, dt2) */ * from tpk dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; id estRows task access object operator info -MergeJoin_24 10000.00 root inner join, left key:test.tpk.c1, right key:test.tpk.c1 -├─Sort_22(Build) 8000.00 root test.tpk.c1 -│ └─Selection_20 8000.00 root not(isnull(test.tpk.c1)) -│ └─CTEFullScan_21 10000.00 root CTE:dt2 data:CTE_0 -└─TableReader_18(Probe) 10000.00 root data:TableFullScan_17 - └─TableFullScan_17 10000.00 cop[tikv] table:dt1 keep order:true, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_12(Seed Part) 10000.00 root data:TableFullScan_11 - └─TableFullScan_11 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo +MergeJoin_26 8000.00 root inner join, left key:test.tpk.c1, right key:test.tpk.c1 +├─Sort_24(Build) 6400.00 root test.tpk.c1 +│ └─Selection_22 6400.00 root not(isnull(test.tpk.c1)) +│ └─CTEFullScan_23 8000.00 root CTE:dt2 data:CTE_0 +└─TableReader_20(Probe) 10000.00 root data:TableFullScan_19 + └─TableFullScan_19 10000.00 cop[tikv] table:dt1 keep order:true, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_11(Seed Part) 8000.00 root not(isnull(test.tpk.c1)) + └─TableReader_14 10000.00 root data:TableFullScan_13 + └─TableFullScan_13 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo with cte1 as (select c1 from tpk) select /*+ MERGE_JOIN(dt1, dt2) */ * from tpk dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; c1 c1 1 1 @@ -428,18 +430,19 @@ c1 c1 // Sort should not exist, because we have order by in CTE definition. Not the best plan for now(#25674). explain with cte1 as (select c1 from t1 order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; id estRows task access object operator info -MergeJoin_30 10000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 -├─Sort_28(Build) 8000.00 root test.t1.c1 -│ └─Selection_26 8000.00 root not(isnull(test.t1.c1)) -│ └─CTEFullScan_27 10000.00 root CTE:dt2 data:CTE_0 -└─Sort_24(Probe) 9990.00 root test.t1.c1 - └─TableReader_23 9990.00 root data:Selection_22 - └─Selection_22 9990.00 cop[tikv] not(isnull(test.t1.c1)) - └─TableFullScan_21 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─Sort_11(Seed Part) 10000.00 root test.t1.c1 - └─TableReader_15 10000.00 root data:TableFullScan_14 - └─TableFullScan_14 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +MergeJoin_32 8000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 +├─Sort_30(Build) 6400.00 root test.t1.c1 +│ └─Selection_28 6400.00 root not(isnull(test.t1.c1)) +│ └─CTEFullScan_29 8000.00 root CTE:dt2 data:CTE_0 +└─Sort_26(Probe) 9990.00 root test.t1.c1 + └─TableReader_25 9990.00 root data:Selection_24 + └─Selection_24 9990.00 cop[tikv] not(isnull(test.t1.c1)) + └─TableFullScan_23 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_12(Seed Part) 8000.00 root not(isnull(test.t1.c1)) + └─Sort_13 10000.00 root test.t1.c1 + └─TableReader_17 10000.00 root data:TableFullScan_16 + └─TableFullScan_16 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo with cte1 as (select c1 from t1 order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; c1 c1 1 1 @@ -500,18 +503,19 @@ c1 c1 // Expect Sort operator in CTE definition. explain with cte1 as (select c1 from t1 order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; id estRows task access object operator info -MergeJoin_30 10000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 -├─Sort_28(Build) 8000.00 root test.t1.c1 -│ └─Selection_26 8000.00 root not(isnull(test.t1.c1)) -│ └─CTEFullScan_27 10000.00 root CTE:dt2 data:CTE_0 -└─Sort_24(Probe) 9990.00 root test.t1.c1 - └─TableReader_23 9990.00 root data:Selection_22 - └─Selection_22 9990.00 cop[tikv] not(isnull(test.t1.c1)) - └─TableFullScan_21 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─Sort_11(Seed Part) 10000.00 root test.t1.c1 - └─TableReader_15 10000.00 root data:TableFullScan_14 - └─TableFullScan_14 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +MergeJoin_32 8000.00 root inner join, left key:test.t1.c1, right key:test.t1.c1 +├─Sort_30(Build) 6400.00 root test.t1.c1 +│ └─Selection_28 6400.00 root not(isnull(test.t1.c1)) +│ └─CTEFullScan_29 8000.00 root CTE:dt2 data:CTE_0 +└─Sort_26(Probe) 9990.00 root test.t1.c1 + └─TableReader_25 9990.00 root data:Selection_24 + └─Selection_24 9990.00 cop[tikv] not(isnull(test.t1.c1)) + └─TableFullScan_23 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_12(Seed Part) 8000.00 root not(isnull(test.t1.c1)) + └─Sort_13 10000.00 root test.t1.c1 + └─TableReader_17 10000.00 root data:TableFullScan_16 + └─TableFullScan_16 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo with cte1 as (select c1 from t1 order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; c1 c1 1 1 @@ -525,17 +529,18 @@ c1 c1 // Sort should not exist, because tpk is ordered. Not the best plan for now(#25674). explain with cte1 as (select c1 from tpk order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; id estRows task access object operator info -MergeJoin_32 10000.00 root inner join, left key:test.t1.c1, right key:test.tpk.c1 -├─Sort_30(Build) 8000.00 root test.tpk.c1 -│ └─Selection_28 8000.00 root not(isnull(test.tpk.c1)) -│ └─CTEFullScan_29 10000.00 root CTE:dt2 data:CTE_0 -└─Sort_26(Probe) 9990.00 root test.t1.c1 - └─TableReader_25 9990.00 root data:Selection_24 - └─Selection_24 9990.00 cop[tikv] not(isnull(test.t1.c1)) - └─TableFullScan_23 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_18(Seed Part) 10000.00 root data:TableFullScan_17 - └─TableFullScan_17 10000.00 cop[tikv] table:tpk keep order:true, stats:pseudo +MergeJoin_34 8000.00 root inner join, left key:test.t1.c1, right key:test.tpk.c1 +├─Sort_32(Build) 6400.00 root test.tpk.c1 +│ └─Selection_30 6400.00 root not(isnull(test.tpk.c1)) +│ └─CTEFullScan_31 8000.00 root CTE:dt2 data:CTE_0 +└─Sort_28(Probe) 9990.00 root test.t1.c1 + └─TableReader_27 9990.00 root data:Selection_26 + └─Selection_26 9990.00 cop[tikv] not(isnull(test.t1.c1)) + └─TableFullScan_25 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_12(Seed Part) 8000.00 root not(isnull(test.tpk.c1)) + └─TableReader_20 10000.00 root data:TableFullScan_19 + └─TableFullScan_19 10000.00 cop[tikv] table:tpk keep order:true, stats:pseudo with cte1 as (select c1 from tpk order by c1) select /*+ MERGE_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = dt1.c1 order by 1, 2; c1 c1 1 1 @@ -545,15 +550,16 @@ c1 c1 // HashJoin. No need to sort explain with cte1 as (select c1 from t1) select /*+ HASH_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = 1 order by 1, 2; id estRows task access object operator info -Sort_13 80000000.00 root test.t1.c1, test.t1.c1 -└─HashJoin_16 80000000.00 root CARTESIAN inner join - ├─Selection_20(Build) 8000.00 root eq(test.t1.c1, 1) - │ └─CTEFullScan_21 10000.00 root CTE:dt2 data:CTE_0 - └─TableReader_19(Probe) 10000.00 root data:TableFullScan_18 - └─TableFullScan_18 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_12(Seed Part) 10000.00 root data:TableFullScan_11 - └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +Sort_15 64000000.00 root test.t1.c1, test.t1.c1 +└─HashJoin_18 64000000.00 root CARTESIAN inner join + ├─Selection_22(Build) 6400.00 root eq(test.t1.c1, 1) + │ └─CTEFullScan_23 8000.00 root CTE:dt2 data:CTE_0 + └─TableReader_21(Probe) 10000.00 root data:TableFullScan_20 + └─TableFullScan_20 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_11(Seed Part) 8000.00 root eq(test.t1.c1, 1) + └─TableReader_14 10000.00 root data:TableFullScan_13 + └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo with cte1 as (select c1 from t1) select /*+ HASH_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = 1 order by 1, 2; c1 c1 1 1 @@ -566,15 +572,16 @@ c1 c1 2 1 explain with cte1 as (select c1 from tpk) select /*+ HASH_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = 1 order by 1, 2; id estRows task access object operator info -Sort_13 80000000.00 root test.t1.c1, test.tpk.c1 -└─HashJoin_16 80000000.00 root CARTESIAN inner join - ├─Selection_20(Build) 8000.00 root eq(test.tpk.c1, 1) - │ └─CTEFullScan_21 10000.00 root CTE:dt2 data:CTE_0 - └─TableReader_19(Probe) 10000.00 root data:TableFullScan_18 - └─TableFullScan_18 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_12(Seed Part) 10000.00 root data:TableFullScan_11 - └─TableFullScan_11 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo +Sort_15 64000000.00 root test.t1.c1, test.tpk.c1 +└─HashJoin_18 64000000.00 root CARTESIAN inner join + ├─Selection_22(Build) 6400.00 root eq(test.tpk.c1, 1) + │ └─CTEFullScan_23 8000.00 root CTE:dt2 data:CTE_0 + └─TableReader_21(Probe) 10000.00 root data:TableFullScan_20 + └─TableFullScan_20 10000.00 cop[tikv] table:dt1 keep order:false, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_11(Seed Part) 8000.00 root eq(test.tpk.c1, 1) + └─TableReader_14 10000.00 root data:TableFullScan_13 + └─TableFullScan_13 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo with cte1 as (select c1 from tpk) select /*+ HASH_JOIN(dt1, dt2) */ * from t1 dt1 inner join cte1 dt2 on dt2.c1 = 1 order by 1, 2; c1 c1 1 1 @@ -589,21 +596,137 @@ create table tpk1(c1 int primary key); insert into tpk1 values(1), (2), (3); explain with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1; id estRows task access object operator info -Projection_18 12500.00 root test.tpk1.c1, test.tpk.c1, test.tpk.c1 -└─HashJoin_20 12500.00 root inner join, equal:[eq(test.tpk.c1, test.tpk.c1)] - ├─Selection_21(Build) 8000.00 root not(isnull(test.tpk.c1)) - │ └─CTEFullScan_22 10000.00 root CTE:dt3 data:CTE_0 - └─MergeJoin_23(Probe) 10000.00 root inner join, left key:test.tpk1.c1, right key:test.tpk.c1 - ├─Sort_29(Build) 8000.00 root test.tpk.c1 - │ └─Selection_27 8000.00 root not(isnull(test.tpk.c1)) - │ └─CTEFullScan_28 10000.00 root CTE:dt2 data:CTE_0 - └─TableReader_25(Probe) 10000.00 root data:TableFullScan_24 - └─TableFullScan_24 10000.00 cop[tikv] table:dt1 keep order:true, stats:pseudo -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_14(Seed Part) 10000.00 root data:TableFullScan_13 - └─TableFullScan_13 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo +Projection_20 10000.00 root test.tpk1.c1, test.tpk.c1, test.tpk.c1 +└─HashJoin_22 10000.00 root inner join, equal:[eq(test.tpk.c1, test.tpk.c1)] + ├─Selection_23(Build) 6400.00 root not(isnull(test.tpk.c1)) + │ └─CTEFullScan_24 8000.00 root CTE:dt3 data:CTE_0 + └─MergeJoin_25(Probe) 8000.00 root inner join, left key:test.tpk1.c1, right key:test.tpk.c1 + ├─Sort_31(Build) 6400.00 root test.tpk.c1 + │ └─Selection_29 6400.00 root not(isnull(test.tpk.c1)) + │ └─CTEFullScan_30 8000.00 root CTE:dt2 data:CTE_0 + └─TableReader_27(Probe) 10000.00 root data:TableFullScan_26 + └─TableFullScan_26 10000.00 cop[tikv] table:dt1 keep order:true, stats:pseudo +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_13(Seed Part) 8000.00 root or(not(isnull(test.tpk.c1)), not(isnull(test.tpk.c1))) + └─TableReader_16 10000.00 root data:TableFullScan_15 + └─TableFullScan_15 10000.00 cop[tikv] table:tpk keep order:false, stats:pseudo with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1; c1 c1 c1 1 1 1 2 2 2 3 3 3 +// Test CTE as inner side of Apply +drop table if exists t1, t2; +create table t1(c1 int, c2 int); +insert into t1 values(2, 1); +insert into t1 values(2, 2); +create table t2(c1 int, c2 int); +insert into t2 values(1, 1); +insert into t2 values(3, 2); +explain select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +id estRows task access object operator info +Projection_18 10000.00 root test.t1.c1, test.t1.c2 +└─Apply_20 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#8), if(ne(Column#9, 0), NULL, 1)), or(eq(Column#10, 0), if(isnull(test.t1.c1), NULL, 0))) + ├─TableReader_22(Build) 10000.00 root data:TableFullScan_21 + │ └─TableFullScan_21 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashAgg_23(Probe) 1.00 root funcs:max(Column#13)->Column#8, funcs:sum(Column#14)->Column#9, funcs:count(1)->Column#10 + └─Projection_27 10.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#14 + └─CTEFullScan_25 10.00 root CTE:cte1 data:CTE_0 +CTE_0 10.00 root Non-Recursive CTE +└─Projection_13(Seed Part) 10.00 root test.t2.c1 + └─TableReader_16 10.00 root data:Selection_15 + └─Selection_15 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2) + └─TableFullScan_14 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +c1 c2 +2 1 +// Test semi apply. +insert into t1 values(2, 3); +explain select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +id estRows task access object operator info +Apply_17 10000.00 root CARTESIAN semi join +├─TableReader_19(Build) 10000.00 root data:TableFullScan_18 +│ └─TableFullScan_18 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +└─CTEFullScan_20(Probe) 10.00 root CTE:cte1 data:CTE_0 +CTE_0 10.00 root Non-Recursive CTE +└─Projection_11(Seed Part) 10.00 root test.t2.c1 + └─TableReader_14 10.00 root data:Selection_13 + └─Selection_13 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2) + └─TableFullScan_12 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +c1 c2 +2 1 +2 2 +// Same as above, but test recursive cte. +explain select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1); +id estRows task access object operator info +Projection_26 10000.00 root test.t1.c1, test.t1.c2 +└─Apply_28 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#14), if(ne(Column#15, 0), NULL, 1)), or(eq(Column#16, 0), if(isnull(test.t1.c1), NULL, 0))) + ├─TableReader_30(Build) 10000.00 root data:TableFullScan_29 + │ └─TableFullScan_29 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashAgg_31(Probe) 1.00 root funcs:max(Column#19)->Column#14, funcs:sum(Column#20)->Column#15, funcs:count(1)->Column#16 + └─Projection_35 20.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#20 + └─CTEFullScan_33 20.00 root CTE:cte1 data:CTE_0 +CTE_0 20.00 root Recursive CTE, limit(offset:0, count:1) +├─Projection_19(Seed Part) 10.00 root test.t2.c1 +│ └─TableReader_22 10.00 root data:Selection_21 +│ └─Selection_21 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2) +│ └─TableFullScan_20 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─Projection_23(Recursive Part) 10.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1 + └─CTETable_24 10.00 root Scan on CTE_0 +select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1); +c1 c2 +2 1 +2 3 +explain select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1); +id estRows task access object operator info +Apply_25 10000.00 root CARTESIAN semi join +├─TableReader_27(Build) 10000.00 root data:TableFullScan_26 +│ └─TableFullScan_26 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +└─CTEFullScan_28(Probe) 20.00 root CTE:cte1 data:CTE_0 +CTE_0 20.00 root Recursive CTE, limit(offset:0, count:10) +├─Projection_17(Seed Part) 10.00 root test.t2.c1 +│ └─TableReader_20 10.00 root data:Selection_19 +│ └─Selection_19 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2) +│ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─Projection_21(Recursive Part) 10.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1 + └─CTETable_22 10.00 root Scan on CTE_0 +select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1); +c1 c2 +2 1 +2 2 +// Test correlated col is in recursive part. +explain select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +id estRows task access object operator info +Projection_24 10000.00 root test.t1.c1, test.t1.c2 +└─Apply_26 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#18), if(ne(Column#19, 0), NULL, 1)), or(eq(Column#20, 0), if(isnull(test.t1.c1), NULL, 0))) + ├─TableReader_28(Build) 10000.00 root data:TableFullScan_27 + │ └─TableFullScan_27 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashAgg_29(Probe) 1.00 root funcs:max(Column#23)->Column#18, funcs:sum(Column#24)->Column#19, funcs:count(1)->Column#20 + └─Projection_33 18000.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#24 + └─CTEFullScan_31 18000.00 root CTE:cte1 data:CTE_0 +CTE_0 18000.00 root Recursive CTE +├─TableReader_19(Seed Part) 10000.00 root data:TableFullScan_18 +│ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─Projection_20(Recursive Part) 8000.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1, cast(plus(test.t2.c2, 1), int(11))->test.t2.c2 + └─Selection_21 8000.00 root eq(test.t2.c2, test.t1.c2) + └─CTETable_22 10000.00 root Scan on CTE_0 +select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +c1 c2 +explain select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +id estRows task access object operator info +Apply_23 10000.00 root CARTESIAN semi join +├─TableReader_25(Build) 10000.00 root data:TableFullScan_24 +│ └─TableFullScan_24 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +└─CTEFullScan_26(Probe) 18000.00 root CTE:cte1 data:CTE_0 +CTE_0 18000.00 root Recursive CTE +├─TableReader_17(Seed Part) 10000.00 root data:TableFullScan_16 +│ └─TableFullScan_16 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─Projection_18(Recursive Part) 8000.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1, cast(plus(test.t2.c2, 1), int(11))->test.t2.c2 + └─Selection_19 8000.00 root eq(test.t2.c2, test.t1.c2) + └─CTETable_20 10000.00 root Scan on CTE_0 +select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +c1 c2 +2 1 +2 2 +2 3 diff --git a/cmd/explaintest/r/explain_complex.result b/cmd/explaintest/r/explain_complex.result index b3c79948a142e..43f7c0f915f14 100644 --- a/cmd/explaintest/r/explain_complex.result +++ b/cmd/explaintest/r/explain_complex.result @@ -182,7 +182,7 @@ CREATE TABLE `tbl_009` (`a` int, `b` int); explain format = 'brief' select sum(a) from (select * from tbl_001 union all select * from tbl_002 union all select * from tbl_003 union all select * from tbl_004 union all select * from tbl_005 union all select * from tbl_006 union all select * from tbl_007 union all select * from tbl_008 union all select * from tbl_009) x group by b; id estRows task access object operator info HashAgg 72000.00 root group by:Column#32, funcs:sum(Column#31)->Column#30 -└─Projection 90000.00 root cast(Column#28, decimal(32,0) BINARY)->Column#31, Column#29 +└─Projection 90000.00 root cast(Column#28, decimal(10,0) BINARY)->Column#31, Column#29 └─Union 90000.00 root ├─TableReader 10000.00 root data:TableFullScan │ └─TableFullScan 10000.00 cop[tikv] table:tbl_001 keep order:false, stats:pseudo diff --git a/cmd/explaintest/r/explain_complex_stats.result b/cmd/explaintest/r/explain_complex_stats.result index 4365be0c45336..ed7021dbbfba2 100644 --- a/cmd/explaintest/r/explain_complex_stats.result +++ b/cmd/explaintest/r/explain_complex_stats.result @@ -205,7 +205,7 @@ load stats 's/explain_complex_stats_tbl_009.json'; explain format = 'brief' select sum(a) from (select * from tbl_001 union all select * from tbl_002 union all select * from tbl_003 union all select * from tbl_004 union all select * from tbl_005 union all select * from tbl_006 union all select * from tbl_007 union all select * from tbl_008 union all select * from tbl_009) x group by b; id estRows task access object operator info HashAgg 18000.00 root group by:Column#32, funcs:sum(Column#31)->Column#30 -└─Projection 18000.00 root cast(Column#28, decimal(32,0) BINARY)->Column#31, Column#29 +└─Projection 18000.00 root cast(Column#28, decimal(10,0) BINARY)->Column#31, Column#29 └─Union 18000.00 root ├─TableReader 2000.00 root data:TableFullScan │ └─TableFullScan 2000.00 cop[tikv] table:tbl_001 keep order:false diff --git a/cmd/explaintest/r/explain_cte.result b/cmd/explaintest/r/explain_cte.result index 59fbda4dc20e9..cc8804b4fc077 100644 --- a/cmd/explaintest/r/explain_cte.result +++ b/cmd/explaintest/r/explain_cte.result @@ -67,17 +67,18 @@ CTE_0 2.00 root Recursive CTE └─CTETable_17 1.00 root Scan on CTE_0 explain with cte(a) as (with recursive cte1(a) as (select 1 union select a + 1 from cte1 where a < 10) select * from cte1) select * from cte t1, cte t2; id estRows task access object operator info -HashJoin_24 4.00 root CARTESIAN inner join -├─CTEFullScan_27(Build) 2.00 root CTE:t2 data:CTE_0 -└─CTEFullScan_26(Probe) 2.00 root CTE:t1 data:CTE_0 -CTE_0 2.00 root Non-Recursive CTE -└─CTEFullScan_21(Seed Part) 2.00 root CTE:cte1 data:CTE_1 +HashJoin_26 2.56 root CARTESIAN inner join +├─CTEFullScan_29(Build) 1.60 root CTE:t2 data:CTE_0 +└─CTEFullScan_28(Probe) 1.60 root CTE:t1 data:CTE_0 +CTE_0 1.60 root Non-Recursive CTE +└─Selection_21(Seed Part) 1.60 root 1 + └─CTEFullScan_23 2.00 root CTE:cte1 data:CTE_1 CTE_1 2.00 root Recursive CTE -├─Projection_15(Seed Part) 1.00 root 1->Column#2 -│ └─TableDual_16 1.00 root rows:1 -└─Projection_17(Recursive Part) 0.80 root cast(plus(Column#3, 1), bigint(1) BINARY)->Column#5 - └─Selection_18 0.80 root lt(Column#3, 10) - └─CTETable_19 1.00 root Scan on CTE_1 +├─Projection_16(Seed Part) 1.00 root 1->Column#2 +│ └─TableDual_17 1.00 root rows:1 +└─Projection_18(Recursive Part) 0.80 root cast(plus(Column#3, 1), bigint(1) BINARY)->Column#5 + └─Selection_19 0.80 root lt(Column#3, 10) + └─CTETable_20 1.00 root Scan on CTE_1 explain with recursive cte1(a) as (select 1 union select a+1 from cte1 where a < 10), cte2(a) as (select c2 from t1 union select a+1 from cte2 where a < 10) select * from cte1, cte2; id estRows task access object operator info HashJoin_37 16002.00 root CARTESIAN inner join @@ -97,14 +98,15 @@ CTE_1 8001.00 root Recursive CTE └─CTETable_33 10000.00 root Scan on CTE_1 explain with q(a,b) as (select * from t1) select /*+ merge(q) no_merge(q1) */ * from q, q q1 where q.a=1 and q1.a=2; id estRows task access object operator info -HashJoin_17 64000000.00 root CARTESIAN inner join -├─Selection_21(Build) 8000.00 root eq(test.t1.c1, 2) -│ └─CTEFullScan_22 10000.00 root CTE:q1 data:CTE_0 -└─Selection_19(Probe) 8000.00 root eq(test.t1.c1, 1) - └─CTEFullScan_20 10000.00 root CTE:q data:CTE_0 -CTE_0 10000.00 root Non-Recursive CTE -└─TableReader_12(Seed Part) 10000.00 root data:TableFullScan_11 - └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +HashJoin_19 40960000.00 root CARTESIAN inner join +├─Selection_23(Build) 6400.00 root eq(test.t1.c1, 2) +│ └─CTEFullScan_24 8000.00 root CTE:q1 data:CTE_0 +└─Selection_21(Probe) 6400.00 root eq(test.t1.c1, 1) + └─CTEFullScan_22 8000.00 root CTE:q data:CTE_0 +CTE_0 8000.00 root Non-Recursive CTE +└─Selection_11(Seed Part) 8000.00 root or(eq(test.t1.c1, 1), eq(test.t1.c1, 2)) + └─TableReader_14 10000.00 root data:TableFullScan_13 + └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo explain with recursive cte(a,b) as (select 1, concat('a', 1) union select a+1, concat(b, 1) from cte where a < 5) select * from cte; id estRows task access object operator info CTEFullScan_17 2.00 root CTE:cte data:CTE_0 @@ -202,3 +204,278 @@ id estRows task access object operator info CTEFullScan_18 0.00 root CTE:cte1 data:CTE_0 CTE_0 0.00 root Non-Recursive CTE └─TableDual_16(Seed Part) 0.00 root rows:0 +CREATE TABLE `customer` ( +`c_customer_sk` int(11) NOT NULL, +`c_customer_id` char(16) NOT NULL, +`c_current_cdemo_sk` int(11) DEFAULT NULL, +`c_current_hdemo_sk` int(11) DEFAULT NULL, +`c_current_addr_sk` int(11) DEFAULT NULL, +`c_first_shipto_date_sk` int(11) DEFAULT NULL, +`c_first_sales_date_sk` int(11) DEFAULT NULL, +`c_salutation` char(10) DEFAULT NULL, +`c_first_name` char(20) DEFAULT NULL, +`c_last_name` char(30) DEFAULT NULL, +`c_preferred_cust_flag` char(1) DEFAULT NULL, +`c_birth_day` int(11) DEFAULT NULL, +`c_birth_month` int(11) DEFAULT NULL, +`c_birth_year` int(11) DEFAULT NULL, +`c_birth_country` varchar(20) DEFAULT NULL, +`c_login` char(13) DEFAULT NULL, +`c_email_address` char(50) DEFAULT NULL, +`c_last_review_date_sk` int(11) DEFAULT NULL, +PRIMARY KEY (`c_customer_sk`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `store_sales` ( +`ss_sold_date_sk` int(11) DEFAULT NULL, +`ss_sold_time_sk` int(11) DEFAULT NULL, +`ss_item_sk` int(11) NOT NULL, +`ss_customer_sk` int(11) DEFAULT NULL, +`ss_cdemo_sk` int(11) DEFAULT NULL, +`ss_hdemo_sk` int(11) DEFAULT NULL, +`ss_addr_sk` int(11) DEFAULT NULL, +`ss_store_sk` int(11) DEFAULT NULL, +`ss_promo_sk` int(11) DEFAULT NULL, +`ss_ticket_number` int(11) NOT NULL, +`ss_quantity` int(11) DEFAULT NULL, +`ss_wholesale_cost` decimal(7,2) DEFAULT NULL, +`ss_list_price` decimal(7,2) DEFAULT NULL, +`ss_sales_price` decimal(7,2) DEFAULT NULL, +`ss_ext_discount_amt` decimal(7,2) DEFAULT NULL, +`ss_ext_sales_price` decimal(7,2) DEFAULT NULL, +`ss_ext_wholesale_cost` decimal(7,2) DEFAULT NULL, +`ss_ext_list_price` decimal(7,2) DEFAULT NULL, +`ss_ext_tax` decimal(7,2) DEFAULT NULL, +`ss_coupon_amt` decimal(7,2) DEFAULT NULL, +`ss_net_paid` decimal(7,2) DEFAULT NULL, +`ss_net_paid_inc_tax` decimal(7,2) DEFAULT NULL, +`ss_net_profit` decimal(7,2) DEFAULT NULL, +PRIMARY KEY (`ss_item_sk`,`ss_ticket_number`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `date_dim` ( +`d_date_sk` int(11) NOT NULL, +`d_date_id` char(16) NOT NULL, +`d_date` date DEFAULT NULL, +`d_month_seq` int(11) DEFAULT NULL, +`d_week_seq` int(11) DEFAULT NULL, +`d_quarter_seq` int(11) DEFAULT NULL, +`d_year` int(11) DEFAULT NULL, +`d_dow` int(11) DEFAULT NULL, +`d_moy` int(11) DEFAULT NULL, +`d_dom` int(11) DEFAULT NULL, +`d_qoy` int(11) DEFAULT NULL, +`d_fy_year` int(11) DEFAULT NULL, +`d_fy_quarter_seq` int(11) DEFAULT NULL, +`d_fy_week_seq` int(11) DEFAULT NULL, +`d_day_name` char(9) DEFAULT NULL, +`d_quarter_name` char(6) DEFAULT NULL, +`d_holiday` char(1) DEFAULT NULL, +`d_weekend` char(1) DEFAULT NULL, +`d_following_holiday` char(1) DEFAULT NULL, +`d_first_dom` int(11) DEFAULT NULL, +`d_last_dom` int(11) DEFAULT NULL, +`d_same_day_ly` int(11) DEFAULT NULL, +`d_same_day_lq` int(11) DEFAULT NULL, +`d_current_day` char(1) DEFAULT NULL, +`d_current_week` char(1) DEFAULT NULL, +`d_current_month` char(1) DEFAULT NULL, +`d_current_quarter` char(1) DEFAULT NULL, +`d_current_year` char(1) DEFAULT NULL, +PRIMARY KEY (`d_date_sk`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `web_sales` ( +`ws_sold_date_sk` int(11) DEFAULT NULL, +`ws_sold_time_sk` int(11) DEFAULT NULL, +`ws_ship_date_sk` int(11) DEFAULT NULL, +`ws_item_sk` int(11) NOT NULL, +`ws_bill_customer_sk` int(11) DEFAULT NULL, +`ws_bill_cdemo_sk` int(11) DEFAULT NULL, +`ws_bill_hdemo_sk` int(11) DEFAULT NULL, +`ws_bill_addr_sk` int(11) DEFAULT NULL, +`ws_ship_customer_sk` int(11) DEFAULT NULL, +`ws_ship_cdemo_sk` int(11) DEFAULT NULL, +`ws_ship_hdemo_sk` int(11) DEFAULT NULL, +`ws_ship_addr_sk` int(11) DEFAULT NULL, +`ws_web_page_sk` int(11) DEFAULT NULL, +`ws_web_site_sk` int(11) DEFAULT NULL, +`ws_ship_mode_sk` int(11) DEFAULT NULL, +`ws_warehouse_sk` int(11) DEFAULT NULL, +`ws_promo_sk` int(11) DEFAULT NULL, +`ws_order_number` int(11) NOT NULL, +`ws_quantity` int(11) DEFAULT NULL, +`ws_wholesale_cost` decimal(7,2) DEFAULT NULL, +`ws_list_price` decimal(7,2) DEFAULT NULL, +`ws_sales_price` decimal(7,2) DEFAULT NULL, +`ws_ext_discount_amt` decimal(7,2) DEFAULT NULL, +`ws_ext_sales_price` decimal(7,2) DEFAULT NULL, +`ws_ext_wholesale_cost` decimal(7,2) DEFAULT NULL, +`ws_ext_list_price` decimal(7,2) DEFAULT NULL, +`ws_ext_tax` decimal(7,2) DEFAULT NULL, +`ws_coupon_amt` decimal(7,2) DEFAULT NULL, +`ws_ext_ship_cost` decimal(7,2) DEFAULT NULL, +`ws_net_paid` decimal(7,2) DEFAULT NULL, +`ws_net_paid_inc_tax` decimal(7,2) DEFAULT NULL, +`ws_net_paid_inc_ship` decimal(7,2) DEFAULT NULL, +`ws_net_paid_inc_ship_tax` decimal(7,2) DEFAULT NULL, +`ws_net_profit` decimal(7,2) DEFAULT NULL, +PRIMARY KEY (`ws_item_sk`,`ws_order_number`) /*T![clustered_index] NONCLUSTERED */ +); +desc format='brief' with year_total as ( +select c_customer_id customer_id +,c_first_name customer_first_name +,c_last_name customer_last_name +,c_preferred_cust_flag customer_preferred_cust_flag +,c_birth_country customer_birth_country +,c_login customer_login +,c_email_address customer_email_address +,d_year dyear +,sum(ss_ext_list_price-ss_ext_discount_amt) year_total +,'s' sale_type +from customer +,store_sales +,date_dim +where c_customer_sk = ss_customer_sk +and ss_sold_date_sk = d_date_sk +group by c_customer_id +,c_first_name +,c_last_name +,c_preferred_cust_flag +,c_birth_country +,c_login +,c_email_address +,d_year +union all +select c_customer_id customer_id +,c_first_name customer_first_name +,c_last_name customer_last_name +,c_preferred_cust_flag customer_preferred_cust_flag +,c_birth_country customer_birth_country +,c_login customer_login +,c_email_address customer_email_address +,d_year dyear +,sum(ws_ext_list_price-ws_ext_discount_amt) year_total +,'w' sale_type +from customer +,web_sales +,date_dim +where c_customer_sk = ws_bill_customer_sk +and ws_sold_date_sk = d_date_sk +group by c_customer_id +,c_first_name +,c_last_name +,c_preferred_cust_flag +,c_birth_country +,c_login +,c_email_address +,d_year +) +select +t_s_secyear.customer_id +,t_s_secyear.customer_first_name +,t_s_secyear.customer_last_name +,t_s_secyear.customer_email_address +from year_total t_s_firstyear +,year_total t_s_secyear +,year_total t_w_firstyear +,year_total t_w_secyear +where t_s_secyear.customer_id = t_s_firstyear.customer_id +and t_s_firstyear.customer_id = t_w_secyear.customer_id +and t_s_firstyear.customer_id = t_w_firstyear.customer_id +and t_s_firstyear.sale_type = 's' +and t_w_firstyear.sale_type = 'w' +and t_s_secyear.sale_type = 's' +and t_w_secyear.sale_type = 'w' +and t_s_firstyear.dyear = 2001 +and t_s_secyear.dyear = 2001+1 +and t_w_firstyear.dyear = 2001 +and t_w_secyear.dyear = 2001+1 +and t_s_firstyear.year_total > 0 +and t_w_firstyear.year_total > 0 +and case when t_w_firstyear.year_total > 0 then t_w_secyear.year_total / t_w_firstyear.year_total else 0.0 end +> case when t_s_firstyear.year_total > 0 then t_s_secyear.year_total / t_s_firstyear.year_total else 0.0 end +order by t_s_secyear.customer_id +,t_s_secyear.customer_first_name +,t_s_secyear.customer_last_name +,t_s_secyear.customer_email_address +limit 100; +id estRows task access object operator info +TopN 40.00 root Column#180, Column#181, Column#182, Column#186, offset:0, count:100 +└─HashJoin 40.00 root inner join, equal:[eq(Column#170, Column#200)], other cond:gt(case(gt(Column#198, 0), div(Column#208, Column#198), 0.0), case(gt(Column#178, 0), div(Column#188, Column#178), 0.0)) + ├─Selection(Build) 40.00 root eq(Column#207, 2002), eq(Column#209, "w"), not(isnull(Column#200)) + │ └─CTEFullScan 50.00 root CTE:t_w_secyear data:CTE_0 + └─HashJoin(Probe) 40.00 root inner join, equal:[eq(Column#170, Column#190)] + ├─Selection(Build) 40.00 root eq(Column#197, 2001), eq(Column#199, "w"), gt(Column#198, 0), not(isnull(Column#190)) + │ └─CTEFullScan 50.00 root CTE:t_w_firstyear data:CTE_0 + └─HashJoin(Probe) 40.00 root inner join, equal:[eq(Column#170, Column#180)] + ├─Selection(Build) 40.00 root eq(Column#187, 2002), eq(Column#189, "s"), not(isnull(Column#180)) + │ └─CTEFullScan 50.00 root CTE:t_s_secyear data:CTE_0 + └─Selection(Probe) 40.00 root eq(Column#177, 2001), eq(Column#179, "s"), gt(Column#178, 0), not(isnull(Column#170)) + └─CTEFullScan 50.00 root CTE:t_s_firstyear data:CTE_0 +CTE_0 50.00 root Non-Recursive CTE +└─Union(Seed Part) 50.00 root + ├─Projection 25.00 root test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year, Column#73, s->Column#169 + │ └─Selection 25.00 root or(or(and(1, and(eq(test.date_dim.d_year, 2001), gt(Column#73, 0))), and(1, eq(test.date_dim.d_year, 2002))), 0) + │ └─HashAgg 31.25 root group by:Column#233, Column#234, Column#235, Column#236, Column#237, Column#238, Column#239, Column#240, funcs:sum(Column#224)->Column#73, funcs:firstrow(Column#225)->test.customer.c_customer_id, funcs:firstrow(Column#226)->test.customer.c_first_name, funcs:firstrow(Column#227)->test.customer.c_last_name, funcs:firstrow(Column#228)->test.customer.c_preferred_cust_flag, funcs:firstrow(Column#229)->test.customer.c_birth_country, funcs:firstrow(Column#230)->test.customer.c_login, funcs:firstrow(Column#231)->test.customer.c_email_address, funcs:firstrow(Column#232)->test.date_dim.d_year + │ └─Projection 31.25 root minus(test.store_sales.ss_ext_list_price, test.store_sales.ss_ext_discount_amt)->Column#224, test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year, test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year + │ └─Projection 31.25 root test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.store_sales.ss_ext_discount_amt, test.store_sales.ss_ext_list_price, test.date_dim.d_year + │ └─IndexJoin 31.25 root inner join, inner:IndexLookUp, outer key:test.store_sales.ss_customer_sk, inner key:test.customer.c_customer_sk, equal cond:eq(test.store_sales.ss_customer_sk, test.customer.c_customer_sk) + │ ├─HashJoin(Build) 25.00 root inner join, equal:[eq(test.date_dim.d_date_sk, test.store_sales.ss_sold_date_sk)] + │ │ ├─TableReader(Build) 20.00 root data:Selection + │ │ │ └─Selection 20.00 cop[tikv] or(and(1, eq(test.date_dim.d_year, 2001)), or(and(1, eq(test.date_dim.d_year, 2002)), 0)) + │ │ │ └─TableFullScan 10000.00 cop[tikv] table:date_dim keep order:false, stats:pseudo + │ │ └─TableReader(Probe) 9980.01 root data:Selection + │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.store_sales.ss_customer_sk)), not(isnull(test.store_sales.ss_sold_date_sk)) + │ │ └─TableFullScan 10000.00 cop[tikv] table:store_sales keep order:false, stats:pseudo + │ └─IndexLookUp(Probe) 1.00 root + │ ├─IndexRangeScan(Build) 1.00 cop[tikv] table:customer, index:PRIMARY(c_customer_sk) range: decided by [eq(test.customer.c_customer_sk, test.store_sales.ss_customer_sk)], keep order:false, stats:pseudo + │ └─TableRowIDScan(Probe) 1.00 cop[tikv] table:customer keep order:false, stats:pseudo + └─Projection 25.00 root test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year, Column#158, w->Column#169 + └─Selection 25.00 root or(0, or(and(1, and(eq(test.date_dim.d_year, 2001), gt(Column#158, 0))), and(1, eq(test.date_dim.d_year, 2002)))) + └─HashAgg 31.25 root group by:Column#250, Column#251, Column#252, Column#253, Column#254, Column#255, Column#256, Column#257, funcs:sum(Column#241)->Column#158, funcs:firstrow(Column#242)->test.customer.c_customer_id, funcs:firstrow(Column#243)->test.customer.c_first_name, funcs:firstrow(Column#244)->test.customer.c_last_name, funcs:firstrow(Column#245)->test.customer.c_preferred_cust_flag, funcs:firstrow(Column#246)->test.customer.c_birth_country, funcs:firstrow(Column#247)->test.customer.c_login, funcs:firstrow(Column#248)->test.customer.c_email_address, funcs:firstrow(Column#249)->test.date_dim.d_year + └─Projection 31.25 root minus(test.web_sales.ws_ext_list_price, test.web_sales.ws_ext_discount_amt)->Column#241, test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year, test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.date_dim.d_year + └─Projection 31.25 root test.customer.c_customer_id, test.customer.c_first_name, test.customer.c_last_name, test.customer.c_preferred_cust_flag, test.customer.c_birth_country, test.customer.c_login, test.customer.c_email_address, test.web_sales.ws_ext_discount_amt, test.web_sales.ws_ext_list_price, test.date_dim.d_year + └─IndexJoin 31.25 root inner join, inner:IndexLookUp, outer key:test.web_sales.ws_bill_customer_sk, inner key:test.customer.c_customer_sk, equal cond:eq(test.web_sales.ws_bill_customer_sk, test.customer.c_customer_sk) + ├─HashJoin(Build) 25.00 root inner join, equal:[eq(test.date_dim.d_date_sk, test.web_sales.ws_sold_date_sk)] + │ ├─TableReader(Build) 20.00 root data:Selection + │ │ └─Selection 20.00 cop[tikv] or(0, or(and(1, eq(test.date_dim.d_year, 2001)), and(1, eq(test.date_dim.d_year, 2002)))) + │ │ └─TableFullScan 10000.00 cop[tikv] table:date_dim keep order:false, stats:pseudo + │ └─TableReader(Probe) 9980.01 root data:Selection + │ └─Selection 9980.01 cop[tikv] not(isnull(test.web_sales.ws_bill_customer_sk)), not(isnull(test.web_sales.ws_sold_date_sk)) + │ └─TableFullScan 10000.00 cop[tikv] table:web_sales keep order:false, stats:pseudo + └─IndexLookUp(Probe) 1.00 root + ├─IndexRangeScan(Build) 1.00 cop[tikv] table:customer, index:PRIMARY(c_customer_sk) range: decided by [eq(test.customer.c_customer_sk, test.web_sales.ws_bill_customer_sk)], keep order:false, stats:pseudo + └─TableRowIDScan(Probe) 1.00 cop[tikv] table:customer keep order:false, stats:pseudo +drop table if exists t1; +create table t1 (id int, bench_type varchar(10),version varchar(10),tps int(20)); +insert into t1 (id,bench_type,version,tps) values (1,'sysbench','5.4.0',1111111); +insert into t1 (id,bench_type,version,tps) values (2,'sysbench','6.0.0',222222); +with all_data as +(select * from t1 +),version1 as (select * from all_data where version ='5.4.0' +),version2 as(select * from all_data where version ='6.0.0') +select v1.tps v1_tps,v2.tps v2_tps +from version1 v1, version2 v2 +where v1.bench_type =v2.bench_type; +v1_tps v2_tps +1111111 222222 +desc format='brief' with all_data as +(select * from t1 +),version1 as (select * from all_data where version ='5.4.0' +),version2 as(select * from all_data where version ='6.0.0') +select v1.tps v1_tps,v2.tps v2_tps +from version1 v1, version2 v2 +where v1.bench_type =v2.bench_type; +id estRows task access object operator info +HashJoin 8000.00 root inner join, equal:[eq(test.t1.bench_type, test.t1.bench_type)] +├─Selection(Build) 6400.00 root not(isnull(test.t1.bench_type)) +│ └─CTEFullScan 8000.00 root CTE:v2 data:CTE_2 +└─Selection(Probe) 6400.00 root not(isnull(test.t1.bench_type)) + └─CTEFullScan 8000.00 root CTE:v1 data:CTE_1 +CTE_2 8000.00 root Non-Recursive CTE +└─Selection(Seed Part) 8000.00 root eq(test.t1.version, "6.0.0"), not(isnull(test.t1.bench_type)) + └─CTEFullScan 10000.00 root CTE:all_data data:CTE_0 +CTE_1 8000.00 root Non-Recursive CTE +└─Selection(Seed Part) 8000.00 root eq(test.t1.version, "5.4.0"), not(isnull(test.t1.bench_type)) + └─CTEFullScan 10000.00 root CTE:all_data data:CTE_0 +CTE_0 10000.00 root Non-Recursive CTE +└─TableReader(Seed Part) 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo diff --git a/cmd/explaintest/r/explain_easy.result b/cmd/explaintest/r/explain_easy.result index 2eec1954d46df..7cc05e4d9702b 100644 --- a/cmd/explaintest/r/explain_easy.result +++ b/cmd/explaintest/r/explain_easy.result @@ -91,7 +91,7 @@ Selection 0.33 root gt(test.t1.c2, 1) explain format = 'brief' select sum(t1.c1 in (select c1 from t2)) from t1; id estRows task access object operator info StreamAgg 1.00 root funcs:sum(Column#13)->Column#11 -└─Projection 10000.00 root cast(Column#10, decimal(65,0) BINARY)->Column#13 +└─Projection 10000.00 root cast(Column#10, decimal(3,0) BINARY)->Column#13 └─HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(test.t1.c1, test.t2.c1) ├─IndexReader(Build) 10000.00 root index:IndexFullScan │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:false, stats:pseudo @@ -118,6 +118,12 @@ Projection 12500.00 root ifnull(Column#10, 0)->Column#10 explain format = 'brief' select * from information_schema.columns; id estRows task access object operator info MemTableScan 10000.00 root table:COLUMNS +explain format = 'brief' select * from information_schema.columns where table_name = 'T1'; +id estRows task access object operator info +MemTableScan 10000.00 root table:COLUMNS table_name:["t1"] +explain format = 'brief' select * from information_schema.columns where table_schema = 'TEST' and table_name = 'T1' and column_name = 'c1'; +id estRows task access object operator info +MemTableScan 10000.00 root table:COLUMNS table_schema:["test"], table_name:["t1"], column_name:["c1"] explain format = 'brief' select c2 = (select c2 from t2 where t1.c1 = t2.c1 order by c1 limit 1) from t1; id estRows task access object operator info Projection 10000.00 root eq(test.t1.c2, test.t2.c2)->Column#11 @@ -225,7 +231,7 @@ set @@session.tidb_opt_insubq_to_join_and_agg=0; explain format = 'brief' select sum(t1.c1 in (select c1 from t2)) from t1; id estRows task access object operator info StreamAgg 1.00 root funcs:sum(Column#13)->Column#11 -└─Projection 10000.00 root cast(Column#10, decimal(65,0) BINARY)->Column#13 +└─Projection 10000.00 root cast(Column#10, decimal(3,0) BINARY)->Column#13 └─HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(test.t1.c1, test.t2.c1) ├─IndexReader(Build) 10000.00 root index:IndexFullScan │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:false, stats:pseudo @@ -241,7 +247,7 @@ HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(1, test.t2 explain format = 'brief' select sum(6 in (select c2 from t2)) from t1; id estRows task access object operator info StreamAgg 1.00 root funcs:sum(Column#13)->Column#11 -└─Projection 10000.00 root cast(Column#10, decimal(65,0) BINARY)->Column#13 +└─Projection 10000.00 root cast(Column#10, decimal(3,0) BINARY)->Column#13 └─HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(6, test.t2.c2) ├─TableReader(Build) 10000.00 root data:TableFullScan │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo @@ -427,10 +433,10 @@ IndexReader 10.00 root index:IndexRangeScan └─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(a, b) range:[1,1], keep order:false, stats:pseudo explain format = 'brief' select * from t where a = 1 and a = 2; id estRows task access object operator info -TableDual 8000.00 root rows:0 +TableDual 0.00 root rows:0 explain format = 'brief' select * from t where b = 1 and b = 2; id estRows task access object operator info -TableDual 8000.00 root rows:0 +TableDual 0.00 root rows:0 explain format = 'brief' select * from t t1 join t t2 where t1.b = t2.b and t2.b is null; id estRows task access object operator info Projection 0.00 root test.t.a, test.t.b, test.t.a, test.t.b @@ -452,7 +458,7 @@ drop table if exists t; create table t(a bigint primary key); explain format = 'brief' select * from t where a = 1 and a = 2; id estRows task access object operator info -TableDual 8000.00 root rows:0 +TableDual 0.00 root rows:0 explain format = 'brief' select null or a > 1 from t; id estRows task access object operator info Projection 10000.00 root or(, gt(test.t.a, 1))->Column#2 @@ -500,17 +506,17 @@ PRIMARY KEY (`id`) explain format = 'brief' SELECT COUNT(1) FROM (SELECT COALESCE(b.region_name, 'ä¸è¯¦') region_name, SUM(a.registration_num) registration_num FROM (SELECT stat_date, show_date, region_id, 0 registration_num FROM test01 WHERE period = 1 AND stat_date >= 20191202 AND stat_date <= 20191202 UNION ALL SELECT stat_date, show_date, region_id, registration_num registration_num FROM test01 WHERE period = 1 AND stat_date >= 20191202 AND stat_date <= 20191202) a LEFT JOIN test02 b ON a.region_id = b.id WHERE registration_num > 0 AND a.stat_date >= '20191202' AND a.stat_date <= '20191202' GROUP BY a.stat_date , a.show_date , COALESCE(b.region_name, 'ä¸è¯¦') ) JLS; id estRows task access object operator info StreamAgg 1.00 root funcs:count(1)->Column#22 -└─HashAgg 8000.00 root group by:Column#32, Column#33, Column#34, funcs:count(1)->Column#31 - └─Projection 10000.01 root Column#14, Column#15, coalesce(test.test02.region_name, ä¸è¯¦)->Column#34 - └─HashJoin 10000.01 root left outer join, equal:[eq(Column#16, test.test02.id)] - ├─TableReader(Build) 10000.00 root data:TableFullScan - │ └─TableFullScan 10000.00 cop[tikv] table:b keep order:false, stats:pseudo - └─Union(Probe) 8000.01 root - ├─TableDual 8000.00 root rows:0 - └─Projection 0.01 root test.test01.stat_date, test.test01.show_date, test.test01.region_id - └─TableReader 0.01 root data:Selection - └─Selection 0.01 cop[tikv] eq(test.test01.period, 1), ge(test.test01.stat_date, 20191202), gt(cast(test.test01.registration_num, bigint(20) BINARY), 0), le(test.test01.stat_date, 20191202) - └─TableFullScan 10000.00 cop[tikv] table:test01 keep order:false, stats:pseudo +└─HashAgg 1.00 root group by:Column#32, Column#33, Column#34, funcs:count(1)->Column#31 + └─Projection 0.01 root Column#14, Column#15, coalesce(test.test02.region_name, ä¸è¯¦)->Column#34 + └─IndexJoin 0.01 root left outer join, inner:TableReader, outer key:Column#16, inner key:test.test02.id, equal cond:eq(Column#16, test.test02.id) + ├─Union(Build) 0.01 root + │ ├─TableDual 0.00 root rows:0 + │ └─Projection 0.01 root test.test01.stat_date, test.test01.show_date, test.test01.region_id + │ └─TableReader 0.01 root data:Selection + │ └─Selection 0.01 cop[tikv] eq(test.test01.period, 1), ge(test.test01.stat_date, 20191202), gt(cast(test.test01.registration_num, bigint(20) BINARY), 0), le(test.test01.stat_date, 20191202) + │ └─TableFullScan 10000.00 cop[tikv] table:test01 keep order:false, stats:pseudo + └─TableReader(Probe) 1.00 root data:TableRangeScan + └─TableRangeScan 1.00 cop[tikv] table:b range: decided by [Column#16], keep order:false, stats:pseudo drop table if exists t; create table t(a int, nb int not null, nc int not null); explain format = 'brief' select ifnull(a, 0) from t; @@ -809,19 +815,19 @@ Projection 1.00 root Column#7 └─HashAgg(Probe) 1.00 root funcs:sum(Column#12)->Column#7 └─HashJoin 1.00 root CARTESIAN left outer join ├─HashAgg(Build) 1.00 root group by:1, funcs:sum(Column#14)->Column#12 - │ └─Projection 1.00 root cast(Column#6, decimal(42,0) BINARY)->Column#14 + │ └─Projection 1.00 root cast(Column#6, decimal(20,0) BINARY)->Column#14 │ └─MaxOneRow 1.00 root │ └─Projection 1.00 root Column#5 │ └─TableDual 1.00 root rows:1 └─TableDual(Probe) 1.00 root rows:1 explain format = 'brief' select count(a) from t group by b order by (select count(a)); id estRows task access object operator info -Sort 8000.00 root Column#4 +Sort 8000.00 root Column#5 └─HashJoin 8000.00 root CARTESIAN left outer join ├─TableDual(Build) 1.00 root rows:1 - └─HashAgg(Probe) 8000.00 root group by:test.t.b, funcs:count(Column#8)->Column#4 + └─HashAgg(Probe) 8000.00 root group by:test.t.b, funcs:count(Column#9)->Column#5 └─TableReader 8000.00 root data:HashAgg - └─HashAgg 8000.00 cop[tikv] group by:test.t.b, funcs:count(test.t.a)->Column#8 + └─HashAgg 8000.00 cop[tikv] group by:test.t.b, funcs:count(test.t.a)->Column#9 └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select (select sum(count(a))) from t; id estRows task access object operator info @@ -831,18 +837,136 @@ Projection 1.00 root Column#5 │ └─TableReader 10000.00 root data:TableFullScan │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo └─StreamAgg(Probe) 1.00 root funcs:sum(Column#7)->Column#5 - └─Projection 1.00 root cast(Column#4, decimal(42,0) BINARY)->Column#7 + └─Projection 1.00 root cast(Column#4, decimal(20,0) BINARY)->Column#7 └─TableDual 1.00 root rows:1 explain format = 'brief' select sum(a), (select sum(a)), count(a) from t group by b order by (select count(a)); id estRows task access object operator info -Projection 8000.00 root Column#4, Column#4, Column#5 -└─Sort 8000.00 root Column#5 +Projection 8000.00 root Column#5, Column#5, Column#6 +└─Sort 8000.00 root Column#6 └─HashJoin 8000.00 root CARTESIAN left outer join ├─TableDual(Build) 1.00 root rows:1 └─HashJoin(Probe) 8000.00 root CARTESIAN left outer join ├─TableDual(Build) 1.00 root rows:1 - └─HashAgg(Probe) 8000.00 root group by:test.t.b, funcs:sum(Column#13)->Column#4, funcs:count(Column#14)->Column#5 + └─HashAgg(Probe) 8000.00 root group by:test.t.b, funcs:sum(Column#14)->Column#5, funcs:count(Column#15)->Column#6 └─TableReader 8000.00 root data:HashAgg - └─HashAgg 8000.00 cop[tikv] group by:test.t.b, funcs:sum(test.t.a)->Column#13, funcs:count(test.t.a)->Column#14 + └─HashAgg 8000.00 cop[tikv] group by:test.t.b, funcs:sum(test.t.a)->Column#14, funcs:count(test.t.a)->Column#15 └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo drop table if exists t; +create table t(a tinyint, b smallint, c mediumint, d int, e bigint); +insert into mysql.opt_rule_blacklist VALUES("aggregation_push_down"); +admin reload opt_rule_blacklist; + +explain format = 'brief' select sum(t1.a) from t t1 join t t2 on t1.a=t2.a; +id estRows task access object operator info +StreamAgg 1.00 root funcs:sum(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.a, decimal(3,0) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.a)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select sum(t1.b) from t t1 join t t2 on t1.b=t2.b; +id estRows task access object operator info +StreamAgg 1.00 root funcs:sum(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.b, decimal(5,0) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.b, test.t.b)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.b)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.b)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select sum(t1.c) from t t1 join t t2 on t1.c=t2.c; +id estRows task access object operator info +StreamAgg 1.00 root funcs:sum(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.c, decimal(8,0) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.c, test.t.c)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.c)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.c)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select sum(t1.d) from t t1 join t t2 on t1.d=t2.d; +id estRows task access object operator info +StreamAgg 1.00 root funcs:sum(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.d, decimal(10,0) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.d, test.t.d)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.d)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.d)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select sum(t1.e) from t t1 join t t2 on t1.e=t2.e; +id estRows task access object operator info +StreamAgg 1.00 root funcs:sum(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.e, decimal(20,0) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.e, test.t.e)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.e)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.e)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select avg(t1.a) from t t1 join t t2 on t1.a=t2.a; +id estRows task access object operator info +StreamAgg 1.00 root funcs:avg(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.a, decimal(8,4) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.a)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select avg(t1.b) from t t1 join t t2 on t1.b=t2.b; +id estRows task access object operator info +StreamAgg 1.00 root funcs:avg(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.b, decimal(10,4) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.b, test.t.b)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.b)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.b)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select avg(t1.c) from t t1 join t t2 on t1.c=t2.c; +id estRows task access object operator info +StreamAgg 1.00 root funcs:avg(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.c, decimal(13,4) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.c, test.t.c)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.c)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.c)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select avg(t1.d) from t t1 join t t2 on t1.d=t2.d; +id estRows task access object operator info +StreamAgg 1.00 root funcs:avg(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.d, decimal(15,4) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.d, test.t.d)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.d)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.d)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +explain format = 'brief' select avg(t1.e) from t t1 join t t2 on t1.e=t2.e; +id estRows task access object operator info +StreamAgg 1.00 root funcs:avg(Column#14)->Column#13 +└─Projection 12487.50 root cast(test.t.e, decimal(24,4) BINARY)->Column#14 + └─HashJoin 12487.50 root inner join, equal:[eq(test.t.e, test.t.e)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(test.t.e)) + │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t.e)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +drop table if exists t; +delete from mysql.opt_rule_blacklist where name="aggregation_push_down"; +admin reload opt_rule_blacklist; + diff --git a/cmd/explaintest/r/explain_generate_column_substitute.result b/cmd/explaintest/r/explain_generate_column_substitute.result index 5162adb37f49c..37976d6005dca 100644 --- a/cmd/explaintest/r/explain_generate_column_substitute.result +++ b/cmd/explaintest/r/explain_generate_column_substitute.result @@ -1,3 +1,4 @@ +set names utf8mb4; use test; drop table if exists t; create table t(a int, b real, c bigint as ((a+1)) virtual, e real as ((b+a))); @@ -522,7 +523,7 @@ a b select @@tidb_allow_function_for_expression_index; @@tidb_allow_function_for_expression_index -lower, md5, reverse, upper, vitess_hash +lower, md5, reverse, tidb_shard, upper, vitess_hash CREATE TABLE `PK_S_MULTI_30_tmp` ( `COL1` double NOT NULL, `COL2` double NOT NULL, @@ -570,3 +571,66 @@ a select * from t004 ignore index (eidx) where timestampadd(microsecond, 1, a) = timestampadd(microsecond, 1, '2021-08-20'); a 2021-08-20 +drop table if exists t; +create table t ( c_int int, c_str varchar(40) character set utf8 collate utf8_general_ci, primary key(c_int, c_str(9)) clustered, key idx((reverse(c_str)))); +replace into t (c_int, c_str) values (9, "beautiful hermann"); +select reverse(c_str) from t use index(idx); +reverse(c_str) +nnamreh lufituaeb +drop table if exists t1; +drop table if exists t2; +create table t1 (c_int int, c_str varchar(40) character set utf8 collate utf8_general_ci, c_datetime datetime, c_timestamp timestamp, c_double double, c_decimal decimal(12, 6), c_enum enum('blue','green','red','yellow','white','orange','purple'), primary key (c_datetime) , key(c_int) , key(c_datetime) , key((c_int + 1)), key((c_int -1)), key((lower(c_str))), key((md5(c_str))), key((reverse(c_str))), key((upper(c_str)))); +create table t2 like t1; +insert into t1 values(11, 'loving grothendieck', '2020-02-02 19:25:49', '2020-03-27 15:17:14', 3.269, 1.851000, 'white' ); +insert into t1 values(11, 'quirky kapitsa' , '2020-06-21 03:55:31', '2020-02-29 17:02:48', 6.94, 1.851000, 'yellow'); +insert into t1 values( 7, 'boring bouman' , '2020-05-10 00:01:04', '2020-02-01 20:18:00', 84.096168, 6.996000, 'white' ); +insert into t2 values( 11, 'wizardly antonelli', '2020-01-30 17:27:17', '2020-01-01 10:05:31', 6.886177, 6.332000, 'green' ); +insert into t2 values( 2, 'angry kapitsa' , '2020-03-30 05:09:44', '2020-02-15 00:36:52', 95.798378, 3.118000, 'blue' ); +insert into t2 values( 7, 'dreamy shamir' , '2020-05-28 14:13:42', '2020-06-02 07:23:22', 26.623227, 3.105000, 'orange'); +begin; +delete from t2 where c_decimal > c_double/2 order by c_int, c_str, c_double, c_decimal limit 1; +desc format='brief' select t2.c_enum from t2,t1 where t1.c_int - 1 = t2.c_int - 1 order by t2.c_enum; +id estRows task access object operator info +Sort 12487.50 root test.t2.c_enum +└─HashJoin 12487.50 root inner join, equal:[eq(minus(test.t1.c_int, 1), minus(test.t2.c_int, 1))] + ├─IndexReader(Build) 9990.00 root index:IndexFullScan + │ └─IndexFullScan 9990.00 cop[tikv] table:t1, index:expression_index_2(`c_int` - 1) keep order:false, stats:pseudo + └─Projection(Probe) 10000.00 root test.t2.c_enum, minus(test.t2.c_int, 1), test.t2._tidb_rowid + └─UnionScan 8000.00 root not(isnull(minus(test.t2.c_int, 1))) + └─Selection 8000.00 root not(isnull(minus(test.t2.c_int, 1))) + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo +select t2.c_enum from t2,t1 where t1.c_int - 1 = t2.c_int - 1 order by t2.c_enum; +c_enum +orange +drop table t1, t2; +drop table t; +drop table if exists t1,t2; +create table t1 (c_int int, c_str varchar(40) ,primary key (c_int) , key(c_str(36)) , key((c_int + 1))) partition by hash (c_int) partitions 4 ; +create table t2 like t1 ; +insert into t1 values (1, 'sleepy kowalevski'); +insert into t2 values (3, 'unruffled chaplygin'); +select (select t2.c_str from t2 where t2.c_int + 1 = 4 order by t2.c_str) x from t1; +x +unruffled chaplygin +select (select t2.c_str from t2 where t2.c_int = 3 order by t2.c_str) x from t1; +x +unruffled chaplygin +drop table t1,t2; +drop table if exists t1, t2; +create table t1 (c_int int, c_decimal decimal(12, 6), primary key (c_int) nonclustered,key((c_int + 1))) ; +create table t2 like t1; +explain format = 'brief' select /*+ agg_to_cop() */ * from t1 where c_decimal in (select c_decimal from t2 where t2.c_int + 1 = 8 + 1); +id estRows task access object operator info +HashJoin 9.99 root inner join, equal:[eq(test.t2.c_decimal, test.t1.c_decimal)] +├─HashAgg(Build) 7.99 root group by:test.t2.c_decimal, funcs:firstrow(test.t2.c_decimal)->test.t2.c_decimal +│ └─IndexLookUp 7.99 root +│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t2, index:expression_index(`c_int` + 1) range:[9,9], keep order:false, stats:pseudo +│ └─HashAgg(Probe) 7.99 cop[tikv] group by:test.t2.c_decimal, +│ └─Selection 9.99 cop[tikv] not(isnull(test.t2.c_decimal)) +│ └─TableRowIDScan 10.00 cop[tikv] table:t2 keep order:false, stats:pseudo +└─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(test.t1.c_decimal)) + └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo +drop table t1; +drop table t2; diff --git a/cmd/explaintest/r/explain_indexmerge.result b/cmd/explaintest/r/explain_indexmerge.result index 83bc89a593e7c..40e0cb4a1159d 100644 --- a/cmd/explaintest/r/explain_indexmerge.result +++ b/cmd/explaintest/r/explain_indexmerge.result @@ -6,19 +6,23 @@ create index td on t (d); load stats 's/explain_indexmerge_stats_t.json'; explain format = 'brief' select * from t where a < 50 or b < 50; id estRows task access object operator info -TableReader 98.00 root data:Selection -└─Selection 98.00 cop[tikv] or(lt(test.t.a, 50), lt(test.t.b, 50)) - └─TableFullScan 5000000.00 cop[tikv] table:t keep order:false +IndexMerge 98.00 root +├─TableRangeScan(Build) 49.00 cop[tikv] table:t range:[-inf,50), keep order:false +├─IndexRangeScan(Build) 49.00 cop[tikv] table:t, index:tb(b) range:[-inf,50), keep order:false +└─TableRowIDScan(Probe) 98.00 cop[tikv] table:t keep order:false explain format = 'brief' select * from t where (a < 50 or b < 50) and f > 100; id estRows task access object operator info -TableReader 98.00 root data:Selection -└─Selection 98.00 cop[tikv] gt(test.t.f, 100), or(lt(test.t.a, 50), lt(test.t.b, 50)) - └─TableFullScan 5000000.00 cop[tikv] table:t keep order:false +IndexMerge 98.00 root +├─TableRangeScan(Build) 49.00 cop[tikv] table:t range:[-inf,50), keep order:false +├─IndexRangeScan(Build) 49.00 cop[tikv] table:t, index:tb(b) range:[-inf,50), keep order:false +└─Selection(Probe) 98.00 cop[tikv] gt(test.t.f, 100) + └─TableRowIDScan 98.00 cop[tikv] table:t keep order:false explain format = 'brief' select * from t where b < 50 or c < 50; id estRows task access object operator info -TableReader 98.00 root data:Selection -└─Selection 98.00 cop[tikv] or(lt(test.t.b, 50), lt(test.t.c, 50)) - └─TableFullScan 5000000.00 cop[tikv] table:t keep order:false +IndexMerge 98.00 root +├─IndexRangeScan(Build) 49.00 cop[tikv] table:t, index:tb(b) range:[-inf,50), keep order:false +├─IndexRangeScan(Build) 49.00 cop[tikv] table:t, index:tc(c) range:[-inf,50), keep order:false +└─TableRowIDScan(Probe) 98.00 cop[tikv] table:t keep order:false set session tidb_enable_index_merge = on; explain format = 'brief' select * from t where a < 50 or b < 50; id estRows task access object operator info diff --git a/cmd/explaintest/r/explain_shard_index.result b/cmd/explaintest/r/explain_shard_index.result new file mode 100644 index 0000000000000..79276d331286c --- /dev/null +++ b/cmd/explaintest/r/explain_shard_index.result @@ -0,0 +1,73 @@ +use test; +drop table if exists test3, test5; +create table test3(id int primary key clustered, a int, b int, unique key uk_expr((tidb_shard(a)),a)); +create table test5(id int primary key clustered, a int, b int, unique key uk_expr((tidb_shard(a)),a,b)); +explain format=brief select * from test3 where a=100; +id estRows task access object operator info +Projection 1.00 root test.test3.id, test.test3.a, test.test3.b +└─Point_Get 1.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) +explain format=brief select * from test3 where a=100 and (b = 100 or b = 200); +id estRows task access object operator info +Projection 0.00 root test.test3.id, test.test3.a, test.test3.b +└─Selection 0.00 root or(eq(test.test3.b, 100), eq(test.test3.b, 200)) + └─Point_Get 1.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) +explain format=brief select * from test3 where tidb_shard(a) = 8; +id estRows task access object operator info +Projection 10.00 root test.test3.id, test.test3.a, test.test3.b +└─IndexLookUp 10.00 root + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:test3, index:uk_expr(tidb_shard(`a`), a) range:[8,8], keep order:false, stats:pseudo + └─TableRowIDScan(Probe) 10.00 cop[tikv] table:test3 keep order:false, stats:pseudo +explain format=brief select * from test3 where a=100 or b = 200; +id estRows task access object operator info +Projection 8000.00 root test.test3.id, test.test3.a, test.test3.b +└─Selection 8000.00 root or(and(eq(tidb_shard(test.test3.a), 8), eq(test.test3.a, 100)), eq(test.test3.b, 200)) + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:test3 keep order:false, stats:pseudo +explain format=brief select * from test3 where a=100 or a = 300; +id estRows task access object operator info +Projection 2.00 root test.test3.id, test.test3.a, test.test3.b +└─Batch_Point_Get 2.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) keep order:false, desc:false +explain format=brief select * from test3 where a=100 or a = 300 or a > 997; +id estRows task access object operator info +Projection 8000.00 root test.test3.id, test.test3.a, test.test3.b +└─Selection 8000.00 root or(and(eq(tidb_shard(test.test3.a), 8), eq(test.test3.a, 100)), or(and(eq(tidb_shard(test.test3.a), 227), eq(test.test3.a, 300)), gt(test.test3.a, 997))) + └─TableReader 10000.00 root data:TableFullScan + └─TableFullScan 10000.00 cop[tikv] table:test3 keep order:false, stats:pseudo +explain format=brief select * from test3 where ((a=100 and b = 100) or a = 200) and b = 300; +id estRows task access object operator info +Projection 0.01 root test.test3.id, test.test3.a, test.test3.b +└─TableReader 0.01 root data:Selection + └─Selection 0.01 cop[tikv] eq(test.test3.b, 300), or(0, eq(test.test3.a, 200)) + └─TableFullScan 10000.00 cop[tikv] table:test3 keep order:false, stats:pseudo +explain format=brief select * from test3 where a = b; +id estRows task access object operator info +Projection 8000.00 root test.test3.id, test.test3.a, test.test3.b +└─TableReader 8000.00 root data:Selection + └─Selection 8000.00 cop[tikv] eq(test.test3.a, test.test3.b) + └─TableFullScan 10000.00 cop[tikv] table:test3 keep order:false, stats:pseudo +explain format=brief select * from test3 where a = b and b = 100; +id estRows task access object operator info +Projection 0.00 root test.test3.id, test.test3.a, test.test3.b +└─Selection 0.00 root eq(test.test3.b, 100) + └─Point_Get 1.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) +explain format=brief select * from test5 where a=100 and b = 100; +id estRows task access object operator info +Projection 1.00 root test.test5.id, test.test5.a, test.test5.b +└─Point_Get 1.00 root table:test5, index:uk_expr(tidb_shard(`a`), a, b) +explain format=brief select * from test5 where (a=100 and b = 100) or (a=200 and b = 200); +id estRows task access object operator info +Projection 2.00 root test.test5.id, test.test5.a, test.test5.b +└─Batch_Point_Get 2.00 root table:test5, index:uk_expr(tidb_shard(`a`), a, b) keep order:false, desc:false +explain format=brief select a+b from test5 where (a, b) in ((100, 100), (200, 200)); +id estRows task access object operator info +Projection 2.00 root plus(test.test5.a, test.test5.b)->Column#5 +└─Batch_Point_Get 2.00 root table:test5, index:uk_expr(tidb_shard(`a`), a, b) keep order:false, desc:false +explain format=brief SELECT * FROM test3 WHERE a IN (100); +id estRows task access object operator info +Projection 1.00 root test.test3.id, test.test3.a, test.test3.b +└─Point_Get 1.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) +explain format=brief SELECT * FROM test3 WHERE a IN (100, 200, 300); +id estRows task access object operator info +Projection 3.00 root test.test3.id, test.test3.a, test.test3.b +└─Batch_Point_Get 3.00 root table:test3, index:uk_expr(tidb_shard(`a`), a) keep order:false, desc:false +drop table if exists test3, test5; diff --git a/cmd/explaintest/r/generated_columns.result b/cmd/explaintest/r/generated_columns.result index d7f120eb28f3f..a937079129e11 100644 --- a/cmd/explaintest/r/generated_columns.result +++ b/cmd/explaintest/r/generated_columns.result @@ -1,4 +1,3 @@ -set @@tidb_partition_prune_mode='dynamic'; DROP TABLE IF EXISTS person; CREATE TABLE person ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -90,6 +89,8 @@ Projection 5.00 root test.sgc1.j1, test.sgc1.j2, test.sgc1.a, test.sgc1.b, test └─TableReader(Probe) 5.00 root data:Selection └─Selection 5.00 cop[tikv] not(isnull(test.sgc1.a)) └─TableFullScan 5.00 cop[tikv] table:sgc1 keep order:false +set @old_prune_mode = @@tidb_partition_prune_mode; +set @@tidb_partition_prune_mode='static'; DROP TABLE IF EXISTS sgc3; CREATE TABLE sgc3 ( j JSON, @@ -136,6 +137,31 @@ PartitionUnion 23263.33 root └─TableReader 3323.33 root data:Selection └─Selection 3323.33 cop[tikv] lt(test.sgc3.a, 7) └─TableFullScan 10000.00 cop[tikv] table:sgc3, partition:max keep order:false, stats:pseudo +set @@tidb_partition_prune_mode='dynamic'; +DROP TABLE sgc3; +CREATE TABLE sgc3 ( +j JSON, +a INT AS (JSON_EXTRACT(j, "$.a")) STORED +) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION p5 VALUES LESS THAN (6), +PARTITION max VALUES LESS THAN MAXVALUE); +EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a <= 1; +id estRows task access object operator info +TableReader 3323.33 root partition:p0,p1 data:Selection +└─Selection 3323.33 cop[tikv] le(test.sgc3.a, 1) + └─TableFullScan 10000.00 cop[tikv] table:sgc3 keep order:false, stats:pseudo +EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a < 7; +id estRows task access object operator info +TableReader 3323.33 root partition:all data:Selection +└─Selection 3323.33 cop[tikv] lt(test.sgc3.a, 7) + └─TableFullScan 10000.00 cop[tikv] table:sgc3 keep order:false, stats:pseudo +set @@tidb_partition_prune_mode = @old_prune_mode; DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INT, b INT AS (a+1) VIRTUAL, c INT AS (b+1) VIRTUAL, d INT AS (c+1) VIRTUAL, KEY(b), INDEX IDX(c, d)); INSERT INTO t1 (a) VALUES (0); @@ -170,9 +196,10 @@ INSERT INTO person (name, address_info) VALUES ("John", CAST('{"city_no": 1}' AS EXPLAIN format = 'brief' SELECT name FROM person where city_no=1; id estRows task access object operator info Projection 10.00 root test.person.name -└─IndexLookUp 10.00 root - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:person, index:city_no(city_no) range:[1,1], keep order:false, stats:pseudo - └─TableRowIDScan(Probe) 10.00 cop[tikv] table:person keep order:false, stats:pseudo +└─Projection 10.00 root test.person.name, test.person.city_no + └─IndexLookUp 10.00 root + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:person, index:city_no(city_no) range:[1,1], keep order:false, stats:pseudo + └─TableRowIDScan(Probe) 10.00 cop[tikv] table:person keep order:false, stats:pseudo DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (-a) VIRTUAL, @@ -182,7 +209,7 @@ INSERT INTO t1 (a) VALUES (2), (1), (1), (3), (NULL); EXPLAIN format = 'brief' SELECT sum(a) FROM t1 GROUP BY b; id estRows task access object operator info HashAgg 8000.00 root group by:Column#7, funcs:sum(Column#6)->Column#5 -└─Projection 10000.00 root cast(test.t1.a, decimal(32,0) BINARY)->Column#6, test.t1.b +└─Projection 10000.00 root cast(test.t1.a, decimal(10,0) BINARY)->Column#6, test.t1.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo EXPLAIN format = 'brief' SELECT sum(a) FROM t1 GROUP BY c; @@ -194,13 +221,13 @@ HashAgg 8000.00 root group by:test.t1.c, funcs:sum(Column#6)->Column#5 EXPLAIN format = 'brief' SELECT sum(b) FROM t1 GROUP BY a; id estRows task access object operator info HashAgg 8000.00 root group by:Column#7, funcs:sum(Column#6)->Column#5 -└─Projection 10000.00 root cast(test.t1.b, decimal(32,0) BINARY)->Column#6, test.t1.a +└─Projection 10000.00 root cast(test.t1.b, decimal(10,0) BINARY)->Column#6, test.t1.a └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo EXPLAIN format = 'brief' SELECT sum(b) FROM t1 GROUP BY c; id estRows task access object operator info HashAgg 8000.00 root group by:Column#9, funcs:sum(Column#8)->Column#5 -└─Projection 10000.00 root cast(test.t1.b, decimal(32,0) BINARY)->Column#8, test.t1.c +└─Projection 10000.00 root cast(test.t1.b, decimal(10,0) BINARY)->Column#8, test.t1.c └─Projection 10000.00 root test.t1.b, test.t1.c └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo @@ -213,7 +240,7 @@ HashAgg 8000.00 root group by:test.t1.a, funcs:sum(Column#6)->Column#5 EXPLAIN format = 'brief' SELECT sum(c) FROM t1 GROUP BY b; id estRows task access object operator info HashAgg 8000.00 root group by:Column#7, funcs:sum(Column#6)->Column#5 -└─Projection 10000.00 root cast(test.t1.c, decimal(32,0) BINARY)->Column#6, test.t1.b +└─Projection 10000.00 root cast(test.t1.c, decimal(10,0) BINARY)->Column#6, test.t1.b └─Projection 10000.00 root test.t1.b, test.t1.c └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo diff --git a/cmd/explaintest/r/imdbload.result b/cmd/explaintest/r/imdbload.result new file mode 100644 index 0000000000000..c3ee5badab7e6 --- /dev/null +++ b/cmd/explaintest/r/imdbload.result @@ -0,0 +1,370 @@ +CREATE DATABASE IF NOT EXISTS `imdbload`; +USE `imdbload`; +CREATE TABLE `kind_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`kind` varchar(15) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `kind_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=11; +CREATE TABLE `keyword` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`keyword` text NOT NULL, +`phonetic_code` varchar(5) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `keyword_idx_keyword` (`keyword`(5)), +KEY `keyword_idx_pcode` (`phonetic_code`), +KEY `itest` (`phonetic_code`,`keyword`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=236629; +CREATE TABLE `company_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`kind` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `company_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6; +CREATE TABLE `comp_cast_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`kind` varchar(32) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `comp_cast_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6; +CREATE TABLE `complete_cast` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) DEFAULT NULL, +`subject_id` int(11) NOT NULL, +`status_id` int(11) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `complete_cast_idx_mid` (`movie_id`), +KEY `complete_cast_idx_sid` (`subject_id`), +KEY `itest` (`movie_id`,`subject_id`,`status_id`), +KEY `itest2` (`subject_id`,`status_id`,`movie_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=135088; +CREATE TABLE `info_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`info` varchar(32) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `info_type_info` (`info`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=115; +CREATE TABLE `link_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`link` varchar(32) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `link_type_link` (`link`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=20; +CREATE TABLE `company_name` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`name` text NOT NULL, +`country_code` varchar(255) DEFAULT NULL, +`imdb_id` int(11) DEFAULT NULL, +`name_pcode_nf` varchar(5) DEFAULT NULL, +`name_pcode_sf` varchar(5) DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `company_name_idx_name` (`name`(6)), +KEY `company_name_idx_ccode` (`country_code`(5)), +KEY `company_name_idx_imdb_id` (`imdb_id`), +KEY `company_name_idx_pcodenf` (`name_pcode_nf`), +KEY `company_name_idx_pcodesf` (`name_pcode_sf`), +KEY `company_name_idx_md5` (`md5sum`(5)), +KEY `itest` (`country_code`,`name_pcode_nf`,`name_pcode_sf`), +KEY `itest2` (`name_pcode_sf`,`country_code`,`name`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=362133; +CREATE TABLE `role_type` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`role` varchar(32) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `role_type_role` (`role`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=14; +CREATE TABLE `movie_link` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) NOT NULL, +`linked_movie_id` int(11) NOT NULL, +`link_type_id` int(11) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `movie_link_idx_mid` (`movie_id`), +KEY `movie_link_idx_lmid` (`linked_movie_id`), +KEY `movie_link_idx_ltypeid` (`link_type_id`), +KEY `itest` (`link_type_id`,`linked_movie_id`,`movie_id`), +KEY `itest2` (`movie_id`,`link_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=2585152; +CREATE TABLE `aka_title` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) NOT NULL, +`title` text NOT NULL, +`imdb_index` varchar(12) DEFAULT NULL, +`kind_id` int(11) NOT NULL, +`production_year` int(11) DEFAULT NULL, +`phonetic_code` varchar(5) DEFAULT NULL, +`episode_of_id` int(11) DEFAULT NULL, +`season_nr` int(11) DEFAULT NULL, +`episode_nr` int(11) DEFAULT NULL, +`note` text DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `aka_title_idx_movieid` (`movie_id`), +KEY `aka_title_idx_title` (`title`(10)), +KEY `aka_title_idx_kindid` (`kind_id`), +KEY `aka_title_idx_year` (`production_year`), +KEY `aka_title_idx_pcode` (`phonetic_code`), +KEY `aka_title_idx_epof` (`episode_of_id`), +KEY `aka_title_idx_md5` (`md5sum`(5)), +KEY `itest` (`phonetic_code`,`production_year`,`kind_id`,`note`(20)), +KEY `itest2` (`episode_of_id`,`season_nr`,`episode_nr`,`production_year`), +KEY `itest3` (`episode_of_id`,`note`(20),`production_year`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=562493; +CREATE TABLE `aka_name` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`person_id` int(11) NOT NULL, +`name` text NOT NULL, +`imdb_index` varchar(12) DEFAULT NULL, +`name_pcode_cf` varchar(5) DEFAULT NULL, +`name_pcode_nf` varchar(5) DEFAULT NULL, +`surname_pcode` varchar(5) DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `aka_name_idx_person` (`person_id`), +KEY `aka_name_idx_name` (`name`(6)), +KEY `aka_name_idx_pcodecf` (`name_pcode_cf`), +KEY `aka_name_idx_pcodenf` (`name_pcode_nf`), +KEY `aka_name_idx_pcode` (`surname_pcode`), +KEY `aka_name_idx_md5` (`md5sum`(5)), +KEY `itest` (`name_pcode_cf`,`name_pcode_nf`,`surname_pcode`), +KEY `itest2` (`surname_pcode`,`name_pcode_cf`,`name_pcode_nf`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1312275; +CREATE TABLE `movie_keyword` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) NOT NULL, +`keyword_id` int(11) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `movie_keyword_idx_mid` (`movie_id`), +KEY `movie_keyword_idx_keywordid` (`keyword_id`), +KEY `itest` (`movie_id`,`keyword_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=7480089; +CREATE TABLE `movie_companies` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) NOT NULL, +`company_id` int(11) NOT NULL, +`company_type_id` int(11) NOT NULL, +`note` text DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `movie_companies_idx_mid` (`movie_id`), +KEY `movie_companies_idx_cid` (`company_id`), +KEY `movie_companies_idx_ctypeid` (`company_type_id`), +KEY `itest` (`movie_id`,`company_type_id`,`company_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4958298; +CREATE TABLE `char_name` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`name` text NOT NULL, +`imdb_index` varchar(12) DEFAULT NULL, +`imdb_id` int(11) DEFAULT NULL, +`name_pcode_nf` varchar(5) DEFAULT NULL, +`surname_pcode` varchar(5) DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `char_name_idx_name` (`name`(6)), +KEY `char_name_idx_imdb_id` (`imdb_id`), +KEY `char_name_idx_pcodenf` (`name_pcode_nf`), +KEY `char_name_idx_pcode` (`surname_pcode`), +KEY `char_name_idx_md5` (`md5sum`(5)), +KEY `itest` (`name_pcode_nf`,`surname_pcode`,`imdb_id`), +KEY `itest2` (`imdb_index`,`surname_pcode`,`name_pcode_nf`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4314866; +CREATE TABLE `title` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`title` text NOT NULL, +`imdb_index` varchar(12) DEFAULT NULL, +`kind_id` int(11) NOT NULL, +`production_year` int(11) DEFAULT NULL, +`imdb_id` int(11) DEFAULT NULL, +`phonetic_code` varchar(5) DEFAULT NULL, +`episode_of_id` int(11) DEFAULT NULL, +`season_nr` int(11) DEFAULT NULL, +`episode_nr` int(11) DEFAULT NULL, +`series_years` varchar(49) DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `title_idx_title` (`title`(10)), +KEY `title_idx_kindid` (`kind_id`), +KEY `title_idx_year` (`production_year`), +KEY `title_idx_imdb_id` (`imdb_id`), +KEY `title_idx_pcode` (`phonetic_code`), +KEY `title_idx_epof` (`episode_of_id`), +KEY `title_idx_season_nr` (`season_nr`), +KEY `title_idx_episode_nr` (`episode_nr`), +KEY `title_idx_md5` (`md5sum`(5)), +KEY `itest` (`episode_of_id`,`season_nr`,`episode_nr`,`imdb_index`,`phonetic_code`), +KEY `itest2` (`kind_id`,`production_year`,`imdb_id`,`title`(20)), +KEY `itest3` (`phonetic_code`,`production_year`,`kind_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4736511; +CREATE TABLE `name` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`name` text NOT NULL, +`imdb_index` varchar(12) DEFAULT NULL, +`imdb_id` int(11) DEFAULT NULL, +`gender` varchar(1) DEFAULT NULL, +`name_pcode_cf` varchar(5) DEFAULT NULL, +`name_pcode_nf` varchar(5) DEFAULT NULL, +`surname_pcode` varchar(5) DEFAULT NULL, +`md5sum` varchar(32) DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `name_idx_name` (`name`(6)), +KEY `name_idx_imdb_id` (`imdb_id`), +KEY `name_idx_gender` (`gender`), +KEY `name_idx_pcodecf` (`name_pcode_cf`), +KEY `name_idx_pcodenf` (`name_pcode_nf`), +KEY `name_idx_pcode` (`surname_pcode`), +KEY `name_idx_md5` (`md5sum`(5)), +KEY `itest` (`name_pcode_cf`,`name_pcode_nf`,`surname_pcode`,`imdb_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6379742; +CREATE TABLE `person_info` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`person_id` int(11) NOT NULL, +`info_type_id` int(11) NOT NULL, +`info` text NOT NULL, +`note` text DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `person_info_idx_pid` (`person_id`), +KEY `person_info_idx_itypeid` (`info_type_id`), +KEY `itest` (`person_id`,`info_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4130209; +CREATE TABLE `movie_info` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`movie_id` int(11) NOT NULL, +`info_type_id` int(11) NOT NULL, +`info` text NOT NULL, +`note` text DEFAULT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `movie_info_idx_mid` (`movie_id`), +KEY `movie_info_idx_infotypeid` (`info_type_id`), +KEY `movie_info_idx_info` (`info`(10)), +KEY `itest` (`movie_id`,`info_type_id`,`info`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=29774986; +CREATE TABLE `cast_info` ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`person_id` int(11) NOT NULL, +`movie_id` int(11) NOT NULL, +`person_role_id` int(11) DEFAULT NULL, +`note` text DEFAULT NULL, +`nr_order` int(11) DEFAULT NULL, +`role_id` int(11) NOT NULL, +PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, +KEY `cast_info_idx_pid` (`person_id`), +KEY `cast_info_idx_mid` (`movie_id`), +KEY `cast_info_idx_cid` (`person_role_id`), +KEY `cast_info_idx_rid` (`role_id`), +KEY `itest` (`person_id`,`movie_id`,`person_role_id`), +KEY `itest2` (`nr_order`,`person_role_id`,`note`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=63475837; +load stats 's/imdbload_stats/kind_type.json'; +load stats 's/imdbload_stats/keyword.json'; +load stats 's/imdbload_stats/company_type.json'; +load stats 's/imdbload_stats/comp_cast_type.json'; +load stats 's/imdbload_stats/complete_cast.json'; +load stats 's/imdbload_stats/info_type.json'; +load stats 's/imdbload_stats/link_type.json'; +load stats 's/imdbload_stats/company_name.json'; +load stats 's/imdbload_stats/role_type.json'; +load stats 's/imdbload_stats/movie_link.json'; +load stats 's/imdbload_stats/aka_title.json'; +load stats 's/imdbload_stats/aka_name.json'; +load stats 's/imdbload_stats/movie_keyword.json'; +load stats 's/imdbload_stats/movie_companies.json'; +load stats 's/imdbload_stats/char_name.json'; +load stats 's/imdbload_stats/title.json'; +load stats 's/imdbload_stats/name.json'; +load stats 's/imdbload_stats/person_info.json'; +load stats 's/imdbload_stats/movie_info.json'; +load stats 's/imdbload_stats/cast_info.json'; +explain select * from char_name where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); +id estRows task access object operator info +IndexLookUp_10 1005030.94 root +├─IndexRangeScan_8(Build) 1005030.94 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:["I" -inf,"I" "E436"), ["L" -inf,"L" "E436"), keep order:false +└─TableRowIDScan_9(Probe) 1005030.94 cop[tikv] table:char_name keep order:false +explain select * from char_name use index (itest2) where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); +id estRows task access object operator info +IndexLookUp_7 1005030.94 root +├─IndexRangeScan_5(Build) 1005030.94 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:["I" -inf,"I" "E436"), ["L" -inf,"L" "E436"), keep order:false +└─TableRowIDScan_6(Probe) 1005030.94 cop[tikv] table:char_name keep order:false +trace plan target = 'estimation' select * from char_name where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); +CE_trace +[{"table_name":"char_name","type":"Column Stats-Point","expr":"((imdb_index = 'I'))","row_count":0},{"table_name":"char_name","type":"Column Stats-Point","expr":"((imdb_index = 'L'))","row_count":0},{"table_name":"char_name","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":4314864},{"table_name":"char_name","type":"Index Stats-Range","expr":"((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436'))","row_count":0},{"table_name":"char_name","type":"Index Stats-Range","expr":"((surname_pcode < 'E436'))","row_count":1005030},{"table_name":"char_name","type":"Table Stats-Expression-CNF","expr":"`or`(`and`(`eq`(imdbload.char_name.imdb_index, 'I'), `lt`(imdbload.char_name.surname_pcode, 'E436')), `and`(`eq`(imdbload.char_name.imdb_index, 'L'), `lt`(imdbload.char_name.surname_pcode, 'E436')))","row_count":804024}] + +explain select * from char_name where ((imdb_index = 'V') and (surname_pcode < 'L3416')); +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:["V" -inf,"V" "L3416"), keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:char_name keep order:false +explain select * from char_name where imdb_index > 'V'; +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:("V",+inf], keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:char_name keep order:false +trace plan target = 'estimation' select * from char_name where imdb_index > 'V'; +CE_trace +[{"table_name":"char_name","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":4314864},{"table_name":"char_name","type":"Column Stats-Range","expr":"((imdb_index > 'V' and true))","row_count":0},{"table_name":"char_name","type":"Index Stats-Range","expr":"((imdb_index > 'V' and true))","row_count":0},{"table_name":"char_name","type":"Table Stats-Expression-CNF","expr":"`gt`(imdbload.char_name.imdb_index, 'V')","row_count":0}] + +explain select * from movie_companies where company_type_id > 2; +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:movie_companies, index:movie_companies_idx_ctypeid(company_type_id) range:(2,+inf], keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:movie_companies keep order:false +trace plan target = 'estimation' select * from movie_companies where company_type_id > 2; +CE_trace +[{"table_name":"movie_companies","type":"Column Stats-Range","expr":"((company_type_id > 2 and true))","row_count":0},{"table_name":"movie_companies","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":4958296},{"table_name":"movie_companies","type":"Index Stats-Range","expr":"((company_type_id > 2 and true))","row_count":0},{"table_name":"movie_companies","type":"Table Stats-Expression-CNF","expr":"`gt`(imdbload.movie_companies.company_type_id, 2)","row_count":0}] + +explain select * from char_name where imdb_index > 'I' and imdb_index < 'II'; +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:("I","II"), keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:char_name keep order:false +trace plan target = 'estimation' select * from char_name where imdb_index > 'I' and imdb_index < 'II'; +CE_trace +[{"table_name":"char_name","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":4314864},{"table_name":"char_name","type":"Column Stats-Range","expr":"((imdb_index > 'I' and imdb_index < 'II'))","row_count":0},{"table_name":"char_name","type":"Index Stats-Range","expr":"((imdb_index > 'I' and imdb_index < 'II'))","row_count":0},{"table_name":"char_name","type":"Table Stats-Expression-CNF","expr":"`and`(`gt`(imdbload.char_name.imdb_index, 'I'), `lt`(imdbload.char_name.imdb_index, 'II'))","row_count":0}] + +explain select * from char_name where imdb_index > 'I'; +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:char_name, index:itest2(imdb_index, surname_pcode, name_pcode_nf) range:("I",+inf], keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:char_name keep order:false +trace plan target = 'estimation' select * from char_name where imdb_index > 'I'; +CE_trace +[{"table_name":"char_name","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":4314864},{"table_name":"char_name","type":"Column Stats-Range","expr":"((imdb_index > 'I' and true))","row_count":0},{"table_name":"char_name","type":"Index Stats-Range","expr":"((imdb_index > 'I' and true))","row_count":0},{"table_name":"char_name","type":"Table Stats-Expression-CNF","expr":"`gt`(imdbload.char_name.imdb_index, 'I')","row_count":0}] + +explain select * from cast_info where nr_order < -2068070866; +id estRows task access object operator info +IndexLookUp_10 83406.52 root +├─IndexRangeScan_8(Build) 83406.52 cop[tikv] table:cast_info, index:itest2(nr_order, person_role_id, note) range:[-inf,-2068070866), keep order:false +└─TableRowIDScan_9(Probe) 83406.52 cop[tikv] table:cast_info keep order:false +explain select * from aka_title where kind_id = 5; +id estRows task access object operator info +IndexLookUp_10 34260.33 root +├─IndexRangeScan_8(Build) 34260.33 cop[tikv] table:aka_title, index:aka_title_idx_kindid(kind_id) range:[5,5], keep order:false +└─TableRowIDScan_9(Probe) 34260.33 cop[tikv] table:aka_title keep order:false +explain select * from aka_title where kind_id > 7; +id estRows task access object operator info +IndexLookUp_10 0.00 root +├─IndexRangeScan_8(Build) 0.00 cop[tikv] table:aka_title, index:aka_title_idx_kindid(kind_id) range:(7,+inf], keep order:false +└─TableRowIDScan_9(Probe) 0.00 cop[tikv] table:aka_title keep order:false +trace plan target = 'estimation' select * from aka_title where kind_id > 7; +CE_trace +[{"table_name":"aka_title","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":528337},{"table_name":"aka_title","type":"Column Stats-Range","expr":"((kind_id > 7 and true))","row_count":0},{"table_name":"aka_title","type":"Index Stats-Range","expr":"((kind_id > 7 and true))","row_count":0},{"table_name":"aka_title","type":"Table Stats-Expression-CNF","expr":"`gt`(imdbload.aka_title.kind_id, 7)","row_count":0}] + +explain select * from keyword where ((phonetic_code = 'R1652') and (keyword > 'ecg-monitor' and keyword < 'killers')); +id estRows task access object operator info +IndexLookUp_11 901.00 root +├─IndexRangeScan_8(Build) 901.00 cop[tikv] table:keyword, index:itest(phonetic_code, keyword) range:("R1652" "ecg-monitor","R1652" "killers"), keep order:false +└─Selection_10(Probe) 901.00 cop[tikv] gt(imdbload.keyword.keyword, "ecg-monitor"), lt(imdbload.keyword.keyword, "killers") + └─TableRowIDScan_9 901.00 cop[tikv] table:keyword keep order:false +trace plan target = 'estimation' select * from keyword where ((phonetic_code = 'R1652') and (keyword > 'ecg-monitor' and keyword < 'killers')); +CE_trace +[{"table_name":"keyword","type":"Column Stats-Point","expr":"((phonetic_code = 'R1652'))","row_count":23480},{"table_name":"keyword","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":236627},{"table_name":"keyword","type":"Column Stats-Range","expr":"((keyword > 'ecg-monitor' and keyword < 'killers'))","row_count":44075},{"table_name":"keyword","type":"Index Stats-Point","expr":"((phonetic_code = 'R1652'))","row_count":23480},{"table_name":"keyword","type":"Index Stats-Range","expr":"((keyword > 'ecg-monitor' and keyword < 'killers'))","row_count":44036},{"table_name":"keyword","type":"Index Stats-Range","expr":"((keyword >= 'ecg-m' and keyword <= 'kille'))","row_count":44036},{"table_name":"keyword","type":"Index Stats-Range","expr":"((phonetic_code = 'R1652') and (keyword > 'ecg-monitor' and keyword < 'killers'))","row_count":901},{"table_name":"keyword","type":"Table Stats-Expression-CNF","expr":"`and`(`eq`(imdbload.keyword.phonetic_code, 'R1652'), `and`(`gt`(imdbload.keyword.keyword, 'ecg-monitor'), `lt`(imdbload.keyword.keyword, 'killers')))","row_count":901}] + +explain select * from cast_info where (nr_order is null) and (person_role_id = 2) and (note >= '(key set pa: Florida'); +id estRows task access object operator info +IndexLookUp_11 144633.00 root +├─IndexRangeScan_8(Build) 144633.00 cop[tikv] table:cast_info, index:itest2(nr_order, person_role_id, note) range:[NULL 2 "(key set pa: Florida",NULL 2 +inf], keep order:false +└─Selection_10(Probe) 144633.00 cop[tikv] ge(imdbload.cast_info.note, "(key set pa: Florida") + └─TableRowIDScan_9 144633.00 cop[tikv] table:cast_info keep order:false +trace plan target = 'estimation' select * from cast_info where (nr_order is null) and (person_role_id = 2) and (note >= '(key set pa: Florida'); +CE_trace +[{"table_name":"cast_info","type":"Column Stats-Point","expr":"((nr_order is null))","row_count":45995275},{"table_name":"cast_info","type":"Column Stats-Point","expr":"((person_role_id = 2))","row_count":2089611},{"table_name":"cast_info","type":"Column Stats-Range","expr":"((id >= -9223372036854775808 and id <= 9223372036854775807))","row_count":63475835},{"table_name":"cast_info","type":"Column Stats-Range","expr":"((note >= '(key set pa: Florida' and true))","row_count":14934328},{"table_name":"cast_info","type":"Index Stats-Point","expr":"((person_role_id = 2))","row_count":2089611},{"table_name":"cast_info","type":"Index Stats-Range","expr":"((nr_order is null) and (person_role_id = 2) and (note >= '(key set pa: Florida' and true))","row_count":144633},{"table_name":"cast_info","type":"Table Stats-Expression-CNF","expr":"`and`(`isnull`(imdbload.cast_info.nr_order), `and`(`eq`(imdbload.cast_info.person_role_id, 2), `ge`(imdbload.cast_info.note, '(key set pa: Florida')))","row_count":144633},{"table_name":"cast_info","type":"Table Stats-Expression-CNF","expr":"`eq`(imdbload.cast_info.person_role_id, 2)","row_count":2089611}] + diff --git a/cmd/explaintest/r/index_join.result b/cmd/explaintest/r/index_join.result index e4518acaa2ef4..771c95ad5e8b1 100644 --- a/cmd/explaintest/r/index_join.result +++ b/cmd/explaintest/r/index_join.result @@ -1,3 +1,4 @@ +use test; drop table if exists t1, t2; create table t1(a bigint, b bigint, index idx(a)); create table t2(a bigint, b bigint, index idx(a)); diff --git a/cmd/explaintest/r/index_merge.result b/cmd/explaintest/r/index_merge.result index f790569635b28..5c7fece7d5161 100644 --- a/cmd/explaintest/r/index_merge.result +++ b/cmd/explaintest/r/index_merge.result @@ -237,11 +237,11 @@ insert into t1(c1, c2) values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5); explain select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 < 10 order by 1; id estRows task access object operator info Sort_5 4060.74 root test.t1.c1 -└─IndexMerge_12 2250.55 root - ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─Selection_11(Probe) 2250.55 cop[tikv] or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), lt(test.t1.c3, 10))) - └─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 2250.55 root or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), lt(test.t1.c3, 10))) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 < 10 order by 1; c1 c2 c3 1 1 2 @@ -252,11 +252,11 @@ c1 c2 c3 explain select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 = c1 + c2 order by 1; id estRows task access object operator info Sort_5 5098.44 root test.t1.c1 -└─IndexMerge_12 2825.66 root - ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─Selection_11(Probe) 2825.66 cop[tikv] or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), eq(test.t1.c3, plus(test.t1.c1, test.t1.c2)))) - └─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 2825.66 root or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), eq(test.t1.c3, plus(test.t1.c1, test.t1.c2)))) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 = c1 + c2 order by 1; c1 c2 c3 1 1 2 @@ -267,11 +267,11 @@ c1 c2 c3 explain select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and substring(c3, c2) order by 1; id estRows task access object operator info Sort_5 5098.44 root test.t1.c1 -└─IndexMerge_12 2825.66 root - ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─Selection_11(Probe) 2825.66 cop[tikv] or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), istrue_with_null(cast(substring(cast(test.t1.c3, var_string(20)), test.t1.c2), double BINARY)))) - └─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 2825.66 root or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), istrue_with_null(cast(substring(cast(test.t1.c3, var_string(20)), test.t1.c2), double BINARY)))) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and substring(c3, c2) order by 1; c1 c2 c3 1 1 2 @@ -282,11 +282,11 @@ c1 c2 c3 explain select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 order by 1; id estRows task access object operator info Sort_5 4800.37 root test.t1.c1 -└─IndexMerge_12 2660.47 root - ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─Selection_11(Probe) 2660.47 cop[tikv] or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), test.t1.c3)) - └─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 2660.47 root or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), test.t1.c3)) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 order by 1; c1 c2 c3 1 1 2 @@ -302,11 +302,11 @@ select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 < 10 explain select * from t1 where c1 < 10 or c2 < 10 and c3 < 10 order by 1; id estRows task access object operator info Sort_5 4060.74 root test.t1.c1 -└─IndexMerge_12 2250.55 root - ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─Selection_11(Probe) 2250.55 cop[tikv] or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), lt(test.t1.c3, 10))) - └─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 2250.55 root or(lt(test.t1.c1, 10), and(lt(test.t1.c2, 10), lt(test.t1.c3, 10))) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select * from t1 where c1 < 10 or c2 < 10 and c3 < 10 order by 1; c1 c2 c3 1 1 2 @@ -322,7 +322,7 @@ drop view if exists v2; create view v2 as select /*+ use_index_merge(t1) */ * from t1 where c1 < 10 or c2 < 10 and c3 < 10; show create view v2; View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `v2` (`c1`, `c2`, `c3`) AS SELECT /*+ USE_INDEX_MERGE(`t1` )*/ `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3` FROM `test`.`t1` WHERE `c1`<10 OR `c2`<10 AND `c3`<10 utf8mb4 utf8mb4_general_ci +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `v2` (`c1`, `c2`, `c3`) AS SELECT /*+ USE_INDEX_MERGE(`t1` )*/ `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3` FROM `test`.`t1` WHERE `c1`<10 OR `c2`<10 AND `c3`<10 utf8mb4 utf8mb4_bin select * from v2 order by 1; c1 c2 c3 1 1 1 @@ -481,7 +481,7 @@ explain select /*+ use_index_merge(t1) */ sum(c1) from t1 where (c1 < 10 or c2 < id estRows task access object operator info Sort_6 1473.49 root Column#5 └─HashAgg_11 1473.49 root group by:Column#10, funcs:sum(Column#9)->Column#5 - └─Projection_18 1841.86 root cast(test.t1.c1, decimal(32,0) BINARY)->Column#9, test.t1.c1 + └─Projection_18 1841.86 root cast(test.t1.c1, decimal(10,0) BINARY)->Column#9, test.t1.c1 └─IndexMerge_16 1841.86 root ├─IndexRangeScan_12(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo ├─IndexRangeScan_13(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo @@ -653,11 +653,11 @@ c1 c2 c3 c4 c5 explain select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and greatest(c1, c2, c4) = 1 order by 1; id estRows task access object operator info Sort_5 4433.77 root test.t1.c1 -└─Selection_8 4433.77 root eq(greatest(test.t1.c1, test.t1.c2, test.t1.c4), 1) - └─IndexMerge_12 5542.21 root - ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo - ├─IndexRangeScan_10(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo - └─TableRowIDScan_11(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo +└─Selection_12 4433.77 root eq(greatest(test.t1.c1, test.t1.c2, test.t1.c4), 1) + └─IndexMerge_11 5542.21 root + ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo + └─TableRowIDScan_10(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and greatest(c1, c2, c4) = 1 order by 1; c1 c2 c3 c4 c5 1 1 1 1 1 diff --git a/cmd/explaintest/r/new_character_set.result b/cmd/explaintest/r/new_character_set.result index e48b58e4c8905..18b0f44662025 100644 --- a/cmd/explaintest/r/new_character_set.result +++ b/cmd/explaintest/r/new_character_set.result @@ -56,3 +56,37 @@ a hex(a) 中文 E4B8ADE69687 涓?枃 E6B6933FE69E83 set @@character_set_client = 'utf8mb4'; +set names gbk; +drop table if exists t; +create table t (b blob, d json); +insert into t values ('你好', '{"测试": "你好"}'); +select b, d from t; +b d +你好 {"测试": "你好"} +select hex(b), hex(d) from t; +hex(b) hex(d) +E4BDA0E5A5BD 7B22E6B58BE8AF95223A2022E4BDA0E5A5BD227D +set names utf8mb4; +drop table if exists t; +create table t(a blob, b char(10)); +insert into t values (0x61, 'å•Š'); +insert into t values (0x61, '一'); +set names gbk; +select * from t; +a b +a °¡ +a Ò» +drop table t; +set names gbk; +set character_set_connection = utf8mb4; +create table t(j json, b blob, s1 varchar(255) collate binary, s2 varchar(255), st set('{"点赞": "你好"}'), en enum('{"点赞": "你好"}')); +insert into t values('{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}'); +select * from t; +j b s1 s2 st en +{"点赞": "你好"} {"éç¡…ç¦": "浣犲ソ"} {"éç¡…ç¦": "浣犲ソ"} {"点赞": "你好"} {"点赞": "你好"} {"点赞": "你好"} +set names utf8mb4; +set @@character_set_client=gbk; +set @@character_set_connection=gbk; +select hex('一a'), '一a'; +hex('涓?') 涓? +E4B83F 涓? diff --git a/cmd/explaintest/r/new_character_set_builtin.result b/cmd/explaintest/r/new_character_set_builtin.result index fa733d990ef1e..96f903a13ee1b 100644 --- a/cmd/explaintest/r/new_character_set_builtin.result +++ b/cmd/explaintest/r/new_character_set_builtin.result @@ -1,3 +1,5 @@ +set names utf8mb4; +set @@sql_mode = ''; drop table if exists t; create table t (a char(20) charset utf8mb4, b char(20) charset gbk, c binary(20)); insert into t values ('一二三', '一二三', '一二三'); @@ -244,8 +246,8 @@ insert into t values ('65'), ('123456'), ('123456789'); select char(a using gbk), char(a using utf8), char(a) from t; char(a using gbk) char(a using utf8) char(a) A A A -釦 â@ â@ -NULL [Í [Í +釦  â@ +[ [ [Í select char(12345678 using gbk); char(12345678 using gbk) ç³°N @@ -253,8 +255,8 @@ set @@tidb_enable_vectorized_expression = true; select char(a using gbk), char(a using utf8), char(a) from t; char(a using gbk) char(a using utf8) char(a) A A A -釦 â@ â@ -NULL [Í [Í +釦  â@ +[ [ [Í select char(12345678 using gbk); char(12345678 using gbk) ç³°N @@ -396,13 +398,17 @@ a like 0xe4b880 b like 0xd2bb 1 1 1 1 select a = 0xb6fe from t; -Error 3854: Cannot convert string 'B6FE' from binary to utf8mb4 +Error 3854: Cannot convert string '\xB6\xFE' from binary to utf8mb4 select b = 0xe4ba8c from t; -Error 3854: Cannot convert string 'E4BA8C' from binary to gbk +Error 3854: Cannot convert string '\xE4\xBA\x8C' from binary to gbk select concat(a, 0xb6fe) from t; -Error 3854: Cannot convert string 'B6FE' from binary to utf8mb4 +Error 3854: Cannot convert string '\xB6\xFE' from binary to utf8mb4 select concat(b, 0xe4ba8c) from t; -Error 3854: Cannot convert string 'E4BA8C' from binary to gbk +Error 3854: Cannot convert string '\xE4\xBA\x8C' from binary to gbk +select concat(convert('a' using gbk), 0x3fff) from t; +Error 3854: Cannot convert string '?\xFF' from binary to gbk +select concat(convert('a' using gbk), 0x3fffffffffffffff) from t; +Error 3854: Cannot convert string '?\xFF\xFF\xFF\xFF\xFF...' from binary to gbk set @@tidb_enable_vectorized_expression = false; select hex(concat(a, c)), hex(concat(b, c)) from t; hex(concat(a, c)) hex(concat(b, c)) @@ -495,13 +501,13 @@ a like 0xe4b880 b like 0xd2bb 1 1 1 1 select a = 0xb6fe from t; -Error 3854: Cannot convert string 'B6FE' from binary to utf8mb4 +Error 3854: Cannot convert string '\xB6\xFE' from binary to utf8mb4 select b = 0xe4ba8c from t; -Error 3854: Cannot convert string 'E4BA8C' from binary to gbk +Error 3854: Cannot convert string '\xE4\xBA\x8C' from binary to gbk select concat(a, 0xb6fe) from t; -Error 3854: Cannot convert string 'B6FE' from binary to utf8mb4 +Error 3854: Cannot convert string '\xB6\xFE' from binary to utf8mb4 select concat(b, 0xe4ba8c) from t; -Error 3854: Cannot convert string 'E4BA8C' from binary to gbk +Error 3854: Cannot convert string '\xE4\xBA\x8C' from binary to gbk drop table if exists t; create table t (a char(20) charset utf8mb4, b char(20) charset gbk, c binary(20)); insert into t values ('一二三', '一二三', '一二三'); @@ -522,3 +528,25 @@ select hex(aes_encrypt(a, '123')), hex(aes_encrypt(b, '123')), hex(aes_encrypt(c hex(aes_encrypt(a, '123')) hex(aes_encrypt(b, '123')) hex(aes_encrypt(c, '123')) C54279F381B0710E145E94106F03C94C 7A747EC6F1906276D036B1F3CE27BAAB A0E5E01289017B8A3691CCFBDE81A59ED4A9D5BF50A298D41287E395CDDCAD56 set @@tidb_enable_vectorized_expression = false; +drop table if exists t; +create table t (a char(20) charset utf8mb4, b char(20) charset gbk, c binary(20)); +insert into t values ('一二三', '一二三', '一二三'); +select crc32(a), crc32(b), crc32(c) from t; +crc32(a) crc32(b) crc32(c) +1785250883 3461331449 4092198678 +set @@tidb_enable_vectorized_expression = true; +select crc32(a), crc32(b), crc32(c) from t; +crc32(a) crc32(b) crc32(c) +1785250883 3461331449 4092198678 +set @@tidb_enable_vectorized_expression = false; +drop table if exists t; +create table t (a enum('a一','b二','c三','då››') default 'c三', b binary(10)) charset=gbk; +insert into t values (1, 0x1234); +set @@tidb_enable_vectorized_expression = true; +select hex(elt(1, a, b)), hex(elt(1, a, 0x12)) from t; +hex(elt(1, a, b)) hex(elt(1, a, 0x12)) +61D2BB 61D2BB +set @@tidb_enable_vectorized_expression = false; +select hex(elt(1, a, b)), hex(elt(1, a, 0x12)) from t; +hex(elt(1, a, b)) hex(elt(1, a, 0x12)) +61D2BB 61D2BB diff --git a/cmd/explaintest/r/new_character_set_invalid.result b/cmd/explaintest/r/new_character_set_invalid.result index aaeb66a8d9b44..92e43d6c747fa 100644 --- a/cmd/explaintest/r/new_character_set_invalid.result +++ b/cmd/explaintest/r/new_character_set_invalid.result @@ -5,7 +5,7 @@ insert into t values ('中文', 'asdf', '字符集'); insert into t values ('À', 'ø', '😂'); Error 1366: Incorrect string value '\xC3\x80' for column 'a' insert into t values ('中文À中文', 'asdføfdsa', '字符集😂字符集'); -Error 1366: Incorrect string value '\xC3\x80\xE4\xB8\xAD\xE6...' for column 'a' +Error 1366: Incorrect string value '\xC3\x80' for column 'a' insert into t values (0x4040ffff, 0x4040ffff, 0x4040ffff); Error 1366: Incorrect string value '\xFF\xFF' for column 'a' select * from t; diff --git a/cmd/explaintest/r/select.result b/cmd/explaintest/r/select.result index 959e761aad086..9fe5dbc5c9a0f 100644 --- a/cmd/explaintest/r/select.result +++ b/cmd/explaintest/r/select.result @@ -354,6 +354,7 @@ Projection_3 1.00 root sysdate()->Column#1, sleep(1)->Column#2, sysdate()->Colu └─TableDual_4 1.00 root rows:1 drop table if exists th; set @@session.tidb_enable_table_partition = '1'; +set @@session.tidb_partition_prune_mode = 'static'; create table th (a int, b int) partition by hash(a) partitions 3; insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8); insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8); @@ -378,6 +379,21 @@ PartitionUnion_8 20000.00 root │ └─TableFullScan_9 10000.00 cop[tikv] table:th, partition:p1 keep order:false, stats:pseudo └─TableReader_12 10000.00 root data:TableFullScan_11 └─TableFullScan_11 10000.00 cop[tikv] table:th, partition:p2 keep order:false, stats:pseudo +set @@session.tidb_partition_prune_mode = 'dynamic'; +desc select * from th where a=-2; +id estRows task access object operator info +TableReader_7 10.00 root partition:p2 data:Selection_6 +└─Selection_6 10.00 cop[tikv] eq(test.th.a, -2) + └─TableFullScan_5 10000.00 cop[tikv] table:th keep order:false, stats:pseudo +desc select * from th; +id estRows task access object operator info +TableReader_5 10000.00 root partition:all data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:th keep order:false, stats:pseudo +desc select * from th partition (p2,p1); +id estRows task access object operator info +TableReader_5 10000.00 root partition:p1,p2 data:TableFullScan_4 +└─TableFullScan_4 10000.00 cop[tikv] table:th keep order:false, stats:pseudo +set @@session.tidb_partition_prune_mode = DEFAULT; drop table if exists t; create table t(a int, b int); explain format = 'brief' select a != any (select a from t t2) from t t1; @@ -385,7 +401,7 @@ id estRows task access object operator info Projection 10000.00 root and(or(or(gt(Column#11, 1), ne(test.t.a, Column#10)), if(ne(Column#12, 0), , 0)), and(ne(Column#13, 0), if(isnull(test.t.a), , 1)))->Column#14 └─HashJoin 10000.00 root CARTESIAN inner join ├─StreamAgg(Build) 1.00 root funcs:max(Column#16)->Column#10, funcs:count(distinct Column#17)->Column#11, funcs:sum(Column#18)->Column#12, funcs:count(1)->Column#13 - │ └─Projection 10000.00 root test.t.a, test.t.a, cast(isnull(test.t.a), decimal(22,0) BINARY)->Column#18 + │ └─Projection 10000.00 root test.t.a, test.t.a, cast(isnull(test.t.a), decimal(20,0) BINARY)->Column#18 │ └─TableReader 10000.00 root data:TableFullScan │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo └─TableReader(Probe) 10000.00 root data:TableFullScan @@ -395,7 +411,7 @@ id estRows task access object operator info Projection 10000.00 root or(and(and(le(Column#11, 1), eq(test.t.a, Column#10)), if(ne(Column#12, 0), , 1)), or(eq(Column#13, 0), if(isnull(test.t.a), , 0)))->Column#14 └─HashJoin 10000.00 root CARTESIAN inner join ├─StreamAgg(Build) 1.00 root funcs:firstrow(Column#16)->Column#10, funcs:count(distinct Column#17)->Column#11, funcs:sum(Column#18)->Column#12, funcs:count(1)->Column#13 - │ └─Projection 10000.00 root test.t.a, test.t.a, cast(isnull(test.t.a), decimal(22,0) BINARY)->Column#18 + │ └─Projection 10000.00 root test.t.a, test.t.a, cast(isnull(test.t.a), decimal(20,0) BINARY)->Column#18 │ └─TableReader 10000.00 root data:TableFullScan │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo └─TableReader(Probe) 10000.00 root data:TableFullScan @@ -498,4 +514,4 @@ a b c d create table t3(a char(10), primary key (a)); insert into t3 values ('a'); select * from t3 where a > 0x80; -Error 1105: Cannot convert string '80' from binary to utf8mb4 +Error 1105: Cannot convert string '\x80' from binary to utf8mb4 diff --git a/cmd/explaintest/r/tpch.result b/cmd/explaintest/r/tpch.result index 319713d946aa2..855021af61533 100644 --- a/cmd/explaintest/r/tpch.result +++ b/cmd/explaintest/r/tpch.result @@ -124,7 +124,7 @@ Sort 2.94 root tpch.lineitem.l_returnflag, tpch.lineitem.l_linestatus └─HashAgg 2.94 root group by:tpch.lineitem.l_linestatus, tpch.lineitem.l_returnflag, funcs:sum(Column#26)->Column#18, funcs:sum(Column#27)->Column#19, funcs:sum(Column#28)->Column#20, funcs:sum(Column#29)->Column#21, funcs:avg(Column#30, Column#31)->Column#22, funcs:avg(Column#32, Column#33)->Column#23, funcs:avg(Column#34, Column#35)->Column#24, funcs:count(Column#36)->Column#25, funcs:firstrow(tpch.lineitem.l_returnflag)->tpch.lineitem.l_returnflag, funcs:firstrow(tpch.lineitem.l_linestatus)->tpch.lineitem.l_linestatus └─TableReader 2.94 root data:HashAgg └─HashAgg 2.94 cop[tikv] group by:tpch.lineitem.l_linestatus, tpch.lineitem.l_returnflag, funcs:sum(tpch.lineitem.l_quantity)->Column#26, funcs:sum(tpch.lineitem.l_extendedprice)->Column#27, funcs:sum(mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount)))->Column#28, funcs:sum(mul(mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount)), plus(1, tpch.lineitem.l_tax)))->Column#29, funcs:count(tpch.lineitem.l_quantity)->Column#30, funcs:sum(tpch.lineitem.l_quantity)->Column#31, funcs:count(tpch.lineitem.l_extendedprice)->Column#32, funcs:sum(tpch.lineitem.l_extendedprice)->Column#33, funcs:count(tpch.lineitem.l_discount)->Column#34, funcs:sum(tpch.lineitem.l_discount)->Column#35, funcs:count(1)->Column#36 - └─Selection 293795345.00 cop[tikv] le(tpch.lineitem.l_shipdate, 1998-08-15) + └─Selection 293795345.00 cop[tikv] le(tpch.lineitem.l_shipdate, 1998-08-15 00:00:00.000000) └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false /* Q2 Minimum Cost Supplier Query @@ -300,7 +300,7 @@ Sort 1.00 root tpch.orders.o_orderpriority └─HashAgg 1.00 root group by:tpch.orders.o_orderpriority, funcs:count(1)->Column#27, funcs:firstrow(tpch.orders.o_orderpriority)->tpch.orders.o_orderpriority └─IndexHashJoin 2340750.00 root semi join, inner:IndexLookUp, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey, equal cond:eq(tpch.orders.o_orderkey, tpch.lineitem.l_orderkey) ├─TableReader(Build) 2925937.50 root data:Selection - │ └─Selection 2925937.50 cop[tikv] ge(tpch.orders.o_orderdate, 1995-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-04-01) + │ └─Selection 2925937.50 cop[tikv] ge(tpch.orders.o_orderdate, 1995-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-04-01 00:00:00.000000) │ └─TableFullScan 75000000.00 cop[tikv] table:orders keep order:false └─IndexLookUp(Probe) 4.05 root ├─IndexRangeScan(Build) 5.06 cop[tikv] table:lineitem, index:PRIMARY(L_ORDERKEY, L_LINENUMBER) range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:false @@ -353,7 +353,7 @@ Sort 5.00 root Column#49:desc │ └─TableFullScan 7500000.00 cop[tikv] table:customer keep order:false └─HashJoin(Probe) 11822812.50 root inner join, equal:[eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)] ├─TableReader(Build) 11822812.50 root data:Selection - │ └─Selection 11822812.50 cop[tikv] ge(tpch.orders.o_orderdate, 1994-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-01-01) + │ └─Selection 11822812.50 cop[tikv] ge(tpch.orders.o_orderdate, 1994-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-01-01 00:00:00.000000) │ └─TableFullScan 75000000.00 cop[tikv] table:orders keep order:false └─HashJoin(Probe) 61163763.01 root inner join, equal:[eq(tpch.supplier.s_suppkey, tpch.lineitem.l_suppkey)] ├─HashJoin(Build) 100000.00 root inner join, equal:[eq(tpch.nation.n_nationkey, tpch.supplier.s_nationkey)] @@ -392,7 +392,7 @@ id estRows task access object operator info StreamAgg 1.00 root funcs:sum(Column#20)->Column#18 └─TableReader 1.00 root data:StreamAgg └─StreamAgg 1.00 cop[tikv] funcs:sum(mul(tpch.lineitem.l_extendedprice, tpch.lineitem.l_discount))->Column#20 - └─Selection 3713857.91 cop[tikv] ge(tpch.lineitem.l_discount, 0.05), ge(tpch.lineitem.l_shipdate, 1994-01-01 00:00:00.000000), le(tpch.lineitem.l_discount, 0.07), lt(tpch.lineitem.l_quantity, 24), lt(tpch.lineitem.l_shipdate, 1995-01-01) + └─Selection 3713858.13 cop[tikv] ge(tpch.lineitem.l_discount, 0.05), ge(tpch.lineitem.l_shipdate, 1994-01-01 00:00:00.000000), le(tpch.lineitem.l_discount, 0.07), lt(tpch.lineitem.l_quantity, 24), lt(tpch.lineitem.l_shipdate, 1995-01-01 00:00:00.000000) └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false /* Q7 Volume Shipping Query @@ -669,7 +669,7 @@ Projection 20.00 root tpch.customer.c_custkey, tpch.customer.c_name, Column#39, └─IndexHashJoin 12222016.17 root inner join, inner:IndexLookUp, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey, equal cond:eq(tpch.orders.o_orderkey, tpch.lineitem.l_orderkey) ├─HashJoin(Build) 3017307.69 root inner join, equal:[eq(tpch.customer.c_custkey, tpch.orders.o_custkey)] │ ├─TableReader(Build) 3017307.69 root data:Selection - │ │ └─Selection 3017307.69 cop[tikv] ge(tpch.orders.o_orderdate, 1993-08-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1993-11-01) + │ │ └─Selection 3017307.69 cop[tikv] ge(tpch.orders.o_orderdate, 1993-08-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1993-11-01 00:00:00.000000) │ │ └─TableFullScan 75000000.00 cop[tikv] table:orders keep order:false │ └─HashJoin(Probe) 7500000.00 root inner join, equal:[eq(tpch.nation.n_nationkey, tpch.customer.c_nationkey)] │ ├─TableReader(Build) 25.00 root data:TableFullScan @@ -773,11 +773,11 @@ id estRows task access object operator info Sort 1.00 root tpch.lineitem.l_shipmode └─Projection 1.00 root tpch.lineitem.l_shipmode, Column#27, Column#28 └─HashAgg 1.00 root group by:Column#40, funcs:sum(Column#37)->Column#27, funcs:sum(Column#38)->Column#28, funcs:firstrow(Column#39)->tpch.lineitem.l_shipmode - └─Projection 10023369.01 root cast(case(or(eq(tpch.orders.o_orderpriority, 1-URGENT), eq(tpch.orders.o_orderpriority, 2-HIGH)), 1, 0), decimal(22,0) BINARY)->Column#37, cast(case(and(ne(tpch.orders.o_orderpriority, 1-URGENT), ne(tpch.orders.o_orderpriority, 2-HIGH)), 1, 0), decimal(22,0) BINARY)->Column#38, tpch.lineitem.l_shipmode, tpch.lineitem.l_shipmode + └─Projection 10023369.01 root cast(case(or(eq(tpch.orders.o_orderpriority, 1-URGENT), eq(tpch.orders.o_orderpriority, 2-HIGH)), 1, 0), decimal(20,0) BINARY)->Column#37, cast(case(and(ne(tpch.orders.o_orderpriority, 1-URGENT), ne(tpch.orders.o_orderpriority, 2-HIGH)), 1, 0), decimal(20,0) BINARY)->Column#38, tpch.lineitem.l_shipmode, tpch.lineitem.l_shipmode └─Projection 10023369.01 root tpch.orders.o_orderpriority, tpch.lineitem.l_shipmode └─IndexJoin 10023369.01 root inner join, inner:TableReader, outer key:tpch.lineitem.l_orderkey, inner key:tpch.orders.o_orderkey, equal cond:eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey) ├─TableReader(Build) 10023369.01 root data:Selection - │ └─Selection 10023369.01 cop[tikv] ge(tpch.lineitem.l_receiptdate, 1997-01-01 00:00:00.000000), in(tpch.lineitem.l_shipmode, "RAIL", "FOB"), lt(tpch.lineitem.l_commitdate, tpch.lineitem.l_receiptdate), lt(tpch.lineitem.l_receiptdate, 1998-01-01), lt(tpch.lineitem.l_shipdate, tpch.lineitem.l_commitdate) + │ └─Selection 10023369.01 cop[tikv] ge(tpch.lineitem.l_receiptdate, 1997-01-01 00:00:00.000000), in(tpch.lineitem.l_shipmode, "RAIL", "FOB"), lt(tpch.lineitem.l_commitdate, tpch.lineitem.l_receiptdate), lt(tpch.lineitem.l_receiptdate, 1998-01-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, tpch.lineitem.l_commitdate) │ └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false └─TableReader(Probe) 1.00 root data:TableRangeScan └─TableRangeScan 1.00 cop[tikv] table:orders range: decided by [tpch.lineitem.l_orderkey], keep order:false @@ -848,7 +848,7 @@ Projection 1.00 root div(mul(100.00, Column#27), Column#28)->Column#29 └─Projection 4121984.49 root case(like(tpch.part.p_type, PROMO%, 92), mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount)), 0)->Column#31, mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount))->Column#32 └─IndexJoin 4121984.49 root inner join, inner:TableReader, outer key:tpch.lineitem.l_partkey, inner key:tpch.part.p_partkey, equal cond:eq(tpch.lineitem.l_partkey, tpch.part.p_partkey) ├─TableReader(Build) 4121984.49 root data:Selection - │ └─Selection 4121984.49 cop[tikv] ge(tpch.lineitem.l_shipdate, 1996-12-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, 1997-01-01) + │ └─Selection 4121984.49 cop[tikv] ge(tpch.lineitem.l_shipdate, 1996-12-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, 1997-01-01 00:00:00.000000) │ └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false └─TableReader(Probe) 1.00 root data:TableRangeScan └─TableRangeScan 1.00 cop[tikv] table:part range: decided by [tpch.lineitem.l_partkey], keep order:false @@ -1100,8 +1100,8 @@ StreamAgg 1.00 root funcs:sum(Column#28)->Column#27 ├─TableReader(Build) 24323.12 root data:Selection │ └─Selection 24323.12 cop[tikv] ge(tpch.part.p_size, 1), or(and(eq(tpch.part.p_brand, "Brand#52"), and(in(tpch.part.p_container, "SM CASE", "SM BOX", "SM PACK", "SM PKG"), le(tpch.part.p_size, 5))), or(and(eq(tpch.part.p_brand, "Brand#11"), and(in(tpch.part.p_container, "MED BAG", "MED BOX", "MED PKG", "MED PACK"), le(tpch.part.p_size, 10))), and(eq(tpch.part.p_brand, "Brand#51"), and(in(tpch.part.p_container, "LG CASE", "LG BOX", "LG PACK", "LG PKG"), le(tpch.part.p_size, 15))))) │ └─TableFullScan 10000000.00 cop[tikv] table:part keep order:false - └─TableReader(Probe) 6286493.79 root data:Selection - └─Selection 6286493.79 cop[tikv] eq(tpch.lineitem.l_shipinstruct, "DELIVER IN PERSON"), in(tpch.lineitem.l_shipmode, "AIR", "AIR REG"), or(and(ge(tpch.lineitem.l_quantity, 4), le(tpch.lineitem.l_quantity, 14)), or(and(ge(tpch.lineitem.l_quantity, 18), le(tpch.lineitem.l_quantity, 28)), and(ge(tpch.lineitem.l_quantity, 29), le(tpch.lineitem.l_quantity, 39)))) + └─TableReader(Probe) 6286493.57 root data:Selection + └─Selection 6286493.57 cop[tikv] eq(tpch.lineitem.l_shipinstruct, "DELIVER IN PERSON"), in(tpch.lineitem.l_shipmode, "AIR", "AIR REG"), or(and(ge(tpch.lineitem.l_quantity, 4), le(tpch.lineitem.l_quantity, 14)), or(and(ge(tpch.lineitem.l_quantity, 18), le(tpch.lineitem.l_quantity, 28)), and(ge(tpch.lineitem.l_quantity, 29), le(tpch.lineitem.l_quantity, 39)))) └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false /* Q20 Potential Part Promotion Query @@ -1170,7 +1170,7 @@ Sort 20000.00 root tpch.supplier.s_name │ ├─IndexRangeScan(Build) 4.02 cop[tikv] table:partsupp, index:PRIMARY(PS_PARTKEY, PS_SUPPKEY) range: decided by [eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)], keep order:false │ └─TableRowIDScan(Probe) 4.02 cop[tikv] table:partsupp keep order:false └─TableReader(Probe) 44189356.65 root data:Selection - └─Selection 44189356.65 cop[tikv] ge(tpch.lineitem.l_shipdate, 1993-01-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, 1994-01-01) + └─Selection 44189356.65 cop[tikv] ge(tpch.lineitem.l_shipdate, 1993-01-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, 1994-01-01 00:00:00.000000) └─TableFullScan 300005811.00 cop[tikv] table:lineitem keep order:false /* Q21 Suppliers Who Kept Orders Waiting Query @@ -1294,14 +1294,13 @@ cntrycode order by cntrycode; id estRows task access object operator info -Sort 1.00 root Column#27 -└─Projection 1.00 root Column#27, Column#28, Column#29 - └─HashAgg 1.00 root group by:Column#33, funcs:count(1)->Column#28, funcs:sum(Column#31)->Column#29, funcs:firstrow(Column#32)->Column#27 - └─Projection 0.00 root tpch.customer.c_acctbal, substring(tpch.customer.c_phone, 1, 2)->Column#32, substring(tpch.customer.c_phone, 1, 2)->Column#33 +Sort 1.00 root Column#31 +└─Projection 1.00 root Column#31, Column#32, Column#33 + └─HashAgg 1.00 root group by:Column#37, funcs:count(1)->Column#32, funcs:sum(Column#35)->Column#33, funcs:firstrow(Column#36)->Column#31 + └─Projection 0.00 root tpch.customer.c_acctbal, substring(tpch.customer.c_phone, 1, 2)->Column#36, substring(tpch.customer.c_phone, 1, 2)->Column#37 └─HashJoin 0.00 root anti semi join, equal:[eq(tpch.customer.c_custkey, tpch.orders.o_custkey)] ├─TableReader(Build) 75000000.00 root data:TableFullScan │ └─TableFullScan 75000000.00 cop[tikv] table:orders keep order:false - └─Selection(Probe) 0.00 root in(substring(tpch.customer.c_phone, 1, 2), "20", "40", "22", "30", "39", "42", "21") - └─TableReader 0.00 root data:Selection - └─Selection 0.00 cop[tikv] gt(tpch.customer.c_acctbal, NULL) - └─TableFullScan 7500000.00 cop[tikv] table:customer keep order:false + └─TableReader(Probe) 0.00 root data:Selection + └─Selection 0.00 cop[tikv] gt(tpch.customer.c_acctbal, NULL), in(substring(tpch.customer.c_phone, 1, 2), "20", "40", "22", "30", "39", "42", "21") + └─TableFullScan 7500000.00 cop[tikv] table:customer keep order:false diff --git a/cmd/explaintest/r/vitess_hash.result b/cmd/explaintest/r/vitess_hash.result index 1e20ff988c8f4..a6beca77cbe4e 100644 --- a/cmd/explaintest/r/vitess_hash.result +++ b/cmd/explaintest/r/vitess_hash.result @@ -19,10 +19,11 @@ explain format = 'brief' select id from t where (vitess_hash(customer_id) >> 56) id estRows task access object operator info Projection 0.50 root test.t.id └─Sort 0.50 root test.t.id - └─IndexLookUp 0.50 root - ├─IndexRangeScan(Build) 20.00 cop[tikv] table:t, index:t_vitess_shard(vitess_hash(`customer_id`) >> 56) range:[224,224], [225,225], keep order:false, stats:pseudo - └─Selection(Probe) 0.50 cop[tikv] ge(test.t.id, 2), le(test.t.id, 5) - └─TableRowIDScan 20.00 cop[tikv] table:t keep order:false, stats:pseudo + └─Projection 0.50 root test.t.id, rightshift(vitess_hash(test.t.customer_id), 56) + └─IndexLookUp 0.50 root + ├─IndexRangeScan(Build) 20.00 cop[tikv] table:t, index:t_vitess_shard(vitess_hash(`customer_id`) >> 56) range:[224,224], [225,225], keep order:false, stats:pseudo + └─Selection(Probe) 0.50 cop[tikv] ge(test.t.id, 2), le(test.t.id, 5) + └─TableRowIDScan 20.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select hex(vitess_hash(1123)) from t; id estRows task access object operator info Projection 10000.00 root 31B565D41BDF8CA->Column#7 diff --git a/cmd/explaintest/r/window_function.result b/cmd/explaintest/r/window_function.result index 6c92b63dcd0d3..b29d1e5d3fba7 100644 --- a/cmd/explaintest/r/window_function.result +++ b/cmd/explaintest/r/window_function.result @@ -6,47 +6,47 @@ set @@session.tidb_window_concurrency = 1; explain format = 'brief' select sum(a) over() from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over() +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over() └─IndexReader 10000.00 root index:IndexFullScan └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx(a) keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a) └─IndexReader 10000.00 root index:IndexFullScan └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx(a) keep order:true, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by b) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by b rows unbounded preceding) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between unbounded preceding and current row) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between unbounded preceding and current row) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by b rows between 1 preceding and 1 following) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between 1 preceding and 1 following) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between 1 preceding and 1 following) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by b range between 1 preceding and 1 following) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between 1 preceding and 1 following) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between 1 preceding and 1 following) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by c range between interval '2:30' minute_second preceding and interval '2:30' minute_second following) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.c range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.c range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) └─Sort 10000.00 root test.t.a, test.t.c └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -54,20 +54,20 @@ set @@session.tidb_window_concurrency = 4; explain format = 'brief' select sum(a) over() from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over() +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over() └─IndexReader 10000.00 root index:IndexFullScan └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx(a) keep order:false, stats:pseudo explain format = 'brief' select sum(a) over(partition by a) from t; id estRows task access object operator info Projection 10000.00 root Column#6 -└─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a) +└─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a) └─IndexReader 10000.00 root index:IndexFullScan └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx(a) keep order:true, stats:pseudo explain format = 'brief' select sum(a) over(partition by a order by b) from t; id estRows task access object operator info Projection 10000.00 root Column#6 └─Shuffle 10000.00 root execution info: concurrency:4, data sources:[TableReader] - └─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row) + └─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -75,7 +75,7 @@ explain format = 'brief' select sum(a) over(partition by a order by b rows unbou id estRows task access object operator info Projection 10000.00 root Column#6 └─Shuffle 10000.00 root execution info: concurrency:4, data sources:[TableReader] - └─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between unbounded preceding and current row) + └─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between unbounded preceding and current row) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -83,7 +83,7 @@ explain format = 'brief' select sum(a) over(partition by a order by b rows betwe id estRows task access object operator info Projection 10000.00 root Column#6 └─Shuffle 10000.00 root execution info: concurrency:4, data sources:[TableReader] - └─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between 1 preceding and 1 following) + └─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b rows between 1 preceding and 1 following) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -91,7 +91,7 @@ explain format = 'brief' select sum(a) over(partition by a order by b range betw id estRows task access object operator info Projection 10000.00 root Column#6 └─Shuffle 10000.00 root execution info: concurrency:4, data sources:[TableReader] - └─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between 1 preceding and 1 following) + └─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.b range between 1 preceding and 1 following) └─Sort 10000.00 root test.t.a, test.t.b └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -99,7 +99,7 @@ explain format = 'brief' select sum(a) over(partition by a order by c range betw id estRows task access object operator info Projection 10000.00 root Column#6 └─Shuffle 10000.00 root execution info: concurrency:4, data sources:[TableReader] - └─Window 10000.00 root sum(cast(test.t.a, decimal(32,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.c range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) + └─Window 10000.00 root sum(cast(test.t.a, decimal(10,0) BINARY))->Column#6 over(partition by test.t.a order by test.t.c range between interval "2:30" "MINUTE_SECOND" preceding and interval "2:30" "MINUTE_SECOND" following) └─Sort 10000.00 root test.t.a, test.t.c └─TableReader 10000.00 root data:TableFullScan └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo @@ -110,7 +110,7 @@ analyze table t1; explain format = 'brief' select sum(a) over(partition by b) from t1; id estRows task access object operator info Projection 2.00 root Column#4 -└─Window 2.00 root sum(cast(test.t1.a, decimal(32,0) BINARY))->Column#4 over(partition by test.t1.b) +└─Window 2.00 root sum(cast(test.t1.a, decimal(10,0) BINARY))->Column#4 over(partition by test.t1.b) └─Sort 2.00 root test.t1.b └─TableReader 2.00 root data:TableFullScan └─TableFullScan 2.00 cop[tikv] table:t1 keep order:false @@ -120,7 +120,7 @@ explain format = 'brief' select sum(a) over(partition by b) from t1; id estRows task access object operator info Projection 3.00 root Column#4 └─Shuffle 3.00 root execution info: concurrency:2, data sources:[TableReader] - └─Window 3.00 root sum(cast(test.t1.a, decimal(32,0) BINARY))->Column#4 over(partition by test.t1.b) + └─Window 3.00 root sum(cast(test.t1.a, decimal(10,0) BINARY))->Column#4 over(partition by test.t1.b) └─Sort 3.00 root test.t1.b └─TableReader 3.00 root data:TableFullScan └─TableFullScan 3.00 cop[tikv] table:t1 keep order:false diff --git a/cmd/explaintest/run-tests.sh b/cmd/explaintest/run-tests.sh index 0ebcabca0b2d5..e05fc2ea6bf35 100755 --- a/cmd/explaintest/run-tests.sh +++ b/cmd/explaintest/run-tests.sh @@ -28,6 +28,7 @@ record_case="" create=0 create_case="" stats="s" +collation_opt=2 set -eu trap 'set +e; PIDS=$(jobs -p); [ -n "$PIDS" ] && kill -9 $PIDS' EXIT @@ -40,6 +41,11 @@ function help_message() -h: Print this help message. + -d : \"y\" or \"Y\" for only enabling the new collation during test. + \"n\" or \"N\" for only disabling the new collation during test. + \"b\" or \"B\" for both tests [default]. + Enable/Disable the new collation during the explain test. + -s : Use tidb-server in for testing. eg. \"./run-tests.sh -s ./explaintest_tidb-server\" @@ -105,7 +111,7 @@ function extract_stats() unzip -qq s.zip } -while getopts "t:s:r:b:c:i:h:p" opt; do +while getopts "t:s:r:b:d:c:i:h:p" opt; do case $opt in t) tests="$OPTARG" @@ -131,6 +137,20 @@ while getopts "t:s:r:b:c:i:h:p" opt; do ;; esac ;; + d) + case $OPTARG in + y|Y) + collation_opt=1 + ;; + n|N) + collation_opt=0 + ;; + *) + help_messge 1>&2 + exit 1 + ;; + esac + ;; h) help_message exit 0 @@ -216,47 +236,84 @@ done port=${ports[0]} status=${ports[1]} -echo "start tidb-server, log file: $explain_test_log" -if [ "${TIDB_TEST_STORE_NAME}" = "tikv" ]; then - $tidb_server -P "$port" -status "$status" -config config.toml -store tikv -path "${TIKV_PATH}" > $explain_test_log 2>&1 & - SERVER_PID=$! -else - $tidb_server -P "$port" -status "$status" -config config.toml -store unistore -path "" > $explain_test_log 2>&1 & - SERVER_PID=$! -fi -echo "tidb-server(PID: $SERVER_PID) started" - -sleep 5 - -if [ $record -eq 1 ]; then - if [ "$record_case" = 'all' ]; then - echo "record all cases" - $explain_test -port "$port" -status "$status" --record --log-level=error - else - echo "record result for case: \"$record_case\"" - $explain_test -port "$port" -status "$status" --record $record_case --log-level=error +function start_tidb_server() +{ + config_file="config.toml" + if [[ $enabled_new_collation = 0 ]]; then + config_file="disable_new_collation.toml" fi -elif [ $create -eq 1 ]; then - if [ "$create_case" = 'all' ]; then - echo "create all cases" - $explain_test -port "$port" -status "$status" --create --log-level=error + echo "start tidb-server, log file: $explain_test_log" + if [ "${TIDB_TEST_STORE_NAME}" = "tikv" ]; then + $tidb_server -P "$port" -status "$status" -config $config_file -store tikv -path "${TIKV_PATH}" > $explain_test_log 2>&1 & + SERVER_PID=$! else - echo "create result for case: \"$create_case\"" - $explain_test -port "$port" -status "$status" --create $create_case --log-level=error + $tidb_server -P "$port" -status "$status" -config $config_file -store unistore -path "" > $explain_test_log 2>&1 & + SERVER_PID=$! fi -else - if [ -z "$tests" ]; then - echo "run all explain test cases" + echo "tidb-server(PID: $SERVER_PID) started" +} + +function run_explain_test() +{ + coll_disabled="false" + coll_msg="enabled new collation" + if [[ $enabled_new_collation = 0 ]]; then + coll_disabled="true" + coll_msg="disabled new collation" + fi + if [ $record -eq 1 ]; then + if [ "$record_case" = 'all' ]; then + echo "record all cases" + $explain_test -port "$port" -status "$status" --collation-disable=$coll_disabled --record --log-level=error + else + echo "record result for case: \"$record_case\"" + $explain_test -port "$port" -status "$status" --collation-disable=$coll_disabled --record $record_case --log-level=error + fi + elif [ $create -eq 1 ]; then + if [ "$create_case" = 'all' ]; then + echo "create all cases" + $explain_test -port "$port" -status "$status" --collation-disable=$coll_disabled --create --log-level=error + else + echo "create result for case: \"$create_case\"" + $explain_test -port "$port" -status "$status" --collation-disable=$coll_disabled --create $create_case --log-level=error + fi else - echo "run explain test cases: $tests" + if [ -z "$tests" ]; then + echo "run all explain test cases ($coll_msg)" + else + echo "run explain test cases($coll_msg): $tests" + fi + $explain_test -port "$port" -status "$status" --collation-disable=$coll_disabled --log-level=error $tests fi - $explain_test -port "$port" -status "$status" --log-level=error $tests +} + +function check_data_race() { + race=`grep 'DATA RACE' $explain_test_log || true` + if [ ! -z "$race" ]; then + echo "tidb-server DATA RACE!" + cat $explain_test_log + exit 1 + fi +} + +enabled_new_collation="" + +if [[ $collation_opt = 0 || $collation_opt = 2 ]]; then + enabled_new_collation=0 + start_tidb_server + sleep 5 + run_explain_test + kill -9 $SERVER_PID + check_data_race fi -race=`grep 'DATA RACE' $explain_test_log || true` -if [ ! -z "$race" ]; then - echo "tidb-server DATA RACE!" - cat $explain_test_log - exit 1 +if [[ $collation_opt = 1 || $collation_opt = 2 ]]; then + enabled_new_collation=1 + start_tidb_server + sleep 5 + run_explain_test + kill -9 $SERVER_PID + check_data_race fi -echo "explaintest end" + +echo "explaintest passed!" diff --git a/cmd/explaintest/s.zip b/cmd/explaintest/s.zip index c3f94fe26af69..d673528b1cb30 100644 Binary files a/cmd/explaintest/s.zip and b/cmd/explaintest/s.zip differ diff --git a/cmd/explaintest/t/agg_predicate_pushdown.test b/cmd/explaintest/t/agg_predicate_pushdown.test new file mode 100644 index 0000000000000..0779fe9744030 --- /dev/null +++ b/cmd/explaintest/t/agg_predicate_pushdown.test @@ -0,0 +1,21 @@ +drop database if exists agg_predicate_pushdown; +create database agg_predicate_pushdown; + +create table t(a int, b int, c int); + +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1) and (a > 2) and 1 and (b > 2) and (avg(c) > 3); + +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 or b > 2) and (a > 2 or b < 1) and 1 and (b > 2) and (avg(c) > 3); + +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 and b > 2) or (a > 2 and b < 1) or (b > 2 and avg(c) > 3); + +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 or avg(c) > 1) and (a < 3); + +desc format='brief' select a, b, avg(c) from t group by a, b, c having +(a > 1 and avg(c) > 1) or (a < 3); + +use test; diff --git a/cmd/explaintest/t/collation.test b/cmd/explaintest/t/collation.test deleted file mode 100644 index 2b67de475c47c..0000000000000 --- a/cmd/explaintest/t/collation.test +++ /dev/null @@ -1,9 +0,0 @@ ---disable_warnings -drop table if exists t; ---enable_warnings -create table t(a char(10) collate utf8mb4_unicode_ci, b char(10) collate utf8mb4_general_ci); -insert into t values ('å•Š', 'æ’’æ—¦'); -select coercibility(concat(a, b)) from t; -select coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) from t; -select coercibility(convert('a' using utf8mb4)); -select coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci); \ No newline at end of file diff --git a/cmd/explaintest/t/collation_agg_func.test b/cmd/explaintest/t/collation_agg_func.test new file mode 100644 index 0000000000000..eb7ada2209981 --- /dev/null +++ b/cmd/explaintest/t/collation_agg_func.test @@ -0,0 +1,102 @@ +# These tests test the aggregate function's behavior according to collation. +# The result of min/max of enum/set is wrong, please fix them soon. + +# prepare database +create database collation_agg_func; +use collation_agg_func; + +create table t(id int, value varchar(20) charset utf8mb4 collate utf8mb4_general_ci, value1 varchar(20) charset utf8mb4 collate utf8mb4_bin); +insert into t values (1, 'abc', 'abc '),(4, 'Abc', 'abc'),(3,'def', 'def '), (5, 'abc', 'ABC'); + +# group_concat +desc format='brief' select group_concat(value order by 1) from t; +select group_concat(value order by 1) from t; +desc format='brief' select group_concat(value) from t; +select group_concat(value) from t; +desc format='brief' select group_concat(value collate utf8mb4_bin) from t; +select group_concat(value collate utf8mb4_bin) from t; +desc format='brief' select group_concat(distinct value order by 1) from t; +select upper(group_concat(distinct value order by 1)) from t; +desc format='brief' select group_concat(distinct value collate utf8mb4_bin order by 1) from t; +select upper(group_concat(distinct value collate utf8mb4_bin order by 1)) from t; +desc format='brief' select group_concat(distinct value) from t; +select upper(group_concat(distinct value)) from t; +desc format='brief' select group_concat(distinct value collate utf8mb4_bin) from t; +select upper(group_concat(distinct value collate utf8mb4_bin)) from t; + +# count(distinct) +desc format='brief' select count(distinct value) from t; +select count(distinct value) from t; +desc format='brief' select count(distinct value collate utf8mb4_bin) from t; +select count(distinct value collate utf8mb4_bin) from t; +desc format='brief' select count(distinct value, value1) from t; +select count(distinct value, value1) from t; +desc format='brief' select count(distinct value collate utf8mb4_bin, value1) from t; +select count(distinct value collate utf8mb4_bin, value1) from t; + +# approxCountDistinct +desc format='brief' select approx_count_distinct(value) from t; +select approx_count_distinct(value) from t; +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin) from t; +select approx_count_distinct(value collate utf8mb4_bin) from t; +desc format='brief' select approx_count_distinct(value, value1) from t; +select approx_count_distinct(value, value1) from t; +desc format='brief' select approx_count_distinct(value collate utf8mb4_bin, value1) from t; +select approx_count_distinct(value collate utf8mb4_bin, value1) from t; + +# minMax +create table tt(a char(10), b enum('a', 'B', 'c'), c set('a', 'B', 'c'), d json) collate utf8mb4_general_ci; +insert into tt values ("a", "a", "a", JSON_OBJECT("a", "a")); +--error 1265 +insert into tt values ("A", "A", "A", JSON_OBJECT("A", "A")); +--error 1265 +insert into tt values ("b", "b", "b", JSON_OBJECT("b", "b")); +insert into tt values ("B", "B", "B", JSON_OBJECT("B", "B")); +insert into tt values ("c", "c", "c", JSON_OBJECT("c", "c")); +--error 1265 +insert into tt values ("C", "C", "C", JSON_OBJECT("C", "C")); +split table tt by (0), (1), (2), (3), (4), (5); +desc format='brief' select min(a) from tt; +select min(a) from tt; +desc format='brief' select min(a collate utf8mb4_bin) from tt; +select min(a collate utf8mb4_bin) from tt; +desc format='brief' select max(a) from tt; +select max(a) from tt; +desc format='brief' select max(a collate utf8mb4_bin) from tt; +select max(a collate utf8mb4_bin) from tt; +desc format='brief' select min(b) from tt; +select min(b) from tt; +desc format='brief' select min(b collate utf8mb4_bin) from tt; +# Fix me later. +# select min(b collate utf8mb4_bin) from tt; +desc format='brief' select max(b) from tt; +select max(b) from tt; +desc format='brief' select max(b collate utf8mb4_bin) from tt; +# Fix me later. +# select max(b collate utf8mb4_bin) from tt; +desc format='brief' select min(c) from tt; +select min(c) from tt; +desc format='brief' select min(c collate utf8mb4_bin) from tt; +# Fix me later. +# select min(c collate utf8mb4_bin) from tt; +desc format='brief' select max(c) from tt; +select max(c) from tt; +desc format='brief' select max(c collate utf8mb4_bin) from tt; +# Fix me later. +# select max(c collate utf8mb4_bin) from tt; +desc format='brief' select min(d) from tt; +select min(d) from tt; +--error 1253 +desc format='brief' select min(d collate utf8mb4_bin) from tt; +--error 1253 +select min(d collate utf8mb4_bin) from tt; +desc format='brief' select max(d) from tt; +select max(d) from tt; +--error 1253 +desc format='brief' select max(d collate utf8mb4_bin) from tt; +--error 1253 +select max(d collate utf8mb4_bin) from tt; + +# cleanup environment +drop database collation_agg_func; +use test diff --git a/cmd/explaintest/t/collation_check_use_collation.test b/cmd/explaintest/t/collation_check_use_collation.test index 67e75f32e38f9..04d4642656de9 100644 --- a/cmd/explaintest/t/collation_check_use_collation.test +++ b/cmd/explaintest/t/collation_check_use_collation.test @@ -11,13 +11,80 @@ CREATE TABLE `t` ( CREATE TABLE `t1` ( `a` char(10) COLLATE utf8mb4_general_ci DEFAULT NULL ); -insert into t values ("a"); -insert into t1 values ("A"); +insert into t values ("A"); +# Ignore error for the disabled new-collation case. +--error 1265 +insert into t1 values ("a"); select a as a_col from t where t.a = all (select a collate utf8mb4_general_ci from t1); select a as a_col from t where t.a != any (select a collate utf8mb4_general_ci from t1); select a as a_col from t where t.a <= all (select a collate utf8mb4_general_ci from t1); select a as a_col from t where t.a <= any (select a collate utf8mb4_general_ci from t1); select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); +## Check rewrite in expression + +# enum part +drop table if exists t; +create table t(a enum('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +drop table if exists t; +create table t(a enum('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +# Ignore error for the disabled new-collation case. +--error 1265 +insert into t values ("B", "b"); +select * from t where 'B' collate utf8mb4_general_ci in (a); +select * from t where 'B' collate utf8mb4_bin in (a); +select * from t where 'B' collate utf8mb4_bin in (a, b); +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +select * from t where 1 in (a); +select * from t where 2 in (a); +select * from t where 1 in (a, 0); +select * from t where a between 1 and 2; +select * from t where a between 1 and "a"; +select * from t where a between "a" and "b"; +select * from t where 2 between a and "c"; +select * from t where 2 between a and 3; +select * from t where "b" between a and a; +select * from t where "b" collate utf8mb4_bin between a and a; +select * from t where "b" between a and 3; + +# set part +drop table if exists t; +create table t(a set('a', 'b'), b varchar(20)); +insert into t values ("a", "b"); +select * from t where a in (a); +drop table if exists t; +create table t(a set('a', 'b') charset utf8mb4 collate utf8mb4_general_ci, b varchar(20)); +insert into t values ("b", "c"); +# Ignore error for the disabled new-collation case. +--error 1265 +insert into t values ("B", "b"); +select * from t where 'B' collate utf8mb4_general_ci in (a); +select * from t where 'B' collate utf8mb4_bin in (a); +select * from t where 'B' collate utf8mb4_bin in (a, b); +select * from t where 'B' collate utf8mb4_bin in (a, "a", 1); +select * from t where 'B' collate utf8mb4_bin in (a, "B", 1); +select * from t where 1 in (a); +select * from t where 2 in (a); +select * from t where 1 in (a, 0); +select * from t where a between 1 and 2; +select * from t where a between 1 and "a"; +select * from t where a between "a" and "b"; +select * from t where 2 between a and "c"; +select * from t where 2 between a and 3; +select * from t where "b" between a and a; +select * from t where "b" collate utf8mb4_bin between a and a; +select * from t where "b" between a and 3; + +# check build range +drop table if exists tbl_2; +create table tbl_2 ( col_20 bigint not null , col_21 smallint not null , col_22 decimal(24,10) default null , col_23 tinyint default 71 not null , col_24 bigint not null , col_25 tinyint default 18 , col_26 varchar(330) collate utf8_bin not null , col_27 char(77) collate utf8mb4_unicode_ci , col_28 char(46) collate utf8_general_ci not null , col_29 smallint unsigned not null , primary key idx_13 ( col_27(5) ) , key idx_14 ( col_24 ) , unique key idx_15 ( col_23,col_21,col_28,col_29,col_24 ) ) collate utf8_bin ; +insert ignore into tbl_2 values ( 5888267793391993829,5371,94.63,-109,5728076076919247337,89,'WUicqUTgdGJcjbC','SapBPqczTWWSN','xUSwH',49462 ); +select col_25 from tbl_2 where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +select col_25 from tbl_2 use index(primary) where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); + # cleanup environment use test diff --git a/cmd/explaintest/t/collation_misc.test b/cmd/explaintest/t/collation_misc.test new file mode 100644 index 0000000000000..443c6c4106cc0 --- /dev/null +++ b/cmd/explaintest/t/collation_misc.test @@ -0,0 +1,65 @@ +# prepare database +create database collation_misc; +use collation_misc; + +# ChangingCharsetToUtf8 +create table t1(a varchar(20) charset utf8); +insert into t1 values ("t1_value"); +alter table t1 collate uTf8mB4_uNiCoDe_Ci charset Utf8mB4 charset uTF8Mb4 collate UTF8MB4_BiN; +alter table t1 modify column a varchar(20) charset utf8mb4; +select * from t1; +create table t(a varchar(20) charset latin1); +insert into t values ("t_value"); +alter table t modify column a varchar(20) charset latin1; +select * from t; +--error 8200 +alter table t modify column a varchar(20) charset utf8; +--error 8200 +alter table t modify column a varchar(20) charset utf8mb4; +--error 8200 +alter table t modify column a varchar(20) charset utf8 collate utf8_bin; +--error 8200 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8mb4_general_ci; +--error 1273 +alter table t modify column a varchar(20) charset utf8mb4 collate utf8bin; +--error 1302, 1273 +alter table t collate LATIN1_GENERAL_CI charset utf8 collate utf8_bin; +--error 1253, 1273 +alter table t collate LATIN1_GENERAL_CI collate UTF8MB4_UNICODE_ci collate utf8_bin; + +# TestCharsetDatabase +create database if not exists cd_test_utf8 CHARACTER SET utf8 COLLATE utf8_bin; +--error 1273 +create database if not exists cd_test_latin1 CHARACTER SET latin1 COLLATE latin1_swedish_ci; +use cd_test_utf8; +select @@character_set_database; +select @@collation_database; +--error 1049 +use cd_test_latin1; +select @@character_set_database; +select @@collation_database; + +# DefaultDBAfterDropCurDB +--error 1273 +create database if not exists test_db CHARACTER SET latin1 COLLATE latin1_swedish_ci; + +# CollationUnion +with cte as (select cast('2010-09-09' as date) a union select '2010-09-09 ') select count(*) from cte; + +# Issue26989 +set names utf8mb4 collate utf8mb4_general_ci; +select position('a' in 'AA'); +select locate('a', 'AA'); +select locate('a', 'a'); +set names utf8mb4; + +# CharacterSetCollations +SELECT default_collate_name, maxlen FROM information_schema.character_sets ORDER BY character_set_name; +SELECT character_set_name, id, sortlen FROM information_schema.collations ORDER BY collation_name, id; +select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY where COLLATION_NAME='utf8mb4_bin'; + +# charset +show charset; +show collation; + +use test; diff --git a/cmd/explaintest/t/collation_pointget.test b/cmd/explaintest/t/collation_pointget.test new file mode 100644 index 0000000000000..ea4cdca6f05c9 --- /dev/null +++ b/cmd/explaintest/t/collation_pointget.test @@ -0,0 +1,129 @@ +# prepare database +create database collation_point_get; +use collation_point_get; + +# pointGet IndexLookupChar +drop table if exists t; +create table t(a char(2), b char(2), index idx_1(a)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +select * from t where a = "aab"; +# Test query with table alias +select * from t tmp where a = "aa"; +select * from t tmp where a = "aab"; +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +drop table if exists t; +create table t(a char(2) binary, b char(2), index idx_1(a)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +select * from t where a = ""; +select * from t where a = " "; +select * from t where a = " "; +select * from t where a = " "; + +# pointGet AliasTableCharPK +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select * from t tmp where a = "aa"; +select * from t tmp where a = "aab"; +truncate table t; +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +select * from t tmp where a = "a "; +select * from t tmp where a = "a "; +# Test CHAR BINARY. +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t tmp where a = "a"; +select * from t tmp where a = "a "; +select * from t tmp where a = "a "; +select * from t tmp where a = ""; +select * from t tmp where a = " "; +select * from t tmp where a = " "; +# Test both wildcard and column name exist in select field list +drop table if exists t; +create table t(a char(2) primary key, b char(2)); +insert into t values("aa", "bb"); +select *, a from t tmp where a = "aa"; +# Test using table alias in field list +select tmp.* from t tmp where a = "aa"; +select tmp.a, tmp.b from t tmp where a = "aa"; +select tmp.*, tmp.a, tmp.b from t tmp where a = "aa"; +select tmp.* from t tmp where a = "aab"; +select tmp.a, tmp.b from t tmp where a = "aab"; +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +select tmp.*, tmp.a, tmp.b from t tmp where a = "aab"; +# Test using table alias in where clause +select * from t tmp where tmp.a = "aa"; +select a, b from t tmp where tmp.a = "aa"; +select *, a, b from t tmp where tmp.a = "aa"; +# Unknown table name in where clause and field list +--error 1054 +select a from t where xxxxx.a = "aa"; +--error 1054 +select xxxxx.a from t where a = "aa"; +# When an alias is provided, it completely hides the actual name of the table. +--error 1054 +select a from t tmp where t.a = "aa"; +--error 1054 +select t.a from t tmp where a = "aa"; +--error 1051 +select t.* from t tmp where a = "aa"; + +# PointGetCharPK +drop table if exists t; +create table t(a char(4) primary key, b char(4)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +select * from t where a = "aab"; +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +# Test CHAR BINARY. +drop table if exists t; +create table t(a char(2) binary primary key, b char(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +select * from t where a = ""; +select * from t where a = " "; +select * from t where a = " "; + +# PointGetVarcharPK +drop table if exists t; +create table t(a varchar(2) primary key, b varchar(2)); +insert into t values("aa", "bb"); +select * from t where a = "aa"; +select * from t where a = "aab"; +truncate table t; +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +# Test VARCHAR BINARY. +drop table if exists t; +create table t(a varchar(2) binary primary key, b varchar(2)); +insert into t values(" ", " "); +insert into t values("a ", "b "); +select * from t where a = "a"; +select * from t where a = "a "; +select * from t where a = "a "; +select * from t where a = ""; +select * from t where a = " "; +select * from t where a = " "; + +use mysql; diff --git a/cmd/explaintest/t/common_collation.test b/cmd/explaintest/t/common_collation.test new file mode 100644 index 0000000000000..8f19d9d1a3e27 --- /dev/null +++ b/cmd/explaintest/t/common_collation.test @@ -0,0 +1,41 @@ +--disable_warnings +drop table if exists t; +--enable_warnings +create table t(a char(10) collate utf8mb4_unicode_ci, b char(10) collate utf8mb4_general_ci); +insert into t values ('å•Š', 'æ’’æ—¦'); +select coercibility(concat(a, b)) from t; +select coercibility(convert(concat(a, b) using utf8mb4) collate utf8mb4_general_ci) from t; +select coercibility(convert('a' using utf8mb4)); +select coercibility(convert('a' using utf8mb4) collate utf8mb4_general_ci); + +# test for coercibility and collation with json type +# see details from https://github.com/pingcap/tidb/issues/31541 and https://github.com/pingcap/tidb/issues/31320#issuecomment-1010599311 +--disable_warnings +drop table if exists t; +--enable_warnings +create table t (a char(20), b blob(100), c text, d json, e timestamp, f set('a一','b二','c三','då››'), g text, h enum('a一','b二','c三','då››') default 'c三'); +insert into t values ('你好', '你好', '你好', '{\"测试\": \"你好\"}', '2018-10-13', 1, '你好', 'a一'); +select coercibility(a), coercibility(b), coercibility(c), coercibility(d), coercibility(e), coercibility(f), coercibility(g), coercibility(h) from t; +select collation(d), collation(upper(d)), collation(elt(1, d, 0x12)), collation(elt(1, elt(1, d, 0x12), 0x12)), collation(elt(1, d, b)) from t; +drop table t; +create table t(a binary, b json, c char charset gbk); +insert into t values ('a', '{"a":"b"}', 'a'); +select collation(concat(a, b)), collation(concat(b, a)), collation(concat(0x61, b)), collation(concat(b, 0x61)), collation(concat(c, b)), collation(concat(b, c)) from t; + +# test greatest and least function with collation. +DROP TABLE IF EXISTS t2; +CREATE TABLE t2 ( + id INT NOT NULL PRIMARY KEY auto_increment, + `col_91` char(47) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `col_92` int(10) unsigned DEFAULT '2478966067', + `col_97` char(32) COLLATE utf8mb4_bin NOT NULL +) collate utf8mb4_general_ci; + +INSERT INTO `t2` VALUES (17,'UUtJeaV',497551109,'snRXXCZHBPW'); + +SET names utf8mb4 collate utf8mb4_bin; +SELECT greatest( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +SELECT least( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +SET names utf8mb4 collate utf8mb4_general_ci; +SELECT greatest( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; +SELECT least( col_91 , col_97 ) as expr1 FROM t2 ORDER BY id; diff --git a/cmd/explaintest/t/cte.test b/cmd/explaintest/t/cte.test index b5fda97071cc8..df9ee6c3b8d06 100644 --- a/cmd/explaintest/t/cte.test +++ b/cmd/explaintest/t/cte.test @@ -226,3 +226,33 @@ create table tpk1(c1 int primary key); insert into tpk1 values(1), (2), (3); explain with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1; with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1; +#case 34 +--echo // Test CTE as inner side of Apply +drop table if exists t1, t2; +create table t1(c1 int, c2 int); +insert into t1 values(2, 1); +insert into t1 values(2, 2); +create table t2(c1 int, c2 int); +insert into t2 values(1, 1); +insert into t2 values(3, 2); +explain select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); + +--echo // Test semi apply. +insert into t1 values(2, 3); +explain select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); +select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1); + +--echo // Same as above, but test recursive cte. +explain select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1); +select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1); + +explain select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1); +select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1); + +--echo // Test correlated col is in recursive part. +explain select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); + +explain select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); +select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1); diff --git a/cmd/explaintest/t/explain_cte.test b/cmd/explaintest/t/explain_cte.test index c657ad5c68898..fd6ba042c9fed 100644 --- a/cmd/explaintest/t/explain_cte.test +++ b/cmd/explaintest/t/explain_cte.test @@ -42,3 +42,219 @@ explain with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 fro explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 1) select * from cte1; explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 100 offset 100) select * from cte1; explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 0 offset 0) select * from cte1; + +# TPC-DS Q11 +CREATE TABLE `customer` ( + `c_customer_sk` int(11) NOT NULL, + `c_customer_id` char(16) NOT NULL, + `c_current_cdemo_sk` int(11) DEFAULT NULL, + `c_current_hdemo_sk` int(11) DEFAULT NULL, + `c_current_addr_sk` int(11) DEFAULT NULL, + `c_first_shipto_date_sk` int(11) DEFAULT NULL, + `c_first_sales_date_sk` int(11) DEFAULT NULL, + `c_salutation` char(10) DEFAULT NULL, + `c_first_name` char(20) DEFAULT NULL, + `c_last_name` char(30) DEFAULT NULL, + `c_preferred_cust_flag` char(1) DEFAULT NULL, + `c_birth_day` int(11) DEFAULT NULL, + `c_birth_month` int(11) DEFAULT NULL, + `c_birth_year` int(11) DEFAULT NULL, + `c_birth_country` varchar(20) DEFAULT NULL, + `c_login` char(13) DEFAULT NULL, + `c_email_address` char(50) DEFAULT NULL, + `c_last_review_date_sk` int(11) DEFAULT NULL, + PRIMARY KEY (`c_customer_sk`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `store_sales` ( + `ss_sold_date_sk` int(11) DEFAULT NULL, + `ss_sold_time_sk` int(11) DEFAULT NULL, + `ss_item_sk` int(11) NOT NULL, + `ss_customer_sk` int(11) DEFAULT NULL, + `ss_cdemo_sk` int(11) DEFAULT NULL, + `ss_hdemo_sk` int(11) DEFAULT NULL, + `ss_addr_sk` int(11) DEFAULT NULL, + `ss_store_sk` int(11) DEFAULT NULL, + `ss_promo_sk` int(11) DEFAULT NULL, + `ss_ticket_number` int(11) NOT NULL, + `ss_quantity` int(11) DEFAULT NULL, + `ss_wholesale_cost` decimal(7,2) DEFAULT NULL, + `ss_list_price` decimal(7,2) DEFAULT NULL, + `ss_sales_price` decimal(7,2) DEFAULT NULL, + `ss_ext_discount_amt` decimal(7,2) DEFAULT NULL, + `ss_ext_sales_price` decimal(7,2) DEFAULT NULL, + `ss_ext_wholesale_cost` decimal(7,2) DEFAULT NULL, + `ss_ext_list_price` decimal(7,2) DEFAULT NULL, + `ss_ext_tax` decimal(7,2) DEFAULT NULL, + `ss_coupon_amt` decimal(7,2) DEFAULT NULL, + `ss_net_paid` decimal(7,2) DEFAULT NULL, + `ss_net_paid_inc_tax` decimal(7,2) DEFAULT NULL, + `ss_net_profit` decimal(7,2) DEFAULT NULL, + PRIMARY KEY (`ss_item_sk`,`ss_ticket_number`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `date_dim` ( + `d_date_sk` int(11) NOT NULL, + `d_date_id` char(16) NOT NULL, + `d_date` date DEFAULT NULL, + `d_month_seq` int(11) DEFAULT NULL, + `d_week_seq` int(11) DEFAULT NULL, + `d_quarter_seq` int(11) DEFAULT NULL, + `d_year` int(11) DEFAULT NULL, + `d_dow` int(11) DEFAULT NULL, + `d_moy` int(11) DEFAULT NULL, + `d_dom` int(11) DEFAULT NULL, + `d_qoy` int(11) DEFAULT NULL, + `d_fy_year` int(11) DEFAULT NULL, + `d_fy_quarter_seq` int(11) DEFAULT NULL, + `d_fy_week_seq` int(11) DEFAULT NULL, + `d_day_name` char(9) DEFAULT NULL, + `d_quarter_name` char(6) DEFAULT NULL, + `d_holiday` char(1) DEFAULT NULL, + `d_weekend` char(1) DEFAULT NULL, + `d_following_holiday` char(1) DEFAULT NULL, + `d_first_dom` int(11) DEFAULT NULL, + `d_last_dom` int(11) DEFAULT NULL, + `d_same_day_ly` int(11) DEFAULT NULL, + `d_same_day_lq` int(11) DEFAULT NULL, + `d_current_day` char(1) DEFAULT NULL, + `d_current_week` char(1) DEFAULT NULL, + `d_current_month` char(1) DEFAULT NULL, + `d_current_quarter` char(1) DEFAULT NULL, + `d_current_year` char(1) DEFAULT NULL, + PRIMARY KEY (`d_date_sk`) /*T![clustered_index] NONCLUSTERED */ +); +CREATE TABLE `web_sales` ( + `ws_sold_date_sk` int(11) DEFAULT NULL, + `ws_sold_time_sk` int(11) DEFAULT NULL, + `ws_ship_date_sk` int(11) DEFAULT NULL, + `ws_item_sk` int(11) NOT NULL, + `ws_bill_customer_sk` int(11) DEFAULT NULL, + `ws_bill_cdemo_sk` int(11) DEFAULT NULL, + `ws_bill_hdemo_sk` int(11) DEFAULT NULL, + `ws_bill_addr_sk` int(11) DEFAULT NULL, + `ws_ship_customer_sk` int(11) DEFAULT NULL, + `ws_ship_cdemo_sk` int(11) DEFAULT NULL, + `ws_ship_hdemo_sk` int(11) DEFAULT NULL, + `ws_ship_addr_sk` int(11) DEFAULT NULL, + `ws_web_page_sk` int(11) DEFAULT NULL, + `ws_web_site_sk` int(11) DEFAULT NULL, + `ws_ship_mode_sk` int(11) DEFAULT NULL, + `ws_warehouse_sk` int(11) DEFAULT NULL, + `ws_promo_sk` int(11) DEFAULT NULL, + `ws_order_number` int(11) NOT NULL, + `ws_quantity` int(11) DEFAULT NULL, + `ws_wholesale_cost` decimal(7,2) DEFAULT NULL, + `ws_list_price` decimal(7,2) DEFAULT NULL, + `ws_sales_price` decimal(7,2) DEFAULT NULL, + `ws_ext_discount_amt` decimal(7,2) DEFAULT NULL, + `ws_ext_sales_price` decimal(7,2) DEFAULT NULL, + `ws_ext_wholesale_cost` decimal(7,2) DEFAULT NULL, + `ws_ext_list_price` decimal(7,2) DEFAULT NULL, + `ws_ext_tax` decimal(7,2) DEFAULT NULL, + `ws_coupon_amt` decimal(7,2) DEFAULT NULL, + `ws_ext_ship_cost` decimal(7,2) DEFAULT NULL, + `ws_net_paid` decimal(7,2) DEFAULT NULL, + `ws_net_paid_inc_tax` decimal(7,2) DEFAULT NULL, + `ws_net_paid_inc_ship` decimal(7,2) DEFAULT NULL, + `ws_net_paid_inc_ship_tax` decimal(7,2) DEFAULT NULL, + `ws_net_profit` decimal(7,2) DEFAULT NULL, + PRIMARY KEY (`ws_item_sk`,`ws_order_number`) /*T![clustered_index] NONCLUSTERED */ +); +desc format='brief' with year_total as ( + select c_customer_id customer_id + ,c_first_name customer_first_name + ,c_last_name customer_last_name + ,c_preferred_cust_flag customer_preferred_cust_flag + ,c_birth_country customer_birth_country + ,c_login customer_login + ,c_email_address customer_email_address + ,d_year dyear + ,sum(ss_ext_list_price-ss_ext_discount_amt) year_total + ,'s' sale_type + from customer + ,store_sales + ,date_dim + where c_customer_sk = ss_customer_sk + and ss_sold_date_sk = d_date_sk + group by c_customer_id + ,c_first_name + ,c_last_name + ,c_preferred_cust_flag + ,c_birth_country + ,c_login + ,c_email_address + ,d_year + union all + select c_customer_id customer_id + ,c_first_name customer_first_name + ,c_last_name customer_last_name + ,c_preferred_cust_flag customer_preferred_cust_flag + ,c_birth_country customer_birth_country + ,c_login customer_login + ,c_email_address customer_email_address + ,d_year dyear + ,sum(ws_ext_list_price-ws_ext_discount_amt) year_total + ,'w' sale_type + from customer + ,web_sales + ,date_dim + where c_customer_sk = ws_bill_customer_sk + and ws_sold_date_sk = d_date_sk + group by c_customer_id + ,c_first_name + ,c_last_name + ,c_preferred_cust_flag + ,c_birth_country + ,c_login + ,c_email_address + ,d_year + ) + select + t_s_secyear.customer_id + ,t_s_secyear.customer_first_name + ,t_s_secyear.customer_last_name + ,t_s_secyear.customer_email_address + from year_total t_s_firstyear + ,year_total t_s_secyear + ,year_total t_w_firstyear + ,year_total t_w_secyear + where t_s_secyear.customer_id = t_s_firstyear.customer_id + and t_s_firstyear.customer_id = t_w_secyear.customer_id + and t_s_firstyear.customer_id = t_w_firstyear.customer_id + and t_s_firstyear.sale_type = 's' + and t_w_firstyear.sale_type = 'w' + and t_s_secyear.sale_type = 's' + and t_w_secyear.sale_type = 'w' + and t_s_firstyear.dyear = 2001 + and t_s_secyear.dyear = 2001+1 + and t_w_firstyear.dyear = 2001 + and t_w_secyear.dyear = 2001+1 + and t_s_firstyear.year_total > 0 + and t_w_firstyear.year_total > 0 + and case when t_w_firstyear.year_total > 0 then t_w_secyear.year_total / t_w_firstyear.year_total else 0.0 end + > case when t_s_firstyear.year_total > 0 then t_s_secyear.year_total / t_s_firstyear.year_total else 0.0 end + order by t_s_secyear.customer_id + ,t_s_secyear.customer_first_name + ,t_s_secyear.customer_last_name + ,t_s_secyear.customer_email_address +limit 100; + + +# predicate pushdown +drop table if exists t1; +create table t1 (id int, bench_type varchar(10),version varchar(10),tps int(20)); +insert into t1 (id,bench_type,version,tps) values (1,'sysbench','5.4.0',1111111); +insert into t1 (id,bench_type,version,tps) values (2,'sysbench','6.0.0',222222); +with all_data as +(select * from t1 +),version1 as (select * from all_data where version ='5.4.0' +),version2 as(select * from all_data where version ='6.0.0') +select v1.tps v1_tps,v2.tps v2_tps +from version1 v1, version2 v2 +where v1.bench_type =v2.bench_type; +desc format='brief' with all_data as +(select * from t1 +),version1 as (select * from all_data where version ='5.4.0' +),version2 as(select * from all_data where version ='6.0.0') +select v1.tps v1_tps,v2.tps v2_tps +from version1 v1, version2 v2 +where v1.bench_type =v2.bench_type; diff --git a/cmd/explaintest/t/explain_easy.test b/cmd/explaintest/t/explain_easy.test index 4d3b698bd7d72..b03e30f5e2af7 100644 --- a/cmd/explaintest/t/explain_easy.test +++ b/cmd/explaintest/t/explain_easy.test @@ -30,6 +30,8 @@ explain format = 'brief' select sum(t1.c1 in (select c1 from t2)) from t1; explain format = 'brief' select c1 from t1 where c1 in (select c2 from t2); explain format = 'brief' select (select count(1) k from t1 s where s.c1 = t1.c1 having k != 0) from t1; explain format = 'brief' select * from information_schema.columns; +explain format = 'brief' select * from information_schema.columns where table_name = 'T1'; +explain format = 'brief' select * from information_schema.columns where table_schema = 'TEST' and table_name = 'T1' and column_name = 'c1'; explain format = 'brief' select c2 = (select c2 from t2 where t1.c1 = t2.c1 order by c1 limit 1) from t1; explain format = 'brief' select * from t1 order by c1 desc limit 1; explain format = 'brief' select * from t4 use index(idx) where a > 1 and b > 1 and c > 1 limit 1; @@ -218,3 +220,22 @@ explain format = 'brief' select count(a) from t group by b order by (select coun explain format = 'brief' select (select sum(count(a))) from t; explain format = 'brief' select sum(a), (select sum(a)), count(a) from t group by b order by (select count(a)); drop table if exists t; + +# lower precision for cast to decimal for integer type variables in sum function +create table t(a tinyint, b smallint, c mediumint, d int, e bigint); +insert into mysql.opt_rule_blacklist VALUES("aggregation_push_down"); +admin reload opt_rule_blacklist; +explain format = 'brief' select sum(t1.a) from t t1 join t t2 on t1.a=t2.a; +explain format = 'brief' select sum(t1.b) from t t1 join t t2 on t1.b=t2.b; +explain format = 'brief' select sum(t1.c) from t t1 join t t2 on t1.c=t2.c; +explain format = 'brief' select sum(t1.d) from t t1 join t t2 on t1.d=t2.d; +explain format = 'brief' select sum(t1.e) from t t1 join t t2 on t1.e=t2.e; +# note that avg will be converted to count and sum, and .decimal field will be non-zero +explain format = 'brief' select avg(t1.a) from t t1 join t t2 on t1.a=t2.a; +explain format = 'brief' select avg(t1.b) from t t1 join t t2 on t1.b=t2.b; +explain format = 'brief' select avg(t1.c) from t t1 join t t2 on t1.c=t2.c; +explain format = 'brief' select avg(t1.d) from t t1 join t t2 on t1.d=t2.d; +explain format = 'brief' select avg(t1.e) from t t1 join t t2 on t1.e=t2.e; +drop table if exists t; +delete from mysql.opt_rule_blacklist where name="aggregation_push_down"; +admin reload opt_rule_blacklist; diff --git a/cmd/explaintest/t/explain_generate_column_substitute.test b/cmd/explaintest/t/explain_generate_column_substitute.test index 152d2c2a6dc7f..1acde78a709e7 100644 --- a/cmd/explaintest/t/explain_generate_column_substitute.test +++ b/cmd/explaintest/t/explain_generate_column_substitute.test @@ -1,3 +1,4 @@ +set names utf8mb4; use test; drop table if exists t; create table t(a int, b real, c bigint as ((a+1)) virtual, e real as ((b+a))); @@ -259,3 +260,45 @@ select * from t004 where timestampadd(microsecond, 1, a) = timestampadd(microsec alter table t004 add index eidx ((timestampadd(microsecond, 1, a))); select * from t004 use index(eidx) where timestampadd(microsecond, 1, a) = timestampadd(microsecond, 1, '2021-08-20'); select * from t004 ignore index (eidx) where timestampadd(microsecond, 1, a) = timestampadd(microsecond, 1, '2021-08-20'); + +drop table if exists t; +create table t ( c_int int, c_str varchar(40) character set utf8 collate utf8_general_ci, primary key(c_int, c_str(9)) clustered, key idx((reverse(c_str)))); +replace into t (c_int, c_str) values (9, "beautiful hermann"); +select reverse(c_str) from t use index(idx); + +drop table if exists t1; +drop table if exists t2; +create table t1 (c_int int, c_str varchar(40) character set utf8 collate utf8_general_ci, c_datetime datetime, c_timestamp timestamp, c_double double, c_decimal decimal(12, 6), c_enum enum('blue','green','red','yellow','white','orange','purple'), primary key (c_datetime) , key(c_int) , key(c_datetime) , key((c_int + 1)), key((c_int -1)), key((lower(c_str))), key((md5(c_str))), key((reverse(c_str))), key((upper(c_str)))); +create table t2 like t1; +insert into t1 values(11, 'loving grothendieck', '2020-02-02 19:25:49', '2020-03-27 15:17:14', 3.269, 1.851000, 'white' ); +insert into t1 values(11, 'quirky kapitsa' , '2020-06-21 03:55:31', '2020-02-29 17:02:48', 6.94, 1.851000, 'yellow'); +insert into t1 values( 7, 'boring bouman' , '2020-05-10 00:01:04', '2020-02-01 20:18:00', 84.096168, 6.996000, 'white' ); +insert into t2 values( 11, 'wizardly antonelli', '2020-01-30 17:27:17', '2020-01-01 10:05:31', 6.886177, 6.332000, 'green' ); +insert into t2 values( 2, 'angry kapitsa' , '2020-03-30 05:09:44', '2020-02-15 00:36:52', 95.798378, 3.118000, 'blue' ); +insert into t2 values( 7, 'dreamy shamir' , '2020-05-28 14:13:42', '2020-06-02 07:23:22', 26.623227, 3.105000, 'orange'); +begin; +delete from t2 where c_decimal > c_double/2 order by c_int, c_str, c_double, c_decimal limit 1; +desc format='brief' select t2.c_enum from t2,t1 where t1.c_int - 1 = t2.c_int - 1 order by t2.c_enum; +select t2.c_enum from t2,t1 where t1.c_int - 1 = t2.c_int - 1 order by t2.c_enum; +drop table t1, t2; + +drop table t; + +drop table if exists t1,t2; +create table t1 (c_int int, c_str varchar(40) ,primary key (c_int) , key(c_str(36)) , key((c_int + 1))) partition by hash (c_int) partitions 4 ; +create table t2 like t1 ; +insert into t1 values (1, 'sleepy kowalevski'); +insert into t2 values (3, 'unruffled chaplygin'); +select (select t2.c_str from t2 where t2.c_int + 1 = 4 order by t2.c_str) x from t1; +select (select t2.c_str from t2 where t2.c_int = 3 order by t2.c_str) x from t1; + +drop table t1,t2; + +-- for issue 33237 +drop table if exists t1, t2; +create table t1 (c_int int, c_decimal decimal(12, 6), primary key (c_int) nonclustered,key((c_int + 1))) ; +create table t2 like t1; +explain format = 'brief' select /*+ agg_to_cop() */ * from t1 where c_decimal in (select c_decimal from t2 where t2.c_int + 1 = 8 + 1); +drop table t1; +drop table t2; + diff --git a/cmd/explaintest/t/explain_shard_index.test b/cmd/explaintest/t/explain_shard_index.test new file mode 100644 index 0000000000000..4264ecfa47796 --- /dev/null +++ b/cmd/explaintest/t/explain_shard_index.test @@ -0,0 +1,22 @@ +use test; +drop table if exists test3, test5; +create table test3(id int primary key clustered, a int, b int, unique key uk_expr((tidb_shard(a)),a)); +create table test5(id int primary key clustered, a int, b int, unique key uk_expr((tidb_shard(a)),a,b)); + +explain format=brief select * from test3 where a=100; +explain format=brief select * from test3 where a=100 and (b = 100 or b = 200); +explain format=brief select * from test3 where tidb_shard(a) = 8; +explain format=brief select * from test3 where a=100 or b = 200; +explain format=brief select * from test3 where a=100 or a = 300; +explain format=brief select * from test3 where a=100 or a = 300 or a > 997; +explain format=brief select * from test3 where ((a=100 and b = 100) or a = 200) and b = 300; +explain format=brief select * from test3 where a = b; +explain format=brief select * from test3 where a = b and b = 100; +explain format=brief select * from test5 where a=100 and b = 100; +explain format=brief select * from test5 where (a=100 and b = 100) or (a=200 and b = 200); +explain format=brief select a+b from test5 where (a, b) in ((100, 100), (200, 200)); +explain format=brief SELECT * FROM test3 WHERE a IN (100); +explain format=brief SELECT * FROM test3 WHERE a IN (100, 200, 300); + +drop table if exists test3, test5; + diff --git a/cmd/explaintest/t/generated_columns.test b/cmd/explaintest/t/generated_columns.test index 82dfcf4d1d8c8..c007f8ff42e66 100644 --- a/cmd/explaintest/t/generated_columns.test +++ b/cmd/explaintest/t/generated_columns.test @@ -2,7 +2,6 @@ -- Most of the cases are ported from other tests to make sure generated columns behaves the same. -- Stored generated columns as indices -set @@tidb_partition_prune_mode='dynamic'; DROP TABLE IF EXISTS person; CREATE TABLE person ( @@ -74,6 +73,8 @@ EXPLAIN format = 'brief' SELECT * from sgc1 join sgc2 on sgc1.a=sgc2.a; -- Stored generated columns as partition columns +set @old_prune_mode = @@tidb_partition_prune_mode; +set @@tidb_partition_prune_mode='static'; DROP TABLE IF EXISTS sgc3; CREATE TABLE sgc3 ( j JSON, @@ -91,6 +92,26 @@ PARTITION max VALUES LESS THAN MAXVALUE); EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a <= 1; EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a < 7; +set @@tidb_partition_prune_mode='dynamic'; +DROP TABLE sgc3; +CREATE TABLE sgc3 ( +j JSON, +a INT AS (JSON_EXTRACT(j, "$.a")) STORED +) +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALUES LESS THAN (2), +PARTITION p2 VALUES LESS THAN (3), +PARTITION p3 VALUES LESS THAN (4), +PARTITION p4 VALUES LESS THAN (5), +PARTITION p5 VALUES LESS THAN (6), +PARTITION max VALUES LESS THAN MAXVALUE); + +EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a <= 1; +EXPLAIN format = 'brief' SELECT * FROM sgc3 WHERE a < 7; + +set @@tidb_partition_prune_mode = @old_prune_mode; + -- Virtual generated columns as indices DROP TABLE IF EXISTS t1; diff --git a/cmd/explaintest/t/imdbload.test b/cmd/explaintest/t/imdbload.test new file mode 100644 index 0000000000000..df73903e0bb93 --- /dev/null +++ b/cmd/explaintest/t/imdbload.test @@ -0,0 +1,323 @@ +CREATE DATABASE IF NOT EXISTS `imdbload`; +USE `imdbload`; +-- The table schema is converted from imdb dataset using IMDbPY +CREATE TABLE `kind_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `kind` varchar(15) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `kind_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=11; +CREATE TABLE `keyword` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `keyword` text NOT NULL, + `phonetic_code` varchar(5) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `keyword_idx_keyword` (`keyword`(5)), + KEY `keyword_idx_pcode` (`phonetic_code`), + KEY `itest` (`phonetic_code`,`keyword`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=236629; +CREATE TABLE `company_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `kind` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `company_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6; +CREATE TABLE `comp_cast_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `kind` varchar(32) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `comp_cast_type_kind` (`kind`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6; +CREATE TABLE `complete_cast` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) DEFAULT NULL, + `subject_id` int(11) NOT NULL, + `status_id` int(11) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `complete_cast_idx_mid` (`movie_id`), + KEY `complete_cast_idx_sid` (`subject_id`), + KEY `itest` (`movie_id`,`subject_id`,`status_id`), + KEY `itest2` (`subject_id`,`status_id`,`movie_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=135088; +CREATE TABLE `info_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `info` varchar(32) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `info_type_info` (`info`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=115; +CREATE TABLE `link_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `link` varchar(32) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `link_type_link` (`link`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=20; +CREATE TABLE `company_name` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` text NOT NULL, + `country_code` varchar(255) DEFAULT NULL, + `imdb_id` int(11) DEFAULT NULL, + `name_pcode_nf` varchar(5) DEFAULT NULL, + `name_pcode_sf` varchar(5) DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `company_name_idx_name` (`name`(6)), + KEY `company_name_idx_ccode` (`country_code`(5)), + KEY `company_name_idx_imdb_id` (`imdb_id`), + KEY `company_name_idx_pcodenf` (`name_pcode_nf`), + KEY `company_name_idx_pcodesf` (`name_pcode_sf`), + KEY `company_name_idx_md5` (`md5sum`(5)), + KEY `itest` (`country_code`,`name_pcode_nf`,`name_pcode_sf`), + KEY `itest2` (`name_pcode_sf`,`country_code`,`name`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=362133; +CREATE TABLE `role_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `role` varchar(32) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `role_type_role` (`role`(5)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=14; +CREATE TABLE `movie_link` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) NOT NULL, + `linked_movie_id` int(11) NOT NULL, + `link_type_id` int(11) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `movie_link_idx_mid` (`movie_id`), + KEY `movie_link_idx_lmid` (`linked_movie_id`), + KEY `movie_link_idx_ltypeid` (`link_type_id`), + KEY `itest` (`link_type_id`,`linked_movie_id`,`movie_id`), + KEY `itest2` (`movie_id`,`link_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=2585152; +CREATE TABLE `aka_title` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) NOT NULL, + `title` text NOT NULL, + `imdb_index` varchar(12) DEFAULT NULL, + `kind_id` int(11) NOT NULL, + `production_year` int(11) DEFAULT NULL, + `phonetic_code` varchar(5) DEFAULT NULL, + `episode_of_id` int(11) DEFAULT NULL, + `season_nr` int(11) DEFAULT NULL, + `episode_nr` int(11) DEFAULT NULL, + `note` text DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `aka_title_idx_movieid` (`movie_id`), + KEY `aka_title_idx_title` (`title`(10)), + KEY `aka_title_idx_kindid` (`kind_id`), + KEY `aka_title_idx_year` (`production_year`), + KEY `aka_title_idx_pcode` (`phonetic_code`), + KEY `aka_title_idx_epof` (`episode_of_id`), + KEY `aka_title_idx_md5` (`md5sum`(5)), + KEY `itest` (`phonetic_code`,`production_year`,`kind_id`,`note`(20)), + KEY `itest2` (`episode_of_id`,`season_nr`,`episode_nr`,`production_year`), + KEY `itest3` (`episode_of_id`,`note`(20),`production_year`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=562493; +CREATE TABLE `aka_name` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `person_id` int(11) NOT NULL, + `name` text NOT NULL, + `imdb_index` varchar(12) DEFAULT NULL, + `name_pcode_cf` varchar(5) DEFAULT NULL, + `name_pcode_nf` varchar(5) DEFAULT NULL, + `surname_pcode` varchar(5) DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `aka_name_idx_person` (`person_id`), + KEY `aka_name_idx_name` (`name`(6)), + KEY `aka_name_idx_pcodecf` (`name_pcode_cf`), + KEY `aka_name_idx_pcodenf` (`name_pcode_nf`), + KEY `aka_name_idx_pcode` (`surname_pcode`), + KEY `aka_name_idx_md5` (`md5sum`(5)), + KEY `itest` (`name_pcode_cf`,`name_pcode_nf`,`surname_pcode`), + KEY `itest2` (`surname_pcode`,`name_pcode_cf`,`name_pcode_nf`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1312275; +CREATE TABLE `movie_keyword` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) NOT NULL, + `keyword_id` int(11) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `movie_keyword_idx_mid` (`movie_id`), + KEY `movie_keyword_idx_keywordid` (`keyword_id`), + KEY `itest` (`movie_id`,`keyword_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=7480089; +CREATE TABLE `movie_companies` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) NOT NULL, + `company_id` int(11) NOT NULL, + `company_type_id` int(11) NOT NULL, + `note` text DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `movie_companies_idx_mid` (`movie_id`), + KEY `movie_companies_idx_cid` (`company_id`), + KEY `movie_companies_idx_ctypeid` (`company_type_id`), + KEY `itest` (`movie_id`,`company_type_id`,`company_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4958298; +CREATE TABLE `char_name` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` text NOT NULL, + `imdb_index` varchar(12) DEFAULT NULL, + `imdb_id` int(11) DEFAULT NULL, + `name_pcode_nf` varchar(5) DEFAULT NULL, + `surname_pcode` varchar(5) DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `char_name_idx_name` (`name`(6)), + KEY `char_name_idx_imdb_id` (`imdb_id`), + KEY `char_name_idx_pcodenf` (`name_pcode_nf`), + KEY `char_name_idx_pcode` (`surname_pcode`), + KEY `char_name_idx_md5` (`md5sum`(5)), + KEY `itest` (`name_pcode_nf`,`surname_pcode`,`imdb_id`), + KEY `itest2` (`imdb_index`,`surname_pcode`,`name_pcode_nf`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4314866; +CREATE TABLE `title` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` text NOT NULL, + `imdb_index` varchar(12) DEFAULT NULL, + `kind_id` int(11) NOT NULL, + `production_year` int(11) DEFAULT NULL, + `imdb_id` int(11) DEFAULT NULL, + `phonetic_code` varchar(5) DEFAULT NULL, + `episode_of_id` int(11) DEFAULT NULL, + `season_nr` int(11) DEFAULT NULL, + `episode_nr` int(11) DEFAULT NULL, + `series_years` varchar(49) DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `title_idx_title` (`title`(10)), + KEY `title_idx_kindid` (`kind_id`), + KEY `title_idx_year` (`production_year`), + KEY `title_idx_imdb_id` (`imdb_id`), + KEY `title_idx_pcode` (`phonetic_code`), + KEY `title_idx_epof` (`episode_of_id`), + KEY `title_idx_season_nr` (`season_nr`), + KEY `title_idx_episode_nr` (`episode_nr`), + KEY `title_idx_md5` (`md5sum`(5)), + KEY `itest` (`episode_of_id`,`season_nr`,`episode_nr`,`imdb_index`,`phonetic_code`), + KEY `itest2` (`kind_id`,`production_year`,`imdb_id`,`title`(20)), + KEY `itest3` (`phonetic_code`,`production_year`,`kind_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4736511; +CREATE TABLE `name` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` text NOT NULL, + `imdb_index` varchar(12) DEFAULT NULL, + `imdb_id` int(11) DEFAULT NULL, + `gender` varchar(1) DEFAULT NULL, + `name_pcode_cf` varchar(5) DEFAULT NULL, + `name_pcode_nf` varchar(5) DEFAULT NULL, + `surname_pcode` varchar(5) DEFAULT NULL, + `md5sum` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `name_idx_name` (`name`(6)), + KEY `name_idx_imdb_id` (`imdb_id`), + KEY `name_idx_gender` (`gender`), + KEY `name_idx_pcodecf` (`name_pcode_cf`), + KEY `name_idx_pcodenf` (`name_pcode_nf`), + KEY `name_idx_pcode` (`surname_pcode`), + KEY `name_idx_md5` (`md5sum`(5)), + KEY `itest` (`name_pcode_cf`,`name_pcode_nf`,`surname_pcode`,`imdb_index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6379742; +CREATE TABLE `person_info` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `person_id` int(11) NOT NULL, + `info_type_id` int(11) NOT NULL, + `info` text NOT NULL, + `note` text DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `person_info_idx_pid` (`person_id`), + KEY `person_info_idx_itypeid` (`info_type_id`), + KEY `itest` (`person_id`,`info_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4130209; +CREATE TABLE `movie_info` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `movie_id` int(11) NOT NULL, + `info_type_id` int(11) NOT NULL, + `info` text NOT NULL, + `note` text DEFAULT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `movie_info_idx_mid` (`movie_id`), + KEY `movie_info_idx_infotypeid` (`info_type_id`), + KEY `movie_info_idx_info` (`info`(10)), + KEY `itest` (`movie_id`,`info_type_id`,`info`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=29774986; +CREATE TABLE `cast_info` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `person_id` int(11) NOT NULL, + `movie_id` int(11) NOT NULL, + `person_role_id` int(11) DEFAULT NULL, + `note` text DEFAULT NULL, + `nr_order` int(11) DEFAULT NULL, + `role_id` int(11) NOT NULL, + PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, + KEY `cast_info_idx_pid` (`person_id`), + KEY `cast_info_idx_mid` (`movie_id`), + KEY `cast_info_idx_cid` (`person_role_id`), + KEY `cast_info_idx_rid` (`role_id`), + KEY `itest` (`person_id`,`movie_id`,`person_role_id`), + KEY `itest2` (`nr_order`,`person_role_id`,`note`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=63475837; + +load stats 's/imdbload_stats/kind_type.json'; +load stats 's/imdbload_stats/keyword.json'; +load stats 's/imdbload_stats/company_type.json'; +load stats 's/imdbload_stats/comp_cast_type.json'; +load stats 's/imdbload_stats/complete_cast.json'; +load stats 's/imdbload_stats/info_type.json'; +load stats 's/imdbload_stats/link_type.json'; +load stats 's/imdbload_stats/company_name.json'; +load stats 's/imdbload_stats/role_type.json'; +load stats 's/imdbload_stats/movie_link.json'; +load stats 's/imdbload_stats/aka_title.json'; +load stats 's/imdbload_stats/aka_name.json'; +load stats 's/imdbload_stats/movie_keyword.json'; +load stats 's/imdbload_stats/movie_companies.json'; +load stats 's/imdbload_stats/char_name.json'; +load stats 's/imdbload_stats/title.json'; +load stats 's/imdbload_stats/name.json'; +load stats 's/imdbload_stats/person_info.json'; +load stats 's/imdbload_stats/movie_info.json'; +load stats 's/imdbload_stats/cast_info.json'; + +-- The statistics and actual row count are from the latest imdb dataset that is distributed as old text files. + +-- Actual row count: 1 +-- Index lookup on itest2 index is the best plan, runs <50ms for the first time. Table scan + Selection runs >800ms. (using 8 core tikv * 5, copr cache disabled) +explain select * from char_name where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); +explain select * from char_name use index (itest2) where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); +trace plan target = 'estimation' select * from char_name where ((imdb_index = 'I') and (surname_pcode < 'E436')) or ((imdb_index = 'L') and (surname_pcode < 'E436')); + +-- Actual row count: 0 +explain select * from char_name where ((imdb_index = 'V') and (surname_pcode < 'L3416')); + +-- Actual row count: 0 +explain select * from char_name where imdb_index > 'V'; +trace plan target = 'estimation' select * from char_name where imdb_index > 'V'; + +-- Actual row count: 0 +explain select * from movie_companies where company_type_id > 2; +trace plan target = 'estimation' select * from movie_companies where company_type_id > 2; + +-- Actual row count: 0 +explain select * from char_name where imdb_index > 'I' and imdb_index < 'II'; +trace plan target = 'estimation' select * from char_name where imdb_index > 'I' and imdb_index < 'II'; + +-- Actual row count: 13 +explain select * from char_name where imdb_index > 'I'; +trace plan target = 'estimation' select * from char_name where imdb_index > 'I'; + +-- Actual row count: 0 +explain select * from cast_info where nr_order < -2068070866; + +-- Actual row count: 0 +explain select * from aka_title where kind_id = 5; + +-- Actual row count: 2 +explain select * from aka_title where kind_id > 7; +trace plan target = 'estimation' select * from aka_title where kind_id > 7; + +-- Actual row count: 0 +explain select * from keyword where ((phonetic_code = 'R1652') and (keyword > 'ecg-monitor' and keyword < 'killers')); +trace plan target = 'estimation' select * from keyword where ((phonetic_code = 'R1652') and (keyword > 'ecg-monitor' and keyword < 'killers')); + +-- Actual row count: 37928 +explain select * from cast_info where (nr_order is null) and (person_role_id = 2) and (note >= '(key set pa: Florida'); +trace plan target = 'estimation' select * from cast_info where (nr_order is null) and (person_role_id = 2) and (note >= '(key set pa: Florida'); diff --git a/cmd/explaintest/t/index_join.test b/cmd/explaintest/t/index_join.test index c0636a876dc4e..f766b1e899e29 100644 --- a/cmd/explaintest/t/index_join.test +++ b/cmd/explaintest/t/index_join.test @@ -1,3 +1,4 @@ +use test; drop table if exists t1, t2; create table t1(a bigint, b bigint, index idx(a)); create table t2(a bigint, b bigint, index idx(a)); diff --git a/cmd/explaintest/t/new_character_set.test b/cmd/explaintest/t/new_character_set.test index 8009ba73dae4b..7de21592b89de 100644 --- a/cmd/explaintest/t/new_character_set.test +++ b/cmd/explaintest/t/new_character_set.test @@ -39,3 +39,30 @@ prepare p1 from "insert into t values ('中文');"; execute p1; select a, hex(a) from t; set @@character_set_client = 'utf8mb4'; + +set names gbk; +drop table if exists t; +create table t (b blob, d json); +insert into t values ('你好', '{"测试": "你好"}'); +select b, d from t; +select hex(b), hex(d) from t; + +set names utf8mb4; +drop table if exists t; +create table t(a blob, b char(10)); +insert into t values (0x61, 'å•Š'); +insert into t values (0x61, '一'); +set names gbk; +select * from t; + +drop table t; +set names gbk; +set character_set_connection = utf8mb4; +create table t(j json, b blob, s1 varchar(255) collate binary, s2 varchar(255), st set('{"点赞": "你好"}'), en enum('{"点赞": "你好"}')); +insert into t values('{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}', '{"点赞": "你好"}'); +select * from t; + +set names utf8mb4; +set @@character_set_client=gbk; +set @@character_set_connection=gbk; +select hex('一a'), '一a'; diff --git a/cmd/explaintest/t/new_character_set_builtin.test b/cmd/explaintest/t/new_character_set_builtin.test index 09b823cdcfaa9..93f160832ce01 100644 --- a/cmd/explaintest/t/new_character_set_builtin.test +++ b/cmd/explaintest/t/new_character_set_builtin.test @@ -1,3 +1,5 @@ +set names utf8mb4; +set @@sql_mode = ''; -- test for builtin function hex(), length(), ascii(), octet_length() drop table if exists t; create table t (a char(20) charset utf8mb4, b char(20) charset gbk, c binary(20)); @@ -190,14 +192,18 @@ select hex(instr(a, 0xe4b880)), hex(instr(b, 0xd2bb)) from t; select hex(position(a in 0xe4b880)), hex(position(b in 0xd2bb)) from t; select a like 0xe4b880, b like 0xd2bb from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select a = 0xb6fe from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select b = 0xe4ba8c from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select concat(a, 0xb6fe) from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select concat(b, 0xe4ba8c) from t; +--error 3854 +select concat(convert('a' using gbk), 0x3fff) from t; +--error 3854 +select concat(convert('a' using gbk), 0x3fffffffffffffff) from t; set @@tidb_enable_vectorized_expression = false; select hex(concat(a, c)), hex(concat(b, c)) from t; @@ -216,13 +222,13 @@ select hex(instr(a, 0xe4b880)), hex(instr(b, 0xd2bb)) from t; select hex(position(a in 0xe4b880)), hex(position(b in 0xd2bb)) from t; select a like 0xe4b880, b like 0xd2bb from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select a = 0xb6fe from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select b = 0xe4ba8c from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select concat(a, 0xb6fe) from t; ---error ER_CANNOT_CONVERT_STRING +--error 3854 select concat(b, 0xe4ba8c) from t; -- test for builtin function aes_encrypt() @@ -238,3 +244,22 @@ select hex(aes_encrypt(a, '123', '1234567890123456')), hex(aes_encrypt(b, '123', set @@block_encryption_mode='aes-128-ecb'; select hex(aes_encrypt(a, '123')), hex(aes_encrypt(b, '123')), hex(aes_encrypt(c, '123')) from t; set @@tidb_enable_vectorized_expression = false; + +-- test for builtin crc32() +drop table if exists t; +create table t (a char(20) charset utf8mb4, b char(20) charset gbk, c binary(20)); +insert into t values ('一二三', '一二三', '一二三'); +select crc32(a), crc32(b), crc32(c) from t; +set @@tidb_enable_vectorized_expression = true; +select crc32(a), crc32(b), crc32(c) from t; +set @@tidb_enable_vectorized_expression = false; + +-- test for elt +drop table if exists t; +create table t (a enum('a一','b二','c三','då››') default 'c三', b binary(10)) charset=gbk; +insert into t values (1, 0x1234); +set @@tidb_enable_vectorized_expression = true; +select hex(elt(1, a, b)), hex(elt(1, a, 0x12)) from t; +set @@tidb_enable_vectorized_expression = false; +select hex(elt(1, a, b)), hex(elt(1, a, 0x12)) from t; + diff --git a/cmd/explaintest/t/new_character_set_invalid.test b/cmd/explaintest/t/new_character_set_invalid.test index 34031d0b83ef8..eaed9ba78c518 100644 --- a/cmd/explaintest/t/new_character_set_invalid.test +++ b/cmd/explaintest/t/new_character_set_invalid.test @@ -2,11 +2,11 @@ set @@sql_mode = 'strict_trans_tables'; drop table if exists t; create table t (a varchar(255) charset gbk, b varchar(255) charset ascii, c varchar(255) charset utf8); insert into t values ('中文', 'asdf', '字符集'); --- error 1366: Incorrect string value '\xC3\x80' for column 'a' +-- error 1366 insert into t values ('À', 'ø', '😂'); --- error 1366: Incorrect string value '\xC3\x80\xE4\xB8\xAD\xE6...' for column 'a' +-- error 1366 insert into t values ('中文À中文', 'asdføfdsa', '字符集😂字符集'); --- error 1366: Incorrect string value '\xFF\xFF' for column 'a' +-- error 1366 insert into t values (0x4040ffff, 0x4040ffff, 0x4040ffff); select * from t; diff --git a/cmd/explaintest/t/select.test b/cmd/explaintest/t/select.test index c53aca600e2b9..5efbbd77a0364 100644 --- a/cmd/explaintest/t/select.test +++ b/cmd/explaintest/t/select.test @@ -56,10 +56,10 @@ SELECT * from t a, t2 b; SELECT * from t as a, t2 as b; SELECT * from t a left join t2 b on a.c1 = b.c1; ---error ER_DUP_FIELDNAME +--error 1060 SELECT * from (SELECT 1, 1) as a; ---error ER_DUP_FIELDNAME +--error 1060 SELECT * from (SELECT * FROM t, t2) as a; # Select bool field @@ -181,12 +181,18 @@ desc select sysdate(), sleep(1), sysdate(); # test select partition table drop table if exists th; set @@session.tidb_enable_table_partition = '1'; +set @@session.tidb_partition_prune_mode = 'static'; create table th (a int, b int) partition by hash(a) partitions 3; insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8); insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8); desc select * from th where a=-2; desc select * from th; desc select * from th partition (p2,p1); +set @@session.tidb_partition_prune_mode = 'dynamic'; +desc select * from th where a=-2; +desc select * from th; +desc select * from th partition (p2,p1); +set @@session.tidb_partition_prune_mode = DEFAULT; # test != any(subq) and = all(subq) drop table if exists t; @@ -247,5 +253,5 @@ SELECT a, b, c, d FROM precise_types; create table t3(a char(10), primary key (a)); insert into t3 values ('a'); ---error ER_CANNOT_CONVERT_STRING +--error 1105 select * from t3 where a > 0x80; diff --git a/cmd/importer/db.go b/cmd/importer/db.go index 2379fd3a08943..235bd0b6ed74f 100644 --- a/cmd/importer/db.go +++ b/cmd/importer/db.go @@ -86,7 +86,7 @@ func nextInt64Value(column *column, min int64, max int64) int64 { } func intToDecimalString(intValue int64, decimal int) string { - data := fmt.Sprintf("%d", intValue) + data := strconv.FormatInt(intValue, 10) // add leading zero if len(data) < decimal { @@ -117,7 +117,7 @@ func genRowDatas(table *table, count int) ([]string, error) { } func genRowData(table *table) (string, error) { - var values []byte + var values []byte // nolint: prealloc for _, column := range table.columns { data, err := genColumnData(table, column) if err != nil { diff --git a/cmd/importer/rand.go b/cmd/importer/rand.go index 8de570e68f429..7ebfd7b291f92 100644 --- a/cmd/importer/rand.go +++ b/cmd/importer/rand.go @@ -87,7 +87,7 @@ func randDate(col *column) string { log.Warn("parse min date failed", zap.Error(err)) } if max == "" { - t := minTime.Add(time.Duration(randInt(0, 365)) * 24 * time.Hour) + t := minTime.Add(time.Duration(randInt(0, 365)) * 24 * time.Hour) // nolint: durationcheck return fmt.Sprintf("%04d-%02d-%02d", t.Year(), t.Month(), t.Day()) } @@ -96,7 +96,7 @@ func randDate(col *column) string { log.Warn("parse max date failed", zap.Error(err)) } days := int(maxTime.Sub(minTime).Hours() / 24) - t := minTime.Add(time.Duration(randInt(0, days)) * 24 * time.Hour) + t := minTime.Add(time.Duration(randInt(0, days)) * 24 * time.Hour) // nolint: durationcheck return fmt.Sprintf("%04d-%02d-%02d", t.Year(), t.Month(), t.Day()) } @@ -145,7 +145,7 @@ func randTimestamp(col *column) string { log.Warn("parse min timestamp failed", zap.Error(err)) } if max == "" { - t := minTime.Add(time.Duration(randInt(0, 365)) * 24 * time.Hour) + t := minTime.Add(time.Duration(randInt(0, 365)) * 24 * time.Hour) // nolint: durationcheck return fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) } diff --git a/cmd/pluginpkg/pluginpkg.go b/cmd/pluginpkg/pluginpkg.go index 8390b10adbb10..24a7c6a0a5dd6 100644 --- a/cmd/pluginpkg/pluginpkg.go +++ b/cmd/pluginpkg/pluginpkg.go @@ -126,7 +126,7 @@ func main() { } genFileName := filepath.Join(pkgDir, filepath.Base(pkgDir)+".gen.go") - genFile, err := os.OpenFile(genFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) + genFile, err := os.OpenFile(genFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0700) // # nosec G302 if err != nil { log.Printf("generate code failure during prepare output file, %+v\n", err) os.Exit(1) diff --git a/config/config.go b/config/config.go index 2319d953286c7..4ffd599416aa7 100644 --- a/config/config.go +++ b/config/config.go @@ -65,6 +65,14 @@ const ( DefTableColumnCountLimit = 1017 // DefMaxOfTableColumnCountLimit is maximum limitation of the number of columns in a table DefMaxOfTableColumnCountLimit = 4096 + // DefStatsLoadConcurrencyLimit is limit of the concurrency of stats-load + DefStatsLoadConcurrencyLimit = 1 + // DefMaxOfStatsLoadConcurrencyLimit is maximum limitation of the concurrency of stats-load + DefMaxOfStatsLoadConcurrencyLimit = 128 + // DefStatsLoadQueueSizeLimit is limit of the size of stats-load request queue + DefStatsLoadQueueSizeLimit = 1 + // DefMaxOfStatsLoadQueueSizeLimit is maximum limitation of the size of stats-load request queue + DefMaxOfStatsLoadQueueSizeLimit = 100000 ) // Valid config maps @@ -101,33 +109,31 @@ type Config struct { MemQuotaQuery int64 `toml:"mem-quota-query" json:"mem-quota-query"` // TempStorageQuota describe the temporary storage Quota during query exector when OOMUseTmpStorage is enabled // If the quota exceed the capacity of the TempStoragePath, the tidb-server would exit with fatal error - TempStorageQuota int64 `toml:"tmp-storage-quota" json:"tmp-storage-quota"` // Bytes - // Deprecated - EnableStreaming bool `toml:"-" json:"-"` - EnableBatchDML bool `toml:"enable-batch-dml" json:"enable-batch-dml"` - TxnLocalLatches tikvcfg.TxnLocalLatches `toml:"-" json:"-"` - // Set sys variable lower-case-table-names, ref: https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html. - // TODO: We actually only support mode 2, which keeps the original case, but the comparison is case-insensitive. - LowerCaseTableNames int `toml:"lower-case-table-names" json:"lower-case-table-names"` - ServerVersion string `toml:"server-version" json:"server-version"` - Log Log `toml:"log" json:"log"` - Security Security `toml:"security" json:"security"` - Status Status `toml:"status" json:"status"` - Performance Performance `toml:"performance" json:"performance"` - PreparedPlanCache PreparedPlanCache `toml:"prepared-plan-cache" json:"prepared-plan-cache"` - OpenTracing OpenTracing `toml:"opentracing" json:"opentracing"` - ProxyProtocol ProxyProtocol `toml:"proxy-protocol" json:"proxy-protocol"` - PDClient tikvcfg.PDClient `toml:"pd-client" json:"pd-client"` - TiKVClient tikvcfg.TiKVClient `toml:"tikv-client" json:"tikv-client"` - Binlog Binlog `toml:"binlog" json:"binlog"` - CompatibleKillQuery bool `toml:"compatible-kill-query" json:"compatible-kill-query"` - Plugin Plugin `toml:"plugin" json:"plugin"` - PessimisticTxn PessimisticTxn `toml:"pessimistic-txn" json:"pessimistic-txn"` - CheckMb4ValueInUTF8 bool `toml:"check-mb4-value-in-utf8" json:"check-mb4-value-in-utf8"` - MaxIndexLength int `toml:"max-index-length" json:"max-index-length"` - IndexLimit int `toml:"index-limit" json:"index-limit"` - TableColumnCountLimit uint32 `toml:"table-column-count-limit" json:"table-column-count-limit"` - GracefulWaitBeforeShutdown int `toml:"graceful-wait-before-shutdown" json:"graceful-wait-before-shutdown"` + TempStorageQuota int64 `toml:"tmp-storage-quota" json:"tmp-storage-quota"` // Bytes + EnableBatchDML bool `toml:"enable-batch-dml" json:"enable-batch-dml"` + TxnLocalLatches tikvcfg.TxnLocalLatches `toml:"-" json:"-"` + ServerVersion string `toml:"server-version" json:"server-version"` + VersionComment string `toml:"version-comment" json:"version-comment"` + TiDBEdition string `toml:"tidb-edition" json:"tidb-edition"` + TiDBReleaseVersion string `toml:"tidb-release-version" json:"tidb-release-version"` + Log Log `toml:"log" json:"log"` + Security Security `toml:"security" json:"security"` + Status Status `toml:"status" json:"status"` + Performance Performance `toml:"performance" json:"performance"` + PreparedPlanCache PreparedPlanCache `toml:"prepared-plan-cache" json:"prepared-plan-cache"` + OpenTracing OpenTracing `toml:"opentracing" json:"opentracing"` + ProxyProtocol ProxyProtocol `toml:"proxy-protocol" json:"proxy-protocol"` + PDClient tikvcfg.PDClient `toml:"pd-client" json:"pd-client"` + TiKVClient tikvcfg.TiKVClient `toml:"tikv-client" json:"tikv-client"` + Binlog Binlog `toml:"binlog" json:"binlog"` + CompatibleKillQuery bool `toml:"compatible-kill-query" json:"compatible-kill-query"` + Plugin Plugin `toml:"plugin" json:"plugin"` + PessimisticTxn PessimisticTxn `toml:"pessimistic-txn" json:"pessimistic-txn"` + CheckMb4ValueInUTF8 AtomicBool `toml:"check-mb4-value-in-utf8" json:"check-mb4-value-in-utf8"` + MaxIndexLength int `toml:"max-index-length" json:"max-index-length"` + IndexLimit int `toml:"index-limit" json:"index-limit"` + TableColumnCountLimit uint32 `toml:"table-column-count-limit" json:"table-column-count-limit"` + GracefulWaitBeforeShutdown int `toml:"graceful-wait-before-shutdown" json:"graceful-wait-before-shutdown"` // AlterPrimaryKey is used to control alter primary key feature. AlterPrimaryKey bool `toml:"alter-primary-key" json:"alter-primary-key"` // TreatOldVersionUTF8AsUTF8MB4 is use to treat old version table/column UTF8 charset as UTF8MB4. This is for compatibility. @@ -135,11 +141,10 @@ type Config struct { TreatOldVersionUTF8AsUTF8MB4 bool `toml:"treat-old-version-utf8-as-utf8mb4" json:"treat-old-version-utf8-as-utf8mb4"` // EnableTableLock indicate whether enable table lock. // TODO: remove this after table lock features stable. - EnableTableLock bool `toml:"enable-table-lock" json:"enable-table-lock"` - DelayCleanTableLock uint64 `toml:"delay-clean-table-lock" json:"delay-clean-table-lock"` - SplitRegionMaxNum uint64 `toml:"split-region-max-num" json:"split-region-max-num"` - StmtSummary StmtSummary `toml:"stmt-summary" json:"stmt-summary"` - TopSQL TopSQL `toml:"top-sql" json:"top-sql"` + EnableTableLock bool `toml:"enable-table-lock" json:"enable-table-lock"` + DelayCleanTableLock uint64 `toml:"delay-clean-table-lock" json:"delay-clean-table-lock"` + SplitRegionMaxNum uint64 `toml:"split-region-max-num" json:"split-region-max-num"` + TopSQL TopSQL `toml:"top-sql" json:"top-sql"` // RepairMode indicates that the TiDB is in the repair mode for table meta. RepairMode bool `toml:"repair-mode" json:"repair-mode"` RepairTableList []string `toml:"repair-table-list" json:"repair-table-list"` @@ -222,11 +227,9 @@ func (c *Config) getTiKVConfig() *tikvcfg.Config { func encodeDefTempStorageDir(tempDir string, host, statusHost string, port, statusPort uint) string { dirName := base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v/%v:%v", host, port, statusHost, statusPort))) - var osUID string + osUID := "" currentUser, err := user.Current() - if err != nil { - osUID = "" - } else { + if err == nil { osUID = currentUser.Uid } return filepath.Join(tempDir, osUID+"_tidb", dirName, "tmp-storage") @@ -483,11 +486,13 @@ type Performance struct { CommitterConcurrency int `toml:"committer-concurrency" json:"committer-concurrency"` MaxTxnTTL uint64 `toml:"max-txn-ttl" json:"max-txn-ttl"` // Deprecated - MemProfileInterval string `toml:"-" json:"-"` - IndexUsageSyncLease string `toml:"index-usage-sync-lease" json:"index-usage-sync-lease"` - PlanReplayerGCLease string `toml:"plan-replayer-gc-lease" json:"plan-replayer-gc-lease"` - GOGC int `toml:"gogc" json:"gogc"` - EnforceMPP bool `toml:"enforce-mpp" json:"enforce-mpp"` + MemProfileInterval string `toml:"-" json:"-"` + IndexUsageSyncLease string `toml:"index-usage-sync-lease" json:"index-usage-sync-lease"` + PlanReplayerGCLease string `toml:"plan-replayer-gc-lease" json:"plan-replayer-gc-lease"` + GOGC int `toml:"gogc" json:"gogc"` + EnforceMPP bool `toml:"enforce-mpp" json:"enforce-mpp"` + StatsLoadConcurrency uint `toml:"stats-load-concurrency" json:"stats-load-concurrency"` + StatsLoadQueueSize uint `toml:"stats-load-queue-size" json:"stats-load-queue-size"` } // PlanCache is the PlanCache section of the config. @@ -562,6 +567,8 @@ type PessimisticTxn struct { DeadlockHistoryCapacity uint `toml:"deadlock-history-capacity" json:"deadlock-history-capacity"` // Whether retryable deadlocks (in-statement deadlocks) are collected to the information_schema.deadlocks table. DeadlockHistoryCollectRetryable bool `toml:"deadlock-history-collect-retryable" json:"deadlock-history-collect-retryable"` + // PessimisticAutoCommit represents if true it means the auto-commit transactions will be in pessimistic mode. + PessimisticAutoCommit AtomicBool `toml:"pessimistic-auto-commit" json:"pessimistic-auto-commit"` } // DefaultPessimisticTxn returns the default configuration for PessimisticTxn @@ -570,6 +577,7 @@ func DefaultPessimisticTxn() PessimisticTxn { MaxRetryCount: 256, DeadlockHistoryCapacity: 10, DeadlockHistoryCollectRetryable: false, + PessimisticAutoCommit: *NewAtomicBool(false), } } @@ -579,22 +587,6 @@ type Plugin struct { Load string `toml:"load" json:"load"` } -// StmtSummary is the config for statement summary. -type StmtSummary struct { - // Enable statement summary or not. - Enable bool `toml:"enable" json:"enable"` - // Enable summary internal query. - EnableInternalQuery bool `toml:"enable-internal-query" json:"enable-internal-query"` - // The maximum number of statements kept in memory. - MaxStmtCount uint `toml:"max-stmt-count" json:"max-stmt-count"` - // The maximum length of displayed normalized SQL and sample SQL. - MaxSQLLength uint `toml:"max-sql-length" json:"max-sql-length"` - // The refresh interval of statement summary. - RefreshInterval int `toml:"refresh-interval" json:"refresh-interval"` - // The maximum history size of statement summary. - HistorySize int `toml:"history-size" json:"history-size"` -} - // TopSQL is the config for TopSQL. type TopSQL struct { // The TopSQL's data receiver address. @@ -636,9 +628,8 @@ var defaultConf = Config{ TempStoragePath: tempStorageDirName, OOMAction: OOMActionCancel, MemQuotaQuery: 1 << 30, - EnableStreaming: false, EnableBatchDML: false, - CheckMb4ValueInUTF8: true, + CheckMb4ValueInUTF8: *NewAtomicBool(true), MaxIndexLength: 3072, IndexLimit: 64, TableColumnCountLimit: 1017, @@ -651,9 +642,11 @@ var defaultConf = Config{ RepairTableList: []string{}, MaxServerConnections: 0, TxnLocalLatches: defTiKVCfg.TxnLocalLatches, - LowerCaseTableNames: 2, GracefulWaitBeforeShutdown: 0, ServerVersion: "", + TiDBEdition: "", + VersionComment: "", + TiDBReleaseVersion: "", Log: Log{ Level: "info", Format: "text", @@ -702,10 +695,12 @@ var defaultConf = Config{ CommitterConcurrency: defTiKVCfg.CommitterConcurrency, MaxTxnTTL: defTiKVCfg.MaxTxnTTL, // 1hour // TODO: set indexUsageSyncLease to 60s. - IndexUsageSyncLease: "0s", - GOGC: 100, - EnforceMPP: false, - PlanReplayerGCLease: "10m", + IndexUsageSyncLease: "0s", + GOGC: 100, + EnforceMPP: false, + PlanReplayerGCLease: "10m", + StatsLoadConcurrency: 5, + StatsLoadQueueSize: 1000, }, ProxyProtocol: ProxyProtocol{ Networks: "", @@ -735,20 +730,11 @@ var defaultConf = Config{ Load: "", }, PessimisticTxn: DefaultPessimisticTxn(), - StmtSummary: StmtSummary{ - Enable: true, - EnableInternalQuery: false, - MaxStmtCount: 3000, - MaxSQLLength: 4096, - RefreshInterval: 1800, - HistorySize: 24, - }, IsolationRead: IsolationRead{ Engines: []string{"tikv", "tiflash", "tidb"}, }, Experimental: Experimental{ EnableGlobalKill: false, - EnableNewCharset: false, }, EnableCollectExecutionInfo: true, EnableTelemetry: true, @@ -760,10 +746,11 @@ var defaultConf = Config{ AutoTLS: false, RSAKeySize: 4096, }, - DeprecateIntegerDisplayWidth: false, - EnableEnumLengthLimit: true, - StoresRefreshInterval: defTiKVCfg.StoresRefreshInterval, - EnableForwarding: defTiKVCfg.EnableForwarding, + DeprecateIntegerDisplayWidth: false, + EnableEnumLengthLimit: true, + StoresRefreshInterval: defTiKVCfg.StoresRefreshInterval, + EnableForwarding: defTiKVCfg.EnableForwarding, + NewCollationsEnabledOnFirstBootstrap: true, } var ( @@ -791,21 +778,29 @@ func StoreGlobalConfig(config *Config) { } var deprecatedConfig = map[string]struct{}{ - "pessimistic-txn.ttl": {}, - "pessimistic-txn.enable": {}, - "log.file.log-rotate": {}, - "log.log-slow-query": {}, - "txn-local-latches": {}, - "txn-local-latches.enabled": {}, - "txn-local-latches.capacity": {}, - "performance.max-memory": {}, - "max-txn-time-use": {}, - "experimental.allow-auto-random": {}, - "enable-redact-log": {}, // use variable tidb_redact_log instead - "tikv-client.copr-cache.enable": {}, - "alter-primary-key": {}, // use NONCLUSTERED keyword instead - "enable-streaming": {}, - "performance.mem-profile-interval": {}, + "pessimistic-txn.ttl": {}, + "pessimistic-txn.enable": {}, + "log.file.log-rotate": {}, + "log.log-slow-query": {}, + "txn-local-latches": {}, + "txn-local-latches.enabled": {}, + "txn-local-latches.capacity": {}, + "performance.max-memory": {}, + "max-txn-time-use": {}, + "experimental.allow-auto-random": {}, + "enable-redact-log": {}, // use variable tidb_redact_log instead + "tikv-client.copr-cache.enable": {}, + "alter-primary-key": {}, // use NONCLUSTERED keyword instead + "enable-streaming": {}, + "performance.mem-profile-interval": {}, + "lower-case-table-names": {}, + "stmt-summary": {}, + "stmt-summary.enable": {}, + "stmt-summary.enable-internal-query": {}, + "stmt-summary.max-stmt-count": {}, + "stmt-summary.max-sql-length": {}, + "stmt-summary.refresh-interval": {}, + "stmt-summary.history-size": {}, } func isAllDeprecatedConfigItems(items []string) bool { @@ -944,11 +939,6 @@ func (c *Config) Valid() error { return fmt.Errorf("table-column-limit should be [%d, %d]", DefIndexLimit, DefMaxOfTableColumnCountLimit) } - // lower_case_table_names is allowed to be 0, 1, 2 - if c.LowerCaseTableNames < 0 || c.LowerCaseTableNames > 2 { - return fmt.Errorf("lower-case-table-names should be 0 or 1 or 2") - } - // txn-local-latches if err := c.TxnLocalLatches.Valid(); err != nil { return err @@ -967,16 +957,6 @@ func (c *Config) Valid() error { return fmt.Errorf("memory-usage-alarm-ratio in [Performance] must be greater than or equal to 0 and less than or equal to 1") } - if c.StmtSummary.MaxStmtCount <= 0 { - return fmt.Errorf("max-stmt-count in [stmt-summary] should be greater than 0") - } - if c.StmtSummary.HistorySize < 0 { - return fmt.Errorf("history-size in [stmt-summary] should be greater than or equal to 0") - } - if c.StmtSummary.RefreshInterval <= 0 { - return fmt.Errorf("refresh-interval in [stmt-summary] should be greater than 0") - } - if c.PreparedPlanCache.Capacity < 1 { return fmt.Errorf("capacity in [prepared-plan-cache] should be at least 1") } @@ -1001,6 +981,14 @@ func (c *Config) Valid() error { c.Security.SpilledFileEncryptionMethod, SpilledFileEncryptionMethodPlaintext, SpilledFileEncryptionMethodAES128CTR) } + // check stats load config + if c.Performance.StatsLoadConcurrency < DefStatsLoadConcurrencyLimit || c.Performance.StatsLoadConcurrency > DefMaxOfStatsLoadConcurrencyLimit { + return fmt.Errorf("stats-load-concurrency should be [%d, %d]", DefStatsLoadConcurrencyLimit, DefMaxOfStatsLoadConcurrencyLimit) + } + if c.Performance.StatsLoadQueueSize < DefStatsLoadQueueSizeLimit || c.Performance.StatsLoadQueueSize > DefMaxOfStatsLoadQueueSizeLimit { + return fmt.Errorf("stats-load-queue-size should be [%d, %d]", DefStatsLoadQueueSizeLimit, DefMaxOfStatsLoadQueueSizeLimit) + } + // test log level l := zap.NewAtomicLevel() return l.UnmarshalText([]byte(c.Log.Level)) @@ -1078,7 +1066,7 @@ func initByLDFlags(edition, checkBeforeDropLDFlag string) { } // The following constants represents the valid action configurations for OOMAction. -// NOTE: Although the values is case insensitive, we should use lower-case +// NOTE: Although the values is case-insensitive, we should use lower-case // strings because the configuration value will be transformed to lower-case // string and compared with these constants in the further usage. const ( diff --git a/config/config.toml.example b/config/config.toml.example index 0e91f903748f8..99cefd528b837 100644 --- a/config/config.toml.example +++ b/config/config.toml.example @@ -54,9 +54,6 @@ oom-action = "cancel" # Enable batch commit for the DMLs. enable-batch-dml = false -# Set system variable 'lower_case_table_names' -lower-case-table-names = 2 - # Make "kill query" behavior compatible with MySQL. It's not recommend to # turn on this option when TiDB server is behind a proxy. compatible-kill-query = false @@ -109,7 +106,7 @@ repair-table-list = [] max-server-connections = 0 # Whether new collations are enabled, as indicated by its name, this configuration entry take effect ONLY when a TiDB cluster bootstraps for the first time. -new_collations_enabled_on_first_bootstrap = false +new_collations_enabled_on_first_bootstrap = true # Don't register information of this TiDB to etcd, so this instance of TiDB won't appear in the services like dashboard. # This option is useful when you want to embed TiDB into your service(i.e. use TiDB as a library). @@ -292,7 +289,7 @@ distinct-agg-push-down = false # If using TiKV as the storage, the entry represents a key/value pair. # NOTE: If binlog is enabled with Kafka (e.g. arbiter cluster), # this value should be less than 1073741824(1G) because this is the maximum size that can be handled by Kafka. -# If binlog is disabled or binlog is enabled without Kafka, this value should be less than 10737418240(10G). +# If binlog is disabled or binlog is enabled without Kafka, this value should be less than 1099511627776(1T). txn-total-size-limit = 104857600 # The limitation of the size in byte for each entry in one transaction. @@ -460,24 +457,8 @@ deadlock-history-capacity = 10 # Whether retryable deadlocks (in-statement deadlocks) are collected to the information_schema.deadlocks table. deadlock-history-collect-retryable = false -[stmt-summary] -# enable statement summary. -enable = true - -# enable statement summary for TiDB internal query, default is false. -enable-internal-query = false - -# max number of statements kept in memory. -max-stmt-count = 3000 - -# max length of displayed normalized sql and sample sql. -max-sql-length = 4096 - -# the refresh interval of statement summary, it's counted in seconds. -refresh-interval = 1800 - -# the maximum history size of statement summary. -history-size = 24 +# If true it means the auto-commit transactions will be in pessimistic mode. +pessimistic-auto-commit = false # experimental section controls the features that are still experimental: their semantics, # interfaces are subject to change, using these features in the production environment is not recommended. diff --git a/config/config_test.go b/config/config_test.go index 25c79dc40ebe3..bc90a2763bfad 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -239,13 +239,6 @@ resolve-lock-lite-threshold = 16 [tikv-client.async-commit] keys-limit=123 total-key-size-limit=1024 -[stmt-summary] -enable=false -enable-internal-query=true -max-stmt-count=1000 -max-sql-length=1024 -refresh-interval=100 -history-size=100 [experimental] allow-expression-index = true [isolation-read] @@ -259,6 +252,7 @@ spilled-file-encryption-method = "plaintext" [pessimistic-txn] deadlock-history-capacity = 123 deadlock-history-collect-retryable = true +pessimistic-auto-commit = true [top-sql] receiver-address = "127.0.0.1:10100" [status] @@ -294,12 +288,6 @@ grpc-max-send-msg-size = 40960 require.True(t, conf.EnableTableLock) require.Equal(t, uint64(5), conf.DelayCleanTableLock) require.Equal(t, uint64(10000), conf.SplitRegionMaxNum) - require.False(t, conf.StmtSummary.Enable) - require.True(t, conf.StmtSummary.EnableInternalQuery) - require.Equal(t, uint(1000), conf.StmtSummary.MaxStmtCount) - require.Equal(t, uint(1024), conf.StmtSummary.MaxSQLLength) - require.Equal(t, 100, conf.StmtSummary.RefreshInterval) - require.Equal(t, 100, conf.StmtSummary.HistorySize) require.True(t, conf.EnableBatchDML) require.True(t, conf.RepairMode) require.Equal(t, uint64(16), conf.TiKVClient.ResolveLockLiteThreshold) @@ -321,7 +309,7 @@ grpc-max-send-msg-size = 40960 require.Equal(t, uint64(30), conf.StoresRefreshInterval) require.Equal(t, uint(123), conf.PessimisticTxn.DeadlockHistoryCapacity) require.True(t, conf.PessimisticTxn.DeadlockHistoryCollectRetryable) - require.False(t, conf.Experimental.EnableNewCharset) + require.True(t, conf.PessimisticTxn.PessimisticAutoCommit.Load()) require.Equal(t, "127.0.0.1:10100", conf.TopSQL.ReceiverAddress) require.True(t, conf.Experimental.AllowsExpressionIndex) require.Equal(t, uint(20), conf.Status.GRPCKeepAliveTime) @@ -339,7 +327,14 @@ grpc-max-send-msg-size = 40960 [log.file] log-rotate = true [performance] -mem-profile-interval="1m"`) +mem-profile-interval="1m" +[stmt-summary] +enable=false +enable-internal-query=true +max-stmt-count=1000 +max-sql-length=1024 +refresh-interval=100 +history-size=100`) require.NoError(t, err) err = conf.Load(configFile) tmp := err.(*ErrConfigValidationFailed) @@ -657,7 +652,7 @@ func TestSecurityValid(t *testing.T) { func TestTcpNoDelay(t *testing.T) { c1 := NewConfig() - //check default value + // check default value require.True(t, c1.Performance.TCPNoDelay) } @@ -674,3 +669,24 @@ func TestConfigExample(t *testing.T) { } } } + +func TestStatsLoadLimit(t *testing.T) { + conf := NewConfig() + checkConcurrencyValid := func(concurrency int, shouldBeValid bool) { + conf.Performance.StatsLoadConcurrency = uint(concurrency) + require.Equal(t, shouldBeValid, conf.Valid() == nil) + } + checkConcurrencyValid(DefStatsLoadConcurrencyLimit, true) + checkConcurrencyValid(DefStatsLoadConcurrencyLimit-1, false) + checkConcurrencyValid(DefMaxOfStatsLoadConcurrencyLimit, true) + checkConcurrencyValid(DefMaxOfStatsLoadConcurrencyLimit+1, false) + conf = NewConfig() + checkQueueSizeValid := func(queueSize int, shouldBeValid bool) { + conf.Performance.StatsLoadQueueSize = uint(queueSize) + require.Equal(t, shouldBeValid, conf.Valid() == nil) + } + checkQueueSizeValid(DefStatsLoadQueueSizeLimit, true) + checkQueueSizeValid(DefStatsLoadQueueSizeLimit-1, false) + checkQueueSizeValid(DefMaxOfStatsLoadQueueSizeLimit, true) + checkQueueSizeValid(DefMaxOfStatsLoadQueueSizeLimit+1, false) +} diff --git a/config/config_util.go b/config/config_util.go index f8ae5221c2617..c192a54fd7dbc 100644 --- a/config/config_util.go +++ b/config/config_util.go @@ -53,7 +53,6 @@ var ( "Log.QueryLogMaxLen": {}, "Log.ExpensiveThreshold": {}, "CheckMb4ValueInUTF8": {}, - "EnableStreaming": {}, "TxnLocalLatches.Capacity": {}, "CompatibleKillQuery": {}, "TreatOldVersionUTF8AsUTF8MB4": {}, diff --git a/config/main_test.go b/config/main_test.go index 0ef0a65458301..f057995fb6137 100644 --- a/config/main_test.go +++ b/config/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/ddl/attributes_sql_test.go b/ddl/attributes_sql_test.go index c3295b1d518d0..0241fefe2cbdb 100644 --- a/ddl/attributes_sql_test.go +++ b/ddl/attributes_sql_test.go @@ -18,69 +18,69 @@ import ( "context" "fmt" "math" + "testing" + "time" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain/infosync" - "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/gcworker" - "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/gcutil" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testAttributesDDLSerialSuite{}) +// MockGC is used to make GC work in the test environment. +func MockGC(tk *testkit.TestKit) (string, string, string, func()) { + originGC := util.IsEmulatorGCEnable() + resetGC := func() { + if originGC { + util.EmulatorGCEnable() + } else { + util.EmulatorGCDisable() + } + } + + // disable emulator GC. + // Otherwise emulator GC will delete table record as soon as possible after execute drop table ddl. + util.EmulatorGCDisable() + gcTimeFormat := "20060102-15:04:05 -0700 MST" + timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) + timeAfterDrop := time.Now().Add(48 * 60 * 60 * time.Second).Format(gcTimeFormat) + safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + // clear GC variables first. + tk.MustExec("delete from mysql.tidb where variable_name in ( 'tikv_gc_safe_point','tikv_gc_enable' )") + return timeBeforeDrop, timeAfterDrop, safePointSQL, resetGC +} -type testAttributesDDLSerialSuite struct{} +func TestAlterTableAttributes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testAttributesDDLSerialSuite) TestAlterTableAttributes(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table alter_t (c int);`) // normal cases - _, err = tk.Exec(`alter table alter_t attributes="merge_option=allow";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_t attributes="merge_option=allow,key=value";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_t attributes="merge_option=allow";`) + tk.MustExec(`alter table alter_t attributes="merge_option=allow,key=value";`) // space cases - _, err = tk.Exec(`alter table alter_t attributes=" merge_option=allow ";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_t attributes=" merge_option = allow , key = value ";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_t attributes=" merge_option=allow ";`) + tk.MustExec(`alter table alter_t attributes=" merge_option = allow , key = value ";`) // without equal - _, err = tk.Exec(`alter table alter_t attributes " merge_option=allow ";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_t attributes " merge_option=allow , key=value ";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_t attributes " merge_option=allow ";`) + tk.MustExec(`alter table alter_t attributes " merge_option=allow , key=value ";`) + } -func (s *testAttributesDDLSerialSuite) TestAlterTablePartitionAttributes(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestAlterTablePartitionAttributes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table alter_p (c int) PARTITION BY RANGE (c) ( @@ -91,37 +91,22 @@ PARTITION BY RANGE (c) ( );`) // normal cases - _, err = tk.Exec(`alter table alter_p partition p0 attributes="merge_option=allow";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_p partition p1 attributes="merge_option=allow,key=value";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_p partition p0 attributes="merge_option=allow";`) + tk.MustExec(`alter table alter_p partition p1 attributes="merge_option=allow,key=value";`) // space cases - _, err = tk.Exec(`alter table alter_p partition p2 attributes=" merge_option=allow ";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_p partition p3 attributes=" merge_option = allow , key = value ";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_p partition p2 attributes=" merge_option=allow ";`) + tk.MustExec(`alter table alter_p partition p3 attributes=" merge_option = allow , key = value ";`) // without equal - _, err = tk.Exec(`alter table alter_p partition p1 attributes " merge_option=allow ";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table alter_p partition p1 attributes " merge_option=allow , key=value ";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table alter_p partition p1 attributes " merge_option=allow ";`) + tk.MustExec(`alter table alter_p partition p1 attributes " merge_option=allow , key=value ";`) } -func (s *testAttributesDDLSerialSuite) TestTruncateTable(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestTruncateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table truncate_t (c int) PARTITION BY RANGE (c) ( @@ -130,58 +115,44 @@ PARTITION BY RANGE (c) ( );`) // add attributes - _, err = tk.Exec(`alter table truncate_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table truncate_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table truncate_t attributes="key=value";`) + tk.MustExec(`alter table truncate_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // truncate table - _, err = tk.Exec(`truncate table truncate_t;`) - c.Assert(err, IsNil) + tk.MustExec(`truncate table truncate_t;`) rows1 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) + require.Len(t, rows1, 2) // check table truncate_t's attribute - c.Assert(rows1[0][0], Equals, "schema/test/truncate_t") - c.Assert(rows1[0][2], Equals, `"key=value"`) - c.Assert(rows1[0][3], Not(Equals), rows[0][3]) + require.Equal(t, "schema/test/truncate_t", rows1[0][0]) + require.Equal(t, `"key=value"`, rows1[0][2]) + require.NotEqual(t, rows[0][3], rows1[0][3]) // check partition p0's attribute - c.Assert(rows1[1][0], Equals, "schema/test/truncate_t/p0") - c.Assert(rows1[1][2], Equals, `"key1=value1"`) - c.Assert(rows1[1][3], Not(Equals), rows[1][3]) + require.Equal(t, "schema/test/truncate_t/p0", rows1[1][0]) + require.Equal(t, `"key1=value1"`, rows1[1][2]) + require.NotEqual(t, rows[1][3], rows1[1][3]) // test only table tk.MustExec(`create table truncate_ot (c int);`) // add attribute - _, err = tk.Exec(`alter table truncate_ot attributes="key=value";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table truncate_ot attributes="key=value";`) rows2 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows2), Equals, 3) + require.Len(t, rows2, 3) // truncate table - _, err = tk.Exec(`truncate table truncate_ot;`) - c.Assert(err, IsNil) + tk.MustExec(`truncate table truncate_ot;`) rows3 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows3), Equals, 3) + require.Len(t, rows3, 3) // check table truncate_ot's attribute - c.Assert(rows3[0][0], Equals, "schema/test/truncate_ot") - c.Assert(rows3[0][2], Equals, `"key=value"`) - c.Assert(rows3[0][3], Not(Equals), rows2[0][3]) + require.Equal(t, "schema/test/truncate_ot", rows3[0][0]) + require.Equal(t, `"key=value"`, rows3[0][2]) + require.NotEqual(t, rows2[0][3], rows3[0][3]) } -func (s *testAttributesDDLSerialSuite) TestRenameTable(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestRenameTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table rename_t (c int) PARTITION BY RANGE (c) ( @@ -190,58 +161,45 @@ PARTITION BY RANGE (c) ( );`) // add attributes - _, err = tk.Exec(`alter table rename_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table rename_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table rename_t attributes="key=value";`) + tk.MustExec(`alter table rename_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // rename table - _, err = tk.Exec(`rename table rename_t to rename_t1;`) - c.Assert(err, IsNil) + tk.MustExec(`rename table rename_t to rename_t1;`) rows1 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) + require.Len(t, rows1, 2) // check table rename_t1's attribute - c.Assert(rows1[0][0], Equals, "schema/test/rename_t1") - c.Assert(rows1[0][2], Equals, `"key=value"`) - c.Assert(rows1[0][3], Equals, rows[0][3]) + require.Equal(t, "schema/test/rename_t1", rows1[0][0]) + require.Equal(t, `"key=value"`, rows1[0][2]) + require.Equal(t, rows[0][3], rows1[0][3]) // check partition p0's attribute - c.Assert(rows1[1][0], Equals, "schema/test/rename_t1/p0") - c.Assert(rows1[1][2], Equals, `"key1=value1"`) - c.Assert(rows1[1][3], Equals, rows[1][3]) + require.Equal(t, "schema/test/rename_t1/p0", rows1[1][0]) + require.Equal(t, `"key1=value1"`, rows1[1][2]) + require.Equal(t, rows[1][3], rows1[1][3]) // test only table tk.MustExec(`create table rename_ot (c int);`) // add attribute - _, err = tk.Exec(`alter table rename_ot attributes="key=value";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table rename_ot attributes="key=value";`) rows2 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows2), Equals, 3) + require.Len(t, rows2, 3) // rename table - _, err = tk.Exec(`rename table rename_ot to rename_ot1;`) - c.Assert(err, IsNil) + tk.MustExec(`rename table rename_ot to rename_ot1;`) + rows3 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows3), Equals, 3) + require.Len(t, rows3, 3) // check table rename_ot1's attribute - c.Assert(rows3[0][0], Equals, "schema/test/rename_ot1") - c.Assert(rows3[0][2], Equals, `"key=value"`) - c.Assert(rows3[0][3], Equals, rows2[0][3]) + require.Equal(t, "schema/test/rename_ot1", rows3[0][0]) + require.Equal(t, `"key=value"`, rows3[0][2]) + require.Equal(t, rows2[0][3], rows3[0][3]) } -func (s *testAttributesDDLSerialSuite) TestRecoverTable(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestRecoverTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table recover_t (c int) PARTITION BY RANGE (c) ( @@ -249,53 +207,42 @@ PARTITION BY RANGE (c) ( PARTITION p1 VALUES LESS THAN (11) );`) - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) defer resetGC() // Set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // Set GC enable. - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + require.NoError(t, gcutil.EnableGC(tk.Session())) // add attributes - _, err = tk.Exec(`alter table recover_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table recover_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table recover_t attributes="key=value";`) + tk.MustExec(`alter table recover_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // drop table - _, err = tk.Exec(`drop table recover_t;`) - c.Assert(err, IsNil) + tk.MustExec(`drop table recover_t;`) // recover table - _, err = tk.Exec(`recover table recover_t;`) - c.Assert(err, IsNil) + tk.MustExec(`recover table recover_t;`) rows1 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) + require.Len(t, rows1, 2) // check table recover_t's attribute - c.Assert(rows1[0][0], Equals, "schema/test/recover_t") - c.Assert(rows1[0][2], Equals, `"key=value"`) - c.Assert(rows1[0][3], Equals, rows[0][3]) + require.Equal(t, "schema/test/recover_t", rows1[0][0]) + require.Equal(t, `"key=value"`, rows1[0][2]) + require.Equal(t, rows[0][3], rows1[0][3]) // check partition p0's attribute - c.Assert(rows1[1][0], Equals, "schema/test/recover_t/p0") - c.Assert(rows1[1][2], Equals, `"key1=value1"`) - c.Assert(rows1[1][3], Equals, rows[1][3]) + require.Equal(t, "schema/test/recover_t/p0", rows1[1][0]) + require.Equal(t, `"key1=value1"`, rows1[1][2]) + require.Equal(t, rows[1][3], rows1[1][3]) } -func (s *testAttributesDDLSerialSuite) TestFlashbackTable(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestFlashbackTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table flash_t (c int) PARTITION BY RANGE (c) ( @@ -303,70 +250,58 @@ PARTITION BY RANGE (c) ( PARTITION p1 VALUES LESS THAN (11) );`) - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) defer resetGC() // Set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // Set GC enable. - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.EnableGC(tk.Session()) + require.NoError(t, err) // add attributes - _, err = tk.Exec(`alter table flash_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table flash_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table flash_t attributes="key=value";`) + tk.MustExec(`alter table flash_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // drop table - _, err = tk.Exec(`drop table flash_t;`) - c.Assert(err, IsNil) + tk.MustExec(`drop table flash_t;`) // flashback table - _, err = tk.Exec(`flashback table flash_t to flash_t1;`) - c.Assert(err, IsNil) + tk.MustExec(`flashback table flash_t to flash_t1;`) rows1 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) + require.Len(t, rows1, 2) // check table flash_t1's attribute - c.Assert(rows1[0][0], Equals, "schema/test/flash_t1") - c.Assert(rows1[0][2], Equals, `"key=value"`) - c.Assert(rows1[0][3], Equals, rows[0][3]) + require.Equal(t, "schema/test/flash_t1", rows1[0][0]) + require.Equal(t, `"key=value"`, rows1[0][2]) + require.Equal(t, rows[0][3], rows1[0][3]) // check partition p0's attribute - c.Assert(rows1[1][0], Equals, "schema/test/flash_t1/p0") - c.Assert(rows1[1][2], Equals, `"key1=value1"`) - c.Assert(rows1[1][3], Equals, rows[1][3]) + require.Equal(t, "schema/test/flash_t1/p0", rows1[1][0]) + require.Equal(t, `"key1=value1"`, rows1[1][2]) + require.Equal(t, rows[1][3], rows1[1][3]) // truncate table - _, err = tk.Exec(`truncate table flash_t1;`) - c.Assert(err, IsNil) + tk.MustExec(`truncate table flash_t1;`) // flashback table - _, err = tk.Exec(`flashback table flash_t1 to flash_t2;`) - c.Assert(err, IsNil) + tk.MustExec(`flashback table flash_t1 to flash_t2;`) rows2 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) + require.Len(t, rows1, 2) // check table flash_t2's attribute - c.Assert(rows2[0][0], Equals, "schema/test/flash_t2") - c.Assert(rows2[0][2], Equals, `"key=value"`) - c.Assert(rows2[0][3], Equals, rows[0][3]) + require.Equal(t, "schema/test/flash_t2", rows2[0][0]) + require.Equal(t, `"key=value"`, rows2[0][2]) + require.Equal(t, rows[0][3], rows2[0][3]) // check partition p0's attribute - c.Assert(rows2[1][0], Equals, "schema/test/flash_t2/p0") - c.Assert(rows2[1][2], Equals, `"key1=value1"`) - c.Assert(rows2[1][3], Equals, rows[1][3]) + require.Equal(t, "schema/test/flash_t2/p0", rows2[1][0]) + require.Equal(t, `"key1=value1"`, rows2[1][2]) + require.Equal(t, rows[1][3], rows2[1][3]) } -func (s *testAttributesDDLSerialSuite) TestDropTable(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestDropTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table drop_t (c int) PARTITION BY RANGE (c) ( @@ -378,48 +313,49 @@ PARTITION BY RANGE (c) ( failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") }() - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) defer resetGC() // Set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // Set GC enable. - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.EnableGC(tk.Session()) + require.NoError(t, err) gcWorker, err := gcworker.NewMockGCWorker(store) - c.Assert(err, IsNil) + require.NoError(t, err) // add attributes - _, err = tk.Exec(`alter table drop_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table drop_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table drop_t attributes="key=value";`) + tk.MustExec(`alter table drop_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // drop table - _, err = tk.Exec(`drop table drop_t;`) - c.Assert(err, IsNil) + tk.MustExec(`drop table drop_t;`) err = gcWorker.DeleteRanges(context.Background(), uint64(math.MaxInt64)) - c.Assert(err, IsNil) + require.NoError(t, err) + rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() + require.Len(t, rows, 0) + + tk.MustExec("use test") + tk.MustExec(`create table drop_t (c int) +PARTITION BY RANGE (c) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11) +);`) + rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testAttributesDDLSerialSuite) TestCreateWithSameName(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestCreateWithSameName(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table recreate_t (c int) PARTITION BY RANGE (c) ( @@ -431,31 +367,28 @@ PARTITION BY RANGE (c) ( failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") }() - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) defer resetGC() // Set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // Set GC enable. - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.EnableGC(tk.Session()) + require.NoError(t, err) gcWorker, err := gcworker.NewMockGCWorker(store) - c.Assert(err, IsNil) + require.NoError(t, err) // add attributes - _, err = tk.Exec(`alter table recreate_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table recreate_t partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table recreate_t attributes="key=value";`) + tk.MustExec(`alter table recreate_t partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // drop table - _, err = tk.Exec(`drop table recreate_t;`) - c.Assert(err, IsNil) + tk.MustExec(`drop table recreate_t;`) rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 0) tk.MustExec(`create table recreate_t (c int) PARTITION BY RANGE (c) ( @@ -463,40 +396,31 @@ PARTITION BY RANGE (c) ( PARTITION p1 VALUES LESS THAN (11) );`) // add attributes - _, err = tk.Exec(`alter table recreate_t attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table recreate_t partition p1 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table recreate_t attributes="key=value";`) + tk.MustExec(`alter table recreate_t partition p1 attributes="key1=value1";`) rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 3) + require.Len(t, rows, 2) err = gcWorker.DeleteRanges(context.Background(), uint64(math.MaxInt64)) - c.Assert(err, IsNil) + require.NoError(t, err) rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // drop table - _, err = tk.Exec(`drop table recreate_t;`) - c.Assert(err, IsNil) + tk.MustExec(`drop table recreate_t;`) err = gcWorker.DeleteRanges(context.Background(), uint64(math.MaxInt64)) - c.Assert(err, IsNil) + require.NoError(t, err) rows = tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testAttributesDDLSerialSuite) TestPartition(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestPartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table part (c int) PARTITION BY RANGE (c) ( @@ -507,69 +431,56 @@ PARTITION BY RANGE (c) ( tk.MustExec(`create table part1 (c int);`) // add attributes - _, err = tk.Exec(`alter table part attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table part partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table part partition p1 attributes="key2=value2";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table part attributes="key=value";`) + tk.MustExec(`alter table part partition p0 attributes="key1=value1";`) + tk.MustExec(`alter table part partition p1 attributes="key2=value2";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows), Equals, 3) + require.Len(t, rows, 3) // drop partition // partition p0's attribute will be deleted - _, err = tk.Exec(`alter table part drop partition p0;`) - c.Assert(err, IsNil) + tk.MustExec(`alter table part drop partition p0;`) rows1 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows1), Equals, 2) - c.Assert(rows1[0][0], Equals, "schema/test/part") - c.Assert(rows1[0][2], Equals, `"key=value"`) - c.Assert(rows1[0][3], Equals, rows[0][3]) - c.Assert(rows1[1][0], Equals, "schema/test/part/p1") - c.Assert(rows1[1][2], Equals, `"key2=value2"`) - c.Assert(rows1[1][3], Equals, rows[2][3]) + require.Len(t, rows1, 2) + require.Equal(t, "schema/test/part", rows1[0][0]) + require.Equal(t, `"key=value"`, rows1[0][2]) + require.Equal(t, rows[0][3], rows1[0][3]) + require.Equal(t, "schema/test/part/p1", rows1[1][0]) + require.Equal(t, `"key2=value2"`, rows1[1][2]) + require.Equal(t, rows[2][3], rows1[1][3]) // truncate partition // partition p1's key range will be updated - _, err = tk.Exec(`alter table part truncate partition p1;`) - c.Assert(err, IsNil) + tk.MustExec(`alter table part truncate partition p1;`) rows2 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows2), Equals, 2) - c.Assert(rows2[0][0], Equals, "schema/test/part") - c.Assert(rows2[0][2], Equals, `"key=value"`) - c.Assert(rows2[0][3], Not(Equals), rows1[0][3]) - c.Assert(rows2[1][0], Equals, "schema/test/part/p1") - c.Assert(rows2[1][2], Equals, `"key2=value2"`) - c.Assert(rows2[1][3], Not(Equals), rows1[1][3]) + require.Len(t, rows2, 2) + require.Equal(t, "schema/test/part", rows2[0][0]) + require.Equal(t, `"key=value"`, rows2[0][2]) + require.NotEqual(t, rows1[0][3], rows2[0][3]) + require.Equal(t, "schema/test/part/p1", rows2[1][0]) + require.Equal(t, `"key2=value2"`, rows2[1][2]) + require.NotEqual(t, rows1[1][3], rows2[1][3]) // exchange partition // partition p1's attribute will be exchanged to table part1 - _, err = tk.Exec(`set @@tidb_enable_exchange_partition=1;`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table part exchange partition p1 with table part1;`) - c.Assert(err, IsNil) + tk.MustExec(`set @@tidb_enable_exchange_partition=1;`) + tk.MustExec(`alter table part exchange partition p1 with table part1;`) rows3 := tk.MustQuery(`select * from information_schema.attributes;`).Sort().Rows() - c.Assert(len(rows3), Equals, 2) - c.Assert(rows3[0][0], Equals, "schema/test/part") - c.Assert(rows3[0][2], Equals, `"key=value"`) - c.Assert(rows3[0][3], Equals, rows2[0][3]) - c.Assert(rows3[1][0], Equals, "schema/test/part1") - c.Assert(rows3[1][2], Equals, `"key2=value2"`) - c.Assert(rows3[1][3], Equals, rows2[1][3]) + require.Len(t, rows3, 2) + require.Equal(t, "schema/test/part", rows3[0][0]) + require.Equal(t, `"key=value"`, rows3[0][2]) + require.Equal(t, rows2[0][3], rows3[0][3]) + require.Equal(t, "schema/test/part1", rows3[1][0]) + require.Equal(t, `"key2=value2"`, rows3[1][2]) + require.Equal(t, rows2[1][3], rows3[1][3]) } -func (s *testAttributesDDLSerialSuite) TestDropSchema(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestDropSchema(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table drop_s1 (c int) PARTITION BY RANGE (c) ( @@ -579,34 +490,24 @@ PARTITION BY RANGE (c) ( tk.MustExec(`create table drop_s2 (c int);`) // add attributes - _, err = tk.Exec(`alter table drop_s1 attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table drop_s1 partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table drop_s2 attributes="key=value";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table drop_s1 attributes="key=value";`) + tk.MustExec(`alter table drop_s1 partition p0 attributes="key1=value1";`) + tk.MustExec(`alter table drop_s2 attributes="key=value";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Rows() - c.Assert(len(rows), Equals, 3) + require.Len(t, rows, 3) // drop database - _, err = tk.Exec(`drop database test`) - c.Assert(err, IsNil) + tk.MustExec(`drop database test`) rows = tk.MustQuery(`select * from information_schema.attributes;`).Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testAttributesDDLSerialSuite) TestDefaultKeyword(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err := store.Close() - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, store) +func TestDefaultKeyword(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table def (c int) PARTITION BY RANGE (c) ( @@ -615,20 +516,16 @@ PARTITION BY RANGE (c) ( );`) // add attributes - _, err = tk.Exec(`alter table def attributes="key=value";`) - c.Assert(err, IsNil) - _, err = tk.Exec(`alter table def partition p0 attributes="key1=value1";`) - c.Assert(err, IsNil) + tk.MustExec(`alter table def attributes="key=value";`) + tk.MustExec(`alter table def partition p0 attributes="key1=value1";`) rows := tk.MustQuery(`select * from information_schema.attributes;`).Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) // reset the partition p0's attribute - _, err = tk.Exec(`alter table def partition p0 attributes=default;`) - c.Assert(err, IsNil) + tk.MustExec(`alter table def partition p0 attributes=default;`) rows = tk.MustQuery(`select * from information_schema.attributes;`).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) // reset the table def's attribute - _, err = tk.Exec(`alter table def attributes=default;`) - c.Assert(err, IsNil) + tk.MustExec(`alter table def attributes=default;`) rows = tk.MustQuery(`select * from information_schema.attributes;`).Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } diff --git a/ddl/backfilling.go b/ddl/backfilling.go index 4f54d13959284..10e9249ee4cf5 100644 --- a/ddl/backfilling.go +++ b/ddl/backfilling.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "strconv" + "sync" "sync/atomic" "time" @@ -37,8 +38,11 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" decoder "github.com/pingcap/tidb/util/rowDecoder" + "github.com/pingcap/tidb/util/timeutil" + "github.com/pingcap/tidb/util/topsql" "github.com/tikv/client-go/v2/tikv" "go.uber.org/zap" ) @@ -290,7 +294,7 @@ func (w *backfillWorker) handleBackfillTask(d *ddlCtx, task *reorgBackfillTask, func (w *backfillWorker) run(d *ddlCtx, bf backfiller, job *model.Job) { logutil.BgLogger().Info("[ddl] backfill worker start", zap.Int("workerID", w.id)) defer func() { - w.resultCh <- &backfillResult{err: errReorgPanic} + w.resultCh <- &backfillResult{err: dbterror.ErrReorgPanic} }() defer util.Recover(metrics.LabelDDL, "backfillWorker.run", nil, false) for { @@ -309,6 +313,11 @@ func (w *backfillWorker) run(d *ddlCtx, bf backfiller, job *model.Job) { } }) + failpoint.Inject("mockHighLoadForAddIndex", func() { + sqlPrefixes := []string{"alter"} + topsql.MockHighCPULoad(job.Query, sqlPrefixes, 5) + }) + // Dynamic change batch size. w.batchCnt = int(variable.GetDDLReorgBatchSize()) result := w.handleBackfillTask(d, task, bf) @@ -341,7 +350,7 @@ func splitTableRanges(t table.PhysicalTable, store kv.Storage, startKey, endKey } if len(ranges) == 0 { errMsg := fmt.Sprintf("cannot find region in range [%s, %s]", startKey.String(), endKey.String()) - return nil, errors.Trace(errInvalidSplitRegionRanges.GenWithStackByArgs(errMsg)) + return nil, errors.Trace(dbterror.ErrInvalidSplitRegionRanges.GenWithStackByArgs(errMsg)) } return ranges, nil } @@ -501,7 +510,7 @@ func (w *worker) sendRangeTaskToWorkers(t table.Table, workers []*backfillWorker var ( // TestCheckWorkerNumCh use for test adjust backfill worker. - TestCheckWorkerNumCh = make(chan struct{}) + TestCheckWorkerNumCh = make(chan *sync.WaitGroup) // TestCheckWorkerNumber use for test adjust backfill worker. TestCheckWorkerNumber = int32(16) // TestCheckReorgTimeout is used to mock timeout when reorg data. @@ -536,6 +545,19 @@ func makeupDecodeColMap(sessCtx sessionctx.Context, t table.Table) (map[int64]de return decodeColMap, nil } +func setSessCtxLocation(sctx sessionctx.Context, info *reorgInfo) error { + // It is set to SystemLocation to be compatible with nil LocationInfo. + *sctx.GetSessionVars().TimeZone = *timeutil.SystemLocation() + if info.ReorgMeta.Location != nil { + loc, err := info.ReorgMeta.Location.GetLocation() + if err != nil { + return errors.Trace(err) + } + *sctx.GetSessionVars().TimeZone = *loc + } + return nil +} + // writePhysicalTableRecord handles the "add index" or "modify/change column" reorganization state for a non-partitioned table or a partition. // For a partitioned table, it should be handled partition by partition. // @@ -606,14 +628,17 @@ func (w *worker) writePhysicalTableRecord(t table.PhysicalTable, bfWorkerType ba // Simulate the sql mode environment in the worker sessionCtx. sqlMode := reorgInfo.ReorgMeta.SQLMode sessCtx.GetSessionVars().SQLMode = sqlMode - // TODO: skip set the timezone, it will cause data inconsistency when add index, since some reorg place using the timeUtil.SystemLocation() to do the time conversion. (need a more systemic plan) - // sessCtx.GetSessionVars().TimeZone = reorgInfo.ReorgMeta.Location + if err := setSessCtxLocation(sessCtx, reorgInfo); err != nil { + return errors.Trace(err) + } + sessCtx.GetSessionVars().StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode() sessCtx.GetSessionVars().StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode() sessCtx.GetSessionVars().StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode() sessCtx.GetSessionVars().StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode() sessCtx.GetSessionVars().StmtCtx.DividedByZeroAsWarning = !sqlMode.HasStrictMode() sessCtx.GetSessionVars().StmtCtx.IgnoreZeroInDate = !sqlMode.HasStrictMode() || sqlMode.HasAllowInvalidDatesMode() + sessCtx.GetSessionVars().StmtCtx.NoZeroDate = sqlMode.HasStrictMode() switch bfWorkerType { case typeAddIndexWorker: @@ -655,7 +680,10 @@ func (w *worker) writePhysicalTableRecord(t table.PhysicalTable, bfWorkerType ba } else if num != len(backfillWorkers) { failpoint.Return(errors.Errorf("check backfill worker num error, len kv ranges is: %v, check backfill worker num is: %v, actual record num is: %v", len(kvRanges), num, len(backfillWorkers))) } - TestCheckWorkerNumCh <- struct{}{} + var wg sync.WaitGroup + wg.Add(1) + TestCheckWorkerNumCh <- &wg + wg.Wait() } } }) @@ -681,7 +709,7 @@ func (w *worker) writePhysicalTableRecord(t table.PhysicalTable, bfWorkerType ba // recordIterFunc is used for low-level record iteration. type recordIterFunc func(h kv.Handle, rowKey kv.Key, rawRecord []byte) (more bool, err error) -func iterateSnapshotRows(store kv.Storage, priority int, t table.Table, version uint64, +func iterateSnapshotRows(ctx *JobContext, store kv.Storage, priority int, t table.Table, version uint64, startKey kv.Key, endKey kv.Key, fn recordIterFunc) error { var firstKey kv.Key if startKey == nil { @@ -700,6 +728,9 @@ func iterateSnapshotRows(store kv.Storage, priority int, t table.Table, version ver := kv.Version{Ver: version} snap := store.GetSnapshot(ver) snap.SetOption(kv.Priority, priority) + if tagger := ctx.getResourceGroupTaggerForTopSQL(); tagger != nil { + snap.SetOption(kv.ResourceGroupTagger, tagger) + } it, err := snap.Iter(firstKey, upperBound) if err != nil { diff --git a/ddl/cancel_ddl_test.go b/ddl/cancel_ddl_test.go new file mode 100644 index 0000000000000..30c0b55a088c1 --- /dev/null +++ b/ddl/cancel_ddl_test.go @@ -0,0 +1,777 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package ddl + +import ( + "context" + "sync" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/charset" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type testDDLSerialSuiteToVerify struct { + suite.Suite +} + +func TestDDLSerialSuite(t *testing.T) { + suite.Run(t, new(testDDLSerialSuiteToVerify)) +} + +func (s *testDDLSerialSuiteToVerify) SetupSuite() { + SetWaitTimeWhenErrorOccurred(time.Microsecond) +} + +func checkCancelState(txn kv.Transaction, job *model.Job, test *testCancelJob) error { + var checkErr error + addIndexFirstReorg := (test.act == model.ActionAddIndex || test.act == model.ActionAddPrimaryKey) && + job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 + // If the action is adding index and the state is writing reorganization, it wants to test the case of cancelling the job when backfilling indexes. + // When the job satisfies this case of addIndexFirstReorg, the worker hasn't started to backfill indexes. + if test.cancelState == job.SchemaState && !addIndexFirstReorg && !job.IsRollingback() { + errs, err := admin.CancelJobs(txn, test.jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return checkErr + } + // It only tests cancel one DDL job. + if !terror.ErrorEqual(errs[0], test.cancelRetErrs[0]) { + checkErr = errors.Trace(errs[0]) + return checkErr + } + } + return checkErr +} + +type testCancelJob struct { + jobIDs []int64 + cancelRetErrs []error // cancelRetErrs is the first return value of CancelJobs. + act model.ActionType // act is the job action. + cancelState model.SchemaState +} + +func buildCancelJobTests(firstID int64) []testCancelJob { + noErrs := []error{nil} + tests := []testCancelJob{ + {act: model.ActionAddIndex, jobIDs: []int64{firstID + 1}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, + {act: model.ActionAddIndex, jobIDs: []int64{firstID + 2}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, + {act: model.ActionAddIndex, jobIDs: []int64{firstID + 3}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, + {act: model.ActionAddIndex, jobIDs: []int64{firstID + 4}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 4)}, cancelState: model.StatePublic}, + + // Test cancel drop index job , see TestCancelDropIndex. + {act: model.ActionAddColumn, jobIDs: []int64{firstID + 5}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, + {act: model.ActionAddColumn, jobIDs: []int64{firstID + 6}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, + {act: model.ActionAddColumn, jobIDs: []int64{firstID + 7}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, + {act: model.ActionAddColumn, jobIDs: []int64{firstID + 8}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 8)}, cancelState: model.StatePublic}, + + // Test create table, watch out, table id will alloc a globalID. + {act: model.ActionCreateTable, jobIDs: []int64{firstID + 10}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + // Test create database, watch out, database id will alloc a globalID. + {act: model.ActionCreateSchema, jobIDs: []int64{firstID + 12}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + + {act: model.ActionDropColumn, jobIDs: []int64{firstID + 13}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 13)}, cancelState: model.StateDeleteOnly}, + {act: model.ActionDropColumn, jobIDs: []int64{firstID + 14}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 14)}, cancelState: model.StateWriteOnly}, + {act: model.ActionDropColumn, jobIDs: []int64{firstID + 15}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 15)}, cancelState: model.StateWriteReorganization}, + {act: model.ActionRebaseAutoID, jobIDs: []int64{firstID + 16}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionShardRowID, jobIDs: []int64{firstID + 17}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 18}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 19}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, + + {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 20}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 21}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 21)}, cancelState: model.StatePublic}, + {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 22}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 23}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 23)}, cancelState: model.StatePublic}, + + {act: model.ActionRenameTable, jobIDs: []int64{firstID + 24}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionRenameTable, jobIDs: []int64{firstID + 25}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 25)}, cancelState: model.StatePublic}, + + {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 26}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 27}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 27)}, cancelState: model.StatePublic}, + {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 28}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 29}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 29)}, cancelState: model.StatePublic}, + {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 31}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 32}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 32)}, cancelState: model.StatePublic}, + + {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 33}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, + {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 34}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, + {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 35}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, + {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 36}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 36)}, cancelState: model.StatePublic}, + {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 37}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, + {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 38}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 38)}, cancelState: model.StateDeleteOnly}, + + {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 40}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 41}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 48)}, cancelState: model.StatePublic}, + + {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 47}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 48}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 55)}, cancelState: model.StatePublic}, + + {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 53}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 54}, cancelRetErrs: noErrs, cancelState: model.StateReplicaOnly}, + {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 55}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, + + // modify column has two different types, normal-type and reorg-type. The latter has 5 states and it can be cancelled except the public state. + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 58}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 59}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 60}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 61}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, + {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 62}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, + + // for alter db placement + {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 68}, cancelRetErrs: noErrs, cancelState: model.StateNone}, + {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 69}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 76)}, cancelState: model.StatePublic}, + } + + return tests +} + +func (s *testDDLSerialSuiteToVerify) checkDropIdx(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { + checkIdxExist(t, d, schemaID, tableID, idxName, !success) +} + +func (s *testDDLSerialSuiteToVerify) checkAddIdx(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { + checkIdxExist(t, d, schemaID, tableID, idxName, success) +} + +func checkIdxExist(t *testing.T, d *ddl, schemaID int64, tableID int64, idxName string, expectedExist bool) { + changedTable := testGetTable(t, d, schemaID, tableID) + var found bool + for _, idxInfo := range changedTable.Meta().Indices { + if idxInfo.Name.O == idxName { + found = true + break + } + } + require.Equal(t, found, expectedExist) +} + +func (s *testDDLSerialSuiteToVerify) checkAddColumns(d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { + changedTable := testGetTable(s.T(), d, schemaID, tableID) + found := !checkColumnsNotFound(changedTable, colNames) + require.Equal(s.T(), found, success) +} + +func (s *testDDLSerialSuiteToVerify) checkCancelDropColumns(d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { + changedTable := testGetTable(s.T(), d, schemaID, tableID) + notFound := checkColumnsNotFound(changedTable, colNames) + require.Equal(s.T(), notFound, success) +} + +func checkColumnsNotFound(t table.Table, colNames []string) bool { + notFound := true + for _, colName := range colNames { + for _, colInfo := range t.Meta().Columns { + if colInfo.Name.O == colName { + notFound = false + } + } + } + return notFound +} + +func checkIdxVisibility(changedTable table.Table, idxName string, expected bool) bool { + for _, idxInfo := range changedTable.Meta().Indices { + if idxInfo.Name.O == idxName && idxInfo.Invisible == expected { + return true + } + } + return false +} + +func (s *testDDLSerialSuiteToVerify) TestCancelJob() { + store := createMockStore(s.T()) + defer func() { + require.NoError(s.T(), store.Close()) + }() + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(s.T(), err) + defer func() { + require.NoError(s.T(), d.Stop()) + }() + dbInfo, err := testSchemaInfo(d, "test_cancel_job") + require.NoError(s.T(), err) + testCreateSchema(s.T(), testNewContext(d), d, dbInfo) + // create a partition table. + partitionTblInfo := testTableInfoWithPartition(s.T(), d, "t_partition", 5) + // Skip using sessPool. Make sure adding primary key can be successful. + partitionTblInfo.Columns[0].Flag |= mysql.NotNullFlag + // create table t (c1 int, c2 int, c3 int, c4 int, c5 int); + tblInfo, err := testTableInfo(d, "t", 5) + require.NoError(s.T(), err) + ctx := testNewContext(d) + err = ctx.NewTxn(context.Background()) + require.NoError(s.T(), err) + err = ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "1") + require.NoError(s.T(), err) + defer func() { + err := ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "0") + require.NoError(s.T(), err) + }() + testCreateTable(s.T(), ctx, d, dbInfo, partitionTblInfo) + tableAutoID := int64(100) + shardRowIDBits := uint64(5) + tblInfo.AutoIncID = tableAutoID + tblInfo.ShardRowIDBits = shardRowIDBits + job := testCreateTable(s.T(), ctx, d, dbInfo, tblInfo) + // insert t values (1, 2, 3, 4, 5); + originTable := testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + row := types.MakeDatums(1, 2, 3, 4, 5) + _, err = originTable.AddRecord(ctx, row) + require.NoError(s.T(), err) + txn, err := ctx.Txn(true) + require.NoError(s.T(), err) + err = txn.Commit(context.Background()) + require.NoError(s.T(), err) + + tc := &TestDDLCallback{} + // set up hook + firstJobID := job.ID + tests := buildCancelJobTests(firstJobID) + var checkErr error + var mu sync.Mutex + var test *testCancelJob + updateTest := func(t *testCancelJob) { + mu.Lock() + test = t + mu.Unlock() + } + hookCancelFunc := func(job *model.Job) { + if job.State == model.JobStateSynced || job.State == model.JobStateCancelled || job.State == model.JobStateCancelling { + return + } + // This hook only valid for the related test job. + // This is use to avoid parallel test fail. + mu.Lock() + if len(test.jobIDs) > 0 && test.jobIDs[0] != job.ID { + mu.Unlock() + return + } + mu.Unlock() + if checkErr != nil { + return + } + + hookCtx := mock.NewContext() + hookCtx.Store = store + err1 := hookCtx.NewTxn(context.Background()) + if err1 != nil { + checkErr = errors.Trace(err1) + return + } + txn, err1 = hookCtx.Txn(true) + if err1 != nil { + checkErr = errors.Trace(err1) + return + } + mu.Lock() + checkErr = checkCancelState(txn, job, test) + mu.Unlock() + if checkErr != nil { + return + } + err1 = txn.Commit(context.Background()) + if err1 != nil { + checkErr = errors.Trace(err1) + return + } + } + tc.onJobUpdated = hookCancelFunc + tc.onJobRunBefore = hookCancelFunc + d.SetHook(tc) + + // for adding index + updateTest(&tests[0]) + idxOrigName := "idx" + validArgs := []interface{}{false, model.NewCIStr(idxOrigName), + []*ast.IndexPartSpecification{{ + Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, + Length: -1, + }}, nil} + + // When the job satisfies this test case, the option will be rollback, so the job's schema state is none. + cancelState := model.StateNone + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[1]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[2]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[3]) + testCreateIndex(s.T(), ctx, d, dbInfo, tblInfo, false, "idx", "c2") + require.NoError(s.T(), checkErr) + txn, err = ctx.Txn(true) + require.NoError(s.T(), err) + require.Nil(s.T(), txn.Commit(context.Background())) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) + + // for add column + updateTest(&tests[4]) + addingColName := "colA" + newColumnDef := &ast.ColumnDef{ + Name: &ast.ColumnName{Name: model.NewCIStr(addingColName)}, + Tp: &types.FieldType{Tp: mysql.TypeLonglong}, + Options: []*ast.ColumnOption{}, + } + chs, coll := charset.GetDefaultCharsetAndCollate() + col, _, err := buildColumnAndConstraint(ctx, 2, newColumnDef, nil, chs, coll) + require.NoError(s.T(), err) + + addColumnArgs := []interface{}{col, &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 0} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) + + updateTest(&tests[5]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) + + updateTest(&tests[6]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) + + updateTest(&tests[7]) + testAddColumn(s.T(), ctx, d, dbInfo, tblInfo, addColumnArgs) + require.NoError(s.T(), checkErr) + s.checkAddColumns(d, dbInfo.ID, tblInfo.ID, []string{addingColName}, true) + + // for create table + tblInfo1, err := testTableInfo(d, "t1", 2) + require.NoError(s.T(), err) + updateTest(&tests[8]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo1.ID, model.ActionCreateTable, []interface{}{tblInfo1}, &cancelState) + require.NoError(s.T(), checkErr) + testCheckTableState(s.T(), d, dbInfo, tblInfo1, model.StateNone) + + // for create database + dbInfo1, err := testSchemaInfo(d, "test_cancel_job1") + require.NoError(s.T(), err) + updateTest(&tests[9]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo1.ID, 0, model.ActionCreateSchema, []interface{}{dbInfo1}, &cancelState) + require.NoError(s.T(), checkErr) + testCheckSchemaState(s.T(), d, dbInfo1, model.StateNone) + + // for drop column. + updateTest(&tests[10]) + dropColName := "c3" + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) + testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) + require.NoError(s.T(), checkErr) + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) + + updateTest(&tests[11]) + dropColName = "c4" + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) + testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) + require.NoError(s.T(), checkErr) + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) + + updateTest(&tests[12]) + dropColName = "c5" + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) + testDropColumn(s.T(), ctx, d, dbInfo, tblInfo, dropColName, false) + require.NoError(s.T(), checkErr) + s.checkCancelDropColumns(d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) + + // cancel rebase auto id + updateTest(&tests[13]) + rebaseIDArgs := []interface{}{int64(200)} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionRebaseAutoID, rebaseIDArgs, &cancelState) + require.NoError(s.T(), checkErr) + changedTable := testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().AutoIncID, tableAutoID) + + // cancel shard bits + updateTest(&tests[14]) + shardRowIDArgs := []interface{}{uint64(7)} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionShardRowID, shardRowIDArgs, &cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().ShardRowIDBits, shardRowIDBits) + + // modify none-state column + col.DefaultValue = "1" + updateTest(&tests[15]) + modifyColumnArgs := []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + changedCol := model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) + require.Nil(s.T(), changedCol.DefaultValue) + + // modify delete-only-state column, + col.FieldType.Tp = mysql.TypeTiny + col.FieldType.Flen-- + updateTest(&tests[16]) + modifyColumnArgs = []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} + cancelState = model.StateNone + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + changedCol = model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) + require.Equal(s.T(), changedCol.FieldType.Tp, mysql.TypeLonglong) + require.Equal(s.T(), changedCol.FieldType.Flen, col.FieldType.Flen+1) + col.FieldType.Flen++ + + // Test add foreign key failed cause by canceled. + updateTest(&tests[17]) + addForeignKeyArgs := []interface{}{model.FKInfo{Name: model.NewCIStr("fk1")}} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 0) + + // Test add foreign key successful. + updateTest(&tests[18]) + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 1) + require.Equal(s.T(), changedTable.Meta().ForeignKeys[0].Name, addForeignKeyArgs[0].(model.FKInfo).Name) + + // Test drop foreign key failed cause by canceled. + updateTest(&tests[19]) + dropForeignKeyArgs := []interface{}{addForeignKeyArgs[0].(model.FKInfo).Name} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 1) + require.Equal(s.T(), changedTable.Meta().ForeignKeys[0].Name, dropForeignKeyArgs[0].(model.CIStr)) + + // Test drop foreign key successful. + updateTest(&tests[20]) + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), len(changedTable.Meta().ForeignKeys), 0) + + // test rename table failed caused by canceled. + test = &tests[21] + renameTableArgs := []interface{}{dbInfo.ID, model.NewCIStr("t2"), dbInfo.Name} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, renameTableArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().Name.L, "t") + + // test rename table successful. + test = &tests[22] + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, renameTableArgs) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().Name.L, "t2") + + // test modify table charset failed caused by canceled. + test = &tests[23] + modifyTableCharsetArgs := []interface{}{"utf8mb4", "utf8mb4_bin"} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().Charset, "utf8") + require.Equal(s.T(), changedTable.Meta().Collate, "utf8_bin") + + // test modify table charset successfully. + test = &tests[24] + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.Equal(s.T(), changedTable.Meta().Charset, "utf8mb4") + require.Equal(s.T(), changedTable.Meta().Collate, "utf8mb4_bin") + + // test truncate table partition failed caused by canceled. + test = &tests[25] + truncateTblPartitionArgs := []interface{}{[]int64{partitionTblInfo.Partition.Definitions[0].ID}} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, partitionTblInfo.ID) + require.True(s.T(), changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID) + + // test truncate table partition charset successfully. + test = &tests[26] + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, partitionTblInfo.ID) + require.False(s.T(), changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID) + + // test modify schema charset failed caused by canceled. + test = &tests[27] + charsetAndCollate := []interface{}{"utf8mb4", "utf8mb4_bin"} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate, &test.cancelState) + require.NoError(s.T(), checkErr) + dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) + require.NoError(s.T(), err) + require.Equal(s.T(), dbInfo.Charset, "") + require.Equal(s.T(), dbInfo.Collate, "") + + // test modify table charset successfully. + test = &tests[28] + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate) + require.NoError(s.T(), checkErr) + dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) + require.NoError(s.T(), err) + require.Equal(s.T(), dbInfo.Charset, "utf8mb4") + require.Equal(s.T(), dbInfo.Collate, "utf8mb4_bin") + + // for adding primary key + tblInfo = changedTable.Meta() + updateTest(&tests[29]) + idxOrigName = "primary" + validArgs = []interface{}{false, model.NewCIStr(idxOrigName), + []*ast.IndexPartSpecification{{ + Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, + Length: -1, + }}, nil} + cancelState = model.StateNone + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[30]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[31]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[32]) + testCreatePrimaryKey(s.T(), ctx, d, dbInfo, tblInfo, "c1") + require.NoError(s.T(), checkErr) + txn, err = ctx.Txn(true) + require.NoError(s.T(), err) + require.Nil(s.T(), txn.Commit(context.Background())) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) + + // for dropping primary key + updateTest(&tests[33]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, model.ActionDropPrimaryKey, validArgs, &cancelState) + require.NoError(s.T(), checkErr) + s.checkDropIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, false) + updateTest(&tests[34]) + testDropIndex(s.T(), ctx, d, dbInfo, tblInfo, idxOrigName) + require.NoError(s.T(), checkErr) + s.checkDropIdx(s.T(), d, dbInfo.ID, tblInfo.ID, idxOrigName, true) + + // test alter index visibility failed caused by canceled. + indexName := "idx_c3" + testCreateIndex(s.T(), ctx, d, dbInfo, tblInfo, false, indexName, "c3") + require.NoError(s.T(), checkErr) + txn, err = ctx.Txn(true) + require.NoError(s.T(), err) + require.Nil(s.T(), txn.Commit(context.Background())) + s.checkAddIdx(s.T(), d, dbInfo.ID, tblInfo.ID, indexName, true) + + updateTest(&tests[35]) + alterIndexVisibility := []interface{}{model.NewCIStr(indexName), true} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility, &test.cancelState) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.True(s.T(), checkIdxVisibility(changedTable, indexName, false)) + + // cancel alter index visibility successfully + updateTest(&tests[36]) + alterIndexVisibility = []interface{}{model.NewCIStr(indexName), true} + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility) + require.NoError(s.T(), checkErr) + changedTable = testGetTable(s.T(), d, dbInfo.ID, tblInfo.ID) + require.True(s.T(), checkIdxVisibility(changedTable, indexName, true)) + + // test exchange partition failed caused by canceled + pt := testTableInfoWithPartition(s.T(), d, "pt", 5) + nt, err := testTableInfo(d, "nt", 5) + require.NoError(s.T(), err) + testCreateTable(s.T(), ctx, d, dbInfo, pt) + testCreateTable(s.T(), ctx, d, dbInfo, nt) + + updateTest(&tests[37]) + defID := pt.Partition.Definitions[0].ID + exchangeTablePartition := []interface{}{defID, dbInfo.ID, pt.ID, "p0", true} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, nt.ID, test.act, exchangeTablePartition, &test.cancelState) + require.NoError(s.T(), checkErr) + changedNtTable := testGetTable(s.T(), d, dbInfo.ID, nt.ID) + changedPtTable := testGetTable(s.T(), d, dbInfo.ID, pt.ID) + require.True(s.T(), changedNtTable.Meta().ID == nt.ID) + require.True(s.T(), changedPtTable.Meta().Partition.Definitions[0].ID == pt.Partition.Definitions[0].ID) + + // cancel exchange partition successfully + updateTest(&tests[38]) + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, nt.ID, test.act, exchangeTablePartition) + require.NoError(s.T(), checkErr) + changedNtTable = testGetTable(s.T(), d, dbInfo.ID, pt.Partition.Definitions[0].ID) + changedPtTable = testGetTable(s.T(), d, dbInfo.ID, pt.ID) + require.False(s.T(), changedNtTable.Meta().ID == nt.ID) + require.True(s.T(), changedPtTable.Meta().Partition.Definitions[0].ID == nt.ID) + + // Cancel add table partition. + baseTableInfo := testTableInfoWithPartitionLessThan(s.T(), d, "empty_table", 5, "1000") + testCreateTable(s.T(), ctx, d, dbInfo, baseTableInfo) + + cancelState = model.StateNone + updateTest(&tests[39]) + addedPartInfo := testAddedNewTablePartitionInfo(s.T(), d, baseTableInfo, "p1", "maxvalue") + addPartitionArgs := []interface{}{addedPartInfo} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable := testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 1) + + updateTest(&tests[40]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 1) + + updateTest(&tests[41]) + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), len(baseTable.Meta().Partition.Definitions), 2) + require.Equal(s.T(), baseTable.Meta().Partition.Definitions[1].ID, addedPartInfo.Definitions[0].ID) + require.Equal(s.T(), baseTable.Meta().Partition.Definitions[1].LessThan[0], addedPartInfo.Definitions[0].LessThan[0]) + + // Cancel modify column which should reorg the data. + require.Nil(s.T(), failpoint.Enable("github.com/pingcap/tidb/ddl/skipMockContextDoExec", `return(true)`)) + baseTableInfo = testTableInfoWith2IndexOnFirstColumn(s.T(), d, "modify-table", 2) + // This will cost 2 global id, one for table id, the other for the job id. + testCreateTable(s.T(), ctx, d, dbInfo, baseTableInfo) + + cancelState = model.StateNone + newCol := baseTableInfo.Columns[0].Clone() + // change type from long to tinyint. + newCol.FieldType = *types.NewFieldType(mysql.TypeTiny) + // change from null to not null + newCol.FieldType.Flag |= mysql.NotNullFlag + newCol.FieldType.Flen = 2 + + originColName := baseTableInfo.Columns[0].Name + pos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} + + updateTest(&tests[42]) + modifyColumnArgs = []interface{}{&newCol, originColName, pos, mysql.TypeNull, 0} + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) + require.Equal(s.T(), mysql.HasNotNullFlag(baseTable.Meta().Columns[0].FieldType.Flag), false) + + updateTest(&tests[43]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) + + updateTest(&tests[44]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) + + updateTest(&tests[45]) + doDDLJobErrWithSchemaState(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeLong) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(0)) + + updateTest(&tests[46]) + doDDLJobSuccess(ctx, d, s.T(), dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs) + require.NoError(s.T(), checkErr) + baseTable = testGetTable(s.T(), d, dbInfo.ID, baseTableInfo.ID) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Tp, mysql.TypeTiny) + require.Equal(s.T(), baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, uint(1)) + require.Nil(s.T(), failpoint.Disable("github.com/pingcap/tidb/ddl/skipMockContextDoExec")) +} + +func doDDLJobErrWithSchemaState(ctx sessionctx.Context, ddl *ddl, t *testing.T, schemaID, tableID int64, tp model.ActionType, + args []interface{}, state *model.SchemaState) *model.Job { + job := &model.Job{ + SchemaID: schemaID, + TableID: tableID, + Type: tp, + Args: args, + BinlogInfo: &model.HistoryInfo{}, + } + // TODO: check error detail + ctx.SetValue(sessionctx.QueryString, "skip") + require.Error(t, ddl.DoDDLJob(ctx, job)) + testCheckJobCancelled(t, ddl.store, job, state) + + return job +} + +func doDDLJobSuccess(ctx sessionctx.Context, ddl DDL, t *testing.T, schemaID, tableID int64, tp model.ActionType, + args []interface{}) { + job := &model.Job{ + SchemaID: schemaID, + TableID: tableID, + Type: tp, + Args: args, + BinlogInfo: &model.HistoryInfo{}, + } + ctx.SetValue(sessionctx.QueryString, "skip") + err := ddl.DoDDLJob(ctx, job) + require.NoError(t, err) +} + +func buildDropColumnJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { + return &model.Job{ + SchemaID: dbInfo.ID, + TableID: tblInfo.ID, + Type: model.ActionDropColumn, + BinlogInfo: &model.HistoryInfo{}, + MultiSchemaInfo: &model.MultiSchemaInfo{}, + Args: []interface{}{model.NewCIStr(colName), false}, + } +} + +func testDropColumn(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string, isError bool) *model.Job { + job := buildDropColumnJob(dbInfo, tblInfo, colName) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + if isError { + require.Error(t, err) + return nil + } + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + return job +} diff --git a/ddl/column.go b/ddl/column.go index ee1eed6c6d669..7d90288f32449 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -43,97 +43,16 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" decoder "github.com/pingcap/tidb/util/rowDecoder" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/timeutil" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) -// adjustColumnInfoInAddColumn is used to set the correct position of column info when adding column. -// 1. The added column was append at the end of tblInfo.Columns, due to ddl state was not public then. -// It should be moved to the correct position when the ddl state to be changed to public. -// 2. The offset of column should also to be set to the right value. -func adjustColumnInfoInAddColumn(tblInfo *model.TableInfo, offset int) { - oldCols := tblInfo.Columns - newCols := make([]*model.ColumnInfo, 0, len(oldCols)) - newCols = append(newCols, oldCols[:offset]...) - newCols = append(newCols, oldCols[len(oldCols)-1]) - newCols = append(newCols, oldCols[offset:len(oldCols)-1]...) - // Adjust column offset. - offsetChanged := make(map[int]int, len(newCols)-offset-1) - for i := offset + 1; i < len(newCols); i++ { - offsetChanged[newCols[i].Offset] = i - newCols[i].Offset = i - } - newCols[offset].Offset = offset - // Update index column offset info. - // TODO: There may be some corner cases for index column offsets, we may check this later. - for _, idx := range tblInfo.Indices { - for _, col := range idx.Columns { - newOffset, ok := offsetChanged[col.Offset] - if ok { - col.Offset = newOffset - } - } - } - tblInfo.Columns = newCols -} - -// adjustColumnInfoInDropColumn is used to set the correct position of column info when dropping column. -// 1. The offset of column should to be set to the last of the columns. -// 2. The dropped column is moved to the end of tblInfo.Columns, due to it was not public any more. -func adjustColumnInfoInDropColumn(tblInfo *model.TableInfo, offset int) { - oldCols := tblInfo.Columns - // Adjust column offset. - offsetChanged := make(map[int]int, len(oldCols)-offset-1) - for i := offset + 1; i < len(oldCols); i++ { - offsetChanged[oldCols[i].Offset] = i - 1 - oldCols[i].Offset = i - 1 - } - oldCols[offset].Offset = len(oldCols) - 1 - // For expression index, we drop hidden columns and index simultaneously. - // So we need to change the offset of expression index. - offsetChanged[offset] = len(oldCols) - 1 - // Update index column offset info. - // TODO: There may be some corner cases for index column offsets, we may check this later. - for _, idx := range tblInfo.Indices { - for _, col := range idx.Columns { - newOffset, ok := offsetChanged[col.Offset] - if ok { - col.Offset = newOffset - } - } - } - newCols := make([]*model.ColumnInfo, 0, len(oldCols)) - newCols = append(newCols, oldCols[:offset]...) - newCols = append(newCols, oldCols[offset+1:]...) - newCols = append(newCols, oldCols[offset]) - tblInfo.Columns = newCols -} - -func createColumnInfo(tblInfo *model.TableInfo, colInfo *model.ColumnInfo, pos *ast.ColumnPosition) (*model.ColumnInfo, *ast.ColumnPosition, int, error) { - // Check column name duplicate. +func createColumnInfo(tblInfo *model.TableInfo, colInfo *model.ColumnInfo) *model.ColumnInfo { cols := tblInfo.Columns - offset := len(cols) - // Should initialize pos when it is nil. - if pos == nil { - pos = &ast.ColumnPosition{} - } - // Get column offset. - if pos.Tp == ast.ColumnPositionFirst { - offset = 0 - } else if pos.Tp == ast.ColumnPositionAfter { - c := model.FindColumnInfo(cols, pos.RelativeColumn.Name.L) - if c == nil { - return nil, pos, 0, infoschema.ErrColumnNotExists.GenWithStackByArgs(pos.RelativeColumn, tblInfo.Name) - } - - // Insert offset is after the mentioned column. - offset = c.Offset + 1 - } colInfo.ID = allocateColumnID(tblInfo) colInfo.State = model.StateNone // To support add column asynchronous, we should mark its offset as the last column. @@ -143,22 +62,24 @@ func createColumnInfo(tblInfo *model.TableInfo, colInfo *model.ColumnInfo, pos * // Append the column info to the end of the tblInfo.Columns. // It will reorder to the right offset in "Columns" when it state change to public. tblInfo.Columns = append(cols, colInfo) - return colInfo, pos, offset, nil + return colInfo } -func checkAddColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.ColumnInfo, *model.ColumnInfo, *ast.ColumnPosition, int, error) { +func checkAddColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.ColumnInfo, *model.ColumnInfo, + *ast.ColumnPosition, bool /* ifNotExists */, error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { - return nil, nil, nil, nil, 0, errors.Trace(err) + return nil, nil, nil, nil, false, errors.Trace(err) } col := &model.ColumnInfo{} pos := &ast.ColumnPosition{} offset := 0 - err = job.DecodeArgs(col, pos, &offset) + ifNotExists := false + err = job.DecodeArgs(col, pos, &offset, &ifNotExists) if err != nil { job.State = model.JobStateCancelled - return nil, nil, nil, nil, 0, errors.Trace(err) + return nil, nil, nil, nil, false, errors.Trace(err) } columnInfo := model.FindColumnInfo(tblInfo.Columns, col.Name.L) @@ -166,10 +87,17 @@ func checkAddColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.Colu if columnInfo.State == model.StatePublic { // We already have a column with the same column name. job.State = model.JobStateCancelled - return nil, nil, nil, nil, 0, infoschema.ErrColumnExists.GenWithStackByArgs(col.Name) + return nil, nil, nil, nil, ifNotExists, infoschema.ErrColumnExists.GenWithStackByArgs(col.Name) } } - return tblInfo, columnInfo, col, pos, offset, nil + + err = checkPosition(tblInfo, pos) + if err != nil { + job.State = model.JobStateCancelled + return nil, nil, nil, nil, false, infoschema.ErrColumnExists.GenWithStackByArgs(col.Name) + } + + return tblInfo, columnInfo, col, pos, false, nil } func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { @@ -188,21 +116,18 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) } }) - tblInfo, columnInfo, col, pos, offset, err := checkAddColumn(t, job) + tblInfo, columnInfo, col, pos, ifNotExists, err := checkAddColumn(t, job) if err != nil { + if ifNotExists && infoschema.ErrColumnExists.Equal(err) { + job.Warning = toTError(err) + job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) + return ver, nil + } return ver, errors.Trace(err) } if columnInfo == nil { - columnInfo, _, offset, err = createColumnInfo(tblInfo, col, pos) - if err != nil { - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } - logutil.BgLogger().Info("[ddl] run add column job", zap.String("job", job.String()), zap.Reflect("columnInfo", *columnInfo), zap.Int("offset", offset)) - // Set offset arg to job. - if offset != 0 { - job.Args = []interface{}{columnInfo, pos, offset} - } + columnInfo = createColumnInfo(tblInfo, col) + logutil.BgLogger().Info("[ddl] run add column job", zap.String("job", job.String()), zap.Reflect("columnInfo", *columnInfo)) if err = checkAddColumnTooManyColumns(len(tblInfo.Columns)); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -237,10 +162,15 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) } // Update the job state when all affairs done. job.SchemaState = model.StateWriteReorganization + job.MarkNonRevertible() case model.StateWriteReorganization: // reorganization -> public // Adjust table column offset. - adjustColumnInfoInAddColumn(tblInfo, offset) + offset, err := locateOffsetToMove(columnInfo.Offset, pos, tblInfo) + if err != nil { + return ver, errors.Trace(err) + } + tblInfo.MoveColumnInfo(columnInfo.Offset, offset) columnInfo.State = model.StatePublic ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) if err != nil { @@ -251,60 +181,20 @@ func onAddColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) asyncNotifyEvent(d, &ddlutil.Event{Tp: model.ActionAddColumn, TableInfo: tblInfo, ColumnInfos: []*model.ColumnInfo{columnInfo}}) default: - err = ErrInvalidDDLState.GenWithStackByArgs("column", columnInfo.State) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("column", columnInfo.State) } return ver, errors.Trace(err) } -func checkAddColumns(t *meta.Meta, job *model.Job) (*model.TableInfo, []*model.ColumnInfo, []*model.ColumnInfo, []*ast.ColumnPosition, []int, []bool, error) { - schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) - if err != nil { - return nil, nil, nil, nil, nil, nil, errors.Trace(err) - } - columns := []*model.ColumnInfo{} - positions := []*ast.ColumnPosition{} - offsets := []int{} - ifNotExists := []bool{} - err = job.DecodeArgs(&columns, &positions, &offsets, &ifNotExists) - if err != nil { - job.State = model.JobStateCancelled - return nil, nil, nil, nil, nil, nil, errors.Trace(err) - } - - columnInfos := make([]*model.ColumnInfo, 0, len(columns)) - newColumns := make([]*model.ColumnInfo, 0, len(columns)) - newPositions := make([]*ast.ColumnPosition, 0, len(columns)) - newOffsets := make([]int, 0, len(columns)) - newIfNotExists := make([]bool, 0, len(columns)) - for i, col := range columns { - columnInfo := model.FindColumnInfo(tblInfo.Columns, col.Name.L) - if columnInfo != nil { - if columnInfo.State == model.StatePublic { - // We already have a column with the same column name. - if ifNotExists[i] { - // TODO: Should return a warning. - logutil.BgLogger().Warn("[ddl] check add columns, duplicate column", zap.Stringer("col", col.Name)) - continue - } - job.State = model.JobStateCancelled - return nil, nil, nil, nil, nil, nil, infoschema.ErrColumnExists.GenWithStackByArgs(col.Name) - } - columnInfos = append(columnInfos, columnInfo) +func checkPosition(tblInfo *model.TableInfo, pos *ast.ColumnPosition) error { + if pos != nil && pos.Tp == ast.ColumnPositionAfter { + c := model.FindColumnInfo(tblInfo.Columns, pos.RelativeColumn.Name.L) + if c == nil { + return infoschema.ErrColumnNotExists.GenWithStackByArgs(pos.RelativeColumn, tblInfo.Name) } - newColumns = append(newColumns, columns[i]) - newPositions = append(newPositions, positions[i]) - newOffsets = append(newOffsets, offsets[i]) - newIfNotExists = append(newIfNotExists, ifNotExists[i]) - } - return tblInfo, columnInfos, newColumns, newPositions, newOffsets, newIfNotExists, nil -} - -func setColumnsState(columnInfos []*model.ColumnInfo, state model.SchemaState) { - for i := range columnInfos { - columnInfos[i].State = state } + return nil } func setIndicesState(indexInfos []*model.IndexInfo, state model.SchemaState) { @@ -313,239 +203,7 @@ func setIndicesState(indexInfos []*model.IndexInfo, state model.SchemaState) { } } -func onAddColumns(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { - // Handle the rolling back job. - if job.IsRollingback() { - ver, err = onDropColumns(t, job) - if err != nil { - return ver, errors.Trace(err) - } - return ver, nil - } - - failpoint.Inject("errorBeforeDecodeArgs", func(val failpoint.Value) { - if val.(bool) { - failpoint.Return(ver, errors.New("occur an error before decode args")) - } - }) - - tblInfo, columnInfos, columns, positions, offsets, ifNotExists, err := checkAddColumns(t, job) - if err != nil { - return ver, errors.Trace(err) - } - if len(columnInfos) == 0 { - if len(columns) == 0 { - job.State = model.JobStateCancelled - return ver, nil - } - for i := range columns { - columnInfo, pos, offset, err := createColumnInfo(tblInfo, columns[i], positions[i]) - if err != nil { - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } - logutil.BgLogger().Info("[ddl] run add columns job", zap.String("job", job.String()), zap.Reflect("columnInfo", *columnInfo), zap.Int("offset", offset)) - positions[i] = pos - offsets[i] = offset - if err = checkAddColumnTooManyColumns(len(tblInfo.Columns)); err != nil { - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } - columnInfos = append(columnInfos, columnInfo) - } - // Set arg to job. - job.Args = []interface{}{columnInfos, positions, offsets, ifNotExists} - } - - originalState := columnInfos[0].State - switch columnInfos[0].State { - case model.StateNone: - // none -> delete only - setColumnsState(columnInfos, model.StateDeleteOnly) - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != columnInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateDeleteOnly - case model.StateDeleteOnly: - // delete only -> write only - setColumnsState(columnInfos, model.StateWriteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateWriteOnly - case model.StateWriteOnly: - // write only -> reorganization - setColumnsState(columnInfos, model.StateWriteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateWriteReorganization - case model.StateWriteReorganization: - // reorganization -> public - // Adjust table column offsets. - oldCols := tblInfo.Columns[:len(tblInfo.Columns)-len(offsets)] - newCols := tblInfo.Columns[len(tblInfo.Columns)-len(offsets):] - tblInfo.Columns = oldCols - for i := range offsets { - // For multiple columns with after position, should adjust offsets. - // e.g. create table t(a int); - // alter table t add column b int after a, add column c int after a; - // alter table t add column a1 int after a, add column b1 int after b, add column c1 int after c; - // alter table t add column a1 int after a, add column b1 int first; - if positions[i].Tp == ast.ColumnPositionAfter { - for j := 0; j < i; j++ { - if (positions[j].Tp == ast.ColumnPositionAfter && offsets[j] < offsets[i]) || positions[j].Tp == ast.ColumnPositionFirst { - offsets[i]++ - } - } - } - tblInfo.Columns = append(tblInfo.Columns, newCols[i]) - adjustColumnInfoInAddColumn(tblInfo, offsets[i]) - } - setColumnsState(columnInfos, model.StatePublic) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - // Finish this job. - job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) - asyncNotifyEvent(d, &ddlutil.Event{Tp: model.ActionAddColumns, TableInfo: tblInfo, ColumnInfos: columnInfos}) - default: - err = ErrInvalidDDLState.GenWithStackByArgs("column", columnInfos[0].State) - } - - return ver, errors.Trace(err) -} - -func onDropColumns(t *meta.Meta, job *model.Job) (ver int64, _ error) { - tblInfo, colInfos, delCount, idxInfos, err := checkDropColumns(t, job) - if err != nil { - return ver, errors.Trace(err) - } - if len(colInfos) == 0 { - job.State = model.JobStateCancelled - return ver, nil - } - - originalState := colInfos[0].State - switch colInfos[0].State { - case model.StatePublic: - // public -> write only - setColumnsState(colInfos, model.StateWriteOnly) - setIndicesState(idxInfos, model.StateWriteOnly) - for _, colInfo := range colInfos { - err = checkDropColumnForStatePublic(tblInfo, colInfo) - if err != nil { - return ver, errors.Trace(err) - } - } - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != colInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateWriteOnly - case model.StateWriteOnly: - // write only -> delete only - setColumnsState(colInfos, model.StateDeleteOnly) - setIndicesState(idxInfos, model.StateDeleteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateDeleteOnly - case model.StateDeleteOnly: - // delete only -> reorganization - setColumnsState(colInfos, model.StateDeleteReorganization) - setIndicesState(idxInfos, model.StateDeleteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateDeleteReorganization - case model.StateDeleteReorganization: - // reorganization -> absent - // All reorganization jobs are done, drop this column. - if len(idxInfos) > 0 { - newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) - for _, idx := range tblInfo.Indices { - if !indexInfoContains(idx.ID, idxInfos) { - newIndices = append(newIndices, idx) - } - } - tblInfo.Indices = newIndices - } - - indexIDs := indexInfosToIDList(idxInfos) - tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-delCount] - setColumnsState(colInfos, model.StateNone) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - - // Finish this job. - if job.IsRollingback() { - job.FinishTableJob(model.JobStateRollbackDone, model.StateNone, ver, tblInfo) - } else { - job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) - job.Args = append(job.Args, indexIDs, getPartitionIDs(tblInfo)) - } - default: - err = errInvalidDDLJob.GenWithStackByArgs("table", tblInfo.State) - } - return ver, errors.Trace(err) -} - -func checkDropColumns(t *meta.Meta, job *model.Job) (*model.TableInfo, []*model.ColumnInfo, int, []*model.IndexInfo, error) { - schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) - if err != nil { - return nil, nil, 0, nil, errors.Trace(err) - } - - var colNames []model.CIStr - var ifExists []bool - err = job.DecodeArgs(&colNames, &ifExists) - if err != nil { - job.State = model.JobStateCancelled - return nil, nil, 0, nil, errors.Trace(err) - } - - newColNames := make([]model.CIStr, 0, len(colNames)) - colInfos := make([]*model.ColumnInfo, 0, len(colNames)) - newIfExists := make([]bool, 0, len(colNames)) - indexInfos := make([]*model.IndexInfo, 0) - for i, colName := range colNames { - colInfo := model.FindColumnInfo(tblInfo.Columns, colName.L) - if colInfo == nil || colInfo.Hidden { - if ifExists[i] { - // TODO: Should return a warning. - logutil.BgLogger().Warn(fmt.Sprintf("column %s doesn't exist", colName)) - continue - } - job.State = model.JobStateCancelled - return nil, nil, 0, nil, ErrCantDropFieldOrKey.GenWithStack("column %s doesn't exist", colName) - } - if err = isDroppableColumn(job.MultiSchemaInfo != nil, tblInfo, colName); err != nil { - job.State = model.JobStateCancelled - return nil, nil, 0, nil, errors.Trace(err) - } - newColNames = append(newColNames, colName) - newIfExists = append(newIfExists, ifExists[i]) - colInfos = append(colInfos, colInfo) - idxInfos := listIndicesWithColumn(colName.L, tblInfo.Indices) - indexInfos = append(indexInfos, idxInfos...) - } - job.Args = []interface{}{newColNames, newIfExists} - return tblInfo, colInfos, len(colInfos), indexInfos, nil -} - func checkDropColumnForStatePublic(tblInfo *model.TableInfo, colInfo *model.ColumnInfo) (err error) { - // Set this column's offset to the last and reset all following columns' offsets. - adjustColumnInfoInDropColumn(tblInfo, colInfo.Offset) // When the dropping column has not-null flag and it hasn't the default value, we can backfill the column value like "add column". // NOTE: If the state of StateWriteOnly can be rollbacked, we'd better reconsider the original default value. // And we need consider the column without not-null flag. @@ -556,7 +214,7 @@ func checkDropColumnForStatePublic(tblInfo *model.TableInfo, colInfo *model.Colu // But currently will be ok, because we can't cancel the drop column job when the job is running, // so the column will be dropped succeed and client will never see the wrong default value of the dropped column. // More info about this problem, see PR#9115. - originDefVal, err := generateOriginDefaultValue(colInfo) + originDefVal, err := generateOriginDefaultValue(colInfo, nil) if err != nil { return err } @@ -566,10 +224,21 @@ func checkDropColumnForStatePublic(tblInfo *model.TableInfo, colInfo *model.Colu } func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { - tblInfo, colInfo, idxInfos, err := checkDropColumn(t, job) + tblInfo, colInfo, idxInfos, ifExists, err := checkDropColumn(t, job) if err != nil { + if ifExists && dbterror.ErrCantDropFieldOrKey.Equal(err) { + job.Warning = toTError(err) + job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) + return ver, nil + } return ver, errors.Trace(err) } + if job.MultiSchemaInfo != nil && job.MultiSchemaInfo.Revertible { + job.MarkNonRevertible() + job.SchemaState = colInfo.State + // Store the mark and enter the next DDL handling loop. + return updateVersionAndTableInfoWithCheck(t, job, tblInfo, false) + } originalState := colInfo.State switch colInfo.State { @@ -577,6 +246,7 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { // public -> write only colInfo.State = model.StateWriteOnly setIndicesState(idxInfos, model.StateWriteOnly) + tblInfo.MoveColumnInfo(colInfo.Offset, len(tblInfo.Columns)-1) err = checkDropColumnForStatePublic(tblInfo, colInfo) if err != nil { return ver, errors.Trace(err) @@ -589,16 +259,25 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { case model.StateWriteOnly: // write only -> delete only colInfo.State = model.StateDeleteOnly - setIndicesState(idxInfos, model.StateDeleteOnly) + if len(idxInfos) > 0 { + newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) + for _, idx := range tblInfo.Indices { + if !indexInfoContains(idx.ID, idxInfos) { + newIndices = append(newIndices, idx) + } + } + tblInfo.Indices = newIndices + } + tblInfo.MoveColumnInfo(colInfo.Offset, len(tblInfo.Columns)-1) ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) } + job.Args = append(job.Args, indexInfosToIDList(idxInfos)) job.SchemaState = model.StateDeleteOnly case model.StateDeleteOnly: // delete only -> reorganization colInfo.State = model.StateDeleteReorganization - setIndicesState(idxInfos, model.StateDeleteReorganization) ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) if err != nil { return ver, errors.Trace(err) @@ -607,17 +286,7 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { case model.StateDeleteReorganization: // reorganization -> absent // All reorganization jobs are done, drop this column. - if len(idxInfos) > 0 { - newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) - for _, idx := range tblInfo.Indices { - if !indexInfoContains(idx.ID, idxInfos) { - newIndices = append(newIndices, idx) - } - } - tblInfo.Indices = newIndices - } - - indexIDs := indexInfosToIDList(idxInfos) + tblInfo.MoveColumnInfo(colInfo.Offset, len(tblInfo.Columns)-1) tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] colInfo.State = model.StateNone ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != colInfo.State) @@ -631,36 +300,39 @@ func onDropColumn(t *meta.Meta, job *model.Job) (ver int64, _ error) { } else { // We should set related index IDs for job job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) - job.Args = append(job.Args, indexIDs, getPartitionIDs(tblInfo)) + job.Args = append(job.Args, getPartitionIDs(tblInfo)) } default: - err = errInvalidDDLJob.GenWithStackByArgs("table", tblInfo.State) + err = dbterror.ErrInvalidDDLJob.GenWithStackByArgs("table", tblInfo.State) } return ver, errors.Trace(err) } -func checkDropColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.ColumnInfo, []*model.IndexInfo, error) { +func checkDropColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.ColumnInfo, []*model.IndexInfo, bool /* ifExists */, error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { - return nil, nil, nil, errors.Trace(err) + return nil, nil, nil, false, errors.Trace(err) } var colName model.CIStr - err = job.DecodeArgs(&colName) + var ifExists bool + // indexIds is used to make sure we don't truncate args when decoding the rawArgs. + var indexIds []int64 + err = job.DecodeArgs(&colName, &ifExists, &indexIds) if err != nil { job.State = model.JobStateCancelled - return nil, nil, nil, errors.Trace(err) + return nil, nil, nil, false, errors.Trace(err) } colInfo := model.FindColumnInfo(tblInfo.Columns, colName.L) if colInfo == nil || colInfo.Hidden { job.State = model.JobStateCancelled - return nil, nil, nil, ErrCantDropFieldOrKey.GenWithStack("column %s doesn't exist", colName) + return nil, nil, nil, ifExists, dbterror.ErrCantDropFieldOrKey.GenWithStack("column %s doesn't exist", colName) } if err = isDroppableColumn(job.MultiSchemaInfo != nil, tblInfo, colName); err != nil { job.State = model.JobStateCancelled - return nil, nil, nil, errors.Trace(err) + return nil, nil, nil, false, errors.Trace(err) } idxInfos := listIndicesWithColumn(colName.L, tblInfo.Indices) if len(idxInfos) > 0 { @@ -668,11 +340,11 @@ func checkDropColumn(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.Col err = checkDropIndexOnAutoIncrementColumn(tblInfo, idxInfo) if err != nil { job.State = model.JobStateCancelled - return nil, nil, nil, err + return nil, nil, nil, false, err } } } - return tblInfo, colInfo, idxInfos, nil + return tblInfo, colInfo, idxInfos, false, nil } func onSetDefaultValue(t *meta.Meta, job *model.Job) (ver int64, _ error) { @@ -736,23 +408,15 @@ func needChangeColumnData(oldCol, newCol *model.ColumnInfo) bool { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: return needTruncationOrToggleSignForInteger() } - case mysql.TypeFloat, mysql.TypeDouble: - switch newCol.Tp { - case mysql.TypeFloat, mysql.TypeDouble: - return needTruncationOrToggleSign() - } + // conversion between float and double needs reorganization, see issue #31372 } return true } -// Column type conversion between varchar to char need reorganization because -// 1. varchar -> char: char type is stored with the padding removed. All the indexes need to be rewritten. -// 2. char -> varchar: the index value encoding of secondary index on clustered primary key tables is different. -// These secondary indexes need to be rewritten. +// TODO: it is used for plugins. so change plugin's using and remove it. func convertBetweenCharAndVarchar(oldCol, newCol byte) bool { - return (types.IsTypeVarchar(oldCol) && newCol == mysql.TypeString) || - (oldCol == mysql.TypeString && types.IsTypeVarchar(newCol) && collate.NewCollationEnabled()) + return types.ConvertBetweenCharAndVarchar(oldCol, newCol) } func isElemsChangedToModifyColumn(oldElems, newElems []string) bool { @@ -768,7 +432,7 @@ func isElemsChangedToModifyColumn(oldElems, newElems []string) bool { return false } -type modifyColumnJobParameter struct { +type modifyingColInfo struct { newCol *model.ColumnInfo oldColName *model.CIStr modifyColumnTp byte @@ -776,33 +440,35 @@ type modifyColumnJobParameter struct { changingCol *model.ColumnInfo changingIdxs []*model.IndexInfo pos *ast.ColumnPosition + removedIdxs []int64 } -func getModifyColumnInfo(t *meta.Meta, job *model.Job) (*model.DBInfo, *model.TableInfo, *model.ColumnInfo, *modifyColumnJobParameter, error) { - jobParam := &modifyColumnJobParameter{pos: &ast.ColumnPosition{}} - err := job.DecodeArgs(&jobParam.newCol, &jobParam.oldColName, jobParam.pos, &jobParam.modifyColumnTp, &jobParam.updatedAutoRandomBits, &jobParam.changingCol, &jobParam.changingIdxs) +func getModifyColumnInfo(t *meta.Meta, job *model.Job) (*model.DBInfo, *model.TableInfo, *model.ColumnInfo, *modifyingColInfo, error) { + modifyInfo := &modifyingColInfo{pos: &ast.ColumnPosition{}} + err := job.DecodeArgs(&modifyInfo.newCol, &modifyInfo.oldColName, modifyInfo.pos, &modifyInfo.modifyColumnTp, + &modifyInfo.updatedAutoRandomBits, &modifyInfo.changingCol, &modifyInfo.changingIdxs, &modifyInfo.removedIdxs) if err != nil { job.State = model.JobStateCancelled - return nil, nil, nil, jobParam, errors.Trace(err) + return nil, nil, nil, modifyInfo, errors.Trace(err) } dbInfo, err := checkSchemaExistAndCancelNotExistJob(t, job) if err != nil { - return nil, nil, nil, jobParam, errors.Trace(err) + return nil, nil, nil, modifyInfo, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { - return nil, nil, nil, jobParam, errors.Trace(err) + return nil, nil, nil, modifyInfo, errors.Trace(err) } - oldCol := model.FindColumnInfo(tblInfo.Columns, jobParam.oldColName.L) + oldCol := model.FindColumnInfo(tblInfo.Columns, modifyInfo.oldColName.L) if oldCol == nil || oldCol.State != model.StatePublic { job.State = model.JobStateCancelled - return nil, nil, nil, jobParam, errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(*(jobParam.oldColName), tblInfo.Name)) + return nil, nil, nil, modifyInfo, errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(*(modifyInfo.oldColName), tblInfo.Name)) } - return dbInfo, tblInfo, oldCol, jobParam, errors.Trace(err) + return dbInfo, tblInfo, oldCol, modifyInfo, errors.Trace(err) } // getOriginDefaultValueForModifyColumn gets the original default value for modifying column. @@ -830,7 +496,7 @@ func getOriginDefaultValueForModifyColumn(d *ddlCtx, changingCol, oldCol *model. } } if originDefVal == nil { - originDefVal, err = generateOriginDefaultValue(changingCol) + originDefVal, err = generateOriginDefaultValue(changingCol, nil) if err != nil { return nil, errors.Trace(err) } @@ -839,139 +505,182 @@ func getOriginDefaultValueForModifyColumn(d *ddlCtx, changingCol, oldCol *model. } func (w *worker) onModifyColumn(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { - dbInfo, tblInfo, oldCol, jobParam, err := getModifyColumnInfo(t, job) + dbInfo, tblInfo, oldCol, modifyInfo, err := getModifyColumnInfo(t, job) if err != nil { return ver, err } if job.IsRollingback() { // For those column-type-change jobs which don't reorg the data. - if !needChangeColumnData(oldCol, jobParam.newCol) { - return rollbackModifyColumnJob(t, tblInfo, job, oldCol, jobParam.modifyColumnTp) + if !needChangeColumnData(oldCol, modifyInfo.newCol) { + return rollbackModifyColumnJob(t, tblInfo, job, modifyInfo.newCol, oldCol, modifyInfo.modifyColumnTp) } // For those column-type-change jobs which reorg the data. - return rollbackModifyColumnJobWithData(t, tblInfo, job, oldCol, jobParam) + return rollbackModifyColumnJobWithData(t, tblInfo, job, oldCol, modifyInfo) } // If we want to rename the column name, we need to check whether it already exists. - if jobParam.newCol.Name.L != jobParam.oldColName.L { - c := model.FindColumnInfo(tblInfo.Columns, jobParam.newCol.Name.L) + if modifyInfo.newCol.Name.L != modifyInfo.oldColName.L { + c := model.FindColumnInfo(tblInfo.Columns, modifyInfo.newCol.Name.L) if c != nil { job.State = model.JobStateCancelled - return ver, errors.Trace(infoschema.ErrColumnExists.GenWithStackByArgs(jobParam.newCol.Name)) + return ver, errors.Trace(infoschema.ErrColumnExists.GenWithStackByArgs(modifyInfo.newCol.Name)) } } failpoint.Inject("uninitializedOffsetAndState", func(val failpoint.Value) { if val.(bool) { - if jobParam.newCol.State != model.StatePublic { + if modifyInfo.newCol.State != model.StatePublic { failpoint.Return(ver, errors.New("the column state is wrong")) } } }) - err = checkAndApplyAutoRandomBits(d, t, dbInfo, tblInfo, oldCol, jobParam.newCol, jobParam.updatedAutoRandomBits) + err = checkAndApplyAutoRandomBits(d, t, dbInfo, tblInfo, oldCol, modifyInfo.newCol, modifyInfo.updatedAutoRandomBits) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } - if !needChangeColumnData(oldCol, jobParam.newCol) { - return w.doModifyColumn(d, t, job, dbInfo, tblInfo, jobParam.newCol, oldCol, jobParam.pos) + if !needChangeColumnData(oldCol, modifyInfo.newCol) { + return w.doModifyColumn(d, t, job, dbInfo, tblInfo, modifyInfo.newCol, oldCol, modifyInfo.pos) } - if err = isGeneratedRelatedColumn(tblInfo, jobParam.newCol, oldCol); err != nil { + if err = isGeneratedRelatedColumn(tblInfo, modifyInfo.newCol, oldCol); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } - if jobParam.changingCol == nil { - changingColPos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} + changingCol := modifyInfo.changingCol + if changingCol == nil { newColName := model.NewCIStr(genChangingColumnUniqueName(tblInfo, oldCol)) if mysql.HasPriKeyFlag(oldCol.Flag) { job.State = model.JobStateCancelled msg := "this column has primary key flag" - return ver, errUnsupportedModifyColumn.GenWithStackByArgs(msg) + return ver, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) } - jobParam.changingCol = jobParam.newCol.Clone() - jobParam.changingCol.Name = newColName - jobParam.changingCol.ChangeStateInfo = &model.ChangeStateInfo{DependencyColumnOffset: oldCol.Offset} - originDefVal, err := getOriginDefaultValueForModifyColumn(d, jobParam.changingCol, oldCol) + changingCol = modifyInfo.newCol.Clone() + changingCol.Name = newColName + changingCol.ChangeStateInfo = &model.ChangeStateInfo{DependencyColumnOffset: oldCol.Offset} + + originDefVal, err := getOriginDefaultValueForModifyColumn(d, changingCol, oldCol) if err != nil { return ver, errors.Trace(err) } - if err = jobParam.changingCol.SetOriginDefaultValue(originDefVal); err != nil { - return ver, errors.Trace(err) - } - - _, _, _, err = createColumnInfo(tblInfo, jobParam.changingCol, changingColPos) - if err != nil { - job.State = model.JobStateCancelled + if err = changingCol.SetOriginDefaultValue(originDefVal); err != nil { return ver, errors.Trace(err) } - idxInfos, offsets := findIndexesByColName(tblInfo.Indices, oldCol.Name.L) - jobParam.changingIdxs = make([]*model.IndexInfo, 0, len(idxInfos)) - for i, idxInfo := range idxInfos { - newIdxInfo := idxInfo.Clone() - newIdxInfo.Name = model.NewCIStr(genChangingIndexUniqueName(tblInfo, idxInfo)) - newIdxInfo.ID = allocateIndexID(tblInfo) - newIdxChangingCol := newIdxInfo.Columns[offsets[i]] - newIdxChangingCol.Name = newColName - newIdxChangingCol.Offset = jobParam.changingCol.Offset - canPrefix := types.IsTypePrefixable(jobParam.changingCol.Tp) - if !canPrefix || (canPrefix && jobParam.changingCol.Flen < newIdxChangingCol.Length) { - newIdxChangingCol.Length = types.UnspecifiedLength + createColumnInfo(tblInfo, changingCol) + indexesToChange := findIndexesByColName(tblInfo, oldCol.Name) + var indexesToRemove []int64 + for _, info := range indexesToChange { + newIdxID := allocateIndexID(tblInfo) + if info.isModifying { + newIdxName := info.indexInfo.Name + newIdxInfo := copyIndexInfoForModifyColumn(info.indexInfo, newIdxID, newIdxName, info.colOffset, changingCol) + indexesToRemove = append(indexesToRemove, info.indexInfo.ID) + tblInfo.Indices[info.idxOffset] = newIdxInfo + } else { + newIdxName := model.NewCIStr(genChangingIndexUniqueName(tblInfo, info.indexInfo)) + newIdxInfo := copyIndexInfoForModifyColumn(info.indexInfo, newIdxID, newIdxName, info.colOffset, changingCol) + tblInfo.Indices = append(tblInfo.Indices, newIdxInfo) } - jobParam.changingIdxs = append(jobParam.changingIdxs, newIdxInfo) } - tblInfo.Indices = append(tblInfo.Indices, jobParam.changingIdxs...) + modifyInfo.removedIdxs = indexesToRemove } else { - tblInfo.Columns[len(tblInfo.Columns)-1] = jobParam.changingCol - copy(tblInfo.Indices[len(tblInfo.Indices)-len(jobParam.changingIdxs):], jobParam.changingIdxs) + changingCol = model.FindColumnInfoByID(tblInfo.Columns, modifyInfo.changingCol.ID) + if changingCol == nil { + logutil.BgLogger().Error("[ddl] the changing column has been removed", zap.Error(err)) + job.State = model.JobStateCancelled + return ver, errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(oldCol.Name, tblInfo.Name)) + } } - return w.doModifyColumnTypeWithData(d, t, job, dbInfo, tblInfo, jobParam.changingCol, oldCol, jobParam.newCol.Name, jobParam.pos, jobParam.changingIdxs) + return w.doModifyColumnTypeWithData(d, t, job, dbInfo, tblInfo, changingCol, oldCol, modifyInfo.newCol.Name, modifyInfo.pos, modifyInfo.removedIdxs) +} + +func copyIndexInfoForModifyColumn(idxInfo *model.IndexInfo, newIndexID int64, newIndexName model.CIStr, + colOffset int, changingCol *model.ColumnInfo) *model.IndexInfo { + newIdxInfo := idxInfo.Clone() + newIdxInfo.Name = newIndexName + newIdxInfo.ID = newIndexID + newIdxChangingCol := newIdxInfo.Columns[colOffset] + newIdxChangingCol.Name = changingCol.Name + newIdxChangingCol.Offset = changingCol.Offset + canPrefix := types.IsTypePrefixable(changingCol.Tp) + if !canPrefix || (canPrefix && changingCol.Flen < newIdxChangingCol.Length) { + newIdxChangingCol.Length = types.UnspecifiedLength + } + return newIdxInfo } // rollbackModifyColumnJobWithData is used to rollback modify-column job which need to reorg the data. -func rollbackModifyColumnJobWithData(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, oldCol *model.ColumnInfo, jobParam *modifyColumnJobParameter) (ver int64, err error) { +func rollbackModifyColumnJobWithData(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, oldCol *model.ColumnInfo, modifyInfo *modifyingColInfo) (ver int64, err error) { // If the not-null change is included, we should clean the flag info in oldCol. - if jobParam.modifyColumnTp == mysql.TypeNull { + if modifyInfo.modifyColumnTp == mysql.TypeNull { // Reset NotNullFlag flag. tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.NotNullFlag // Reset PreventNullInsertFlag flag. tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.PreventNullInsertFlag } - if jobParam.changingCol != nil { - // changingCol isn't nil means the job has been in the mid state. These appended changingCol and changingIndex should + var changingIdxIDs []int64 + if modifyInfo.changingCol != nil { + changingIdxIDs = getRelatedIndexIDs(tblInfo, modifyInfo.changingCol.ID) + // The job is in the middle state. The appended changingCol and changingIndex should // be removed from the tableInfo as well. - tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] - tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-len(jobParam.changingIdxs)] + removeChangingColAndIdxs(tblInfo, modifyInfo.changingCol.ID) } ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) } job.FinishTableJob(model.JobStateRollbackDone, model.StateNone, ver, tblInfo) - // Refactor the job args to add the abandoned temporary index ids into delete range table. - idxIDs := make([]int64, 0, len(jobParam.changingIdxs)) - for _, idx := range jobParam.changingIdxs { - idxIDs = append(idxIDs, idx.ID) - } - job.Args = []interface{}{idxIDs, getPartitionIDs(tblInfo)} + // Reconstruct the job args to add the abandoned temporary index ids into delete range table. + job.Args = []interface{}{changingIdxIDs, getPartitionIDs(tblInfo)} return ver, nil } +func removeChangingColAndIdxs(tblInfo *model.TableInfo, changingColID int64) { + var colName string + for i, c := range tblInfo.Columns { + if c.ID == changingColID { + tblInfo.MoveColumnInfo(i, len(tblInfo.Columns)-1) + colName = c.Name.L + break + } + } + if len(colName) == 0 { + return + } + tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] + for i, idx := range tblInfo.Indices { + for _, idxCol := range idx.Columns { + if colName == idxCol.Name.L { + tblInfo.Indices[i] = nil + break + } + } + } + tmp := tblInfo.Indices[:0] + for _, idx := range tblInfo.Indices { + if idx != nil { + tmp = append(tmp, idx) + } + } + tblInfo.Indices = tmp +} + func (w *worker) doModifyColumnTypeWithData( d *ddlCtx, t *meta.Meta, job *model.Job, dbInfo *model.DBInfo, tblInfo *model.TableInfo, changingCol, oldCol *model.ColumnInfo, - colName model.CIStr, pos *ast.ColumnPosition, changingIdxs []*model.IndexInfo) (ver int64, _ error) { + colName model.CIStr, pos *ast.ColumnPosition, rmIdxIDs []int64) (ver int64, _ error) { var err error originalState := changingCol.State targetCol := changingCol.Clone() targetCol.Name = colName + changingIdxs := getRelatedIndexInfos(tblInfo, changingCol.ID) switch changingCol.State { case model.StateNone: // Column from null to not null. @@ -979,14 +688,14 @@ func (w *worker) doModifyColumnTypeWithData( // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.Tp != changingCol.Tp) if err != nil { - if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) { + if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback } return ver, err } } // none -> delete only - updateChangingInfo(changingCol, changingIdxs, model.StateDeleteOnly) + updateChangingObjState(changingCol, changingIdxs, model.StateDeleteOnly) failpoint.Inject("mockInsertValueAfterCheckNull", func(val failpoint.Value) { if valStr, ok := val.(string); ok { var ctx sessionctx.Context @@ -996,12 +705,7 @@ func (w *worker) doModifyColumnTypeWithData( } defer w.sessPool.put(ctx) - stmt, err := ctx.(sqlexec.RestrictedSQLExecutor).ParseWithParams(context.Background(), valStr) - if err != nil { - job.State = model.JobStateCancelled - failpoint.Return(ver, err) - } - _, _, err = ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(context.Background(), stmt) + _, _, err = ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(context.Background(), nil, valStr) if err != nil { job.State = model.JobStateCancelled failpoint.Return(ver, err) @@ -1016,21 +720,21 @@ func (w *worker) doModifyColumnTypeWithData( // be updated in `updateDDLJob` even if it meets an error in `updateVersionAndTableInfoWithCheck`. job.SchemaState = model.StateDeleteOnly metrics.GetBackfillProgressByLabel(metrics.LblModifyColumn).Set(0) - job.Args = append(job.Args, changingCol, changingIdxs) + job.Args = append(job.Args, changingCol, changingIdxs, rmIdxIDs) case model.StateDeleteOnly: // Column from null to not null. if !mysql.HasNotNullFlag(oldCol.Flag) && mysql.HasNotNullFlag(changingCol.Flag) { // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, targetCol, oldCol.Tp != changingCol.Tp) if err != nil { - if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) { + if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback } return ver, err } } // delete only -> write only - updateChangingInfo(changingCol, changingIdxs, model.StateWriteOnly) + updateChangingObjState(changingCol, changingIdxs, model.StateWriteOnly) ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) @@ -1038,7 +742,7 @@ func (w *worker) doModifyColumnTypeWithData( job.SchemaState = model.StateWriteOnly case model.StateWriteOnly: // write only -> reorganization - updateChangingInfo(changingCol, changingIdxs, model.StateWriteReorganization) + updateChangingObjState(changingCol, changingIdxs, model.StateWriteReorganization) ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) if err != nil { return ver, errors.Trace(err) @@ -1052,97 +756,258 @@ func (w *worker) doModifyColumnTypeWithData( return ver, errors.Trace(err) } - reorgInfo, err := getReorgInfo(d, t, job, tbl, BuildElements(changingCol, changingIdxs)) - if err != nil || reorgInfo.first { - // If we run reorg firstly, we should update the job snapshot version - // and then run the reorg next time. + var done bool + done, ver, err = doReorgWorkForModifyColumnMultiSchema(w, d, t, job, tbl, oldCol, changingCol, changingIdxs) + if !done { + return ver, err + } + + rmIdxIDs = append(getRelatedIndexIDs(tblInfo, oldCol.ID), rmIdxIDs...) + + err = adjustTableInfoAfterModifyColumnWithData(tblInfo, pos, oldCol, changingCol, colName, changingIdxs) + if err != nil { + job.State = model.JobStateRollingback return ver, errors.Trace(err) } - // Inject a failpoint so that we can pause here and do verification on other components. - // With a failpoint-enabled version of TiDB, you can trigger this failpoint by the following command: - // enable: curl -X PUT -d "pause" "http://127.0.0.1:10080/fail/github.com/pingcap/tidb/ddl/mockDelayInModifyColumnTypeWithData". - // disable: curl -X DELETE "http://127.0.0.1:10080/fail/github.com/pingcap/tidb/ddl/mockDelayInModifyColumnTypeWithData" - failpoint.Inject("mockDelayInModifyColumnTypeWithData", func() {}) - err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (addIndexErr error) { - defer util.Recover(metrics.LabelDDL, "onModifyColumn", - func() { - addIndexErr = errCancelledDDLJob.GenWithStack("modify table `%v` column `%v` panic", tblInfo.Name, oldCol.Name) - }, false) - // Use old column name to generate less confusing error messages. - changingColCpy := changingCol.Clone() - changingColCpy.Name = oldCol.Name - return w.updateColumnAndIndexes(tbl, oldCol, changingColCpy, changingIdxs, reorgInfo) - }) + updateChangingObjState(changingCol, changingIdxs, model.StatePublic) + ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) if err != nil { - if errWaitReorgTimeout.Equal(err) { - // If timeout, we should return, check for the owner and re-wait job done. - return ver, nil - } - if kv.IsTxnRetryableError(err) { - // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. - w.reorgCtx.cleanNotifyReorgCancel() - return ver, errors.Trace(err) - } - if err1 := t.RemoveDDLReorgHandle(job, reorgInfo.elements); err1 != nil { - logutil.BgLogger().Warn("[ddl] run modify column job failed, RemoveDDLReorgHandle failed, can't convert job to rollback", - zap.String("job", job.String()), zap.Error(err1)) - } - logutil.BgLogger().Warn("[ddl] run modify column job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err)) + return ver, errors.Trace(err) + } + + // Finish this job. + job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) + // Refactor the job args to add the old index ids into delete range table. + job.Args = []interface{}{rmIdxIDs, getPartitionIDs(tblInfo)} + asyncNotifyEvent(d, &ddlutil.Event{Tp: model.ActionModifyColumn, TableInfo: tblInfo, ColumnInfos: []*model.ColumnInfo{changingCol}}) + default: + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("column", changingCol.State) + } + + return ver, errors.Trace(err) +} + +func doReorgWorkForModifyColumnMultiSchema(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, + oldCol, changingCol *model.ColumnInfo, changingIdxs []*model.IndexInfo) (done bool, ver int64, err error) { + if job.MultiSchemaInfo != nil { + if job.IsCancelling() { + logutil.BgLogger().Warn("[ddl] run modify column job failed, convert job to rollback", + zap.String("job", job.String()), zap.Error(err)) + w.reorgCtx.cleanNotifyReorgCancel() job.State = model.JobStateRollingback + return false, ver, err + } + if job.MultiSchemaInfo.Revertible { + done, ver, err = doReorgWorkForModifyColumn(w, d, t, job, tbl, oldCol, changingCol, changingIdxs) + if done { + job.MarkNonRevertible() + done = false // Wait for the other sub jobs. + } + return done, ver, err + } + // Non-revertible means all the sub jobs finished. + return true, ver, err + } + return doReorgWorkForModifyColumn(w, d, t, job, tbl, oldCol, changingCol, changingIdxs) +} + +func doReorgWorkForModifyColumn(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, + oldCol, changingCol *model.ColumnInfo, changingIdxs []*model.IndexInfo) (done bool, ver int64, err error) { + reorgInfo, err := getReorgInfo(w.JobContext, d, t, job, tbl, BuildElements(changingCol, changingIdxs)) + if err != nil || reorgInfo.first { + // If we run reorg firstly, we should update the job snapshot version + // and then run the reorg next time. + return false, ver, errors.Trace(err) + } + + // Inject a failpoint so that we can pause here and do verification on other components. + // With a failpoint-enabled version of TiDB, you can trigger this failpoint by the following command: + // enable: curl -X PUT -d "pause" "http://127.0.0.1:10080/fail/github.com/pingcap/tidb/ddl/mockDelayInModifyColumnTypeWithData". + // disable: curl -X DELETE "http://127.0.0.1:10080/fail/github.com/pingcap/tidb/ddl/mockDelayInModifyColumnTypeWithData" + failpoint.Inject("mockDelayInModifyColumnTypeWithData", func() {}) + err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (addIndexErr error) { + defer util.Recover(metrics.LabelDDL, "onModifyColumn", + func() { + addIndexErr = dbterror.ErrCancelledDDLJob.GenWithStack("modify table `%v` column `%v` panic", tbl.Meta().Name, oldCol.Name) + }, false) + // Use old column name to generate less confusing error messages. + changingColCpy := changingCol.Clone() + changingColCpy.Name = oldCol.Name + return w.updateColumnAndIndexes(tbl, oldCol, changingColCpy, changingIdxs, reorgInfo) + }) + if err != nil { + if dbterror.ErrWaitReorgTimeout.Equal(err) { + // If timeout, we should return, check for the owner and re-wait job done. + return false, ver, nil + } + if kv.IsTxnRetryableError(err) { // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. w.reorgCtx.cleanNotifyReorgCancel() - return ver, errors.Trace(err) + return false, ver, errors.Trace(err) + } + if err1 := t.RemoveDDLReorgHandle(job, reorgInfo.elements); err1 != nil { + logutil.BgLogger().Warn("[ddl] run modify column job failed, RemoveDDLReorgHandle failed, can't convert job to rollback", + zap.String("job", job.String()), zap.Error(err1)) } + logutil.BgLogger().Warn("[ddl] run modify column job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err)) + job.State = model.JobStateRollingback // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. w.reorgCtx.cleanNotifyReorgCancel() + return false, ver, errors.Trace(err) + } + // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. + w.reorgCtx.cleanNotifyReorgCancel() + return true, ver, nil +} - // Remove the old column and indexes. Update the relative column name and index names. - oldIdxIDs := make([]int64, 0, len(changingIdxs)) - tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] +func adjustTableInfoAfterModifyColumnWithData(tblInfo *model.TableInfo, pos *ast.ColumnPosition, + oldCol, changingCol *model.ColumnInfo, newName model.CIStr, changingIdxs []*model.IndexInfo) (err error) { + if pos != nil && pos.RelativeColumn != nil && oldCol.Name.L == pos.RelativeColumn.Name.L { + // For cases like `modify column b after b`, it should report this error. + return errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(oldCol.Name, tblInfo.Name)) + } + internalColName := changingCol.Name + changingCol = replaceOldColumn(tblInfo, oldCol, changingCol, newName) + if len(changingIdxs) > 0 { + indexesToRemove := updateNewIndexesCols(changingIdxs, internalColName, newName, changingCol.Offset) + replaceOldIndexes(tblInfo, indexesToRemove) + } + // Move the new column to a correct offset. + destOffset, err := locateOffsetToMove(changingCol.Offset, pos, tblInfo) + if err != nil { + return errors.Trace(err) + } + tblInfo.MoveColumnInfo(changingCol.Offset, destOffset) + return nil +} + +func replaceOldColumn(tblInfo *model.TableInfo, oldCol, changingCol *model.ColumnInfo, + newName model.CIStr) *model.ColumnInfo { + // Replace the old column. + tblInfo.MoveColumnInfo(changingCol.Offset, len(tblInfo.Columns)-1) + changingCol = updateChangingCol(changingCol, newName, oldCol.Offset) + tblInfo.Columns[oldCol.Offset] = changingCol + tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-1] + return changingCol +} + +func replaceOldIndexes(tblInfo *model.TableInfo, changingIdxs []*model.IndexInfo) { + // Remove the changing indexes. + for i, idx := range tblInfo.Indices { for _, cIdx := range changingIdxs { - idxName := getChangingIndexOriginName(cIdx) - for i, idx := range tblInfo.Indices { - if strings.EqualFold(idxName, idx.Name.O) { - cIdx.Name = model.NewCIStr(idxName) - tblInfo.Indices[i] = cIdx - oldIdxIDs = append(oldIdxIDs, idx.ID) - break + if cIdx.ID == idx.ID { + tblInfo.Indices[i] = nil + break + } + } + } + tmp := tblInfo.Indices[:0] + for _, idx := range tblInfo.Indices { + if idx != nil { + tmp = append(tmp, idx) + } + } + tblInfo.Indices = tmp + // Replace the old indexes with changing indexes. + for _, cIdx := range changingIdxs { + // The index name should be changed from '_Idx$_name' to 'name'. + idxName := getChangingIndexOriginName(cIdx) + for i, idx := range tblInfo.Indices { + if strings.EqualFold(idxName, idx.Name.O) { + cIdx.Name = model.NewCIStr(idxName) + tblInfo.Indices[i] = cIdx + break + } + } + } +} + +// updateNewIndexesCols updates the changing indexes column name&offset, and +// filter out the indexes that can be removed. +func updateNewIndexesCols(changingIdxs []*model.IndexInfo, + oldName, newName model.CIStr, newOffset int) []*model.IndexInfo { + indexesToRemove := make([]*model.IndexInfo, 0, len(changingIdxs)) + for _, idx := range changingIdxs { + var hasOtherChangingCol bool + for i, col := range idx.Columns { + if col.Name.L == oldName.L { + idx.Columns[i].Name = newName + idx.Columns[i].Offset = newOffset + } else { + if !hasOtherChangingCol { + hasOtherChangingCol = getChangingColumnOriginName(col) != col.Name.O } } } - changingColumnUniqueName := changingCol.Name - changingCol.Name = colName - changingCol.ChangeStateInfo = nil - // After changing the column, the column's type is change, so it needs to set OriginDefaultValue back - // so that there is no error in getting the default value from OriginDefaultValue. - // Besides, nil data that was not backfilled in the "add column" is backfilled after the column is changed. - // So it can set OriginDefaultValue to nil. - if err = changingCol.SetOriginDefaultValue(nil); err != nil { - return ver, errors.Trace(err) + // For the indexes that still contains other changing column, skip removing it now. + if !hasOtherChangingCol { + indexesToRemove = append(indexesToRemove, idx) } - tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-len(changingIdxs)] - // Adjust table column offset. - if err = adjustColumnInfoInModifyColumn(job, tblInfo, changingCol, oldCol, pos, changingColumnUniqueName.L); err != nil { - // TODO: Do rollback. - return ver, errors.Trace(err) + } + return indexesToRemove +} + +func updateChangingCol(col *model.ColumnInfo, newName model.CIStr, newOffset int) *model.ColumnInfo { + col.Name = newName + col.ChangeStateInfo = nil + col.Offset = newOffset + // After changing the column, the column's type is change, so it needs to set OriginDefaultValue back + // so that there is no error in getting the default value from OriginDefaultValue. + // Besides, nil data that was not backfilled in the "add column" is backfilled after the column is changed. + // So it can set OriginDefaultValue to nil. + col.OriginDefaultValue = nil + return col +} + +func getRelatedIndexInfos(tblInfo *model.TableInfo, colID int64) []*model.IndexInfo { + var indexInfos []*model.IndexInfo + for _, idx := range tblInfo.Indices { + for _, idxCol := range idx.Columns { + if tblInfo.Columns[idxCol.Offset].ID == colID { + indexInfos = append(indexInfos, idx) + break + } } - updateChangingInfo(changingCol, changingIdxs, model.StatePublic) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != changingCol.State) - if err != nil { - return ver, errors.Trace(err) + } + return indexInfos +} + +func getRelatedIndexIDs(tblInfo *model.TableInfo, colID int64) []int64 { + var oldIdxIDs []int64 + for _, idx := range tblInfo.Indices { + for _, idxCol := range idx.Columns { + if tblInfo.Columns[idxCol.Offset].ID == colID { + oldIdxIDs = append(oldIdxIDs, idx.ID) + break + } } + } + return oldIdxIDs +} - // Finish this job. - job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) - // Refactor the job args to add the old index ids into delete range table. - job.Args = []interface{}{oldIdxIDs, getPartitionIDs(tblInfo)} - asyncNotifyEvent(d, &ddlutil.Event{Tp: model.ActionModifyColumn, TableInfo: tblInfo, ColumnInfos: []*model.ColumnInfo{changingCol}}) +func locateOffsetToMove(currentOffset int, pos *ast.ColumnPosition, tblInfo *model.TableInfo) (destOffset int, err error) { + if pos == nil { + return currentOffset, nil + } + // Get column offset. + switch pos.Tp { + case ast.ColumnPositionFirst: + return 0, nil + case ast.ColumnPositionAfter: + c := model.FindColumnInfo(tblInfo.Columns, pos.RelativeColumn.Name.L) + if c == nil || c.State != model.StatePublic { + return 0, infoschema.ErrColumnNotExists.GenWithStackByArgs(pos.RelativeColumn, tblInfo.Name) + } + if currentOffset <= c.Offset { + return c.Offset, nil + } + return c.Offset + 1, nil + case ast.ColumnPositionNone: + return currentOffset, nil default: - err = ErrInvalidDDLState.GenWithStackByArgs("column", changingCol.State) + return 0, errors.Errorf("unknown column position type") } - - return ver, errors.Trace(err) } // BuildElements is exported for testing. @@ -1173,7 +1038,7 @@ func (w *worker) updateColumnAndIndexes(t table.Table, oldCol, col *model.Column time.Sleep(30 * time.Millisecond) if w.reorgCtx.isReorgCanceled() { // Job is cancelled. So it can't be done. - failpoint.Return(errCancelledDDLJob) + failpoint.Return(dbterror.ErrCancelledDDLJob) } } } @@ -1191,7 +1056,7 @@ func (w *worker) updateColumnAndIndexes(t table.Table, oldCol, col *model.Column if err != nil { return errors.Trace(err) } - originalStartHandle, originalEndHandle, err := getTableRange(reorgInfo.d, t.(table.PhysicalTable), currentVer.Ver, reorgInfo.Job.Priority) + originalStartHandle, originalEndHandle, err := getTableRange(w.JobContext, reorgInfo.d, t.(table.PhysicalTable), currentVer.Ver, reorgInfo.Job.Priority) if err != nil { return errors.Trace(err) } @@ -1262,7 +1127,7 @@ func newUpdateColumnWorker(sessCtx sessionctx.Context, worker *worker, id int, t backfillWorker: newBackfillWorker(sessCtx, worker, id, t), oldColInfo: oldCol, newColInfo: newCol, - metricCounter: metrics.BackfillTotalCounter.WithLabelValues("update_col_speed"), + metricCounter: metrics.BackfillTotalCounter.WithLabelValues("update_col_rate"), rowDecoder: rowDecoder, rowMap: make(map[int64]types.Datum, len(decodeColMap)), sqlMode: sqlMode, @@ -1298,7 +1163,7 @@ func (w *updateColumnWorker) fetchRowColVals(txn kv.Transaction, taskRange reorg taskDone := false var lastAccessedHandle kv.Key oprStartTime := startTime - err := iterateSnapshotRows(w.sessCtx.GetStore(), w.priority, w.table, txn.StartTS(), taskRange.startKey, taskRange.endKey, + err := iterateSnapshotRows(w.ddlWorker.JobContext, w.sessCtx.GetStore(), w.priority, w.table, txn.StartTS(), taskRange.startKey, taskRange.endKey, func(handle kv.Handle, recordKey kv.Key, rawRow []byte) (bool, error) { oprEndTime := time.Now() logSlowOperations(oprEndTime.Sub(oprStartTime), "iterateSnapshotRows in updateColumnWorker fetchRowColVals", 0) @@ -1331,9 +1196,10 @@ func (w *updateColumnWorker) fetchRowColVals(txn kv.Transaction, taskRange reorg } func (w *updateColumnWorker) getRowRecord(handle kv.Handle, recordKey []byte, rawRow []byte) error { - _, err := w.rowDecoder.DecodeTheExistedColumnMap(w.sessCtx, handle, rawRow, time.UTC, w.rowMap) + sysTZ := w.sessCtx.GetSessionVars().StmtCtx.TimeZone + _, err := w.rowDecoder.DecodeTheExistedColumnMap(w.sessCtx, handle, rawRow, sysTZ, w.rowMap) if err != nil { - return errors.Trace(errCantDecodeRecord.GenWithStackByArgs("column", err)) + return errors.Trace(dbterror.ErrCantDecodeRecord.GenWithStackByArgs("column", err)) } if _, ok := w.rowMap[w.newColInfo.ID]; ok { @@ -1354,7 +1220,7 @@ func (w *updateColumnWorker) getRowRecord(handle kv.Handle, recordKey []byte, ra val := w.rowMap[w.oldColInfo.ID] col := w.newColInfo if val.Kind() == types.KindNull && col.FieldType.Tp == mysql.TypeTimestamp && mysql.HasNotNullFlag(col.Flag) { - if v, err := expression.GetTimeCurrentTimestamp(w.sessCtx, col.Tp, int8(col.Decimal)); err == nil { + if v, err := expression.GetTimeCurrentTimestamp(w.sessCtx, col.Tp, col.Decimal); err == nil { // convert null value to timestamp should be substituted with current timestamp if NOT_NULL flag is set. w.rowMap[w.oldColInfo.ID] = v } @@ -1371,13 +1237,13 @@ func (w *updateColumnWorker) getRowRecord(handle kv.Handle, recordKey []byte, ra failpoint.Inject("MockReorgTimeoutInOneRegion", func(val failpoint.Value) { if val.(bool) { if handle.IntValue() == 3000 && atomic.CompareAndSwapInt32(&TestCheckReorgTimeout, 0, 1) { - failpoint.Return(errors.Trace(errWaitReorgTimeout)) + failpoint.Return(errors.Trace(dbterror.ErrWaitReorgTimeout)) } } }) w.rowMap[w.newColInfo.ID] = newColVal - _, err = w.rowDecoder.EvalRemainedExprColumnMap(w.sessCtx, timeutil.SystemLocation(), w.rowMap) + _, err = w.rowDecoder.EvalRemainedExprColumnMap(w.sessCtx, w.rowMap) if err != nil { return errors.Trace(err) } @@ -1434,6 +1300,9 @@ func (w *updateColumnWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (t taskCtx.addedCount = 0 taskCtx.scanCount = 0 txn.SetOption(kv.Priority, w.priority) + if tagger := w.ddlWorker.getResourceGroupTaggerForTopSQL(); tagger != nil { + txn.SetOption(kv.ResourceGroupTagger, tagger) + } rowRecords, nextKey, taskDone, err := w.fetchRowColVals(txn, handleRange) if err != nil { @@ -1472,7 +1341,7 @@ func (w *updateColumnWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (t return } -func updateChangingInfo(changingCol *model.ColumnInfo, changingIdxs []*model.IndexInfo, schemaState model.SchemaState) { +func updateChangingObjState(changingCol *model.ColumnInfo, changingIdxs []*model.IndexInfo, schemaState model.SchemaState) { changingCol.State = schemaState for _, idx := range changingIdxs { idx.State = schemaState @@ -1483,6 +1352,10 @@ func updateChangingInfo(changingCol *model.ColumnInfo, changingIdxs []*model.Ind func (w *worker) doModifyColumn( d *ddlCtx, t *meta.Meta, job *model.Job, dbInfo *model.DBInfo, tblInfo *model.TableInfo, newCol, oldCol *model.ColumnInfo, pos *ast.ColumnPosition) (ver int64, _ error) { + if oldCol.ID != newCol.ID { + job.State = model.JobStateRollingback + return ver, dbterror.ErrKeyColumnDoesNotExits.GenWithStack("column %s id %d does not exist, this column may have been updated by other DDL ran in parallel", oldCol.Name, newCol.ID) + } // Column from null to not null. if !mysql.HasNotNullFlag(oldCol.Flag) && mysql.HasNotNullFlag(newCol.Flag) { noPreventNullFlag := !mysql.HasPreventNullInsertFlag(oldCol.Flag) @@ -1496,7 +1369,7 @@ func (w *worker) doModifyColumn( // Introduce the `mysql.PreventNullInsertFlag` flag to prevent users from inserting or updating null values. err := modifyColsFromNull2NotNull(w, dbInfo, tblInfo, []*model.ColumnInfo{oldCol}, newCol, oldCol.Tp != newCol.Tp) if err != nil { - if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) { + if dbterror.ErrWarnDataTruncated.Equal(err) || dbterror.ErrInvalidUseOfNull.Equal(err) { job.State = model.JobStateRollingback } return ver, err @@ -1507,7 +1380,14 @@ func (w *worker) doModifyColumn( } } - if err := adjustColumnInfoInModifyColumn(job, tblInfo, newCol, oldCol, pos, ""); err != nil { + if job.MultiSchemaInfo != nil && job.MultiSchemaInfo.Revertible { + job.MarkNonRevertible() + // Store the mark and enter the next DDL handling loop. + return updateVersionAndTableInfoWithCheck(t, job, tblInfo, false) + } + + if err := adjustTableInfoAfterModifyColumn(tblInfo, newCol, oldCol, pos); err != nil { + job.State = model.JobStateRollingback return ver, errors.Trace(err) } @@ -1524,82 +1404,22 @@ func (w *worker) doModifyColumn( return ver, nil } -func adjustColumnInfoInModifyColumn( - job *model.Job, tblInfo *model.TableInfo, newCol, oldCol *model.ColumnInfo, pos *ast.ColumnPosition, changingColUniqueLowerName string) error { +func adjustTableInfoAfterModifyColumn( + tblInfo *model.TableInfo, newCol, oldCol *model.ColumnInfo, pos *ast.ColumnPosition) error { // We need the latest column's offset and state. This information can be obtained from the store. newCol.Offset = oldCol.Offset newCol.State = oldCol.State - // Calculate column's new position. - oldPos, newPos := oldCol.Offset, oldCol.Offset - if pos.Tp == ast.ColumnPositionAfter { - // TODO: The check of "RelativeColumn" can be checked in advance. When "EnableChangeColumnType" is true, unnecessary state changes can be reduced. - if oldCol.Name.L == pos.RelativeColumn.Name.L { - // `alter table tableName modify column b int after b` will return ver,ErrColumnNotExists. - // Modified the type definition of 'null' to 'not null' before this, so rollback the job when an error occurs. - job.State = model.JobStateRollingback - return infoschema.ErrColumnNotExists.GenWithStackByArgs(oldCol.Name, tblInfo.Name) - } - - relative := model.FindColumnInfo(tblInfo.Columns, pos.RelativeColumn.Name.L) - if relative == nil || relative.State != model.StatePublic { - job.State = model.JobStateRollingback - return infoschema.ErrColumnNotExists.GenWithStackByArgs(pos.RelativeColumn, tblInfo.Name) - } - - if relative.Offset < oldPos { - newPos = relative.Offset + 1 - } else { - newPos = relative.Offset - } - } else if pos.Tp == ast.ColumnPositionFirst { - newPos = 0 + if pos != nil && pos.RelativeColumn != nil && oldCol.Name.L == pos.RelativeColumn.Name.L { + // For cases like `modify column b after b`, it should report this error. + return errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(oldCol.Name, tblInfo.Name)) } - - columnChanged := make(map[string]*model.ColumnInfo) - columnChanged[oldCol.Name.L] = newCol - - if newPos == oldPos { - tblInfo.Columns[newPos] = newCol - } else { - cols := tblInfo.Columns - - // Reorder columns in place. - if newPos < oldPos { - // ******** +(new) ****** -(old) ******** - // [newPos:old-1] should shift one step to the right. - copy(cols[newPos+1:], cols[newPos:oldPos]) - } else { - // ******** -(old) ****** +(new) ******** - // [old+1:newPos] should shift one step to the left. - copy(cols[oldPos:], cols[oldPos+1:newPos+1]) - } - cols[newPos] = newCol - - for i, col := range tblInfo.Columns { - if col.Offset != i { - columnChanged[col.Name.L] = col - col.Offset = i - } - } - } - - // Change offset and name in indices. - for _, idx := range tblInfo.Indices { - for _, c := range idx.Columns { - cName := c.Name.L - // With the unique changing column name, the format is designed as `_Col$_xx_uniqueNum`. - // The suffix `_uniqueNum` will be trimmed when we get the origin changing column name. - // There is a possibility that some other column named as `xx_xx_xx`, and it will be get - // trimmed as `xx_xx`. So here we check here and only do the trim for the changing index column. - if len(changingColUniqueLowerName) != 0 && c.Name.L == changingColUniqueLowerName { - cName = strings.ToLower(getChangingColumnOriginName(c)) - } - if newCol, ok := columnChanged[cName]; ok { - c.Name = newCol.Name - c.Offset = newCol.Offset - } - } + destOffset, err := locateOffsetToMove(oldCol.Offset, pos, tblInfo) + if err != nil { + return errors.Trace(infoschema.ErrColumnNotExists.GenWithStackByArgs(oldCol.Name, tblInfo.Name)) } + tblInfo.Columns[oldCol.Offset] = newCol + tblInfo.MoveColumnInfo(oldCol.Offset, destOffset) + updateNewIndexesCols(tblInfo.Indices, oldCol.Name, newCol.Name, newCol.Offset) return nil } @@ -1641,7 +1461,7 @@ func checkNewAutoRandomBits(idAccessors meta.AutoIDAccessors, oldCol *model.Colu if usedBits > newLayout.IncrementalBits { overflowCnt := usedBits - newLayout.IncrementalBits errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg, newAutoRandBits-overflowCnt, newAutoRandBits, oldCol.Name.O) - return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } return nil } @@ -1658,7 +1478,7 @@ func applyNewAutoRandomBits(d *ddlCtx, m *meta.Meta, dbInfo *model.DBInfo, autoRandAlloc := autoid.NewAllocatorsFromTblInfo(d.store, dbInfo.ID, tblInfo).Get(autoid.AutoRandomType) if autoRandAlloc == nil { errMsg := fmt.Sprintf(autoid.AutoRandomAllocatorNotFound, dbInfo.Name.O, tblInfo.Name.O) - return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } idAcc := m.GetAutoIDAccessors(dbInfo.ID, tblInfo.ID).RowID() nextAutoIncID, err := idAcc.Get() @@ -1703,26 +1523,22 @@ func checkForNullValue(ctx context.Context, sctx sessionctx.Context, isDataTrunc } } buf.WriteString(" limit 1") - stmt, err := sctx.(sqlexec.RestrictedSQLExecutor).ParseWithParams(ctx, buf.String(), paramsList...) - if err != nil { - return errors.Trace(err) - } - rows, _, err := sctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(ctx, stmt) + rows, _, err := sctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, nil, buf.String(), paramsList...) if err != nil { return errors.Trace(err) } rowCount := len(rows) if rowCount != 0 { if isDataTruncated { - return ErrWarnDataTruncated.GenWithStackByArgs(newCol.Name.L, rowCount) + return dbterror.ErrWarnDataTruncated.GenWithStackByArgs(newCol.Name.L, rowCount) } - return errInvalidUseOfNull + return dbterror.ErrInvalidUseOfNull } return nil } func updateColumnDefaultValue(t *meta.Meta, job *model.Job, newCol *model.ColumnInfo, oldColName *model.CIStr) (ver int64, _ error) { - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -1757,17 +1573,20 @@ func isColumnWithIndex(colName string, indices []*model.IndexInfo) bool { return false } -func isColumnCanDropWithIndex(isMultiSchemaChange bool, colName string, indices []*model.IndexInfo) bool { +func isColumnCanDropWithIndex(isMultiSchemaChange bool, colName string, indices []*model.IndexInfo) error { for _, indexInfo := range indices { - if indexInfo.Primary || len(indexInfo.Columns) > 1 || (!isMultiSchemaChange && len(indexInfo.Columns) == 1) { + if indexInfo.Primary || len(indexInfo.Columns) > 1 { for _, col := range indexInfo.Columns { if col.Name.L == colName { - return false + return dbterror.ErrCantDropColWithIndex.GenWithStack("can't drop column %s with composite index covered or Primary Key covered now", colName) } } } + if len(indexInfo.Columns) == 1 && indexInfo.Columns[0].Name.L == colName && !isMultiSchemaChange { + return dbterror.ErrCantDropColWithIndex.GenWithStack("can't drop column %s with tidb_enable_change_multi_schema is disable", colName) + } } - return true + return nil } func listIndicesWithColumn(colName string, indices []*model.IndexInfo) []*model.IndexInfo { @@ -1798,15 +1617,15 @@ func allocateColumnID(tblInfo *model.TableInfo) int64 { func checkAddColumnTooManyColumns(colNum int) error { if uint32(colNum) > atomic.LoadUint32(&config.GetGlobalConfig().TableColumnCountLimit) { - return errTooManyFields + return dbterror.ErrTooManyFields } return nil } // rollbackModifyColumnJob rollbacks the job when an error occurs. -func rollbackModifyColumnJob(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, oldCol *model.ColumnInfo, modifyColumnTp byte) (ver int64, _ error) { +func rollbackModifyColumnJob(t *meta.Meta, tblInfo *model.TableInfo, job *model.Job, newCol, oldCol *model.ColumnInfo, modifyColumnTp byte) (ver int64, _ error) { var err error - if modifyColumnTp == mysql.TypeNull { + if oldCol.ID == newCol.ID && modifyColumnTp == mysql.TypeNull { // field NotNullFlag flag reset. tblInfo.Columns[oldCol.Offset].Flag = oldCol.Flag &^ mysql.NotNullFlag // field PreventNullInsertFlag flag reset. @@ -1854,7 +1673,7 @@ func modifyColsFromNull2NotNull(w *worker, dbInfo *model.DBInfo, tblInfo *model. return nil } -func generateOriginDefaultValue(col *model.ColumnInfo) (interface{}, error) { +func generateOriginDefaultValue(col *model.ColumnInfo, ctx sessionctx.Context) (interface{}, error) { var err error odValue := col.GetDefaultValue() if odValue == nil && mysql.HasNotNullFlag(col.Flag) { @@ -1877,10 +1696,16 @@ func generateOriginDefaultValue(col *model.ColumnInfo) (interface{}, error) { } if odValue == strings.ToUpper(ast.CurrentTimestamp) { + var t time.Time + if ctx == nil { + t = time.Now() + } else { + t, _ = expression.GetStmtTimestamp(ctx) + } if col.Tp == mysql.TypeTimestamp { - odValue = types.NewTime(types.FromGoTime(time.Now().UTC()), col.Tp, int8(col.Decimal)).String() + odValue = types.NewTime(types.FromGoTime(t.UTC()), col.Tp, col.Decimal).String() } else if col.Tp == mysql.TypeDatetime { - odValue = types.NewTime(types.FromGoTime(time.Now()), col.Tp, int8(col.Decimal)).String() + odValue = types.NewTime(types.FromGoTime(t), col.Tp, col.Decimal).String() } } return odValue, nil diff --git a/ddl/column_change_test.go b/ddl/column_change_test.go index 2349c7fc3d47f..7510fd96e3181 100644 --- a/ddl/column_change_test.go +++ b/ddl/column_change_test.go @@ -12,303 +12,178 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" "fmt" - "sync" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/meta/autoid" - "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testColumnChangeSuite{}) +func TestColumnAdd(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) + tk := testkit.NewTestKit(t, store) + internal := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c1 int, c2 int);") + tk.MustExec("insert t values (1, 2);") -type testColumnChangeSuite struct { - store kv.Storage - dbInfo *model.DBInfo -} - -func (s *testColumnChangeSuite) SetUpSuite(c *C) { - SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) - s.store = testCreateStore(c, "test_column_change") - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - s.dbInfo, err = testSchemaInfo(d, "test_index_change") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, s.dbInfo) -} - -func (s *testColumnChangeSuite) TearDownSuite(c *C) { - s.store.Close() -} - -func (s *testColumnChangeSuite) TestColumnChange(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - // create table t (c1 int, c2 int); - tblInfo, err := testTableInfo(d, "t", 2) - c.Assert(err, IsNil) - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - // insert t values (1, 2); - originTable := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - row := types.MakeDatums(1, 2) - h, err := originTable.AddRecord(ctx, row) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} - var mu sync.Mutex - tc := &TestDDLCallback{} + ct := testNewContext(store) // set up hook - prevState := model.StateNone var ( deleteOnlyTable table.Table writeOnlyTable table.Table publicTable table.Table + dropCol *table.Column ) - var checkErr error - tc.onJobUpdated = func(job *model.Job) { - if job.SchemaState == prevState { - return - } - hookCtx := mock.NewContext() - hookCtx.Store = s.store - prevState = job.SchemaState - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } + first := true + var jobID int64 + tc.OnJobUpdatedExported = func(job *model.Job) { + jobID = job.ID + require.NoError(t, dom.Reload()) + tbl, exist := dom.InfoSchema().TableByID(job.TableID) + require.True(t, exist) switch job.SchemaState { case model.StateDeleteOnly: - deleteOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } + deleteOnlyTable = tbl case model.StateWriteOnly: - writeOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - err = s.checkAddWriteOnly(hookCtx, d, deleteOnlyTable, writeOnlyTable, h) - if err != nil { - checkErr = errors.Trace(err) - } + writeOnlyTable = tbl + require.NoError(t, checkAddWriteOnly(ct, deleteOnlyTable, writeOnlyTable, kv.IntHandle(1))) case model.StatePublic: - mu.Lock() - publicTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) + if first { + first = false + } else { + return } - err = s.checkAddPublic(hookCtx, d, writeOnlyTable, publicTable) - if err != nil { - checkErr = errors.Trace(err) - } - mu.Unlock() + publicTable = tbl + require.NoError(t, checkAddPublic(ct, writeOnlyTable, publicTable)) } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) + } + d.SetHook(tc) + tk.MustExec("alter table t add column c3 int default 3") + tb := publicTable + v := getSchemaVer(t, tk.Session()) + checkHistoryJobArgs(t, tk.Session(), jobID, &historyJobArgs{ver: v, tbl: tb.Meta()}) + + // Drop column. + tc.OnJobRunBeforeExported = func(job *model.Job) { + if dropCol == nil { + tbl := external.GetTableByName(t, internal, "test", "t") + dropCol = tbl.VisibleCols()[2] } - err = txn.Commit(context.Background()) - if err != nil { - checkErr = errors.Trace(err) + } + tc.OnJobUpdatedExported = func(job *model.Job) { + jobID = job.ID + tbl := external.GetTableByName(t, internal, "test", "t") + if job.SchemaState != model.StateNone { + for _, col := range tbl.Cols() { + require.NotEqualf(t, col.ID, dropCol.ID, "column is not dropped") + } } } d.SetHook(tc) - defaultValue := int64(3) - job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c3", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, defaultValue) - c.Assert(checkErr, IsNil) - testCheckJobDone(c, d, job, true) - mu.Lock() - tb := publicTable - mu.Unlock() - s.testColumnDrop(c, ctx, d, tb) - s.testAddColumnNoDefault(c, ctx, d, tblInfo) + tk.MustExec("alter table t drop column c3") + v = getSchemaVer(t, tk.Session()) + // Don't check column, so it's ok to use tb. + checkHistoryJobArgs(t, tk.Session(), jobID, &historyJobArgs{ver: v, tbl: tb.Meta()}) + + // Add column not default. + first = true + tc.OnJobUpdatedExported = func(job *model.Job) { + jobID = job.ID + tbl, exist := dom.InfoSchema().TableByID(job.TableID) + require.True(t, exist) + switch job.SchemaState { + case model.StateWriteOnly: + writeOnlyTable = tbl + case model.StatePublic: + if first { + first = false + } else { + return + } + sess := testNewContext(store) + err := sess.NewTxn(context.Background()) + require.NoError(t, err) + _, err = writeOnlyTable.AddRecord(sess, types.MakeDatums(10, 10)) + require.NoError(t, err) + } + } + d.SetHook(tc) + tk.MustExec("alter table t add column c3 int") + testCheckJobDone(t, store, jobID, true) } -func (s *testColumnChangeSuite) TestModifyAutoRandColumnWithMetaKeyChanged(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() +func TestModifyAutoRandColumnWithMetaKeyChanged(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a bigint primary key clustered AUTO_RANDOM(5));") - ids, err := d.genGlobalIDs(1) - tableID := ids[0] - c.Assert(err, IsNil) - colInfo := &model.ColumnInfo{ - Name: model.NewCIStr("a"), - Offset: 0, - State: model.StatePublic, - FieldType: *types.NewFieldType(mysql.TypeLonglong), - } - tblInfo := &model.TableInfo{ - ID: tableID, - Name: model.NewCIStr("auto_random_table_name"), - Columns: []*model.ColumnInfo{colInfo}, - AutoRandomBits: 5, - } - colInfo.ID = allocateColumnID(tblInfo) - ctx := testNewContext(d) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} - tc := &TestDDLCallback{} var errCount int32 = 3 var genAutoRandErr error - tc.onJobRunBefore = func(job *model.Job) { + var dbID int64 + var tID int64 + var jobID int64 + tc.OnJobRunBeforeExported = func(job *model.Job) { + jobID = job.ID + dbID = job.SchemaID + tID = job.TableID if atomic.LoadInt32(&errCount) > 0 && job.Type == model.ActionModifyColumn { atomic.AddInt32(&errCount, -1) - genAutoRandErr = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { + genAutoRandErr = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) - _, err1 := t.GetAutoIDAccessors(s.dbInfo.ID, tableID).RandomID().Inc(1) + _, err1 := t.GetAutoIDAccessors(dbID, tID).RandomID().Inc(1) return err1 }) } } d.SetHook(tc) + + tk.MustExec("alter table t modify column a bigint AUTO_RANDOM(10)") + require.True(t, errCount == 0) + require.Nil(t, genAutoRandErr) const newAutoRandomBits uint64 = 10 - job := &model.Job{ - SchemaID: s.dbInfo.ID, - TableID: tblInfo.ID, - SchemaName: s.dbInfo.Name.L, - Type: model.ActionModifyColumn, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{colInfo, colInfo.Name, ast.ColumnPosition{}, 0, newAutoRandomBits}, - } - err = d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - c.Assert(errCount == 0, IsTrue) - c.Assert(genAutoRandErr, IsNil) - testCheckJobDone(c, d, job, true) + testCheckJobDone(t, store, jobID, true) var newTbInfo *model.TableInfo - err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) var err error - newTbInfo, err = t.GetTable(s.dbInfo.ID, tableID) + newTbInfo, err = t.GetTable(dbID, tID) if err != nil { return errors.Trace(err) } return nil }) - c.Assert(err, IsNil) - c.Assert(newTbInfo.AutoRandomBits, Equals, newAutoRandomBits) -} - -func (s *testColumnChangeSuite) testAddColumnNoDefault(c *C, ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo) { - tc := &TestDDLCallback{} - // set up hook - prevState := model.StateNone - var checkErr error - var writeOnlyTable table.Table - tc.onJobUpdated = func(job *model.Job) { - if job.SchemaState == prevState { - return - } - hookCtx := mock.NewContext() - hookCtx.Store = s.store - prevState = job.SchemaState - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } - switch job.SchemaState { - case model.StateWriteOnly: - writeOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - case model.StatePublic: - _, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - _, err = writeOnlyTable.AddRecord(hookCtx, types.MakeDatums(10, 10)) - if err != nil { - checkErr = errors.Trace(err) - } - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - } - err = txn.Commit(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - } - } - d.SetHook(tc) - job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c3", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, nil) - c.Assert(checkErr, IsNil) - testCheckJobDone(c, d, job, true) -} - -func (s *testColumnChangeSuite) testColumnDrop(c *C, ctx sessionctx.Context, d *ddl, tbl table.Table) { - dropCol := tbl.Cols()[2] - tc := &TestDDLCallback{} - // set up hook - prevState := model.StateNone - var checkErr error - tc.onJobUpdated = func(job *model.Job) { - if job.SchemaState == prevState { - return - } - prevState = job.SchemaState - currentTbl, err := getCurrentTable(d, s.dbInfo.ID, tbl.Meta().ID) - if err != nil { - checkErr = errors.Trace(err) - } - for _, col := range currentTbl.Cols() { - if col.ID == dropCol.ID { - checkErr = errors.Errorf("column is not dropped") - } - } - } - d.SetHook(tc) - c.Assert(checkErr, IsNil) - testDropColumn(c, ctx, d, s.dbInfo, tbl.Meta(), dropCol.Name.L, false) + require.NoError(t, err) + require.Equal(t, newTbInfo.AutoRandomBits, newAutoRandomBits) } func seek(t table.PhysicalTable, ctx sessionctx.Context, h kv.Handle) (kv.Handle, bool, error) { @@ -333,7 +208,7 @@ func seek(t table.PhysicalTable, ctx sessionctx.Context, h kv.Handle) (kv.Handle return handle, true, nil } -func (s *testColumnChangeSuite) checkAddWriteOnly(ctx sessionctx.Context, d *ddl, deleteOnlyTable, writeOnlyTable table.Table, h kv.Handle) error { +func checkAddWriteOnly(ctx sessionctx.Context, deleteOnlyTable, writeOnlyTable table.Table, h kv.Handle) error { // WriteOnlyTable: insert t values (2, 3) err := ctx.NewTxn(context.Background()) if err != nil { @@ -347,8 +222,10 @@ func (s *testColumnChangeSuite) checkAddWriteOnly(ctx sessionctx.Context, d *ddl if err != nil { return errors.Trace(err) } - err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), - testutil.RowsWithSep(" ", "1 2 ", "2 3 3")) + err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), [][]string{ + {"1", "2", ""}, + {"2", "3", "3"}, + }) if err != nil { return errors.Trace(err) } @@ -363,7 +240,10 @@ func (s *testColumnChangeSuite) checkAddWriteOnly(ctx sessionctx.Context, d *ddl return errors.Errorf("expect %v, got %v", expect, got) } // DeleteOnlyTable: select * from t - err = checkResult(ctx, deleteOnlyTable, deleteOnlyTable.WritableCols(), testutil.RowsWithSep(" ", "1 2", "2 3")) + err = checkResult(ctx, deleteOnlyTable, deleteOnlyTable.WritableCols(), [][]string{ + {"1", "2"}, + {"2", "3"}, + }) if err != nil { return errors.Trace(err) } @@ -381,7 +261,10 @@ func (s *testColumnChangeSuite) checkAddWriteOnly(ctx sessionctx.Context, d *ddl return errors.Trace(err) } // After we update the first row, its default value is also set. - err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), testutil.RowsWithSep(" ", "2 2 3", "2 3 3")) + err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), [][]string{ + {"2", "2", "3"}, + {"2", "3", "3"}, + }) if err != nil { return errors.Trace(err) } @@ -395,7 +278,9 @@ func (s *testColumnChangeSuite) checkAddWriteOnly(ctx sessionctx.Context, d *ddl return errors.Trace(err) } // After delete table has deleted the first row, check the WriteOnly table records. - err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), testutil.RowsWithSep(" ", "2 3 3")) + err = checkResult(ctx, writeOnlyTable, writeOnlyTable.WritableCols(), [][]string{ + {"2", "3", "3"}, + }) return errors.Trace(err) } @@ -407,7 +292,7 @@ func touchedSlice(t table.Table) []bool { return touched } -func (s *testColumnChangeSuite) checkAddPublic(sctx sessionctx.Context, d *ddl, writeOnlyTable, publicTable table.Table) error { +func checkAddPublic(sctx sessionctx.Context, writeOnlyTable, publicTable table.Table) error { ctx := context.TODO() // publicTable Insert t values (4, 4, 4) err := sctx.NewTxn(ctx) @@ -440,36 +325,17 @@ func (s *testColumnChangeSuite) checkAddPublic(sctx sessionctx.Context, d *ddl, return errors.Trace(err) } // publicTable select * from t, make sure the new c3 value 4 is not overwritten to default value 3. - err = checkResult(sctx, publicTable, publicTable.WritableCols(), testutil.RowsWithSep(" ", "2 3 3", "3 4 4")) + err = checkResult(sctx, publicTable, publicTable.WritableCols(), [][]string{ + {"2", "3", "3"}, + {"3", "4", "4"}, + }) if err != nil { return errors.Trace(err) } return nil } -func getCurrentTable(d *ddl, schemaID, tableID int64) (table.Table, error) { - var tblInfo *model.TableInfo - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - var err error - tblInfo, err = t.GetTable(schemaID, tableID) - if err != nil { - return errors.Trace(err) - } - return nil - }) - if err != nil { - return nil, errors.Trace(err) - } - alloc := autoid.NewAllocator(d.store, schemaID, tblInfo.ID, false, autoid.RowIDAllocType) - tbl, err := table.TableFromMeta(autoid.NewAllocators(alloc), tblInfo) - if err != nil { - return nil, errors.Trace(err) - } - return tbl, err -} - -func checkResult(ctx sessionctx.Context, t table.Table, cols []*table.Column, rows [][]interface{}) error { +func checkResult(ctx sessionctx.Context, t table.Table, cols []*table.Column, rows [][]string) error { var gotRows [][]interface{} err := tables.IterRecords(t, ctx, cols, func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { gotRows = append(gotRows, datumsToInterfaces(data)) @@ -493,3 +359,76 @@ func datumsToInterfaces(datums []types.Datum) []interface{} { } return ifs } + +type historyJobArgs struct { + ver int64 + db *model.DBInfo + tbl *model.TableInfo + tblIDs map[int64]struct{} +} + +func getSchemaVer(t *testing.T, ctx sessionctx.Context) int64 { + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err := ctx.Txn(true) + require.NoError(t, err) + m := meta.NewMeta(txn) + ver, err := m.GetSchemaVersion() + require.NoError(t, err) + return ver +} + +func checkEqualTable(t *testing.T, t1, t2 *model.TableInfo) { + require.Equal(t, t1.ID, t2.ID) + require.Equal(t, t1.Name, t2.Name) + require.Equal(t, t1.Charset, t2.Charset) + require.Equal(t, t1.Collate, t2.Collate) + require.Equal(t, t1.PKIsHandle, t2.PKIsHandle) + require.Equal(t, t1.Comment, t2.Comment) + require.Equal(t, t1.AutoIncID, t2.AutoIncID) +} + +func checkHistoryJobArgs(t *testing.T, ctx sessionctx.Context, id int64, args *historyJobArgs) { + txn, err := ctx.Txn(true) + require.NoError(t, err) + tran := meta.NewMeta(txn) + historyJob, err := tran.GetHistoryDDLJob(id) + require.NoError(t, err) + require.Greater(t, historyJob.BinlogInfo.FinishedTS, uint64(0)) + + if args.tbl != nil { + require.Equal(t, historyJob.BinlogInfo.SchemaVersion, args.ver) + checkEqualTable(t, historyJob.BinlogInfo.TableInfo, args.tbl) + return + } + + // for handling schema job + require.Equal(t, historyJob.BinlogInfo.SchemaVersion, args.ver) + require.Equal(t, historyJob.BinlogInfo.DBInfo, args.db) + // only for creating schema job + if args.db != nil && len(args.tblIDs) == 0 { + return + } +} + +func testCheckJobDone(t *testing.T, store kv.Storage, jobID int64, isAdd bool) { + require.NoError(t, kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + historyJob, err := m.GetHistoryDDLJob(jobID) + require.NoError(t, err) + require.Equal(t, historyJob.State, model.JobStateSynced) + if isAdd { + require.Equal(t, historyJob.SchemaState, model.StatePublic) + } else { + require.Equal(t, historyJob.SchemaState, model.StateNone) + } + + return nil + })) +} + +func testNewContext(store kv.Storage) sessionctx.Context { + ctx := mock.NewContext() + ctx.Store = store + return ctx +} diff --git a/ddl/column_modify_test.go b/ddl/column_modify_test.go new file mode 100644 index 0000000000000..b14a6f903beb7 --- /dev/null +++ b/ddl/column_modify_test.go @@ -0,0 +1,1294 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "math/rand" + "strconv" + "strings" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/ddl" + testddlutil "github.com/pingcap/tidb/ddl/testutil" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" +) + +const columnModifyLease = 600 * time.Millisecond + +func TestAddAndDropColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t2 (c1 int, c2 int, c3 int)") + tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") + + // ========== + // ADD COLUMN + // ========== + + done := make(chan error, 1) + + num := defaultBatchSize + 10 + // add some rows + batchInsert(tk, "t2", 0, num) + + testddlutil.SessionExecInGoroutine(store, "test", "alter table t2 add column c4 int default -1", done) + + ticker := time.NewTicker(columnModifyLease / 2) + defer ticker.Stop() + step := 10 +AddLoop: + for { + select { + case err := <-done: + if err == nil { + break AddLoop + } + require.NoError(t, err) + case <-ticker.C: + // delete some rows, and add some data + for i := num; i < num+step; i++ { + n := rand.Intn(num) + tk.MustExec("begin") + tk.MustExec("delete from t2 where c1 = ?", n) + tk.MustExec("commit") + + // Make sure that statement of insert and show use the same infoSchema. + tk.MustExec("begin") + err := tk.ExecToErr("insert into t2 values (?, ?, ?)", i, i, i) + if err != nil { + // if err is failed, the column number must be 4 now. + values := tk.MustQuery("show columns from t2").Rows() + require.Len(t, values, 4) + } + tk.MustExec("commit") + } + num += step + } + } + + // add data, here c4 must exist + for i := num; i < num+step; i++ { + tk.MustExec("insert into t2 values (?, ?, ?, ?)", i, i, i, i) + } + + rows := tk.MustQuery("select count(c4) from t2").Rows() + require.Len(t, rows, 1) + require.Len(t, rows[0], 1) + count, err := strconv.ParseInt(rows[0][0].(string), 10, 64) + require.NoError(t, err) + require.Greater(t, count, int64(0)) + + tk.MustQuery("select count(c4) from t2 where c4 = -1").Check([][]interface{}{ + {fmt.Sprintf("%v", count-int64(step))}, + }) + + for i := num; i < num+step; i++ { + tk.MustQuery("select c4 from t2 where c4 = ?", i).Check([][]interface{}{ + {fmt.Sprintf("%v", i)}, + }) + } + + tbl := external.GetTableByName(t, tk, "test", "t2") + i := 0 + j := 0 + require.NoError(t, tk.Session().NewTxn(context.Background())) + defer func() { + if txn, err := tk.Session().Txn(true); err == nil { + require.NoError(t, txn.Rollback()) + } + }() + + err = tables.IterRecords(tbl, tk.Session(), tbl.Cols(), + func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + i++ + // c4 must be -1 or > 0 + v, err := data[3].ToInt64(tk.Session().GetSessionVars().StmtCtx) + require.NoError(t, err) + if v == -1 { + j++ + } else { + require.Greater(t, v, int64(0)) + } + return true, nil + }) + require.NoError(t, err) + require.Equal(t, int(count), i) + require.LessOrEqual(t, i, num+step) + require.Equal(t, int(count)-step, j) + + // for modifying columns after adding columns + tk.MustExec("alter table t2 modify c4 int default 11") + for i := num + step; i < num+step+10; i++ { + tk.MustExec("insert into t2 values (?, ?, ?, ?)", i, i, i, i) + } + tk.MustQuery("select count(c4) from t2 where c4 = -1").Check([][]interface{}{ + {fmt.Sprintf("%v", count-int64(step))}, + }) + + // add timestamp type column + tk.MustExec("create table test_on_update_c (c1 int, c2 timestamp);") + defer tk.MustExec("drop table test_on_update_c;") + tk.MustExec("alter table test_on_update_c add column c3 timestamp null default '2017-02-11' on update current_timestamp;") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_on_update_c")) + require.NoError(t, err) + tblInfo := tbl.Meta() + colC := tblInfo.Columns[2] + require.Equal(t, mysql.TypeTimestamp, colC.Tp) + require.False(t, mysql.HasNotNullFlag(colC.Flag)) + // add datetime type column + tk.MustExec("create table test_on_update_d (c1 int, c2 datetime);") + tk.MustExec("alter table test_on_update_d add column c3 datetime on update current_timestamp;") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_on_update_d")) + require.NoError(t, err) + tblInfo = tbl.Meta() + colC = tblInfo.Columns[2] + require.Equal(t, mysql.TypeDatetime, colC.Tp) + require.False(t, mysql.HasNotNullFlag(colC.Flag)) + + // add year type column + tk.MustExec("create table test_on_update_e (c1 int);") + defer tk.MustExec("drop table test_on_update_e;") + tk.MustExec("insert into test_on_update_e (c1) values (0);") + tk.MustExec("alter table test_on_update_e add column c2 year not null;") + tk.MustQuery("select c2 from test_on_update_e").Check(testkit.Rows("0")) + + // test add unsupported constraint + tk.MustExec("create table t_add_unsupported_constraint (a int);") + err = tk.ExecToErr("ALTER TABLE t_add_unsupported_constraint ADD id int AUTO_INCREMENT;") + require.EqualError(t, err, "[ddl:8200]unsupported add column 'id' constraint AUTO_INCREMENT when altering 'test.t_add_unsupported_constraint'") + err = tk.ExecToErr("ALTER TABLE t_add_unsupported_constraint ADD id int KEY;") + require.EqualError(t, err, "[ddl:8200]unsupported add column 'id' constraint PRIMARY KEY when altering 'test.t_add_unsupported_constraint'") + err = tk.ExecToErr("ALTER TABLE t_add_unsupported_constraint ADD id int UNIQUE;") + require.EqualError(t, err, "[ddl:8200]unsupported add column 'id' constraint UNIQUE KEY when altering 'test.t_add_unsupported_constraint'") + + // =========== + // DROP COLUMN + // =========== + + done = make(chan error, 1) + tk.MustExec("delete from t2") + + num = 100 + // add some rows + for i := 0; i < num; i++ { + tk.MustExec("insert into t2 values (?, ?, ?, ?)", i, i, i, i) + } + + // get c4 column id + testddlutil.SessionExecInGoroutine(store, "test", "alter table t2 drop column c4", done) + + ticker = time.NewTicker(columnModifyLease / 2) + defer ticker.Stop() + step = 10 +DropLoop: + for { + select { + case err := <-done: + if err == nil { + break DropLoop + } + require.NoError(t, err) + case <-ticker.C: + // delete some rows, and add some data + for i := num; i < num+step; i++ { + // Make sure that statement of insert and show use the same infoSchema. + tk.MustExec("begin") + err := tk.ExecToErr("insert into t2 values (?, ?, ?)", i, i, i) + if err != nil { + // If executing is failed, the column number must be 4 now. + values := tk.MustQuery("show columns from t2").Rows() + require.Len(t, values, 4) + } + tk.MustExec("commit") + } + num += step + } + } + + // add data, here c4 must not exist + for i := num; i < num+step; i++ { + tk.MustExec("insert into t2 values (?, ?, ?)", i, i, i) + } + + rows = tk.MustQuery("select count(*) from t2").Rows() + require.Len(t, rows, 1) + require.Len(t, rows[0], 1) + count, err = strconv.ParseInt(rows[0][0].(string), 10, 64) + require.NoError(t, err) + require.Greater(t, count, int64(0)) +} + +// TestDropColumn is for inserting value with a to-be-dropped column when do drop column. +// Column info from schema in build-insert-plan should be public only, +// otherwise they will not be consisted with Table.Col(), then the server will panic. +func TestDropColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + num := 25 + multiDDL := make([]string, 0, num) + sql := "create table t2 (c1 int, c2 int, c3 int, " + for i := 4; i < 4+num; i++ { + multiDDL = append(multiDDL, fmt.Sprintf("alter table t2 drop column c%d", i)) + + if i != 3+num { + sql += fmt.Sprintf("c%d int, ", i) + } else { + sql += fmt.Sprintf("c%d int)", i) + } + } + tk.MustExec(sql) + dmlDone := make(chan error, num) + ddlDone := make(chan error, num) + + testddlutil.ExecMultiSQLInGoroutine(store, "test", multiDDL, ddlDone) + for i := 0; i < num; i++ { + testddlutil.ExecMultiSQLInGoroutine(store, "test", []string{"insert into t2 set c1 = 1, c2 = 1, c3 = 1, c4 = 1"}, dmlDone) + } + for i := 0; i < num; i++ { + err := <-ddlDone + require.NoError(t, err) + } + + // Test for drop partition table column. + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int,b int) partition by hash(a) partitions 4;") + err := tk.ExecToErr("alter table t1 drop column a") + // TODO: refine the error message to compatible with MySQL + require.EqualError(t, err, "[planner:1054]Unknown column 'a' in 'expression'") +} + +func TestChangeColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table t3 (a int default '0', b varchar(10), d int not null default '0')") + tk.MustExec("insert into t3 set b = 'a'") + tk.MustQuery("select a from t3").Check(testkit.Rows("0")) + tk.MustExec("alter table t3 change a aa bigint") + tk.MustExec("insert into t3 set b = 'b'") + tk.MustQuery("select aa from t3").Check(testkit.Rows("0", "")) + // for no default flag + tk.MustExec("alter table t3 change d dd bigint not null") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) + require.NoError(t, err) + tblInfo := tbl.Meta() + colD := tblInfo.Columns[2] + require.True(t, mysql.HasNoDefaultValueFlag(colD.Flag)) + // for the following definitions: 'not null', 'null', 'default value' and 'comment' + tk.MustExec("alter table t3 change b b varchar(20) null default 'c' comment 'my comment'") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) + require.NoError(t, err) + tblInfo = tbl.Meta() + colB := tblInfo.Columns[1] + require.Equal(t, "my comment", colB.Comment) + require.False(t, mysql.HasNotNullFlag(colB.Flag)) + tk.MustExec("insert into t3 set aa = 3, dd = 5") + tk.MustQuery("select b from t3").Check(testkit.Rows("a", "b", "c")) + // for timestamp + tk.MustExec("alter table t3 add column c timestamp not null") + tk.MustExec("alter table t3 change c c timestamp null default '2017-02-11' comment 'col c comment' on update current_timestamp") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) + require.NoError(t, err) + tblInfo = tbl.Meta() + colC := tblInfo.Columns[3] + require.Equal(t, "col c comment", colC.Comment) + require.False(t, mysql.HasNotNullFlag(colC.Flag)) + // for enum + tk.MustExec("alter table t3 add column en enum('a', 'b', 'c') not null default 'a'") + // https://github.com/pingcap/tidb/issues/23488 + // if there is a prefix index on the varchar column, then we can change it to text + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (k char(10), v int, INDEX(k(7)));") + tk.MustExec("alter table t change column k k tinytext") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + // for failing tests + sql := "alter table t3 change aa a bigint default ''" + tk.MustGetErrCode(sql, errno.ErrInvalidDefault) + sql = "alter table t3 change a testx.t3.aa bigint" + tk.MustGetErrCode(sql, errno.ErrWrongDBName) + sql = "alter table t3 change t.a aa bigint" + tk.MustGetErrCode(sql, errno.ErrWrongTableName) + tk.MustExec("create table t4 (c1 int, c2 int, c3 int default 1, index (c1));") + tk.MustExec("insert into t4(c2) values (null);") + err = tk.ExecToErr("alter table t4 change c1 a1 int not null;") + require.EqualError(t, err, "[ddl:1265]Data truncated for column 'a1' at row 1") + sql = "alter table t4 change c2 a bigint not null;" + tk.MustGetErrCode(sql, mysql.WarnDataTruncated) + sql = "alter table t3 modify en enum('a', 'z', 'b', 'c') not null default 'a'" + tk.MustExec(sql) + // Rename to an existing column. + tk.MustExec("alter table t3 add column a bigint") + sql = "alter table t3 change aa a bigint" + tk.MustGetErrCode(sql, errno.ErrDupFieldName) + // https://github.com/pingcap/tidb/issues/23488 + tk.MustExec("drop table if exists t5") + tk.MustExec("create table t5 (k char(10) primary key, v int)") + sql = "alter table t5 change column k k tinytext;" + tk.MustGetErrCode(sql, mysql.ErrBlobKeyWithoutLength) + tk.MustExec("drop table t5") + tk.MustExec("drop table if exists t5") + tk.MustExec("create table t5 (k char(10), v int, INDEX(k))") + sql = "alter table t5 change column k k tinytext;" + tk.MustGetErrCode(sql, mysql.ErrBlobKeyWithoutLength) + tk.MustExec("drop table t5") + tk.MustExec("drop table t3") +} + +func TestRenameColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + assertColNames := func(tableName string, colNames ...string) { + cols := external.GetTableByName(t, tk, "test", tableName).Cols() + require.Equal(t, len(colNames), len(cols)) + for i := range cols { + require.Equal(t, strings.ToLower(colNames[i]), cols[i].Name.L) + } + } + + tk.MustExec("create table test_rename_column (id int not null primary key auto_increment, col1 int)") + tk.MustExec("alter table test_rename_column rename column col1 to col1") + assertColNames("test_rename_column", "id", "col1") + tk.MustExec("alter table test_rename_column rename column col1 to col2") + assertColNames("test_rename_column", "id", "col2") + + // Test renaming non-exist columns. + tk.MustGetErrCode("alter table test_rename_column rename column non_exist_col to col3", errno.ErrBadField) + + // Test renaming to an exist column. + tk.MustGetErrCode("alter table test_rename_column rename column col2 to id", errno.ErrDupFieldName) + + // Test renaming the column with foreign key. + tk.MustExec("drop table test_rename_column") + tk.MustExec("create table test_rename_column_base (base int)") + tk.MustExec("create table test_rename_column (col int, foreign key (col) references test_rename_column_base(base))") + + tk.MustGetErrCode("alter table test_rename_column rename column col to col1", errno.ErrFKIncompatibleColumns) + + tk.MustExec("drop table test_rename_column_base") + + // Test renaming generated columns. + tk.MustExec("drop table test_rename_column") + tk.MustExec("create table test_rename_column (id int, col1 int generated always as (id + 1))") + + tk.MustExec("alter table test_rename_column rename column col1 to col2") + assertColNames("test_rename_column", "id", "col2") + tk.MustExec("alter table test_rename_column rename column col2 to col1") + assertColNames("test_rename_column", "id", "col1") + tk.MustGetErrCode("alter table test_rename_column rename column id to id1", errno.ErrDependentByGeneratedColumn) + + // Test renaming view columns. + tk.MustExec("drop table test_rename_column") + tk.MustExec("create table test_rename_column (id int, col1 int)") + tk.MustExec("create view test_rename_column_view as select * from test_rename_column") + + tk.MustExec("alter table test_rename_column rename column col1 to col2") + tk.MustGetErrCode("select * from test_rename_column_view", errno.ErrViewInvalid) + + tk.MustExec("drop view test_rename_column_view") + tk.MustExec("drop table test_rename_column") +} + +// TestCancelDropColumn tests cancel ddl job which type is drop column. +func TestCancelDropColumn(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table test_drop_column(c1 int, c2 int)") + defer tk.MustExec("drop table test_drop_column;") + testCases := []struct { + needAddColumn bool + jobState model.JobState + JobSchemaState model.SchemaState + cancelSucc bool + }{ + {true, model.JobStateQueueing, model.StateNone, true}, + {false, model.JobStateRunning, model.StateWriteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteReorganization, false}, + } + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + var jobID int64 + testCase := &testCases[0] + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type == model.ActionDropColumn && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { + jobIDs := []int64{job.ID} + jobID = job.ID + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.TODO()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + + originalHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + for i := range testCases { + testCase = &testCases[i] + if testCase.needAddColumn { + tk.MustExec("alter table test_drop_column add column c3 int") + tk.MustExec("alter table test_drop_column add index idx_c3(c3)") + } + + err := tk.ExecToErr("alter table test_drop_column drop column c3") + var col1 *table.Column + var idx1 table.Index + tbl := external.GetTableByName(t, tk, "test", "test_drop_column") + for _, col := range tbl.Cols() { + if strings.EqualFold(col.Name.L, "c3") { + col1 = col + break + } + } + for _, idx := range tbl.Indices() { + if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { + idx1 = idx + break + } + } + if testCase.cancelSucc { + require.NoError(t, checkErr) + require.NotNil(t, col1) + require.Equal(t, "c3", col1.Name.L) + require.NotNil(t, idx1) + require.Equal(t, "idx_c3", idx1.Meta().Name.L) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + } else { + require.Nil(t, col1) + require.Nil(t, col1) + require.NoError(t, err) + require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) + } + } + dom.DDL().SetHook(originalHook) + tk.MustExec("alter table test_drop_column add column c3 int") + tk.MustExec("alter table test_drop_column drop column c3") +} + +// TestCancelDropColumns tests cancel ddl job which type is drop multi-columns. +func TestCancelDropColumns(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table test_drop_column(c1 int, c2 int)") + defer tk.MustExec("drop table test_drop_column;") + testCases := []struct { + needAddColumn bool + jobState model.JobState + JobSchemaState model.SchemaState + cancelSucc bool + }{ + {true, model.JobStateQueueing, model.StateNone, true}, + {false, model.JobStateRunning, model.StateWriteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteReorganization, false}, + } + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + var jobID int64 + testCase := &testCases[0] + hook.OnJobRunBeforeExported = func(job *model.Job) { + isDropColTp := job.Type == model.ActionMultiSchemaChange && + job.MultiSchemaInfo.SubJobs[0].Type == model.ActionDropColumn + if isDropColTp && job.MultiSchemaInfo.SubJobs[0].State == testCase.jobState && + job.MultiSchemaInfo.SubJobs[0].SchemaState == testCase.JobSchemaState { + jobIDs := []int64{job.ID} + jobID = job.ID + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.TODO()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + + originalHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + for i := range testCases { + testCase = &testCases[i] + if testCase.needAddColumn { + tk.MustExec("alter table test_drop_column add column c3 int, add column c4 int") + tk.MustExec("alter table test_drop_column add index idx_c3(c3)") + } + err := tk.ExecToErr("alter table test_drop_column drop column c3, drop column c4") + tbl := external.GetTableByName(t, tk, "test", "test_drop_column") + col3 := table.FindCol(tbl.Cols(), "c3") + col4 := table.FindCol(tbl.Cols(), "c4") + var idx3 table.Index + for _, idx := range tbl.Indices() { + if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { + idx3 = idx + break + } + } + if testCase.cancelSucc { + require.NoError(t, checkErr) + require.NotNil(t, col3) + require.NotNil(t, col4) + require.NotNil(t, idx3) + require.Equal(t, "c3", col3.Name.L) + require.Equal(t, "c4", col4.Name.L) + require.Equal(t, "idx_c3", idx3.Meta().Name.L) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + } else { + require.Nil(t, col3) + require.Nil(t, col4) + require.Nil(t, idx3) + require.NoError(t, err) + require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) + } + } + dom.DDL().SetHook(originalHook) + tk.MustExec("alter table test_drop_column add column c3 int, add column c4 int") + tk.MustExec("alter table test_drop_column drop column c3, drop column c4") +} + +func TestVirtualColumnDDL(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`create global temporary table test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored) on commit delete rows;`) + is := tk.Session().(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_gv_ddl")) + require.NoError(t, err) + testCases := []struct { + generatedExprString string + generatedStored bool + }{ + {"", false}, + {"`a` + 8", false}, + {"`b` + 2", true}, + } + for i, column := range tbl.Meta().Columns { + require.Equal(t, testCases[i].generatedExprString, column.GeneratedExprString) + require.Equal(t, testCases[i].generatedStored, column.GeneratedStored) + } + result := tk.MustQuery(`DESC test_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) + tk.MustExec("begin;") + tk.MustExec("insert into test_gv_ddl values (1, default, default)") + tk.MustQuery("select * from test_gv_ddl").Check(testkit.Rows("1 9 11")) + tk.MustExec("commit") + + // for local temporary table + tk.MustExec(`create temporary table test_local_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored);`) + is = tk.Session().(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_local_gv_ddl")) + require.NoError(t, err) + for i, column := range tbl.Meta().Columns { + require.Equal(t, testCases[i].generatedExprString, column.GeneratedExprString) + require.Equal(t, testCases[i].generatedStored, column.GeneratedStored) + } + result = tk.MustQuery(`DESC test_local_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) + tk.MustExec("begin;") + tk.MustExec("insert into test_local_gv_ddl values (1, default, default)") + tk.MustQuery("select * from test_local_gv_ddl").Check(testkit.Rows("1 9 11")) + tk.MustExec("commit") + tk.MustQuery("select * from test_local_gv_ddl").Check(testkit.Rows("1 9 11")) +} + +func TestGeneratedColumnDDL(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // Check create table with virtual and stored generated columns. + tk.MustExec(`CREATE TABLE test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored)`) + + // Check desc table with virtual and stored generated columns. + result := tk.MustQuery(`DESC test_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) + + // Check show create table with virtual and stored generated columns. + result = tk.MustQuery(`show create table test_gv_ddl`) + result.Check(testkit.Rows( + "test_gv_ddl CREATE TABLE `test_gv_ddl` (\n `a` int(11) DEFAULT NULL,\n `b` int(11) GENERATED ALWAYS AS (`a` + 8) VIRTUAL,\n `c` int(11) GENERATED ALWAYS AS (`b` + 2) STORED\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", + )) + + // Check generated expression with blanks. + tk.MustExec("create table table_with_gen_col_blanks (a int, b char(20) as (cast( \r\n\t a \r\n\tas char)), c int as (a+100))") + result = tk.MustQuery(`show create table table_with_gen_col_blanks`) + result.Check(testkit.Rows("table_with_gen_col_blanks CREATE TABLE `table_with_gen_col_blanks` (\n" + + " `a` int(11) DEFAULT NULL,\n" + + " `b` char(20) GENERATED ALWAYS AS (cast(`a` as char)) VIRTUAL,\n" + + " `c` int(11) GENERATED ALWAYS AS (`a` + 100) VIRTUAL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // Check generated expression with charset latin1 ("latin1" != mysql.DefaultCharset). + tk.MustExec("create table table_with_gen_col_latin1 (a int, b char(20) as (cast( \r\n\t a \r\n\tas char charset latin1)), c int as (a+100))") + result = tk.MustQuery(`show create table table_with_gen_col_latin1`) + result.Check(testkit.Rows("table_with_gen_col_latin1 CREATE TABLE `table_with_gen_col_latin1` (\n" + + " `a` int(11) DEFAULT NULL,\n" + + " `b` char(20) GENERATED ALWAYS AS (cast(`a` as char charset latin1)) VIRTUAL,\n" + + " `c` int(11) GENERATED ALWAYS AS (`a` + 100) VIRTUAL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // Check generated expression with string (issue 9457). + tk.MustExec("create table table_with_gen_col_string (first_name varchar(10), last_name varchar(10), full_name varchar(255) AS (CONCAT(first_name,' ',last_name)))") + result = tk.MustQuery(`show create table table_with_gen_col_string`) + result.Check(testkit.Rows("table_with_gen_col_string CREATE TABLE `table_with_gen_col_string` (\n" + + " `first_name` varchar(10) DEFAULT NULL,\n" + + " `last_name` varchar(10) DEFAULT NULL,\n" + + " `full_name` varchar(255) GENERATED ALWAYS AS (concat(`first_name`, _utf8mb4' ', `last_name`)) VIRTUAL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + tk.MustExec("alter table table_with_gen_col_string modify column full_name varchar(255) GENERATED ALWAYS AS (CONCAT(last_name,' ' ,first_name) ) VIRTUAL") + result = tk.MustQuery(`show create table table_with_gen_col_string`) + result.Check(testkit.Rows("table_with_gen_col_string CREATE TABLE `table_with_gen_col_string` (\n" + + " `first_name` varchar(10) DEFAULT NULL,\n" + + " `last_name` varchar(10) DEFAULT NULL,\n" + + " `full_name` varchar(255) GENERATED ALWAYS AS (concat(`last_name`, _utf8mb4' ', `first_name`)) VIRTUAL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // Test incorrect parameter count. + tk.MustGetErrCode("create table test_gv_incorrect_pc(a double, b int as (lower(a, 2)))", errno.ErrWrongParamcountToNativeFct) + tk.MustGetErrCode("create table test_gv_incorrect_pc(a double, b int as (lower(a, 2)) stored)", errno.ErrWrongParamcountToNativeFct) + + genExprTests := []struct { + stmt string + err int + }{ + // Drop/rename columns dependent by other column. + {`alter table test_gv_ddl drop column a`, errno.ErrDependentByGeneratedColumn}, + {`alter table test_gv_ddl change column a anew int`, errno.ErrBadField}, + + // Modify/change stored status of generated columns. + {`alter table test_gv_ddl modify column b bigint`, errno.ErrUnsupportedOnGeneratedColumn}, + {`alter table test_gv_ddl change column c cnew bigint as (a+100)`, errno.ErrUnsupportedOnGeneratedColumn}, + + // Modify/change generated columns breaking prior. + {`alter table test_gv_ddl modify column b int as (c+100)`, errno.ErrGeneratedColumnNonPrior}, + {`alter table test_gv_ddl change column b bnew int as (c+100)`, errno.ErrGeneratedColumnNonPrior}, + + // Refer not exist columns in generation expression. + {`create table test_gv_ddl_bad (a int, b int as (c+8))`, errno.ErrBadField}, + + // Refer generated columns non prior. + {`create table test_gv_ddl_bad (a int, b int as (c+1), c int as (a+1))`, errno.ErrGeneratedColumnNonPrior}, + + // Virtual generated columns cannot be primary key. + {`create table test_gv_ddl_bad (a int, b int, c int as (a+b) primary key)`, errno.ErrUnsupportedOnGeneratedColumn}, + {`create table test_gv_ddl_bad (a int, b int, c int as (a+b), primary key(c))`, errno.ErrUnsupportedOnGeneratedColumn}, + {`create table test_gv_ddl_bad (a int, b int, c int as (a+b), primary key(a, c))`, errno.ErrUnsupportedOnGeneratedColumn}, + + // Add stored generated column through alter table. + {`alter table test_gv_ddl add column d int as (b+2) stored`, errno.ErrUnsupportedOnGeneratedColumn}, + {`alter table test_gv_ddl modify column b int as (a + 8) stored`, errno.ErrUnsupportedOnGeneratedColumn}, + + // Add generated column with incorrect parameter count. + {`alter table test_gv_ddl add column z int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, + {`alter table test_gv_ddl add column z int as (lower(a, 2)) stored`, errno.ErrWrongParamcountToNativeFct}, + + // Modify generated column with incorrect parameter count. + {`alter table test_gv_ddl modify column b int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, + {`alter table test_gv_ddl change column b b int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, + } + for _, tt := range genExprTests { + tk.MustGetErrCode(tt.stmt, tt.err) + } + + // Check alter table modify/change generated column. + modStoredColErrMsg := "[ddl:3106]'modifying a stored column' is not supported for generated columns." + tk.MustGetErrMsg(`alter table test_gv_ddl modify column c bigint as (b+200) stored`, modStoredColErrMsg) + + result = tk.MustQuery(`DESC test_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) + + tk.MustExec(`alter table test_gv_ddl change column b b bigint as (a+100) virtual`) + result = tk.MustQuery(`DESC test_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b bigint(20) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) + + tk.MustExec(`alter table test_gv_ddl change column c cnew bigint`) + result = tk.MustQuery(`DESC test_gv_ddl`) + result.Check(testkit.Rows(`a int(11) YES `, `b bigint(20) YES VIRTUAL GENERATED`, `cnew bigint(20) YES `)) + + // Test generated column `\\`. + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t(c0 TEXT AS ('\\\\'));") + tk.MustExec("insert into t values ()") + tk.MustQuery("select * from t").Check(testkit.Rows("\\")) + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t(c0 TEXT AS ('a\\\\b\\\\c\\\\'))") + tk.MustExec("insert into t values ()") + tk.MustQuery("select * from t").Check(testkit.Rows("a\\b\\c\\")) +} + +func TestColumnModifyingDefinition(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table test2 (c1 int, c2 int, c3 int default 1, index (c1));") + tk.MustExec("alter table test2 change c2 a int not null;") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test2")) + require.NoError(t, err) + var c2 *table.Column + for _, col := range tbl.Cols() { + if col.Name.L == "a" { + c2 = col + } + } + require.True(t, mysql.HasNotNullFlag(c2.Flag)) + + tk.MustExec("drop table if exists test2;") + tk.MustExec("create table test2 (c1 int, c2 int, c3 int default 1, index (c1));") + tk.MustExec("insert into test2(c2) values (null);") + tk.MustGetErrMsg("alter table test2 change c2 a int not null", "[ddl:1265]Data truncated for column 'a' at row 1") + tk.MustGetErrCode("alter table test2 change c1 a1 bigint not null;", mysql.WarnDataTruncated) +} + +func TestTransactionWithWriteOnlyColumn(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int key);") + + transactions := [][]string{ + { + "begin", + "insert into t1 set a=1", + "update t1 set a=2 where a=1", + "commit", + }, + } + + hook := &ddl.TestDDLCallback{Do: dom} + var checkErr error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if checkErr != nil { + return + } + switch job.SchemaState { + case model.StateWriteOnly: + default: + return + } + // do transaction. + for _, transaction := range transactions { + for _, sql := range transaction { + if _, checkErr = tk.Exec(sql); checkErr != nil { + checkErr = errors.Errorf("err: %s, sql: %s, job schema state: %s", checkErr.Error(), sql, job.SchemaState) + return + } + } + } + } + dom.DDL().SetHook(hook) + done := make(chan error, 1) + // test transaction on add column. + go backgroundExec(store, "alter table t1 add column c int not null", done) + err := <-done + require.NoError(t, err) + require.NoError(t, checkErr) + tk.MustQuery("select a from t1").Check(testkit.Rows("2")) + tk.MustExec("delete from t1") + + // test transaction on drop column. + go backgroundExec(store, "alter table t1 drop column c", done) + err = <-done + require.NoError(t, err) + require.NoError(t, checkErr) + tk.MustQuery("select a from t1").Check(testkit.Rows("2")) +} + +func TestColumnCheck(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists column_check") + tk.MustExec("create table column_check (pk int primary key, a int check (a > 1))") + defer tk.MustExec("drop table if exists column_check") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8231|CONSTRAINT CHECK is not supported")) +} + +func TestModifyGeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + modIdxColErrMsg := "[ddl:3106]'modifying an indexed column' is not supported for generated columns." + modStoredColErrMsg := "[ddl:3106]'modifying a stored column' is not supported for generated columns." + + // Modify column with single-col-index. + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1 (a int, b int as (a+1), index idx(b));") + tk.MustExec("insert into t1 set a=1;") + tk.MustGetErrMsg("alter table t1 modify column b int as (a+2);", modIdxColErrMsg) + tk.MustExec("drop index idx on t1;") + tk.MustExec("alter table t1 modify b int as (a+2);") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 3")) + + // Modify column with multi-col-index. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int as (a+1), index idx(a, b));") + tk.MustExec("insert into t1 set a=1;") + tk.MustGetErrMsg("alter table t1 modify column b int as (a+2);", modIdxColErrMsg) + tk.MustExec("drop index idx on t1;") + tk.MustExec("alter table t1 modify b int as (a+2);") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 3")) + + // Modify column with stored status to a different expression. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int as (a+1) stored);") + tk.MustExec("insert into t1 set a=1;") + tk.MustGetErrMsg("alter table t1 modify column b int as (a+2) stored;", modStoredColErrMsg) + + // Modify column with stored status to the same expression. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int as (a+1) stored);") + tk.MustExec("insert into t1 set a=1;") + tk.MustExec("alter table t1 modify column b bigint as (a+1) stored;") + tk.MustExec("alter table t1 modify column b bigint as (a + 1) stored;") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) + + // Modify column with index to the same expression. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int as (a+1), index idx(b));") + tk.MustExec("insert into t1 set a=1;") + tk.MustExec("alter table t1 modify column b bigint as (a+1);") + tk.MustExec("alter table t1 modify column b bigint as (a + 1);") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) + + // Modify column from non-generated to stored generated. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int);") + tk.MustGetErrMsg("alter table t1 modify column b bigint as (a+1) stored;", modStoredColErrMsg) + + // Modify column from stored generated to non-generated. + tk.MustExec("drop table t1;") + tk.MustExec("create table t1 (a int, b int as (a+1) stored);") + tk.MustExec("insert into t1 set a=1;") + tk.MustExec("alter table t1 modify column b int;") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) +} + +func TestCheckColumnDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists text_default_text;") + tk.MustGetErrCode("create table text_default_text(c1 text not null default '');", errno.ErrBlobCantHaveDefault) + tk.MustGetErrCode("create table text_default_text(c1 text not null default 'scds');", errno.ErrBlobCantHaveDefault) + + tk.MustExec("drop table if exists text_default_json;") + tk.MustGetErrCode("create table text_default_json(c1 json not null default '');", errno.ErrBlobCantHaveDefault) + tk.MustGetErrCode("create table text_default_json(c1 json not null default 'dfew555');", errno.ErrBlobCantHaveDefault) + + tk.MustExec("drop table if exists text_default_blob;") + tk.MustGetErrCode("create table text_default_blob(c1 blob not null default '');", errno.ErrBlobCantHaveDefault) + tk.MustGetErrCode("create table text_default_blob(c1 blob not null default 'scds54');", errno.ErrBlobCantHaveDefault) + + tk.MustExec("set sql_mode='';") + tk.MustExec("create table text_default_text(c1 text not null default '');") + tk.MustQuery(`show create table text_default_text`).Check(testkit.RowsWithSep("|", + "text_default_text CREATE TABLE `text_default_text` (\n"+ + " `c1` text NOT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", + )) + is := domain.GetDomain(tk.Session()).InfoSchema() + tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_text")) + require.NoError(t, err) + require.Empty(t, tblInfo.Meta().Columns[0].DefaultValue) + + tk.MustExec("create table text_default_blob(c1 blob not null default '');") + tk.MustQuery(`show create table text_default_blob`).Check(testkit.RowsWithSep("|", + "text_default_blob CREATE TABLE `text_default_blob` (\n"+ + " `c1` blob NOT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", + )) + is = domain.GetDomain(tk.Session()).InfoSchema() + tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_blob")) + require.NoError(t, err) + require.Empty(t, tblInfo.Meta().Columns[0].DefaultValue) + + tk.MustExec("create table text_default_json(c1 json not null default '');") + tk.MustQuery(`show create table text_default_json`).Check(testkit.RowsWithSep("|", + "text_default_json CREATE TABLE `text_default_json` (\n"+ + " `c1` json NOT NULL DEFAULT 'null'\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", + )) + is = domain.GetDomain(tk.Session()).InfoSchema() + tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_json")) + require.NoError(t, err) + require.Equal(t, "null", tblInfo.Meta().Columns[0].DefaultValue) +} + +func TestCheckConvertToCharacter(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a varchar(10) charset binary);") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8 collate utf8_bin", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8mb4 collate utf8mb4_bin", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify column a varchar(10) charset latin1 collate latin1_bin", errno.ErrUnsupportedDDLOperation) + require.Equal(t, "binary", tbl.Cols()[0].Charset) +} + +func TestAddMultiColumnsIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, columnModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists tidb;") + tk.MustExec("create database tidb;") + tk.MustExec("use tidb;") + tk.MustExec("create table tidb.test (a int auto_increment primary key, b int);") + tk.MustExec("insert tidb.test values (1, 1);") + tk.MustExec("update tidb.test set b = b + 1 where a = 1;") + tk.MustExec("insert into tidb.test values (2, 2);") + // Test that the b value is nil. + tk.MustExec("insert into tidb.test (a) values (3);") + tk.MustExec("insert into tidb.test values (4, 4);") + // Test that the b value is nil again. + tk.MustExec("insert into tidb.test (a) values (5);") + tk.MustExec("insert tidb.test values (6, 6);") + tk.MustExec("alter table tidb.test add index idx1 (a, b);") + tk.MustExec("admin check table test") +} + +// For issue #31735. +func TestAddGeneratedColumnAndInsert(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (a int, unique kye(a))") + tk.MustExec("insert into t1 value (1), (10)") + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + + d := dom.DDL() + hook := &ddl.TestDDLCallback{Do: dom} + ctx := mock.NewContext() + ctx.Store = store + times := 0 + var checkErr error + hook.OnJobUpdatedExported = func(job *model.Job) { + if checkErr != nil { + return + } + switch job.SchemaState { + case model.StateDeleteOnly: + _, checkErr = tk1.Exec("insert into t1 values (1) on duplicate key update a=a+1") + if checkErr == nil { + _, checkErr = tk1.Exec("replace into t1 values (2)") + } + case model.StateWriteOnly: + _, checkErr = tk1.Exec("insert into t1 values (2) on duplicate key update a=a+1") + if checkErr == nil { + _, checkErr = tk1.Exec("replace into t1 values (3)") + } + case model.StateWriteReorganization: + if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 { + _, checkErr = tk1.Exec("insert into t1 values (3) on duplicate key update a=a+1") + if checkErr == nil { + _, checkErr = tk1.Exec("replace into t1 values (4)") + } + times++ + } + } + } + d.SetHook(hook) + + tk.MustExec("alter table t1 add column gc int as ((a+1))") + tk.MustQuery("select * from t1 order by a").Check(testkit.Rows("4 5", "10 11")) + require.NoError(t, checkErr) +} + +func TestColumnTypeChangeGenUniqueChangingName(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + hook := &ddl.TestDDLCallback{} + var checkErr error + assertChangingColName := "_col$_c2_0" + assertChangingIdxName := "_idx$_idx_0" + hook.OnJobUpdatedExported = func(job *model.Job) { + if job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn { + var ( + newCol *model.ColumnInfo + oldColName *model.CIStr + modifyColumnTp byte + updatedAutoRandomBits uint64 + changingCol *model.ColumnInfo + changingIdxs []*model.IndexInfo + ) + pos := &ast.ColumnPosition{} + err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) + if err != nil { + checkErr = err + return + } + if changingCol.Name.L != assertChangingColName { + checkErr = errors.New("changing column name is incorrect") + } else if changingIdxs[0].Name.L != assertChangingIdxName { + checkErr = errors.New("changing index name is incorrect") + } + } + } + d := dom.DDL() + d.SetHook(hook) + + tk.MustExec("create table if not exists t(c1 varchar(256), c2 bigint, `_col$_c2` varchar(10), unique _idx$_idx(c1), unique idx(c2));") + tk.MustExec("alter table test.t change column c2 cC2 tinyint after `_col$_c2`") + require.NoError(t, checkErr) + + tbl := external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().Columns, 3) + require.Equal(t, "c1", tbl.Meta().Columns[0].Name.O) + require.Equal(t, 0, tbl.Meta().Columns[0].Offset) + require.Equal(t, "_col$_c2", tbl.Meta().Columns[1].Name.O) + require.Equal(t, 1, tbl.Meta().Columns[1].Offset) + require.Equal(t, "cC2", tbl.Meta().Columns[2].Name.O) + require.Equal(t, 2, tbl.Meta().Columns[2].Offset) + + require.Len(t, tbl.Meta().Indices, 2) + require.Equal(t, "_idx$_idx", tbl.Meta().Indices[0].Name.O) + require.Equal(t, "idx", tbl.Meta().Indices[1].Name.O) + + require.Len(t, tbl.Meta().Indices[0].Columns, 1) + require.Equal(t, "c1", tbl.Meta().Indices[0].Columns[0].Name.O) + require.Equal(t, 0, tbl.Meta().Indices[0].Columns[0].Offset) + + require.Len(t, tbl.Meta().Indices[1].Columns, 1) + require.Equal(t, "cC2", tbl.Meta().Indices[1].Columns[0].Name.O) + require.Equal(t, 2, tbl.Meta().Indices[1].Columns[0].Offset) + + assertChangingColName1 := "_col$__col$_c1_1" + assertChangingColName2 := "_col$__col$__col$_c1_0_1" + query1 := "alter table t modify column _col$_c1 tinyint" + query2 := "alter table t modify column _col$__col$_c1_0 tinyint" + hook.OnJobUpdatedExported = func(job *model.Job) { + if (job.Query == query1 || job.Query == query2) && job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn { + var ( + newCol *model.ColumnInfo + oldColName *model.CIStr + modifyColumnTp byte + updatedAutoRandomBits uint64 + changingCol *model.ColumnInfo + changingIdxs []*model.IndexInfo + ) + pos := &ast.ColumnPosition{} + err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) + if err != nil { + checkErr = err + return + } + if job.Query == query1 && changingCol.Name.L != assertChangingColName1 { + checkErr = errors.New("changing column name is incorrect") + } + if job.Query == query2 && changingCol.Name.L != assertChangingColName2 { + checkErr = errors.New("changing column name is incorrect") + } + } + } + d.SetHook(hook) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table if not exists t(c1 bigint, _col$_c1 bigint, _col$__col$_c1_0 bigint, _col$__col$__col$_c1_0_0 bigint)") + tk.MustExec("alter table t modify column c1 tinyint") + tk.MustExec("alter table t modify column _col$_c1 tinyint") + require.NoError(t, checkErr) + tk.MustExec("alter table t modify column _col$__col$_c1_0 tinyint") + require.NoError(t, checkErr) + tk.MustExec("alter table t change column _col$__col$__col$_c1_0_0 _col$__col$__col$_c1_0_0 tinyint") + + tbl = external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().Columns, 4) + require.Equal(t, "c1", tbl.Meta().Columns[0].Name.O) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[0].Tp) + require.Equal(t, 0, tbl.Meta().Columns[0].Offset) + require.Equal(t, "_col$_c1", tbl.Meta().Columns[1].Name.O) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[1].Tp) + require.Equal(t, 1, tbl.Meta().Columns[1].Offset) + require.Equal(t, "_col$__col$_c1_0", tbl.Meta().Columns[2].Name.O) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[2].Tp) + require.Equal(t, 2, tbl.Meta().Columns[2].Offset) + require.Equal(t, "_col$__col$__col$_c1_0_0", tbl.Meta().Columns[3].Name.O) + require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[3].Tp) + require.Equal(t, 3, tbl.Meta().Columns[3].Offset) + + tk.MustExec("drop table if exists t") +} + +func TestWriteReorgForColumnTypeChangeOnAmendTxn(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("set global tidb_enable_amend_pessimistic_txn = ON") + defer tk.MustExec("set global tidb_enable_amend_pessimistic_txn = OFF") + + d := dom.DDL() + testInsertOnModifyColumn := func(sql string, startColState, commitColState model.SchemaState, retStrs []string, retErr error) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") + tk.MustExec("insert into t1 values (20, 20, 20);") + + var checkErr error + tk1 := testkit.NewTestKit(t, store) + defer func() { + if tk1.Session() != nil { + tk1.Session().Close() + } + }() + hook := &ddl.TestDDLCallback{Do: dom} + times := 0 + hook.OnJobUpdatedExported = func(job *model.Job) { + if job.Type != model.ActionModifyColumn || checkErr != nil || + (job.SchemaState != startColState && job.SchemaState != commitColState) { + return + } + + if job.SchemaState == startColState { + tk1.MustExec("use test") + tk1.MustExec("begin pessimistic;") + tk1.MustExec("insert into t1 values(101, 102, 103)") + return + } + if times == 0 { + _, checkErr = tk1.Exec("commit;") + } + times++ + } + d.SetHook(hook) + + tk.MustExec(sql) + if retErr == nil { + require.NoError(t, checkErr) + } else { + require.Error(t, checkErr) + require.Contains(t, checkErr.Error(), retErr.Error()) + } + tk.MustQuery("select * from t1").Check(testkit.Rows(retStrs...)) + tk.MustExec("admin check table t1") + } + + // Testing it needs reorg data. + ddlStatement := "alter table t1 change column c2 cc smallint;" + testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) + + // Testing it needs not reorg data. This case only have two states: none, public. + ddlStatement = "alter table t1 change column c2 cc bigint;" + testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, nil) + testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, nil) + testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20", "101 102 103"}, nil) + testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, nil) +} diff --git a/ddl/column_test.go b/ddl/column_test.go index c10696b1806cf..90e6e14bdab66 100644 --- a/ddl/column_test.go +++ b/ddl/column_test.go @@ -12,339 +12,254 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" "fmt" "reflect" + "strconv" "sync" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" - "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser" - "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testColumnSuite{}) - -type testColumnSuite struct { - store kv.Storage - dbInfo *model.DBInfo -} - -func (s *testColumnSuite) SetUpSuite(c *C) { - s.store = testCreateStore(c, "test_column") - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - - s.dbInfo, err = testSchemaInfo(d, "test_column") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, s.dbInfo) - c.Assert(d.Stop(), IsNil) -} - -func (s *testColumnSuite) TearDownSuite(c *C) { - err := s.store.Close() - c.Assert(err, IsNil) -} - -func buildCreateColumnJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string, - pos *ast.ColumnPosition, defaultValue interface{}) *model.Job { - col := &model.ColumnInfo{ - Name: model.NewCIStr(colName), - Offset: len(tblInfo.Columns), - DefaultValue: defaultValue, - OriginDefaultValue: defaultValue, - } - col.ID = allocateColumnID(tblInfo) - col.FieldType = *types.NewFieldType(mysql.TypeLong) - - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddColumn, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{col, pos, 0}, - } - return job +func testCreateColumn(tk *testkit.TestKit, t *testing.T, ctx sessionctx.Context, tblID int64, + colName string, pos string, defaultValue interface{}, dom *domain.Domain) int64 { + sql := fmt.Sprintf("alter table t1 add column %s int ", colName) + if defaultValue != nil { + sql += fmt.Sprintf("default %v ", defaultValue) + } + sql += pos + tk.MustExec(sql) + idi, _ := strconv.Atoi(tk.MustQuery("admin show ddl jobs 1;").Rows()[0][0].(string)) + id := int64(idi) + v := getSchemaVer(t, ctx) + require.NoError(t, dom.Reload()) + tblInfo, exist := dom.InfoSchema().TableByID(tblID) + require.True(t, exist) + checkHistoryJobArgs(t, ctx, id, &historyJobArgs{ver: v, tbl: tblInfo.Meta()}) + return id } -func testCreateColumn(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, - colName string, pos *ast.ColumnPosition, defaultValue interface{}) *model.Job { - job := buildCreateColumnJob(dbInfo, tblInfo, colName, pos, defaultValue) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func buildCreateColumnsJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colNames []string, - positions []*ast.ColumnPosition, defaultValue interface{}) *model.Job { - colInfos := make([]*model.ColumnInfo, len(colNames)) - offsets := make([]int, len(colNames)) - ifNotExists := make([]bool, len(colNames)) - for i, colName := range colNames { - col := &model.ColumnInfo{ - Name: model.NewCIStr(colName), - Offset: len(tblInfo.Columns), - DefaultValue: defaultValue, - OriginDefaultValue: defaultValue, - } - col.ID = allocateColumnID(tblInfo) - col.FieldType = *types.NewFieldType(mysql.TypeLong) - colInfos[i] = col +func testDropColumnInternal(tk *testkit.TestKit, t *testing.T, ctx sessionctx.Context, tblID int64, colName string, isError bool, dom *domain.Domain) int64 { + sql := fmt.Sprintf("alter table t1 drop column %s ", colName) + _, err := tk.Exec(sql) + if isError { + require.Error(t, err) + } else { + require.NoError(t, err) } - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddColumns, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{colInfos, positions, offsets, ifNotExists}, - } - return job + idi, _ := strconv.Atoi(tk.MustQuery("admin show ddl jobs 1;").Rows()[0][0].(string)) + id := int64(idi) + v := getSchemaVer(t, ctx) + require.NoError(t, dom.Reload()) + tblInfo, exist := dom.InfoSchema().TableByID(tblID) + require.True(t, exist) + checkHistoryJobArgs(t, ctx, id, &historyJobArgs{ver: v, tbl: tblInfo.Meta()}) + return id } -func testCreateColumns(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, - colNames []string, positions []*ast.ColumnPosition, defaultValue interface{}) *model.Job { - job := buildCreateColumnsJob(dbInfo, tblInfo, colNames, positions, defaultValue) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} +func testDropTable(tk *testkit.TestKit, t *testing.T, tblName string, dom *domain.Domain) int64 { + sql := fmt.Sprintf("drop table %s ", tblName) + tk.MustExec(sql) -func buildDropColumnJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropColumn, - BinlogInfo: &model.HistoryInfo{}, - MultiSchemaInfo: &model.MultiSchemaInfo{}, - Args: []interface{}{model.NewCIStr(colName)}, - } + idi, _ := strconv.Atoi(tk.MustQuery("admin show ddl jobs 1;").Rows()[0][0].(string)) + id := int64(idi) + require.NoError(t, dom.Reload()) + _, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr(tblName)) + require.Error(t, err) + return id } -func testDropColumn(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string, isError bool) *model.Job { - job := buildDropColumnJob(dbInfo, tblInfo, colName) - err := d.doDDLJob(ctx, job) - if isError { - c.Assert(err, NotNil) - return nil - } - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job +func testCreateIndex(tk *testkit.TestKit, t *testing.T, ctx sessionctx.Context, tblID int64, unique bool, indexName string, colName string, dom *domain.Domain) int64 { + un := "" + if unique { + un = "unique" + } + sql := fmt.Sprintf("alter table t1 add %s index %s(%s)", un, indexName, colName) + tk.MustExec(sql) + + idi, _ := strconv.Atoi(tk.MustQuery("admin show ddl jobs 1;").Rows()[0][0].(string)) + id := int64(idi) + v := getSchemaVer(t, ctx) + require.NoError(t, dom.Reload()) + tblInfo, exist := dom.InfoSchema().TableByID(tblID) + require.True(t, exist) + checkHistoryJobArgs(t, ctx, id, &historyJobArgs{ver: v, tbl: tblInfo.Meta()}) + return id } -func buildDropColumnsJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, colNames []string) *model.Job { - columnNames := make([]model.CIStr, len(colNames)) - ifExists := make([]bool, len(colNames)) - for i, colName := range colNames { - columnNames[i] = model.NewCIStr(colName) - } - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropColumns, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{columnNames, ifExists}, - } - return job -} +func TestColumnBasic(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") -func testDropColumns(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colNames []string, isError bool) *model.Job { - job := buildDropColumnsJob(dbInfo, tblInfo, colNames) - err := d.doDDLJob(ctx, job) - if isError { - c.Assert(err, NotNil) - return nil + num := 10 + for i := 0; i < num; i++ { + tk.MustExec(fmt.Sprintf("insert into t1 values(%d, %d, %d)", i, 10*i, 100*i)) } - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - -func (s *testColumnSuite) TestColumnBasic(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - tblInfo, err := testTableInfo(d, "t1", 3) - c.Assert(err, IsNil) - ctx := testNewContext(d) + ctx := testNewContext(store) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) + var tableID int64 + rs := tk.MustQuery("select TIDB_TABLE_ID from information_schema.tables where table_name='t1' and table_schema='test';") + tableIDi, _ := strconv.Atoi(rs.Rows()[0][0].(string)) + tableID = int64(tableIDi) - num := 10 - for i := 0; i < num; i++ { - _, err := t.AddRecord(ctx, types.MakeDatums(i, 10*i, 100*i)) - c.Assert(err, IsNil) - } + tbl := testGetTable(t, dom, tableID) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - i := int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - c.Assert(data, HasLen, 3) - c.Assert(data[0].GetInt64(), Equals, i) - c.Assert(data[1].GetInt64(), Equals, 10*i) - c.Assert(data[2].GetInt64(), Equals, 100*i) + i := 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Len(t, data, 3) + require.Equal(t, data[0].GetInt64(), int64(i)) + require.Equal(t, data[1].GetInt64(), int64(10*i)) + require.Equal(t, data[2].GetInt64(), int64(100*i)) i++ return true, nil }) - c.Assert(err, IsNil) - c.Assert(i, Equals, int64(num)) + require.NoError(t, err) + require.Equal(t, i, num) - c.Assert(table.FindCol(t.Cols(), "c4"), IsNil) + require.Nil(t, table.FindCol(tbl.Cols(), "c4")) - job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c4", &ast.ColumnPosition{Tp: ast.ColumnPositionAfter, RelativeColumn: &ast.ColumnName{Name: model.NewCIStr("c3")}}, 100) - testCheckJobDone(c, d, job, true) + jobID := testCreateColumn(tk, t, testNewContext(store), tableID, "c4", "after c3", 100, dom) + testCheckJobDone(t, store, jobID, true) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - c.Assert(table.FindCol(t.Cols(), "c4"), NotNil) + tbl = testGetTable(t, dom, tableID) + require.NotNil(t, table.FindCol(tbl.Cols(), "c4")) - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - c.Assert(data, HasLen, 4) - c.Assert(data[0].GetInt64(), Equals, i) - c.Assert(data[1].GetInt64(), Equals, 10*i) - c.Assert(data[2].GetInt64(), Equals, 100*i) - c.Assert(data[3].GetInt64(), Equals, int64(100)) + require.Len(t, data, 4) + require.Equal(t, data[0].GetInt64(), int64(i)) + require.Equal(t, data[1].GetInt64(), int64(10*i)) + require.Equal(t, data[2].GetInt64(), int64(100*i)) + require.Equal(t, data[3].GetInt64(), int64(100)) i++ return true, nil }) - c.Assert(err, IsNil) - c.Assert(i, Equals, int64(num)) + require.NoError(t, err) + require.Equal(t, i, num) - h, err := t.AddRecord(ctx, types.MakeDatums(11, 12, 13, 14)) - c.Assert(err, IsNil) + h, err := tbl.AddRecord(ctx, types.MakeDatums(11, 12, 13, 14)) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - values, err := tables.RowWithCols(t, ctx, h, t.Cols()) - c.Assert(err, IsNil) + require.NoError(t, err) + values, err := tables.RowWithCols(tbl, ctx, h, tbl.Cols()) + require.NoError(t, err) - c.Assert(values, HasLen, 4) - c.Assert(values[3].GetInt64(), Equals, int64(14)) + require.Len(t, values, 4) + require.Equal(t, values[3].GetInt64(), int64(14)) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c4", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c4", false, dom) + testCheckJobDone(t, store, jobID, false) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - values, err = tables.RowWithCols(t, ctx, h, t.Cols()) - c.Assert(err, IsNil) + tbl = testGetTable(t, dom, tableID) + values, err = tables.RowWithCols(tbl, ctx, h, tbl.Cols()) + require.NoError(t, err) - c.Assert(values, HasLen, 3) - c.Assert(values[2].GetInt64(), Equals, int64(13)) + require.Len(t, values, 3) + require.Equal(t, values[2].GetInt64(), int64(13)) - job = testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c4", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 111) - testCheckJobDone(c, d, job, true) + jobID = testCreateColumn(tk, t, testNewContext(store), tableID, "c4", "", 111, dom) + testCheckJobDone(t, store, jobID, true) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - values, err = tables.RowWithCols(t, ctx, h, t.Cols()) - c.Assert(err, IsNil) + tbl = testGetTable(t, dom, tableID) + values, err = tables.RowWithCols(tbl, ctx, h, tbl.Cols()) + require.NoError(t, err) - c.Assert(values, HasLen, 4) - c.Assert(values[3].GetInt64(), Equals, int64(111)) + require.Len(t, values, 4) + require.Equal(t, values[3].GetInt64(), int64(111)) - job = testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c5", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 101) - testCheckJobDone(c, d, job, true) + jobID = testCreateColumn(tk, t, testNewContext(store), tableID, "c5", "", 101, dom) + testCheckJobDone(t, store, jobID, true) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - values, err = tables.RowWithCols(t, ctx, h, t.Cols()) - c.Assert(err, IsNil) + tbl = testGetTable(t, dom, tableID) + values, err = tables.RowWithCols(tbl, ctx, h, tbl.Cols()) + require.NoError(t, err) - c.Assert(values, HasLen, 5) - c.Assert(values[4].GetInt64(), Equals, int64(101)) + require.Len(t, values, 5) + require.Equal(t, values[4].GetInt64(), int64(101)) - job = testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c6", &ast.ColumnPosition{Tp: ast.ColumnPositionFirst}, 202) - testCheckJobDone(c, d, job, true) + jobID = testCreateColumn(tk, t, testNewContext(store), tableID, "c6", "first", 202, dom) + testCheckJobDone(t, store, jobID, true) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - cols := t.Cols() - c.Assert(cols, HasLen, 6) - c.Assert(cols[0].Offset, Equals, 0) - c.Assert(cols[0].Name.L, Equals, "c6") - c.Assert(cols[1].Offset, Equals, 1) - c.Assert(cols[1].Name.L, Equals, "c1") - c.Assert(cols[2].Offset, Equals, 2) - c.Assert(cols[2].Name.L, Equals, "c2") - c.Assert(cols[3].Offset, Equals, 3) - c.Assert(cols[3].Name.L, Equals, "c3") - c.Assert(cols[4].Offset, Equals, 4) - c.Assert(cols[4].Name.L, Equals, "c4") - c.Assert(cols[5].Offset, Equals, 5) - c.Assert(cols[5].Name.L, Equals, "c5") + tbl = testGetTable(t, dom, tableID) + cols := tbl.Cols() + require.Len(t, cols, 6) + require.Equal(t, cols[0].Offset, 0) + require.Equal(t, cols[0].Name.L, "c6") + require.Equal(t, cols[1].Offset, 1) + require.Equal(t, cols[1].Name.L, "c1") + require.Equal(t, cols[2].Offset, 2) + require.Equal(t, cols[2].Name.L, "c2") + require.Equal(t, cols[3].Offset, 3) + require.Equal(t, cols[3].Name.L, "c3") + require.Equal(t, cols[4].Offset, 4) + require.Equal(t, cols[4].Name.L, "c4") + require.Equal(t, cols[5].Offset, 5) + require.Equal(t, cols[5].Name.L, "c5") - values, err = tables.RowWithCols(t, ctx, h, cols) - c.Assert(err, IsNil) + values, err = tables.RowWithCols(tbl, ctx, h, cols) + require.NoError(t, err) - c.Assert(values, HasLen, 6) - c.Assert(values[0].GetInt64(), Equals, int64(202)) - c.Assert(values[5].GetInt64(), Equals, int64(101)) + require.Len(t, values, 6) + require.Equal(t, values[0].GetInt64(), int64(202)) + require.Equal(t, values[5].GetInt64(), int64(101)) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c2", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c2", false, dom) + testCheckJobDone(t, store, jobID, false) - t = testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) + tbl = testGetTable(t, dom, tableID) - values, err = tables.RowWithCols(t, ctx, h, t.Cols()) - c.Assert(err, IsNil) - c.Assert(values, HasLen, 5) - c.Assert(values[0].GetInt64(), Equals, int64(202)) - c.Assert(values[4].GetInt64(), Equals, int64(101)) + values, err = tables.RowWithCols(tbl, ctx, h, tbl.Cols()) + require.NoError(t, err) + require.Len(t, values, 5) + require.Equal(t, values[0].GetInt64(), int64(202)) + require.Equal(t, values[4].GetInt64(), int64(101)) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c1", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c1", false, dom) + testCheckJobDone(t, store, jobID, false) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c3", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c3", false, dom) + testCheckJobDone(t, store, jobID, false) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c4", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c4", false, dom) + testCheckJobDone(t, store, jobID, false) - job = testCreateIndex(c, ctx, d, s.dbInfo, tblInfo, false, "c5_idx", "c5") - testCheckJobDone(c, d, job, true) + jobID = testCreateIndex(tk, t, testNewContext(store), tableID, false, "c5_idx", "c5", dom) + testCheckJobDone(t, store, jobID, true) - job = testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c5", false) - testCheckJobDone(c, d, job, false) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c5", false, dom) + testCheckJobDone(t, store, jobID, false) - testDropColumn(c, ctx, d, s.dbInfo, tblInfo, "c6", true) + jobID = testDropColumnInternal(tk, t, testNewContext(store), tableID, "c6", true, dom) + testCheckJobDone(t, store, jobID, false) - testDropTable(c, ctx, d, s.dbInfo, tblInfo) + testDropTable(tk, t, "t1", dom) } -func (s *testColumnSuite) checkColumnKVExist(ctx sessionctx.Context, t table.Table, handle kv.Handle, col *table.Column, columnValue interface{}, isExist bool) error { +func checkColumnKVExist(ctx sessionctx.Context, t table.Table, handle kv.Handle, col *table.Column, columnValue interface{}, isExist bool) error { err := ctx.NewTxn(context.Background()) if err != nil { return errors.Trace(err) @@ -390,440 +305,277 @@ func (s *testColumnSuite) checkColumnKVExist(ctx sessionctx.Context, t table.Tab return nil } -func (s *testColumnSuite) checkNoneColumn(ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo, handle kv.Handle, col *table.Column, columnValue interface{}) error { - t, err := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - return errors.Trace(err) - } - err = s.checkColumnKVExist(ctx, t, handle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } - err = s.testGetColumn(t, col.Name.L, false) - if err != nil { - return errors.Trace(err) - } - return nil +func checkNoneColumn(t *testing.T, ctx sessionctx.Context, tableID int64, handle kv.Handle, col *table.Column, columnValue interface{}, dom *domain.Domain) { + tbl := testGetTable(t, dom, tableID) + err := checkColumnKVExist(ctx, tbl, handle, col, columnValue, false) + require.NoError(t, err) + err = testGetColumn(tbl, col.Name.L, false) + require.NoError(t, err) } -func (s *testColumnSuite) checkDeleteOnlyColumn(ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo, handle kv.Handle, col *table.Column, row []types.Datum, columnValue interface{}) error { - t, err := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - return errors.Trace(err) - } - err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } - i := int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, row) { - return false, errors.Errorf("%v not equal to %v", data, row) - } +func checkDeleteOnlyColumn(t *testing.T, ctx sessionctx.Context, tableID int64, handle kv.Handle, col *table.Column, row []types.Datum, columnValue interface{}, dom *domain.Domain) { + tbl := testGetTable(t, dom, tableID) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) + i := 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, row), "%v not equal to %v", data, row) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } - err = s.checkColumnKVExist(ctx, t, handle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) + err = checkColumnKVExist(ctx, tbl, handle, col, columnValue, false) + require.NoError(t, err) // Test add a new row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) newRow := types.MakeDatums(int64(11), int64(22), int64(33)) - newHandle, err := t.AddRecord(ctx, newRow) - if err != nil { - return errors.Trace(err) - } + newHandle, err := tbl.AddRecord(ctx, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) rows := [][]types.Datum{row, newRow} - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, rows[i]) { - return false, errors.Errorf("%v not equal to %v", data, rows[i]) - } + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, rows[i]), "%v not equal to %v", data, rows[i]) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 2 { - return errors.Errorf("expect 2, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 2, i, "expect 2, got %v", i) - err = s.checkColumnKVExist(ctx, t, handle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } + err = checkColumnKVExist(ctx, tbl, handle, col, columnValue, false) + require.NoError(t, err) // Test remove a row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - err = t.RemoveRecord(ctx, newHandle, newRow) - if err != nil { - return errors.Trace(err) - } + err = tbl.RemoveRecord(ctx, newHandle, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.NoError(t, err) + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } - err = s.checkColumnKVExist(ctx, t, newHandle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } - err = s.testGetColumn(t, col.Name.L, false) - if err != nil { - return errors.Trace(err) - } - return nil + require.Equalf(t, 1, i, "expect 1, got %v", i) + err = checkColumnKVExist(ctx, tbl, newHandle, col, columnValue, false) + require.NoError(t, err) + err = testGetColumn(tbl, col.Name.L, false) + require.NoError(t, err) } -func (s *testColumnSuite) checkWriteOnlyColumn(ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo, handle kv.Handle, col *table.Column, row []types.Datum, columnValue interface{}) error { - t, err := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - return errors.Trace(err) - } - err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } +func checkWriteOnlyColumn(t *testing.T, ctx sessionctx.Context, tableID int64, handle kv.Handle, col *table.Column, row []types.Datum, columnValue interface{}, dom *domain.Domain) { + tbl := testGetTable(t, dom, tableID) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) - i := int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, row) { - return false, errors.Errorf("%v not equal to %v", data, row) - } + i := 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, row), "%v not equal to %v", data, row) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) - err = s.checkColumnKVExist(ctx, t, handle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } + err = checkColumnKVExist(ctx, tbl, handle, col, columnValue, false) + require.NoError(t, err) // Test add a new row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) newRow := types.MakeDatums(int64(11), int64(22), int64(33)) - newHandle, err := t.AddRecord(ctx, newRow) - if err != nil { - return errors.Trace(err) - } + newHandle, err := tbl.AddRecord(ctx, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) rows := [][]types.Datum{row, newRow} - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, rows[i]) { - return false, errors.Errorf("%v not equal to %v", data, rows[i]) - } + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, rows[i]), "%v not equal to %v", data, rows[i]) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 2 { - return errors.Errorf("expect 2, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 2, i, "expect 2, got %v", i) - err = s.checkColumnKVExist(ctx, t, newHandle, col, columnValue, true) - if err != nil { - return errors.Trace(err) - } + err = checkColumnKVExist(ctx, tbl, newHandle, col, columnValue, true) + require.NoError(t, err) // Test remove a row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - err = t.RemoveRecord(ctx, newHandle, newRow) - if err != nil { - return errors.Trace(err) - } + err = tbl.RemoveRecord(ctx, newHandle, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) - err = s.checkColumnKVExist(ctx, t, newHandle, col, columnValue, false) - if err != nil { - return errors.Trace(err) - } - err = s.testGetColumn(t, col.Name.L, false) - if err != nil { - return errors.Trace(err) - } - return nil + err = checkColumnKVExist(ctx, tbl, newHandle, col, columnValue, false) + require.NoError(t, err) + err = testGetColumn(tbl, col.Name.L, false) + require.NoError(t, err) } -func (s *testColumnSuite) checkReorganizationColumn(ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo, col *table.Column, row []types.Datum, columnValue interface{}) error { - t, err := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - return errors.Trace(err) - } - err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } +func checkReorganizationColumn(t *testing.T, ctx sessionctx.Context, tableID int64, col *table.Column, row []types.Datum, columnValue interface{}, dom *domain.Domain) { + tbl := testGetTable(t, dom, tableID) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) - i := int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, row) { - return false, errors.Errorf("%v not equal to %v", data, row) - } + i := 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, row), "%v not equal to %v", data, row) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1 got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) // Test add a new row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) newRow := types.MakeDatums(int64(11), int64(22), int64(33)) - newHandle, err := t.AddRecord(ctx, newRow) - if err != nil { - return errors.Trace(err) - } + newHandle, err := tbl.AddRecord(ctx, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) rows := [][]types.Datum{row, newRow} - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, rows[i]) { - return false, errors.Errorf("%v not equal to %v", data, rows[i]) - } + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, rows[i]), "%v not equal to %v", data, rows[i]) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 2 { - return errors.Errorf("expect 2, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 2, i, "expect 2, got %v", i) - err = s.checkColumnKVExist(ctx, t, newHandle, col, columnValue, true) - if err != nil { - return errors.Trace(err) - } + err = checkColumnKVExist(ctx, tbl, newHandle, col, columnValue, true) + require.NoError(t, err) // Test remove a row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - err = t.RemoveRecord(ctx, newHandle, newRow) - if err != nil { - return errors.Trace(err) - } + err = tbl.RemoveRecord(ctx, newHandle, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } - err = s.testGetColumn(t, col.Name.L, false) - if err != nil { - return errors.Trace(err) - } - return nil + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) + err = testGetColumn(tbl, col.Name.L, false) + require.NoError(t, err) } -func (s *testColumnSuite) checkPublicColumn(ctx sessionctx.Context, d *ddl, tblInfo *model.TableInfo, newCol *table.Column, oldRow []types.Datum, columnValue interface{}) error { - t, err := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - return errors.Trace(err) - } - err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } +func checkPublicColumn(t *testing.T, ctx sessionctx.Context, tableID int64, newCol *table.Column, oldRow []types.Datum, columnValue interface{}, dom *domain.Domain, columnCnt int) { + tbl := testGetTable(t, dom, tableID) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) - i := int64(0) - updatedRow := append(oldRow, types.NewDatum(columnValue)) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, updatedRow) { - return false, errors.Errorf("%v not equal to %v", data, updatedRow) - } + i := 0 + var updatedRow []types.Datum + updatedRow = append(updatedRow, oldRow...) + for j := 0; j < columnCnt; j++ { + updatedRow = append(updatedRow, types.NewDatum(columnValue)) + } + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, updatedRow), "%v not equal to %v", data, updatedRow) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) // Test add a new row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) newRow := types.MakeDatums(int64(11), int64(22), int64(33), int64(44)) - handle, err := t.AddRecord(ctx, newRow) - if err != nil { - return errors.Trace(err) + for j := 1; j < columnCnt; j++ { + newRow = append(newRow, types.NewDatum(int64(44))) } + handle, err := tbl.AddRecord(ctx, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) rows := [][]types.Datum{updatedRow, newRow} - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, rows[i]) { - return false, errors.Errorf("%v not equal to %v", data, rows[i]) - } + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, rows[i]), "%v not equal to %v", data, rows[i]) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 2 { - return errors.Errorf("expect 2, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 2, i, "expect 2, got %v", i) // Test remove a row. err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - err = t.RemoveRecord(ctx, handle, newRow) - if err != nil { - return errors.Trace(err) - } + err = tbl.RemoveRecord(ctx, handle, newRow) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - if err != nil { - return errors.Trace(err) - } + require.NoError(t, err) - i = int64(0) - err = tables.IterRecords(t, ctx, t.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - if !reflect.DeepEqual(data, updatedRow) { - return false, errors.Errorf("%v not equal to %v", data, updatedRow) - } + i = 0 + err = tables.IterRecords(tbl, ctx, tbl.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + require.Truef(t, reflect.DeepEqual(data, rows[i]), "%v not equal to %v", data, rows[i]) i++ return true, nil }) - if err != nil { - return errors.Trace(err) - } - if i != 1 { - return errors.Errorf("expect 1, got %v", i) - } + require.NoError(t, err) + require.Equalf(t, 1, i, "expect 1, got %v", i) - err = s.testGetColumn(t, newCol.Name.L, true) - if err != nil { - return errors.Trace(err) - } - return nil + err = testGetColumn(tbl, newCol.Name.L, true) + require.NoError(t, err) } -func (s *testColumnSuite) checkAddColumn(state model.SchemaState, d *ddl, tblInfo *model.TableInfo, handle kv.Handle, newCol *table.Column, oldRow []types.Datum, columnValue interface{}) error { - ctx := testNewContext(d) - var err error +func checkAddColumn(t *testing.T, state model.SchemaState, tableID int64, handle kv.Handle, newCol *table.Column, oldRow []types.Datum, columnValue interface{}, dom *domain.Domain, store kv.Storage, columnCnt int) { + ctx := testNewContext(store) switch state { case model.StateNone: - err = errors.Trace(s.checkNoneColumn(ctx, d, tblInfo, handle, newCol, columnValue)) + checkNoneColumn(t, ctx, tableID, handle, newCol, columnValue, dom) case model.StateDeleteOnly: - err = errors.Trace(s.checkDeleteOnlyColumn(ctx, d, tblInfo, handle, newCol, oldRow, columnValue)) + checkDeleteOnlyColumn(t, ctx, tableID, handle, newCol, oldRow, columnValue, dom) case model.StateWriteOnly: - err = errors.Trace(s.checkWriteOnlyColumn(ctx, d, tblInfo, handle, newCol, oldRow, columnValue)) + checkWriteOnlyColumn(t, ctx, tableID, handle, newCol, oldRow, columnValue, dom) case model.StateWriteReorganization, model.StateDeleteReorganization: - err = errors.Trace(s.checkReorganizationColumn(ctx, d, tblInfo, newCol, oldRow, columnValue)) + checkReorganizationColumn(t, ctx, tableID, newCol, oldRow, columnValue, dom) case model.StatePublic: - err = errors.Trace(s.checkPublicColumn(ctx, d, tblInfo, newCol, oldRow, columnValue)) + checkPublicColumn(t, ctx, tableID, newCol, oldRow, columnValue, dom, columnCnt) } - return err } -func (s *testColumnSuite) testGetColumn(t table.Table, name string, isExist bool) error { +func testGetColumn(t table.Table, name string, isExist bool) error { col := table.FindCol(t.Cols(), name) if isExist { if col == nil { @@ -837,62 +589,50 @@ func (s *testColumnSuite) testGetColumn(t table.Table, name string, isExist bool return nil } -func (s *testColumnSuite) TestAddColumn(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - ctx := testNewContext(d) +func TestAddColumn(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) + var tableID int64 + rs := tk.MustQuery("select TIDB_TABLE_ID from information_schema.tables where table_name='t1' and table_schema='test';") + tableIDi, _ := strconv.Atoi(rs.Rows()[0][0].(string)) + tableID = int64(tableIDi) + tbl := testGetTable(t, dom, tableID) + ctx := testNewContext(store) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) oldRow := types.MakeDatums(int64(1), int64(2), int64(3)) - handle, err := t.AddRecord(ctx, oldRow) - c.Assert(err, IsNil) + handle, err := tbl.AddRecord(ctx, oldRow) + require.NoError(t, err) txn, err := ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) newColName := "c4" defaultColValue := int64(4) - var mu sync.Mutex - var hookErr error checkOK := false - tc := &TestDDLCallback{} - tc.onJobUpdated = func(job *model.Job) { - mu.Lock() - defer mu.Unlock() + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} + tc.OnJobUpdatedExported = func(job *model.Job) { if checkOK { return } - t, err1 := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } - newCol := table.FindCol(t.(*tables.TableCommon).Columns, newColName) + tbl := testGetTable(t, dom, tableID) + newCol := table.FindCol(tbl.(*tables.TableCommon).Columns, newColName) if newCol == nil { return } - err1 = s.checkAddColumn(newCol.State, d, tblInfo, handle, newCol, oldRow, defaultColValue) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } + checkAddColumn(t, newCol.State, tableID, handle, newCol, oldRow, defaultColValue, dom, store, 1) if newCol.State == model.StatePublic { checkOK = true @@ -901,162 +641,56 @@ func (s *testColumnSuite) TestAddColumn(c *C) { d.SetHook(tc) - job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, newColName, &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, defaultColValue) + jobID := testCreateColumn(tk, t, testNewContext(store), tableID, newColName, "", defaultColValue, dom) + testCheckJobDone(t, store, jobID, true) - testCheckJobDone(c, d, job, true) - mu.Lock() - hErr := hookErr - ok := checkOK - mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.True(t, checkOK) - job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) - testCheckJobDone(c, d, job, false) - - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - err = d.Stop() - c.Assert(err, IsNil) + jobID = testDropTable(tk, t, "t1", dom) + testCheckJobDone(t, store, jobID, false) } -func (s *testColumnSuite) TestAddColumns(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - ctx := testNewContext(d) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) +func TestDropColumnInColumnTest(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int, c4 int);") - oldRow := types.MakeDatums(int64(1), int64(2), int64(3)) - handle, err := t.AddRecord(ctx, oldRow) - c.Assert(err, IsNil) - - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - newColNames := []string{"c4,c5,c6"} - positions := make([]*ast.ColumnPosition, 3) - for i := range positions { - positions[i] = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} - } - defaultColValue := int64(4) - - var mu sync.Mutex - var hookErr error - checkOK := false - - tc := &TestDDLCallback{} - tc.onJobUpdated = func(job *model.Job) { - mu.Lock() - defer mu.Unlock() - if checkOK { - return - } - - t, err1 := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } - for _, newColName := range newColNames { - newCol := table.FindCol(t.(*tables.TableCommon).Columns, newColName) - if newCol == nil { - return - } - - err1 = s.checkAddColumn(newCol.State, d, tblInfo, handle, newCol, oldRow, defaultColValue) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } - - if newCol.State == model.StatePublic { - checkOK = true - } - } - } - - d.SetHook(tc) - - job := testCreateColumns(c, ctx, d, s.dbInfo, tblInfo, newColNames, positions, defaultColValue) - - testCheckJobDone(c, d, job, true) - mu.Lock() - hErr := hookErr - ok := checkOK - mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) - - job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) - testCheckJobDone(c, d, job, false) - err = d.Stop() - c.Assert(err, IsNil) -} - -func (s *testColumnSuite) TestDropColumn(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t2", 4) - c.Assert(err, IsNil) - ctx := testNewContext(d) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) + var tableID int64 + rs := tk.MustQuery("select TIDB_TABLE_ID from information_schema.tables where table_name='t1' and table_schema='test';") + tableIDi, _ := strconv.Atoi(rs.Rows()[0][0].(string)) + tableID = int64(tableIDi) + tbl := testGetTable(t, dom, tableID) + ctx := testNewContext(store) colName := "c4" defaultColValue := int64(4) row := types.MakeDatums(int64(1), int64(2), int64(3)) - _, err = t.AddRecord(ctx, append(row, types.NewDatum(defaultColValue))) - c.Assert(err, IsNil) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) + _, err = tbl.AddRecord(ctx, append(row, types.NewDatum(defaultColValue))) + require.NoError(t, err) txn, err := ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) checkOK := false var hookErr error var mu sync.Mutex - tc := &TestDDLCallback{} - tc.onJobUpdated = func(job *model.Job) { + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} + tc.OnJobUpdatedExported = func(job *model.Job) { mu.Lock() defer mu.Unlock() if checkOK { return } - t, err1 := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } - col := table.FindCol(t.(*tables.TableCommon).Columns, colName) + tbl := testGetTable(t, dom, tableID) + col := table.FindCol(tbl.(*tables.TableCommon).Columns, colName) if col == nil { checkOK = true return @@ -1065,213 +699,72 @@ func (s *testColumnSuite) TestDropColumn(c *C) { d.SetHook(tc) - job := testDropColumn(c, ctx, d, s.dbInfo, tblInfo, colName, false) - testCheckJobDone(c, d, job, false) + jobID := testDropColumnInternal(tk, t, testNewContext(store), tableID, colName, false, dom) + testCheckJobDone(t, store, jobID, false) mu.Lock() hErr := hookErr ok := checkOK mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, hErr) + require.True(t, ok) - job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) - testCheckJobDone(c, d, job, false) - - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - err = d.Stop() - c.Assert(err, IsNil) + jobID = testDropTable(tk, t, "t1", dom) + testCheckJobDone(t, store, jobID, false) } -func (s *testColumnSuite) TestDropColumns(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t2", 4) - c.Assert(err, IsNil) - ctx := testNewContext(d) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - - colNames := []string{"c3", "c4"} - defaultColValue := int64(4) - row := types.MakeDatums(int64(1), int64(2), int64(3)) - _, err = t.AddRecord(ctx, append(row, types.NewDatum(defaultColValue))) - c.Assert(err, IsNil) - - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - checkOK := false - var hookErr error - var mu sync.Mutex - - tc := &TestDDLCallback{} - tc.onJobUpdated = func(job *model.Job) { - mu.Lock() - defer mu.Unlock() - if checkOK { - return - } - t, err1 := testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) - if err1 != nil { - hookErr = errors.Trace(err1) - return - } - for _, colName := range colNames { - col := table.FindCol(t.(*tables.TableCommon).Columns, colName) - if col == nil { - checkOK = true - return - } - } - } - - d.SetHook(tc) - - job := testDropColumns(c, ctx, d, s.dbInfo, tblInfo, colNames, false) - testCheckJobDone(c, d, job, false) - mu.Lock() - hErr := hookErr - ok := checkOK - mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) - - job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) - testCheckJobDone(c, d, job, false) - err = d.Stop() - c.Assert(err, IsNil) -} - -func (s *testColumnSuite) TestModifyColumn(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - ctx := testNewContext(d) - - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - tests := []struct { - origin string - to string - err error - }{ - {"int", "bigint", nil}, - {"int", "int unsigned", nil}, - {"varchar(10)", "text", nil}, - {"varbinary(10)", "blob", nil}, - {"text", "blob", errUnsupportedModifyCharset.GenWithStackByArgs("charset from utf8mb4 to binary")}, - {"varchar(10)", "varchar(8)", nil}, - {"varchar(10)", "varchar(11)", nil}, - {"varchar(10) character set utf8 collate utf8_bin", "varchar(10) character set utf8", nil}, - {"decimal(2,1)", "decimal(3,2)", nil}, - {"decimal(2,1)", "decimal(2,2)", nil}, - {"decimal(2,1)", "decimal(2,1)", nil}, - {"decimal(2,1)", "int", nil}, - {"decimal", "int", nil}, - {"decimal(2,1)", "bigint", nil}, - } - for _, tt := range tests { - ftA := s.colDefStrToFieldType(c, tt.origin) - ftB := s.colDefStrToFieldType(c, tt.to) - err := checkModifyTypes(ctx, ftA, ftB, false) - if err == nil { - c.Assert(tt.err, IsNil, Commentf("origin:%v, to:%v", tt.origin, tt.to)) - } else { - c.Assert(err.Error(), Equals, tt.err.Error()) - } - } -} - -func (s *testColumnSuite) colDefStrToFieldType(c *C, str string) *types.FieldType { - sqlA := "alter table t modify column a " + str - stmt, err := parser.New().ParseOneStmt(sqlA, "", "") - c.Assert(err, IsNil) - colDef := stmt.(*ast.AlterTableStmt).Specs[0].NewColumns[0] - chs, coll := charset.GetDefaultCharsetAndCollate() - col, _, err := buildColumnAndConstraint(nil, 0, colDef, nil, chs, coll) - c.Assert(err, IsNil) - return &col.FieldType +func testGetTable(t *testing.T, dom *domain.Domain, tableID int64) table.Table { + require.NoError(t, dom.Reload()) + tbl, exist := dom.InfoSchema().TableByID(tableID) + require.True(t, exist) + return tbl } -func (s *testColumnSuite) TestFieldCase(c *C) { - var fields = []string{"field", "Field"} - colObjects := make([]*model.ColumnInfo, len(fields)) - for i, name := range fields { - colObjects[i] = &model.ColumnInfo{ - Name: model.NewCIStr(name), - } - } - err := checkDuplicateColumn(colObjects) - c.Assert(err.Error(), Equals, infoschema.ErrColumnExists.GenWithStackByArgs("Field").Error()) -} - -func (s *testColumnSuite) TestAutoConvertBlobTypeByLength(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - // Close the customized ddl(worker goroutine included) after the test is finished, otherwise, it will - // cause go routine in TiDB leak test. - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - - sql := fmt.Sprintf("create table t0(c0 Blob(%d), c1 Blob(%d), c2 Blob(%d), c3 Blob(%d))", - tinyBlobMaxLength-1, blobMaxLength-1, mediumBlobMaxLength-1, longBlobMaxLength-1) - stmt, err := parser.New().ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) - tblInfo, err := BuildTableInfoFromAST(stmt.(*ast.CreateTableStmt)) - c.Assert(err, IsNil) - genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) - tblInfo.ID = genIDs[0] - - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - - c.Assert(t.Cols()[0].Tp, Equals, mysql.TypeTinyBlob) - c.Assert(t.Cols()[0].Flen, Equals, tinyBlobMaxLength) - c.Assert(t.Cols()[1].Tp, Equals, mysql.TypeBlob) - c.Assert(t.Cols()[1].Flen, Equals, blobMaxLength) - c.Assert(t.Cols()[2].Tp, Equals, mysql.TypeMediumBlob) - c.Assert(t.Cols()[2].Flen, Equals, mediumBlobMaxLength) - c.Assert(t.Cols()[3].Tp, Equals, mysql.TypeLongBlob) - c.Assert(t.Cols()[3].Flen, Equals, longBlobMaxLength) - - oldRow := types.MakeDatums([]byte("a"), []byte("a"), []byte("a"), []byte("a")) - _, err = t.AddRecord(ctx, oldRow) - c.Assert(err, IsNil) - - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) +func TestGetDefaultValueOfColumn(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (da date default '1962-03-03 23:33:34', dt datetime default '1962-03-03'," + + " ti time default '2020-10-11 12:23:23', ts timestamp default '2020-10-13 12:23:23')") + + tk.MustQuery("show create table t1").Check(testkit.RowsWithSep("|", ""+ + "t1 CREATE TABLE `t1` (\n"+ + " `da` date DEFAULT '1962-03-03',\n"+ + " `dt` datetime DEFAULT '1962-03-03 00:00:00',\n"+ + " `ti` time DEFAULT '12:23:23',\n"+ + " `ts` timestamp DEFAULT '2020-10-13 12:23:23'\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + tk.MustExec("insert into t1 values()") + + tk.MustQuery("select * from t1").Check(testkit.RowsWithSep("|", ""+ + "1962-03-03 1962-03-03 00:00:00 12:23:23 2020-10-13 12:23:23")) + + tk.MustExec("alter table t1 add column da1 date default '2020-03-27 20:20:20 123456'") + + tk.MustQuery("show create table t1").Check(testkit.RowsWithSep("|", ""+ + "t1 CREATE TABLE `t1` (\n"+ + " `da` date DEFAULT '1962-03-03',\n"+ + " `dt` datetime DEFAULT '1962-03-03 00:00:00',\n"+ + " `ti` time DEFAULT '12:23:23',\n"+ + " `ts` timestamp DEFAULT '2020-10-13 12:23:23',\n"+ + " `da1` date DEFAULT '2020-03-27'\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + tk.MustQuery("select * from t1").Check(testkit.RowsWithSep("|", ""+ + "1962-03-03 1962-03-03 00:00:00 12:23:23 2020-10-13 12:23:23 2020-03-27")) + + tk.MustExec("alter table t1 change ts da2 date default '2020-10-10 20:20:20'") + + tk.MustQuery("show create table t1").Check(testkit.RowsWithSep("|", ""+ + "t1 CREATE TABLE `t1` (\n"+ + " `da` date DEFAULT '1962-03-03',\n"+ + " `dt` datetime DEFAULT '1962-03-03 00:00:00',\n"+ + " `ti` time DEFAULT '12:23:23',\n"+ + " `da2` date DEFAULT '2020-10-10',\n"+ + " `da1` date DEFAULT '2020-03-27'\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + tk.MustQuery("select * from t1").Check(testkit.RowsWithSep("|", ""+ + "1962-03-03 1962-03-03 00:00:00 12:23:23 2020-10-13 2020-03-27")) } diff --git a/ddl/column_type_change_test.go b/ddl/column_type_change_test.go index 573a809894d7d..4d29f0ad18b8b 100644 --- a/ddl/column_type_change_test.go +++ b/ddl/column_type_change_test.go @@ -19,56 +19,33 @@ import ( "errors" "fmt" "strconv" - "strings" - "sync" + "testing" "time" - . "github.com/pingcap/check" errors2 "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/ddl" - "github.com/pingcap/tidb/domain" - mysql "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" - parser_mysql "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/helper" - "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/dbterror" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testColumnTypeChangeSuite{}) - -type testColumnTypeChangeSuite struct { - store kv.Storage - dom *domain.Domain -} - -func (s *testColumnTypeChangeSuite) SetUpSuite(c *C) { - var err error - ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) - s.store, err = mockstore.NewMockStore() - c.Assert(err, IsNil) - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} - -func (s *testColumnTypeChangeSuite) TearDownSuite(c *C) { - s.dom.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeBetweenInteger(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeBetweenInteger(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Modify column from null to not null. @@ -79,11 +56,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeBetweenInteger(c *C) { tk.MustExec("insert into t(a, b) values (null, 1)") // Modify column from null to not null in same type will cause ErrWarnDataTruncated _, err := tk.Exec("alter table t modify column a int not null") - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a' at row 1") + require.Equal(t, "[ddl:1265]Data truncated for column 'a' at row 1", err.Error()) // Modify column from null to not null in different type will cause WarnDataTruncated. - tk.MustGetErrCode("alter table t modify column a tinyint not null", mysql.WarnDataTruncated) - tk.MustGetErrCode("alter table t modify column a bigint not null", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify column a tinyint not null", errno.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify column a bigint not null", errno.WarnDataTruncated) // Modify column not null to null. tk.MustExec("drop table if exists t") @@ -124,34 +101,33 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeBetweenInteger(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t (a bigint)") tk.MustExec("insert into t(a) values (9223372036854775807)") - tk.MustGetErrCode("alter table t modify column a int", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify column a mediumint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify column a smallint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify column a tinyint", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a int", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a mediumint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a smallint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a tinyint", errno.ErrDataOutOfRange) _, err = tk.Exec("admin check table t") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeStateBetweenInteger(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeStateBetweenInteger(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 int, c2 int)") tk.MustExec("insert into t(c1, c2) values (1, 1)") // use new session to check meta in callback function. - internalTK := testkit.NewTestKit(c, s.store) + internalTK := testkit.NewTestKit(t, store) internalTK.MustExec("use test") - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(len(tbl.Cols()), Equals, 2) - c.Assert(getModifyColumn(c, tk.Se.(sessionctx.Context), "test", "t", "c2", false), NotNil) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, 2, len(tbl.Cols())) + require.NotNil(t, external.GetModifyColumn(t, tk, "test", "t", "c2", false)) - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} var checkErr error hook.OnJobRunBeforeExported = func(job *model.Job) { if checkErr != nil { @@ -162,95 +138,90 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeStateBetweenInteger(c *C } switch job.SchemaState { case model.StateNone: - tbl = testGetTableByName(c, internalTK.Se, "test", "t") + tbl = external.GetTableByName(t, internalTK, "test", "t") if tbl == nil { checkErr = errors.New("tbl is nil") } else if len(tbl.Cols()) != 2 { checkErr = errors.New("len(cols) is not right") } case model.StateDeleteOnly, model.StateWriteOnly, model.StateWriteReorganization: - tbl = testGetTableByName(c, internalTK.Se, "test", "t") + tbl = external.GetTableByName(t, internalTK, "test", "t") if tbl == nil { checkErr = errors.New("tbl is nil") } else if len(tbl.(*tables.TableCommon).Columns) != 3 { // changingCols has been added into meta. checkErr = errors.New("len(cols) is not right") - } else if getModifyColumn(c, internalTK.Se.(sessionctx.Context), "test", "t", "c2", true).Flag&parser_mysql.PreventNullInsertFlag == uint(0) { + } else if external.GetModifyColumn(t, internalTK, "test", "t", "c2", true).Flag&mysql.PreventNullInsertFlag == uint(0) { checkErr = errors.New("old col's flag is not right") - } else if getModifyColumn(c, internalTK.Se.(sessionctx.Context), "test", "t", "_Col$_c2_0", true) == nil { + } else if external.GetModifyColumn(t, internalTK, "test", "t", "_Col$_c2_0", true) == nil { checkErr = errors.New("changingCol is nil") } } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) // Alter sql will modify column c2 to tinyint not null. SQL := "alter table t modify column c2 tinyint not null" tk.MustExec(SQL) // Assert the checkErr in the job of every state. - c.Assert(checkErr, IsNil) + require.NoError(t, checkErr) // Check the col meta after the column type change. - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(len(tbl.Cols()), Equals, 2) - col := getModifyColumn(c, tk.Se.(sessionctx.Context), "test", "t", "c2", false) - c.Assert(col, NotNil) - c.Assert(parser_mysql.HasNotNullFlag(col.Flag), Equals, true) - c.Assert(col.Flag&parser_mysql.NoDefaultValueFlag, Not(Equals), uint(0)) - c.Assert(col.Tp, Equals, parser_mysql.TypeTiny) - c.Assert(col.ChangeStateInfo, IsNil) + tbl = external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, 2, len(tbl.Cols())) + col := external.GetModifyColumn(t, tk, "test", "t", "c2", false) + require.NotNil(t, col) + require.Equal(t, true, mysql.HasNotNullFlag(col.Flag)) + require.NotEqual(t, 0, col.Flag&mysql.NoDefaultValueFlag) + require.Equal(t, mysql.TypeTiny, col.Tp) + require.Nil(t, col.ChangeStateInfo) tk.MustQuery("select * from t").Check(testkit.Rows("1 1")) } -func (s *testColumnTypeChangeSuite) TestRollbackColumnTypeChangeBetweenInteger(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRollbackColumnTypeChangeBetweenInteger(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 bigint, c2 bigint)") tk.MustExec("insert into t(c1, c2) values (1, 1)") - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(len(tbl.Cols()), Equals, 2) - c.Assert(getModifyColumn(c, tk.Se.(sessionctx.Context), "test", "t", "c2", false), NotNil) - - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, 2, len(tbl.Cols())) + require.NotNil(t, external.GetModifyColumn(t, tk, "test", "t", "c2", false)) - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} // Mock roll back at model.StateNone. customizeHookRollbackAtState(hook, tbl, model.StateNone) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) // Alter sql will modify column c2 to bigint not null. SQL := "alter table t modify column c2 int not null" - _, err := tk.Exec(SQL) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1]MockRollingBackInCallBack-queueing") - assertRollBackedColUnchanged(c, tk) + err := tk.ExecToErr(SQL) + require.EqualError(t, err, "[ddl:1]MockRollingBackInCallBack-none") + assertRollBackedColUnchanged(t, tk) // Mock roll back at model.StateDeleteOnly. customizeHookRollbackAtState(hook, tbl, model.StateDeleteOnly) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err = tk.Exec(SQL) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1]MockRollingBackInCallBack-delete only") - assertRollBackedColUnchanged(c, tk) + dom.DDL().SetHook(hook) + err = tk.ExecToErr(SQL) + require.EqualError(t, err, "[ddl:1]MockRollingBackInCallBack-delete only") + assertRollBackedColUnchanged(t, tk) // Mock roll back at model.StateWriteOnly. customizeHookRollbackAtState(hook, tbl, model.StateWriteOnly) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err = tk.Exec(SQL) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1]MockRollingBackInCallBack-write only") - assertRollBackedColUnchanged(c, tk) + dom.DDL().SetHook(hook) + err = tk.ExecToErr(SQL) + require.EqualError(t, err, "[ddl:1]MockRollingBackInCallBack-write only") + assertRollBackedColUnchanged(t, tk) // Mock roll back at model.StateWriteReorg. customizeHookRollbackAtState(hook, tbl, model.StateWriteReorganization) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err = tk.Exec(SQL) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1]MockRollingBackInCallBack-write reorganization") - assertRollBackedColUnchanged(c, tk) + dom.DDL().SetHook(hook) + err = tk.ExecToErr(SQL) + require.EqualError(t, err, "[ddl:1]MockRollingBackInCallBack-write reorganization") + assertRollBackedColUnchanged(t, tk) } func customizeHookRollbackAtState(hook *ddl.TestDDLCallback, tbl table.Table, state model.SchemaState) { @@ -265,15 +236,15 @@ func customizeHookRollbackAtState(hook *ddl.TestDDLCallback, tbl table.Table, st } } -func assertRollBackedColUnchanged(c *C, tk *testkit.TestKit) { - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(len(tbl.Cols()), Equals, 2) - col := getModifyColumn(c, tk.Se.(sessionctx.Context), "test", "t", "c2", false) - c.Assert(col, NotNil) - c.Assert(col.Flag, Equals, uint(0)) - c.Assert(col.Tp, Equals, parser_mysql.TypeLonglong) - c.Assert(col.ChangeStateInfo, IsNil) +func assertRollBackedColUnchanged(t *testing.T, tk *testkit.TestKit) { + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, 2, len(tbl.Cols())) + col := external.GetModifyColumn(t, tk, "test", "t", "c2", false) + require.NotNil(t, col) + require.Equal(t, uint(0), col.Flag) + require.Equal(t, mysql.TypeLonglong, col.Tp) + require.Nil(t, col.ChangeStateInfo) tk.MustQuery("select * from t").Check(testkit.Rows("1 1")) } @@ -287,8 +258,10 @@ func init() { mockTerrorMap[model.StateWriteReorganization.String()] = dbterror.ClassDDL.New(1, "MockRollingBackInCallBack-"+model.StateWriteReorganization.String()) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromIntegerToOthers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeFromIntegerToOthers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") prepare := func(tk *testkit.TestKit) { @@ -305,143 +278,143 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromIntegerToOthers(c *C // integer to string prepare(tk) tk.MustExec("alter table t modify a varchar(10)") - modifiedColumn := getModifyColumn(c, tk.Se, "test", "t", "a", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeVarchar) + modifiedColumn := external.GetModifyColumn(t, tk, "test", "t", "a", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeVarchar, modifiedColumn.Tp) tk.MustQuery("select a from t").Check(testkit.Rows("1")) tk.MustExec("alter table t modify b char(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "b", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeString) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeString, modifiedColumn.Tp) tk.MustQuery("select b from t").Check(testkit.Rows("11")) tk.MustExec("alter table t modify c binary(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "c", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeString) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeString, modifiedColumn.Tp) tk.MustQuery("select c from t").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00")) tk.MustExec("alter table t modify d varbinary(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "d", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeVarchar) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeVarchar, modifiedColumn.Tp) tk.MustQuery("select d from t").Check(testkit.Rows("1111")) tk.MustExec("alter table t modify e blob(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "e", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeTinyBlob) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "e", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.Tp) tk.MustQuery("select e from t").Check(testkit.Rows("11111")) tk.MustExec("alter table t modify f text(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "f", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeTinyBlob) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "f", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeTinyBlob, modifiedColumn.Tp) tk.MustQuery("select f from t").Check(testkit.Rows("111111")) // integer to decimal prepare(tk) tk.MustExec("alter table t modify a decimal(2,1)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "a", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeNewDecimal) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeNewDecimal, modifiedColumn.Tp) tk.MustQuery("select a from t").Check(testkit.Rows("1.0")) // integer to year // For year(2), MySQL converts values in the ranges '0' to '69' and '70' to '99' to YEAR values in the ranges 2000 to 2069 and 1970 to 1999. tk.MustExec("alter table t modify b year") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "b", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeYear) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeYear, modifiedColumn.Tp) tk.MustQuery("select b from t").Check(testkit.Rows("2011")) // integer to time tk.MustExec("alter table t modify c time") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "c", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeDuration) // mysql.TypeTime has rename to TypeDuration. + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeDuration, modifiedColumn.Tp) tk.MustQuery("select c from t").Check(testkit.Rows("00:01:11")) // integer to date (mysql will throw `Incorrect date value: '1111' for column 'd' at row 1` error) tk.MustExec("alter table t modify d date") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "d", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeDate) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeDate, modifiedColumn.Tp) tk.MustQuery("select d from t").Check(testkit.Rows("2000-11-11")) // the given number will be left-forward used. // integer to timestamp (according to what timezone you have set) tk.MustExec("alter table t modify e timestamp") tk.MustExec("set @@session.time_zone=UTC") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "e", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeTimestamp) - tk.MustQuery("select e from t").Check(testkit.Rows("2001-11-11 00:00:00")) // the given number will be left-forward used. + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "e", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeTimestamp, modifiedColumn.Tp) + tk.MustQuery("select e from t").Check(testkit.Rows("2001-11-10 16:00:00")) // the given number will be left-forward used. // integer to datetime tk.MustExec("alter table t modify f datetime") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "f", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeDatetime) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "f", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeDatetime, modifiedColumn.Tp) tk.MustQuery("select f from t").Check(testkit.Rows("2011-11-11 00:00:00")) // the given number will be left-forward used. // integer to floating-point values prepare(tk) tk.MustExec("alter table t modify a float") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "a", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeFloat) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeFloat, modifiedColumn.Tp) tk.MustQuery("select a from t").Check(testkit.Rows("1")) tk.MustExec("alter table t modify b double") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "b", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeDouble) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeDouble, modifiedColumn.Tp) tk.MustQuery("select b from t").Check(testkit.Rows("11")) // integer to bit tk.MustExec("alter table t modify c bit(10)") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "c", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeBit) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "c", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeBit, modifiedColumn.Tp) // 111 will be stored ad 0x00,0110,1111 = 0x6F, which will be shown as ASCII('o')=111 as well. tk.MustQuery("select c from t").Check(testkit.Rows("\x00o")) // integer to json tk.MustExec("alter table t modify d json") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "d", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeJSON) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "d", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeJSON, modifiedColumn.Tp) tk.MustQuery("select d from t").Check(testkit.Rows("1111")) // integer to enum prepareForEnumSet(tk) // TiDB take integer as the enum element offset to cast. tk.MustExec("alter table t modify a enum(\"a\", \"b\")") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "a", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeEnum) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "a", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeEnum, modifiedColumn.Tp) tk.MustQuery("select a from t").Check(testkit.Rows("a")) // TiDB take integer as the set element offset to cast. tk.MustExec("alter table t modify b set(\"a\", \"b\")") - modifiedColumn = getModifyColumn(c, tk.Se, "test", "t", "b", false) - c.Assert(modifiedColumn, NotNil) - c.Assert(modifiedColumn.Tp, Equals, parser_mysql.TypeSet) + modifiedColumn = external.GetModifyColumn(t, tk, "test", "t", "b", false) + require.NotNil(t, modifiedColumn) + require.Equal(t, mysql.TypeSet, modifiedColumn.Tp) tk.MustQuery("select b from t").Check(testkit.Rows("a")) // TiDB can't take integer as the enum element string to cast, while the MySQL can. - tk.MustGetErrCode("alter table t modify d enum(\"11111\", \"22222\")", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify d enum(\"11111\", \"22222\")", errno.WarnDataTruncated) // TiDB can't take integer as the set element string to cast, while the MySQL can. - tk.MustGetErrCode("alter table t modify e set(\"11111\", \"22222\")", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify e set(\"11111\", \"22222\")", errno.WarnDataTruncated) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeBetweenVarcharAndNonVarchar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeBetweenVarcharAndNonVarchar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("drop database if exists col_type_change_char;") tk.MustExec("create database col_type_change_char;") tk.MustExec("use col_type_change_char;") @@ -466,15 +439,17 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeBetweenVarcharAndNonVarc tk.MustQuery("select a from t;").Check(testkit.Rows("aaa")) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeFromStringToOthers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Set time zone to UTC. - originalTz := tk.Se.GetSessionVars().TimeZone - tk.Se.GetSessionVars().TimeZone = time.UTC + originalTz := tk.Session().GetSessionVars().TimeZone + tk.Session().GetSessionVars().TimeZone = time.UTC defer func() { - tk.Se.GetSessionVars().TimeZone = originalTz + tk.Session().GetSessionVars().TimeZone = originalTz }() // Init string date type table. @@ -534,12 +509,12 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) // bit reset(tk) tk.MustExec("insert into t values ('1', '1', '1', '1', '1', '1', '123', '123')") - tk.MustGetErrCode("alter table t modify c bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify vc bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify bny bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify vbny bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify bb bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify txt bit", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify c bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify vc bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify bny bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify vbny bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify bb bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify txt bit", errno.ErrUnsupportedDDLOperation) tk.MustExec("alter table t modify e bit") tk.MustExec("alter table t modify s bit") tk.MustQuery("select * from t").Check(testkit.Rows("1 1 1\x00\x00\x00\x00\x00\x00\x00 1 1 1 \x01 \x01")) @@ -548,7 +523,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) tk.MustExec("insert into t values ('123.45', '123.45', '123.45', '123.45', '123.45', '123.45', '123', '123')") tk.MustExec("alter table t modify c decimal(7, 4)") tk.MustExec("alter table t modify vc decimal(7, 4)") - tk.MustGetErrCode("alter table t modify bny decimal(7, 4)", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify bny decimal(7, 4)", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify vbny decimal(7, 4)") tk.MustExec("alter table t modify bb decimal(7, 4)") tk.MustExec("alter table t modify txt decimal(7, 4)") @@ -578,9 +553,9 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) tk.MustExec("alter table t modify vbny date") tk.MustExec("alter table t modify bb date") // Alter text '08-26 19:35:41' to date will error. (same as mysql does) - tk.MustGetErrCode("alter table t modify txt date", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify e date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify s date", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify txt date", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify e date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify s date", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-08-26 2020-08-26 2020-08-26 2020-08-26 2020-08-26 08-26 19:35:41 2020-07-15 18:32:17.888 2020-07-15 18:32:17.888")) // time reset(tk) @@ -591,8 +566,8 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) tk.MustExec("alter table t modify vbny time") tk.MustExec("alter table t modify bb time") tk.MustExec("alter table t modify txt time") - tk.MustGetErrCode("alter table t modify e time", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify s time", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify e time", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify s time", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("19:35:41 19:35:41 19:35:41 19:35:41 19:35:41 19:35:41 2020-07-15 18:32:17.888 2020-07-15 18:32:17.888")) // datetime reset(tk) @@ -607,8 +582,8 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) tk.MustExec("alter table t modify vbny datetime") tk.MustExec("alter table t modify bb datetime") tk.MustExec("alter table t modify txt datetime") - tk.MustGetErrCode("alter table t modify e datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify s datetime", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify e datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify s datetime", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:17.888 2020-07-15 18:32:17.888")) // timestamp reset(tk) @@ -623,8 +598,8 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) tk.MustExec("alter table t modify vbny timestamp") tk.MustExec("alter table t modify bb timestamp") tk.MustExec("alter table t modify txt timestamp") - tk.MustGetErrCode("alter table t modify e timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify s timestamp", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify e timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify s timestamp", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:18 2020-07-15 18:32:17.888 2020-07-15 18:32:17.888")) // year reset(tk) @@ -658,24 +633,24 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) reset(tk) tk.MustExec("insert into t values ('123x', 'x123', 'abc', 'datetime', 'timestamp', 'date', '123', '123')") - tk.MustGetErrCode("alter table t modify c int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify c int", errno.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify vc smallint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify vc smallint", errno.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify bny bigint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify bny bigint", errno.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify vbny datetime", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify vbny datetime", errno.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify bb timestamp", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify bb timestamp", errno.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify txt date", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify txt date", errno.ErrTruncatedWrongValue) reset(tk) tk.MustExec("alter table t modify vc varchar(20)") tk.MustExec("insert into t(c, vc) values ('1x', '20200915110836')") - tk.MustGetErrCode("alter table t modify c year", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify c year", errno.ErrTruncatedWrongValue) - // Special cases about different behavior between TiDB and MySQL. + // Special cases about different behavior between TiDB and errno. // MySQL will get warning but TiDB not. // MySQL will get "Warning 1292 Incorrect time value: '20200915110836' for column 'vc'" tk.MustExec("alter table t modify vc time") @@ -686,22 +661,24 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C) reset(tk) tk.MustExec("alter table t modify c char(15)") tk.MustExec("insert into t(c) values ('{\"k1\": \"value\"')") - tk.MustGetErrCode("alter table t modify c json", mysql.ErrInvalidJSONText) + tk.MustGetErrCode("alter table t modify c json", errno.ErrInvalidJSONText) // MySQL will get "ERROR 1366 (HY000): Incorrect DECIMAL value: '0' for column '' at row -1" error. tk.MustExec("insert into t(vc) values ('abc')") - tk.MustGetErrCode("alter table t modify vc decimal(5,3)", mysql.ErrBadNumber) + tk.MustGetErrCode("alter table t modify vc decimal(5,3)", errno.ErrBadNumber) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeFromNumericToOthers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Set time zone to UTC. - originalTz := tk.Se.GetSessionVars().TimeZone - tk.Se.GetSessionVars().TimeZone = time.UTC + originalTz := tk.Session().GetSessionVars().TimeZone + tk.Session().GetSessionVars().TimeZone = time.UTC defer func() { - tk.Se.GetSessionVars().TimeZone = originalTz + tk.Session().GetSessionVars().TimeZone = originalTz }() // Init string date type table. @@ -724,12 +701,12 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C // tinyint reset(tk) tk.MustExec("insert into t values (-258.12345, 333.33, 2000000.20000002, 323232323.3232323232, -111.11111111, -222222222222.222222222222222, b'10101')") - tk.MustGetErrCode("alter table t modify d tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify n tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify r tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify db tinyint", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify d tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify n tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify r tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify db tinyint", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify f32 tinyint") - tk.MustGetErrCode("alter table t modify f64 tinyint", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify f64 tinyint", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify b tinyint") tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111 -222222222222.22223 21")) // int @@ -740,7 +717,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C tk.MustExec("alter table t modify r int") tk.MustExec("alter table t modify db int") tk.MustExec("alter table t modify f32 int") - tk.MustGetErrCode("alter table t modify f64 int", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify f64 int", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify b int") tk.MustQuery("select * from t").Check(testkit.Rows("-258 333 2000000 323232323 -111 -222222222222.22223 21")) // bigint @@ -758,14 +735,14 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C reset(tk) tk.MustExec("insert into t values (-258.12345, 333.33, 2000000.20000002, 323232323.3232323232, -111.11111111, -222222222222.222222222222222, b'10101')") // MySQL will get "ERROR 1264 (22001): Data truncation: Out of range value for column 'd' at row 1". - tk.MustGetErrCode("alter table t modify d bigint unsigned", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify d bigint unsigned", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify n bigint unsigned") tk.MustExec("alter table t modify r bigint unsigned") tk.MustExec("alter table t modify db bigint unsigned") // MySQL will get "ERROR 1264 (22001): Data truncation: Out of range value for column 'f32' at row 1". - tk.MustGetErrCode("alter table t modify f32 bigint unsigned", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify f32 bigint unsigned", errno.ErrDataOutOfRange) // MySQL will get "ERROR 1264 (22001): Data truncation: Out of range value for column 'f64' at row 1". - tk.MustGetErrCode("alter table t modify f64 bigint unsigned", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify f64 bigint unsigned", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify b int") tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333 2000000 323232323 -111.111115 -222222222222.22223 21")) @@ -797,18 +774,18 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C // MySQL will get "ERROR 1406 (22001): Data truncation: Data too long for column 'f64' at row 1". tk.MustExec("alter table t modify f64 varchar(30)") tk.MustExec("alter table t modify b varchar(30)") - tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 \x15")) + tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 21")) // binary reset(tk) tk.MustExec("insert into t values (-258.12345, 333.33, 2000000.20000002, 323232323.3232323232, -111.11111111, -222222222222.222222222222222, b'10101')") - tk.MustGetErrCode("alter table t modify d binary(10)", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify d binary(10)", errno.WarnDataTruncated) tk.MustExec("alter table t modify n binary(10)") - tk.MustGetErrCode("alter table t modify r binary(10)", mysql.WarnDataTruncated) - tk.MustGetErrCode("alter table t modify db binary(10)", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify r binary(10)", errno.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify db binary(10)", errno.WarnDataTruncated) // MySQL will run with no error. - tk.MustGetErrCode("alter table t modify f32 binary(10)", mysql.WarnDataTruncated) - tk.MustGetErrCode("alter table t modify f64 binary(10)", mysql.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify f32 binary(10)", errno.WarnDataTruncated) + tk.MustGetErrCode("alter table t modify f64 binary(10)", errno.WarnDataTruncated) tk.MustExec("alter table t modify b binary(10)") tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33\x00\x00\x00\x00 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 21\x00\x00\x00\x00\x00\x00\x00\x00")) @@ -837,7 +814,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C tk.MustExec("alter table t modify f32 blob") tk.MustExec("alter table t modify f64 blob") tk.MustExec("alter table t modify b blob") - tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 \x15")) + tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 21")) // text reset(tk) @@ -850,30 +827,30 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C tk.MustExec("alter table t modify f32 text") tk.MustExec("alter table t modify f64 text") tk.MustExec("alter table t modify b text") - tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 \x15")) + tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111115 -222222222222.22223 21")) // enum reset(tk) tk.MustExec("insert into t values (-258.12345, 333.33, 2000000.20000002, 323232323.3232323232, -111.111, -222222222222.222222222222222, b'10101')") - tk.MustGetErrCode("alter table t modify d enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify n enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify r enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify db enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f32 enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify b enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify n enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify r enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify db enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f32 enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b enum('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111 -222222222222.22223 \x15")) // set reset(tk) tk.MustExec("insert into t values (-258.12345, 333.33, 2000000.20000002, 323232323.3232323232, -111.111, -222222222222.222222222222222, b'10101')") - tk.MustGetErrCode("alter table t modify d set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify n set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify r set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify db set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f32 set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify b set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify n set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify r set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify db set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f32 set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b set('-258.12345', '333.33', '2000000.20000002', '323232323.3232323232', '-111.111', '-222222222222.222222222222222', b'10101')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("-258.1234500 333.33 2000000.20000002 323232323.32323235 -111.111 -222222222222.22223 \x15")) // To date and time data types. @@ -881,57 +858,57 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C reset(tk) tk.MustExec("insert into t values (200805.11, 307.333, 20200805.11111111, 20200805111307.11111111, 200805111307.11111111, 20200805111307.11111111, b'10101')") // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect datetime value: '200805.1100000' for column 'd' at row 1". - tk.MustGetErrCode("alter table t modify d datetime", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d datetime", errno.ErrUnsupportedDDLOperation) // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect datetime value: '307.33' for column 'n' at row 1". - tk.MustGetErrCode("alter table t modify n datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify r datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify db datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f32 datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 datetime", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify b datetime", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify n datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify r datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify db datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f32 datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 datetime", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b datetime", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("200805.1100000 307.33 20200805.11111111 20200805111307.11 200805100000 20200805111307.11 \x15")) // time reset(tk) tk.MustExec("insert into t values (200805.11, 307.333, 20200805.11111111, 20200805111307.11111111, 200805111307.11111111, 20200805111307.11111111, b'10101')") tk.MustExec("alter table t modify d time") tk.MustExec("alter table t modify n time") - tk.MustGetErrCode("alter table t modify r time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify r time", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify db time") tk.MustExec("alter table t modify f32 time") tk.MustExec("alter table t modify f64 time") - tk.MustGetErrCode("alter table t modify b time", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b time", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("20:08:05 00:03:07 20200805.11111111 11:13:07 10:00:00 11:13:07 \x15")) // date reset(tk) tk.MustExec("insert into t values (200805.11, 307.333, 20200805.11111111, 20200805111307.11111111, 200805111307.11111111, 20200805111307.11111111, b'10101')") // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect date value: '200805.1100000' for column 'd' at row 1". - tk.MustGetErrCode("alter table t modify d date", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d date", errno.ErrUnsupportedDDLOperation) // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect date value: '307.33' for column 'n' at row 1". - tk.MustGetErrCode("alter table t modify n date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify r date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify db date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f32 date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 date", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify b date", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify n date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify r date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify db date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f32 date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 date", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b date", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("200805.1100000 307.33 20200805.11111111 20200805111307.11 200805100000 20200805111307.11 \x15")) // timestamp reset(tk) tk.MustExec("insert into t values (200805.11, 307.333, 20200805.11111111, 20200805111307.11111111, 200805111307.11111111, 20200805111307.11111111, b'10101')") // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect datetime value: '200805.1100000' for column 'd' at row 1". - tk.MustGetErrCode("alter table t modify d timestamp", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d timestamp", errno.ErrUnsupportedDDLOperation) // MySQL will get "ERROR 1292 (22001) Data truncation: Incorrect datetime value: '307.33' for column 'n' at row 1". - tk.MustGetErrCode("alter table t modify n timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify r timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify db timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f32 timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 timestamp", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify b timestamp", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify n timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify r timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify db timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f32 timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 timestamp", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify b timestamp", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("200805.1100000 307.33 20200805.11111111 20200805111307.11 200805100000 20200805111307.11 \x15")) // year reset(tk) tk.MustExec("insert into t values (200805.11, 307.333, 2.55555, 98.1111111, 2154.00001, 20200805111307.11111111, b'10101')") tk.MustGetErrMsg("alter table t modify d year", "[types:1264]Out of range value for column 'd', the value is '200805.1100000'") - tk.MustGetErrCode("alter table t modify n year", mysql.ErrWarnDataOutOfRange) + tk.MustGetErrCode("alter table t modify n year", errno.ErrWarnDataOutOfRange) // MySQL will get "ERROR 1264 (22001) Data truncation: Out of range value for column 'r' at row 1". tk.MustExec("alter table t modify r year") // MySQL will get "ERROR 1264 (22001) Data truncation: Out of range value for column 'db' at row 1". @@ -956,18 +933,17 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromNumericToOthers(c *C } // Test issue #20529. -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeIgnoreDisplayLength(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeIgnoreDisplayLength(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - var assertResult bool assertHasAlterWriteReorg := func(tbl table.Table) { - // Restore the assert result to false. + // Restore assertResult to false. assertResult = false - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} hook.OnJobRunBeforeExported = func(job *model.Job) { if tbl.Meta().ID != job.TableID { return @@ -976,38 +952,40 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeIgnoreDisplayLength(c *C assertResult = true } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) } // Change int to tinyint. // Although display length is increased, the default flen is decreased, reorg is needed. tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int(1))") - tbl := testGetTableByName(c, tk.Se, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") assertHasAlterWriteReorg(tbl) tk.MustExec("alter table t modify column a tinyint(3)") - c.Assert(assertResult, Equals, true) + require.True(t, assertResult) // Change tinyint to tinyint // Although display length is decreased, default flen is the same, reorg is not needed. tk.MustExec("drop table if exists t") tk.MustExec("create table t(a tinyint(3))") - tbl = testGetTableByName(c, tk.Se, "test", "t") + tbl = external.GetTableByName(t, tk, "test", "t") assertHasAlterWriteReorg(tbl) tk.MustExec("alter table t modify column a tinyint(1)") - c.Assert(assertResult, Equals, false) + require.False(t, assertResult) tk.MustExec("drop table if exists t") } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromDateTimeTypeToOthers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeFromDateTimeTypeToOthers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Set time zone to UTC. - originalTz := tk.Se.GetSessionVars().TimeZone - tk.Se.GetSessionVars().TimeZone = time.UTC + originalTz := tk.Session().GetSessionVars().TimeZone + tk.Session().GetSessionVars().TimeZone = time.UTC defer func() { - tk.Se.GetSessionVars().TimeZone = originalTz + tk.Session().GetSessionVars().TimeZone = originalTz }() // Init string date type table. @@ -1028,19 +1006,19 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromDateTimeTypeToOthers // tinyint reset(tk) tk.MustExec("insert into t values ('2020-10-30', '19:38:25.001', 20201030082133.455555, 20201030082133.455555, 2020)") - tk.MustGetErrCode("alter table t modify d tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify t tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify dt tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify tmp tinyint", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify y tinyint", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify d tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify t tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify dt tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify tmp tinyint", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify y tinyint", errno.ErrDataOutOfRange) tk.MustQuery("select * from t").Check(testkit.Rows("2020-10-30 19:38:25.001 2020-10-30 08:21:33.455555 2020-10-30 08:21:33.455555 2020")) // int reset(tk) tk.MustExec("insert into t values ('2020-10-30', '19:38:25.001', 20201030082133.455555, 20201030082133.455555, 2020)") tk.MustExec("alter table t modify d int") tk.MustExec("alter table t modify t int") - tk.MustGetErrCode("alter table t modify dt int", mysql.ErrDataOutOfRange) - tk.MustGetErrCode("alter table t modify tmp int", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify dt int", errno.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify tmp int", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify y int") tk.MustQuery("select * from t").Check(testkit.Rows("20201030 193825 2020-10-30 08:21:33.455555 2020-10-30 08:21:33.455555 2020")) // bigint @@ -1055,11 +1033,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromDateTimeTypeToOthers // bit reset(tk) tk.MustExec("insert into t values ('2020-10-30', '19:38:25.001', 20201030082133.455555, 20201030082133.455555, 2020)") - tk.MustGetErrCode("alter table t modify d bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify dt bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify tmp bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify y bit", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify dt bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify tmp bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify y bit", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-10-30 19:38:25.001 2020-10-30 08:21:33.455555 2020-10-30 08:21:33.455555 2020")) // decimal reset(tk) @@ -1148,21 +1126,21 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromDateTimeTypeToOthers // enum reset(tk) tk.MustExec("insert into t values ('2020-10-30', '19:38:25.001', 20201030082133.455555, 20201030082133.455555, 2020)") - tk.MustGetErrCode("alter table t modify d enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify dt enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify tmp enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify y enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify dt enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify tmp enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify y enum('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-10-30 19:38:25.001 2020-10-30 08:21:33.455555 2020-10-30 08:21:33.455555 2020")) // set reset(tk) tk.MustExec("insert into t values ('2020-10-30', '19:38:25.001', 20201030082133.455555, 20201030082133.455555, 2020)") - tk.MustGetErrCode("alter table t modify d set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify dt set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify tmp set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify y set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify d set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify dt set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify tmp set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify y set('2020-10-30', '19:38:25.001', '20201030082133.455555', '2020')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("2020-10-30 19:38:25.001 2020-10-30 08:21:33.455555 2020-10-30 08:21:33.455555 2020")) // To json data type. @@ -1176,15 +1154,17 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromDateTimeTypeToOthers tk.MustQuery("select * from t").Check(testkit.Rows("\"2020-10-30\" \"19:38:25.001\" \"2020-10-30 08:21:33.455555\" \"2020-10-30 08:21:33.455555\" 2020")) } -func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnTypeChangeFromJsonToOthers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Set time zone to UTC. - originalTz := tk.Se.GetSessionVars().TimeZone - tk.Se.GetSessionVars().TimeZone = time.UTC + originalTz := tk.Session().GetSessionVars().TimeZone + tk.Session().GetSessionVars().TimeZone = time.UTC defer func() { - tk.Se.GetSessionVars().TimeZone = originalTz + tk.Session().GetSessionVars().TimeZone = originalTz }() // Init string date type table. @@ -1211,20 +1191,20 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj tinyint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj tinyint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '[-1, 0, 1]' for column 'arr' at row 1". - tk.MustGetErrCode("alter table t modify arr tinyint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr tinyint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil tinyint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil tinyint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'true' for column 't' at row 1". tk.MustExec("alter table t modify t tinyint") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'false' for column 'f' at row 1". tk.MustExec("alter table t modify f tinyint") tk.MustExec("alter table t modify i tinyint") tk.MustExec("alter table t modify ui tinyint") - tk.MustGetErrCode("alter table t modify f64 tinyint", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify f64 tinyint", errno.ErrDataOutOfRange) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '"json string"' for column 'str' at row 1". - tk.MustGetErrCode("alter table t modify str tinyint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify str tinyint", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify nul tinyint") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1 0 -22 22 323232323.32323235 \"json string\" ")) @@ -1232,11 +1212,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj int", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '[-1, 0, 1]' for column 'arr' at row 1". - tk.MustGetErrCode("alter table t modify arr int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr int", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil int", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'true' for column 't' at row 1". tk.MustExec("alter table t modify t int") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'false' for column 'f' at row 1". @@ -1245,7 +1225,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { tk.MustExec("alter table t modify ui int") tk.MustExec("alter table t modify f64 int") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '"json string"' for column 'str' at row 1". - tk.MustGetErrCode("alter table t modify str int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify str int", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify nul int") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1 0 -22 22 323232323 \"json string\" ")) @@ -1253,11 +1233,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj bigint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj bigint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '[-1, 0, 1]' for column 'arr' at row 1". - tk.MustGetErrCode("alter table t modify arr bigint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr bigint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil bigint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil bigint", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'true' for column 't' at row 1". tk.MustExec("alter table t modify t bigint") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'false' for column 'f' at row 1". @@ -1266,7 +1246,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { tk.MustExec("alter table t modify ui bigint") tk.MustExec("alter table t modify f64 bigint") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '"json string"' for column 'str' at row 1". - tk.MustGetErrCode("alter table t modify str bigint", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify str bigint", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify nul bigint") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1 0 -22 22 323232323 \"json string\" ")) @@ -1274,55 +1254,55 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj bigint unsigned", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj bigint unsigned", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '[-1, 0, 1]' for column 'arr' at row 1". - tk.MustGetErrCode("alter table t modify arr bigint unsigned", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr bigint unsigned", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil bigint unsigned", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil bigint unsigned", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'true' for column 't' at row 1". tk.MustExec("alter table t modify t bigint unsigned") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: 'false' for column 'f' at row 1". tk.MustExec("alter table t modify f bigint unsigned") // MySQL will get "ERROR 1264 (22003) Out of range value for column 'i' at row 1". - tk.MustGetErrCode("alter table t modify i bigint unsigned", mysql.ErrDataOutOfRange) + tk.MustGetErrCode("alter table t modify i bigint unsigned", errno.ErrDataOutOfRange) tk.MustExec("alter table t modify ui bigint unsigned") tk.MustExec("alter table t modify f64 bigint unsigned") // MySQL will get "ERROR 1366 (HY000) Incorrect integer value: '"json string"' for column 'str' at row 1". - tk.MustGetErrCode("alter table t modify str bigint unsigned", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify str bigint unsigned", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify nul bigint unsigned") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1 0 -22 22 323232323 \"json string\" ")) // bit reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") - tk.MustGetErrCode("alter table t modify obj bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify arr bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nil bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify i bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify ui bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify str bit", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nul bit", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify obj bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify arr bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nil bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify i bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify ui bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify str bit", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nul bit", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null true false -22 22 323232323.32323235 \"json string\" ")) // decimal reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 3156 (22001) Invalid JSON value for CAST to DECIMAL from column obj at row 1". - tk.MustGetErrCode("alter table t modify obj decimal(20, 10)", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj decimal(20, 10)", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 3156 (22001) Invalid JSON value for CAST to DECIMAL from column arr at row 1". - tk.MustGetErrCode("alter table t modify arr decimal(20, 10)", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr decimal(20, 10)", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 3156 (22001) Invalid JSON value for CAST to DECIMAL from column nil at row 1". - tk.MustGetErrCode("alter table t modify nil decimal(20, 10)", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil decimal(20, 10)", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify t decimal(20, 10)") tk.MustExec("alter table t modify f decimal(20, 10)") tk.MustExec("alter table t modify i decimal(20, 10)") tk.MustExec("alter table t modify ui decimal(20, 10)") tk.MustExec("alter table t modify f64 decimal(20, 10)") // MySQL will get "ERROR 1366 (HY000): Incorrect DECIMAL value: '0' for column '' at row -1". - tk.MustGetErrCode("alter table t modify str decimal(20, 10)", mysql.ErrBadNumber) + tk.MustGetErrCode("alter table t modify str decimal(20, 10)", errno.ErrBadNumber) tk.MustExec("alter table t modify nul decimal(20, 10)") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1.0000000000 0.0000000000 -22.0000000000 22.0000000000 323232323.3232323500 \"json string\" ")) @@ -1330,11 +1310,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") // MySQL will get "ERROR 1265 (01000): Data truncated for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj double", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj double", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1265 (01000): Data truncated for column 'arr' at row 1". - tk.MustGetErrCode("alter table t modify arr double", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr double", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1265 (01000): Data truncated for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil double", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil double", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1265 (01000): Data truncated for column 't' at row 1". tk.MustExec("alter table t modify t double") // MySQL will get "ERROR 1265 (01000): Data truncated for column 'f' at row 1". @@ -1343,7 +1323,7 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { tk.MustExec("alter table t modify ui double") tk.MustExec("alter table t modify f64 double") // MySQL will get "ERROR 1265 (01000): Data truncated for column 'str' at row 1". - tk.MustGetErrCode("alter table t modify str double", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify str double", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify nul double") tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 1 0 -22 22 323232323.32323235 \"json string\" ")) @@ -1449,42 +1429,42 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { // enum reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") - tk.MustGetErrCode("alter table t modify obj enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify arr enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nil enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify i enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify ui enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify str enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nul enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify obj enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify arr enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nil enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify i enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify ui enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify str enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nul enum('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null true false -22 22 323232323.32323235 \"json string\" ")) // set reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"', null)") - tk.MustGetErrCode("alter table t modify obj set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify arr set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nil set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify t set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify i set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify ui set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify f64 set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify str set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify nul set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", mysql.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify obj set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify arr set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nil set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify t set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify i set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify ui set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify f64 set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify str set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t modify nul set('{\"obj\": 100}', '[-1]', 'null', 'true', 'false', '-22', '22', '323232323.3232323232', '\"json string\"')", errno.ErrUnsupportedDDLOperation) tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1] null true false -22 22 323232323.32323235 \"json string\" ")) // To date and time data types. // datetime reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '20200826173501', '20201123', '20200826173501.123456', '\"2020-08-26 17:35:01.123456\"', null)") - tk.MustGetErrCode("alter table t modify obj datetime", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify arr datetime", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify nil datetime", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify t datetime", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify f datetime", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj datetime", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr datetime", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil datetime", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify t datetime", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify f datetime", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify i datetime") tk.MustExec("alter table t modify ui datetime") tk.MustExec("alter table t modify f64 datetime") @@ -1497,15 +1477,15 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '200805', '1111', '200805.11', '\"19:35:41\"', null)") // MySQL will get "ERROR 1366 (HY000): Incorrect time value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj time", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect time value: '[-1, 0, 1]' for column 'arr' at row 11". - tk.MustGetErrCode("alter table t modify arr time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr time", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect time value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil time", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect time value: 'true' for column 't' at row 1". - tk.MustGetErrCode("alter table t modify t time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify t time", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect time value: 'true' for column 't' at row 1". - tk.MustGetErrCode("alter table t modify f time", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify f time", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify i time") tk.MustExec("alter table t modify ui time") tk.MustExec("alter table t modify f64 time") @@ -1517,11 +1497,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { // date reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '20200826173501', '20201123', '20200826173501.123456', '\"2020-08-26 17:35:01.123456\"', null)") - tk.MustGetErrCode("alter table t modify obj date", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify arr date", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify nil date", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify t date", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify f date", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj date", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr date", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil date", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify t date", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify f date", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify i date") tk.MustExec("alter table t modify ui date") tk.MustExec("alter table t modify f64 date") @@ -1533,11 +1513,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { // timestamp reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '20200826173501', '20201123', '20200826173501.123456', '\"2020-08-26 17:35:01.123456\"', null)") - tk.MustGetErrCode("alter table t modify obj timestamp", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify arr timestamp", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify nil timestamp", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify t timestamp", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify f timestamp", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj timestamp", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr timestamp", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil timestamp", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify t timestamp", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify f timestamp", errno.ErrTruncatedWrongValue) tk.MustExec("alter table t modify i timestamp") tk.MustExec("alter table t modify ui timestamp") tk.MustExec("alter table t modify f64 timestamp") @@ -1550,11 +1530,11 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { reset(tk) tk.MustExec("insert into t values ('{\"obj\": 100}', '[-1, 0, 1]', 'null', 'true', 'false', '2020', '91', '9', '\"2020\"', null)") // MySQL will get "ERROR 1366 (HY000): Incorrect integer value: '{"obj": 100}' for column 'obj' at row 1". - tk.MustGetErrCode("alter table t modify obj year", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify obj year", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect integer value: '[-1, 0, 1]' for column 'arr' at row 11". - tk.MustGetErrCode("alter table t modify arr year", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify arr year", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect integer value: 'null' for column 'nil' at row 1". - tk.MustGetErrCode("alter table t modify nil year", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify nil year", errno.ErrTruncatedWrongValue) // MySQL will get "ERROR 1366 (HY000): Incorrect integer value: 'true' for column 't' at row 1". tk.MustExec("alter table t modify t year") // MySQL will get "ERROR 1366 (HY000): Incorrect integer value: 'false' for column 'f' at row 1". @@ -1568,8 +1548,10 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromJsonToOthers(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("{\"obj\": 100} [-1, 0, 1] null 2001 0 2020 1991 2009 2020 ")) } -func (s *testColumnTypeChangeSuite) TestUpdateDataAfterChangeTimestampToDate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateDataAfterChangeTimestampToDate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, t1") tk.MustExec("create table t (col timestamp default '1971-06-09' not null, col1 int default 1, unique key(col1));") @@ -1589,22 +1571,24 @@ func (s *testColumnTypeChangeSuite) TestUpdateDataAfterChangeTimestampToDate(c * } // TestRowFormat is used to close issue #21391, the encoded row in column type change should be aware of the new row format. -func (s *testColumnTypeChangeSuite) TestRowFormat(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRowFormat(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key, v varchar(10))") tk.MustExec("insert into t values (1, \"123\");") tk.MustExec("alter table t modify column v varchar(5);") - tbl := testGetTableByName(c, tk.Se, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") encodedKey := tablecodec.EncodeRowKeyWithHandle(tbl.Meta().ID, kv.IntHandle(1)) - h := helper.NewHelper(s.store.(helper.Storage)) + h := helper.NewHelper(store.(helper.Storage)) data, err := h.GetMvccByEncodedKey(encodedKey) - c.Assert(err, IsNil) + require.NoError(t, err) // The new format will start with CodecVer = 128 (0x80). - c.Assert(data.Info.Writes[0].ShortValue, DeepEquals, []byte{0x80, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x1, 0x0, 0x4, 0x0, 0x7, 0x0, 0x1, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33}) + require.Equal(t, []byte{0x80, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x1, 0x0, 0x4, 0x0, 0x7, 0x0, 0x1, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33}, data.Info.Writes[0].ShortValue) tk.MustExec("drop table if exists t") } @@ -1614,11 +1598,13 @@ func (s *testColumnTypeChangeSuite) TestRowFormat(c *C) { // The added column with NOT-NULL option will be fetched with error when it's origin default value is not set. // It's good because the insert / update logic will cast the related column to changing column rather than use // origin default value directly. -func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangingColOriginDefaultValue(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1626,9 +1612,9 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValue(c *C) { tk.MustExec("insert into t values(1, 1)") tk.MustExec("insert into t values(2, 2)") - tbl := testGetTableByName(c, tk.Se, "test", "t") - originalHook := s.dom.DDL().GetHook() - hook := &ddl.TestDDLCallback{Do: s.dom} + tbl := external.GetTableByName(t, tk, "test", "t") + originalHook := dom.DDL().GetHook() + hook := &ddl.TestDDLCallback{Do: dom} var ( once bool checkErr error @@ -1644,7 +1630,7 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValue(c *C) { if (job.SchemaState == model.StateWriteOnly || job.SchemaState == model.StateWriteReorganization) && i < 3 { if !once { once = true - tbl := testGetTableByName(c, tk1.Se, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") if len(tbl.WritableCols()) != 3 { checkErr = errors.New("assert the writable column number error") return @@ -1680,20 +1666,22 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValue(c *C) { i++ } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) tk.MustExec("alter table t modify column b tinyint NOT NULL") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - c.Assert(checkErr, IsNil) + dom.DDL().SetHook(originalHook) + require.NoError(t, checkErr) // Since getReorgInfo will stagnate StateWriteReorganization for a ddl round, so insert should exec 3 times. tk.MustQuery("select * from t order by a").Check(testkit.Rows("1 -1", "2 -2", "3 3", "4 4", "5 5")) tk.MustExec("drop table if exists t") } -func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddColAndCastSucc(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangingColOriginDefaultValueAfterAddColAndCastSucc(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") tk.MustExec("set time_zone = 'UTC'") @@ -1703,9 +1691,9 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol tk.MustExec("insert into t values(2, 2)") tk.MustExec("alter table t add column c timestamp default '1971-06-09' not null") - tbl := testGetTableByName(c, tk.Se, "test", "t") - originalHook := s.dom.DDL().GetHook() - hook := &ddl.TestDDLCallback{Do: s.dom} + tbl := external.GetTableByName(t, tk, "test", "t") + originalHook := dom.DDL().GetHook() + hook := &ddl.TestDDLCallback{Do: dom} var ( once bool checkErr error @@ -1721,7 +1709,7 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol if (job.SchemaState == model.StateWriteOnly || job.SchemaState == model.StateWriteReorganization) && stableTimes < 3 { if !once { once = true - tbl := testGetTableByName(c, tk1.Se, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") if len(tbl.WritableCols()) != 4 { checkErr = errors.New("assert the writable column number error") return @@ -1764,10 +1752,10 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol i++ } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) tk.MustExec("alter table t modify column c date NOT NULL") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - c.Assert(checkErr, IsNil) + dom.DDL().SetHook(originalHook) + require.NoError(t, checkErr) // Since getReorgInfo will stagnate StateWriteReorganization for a ddl round, so insert should exec 3 times. tk.MustQuery("select * from t order by a").Check( testkit.Rows("1 -1 1971-06-09", "2 -2 1971-06-09", "5 5 2021-06-06", "6 6 2021-06-06", "7 7 2021-06-06")) @@ -1775,11 +1763,13 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol } // TestChangingColOriginDefaultValueAfterAddColAndCastFail tests #25383. -func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddColAndCastFail(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangingColOriginDefaultValueAfterAddColAndCastFail(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") tk.MustExec("set time_zone = 'UTC'") @@ -1787,9 +1777,9 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol tk.MustExec("create table t(a VARCHAR(31) NULL DEFAULT 'wwrzfwzb01j6ddj', b DECIMAL(12,0) NULL DEFAULT '-729850476163')") tk.MustExec("ALTER TABLE t ADD COLUMN x CHAR(218) NULL DEFAULT 'lkittuae'") - tbl := testGetTableByName(c, tk.Se, "test", "t") - originalHook := s.dom.DDL().GetHook() - hook := &ddl.TestDDLCallback{Do: s.dom} + tbl := external.GetTableByName(t, tk, "test", "t") + originalHook := dom.DDL().GetHook() + hook := &ddl.TestDDLCallback{Do: dom} var checkErr error hook.OnJobRunBeforeExported = func(job *model.Job) { if checkErr != nil { @@ -1800,7 +1790,7 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol } if job.SchemaState == model.StateWriteOnly || job.SchemaState == model.StateWriteReorganization { - tbl := testGetTableByName(c, tk1.Se, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") if len(tbl.WritableCols()) != 4 { errMsg := fmt.Sprintf("cols len:%v", len(tbl.WritableCols())) checkErr = errors.New("assert the writable column number error" + errMsg) @@ -1822,17 +1812,19 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) tk.MustExec("alter table t modify column x DATETIME NULL DEFAULT '3771-02-28 13:00:11' AFTER b;") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - c.Assert(checkErr, IsNil) + dom.DDL().SetHook(originalHook) + require.NoError(t, checkErr) tk.MustQuery("select * from t order by a").Check(testkit.Rows()) tk.MustExec("drop table if exists t") } // Close issue #22820 -func (s *testColumnTypeChangeSuite) TestChangingAttributeOfColumnWithFK(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangingAttributeOfColumnWithFK(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") prepare := func() { @@ -1845,63 +1837,69 @@ func (s *testColumnTypeChangeSuite) TestChangingAttributeOfColumnWithFK(c *C) { prepare() // For column with FK, alter action can be performed for changing null/not null, default value, comment and so on, but column type. tk.MustExec("alter table orders modify user_id int null;") - tbl := testGetTableByName(c, tk.Se, "test", "orders") - c.Assert(parser_mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag), Equals, false) + tbl := external.GetTableByName(t, tk, "test", "orders") + require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag)) prepare() tk.MustExec("alter table orders change user_id user_id2 int null") - tbl = testGetTableByName(c, tk.Se, "test", "orders") - c.Assert(tbl.Meta().Columns[1].Name.L, Equals, "user_id2") - c.Assert(parser_mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag), Equals, false) + tbl = external.GetTableByName(t, tk, "test", "orders") + require.Equal(t, "user_id2", tbl.Meta().Columns[1].Name.L) + require.Equal(t, false, mysql.HasNotNullFlag(tbl.Meta().Columns[1].Flag)) prepare() tk.MustExec("alter table orders modify user_id int default -1 comment \"haha\"") - tbl = testGetTableByName(c, tk.Se, "test", "orders") - c.Assert(tbl.Meta().Columns[1].Comment, Equals, "haha") - c.Assert(tbl.Meta().Columns[1].DefaultValue.(string), Equals, "-1") + tbl = external.GetTableByName(t, tk, "test", "orders") + require.Equal(t, "haha", tbl.Meta().Columns[1].Comment) + require.Equal(t, "-1", tbl.Meta().Columns[1].DefaultValue.(string)) prepare() - tk.MustGetErrCode("alter table orders modify user_id bigint", mysql.ErrFKIncompatibleColumns) + tk.MustGetErrCode("alter table orders modify user_id bigint", errno.ErrFKIncompatibleColumns) tk.MustExec("drop table if exists orders, users") } -func (s *testColumnTypeChangeSuite) TestAlterPrimaryKeyToNull(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterPrimaryKeyToNull(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, t1") tk.MustExec("create table t(a int not null, b int not null, primary key(a, b));") - tk.MustGetErrCode("alter table t modify a bigint null;", mysql.ErrPrimaryCantHaveNull) - tk.MustGetErrCode("alter table t change column a a bigint null;", mysql.ErrPrimaryCantHaveNull) + tk.MustGetErrCode("alter table t modify a bigint null;", errno.ErrPrimaryCantHaveNull) + tk.MustGetErrCode("alter table t change column a a bigint null;", errno.ErrPrimaryCantHaveNull) tk.MustExec("create table t1(a int not null, b int not null, primary key(a));") - tk.MustGetErrCode("alter table t modify a bigint null;", mysql.ErrPrimaryCantHaveNull) - tk.MustGetErrCode("alter table t change column a a bigint null;", mysql.ErrPrimaryCantHaveNull) + tk.MustGetErrCode("alter table t modify a bigint null;", errno.ErrPrimaryCantHaveNull) + tk.MustGetErrCode("alter table t change column a a bigint null;", errno.ErrPrimaryCantHaveNull) } // Close https://github.com/pingcap/tidb/issues/24839. -func (s testColumnTypeChangeSuite) TestChangeUnsignedIntToDatetime(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeUnsignedIntToDatetime(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int(10) unsigned default null, b bigint unsigned, c tinyint unsigned);") tk.MustExec("insert into t values (1, 1, 1);") - tk.MustGetErrCode("alter table t modify column a datetime;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column b datetime;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column c datetime;", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column a datetime;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column b datetime;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column c datetime;", errno.ErrTruncatedWrongValue) tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int(10) unsigned default null, b bigint unsigned, c tinyint unsigned);") tk.MustExec("insert into t values (4294967295, 18446744073709551615, 255);") - tk.MustGetErrCode("alter table t modify column a datetime;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column b datetime;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column c datetime;", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column a datetime;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column b datetime;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column c datetime;", errno.ErrTruncatedWrongValue) } // Close issue #23202 -func (s *testColumnTypeChangeSuite) TestDDLExitWhenCancelMeetPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDDLExitWhenCancelMeetPanic(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1910,15 +1908,12 @@ func (s *testColumnTypeChangeSuite) TestDDLExitWhenCancelMeetPanic(c *C) { tk.MustExec("alter table t add index(b)") tk.MustExec("set @@global.tidb_ddl_error_count_limit=3") - failpoint.Enable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit", `return(true)`) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit", `return(true)`)) defer func() { - failpoint.Disable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit")) }() - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - - hook := &ddl.TestDDLCallback{Do: s.dom} + hook := &ddl.TestDDLCallback{Do: dom} var jobID int64 hook.OnJobRunBeforeExported = func(job *model.Job) { if jobID != 0 { @@ -1928,31 +1923,32 @@ func (s *testColumnTypeChangeSuite) TestDDLExitWhenCancelMeetPanic(c *C) { jobID = job.ID } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) // when it panics in write-reorg state, the job will be pulled up as a cancelling job. Since drop-index with // write-reorg can't be cancelled, so it will be converted to running state and try again (dead loop). - _, err := tk.Exec("alter table t drop index b") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1]panic in handling DDL logic and error count beyond the limitation 3, cancelled") - c.Assert(jobID > 0, Equals, true) + err := tk.ExecToErr("alter table t drop index b") + require.EqualError(t, err, "[ddl:-1]panic in handling DDL logic and error count beyond the limitation 3, cancelled") + require.Less(t, int64(0), jobID) // Verification of the history job state. var job *model.Job - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) var err1 error - job, err1 = t.GetHistoryDDLJob(jobID) + job, err1 = m.GetHistoryDDLJob(jobID) return errors2.Trace(err1) }) - c.Assert(err, IsNil) - c.Assert(job.ErrorCount, Equals, int64(4)) - c.Assert(job.Error.Error(), Equals, "[ddl:-1]panic in handling DDL logic and error count beyond the limitation 3, cancelled") + require.NoError(t, err) + require.Equal(t, int64(4), job.ErrorCount) + require.Equal(t, "[ddl:-1]panic in handling DDL logic and error count beyond the limitation 3, cancelled", job.Error.Error()) } // Close issue #24253 -func (s *testColumnTypeChangeSuite) TestChangeIntToBitWillPanicInBackfillIndexes(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeIntToBitWillPanicInBackfillIndexes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1980,25 +1976,27 @@ func (s *testColumnTypeChangeSuite) TestChangeIntToBitWillPanicInBackfillIndexes } // Close issue #24584 -func (s *testColumnTypeChangeSuite) TestCancelCTCInReorgStateWillCauseGoroutineLeak(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCancelCTCInReorgStateWillCauseGoroutineLeak(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - failpoint.Enable("github.com/pingcap/tidb/ddl/mockInfiniteReorgLogic", `return(true)`) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockInfiniteReorgLogic", `return(true)`)) defer func() { - failpoint.Disable("github.com/pingcap/tidb/ddl/mockInfiniteReorgLogic") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockInfiniteReorgLogic")) }() // set ddl hook - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) + originalHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originalHook) tk.MustExec("drop table if exists ctc_goroutine_leak") tk.MustExec("create table ctc_goroutine_leak (a int)") tk.MustExec("insert into ctc_goroutine_leak values(1),(2),(3)") - tbl := testGetTableByName(c, tk.Se, "test", "ctc_goroutine_leak") + tbl := external.GetTableByName(t, tk, "test", "ctc_goroutine_leak") - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} var jobID int64 hook.OnJobRunBeforeExported = func(job *model.Job) { if jobID != 0 { @@ -2011,43 +2009,44 @@ func (s *testColumnTypeChangeSuite) TestCancelCTCInReorgStateWillCauseGoroutineL jobID = job.ID } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") var ( - wg = sync.WaitGroup{} + wg util.WaitGroupWrapper alterErr error ) - wg.Add(1) - go func() { - defer wg.Done() + wg.Run(func() { // This ddl will be hang over in the failpoint loop, waiting for outside cancel. _, alterErr = tk1.Exec("alter table ctc_goroutine_leak modify column a tinyint") - }() + }) + <-ddl.TestReorgGoroutineRunning tk.MustExec("admin cancel ddl jobs " + strconv.Itoa(int(jobID))) wg.Wait() - c.Assert(alterErr.Error(), Equals, "[ddl:8214]Cancelled DDL job") + require.Equal(t, "[ddl:8214]Cancelled DDL job", alterErr.Error()) } // Close issue #24971, #24973, #24974 -func (s *testColumnTypeChangeSuite) TestCTCShouldCastTheDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCTCShouldCastTheDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") tk.MustExec("insert into t values(1)") tk.MustExec("alter table t add column b bit(51) default 1512687856625472") // virtual fill the column data - tk.MustGetErrCode("alter table t modify column b decimal(30,18)", mysql.ErrDataOutOfRange) // because 1512687856625472 is out of range. + tk.MustGetErrCode("alter table t modify column b decimal(30,18)", errno.ErrDataOutOfRange) // because 1512687856625472 is out of range. tk.MustExec("drop table if exists t") tk.MustExec("create table tbl_1 (col int)") tk.MustExec("insert into tbl_1 values (9790)") tk.MustExec("alter table tbl_1 add column col1 blob(6) collate binary not null") tk.MustQuery("select col1 from tbl_1").Check(testkit.Rows("")) - tk.MustGetErrCode("alter table tbl_1 change column col1 col2 int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table tbl_1 change column col1 col2 int", errno.ErrTruncatedWrongValue) tk.MustQuery("select col1 from tbl_1").Check(testkit.Rows("")) tk.MustExec("drop table if exists t") @@ -2055,15 +2054,17 @@ func (s *testColumnTypeChangeSuite) TestCTCShouldCastTheDefaultValue(c *C) { tk.MustExec("replace into tbl values (89687.448)") tk.MustExec("alter table tbl add column col_279 binary(197) collate binary default 'RAWTdm' not null") tk.MustQuery("select col_279 from tbl").Check(testkit.Rows("RAWTdm\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")) - tk.MustGetErrCode("alter table tbl change column col_279 col_287 int", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table tbl change column col_279 col_287 int", errno.ErrTruncatedWrongValue) tk.MustQuery("select col_279 from tbl").Check(testkit.Rows("RAWTdm\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")) } // Close issue #25037 // 1: for default value of binary of create-table, it should append the \0 as the suffix to meet flen. // 2: when cast the bit to binary, we should consider to convert it to uint then cast uint to string, rather than taking the bit to string directly. -func (s *testColumnTypeChangeSuite) TestCTCCastBitToBinary(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCTCCastBitToBinary(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // For point 1: @@ -2088,46 +2089,46 @@ func (s *testColumnTypeChangeSuite) TestCTCCastBitToBinary(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("4047")) } -func (s *testColumnTypeChangeSuite) TestChangePrefixedIndexColumnToNonPrefixOne(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangePrefixedIndexColumnToNonPrefixOne(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a text, unique index idx(a(2)));") tk.MustExec("alter table t modify column a int;") showCreateTable := tk.MustQuery("show create table t").Rows()[0][1].(string) - c.Assert(strings.Contains(showCreateTable, "UNIQUE KEY `idx` (`a`)"), IsTrue, - Commentf("%s", showCreateTable)) + require.Containsf(t, showCreateTable, "UNIQUE KEY `idx` (`a`)", showCreateTable) tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a char(255), unique index idx(a(2)));") tk.MustExec("alter table t modify column a float;") showCreateTable = tk.MustQuery("show create table t").Rows()[0][1].(string) - c.Assert(strings.Contains(showCreateTable, "UNIQUE KEY `idx` (`a`)"), IsTrue, - Commentf("%s", showCreateTable)) + require.Containsf(t, showCreateTable, "UNIQUE KEY `idx` (`a`)", showCreateTable) tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a char(255), b text, unique index idx(a(2), b(10)));") tk.MustExec("alter table t modify column b int;") showCreateTable = tk.MustQuery("show create table t").Rows()[0][1].(string) - c.Assert(strings.Contains(showCreateTable, "UNIQUE KEY `idx` (`a`(2),`b`)"), IsTrue, - Commentf("%s", showCreateTable)) + require.Containsf(t, showCreateTable, "UNIQUE KEY `idx` (`a`(2),`b`)", showCreateTable) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a char(250), unique key idx(a(10)));") tk.MustExec("alter table t modify a char(9);") showCreateTable = tk.MustQuery("show create table t").Rows()[0][1].(string) - c.Assert(strings.Contains(showCreateTable, "UNIQUE KEY `idx` (`a`)"), IsTrue, - Commentf("%s", showCreateTable)) + require.Containsf(t, showCreateTable, "UNIQUE KEY `idx` (`a`)", showCreateTable) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a varchar(700), key(a(700)));") - tk.MustGetErrCode("alter table t change column a a tinytext;", mysql.ErrBlobKeyWithoutLength) + tk.MustGetErrCode("alter table t change column a a tinytext;", errno.ErrBlobKeyWithoutLength) } // Fix issue https://github.com/pingcap/tidb/issues/25469 -func (s *testColumnTypeChangeSuite) TestCastToTimeStampDecodeError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCastToTimeStampDecodeError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t") @@ -2135,14 +2136,14 @@ func (s *testColumnTypeChangeSuite) TestCastToTimeStampDecodeError(c *C) { " `a` datetime DEFAULT '1764-06-11 02:46:14'" + ") ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin COMMENT='7b84832e-f857-4116-8872-82fc9dcc4ab3'") tk.MustExec("insert into `t` values();") - tk.MustGetErrCode("alter table `t` change column `a` `b` TIMESTAMP NULL DEFAULT '2015-11-14 07:12:24';", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table `t` change column `a` `b` TIMESTAMP NULL DEFAULT '2015-11-14 07:12:24';", errno.ErrTruncatedWrongValue) tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` (" + " `a` date DEFAULT '1764-06-11 02:46:14'" + ") ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin COMMENT='7b84832e-f857-4116-8872-82fc9dcc4ab3'") tk.MustExec("insert into `t` values();") - tk.MustGetErrCode("alter table `t` change column `a` `b` TIMESTAMP NULL DEFAULT '2015-11-14 07:12:24';", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table `t` change column `a` `b` TIMESTAMP NULL DEFAULT '2015-11-14 07:12:24';", errno.ErrTruncatedWrongValue) tk.MustExec("drop table if exists t") // Normal cast datetime to timestamp can succeed. @@ -2150,8 +2151,10 @@ func (s *testColumnTypeChangeSuite) TestCastToTimeStampDecodeError(c *C) { } // https://github.com/pingcap/tidb/issues/25285. -func (s *testColumnTypeChangeSuite) TestCastFromZeroIntToTimeError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCastFromZeroIntToTimeError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") prepare := func() { @@ -2164,8 +2167,8 @@ func (s *testColumnTypeChangeSuite) TestCastFromZeroIntToTimeError(c *C) { sqlMode string errCode int }{ - {"STRICT_TRANS_TABLES", mysql.ErrTruncatedWrongValue}, - {"STRICT_ALL_TABLES", mysql.ErrTruncatedWrongValue}, + {"STRICT_TRANS_TABLES", errno.ErrTruncatedWrongValue}, + {"STRICT_ALL_TABLES", errno.ErrTruncatedWrongValue}, {"NO_ZERO_IN_DATE", errCodeNone}, {"NO_ZERO_DATE", errCodeNone}, {"ALLOW_INVALID_DATES", errCodeNone}, @@ -2187,16 +2190,18 @@ func (s *testColumnTypeChangeSuite) TestCastFromZeroIntToTimeError(c *C) { prepare() tk.MustExec("alter table t modify column a timestamp;") } else { - tk.MustGetErrCode("alter table t modify column a date;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column a datetime;", mysql.ErrTruncatedWrongValue) - tk.MustGetErrCode("alter table t modify column a timestamp;", mysql.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column a date;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column a datetime;", errno.ErrTruncatedWrongValue) + tk.MustGetErrCode("alter table t modify column a timestamp;", errno.ErrTruncatedWrongValue) } } tk.MustExec("drop table if exists t;") } -func (s *testColumnTypeChangeSuite) TestChangeFromTimeToYear(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeFromTimeToYear(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -2212,9 +2217,9 @@ func (s *testColumnTypeChangeSuite) TestChangeFromTimeToYear(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("create table t (id bigint primary key, a time);") tk.MustExec("replace into t values (1, '10:10:10');") - tk.MustGetErrCode("alter table t modify column a year;", mysql.ErrWarnDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a year;", errno.ErrWarnDataOutOfRange) tk.MustExec("replace into t values (1, '12:13:14');") - tk.MustGetErrCode("alter table t modify column a year;", mysql.ErrWarnDataOutOfRange) + tk.MustGetErrCode("alter table t modify column a year;", errno.ErrWarnDataOutOfRange) tk.MustExec("set @@sql_mode = '';") tk.MustExec("alter table t modify column a year;") tk.MustQuery("show warnings").Check( @@ -2223,56 +2228,48 @@ func (s *testColumnTypeChangeSuite) TestChangeFromTimeToYear(c *C) { // Fix issue: https://github.com/pingcap/tidb/issues/26292 // Cast date to timestamp has two kind behavior: cast("3977-02-22" as date) -// For select statement, it truncate the string and return no errors. (which is 3977-02-22 00:00:00 here) -// For ddl reorging or changing column in ctc, it need report some errors. -func (s *testColumnTypeChangeSuite) TestCastDateToTimestampInReorgAttribute(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") +// For select statement, it truncates the string and return no errors. (which is 3977-02-22 00:00:00 here) +// For ddl reorging or changing column in ctc, it needs report some errors. +func TestCastDateToTimestampInReorgAttribute(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, 600*time.Millisecond) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") - tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` (`a` DATE NULL DEFAULT '8497-01-06')") tk.MustExec("insert into t values(now())") - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Len(t, tbl.Cols(), 1) + var checkErr1 error + var checkErr2 error - // use new session to check meta in callback function. - internalTK := testkit.NewTestKit(c, s.store) - internalTK.MustExec("use test") - - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(len(tbl.Cols()), Equals, 1) - - hook := &ddl.TestDDLCallback{} - var ( - checkErr1 error - checkErr2 error - ) + hook := &ddl.TestDDLCallback{Do: dom} hook.OnJobRunBeforeExported = func(job *model.Job) { - if checkErr1 != nil || checkErr2 != nil { - return - } - if tbl.Meta().ID != job.TableID { + if checkErr1 != nil || checkErr2 != nil || tbl.Meta().ID != job.TableID { return } switch job.SchemaState { case model.StateWriteOnly: - _, checkErr1 = internalTK.Exec("insert into `t` set `a` = '3977-02-22'") // this(string) will be cast to a as date, then cast a(date) as timestamp to changing column. - _, checkErr2 = internalTK.Exec("update t set `a` = '3977-02-22'") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + checkErr1 = tk.ExecToErr("insert into `t` set `a` = '3977-02-22'") // this(string) will be cast to a as date, then cast a(date) as timestamp to changing column. + checkErr2 = tk.ExecToErr("update t set `a` = '3977-02-22'") } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) tk.MustExec("alter table t modify column a TIMESTAMP NULL DEFAULT '2021-04-28 03:35:11' FIRST") - c.Assert(checkErr1.Error(), Equals, "[types:1292]Incorrect timestamp value: '3977-02-22'") - c.Assert(checkErr2.Error(), Equals, "[types:1292]Incorrect timestamp value: '3977-02-22'") - tk.MustExec("drop table if exists t") + require.EqualError(t, checkErr1, "[types:1292]Incorrect timestamp value: '3977-02-22'") + require.EqualError(t, checkErr2, "[types:1292]Incorrect timestamp value: '3977-02-22'") } // https://github.com/pingcap/tidb/issues/25282. -func (s *testColumnTypeChangeSuite) TestChangeFromUnsignedIntToTime(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeFromUnsignedIntToTime(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -2284,19 +2281,24 @@ func (s *testColumnTypeChangeSuite) TestChangeFromUnsignedIntToTime(c *C) { } // See https://github.com/pingcap/tidb/issues/25287. -func (s *testColumnTypeChangeSuite) TestChangeFromBitToStringInvalidUtf8ErrMsg(c *C) { - tk := testkit.NewTestKit(c, s.store) +// Revised according to https://github.com/pingcap/tidb/pull/31031#issuecomment-1001404832. +func TestChangeFromBitToStringInvalidUtf8ErrMsg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a bit(45));") tk.MustExec("insert into t values (1174717);") - errMsg := "[table:1366]Incorrect string value '\\xEC\\xBD' for column 'a'" - tk.MustGetErrMsg("alter table t modify column a varchar(31) collate utf8mb4_general_ci;", errMsg) + tk.MustExec("alter table t modify column a varchar(31) collate utf8mb4_general_ci;") + tk.MustQuery("select a from t;").Check(testkit.Rows("1174717")) } -func (s *testColumnTypeChangeSuite) TestForIssue24621(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestForIssue24621(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2306,8 +2308,10 @@ func (s *testColumnTypeChangeSuite) TestForIssue24621(c *C) { tk.MustGetErrMsg("alter table t modify a char(12) null;", errMsg) } -func (s *testColumnTypeChangeSuite) TestChangeNullValueFromOtherTypeToTimestamp(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeNullValueFromOtherTypeToTimestamp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Some ddl cases. @@ -2325,8 +2329,8 @@ func (s *testColumnTypeChangeSuite) TestChangeNullValueFromOtherTypeToTimestamp( prepare() // only from other type NULL to timestamp type NOT NULL, it should be successful. _, err := tk.Exec("alter table t change column a a1 time NOT NULL") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a1' at row 1") + require.Error(t, err) + require.Equal(t, "[ddl:1265]Data truncated for column 'a1' at row 1", err.Error()) prepare2 := func() { tk.MustExec("drop table if exists t") @@ -2338,16 +2342,129 @@ func (s *testColumnTypeChangeSuite) TestChangeNullValueFromOtherTypeToTimestamp( prepare2() // only from other type NULL to timestamp type NOT NULL, it should be successful. (timestamp to timestamp excluded) _, err = tk.Exec("alter table t modify column a timestamp NOT NULL") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a' at row 1") + require.Error(t, err) + require.Equal(t, "[ddl:1265]Data truncated for column 'a' at row 1", err.Error()) // Some dml cases. tk.MustExec("drop table if exists t") tk.MustExec("create table t(a timestamp NOT NULL)") _, err = tk.Exec("insert into t values()") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[table:1364]Field 'a' doesn't have a default value") + require.Error(t, err) + require.Equal(t, "[table:1364]Field 'a' doesn't have a default value", err.Error()) _, err = tk.Exec("insert into t values(null)") - c.Assert(err.Error(), Equals, "[table:1048]Column 'a' cannot be null") + require.Equal(t, "[table:1048]Column 'a' cannot be null", err.Error()) +} + +func TestColumnTypeChangeBetweenFloatAndDouble(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + // issue #31372 + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + prepare := func(createTableStmt string) { + tk.MustExec("drop table if exists t;") + tk.MustExec(createTableStmt) + tk.MustExec("insert into t values (36.4), (24.1);") + } + + prepare("create table t (a float(6,2));") + tk.MustExec("alter table t modify a double(6,2)") + tk.MustQuery("select a from t;").Check(testkit.Rows("36.4", "24.1")) + + prepare("create table t (a double(6,2));") + tk.MustExec("alter table t modify a double(6,1)") + tk.MustQuery("select a from t;").Check(testkit.Rows("36.4", "24.1")) + tk.MustExec("alter table t modify a float(6,1)") + tk.MustQuery("select a from t;").Check(testkit.Rows("36.4", "24.1")) +} + +func TestColumnTypeChangeTimestampToInt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // 1. modify a timestamp column to bigint + // 2. modify the bigint column to timestamp + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key auto_increment, c1 timestamp default '2020-07-10 01:05:08');") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("alter table t modify column c1 bigint;") + tk.MustQuery("select * from t").Check(testkit.Rows("1 20200710010508")) + tk.MustExec("alter table t modify c1 timestamp") + tk.MustExec("set @@session.time_zone=UTC") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-09 17:05:08")) + + // 1. modify a timestamp column to bigint + // 2. add the index + // 3. modify the bigint column to timestamp + // The current session.time_zone is '+00:00'. + tk.MustExec(`set time_zone = '+00:00'`) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key auto_increment, c1 timestamp default '2020-07-10 01:05:08', index idx(c1));") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("alter table t modify column c1 bigint;") + tk.MustExec("alter table t add index idx1(id, c1);") + tk.MustQuery("select * from t").Check(testkit.Rows("1 20200710010508")) + tk.MustExec("admin check table t") + // change timezone + tk.MustExec("set @@session.time_zone='+5:00'") + tk.MustExec("alter table t modify c1 timestamp") + // change timezone + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("set @@session.time_zone='-8:00'") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-09 12:05:08")) + tk.MustExec("admin check table t") + // test the timezone of "default" and "system" + // The current session.time_zone is '-8:00'. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key auto_increment, c1 timestamp default '2020-07-10 01:05:08', index idx(c1));") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("alter table t modify column c1 bigint;") + tk.MustExec("alter table t add index idx1(id, c1);") + tk.MustQuery("select * from t").Check(testkit.Rows("1 20200710010508")) + tk.MustExec("admin check table t") + // change timezone + tk.MustExec("set @@session.time_zone= default") + tk.MustExec("alter table t modify c1 timestamp") + // change timezone + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("set @@session.time_zone='SYSTEM'") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2020-07-10 01:05:08")) + tk.MustExec("admin check table t") + + // tests DST + // 1. modify a timestamp column to bigint + // 2. modify the bigint column to timestamp + tk.MustExec("drop table if exists t") + tk.MustExec("set @@session.time_zone=UTC") + tk.MustExec("create table t(id int primary key auto_increment, c1 timestamp default '1990-04-15 18:00:00');") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 1990-04-15 18:00:00")) + tk.MustExec("set @@session.time_zone='Asia/Shanghai'") + tk.MustExec("alter table t modify column c1 bigint;") + tk.MustQuery("select * from t").Check(testkit.Rows("1 19900416030000")) + tk.MustExec("alter table t modify c1 timestamp default '1990-04-15 18:00:00'") + tk.MustExec("set @@session.time_zone=UTC") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 1990-04-15 18:00:00", "2 1990-04-15 09:00:00")) + // 1. modify a timestamp column to bigint + // 2. add the index + // 3. modify the bigint column to timestamp + // The current session.time_zone is '+00:00'. + tk.MustExec("drop table if exists t") + tk.MustExec("set @@session.time_zone='-8:00'") + tk.MustExec("create table t(id int primary key auto_increment, c1 timestamp default '2016-03-13 02:30:00', index idx(c1));") + tk.MustExec("insert into t values();") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2016-03-13 02:30:00")) + tk.MustExec("set @@session.time_zone='America/Los_Angeles'") + tk.MustExec("alter table t modify column c1 bigint;") + tk.MustQuery("select * from t").Check(testkit.Rows("1 20160313033000")) + tk.MustExec("alter table t add index idx1(id, c1);") + tk.MustExec("admin check table t") } diff --git a/ddl/db_cache_serial_test.go b/ddl/db_cache_serial_test.go deleted file mode 100644 index e024cef522682..0000000000000 --- a/ddl/db_cache_serial_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ddl_test - -import ( - "testing" - "time" - - "github.com/pingcap/tidb/ddl" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/errno" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/testkit" - "github.com/stretchr/testify/require" -) - -func TestAlterTableCache(t *testing.T) { - store, err := mockstore.NewMockStore() - require.NoError(t, err) - session.SetSchemaLease(600 * time.Millisecond) - session.DisableStats4Test() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - - dom.SetStatsUpdating(true) - - clean := func() { - dom.Close() - err := store.Close() - require.NoError(t, err) - } - defer clean() - tk := testkit.NewTestKit(t, store) - tk2 := testkit.NewTestKit(t, store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk2.MustExec("use test") - /* Test of cache table */ - tk.MustExec("create table t1 ( n int auto_increment primary key)") - tk.MustGetErrCode("alter table t1 ca", errno.ErrParse) - tk.MustGetErrCode("alter table t2 cache", errno.ErrNoSuchTable) - tk.MustExec("alter table t1 cache") - checkTableCacheStatus(t, tk.Session(), "test", "t1", model.TableCacheStatusEnable) - tk.MustExec("drop table if exists t1") - /*Test can't skip schema checker*/ - tk.MustExec("drop table if exists t1,t2") - tk.MustExec("CREATE TABLE t1 (a int)") - tk.MustExec("CREATE TABLE t2 (a int)") - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1;") - tk2.MustExec("alter table t1 cache;") - _, err = tk.Exec("commit") - require.True(t, terror.ErrorEqual(domain.ErrInfoSchemaChanged, err)) - /* Test can skip schema checker */ - tk.MustExec("begin") - tk.MustExec("drop table if exists t1") - tk.MustExec("CREATE TABLE t1 (a int)") - tk.MustExec("insert into t1 set a=2;") - tk2.MustExec("alter table t2 cache") - tk.MustExec("commit") - // Test if a table is not exists - tk.MustExec("drop table if exists t") - tk.MustGetErrCode("alter table t cache", errno.ErrNoSuchTable) - tk.MustExec("create table t (a int)") - tk.MustExec("alter table t cache") - // Multiple alter cache is okay - tk.MustExec("alter table t cache") - tk.MustExec("alter table t cache") - // Test a temporary table - tk.MustExec("drop table if exists t") - tk.MustExec("create temporary table t (id int primary key auto_increment, u int unique, v int)") - tk.MustExec("drop table if exists tmp1") - // local temporary table alter is not supported - tk.MustGetErrCode("alter table t cache", errno.ErrUnsupportedDDLOperation) - // test global temporary table - tk.MustExec("create global temporary table tmp1 " + - "(id int not null primary key, code int not null, value int default null, unique key code(code))" + - "on commit delete rows") - tk.MustGetErrMsg("alter table tmp1 cache", ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache").Error()) - -} diff --git a/ddl/db_cache_test.go b/ddl/db_cache_test.go index 120c0c687e049..001500aaae856 100644 --- a/ddl/db_cache_test.go +++ b/ddl/db_cache_test.go @@ -16,35 +16,28 @@ package ddl_test import ( "testing" + "time" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/dbterror" "github.com/stretchr/testify/require" ) -func checkTableCacheStatus(t *testing.T, se session.Session, dbName, tableName string, status model.TableCacheStatusType) { - tb := testGetTableByNameT(t, se, dbName, tableName) - dom := domain.GetDomain(se) +func checkTableCacheStatus(t *testing.T, tk *testkit.TestKit, dbName, tableName string, status model.TableCacheStatusType) { + tb := external.GetTableByName(t, tk, dbName, tableName) + dom := domain.GetDomain(tk.Session()) err := dom.Reload() require.NoError(t, err) require.Equal(t, status, tb.Meta().TableCacheStatusType) } -func testGetTableByNameT(t *testing.T, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - require.NoError(t, err) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - require.NoError(t, err) - return tbl -} - func TestAlterPartitionCache(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -97,9 +90,9 @@ func TestAlterTableNoCache(t *testing.T) { /* Test of cache table */ tk.MustExec("create table nocache_t1 ( n int auto_increment primary key)") tk.MustExec("alter table nocache_t1 cache") - checkTableCacheStatus(t, tk.Session(), "test", "nocache_t1", model.TableCacheStatusEnable) + checkTableCacheStatus(t, tk, "test", "nocache_t1", model.TableCacheStatusEnable) tk.MustExec("alter table nocache_t1 nocache") - checkTableCacheStatus(t, tk.Session(), "test", "nocache_t1", model.TableCacheStatusDisable) + checkTableCacheStatus(t, tk, "test", "nocache_t1", model.TableCacheStatusDisable) tk.MustExec("drop table if exists t1") // Test if a table is not exists tk.MustExec("drop table if exists nocache_t") @@ -132,4 +125,146 @@ func TestIndexOnCacheTable(t *testing.T) { tk.MustExec("create table cache_index_1 (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));") tk.MustExec("alter table cache_index_1 cache") tk.MustGetErrCode("alter table cache_index_1 drop index i1, drop index i2;", errno.ErrOptOnCacheTable) + + // cleanup + tk.MustExec("alter table cache_index_1 nocache") + tk.MustExec("alter table cache_index nocache") +} + +func TestAlterTableCache(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + session.SetSchemaLease(600 * time.Millisecond) + session.DisableStats4Test() + dom, err := session.BootstrapSession(store) + require.NoError(t, err) + + dom.SetStatsUpdating(true) + + clean := func() { + dom.Close() + err := store.Close() + require.NoError(t, err) + } + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk2.MustExec("use test") + /* Test of cache table */ + tk.MustExec("create table t1 ( n int auto_increment primary key)") + tk.MustGetErrCode("alter table t1 ca", errno.ErrParse) + tk.MustGetErrCode("alter table t2 cache", errno.ErrNoSuchTable) + tk.MustExec("alter table t1 cache") + checkTableCacheStatus(t, tk, "test", "t1", model.TableCacheStatusEnable) + tk.MustExec("alter table t1 nocache") + tk.MustExec("drop table if exists t1") + /*Test can't skip schema checker*/ + tk.MustExec("drop table if exists t1,t2") + tk.MustExec("CREATE TABLE t1 (a int)") + tk.MustExec("CREATE TABLE t2 (a int)") + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1;") + tk2.MustExec("alter table t1 cache;") + _, err = tk.Exec("commit") + require.True(t, terror.ErrorEqual(domain.ErrInfoSchemaChanged, err)) + /* Test can skip schema checker */ + tk.MustExec("begin") + tk.MustExec("alter table t1 nocache") + tk.MustExec("drop table if exists t1") + tk.MustExec("CREATE TABLE t1 (a int)") + tk.MustExec("insert into t1 set a=2;") + tk2.MustExec("alter table t2 cache") + tk.MustExec("commit") + // Test if a table is not exists + tk.MustExec("drop table if exists t") + tk.MustGetErrCode("alter table t cache", errno.ErrNoSuchTable) + tk.MustExec("create table t (a int)") + tk.MustExec("alter table t cache") + // Multiple alter cache is okay + tk.MustExec("alter table t cache") + tk.MustExec("alter table t cache") + // Test a temporary table + tk.MustExec("alter table t nocache") + tk.MustExec("drop table if exists t") + tk.MustExec("create temporary table t (id int primary key auto_increment, u int unique, v int)") + tk.MustExec("drop table if exists tmp1") + // local temporary table alter is not supported + tk.MustGetErrCode("alter table t cache", errno.ErrUnsupportedDDLOperation) + // test global temporary table + tk.MustExec("create global temporary table tmp1 " + + "(id int not null primary key, code int not null, value int default null, unique key code(code))" + + "on commit delete rows") + tk.MustGetErrMsg("alter table tmp1 cache", dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache").Error()) +} + +func TestCacheTableSizeLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists cache_t1") + tk.MustExec("create table cache_t1 (c1 int, c varchar(1024))") + tk.MustExec("create table cache_t2 (c1 int, c varchar(1024))") + tk.MustExec("create table tmp (c1 int, c varchar(1024))") + defer tk.MustExec("drop table if exists cache_t1") + + for i := 0; i < 64; i++ { + tk.MustExec("insert into tmp values (?, repeat('x', 1024));", i) + } + + // Make the cache_t1 size large than 64K + for i := 0; i < 1024; i++ { + tk.MustExec("insert into cache_t1 select * from tmp;") + if i == 900 { + tk.MustExec("insert into cache_t2 select * from cache_t1;") + } + } + // Check 'alter table cache' fail + tk.MustGetErrCode("alter table cache_t1 cache", errno.ErrOptOnCacheTable) + + // Check 'alter table cache' success + tk.MustExec("alter table cache_t2 cache") + + // But after continuously insertion, the table reachs the size limit + for i := 0; i < 124; i++ { + _, err := tk.Exec("insert into cache_t2 select * from tmp;") + // The size limit check is not accurate, so it's not detected here. + require.NoError(t, err) + } + + lastReadFromCache := func(tk *testkit.TestKit) bool { + return tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache + } + + cached := false + for i := 0; i < 200; i++ { + tk.MustQuery("select count(*) from (select * from cache_t2 limit 1) t1").Check(testkit.Rows("1")) + if lastReadFromCache(tk) { + cached = true + break + } + time.Sleep(50 * time.Millisecond) + } + require.True(t, cached) + + // Forbit the insert once the table size limit is detected. + tk.MustGetErrCode("insert into cache_t2 select * from tmp;", errno.ErrOptOnCacheTable) +} + +func TestIssue32692(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("create table cache_t2 (c1 int);") + tk.MustExec("alter table cache_t2 cache;") + tk.MustExec("alter table cache_t2 nocache;") + // Check no warning message here. + tk.MustExec("alter table cache_t2 cache;") + tk.MustQuery("show warnings").Check(testkit.Rows()) } diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 3ae2259ddaf07..c93ed671ccc38 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -21,13 +21,14 @@ import ( "strings" "sync" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/log" "github.com/pingcap/tidb/ddl" + ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" @@ -41,69 +42,61 @@ import ( "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/gcutil" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "go.uber.org/zap" ) -var _ = Suite(&testStateChangeSuite{}) -var _ = SerialSuites(&serialTestStateChangeSuite{}) - -type serialTestStateChangeSuite struct { - testStateChangeSuiteBase -} - -type testStateChangeSuite struct { - testStateChangeSuiteBase +type stateChangeSuite struct { + suite.Suite + store kv.Storage + dom *domain.Domain + tk *testkit.TestKit } -type testStateChangeSuiteBase struct { - lease time.Duration - store kv.Storage - dom *domain.Domain - se session.Session - p *parser.Parser - preSQL string +func TestStateChange(t *testing.T) { + suite.Run(t, new(stateChangeSuite)) } -func (s *testStateChangeSuiteBase) SetUpSuite(c *C) { - s.lease = 200 * time.Millisecond +func (s *stateChangeSuite) SetupSuite() { ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) + session.SetSchemaLease(200 * time.Millisecond) + var err error s.store, err = mockstore.NewMockStore() - c.Assert(err, IsNil) - session.SetSchemaLease(s.lease) + s.Require().NoError(err) s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - s.se, err = session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create database test_db_state default charset utf8 default collate utf8_bin") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - s.p = parser.New() -} - -func (s *testStateChangeSuiteBase) TearDownSuite(c *C) { - _, err := s.se.Execute(context.Background(), "drop database if exists test_db_state") - c.Assert(err, IsNil) - s.se.Close() + s.Require().NoError(err) + tk := testkit.NewTestKit(s.T(), s.store) + tk.MustExec("create database test_db_state default charset utf8 default collate utf8_bin") + tk.MustExec("use test_db_state") +} + +func (s *stateChangeSuite) SetupTest() { + s.tk = testkit.NewTestKit(s.T(), s.store) + s.tk.MustExec("use test_db_state") +} + +func (s *stateChangeSuite) TearDownSuite() { s.dom.Close() - err = s.store.Close() - c.Assert(err, IsNil) + s.Require().NoError(s.store.Close()) } // TestShowCreateTable tests the result of "show create table" when we are running "add index" or "add column". -func (s *serialTestStateChangeSuite) TestShowCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestShowCreateTable() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test") tk.MustExec("create table t (id int)") tk.MustExec("create table t2 (a int, b varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci") // tkInternal is used to execute additional sql (here show create table) in ddl change callback. // Using same `tk` in different goroutines may lead to data race. - tkInternal := testkit.NewTestKit(c, s.store) + tkInternal := testkit.NewTestKit(s.T(), s.store) tkInternal.MustExec("use test") var checkErr error @@ -134,7 +127,7 @@ func (s *serialTestStateChangeSuite) TestShowCreateTable(c *C) { } if job.SchemaState != model.StatePublic { var result sqlexec.RecordSet - tbl2 := testGetTableByName(c, tkInternal.Se, "test", "t2") + tbl2 := external.GetTableByName(s.T(), tkInternal, "test", "t2") if job.TableID == tbl2.Meta().ID { // Try to do not use mustQuery in hook func, cause assert fail in mustQuery will cause ddl job hung. result, checkErr = tkInternal.Exec("show create table t2") @@ -162,17 +155,17 @@ func (s *serialTestStateChangeSuite) TestShowCreateTable(c *C) { } d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) - d.(ddl.DDLForTest).SetHook(callback) + defer d.SetHook(originalCallback) + d.SetHook(callback) for _, tc := range testCases { tk.MustExec(tc.sql) - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) } } // TestDropNotNullColumn is used to test issue #8654. -func (s *testStateChangeSuite) TestDropNotNullColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestDropNotNullColumn() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test") tk.MustExec("create table t (id int, a int not null default 11)") tk.MustExec("insert into t values(1, 1)") @@ -182,7 +175,7 @@ func (s *testStateChangeSuite) TestDropNotNullColumn(c *C) { tk.MustExec("insert into t2 values(3, '11:22:33')") tk.MustExec("create table t3 (id int, d json not null)") tk.MustExec("insert into t3 values(4, d)") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(s.T(), s.store) tk1.MustExec("use test") var checkErr error @@ -195,7 +188,7 @@ func (s *testStateChangeSuite) TestDropNotNullColumn(c *C) { return } err := originalCallback.OnChanged(nil) - c.Assert(err, IsNil) + s.Require().NoError(err) if job.SchemaState == model.StateWriteOnly { switch sqlNum { case 0: @@ -210,23 +203,23 @@ func (s *testStateChangeSuite) TestDropNotNullColumn(c *C) { } } - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) tk.MustExec("alter table t drop column a") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) sqlNum++ tk.MustExec("alter table t1 drop column b") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) sqlNum++ tk.MustExec("alter table t2 drop column c") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) sqlNum++ tk.MustExec("alter table t3 drop column d") - c.Assert(checkErr, IsNil) - d.(ddl.DDLForTest).SetHook(originalCallback) + s.Require().NoError(checkErr) + d.SetHook(originalCallback) tk.MustExec("drop table t, t1, t2, t3") } -func (s *testStateChangeSuite) TestTwoStates(c *C) { +func (s *stateChangeSuite) TestTwoStates() { cnt := 5 // New the testExecInfo. testInfo := &testExecInfo{ @@ -241,7 +234,7 @@ func (s *testStateChangeSuite) TestTwoStates(c *C) { testInfo.sqlInfos[i] = sqlInfo } err := testInfo.createSessions(s.store, "test_db_state") - c.Assert(err, IsNil) + s.Require().NoError(err) // Fill the SQLs and expected error messages. testInfo.sqlInfos[0].sql = "insert into t (c1, c2, c3, c4) value(2, 'b', 'N', '2017-07-02')" testInfo.sqlInfos[1].sql = "insert into t (c1, c2, c3, d3, c4) value(3, 'b', 'N', 'a', '2017-07-03')" @@ -254,31 +247,27 @@ func (s *testStateChangeSuite) TestTwoStates(c *C) { testInfo.sqlInfos[3].sql = "replace into t values(5, 'e', 'N', '2017-07-05')" testInfo.sqlInfos[3].cases[4].expectedCompileErr = "[planner:1136]Column count doesn't match value count at row 1" alterTableSQL := "alter table t add column d3 enum('a', 'b') not null default 'a' after c3" - s.test(c, "", alterTableSQL, testInfo) + s.test(alterTableSQL, testInfo) // TODO: Add more DDL statements. } -func (s *testStateChangeSuite) test(c *C, tableName, alterTableSQL string, testInfo *testExecInfo) { - _, err := s.se.Execute(context.Background(), `create table t ( +func (s *stateChangeSuite) test(alterTableSQL string, testInfo *testExecInfo) { + s.tk.MustExec(`create table t ( c1 int, c2 varchar(64), c3 enum('N','Y') not null default 'N', c4 timestamp on update current_timestamp, key(c1, c2))`) - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() - _, err = s.se.Execute(context.Background(), "insert into t values(1, 'a', 'N', '2017-07-01')") - c.Assert(err, IsNil) + defer s.tk.MustExec("drop table t") + + s.tk.MustExec("insert into t values(1, 'a', 'N', '2017-07-01')") callback := &ddl.TestDDLCallback{} prevState := model.StateNone - var checkErr error - err = testInfo.parseSQLs(s.p) - c.Assert(err, IsNil, Commentf("error stack %v", errors.ErrorStack(err))) + s.Require().NoError(testInfo.parseSQLs(parser.New())) + times := 0 + var checkErr error callback.OnJobUpdatedExported = func(job *model.Job) { if job.SchemaState == prevState || checkErr != nil || times >= 3 { return @@ -287,7 +276,7 @@ func (s *testStateChangeSuite) test(c *C, tableName, alterTableSQL string, testI switch job.SchemaState { case model.StateDeleteOnly: // This state we execute every sqlInfo one time using the first session and other information. - err = testInfo.compileSQL(0) + err := testInfo.compileSQL(0) if err != nil { checkErr = err break @@ -298,13 +287,13 @@ func (s *testStateChangeSuite) test(c *C, tableName, alterTableSQL string, testI } case model.StateWriteOnly: // This state we put the schema information to the second case. - err = testInfo.compileSQL(1) + err := testInfo.compileSQL(1) if err != nil { checkErr = err } case model.StateWriteReorganization: // This state we execute every sqlInfo one time using the third session and other information. - err = testInfo.compileSQL(2) + err := testInfo.compileSQL(2) if err != nil { checkErr = err break @@ -329,18 +318,14 @@ func (s *testStateChangeSuite) test(c *C, tableName, alterTableSQL string, testI } d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) - d.(ddl.DDLForTest).SetHook(callback) - _, err = s.se.Execute(context.Background(), alterTableSQL) - c.Assert(err, IsNil) - err = testInfo.compileSQL(4) - c.Assert(err, IsNil) - err = testInfo.execSQL(4) - c.Assert(err, IsNil) + defer d.SetHook(originalCallback) + d.SetHook(callback) + s.tk.MustExec(alterTableSQL) + s.Require().NoError(testInfo.compileSQL(4)) + s.Require().NoError(testInfo.execSQL(4)) // Mock the server is in `write reorg` state. - err = testInfo.execSQL(3) - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) + s.Require().NoError(testInfo.execSQL(3)) + s.Require().NoError(checkErr) } type stateCase struct { @@ -411,7 +396,9 @@ func (t *testExecInfo) compileSQL(idx int) (err error) { compiler := executor.Compiler{Ctx: c.session} se := c.session ctx := context.TODO() - se.PrepareTxnCtx(ctx) + if err = se.PrepareTxnCtx(ctx); err != nil { + return err + } sctx := se.(sessionctx.Context) if err = executor.ResetContextOfStmt(sctx, c.rawStmt); err != nil { return errors.Trace(err) @@ -466,89 +453,81 @@ type expectQuery struct { rows []string } -func (s *testStateChangeSuite) TestAppendEnum(c *C) { - _, err := s.se.Execute(context.Background(), `create table t ( +func (s *stateChangeSuite) TestAppendEnum() { + s.tk.MustExec(`create table t ( c1 varchar(64), c2 enum('N','Y') not null default 'N', c3 timestamp on update current_timestamp, c4 int primary key, unique key idx2 (c2, c3))`) - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() - _, err = s.se.Execute(context.Background(), "insert into t values('a', 'N', '2017-07-01', 8)") - c.Assert(err, IsNil) - // Make sure these sqls use the the plan of index scan. - _, err = s.se.Execute(context.Background(), "drop stats t") - c.Assert(err, IsNil) - se, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "insert into t values('a', 'A', '2018-09-19', 9)") - c.Assert(err.Error(), Equals, "[types:1265]Data truncated for column 'c2' at row 1") - failAlterTableSQL1 := "alter table t change c2 c2 enum('N') DEFAULT 'N'" - _, err = s.se.Execute(context.Background(), failAlterTableSQL1) - c.Assert(err, IsNil) - failAlterTableSQL2 := "alter table t change c2 c2 int default 0" - _, err = s.se.Execute(context.Background(), failAlterTableSQL2) - c.Assert(err, IsNil) - alterTableSQL := "alter table t change c2 c2 enum('N','Y','A') DEFAULT 'A'" - _, err = s.se.Execute(context.Background(), alterTableSQL) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "insert into t values('a', 'A', '2018-09-20', 10)") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "insert into t (c1, c3, c4) values('a', '2018-09-21', 11)") - c.Assert(err, IsNil) - - tk := testkit.NewTestKit(c, s.store) + defer s.tk.MustExec("drop table t") + s.tk.MustExec("insert into t values('a', 'N', '2017-07-01', 8)") + // Make sure these SQLs use the plan of index scan. + s.tk.MustExec("drop stats t") + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") - result, err := s.execQuery(tk, "select c4, c2 from t order by c4 asc") - c.Assert(err, IsNil) - expected := []string{"8 N", "10 A", "11 A"} - err = checkResult(result, testkit.Rows(expected...)) - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "update t set c2='N' where c4 = 10") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "select c2 from t where c4 = 10") - c.Assert(err, IsNil) + + err := s.tk.ExecToErr("insert into t values('a', 'A', '2018-09-19', 9)") + s.Require().EqualError(err, "[types:1265]Data truncated for column 'c2' at row 1") + + s.tk.MustExec("alter table t change c2 c2 enum('N') DEFAULT 'N'") + s.tk.MustExec("alter table t change c2 c2 int default 0") + s.tk.MustExec("alter table t change c2 c2 enum('N','Y','A') DEFAULT 'A'") + s.tk.MustExec("insert into t values('a', 'A', '2018-09-20', 10)") + s.tk.MustExec("insert into t (c1, c3, c4) values('a', '2018-09-21', 11)") + + tk = testkit.NewTestKit(s.T(), s.store) + tk.MustExec("use test_db_state") + tk.MustQuery("select c4, c2 from t order by c4 asc").Check(testkit.Rows("8 N", "10 A", "11 A")) + // fixed - expected = []string{"N"} - err = checkResult(result, testkit.Rows(expected...)) - c.Assert(err, IsNil) + s.tk.MustExec("update t set c2='N' where c4 = 10") + tk.MustQuery("select c2 from t where c4 = 10").Check(testkit.Rows("N")) + } // https://github.com/pingcap/tidb/pull/6249 fixes the following two test cases. -func (s *testStateChangeSuite) TestWriteOnlyWriteNULL(c *C) { +func (s *stateChangeSuite) TestWriteOnlyWriteNULL() { sqls := make([]sqlWithErr, 1) sqls[0] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2019-02-12', c4 = 8 on duplicate key update c1 = values(c1)", nil} addColumnSQL := "alter table t add column c5 int not null default 1 after c4" expectQuery := &expectQuery{"select c4, c5 from t", []string{"8 1"}} - s.runTestInSchemaState(c, model.StateWriteOnly, true, addColumnSQL, sqls, expectQuery) + s.runTestInSchemaState(model.StateWriteOnly, true, addColumnSQL, sqls, expectQuery) } -func (s *testStateChangeSuite) TestWriteOnlyOnDupUpdate(c *C) { +func (s *stateChangeSuite) TestWriteOnlyOnDupUpdate() { sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"delete from t", nil} sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2018-02-12', c4 = 2 on duplicate key update c1 = values(c1)", nil} sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2019-02-12', c4 = 2 on duplicate key update c1 = values(c1)", nil} addColumnSQL := "alter table t add column c5 int not null default 1 after c4" expectQuery := &expectQuery{"select c4, c5 from t", []string{"2 1"}} - s.runTestInSchemaState(c, model.StateWriteOnly, true, addColumnSQL, sqls, expectQuery) + s.runTestInSchemaState(model.StateWriteOnly, true, addColumnSQL, sqls, expectQuery) } -func (s *testStateChangeSuite) TestWriteOnlyOnDupUpdateForAddColumns(c *C) { +func (s *stateChangeSuite) TestWriteOnlyOnDupUpdateForAddColumns() { sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"delete from t", nil} sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2018-02-12', c4 = 2 on duplicate key update c1 = values(c1)", nil} sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2019-02-12', c4 = 2 on duplicate key update c1 = values(c1)", nil} addColumnsSQL := "alter table t add column c5 int not null default 1 after c4, add column c44 int not null default 1" expectQuery := &expectQuery{"select c4, c5, c44 from t", []string{"2 1 1"}} - s.runTestInSchemaState(c, model.StateWriteOnly, true, addColumnsSQL, sqls, expectQuery) + s.runTestInSchemaState(model.StateWriteOnly, true, addColumnsSQL, sqls, expectQuery) +} + +func (s *stateChangeSuite) TestWriteReorgForModifyColumnTimestampToInt() { + tk := testkit.NewTestKit(s.T(), s.store) + tk.MustExec("use test_db_state") + tk.MustExec("drop table if exists tt") + tk.MustExec("create table tt(id int primary key auto_increment, c1 timestamp default '2020-07-10 01:05:08');") + tk.MustExec("insert into tt values();") + defer tk.MustExec("drop table if exists tt") + + sqls := make([]sqlWithErr, 1) + sqls[0] = sqlWithErr{"insert into tt values();", nil} + modifyColumnSQL := "alter table tt modify column c1 bigint;" + expectQuery := &expectQuery{"select c1 from tt", []string{"20200710010508", "20200710010508"}} + s.runTestInSchemaState(model.StateWriteReorganization, true, modifyColumnSQL, sqls, expectQuery) } type idxType byte @@ -560,33 +539,27 @@ const ( ) // TestWriteReorgForModifyColumn tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumn(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumn() { modifyColumnSQL := "alter table tt change column c cc tinyint not null default 1 first" - s.testModifyColumn(c, model.StateWriteReorganization, modifyColumnSQL, noneIdx) + s.testModifyColumn(model.StateWriteReorganization, modifyColumnSQL, noneIdx) } // TestWriteReorgForModifyColumnWithUniqIdx tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithUniqIdx(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumnWithUniqIdx() { modifyColumnSQL := "alter table tt change column c cc tinyint unsigned not null default 1 first" - s.testModifyColumn(c, model.StateWriteReorganization, modifyColumnSQL, uniqIdx) + s.testModifyColumn(model.StateWriteReorganization, modifyColumnSQL, uniqIdx) } // TestWriteReorgForModifyColumnWithPKIsHandle tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithPKIsHandle(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumnWithPKIsHandle() { modifyColumnSQL := "alter table tt change column c cc tinyint not null default 1 first" - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table tt (a int not null, b int default 1, c int not null default 0, unique index idx(c), primary key idx1(a) clustered, index idx2(a, c))`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (a, c) values(-1, -11)") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (a, c) values(1, 11)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tt") - c.Assert(err, IsNil) - }() + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists tt") + s.tk.MustExec(`create table tt (a int not null, b int default 1, c int not null default 0, unique index idx(c), primary key idx1(a) clustered, index idx2(a, c))`) + s.tk.MustExec("insert into tt (a, c) values(-1, -11)") + s.tk.MustExec("insert into tt (a, c) values(1, 11)") + defer s.tk.MustExec("drop table if exists tt") sqls := make([]sqlWithErr, 12) sqls[0] = sqlWithErr{"delete from tt where c = -11", nil} @@ -603,54 +576,48 @@ func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithPKIsHandle sqls[11] = sqlWithErr{"replace into tt values(6, 66, 56)", nil} query := &expectQuery{sql: "admin check table tt;", rows: nil} - s.runTestInSchemaState(c, model.StateWriteReorganization, false, modifyColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateWriteReorganization, false, modifyColumnSQL, sqls, query) } // TestWriteReorgForModifyColumnWithPrimaryIdx tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithPrimaryIdx(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumnWithPrimaryIdx() { modifyColumnSQL := "alter table tt change column c cc tinyint not null default 1 first" - s.testModifyColumn(c, model.StateWriteReorganization, modifyColumnSQL, uniqIdx) + s.testModifyColumn(model.StateWriteReorganization, modifyColumnSQL, uniqIdx) } // TestWriteReorgForModifyColumnWithoutFirst tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithoutFirst(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumnWithoutFirst() { modifyColumnSQL := "alter table tt change column c cc tinyint not null default 1" - s.testModifyColumn(c, model.StateWriteReorganization, modifyColumnSQL, noneIdx) + s.testModifyColumn(model.StateWriteReorganization, modifyColumnSQL, noneIdx) } // TestWriteReorgForModifyColumnWithoutDefaultVal tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestWriteReorgForModifyColumnWithoutDefaultVal(c *C) { +func (s *stateChangeSuite) TestWriteReorgForModifyColumnWithoutDefaultVal() { modifyColumnSQL := "alter table tt change column c cc tinyint first" - s.testModifyColumn(c, model.StateWriteReorganization, modifyColumnSQL, noneIdx) + s.testModifyColumn(model.StateWriteReorganization, modifyColumnSQL, noneIdx) } // TestDeleteOnlyForModifyColumnWithoutDefaultVal tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *serialTestStateChangeSuite) TestDeleteOnlyForModifyColumnWithoutDefaultVal(c *C) { +func (s *stateChangeSuite) TestDeleteOnlyForModifyColumnWithoutDefaultVal() { modifyColumnSQL := "alter table tt change column c cc tinyint first" - s.testModifyColumn(c, model.StateDeleteOnly, modifyColumnSQL, noneIdx) + s.testModifyColumn(model.StateDeleteOnly, modifyColumnSQL, noneIdx) } -func (s *serialTestStateChangeSuite) testModifyColumn(c *C, state model.SchemaState, modifyColumnSQL string, idx idxType) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) +func (s *stateChangeSuite) testModifyColumn(state model.SchemaState, modifyColumnSQL string, idx idxType) { + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists tt") switch idx { case uniqIdx: - _, err = s.se.Execute(context.Background(), `create table tt (a varchar(64), b int default 1, c int not null default 0, unique index idx(c), unique index idx1(a), index idx2(a, c))`) + s.tk.MustExec(`create table tt (a varchar(64), b int default 1, c int not null default 0, unique index idx(c), unique index idx1(a), index idx2(a, c))`) case primaryIdx: // TODO: Support modify/change column with the primary key. - _, err = s.se.Execute(context.Background(), `create table tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), primary index idx1(a), index idx2(a, c))`) + s.tk.MustExec(`create table tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), primary index idx1(a), index idx2(a, c))`) default: - _, err = s.se.Execute(context.Background(), `create table tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), index idx1(a), index idx2(a, c))`) + s.tk.MustExec(`create table tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), index idx1(a), index idx2(a, c))`) } - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (a, c) values('a', 11)") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (a, c) values('b', 22)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tt") - c.Assert(err, IsNil) - }() + s.tk.MustExec("insert into tt (a, c) values('a', 11)") + s.tk.MustExec("insert into tt (a, c) values('b', 22)") + defer s.tk.MustExec("drop table if exists tt") sqls := make([]sqlWithErr, 13) sqls[0] = sqlWithErr{"delete from tt where c = 11", nil} @@ -677,41 +644,36 @@ func (s *serialTestStateChangeSuite) testModifyColumn(c *C, state model.SchemaSt sqls[12] = sqlWithErr{"replace into tt values('a_replace_2', 77, 56)", nil} query := &expectQuery{sql: "admin check table tt;", rows: nil} - s.runTestInSchemaState(c, state, false, modifyColumnSQL, sqls, query) + s.runTestInSchemaState(state, false, modifyColumnSQL, sqls, query) } // TestWriteOnly tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *testStateChangeSuite) TestWriteOnly(c *C) { +func (s *stateChangeSuite) TestWriteOnly() { sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil} sqls[1] = sqlWithErr{"update t use index(idx2) set c1 = 'c1_update' where c1 = 'a'", nil} sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2018-02-12', c4 = 1", nil} addColumnSQL := "alter table t add column c5 int not null default 1 first" - s.runTestInSchemaState(c, model.StateWriteOnly, true, addColumnSQL, sqls, nil) + s.runTestInSchemaState(model.StateWriteOnly, true, addColumnSQL, sqls, nil) } // TestWriteOnlyForAddColumns tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *testStateChangeSuite) TestWriteOnlyForAddColumns(c *C) { +func (s *stateChangeSuite) TestWriteOnlyForAddColumns() { sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil} sqls[1] = sqlWithErr{"update t use index(idx2) set c1 = 'c1_update' where c1 = 'a'", nil} sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2018-02-12', c4 = 1", nil} addColumnsSQL := "alter table t add column c5 int not null default 1 first, add column c6 int not null default 1" - s.runTestInSchemaState(c, model.StateWriteOnly, true, addColumnsSQL, sqls, nil) + s.runTestInSchemaState(model.StateWriteOnly, true, addColumnsSQL, sqls, nil) } // TestDeleteOnly tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *testStateChangeSuite) TestDeleteOnly(c *C) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table tt (c varchar(64), c4 int)`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (c, c4) values('a', 8)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tt") - c.Assert(err, IsNil) - }() +func (s *stateChangeSuite) TestDeleteOnly() { + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists tt") + s.tk.MustExec(`create table tt (c varchar(64), c4 int)`) + s.tk.MustExec("insert into tt (c, c4) values('a', 8)") + defer s.tk.MustExec("drop table if exists tt") sqls := make([]sqlWithErr, 5) sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2018-02-12', c4 = 1", @@ -726,75 +688,91 @@ func (s *testStateChangeSuite) TestDeleteOnly(c *C) { errors.Errorf("[planner:1054]Unknown column 't.c1' in 'on clause'")} query := &expectQuery{sql: "select * from t;", rows: []string{"N 2017-07-01 00:00:00 8"}} dropColumnSQL := "alter table t drop column c1" - s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateDeleteOnly, true, dropColumnSQL, sqls, query) } -// TestDeleteOnlyForDropColumnWithIndexes test for delete data when a middle-state column with indexes in it. -func (s *testStateChangeSuite) TestDeleteOnlyForDropColumnWithIndexes(c *C) { - tk := testkit.NewTestKit(c, s.store) +// TestSchemaChangeForDropColumnWithIndexes test for modify data when a middle-state column with indexes in it. +func (s *stateChangeSuite) TestSchemaChangeForDropColumnWithIndexes() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") - sqls := make([]sqlWithErr, 2) + sqls := make([]sqlWithErr, 5) sqls[0] = sqlWithErr{"delete from t1", nil} sqls[1] = sqlWithErr{"delete from t1 where b=1", errors.Errorf("[planner:1054]Unknown column 'b' in 'where clause'")} + sqls[2] = sqlWithErr{"insert into t1(a) values(1);", nil} + sqls[3] = sqlWithErr{"update t1 set a = 2 where a=1;", nil} + sqls[4] = sqlWithErr{"delete from t1", nil} prepare := func() { tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(a int key, b int, c int, index idx(b));") + tk.MustExec("create table t1(a bigint unsigned not null primary key, b int, c int, index idx(b));") tk.MustExec("insert into t1 values(1,1,1);") } prepare() dropColumnSQL := "alter table t1 drop column b" query := &expectQuery{sql: "select * from t1;", rows: []string{}} - s.runTestInSchemaState(c, model.StateWriteOnly, true, dropColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateWriteOnly, true, dropColumnSQL, sqls, query) + prepare() + s.runTestInSchemaState(model.StateDeleteOnly, true, dropColumnSQL, sqls, query) + prepare() + s.runTestInSchemaState(model.StateDeleteReorganization, true, dropColumnSQL, sqls, query) +} + +// TestSchemaChangeForDropColumnWithIndexes test for modify data when some middle-state columns with indexes in it. +func (s *stateChangeSuite) TestSchemaChangeForDropColumnsWithIndexes() { + tk := testkit.NewTestKit(s.T(), s.store) + tk.MustExec("use test_db_state") + sqls := make([]sqlWithErr, 5) + sqls[0] = sqlWithErr{"delete from t1", nil} + sqls[1] = sqlWithErr{"delete from t1 where b=1", errors.Errorf("[planner:1054]Unknown column 'b' in 'where clause'")} + sqls[2] = sqlWithErr{"insert into t1(a) values(1);", nil} + sqls[3] = sqlWithErr{"update t1 set a = 2 where a=1;", nil} + sqls[4] = sqlWithErr{"delete from t1", nil} + prepare := func() { + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(a bigint unsigned not null primary key, b int, c int, d int, index idx(b), index idx2(d));") + tk.MustExec("insert into t1 values(1,1,1,1);") + } + prepare() + dropColumnSQL := "alter table t1 drop column b, drop column d" + query := &expectQuery{sql: "select * from t1;", rows: []string{}} + s.runTestInSchemaState(model.StateWriteOnly, true, dropColumnSQL, sqls, query) prepare() - s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateDeleteOnly, true, dropColumnSQL, sqls, query) prepare() - s.runTestInSchemaState(c, model.StateDeleteReorganization, true, dropColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateDeleteReorganization, true, dropColumnSQL, sqls, query) } // TestDeleteOnlyForDropExpressionIndex tests for deleting data when the hidden column is delete-only state. -func (s *serialTestStateChangeSuite) TestDeleteOnlyForDropExpressionIndex(c *C) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table tt (a int, b int)`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `alter table tt add index expr_idx((a+1))`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (a, b) values(8, 8)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tt") - c.Assert(err, IsNil) - }() +func (s *stateChangeSuite) TestDeleteOnlyForDropExpressionIndex() { + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists tt") + s.tk.MustExec(`create table tt (a int, b int)`) + s.tk.MustExec(`alter table tt add index expr_idx((a+1))`) + s.tk.MustExec("insert into tt (a, b) values(8, 8)") + defer s.tk.MustExec("drop table if exists tt") sqls := make([]sqlWithErr, 1) sqls[0] = sqlWithErr{"delete from tt where b=8", nil} dropIdxSQL := "alter table tt drop index expr_idx" - s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropIdxSQL, sqls, nil) + s.runTestInSchemaState(model.StateDeleteOnly, true, dropIdxSQL, sqls, nil) - _, err = s.se.Execute(context.Background(), "admin check table tt") - c.Assert(err, IsNil) + s.tk.MustExec("admin check table tt") } // TestDeleteOnlyForDropColumns tests whether the correct columns is used in PhysicalIndexScan's ToPB function. -func (s *testStateChangeSuite) TestDeleteOnlyForDropColumns(c *C) { +func (s *stateChangeSuite) TestDeleteOnlyForDropColumns() { sqls := make([]sqlWithErr, 1) sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2018-02-12', c4 = 1", errors.Errorf("Can't find column c1")} dropColumnsSQL := "alter table t drop column c1, drop column c3" - s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropColumnsSQL, sqls, nil) + s.runTestInSchemaState(model.StateDeleteOnly, true, dropColumnsSQL, sqls, nil) } -func (s *testStateChangeSuite) TestWriteOnlyForDropColumn(c *C) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table tt (c1 int, c4 int)`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tt (c1, c4) values(8, 8)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tt") - c.Assert(err, IsNil) - }() +func (s *stateChangeSuite) TestWriteOnlyForDropColumn() { + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists tt") + s.tk.MustExec(`create table tt (c1 int, c4 int)`) + s.tk.MustExec("insert into tt (c1, c4) values(8, 8)") + defer s.tk.MustExec("drop table if exists tt") sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"update t set c1='5', c3='2020-03-01';", errors.New("[planner:1054]Unknown column 'c3' in 'field list'")} @@ -804,20 +782,14 @@ func (s *testStateChangeSuite) TestWriteOnlyForDropColumn(c *C) { sqls[2] = sqlWithErr{"update t set c1='5' where c3='2017-07-01';", errors.New("[planner:1054]Unknown column 'c3' in 'where clause'")} dropColumnSQL := "alter table t drop column c3" query := &expectQuery{sql: "select * from t;", rows: []string{"a N 8"}} - s.runTestInSchemaState(c, model.StateWriteOnly, false, dropColumnSQL, sqls, query) + s.runTestInSchemaState(model.StateWriteOnly, false, dropColumnSQL, sqls, query) } -func (s *testStateChangeSuite) TestWriteOnlyForDropColumns(c *C) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table t_drop_columns (c1 int, c4 int)`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into t_drop_columns (c1, c4) values(8, 8)") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t_drop_columns") - c.Assert(err, IsNil) - }() +func (s *stateChangeSuite) TestWriteOnlyForDropColumns() { + s.tk.MustExec("use test_db_state") + s.tk.MustExec(`create table t_drop_columns (c1 int, c4 int)`) + s.tk.MustExec("insert into t_drop_columns (c1, c4) values(8, 8)") + defer s.tk.MustExec("drop table t_drop_columns") sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"update t set c1='5', c3='2020-03-01';", errors.New("[planner:1054]Unknown column 'c1' in 'field list'")} @@ -826,42 +798,43 @@ func (s *testStateChangeSuite) TestWriteOnlyForDropColumns(c *C) { sqls[2] = sqlWithErr{"update t set c1='5' where c3='2017-07-01';", errors.New("[planner:1054]Unknown column 'c3' in 'where clause'")} dropColumnsSQL := "alter table t drop column c3, drop column c1" query := &expectQuery{sql: "select * from t;", rows: []string{"N 8"}} - s.runTestInSchemaState(c, model.StateWriteOnly, false, dropColumnsSQL, sqls, query) + s.runTestInSchemaState(model.StateWriteOnly, false, dropColumnsSQL, sqls, query) } -func (s *testStateChangeSuiteBase) runTestInSchemaState(c *C, state model.SchemaState, isOnJobUpdated bool, alterTableSQL string, - sqlWithErrs []sqlWithErr, expectQuery *expectQuery) { - _, err := s.se.Execute(context.Background(), `create table t ( +func (s *stateChangeSuite) runTestInSchemaState( + state model.SchemaState, + isOnJobUpdated bool, + alterTableSQL string, + sqlWithErrs []sqlWithErr, + expectQuery *expectQuery, +) { + s.tk.MustExec(`create table t ( c1 varchar(64), c2 enum('N','Y') not null default 'N', c3 timestamp on update current_timestamp, c4 int primary key, unique key idx2 (c2))`) - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() - _, err = s.se.Execute(context.Background(), "insert into t values('a', 'N', '2017-07-01', 8)") - c.Assert(err, IsNil) - // Make sure these sqls use the the plan of index scan. - _, err = s.se.Execute(context.Background(), "drop stats t") - c.Assert(err, IsNil) + defer s.tk.MustExec("drop table t") + s.tk.MustExec("insert into t values('a', 'N', '2017-07-01', 8)") + // Make sure these SQLs use the plan of index scan. + s.tk.MustExec("drop stats t") callback := &ddl.TestDDLCallback{Do: s.dom} prevState := model.StateNone - var checkErr error times := 0 + var checkErr error se, err := session.CreateSession(s.store) - c.Assert(err, IsNil) + s.Require().NoError(err) _, err = se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) + s.Require().NoError(err) cbFunc := func(job *model.Job) { - if job.SchemaState == prevState || checkErr != nil || times >= 3 { + if currentSchemaState(job) == prevState || checkErr != nil || times >= 3 { return } - times++ - if job.SchemaState != state { + if job.MultiSchemaInfo == nil { + times++ + } + if currentSchemaState(job) != state { return } for _, sqlWithErr := range sqlWithErrs { @@ -879,69 +852,39 @@ func (s *testStateChangeSuiteBase) runTestInSchemaState(c *C, state model.Schema } d := s.dom.DDL() originalCallback := d.GetHook() - d.(ddl.DDLForTest).SetHook(callback) - _, err = s.se.Execute(context.Background(), alterTableSQL) - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) - d.(ddl.DDLForTest).SetHook(originalCallback) + d.SetHook(callback) + s.tk.MustExec(alterTableSQL) + s.Require().NoError(checkErr) + d.SetHook(originalCallback) if expectQuery != nil { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") - result, err := s.execQuery(tk, expectQuery.sql) - c.Assert(err, IsNil) + rs, _ := tk.Exec(expectQuery.sql) if expectQuery.rows == nil { - c.Assert(result, IsNil) - return + s.Require().Nil(rs) + } else { + rows := tk.ResultSetToResult(rs, fmt.Sprintf("sql:%s", expectQuery.sql)) + rows.Check(testkit.Rows(expectQuery.rows...)) } - err = checkResult(result, testkit.Rows(expectQuery.rows...)) - c.Assert(err, IsNil) } } -func (s *testStateChangeSuiteBase) execQuery(tk *testkit.TestKit, sql string, args ...interface{}) (*testkit.Result, error) { - comment := Commentf("sql:%s, args:%v", sql, args) - rs, err := tk.Exec(sql, args...) - if err != nil { - return nil, err +func currentSchemaState(job *model.Job) model.SchemaState { + if job.Type == model.ActionMultiSchemaChange && job.MultiSchemaInfo != nil { + subs := job.MultiSchemaInfo.SubJobs + return subs[len(subs)-1].SchemaState } - if rs == nil { - return nil, nil - } - result := tk.ResultSetToResult(rs, comment) - return result, nil + return job.SchemaState } -func checkResult(result *testkit.Result, expected [][]interface{}) error { - got := fmt.Sprintf("%s", result.Rows()) - need := fmt.Sprintf("%s", expected) - if got != need { - return fmt.Errorf("need %v, but got %v", need, got) - } - return nil -} - -func (s *testStateChangeSuiteBase) CheckResult(tk *testkit.TestKit, sql string, args ...interface{}) (*testkit.Result, error) { - comment := Commentf("sql:%s, args:%v", sql, args) - rs, err := tk.Exec(sql, args...) - if err != nil { - return nil, err - } - result := tk.ResultSetToResult(rs, comment) - return result, nil -} - -func (s *testStateChangeSuite) TestShowIndex(c *C) { - _, err := s.se.Execute(context.Background(), `create table t(c1 int primary key nonclustered, c2 int)`) - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() +func (s *stateChangeSuite) TestShowIndex() { + s.tk.MustExec(`create table t(c1 int primary key nonclustered, c2 int)`) + defer s.tk.MustExec("drop table t") callback := &ddl.TestDDLCallback{} prevState := model.StateNone - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") showIndexSQL := `show index from t` var checkErr error @@ -951,35 +894,34 @@ func (s *testStateChangeSuite) TestShowIndex(c *C) { } switch job.SchemaState { case model.StateDeleteOnly, model.StateWriteOnly, model.StateWriteReorganization: - result, err1 := s.execQuery(tk, showIndexSQL) + result, err1 := tk.Exec(showIndexSQL) if err1 != nil { checkErr = err1 break } - checkErr = checkResult(result, testkit.Rows("t 0 PRIMARY 1 c1 A 0 BTREE YES NO")) + rows := tk.ResultSetToResult(result, fmt.Sprintf("sql:%s", showIndexSQL)) + got := fmt.Sprintf("%s", rows.Rows()) + need := fmt.Sprintf("%s", testkit.Rows("t 0 PRIMARY 1 c1 A 0 BTREE YES NO")) + if got != need { + checkErr = fmt.Errorf("need %v, but got %v", need, got) + } } } d := s.dom.DDL() originalCallback := d.GetHook() - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) alterTableSQL := `alter table t add index c2(c2)` - _, err = s.se.Execute(context.Background(), alterTableSQL) - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) + s.tk.MustExec(alterTableSQL) + s.Require().NoError(checkErr) - result, err := s.execQuery(tk, showIndexSQL) - c.Assert(err, IsNil) - err = checkResult(result, testkit.Rows( + tk.MustQuery(showIndexSQL).Check(testkit.Rows( "t 0 PRIMARY 1 c1 A 0 BTREE YES NO", "t 1 c2 1 c2 A 0 YES BTREE YES NO", )) - c.Assert(err, IsNil) - d.(ddl.DDLForTest).SetHook(originalCallback) - - c.Assert(err, IsNil) + d.SetHook(originalCallback) - _, err = s.se.Execute(context.Background(), `create table tr( + s.tk.MustExec(`create table tr( id int, name varchar(50), purchased date ) @@ -991,146 +933,222 @@ func (s *testStateChangeSuite) TestShowIndex(c *C) { partition p4 values less than (2010), partition p5 values less than (2015) );`) - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tr") - c.Assert(err, IsNil) - }() - _, err = s.se.Execute(context.Background(), "create index idx1 on tr (purchased);") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "show index from tr;") - c.Assert(err, IsNil) - err = checkResult(result, testkit.Rows("tr 1 idx1 1 purchased A 0 YES BTREE YES NO")) - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "drop table if exists tr") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table tr(id int primary key clustered, v int, key vv(v))") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "show index from tr") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("tr 0 PRIMARY 1 id A 0 BTREE YES YES", "tr 1 vv 1 v A 0 YES BTREE YES NO")), IsNil) - result, err = s.execQuery(tk, "select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("PRIMARY YES", "vv NO")), IsNil) - - _, err = s.se.Execute(context.Background(), "drop table if exists tr") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table tr(id int primary key nonclustered, v int, key vv(v))") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "show index from tr") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES NO")), IsNil) - result, err = s.execQuery(tk, "select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("PRIMARY NO", "vv NO")), IsNil) - - _, err = s.se.Execute(context.Background(), "drop table if exists tr") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table tr(id char(100) primary key clustered, v int, key vv(v))") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "show index from tr") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES YES")), IsNil) - result, err = s.execQuery(tk, "select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("PRIMARY YES", "vv NO")), IsNil) - - _, err = s.se.Execute(context.Background(), "drop table if exists tr") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table tr(id char(100) primary key nonclustered, v int, key vv(v))") - c.Assert(err, IsNil) - result, err = s.execQuery(tk, "show index from tr") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES NO")), IsNil) - result, err = s.execQuery(tk, "select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name") - c.Assert(err, IsNil) - c.Assert(checkResult(result, testkit.Rows("PRIMARY NO", "vv NO")), IsNil) -} - -func (s *testStateChangeSuite) TestParallelAlterModifyColumn(c *C) { + defer s.tk.MustExec("drop table tr") + s.tk.MustExec("create index idx1 on tr (purchased);") + tk.MustQuery("show index from tr;").Check(testkit.Rows("tr 1 idx1 1 purchased A 0 YES BTREE YES NO")) + + s.tk.MustExec("drop table if exists tr") + s.tk.MustExec("create table tr(id int primary key clustered, v int, key vv(v))") + tk.MustQuery("show index from tr").Check(testkit.Rows("tr 0 PRIMARY 1 id A 0 BTREE YES YES", "tr 1 vv 1 v A 0 YES BTREE YES NO")) + tk.MustQuery("select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name").Check(testkit.Rows("PRIMARY YES", "vv NO")) + + s.tk.MustExec("drop table if exists tr") + s.tk.MustExec("create table tr(id int primary key nonclustered, v int, key vv(v))") + tk.MustQuery("show index from tr").Check(testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name").Check(testkit.Rows("PRIMARY NO", "vv NO")) + + s.tk.MustExec("drop table if exists tr") + s.tk.MustExec("create table tr(id char(100) primary key clustered, v int, key vv(v))") + tk.MustQuery("show index from tr").Check(testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name").Check(testkit.Rows("PRIMARY YES", "vv NO")) + + s.tk.MustExec("drop table if exists tr") + s.tk.MustExec("create table tr(id char(100) primary key nonclustered, v int, key vv(v))") + tk.MustQuery("show index from tr").Check(testkit.Rows("tr 1 vv 1 v A 0 YES BTREE YES NO", "tr 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("select key_name, clustered from information_schema.tidb_indexes where table_name = 'tr' order by key_name").Check(testkit.Rows("PRIMARY NO", "vv NO")) +} + +func (s *stateChangeSuite) TestParallelAlterModifyColumn() { sql := "ALTER TABLE t MODIFY COLUMN b int FIRST;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, IsNil) - rs, err := s.se.Execute(context.Background(), "select * from t") - c.Assert(err, IsNil) - c.Assert(rs[0].Close(), IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().NoError(err2) + s.tk.MustExec("select * from t") + } + s.testControlParallelExecSQL("", sql, sql, f) +} + +func (s *stateChangeSuite) TestParallelAlterModifyColumnWithData() { + // modify column: double -> int + // modify column: double -> int + sql := "ALTER TABLE t MODIFY COLUMN c int;" + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1072]column c id 3 does not exist, this column may have been updated by other DDL ran in parallel") + rs, err := s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err := session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("3", sRows[0][2]) + s.Require().NoError(rs.Close()) + s.tk.MustExec("insert into t values(11, 22, 33.3, 44, 55)") + rs, err = s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err = session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("33", sRows[1][2]) + s.Require().NoError(rs.Close()) } - s.testControlParallelExecSQL(c, sql, sql, f) + s.testControlParallelExecSQL("", sql, sql, f) + + // modify column: int -> double + // rename column: double -> int + sql1 := "ALTER TABLE t MODIFY b double;" + sql2 := "ALTER TABLE t RENAME COLUMN b to bb;" + f = func(err1, err2 error) { + s.Require().Nil(err1) + s.Require().Nil(err2) + rs, err := s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err := session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("2", sRows[0][1]) + s.Require().NoError(rs.Close()) + s.tk.MustExec("insert into t values(11, 22.2, 33, 44, 55)") + rs, err = s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err = session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("22", sRows[1][1]) + s.Require().NoError(rs.Close()) + } + s.testControlParallelExecSQL("", sql1, sql2, f) + + // modify column: int -> double + // modify column: double -> int + sql2 = "ALTER TABLE t CHANGE b bb int;" + f = func(err1, err2 error) { + s.Require().Nil(err1) + s.Require().Nil(err2) + rs, err := s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err := session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("2", sRows[0][1]) + s.Require().NoError(rs.Close()) + s.tk.MustExec("insert into t values(11, 22.2, 33, 44, 55)") + rs, err = s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err = session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("22", sRows[1][1]) + s.Require().NoError(rs.Close()) + } + s.testControlParallelExecSQL("", sql1, sql2, f) +} + +func (s *stateChangeSuite) TestParallelAlterModifyColumnToNotNullWithData() { + // double null -> int not null + // double null -> int not null + sql := "ALTER TABLE t MODIFY COLUMN c int not null;" + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1072]column c id 3 does not exist, this column may have been updated by other DDL ran in parallel") + rs, err := s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err := session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("3", sRows[0][2]) + s.Require().NoError(rs.Close()) + err = s.tk.ExecToErr("insert into t values(11, 22, null, 44, 55)") + s.Require().Error(err) + s.tk.MustExec("insert into t values(11, 22, 33.3, 44, 55)") + rs, err = s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err = session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("33", sRows[1][2]) + s.Require().NoError(rs.Close()) + } + s.testControlParallelExecSQL("", sql, sql, f) + + // int null -> double not null + // double not null -> int null + sql1 := "ALTER TABLE t CHANGE b b double not null;" + sql2 := "ALTER TABLE t CHANGE b bb int null;" + f = func(err1, err2 error) { + s.Require().Nil(err1) + s.Require().Nil(err2) + rs, err := s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err := session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("2", sRows[0][1]) + s.Require().NoError(rs.Close()) + err = s.tk.ExecToErr("insert into t values(11, null, 33, 44, 55)") + s.Require().NoError(err) + s.tk.MustExec("insert into t values(11, 22.2, 33, 44, 55)") + rs, err = s.tk.Exec("select * from t") + s.Require().NoError(err) + sRows, err = session.ResultSetToStringSlice(context.Background(), s.tk.Session(), rs) + s.Require().NoError(err) + s.Require().Equal("", sRows[1][1]) + s.Require().Equal("22", sRows[2][1]) + s.Require().NoError(rs.Close()) + } + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAddGeneratedColumnAndAlterModifyColumn(c *C) { +func (s *stateChangeSuite) TestParallelAddGeneratedColumnAndAlterModifyColumn() { sql1 := "ALTER TABLE t ADD COLUMN f INT GENERATED ALWAYS AS(a+1);" sql2 := "ALTER TABLE t MODIFY COLUMN a tinyint;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:8200]Unsupported modify column: oldCol is a dependent column 'a' for generated column") - rs, err := s.se.Execute(context.Background(), "select * from t") - c.Assert(err, IsNil) - c.Assert(rs[0].Close(), IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:8200]Unsupported modify column: oldCol is a dependent column 'a' for generated column") + s.tk.MustExec("select * from t") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAlterModifyColumnAndAddPK(c *C) { +func (s *stateChangeSuite) TestParallelAlterModifyColumnAndAddPK() { sql1 := "ALTER TABLE t ADD PRIMARY KEY (b) NONCLUSTERED;" sql2 := "ALTER TABLE t MODIFY COLUMN b tinyint;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:8200]Unsupported modify column: this column has primary key flag") - rs, err := s.se.Execute(context.Background(), "select * from t") - c.Assert(err, IsNil) - c.Assert(rs[0].Close(), IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:8200]Unsupported modify column: this column has primary key flag") + s.tk.MustExec("select * from t") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } // TODO: This test is not a test that performs two DDLs in parallel. // So we should not use the function of testControlParallelExecSQL. We will handle this test in the next PR. -// func (s *testStateChangeSuite) TestParallelColumnModifyingDefinition(c *C) { +// func (s *stateChangeSuite) TestParallelColumnModifyingDefinition() { // sql1 := "insert into t(b) values (null);" // sql2 := "alter table t change b b2 bigint not null;" -// f := func(c *C, err1, err2 error) { -// c.Assert(err1, IsNil) +// f := func(err1, err2 error) { +// s.Require().NoError(err1) // if err2 != nil { -// c.Assert(err2.Error(), Equals, "[ddl:1265]Data truncated for column 'b2' at row 1") +// s.Require().ErrorEqual(err2, "[ddl:1265]Data truncated for column 'b2' at row 1") // } // } -// s.testControlParallelExecSQL(c, sql1, sql2, f) +// s.testControlParallelExecSQL("", sql1, sql2, f) // } -func (s *testStateChangeSuite) TestParallelAddColumAndSetDefaultValue(c *C) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table tx ( +func (s *stateChangeSuite) TestParallelAddColumAndSetDefaultValue() { + s.tk.MustExec("use test_db_state") + s.tk.MustExec(`create table tx ( c1 varchar(64), c2 enum('N','Y') not null default 'N', primary key idx2 (c2, c1))`) - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "insert into tx values('a', 'N')") - c.Assert(err, IsNil) - defer func() { - _, err := s.se.Execute(context.Background(), "drop table tx") - c.Assert(err, IsNil) - }() + s.tk.MustExec("insert into tx values('a', 'N')") + defer s.tk.MustExec("drop table tx") sql1 := "alter table tx add column cx int after c1" sql2 := "alter table tx alter c2 set default 'N'" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, IsNil) - _, err := s.se.Execute(context.Background(), "delete from tx where c1='a'") - c.Assert(err, IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().NoError(err2) + s.tk.MustExec("delete from tx where c1='a'") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelChangeColumnName(c *C) { +func (s *stateChangeSuite) TestParallelChangeColumnName() { sql1 := "ALTER TABLE t CHANGE a aa int;" sql2 := "ALTER TABLE t CHANGE b aa int;" - f := func(c *C, err1, err2 error) { + f := func(err1, err2 error) { // Make sure only a DDL encounters the error of 'duplicate column name'. var oneErr error if (err1 != nil && err2 == nil) || (err1 == nil && err2 != nil) { @@ -1140,137 +1158,125 @@ func (s *testStateChangeSuite) TestParallelChangeColumnName(c *C) { oneErr = err2 } } - c.Assert(oneErr.Error(), Equals, "[schema:1060]Duplicate column name 'aa'") + s.Require().EqualError(oneErr, "[schema:1060]Duplicate column name 'aa'") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAlterAddIndex(c *C) { +func (s *stateChangeSuite) TestParallelAlterAddIndex() { sql1 := "ALTER TABLE t add index index_b(b);" sql2 := "CREATE INDEX index_b ON t (c);" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1061]index already exist index_b") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1061]index already exist index_b") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *serialTestStateChangeSuite) TestParallelAlterAddExpressionIndex(c *C) { +func (s *stateChangeSuite) TestParallelAlterAddExpressionIndex() { sql1 := "ALTER TABLE t add index expr_index_b((b+1));" sql2 := "CREATE INDEX expr_index_b ON t ((c+1));" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1061]index already exist expr_index_b") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1061]index already exist expr_index_b") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAddPrimaryKey(c *C) { +func (s *stateChangeSuite) TestParallelAddPrimaryKey() { sql1 := "ALTER TABLE t add primary key index_b(b);" sql2 := "ALTER TABLE t add primary key index_b(c);" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[schema:1068]Multiple primary key defined") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[schema:1068]Multiple primary key defined") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAlterAddPartition(c *C) { +func (s *stateChangeSuite) TestParallelAlterAddPartition() { sql1 := `alter table t_part add partition ( partition p2 values less than (30) );` sql2 := `alter table t_part add partition ( partition p3 values less than (30) );` - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1493]VALUES LESS THAN value must be strictly increasing for each partition") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1493]VALUES LESS THAN value must be strictly increasing for each partition") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelDropColumn(c *C) { +func (s *stateChangeSuite) TestParallelDropColumn() { sql := "ALTER TABLE t drop COLUMN c ;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1091]column c doesn't exist") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1091]column c doesn't exist") } - s.testControlParallelExecSQL(c, sql, sql, f) + s.testControlParallelExecSQL("", sql, sql, f) } -func (s *testStateChangeSuite) TestParallelDropColumns(c *C) { +func (s *stateChangeSuite) TestParallelDropColumns() { sql := "ALTER TABLE t drop COLUMN b, drop COLUMN c;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1091]column b doesn't exist") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1091]column b doesn't exist") } - s.testControlParallelExecSQL(c, sql, sql, f) + s.testControlParallelExecSQL("", sql, sql, f) } -func (s *testStateChangeSuite) TestParallelDropIfExistsColumns(c *C) { +func (s *stateChangeSuite) TestParallelDropIfExistsColumns() { sql := "ALTER TABLE t drop COLUMN if exists b, drop COLUMN if exists c;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().NoError(err2) } - s.testControlParallelExecSQL(c, sql, sql, f) + s.testControlParallelExecSQL("", sql, sql, f) } -func (s *testStateChangeSuite) TestParallelDropIndex(c *C) { +func (s *stateChangeSuite) TestParallelDropIndex() { sql1 := "alter table t drop index idx1 ;" sql2 := "alter table t drop index idx2 ;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[autoid:1075]Incorrect table definition; there can be only one auto column and it must be defined as a key") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[autoid:1075]Incorrect table definition; there can be only one auto column and it must be defined as a key") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelDropPrimaryKey(c *C) { - s.preSQL = "ALTER TABLE t add primary key index_b(c);" - defer func() { - s.preSQL = "" - }() +func (s *stateChangeSuite) TestParallelDropPrimaryKey() { sql1 := "alter table t drop primary key;" sql2 := "alter table t drop primary key;" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:1091]index PRIMARY doesn't exist") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:1091]index PRIMARY doesn't exist") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("ALTER TABLE t add primary key index_b(c);", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelCreateAndRename(c *C) { +func (s *stateChangeSuite) TestParallelCreateAndRename() { sql1 := "create table t_exists(c int);" sql2 := "alter table t rename to t_exists;" - defer func() { - // fixed - _, err := s.se.Execute(context.Background(), "drop table if exists t_exists ") - c.Assert(err, IsNil) - }() - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[schema:1050]Table 't_exists' already exists") + defer s.tk.MustExec("drop table if exists t_exists ") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[schema:1050]Table 't_exists' already exists") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -func (s *testStateChangeSuite) TestParallelAlterAndDropSchema(c *C) { - _, err := s.se.Execute(context.Background(), "create database db_drop_db") - c.Assert(err, IsNil) +func (s *stateChangeSuite) TestParallelAlterAndDropSchema() { + s.tk.MustExec("create database db_drop_db") sql1 := "DROP SCHEMA db_drop_db" sql2 := "ALTER SCHEMA db_drop_db CHARSET utf8mb4 COLLATE utf8mb4_general_ci" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, NotNil) - c.Assert(err2.Error(), Equals, "[schema:1008]Can't drop database ''; database doesn't exist") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[schema:1008]Can't drop database ''; database doesn't exist") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } -type checkRet func(c *C, err1, err2 error) - -func (s *testStateChangeSuiteBase) prepareTestControlParallelExecSQL(c *C) (session.Session, session.Session, chan struct{}, ddl.Callback) { +func (s *stateChangeSuite) prepareTestControlParallelExecSQL() (*testkit.TestKit, *testkit.TestKit, chan struct{}, ddl.Callback) { callback := &ddl.TestDDLCallback{} times := 0 callback.OnJobUpdatedExported = func(job *model.Job) { @@ -1287,7 +1293,7 @@ func (s *testStateChangeSuiteBase) prepareTestControlParallelExecSQL(c *C) (sess qLen = len(jobs) return nil }) - c.Assert(err, IsNil) + s.Require().NoError(err) if qLen == 2 { break } @@ -1297,16 +1303,13 @@ func (s *testStateChangeSuiteBase) prepareTestControlParallelExecSQL(c *C) (sess } d := s.dom.DDL() originalCallback := d.GetHook() - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) - se, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - se1, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se1.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) + tk1 := testkit.NewTestKit(s.T(), s.store) + tk1.MustExec("use test_db_state") + + tk2 := testkit.NewTestKit(s.T(), s.store) + tk2.MustExec("use test_db_state") ch := make(chan struct{}) // Make sure the sql1 is put into the DDLJobQueue. go func() { @@ -1320,7 +1323,7 @@ func (s *testStateChangeSuiteBase) prepareTestControlParallelExecSQL(c *C) (sess qLen = len(jobs) return nil }) - c.Assert(err, IsNil) + s.Require().NoError(err) if qLen == 1 { // Make sure sql2 is executed after the sql1. close(ch) @@ -1329,121 +1332,95 @@ func (s *testStateChangeSuiteBase) prepareTestControlParallelExecSQL(c *C) (sess time.Sleep(5 * time.Millisecond) } }() - return se, se1, ch, originalCallback + return tk1, tk2, ch, originalCallback } -func (s *testStateChangeSuiteBase) testControlParallelExecSQL(c *C, sql1, sql2 string, f checkRet) { - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table t(a int, b int, c int, d int auto_increment,e int, index idx1(d), index idx2(d,e))") - c.Assert(err, IsNil) - if len(s.preSQL) != 0 { - _, err := s.se.Execute(context.Background(), s.preSQL) - c.Assert(err, IsNil) +func (s *stateChangeSuite) testControlParallelExecSQL(preSQL, sql1, sql2 string, f func(e1, e2 error)) { + s.tk.MustExec("use test_db_state") + s.tk.MustExec("create table t(a int, b int, c double default null, d int auto_increment,e int, index idx1(d), index idx2(d,e))") + if len(preSQL) != 0 { + s.tk.MustExec(preSQL) } - defer func() { - _, err := s.se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() + s.tk.MustExec("insert into t values(1, 2, 3.1234, 4, 5)") + + defer s.tk.MustExec("drop table t") // fixed - _, err = s.se.Execute(context.Background(), "drop table if exists t_part") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), `create table t_part (a int key) - partition by range(a) ( - partition p0 values less than (10), - partition p1 values less than (20) - );`) - c.Assert(err, IsNil) - - se, se1, ch, originalCallback := s.prepareTestControlParallelExecSQL(c) - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalCallback) + s.tk.MustExec("drop table if exists t_part") + s.tk.MustExec(`create table t_part (a int key) + partition by range(a) ( + partition p0 values less than (10), + partition p1 values less than (20) + );`) + + tk1, tk2, ch, originalCallback := s.prepareTestControlParallelExecSQL() + defer s.dom.DDL().SetHook(originalCallback) var err1 error var err2 error - wg := sync.WaitGroup{} - wg.Add(2) - go func() { - defer wg.Done() - var rss []sqlexec.RecordSet - rss, err1 = se.Execute(context.Background(), sql1) - if err1 == nil && len(rss) > 0 { - for _, rs := range rss { - c.Assert(rs.Close(), IsNil) - } + var wg util.WaitGroupWrapper + wg.Run(func() { + var rs sqlexec.RecordSet + rs, err1 = tk1.Exec(sql1) + if err1 == nil && rs != nil { + s.Require().NoError(rs.Close()) } - }() - go func() { - defer wg.Done() + }) + wg.Run(func() { <-ch - var rss []sqlexec.RecordSet - rss, err2 = se1.Execute(context.Background(), sql2) - if err2 == nil && len(rss) > 0 { - for _, rs := range rss { - c.Assert(rs.Close(), IsNil) - } + var rs sqlexec.RecordSet + rs, err2 = tk2.Exec(sql2) + if err2 == nil && rs != nil { + s.Require().NoError(rs.Close()) } - }() + }) wg.Wait() - f(c, err1, err2) + f(err1, err2) } -func (s *serialTestStateChangeSuite) TestParallelUpdateTableReplica(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) +func (s *stateChangeSuite) TestParallelUpdateTableReplica() { + s.Require().NoError(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) + s.Require().NoError(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount")) }() - ctx := context.Background() - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(ctx, "drop table if exists t1;") - c.Assert(err, IsNil) - _, err = s.se.Execute(ctx, "create table t1 (a int);") - c.Assert(err, IsNil) - _, err = s.se.Execute(ctx, "alter table t1 set tiflash replica 3 location labels 'a','b';") - c.Assert(err, IsNil) + s.tk.MustExec("use test_db_state") + s.tk.MustExec("drop table if exists t1;") + s.tk.MustExec("create table t1 (a int);") + s.tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") - se, se1, ch, originalCallback := s.prepareTestControlParallelExecSQL(c) - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalCallback) + tk1, tk2, ch, originalCallback := s.prepareTestControlParallelExecSQL() + defer s.dom.DDL().SetHook(originalCallback) - t1 := testGetTableByName(c, se, "test_db_state", "t1") + t1 := external.GetTableByName(s.T(), s.tk, "test_db_state", "t1") var err1 error var err2 error - wg := sync.WaitGroup{} - wg.Add(2) - go func() { - defer wg.Done() + var wg util.WaitGroupWrapper + wg.Run(func() { // Mock for table tiflash replica was available. - err1 = domain.GetDomain(se).DDL().UpdateTableReplicaInfo(se, t1.Meta().ID, true) - }() - go func() { - defer wg.Done() + err1 = domain.GetDomain(tk1.Session()).DDL().UpdateTableReplicaInfo(tk1.Session(), t1.Meta().ID, true) + }) + wg.Run(func() { <-ch // Mock for table tiflash replica was available. - err2 = domain.GetDomain(se1).DDL().UpdateTableReplicaInfo(se1, t1.Meta().ID, true) - }() + err2 = domain.GetDomain(tk2.Session()).DDL().UpdateTableReplicaInfo(tk2.Session(), t1.Meta().ID, true) + }) wg.Wait() - c.Assert(err1, IsNil) - c.Assert(err2.Error(), Equals, "[ddl:-1]the replica available status of table t1 is already updated") + s.Require().NoError(err1) + s.Require().EqualError(err2, "[ddl:-1]the replica available status of table t1 is already updated") } -func (s *testStateChangeSuite) testParallelExecSQL(c *C, sql string) { - se, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) +func (s *stateChangeSuite) testParallelExecSQL(sql string) { + tk1 := testkit.NewTestKit(s.T(), s.store) + tk1.MustExec("use test_db_state") - se1, err1 := session.CreateSession(s.store) - c.Assert(err1, IsNil) - _, err = se1.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) + tk2 := testkit.NewTestKit(s.T(), s.store) + tk2.MustExec("use test_db_state") var err2, err3 error - wg := sync.WaitGroup{} + var wg util.WaitGroupWrapper callback := &ddl.TestDDLCallback{} once := sync.Once{} @@ -1456,121 +1433,93 @@ func (s *testStateChangeSuite) testParallelExecSQL(c *C, sql string) { d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) - d.(ddl.DDLForTest).SetHook(callback) - - wg.Add(2) - go func() { - defer wg.Done() - _, err2 = se.Execute(context.Background(), sql) - }() - - go func() { - defer wg.Done() - _, err3 = se1.Execute(context.Background(), sql) - }() + defer d.SetHook(originalCallback) + d.SetHook(callback) + wg.Run(func() { + err2 = tk1.ExecToErr(sql) + }) + wg.Run(func() { + err3 = tk2.ExecToErr(sql) + }) wg.Wait() - c.Assert(err2, IsNil) - c.Assert(err3, IsNil) + s.Require().NoError(err2) + s.Require().NoError(err3) } // TestCreateTableIfNotExists parallel exec create table if not exists xxx. No error returns is expected. -func (s *testStateChangeSuite) TestCreateTableIfNotExists(c *C) { - defer func() { - _, err := s.se.Execute(context.Background(), "drop table test_not_exists") - c.Assert(err, IsNil) - }() - s.testParallelExecSQL(c, "create table if not exists test_not_exists(a int);") +func (s *stateChangeSuite) TestCreateTableIfNotExists() { + defer s.tk.MustExec("drop table test_not_exists") + s.testParallelExecSQL("create table if not exists test_not_exists(a int);") } // TestCreateDBIfNotExists parallel exec create database if not exists xxx. No error returns is expected. -func (s *testStateChangeSuite) TestCreateDBIfNotExists(c *C) { - defer func() { - _, err := s.se.Execute(context.Background(), "drop database test_not_exists") - c.Assert(err, IsNil) - }() - s.testParallelExecSQL(c, "create database if not exists test_not_exists;") +func (s *stateChangeSuite) TestCreateDBIfNotExists() { + defer s.tk.MustExec("drop database test_not_exists") + s.testParallelExecSQL("create database if not exists test_not_exists;") } // TestDDLIfNotExists parallel exec some DDLs with `if not exists` clause. No error returns is expected. -func (s *testStateChangeSuite) TestDDLIfNotExists(c *C) { - defer func() { - _, err := s.se.Execute(context.Background(), "drop table test_not_exists") - c.Assert(err, IsNil) - }() - _, err := s.se.Execute(context.Background(), "create table if not exists test_not_exists(a int)") - c.Assert(err, IsNil) +func (s *stateChangeSuite) TestDDLIfNotExists() { + defer s.tk.MustExec("drop table test_not_exists") + s.tk.MustExec("create table if not exists test_not_exists(a int)") // ADD COLUMN - s.testParallelExecSQL(c, "alter table test_not_exists add column if not exists b int") + s.testParallelExecSQL("alter table test_not_exists add column if not exists b int") // ADD COLUMNS - s.testParallelExecSQL(c, "alter table test_not_exists add column if not exists (c11 int, d11 int)") + s.testParallelExecSQL("alter table test_not_exists add column if not exists (c11 int, d11 int)") // ADD INDEX - s.testParallelExecSQL(c, "alter table test_not_exists add index if not exists idx_b (b)") + s.testParallelExecSQL("alter table test_not_exists add index if not exists idx_b (b)") // CREATE INDEX - s.testParallelExecSQL(c, "create index if not exists idx_b on test_not_exists (b)") + s.testParallelExecSQL("create index if not exists idx_b on test_not_exists (b)") } // TestDDLIfExists parallel exec some DDLs with `if exists` clause. No error returns is expected. -func (s *testStateChangeSuite) TestDDLIfExists(c *C) { +func (s *stateChangeSuite) TestDDLIfExists() { defer func() { - _, err := s.se.Execute(context.Background(), "drop table test_exists") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "drop table test_exists_2") - c.Assert(err, IsNil) + s.tk.MustExec("drop table test_exists") + s.tk.MustExec("drop table test_exists_2") }() - _, err := s.se.Execute(context.Background(), "create table if not exists test_exists (a int key, b int)") - c.Assert(err, IsNil) + s.tk.MustExec("create table if not exists test_exists (a int key, b int)") // DROP COLUMNS - s.testParallelExecSQL(c, "alter table test_exists drop column if exists c, drop column if exists d") + s.testParallelExecSQL("alter table test_exists drop column if exists c, drop column if exists d") // DROP COLUMN - s.testParallelExecSQL(c, "alter table test_exists drop column if exists b") // only `a` exists now + s.testParallelExecSQL("alter table test_exists drop column if exists b") // only `a` exists now // CHANGE COLUMN - s.testParallelExecSQL(c, "alter table test_exists change column if exists a c int") // only, `c` exists now + s.testParallelExecSQL("alter table test_exists change column if exists a c int") // only, `c` exists now // MODIFY COLUMN - s.testParallelExecSQL(c, "alter table test_exists modify column if exists a bigint") + s.testParallelExecSQL("alter table test_exists modify column if exists a bigint") // DROP INDEX - _, err = s.se.Execute(context.Background(), "alter table test_exists add index idx_c (c)") - c.Assert(err, IsNil) - s.testParallelExecSQL(c, "alter table test_exists drop index if exists idx_c") + s.tk.MustExec("alter table test_exists add index idx_c (c)") + s.testParallelExecSQL("alter table test_exists drop index if exists idx_c") // DROP PARTITION (ADD PARTITION tested in TestParallelAlterAddPartition) - _, err = s.se.Execute(context.Background(), "create table test_exists_2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20))") - c.Assert(err, IsNil) - s.testParallelExecSQL(c, "alter table test_exists_2 drop partition if exists p1") + s.tk.MustExec("create table test_exists_2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than (30))") + s.testParallelExecSQL("alter table test_exists_2 drop partition if exists p1") } // TestParallelDDLBeforeRunDDLJob tests a session to execute DDL with an outdated information schema. // This test is used to simulate the following conditions: // In a cluster, TiDB "a" executes the DDL. // TiDB "b" fails to load schema, then TiDB "b" executes the DDL statement associated with the DDL statement executed by "a". -func (s *testStateChangeSuite) TestParallelDDLBeforeRunDDLJob(c *C) { - defer func() { - _, err := s.se.Execute(context.Background(), "drop table test_table") - c.Assert(err, IsNil) - }() - _, err := s.se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - _, err = s.se.Execute(context.Background(), "create table test_table (c1 int, c2 int default 1, index (c1))") - c.Assert(err, IsNil) +func (s *stateChangeSuite) TestParallelDDLBeforeRunDDLJob() { + defer s.tk.MustExec("drop table test_table") + s.tk.MustExec("use test_db_state") + s.tk.MustExec("create table test_table (c1 int, c2 int default 1, index (c1))") // Create two sessions. - se, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) - se1, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - _, err = se1.Execute(context.Background(), "use test_db_state") - c.Assert(err, IsNil) + tk1 := testkit.NewTestKit(s.T(), s.store) + tk1.MustExec("use test_db_state") + + tk2 := testkit.NewTestKit(s.T(), s.store) + tk2.MustExec("use test_db_state") intercept := &ddl.TestInterceptor{} firstConnID := uint64(1) @@ -1614,26 +1563,20 @@ func (s *testStateChangeSuite) TestParallelDDLBeforeRunDDLJob(c *C) { // Make sure the connection 1 executes a SQL before the connection 2. // And the connection 2 executes a SQL with an outdated information schema. - wg := sync.WaitGroup{} - wg.Add(2) - go func() { - defer wg.Done() - - se.SetConnectionID(firstConnID) - _, err1 := se.Execute(context.Background(), "alter table test_table drop column c2") - c.Assert(err1, IsNil) + var wg util.WaitGroupWrapper + wg.Run(func() { + tk1.Session().SetConnectionID(firstConnID) + tk1.MustExec("alter table test_table drop column c2") // Sleep a while to make sure the connection 2 break out the first for loop in OnGetInfoSchemaExported, otherwise atomic.LoadInt32(&sessionCnt) == 2 will be false forever. time.Sleep(100 * time.Millisecond) atomic.StoreInt32(&sessionCnt, finishedCnt) - }() - go func() { - defer wg.Done() - - se1.SetConnectionID(2) - _, err2 := se1.Execute(context.Background(), "alter table test_table add column c2 int") - c.Assert(err2, NotNil) - c.Assert(strings.Contains(err2.Error(), "Information schema is changed"), IsTrue) - }() + }) + wg.Run(func() { + tk2.Session().SetConnectionID(2) + err := tk2.ExecToErr("alter table test_table add column c2 int") + s.Require().Error(err) + s.Require().Contains(err.Error(), "Information schema is changed") + }) wg.Wait() @@ -1641,72 +1584,70 @@ func (s *testStateChangeSuite) TestParallelDDLBeforeRunDDLJob(c *C) { d.(ddl.DDLForTest).SetInterceptor(intercept) } -func (s *testStateChangeSuite) TestParallelAlterSchemaCharsetAndCollate(c *C) { +func (s *stateChangeSuite) TestParallelAlterSchemaCharsetAndCollate() { sql := "ALTER SCHEMA test_db_state CHARSET utf8mb4 COLLATE utf8mb4_general_ci" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, IsNil) + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().NoError(err2) } - s.testControlParallelExecSQL(c, sql, sql, f) + s.testControlParallelExecSQL("", sql, sql, f) sql = `SELECT default_character_set_name, default_collation_name FROM information_schema.schemata WHERE schema_name='test_db_state'` - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(s.T(), s.store) tk.MustQuery(sql).Check(testkit.Rows("utf8mb4 utf8mb4_general_ci")) } // TestParallelTruncateTableAndAddColumn tests add column when truncate table. -func (s *testStateChangeSuite) TestParallelTruncateTableAndAddColumn(c *C) { +func (s *stateChangeSuite) TestParallelTruncateTableAndAddColumn() { sql1 := "truncate table t" sql2 := "alter table t add column c3 int" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, NotNil) - c.Assert(err2.Error(), Equals, "[domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } // TestParallelTruncateTableAndAddColumns tests add columns when truncate table. -func (s *testStateChangeSuite) TestParallelTruncateTableAndAddColumns(c *C) { +func (s *stateChangeSuite) TestParallelTruncateTableAndAddColumns() { sql1 := "truncate table t" sql2 := "alter table t add column c3 int, add column c4 int" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, NotNil) - c.Assert(err2.Error(), Equals, "[domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]") } - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } // TestParallelFlashbackTable tests parallel flashback table. -func (s *serialTestStateChangeSuite) TestParallelFlashbackTable(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) +func (s *stateChangeSuite) TestParallelFlashbackTable() { + s.Require().NoError(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func(originGC bool) { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) + s.Require().NoError(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) if originGC { - ddl.EmulatorGCEnable() + ddlutil.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + ddlutil.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(ddlutil.IsEmulatorGCEnable()) // disable emulator GC. // Disable emulator GC, otherwise, emulator GC will delete table record as soon as possible after executing drop table DDL. - ddl.EmulatorGCDisable() + ddlutil.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') ON DUPLICATE KEY UPDATE variable_value = '%[1]s'` - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(s.T(), s.store) // clear GC variables first. tk.MustExec("delete from mysql.tidb where variable_name in ( 'tikv_gc_safe_point','tikv_gc_enable' )") // set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // set GC enable. - err := gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err := gcutil.EnableGC(tk.Session()) + s.Require().NoError(err) // prepare dropped table. tk.MustExec("use test_db_state") @@ -1715,56 +1656,55 @@ func (s *serialTestStateChangeSuite) TestParallelFlashbackTable(c *C) { tk.MustExec("drop table if exists t") // Test parallel flashback table. sql1 := "flashback table t to t_flashback" - f := func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, NotNil) - c.Assert(err2.Error(), Equals, "[schema:1050]Table 't_flashback' already exists") + f := func(err1, err2 error) { + s.Require().NoError(err1) + s.Require().EqualError(err2, "[schema:1050]Table 't_flashback' already exists") } - s.testControlParallelExecSQL(c, sql1, sql1, f) + s.testControlParallelExecSQL("", sql1, sql1, f) // Test parallel flashback table with different name tk.MustExec("drop table t_flashback") sql1 = "flashback table t_flashback" sql2 := "flashback table t_flashback to t_flashback2" - s.testControlParallelExecSQL(c, sql1, sql2, f) + s.testControlParallelExecSQL("", sql1, sql2, f) } // TestModifyColumnTypeArgs test job raw args won't be updated when error occurs in `updateVersionAndTableInfo`. -func (s *serialTestStateChangeSuite) TestModifyColumnTypeArgs(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockUpdateVersionAndTableInfoErr", `return(2)`), IsNil) +func (s *stateChangeSuite) TestModifyColumnTypeArgs() { + s.Require().NoError(failpoint.Enable("github.com/pingcap/tidb/ddl/mockUpdateVersionAndTableInfoErr", `return(2)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockUpdateVersionAndTableInfoErr"), IsNil) + s.Require().NoError(failpoint.Disable("github.com/pingcap/tidb/ddl/mockUpdateVersionAndTableInfoErr")) }() - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test") tk.MustExec("drop table if exists t_modify_column_args") tk.MustExec("create table t_modify_column_args(a int, unique(a))") - _, err := tk.Exec("alter table t_modify_column_args modify column a tinyint") - c.Assert(err, NotNil) + err := tk.ExecToErr("alter table t_modify_column_args modify column a tinyint") + s.Require().Error(err) // error goes like `mock update version and tableInfo error,jobID=xx` strs := strings.Split(err.Error(), ",") - c.Assert(strs[0], Equals, "[ddl:-1]mock update version and tableInfo error") - jobID := strings.Split(strs[1], "=")[1] + s.Require().Equal("[ddl:-1]mock update version and tableInfo error", strs[0]) - tbl := testGetTableByName(c, tk.Se, "test", "t_modify_column_args") - c.Assert(len(tbl.Meta().Columns), Equals, 1) - c.Assert(len(tbl.Meta().Indices), Equals, 1) + jobID := strings.Split(strs[1], "=")[1] + tbl := external.GetTableByName(s.T(), tk, "test", "t_modify_column_args") + s.Require().Len(tbl.Meta().Columns, 1) + s.Require().Len(tbl.Meta().Indices, 1) - ID, err := strconv.Atoi(jobID) - c.Assert(err, IsNil) + id, err := strconv.Atoi(jobID) + s.Require().NoError(err) var historyJob *model.Job err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) - historyJob, err = t.GetHistoryDDLJob(int64(ID)) + historyJob, err = t.GetHistoryDDLJob(int64(id)) if err != nil { return err } return nil }) - c.Assert(err, IsNil) - c.Assert(historyJob, NotNil) + s.Require().NoError(err) + s.Require().NotNil(historyJob) var ( newCol *model.ColumnInfo @@ -1776,13 +1716,13 @@ func (s *serialTestStateChangeSuite) TestModifyColumnTypeArgs(c *C) { ) pos := &ast.ColumnPosition{} err = historyJob.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) - c.Assert(err, IsNil) - c.Assert(changingCol, IsNil) - c.Assert(changingIdxs, IsNil) + s.Require().NoError(err) + s.Require().Nil(changingCol) + s.Require().Nil(changingIdxs) } -func (s *testStateChangeSuite) TestWriteReorgForColumnTypeChange(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestWriteReorgForColumnTypeChange() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") tk.MustExec(`CREATE TABLE t_ctc ( a DOUBLE NULL DEFAULT '1.732088511183121', @@ -1790,29 +1730,25 @@ func (s *testStateChangeSuite) TestWriteReorgForColumnTypeChange(c *C) { KEY idx (a,c) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin COMMENT='…comment'; `) - defer func() { - tk.MustExec("drop table t_ctc") - }() + defer tk.MustExec("drop table t_ctc") sqls := make([]sqlWithErr, 2) sqls[0] = sqlWithErr{"INSERT INTO t_ctc SET c = 'zr36f7ywjquj1curxh9gyrwnx', a = '1.9897043136824033';", nil} sqls[1] = sqlWithErr{"DELETE FROM t_ctc;", nil} dropColumnsSQL := "alter table t_ctc change column a ddd TIME NULL DEFAULT '18:21:32' AFTER c;" query := &expectQuery{sql: "admin check table t_ctc;", rows: nil} - s.runTestInSchemaState(c, model.StateWriteReorganization, false, dropColumnsSQL, sqls, query) + s.runTestInSchemaState(model.StateWriteReorganization, false, dropColumnsSQL, sqls, query) } -func (s *serialTestStateChangeSuite) TestCreateExpressionIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestCreateExpressionIndex() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int default 0, b int default 0)") - defer func() { - tk.MustExec("drop table t") - }() + defer tk.MustExec("drop table t") tk.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (4, 4)") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(s.T(), s.store) tk1.MustExec("use test_db_state") stateDeleteOnlySQLs := []string{"insert into t values (5, 5)", "begin pessimistic;", "insert into t select * from t", "rollback", "insert into t set b = 6", "update t set b = 7 where a = 1", "delete from t where b = 4"} @@ -1824,14 +1760,14 @@ func (s *serialTestStateChangeSuite) TestCreateExpressionIndex(c *C) { var checkErr error d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) + defer d.SetHook(originalCallback) callback := &ddl.TestDDLCallback{} callback.OnJobUpdatedExported = func(job *model.Job) { if checkErr != nil { return } err := originalCallback.OnChanged(nil) - c.Assert(err, IsNil) + s.Require().NoError(err) switch job.SchemaState { case model.StateDeleteOnly: for _, sql := range stateDeleteOnlySQLs { @@ -1865,24 +1801,22 @@ func (s *serialTestStateChangeSuite) TestCreateExpressionIndex(c *C) { } } - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) tk.MustExec("alter table t add index idx((b+1))") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) tk.MustExec("admin check table t") tk.MustQuery("select * from t order by a, b").Check(testkit.Rows("0 9", "0 11", "0 11", "1 7", "2 7", "5 7", "8 8", "10 10", "10 10")) } -func (s *serialTestStateChangeSuite) TestCreateUniqueExpressionIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestCreateUniqueExpressionIndex() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int default 0, b int default 0)") - defer func() { - tk.MustExec("drop table t") - }() + defer tk.MustExec("drop table t") tk.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (4, 4)") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(s.T(), s.store) tk1.MustExec("use test_db_state") stateDeleteOnlySQLs := []string{"insert into t values (5, 5)", "begin pessimistic;", "insert into t select * from t", "rollback", "insert into t set b = 6", "update t set b = 7 where a = 1", "delete from t where b = 4"} @@ -1892,14 +1826,14 @@ func (s *serialTestStateChangeSuite) TestCreateUniqueExpressionIndex(c *C) { var checkErr error d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) + defer d.SetHook(originalCallback) callback := &ddl.TestDDLCallback{} callback.OnJobUpdatedExported = func(job *model.Job) { if checkErr != nil { return } err := originalCallback.OnChanged(nil) - c.Assert(err, IsNil) + s.Require().NoError(err) switch job.SchemaState { case model.StateDeleteOnly: for _, sql := range stateDeleteOnlySQLs { @@ -1979,24 +1913,22 @@ func (s *serialTestStateChangeSuite) TestCreateUniqueExpressionIndex(c *C) { } } - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) tk.MustExec("alter table t add unique index idx((a*b+1))") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) tk.MustExec("admin check table t") tk.MustQuery("select * from t order by a, b").Check(testkit.Rows("0 11", "1 7", "2 7", "5 7", "8 8", "11 10", "13 9")) } -func (s *serialTestStateChangeSuite) TestDropExpressionIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestDropExpressionIndex() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int default 0, b int default 0, key idx((b+1)))") - defer func() { - tk.MustExec("drop table t") - }() + defer tk.MustExec("drop table t") tk.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (4, 4)") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(s.T(), s.store) tk1.MustExec("use test_db_state") stateDeleteOnlySQLs := []string{"insert into t values (5, 5)", "begin pessimistic;", "insert into t select * from t", "rollback", "insert into t set b = 6", "update t set b = 7 where a = 1", "delete from t where b = 4"} stateWriteOnlySQLs := []string{"insert into t values (8, 8)", "begin pessimistic;", "insert into t select * from t", "rollback", "insert into t set b = 9", "update t set b = 7 where a = 2", "delete from t where b = 3"} @@ -2005,14 +1937,14 @@ func (s *serialTestStateChangeSuite) TestDropExpressionIndex(c *C) { var checkErr error d := s.dom.DDL() originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) + defer d.SetHook(originalCallback) callback := &ddl.TestDDLCallback{} callback.OnJobUpdatedExported = func(job *model.Job) { if checkErr != nil { return } err := originalCallback.OnChanged(nil) - c.Assert(err, IsNil) + s.Require().NoError(err) switch job.SchemaState { case model.StateDeleteOnly: for _, sql := range stateDeleteOnlySQLs { @@ -2041,15 +1973,15 @@ func (s *serialTestStateChangeSuite) TestDropExpressionIndex(c *C) { } } - d.(ddl.DDLForTest).SetHook(callback) + d.SetHook(callback) tk.MustExec("alter table t drop index idx") - c.Assert(checkErr, IsNil) + s.Require().NoError(checkErr) tk.MustExec("admin check table t") tk.MustQuery("select * from t order by a, b").Check(testkit.Rows("0 9", "0 11", "1 7", "2 7", "5 7", "8 8", "10 10")) } -func (s *testStateChangeSuite) TestExpressionIndexDDLError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestExpressionIndexDDLError() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test_db_state") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, index idx((a+b)))") @@ -2058,8 +1990,8 @@ func (s *testStateChangeSuite) TestExpressionIndexDDLError(c *C) { tk.MustExec("drop table t") } -func (s *serialTestStateChangeSuite) TestRestrainDropColumnWithIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func (s *stateChangeSuite) TestRestrainDropColumnWithIndex() { + tk := testkit.NewTestKit(s.T(), s.store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int, b int, index(a));") @@ -2070,3 +2002,122 @@ func (s *serialTestStateChangeSuite) TestRestrainDropColumnWithIndex(c *C) { tk.MustExec("alter table t drop column a;") tk.MustExec("drop table if exists t;") } + +func TestParallelRenameTable(t *testing.T) { + store, d, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create database test2") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int default 0, b int default 0, key idx((b+1)))") + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk3 := testkit.NewTestKit(t, store) + tk3.MustExec("use test") + + var concurrentDDLQueryPre string + var concurrentDDLQuery string + firstDDL := true + + var wg sync.WaitGroup + var checkErr error + d2 := d.DDL() + originalCallback := d2.GetHook() + defer d2.SetHook(originalCallback) + callback := &ddl.TestDDLCallback{Do: d} + callback.OnJobRunBeforeExported = func(job *model.Job) { + switch job.SchemaState { + case model.StateNone: + if firstDDL { + firstDDL = false + } else { + return + } + wg.Add(1) + go func() { + if concurrentDDLQueryPre != "" { + wg.Add(1) + go func() { + // We assume that no error, we don't want to test it. + tk3.MustExec(concurrentDDLQueryPre) + wg.Done() + }() + time.Sleep(10 * time.Millisecond) + } + _, err := tk1.Exec(concurrentDDLQuery) + if err != nil { + checkErr = err + } + wg.Done() + }() + time.Sleep(10 * time.Millisecond) + } + } + + d2.SetHook(callback) + + // rename then add column + concurrentDDLQuery = "alter table t add column g int" + tk.MustExec("rename table t to t1") + wg.Wait() + require.Error(t, checkErr) + require.True(t, strings.Contains(checkErr.Error(), "Table 'test.t' doesn't exist"), checkErr.Error()) + tk.MustExec("rename table t1 to t") + checkErr = nil + + // rename then add column, but rename to other database + concurrentDDLQuery = "alter table t add column g int" + firstDDL = true + tk.MustExec("rename table t to test2.t1") + wg.Wait() + require.Error(t, checkErr) + // [schema:1146]Table '(Schema ID 1).(Table ID 65)' doesn't exist + require.True(t, strings.Contains(checkErr.Error(), "doesn't exist"), checkErr.Error()) + tk.MustExec("rename table test2.t1 to test.t") + checkErr = nil + + // rename then add column, but rename to other database and create same name table + concurrentDDLQuery = "alter table t add column g int" + firstDDL = true + tk.MustExec("rename table t to test2.t1") + concurrentDDLQueryPre = "create table t(a int)" + wg.Wait() + require.Error(t, checkErr) + // [schema:1146]Table '(Schema ID 1).(Table ID 65)' doesn't exist + require.True(t, strings.Contains(checkErr.Error(), "doesn't exist"), checkErr.Error()) + tk.MustExec("rename table test2.t1 to test.t") + concurrentDDLQueryPre = "" + checkErr = nil + + // rename then rename + concurrentDDLQuery = "rename table t to t2" + firstDDL = true + tk.MustExec("rename table t to t1") + wg.Wait() + require.Error(t, checkErr) + require.True(t, strings.Contains(checkErr.Error(), "Table 'test.t' doesn't exist"), checkErr.Error()) + tk.MustExec("rename table t1 to t") + checkErr = nil + + // rename then rename, but rename to other database + concurrentDDLQuery = "rename table t to t2" + firstDDL = true + tk.MustExec("rename table t to test2.t1") + wg.Wait() + require.Error(t, checkErr) + require.True(t, strings.Contains(checkErr.Error(), "doesn't exist"), checkErr.Error()) + tk.MustExec("rename table test2.t1 to test.t") + checkErr = nil + + // renames then add index on one table + tk.MustExec("create table t2(a int)") + tk.MustExec("create table t3(a int)") + concurrentDDLQuery = "alter table t add index(a)" + firstDDL = true + tk.MustExec("rename table t to tt, t2 to tt2, t3 to tt3") + wg.Wait() + require.Error(t, checkErr) + require.True(t, strings.Contains(checkErr.Error(), "Table 'test.t' doesn't exist"), checkErr.Error()) + tk.MustExec("rename table tt to t") +} diff --git a/ddl/db_foreign_key_test.go b/ddl/db_foreign_key_test.go new file mode 100644 index 0000000000000..6ac5de33e5f52 --- /dev/null +++ b/ddl/db_foreign_key_test.go @@ -0,0 +1,69 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "testing" + + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/testkit" +) + +func TestDuplicateForeignKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("drop table if exists t1") + // Foreign table. + tk.MustExec("create table t(id int key)") + // Create target table with duplicate fk. + tk.MustGetErrCode("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`), CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))", mysql.ErrFkDupName) + tk.MustGetErrCode("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`), CONSTRAINT `fk_aaA` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))", mysql.ErrFkDupName) + + tk.MustExec("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))") + // Alter target table with duplicate fk. + tk.MustGetErrCode("alter table t1 add CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`)", mysql.ErrFkDupName) + tk.MustGetErrCode("alter table t1 add CONSTRAINT `fk_aAa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`)", mysql.ErrFkDupName) + tk.MustExec("drop table if exists t") + tk.MustExec("drop table if exists t1") +} + +func TestTemporaryTableForeignKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1 (a int, b int);") + tk.MustExec("drop table if exists t1_tmp;") + tk.MustExec("create global temporary table t1_tmp (a int, b int) on commit delete rows;") + tk.MustExec("create temporary table t2_tmp (a int, b int)") + // test add foreign key. + tk.MustExec("drop table if exists t2;") + tk.MustExec("create table t2 (a int, b int);") + failSQL := "alter table t1_tmp add foreign key (c) REFERENCES t2(a);" + tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) + failSQL = "alter table t2_tmp add foreign key (c) REFERENCES t2(a);" + tk.MustGetErrCode(failSQL, errno.ErrUnsupportedDDLOperation) + // Test drop column with foreign key. + failSQL = "create global temporary table t3 (c int,d int,foreign key (d) references t1 (b)) on commit delete rows;" + tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) + failSQL = "create temporary table t4(c int,d int,foreign key (d) references t1 (b));" + tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) + tk.MustExec("drop table if exists t1,t2,t3, t4,t1_tmp,t2_tmp;") +} diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 3e28686ad2302..42d3edbdfd265 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -22,18 +22,16 @@ import ( "strconv" "strings" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" @@ -41,98 +39,22 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/israce" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" - "github.com/tikv/client-go/v2/testutils" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testIntegrationSuite1{&testIntegrationSuite{}}) -var _ = Suite(&testIntegrationSuite2{&testIntegrationSuite{}}) -var _ = Suite(&testIntegrationSuite3{&testIntegrationSuite{}}) -var _ = Suite(&testIntegrationSuite4{&testIntegrationSuite{}}) -var _ = Suite(&testIntegrationSuite5{&testIntegrationSuite{}}) -var _ = Suite(&testIntegrationSuite6{&testIntegrationSuite{}}) - -type testIntegrationSuite struct { - lease time.Duration - cluster testutils.Cluster - store kv.Storage - dom *domain.Domain - ctx sessionctx.Context -} - -func setupIntegrationSuite(s *testIntegrationSuite, c *C) { - var err error - s.lease = 50 * time.Millisecond - ddl.SetWaitTimeWhenErrorOccurred(0) - - s.store, err = mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - session.SetSchemaLease(s.lease) - session.DisableStats4Test() - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - s.ctx = se.(sessionctx.Context) - _, err = se.Execute(context.Background(), "create database test_db") - c.Assert(err, IsNil) -} - -func tearDownIntegrationSuiteTest(s *testIntegrationSuite, c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } -} - -func tearDownIntegrationSuite(s *testIntegrationSuite, c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *testIntegrationSuite) SetUpSuite(c *C) { - setupIntegrationSuite(s, c) -} - -func (s *testIntegrationSuite) TearDownSuite(c *C) { - tearDownIntegrationSuite(s, c) -} - -type testIntegrationSuite1 struct{ *testIntegrationSuite } -type testIntegrationSuite2 struct{ *testIntegrationSuite } - -func (s *testIntegrationSuite2) TearDownTest(c *C) { - tearDownIntegrationSuiteTest(s.testIntegrationSuite, c) -} - -type testIntegrationSuite3 struct{ *testIntegrationSuite } -type testIntegrationSuite4 struct{ *testIntegrationSuite } -type testIntegrationSuite5 struct{ *testIntegrationSuite } -type testIntegrationSuite6 struct{ *testIntegrationSuite } -type testIntegrationSuite7 struct{ *testIntegrationSuite } - -func (s *testIntegrationSuite5) TestNoZeroDateMode(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNoZeroDateMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) defer tk.MustExec("set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';") @@ -143,55 +65,97 @@ func (s *testIntegrationSuite5) TestNoZeroDateMode(c *C) { tk.MustGetErrCode("create table test_zero_date(agent_start_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00')", errno.ErrInvalidDefault) tk.MustGetErrCode("create table test_zero_date(a timestamp default '0000-00-00 00');", errno.ErrInvalidDefault) tk.MustGetErrCode("create table test_zero_date(a timestamp default 0);", errno.ErrInvalidDefault) -} - -func (s *testIntegrationSuite2) TestInvalidDefault(c *C) { - tk := testkit.NewTestKit(c, s.store) + defer tk.MustExec(`drop table if exists test_zero_date`) + tk.MustExec("set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';") + tk.MustExec("create table test_zero_date (a timestamp default 0)") + tk.MustExec(`insert into test_zero_date values (0)`) + tk.MustQuery(`select a, unix_timestamp(a) from test_zero_date`).Check(testkit.Rows("0000-00-00 00:00:00 0")) + tk.MustExec(`update test_zero_date set a = '2001-01-01 11:11:11' where a = 0`) + tk.MustExec(`replace into test_zero_date values (0)`) + tk.MustExec(`delete from test_zero_date where a = 0`) + tk.MustExec(`update test_zero_date set a = 0 where a = '2001-01-01 11:11:11'`) + tk.MustExec("set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';") + tk.MustGetErrCode(`insert into test_zero_date values (0)`, errno.ErrTruncatedWrongValue) + tk.MustGetErrCode(`replace into test_zero_date values (0)`, errno.ErrTruncatedWrongValue) + tk.MustGetErrCode(`update test_zero_date set a = 0 where a = 0`, errno.ErrTruncatedWrongValue) + tk.MustExec(`delete from test_zero_date where a = 0`) + tk.MustQuery(`select a, unix_timestamp(a) from test_zero_date`).Check(testkit.Rows()) + tk.MustExec(`drop table test_zero_date`) + tk.MustExec("set session sql_mode=''") + tk.MustExec("create table test_zero_date (a timestamp default 0)") + tk.MustExec(`drop table test_zero_date`) + tk.MustExec(`create table test_zero_date (a int)`) + tk.MustExec(`insert into test_zero_date values (0)`) + tk.MustExec(`alter table test_zero_date modify a date`) + tk.MustExec("set session sql_mode='NO_ZERO_DATE'") + tk.MustExec(`drop table test_zero_date`) + tk.MustExec("create table test_zero_date (a timestamp default 0)") + tk.MustExec(`drop table test_zero_date`) + tk.MustExec(`create table test_zero_date (a int)`) + tk.MustExec(`insert into test_zero_date values (0)`) + tk.MustExec(`alter table test_zero_date modify a date`) + tk.MustExec("set session sql_mode='STRICT_TRANS_TABLES'") + tk.MustExec(`drop table test_zero_date`) + tk.MustExec("create table test_zero_date (a timestamp default 0)") + tk.MustExec(`drop table test_zero_date`) + tk.MustExec(`create table test_zero_date (a int)`) + tk.MustExec(`insert into test_zero_date values (0)`) + tk.MustGetErrCode(`alter table test_zero_date modify a date`, errno.ErrTruncatedWrongValue) + tk.MustExec("set session sql_mode='NO_ZERO_DATE,STRICT_TRANS_TABLES'") + tk.MustExec(`drop table test_zero_date`) + tk.MustGetErrCode("create table test_zero_date (a timestamp default 0)", errno.ErrInvalidDefault) + tk.MustExec(`create table test_zero_date (a int)`) + tk.MustExec(`insert into test_zero_date values (0)`) + tk.MustGetErrCode(`alter table test_zero_date modify a date`, errno.ErrTruncatedWrongValue) +} + +func TestInvalidDefault(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") _, err := tk.Exec("create table t(c1 decimal default 1.7976931348623157E308)") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, types.ErrInvalidDefault), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, types.ErrInvalidDefault), "err %v", err) _, err = tk.Exec("create table t( c1 varchar(2) default 'TiDB');") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, types.ErrInvalidDefault), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, types.ErrInvalidDefault), "err %v", err) } // TestKeyWithoutLength for issue #13452 -func (s testIntegrationSuite3) TestKeyWithoutLengthCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestKeyWithoutLengthCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test") _, err := tk.Exec("create table t_without_length (a text primary key)") - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, ".*BLOB/TEXT column 'a' used in key specification without a key length") + require.Error(t, err) + require.Regexp(t, ".*BLOB/TEXT column 'a' used in key specification without a key length", err.Error()) } // TestInvalidNameWhenCreateTable for issue #3848 -func (s *testIntegrationSuite3) TestInvalidNameWhenCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInvalidNameWhenCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") - _, err := tk.Exec("create table t(xxx.t.a bigint)") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, ddl.ErrWrongDBName), IsTrue, Commentf("err %v", err)) - - _, err = tk.Exec("create table t(test.tttt.a bigint)") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, ddl.ErrWrongTableName), IsTrue, Commentf("err %v", err)) - - _, err = tk.Exec("create table t(t.tttt.a bigint)") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, ddl.ErrWrongDBName), IsTrue, Commentf("err %v", err)) + tk.MustGetErrCode("create table t(xxx.t.a bigint)", errno.ErrWrongDBName) + tk.MustGetErrCode("create table t(test.tttt.a bigint)", errno.ErrWrongTableName) + tk.MustGetErrCode("create table t(t.tttt.a bigint)", errno.ErrWrongDBName) } // TestCreateTableIfNotExists for issue #6879 -func (s *testIntegrationSuite3) TestCreateTableIfNotExists(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableIfNotExists(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") @@ -200,32 +164,36 @@ func (s *testIntegrationSuite3) TestCreateTableIfNotExists(c *C) { // Test duplicate create-table with `LIKE` clause tk.MustExec("create table if not exists ct like ct1;") - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), GreaterEqual, 1) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.GreaterOrEqual(t, len(warnings), 1) lastWarn := warnings[len(warnings)-1] - c.Assert(terror.ErrorEqual(infoschema.ErrTableExists, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err)) - c.Assert(lastWarn.Level, Equals, stmtctx.WarnLevelNote) + require.Truef(t, terror.ErrorEqual(infoschema.ErrTableExists, lastWarn.Err), "err %v", lastWarn.Err) + require.Equal(t, stmtctx.WarnLevelNote, lastWarn.Level) // Test duplicate create-table without `LIKE` clause tk.MustExec("create table if not exists ct(b bigint, c varchar(60));") - warnings = tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), GreaterEqual, 1) + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.GreaterOrEqual(t, len(warnings), 1) lastWarn = warnings[len(warnings)-1] - c.Assert(terror.ErrorEqual(infoschema.ErrTableExists, lastWarn.Err), IsTrue) + require.True(t, terror.ErrorEqual(infoschema.ErrTableExists, lastWarn.Err)) } // for issue #9910 -func (s *testIntegrationSuite2) TestCreateTableWithKeyWord(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithKeyWord(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") _, err := tk.Exec("create table t1(pump varchar(20), drainer varchar(20), node_id varchar(20), node_state varchar(20));") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testIntegrationSuite6) TestUniqueKeyNullValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUniqueKeyNullValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(255))") @@ -239,8 +207,10 @@ func (s *testIntegrationSuite6) TestUniqueKeyNullValue(c *C) { tk.MustExec("admin check index t b") } -func (s *testIntegrationSuite2) TestUniqueKeyNullValueClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUniqueKeyNullValueClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists unique_null_val;") tk.MustExec("create database unique_null_val;") @@ -255,16 +225,20 @@ func (s *testIntegrationSuite2) TestUniqueKeyNullValueClusterIndex(c *C) { } // TestModifyColumnAfterAddIndex Issue 5134 -func (s *testIntegrationSuite3) TestModifyColumnAfterAddIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestModifyColumnAfterAddIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table city (city VARCHAR(2) KEY);") tk.MustExec("alter table city change column city city varchar(50);") tk.MustExec(`insert into city values ("abc"), ("abd");`) } -func (s *testIntegrationSuite3) TestIssue2293(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue2293(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_issue_2293 (a int)") tk.MustGetErrCode("alter table t_issue_2293 add b int not null default 'a'", errno.ErrInvalidDefault) @@ -272,13 +246,15 @@ func (s *testIntegrationSuite3) TestIssue2293(c *C) { tk.MustQuery("select * from t_issue_2293").Check(testkit.Rows("1")) } -func (s *testIntegrationSuite2) TestIssue6101(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue6101(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t1 (quantity decimal(2) unsigned);") _, err := tk.Exec("insert into t1 values (500), (-500), (~0), (-1);") terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.ErrWarnDataOutOfRange)) + require.Equal(t, errors.ErrCode(errno.ErrWarnDataOutOfRange), terr.Code()) tk.MustExec("drop table t1") tk.MustExec("set sql_mode=''") @@ -288,30 +264,34 @@ func (s *testIntegrationSuite2) TestIssue6101(c *C) { tk.MustExec("drop table t1") } -func (s *testIntegrationSuite2) TestIssue19229(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue19229(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("CREATE TABLE enumt (type enum('a', 'b') );") _, err := tk.Exec("insert into enumt values('xxx');") terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.WarnDataTruncated)) + require.Equal(t, errors.ErrCode(errno.WarnDataTruncated), terr.Code()) _, err = tk.Exec("insert into enumt values(-1);") terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.WarnDataTruncated)) + require.Equal(t, errors.ErrCode(errno.WarnDataTruncated), terr.Code()) tk.MustExec("drop table enumt") tk.MustExec("CREATE TABLE sett (type set('a', 'b') );") _, err = tk.Exec("insert into sett values('xxx');") terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.WarnDataTruncated)) + require.Equal(t, errors.ErrCode(errno.WarnDataTruncated), terr.Code()) _, err = tk.Exec("insert into sett values(-1);") terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.WarnDataTruncated)) + require.Equal(t, errors.ErrCode(errno.WarnDataTruncated), terr.Code()) tk.MustExec("drop table sett") } -func (s *testIntegrationSuite7) TestIndexLength(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexLength(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table idx_len(a int(0), b timestamp(0), c datetime(0), d time(0), f float(0), g decimal(0))") tk.MustExec("create index idx on idx_len(a)") @@ -338,8 +318,10 @@ func (s *testIntegrationSuite7) TestIndexLength(c *C) { tk.MustExec("drop table idx_len;") } -func (s *testIntegrationSuite3) TestIssue3833(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue3833(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table issue3833 (b char(0), c binary(0), d varchar(0))") tk.MustGetErrCode("create index idx on issue3833 (b)", errno.ErrWrongKeyColumn) @@ -353,8 +335,10 @@ func (s *testIntegrationSuite3) TestIssue3833(c *C) { tk.MustGetErrCode("create table issue3833_2 (b char(0), c binary(0), d varchar(0), index(d))", errno.ErrWrongKeyColumn) } -func (s *testIntegrationSuite1) TestIssue2858And2717(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue2858And2717(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_issue_2858_bit (a bit(64) default b'0')") @@ -370,8 +354,10 @@ func (s *testIntegrationSuite1) TestIssue2858And2717(c *C) { tk.MustExec(`alter table t_issue_2858_hex alter column a set default 0x321`) } -func (s *testIntegrationSuite1) TestIssue4432(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue4432(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table tx (col bit(10) default 'a')") @@ -395,8 +381,10 @@ func (s *testIntegrationSuite1) TestIssue4432(c *C) { tk.MustExec("drop table tx") } -func (s *testIntegrationSuite7) TestIssue5092(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue5092(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_issue_5092 (a int)") @@ -418,7 +406,7 @@ func (s *testIntegrationSuite7) TestIssue5092(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // The following two statements are consistent with MariaDB. tk.MustGetErrCode("alter table t_issue_5092 add column if not exists d int, add column d int", errno.ErrDupFieldName) - tk.MustExec("alter table t_issue_5092 add column dd int, add column if not exists dd int") + tk.MustGetErrCode("alter table t_issue_5092 add column dd int, add column if not exists dd int", errno.ErrUnsupportedDDLOperation) tk.MustExec("alter table t_issue_5092 add column if not exists (d int, e int), add column ff text") tk.MustExec("alter table t_issue_5092 add column b2 int after b1, add column c2 int first") tk.MustQuery("show create table t_issue_5092").Check(testkit.Rows("t_issue_5092 CREATE TABLE `t_issue_5092` (\n" + @@ -434,7 +422,6 @@ func (s *testIntegrationSuite7) TestIssue5092(c *C) { " `c1` int(11) DEFAULT NULL,\n" + " `f` int(11) DEFAULT NULL,\n" + " `g` int(11) DEFAULT NULL,\n" + - " `dd` int(11) DEFAULT NULL,\n" + " `ff` text DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) tk.MustExec("drop table t_issue_5092") @@ -468,14 +455,16 @@ func (s *testIntegrationSuite7) TestIssue5092(c *C) { tk.MustExec("create table t_issue_5092 (a int)") tk.MustExec("alter table t_issue_5092 add column (b int, c int)") tk.MustGetErrCode("alter table t_issue_5092 drop column if exists a, drop column b, drop column c", errno.ErrCantRemoveAllFields) - tk.MustGetErrCode("alter table t_issue_5092 drop column if exists c, drop column c", errno.ErrCantDropFieldOrKey) - tk.MustExec("alter table t_issue_5092 drop column c, drop column if exists c") + tk.MustGetErrCode("alter table t_issue_5092 drop column if exists c, drop column c", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t_issue_5092 drop column c, drop column if exists c", errno.ErrUnsupportedDDLOperation) tk.MustExec("drop table t_issue_5092") } -func (s *testIntegrationSuite5) TestErrnoErrorCode(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestErrnoErrorCode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") // create database sql := "create database aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" @@ -609,9 +598,9 @@ func (s *testIntegrationSuite5) TestErrnoErrorCode(c *C) { sql = "alter table test_drop_columns drop column c1, drop column c2, drop column c3;" tk.MustGetErrCode(sql, errno.ErrCantRemoveAllFields) sql = "alter table test_drop_columns drop column c1, add column c2 int;" - tk.MustGetErrCode(sql, errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode(sql, errno.ErrDupFieldName) sql = "alter table test_drop_columns drop column c1, drop column c1;" - tk.MustGetErrCode(sql, errno.ErrCantDropFieldOrKey) + tk.MustGetErrCode(sql, errno.ErrUnsupportedDDLOperation) // add index sql = "alter table test_error_code_succ add index idx (c_not_exist)" tk.MustGetErrCode(sql, errno.ErrKeyColumnDoesNotExits) @@ -645,8 +634,10 @@ func (s *testIntegrationSuite5) TestErrnoErrorCode(c *C) { tk.MustExec("set global tidb_enable_change_multi_schema = true") } -func (s *testIntegrationSuite3) TestTableDDLWithFloatType(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableDDLWithFloatType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustGetErrCode("create table t (a decimal(1, 2))", errno.ErrMBiggerThanD) @@ -660,18 +651,17 @@ func (s *testIntegrationSuite3) TestTableDDLWithFloatType(c *C) { tk.MustExec("drop table t") } -func (s *testIntegrationSuite1) TestTableDDLWithTimeType(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestTableDDLWithTimeType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustGetErrCode("create table t (a time(7))", errno.ErrTooBigPrecision) tk.MustGetErrCode("create table t (a datetime(7))", errno.ErrTooBigPrecision) tk.MustGetErrCode("create table t (a timestamp(7))", errno.ErrTooBigPrecision) _, err := tk.Exec("create table t (a time(-1))") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("create table t (a datetime)") tk.MustGetErrCode("alter table t add column b time(7)", errno.ErrTooBigPrecision) tk.MustGetErrCode("alter table t add column b datetime(7)", errno.ErrTooBigPrecision) @@ -686,21 +676,23 @@ func (s *testIntegrationSuite1) TestTableDDLWithTimeType(c *C) { tk.MustExec("drop table t") } -func (s *testIntegrationSuite2) TestUpdateMultipleTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateMultipleTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database umt_db") tk.MustExec("use umt_db") tk.MustExec("create table t1 (c1 int, c2 int)") tk.MustExec("insert t1 values (1, 1), (2, 2)") tk.MustExec("create table t2 (c1 int, c2 int)") tk.MustExec("insert t2 values (1, 3), (2, 5)") - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() dom := domain.GetDomain(ctx) is := dom.InfoSchema() db, ok := is.SchemaByName(model.NewCIStr("umt_db")) - c.Assert(ok, IsTrue) + require.True(t, ok) t1Tbl, err := is.TableByName(model.NewCIStr("umt_db"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) t1Info := t1Tbl.Meta() // Add a new column in write only state. @@ -715,16 +707,16 @@ func (s *testIntegrationSuite2) TestUpdateMultipleTable(c *C) { } t1Info.Columns = append(t1Info.Columns, newColumn) - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) _, err = m.GenSchemaVersion() - c.Assert(err, IsNil) - c.Assert(m.UpdateTable(db.ID, t1Info), IsNil) + require.NoError(t, err) + require.Nil(t, m.UpdateTable(db.ID, t1Info)) return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) err = dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("update t1, t2 set t1.c1 = 8, t2.c2 = 10 where t1.c2 = t2.c1") tk.MustQuery("select * from t1").Check(testkit.Rows("8 1", "8 2")) @@ -732,23 +724,25 @@ func (s *testIntegrationSuite2) TestUpdateMultipleTable(c *C) { newColumn.State = model.StatePublic - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) _, err = m.GenSchemaVersion() - c.Assert(err, IsNil) - c.Assert(m.UpdateTable(db.ID, t1Info), IsNil) + require.NoError(t, err) + require.Nil(t, m.UpdateTable(db.ID, t1Info)) return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) err = dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery("select * from t1").Check(testkit.Rows("8 1 9", "8 2 9")) tk.MustExec("drop database umt_db") } -func (s *testIntegrationSuite2) TestNullGeneratedColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNullGeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -765,8 +759,10 @@ func (s *testIntegrationSuite2) TestNullGeneratedColumn(c *C) { tk.MustExec("drop table t") } -func (s *testIntegrationSuite2) TestDependedGeneratedColumnPrior2GeneratedColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDependedGeneratedColumnPrior2GeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` (" + @@ -789,39 +785,15 @@ func (s *testIntegrationSuite2) TestDependedGeneratedColumnPrior2GeneratedColumn tk.MustExec("alter table t add column(e int as (c+1))") } -func (s *testIntegrationSuite3) TestChangingCharsetToUtf8(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("create table t1(a varchar(20) charset utf8)") - tk.MustExec("insert into t1 values (?)", "t1_value") - tk.MustExec("alter table t1 collate uTf8mB4_uNiCoDe_Ci charset Utf8mB4 charset uTF8Mb4 collate UTF8MB4_BiN") - tk.MustExec("alter table t1 modify column a varchar(20) charset utf8mb4") - tk.MustQuery("select * from t1;").Check(testkit.Rows("t1_value")) - - tk.MustExec("create table t(a varchar(20) charset latin1)") - tk.MustExec("insert into t values (?)", "t_value") - - tk.MustExec("alter table t modify column a varchar(20) charset latin1") - tk.MustQuery("select * from t;").Check(testkit.Rows("t_value")) - - tk.MustGetErrCode("alter table t modify column a varchar(20) charset utf8", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify column a varchar(20) charset utf8mb4", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify column a varchar(20) charset utf8 collate utf8_bin", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify column a varchar(20) charset utf8mb4 collate utf8mb4_general_ci", errno.ErrUnsupportedDDLOperation) - - tk.MustGetErrCode("alter table t modify column a varchar(20) charset utf8mb4 collate utf8bin", errno.ErrUnknownCollation) - tk.MustGetErrCode("alter table t collate LATIN1_GENERAL_CI charset utf8 collate utf8_bin", errno.ErrConflictingDeclarations) - tk.MustGetErrCode("alter table t collate LATIN1_GENERAL_CI collate UTF8MB4_UNICODE_ci collate utf8_bin", errno.ErrCollationCharsetMismatch) -} - -func (s *testIntegrationSuite4) TestChangingTableCharset(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangingTableCharset(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test") tk.MustExec("create table t(a char(10)) charset latin1 collate latin1_bin") - tk.MustGetErrCode("alter table t charset gbk", errno.ErrUnknownCharacterSet) + tk.MustGetErrCode("alter table t charset gbk", errno.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table t charset ''", errno.ErrUnknownCharacterSet) tk.MustGetErrCode("alter table t charset utf8mb4 collate '' collate utf8mb4_bin;", errno.ErrUnknownCollation) @@ -841,13 +813,13 @@ func (s *testIntegrationSuite4) TestChangingTableCharset(c *C) { tk.MustExec("create table t(a varchar(10)) charset utf8") tk.MustExec("alter table t convert to charset utf8mb4;") checkCharset := func(chs, coll string) { - tbl := testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().Charset, Equals, chs) - c.Assert(tbl.Meta().Collate, Equals, coll) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, chs, tbl.Meta().Charset) + require.Equal(t, coll, tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { - c.Assert(col.Charset, Equals, chs) - c.Assert(col.Collate, Equals, coll) + require.Equal(t, chs, col.Charset) + require.Equal(t, coll, col.Collate) } } checkCharset(charset.CharsetUTF8MB4, charset.CollationUTF8MB4) @@ -869,57 +841,57 @@ func (s *testIntegrationSuite4) TestChangingTableCharset(c *C) { checkCharset(charset.CharsetUTF8MB4, "utf8mb4_general_ci") // Mock table info with charset is "". Old TiDB maybe create table with charset is "". - db, ok := domain.GetDomain(s.ctx).InfoSchema().SchemaByName(model.NewCIStr("test")) - c.Assert(ok, IsTrue) - tbl := testGetTableByName(c, s.ctx, "test", "t") + db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("test")) + require.True(t, ok) + tbl := external.GetTableByName(t, tk, "test", "t") tblInfo := tbl.Meta().Clone() tblInfo.Charset = "" tblInfo.Collate = "" updateTableInfo := func(tblInfo *model.TableInfo) { mockCtx := mock.NewContext() - mockCtx.Store = s.store + mockCtx.Store = store err := mockCtx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) txn, err := mockCtx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) mt := meta.NewMeta(txn) err = mt.UpdateTable(db.ID, tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) } updateTableInfo(tblInfo) // check table charset is "" tk.MustExec("alter table t add column b varchar(10);") // load latest schema. - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().Charset, Equals, "") - c.Assert(tbl.Meta().Collate, Equals, "") + tbl = external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, "", tbl.Meta().Charset) + require.Equal(t, "", tbl.Meta().Collate) // Test when table charset is "", this for compatibility. tk.MustExec("alter table t convert to charset utf8mb4;") checkCharset(charset.CharsetUTF8MB4, charset.CollationUTF8MB4) // Test when column charset is "". - tbl = testGetTableByName(c, s.ctx, "test", "t") + tbl = external.GetTableByName(t, tk, "test", "t") tblInfo = tbl.Meta().Clone() tblInfo.Columns[0].Charset = "" tblInfo.Columns[0].Collate = "" updateTableInfo(tblInfo) // check table charset is "" tk.MustExec("alter table t drop column b;") // load latest schema. - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().Columns[0].Charset, Equals, "") - c.Assert(tbl.Meta().Columns[0].Collate, Equals, "") + tbl = external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, "", tbl.Meta().Columns[0].Charset) + require.Equal(t, "", tbl.Meta().Columns[0].Collate) tk.MustExec("alter table t convert to charset utf8mb4;") checkCharset(charset.CharsetUTF8MB4, charset.CollationUTF8MB4) tk.MustExec("drop table t") tk.MustExec("create table t (a blob) character set utf8;") tk.MustExec("alter table t charset=utf8mb4 collate=utf8mb4_bin;") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` blob DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", @@ -928,40 +900,42 @@ func (s *testIntegrationSuite4) TestChangingTableCharset(c *C) { tk.MustExec("drop table t") tk.MustExec("create table t(a varchar(5) charset utf8) charset utf8") tk.MustExec("alter table t charset utf8mb4") - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().Charset, Equals, "utf8mb4") - c.Assert(tbl.Meta().Collate, Equals, "utf8mb4_bin") + tbl = external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, "utf8mb4", tbl.Meta().Charset) + require.Equal(t, "utf8mb4_bin", tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { // Column charset and collate should remain unchanged. - c.Assert(col.Charset, Equals, "utf8") - c.Assert(col.Collate, Equals, "utf8_bin") + require.Equal(t, "utf8", col.Charset) + require.Equal(t, "utf8_bin", col.Collate) } tk.MustExec("drop table t") tk.MustExec("create table t(a varchar(5) charset utf8 collate utf8_unicode_ci) charset utf8 collate utf8_unicode_ci") - tk.MustExec("alter table t collate utf8_danish_ci") - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().Charset, Equals, "utf8") - c.Assert(tbl.Meta().Collate, Equals, "utf8_danish_ci") + tk.MustExec("alter table t collate utf8_general_ci") + tbl = external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.Equal(t, "utf8", tbl.Meta().Charset) + require.Equal(t, "utf8_general_ci", tbl.Meta().Collate) for _, col := range tbl.Meta().Columns { - c.Assert(col.Charset, Equals, "utf8") + require.Equal(t, "utf8", col.Charset) // Column collate should remain unchanged. - c.Assert(col.Collate, Equals, "utf8_unicode_ci") + require.Equal(t, "utf8_unicode_ci", col.Collate) } } -func (s *testIntegrationSuite5) TestModifyColumnOption(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestModifyColumnOption(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") errMsg := "[ddl:8200]" // unsupported modify column with references assertErrCode := func(sql string, errCodeStr string) { _, err := tk.Exec(sql) - c.Assert(err, NotNil) - c.Assert(err.Error()[:len(errCodeStr)], Equals, errCodeStr) + require.Error(t, err) + require.Equal(t, errCodeStr, err.Error()[:len(errCodeStr)]) } tk.MustExec("drop table if exists t1") @@ -978,19 +952,21 @@ func (s *testIntegrationSuite5) TestModifyColumnOption(c *C) { tk.MustExec("create table t2 (b char, c int)") assertErrCode("alter table t2 modify column c int references t1(a)", errMsg) _, err := tk.Exec("alter table t1 change a a varchar(16)") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("alter table t1 change a a varchar(10)") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("alter table t1 change a a datetime") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("alter table t1 change a a int(11) unsigned") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("alter table t2 change b b int(11) unsigned") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1004,8 +980,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn1(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn1(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1019,8 +997,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn1(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1034,8 +1014,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn2(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn3(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn3(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1049,8 +1031,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn3(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn4(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn4(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1064,8 +1048,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn4(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn5(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexOnMultipleGeneratedColumn5(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -1082,8 +1068,10 @@ func (s *testIntegrationSuite4) TestIndexOnMultipleGeneratedColumn5(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite6) TestCaseInsensitiveCharsetAndCollate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCaseInsensitiveCharsetAndCollate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_charset_collate") defer tk.MustExec("drop database test_charset_collate") @@ -1097,36 +1085,36 @@ func (s *testIntegrationSuite6) TestCaseInsensitiveCharsetAndCollate(c *C) { tk.MustExec("create table t5(a varchar(20)) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4 COLLATE=UTF8MB4_GENERAL_CI;") tk.MustExec("insert into t5 values ('特克斯和凯科斯群岛')") - db, ok := domain.GetDomain(s.ctx).InfoSchema().SchemaByName(model.NewCIStr("test_charset_collate")) - c.Assert(ok, IsTrue) - tbl := testGetTableByName(c, s.ctx, "test_charset_collate", "t5") + db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("test_charset_collate")) + require.True(t, ok) + tbl := external.GetTableByName(t, tk, "test_charset_collate", "t5") tblInfo := tbl.Meta().Clone() - c.Assert(tblInfo.Charset, Equals, "utf8mb4") - c.Assert(tblInfo.Columns[0].Charset, Equals, "utf8mb4") + require.Equal(t, "utf8mb4", tblInfo.Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) tblInfo.Version = model.TableInfoVersion2 tblInfo.Charset = "UTF8MB4" updateTableInfo := func(tblInfo *model.TableInfo) { mockCtx := mock.NewContext() - mockCtx.Store = s.store + mockCtx.Store = store err := mockCtx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) txn, err := mockCtx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) mt := meta.NewMeta(txn) - c.Assert(ok, IsTrue) + require.True(t, ok) err = mt.UpdateTable(db.ID, tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) } updateTableInfo(tblInfo) tk.MustExec("alter table t5 add column b varchar(10);") // load latest schema. - tblInfo = testGetTableByName(c, s.ctx, "test_charset_collate", "t5").Meta() - c.Assert(tblInfo.Charset, Equals, "utf8mb4") - c.Assert(tblInfo.Columns[0].Charset, Equals, "utf8mb4") + tblInfo = external.GetTableByName(t, tk, "test_charset_collate", "t5").Meta() + require.Equal(t, "utf8mb4", tblInfo.Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) // For model.TableInfoVersion3, it is believed that all charsets / collations are lower-cased, do not do case-convert tblInfo = tblInfo.Clone() @@ -1135,19 +1123,21 @@ func (s *testIntegrationSuite6) TestCaseInsensitiveCharsetAndCollate(c *C) { updateTableInfo(tblInfo) tk.MustExec("alter table t5 add column c varchar(10);") // load latest schema. - tblInfo = testGetTableByName(c, s.ctx, "test_charset_collate", "t5").Meta() - c.Assert(tblInfo.Charset, Equals, "UTF8MB4") - c.Assert(tblInfo.Columns[0].Charset, Equals, "utf8mb4") + tblInfo = external.GetTableByName(t, tk, "test_charset_collate", "t5").Meta() + require.Equal(t, "UTF8MB4", tblInfo.Charset) + require.Equal(t, "utf8mb4", tblInfo.Columns[0].Charset) } -func (s *testIntegrationSuite3) TestZeroFillCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestZeroFillCreateTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists abc;") tk.MustExec("create table abc(y year, z tinyint(10) zerofill, primary key(y));") - is := s.dom.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("abc")) - c.Assert(err, IsNil) + require.NoError(t, err) var yearCol, zCol *model.ColumnInfo for _, col := range tbl.Meta().Columns { if col.Name.String() == "y" { @@ -1157,16 +1147,18 @@ func (s *testIntegrationSuite3) TestZeroFillCreateTable(c *C) { zCol = col } } - c.Assert(yearCol, NotNil) - c.Assert(yearCol.Tp, Equals, mysql.TypeYear) - c.Assert(mysql.HasUnsignedFlag(yearCol.Flag), IsTrue) + require.NotNil(t, yearCol) + require.Equal(t, mysql.TypeYear, yearCol.Tp) + require.True(t, mysql.HasUnsignedFlag(yearCol.Flag)) - c.Assert(zCol, NotNil) - c.Assert(mysql.HasUnsignedFlag(zCol.Flag), IsTrue) + require.NotNil(t, zCol) + require.True(t, mysql.HasUnsignedFlag(zCol.Flag)) } -func (s *testIntegrationSuite5) TestBitDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBitDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_bit (c1 bit(10) default 250, c2 int);") tk.MustExec("insert into t_bit set c2=1;") @@ -1235,112 +1227,20 @@ func (s *testIntegrationSuite5) TestBitDefaultValue(c *C) { );`) } -func (s *testIntegrationSuite5) TestBackwardCompatibility(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_backward_compatibility") - defer tk.MustExec("drop database test_backward_compatibility") - tk.MustExec("use test_backward_compatibility") - tk.MustExec("create table t(a int primary key, b int)") - for i := 0; i < 200; i++ { - tk.MustExec(fmt.Sprintf("insert into t values(%v, %v)", i, i)) - } - - // alter table t add index idx_b(b); - is := s.dom.InfoSchema() - schemaName := model.NewCIStr("test_backward_compatibility") - tableName := model.NewCIStr("t") - schema, ok := is.SchemaByName(schemaName) - c.Assert(ok, IsTrue) - tbl, err := is.TableByName(schemaName, tableName) - c.Assert(err, IsNil) - - // Split the table. - tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 10) - - unique := false - indexName := model.NewCIStr("idx_b") - indexPartSpecification := &ast.IndexPartSpecification{ - Column: &ast.ColumnName{ - Schema: schemaName, - Table: tableName, - Name: model.NewCIStr("b"), - }, - Length: types.UnspecifiedLength, - } - indexPartSpecifications := []*ast.IndexPartSpecification{indexPartSpecification} - var indexOption *ast.IndexOption - job := &model.Job{ - SchemaID: schema.ID, - TableID: tbl.Meta().ID, - Type: model.ActionAddIndex, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{unique, indexName, indexPartSpecifications, indexOption}, +func backgroundExec(s kv.Storage, sql string, done chan error) { + se, err := session.CreateSession4Test(s) + if err != nil { + done <- errors.Trace(err) + return } - txn, err := s.store.Begin() - c.Assert(err, IsNil) - t := meta.NewMeta(txn) - job.ID, err = t.GenGlobalID() - c.Assert(err, IsNil) - job.Version = 1 - job.StartTS = txn.StartTS() - - // Simulate old TiDB init the add index job, old TiDB will not init the model.Job.ReorgMeta field, - // if we set job.SnapshotVer here, can simulate the behavior. - job.SnapshotVer = txn.StartTS() - err = t.EnQueueDDLJob(job) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - ticker := time.NewTicker(s.lease) - defer ticker.Stop() - for range ticker.C { - historyJob, err := getHistoryDDLJob(s.store, job.ID) - c.Assert(err, IsNil) - if historyJob == nil { - continue - } - c.Assert(historyJob.Error, IsNil) - - if historyJob.IsSynced() { - break - } + defer se.Close() + _, err = se.Execute(context.Background(), "use test") + if err != nil { + done <- errors.Trace(err) + return } - - // finished add index - tk.MustExec("admin check index t idx_b") -} - -type testMaxTableRowIDContext struct { - c *C - d ddl.DDL - tbl table.Table -} - -func newTestMaxTableRowIDContext(c *C, d ddl.DDL, tbl table.Table) *testMaxTableRowIDContext { - return &testMaxTableRowIDContext{ - c: c, - d: d, - tbl: tbl, - } -} - -func getMaxTableHandle(ctx *testMaxTableRowIDContext, store kv.Storage) (kv.Handle, bool) { - c := ctx.c - d := ctx.d - tbl := ctx.tbl - curVer, err := store.CurrentVersion(kv.GlobalTxnScope) - c.Assert(err, IsNil) - maxHandle, emptyTable, err := d.GetTableMaxHandle(curVer.Ver, tbl.(table.PhysicalTable)) - c.Assert(err, IsNil) - return maxHandle, emptyTable -} - -func checkGetMaxTableRowID(ctx *testMaxTableRowIDContext, store kv.Storage, expectEmpty bool, expectMaxHandle kv.Handle) { - c := ctx.c - maxHandle, emptyTable := getMaxTableHandle(ctx, store) - c.Assert(emptyTable, Equals, expectEmpty) - c.Assert(maxHandle, testutil.HandleEquals, expectMaxHandle) + _, err = se.Execute(context.Background(), sql) + done <- errors.Trace(err) } func getHistoryDDLJob(store kv.Storage, id int64) (*model.Job, error) { @@ -1356,11 +1256,10 @@ func getHistoryDDLJob(store kv.Storage, id int64) (*model.Job, error) { return job, errors.Trace(err) } -func (s *testIntegrationSuite6) TestCreateTableTooLarge(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableTooLarge(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sql := "create table t_too_large (" @@ -1377,12 +1276,14 @@ func (s *testIntegrationSuite6) TestCreateTableTooLarge(c *C) { originLimit := config.GetGlobalConfig().TableColumnCountLimit atomic.StoreUint32(&config.GetGlobalConfig().TableColumnCountLimit, uint32(cnt*4)) _, err := tk.Exec(sql) - c.Assert(kv.ErrEntryTooLarge.Equal(err), IsTrue, Commentf("err:%v", err)) + require.Truef(t, kv.ErrEntryTooLarge.Equal(err), "err:%v", err) atomic.StoreUint32(&config.GetGlobalConfig().TableColumnCountLimit, originLimit) } -func (s *testSerialDBSuite1) TestCreateTableTooManyIndexes(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableTooManyIndexes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sql := "create table t_too_many_indexes (" @@ -1401,8 +1302,10 @@ func (s *testSerialDBSuite1) TestCreateTableTooManyIndexes(c *C) { tk.MustGetErrCode(sql, errno.ErrTooManyKeys) } -func (s *testIntegrationSuite3) TestChangeColumnPosition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestChangeColumnPosition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table position (a int default 1, b int default 2)") @@ -1449,11 +1352,13 @@ func (s *testIntegrationSuite3) TestChangeColumnPosition(c *C) { " KEY `t` (`c`)", ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", } - c.Assert(createSQL, Equals, strings.Join(expectedSQL, "\n")) + require.Equal(t, strings.Join(expectedSQL, "\n"), createSQL) } -func (s *testIntegrationSuite2) TestAddIndexAfterAddColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddIndexAfterAddColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table test_add_index_after_add_col(a int, b int not null default '0')") @@ -1465,16 +1370,18 @@ func (s *testIntegrationSuite2) TestAddIndexAfterAddColumn(c *C) { tk.MustGetErrCode(sql, errno.ErrTooManyKeyParts) } -func (s *testIntegrationSuite3) TestResolveCharset(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestResolveCharset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists resolve_charset") tk.MustExec(`CREATE TABLE resolve_charset (a varchar(255) DEFAULT NULL) DEFAULT CHARSET=latin1`) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("resolve_charset")) - c.Assert(err, IsNil) - c.Assert(tbl.Cols()[0].Charset, Equals, "latin1") + require.NoError(t, err) + require.Equal(t, "latin1", tbl.Cols()[0].Charset) tk.MustExec("INSERT INTO resolve_charset VALUES('鰈')") tk.MustExec("create database resolve_charset charset binary") @@ -1483,20 +1390,95 @@ func (s *testIntegrationSuite3) TestResolveCharset(c *C) { is = domain.GetDomain(ctx).InfoSchema() tbl, err = is.TableByName(model.NewCIStr("resolve_charset"), model.NewCIStr("resolve_charset")) - c.Assert(err, IsNil) - c.Assert(tbl.Cols()[0].Charset, Equals, "latin1") - c.Assert(tbl.Meta().Charset, Equals, "latin1") + require.NoError(t, err) + require.Equal(t, "latin1", tbl.Cols()[0].Charset) + require.Equal(t, "latin1", tbl.Meta().Charset) tk.MustExec(`CREATE TABLE resolve_charset1 (a varchar(255) DEFAULT NULL)`) is = domain.GetDomain(ctx).InfoSchema() tbl, err = is.TableByName(model.NewCIStr("resolve_charset"), model.NewCIStr("resolve_charset1")) - c.Assert(err, IsNil) - c.Assert(tbl.Cols()[0].Charset, Equals, "binary") - c.Assert(tbl.Meta().Charset, Equals, "binary") + require.NoError(t, err) + require.Equal(t, "binary", tbl.Cols()[0].Charset) + require.Equal(t, "binary", tbl.Meta().Charset) } -func (s *testIntegrationSuite6) TestAddColumnTooMany(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddColumnDefaultNow(t *testing.T) { + // Related Issue: https://github.com/pingcap/tidb/issues/31968 + mockStore, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, mockStore) + const dateHourLength = len("yyyy-mm-dd hh:") + + tk.MustExec("SET timestamp = 1000") + tk.MustExec("USE test") + tk.MustExec("DROP TABLE IF EXISTS t1") + tk.MustExec("CREATE TABLE t1 ( i INT )") + tk.MustExec("INSERT INTO t1 VALUES (1)") + + // test datetime + tk.MustExec("ALTER TABLE t1 ADD COLUMN c4 DATETIME(6) DEFAULT NOW(6) ON UPDATE NOW(6) FIRST") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c3 DATETIME(6) DEFAULT NOW(6) FIRST") + + // test timestamp + tk.MustExec("ALTER TABLE t1 ADD COLUMN c2 TIMESTAMP(6) DEFAULT NOW(6) ON UPDATE NOW(6) FIRST") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c1 TIMESTAMP(6) DEFAULT NOW(6) FIRST") + + tk.MustExec("SET time_zone = 'Europe/Amsterdam'") + rows := tk.MustQuery("select * from t1").Sort().Rows() + require.Len(t, rows, 1, "Result should has only 1 row") + row := rows[0] + if c3, ok := row[0].(string); ok { + require.Equal(t, "19", c3[:len("19")], "The datetime should start with '19'") + } + if c4, ok := row[1].(string); ok { + require.Equal(t, "19", c4[:len("19")], "The datetime should start with '19'") + } + + var amsterdamC1YMDH, shanghaiC1YMDH, amsterdamC1MS, shanghaiC1MS string + var amsterdamC2YMDH, shanghaiC2YMDH, amsterdamC2MS, shanghaiC2MS string + + if c1, ok := row[0].(string); ok { + require.Equal(t, "19", c1[:len("19")], "The timestamp should start with '19'") + + amsterdamC1YMDH = c1[:dateHourLength] // YMDH means "yyyy-mm-dd hh" + amsterdamC1MS = c1[dateHourLength:] // MS means "mm-ss.fractional" + } + if c2, ok := row[1].(string); ok { + require.Equal(t, "19", c2[:len("19")], "The timestamp should start with '19'") + + amsterdamC2YMDH = c2[:dateHourLength] // YMDH means "yyyy-mm-dd hh" + amsterdamC2MS = c2[dateHourLength:] // MS means "mm-ss.fractional" + } + + tk.MustExec("SET time_zone = 'Asia/Shanghai'") + rows = tk.MustQuery("select * from t1").Sort().Rows() + require.Len(t, rows, 1, "Result should has only 1 row") + row = rows[0] + + if c1, ok := row[0].(string); ok { + require.Equal(t, "19", c1[:len("19")], "The timestamp should start with '19'") + + shanghaiC1YMDH = c1[:dateHourLength] // YMDH means "yyyy-mm-dd hh" + shanghaiC1MS = c1[dateHourLength:] // MS means "mm-ss.fractional" + } + if c2, ok := row[1].(string); ok { + require.Equal(t, "19", c2[:len("19")], "The timestamp should start with '19'") + + shanghaiC2YMDH = c2[:dateHourLength] // YMDH means "yyyy-mm-dd hh" + shanghaiC2MS = c2[dateHourLength:] // MS means "mm-ss.fractional" + } + + require.True(t, amsterdamC1YMDH != shanghaiC1YMDH, "The timestamp before 'hour' should not be equivalent") + require.True(t, amsterdamC2YMDH != shanghaiC2YMDH, "The timestamp before 'hour' should not be equivalent") + require.Equal(t, amsterdamC1MS, shanghaiC1MS, "The timestamp after 'hour' should be equivalent") + require.Equal(t, amsterdamC2MS, shanghaiC2MS, "The timestamp after 'hour' should be equivalent") + +} + +func TestAddColumnTooMany(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") count := int(atomic.LoadUint32(&config.GetGlobalConfig().TableColumnCountLimit) - 1) var cols []string @@ -1510,8 +1492,10 @@ func (s *testIntegrationSuite6) TestAddColumnTooMany(c *C) { tk.MustGetErrCode(alterSQL, errno.ErrTooManyFields) } -func (s *testSerialDBSuite1) TestCreateTooManyIndexes(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTooManyIndexes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") count := config.GetGlobalConfig().IndexLimit - 1 sql := "create table t_index_too_many (" @@ -1532,8 +1516,10 @@ func (s *testSerialDBSuite1) TestCreateTooManyIndexes(c *C) { tk.MustGetErrCode(alterSQL, errno.ErrTooManyKeys) } -func (s *testSerialDBSuite1) TestCreateSecondaryIndexInCluster(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateSecondaryIndexInCluster(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // test create table with non-unique key @@ -1613,51 +1599,53 @@ CREATE TABLE t ( tk.MustExec("create table t2 like t") } -func (s *testIntegrationSuite3) TestAlterColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestAlterColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table test_alter_column (a int default 111, b varchar(8), c varchar(8) not null, d timestamp on update current_timestamp)") tk.MustExec("insert into test_alter_column set b = 'a', c = 'aa'") tk.MustQuery("select a from test_alter_column").Check(testkit.Rows("111")) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_alter_column")) - c.Assert(err, IsNil) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_alter_column")) + require.NoError(t, err) tblInfo := tbl.Meta() colA := tblInfo.Columns[0] hasNoDefault := mysql.HasNoDefaultValueFlag(colA.Flag) - c.Assert(hasNoDefault, IsFalse) + require.False(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column a set default 222") tk.MustExec("insert into test_alter_column set b = 'b', c = 'bb'") tk.MustQuery("select a from test_alter_column").Check(testkit.Rows("111", "222")) is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_alter_column")) - c.Assert(err, IsNil) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_alter_column")) + require.NoError(t, err) tblInfo = tbl.Meta() colA = tblInfo.Columns[0] hasNoDefault = mysql.HasNoDefaultValueFlag(colA.Flag) - c.Assert(hasNoDefault, IsFalse) + require.False(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column b set default null") tk.MustExec("insert into test_alter_column set c = 'cc'") tk.MustQuery("select b from test_alter_column").Check(testkit.Rows("a", "b", "")) is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_alter_column")) - c.Assert(err, IsNil) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_alter_column")) + require.NoError(t, err) tblInfo = tbl.Meta() colC := tblInfo.Columns[2] hasNoDefault = mysql.HasNoDefaultValueFlag(colC.Flag) - c.Assert(hasNoDefault, IsTrue) + require.True(t, hasNoDefault) tk.MustExec("alter table test_alter_column alter column c set default 'xx'") tk.MustExec("insert into test_alter_column set a = 123") tk.MustQuery("select c from test_alter_column").Check(testkit.Rows("aa", "bb", "cc", "xx")) is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_alter_column")) - c.Assert(err, IsNil) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_alter_column")) + require.NoError(t, err) tblInfo = tbl.Meta() colC = tblInfo.Columns[2] hasNoDefault = mysql.HasNoDefaultValueFlag(colC.Flag) - c.Assert(hasNoDefault, IsFalse) + require.False(t, hasNoDefault) // TODO: After fix issue 2606. // tk.MustExec( "alter table test_alter_column alter column d set default null") tk.MustExec("alter table test_alter_column alter column a drop default") @@ -1679,13 +1667,13 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { tk.MustExec("drop table if exists mc") tk.MustExec("create table mc(a int key nonclustered, b int, c int)") _, err = tk.Exec("alter table mc modify column a int key") // Adds a new primary key - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("alter table mc modify column c int unique") // Adds a new unique key - c.Assert(err, NotNil) + require.Error(t, err) result := tk.MustQuery("show create table mc") createSQL := result.Rows()[0][1] expected := "CREATE TABLE `mc` (\n `a` int(11) NOT NULL,\n `b` int(11) DEFAULT NULL,\n `c` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + require.Equal(t, expected, createSQL) // Change / modify column should preserve index options. tk.MustExec("drop table if exists mc") @@ -1696,7 +1684,7 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { result = tk.MustQuery("show create table mc") createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` bigint(20) DEFAULT NULL,\n `c` bigint(20) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */,\n UNIQUE KEY `c` (`c`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + require.Equal(t, expected, createSQL) // Dropping or keeping auto_increment is allowed, however adding is not allowed. tk.MustExec("drop table if exists mc") @@ -1705,18 +1693,18 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { result = tk.MustQuery("show create table mc") createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL AUTO_INCREMENT,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + require.Equal(t, expected, createSQL) _, err = tk.Exec("alter table mc modify column a bigint") // Droppping auto_increment is not allow when @@tidb_allow_remove_auto_inc == 'off' - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("set @@tidb_allow_remove_auto_inc = on") tk.MustExec("alter table mc modify column a bigint") // Dropping auto_increment is ok when @@tidb_allow_remove_auto_inc == 'on' result = tk.MustQuery("show create table mc") createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + require.Equal(t, expected, createSQL) _, err = tk.Exec("alter table mc modify column a bigint auto_increment") // Adds auto_increment should throw error - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("drop table if exists t") tk.MustExec("create table t1 (a varchar(10),b varchar(100),c tinyint,d varchar(3071),index(a),index(a,b),index (c,d)) charset = ascii;") @@ -1743,31 +1731,29 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { tk.MustExec("alter table t1 add column update_time3 datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3);") tk.MustExec("alter table t1 add column update_time6 datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6);") rows := tk.MustQuery("select * from t1").Rows() - c.Assert(rows[0][0], Equals, "1") + require.Equal(t, "1", rows[0][0]) updateTime3 := rows[0][1].(string) - c.Assert(updateTime3[len(updateTime3)-3:], Not(Equals), "000") + require.NotEqual(t, "000", updateTime3[len(updateTime3)-3:]) updateTime6 := rows[0][2].(string) - c.Assert(updateTime6[len(updateTime6)-6:], Not(Equals), "000000") + require.NotEqual(t, "000000", updateTime6[len(updateTime6)-6:]) } -func (s *testIntegrationSuite) assertWarningExec(tk *testkit.TestKit, c *C, sql string, expectedWarn *terror.Error) { +func assertWarningExec(tk *testkit.TestKit, t *testing.T, sql string, expectedWarn *terror.Error) { _, err := tk.Exec(sql) - c.Assert(err, IsNil) - st := tk.Se.GetSessionVars().StmtCtx - c.Assert(st.WarningCount(), Equals, uint16(1)) - c.Assert(expectedWarn.Equal(st.GetWarnings()[0].Err), IsTrue, Commentf("error:%v", err)) -} - -func (s *testIntegrationSuite) assertAlterWarnExec(tk *testkit.TestKit, c *C, sql string) { - s.assertWarningExec(tk, c, sql, ddl.ErrAlterOperationNotSupported) + require.NoError(t, err) + st := tk.Session().GetSessionVars().StmtCtx + require.Equal(t, uint16(1), st.WarningCount()) + require.Truef(t, expectedWarn.Equal(st.GetWarnings()[0].Err), "error:%v", err) } -func (s *testIntegrationSuite) assertAlterErrorExec(tk *testkit.TestKit, c *C, sql string) { - tk.MustGetErrCode(sql, errno.ErrAlterOperationNotSupportedReason) +func assertAlterWarnExec(tk *testkit.TestKit, t *testing.T, sql string) { + assertWarningExec(tk, t, sql, dbterror.ErrAlterOperationNotSupported) } -func (s *testIntegrationSuite3) TestAlterAlgorithm(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterAlgorithm(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, t1") defer tk.MustExec("drop table if exists t") @@ -1782,57 +1768,59 @@ func (s *testIntegrationSuite3) TestAlterAlgorithm(c *C) { PARTITION p2 VALUES LESS THAN (16), PARTITION p3 VALUES LESS THAN (21) )`) - s.assertAlterWarnExec(tk, c, "alter table t modify column a bigint, ALGORITHM=INPLACE;") + assertAlterWarnExec(tk, t, "alter table t modify column a bigint, ALGORITHM=INPLACE;") tk.MustExec("alter table t modify column a bigint, ALGORITHM=INPLACE, ALGORITHM=INSTANT;") tk.MustExec("alter table t modify column a bigint, ALGORITHM=DEFAULT;") // Test add/drop index - s.assertAlterErrorExec(tk, c, "alter table t add index idx_b(b), ALGORITHM=INSTANT") - s.assertAlterWarnExec(tk, c, "alter table t add index idx_b1(b), ALGORITHM=COPY") + tk.MustGetErrCode("alter table t add index idx_b(b), ALGORITHM=INSTANT", errno.ErrAlterOperationNotSupportedReason) + assertAlterWarnExec(tk, t, "alter table t add index idx_b1(b), ALGORITHM=COPY") tk.MustExec("alter table t add index idx_b2(b), ALGORITHM=INPLACE") tk.MustExec("alter table t add index idx_b3(b), ALGORITHM=DEFAULT") - s.assertAlterWarnExec(tk, c, "alter table t drop index idx_b3, ALGORITHM=INPLACE") - s.assertAlterWarnExec(tk, c, "alter table t drop index idx_b1, ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t drop index idx_b3, ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t drop index idx_b1, ALGORITHM=COPY") tk.MustExec("alter table t drop index idx_b2, ALGORITHM=INSTANT") // Test rename - s.assertAlterWarnExec(tk, c, "alter table t rename to t1, ALGORITHM=COPY") - s.assertAlterWarnExec(tk, c, "alter table t1 rename to t2, ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t rename to t1, ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t1 rename to t2, ALGORITHM=INPLACE") tk.MustExec("alter table t2 rename to t, ALGORITHM=INSTANT") tk.MustExec("alter table t rename to t1, ALGORITHM=DEFAULT") tk.MustExec("alter table t1 rename to t") // Test rename index - s.assertAlterWarnExec(tk, c, "alter table t rename index idx_c to idx_c1, ALGORITHM=COPY") - s.assertAlterWarnExec(tk, c, "alter table t rename index idx_c1 to idx_c2, ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t rename index idx_c to idx_c1, ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t rename index idx_c1 to idx_c2, ALGORITHM=INPLACE") tk.MustExec("alter table t rename index idx_c2 to idx_c, ALGORITHM=INSTANT") tk.MustExec("alter table t rename index idx_c to idx_c1, ALGORITHM=DEFAULT") // partition. - s.assertAlterWarnExec(tk, c, "alter table t ALGORITHM=COPY, truncate partition p1") - s.assertAlterWarnExec(tk, c, "alter table t ALGORITHM=INPLACE, truncate partition p2") + assertAlterWarnExec(tk, t, "alter table t ALGORITHM=COPY, truncate partition p1") + assertAlterWarnExec(tk, t, "alter table t ALGORITHM=INPLACE, truncate partition p2") tk.MustExec("alter table t ALGORITHM=INSTANT, truncate partition p3") - s.assertAlterWarnExec(tk, c, "alter table t add partition (partition p4 values less than (2002)), ALGORITHM=COPY") - s.assertAlterWarnExec(tk, c, "alter table t add partition (partition p5 values less than (3002)), ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t add partition (partition p4 values less than (2002)), ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t add partition (partition p5 values less than (3002)), ALGORITHM=INPLACE") tk.MustExec("alter table t add partition (partition p6 values less than (4002)), ALGORITHM=INSTANT") - s.assertAlterWarnExec(tk, c, "alter table t ALGORITHM=COPY, drop partition p4") - s.assertAlterWarnExec(tk, c, "alter table t ALGORITHM=INPLACE, drop partition p5") + assertAlterWarnExec(tk, t, "alter table t ALGORITHM=COPY, drop partition p4") + assertAlterWarnExec(tk, t, "alter table t ALGORITHM=INPLACE, drop partition p5") tk.MustExec("alter table t ALGORITHM=INSTANT, drop partition p6") // Table options - s.assertAlterWarnExec(tk, c, "alter table t comment = 'test', ALGORITHM=COPY") - s.assertAlterWarnExec(tk, c, "alter table t comment = 'test', ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t comment = 'test', ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t comment = 'test', ALGORITHM=INPLACE") tk.MustExec("alter table t comment = 'test', ALGORITHM=INSTANT") - s.assertAlterWarnExec(tk, c, "alter table t default charset = utf8mb4, ALGORITHM=COPY") - s.assertAlterWarnExec(tk, c, "alter table t default charset = utf8mb4, ALGORITHM=INPLACE") + assertAlterWarnExec(tk, t, "alter table t default charset = utf8mb4, ALGORITHM=COPY") + assertAlterWarnExec(tk, t, "alter table t default charset = utf8mb4, ALGORITHM=INPLACE") tk.MustExec("alter table t default charset = utf8mb4, ALGORITHM=INSTANT") } -func (s *testIntegrationSuite3) TestAlterTableAddUniqueOnPartionRangeColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddUniqueOnPartionRangeColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -1859,27 +1847,31 @@ func (s *testIntegrationSuite3) TestAlterTableAddUniqueOnPartionRangeColumn(c *C tk.MustGetErrCode("alter table t add unique index idx_b(b)", errno.ErrUniqueKeyNeedAllFieldsInPf) } -func (s *testIntegrationSuite5) TestFulltextIndexIgnore(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestFulltextIndexIgnore(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t_ft") defer tk.MustExec("drop table if exists t_ft") // Make sure that creating and altering to add a fulltext key gives the correct warning - s.assertWarningExec(tk, c, "create table t_ft (a text, fulltext key (a))", ddl.ErrTableCantHandleFt) - s.assertWarningExec(tk, c, "alter table t_ft add fulltext key (a)", ddl.ErrTableCantHandleFt) + assertWarningExec(tk, t, "create table t_ft (a text, fulltext key (a))", dbterror.ErrTableCantHandleFt) + assertWarningExec(tk, t, "alter table t_ft add fulltext key (a)", dbterror.ErrTableCantHandleFt) // Make sure table t_ft still has no indexes even after it was created and altered r := tk.MustQuery("show index from t_ft") - c.Assert(r.Rows(), HasLen, 0) + require.Len(t, r.Rows(), 0) r = tk.MustQuery("select * from information_schema.statistics where table_schema='test' and table_name='t_ft'") - c.Assert(r.Rows(), HasLen, 0) + require.Len(t, r.Rows(), 0) + } -func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestTreatOldVersionUTF8AsUTF8MB4(t *testing.T) { + restoreFunc := config.RestoreFunc() + defer restoreFunc() + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -1892,28 +1884,28 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // Mock old version table info with column charset is utf8. - db, ok := domain.GetDomain(s.ctx).InfoSchema().SchemaByName(model.NewCIStr("test")) - tbl := testGetTableByName(c, s.ctx, "test", "t") + db, ok := domain.GetDomain(tk.Session()).InfoSchema().SchemaByName(model.NewCIStr("test")) + tbl := external.GetTableByName(t, tk, "test", "t") tblInfo := tbl.Meta().Clone() tblInfo.Version = model.TableInfoVersion0 tblInfo.Columns[0].Version = model.ColumnInfoVersion0 updateTableInfo := func(tblInfo *model.TableInfo) { mockCtx := mock.NewContext() - mockCtx.Store = s.store + mockCtx.Store = store err := mockCtx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) txn, err := mockCtx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) mt := meta.NewMeta(txn) - c.Assert(ok, IsTrue) + require.True(t, ok) err = mt.UpdateTable(db.ID, tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) } updateTableInfo(tblInfo) tk.MustExec("alter table t add column c varchar(10) character set utf8;") // load latest schema. - c.Assert(config.GetGlobalConfig().TreatOldVersionUTF8AsUTF8MB4, IsTrue) + require.True(t, config.GetGlobalConfig().TreatOldVersionUTF8AsUTF8MB4) tk.MustExec("insert into t set a= x'f09f8c80'") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` varchar(10) DEFAULT NULL,\n" + @@ -1931,7 +1923,7 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // Mock old version table info with table and column charset is utf8. - tbl = testGetTableByName(c, s.ctx, "test", "t") + tbl = external.GetTableByName(t, tk, "test", "t") tblInfo = tbl.Meta().Clone() tblInfo.Charset = charset.CharsetUTF8 tblInfo.Collate = charset.CollationUTF8 @@ -1965,10 +1957,10 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { conf.TreatOldVersionUTF8AsUTF8MB4 = true }) tk.MustExec("alter table t modify column a varchar(10) character set utf8mb4") // change column charset. - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl.Meta().Columns[0].Charset, Equals, charset.CharsetUTF8MB4) - c.Assert(tbl.Meta().Columns[0].Collate, Equals, charset.CollationUTF8MB4) - c.Assert(tbl.Meta().Columns[0].Version, Equals, model.ColumnInfoVersion0) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].Charset) + require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].Collate) + require.Equal(t, model.ColumnInfoVersion0, tbl.Meta().Columns[0].Version) tk.MustExec("insert into t set a= x'f09f8c80'") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` varchar(10) DEFAULT NULL,\n" + @@ -1976,13 +1968,13 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // Test for change column should not modify the column version. tk.MustExec("alter table t change column a a varchar(20)") // change column. - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl.Meta().Columns[0].Charset, Equals, charset.CharsetUTF8MB4) - c.Assert(tbl.Meta().Columns[0].Collate, Equals, charset.CollationUTF8MB4) - c.Assert(tbl.Meta().Columns[0].Version, Equals, model.ColumnInfoVersion0) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Equal(t, charset.CharsetUTF8MB4, tbl.Meta().Columns[0].Charset) + require.Equal(t, charset.CollationUTF8MB4, tbl.Meta().Columns[0].Collate) + require.Equal(t, model.ColumnInfoVersion0, tbl.Meta().Columns[0].Version) // Test for v2.1.5 and v2.1.6 that table version is 1 but column version is 0. - tbl = testGetTableByName(c, s.ctx, "test", "t") + tbl = external.GetTableByName(t, tk, "test", "t") tblInfo = tbl.Meta().Clone() tblInfo.Charset = charset.CharsetUTF8 tblInfo.Collate = charset.CollationUTF8 @@ -1991,7 +1983,7 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { tblInfo.Columns[0].Charset = charset.CharsetUTF8 tblInfo.Columns[0].Collate = charset.CollationUTF8 updateTableInfo(tblInfo) - c.Assert(config.GetGlobalConfig().TreatOldVersionUTF8AsUTF8MB4, IsTrue) + require.True(t, config.GetGlobalConfig().TreatOldVersionUTF8AsUTF8MB4) tk.MustExec("alter table t change column b b varchar(20) character set ascii") // reload schema. tk.MustExec("insert into t set a= x'f09f8c80'") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + @@ -2026,18 +2018,64 @@ func (s *testIntegrationSuite1) TestTreatOldVersionUTF8AsUTF8MB4(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) } -func (s *testIntegrationSuite3) TestDefaultValueIsString(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDefaultValueIsString(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int default b'1');") - tbl := testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl.Meta().Columns[0].DefaultValue, Equals, "1") + tbl := external.GetTableByName(t, tk, "test", "t") + require.Equal(t, "1", tbl.Meta().Columns[0].DefaultValue) } -func (s *testIntegrationSuite5) TestChangingDBCharset(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDefaultColumnWithRand(t *testing.T) { + // Related issue: https://github.com/pingcap/tidb/issues/10377 + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t, t1, t2") + + // create table + tk.MustExec("create table t (c int(10), c1 int default (rand()))") + tk.MustExec("create table t1 (c int, c1 double default (rand()))") + tk.MustExec("create table t2 (c int, c1 double default (rand(1)))") + + // add column with default rand() for table t is forbidden in MySQL 8.0 + tk.MustGetErrCode("alter table t add column c2 double default (rand(2))", errno.ErrBinlogUnsafeSystemFunction) + tk.MustGetErrCode("alter table t add column c3 int default ((rand()))", errno.ErrBinlogUnsafeSystemFunction) + tk.MustGetErrCode("alter table t add column c4 int default (((rand(3))))", errno.ErrBinlogUnsafeSystemFunction) + + // insert records + tk.MustExec("insert into t(c) values (1),(2),(3)") + tk.MustExec("insert into t1(c) values (1),(2),(3)") + tk.MustExec("insert into t2(c) values (1),(2),(3)") + + queryStmts := []string{ + "SELECT c1 from t", + "SELECT c1 from t1", + "SELECT c1 from t2", + } + for _, queryStmt := range queryStmts { + r := tk.MustQuery(queryStmt).Rows() + for _, row := range r { + d, ok := row[0].(float64) + if ok { + require.True(t, 0.0 <= d && d < 1.0, "rand() return a random floating-point value in the range 0 <= v < 1.0.") + } + } + } + + // use a non-existent function name + tk.MustGetErrCode("CREATE TABLE t3 (c int, c1 int default a_function_not_supported_yet());", errno.ErrDefValGeneratedNamedFunctionIsNotAllowed) +} + +func TestChangingDBCharset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("DROP DATABASE IF EXISTS alterdb1") tk.MustExec("CREATE DATABASE alterdb1 CHARSET=utf8 COLLATE=utf8_unicode_ci") @@ -2057,13 +2095,13 @@ func (s *testIntegrationSuite5) TestChangingDBCharset(c *C) { }, } for _, fc := range noDBFailedCases { - c.Assert(tk.ExecToErr(fc.stmt).Error(), Equals, fc.errMsg, Commentf("%v", fc.stmt)) + require.EqualError(t, tk.ExecToErr(fc.stmt), fc.errMsg) } verifyDBCharsetAndCollate := func(dbName, chs string, coll string) { // check `SHOW CREATE SCHEMA`. r := tk.MustQuery("SHOW CREATE SCHEMA " + dbName).Rows()[0][1].(string) - c.Assert(strings.Contains(r, "CHARACTER SET "+chs), IsTrue) + require.True(t, strings.Contains(r, "CHARACTER SET "+chs)) template := `SELECT DEFAULT_CHARACTER_SET_NAME, @@ -2073,14 +2111,14 @@ func (s *testIntegrationSuite5) TestChangingDBCharset(c *C) { sql := fmt.Sprintf(template, dbName) tk.MustQuery(sql).Check(testkit.Rows(fmt.Sprintf("%s %s", chs, coll))) - dom := domain.GetDomain(s.ctx) + dom := domain.GetDomain(tk.Session()) // Make sure the table schema is the new schema. err := dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) dbInfo, ok := dom.InfoSchema().SchemaByName(model.NewCIStr(dbName)) - c.Assert(ok, Equals, true) - c.Assert(dbInfo.Charset, Equals, chs) - c.Assert(dbInfo.Collate, Equals, coll) + require.Equal(t, true, ok) + require.Equal(t, chs, dbInfo.Charset) + require.Equal(t, coll, dbInfo.Collate) } tk.MustExec("ALTER SCHEMA alterdb1 COLLATE = utf8mb4_general_ci") @@ -2129,7 +2167,7 @@ func (s *testIntegrationSuite5) TestChangingDBCharset(c *C) { } for _, fc := range failedCases { - c.Assert(tk.ExecToErr(fc.stmt).Error(), Equals, fc.errMsg, Commentf("%v", fc.stmt)) + require.EqualError(t, tk.ExecToErr(fc.stmt), fc.errMsg) } tk.MustExec("ALTER SCHEMA CHARACTER SET = 'utf8' COLLATE = 'utf8_unicode_ci'") verifyDBCharsetAndCollate("alterdb2", "utf8", "utf8_unicode_ci") @@ -2148,11 +2186,17 @@ func (s *testIntegrationSuite5) TestChangingDBCharset(c *C) { tk.MustExec("alter database TEST_UPPERCASE_DB_CHARSET default character set utf8mb4;") } -func (s *testIntegrationSuite4) TestDropAutoIncrementIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropAutoIncrementIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int(11) not null auto_increment key, b int(11), c bigint, unique key (a, b, c))") + tk.MustExec("alter table t1 drop index a") + tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int auto_increment, unique key (a))") dropIndexSQL := "alter table t1 drop index a" @@ -2164,8 +2208,10 @@ func (s *testIntegrationSuite4) TestDropAutoIncrementIndex(c *C) { tk.MustGetErrCode(dropIndexSQL, errno.ErrWrongAutoKey) } -func (s *testIntegrationSuite4) TestInsertIntoGeneratedColumnWithDefaultExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertIntoGeneratedColumnWithDefaultExpr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") @@ -2222,8 +2268,10 @@ func (s *testIntegrationSuite4) TestInsertIntoGeneratedColumnWithDefaultExpr(c * tk.MustExec("drop table t1, t2, t3, t4, t5") } -func (s *testIntegrationSuite3) TestSqlFunctionsInGeneratedColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSqlFunctionsInGeneratedColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test") tk.MustExec("use test") tk.MustExec("drop table if exists t, t1") @@ -2264,19 +2312,31 @@ func (s *testIntegrationSuite3) TestSqlFunctionsInGeneratedColumns(c *C) { tk.MustExec("create table t (a int, b int as ((a)))") } -func (s *testIntegrationSuite3) TestParserIssue284(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestParserIssue284(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table test.t_parser_issue_284(c1 int not null primary key)") _, err := tk.Exec("create table test.t_parser_issue_284_2(id int not null primary key, c1 int not null, constraint foreign key (c1) references t_parser_issue_284(c1))") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop table test.t_parser_issue_284") tk.MustExec("drop table test.t_parser_issue_284_2") } -func (s *testSerialDBSuite1) TestAddExpressionIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddExpressionIndex(t *testing.T) { + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + conf.Experimental.AllowsExpressionIndex = true + }) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") @@ -2285,37 +2345,37 @@ func (s *testSerialDBSuite1) TestAddExpressionIndex(c *C) { tk.MustExec("alter table t add index idx((a+b));") tk.MustQuery("SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_name = 't'").Check(testkit.Rows()) - tblInfo, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tblInfo, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) columns := tblInfo.Meta().Columns - c.Assert(len(columns), Equals, 3) - c.Assert(columns[2].Hidden, IsTrue) + require.Equal(t, 3, len(columns)) + require.True(t, columns[2].Hidden) tk.MustQuery("select * from t;").Check(testkit.Rows("1 2.1")) tk.MustExec("alter table t add index idx_multi((a+b),(a+1), b);") - tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tblInfo, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) columns = tblInfo.Meta().Columns - c.Assert(len(columns), Equals, 5) - c.Assert(columns[3].Hidden, IsTrue) - c.Assert(columns[4].Hidden, IsTrue) + require.Equal(t, 5, len(columns)) + require.True(t, columns[3].Hidden) + require.True(t, columns[4].Hidden) tk.MustQuery("select * from t;").Check(testkit.Rows("1 2.1")) tk.MustExec("alter table t drop index idx;") - tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tblInfo, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) columns = tblInfo.Meta().Columns - c.Assert(len(columns), Equals, 4) + require.Equal(t, 4, len(columns)) tk.MustQuery("select * from t;").Check(testkit.Rows("1 2.1")) tk.MustExec("alter table t drop index idx_multi;") - tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tblInfo, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) columns = tblInfo.Meta().Columns - c.Assert(len(columns), Equals, 2) + require.Equal(t, 2, len(columns)) tk.MustQuery("select * from t;").Check(testkit.Rows("1 2.1")) @@ -2348,8 +2408,18 @@ func (s *testSerialDBSuite1) TestAddExpressionIndex(c *C) { }) } -func (s *testSerialDBSuite1) TestCreateExpressionIndexError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateExpressionIndexError(t *testing.T) { + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + conf.Experimental.AllowsExpressionIndex = true + }) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int, b real);") @@ -2393,8 +2463,10 @@ func (s *testSerialDBSuite1) TestCreateExpressionIndexError(c *C) { tk.MustExec("update t t1 set t1.short_name='a' where t1.id='1';") } -func (s *testSerialDBSuite1) TestAddExpressionIndexOnPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddExpressionIndexOnPartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec(`create table t( @@ -2410,11 +2482,11 @@ func (s *testSerialDBSuite1) TestAddExpressionIndexOnPartition(c *C) { tk.MustExec("insert into t values (1, 'test', 2), (12, 'test', 3), (15, 'test', 10), (20, 'test', 20);") tk.MustExec("alter table t add index idx((a+c));") - tblInfo, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tblInfo, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) columns := tblInfo.Meta().Columns - c.Assert(len(columns), Equals, 4) - c.Assert(columns[3].Hidden, IsTrue) + require.Equal(t, 4, len(columns)) + require.True(t, columns[3].Hidden) tk.MustQuery("select * from t order by a;").Check(testkit.Rows("1 test 2", "12 test 3", "15 test 10", "20 test 20")) } @@ -2422,17 +2494,19 @@ func (s *testSerialDBSuite1) TestAddExpressionIndexOnPartition(c *C) { // TestCreateTableWithAutoIdCache test the auto_id_cache table option. // `auto_id_cache` take effects on handle too when `PKIshandle` is false, // or even there is no auto_increment column at all. -func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithAutoIdCache(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") // Test primary key is handle. tk.MustExec("create table t(a int auto_increment key clustered) auto_id_cache 100") - tblInfo, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(100)) + tblInfo, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + require.Equal(t, int64(100), tblInfo.Meta().AutoIdCache) tk.MustExec("insert into t values()") tk.MustQuery("select * from t").Check(testkit.Rows("1")) tk.MustExec("delete from t") @@ -2446,8 +2520,8 @@ func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t(a int) auto_id_cache 100") - _, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + _, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tk.MustExec("insert into t values()") tk.MustQuery("select _tidb_rowid from t").Check(testkit.Rows("1")) @@ -2462,8 +2536,8 @@ func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t(a int null, b int auto_increment unique) auto_id_cache 100") - _, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + _, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tk.MustExec("insert into t(b) values(NULL)") tk.MustQuery("select b, _tidb_rowid from t").Check(testkit.Rows("1 2")) @@ -2477,9 +2551,9 @@ func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { // Test alter auto_id_cache. tk.MustExec("alter table t1 auto_id_cache 200") - tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(200)) + tblInfo, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, int64(200), tblInfo.Meta().AutoIdCache) tk.MustExec("insert into t1(b) values(NULL)") tk.MustQuery("select b, _tidb_rowid from t1").Check(testkit.Rows("201 202")) @@ -2494,9 +2568,9 @@ func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t(a int auto_increment key clustered) auto_id_cache 3") - tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(3)) + tblInfo, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + require.Equal(t, int64(3), tblInfo.Meta().AutoIdCache) // Test insert batch size(4 here) greater than the customized autoid step(3 here). tk.MustExec("insert into t(a) values(NULL),(NULL),(NULL)") @@ -2510,23 +2584,25 @@ func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) { tk.MustExec("insert into t1(a) values(NULL)") next := tk.MustQuery("select a from t1").Rows()[0][0].(string) nextInt, err := strconv.Atoi(next) - c.Assert(err, IsNil) - c.Assert(nextInt, Greater, 5) + require.NoError(t, err) + require.Greater(t, nextInt, 5) // Test auto_id_cache overflows int64. tk.MustExec("drop table if exists t;") _, err = tk.Exec("create table t(a int) auto_id_cache = 9223372036854775808") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "table option auto_id_cache overflows int64") + require.Error(t, err) + require.Equal(t, "table option auto_id_cache overflows int64", err.Error()) tk.MustExec("create table t(a int) auto_id_cache = 9223372036854775807") _, err = tk.Exec("alter table t auto_id_cache = 9223372036854775808") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "table option auto_id_cache overflows int64") + require.Error(t, err) + require.Equal(t, "table option auto_id_cache overflows int64", err.Error()) } -func (s *testIntegrationSuite4) TestAlterIndexVisibility(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterIndexVisibility(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists alter_index_test") tk.MustExec("USE alter_index_test;") tk.MustExec("drop table if exists t, t1, t2, t3;") @@ -2568,8 +2644,10 @@ func queryIndexOnTable(dbName, tableName string) string { return fmt.Sprintf("select distinct index_name, is_visible from information_schema.statistics where table_schema = '%s' and table_name = '%s' order by index_name", dbName, tableName) } -func (s *testIntegrationSuite5) TestDropColumnWithCompositeIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropColumnWithCompositeIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) query := queryIndexOnTable("drop_composite_index_test", "t_drop_column_with_comp_idx") tk.MustExec("create database if not exists drop_composite_index_test") tk.MustExec("use drop_composite_index_test") @@ -2585,60 +2663,70 @@ func (s *testIntegrationSuite5) TestDropColumnWithCompositeIndex(c *C) { tk.MustQuery(query).Check(testkit.Rows("idx_b NO", "idx_bc NO")) } -func (s *testIntegrationSuite5) TestDropColumnWithIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestDropColumnWithIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t_drop_column_with_idx(a int, b int, c int)") defer tk.MustExec("drop table if exists t_drop_column_with_idx") tk.MustExec("create index idx on t_drop_column_with_idx(b)") tk.MustExec("alter table t_drop_column_with_idx drop column b") - query := queryIndexOnTable("test_db", "t_drop_column_with_idx") + query := queryIndexOnTable("test", "t_drop_column_with_idx") tk.MustQuery(query).Check(testkit.Rows()) } -func (s *testIntegrationSuite5) TestDropColumnWithMultiIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestDropColumnWithMultiIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t_drop_column_with_idx(a int, b int, c int)") defer tk.MustExec("drop table if exists t_drop_column_with_idx") tk.MustExec("create index idx_1 on t_drop_column_with_idx(b)") tk.MustExec("create index idx_2 on t_drop_column_with_idx(b)") tk.MustExec("alter table t_drop_column_with_idx drop column b") - query := queryIndexOnTable("test_db", "t_drop_column_with_idx") + query := queryIndexOnTable("test", "t_drop_column_with_idx") tk.MustQuery(query).Check(testkit.Rows()) } -func (s *testIntegrationSuite5) TestDropColumnsWithMultiIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestDropColumnsWithMultiIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t_drop_columns_with_idx(a int, b int, c int)") defer tk.MustExec("drop table if exists t_drop_columns_with_idx") tk.MustExec("create index idx_1 on t_drop_columns_with_idx(b)") tk.MustExec("create index idx_2 on t_drop_columns_with_idx(b)") tk.MustExec("create index idx_3 on t_drop_columns_with_idx(c)") tk.MustExec("alter table t_drop_columns_with_idx drop column b, drop column c") - query := queryIndexOnTable("test_db", "t_drop_columns_with_idx") + query := queryIndexOnTable("test", "t_drop_columns_with_idx") tk.MustQuery(query).Check(testkit.Rows()) } -func (s *testSerialDBSuite) TestDropLastVisibleColumnOrColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") +func TestDropLastVisibleColumnOrColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t_drop_last_column(x int, key((1+1)))") _, err := tk.Exec("alter table t_drop_last_column drop column x") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1113]A table must have at least 1 column") + require.Error(t, err) + require.Equal(t, "[ddl:1113]A table must have at least 1 column", err.Error()) // for visible columns tk.MustExec("create table t_drop_last_columns(x int, y int, key((1+1)))") _, err = tk.Exec("alter table t_drop_last_columns drop column x, drop column y") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1113]A table must have at least 1 column") + require.Error(t, err) + require.Equal(t, "[ddl:1113]A table must have at least 1 column", err.Error()) tk.MustExec("drop table if exists t_drop_last_column, t_drop_last_columns") } -func (s *testSerialDBSuite1) TestAutoIncrementTableOption(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoIncrementTableOption(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_auto_inc_table_opt;") tk.MustExec("create database test_auto_inc_table_opt;") tk.MustExec("use test_auto_inc_table_opt;") @@ -2656,15 +2744,17 @@ func (s *testSerialDBSuite1) TestAutoIncrementTableOption(c *C) { tk.MustQuery("select * from t;").Check(testkit.Rows("12345678901234567890")) } -func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoIncrementForce(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists auto_inc_force;") tk.MustExec("create database auto_inc_force;") tk.MustExec("use auto_inc_force;") getNextGlobalID := func() uint64 { gidStr := tk.MustQuery("show table t next_row_id").Rows()[0][3] gid, err := strconv.ParseUint(gidStr.(string), 10, 64) - c.Assert(err, IsNil) + require.NoError(t, err) return gid } // Rebase _tidb_row_id. @@ -2675,10 +2765,10 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { // Cannot set next global ID to 0. tk.MustGetErrCode("alter table t force auto_increment = 0;", errno.ErrAutoincReadFailed) tk.MustExec("alter table t force auto_increment = 1;") - c.Assert(getNextGlobalID(), Equals, uint64(1)) + require.Equal(t, uint64(1), getNextGlobalID()) // inserting new rows can overwrite the existing data. tk.MustExec("insert into t values (3);") - c.Assert(tk.ExecToErr("insert into t values (3);").Error(), Equals, "[kv:1062]Duplicate entry '2' for key 'PRIMARY'") + require.Equal(t, "[kv:1062]Duplicate entry '2' for key 'PRIMARY'", tk.ExecToErr("insert into t values (3);").Error()) tk.MustQuery("select a, _tidb_rowid from t;").Check(testkit.Rows("3 1", "1 2", "2 3")) // Rebase auto_increment. @@ -2687,11 +2777,11 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { tk.MustExec("insert into t values (1, 1);") tk.MustExec("insert into t values (100000000, 1);") tk.MustExec("delete from t where a = 100000000;") - c.Assert(getNextGlobalID(), Greater, uint64(100000000)) + require.Greater(t, getNextGlobalID(), uint64(100000000)) // Cannot set next global ID to 0. tk.MustGetErrCode("alter table t /*T![force_inc] force */ auto_increment = 0;", errno.ErrAutoincReadFailed) tk.MustExec("alter table t /*T![force_inc] force */ auto_increment = 2;") - c.Assert(getNextGlobalID(), Equals, uint64(2)) + require.Equal(t, uint64(2), getNextGlobalID()) tk.MustExec("insert into t(b) values (2);") tk.MustQuery("select a, b from t;").Check(testkit.Rows("1 1", "2 2")) @@ -2702,11 +2792,11 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { tk.MustExec("set @@allow_auto_random_explicit_insert = true") tk.MustExec("insert into t values (100000000);") tk.MustExec("delete from t where a = 100000000;") - c.Assert(getNextGlobalID(), Greater, uint64(100000000)) + require.Greater(t, getNextGlobalID(), uint64(100000000)) // Cannot set next global ID to 0. tk.MustGetErrCode("alter table t force auto_random_base = 0;", errno.ErrAutoincReadFailed) tk.MustExec("alter table t force auto_random_base = 2;") - c.Assert(getNextGlobalID(), Equals, uint64(2)) + require.Equal(t, uint64(2), getNextGlobalID()) tk.MustExec("insert into t values ();") tk.MustQuery("select (a & 3) from t order by 1;").Check(testkit.Rows("1", "2")) @@ -2718,7 +2808,7 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { lastBase := fmt.Sprintf("%d", bases[len(bases)-1]) for _, b := range bases { tk.MustExec(fmt.Sprintf("alter table t force auto_increment = %d;", b)) - c.Assert(getNextGlobalID(), Equals, b) + require.Equal(t, b, getNextGlobalID()) } tk.MustExec("insert into t values ();") tk.MustQuery("select a from t;").Check(testkit.Rows("1", lastBase)) @@ -2727,7 +2817,7 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { tk.MustExec("create table t (a bigint unsigned primary key auto_increment);") for _, b := range bases { tk.MustExec(fmt.Sprintf("alter table t force auto_increment = %d;", b)) - c.Assert(getNextGlobalID(), Equals, b) + require.Equal(t, b, getNextGlobalID()) tk.MustExec("insert into t values ();") tk.MustQuery("select a from t;").Check(testkit.Rows(fmt.Sprintf("%d", b))) tk.MustExec("delete from t;") @@ -2744,10 +2834,29 @@ func (s *testIntegrationSuite3) TestAutoIncrementForce(c *C) { tk.MustQuery("select * from t;").Check(testkit.Rows("101", "112", "500")) tk.MustQuery("select * from t order by a;").Check(testkit.Rows("101", "112", "500")) tk.MustExec("drop table if exists t;") + + // Check for warning in case we can't set the auto_increment to the desired value + tk.MustExec("create table t(a int primary key auto_increment)") + tk.MustExec("insert into t values (200)") + tk.MustQuery("show create table t").Check(testkit.Rows( + "t CREATE TABLE `t` (\n" + + " `a` int(11) NOT NULL AUTO_INCREMENT,\n" + + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=5201")) + tk.MustExec("alter table t auto_increment=100;") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Can't reset AUTO_INCREMENT to 100 without FORCE option, using 5201 instead")) + tk.MustQuery("show create table t").Check(testkit.Rows( + "t CREATE TABLE `t` (\n" + + " `a` int(11) NOT NULL AUTO_INCREMENT,\n" + + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=5201")) + tk.MustExec("drop table t") } -func (s *testIntegrationSuite3) TestIssue20490(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20490(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("create table issue20490 (a int);") tk.MustExec("insert into issue20490(a) values(1);") @@ -2759,8 +2868,10 @@ func (s *testIntegrationSuite3) TestIssue20490(c *C) { tk.MustQuery("select b from issue20490 order by a;").Check(testkit.Rows("1", "1", "")) } -func (s *testIntegrationSuite3) TestIssue20741WithEnumField(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20741WithEnumField(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists issue20741") tk.MustExec("create table issue20741(id int primary key, c int)") @@ -2772,8 +2883,10 @@ func (s *testIntegrationSuite3) TestIssue20741WithEnumField(c *C) { tk.MustQuery("select * from issue20741 where cc = 1").Check(testkit.Rows("1 2 a", "2 2 a")) } -func (s *testIntegrationSuite3) TestIssue20741WithSetField(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20741WithSetField(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists issue20741_2") tk.MustExec("create table issue20741_2(id int primary key, c int)") @@ -2784,44 +2897,50 @@ func (s *testIntegrationSuite3) TestIssue20741WithSetField(c *C) { tk.MustQuery("select * from issue20741_2 where cc = 0").Check(testkit.Rows("1 2 ", "2 2 ")) tk.MustQuery("select * from issue20741_2 where cc = 1").Check(testkit.Rows()) _, err := tk.Exec("insert into issue20741_2(id, c) values (3, 3)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[table:1364]Field 'cc' doesn't have a default value") + require.Error(t, err) + require.Equal(t, "[table:1364]Field 'cc' doesn't have a default value", err.Error()) } // TestDefaultValueIsLatin1 for issue #18977 -func (s *testIntegrationSuite3) TestEnumAndSetDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnumAndSetDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (a enum(0x61, 'b') not null default 0x61, b set(0x61, 'b') not null default 0x61) character set latin1") - tbl := testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl.Meta().Columns[0].DefaultValue, Equals, "a") - c.Assert(tbl.Meta().Columns[1].DefaultValue, Equals, "a") + tbl := external.GetTableByName(t, tk, "test", "t") + require.Equal(t, "a", tbl.Meta().Columns[0].DefaultValue) + require.Equal(t, "a", tbl.Meta().Columns[1].DefaultValue) tk.MustExec("drop table t") tk.MustExec("create table t (a enum(0x61, 'b') not null default 0x61, b set(0x61, 'b') not null default 0x61) character set utf8mb4") - tbl = testGetTableByName(c, s.ctx, "test", "t") - c.Assert(tbl.Meta().Columns[0].DefaultValue, Equals, "a") - c.Assert(tbl.Meta().Columns[1].DefaultValue, Equals, "a") + tbl = external.GetTableByName(t, tk, "test", "t") + require.Equal(t, "a", tbl.Meta().Columns[0].DefaultValue) + require.Equal(t, "a", tbl.Meta().Columns[1].DefaultValue) } -func (s *testIntegrationSuite3) TestStrictDoubleTypeCheck(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStrictDoubleTypeCheck(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_strict_double_type_check = 'ON'") sql := "create table double_type_check(id int, c double(10));" _, err := tk.Exec(sql) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[parser:1149]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use") + require.Error(t, err) + require.Equal(t, "[parser:1149]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use", err.Error()) tk.MustExec("set @@tidb_enable_strict_double_type_check = 'OFF'") defer tk.MustExec("set @@tidb_enable_strict_double_type_check = 'ON'") tk.MustExec(sql) } -func (s *testSerialDBSuite) TestDuplicateErrorMessage(c *C) { - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestDuplicateErrorMessage(t *testing.T) { + defer collate.SetNewCollationEnabledForTest(true) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") type testdata struct { @@ -2844,7 +2963,7 @@ func (s *testSerialDBSuite) TestDuplicateErrorMessage(c *C) { conf.EnableGlobalIndex = globalIndex }) for _, clusteredIndex := range []variable.ClusteredIndexDefMode{variable.ClusteredIndexDefModeOn, variable.ClusteredIndexDefModeOff, variable.ClusteredIndexDefModeIntOnly} { - tk.Se.GetSessionVars().EnableClusteredIndex = clusteredIndex + tk.Session().GetSessionVars().EnableClusteredIndex = clusteredIndex for _, t := range tests { tk.MustExec("drop table if exists t;") fields := make([]string, len(t.types)) @@ -2874,29 +2993,35 @@ func (s *testSerialDBSuite) TestDuplicateErrorMessage(c *C) { } } -func (s *testIntegrationSuite3) TestIssue22028(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22028(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") _, err := tk.Exec("create table t(a double(0, 0));") - c.Assert(err.Error(), Equals, "[types:1439]Display width out of range for column 'a' (max = 255)") + require.Equal(t, "[types:1439]Display width out of range for column 'a' (max = 255)", err.Error()) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a double);") _, err = tk.Exec("ALTER TABLE t MODIFY COLUMN a DOUBLE(0,0);") - c.Assert(err.Error(), Equals, "[types:1439]Display width out of range for column 'a' (max = 255)") + require.Equal(t, "[types:1439]Display width out of range for column 'a' (max = 255)", err.Error()) } -func (s *testIntegrationSuite3) TestIssue21835(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue21835(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") _, err := tk.Exec("create table t( col decimal(1,2) not null default 0);") - c.Assert(err.Error(), Equals, "[types:1427]For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 'col').") + require.Equal(t, "[types:1427]For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 'col').", err.Error()) } -func (s *testIntegrationSuite3) TestCreateTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") @@ -2935,7 +3060,7 @@ func (s *testIntegrationSuite3) TestCreateTemporaryTable(c *C) { tk.MustQuery("select * from t1") // No error tk.MustExec("drop database tmp_db") _, err := tk.Exec("select * from t1") - c.Assert(err, NotNil) + require.Error(t, err) // In MySQL, drop DB does not really drop the table, it's back! tk.MustExec("create database tmp_db") tk.MustExec("use tmp_db") @@ -2945,7 +3070,7 @@ func (s *testIntegrationSuite3) TestCreateTemporaryTable(c *C) { tk.MustExec("create table overlap (id int)") tk.MustExec("create temporary table overlap (a int, b int)") _, err = tk.Exec("insert into overlap values (1)") // column not match - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("insert into overlap values (1, 1)") // Check create local temporary table does not auto commit the transaction. @@ -2962,7 +3087,7 @@ func (s *testIntegrationSuite3) TestCreateTemporaryTable(c *C) { // Check create temporary table for if not exists tk.MustExec("create temporary table b_local_temp_table (id int)") _, err = tk.Exec("create temporary table b_local_temp_table (id int)") - c.Assert(infoschema.ErrTableExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableExists.Equal(err)) tk.MustExec("create temporary table if not exists b_local_temp_table (id int)") // Stale read see the local temporary table but can't read on it. @@ -2980,8 +3105,10 @@ func (s *testIntegrationSuite3) TestCreateTemporaryTable(c *C) { tk.MustExec(updateSafePoint) } -func (s *testIntegrationSuite3) TestAccessLocalTmpTableAfterDropDB(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAccessLocalTmpTableAfterDropDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists tmpdb") tk.MustExec("create temporary table tmpdb.tmp(id int)") tk.MustExec("drop database tmpdb") @@ -3063,8 +3190,10 @@ func (s *testIntegrationSuite3) TestAccessLocalTmpTableAfterDropDB(c *C) { executeTests() } -func (s *testSerialDBSuite) TestPlacementOnTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPlacementOnTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test.tplacement1, db2.t1, db2.tplacement3, db2.tplacement5") tk.MustExec("drop database if exists db2") @@ -3073,23 +3202,14 @@ func (s *testSerialDBSuite) TestPlacementOnTemporaryTable(c *C) { defer tk.MustExec("drop placement policy x") // Cannot create temporary table with placement options - tk.MustGetErrCode("create global temporary table tplacement1 (id int) followers=4 on commit delete rows", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("create global temporary table tplacement1 (id int) primary_region='us-east-1' regions='us-east-1,us-west-1' on commit delete rows", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("create global temporary table tplacement1 (id int) placement policy='x' on commit delete rows", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("create temporary table tplacement2 (id int) followers=4", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("create temporary table tplacement2 (id int) primary_region='us-east-1' regions='us-east-1,us-west-1'", errno.ErrOptOnTemporaryTable) tk.MustGetErrCode("create temporary table tplacement2 (id int) placement policy='x'", errno.ErrOptOnTemporaryTable) // Cannot alter temporary table with placement options tk.MustExec("create global temporary table tplacement1 (id int) on commit delete rows") defer tk.MustExec("drop table tplacement1") - tk.MustGetErrCode("alter table tplacement1 followers=4", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("alter table tplacement1 primary_region='us-east-1' regions='us-east-1,us-west-1'", errno.ErrOptOnTemporaryTable) tk.MustGetErrCode("alter table tplacement1 placement policy='x'", errno.ErrOptOnTemporaryTable) tk.MustExec("create temporary table tplacement2 (id int)") - tk.MustGetErrCode("alter table tplacement2 followers=4", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table tplacement2 primary_region='us-east-1' regions='us-east-1,us-west-1'", errno.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table tplacement2 placement policy='x'", errno.ErrUnsupportedDDLOperation) // Temporary table will not inherit placement from db @@ -3131,11 +3251,13 @@ func (s *testSerialDBSuite) TestPlacementOnTemporaryTable(c *C) { )) } -func (s *testIntegrationSuite3) TestAvoidCreateViewOnLocalTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAvoidCreateViewOnLocalTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) tk.MustExec("drop table if exists tt0") tk.MustExec("drop table if exists tt1") tk.MustExec("drop table if exists tt2") @@ -3147,55 +3269,55 @@ func (s *testIntegrationSuite3) TestAvoidCreateViewOnLocalTemporaryTable(c *C) { checkCreateView := func() { _, err := tk.Exec("create view v1 as select * from tt1") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v1' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v1' doesn't exist", err.Error()) _, err = tk.Exec("create view v1 as select * from (select * from tt1) as tt") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v1' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v1' doesn't exist", err.Error()) _, err = tk.Exec("create view v2 as select * from tt0 union select * from tt1") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v2") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v2' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v2' doesn't exist", err.Error()) _, err = tk.Exec("create view v3 as select * from tt0, tt1 where tt0.a = tt1.a") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v3") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v3' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v3' doesn't exist", err.Error()) _, err = tk.Exec("create view v4 as select a, (select count(1) from tt1 where tt1.a = tt0.a) as tt1a from tt0") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v4") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v4' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v4' doesn't exist", err.Error()) _, err = tk.Exec("create view v5 as select a, (select count(1) from tt1 where tt1.a = 1) as tt1a from tt0") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v5") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v5' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v5' doesn't exist", err.Error()) _, err = tk.Exec("create view v6 as select * from tt0 where tt0.a=(select max(tt1.b) from tt1)") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v6") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v6' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v6' doesn't exist", err.Error()) _, err = tk.Exec("create view v7 as select * from tt0 where tt0.b=(select max(tt1.b) from tt1 where tt0.a=tt1.a)") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) _, err = tk.Exec("select * from v7") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.v7' doesn't exist") + require.Error(t, err) + require.Equal(t, "[schema:1146]Table 'test.v7' doesn't exist", err.Error()) _, err = tk.Exec("create or replace view v0 as select * from tt1") - c.Assert(core.ErrViewSelectTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrViewSelectTemporaryTable.Equal(err)) } checkCreateView() @@ -3206,8 +3328,18 @@ func (s *testIntegrationSuite3) TestAvoidCreateViewOnLocalTemporaryTable(c *C) { checkCreateView() } -func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropTemporaryTable(t *testing.T) { + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + conf.Experimental.AllowsExpressionIndex = true + }) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Check drop temporary table(include meta data and real data. @@ -3215,7 +3347,7 @@ func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) { tk.MustQuery("select * from b_local_temp_table").Check(testkit.Rows()) tk.MustExec("drop table b_local_temp_table") _, err := tk.Exec("select * from b_local_temp_table") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.b_local_temp_table' doesn't exist") + require.Equal(t, "[schema:1146]Table 'test.b_local_temp_table' doesn't exist", err.Error()) // TODO: test drop real data // Check if we have a normal and local temporary table in the same db with the same name, @@ -3225,11 +3357,11 @@ func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) { tk.MustExec("create temporary table if not exists b_table_local_and_normal (id int)") tk.MustQuery("select * from b_table_local_and_normal").Check(testkit.Rows()) tk.MustExec("drop table b_table_local_and_normal") - sequenceTable := testGetTableByName(c, tk.Se, "test", "b_table_local_and_normal") - c.Assert(sequenceTable.Meta().TempTableType, Equals, model.TempTableNone) + sequenceTable := external.GetTableByName(t, tk, "test", "b_table_local_and_normal") + require.Equal(t, model.TempTableNone, sequenceTable.Meta().TempTableType) tk.MustExec("drop table if exists b_table_local_and_normal") _, err = tk.Exec("select * from b_table_local_and_normal") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.b_table_local_and_normal' doesn't exist") + require.Equal(t, "[schema:1146]Table 'test.b_table_local_and_normal' doesn't exist", err.Error()) // Check dropping local temporary tables should not commit current transaction implicitly. tk.MustExec("drop table if exists check_data_normal_table") @@ -3275,30 +3407,26 @@ func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) { tk.MustExec("create table a_normal_table_2 (id int)") defer tk.MustExec("drop table if exists a_normal_table_2") _, err = tk.Exec("drop table a_local_temp_table_3, a_local_temp_table_4, a_local_temp_table_5, a_normal_table_2, a_local_temp_table_6") - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.a_local_temp_table_6'") + require.Equal(t, "[schema:1051]Unknown table 'test.a_local_temp_table_6'", err.Error()) tk.MustExec("drop table if exists check_data_normal_table_3") tk.MustExec("create table check_data_normal_table_3 (id int)") defer tk.MustExec("drop table if exists check_data_normal_table_3") tk.MustExec("create temporary table a_local_temp_table_6 (id int)") _, err = tk.Exec("drop table check_data_normal_table_3, check_data_normal_table_7, a_local_temp_table_6") - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.check_data_normal_table_7'") + require.Equal(t, "[schema:1051]Unknown table 'test.check_data_normal_table_7'", err.Error()) // Check filter out data from removed local temp tables tk.MustExec("create temporary table a_local_temp_table_7 (id int)") - ctx := s.ctx - c.Assert(ctx.NewTxn(context.Background()), IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - defer func() { - err := txn.Rollback() - c.Assert(err, IsNil) - }() - sessionVars := tk.Se.GetSessionVars() + ctx := tk.Session() + require.Nil(t, ctx.NewTxn(context.Background())) + _, err = ctx.Txn(true) + require.NoError(t, err) + sessionVars := tk.Session().GetSessionVars() sessVarsTempTable := sessionVars.LocalTemporaryTables localTemporaryTable := sessVarsTempTable.(*infoschema.LocalTemporaryTables) tbl, exist := localTemporaryTable.TableByName(model.NewCIStr("test"), model.NewCIStr("a_local_temp_table_7")) - c.Assert(exist, IsTrue) + require.True(t, exist) tblInfo := tbl.Meta() tablePrefix := tablecodec.EncodeTablePrefix(tblInfo.ID) endTablePrefix := tablecodec.EncodeTablePrefix(tblInfo.ID + 1) @@ -3311,31 +3439,33 @@ func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) { tk.MustExec("commit") _, err = tk.Exec("select * from a_local_temp_table_7") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.a_local_temp_table_7' doesn't exist") + require.Equal(t, "[schema:1146]Table 'test.a_local_temp_table_7' doesn't exist", err.Error()) memData := sessionVars.TemporaryTableData iter, err := memData.Iter(tablePrefix, endTablePrefix) - c.Assert(err, IsNil) + require.NoError(t, err) for iter.Valid() { key := iter.Key() if !bytes.HasPrefix(key, tablePrefix) { break } value := iter.Value() - c.Assert(len(value), Equals, 0) + require.Equal(t, 0, len(value)) _ = iter.Next() } - c.Assert(iter.Valid(), IsFalse) + require.False(t, iter.Valid()) // Check drop not exists table in transaction. tk.MustExec("begin") tk.MustExec("create temporary table a_local_temp_table_8 (id int)") _, err = tk.Exec("drop table a_local_temp_table_8, a_local_temp_table_9_not_exist") - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.a_local_temp_table_9_not_exist'") + require.Equal(t, "[schema:1051]Unknown table 'test.a_local_temp_table_9_not_exist'", err.Error()) tk.MustQuery("select * from a_local_temp_table_8").Check(testkit.Rows()) } -func (s *testIntegrationSuite3) TestDropWithGlobalTemporaryTableKeyWord(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropWithGlobalTemporaryTableKeyWord(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") clearSQL := "drop table if exists tb, tb2, temp, temp1, ltemp1, ltemp2" tk.MustExec(clearSQL) @@ -3352,51 +3482,51 @@ func (s *testIntegrationSuite3) TestDropWithGlobalTemporaryTableKeyWord(c *C) { // testing for drop table which is not global temporary err := tk.ExecToErr("drop global temporary table tb") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table test.tb") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table ltemp1") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table test.ltemp1") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table ltemp1, temp") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table temp, ltemp1") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table xxx, ltemp1") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table xxx") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) // testing for drop table if exists which is not global temporary err = tk.ExecToErr("drop global temporary table if exists tb") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table if exists ltemp1") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) tk.MustExec("drop global temporary table if exists xxx") tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.xxx'")) err = tk.ExecToErr("drop global temporary table if exists xxx,tb") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) err = tk.ExecToErr("drop global temporary table if exists test.tb") - c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue) + require.True(t, core.ErrDropTableOnTemporaryTable.Equal(err)) // testing for drop global temporary table successfully tk.MustExec("drop global temporary table temp") err = tk.ExecToErr("select * from temp") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("drop global temporary table test.temp1") err = tk.ExecToErr("select * from temp2") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("create global temporary table temp (id int) on commit delete rows") tk.MustExec("create global temporary table temp1 (id int) on commit delete rows") tk.MustExec("drop global temporary table temp, temp1") err = tk.ExecToErr("select * from temp") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) err = tk.ExecToErr("select * from temp1") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("create global temporary table temp (id int) on commit delete rows") tk.MustExec("create global temporary table temp1 (id int) on commit delete rows") @@ -3404,11 +3534,13 @@ func (s *testIntegrationSuite3) TestDropWithGlobalTemporaryTableKeyWord(c *C) { tk.MustExec("drop global temporary table if exists temp") tk.MustQuery("show warnings").Check(testkit.Rows()) err = tk.ExecToErr("select * from temp") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) } -func (s *testIntegrationSuite3) TestDropWithLocalTemporaryTableKeyWord(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropWithLocalTemporaryTableKeyWord(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") clearSQL := "drop table if exists tb, tb2, temp, temp1, ltemp1, ltemp2, testt.ltemp3" tk.MustExec(clearSQL) @@ -3430,21 +3562,21 @@ func (s *testIntegrationSuite3) TestDropWithLocalTemporaryTableKeyWord(c *C) { // testing for drop table which is not local temporary err := tk.ExecToErr("drop temporary table tb") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table test.tb") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table temp1") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table test.temp1") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table ltemp1, tb") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table temp, ltemp1") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table xxx, ltemp1") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) err = tk.ExecToErr("drop temporary table xxx") - c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableDropExists.Equal(err)) // testing for drop table if exists which is not local temporary tk.MustExec("drop temporary table if exists xxx") @@ -3465,11 +3597,11 @@ func (s *testIntegrationSuite3) TestDropWithLocalTemporaryTableKeyWord(c *C) { // testing for drop temporary table successfully tk.MustExec("drop temporary table ltemp1") err = tk.ExecToErr("select * from ltemp1") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("drop temporary table test.ltemp2") err = tk.ExecToErr("select * from ltemp2") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("drop temporary table tb2") tk.MustQuery("select * from tb2").Check(testkit.Rows("1")) @@ -3479,18 +3611,20 @@ func (s *testIntegrationSuite3) TestDropWithLocalTemporaryTableKeyWord(c *C) { tk.MustExec("drop temporary table testt.ltemp3, ltemp1") err = tk.ExecToErr("select * from testt.ltemp3") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) err = tk.ExecToErr("select * from ltemp1") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) tk.MustExec("drop temporary table if exists ltemp2") tk.MustQuery("show warnings").Check(testkit.Rows()) err = tk.ExecToErr("select * from ltemp2") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) } -func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateLocalTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, tn") @@ -3554,28 +3688,28 @@ func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) { tk.MustExec("create temporary table t1 (id int primary key auto_increment)") // truncate temporary table will clear session data - localTemporaryTables := tk.Se.GetSessionVars().LocalTemporaryTables.(*infoschema.LocalTemporaryTables) + localTemporaryTables := tk.Session().GetSessionVars().LocalTemporaryTables.(*infoschema.LocalTemporaryTables) tb1, exist := localTemporaryTables.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) tbl1Info := tb1.Meta() tablePrefix := tablecodec.EncodeTablePrefix(tbl1Info.ID) endTablePrefix := tablecodec.EncodeTablePrefix(tbl1Info.ID + 1) - c.Assert(exist, IsTrue) + require.True(t, exist) tk.MustExec("insert into t1 values(1), (2), (3)") tk.MustExec("begin") tk.MustExec("insert into t1 values(5), (6), (7)") tk.MustExec("truncate table t1") - iter, err := tk.Se.GetSessionVars().TemporaryTableData.Iter(tablePrefix, endTablePrefix) - c.Assert(err, IsNil) + iter, err := tk.Session().GetSessionVars().TemporaryTableData.Iter(tablePrefix, endTablePrefix) + require.NoError(t, err) for iter.Valid() { key := iter.Key() if !bytes.HasPrefix(key, tablePrefix) { break } value := iter.Value() - c.Assert(len(value), Equals, 0) + require.Equal(t, 0, len(value)) _ = iter.Next() } - c.Assert(iter.Valid(), IsFalse) + require.False(t, iter.Valid()) // truncate after drop database should be successful tk.MustExec("create temporary table testt.t3 (id int)") @@ -3585,9 +3719,11 @@ func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) { tk.MustQuery("select * from testt.t3").Check(testkit.Rows()) } -func (s *testIntegrationSuite3) TestIssue29282(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk1 := testkit.NewTestKit(c, s.store) +func TestIssue29282(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk1 := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists issue29828_t") tk.MustExec("create table issue29828_t (id int)") @@ -3609,6 +3745,7 @@ func (s *testIntegrationSuite3) TestIssue29282(c *C) { // This query should block. tk1.MustQuery("select * from issue29828_t where id = 1 for update;").Check(testkit.Rows("1")) ch <- struct{}{} + tk1.MustExec("rollback") }() select { @@ -3617,28 +3754,39 @@ func (s *testIntegrationSuite3) TestIssue29282(c *C) { tk.MustExec("rollback") case <-ch: // Unexpected, test fail. - c.Fail() + t.Fail() + } + + // Wait the background query rollback + select { + case <-time.After(100 * time.Millisecond): + t.Fail() + case <-ch: } } // See https://github.com/pingcap/tidb/issues/29327 -func (s *testIntegrationSuite3) TestEnumDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnumDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") - tk.MustExec("CREATE TABLE `t1` ( `a` enum('','a','b') NOT NULL DEFAULT 'b' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;") + tk.MustExec("CREATE TABLE `t1` ( `a` enum('','a','b') NOT NULL DEFAULT 'b' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;") tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + - " `a` enum('','a','b') COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'b'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci")) + " `a` enum('','a','b') COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'b'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci")) tk.MustExec("drop table if exists t1;") - tk.MustExec("CREATE TABLE `t1` ( `a` enum('','a','b') NOT NULL DEFAULT 'b ' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;") + tk.MustExec("CREATE TABLE `t1` ( `a` enum('','a','b') NOT NULL DEFAULT 'b ' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;") tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + - " `a` enum('','a','b') COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'b'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci")) + " `a` enum('','a','b') COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'b'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci")) } -func (s *testIntegrationSuite3) TestIssue29326(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue29326(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") @@ -3656,33 +3804,33 @@ func (s *testIntegrationSuite3) TestIssue29326(c *C) { tk.MustExec("create view v1 as select 1,1") rs, err := tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "1") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "Name_exp_1") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1")) + require.Equal(t, "1", rs.Fields()[0].Column.Name.O) + require.Equal(t, "Name_exp_1", rs.Fields()[1].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create view v1 as select 1, 2, 1, 2, 1, 2, 1, 2") rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 2 1 2 1 2 1 2")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "1") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "2") - c.Assert(rs.Fields()[2].Column.Name.O, Equals, "Name_exp_1") - c.Assert(rs.Fields()[3].Column.Name.O, Equals, "Name_exp_2") - c.Assert(rs.Fields()[4].Column.Name.O, Equals, "Name_exp_1_1") - c.Assert(rs.Fields()[5].Column.Name.O, Equals, "Name_exp_1_2") - c.Assert(rs.Fields()[6].Column.Name.O, Equals, "Name_exp_2_1") - c.Assert(rs.Fields()[7].Column.Name.O, Equals, "Name_exp_2_2") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 2 1 2 1 2 1 2")) + require.Equal(t, "1", rs.Fields()[0].Column.Name.O) + require.Equal(t, "2", rs.Fields()[1].Column.Name.O) + require.Equal(t, "Name_exp_1", rs.Fields()[2].Column.Name.O) + require.Equal(t, "Name_exp_2", rs.Fields()[3].Column.Name.O) + require.Equal(t, "Name_exp_1_1", rs.Fields()[4].Column.Name.O) + require.Equal(t, "Name_exp_1_2", rs.Fields()[5].Column.Name.O) + require.Equal(t, "Name_exp_2_1", rs.Fields()[6].Column.Name.O) + require.Equal(t, "Name_exp_2_2", rs.Fields()[7].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create view v1 as select 't', 't', 1 as t") rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("t t 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "Name_exp_t") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "Name_exp_1_t") - c.Assert(rs.Fields()[2].Column.Name.O, Equals, "t") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("t t 1")) + require.Equal(t, "Name_exp_t", rs.Fields()[0].Column.Name.O) + require.Equal(t, "Name_exp_1_t", rs.Fields()[1].Column.Name.O) + require.Equal(t, "t", rs.Fields()[2].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create definer=`root`@`127.0.0.1` view v1 as select 1, 1 union all select 1, 1") @@ -3691,10 +3839,10 @@ func (s *testIntegrationSuite3) TestIssue29326(c *C) { "AS SELECT 1 AS `1`,1 AS `Name_exp_1` UNION ALL SELECT 1 AS `1`,1 AS `1` " + "utf8mb4 utf8mb4_bin")) rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1", "1 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "1") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "Name_exp_1") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1", "1 1")) + require.Equal(t, "1", rs.Fields()[0].Column.Name.O) + require.Equal(t, "Name_exp_1", rs.Fields()[1].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create definer=`root`@`127.0.0.1` view v1 as select 'id', id from t1") @@ -3703,10 +3851,10 @@ func (s *testIntegrationSuite3) TestIssue29326(c *C) { "AS SELECT _UTF8MB4'id' AS `Name_exp_id`,`id` AS `id` FROM `test`.`t1` " + "utf8mb4 utf8mb4_bin")) rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("id 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "Name_exp_id") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "id") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("id 1")) + require.Equal(t, "Name_exp_id", rs.Fields()[0].Column.Name.O) + require.Equal(t, "id", rs.Fields()[1].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create definer=`root`@`127.0.0.1` view v1 as select 1, (select id from t1 where t1.id=t2.id) as '1' from t2") @@ -3715,10 +3863,10 @@ func (s *testIntegrationSuite3) TestIssue29326(c *C) { "AS SELECT 1 AS `Name_exp_1`,(SELECT `id` AS `id` FROM `test`.`t1` WHERE `t1`.`id`=`t2`.`id`) AS `1` FROM `test`.`t2` " + "utf8mb4 utf8mb4_bin")) rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "Name_exp_1") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "1") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1")) + require.Equal(t, "Name_exp_1", rs.Fields()[0].Column.Name.O) + require.Equal(t, "1", rs.Fields()[1].Column.Name.O) tk.MustExec("drop view if exists v1") tk.MustExec("create definer=`root`@`127.0.0.1` view v1 as select 1 as 'abs(t1.id)', abs(t1.id) from t1") @@ -3727,24 +3875,72 @@ func (s *testIntegrationSuite3) TestIssue29326(c *C) { "AS SELECT 1 AS `abs(t1.id)`,ABS(`t1`.`id`) AS `Name_exp_abs(t1.id)` FROM `test`.`t1` " + "utf8mb4 utf8mb4_bin")) rs, err = tk.Exec("select * from v1") - c.Assert(err, IsNil) - tk.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1")) - c.Assert(rs.Fields()[0].Column.Name.O, Equals, "abs(t1.id)") - c.Assert(rs.Fields()[1].Column.Name.O, Equals, "Name_exp_abs(t1.id)") + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1")) + require.Equal(t, "abs(t1.id)", rs.Fields()[0].Column.Name.O) + require.Equal(t, "Name_exp_abs(t1.id)", rs.Fields()[1].Column.Name.O) tk.MustExec("drop view if exists v1") err = tk.ExecToErr("create definer=`root`@`127.0.0.1` view v1 as select 1 as t,1 as t") - c.Assert(infoschema.ErrColumnExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrColumnExists.Equal(err)) tk.MustExec("drop view if exists v1") err = tk.ExecToErr("create definer=`root`@`127.0.0.1` view v1 as select 1 as id, id from t1") - c.Assert(infoschema.ErrColumnExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrColumnExists.Equal(err)) tk.MustExec("drop view if exists v1") err = tk.ExecToErr("create definer=`root`@`127.0.0.1` view v1 as select * from t1 left join t2 on t1.id=t2.id") - c.Assert(infoschema.ErrColumnExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrColumnExists.Equal(err)) tk.MustExec("drop view if exists v1") err = tk.ExecToErr("create definer=`root`@`127.0.0.1` view v1 as select t1.id, t2.id from t1,t2 where t1.id=t2.id") - c.Assert(infoschema.ErrColumnExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrColumnExists.Equal(err)) +} + +func TestInvalidPartitionNameWhenCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("create database invalidPartitionNames") + defer tk.MustExec("drop database invalidPartitionNames") + tk.MustExec("USE invalidPartitionNames") + + _, err := tk.Exec("create table t(a int) partition by range (a) (partition p0 values less than (0), partition `p1 ` values less than (3))") + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, dbterror.ErrWrongPartitionName), "err %v", err) + + _, err = tk.Exec("create table t(a int) partition by range (a) (partition `` values less than (0), partition `p1` values less than (3))") + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, dbterror.ErrWrongPartitionName), "err %v", err) + + tk.MustExec("create table t(a int) partition by range (a) (partition `p0` values less than (0), partition `p1` values less than (3))") + _, err = tk.Exec("alter table t add partition (partition `p2 ` values less than (5))") + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, dbterror.ErrWrongPartitionName), "err %v", err) +} + +func TestDDLLastInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test;`) + tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.query'), json_extract(@@tidb_last_ddl_info, '$.seq_num')").Check(testkit.Rows("\"\" 0")) + tk.MustExec("create table t(a int)") + firstSequence := 0 + res := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.query'), json_extract(@@tidb_last_ddl_info, '$.seq_num')") + require.Len(t, res.Rows(), 1) + require.Equal(t, "\"create table t(a int)\"", res.Rows()[0][0]) + var err error + firstSequence, err = strconv.Atoi(fmt.Sprintf("%v", res.Rows()[0][1])) + require.NoError(t, err) + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec(`use test;`) + tk.MustExec("create table t2(a int)") + tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.query'), json_extract(@@tidb_last_ddl_info, '$.seq_num')").Check(testkit.Rows(fmt.Sprintf("\"create table t2(a int)\" %d", firstSequence+1))) + + tk.MustExec("drop table t, t2") + tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.query'), json_extract(@@tidb_last_ddl_info, '$.seq_num')").Check(testkit.Rows(fmt.Sprintf("\"drop table t, t2\" %d", firstSequence+3))) } diff --git a/ddl/db_partition_test.go b/ddl/db_partition_test.go index 647c421ab6b0d..58a644a6ff3ce 100644 --- a/ddl/db_partition_test.go +++ b/ddl/db_partition_test.go @@ -21,9 +21,9 @@ import ( "math/rand" "strings" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" @@ -44,18 +44,51 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/israce" + "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" "go.uber.org/zap" ) -func (s *testIntegrationSuite3) TestCreateTableWithPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func checkGlobalIndexCleanUpDone(t *testing.T, ctx sessionctx.Context, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, pid int64) int { + require.NoError(t, ctx.NewTxn(context.Background())) + txn, err := ctx.Txn(true) + require.NoError(t, err) + defer func() { + err := txn.Rollback() + require.NoError(t, err) + }() + + cnt := 0 + prefix := tablecodec.EncodeTableIndexPrefix(tblInfo.ID, idxInfo.ID) + it, err := txn.Iter(prefix, nil) + require.NoError(t, err) + for it.Valid() { + if !it.Key().HasPrefix(prefix) { + break + } + segs := tablecodec.SplitIndexValue(it.Value()) + require.NotNil(t, segs.PartitionID) + _, pi, err := codec.DecodeInt(segs.PartitionID) + require.NoError(t, err) + require.NotEqual(t, pid, pi) + cnt++ + err = it.Next() + require.NoError(t, err) + } + return cnt +} + +func TestCreateTableWithPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists tp;") tk.MustExec(`CREATE TABLE tp (a int) PARTITION BY RANGE(a) ( @@ -63,24 +96,24 @@ func (s *testIntegrationSuite3) TestCreateTableWithPartition(c *C) { PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (MAXVALUE) );`) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type, Equals, model.PartitionTypeRange) - c.Assert(part.Expr, Equals, "`a`") + require.Equal(t, model.PartitionTypeRange, part.Type) + require.Equal(t, "`a`", part.Expr) for _, pdef := range part.Definitions { - c.Assert(pdef.ID, Greater, int64(0)) + require.Greater(t, pdef.ID, int64(0)) } - c.Assert(part.Definitions, HasLen, 3) - c.Assert(part.Definitions[0].LessThan[0], Equals, "10") - c.Assert(part.Definitions[0].Name.L, Equals, "p0") - c.Assert(part.Definitions[1].LessThan[0], Equals, "20") - c.Assert(part.Definitions[1].Name.L, Equals, "p1") - c.Assert(part.Definitions[2].LessThan[0], Equals, "MAXVALUE") - c.Assert(part.Definitions[2].Name.L, Equals, "p2") + require.Len(t, part.Definitions, 3) + require.Equal(t, "10", part.Definitions[0].LessThan[0]) + require.Equal(t, "p0", part.Definitions[0].Name.L) + require.Equal(t, "20", part.Definitions[1].LessThan[0]) + require.Equal(t, "p1", part.Definitions[1].Name.L) + require.Equal(t, "MAXVALUE", part.Definitions[2].LessThan[0]) + require.Equal(t, "p2", part.Definitions[2].Name.L) tk.MustExec("drop table if exists employees;") sql1 := `create table employees ( @@ -138,7 +171,7 @@ func (s *testIntegrationSuite3) TestCreateTableWithPartition(c *C) { partition p3 values less than (65,30,13), partition p4 values less than (maxvalue,30,40) );`) - c.Assert(err, IsNil) + require.NoError(t, err) sql6 := `create table employees ( id int not null, @@ -191,7 +224,7 @@ func (s *testIntegrationSuite3) TestCreateTableWithPartition(c *C) { partition p2 values less than (20), partition p3 values less than (20) );`) - c.Assert(ddl.ErrRangeNotIncreasing.Equal(err), IsTrue) + require.True(t, dbterror.ErrRangeNotIncreasing.Equal(err)) tk.MustGetErrCode(`create TABLE t10 (c1 int,c2 int) partition by range(c1 / c2 ) (partition p0 values less than (2));`, tmysql.ErrPartitionFunctionIsNotAllowed) @@ -307,8 +340,10 @@ partition by range (a) partition p2 values less than maxvalue)`) } -func (s *testIntegrationSuite2) TestCreateTableWithHashPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithHashPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists employees;") tk.MustExec("set @@session.tidb_enable_table_partition = 1") @@ -364,10 +399,10 @@ func (s *testIntegrationSuite2) TestCreateTableWithHashPartition(c *C) { tk.MustExec("create table t4 (a int, b int) partition by hash(floor(a-b)) partitions 10") } -func (s *testSerialDBSuite1) TestCreateTableWithRangeColumnPartition(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithRangeColumnPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists log_message_1;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -415,15 +450,15 @@ create table log_message_1 ( }, { "create table t(a datetime) partition by range columns (a) (partition p1 values less than ('2000-02-01'), partition p2 values less than ('20000102'));", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, }, { "create table t(a time) partition by range columns (a) (partition p1 values less than ('202020'), partition p2 values less than ('20:20:10'));", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, }, { "create table t(a time) partition by range columns (a) (partition p1 values less than ('202090'));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (id int) partition by range columns (id) (partition p0 values less than (1, 2));", @@ -435,15 +470,15 @@ create table log_message_1 ( }, { "create table t (a int) partition by range columns (b) (partition p0 values less than (1));", - ddl.ErrFieldNotFoundPart, + dbterror.ErrFieldNotFoundPart, }, { "create table t (a date) partition by range (to_days(to_days(a))) (partition p0 values less than (1));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, { "create table t (id timestamp) partition by range columns (id) (partition p0 values less than ('2019-01-09 11:23:34'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { `create table t29 ( @@ -451,120 +486,127 @@ create table log_message_1 ( ) partition by range columns (a) (partition p0 values less than (0));`, - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id text) partition by range columns (id) (partition p0 values less than ('abc'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, // create as normal table, warning. // { // "create table t (a int, b varchar(64)) partition by range columns (a, b) (" + // "partition p0 values less than (1, 'a')," + // "partition p1 values less than (1, 'a'))", - // ddl.ErrRangeNotIncreasing, + // dbterror.ErrRangeNotIncreasing, // }, { "create table t (a int, b varchar(64)) partition by range columns ( b) (" + "partition p0 values less than ( 'a')," + "partition p1 values less than ('a'))", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, }, // create as normal table, warning. // { // "create table t (a int, b varchar(64)) partition by range columns (a, b) (" + // "partition p0 values less than (1, 'b')," + // "partition p1 values less than (1, 'a'))", - // ddl.ErrRangeNotIncreasing, + // dbterror.ErrRangeNotIncreasing, // }, { "create table t (a int, b varchar(64)) partition by range columns (b) (" + "partition p0 values less than ('b')," + "partition p1 values less than ('a'))", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, }, // create as normal table, warning. // { // "create table t (a int, b varchar(64)) partition by range columns (a, b) (" + // "partition p0 values less than (1, maxvalue)," + // "partition p1 values less than (1, 'a'))", - // ddl.ErrRangeNotIncreasing, + // dbterror.ErrRangeNotIncreasing, // }, { "create table t (a int, b varchar(64)) partition by range columns ( b) (" + "partition p0 values less than ( maxvalue)," + "partition p1 values less than ('a'))", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, }, { "create table t (col datetime not null default '2000-01-01')" + "partition by range columns (col) (" + "PARTITION p0 VALUES LESS THAN (20190905)," + "PARTITION p1 VALUES LESS THAN (20190906));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t(a char(10) collate utf8mb4_bin) " + "partition by range columns (a) (" + "partition p0 values less than ('a'), " + "partition p1 values less than ('G'));", - ddl.ErrRangeNotIncreasing, + dbterror.ErrRangeNotIncreasing, + }, + { + "create table t(a char(10) collate utf8mb4_bin) " + + "partition by range columns (a) (" + + "partition p0 values less than ('g'), " + + "partition p1 values less than ('A'));", + dbterror.ErrRangeNotIncreasing, }, { "CREATE TABLE t1(c0 INT) PARTITION BY HASH((NOT c0)) PARTITIONS 2;", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "CREATE TABLE t1(c0 INT) PARTITION BY HASH((!c0)) PARTITIONS 2;", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "CREATE TABLE t1(c0 INT) PARTITION BY LIST((NOT c0)) (partition p0 values in (0), partition p1 values in (1));", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "CREATE TABLE t1(c0 INT) PARTITION BY LIST((!c0)) (partition p0 values in (0), partition p1 values in (1));", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "CREATE TABLE t1 (a TIME, b DATE) PARTITION BY range(DATEDIFF(a, b)) (partition p1 values less than (20));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, { "CREATE TABLE t1 (a DATE, b VARCHAR(10)) PARTITION BY range(DATEDIFF(a, b)) (partition p1 values less than (20));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, { "create table t1 (a bigint unsigned) partition by list (a) (partition p0 values in (10, 20, 30, -1));", - ddl.ErrPartitionConstDomain, + dbterror.ErrPartitionConstDomain, }, { "create table t1 (a bigint unsigned) partition by range (a) (partition p0 values less than (-1));", - ddl.ErrPartitionConstDomain, + dbterror.ErrPartitionConstDomain, }, { "create table t1 (a int unsigned) partition by range (a) (partition p0 values less than (-1));", - ddl.ErrPartitionConstDomain, + dbterror.ErrPartitionConstDomain, }, { "create table t1 (a tinyint(20) unsigned) partition by range (a) (partition p0 values less than (-1));", - ddl.ErrPartitionConstDomain, + dbterror.ErrPartitionConstDomain, }, { "CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) PARTITION BY RANGE (a % 2) (PARTITION p VALUES LESS THAN (20080819));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, { "CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) PARTITION BY RANGE (a+2) (PARTITION p VALUES LESS THAN (20080819));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, } - for i, t := range cases { - _, err := tk.Exec(t.sql) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + for i, tt := range cases { + _, err := tk.Exec(tt.sql) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.sql, t.err, err, - )) + i, tt.sql, tt.err, err, + ) } tk.MustExec("drop table if exists t1;") @@ -582,6 +624,14 @@ create table log_message_1 ( partition p0 values less than ('a'), partition p1 values less than ('G'));`) + tk.MustExec("drop table if exists t;") + tk.MustExec(`create table t (a varchar(255) charset utf8mb4 collate utf8mb4_bin) ` + + `partition by range columns (a) ` + + `(partition pnull values less than (""),` + + `partition puppera values less than ("AAA"),` + + `partition plowera values less than ("aaa"),` + + `partition pmax values less than (MAXVALUE))`) + tk.MustExec("drop table if exists t;") tk.MustExec(`create table t(a int) partition by range columns (a) ( partition p0 values less than (10), @@ -597,11 +647,10 @@ create table log_message_1 ( tk.MustQuery(`select * from t where a < X'0D' order by a`).Check(testkit.Rows("\x0B", "\x0C")) } -func (s *testIntegrationSuite1) TestDisableTablePartition(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestDisableTablePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") for _, v := range []string{"'AUTO'", "'OFF'", "0", "'ON'"} { tk.MustExec("set @@session.tidb_enable_table_partition = " + v) @@ -609,17 +658,17 @@ func (s *testIntegrationSuite1) TestDisableTablePartition(c *C) { tk.MustExec("drop table if exists t") tk.MustExec(`create table t (id int) partition by list (id) ( partition p0 values in (1,2),partition p1 values in (3,4));`) - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl.Meta().Partition, IsNil) + tbl := external.GetTableByName(t, tk, "test", "t") + require.Nil(t, tbl.Meta().Partition) _, err := tk.Exec(`alter table t add partition ( partition p4 values in (7), partition p5 values in (8,9));`) - c.Assert(ddl.ErrPartitionMgmtOnNonpartitioned.Equal(err), IsTrue) + require.True(t, dbterror.ErrPartitionMgmtOnNonpartitioned.Equal(err)) tk.MustExec("insert into t values (1),(3),(5),(100),(null)") } } -func (s *testIntegrationSuite1) generatePartitionTableByNum(num int) string { +func generatePartitionTableByNum(num int) string { buf := bytes.NewBuffer(make([]byte, 0, 1024*1024)) buf.WriteString("create table gen_t (id int) partition by list (id) (") for i := 0; i < num; i++ { @@ -632,8 +681,10 @@ func (s *testIntegrationSuite1) generatePartitionTableByNum(num int) string { return buf.String() } -func (s *testIntegrationSuite1) TestCreateTableWithListPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithListPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("drop table if exists t") @@ -648,75 +699,75 @@ func (s *testIntegrationSuite1) TestCreateTableWithListPartition(c *C) { }, { "create table t (a int) partition by list (b) (partition p0 values in (1));", - ddl.ErrBadField, + dbterror.ErrBadField, }, { "create table t (id timestamp) partition by list (id) (partition p0 values in ('2019-01-09 11:23:34'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (id decimal) partition by list (id) (partition p0 values in ('2019-01-09 11:23:34'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (id float) partition by list (id) (partition p0 values in (1));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id double) partition by list (id) (partition p0 values in (1));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id text) partition by list (id) (partition p0 values in ('abc'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (id blob) partition by list (id) (partition p0 values in ('abc'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (id enum('a','b')) partition by list (id) (partition p0 values in ('a'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (id set('a','b')) partition by list (id) (partition p0 values in ('a'));", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, { "create table t (a int) partition by list (a) (partition p0 values in (1), partition p0 values in (2));", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, { "create table t (a int) partition by list (a) (partition p0 values in (1), partition P0 values in (2));", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, { "create table t (id bigint) partition by list (cast(id as unsigned)) (partition p0 values in (1))", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "create table t (id float) partition by list (ceiling(id)) (partition p0 values in (1))", - ddl.ErrPartitionFuncNotAllowed, + dbterror.ErrPartitionFuncNotAllowed, }, { "create table t(b char(10)) partition by range columns (b) (partition p1 values less than ('G' collate utf8mb4_unicode_ci));", - ddl.ErrPartitionFunctionIsNotAllowed, + dbterror.ErrPartitionFunctionIsNotAllowed, }, { "create table t (a date) partition by list (to_days(to_days(a))) (partition p0 values in (1), partition P1 values in (2));", - ddl.ErrWrongExprInPartitionFunc, + dbterror.ErrWrongExprInPartitionFunc, }, { "create table t (a int) partition by list (a) (partition p0 values in (1), partition p1 values in (1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a int) partition by list (a) (partition p0 values in (1), partition p1 values in (+1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a int) partition by list (a) (partition p0 values in (null), partition p1 values in (NULL));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { `create table t1 (id int key, name varchar(10), unique index idx(name)) partition by list (id) ( @@ -725,19 +776,19 @@ func (s *testIntegrationSuite1) TestCreateTableWithListPartition(c *C) { partition p2 values in (4,12,13,14,18), partition p3 values in (7,8,15,16) );`, - ddl.ErrUniqueKeyNeedAllFieldsInPf, + dbterror.ErrUniqueKeyNeedAllFieldsInPf, }, { - s.generatePartitionTableByNum(ddl.PartitionCountLimit + 1), - ddl.ErrTooManyPartitions, + generatePartitionTableByNum(ddl.PartitionCountLimit + 1), + dbterror.ErrTooManyPartitions, }, } - for i, t := range cases { - _, err := tk.Exec(t.sql) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + for i, tt := range cases { + _, err := tk.Exec(tt.sql) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.sql, t.err, err, - )) + i, tt.sql, tt.err, err, + ) } validCases := []string{ @@ -759,7 +810,7 @@ func (s *testIntegrationSuite1) TestCreateTableWithListPartition(c *C) { "create table t (a datetime) partition by list (to_seconds(a)) (partition p0 values in (to_seconds('2020-09-28 17:03:38'),to_seconds('2020-09-28 17:03:39')));", "create table t (a int, b int generated always as (a+1) virtual) partition by list (b + 1) (partition p0 values in (1));", "create table t(a binary) partition by list columns (a) (partition p0 values in (X'0C'));", - s.generatePartitionTableByNum(ddl.PartitionCountLimit), + generatePartitionTableByNum(ddl.PartitionCountLimit), } for id, sql := range validCases { @@ -769,16 +820,18 @@ func (s *testIntegrationSuite1) TestCreateTableWithListPartition(c *C) { if id == len(validCases)-1 { tblName = "gen_t" } - tbl := testGetTableByName(c, s.ctx, "test", tblName) + tbl := external.GetTableByName(t, tk, "test", tblName) tblInfo := tbl.Meta() - c.Assert(tblInfo.Partition, NotNil) - c.Assert(tblInfo.Partition.Enable, Equals, true) - c.Assert(tblInfo.Partition.Type == model.PartitionTypeList, IsTrue) + require.NotNil(t, tblInfo.Partition) + require.True(t, tblInfo.Partition.Enable) + require.Equal(t, model.PartitionTypeList, tblInfo.Partition.Type) } } -func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithListColumnsPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("drop table if exists t") @@ -793,111 +846,119 @@ func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { }, { "create table t (a int) partition by list columns (b) (partition p0 values in (1));", - ddl.ErrFieldNotFoundPart, + dbterror.ErrFieldNotFoundPart, }, { "create table t (id timestamp) partition by list columns (id) (partition p0 values in ('2019-01-09 11:23:34'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id decimal) partition by list columns (id) (partition p0 values in ('2019-01-09 11:23:34'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id year) partition by list columns (id) (partition p0 values in (2000));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id float) partition by list columns (id) (partition p0 values in (1));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id double) partition by list columns (id) (partition p0 values in (1));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id text) partition by list columns (id) (partition p0 values in ('abc'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id blob) partition by list columns (id) (partition p0 values in ('abc'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id enum('a','b')) partition by list columns (id) (partition p0 values in ('a'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (id set('a','b')) partition by list columns (id) (partition p0 values in ('a'));", - ddl.ErrNotAllowedTypeInPartition, + dbterror.ErrNotAllowedTypeInPartition, }, { "create table t (a varchar(2)) partition by list columns (a) (partition p0 values in ('abc'));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a tinyint) partition by list columns (a) (partition p0 values in (65536));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a bigint) partition by list columns (a) (partition p0 values in (18446744073709551615));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a bigint unsigned) partition by list columns (a) (partition p0 values in (-1));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a char) partition by list columns (a) (partition p0 values in ('abc'));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a datetime) partition by list columns (a) (partition p0 values in ('2020-11-31 12:00:00'));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a int) partition by list columns (a) (partition p0 values in (1), partition p0 values in (2));", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, { "create table t (a int) partition by list columns (a) (partition p0 values in (1), partition P0 values in (2));", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, { "create table t (a int) partition by list columns (a) (partition p0 values in (1), partition p1 values in (1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a int) partition by list columns (a) (partition p0 values in (1), partition p1 values in (+1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a tinyint) partition by list columns (a) (partition p0 values in (1), partition p1 values in (+1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a mediumint) partition by list columns (a) (partition p0 values in (1), partition p1 values in (+1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a bigint) partition by list columns (a) (partition p0 values in (1), partition p1 values in (+1));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a bigint) partition by list columns (a) (partition p0 values in (1,+1))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a int) partition by list columns (a) (partition p0 values in (null), partition p1 values in (NULL));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a bigint, b int) partition by list columns (a,b) (partition p0 values in ((1,2),(1,2)))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a bigint, b int) partition by list columns (a,b) (partition p0 values in ((1,1),(2,2)), partition p1 values in ((+1,1)));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, + }, + { + "create table t1 (a int, b int) partition by list columns(a,a) ( partition p values in ((1,1)));", + dbterror.ErrSameNamePartitionField, + }, + { + "create table t1 (a int, b int) partition by list columns(a,b,b) ( partition p values in ((1,1,1)));", + dbterror.ErrSameNamePartitionField, }, { `create table t1 (id int key, name varchar(10), unique index idx(name)) partition by list columns (id) ( @@ -906,11 +967,11 @@ func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { partition p2 values in (4,12,13,14,18), partition p3 values in (7,8,15,16) );`, - ddl.ErrUniqueKeyNeedAllFieldsInPf, + dbterror.ErrUniqueKeyNeedAllFieldsInPf, }, { "create table t (a date) partition by list columns (a) (partition p0 values in ('2020-02-02'), partition p1 values in ('20200202'));", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, { "create table t (a int, b varchar(10)) partition by list columns (a,b) (partition p0 values in (1));", @@ -918,7 +979,7 @@ func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { }, { "create table t (a int, b varchar(10)) partition by list columns (a,b) (partition p0 values in (('ab','ab')));", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a int, b datetime) partition by list columns (a,b) (partition p0 values in ((1)));", @@ -926,15 +987,15 @@ func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { }, { "create table t(b int) partition by hash ( b ) partitions 3 (partition p1, partition p2, partition p2);", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, } - for i, t := range cases { - _, err := tk.Exec(t.sql) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + for i, tt := range cases { + _, err := tk.Exec(tt.sql) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.sql, t.err, err, - )) + i, tt.sql, tt.err, err, + ) } validCases := []string{ @@ -966,16 +1027,18 @@ func (s *testIntegrationSuite1) TestCreateTableWithListColumnsPartition(c *C) { for _, sql := range validCases { tk.MustExec("drop table if exists t") tk.MustExec(sql) - tbl := testGetTableByName(c, s.ctx, "test", "t") + tbl := external.GetTableByName(t, tk, "test", "t") tblInfo := tbl.Meta() - c.Assert(tblInfo.Partition, NotNil) - c.Assert(tblInfo.Partition.Enable, Equals, true) - c.Assert(tblInfo.Partition.Type == model.PartitionTypeList, IsTrue) + require.NotNil(t, tblInfo.Partition) + require.Equal(t, true, tblInfo.Partition.Enable) + require.True(t, tblInfo.Partition.Type == model.PartitionTypeList) } } -func (s *testIntegrationSuite5) TestAlterTableAddPartitionByList(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddPartitionByList(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -988,57 +1051,57 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartitionByList(c *C) { partition p4 values in (7), partition p5 values in (8,9));`) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - - c.Assert(part.Expr, Equals, "`id`") - c.Assert(part.Definitions, HasLen, 5) - c.Assert(part.Definitions[0].InValues, DeepEquals, [][]string{{"1"}, {"2"}}) - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p0")) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"3"}, {"4"}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[2].InValues, DeepEquals, [][]string{{"5"}, {"NULL"}}) - c.Assert(part.Definitions[2].Name, Equals, model.NewCIStr("p3")) - c.Assert(part.Definitions[3].InValues, DeepEquals, [][]string{{"7"}}) - c.Assert(part.Definitions[3].Name, Equals, model.NewCIStr("p4")) - c.Assert(part.Definitions[4].InValues, DeepEquals, [][]string{{"8"}, {"9"}}) - c.Assert(part.Definitions[4].Name, Equals, model.NewCIStr("p5")) + require.True(t, part.Type == model.PartitionTypeList) + + require.Equal(t, "`id`", part.Expr) + require.Len(t, part.Definitions, 5) + require.Equal(t, [][]string{{"1"}, {"2"}}, part.Definitions[0].InValues) + require.Equal(t, model.NewCIStr("p0"), part.Definitions[0].Name) + require.Equal(t, [][]string{{"3"}, {"4"}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[1].Name) + require.Equal(t, [][]string{{"5"}, {"NULL"}}, part.Definitions[2].InValues) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[2].Name) + require.Equal(t, [][]string{{"7"}}, part.Definitions[3].InValues) + require.Equal(t, model.NewCIStr("p4"), part.Definitions[3].Name) + require.Equal(t, [][]string{{"8"}, {"9"}}, part.Definitions[4].InValues) + require.Equal(t, model.NewCIStr("p5"), part.Definitions[4].Name) errorCases := []struct { sql string err *terror.Error }{ {"alter table t add partition (partition p4 values in (7))", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, {"alter table t add partition (partition p6 values less than (7))", ast.ErrPartitionWrongValues, }, {"alter table t add partition (partition p6 values in (null))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, {"alter table t add partition (partition p6 values in (7))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, {"alter table t add partition (partition p6 values in ('a'))", - ddl.ErrValuesIsNotIntType, + dbterror.ErrValuesIsNotIntType, }, {"alter table t add partition (partition p5 values in (10),partition p6 values in (7))", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, } - for i, t := range errorCases { - _, err := tk.Exec(t.sql) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + for i, tt := range errorCases { + _, err := tk.Exec(tt.sql) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.sql, t.err, err, - )) + i, tt.sql, tt.err, err, + ) } errorCases2 := []struct { @@ -1049,48 +1112,50 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartitionByList(c *C) { { "create table t (a bigint unsigned) partition by list columns (a) (partition p0 values in (1));", "alter table t add partition (partition p1 values in (-1))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a varchar(2)) partition by list columns (a) (partition p0 values in ('a','b'));", "alter table t add partition (partition p1 values in ('abc'))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a tinyint) partition by list columns (a) (partition p0 values in (1,2,3));", "alter table t add partition (partition p1 values in (65536))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a bigint) partition by list columns (a) (partition p0 values in (1,2,3));", "alter table t add partition (partition p1 values in (18446744073709551615))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a char) partition by list columns (a) (partition p0 values in ('a','b'));", "alter table t add partition (partition p1 values in ('abc'))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, { "create table t (a datetime) partition by list columns (a) (partition p0 values in ('2020-11-30 12:00:00'));", "alter table t add partition (partition p1 values in ('2020-11-31 12:00:00'))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, } - for i, t := range errorCases2 { + for i, tt := range errorCases2 { tk.MustExec("drop table if exists t;") - tk.MustExec(t.create) - _, err := tk.Exec(t.alter) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + tk.MustExec(tt.create) + _, err := tk.Exec(tt.alter) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.alter, t.err, err, - )) + i, tt.alter, tt.err, err, + ) } } -func (s *testIntegrationSuite5) TestAlterTableAddPartitionByListColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddPartitionByListColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -1103,61 +1168,63 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartitionByListColumns(c *C) { partition p4 values in ((7,'a')), partition p5 values in ((8,'a')));`) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - - c.Assert(part.Expr, Equals, "") - c.Assert(part.Columns[0].O, Equals, "id") - c.Assert(part.Columns[1].O, Equals, "name") - c.Assert(part.Definitions, HasLen, 5) - c.Assert(part.Definitions[0].InValues, DeepEquals, [][]string{{"1", `"a"`}, {"2", `"b"`}}) - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p0")) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"3", `"a"`}, {"4", `"b"`}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[2].InValues, DeepEquals, [][]string{{"5", `NULL`}}) - c.Assert(part.Definitions[2].Name, Equals, model.NewCIStr("p3")) - c.Assert(part.Definitions[3].InValues, DeepEquals, [][]string{{"7", `"a"`}}) - c.Assert(part.Definitions[3].Name, Equals, model.NewCIStr("p4")) - c.Assert(part.Definitions[4].InValues, DeepEquals, [][]string{{"8", `"a"`}}) - c.Assert(part.Definitions[4].Name, Equals, model.NewCIStr("p5")) + require.True(t, part.Type == model.PartitionTypeList) + + require.Equal(t, "", part.Expr) + require.Equal(t, "id", part.Columns[0].O) + require.Equal(t, "name", part.Columns[1].O) + require.Len(t, part.Definitions, 5) + require.Equal(t, [][]string{{"1", `"a"`}, {"2", `"b"`}}, part.Definitions[0].InValues) + require.Equal(t, model.NewCIStr("p0"), part.Definitions[0].Name) + require.Equal(t, [][]string{{"3", `"a"`}, {"4", `"b"`}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[1].Name) + require.Equal(t, [][]string{{"5", `NULL`}}, part.Definitions[2].InValues) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[2].Name) + require.Equal(t, [][]string{{"7", `"a"`}}, part.Definitions[3].InValues) + require.Equal(t, model.NewCIStr("p4"), part.Definitions[3].Name) + require.Equal(t, [][]string{{"8", `"a"`}}, part.Definitions[4].InValues) + require.Equal(t, model.NewCIStr("p5"), part.Definitions[4].Name) errorCases := []struct { sql string err *terror.Error }{ {"alter table t add partition (partition p4 values in ((7,'b')))", - ddl.ErrSameNamePartition, + dbterror.ErrSameNamePartition, }, {"alter table t add partition (partition p6 values less than ((7,'a')))", ast.ErrPartitionWrongValues, }, {"alter table t add partition (partition p6 values in ((5,null)))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, {"alter table t add partition (partition p6 values in ((7,'a')))", - ddl.ErrMultipleDefConstInListPart, + dbterror.ErrMultipleDefConstInListPart, }, {"alter table t add partition (partition p6 values in (('a','a')))", - ddl.ErrWrongTypeColumnValue, + dbterror.ErrWrongTypeColumnValue, }, } - for i, t := range errorCases { - _, err := tk.Exec(t.sql) - c.Assert(t.err.Equal(err), IsTrue, Commentf( + for i, tt := range errorCases { + _, err := tk.Exec(tt.sql) + require.Truef(t, tt.err.Equal(err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.sql, t.err, err, - )) + i, tt.sql, tt.err, err, + ) } } -func (s *testIntegrationSuite5) TestAlterTableDropPartitionByList(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableDropPartitionByList(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -1169,19 +1236,19 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartitionByList(c *C) { tk.MustExec(`insert into t values (1),(3),(5),(null)`) tk.MustExec(`alter table t drop partition p1`) tk.MustQuery("select * from t").Check(testkit.Rows("1", "5", "")) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - c.Assert(part.Expr, Equals, "`id`") - c.Assert(part.Definitions, HasLen, 2) - c.Assert(part.Definitions[0].InValues, DeepEquals, [][]string{{"1"}, {"2"}}) - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p0")) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"5"}, {"NULL"}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p3")) + require.True(t, part.Type == model.PartitionTypeList) + require.Equal(t, "`id`", part.Expr) + require.Len(t, part.Definitions, 2) + require.Equal(t, [][]string{{"1"}, {"2"}}, part.Definitions[0].InValues) + require.Equal(t, model.NewCIStr("p0"), part.Definitions[0].Name) + require.Equal(t, [][]string{{"5"}, {"NULL"}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[1].Name) sql := "alter table t drop partition p10;" tk.MustGetErrCode(sql, tmysql.ErrDropPartitionNonExistent) @@ -1191,8 +1258,10 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartitionByList(c *C) { tk.MustGetErrCode(sql, tmysql.ErrDropLastPartition) } -func (s *testIntegrationSuite5) TestAlterTableDropPartitionByListColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableDropPartitionByListColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -1204,21 +1273,21 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartitionByListColumns(c *C) { tk.MustExec(`insert into t values (1,'a'),(3,'a'),(5,'a'),(null,null)`) tk.MustExec(`alter table t drop partition p1`) tk.MustQuery("select * from t").Sort().Check(testkit.Rows("1 a", "5 a", " ")) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - c.Assert(part.Expr, Equals, "") - c.Assert(part.Columns[0].O, Equals, "id") - c.Assert(part.Columns[1].O, Equals, "name") - c.Assert(part.Definitions, HasLen, 2) - c.Assert(part.Definitions[0].InValues, DeepEquals, [][]string{{"1", `"a"`}, {"2", `"b"`}}) - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p0")) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"5", `"a"`}, {"NULL", "NULL"}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p3")) + require.True(t, part.Type == model.PartitionTypeList) + require.Equal(t, "", part.Expr) + require.Equal(t, "id", part.Columns[0].O) + require.Equal(t, "name", part.Columns[1].O) + require.Len(t, part.Definitions, 2) + require.Equal(t, [][]string{{"1", `"a"`}, {"2", `"b"`}}, part.Definitions[0].InValues) + require.Equal(t, model.NewCIStr("p0"), part.Definitions[0].Name) + require.Equal(t, [][]string{{"5", `"a"`}, {"NULL", "NULL"}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[1].Name) sql := "alter table t drop partition p10;" tk.MustGetErrCode(sql, tmysql.ErrDropPartitionNonExistent) @@ -1228,8 +1297,10 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartitionByListColumns(c *C) { tk.MustGetErrCode(sql, tmysql.ErrDropLastPartition) } -func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByList(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableTruncatePartitionByList(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -1239,17 +1310,17 @@ func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByList(c *C) { partition p3 values in (5,null) );`) tk.MustExec(`insert into t values (1),(3),(5),(null)`) - oldTbl := testGetTableByName(c, tk.Se, "test", "t") + oldTbl := external.GetTableByName(t, tk, "test", "t") tk.MustExec(`alter table t truncate partition p1`) - tk.MustQuery("select * from t").Check(testkit.Rows("1", "5", "")) - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl.Meta().Partition, NotNil) + tk.MustQuery("select * from t").Sort().Check(testkit.Rows("1", "5", "")) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - c.Assert(part.Definitions, HasLen, 3) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"3"}, {"4"}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[1].ID == oldTbl.Meta().Partition.Definitions[1].ID, IsFalse) + require.True(t, part.Type == model.PartitionTypeList) + require.Len(t, part.Definitions, 3) + require.Equal(t, [][]string{{"3"}, {"4"}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[1].Name) + require.False(t, part.Definitions[1].ID == oldTbl.Meta().Partition.Definitions[1].ID) sql := "alter table t truncate partition p10;" tk.MustGetErrCode(sql, tmysql.ErrUnknownPartition) @@ -1259,8 +1330,10 @@ func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByList(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows()) } -func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByListColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableTruncatePartitionByListColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -1270,17 +1343,17 @@ func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByListColumns(c * partition p3 values in ((5,'a'),(null,null)) );`) tk.MustExec(`insert into t values (1,'a'),(3,'a'),(5,'a'),(null,null)`) - oldTbl := testGetTableByName(c, tk.Se, "test", "t") + oldTbl := external.GetTableByName(t, tk, "test", "t") tk.MustExec(`alter table t truncate partition p1`) - tk.MustQuery("select * from t").Check(testkit.Rows("1 a", "5 a", " ")) - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl.Meta().Partition, NotNil) + tk.MustQuery("select * from t").Sort().Check(testkit.Rows("1 a", "5 a", " ")) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type == model.PartitionTypeList, IsTrue) - c.Assert(part.Definitions, HasLen, 3) - c.Assert(part.Definitions[1].InValues, DeepEquals, [][]string{{"3", `"a"`}, {"4", `"b"`}}) - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[1].ID == oldTbl.Meta().Partition.Definitions[1].ID, IsFalse) + require.True(t, part.Type == model.PartitionTypeList) + require.Len(t, part.Definitions, 3) + require.Equal(t, [][]string{{"3", `"a"`}, {"4", `"b"`}}, part.Definitions[1].InValues) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[1].Name) + require.False(t, part.Definitions[1].ID == oldTbl.Meta().Partition.Definitions[1].ID) sql := "alter table t truncate partition p10;" tk.MustGetErrCode(sql, tmysql.ErrUnknownPartition) @@ -1290,8 +1363,10 @@ func (s *testIntegrationSuite5) TestAlterTableTruncatePartitionByListColumns(c * tk.MustQuery("select * from t").Check(testkit.Rows()) } -func (s *testIntegrationSuite3) TestCreateTableWithKeyPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithKeyPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists tm1;") tk.MustExec(`create table tm1 @@ -1304,8 +1379,10 @@ func (s *testIntegrationSuite3) TestCreateTableWithKeyPartition(c *C) { tk.MustExec(`create table tm2 (a char(5), unique key(a(5))) partition by key() partitions 5;`) } -func (s *testIntegrationSuite5) TestAlterTableAddPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists employees;") tk.MustExec(`create table employees ( @@ -1322,26 +1399,26 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartition(c *C) { partition p5 values less than MAXVALUE );`) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("employees")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().Partition, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().Partition) part := tbl.Meta().Partition - c.Assert(part.Type, Equals, model.PartitionTypeRange) - - c.Assert(part.Expr, Equals, "YEAR(`hired`)") - c.Assert(part.Definitions, HasLen, 5) - c.Assert(part.Definitions[0].LessThan[0], Equals, "1991") - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[1].LessThan[0], Equals, "1996") - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p2")) - c.Assert(part.Definitions[2].LessThan[0], Equals, "2001") - c.Assert(part.Definitions[2].Name, Equals, model.NewCIStr("p3")) - c.Assert(part.Definitions[3].LessThan[0], Equals, "2010") - c.Assert(part.Definitions[3].Name, Equals, model.NewCIStr("p4")) - c.Assert(part.Definitions[4].LessThan[0], Equals, "MAXVALUE") - c.Assert(part.Definitions[4].Name, Equals, model.NewCIStr("p5")) + require.Equal(t, model.PartitionTypeRange, part.Type) + + require.Equal(t, "YEAR(`hired`)", part.Expr) + require.Len(t, part.Definitions, 5) + require.Equal(t, "1991", part.Definitions[0].LessThan[0]) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[0].Name) + require.Equal(t, "1996", part.Definitions[1].LessThan[0]) + require.Equal(t, model.NewCIStr("p2"), part.Definitions[1].Name) + require.Equal(t, "2001", part.Definitions[2].LessThan[0]) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[2].Name) + require.Equal(t, "2010", part.Definitions[3].LessThan[0]) + require.Equal(t, model.NewCIStr("p4"), part.Definitions[3].Name) + require.Equal(t, "MAXVALUE", part.Definitions[4].LessThan[0]) + require.Equal(t, model.NewCIStr("p5"), part.Definitions[4].Name) tk.MustExec("drop table if exists table1;") tk.MustExec("create table table1(a int)") @@ -1450,8 +1527,10 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartition(c *C) { tk.MustGetErrCode(sql, tmysql.ErrWrongTypeColumnValue) } -func (s *testIntegrationSuite5) TestAlterTableDropPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableDropPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists employees") tk.MustExec(`create table employees ( @@ -1465,19 +1544,19 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartition(c *C) { );`) tk.MustExec("alter table employees drop partition p3;") - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("employees")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().GetPartitionInfo(), NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().GetPartitionInfo()) part := tbl.Meta().Partition - c.Assert(part.Type, Equals, model.PartitionTypeRange) - c.Assert(part.Expr, Equals, "`hired`") - c.Assert(part.Definitions, HasLen, 2) - c.Assert(part.Definitions[0].LessThan[0], Equals, "1991") - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[1].LessThan[0], Equals, "1996") - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p2")) + require.Equal(t, model.PartitionTypeRange, part.Type) + require.Equal(t, "`hired`", part.Expr) + require.Len(t, part.Definitions, 2) + require.Equal(t, "1991", part.Definitions[0].LessThan[0]) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[0].Name) + require.Equal(t, "1996", part.Definitions[1].LessThan[0]) + require.Equal(t, model.NewCIStr("p2"), part.Definitions[1].Name) tk.MustExec("drop table if exists table1;") tk.MustExec("create table table1 (a int);") @@ -1520,16 +1599,16 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartition(c *C) { tk.MustExec("alter table table4 drop partition p2;") is = domain.GetDomain(ctx).InfoSchema() tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("table4")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().GetPartitionInfo(), NotNil) + require.NoError(t, err) + require.NotNil(t, tbl.Meta().GetPartitionInfo()) part = tbl.Meta().Partition - c.Assert(part.Type, Equals, model.PartitionTypeRange) - c.Assert(part.Expr, Equals, "`id`") - c.Assert(part.Definitions, HasLen, 2) - c.Assert(part.Definitions[0].LessThan[0], Equals, "10") - c.Assert(part.Definitions[0].Name, Equals, model.NewCIStr("p1")) - c.Assert(part.Definitions[1].LessThan[0], Equals, "MAXVALUE") - c.Assert(part.Definitions[1].Name, Equals, model.NewCIStr("p3")) + require.Equal(t, model.PartitionTypeRange, part.Type) + require.Equal(t, "`id`", part.Expr) + require.Len(t, part.Definitions, 2) + require.Equal(t, "10", part.Definitions[0].LessThan[0]) + require.Equal(t, model.NewCIStr("p1"), part.Definitions[0].Name) + require.Equal(t, "MAXVALUE", part.Definitions[1].LessThan[0]) + require.Equal(t, model.NewCIStr("p3"), part.Definitions[1].Name) tk.MustExec("drop table if exists tr;") tk.MustExec(` create table tr( @@ -1590,8 +1669,10 @@ func (s *testIntegrationSuite5) TestAlterTableDropPartition(c *C) { tk.MustGetErrCode("alter table t1 drop partition p2", tmysql.ErrOnlyOnRangeListPartition) } -func (s *testIntegrationSuite5) TestMultiPartitionDropAndTruncate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiPartitionDropAndTruncate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists employees") tk.MustExec(`create table employees ( @@ -1615,11 +1696,15 @@ func (s *testIntegrationSuite5) TestMultiPartitionDropAndTruncate(c *C) { result.Check(testkit.Rows(`2010`)) } -func (s *testSerialDBSuite1) TestDropPartitionWithGlobalIndex(c *C) { +func TestDropPartitionWithGlobalIndex(t *testing.T) { + restore := config.RestoreFunc() + defer restore() + store, clean := testkit.CreateMockStore(t) + defer clean() config.UpdateGlobal(func(conf *config.Config) { conf.EnableGlobalIndex = true }) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test_global") tk.MustExec(`create table test_global ( a int, b int, c int) @@ -1627,8 +1712,8 @@ func (s *testSerialDBSuite1) TestDropPartitionWithGlobalIndex(c *C) { partition p1 values less than (10), partition p2 values less than (20) );`) - t := testGetTableByName(c, s.ctx, "test", "test_global") - pid := t.Meta().Partition.Definitions[1].ID + tt := external.GetTableByName(t, tk, "test", "test_global") + pid := tt.Meta().Partition.Definitions[1].ID tk.MustExec("Alter Table test_global Add Unique Index idx_b (b);") tk.MustExec("Alter Table test_global Add Unique Index idx_c (c);") @@ -1638,23 +1723,25 @@ func (s *testSerialDBSuite1) TestDropPartitionWithGlobalIndex(c *C) { result := tk.MustQuery("select * from test_global;") result.Sort().Check(testkit.Rows(`1 1 1`, `2 2 2`)) - t = testGetTableByName(c, s.ctx, "test", "test_global") - idxInfo := t.Meta().FindIndexByName("idx_b") - c.Assert(idxInfo, NotNil) - cnt := checkGlobalIndexCleanUpDone(c, s.ctx, t.Meta(), idxInfo, pid) - c.Assert(cnt, Equals, 2) + tt = external.GetTableByName(t, tk, "test", "test_global") + idxInfo := tt.Meta().FindIndexByName("idx_b") + require.NotNil(t, idxInfo) + cnt := checkGlobalIndexCleanUpDone(t, tk.Session(), tt.Meta(), idxInfo, pid) + require.Equal(t, 2, cnt) - idxInfo = t.Meta().FindIndexByName("idx_c") - c.Assert(idxInfo, NotNil) - cnt = checkGlobalIndexCleanUpDone(c, s.ctx, t.Meta(), idxInfo, pid) - c.Assert(cnt, Equals, 2) + idxInfo = tt.Meta().FindIndexByName("idx_c") + require.NotNil(t, idxInfo) + cnt = checkGlobalIndexCleanUpDone(t, tk.Session(), tt.Meta(), idxInfo, pid) + require.Equal(t, 2, cnt) config.UpdateGlobal(func(conf *config.Config) { conf.EnableGlobalIndex = false }) } -func (s *testSerialDBSuite1) TestAlterTableExchangePartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableExchangePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists e") tk.MustExec("drop table if exists e2") @@ -1808,10 +1895,10 @@ func (s *testSerialDBSuite1) TestAlterTableExchangePartition(c *C) { tk.MustGetErrCode("alter table e12 exchange partition p0 with table e14", tmysql.ErrPartitionExchangeDifferentOption) // test for tiflash replica - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) + require.Nil(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) defer func() { err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) + require.NoError(t, err) }() tk.MustExec("create table e15 (a int) partition by hash(a) partitions 1;") @@ -1819,15 +1906,15 @@ func (s *testSerialDBSuite1) TestAlterTableExchangePartition(c *C) { tk.MustExec("alter table e15 set tiflash replica 1;") tk.MustExec("alter table e16 set tiflash replica 2;") - e15 := testGetTableByName(c, s.ctx, "test", "e15") + e15 := external.GetTableByName(t, tk, "test", "e15") partition := e15.Meta().Partition - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) - e16 := testGetTableByName(c, s.ctx, "test", "e16") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, e16.Meta().ID, true) - c.Assert(err, IsNil) + e16 := external.GetTableByName(t, tk, "test", "e16") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), e16.Meta().ID, true) + require.NoError(t, err) tk.MustGetErrCode("alter table e15 exchange partition p0 with table e16", tmysql.ErrTablesDifferentMetadata) tk.MustExec("drop table e15, e16") @@ -1837,29 +1924,29 @@ func (s *testSerialDBSuite1) TestAlterTableExchangePartition(c *C) { tk.MustExec("alter table e15 set tiflash replica 1;") tk.MustExec("alter table e16 set tiflash replica 1;") - e15 = testGetTableByName(c, s.ctx, "test", "e15") + e15 = external.GetTableByName(t, tk, "test", "e15") partition = e15.Meta().Partition - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) - e16 = testGetTableByName(c, s.ctx, "test", "e16") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, e16.Meta().ID, true) - c.Assert(err, IsNil) + e16 = external.GetTableByName(t, tk, "test", "e16") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), e16.Meta().ID, true) + require.NoError(t, err) tk.MustExec("alter table e15 exchange partition p0 with table e16") - e15 = testGetTableByName(c, s.ctx, "test", "e15") + e15 = external.GetTableByName(t, tk, "test", "e15") partition = e15.Meta().Partition - c.Assert(e15.Meta().TiFlashReplica, NotNil) - c.Assert(e15.Meta().TiFlashReplica.Available, IsTrue) - c.Assert(e15.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID}) + require.NotNil(t, e15.Meta().TiFlashReplica) + require.True(t, e15.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID}, e15.Meta().TiFlashReplica.AvailablePartitionIDs) - e16 = testGetTableByName(c, s.ctx, "test", "e16") - c.Assert(e16.Meta().TiFlashReplica, NotNil) - c.Assert(e16.Meta().TiFlashReplica.Available, IsTrue) + e16 = external.GetTableByName(t, tk, "test", "e16") + require.NotNil(t, e16.Meta().TiFlashReplica) + require.True(t, e16.Meta().TiFlashReplica.Available) tk.MustExec("drop table e15, e16") tk.MustExec("create table e15 (a int) partition by hash(a) partitions 1;") @@ -1872,20 +1959,22 @@ func (s *testSerialDBSuite1) TestAlterTableExchangePartition(c *C) { tk.MustExec("alter table e16 set tiflash replica 1 location labels 'a', 'b';") - e15 = testGetTableByName(c, s.ctx, "test", "e15") + e15 = external.GetTableByName(t, tk, "test", "e15") partition = e15.Meta().Partition - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) - e16 = testGetTableByName(c, s.ctx, "test", "e16") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, e16.Meta().ID, true) - c.Assert(err, IsNil) + e16 = external.GetTableByName(t, tk, "test", "e16") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), e16.Meta().ID, true) + require.NoError(t, err) tk.MustExec("alter table e15 exchange partition p0 with table e16") } -func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { +func TestExchangePartitionTableCompatiable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() type testCase struct { ptSQL string ntSQL string @@ -1903,37 +1992,37 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt1 (id int not null, fname varchar(3)) partition by hash (id) partitions 4;", "create table nt1 (id int not null, fname varchar(4));", "alter table pt1 exchange partition p0 with table nt1;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt2 (id int not null, salary decimal) partition by hash(id) partitions 4;", "create table nt2 (id int not null, salary decimal(3,2));", "alter table pt2 exchange partition p0 with table nt2;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt3 (id int not null, salary decimal) partition by hash(id) partitions 1;", "create table nt3 (id int not null, salary decimal(10, 1));", "alter table pt3 exchange partition p0 with table nt3", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt4 (id int not null) partition by hash(id) partitions 1;", "create table nt4 (id1 int not null);", "alter table pt4 exchange partition p0 with table nt4;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt5 (id int not null, primary key (id)) partition by hash(id) partitions 1;", "create table nt5 (id int not null);", "alter table pt5 exchange partition p0 with table nt5;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt6 (id int not null, salary decimal, index idx (id, salary)) partition by hash(id) partitions 1;", "create table nt6 (id int not null, salary decimal, index idx (salary, id));", "alter table pt6 exchange partition p0 with table nt6;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt7 (id int not null, index idx (id) invisible) partition by hash(id) partitions 1;", @@ -1945,7 +2034,7 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt8 (id int not null, index idx (id)) partition by hash(id) partitions 1;", "create table nt8 (id int not null, index id_idx (id));", "alter table pt8 exchange partition p0 with table nt8;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { // foreign key test @@ -1953,33 +2042,33 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt9 (id int not null primary key auto_increment,t_id int not null) partition by hash(id) partitions 1;", "create table nt9 (id int not null primary key auto_increment, t_id int not null,foreign key fk_id (t_id) references pt5(id));", "alter table pt9 exchange partition p0 with table nt9;", - ddl.ErrPartitionExchangeForeignKey, + dbterror.ErrPartitionExchangeForeignKey, }, { // Generated column (virtual) "create table pt10 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname,' ')) virtual) partition by hash(id) partitions 1;", "create table nt10 (id int not null, lname varchar(30), fname varchar(100));", "alter table pt10 exchange partition p0 with table nt10;", - ddl.ErrUnsupportedOnGeneratedColumn, + dbterror.ErrUnsupportedOnGeneratedColumn, }, { "create table pt11 (id int not null, lname varchar(30), fname varchar(100)) partition by hash(id) partitions 1;", "create table nt11 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) virtual);", "alter table pt11 exchange partition p0 with table nt11;", - ddl.ErrUnsupportedOnGeneratedColumn, + dbterror.ErrUnsupportedOnGeneratedColumn, }, { "create table pt12 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname,' ')) stored) partition by hash(id) partitions 1;", "create table nt12 (id int not null, lname varchar(30), fname varchar(100));", "alter table pt12 exchange partition p0 with table nt12;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt13 (id int not null, lname varchar(30), fname varchar(100)) partition by hash(id) partitions 1;", "create table nt13 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) stored);", "alter table pt13 exchange partition p0 with table nt13;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt14 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) virtual) partition by hash(id) partitions 1;", @@ -1992,14 +2081,14 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt15 (id int not null, unique index uk_id (id)) partition by hash(id) partitions 1;", "create table nt15 (id int not null, index uk_id (id));", "alter table pt15 exchange partition p0 with table nt15", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { // auto_increment "create table pt16 (id int not null primary key auto_increment) partition by hash(id) partitions 1;", "create table nt16 (id int not null primary key);", "alter table pt16 exchange partition p0 with table nt16;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { // default @@ -2013,39 +2102,39 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt18 (id int not null) partition by hash(id) partitions 1;", "create view nt18 as select id from nt17;", "alter table pt18 exchange partition p0 with table nt18", - ddl.ErrCheckNoSuchTable, + dbterror.ErrCheckNoSuchTable, }, { "create table pt19 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) stored) partition by hash(id) partitions 1;", "create table nt19 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) virtual);", "alter table pt19 exchange partition p0 with table nt19;", - ddl.ErrUnsupportedOnGeneratedColumn, + dbterror.ErrUnsupportedOnGeneratedColumn, }, { "create table pt20 (id int not null) partition by hash(id) partitions 1;", "create table nt20 (id int default null);", "alter table pt20 exchange partition p0 with table nt20;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { // unsigned "create table pt21 (id int unsigned) partition by hash(id) partitions 1;", "create table nt21 (id int);", "alter table pt21 exchange partition p0 with table nt21;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { // zerofill "create table pt22 (id int) partition by hash(id) partitions 1;", "create table nt22 (id int zerofill);", "alter table pt22 exchange partition p0 with table nt22;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt23 (id int, lname varchar(10) charset binary) partition by hash(id) partitions 1;", "create table nt23 (id int, lname varchar(10));", "alter table pt23 exchange partition p0 with table nt23;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt25 (id int, a datetime on update current_timestamp) partition by hash(id) partitions 1;", @@ -2057,39 +2146,51 @@ func (s *testIntegrationSuite4) TestExchangePartitionTableCompatiable(c *C) { "create table pt26 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) virtual) partition by hash(id) partitions 1;", "create table nt26 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(id, ' ')) virtual);", "alter table pt26 exchange partition p0 with table nt26;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, { "create table pt27 (a int key, b int, index(a)) partition by hash(a) partitions 1;", "create table nt27 (a int not null, b int, index(a));", "alter table pt27 exchange partition p0 with table nt27;", - ddl.ErrTablesDifferentMetadata, + dbterror.ErrTablesDifferentMetadata, }, } - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - err := tk.Se.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "1") - c.Assert(err, IsNil) - for i, t := range cases { - tk.MustExec(t.ptSQL) - tk.MustExec(t.ntSQL) - if t.err != nil { - _, err := tk.Exec(t.exchangeSQL) - c.Assert(terror.ErrorEqual(err, t.err), IsTrue, Commentf( + err := tk.Session().GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "1") + require.NoError(t, err) + for i, tt := range cases { + tk.MustExec(tt.ptSQL) + tk.MustExec(tt.ntSQL) + if tt.err != nil { + _, err := tk.Exec(tt.exchangeSQL) + require.Truef(t, terror.ErrorEqual(err, tt.err), "case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`", - i, t.exchangeSQL, t.err, err, - )) + i, tt.exchangeSQL, tt.err, err, + ) } else { - tk.MustExec(t.exchangeSQL) + tk.MustExec(tt.exchangeSQL) } } - err = tk.Se.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "0") - c.Assert(err, IsNil) + err = tk.Session().GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "0") + require.NoError(t, err) } -func (s *testSerialDBSuite1) TestExchangePartitionExpressIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExchangePartitionExpressIndex(t *testing.T) { + restore := config.RestoreFunc() + defer restore() + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + conf.Experimental.AllowsExpressionIndex = true + }) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_exchange_partition=1") defer tk.MustExec("set @@tidb_enable_exchange_partition=0") @@ -2121,8 +2222,10 @@ func (s *testSerialDBSuite1) TestExchangePartitionExpressIndex(c *C) { } -func (s *testIntegrationSuite4) TestAddPartitionTooManyPartitions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddPartitionTooManyPartitions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") count := ddl.PartitionCountLimit tk.MustExec("drop table if exists p1;") @@ -2153,13 +2256,13 @@ func (s *testIntegrationSuite4) TestAddPartitionTooManyPartitions(c *C) { tk.MustGetErrCode(sql3, tmysql.ErrTooManyPartitions) } -func waitGCDeleteRangeDone(c *C, tk *testkit.TestKit, physicalID int64) bool { +func waitGCDeleteRangeDone(t *testing.T, tk *testkit.TestKit, physicalID int64) bool { var i int for i = 0; i < waitForCleanDataRound; i++ { rs, err := tk.Exec("select count(1) from mysql.gc_delete_range_done where element_id = ?", physicalID) - c.Assert(err, IsNil) - rows, err := session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + rows, err := session.ResultSetToStringSlice(context.Background(), tk.Session(), rs) + require.NoError(t, err) val := rows[0][0] if val != "0" { return true @@ -2170,11 +2273,11 @@ func waitGCDeleteRangeDone(c *C, tk *testkit.TestKit, physicalID int64) bool { return false } -func checkPartitionDelRangeDone(c *C, tk *testkit.TestKit, s *testIntegrationSuite, oldPID int64) { +func checkPartitionDelRangeDone(t *testing.T, tk *testkit.TestKit, store kv.Storage, oldPID int64) { startTime := time.Now() partitionPrefix := tablecodec.EncodeTablePrefix(oldPID) - done := waitGCDeleteRangeDone(c, tk, oldPID) + done := waitGCDeleteRangeDone(t, tk, oldPID) if !done { // Takes too long, give up the check. logutil.BgLogger().Info("truncate partition table", @@ -2185,7 +2288,7 @@ func checkPartitionDelRangeDone(c *C, tk *testkit.TestKit, s *testIntegrationSui } hasOldPartitionData := true - err := kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { it, err := txn.Iter(partitionPrefix, nil) if err != nil { return err @@ -2198,12 +2301,14 @@ func checkPartitionDelRangeDone(c *C, tk *testkit.TestKit, s *testIntegrationSui it.Close() return nil }) - c.Assert(err, IsNil) - c.Assert(hasOldPartitionData, IsFalse) + require.NoError(t, err) + require.False(t, hasOldPartitionData) } -func (s *testIntegrationSuite5) TestTruncatePartitionAndDropTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncatePartitionAndDropTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") // Test truncate common table. tk.MustExec("drop table if exists t1;") @@ -2255,14 +2360,14 @@ func (s *testIntegrationSuite5) TestTruncatePartitionAndDropTable(c *C) { (10, 'lava lamp', '1998-12-25');`) result = tk.MustQuery("select count(*) from t3;") result.Check(testkit.Rows("10")) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) - c.Assert(err, IsNil) + require.NoError(t, err) // Only one partition id test is taken here. tk.MustExec("truncate table t3;") oldPID := oldTblInfo.Meta().Partition.Definitions[0].ID - checkPartitionDelRangeDone(c, tk, s.testIntegrationSuite, oldPID) + checkPartitionDelRangeDone(t, tk, store, oldPID) // Test drop table partition. tk.MustExec("drop table if exists t4;") @@ -2293,11 +2398,11 @@ func (s *testIntegrationSuite5) TestTruncatePartitionAndDropTable(c *C) { result.Check(testkit.Rows("10")) is = domain.GetDomain(ctx).InfoSchema() oldTblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t4")) - c.Assert(err, IsNil) + require.NoError(t, err) // Only one partition id test is taken here. oldPID = oldTblInfo.Meta().Partition.Definitions[1].ID tk.MustExec("drop table t4;") - checkPartitionDelRangeDone(c, tk, s.testIntegrationSuite, oldPID) + checkPartitionDelRangeDone(t, tk, store, oldPID) tk.MustGetErrCode("select * from t4;", tmysql.ErrNoSuchTable) // Test truncate table partition reassigns new partitionIDs. @@ -2317,15 +2422,15 @@ func (s *testIntegrationSuite5) TestTruncatePartitionAndDropTable(c *C) { );`) is = domain.GetDomain(ctx).InfoSchema() oldTblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t5")) - c.Assert(err, IsNil) + require.NoError(t, err) oldPID = oldTblInfo.Meta().Partition.Definitions[0].ID tk.MustExec("truncate table t5;") is = domain.GetDomain(ctx).InfoSchema() newTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t5")) - c.Assert(err, IsNil) + require.NoError(t, err) newPID := newTblInfo.Meta().Partition.Definitions[0].ID - c.Assert(oldPID != newPID, IsTrue) + require.True(t, oldPID != newPID) tk.MustExec("set @@session.tidb_enable_table_partition = 1;") tk.MustExec("drop table if exists clients;") @@ -2339,22 +2444,24 @@ func (s *testIntegrationSuite5) TestTruncatePartitionAndDropTable(c *C) { partitions 12;`) is = domain.GetDomain(ctx).InfoSchema() oldTblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("clients")) - c.Assert(err, IsNil) + require.NoError(t, err) oldDefs := oldTblInfo.Meta().Partition.Definitions // Test truncate `hash partitioned table` reassigns new partitionIDs. tk.MustExec("truncate table clients;") is = domain.GetDomain(ctx).InfoSchema() newTblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("clients")) - c.Assert(err, IsNil) + require.NoError(t, err) newDefs := newTblInfo.Meta().Partition.Definitions for i := 0; i < len(oldDefs); i++ { - c.Assert(oldDefs[i].ID != newDefs[i].ID, IsTrue) + require.True(t, oldDefs[i].ID != newDefs[i].ID) } } -func (s *testIntegrationSuite5) TestPartitionUniqueKeyNeedAllFieldsInPf(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionUniqueKeyNeedAllFieldsInPf(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists part1;") tk.MustExec(`create table part1 ( @@ -2605,24 +2712,28 @@ func (s *testIntegrationSuite5) TestPartitionUniqueKeyNeedAllFieldsInPf(c *C) { tk.MustExec(sql13) } -func (s *testIntegrationSuite2) TestPartitionDropPrimaryKey(c *C) { +func TestPartitionDropPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() idxName := "primary" addIdxSQL := "alter table partition_drop_idx add primary key idx1 (c1);" dropIdxSQL := "alter table partition_drop_idx drop primary key;" - testPartitionDropIndex(c, s.store, s.lease, idxName, addIdxSQL, dropIdxSQL) + testPartitionDropIndex(t, store, 50*time.Millisecond, idxName, addIdxSQL, dropIdxSQL) } -func (s *testIntegrationSuite3) TestPartitionDropIndex(c *C) { +func TestPartitionDropIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() idxName := "idx1" addIdxSQL := "alter table partition_drop_idx add index idx1 (c1);" dropIdxSQL := "alter table partition_drop_idx drop index idx1;" - testPartitionDropIndex(c, s.store, s.lease, idxName, addIdxSQL, dropIdxSQL) + testPartitionDropIndex(t, store, 50*time.Millisecond, idxName, addIdxSQL, dropIdxSQL) } -func testPartitionDropIndex(c *C, store kv.Storage, lease time.Duration, idxName, addIdxSQL, dropIdxSQL string) { - tk := testkit.NewTestKit(c, store) +func testPartitionDropIndex(t *testing.T, store kv.Storage, lease time.Duration, idxName, addIdxSQL, dropIdxSQL string) { + tk := testkit.NewTestKit(t, store) done := make(chan error, 1) - tk.MustExec("use test_db") + tk.MustExec("use test") tk.MustExec("drop table if exists partition_drop_idx;") tk.MustExec(`create table partition_drop_idx ( c1 int, c2 int, c3 int @@ -2643,12 +2754,7 @@ func testPartitionDropIndex(c *C, store kv.Storage, lease time.Duration, idxName } tk.MustExec(addIdxSQL) - ctx := tk.Se.(sessionctx.Context) - indexID := testGetIndexID(c, ctx, "test_db", "partition_drop_idx", idxName) - - jobIDExt, reset := setupJobIDExtCallback(ctx) - defer reset() - testutil.SessionExecInGoroutine(store, dropIdxSQL, done) + testutil.ExecMultiSQLInGoroutine(store, "test", []string{dropIdxSQL}, done) ticker := time.NewTicker(lease / 2) defer ticker.Stop() LOOP: @@ -2658,7 +2764,7 @@ LOOP: if err == nil { break LOOP } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) + require.NoError(t, err) case <-ticker.C: step := 10 rand.Seed(time.Now().Unix()) @@ -2670,26 +2776,40 @@ LOOP: num += step } } - checkDelRangeAdded(tk, jobIDExt.jobID, indexID) tk.MustExec("drop table partition_drop_idx;") } -func (s *testIntegrationSuite2) TestPartitionCancelAddPrimaryKey(c *C) { +func TestPartitionCancelAddPrimaryKey(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() idxName := "primary" addIdxSQL := "alter table t1 add primary key c3_index (c1);" - testPartitionCancelAddIndex(c, s.store, s.dom.DDL(), s.lease, idxName, addIdxSQL) + testPartitionCancelAddIndex(t, store, dom.DDL(), 50*time.Millisecond, idxName, addIdxSQL) } -func (s *testIntegrationSuite4) TestPartitionCancelAddIndex(c *C) { +func TestPartitionCancelAddIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() idxName := "c3_index" addIdxSQL := "create unique index c3_index on t1 (c1)" - testPartitionCancelAddIndex(c, s.store, s.dom.DDL(), s.lease, idxName, addIdxSQL) + testPartitionCancelAddIndex(t, store, dom.DDL(), 50*time.Millisecond, idxName, addIdxSQL) } -func testPartitionCancelAddIndex(c *C, store kv.Storage, d ddl.DDL, lease time.Duration, idxName, addIdxSQL string) { - tk := testkit.NewTestKit(c, store) +func batchInsertT(tk *testkit.TestKit, tbl string, start, end int) { + dml := fmt.Sprintf("insert into %s values", tbl) + for i := start; i < end; i++ { + dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) + if i != end-1 { + dml += "," + } + } + tk.MustExec(dml) +} + +func testPartitionCancelAddIndex(t *testing.T, store kv.Storage, d ddl.DDL, lease time.Duration, idxName, addIdxSQL string) { + tk := testkit.NewTestKit(t, store) - tk.MustExec("use test_db") + tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec(`create table t1 ( c1 int, c2 int, c3 int @@ -2704,22 +2824,20 @@ func testPartitionCancelAddIndex(c *C, store kv.Storage, d ddl.DDL, lease time.D count := defaultBatchSize * 32 // add some rows for i := 0; i < count; i += defaultBatchSize { - batchInsert(tk, "t1", i, i+defaultBatchSize) + batchInsertT(tk, "t1", i, i+defaultBatchSize) } var checkErr error - var c3IdxInfo *model.IndexInfo hook := &ddl.TestDDLCallback{} originBatchSize := tk.MustQuery("select @@global.tidb_ddl_reorg_batch_size") // Set batch size to lower try to slow down add-index reorganization, This if for hook to cancel this ddl job. tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 32") - ctx := tk.Se.(sessionctx.Context) defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", originBatchSize.Rows()[0][0])) - hook.OnJobUpdatedExported, c3IdxInfo, checkErr = backgroundExecOnJobUpdatedExported(c, store, ctx, hook, idxName) + hook.OnJobUpdatedExported, _, checkErr = backgroundExecOnJobUpdatedExportedT(t, tk, store, hook, idxName) originHook := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originHook) + defer d.SetHook(originHook) jobIDExt := wrapJobIDExtCallback(hook) - d.(ddl.DDLForTest).SetHook(jobIDExt) + d.SetHook(jobIDExt) done := make(chan error, 1) go backgroundExec(store, addIdxSQL, done) @@ -2730,9 +2848,8 @@ LOOP: for { select { case err := <-done: - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") + require.Nil(t, checkErr) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") break LOOP case <-ticker.C: if times >= 10 { @@ -2750,11 +2867,10 @@ LOOP: times++ } } - checkDelRangeAdded(tk, jobIDExt.jobID, c3IdxInfo.ID) tk.MustExec("drop table t1") } -func backgroundExecOnJobUpdatedExported(c *C, store kv.Storage, ctx sessionctx.Context, hook *ddl.TestDDLCallback, idxName string) ( +func backgroundExecOnJobUpdatedExportedT(t *testing.T, tk *testkit.TestKit, store kv.Storage, hook *ddl.TestDDLCallback, idxName string) ( func(*model.Job), *model.IndexInfo, error) { var checkErr error first := true @@ -2769,8 +2885,8 @@ func backgroundExecOnJobUpdatedExported(c *C, store kv.Storage, ctx sessionctx.C if c3IdxInfo.ID != 0 { return } - t := testGetTableByName(c, ctx, "test_db", "t1") - for _, index := range t.Indices() { + tt := external.GetTableByName(t, tk, "test", "t1") + for _, index := range tt.Indices() { if !tables.IsIndexWritable(index) { continue } @@ -2824,17 +2940,21 @@ func backgroundExecOnJobUpdatedExported(c *C, store kv.Storage, ctx sessionctx.C return hook.OnJobUpdatedExported, c3IdxInfo, checkErr } -func (s *testIntegrationSuite5) TestPartitionAddPrimaryKey(c *C) { - tk := testkit.NewTestKit(c, s.store) - testPartitionAddIndexOrPK(c, tk, "primary key") +func TestPartitionAddPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + testPartitionAddIndexOrPK(t, tk, "primary key") } -func (s *testIntegrationSuite1) TestPartitionAddIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - testPartitionAddIndexOrPK(c, tk, "index") +func TestPartitionAddIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + testPartitionAddIndexOrPK(t, tk, "index") } -func testPartitionAddIndexOrPK(c *C, tk *testkit.TestKit, key string) { +func testPartitionAddIndexOrPK(t *testing.T, tk *testkit.TestKit, key string) { tk.MustExec("use test") tk.MustExec(`create table partition_add_idx ( id int not null, @@ -2848,7 +2968,7 @@ func testPartitionAddIndexOrPK(c *C, tk *testkit.TestKit, key string) { partition p6 values less than (2012), partition p7 values less than (2018) );`) - testPartitionAddIndex(tk, c, key) + testPartitionAddIndex(tk, t, key) // test hash partition table. tk.MustExec("set @@session.tidb_enable_table_partition = '1';") @@ -2857,7 +2977,7 @@ func testPartitionAddIndexOrPK(c *C, tk *testkit.TestKit, key string) { id int not null, hired date not null ) partition by hash( year(hired) ) partitions 4;`) - testPartitionAddIndex(tk, c, key) + testPartitionAddIndex(tk, t, key) // Test hash partition for pr 10475. tk.MustExec("drop table if exists t1") @@ -2876,7 +2996,7 @@ func testPartitionAddIndexOrPK(c *C, tk *testkit.TestKit, key string) { tk.MustExec("admin check table t1;") } -func testPartitionAddIndex(tk *testkit.TestKit, c *C, key string) { +func testPartitionAddIndex(tk *testkit.TestKit, t *testing.T, key string) { idxName1 := "idx1" f := func(end int, isPK bool) string { @@ -2905,18 +3025,18 @@ func testPartitionAddIndex(tk *testkit.TestKit, c *C, key string) { tk.MustExec(fmt.Sprintf("alter table partition_add_idx add %s idx1 (hired)", key)) tk.MustExec("alter table partition_add_idx add index idx2 (id, hired)") - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session() is := domain.GetDomain(ctx).InfoSchema() - t, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("partition_add_idx")) - c.Assert(err, IsNil) + tt, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("partition_add_idx")) + require.NoError(t, err) var idx1 table.Index - for _, idx := range t.Indices() { + for _, idx := range tt.Indices() { if idx.Meta().Name.L == idxName1 { idx1 = idx break } } - c.Assert(idx1, NotNil) + require.NotNil(t, idx1) tk.MustQuery(fmt.Sprintf("select count(hired) from partition_add_idx use index(%s)", idxName1)).Check(testkit.Rows("500")) tk.MustQuery("select count(id) from partition_add_idx use index(idx2)").Check(testkit.Rows("500")) @@ -2925,8 +3045,10 @@ func testPartitionAddIndex(tk *testkit.TestKit, c *C, key string) { tk.MustExec("drop table partition_add_idx") } -func (s *testIntegrationSuite5) TestDropSchemaWithPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropSchemaWithPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_db_with_partition") tk.MustExec("create database test_db_with_partition") tk.MustExec("use test_db_with_partition") @@ -2936,39 +3058,39 @@ func (s *testIntegrationSuite5) TestDropSchemaWithPartitionTable(c *C) { partition p1 values less than (20) );`) tk.MustExec("insert into t_part values (1),(2),(11),(12);") - ctx := s.ctx - tbl := testGetTableByName(c, ctx, "test_db_with_partition", "t_part") + ctx := tk.Session() + tbl := external.GetTableByName(t, tk, "test_db_with_partition", "t_part") // check records num before drop database. - recordsNum := getPartitionTableRecordsNum(c, ctx, tbl.(table.PartitionedTable)) - c.Assert(recordsNum, Equals, 4) + recordsNum := getPartitionTableRecordsNum(t, ctx, tbl.(table.PartitionedTable)) + require.Equal(t, 4, recordsNum) tk.MustExec("drop database if exists test_db_with_partition") // check job args. rs, err := tk.Exec("admin show ddl jobs") - c.Assert(err, IsNil) - rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + rows, err := session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) row := rows[0] - c.Assert(row.GetString(3), Equals, "drop schema") + require.Equal(t, "drop schema", row.GetString(3)) jobID := row.GetInt64(0) var tableIDs []int64 - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - historyJob, err := t.GetHistoryDDLJob(jobID) - c.Assert(err, IsNil) + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + tt := meta.NewMeta(txn) + historyJob, err := tt.GetHistoryDDLJob(jobID) + require.NoError(t, err) err = historyJob.DecodeArgs(&tableIDs) - c.Assert(err, IsNil) + require.NoError(t, err) // There is 2 partitions. - c.Assert(len(tableIDs), Equals, 3) + require.Equal(t, 3, len(tableIDs)) return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) startTime := time.Now() - done := waitGCDeleteRangeDone(c, tk, tableIDs[2]) + done := waitGCDeleteRangeDone(t, tk, tableIDs[2]) if !done { // Takes too long, give up the check. logutil.BgLogger().Info("drop schema", @@ -2980,35 +3102,37 @@ func (s *testIntegrationSuite5) TestDropSchemaWithPartitionTable(c *C) { // check records num after drop database. for i := 0; i < waitForCleanDataRound; i++ { - recordsNum = getPartitionTableRecordsNum(c, ctx, tbl.(table.PartitionedTable)) + recordsNum = getPartitionTableRecordsNum(t, ctx, tbl.(table.PartitionedTable)) if recordsNum != 0 { time.Sleep(waitForCleanDataInterval) } else { break } } - c.Assert(recordsNum, Equals, 0) + require.Equal(t, 0, recordsNum) } -func getPartitionTableRecordsNum(c *C, ctx sessionctx.Context, tbl table.PartitionedTable) int { +func getPartitionTableRecordsNum(t *testing.T, ctx sessionctx.Context, tbl table.PartitionedTable) int { num := 0 info := tbl.Meta().GetPartitionInfo() for _, def := range info.Definitions { pid := def.ID partition := tbl.GetPartition(pid) - c.Assert(ctx.NewTxn(context.Background()), IsNil) + require.Nil(t, ctx.NewTxn(context.Background())) err := tables.IterRecords(partition, ctx, partition.Cols(), func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { num++ return true, nil }) - c.Assert(err, IsNil) + require.NoError(t, err) } return num } -func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionErrorCode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // add partition tk.MustExec("set @@session.tidb_enable_table_partition = 1") tk.MustExec("drop database if exists test_db_with_partition") @@ -3026,10 +3150,10 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { partition by hash(store_id) partitions 4;`) _, err := tk.Exec("alter table employees add partition partitions 8;") - c.Assert(ddl.ErrUnsupportedAddPartition.Equal(err), IsTrue) + require.True(t, dbterror.ErrUnsupportedAddPartition.Equal(err)) _, err = tk.Exec("alter table employees add partition (partition p5 values less than (42));") - c.Assert(ddl.ErrUnsupportedAddPartition.Equal(err), IsTrue) + require.True(t, dbterror.ErrUnsupportedAddPartition.Equal(err)) // coalesce partition tk.MustExec(`create table clients ( @@ -3041,7 +3165,7 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { partition by hash( month(signed) ) partitions 12;`) _, err = tk.Exec("alter table clients coalesce partition 4;") - c.Assert(ddl.ErrUnsupportedCoalescePartition.Equal(err), IsTrue) + require.True(t, dbterror.ErrUnsupportedCoalescePartition.Equal(err)) tk.MustExec(`create table t_part (a int key) partition by range(a) ( @@ -3049,7 +3173,7 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { partition p1 values less than (20) );`) _, err = tk.Exec("alter table t_part coalesce partition 4;") - c.Assert(ddl.ErrCoalesceOnlyOnHashPartition.Equal(err), IsTrue) + require.True(t, dbterror.ErrCoalesceOnlyOnHashPartition.Equal(err)) tk.MustGetErrCode(`alter table t_part reorganize partition p0, p1 into ( partition p0 values less than (1980));`, tmysql.ErrUnsupportedDDLOperation) @@ -3061,7 +3185,7 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { tk.MustGetErrCode("alter table t_part repair partition p1;", tmysql.ErrUnsupportedDDLOperation) // Reduce the impact on DML when executing partition DDL - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") tk1.MustExec("drop table if exists t;") tk1.MustExec(`create table t(id int primary key) @@ -3069,16 +3193,18 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { tk1.MustExec("begin") tk1.MustExec("insert into t values(1);") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") tk2.MustExec("alter table t truncate partition p0;") _, err = tk1.Exec("commit") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testIntegrationSuite5) TestConstAndTimezoneDepent(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestConstAndTimezoneDepent(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // add partition tk.MustExec("set @@session.tidb_enable_table_partition = 1") tk.MustExec("drop database if exists test_db_with_partition_const") @@ -3165,8 +3291,10 @@ func (s *testIntegrationSuite5) TestConstAndTimezoneDepent(c *C) { tk.MustGetErrCode(sql14, tmysql.ErrWrongExprInPartitionFunc) } -func (s *testIntegrationSuite5) TestConstAndTimezoneDepent2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestConstAndTimezoneDepent2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // add partition tk.MustExec("set @@session.tidb_enable_table_partition = 1") tk.MustExec("drop database if exists test_db_with_partition_const") @@ -3195,8 +3323,10 @@ func (s *testIntegrationSuite5) TestConstAndTimezoneDepent2(c *C) { );`) } -func (s *testIntegrationSuite3) TestUnsupportedPartitionManagementDDLs(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUnsupportedPartitionManagementDDLs(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists test_1465;") tk.MustExec(` @@ -3209,11 +3339,22 @@ func (s *testIntegrationSuite3) TestUnsupportedPartitionManagementDDLs(c *C) { `) _, err := tk.Exec("alter table test_1465 partition by hash(a)") - c.Assert(err, ErrorMatches, ".*alter table partition is unsupported") + require.Regexp(t, ".*alter table partition is unsupported", err.Error()) } -func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCommitWhenSchemaChange(t *testing.T) { + restore := config.RestoreFunc() + defer restore() + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.Experimental.AllowsExpressionIndex = true + }) + store, clean := testkit.CreateMockStoreWithSchemaLease(t, time.Second) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@global.tidb_max_delta_schema_count= 4096") tk.MustExec("use test") tk.MustExec(`create table schema_change (a int, b timestamp) partition by range(a) ( @@ -3221,7 +3362,7 @@ func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { partition p1 values less than (7), partition p2 values less than (11) )`) - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") tk2.MustExec("set @@tidb_enable_exchange_partition=1") defer tk2.MustExec("set @@tidb_enable_exchange_partition=0") @@ -3238,8 +3379,9 @@ func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { defer func() { atomic.StoreUint32(&session.SchemaChangedWithoutRetry, 0) }() - _, err := tk.Se.Execute(context.Background(), "commit") - c.Assert(domain.ErrInfoSchemaChanged.Equal(err), IsTrue) + _, err := tk.Exec("commit") + require.Error(t, err) + require.Truef(t, domain.ErrInfoSchemaChanged.Equal(err), err.Error()) // Cover a bug that schema validator does not prevent transaction commit when // the schema has changed on the partitioned table. @@ -3256,8 +3398,8 @@ func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { tk.MustExec("insert into nt values (1), (3), (5);") tk2.MustExec("alter table pt exchange partition p1 with table nt;") tk.MustExec("insert into nt values (7), (9);") - _, err = tk.Se.Execute(context.Background(), "commit") - c.Assert(domain.ErrInfoSchemaChanged.Equal(err), IsTrue) + _, err = tk.Session().Execute(context.Background(), "commit") + require.True(t, domain.ErrInfoSchemaChanged.Equal(err)) tk.MustExec("admin check table pt") tk.MustQuery("select * from pt").Check(testkit.Rows()) @@ -3268,8 +3410,8 @@ func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { tk.MustExec("insert into pt values (1), (3), (5);") tk2.MustExec("alter table pt exchange partition p1 with table nt;") tk.MustExec("insert into pt values (7), (9);") - _, err = tk.Se.Execute(context.Background(), "commit") - c.Assert(domain.ErrInfoSchemaChanged.Equal(err), IsTrue) + _, err = tk.Session().Execute(context.Background(), "commit") + require.True(t, domain.ErrInfoSchemaChanged.Equal(err)) tk.MustExec("admin check table pt") tk.MustQuery("select * from pt").Check(testkit.Rows()) @@ -3277,8 +3419,10 @@ func (s *testSerialDBSuite1) TestCommitWhenSchemaChange(c *C) { tk.MustQuery("select * from nt").Check(testkit.Rows()) } -func (s *testSerialDBSuite1) TestCreatePartitionTableWithWrongType(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreatePartitionTableWithWrongType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") var err error @@ -3288,8 +3432,8 @@ func (s *testSerialDBSuite1) TestCreatePartitionTableWithWrongType(c *C) { partition p0 values less than (0x10), partition p3 values less than (0x20) )`) - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec(`create table t( b int(10) @@ -3297,8 +3441,8 @@ func (s *testSerialDBSuite1) TestCreatePartitionTableWithWrongType(c *C) { partition p0 values less than ('g'), partition p3 values less than ('k') )`) - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec(`create table t( b char(10) @@ -3306,8 +3450,8 @@ func (s *testSerialDBSuite1) TestCreatePartitionTableWithWrongType(c *C) { partition p0 values less than (30), partition p3 values less than (60) )`) - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec(`create table t( b datetime @@ -3315,11 +3459,13 @@ func (s *testSerialDBSuite1) TestCreatePartitionTableWithWrongType(c *C) { partition p0 values less than ('g'), partition p3 values less than ('m') )`) - c.Assert(err, NotNil) + require.Error(t, err) } -func (s *testSerialDBSuite1) TestAddPartitionForTableWithWrongType(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddPartitionForTableWithWrongType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop tables if exists t_int, t_char, t_date") tk.MustExec(`create table t_int(b int(10)) @@ -3340,36 +3486,38 @@ func (s *testSerialDBSuite1) TestAddPartitionForTableWithWrongType(c *C) { var err error _, err = tk.Exec("alter table t_int add partition (partition p1 values less than ('g'))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec("alter table t_int add partition (partition p1 values less than (0x20))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec("alter table t_char add partition (partition p1 values less than (0x20))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrRangeNotIncreasing.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrRangeNotIncreasing.Equal(err)) _, err = tk.Exec("alter table t_char add partition (partition p1 values less than (10))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec("alter table t_date add partition (partition p1 values less than ('m'))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec("alter table t_date add partition (partition p1 values less than (0x20))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) _, err = tk.Exec("alter table t_date add partition (partition p1 values less than (20))") - c.Assert(err, NotNil) - c.Assert(ddl.ErrWrongTypeColumnValue.Equal(err), IsTrue) + require.Error(t, err) + require.True(t, dbterror.ErrWrongTypeColumnValue.Equal(err)) } -func (s *testSerialDBSuite1) TestPartitionListWithTimeType(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionListWithTimeType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("create table t_list1(a date) partition by list columns (a) (partition p0 values in ('2010-02-02', '20180203'), partition p1 values in ('20200202'));") @@ -3377,10 +3525,10 @@ func (s *testSerialDBSuite1) TestPartitionListWithTimeType(c *C) { tk.MustQuery(`select * from t_list1 partition (p0);`).Check(testkit.Rows("2018-02-03")) } -func (s *testSerialDBSuite1) TestPartitionListWithNewCollation(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionListWithNewCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_enable_list_partition = ON") @@ -3391,19 +3539,21 @@ func (s *testSerialDBSuite1) TestPartitionListWithNewCollation(c *C) { tk.MustQuery(`select * from t11 partition (p0);`).Check(testkit.Rows("A", "B")) tk.MustQuery(`select * from t11 partition (p1);`).Check(testkit.Rows("c", "C", "d")) str := tk.MustQuery(`desc select * from t11 where a = 'b';`).Rows()[0][3].(string) - c.Assert(strings.Contains(str, "partition:p0"), IsTrue) + require.True(t, strings.Contains(str, "partition:p0")) } -func (s *testSerialDBSuite1) TestAddTableWithPartition(c *C) { +func TestAddTableWithPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // for global temporary table - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists global_partition_table;") tk.MustGetErrCode("create global temporary table global_partition_table (a int, b int) partition by hash(a) partitions 3 ON COMMIT DELETE ROWS;", errno.ErrPartitionNoTemporary) tk.MustExec("drop table if exists global_partition_table;") tk.MustExec("drop table if exists partition_table;") _, err := tk.Exec("create table partition_table (a int, b int) partition by hash(a) partitions 3;") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop table if exists partition_table;") tk.MustExec("drop table if exists partition_range_table;") tk.MustGetErrCode(`create global temporary table partition_range_table (c1 smallint(6) not null, c2 char(5) default null) partition by range ( c1 ) ( @@ -3429,7 +3579,7 @@ func (s *testSerialDBSuite1) TestAddTableWithPartition(c *C) { tk.MustExec("drop table if exists local_partition_table;") tk.MustExec("drop table if exists partition_table;") _, err = tk.Exec("create table partition_table (a int, b int) partition by hash(a) partitions 3;") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop table if exists partition_table;") tk.MustExec("drop table if exists local_partition_range_table;") tk.MustGetErrCode(`create temporary table local_partition_range_table (c1 smallint(6) not null, c2 char(5) default null) partition by range ( c1 ) ( @@ -3449,13 +3599,15 @@ func (s *testSerialDBSuite1) TestAddTableWithPartition(c *C) { tk.MustExec("drop table if exists local_partition_list_table;") } -func (s *testSerialDBSuite1) TestTruncatePartitionMultipleTimes(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestTruncatePartitionMultipleTimes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop table if exists test.t;") tk.MustExec(`create table test.t (a int primary key) partition by range (a) ( partition p0 values less than (10), partition p1 values less than (maxvalue));`) - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) originHook := dom.DDL().GetHook() defer dom.DDL().SetHook(originHook) hook := &ddl.TestDDLCallback{} @@ -3474,52 +3626,93 @@ func (s *testSerialDBSuite1) TestTruncatePartitionMultipleTimes(c *C) { } } done1 := make(chan error, 1) - go backgroundExec(s.store, "alter table test.t truncate partition p0;", done1) + go backgroundExec(store, "alter table test.t truncate partition p0;", done1) done2 := make(chan error, 1) - go backgroundExec(s.store, "alter table test.t truncate partition p0;", done2) + go backgroundExec(store, "alter table test.t truncate partition p0;", done2) <-done1 <-done2 - c.Assert(errCount, LessEqual, int32(1)) + require.LessOrEqual(t, errCount, int32(1)) } -func (s *testSerialDBSuite1) TestAddPartitionReplicaBiggerThanTiFlashStores(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddPartitionReplicaBiggerThanTiFlashStores(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_partition2") tk.MustExec("use test_partition2") tk.MustExec("drop table if exists t1") // Build a tableInfo with replica count = 1 while there is no real tiFlash store. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) tk.MustExec(`create table t1 (c int) partition by range(c) ( partition p0 values less than (100), partition p1 values less than (200))`) tk.MustExec("alter table t1 set tiflash replica 1") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount")) // Mock partitions replica as available. - t1 := testGetTableByName(c, s.s, "test_partition2", "t1") + t1 := external.GetTableByName(t, tk, "test_partition2", "t1") partition := t1.Meta().Partition - c.Assert(len(partition.Definitions), Equals, 2) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[1].ID, true) - c.Assert(err, IsNil) - t1 = testGetTableByName(c, s.s, "test_partition2", "t1") - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) + require.Equal(t, 2, len(partition.Definitions)) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[1].ID, true) + require.NoError(t, err) + t1 = external.GetTableByName(t, tk, "test_partition2", "t1") + require.True(t, t1.Meta().TiFlashReplica.Available) // Since there is no real TiFlash store (less than replica count), adding a partition will error here. err = tk.ExecToErr("alter table t1 add partition (partition p2 values less than (300));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1][ddl] the tiflash replica count: 1 should be less than the total tiflash server count: 0") + require.Error(t, err) + require.EqualError(t, err, "[ddl:-1][ddl] the tiflash replica count: 1 should be less than the total tiflash server count: 0") // Test `add partition` waiting TiFlash replica can exit when its retry count is beyond the limitation. originErrCountLimit := variable.GetDDLErrorCountLimit() tk.MustExec("set @@global.tidb_ddl_error_count_limit = 3") defer func() { tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %v", originErrCountLimit)) }() - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockWaitTiFlashReplica", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockWaitTiFlashReplica", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockWaitTiFlashReplica"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockWaitTiFlashReplica")) }() - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) + require.True(t, t1.Meta().TiFlashReplica.Available) err = tk.ExecToErr("alter table t1 add partition (partition p3 values less than (300));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1]DDL job rollback, error msg: [ddl] add partition wait for tiflash replica to complete") + require.Error(t, err) + require.Equal(t, "[ddl:-1]DDL job rollback, error msg: [ddl] add partition wait for tiflash replica to complete", err.Error()) +} + +func TestDuplicatePartitionNames(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("create database DuplicatePartitionNames") + defer tk.MustExec("drop database DuplicatePartitionNames") + tk.MustExec("use DuplicatePartitionNames") + + tk.MustExec("set @@tidb_enable_list_partition=on") + tk.MustExec("create table t1 (a int) partition by list (a) (partition p1 values in (1), partition p2 values in (2), partition p3 values in (3))") + tk.MustExec("insert into t1 values (1),(2),(3)") + tk.MustExec("alter table t1 truncate partition p1,p1") + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows("2", "3")) + tk.MustExec("insert into t1 values (1)") + err := tk.ExecToErr("alter table t1 drop partition p1,p1") + require.Error(t, err) + require.Equal(t, "[ddl:1507]Error in list of partitions to DROP", err.Error()) + err = tk.ExecToErr("alter table t1 drop partition p1,p9") + require.Error(t, err) + require.Equal(t, "[ddl:1507]Error in list of partitions to DROP", err.Error()) + err = tk.ExecToErr("alter table t1 drop partition p1,p1,p1") + require.Error(t, err) + require.Equal(t, "[ddl:1508]Cannot remove all partitions, use DROP TABLE instead", err.Error()) + err = tk.ExecToErr("alter table t1 drop partition p1,p9,p1") + require.Error(t, err) + require.Equal(t, "[ddl:1508]Cannot remove all partitions, use DROP TABLE instead", err.Error()) + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows("1", "2", "3")) + tk.MustExec("alter table t1 drop partition p1") + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows("2", "3")) + tk.MustQuery("Show create table t1").Check(testkit.Rows("" + + "t1 CREATE TABLE `t1` (\n" + + " `a` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY LIST (`a`)\n" + + "(PARTITION `p2` VALUES IN (2),\n" + + " PARTITION `p3` VALUES IN (3))")) } diff --git a/ddl/db_rename_test.go b/ddl/db_rename_test.go new file mode 100644 index 0000000000000..b84d22e63a31c --- /dev/null +++ b/ddl/db_rename_test.go @@ -0,0 +1,370 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" +) + +func TestRenameIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (pk int primary key, c int default 1, c1 int default 1, unique key k1(c), key k2(c1))") + + // Test rename success + tk.MustExec("alter table t rename index k1 to k3") + tk.MustExec("admin check index t k3") + + // Test rename to the same name + tk.MustExec("alter table t rename index k3 to k3") + tk.MustExec("admin check index t k3") + + // Test rename on non-exists keys + tk.MustGetErrCode("alter table t rename index x to x", errno.ErrKeyDoesNotExist) + + // Test rename on already-exists keys + tk.MustGetErrCode("alter table t rename index k3 to k2", errno.ErrDupKeyName) + + tk.MustExec("alter table t rename index k2 to K2") + tk.MustGetErrCode("alter table t rename key k3 to K2", errno.ErrDupKeyName) +} + +// TestCancelRenameIndex tests cancel ddl job which type is rename index. +func TestCancelRenameIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create database if not exists test_rename_index") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(c1 int, c2 int)") + defer tk.MustExec("drop table t;") + for i := 0; i < 100; i++ { + tk.MustExec("insert into t values (?, ?)", i, i) + } + tk.MustExec("alter table t add index idx_c2(c2)") + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type == model.ActionRenameIndex && job.State == model.JobStateQueueing { + jobIDs := []int64{job.ID} + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + originalHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + tk.MustGetErrMsg("alter table t rename index idx_c2 to idx_c3", "[ddl:8214]Cancelled DDL job") + require.NoError(t, checkErr) + dom.DDL().SetHook(originalHook) + tt := external.GetTableByName(t, tk, "test", "t") + for _, idx := range tt.Indices() { + require.False(t, strings.EqualFold(idx.Meta().Name.L, "idx_c3")) + } + tk.MustExec("alter table t rename index idx_c2 to idx_c3") +} + +// See issue: https://github.com/pingcap/tidb/issues/29752 +// Ref https://dev.mysql.com/doc/refman/8.0/en/rename-table.html +func TestRenameTableWithLocked(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableTableLock = true + }) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database renamedb") + tk.MustExec("create database renamedb2") + tk.MustExec("use renamedb") + tk.MustExec("DROP TABLE IF EXISTS t1;") + tk.MustExec("CREATE TABLE t1 (a int);") + + tk.MustExec("LOCK TABLES t1 WRITE;") + tk.MustGetErrCode("drop database renamedb2;", errno.ErrLockOrActiveTransaction) + tk.MustExec("RENAME TABLE t1 TO t2;") + tk.MustQuery("select * from renamedb.t2").Check(testkit.Rows()) + tk.MustExec("UNLOCK TABLES") + tk.MustExec("RENAME TABLE t2 TO t1;") + tk.MustQuery("select * from renamedb.t1").Check(testkit.Rows()) + + tk.MustExec("LOCK TABLES t1 READ;") + tk.MustGetErrCode("RENAME TABLE t1 TO t2;", errno.ErrTableNotLockedForWrite) + tk.MustExec("UNLOCK TABLES") + + tk.MustExec("drop database renamedb") +} + +func TestRenameTable2(t *testing.T) { + isAlterTable := false + testRenameTable(t, "rename table %s to %s", isAlterTable) +} + +func TestAlterTableRenameTable(t *testing.T) { + isAlterTable := true + testRenameTable(t, "alter table %s rename to %s", isAlterTable) +} + +func testRenameTable(t *testing.T, sql string, isAlterTable bool) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustGetErrCode("rename table tb1 to tb2;", errno.ErrNoSuchTable) + // for different databases + tk.MustExec("create table t (c1 int, c2 int)") + tk.MustExec("insert t values (1, 1), (2, 2)") + ctx := tk.Session() + is := domain.GetDomain(ctx).InfoSchema() + oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + oldTblID := oldTblInfo.Meta().ID + tk.MustExec("create database test1") + tk.MustExec("use test1") + tk.MustExec(fmt.Sprintf(sql, "test.t", "test1.t1")) + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, oldTblID, newTblInfo.Meta().ID) + tk.MustQuery("select * from t1").Check(testkit.Rows("1 1", "2 2")) + tk.MustExec("use test") + + // Make sure t doesn't exist. + tk.MustExec("create table t (c1 int, c2 int)") + tk.MustExec("drop table t") + + // for the same database + tk.MustExec("use test1") + tk.MustExec(fmt.Sprintf(sql, "t1", "t2")) + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) + require.NoError(t, err) + require.Equal(t, oldTblID, newTblInfo.Meta().ID) + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1", "2 2")) + isExist := is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t1")) + require.False(t, isExist) + tk.MustQuery("show tables").Check(testkit.Rows("t2")) + + // for failure case + failSQL := fmt.Sprintf(sql, "test_not_exist.t", "test_not_exist.t") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } + failSQL = fmt.Sprintf(sql, "test.test_not_exist", "test.test_not_exist") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } + failSQL = fmt.Sprintf(sql, "test.t_not_exist", "test_not_exist.t") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } + failSQL = fmt.Sprintf(sql, "test1.t2", "test_not_exist.t") + tk.MustGetErrCode(failSQL, errno.ErrErrorOnRename) + + tk.MustExec("use test1") + tk.MustExec("create table if not exists t_exist (c1 int, c2 int)") + failSQL = fmt.Sprintf(sql, "test1.t2", "test1.t_exist") + tk.MustGetErrCode(failSQL, errno.ErrTableExists) + failSQL = fmt.Sprintf(sql, "test.t_not_exist", "test1.t_exist") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrTableExists) + } + failSQL = fmt.Sprintf(sql, "test_not_exist.t", "test1.t_exist") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrTableExists) + } + failSQL = fmt.Sprintf(sql, "test_not_exist.t", "test1.t_not_exist") + if isAlterTable { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } else { + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + } + + // for the same table name + tk.MustExec("use test1") + tk.MustExec("create table if not exists t (c1 int, c2 int)") + tk.MustExec("create table if not exists t1 (c1 int, c2 int)") + if isAlterTable { + tk.MustExec(fmt.Sprintf(sql, "test1.t", "t")) + tk.MustExec(fmt.Sprintf(sql, "test1.t1", "test1.T1")) + } else { + tk.MustGetErrCode(fmt.Sprintf(sql, "test1.t", "t"), errno.ErrTableExists) + tk.MustGetErrCode(fmt.Sprintf(sql, "test1.t1", "test1.T1"), errno.ErrTableExists) + } + + // Test rename table name too long. + tk.MustGetErrCode("rename table test1.t1 to test1.txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", errno.ErrTooLongIdent) + tk.MustGetErrCode("alter table test1.t1 rename to test1.txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", errno.ErrTooLongIdent) + + tk.MustExec("drop database test1") +} + +func TestRenameMultiTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1(id int)") + tk.MustExec("create table t2(id int)") + sql := "rename table t1 to t3, t2 to t4" + _, err := tk.Exec(sql) + require.NoError(t, err) + + tk.MustExec("drop table t3, t4") + + tk.MustExec("create table t1 (c1 int, c2 int)") + tk.MustExec("create table t2 (c1 int, c2 int)") + tk.MustExec("insert t1 values (1, 1), (2, 2)") + tk.MustExec("insert t2 values (1, 1), (2, 2)") + ctx := tk.Session() + is := domain.GetDomain(ctx).InfoSchema() + oldTblInfo1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + oldTblID1 := oldTblInfo1.Meta().ID + oldTblInfo2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + oldTblID2 := oldTblInfo2.Meta().ID + tk.MustExec("create database test1") + tk.MustExec("use test1") + tk.MustExec("rename table test.t1 to test1.t1, test.t2 to test1.t2") + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo1, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, oldTblID1, newTblInfo1.Meta().ID) + newTblInfo2, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) + require.NoError(t, err) + require.Equal(t, oldTblID2, newTblInfo2.Meta().ID) + tk.MustQuery("select * from t1").Check(testkit.Rows("1 1", "2 2")) + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1", "2 2")) + + // Make sure t1,t2 doesn't exist. + isExist := is.TableExists(model.NewCIStr("test"), model.NewCIStr("t1")) + require.False(t, isExist) + isExist = is.TableExists(model.NewCIStr("test"), model.NewCIStr("t2")) + require.False(t, isExist) + + // for the same database + tk.MustExec("use test1") + tk.MustExec("rename table test1.t1 to test1.t3, test1.t2 to test1.t4") + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo1, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t3")) + require.NoError(t, err) + require.Equal(t, oldTblID1, newTblInfo1.Meta().ID) + newTblInfo2, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t4")) + require.NoError(t, err) + require.Equal(t, oldTblID2, newTblInfo2.Meta().ID) + tk.MustQuery("select * from t3").Check(testkit.Rows("1 1", "2 2")) + isExist = is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t1")) + require.False(t, isExist) + tk.MustQuery("select * from t4").Check(testkit.Rows("1 1", "2 2")) + isExist = is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t2")) + require.False(t, isExist) + tk.MustQuery("show tables").Check(testkit.Rows("t3", "t4")) + + // for multi tables same database + tk.MustExec("create table t5 (c1 int, c2 int)") + tk.MustExec("insert t5 values (1, 1), (2, 2)") + is = domain.GetDomain(ctx).InfoSchema() + oldTblInfo3, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t5")) + require.NoError(t, err) + oldTblID3 := oldTblInfo3.Meta().ID + tk.MustExec("rename table test1.t3 to test1.t1, test1.t4 to test1.t2, test1.t5 to test1.t3") + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo1, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, oldTblID1, newTblInfo1.Meta().ID) + newTblInfo2, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) + require.NoError(t, err) + require.Equal(t, oldTblID2, newTblInfo2.Meta().ID) + newTblInfo3, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t3")) + require.NoError(t, err) + require.Equal(t, oldTblID3, newTblInfo3.Meta().ID) + tk.MustQuery("show tables").Check(testkit.Rows("t1", "t2", "t3")) + + // for multi tables different databases + tk.MustExec("use test") + tk.MustExec("rename table test1.t1 to test.t2, test1.t2 to test.t3, test1.t3 to test.t4") + is = domain.GetDomain(ctx).InfoSchema() + newTblInfo1, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + require.Equal(t, oldTblID1, newTblInfo1.Meta().ID) + newTblInfo2, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) + require.NoError(t, err) + require.Equal(t, oldTblID2, newTblInfo2.Meta().ID) + newTblInfo3, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t4")) + require.NoError(t, err) + require.Equal(t, oldTblID3, newTblInfo3.Meta().ID) + tk.MustQuery("show tables").Check(testkit.Rows("t2", "t3", "t4")) + + // for failure case + failSQL := "rename table test_not_exist.t to test_not_exist.t, test_not_exist.t to test_not_exist.t" + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + failSQL = "rename table test.test_not_exist to test.test_not_exist, test.test_not_exist to test.test_not_exist" + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + failSQL = "rename table test.t_not_exist to test_not_exist.t, test.t_not_exist to test_not_exist.t" + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + failSQL = "rename table test1.t2 to test_not_exist.t, test1.t2 to test_not_exist.t" + tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) + + tk.MustExec("drop database test1") + tk.MustExec("drop database test") +} diff --git a/ddl/db_table_test.go b/ddl/db_table_test.go new file mode 100644 index 0000000000000..146aa01e38608 --- /dev/null +++ b/ddl/db_table_test.go @@ -0,0 +1,1102 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "bytes" + "context" + "fmt" + "strings" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" + testddlutil "github.com/pingcap/tidb/ddl/testutil" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" +) + +// TestCancelDropTable tests cancel ddl job which type is drop table. +func TestCancelDropTableAndSchema(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + testCases := []struct { + needAddTableOrDB bool + action model.ActionType + jobState model.JobState + JobSchemaState model.SchemaState + cancelSucc bool + }{ + // Check drop table. + // model.JobStateNone means the jobs is canceled before the first run. + {true, model.ActionDropTable, model.JobStateQueueing, model.StateNone, true}, + {false, model.ActionDropTable, model.JobStateRunning, model.StateWriteOnly, false}, + {true, model.ActionDropTable, model.JobStateRunning, model.StateDeleteOnly, false}, + + // Check drop database. + {true, model.ActionDropSchema, model.JobStateQueueing, model.StateNone, true}, + {false, model.ActionDropSchema, model.JobStateRunning, model.StateWriteOnly, false}, + {true, model.ActionDropSchema, model.JobStateRunning, model.StateDeleteOnly, false}, + } + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + var jobID int64 + testCase := &testCases[0] + tk.MustExec("create database if not exists test_drop_db") + dbInfo, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("test_drop_db")) + require.True(t, ok) + + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState && job.SchemaID == dbInfo.ID { + jobIDs := []int64{job.ID} + jobID = job.ID + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.TODO()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + originHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originHook) + dom.DDL().SetHook(hook) + var err error + sql := "" + for i := range testCases { + testCase = &testCases[i] + if testCase.needAddTableOrDB { + tk.MustExec("create database if not exists test_drop_db") + tk.MustExec("use test_drop_db") + tk.MustExec("create table if not exists t(c1 int, c2 int)") + } + + dbInfo, ok = dom.InfoSchema().SchemaByName(model.NewCIStr("test_drop_db")) + require.True(t, ok) + + if testCase.action == model.ActionDropTable { + sql = "drop table t;" + } else if testCase.action == model.ActionDropSchema { + sql = "drop database test_drop_db;" + } + + _, err = tk.Exec(sql) + if testCase.cancelSucc { + require.Nil(t, checkErr) + require.Error(t, err) + require.Equal(t, "[ddl:8214]Cancelled DDL job", err.Error()) + tk.MustExec("insert into t values (?, ?)", i, i) + } else { + require.NoError(t, err) + require.NotNil(t, checkErr) + require.Equal(t, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error(), checkErr.Error()) + _, err = tk.Exec("insert into t values (?, ?)", i, i) + require.Error(t, err) + } + } +} + +func TestTableForeignKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (a int, b int);") + // test create table with foreign key. + failSQL := "create table t2 (c int, foreign key (a) references t1(a));" + tk.MustGetErrCode(failSQL, errno.ErrKeyColumnDoesNotExits) + // test add foreign key. + tk.MustExec("create table t3 (a int, b int);") + failSQL = "alter table t1 add foreign key (c) REFERENCES t3(a);" + tk.MustGetErrCode(failSQL, errno.ErrKeyColumnDoesNotExits) + // test origin key not match error + failSQL = "alter table t1 add foreign key (a) REFERENCES t3(a, b);" + tk.MustGetErrCode(failSQL, errno.ErrWrongFkDef) + // Test drop column with foreign key. + tk.MustExec("create table t4 (c int,d int,foreign key (d) references t1 (b));") + failSQL = "alter table t4 drop column d" + tk.MustGetErrCode(failSQL, errno.ErrFkColumnCannotDrop) + // Test change column with foreign key. + failSQL = "alter table t4 change column d e bigint;" + tk.MustGetErrCode(failSQL, errno.ErrFKIncompatibleColumns) + // Test modify column with foreign key. + failSQL = "alter table t4 modify column d bigint;" + tk.MustGetErrCode(failSQL, errno.ErrFKIncompatibleColumns) + tk.MustQuery("select count(*) from information_schema.KEY_COLUMN_USAGE;") + tk.MustExec("alter table t4 drop foreign key d") + tk.MustExec("alter table t4 modify column d bigint;") + tk.MustExec("drop table if exists t1,t2,t3,t4;") +} + +func TestAddNotNullColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // for different databases + tk.MustExec("create table tnn (c1 int primary key auto_increment, c2 int)") + tk.MustExec("insert tnn (c2) values (0)" + strings.Repeat(",(0)", 99)) + done := make(chan error, 1) + testddlutil.SessionExecInGoroutine(store, "test", "alter table tnn add column c3 int not null default 3", done) + updateCnt := 0 +out: + for { + select { + case err := <-done: + require.NoError(t, err) + break out + default: + // Close issue #14636 + // Because add column action is not amendable now, it causes an error when the schema is changed + // in the process of an insert statement. + _, err := tk.Exec("update tnn set c2 = c2 + 1 where c1 = 99") + if err == nil { + updateCnt++ + } + } + } + expected := fmt.Sprintf("%d %d", updateCnt, 3) + tk.MustQuery("select c2, c3 from tnn where c1 = 99").Check(testkit.Rows(expected)) + tk.MustExec("drop table tnn") +} + +func TestCharacterSetInColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database varchar_test;") + defer tk.MustExec("drop database varchar_test;") + tk.MustExec("use varchar_test") + tk.MustExec("create table t (c1 int, s1 varchar(10), s2 text)") + tk.MustQuery("select count(*) from information_schema.columns where table_schema = 'varchar_test' and character_set_name != 'utf8mb4'").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from information_schema.columns where table_schema = 'varchar_test' and character_set_name = 'utf8mb4'").Check(testkit.Rows("2")) + + tk.MustExec("create table t1(id int) charset=UTF8;") + tk.MustExec("create table t2(id int) charset=BINARY;") + tk.MustExec("create table t3(id int) charset=LATIN1;") + tk.MustExec("create table t4(id int) charset=ASCII;") + tk.MustExec("create table t5(id int) charset=UTF8MB4;") + + tk.MustExec("create table t11(id int) charset=utf8;") + tk.MustExec("create table t12(id int) charset=binary;") + tk.MustExec("create table t13(id int) charset=latin1;") + tk.MustExec("create table t14(id int) charset=ascii;") + tk.MustExec("create table t15(id int) charset=utf8mb4;") +} + +func TestAddNotNullColumnWhileInsertOnDupUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + closeCh := make(chan bool) + var wg util.WaitGroupWrapper + tk1.MustExec("create table nn (a int primary key, b int)") + tk1.MustExec("insert nn values (1, 1)") + wg.Run(func() { + for { + select { + case <-closeCh: + return + default: + } + tk2.MustExec("insert nn (a, b) values (1, 1) on duplicate key update a = 1, b = values(b) + 1") + } + }) + tk1.MustExec("alter table nn add column c int not null default 3 after a") + close(closeCh) + wg.Wait() + tk1.MustQuery("select * from nn").Check(testkit.Rows("1 3 2")) +} + +func TestTransactionOnAddDropColumn(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, time.Microsecond*500) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int);") + tk.MustExec("create table t2 (a int, b int);") + tk.MustExec("insert into t2 values (2,0)") + + transactions := [][]string{ + { + "begin", + "insert into t1 set a=1", + "update t1 set b=1 where a=1", + "commit", + }, + { + "begin", + "insert into t1 select a,b from t2", + "update t1 set b=2 where a=2", + "commit", + }, + } + + originHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originHook) + hook := &ddl.TestDDLCallback{Do: dom} + var checkErr error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if checkErr != nil { + return + } + switch job.SchemaState { + case model.StateWriteOnly, model.StateWriteReorganization, model.StateDeleteOnly, model.StateDeleteReorganization: + default: + return + } + // do transaction. + for _, transaction := range transactions { + for _, sql := range transaction { + if _, checkErr = tk.Exec(sql); checkErr != nil { + checkErr = errors.Errorf("err: %s, sql: %s, job schema state: %s", checkErr.Error(), sql, job.SchemaState) + return + } + } + } + } + dom.DDL().SetHook(hook) + done := make(chan error, 1) + // test transaction on add column. + go backgroundExec(store, "alter table t1 add column c int not null after a", done) + err := <-done + require.NoError(t, err) + require.Nil(t, checkErr) + tk.MustQuery("select a,b from t1 order by a").Check(testkit.Rows("1 1", "1 1", "1 1", "2 2", "2 2", "2 2")) + tk.MustExec("delete from t1") + + // test transaction on drop column. + go backgroundExec(store, "alter table t1 drop column c", done) + err = <-done + require.NoError(t, err) + require.Nil(t, checkErr) + tk.MustQuery("select a,b from t1 order by a").Check(testkit.Rows("1 1", "1 1", "1 1", "2 2", "2 2", "2 2")) +} + +func TestCreateTableWithSetCol(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t_set (a int, b set('e') default '');") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` int(11) DEFAULT NULL,\n" + + " `b` set('e') DEFAULT ''\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("drop table t_set") + tk.MustExec("create table t_set (a set('a', 'b', 'c', 'd') default 'a,c,c');") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` set('a','b','c','d') DEFAULT 'a,c'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // It's for failure cases. + // The type of default value is string. + tk.MustExec("drop table t_set") + failedSQL := "create table t_set (a set('1', '4', '10') default '3');" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + failedSQL = "create table t_set (a set('1', '4', '10') default '1,4,11');" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + // Success when the new collation is enabled. + tk.MustExec("create table t_set (a set('1', '4', '10') default '1 ,4');") + // The type of default value is int. + failedSQL = "create table t_set (a set('1', '4', '10') default 0);" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + failedSQL = "create table t_set (a set('1', '4', '10') default 8);" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + + // The type of default value is int. + // It's for successful cases + tk.MustExec("drop table if exists t_set") + tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 1);") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` set('1','4','10','21') DEFAULT '1'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("drop table t_set") + tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 2);") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` set('1','4','10','21') DEFAULT '4'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("drop table t_set") + tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 3);") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` set('1','4','10','21') DEFAULT '1,4'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("drop table t_set") + tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 15);") + tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + + " `a` set('1','4','10','21') DEFAULT '1,4,10,21'\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("insert into t_set value()") + tk.MustQuery("select * from t_set").Check(testkit.Rows("1,4,10,21")) +} + +func TestCreateTableWithEnumCol(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // It's for failure cases. + // The type of default value is string. + tk.MustExec("drop table if exists t_enum") + failedSQL := "create table t_enum (a enum('1', '4', '10') default '3');" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + failedSQL = "create table t_enum (a enum('1', '4', '10') default '');" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + // The type of default value is int. + failedSQL = "create table t_enum (a enum('1', '4', '10') default 0);" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + failedSQL = "create table t_enum (a enum('1', '4', '10') default 8);" + tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) + + // The type of default value is int. + // It's for successful cases + tk.MustExec("drop table if exists t_enum") + tk.MustExec("create table t_enum (a enum('2', '3', '4') default 2);") + ret := tk.MustQuery("show create table t_enum").Rows()[0][1] + require.True(t, strings.Contains(ret.(string), "`a` enum('2','3','4') DEFAULT '3'")) + tk.MustExec("drop table t_enum") + tk.MustExec("create table t_enum (a enum('a', 'c', 'd') default 2);") + ret = tk.MustQuery("show create table t_enum").Rows()[0][1] + require.True(t, strings.Contains(ret.(string), "`a` enum('a','c','d') DEFAULT 'c'")) + tk.MustExec("insert into t_enum value()") + tk.MustQuery("select * from t_enum").Check(testkit.Rows("c")) +} + +// TestCancelAddTableAndDropTablePartition tests cancel ddl job which type is add/drop table partition. +func TestCancelAddTableAndDropTablePartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists test_partition_table") + tk.MustExec("use test_partition_table") + tk.MustExec("drop table if exists t_part") + tk.MustExec(`create table t_part (a int key) + partition by range(a) ( + partition p0 values less than (10), + partition p1 values less than (20) + );`) + defer tk.MustExec("drop table t_part;") + base := 10 + for i := 0; i < base; i++ { + tk.MustExec("insert into t_part values (?)", i) + } + + testCases := []struct { + action model.ActionType + jobState model.JobState + JobSchemaState model.SchemaState + cancelSucc bool + }{ + {model.ActionAddTablePartition, model.JobStateQueueing, model.StateNone, true}, + {model.ActionDropTablePartition, model.JobStateQueueing, model.StateNone, true}, + // Add table partition now can be cancelled in ReplicaOnly state. + {model.ActionAddTablePartition, model.JobStateRunning, model.StateReplicaOnly, true}, + } + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + testCase := &testCases[0] + var jobID int64 + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { + jobIDs := []int64{job.ID} + jobID = job.ID + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + originalHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + + var err error + sql := "" + for i := range testCases { + testCase = &testCases[i] + if testCase.action == model.ActionAddTablePartition { + sql = `alter table t_part add partition ( + partition p2 values less than (30) + );` + } else if testCase.action == model.ActionDropTablePartition { + sql = "alter table t_part drop partition p1;" + } + _, err = tk.Exec(sql) + if testCase.cancelSucc { + require.Nil(t, checkErr) + require.Error(t, err) + require.Equal(t, "[ddl:8214]Cancelled DDL job", err.Error()) + tk.MustExec("insert into t_part values (?)", i+base) + + ctx := tk.Session() + is := domain.GetDomain(ctx).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test_partition_table"), model.NewCIStr("t_part")) + require.NoError(t, err) + partitionInfo := tbl.Meta().GetPartitionInfo() + require.NotNil(t, partitionInfo) + require.Len(t, partitionInfo.AddingDefinitions, 0) + } else { + require.NoError(t, err) + require.NoError(t, checkErr) + require.Equal(t, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error(), checkErr.Error()) + tk.MustExec("insert into t_part values (?)", i) + + } + } + dom.DDL().SetHook(originalHook) +} + +func TestAlterTableWithValidation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + defer tk.MustExec("drop table if exists t1") + + tk.MustExec("create table t1 (c1 int, c2 int as (c1 + 1));") + + // Test for alter table with validation. + tk.MustExec("alter table t1 with validation") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8200|ALTER TABLE WITH VALIDATION is currently unsupported")) + + // Test for alter table without validation. + tk.MustExec("alter table t1 without validation") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8200|ALTER TABLE WITHOUT VALIDATION is currently unsupported")) +} + +func TestBatchCreateTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, time.Microsecond*500) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists tables_1") + tk.MustExec("drop table if exists tables_2") + tk.MustExec("drop table if exists tables_3") + + d := dom.DDL() + infos := []*model.TableInfo{} + infos = append(infos, &model.TableInfo{ + Name: model.NewCIStr("tables_1"), + }) + infos = append(infos, &model.TableInfo{ + Name: model.NewCIStr("tables_2"), + }) + infos = append(infos, &model.TableInfo{ + Name: model.NewCIStr("tables_3"), + }) + + // correct name + tk.Session().SetValue(sessionctx.QueryString, "skip") + err := d.BatchCreateTableWithInfo(tk.Session(), model.NewCIStr("test"), infos, ddl.OnExistError) + require.NoError(t, err) + + tk.MustQuery("show tables like '%tables_%'").Check(testkit.Rows("tables_1", "tables_2", "tables_3")) + job := tk.MustQuery("admin show ddl jobs").Rows()[0] + require.Equal(t, "test", job[1]) + require.Equal(t, "tables_1,tables_2,tables_3", job[2]) + require.Equal(t, "create tables", job[3]) + require.Equal(t, "public", job[4]) + // FIXME: we must change column type to give multiple id + // c.Assert(job[6], Matches, "[^,]+,[^,]+,[^,]+") + + // duplicated name + infos[1].Name = model.NewCIStr("tables_1") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = d.BatchCreateTableWithInfo(tk.Session(), model.NewCIStr("test"), infos, ddl.OnExistError) + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableExists)) + + newinfo := &model.TableInfo{ + Name: model.NewCIStr("tables_4"), + } + { + colNum := 2 + cols := make([]*model.ColumnInfo, colNum) + viewCols := make([]model.CIStr, colNum) + var stmtBuffer bytes.Buffer + stmtBuffer.WriteString("SELECT ") + for i := range cols { + col := &model.ColumnInfo{ + Name: model.NewCIStr(fmt.Sprintf("c%d", i+1)), + Offset: i, + State: model.StatePublic, + } + cols[i] = col + viewCols[i] = col.Name + stmtBuffer.WriteString(cols[i].Name.L + ",") + } + stmtBuffer.WriteString("1 FROM t") + newinfo.Columns = cols + newinfo.View = &model.ViewInfo{Cols: viewCols, Security: model.SecurityDefiner, Algorithm: model.AlgorithmMerge, SelectStmt: stmtBuffer.String(), CheckOption: model.CheckOptionCascaded, Definer: &auth.UserIdentity{CurrentUser: true}} + } + + tk.Session().SetValue(sessionctx.QueryString, "skip") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = d.BatchCreateTableWithInfo(tk.Session(), model.NewCIStr("test"), []*model.TableInfo{newinfo}, ddl.OnExistError) + require.NoError(t, err) +} + +// port from mysql +// https://github.com/mysql/mysql-server/blob/124c7ab1d6f914637521fd4463a993aa73403513/mysql-test/t/lock.test +func TestLock(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + /* Testing of table locking */ + tk.MustExec("DROP TABLE IF EXISTS t1") + tk.MustExec("CREATE TABLE t1 ( `id` int(11) NOT NULL default '0', `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0', `dummy1` char(30) default NULL, PRIMARY KEY (`id`,`id2`), KEY `index_id3` (`id3`))") + tk.MustExec("insert into t1 (id,id2) values (1,1),(1,2),(1,3)") + tk.MustExec("LOCK TABLE t1 WRITE") + tk.MustExec("select dummy1,count(distinct id) from t1 group by dummy1") + tk.MustExec("update t1 set id=-1 where id=1") + tk.MustExec("LOCK TABLE t1 READ") + _, err := tk.Exec("update t1 set id=1 where id=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite)) + tk.MustExec("unlock tables") + tk.MustExec("update t1 set id=1 where id=-1") + tk.MustExec("drop table t1") +} + +// port from mysql +// https://github.com/mysql/mysql-server/blob/4f1d7cf5fcb11a3f84cff27e37100d7295e7d5ca/mysql-test/t/tablelock.test +func TestTableLock(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1,t2") + + /* Test of lock tables */ + tk.MustExec("create table t1 ( n int auto_increment primary key)") + tk.MustExec("lock tables t1 write") + tk.MustExec("insert into t1 values(NULL)") + tk.MustExec("unlock tables") + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + + tk.MustExec("lock tables t1 write") + tk.MustExec("insert into t1 values(NULL)") + tk.MustExec("unlock tables") + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + + tk.MustExec("drop table if exists t1") + + /* Test of locking and delete of files */ + tk.MustExec("drop table if exists t1,t2") + tk.MustExec("CREATE TABLE t1 (a int)") + tk.MustExec("CREATE TABLE t2 (a int)") + tk.MustExec("lock tables t1 write, t2 write") + tk.MustExec("drop table t1,t2") + + tk.MustExec("CREATE TABLE t1 (a int)") + tk.MustExec("CREATE TABLE t2 (a int)") + tk.MustExec("lock tables t1 write, t2 write") + tk.MustExec("drop table t2,t1") +} + +// port from mysql +// https://github.com/mysql/mysql-server/blob/4f1d7cf5fcb11a3f84cff27e37100d7295e7d5ca/mysql-test/t/lock_tables_lost_commit.test +func TestTableLocksLostCommit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk2.MustExec("use test") + + tk.MustExec("DROP TABLE IF EXISTS t1") + tk.MustExec("CREATE TABLE t1(a INT)") + tk.MustExec("LOCK TABLES t1 WRITE") + tk.MustExec("INSERT INTO t1 VALUES(10)") + + _, err := tk2.Exec("SELECT * FROM t1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + + tk.Session().Close() + + tk2.MustExec("SELECT * FROM t1") + tk2.MustExec("DROP TABLE t1") + + tk.MustExec("unlock tables") +} + +func checkTableLock(t *testing.T, tk *testkit.TestKit, dbName, tableName string, lockTp model.TableLockType) { + tb := external.GetTableByName(t, tk, dbName, tableName) + dom := domain.GetDomain(tk.Session()) + err := dom.Reload() + require.NoError(t, err) + if lockTp != model.TableLockNone { + require.NotNil(t, tb.Meta().Lock) + require.Equal(t, lockTp, tb.Meta().Lock.Tp) + require.Equal(t, model.TableLockStatePublic, tb.Meta().Lock.State) + require.True(t, len(tb.Meta().Lock.Sessions) == 1) + require.Equal(t, dom.DDL().GetID(), tb.Meta().Lock.Sessions[0].ServerID) + require.Equal(t, tk.Session().GetSessionVars().ConnectionID, tb.Meta().Lock.Sessions[0].SessionID) + } else { + require.Nil(t, tb.Meta().Lock) + } +} + +// test write local lock +func TestWriteLocal(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk2.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 ( n int auto_increment primary key)") + + // Test: allow read + tk.MustExec("lock tables t1 write local") + tk.MustExec("insert into t1 values(NULL)") + tk2.MustQuery("select count(*) from t1") + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test: forbid write + tk.MustExec("lock tables t1 write local") + _, err := tk2.Exec("insert into t1 values(NULL)") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test mutex: lock write local first + tk.MustExec("lock tables t1 write local") + _, err = tk2.Exec("lock tables t1 write local") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("lock tables t1 write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("lock tables t1 read") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test mutex: lock write first + tk.MustExec("lock tables t1 write") + _, err = tk2.Exec("lock tables t1 write local") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test mutex: lock read first + tk.MustExec("lock tables t1 read") + _, err = tk2.Exec("lock tables t1 write local") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") +} + +func TestLockTables(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, time.Microsecond*500) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1,t2") + defer tk.MustExec("drop table if exists t1,t2") + tk.MustExec("create table t1 (a int)") + tk.MustExec("create table t2 (a int)") + + // Test lock 1 table. + tk.MustExec("lock tables t1 write") + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + tk.MustExec("lock tables t1 read") + checkTableLock(t, tk, "test", "t1", model.TableLockRead) + tk.MustExec("lock tables t1 write") + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + + // Test lock multi tables. + tk.MustExec("lock tables t1 write, t2 read") + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + checkTableLock(t, tk, "test", "t2", model.TableLockRead) + tk.MustExec("lock tables t1 read, t2 write") + checkTableLock(t, tk, "test", "t1", model.TableLockRead) + checkTableLock(t, tk, "test", "t2", model.TableLockWrite) + tk.MustExec("lock tables t2 write") + checkTableLock(t, tk, "test", "t2", model.TableLockWrite) + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + tk.MustExec("lock tables t1 write") + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + checkTableLock(t, tk, "test", "t2", model.TableLockNone) + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + // Test read lock. + tk.MustExec("lock tables t1 read") + tk.MustQuery("select * from t1") + tk2.MustQuery("select * from t1") + _, err := tk.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite)) + _, err = tk.Exec("update t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite)) + _, err = tk.Exec("delete from t1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite)) + + _, err = tk2.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("update t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("delete from t1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk2.MustExec("lock tables t1 read") + _, err = tk2.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite)) + + // Test write lock. + _, err = tk.Exec("lock tables t1 write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk2.MustExec("unlock tables") + tk.MustExec("lock tables t1 write") + tk.MustQuery("select * from t1") + tk.MustExec("delete from t1") + tk.MustExec("insert into t1 set a=1") + + _, err = tk2.Exec("select * from t1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("lock tables t1 write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + + // Test write local lock. + tk.MustExec("lock tables t1 write local") + tk.MustQuery("select * from t1") + tk.MustExec("delete from t1") + tk.MustExec("insert into t1 set a=1") + + tk2.MustQuery("select * from t1") + _, err = tk2.Exec("delete from t1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("lock tables t1 write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("lock tables t1 read") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + + // Test none unique table. + _, err = tk.Exec("lock tables t1 read, t1 write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrNonuniqTable)) + + // Test lock table by other session in transaction and commit without retry. + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + tk.MustExec("set @@session.tidb_disable_txn_auto_retry=1") + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1") + tk2.MustExec("lock tables t1 write") + _, err = tk.Exec("commit") + require.Error(t, err) + require.Equal(t, "previous statement: insert into t1 set a=1: [domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]", err.Error()) + + // Test lock table by other session in transaction and commit with retry. + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + tk.MustExec("set @@session.tidb_disable_txn_auto_retry=0") + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1") + tk2.MustExec("lock tables t1 write") + _, err = tk.Exec("commit") + require.Truef(t, terror.ErrorEqual(err, infoschema.ErrTableLocked), "err: %v\n", err) + + // Test for lock the same table multiple times. + tk2.MustExec("lock tables t1 write") + tk2.MustExec("lock tables t1 write, t2 read") + + // Test lock tables and drop tables + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") + tk.MustExec("lock tables t1 write, t2 write") + tk.MustExec("drop table t1") + tk2.MustExec("create table t1 (a int)") + tk.MustExec("lock tables t1 write, t2 read") + + // Test lock tables and drop database. + tk.MustExec("unlock tables") + tk.MustExec("create database test_lock") + tk.MustExec("create table test_lock.t3 (a int)") + tk.MustExec("lock tables t1 write, test_lock.t3 write") + tk2.MustExec("create table t3 (a int)") + tk.MustExec("lock tables t1 write, t3 write") + tk.MustExec("drop table t3") + + // Test lock tables and truncate tables. + tk.MustExec("unlock tables") + tk.MustExec("lock tables t1 write, t2 read") + tk.MustExec("truncate table t1") + tk.MustExec("insert into t1 set a=1") + _, err = tk2.Exec("insert into t1 set a=1") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + + // Test for lock unsupported schema tables. + _, err = tk2.Exec("lock tables performance_schema.global_status write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrAccessDenied)) + _, err = tk2.Exec("lock tables information_schema.tables write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrAccessDenied)) + _, err = tk2.Exec("lock tables mysql.db write") + require.True(t, terror.ErrorEqual(err, infoschema.ErrAccessDenied)) + + // Test create table/view when session is holding the table locks. + tk.MustExec("unlock tables") + tk.MustExec("lock tables t1 write, t2 read") + _, err = tk.Exec("create table t3 (a int)") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLocked)) + _, err = tk.Exec("create view v1 as select * from t1;") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotLocked)) + + // Test for locking view was not supported. + tk.MustExec("unlock tables") + tk.MustExec("create view v1 as select * from t1;") + _, err = tk.Exec("lock tables v1 read") + require.True(t, terror.ErrorEqual(err, table.ErrUnsupportedOp)) + + // Test for locking sequence was not supported. + tk.MustExec("unlock tables") + tk.MustExec("create sequence seq") + _, err = tk.Exec("lock tables seq read") + require.True(t, terror.ErrorEqual(err, table.ErrUnsupportedOp)) + tk.MustExec("drop sequence seq") + + // Test for create/drop/alter database when session is holding the table locks. + tk.MustExec("unlock tables") + tk.MustExec("lock table t1 write") + _, err = tk.Exec("drop database test") + require.True(t, terror.ErrorEqual(err, table.ErrLockOrActiveTransaction)) + _, err = tk.Exec("create database test_lock") + require.True(t, terror.ErrorEqual(err, table.ErrLockOrActiveTransaction)) + _, err = tk.Exec("alter database test charset='utf8mb4'") + require.True(t, terror.ErrorEqual(err, table.ErrLockOrActiveTransaction)) + // Test alter/drop database when other session is holding the table locks of the database. + tk2.MustExec("create database test_lock2") + _, err = tk2.Exec("drop database test") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + _, err = tk2.Exec("alter database test charset='utf8mb4'") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + + // Test for admin cleanup table locks. + tk.MustExec("unlock tables") + tk.MustExec("lock table t1 write, t2 write") + _, err = tk2.Exec("lock tables t1 write, t2 read") + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableLocked)) + tk2.MustExec("admin cleanup table lock t1,t2") + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + checkTableLock(t, tk, "test", "t2", model.TableLockNone) + // cleanup unlocked table. + tk2.MustExec("admin cleanup table lock t1,t2") + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + checkTableLock(t, tk, "test", "t2", model.TableLockNone) + tk2.MustExec("lock tables t1 write, t2 read") + checkTableLock(t, tk2, "test", "t1", model.TableLockWrite) + checkTableLock(t, tk2, "test", "t2", model.TableLockRead) + + tk.MustExec("unlock tables") + tk2.MustExec("unlock tables") +} + +func TestTablesLockDelayClean(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk.MustExec("use test") + tk.MustExec("drop table if exists t1,t2") + defer tk.MustExec("drop table if exists t1,t2") + tk.MustExec("create table t1 (a int)") + tk.MustExec("create table t2 (a int)") + + tk.MustExec("lock tables t1 write") + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + config.UpdateGlobal(func(conf *config.Config) { + conf.DelayCleanTableLock = 100 + }) + var wg util.WaitGroupWrapper + var startTime time.Time + wg.Run(func() { + startTime = time.Now() + tk.Session().Close() + }) + time.Sleep(50 * time.Millisecond) + checkTableLock(t, tk, "test", "t1", model.TableLockWrite) + wg.Wait() + require.True(t, time.Since(startTime).Seconds() > 0.1) + checkTableLock(t, tk, "test", "t1", model.TableLockNone) + config.UpdateGlobal(func(conf *config.Config) { + conf.DelayCleanTableLock = 0 + }) +} + +func TestDDLWithInvalidTableInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + defer tk.MustExec("drop table if exists t") + // Test create with invalid expression. + _, err := tk.Exec(`CREATE TABLE t ( + c0 int(11) , + c1 int(11), + c2 decimal(16,4) GENERATED ALWAYS AS ((case when (c0 = 0) then 0when (c0 > 0) then (c1 / c0) end)) + );`) + require.Error(t, err) + require.Equal(t, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 4 column 88 near \"then (c1 / c0) end))\n\t);\" ", err.Error()) + + tk.MustExec("create table t (a bigint, b int, c int generated always as (b+1)) partition by hash(a) partitions 4;") + // Test drop partition column. + _, err = tk.Exec("alter table t drop column a;") + require.Error(t, err) + // TODO: refine the error message to compatible with MySQL + require.Equal(t, "[planner:1054]Unknown column 'a' in 'expression'", err.Error()) + // Test modify column with invalid expression. + _, err = tk.Exec("alter table t modify column c int GENERATED ALWAYS AS ((case when (a = 0) then 0when (a > 0) then (b / a) end));") + require.Error(t, err) + require.Equal(t, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 97 near \"then (b / a) end));\" ", err.Error()) + // Test add column with invalid expression. + _, err = tk.Exec("alter table t add column d int GENERATED ALWAYS AS ((case when (a = 0) then 0when (a > 0) then (b / a) end));") + require.Error(t, err) + require.Equal(t, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 94 near \"then (b / a) end));\" ", err.Error()) +} + +func TestAddColumn2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, time.Microsecond*500) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int key, b int);") + defer tk.MustExec("drop table if exists t1, t2") + + originHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originHook) + hook := &ddl.TestDDLCallback{Do: dom} + var writeOnlyTable table.Table + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.SchemaState == model.StateWriteOnly { + writeOnlyTable, _ = dom.InfoSchema().TableByID(job.TableID) + } + } + dom.DDL().SetHook(hook) + done := make(chan error, 1) + // test transaction on add column. + go backgroundExec(store, "alter table t1 add column c int not null", done) + err := <-done + require.NoError(t, err) + + tk.MustExec("insert into t1 values (1,1,1)") + tk.MustQuery("select a,b,c from t1").Check(testkit.Rows("1 1 1")) + + // mock for outdated tidb update record. + require.NotNil(t, writeOnlyTable) + ctx := context.Background() + err = tk.Session().NewTxn(ctx) + require.NoError(t, err) + oldRow, err := tables.RowWithCols(writeOnlyTable, tk.Session(), kv.IntHandle(1), writeOnlyTable.WritableCols()) + require.NoError(t, err) + require.Equal(t, 3, len(oldRow)) + err = writeOnlyTable.RemoveRecord(tk.Session(), kv.IntHandle(1), oldRow) + require.NoError(t, err) + _, err = writeOnlyTable.AddRecord(tk.Session(), types.MakeDatums(oldRow[0].GetInt64(), 2, oldRow[2].GetInt64()), table.IsUpdate) + require.NoError(t, err) + tk.Session().StmtCommit() + err = tk.Session().CommitTxn(ctx) + require.NoError(t, err) + + tk.MustQuery("select a,b,c from t1").Check(testkit.Rows("1 2 1")) + + // Test for _tidb_rowid + var re *testkit.Result + tk.MustExec("create table t2 (a int);") + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.SchemaState != model.StateWriteOnly { + return + } + // allow write _tidb_rowid first + tk.MustExec("set @@tidb_opt_write_row_id=1") + tk.MustExec("begin") + tk.MustExec("insert into t2 (a,_tidb_rowid) values (1,2);") + re = tk.MustQuery(" select a,_tidb_rowid from t2;") + tk.MustExec("commit") + + } + dom.DDL().SetHook(hook) + + go backgroundExec(store, "alter table t2 add column b int not null default 3", done) + err = <-done + require.NoError(t, err) + re.Check(testkit.Rows("1 2")) + tk.MustQuery("select a,b,_tidb_rowid from t2").Check(testkit.Rows("1 3 2")) +} diff --git a/ddl/db_test.go b/ddl/db_test.go index 309ca8a03e736..d848ba542efe2 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 PingCAP, Inc. +// Copyright 2022 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,54 +17,32 @@ package ddl_test import ( "context" "fmt" - "io" - "math" - "math/rand" "sort" "strconv" "strings" - "sync" - "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" - "github.com/pingcap/errors" "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" - testddlutil "github.com/pingcap/tidb/ddl/testutil" - "github.com/pingcap/tidb/domain" + ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/errno" - "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/meta/autoid" - "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" parsertypes "github.com/pingcap/tidb/parser/types" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/codec" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/domainutil" - "github.com/pingcap/tidb/util/israce" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" - "github.com/tikv/client-go/v2/testutils" + "github.com/stretchr/testify/require" ) const ( @@ -74,5635 +52,697 @@ const ( waitForCleanDataInterval = time.Millisecond * 100 ) -var _ = Suite(&testDBSuite1{&testDBSuite{}}) -var _ = Suite(&testDBSuite2{&testDBSuite{}}) -var _ = Suite(&testDBSuite3{&testDBSuite{}}) -var _ = Suite(&testDBSuite4{&testDBSuite{}}) -var _ = Suite(&testDBSuite5{&testDBSuite{}}) -var _ = SerialSuites(&testDBSuite6{&testDBSuite{}}) -var _ = Suite(&testDBSuite7{&testDBSuite{}}) -var _ = Suite(&testDBSuite8{&testDBSuite{}}) -var _ = SerialSuites(&testSerialDBSuite{&testDBSuite{}}) -var _ = SerialSuites(&testSerialDBSuite1{&testDBSuite{}}) - const defaultBatchSize = 1024 const defaultReorgBatchSize = 256 -type testDBSuite struct { - cluster testutils.Cluster - store kv.Storage - dom *domain.Domain - schemaName string - s session.Session - lease time.Duration - autoIDStep int64 - ctx sessionctx.Context -} +const dbTestLease = 600 * time.Millisecond -func setUpSuite(s *testDBSuite, c *C) { - var err error - - s.lease = 600 * time.Millisecond - session.SetSchemaLease(s.lease) - session.DisableStats4Test() - s.schemaName = "test_db" - s.autoIDStep = autoid.GetStep() - ddl.SetWaitTimeWhenErrorOccurred(0) - - s.store, err = mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - s.s, err = session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - s.ctx = s.s.(sessionctx.Context) - - _, err = s.s.Execute(context.Background(), "create database test_db") - c.Assert(err, IsNil) - _, err = s.s.Execute(context.Background(), "set @@global.tidb_max_delta_schema_count= 4096") - c.Assert(err, IsNil) - _, err = s.s.Execute(context.Background(), "set @@global.tidb_enable_alter_placement=1") - c.Assert(err, IsNil) -} +// Close issue #24580 +// See https://github.com/pingcap/tidb/issues/24580 +func TestIssue24580(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func tearDownSuite(s *testDBSuite, c *C) { - _, err := s.s.Execute(context.Background(), "drop database if exists test_db") - c.Assert(err, IsNil) - s.s.Close() - s.dom.Close() - err = s.store.Close() - c.Assert(err, IsNil) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(250) default null);") + tk.MustExec("insert into t values();") + tk.MustGetErrMsg("alter table t modify a char not null;", "[ddl:1265]Data truncated for column 'a' at row 1") + tk.MustExec("drop table if exists t") } -func (s *testDBSuite) SetUpSuite(c *C) { - setUpSuite(s, c) -} +// Close issue #27862 https://github.com/pingcap/tidb/issues/27862 +// Ref: https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html#data-types-storage-reqs-strings +// text(100) in utf8mb4 charset needs max 400 byte length, thus tinytext is not enough. +func TestCreateTextAdjustLen(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func (s *testDBSuite) TearDownSuite(c *C) { - tearDownSuite(s, c) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a text(100));") + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ + "t CREATE TABLE `t` (\n"+ + " `a` text DEFAULT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("alter table t add b text(100);") + tk.MustExec("alter table t add c text;") + tk.MustExec("alter table t add d text(50);") + tk.MustExec("alter table t change column a a text(50);") + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ + "t CREATE TABLE `t` (\n"+ + " `a` tinytext DEFAULT NULL,\n"+ + " `b` text DEFAULT NULL,\n"+ + " `c` text DEFAULT NULL,\n"+ + " `d` tinytext DEFAULT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) -type testDBSuite1 struct{ *testDBSuite } -type testDBSuite2 struct{ *testDBSuite } -type testDBSuite3 struct{ *testDBSuite } -type testDBSuite4 struct{ *testDBSuite } -type testDBSuite5 struct{ *testDBSuite } -type testDBSuite6 struct{ *testDBSuite } -type testDBSuite7 struct{ *testDBSuite } -type testDBSuite8 struct{ *testDBSuite } -type testSerialDBSuite struct{ *testDBSuite } -type testSerialDBSuite1 struct{ *testDBSuite } - -func testAddIndexWithPK(tk *testkit.TestKit) { - tk.MustExec("drop table if exists test_add_index_with_pk") - tk.MustExec("create table test_add_index_with_pk(a int not null, b int not null default '0', primary key(a))") - tk.MustExec("insert into test_add_index_with_pk values(1, 2)") - tk.MustExec("alter table test_add_index_with_pk add index idx (a)") - tk.MustQuery("select a from test_add_index_with_pk").Check(testkit.Rows("1")) - tk.MustExec("insert into test_add_index_with_pk values(2, 2)") - tk.MustExec("alter table test_add_index_with_pk add index idx1 (a, b)") - tk.MustQuery("select * from test_add_index_with_pk").Check(testkit.Rows("1 2", "2 2")) - tk.MustExec("drop table if exists test_add_index_with_pk1") - tk.MustExec("create table test_add_index_with_pk1(a int not null, b int not null default '0', c int, d int, primary key(c))") - tk.MustExec("insert into test_add_index_with_pk1 values(1, 1, 1, 1)") - tk.MustExec("alter table test_add_index_with_pk1 add index idx (c)") - tk.MustExec("insert into test_add_index_with_pk1 values(2, 2, 2, 2)") - tk.MustQuery("select * from test_add_index_with_pk1").Check(testkit.Rows("1 1 1 1", "2 2 2 2")) - tk.MustExec("drop table if exists test_add_index_with_pk2") - tk.MustExec("create table test_add_index_with_pk2(a int not null, b int not null default '0', c int unsigned, d int, primary key(c))") - tk.MustExec("insert into test_add_index_with_pk2 values(1, 1, 1, 1)") - tk.MustExec("alter table test_add_index_with_pk2 add index idx (c)") - tk.MustExec("insert into test_add_index_with_pk2 values(2, 2, 2, 2)") - tk.MustQuery("select * from test_add_index_with_pk2").Check(testkit.Rows("1 1 1 1", "2 2 2 2")) + // Ref: https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html + // TINYBLOB, TINYTEXT L + 1 bytes, where L < 2^8 + // BLOB, TEXT L + 2 bytes, where L < 2^16 + // MEDIUMBLOB, MEDIUMTEXT L + 3 bytes, where L < 2^24 + // LONGBLOB, LONGTEXT L + 4 bytes, where L < 2^32 + tk.MustExec("alter table t change column d d text(100);") + tk.MustExec("alter table t change column c c text(30000);") + tk.MustExec("alter table t change column b b text(10000000);") + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ + "t CREATE TABLE `t` (\n"+ + " `a` tinytext DEFAULT NULL,\n"+ + " `b` longtext DEFAULT NULL,\n"+ + " `c` mediumtext DEFAULT NULL,\n"+ + " `d` text DEFAULT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int, b int, c int, primary key(a, b));") - tk.MustExec("insert into t values (1, 2, 3);") - tk.MustExec("create index idx on t (a, b);") } -func (s *testDBSuite7) TestAddIndexWithPK(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) +func TestGetTimeZone(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - testAddIndexWithPK(tk) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - testAddIndexWithPK(tk) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") -func (s *testDBSuite5) TestAddIndexWithDupIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - - err1 := ddl.ErrDupKeyName.GenWithStack("index already exist %s", "idx") - err2 := ddl.ErrDupKeyName.GenWithStack("index already exist %s; "+ - "a background job is trying to add the same index, "+ - "please check by `ADMIN SHOW DDL JOBS`", "idx") - - // When there is already an duplicate index, show error message. - tk.MustExec("create table test_add_index_with_dup (a int, key idx (a))") - _, err := tk.Exec("alter table test_add_index_with_dup add index idx (a)") - c.Check(errors.Cause(err1).(*terror.Error).Equal(err), Equals, true) - c.Assert(errors.Cause(err1).Error() == err.Error(), IsTrue) - - // When there is another session adding duplicate index with state other than - // StatePublic, show explicit error message. - t := s.testGetTable(c, "test_add_index_with_dup") - indexInfo := t.Meta().FindIndexByName("idx") - indexInfo.State = model.StateNone - _, err = tk.Exec("alter table test_add_index_with_dup add index idx (a)") - c.Check(errors.Cause(err2).(*terror.Error).Equal(err), Equals, true) - c.Assert(errors.Cause(err2).Error() == err.Error(), IsTrue) - - tk.MustExec("drop table test_add_index_with_dup") + testCases := []struct { + tzSQL string + tzStr string + tzName string + offset int + err string + }{ + {"set time_zone = '+00:00'", "", "UTC", 0, ""}, + {"set time_zone = '-00:00'", "", "UTC", 0, ""}, + {"set time_zone = 'UTC'", "UTC", "UTC", 0, ""}, + {"set time_zone = '+05:00'", "", "UTC", 18000, ""}, + {"set time_zone = '-08:00'", "", "UTC", -28800, ""}, + {"set time_zone = '+08:00'", "", "UTC", 28800, ""}, + {"set time_zone = 'Asia/Shanghai'", "Asia/Shanghai", "Asia/Shanghai", 0, ""}, + {"set time_zone = 'SYSTEM'", "Asia/Shanghai", "Asia/Shanghai", 0, ""}, + {"set time_zone = DEFAULT", "Asia/Shanghai", "Asia/Shanghai", 0, ""}, + {"set time_zone = 'GMT'", "GMT", "GMT", 0, ""}, + {"set time_zone = 'GMT+1'", "GMT", "GMT", 0, "[variable:1298]Unknown or incorrect time zone: 'GMT+1'"}, + {"set time_zone = 'Etc/GMT+12'", "Etc/GMT+12", "Etc/GMT+12", 0, ""}, + {"set time_zone = 'Etc/GMT-12'", "Etc/GMT-12", "Etc/GMT-12", 0, ""}, + {"set time_zone = 'EST'", "EST", "EST", 0, ""}, + {"set time_zone = 'Australia/Lord_Howe'", "Australia/Lord_Howe", "Australia/Lord_Howe", 0, ""}, + } + for _, tc := range testCases { + if tc.err != "" { + tk.MustGetErrMsg(tc.tzSQL, tc.err) + } else { + tk.MustExec(tc.tzSQL) + } + require.Equal(t, tc.tzStr, tk.Session().GetSessionVars().TimeZone.String(), fmt.Sprintf("sql: %s", tc.tzSQL)) + tz, offset := ddlutil.GetTimeZone(tk.Session()) + require.Equal(t, tz, tc.tzName, fmt.Sprintf("sql: %s, offset: %d", tc.tzSQL, offset)) + require.Equal(t, offset, tc.offset, fmt.Sprintf("sql: %s", tc.tzSQL)) + } } -func (s *testDBSuite1) TestRenameIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("create table t (pk int primary key, c int default 1, c1 int default 1, unique key k1(c), key k2(c1))") - - // Test rename success - tk.MustExec("alter table t rename index k1 to k3") - tk.MustExec("admin check index t k3") +// for issue #30328 +func TestTooBigFieldLengthAutoConvert(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - // Test rename to the same name - tk.MustExec("alter table t rename index k3 to k3") - tk.MustExec("admin check index t k3") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") - // Test rename on non-exists keys - tk.MustGetErrCode("alter table t rename index x to x", errno.ErrKeyDoesNotExist) + err := tk.ExecToErr("create table i30328_1(a varbinary(70000), b varchar(70000000))") + require.True(t, types.ErrTooBigFieldLength.Equal(err)) - // Test rename on already-exists keys - tk.MustGetErrCode("alter table t rename index k3 to k2", errno.ErrDupKeyName) + // save previous sql_mode and change + r := tk.MustQuery("select @@sql_mode") + defer func(sqlMode string) { + tk.MustExec("set @@sql_mode= '" + sqlMode + "'") + tk.MustExec("drop table if exists i30328_1") + tk.MustExec("drop table if exists i30328_2") + }(r.Rows()[0][0].(string)) + tk.MustExec("set @@sql_mode='NO_ENGINE_SUBSTITUTION'") - tk.MustExec("alter table t rename index k2 to K2") - tk.MustGetErrCode("alter table t rename key k3 to K2", errno.ErrDupKeyName) + tk.MustExec("create table i30328_1(a varbinary(70000), b varchar(70000000))") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1246 Converting column 'a' from VARBINARY to BLOB", "Warning 1246 Converting column 'b' from VARCHAR to TEXT")) + tk.MustExec("create table i30328_2(a varchar(200))") + tk.MustExec("alter table i30328_2 modify a varchar(70000000);") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1246 Converting column 'a' from VARCHAR to TEXT")) } -func testGetTableByName(c *C, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - c.Assert(err, IsNil) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - c.Assert(err, IsNil) - return tbl -} +// For Close issue #24288 +// see https://github.com/pingcap/tidb/issues/24288 +func TestDdlMaxLimitOfIdentifier(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func testGetSchemaByName(c *C, ctx sessionctx.Context, db string) *model.DBInfo { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - c.Assert(err, IsNil) - dbInfo, ok := dom.InfoSchema().SchemaByName(model.NewCIStr(db)) - c.Assert(ok, IsTrue) - return dbInfo -} + tk := testkit.NewTestKit(t, store) -func (s *testDBSuite) testGetTable(c *C, name string) table.Table { - ctx := s.s.(sessionctx.Context) - return testGetTableByName(c, ctx, s.schemaName, name) -} + // create/drop database test + longDbName := strings.Repeat("库", mysql.MaxDatabaseNameLength-1) + tk.MustExec(fmt.Sprintf("create database %s", longDbName)) + defer func() { + tk.MustExec(fmt.Sprintf("drop database %s", longDbName)) + }() + tk.MustExec(fmt.Sprintf("use %s", longDbName)) -func (s *testDBSuite) testGetDB(c *C, dbName string) *model.DBInfo { - ctx := s.s.(sessionctx.Context) - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - c.Assert(err, IsNil) - db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr(dbName)) - c.Assert(ok, IsTrue) - return db -} + // create/drop table,index test + longTblName := strings.Repeat("表", mysql.MaxTableNameLength-1) + longColName := strings.Repeat("三", mysql.MaxColumnNameLength-1) + longIdxName := strings.Repeat("索", mysql.MaxIndexIdentifierLen-1) + tk.MustExec(fmt.Sprintf("create table %s(f1 int primary key,f2 int, %s varchar(50))", longTblName, longColName)) + tk.MustExec(fmt.Sprintf("create index %s on %s(%s)", longIdxName, longTblName, longColName)) + defer func() { + tk.MustExec(fmt.Sprintf("drop index %s on %s", longIdxName, longTblName)) + tk.MustExec(fmt.Sprintf("drop table %s", longTblName)) + }() -func backgroundExec(s kv.Storage, sql string, done chan error) { - se, err := session.CreateSession4Test(s) - if err != nil { - done <- errors.Trace(err) - return - } - defer se.Close() - _, err = se.Execute(context.Background(), "use test_db") - if err != nil { - done <- errors.Trace(err) - return - } - _, err = se.Execute(context.Background(), sql) - done <- errors.Trace(err) -} + // alter table + tk.MustExec(fmt.Sprintf("alter table %s change f2 %s int", longTblName, strings.Repeat("二", mysql.MaxColumnNameLength-1))) -// TestAddPrimaryKeyRollback1 is used to test scenarios that will roll back when a duplicate primary key is encountered. -func (s *testDBSuite8) TestAddPrimaryKeyRollback1(c *C) { - hasNullValsInKey := false - idxName := "PRIMARY" - addIdxSQL := "alter table t1 add primary key c3_index (c3);" - errMsg := "[kv:1062]Duplicate entry '" + strconv.Itoa(defaultBatchSize*2-10) + "' for key 'PRIMARY'" - testAddIndexRollback(c, s.store, s.lease, idxName, addIdxSQL, errMsg, hasNullValsInKey) } -// TestAddPrimaryKeyRollback2 is used to test scenarios that will roll back when a null primary key is encountered. -func (s *testDBSuite8) TestAddPrimaryKeyRollback2(c *C) { - hasNullValsInKey := true - idxName := "PRIMARY" - addIdxSQL := "alter table t1 add primary key c3_index (c3);" - errMsg := "[ddl:1138]Invalid use of NULL value" - testAddIndexRollback(c, s.store, s.lease, idxName, addIdxSQL, errMsg, hasNullValsInKey) -} +// Close issue #23321. +// See https://github.com/pingcap/tidb/issues/23321 +func TestJsonUnmarshalErrWhenPanicInCancellingPath(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func (s *testDBSuite2) TestAddUniqueIndexRollback(c *C) { - hasNullValsInKey := false - idxName := "c3_index" - addIdxSQL := "create unique index c3_index on t1 (c3)" - errMsg := "[kv:1062]Duplicate entry '" + strconv.Itoa(defaultBatchSize*2-10) + "' for key 'c3_index'" - testAddIndexRollback(c, s.store, s.lease, idxName, addIdxSQL, errMsg, hasNullValsInKey) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") -func (s *testSerialDBSuite) TestWriteReorgForColumnTypeChangeOnAmendTxn(c *C) { - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test_db") - tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = ON;") - defer func() { - tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = OFF;") - }() + tk.MustExec("drop table if exists test_add_index_after_add_col") + tk.MustExec("create table test_add_index_after_add_col(a int, b int not null default '0');") + tk.MustExec("insert into test_add_index_after_add_col values(1, 2),(2,2);") + tk.MustExec("alter table test_add_index_after_add_col add column c int not null default '0';") + tk.MustGetErrMsg("alter table test_add_index_after_add_col add unique index cc(c);", "[kv:1062]Duplicate entry '0' for key 'cc'") +} - d := s.dom.DDL() - originalHook := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalHook) - testInsertOnModifyColumn := func(sql string, startColState, commitColState model.SchemaState, retStrs []string, retErr error) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") - tk.MustExec("insert into t1 values (20, 20, 20);") - - var checkErr error - tk1 := testkit.NewTestKit(c, s.store) - defer func() { - if tk1.Se != nil { - tk1.Se.Close() - } - }() - hook := &ddl.TestDDLCallback{Do: s.dom} - times := 0 - hook.OnJobUpdatedExported = func(job *model.Job) { - if job.Type != model.ActionModifyColumn || checkErr != nil || - (job.SchemaState != startColState && job.SchemaState != commitColState) { - return - } +func TestIssue22819(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - if job.SchemaState == startColState { - tk1.MustExec("use test_db") - tk1.MustExec("begin pessimistic;") - tk1.MustExec("insert into t1 values(101, 102, 103)") - return - } - if times == 0 { - _, checkErr = tk1.Exec("commit;") - } - times++ - } - d.(ddl.DDLForTest).SetHook(hook) + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test;") + tk1.MustExec("create table t1 (v int) partition by hash (v) partitions 2") + tk1.MustExec("insert into t1 values (1)") - tk.MustExec(sql) - if retErr == nil { - c.Assert(checkErr, IsNil) - } else { - c.Assert(strings.Contains(checkErr.Error(), retErr.Error()), IsTrue) - } - tk.MustQuery("select * from t1;").Check(testkit.Rows(retStrs...)) + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test;") + tk1.MustExec("begin") + tk1.MustExec("update t1 set v = 2 where v = 1") - tk.MustExec("admin check table t1") - } + tk2.MustExec("alter table t1 truncate partition p0") - // Testing it needs reorg data. - ddlStatement := "alter table t1 change column c2 cc smallint;" - testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged) - - // Testing it needs not reorg data. This case only have two state: none, public. - ddlStatement = "alter table t1 change column c2 cc bigint;" - testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, nil) - testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, nil) - testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20", "101 102 103"}, nil) - testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, nil) + err := tk1.ExecToErr("commit") + require.Error(t, err) + require.Regexp(t, ".*8028.*Information schema is changed during the execution of the statement.*", err.Error()) } -func (s *testSerialDBSuite) TestAddExpressionIndexRollback(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") - tk.MustExec("insert into t1 values (20, 20, 20), (40, 40, 40), (80, 80, 80), (160, 160, 160);") +func TestIssue22307(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() - var checkErr error - tk1 := testkit.NewTestKit(c, s.store) - _, checkErr = tk1.Exec("use test_db") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int)") + tk.MustExec("insert into t values(1, 1);") - d := s.dom.DDL() - hook := &ddl.TestDDLCallback{Do: s.dom} - var currJob *model.Job - ctx := mock.NewContext() - ctx.Store = s.store - times := 0 - hook.OnJobUpdatedExported = func(job *model.Job) { - if checkErr != nil { + hook := &ddl.TestDDLCallback{Do: dom} + var checkErr1, checkErr2 error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.SchemaState != model.StateWriteOnly { return } - switch job.SchemaState { - case model.StateDeleteOnly: - _, checkErr = tk1.Exec("insert into t1 values (6, 3, 3) on duplicate key update c1 = 10") - if checkErr == nil { - _, checkErr = tk1.Exec("update t1 set c1 = 7 where c2=6;") - } - if checkErr == nil { - _, checkErr = tk1.Exec("delete from t1 where c1 = 40;") - } - case model.StateWriteOnly: - _, checkErr = tk1.Exec("insert into t1 values (2, 2, 2)") - if checkErr == nil { - _, checkErr = tk1.Exec("update t1 set c1 = 3 where c2 = 80") - } - case model.StateWriteReorganization: - if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 { - _, checkErr = tk1.Exec("insert into t1 values (4, 4, 4)") - if checkErr != nil { - return - } - _, checkErr = tk1.Exec("update t1 set c1 = 5 where c2 = 80") - if checkErr != nil { - return - } - currJob = job - times++ - } - } + _, checkErr1 = tk.Exec("update t set a = 3 where b = 1;") + _, checkErr2 = tk.Exec("update t set a = 3 order by b;") } - d.(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) + done := make(chan error, 1) + // test transaction on add column. + go backgroundExec(store, "alter table t drop column b;", done) + err := <-done + require.NoError(t, err) + require.EqualError(t, checkErr1, "[planner:1054]Unknown column 'b' in 'where clause'") + require.EqualError(t, checkErr2, "[planner:1054]Unknown column 'b' in 'order clause'") +} - tk.MustGetErrMsg("alter table t1 add index expr_idx ((pow(c1, c2)));", "[ddl:8202]Cannot decode index value, because [types:1690]DOUBLE value is out of range in 'pow(160, 160)'") - c.Assert(checkErr, IsNil) - tk.MustQuery("select * from t1 order by c1;").Check(testkit.Rows("2 2 2", "4 4 4", "5 80 80", "10 3 3", "20 20 20", "160 160 160")) +func TestIssue9100(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - // Check whether the reorg information is cleaned up. - err := ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - m := meta.NewMeta(txn) - element, start, end, physicalID, err := m.GetDDLReorgHandle(currJob) - c.Assert(meta.ErrDDLReorgElementNotExist.Equal(err), IsTrue) - c.Assert(element, IsNil) - c.Assert(start, IsNil) - c.Assert(end, IsNil) - c.Assert(physicalID, Equals, int64(0)) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table employ (a int, b int) partition by range (b) (partition p0 values less than (1));") + tk.MustGetErrMsg("alter table employ add unique index p_a (a);", "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function") + tk.MustGetErrMsg("alter table employ add primary key p_a (a);", "[ddl:1503]A PRIMARY must include all columns in the table's partitioning function") -func (s *testSerialDBSuite) TestDropTableOnTiKVDiskFull(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("create table test_disk_full_drop_table(a int);") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull", `return(true)`), IsNil) - defer failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull") - tk.MustExec("drop table test_disk_full_drop_table;") -} + tk.MustExec("create table issue9100t1 (col1 int not null, col2 date not null, col3 int not null, unique key (col1, col2)) partition by range( col1 ) (partition p1 values less than (11))") + tk.MustExec("alter table issue9100t1 add unique index p_col1 (col1)") + tk.MustExec("alter table issue9100t1 add primary key p_col1 (col1)") -func batchInsert(tk *testkit.TestKit, tbl string, start, end int) { - dml := fmt.Sprintf("insert into %s values", tbl) - for i := start; i < end; i++ { - dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) - if i != end-1 { - dml += "," - } - } - tk.MustExec(dml) + tk.MustExec("create table issue9100t2 (col1 int not null, col2 date not null, col3 int not null, unique key (col1, col3)) partition by range( col1 + col3 ) (partition p1 values less than (11))") + tk.MustGetErrMsg("alter table issue9100t2 add unique index p_col1 (col1)", "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function") + tk.MustGetErrMsg("alter table issue9100t2 add primary key p_col1 (col1)", "[ddl:1503]A PRIMARY must include all columns in the table's partitioning function") } -func testAddIndexRollback(c *C, store kv.Storage, lease time.Duration, idxName, addIdxSQL, errMsg string, hasNullValsInKey bool) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") - // defaultBatchSize is equal to ddl.defaultBatchSize - base := defaultBatchSize * 2 - count := base - // add some rows - batchInsert(tk, "t1", 0, count) - // add some null rows - if hasNullValsInKey { - for i := count - 10; i < count; i++ { - tk.MustExec("insert into t1 values (?, ?, null)", i+10, i) - } - } else { - // add some duplicate rows - for i := count - 10; i < count; i++ { - tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) - } - } +func TestIssue22207(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - done := make(chan error, 1) - go backgroundExec(store, addIdxSQL, done) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_enable_list_partition = ON") + tk.MustExec("set @@session.tidb_enable_exchange_partition = 1;") + tk.MustExec("drop table if exists t1;") + tk.MustExec("drop table if exists t2;") + tk.MustExec("create table t1(id char(10)) partition by list columns(id) (partition p0 values in ('a'), partition p1 values in ('b'));") + tk.MustExec("insert into t1 VALUES('a')") + tk.MustExec("create table t2(id char(10));") + tk.MustExec("ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;") + tk.MustQuery("select * from t2").Check(testkit.Rows("a")) + require.Len(t, tk.MustQuery("select * from t1").Rows(), 0) - times := 0 - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, errMsg, Commentf("err:%v", err)) - break LOOP - case <-ticker.C: - if times >= 10 { - break - } - step := 5 - // delete some rows, and add some data - for i := count; i < count+step; i++ { - n := rand.Intn(count) - // (2048, 2038, 2038) and (2038, 2038, 2038) - // Don't delete rows where c1 is 2048 or 2038, otherwise, the entry value in duplicated error message would change. - if n == defaultBatchSize*2-10 || n == defaultBatchSize*2 { - continue - } - tk.MustExec("delete from t1 where c1 = ?", n) - tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) - } - count += step - times++ - } - } + tk.MustExec("drop table if exists t1;") + tk.MustExec("drop table if exists t2;") + tk.MustExec("create table t1 (id int) partition by list (id) (partition p0 values in (1,2,3), partition p1 values in (4,5,6));") + tk.MustExec("insert into t1 VALUES(1);") + tk.MustExec("insert into t1 VALUES(2);") + tk.MustExec("insert into t1 VALUES(3);") + tk.MustExec("create table t2(id int);") + tk.MustExec("ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;") + tk.MustQuery("select * from t2").Check(testkit.Rows("1", "2", "3")) + require.Len(t, tk.MustQuery("select * from t1").Rows(), 0) + tk.MustExec("set @@session.tidb_enable_exchange_partition = 0;") +} - ctx := tk.Se.(sessionctx.Context) - t := testGetTableByName(c, ctx, "test_db", "t1") - for _, tidx := range t.Indices() { - c.Assert(strings.EqualFold(tidx.Meta().Name.L, idxName), IsFalse) - } +func TestIssue23473(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - // delete duplicated/null rows, then add index - for i := base - 10; i < base; i++ { - tk.MustExec("delete from t1 where c1 = ?", i+10) - } - sessionExec(c, store, addIdxSQL) - tk.MustExec("drop table t1") -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_23473;") + tk.MustExec("create table t_23473 (k int primary key, v int)") + tk.MustExec("alter table t_23473 change column k k bigint") -func (s *testDBSuite8) TestCancelAddPrimaryKey(c *C) { - idxName := "primary" - addIdxSQL := "alter table t1 add primary key idx_c2 (c2);" - testCancelAddIndex(c, s.store, s.dom.DDL(), s.lease, idxName, addIdxSQL, "", s.dom) - - // Check the column's flag when the "add primary key" failed. - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - ctx := tk.Se.(sessionctx.Context) - c.Assert(ctx.NewTxn(context.Background()), IsNil) - t := testGetTableByName(c, ctx, "test_db", "t1") - col1Flag := t.Cols()[1].Flag - c.Assert(!mysql.HasNotNullFlag(col1Flag) && !mysql.HasPreventNullInsertFlag(col1Flag) && mysql.HasUnsignedFlag(col1Flag), IsTrue) - tk.MustExec("drop table t1") + tbl := external.GetTableByName(t, tk, "test", "t_23473") + require.True(t, mysql.HasNoDefaultValueFlag(tbl.Cols()[0].Flag)) } -func (s *testDBSuite7) TestCancelAddIndex(c *C) { - idxName := "c3_index" - addIdxSQL := "create unique index c3_index on t1 (c3)" - testCancelAddIndex(c, s.store, s.dom.DDL(), s.lease, idxName, addIdxSQL, "", s.dom) +func TestDropCheck(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("drop table t1") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists drop_check") + tk.MustExec("create table drop_check (pk int primary key)") + defer tk.MustExec("drop table if exists drop_check") + tk.MustExec("alter table drop_check drop check crcn") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8231|DROP CHECK is not supported")) } -func testCancelAddIndex(c *C, store kv.Storage, d ddl.DDL, lease time.Duration, idxName, addIdxSQL, sqlModeSQL string, dom *domain.Domain) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int unsigned, c3 int, unique key(c1))") - // defaultBatchSize is equal to ddl.defaultBatchSize - count := defaultBatchSize * 32 - start := 0 - // add some rows - if len(sqlModeSQL) != 0 { - // Insert some null values. - tk.MustExec(sqlModeSQL) - tk.MustExec("insert into t1 set c1 = ?", 0) - tk.MustExec("insert into t1 set c2 = ?", 1) - tk.MustExec("insert into t1 set c3 = ?", 2) - start = 3 - } - for i := start; i < count; i += defaultBatchSize { - batchInsert(tk, "t1", i, i+defaultBatchSize) - } +func TestAlterOrderBy(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - var c3IdxInfo *model.IndexInfo - hook := &ddl.TestDDLCallback{Do: dom} - originBatchSize := tk.MustQuery("select @@global.tidb_ddl_reorg_batch_size") - // Set batch size to lower try to slow down add-index reorganization, This if for hook to cancel this ddl job. - tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 32") - defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", originBatchSize.Rows()[0][0])) - // let hook.OnJobUpdatedExported has chance to cancel the job. - // the hook.OnJobUpdatedExported is called when the job is updated, runReorgJob will wait ddl.ReorgWaitTimeout, then return the ddl.runDDLJob. - // After that ddl call d.hook.OnJobUpdated(job), so that we can canceled the job in this test case. - var checkErr error - ctx := tk.Se.(sessionctx.Context) - hook.OnJobUpdatedExported, c3IdxInfo, checkErr = backgroundExecOnJobUpdatedExported(c, store, ctx, hook, idxName) - originalHook := d.GetHook() - jobIDExt := wrapJobIDExtCallback(hook) - d.(ddl.DDLForTest).SetHook(jobIDExt) - done := make(chan error, 1) - go backgroundExec(store, addIdxSQL, done) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table ob (pk int primary key, c int default 1, c1 int default 1, KEY cl(c1))") - times := 0 - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - break LOOP - case <-ticker.C: - if times >= 10 { - break - } - step := 5 - // delete some rows, and add some data - for i := count; i < count+step; i++ { - n := rand.Intn(count) - tk.MustExec("delete from t1 where c1 = ?", n) - tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) - } - count += step - times++ - } - } - checkDelRangeAdded(tk, jobIDExt.jobID, c3IdxInfo.ID) - d.(ddl.DDLForTest).SetHook(originalHook) -} + // Test order by with primary key + tk.MustExec("alter table ob order by c") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1105|ORDER BY ignored as there is a user-defined clustered index in the table 'ob'")) -// TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started. -func (s *testDBSuite4) TestCancelAddIndex1(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t") - s.mustExec(tk, c, "create table t(c1 int, c2 int)") - defer s.mustExec(tk, c, "drop table t;") + // Test order by with no primary key + tk.MustExec("drop table if exists ob") + tk.MustExec("create table ob (c int default 1, c1 int default 1, KEY cl(c1))") + tk.MustExec("alter table ob order by c") + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustExec("drop table if exists ob") +} - for i := 0; i < 50; i++ { - s.mustExec(tk, c, "insert into t values (?, ?)", i, i) - } +func TestFKOnGeneratedColumns(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // test add foreign key to generated column - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - - checkErr = txn.Commit(context.Background()) - } - } - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - rs, err := tk.Exec("alter table t add index idx_c2(c2)") - if rs != nil { - rs.Close() - } - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - t := s.testGetTable(c, "t") - for _, idx := range t.Indices() { - c.Assert(strings.EqualFold(idx.Meta().Name.L, "idx_c2"), IsFalse) - } - s.mustExec(tk, c, "alter table t add index idx_c2(c2)") - s.mustExec(tk, c, "alter table t drop index idx_c2") -} - -// TestCancelDropIndex tests cancel ddl job which type is drop primary key. -func (s *testDBSuite4) TestCancelDropPrimaryKey(c *C) { - idxName := "primary" - addIdxSQL := "alter table t add primary key idx_c2 (c2);" - dropIdxSQL := "alter table t drop primary key;" - testCancelDropIndex(c, s.store, s.dom.DDL(), idxName, addIdxSQL, dropIdxSQL, s.dom) -} - -// TestCancelDropIndex tests cancel ddl job which type is drop index. -func (s *testDBSuite5) TestCancelDropIndex(c *C) { - idxName := "idx_c2" - addIdxSQL := "alter table t add index idx_c2 (c2);" - dropIdxSQL := "alter table t drop index idx_c2;" - testCancelDropIndex(c, s.store, s.dom.DDL(), idxName, addIdxSQL, dropIdxSQL, s.dom) -} - -// testCancelDropIndex tests cancel ddl job which type is drop index. -func testCancelDropIndex(c *C, store kv.Storage, d ddl.DDL, idxName, addIdxSQL, dropIdxSQL string, dom *domain.Domain) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(c1 int, c2 int)") - defer tk.MustExec("drop table t;") - for i := 0; i < 5; i++ { - tk.MustExec("insert into t values (?, ?)", i, i) - } - testCases := []struct { - needAddIndex bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - // model.JobStateNone means the jobs is canceled before the first run. - // if we cancel successfully, we need to set needAddIndex to false in the next test case. Otherwise, set needAddIndex to true. - {true, model.JobStateNone, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: dom} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if (job.Type == model.ActionDropIndex || job.Type == model.ActionDropPrimaryKey) && - job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobID = job.ID - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := d.GetHook() - d.(ddl.DDLForTest).SetHook(hook) - ctx := tk.Se.(sessionctx.Context) - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddIndex { - tk.MustExec(addIdxSQL) - } - rs, err := tk.Exec(dropIdxSQL) - if rs != nil { - rs.Close() - } - t := testGetTableByName(c, ctx, "test_db", "t") - indexInfo := t.Meta().FindIndexByName(idxName) - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - c.Assert(indexInfo, NotNil) - c.Assert(indexInfo.State, Equals, model.StatePublic) - } else { - err1 := admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID) - c.Assert(err, IsNil) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, err1.Error()) - c.Assert(indexInfo, IsNil) - } - } - d.(ddl.DDLForTest).SetHook(originalHook) - tk.MustExec(addIdxSQL) - tk.MustExec(dropIdxSQL) -} - -// TestCancelTruncateTable tests cancel ddl job which type is truncate table. -func (s *testDBSuite5) TestCancelTruncateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "create database if not exists test_truncate_table") - s.mustExec(tk, c, "drop table if exists t") - s.mustExec(tk, c, "create table t(c1 int, c2 int)") - defer s.mustExec(tk, c, "drop table t;") - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionTruncateTable && job.State == model.JobStateNone { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err := tk.Exec("truncate table t") - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) -} - -func (s *testDBSuite5) TestParallelDropSchemaAndDropTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "create database if not exists test_drop_schema_table") - s.mustExec(tk, c, "use test_drop_schema_table") - s.mustExec(tk, c, "create table t(c1 int, c2 int)") - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - dbInfo := testGetSchemaByName(c, tk.Se, "test_drop_schema_table") - done := false - var wg sync.WaitGroup - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test_drop_schema_table") - hook.OnJobUpdatedExported = func(job *model.Job) { - if job.Type == model.ActionDropSchema && job.State == model.JobStateRunning && - job.SchemaState == model.StateWriteOnly && job.SchemaID == dbInfo.ID && done == false { - wg.Add(1) - done = true - go func() { - _, checkErr = tk2.Exec("drop table t") - wg.Done() - }() - time.Sleep(5 * time.Millisecond) - } - } - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - s.mustExec(tk, c, "drop database test_drop_schema_table") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - wg.Wait() - c.Assert(done, IsTrue) - c.Assert(checkErr, NotNil) - // There are two possible assert result because: - // 1: If drop-database is finished before drop-table being put into the ddl job queue, it will return "unknown table" error directly in the previous check. - // 2: If drop-table has passed the previous check and been put into the ddl job queue, then drop-database finished, it will return schema change error. - assertRes := checkErr.Error() == "[domain:8028]Information schema is changed during the execution of the"+ - " statement(for example, table definition may be updated by other DDL ran in parallel). "+ - "If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]" || - checkErr.Error() == "[schema:1051]Unknown table 'test_drop_schema_table.t'" - - c.Assert(assertRes, Equals, true) - - // Below behaviour is use to mock query `curl "http://$IP:10080/tiflash/replica"` - fn := func(jobs []*model.Job) (bool, error) { - return executor.GetDropOrTruncateTableInfoFromJobs(jobs, 0, s.dom, func(job *model.Job, info *model.TableInfo) (bool, error) { - return false, nil - }) - } - err := tk.Se.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := tk.Se.Txn(true) - c.Assert(err, IsNil) - err = admin.IterHistoryDDLJobs(txn, fn) - c.Assert(err, IsNil) -} - -// TestCancelRenameIndex tests cancel ddl job which type is rename index. -func (s *testDBSuite1) TestCancelRenameIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "create database if not exists test_rename_index") - s.mustExec(tk, c, "drop table if exists t") - s.mustExec(tk, c, "create table t(c1 int, c2 int)") - defer s.mustExec(tk, c, "drop table t;") - for i := 0; i < 100; i++ { - s.mustExec(tk, c, "insert into t values (?, ?)", i, i) - } - s.mustExec(tk, c, "alter table t add index idx_c2(c2)") - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionRenameIndex && job.State == model.JobStateNone { - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - rs, err := tk.Exec("alter table t rename index idx_c2 to idx_c3") - if rs != nil { - rs.Close() - } - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - t := s.testGetTable(c, "t") - for _, idx := range t.Indices() { - c.Assert(strings.EqualFold(idx.Meta().Name.L, "idx_c3"), IsFalse) - } - s.mustExec(tk, c, "alter table t rename index idx_c2 to idx_c3") -} - -// TestCancelDropTable tests cancel ddl job which type is drop table. -func (s *testDBSuite2) TestCancelDropTableAndSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) - testCases := []struct { - needAddTableOrDB bool - action model.ActionType - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - // Check drop table. - // model.JobStateNone means the jobs is canceled before the first run. - {true, model.ActionDropTable, model.JobStateNone, model.StateNone, true}, - {false, model.ActionDropTable, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.ActionDropTable, model.JobStateRunning, model.StateDeleteOnly, false}, - - // Check drop database. - {true, model.ActionDropSchema, model.JobStateNone, model.StateNone, true}, - {false, model.ActionDropSchema, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.ActionDropSchema, model.JobStateRunning, model.StateDeleteOnly, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - var jobID int64 - testCase := &testCases[0] - s.mustExec(tk, c, "create database if not exists test_drop_db") - dbInfo := s.testGetDB(c, "test_drop_db") - - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState && job.SchemaID == dbInfo.ID { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - var err error - sql := "" - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddTableOrDB { - s.mustExec(tk, c, "create database if not exists test_drop_db") - s.mustExec(tk, c, "use test_drop_db") - s.mustExec(tk, c, "create table if not exists t(c1 int, c2 int)") - } - - dbInfo = s.testGetDB(c, "test_drop_db") - - if testCase.action == model.ActionDropTable { - sql = "drop table t;" - } else if testCase.action == model.ActionDropSchema { - sql = "drop database test_drop_db;" - } - - _, err = tk.Exec(sql) - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - s.mustExec(tk, c, "insert into t values (?, ?)", i, i) - } else { - c.Assert(err, IsNil) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - _, err = tk.Exec("insert into t values (?, ?)", i, i) - c.Assert(err, NotNil) - } - } -} - -func (s *testDBSuite3) TestAddAnonymousIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - s.mustExec(tk, c, "create table t_anonymous_index (c1 int, c2 int, C3 int)") - s.mustExec(tk, c, "alter table t_anonymous_index add index (c1, c2)") - // for dropping empty index - _, err := tk.Exec("alter table t_anonymous_index drop index") - c.Assert(err, NotNil) - // The index name is c1 when adding index (c1, c2). - s.mustExec(tk, c, "alter table t_anonymous_index drop index c1") - t := s.testGetTable(c, "t_anonymous_index") - c.Assert(t.Indices(), HasLen, 0) - // for adding some indices that the first column name is c1 - s.mustExec(tk, c, "alter table t_anonymous_index add index (c1)") - _, err = tk.Exec("alter table t_anonymous_index add index c1 (c2)") - c.Assert(err, NotNil) - t = s.testGetTable(c, "t_anonymous_index") - c.Assert(t.Indices(), HasLen, 1) - idx := t.Indices()[0].Meta().Name.L - c.Assert(idx, Equals, "c1") - // The MySQL will be a warning. - s.mustExec(tk, c, "alter table t_anonymous_index add index c1_3 (c1)") - s.mustExec(tk, c, "alter table t_anonymous_index add index (c1, c2, C3)") - // The MySQL will be a warning. - s.mustExec(tk, c, "alter table t_anonymous_index add index (c1)") - t = s.testGetTable(c, "t_anonymous_index") - c.Assert(t.Indices(), HasLen, 4) - s.mustExec(tk, c, "alter table t_anonymous_index drop index c1") - s.mustExec(tk, c, "alter table t_anonymous_index drop index c1_2") - s.mustExec(tk, c, "alter table t_anonymous_index drop index c1_3") - s.mustExec(tk, c, "alter table t_anonymous_index drop index c1_4") - // for case insensitive - s.mustExec(tk, c, "alter table t_anonymous_index add index (C3)") - s.mustExec(tk, c, "alter table t_anonymous_index drop index c3") - s.mustExec(tk, c, "alter table t_anonymous_index add index c3 (C3)") - s.mustExec(tk, c, "alter table t_anonymous_index drop index C3") - // for anonymous index with column name `primary` - s.mustExec(tk, c, "create table t_primary (`primary` int, b int, key (`primary`))") - t = s.testGetTable(c, "t_primary") - c.Assert(t.Indices()[0].Meta().Name.String(), Equals, "primary_2") - s.mustExec(tk, c, "alter table t_primary add index (`primary`);") - t = s.testGetTable(c, "t_primary") - c.Assert(t.Indices()[0].Meta().Name.String(), Equals, "primary_2") - c.Assert(t.Indices()[1].Meta().Name.String(), Equals, "primary_3") - s.mustExec(tk, c, "alter table t_primary add primary key(b);") - t = s.testGetTable(c, "t_primary") - c.Assert(t.Indices()[0].Meta().Name.String(), Equals, "primary_2") - c.Assert(t.Indices()[1].Meta().Name.String(), Equals, "primary_3") - c.Assert(t.Indices()[2].Meta().Name.L, Equals, "primary") - s.mustExec(tk, c, "create table t_primary_2 (`primary` int, key primary_2 (`primary`), key (`primary`))") - t = s.testGetTable(c, "t_primary_2") - c.Assert(t.Indices()[0].Meta().Name.String(), Equals, "primary_2") - c.Assert(t.Indices()[1].Meta().Name.String(), Equals, "primary_3") - s.mustExec(tk, c, "create table t_primary_3 (`primary_2` int, key(`primary_2`), `primary` int, key(`primary`));") - t = s.testGetTable(c, "t_primary_3") - c.Assert(t.Indices()[0].Meta().Name.String(), Equals, "primary_2") - c.Assert(t.Indices()[1].Meta().Name.String(), Equals, "primary_3") -} - -func (s *testDBSuite4) TestAlterLock(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - s.mustExec(tk, c, "create table t_index_lock (c1 int, c2 int, C3 int)") - s.mustExec(tk, c, "alter table t_index_lock add index (c1, c2), lock=none") -} - -func (s *testDBSuite5) TestAddMultiColumnsIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - - tk.MustExec("drop database if exists tidb;") - tk.MustExec("create database tidb;") - tk.MustExec("use tidb;") - tk.MustExec("create table tidb.test (a int auto_increment primary key, b int);") - tk.MustExec("insert tidb.test values (1, 1);") - tk.MustExec("update tidb.test set b = b + 1 where a = 1;") - tk.MustExec("insert into tidb.test values (2, 2);") - // Test that the b value is nil. - tk.MustExec("insert into tidb.test (a) values (3);") - tk.MustExec("insert into tidb.test values (4, 4);") - // Test that the b value is nil again. - tk.MustExec("insert into tidb.test (a) values (5);") - tk.MustExec("insert tidb.test values (6, 6);") - tk.MustExec("alter table tidb.test add index idx1 (a, b);") - tk.MustExec("admin check table test") -} + // foreign key constraint cannot be defined on a virtual generated column. + tk.MustExec("create table t1 (a int primary key);") + tk.MustGetErrCode("create table t2 (a int, b int as (a+1) virtual, foreign key (b) references t1(a));", errno.ErrCannotAddForeign) + tk.MustExec("create table t2 (a int, b int generated always as (a+1) virtual);") + tk.MustGetErrCode("alter table t2 add foreign key (b) references t1(a);", errno.ErrCannotAddForeign) + tk.MustExec("drop table t1, t2;") -func (s *testDBSuite6) TestAddMultiColumnsIndexClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_add_multi_col_index_clustered;") - tk.MustExec("create database test_add_multi_col_index_clustered;") - tk.MustExec("use test_add_multi_col_index_clustered;") + // foreign key constraint can be defined on a stored generated column. + tk.MustExec("create table t2 (a int primary key);") + tk.MustExec("create table t1 (a int, b int as (a+1) stored, foreign key (b) references t2(a));") + tk.MustExec("create table t3 (a int, b int generated always as (a+1) stored);") + tk.MustExec("alter table t3 add foreign key (b) references t2(a);") + tk.MustExec("drop table t1, t2, t3;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("create table t (a int, b varchar(10), c int, primary key (a, b));") - tk.MustExec("insert into t values (1, '1', 1), (2, '2', NULL), (3, '3', 3);") - tk.MustExec("create index idx on t (a, c);") + // foreign key constraint can reference a stored generated column. + tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored primary key);") + tk.MustExec("create table t2 (a int, foreign key (a) references t1(b));") + tk.MustExec("create table t3 (a int);") + tk.MustExec("alter table t3 add foreign key (a) references t1(b);") + tk.MustExec("drop table t1, t2, t3;") - tk.MustExec("admin check index t idx;") - tk.MustExec("admin check table t;") + // rejected FK options on stored generated columns + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set null);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update cascade);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set default);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on delete set null);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on delete set default);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustExec("create table t2 (a int primary key);") + tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update cascade;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set default;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on delete set null;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on delete set default;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustExec("drop table t1, t2;") + // column name with uppercase characters + tk.MustGetErrCode("create table t1 (A int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set null);", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustExec("create table t2 (a int primary key);") + tk.MustExec("create table t1 (A int, b int generated always as (a+1) stored);") + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrWrongFKOptionForGeneratedColumn) + tk.MustExec("drop table t1, t2;") - tk.MustExec("insert into t values (5, '5', 5), (6, '6', NULL);") + // special case: TiDB error different from MySQL 8.0 + // MySQL: ERROR 3104 (HY000): Cannot define foreign key with ON UPDATE SET NULL clause on a generated column. + // TiDB: ERROR 1146 (42S02): Table 'test.t2' doesn't exist + tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") + tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrNoSuchTable) + tk.MustExec("drop table t1;") - tk.MustExec("admin check index t idx;") - tk.MustExec("admin check table t;") -} + // allowed FK options on stored generated columns + tk.MustExec("create table t1 (a int primary key, b char(5));") + tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on update restrict);") + tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on update no action);") + tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete restrict);") + tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete cascade);") + tk.MustExec("create table t6 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete no action);") + tk.MustExec("drop table t2,t3,t4,t5,t6;") + tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t2 add foreign key (b) references t1(a) on update restrict;") + tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t3 add foreign key (b) references t1(a) on update no action;") + tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t4 add foreign key (b) references t1(a) on delete restrict;") + tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t5 add foreign key (b) references t1(a) on delete cascade;") + tk.MustExec("create table t6 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t6 add foreign key (b) references t1(a) on delete no action;") + tk.MustExec("drop table t1,t2,t3,t4,t5,t6;") -func (s *testDBSuite6) TestAddPrimaryKey1(c *C) { - testAddIndex(c, s.store, s.lease, testPlain, - "create table test_add_index (c1 bigint, c2 bigint, c3 bigint, unique key(c1))", "primary") -} + // rejected FK options on the base columns of a stored generated columns + tk.MustExec("create table t2 (a int primary key);") + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update set null);", errno.ErrCannotAddForeign) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update cascade);", errno.ErrCannotAddForeign) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update set default);", errno.ErrCannotAddForeign) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete set null);", errno.ErrCannotAddForeign) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete cascade);", errno.ErrCannotAddForeign) + tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete set default);", errno.ErrCannotAddForeign) + tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update set null;", errno.ErrCannotAddForeign) + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update cascade;", errno.ErrCannotAddForeign) + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update set default;", errno.ErrCannotAddForeign) + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete set null;", errno.ErrCannotAddForeign) + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete cascade;", errno.ErrCannotAddForeign) + tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete set default;", errno.ErrCannotAddForeign) + tk.MustExec("drop table t1, t2;") -func (s *testDBSuite2) TestAddPrimaryKey2(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) - partition by range (c3) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "primary") + // allowed FK options on the base columns of a stored generated columns + tk.MustExec("create table t1 (a int primary key, b char(5));") + tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on update restrict);") + tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on update no action);") + tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on delete restrict);") + tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on delete no action);") + tk.MustExec("drop table t2,t3,t4,t5") + tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t2 add foreign key (a) references t1(a) on update restrict;") + tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t3 add foreign key (a) references t1(a) on update no action;") + tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t4 add foreign key (a) references t1(a) on delete restrict;") + tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored);") + tk.MustExec("alter table t5 add foreign key (a) references t1(a) on delete no action;") + tk.MustExec("drop table t1,t2,t3,t4,t5;") } -func (s *testDBSuite3) TestAddPrimaryKey3(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) - partition by hash (c3) partitions 4;`, "primary") -} +func TestSelectInViewFromAnotherDB(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func (s *testDBSuite4) TestAddPrimaryKey4(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) - partition by range columns (c3) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "primary") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create database test_db2") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int)") + tk.MustExec("use test_db2") + tk.MustExec("create sql security invoker view v as select * from test.t") + tk.MustExec("use test") + tk.MustExec("select test_db2.v.a from test_db2.v") } -func (s *testDBSuite6) TestAddIndex1(c *C) { - testAddIndex(c, s.store, s.lease, testPlain, - "create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1))", "") -} +func TestAddConstraintCheck(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func (s *testSerialDBSuite1) TestAddIndex1WithShardRowID(c *C) { - testAddIndex(c, s.store, s.lease, testPartition|testShardRowID, - "create table test_add_index (c1 bigint, c2 bigint, c3 bigint) SHARD_ROW_ID_BITS = 4 pre_split_regions = 4;", "") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists add_constraint_check") + tk.MustExec("create table add_constraint_check (pk int primary key, a int)") + defer tk.MustExec("drop table if exists add_constraint_check") + tk.MustExec("alter table add_constraint_check add constraint crn check (a > 1)") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8231|ADD CONSTRAINT CHECK is not supported")) } -func (s *testDBSuite2) TestAddIndex2(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) - partition by range (c1) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "") -} +func TestCreateTableIgnoreCheckConstraint(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() -func (s *testSerialDBSuite) TestAddIndex2WithShardRowID(c *C) { - testAddIndex(c, s.store, s.lease, testPartition|testShardRowID, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) - SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 - partition by range (c1) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists table_constraint_check") + tk.MustExec("CREATE TABLE admin_user (enable bool, CHECK (enable IN (0, 1)));") + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|8231|CONSTRAINT CHECK is not supported")) + tk.MustQuery("show create table admin_user").Check(testkit.RowsWithSep("|", ""+ + "admin_user CREATE TABLE `admin_user` (\n"+ + " `enable` tinyint(1) DEFAULT NULL\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) } -func (s *testDBSuite3) TestAddIndex3(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) - partition by hash (c1) partitions 4;`, "") -} +func TestAutoConvertBlobTypeByLength(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() -func (s *testSerialDBSuite1) TestAddIndex3WithShardRowID(c *C) { - testAddIndex(c, s.store, s.lease, testPartition|testShardRowID, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) - SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 - partition by hash (c1) partitions 4;`, "") -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + sql := fmt.Sprintf("create table t0(c0 Blob(%d), c1 Blob(%d), c2 Blob(%d), c3 Blob(%d))", + 255-1, 65535-1, 16777215-1, 4294967295-1) + tk.MustExec(sql) -func (s *testDBSuite8) TestAddIndex4(c *C) { - testAddIndex(c, s.store, s.lease, testPartition, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) - partition by range columns (c1) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "") -} + var tableID int64 + rs := tk.MustQuery("select TIDB_TABLE_ID from information_schema.tables where table_name='t0' and table_schema='test';") + tableIDi, _ := strconv.Atoi(rs.Rows()[0][0].(string)) + tableID = int64(tableIDi) -func (s *testSerialDBSuite) TestAddIndex4WithShardRowID(c *C) { - testAddIndex(c, s.store, s.lease, testPartition|testShardRowID, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) - SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 - partition by range columns (c1) ( - partition p0 values less than (3440), - partition p1 values less than (61440), - partition p2 values less than (122880), - partition p3 values less than (204800), - partition p4 values less than maxvalue)`, "") -} + tbl, exist := dom.InfoSchema().TableByID(tableID) + require.True(t, exist) -func (s *testDBSuite5) TestAddIndex5(c *C) { - testAddIndex(c, s.store, s.lease, testClusteredIndex, - `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c2, c3))`, "") + require.Equal(t, tbl.Cols()[0].Tp, mysql.TypeTinyBlob) + require.Equal(t, tbl.Cols()[0].Flen, 255) + require.Equal(t, tbl.Cols()[1].Tp, mysql.TypeBlob) + require.Equal(t, tbl.Cols()[1].Flen, 65535) + require.Equal(t, tbl.Cols()[2].Tp, mysql.TypeMediumBlob) + require.Equal(t, tbl.Cols()[2].Flen, 16777215) + require.Equal(t, tbl.Cols()[3].Tp, mysql.TypeLongBlob) + require.Equal(t, tbl.Cols()[3].Flen, 4294967295) } -type testAddIndexType uint8 - -const ( - testPlain testAddIndexType = 1 - testPartition testAddIndexType = 1 << 1 - testClusteredIndex testAddIndexType = 1 << 2 - testShardRowID testAddIndexType = 1 << 3 -) +func TestAddExpressionIndexRollback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") + tk.MustExec("insert into t1 values (20, 20, 20), (40, 40, 40), (80, 80, 80), (160, 160, 160);") -func testAddIndex(c *C, store kv.Storage, lease time.Duration, tp testAddIndexType, createTableSQL, idxTp string) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - isTestPartition := (testPartition & tp) > 0 - isTestShardRowID := (testShardRowID & tp) > 0 - if isTestShardRowID { - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("set global tidb_scatter_region = 1") - defer func() { - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) - tk.MustExec("set global tidb_scatter_region = 0") - }() - } - if isTestPartition { - tk.MustExec("set @@session.tidb_enable_table_partition = '1';") - } else if (testClusteredIndex & tp) > 0 { - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - } - tk.MustExec("drop table if exists test_add_index") - tk.MustExec(createTableSQL) + var checkErr error + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") - done := make(chan error, 1) - start := -10 - num := defaultBatchSize - // first add some rows - batchInsert(tk, "test_add_index", start, num) - - // Add some discrete rows. - maxBatch := 20 - batchCnt := 100 - otherKeys := make([]int, 0, batchCnt*maxBatch) - // Make sure there are no duplicate keys. - base := defaultBatchSize * 20 - for i := 1; i < batchCnt; i++ { - if isTestShardRowID { - base = i % 4 << 61 - } - n := base + i*defaultBatchSize + i - for j := 0; j < rand.Intn(maxBatch); j++ { - n += j - sql := fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", n, n, n) - tk.MustExec(sql) - otherKeys = append(otherKeys, n) + d := dom.DDL() + hook := &ddl.TestDDLCallback{Do: dom} + var currJob *model.Job + ctx := mock.NewContext() + ctx.Store = store + times := 0 + hook.OnJobUpdatedExported = func(job *model.Job) { + if checkErr != nil { + return } - } - // Encounter the value of math.MaxInt64 in middle of - v := math.MaxInt64 - defaultBatchSize/2 - tk.MustExec(fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", v, v, v)) - otherKeys = append(otherKeys, v) - - addIdxSQL := fmt.Sprintf("alter table test_add_index add %s key c3_index(c3)", idxTp) - testddlutil.SessionExecInGoroutine(store, addIdxSQL, done) - - deletedKeys := make(map[int]struct{}) - - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP + switch job.SchemaState { + case model.StateDeleteOnly: + _, checkErr = tk1.Exec("insert into t1 values (6, 3, 3) on duplicate key update c1 = 10") + if checkErr == nil { + _, checkErr = tk1.Exec("update t1 set c1 = 7 where c2=6;") } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - // When the server performance is particularly poor, - // the adding index operation can not be completed. - // So here is a limit to the number of rows inserted. - if num > defaultBatchSize*10 { - break + if checkErr == nil { + _, checkErr = tk1.Exec("delete from t1 where c1 = 40;") } - step := 5 - // delete some rows, and add some data - for i := num; i < num+step; i++ { - n := rand.Intn(num) - deletedKeys[n] = struct{}{} - sql := fmt.Sprintf("delete from test_add_index where c1 = %d", n) - tk.MustExec(sql) - sql = fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", i, i, i) - tk.MustExec(sql) + case model.StateWriteOnly: + _, checkErr = tk1.Exec("insert into t1 values (2, 2, 2)") + if checkErr == nil { + _, checkErr = tk1.Exec("update t1 set c1 = 3 where c2 = 80") } - num += step - } - } - - if isTestShardRowID { - re := tk.MustQuery("show table test_add_index regions;") - rows := re.Rows() - c.Assert(len(rows), GreaterEqual, 16) - tk.MustExec("admin check table test_add_index") - return - } - - // get exists keys - keys := make([]int, 0, num) - for i := start; i < num; i++ { - if _, ok := deletedKeys[i]; ok { - continue - } - keys = append(keys, i) - } - keys = append(keys, otherKeys...) - - // test index key - expectedRows := make([][]interface{}, 0, len(keys)) - for _, key := range keys { - expectedRows = append(expectedRows, []interface{}{key}) - } - rows := tk.MustQuery(fmt.Sprintf("select c1 from test_add_index where c3 >= %d order by c1", start)).Rows() - matchRows(c, rows, expectedRows) - - tk.MustExec("admin check table test_add_index") - if isTestPartition { - return - } - - // TODO: Support explain in future. - // rows := s.mustQuery(c, "explain select c1 from test_add_index where c3 >= 100") - - // ay := dumpRows(c, rows) - // c.Assert(strings.Contains(fmt.Sprintf("%v", ay), "c3_index"), IsTrue) - - // get all row handles - ctx := tk.Se.(sessionctx.Context) - c.Assert(ctx.NewTxn(context.Background()), IsNil) - t := testGetTableByName(c, ctx, "test_db", "test_add_index") - handles := kv.NewHandleMap() - err := tables.IterRecords(t, ctx, t.Cols(), - func(h kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - handles.Set(h, struct{}{}) - return true, nil - }) - c.Assert(err, IsNil) - - // check in index - var nidx table.Index - idxName := "c3_index" - if len(idxTp) != 0 { - idxName = "primary" - } - for _, tidx := range t.Indices() { - if tidx.Meta().Name.L == idxName { - nidx = tidx - break - } - } - // Make sure there is index with name c3_index. - c.Assert(nidx, NotNil) - c.Assert(nidx.Meta().ID, Greater, int64(0)) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Rollback() - c.Assert(err, IsNil) - - c.Assert(ctx.NewTxn(context.Background()), IsNil) - - it, err := nidx.SeekFirst(txn) - c.Assert(err, IsNil) - defer it.Close() - - for { - _, h, err := it.Next() - if terror.ErrorEqual(err, io.EOF) { - break - } - - c.Assert(err, IsNil) - _, ok := handles.Get(h) - c.Assert(ok, IsTrue, Commentf("handle: %v", h.String())) - handles.Delete(h) - } - c.Assert(handles.Len(), Equals, 0) - tk.MustExec("drop table test_add_index") -} - -func (s *testDBSuite1) TestAddIndexWithSplitTable(c *C) { - createSQL := "CREATE TABLE test_add_index(a bigint PRIMARY KEY AUTO_RANDOM(4), b varchar(255), c bigint)" - stSQL := fmt.Sprintf("SPLIT TABLE test_add_index BETWEEN (%d) AND (%d) REGIONS 16;", math.MinInt64, math.MaxInt64) - testAddIndexWithSplitTable(c, s.store, s.lease, createSQL, stSQL) -} - -func (s *testSerialDBSuite) TestAddIndexWithShardRowID(c *C) { - createSQL := "create table test_add_index(a bigint, b bigint, c bigint) SHARD_ROW_ID_BITS = 4 pre_split_regions = 4;" - testAddIndexWithSplitTable(c, s.store, s.lease, createSQL, "") -} - -func testAddIndexWithSplitTable(c *C, store kv.Storage, lease time.Duration, createSQL, splitTableSQL string) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists test_add_index") - hasAutoRadomField := len(splitTableSQL) > 0 - if !hasAutoRadomField { - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("set global tidb_scatter_region = 1") - defer func() { - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) - tk.MustExec("set global tidb_scatter_region = 0") - }() - } - tk.MustExec(createSQL) - - batchInsertRows := func(tk *testkit.TestKit, needVal bool, tbl string, start, end int) error { - dml := fmt.Sprintf("insert into %s values", tbl) - for i := start; i < end; i++ { - if needVal { - dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) - } else { - dml += "()" - } - if i != end-1 { - dml += "," - } - } - _, err := tk.Exec(dml) - return err - } - - done := make(chan error, 1) - start := -20 - num := defaultBatchSize - // Add some discrete rows. - goCnt := 10 - errCh := make(chan error, goCnt) - for i := 0; i < goCnt; i++ { - base := (i % 8) << 60 - go func(b int, eCh chan error) { - tk1 := testkit.NewTestKit(c, store) - tk1.MustExec("use test_db") - eCh <- batchInsertRows(tk1, !hasAutoRadomField, "test_add_index", base+start, base+num) - }(base, errCh) - } - for i := 0; i < goCnt; i++ { - e := <-errCh - c.Assert(e, IsNil) - } - - if hasAutoRadomField { - tk.MustQuery(splitTableSQL).Check(testkit.Rows("15 1")) - } - tk.MustQuery("select @@session.tidb_wait_split_region_finish;").Check(testkit.Rows("1")) - re := tk.MustQuery("show table test_add_index regions;") - rows := re.Rows() - c.Assert(len(rows), Equals, 16) - addIdxSQL := "alter table test_add_index add index idx(a)" - testddlutil.SessionExecInGoroutine(store, addIdxSQL, done) - - ticker := time.NewTicker(lease / 5) - defer ticker.Stop() - num = 0 -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP - } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - // When the server performance is particularly poor, - // the adding index operation can not be completed. - // So here is a limit to the number of rows inserted. - if num >= 1000 { - break - } - step := 20 - // delete, insert and update some data - for i := num; i < num+step; i++ { - sql := fmt.Sprintf("delete from test_add_index where a = %d", i+1) - tk.MustExec(sql) - if hasAutoRadomField { - sql = "insert into test_add_index values ()" - } else { - sql = fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", i, i, i) - } - tk.MustExec(sql) - sql = fmt.Sprintf("update test_add_index set b = %d", i*10) - tk.MustExec(sql) - } - num += step - } - } - - tk.MustExec("admin check table test_add_index") -} - -// TestCancelAddTableAndDropTablePartition tests cancel ddl job which type is add/drop table partition. -func (s *testDBSuite1) TestCancelAddTableAndDropTablePartition(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "create database if not exists test_partition_table") - s.mustExec(tk, c, "use test_partition_table") - s.mustExec(tk, c, "drop table if exists t_part") - s.mustExec(tk, c, `create table t_part (a int key) - partition by range(a) ( - partition p0 values less than (10), - partition p1 values less than (20) - );`) - defer s.mustExec(tk, c, "drop table t_part;") - base := 10 - for i := 0; i < base; i++ { - s.mustExec(tk, c, "insert into t_part values (?)", i) - } - - testCases := []struct { - action model.ActionType - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {model.ActionAddTablePartition, model.JobStateNone, model.StateNone, true}, - {model.ActionDropTablePartition, model.JobStateNone, model.StateNone, true}, - // Add table partition now can be cancelled in ReplicaOnly state. - {model.ActionAddTablePartition, model.JobStateRunning, model.StateReplicaOnly, true}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - testCase := &testCases[0] - var jobID int64 - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == testCase.action && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - - var err error - sql := "" - for i := range testCases { - testCase = &testCases[i] - if testCase.action == model.ActionAddTablePartition { - sql = `alter table t_part add partition ( - partition p2 values less than (30) - );` - } else if testCase.action == model.ActionDropTablePartition { - sql = "alter table t_part drop partition p1;" - } - _, err = tk.Exec(sql) - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - s.mustExec(tk, c, "insert into t_part values (?)", i+base) - - ctx := s.s.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_partition_table"), model.NewCIStr("t_part")) - c.Assert(err, IsNil) - partitionInfo := tbl.Meta().GetPartitionInfo() - c.Assert(partitionInfo, NotNil) - c.Assert(len(partitionInfo.AddingDefinitions), Equals, 0) - } else { - c.Assert(err, IsNil, Commentf("err:%v", err)) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - _, err = tk.Exec("insert into t_part values (?)", i) - c.Assert(err, NotNil) - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) -} - -func (s *testDBSuite1) TestDropPrimaryKey(c *C) { - idxName := "primary" - createSQL := "create table test_drop_index (c1 int, c2 int, c3 int, unique key(c1), primary key(c3) nonclustered)" - dropIdxSQL := "alter table test_drop_index drop primary key;" - testDropIndex(c, s.store, s.lease, createSQL, dropIdxSQL, idxName) -} - -func (s *testDBSuite2) TestDropIndex(c *C) { - idxName := "c3_index" - createSQL := "create table test_drop_index (c1 int, c2 int, c3 int, unique key(c1), key c3_index(c3))" - dropIdxSQL := "alter table test_drop_index drop index c3_index;" - testDropIndex(c, s.store, s.lease, createSQL, dropIdxSQL, idxName) -} - -func testDropIndex(c *C, store kv.Storage, lease time.Duration, createSQL, dropIdxSQL, idxName string) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists test_drop_index") - tk.MustExec(createSQL) - done := make(chan error, 1) - tk.MustExec("delete from test_drop_index") - - num := 100 - // add some rows - for i := 0; i < num; i++ { - tk.MustExec("insert into test_drop_index values (?, ?, ?)", i, i, i) - } - ctx := tk.Se.(sessionctx.Context) - indexID := testGetIndexID(c, ctx, "test_db", "test_drop_index", idxName) - jobIDExt, reset := setupJobIDExtCallback(ctx) - defer reset() - testddlutil.SessionExecInGoroutine(store, dropIdxSQL, done) - - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP - } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - step := 5 - // delete some rows, and add some data - for i := num; i < num+step; i++ { - n := rand.Intn(num) - tk.MustExec("update test_drop_index set c2 = 1 where c1 = ?", n) - tk.MustExec("insert into test_drop_index values (?, ?, ?)", i, i, i) - } - num += step - } - } - - rows := tk.MustQuery("explain select c1 from test_drop_index where c3 >= 0") - c.Assert(strings.Contains(fmt.Sprintf("%v", rows), idxName), IsFalse) - - checkDelRangeAdded(tk, jobIDExt.jobID, indexID) - tk.MustExec("drop table test_drop_index") -} - -// TestCancelDropColumn tests cancel ddl job which type is drop column. -func (s *testDBSuite3) TestCancelDropColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - s.mustExec(tk, c, "drop table if exists test_drop_column") - s.mustExec(tk, c, "create table test_drop_column(c1 int, c2 int)") - defer s.mustExec(tk, c, "drop table test_drop_column;") - testCases := []struct { - needAddColumn bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {true, model.JobStateNone, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionDropColumn && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - var err1 error - for i := range testCases { - var c3IdxID int64 - testCase = &testCases[i] - if testCase.needAddColumn { - s.mustExec(tk, c, "alter table test_drop_column add column c3 int") - s.mustExec(tk, c, "alter table test_drop_column add index idx_c3(c3)") - ctx := tk.Se.(sessionctx.Context) - c3IdxID = testGetIndexID(c, ctx, s.schemaName, "test_drop_column", "idx_c3") - } - _, err1 = tk.Exec("alter table test_drop_column drop column c3") - var col1 *table.Column - var idx1 table.Index - t := s.testGetTable(c, "test_drop_column") - for _, col := range t.Cols() { - if strings.EqualFold(col.Name.L, "c3") { - col1 = col - break - } - } - for _, idx := range t.Indices() { - if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { - idx1 = idx - break - } - } - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(col1, NotNil) - c.Assert(col1.Name.L, Equals, "c3") - c.Assert(idx1, NotNil) - c.Assert(idx1.Meta().Name.L, Equals, "idx_c3") - c.Assert(err1.Error(), Equals, "[ddl:8214]Cancelled DDL job") - } else { - c.Assert(col1, IsNil) - c.Assert(idx1, IsNil) - c.Assert(err1, IsNil) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - if c3IdxID != 0 { - // Check index is deleted - checkDelRangeAdded(tk, jobID, c3IdxID) - } - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - s.mustExec(tk, c, "alter table test_drop_column add column c3 int") - s.mustExec(tk, c, "alter table test_drop_column drop column c3") -} - -// TestCancelDropColumns tests cancel ddl job which type is drop multi-columns. -func (s *testDBSuite3) TestCancelDropColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - s.mustExec(tk, c, "drop table if exists test_drop_column") - s.mustExec(tk, c, "create table test_drop_column(c1 int, c2 int)") - defer s.mustExec(tk, c, "drop table test_drop_column;") - testCases := []struct { - needAddColumn bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - {true, model.JobStateNone, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionDropColumns && job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobIDs := []int64{job.ID} - jobID = job.ID - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - var err1 error - for i := range testCases { - var c3IdxID int64 - testCase = &testCases[i] - if testCase.needAddColumn { - s.mustExec(tk, c, "alter table test_drop_column add column c3 int, add column c4 int") - s.mustExec(tk, c, "alter table test_drop_column add index idx_c3(c3)") - ctx := tk.Se.(sessionctx.Context) - c3IdxID = testGetIndexID(c, ctx, s.schemaName, "test_drop_column", "idx_c3") - } - _, err1 = tk.Exec("alter table test_drop_column drop column c3, drop column c4") - t := s.testGetTable(c, "test_drop_column") - col3 := table.FindCol(t.Cols(), "c3") - col4 := table.FindCol(t.Cols(), "c4") - var idx3 table.Index - for _, idx := range t.Indices() { - if strings.EqualFold(idx.Meta().Name.L, "idx_c3") { - idx3 = idx - break - } - } - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(col3, NotNil) - c.Assert(col4, NotNil) - c.Assert(idx3, NotNil) - c.Assert(col3.Name.L, Equals, "c3") - c.Assert(col4.Name.L, Equals, "c4") - c.Assert(idx3.Meta().Name.L, Equals, "idx_c3") - c.Assert(err1.Error(), Equals, "[ddl:8214]Cancelled DDL job") - } else { - c.Assert(col3, IsNil) - c.Assert(col4, IsNil) - c.Assert(idx3, IsNil) - c.Assert(err1, IsNil) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) - if c3IdxID != 0 { - // Check index is deleted - checkDelRangeAdded(tk, jobID, c3IdxID) - } - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - s.mustExec(tk, c, "alter table test_drop_column add column c3 int, add column c4 int") - s.mustExec(tk, c, "alter table test_drop_column drop column c3, drop column c4") -} - -func testGetIndexID(c *C, ctx sessionctx.Context, dbName, tblName, idxName string) int64 { - is := domain.GetDomain(ctx).InfoSchema() - t, err := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName)) - c.Assert(err, IsNil) - - for _, idx := range t.Indices() { - if idx.Meta().Name.L == idxName { - return idx.Meta().ID - } - } - c.Fatalf("index %s not found(db: %s, tbl: %s)", idxName, dbName, tblName) - return -1 -} - -type testDDLJobIDCallback struct { - ddl.Callback - jobID int64 -} - -func (t *testDDLJobIDCallback) OnJobUpdated(job *model.Job) { - if t.jobID == 0 { - t.jobID = job.ID - } - if t.Callback != nil { - t.Callback.OnJobUpdated(job) - } -} - -func wrapJobIDExtCallback(oldCallback ddl.Callback) *testDDLJobIDCallback { - return &testDDLJobIDCallback{ - Callback: oldCallback, - jobID: 0, - } -} - -func setupJobIDExtCallback(ctx sessionctx.Context) (jobExt *testDDLJobIDCallback, tearDown func()) { - dom := domain.GetDomain(ctx) - originHook := dom.DDL().GetHook() - jobIDExt := wrapJobIDExtCallback(originHook) - dom.DDL().SetHook(jobIDExt) - return jobIDExt, func() { - dom.DDL().SetHook(originHook) - } -} - -func checkDelRangeAdded(tk *testkit.TestKit, jobID int64, elemID int64) { - query := `select sum(cnt) from - (select count(1) cnt from mysql.gc_delete_range where job_id = ? and element_id = ? union - select count(1) cnt from mysql.gc_delete_range_done where job_id = ? and element_id = ?) as gdr;` - tk.MustQuery(query, jobID, elemID, jobID, elemID).Check(testkit.Rows("1")) -} - -func checkGlobalIndexCleanUpDone(c *C, ctx sessionctx.Context, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, pid int64) int { - c.Assert(ctx.NewTxn(context.Background()), IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - defer func() { - err := txn.Rollback() - c.Assert(err, IsNil) - }() - - cnt := 0 - prefix := tablecodec.EncodeTableIndexPrefix(tblInfo.ID, idxInfo.ID) - it, err := txn.Iter(prefix, nil) - c.Assert(err, IsNil) - for it.Valid() { - if !it.Key().HasPrefix(prefix) { - break - } - segs := tablecodec.SplitIndexValue(it.Value()) - c.Assert(segs.PartitionID, NotNil) - _, pi, err := codec.DecodeInt(segs.PartitionID) - c.Assert(err, IsNil) - c.Assert(pi, Not(Equals), pid) - cnt++ - err = it.Next() - c.Assert(err, IsNil) - } - return cnt -} - -func (s *testDBSuite5) TestAlterPrimaryKey(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table test_add_pk(a int, b int unsigned , c varchar(255) default 'abc', d int as (a+b), e int as (a+1) stored, index idx(b))") - defer tk.MustExec("drop table test_add_pk") - - // for generated columns - tk.MustGetErrCode("alter table test_add_pk add primary key(d);", errno.ErrUnsupportedOnGeneratedColumn) - // The primary key name is the same as the existing index name. - tk.MustExec("alter table test_add_pk add primary key idx(e)") - tk.MustExec("drop index `primary` on test_add_pk") - - // for describing table - tk.MustExec("create table test_add_pk1(a int, index idx(a))") - tk.MustQuery("desc test_add_pk1").Check(testutil.RowsWithSep(",", `a,int(11),YES,MUL,,`)) - tk.MustExec("alter table test_add_pk1 add primary key idx(a)") - tk.MustQuery("desc test_add_pk1").Check(testutil.RowsWithSep(",", `a,int(11),NO,PRI,,`)) - tk.MustExec("alter table test_add_pk1 drop primary key") - tk.MustQuery("desc test_add_pk1").Check(testutil.RowsWithSep(",", `a,int(11),NO,MUL,,`)) - tk.MustExec("create table test_add_pk2(a int, b int, index idx(a))") - tk.MustExec("alter table test_add_pk2 add primary key idx(a, b)") - tk.MustQuery("desc test_add_pk2").Check(testutil.RowsWithSep(",", ""+ - "a int(11) NO PRI ]\n"+ - "[b int(11) NO PRI ")) - tk.MustQuery("show create table test_add_pk2").Check(testutil.RowsWithSep("|", ""+ - "test_add_pk2 CREATE TABLE `test_add_pk2` (\n"+ - " `a` int(11) NOT NULL,\n"+ - " `b` int(11) NOT NULL,\n"+ - " KEY `idx` (`a`),\n"+ - " PRIMARY KEY (`a`,`b`) /*T![clustered_index] NONCLUSTERED */\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("alter table test_add_pk2 drop primary key") - tk.MustQuery("desc test_add_pk2").Check(testutil.RowsWithSep(",", ""+ - "a int(11) NO MUL ]\n"+ - "[b int(11) NO ")) - - // Check if the primary key exists before checking the table's pkIsHandle. - tk.MustGetErrCode("alter table test_add_pk drop primary key", errno.ErrCantDropFieldOrKey) - - // for the limit of name - validName := strings.Repeat("a", mysql.MaxIndexIdentifierLen) - invalidName := strings.Repeat("b", mysql.MaxIndexIdentifierLen+1) - tk.MustGetErrCode("alter table test_add_pk add primary key "+invalidName+"(a)", errno.ErrTooLongIdent) - // for valid name - tk.MustExec("alter table test_add_pk add primary key " + validName + "(a)") - // for multiple primary key - tk.MustGetErrCode("alter table test_add_pk add primary key (a)", errno.ErrMultiplePriKey) - tk.MustExec("alter table test_add_pk drop primary key") - // for not existing primary key - tk.MustGetErrCode("alter table test_add_pk drop primary key", errno.ErrCantDropFieldOrKey) - tk.MustGetErrCode("drop index `primary` on test_add_pk", errno.ErrCantDropFieldOrKey) - - // for too many key parts specified - tk.MustGetErrCode("alter table test_add_pk add primary key idx_test(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17);", - errno.ErrTooManyKeyParts) - - // for the limit of comment's length - validComment := "'" + strings.Repeat("a", ddl.MaxCommentLength) + "'" - invalidComment := "'" + strings.Repeat("b", ddl.MaxCommentLength+1) + "'" - tk.MustGetErrCode("alter table test_add_pk add primary key(a) comment "+invalidComment, errno.ErrTooLongIndexComment) - // for empty sql_mode - r := tk.MustQuery("select @@sql_mode") - sqlMode := r.Rows()[0][0].(string) - tk.MustExec("set @@sql_mode=''") - tk.MustExec("alter table test_add_pk add primary key(a) comment " + invalidComment) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1688|Comment for index 'PRIMARY' is too long (max = 1024)")) - tk.MustExec("set @@sql_mode= '" + sqlMode + "'") - tk.MustExec("alter table test_add_pk drop primary key") - // for valid comment - tk.MustExec("alter table test_add_pk add primary key(a, b, c) comment " + validComment) - ctx := tk.Se.(sessionctx.Context) - c.Assert(ctx.NewTxn(context.Background()), IsNil) - t := testGetTableByName(c, ctx, "test", "test_add_pk") - col1Flag := t.Cols()[0].Flag - col2Flag := t.Cols()[1].Flag - col3Flag := t.Cols()[2].Flag - c.Assert(mysql.HasNotNullFlag(col1Flag) && !mysql.HasPreventNullInsertFlag(col1Flag), IsTrue) - c.Assert(mysql.HasNotNullFlag(col2Flag) && !mysql.HasPreventNullInsertFlag(col2Flag) && mysql.HasUnsignedFlag(col2Flag), IsTrue) - c.Assert(mysql.HasNotNullFlag(col3Flag) && !mysql.HasPreventNullInsertFlag(col3Flag) && !mysql.HasNoDefaultValueFlag(col3Flag), IsTrue) - tk.MustExec("alter table test_add_pk drop primary key") - - // for null values in primary key - tk.MustExec("drop table test_add_pk") - tk.MustExec("create table test_add_pk(a int, b int unsigned , c varchar(255) default 'abc', index idx(b))") - tk.MustExec("insert into test_add_pk set a = 0, b = 0, c = 0") - tk.MustExec("insert into test_add_pk set a = 1") - tk.MustGetErrCode("alter table test_add_pk add primary key (b)", errno.ErrInvalidUseOfNull) - tk.MustExec("insert into test_add_pk set a = 2, b = 2") - tk.MustGetErrCode("alter table test_add_pk add primary key (a, b)", errno.ErrInvalidUseOfNull) - tk.MustExec("insert into test_add_pk set a = 3, c = 3") - tk.MustGetErrCode("alter table test_add_pk add primary key (c, b, a)", errno.ErrInvalidUseOfNull) -} - -func (s *testDBSuite4) TestAddIndexWithDupCols(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - err1 := infoschema.ErrColumnExists.GenWithStackByArgs("b") - err2 := infoschema.ErrColumnExists.GenWithStackByArgs("B") - - tk.MustExec("create table test_add_index_with_dup (a int, b int)") - _, err := tk.Exec("create index c on test_add_index_with_dup(b, a, b)") - c.Check(errors.Cause(err1).(*terror.Error).Equal(err), Equals, true) - - _, err = tk.Exec("create index c on test_add_index_with_dup(b, a, B)") - c.Check(errors.Cause(err2).(*terror.Error).Equal(err), Equals, true) - - _, err = tk.Exec("alter table test_add_index_with_dup add index c (b, a, b)") - c.Check(errors.Cause(err1).(*terror.Error).Equal(err), Equals, true) - - _, err = tk.Exec("alter table test_add_index_with_dup add index c (b, a, B)") - c.Check(errors.Cause(err2).(*terror.Error).Equal(err), Equals, true) - - tk.MustExec("drop table test_add_index_with_dup") -} - -// checkGlobalIndexRow reads one record from global index and check. Only support int handle. -func checkGlobalIndexRow(c *C, ctx sessionctx.Context, tblInfo *model.TableInfo, indexInfo *model.IndexInfo, - pid int64, idxVals []types.Datum, rowVals []types.Datum) { - err := ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - sc := ctx.GetSessionVars().StmtCtx - c.Assert(err, IsNil) - - tblColMap := make(map[int64]*types.FieldType, len(tblInfo.Columns)) - for _, col := range tblInfo.Columns { - tblColMap[col.ID] = &col.FieldType - } - - // Check local index entry does not exist. - localPrefix := tablecodec.EncodeTableIndexPrefix(pid, indexInfo.ID) - it, err := txn.Iter(localPrefix, nil) - c.Assert(err, IsNil) - // no local index entry. - c.Assert(it.Valid() && it.Key().HasPrefix(localPrefix), IsFalse) - it.Close() - - // Check global index entry. - encodedValue, err := codec.EncodeKey(sc, nil, idxVals...) - c.Assert(err, IsNil) - key := tablecodec.EncodeIndexSeekKey(tblInfo.ID, indexInfo.ID, encodedValue) - c.Assert(err, IsNil) - value, err := txn.Get(context.Background(), key) - c.Assert(err, IsNil) - idxColInfos := tables.BuildRowcodecColInfoForIndexColumns(indexInfo, tblInfo) - colVals, err := tablecodec.DecodeIndexKV(key, value, len(indexInfo.Columns), tablecodec.HandleDefault, idxColInfos) - c.Assert(err, IsNil) - c.Assert(colVals, HasLen, len(idxVals)+2) - for i, val := range idxVals { - _, d, err := codec.DecodeOne(colVals[i]) - c.Assert(err, IsNil) - c.Assert(d, DeepEquals, val) - } - _, d, err := codec.DecodeOne(colVals[len(idxVals)+1]) // pid - c.Assert(err, IsNil) - c.Assert(d.GetInt64(), Equals, pid) - - _, d, err = codec.DecodeOne(colVals[len(idxVals)]) // handle - c.Assert(err, IsNil) - h := kv.IntHandle(d.GetInt64()) - rowKey := tablecodec.EncodeRowKey(pid, h.Encoded()) - rowValue, err := txn.Get(context.Background(), rowKey) - c.Assert(err, IsNil) - rowValueDatums, err := tablecodec.DecodeRowToDatumMap(rowValue, tblColMap, time.UTC) - c.Assert(err, IsNil) - c.Assert(rowValueDatums, NotNil) - for i, val := range rowVals { - c.Assert(rowValueDatums[tblInfo.Columns[i].ID], DeepEquals, val) - } -} - -func (s *testSerialDBSuite) TestAddGlobalIndex(c *C) { - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.EnableGlobalIndex = true - }) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("create table test_t1 (a int, b int) partition by range (b)" + - " (partition p0 values less than (10), " + - " partition p1 values less than (maxvalue));") - tk.MustExec("insert test_t1 values (1, 1)") - tk.MustExec("alter table test_t1 add unique index p_a (a);") - tk.MustExec("insert test_t1 values (2, 11)") - t := s.testGetTable(c, "test_t1") - tblInfo := t.Meta() - indexInfo := tblInfo.FindIndexByName("p_a") - c.Assert(indexInfo, NotNil) - c.Assert(indexInfo.Global, IsTrue) - - ctx := s.s.(sessionctx.Context) - err := ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - - // check row 1 - pid := tblInfo.Partition.Definitions[0].ID - idxVals := []types.Datum{types.NewDatum(1)} - rowVals := []types.Datum{types.NewDatum(1), types.NewDatum(1)} - checkGlobalIndexRow(c, ctx, tblInfo, indexInfo, pid, idxVals, rowVals) - - // check row 2 - pid = tblInfo.Partition.Definitions[1].ID - idxVals = []types.Datum{types.NewDatum(2)} - rowVals = []types.Datum{types.NewDatum(2), types.NewDatum(11)} - checkGlobalIndexRow(c, ctx, tblInfo, indexInfo, pid, idxVals, rowVals) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - // Test add global Primary Key index - tk.MustExec("create table test_t2 (a int, b int) partition by range (b)" + - " (partition p0 values less than (10), " + - " partition p1 values less than (maxvalue));") - tk.MustExec("insert test_t2 values (1, 1)") - tk.MustExec("alter table test_t2 add primary key (a) nonclustered;") - tk.MustExec("insert test_t2 values (2, 11)") - t = s.testGetTable(c, "test_t2") - tblInfo = t.Meta() - indexInfo = t.Meta().FindIndexByName("primary") - c.Assert(indexInfo, NotNil) - c.Assert(indexInfo.Global, IsTrue) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - - // check row 1 - pid = tblInfo.Partition.Definitions[0].ID - idxVals = []types.Datum{types.NewDatum(1)} - rowVals = []types.Datum{types.NewDatum(1), types.NewDatum(1)} - checkGlobalIndexRow(c, ctx, tblInfo, indexInfo, pid, idxVals, rowVals) - - // check row 2 - pid = tblInfo.Partition.Definitions[1].ID - idxVals = []types.Datum{types.NewDatum(2)} - rowVals = []types.Datum{types.NewDatum(2), types.NewDatum(11)} - checkGlobalIndexRow(c, ctx, tblInfo, indexInfo, pid, idxVals, rowVals) - - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) -} - -func (s *testDBSuite) showColumns(tk *testkit.TestKit, c *C, tableName string) [][]interface{} { - return s.mustQuery(tk, c, fmt.Sprintf("show columns from %s", tableName)) -} - -func (s *testDBSuite5) TestCreateIndexType(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - sql := `CREATE TABLE test_index ( - price int(5) DEFAULT '0' NOT NULL, - area varchar(40) DEFAULT '' NOT NULL, - type varchar(40) DEFAULT '' NOT NULL, - transityes set('a','b'), - shopsyes enum('Y','N') DEFAULT 'Y' NOT NULL, - schoolsyes enum('Y','N') DEFAULT 'Y' NOT NULL, - petsyes enum('Y','N') DEFAULT 'Y' NOT NULL, - KEY price (price,area,type,transityes,shopsyes,schoolsyes,petsyes));` - tk.MustExec(sql) -} - -func (s *testDBSuite6) TestColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("create table t2 (c1 int, c2 int, c3 int)") - tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") - s.testAddColumn(tk, c) - s.testDropColumn(tk, c) - tk.MustExec("drop table t2") -} - -func sessionExec(c *C, s kv.Storage, sql string) { - se, err := session.CreateSession4Test(s) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_db") - c.Assert(err, IsNil) - rs, err := se.Execute(context.Background(), sql) - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - c.Assert(rs, IsNil) - se.Close() -} - -func (s *testDBSuite) testAddColumn(tk *testkit.TestKit, c *C) { - done := make(chan error, 1) - - num := defaultBatchSize + 10 - // add some rows - batchInsert(tk, "t2", 0, num) - - testddlutil.SessionExecInGoroutine(s.store, "alter table t2 add column c4 int default -1", done) - - ticker := time.NewTicker(s.lease / 2) - defer ticker.Stop() - step := 10 -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP - } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - // delete some rows, and add some data - for i := num; i < num+step; i++ { - n := rand.Intn(num) - tk.MustExec("begin") - tk.MustExec("delete from t2 where c1 = ?", n) - tk.MustExec("commit") - - // Make sure that statement of insert and show use the same infoSchema. - tk.MustExec("begin") - _, err := tk.Exec("insert into t2 values (?, ?, ?)", i, i, i) - if err != nil { - // if err is failed, the column number must be 4 now. - values := s.showColumns(tk, c, "t2") - c.Assert(values, HasLen, 4, Commentf("err:%v", errors.ErrorStack(err))) - } - tk.MustExec("commit") - } - num += step - } - } - - // add data, here c4 must exist - for i := num; i < num+step; i++ { - tk.MustExec("insert into t2 values (?, ?, ?, ?)", i, i, i, i) - } - - rows := s.mustQuery(tk, c, "select count(c4) from t2") - c.Assert(rows, HasLen, 1) - c.Assert(rows[0], HasLen, 1) - count, err := strconv.ParseInt(rows[0][0].(string), 10, 64) - c.Assert(err, IsNil) - c.Assert(count, Greater, int64(0)) - - rows = s.mustQuery(tk, c, "select count(c4) from t2 where c4 = -1") - matchRows(c, rows, [][]interface{}{{count - int64(step)}}) - - for i := num; i < num+step; i++ { - rows = s.mustQuery(tk, c, "select c4 from t2 where c4 = ?", i) - matchRows(c, rows, [][]interface{}{{i}}) - } - - ctx := s.s.(sessionctx.Context) - t := s.testGetTable(c, "t2") - i := 0 - j := 0 - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - defer func() { - if txn, err1 := ctx.Txn(true); err1 == nil { - err := txn.Rollback() - c.Assert(err, IsNil) - } - }() - err = tables.IterRecords(t, ctx, t.Cols(), - func(_ kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { - i++ - // c4 must be -1 or > 0 - v, err1 := data[3].ToInt64(ctx.GetSessionVars().StmtCtx) - c.Assert(err1, IsNil) - if v == -1 { - j++ - } else { - c.Assert(v, Greater, int64(0)) - } - return true, nil - }) - c.Assert(err, IsNil) - c.Assert(i, Equals, int(count)) - c.Assert(i, LessEqual, num+step) - c.Assert(j, Equals, int(count)-step) - - // for modifying columns after adding columns - tk.MustExec("alter table t2 modify c4 int default 11") - for i := num + step; i < num+step+10; i++ { - s.mustExec(tk, c, "insert into t2 values (?, ?, ?, ?)", i, i, i, i) - } - rows = s.mustQuery(tk, c, "select count(c4) from t2 where c4 = -1") - matchRows(c, rows, [][]interface{}{{count - int64(step)}}) - - // add timestamp type column - s.mustExec(tk, c, "create table test_on_update_c (c1 int, c2 timestamp);") - defer tk.MustExec("drop table test_on_update_c;") - s.mustExec(tk, c, "alter table test_on_update_c add column c3 timestamp null default '2017-02-11' on update current_timestamp;") - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_on_update_c")) - c.Assert(err, IsNil) - tblInfo := tbl.Meta() - colC := tblInfo.Columns[2] - c.Assert(colC.Tp, Equals, mysql.TypeTimestamp) - hasNotNull := mysql.HasNotNullFlag(colC.Flag) - c.Assert(hasNotNull, IsFalse) - // add datetime type column - s.mustExec(tk, c, "create table test_on_update_d (c1 int, c2 datetime);") - defer tk.MustExec("drop table test_on_update_d;") - s.mustExec(tk, c, "alter table test_on_update_d add column c3 datetime on update current_timestamp;") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("test_on_update_d")) - c.Assert(err, IsNil) - tblInfo = tbl.Meta() - colC = tblInfo.Columns[2] - c.Assert(colC.Tp, Equals, mysql.TypeDatetime) - hasNotNull = mysql.HasNotNullFlag(colC.Flag) - c.Assert(hasNotNull, IsFalse) - - // add year type column - s.mustExec(tk, c, "create table test_on_update_e (c1 int);") - defer tk.MustExec("drop table test_on_update_e;") - s.mustExec(tk, c, "insert into test_on_update_e (c1) values (0);") - s.mustExec(tk, c, "alter table test_on_update_e add column c2 year not null;") - tk.MustQuery("select c2 from test_on_update_e").Check(testkit.Rows("0")) - - // test add unsupported constraint - s.mustExec(tk, c, "create table t_add_unsupported_constraint (a int);") - _, err = tk.Exec("ALTER TABLE t_add_unsupported_constraint ADD id int AUTO_INCREMENT;") - c.Assert(err.Error(), Equals, "[ddl:8200]unsupported add column 'id' constraint AUTO_INCREMENT when altering 'test_db.t_add_unsupported_constraint'") - _, err = tk.Exec("ALTER TABLE t_add_unsupported_constraint ADD id int KEY;") - c.Assert(err.Error(), Equals, "[ddl:8200]unsupported add column 'id' constraint PRIMARY KEY when altering 'test_db.t_add_unsupported_constraint'") - _, err = tk.Exec("ALTER TABLE t_add_unsupported_constraint ADD id int UNIQUE;") - c.Assert(err.Error(), Equals, "[ddl:8200]unsupported add column 'id' constraint UNIQUE KEY when altering 'test_db.t_add_unsupported_constraint'") -} - -func (s *testDBSuite) testDropColumn(tk *testkit.TestKit, c *C) { - done := make(chan error, 1) - s.mustExec(tk, c, "delete from t2") - - num := 100 - // add some rows - for i := 0; i < num; i++ { - s.mustExec(tk, c, "insert into t2 values (?, ?, ?, ?)", i, i, i, i) - } - - // get c4 column id - testddlutil.SessionExecInGoroutine(s.store, "alter table t2 drop column c4", done) - - ticker := time.NewTicker(s.lease / 2) - defer ticker.Stop() - step := 10 -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP - } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - // delete some rows, and add some data - for i := num; i < num+step; i++ { - // Make sure that statement of insert and show use the same infoSchema. - tk.MustExec("begin") - _, err := tk.Exec("insert into t2 values (?, ?, ?)", i, i, i) - if err != nil { - // If executing is failed, the column number must be 4 now. - values := s.showColumns(tk, c, "t2") - c.Assert(values, HasLen, 4, Commentf("err:%v", errors.ErrorStack(err))) - } - tk.MustExec("commit") - } - num += step - } - } - - // add data, here c4 must not exist - for i := num; i < num+step; i++ { - s.mustExec(tk, c, "insert into t2 values (?, ?, ?)", i, i, i) - } - - rows := s.mustQuery(tk, c, "select count(*) from t2") - c.Assert(rows, HasLen, 1) - c.Assert(rows[0], HasLen, 1) - count, err := strconv.ParseInt(rows[0][0].(string), 10, 64) - c.Assert(err, IsNil) - c.Assert(count, Greater, int64(0)) -} - -// TestDropColumn is for inserting value with a to-be-dropped column when do drop column. -// Column info from schema in build-insert-plan should be public only, -// otherwise they will not be consist with Table.Col(), then the server will panic. -func (s *testDBSuite6) TestDropColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database drop_col_db") - tk.MustExec("use drop_col_db") - num := 25 - multiDDL := make([]string, 0, num) - sql := "create table t2 (c1 int, c2 int, c3 int, " - for i := 4; i < 4+num; i++ { - multiDDL = append(multiDDL, fmt.Sprintf("alter table t2 drop column c%d", i)) - - if i != 3+num { - sql += fmt.Sprintf("c%d int, ", i) - } else { - sql += fmt.Sprintf("c%d int)", i) - } - } - tk.MustExec(sql) - dmlDone := make(chan error, num) - ddlDone := make(chan error, num) - - testddlutil.ExecMultiSQLInGoroutine(s.store, "drop_col_db", multiDDL, ddlDone) - for i := 0; i < num; i++ { - testddlutil.ExecMultiSQLInGoroutine(s.store, "drop_col_db", []string{"insert into t2 set c1 = 1, c2 = 1, c3 = 1, c4 = 1"}, dmlDone) - } - for i := 0; i < num; i++ { - err := <-ddlDone - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - } - - // Test for drop partition table column. - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int,b int) partition by hash(a) partitions 4;") - _, err := tk.Exec("alter table t1 drop column a") - c.Assert(err, NotNil) - // TODO: refine the error message to compatible with MySQL - c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 'a' in 'expression'") - - tk.MustExec("drop database drop_col_db") -} - -func (s *testDBSuite4) TestChangeColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - - s.mustExec(tk, c, "create table t3 (a int default '0', b varchar(10), d int not null default '0')") - s.mustExec(tk, c, "insert into t3 set b = 'a'") - tk.MustQuery("select a from t3").Check(testkit.Rows("0")) - s.mustExec(tk, c, "alter table t3 change a aa bigint") - s.mustExec(tk, c, "insert into t3 set b = 'b'") - tk.MustQuery("select aa from t3").Check(testkit.Rows("0", "")) - // for no default flag - s.mustExec(tk, c, "alter table t3 change d dd bigint not null") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - tblInfo := tbl.Meta() - colD := tblInfo.Columns[2] - hasNoDefault := mysql.HasNoDefaultValueFlag(colD.Flag) - c.Assert(hasNoDefault, IsTrue) - // for the following definitions: 'not null', 'null', 'default value' and 'comment' - s.mustExec(tk, c, "alter table t3 change b b varchar(20) null default 'c' comment 'my comment'") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - tblInfo = tbl.Meta() - colB := tblInfo.Columns[1] - c.Assert(colB.Comment, Equals, "my comment") - hasNotNull := mysql.HasNotNullFlag(colB.Flag) - c.Assert(hasNotNull, IsFalse) - s.mustExec(tk, c, "insert into t3 set aa = 3, dd = 5") - tk.MustQuery("select b from t3").Check(testkit.Rows("a", "b", "c")) - // for timestamp - s.mustExec(tk, c, "alter table t3 add column c timestamp not null") - s.mustExec(tk, c, "alter table t3 change c c timestamp null default '2017-02-11' comment 'col c comment' on update current_timestamp") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - tblInfo = tbl.Meta() - colC := tblInfo.Columns[3] - c.Assert(colC.Comment, Equals, "col c comment") - hasNotNull = mysql.HasNotNullFlag(colC.Flag) - c.Assert(hasNotNull, IsFalse) - // for enum - s.mustExec(tk, c, "alter table t3 add column en enum('a', 'b', 'c') not null default 'a'") - // https://github.com/pingcap/tidb/issues/23488 - // if there is a prefix index on the varchar column, then we can change it to text - s.mustExec(tk, c, "drop table if exists t") - s.mustExec(tk, c, "create table t (k char(10), v int, INDEX(k(7)));") - s.mustExec(tk, c, "alter table t change column k k tinytext") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test_db"), model.NewCIStr("t")) - c.Assert(err, IsNil) - - // for failing tests - sql := "alter table t3 change aa a bigint default ''" - tk.MustGetErrCode(sql, errno.ErrInvalidDefault) - sql = "alter table t3 change a testx.t3.aa bigint" - tk.MustGetErrCode(sql, errno.ErrWrongDBName) - sql = "alter table t3 change t.a aa bigint" - tk.MustGetErrCode(sql, errno.ErrWrongTableName) - s.mustExec(tk, c, "create table t4 (c1 int, c2 int, c3 int default 1, index (c1));") - tk.MustExec("insert into t4(c2) values (null);") - _, err = tk.Exec("alter table t4 change c1 a1 int not null;") - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a1' at row 1") - sql = "alter table t4 change c2 a bigint not null;" - tk.MustGetErrCode(sql, mysql.WarnDataTruncated) - sql = "alter table t3 modify en enum('a', 'z', 'b', 'c') not null default 'a'" - tk.MustExec(sql) - // Rename to an existing column. - s.mustExec(tk, c, "alter table t3 add column a bigint") - sql = "alter table t3 change aa a bigint" - tk.MustGetErrCode(sql, errno.ErrDupFieldName) - // https://github.com/pingcap/tidb/issues/23488 - s.mustExec(tk, c, "drop table if exists t5") - s.mustExec(tk, c, "create table t5 (k char(10) primary key, v int)") - sql = "alter table t5 change column k k tinytext;" - tk.MustGetErrCode(sql, mysql.ErrBlobKeyWithoutLength) - tk.MustExec("drop table t5") - - s.mustExec(tk, c, "drop table if exists t5") - s.mustExec(tk, c, "create table t5 (k char(10), v int, INDEX(k))") - sql = "alter table t5 change column k k tinytext;" - tk.MustGetErrCode(sql, mysql.ErrBlobKeyWithoutLength) - tk.MustExec("drop table t5") - - tk.MustExec("drop table t3") -} - -func (s *testDBSuite5) TestRenameColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - - assertColNames := func(tableName string, colNames ...string) { - cols := s.testGetTable(c, tableName).Cols() - c.Assert(len(cols), Equals, len(colNames), Commentf("number of columns mismatch")) - for i := range cols { - c.Assert(cols[i].Name.L, Equals, strings.ToLower(colNames[i])) - } - } - - s.mustExec(tk, c, "create table test_rename_column (id int not null primary key auto_increment, col1 int)") - s.mustExec(tk, c, "alter table test_rename_column rename column col1 to col1") - assertColNames("test_rename_column", "id", "col1") - s.mustExec(tk, c, "alter table test_rename_column rename column col1 to col2") - assertColNames("test_rename_column", "id", "col2") - - // Test renaming non-exist columns. - tk.MustGetErrCode("alter table test_rename_column rename column non_exist_col to col3", errno.ErrBadField) - - // Test renaming to an exist column. - tk.MustGetErrCode("alter table test_rename_column rename column col2 to id", errno.ErrDupFieldName) - - // Test renaming the column with foreign key. - tk.MustExec("drop table test_rename_column") - tk.MustExec("create table test_rename_column_base (base int)") - tk.MustExec("create table test_rename_column (col int, foreign key (col) references test_rename_column_base(base))") - - tk.MustGetErrCode("alter table test_rename_column rename column col to col1", errno.ErrFKIncompatibleColumns) - - tk.MustExec("drop table test_rename_column_base") - - // Test renaming generated columns. - tk.MustExec("drop table test_rename_column") - tk.MustExec("create table test_rename_column (id int, col1 int generated always as (id + 1))") - - s.mustExec(tk, c, "alter table test_rename_column rename column col1 to col2") - assertColNames("test_rename_column", "id", "col2") - s.mustExec(tk, c, "alter table test_rename_column rename column col2 to col1") - assertColNames("test_rename_column", "id", "col1") - tk.MustGetErrCode("alter table test_rename_column rename column id to id1", errno.ErrDependentByGeneratedColumn) - - // Test renaming view columns. - tk.MustExec("drop table test_rename_column") - s.mustExec(tk, c, "create table test_rename_column (id int, col1 int)") - s.mustExec(tk, c, "create view test_rename_column_view as select * from test_rename_column") - - s.mustExec(tk, c, "alter table test_rename_column rename column col1 to col2") - tk.MustGetErrCode("select * from test_rename_column_view", errno.ErrViewInvalid) - - s.mustExec(tk, c, "drop view test_rename_column_view") - tk.MustExec("drop table test_rename_column") -} - -func (s *testDBSuite7) TestSelectInViewFromAnotherDB(c *C) { - _, _ = s.s.Execute(context.Background(), "create database test_db2") - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int)") - tk.MustExec("use test_db2") - tk.MustExec("create sql security invoker view v as select * from " + s.schemaName + ".t") - tk.MustExec("use " + s.schemaName) - tk.MustExec("select test_db2.v.a from test_db2.v") -} - -func (s *testDBSuite) mustExec(tk *testkit.TestKit, c *C, query string, args ...interface{}) { - tk.MustExec(query, args...) -} - -func (s *testDBSuite) mustQuery(tk *testkit.TestKit, c *C, query string, args ...interface{}) [][]interface{} { - r := tk.MustQuery(query, args...) - return r.Rows() -} - -func matchRows(c *C, rows [][]interface{}, expected [][]interface{}) { - c.Assert(len(rows), Equals, len(expected), Commentf("got %v, expected %v", rows, expected)) - for i := range rows { - match(c, rows[i], expected[i]...) - } -} - -func match(c *C, row []interface{}, expected ...interface{}) { - c.Assert(len(row), Equals, len(expected)) - for i := range row { - got := fmt.Sprintf("%v", row[i]) - need := fmt.Sprintf("%v", expected[i]) - c.Assert(got, Equals, need) - } -} - -// TestCreateTableWithLike2 tests create table with like when refer table have non-public column/index. -func (s *testSerialDBSuite) TestCreateTableWithLike2(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1,t2;") - defer tk.MustExec("drop table if exists t1,t2;") - tk.MustExec("create table t1 (a int, b int, c int, index idx1(c));") - - tbl1 := testGetTableByName(c, s.s, "test_db", "t1") - doneCh := make(chan error, 2) - hook := &ddl.TestDDLCallback{Do: s.dom} - var onceChecker sync.Map - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type != model.ActionAddColumn && job.Type != model.ActionDropColumn && - job.Type != model.ActionAddColumns && job.Type != model.ActionDropColumns && - job.Type != model.ActionAddIndex && job.Type != model.ActionDropIndex { - return - } - if job.TableID != tbl1.Meta().ID { - return - } - - if job.SchemaState == model.StateDeleteOnly { - if _, ok := onceChecker.Load(job.ID); ok { - return - } - - onceChecker.Store(job.ID, true) - go backgroundExec(s.store, "create table t2 like t1", doneCh) - } - } - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - - // create table when refer table add column - tk.MustExec("alter table t1 add column d int") - checkTbl2 := func() { - err := <-doneCh - c.Assert(err, IsNil) - tk.MustExec("alter table t2 add column e int") - t2Info := testGetTableByName(c, s.s, "test_db", "t2") - c.Assert(len(t2Info.Meta().Columns), Equals, len(t2Info.Cols())) - } - checkTbl2() - - // create table when refer table drop column - tk.MustExec("drop table t2;") - tk.MustExec("alter table t1 drop column b;") - checkTbl2() - - // create table when refer table add index - tk.MustExec("drop table t2;") - tk.MustExec("alter table t1 add index idx2(a);") - checkTbl2 = func() { - err := <-doneCh - c.Assert(err, IsNil) - tk.MustExec("alter table t2 add column e int") - tbl2 := testGetTableByName(c, s.s, "test_db", "t2") - c.Assert(len(tbl2.Meta().Columns), Equals, len(tbl2.Cols())) - - for i := 0; i < len(tbl2.Meta().Indices); i++ { - c.Assert(tbl2.Meta().Indices[i].State, Equals, model.StatePublic) - } - } - checkTbl2() - - // create table when refer table drop index. - tk.MustExec("drop table t2;") - tk.MustExec("alter table t1 drop index idx2;") - checkTbl2() - - // Test for table has tiflash replica. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) - }() - - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - tk.MustExec("drop table if exists t1,t2;") - tk.MustExec("create table t1 (a int) partition by hash(a) partitions 2;") - tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") - t1 := testGetTableByName(c, s.s, "test_db", "t1") - // Mock for all partitions replica was available. - partition := t1.Meta().Partition - c.Assert(len(partition.Definitions), Equals, 2) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[1].ID, true) - c.Assert(err, IsNil) - t1 = testGetTableByName(c, s.s, "test_db", "t1") - c.Assert(t1.Meta().TiFlashReplica, NotNil) - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) - c.Assert(t1.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}) - - tk.MustExec("create table t2 like t1") - t2 := testGetTableByName(c, s.s, "test_db", "t2") - c.Assert(t2.Meta().TiFlashReplica.Count, Equals, t1.Meta().TiFlashReplica.Count) - c.Assert(t2.Meta().TiFlashReplica.LocationLabels, DeepEquals, t1.Meta().TiFlashReplica.LocationLabels) - c.Assert(t2.Meta().TiFlashReplica.Available, IsFalse) - c.Assert(t2.Meta().TiFlashReplica.AvailablePartitionIDs, HasLen, 0) - // Test for not affecting the original table. - t1 = testGetTableByName(c, s.s, "test_db", "t1") - c.Assert(t1.Meta().TiFlashReplica, NotNil) - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) - c.Assert(t1.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}) -} - -func (s *testSerialDBSuite) TestCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("CREATE TABLE `t` (`a` double DEFAULT 1.0 DEFAULT now() DEFAULT 2.0 );") - tk.MustExec("CREATE TABLE IF NOT EXISTS `t` (`a` double DEFAULT 1.0 DEFAULT now() DEFAULT 2.0 );") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - cols := tbl.Cols() - - c.Assert(len(cols), Equals, 1) - col := cols[0] - c.Assert(col.Name.L, Equals, "a") - d, ok := col.DefaultValue.(string) - c.Assert(ok, IsTrue) - c.Assert(d, Equals, "2.0") - - tk.MustExec("drop table t") - - tk.MustGetErrCode("CREATE TABLE `t` (`a` int) DEFAULT CHARSET=abcdefg", errno.ErrUnknownCharacterSet) - - tk.MustExec("CREATE TABLE `collateTest` (`a` int, `b` varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_slovak_ci") - expects := "collateTest CREATE TABLE `collateTest` (\n `a` int(11) DEFAULT NULL,\n `b` varchar(10) COLLATE utf8_slovak_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_slovak_ci" - tk.MustQuery("show create table collateTest").Check(testkit.Rows(expects)) - - tk.MustGetErrCode("CREATE TABLE `collateTest2` (`a` int) CHARSET utf8 COLLATE utf8mb4_unicode_ci", errno.ErrCollationCharsetMismatch) - tk.MustGetErrCode("CREATE TABLE `collateTest3` (`a` int) COLLATE utf8mb4_unicode_ci CHARSET utf8", errno.ErrConflictingDeclarations) - - tk.MustExec("CREATE TABLE `collateTest4` (`a` int) COLLATE utf8_uniCOde_ci") - expects = "collateTest4 CREATE TABLE `collateTest4` (\n `a` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci" - tk.MustQuery("show create table collateTest4").Check(testkit.Rows(expects)) - - tk.MustExec("create database test2 default charset utf8 collate utf8_general_ci") - tk.MustExec("use test2") - tk.MustExec("create table dbCollateTest (a varchar(10))") - expects = "dbCollateTest CREATE TABLE `dbCollateTest` (\n `a` varchar(10) COLLATE utf8_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci" - tk.MustQuery("show create table dbCollateTest").Check(testkit.Rows(expects)) - - // test for enum column - tk.MustExec("use test") - failSQL := "create table t_enum (a enum('e','e'));" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk = testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - failSQL = "create table t_enum (a enum('e','E')) charset=utf8 collate=utf8_general_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a enum('abc','Abc')) charset=utf8 collate=utf8_general_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a enum('e','E')) charset=utf8 collate=utf8_unicode_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a enum('ss','ß')) charset=utf8 collate=utf8_unicode_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - // test for set column - failSQL = "create table t_enum (a set('e','e'));" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a set('e','E')) charset=utf8 collate=utf8_general_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a set('abc','Abc')) charset=utf8 collate=utf8_general_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - _, err = tk.Exec("create table t_enum (a enum('B','b')) charset=utf8 collate=utf8_general_ci;") - c.Assert(err.Error(), Equals, "[types:1291]Column 'a' has duplicated value 'b' in ENUM") - failSQL = "create table t_enum (a set('e','E')) charset=utf8 collate=utf8_unicode_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - failSQL = "create table t_enum (a set('ss','ß')) charset=utf8 collate=utf8_unicode_ci;" - tk.MustGetErrCode(failSQL, errno.ErrDuplicatedValueInType) - _, err = tk.Exec("create table t_enum (a enum('ss','ß')) charset=utf8 collate=utf8_unicode_ci;") - c.Assert(err.Error(), Equals, "[types:1291]Column 'a' has duplicated value 'ß' in ENUM") - - // test for table option "union" not supported - tk.MustExec("use test") - tk.MustExec("CREATE TABLE x (a INT) ENGINE = MyISAM;") - tk.MustExec("CREATE TABLE y (a INT) ENGINE = MyISAM;") - failSQL = "CREATE TABLE z (a INT) ENGINE = MERGE UNION = (x, y);" - tk.MustGetErrCode(failSQL, errno.ErrTableOptionUnionUnsupported) - failSQL = "ALTER TABLE x UNION = (y);" - tk.MustGetErrCode(failSQL, errno.ErrTableOptionUnionUnsupported) - tk.MustExec("drop table x;") - tk.MustExec("drop table y;") - - // test for table option "insert method" not supported - tk.MustExec("use test") - tk.MustExec("CREATE TABLE x (a INT) ENGINE = MyISAM;") - tk.MustExec("CREATE TABLE y (a INT) ENGINE = MyISAM;") - failSQL = "CREATE TABLE z (a INT) ENGINE = MERGE INSERT_METHOD=LAST;" - tk.MustGetErrCode(failSQL, errno.ErrTableOptionInsertMethodUnsupported) - failSQL = "ALTER TABLE x INSERT_METHOD=LAST;" - tk.MustGetErrCode(failSQL, errno.ErrTableOptionInsertMethodUnsupported) - tk.MustExec("drop table x;") - tk.MustExec("drop table y;") -} - -func (s *testSerialDBSuite) TestRepairTable(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable"), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t, other_table, origin") - - // Test repair table when TiDB is not in repair mode. - tk.MustExec("CREATE TABLE t (a int primary key nonclustered, b varchar(10));") - _, err := tk.Exec("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: TiDB is not in REPAIR MODE") - - // Test repair table when the repaired list is empty. - domainutil.RepairInfo.SetRepairMode(true) - _, err = tk.Exec("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: repair list is empty") - - // Test repair table when it's database isn't in repairInfo. - domainutil.RepairInfo.SetRepairTableList([]string{"test.other_table"}) - _, err = tk.Exec("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: database test is not in repair") - - // Test repair table when the table isn't in repairInfo. - tk.MustExec("CREATE TABLE other_table (a int, b varchar(1), key using hash(b));") - _, err = tk.Exec("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: table t is not in repair") - - // Test user can't access to the repaired table. - _, err = tk.Exec("select * from other_table") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.other_table' doesn't exist") - - // Test create statement use the same name with what is in repaired. - _, err = tk.Exec("CREATE TABLE other_table (a int);") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:1103]Incorrect table name 'other_table'%!(EXTRA string=this table is in repair)") - - // Test column lost in repair table. - _, err = tk.Exec("admin repair table other_table CREATE TABLE other_table (a int, c char(1));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Column c has lost") - - // Test column type should be the same. - _, err = tk.Exec("admin repair table other_table CREATE TABLE other_table (a bigint, b varchar(1), key using hash(b));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Column a type should be the same") - - // Test index lost in repair table. - _, err = tk.Exec("admin repair table other_table CREATE TABLE other_table (a int unique);") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Index a has lost") - - // Test index type should be the same. - _, err = tk.Exec("admin repair table other_table CREATE TABLE other_table (a int, b varchar(2) unique)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Index b type should be the same") - - // Test sub create statement in repair statement with the same name. - _, err = tk.Exec("admin repair table other_table CREATE TABLE other_table (a int);") - c.Assert(err, IsNil) - - // Test whether repair table name is case sensitive. - domainutil.RepairInfo.SetRepairMode(true) - domainutil.RepairInfo.SetRepairTableList([]string{"test.other_table2"}) - tk.MustExec("CREATE TABLE otHer_tAblE2 (a int, b varchar(1));") - _, err = tk.Exec("admin repair table otHer_tAblE2 CREATE TABLE otHeR_tAbLe (a int, b varchar(2));") - c.Assert(err, IsNil) - repairTable := testGetTableByName(c, s.s, "test", "otHeR_tAbLe") - c.Assert(repairTable.Meta().Name.O, Equals, "otHeR_tAbLe") - - // Test memory and system database is not for repair. - domainutil.RepairInfo.SetRepairMode(true) - domainutil.RepairInfo.SetRepairTableList([]string{"test.xxx"}) - _, err = tk.Exec("admin repair table performance_schema.xxx CREATE TABLE yyy (a int);") - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: memory or system database is not for repair") - - // Test the repair detail. - turnRepairModeAndInit(true) - defer turnRepairModeAndInit(false) - // Domain reload the tableInfo and add it into repairInfo. - tk.MustExec("CREATE TABLE origin (a int primary key nonclustered auto_increment, b varchar(10), c int);") - // Repaired tableInfo has been filtered by `domain.InfoSchema()`, so get it in repairInfo. - originTableInfo, _ := domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") - - hook := &ddl.TestDDLCallback{Do: s.dom} - var repairErr error - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type != model.ActionRepairTable { - return - } - if job.TableID != originTableInfo.ID { - repairErr = errors.New("table id should be the same") - return - } - if job.SchemaState != model.StateNone { - repairErr = errors.New("repair job state should be the none") - return - } - // Test whether it's readable, when repaired table is still stateNone. - tkInternal := testkit.NewTestKitWithInit(c, s.store) - _, repairErr = tkInternal.Exec("select * from origin") - // Repaired tableInfo has been filtered by `domain.InfoSchema()`, here will get an error cause user can't get access to it. - if repairErr != nil && terror.ErrorEqual(repairErr, infoschema.ErrTableNotExists) { - repairErr = nil - } - } - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - - // Exec the repair statement to override the tableInfo. - tk.MustExec("admin repair table origin CREATE TABLE origin (a int primary key nonclustered auto_increment, b varchar(5), c int);") - c.Assert(repairErr, IsNil) - - // Check the repaired tableInfo is exactly the same with old one in tableID, indexID, colID. - // testGetTableByName will extract the Table from `domain.InfoSchema()` directly. - repairTable = testGetTableByName(c, s.s, "test", "origin") - c.Assert(repairTable.Meta().ID, Equals, originTableInfo.ID) - c.Assert(len(repairTable.Meta().Columns), Equals, 3) - c.Assert(repairTable.Meta().Columns[0].ID, Equals, originTableInfo.Columns[0].ID) - c.Assert(repairTable.Meta().Columns[1].ID, Equals, originTableInfo.Columns[1].ID) - c.Assert(repairTable.Meta().Columns[2].ID, Equals, originTableInfo.Columns[2].ID) - c.Assert(len(repairTable.Meta().Indices), Equals, 1) - c.Assert(repairTable.Meta().Indices[0].ID, Equals, originTableInfo.Columns[0].ID) - c.Assert(repairTable.Meta().AutoIncID, Equals, originTableInfo.AutoIncID) - - c.Assert(repairTable.Meta().Columns[0].Tp, Equals, mysql.TypeLong) - c.Assert(repairTable.Meta().Columns[1].Tp, Equals, mysql.TypeVarchar) - c.Assert(repairTable.Meta().Columns[1].Flen, Equals, 5) - c.Assert(repairTable.Meta().Columns[2].Tp, Equals, mysql.TypeLong) - - // Exec the show create table statement to make sure new tableInfo has been set. - result := tk.MustQuery("show create table origin") - c.Assert(result.Rows()[0][1], Equals, "CREATE TABLE `origin` (\n `a` int(11) NOT NULL AUTO_INCREMENT,\n `b` varchar(5) DEFAULT NULL,\n `c` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin") - -} - -func turnRepairModeAndInit(on bool) { - list := make([]string, 0) - if on { - list = append(list, "test.origin") - } - domainutil.RepairInfo.SetRepairMode(on) - domainutil.RepairInfo.SetRepairTableList(list) -} - -func (s *testSerialDBSuite) TestRepairTableWithPartition(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable"), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists origin") - - turnRepairModeAndInit(true) - defer turnRepairModeAndInit(false) - // Domain reload the tableInfo and add it into repairInfo. - tk.MustExec("create table origin (a int not null) partition by RANGE(a) (" + - "partition p10 values less than (10)," + - "partition p30 values less than (30)," + - "partition p50 values less than (50)," + - "partition p70 values less than (70)," + - "partition p90 values less than (90));") - // Test for some old partition has lost. - _, err := tk.Exec("admin repair table origin create table origin (a int not null) partition by RANGE(a) (" + - "partition p10 values less than (10)," + - "partition p30 values less than (30)," + - "partition p50 values less than (50)," + - "partition p90 values less than (90)," + - "partition p100 values less than (100));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Partition p100 has lost") - - // Test for some partition changed the condition. - _, err = tk.Exec("admin repair table origin create table origin (a int not null) partition by RANGE(a) (" + - "partition p10 values less than (10)," + - "partition p20 values less than (25)," + - "partition p50 values less than (50)," + - "partition p90 values less than (90));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Partition p20 has lost") - - // Test for some partition changed the partition name. - _, err = tk.Exec("admin repair table origin create table origin (a int not null) partition by RANGE(a) (" + - "partition p10 values less than (10)," + - "partition p30 values less than (30)," + - "partition pNew values less than (50)," + - "partition p90 values less than (90));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Partition pnew has lost") - - originTableInfo, _ := domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") - tk.MustExec("admin repair table origin create table origin_rename (a int not null) partition by RANGE(a) (" + - "partition p10 values less than (10)," + - "partition p30 values less than (30)," + - "partition p50 values less than (50)," + - "partition p90 values less than (90));") - repairTable := testGetTableByName(c, s.s, "test", "origin_rename") - c.Assert(repairTable.Meta().ID, Equals, originTableInfo.ID) - c.Assert(len(repairTable.Meta().Columns), Equals, 1) - c.Assert(repairTable.Meta().Columns[0].ID, Equals, originTableInfo.Columns[0].ID) - c.Assert(len(repairTable.Meta().Partition.Definitions), Equals, 4) - c.Assert(repairTable.Meta().Partition.Definitions[0].ID, Equals, originTableInfo.Partition.Definitions[0].ID) - c.Assert(repairTable.Meta().Partition.Definitions[1].ID, Equals, originTableInfo.Partition.Definitions[1].ID) - c.Assert(repairTable.Meta().Partition.Definitions[2].ID, Equals, originTableInfo.Partition.Definitions[2].ID) - c.Assert(repairTable.Meta().Partition.Definitions[3].ID, Equals, originTableInfo.Partition.Definitions[4].ID) - - // Test hash partition. - tk.MustExec("drop table if exists origin") - domainutil.RepairInfo.SetRepairMode(true) - domainutil.RepairInfo.SetRepairTableList([]string{"test.origin"}) - tk.MustExec("create table origin (a varchar(1), b int not null, c int, key idx(c)) partition by hash(b) partitions 30") - - // Test partition num in repair should be exactly same with old one, other wise will cause partition semantic problem. - _, err = tk.Exec("admin repair table origin create table origin (a varchar(2), b int not null, c int, key idx(c)) partition by hash(b) partitions 20") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8215]Failed to repair table: Hash partition num should be the same") - - originTableInfo, _ = domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") - tk.MustExec("admin repair table origin create table origin (a varchar(3), b int not null, c int, key idx(c)) partition by hash(b) partitions 30") - repairTable = testGetTableByName(c, s.s, "test", "origin") - c.Assert(repairTable.Meta().ID, Equals, originTableInfo.ID) - c.Assert(len(repairTable.Meta().Partition.Definitions), Equals, 30) - c.Assert(repairTable.Meta().Partition.Definitions[0].ID, Equals, originTableInfo.Partition.Definitions[0].ID) - c.Assert(repairTable.Meta().Partition.Definitions[1].ID, Equals, originTableInfo.Partition.Definitions[1].ID) - c.Assert(repairTable.Meta().Partition.Definitions[29].ID, Equals, originTableInfo.Partition.Definitions[29].ID) -} - -func (s *testDBSuite2) TestCreateTableWithSetCol(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t_set (a int, b set('e') default '');") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` int(11) DEFAULT NULL,\n" + - " `b` set('e') DEFAULT ''\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("drop table t_set") - tk.MustExec("create table t_set (a set('a', 'b', 'c', 'd') default 'a,c,c');") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` set('a','b','c','d') DEFAULT 'a,c'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // It's for failure cases. - // The type of default value is string. - tk.MustExec("drop table t_set") - failedSQL := "create table t_set (a set('1', '4', '10') default '3');" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - failedSQL = "create table t_set (a set('1', '4', '10') default '1,4,11');" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - failedSQL = "create table t_set (a set('1', '4', '10') default '1 ,4');" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - // The type of default value is int. - failedSQL = "create table t_set (a set('1', '4', '10') default 0);" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - failedSQL = "create table t_set (a set('1', '4', '10') default 8);" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - - // The type of default value is int. - // It's for successful cases - tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 1);") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` set('1','4','10','21') DEFAULT '1'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("drop table t_set") - tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 2);") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` set('1','4','10','21') DEFAULT '4'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("drop table t_set") - tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 3);") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` set('1','4','10','21') DEFAULT '1,4'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("drop table t_set") - tk.MustExec("create table t_set (a set('1', '4', '10', '21') default 15);") - tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" + - " `a` set('1','4','10','21') DEFAULT '1,4,10,21'\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("insert into t_set value()") - tk.MustQuery("select * from t_set").Check(testkit.Rows("1,4,10,21")) -} - -func (s *testDBSuite2) TestCreateTableWithEnumCol(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - // It's for failure cases. - // The type of default value is string. - tk.MustExec("drop table if exists t_enum") - failedSQL := "create table t_enum (a enum('1', '4', '10') default '3');" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - failedSQL = "create table t_enum (a enum('1', '4', '10') default '');" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - // The type of default value is int. - failedSQL = "create table t_enum (a enum('1', '4', '10') default 0);" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - failedSQL = "create table t_enum (a enum('1', '4', '10') default 8);" - tk.MustGetErrCode(failedSQL, errno.ErrInvalidDefault) - - // The type of default value is int. - // It's for successful cases - tk.MustExec("drop table if exists t_enum") - tk.MustExec("create table t_enum (a enum('2', '3', '4') default 2);") - ret := tk.MustQuery("show create table t_enum").Rows()[0][1] - c.Assert(strings.Contains(ret.(string), "`a` enum('2','3','4') DEFAULT '3'"), IsTrue) - tk.MustExec("drop table t_enum") - tk.MustExec("create table t_enum (a enum('a', 'c', 'd') default 2);") - ret = tk.MustQuery("show create table t_enum").Rows()[0][1] - c.Assert(strings.Contains(ret.(string), "`a` enum('a','c','d') DEFAULT 'c'"), IsTrue) - tk.MustExec("insert into t_enum value()") - tk.MustQuery("select * from t_enum").Check(testkit.Rows("c")) -} - -func (s *testDBSuite2) TestTableForeignKey(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t1 (a int, b int);") - // test create table with foreign key. - failSQL := "create table t2 (c int, foreign key (a) references t1(a));" - tk.MustGetErrCode(failSQL, errno.ErrKeyColumnDoesNotExits) - // test add foreign key. - tk.MustExec("create table t3 (a int, b int);") - failSQL = "alter table t1 add foreign key (c) REFERENCES t3(a);" - tk.MustGetErrCode(failSQL, errno.ErrKeyColumnDoesNotExits) - // test origin key not match error - failSQL = "alter table t1 add foreign key (a) REFERENCES t3(a, b);" - tk.MustGetErrCode(failSQL, errno.ErrWrongFkDef) - // Test drop column with foreign key. - tk.MustExec("create table t4 (c int,d int,foreign key (d) references t1 (b));") - failSQL = "alter table t4 drop column d" - tk.MustGetErrCode(failSQL, errno.ErrFkColumnCannotDrop) - // Test change column with foreign key. - failSQL = "alter table t4 change column d e bigint;" - tk.MustGetErrCode(failSQL, errno.ErrFKIncompatibleColumns) - // Test modify column with foreign key. - failSQL = "alter table t4 modify column d bigint;" - tk.MustGetErrCode(failSQL, errno.ErrFKIncompatibleColumns) - tk.MustQuery("select count(*) from information_schema.KEY_COLUMN_USAGE;") - tk.MustExec("alter table t4 drop foreign key d") - tk.MustExec("alter table t4 modify column d bigint;") - tk.MustExec("drop table if exists t1,t2,t3,t4;") -} - -func (s *testDBSuite2) TestDuplicateForeignKey(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("drop table if exists t1") - // Foreign table. - tk.MustExec("create table t(id int key)") - // Create target table with duplicate fk. - tk.MustGetErrCode("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`), CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))", mysql.ErrFkDupName) - tk.MustGetErrCode("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`), CONSTRAINT `fk_aaA` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))", mysql.ErrFkDupName) - - tk.MustExec("create table t1(id int, id_fk int, CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`))") - // Alter target table with duplicate fk. - tk.MustGetErrCode("alter table t1 add CONSTRAINT `fk_aaa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`)", mysql.ErrFkDupName) - tk.MustGetErrCode("alter table t1 add CONSTRAINT `fk_aAa` FOREIGN KEY (`id_fk`) REFERENCES `t` (`id`)", mysql.ErrFkDupName) - tk.MustExec("drop table if exists t") - tk.MustExec("drop table if exists t1") -} - -func (s *testDBSuite2) TestTemporaryTableForeignKey(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1 (a int, b int);") - tk.MustExec("drop table if exists t1_tmp;") - tk.MustExec("create global temporary table t1_tmp (a int, b int) on commit delete rows;") - tk.MustExec("create temporary table t2_tmp (a int, b int)") - // test add foreign key. - tk.MustExec("drop table if exists t2;") - tk.MustExec("create table t2 (a int, b int);") - failSQL := "alter table t1_tmp add foreign key (c) REFERENCES t2(a);" - tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) - failSQL = "alter table t2_tmp add foreign key (c) REFERENCES t2(a);" - tk.MustGetErrCode(failSQL, errno.ErrUnsupportedDDLOperation) - // Test drop column with foreign key. - failSQL = "create global temporary table t3 (c int,d int,foreign key (d) references t1 (b)) on commit delete rows;" - tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) - failSQL = "create temporary table t4(c int,d int,foreign key (d) references t1 (b));" - tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign) - tk.MustExec("drop table if exists t1,t2,t3, t4,t1_tmp,t2_tmp;") -} - -func (s *testDBSuite8) TestFKOnGeneratedColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - // test add foreign key to generated column - - // foreign key constraint cannot be defined on a virtual generated column. - tk.MustExec("create table t1 (a int primary key);") - tk.MustGetErrCode("create table t2 (a int, b int as (a+1) virtual, foreign key (b) references t1(a));", errno.ErrCannotAddForeign) - tk.MustExec("create table t2 (a int, b int generated always as (a+1) virtual);") - tk.MustGetErrCode("alter table t2 add foreign key (b) references t1(a);", errno.ErrCannotAddForeign) - tk.MustExec("drop table t1, t2;") - - // foreign key constraint can be defined on a stored generated column. - tk.MustExec("create table t2 (a int primary key);") - tk.MustExec("create table t1 (a int, b int as (a+1) stored, foreign key (b) references t2(a));") - tk.MustExec("create table t3 (a int, b int generated always as (a+1) stored);") - tk.MustExec("alter table t3 add foreign key (b) references t2(a);") - tk.MustExec("drop table t1, t2, t3;") - - // foreign key constraint can reference a stored generated column. - tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored primary key);") - tk.MustExec("create table t2 (a int, foreign key (a) references t1(b));") - tk.MustExec("create table t3 (a int);") - tk.MustExec("alter table t3 add foreign key (a) references t1(b);") - tk.MustExec("drop table t1, t2, t3;") - - // rejected FK options on stored generated columns - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set null);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update cascade);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set default);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on delete set null);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on delete set default);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustExec("create table t2 (a int primary key);") - tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update cascade;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set default;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on delete set null;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on delete set default;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustExec("drop table t1, t2;") - // column name with uppercase characters - tk.MustGetErrCode("create table t1 (A int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set null);", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustExec("create table t2 (a int primary key);") - tk.MustExec("create table t1 (A int, b int generated always as (a+1) stored);") - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrWrongFKOptionForGeneratedColumn) - tk.MustExec("drop table t1, t2;") - - // special case: TiDB error different from MySQL 8.0 - // MySQL: ERROR 3104 (HY000): Cannot define foreign key with ON UPDATE SET NULL clause on a generated column. - // TiDB: ERROR 1146 (42S02): Table 'test.t2' doesn't exist - tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") - tk.MustGetErrCode("alter table t1 add foreign key (b) references t2(a) on update set null;", errno.ErrNoSuchTable) - tk.MustExec("drop table t1;") - - // allowed FK options on stored generated columns - tk.MustExec("create table t1 (a int primary key, b char(5));") - tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on update restrict);") - tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on update no action);") - tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete restrict);") - tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete cascade);") - tk.MustExec("create table t6 (a int, b int generated always as (a % 10) stored, foreign key (b) references t1(a) on delete no action);") - tk.MustExec("drop table t2,t3,t4,t5,t6;") - tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t2 add foreign key (b) references t1(a) on update restrict;") - tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t3 add foreign key (b) references t1(a) on update no action;") - tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t4 add foreign key (b) references t1(a) on delete restrict;") - tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t5 add foreign key (b) references t1(a) on delete cascade;") - tk.MustExec("create table t6 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t6 add foreign key (b) references t1(a) on delete no action;") - tk.MustExec("drop table t1,t2,t3,t4,t5,t6;") - - // rejected FK options on the base columns of a stored generated columns - tk.MustExec("create table t2 (a int primary key);") - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update set null);", errno.ErrCannotAddForeign) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update cascade);", errno.ErrCannotAddForeign) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on update set default);", errno.ErrCannotAddForeign) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete set null);", errno.ErrCannotAddForeign) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete cascade);", errno.ErrCannotAddForeign) - tk.MustGetErrCode("create table t1 (a int, b int generated always as (a+1) stored, foreign key (a) references t2(a) on delete set default);", errno.ErrCannotAddForeign) - tk.MustExec("create table t1 (a int, b int generated always as (a+1) stored);") - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update set null;", errno.ErrCannotAddForeign) - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update cascade;", errno.ErrCannotAddForeign) - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on update set default;", errno.ErrCannotAddForeign) - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete set null;", errno.ErrCannotAddForeign) - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete cascade;", errno.ErrCannotAddForeign) - tk.MustGetErrCode("alter table t1 add foreign key (a) references t2(a) on delete set default;", errno.ErrCannotAddForeign) - tk.MustExec("drop table t1, t2;") - - // allowed FK options on the base columns of a stored generated columns - tk.MustExec("create table t1 (a int primary key, b char(5));") - tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on update restrict);") - tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on update no action);") - tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on delete restrict);") - tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored, foreign key (a) references t1(a) on delete no action);") - tk.MustExec("drop table t2,t3,t4,t5") - tk.MustExec("create table t2 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t2 add foreign key (a) references t1(a) on update restrict;") - tk.MustExec("create table t3 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t3 add foreign key (a) references t1(a) on update no action;") - tk.MustExec("create table t4 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t4 add foreign key (a) references t1(a) on delete restrict;") - tk.MustExec("create table t5 (a int, b int generated always as (a % 10) stored);") - tk.MustExec("alter table t5 add foreign key (a) references t1(a) on delete no action;") - tk.MustExec("drop table t1,t2,t3,t4,t5;") -} - -func (s *testSerialDBSuite) TestTruncateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table truncate_table (c1 int, c2 int)") - tk.MustExec("insert truncate_table values (1, 1), (2, 2)") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("truncate_table")) - c.Assert(err, IsNil) - oldTblID := oldTblInfo.Meta().ID - - tk.MustExec("truncate table truncate_table") - - tk.MustExec("insert truncate_table values (3, 3), (4, 4)") - tk.MustQuery("select * from truncate_table").Check(testkit.Rows("3 3", "4 4")) - - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("truncate_table")) - c.Assert(err, IsNil) - c.Assert(newTblInfo.Meta().ID, Greater, oldTblID) - - // Verify that the old table data has been deleted by background worker. - tablePrefix := tablecodec.EncodeTablePrefix(oldTblID) - hasOldTableData := true - for i := 0; i < waitForCleanDataRound; i++ { - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - it, err1 := txn.Iter(tablePrefix, nil) - if err1 != nil { - return err1 - } - if !it.Valid() { - hasOldTableData = false - } else { - hasOldTableData = it.Key().HasPrefix(tablePrefix) - } - it.Close() - return nil - }) - c.Assert(err, IsNil) - if !hasOldTableData { - break - } - time.Sleep(waitForCleanDataInterval) - } - c.Assert(hasOldTableData, IsFalse) - - // Test for truncate table should clear the tiflash available status. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) - defer func() { - err = failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) - }() - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1 (a int);") - tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") - t1 := testGetTableByName(c, s.s, "test", "t1") - // Mock for table tiflash replica was available. - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, t1.Meta().ID, true) - c.Assert(err, IsNil) - t1 = testGetTableByName(c, s.s, "test", "t1") - c.Assert(t1.Meta().TiFlashReplica, NotNil) - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) - - tk.MustExec("truncate table t1") - t2 := testGetTableByName(c, s.s, "test", "t1") - c.Assert(t2.Meta().TiFlashReplica.Count, Equals, t1.Meta().TiFlashReplica.Count) - c.Assert(t2.Meta().TiFlashReplica.LocationLabels, DeepEquals, t1.Meta().TiFlashReplica.LocationLabels) - c.Assert(t2.Meta().TiFlashReplica.Available, IsFalse) - c.Assert(t2.Meta().TiFlashReplica.AvailablePartitionIDs, HasLen, 0) - - // Test for truncate partition should clear the tiflash available status. - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1 (a int) partition by hash(a) partitions 2;") - tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") - t1 = testGetTableByName(c, s.s, "test", "t1") - // Mock for all partitions replica was available. - partition := t1.Meta().Partition - c.Assert(len(partition.Definitions), Equals, 2) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[1].ID, true) - c.Assert(err, IsNil) - t1 = testGetTableByName(c, s.s, "test", "t1") - c.Assert(t1.Meta().TiFlashReplica, NotNil) - c.Assert(t1.Meta().TiFlashReplica.Available, IsTrue) - c.Assert(t1.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}) - - tk.MustExec("alter table t1 truncate partition p0") - t2 = testGetTableByName(c, s.s, "test", "t1") - c.Assert(t2.Meta().TiFlashReplica.Count, Equals, t1.Meta().TiFlashReplica.Count) - c.Assert(t2.Meta().TiFlashReplica.LocationLabels, DeepEquals, t1.Meta().TiFlashReplica.LocationLabels) - c.Assert(t2.Meta().TiFlashReplica.Available, IsFalse) - c.Assert(t2.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[1].ID}) - // Test for truncate twice. - tk.MustExec("alter table t1 truncate partition p0") - t2 = testGetTableByName(c, s.s, "test", "t1") - c.Assert(t2.Meta().TiFlashReplica.Count, Equals, t1.Meta().TiFlashReplica.Count) - c.Assert(t2.Meta().TiFlashReplica.LocationLabels, DeepEquals, t1.Meta().TiFlashReplica.LocationLabels) - c.Assert(t2.Meta().TiFlashReplica.Available, IsFalse) - c.Assert(t2.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[1].ID}) - -} - -func (s *testDBSuite4) TestRenameTable(c *C) { - isAlterTable := false - s.testRenameTable(c, "rename table %s to %s", isAlterTable) -} - -func (s *testDBSuite5) TestAlterTableRenameTable(c *C) { - isAlterTable := true - s.testRenameTable(c, "alter table %s rename to %s", isAlterTable) -} - -func (s *testDBSuite) testRenameTable(c *C, sql string, isAlterTable bool) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - // for different databases - tk.MustExec("create table t (c1 int, c2 int)") - tk.MustExec("insert t values (1, 1), (2, 2)") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - oldTblID := oldTblInfo.Meta().ID - tk.MustExec("create database test1") - tk.MustExec("use test1") - tk.MustExec(fmt.Sprintf(sql, "test.t", "test1.t1")) - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(newTblInfo.Meta().ID, Equals, oldTblID) - tk.MustQuery("select * from t1").Check(testkit.Rows("1 1", "2 2")) - tk.MustExec("use test") - - // Make sure t doesn't exist. - tk.MustExec("create table t (c1 int, c2 int)") - tk.MustExec("drop table t") - - // for the same database - tk.MustExec("use test1") - tk.MustExec(fmt.Sprintf(sql, "t1", "t2")) - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(newTblInfo.Meta().ID, Equals, oldTblID) - tk.MustQuery("select * from t2").Check(testkit.Rows("1 1", "2 2")) - isExist := is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t1")) - c.Assert(isExist, IsFalse) - tk.MustQuery("show tables").Check(testkit.Rows("t2")) - - // for failure case - failSQL := fmt.Sprintf(sql, "test_not_exist.t", "test_not_exist.t") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - } - failSQL = fmt.Sprintf(sql, "test.test_not_exist", "test.test_not_exist") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - } - failSQL = fmt.Sprintf(sql, "test.t_not_exist", "test_not_exist.t") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - } - failSQL = fmt.Sprintf(sql, "test1.t2", "test_not_exist.t") - tk.MustGetErrCode(failSQL, errno.ErrErrorOnRename) - - tk.MustExec("use test1") - tk.MustExec("create table if not exists t_exist (c1 int, c2 int)") - failSQL = fmt.Sprintf(sql, "test1.t2", "test1.t_exist") - tk.MustGetErrCode(failSQL, errno.ErrTableExists) - failSQL = fmt.Sprintf(sql, "test.t_not_exist", "test1.t_exist") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrTableExists) - } - failSQL = fmt.Sprintf(sql, "test_not_exist.t", "test1.t_exist") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrTableExists) - } - failSQL = fmt.Sprintf(sql, "test_not_exist.t", "test1.t_not_exist") - if isAlterTable { - tk.MustGetErrCode(failSQL, errno.ErrNoSuchTable) - } else { - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - } - - // for the same table name - tk.MustExec("use test1") - tk.MustExec("create table if not exists t (c1 int, c2 int)") - tk.MustExec("create table if not exists t1 (c1 int, c2 int)") - if isAlterTable { - tk.MustExec(fmt.Sprintf(sql, "test1.t", "t")) - tk.MustExec(fmt.Sprintf(sql, "test1.t1", "test1.T1")) - } else { - tk.MustGetErrCode(fmt.Sprintf(sql, "test1.t", "t"), errno.ErrTableExists) - tk.MustGetErrCode(fmt.Sprintf(sql, "test1.t1", "test1.T1"), errno.ErrTableExists) - } - - // Test rename table name too long. - tk.MustGetErrCode("rename table test1.t1 to test1.txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", errno.ErrTooLongIdent) - tk.MustGetErrCode("alter table test1.t1 rename to test1.txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", errno.ErrTooLongIdent) - - tk.MustExec("drop database test1") -} - -func (s *testDBSuite1) TestRenameMultiTables(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t1(id int)") - tk.MustExec("create table t2(id int)") - sql := "rename table t1 to t3, t2 to t4" - _, err := tk.Exec(sql) - c.Assert(err, IsNil) - - tk.MustExec("drop table t3, t4") - - tk.MustExec("create table t1 (c1 int, c2 int)") - tk.MustExec("create table t2 (c1 int, c2 int)") - tk.MustExec("insert t1 values (1, 1), (2, 2)") - tk.MustExec("insert t2 values (1, 1), (2, 2)") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - oldTblInfo1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - oldTblID1 := oldTblInfo1.Meta().ID - oldTblInfo2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - oldTblID2 := oldTblInfo2.Meta().ID - tk.MustExec("create database test1") - tk.MustExec("use test1") - tk.MustExec("rename table test.t1 to test1.t1, test.t2 to test1.t2") - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo1, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(newTblInfo1.Meta().ID, Equals, oldTblID1) - newTblInfo2, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(newTblInfo2.Meta().ID, Equals, oldTblID2) - tk.MustQuery("select * from t1").Check(testkit.Rows("1 1", "2 2")) - tk.MustQuery("select * from t2").Check(testkit.Rows("1 1", "2 2")) - - // Make sure t1,t2 doesn't exist. - isExist := is.TableExists(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(isExist, IsFalse) - isExist = is.TableExists(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(isExist, IsFalse) - - // for the same database - tk.MustExec("use test1") - tk.MustExec("rename table test1.t1 to test1.t3, test1.t2 to test1.t4") - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo1, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - c.Assert(newTblInfo1.Meta().ID, Equals, oldTblID1) - newTblInfo2, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t4")) - c.Assert(err, IsNil) - c.Assert(newTblInfo2.Meta().ID, Equals, oldTblID2) - tk.MustQuery("select * from t3").Check(testkit.Rows("1 1", "2 2")) - isExist = is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t1")) - c.Assert(isExist, IsFalse) - tk.MustQuery("select * from t4").Check(testkit.Rows("1 1", "2 2")) - isExist = is.TableExists(model.NewCIStr("test1"), model.NewCIStr("t2")) - c.Assert(isExist, IsFalse) - tk.MustQuery("show tables").Check(testkit.Rows("t3", "t4")) - - // for multi tables same database - tk.MustExec("create table t5 (c1 int, c2 int)") - tk.MustExec("insert t5 values (1, 1), (2, 2)") - is = domain.GetDomain(ctx).InfoSchema() - oldTblInfo3, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t5")) - c.Assert(err, IsNil) - oldTblID3 := oldTblInfo3.Meta().ID - tk.MustExec("rename table test1.t3 to test1.t1, test1.t4 to test1.t2, test1.t5 to test1.t3") - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo1, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(newTblInfo1.Meta().ID, Equals, oldTblID1) - newTblInfo2, err = is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(newTblInfo2.Meta().ID, Equals, oldTblID2) - newTblInfo3, err := is.TableByName(model.NewCIStr("test1"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - c.Assert(newTblInfo3.Meta().ID, Equals, oldTblID3) - tk.MustQuery("show tables").Check(testkit.Rows("t1", "t2", "t3")) - - // for multi tables different databases - tk.MustExec("use test") - tk.MustExec("rename table test1.t1 to test.t2, test1.t2 to test.t3, test1.t3 to test.t4") - is = domain.GetDomain(ctx).InfoSchema() - newTblInfo1, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(newTblInfo1.Meta().ID, Equals, oldTblID1) - newTblInfo2, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - c.Assert(newTblInfo2.Meta().ID, Equals, oldTblID2) - newTblInfo3, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t4")) - c.Assert(err, IsNil) - c.Assert(newTblInfo3.Meta().ID, Equals, oldTblID3) - tk.MustQuery("show tables").Check(testkit.Rows("t2", "t3", "t4")) - - // for failure case - failSQL := "rename table test_not_exist.t to test_not_exist.t, test_not_exist.t to test_not_exist.t" - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - failSQL = "rename table test.test_not_exist to test.test_not_exist, test.test_not_exist to test.test_not_exist" - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - failSQL = "rename table test.t_not_exist to test_not_exist.t, test.t_not_exist to test_not_exist.t" - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - failSQL = "rename table test1.t2 to test_not_exist.t, test1.t2 to test_not_exist.t" - tk.MustGetErrCode(failSQL, errno.ErrFileNotFound) - - tk.MustExec("drop database test1") - tk.MustExec("drop database test") -} - -func (s *testDBSuite2) TestAddNotNullColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - // for different databases - tk.MustExec("create table tnn (c1 int primary key auto_increment, c2 int)") - tk.MustExec("insert tnn (c2) values (0)" + strings.Repeat(",(0)", 99)) - done := make(chan error, 1) - testddlutil.SessionExecInGoroutine(s.store, "alter table tnn add column c3 int not null default 3", done) - updateCnt := 0 -out: - for { - select { - case err := <-done: - c.Assert(err, IsNil) - break out - default: - // Close issue #14636 - // Because add column action is not amendable now, it causes an error when the schema is changed - // in the process of an insert statement. - _, err := tk.Exec("update tnn set c2 = c2 + 1 where c1 = 99") - if err == nil { - updateCnt++ - } - } - } - expected := fmt.Sprintf("%d %d", updateCnt, 3) - tk.MustQuery("select c2, c3 from tnn where c1 = 99").Check(testkit.Rows(expected)) - - tk.MustExec("drop table tnn") -} - -func (s *testDBSuite3) TestVirtualColumnDDL(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists test_gv_ddl") - tk.MustExec(`create global temporary table test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored) on commit delete rows;`) - defer tk.MustExec("drop table if exists test_gv_ddl") - is := tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) - table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_gv_ddl")) - c.Assert(err, IsNil) - testCases := []struct { - generatedExprString string - generatedStored bool - }{ - {"", false}, - {"`a` + 8", false}, - {"`b` + 2", true}, - } - for i, column := range table.Meta().Columns { - c.Assert(column.GeneratedExprString, Equals, testCases[i].generatedExprString) - c.Assert(column.GeneratedStored, Equals, testCases[i].generatedStored) - } - result := tk.MustQuery(`DESC test_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - tk.MustExec("begin;") - tk.MustExec("insert into test_gv_ddl values (1, default, default)") - tk.MustQuery("select * from test_gv_ddl").Check(testkit.Rows("1 9 11")) - _, err = tk.Exec("commit") - c.Assert(err, IsNil) - - // for local temporary table - tk.MustExec(`create temporary table test_local_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored);`) - defer tk.MustExec("drop table if exists test_local_gv_ddl") - is = tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) - table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_local_gv_ddl")) - c.Assert(err, IsNil) - for i, column := range table.Meta().Columns { - c.Assert(column.GeneratedExprString, Equals, testCases[i].generatedExprString) - c.Assert(column.GeneratedStored, Equals, testCases[i].generatedStored) - } - result = tk.MustQuery(`DESC test_local_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - tk.MustExec("begin;") - tk.MustExec("insert into test_local_gv_ddl values (1, default, default)") - tk.MustQuery("select * from test_local_gv_ddl").Check(testkit.Rows("1 9 11")) - _, err = tk.Exec("commit") - c.Assert(err, IsNil) - tk.MustQuery("select * from test_local_gv_ddl").Check(testkit.Rows("1 9 11")) -} - -func (s *testDBSuite3) TestGeneratedColumnDDL(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - // Check create table with virtual and stored generated columns. - tk.MustExec(`CREATE TABLE test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored)`) - - // Check desc table with virtual and stored generated columns. - result := tk.MustQuery(`DESC test_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - - // Check show create table with virtual and stored generated columns. - result = tk.MustQuery(`show create table test_gv_ddl`) - result.Check(testkit.Rows( - "test_gv_ddl CREATE TABLE `test_gv_ddl` (\n `a` int(11) DEFAULT NULL,\n `b` int(11) GENERATED ALWAYS AS (`a` + 8) VIRTUAL,\n `c` int(11) GENERATED ALWAYS AS (`b` + 2) STORED\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", - )) - - // Check generated expression with blanks. - tk.MustExec("create table table_with_gen_col_blanks (a int, b char(20) as (cast( \r\n\t a \r\n\tas char)), c int as (a+100))") - result = tk.MustQuery(`show create table table_with_gen_col_blanks`) - result.Check(testkit.Rows("table_with_gen_col_blanks CREATE TABLE `table_with_gen_col_blanks` (\n" + - " `a` int(11) DEFAULT NULL,\n" + - " `b` char(20) GENERATED ALWAYS AS (cast(`a` as char)) VIRTUAL,\n" + - " `c` int(11) GENERATED ALWAYS AS (`a` + 100) VIRTUAL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Check generated expression with charset latin1 ("latin1" != mysql.DefaultCharset). - tk.MustExec("create table table_with_gen_col_latin1 (a int, b char(20) as (cast( \r\n\t a \r\n\tas char charset latin1)), c int as (a+100))") - result = tk.MustQuery(`show create table table_with_gen_col_latin1`) - result.Check(testkit.Rows("table_with_gen_col_latin1 CREATE TABLE `table_with_gen_col_latin1` (\n" + - " `a` int(11) DEFAULT NULL,\n" + - " `b` char(20) GENERATED ALWAYS AS (cast(`a` as char charset latin1)) VIRTUAL,\n" + - " `c` int(11) GENERATED ALWAYS AS (`a` + 100) VIRTUAL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Check generated expression with string (issue 9457). - tk.MustExec("create table table_with_gen_col_string (first_name varchar(10), last_name varchar(10), full_name varchar(255) AS (CONCAT(first_name,' ',last_name)))") - result = tk.MustQuery(`show create table table_with_gen_col_string`) - result.Check(testkit.Rows("table_with_gen_col_string CREATE TABLE `table_with_gen_col_string` (\n" + - " `first_name` varchar(10) DEFAULT NULL,\n" + - " `last_name` varchar(10) DEFAULT NULL,\n" + - " `full_name` varchar(255) GENERATED ALWAYS AS (concat(`first_name`, _utf8mb4' ', `last_name`)) VIRTUAL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - tk.MustExec("alter table table_with_gen_col_string modify column full_name varchar(255) GENERATED ALWAYS AS (CONCAT(last_name,' ' ,first_name) ) VIRTUAL") - result = tk.MustQuery(`show create table table_with_gen_col_string`) - result.Check(testkit.Rows("table_with_gen_col_string CREATE TABLE `table_with_gen_col_string` (\n" + - " `first_name` varchar(10) DEFAULT NULL,\n" + - " `last_name` varchar(10) DEFAULT NULL,\n" + - " `full_name` varchar(255) GENERATED ALWAYS AS (concat(`last_name`, _utf8mb4' ', `first_name`)) VIRTUAL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Test incorrect parameter count. - tk.MustGetErrCode("create table test_gv_incorrect_pc(a double, b int as (lower(a, 2)))", errno.ErrWrongParamcountToNativeFct) - tk.MustGetErrCode("create table test_gv_incorrect_pc(a double, b int as (lower(a, 2)) stored)", errno.ErrWrongParamcountToNativeFct) - - genExprTests := []struct { - stmt string - err int - }{ - // Drop/rename columns dependent by other column. - {`alter table test_gv_ddl drop column a`, errno.ErrDependentByGeneratedColumn}, - {`alter table test_gv_ddl change column a anew int`, errno.ErrBadField}, - - // Modify/change stored status of generated columns. - {`alter table test_gv_ddl modify column b bigint`, errno.ErrUnsupportedOnGeneratedColumn}, - {`alter table test_gv_ddl change column c cnew bigint as (a+100)`, errno.ErrUnsupportedOnGeneratedColumn}, - - // Modify/change generated columns breaking prior. - {`alter table test_gv_ddl modify column b int as (c+100)`, errno.ErrGeneratedColumnNonPrior}, - {`alter table test_gv_ddl change column b bnew int as (c+100)`, errno.ErrGeneratedColumnNonPrior}, - - // Refer not exist columns in generation expression. - {`create table test_gv_ddl_bad (a int, b int as (c+8))`, errno.ErrBadField}, - - // Refer generated columns non prior. - {`create table test_gv_ddl_bad (a int, b int as (c+1), c int as (a+1))`, errno.ErrGeneratedColumnNonPrior}, - - // Virtual generated columns cannot be primary key. - {`create table test_gv_ddl_bad (a int, b int, c int as (a+b) primary key)`, errno.ErrUnsupportedOnGeneratedColumn}, - {`create table test_gv_ddl_bad (a int, b int, c int as (a+b), primary key(c))`, errno.ErrUnsupportedOnGeneratedColumn}, - {`create table test_gv_ddl_bad (a int, b int, c int as (a+b), primary key(a, c))`, errno.ErrUnsupportedOnGeneratedColumn}, - - // Add stored generated column through alter table. - {`alter table test_gv_ddl add column d int as (b+2) stored`, errno.ErrUnsupportedOnGeneratedColumn}, - {`alter table test_gv_ddl modify column b int as (a + 8) stored`, errno.ErrUnsupportedOnGeneratedColumn}, - - // Add generated column with incorrect parameter count. - {`alter table test_gv_ddl add column z int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, - {`alter table test_gv_ddl add column z int as (lower(a, 2)) stored`, errno.ErrWrongParamcountToNativeFct}, - - // Modify generated column with incorrect parameter count. - {`alter table test_gv_ddl modify column b int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, - {`alter table test_gv_ddl change column b b int as (lower(a, 2))`, errno.ErrWrongParamcountToNativeFct}, - } - for _, tt := range genExprTests { - tk.MustGetErrCode(tt.stmt, tt.err) - } - - // Check alter table modify/change generated column. - modStoredColErrMsg := "[ddl:3106]'modifying a stored column' is not supported for generated columns." - _, err := tk.Exec(`alter table test_gv_ddl modify column c bigint as (b+200) stored`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, modStoredColErrMsg) - - result = tk.MustQuery(`DESC test_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - - tk.MustExec(`alter table test_gv_ddl change column b b bigint as (a+100) virtual`) - result = tk.MustQuery(`DESC test_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b bigint(20) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - - tk.MustExec(`alter table test_gv_ddl change column c cnew bigint`) - result = tk.MustQuery(`DESC test_gv_ddl`) - result.Check(testkit.Rows(`a int(11) YES `, `b bigint(20) YES VIRTUAL GENERATED`, `cnew bigint(20) YES `)) - - // Test generated column `\\`. - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t(c0 TEXT AS ('\\\\'));") - tk.MustExec("insert into t values ()") - tk.MustQuery("select * from t").Check(testkit.Rows("\\")) - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t(c0 TEXT AS ('a\\\\b\\\\c\\\\'))") - tk.MustExec("insert into t values ()") - tk.MustQuery("select * from t").Check(testkit.Rows("a\\b\\c\\")) -} - -func (s *testDBSuite4) TestComment(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists ct, ct1") - - validComment := strings.Repeat("a", 1024) - invalidComment := strings.Repeat("b", 1025) - - tk.MustExec("create table ct (c int, d int, e int, key (c) comment '" + validComment + "')") - tk.MustExec("create index i on ct (d) comment '" + validComment + "'") - tk.MustExec("alter table ct add key (e) comment '" + validComment + "'") - - tk.MustGetErrCode("create table ct1 (c int, key (c) comment '"+invalidComment+"')", errno.ErrTooLongIndexComment) - tk.MustGetErrCode("create index i1 on ct (d) comment '"+invalidComment+"b"+"'", errno.ErrTooLongIndexComment) - tk.MustGetErrCode("alter table ct add key (e) comment '"+invalidComment+"'", errno.ErrTooLongIndexComment) - - tk.MustExec("set @@sql_mode=''") - tk.MustExec("create table ct1 (c int, d int, e int, key (c) comment '" + invalidComment + "')") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1688|Comment for index 'c' is too long (max = 1024)")) - tk.MustExec("create index i1 on ct1 (d) comment '" + invalidComment + "b" + "'") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1688|Comment for index 'i1' is too long (max = 1024)")) - tk.MustExec("alter table ct1 add key (e) comment '" + invalidComment + "'") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1688|Comment for index 'e' is too long (max = 1024)")) - - tk.MustExec("drop table if exists ct, ct1") -} - -func (s *testSerialDBSuite) TestRebaseAutoID(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - - tk.MustExec("drop database if exists tidb;") - tk.MustExec("create database tidb;") - tk.MustExec("use tidb;") - tk.MustExec("create table tidb.test (a int auto_increment primary key, b int);") - tk.MustExec("insert tidb.test values (null, 1);") - tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1")) - tk.MustExec("alter table tidb.test auto_increment = 6000;") - tk.MustExec("insert tidb.test values (null, 1);") - tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1")) - tk.MustExec("alter table tidb.test auto_increment = 5;") - tk.MustExec("insert tidb.test values (null, 1);") - tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1", "11000 1")) - - // Current range for table test is [11000, 15999]. - // Though it does not have a tuple "a = 15999", its global next auto increment id should be 16000. - // Anyway it is not compatible with MySQL. - tk.MustExec("alter table tidb.test auto_increment = 12000;") - tk.MustExec("insert tidb.test values (null, 1);") - tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1", "11000 1", "16000 1")) - - tk.MustExec("create table tidb.test2 (a int);") - tk.MustGetErrCode("alter table tidb.test2 add column b int auto_increment key, auto_increment=10;", errno.ErrUnsupportedDDLOperation) -} - -func (s *testDBSuite5) TestCheckColumnDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists text_default_text;") - tk.MustGetErrCode("create table text_default_text(c1 text not null default '');", errno.ErrBlobCantHaveDefault) - tk.MustGetErrCode("create table text_default_text(c1 text not null default 'scds');", errno.ErrBlobCantHaveDefault) - - tk.MustExec("drop table if exists text_default_json;") - tk.MustGetErrCode("create table text_default_json(c1 json not null default '');", errno.ErrBlobCantHaveDefault) - tk.MustGetErrCode("create table text_default_json(c1 json not null default 'dfew555');", errno.ErrBlobCantHaveDefault) - - tk.MustExec("drop table if exists text_default_blob;") - tk.MustGetErrCode("create table text_default_blob(c1 blob not null default '');", errno.ErrBlobCantHaveDefault) - tk.MustGetErrCode("create table text_default_blob(c1 blob not null default 'scds54');", errno.ErrBlobCantHaveDefault) - - tk.MustExec("set sql_mode='';") - tk.MustExec("create table text_default_text(c1 text not null default '');") - tk.MustQuery(`show create table text_default_text`).Check(testutil.RowsWithSep("|", - "text_default_text CREATE TABLE `text_default_text` (\n"+ - " `c1` text NOT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", - )) - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_text")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, "") - - tk.MustExec("create table text_default_blob(c1 blob not null default '');") - tk.MustQuery(`show create table text_default_blob`).Check(testutil.RowsWithSep("|", - "text_default_blob CREATE TABLE `text_default_blob` (\n"+ - " `c1` blob NOT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", - )) - is = domain.GetDomain(ctx).InfoSchema() - tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_blob")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, "") - - tk.MustExec("create table text_default_json(c1 json not null default '');") - tk.MustQuery(`show create table text_default_json`).Check(testutil.RowsWithSep("|", - "text_default_json CREATE TABLE `text_default_json` (\n"+ - " `c1` json NOT NULL DEFAULT 'null'\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", - )) - is = domain.GetDomain(ctx).InfoSchema() - tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_json")) - c.Assert(err, IsNil) - c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, `null`) -} - -func (s *testDBSuite1) TestCharacterSetInColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database varchar_test;") - defer tk.MustExec("drop database varchar_test;") - tk.MustExec("use varchar_test") - tk.MustExec("create table t (c1 int, s1 varchar(10), s2 text)") - tk.MustQuery("select count(*) from information_schema.columns where table_schema = 'varchar_test' and character_set_name != 'utf8mb4'").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from information_schema.columns where table_schema = 'varchar_test' and character_set_name = 'utf8mb4'").Check(testkit.Rows("2")) - - tk.MustExec("create table t1(id int) charset=UTF8;") - tk.MustExec("create table t2(id int) charset=BINARY;") - tk.MustExec("create table t3(id int) charset=LATIN1;") - tk.MustExec("create table t4(id int) charset=ASCII;") - tk.MustExec("create table t5(id int) charset=UTF8MB4;") - - tk.MustExec("create table t11(id int) charset=utf8;") - tk.MustExec("create table t12(id int) charset=binary;") - tk.MustExec("create table t13(id int) charset=latin1;") - tk.MustExec("create table t14(id int) charset=ascii;") - tk.MustExec("create table t15(id int) charset=utf8mb4;") -} - -func (s *testDBSuite2) TestAddNotNullColumnWhileInsertOnDupUpdate(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use " + s.schemaName) - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use " + s.schemaName) - closeCh := make(chan bool) - wg := new(sync.WaitGroup) - wg.Add(1) - tk1.MustExec("create table nn (a int primary key, b int)") - tk1.MustExec("insert nn values (1, 1)") - var tk2Err error - go func() { - defer wg.Done() - for { - select { - case <-closeCh: - return - default: - } - _, tk2Err = tk2.Exec("insert nn (a, b) values (1, 1) on duplicate key update a = 1, b = values(b) + 1") - if tk2Err != nil { - return - } - } - }() - tk1.MustExec("alter table nn add column c int not null default 3 after a") - close(closeCh) - wg.Wait() - c.Assert(tk2Err, IsNil) - tk1.MustQuery("select * from nn").Check(testkit.Rows("1 3 2")) -} - -func (s *testDBSuite3) TestColumnModifyingDefinition(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists test2;") - tk.MustExec("create table test2 (c1 int, c2 int, c3 int default 1, index (c1));") - tk.MustExec("alter table test2 change c2 a int not null;") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - t, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test2")) - c.Assert(err, IsNil) - var c2 *table.Column - for _, col := range t.Cols() { - if col.Name.L == "a" { - c2 = col - } - } - c.Assert(mysql.HasNotNullFlag(c2.Flag), IsTrue) - - tk.MustExec("drop table if exists test2;") - tk.MustExec("create table test2 (c1 int, c2 int, c3 int default 1, index (c1));") - tk.MustExec("insert into test2(c2) values (null);") - _, err = tk.Exec("alter table test2 change c2 a int not null") - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a' at row 1") - tk.MustGetErrCode("alter table test2 change c1 a1 bigint not null;", mysql.WarnDataTruncated) -} - -func (s *testDBSuite4) TestCheckTooBigFieldLength(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists tr_01;") - tk.MustExec("create table tr_01 (id int, name varchar(20000), purchased date ) default charset=utf8 collate=utf8_bin;") - - tk.MustExec("drop table if exists tr_02;") - tk.MustExec("create table tr_02 (id int, name varchar(16000), purchased date ) default charset=utf8mb4 collate=utf8mb4_bin;") - - tk.MustExec("drop table if exists tr_03;") - tk.MustExec("create table tr_03 (id int, name varchar(65534), purchased date ) default charset=latin1;") - - tk.MustExec("drop table if exists tr_04;") - tk.MustExec("create table tr_04 (a varchar(20000) ) default charset utf8;") - tk.MustGetErrCode("alter table tr_04 add column b varchar(20000) charset utf8mb4;", errno.ErrTooBigFieldlength) - tk.MustGetErrCode("alter table tr_04 convert to character set utf8mb4;", errno.ErrTooBigFieldlength) - tk.MustGetErrCode("create table tr (id int, name varchar(30000), purchased date ) default charset=utf8 collate=utf8_bin;", errno.ErrTooBigFieldlength) - tk.MustGetErrCode("create table tr (id int, name varchar(20000) charset utf8mb4, purchased date ) default charset=utf8 collate=utf8_bin;", errno.ErrTooBigFieldlength) - tk.MustGetErrCode("create table tr (id int, name varchar(65536), purchased date ) default charset=latin1;", errno.ErrTooBigFieldlength) - - tk.MustExec("drop table if exists tr_05;") - tk.MustExec("create table tr_05 (a varchar(16000) charset utf8);") - tk.MustExec("alter table tr_05 modify column a varchar(16000) charset utf8;") - tk.MustExec("alter table tr_05 modify column a varchar(16000) charset utf8mb4;") -} - -func (s *testDBSuite5) TestCheckConvertToCharacter(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - defer tk.MustExec("drop table t") - tk.MustExec("create table t(a varchar(10) charset binary);") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - t, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8 collate utf8_bin", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify column a varchar(10) charset utf8mb4 collate utf8mb4_bin", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t modify column a varchar(10) charset latin1 collate latin1_bin", errno.ErrUnsupportedDDLOperation) - c.Assert(t.Cols()[0].Charset, Equals, "binary") -} - -func (s *testDBSuite5) TestModifyColumnRollBack(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (c1 int, c2 int, c3 int default 1, index (c1));") - - var c2 *table.Column - var checkErr error - hook := &ddl.TestDDLCallback{Do: s.dom} - hook.OnJobUpdatedExported = func(job *model.Job) { - if checkErr != nil { - return - } - - t := s.testGetTable(c, "t1") - for _, col := range t.Cols() { - if col.Name.L == "c2" { - c2 = col - } - } - if mysql.HasPreventNullInsertFlag(c2.Flag) { - tk.MustGetErrCode("insert into t1(c2) values (null);", errno.ErrBadNull) - } - - hookCtx := mock.NewContext() - hookCtx.Store = s.store - err := hookCtx.NewTxn(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - return - } - - jobIDs := []int64{job.ID} - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - // It only tests cancel one DDL job. - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - - txn, err = hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - err = txn.Commit(context.Background()) - if err != nil { - checkErr = errors.Trace(err) - } - } - - originalHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - done := make(chan error, 1) - go backgroundExec(s.store, "alter table t1 change c2 c2 bigint not null;", done) - - err := <-done - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - s.mustExec(tk, c, "insert into t1(c2) values (null);") - - t := s.testGetTable(c, "t1") - for _, col := range t.Cols() { - if col.Name.L == "c2" { - c2 = col - } - } - c.Assert(mysql.HasNotNullFlag(c2.Flag), IsFalse) - s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - s.mustExec(tk, c, "drop table t1") -} - -func (s *testSerialDBSuite) TestModifyColumnReorgInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int, index idx(c2), index idx1(c1, c2));") - - sql := "alter table t1 change c2 c2 mediumint;" - // defaultBatchSize is equal to ddl.defaultBatchSize - base := defaultBatchSize * 8 - // add some rows - batchInsert(tk, "t1", 0, base) - // Make sure the count of regions more than backfill workers. - tk.MustQuery("split table t1 between (0) and (8192) regions 8;").Check(testkit.Rows("8 1")) - - tbl := s.testGetTable(c, "t1") - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - - // Check insert null before job first update. - hook := &ddl.TestDDLCallback{Do: s.dom} - var checkErr error - var currJob *model.Job - var elements []*meta.Element - ctx := mock.NewContext() - ctx.Store = s.store - times := 0 - hook.OnJobRunBeforeExported = func(job *model.Job) { - if tbl.Meta().ID != job.TableID || checkErr != nil || job.SchemaState != model.StateWriteReorganization { - return - } - if job.Type == model.ActionModifyColumn { - if times == 0 { - times++ - return - } - currJob = job - var ( - newCol *model.ColumnInfo - oldColName *model.CIStr - modifyColumnTp byte - updatedAutoRandomBits uint64 - changingCol *model.ColumnInfo - changingIdxs []*model.IndexInfo - ) - pos := &ast.ColumnPosition{} - checkErr = job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) - elements = ddl.BuildElements(changingCol, changingIdxs) - } - if job.Type == model.ActionAddIndex { - if times == 1 { - times++ - return - } - tbl := s.testGetTable(c, "t1") - indexInfo := tbl.Meta().FindIndexByName("idx2") - elements = []*meta.Element{{ID: indexInfo.ID, TypeKey: meta.IndexElementKey}} - } - } - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("cantDecodeRecordErr")`), IsNil) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err := tk.Exec(sql) - c.Assert(err.Error(), Equals, "[ddl:8202]Cannot decode index value, because mock can't decode record error") - c.Assert(checkErr, IsNil) - // Check whether the reorg information is cleaned up when executing "modify column" failed. - checkReorgHandle := func(gotElements, expectedElements []*meta.Element) { - for i, e := range gotElements { - c.Assert(e, DeepEquals, expectedElements[i]) - } - err := ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - m := meta.NewMeta(txn) - e, start, end, physicalID, err := m.GetDDLReorgHandle(currJob) - c.Assert(meta.ErrDDLReorgElementNotExist.Equal(err), IsTrue) - c.Assert(e, IsNil) - c.Assert(start, IsNil) - c.Assert(end, IsNil) - c.Assert(physicalID, Equals, int64(0)) - } - expectedEles := []*meta.Element{ - {ID: 4, TypeKey: meta.ColumnElementKey}, - {ID: 3, TypeKey: meta.IndexElementKey}, - {ID: 4, TypeKey: meta.IndexElementKey}} - checkReorgHandle(elements, expectedEles) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr"), IsNil) - tk.MustExec("admin check table t1") - - // Check whether the reorg information is cleaned up when executing "modify column" successfully. - // Test encountering a "notOwnerErr" error which caused the processing backfill job to exit halfway. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("modifyColumnNotOwnerErr")`), IsNil) - tk.MustExec(sql) - expectedEles = []*meta.Element{ - {ID: 5, TypeKey: meta.ColumnElementKey}, - {ID: 5, TypeKey: meta.IndexElementKey}, - {ID: 6, TypeKey: meta.IndexElementKey}} - checkReorgHandle(elements, expectedEles) - tk.MustExec("admin check table t1") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr"), IsNil) - - // Test encountering a "notOwnerErr" error which caused the processing backfill job to exit halfway. - // During the period, the old TiDB version(do not exist the element information) is upgraded to the new TiDB version. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("addIdxNotOwnerErr")`), IsNil) - tk.MustExec("alter table t1 add index idx2(c1)") - expectedEles = []*meta.Element{ - {ID: 7, TypeKey: meta.IndexElementKey}} - checkReorgHandle(elements, expectedEles) - tk.MustExec("admin check table t1") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr"), IsNil) -} - -func (s *testSerialDBSuite) TestModifyColumnNullToNotNullWithChangingVal2(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockInsertValueAfterCheckNull", `return("insert into test.tt values (NULL, NULL)")`), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/ddl/mockInsertValueAfterCheckNull") - c.Assert(err, IsNil) - }() - - tk.MustExec("drop table if exists tt;") - tk.MustExec(`create table tt (a bigint, b int, unique index idx(a));`) - tk.MustExec("insert into tt values (1,1),(2,2),(3,3);") - _, err := tk.Exec("alter table tt modify a int not null;") - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a' at row 1") - tk.MustExec("drop table tt") -} - -func (s *testDBSuite1) TestModifyColumnNullToNotNull(c *C) { - sql1 := "alter table t1 change c2 c2 int not null;" - sql2 := "alter table t1 change c2 c2 int not null;" - testModifyColumnNullToNotNull(c, s.testDBSuite, false, sql1, sql2) -} - -func (s *testSerialDBSuite) TestModifyColumnNullToNotNullWithChangingVal(c *C) { - sql1 := "alter table t1 change c2 c2 tinyint not null;" - sql2 := "alter table t1 change c2 c2 tinyint not null;" - testModifyColumnNullToNotNull(c, s.testDBSuite, true, sql1, sql2) - c2 := getModifyColumn(c, s.s.(sessionctx.Context), s.schemaName, "t1", "c2", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeTiny) -} - -func (s *testSerialDBSuite) TestModifyColumnBetweenStringTypes(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - // varchar to varchar - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt (a varchar(10));") - tk.MustExec("insert into tt values ('111'),('10000');") - tk.MustExec("alter table tt change a a varchar(5);") - mvc := getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(mvc.FieldType.Flen, Equals, 5) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustGetErrMsg("alter table tt change a a varchar(4);", "[types:1265]Data truncated for column 'a', value is '10000'") - tk.MustExec("alter table tt change a a varchar(100);") - tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) - - // char to char - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt (a char(10));") - tk.MustExec("insert into tt values ('111'),('10000');") - tk.MustExec("alter table tt change a a char(5);") - mc := getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(mc.FieldType.Flen, Equals, 5) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") - tk.MustExec("alter table tt change a a char(100);") - tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) - - // binary to binary - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt (a binary(10));") - tk.MustExec("insert into tt values ('111'),('10000');") - tk.MustGetErrMsg("alter table tt change a a binary(5);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") - mb := getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(mb.FieldType.Flen, Equals, 10) - tk.MustQuery("select * from tt").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00", "10000\x00\x00\x00\x00\x00")) - tk.MustGetErrMsg("alter table tt change a a binary(4);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") - tk.MustExec("alter table tt change a a binary(12);") - tk.MustQuery("select * from tt").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00\x00\x00", "10000\x00\x00\x00\x00\x00\x00\x00")) - tk.MustQuery("select length(a) from tt").Check(testkit.Rows("12", "12")) - - // varbinary to varbinary - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt (a varbinary(10));") - tk.MustExec("insert into tt values ('111'),('10000');") - tk.MustExec("alter table tt change a a varbinary(5);") - mvb := getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(mvb.FieldType.Flen, Equals, 5) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustGetErrMsg("alter table tt change a a varbinary(4);", "[types:1265]Data truncated for column 'a', value is '10000'") - tk.MustExec("alter table tt change a a varbinary(12);") - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) - - // varchar to char - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt (a varchar(10));") - tk.MustExec("insert into tt values ('111'),('10000');") - - tk.MustExec("alter table tt change a a char(10);") - c2 := getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeString) - c.Assert(c2.FieldType.Flen, Equals, 10) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") - - // char to text - tk.MustExec("alter table tt change a a text;") - c2 = getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeBlob) - - // text to set - tk.MustGetErrMsg("alter table tt change a a set('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") - tk.MustExec("alter table tt change a a set('111', '10000');") - c2 = getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeSet) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - - // set to set - tk.MustExec("alter table tt change a a set('10000', '111');") - c2 = getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeSet) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - - // set to enum - tk.MustGetErrMsg("alter table tt change a a enum('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") - tk.MustExec("alter table tt change a a enum('111', '10000');") - c2 = getModifyColumn(c, s.s.(sessionctx.Context), "test", "tt", "a", false) - c.Assert(c2.FieldType.Tp, Equals, mysql.TypeEnum) - tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) - tk.MustExec("alter table tt change a a enum('10000', '111');") - tk.MustQuery("select * from tt where a = 1").Check(testkit.Rows("10000")) - tk.MustQuery("select * from tt where a = 2").Check(testkit.Rows("111")) - - // no-strict mode - tk.MustExec(`set @@sql_mode="";`) - tk.MustExec("alter table tt change a a enum('111', '2222');") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1265|Data truncated for column 'a', value is '10000'")) - - tk.MustExec("drop table tt;") -} - -func getModifyColumn(c *C, ctx sessionctx.Context, db, tbl, colName string, allColumn bool) *table.Column { - t := testGetTableByName(c, ctx, db, tbl) - colName = strings.ToLower(colName) - var cols []*table.Column - if allColumn { - cols = t.(*tables.TableCommon).Columns - } else { - cols = t.Cols() - } - for _, col := range cols { - if col.Name.L == colName { - return col - } - } - return nil -} - -func testModifyColumnNullToNotNull(c *C, s *testDBSuite, enableChangeColumnType bool, sql1, sql2 string) { - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test_db") - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (c1 int, c2 int);") - - tbl := s.testGetTable(c, "t1") - getModifyColumn(c, s.s.(sessionctx.Context), s.schemaName, "t1", "c2", false) - - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - - // Check insert null before job first update. - times := 0 - hook := &ddl.TestDDLCallback{Do: s.dom} - tk.MustExec("delete from t1") - var checkErr error - hook.OnJobRunBeforeExported = func(job *model.Job) { - if tbl.Meta().ID != job.TableID { - return - } - if times == 0 { - _, checkErr = tk2.Exec("insert into t1 values ();") - } - times++ - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - _, err := tk.Exec(sql1) - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - if enableChangeColumnType { - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'c2' at row 1") - // Check whether the reorg information is cleaned up. - } else { - c.Assert(err.Error(), Equals, "[ddl:1138]Invalid use of NULL value") - } - tk.MustQuery("select * from t1").Check(testkit.Rows(" ")) - - // Check insert error when column has PreventNullInsertFlag. - tk.MustExec("delete from t1") - hook.OnJobRunBeforeExported = func(job *model.Job) { - if tbl.Meta().ID != job.TableID { - return - } - if job.State != model.JobStateRunning { - return - } - // now c2 has PreventNullInsertFlag, an error is expected. - _, checkErr = tk2.Exec("insert into t1 values ();") - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - tk.MustExec(sql2) - c.Assert(checkErr.Error(), Equals, "[table:1048]Column 'c2' cannot be null") - - c2 := getModifyColumn(c, s.s.(sessionctx.Context), s.schemaName, "t1", "c2", false) - c.Assert(mysql.HasNotNullFlag(c2.Flag), IsTrue) - c.Assert(mysql.HasPreventNullInsertFlag(c2.Flag), IsFalse) - _, err = tk.Exec("insert into t1 values ();") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[table:1364]Field 'c2' doesn't have a default value") -} - -func (s *testDBSuite2) TestTransactionOnAddDropColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (a int, b int);") - s.mustExec(tk, c, "create table t2 (a int, b int);") - s.mustExec(tk, c, "insert into t2 values (2,0)") - - transactions := [][]string{ - { - "begin", - "insert into t1 set a=1", - "update t1 set b=1 where a=1", - "commit", - }, - { - "begin", - "insert into t1 select a,b from t2", - "update t1 set b=2 where a=2", - "commit", - }, - } - - originHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originHook) - hook := &ddl.TestDDLCallback{Do: s.dom} - var checkErr error - hook.OnJobRunBeforeExported = func(job *model.Job) { - if checkErr != nil { - return - } - switch job.SchemaState { - case model.StateWriteOnly, model.StateWriteReorganization, model.StateDeleteOnly, model.StateDeleteReorganization: - default: - return - } - // do transaction. - for _, transaction := range transactions { - for _, sql := range transaction { - if _, checkErr = tk.Exec(sql); checkErr != nil { - checkErr = errors.Errorf("err: %s, sql: %s, job schema state: %s", checkErr.Error(), sql, job.SchemaState) + case model.StateWriteReorganization: + if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 { + _, checkErr = tk1.Exec("insert into t1 values (4, 4, 4)") + if checkErr != nil { return } - } - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - done := make(chan error, 1) - // test transaction on add column. - go backgroundExec(s.store, "alter table t1 add column c int not null after a", done) - err := <-done - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) - tk.MustQuery("select a,b from t1 order by a").Check(testkit.Rows("1 1", "1 1", "1 1", "2 2", "2 2", "2 2")) - s.mustExec(tk, c, "delete from t1") - - // test transaction on drop column. - go backgroundExec(s.store, "alter table t1 drop column c", done) - err = <-done - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) - tk.MustQuery("select a,b from t1 order by a").Check(testkit.Rows("1 1", "1 1", "1 1", "2 2", "2 2", "2 2")) -} - -func (s *testDBSuite3) TestIssue22307(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t") - s.mustExec(tk, c, "create table t (a int, b int)") - s.mustExec(tk, c, "insert into t values(1, 1);") - - originHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originHook) - hook := &ddl.TestDDLCallback{Do: s.dom} - var checkErr1, checkErr2 error - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.SchemaState != model.StateWriteOnly { - return - } - _, checkErr1 = tk.Exec("update t set a = 3 where b = 1;") - _, checkErr2 = tk.Exec("update t set a = 3 order by b;") - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - done := make(chan error, 1) - // test transaction on add column. - go backgroundExec(s.store, "alter table t drop column b;", done) - err := <-done - c.Assert(err, IsNil) - c.Assert(checkErr1.Error(), Equals, "[planner:1054]Unknown column 'b' in 'where clause'") - c.Assert(checkErr2.Error(), Equals, "[planner:1054]Unknown column 'b' in 'order clause'") -} - -func (s *testDBSuite3) TestTransactionWithWriteOnlyColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (a int key);") - - transactions := [][]string{ - { - "begin", - "insert into t1 set a=1", - "update t1 set a=2 where a=1", - "commit", - }, - } - - originHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originHook) - hook := &ddl.TestDDLCallback{Do: s.dom} - var checkErr error - hook.OnJobRunBeforeExported = func(job *model.Job) { - if checkErr != nil { - return - } - switch job.SchemaState { - case model.StateWriteOnly: - default: - return - } - // do transaction. - for _, transaction := range transactions { - for _, sql := range transaction { - if _, checkErr = tk.Exec(sql); checkErr != nil { - checkErr = errors.Errorf("err: %s, sql: %s, job schema state: %s", checkErr.Error(), sql, job.SchemaState) + _, checkErr = tk1.Exec("update t1 set c1 = 5 where c2 = 80") + if checkErr != nil { return } - } - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - done := make(chan error, 1) - // test transaction on add column. - go backgroundExec(s.store, "alter table t1 add column c int not null", done) - err := <-done - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) - tk.MustQuery("select a from t1").Check(testkit.Rows("2")) - s.mustExec(tk, c, "delete from t1") - - // test transaction on drop column. - go backgroundExec(s.store, "alter table t1 drop column c", done) - err = <-done - c.Assert(err, IsNil) - c.Assert(checkErr, IsNil) - tk.MustQuery("select a from t1").Check(testkit.Rows("2")) -} - -func (s *testDBSuite4) TestAddColumn2(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.mustExec(tk, c, "use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (a int key, b int);") - defer s.mustExec(tk, c, "drop table if exists t1, t2") - - originHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originHook) - hook := &ddl.TestDDLCallback{} - var writeOnlyTable table.Table - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.SchemaState == model.StateWriteOnly { - writeOnlyTable, _ = s.dom.InfoSchema().TableByID(job.TableID) - } - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - done := make(chan error, 1) - // test transaction on add column. - go backgroundExec(s.store, "alter table t1 add column c int not null", done) - err := <-done - c.Assert(err, IsNil) - - s.mustExec(tk, c, "insert into t1 values (1,1,1)") - tk.MustQuery("select a,b,c from t1").Check(testkit.Rows("1 1 1")) - - // mock for outdated tidb update record. - c.Assert(writeOnlyTable, NotNil) - ctx := context.Background() - err = tk.Se.NewTxn(ctx) - c.Assert(err, IsNil) - oldRow, err := tables.RowWithCols(writeOnlyTable, tk.Se, kv.IntHandle(1), writeOnlyTable.WritableCols()) - c.Assert(err, IsNil) - c.Assert(len(oldRow), Equals, 3) - err = writeOnlyTable.RemoveRecord(tk.Se, kv.IntHandle(1), oldRow) - c.Assert(err, IsNil) - _, err = writeOnlyTable.AddRecord(tk.Se, types.MakeDatums(oldRow[0].GetInt64(), 2, oldRow[2].GetInt64()), table.IsUpdate) - c.Assert(err, IsNil) - tk.Se.StmtCommit() - err = tk.Se.CommitTxn(ctx) - c.Assert(err, IsNil) - - tk.MustQuery("select a,b,c from t1").Check(testkit.Rows("1 2 1")) - - // Test for _tidb_rowid - var re *testkit.Result - s.mustExec(tk, c, "create table t2 (a int);") - hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.SchemaState != model.StateWriteOnly { - return - } - // allow write _tidb_rowid first - s.mustExec(tk, c, "set @@tidb_opt_write_row_id=1") - s.mustExec(tk, c, "begin") - s.mustExec(tk, c, "insert into t2 (a,_tidb_rowid) values (1,2);") - re = tk.MustQuery(" select a,_tidb_rowid from t2;") - s.mustExec(tk, c, "commit") - - } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - - go backgroundExec(s.store, "alter table t2 add column b int not null default 3", done) - err = <-done - c.Assert(err, IsNil) - re.Check(testkit.Rows("1 2")) - tk.MustQuery("select a,b,_tidb_rowid from t2").Check(testkit.Rows("1 3 2")) -} - -func (s *testDBSuite4) TestIfNotExists(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (a int key);") - - // ADD COLUMN - sql := "alter table t1 add column b int" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrDupFieldName) - s.mustExec(tk, c, "alter table t1 add column if not exists b int") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1060|Duplicate column name 'b'")) - - // ADD INDEX - sql = "alter table t1 add index idx_b (b)" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrDupKeyName) - s.mustExec(tk, c, "alter table t1 add index if not exists idx_b (b)") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1061|index already exist idx_b")) - - // CREATE INDEX - sql = "create index idx_b on t1 (b)" - tk.MustGetErrCode(sql, errno.ErrDupKeyName) - s.mustExec(tk, c, "create index if not exists idx_b on t1 (b)") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1061|index already exist idx_b")) - - // ADD PARTITION - s.mustExec(tk, c, "drop table if exists t2") - s.mustExec(tk, c, "create table t2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20))") - sql = "alter table t2 add partition (partition p2 values less than (30))" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrSameNamePartition) - s.mustExec(tk, c, "alter table t2 add partition if not exists (partition p2 values less than (30))") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1517|Duplicate partition name p2")) -} - -func (s *testDBSuite4) TestIfExists(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - s.mustExec(tk, c, "drop table if exists t1") - s.mustExec(tk, c, "create table t1 (a int key, b int);") - - // DROP COLUMN - sql := "alter table t1 drop column b" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrCantDropFieldOrKey) - s.mustExec(tk, c, "alter table t1 drop column if exists b") // only `a` exists now - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1091|Can't DROP 'b'; check that column/key exists")) - - // CHANGE COLUMN - sql = "alter table t1 change column b c int" - tk.MustGetErrCode(sql, errno.ErrBadField) - s.mustExec(tk, c, "alter table t1 change column if exists b c int") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1054|Unknown column 'b' in 't1'")) - s.mustExec(tk, c, "alter table t1 change column if exists a c int") // only `c` exists now - - // MODIFY COLUMN - sql = "alter table t1 modify column a bigint" - tk.MustGetErrCode(sql, errno.ErrBadField) - s.mustExec(tk, c, "alter table t1 modify column if exists a bigint") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1054|Unknown column 'a' in 't1'")) - s.mustExec(tk, c, "alter table t1 modify column if exists c bigint") // only `c` exists now - - // DROP INDEX - s.mustExec(tk, c, "alter table t1 add index idx_c (c)") - sql = "alter table t1 drop index idx_c" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrCantDropFieldOrKey) - s.mustExec(tk, c, "alter table t1 drop index if exists idx_c") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1091|index idx_c doesn't exist")) - - // DROP PARTITION - s.mustExec(tk, c, "drop table if exists t2") - s.mustExec(tk, c, "create table t2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20))") - sql = "alter table t2 drop partition p1" - s.mustExec(tk, c, sql) - tk.MustGetErrCode(sql, errno.ErrDropPartitionNonExistent) - s.mustExec(tk, c, "alter table t2 drop partition if exists p1") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1507|Error in list of partitions to p1")) -} - -func testAddIndexForGeneratedColumn(tk *testkit.TestKit, s *testDBSuite5, c *C) { - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(y year NOT NULL DEFAULT '2155')") - defer s.mustExec(tk, c, "drop table t;") - for i := 0; i < 50; i++ { - s.mustExec(tk, c, "insert into t values (?)", i) - } - tk.MustExec("insert into t values()") - tk.MustExec("ALTER TABLE t ADD COLUMN y1 year as (y + 2)") - _, err := tk.Exec("ALTER TABLE t ADD INDEX idx_y(y1)") - c.Assert(err, IsNil) - - t := s.testGetTable(c, "t") - for _, idx := range t.Indices() { - c.Assert(strings.EqualFold(idx.Meta().Name.L, "idx_c2"), IsFalse) - } - // NOTE: this test case contains a bug, it should be uncommented after the bug is fixed. - // TODO: Fix bug https://github.com/pingcap/tidb/issues/12181 - // s.mustExec(c, "delete from t where y = 2155") - // s.mustExec(c, "alter table t add index idx_y(y1)") - // s.mustExec(c, "alter table t drop index idx_y") - - // Fix issue 9311. - tk.MustExec("drop table if exists gcai_table") - tk.MustExec("create table gcai_table (id int primary key);") - tk.MustExec("insert into gcai_table values(1);") - tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d date DEFAULT '9999-12-31';") - tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d1 date as (DATE_SUB(d, INTERVAL 31 DAY));") - tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx(d1);") - tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30")) - tk.MustQuery("select d1 from gcai_table use index(idx)").Check(testkit.Rows("9999-11-30")) - tk.MustExec("admin check table gcai_table") - // The column is PKIsHandle in generated column expression. - tk.MustExec("ALTER TABLE gcai_table ADD COLUMN id1 int as (id+5);") - tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx1(id1);") - tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30 6")) - tk.MustQuery("select id1 from gcai_table use index(idx1)").Check(testkit.Rows("6")) - tk.MustExec("admin check table gcai_table") -} - -func (s *testDBSuite5) TestAddIndexForGeneratedColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - testAddIndexForGeneratedColumn(tk, s, c) -} - -func (s *testDBSuite5) TestModifyGeneratedColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test;") - tk.MustExec("use test") - modIdxColErrMsg := "[ddl:3106]'modifying an indexed column' is not supported for generated columns." - modStoredColErrMsg := "[ddl:3106]'modifying a stored column' is not supported for generated columns." - - // Modify column with single-col-index. - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1 (a int, b int as (a+1), index idx(b));") - tk.MustExec("insert into t1 set a=1;") - _, err := tk.Exec("alter table t1 modify column b int as (a+2);") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, modIdxColErrMsg) - tk.MustExec("drop index idx on t1;") - tk.MustExec("alter table t1 modify b int as (a+2);") - tk.MustQuery("select * from t1").Check(testkit.Rows("1 3")) - - // Modify column with multi-col-index. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int as (a+1), index idx(a, b));") - tk.MustExec("insert into t1 set a=1;") - _, err = tk.Exec("alter table t1 modify column b int as (a+2);") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, modIdxColErrMsg) - tk.MustExec("drop index idx on t1;") - tk.MustExec("alter table t1 modify b int as (a+2);") - tk.MustQuery("select * from t1").Check(testkit.Rows("1 3")) - - // Modify column with stored status to a different expression. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int as (a+1) stored);") - tk.MustExec("insert into t1 set a=1;") - _, err = tk.Exec("alter table t1 modify column b int as (a+2) stored;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, modStoredColErrMsg) - - // Modify column with stored status to the same expression. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int as (a+1) stored);") - tk.MustExec("insert into t1 set a=1;") - tk.MustExec("alter table t1 modify column b bigint as (a+1) stored;") - tk.MustExec("alter table t1 modify column b bigint as (a + 1) stored;") - tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) - - // Modify column with index to the same expression. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int as (a+1), index idx(b));") - tk.MustExec("insert into t1 set a=1;") - tk.MustExec("alter table t1 modify column b bigint as (a+1);") - tk.MustExec("alter table t1 modify column b bigint as (a + 1);") - tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) - - // Modify column from non-generated to stored generated. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int);") - _, err = tk.Exec("alter table t1 modify column b bigint as (a+1) stored;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, modStoredColErrMsg) - - // Modify column from stored generated to non-generated. - tk.MustExec("drop table t1;") - tk.MustExec("create table t1 (a int, b int as (a+1) stored);") - tk.MustExec("insert into t1 set a=1;") - tk.MustExec("alter table t1 modify column b int;") - tk.MustQuery("select * from t1").Check(testkit.Rows("1 2")) -} - -func (s *testDBSuite5) TestDefaultSQLFunction(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test;") - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1, t2, t3, t4;") - - // For issue #13189 - // Use `DEFAULT()` in `INSERT` / `INSERT ON DUPLICATE KEY UPDATE` statement - tk.MustExec("create table t1(a int primary key, b int default 20, c int default 30, d int default 40);") - tk.MustExec("insert into t1 set a = 1, b = default(c);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40")) - tk.MustExec("insert into t1 set a = 2, b = default(c), c = default(d), d = default(b);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40", "2 30 40 20")) - tk.MustExec("insert into t1 values (2, 3, 4, 5) on duplicate key update b = default(d), c = default(b);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40", "2 40 20 20")) - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 set a = default(b) + default(c) - default(d)") - tk.MustQuery("select * from t1;").Check(testkit.Rows("10 20 30 40")) - // Use `DEFAULT()` in `UPDATE` statement - tk.MustExec("delete from t1;") - tk.MustExec("insert into t1 value (1, 2, 3, 4);") - tk.MustExec("update t1 set a = 1, c = default(b);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 2 20 4")) - tk.MustExec("insert into t1 value (2, 2, 3, 4);") - tk.MustExec("update t1 set c = default(b), b = default(c) where a = 2;") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 2 20 4", "2 30 20 4")) - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 set a = 10") - tk.MustExec("update t1 set a = 10, b = default(c) + default(d)") - tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40")) - // Use `DEFAULT()` in `REPLACE` statement - tk.MustExec("delete from t1;") - tk.MustExec("insert into t1 value (1, 2, 3, 4);") - tk.MustExec("replace into t1 set a = 1, c = default(b);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 20 40")) - tk.MustExec("insert into t1 value (2, 2, 3, 4);") - tk.MustExec("replace into t1 set a = 2, d = default(b), c = default(d);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 20 40", "2 20 40 20")) - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 set a = 10, c = 3") - tk.MustExec("replace into t1 set a = 10, b = default(c) + default(d)") - tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40")) - tk.MustExec("replace into t1 set a = 20, d = default(c) + default(b)") - tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40", "20 20 30 50")) - - // Use `DEFAULT()` in expression of generate columns, issue #12471 - tk.MustExec("create table t2(a int default 9, b int as (1 + default(a)));") - tk.MustExec("insert into t2 values(1, default);") - tk.MustQuery("select * from t2;").Check(testkit.Rows("1 10")) - - // Use `DEFAULT()` with subquery, issue #13390 - tk.MustExec("create table t3(f1 int default 11);") - tk.MustExec("insert into t3 value ();") - tk.MustQuery("select default(f1) from (select * from t3) t1;").Check(testkit.Rows("11")) - tk.MustQuery("select default(f1) from (select * from (select * from t3) t1 ) t1;").Check(testkit.Rows("11")) - - tk.MustExec("create table t4(a int default 4);") - tk.MustExec("insert into t4 value (2);") - tk.MustQuery("select default(c) from (select b as c from (select a as b from t4) t3) t2;").Check(testkit.Rows("4")) - tk.MustGetErrCode("select default(a) from (select a from (select 1 as a) t4) t4;", errno.ErrNoDefaultForField) - - tk.MustExec("drop table t1, t2, t3, t4;") -} - -func (s *testDBSuite4) TestIssue9100(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("create table employ (a int, b int) partition by range (b) (partition p0 values less than (1));") - _, err := tk.Exec("alter table employ add unique index p_a (a);") - c.Assert(err.Error(), Equals, "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function") - _, err = tk.Exec("alter table employ add primary key p_a (a);") - c.Assert(err.Error(), Equals, "[ddl:1503]A PRIMARY must include all columns in the table's partitioning function") - - tk.MustExec("create table issue9100t1 (col1 int not null, col2 date not null, col3 int not null, unique key (col1, col2)) partition by range( col1 ) (partition p1 values less than (11))") - tk.MustExec("alter table issue9100t1 add unique index p_col1 (col1)") - tk.MustExec("alter table issue9100t1 add primary key p_col1 (col1)") - - tk.MustExec("create table issue9100t2 (col1 int not null, col2 date not null, col3 int not null, unique key (col1, col3)) partition by range( col1 + col3 ) (partition p1 values less than (11))") - _, err = tk.Exec("alter table issue9100t2 add unique index p_col1 (col1)") - c.Assert(err.Error(), Equals, "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function") - _, err = tk.Exec("alter table issue9100t2 add primary key p_col1 (col1)") - c.Assert(err.Error(), Equals, "[ddl:1503]A PRIMARY must include all columns in the table's partitioning function") -} - -func (s *testSerialDBSuite) TestProcessColumnFlags(c *C) { - // check `processColumnFlags()` - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("create table t(a year(4) comment 'xxx', b year, c bit)") - defer s.mustExec(tk, c, "drop table t;") - - check := func(n string, f func(uint) bool) { - t := testGetTableByName(c, tk.Se, "test_db", "t") - for _, col := range t.Cols() { - if strings.EqualFold(col.Name.L, n) { - c.Assert(f(col.Flag), IsTrue) - break - } - } - } - - yearcheck := func(f uint) bool { - return mysql.HasUnsignedFlag(f) && mysql.HasZerofillFlag(f) && !mysql.HasBinaryFlag(f) - } - - tk.MustExec("alter table t modify a year(4)") - check("a", yearcheck) - - tk.MustExec("alter table t modify a year(4) unsigned") - check("a", yearcheck) - - tk.MustExec("alter table t modify a year(4) zerofill") - - tk.MustExec("alter table t modify b year") - check("b", yearcheck) - - tk.MustExec("alter table t modify c bit") - check("c", func(f uint) bool { - return mysql.HasUnsignedFlag(f) && !mysql.HasBinaryFlag(f) - }) -} - -func (s *testSerialDBSuite) TestModifyColumnCharset(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("create table t_mcc(a varchar(8) charset utf8, b varchar(8) charset utf8)") - defer s.mustExec(tk, c, "drop table t_mcc;") - - result := tk.MustQuery(`show create table t_mcc`) - result.Check(testkit.Rows( - "t_mcc CREATE TABLE `t_mcc` (\n" + - " `a` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n" + - " `b` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - tk.MustExec("alter table t_mcc modify column a varchar(8);") - t := s.testGetTable(c, "t_mcc") - t.Meta().Version = model.TableInfoVersion0 - // When the table version is TableInfoVersion0, the following statement don't change "b" charset. - // So the behavior is not compatible with MySQL. - tk.MustExec("alter table t_mcc modify column b varchar(8);") - result = tk.MustQuery(`show create table t_mcc`) - result.Check(testkit.Rows( - "t_mcc CREATE TABLE `t_mcc` (\n" + - " `a` varchar(8) DEFAULT NULL,\n" + - " `b` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - -} - -func (s *testDBSuite1) TestModifyColumnTime_TimeToYear(c *C) { - outOfRangeCode := uint16(1264) - tests := []testModifyColumnTimeCase{ - // time to year, it's reasonable to return current year and discard the time (even if MySQL may get data out of range error). - {"time", `"30 20:00:12"`, "year", "", outOfRangeCode}, - {"time", `"30 20:00"`, "year", "", outOfRangeCode}, - {"time", `"30 20"`, "year", "", outOfRangeCode}, - {"time", `"20:00:12"`, "year", "", outOfRangeCode}, - {"time", `"20:00"`, "year", "", outOfRangeCode}, - {"time", `"12"`, "year", "2012", 0}, - {"time", `"200012"`, "year", "", outOfRangeCode}, - {"time", `200012`, "year", "", outOfRangeCode}, - {"time", `0012`, "year", "2012", 0}, - {"time", `12`, "year", "2012", 0}, - {"time", `"30 20:00:12.498"`, "year", "", outOfRangeCode}, - {"time", `"20:00:12.498"`, "year", "", outOfRangeCode}, - {"time", `"200012.498"`, "year", "", outOfRangeCode}, - {"time", `200012.498`, "year", "", outOfRangeCode}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimeToDate(c *C) { - now := time.Now().UTC() - now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) - timeToDate1 := now.Format("2006-01-02") - timeToDate2 := now.AddDate(0, 0, 30).Format("2006-01-02") - tests := []testModifyColumnTimeCase{ - // time to date - {"time", `"30 20:00:12"`, "date", timeToDate2, 0}, - {"time", `"30 20:00"`, "date", timeToDate2, 0}, - {"time", `"30 20"`, "date", timeToDate2, 0}, - {"time", `"20:00:12"`, "date", timeToDate1, 0}, - {"time", `"20:00"`, "date", timeToDate1, 0}, - {"time", `"12"`, "date", timeToDate1, 0}, - {"time", `"200012"`, "date", timeToDate1, 0}, - {"time", `200012`, "date", timeToDate1, 0}, - {"time", `0012`, "date", timeToDate1, 0}, - {"time", `12`, "date", timeToDate1, 0}, - {"time", `"30 20:00:12.498"`, "date", timeToDate2, 0}, - {"time", `"20:00:12.498"`, "date", timeToDate1, 0}, - {"time", `"200012.498"`, "date", timeToDate1, 0}, - {"time", `200012.498`, "date", timeToDate1, 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimeToDatetime(c *C) { - now := time.Now().UTC() - now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) - timeToDatetime1 := now.Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToDatetime2 := now.Add(20 * time.Hour).Format("2006-01-02 15:04:05") - timeToDatetime3 := now.Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToDatetime4 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToDatetime5 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Format("2006-01-02 15:04:05") - tests := []testModifyColumnTimeCase{ - // time to datetime - {"time", `"30 20:00:12"`, "datetime", timeToDatetime4, 0}, - {"time", `"30 20:00"`, "datetime", timeToDatetime5, 0}, - {"time", `"30 20"`, "datetime", timeToDatetime5, 0}, - {"time", `"20:00:12"`, "datetime", timeToDatetime1, 0}, - {"time", `"20:00"`, "datetime", timeToDatetime2, 0}, - {"time", `"12"`, "datetime", timeToDatetime3, 0}, - {"time", `"200012"`, "datetime", timeToDatetime1, 0}, - {"time", `200012`, "datetime", timeToDatetime1, 0}, - {"time", `0012`, "datetime", timeToDatetime3, 0}, - {"time", `12`, "datetime", timeToDatetime3, 0}, - {"time", `"30 20:00:12.498"`, "datetime", timeToDatetime4, 0}, - {"time", `"20:00:12.498"`, "datetime", timeToDatetime1, 0}, - {"time", `"200012.498"`, "datetime", timeToDatetime1, 0}, - {"time", `200012.498`, "datetime", timeToDatetime1, 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimeToTimestamp(c *C) { - now := time.Now().UTC() - now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) - timeToTimestamp1 := now.Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToTimestamp2 := now.Add(20 * time.Hour).Format("2006-01-02 15:04:05") - timeToTimestamp3 := now.Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToTimestamp4 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") - timeToTimestamp5 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Format("2006-01-02 15:04:05") - tests := []testModifyColumnTimeCase{ - // time to timestamp - {"time", `"30 20:00:12"`, "timestamp", timeToTimestamp4, 0}, - {"time", `"30 20:00"`, "timestamp", timeToTimestamp5, 0}, - {"time", `"30 20"`, "timestamp", timeToTimestamp5, 0}, - {"time", `"20:00:12"`, "timestamp", timeToTimestamp1, 0}, - {"time", `"20:00"`, "timestamp", timeToTimestamp2, 0}, - {"time", `"12"`, "timestamp", timeToTimestamp3, 0}, - {"time", `"200012"`, "timestamp", timeToTimestamp1, 0}, - {"time", `200012`, "timestamp", timeToTimestamp1, 0}, - {"time", `0012`, "timestamp", timeToTimestamp3, 0}, - {"time", `12`, "timestamp", timeToTimestamp3, 0}, - {"time", `"30 20:00:12.498"`, "timestamp", timeToTimestamp4, 0}, - {"time", `"20:00:12.498"`, "timestamp", timeToTimestamp1, 0}, - {"time", `"200012.498"`, "timestamp", timeToTimestamp1, 0}, - {"time", `200012.498`, "timestamp", timeToTimestamp1, 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite7) TestModifyColumnTime_DateToTime(c *C) { - tests := []testModifyColumnTimeCase{ - // date to time - {"date", `"2019-01-02"`, "time", "00:00:00", 0}, - {"date", `"19-01-02"`, "time", "00:00:00", 0}, - {"date", `"20190102"`, "time", "00:00:00", 0}, - {"date", `"190102"`, "time", "00:00:00", 0}, - {"date", `20190102`, "time", "00:00:00", 0}, - {"date", `190102`, "time", "00:00:00", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_DateToYear(c *C) { - tests := []testModifyColumnTimeCase{ - // date to year - {"date", `"2019-01-02"`, "year", "2019", 0}, - {"date", `"19-01-02"`, "year", "2019", 0}, - {"date", `"20190102"`, "year", "2019", 0}, - {"date", `"190102"`, "year", "2019", 0}, - {"date", `20190102`, "year", "2019", 0}, - {"date", `190102`, "year", "2019", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_DateToDatetime(c *C) { - tests := []testModifyColumnTimeCase{ - // date to datetime - {"date", `"2019-01-02"`, "datetime", "2019-01-02 00:00:00", 0}, - {"date", `"19-01-02"`, "datetime", "2019-01-02 00:00:00", 0}, - {"date", `"20190102"`, "datetime", "2019-01-02 00:00:00", 0}, - {"date", `"190102"`, "datetime", "2019-01-02 00:00:00", 0}, - {"date", `20190102`, "datetime", "2019-01-02 00:00:00", 0}, - {"date", `190102`, "datetime", "2019-01-02 00:00:00", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_DateToTimestamp(c *C) { - tests := []testModifyColumnTimeCase{ - // date to timestamp - {"date", `"2019-01-02"`, "timestamp", "2019-01-02 00:00:00", 0}, - {"date", `"19-01-02"`, "timestamp", "2019-01-02 00:00:00", 0}, - {"date", `"20190102"`, "timestamp", "2019-01-02 00:00:00", 0}, - {"date", `"190102"`, "timestamp", "2019-01-02 00:00:00", 0}, - {"date", `20190102`, "timestamp", "2019-01-02 00:00:00", 0}, - {"date", `190102`, "timestamp", "2019-01-02 00:00:00", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimestampToYear(c *C) { - tests := []testModifyColumnTimeCase{ - // timestamp to year - {"timestamp", `"2006-01-02 15:04:05"`, "year", "2006", 0}, - {"timestamp", `"06-01-02 15:04:05"`, "year", "2006", 0}, - {"timestamp", `"20060102150405"`, "year", "2006", 0}, - {"timestamp", `"060102150405"`, "year", "2006", 0}, - {"timestamp", `20060102150405`, "year", "2006", 0}, - {"timestamp", `060102150405`, "year", "2006", 0}, - {"timestamp", `"2006-01-02 23:59:59.506"`, "year", "2006", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimestampToTime(c *C) { - tests := []testModifyColumnTimeCase{ - // timestamp to time - {"timestamp", `"2006-01-02 15:04:05"`, "time", "15:04:05", 0}, - {"timestamp", `"06-01-02 15:04:05"`, "time", "15:04:05", 0}, - {"timestamp", `"20060102150405"`, "time", "15:04:05", 0}, - {"timestamp", `"060102150405"`, "time", "15:04:05", 0}, - {"timestamp", `20060102150405`, "time", "15:04:05", 0}, - {"timestamp", `060102150405`, "time", "15:04:05", 0}, - {"timestamp", `"2006-01-02 23:59:59.506"`, "time", "00:00:00", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimestampToDate(c *C) { - tests := []testModifyColumnTimeCase{ - // timestamp to date - {"timestamp", `"2006-01-02 15:04:05"`, "date", "2006-01-02", 0}, - {"timestamp", `"06-01-02 15:04:05"`, "date", "2006-01-02", 0}, - {"timestamp", `"20060102150405"`, "date", "2006-01-02", 0}, - {"timestamp", `"060102150405"`, "date", "2006-01-02", 0}, - {"timestamp", `20060102150405`, "date", "2006-01-02", 0}, - {"timestamp", `060102150405`, "date", "2006-01-02", 0}, - {"timestamp", `"2006-01-02 23:59:59.506"`, "date", "2006-01-03", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_TimestampToDatetime(c *C) { - tests := []testModifyColumnTimeCase{ - // timestamp to datetime - {"timestamp", `"2006-01-02 15:04:05"`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `"06-01-02 15:04:05"`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `"20060102150405"`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `"060102150405"`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `20060102150405`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `060102150405`, "datetime", "2006-01-02 15:04:05", 0}, - {"timestamp", `"2006-01-02 23:59:59.506"`, "datetime", "2006-01-03 00:00:00", 0}, - } - testModifyColumnTime(c, s.store, tests) -} - -func (s *testDBSuite1) TestModifyColumnTime_DatetimeToYear(c *C) { - tests := []testModifyColumnTimeCase{ - // datetime to year - {"datetime", `"2006-01-02 15:04:05"`, "year", "2006", 0}, - {"datetime", `"06-01-02 15:04:05"`, "year", "2006", 0}, - {"datetime", `"20060102150405"`, "year", "2006", 0}, - {"datetime", `"060102150405"`, "year", "2006", 0}, - {"datetime", `20060102150405`, "year", "2006", 0}, - {"datetime", `060102150405`, "year", "2006", 0}, - {"datetime", `"2006-01-02 23:59:59.506"`, "year", "2006", 0}, - {"datetime", `"1000-01-02 23:59:59"`, "year", "", errno.ErrWarnDataOutOfRange}, - {"datetime", `"9999-01-02 23:59:59"`, "year", "", errno.ErrWarnDataOutOfRange}, + currJob = job + times++ + } + } } - testModifyColumnTime(c, s.store, tests) -} + d.SetHook(hook) -func (s *testDBSuite1) TestModifyColumnTime_DatetimeToTime(c *C) { - tests := []testModifyColumnTimeCase{ - // datetime to time - {"datetime", `"2006-01-02 15:04:05"`, "time", "15:04:05", 0}, - {"datetime", `"06-01-02 15:04:05"`, "time", "15:04:05", 0}, - {"datetime", `"20060102150405"`, "time", "15:04:05", 0}, - {"datetime", `"060102150405"`, "time", "15:04:05", 0}, - {"datetime", `20060102150405`, "time", "15:04:05", 0}, - {"datetime", `060102150405`, "time", "15:04:05", 0}, - {"datetime", `"2006-01-02 23:59:59.506"`, "time", "00:00:00", 0}, - {"datetime", `"1000-01-02 23:59:59"`, "time", "23:59:59", 0}, - {"datetime", `"9999-01-02 23:59:59"`, "time", "23:59:59", 0}, - } - testModifyColumnTime(c, s.store, tests) -} + tk.MustGetErrMsg("alter table t1 add index expr_idx ((pow(c1, c2)));", "[ddl:8202]Cannot decode index value, because [types:1690]DOUBLE value is out of range in 'pow(160, 160)'") + require.NoError(t, checkErr) + tk.MustQuery("select * from t1 order by c1;").Check(testkit.Rows("2 2 2", "4 4 4", "5 80 80", "10 3 3", "20 20 20", "160 160 160")) -func (s *testDBSuite1) TestModifyColumnTime_DatetimeToDate(c *C) { - tests := []testModifyColumnTimeCase{ - // datetime to date - {"datetime", `"2006-01-02 15:04:05"`, "date", "2006-01-02", 0}, - {"datetime", `"06-01-02 15:04:05"`, "date", "2006-01-02", 0}, - {"datetime", `"20060102150405"`, "date", "2006-01-02", 0}, - {"datetime", `"060102150405"`, "date", "2006-01-02", 0}, - {"datetime", `20060102150405`, "date", "2006-01-02", 0}, - {"datetime", `060102150405`, "date", "2006-01-02", 0}, - {"datetime", `"2006-01-02 23:59:59.506"`, "date", "2006-01-03", 0}, - {"datetime", `"1000-01-02 23:59:59"`, "date", "1000-01-02", 0}, - {"datetime", `"9999-01-02 23:59:59"`, "date", "9999-01-02", 0}, - } - testModifyColumnTime(c, s.store, tests) + // Check whether the reorg information is cleaned up. + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err := ctx.Txn(true) + require.NoError(t, err) + m := meta.NewMeta(txn) + element, start, end, physicalID, err := m.GetDDLReorgHandle(currJob) + require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err)) + require.Nil(t, element) + require.Nil(t, start) + require.Nil(t, end) + require.Equal(t, int64(0), physicalID) } -func (s *testDBSuite1) TestModifyColumnTime_DatetimeToTimestamp(c *C) { - tests := []testModifyColumnTimeCase{ - // datetime to timestamp - {"datetime", `"2006-01-02 15:04:05"`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `"06-01-02 15:04:05"`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `"20060102150405"`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `"060102150405"`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `20060102150405`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `060102150405`, "timestamp", "2006-01-02 15:04:05", 0}, - {"datetime", `"2006-01-02 23:59:59.506"`, "timestamp", "2006-01-03 00:00:00", 0}, - {"datetime", `"1971-01-02 23:59:59"`, "timestamp", "1971-01-02 23:59:59", 0}, - {"datetime", `"2009-01-02 23:59:59"`, "timestamp", "2009-01-02 23:59:59", 0}, - } - testModifyColumnTime(c, s.store, tests) +func TestDropTableOnTiKVDiskFull(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table test_disk_full_drop_table(a int);") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull")) + }() + tk.MustExec("drop table test_disk_full_drop_table;") } -func (s *testDBSuite1) TestModifyColumnTime_YearToTime(c *C) { - tests := []testModifyColumnTimeCase{ - // year to time - // failed cases are not handled by TiDB - {"year", `"2019"`, "time", "00:20:19", 0}, - {"year", `2019`, "time", "00:20:19", 0}, - {"year", `"00"`, "time", "00:20:00", 0}, - {"year", `"69"`, "time", "", errno.ErrTruncatedWrongValue}, - {"year", `"70"`, "time", "", errno.ErrTruncatedWrongValue}, - {"year", `"99"`, "time", "", errno.ErrTruncatedWrongValue}, - {"year", `00`, "time", "00:00:00", 0}, - {"year", `69`, "time", "", errno.ErrTruncatedWrongValue}, - {"year", `70`, "time", "", errno.ErrTruncatedWrongValue}, - {"year", `99`, "time", "", errno.ErrTruncatedWrongValue}, - } - testModifyColumnTime(c, s.store, tests) -} +func TestRebaseAutoID(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) + defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() -func (s *testDBSuite1) TestModifyColumnTime_YearToDate(c *C) { - tests := []testModifyColumnTimeCase{ - // year to date - {"year", `"2019"`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `2019`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `"00"`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `"69"`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `"70"`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `"99"`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `00`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `69`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `70`, "date", "", errno.ErrTruncatedWrongValue}, - {"year", `99`, "date", "", errno.ErrTruncatedWrongValue}, - } - testModifyColumnTime(c, s.store, tests) -} + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) -func (s *testDBSuite1) TestModifyColumnTime_YearToDatetime(c *C) { - tests := []testModifyColumnTimeCase{ - // year to datetime - {"year", `"2019"`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `2019`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `"00"`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `"69"`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `"70"`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `"99"`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `00`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `69`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `70`, "datetime", "", errno.ErrTruncatedWrongValue}, - {"year", `99`, "datetime", "", errno.ErrTruncatedWrongValue}, - } - testModifyColumnTime(c, s.store, tests) -} + tk.MustExec("drop database if exists tidb;") + tk.MustExec("create database tidb;") + tk.MustExec("use tidb;") + tk.MustExec("create table tidb.test (a int auto_increment primary key, b int);") + tk.MustExec("insert tidb.test values (null, 1);") + tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1")) + tk.MustExec("alter table tidb.test auto_increment = 6000;") + tk.MustExec("insert tidb.test values (null, 1);") + tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1")) + tk.MustExec("alter table tidb.test auto_increment = 5;") + tk.MustExec("insert tidb.test values (null, 1);") + tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1", "11000 1")) -func (s *testDBSuite1) TestModifyColumnTime_YearToTimestamp(c *C) { - tests := []testModifyColumnTimeCase{ - // year to timestamp - {"year", `"2019"`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `2019`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `"00"`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `"69"`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `"70"`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `"99"`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `00`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `69`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `70`, "timestamp", "", errno.ErrTruncatedWrongValue}, - {"year", `99`, "timestamp", "", errno.ErrTruncatedWrongValue}, - } - testModifyColumnTime(c, s.store, tests) -} + // Current range for table test is [11000, 15999]. + // Though it does not have a tuple "a = 15999", its global next auto increment id should be 16000. + // Anyway it is not compatible with MySQL. + tk.MustExec("alter table tidb.test auto_increment = 12000;") + tk.MustExec("insert tidb.test values (null, 1);") + tk.MustQuery("select * from tidb.test").Check(testkit.Rows("1 1", "6000 1", "11000 1", "16000 1")) -type testModifyColumnTimeCase struct { - from string - value string - to string - expect string - err uint16 + tk.MustExec("create table tidb.test2 (a int);") + tk.MustGetErrCode("alter table tidb.test2 add column b int auto_increment key, auto_increment=10;", errno.ErrUnsupportedDDLOperation) } -func testModifyColumnTime(c *C, store kv.Storage, tests []testModifyColumnTimeCase) { - limit := variable.GetDDLErrorCountLimit() - - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("set @@global.tidb_ddl_error_count_limit = 3") - - // Set time zone to UTC. - originalTz := tk.Se.GetSessionVars().TimeZone - tk.Se.GetSessionVars().TimeZone = time.UTC - defer func() { - tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %v", limit)) - tk.Se.GetSessionVars().TimeZone = originalTz - }() +func TestProcessColumnFlags(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // check `processColumnFlags()` + tk.MustExec("create table t(a year(4) comment 'xxx', b year, c bit)") + defer tk.MustExec("drop table t;") - for _, t := range tests { - tk.MustExec("drop table if exists t_mc") - tk.MustExec(fmt.Sprintf("create table t_mc(a %s)", t.from)) - tk.MustExec(fmt.Sprintf(`insert into t_mc (a) values (%s)`, t.value)) - _, err := tk.Exec(fmt.Sprintf(`alter table t_mc modify a %s`, t.to)) - if t.err != 0 { - c.Assert(err, NotNil, Commentf("%+v", t)) - c.Assert(err, ErrorMatches, fmt.Sprintf(".*[ddl:%d].*", t.err), Commentf("%+v", t)) - continue + check := func(n string, f func(uint) bool) { + tbl := external.GetTableByName(t, tk, "test", "t") + for _, col := range tbl.Cols() { + if strings.EqualFold(col.Name.L, n) { + require.True(t, f(col.Flag)) + break + } } - c.Assert(err, IsNil, Commentf("%+v", t)) - - rs, err := tk.Exec("select a from t_mc") - c.Assert(err, IsNil, Commentf("%+v", t)) + } - tk.ResultSetToResult(rs, Commentf("%+v", t)).Check(testkit.Rows(t.expect)) + yearcheck := func(f uint) bool { + return mysql.HasUnsignedFlag(f) && mysql.HasZerofillFlag(f) && !mysql.HasBinaryFlag(f) } -} -func (s *testSerialDBSuite) TestSetTableFlashReplica(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) - - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - s.mustExec(tk, c, "drop table if exists t_flash;") - tk.MustExec("create table t_flash(a int, b int)") - defer s.mustExec(tk, c, "drop table t_flash;") - - t := s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica, IsNil) - - tk.MustExec("alter table t_flash set tiflash replica 2 location labels 'a','b';") - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica, NotNil) - c.Assert(t.Meta().TiFlashReplica.Count, Equals, uint64(2)) - c.Assert(strings.Join(t.Meta().TiFlashReplica.LocationLabels, ","), Equals, "a,b") - - tk.MustExec("alter table t_flash set tiflash replica 0") - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica, IsNil) - - // Test set tiflash replica for partition table. - s.mustExec(tk, c, "drop table if exists t_flash;") - tk.MustExec("create table t_flash(a int, b int) partition by hash(a) partitions 3") - tk.MustExec("alter table t_flash set tiflash replica 2 location labels 'a','b';") - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica, NotNil) - c.Assert(t.Meta().TiFlashReplica.Count, Equals, uint64(2)) - c.Assert(strings.Join(t.Meta().TiFlashReplica.LocationLabels, ","), Equals, "a,b") - - // Use table ID as physical ID, mock for partition feature was not enabled. - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, t.Meta().ID, true) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica, NotNil) - c.Assert(t.Meta().TiFlashReplica.Available, Equals, true) - c.Assert(len(t.Meta().TiFlashReplica.AvailablePartitionIDs), Equals, 0) - - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, t.Meta().ID, false) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica.Available, Equals, false) - - // Mock for partition 0 replica was available. - partition := t.Meta().Partition - c.Assert(len(partition.Definitions), Equals, 3) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica.Available, Equals, false) - c.Assert(t.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID}) - - // Mock for partition 0 replica become unavailable. - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, false) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica.Available, Equals, false) - c.Assert(t.Meta().TiFlashReplica.AvailablePartitionIDs, HasLen, 0) - - // Mock for partition 0, 1,2 replica was available. - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[0].ID, true) - c.Assert(err, IsNil) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[1].ID, true) - c.Assert(err, IsNil) - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[2].ID, true) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica.Available, Equals, true) - c.Assert(t.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID, partition.Definitions[2].ID}) - - // Mock for partition 1 replica was unavailable. - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.Definitions[1].ID, false) - c.Assert(err, IsNil) - t = s.testGetTable(c, "t_flash") - c.Assert(t.Meta().TiFlashReplica.Available, Equals, false) - c.Assert(t.Meta().TiFlashReplica.AvailablePartitionIDs, DeepEquals, []int64{partition.Definitions[0].ID, partition.Definitions[2].ID}) - - // Test for update table replica with unknown table ID. - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, math.MaxInt64, false) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1146]Table which ID = 9223372036854775807 does not exist.") - - // Test for FindTableByPartitionID. - is := domain.GetDomain(tk.Se).InfoSchema() - t, dbInfo, _ := is.FindTableByPartitionID(partition.Definitions[0].ID) - c.Assert(t, NotNil) - c.Assert(dbInfo, NotNil) - c.Assert(t.Meta().Name.L, Equals, "t_flash") - t, dbInfo, _ = is.FindTableByPartitionID(t.Meta().ID) - c.Assert(t, IsNil) - c.Assert(dbInfo, IsNil) - err = failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) - - // Test for set replica count more than the tiflash store count. - s.mustExec(tk, c, "drop table if exists t_flash;") - tk.MustExec("create table t_flash(a int, b int)") - _, err = tk.Exec("alter table t_flash set tiflash replica 2 location labels 'a','b';") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "the tiflash replica count: 2 should be less than the total tiflash server count: 0") -} + tk.MustExec("alter table t modify a year(4)") + check("a", yearcheck) -func (s *testSerialDBSuite) TestForbitCacheTableForSystemTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - sysTables := make([]string, 0, 24) - memOrSysDB := []string{"MySQL", "INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "METRICS_SCHEMA"} - for _, db := range memOrSysDB { - tk.MustExec("use " + db) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) - rows := tk.MustQuery("show tables").Rows() - for i := 0; i < len(rows); i++ { - sysTables = append(sysTables, rows[i][0].(string)) - } - for _, one := range sysTables { - _, err := tk.Exec(fmt.Sprintf("alter table `%s` cache", one)) - if db == "MySQL" { - c.Assert(err.Error(), Equals, "[ddl:8200]ALTER table cache for tables in system database is currently unsupported") - } else { - c.Assert(err.Error(), Equals, fmt.Sprintf("[planner:1142]ALTER command denied to user 'root'@'%%' for table '%s'", strings.ToLower(one))) - } + tk.MustExec("alter table t modify a year(4) unsigned") + check("a", yearcheck) - } - sysTables = sysTables[:0] - } + tk.MustExec("alter table t modify a year(4) zerofill") + + tk.MustExec("alter table t modify b year") + check("b", yearcheck) + + tk.MustExec("alter table t modify c bit") + check("c", func(f uint) bool { + return mysql.HasUnsignedFlag(f) && !mysql.HasBinaryFlag(f) + }) } -func (s *testSerialDBSuite) TestSetTableFlashReplicaForSystemTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestForbidCacheTableForSystemTable(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) sysTables := make([]string, 0, 24) memOrSysDB := []string{"MySQL", "INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "METRICS_SCHEMA"} for _, db := range memOrSysDB { tk.MustExec("use " + db) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) rows := tk.MustQuery("show tables").Rows() for i := 0; i < len(rows); i++ { sysTables = append(sysTables, rows[i][0].(string)) } for _, one := range sysTables { - _, err := tk.Exec(fmt.Sprintf("alter table `%s` set tiflash replica 1", one)) + err := tk.ExecToErr(fmt.Sprintf("alter table `%s` cache", one)) if db == "MySQL" { - c.Assert(err.Error(), Equals, "[ddl:8200]ALTER table replica for tables in system database is currently unsupported") + require.EqualError(t, err, "[ddl:8200]ALTER table cache for tables in system database is currently unsupported") } else { - c.Assert(err.Error(), Equals, fmt.Sprintf("[planner:1142]ALTER command denied to user 'root'@'%%' for table '%s'", strings.ToLower(one))) + require.EqualError(t, err, fmt.Sprintf("[planner:1142]ALTER command denied to user 'root'@'%%' for table '%s'", strings.ToLower(one))) } } @@ -5710,62 +750,31 @@ func (s *testSerialDBSuite) TestSetTableFlashReplicaForSystemTable(c *C) { } } -func (s *testSerialDBSuite) TestSetTiFlashReplicaForTemporaryTable(c *C) { - // test for tiflash replica - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) - }() - - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists temp, temp2") - tk.MustExec("drop table if exists temp") - tk.MustExec("create global temporary table temp(id int) on commit delete rows") - tk.MustExec("create temporary table temp2(id int)") - tk.MustGetErrCode("alter table temp set tiflash replica 1", errno.ErrOptOnTemporaryTable) - tk.MustGetErrCode("alter table temp2 set tiflash replica 1", errno.ErrUnsupportedDDLOperation) - tk.MustExec("drop table temp, temp2") - - tk.MustExec("drop table if exists normal") - tk.MustExec("create table normal(id int)") - defer tk.MustExec("drop table normal") - tk.MustExec("alter table normal set tiflash replica 1") - tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='normal'").Check(testkit.Rows("1")) - tk.MustExec("create global temporary table temp like normal on commit delete rows") - tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='temp'").Check(testkit.Rows()) - tk.MustExec("drop table temp") - tk.MustExec("create temporary table temp like normal") - tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='temp'").Check(testkit.Rows()) -} - -func (s *testSerialDBSuite) TestAlterShardRowIDBits(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) +func TestAlterShardRowIDBits(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test alter shard_row_id_bits - tk.MustExec("drop table if exists t1") - defer tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int) shard_row_id_bits = 5") tk.MustExec(fmt.Sprintf("alter table t1 auto_increment = %d;", 1<<56)) tk.MustExec("insert into t1 set a=1;") // Test increase shard_row_id_bits failed by overflow global auto ID. - _, err := tk.Exec("alter table t1 SHARD_ROW_ID_BITS = 10;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[autoid:1467]shard_row_id_bits 10 will cause next global auto ID 72057594037932936 overflow") + tk.MustGetErrMsg("alter table t1 SHARD_ROW_ID_BITS = 10;", "[autoid:1467]shard_row_id_bits 10 will cause next global auto ID 72057594037932936 overflow") // Test reduce shard_row_id_bits will be ok. tk.MustExec("alter table t1 SHARD_ROW_ID_BITS = 3;") checkShardRowID := func(maxShardRowIDBits, shardRowIDBits uint64) { - tbl := testGetTableByName(c, tk.Se, "test", "t1") - c.Assert(tbl.Meta().MaxShardRowIDBits == maxShardRowIDBits, IsTrue) - c.Assert(tbl.Meta().ShardRowIDBits == shardRowIDBits, IsTrue) + tbl := external.GetTableByName(t, tk, "test", "t1") + require.True(t, tbl.Meta().MaxShardRowIDBits == maxShardRowIDBits) + require.True(t, tbl.Meta().ShardRowIDBits == shardRowIDBits) } checkShardRowID(5, 3) @@ -5775,869 +784,80 @@ func (s *testSerialDBSuite) TestAlterShardRowIDBits(c *C) { tk.MustExec("alter table t1 SHARD_ROW_ID_BITS = 5;") checkShardRowID(10, 5) tk.MustExec(fmt.Sprintf("alter table t1 auto_increment = %d;", 1<<56)) - _, err = tk.Exec("insert into t1 set a=1;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[autoid:1467]Failed to read auto-increment value from storage engine") + tk.MustGetErrMsg("insert into t1 set a=1;", "[autoid:1467]Failed to read auto-increment value from storage engine") } -func (s *testSerialDBSuite) TestShardRowIDBitsOnTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShardRowIDBitsOnTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // for global temporary table tk.MustExec("drop table if exists shard_row_id_temporary") - _, err := tk.Exec("create global temporary table shard_row_id_temporary (a int) shard_row_id_bits = 5 on commit delete rows;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) + tk.MustGetErrMsg( + "create global temporary table shard_row_id_temporary (a int) shard_row_id_bits = 5 on commit delete rows;", + core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) tk.MustExec("create global temporary table shard_row_id_temporary (a int) on commit delete rows;") - defer tk.MustExec("drop table if exists shard_row_id_temporary") - _, err = tk.Exec("alter table shard_row_id_temporary shard_row_id_bits = 4;") - c.Assert(err.Error(), Equals, ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) + tk.MustGetErrMsg( + "alter table shard_row_id_temporary shard_row_id_bits = 4;", + dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) // for local temporary table tk.MustExec("drop table if exists local_shard_row_id_temporary") - _, err = tk.Exec("create temporary table local_shard_row_id_temporary (a int) shard_row_id_bits = 5;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) + tk.MustGetErrMsg( + "create temporary table local_shard_row_id_temporary (a int) shard_row_id_bits = 5;", + core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) tk.MustExec("create temporary table local_shard_row_id_temporary (a int);") - defer tk.MustExec("drop table if exists local_shard_row_id_temporary") - _, err = tk.Exec("alter table local_shard_row_id_temporary shard_row_id_bits = 4;") - c.Assert(err.Error(), Equals, ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ALTER TABLE").Error()) -} - -// port from mysql -// https://github.com/mysql/mysql-server/blob/124c7ab1d6f914637521fd4463a993aa73403513/mysql-test/t/lock.test -func (s *testDBSuite2) TestLock(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - /* Testing of table locking */ - tk.MustExec("DROP TABLE IF EXISTS t1") - tk.MustExec("CREATE TABLE t1 ( `id` int(11) NOT NULL default '0', `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0', `dummy1` char(30) default NULL, PRIMARY KEY (`id`,`id2`), KEY `index_id3` (`id3`))") - tk.MustExec("insert into t1 (id,id2) values (1,1),(1,2),(1,3)") - tk.MustExec("LOCK TABLE t1 WRITE") - tk.MustExec("select dummy1,count(distinct id) from t1 group by dummy1") - tk.MustExec("update t1 set id=-1 where id=1") - tk.MustExec("LOCK TABLE t1 READ") - _, err := tk.Exec("update t1 set id=1 where id=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite), IsTrue) - tk.MustExec("unlock tables") - tk.MustExec("update t1 set id=1 where id=-1") - tk.MustExec("drop table t1") -} - -// port from mysql -// https://github.com/mysql/mysql-server/blob/4f1d7cf5fcb11a3f84cff27e37100d7295e7d5ca/mysql-test/t/tablelock.test -func (s *testDBSuite2) TestTableLock(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2") - - /* Test of lock tables */ - tk.MustExec("create table t1 ( n int auto_increment primary key)") - tk.MustExec("lock tables t1 write") - tk.MustExec("insert into t1 values(NULL)") - tk.MustExec("unlock tables") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - - tk.MustExec("lock tables t1 write") - tk.MustExec("insert into t1 values(NULL)") - tk.MustExec("unlock tables") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - - tk.MustExec("drop table if exists t1") - - /* Test of locking and delete of files */ - tk.MustExec("drop table if exists t1,t2") - tk.MustExec("CREATE TABLE t1 (a int)") - tk.MustExec("CREATE TABLE t2 (a int)") - tk.MustExec("lock tables t1 write, t2 write") - tk.MustExec("drop table t1,t2") - - tk.MustExec("CREATE TABLE t1 (a int)") - tk.MustExec("CREATE TABLE t2 (a int)") - tk.MustExec("lock tables t1 write, t2 write") - tk.MustExec("drop table t2,t1") -} - -// port from mysql -// https://github.com/mysql/mysql-server/blob/4f1d7cf5fcb11a3f84cff27e37100d7295e7d5ca/mysql-test/t/lock_tables_lost_commit.test -func (s *testDBSuite2) TestTableLocksLostCommit(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk2.MustExec("use test") - - tk.MustExec("DROP TABLE IF EXISTS t1") - tk.MustExec("CREATE TABLE t1(a INT)") - tk.MustExec("LOCK TABLES t1 WRITE") - tk.MustExec("INSERT INTO t1 VALUES(10)") - - _, err := tk2.Exec("SELECT * FROM t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - tk.Se.Close() - - tk2.MustExec("SELECT * FROM t1") - tk2.MustExec("DROP TABLE t1") - - tk.MustExec("unlock tables") -} - -// test write local lock -func (s *testDBSuite2) TestWriteLocal(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk2.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 ( n int auto_increment primary key)") - - // Test: allow read - tk.MustExec("lock tables t1 write local") - tk.MustExec("insert into t1 values(NULL)") - tk2.MustQuery("select count(*) from t1") - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test: forbid write - tk.MustExec("lock tables t1 write local") - _, err := tk2.Exec("insert into t1 values(NULL)") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test mutex: lock write local first - tk.MustExec("lock tables t1 write local") - _, err = tk2.Exec("lock tables t1 write local") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("lock tables t1 write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("lock tables t1 read") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test mutex: lock write first - tk.MustExec("lock tables t1 write") - _, err = tk2.Exec("lock tables t1 write local") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test mutex: lock read first - tk.MustExec("lock tables t1 read") - _, err = tk2.Exec("lock tables t1 write local") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") -} - -func (s *testSerialDBSuite) TestSkipSchemaChecker(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) - }() - - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - defer tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int)") - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - // Test skip schema checker for ActionSetTiFlashReplica. - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1;") - tk2.MustExec("alter table t1 set tiflash replica 2 location labels 'a','b';") - tk.MustExec("commit") - - // Test skip schema checker for ActionUpdateTiFlashReplicaStatus. - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1;") - tb := testGetTableByName(c, tk.Se, "test", "t1") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) - tk.MustExec("commit") - - // Test can't skip schema checker. - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1;") - tk2.MustExec("alter table t1 add column b int;") - _, err = tk.Exec("commit") - c.Assert(terror.ErrorEqual(domain.ErrInfoSchemaChanged, err), IsTrue) -} - -// See issue: https://github.com/pingcap/tidb/issues/29752 -// Ref https://dev.mysql.com/doc/refman/8.0/en/rename-table.html -func (s *testDBSuite2) TestRenameTableWithLocked(c *C) { - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.EnableTableLock = true - }) - - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database renamedb") - tk.MustExec("create database renamedb2") - tk.MustExec("use renamedb") - tk.MustExec("DROP TABLE IF EXISTS t1;") - tk.MustExec("CREATE TABLE t1 (a int);") - - tk.MustExec("LOCK TABLES t1 WRITE;") - tk.MustGetErrCode("drop database renamedb2;", errno.ErrLockOrActiveTransaction) - tk.MustExec("RENAME TABLE t1 TO t2;") - tk.MustQuery("select * from renamedb.t2").Check(testkit.Rows()) - tk.MustExec("UNLOCK TABLES") - tk.MustExec("RENAME TABLE t2 TO t1;") - tk.MustQuery("select * from renamedb.t1").Check(testkit.Rows()) - - tk.MustExec("LOCK TABLES t1 READ;") - tk.MustGetErrCode("RENAME TABLE t1 TO t2;", errno.ErrTableNotLockedForWrite) - tk.MustExec("UNLOCK TABLES") - - tk.MustExec("drop database renamedb") -} - -func (s *testDBSuite2) TestLockTables(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2") - defer tk.MustExec("drop table if exists t1,t2") - tk.MustExec("create table t1 (a int)") - tk.MustExec("create table t2 (a int)") - - // Test lock 1 table. - tk.MustExec("lock tables t1 write") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - tk.MustExec("lock tables t1 read") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockRead) - tk.MustExec("lock tables t1 write") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - - // Test lock multi tables. - tk.MustExec("lock tables t1 write, t2 read") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - checkTableLock(c, tk.Se, "test", "t2", model.TableLockRead) - tk.MustExec("lock tables t1 read, t2 write") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockRead) - checkTableLock(c, tk.Se, "test", "t2", model.TableLockWrite) - tk.MustExec("lock tables t2 write") - checkTableLock(c, tk.Se, "test", "t2", model.TableLockWrite) - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - tk.MustExec("lock tables t1 write") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - checkTableLock(c, tk.Se, "test", "t2", model.TableLockNone) - - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - // Test read lock. - tk.MustExec("lock tables t1 read") - tk.MustQuery("select * from t1") - tk2.MustQuery("select * from t1") - _, err := tk.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite), IsTrue) - _, err = tk.Exec("update t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite), IsTrue) - _, err = tk.Exec("delete from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite), IsTrue) - - _, err = tk2.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("update t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("delete from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk2.MustExec("lock tables t1 read") - _, err = tk2.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLockedForWrite), IsTrue) - - // Test write lock. - _, err = tk.Exec("lock tables t1 write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk2.MustExec("unlock tables") - tk.MustExec("lock tables t1 write") - tk.MustQuery("select * from t1") - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 set a=1") - - _, err = tk2.Exec("select * from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("lock tables t1 write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - // Test write local lock. - tk.MustExec("lock tables t1 write local") - tk.MustQuery("select * from t1") - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 set a=1") - - tk2.MustQuery("select * from t1") - _, err = tk2.Exec("delete from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("lock tables t1 write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("lock tables t1 read") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - // Test none unique table. - _, err = tk.Exec("lock tables t1 read, t1 write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrNonuniqTable), IsTrue) - - // Test lock table by other session in transaction and commit without retry. - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - tk.MustExec("set @@session.tidb_disable_txn_auto_retry=1") - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1") - tk2.MustExec("lock tables t1 write") - _, err = tk.Exec("commit") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "previous statement: insert into t1 set a=1: [domain:8028]Information schema is changed during the execution of the statement(for example, table definition may be updated by other DDL ran in parallel). If you see this error often, try increasing `tidb_max_delta_schema_count`. [try again later]") - - // Test lock table by other session in transaction and commit with retry. - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - tk.MustExec("set @@session.tidb_disable_txn_auto_retry=0") - tk.MustExec("begin") - tk.MustExec("insert into t1 set a=1") - tk2.MustExec("lock tables t1 write") - _, err = tk.Exec("commit") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue, Commentf("err: %v\n", err)) - - // Test for lock the same table multiple times. - tk2.MustExec("lock tables t1 write") - tk2.MustExec("lock tables t1 write, t2 read") - - // Test lock tables and drop tables - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - tk.MustExec("lock tables t1 write, t2 write") - tk.MustExec("drop table t1") - tk2.MustExec("create table t1 (a int)") - tk.MustExec("lock tables t1 write, t2 read") - - // Test lock tables and drop database. - tk.MustExec("unlock tables") - tk.MustExec("create database test_lock") - tk.MustExec("create table test_lock.t3 (a int)") - tk.MustExec("lock tables t1 write, test_lock.t3 write") - tk2.MustExec("create table t3 (a int)") - tk.MustExec("lock tables t1 write, t3 write") - tk.MustExec("drop table t3") - - // Test lock tables and truncate tables. - tk.MustExec("unlock tables") - tk.MustExec("lock tables t1 write, t2 read") - tk.MustExec("truncate table t1") - tk.MustExec("insert into t1 set a=1") - _, err = tk2.Exec("insert into t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - // Test for lock unsupported schema tables. - _, err = tk2.Exec("lock tables performance_schema.global_status write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrAccessDenied), IsTrue) - _, err = tk2.Exec("lock tables information_schema.tables write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrAccessDenied), IsTrue) - _, err = tk2.Exec("lock tables mysql.db write") - c.Assert(terror.ErrorEqual(err, infoschema.ErrAccessDenied), IsTrue) - - // Test create table/view when session is holding the table locks. - tk.MustExec("unlock tables") - tk.MustExec("lock tables t1 write, t2 read") - _, err = tk.Exec("create table t3 (a int)") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLocked), IsTrue) - _, err = tk.Exec("create view v1 as select * from t1;") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotLocked), IsTrue) - - // Test for locking view was not supported. - tk.MustExec("unlock tables") - tk.MustExec("create view v1 as select * from t1;") - _, err = tk.Exec("lock tables v1 read") - c.Assert(terror.ErrorEqual(err, table.ErrUnsupportedOp), IsTrue) - - // Test for locking sequence was not supported. - tk.MustExec("unlock tables") - tk.MustExec("create sequence seq") - _, err = tk.Exec("lock tables seq read") - c.Assert(terror.ErrorEqual(err, table.ErrUnsupportedOp), IsTrue) - tk.MustExec("drop sequence seq") - - // Test for create/drop/alter database when session is holding the table locks. - tk.MustExec("unlock tables") - tk.MustExec("lock table t1 write") - _, err = tk.Exec("drop database test") - c.Assert(terror.ErrorEqual(err, table.ErrLockOrActiveTransaction), IsTrue) - _, err = tk.Exec("create database test_lock") - c.Assert(terror.ErrorEqual(err, table.ErrLockOrActiveTransaction), IsTrue) - _, err = tk.Exec("alter database test charset='utf8mb4'") - c.Assert(terror.ErrorEqual(err, table.ErrLockOrActiveTransaction), IsTrue) - // Test alter/drop database when other session is holding the table locks of the database. - tk2.MustExec("create database test_lock2") - _, err = tk2.Exec("drop database test") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("alter database test charset='utf8mb4'") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - // Test for admin cleanup table locks. - tk.MustExec("unlock tables") - tk.MustExec("lock table t1 write, t2 write") - _, err = tk2.Exec("lock tables t1 write, t2 read") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk2.MustExec("admin cleanup table lock t1,t2") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - checkTableLock(c, tk.Se, "test", "t2", model.TableLockNone) - // cleanup unlocked table. - tk2.MustExec("admin cleanup table lock t1,t2") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - checkTableLock(c, tk.Se, "test", "t2", model.TableLockNone) - tk2.MustExec("lock tables t1 write, t2 read") - checkTableLock(c, tk2.Se, "test", "t1", model.TableLockWrite) - checkTableLock(c, tk2.Se, "test", "t2", model.TableLockRead) - - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") -} - -func (s *testDBSuite2) TestTablesLockDelayClean(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2") - defer tk.MustExec("drop table if exists t1,t2") - tk.MustExec("create table t1 (a int)") - tk.MustExec("create table t2 (a int)") - - tk.MustExec("lock tables t1 write") - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - config.UpdateGlobal(func(conf *config.Config) { - conf.DelayCleanTableLock = 100 - }) - var wg sync.WaitGroup - wg.Add(1) - var startTime time.Time - go func() { - startTime = time.Now() - tk.Se.Close() - wg.Done() - }() - time.Sleep(50 * time.Millisecond) - checkTableLock(c, tk.Se, "test", "t1", model.TableLockWrite) - wg.Wait() - c.Assert(time.Since(startTime).Seconds() > 0.1, IsTrue) - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) - config.UpdateGlobal(func(conf *config.Config) { - conf.DelayCleanTableLock = 0 - }) -} - -// TestConcurrentLockTables test concurrent lock/unlock tables. -func (s *testDBSuite4) TestConcurrentLockTables(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - defer tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int)") - tk2.MustExec("use test") - - // Test concurrent lock tables read. - sql1 := "lock tables t1 read" - sql2 := "lock tables t1 read" - s.testParallelExecSQL(c, sql1, sql2, tk.Se, tk2.Se, func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(err2, IsNil) - }) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test concurrent lock tables write. - sql1 = "lock tables t1 write" - sql2 = "lock tables t1 write" - s.testParallelExecSQL(c, sql1, sql2, tk.Se, tk2.Se, func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(terror.ErrorEqual(err2, infoschema.ErrTableLocked), IsTrue) - }) - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") - - // Test concurrent lock tables write local. - sql1 = "lock tables t1 write local" - sql2 = "lock tables t1 write local" - s.testParallelExecSQL(c, sql1, sql2, tk.Se, tk2.Se, func(c *C, err1, err2 error) { - c.Assert(err1, IsNil) - c.Assert(terror.ErrorEqual(err2, infoschema.ErrTableLocked), IsTrue) - }) - - tk.MustExec("unlock tables") - tk2.MustExec("unlock tables") -} - -func (s *testDBSuite4) TestLockTableReadOnly(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2") - defer func() { - tk.MustExec("alter table t1 read write") - tk.MustExec("alter table t2 read write") - tk.MustExec("drop table if exists t1,t2") - }() - tk.MustExec("create table t1 (a int key, b int)") - tk.MustExec("create table t2 (a int key)") - - tk.MustExec("alter table t1 read only") - tk.MustQuery("select * from t1") - tk2.MustQuery("select * from t1") - _, err := tk.Exec("insert into t1 set a=1, b=2") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk.Exec("update t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk.Exec("delete from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - - _, err = tk2.Exec("insert into t1 set a=1, b=2") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("update t1 set a=1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - _, err = tk2.Exec("delete from t1") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk2.MustExec("alter table t1 read only") - _, err = tk2.Exec("insert into t1 set a=1, b=2") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableLocked), IsTrue) - tk.MustExec("alter table t1 read write") - - tk.MustExec("lock tables t1 read") - c.Assert(terror.ErrorEqual(tk.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - tk.MustExec("lock tables t1 write") - c.Assert(terror.ErrorEqual(tk.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - tk.MustExec("lock tables t1 write local") - c.Assert(terror.ErrorEqual(tk.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked), IsTrue) - tk.MustExec("unlock tables") - - tk.MustExec("alter table t1 read only") - c.Assert(terror.ErrorEqual(tk.ExecToErr("lock tables t1 read"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("lock tables t1 read"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk.ExecToErr("lock tables t1 write"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("lock tables t1 write"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk.ExecToErr("lock tables t1 write local"), infoschema.ErrTableLocked), IsTrue) - c.Assert(terror.ErrorEqual(tk2.ExecToErr("lock tables t1 write local"), infoschema.ErrTableLocked), IsTrue) - tk.MustExec("admin cleanup table lock t1") - tk2.MustExec("insert into t1 set a=1, b=2") - - tk.MustExec("set tidb_enable_amend_pessimistic_txn = 1") - tk.MustExec("begin pessimistic") - tk.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 2")) - tk2.MustExec("update t1 set b = 3") - tk2.MustExec("alter table t1 read only") - tk2.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 3")) - tk.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 2")) - tk.MustExec("update t1 set b = 4") - c.Assert(terror.ErrorEqual(tk.ExecToErr("commit"), domain.ErrInfoSchemaChanged), IsTrue) - tk2.MustExec("alter table t1 read write") -} - -func (s *testDBSuite4) testParallelExecSQL(c *C, sql1, sql2 string, se1, se2 session.Session, f checkRet) { - callback := &ddl.TestDDLCallback{} - times := 0 - callback.OnJobRunBeforeExported = func(job *model.Job) { - if times != 0 { - return - } - var qLen int - for { - err := kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - jobs, err1 := admin.GetDDLJobs(txn) - if err1 != nil { - return err1 - } - qLen = len(jobs) - return nil - }) - c.Assert(err, IsNil) - if qLen == 2 { - break - } - time.Sleep(5 * time.Millisecond) - } - times++ - } - d := s.dom.DDL() - originalCallback := d.GetHook() - defer d.(ddl.DDLForTest).SetHook(originalCallback) - d.(ddl.DDLForTest).SetHook(callback) - - wg := sync.WaitGroup{} - var err1 error - var err2 error - wg.Add(2) - ch := make(chan struct{}) - // Make sure the sql1 is put into the DDLJobQueue. - go func() { - var qLen int - for { - err := kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - jobs, err3 := admin.GetDDLJobs(txn) - if err3 != nil { - return err3 - } - qLen = len(jobs) - return nil - }) - c.Assert(err, IsNil) - if qLen == 1 { - // Make sure sql2 is executed after the sql1. - close(ch) - break - } - time.Sleep(5 * time.Millisecond) - } - }() - go func() { - defer wg.Done() - _, err1 = se1.Execute(context.Background(), sql1) - }() - go func() { - defer wg.Done() - <-ch - _, err2 = se2.Execute(context.Background(), sql2) - }() - - wg.Wait() - f(c, err1, err2) -} - -func checkTableLock(c *C, se session.Session, dbName, tableName string, lockTp model.TableLockType) { - tb := testGetTableByName(c, se, dbName, tableName) - dom := domain.GetDomain(se) - err := dom.Reload() - c.Assert(err, IsNil) - if lockTp != model.TableLockNone { - c.Assert(tb.Meta().Lock, NotNil) - c.Assert(tb.Meta().Lock.Tp, Equals, lockTp) - c.Assert(tb.Meta().Lock.State, Equals, model.TableLockStatePublic) - c.Assert(len(tb.Meta().Lock.Sessions) == 1, IsTrue) - c.Assert(tb.Meta().Lock.Sessions[0].ServerID, Equals, dom.DDL().GetID()) - c.Assert(tb.Meta().Lock.Sessions[0].SessionID, Equals, se.GetSessionVars().ConnectionID) - } else { - c.Assert(tb.Meta().Lock, IsNil) - } -} - -func (s *testDBSuite2) TestDDLWithInvalidTableInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - defer tk.MustExec("drop table if exists t") - // Test create with invalid expression. - _, err := tk.Exec(`CREATE TABLE t ( - c0 int(11) , - c1 int(11), - c2 decimal(16,4) GENERATED ALWAYS AS ((case when (c0 = 0) then 0when (c0 > 0) then (c1 / c0) end)) - );`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 4 column 88 near \"then (c1 / c0) end))\n\t);\" ") - - tk.MustExec("create table t (a bigint, b int, c int generated always as (b+1)) partition by hash(a) partitions 4;") - // Test drop partition column. - _, err = tk.Exec("alter table t drop column a;") - c.Assert(err, NotNil) - // TODO: refine the error message to compatible with MySQL - c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 'a' in 'expression'") - // Test modify column with invalid expression. - _, err = tk.Exec("alter table t modify column c int GENERATED ALWAYS AS ((case when (a = 0) then 0when (a > 0) then (b / a) end));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 97 near \"then (b / a) end));\" ") - // Test add column with invalid expression. - _, err = tk.Exec("alter table t add column d int GENERATED ALWAYS AS ((case when (a = 0) then 0when (a > 0) then (b / a) end));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 94 near \"then (b / a) end));\" ") -} - -func (s *testDBSuite4) TestColumnCheck(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists column_check") - tk.MustExec("create table column_check (pk int primary key, a int check (a > 1))") - defer tk.MustExec("drop table if exists column_check") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8231|CONSTRAINT CHECK is not supported")) -} - -func (s *testDBSuite5) TestAlterCheck(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists alter_check") - tk.MustExec("create table alter_check (pk int primary key)") - defer tk.MustExec("drop table if exists alter_check") - tk.MustExec("alter table alter_check alter check crcn ENFORCED") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8231|ALTER CHECK is not supported")) -} - -func (s *testDBSuite6) TestDropCheck(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists drop_check") - tk.MustExec("create table drop_check (pk int primary key)") - defer tk.MustExec("drop table if exists drop_check") - tk.MustExec("alter table drop_check drop check crcn") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8231|DROP CHECK is not supported")) -} - -func (s *testDBSuite7) TestAddConstraintCheck(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists add_constraint_check") - tk.MustExec("create table add_constraint_check (pk int primary key, a int)") - defer tk.MustExec("drop table if exists add_constraint_check") - tk.MustExec("alter table add_constraint_check add constraint crn check (a > 1)") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8231|ADD CONSTRAINT CHECK is not supported")) -} - -func (s *testDBSuite7) TestCreateTableIngoreCheckConstraint(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("drop table if exists table_constraint_check") - tk.MustExec("CREATE TABLE admin_user (enable bool, CHECK (enable IN (0, 1)));") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8231|CONSTRAINT CHECK is not supported")) - tk.MustQuery("show create table admin_user").Check(testutil.RowsWithSep("|", ""+ - "admin_user CREATE TABLE `admin_user` (\n"+ - " `enable` tinyint(1) DEFAULT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) -} - -func (s *testDBSuite6) TestAlterOrderBy(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use " + s.schemaName) - tk.MustExec("create table ob (pk int primary key, c int default 1, c1 int default 1, KEY cl(c1))") - - // Test order by with primary key - tk.MustExec("alter table ob order by c") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|ORDER BY ignored as there is a user-defined clustered index in the table 'ob'")) - - // Test order by with no primary key - tk.MustExec("drop table if exists ob") - tk.MustExec("create table ob (c int default 1, c1 int default 1, KEY cl(c1))") - tk.MustExec("alter table ob order by c") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) - tk.MustExec("drop table if exists ob") + tk.MustGetErrMsg( + "alter table local_shard_row_id_temporary shard_row_id_bits = 4;", + dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ALTER TABLE").Error()) } -func (s *testSerialDBSuite) TestDDLJobErrorCount(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDDLJobErrorCount(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ddl_error_table, new_ddl_error_table") tk.MustExec("create table ddl_error_table(a int)") - is := s.dom.InfoSchema() - schemaName := model.NewCIStr("test") - tableName := model.NewCIStr("ddl_error_table") - schema, ok := is.SchemaByName(schemaName) - c.Assert(ok, IsTrue) - tbl, err := is.TableByName(schemaName, tableName) - c.Assert(err, IsNil) - - newTableName := model.NewCIStr("new_ddl_error_table") - job := &model.Job{ - SchemaID: schema.ID, - TableID: tbl.Meta().ID, - SchemaName: schema.Name.L, - Type: model.ActionRenameTable, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{schema.ID, newTableName}, - } - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockErrEntrySizeTooLarge", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockErrEntrySizeTooLarge", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockErrEntrySizeTooLarge"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockErrEntrySizeTooLarge")) }() - txn, err := s.store.Begin() - c.Assert(err, IsNil) - t := meta.NewMeta(txn) - job.ID, err = t.GenGlobalID() - c.Assert(err, IsNil) - job.Version = 1 - job.StartTS = txn.StartTS() - - err = t.EnQueueDDLJob(job) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - ticker := time.NewTicker(s.lease) - defer ticker.Stop() - for range ticker.C { - historyJob, err := getHistoryDDLJob(s.store, job.ID) - c.Assert(err, IsNil) - if historyJob == nil { - continue - } - c.Assert(historyJob.ErrorCount, Equals, int64(1), Commentf("%v", historyJob)) - kv.ErrEntryTooLarge.Equal(historyJob.Error) - break + var jobID int64 + hook := &ddl.TestDDLCallback{} + hook.OnJobUpdatedExported = func(job *model.Job) { + jobID = job.ID } -} - -func (s *testDBSuite1) TestAlterTableWithValidation(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - defer tk.MustExec("drop table if exists t1") - - tk.MustExec("create table t1 (c1 int, c2 int as (c1 + 1));") + originHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + defer dom.DDL().SetHook(originHook) - // Test for alter table with validation. - tk.MustExec("alter table t1 with validation") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8200|ALTER TABLE WITH VALIDATION is currently unsupported")) + tk.MustGetErrCode("rename table ddl_error_table to new_ddl_error_table", errno.ErrEntryTooLarge) - // Test for alter table without validation. - tk.MustExec("alter table t1 without validation") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|8200|ALTER TABLE WITHOUT VALIDATION is currently unsupported")) + historyJob, err := getHistoryDDLJob(store, jobID) + require.NoError(t, err) + require.NotNil(t, historyJob) + require.Equal(t, int64(1), historyJob.ErrorCount) + require.True(t, kv.ErrEntryTooLarge.Equal(historyJob.Error)) } -func (s *testSerialDBSuite) TestCommitTxnWithIndexChange(c *C) { +func TestCommitTxnWithIndexChange(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() // Prepare work. - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("set tidb_enable_amend_pessimistic_txn = 1;") - tk.MustExec("drop database if exists test_db") - tk.MustExec("create database test_db") - tk.MustExec("use test_db") + tk.MustExec("use test") tk.MustExec("create table t1 (c1 int primary key, c2 int, c3 int, index ok2(c2))") tk.MustExec("insert t1 values (1, 10, 100), (2, 20, 200)") tk.MustExec("alter table t1 add index k2(c2)") tk.MustExec("alter table t1 drop index k2") tk.MustExec("alter table t1 add index k2(c2)") tk.MustExec("alter table t1 drop index k2") - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test_db") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") // tkSQLs are the sql statements for the pessimistic transaction. // tk2DDL are the ddl statements executed before the pessimistic transaction. @@ -6745,7 +965,7 @@ func (s *testSerialDBSuite) TestCommitTxnWithIndexChange(c *C) { tk.MustQuery("select * from t1;").Check(testkit.Rows("1 10 100", "2 20 200")) // Test add index state change - do := s.dom.DDL() + do := dom.DDL() startStates := []model.SchemaState{model.StateNone, model.StateDeleteOnly} for _, startState := range startStates { endStatMap := session.ConstOpAddIndex[startState] @@ -6787,8 +1007,8 @@ func (s *testSerialDBSuite) TestCommitTxnWithIndexChange(c *C) { } else if job.SchemaState == endState { if !committed { if curCase.failCommit { - _, err := tk.Exec("commit") - c.Assert(err, NotNil) + err := tk.ExecToErr("commit") + require.Error(t, err) } else { tk.MustExec("commit") } @@ -6797,9 +1017,9 @@ func (s *testSerialDBSuite) TestCommitTxnWithIndexChange(c *C) { } } originalCallback := do.GetHook() - do.(ddl.DDLForTest).SetHook(hook) + do.SetHook(hook) tk2.MustExec(curCase.idxDDL) - do.(ddl.DDLForTest).SetHook(originalCallback) + do.SetHook(originalCallback) tk2.MustExec("admin check table t1") for i, checkSQL := range curCase.checkSQLs { if len(curCase.rowsExps[i]) > 0 { @@ -6815,12 +1035,12 @@ func (s *testSerialDBSuite) TestCommitTxnWithIndexChange(c *C) { } // TestAddIndexFailOnCaseWhenCanExit is used to close #19325. -func (s *testSerialDBSuite) TestAddIndexFailOnCaseWhenCanExit(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/MockCaseWhenParseFailure", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/MockCaseWhenParseFailure"), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) +func TestAddIndexFailOnCaseWhenCanExit(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockCaseWhenParseFailure", `return(true)`)) + defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockCaseWhenParseFailure")) }() + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) originalVal := variable.GetDDLErrorCountLimit() tk.MustExec("set @@global.tidb_ddl_error_count_limit = 1") defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %d", originalVal)) @@ -6829,25 +1049,17 @@ func (s *testSerialDBSuite) TestAddIndexFailOnCaseWhenCanExit(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values(1, 1)") - _, err := tk.Exec("alter table t add index idx(b)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1]DDL job rollback, error msg: job.ErrCount:1, mock unknown type: ast.whenClause.") + tk.MustGetErrMsg("alter table t add index idx(b)", "[ddl:-1]DDL job rollback, error msg: job.ErrCount:1, mock unknown type: ast.whenClause.") tk.MustExec("drop table if exists t") } -func init() { - // Make sure it will only be executed once. - domain.SchemaOutOfDateRetryInterval = int64(50 * time.Millisecond) - domain.SchemaOutOfDateRetryTimes = int32(50) -} - -func (s *testSerialDBSuite) TestCreateTableWithIntegerLengthWaring(c *C) { +func TestCreateTableWithIntegerLengthWaring(t *testing.T) { // Inject the strict-integer-display-width variable in parser directly. parsertypes.TiDBStrictIntegerDisplayWidth = true - defer func() { - parsertypes.TiDBStrictIntegerDisplayWidth = false - }() - tk := testkit.NewTestKit(c, s.store) + defer func() { parsertypes.TiDBStrictIntegerDisplayWidth = false }() + store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -6897,427 +1109,38 @@ func (s *testSerialDBSuite) TestCreateTableWithIntegerLengthWaring(c *C) { tk.MustExec("drop table if exists t") } -func (s *testSerialDBSuite) TestColumnTypeChangeGenUniqueChangingName(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - - hook := &ddl.TestDDLCallback{} - var checkErr error - assertChangingColName := "_col$_c2_0" - assertChangingIdxName := "_idx$_idx_0" - hook.OnJobUpdatedExported = func(job *model.Job) { - if job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn { - var ( - newCol *model.ColumnInfo - oldColName *model.CIStr - modifyColumnTp byte - updatedAutoRandomBits uint64 - changingCol *model.ColumnInfo - changingIdxs []*model.IndexInfo - ) - pos := &ast.ColumnPosition{} - err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) - if err != nil { - checkErr = err - return - } - if changingCol.Name.L != assertChangingColName { - checkErr = errors.New("changing column name is incorrect") - } else if changingIdxs[0].Name.L != assertChangingIdxName { - checkErr = errors.New("changing index name is incorrect") - } - } - } - d := s.dom.DDL() - originHook := d.GetHook() - d.(ddl.DDLForTest).SetHook(hook) - defer d.(ddl.DDLForTest).SetHook(originHook) - - tk.MustExec("create table if not exists t(c1 varchar(256), c2 bigint, `_col$_c2` varchar(10), unique _idx$_idx(c1), unique idx(c2));") - tk.MustExec("alter table test.t change column c2 cC2 tinyint after `_col$_c2`") - c.Assert(checkErr, IsNil) - - t := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(t.Meta().Columns), Equals, 3) - c.Assert(t.Meta().Columns[0].Name.O, Equals, "c1") - c.Assert(t.Meta().Columns[0].Offset, Equals, 0) - c.Assert(t.Meta().Columns[1].Name.O, Equals, "_col$_c2") - c.Assert(t.Meta().Columns[1].Offset, Equals, 1) - c.Assert(t.Meta().Columns[2].Name.O, Equals, "cC2") - c.Assert(t.Meta().Columns[2].Offset, Equals, 2) - - c.Assert(len(t.Meta().Indices), Equals, 2) - c.Assert(t.Meta().Indices[0].Name.O, Equals, "_idx$_idx") - c.Assert(t.Meta().Indices[1].Name.O, Equals, "idx") - - c.Assert(len(t.Meta().Indices[0].Columns), Equals, 1) - c.Assert(t.Meta().Indices[0].Columns[0].Name.O, Equals, "c1") - c.Assert(t.Meta().Indices[0].Columns[0].Offset, Equals, 0) - - c.Assert(len(t.Meta().Indices[1].Columns), Equals, 1) - c.Assert(t.Meta().Indices[1].Columns[0].Name.O, Equals, "cC2") - c.Assert(t.Meta().Indices[1].Columns[0].Offset, Equals, 2) - - assertChangingColName1 := "_col$__col$_c1_1" - assertChangingColName2 := "_col$__col$__col$_c1_0_1" - query1 := "alter table t modify column _col$_c1 tinyint" - query2 := "alter table t modify column _col$__col$_c1_0 tinyint" - hook.OnJobUpdatedExported = func(job *model.Job) { - if (job.Query == query1 || job.Query == query2) && job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn { - var ( - newCol *model.ColumnInfo - oldColName *model.CIStr - modifyColumnTp byte - updatedAutoRandomBits uint64 - changingCol *model.ColumnInfo - changingIdxs []*model.IndexInfo - ) - pos := &ast.ColumnPosition{} - err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) - if err != nil { - checkErr = err - return - } - if job.Query == query1 && changingCol.Name.L != assertChangingColName1 { - checkErr = errors.New("changing column name is incorrect") - } - if job.Query == query2 && changingCol.Name.L != assertChangingColName2 { - checkErr = errors.New("changing column name is incorrect") - } - } - } - d.(ddl.DDLForTest).SetHook(hook) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table if not exists t(c1 bigint, _col$_c1 bigint, _col$__col$_c1_0 bigint, _col$__col$__col$_c1_0_0 bigint)") - tk.MustExec("alter table t modify column c1 tinyint") - tk.MustExec("alter table t modify column _col$_c1 tinyint") - c.Assert(checkErr, IsNil) - tk.MustExec("alter table t modify column _col$__col$_c1_0 tinyint") - c.Assert(checkErr, IsNil) - tk.MustExec("alter table t change column _col$__col$__col$_c1_0_0 _col$__col$__col$_c1_0_0 tinyint") - - t = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(t.Meta().Columns), Equals, 4) - c.Assert(t.Meta().Columns[0].Name.O, Equals, "c1") - c.Assert(t.Meta().Columns[0].Tp, Equals, mysql.TypeTiny) - c.Assert(t.Meta().Columns[0].Offset, Equals, 0) - c.Assert(t.Meta().Columns[1].Name.O, Equals, "_col$_c1") - c.Assert(t.Meta().Columns[1].Tp, Equals, mysql.TypeTiny) - c.Assert(t.Meta().Columns[1].Offset, Equals, 1) - c.Assert(t.Meta().Columns[2].Name.O, Equals, "_col$__col$_c1_0") - c.Assert(t.Meta().Columns[2].Tp, Equals, mysql.TypeTiny) - c.Assert(t.Meta().Columns[2].Offset, Equals, 2) - c.Assert(t.Meta().Columns[3].Name.O, Equals, "_col$__col$__col$_c1_0_0") - c.Assert(t.Meta().Columns[3].Tp, Equals, mysql.TypeTiny) - c.Assert(t.Meta().Columns[3].Offset, Equals, 3) - - tk.MustExec("drop table if exists t") -} - -func (s *testSerialDBSuite) TestModifyColumnTypeWithWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - // Test normal warnings. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a decimal(5,2))") - tk.MustExec("insert into t values(111.22),(111.22),(111.22),(111.22),(333.4)") - // 111.22 will be truncated the fraction .22 as .2 with truncated warning for each row. - tk.MustExec("alter table t modify column a decimal(4,1)") - // there should 4 rows of warnings corresponding to the origin rows. - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect DECIMAL value: '111.22'", - "Warning 1292 Truncated incorrect DECIMAL value: '111.22'", - "Warning 1292 Truncated incorrect DECIMAL value: '111.22'", - "Warning 1292 Truncated incorrect DECIMAL value: '111.22'")) - - // Test the strict warnings is treated as errors under the strict mode. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a decimal(5,2))") - tk.MustExec("insert into t values(111.22),(111.22),(111.22),(33.4)") - // Since modify column a from decimal(5,2) to decimal(3,1), the first three rows with 111.22 will overflows the target types. - _, err := tk.Exec("alter table t modify column a decimal(3,1)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[types:1690]DECIMAL value is out of range in '(3, 1)'") - - // Test the strict warnings is treated as warnings under the non-strict mode. - tk.MustExec("set @@sql_mode=\"\"") - tk.MustExec("alter table t modify column a decimal(3,1)") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1690 DECIMAL value is out of range in '(3, 1)'", - "Warning 1690 DECIMAL value is out of range in '(3, 1)'", - "Warning 1690 DECIMAL value is out of range in '(3, 1)'")) -} - -// TestModifyColumnTypeWhenInterception is to test modifying column type with warnings intercepted by -// reorg timeout, not owner error and so on. -func (s *testSerialDBSuite) TestModifyColumnTypeWhenInterception(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - // Test normal warnings. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int primary key, b decimal(4,2))") - - count := defaultBatchSize * 4 - // Add some rows. - dml := "insert into t values" - for i := 1; i <= count; i++ { - dml += fmt.Sprintf("(%d, %f)", i, 11.22) - if i != count { - dml += "," - } - } - tk.MustExec(dml) - // Make the regions scale like: [1, 1024), [1024, 2048), [2048, 3072), [3072, 4096] - tk.MustQuery("split table t between(0) and (4096) regions 4") - - d := s.dom.DDL() - hook := &ddl.TestDDLCallback{} - var checkMiddleWarningCount bool - var checkMiddleAddedCount bool - // Since the `DefTiDBDDLReorgWorkerCount` is 4, every worker will be assigned with one region - // for the first time. Here we mock the insert failure/reorg timeout in region [2048, 3072) - // which will lead next handle be set to 2048 and partial warnings be stored into ddl job. - // Since the existence of reorg batch size, only the last reorg batch [2816, 3072) of kv - // range [2048, 3072) fail to commit, the rest of them all committed successfully. So the - // addedCount and warnings count in the job are all equal to `4096 - reorg batch size`. - // In the next round of this ddl job, the last reorg batch will be finished. - var middleWarningsCount = int64(defaultBatchSize*4 - defaultReorgBatchSize) - hook.OnJobUpdatedExported = func(job *model.Job) { - if job.SchemaState == model.StateWriteReorganization || job.SnapshotVer != 0 { - if len(job.ReorgMeta.WarningsCount) == len(job.ReorgMeta.Warnings) { - for _, v := range job.ReorgMeta.WarningsCount { - if v == middleWarningsCount { - checkMiddleWarningCount = true - } - } - } - if job.RowCount == middleWarningsCount { - checkMiddleAddedCount = true - } - } - } - originHook := d.GetHook() - d.(ddl.DDLForTest).SetHook(hook) - defer d.(ddl.DDLForTest).SetHook(originHook) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/MockReorgTimeoutInOneRegion", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/MockReorgTimeoutInOneRegion"), IsNil) - }() - tk.MustExec("alter table t modify column b decimal(3,1)") - c.Assert(checkMiddleWarningCount, Equals, true) - c.Assert(checkMiddleAddedCount, Equals, true) - res := tk.MustQuery("show warnings") - c.Assert(len(res.Rows()), Equals, count) -} - -func (s *testDBSuite4) TestGeneratedColumnWindowFunction(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("DROP TABLE IF EXISTS t") - tk.MustGetErrCode("CREATE TABLE t (a INT , b INT as (ROW_NUMBER() OVER (ORDER BY a)))", errno.ErrWindowInvalidWindowFuncUse) - tk.MustGetErrCode("CREATE TABLE t (a INT , index idx ((ROW_NUMBER() OVER (ORDER BY a))))", errno.ErrWindowInvalidWindowFuncUse) -} - -func (s *testDBSuite4) TestAnonymousIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("DROP TABLE IF EXISTS t") - tk.MustExec("create table t(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb int, b int);") - tk.MustExec("alter table t add index bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(b);") - tk.MustExec("alter table t add index (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);") - res := tk.MustQuery("show index from t where key_name='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';") - c.Assert(len(res.Rows()), Equals, 1) - res = tk.MustQuery("show index from t where key_name='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_2';") - c.Assert(len(res.Rows()), Equals, 1) -} - -func (s *testDBSuite4) TestUnsupportedAlterTableOption(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test_db") - tk.MustExec("DROP TABLE IF EXISTS t") - tk.MustExec("create table t(a char(10) not null,b char(20)) shard_row_id_bits=6;") - tk.MustGetErrCode("alter table t pre_split_regions=6;", errno.ErrUnsupportedDDLOperation) -} - -func (s *testDBSuite4) TestCreateTableWithDecimalWithDoubleZero(c *C) { - tk := testkit.NewTestKit(c, s.store) - - checkType := func(db, table, field string) { - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tableInfo, err := is.TableByName(model.NewCIStr(db), model.NewCIStr(table)) - c.Assert(err, IsNil) - tblInfo := tableInfo.Meta() - for _, col := range tblInfo.Columns { - if col.Name.L == field { - c.Assert(col.Flen, Equals, 10) - } - } - } - - tk.MustExec("use test") - tk.MustExec("drop table if exists tt") - tk.MustExec("create table tt(d decimal(0, 0))") - checkType("test", "tt", "d") - - tk.MustExec("drop table tt") - tk.MustExec("create table tt(a int)") - tk.MustExec("alter table tt add column d decimal(0, 0)") - checkType("test", "tt", "d") - - /* - Currently not support change column to decimal - tk.MustExec("drop table tt") - tk.MustExec("create table tt(d int)") - tk.MustExec("alter table tt change column d d decimal(0, 0)") - checkType("test", "tt", "d") - */ -} - -func (s *testDBSuite4) TestIssue22207(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("set @@session.tidb_enable_list_partition = ON") - tk.MustExec("set @@session.tidb_enable_exchange_partition = 1;") - tk.MustExec("drop table if exists t1;") - tk.MustExec("drop table if exists t2;") - tk.MustExec("create table t1(id char(10)) partition by list columns(id) (partition p0 values in ('a'), partition p1 values in ('b'));") - tk.MustExec("insert into t1 VALUES('a')") - tk.MustExec("create table t2(id char(10));") - tk.MustExec("ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;") - tk.MustQuery("select * from t2").Check(testkit.Rows("a")) - c.Assert(len(tk.MustQuery("select * from t1").Rows()), Equals, 0) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("drop table if exists t2;") - tk.MustExec("create table t1 (id int) partition by list (id) (partition p0 values in (1,2,3), partition p1 values in (4,5,6));") - tk.MustExec("insert into t1 VALUES(1);") - tk.MustExec("insert into t1 VALUES(2);") - tk.MustExec("insert into t1 VALUES(3);") - tk.MustExec("create table t2(id int);") - tk.MustExec("ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;") - tk.MustQuery("select * from t2").Check(testkit.Rows("1", "2", "3")) - c.Assert(len(tk.MustQuery("select * from t1").Rows()), Equals, 0) - tk.MustExec("set @@session.tidb_enable_exchange_partition = 0;") -} - -func (s *testDBSuite5) TestIssue23473(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t_23473;") - tk.MustExec("create table t_23473 (k int primary key, v int)") - tk.MustExec("alter table t_23473 change column k k bigint") - t := testGetTableByName(c, tk.Se.(sessionctx.Context), "test", "t_23473") - col1Flag := t.Cols()[0].Flag - c.Assert(mysql.HasNoDefaultValueFlag(col1Flag), IsTrue) -} - -func (s *testSerialDBSuite) TestIssue22819(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test;") - tk1.MustExec("drop table if exists t1;") - defer func() { - tk1.MustExec("drop table if exists t1;") - }() - - tk1.MustExec("create table t1 (v int) partition by hash (v) partitions 2") - tk1.MustExec("insert into t1 values (1)") - - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test;") - tk1.MustExec("begin") - tk1.MustExec("update t1 set v = 2 where v = 1") - - tk2.MustExec("alter table t1 truncate partition p0") - - _, err := tk1.Exec("commit") - c.Assert(err, ErrorMatches, ".*8028.*Information schema is changed during the execution of the statement.*") -} - -func (s *testSerialSuite) TestTruncateAllPartitions(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test;") - tk1.MustExec("drop table if exists partition_table;") - defer func() { - tk1.MustExec("drop table if exists partition_table;") - }() - tk1.MustExec("create table partition_table (v int) partition by hash (v) partitions 10;") - tk1.MustExec("insert into partition_table values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);") - tk1.MustExec("alter table partition_table truncate partition all;") - tk1.MustQuery("select count(*) from partition_table;").Check(testkit.Rows("0")) -} - -func (s *testSerialSuite) TestIssue23872(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists test_create_table;") - defer tk.MustExec("drop table if exists test_create_table;") - tk.MustExec("create table test_create_table(id smallint,id1 int, primary key (id));") - rs, err := tk.Exec("select * from test_create_table;") - c.Assert(err, IsNil) - cols := rs.Fields() - err = rs.Close() - c.Assert(err, IsNil) - expectFlag := uint16(mysql.NotNullFlag | mysql.PriKeyFlag | mysql.NoDefaultValueFlag) - c.Assert(cols[0].Column.Flag, Equals, uint(expectFlag)) - tk.MustExec("create table t(a int default 1, primary key(a));") - defer tk.MustExec("drop table if exists t;") - rs1, err := tk.Exec("select * from t;") - c.Assert(err, IsNil) - cols1 := rs1.Fields() - err = rs1.Close() - c.Assert(err, IsNil) - expectFlag1 := uint16(mysql.NotNullFlag | mysql.PriKeyFlag) - c.Assert(cols1[0].Column.Flag, Equals, uint(expectFlag1)) -} - -// Close issue #23321. -// See https://github.com/pingcap/tidb/issues/23321 -func (s *testSerialDBSuite) TestJsonUnmarshalErrWhenPanicInCancellingPath(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - tk.MustExec("drop table if exists test_add_index_after_add_col") - tk.MustExec("create table test_add_index_after_add_col(a int, b int not null default '0');") - tk.MustExec("insert into test_add_index_after_add_col values(1, 2),(2,2);") - tk.MustExec("alter table test_add_index_after_add_col add column c int not null default '0';") +// Close issue #24172. +// See https://github.com/pingcap/tidb/issues/24172 +func TestCancelJobWriteConflict(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease) + defer clean() - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit", `return(true)`), IsNil) - defer c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit"), IsNil) + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) - _, err := tk.Exec("alter table test_add_index_after_add_col add unique index cc(c);") - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '0' for key 'cc'") -} + tk1.MustExec("use test") -// Close issue #24172. -// See https://github.com/pingcap/tidb/issues/24172 -func (s *testSerialDBSuite) TestCancelJobWriteConflict(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk1 := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id int)") + tk1.MustExec("create table t(id int)") var cancelErr error var rs []sqlexec.RecordSet hook := &ddl.TestDDLCallback{} - d := s.dom.DDL() + d := dom.DDL() originalHook := d.GetHook() - d.(ddl.DDLForTest).SetHook(hook) - defer d.(ddl.DDLForTest).SetHook(originalHook) + d.SetHook(hook) + defer d.SetHook(originalHook) // Test when cancelling cannot be retried and adding index succeeds. hook.OnJobRunBeforeExported = func(job *model.Job) { if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization { stmt := fmt.Sprintf("admin cancel ddl jobs %d", job.ID) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn", `return("no_retry")`), IsNil) - defer func() { c.Assert(failpoint.Disable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn"), IsNil) }() - rs, cancelErr = tk1.Se.Execute(context.Background(), stmt) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn", `return("no_retry")`)) + defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn")) }() + rs, cancelErr = tk2.Session().Execute(context.Background(), stmt) } } - tk.MustExec("alter table t add index (id)") - c.Assert(cancelErr.Error(), Equals, "mock commit error") + tk1.MustExec("alter table t add index (id)") + require.EqualError(t, cancelErr, "mock commit error") // Test when cancelling is retried only once and adding index is cancelled in the end. var jobID int64 @@ -7325,319 +1148,13 @@ func (s *testSerialDBSuite) TestCancelJobWriteConflict(c *C) { if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization { jobID = job.ID stmt := fmt.Sprintf("admin cancel ddl jobs %d", job.ID) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn", `return("retry_once")`), IsNil) - defer func() { c.Assert(failpoint.Disable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn"), IsNil) }() - rs, cancelErr = tk1.Se.Execute(context.Background(), stmt) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn", `return("retry_once")`)) + defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/kv/mockCommitErrorInNewTxn")) }() + rs, cancelErr = tk2.Session().Execute(context.Background(), stmt) } } - tk.MustGetErrCode("alter table t add index (id)", errno.ErrCancelledDDLJob) - c.Assert(cancelErr, IsNil) - result := tk1.ResultSetToResultWithCtx(context.Background(), rs[0], Commentf("cancel ddl job fails")) + tk1.MustGetErrCode("alter table t add index (id)", errno.ErrCancelledDDLJob) + require.NoError(t, cancelErr) + result := tk2.ResultSetToResultWithCtx(context.Background(), rs[0], "cancel ddl job fails") result.Check(testkit.Rows(fmt.Sprintf("%d successful", jobID))) } - -// For Close issue #24288 -// see https://github.com/pingcap/tidb/issues/24288 -func (s *testDBSuite8) TestDdlMaxLimitOfIdentifier(c *C) { - tk := testkit.NewTestKit(c, s.store) - - // create/drop database test - longDbName := strings.Repeat("库", mysql.MaxDatabaseNameLength-1) - tk.MustExec(fmt.Sprintf("create database %s", longDbName)) - defer func() { - tk.MustExec(fmt.Sprintf("drop database %s", longDbName)) - }() - tk.MustExec(fmt.Sprintf("use %s", longDbName)) - - // create/drop table,index test - longTblName := strings.Repeat("表", mysql.MaxTableNameLength-1) - longColName := strings.Repeat("三", mysql.MaxColumnNameLength-1) - longIdxName := strings.Repeat("ç´¢", mysql.MaxIndexIdentifierLen-1) - tk.MustExec(fmt.Sprintf("create table %s(f1 int primary key,f2 int, %s varchar(50))", longTblName, longColName)) - tk.MustExec(fmt.Sprintf("create index %s on %s(%s)", longIdxName, longTblName, longColName)) - defer func() { - tk.MustExec(fmt.Sprintf("drop index %s on %s", longIdxName, longTblName)) - tk.MustExec(fmt.Sprintf("drop table %s", longTblName)) - }() - - // alter table - tk.MustExec(fmt.Sprintf("alter table %s change f2 %s int", longTblName, strings.Repeat("二", mysql.MaxColumnNameLength-1))) - -} - -func testDropIndexes(c *C, store kv.Storage, lease time.Duration, createSQL, dropIdxSQL string, idxNames []string) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists test_drop_indexes") - tk.MustExec(createSQL) - done := make(chan error, 1) - - num := 100 - // add some rows - for i := 0; i < num; i++ { - tk.MustExec("insert into test_drop_indexes values (?, ?, ?)", i, i, i) - } - ctx := tk.Se.(sessionctx.Context) - idxIDs := make([]int64, 0, 3) - for _, idxName := range idxNames { - idxIDs = append(idxIDs, testGetIndexID(c, ctx, "test_db", "test_drop_indexes", idxName)) - } - jobIDExt, resetHook := setupJobIDExtCallback(ctx) - defer resetHook() - testddlutil.SessionExecInGoroutine(store, dropIdxSQL, done) - - ticker := time.NewTicker(lease / 2) - defer ticker.Stop() -LOOP: - for { - select { - case err := <-done: - if err == nil { - break LOOP - } - c.Assert(err, IsNil, Commentf("err:%v", errors.ErrorStack(err))) - case <-ticker.C: - step := 5 - // delete some rows, and add some data - for i := num; i < num+step; i++ { - n := rand.Intn(num) - tk.MustExec("update test_drop_indexes set c2 = 1 where c1 = ?", n) - tk.MustExec("insert into test_drop_indexes values (?, ?, ?)", i, i, i) - } - num += step - } - } - for _, idxID := range idxIDs { - checkDelRangeAdded(tk, jobIDExt.jobID, idxID) - } -} - -func testCancelDropIndexes(c *C, store kv.Storage, d ddl.DDL) { - indexesName := []string{"idx_c1", "idx_c2"} - addIdxesSQL := "alter table t add index idx_c1 (c1);alter table t add index idx_c2 (c2);" - dropIdxesSQL := "alter table t drop index idx_c1;alter table t drop index idx_c2;" - - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test_db") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(c1 int, c2 int)") - defer tk.MustExec("drop table t;") - for i := 0; i < 5; i++ { - tk.MustExec("insert into t values (?, ?)", i, i) - } - testCases := []struct { - needAddIndex bool - jobState model.JobState - JobSchemaState model.SchemaState - cancelSucc bool - }{ - // model.JobStateNone means the jobs is canceled before the first run. - // if we cancel successfully, we need to set needAddIndex to false in the next test case. Otherwise, set needAddIndex to true. - {true, model.JobStateNone, model.StateNone, true}, - {false, model.JobStateRunning, model.StateWriteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteOnly, false}, - {true, model.JobStateRunning, model.StateDeleteReorganization, false}, - } - var checkErr error - hook := &ddl.TestDDLCallback{} - var jobID int64 - testCase := &testCases[0] - hook.OnJobRunBeforeExported = func(job *model.Job) { - if (job.Type == model.ActionDropIndex || job.Type == model.ActionDropPrimaryKey) && - job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { - jobID = job.ID - jobIDs := []int64{job.ID} - hookCtx := mock.NewContext() - hookCtx.Store = store - err := hookCtx.NewTxn(context.TODO()) - if err != nil { - checkErr = errors.Trace(err) - return - } - txn, err := hookCtx.Txn(true) - if err != nil { - checkErr = errors.Trace(err) - return - } - - errs, err := admin.CancelJobs(txn, jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return - } - if errs[0] != nil { - checkErr = errors.Trace(errs[0]) - return - } - checkErr = txn.Commit(context.Background()) - } - } - originalHook := d.GetHook() - d.(ddl.DDLForTest).SetHook(hook) - ctx := tk.Se.(sessionctx.Context) - for i := range testCases { - testCase = &testCases[i] - if testCase.needAddIndex { - tk.MustExec(addIdxesSQL) - } - rs, err := tk.Exec(dropIdxesSQL) - if rs != nil { - rs.Close() - } - t := testGetTableByName(c, ctx, "test_db", "t") - - var indexInfos []*model.IndexInfo - for _, idxName := range indexesName { - indexInfo := t.Meta().FindIndexByName(idxName) - if indexInfo != nil { - indexInfos = append(indexInfos, indexInfo) - } - } - - if testCase.cancelSucc { - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8214]Cancelled DDL job") - c.Assert(indexInfos, NotNil) - c.Assert(indexInfos[0].State, Equals, model.StatePublic) - } else { - err1 := admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID) - c.Assert(err, IsNil) - c.Assert(checkErr, NotNil) - c.Assert(checkErr.Error(), Equals, err1.Error()) - c.Assert(indexInfos, IsNil) - } - } - d.(ddl.DDLForTest).SetHook(originalHook) - tk.MustExec(addIdxesSQL) - tk.MustExec(dropIdxesSQL) -} - -func testDropIndexesIfExists(c *C, store kv.Storage) { - tk := testkit.NewTestKitWithInit(c, store) - tk.MustExec("use test_db;") - tk.MustExec("drop table if exists test_drop_indexes_if_exists;") - tk.MustExec("create table test_drop_indexes_if_exists (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));") - - // Drop different indexes. - tk.MustGetErrMsg( - "alter table test_drop_indexes_if_exists drop index i1, drop index i3;", - "[ddl:1091]index i3 doesn't exist", - ) - if _, err := tk.Exec("alter table test_drop_indexes_if_exists drop index i1, drop index if exists i3;"); true { - c.Assert(err, IsNil) - } - tk.MustQuery("show warnings;").Check( - testutil.RowsWithSep("|", "Warning|1091|index i3 doesn't exist"), - ) - - // Verify the impact of deletion order when dropping duplicate indexes. - tk.MustGetErrMsg( - "alter table test_drop_indexes_if_exists drop index i2, drop index i2;", - "[ddl:1091]index i2 doesn't exist", - ) - tk.MustGetErrMsg( - "alter table test_drop_indexes_if_exists drop index if exists i2, drop index i2;", - "[ddl:1091]index i2 doesn't exist", - ) - if _, err := tk.Exec("alter table test_drop_indexes_if_exists drop index i2, drop index if exists i2;"); true { - c.Assert(err, IsNil) - } - tk.MustQuery("show warnings;").Check( - testutil.RowsWithSep("|", "Warning|1091|index i2 doesn't exist"), - ) -} - -func testDropIndexesFromPartitionedTable(c *C, store kv.Storage) { - tk := testkit.NewTestKitWithInit(c, store) - tk.MustExec("use test_db;") - tk.MustExec("drop table if exists test_drop_indexes_from_partitioned_table;") - tk.MustExec(` - create table test_drop_indexes_from_partitioned_table (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2)) - partition by range(id) (partition p0 values less than (6), partition p1 values less than maxvalue); - `) - for i := 0; i < 20; i++ { - tk.MustExec("insert into test_drop_indexes_from_partitioned_table values (?, ?, ?)", i, i, i) - } - if _, err := tk.Exec("alter table test_drop_indexes_from_partitioned_table drop index i1, drop index if exists i2;"); true { - c.Assert(err, IsNil) - } -} - -func (s *testDBSuite5) TestDropIndexes(c *C) { - // drop multiple indexes - createSQL := "create table test_drop_indexes (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));" - dropIdxSQL := "alter table test_drop_indexes drop index i1, drop index i2;" - idxNames := []string{"i1", "i2"} - testDropIndexes(c, s.store, s.lease, createSQL, dropIdxSQL, idxNames) - - createSQL = "create table test_drop_indexes (id int, c1 int, c2 int, primary key(id) nonclustered, unique key i1(c1), key i2(c2));" - dropIdxSQL = "alter table test_drop_indexes drop primary key, drop index i1;" - idxNames = []string{"primary", "i1"} - testDropIndexes(c, s.store, s.lease, createSQL, dropIdxSQL, idxNames) - - createSQL = "create table test_drop_indexes (uuid varchar(32), c1 int, c2 int, primary key(uuid), unique key i1(c1), key i2(c2));" - dropIdxSQL = "alter table test_drop_indexes drop primary key, drop index i1, drop index i2;" - idxNames = []string{"primary", "i1", "i2"} - testDropIndexes(c, s.store, s.lease, createSQL, dropIdxSQL, idxNames) - - testDropIndexesIfExists(c, s.store) - testDropIndexesFromPartitionedTable(c, s.store) - testCancelDropIndexes(c, s.store, s.dom.DDL()) -} - -// Close issue #24580. -// See https://github.com/pingcap/tidb/issues/24580 -func (s *testDBSuite8) TestIssue24580(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a char(250) default null);") - tk.MustExec("insert into t values();") - - _, err := tk.Exec("alter table t modify a char not null;") - c.Assert(err.Error(), Equals, "[ddl:1265]Data truncated for column 'a' at row 1") - tk.MustExec("drop table if exists t") -} - -// Close issue #27862 https://github.com/pingcap/tidb/issues/27862 -// Ref: https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html#data-types-storage-reqs-strings -// text(100) in utf8mb4 charset needs max 400 byte length, thus tinytext is not enough. -func (s *testDBSuite8) TestCreateTextAdjustLen(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a text(100));") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", ""+ - "t CREATE TABLE `t` (\n"+ - " `a` text DEFAULT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("alter table t add b text(100);") - tk.MustExec("alter table t add c text;") - tk.MustExec("alter table t add d text(50);") - tk.MustExec("alter table t change column a a text(50);") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", ""+ - "t CREATE TABLE `t` (\n"+ - " `a` tinytext DEFAULT NULL,\n"+ - " `b` text DEFAULT NULL,\n"+ - " `c` text DEFAULT NULL,\n"+ - " `d` tinytext DEFAULT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Ref: https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html - // TINYBLOB, TINYTEXT L + 1 bytes, where L < 2^8 - // BLOB, TEXT L + 2 bytes, where L < 2^16 - // MEDIUMBLOB, MEDIUMTEXT L + 3 bytes, where L < 2^24 - // LONGBLOB, LONGTEXT L + 4 bytes, where L < 2^32 - tk.MustExec("alter table t change column d d text(100);") - tk.MustExec("alter table t change column c c text(30000);") - tk.MustExec("alter table t change column b b text(10000000);") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", ""+ - "t CREATE TABLE `t` (\n"+ - " `a` tinytext DEFAULT NULL,\n"+ - " `b` longtext DEFAULT NULL,\n"+ - " `c` mediumtext DEFAULT NULL,\n"+ - " `d` text DEFAULT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("drop table if exists t") -} diff --git a/ddl/ddl.go b/ddl/ddl.go index 2277e35ac4b0b..202ee05a25773 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -29,7 +29,6 @@ import ( "github.com/ngaut/pools" "github.com/pingcap/errors" "github.com/pingcap/failpoint" - pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/infoschema" @@ -45,11 +44,13 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/table" + pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" goutil "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/admin" + tidbutil "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/gcutil" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" + atomicutil "go.uber.org/atomic" "go.uber.org/zap" ) @@ -94,8 +95,8 @@ var ( // DDL is responsible for updating schema in data store and maintaining in-memory InfoSchema cache. type DDL interface { - CreateSchema(ctx sessionctx.Context, schema model.CIStr, charsetInfo *ast.CharsetOpt, directPlacementOpts *model.PlacementSettings, placementPolicyRef *model.PolicyRefInfo) error - AlterSchema(ctx sessionctx.Context, stmt *ast.AlterDatabaseStmt) error + CreateSchema(ctx sessionctx.Context, schema model.CIStr, charsetInfo *ast.CharsetOpt, placementPolicyRef *model.PolicyRefInfo) error + AlterSchema(sctx sessionctx.Context, stmt *ast.AlterDatabaseStmt) error DropSchema(ctx sessionctx.Context, schema model.CIStr) error CreateTable(ctx sessionctx.Context, stmt *ast.CreateTableStmt) error CreateView(ctx sessionctx.Context, stmt *ast.CreateViewStmt) error @@ -123,32 +124,34 @@ type DDL interface { // CreateSchemaWithInfo creates a database (schema) given its database info. // - // If `tryRetainID` is true, this method will try to keep the database ID specified in - // the `info` rather than generating new ones. This is just a hint though, if the ID collides - // with an existing database a new ID will always be used. - // // WARNING: the DDL owns the `info` after calling this function, and will modify its fields // in-place. If you want to keep using `info`, please call Clone() first. CreateSchemaWithInfo( ctx sessionctx.Context, info *model.DBInfo, - onExist OnExist, - tryRetainID bool) error + onExist OnExist) error // CreateTableWithInfo creates a table, view or sequence given its table info. // - // If `tryRetainID` is true, this method will try to keep the table ID specified in the `info` - // rather than generating new ones. This is just a hint though, if the ID collides with an - // existing table a new ID will always be used. - // // WARNING: the DDL owns the `info` after calling this function, and will modify its fields // in-place. If you want to keep using `info`, please call Clone() first. CreateTableWithInfo( ctx sessionctx.Context, schema model.CIStr, info *model.TableInfo, - onExist OnExist, - tryRetainID bool) error + onExist OnExist) error + + // BatchCreateTableWithInfo is like CreateTableWithInfo, but can handle multiple tables. + BatchCreateTableWithInfo(ctx sessionctx.Context, + schema model.CIStr, + info []*model.TableInfo, + onExist OnExist) error + + // CreatePlacementPolicyWithInfo creates a placement policy + // + // WARNING: the DDL owns the `policy` after calling this function, and will modify its fields + // in-place. If you want to keep using `policy`, please call Clone() first. + CreatePlacementPolicyWithInfo(ctx sessionctx.Context, policy *model.PolicyInfo, onExist OnExist) error // Start campaigns the owner and starts workers. // ctxPool is used for the worker's delRangeManager and creates sessions. @@ -170,13 +173,15 @@ type DDL interface { // GetID gets the ddl ID. GetID() string // GetTableMaxHandle gets the max row ID of a normal table or a partition. - GetTableMaxHandle(startTS uint64, tbl table.PhysicalTable) (kv.Handle, bool, error) + GetTableMaxHandle(ctx *JobContext, startTS uint64, tbl table.PhysicalTable) (kv.Handle, bool, error) // SetBinlogClient sets the binlog client for DDL worker. It's exported for testing. SetBinlogClient(*pumpcli.PumpsClient) // GetHook gets the hook. It's exported for testing. GetHook() Callback // SetHook sets the hook. SetHook(h Callback) + // DoDDLJob does the DDL job, it's exported for test. + DoDDLJob(ctx sessionctx.Context, job *model.Job) error } type limitJobTask struct { @@ -189,13 +194,14 @@ type ddl struct { m sync.RWMutex ctx context.Context cancel context.CancelFunc - wg sync.WaitGroup // It's only used to deal with data race in restart_test. + wg tidbutil.WaitGroupWrapper // It's only used to deal with data race in restart_test. limitJobCh chan *limitJobTask *ddlCtx - workers map[workerType]*worker - sessPool *sessionPool - delRangeMgr delRangeManager + workers map[workerType]*worker + sessPool *sessionPool + delRangeMgr delRangeManager + enableTiFlashPoll *atomicutil.Bool } // ddlCtx is the context when we use worker to handle DDL jobs. @@ -219,6 +225,11 @@ type ddlCtx struct { hook Callback interceptor Interceptor } + + ddlSeqNumMu struct { + sync.Mutex + seqNum uint64 + } } func (dc *ddlCtx) isOwner() bool { @@ -230,6 +241,25 @@ func (dc *ddlCtx) isOwner() bool { return isOwner } +// EnableTiFlashPoll enables TiFlash poll loop aka PollTiFlashReplicaStatus. +func EnableTiFlashPoll(d interface{}) { + if dd, ok := d.(*ddl); ok { + dd.enableTiFlashPoll.Store(true) + } +} + +// DisableTiFlashPoll disables TiFlash poll loop aka PollTiFlashReplicaStatus. +func DisableTiFlashPoll(d interface{}) { + if dd, ok := d.(*ddl); ok { + dd.enableTiFlashPoll.Store(false) + } +} + +// IsTiFlashPollEnabled reveals enableTiFlashPoll +func (d *ddl) IsTiFlashPollEnabled() bool { + return d.enableTiFlashPoll.Load() +} + // RegisterStatsHandle registers statistics handle and its corresponding even channel for ddl. func (d *ddl) RegisterStatsHandle(h *handle.Handle) { d.ddlCtx.statsHandle = h @@ -253,10 +283,10 @@ func asyncNotifyEvent(d *ddlCtx, e *util.Event) { case d.ddlEventCh <- e: return default: - logutil.BgLogger().Warn("[ddl] fail to notify DDL event", zap.String("event", e.String())) time.Sleep(time.Microsecond * 10) } } + logutil.BgLogger().Warn("[ddl] fail to notify DDL event", zap.String("event", e.String())) } } @@ -312,10 +342,11 @@ func newDDL(ctx context.Context, options ...Option) *ddl { ddlCtx.mu.hook = opt.Hook ddlCtx.mu.interceptor = &BaseInterceptor{} d := &ddl{ - ctx: ctx, - ddlCtx: ddlCtx, - limitJobCh: make(chan *limitJobTask, batchAddingJobs), + ddlCtx: ddlCtx, + limitJobCh: make(chan *limitJobTask, batchAddingJobs), + enableTiFlashPoll: atomicutil.NewBool(true), } + d.ctx, d.cancel = context.WithCancel(ctx) return d } @@ -346,11 +377,12 @@ func (d *ddl) newDeleteRangeManager(mock bool) delRangeManager { // Start implements DDL.Start interface. func (d *ddl) Start(ctxPool *pools.ResourcePool) error { logutil.BgLogger().Info("[ddl] start DDL", zap.String("ID", d.uuid), zap.Bool("runWorker", RunWorker)) - d.ctx, d.cancel = context.WithCancel(d.ctx) d.wg.Add(1) go d.limitDDLJobs() + d.sessPool = newSessionPool(ctxPool) + // If RunWorker is true, we need campaign owner and do DDL job. // Otherwise, we needn't do that. if RunWorker { @@ -360,10 +392,9 @@ func (d *ddl) Start(ctxPool *pools.ResourcePool) error { } d.workers = make(map[workerType]*worker, 2) - d.sessPool = newSessionPool(ctxPool) d.delRangeMgr = d.newDeleteRangeManager(ctxPool == nil) - d.workers[generalWorker] = newWorker(d.ctx, generalWorker, d.sessPool, d.delRangeMgr) - d.workers[addIdxWorker] = newWorker(d.ctx, addIdxWorker, d.sessPool, d.delRangeMgr) + d.workers[generalWorker] = newWorker(d.ctx, generalWorker, d.sessPool, d.delRangeMgr, d.ddlCtx) + d.workers[addIdxWorker] = newWorker(d.ctx, addIdxWorker, d.sessPool, d.delRangeMgr, d.ddlCtx) for _, worker := range d.workers { worker.wg.Add(1) w := worker @@ -376,6 +407,15 @@ func (d *ddl) Start(ctxPool *pools.ResourcePool) error { asyncNotify(worker.ddlJobCh) } + err = kv.RunInNewTxn(d.ctx, d.store, true, func(ctx context.Context, txn kv.Transaction) error { + t := meta.NewMeta(txn) + d.ddlSeqNumMu.seqNum, err = t.GetHistoryDDLCount() + return err + }) + if err != nil { + return err + } + go d.schemaSyncer.StartCleanWork() if config.TableLockEnabled() { d.wg.Add(1) @@ -387,6 +427,10 @@ func (d *ddl) Start(ctxPool *pools.ResourcePool) error { variable.RegisterStatistics(d) metrics.DDLCounter.WithLabelValues(metrics.CreateDDLInstance).Inc() + + // Start some background routine to manage TiFlash replica. + d.wg.Run(d.PollTiFlashRoutine) + return nil } @@ -453,6 +497,18 @@ func (d *ddl) genGlobalIDs(count int) ([]int64, error) { return ret, err } +func (d *ddl) genPlacementPolicyID() (int64, error) { + var ret int64 + err := kv.RunInNewTxn(context.Background(), d.store, true, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + var err error + ret, err = m.GenPlacementPolicyID() + return err + }) + + return ret, err +} + // SchemaSyncer implements DDL.SchemaSyncer interface. func (d *ddl) SchemaSyncer() util.SchemaSyncer { return d.schemaSyncer @@ -505,15 +561,37 @@ func getJobCheckInterval(job *model.Job, i int) (time.Duration, bool) { } } +// mayNeedReorg indicates that this job may need to reorganize the data. +func mayNeedReorg(job *model.Job) bool { + switch job.Type { + case model.ActionAddIndex, model.ActionAddPrimaryKey: + return true + case model.ActionModifyColumn: + if len(job.CtxVars) > 0 { + needReorg, ok := job.CtxVars[0].(bool) + return ok && needReorg + } + return false + case model.ActionMultiSchemaChange: + for _, sub := range job.MultiSchemaInfo.SubJobs { + proxyJob := cloneFromSubJob(job, sub) + if mayNeedReorg(proxyJob) { + return true + } + } + return false + default: + return false + } +} + func (d *ddl) asyncNotifyWorker(job *model.Job) { - // If the workers don't run, we needn't to notify workers. + // If the workers don't run, we needn't notify workers. if !RunWorker { return } - var worker *worker - jobTp := job.Type - if admin.MayNeedBackfill(jobTp) { + if mayNeedReorg(job) { worker = d.workers[addIdxWorker] } else { worker = d.workers[generalWorker] @@ -535,15 +613,49 @@ func updateTickerInterval(ticker *time.Ticker, lease time.Duration, job *model.J return time.NewTicker(chooseLeaseTime(lease, interval)) } -// doDDLJob will return +func recordLastDDLInfo(ctx sessionctx.Context, job *model.Job) { + if job == nil { + return + } + ctx.GetSessionVars().LastDDLInfo.Query = job.Query + ctx.GetSessionVars().LastDDLInfo.SeqNum = job.SeqNum +} + +func setDDLJobQuery(ctx sessionctx.Context, job *model.Job) { + switch job.Type { + case model.ActionUpdateTiFlashReplicaStatus, model.ActionUnlockTable: + job.Query = "" + default: + job.Query, _ = ctx.Value(sessionctx.QueryString).(string) + } +} + +// DoDDLJob will return // - nil: found in history DDL job and no job error // - context.Cancel: job has been sent to worker, but not found in history DDL job before cancel // - other: found in history DDL job and return that job error -func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { +func (d *ddl) DoDDLJob(ctx sessionctx.Context, job *model.Job) error { + if mci := ctx.GetSessionVars().StmtCtx.MultiSchemaInfo; mci != nil { + // In multiple schema change, we don't run the job. + // Instead, merge all the jobs into one pending job. + return appendToSubJobs(mci, job) + } // Get a global job ID and put the DDL job in the queue. - job.Query, _ = ctx.Value(sessionctx.QueryString).(string) + setDDLJobQuery(ctx, job) task := &limitJobTask{job, make(chan error)} d.limitJobCh <- task + + failpoint.Inject("mockParallelSameDDLJobTwice", func(val failpoint.Value) { + if val.(bool) { + // The same job will be put to the DDL queue twice. + task1 := &limitJobTask{job, make(chan error)} + d.limitJobCh <- task1 + <-task.err + // The second job result is used for test. + task = task1 + } + }) + // worker should restart to continue handling tasks in limitJobCh, and send back through task.err err := <-task.err if err != nil { @@ -570,6 +682,7 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { ticker.Stop() metrics.JobsGauge.WithLabelValues(job.Type.String()).Dec() metrics.HandleJobHistogram.WithLabelValues(job.Type.String(), metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds()) + recordLastDDLInfo(ctx, historyJob) }() i := 0 for { @@ -583,7 +696,7 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { i++ ticker = updateTickerInterval(ticker, 10*d.lease, job, i) case <-d.ctx.Done(): - logutil.BgLogger().Info("[ddl] doDDLJob will quit because context done") + logutil.BgLogger().Info("[ddl] DoDDLJob will quit because context done") return context.Canceled } @@ -597,6 +710,8 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { continue } + d.checkHistoryJobInTest(ctx, historyJob) + // If a job is a history job, the state must be JobStateSynced or JobStateRollbackDone or JobStateCancelled. if historyJob.IsSynced() { // Judge whether there are some warnings when executing DDL under the certain SQL mode. @@ -612,11 +727,7 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { } } - if historyJob.MultiSchemaInfo != nil && len(historyJob.MultiSchemaInfo.Warnings) != 0 { - for _, warning := range historyJob.MultiSchemaInfo.Warnings { - ctx.GetSessionVars().StmtCtx.AppendWarning(warning) - } - } + appendMultiChangeWarningsToOwnerCtx(ctx, historyJob) logutil.BgLogger().Info("[ddl] DDL job is finished", zap.Int64("jobID", jobID)) return nil @@ -626,16 +737,6 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { logutil.BgLogger().Info("[ddl] DDL job is failed", zap.Int64("jobID", jobID)) return errors.Trace(historyJob.Error) } - // Only for JobStateCancelled job which is adding columns or drop columns or drop indexes. - if historyJob.IsCancelled() && (historyJob.Type == model.ActionAddColumns || historyJob.Type == model.ActionDropColumns || historyJob.Type == model.ActionDropIndexes) { - if historyJob.MultiSchemaInfo != nil && len(historyJob.MultiSchemaInfo.Warnings) != 0 { - for _, warning := range historyJob.MultiSchemaInfo.Warnings { - ctx.GetSessionVars().StmtCtx.AppendWarning(warning) - } - } - logutil.BgLogger().Info("[ddl] DDL job is cancelled", zap.Int64("jobID", jobID)) - return nil - } panic("When the state is JobStateRollbackDone or JobStateCancelled, historyJob.Error should never be nil") } } diff --git a/ddl/ddl_algorithm.go b/ddl/ddl_algorithm.go index f0b4b3e0ae716..acc061c3c27b9 100644 --- a/ddl/ddl_algorithm.go +++ b/ddl/ddl_algorithm.go @@ -18,6 +18,7 @@ import ( "fmt" "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/util/dbterror" ) // AlterAlgorithm is used to store supported alter algorithm. @@ -60,7 +61,7 @@ func getProperAlgorithm(specify ast.AlgorithmType, algorithm *AlterAlgorithm) (a var err error if specify != r { - err = ErrAlterOperationNotSupported.GenWithStackByArgs(fmt.Sprintf("ALGORITHM=%s", specify), fmt.Sprintf("Cannot alter table by %s", specify), fmt.Sprintf("ALGORITHM=%s", algorithm.defAlgorithm)) + err = dbterror.ErrAlterOperationNotSupported.GenWithStackByArgs(fmt.Sprintf("ALGORITHM=%s", specify), fmt.Sprintf("Cannot alter table by %s", specify), fmt.Sprintf("ALGORITHM=%s", algorithm.defAlgorithm)) } return r, err } diff --git a/ddl/ddl_algorithm_serial_test.go b/ddl/ddl_algorithm_test.go similarity index 96% rename from ddl/ddl_algorithm_serial_test.go rename to ddl/ddl_algorithm_test.go index be9c87af3a163..339582651de0e 100644 --- a/ddl/ddl_algorithm_serial_test.go +++ b/ddl/ddl_algorithm_test.go @@ -19,6 +19,7 @@ import ( "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/util/dbterror" "github.com/stretchr/testify/require" ) @@ -99,7 +100,7 @@ Loop: for i, alm := range tc.supportedAlgorithm { algorithm, err = ddl.ResolveAlterAlgorithm(&tc.alterSpec, alm) if err != nil { - require.True(t, ddl.ErrAlterOperationNotSupported.Equal(err)) + require.True(t, dbterror.ErrAlterOperationNotSupported.Equal(err)) } require.Equal(t, tc.expectedAlgorithm[i], algorithm) } @@ -109,6 +110,6 @@ Loop: algorithm, err = ddl.ResolveAlterAlgorithm(&tc.alterSpec, alm) require.Equal(t, ast.AlgorithmTypeDefault, algorithm) require.Error(t, err) - require.True(t, ddl.ErrAlterOperationNotSupported.Equal(err)) + require.True(t, dbterror.ErrAlterOperationNotSupported.Equal(err)) } } diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 957ba6e68386d..b26a7540b236f 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/label" + ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" @@ -48,11 +49,13 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/domainutil" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mock" @@ -72,10 +75,14 @@ const ( longBlobMaxLength = 4294967295 // When setting the placement policy with "PLACEMENT POLICY `default`", // it means to remove placement policy from the specified object. - defaultPlacementPolicyName = "default" + defaultPlacementPolicyName = "default" + tiflashCheckPendingTablesWaitTime = 3000 * time.Millisecond + // Once tiflashCheckPendingTablesLimit is reached, we trigger a limiter detection. + tiflashCheckPendingTablesLimit = 100 + tiflashCheckPendingTablesRetry = 7 ) -func (d *ddl) CreateSchema(ctx sessionctx.Context, schema model.CIStr, charsetInfo *ast.CharsetOpt, directPlacementOpts *model.PlacementSettings, placementPolicyRef *model.PolicyRefInfo) (err error) { +func (d *ddl) CreateSchema(ctx sessionctx.Context, schema model.CIStr, charsetInfo *ast.CharsetOpt, placementPolicyRef *model.PolicyRefInfo) (err error) { dbInfo := &model.DBInfo{Name: schema} if charsetInfo != nil { chs, coll, err := ResolveCharsetCollation(ast.CharsetOpt{Chs: charsetInfo.Chs, Col: charsetInfo.Col}) @@ -88,19 +95,14 @@ func (d *ddl) CreateSchema(ctx sessionctx.Context, schema model.CIStr, charsetIn dbInfo.Charset, dbInfo.Collate = charset.GetDefaultCharsetAndCollate() } - dbInfo.PlacementPolicyRef, dbInfo.DirectPlacementOpts, err = checkAndNormalizePlacement(ctx, placementPolicyRef, directPlacementOpts, nil, nil) - if err != nil { - return errors.Trace(err) - } - - return d.CreateSchemaWithInfo(ctx, dbInfo, OnExistError, false /*tryRetainID*/) + dbInfo.PlacementPolicyRef = placementPolicyRef + return d.CreateSchemaWithInfo(ctx, dbInfo, OnExistError) } func (d *ddl) CreateSchemaWithInfo( ctx sessionctx.Context, dbInfo *model.DBInfo, onExist OnExist, - tryRetainID bool, ) error { is := d.GetInfoSchemaWithInterceptor(ctx) _, ok := is.SchemaByName(dbInfo.Name) @@ -124,6 +126,10 @@ func (d *ddl) CreateSchemaWithInfo( return errors.Trace(err) } + if err := handleDatabasePlacement(ctx, dbInfo); err != nil { + return errors.Trace(err) + } + // FIXME: support `tryRetainID`. genIDs, err := d.genGlobalIDs(1) if err != nil { @@ -139,7 +145,7 @@ func (d *ddl) CreateSchemaWithInfo( Args: []interface{}{dbInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -169,12 +175,12 @@ func (d *ddl) ModifySchemaCharsetAndCollate(ctx sessionctx.Context, stmt *ast.Al BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{toCharset, toCollate}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } -func (d *ddl) ModifySchemaDefaultPlacement(ctx sessionctx.Context, stmt *ast.AlterDatabaseStmt, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings) (err error) { +func (d *ddl) ModifySchemaDefaultPlacement(ctx sessionctx.Context, stmt *ast.AlterDatabaseStmt, placementPolicyRef *model.PolicyRefInfo) (err error) { dbName := model.NewCIStr(stmt.Name) is := d.GetInfoSchemaWithInterceptor(ctx) dbInfo, ok := is.SchemaByName(dbName) @@ -182,7 +188,11 @@ func (d *ddl) ModifySchemaDefaultPlacement(ctx sessionctx.Context, stmt *ast.Alt return infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbName.O) } - placementPolicyRef, directPlacementOpts, err = checkAndNormalizePlacement(ctx, placementPolicyRef, directPlacementOpts, dbInfo.PlacementPolicyRef, dbInfo.DirectPlacementOpts) + if checkIgnorePlacementDDL(ctx) { + return nil + } + + placementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, placementPolicyRef) if err != nil { return err } @@ -193,14 +203,187 @@ func (d *ddl) ModifySchemaDefaultPlacement(ctx sessionctx.Context, stmt *ast.Alt SchemaName: dbInfo.Name.L, Type: model.ActionModifySchemaDefaultPlacement, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{placementPolicyRef, directPlacementOpts}, + Args: []interface{}{placementPolicyRef}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } -func (d *ddl) AlterTablePlacement(ctx sessionctx.Context, ident ast.Ident, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings) (err error) { +// getPendingTiFlashTableCount counts unavailable TiFlash replica by iterating all tables in infoCache. +func (d *ddl) getPendingTiFlashTableCount(sctx sessionctx.Context, originVersion int64, pendingCount uint32) (int64, uint32) { + is := d.GetInfoSchemaWithInterceptor(sctx) + dbInfos := is.AllSchemas() + // If there are no schema change since last time(can be weird). + if is.SchemaMetaVersion() == originVersion { + return originVersion, pendingCount + } + cnt := uint32(0) + for _, dbInfo := range dbInfos { + if util.IsMemOrSysDB(dbInfo.Name.L) { + continue + } + for _, tbl := range dbInfo.Tables { + if tbl.TiFlashReplica != nil && !tbl.TiFlashReplica.Available { + cnt += 1 + } + } + } + return is.SchemaMetaVersion(), cnt +} + +func isSessionDone(sctx sessionctx.Context) (bool, uint32) { + done := false + killed := atomic.LoadUint32(&sctx.GetSessionVars().Killed) + if killed == 1 { + done = true + } + failpoint.Inject("BatchAddTiFlashSendDone", func(val failpoint.Value) { + done = val.(bool) + }) + return done, killed +} + +func (d *ddl) waitPendingTableThreshold(sctx sessionctx.Context, schemaID int64, tableID int64, originVersion int64, pendingCount uint32, threshold uint32) (bool, int64, uint32, bool) { + configRetry := tiflashCheckPendingTablesRetry + configWaitTime := tiflashCheckPendingTablesWaitTime + failpoint.Inject("FastFailCheckTiFlashPendingTables", func(value failpoint.Value) { + configRetry = value.(int) + configWaitTime = time.Millisecond * 200 + }) + + for retry := 0; retry < configRetry; retry += 1 { + done, killed := isSessionDone(sctx) + if done { + logutil.BgLogger().Info("abort batch add TiFlash replica", zap.Int64("schemaID", schemaID), zap.Uint32("isKilled", killed)) + return true, originVersion, pendingCount, false + } + originVersion, pendingCount = d.getPendingTiFlashTableCount(sctx, originVersion, pendingCount) + delay := time.Duration(0) + if pendingCount >= threshold { + logutil.BgLogger().Info("too many unavailable tables, wait", zap.Uint32("threshold", threshold), zap.Uint32("currentPendingCount", pendingCount), zap.Int64("schemaID", schemaID), zap.Int64("tableID", tableID), zap.Duration("time", configWaitTime)) + delay = configWaitTime + } else { + // If there are not many unavailable tables, we don't need a force check. + return false, originVersion, pendingCount, false + } + time.Sleep(delay) + } + logutil.BgLogger().Info("too many unavailable tables, timeout", zap.Int64("schemaID", schemaID), zap.Int64("tableID", tableID)) + // If timeout here, we will trigger a ddl job, to force sync schema. However, it doesn't mean we remove limiter, + // so there is a force check immediately after that. + return false, originVersion, pendingCount, true +} + +func (d *ddl) ModifySchemaSetTiFlashReplica(sctx sessionctx.Context, stmt *ast.AlterDatabaseStmt, tiflashReplica *ast.TiFlashReplicaSpec) error { + dbName := model.NewCIStr(stmt.Name) + is := d.GetInfoSchemaWithInterceptor(sctx) + dbInfo, ok := is.SchemaByName(dbName) + if !ok { + return infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbName.O) + } + if util.IsMemOrSysDB(dbInfo.Name.L) { + return errors.Trace(dbterror.ErrUnsupportedAlterReplicaForSysTable) + } + + total := len(dbInfo.Tables) + succ := 0 + skip := 0 + fail := 0 + oneFail := int64(0) + + if total == 0 { + return infoschema.ErrEmptyDatabase.GenWithStack("Empty database '%v'", dbName.O) + } + err := checkTiFlashReplicaCount(sctx, tiflashReplica.Count) + if err != nil { + return errors.Trace(err) + } + + var originVersion int64 = 0 + var pendingCount uint32 = 0 + forceCheck := false + + logutil.BgLogger().Info("start batch add TiFlash replicas", zap.Int("total", total), zap.Int64("schemaID", dbInfo.ID)) + threshold := uint32(sctx.GetSessionVars().BatchPendingTiFlashCount) + + for _, tbl := range dbInfo.Tables { + done, killed := isSessionDone(sctx) + if done { + logutil.BgLogger().Info("abort batch add TiFlash replica", zap.Int64("schemaID", dbInfo.ID), zap.Uint32("isKilled", killed)) + return nil + } + + tbReplicaInfo := tbl.TiFlashReplica + if !shouldModifyTiFlashReplica(tbReplicaInfo, tiflashReplica) { + logutil.BgLogger().Info("skip repeated processing table", zap.Int64("tableID", tbl.ID), zap.Int64("schemaID", dbInfo.ID), zap.String("tableName", tbl.Name.String()), zap.String("schemaName", dbInfo.Name.String())) + skip += 1 + continue + } + + // Ban setting replica count for tables in system database. + if tbl.TempTableType != model.TempTableNone { + logutil.BgLogger().Info("skip processing temporary table", zap.Int64("tableID", tbl.ID), zap.Int64("schemaID", dbInfo.ID), zap.String("tableName", tbl.Name.String()), zap.String("schemaName", dbInfo.Name.String())) + skip += 1 + continue + } + + charsetOk := true + // Ban setting replica count for tables which has charset not supported by TiFlash + for _, col := range tbl.Cols() { + _, ok := charset.TiFlashSupportedCharsets[col.Charset] + if !ok { + charsetOk = false + break + } + } + if !charsetOk { + logutil.BgLogger().Info("skip processing schema table, unsupported charset", zap.Int64("tableID", tbl.ID), zap.Int64("schemaID", dbInfo.ID), zap.String("tableName", tbl.Name.String()), zap.String("schemaName", dbInfo.Name.String())) + skip += 1 + continue + } + + // Alter `tiflashCheckPendingTablesLimit` tables are handled, we need to check if we have reached threshold. + if (succ+fail)%tiflashCheckPendingTablesLimit == 0 || forceCheck { + // We can execute one probing ddl to the latest schema, if we timeout in `pendingFunc`. + // However, we shall mark `forceCheck` to true, because we may still reach `threshold`. + finished := false + finished, originVersion, pendingCount, forceCheck = d.waitPendingTableThreshold(sctx, dbInfo.ID, tbl.ID, originVersion, pendingCount, threshold) + if finished { + logutil.BgLogger().Info("abort batch add TiFlash replica", zap.Int64("schemaID", dbInfo.ID)) + return nil + } + } + + job := &model.Job{ + SchemaID: dbInfo.ID, + SchemaName: dbInfo.Name.L, + TableID: tbl.ID, + Type: model.ActionSetTiFlashReplica, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{*tiflashReplica}, + } + err := d.DoDDLJob(sctx, job) + err = d.callHookOnChanged(err) + if err != nil { + oneFail = tbl.ID + fail += 1 + logutil.BgLogger().Info("processing schema table error", zap.Int64("tableID", tbl.ID), zap.Int64("schemaID", dbInfo.ID), zap.String("tableName", tbl.Name.String()), zap.String("schemaName", dbInfo.Name.String()), zap.Error(err)) + } else { + succ += 1 + } + } + failStmt := "" + if fail > 0 { + failStmt = fmt.Sprintf("(including table %v)", oneFail) + } + msg := fmt.Sprintf("In total %v tables: %v succeed, %v failed%v, %v skipped", total, succ, fail, failStmt, skip) + sctx.GetSessionVars().StmtCtx.SetMessage(msg) + logutil.BgLogger().Info("finish batch add TiFlash replica", zap.Int64("schemaID", dbInfo.ID)) + return nil +} + +func (d *ddl) AlterTablePlacement(ctx sessionctx.Context, ident ast.Ident, placementPolicyRef *model.PolicyRefInfo) (err error) { is := d.infoCache.GetLatest() schema, ok := is.SchemaByName(ident.Schema) if !ok { @@ -212,11 +395,15 @@ func (d *ddl) AlterTablePlacement(ctx sessionctx.Context, ident ast.Ident, place return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name)) } + if checkIgnorePlacementDDL(ctx) { + return nil + } + if tb.Meta().TempTableType != model.TempTableNone { - return errors.Trace(ErrOptOnTemporaryTable.GenWithStackByArgs("placement")) + return errors.Trace(dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("placement")) } - placementPolicyRef, directPlacementOpts, err = checkAndNormalizePlacement(ctx, placementPolicyRef, directPlacementOpts, tb.Meta().PlacementPolicyRef, tb.Meta().DirectPlacementOpts) + placementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, placementPolicyRef) if err != nil { return err } @@ -225,67 +412,73 @@ func (d *ddl) AlterTablePlacement(ctx sessionctx.Context, ident ast.Ident, place SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionAlterTablePlacement, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{placementPolicyRef, directPlacementOpts}, + Args: []interface{}{placementPolicyRef}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } -func checkAndNormalizePlacement(ctx sessionctx.Context, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings, fallbackPlacementPolicyRef *model.PolicyRefInfo, fallbackDirectPlacementOpts *model.PlacementSettings) (*model.PolicyRefInfo, *model.PlacementSettings, error) { - if !ctx.GetSessionVars().EnableAlterPlacement && (placementPolicyRef != nil || directPlacementOpts != nil) { - return nil, nil, ErrPlacementDisabled - } - if placementPolicyRef != nil && directPlacementOpts != nil { - return nil, nil, errors.Trace(ErrPlacementPolicyWithDirectOption.GenWithStackByArgs(placementPolicyRef.Name)) +func checkAndNormalizePlacementPolicy(ctx sessionctx.Context, placementPolicyRef *model.PolicyRefInfo) (*model.PolicyRefInfo, error) { + if placementPolicyRef == nil { + return nil, nil } - if placementPolicyRef != nil && placementPolicyRef.Name.L == defaultPlacementPolicyName { + if placementPolicyRef.Name.L == defaultPlacementPolicyName { // When policy name is 'default', it means to remove the placement settings - placementPolicyRef = nil + return nil, nil } - if placementPolicyRef != nil { - policy, ok := ctx.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(placementPolicyRef.Name) - if !ok { - if !ctx.GetSessionVars().EnablePlacementChecks { - ctx.GetSessionVars().StmtCtx.AppendWarning(infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs(placementPolicyRef.Name)) - return fallbackPlacementPolicyRef, fallbackDirectPlacementOpts, nil - } - return nil, nil, errors.Trace(infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs(placementPolicyRef.Name)) - } - placementPolicyRef.ID = policy.ID + policy, ok := ctx.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(placementPolicyRef.Name) + if !ok { + return nil, errors.Trace(infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs(placementPolicyRef.Name)) } - if directPlacementOpts != nil { - // check the direct placement option compatibility. - if err := checkPolicyValidation(directPlacementOpts); err != nil { - return nil, nil, errors.Trace(err) + placementPolicyRef.ID = policy.ID + return placementPolicyRef, nil +} + +func checkMultiSchemaSpecs(_sctx sessionctx.Context, specs []*ast.DatabaseOption) error { + hasSetTiFlashReplica := false + if len(specs) == 1 { + return nil + } + for _, spec := range specs { + if spec.Tp == ast.DatabaseSetTiFlashReplica { + if hasSetTiFlashReplica { + return dbterror.ErrRunMultiSchemaChanges + } + hasSetTiFlashReplica = true } } - - return placementPolicyRef, directPlacementOpts, nil + return nil } -func (d *ddl) AlterSchema(ctx sessionctx.Context, stmt *ast.AlterDatabaseStmt) (err error) { +func (d *ddl) AlterSchema(sctx sessionctx.Context, stmt *ast.AlterDatabaseStmt) (err error) { // Resolve target charset and collation from options. var ( - toCharset, toCollate string - isAlterCharsetAndCollate, isAlterPlacement bool - placementPolicyRef *model.PolicyRefInfo - directPlacementOpts *model.PlacementSettings + toCharset, toCollate string + isAlterCharsetAndCollate, isAlterPlacement, isTiFlashReplica bool + placementPolicyRef *model.PolicyRefInfo + tiflashReplica *ast.TiFlashReplicaSpec ) + err = checkMultiSchemaSpecs(sctx, stmt.Options) + if err != nil { + return err + } + for _, val := range stmt.Options { switch val.Tp { case ast.DatabaseOptionCharset: if toCharset == "" { toCharset = val.Value } else if toCharset != val.Value { - return ErrConflictingDeclarations.GenWithStackByArgs(toCharset, val.Value) + return dbterror.ErrConflictingDeclarations.GenWithStackByArgs(toCharset, val.Value) } isAlterCharsetAndCollate = true case ast.DatabaseOptionCollate: @@ -296,36 +489,34 @@ func (d *ddl) AlterSchema(ctx sessionctx.Context, stmt *ast.AlterDatabaseStmt) ( if toCharset == "" { toCharset = info.CharsetName } else if toCharset != info.CharsetName { - return ErrConflictingDeclarations.GenWithStackByArgs(toCharset, info.CharsetName) + return dbterror.ErrConflictingDeclarations.GenWithStackByArgs(toCharset, info.CharsetName) } toCollate = info.Name isAlterCharsetAndCollate = true - case ast.DatabaseOptionPlacementPrimaryRegion, ast.DatabaseOptionPlacementRegions, ast.DatabaseOptionPlacementFollowerCount, ast.DatabaseOptionPlacementVoterCount, ast.DatabaseOptionPlacementLearnerCount, ast.DatabaseOptionPlacementSchedule, ast.DatabaseOptionPlacementConstraints, ast.DatabaseOptionPlacementLeaderConstraints, ast.DatabaseOptionPlacementLearnerConstraints, ast.DatabaseOptionPlacementFollowerConstraints, ast.DatabaseOptionPlacementVoterConstraints: - if directPlacementOpts == nil { - directPlacementOpts = &model.PlacementSettings{} - } - err = SetDirectPlacementOpt(directPlacementOpts, ast.PlacementOptionType(val.Tp), val.Value, val.UintValue) - if err != nil { - return err - } - isAlterPlacement = true case ast.DatabaseOptionPlacementPolicy: placementPolicyRef = &model.PolicyRefInfo{Name: model.NewCIStr(val.Value)} isAlterPlacement = true + case ast.DatabaseSetTiFlashReplica: + tiflashReplica = val.TiFlashReplica + isTiFlashReplica = true } } if isAlterCharsetAndCollate { - if err = d.ModifySchemaCharsetAndCollate(ctx, stmt, toCharset, toCollate); err != nil { + if err = d.ModifySchemaCharsetAndCollate(sctx, stmt, toCharset, toCollate); err != nil { return err } } if isAlterPlacement { - if err = d.ModifySchemaDefaultPlacement(ctx, stmt, placementPolicyRef, directPlacementOpts); err != nil { + if err = d.ModifySchemaDefaultPlacement(sctx, stmt, placementPolicyRef); err != nil { + return err + } + } + if isTiFlashReplica { + if err = d.ModifySchemaSetTiFlashReplica(sctx, stmt, tiflashReplica); err != nil { return err } } - return nil } @@ -342,7 +533,7 @@ func (d *ddl) DropSchema(ctx sessionctx.Context, schema model.CIStr) (err error) BinlogInfo: &model.HistoryInfo{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) if err != nil { return errors.Trace(err) @@ -364,21 +555,21 @@ func (d *ddl) DropSchema(ctx sessionctx.Context, schema model.CIStr) (err error) func checkTooLongSchema(schema model.CIStr) error { if utf8.RuneCountInString(schema.L) > mysql.MaxDatabaseNameLength { - return ErrTooLongIdent.GenWithStackByArgs(schema) + return dbterror.ErrTooLongIdent.GenWithStackByArgs(schema) } return nil } func checkTooLongTable(table model.CIStr) error { if utf8.RuneCountInString(table.L) > mysql.MaxTableNameLength { - return ErrTooLongIdent.GenWithStackByArgs(table) + return dbterror.ErrTooLongIdent.GenWithStackByArgs(table) } return nil } func checkTooLongIndex(index model.CIStr) error { if utf8.RuneCountInString(index.L) > mysql.MaxIndexIdentifierLen { - return ErrTooLongIdent.GenWithStackByArgs(index) + return dbterror.ErrTooLongIdent.GenWithStackByArgs(index) } return nil } @@ -527,7 +718,7 @@ func typesNeedCharset(tp byte) bool { return false } -func setCharsetCollationFlenDecimal(tp *types.FieldType, colCharset, colCollate string) error { +func setCharsetCollationFlenDecimal(tp *types.FieldType, colName, colCharset, colCollate string, sessVars *variable.SessionVars) error { var err error if typesNeedCharset(tp.Tp) { tp.Charset = colCharset @@ -551,9 +742,11 @@ func setCharsetCollationFlenDecimal(tp *types.FieldType, colCharset, colCollate } } else { // Adjust the field type for blob/text types if the flen is set. - err = adjustBlobTypesFlen(tp, colCharset) + if err = adjustBlobTypesFlen(tp, colCharset); err != nil { + return err + } } - return err + return checkTooBigFieldLengthAndTryAutoConvert(tp, colName, sessVars) } // buildColumnAndConstraint builds table.Column and ast.Constraint from the parameters. @@ -568,7 +761,7 @@ func buildColumnAndConstraint( tblCollate string, ) (*table.Column, []*ast.Constraint, error) { if colName := colDef.Name.Name.L; colName == model.ExtraHandleName.L { - return nil, nil, ErrWrongColumnName.GenWithStackByArgs(colName) + return nil, nil, dbterror.ErrWrongColumnName.GenWithStackByArgs(colName) } // specifiedCollate refers to the last collate specified in colDef.Options. @@ -585,7 +778,7 @@ func buildColumnAndConstraint( return nil, nil, errors.Trace(err) } - if err := setCharsetCollationFlenDecimal(colDef.Tp, chs, coll); err != nil { + if err := setCharsetCollationFlenDecimal(colDef.Tp, colDef.Name.Name.O, chs, coll, ctx.GetSessionVars()); err != nil { return nil, nil, errors.Trace(err) } col, cts, err := columnDefToCol(ctx, offset, colDef, outPriKeyConstraint) @@ -615,16 +808,16 @@ func checkColumnDefaultValue(ctx sessionctx.Context, col *table.Column, value in value = `null` } sc := ctx.GetSessionVars().StmtCtx - sc.AppendWarning(errBlobCantHaveDefault.GenWithStackByArgs(col.Name.O)) + sc.AppendWarning(dbterror.ErrBlobCantHaveDefault.GenWithStackByArgs(col.Name.O)) return hasDefaultValue, value, nil } // In strict SQL mode or default value is not an empty string. - return hasDefaultValue, value, errBlobCantHaveDefault.GenWithStackByArgs(col.Name.O) + return hasDefaultValue, value, dbterror.ErrBlobCantHaveDefault.GenWithStackByArgs(col.Name.O) } if value != nil && ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() && ctx.GetSessionVars().SQLMode.HasStrictMode() && types.IsTypeTime(col.Tp) { if vv, ok := value.(string); ok { - timeValue, err := expression.GetTimeValue(ctx, vv, col.Tp, int8(col.Decimal)) + timeValue, err := expression.GetTimeValue(ctx, vv, col.Tp, col.Decimal) if err != nil { return hasDefaultValue, value, errors.Trace(err) } @@ -640,7 +833,7 @@ func checkSequenceDefaultValue(col *table.Column) error { if mysql.IsIntegerType(col.Tp) { return nil } - return ErrColumnTypeUnsupportedNextValue.GenWithStackByArgs(col.ColumnInfo.Name.O) + return dbterror.ErrColumnTypeUnsupportedNextValue.GenWithStackByArgs(col.ColumnInfo.Name.O) } func convertTimestampDefaultValToUTC(ctx sessionctx.Context, defaultVal interface{}, col *table.Column) (interface{}, error) { @@ -649,7 +842,7 @@ func convertTimestampDefaultValToUTC(ctx sessionctx.Context, defaultVal interfac } if vv, ok := defaultVal.(string); ok { if vv != types.ZeroDatetimeStr && !strings.EqualFold(vv, ast.CurrentTimestamp) { - t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.Tp, int8(col.Decimal)) + t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.Tp, col.Decimal) if err != nil { return defaultVal, errors.Trace(err) } @@ -803,10 +996,10 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o // TODO: Support other time functions. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { if !expression.IsValidCurrentTimestampExpr(v.Expr, colDef.Tp) { - return nil, nil, ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) + return nil, nil, dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { - return nil, nil, ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) + return nil, nil, dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } col.Flag |= mysql.OnUpdateNowFlag setOnUpdateNow = true @@ -830,9 +1023,9 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o col.FieldType.Collate = v.StrValue } case ast.ColumnOptionFulltext: - ctx.GetSessionVars().StmtCtx.AppendWarning(ErrTableCantHandleFt.GenWithStackByArgs()) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrTableCantHandleFt.GenWithStackByArgs()) case ast.ColumnOptionCheck: - ctx.GetSessionVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("CONSTRAINT CHECK")) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedConstraintCheck.GenWithStackByArgs("CONSTRAINT CHECK")) } } } @@ -843,30 +1036,67 @@ func columnDefToCol(ctx sessionctx.Context, offset int, colDef *ast.ColumnDef, o return col, constraints, nil } +// getFuncCallDefaultValue gets the default column value of function-call expression. +func getFuncCallDefaultValue(col *table.Column, option *ast.ColumnOption, expr *ast.FuncCallExpr) (interface{}, bool, error) { + switch expr.FnName.L { + case ast.Rand: + if err := expression.VerifyArgsWrapper(ast.Rand, len(expr.Args)); err != nil { + return nil, false, errors.Trace(err) + } + col.DefaultIsExpr = true + var sb strings.Builder + restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes | + format.RestoreSpacesAroundBinaryOperation + restoreCtx := format.NewRestoreCtx(restoreFlags, &sb) + if err := expr.Restore(restoreCtx); err != nil { + return "", false, err + } + return sb.String(), false, nil + case ast.NextVal: + // handle default next value of sequence. (keep the expr string) + str, err := getSequenceDefaultValue(option) + if err != nil { + return nil, false, errors.Trace(err) + } + return str, true, nil + case ast.CurrentTimestamp: + tp, fsp := col.FieldType.Tp, col.FieldType.Decimal + if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { + defaultFsp := 0 + if len(expr.Args) == 1 { + if val := expr.Args[0].(*driver.ValueExpr); val != nil { + defaultFsp = int(val.GetInt64()) + } + } + if defaultFsp != fsp { + return nil, false, dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + } + } + return nil, false, nil + default: + return nil, false, dbterror.ErrDefValGeneratedNamedFunctionIsNotAllowed.GenWithStackByArgs(col.Name.String(), expr.FnName.String()) + } +} + // getDefaultValue will get the default value for column. // 1: get the expr restored string for the column which uses sequence next value as default value. // 2: get specific default value for the other column. -func getDefaultValue(ctx sessionctx.Context, col *table.Column, c *ast.ColumnOption) (interface{}, bool, error) { +func getDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.ColumnOption) (interface{}, bool, error) { + // handle default value with function call tp, fsp := col.FieldType.Tp, col.FieldType.Decimal - if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { - switch x := c.Expr.(type) { - case *ast.FuncCallExpr: - if x.FnName.L == ast.CurrentTimestamp { - defaultFsp := 0 - if len(x.Args) == 1 { - if val := x.Args[0].(*driver.ValueExpr); val != nil { - defaultFsp = int(val.GetInt64()) - } - } - if defaultFsp != fsp { - return nil, false, ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) - } - } + if x, ok := option.Expr.(*ast.FuncCallExpr); ok { + val, isSeqExpr, err := getFuncCallDefaultValue(col, option, x) + if val != nil || isSeqExpr || err != nil { + return val, isSeqExpr, err } - vd, err := expression.GetTimeValue(ctx, c.Expr, tp, int8(fsp)) + // If the function call is ast.CurrentTimestamp, it needs to be continuously processed. + } + + if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { + vd, err := expression.GetTimeValue(ctx, option.Expr, tp, fsp) value := vd.GetValue() if err != nil { - return nil, false, ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + return nil, false, dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } // Value is nil means `default null`. @@ -881,17 +1111,9 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, c *ast.ColumnOpt return value, false, nil } - // handle default next value of sequence. (keep the expr string) - str, isSeqExpr, err := tryToGetSequenceDefaultValue(c) - if err != nil { - return nil, false, errors.Trace(err) - } - if isSeqExpr { - return str, true, nil - } - // evaluate the non-sequence expr to a certain value. - v, err := expression.EvalAstExpr(ctx, c.Expr) + // evaluate the non-function-call expr to a certain value. + v, err := expression.EvalAstExpr(ctx, option.Expr) if err != nil { return nil, false, errors.Trace(err) } @@ -901,13 +1123,20 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, c *ast.ColumnOpt } if v.Kind() == types.KindBinaryLiteral || v.Kind() == types.KindMysqlBit { - if tp == mysql.TypeBit || - tp == mysql.TypeString || tp == mysql.TypeVarchar || tp == mysql.TypeVarString || - tp == mysql.TypeBlob || tp == mysql.TypeLongBlob || tp == mysql.TypeMediumBlob || tp == mysql.TypeTinyBlob || - tp == mysql.TypeJSON || tp == mysql.TypeEnum || tp == mysql.TypeSet { - // For BinaryLiteral / string fields, when getting default value we cast the value into BinaryLiteral{}, thus we return - // its raw string content here. - return v.GetBinaryLiteral().ToString(), false, nil + if types.IsTypeBlob(tp) || tp == mysql.TypeJSON { + // BLOB/TEXT/JSON column cannot have a default value. + // Skip the unnecessary decode procedure. + return v.GetString(), false, err + } + if tp == mysql.TypeBit || tp == mysql.TypeString || tp == mysql.TypeVarchar || + tp == mysql.TypeVarString || tp == mysql.TypeEnum || tp == mysql.TypeSet { + // For BinaryLiteral or bit fields, we decode the default value to utf8 string. + str, err := v.GetBinaryStringDecoded(nil, col.Charset) + if err != nil { + // Overwrite the decoding error with invalid default value error. + err = dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + } + return str, false, err } // For other kind of fields (e.g. INT), we supply its integer as string value. value, err := v.GetBinaryLiteral().ToInt(ctx.GetSessionVars().StmtCtx) @@ -924,7 +1153,7 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, c *ast.ColumnOpt case mysql.TypeEnum: val, err := getEnumDefaultValue(v, col) return val, false, err - case mysql.TypeDuration: + case mysql.TypeDuration, mysql.TypeDate: if v, err = v.ConvertTo(ctx.GetSessionVars().StmtCtx, &col.FieldType); err != nil { return "", false, errors.Trace(err) } @@ -939,18 +1168,15 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, c *ast.ColumnOpt return val, false, err } -func tryToGetSequenceDefaultValue(c *ast.ColumnOption) (expr string, isExpr bool, err error) { - if f, ok := c.Expr.(*ast.FuncCallExpr); ok && f.FnName.L == ast.NextVal { - var sb strings.Builder - restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes | - format.RestoreSpacesAroundBinaryOperation - restoreCtx := format.NewRestoreCtx(restoreFlags, &sb) - if err := c.Expr.Restore(restoreCtx); err != nil { - return "", true, err - } - return sb.String(), true, nil +func getSequenceDefaultValue(c *ast.ColumnOption) (expr string, err error) { + var sb strings.Builder + restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes | + format.RestoreSpacesAroundBinaryOperation + restoreCtx := format.NewRestoreCtx(restoreFlags, &sb) + if err := c.Expr.Restore(restoreCtx); err != nil { + return "", err } - return "", false, nil + return sb.String(), nil } // getSetDefaultValue gets the default value for the set type. See https://dev.mysql.com/doc/refman/5.7/en/set.html. @@ -960,7 +1186,7 @@ func getSetDefaultValue(v types.Datum, col *table.Column) (string, error) { maxLimit := int64(1< maxLimit { - return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } setVal, err := types.ParseSetValue(col.Elems, uint64(val)) if err != nil { @@ -979,7 +1205,7 @@ func getSetDefaultValue(v types.Datum, col *table.Column) (string, error) { } setVal, err := types.ParseSetName(col.Elems, str, col.Collate) if err != nil { - return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } v.SetMysqlSet(setVal, col.Collate) @@ -991,7 +1217,7 @@ func getEnumDefaultValue(v types.Datum, col *table.Column) (string, error) { if v.Kind() == types.KindInt64 { val := v.GetInt64() if val < 1 || val > int64(len(col.Elems)) { - return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } enumVal, err := types.ParseEnumValue(col.Elems, uint64(val)) if err != nil { @@ -1009,7 +1235,7 @@ func getEnumDefaultValue(v types.Datum, col *table.Column) (string, error) { str = strings.TrimRight(str, " ") enumVal, err := types.ParseEnumName(col.Elems, str, col.Collate) if err != nil { - return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) + return "", dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) } v.SetMysqlEnum(enumVal, col.Collate) @@ -1096,7 +1322,7 @@ func checkDefaultValue(ctx sessionctx.Context, c *table.Column, hasDefaultValue } // Primary key default null is invalid. if mysql.HasPriKeyFlag(c.Flag) { - return ErrPrimaryCantHaveNull + return dbterror.ErrPrimaryCantHaveNull } // Set not null but default null is invalid. @@ -1126,7 +1352,7 @@ func checkPriKeyConstraint(col *table.Column, hasDefaultValue, hasNullFlag bool, } // Primary key should not be null. if mysql.HasPriKeyFlag(col.Flag) && hasNullFlag { - return ErrPrimaryCantHaveNull + return dbterror.ErrPrimaryCantHaveNull } return nil } @@ -1149,7 +1375,7 @@ func checkColumnValueConstraint(col *table.Column, collation string) error { // where M is the element literal length and w is the number of bytes required for the maximum-length character in the character set. // See https://dev.mysql.com/doc/refman/8.0/en/string-type-syntax.html for more details. if enumLengthLimit && (len(val) > 255 || len(val)*desc.Maxlen > 1020) { - return ErrTooLongValueForType.GenWithStackByArgs(col.Name) + return dbterror.ErrTooLongValueForType.GenWithStackByArgs(col.Name) } if _, ok := valueMap[val]; ok { tpStr := "ENUM" @@ -1224,7 +1450,7 @@ func checkGeneratedColumn(ctx sessionctx.Context, colDefs []*ast.ColumnDef) erro if !ctx.GetSessionVars().EnableAutoIncrementInGenerated { for colName, generated := range colName2Generation { if _, found := generated.dependences[autoIncrementColumn]; found { - return ErrGeneratedColumnRefAutoInc.GenWithStackByArgs(colName) + return dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs(colName) } } } @@ -1243,7 +1469,7 @@ func checkTooLongColumn(cols []*model.ColumnInfo) error { for _, col := range cols { colName := col.Name.O if utf8.RuneCountInString(colName) > mysql.MaxColumnNameLength { - return ErrTooLongIdent.GenWithStackByArgs(colName) + return dbterror.ErrTooLongIdent.GenWithStackByArgs(colName) } } return nil @@ -1251,14 +1477,14 @@ func checkTooLongColumn(cols []*model.ColumnInfo) error { func checkTooManyColumns(colDefs []*model.ColumnInfo) error { if uint32(len(colDefs)) > atomic.LoadUint32(&config.GetGlobalConfig().TableColumnCountLimit) { - return errTooManyFields + return dbterror.ErrTooManyFields } return nil } func checkTooManyIndexes(idxDefs []*model.IndexInfo) error { if len(idxDefs) > config.GetGlobalConfig().IndexLimit { - return errTooManyKeys.GenWithStackByArgs(config.GetGlobalConfig().IndexLimit) + return dbterror.ErrTooManyKeys.GenWithStackByArgs(config.GetGlobalConfig().IndexLimit) } return nil } @@ -1305,7 +1531,7 @@ func checkColumnAttributes(colName string, tp *types.FieldType) error { return types.ErrMBiggerThanD.GenWithStackByArgs(colName) } case mysql.TypeDatetime, mysql.TypeDuration, mysql.TypeTimestamp: - if tp.Decimal != int(types.UnspecifiedFsp) && (tp.Decimal < int(types.MinFsp) || tp.Decimal > int(types.MaxFsp)) { + if tp.Decimal != types.UnspecifiedFsp && (tp.Decimal < types.MinFsp || tp.Decimal > types.MaxFsp) { return types.ErrTooBigPrecision.GenWithStackByArgs(tp.Decimal, colName, types.MaxFsp) } } @@ -1319,9 +1545,9 @@ func checkDuplicateConstraint(namesMap map[string]bool, name string, foreign boo nameLower := strings.ToLower(name) if namesMap[nameLower] { if foreign { - return ErrFkDupName.GenWithStackByArgs(name) + return dbterror.ErrFkDupName.GenWithStackByArgs(name) } - return ErrDupKeyName.GenWithStack("duplicate key name %s", name) + return dbterror.ErrDupKeyName.GenWithStack("duplicate key name %s", name) } namesMap[nameLower] = true return nil @@ -1399,7 +1625,7 @@ func checkInvisibleIndexOnPK(tblInfo *model.TableInfo) error { } pk := getPrimaryKey(tblInfo) if pk != nil && pk.Invisible { - return ErrPKIndexCantBeInvisible + return dbterror.ErrPKIndexCantBeInvisible } return nil } @@ -1457,18 +1683,18 @@ func setTableAutoRandomBits(ctx sessionctx.Context, tbInfo *model.TableInfo, col for _, col := range colDefs { if containsColumnOption(col, ast.ColumnOptionAutoRandom) { if col.Tp.Tp != mysql.TypeLonglong { - return ErrInvalidAutoRandom.GenWithStackByArgs( + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs( fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(col.Tp.Tp))) } if !tbInfo.PKIsHandle || col.Name.Name.L != pkColName.L { errMsg := fmt.Sprintf(autoid.AutoRandomPKisNotHandleErrMsg, col.Name.Name.O) - return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } if containsColumnOption(col, ast.ColumnOptionAutoIncrement) { - return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg) } if containsColumnOption(col, ast.ColumnOptionDefaultValue) { - return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) } autoRandBits, err := extractAutoRandomBitsFromColDef(col) @@ -1478,11 +1704,11 @@ func setTableAutoRandomBits(ctx sessionctx.Context, tbInfo *model.TableInfo, col layout := autoid.NewShardIDLayout(col.Tp, autoRandBits) if autoRandBits == 0 { - return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive) } else if autoRandBits > autoid.MaxAutoRandomBits { errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg, autoid.MaxAutoRandomBits, autoRandBits, col.Name.Name.O) - return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } tbInfo.AutoRandomBits = autoRandBits @@ -1506,7 +1732,7 @@ func convertAutoRandomBitsToUnsigned(autoRandomBits int) (uint64, error) { if autoRandomBits == types.UnspecifiedLength { return autoid.DefaultAutoRandomBits, nil } else if autoRandomBits < 0 { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive) } return uint64(autoRandomBits), nil } @@ -1546,7 +1772,7 @@ func buildTableInfo( // Check clustered on non-primary key. if constr.Option != nil && constr.Option.PrimaryKeyTp != model.PrimaryKeyTypeDefault && constr.Tp != ast.ConstraintPrimaryKey { - return nil, errUnsupportedClusteredSecondaryKey + return nil, dbterror.ErrUnsupportedClusteredSecondaryKey } if constr.Tp == ast.ConstraintForeignKey { for _, fk := range tbInfo.ForeignKeys { @@ -1580,7 +1806,7 @@ func buildTableInfo( if tbInfo.HasClusteredIndex() { // Primary key cannot be invisible. if constr.Option != nil && constr.Option.Visibility == ast.IndexVisibilityInvisible { - return nil, ErrPKIndexCantBeInvisible + return nil, dbterror.ErrPKIndexCantBeInvisible } } if tbInfo.PKIsHandle { @@ -1589,11 +1815,11 @@ func buildTableInfo( } if constr.Tp == ast.ConstraintFulltext { - ctx.GetSessionVars().StmtCtx.AppendWarning(ErrTableCantHandleFt.GenWithStackByArgs()) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrTableCantHandleFt.GenWithStackByArgs()) continue } if constr.Tp == ast.ConstraintCheck { - ctx.GetSessionVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("CONSTRAINT CHECK")) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedConstraintCheck.GenWithStackByArgs("CONSTRAINT CHECK")) continue } // build index info. @@ -1639,19 +1865,19 @@ func buildTableInfo( return } -func indexColumnsLen(cols []*model.ColumnInfo, idxCols []*model.IndexColumn) (len int, err error) { +func indexColumnsLen(cols []*model.ColumnInfo, idxCols []*model.IndexColumn) (colLen int, err error) { for _, idxCol := range idxCols { col := model.FindColumnInfo(cols, idxCol.Name.L) if col == nil { - err = errKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", idxCol.Name.L) + err = dbterror.ErrKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", idxCol.Name.L) return } - var colLen int - colLen, err = getIndexColumnLength(col, idxCol.Length) + var l int + l, err = getIndexColumnLength(col, idxCol.Length) if err != nil { return } - len += colLen + colLen += l } return } @@ -1755,6 +1981,9 @@ func checkPartitionDefinitionConstraints(ctx sessionctx.Context, tbInfo *model.T if err = checkAddPartitionOnTemporaryMode(tbInfo); err != nil { return err } + if err = checkPartitionColumnsUnique(tbInfo); err != nil { + return err + } switch tbInfo.Partition.Type { case model.PartitionTypeRange: @@ -1779,7 +2008,7 @@ func checkTableInfoValid(tblInfo *model.TableInfo) error { func buildTableInfoWithLike(ctx sessionctx.Context, ident ast.Ident, referTblInfo *model.TableInfo, s *ast.CreateTableStmt) (*model.TableInfo, error) { // Check the referred table is a real table object. if referTblInfo.IsSequence() || referTblInfo.IsView() { - return nil, ErrWrongObject.GenWithStackByArgs(ident.Schema, referTblInfo.Name, "BASE TABLE") + return nil, dbterror.ErrWrongObject.GenWithStackByArgs(ident.Schema, referTblInfo.Name, "BASE TABLE") } tblInfo := *referTblInfo if err := setTemporaryType(ctx, &tblInfo, s); err != nil { @@ -1820,13 +2049,13 @@ func buildTableInfoWithLike(ctx sessionctx.Context, ident ast.Ident, referTblInf // BuildTableInfoFromAST builds model.TableInfo from a SQL statement. // Note: TableID and PartitionID are left as uninitialized value. func BuildTableInfoFromAST(s *ast.CreateTableStmt) (*model.TableInfo, error) { - return buildTableInfoWithCheck(mock.NewContext(), s, mysql.DefaultCharset, "", nil, nil) + return buildTableInfoWithCheck(mock.NewContext(), s, mysql.DefaultCharset, "", nil) } // buildTableInfoWithCheck builds model.TableInfo from a SQL statement. // Note: TableID and PartitionIDs are left as uninitialized value. -func buildTableInfoWithCheck(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings) (*model.TableInfo, error) { - tbInfo, err := buildTableInfoWithStmt(ctx, s, dbCharset, dbCollate, placementPolicyRef, directPlacementOpts) +func buildTableInfoWithCheck(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo) (*model.TableInfo, error) { + tbInfo, err := buildTableInfoWithStmt(ctx, s, dbCharset, dbCollate, placementPolicyRef) if err != nil { return nil, err } @@ -1843,7 +2072,7 @@ func buildTableInfoWithCheck(ctx sessionctx.Context, s *ast.CreateTableStmt, dbC } // BuildSessionTemporaryTableInfo builds model.TableInfo from a SQL statement. -func BuildSessionTemporaryTableInfo(ctx sessionctx.Context, is infoschema.InfoSchema, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings) (*model.TableInfo, error) { +func BuildSessionTemporaryTableInfo(ctx sessionctx.Context, is infoschema.InfoSchema, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo) (*model.TableInfo, error) { ident := ast.Ident{Schema: s.Table.Schema, Name: s.Table.Name} //build tableInfo var tbInfo *model.TableInfo @@ -1861,13 +2090,13 @@ func BuildSessionTemporaryTableInfo(ctx sessionctx.Context, is infoschema.InfoSc } tbInfo, err = buildTableInfoWithLike(ctx, ident, referTbl.Meta(), s) } else { - tbInfo, err = buildTableInfoWithCheck(ctx, s, dbCharset, dbCollate, placementPolicyRef, directPlacementOpts) + tbInfo, err = buildTableInfoWithCheck(ctx, s, dbCharset, dbCollate, placementPolicyRef) } return tbInfo, err } // buildTableInfoWithStmt builds model.TableInfo from a SQL statement without validity check -func buildTableInfoWithStmt(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo, directPlacementOpts *model.PlacementSettings) (*model.TableInfo, error) { +func buildTableInfoWithStmt(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCharset, dbCollate string, placementPolicyRef *model.PolicyRefInfo) (*model.TableInfo, error) { colDefs := s.Cols tableCharset, tableCollate, err := getCharsetAndCollateInTableOption(0, s.Options) if err != nil { @@ -1908,26 +2137,9 @@ func buildTableInfoWithStmt(ctx sessionctx.Context, s *ast.CreateTableStmt, dbCh return nil, errors.Trace(err) } - if tbInfo.TempTableType == model.TempTableNone && tbInfo.PlacementPolicyRef == nil && tbInfo.DirectPlacementOpts == nil { + if tbInfo.TempTableType == model.TempTableNone && tbInfo.PlacementPolicyRef == nil && placementPolicyRef != nil { // Set the defaults from Schema. Note: they are mutual exclusive! - if placementPolicyRef != nil { - tbInfo.PlacementPolicyRef = placementPolicyRef - } else if directPlacementOpts != nil { - tbInfo.DirectPlacementOpts = directPlacementOpts - } - } - tbInfo.PlacementPolicyRef, tbInfo.DirectPlacementOpts, err = checkAndNormalizePlacement(ctx, tbInfo.PlacementPolicyRef, tbInfo.DirectPlacementOpts, placementPolicyRef, directPlacementOpts) - if err != nil { - return nil, errors.Trace(err) - } - - if tbInfo.Partition != nil { - for _, partition := range tbInfo.Partition.Definitions { - partition.PlacementPolicyRef, partition.DirectPlacementOpts, err = checkAndNormalizePlacement(ctx, partition.PlacementPolicyRef, partition.DirectPlacementOpts, nil, nil) - if err != nil { - return nil, errors.Trace(err) - } - } + tbInfo.PlacementPolicyRef = placementPolicyRef } // After handleTableOptions, so the partitions can get defaults from Table level @@ -1985,7 +2197,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e if s.ReferTable != nil { tbInfo, err = buildTableInfoWithLike(ctx, ident, referTbl.Meta(), s) } else { - tbInfo, err = buildTableInfoWithStmt(ctx, s, schema.Charset, schema.Collate, schema.PlacementPolicyRef, schema.DirectPlacementOpts) + tbInfo, err = buildTableInfoWithStmt(ctx, s, schema.Charset, schema.Collate, schema.PlacementPolicyRef) } if err != nil { return errors.Trace(err) @@ -2000,7 +2212,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e onExist = OnExistIgnore } - return d.CreateTableWithInfo(ctx, schema.Name, tbInfo, onExist, false /*tryRetainID*/) + return d.CreateTableWithInfo(ctx, schema.Name, tbInfo, onExist) } func setTemporaryType(ctx sessionctx.Context, tbInfo *model.TableInfo, s *ast.CreateTableStmt) error { @@ -2009,7 +2221,7 @@ func setTemporaryType(ctx sessionctx.Context, tbInfo *model.TableInfo, s *ast.Cr tbInfo.TempTableType = model.TempTableGlobal // "create global temporary table ... on commit preserve rows" if !s.OnCommitDelete { - return errors.Trace(errUnsupportedOnCommitPreserve) + return errors.Trace(dbterror.ErrUnsupportedOnCommitPreserve) } case ast.TemporaryLocal: tbInfo.TempTableType = model.TempTableLocal @@ -2019,17 +2231,25 @@ func setTemporaryType(ctx sessionctx.Context, tbInfo *model.TableInfo, s *ast.Cr return nil } -func (d *ddl) CreateTableWithInfo( +// createTableWithInfoJob returns the table creation job. +// WARNING: it may return a nil job, which means you don't need to submit any DDL job. +// WARNING!!!: if retainID == true, it will not allocate ID by itself. That means if the caller +// can not promise ID is unique, then we got inconsistency. +func (d *ddl) createTableWithInfoJob( ctx sessionctx.Context, dbName model.CIStr, tbInfo *model.TableInfo, onExist OnExist, - tryRetainID bool, -) (err error) { + retainID bool, +) (job *model.Job, err error) { is := d.GetInfoSchemaWithInterceptor(ctx) schema, ok := is.SchemaByName(dbName) if !ok { - return infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbName) + return nil, infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbName) + } + + if err = handleTablePlacement(ctx, tbInfo); err != nil { + return nil, errors.Trace(err) } var oldViewTblID int64 @@ -2038,7 +2258,7 @@ func (d *ddl) CreateTableWithInfo( switch onExist { case OnExistIgnore: ctx.GetSessionVars().StmtCtx.AppendNote(err) - return nil + return nil, nil case OnExistReplace: // only CREATE OR REPLACE VIEW is supported at the moment. if tbInfo.View != nil { @@ -2047,27 +2267,28 @@ func (d *ddl) CreateTableWithInfo( break } // The object to replace isn't a view. - return ErrWrongObject.GenWithStackByArgs(dbName, tbInfo.Name, "VIEW") + return nil, dbterror.ErrWrongObject.GenWithStackByArgs(dbName, tbInfo.Name, "VIEW") } - return err + return nil, err default: - return err + return nil, err } } - // FIXME: Implement `tryRetainID` - if err := d.assignTableID(tbInfo); err != nil { - return errors.Trace(err) - } + if !retainID { + if err := d.assignTableID(tbInfo); err != nil { + return nil, errors.Trace(err) + } - if tbInfo.Partition != nil { - if err := d.assignPartitionIDs(tbInfo.Partition.Definitions); err != nil { - return errors.Trace(err) + if tbInfo.Partition != nil { + if err := d.assignPartitionIDs(tbInfo.Partition.Definitions); err != nil { + return nil, errors.Trace(err) + } } } if err := checkTableInfoValidExtra(tbInfo); err != nil { - return err + return nil, err } var actionType model.ActionType @@ -2082,73 +2303,241 @@ func (d *ddl) CreateTableWithInfo( actionType = model.ActionCreateTable } - job := &model.Job{ + job = &model.Job{ SchemaID: schema.ID, TableID: tbInfo.ID, SchemaName: schema.Name.L, + TableName: tbInfo.Name.L, Type: actionType, BinlogInfo: &model.HistoryInfo{}, Args: args, } + return job, nil +} + +func (d *ddl) createTableWithInfoPost( + ctx sessionctx.Context, + tbInfo *model.TableInfo, + schemaID int64, +) error { + var err error + d.preSplitAndScatter(ctx, tbInfo, tbInfo.GetPartitionInfo()) + if tbInfo.AutoIncID > 1 { + // Default tableAutoIncID base is 0. + // If the first ID is expected to greater than 1, we need to do rebase. + newEnd := tbInfo.AutoIncID - 1 + if err = d.handleAutoIncID(tbInfo, schemaID, newEnd, autoid.RowIDAllocType); err != nil { + return errors.Trace(err) + } + } + if tbInfo.AutoRandID > 1 { + // Default tableAutoRandID base is 0. + // If the first ID is expected to greater than 1, we need to do rebase. + newEnd := tbInfo.AutoRandID - 1 + err = d.handleAutoIncID(tbInfo, schemaID, newEnd, autoid.AutoRandomType) + } + return err +} + +func (d *ddl) CreateTableWithInfo( + ctx sessionctx.Context, + dbName model.CIStr, + tbInfo *model.TableInfo, + onExist OnExist, +) (err error) { + job, err := d.createTableWithInfoJob(ctx, dbName, tbInfo, onExist, false) + if err != nil { + return err + } + if job == nil { + return nil + } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { // table exists, but if_not_exists flags is true, so we ignore this error. if onExist == OnExistIgnore && infoschema.ErrTableExists.Equal(err) { ctx.GetSessionVars().StmtCtx.AppendNote(err) err = nil } - } else if actionType == model.ActionCreateTable { - d.preSplitAndScatter(ctx, tbInfo, tbInfo.GetPartitionInfo()) - if tbInfo.AutoIncID > 1 { - // Default tableAutoIncID base is 0. - // If the first ID is expected to greater than 1, we need to do rebase. - newEnd := tbInfo.AutoIncID - 1 - if err = d.handleAutoIncID(tbInfo, schema.ID, newEnd, autoid.RowIDAllocType); err != nil { - return errors.Trace(err) - } - } - if tbInfo.AutoRandID > 1 { - // Default tableAutoRandID base is 0. - // If the first ID is expected to greater than 1, we need to do rebase. - newEnd := tbInfo.AutoRandID - 1 - err = d.handleAutoIncID(tbInfo, schema.ID, newEnd, autoid.AutoRandomType) - } + } else { + err = d.createTableWithInfoPost(ctx, tbInfo, job.SchemaID) } err = d.callHookOnChanged(err) return errors.Trace(err) } -// preSplitAndScatter performs pre-split and scatter of the table's regions. -// If `pi` is not nil, will only split region for `pi`, this is used when add partition. -func (d *ddl) preSplitAndScatter(ctx sessionctx.Context, tbInfo *model.TableInfo, pi *model.PartitionInfo) { - if tbInfo.TempTableType != model.TempTableNone { - return +func (d *ddl) BatchCreateTableWithInfo(ctx sessionctx.Context, + dbName model.CIStr, + infos []*model.TableInfo, + onExist OnExist) error { + jobs := &model.Job{ + BinlogInfo: &model.HistoryInfo{}, } - sp, ok := d.store.(kv.SplittableStore) - if !ok || atomic.LoadUint32(&EnableSplitTableRegion) == 0 { - return + args := make([]*model.TableInfo, 0, len(infos)) + + var err error + + // 1. counts how many IDs are there + // 2. if there is any duplicated table name + totalID := 0 + duplication := make(map[string]struct{}) + for _, info := range infos { + if _, ok := duplication[info.Name.L]; ok { + err = infoschema.ErrTableExists.FastGenByArgs("can not batch create tables with same name") + if onExist == OnExistIgnore && infoschema.ErrTableExists.Equal(err) { + ctx.GetSessionVars().StmtCtx.AppendNote(err) + err = nil + } + } + if err != nil { + return errors.Trace(err) + } + + duplication[info.Name.L] = struct{}{} + + totalID += 1 + parts := info.GetPartitionInfo() + if parts != nil { + totalID += len(parts.Definitions) + } } - var ( - preSplit func() - scatterRegion bool - ) - val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBScatterRegion) + + genIDs, err := d.genGlobalIDs(totalID) if err != nil { - logutil.BgLogger().Warn("[ddl] won't scatter region", zap.Error(err)) - } else { - scatterRegion = variable.TiDBOptOn(val) - } - if pi != nil { - preSplit = func() { splitPartitionTableRegion(ctx, sp, tbInfo, pi, scatterRegion) } - } else { - preSplit = func() { splitTableRegion(ctx, sp, tbInfo, scatterRegion) } - } - if scatterRegion { - preSplit() - } else { - go preSplit() + return errors.Trace(err) + } + + for _, info := range infos { + info.ID, genIDs = genIDs[0], genIDs[1:] + + if parts := info.GetPartitionInfo(); parts != nil { + for i := range parts.Definitions { + parts.Definitions[i].ID, genIDs = genIDs[0], genIDs[1:] + } + } + + job, err := d.createTableWithInfoJob(ctx, dbName, info, onExist, true) + if err != nil { + return errors.Trace(err) + } + if job == nil { + continue + } + + // if jobs.Type == model.ActionCreateTables, it is initialized + // if not, initialize jobs by job.XXXX + if jobs.Type != model.ActionCreateTables { + jobs.Type = model.ActionCreateTables + jobs.SchemaID = job.SchemaID + jobs.SchemaName = job.SchemaName + } + + // append table job args + info, ok := job.Args[0].(*model.TableInfo) + if !ok { + return errors.Trace(fmt.Errorf("except table info")) + } + args = append(args, info) + } + if len(args) == 0 { + return nil + } + jobs.Args = append(jobs.Args, args) + + err = d.DoDDLJob(ctx, jobs) + if err != nil { + // table exists, but if_not_exists flags is true, so we ignore this error. + if onExist == OnExistIgnore && infoschema.ErrTableExists.Equal(err) { + ctx.GetSessionVars().StmtCtx.AppendNote(err) + err = nil + } + return errors.Trace(d.callHookOnChanged(err)) + } + + for j := range args { + if err = d.createTableWithInfoPost(ctx, args[j], jobs.SchemaID); err != nil { + return errors.Trace(d.callHookOnChanged(err)) + } + } + + return nil +} + +func (d *ddl) CreatePlacementPolicyWithInfo(ctx sessionctx.Context, policy *model.PolicyInfo, onExist OnExist) error { + if checkIgnorePlacementDDL(ctx) { + return nil + } + + policyName := policy.Name + if policyName.L == defaultPlacementPolicyName { + return errors.Trace(infoschema.ErrReservedSyntax.GenWithStackByArgs(policyName)) + } + + // Check policy existence. + _, ok := d.GetInfoSchemaWithInterceptor(ctx).PolicyByName(policyName) + if ok { + err := infoschema.ErrPlacementPolicyExists.GenWithStackByArgs(policyName) + switch onExist { + case OnExistIgnore: + ctx.GetSessionVars().StmtCtx.AppendNote(err) + return nil + case OnExistError: + return err + } + } + + if err := checkPolicyValidation(policy.PlacementSettings); err != nil { + return err + } + + policyID, err := d.genPlacementPolicyID() + if err != nil { + return err + } + policy.ID = policyID + + job := &model.Job{ + SchemaName: policy.Name.L, + Type: model.ActionCreatePlacementPolicy, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{policy, onExist == OnExistReplace}, + } + err = d.DoDDLJob(ctx, job) + err = d.callHookOnChanged(err) + return errors.Trace(err) +} + +// preSplitAndScatter performs pre-split and scatter of the table's regions. +// If `pi` is not nil, will only split region for `pi`, this is used when add partition. +func (d *ddl) preSplitAndScatter(ctx sessionctx.Context, tbInfo *model.TableInfo, pi *model.PartitionInfo) { + if tbInfo.TempTableType != model.TempTableNone { + return + } + sp, ok := d.store.(kv.SplittableStore) + if !ok || atomic.LoadUint32(&EnableSplitTableRegion) == 0 { + return + } + var ( + preSplit func() + scatterRegion bool + ) + val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBScatterRegion) + if err != nil { + logutil.BgLogger().Warn("[ddl] won't scatter region", zap.Error(err)) + } else { + scatterRegion = variable.TiDBOptOn(val) + } + if pi != nil { + preSplit = func() { splitPartitionTableRegion(ctx, sp, tbInfo, pi, scatterRegion) } + } else { + preSplit = func() { splitTableRegion(ctx, sp, tbInfo, scatterRegion) } + } + if scatterRegion { + preSplit() + } else { + go preSplit() } } @@ -2172,13 +2561,15 @@ func (d *ddl) RecoverTable(ctx sessionctx.Context, recoverInfo *RecoverInfo) (er SchemaID: schemaID, TableID: tbInfo.ID, SchemaName: schema.Name.L, + TableName: tbInfo.Name.L, + Type: model.ActionRecoverTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{tbInfo, recoverInfo.AutoIDs.RowID, recoverInfo.DropJobID, recoverInfo.SnapshotTS, recoverTableCheckFlagNone, recoverInfo.AutoIDs.RandomID, recoverInfo.OldSchemaName, recoverInfo.OldTableName}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -2219,7 +2610,7 @@ func (d *ddl) CreateView(ctx sessionctx.Context, s *ast.CreateViewStmt) (err err onExist = OnExistReplace } - return d.CreateTableWithInfo(ctx, s.ViewName.Schema, tbInfo, onExist, false /*tryRetainID*/) + return d.CreateTableWithInfo(ctx, s.ViewName.Schema, tbInfo, onExist) } func buildViewInfo(ctx sessionctx.Context, s *ast.CreateViewStmt) (*model.ViewInfo, error) { @@ -2261,7 +2652,7 @@ func checkColumnsPartitionType(tbInfo *model.TableInfo) error { for _, col := range tbInfo.Partition.Columns { colInfo := getColumnInfoByName(tbInfo, col.L) if colInfo == nil { - return errors.Trace(ErrFieldNotFoundPart) + return errors.Trace(dbterror.ErrFieldNotFoundPart) } // The permitted data types are shown in the following list: // All integer types @@ -2273,7 +2664,7 @@ func checkColumnsPartitionType(tbInfo *model.TableInfo) error { case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeDuration: case mysql.TypeVarchar, mysql.TypeString: default: - return ErrNotAllowedTypeInPartition.GenWithStackByArgs(col.O) + return dbterror.ErrNotAllowedTypeInPartition.GenWithStackByArgs(col.O) } } return nil @@ -2299,7 +2690,7 @@ func checkRangeColumnsPartitionValue(ctx sessionctx.Context, tbInfo *model.Table return err } if !succ { - return errors.Trace(ErrRangeNotIncreasing) + return errors.Trace(dbterror.ErrRangeNotIncreasing) } } return nil @@ -2320,11 +2711,6 @@ func checkTwoRangeColumns(ctx sessionctx.Context, curr, prev *model.PartitionDef return false, nil } - // Current and previous is the same. - if strings.EqualFold(curr.LessThan[i], prev.LessThan[i]) { - continue - } - // The tuples of column values used to define the partitions are strictly increasing: // PARTITION p0 VALUES LESS THAN (5,10,'ggg') // PARTITION p1 VALUES LESS THAN (10,20,'mmm') @@ -2365,7 +2751,7 @@ func parseAndEvalBoolExpr(ctx sessionctx.Context, l, r string, colInfo *model.Co func checkCharsetAndCollation(cs string, co string) error { if !charset.ValidCharsetAndCollation(cs, co) { - return ErrUnknownCharacterSet.GenWithStackByArgs(cs) + return dbterror.ErrUnknownCharacterSet.GenWithStackByArgs(cs) } if co != "" { if _, err := collate.GetCollationByName(co); err != nil { @@ -2439,7 +2825,7 @@ func handleTableOptions(options []*ast.TableOption, tbInfo *model.TableInfo) err tbInfo.Compression = op.StrValue case ast.TableOptionShardRowID: if op.UintValue > 0 && tbInfo.HasClusteredIndex() { - return errUnsupportedShardRowIDBits + return dbterror.ErrUnsupportedShardRowIDBits } tbInfo.ShardRowIDBits = op.UintValue if tbInfo.ShardRowIDBits > shardRowIDBitsMax { @@ -2448,7 +2834,7 @@ func handleTableOptions(options []*ast.TableOption, tbInfo *model.TableInfo) err tbInfo.MaxShardRowIDBits = tbInfo.ShardRowIDBits case ast.TableOptionPreSplitRegion: if tbInfo.TempTableType != model.TempTableNone { - return errors.Trace(ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions")) + return errors.Trace(dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions")) } tbInfo.PreSplitRegions = op.UintValue case ast.TableOptionCharset, ast.TableOptionCollate: @@ -2457,19 +2843,6 @@ func handleTableOptions(options []*ast.TableOption, tbInfo *model.TableInfo) err tbInfo.PlacementPolicyRef = &model.PolicyRefInfo{ Name: model.NewCIStr(op.StrValue), } - case ast.TableOptionPlacementPrimaryRegion, ast.TableOptionPlacementRegions, - ast.TableOptionPlacementFollowerCount, ast.TableOptionPlacementVoterCount, - ast.TableOptionPlacementLearnerCount, ast.TableOptionPlacementSchedule, - ast.TableOptionPlacementConstraints, ast.TableOptionPlacementLeaderConstraints, - ast.TableOptionPlacementLearnerConstraints, ast.TableOptionPlacementFollowerConstraints, - ast.TableOptionPlacementVoterConstraints: - if tbInfo.DirectPlacementOpts == nil { - tbInfo.DirectPlacementOpts = &model.PlacementSettings{} - } - err := SetDirectPlacementOpt(tbInfo.DirectPlacementOpts, ast.PlacementOptionType(op.Tp), op.StrValue, op.UintValue) - if err != nil { - return err - } } } shardingBits := shardingBits(tbInfo) @@ -2512,7 +2885,7 @@ func getCharsetAndCollateInColumnDef(def *ast.ColumnDef) (chs, coll string, err if chs == "" { chs = info.CharsetName } else if chs != info.CharsetName { - return "", "", ErrCollationCharsetMismatch.GenWithStackByArgs(info.Name, chs) + return "", "", dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs(info.Name, chs) } coll = info.Name } @@ -2537,7 +2910,7 @@ func getCharsetAndCollateInTableOption(startIdx int, options []*ast.TableOption) if len(chs) == 0 { chs = info.Name } else if chs != info.Name { - return "", "", ErrConflictingDeclarations.GenWithStackByArgs(chs, info.Name) + return "", "", dbterror.ErrConflictingDeclarations.GenWithStackByArgs(chs, info.Name) } if len(coll) == 0 { coll = info.DefaultCollation @@ -2550,7 +2923,7 @@ func getCharsetAndCollateInTableOption(startIdx int, options []*ast.TableOption) if len(chs) == 0 { chs = info.CharsetName } else if chs != info.CharsetName { - return "", "", ErrCollationCharsetMismatch.GenWithStackByArgs(info.Name, chs) + return "", "", dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs(info.Name, chs) } coll = info.Name } @@ -2569,6 +2942,16 @@ func needToOverwriteColCharset(options []*ast.TableOption) bool { return false } +func resolveAlterTableAddColumns(spec *ast.AlterTableSpec) []*ast.AlterTableSpec { + specs := make([]*ast.AlterTableSpec, len(spec.NewColumns)) + for i, col := range spec.NewColumns { + t := *spec + t.NewColumns = []*ast.ColumnDef{col} + specs[i] = &t + } + return specs +} + // resolveAlterTableSpec resolves alter table algorithm and removes ignore table spec in specs. // returns valied specs, and the occurred error. func resolveAlterTableSpec(ctx sessionctx.Context, specs []*ast.AlterTableSpec) ([]*ast.AlterTableSpec, error) { @@ -2582,7 +2965,11 @@ func resolveAlterTableSpec(ctx sessionctx.Context, specs []*ast.AlterTableSpec) if isIgnorableSpec(spec.Tp) { continue } - validSpecs = append(validSpecs, spec) + if spec.Tp == ast.AlterTableAddColumns && len(spec.NewColumns) > 1 { + validSpecs = append(validSpecs, resolveAlterTableAddColumns(spec)...) + } else { + validSpecs = append(validSpecs, spec) + } } // Verify whether the algorithm is supported. @@ -2604,31 +2991,13 @@ func resolveAlterTableSpec(ctx sessionctx.Context, specs []*ast.AlterTableSpec) return validSpecs, nil } -func isSameTypeMultiSpecs(specs []*ast.AlterTableSpec) bool { - specType := specs[0].Tp - for _, spec := range specs { - // We think AlterTableDropPrimaryKey and AlterTableDropIndex are the same types. - if spec.Tp == ast.AlterTableDropPrimaryKey || spec.Tp == ast.AlterTableDropIndex { - continue - } - if spec.Tp != specType { - return false - } - } - return true -} - func checkMultiSpecs(sctx sessionctx.Context, specs []*ast.AlterTableSpec) error { if !sctx.GetSessionVars().EnableChangeMultiSchema { if len(specs) > 1 { - return errRunMultiSchemaChanges + return dbterror.ErrRunMultiSchemaChanges } if len(specs) == 1 && len(specs[0].NewColumns) > 1 && specs[0].Tp == ast.AlterTableAddColumns { - return errRunMultiSchemaChanges - } - } else { - if len(specs) > 1 && !isSameTypeMultiSpecs(specs) { - return errRunMultiSchemaChanges + return dbterror.ErrRunMultiSchemaChanges } } return nil @@ -2641,8 +3010,20 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast } is := d.infoCache.GetLatest() - if is.TableIsView(ident.Schema, ident.Name) || is.TableIsSequence(ident.Schema, ident.Name) { - return ErrWrongObject.GenWithStackByArgs(ident.Schema, ident.Name, "BASE TABLE") + tb, err := is.TableByName(ident.Schema, ident.Name) + if err != nil { + return errors.Trace(err) + } + if tb.Meta().IsView() || tb.Meta().IsSequence() { + return dbterror.ErrWrongObject.GenWithStackByArgs(ident.Schema, ident.Name, "BASE TABLE") + } + if tb.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + if len(validSpecs) != 1 { + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Alter Table") + } + if validSpecs[0].Tp != ast.AlterTableCache && validSpecs[0].Tp != ast.AlterTableNoCache { + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Alter Table") + } } err = checkMultiSpecs(sctx, validSpecs) @@ -2651,47 +3032,29 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast } if len(validSpecs) > 1 { - switch validSpecs[0].Tp { - case ast.AlterTableAddColumns: - err = d.AddColumns(sctx, ident, validSpecs) - case ast.AlterTableDropColumn: - err = d.DropColumns(sctx, ident, validSpecs) - case ast.AlterTableDropPrimaryKey, ast.AlterTableDropIndex: - err = d.DropIndexes(sctx, ident, validSpecs) - default: - return errRunMultiSchemaChanges - } - if err != nil { - return errors.Trace(err) - } - return nil + sctx.GetSessionVars().StmtCtx.MultiSchemaInfo = model.NewMultiSchemaInfo() } - for _, spec := range validSpecs { var handledCharsetOrCollate bool switch spec.Tp { case ast.AlterTableAddColumns: - if len(spec.NewColumns) != 1 { - err = d.AddColumns(sctx, ident, []*ast.AlterTableSpec{spec}) - } else { - err = d.AddColumn(sctx, ident, spec) - } + err = d.AddColumn(sctx, ident, spec) case ast.AlterTableAddPartitions: err = d.AddTablePartitions(sctx, ident, spec) case ast.AlterTableCoalescePartitions: err = d.CoalescePartitions(sctx, ident, spec) case ast.AlterTableReorganizePartition: - err = errors.Trace(errUnsupportedReorganizePartition) + err = errors.Trace(dbterror.ErrUnsupportedReorganizePartition) case ast.AlterTableCheckPartitions: - err = errors.Trace(errUnsupportedCheckPartition) + err = errors.Trace(dbterror.ErrUnsupportedCheckPartition) case ast.AlterTableRebuildPartition: - err = errors.Trace(errUnsupportedRebuildPartition) + err = errors.Trace(dbterror.ErrUnsupportedRebuildPartition) case ast.AlterTableOptimizePartition: - err = errors.Trace(errUnsupportedOptimizePartition) + err = errors.Trace(dbterror.ErrUnsupportedOptimizePartition) case ast.AlterTableRemovePartitioning: - err = errors.Trace(errUnsupportedRemovePartition) + err = errors.Trace(dbterror.ErrUnsupportedRemovePartition) case ast.AlterTableRepairPartition: - err = errors.Trace(errUnsupportedRepairPartition) + err = errors.Trace(dbterror.ErrUnsupportedRepairPartition) case ast.AlterTableDropColumn: err = d.DropColumn(sctx, ident, spec) case ast.AlterTableDropIndex: @@ -2740,9 +3103,9 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast case ast.ConstraintPrimaryKey: err = d.CreatePrimaryKey(sctx, ident, model.NewCIStr(constr.Name), spec.Constraint.Keys, constr.Option) case ast.ConstraintFulltext: - sctx.GetSessionVars().StmtCtx.AppendWarning(ErrTableCantHandleFt) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrTableCantHandleFt) case ast.ConstraintCheck: - sctx.GetSessionVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("ADD CONSTRAINT CHECK")) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedConstraintCheck.GenWithStackByArgs("ADD CONSTRAINT CHECK")) default: // Nothing to do now. } @@ -2765,7 +3128,6 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast // Prevent silent succeed if user executes ALTER TABLE x PARTITION BY ... err = errors.New("alter table partition is unsupported") case ast.AlterTableOption: - var placementSettings *model.PlacementSettings var placementPolicyRef *model.PolicyRefInfo for i, opt := range spec.Options { switch opt.Tp { @@ -2805,19 +3167,9 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast placementPolicyRef = &model.PolicyRefInfo{ Name: model.NewCIStr(opt.StrValue), } - case ast.TableOptionPlacementPrimaryRegion, ast.TableOptionPlacementRegions, - ast.TableOptionPlacementFollowerCount, ast.TableOptionPlacementVoterCount, - ast.TableOptionPlacementLearnerCount, ast.TableOptionPlacementSchedule, - ast.TableOptionPlacementConstraints, ast.TableOptionPlacementLeaderConstraints, - ast.TableOptionPlacementLearnerConstraints, ast.TableOptionPlacementFollowerConstraints, - ast.TableOptionPlacementVoterConstraints: - if placementSettings == nil { - placementSettings = &model.PlacementSettings{} - } - err = SetDirectPlacementOpt(placementSettings, ast.PlacementOptionType(opt.Tp), opt.StrValue, opt.UintValue) case ast.TableOptionEngine: default: - err = errUnsupportedAlterTableOption + err = dbterror.ErrUnsupportedAlterTableOption } if err != nil { @@ -2825,8 +3177,8 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast } } - if placementPolicyRef != nil || placementSettings != nil { - err = d.AlterTablePlacement(sctx, ident, placementPolicyRef, placementSettings) + if placementPolicyRef != nil { + err = d.AlterTablePlacement(sctx, ident, placementPolicyRef) } case ast.AlterTableSetTiFlashReplica: err = d.AlterTableSetTiFlashReplica(sctx, ident, spec.TiFlashReplica) @@ -2835,13 +3187,13 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast case ast.AlterTableIndexInvisible: err = d.AlterIndexVisibility(sctx, ident, spec.IndexName, spec.Visibility) case ast.AlterTableAlterCheck: - sctx.GetSessionVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("ALTER CHECK")) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedConstraintCheck.GenWithStackByArgs("ALTER CHECK")) case ast.AlterTableDropCheck: - sctx.GetSessionVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("DROP CHECK")) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedConstraintCheck.GenWithStackByArgs("DROP CHECK")) case ast.AlterTableWithValidation: - sctx.GetSessionVars().StmtCtx.AppendWarning(errUnsupportedAlterTableWithValidation) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedAlterTableWithValidation) case ast.AlterTableWithoutValidation: - sctx.GetSessionVars().StmtCtx.AppendWarning(errUnsupportedAlterTableWithoutValidation) + sctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedAlterTableWithoutValidation) case ast.AlterTableAddStatistics: err = d.AlterTableAddStatistics(sctx, ident, spec.Statistics, spec.IfNotExists) case ast.AlterTableDropStatistics: @@ -2864,6 +3216,12 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast return errors.Trace(err) } } + if sctx.GetSessionVars().StmtCtx.MultiSchemaInfo != nil { + err = d.MultiSchemaChange(sctx, ident) + if err != nil { + return errors.Trace(err) + } + } return nil } @@ -2878,7 +3236,7 @@ func (d *ddl) RebaseAutoID(ctx sessionctx.Context, ident ast.Ident, newBase int6 case autoid.AutoRandomType: tbInfo := t.Meta() if tbInfo.AutoRandomBits == 0 { - return errors.Trace(ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomRebaseNotApplicable)) + return errors.Trace(dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomRebaseNotApplicable)) } var autoRandColTp types.FieldType for _, c := range tbInfo.Columns { @@ -2890,7 +3248,7 @@ func (d *ddl) RebaseAutoID(ctx sessionctx.Context, ident ast.Ident, newBase int6 layout := autoid.NewShardIDLayout(&autoRandColTp, tbInfo.AutoRandomBits) if layout.IncrementalMask()&newBase != newBase { errMsg := fmt.Sprintf(autoid.AutoRandomRebaseOverflow, newBase, layout.IncrementalBitsCapacity()) - return errors.Trace(ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)) + return errors.Trace(dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)) } actionType = model.ActionRebaseAutoRandomBase case autoid.RowIDAllocType: @@ -2898,20 +3256,28 @@ func (d *ddl) RebaseAutoID(ctx sessionctx.Context, ident ast.Ident, newBase int6 } if !force { - newBase, err = adjustNewBaseToNextGlobalID(ctx, t, tp, newBase) + newBaseTemp, err := adjustNewBaseToNextGlobalID(ctx, t, tp, newBase) if err != nil { return err } + if newBase != newBaseTemp { + ctx.GetSessionVars().StmtCtx.AppendWarning( + fmt.Errorf("Can't reset AUTO_INCREMENT to %d without FORCE option, using %d instead", + newBase, newBaseTemp, + )) + } + newBase = newBaseTemp } job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: actionType, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newBase, force}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -2940,14 +3306,14 @@ func (d *ddl) ShardRowID(ctx sessionctx.Context, tableIdent ast.Ident, uVal uint return errors.Trace(err) } if t.Meta().TempTableType != model.TempTableNone { - return ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits") + return dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits") } if uVal == t.Meta().ShardRowIDBits { // Nothing need to do. return nil } if uVal > 0 && t.Meta().HasClusteredIndex() { - return errUnsupportedShardRowIDBits + return dbterror.ErrUnsupportedShardRowIDBits } err = verifyNoOverflowShardBits(d.sessPool, t, uVal) if err != nil { @@ -2958,10 +3324,11 @@ func (d *ddl) ShardRowID(ctx sessionctx.Context, tableIdent ast.Ident, uVal uint SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{uVal}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -2983,14 +3350,14 @@ func checkUnsupportedColumnConstraint(col *ast.ColumnDef, ti ast.Ident) error { for _, constraint := range col.Options { switch constraint.Tp { case ast.ColumnOptionAutoIncrement: - return errUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint AUTO_INCREMENT when altering '%s.%s'", col.Name, ti.Schema, ti.Name) + return dbterror.ErrUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint AUTO_INCREMENT when altering '%s.%s'", col.Name, ti.Schema, ti.Name) case ast.ColumnOptionPrimaryKey: - return errUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint PRIMARY KEY when altering '%s.%s'", col.Name, ti.Schema, ti.Name) + return dbterror.ErrUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint PRIMARY KEY when altering '%s.%s'", col.Name, ti.Schema, ti.Name) case ast.ColumnOptionUniqKey: - return errUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint UNIQUE KEY when altering '%s.%s'", col.Name, ti.Schema, ti.Name) + return dbterror.ErrUnsupportedAddColumn.GenWithStack("unsupported add column '%s' constraint UNIQUE KEY when altering '%s.%s'", col.Name, ti.Schema, ti.Name) case ast.ColumnOptionAutoRandom: errMsg := fmt.Sprintf(autoid.AutoRandomAlterAddColumn, col.Name, ti.Schema, ti.Name) - return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } } @@ -3018,7 +3385,7 @@ func checkAndCreateNewColumn(ctx sessionctx.Context, ti ast.Ident, schema *model return nil, errors.Trace(err) } if utf8.RuneCountInString(colName) > mysql.MaxColumnNameLength { - return nil, ErrTooLongIdent.GenWithStackByArgs(colName) + return nil, dbterror.ErrTooLongIdent.GenWithStackByArgs(colName) } // If new column is a generated column, do validation. @@ -3031,7 +3398,7 @@ func checkAndCreateNewColumn(ctx sessionctx.Context, ti ast.Ident, schema *model } if option.Stored { - return nil, ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Adding generated stored column through ALTER TABLE") + return nil, dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Adding generated stored column through ALTER TABLE") } _, dependColNames := findDependedColumnNames(specNewColumn) @@ -3059,12 +3426,16 @@ func checkAndCreateNewColumn(ctx sessionctx.Context, ti ast.Ident, schema *model // known rows with specific sequence next value under current add column logic. // More explanation can refer: TestSequenceDefaultLogic's comment in sequence_test.go if option.Tp == ast.ColumnOptionDefaultValue { - _, isSeqExpr, err := tryToGetSequenceDefaultValue(option) - if err != nil { - return nil, errors.Trace(err) - } - if isSeqExpr { - return nil, errors.Trace(ErrAddColumnWithSequenceAsDefault.GenWithStackByArgs(specNewColumn.Name.Name.O)) + if f, ok := option.Expr.(*ast.FuncCallExpr); ok { + switch f.FnName.L { + case ast.NextVal: + if _, err := getSequenceDefaultValue(option); err != nil { + return nil, errors.Trace(err) + } + return nil, errors.Trace(dbterror.ErrAddColumnWithSequenceAsDefault.GenWithStackByArgs(specNewColumn.Name.Name.O)) + case ast.Rand: + return nil, errors.Trace(dbterror.ErrBinlogUnsafeSystemFunction.GenWithStackByArgs()) + } } } } @@ -3090,13 +3461,16 @@ func checkAndCreateNewColumn(ctx sessionctx.Context, ti ast.Ident, schema *model return nil, errors.Trace(err) } - originDefVal, err := generateOriginDefaultValue(col.ToInfo()) + originDefVal, err := generateOriginDefaultValue(col.ToInfo(), ctx) if err != nil { return nil, errors.Trace(err) } err = col.SetOriginDefaultValue(originDefVal) - return col, err + if err != nil { + return nil, errors.Trace(err) + } + return col, nil } // AddColumn will add a new column to the table. @@ -3117,96 +3491,22 @@ func (d *ddl) AddColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTab if col == nil { return nil } - - job := &model.Job{ - SchemaID: schema.ID, - TableID: t.Meta().ID, - SchemaName: schema.Name.L, - Type: model.ActionAddColumn, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{col, spec.Position, 0}, - } - - err = d.doDDLJob(ctx, job) - // column exists, but if_not_exists flags is true, so we ignore this error. - if infoschema.ErrColumnExists.Equal(err) && spec.IfNotExists { - ctx.GetSessionVars().StmtCtx.AppendNote(err) - return nil - } - err = d.callHookOnChanged(err) - return errors.Trace(err) -} - -// AddColumns will add multi new columns to the table. -func (d *ddl) AddColumns(ctx sessionctx.Context, ti ast.Ident, specs []*ast.AlterTableSpec) error { - schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) + err = checkPosition(t.Meta(), spec.Position) if err != nil { return errors.Trace(err) } - // Check all the columns at once. - addingColumnNames := make(map[string]bool) - dupColumnNames := make(map[string]bool) - for _, spec := range specs { - for _, specNewColumn := range spec.NewColumns { - if !addingColumnNames[specNewColumn.Name.Name.L] { - addingColumnNames[specNewColumn.Name.Name.L] = true - continue - } - if !spec.IfNotExists { - return errors.Trace(infoschema.ErrColumnExists.GenWithStackByArgs(specNewColumn.Name.Name.O)) - } - dupColumnNames[specNewColumn.Name.Name.L] = true - } - } - columns := make([]*table.Column, 0, len(addingColumnNames)) - positions := make([]*ast.ColumnPosition, 0, len(addingColumnNames)) - offsets := make([]int, 0, len(addingColumnNames)) - ifNotExists := make([]bool, 0, len(addingColumnNames)) - newColumnsCount := 0 - // Check the columns one by one. - for _, spec := range specs { - for _, specNewColumn := range spec.NewColumns { - if spec.IfNotExists && dupColumnNames[specNewColumn.Name.Name.L] { - err = infoschema.ErrColumnExists.GenWithStackByArgs(specNewColumn.Name.Name.O) - ctx.GetSessionVars().StmtCtx.AppendNote(err) - continue - } - col, err := checkAndCreateNewColumn(ctx, ti, schema, spec, t, specNewColumn) - if err != nil { - return errors.Trace(err) - } - // Added column has existed and if_not_exists flag is true. - if col == nil && spec.IfNotExists { - continue - } - columns = append(columns, col) - positions = append(positions, spec.Position) - offsets = append(offsets, 0) - ifNotExists = append(ifNotExists, spec.IfNotExists) - newColumnsCount++ - } - } - if newColumnsCount == 0 { - return nil - } - if err = checkAddColumnTooManyColumns(len(t.Cols()) + newColumnsCount); err != nil { - return errors.Trace(err) - } - job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, - Type: model.ActionAddColumns, + TableName: t.Meta().Name.L, + Type: model.ActionAddColumn, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{columns, positions, offsets, ifNotExists}, + Args: []interface{}{col, spec.Position, 0, spec.IfNotExists}, } - err = d.doDDLJob(ctx, job) - if err != nil { - return errors.Trace(err) - } + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -3226,7 +3526,7 @@ func (d *ddl) AddTablePartitions(ctx sessionctx.Context, ident ast.Ident, spec * meta := t.Meta() pi := meta.GetPartitionInfo() if pi == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } partInfo, err := buildAddedPartitionInfo(ctx, meta, spec) @@ -3244,24 +3544,29 @@ func (d *ddl) AddTablePartitions(ctx sessionctx.Context, ident ast.Ident, spec * tmp.Definitions = append(pi.Definitions, tmp.Definitions...) clonedMeta.Partition = &tmp if err := checkPartitionDefinitionConstraints(ctx, clonedMeta); err != nil { - if ErrSameNamePartition.Equal(err) && spec.IfNotExists { + if dbterror.ErrSameNamePartition.Equal(err) && spec.IfNotExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil } return errors.Trace(err) } + if err = handlePartitionPlacement(ctx, partInfo); err != nil { + return errors.Trace(err) + } + job := &model.Job{ SchemaID: schema.ID, TableID: meta.ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionAddTablePartition, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{partInfo}, } - err = d.doDDLJob(ctx, job) - if ErrSameNamePartition.Equal(err) && spec.IfNotExists { + err = d.DoDDLJob(ctx, job) + if dbterror.ErrSameNamePartition.Equal(err) && spec.IfNotExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil } @@ -3286,20 +3591,20 @@ func (d *ddl) CoalescePartitions(ctx sessionctx.Context, ident ast.Ident, spec * meta := t.Meta() if meta.GetPartitionInfo() == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } switch meta.Partition.Type { // We don't support coalesce partitions hash type partition now. case model.PartitionTypeHash: - return errors.Trace(ErrUnsupportedCoalescePartition) + return errors.Trace(dbterror.ErrUnsupportedCoalescePartition) // Key type partition cannot be constructed currently, ignoring it for now. case model.PartitionTypeKey: // Coalesce partition can only be used on hash/key partitions. default: - return errors.Trace(ErrCoalesceOnlyOnHashPartition) + return errors.Trace(dbterror.ErrCoalesceOnlyOnHashPartition) } return errors.Trace(err) @@ -3317,35 +3622,46 @@ func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, sp } meta := t.Meta() if meta.GetPartitionInfo() == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } - pids := make([]int64, len(spec.PartitionNames)) + var pids []int64 if spec.OnAllPartitions { pids = make([]int64, len(meta.GetPartitionInfo().Definitions)) for i, def := range meta.GetPartitionInfo().Definitions { pids[i] = def.ID } } else { - for i, name := range spec.PartitionNames { + // MySQL allows duplicate partition names in truncate partition + // so we filter them out through a hash + pidMap := make(map[int64]bool) + for _, name := range spec.PartitionNames { pid, err := tables.FindPartitionByName(meta, name.L) if err != nil { return errors.Trace(err) } - pids[i] = pid + pidMap[pid] = true } + // linter makezero does not handle changing pids to zero length, + // so create a new var and then assign to pids... + newPids := make([]int64, 0, len(pidMap)) + for pid := range pidMap { + newPids = append(newPids, pid) + } + pids = newPids } job := &model.Job{ SchemaID: schema.ID, TableID: meta.ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionTruncateTablePartition, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{pids}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { return errors.Trace(err) } @@ -3365,7 +3681,7 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec * } meta := t.Meta() if meta.GetPartitionInfo() == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } partNames := make([]string, len(spec.PartitionNames)) @@ -3374,7 +3690,7 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec * } err = checkDropTablePartition(meta, partNames) if err != nil { - if ErrDropPartitionNonExistent.Equal(err) && spec.IfExists { + if dbterror.ErrDropPartitionNonExistent.Equal(err) && spec.IfExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil } @@ -3385,14 +3701,15 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec * SchemaID: schema.ID, TableID: meta.ID, SchemaName: schema.Name.L, + TableName: meta.Name.L, Type: model.ActionDropTablePartition, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{partNames}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { - if ErrDropPartitionNonExistent.Equal(err) && spec.IfExists { + if dbterror.ErrDropPartitionNonExistent.Equal(err) && spec.IfExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil } @@ -3453,34 +3770,34 @@ func checkTableDefCompatible(source *model.TableInfo, target *model.TableInfo) e source.ShardRowIDBits != target.ShardRowIDBits || source.MaxShardRowIDBits != target.MaxShardRowIDBits || !checkTiFlashReplicaCompatible(source.TiFlashReplica, target.TiFlashReplica) { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } if len(source.Cols()) != len(target.Cols()) { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } // Col compatible check for i, sourceCol := range source.Cols() { targetCol := target.Cols()[i] if isVirtualGeneratedColumn(sourceCol) != isVirtualGeneratedColumn(targetCol) { - return ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Exchanging partitions for non-generated columns") + return dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Exchanging partitions for non-generated columns") } // It should strictyle compare expressions for generated columns if sourceCol.Name.L != targetCol.Name.L || sourceCol.Hidden != targetCol.Hidden || !checkFieldTypeCompatible(&sourceCol.FieldType, &targetCol.FieldType) || sourceCol.GeneratedExprString != targetCol.GeneratedExprString { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } if sourceCol.State != model.StatePublic || targetCol.State != model.StatePublic { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } if sourceCol.ID != targetCol.ID { - return ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("column: %s", sourceCol.Name)) + return dbterror.ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("column: %s", sourceCol.Name)) } } if len(source.Indices) != len(target.Indices) { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } for _, sourceIdx := range source.Indices { var compatIdx *model.IndexInfo @@ -3491,27 +3808,27 @@ func checkTableDefCompatible(source *model.TableInfo, target *model.TableInfo) e } // No match index if compatIdx == nil { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } // Index type is not compatible if sourceIdx.Tp != compatIdx.Tp || sourceIdx.Unique != compatIdx.Unique || sourceIdx.Primary != compatIdx.Primary { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } // The index column if len(sourceIdx.Columns) != len(compatIdx.Columns) { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } for i, sourceIdxCol := range sourceIdx.Columns { compatIdxCol := compatIdx.Columns[i] if sourceIdxCol.Length != compatIdxCol.Length || sourceIdxCol.Name.L != compatIdxCol.Name.L { - return errors.Trace(ErrTablesDifferentMetadata) + return errors.Trace(dbterror.ErrTablesDifferentMetadata) } } if sourceIdx.ID != compatIdx.ID { - return ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("index: %s", sourceIdx.Name)) + return dbterror.ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("index: %s", sourceIdx.Name)) } } @@ -3520,17 +3837,17 @@ func checkTableDefCompatible(source *model.TableInfo, target *model.TableInfo) e func checkExchangePartition(pt *model.TableInfo, nt *model.TableInfo) error { if nt.IsView() || nt.IsSequence() { - return errors.Trace(ErrCheckNoSuchTable) + return errors.Trace(dbterror.ErrCheckNoSuchTable) } if pt.GetPartitionInfo() == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } if nt.GetPartitionInfo() != nil { - return errors.Trace(ErrPartitionExchangePartTable.GenWithStackByArgs(nt.Name)) + return errors.Trace(dbterror.ErrPartitionExchangePartTable.GenWithStackByArgs(nt.Name)) } if nt.ForeignKeys != nil { - return errors.Trace(ErrPartitionExchangeForeignKey.GenWithStackByArgs(nt.Name)) + return errors.Trace(dbterror.ErrPartitionExchangeForeignKey.GenWithStackByArgs(nt.Name)) } // NOTE: if nt is temporary table, it should be checked @@ -3539,7 +3856,7 @@ func checkExchangePartition(pt *model.TableInfo, nt *model.TableInfo) error { func (d *ddl) ExchangeTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error { if !ctx.GetSessionVars().TiDBEnableExchangePartition { - ctx.GetSessionVars().StmtCtx.AppendWarning(errExchangePartitionDisabled) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrExchangePartitionDisabled) return nil } ptSchema, pt, err := d.getSchemaAndTableByIdent(ctx, ident) @@ -3580,12 +3897,13 @@ func (d *ddl) ExchangeTablePartition(ctx sessionctx.Context, ident ast.Ident, sp SchemaID: ntSchema.ID, TableID: ntMeta.ID, SchemaName: ntSchema.Name.L, + TableName: ntMeta.Name.L, Type: model.ActionExchangeTablePartition, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{defID, ptSchema.ID, ptMeta.ID, partName, spec.WithValidation}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { return errors.Trace(err) } @@ -3608,103 +3926,27 @@ func (d *ddl) DropColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTa return nil } colName := spec.OldColumnName.Name - err = checkDropVisibleColumnCnt(t, 1) + err = checkVisibleColumnCnt(t, 0, 1) if err != nil { return err } - var multiSchemaInfo *model.MultiSchemaInfo - if ctx.GetSessionVars().EnableChangeMultiSchema { - multiSchemaInfo = &model.MultiSchemaInfo{} - } - - job := &model.Job{ - SchemaID: schema.ID, - TableID: t.Meta().ID, - SchemaName: schema.Name.L, - Type: model.ActionDropColumn, - BinlogInfo: &model.HistoryInfo{}, - MultiSchemaInfo: multiSchemaInfo, - Args: []interface{}{colName}, - } - - err = d.doDDLJob(ctx, job) - // column not exists, but if_exists flags is true, so we ignore this error. - if ErrCantDropFieldOrKey.Equal(err) && spec.IfExists { - ctx.GetSessionVars().StmtCtx.AppendNote(err) - return nil - } - err = d.callHookOnChanged(err) - return errors.Trace(err) -} - -// DropColumns will drop multi-columns from the table, now we don't support drop the column with index covered. -func (d *ddl) DropColumns(ctx sessionctx.Context, ti ast.Ident, specs []*ast.AlterTableSpec) error { - schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) - if err != nil { - return errors.Trace(err) - } - tblInfo := t.Meta() - - dropingColumnNames := make(map[string]bool) - dupColumnNames := make(map[string]bool) - for _, spec := range specs { - if !dropingColumnNames[spec.OldColumnName.Name.L] { - dropingColumnNames[spec.OldColumnName.Name.L] = true - } else { - if spec.IfExists { - dupColumnNames[spec.OldColumnName.Name.L] = true - continue - } - return errors.Trace(ErrCantDropFieldOrKey.GenWithStack("column %s doesn't exist", spec.OldColumnName.Name.O)) - } - } - ifExists := make([]bool, 0, len(specs)) - colNames := make([]model.CIStr, 0, len(specs)) - for _, spec := range specs { - if spec.IfExists && dupColumnNames[spec.OldColumnName.Name.L] { - err = ErrCantDropFieldOrKey.GenWithStack("column %s doesn't exist", spec.OldColumnName.Name.L) - ctx.GetSessionVars().StmtCtx.AppendNote(err) - continue - } - isDropable, err := checkIsDroppableColumn(ctx, t, spec) - if err != nil { - return err - } - // Column can't drop and if_exists flag is true. - if !isDropable && spec.IfExists { - continue - } - colNames = append(colNames, spec.OldColumnName.Name) - ifExists = append(ifExists, spec.IfExists) - } - if len(colNames) == 0 { - return nil - } - if len(tblInfo.Columns) == len(colNames) { - return ErrCantRemoveAllFields.GenWithStack("can't drop all columns in table %s", - tblInfo.Name) - } - err = checkDropVisibleColumnCnt(t, len(colNames)) - if err != nil { - return err - } var multiSchemaInfo *model.MultiSchemaInfo if ctx.GetSessionVars().EnableChangeMultiSchema { multiSchemaInfo = &model.MultiSchemaInfo{} } - job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, - Type: model.ActionDropColumns, + TableName: t.Meta().Name.L, + Type: model.ActionDropColumn, BinlogInfo: &model.HistoryInfo{}, MultiSchemaInfo: multiSchemaInfo, - Args: []interface{}{colNames, ifExists}, + Args: []interface{}{colName, spec.IfExists}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { return errors.Trace(err) } @@ -3718,216 +3960,96 @@ func checkIsDroppableColumn(ctx sessionctx.Context, t table.Table, spec *ast.Alt colName := spec.OldColumnName.Name col := table.FindCol(t.VisibleCols(), colName.L) if col == nil { - err = ErrCantDropFieldOrKey.GenWithStackByArgs(colName) + err = dbterror.ErrCantDropFieldOrKey.GenWithStackByArgs(colName) if spec.IfExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return false, nil } - return false, err - } - - if err = isDroppableColumn(ctx.GetSessionVars().EnableChangeMultiSchema, tblInfo, colName); err != nil { - return false, errors.Trace(err) - } - // We don't support dropping column with PK handle covered now. - if col.IsPKHandleColumn(tblInfo) { - return false, errUnsupportedPKHandle - } - return true, nil -} - -func checkDropVisibleColumnCnt(t table.Table, columnCnt int) error { - tblInfo := t.Meta() - visibleColumCnt := 0 - for _, column := range tblInfo.Columns { - if !column.Hidden { - visibleColumCnt++ - } - if visibleColumCnt > columnCnt { - return nil - } - } - return ErrTableMustHaveColumns -} - -// checkModifyCharsetAndCollation returns error when the charset or collation is not modifiable. -// needRewriteCollationData is used when trying to modify the collation of a column, it is true when the column is with -// index because index of a string column is collation-aware. -func checkModifyCharsetAndCollation(toCharset, toCollate, origCharset, origCollate string, needRewriteCollationData bool) error { - if !charset.ValidCharsetAndCollation(toCharset, toCollate) { - return ErrUnknownCharacterSet.GenWithStack("Unknown character set: '%s', collation: '%s'", toCharset, toCollate) - } - - if needRewriteCollationData && collate.NewCollationEnabled() && !collate.CompatibleCollate(origCollate, toCollate) { - return errUnsupportedModifyCollation.GenWithStackByArgs(origCollate, toCollate) - } - - if (origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8MB4) || - (origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8) || - (origCharset == charset.CharsetUTF8MB4 && toCharset == charset.CharsetUTF8MB4) { - // TiDB only allow utf8 to be changed to utf8mb4, or changing the collation when the charset is utf8/utf8mb4. - return nil - } - - if toCharset != origCharset { - msg := fmt.Sprintf("charset from %s to %s", origCharset, toCharset) - return errUnsupportedModifyCharset.GenWithStackByArgs(msg) - } - if toCollate != origCollate { - msg := fmt.Sprintf("change collate from %s to %s", origCollate, toCollate) - return errUnsupportedModifyCharset.GenWithStackByArgs(msg) - } - return nil -} - -// CheckModifyTypeCompatible checks whether changes column type to another is compatible and can be changed. -// If types are compatible and can be directly changed, nil err will be returned; otherwise the types are incompatible. -// There are two cases when types incompatible: -// 1. returned canReorg == true: types can be changed by reorg -// 2. returned canReorg == false: type change not supported yet -func CheckModifyTypeCompatible(origin *types.FieldType, to *types.FieldType) (canReorg bool, err error) { - // Deal with the same type. - if origin.Tp == to.Tp { - if origin.Tp == mysql.TypeEnum || origin.Tp == mysql.TypeSet { - typeVar := "set" - if origin.Tp == mysql.TypeEnum { - typeVar = "enum" - } - if len(to.Elems) < len(origin.Elems) { - msg := fmt.Sprintf("the number of %s column's elements is less than the original: %d", typeVar, len(origin.Elems)) - return true, errUnsupportedModifyColumn.GenWithStackByArgs(msg) - } - for index, originElem := range origin.Elems { - toElem := to.Elems[index] - if originElem != toElem { - msg := fmt.Sprintf("cannot modify %s column value %s to %s", typeVar, originElem, toElem) - return true, errUnsupportedModifyColumn.GenWithStackByArgs(msg) - } - } - } - - if origin.Tp == mysql.TypeNewDecimal { - // Floating-point and fixed-point types also can be UNSIGNED. As with integer types, this attribute prevents - // negative values from being stored in the column. Unlike the integer types, the upper range of column values - // remains the same. - if to.Flen != origin.Flen || to.Decimal != origin.Decimal || mysql.HasUnsignedFlag(to.Flag) != mysql.HasUnsignedFlag(origin.Flag) { - msg := fmt.Sprintf("decimal change from decimal(%d, %d) to decimal(%d, %d)", origin.Flen, origin.Decimal, to.Flen, to.Decimal) - return true, errUnsupportedModifyColumn.GenWithStackByArgs(msg) - } - } - - needReorg, reason := needReorgToChange(origin, to) - if !needReorg { - return false, nil - } - return true, errUnsupportedModifyColumn.GenWithStackByArgs(reason) - } - - // Deal with the different type. - if !checkTypeChangeSupported(origin, to) { - unsupportedMsg := fmt.Sprintf("change from original type %v to %v is currently unsupported yet", origin.CompactStr(), to.CompactStr()) - return false, errUnsupportedModifyColumn.GenWithStackByArgs(unsupportedMsg) - } - - // Check if different type can directly convert and no need to reorg. - stringToString := types.IsString(origin.Tp) && types.IsString(to.Tp) - integerToInteger := mysql.IsIntegerType(origin.Tp) && mysql.IsIntegerType(to.Tp) - if stringToString || integerToInteger { - needReorg, reason := needReorgToChange(origin, to) - if !needReorg { - return false, nil - } - return true, errUnsupportedModifyColumn.GenWithStackByArgs(reason) + return false, err } - - notCompatibleMsg := fmt.Sprintf("type %v not match origin %v", to.CompactStr(), origin.CompactStr()) - return true, errUnsupportedModifyColumn.GenWithStackByArgs(notCompatibleMsg) -} - -func needReorgToChange(origin *types.FieldType, to *types.FieldType) (needReorg bool, reasonMsg string) { - toFlen := to.Flen - originFlen := origin.Flen - if mysql.IsIntegerType(to.Tp) && mysql.IsIntegerType(origin.Tp) { - // For integers, we should ignore the potential display length represented by flen, using - // the default flen of the type. - originFlen, _ = mysql.GetDefaultFieldLengthAndDecimal(origin.Tp) - toFlen, _ = mysql.GetDefaultFieldLengthAndDecimal(to.Tp) + if err = isDroppableColumn(ctx.GetSessionVars().EnableChangeMultiSchema, tblInfo, colName); err != nil { + return false, errors.Trace(err) } - - if convertBetweenCharAndVarchar(origin.Tp, to.Tp) { - return true, "conversion between char and varchar string needs reorganization" + // We don't support dropping column with PK handle covered now. + if col.IsPKHandleColumn(tblInfo) { + return false, dbterror.ErrUnsupportedPKHandle } + return true, nil +} - if toFlen > 0 && toFlen != originFlen { - if toFlen < originFlen { - return true, fmt.Sprintf("length %d is less than origin %d", toFlen, originFlen) - } - - // Due to the behavior of padding \x00 at binary type, we need to reorg when binary length changed - isBinaryType := func(tp *types.FieldType) bool { return tp.Tp == mysql.TypeString && types.IsBinaryStr(tp) } - if isBinaryType(origin) && isBinaryType(to) { - return true, "can't change binary types of different length" +func checkVisibleColumnCnt(t table.Table, addCnt, dropCnt int) error { + tblInfo := t.Meta() + visibleColumCnt := 0 + for _, column := range tblInfo.Columns { + if !column.Hidden { + visibleColumCnt++ } } - if to.Decimal > 0 && to.Decimal < origin.Decimal { - return true, fmt.Sprintf("decimal %d is less than origin %d", to.Decimal, origin.Decimal) + if visibleColumCnt+addCnt > dropCnt { + return nil } - if mysql.HasUnsignedFlag(origin.Flag) != mysql.HasUnsignedFlag(to.Flag) { - return true, "can't change unsigned integer to signed or vice versa" + if len(tblInfo.Columns)-visibleColumCnt > 0 { + // There are only invisible columns. + return dbterror.ErrTableMustHaveColumns } - return false, "" + return dbterror.ErrCantRemoveAllFields } -func checkTypeChangeSupported(origin *types.FieldType, to *types.FieldType) bool { - if (types.IsTypeTime(origin.Tp) || origin.Tp == mysql.TypeDuration || origin.Tp == mysql.TypeYear || - types.IsString(origin.Tp) || origin.Tp == mysql.TypeJSON) && - to.Tp == mysql.TypeBit { - // TODO: Currently date/datetime/timestamp/time/year/string/json data type cast to bit are not compatible with mysql, should fix here after compatible. - return false +// checkModifyCharsetAndCollation returns error when the charset or collation is not modifiable. +// needRewriteCollationData is used when trying to modify the collation of a column, it is true when the column is with +// index because index of a string column is collation-aware. +func checkModifyCharsetAndCollation(toCharset, toCollate, origCharset, origCollate string, needRewriteCollationData bool) error { + if !charset.ValidCharsetAndCollation(toCharset, toCollate) { + return dbterror.ErrUnknownCharacterSet.GenWithStack("Unknown character set: '%s', collation: '%s'", toCharset, toCollate) } - if (types.IsTypeTime(origin.Tp) || origin.Tp == mysql.TypeDuration || origin.Tp == mysql.TypeYear || - origin.Tp == mysql.TypeNewDecimal || origin.Tp == mysql.TypeFloat || origin.Tp == mysql.TypeDouble || origin.Tp == mysql.TypeJSON || origin.Tp == mysql.TypeBit) && - (to.Tp == mysql.TypeEnum || to.Tp == mysql.TypeSet) { - // TODO: Currently date/datetime/timestamp/time/year/decimal/float/double/json/bit cast to enum/set are not support yet, should fix here after supported. - return false + if needRewriteCollationData && collate.NewCollationEnabled() && !collate.CompatibleCollate(origCollate, toCollate) { + return dbterror.ErrUnsupportedModifyCollation.GenWithStackByArgs(origCollate, toCollate) } - if (origin.Tp == mysql.TypeEnum || origin.Tp == mysql.TypeSet || origin.Tp == mysql.TypeBit || - origin.Tp == mysql.TypeNewDecimal || origin.Tp == mysql.TypeFloat || origin.Tp == mysql.TypeDouble) && - (types.IsTypeTime(to.Tp)) { - // TODO: Currently enum/set/bit/decimal/float/double cast to date/datetime/timestamp type are not support yet, should fix here after supported. - return false + if (origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8MB4) || + (origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8) || + (origCharset == charset.CharsetUTF8MB4 && toCharset == charset.CharsetUTF8MB4) { + // TiDB only allow utf8 to be changed to utf8mb4, or changing the collation when the charset is utf8/utf8mb4. + return nil } - if (origin.Tp == mysql.TypeEnum || origin.Tp == mysql.TypeSet || origin.Tp == mysql.TypeBit) && - to.Tp == mysql.TypeDuration { - // TODO: Currently enum/set/bit cast to time are not support yet, should fix here after supported. - return false + if toCharset != origCharset { + msg := fmt.Sprintf("charset from %s to %s", origCharset, toCharset) + return dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs(msg) } - - return true + if toCollate != origCollate { + msg := fmt.Sprintf("change collate from %s to %s", origCollate, toCollate) + return dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs(msg) + } + return nil } // checkModifyTypes checks if the 'origin' type can be modified to 'to' type no matter directly change // or change by reorg. It returns error if the two types are incompatible and correlated change are not // supported. However, even the two types can be change, if the "origin" type contains primary key, error will be returned. func checkModifyTypes(ctx sessionctx.Context, origin *types.FieldType, to *types.FieldType, needRewriteCollationData bool) error { - canReorg, err := CheckModifyTypeCompatible(origin, to) + canReorg, err := types.CheckModifyTypeCompatible(origin, to) if err != nil { if !canReorg { - return errors.Trace(err) + return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(err.Error())) } if mysql.HasPriKeyFlag(origin.Flag) { msg := "this column has primary key flag" - return errUnsupportedModifyColumn.GenWithStackByArgs(msg) + return dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) } } err = checkModifyCharsetAndCollation(to.Charset, to.Collate, origin.Charset, origin.Collate, needRewriteCollationData) - // column type change can handle the charset change between these two types in the process of the reorg. - if err != nil && errUnsupportedModifyCharset.Equal(err) && canReorg { - return nil + + if err != nil { + if to.Charset == charset.CharsetGBK || origin.Charset == charset.CharsetGBK { + return errors.Trace(err) + } + // column type change can handle the charset change between these two types in the process of the reorg. + if dbterror.ErrUnsupportedModifyCharset.Equal(err) && canReorg { + return nil + } } return errors.Trace(err) } @@ -3936,7 +4058,7 @@ func setDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.Colu hasDefaultValue := false value, isSeqExpr, err := getDefaultValue(ctx, col, option) if err != nil { - return hasDefaultValue, errors.Trace(err) + return false, errors.Trace(err) } if isSeqExpr { if err := checkSequenceDefaultValue(col); err != nil { @@ -4014,15 +4136,15 @@ func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []* case ast.ColumnOptionAutoIncrement: col.Flag |= mysql.AutoIncrementFlag case ast.ColumnOptionPrimaryKey, ast.ColumnOptionUniqKey: - return errUnsupportedModifyColumn.GenWithStack("can't change column constraint - %v", opt.Tp) + return dbterror.ErrUnsupportedModifyColumn.GenWithStack("can't change column constraint - %v", opt.Tp) case ast.ColumnOptionOnUpdate: // TODO: Support other time functions. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { if !expression.IsValidCurrentTimestampExpr(opt.Expr, &col.FieldType) { - return ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) + return dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } } else { - return ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) + return dbterror.ErrInvalidOnUpdate.GenWithStackByArgs(col.Name) } col.Flag |= mysql.OnUpdateNowFlag setOnUpdateNow = true @@ -4042,15 +4164,15 @@ func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []* case ast.ColumnOptionCollate: col.Collate = opt.StrValue case ast.ColumnOptionReference: - return errors.Trace(errUnsupportedModifyColumn.GenWithStackByArgs("can't modify with references")) + return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't modify with references")) case ast.ColumnOptionFulltext: - return errors.Trace(errUnsupportedModifyColumn.GenWithStackByArgs("can't modify with full text")) + return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't modify with full text")) case ast.ColumnOptionCheck: - return errors.Trace(errUnsupportedModifyColumn.GenWithStackByArgs("can't modify with check")) + return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't modify with check")) // Ignore ColumnOptionAutoRandom. It will be handled later. case ast.ColumnOptionAutoRandom: default: - return errors.Trace(errUnsupportedModifyColumn.GenWithStackByArgs(fmt.Sprintf("unknown column option type: %d", opt.Tp))) + return errors.Trace(dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(fmt.Sprintf("unknown column option type: %d", opt.Tp))) } } @@ -4100,7 +4222,7 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex } newColName := specNewColumn.Name.Name if newColName.L == model.ExtraHandleName.L { - return nil, ErrWrongColumnName.GenWithStackByArgs(newColName.L) + return nil, dbterror.ErrWrongColumnName.GenWithStackByArgs(newColName.L) } // If we want to rename the column name, we need to check whether it already exists. if newColName.L != originalColName.L { @@ -4114,7 +4236,7 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex // which will be done by `processColumnOptions` later. if specNewColumn.Tp == nil { // Make sure the column definition is simple field type. - return nil, errors.Trace(errUnsupportedModifyColumn) + return nil, errors.Trace(dbterror.ErrUnsupportedModifyColumn) } if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp); err != nil { @@ -4162,7 +4284,7 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex } } - if err = setCharsetCollationFlenDecimal(&newCol.FieldType, chs, coll); err != nil { + if err = setCharsetCollationFlenDecimal(&newCol.FieldType, newCol.Name.O, chs, coll, sctx.GetSessionVars()); err != nil { return nil, errors.Trace(err) } @@ -4171,7 +4293,7 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex // For now we strongly ban the all column type change for column with foreign key. // Actually MySQL support change column with foreign key from varchar(m) -> varchar(m+t) and t > 0. if newCol.Tp != col.Tp || newCol.Flen != col.Flen || newCol.Decimal != col.Decimal { - return nil, errFKIncompatibleColumns.GenWithStackByArgs(originalColName, fkInfo.Name) + return nil, dbterror.ErrFKIncompatibleColumns.GenWithStackByArgs(originalColName, fkInfo.Name) } } @@ -4190,26 +4312,27 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex if err = checkModifyTypes(sctx, &col.FieldType, &newCol.FieldType, isColumnWithIndex(col.Name.L, t.Meta().Indices)); err != nil { if strings.Contains(err.Error(), "Unsupported modifying collation") { colErrMsg := "Unsupported modifying collation of column '%s' from '%s' to '%s' when index is defined on it." - err = errUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, newCol.Collate) + err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, newCol.Collate) } return nil, errors.Trace(err) } - if needChangeColumnData(col.ColumnInfo, newCol.ColumnInfo) { + needChangeColData := needChangeColumnData(col.ColumnInfo, newCol.ColumnInfo) + if needChangeColData { if err = isGeneratedRelatedColumn(t.Meta(), newCol.ColumnInfo, col.ColumnInfo); err != nil { return nil, errors.Trace(err) } if t.Meta().Partition != nil { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("table is partition table") + return nil, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("table is partition table") } } // We don't support modifying column from not_auto_increment to auto_increment. if !mysql.HasAutoIncrementFlag(col.Flag) && mysql.HasAutoIncrementFlag(newCol.Flag) { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("can't set auto_increment") + return nil, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't set auto_increment") } // Disallow modifying column from auto_increment to not auto_increment if the session variable `AllowRemoveAutoInc` is false. if !sctx.GetSessionVars().AllowRemoveAutoInc && mysql.HasAutoIncrementFlag(col.Flag) && !mysql.HasAutoIncrementFlag(newCol.Flag) { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("can't remove auto_increment without @@tidb_allow_remove_auto_inc enabled") + return nil, dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs("can't remove auto_increment without @@tidb_allow_remove_auto_inc enabled") } // We support modifying the type definitions of 'null' to 'not null' now. @@ -4236,19 +4359,22 @@ func (d *ddl) getModifiableColumnJob(ctx context.Context, sctx sessionctx.Contex return nil, errors.Trace(err) } + tzName, tzOffset := ddlutil.GetTimeZone(sctx) job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionModifyColumn, BinlogInfo: &model.HistoryInfo{}, ReorgMeta: &model.DDLReorgMeta{ SQLMode: sctx.GetSessionVars().SQLMode, Warnings: make(map[errors.ErrorID]*terror.Error), WarningsCount: make(map[errors.ErrorID]int64), - Location: sctx.GetSessionVars().Location(), + Location: &model.TimeZoneLocation{Name: tzName, Offset: tzOffset}, }, - Args: []interface{}{&newCol, originalColName, spec.Position, modifyColumnTp, newAutoRandBits}, + CtxVars: []interface{}{needChangeColData}, + Args: []interface{}{&newCol.ColumnInfo, originalColName, spec.Position, modifyColumnTp, newAutoRandBits}, } return job, nil } @@ -4320,7 +4446,7 @@ func checkIndexInModifiableColumns(columns []*model.ColumnInfo, idxColumns []*mo for _, ic := range idxColumns { col := model.FindColumnInfo(columns, ic.Name.L) if col == nil { - return errKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", ic.Name) + return dbterror.ErrKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", ic.Name) } prefixLength := types.UnspecifiedLength @@ -4353,38 +4479,38 @@ func checkAutoRandom(tableInfo *model.TableInfo, originCol *table.Column, specNe if addingAutoRandom { convFromAutoInc := mysql.HasAutoIncrementFlag(originCol.Flag) && originCol.IsPKHandleColumn(tableInfo) if !convFromAutoInc { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterChangeFromAutoInc) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterChangeFromAutoInc) } } if autoid.MaxAutoRandomBits < newRandBits { errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg, autoid.MaxAutoRandomBits, newRandBits, specNewColumn.Name.Name.O) - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(errMsg) } // increasing auto_random shard bits is allowed. case oldRandBits > newRandBits: if newRandBits == 0 { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterErrMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterErrMsg) } - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomDecreaseBitErrMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomDecreaseBitErrMsg) } modifyingAutoRandCol := oldRandBits > 0 || newRandBits > 0 if modifyingAutoRandCol { // Disallow changing the column field type. if originCol.Tp != specNewColumn.Tp.Tp { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomModifyColTypeErrMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomModifyColTypeErrMsg) } if originCol.Tp != mysql.TypeLonglong { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(originCol.Tp))) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(autoid.AutoRandomOnNonBigIntColumn, types.TypeStr(originCol.Tp))) } // Disallow changing from auto_random to auto_increment column. if containsColumnOption(specNewColumn, ast.ColumnOptionAutoIncrement) { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg) } // Disallow specifying a default value on auto_random column. if containsColumnOption(specNewColumn, ast.ColumnOptionDefaultValue) { - return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) + return 0, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) } } return newRandBits, nil @@ -4396,16 +4522,16 @@ func checkAutoRandom(tableInfo *model.TableInfo, originCol *table.Column, specNe func (d *ddl) ChangeColumn(ctx context.Context, sctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error { specNewColumn := spec.NewColumns[0] if len(specNewColumn.Name.Schema.O) != 0 && ident.Schema.L != specNewColumn.Name.Schema.L { - return ErrWrongDBName.GenWithStackByArgs(specNewColumn.Name.Schema.O) + return dbterror.ErrWrongDBName.GenWithStackByArgs(specNewColumn.Name.Schema.O) } if len(spec.OldColumnName.Schema.O) != 0 && ident.Schema.L != spec.OldColumnName.Schema.L { - return ErrWrongDBName.GenWithStackByArgs(spec.OldColumnName.Schema.O) + return dbterror.ErrWrongDBName.GenWithStackByArgs(spec.OldColumnName.Schema.O) } if len(specNewColumn.Name.Table.O) != 0 && ident.Name.L != specNewColumn.Name.Table.L { - return ErrWrongTableName.GenWithStackByArgs(specNewColumn.Name.Table.O) + return dbterror.ErrWrongTableName.GenWithStackByArgs(specNewColumn.Name.Table.O) } if len(spec.OldColumnName.Table.O) != 0 && ident.Name.L != spec.OldColumnName.Table.L { - return ErrWrongTableName.GenWithStackByArgs(spec.OldColumnName.Table.O) + return dbterror.ErrWrongTableName.GenWithStackByArgs(spec.OldColumnName.Table.O) } job, err := d.getModifiableColumnJob(ctx, sctx, ident, spec.OldColumnName.Name, spec) @@ -4417,7 +4543,7 @@ func (d *ddl) ChangeColumn(ctx context.Context, sctx sessionctx.Context, ident a return errors.Trace(err) } - err = d.doDDLJob(sctx, job) + err = d.DoDDLJob(sctx, job) // column not exists, but if_exists flags is true, so we ignore this error. if infoschema.ErrColumnNotExists.Equal(err) && spec.IfExists { sctx.GetSessionVars().StmtCtx.AppendNote(err) @@ -4435,7 +4561,7 @@ func (d *ddl) RenameColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Al return nil } if newColName.L == model.ExtraHandleName.L { - return ErrWrongColumnName.GenWithStackByArgs(newColName.L) + return dbterror.ErrWrongColumnName.GenWithStackByArgs(newColName.L) } schema, tbl, err := d.getSchemaAndTableByIdent(ctx, ident) @@ -4455,7 +4581,7 @@ func (d *ddl) RenameColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Al } if fkInfo := getColumnForeignKeyInfo(oldColName.L, tbl.Meta().ForeignKeys); fkInfo != nil { - return errFKIncompatibleColumns.GenWithStackByArgs(oldColName, fkInfo.Name) + return dbterror.ErrFKIncompatibleColumns.GenWithStackByArgs(oldColName, fkInfo.Name) } // Check generated expression. @@ -4467,30 +4593,33 @@ func (d *ddl) RenameColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Al for _, name := range dependedColNames { if name.Name.L == oldColName.L { if col.Hidden { - return errDependentByFunctionalIndex.GenWithStackByArgs(oldColName.O) + return dbterror.ErrDependentByFunctionalIndex.GenWithStackByArgs(oldColName.O) } - return errDependentByGeneratedColumn.GenWithStackByArgs(oldColName.O) + return dbterror.ErrDependentByGeneratedColumn.GenWithStackByArgs(oldColName.O) } } } + tzName, tzOffset := ddlutil.GetTimeZone(ctx) + newCol := oldCol.Clone() newCol.Name = newColName job := &model.Job{ SchemaID: schema.ID, TableID: tbl.Meta().ID, SchemaName: schema.Name.L, + TableName: tbl.Meta().Name.L, Type: model.ActionModifyColumn, BinlogInfo: &model.HistoryInfo{}, ReorgMeta: &model.DDLReorgMeta{ SQLMode: ctx.GetSessionVars().SQLMode, Warnings: make(map[errors.ErrorID]*terror.Error), WarningsCount: make(map[errors.ErrorID]int64), - Location: ctx.GetSessionVars().Location(), + Location: &model.TimeZoneLocation{Name: tzName, Offset: tzOffset}, }, - Args: []interface{}{&newCol, oldColName, spec.Position, 0}, + Args: []interface{}{&newCol, oldColName, spec.Position, 0, 0}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4500,10 +4629,10 @@ func (d *ddl) RenameColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Al func (d *ddl) ModifyColumn(ctx context.Context, sctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error { specNewColumn := spec.NewColumns[0] if len(specNewColumn.Name.Schema.O) != 0 && ident.Schema.L != specNewColumn.Name.Schema.L { - return ErrWrongDBName.GenWithStackByArgs(specNewColumn.Name.Schema.O) + return dbterror.ErrWrongDBName.GenWithStackByArgs(specNewColumn.Name.Schema.O) } if len(specNewColumn.Name.Table.O) != 0 && ident.Name.L != specNewColumn.Name.Table.L { - return ErrWrongTableName.GenWithStackByArgs(specNewColumn.Name.Table.O) + return dbterror.ErrWrongTableName.GenWithStackByArgs(specNewColumn.Name.Table.O) } originalColName := specNewColumn.Name.Name @@ -4516,7 +4645,7 @@ func (d *ddl) ModifyColumn(ctx context.Context, sctx sessionctx.Context, ident a return errors.Trace(err) } - err = d.doDDLJob(sctx, job) + err = d.DoDDLJob(sctx, job) // column not exists, but if_exists flags is true, so we ignore this error. if infoschema.ErrColumnNotExists.Equal(err) && spec.IfExists { sctx.GetSessionVars().StmtCtx.AppendNote(err) @@ -4540,10 +4669,11 @@ func (d *ddl) AlterColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt colName := specNewColumn.Name.Name // Check whether alter column has existed. - col := table.FindCol(t.Cols(), colName.L) - if col == nil { - return ErrBadField.GenWithStackByArgs(colName, ident.Name) + oldCol := table.FindCol(t.Cols(), colName.L) + if oldCol == nil { + return dbterror.ErrBadField.GenWithStackByArgs(colName, ident.Name) } + col := table.ToColumn(oldCol.Clone()) // Clean the NoDefaultValueFlag value. col.Flag &= ^mysql.NoDefaultValueFlag @@ -4555,7 +4685,7 @@ func (d *ddl) AlterColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt setNoDefaultValueFlag(col, false) } else { if IsAutoRandomColumnID(t.Meta(), col.ID) { - return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) + return dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg) } hasDefaultValue, err := setDefaultValue(ctx, col, specNewColumn.Options[0]) if err != nil { @@ -4570,12 +4700,13 @@ func (d *ddl) AlterColumn(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionSetDefaultValue, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{col}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4597,12 +4728,13 @@ func (d *ddl) AlterTableComment(ctx sessionctx.Context, ident ast.Ident, spec *a SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionModifyTableComment, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{spec.Comment}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4618,12 +4750,13 @@ func (d *ddl) AlterTableAutoIDCache(ctx sessionctx.Context, ident ast.Ident, new SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionModifyTableAutoIdCache, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newCache}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4632,7 +4765,7 @@ func (d *ddl) AlterTableAutoIDCache(ctx sessionctx.Context, ident ast.Ident, new func (d *ddl) AlterTableCharsetAndCollate(ctx sessionctx.Context, ident ast.Ident, toCharset, toCollate string, needsOverwriteCols bool) error { // use the last one. if toCharset == "" && toCollate == "" { - return ErrUnknownCharacterSet.GenWithStackByArgs(toCharset) + return dbterror.ErrUnknownCharacterSet.GenWithStackByArgs(toCharset) } is := d.infoCache.GetLatest() @@ -4670,15 +4803,29 @@ func (d *ddl) AlterTableCharsetAndCollate(ctx sessionctx.Context, ident ast.Iden SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionModifyTableCharsetAndCollate, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{toCharset, toCollate, needsOverwriteCols}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } +func shouldModifyTiFlashReplica(tbReplicaInfo *model.TiFlashReplicaInfo, replicaInfo *ast.TiFlashReplicaSpec) bool { + if tbReplicaInfo != nil && tbReplicaInfo.Count == replicaInfo.Count && + len(tbReplicaInfo.LocationLabels) == len(replicaInfo.Labels) { + for i, label := range tbReplicaInfo.LocationLabels { + if replicaInfo.Labels[i] != label { + return true + } + } + return false + } + return true +} + // AlterTableSetTiFlashReplica sets the TiFlash replicas info. func (d *ddl) AlterTableSetTiFlashReplica(ctx sessionctx.Context, ident ast.Ident, replicaInfo *ast.TiFlashReplicaSpec) error { schema, tb, err := d.getSchemaAndTableByIdent(ctx, ident) @@ -4687,32 +4834,22 @@ func (d *ddl) AlterTableSetTiFlashReplica(ctx sessionctx.Context, ident ast.Iden } // Ban setting replica count for tables in system database. if util.IsMemOrSysDB(schema.Name.L) { - return errors.Trace(errUnsupportedAlterReplicaForSysTable) + return errors.Trace(dbterror.ErrUnsupportedAlterReplicaForSysTable) } else if tb.Meta().TempTableType != model.TempTableNone { - return ErrOptOnTemporaryTable.GenWithStackByArgs("set tiflash replica") + return dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("set tiflash replica") } // Ban setting replica count for tables which has charset not supported by TiFlash for _, col := range tb.Cols() { _, ok := charset.TiFlashSupportedCharsets[col.Charset] if !ok { - return errAlterReplicaForUnsupportedCharsetTable.GenWithStackByArgs(col.Charset) + return dbterror.ErrAlterReplicaForUnsupportedCharsetTable.GenWithStackByArgs(col.Charset) } } tbReplicaInfo := tb.Meta().TiFlashReplica - if tbReplicaInfo != nil && tbReplicaInfo.Count == replicaInfo.Count && - len(tbReplicaInfo.LocationLabels) == len(replicaInfo.Labels) { - changed := false - for i, label := range tbReplicaInfo.LocationLabels { - if replicaInfo.Labels[i] != label { - changed = true - break - } - } - if !changed { - return nil - } + if !shouldModifyTiFlashReplica(tbReplicaInfo, replicaInfo) { + return nil } err = checkTiFlashReplicaCount(ctx, replicaInfo.Count) @@ -4724,11 +4861,12 @@ func (d *ddl) AlterTableSetTiFlashReplica(ctx sessionctx.Context, ident ast.Iden SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionSetTiFlashReplica, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{*replicaInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4833,11 +4971,12 @@ func (d *ddl) UpdateTableReplicaInfo(ctx sessionctx.Context, physicalID int64, a SchemaID: db.ID, TableID: tb.Meta().ID, SchemaName: db.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionUpdateTiFlashReplicaStatus, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{available, physicalID}, } - err := d.doDDLJob(ctx, job) + err := d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4901,7 +5040,7 @@ func checkAlterTableCharset(tblInfo *model.TableInfo, dbInfo *model.DBInfo, toCh if err = checkModifyCharsetAndCollation(toCharset, toCollate, col.Charset, col.Collate, isColumnWithIndex(col.Name.L, tblInfo.Indices)); err != nil { if strings.Contains(err.Error(), "Unsupported modifying collation") { colErrMsg := "Unsupported converting collation of column '%s' from '%s' to '%s' when index is defined on it." - err = errUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, toCollate) + err = dbterror.ErrUnsupportedModifyCollation.GenWithStack(colErrMsg, col.Name.L, col.Collate, toCollate) } return doNothing, err } @@ -4924,7 +5063,7 @@ func (d *ddl) RenameIndex(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name)) } if tb.Meta().TableCacheStatusType != model.TableCacheStatusDisable { - return errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Rename Index")) + return errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Rename Index")) } duplicate, err := validateRenameIndex(spec.FromKey, spec.ToKey, tb.Meta()) if duplicate { @@ -4938,12 +5077,13 @@ func (d *ddl) RenameIndex(ctx sessionctx.Context, ident ast.Ident, spec *ast.Alt SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionRenameIndex, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{spec.FromKey, spec.ToKey}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -4961,16 +5101,20 @@ func (d *ddl) DropTable(ctx sessionctx.Context, ti ast.Ident) (err error) { if tb.Meta().IsSequence() { return infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name) } + if tb.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Drop Table") + } job := &model.Job{ SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionDropTable, BinlogInfo: &model.HistoryInfo{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) if err != nil { return errors.Trace(err) @@ -4992,18 +5136,19 @@ func (d *ddl) DropView(ctx sessionctx.Context, ti ast.Ident) (err error) { } if !tb.Meta().IsView() { - return ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "VIEW") + return dbterror.ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "VIEW") } job := &model.Job{ SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionDropView, BinlogInfo: &model.HistoryInfo{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5016,6 +5161,10 @@ func (d *ddl) TruncateTable(ctx sessionctx.Context, ti ast.Ident) error { if tb.Meta().IsView() || tb.Meta().IsSequence() { return infoschema.ErrTableNotExists.GenWithStackByArgs(schema.Name.O, tb.Meta().Name.O) } + if tb.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Truncate Table") + } + genIDs, err := d.genGlobalIDs(1) if err != nil { return errors.Trace(err) @@ -5025,6 +5174,7 @@ func (d *ddl) TruncateTable(ctx sessionctx.Context, ti ast.Ident) error { SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionTruncateTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newTableID}, @@ -5036,7 +5186,7 @@ func (d *ddl) TruncateTable(ctx sessionctx.Context, ti ast.Ident) error { // but the session was killed before return. ctx.AddTableLock([]model.TableLockTpInfo{{SchemaID: schema.ID, TableID: newTableID, Tp: tb.Meta().Lock.Tp}}) } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) if err != nil { if config.TableLockEnabled() { @@ -5069,22 +5219,30 @@ func (d *ddl) RenameTable(ctx sessionctx.Context, oldIdent, newIdent ast.Ident, return nil } + if tbl, ok := is.TableByID(tableID); ok { + if tbl.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + return errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Rename Table")) + } + } + job := &model.Job{ SchemaID: schemas[1].ID, TableID: tableID, SchemaName: schemas[1].Name.L, + TableName: oldIdent.Name.L, Type: model.ActionRenameTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{schemas[0].ID, newIdent.Name, schemas[0].Name}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } func (d *ddl) RenameTables(ctx sessionctx.Context, oldIdents, newIdents []ast.Ident, isAlterTable bool) error { is := d.GetInfoSchemaWithInterceptor(ctx) + oldTableNames := make([]*model.CIStr, 0, len(oldIdents)) tableNames := make([]*model.CIStr, 0, len(oldIdents)) oldSchemaIDs := make([]int64, 0, len(oldIdents)) newSchemaIDs := make([]int64, 0, len(oldIdents)) @@ -5101,7 +5259,15 @@ func (d *ddl) RenameTables(ctx sessionctx.Context, oldIdents, newIdents []ast.Id if err != nil { return err } + + if t, ok := is.TableByID(tableID); ok { + if t.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + return errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Rename Tables")) + } + } + tableIDs = append(tableIDs, tableID) + oldTableNames = append(oldTableNames, &oldIdents[i].Name) tableNames = append(tableNames, &newIdents[i].Name) oldSchemaIDs = append(oldSchemaIDs, schemas[0].ID) newSchemaIDs = append(newSchemaIDs, schemas[1].ID) @@ -5114,10 +5280,10 @@ func (d *ddl) RenameTables(ctx sessionctx.Context, oldIdents, newIdents []ast.Id SchemaName: schemas[1].Name.L, Type: model.ActionRenameTables, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{oldSchemaIDs, newSchemaIDs, tableNames, tableIDs, oldSchemaNames}, + Args: []interface{}{oldSchemaIDs, newSchemaIDs, tableNames, tableIDs, oldSchemaNames, oldTableNames}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5131,7 +5297,7 @@ func extractTblInfos(is infoschema.InfoSchema, oldIdent, newIdent ast.Ident, isA if tableExists(is, newIdent, tables) { return nil, 0, infoschema.ErrTableExists.GenWithStackByArgs(newIdent) } - return nil, 0, errFileNotFound.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name) + return nil, 0, infoschema.ErrTableNotExists.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name) } if !tableExists(is, oldIdent, tables) { if isAlterTable { @@ -5140,7 +5306,7 @@ func extractTblInfos(is infoschema.InfoSchema, oldIdent, newIdent ast.Ident, isA if tableExists(is, newIdent, tables) { return nil, 0, infoschema.ErrTableExists.GenWithStackByArgs(newIdent) } - return nil, 0, errFileNotFound.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name) + return nil, 0, infoschema.ErrTableNotExists.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name) } if isAlterTable && newIdent.Schema.L == oldIdent.Schema.L && newIdent.Name.L == oldIdent.Name.L { // oldIdent is equal to newIdent, do nothing @@ -5148,7 +5314,7 @@ func extractTblInfos(is infoschema.InfoSchema, oldIdent, newIdent ast.Ident, isA } newSchema, ok := is.SchemaByName(newIdent.Schema) if !ok { - return nil, 0, ErrErrorOnRename.GenWithStackByArgs( + return nil, 0, dbterror.ErrErrorOnRename.GenWithStackByArgs( fmt.Sprintf("%s.%s", oldIdent.Schema, oldIdent.Name), fmt.Sprintf("%s.%s", newIdent.Schema, newIdent.Name), 168, @@ -5224,7 +5390,7 @@ func getAnonymousIndex(t table.Table, colName model.CIStr, idxName model.CIStr) func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName model.CIStr, indexPartSpecifications []*ast.IndexPartSpecification, indexOption *ast.IndexOption) error { if indexOption != nil && indexOption.PrimaryKeyTp == model.PrimaryKeyTypeClustered { - return ErrUnsupportedModifyPrimaryKey.GenWithStack("Adding clustered primary key is not supported. " + + return dbterror.ErrUnsupportedModifyPrimaryKey.GenWithStack("Adding clustered primary key is not supported. " + "Please consider adding NONCLUSTERED primary key instead") } schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) @@ -5233,7 +5399,7 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m } if err = checkTooLongIndex(indexName); err != nil { - return ErrTooLongIdent.GenWithStackByArgs(mysql.PrimaryKeyName) + return dbterror.ErrTooLongIdent.GenWithStackByArgs(mysql.PrimaryKeyName) } indexName = model.NewCIStr(mysql.PrimaryKeyName) @@ -5247,7 +5413,7 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m // but expression index parts are implemented as virtual generated columns, not stored generated columns. for _, idxPart := range indexPartSpecifications { if idxPart.Expr != nil { - return ErrFunctionalIndexPrimaryKey + return dbterror.ErrFunctionalIndexPrimaryKey } } @@ -5274,7 +5440,7 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m } if !ck { if !config.GetGlobalConfig().EnableGlobalIndex { - return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY") + return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY") } // index columns does not contain all partition columns, must set global global = true @@ -5286,25 +5452,28 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m return errors.Trace(err) } + tzName, tzOffset := ddlutil.GetTimeZone(ctx) + unique := true sqlMode := ctx.GetSessionVars().SQLMode job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionAddPrimaryKey, BinlogInfo: &model.HistoryInfo{}, ReorgMeta: &model.DDLReorgMeta{ SQLMode: ctx.GetSessionVars().SQLMode, Warnings: make(map[errors.ErrorID]*terror.Error), WarningsCount: make(map[errors.ErrorID]int64), - Location: ctx.GetSessionVars().Location(), + Location: &model.TimeZoneLocation{Name: tzName, Offset: tzOffset}, }, Args: []interface{}{unique, indexName, indexPartSpecifications, indexOption, sqlMode, nil, global}, Priority: ctx.GetSessionVars().DDLReorgPriority, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5326,7 +5495,7 @@ func buildHiddenColumnInfo(ctx sessionctx.Context, indexPartSpecifications []*as // The index part is an expression, prepare a hidden column for it. if utf8.RuneCountInString(idxPart.Column.Name.L) > mysql.MaxColumnNameLength { // TODO: Refine the error message. - return nil, ErrTooLongIdent.GenWithStackByArgs("hidden column") + return nil, dbterror.ErrTooLongIdent.GenWithStackByArgs("hidden column") } // TODO: refine the error message. if err := checkIllegalFn4Generated(indexName.L, typeIndex, idxPart.Expr); err != nil { @@ -5348,7 +5517,7 @@ func buildHiddenColumnInfo(ctx sessionctx.Context, indexPartSpecifications []*as return nil, err } if _, ok := expr.(*expression.Column); ok { - return nil, ErrFunctionalIndexOnField + return nil, dbterror.ErrFunctionalIndexOnField } colInfo := &model.ColumnInfo{ @@ -5360,6 +5529,11 @@ func buildHiddenColumnInfo(ctx sessionctx.Context, indexPartSpecifications []*as Hidden: true, FieldType: *expr.GetType(), } + // Reset some flag, it may be caused by wrong type infer. But it's not easy to fix them all, so reset them here for safety. + colInfo.Flag &= ^mysql.PriKeyFlag + colInfo.Flag &= ^mysql.UniqueKeyFlag + colInfo.Flag &= ^mysql.AutoIncrementFlag + if colInfo.Tp == mysql.TypeDatetime || colInfo.Tp == mysql.TypeDate || colInfo.Tp == mysql.TypeTimestamp || colInfo.Tp == mysql.TypeDuration { if colInfo.FieldType.Decimal == types.UnspecifiedLength { colInfo.FieldType.Decimal = int(types.MaxFsp) @@ -5388,7 +5562,7 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde indexPartSpecifications []*ast.IndexPartSpecification, indexOption *ast.IndexOption, ifNotExists bool) error { // not support Spatial and FullText index if keyType == ast.IndexKeyTypeFullText || keyType == ast.IndexKeyTypeSpatial { - return errUnsupportedIndexType.GenWithStack("FULLTEXT and SPATIAL index is not supported") + return dbterror.ErrUnsupportedIndexType.GenWithStack("FULLTEXT and SPATIAL index is not supported") } unique := keyType == ast.IndexKeyTypeUnique schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) @@ -5397,7 +5571,7 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde } if t.Meta().TableCacheStatusType != model.TableCacheStatusDisable { - return errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Create Index")) + return errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Create Index")) } // Deal with anonymous index. if len(indexName.L) == 0 { @@ -5411,11 +5585,11 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde if indexInfo := t.Meta().FindIndexByName(indexName.L); indexInfo != nil { if indexInfo.State != model.StatePublic { // NOTE: explicit error message. See issue #18363. - err = ErrDupKeyName.GenWithStack("index already exist %s; "+ + err = dbterror.ErrDupKeyName.GenWithStack("index already exist %s; "+ "a background job is trying to add the same index, "+ "please check by `ADMIN SHOW DDL JOBS`", indexName) } else { - err = ErrDupKeyName.GenWithStack("index already exist %s", indexName) + err = dbterror.ErrDupKeyName.GenWithStack("index already exist %s", indexName) } if ifNotExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) @@ -5461,7 +5635,7 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde } if !ck { if !config.GetGlobalConfig().EnableGlobalIndex { - return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX") + return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX") } // index columns does not contain all partition columns, must set global global = true @@ -5471,25 +5645,28 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde if _, err = validateCommentLength(ctx.GetSessionVars(), indexName.String(), indexOption); err != nil { return errors.Trace(err) } + + tzName, tzOffset := ddlutil.GetTimeZone(ctx) job := &model.Job{ SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionAddIndex, BinlogInfo: &model.HistoryInfo{}, ReorgMeta: &model.DDLReorgMeta{ SQLMode: ctx.GetSessionVars().SQLMode, Warnings: make(map[errors.ErrorID]*terror.Error), WarningsCount: make(map[errors.ErrorID]int64), - Location: ctx.GetSessionVars().Location(), + Location: &model.TimeZoneLocation{Name: tzName, Offset: tzOffset}, }, Args: []interface{}{unique, indexName, indexPartSpecifications, indexOption, hiddenCols, global}, Priority: ctx.GetSessionVars().DDLReorgPriority, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) // key exists, but if_not_exists flags is true, so we ignore this error. - if ErrDupKeyName.Equal(err) && ifNotExists { + if dbterror.ErrDupKeyName.Equal(err) && ifNotExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil } @@ -5534,11 +5711,11 @@ func buildFKInfo(fkName model.CIStr, keys []*ast.IndexPartSpecification, refer * // Check wrong reference options of foreign key on stored generated columns switch refer.OnUpdate.ReferOpt { case ast.ReferOptionCascade, ast.ReferOptionSetNull, ast.ReferOptionSetDefault: - return nil, errWrongFKOptionForGeneratedColumn.GenWithStackByArgs("ON UPDATE " + refer.OnUpdate.ReferOpt.String()) + return nil, dbterror.ErrWrongFKOptionForGeneratedColumn.GenWithStackByArgs("ON UPDATE " + refer.OnUpdate.ReferOpt.String()) } switch refer.OnDelete.ReferOpt { case ast.ReferOptionSetNull, ast.ReferOptionSetDefault: - return nil, errWrongFKOptionForGeneratedColumn.GenWithStackByArgs("ON DELETE " + refer.OnDelete.ReferOpt.String()) + return nil, dbterror.ErrWrongFKOptionForGeneratedColumn.GenWithStackByArgs("ON DELETE " + refer.OnDelete.ReferOpt.String()) } continue } @@ -5555,7 +5732,7 @@ func buildFKInfo(fkName model.CIStr, keys []*ast.IndexPartSpecification, refer * } } if table.FindCol(cols, key.Column.Name.O) == nil { - return nil, errKeyColumnDoesNotExits.GenWithStackByArgs(key.Column.Name) + return nil, dbterror.ErrKeyColumnDoesNotExits.GenWithStackByArgs(key.Column.Name) } fkInfo.Cols[i] = key.Column.Name } @@ -5589,7 +5766,7 @@ func (d *ddl) CreateForeignKey(ctx sessionctx.Context, ti ast.Ident, fkName mode // Check the uniqueness of the FK. for _, fk := range t.Meta().ForeignKeys { if fk.Name.L == fkName.L { - return ErrFkDupName.GenWithStackByArgs(fkName.O) + return dbterror.ErrFkDupName.GenWithStackByArgs(fkName.O) } } @@ -5602,12 +5779,13 @@ func (d *ddl) CreateForeignKey(ctx sessionctx.Context, ti ast.Ident, fkName mode SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionAddForeignKey, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{fkInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5628,12 +5806,13 @@ func (d *ddl) DropForeignKey(ctx sessionctx.Context, ti ast.Ident, fkName model. SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: model.ActionDropForeignKey, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{fkName}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5649,7 +5828,7 @@ func (d *ddl) DropIndex(ctx sessionctx.Context, ti ast.Ident, indexName model.CI return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name)) } if t.Meta().TableCacheStatusType != model.TableCacheStatusDisable { - return errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Drop Index")) + return errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Drop Index")) } indexInfo := t.Meta().FindIndexByName(indexName.L) @@ -5660,7 +5839,7 @@ func (d *ddl) DropIndex(ctx sessionctx.Context, ti ast.Ident, indexName model.CI } if indexInfo == nil { - err = ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) + err = dbterror.ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) if ifExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil @@ -5683,65 +5862,13 @@ func (d *ddl) DropIndex(ctx sessionctx.Context, ti ast.Ident, indexName model.CI SchemaID: schema.ID, TableID: t.Meta().ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, Type: jobTp, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{indexName}, - } - - err = d.doDDLJob(ctx, job) - // index not exists, but if_exists flags is true, so we ignore this error. - if ErrCantDropFieldOrKey.Equal(err) && ifExists { - ctx.GetSessionVars().StmtCtx.AppendNote(err) - return nil - } - err = d.callHookOnChanged(err) - return errors.Trace(err) -} - -func (d *ddl) DropIndexes(ctx sessionctx.Context, ti ast.Ident, specs []*ast.AlterTableSpec) error { - schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) - if err != nil { - return err - } - - if t.Meta().TableCacheStatusType != model.TableCacheStatusDisable { - return errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Drop Indexes")) - } - indexNames := make([]model.CIStr, 0, len(specs)) - ifExists := make([]bool, 0, len(specs)) - for _, spec := range specs { - var indexName model.CIStr - if spec.Tp == ast.AlterTableDropPrimaryKey { - indexName = model.NewCIStr(mysql.PrimaryKeyName) - } else { - indexName = model.NewCIStr(spec.Name) - } - - indexInfo := t.Meta().FindIndexByName(indexName.L) - if indexInfo != nil { - _, err := checkIsDropPrimaryKey(indexName, indexInfo, t) - if err != nil { - return err - } - if err := checkDropIndexOnAutoIncrementColumn(t.Meta(), indexInfo); err != nil { - return errors.Trace(err) - } - } - - indexNames = append(indexNames, indexName) - ifExists = append(ifExists, spec.IfExists) - } - - job := &model.Job{ - SchemaID: schema.ID, - TableID: t.Meta().ID, - SchemaName: schema.Name.L, - Type: model.ActionDropIndexes, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{indexNames, ifExists}, + Args: []interface{}{indexName, ifExists}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -5756,13 +5883,13 @@ func checkIsDropPrimaryKey(indexName model.CIStr, indexInfo *model.IndexInfo, t if isPK { // If the table's PKIsHandle is true, we can't find the index from the table. So we check the value of PKIsHandle. if indexInfo == nil && !t.Meta().PKIsHandle { - return isPK, ErrCantDropFieldOrKey.GenWithStackByArgs("PRIMARY") + return isPK, dbterror.ErrCantDropFieldOrKey.GenWithStackByArgs("PRIMARY") } if t.Meta().PKIsHandle { - return isPK, ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the table's pkIsHandle is true") + return isPK, dbterror.ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the table's pkIsHandle is true") } if t.Meta().IsCommonHandle { - return isPK, ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the table is using clustered index") + return isPK, dbterror.ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the table is using clustered index") } } @@ -5772,22 +5899,23 @@ func checkIsDropPrimaryKey(indexName model.CIStr, indexInfo *model.IndexInfo, t func isDroppableColumn(multiSchemaChange bool, tblInfo *model.TableInfo, colName model.CIStr) error { if ok, dep, isHidden := hasDependentByGeneratedColumn(tblInfo, colName); ok { if isHidden { - return errDependentByFunctionalIndex.GenWithStackByArgs(dep) + return dbterror.ErrDependentByFunctionalIndex.GenWithStackByArgs(dep) } - return errDependentByGeneratedColumn.GenWithStackByArgs(dep) + return dbterror.ErrDependentByGeneratedColumn.GenWithStackByArgs(dep) } if len(tblInfo.Columns) == 1 { - return ErrCantRemoveAllFields.GenWithStack("can't drop only column %s in table %s", + return dbterror.ErrCantRemoveAllFields.GenWithStack("can't drop only column %s in table %s", colName, tblInfo.Name) } // We only support dropping column with single-value none Primary Key index covered now. - if !isColumnCanDropWithIndex(multiSchemaChange, colName.L, tblInfo.Indices) { - return errCantDropColWithIndex.GenWithStack("can't drop column %s with composite index covered or Primary Key covered now", colName) + err := isColumnCanDropWithIndex(multiSchemaChange, colName.L, tblInfo.Indices) + if err != nil { + return err } // Check the column with foreign key. if fkInfo := getColumnForeignKeyInfo(colName.L, tblInfo.ForeignKeys); fkInfo != nil { - return errFkColumnCannotDrop.GenWithStackByArgs(colName, fkInfo.Name) + return dbterror.ErrFkColumnCannotDrop.GenWithStackByArgs(colName, fkInfo.Name) } return nil } @@ -5802,7 +5930,7 @@ func validateCommentLength(vars *variable.SessionVars, indexName string, indexOp maxLen := MaxCommentLength if len(indexOption.Comment) > maxLen { - err := errTooLongIndexComment.GenWithStackByArgs(indexName, maxLen) + err := dbterror.ErrTooLongIndexComment.GenWithStackByArgs(indexName, maxLen) if vars.StrictSQLMode { return "", err } @@ -5821,7 +5949,7 @@ func buildAddedPartitionInfo(ctx sessionctx.Context, meta *model.TableInfo, spec } default: // we don't support ADD PARTITION for all other partition types yet. - return nil, errors.Trace(ErrUnsupportedAddPartition) + return nil, errors.Trace(dbterror.ErrUnsupportedAddPartition) } part := &model.PartitionInfo{ @@ -5863,30 +5991,30 @@ func checkColumnsTypeAndValuesMatch(ctx sessionctx.Context, meta *model.TableInf case types.KindString, types.KindBytes: break default: - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: switch vkind { case types.KindInt64, types.KindUint64, types.KindNull: default: - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } case mysql.TypeFloat, mysql.TypeDouble: switch vkind { case types.KindFloat32, types.KindFloat64, types.KindNull: default: - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } case mysql.TypeString, mysql.TypeVarString: switch vkind { case types.KindString, types.KindBytes, types.KindNull, types.KindBinaryLiteral: default: - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } } _, err = val.ConvertTo(ctx.GetSessionVars().StmtCtx, &colType) if err != nil { - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } } return nil @@ -5914,6 +6042,7 @@ func (d *ddl) LockTables(ctx sessionctx.Context, stmt *ast.LockTablesStmt) error if t.Meta().IsView() || t.Meta().IsSequence() { return table.ErrUnsupportedOp.GenWithStackByArgs() } + err = checkTableLocked(t.Meta(), tl.Type, sessionInfo) if err != nil { return err @@ -5940,7 +6069,7 @@ func (d *ddl) LockTables(ctx sessionctx.Context, stmt *ast.LockTablesStmt) error } // AddTableLock here is avoiding this job was executed successfully but the session was killed before return. ctx.AddTableLock(lockTables) - err := d.doDDLJob(ctx, job) + err := d.DoDDLJob(ctx, job) if err == nil { ctx.ReleaseTableLocks(unlockTables) ctx.AddTableLock(lockTables) @@ -5969,7 +6098,7 @@ func (d *ddl) UnlockTables(ctx sessionctx.Context, unlockTables []model.TableLoc Args: []interface{}{arg}, } - err := d.doDDLJob(ctx, job) + err := d.DoDDLJob(ctx, job) if err == nil { ctx.ReleaseAllTableLocks() } @@ -5999,7 +6128,7 @@ func (d *ddl) CleanDeadTableLock(unlockTables []model.TableLockTpInfo, se model. return err } defer d.sessPool.put(ctx) - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6060,7 +6189,7 @@ func (d *ddl) CleanupTableLock(ctx sessionctx.Context, tables []*ast.TableName) BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{arg}, } - err := d.doDDLJob(ctx, job) + err := d.DoDDLJob(ctx, job) if err == nil { ctx.ReleaseTableLocks(cleanupTables) } @@ -6081,19 +6210,19 @@ func (d *ddl) RepairTable(ctx sessionctx.Context, table *ast.TableName, createSt // Existence of DB and table has been checked in the preprocessor. oldTableInfo, ok := (ctx.Value(domainutil.RepairedTable)).(*model.TableInfo) if !ok || oldTableInfo == nil { - return ErrRepairTableFail.GenWithStack("Failed to get the repaired table") + return dbterror.ErrRepairTableFail.GenWithStack("Failed to get the repaired table") } oldDBInfo, ok := (ctx.Value(domainutil.RepairedDatabase)).(*model.DBInfo) if !ok || oldDBInfo == nil { - return ErrRepairTableFail.GenWithStack("Failed to get the repaired database") + return dbterror.ErrRepairTableFail.GenWithStack("Failed to get the repaired database") } // By now only support same DB repair. if createStmt.Table.Schema.L != oldDBInfo.Name.L { - return ErrRepairTableFail.GenWithStack("Repaired table should in same database with the old one") + return dbterror.ErrRepairTableFail.GenWithStack("Repaired table should in same database with the old one") } // It is necessary to specify the table.ID and partition.ID manually. - newTableInfo, err := buildTableInfoWithCheck(ctx, createStmt, oldTableInfo.Charset, oldTableInfo.Collate, oldTableInfo.PlacementPolicyRef, oldTableInfo.DirectPlacementOpts) + newTableInfo, err := buildTableInfoWithCheck(ctx, createStmt, oldTableInfo.Charset, oldTableInfo.Collate, oldTableInfo.PlacementPolicyRef) if err != nil { return errors.Trace(err) } @@ -6108,10 +6237,10 @@ func (d *ddl) RepairTable(ctx sessionctx.Context, table *ast.TableName, createSt for i, newOne := range newTableInfo.Columns { old := getColumnInfoByName(oldTableInfo, newOne.Name.L) if old == nil { - return ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " has lost") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " has lost") } if newOne.Tp != old.Tp { - return ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " type should be the same") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Column " + newOne.Name.L + " type should be the same") } if newOne.Flen != old.Flen { logutil.BgLogger().Warn("[ddl] admin repair table : Column " + newOne.Name.L + " flen is not equal to the old one") @@ -6122,10 +6251,10 @@ func (d *ddl) RepairTable(ctx sessionctx.Context, table *ast.TableName, createSt for i, newOne := range newTableInfo.Indices { old := getIndexInfoByNameAndColumn(oldTableInfo, newOne) if old == nil { - return ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " has lost") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " has lost") } if newOne.Tp != old.Tp { - return ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " type should be the same") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " type should be the same") } newTableInfo.Indices[i].ID = old.ID } @@ -6141,11 +6270,12 @@ func (d *ddl) RepairTable(ctx sessionctx.Context, table *ast.TableName, createSt SchemaID: oldDBInfo.ID, TableID: newTableInfo.ID, SchemaName: oldDBInfo.Name.L, + TableName: newTableInfo.Name.L, Type: model.ActionRepairTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newTableInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err == nil { // Remove the old TableInfo from repairInfo before domain reload. domainutil.RepairInfo.RemoveFromRepairInfo(oldDBInfo.Name.L, oldTableInfo.Name.L) @@ -6183,7 +6313,7 @@ func (d *ddl) CreateSequence(ctx sessionctx.Context, stmt *ast.CreateSequenceStm onExist = OnExistIgnore } - return d.CreateTableWithInfo(ctx, ident.Schema, tbInfo, onExist, false /*tryRetainID*/) + return d.CreateTableWithInfo(ctx, ident.Schema, tbInfo, onExist) } func (d *ddl) AlterSequence(ctx sessionctx.Context, stmt *ast.AlterSequenceStmt) error { @@ -6204,7 +6334,7 @@ func (d *ddl) AlterSequence(ctx sessionctx.Context, stmt *ast.AlterSequenceStmt) return err } if !tbl.Meta().IsSequence() { - return ErrWrongObject.GenWithStackByArgs(ident.Schema, ident.Name, "SEQUENCE") + return dbterror.ErrWrongObject.GenWithStackByArgs(ident.Schema, ident.Name, "SEQUENCE") } // Validate the new sequence option value in old sequenceInfo. @@ -6219,12 +6349,13 @@ func (d *ddl) AlterSequence(ctx sessionctx.Context, stmt *ast.AlterSequenceStmt) SchemaID: db.ID, TableID: tbl.Meta().ID, SchemaName: db.Name.L, + TableName: tbl.Meta().Name.L, Type: model.ActionAlterSequence, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{ident, stmt.SeqOptions}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6236,7 +6367,7 @@ func (d *ddl) DropSequence(ctx sessionctx.Context, ti ast.Ident, ifExists bool) } if !tbl.Meta().IsSequence() { - err = ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "SEQUENCE") + err = dbterror.ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "SEQUENCE") if ifExists { ctx.GetSessionVars().StmtCtx.AppendNote(err) return nil @@ -6248,11 +6379,12 @@ func (d *ddl) DropSequence(ctx sessionctx.Context, ti ast.Ident, ifExists bool) SchemaID: schema.ID, TableID: tbl.Meta().ID, SchemaName: schema.Name.L, + TableName: tbl.Meta().Name.L, Type: model.ActionDropSequence, BinlogInfo: &model.HistoryInfo{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6280,12 +6412,13 @@ func (d *ddl) AlterIndexVisibility(ctx sessionctx.Context, ident ast.Ident, inde SchemaID: schema.ID, TableID: tb.Meta().ID, SchemaName: schema.Name.L, + TableName: tb.Meta().Name.L, Type: model.ActionAlterIndexVisibility, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{indexName, invisible}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6300,13 +6433,7 @@ func (d *ddl) AlterTableAttributes(ctx sessionctx.Context, ident ast.Ident, spec rule := label.NewRule() err = rule.ApplyAttributesSpec(spec.AttributesSpec) if err != nil { - var sb strings.Builder - restoreCtx := format.NewRestoreCtx(format.RestoreStringSingleQuotes|format.RestoreKeyWordLowercase|format.RestoreNameBackQuotes, &sb) - - if e := spec.Restore(restoreCtx); e != nil { - return ErrInvalidAttributesSpec.GenWithStackByArgs(sb.String(), err) - } - return ErrInvalidAttributesSpec.GenWithStackByArgs(err) + return dbterror.ErrInvalidAttributesSpec.GenWithStackByArgs(err) } ids := getIDs([]*model.TableInfo{meta}) rule.Reset(schema.Name.L, meta.Name.L, "", ids...) @@ -6315,12 +6442,13 @@ func (d *ddl) AlterTableAttributes(ctx sessionctx.Context, ident ast.Ident, spec SchemaID: schema.ID, TableID: meta.ID, SchemaName: schema.Name.L, + TableName: meta.Name.L, Type: model.ActionAlterTableAttributes, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{rule}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { return errors.Trace(err) } @@ -6337,7 +6465,7 @@ func (d *ddl) AlterTablePartitionAttributes(ctx sessionctx.Context, ident ast.Id meta := tb.Meta() if meta.Partition == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } partitionID, err := tables.FindPartitionByName(meta, spec.PartitionNames[0].L) @@ -6348,13 +6476,7 @@ func (d *ddl) AlterTablePartitionAttributes(ctx sessionctx.Context, ident ast.Id rule := label.NewRule() err = rule.ApplyAttributesSpec(spec.AttributesSpec) if err != nil { - var sb strings.Builder - restoreCtx := format.NewRestoreCtx(format.RestoreStringSingleQuotes|format.RestoreKeyWordLowercase|format.RestoreNameBackQuotes, &sb) - - if e := spec.Restore(restoreCtx); e != nil { - return ErrInvalidAttributesSpec.GenWithStackByArgs("", err) - } - return ErrInvalidAttributesSpec.GenWithStackByArgs(sb.String(), err) + return dbterror.ErrInvalidAttributesSpec.GenWithStackByArgs(err) } rule.Reset(schema.Name.L, meta.Name.L, spec.PartitionNames[0].L, partitionID) @@ -6362,12 +6484,13 @@ func (d *ddl) AlterTablePartitionAttributes(ctx sessionctx.Context, ident ast.Id SchemaID: schema.ID, TableID: meta.ID, SchemaName: schema.Name.L, + TableName: meta.Name.L, Type: model.ActionAlterTablePartitionAttributes, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{partitionID, rule}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) if err != nil { return errors.Trace(err) } @@ -6378,7 +6501,6 @@ func (d *ddl) AlterTablePartitionAttributes(ctx sessionctx.Context, ident ast.Id func (d *ddl) AlterTablePartitionOptions(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) (err error) { var policyRefInfo *model.PolicyRefInfo - var placementSettings *model.PlacementSettings if spec.Options != nil { for _, op := range spec.Options { switch op.Tp { @@ -6386,27 +6508,14 @@ func (d *ddl) AlterTablePartitionOptions(ctx sessionctx.Context, ident ast.Ident policyRefInfo = &model.PolicyRefInfo{ Name: model.NewCIStr(op.StrValue), } - case ast.TableOptionPlacementPrimaryRegion, ast.TableOptionPlacementRegions, - ast.TableOptionPlacementFollowerCount, ast.TableOptionPlacementVoterCount, - ast.TableOptionPlacementLearnerCount, ast.TableOptionPlacementSchedule, - ast.TableOptionPlacementConstraints, ast.TableOptionPlacementLeaderConstraints, - ast.TableOptionPlacementLearnerConstraints, ast.TableOptionPlacementFollowerConstraints, - ast.TableOptionPlacementVoterConstraints: - if placementSettings == nil { - placementSettings = &model.PlacementSettings{} - } - err = SetDirectPlacementOpt(placementSettings, ast.PlacementOptionType(op.Tp), op.StrValue, op.UintValue) - if err != nil { - return err - } default: return errors.Trace(errors.New("unknown partition option")) } } } - if policyRefInfo != nil || placementSettings != nil { - err = d.AlterTablePartitionPlacement(ctx, ident, spec, policyRefInfo, placementSettings) + if policyRefInfo != nil { + err = d.AlterTablePartitionPlacement(ctx, ident, spec, policyRefInfo) if err != nil { return errors.Trace(err) } @@ -6415,7 +6524,7 @@ func (d *ddl) AlterTablePartitionOptions(ctx sessionctx.Context, ident ast.Ident return nil } -func (d *ddl) AlterTablePartitionPlacement(ctx sessionctx.Context, tableIdent ast.Ident, spec *ast.AlterTableSpec, policyRefInfo *model.PolicyRefInfo, placementSettings *model.PlacementSettings) (err error) { +func (d *ddl) AlterTablePartitionPlacement(ctx sessionctx.Context, tableIdent ast.Ident, spec *ast.AlterTableSpec, policyRefInfo *model.PolicyRefInfo) (err error) { schema, tb, err := d.getSchemaAndTableByIdent(ctx, tableIdent) if err != nil { return errors.Trace(err) @@ -6423,15 +6532,19 @@ func (d *ddl) AlterTablePartitionPlacement(ctx sessionctx.Context, tableIdent as tblInfo := tb.Meta() if tblInfo.Partition == nil { - return errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } partitionID, err := tables.FindPartitionByName(tblInfo, spec.PartitionNames[0].L) if err != nil { return errors.Trace(err) } - ptPlacementPolicyRef, ptPlacementSettings := tblInfo.Partition.GetPlacementByID(partitionID) - policyRefInfo, placementSettings, err = checkAndNormalizePlacement(ctx, policyRefInfo, placementSettings, ptPlacementPolicyRef, ptPlacementSettings) + + if checkIgnorePlacementDDL(ctx) { + return nil + } + + policyRefInfo, err = checkAndNormalizePlacementPolicy(ctx, policyRefInfo) if err != nil { return errors.Trace(err) } @@ -6440,12 +6553,13 @@ func (d *ddl) AlterTablePartitionPlacement(ctx sessionctx.Context, tableIdent as SchemaID: schema.ID, TableID: tblInfo.ID, SchemaName: schema.Name.L, + TableName: tblInfo.Name.L, Type: model.ActionAlterTablePartitionPlacement, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{partitionID, policyRefInfo, placementSettings}, + Args: []interface{}{partitionID, policyRefInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6462,45 +6576,144 @@ func buildPolicyInfo(name model.CIStr, options []*ast.PlacementOption) (*model.P return policyInfo, nil } -func (d *ddl) CreatePlacementPolicy(ctx sessionctx.Context, stmt *ast.CreatePlacementPolicyStmt) (err error) { - policyName := stmt.PolicyName - if policyName.L == defaultPlacementPolicyName { - return errors.Trace(infoschema.ErrReservedSyntax.GenWithStackByArgs(policyName)) +func removeTablePlacement(tbInfo *model.TableInfo) bool { + hasPlacementSettings := false + if tbInfo.PlacementPolicyRef != nil { + tbInfo.PlacementPolicyRef = nil + hasPlacementSettings = true } - is := d.GetInfoSchemaWithInterceptor(ctx) - // Check policy existence. - _, ok := is.PolicyByName(policyName) - if ok { - err = infoschema.ErrPlacementPolicyExists.GenWithStackByArgs(policyName) - if stmt.IfNotExists { - ctx.GetSessionVars().StmtCtx.AppendNote(err) - return nil + + if removePartitionPlacement(tbInfo.Partition) { + hasPlacementSettings = true + } + + return hasPlacementSettings +} + +func removePartitionPlacement(partInfo *model.PartitionInfo) bool { + if partInfo == nil { + return false + } + + hasPlacementSettings := false + for i := range partInfo.Definitions { + def := &partInfo.Definitions[i] + if def.PlacementPolicyRef != nil { + def.PlacementPolicyRef = nil + hasPlacementSettings = true } + } + return hasPlacementSettings +} + +func handleDatabasePlacement(ctx sessionctx.Context, dbInfo *model.DBInfo) error { + if dbInfo.PlacementPolicyRef == nil { + return nil + } + + sessVars := ctx.GetSessionVars() + if sessVars.PlacementMode == variable.PlacementModeIgnore { + dbInfo.PlacementPolicyRef = nil + sessVars.StmtCtx.AppendNote(errors.New( + fmt.Sprintf("Placement is ignored when TIDB_PLACEMENT_MODE is '%s'", variable.PlacementModeIgnore), + )) + return nil + } + + var err error + dbInfo.PlacementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, dbInfo.PlacementPolicyRef) + return err +} + +func handleTablePlacement(ctx sessionctx.Context, tbInfo *model.TableInfo) error { + sessVars := ctx.GetSessionVars() + if sessVars.PlacementMode == variable.PlacementModeIgnore && removeTablePlacement(tbInfo) { + sessVars.StmtCtx.AppendNote(errors.New( + fmt.Sprintf("Placement is ignored when TIDB_PLACEMENT_MODE is '%s'", variable.PlacementModeIgnore), + )) + return nil + } + + var err error + tbInfo.PlacementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, tbInfo.PlacementPolicyRef) + if err != nil { return err } - // Auto fill the policyID when it is inserted. + + if tbInfo.Partition != nil { + for i := range tbInfo.Partition.Definitions { + partition := &tbInfo.Partition.Definitions[i] + partition.PlacementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, partition.PlacementPolicyRef) + if err != nil { + return err + } + } + } + return nil +} + +func handlePartitionPlacement(ctx sessionctx.Context, partInfo *model.PartitionInfo) error { + sessVars := ctx.GetSessionVars() + if sessVars.PlacementMode == variable.PlacementModeIgnore && removePartitionPlacement(partInfo) { + sessVars.StmtCtx.AppendNote(errors.New( + fmt.Sprintf("Placement is ignored when TIDB_PLACEMENT_MODE is '%s'", variable.PlacementModeIgnore), + )) + return nil + } + + var err error + for i := range partInfo.Definitions { + partition := &partInfo.Definitions[i] + partition.PlacementPolicyRef, err = checkAndNormalizePlacementPolicy(ctx, partition.PlacementPolicyRef) + if err != nil { + return err + } + } + return nil +} + +func checkIgnorePlacementDDL(ctx sessionctx.Context) bool { + sessVars := ctx.GetSessionVars() + if sessVars.PlacementMode == variable.PlacementModeIgnore { + sessVars.StmtCtx.AppendNote(errors.New( + fmt.Sprintf("Placement is ignored when TIDB_PLACEMENT_MODE is '%s'", variable.PlacementModeIgnore), + )) + return true + } + return false +} + +func (d *ddl) CreatePlacementPolicy(ctx sessionctx.Context, stmt *ast.CreatePlacementPolicyStmt) (err error) { + if checkIgnorePlacementDDL(ctx) { + return nil + } + + if stmt.OrReplace && stmt.IfNotExists { + return dbterror.ErrWrongUsage.GenWithStackByArgs("OR REPLACE", "IF NOT EXISTS") + } + policyInfo, err := buildPolicyInfo(stmt.PolicyName, stmt.PlacementOptions) if err != nil { return errors.Trace(err) } - err = checkPolicyValidation(policyInfo.PlacementSettings) - if err != nil { - return err + var onExists OnExist + switch { + case stmt.IfNotExists: + onExists = OnExistIgnore + case stmt.OrReplace: + onExists = OnExistReplace + default: + onExists = OnExistError } - job := &model.Job{ - SchemaName: policyInfo.Name.L, - Type: model.ActionCreatePlacementPolicy, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{policyInfo}, - } - err = d.doDDLJob(ctx, job) - err = d.callHookOnChanged(err) - return errors.Trace(err) + return d.CreatePlacementPolicyWithInfo(ctx, policyInfo, onExists) } func (d *ddl) DropPlacementPolicy(ctx sessionctx.Context, stmt *ast.DropPlacementPolicyStmt) (err error) { + if checkIgnorePlacementDDL(ctx) { + return nil + } policyName := stmt.PolicyName is := d.GetInfoSchemaWithInterceptor(ctx) // Check policy existence. @@ -6525,12 +6738,15 @@ func (d *ddl) DropPlacementPolicy(ctx sessionctx.Context, stmt *ast.DropPlacemen BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{policyName}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } func (d *ddl) AlterPlacementPolicy(ctx sessionctx.Context, stmt *ast.AlterPlacementPolicyStmt) (err error) { + if checkIgnorePlacementDDL(ctx) { + return nil + } policyName := stmt.PolicyName is := d.GetInfoSchemaWithInterceptor(ctx) // Check policy existence. @@ -6556,7 +6772,7 @@ func (d *ddl) AlterPlacementPolicy(ctx sessionctx.Context, stmt *ast.AlterPlacem BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newPolicyInfo}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) err = d.callHookOnChanged(err) return errors.Trace(err) } @@ -6573,37 +6789,81 @@ func (d *ddl) AlterTableCache(ctx sessionctx.Context, ti ast.Ident) (err error) // forbit cache table in system database. if util.IsMemOrSysDB(schema.Name.L) { - return errors.Trace(errUnsupportedAlterCacheForSysTable) + return errors.Trace(dbterror.ErrUnsupportedAlterCacheForSysTable) } else if t.Meta().TempTableType != model.TempTableNone { - return errors.Trace(ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache")) + return dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache") } if t.Meta().Partition != nil { - return errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("partition mode")) + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("partition mode") + } + + succ, err := checkCacheTableSize(d.store, t.Meta().ID) + if err != nil { + return errors.Trace(err) + } + if !succ { + return dbterror.ErrOptOnCacheTable.GenWithStackByArgs("table too large") } + ddlQuery, _ := ctx.Value(sessionctx.QueryString).(string) // Initialize the cached table meta lock info in `mysql.table_cache_meta`. // The operation shouldn't fail in most cases, and if it does, return the error directly. // This DML and the following DDL is not atomic, that's not a problem. _, err = ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.Background(), - "insert ignore into mysql.table_cache_meta values (%?, 'NONE', 0, 0)", t.Meta().ID) + "replace into mysql.table_cache_meta values (%?, 'NONE', 0, 0)", t.Meta().ID) if err != nil { return errors.Trace(err) } + ctx.SetValue(sessionctx.QueryString, ddlQuery) job := &model.Job{ SchemaID: schema.ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, TableID: t.Meta().ID, Type: model.ActionAlterCacheTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) return d.callHookOnChanged(err) } +func checkCacheTableSize(store kv.Storage, tableID int64) (bool, error) { + const cacheTableSizeLimit = 64 * (1 << 20) // 64M + succ := true + err := kv.RunInNewTxn(context.Background(), store, true, func(ctx context.Context, txn kv.Transaction) error { + prefix := tablecodec.GenTablePrefix(tableID) + it, err := txn.Iter(prefix, prefix.PrefixNext()) + if err != nil { + return errors.Trace(err) + } + defer it.Close() + + totalSize := 0 + for it.Valid() && it.Key().HasPrefix(prefix) { + key := it.Key() + value := it.Value() + totalSize += len(key) + totalSize += len(value) + + if totalSize > cacheTableSizeLimit { + succ = false + break + } + + err = it.Next() + if err != nil { + return errors.Trace(err) + } + } + return nil + }) + return succ, err +} + func (d *ddl) AlterTableNoCache(ctx sessionctx.Context, ti ast.Ident) (err error) { schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) if err != nil { @@ -6617,12 +6877,33 @@ func (d *ddl) AlterTableNoCache(ctx sessionctx.Context, ti ast.Ident) (err error job := &model.Job{ SchemaID: schema.ID, SchemaName: schema.Name.L, + TableName: t.Meta().Name.L, TableID: t.Meta().ID, Type: model.ActionAlterNoCacheTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{}, } - err = d.doDDLJob(ctx, job) + err = d.DoDDLJob(ctx, job) return d.callHookOnChanged(err) } + +// checkTooBigFieldLengthAndTryAutoConvert will check whether the field length is too big +// in non-strict mode and varchar column. If it is, will try to adjust to blob or text, see issue #30328 +func checkTooBigFieldLengthAndTryAutoConvert(tp *types.FieldType, colName string, sessVars *variable.SessionVars) error { + if sessVars != nil && !sessVars.SQLMode.HasStrictMode() && tp.Tp == mysql.TypeVarchar { + err := IsTooBigFieldLength(tp.Flen, colName, tp.Charset) + if err != nil && terror.ErrorEqual(types.ErrTooBigFieldLength, err) { + tp.Tp = mysql.TypeBlob + if err = adjustBlobTypesFlen(tp, tp.Charset); err != nil { + return err + } + if tp.Charset == charset.CharsetBin { + sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colName, "VARBINARY", "BLOB")) + } else { + sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colName, "VARCHAR", "TEXT")) + } + } + } + return nil +} diff --git a/ddl/ddl_error_test.go b/ddl/ddl_error_test.go new file mode 100644 index 0000000000000..b771ea273014d --- /dev/null +++ b/ddl/ddl_error_test.go @@ -0,0 +1,188 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package ddl_test + +import ( + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +// This test file contains tests that test the expected or unexpected DDL error. +// For expected error, we use SQL to check it. +// For unexpected error, we mock a SQL job to check it. + +func TestTableError(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table testDrop(a int)") + // Schema ID is wrong, so dropping table is failed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + _, err := tk.Exec("drop table testDrop") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) + + // Table ID is wrong, so dropping table is failed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobTableId", `return(-1)`)) + _, err = tk.Exec("drop table testDrop") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobTableId")) + + // Args is wrong, so creating table is failed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobArg", `return(true)`)) + _, err = tk.Exec("create table test.t1(a int)") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobArg")) + + // Table exists, so creating table is failed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + _, err = tk.Exec("create table test.t1(a int)") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) + // Table exists, so creating table is failed. + tk.MustExec("create table test.t2(a int)") + tk.MustGetErrCode("create table test.t2(a int)", errno.ErrTableExists) +} + +func TestViewError(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int)") + + // Args is wrong, so creating view is failed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobArg", `return(true)`)) + _, err := tk.Exec("create view v as select * from t") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobArg")) +} + +func TestForeignKeyError(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int)") + tk.MustExec("create table t1 (a int, FOREIGN KEY fk(a) REFERENCES t(a))") + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + _, err := tk.Exec("alter table t1 add foreign key idx(a) REFERENCES t(a)") + require.Error(t, err) + _, err = tk.Exec("alter table t1 drop index fk") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) +} + +func TestIndexError(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int)") + tk.MustExec("alter table t add index a(a)") + + // Schema ID is wrong. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + _, err := tk.Exec("alter table t add index idx(a)") + require.Error(t, err) + _, err = tk.Exec("alter table t1 drop a") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) + + // for adding index + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobArg", `return(true)`)) + _, err = tk.Exec("alter table t add index idx(a)") + require.Error(t, err) + _, err = tk.Exec("alter table t drop index a") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobArg")) +} + +func TestColumnError(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, testLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int, aa int, ab int)") + tk.MustExec("alter table t add index a(a)") + + // Invalid schema ID. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + _, err := tk.Exec("alter table t add column ta int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t add column ta int, add column tb int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa, drop column ab") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) + + // Invalid table ID. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobTableId", `return(-1)`)) + _, err = tk.Exec("alter table t add column ta int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t add column ta int, add column tb int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa, drop column ab") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobTableId")) + + // Invalid argument. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockModifyJobArg", `return(true)`)) + _, err = tk.Exec("alter table t add column ta int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa") + require.Error(t, err) + _, err = tk.Exec("alter table t add column ta int, add column tb int") + require.Error(t, err) + _, err = tk.Exec("alter table t drop column aa, drop column ab") + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockModifyJobArg")) + + tk.MustGetErrCode("alter table t add column c int after c5", errno.ErrBadField) + tk.MustGetErrCode("alter table t drop column c5", errno.ErrCantDropFieldOrKey) + tk.MustGetErrCode("alter table t add column c int after c5, add column d int", errno.ErrBadField) + tk.MustGetErrCode("alter table t drop column ab, drop column c5", errno.ErrCantDropFieldOrKey) +} + +func TestCreateDatabaseError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId", `return(-1)`)) + tk.MustExec("create database db1;") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockModifyJobSchemaId")) +} diff --git a/ddl/ddl_test.go b/ddl/ddl_test.go index 08eb1f2bbae1d..dabcd2f366b0e 100644 --- a/ddl/ddl_test.go +++ b/ddl/ddl_test.go @@ -16,33 +16,26 @@ package ddl import ( "context" - "os" "testing" "time" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/meta/autoid" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testleak" "github.com/stretchr/testify/require" - "github.com/tikv/client-go/v2/tikv" ) type DDLForTest interface { - // SetHook sets the hook. - SetHook(h Callback) // SetInterceptor sets the interceptor. SetInterceptor(h Interceptor) } @@ -65,38 +58,6 @@ func GetMaxRowID(store kv.Storage, priority int, t table.Table, startHandle, end return getRangeEndKey(store, priority, t, startHandle, endHandle) } -func TestT(t *testing.T) { - CustomVerboseFlag = true - *CustomParallelSuiteFlag = true - logLevel := os.Getenv("log_level") - err := logutil.InitLogger(logutil.NewLogConfig(logLevel, "", "", logutil.EmptyFileLogConfig, false)) - if err != nil { - t.Fatal(err) - } - autoid.SetStep(5000) - ReorgWaitTimeout = 30 * time.Millisecond - batchInsertDeleteRangeSize = 2 - - config.UpdateGlobal(func(conf *config.Config) { - // Test for table lock. - conf.EnableTableLock = true - conf.Log.SlowThreshold = 10000 - conf.TiKVClient.AsyncCommit.SafeWindow = 0 - conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 - conf.Experimental.AllowsExpressionIndex = true - }) - tikv.EnableFailpoints() - - _, err = infosync.GlobalInfoSyncerInit(context.Background(), "t", func() uint64 { return 1 }, nil, true) - if err != nil { - t.Fatal(err) - } - - testleak.BeforeTest() - TestingT(t) - testleak.AfterTestT(t)() -} - func testNewDDLAndStart(ctx context.Context, options ...Option) (*ddl, error) { // init infoCache and a stub infoSchema ic := infoschema.NewCache(2) @@ -107,9 +68,9 @@ func testNewDDLAndStart(ctx context.Context, options ...Option) (*ddl, error) { return d, err } -func testCreateStore(c *C, name string) kv.Storage { +func createMockStore(t *testing.T) kv.Storage { store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) + require.NoError(t, err) return store } @@ -119,18 +80,7 @@ func testNewContext(d *ddl) sessionctx.Context { return ctx } -func getSchemaVer(c *C, ctx sessionctx.Context) int64 { - err := ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - m := meta.NewMeta(txn) - ver, err := m.GetSchemaVersion() - c.Assert(err, IsNil) - return ver -} - -func getSchemaVerT(t *testing.T, ctx sessionctx.Context) int64 { +func getSchemaVer(t *testing.T, ctx sessionctx.Context) int64 { err := ctx.NewTxn(context.Background()) require.NoError(t, err) txn, err := ctx.Txn(true) @@ -148,70 +98,37 @@ type historyJobArgs struct { tblIDs map[int64]struct{} } -func checkEqualTable(c *C, t1, t2 *model.TableInfo) { - c.Assert(t1.ID, Equals, t2.ID) - c.Assert(t1.Name, Equals, t2.Name) - c.Assert(t1.Charset, Equals, t2.Charset) - c.Assert(t1.Collate, Equals, t2.Collate) - c.Assert(t1.PKIsHandle, DeepEquals, t2.PKIsHandle) - c.Assert(t1.Comment, DeepEquals, t2.Comment) - c.Assert(t1.AutoIncID, DeepEquals, t2.AutoIncID) -} - -func checkEqualTableT(t *testing.T, t1, t2 *model.TableInfo) { +func checkEqualTable(t *testing.T, t1, t2 *model.TableInfo) { require.Equal(t, t1.ID, t2.ID) require.Equal(t, t1.Name, t2.Name) require.Equal(t, t1.Charset, t2.Charset) require.Equal(t, t1.Collate, t2.Collate) - require.EqualValues(t, t1.PKIsHandle, t2.PKIsHandle) - require.EqualValues(t, t1.Comment, t2.Comment) - require.EqualValues(t, t1.AutoIncID, t2.AutoIncID) + require.Equal(t, t1.PKIsHandle, t2.PKIsHandle) + require.Equal(t, t1.Comment, t2.Comment) + require.Equal(t, t1.AutoIncID, t2.AutoIncID) } -func checkHistoryJob(c *C, job *model.Job) { - c.Assert(job.State, Equals, model.JobStateSynced) -} - -func checkHistoryJobArgs(c *C, ctx sessionctx.Context, id int64, args *historyJobArgs) { - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - t := meta.NewMeta(txn) - historyJob, err := t.GetHistoryDDLJob(id) - c.Assert(err, IsNil) - c.Assert(historyJob.BinlogInfo.FinishedTS, Greater, uint64(0)) - - if args.tbl != nil { - c.Assert(historyJob.BinlogInfo.SchemaVersion, Equals, args.ver) - checkEqualTable(c, historyJob.BinlogInfo.TableInfo, args.tbl) - return - } - - // for handling schema job - c.Assert(historyJob.BinlogInfo.SchemaVersion, Equals, args.ver) - c.Assert(historyJob.BinlogInfo.DBInfo, DeepEquals, args.db) - // only for creating schema job - if args.db != nil && len(args.tblIDs) == 0 { - return - } +func checkHistoryJob(t *testing.T, job *model.Job) { + require.Equal(t, job.State, model.JobStateSynced) } -func checkHistoryJobArgsT(t *testing.T, ctx sessionctx.Context, id int64, args *historyJobArgs) { +func checkHistoryJobArgs(t *testing.T, ctx sessionctx.Context, id int64, args *historyJobArgs) { txn, err := ctx.Txn(true) require.NoError(t, err) - tt := meta.NewMeta(txn) - historyJob, err := tt.GetHistoryDDLJob(id) + tran := meta.NewMeta(txn) + historyJob, err := tran.GetHistoryDDLJob(id) require.NoError(t, err) require.Greater(t, historyJob.BinlogInfo.FinishedTS, uint64(0)) if args.tbl != nil { - require.Equal(t, args.ver, historyJob.BinlogInfo.SchemaVersion) - checkEqualTableT(t, historyJob.BinlogInfo.TableInfo, args.tbl) + require.Equal(t, historyJob.BinlogInfo.SchemaVersion, args.ver) + checkEqualTable(t, historyJob.BinlogInfo.TableInfo, args.tbl) return } // for handling schema job - require.Equal(t, args.ver, historyJob.BinlogInfo.SchemaVersion) - require.EqualValues(t, args.db, historyJob.BinlogInfo.DBInfo) + require.Equal(t, historyJob.BinlogInfo.SchemaVersion, args.ver) + require.Equal(t, historyJob.BinlogInfo.DBInfo, args.db) // only for creating schema job if args.db != nil && len(args.tblIDs) == 0 { return @@ -231,37 +148,28 @@ func buildCreateIdxJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bo } } -func buildModifyColJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - newCol := table.ToColumn(tblInfo.Columns[0]) - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionModifyColumn, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{&newCol, newCol.Name, ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 0}, - } -} - -func testCreatePrimaryKey(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { +func testCreatePrimaryKey(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, colName string) *model.Job { job := buildCreateIdxJob(dbInfo, tblInfo, true, "primary", colName) job.Type = model.ActionAddPrimaryKey - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } -func testCreateIndex(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { +func testCreateIndex(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { job := buildCreateIdxJob(dbInfo, tblInfo, unique, indexName, colName) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } -func testAddColumn(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, args []interface{}) *model.Job { +func testAddColumn(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, args []interface{}) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, TableID: tblInfo.ID, @@ -269,25 +177,12 @@ func testAddColumn(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, t Args: args, BinlogInfo: &model.HistoryInfo{}, } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} -func testAddColumns(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, args []interface{}) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionAddColumns, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } @@ -305,26 +200,18 @@ func buildDropIdxJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName s } } -func testDropIndex(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName string) *model.Job { +func testDropIndex(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName string) *model.Job { job := buildDropIdxJob(dbInfo, tblInfo, indexName) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} -func buildRebaseAutoIDJobJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, newBaseID int64) *model.Job { - return &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionRebaseAutoID, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{newBaseID}, - } + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + return job } -func (s *testDDLSuite) TestGetIntervalFromPolicy(c *C) { +func TestGetIntervalFromPolicy(t *testing.T) { policy := []time.Duration{ 1 * time.Second, 2 * time.Second, @@ -335,18 +222,272 @@ func (s *testDDLSuite) TestGetIntervalFromPolicy(c *C) { ) val, changed = getIntervalFromPolicy(policy, 0) - c.Assert(val, Equals, 1*time.Second) - c.Assert(changed, Equals, true) + require.Equal(t, val, 1*time.Second) + require.True(t, changed) val, changed = getIntervalFromPolicy(policy, 1) - c.Assert(val, Equals, 2*time.Second) - c.Assert(changed, Equals, true) + require.Equal(t, val, 2*time.Second) + require.True(t, changed) val, changed = getIntervalFromPolicy(policy, 2) - c.Assert(val, Equals, 2*time.Second) - c.Assert(changed, Equals, false) + require.Equal(t, val, 2*time.Second) + require.False(t, changed) val, changed = getIntervalFromPolicy(policy, 3) - c.Assert(val, Equals, 2*time.Second) - c.Assert(changed, Equals, false) + require.Equal(t, val, 2*time.Second) + require.False(t, changed) +} + +func colDefStrToFieldType(t *testing.T, str string, ctx sessionctx.Context) *types.FieldType { + sqlA := "alter table t modify column a " + str + stmt, err := parser.New().ParseOneStmt(sqlA, "", "") + require.NoError(t, err) + colDef := stmt.(*ast.AlterTableStmt).Specs[0].NewColumns[0] + chs, coll := charset.GetDefaultCharsetAndCollate() + col, _, err := buildColumnAndConstraint(ctx, 0, colDef, nil, chs, coll) + require.NoError(t, err) + return &col.FieldType +} + +func TestModifyColumn(t *testing.T) { + ctx := mock.NewContext() + tests := []struct { + origin string + to string + err error + }{ + {"int", "bigint", nil}, + {"int", "int unsigned", nil}, + {"varchar(10)", "text", nil}, + {"varbinary(10)", "blob", nil}, + {"text", "blob", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from utf8mb4 to binary")}, + {"varchar(10)", "varchar(8)", nil}, + {"varchar(10)", "varchar(11)", nil}, + {"varchar(10) character set utf8 collate utf8_bin", "varchar(10) character set utf8", nil}, + {"decimal(2,1)", "decimal(3,2)", nil}, + {"decimal(2,1)", "decimal(2,2)", nil}, + {"decimal(2,1)", "decimal(2,1)", nil}, + {"decimal(2,1)", "int", nil}, + {"decimal", "int", nil}, + {"decimal(2,1)", "bigint", nil}, + {"int", "varchar(10) character set gbk", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from binary to gbk")}, + {"varchar(10) character set gbk", "int", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from gbk to binary")}, + {"varchar(10) character set gbk", "varchar(10) character set utf8", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from gbk to utf8")}, + {"varchar(10) character set gbk", "char(10) character set utf8", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from gbk to utf8")}, + {"varchar(10) character set utf8", "char(10) character set gbk", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from utf8 to gbk")}, + {"varchar(10) character set utf8", "varchar(10) character set gbk", dbterror.ErrUnsupportedModifyCharset.GenWithStackByArgs("charset from utf8 to gbk")}, + {"varchar(10) character set gbk", "varchar(255) character set gbk", nil}, + } + for _, tt := range tests { + ftA := colDefStrToFieldType(t, tt.origin, ctx) + ftB := colDefStrToFieldType(t, tt.to, ctx) + err := checkModifyTypes(ctx, ftA, ftB, false) + if err == nil { + require.NoErrorf(t, tt.err, "origin:%v, to:%v", tt.origin, tt.to) + } else { + require.EqualError(t, err, tt.err.Error()) + } + } +} + +func TestFieldCase(t *testing.T) { + var fields = []string{"field", "Field"} + colObjects := make([]*model.ColumnInfo, len(fields)) + for i, name := range fields { + colObjects[i] = &model.ColumnInfo{ + Name: model.NewCIStr(name), + } + } + err := checkDuplicateColumn(colObjects) + require.EqualError(t, err, infoschema.ErrColumnExists.GenWithStackByArgs("Field").Error()) +} + +func TestIgnorableSpec(t *testing.T) { + specs := []ast.AlterTableType{ + ast.AlterTableOption, + ast.AlterTableAddColumns, + ast.AlterTableAddConstraint, + ast.AlterTableDropColumn, + ast.AlterTableDropPrimaryKey, + ast.AlterTableDropIndex, + ast.AlterTableDropForeignKey, + ast.AlterTableModifyColumn, + ast.AlterTableChangeColumn, + ast.AlterTableRenameTable, + ast.AlterTableAlterColumn, + } + for _, spec := range specs { + require.False(t, isIgnorableSpec(spec)) + } + + ignorableSpecs := []ast.AlterTableType{ + ast.AlterTableLock, + ast.AlterTableAlgorithm, + } + for _, spec := range ignorableSpecs { + require.True(t, isIgnorableSpec(spec)) + } +} + +func TestBuildJobDependence(t *testing.T) { + store := createMockStore(t) + defer func() { + require.NoError(t, store.Close()) + }() + // Add some non-add-index jobs. + job1 := &model.Job{ID: 1, TableID: 1, Type: model.ActionAddColumn} + job2 := &model.Job{ID: 2, TableID: 1, Type: model.ActionCreateTable} + job3 := &model.Job{ID: 3, TableID: 2, Type: model.ActionDropColumn} + job6 := &model.Job{ID: 6, TableID: 1, Type: model.ActionDropTable} + job7 := &model.Job{ID: 7, TableID: 2, Type: model.ActionModifyColumn} + job9 := &model.Job{ID: 9, SchemaID: 111, Type: model.ActionDropSchema} + job11 := &model.Job{ID: 11, TableID: 2, Type: model.ActionRenameTable, Args: []interface{}{int64(111), "old db name"}} + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + require.NoError(t, m.EnQueueDDLJob(job1)) + require.NoError(t, m.EnQueueDDLJob(job2)) + require.NoError(t, m.EnQueueDDLJob(job3)) + require.NoError(t, m.EnQueueDDLJob(job6)) + require.NoError(t, m.EnQueueDDLJob(job7)) + require.NoError(t, m.EnQueueDDLJob(job9)) + require.NoError(t, m.EnQueueDDLJob(job11)) + return nil + }) + require.NoError(t, err) + job4 := &model.Job{ID: 4, TableID: 1, Type: model.ActionAddIndex} + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := buildJobDependence(m, job4) + require.NoError(t, err) + require.Equal(t, job4.DependencyID, int64(2)) + return nil + }) + require.NoError(t, err) + job5 := &model.Job{ID: 5, TableID: 2, Type: model.ActionAddIndex} + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := buildJobDependence(m, job5) + require.NoError(t, err) + require.Equal(t, job5.DependencyID, int64(3)) + return nil + }) + require.NoError(t, err) + job8 := &model.Job{ID: 8, TableID: 3, Type: model.ActionAddIndex} + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := buildJobDependence(m, job8) + require.NoError(t, err) + require.Equal(t, job8.DependencyID, int64(0)) + return nil + }) + require.NoError(t, err) + job10 := &model.Job{ID: 10, SchemaID: 111, TableID: 3, Type: model.ActionAddIndex} + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := buildJobDependence(m, job10) + require.NoError(t, err) + require.Equal(t, job10.DependencyID, int64(9)) + return nil + }) + require.NoError(t, err) + job12 := &model.Job{ID: 12, SchemaID: 112, TableID: 2, Type: model.ActionAddIndex} + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := buildJobDependence(m, job12) + require.NoError(t, err) + require.Equal(t, job12.DependencyID, int64(11)) + return nil + }) + require.NoError(t, err) +} + +func TestNotifyDDLJob(t *testing.T) { + store := createMockStore(t) + defer func() { + require.NoError(t, store.Close()) + }() + + getFirstNotificationAfterStartDDL := func(d *ddl) { + select { + case <-d.workers[addIdxWorker].ddlJobCh: + default: + // The notification may be received by the worker. + } + select { + case <-d.workers[generalWorker].ddlJobCh: + default: + // The notification may be received by the worker. + } + } + + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() + getFirstNotificationAfterStartDDL(d) + // Ensure that the notification is not handled in workers `start` function. + d.cancel() + for _, worker := range d.workers { + worker.close() + } + + job := &model.Job{ + SchemaID: 1, + TableID: 2, + Type: model.ActionCreateTable, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{}, + } + // Test the notification mechanism of the owner and the server receiving the DDL request on the same TiDB. + // This DDL request is a general DDL job. + d.asyncNotifyWorker(job) + select { + case <-d.workers[generalWorker].ddlJobCh: + default: + require.FailNow(t, "do not get the general job notification") + } + // Test the notification mechanism of the owner and the server receiving the DDL request on the same TiDB. + // This DDL request is a add index DDL job. + job.Type = model.ActionAddIndex + d.asyncNotifyWorker(job) + select { + case <-d.workers[addIdxWorker].ddlJobCh: + default: + require.FailNow(t, "do not get the add index job notification") + } + + // Test the notification mechanism that the owner and the server receiving the DDL request are not on the same TiDB. + // And the etcd client is nil. + d1, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + require.NoError(t, d1.Stop()) + }() + getFirstNotificationAfterStartDDL(d1) + // Ensure that the notification is not handled by worker's "start". + d1.cancel() + for _, worker := range d1.workers { + worker.close() + } + d1.ownerManager.RetireOwner() + d1.asyncNotifyWorker(job) + job.Type = model.ActionCreateTable + d1.asyncNotifyWorker(job) + testCheckOwner(t, d1, false) + select { + case <-d1.workers[addIdxWorker].ddlJobCh: + require.FailNow(t, "should not get the add index job notification") + case <-d1.workers[generalWorker].ddlJobCh: + require.FailNow(t, "should not get the general job notification") + default: + } } diff --git a/ddl/ddl_tiflash_api.go b/ddl/ddl_tiflash_api.go new file mode 100644 index 0000000000000..5638cc4bbb39d --- /dev/null +++ b/ddl/ddl_tiflash_api.go @@ -0,0 +1,612 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +package ddl + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl/placement" + ddlutil "github.com/pingcap/tidb/ddl/util" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/gcutil" + "github.com/pingcap/tidb/util/logutil" + atomicutil "go.uber.org/atomic" + "go.uber.org/zap" +) + +// TiFlashReplicaStatus records status for each TiFlash replica. +type TiFlashReplicaStatus struct { + ID int64 + Count uint64 + LocationLabels []string + Available bool + HighPriority bool + IsPartition bool +} + +// TiFlashTick is type for backoff threshold. +type TiFlashTick float64 + +// PollTiFlashBackoffElement records backoff for each TiFlash Table. +// `Counter` increases every `Tick`, if it reached `Threshold`, it will be reset to 0 while `Threshold` grows. +// `TotalCounter` records total `Tick`s this element has since created. +type PollTiFlashBackoffElement struct { + Counter int + Threshold TiFlashTick + TotalCounter int +} + +// NewPollTiFlashBackoffElement initialize backoff element for a TiFlash table. +func NewPollTiFlashBackoffElement() *PollTiFlashBackoffElement { + return &PollTiFlashBackoffElement{ + Counter: 0, + Threshold: PollTiFlashBackoffMinTick, + TotalCounter: 0, + } +} + +// PollTiFlashBackoffContext is a collection of all backoff states. +type PollTiFlashBackoffContext struct { + MinThreshold TiFlashTick + MaxThreshold TiFlashTick + // Capacity limits tables a backoff pool can handle, in order to limit handling of big tables. + Capacity int + Rate TiFlashTick + elements map[int64]*PollTiFlashBackoffElement +} + +// NewPollTiFlashBackoffContext creates an instance of PollTiFlashBackoffContext. +func NewPollTiFlashBackoffContext(MinThreshold, MaxThreshold TiFlashTick, Capacity int, Rate TiFlashTick) (*PollTiFlashBackoffContext, error) { + if MaxThreshold < MinThreshold { + return nil, fmt.Errorf("`MaxThreshold` should always be larger than `MinThreshold`") + } + if MinThreshold < 1 { + return nil, fmt.Errorf("`MinThreshold` should not be less than 1") + } + if Capacity < 0 { + return nil, fmt.Errorf("negative `Capacity`") + } + if Rate <= 1 { + return nil, fmt.Errorf("`Rate` should always be larger than 1") + } + return &PollTiFlashBackoffContext{ + MinThreshold: MinThreshold, + MaxThreshold: MaxThreshold, + Capacity: Capacity, + elements: make(map[int64]*PollTiFlashBackoffElement), + Rate: Rate, + }, nil +} + +// TiFlashManagementContext is the context for TiFlash Replica Management +type TiFlashManagementContext struct { + TiFlashStores map[int64]helper.StoreStat + HandlePdCounter uint64 + UpdateTiFlashStoreCounter uint64 + UpdateMap map[int64]bool + Backoff *PollTiFlashBackoffContext +} + +// Tick will first check increase Counter. +// It returns: +// 1. A bool indicates whether threshold is grown during this tick. +// 2. A bool indicates whether this ID exists. +// 3. A int indicates how many ticks ID has counted till now. +func (b *PollTiFlashBackoffContext) Tick(ID int64) (bool, bool, int) { + e, ok := b.Get(ID) + if !ok { + return false, false, 0 + } + grew := e.MaybeGrow(b) + e.Counter += 1 + e.TotalCounter += 1 + return grew, true, e.TotalCounter +} + +// NeedGrow returns if we need to grow. +// It is exported for testing. +func (e *PollTiFlashBackoffElement) NeedGrow() bool { + return e.Counter >= int(e.Threshold) +} + +func (e *PollTiFlashBackoffElement) doGrow(b *PollTiFlashBackoffContext) { + if e.Threshold < b.MinThreshold { + e.Threshold = b.MinThreshold + } + if e.Threshold*b.Rate > b.MaxThreshold { + e.Threshold = b.MaxThreshold + } else { + e.Threshold *= b.Rate + } + e.Counter = 0 +} + +// MaybeGrow grows threshold and reset counter when needed. +func (e *PollTiFlashBackoffElement) MaybeGrow(b *PollTiFlashBackoffContext) bool { + if !e.NeedGrow() { + return false + } + e.doGrow(b) + return true +} + +// Remove will reset table from backoff. +func (b *PollTiFlashBackoffContext) Remove(ID int64) bool { + _, ok := b.elements[ID] + delete(b.elements, ID) + return ok +} + +// Get returns pointer to inner PollTiFlashBackoffElement. +// Only exported for test. +func (b *PollTiFlashBackoffContext) Get(ID int64) (*PollTiFlashBackoffElement, bool) { + res, ok := b.elements[ID] + return res, ok +} + +// Put will record table into backoff pool, if there is enough room, or returns false. +func (b *PollTiFlashBackoffContext) Put(ID int64) bool { + _, ok := b.elements[ID] + if ok { + return true + } else if b.Len() < b.Capacity { + b.elements[ID] = NewPollTiFlashBackoffElement() + return true + } + return false +} + +// Len gets size of PollTiFlashBackoffContext. +func (b *PollTiFlashBackoffContext) Len() int { + return len(b.elements) +} + +// NewTiFlashManagementContext creates an instance for TiFlashManagementContext. +func NewTiFlashManagementContext() (*TiFlashManagementContext, error) { + c, err := NewPollTiFlashBackoffContext(PollTiFlashBackoffMinTick, PollTiFlashBackoffMaxTick, PollTiFlashBackoffCapacity, PollTiFlashBackoffRate) + if err != nil { + return nil, err + } + return &TiFlashManagementContext{ + HandlePdCounter: 0, + UpdateTiFlashStoreCounter: 0, + TiFlashStores: make(map[int64]helper.StoreStat), + UpdateMap: make(map[int64]bool), + Backoff: c, + }, nil +} + +var ( + // PollTiFlashInterval is the interval between every pollTiFlashReplicaStatus call. + PollTiFlashInterval = 2 * time.Second + // PullTiFlashPdTick indicates the number of intervals before we fully sync all TiFlash pd rules and tables. + PullTiFlashPdTick = atomicutil.NewUint64(30 * 5) + // UpdateTiFlashStoreTick indicates the number of intervals before we fully update TiFlash stores. + UpdateTiFlashStoreTick = atomicutil.NewUint64(5) + // PollTiFlashBackoffMaxTick is the max tick before we try to update TiFlash replica availability for one table. + PollTiFlashBackoffMaxTick TiFlashTick = 10 + // PollTiFlashBackoffMinTick is the min tick before we try to update TiFlash replica availability for one table. + PollTiFlashBackoffMinTick TiFlashTick = 1 + // PollTiFlashBackoffCapacity is the cache size of backoff struct. + PollTiFlashBackoffCapacity int = 1000 + // PollTiFlashBackoffRate is growth rate of exponential backoff threshold. + PollTiFlashBackoffRate TiFlashTick = 1.5 +) + +func getTiflashHTTPAddr(host string, statusAddr string) (string, error) { + configURL := fmt.Sprintf("%s://%s/config", + util.InternalHTTPSchema(), + statusAddr, + ) + resp, err := util.InternalHTTPClient().Get(configURL) + if err != nil { + return "", errors.Trace(err) + } + defer func() { + resp.Body.Close() + }() + + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(resp.Body) + if err != nil { + return "", errors.Trace(err) + } + + var j map[string]interface{} + err = json.Unmarshal(buf.Bytes(), &j) + if err != nil { + return "", errors.Trace(err) + } + + engineStore, ok := j["engine-store"].(map[string]interface{}) + if !ok { + return "", errors.New("Error json") + } + port64, ok := engineStore["http_port"].(float64) + if !ok { + return "", errors.New("Error json") + } + port := int(port64) + + addr := fmt.Sprintf("%v:%v", host, port) + return addr, nil +} + +// GetTiFlashReplicaInfo parses model.TableInfo into []TiFlashReplicaStatus. +func GetTiFlashReplicaInfo(tblInfo *model.TableInfo, tableList *[]TiFlashReplicaStatus) { + if tblInfo.TiFlashReplica == nil { + // reject tables that has no tiflash replica such like `INFORMATION_SCHEMA` + return + } + if pi := tblInfo.GetPartitionInfo(); pi != nil { + for _, p := range pi.Definitions { + logutil.BgLogger().Debug(fmt.Sprintf("Table %v has partition %v\n", tblInfo.ID, p.ID)) + *tableList = append(*tableList, TiFlashReplicaStatus{p.ID, + tblInfo.TiFlashReplica.Count, tblInfo.TiFlashReplica.LocationLabels, tblInfo.TiFlashReplica.IsPartitionAvailable(p.ID), false, true}) + } + // partitions that in adding mid-state + for _, p := range pi.AddingDefinitions { + logutil.BgLogger().Debug(fmt.Sprintf("Table %v has partition adding %v\n", tblInfo.ID, p.ID)) + *tableList = append(*tableList, TiFlashReplicaStatus{p.ID, tblInfo.TiFlashReplica.Count, tblInfo.TiFlashReplica.LocationLabels, tblInfo.TiFlashReplica.IsPartitionAvailable(p.ID), true, true}) + } + } else { + logutil.BgLogger().Debug(fmt.Sprintf("Table %v has no partition\n", tblInfo.ID)) + *tableList = append(*tableList, TiFlashReplicaStatus{tblInfo.ID, tblInfo.TiFlashReplica.Count, tblInfo.TiFlashReplica.LocationLabels, tblInfo.TiFlashReplica.Available, false, false}) + } +} + +// UpdateTiFlashHTTPAddress report TiFlash's StatusAddress's port to Pd's etcd. +func (d *ddl) UpdateTiFlashHTTPAddress(store *helper.StoreStat) error { + addrAndPort := strings.Split(store.Store.StatusAddress, ":") + if len(addrAndPort) < 2 { + return errors.New("Can't get TiFlash Address from PD") + } + httpAddr, err := getTiflashHTTPAddr(addrAndPort[0], store.Store.StatusAddress) + if err != nil { + return errors.Trace(err) + } + // Report to pd + key := fmt.Sprintf("/tiflash/cluster/http_port/%v", store.Store.Address) + if d.etcdCli == nil { + return errors.New("no etcdCli in ddl") + } + origin := "" + resp, err := d.etcdCli.Get(d.ctx, key) + if err != nil { + return errors.Trace(err) + } + // Try to update. + for _, kv := range resp.Kvs { + if string(kv.Key) == key { + origin = string(kv.Value) + break + } + } + if origin != httpAddr { + logutil.BgLogger().Warn(fmt.Sprintf("Update status addr of %v from %v to %v", key, origin, httpAddr)) + err := ddlutil.PutKVToEtcd(d.ctx, d.etcdCli, 1, key, httpAddr) + if err != nil { + return errors.Trace(err) + } + } + + return nil +} + +func updateTiFlashStores(pollTiFlashContext *TiFlashManagementContext) error { + // We need the up-to-date information about TiFlash stores. + // Since TiFlash Replica synchronize may happen immediately after new TiFlash stores are added. + tikvStats, err := infosync.GetTiFlashStoresStat(context.Background()) + // If MockTiFlash is not set, will issue a MockTiFlashError here. + if err != nil { + return err + } + pollTiFlashContext.TiFlashStores = make(map[int64]helper.StoreStat) + for _, store := range tikvStats.Stores { + for _, l := range store.Store.Labels { + if l.Key == "engine" && l.Value == "tiflash" { + pollTiFlashContext.TiFlashStores[store.Store.ID] = store + logutil.BgLogger().Debug("Found tiflash store", zap.Int64("id", store.Store.ID), zap.String("Address", store.Store.Address), zap.String("StatusAddress", store.Store.StatusAddress)) + } + } + } + logutil.BgLogger().Info("updateTiFlashStores finished", zap.Int("TiFlash store count", len(pollTiFlashContext.TiFlashStores))) + return nil +} + +func (d *ddl) pollTiFlashReplicaStatus(ctx sessionctx.Context, pollTiFlashContext *TiFlashManagementContext) (bool, error) { + allReplicaReady := true + defer func() { + pollTiFlashContext.HandlePdCounter += 1 + pollTiFlashContext.HandlePdCounter %= PullTiFlashPdTick.Load() + }() + + updateTiFlash := pollTiFlashContext.UpdateTiFlashStoreCounter%UpdateTiFlashStoreTick.Load() == 0 + if updateTiFlash { + if err := updateTiFlashStores(pollTiFlashContext); err != nil { + // If we failed to get from pd, retry everytime. + pollTiFlashContext.UpdateTiFlashStoreCounter = 0 + return false, err + } + } + pollTiFlashContext.UpdateTiFlashStoreCounter += 1 + pollTiFlashContext.UpdateTiFlashStoreCounter %= UpdateTiFlashStoreTick.Load() + + // The following loop updates TiFlash store's status address. + for _, store := range pollTiFlashContext.TiFlashStores { + s := store + if err := d.UpdateTiFlashHTTPAddress(&s); err != nil { + } + } + + // Start to process every table. + schema := d.GetInfoSchemaWithInterceptor(ctx) + if schema == nil { + return false, errors.New("Schema is nil") + } + + var tableList = make([]TiFlashReplicaStatus, 0) + + // Collect TiFlash Replica info, for every table. + for _, db := range schema.AllSchemas() { + tbls := schema.SchemaTables(db.Name) + for _, tbl := range tbls { + tblInfo := tbl.Meta() + GetTiFlashReplicaInfo(tblInfo, &tableList) + } + } + + for _, tb := range tableList { + // For every region in each table, if it has one replica, we reckon it ready. + // These request can be batched as an optimization. + available := tb.Available + failpoint.Inject("PollTiFlashReplicaStatusReplacePrevAvailableValue", func(val failpoint.Value) { + available = val.(bool) + }) + // We only check unavailable tables here, so doesn't include blocked add partition case. + if !available { + allReplicaReady = false + enabled, inqueue, _ := pollTiFlashContext.Backoff.Tick(tb.ID) + if inqueue && !enabled { + logutil.BgLogger().Info("Escape checking available status due to backoff", zap.Int64("tableId", tb.ID)) + continue + } + + // We don't need to set accelerate schedule for this table, since it is already done in DDL, when + // 1. Add partition + // 2. Set TiFlash replica + + // Compute sync data process by request TiFlash. + regionReplica := make(map[int64]int) + for _, store := range pollTiFlashContext.TiFlashStores { + err := helper.CollectTiFlashStatus(store.Store.StatusAddress, tb.ID, ®ionReplica) + if err != nil { + return allReplicaReady, errors.Trace(err) + } + } + + logutil.BgLogger().Debug("CollectTiFlashStatus", zap.Any("regionReplica", regionReplica), zap.Int64("tableID", tb.ID)) + + var stats helper.PDRegionStats + if err := infosync.GetTiFlashPDRegionRecordStats(context.Background(), tb.ID, &stats); err != nil { + return allReplicaReady, err + } + regionCount := stats.Count + flashRegionCount := len(regionReplica) + avail := regionCount == flashRegionCount + failpoint.Inject("PollTiFlashReplicaStatusReplaceCurAvailableValue", func(val failpoint.Value) { + avail = val.(bool) + }) + + if !avail { + logutil.BgLogger().Info("Tiflash replica is not available", zap.Int64("tableID", tb.ID), zap.Uint64("region need", uint64(regionCount)), zap.Uint64("region have", uint64(flashRegionCount))) + pollTiFlashContext.Backoff.Put(tb.ID) + err := infosync.UpdateTiFlashTableSyncProgress(context.Background(), tb.ID, float64(flashRegionCount)/float64(regionCount)) + if err != nil { + return false, err + } + } else { + logutil.BgLogger().Info("Tiflash replica is available", zap.Int64("tableID", tb.ID), zap.Uint64("region need", uint64(regionCount))) + pollTiFlashContext.Backoff.Remove(tb.ID) + err := infosync.DeleteTiFlashTableSyncProgress(tb.ID) + if err != nil { + return false, err + } + } + failpoint.Inject("skipUpdateTableReplicaInfoInLoop", func() { + failpoint.Continue() + }) + // Will call `onUpdateFlashReplicaStatus` to update `TiFlashReplica`. + if err := d.UpdateTableReplicaInfo(ctx, tb.ID, avail); err != nil { + if infoschema.ErrTableNotExists.Equal(err) && tb.IsPartition { + // May be due to blocking add partition + logutil.BgLogger().Info("updating TiFlash replica status err, maybe false alarm by blocking add", zap.Error(err), zap.Int64("tableID", tb.ID), zap.Bool("isPartition", tb.IsPartition)) + } else { + logutil.BgLogger().Error("updating TiFlash replica status err", zap.Error(err), zap.Int64("tableID", tb.ID), zap.Bool("isPartition", tb.IsPartition)) + } + } + } + } + + return allReplicaReady, nil +} + +func getDropOrTruncateTableTiflash(ctx sessionctx.Context, currentSchema infoschema.InfoSchema, tikvHelper *helper.Helper, replicaInfos *[]TiFlashReplicaStatus) error { + store := tikvHelper.Store.(kv.Storage) + + txn, err := store.Begin() + if err != nil { + return errors.Trace(err) + } + gcSafePoint, err := gcutil.GetGCSafePoint(ctx) + if err != nil { + return err + } + uniqueIDMap := make(map[int64]struct{}) + handleJobAndTableInfo := func(job *model.Job, tblInfo *model.TableInfo) (bool, error) { + // Avoid duplicate table ID info. + if _, ok := currentSchema.TableByID(tblInfo.ID); ok { + return false, nil + } + if _, ok := uniqueIDMap[tblInfo.ID]; ok { + return false, nil + } + uniqueIDMap[tblInfo.ID] = struct{}{} + GetTiFlashReplicaInfo(tblInfo, replicaInfos) + return false, nil + } + fn := func(jobs []*model.Job) (bool, error) { + getTable := func(StartTS uint64, SchemaID int64, TableID int64) (*model.TableInfo, error) { + snapMeta := meta.NewSnapshotMeta(store.GetSnapshot(kv.NewVersion(StartTS))) + if err != nil { + return nil, err + } + tbl, err := snapMeta.GetTable(SchemaID, TableID) + return tbl, err + } + return GetDropOrTruncateTableInfoFromJobsByStore(jobs, gcSafePoint, getTable, handleJobAndTableInfo) + } + + err = admin.IterAllDDLJobs(txn, fn) + if err != nil { + if terror.ErrorEqual(variable.ErrSnapshotTooOld, err) { + // The err indicate that current ddl job and remain DDL jobs was been deleted by GC, + // just ignore the error and return directly. + return nil + } + return err + } + return nil +} + +// HandlePlacementRuleRoutine fetch all rules from pd, remove all obsolete rules. +// It handles rare situation, when we fail to alter pd rules. +func HandlePlacementRuleRoutine(ctx sessionctx.Context, d *ddl, tableList []TiFlashReplicaStatus) error { + c := context.Background() + tikvStore, ok := ctx.GetStore().(helper.Storage) + if !ok { + return errors.New("Can not get Helper") + } + tikvHelper := &helper.Helper{ + Store: tikvStore, + RegionCache: tikvStore.GetRegionCache(), + } + + allRulesArr, err := infosync.GetTiFlashGroupRules(c, "tiflash") + if err != nil { + return errors.Trace(err) + } + allRules := make(map[string]placement.TiFlashRule) + for _, r := range allRulesArr { + allRules[r.ID] = r + } + + start := time.Now() + originLen := len(tableList) + currentSchema := d.GetInfoSchemaWithInterceptor(ctx) + if err := getDropOrTruncateTableTiflash(ctx, currentSchema, tikvHelper, &tableList); err != nil { + // may fail when no `tikv_gc_safe_point` available, should return in order to remove valid pd rules. + logutil.BgLogger().Error("getDropOrTruncateTableTiflash returns error", zap.Error(err)) + return errors.Trace(err) + } + elapsed := time.Since(start) + logutil.BgLogger().Info("getDropOrTruncateTableTiflash cost", zap.Duration("time", elapsed), zap.Int("updated", len(tableList)-originLen)) + for _, tb := range tableList { + // For every region in each table, if it has one replica, we reckon it ready. + ruleID := fmt.Sprintf("table-%v-r", tb.ID) + if _, ok := allRules[ruleID]; !ok { + // Mostly because of a previous failure of setting pd rule. + logutil.BgLogger().Warn(fmt.Sprintf("Table %v exists, but there are no rule for it", tb.ID)) + newRule := infosync.MakeNewRule(tb.ID, tb.Count, tb.LocationLabels) + _ = infosync.SetTiFlashPlacementRule(context.Background(), *newRule) + } + // For every existing table, we do not remove their rules. + delete(allRules, ruleID) + } + + // Remove rules of non-existing table + for _, v := range allRules { + logutil.BgLogger().Info("Remove TiFlash rule", zap.String("id", v.ID)) + if err := infosync.DeleteTiFlashPlacementRule(c, "tiflash", v.ID); err != nil { + logutil.BgLogger().Warn("delete TiFlash pd rule failed", zap.Error(err), zap.String("ruleID", v.ID)) + } + } + + return nil +} + +func (d *ddl) PollTiFlashRoutine() { + pollTiflashContext, err := NewTiFlashManagementContext() + if err != nil { + logutil.BgLogger().Fatal("TiFlashManagement init failed", zap.Error(err)) + } + for { + select { + case <-d.ctx.Done(): + return + case <-time.After(PollTiFlashInterval): + } + if d.IsTiFlashPollEnabled() { + if d.sessPool == nil { + logutil.BgLogger().Error("failed to get sessionPool for pollTiFlashReplicaStatus") + return + } + failpoint.Inject("BeforePollTiFlashReplicaStatusLoop", func() { + failpoint.Continue() + }) + sctx, err := d.sessPool.get() + if err == nil { + if d.ownerManager.IsOwner() { + _, err := d.pollTiFlashReplicaStatus(sctx, pollTiflashContext) + if err != nil { + switch err.(type) { + case *infosync.MockTiFlashError: + // If we have not set up MockTiFlash instance, for those tests without TiFlash, just suppress. + default: + logutil.BgLogger().Warn("pollTiFlashReplicaStatus returns error", zap.Error(err)) + } + } + } + d.sessPool.put(sctx) + } else { + if sctx != nil { + d.sessPool.put(sctx) + } + logutil.BgLogger().Error("failed to get session for pollTiFlashReplicaStatus", zap.Error(err)) + } + } + } +} diff --git a/ddl/ddl_tiflash_test.go b/ddl/ddl_tiflash_test.go new file mode 100644 index 0000000000000..bd4efc96c3dac --- /dev/null +++ b/ddl/ddl_tiflash_test.go @@ -0,0 +1,949 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +package ddl_test + +import ( + "context" + "fmt" + "math" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/kvproto/pkg/metapb" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/ddl/placement" + ddlutil "github.com/pingcap/tidb/ddl/util" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/store/gcworker" + "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/store/mockstore/unistore" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/logutil" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/testutils" + "go.uber.org/zap" +) + +type tiflashContext struct { + store kv.Storage + dom *domain.Domain + tiflash *infosync.MockTiFlash + cluster *unistore.Cluster +} + +const ( + RoundToBeAvailable = 2 + RoundToBeAvailablePartitionTable = 3 +) + +func createTiFlashContext(t *testing.T) (*tiflashContext, func()) { + s := &tiflashContext{} + var err error + + ddl.PollTiFlashInterval = 1000 * time.Millisecond + ddl.PullTiFlashPdTick.Store(60) + s.tiflash = infosync.NewMockTiFlash() + s.store, err = mockstore.NewMockStore( + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockCluster := c.(*unistore.Cluster) + _, _, region1 := mockstore.BootstrapWithSingleStore(c) + tiflashIdx := 0 + for tiflashIdx < 2 { + store2 := c.AllocID() + peer2 := c.AllocID() + addr2 := fmt.Sprintf("tiflash%d", tiflashIdx) + mockCluster.AddStore(store2, addr2, &metapb.StoreLabel{Key: "engine", Value: "tiflash"}) + mockCluster.AddPeer(region1, store2, peer2) + tiflashIdx++ + } + s.cluster = mockCluster + }), + mockstore.WithStoreType(mockstore.EmbedUnistore), + ) + + require.NoError(t, err) + session.SetSchemaLease(0) + session.DisableStats4Test() + s.dom, err = session.BootstrapSession(s.store) + infosync.SetMockTiFlash(s.tiflash) + require.NoError(t, err) + s.dom.SetStatsUpdating(true) + + tearDown := func() { + s.tiflash.Lock() + s.tiflash.StatusServer.Close() + s.tiflash.Unlock() + s.dom.Close() + require.NoError(t, s.store.Close()) + ddl.PollTiFlashInterval = 2 * time.Second + } + return s, tearDown +} + +func ChangeGCSafePoint(tk *testkit.TestKit, t time.Time, enable string, lifeTime string) { + gcTimeFormat := "20060102-15:04:05 -0700 MST" + lastSafePoint := t.Format(gcTimeFormat) + s := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + s = fmt.Sprintf(s, lastSafePoint) + tk.MustExec(s) + s = `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_enable','%[1]s','') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + s = fmt.Sprintf(s, enable) + tk.MustExec(s) + s = `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_life_time','%[1]s','') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + s = fmt.Sprintf(s, lifeTime) + tk.MustExec(s) +} + +func CheckPlacementRule(tiflash *infosync.MockTiFlash, rule placement.TiFlashRule) bool { + return tiflash.CheckPlacementRule(rule) +} + +func (s *tiflashContext) CheckFlashback(tk *testkit.TestKit, t *testing.T) { + // If table is dropped after tikv_gc_safe_point, it can be recovered + ChangeGCSafePoint(tk, time.Now().Add(-time.Hour), "false", "10m0s") + defer func() { + ChangeGCSafePoint(tk, time.Now(), "true", "10m0s") + }() + + fCancel := TempDisableEmulatorGC() + defer fCancel() + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("flashback table ddltiflash") + time.Sleep(ddl.PollTiFlashInterval * 3) + CheckTableAvailable(s.dom, t, 1, []string{}) + + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + require.NotNil(t, tb) + if tb.Meta().Partition != nil { + for _, e := range tb.Meta().Partition.Definitions { + ruleName := fmt.Sprintf("table-%v-r", e.ID) + _, ok := s.tiflash.GetPlacementRule(ruleName) + require.True(t, ok) + } + } else { + ruleName := fmt.Sprintf("table-%v-r", tb.Meta().ID) + _, ok := s.tiflash.GetPlacementRule(ruleName) + require.True(t, ok) + } +} + +func TempDisableEmulatorGC() func() { + ori := ddlutil.IsEmulatorGCEnable() + f := func() { + if ori { + ddlutil.EmulatorGCEnable() + } else { + ddlutil.EmulatorGCDisable() + } + } + ddlutil.EmulatorGCDisable() + return f +} + +func (s *tiflashContext) SetPdLoop(tick uint64) func() { + originValue := ddl.PullTiFlashPdTick.Swap(tick) + return func() { + ddl.PullTiFlashPdTick.Store(originValue) + } +} + +// Run all kinds of DDLs, and will create no redundant pd rules for TiFlash. +func TestTiFlashNoRedundantPDRules(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + + rpcClient, pdClient, cluster, err := unistore.New("") + require.NoError(t, err) + defer func() { + rpcClient.Close() + pdClient.Close() + cluster.Close() + }() + for _, store := range s.cluster.GetAllStores() { + cluster.AddStore(store.Id, store.Address, store.Labels...) + } + gcWorker, err := gcworker.NewMockGCWorker(s.store) + require.NoError(t, err) + tk := testkit.NewTestKit(t, s.store) + fCancel := TempDisableEmulatorGC() + defer fCancel() + // Disable emulator GC, otherwise delete range will be automatically called. + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) + }() + + fCancelPD := s.SetPdLoop(10000) + defer fCancelPD() + + // Clean all rules + s.tiflash.CleanPlacementRules() + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("drop table if exists ddltiflashp") + tk.MustExec("create table ddltiflash(z int)") + tk.MustExec("create table ddltiflashp(z int) PARTITION BY RANGE(z) (PARTITION p0 VALUES LESS THAN (10),PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30))") + + total := 0 + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("alter table ddltiflash set tiflash replica 1") + total += 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("alter table ddltiflashp set tiflash replica 1") + total += 3 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + lessThan := 40 + tk.MustExec(fmt.Sprintf("ALTER TABLE ddltiflashp ADD PARTITION (PARTITION pn VALUES LESS THAN (%v))", lessThan)) + total += 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("alter table ddltiflashp truncate partition p1") + total += 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + // Now gc will trigger, and will remove dropped partition. + require.NoError(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) + total -= 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("alter table ddltiflashp drop partition p2") + require.NoError(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) + total -= 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("truncate table ddltiflash") + total += 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + require.NoError(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) + total -= 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) + + tk.MustExec("drop table ddltiflash") + total -= 1 + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + require.NoError(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) + require.Equal(t, total, s.tiflash.PlacementRulesLen()) +} + +func TestTiFlashReplicaPartitionTableNormal(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int) PARTITION BY RANGE(z) (PARTITION p0 VALUES LESS THAN (10),PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30))") + + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + replica := tb.Meta().TiFlashReplica + require.Nil(t, replica) + + tk.MustExec("alter table ddltiflash set tiflash replica 1") + lessThan := "40" + tk.MustExec(fmt.Sprintf("ALTER TABLE ddltiflash ADD PARTITION (PARTITION pn VALUES LESS THAN (%v))", lessThan)) + + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + // Should get schema again + CheckTableAvailable(s.dom, t, 1, []string{}) + + tb2, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + require.NotNil(t, tb2) + pi := tb2.Meta().GetPartitionInfo() + require.NotNil(t, pi) + require.NotNil(t, tb2.Meta().TiFlashReplica) + for _, p := range pi.Definitions { + require.True(t, tb2.Meta().TiFlashReplica.IsPartitionAvailable(p.ID)) + if len(p.LessThan) == 1 && p.LessThan[0] == lessThan { + table, ok := s.tiflash.GetTableSyncStatus(int(p.ID)) + require.True(t, ok) + require.True(t, table.Accel) + } + } + require.Zero(t, len(pi.AddingDefinitions)) + s.CheckFlashback(tk, t) +} + +// When block add partition, new partition shall be available even we break `UpdateTableReplicaInfo` +func TestTiFlashReplicaPartitionTableBlock(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int) PARTITION BY RANGE(z) (PARTITION p0 VALUES LESS THAN (10),PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30))") + tk.MustExec("alter table ddltiflash set tiflash replica 1") + // Make sure is available + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + CheckTableAvailable(s.dom, t, 1, []string{}) + + lessThan := "40" + // Stop loop + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/BeforePollTiFlashReplicaStatusLoop", `return`)) + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/ddl/BeforePollTiFlashReplicaStatusLoop") + }() + + tk.MustExec(fmt.Sprintf("ALTER TABLE ddltiflash ADD PARTITION (PARTITION pn VALUES LESS THAN (%v))", lessThan)) + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + pi := tb.Meta().GetPartitionInfo() + require.NotNil(t, pi) + + // Partition `lessThan` shall be ready + for _, p := range pi.Definitions { + require.True(t, tb.Meta().TiFlashReplica.IsPartitionAvailable(p.ID)) + if len(p.LessThan) == 1 && p.LessThan[0] == lessThan { + table, ok := s.tiflash.GetTableSyncStatus(int(p.ID)) + require.True(t, ok) + require.True(t, table.Accel) + } + } + require.Equal(t, 0, len(pi.AddingDefinitions)) + s.CheckFlashback(tk, t) +} + +// TiFlash Table shall be eventually available. +func TestTiFlashReplicaAvailable(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int)") + tk.MustExec("alter table ddltiflash set tiflash replica 1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable * 3) + CheckTableAvailable(s.dom, t, 1, []string{}) + + tk.MustExec("drop table if exists ddltiflash2") + tk.MustExec("create table ddltiflash2 like ddltiflash") + tk.MustExec("alter table ddltiflash2 set tiflash replica 1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable * 3) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash2") + + s.CheckFlashback(tk, t) + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + r, ok := s.tiflash.GetPlacementRule(fmt.Sprintf("table-%v-r", tb.Meta().ID)) + require.NotNil(t, r) + require.True(t, ok) + tk.MustExec("alter table ddltiflash set tiflash replica 0") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable) + tb, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + replica := tb.Meta().TiFlashReplica + require.Nil(t, replica) + r, ok = s.tiflash.GetPlacementRule(fmt.Sprintf("table-%v-r", tb.Meta().ID)) + require.Nil(t, r) + require.False(t, ok) +} + +// Truncate partition shall not block. +func TestTiFlashTruncatePartition(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(i int not null, s varchar(255)) partition by range (i) (partition p0 values less than (10), partition p1 values less than (20))") + tk.MustExec("alter table ddltiflash set tiflash replica 1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + tk.MustExec("insert into ddltiflash values(1, 'abc'), (11, 'def')") + tk.MustExec("alter table ddltiflash truncate partition p1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash") +} + +// Fail truncate partition. +func TestTiFlashFailTruncatePartition(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(i int not null, s varchar(255)) partition by range (i) (partition p0 values less than (10), partition p1 values less than (20))") + tk.MustExec("alter table ddltiflash set tiflash replica 1") + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/FailTiFlashTruncatePartition", `return`)) + defer func() { + failpoint.Disable("github.com/pingcap/tidb/ddl/FailTiFlashTruncatePartition") + }() + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + + tk.MustExec("insert into ddltiflash values(1, 'abc'), (11, 'def')") + tk.MustGetErrMsg("alter table ddltiflash truncate partition p1", "[ddl:-1]enforced error") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash") +} + +// Drop partition shall not block. +func TestTiFlashDropPartition(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(i int not null, s varchar(255)) partition by range (i) (partition p0 values less than (10), partition p1 values less than (20))") + tk.MustExec("alter table ddltiflash set tiflash replica 1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash") + tk.MustExec("alter table ddltiflash drop partition p1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable * 5) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash") +} + +func CheckTableAvailableWithTableName(dom *domain.Domain, t *testing.T, count uint64, labels []string, db string, table string) { + tb, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) + require.NoError(t, err) + replica := tb.Meta().TiFlashReplica + require.NotNil(t, replica) + require.True(t, replica.Available) + require.Equal(t, count, replica.Count) + require.ElementsMatch(t, labels, replica.LocationLabels) +} + +func CheckTableAvailable(dom *domain.Domain, t *testing.T, count uint64, labels []string) { + CheckTableAvailableWithTableName(dom, t, count, labels, "test", "ddltiflash") +} + +func CheckTableNoReplica(dom *domain.Domain, t *testing.T, db string, table string) { + tb, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) + require.NoError(t, err) + replica := tb.Meta().TiFlashReplica + require.Nil(t, replica) +} + +// Truncate table shall not block. +func TestTiFlashTruncateTable(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflashp") + tk.MustExec("create table ddltiflashp(z int not null) partition by range (z) (partition p0 values less than (10), partition p1 values less than (20))") + tk.MustExec("alter table ddltiflashp set tiflash replica 1") + + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + // Should get schema right now + tk.MustExec("truncate table ddltiflashp") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailablePartitionTable) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflashp") + tk.MustExec("drop table if exists ddltiflash2") + tk.MustExec("create table ddltiflash2(z int)") + tk.MustExec("alter table ddltiflash2 set tiflash replica 1") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable) + // Should get schema right now + + tk.MustExec("truncate table ddltiflash2") + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable) + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", "ddltiflash2") +} + +// TiFlash Table shall be eventually available, even with lots of small table created. +func TestTiFlashMassiveReplicaAvailable(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + for i := 0; i < 100; i++ { + tk.MustExec(fmt.Sprintf("drop table if exists ddltiflash%v", i)) + tk.MustExec(fmt.Sprintf("create table ddltiflash%v(z int)", i)) + tk.MustExec(fmt.Sprintf("alter table ddltiflash%v set tiflash replica 1", i)) + } + + time.Sleep(ddl.PollTiFlashInterval * 10) + // Should get schema right now + for i := 0; i < 100; i++ { + CheckTableAvailableWithTableName(s.dom, t, 1, []string{}, "test", fmt.Sprintf("ddltiflash%v", i)) + } +} + +// When set TiFlash replica, tidb shall add one Pd Rule for this table. +// When drop/truncate table, Pd Rule shall be removed in limited time. +func TestSetPlacementRuleNormal(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int)") + tk.MustExec("alter table ddltiflash set tiflash replica 1 location labels 'a','b'") + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + expectRule := infosync.MakeNewRule(tb.Meta().ID, 1, []string{"a", "b"}) + res := CheckPlacementRule(s.tiflash, *expectRule) + require.True(t, res) + + // Set lastSafePoint to a timepoint in future, so all dropped table can be reckon as gc-ed. + ChangeGCSafePoint(tk, time.Now().Add(+3*time.Second), "true", "10m0s") + defer func() { + ChangeGCSafePoint(tk, time.Now(), "true", "10m0s") + }() + fCancelPD := s.SetPdLoop(1) + defer fCancelPD() + tk.MustExec("drop table ddltiflash") + expectRule = infosync.MakeNewRule(tb.Meta().ID, 1, []string{"a", "b"}) + res = CheckPlacementRule(s.tiflash, *expectRule) + require.True(t, res) +} + +// When gc worker works, it will automatically remove pd rule for TiFlash. + +func TestSetPlacementRuleWithGCWorker(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + + rpcClient, pdClient, cluster, err := unistore.New("") + defer func() { + rpcClient.Close() + pdClient.Close() + cluster.Close() + }() + for _, store := range s.cluster.GetAllStores() { + cluster.AddStore(store.Id, store.Address, store.Labels...) + } + failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) + defer func() { + failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + }() + fCancelPD := s.SetPdLoop(10000) + defer fCancelPD() + + require.NoError(t, err) + gcWorker, err := gcworker.NewMockGCWorker(s.store) + require.NoError(t, err) + // Make SetPdLoop take effects. + time.Sleep(time.Second) + + fCancel := TempDisableEmulatorGC() + defer fCancel() + + tk := testkit.NewTestKit(t, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash_gc") + tk.MustExec("create table ddltiflash_gc(z int)") + tk.MustExec("alter table ddltiflash_gc set tiflash replica 1 location labels 'a','b'") + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash_gc")) + require.NoError(t, err) + + expectRule := infosync.MakeNewRule(tb.Meta().ID, 1, []string{"a", "b"}) + res := CheckPlacementRule(s.tiflash, *expectRule) + require.True(t, res) + + ChangeGCSafePoint(tk, time.Now().Add(-time.Hour), "true", "10m0s") + tk.MustExec("drop table ddltiflash_gc") + // Now gc will trigger, and will remove dropped table. + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) + + // Wait GC + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable) + res = CheckPlacementRule(s.tiflash, *expectRule) + require.False(t, res) +} + +func TestSetPlacementRuleFail(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int)") + s.tiflash.PdSwitch(false) + defer func() { + s.tiflash.PdSwitch(true) + }() + tk.MustExec("alter table ddltiflash set tiflash replica 1") + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + + expectRule := infosync.MakeNewRule(tb.Meta().ID, 1, []string{}) + res := CheckPlacementRule(s.tiflash, *expectRule) + require.False(t, res) +} + +// Test standalone backoffer +func TestTiFlashBackoffer(t *testing.T) { + var maxTick ddl.TiFlashTick = 10 + var rate ddl.TiFlashTick = 1.5 + c := 2 + backoff, err := ddl.NewPollTiFlashBackoffContext(1, maxTick, c, rate) + require.NoError(t, err) + mustGet := func(ID int64) *ddl.PollTiFlashBackoffElement { + e, ok := backoff.Get(ID) + require.True(t, ok) + return e + } + mustNotGrow := func(ID int64) { + e := mustGet(ID) + ori := e.Threshold + oriTotal := e.TotalCounter + c := e.Counter + growed, ok, total := backoff.Tick(ID) + require.True(t, ok) + require.False(t, growed) + require.Equal(t, ori, e.Threshold) + require.Equal(t, c+1, e.Counter) + require.Equal(t, oriTotal+1, total) + } + mustGrow := func(ID int64) { + e := mustGet(ID) + ori := e.Threshold + oriTotal := e.TotalCounter + growed, ok, total := backoff.Tick(ID) + require.True(t, ok) + require.True(t, growed) + require.Equal(t, e.Threshold, rate*ori) + require.Equal(t, 1, e.Counter) + require.Equal(t, oriTotal+1, total) + } + // Test grow + ok := backoff.Put(1) + require.True(t, ok) + require.False(t, mustGet(1).NeedGrow()) + mustNotGrow(1) // 0;1 -> 1;1 + mustGrow(1) // 1;1 -> 0;1.5 -> 1;1.5 + mustGrow(1) // 1;1.5 -> 0;2.25 -> 1;2.25 + mustNotGrow(1) // 1;2.25 -> 2;2.25 + mustGrow(1) // 2;2.25 -> 0;3.375 -> 1;3.375 + mustNotGrow(1) // 1;3.375 -> 2;3.375 + mustNotGrow(1) // 2;3.375 -> 3;3.375 + mustGrow(1) // 3;3.375 -> 0;5.0625 + require.Equal(t, 8, mustGet(1).TotalCounter) + + // Test converge + backoff.Put(2) + for i := 0; i < 20; i++ { + backoff.Tick(2) + } + require.Equal(t, maxTick, mustGet(2).Threshold) + require.Equal(t, 20, mustGet(2).TotalCounter) + + // Test context + ok = backoff.Put(3) + require.False(t, ok) + _, ok, _ = backoff.Tick(3) + require.False(t, ok) + + require.True(t, backoff.Remove(1)) + require.False(t, backoff.Remove(1)) + require.Equal(t, 1, backoff.Len()) + + // Test error context + _, err = ddl.NewPollTiFlashBackoffContext(0.5, 1, 1, 1) + require.Error(t, err) + _, err = ddl.NewPollTiFlashBackoffContext(10, 1, 1, 1) + require.Error(t, err) + _, err = ddl.NewPollTiFlashBackoffContext(1, 10, 0, 1) + require.Error(t, err) + _, err = ddl.NewPollTiFlashBackoffContext(1, 10, 1, 0.5) + require.Error(t, err) + _, err = ddl.NewPollTiFlashBackoffContext(1, 10, 1, -1) + require.Error(t, err) +} + +// Test backoffer in TiFlash. +func TestTiFlashBackoff(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists ddltiflash") + tk.MustExec("create table ddltiflash(z int)") + + // Not available for all tables + ddl.DisableTiFlashPoll(s.dom.DDL()) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplacePrevAvailableValue", `return(false)`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplaceCurAvailableValue", `return(false)`)) + ddl.EnableTiFlashPoll(s.dom.DDL()) + tk.MustExec("alter table ddltiflash set tiflash replica 1") + + // 1, 1.5, 2.25, 3.375, 5.5625 + // (1), 1, 1, 2, 3, 5 + time.Sleep(ddl.PollTiFlashInterval * 5) + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + require.NotNil(t, tb) + require.False(t, tb.Meta().TiFlashReplica.Available) + + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplacePrevAvailableValue")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplaceCurAvailableValue")) + + time.Sleep(ddl.PollTiFlashInterval * 3) + tb, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("ddltiflash")) + require.NoError(t, err) + require.NotNil(t, tb) + require.True(t, tb.Meta().TiFlashReplica.Available) +} + +func TestAlterDatabaseErrorGrammar(t *testing.T) { + store, tear := testkit.CreateMockStore(t) + defer tear() + + tk := testkit.NewTestKit(t, store) + tk.MustGetErrMsg("ALTER DATABASE t SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2 LOCATION LABELS 'a','b'", "[ddl:8200]Unsupported multi schema change") + tk.MustGetErrMsg("ALTER DATABASE t SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2", "[ddl:8200]Unsupported multi schema change") + tk.MustGetErrMsg("ALTER DATABASE t SET TIFLASH REPLICA 1 LOCATION LABELS 'a','b' SET TIFLASH REPLICA 2", "[ddl:8200]Unsupported multi schema change") + tk.MustGetErrMsg("ALTER DATABASE t SET TIFLASH REPLICA 1 LOCATION LABELS 'a','b' SET TIFLASH REPLICA 2 LOCATION LABELS 'a','b'", "[ddl:8200]Unsupported multi schema change") +} + +func TestAlterDatabaseBasic(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("drop database if exists tiflash_ddl") + tk.MustExec("create database tiflash_ddl") + tk.MustExec("create table tiflash_ddl.ddltiflash(z int)") + tk.MustExec("create table tiflash_ddl.ddltiflash2(z int)") + // ALTER DATABASE can override previous ALTER TABLE. + tk.MustExec("alter table tiflash_ddl.ddltiflash set tiflash replica 1") + tk.MustExec("alter database tiflash_ddl set tiflash replica 2") + require.Equal(t, "In total 2 tables: 2 succeed, 0 failed, 0 skipped", tk.Session().GetSessionVars().StmtCtx.GetMessage()) + time.Sleep(ddl.PollTiFlashInterval * RoundToBeAvailable * 2) + CheckTableAvailableWithTableName(s.dom, t, 2, []string{}, "tiflash_ddl", "ddltiflash") + CheckTableAvailableWithTableName(s.dom, t, 2, []string{}, "tiflash_ddl", "ddltiflash2") + + // Skip already set TiFlash tables. + tk.MustExec("alter database tiflash_ddl set tiflash replica 2") + require.Equal(t, "In total 2 tables: 0 succeed, 0 failed, 2 skipped", tk.Session().GetSessionVars().StmtCtx.GetMessage()) + CheckTableAvailableWithTableName(s.dom, t, 2, []string{}, "tiflash_ddl", "ddltiflash") + CheckTableAvailableWithTableName(s.dom, t, 2, []string{}, "tiflash_ddl", "ddltiflash2") + + // There is no existing database. + tk.MustExec("drop database if exists tiflash_ddl_missing") + tk.MustGetErrMsg("alter database tiflash_ddl_missing set tiflash replica 2", "[schema:1049]Unknown database 'tiflash_ddl_missing'") + + // There is no table in database + tk.MustExec("drop database if exists tiflash_ddl_empty") + tk.MustExec("create database tiflash_ddl_empty") + tk.MustGetErrMsg("alter database tiflash_ddl_empty set tiflash replica 2", "[schema:1049]Empty database 'tiflash_ddl_empty'") + + // There is less TiFlash store + tk.MustGetErrMsg("alter database tiflash_ddl set tiflash replica 3", "the tiflash replica count: 3 should be less than the total tiflash server count: 2") +} + +func checkBatchPandingNum(t *testing.T, tkx *testkit.TestKit, level string, value string, ok bool) { + l := len(tkx.MustQuery(fmt.Sprintf("show %v variables where Variable_name='tidb_batch_pending_tiflash_count' and Value='%v'", level, value)).Rows()) + if ok { + require.Equal(t, 1, l) + } else { + require.Equal(t, 0, l) + } +} + +func TestTiFlashBatchAddVariables(t *testing.T) { + store, tear := testkit.CreateMockStore(t) + defer tear() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("set SESSION tidb_batch_pending_tiflash_count=5") + tk.MustExec("set GLOBAL tidb_batch_pending_tiflash_count=6") + + checkBatchPandingNum(t, tk, "session", "5", true) + checkBatchPandingNum(t, tk, "global", "6", true) + checkBatchPandingNum(t, tk, "global", "1.5", false) + + tk.MustGetErrMsg("set GLOBAL tidb_batch_pending_tiflash_count=1.5", "[variable:1232]Incorrect argument type to variable 'tidb_batch_pending_tiflash_count'") + checkBatchPandingNum(t, tk, "global", "6", true) + + tk2 := testkit.NewTestKit(t, store) + checkBatchPandingNum(t, tk2, "session", "6", true) +} + +func execWithTimeout(t *testing.T, tk *testkit.TestKit, to time.Duration, sql string) (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), to) + defer cancel() + doneCh := make(chan error, 1) + + go func() { + _, err := tk.Exec(sql) + doneCh <- err + }() + + select { + case e := <-doneCh: + // Exit normally + return false, e + case <-ctx.Done(): + // Exceed given timeout + logutil.BgLogger().Info("execWithTimeout meet timeout", zap.String("sql", sql)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/BatchAddTiFlashSendDone", "return(true)")) + } + + e := <-doneCh + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/BatchAddTiFlashSendDone")) + return true, e +} + +func TestTiFlashBatchRateLimiter(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + threshold := 2 + tk.MustExec("create database tiflash_ddl_limit") + tk.MustExec(fmt.Sprintf("set SESSION tidb_batch_pending_tiflash_count=%v", threshold)) + for i := 0; i < threshold; i++ { + tk.MustExec(fmt.Sprintf("create table tiflash_ddl_limit.t%v(z int)", i)) + } + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplaceCurAvailableValue", `return(false)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/PollTiFlashReplicaStatusReplaceCurAvailableValue")) + }() + + tk.MustExec("alter database tiflash_ddl_limit set tiflash replica 1") + tk.MustExec(fmt.Sprintf("create table tiflash_ddl_limit.t%v(z int)", threshold)) + // The following statement shall fail, because it reaches limit + timeOut, err := execWithTimeout(t, tk, time.Second*1, "alter database tiflash_ddl_limit set tiflash replica 1") + require.NoError(t, err) + require.True(t, timeOut) + + // There must be one table with no TiFlashReplica. + check := func(expected int, total int) { + cnt := 0 + for i := 0; i < total; i++ { + tb, err := s.dom.InfoSchema().TableByName(model.NewCIStr("tiflash_ddl_limit"), model.NewCIStr(fmt.Sprintf("t%v", i))) + require.NoError(t, err) + if tb.Meta().TiFlashReplica != nil { + cnt += 1 + } + } + require.Equal(t, expected, cnt) + } + check(2, 3) + + // If we exec in another session, it will not trigger limit. Since DefTiDBBatchPendingTiFlashCount is more than 3. + tk2 := testkit.NewTestKit(t, s.store) + tk2.MustExec("alter database tiflash_ddl_limit set tiflash replica 1") + check(3, 3) + + loop := 3 + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/FastFailCheckTiFlashPendingTables", fmt.Sprintf("return(%v)", loop))) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/FastFailCheckTiFlashPendingTables")) + }() + // We will force trigger its DDL to update schema cache. + tk.MustExec(fmt.Sprintf("create table tiflash_ddl_limit.t%v(z int)", threshold+1)) + timeOut, err = execWithTimeout(t, tk, time.Millisecond*time.Duration(200*(loop+1)), "alter database tiflash_ddl_limit set tiflash replica 1") + require.NoError(t, err) + require.False(t, timeOut) + check(4, 4) + + // However, forceCheck is true, so we will still enter try loop. + tk.MustExec(fmt.Sprintf("create table tiflash_ddl_limit.t%v(z int)", threshold+2)) + timeOut, err = execWithTimeout(t, tk, time.Millisecond*200, "alter database tiflash_ddl_limit set tiflash replica 1") + require.NoError(t, err) + require.True(t, timeOut) + check(4, 5) + + // Retrigger, but close session before the whole job ends. + var wg util.WaitGroupWrapper + var mu sync.Mutex + wg.Run(func() { + time.Sleep(time.Millisecond * 20) + mu.Lock() + defer mu.Unlock() + tk.Session().Close() + logutil.BgLogger().Info("session closed") + }) + mu.Lock() + timeOut, err = execWithTimeout(t, tk, time.Second*2, "alter database tiflash_ddl_limit set tiflash replica 1") + mu.Unlock() + require.NoError(t, err) + require.False(t, timeOut) + check(5, 5) + wg.Wait() +} + +func TestTiFlashBatchKill(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("create database tiflash_ddl_limit") + tk.MustExec("set SESSION tidb_batch_pending_tiflash_count=0") + tk.MustExec("create table tiflash_ddl_limit.t0(z int)") + + var wg util.WaitGroupWrapper + wg.Run(func() { + time.Sleep(time.Millisecond * 100) + sessVars := tk.Session().GetSessionVars() + atomic.StoreUint32(&sessVars.Killed, 1) + }) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/FastFailCheckTiFlashPendingTables", `return(2)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/FastFailCheckTiFlashPendingTables")) + }() + timeOut, err := execWithTimeout(t, tk, time.Second*2000, "alter database tiflash_ddl_limit set tiflash replica 1") + require.Error(t, err, "[executor:1317]Query execution was interrupted") + require.False(t, timeOut) + wg.Wait() +} + +func TestTiFlashBatchUnsupported(t *testing.T) { + s, teardown := createTiFlashContext(t) + defer teardown() + tk := testkit.NewTestKit(t, s.store) + + tk.MustExec("create database tiflash_ddl_view") + tk.MustExec("create table tiflash_ddl_view.t(z int)") + tk.MustExec("insert into tiflash_ddl_view.t values (1)") + tk.MustExec("CREATE VIEW tiflash_ddl_view.v AS select * from tiflash_ddl_view.t") + tk.MustExec("alter database tiflash_ddl_view set tiflash replica 1") + require.Equal(t, "In total 2 tables: 1 succeed, 0 failed, 1 skipped", tk.Session().GetSessionVars().StmtCtx.GetMessage()) + tk.MustGetErrCode("alter database information_schema set tiflash replica 1", 8200) +} diff --git a/ddl/ddl_worker.go b/ddl/ddl_worker.go index 24c3769217e5d..d1c4f4eafd50a 100644 --- a/ddl/ddl_worker.go +++ b/ddl/ddl_worker.go @@ -25,7 +25,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/kvrpcpb" - pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" @@ -36,12 +35,16 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/binloginfo" "github.com/pingcap/tidb/sessionctx/variable" + pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" tidbutil "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/resourcegrouptag" "github.com/pingcap/tidb/util/topsql" - "go.etcd.io/etcd/clientv3" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/tikv/client-go/v2/tikvrpc" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" ) @@ -91,12 +94,14 @@ type worker struct { reorgCtx *reorgCtx // reorgCtx is used for reorganization. delRangeManager delRangeManager logCtx context.Context + lockSeqNum bool - ddlJobCache + *ddlCtx + *JobContext } -// ddlJobCache is a cache for each DDL job. -type ddlJobCache struct { +// JobContext is the ddl job execution context. +type JobContext struct { // below fields are cache for top sql ddlJobCtx context.Context cacheSQL string @@ -104,18 +109,24 @@ type ddlJobCache struct { cacheDigest *parser.Digest } -func newWorker(ctx context.Context, tp workerType, sessPool *sessionPool, delRangeMgr delRangeManager) *worker { +// NewJobContext returns a new ddl job context. +func NewJobContext() *JobContext { + return &JobContext{ + ddlJobCtx: context.Background(), + cacheSQL: "", + cacheNormalizedSQL: "", + cacheDigest: nil, + } +} + +func newWorker(ctx context.Context, tp workerType, sessPool *sessionPool, delRangeMgr delRangeManager, dCtx *ddlCtx) *worker { worker := &worker{ - id: atomic.AddInt32(&ddlWorkerID, 1), - tp: tp, - ddlJobCh: make(chan struct{}, 1), - ctx: ctx, - ddlJobCache: ddlJobCache{ - ddlJobCtx: context.Background(), - cacheSQL: "", - cacheNormalizedSQL: "", - cacheDigest: nil, - }, + id: atomic.AddInt32(&ddlWorkerID, 1), + tp: tp, + ddlJobCh: make(chan struct{}, 1), + ctx: ctx, + JobContext: NewJobContext(), + ddlCtx: dCtx, reorgCtx: &reorgCtx{notifyCancelReorgJob: 0}, sessPool: sessPool, delRangeManager: delRangeMgr, @@ -229,7 +240,7 @@ func buildJobDependence(t *meta.Meta, curJob *model.Job) error { // Jobs in the same queue are ordered. If we want to find a job's dependency-job, we need to look for // it from the other queue. So if the job is "ActionAddIndex" job, we need find its dependency-job from DefaultJobList. jobListKey := meta.DefaultJobListKey - if !admin.MayNeedBackfill(curJob.Type) { + if !mayNeedReorg(curJob) { jobListKey = meta.AddIndexJobListKey } jobs, err := t.GetAllDDLJobsInQueue(jobListKey) @@ -290,13 +301,25 @@ func (d *ddl) addBatchDDLJobs(tasks []*limitJobTask) { job.Version = currentVersion job.StartTS = txn.StartTS() job.ID = ids[i] + job.State = model.JobStateQueueing if err = buildJobDependence(t, job); err != nil { return errors.Trace(err) } jobListKey := meta.DefaultJobListKey - if admin.MayNeedBackfill(job.Type) { + if mayNeedReorg(job) { jobListKey = meta.AddIndexJobListKey } + failpoint.Inject("MockModifyJobArg", func(val failpoint.Value) { + if val.(bool) { + if job.Type == model.ActionMultiSchemaChange { + if len(job.MultiSchemaInfo.SubJobs) > 0 && len(job.MultiSchemaInfo.SubJobs[0].Args) > 0 { + job.MultiSchemaInfo.SubJobs[0].Args[0] = 1 + } + } else if len(job.Args) > 0 { + job.Args[0] = 1 + } + } + }) if err = t.EnQueueDDLJob(job, jobListKey); err != nil { return errors.Trace(err) } @@ -336,9 +359,22 @@ func (d *ddl) getHistoryDDLJob(id int64) (*model.Job, error) { return job, errors.Trace(err) } +func injectFailPointForGetJob(job *model.Job) { + if job == nil { + return + } + failpoint.Inject("mockModifyJobSchemaId", func(val failpoint.Value) { + job.SchemaID = int64(val.(int)) + }) + failpoint.Inject("MockModifyJobTableId", func(val failpoint.Value) { + job.TableID = int64(val.(int)) + }) +} + // getFirstDDLJob gets the first DDL job form DDL queue. func (w *worker) getFirstDDLJob(t *meta.Meta) (*model.Job, error) { job, err := t.GetDDLJobByIdx(0) + injectFailPointForGetJob(job) return job, errors.Trace(err) } @@ -384,35 +420,59 @@ func (w *worker) deleteRange(ctx context.Context, job *model.Job) error { if job.Version <= currentVersion { err = w.delRangeManager.addDelRangeJob(ctx, job) } else { - err = errInvalidDDLJobVersion.GenWithStackByArgs(job.Version, currentVersion) + err = dbterror.ErrInvalidDDLJobVersion.GenWithStackByArgs(job.Version, currentVersion) } return errors.Trace(err) } -// finishDDLJob deletes the finished DDL job in the ddl queue and puts it to history queue. -// If the DDL job need to handle in background, it will prepare a background job. -func (w *worker) finishDDLJob(t *meta.Meta, job *model.Job) (err error) { - startTime := time.Now() - defer func() { - metrics.DDLWorkerHistogram.WithLabelValues(metrics.WorkerFinishDDLJob, job.Type.String(), metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds()) - }() - +func jobNeedGC(job *model.Job) bool { if !job.IsCancelled() { + if job.Warning != nil && dbterror.ErrCantDropFieldOrKey.Equal(job.Warning) { + // For the field/key not exists warnings, there is no need to + // delete the ranges. + return false + } switch job.Type { case model.ActionAddIndex, model.ActionAddPrimaryKey: if job.State != model.JobStateRollbackDone { break } - // After rolling back an AddIndex operation, we need to use delete-range to delete the half-done index data. - err = w.deleteRange(w.ddlJobCtx, job) + return true case model.ActionDropSchema, model.ActionDropTable, model.ActionTruncateTable, model.ActionDropIndex, model.ActionDropPrimaryKey, - model.ActionDropTablePartition, model.ActionTruncateTablePartition, model.ActionDropColumn, model.ActionDropColumns, model.ActionModifyColumn, model.ActionDropIndexes: - err = w.deleteRange(w.ddlJobCtx, job) + model.ActionDropTablePartition, model.ActionTruncateTablePartition, model.ActionDropColumn, model.ActionModifyColumn: + return true + case model.ActionMultiSchemaChange: + return true + } + } + return false +} + +// finishDDLJob deletes the finished DDL job in the ddl queue and puts it to history queue. +// If the DDL job need to handle in background, it will prepare a background job. +func (w *worker) finishDDLJob(t *meta.Meta, job *model.Job) (err error) { + startTime := time.Now() + defer func() { + metrics.DDLWorkerHistogram.WithLabelValues(metrics.WorkerFinishDDLJob, job.Type.String(), metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds()) + }() + + if jobNeedGC(job) { + err = w.deleteRange(w.ddlJobCtx, job) + if err != nil { + return errors.Trace(err) } } - if job.Type == model.ActionRecoverTable { + + switch job.Type { + case model.ActionRecoverTable: err = finishRecoverTable(w, job) + case model.ActionCreateTables: + if job.IsCancelled() { + // it may be too large that it can not be added to the history queue, too + // delete its arguments + job.Args = nil + } } if err != nil { return errors.Trace(err) @@ -431,10 +491,19 @@ func (w *worker) finishDDLJob(t *meta.Meta, job *model.Job) (err error) { // Notice: warnings is used to support non-strict mode. updateRawArgs = false } + w.writeDDLSeqNum(job) + w.JobContext.resetWhenJobFinish() err = t.AddHistoryDDLJob(job, updateRawArgs) return errors.Trace(err) } +func (w *worker) writeDDLSeqNum(job *model.Job) { + w.ddlSeqNumMu.Lock() + w.ddlSeqNumMu.seqNum++ + w.lockSeqNum = true + job.SeqNum = w.ddlSeqNumMu.seqNum +} + func finishRecoverTable(w *worker, job *model.Job) error { tbInfo := &model.TableInfo{} var autoIncID, autoRandID, dropJobID, recoverTableCheckFlag int64 @@ -476,17 +545,38 @@ func newMetaWithQueueTp(txn kv.Transaction, tp workerType) *meta.Meta { return meta.NewMeta(txn) } -func (w *worker) setDDLLabelForTopSQL(job *model.Job) { - if !variable.TopSQLEnabled() || job == nil { +func (w *JobContext) setDDLLabelForTopSQL(job *model.Job) { + if !topsqlstate.TopSQLEnabled() || job == nil { return } - if job.Query != w.cacheSQL { + if job.Query != w.cacheSQL || w.cacheDigest == nil { w.cacheNormalizedSQL, w.cacheDigest = parser.NormalizeDigest(job.Query) w.cacheSQL = job.Query + w.ddlJobCtx = topsql.AttachSQLInfo(context.Background(), w.cacheNormalizedSQL, w.cacheDigest, "", nil, false) + } else { + topsql.AttachSQLInfo(w.ddlJobCtx, w.cacheNormalizedSQL, w.cacheDigest, "", nil, false) + } +} + +func (w *JobContext) getResourceGroupTaggerForTopSQL() tikvrpc.ResourceGroupTagger { + if !topsqlstate.TopSQLEnabled() || w.cacheDigest == nil { + return nil + } + + digest := w.cacheDigest + tagger := func(req *tikvrpc.Request) { + req.ResourceGroupTag = resourcegrouptag.EncodeResourceGroupTag(digest, nil, + resourcegrouptag.GetResourceGroupLabelByKey(resourcegrouptag.GetFirstKeyFromRequest(req))) } + return tagger +} - w.ddlJobCtx = topsql.AttachSQLInfo(context.Background(), w.cacheNormalizedSQL, w.cacheDigest, "", nil, false) +func (w *JobContext) resetWhenJobFinish() { + w.ddlJobCtx = context.Background() + w.cacheSQL = "" + w.cacheDigest = nil + w.cacheNormalizedSQL = "" } // handleDDLJobQueue handles DDL jobs in DDL Job queue. @@ -524,6 +614,9 @@ func (w *worker) handleDDLJobQueue(d *ddlCtx) error { } w.setDDLLabelForTopSQL(job) + if tagger := w.getResourceGroupTaggerForTopSQL(); tagger != nil { + txn.SetOption(kv.ResourceGroupTagger, tagger) + } if isDone, err1 := isDependencyJobDone(t, job); err1 != nil || !isDone { return errors.Trace(err1) } @@ -583,11 +676,21 @@ func (w *worker) handleDDLJobQueue(d *ddlCtx) error { } if err != nil { + if w.lockSeqNum { + // txn commit failed, we should reset seqNum. + w.ddlSeqNumMu.seqNum-- + w.lockSeqNum = false + w.ddlSeqNumMu.Unlock() + } return errors.Trace(err) } else if job == nil { // No job now, return and retry getting later. return nil } + if w.lockSeqNum { + w.lockSeqNum = false + d.ddlSeqNumMu.Unlock() + } w.waitDependencyJobFinished(job, &waitDependencyJobCnt) // Here means the job enters another state (delete only, write only, public, etc...) or is cancelled. @@ -620,6 +723,10 @@ func skipWriteBinlog(job *model.Job) bool { // it's used to update table's TiFlash replica available status. case model.ActionUpdateTiFlashReplicaStatus: return true + // Don't sync 'alter table cache|nocache' to other tools. + // It's internal to the current cluster. + case model.ActionAlterCacheTable, model.ActionAlterNoCacheTable: + return true } return false @@ -630,7 +737,7 @@ func writeBinlog(binlogCli *pumpcli.PumpsClient, txn kv.Transaction, job *model. // When this column is in the "delete only" and "delete reorg" states, the binlog of "drop column" has not been written yet, // but the column has been removed from the binlog of the write operation. // So we add this binlog to enable downstream components to handle DML correctly in this schema state. - ((job.Type == model.ActionDropColumn || job.Type == model.ActionDropColumns) && job.SchemaState == model.StateDeleteOnly) { + (job.Type == model.ActionDropColumn && job.SchemaState == model.StateDeleteOnly) { if skipWriteBinlog(job) { return } @@ -721,8 +828,13 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, // Mock for run ddl job panic. failpoint.Inject("mockPanicInRunDDLJob", func(val failpoint.Value) {}) - logutil.Logger(w.logCtx).Info("[ddl] run DDL job", zap.String("job", job.String())) + if job.Type != model.ActionMultiSchemaChange { + logutil.Logger(w.logCtx).Info("[ddl] run DDL job", zap.String("job", job.String())) + } timeStart := time.Now() + if job.RealStartTS == 0 { + job.RealStartTS = t.StartTS + } defer func() { metrics.DDLWorkerHistogram.WithLabelValues(metrics.WorkerRunDDLJob, job.Type.String(), metrics.RetLabel(err)).Observe(time.Since(timeStart).Seconds()) }() @@ -754,12 +866,14 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, ver, err = onModifySchemaDefaultPlacement(t, job) case model.ActionCreateTable: ver, err = onCreateTable(d, t, job) + case model.ActionCreateTables: + ver, err = onCreateTables(d, t, job) case model.ActionRepairTable: ver, err = onRepairTable(d, t, job) case model.ActionCreateView: ver, err = onCreateView(d, t, job) case model.ActionDropTable, model.ActionDropView, model.ActionDropSequence: - ver, err = onDropTableOrView(d, t, job) + ver, err = onDropTableOrView(t, job) case model.ActionDropTablePartition: ver, err = w.onDropTablePartition(d, t, job) case model.ActionTruncateTablePartition: @@ -768,12 +882,8 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, ver, err = w.onExchangeTablePartition(d, t, job) case model.ActionAddColumn: ver, err = onAddColumn(d, t, job) - case model.ActionAddColumns: - ver, err = onAddColumns(d, t, job) case model.ActionDropColumn: ver, err = onDropColumn(t, job) - case model.ActionDropColumns: - ver, err = onDropColumns(t, job) case model.ActionModifyColumn: ver, err = w.onModifyColumn(d, t, job) case model.ActionSetDefaultValue: @@ -784,8 +894,6 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, ver, err = w.onCreateIndex(d, t, job, true) case model.ActionDropIndex, model.ActionDropPrimaryKey: ver, err = onDropIndex(t, job) - case model.ActionDropIndexes: - ver, err = onDropIndexes(t, job) case model.ActionRenameIndex: ver, err = onRenameIndex(t, job) case model.ActionAddForeignKey: @@ -837,7 +945,7 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, case model.ActionDropPlacementPolicy: ver, err = onDropPlacementPolicy(d, t, job) case model.ActionAlterPlacementPolicy: - ver, err = onAlterPlacementPolicy(d, t, job) + ver, err = onAlterPlacementPolicy(t, job) case model.ActionAlterTablePartitionPlacement: ver, err = onAlterTablePartitionPlacement(t, job) case model.ActionAlterTablePlacement: @@ -846,10 +954,12 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, ver, err = onAlterCacheTable(t, job) case model.ActionAlterNoCacheTable: ver, err = onAlterNoCacheTable(t, job) + case model.ActionMultiSchemaChange: + ver, err = onMultiSchemaChange(w, d, t, job) default: // Invalid job, cancel it. job.State = model.JobStateCancelled - err = errInvalidDDLJob.GenWithStack("invalid ddl job type: %v", job.Type) + err = dbterror.ErrInvalidDDLJob.GenWithStack("invalid ddl job type: %v", job.Type) } // Save errors in job if any, so that others can know errors happened. @@ -978,6 +1088,21 @@ func updateSchemaVersion(t *meta.Meta, job *model.Job) (int64, error) { SchemaID: job.SchemaID, } switch job.Type { + case model.ActionCreateTables: + tableInfos := []*model.TableInfo{} + err = job.DecodeArgs(&tableInfos) + if err != nil { + return 0, errors.Trace(err) + } + diff.AffectedOpts = make([]*model.AffectedOption, len(tableInfos)) + for i := range tableInfos { + diff.AffectedOpts[i] = &model.AffectedOption{ + SchemaID: job.SchemaID, + OldSchemaID: job.SchemaID, + TableID: tableInfos[i].ID, + OldTableID: tableInfos[i].ID, + } + } case model.ActionTruncateTable: // Truncate table has two table ID, should be handled differently. err = job.DecodeArgs(&diff.TableID) diff --git a/ddl/ddl_worker_test.go b/ddl/ddl_worker_test.go index 5321d12671b40..1eb52164e221b 100644 --- a/ddl/ddl_worker_test.go +++ b/ddl/ddl_worker_test.go @@ -12,335 +12,41 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" + "strconv" "sync" "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) -var _ = Suite(&testDDLSuite{}) -var _ = SerialSuites(&testDDLSerialSuite{}) - -type testDDLSuite struct { - testutil.CommonHandleSuite -} -type testDDLSerialSuite struct{} - const testLease = 5 * time.Millisecond -func (s *testDDLSerialSuite) SetUpSuite(c *C) { - SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) - - // We hope that this test is serially executed. So put it here. - s.testRunWorker(c) -} - -func (s *testDDLSuite) TestCheckOwner(c *C) { - store := testCreateStore(c, "test_owner") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() +func TestCheckOwner(t *testing.T) { + _, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - d1, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d1.Stop() - c.Assert(err, IsNil) - }() time.Sleep(testLease) - testCheckOwner(c, d1, true) - - c.Assert(d1.GetLease(), Equals, testLease) -} - -func (s *testDDLSuite) TestNotifyDDLJob(c *C) { - store := testCreateStore(c, "test_notify_job") - defer store.Close() - - getFirstNotificationAfterStartDDL := func(d *ddl) { - select { - case <-d.workers[addIdxWorker].ddlJobCh: - default: - // The notification may be received by the worker. - } - select { - case <-d.workers[generalWorker].ddlJobCh: - default: - // The notification may be received by the worker. - } - } - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - getFirstNotificationAfterStartDDL(d) - // Ensure that the notification is not handled in workers `start` function. - d.cancel() - for _, worker := range d.workers { - worker.close() - } - - job := &model.Job{ - SchemaID: 1, - TableID: 2, - Type: model.ActionCreateTable, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{}, - } - // Test the notification mechanism of the owner and the server receiving the DDL request on the same TiDB. - // This DDL request is a general DDL job. - d.asyncNotifyWorker(job) - select { - case <-d.workers[generalWorker].ddlJobCh: - default: - c.Fatal("do not get the general job notification") - } - // Test the notification mechanism of the owner and the server receiving the DDL request on the same TiDB. - // This DDL request is a add index DDL job. - job.Type = model.ActionAddIndex - d.asyncNotifyWorker(job) - select { - case <-d.workers[addIdxWorker].ddlJobCh: - default: - c.Fatal("do not get the add index job notification") - } - - // Test the notification mechanism that the owner and the server receiving the DDL request are not on the same TiDB. - // And the etcd client is nil. - d1, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d1.Stop() - c.Assert(err, IsNil) - }() - getFirstNotificationAfterStartDDL(d1) - // Ensure that the notification is not handled by worker's "start". - d1.cancel() - for _, worker := range d1.workers { - worker.close() - } - d1.ownerManager.RetireOwner() - d1.asyncNotifyWorker(job) - job.Type = model.ActionCreateTable - d1.asyncNotifyWorker(job) - testCheckOwner(c, d1, false) - select { - case <-d1.workers[addIdxWorker].ddlJobCh: - c.Fatal("should not get the add index job notification") - case <-d1.workers[generalWorker].ddlJobCh: - c.Fatal("should not get the general job notification") - default: - } -} - -// testRunWorker tests no job is handled when the value of RunWorker is false. -func (s *testDDLSerialSuite) testRunWorker(c *C) { - store := testCreateStore(c, "test_run_worker") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - RunWorker = false - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - testCheckOwner(c, d, false) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - - // Make sure the DDL worker is nil. - worker := d.generalWorker() - c.Assert(worker, IsNil) - // Make sure the DDL job can be done and exit that goroutine. - RunWorker = true - d1, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - testCheckOwner(c, d1, true) - defer func() { - err := d1.Stop() - c.Assert(err, IsNil) - }() - worker = d1.generalWorker() - c.Assert(worker, NotNil) -} - -func (s *testDDLSuite) TestSchemaError(c *C) { - store := testCreateStore(c, "test_schema_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - - doDDLJobErr(c, 1, 0, model.ActionCreateSchema, []interface{}{1}, ctx, d) -} - -func (s *testDDLSuite) TestTableError(c *C) { - store := testCreateStore(c, "test_table_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - - // Schema ID is wrong, so dropping table is failed. - doDDLJobErr(c, -1, 1, model.ActionDropTable, nil, ctx, d) - // Table ID is wrong, so dropping table is failed. - dbInfo, err := testSchemaInfo(d, "test_ddl") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) - job := doDDLJobErr(c, dbInfo.ID, -1, model.ActionDropTable, nil, ctx, d) - - // Table ID or schema ID is wrong, so getting table is failed. - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, dbInfo, tblInfo) - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - job.SchemaID = -1 - job.TableID = -1 - t := meta.NewMeta(txn) - _, err1 := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) - c.Assert(err1, NotNil) - job.SchemaID = dbInfo.ID - _, err1 = getTableInfoAndCancelFaultJob(t, job, job.SchemaID) - c.Assert(err1, NotNil) - return nil - }) - c.Assert(err, IsNil) - - // Args is wrong, so creating table is failed. - doDDLJobErr(c, 1, 1, model.ActionCreateTable, []interface{}{1}, ctx, d) - // Schema ID is wrong, so creating table is failed. - doDDLJobErr(c, -1, tblInfo.ID, model.ActionCreateTable, []interface{}{tblInfo}, ctx, d) - // Table exists, so creating table is failed. - tblInfo.ID++ - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionCreateTable, []interface{}{tblInfo}, ctx, d) - -} - -func (s *testDDLSuite) TestViewError(c *C) { - store := testCreateStore(c, "test_view_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - dbInfo, err := testSchemaInfo(d, "test_ddl") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) - - // Table ID or schema ID is wrong, so getting table is failed. - tblInfo := testViewInfo(c, d, "t", 3) - testCreateView(c, ctx, d, dbInfo, tblInfo) - - // Args is wrong, so creating view is failed. - doDDLJobErr(c, 1, 1, model.ActionCreateView, []interface{}{1}, ctx, d) - // Schema ID is wrong and orReplace is false, so creating view is failed. - doDDLJobErr(c, -1, tblInfo.ID, model.ActionCreateView, []interface{}{tblInfo, false}, ctx, d) - // View exists and orReplace is false, so creating view is failed. - tblInfo.ID++ - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionCreateView, []interface{}{tblInfo, false}, ctx, d) - + require.Equal(t, dom.DDL().OwnerManager().IsOwner(), true) + require.Equal(t, dom.DDL().GetLease(), testLease) } -func (s *testDDLSuite) TestInvalidDDLJob(c *C) { - store := testCreateStore(c, "test_invalid_ddl_job_type_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) +func TestInvalidDDLJob(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() job := &model.Job{ SchemaID: 0, @@ -349,1203 +55,34 @@ func (s *testDDLSuite) TestInvalidDDLJob(c *C) { BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{}, } - err = d.doDDLJob(ctx, job) - c.Assert(err.Error(), Equals, "[ddl:8204]invalid ddl job type: none") -} - -func (s *testDDLSuite) TestForeignKeyError(c *C) { - store := testCreateStore(c, "test_foreign_key_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - - doDDLJobErr(c, -1, 1, model.ActionAddForeignKey, nil, ctx, d) - doDDLJobErr(c, -1, 1, model.ActionDropForeignKey, nil, ctx, d) - - dbInfo, err := testSchemaInfo(d, "test_ddl") - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d, dbInfo) - testCreateTable(c, ctx, d, dbInfo, tblInfo) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropForeignKey, []interface{}{model.NewCIStr("c1_foreign_key")}, ctx, d) -} - -func (s *testDDLSuite) TestIndexError(c *C) { - store := testCreateStore(c, "test_index_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - - // Schema ID is wrong. - doDDLJobErr(c, -1, 1, model.ActionAddIndex, nil, ctx, d) - doDDLJobErr(c, -1, 1, model.ActionDropIndex, nil, ctx, d) - - dbInfo, err := testSchemaInfo(d, "test_ddl") - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d, dbInfo) - testCreateTable(c, ctx, d, dbInfo, tblInfo) - - // for adding index - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, []interface{}{1}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, - []interface{}{false, model.NewCIStr("t"), 1, - []*ast.IndexPartSpecification{{Column: &ast.ColumnName{Name: model.NewCIStr("c")}, Length: 256}}}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, - []interface{}{false, model.NewCIStr("c1_index"), 1, - []*ast.IndexPartSpecification{{Column: &ast.ColumnName{Name: model.NewCIStr("c")}, Length: 256}}}, ctx, d) - testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, "c1_index", "c1") - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, - []interface{}{false, model.NewCIStr("c1_index"), 1, - []*ast.IndexPartSpecification{{Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, Length: 256}}}, ctx, d) - - // for dropping index - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropIndex, []interface{}{1}, ctx, d) - testDropIndex(c, ctx, d, dbInfo, tblInfo, "c1_index") - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropIndex, []interface{}{model.NewCIStr("c1_index")}, ctx, d) + ctx := testNewContext(store) + ctx.SetValue(sessionctx.QueryString, "skip") + err := dom.DDL().DoDDLJob(ctx, job) + require.Equal(t, err.Error(), "[ddl:8204]invalid ddl job type: none") } -func (s *testDDLSuite) TestColumnError(c *C) { - store := testCreateStore(c, "test_column_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - - dbInfo, err := testSchemaInfo(d, "test_ddl") - c.Assert(err, IsNil) - tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d, dbInfo) - testCreateTable(c, ctx, d, dbInfo, tblInfo) - col := &model.ColumnInfo{ - Name: model.NewCIStr("c4"), - Offset: len(tblInfo.Columns), - DefaultValue: 0, - } - col.ID = allocateColumnID(tblInfo) - col.FieldType = *types.NewFieldType(mysql.TypeLong) - pos := &ast.ColumnPosition{Tp: ast.ColumnPositionAfter, RelativeColumn: &ast.ColumnName{Name: model.NewCIStr("c5")}} - - cols := &[]*model.ColumnInfo{col} - positions := &[]*ast.ColumnPosition{pos} - - // for adding column - doDDLJobErr(c, -1, tblInfo.ID, model.ActionAddColumn, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, -1, model.ActionAddColumn, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddColumn, []interface{}{0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddColumn, []interface{}{col, pos, 0}, ctx, d) - - // for dropping column - doDDLJobErr(c, -1, tblInfo.ID, model.ActionDropColumn, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, -1, model.ActionDropColumn, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropColumn, []interface{}{0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropColumn, []interface{}{model.NewCIStr("c5")}, ctx, d) - - // for adding columns - doDDLJobErr(c, -1, tblInfo.ID, model.ActionAddColumns, []interface{}{cols, positions, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, -1, model.ActionAddColumns, []interface{}{cols, positions, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddColumns, []interface{}{0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionAddColumns, []interface{}{cols, positions, 0}, ctx, d) - - // for dropping columns - doDDLJobErr(c, -1, tblInfo.ID, model.ActionDropColumns, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, -1, model.ActionDropColumns, []interface{}{col, pos, 0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropColumns, []interface{}{0}, ctx, d) - doDDLJobErr(c, dbInfo.ID, tblInfo.ID, model.ActionDropColumns, []interface{}{[]model.CIStr{model.NewCIStr("c5"), model.NewCIStr("c6")}, make([]bool, 2)}, ctx, d) -} +func TestAddBatchJobError(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + ctx := testNewContext(store) -func (s *testDDLSerialSuite) TestAddBatchJobError(c *C) { - store := testCreateStore(c, "test_add_batch_job_error") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockAddBatchDDLJobsErr", `return(true)`), IsNil) + require.Nil(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockAddBatchDDLJobsErr", `return(true)`)) // Test the job runner should not hang forever. job := &model.Job{SchemaID: 1, TableID: 1} - err = d.doDDLJob(ctx, job) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "mockAddBatchDDLJobsErr") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockAddBatchDDLJobsErr"), IsNil) -} - -func testCheckOwner(c *C, d *ddl, expectedVal bool) { - c.Assert(d.isOwner(), Equals, expectedVal) -} - -func testCheckJobDone(c *C, d *ddl, job *model.Job, isAdd bool) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - historyJob, err := t.GetHistoryDDLJob(job.ID) - c.Assert(err, IsNil) - checkHistoryJob(c, historyJob) - if isAdd { - c.Assert(historyJob.SchemaState, Equals, model.StatePublic) - } else { - c.Assert(historyJob.SchemaState, Equals, model.StateNone) - } - - return nil - }) - c.Assert(err, IsNil) -} - -func testCheckJobDoneT(t *testing.T, d *ddl, job *model.Job, isAdd bool) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - tt := meta.NewMeta(txn) - historyJob, err := tt.GetHistoryDDLJob(job.ID) - require.NoError(t, err) - require.Equal(t, model.JobStateSynced, historyJob.State) - if isAdd { - require.Equal(t, model.StatePublic, historyJob.SchemaState) - } else { - require.Equal(t, model.StateNone, historyJob.SchemaState) - } - - return nil - }) - require.NoError(t, err) -} - -func testCheckJobCancelledT(t *testing.T, d *ddl, job *model.Job, state *model.SchemaState) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - tt := meta.NewMeta(txn) - historyJob, err := tt.GetHistoryDDLJob(job.ID) - require.NoError(t, err) - require.True(t, historyJob.IsCancelled() || historyJob.IsRollbackDone(), "history job %s", historyJob) - if state != nil { - require.Equal(t, *state, historyJob.SchemaState) - } - return nil - }) - require.NoError(t, err) -} - -func testCheckJobCancelled(c *C, d *ddl, job *model.Job, state *model.SchemaState) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - historyJob, err := t.GetHistoryDDLJob(job.ID) - c.Assert(err, IsNil) - c.Assert(historyJob.IsCancelled() || historyJob.IsRollbackDone(), IsTrue, Commentf("history job %s", historyJob)) - if state != nil { - c.Assert(historyJob.SchemaState, Equals, *state) - } - return nil - }) - c.Assert(err, IsNil) -} - -func doDDLJobErrWithSchemaState(ctx sessionctx.Context, d *ddl, c *C, schemaID, tableID int64, tp model.ActionType, - args []interface{}, state *model.SchemaState) *model.Job { - job := &model.Job{ - SchemaID: schemaID, - TableID: tableID, - Type: tp, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - err := d.doDDLJob(ctx, job) - // TODO: Add the detail error check. - c.Assert(err, NotNil, Commentf("err:%v", err)) - testCheckJobCancelled(c, d, job, state) - - return job -} - -func doDDLJobErrWithSchemaStateT(ctx sessionctx.Context, d *ddl, t *testing.T, schemaID, tableID int64, tp model.ActionType, - args []interface{}, state *model.SchemaState) *model.Job { - job := &model.Job{ - SchemaID: schemaID, - TableID: tableID, - Type: tp, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - err := d.doDDLJob(ctx, job) - // TODO: Add the detail error check. - require.Error(t, err, "err:%v", err) - testCheckJobCancelledT(t, d, job, state) - - return job -} - -func doDDLJobSuccess(ctx sessionctx.Context, d *ddl, c *C, schemaID, tableID int64, tp model.ActionType, - args []interface{}) { - job := &model.Job{ - SchemaID: schemaID, - TableID: tableID, - Type: tp, - Args: args, - BinlogInfo: &model.HistoryInfo{}, - } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) -} - -func doDDLJobErr(c *C, schemaID, tableID int64, tp model.ActionType, args []interface{}, - ctx sessionctx.Context, d *ddl) *model.Job { - return doDDLJobErrWithSchemaState(ctx, d, c, schemaID, tableID, tp, args, nil) -} - -func doDDLJobErrT(t *testing.T, schemaID, tableID int64, tp model.ActionType, args []interface{}, - ctx sessionctx.Context, d *ddl) *model.Job { - return doDDLJobErrWithSchemaStateT(ctx, d, t, schemaID, tableID, tp, args, nil) -} - -func checkCancelState(txn kv.Transaction, job *model.Job, test *testCancelJob) error { - var checkErr error - addIndexFirstReorg := (test.act == model.ActionAddIndex || test.act == model.ActionAddPrimaryKey) && - job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 - // If the action is adding index and the state is writing reorganization, it wants to test the case of cancelling the job when backfilling indexes. - // When the job satisfies this case of addIndexFirstReorg, the worker hasn't started to backfill indexes. - if test.cancelState == job.SchemaState && !addIndexFirstReorg && !job.IsRollingback() { - errs, err := admin.CancelJobs(txn, test.jobIDs) - if err != nil { - checkErr = errors.Trace(err) - return checkErr - } - // It only tests cancel one DDL job. - if !terror.ErrorEqual(errs[0], test.cancelRetErrs[0]) { - checkErr = errors.Trace(errs[0]) - return checkErr - } - } - return checkErr -} - -type testCancelJob struct { - jobIDs []int64 - cancelRetErrs []error // cancelRetErrs is the first return value of CancelJobs. - act model.ActionType // act is the job action. - cancelState model.SchemaState + ctx.SetValue(sessionctx.QueryString, "skip") + err := dom.DDL().DoDDLJob(ctx, job) + require.Error(t, err) + require.Equal(t, err.Error(), "mockAddBatchDDLJobsErr") + require.Nil(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockAddBatchDDLJobsErr")) } -func buildCancelJobTests(firstID int64) []testCancelJob { - noErrs := []error{nil} - tests := []testCancelJob{ - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 1}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 2}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 3}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddIndex, jobIDs: []int64{firstID + 4}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 4)}, cancelState: model.StatePublic}, - - // Test cancel drop index job , see TestCancelDropIndex. - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 5}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 6}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 7}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddColumn, jobIDs: []int64{firstID + 8}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 8)}, cancelState: model.StatePublic}, - - // Test create table, watch out, table id will alloc a globalID. - {act: model.ActionCreateTable, jobIDs: []int64{firstID + 10}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - // Test create database, watch out, database id will alloc a globalID. - {act: model.ActionCreateSchema, jobIDs: []int64{firstID + 12}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 13}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 13)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 14}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 14)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropColumn, jobIDs: []int64{firstID + 15}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 15)}, cancelState: model.StateWriteReorganization}, - {act: model.ActionRebaseAutoID, jobIDs: []int64{firstID + 16}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionShardRowID, jobIDs: []int64{firstID + 17}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 18}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 19}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, +func TestParallelDDL(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() - {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 20}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAddForeignKey, jobIDs: []int64{firstID + 21}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 21)}, cancelState: model.StatePublic}, - {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 22}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionDropForeignKey, jobIDs: []int64{firstID + 23}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 23)}, cancelState: model.StatePublic}, - - {act: model.ActionRenameTable, jobIDs: []int64{firstID + 24}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionRenameTable, jobIDs: []int64{firstID + 25}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 25)}, cancelState: model.StatePublic}, - - {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 26}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyTableCharsetAndCollate, jobIDs: []int64{firstID + 27}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 27)}, cancelState: model.StatePublic}, - {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 28}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionTruncateTablePartition, jobIDs: []int64{firstID + 29}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 29)}, cancelState: model.StatePublic}, - {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 31}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifySchemaCharsetAndCollate, jobIDs: []int64{firstID + 32}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 32)}, cancelState: model.StatePublic}, - - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 33}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 34}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 35}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddPrimaryKey, jobIDs: []int64{firstID + 36}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 36)}, cancelState: model.StatePublic}, - {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 37}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionDropPrimaryKey, jobIDs: []int64{firstID + 38}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 38)}, cancelState: model.StateDeleteOnly}, - - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 39}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 40}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 41}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionAddColumns, jobIDs: []int64{firstID + 42}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 42)}, cancelState: model.StatePublic}, - - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 43}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 43)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 44}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 44)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropColumns, jobIDs: []int64{firstID + 45}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 45)}, cancelState: model.StateWriteReorganization}, - - {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 47}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAlterIndexVisibility, jobIDs: []int64{firstID + 48}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 48)}, cancelState: model.StatePublic}, - - {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 54}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionExchangeTablePartition, jobIDs: []int64{firstID + 55}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 55)}, cancelState: model.StatePublic}, - - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 60}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 61}, cancelRetErrs: noErrs, cancelState: model.StateReplicaOnly}, - {act: model.ActionAddTablePartition, jobIDs: []int64{firstID + 62}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, - - // modify column has two different types, normal-type and reorg-type. The latter has 5 states and it can be cancelled except the public state. - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 65}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 66}, cancelRetErrs: noErrs, cancelState: model.StateDeleteOnly}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 67}, cancelRetErrs: noErrs, cancelState: model.StateWriteOnly}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 68}, cancelRetErrs: noErrs, cancelState: model.StateWriteReorganization}, - {act: model.ActionModifyColumn, jobIDs: []int64{firstID + 69}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob}, cancelState: model.StatePublic}, - - // for drop indexes - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 72}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 72)}, cancelState: model.StateWriteOnly}, - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 73}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 73)}, cancelState: model.StateDeleteOnly}, - {act: model.ActionDropIndexes, jobIDs: []int64{firstID + 74}, cancelRetErrs: []error{admin.ErrCannotCancelDDLJob.GenWithStackByArgs(firstID + 74)}, cancelState: model.StateWriteReorganization}, - - // for alter db placement - {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 75}, cancelRetErrs: noErrs, cancelState: model.StateNone}, - {act: model.ActionModifySchemaDefaultPlacement, jobIDs: []int64{firstID + 76}, cancelRetErrs: []error{admin.ErrCancelFinishedDDLJob.GenWithStackByArgs(firstID + 76)}, cancelState: model.StatePublic}, - } - - return tests -} - -func (s *testDDLSerialSuite) checkDropIdx(c *C, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { - checkIdxExist(c, d, schemaID, tableID, idxName, !success) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") -func (s *testDDLSerialSuite) checkAddIdx(c *C, d *ddl, schemaID int64, tableID int64, idxName string, success bool) { - checkIdxExist(c, d, schemaID, tableID, idxName, success) -} - -func checkIdxExist(c *C, d *ddl, schemaID int64, tableID int64, idxName string, expectedExist bool) { - changedTable := testGetTable(c, d, schemaID, tableID) - var found bool - for _, idxInfo := range changedTable.Meta().Indices { - if idxInfo.Name.O == idxName { - found = true - break - } - } - c.Assert(found, Equals, expectedExist) -} - -func (s *testDDLSerialSuite) checkAddColumns(c *C, d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { - changedTable := testGetTable(c, d, schemaID, tableID) - found := !checkColumnsNotFound(changedTable, colNames) - c.Assert(found, Equals, success) -} - -func (s *testDDLSerialSuite) checkCancelDropColumns(c *C, d *ddl, schemaID int64, tableID int64, colNames []string, success bool) { - changedTable := testGetTable(c, d, schemaID, tableID) - notFound := checkColumnsNotFound(changedTable, colNames) - c.Assert(notFound, Equals, success) -} - -func checkColumnsNotFound(t table.Table, colNames []string) bool { - notFound := true - for _, colName := range colNames { - for _, colInfo := range t.Meta().Columns { - if colInfo.Name.O == colName { - notFound = false - } - } - } - return notFound -} - -func checkIdxVisibility(changedTable table.Table, idxName string, expected bool) bool { - for _, idxInfo := range changedTable.Meta().Indices { - if idxInfo.Name.O == idxName && idxInfo.Invisible == expected { - return true - } - } - return false -} - -func (s *testDDLSerialSuite) TestCancelJob(c *C) { - store := testCreateStore(c, "test_cancel_job") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - dbInfo, err := testSchemaInfo(d, "test_cancel_job") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) - // create a partition table. - partitionTblInfo := testTableInfoWithPartition(c, d, "t_partition", 5) - // Skip using sessPool. Make sure adding primary key can be successful. - partitionTblInfo.Columns[0].Flag |= mysql.NotNullFlag - // create table t (c1 int, c2 int, c3 int, c4 int, c5 int); - tblInfo, err := testTableInfo(d, "t", 5) - c.Assert(err, IsNil) - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - err = ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "1") - c.Assert(err, IsNil) - defer func() { - err := ctx.GetSessionVars().SetSystemVar("tidb_enable_exchange_partition", "0") - c.Assert(err, IsNil) - }() - testCreateTable(c, ctx, d, dbInfo, partitionTblInfo) - tableAutoID := int64(100) - shardRowIDBits := uint64(5) - tblInfo.AutoIncID = tableAutoID - tblInfo.ShardRowIDBits = shardRowIDBits - job := testCreateTable(c, ctx, d, dbInfo, tblInfo) - // insert t values (1, 2, 3, 4, 5); - originTable := testGetTable(c, d, dbInfo.ID, tblInfo.ID) - row := types.MakeDatums(1, 2, 3, 4, 5) - _, err = originTable.AddRecord(ctx, row) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - tc := &TestDDLCallback{} - // set up hook - firstJobID := job.ID - tests := buildCancelJobTests(firstJobID) - var checkErr error - var mu sync.Mutex - var test *testCancelJob - updateTest := func(t *testCancelJob) { - mu.Lock() - test = t - mu.Unlock() - } - hookCancelFunc := func(job *model.Job) { - if job.State == model.JobStateSynced || job.State == model.JobStateCancelled || job.State == model.JobStateCancelling { - return - } - // This hook only valid for the related test job. - // This is use to avoid parallel test fail. - mu.Lock() - if len(test.jobIDs) > 0 && test.jobIDs[0] != job.ID { - mu.Unlock() - return - } - mu.Unlock() - if checkErr != nil { - return - } - - hookCtx := mock.NewContext() - hookCtx.Store = store - err1 := hookCtx.NewTxn(context.Background()) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - txn, err1 = hookCtx.Txn(true) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - mu.Lock() - checkErr = checkCancelState(txn, job, test) - mu.Unlock() - if checkErr != nil { - return - } - err1 = txn.Commit(context.Background()) - if err1 != nil { - checkErr = errors.Trace(err1) - return - } - } - tc.onJobUpdated = hookCancelFunc - tc.onJobRunBefore = hookCancelFunc - d.SetHook(tc) - - // for adding index - updateTest(&tests[0]) - idxOrigName := "idx" - validArgs := []interface{}{false, model.NewCIStr(idxOrigName), - []*ast.IndexPartSpecification{{ - Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, - Length: -1, - }}, nil} - - // When the job satisfies this test case, the option will be rollback, so the job's schema state is none. - cancelState := model.StateNone - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[1]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[2]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddIndex, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[3]) - testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, "idx", "c2") - c.Check(checkErr, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - c.Assert(txn.Commit(context.Background()), IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for add column - updateTest(&tests[4]) - addingColName := "colA" - newColumnDef := &ast.ColumnDef{ - Name: &ast.ColumnName{Name: model.NewCIStr(addingColName)}, - Tp: &types.FieldType{Tp: mysql.TypeLonglong}, - Options: []*ast.ColumnOption{}, - } - chs, coll := charset.GetDefaultCharsetAndCollate() - col, _, err := buildColumnAndConstraint(ctx, 2, newColumnDef, nil, chs, coll) - c.Assert(err, IsNil) - - addColumnArgs := []interface{}{col, &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, 0} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[5]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[6]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumn, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, []string{addingColName}, false) - - updateTest(&tests[7]) - testAddColumn(c, ctx, d, dbInfo, tblInfo, addColumnArgs) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, []string{addingColName}, true) - - // for create table - tblInfo1, err := testTableInfo(d, "t1", 2) - c.Assert(err, IsNil) - updateTest(&tests[8]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo1.ID, model.ActionCreateTable, []interface{}{tblInfo1}, &cancelState) - c.Check(checkErr, IsNil) - testCheckTableState(c, d, dbInfo, tblInfo1, model.StateNone) - - // for create database - dbInfo1, err := testSchemaInfo(d, "test_cancel_job1") - c.Assert(err, IsNil) - updateTest(&tests[9]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo1.ID, 0, model.ActionCreateSchema, []interface{}{dbInfo1}, &cancelState) - c.Check(checkErr, IsNil) - testCheckSchemaState(c, d, dbInfo1, model.StateNone) - - // for drop column. - updateTest(&tests[10]) - dropColName := "c3" - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(c, ctx, d, dbInfo, tblInfo, dropColName, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - updateTest(&tests[11]) - dropColName = "c4" - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(c, ctx, d, dbInfo, tblInfo, dropColName, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - updateTest(&tests[12]) - dropColName = "c5" - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, false) - testDropColumn(c, ctx, d, dbInfo, tblInfo, dropColName, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, []string{dropColName}, true) - - // cancel rebase auto id - updateTest(&tests[13]) - rebaseIDArgs := []interface{}{int64(200)} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionRebaseAutoID, rebaseIDArgs, &cancelState) - c.Check(checkErr, IsNil) - changedTable := testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().AutoIncID, Equals, tableAutoID) - - // cancel shard bits - updateTest(&tests[14]) - shardRowIDArgs := []interface{}{uint64(7)} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionShardRowID, shardRowIDArgs, &cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().ShardRowIDBits, Equals, shardRowIDBits) - - // modify none-state column - col.DefaultValue = "1" - updateTest(&tests[15]) - modifyColumnArgs := []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - changedCol := model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) - c.Assert(changedCol.DefaultValue, IsNil) - - // modify delete-only-state column, - col.FieldType.Tp = mysql.TypeTiny - col.FieldType.Flen-- - updateTest(&tests[16]) - modifyColumnArgs = []interface{}{col, col.Name, &ast.ColumnPosition{}, byte(0), uint64(0)} - cancelState = model.StateNone - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - changedCol = model.FindColumnInfo(changedTable.Meta().Columns, col.Name.L) - c.Assert(changedCol.FieldType.Tp, Equals, mysql.TypeLonglong) - c.Assert(changedCol.FieldType.Flen, Equals, col.FieldType.Flen+1) - col.FieldType.Flen++ - - // Test add foreign key failed cause by canceled. - updateTest(&tests[17]) - addForeignKeyArgs := []interface{}{model.FKInfo{Name: model.NewCIStr("fk1")}} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(len(changedTable.Meta().ForeignKeys), Equals, 0) - - // Test add foreign key successful. - updateTest(&tests[18]) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(len(changedTable.Meta().ForeignKeys), Equals, 1) - c.Assert(changedTable.Meta().ForeignKeys[0].Name, Equals, addForeignKeyArgs[0].(model.FKInfo).Name) - - // Test drop foreign key failed cause by canceled. - updateTest(&tests[19]) - dropForeignKeyArgs := []interface{}{addForeignKeyArgs[0].(model.FKInfo).Name} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(len(changedTable.Meta().ForeignKeys), Equals, 1) - c.Assert(changedTable.Meta().ForeignKeys[0].Name, Equals, dropForeignKeyArgs[0].(model.CIStr)) - - // Test drop foreign key successful. - updateTest(&tests[20]) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(len(changedTable.Meta().ForeignKeys), Equals, 0) - - // test rename table failed caused by canceled. - test = &tests[21] - renameTableArgs := []interface{}{dbInfo.ID, model.NewCIStr("t2"), dbInfo.Name} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, renameTableArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().Name.L, Equals, "t") - - // test rename table successful. - test = &tests[22] - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, renameTableArgs) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().Name.L, Equals, "t2") - - // test modify table charset failed caused by canceled. - test = &tests[23] - modifyTableCharsetArgs := []interface{}{"utf8mb4", "utf8mb4_bin"} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().Charset, Equals, "utf8") - c.Assert(changedTable.Meta().Collate, Equals, "utf8_bin") - - // test modify table charset successfully. - test = &tests[24] - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyTableCharsetArgs) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(changedTable.Meta().Charset, Equals, "utf8mb4") - c.Assert(changedTable.Meta().Collate, Equals, "utf8mb4_bin") - - // test truncate table partition failed caused by canceled. - test = &tests[25] - truncateTblPartitionArgs := []interface{}{[]int64{partitionTblInfo.Partition.Definitions[0].ID}} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, partitionTblInfo.ID) - c.Assert(changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID, IsTrue) - - // test truncate table partition charset successfully. - test = &tests[26] - doDDLJobSuccess(ctx, d, c, dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, partitionTblInfo.ID) - c.Assert(changedTable.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID, IsFalse) - - // test modify schema charset failed caused by canceled. - test = &tests[27] - charsetAndCollate := []interface{}{"utf8mb4", "utf8mb4_bin"} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate, &test.cancelState) - c.Check(checkErr, IsNil) - dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) - c.Assert(err, IsNil) - c.Assert(dbInfo.Charset, Equals, "") - c.Assert(dbInfo.Collate, Equals, "") - - // test modify table charset successfully. - test = &tests[28] - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, charsetAndCollate) - c.Check(checkErr, IsNil) - dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID) - c.Assert(err, IsNil) - c.Assert(dbInfo.Charset, Equals, "utf8mb4") - c.Assert(dbInfo.Collate, Equals, "utf8mb4_bin") - - // for adding primary key - tblInfo = changedTable.Meta() - updateTest(&tests[29]) - idxOrigName = "primary" - validArgs = []interface{}{false, model.NewCIStr(idxOrigName), - []*ast.IndexPartSpecification{{ - Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, - Length: -1, - }}, nil} - cancelState = model.StateNone - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[30]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[31]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddPrimaryKey, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[32]) - testCreatePrimaryKey(c, ctx, d, dbInfo, tblInfo, "c1") - c.Check(checkErr, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - c.Assert(txn.Commit(context.Background()), IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for dropping primary key - updateTest(&tests[33]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionDropPrimaryKey, validArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkDropIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false) - updateTest(&tests[34]) - testDropIndex(c, ctx, d, dbInfo, tblInfo, idxOrigName) - c.Check(checkErr, IsNil) - s.checkDropIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true) - - // for add columns - updateTest(&tests[35]) - addingColNames := []string{"colA", "colB", "colC", "colD", "colE", "colF"} - cols := make([]*table.Column, len(addingColNames)) - for i, addingColName := range addingColNames { - newColumnDef := &ast.ColumnDef{ - Name: &ast.ColumnName{Name: model.NewCIStr(addingColName)}, - Tp: &types.FieldType{Tp: mysql.TypeLonglong}, - Options: []*ast.ColumnOption{}, - } - col, _, err := buildColumnAndConstraint(ctx, 0, newColumnDef, nil, mysql.DefaultCharset, "") - c.Assert(err, IsNil) - cols[i] = col - } - offsets := make([]int, len(cols)) - positions := make([]*ast.ColumnPosition, len(cols)) - for i := range positions { - positions[i] = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} - } - ifNotExists := make([]bool, len(cols)) - - addColumnArgs = []interface{}{cols, positions, offsets, ifNotExists} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[36]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[37]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, model.ActionAddColumns, addColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, addingColNames, false) - - updateTest(&tests[38]) - testAddColumns(c, ctx, d, dbInfo, tblInfo, addColumnArgs) - c.Check(checkErr, IsNil) - s.checkAddColumns(c, d, dbInfo.ID, tblInfo.ID, addingColNames, true) - - // for drop columns - updateTest(&tests[39]) - dropColNames := []string{"colA", "colB"} - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(c, ctx, d, dbInfo, tblInfo, dropColNames, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - updateTest(&tests[40]) - dropColNames = []string{"colC", "colD"} - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(c, ctx, d, dbInfo, tblInfo, dropColNames, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - updateTest(&tests[41]) - dropColNames = []string{"colE", "colF"} - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, false) - testDropColumns(c, ctx, d, dbInfo, tblInfo, dropColNames, false) - c.Check(checkErr, IsNil) - s.checkCancelDropColumns(c, d, dbInfo.ID, tblInfo.ID, dropColNames, true) - - // test alter index visibility failed caused by canceled. - indexName := "idx_c3" - testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, indexName, "c3") - c.Check(checkErr, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - c.Assert(txn.Commit(context.Background()), IsNil) - s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, indexName, true) - - updateTest(&tests[42]) - alterIndexVisibility := []interface{}{model.NewCIStr(indexName), true} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility, &test.cancelState) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(checkIdxVisibility(changedTable, indexName, false), IsTrue) - - // cancel alter index visibility successfully - updateTest(&tests[43]) - alterIndexVisibility = []interface{}{model.NewCIStr(indexName), true} - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility) - c.Check(checkErr, IsNil) - changedTable = testGetTable(c, d, dbInfo.ID, tblInfo.ID) - c.Assert(checkIdxVisibility(changedTable, indexName, true), IsTrue) - - // test exchange partition failed caused by canceled - pt := testTableInfoWithPartition(c, d, "pt", 5) - nt, err := testTableInfo(d, "nt", 5) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, dbInfo, pt) - testCreateTable(c, ctx, d, dbInfo, nt) - - updateTest(&tests[44]) - defID := pt.Partition.Definitions[0].ID - exchangeTablePartition := []interface{}{defID, dbInfo.ID, pt.ID, "p0", true} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, nt.ID, test.act, exchangeTablePartition, &test.cancelState) - c.Check(checkErr, IsNil) - changedNtTable := testGetTable(c, d, dbInfo.ID, nt.ID) - changedPtTable := testGetTable(c, d, dbInfo.ID, pt.ID) - c.Assert(changedNtTable.Meta().ID == nt.ID, IsTrue) - c.Assert(changedPtTable.Meta().Partition.Definitions[0].ID == pt.Partition.Definitions[0].ID, IsTrue) - - // cancel exchange partition successfully - updateTest(&tests[45]) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, nt.ID, test.act, exchangeTablePartition) - c.Check(checkErr, IsNil) - changedNtTable = testGetTable(c, d, dbInfo.ID, pt.Partition.Definitions[0].ID) - changedPtTable = testGetTable(c, d, dbInfo.ID, pt.ID) - c.Assert(changedNtTable.Meta().ID == nt.ID, IsFalse) - c.Assert(changedPtTable.Meta().Partition.Definitions[0].ID == nt.ID, IsTrue) - - // Cancel add table partition. - baseTableInfo := testTableInfoWithPartitionLessThan(c, d, "empty_table", 5, "1000") - testCreateTable(c, ctx, d, dbInfo, baseTableInfo) - - cancelState = model.StateNone - updateTest(&tests[46]) - addedPartInfo := testAddedNewTablePartitionInfo(c, d, baseTableInfo, "p1", "maxvalue") - addPartitionArgs := []interface{}{addedPartInfo} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable := testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(len(baseTable.Meta().Partition.Definitions), Equals, 1) - - updateTest(&tests[47]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(len(baseTable.Meta().Partition.Definitions), Equals, 1) - - updateTest(&tests[48]) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, addPartitionArgs) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(len(baseTable.Meta().Partition.Definitions), Equals, 2) - c.Assert(baseTable.Meta().Partition.Definitions[1].ID, Equals, addedPartInfo.Definitions[0].ID) - c.Assert(baseTable.Meta().Partition.Definitions[1].LessThan[0], Equals, addedPartInfo.Definitions[0].LessThan[0]) - - // Cancel modify column which should reorg the data. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/skipMockContextDoExec", `return(true)`), IsNil) - baseTableInfo = testTableInfoWith2IndexOnFirstColumn(c, d, "modify-table", 2) - // This will cost 2 global id, one for table id, the other for the job id. - testCreateTable(c, ctx, d, dbInfo, baseTableInfo) - - cancelState = model.StateNone - newCol := baseTableInfo.Columns[0].Clone() - // change type from long to tinyint. - newCol.FieldType = *types.NewFieldType(mysql.TypeTiny) - // change from null to not null - newCol.FieldType.Flag |= mysql.NotNullFlag - newCol.FieldType.Flen = 2 - - originColName := baseTableInfo.Columns[0].Name - pos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} - - updateTest(&tests[49]) - modifyColumnArgs = []interface{}{&newCol, originColName, pos, mysql.TypeNull, 0} - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(baseTable.Meta().Columns[0].FieldType.Tp, Equals, mysql.TypeLong) - c.Assert(mysql.HasNotNullFlag(baseTable.Meta().Columns[0].FieldType.Flag), Equals, false) - - updateTest(&tests[50]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(baseTable.Meta().Columns[0].FieldType.Tp, Equals, mysql.TypeLong) - c.Assert(baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, Equals, uint(0)) - - updateTest(&tests[51]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(baseTable.Meta().Columns[0].FieldType.Tp, Equals, mysql.TypeLong) - c.Assert(baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, Equals, uint(0)) - - updateTest(&tests[52]) - doDDLJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs, &cancelState) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(baseTable.Meta().Columns[0].FieldType.Tp, Equals, mysql.TypeLong) - c.Assert(baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, Equals, uint(0)) - - updateTest(&tests[53]) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, baseTableInfo.ID, test.act, modifyColumnArgs) - c.Check(checkErr, IsNil) - baseTable = testGetTable(c, d, dbInfo.ID, baseTableInfo.ID) - c.Assert(baseTable.Meta().Columns[0].FieldType.Tp, Equals, mysql.TypeTiny) - c.Assert(baseTable.Meta().Columns[0].FieldType.Flag&mysql.NotNullFlag, Equals, uint(1)) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/skipMockContextDoExec"), IsNil) - - // for drop indexes - updateTest(&tests[54]) - ifExists := make([]bool, 2) - idxNames := []model.CIStr{model.NewCIStr("i1"), model.NewCIStr("i2")} - dropIndexesArgs := []interface{}{idxNames, ifExists} - tableInfo := createTestTableForDropIndexes(c, ctx, d, dbInfo, "test-drop-indexes", 6) - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(c, d, dbInfo.ID, tableInfo.ID, idxNames, true) - - updateTest(&tests[55]) - idxNames = []model.CIStr{model.NewCIStr("i3"), model.NewCIStr("i4")} - dropIndexesArgs = []interface{}{idxNames, ifExists} - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(c, d, dbInfo.ID, tableInfo.ID, idxNames, true) - - updateTest(&tests[56]) - idxNames = []model.CIStr{model.NewCIStr("i5"), model.NewCIStr("i6")} - dropIndexesArgs = []interface{}{idxNames, ifExists} - doDDLJobSuccess(ctx, d, c, dbInfo.ID, tableInfo.ID, test.act, dropIndexesArgs) - s.checkDropIndexes(c, d, dbInfo.ID, tableInfo.ID, idxNames, true) -} - -func (s *testDDLSuite) TestIgnorableSpec(c *C) { - specs := []ast.AlterTableType{ - ast.AlterTableOption, - ast.AlterTableAddColumns, - ast.AlterTableAddConstraint, - ast.AlterTableDropColumn, - ast.AlterTableDropPrimaryKey, - ast.AlterTableDropIndex, - ast.AlterTableDropForeignKey, - ast.AlterTableModifyColumn, - ast.AlterTableChangeColumn, - ast.AlterTableRenameTable, - ast.AlterTableAlterColumn, - } - for _, spec := range specs { - c.Assert(isIgnorableSpec(spec), IsFalse) - } - - ignorableSpecs := []ast.AlterTableType{ - ast.AlterTableLock, - ast.AlterTableAlgorithm, - } - for _, spec := range ignorableSpecs { - c.Assert(isIgnorableSpec(spec), IsTrue) - } -} - -func (s *testDDLSuite) TestBuildJobDependence(c *C) { - store := testCreateStore(c, "test_set_job_relation") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - // Add some non-add-index jobs. - job1 := &model.Job{ID: 1, TableID: 1, Type: model.ActionAddColumn} - job2 := &model.Job{ID: 2, TableID: 1, Type: model.ActionCreateTable} - job3 := &model.Job{ID: 3, TableID: 2, Type: model.ActionDropColumn} - job6 := &model.Job{ID: 6, TableID: 1, Type: model.ActionDropTable} - job7 := &model.Job{ID: 7, TableID: 2, Type: model.ActionModifyColumn} - job9 := &model.Job{ID: 9, SchemaID: 111, Type: model.ActionDropSchema} - job11 := &model.Job{ID: 11, TableID: 2, Type: model.ActionRenameTable, Args: []interface{}{int64(111), "old db name"}} - err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := t.EnQueueDDLJob(job1) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job2) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job3) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job6) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job7) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job9) - c.Assert(err, IsNil) - err = t.EnQueueDDLJob(job11) - c.Assert(err, IsNil) - return nil - }) - c.Assert(err, IsNil) - job4 := &model.Job{ID: 4, TableID: 1, Type: model.ActionAddIndex} - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := buildJobDependence(t, job4) - c.Assert(err, IsNil) - c.Assert(job4.DependencyID, Equals, int64(2)) - return nil - }) - c.Assert(err, IsNil) - job5 := &model.Job{ID: 5, TableID: 2, Type: model.ActionAddIndex} - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := buildJobDependence(t, job5) - c.Assert(err, IsNil) - c.Assert(job5.DependencyID, Equals, int64(3)) - return nil - }) - c.Assert(err, IsNil) - job8 := &model.Job{ID: 8, TableID: 3, Type: model.ActionAddIndex} - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := buildJobDependence(t, job8) - c.Assert(err, IsNil) - c.Assert(job8.DependencyID, Equals, int64(0)) - return nil - }) - c.Assert(err, IsNil) - job10 := &model.Job{ID: 10, SchemaID: 111, TableID: 3, Type: model.ActionAddIndex} - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := buildJobDependence(t, job10) - c.Assert(err, IsNil) - c.Assert(job10.DependencyID, Equals, int64(9)) - return nil - }) - c.Assert(err, IsNil) - job12 := &model.Job{ID: 12, SchemaID: 112, TableID: 2, Type: model.ActionAddIndex} - err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := buildJobDependence(t, job12) - c.Assert(err, IsNil) - c.Assert(job12.DependencyID, Equals, int64(11)) - return nil - }) - c.Assert(err, IsNil) -} - -func addDDLJob(c *C, d *ddl, job *model.Job) { - task := &limitJobTask{job, make(chan error)} - d.limitJobCh <- task - err := <-task.err - c.Assert(err, IsNil) -} - -func (s *testDDLSuite) TestParallelDDL(c *C) { - store := testCreateStore(c, "test_parallel_ddl") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) /* build structure: DBs -> { @@ -1557,63 +94,24 @@ func (s *testDDLSuite) TestParallelDDL(c *C) { db1.t2 (c1 int primary key, c2 int, c3 int) db2.t3 (c1 int, c2 int, c3 int, c4 int) } - Data -> { - t1: (10, 10), (20, 20) - t2: (1, 1, 1), (2, 2, 2), (3, 3, 3) - t3: (11, 22, 33, 44) - } */ - // create database test_parallel_ddl_1; - dbInfo1, err := testSchemaInfo(d, "test_parallel_ddl_1") - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d, dbInfo1) - // create table t1 (c1 int, c2 int); - tblInfo1, err := testTableInfo(d, "t1", 2) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, dbInfo1, tblInfo1) - // insert t1 values (10, 10), (20, 20) - tbl1 := testGetTable(c, d, dbInfo1.ID, tblInfo1.ID) - _, err = tbl1.AddRecord(ctx, types.MakeDatums(1, 1)) - c.Assert(err, IsNil) - _, err = tbl1.AddRecord(ctx, types.MakeDatums(2, 2)) - c.Assert(err, IsNil) - // create table t2 (c1 int primary key, c2 int, c3 int); - tblInfo2, err := testTableInfo(d, "t2", 3) - c.Assert(err, IsNil) - tblInfo2.Columns[0].Flag = mysql.PriKeyFlag | mysql.NotNullFlag - tblInfo2.PKIsHandle = true - testCreateTable(c, ctx, d, dbInfo1, tblInfo2) - // insert t2 values (1, 1), (2, 2), (3, 3) - tbl2 := testGetTable(c, d, dbInfo1.ID, tblInfo2.ID) - _, err = tbl2.AddRecord(ctx, types.MakeDatums(1, 1, 1)) - c.Assert(err, IsNil) - _, err = tbl2.AddRecord(ctx, types.MakeDatums(2, 2, 2)) - c.Assert(err, IsNil) - _, err = tbl2.AddRecord(ctx, types.MakeDatums(3, 3, 3)) - c.Assert(err, IsNil) - // create database test_parallel_ddl_2; - dbInfo2, err := testSchemaInfo(d, "test_parallel_ddl_2") - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d, dbInfo2) - // create table t3 (c1 int, c2 int, c3 int, c4 int); - tblInfo3, err := testTableInfo(d, "t3", 4) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, dbInfo2, tblInfo3) - // insert t3 values (11, 22, 33, 44) - tbl3 := testGetTable(c, d, dbInfo2.ID, tblInfo3.ID) - _, err = tbl3.AddRecord(ctx, types.MakeDatums(11, 22, 33, 44)) - c.Assert(err, IsNil) + tk.MustExec("create database test_parallel_ddl_1") + tk.MustExec("create database test_parallel_ddl_2") + tk.MustExec("create table test_parallel_ddl_1.t1(c1 int, c2 int, key db1_idx2(c2))") + tk.MustExec("create table test_parallel_ddl_1.t2(c1 int primary key, c2 int, c3 int)") + tk.MustExec("create table test_parallel_ddl_2.t3(c1 int, c2 int, c3 int, c4 int)") // set hook to execute jobs after all jobs are in queue. - jobCnt := int64(12) - tc := &TestDDLCallback{} + jobCnt := int64(11) + tc := &ddl.TestDDLCallback{Do: dom} once := sync.Once{} var checkErr error - tc.onJobRunBefore = func(job *model.Job) { + tc.OnJobRunBeforeExported = func(job *model.Job) { // TODO: extract a unified function for other tests. once.Do(func() { qLen1 := int64(0) qLen2 := int64(0) + var err error for { checkErr = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) @@ -1631,7 +129,7 @@ func (s *testDDLSuite) TestParallelDDL(c *C) { break } if qLen1+qLen2 == jobCnt { - if qLen2 != 6 { + if qLen2 != 5 { checkErr = errors.Errorf("add index jobs cnt %v != 6", qLen2) } break @@ -1640,7 +138,7 @@ func (s *testDDLSuite) TestParallelDDL(c *C) { } }) } - d.SetHook(tc) + dom.DDL().SetHook(tc) /* prepare jobs: @@ -1655,119 +153,115 @@ func (s *testDDLSuite) TestParallelDDL(c *C) { / 8 / 2 / 3 / rebase autoID/ / 9 / 1 / 1 / add index / / 10 / 2 / null / drop schema / - / 11 / 1 / 1 / modify column/ - / 12 / 2 / 2 / add index / + / 11 / 2 / 2 / add index / */ - job1 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx1", "c1") - addDDLJob(c, d, job1) - job2 := buildCreateColumnJob(dbInfo1, tblInfo1, "c3", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, nil) - addDDLJob(c, d, job2) - job3 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx2", "c3") - addDDLJob(c, d, job3) - job4 := buildDropColumnJob(dbInfo1, tblInfo2, "c3") - addDDLJob(c, d, job4) - job5 := buildDropIdxJob(dbInfo1, tblInfo1, "db1_idx1") - addDDLJob(c, d, job5) - job6 := buildCreateIdxJob(dbInfo1, tblInfo2, false, "db2_idx1", "c2") - addDDLJob(c, d, job6) - job7 := buildDropColumnJob(dbInfo2, tblInfo3, "c4") - addDDLJob(c, d, job7) - job8 := buildRebaseAutoIDJobJob(dbInfo2, tblInfo3, 1024) - addDDLJob(c, d, job8) - job9 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx3", "c2") - addDDLJob(c, d, job9) - job10 := buildDropSchemaJob(dbInfo2) - addDDLJob(c, d, job10) - job11 := buildModifyColJob(dbInfo1, tblInfo1) - addDDLJob(c, d, job11) - job12 := buildCreateIdxJob(dbInfo2, tblInfo3, false, "db3_idx1", "c2") - addDDLJob(c, d, job12) - // TODO: add rename table job - - // check results. - isChecked := false - for !isChecked { - err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { - m := meta.NewMeta(txn) - lastJob, err := m.GetHistoryDDLJob(job12.ID) - c.Assert(err, IsNil) - // all jobs are finished. - if lastJob != nil { - finishedJobs, err := m.GetAllHistoryDDLJobs() - c.Assert(err, IsNil) - // get the last 12 jobs completed. - finishedJobs = finishedJobs[len(finishedJobs)-12:] - // check some jobs are ordered because of the dependence. - c.Assert(finishedJobs[0].ID, Equals, job1.ID) - c.Assert(finishedJobs[1].ID, Equals, job2.ID) - c.Assert(finishedJobs[2].ID, Equals, job3.ID) - c.Assert(finishedJobs[4].ID, Equals, job5.ID) - c.Assert(finishedJobs[11].ID, Equals, job12.ID) - // check the jobs are ordered in the backfill-job queue or general-job queue. - backfillJobID := int64(0) - generalJobID := int64(0) - for _, job := range finishedJobs { - // check jobs' order. - if admin.MayNeedBackfill(job.Type) { - c.Assert(job.ID, Greater, backfillJobID) - backfillJobID = job.ID - } else { - c.Assert(job.ID, Greater, generalJobID) - generalJobID = job.ID - } - // check jobs' state. - if job.ID == lastJob.ID { - c.Assert(job.State, Equals, model.JobStateCancelled, Commentf("job: %v", job)) - } else { - c.Assert(job.State, Equals, model.JobStateSynced, Commentf("job: %v", job)) - } - } - - isChecked = true - } - return nil - }) - c.Assert(err, IsNil) - time.Sleep(10 * time.Millisecond) - } + var wg util.WaitGroupWrapper - c.Assert(checkErr, IsNil) - tc = &TestDDLCallback{} - d.SetHook(tc) -} + seqIDs := make([]int, 11) -func (s *testDDLSuite) TestDDLPackageExecuteSQL(c *C) { - store := testCreateStore(c, "test_run_sql") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() - - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - testCheckOwner(c, d, true) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - worker := d.generalWorker() - c.Assert(worker, NotNil) - - // In test environment, worker.ctxPool will be nil, and get will return mock.Context. - // We just test that can use it to call sqlexec.SQLExecutor.Execute. - sess, err := worker.sessPool.get() - c.Assert(err, IsNil) - defer worker.sessPool.put(sess) - se := sess.(sqlexec.SQLExecutor) - _, _ = se.Execute(context.Background(), "create table t(a int);") -} + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t1 add index db1_idx1(c1)") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[0], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t1 add column c3 int") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[1], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t1 add index db1_idxx(c1)") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[2], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t2 drop column c3") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[3], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t1 drop index db1_idx2") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[4], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t2 add index db1_idx2(c2)") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[5], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_2.t3 drop column c4") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[6], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_2.t3 auto_id_cache 1024") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[7], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("alter table test_parallel_ddl_1.t1 add index db1_idx3(c2)") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[8], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database test_parallel_ddl_2") + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[9], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) + time.Sleep(5 * time.Millisecond) + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + _, err := tk.Exec("alter table test_parallel_ddl_2.t3 add index db3_idx1(c2)") + require.Error(t, err) + rs := tk.MustQuery("select json_extract(@@tidb_last_ddl_info, '$.seq_num')") + seqIDs[10], _ = strconv.Atoi(rs.Rows()[0][0].(string)) + }) -func (s *testDDLSerialSuite) checkDropIndexes(c *C, d *ddl, schemaID int64, tableID int64, idxNames []model.CIStr, success bool) { - for _, idxName := range idxNames { - checkIdxExist(c, d, schemaID, tableID, idxName.O, !success) - } + wg.Wait() + + // Table 1 order. + require.Less(t, seqIDs[0], seqIDs[1]) + require.Less(t, seqIDs[1], seqIDs[2]) + require.Less(t, seqIDs[2], seqIDs[4]) + require.Less(t, seqIDs[4], seqIDs[8]) + + // Table 2 order. + require.Less(t, seqIDs[3], seqIDs[10]) + + // Table 3 order. + require.Less(t, seqIDs[6], seqIDs[7]) + require.Less(t, seqIDs[7], seqIDs[9]) + require.Less(t, seqIDs[9], seqIDs[10]) + + // General job order. + require.Less(t, seqIDs[1], seqIDs[3]) + require.Less(t, seqIDs[3], seqIDs[4]) + require.Less(t, seqIDs[4], seqIDs[6]) + require.Less(t, seqIDs[6], seqIDs[7]) + require.Less(t, seqIDs[7], seqIDs[9]) + + // Reorg job order. + require.Less(t, seqIDs[2], seqIDs[5]) + require.Less(t, seqIDs[5], seqIDs[8]) + require.Less(t, seqIDs[8], seqIDs[10]) } diff --git a/ddl/delete_range.go b/ddl/delete_range.go index f26fd4ccd7444..0b56300db04b4 100644 --- a/ddl/delete_range.go +++ b/ddl/delete_range.go @@ -17,10 +17,10 @@ package ddl import ( "context" "encoding/hex" + "fmt" "math" "strings" "sync" - "sync/atomic" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" @@ -32,6 +32,7 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "go.uber.org/zap" ) @@ -45,9 +46,6 @@ const ( ) var ( - // enableEmulatorGC means whether to enable emulator GC. The default is enable. - // In some unit tests, we want to stop emulator GC, then wen can set enableEmulatorGC to 0. - emulatorGCEnable = int32(1) // batchInsertDeleteRangeSize is the maximum size for each batch insert statement in the delete-range. batchInsertDeleteRangeSize = 256 ) @@ -96,7 +94,11 @@ func (dr *delRange) addDelRangeJob(ctx context.Context, job *model.Job) error { } defer dr.sessPool.put(sctx) - err = insertJobIntoDeleteRangeTable(ctx, sctx, job) + if job.MultiSchemaInfo != nil { + err = insertJobIntoDeleteRangeTableMultiSchema(ctx, sctx, job) + } else { + err = insertJobIntoDeleteRangeTable(ctx, sctx, job, &elementIDAlloc{}) + } if err != nil { logutil.BgLogger().Error("[ddl] add job into delete-range table failed", zap.Int64("jobID", job.ID), zap.String("jobType", job.Type.String()), zap.Error(err)) return errors.Trace(err) @@ -108,6 +110,20 @@ func (dr *delRange) addDelRangeJob(ctx context.Context, job *model.Job) error { return nil } +func insertJobIntoDeleteRangeTableMultiSchema(ctx context.Context, sctx sessionctx.Context, job *model.Job) error { + var ea elementIDAlloc + for _, sub := range job.MultiSchemaInfo.SubJobs { + proxyJob := cloneFromSubJob(job, sub) + if jobNeedGC(proxyJob) { + err := insertJobIntoDeleteRangeTable(ctx, sctx, proxyJob, &ea) + if err != nil { + return errors.Trace(err) + } + } + } + return nil +} + // removeFromGCDeleteRange implements delRangeManager interface. func (dr *delRange) removeFromGCDeleteRange(ctx context.Context, jobID int64, tableIDs []int64) error { sctx, err := dr.sessPool.get() @@ -146,28 +162,13 @@ func (dr *delRange) startEmulator() { case <-dr.quitCh: return } - if IsEmulatorGCEnable() { + if util.IsEmulatorGCEnable() { err := dr.doDelRangeWork() terror.Log(errors.Trace(err)) } } } -// EmulatorGCEnable enables emulator gc. It exports for testing. -func EmulatorGCEnable() { - atomic.StoreInt32(&emulatorGCEnable, 1) -} - -// EmulatorGCDisable disables emulator gc. It exports for testing. -func EmulatorGCDisable() { - atomic.StoreInt32(&emulatorGCEnable, 0) -} - -// IsEmulatorGCEnable indicates whether emulator GC enabled. It exports for testing. -func IsEmulatorGCEnable() bool { - return atomic.LoadInt32(&emulatorGCEnable) == 1 -} - func (dr *delRange) doDelRangeWork() error { ctx, err := dr.sessPool.get() if err != nil { @@ -198,6 +199,10 @@ func (dr *delRange) doTask(ctx sessionctx.Context, r util.DelRangeTask) error { finish := true dr.keys = dr.keys[:0] err := kv.RunInNewTxn(context.Background(), dr.store, false, func(ctx context.Context, txn kv.Transaction) error { + if topsqlstate.TopSQLEnabled() { + // Only when TiDB run without PD(use unistore as storage for test) will run into here, so just set a mock internal resource tagger. + txn.SetOption(kv.ResourceGroupTagger, util.GetInternalResourceGroupTaggerForTopSQL()) + } iter, err := txn.Iter(oldStartKey, r.EndKey) if err != nil { return errors.Trace(err) @@ -252,8 +257,8 @@ func (dr *delRange) doTask(ctx sessionctx.Context, r util.DelRangeTask) error { // insertJobIntoDeleteRangeTable parses the job into delete-range arguments, // and inserts a new record into gc_delete_range table. The primary key is -// job ID, so we ignore key conflict error. -func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, job *model.Job) error { +// (job ID, element ID), so we ignore key conflict error. +func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, job *model.Job, ea *elementIDAlloc) error { now, err := getNowTSO(sctx) if err != nil { return errors.Trace(err) @@ -271,7 +276,7 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, if batchEnd > i+batchInsertDeleteRangeSize { batchEnd = i + batchInsertDeleteRangeSize } - if err := doBatchInsert(ctx, s, job.ID, tableIDs[i:batchEnd], now); err != nil { + if err := doBatchInsert(ctx, s, job.ID, tableIDs[i:batchEnd], now, ea); err != nil { return errors.Trace(err) } } @@ -288,7 +293,8 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, for _, pid := range physicalTableIDs { startKey = tablecodec.EncodeTablePrefix(pid) endKey := tablecodec.EncodeTablePrefix(pid + 1) - if err := doInsert(ctx, s, job.ID, pid, startKey, endKey, now); err != nil { + elemID := ea.allocForPartitionID(pid) + if err := doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("partition ID is %d", pid)); err != nil { return errors.Trace(err) } } @@ -296,7 +302,8 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, } startKey = tablecodec.EncodeTablePrefix(tableID) endKey := tablecodec.EncodeTablePrefix(tableID + 1) - return doInsert(ctx, s, job.ID, tableID, startKey, endKey, now) + elemID := ea.allocForTableID(tableID) + return doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("table ID is %d", tableID)) case model.ActionDropTablePartition, model.ActionTruncateTablePartition: var physicalTableIDs []int64 if err := job.DecodeArgs(&physicalTableIDs); err != nil { @@ -305,7 +312,8 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, for _, physicalTableID := range physicalTableIDs { startKey := tablecodec.EncodeTablePrefix(physicalTableID) endKey := tablecodec.EncodeTablePrefix(physicalTableID + 1) - if err := doInsert(ctx, s, job.ID, physicalTableID, startKey, endKey, now); err != nil { + elemID := ea.allocForPartitionID(physicalTableID) + if err := doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("partition table ID is %d", physicalTableID)); err != nil { return errors.Trace(err) } } @@ -313,97 +321,67 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, case model.ActionAddIndex, model.ActionAddPrimaryKey: tableID := job.TableID var indexID int64 + var ifExists bool var partitionIDs []int64 - if err := job.DecodeArgs(&indexID, &partitionIDs); err != nil { + if err := job.DecodeArgs(&indexID, &ifExists, &partitionIDs); err != nil { return errors.Trace(err) } if len(partitionIDs) > 0 { for _, pid := range partitionIDs { startKey := tablecodec.EncodeTableIndexPrefix(pid, indexID) endKey := tablecodec.EncodeTableIndexPrefix(pid, indexID+1) - if err := doInsert(ctx, s, job.ID, indexID, startKey, endKey, now); err != nil { + elemID := ea.allocForIndexID(indexID) + if err := doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("partition table ID is %d", pid)); err != nil { return errors.Trace(err) } } } else { startKey := tablecodec.EncodeTableIndexPrefix(tableID, indexID) endKey := tablecodec.EncodeTableIndexPrefix(tableID, indexID+1) - return doInsert(ctx, s, job.ID, indexID, startKey, endKey, now) + elemID := ea.allocForIndexID(indexID) + return doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("table ID is %d", tableID)) } case model.ActionDropIndex, model.ActionDropPrimaryKey: tableID := job.TableID var indexName interface{} + var ifExists bool var indexID int64 var partitionIDs []int64 - if err := job.DecodeArgs(&indexName, &indexID, &partitionIDs); err != nil { + if err := job.DecodeArgs(&indexName, &ifExists, &indexID, &partitionIDs); err != nil { return errors.Trace(err) } if len(partitionIDs) > 0 { for _, pid := range partitionIDs { startKey := tablecodec.EncodeTableIndexPrefix(pid, indexID) endKey := tablecodec.EncodeTableIndexPrefix(pid, indexID+1) - if err := doInsert(ctx, s, job.ID, indexID, startKey, endKey, now); err != nil { + elemID := ea.allocForIndexID(indexID) + if err := doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("partition table ID is %d", pid)); err != nil { return errors.Trace(err) } } } else { startKey := tablecodec.EncodeTableIndexPrefix(tableID, indexID) endKey := tablecodec.EncodeTableIndexPrefix(tableID, indexID+1) - return doInsert(ctx, s, job.ID, indexID, startKey, endKey, now) - } - case model.ActionDropIndexes: - var indexIDs []int64 - var partitionIDs []int64 - if err := job.DecodeArgs(&[]model.CIStr{}, &[]bool{}, &indexIDs, &partitionIDs); err != nil { - return errors.Trace(err) - } - // Remove data in TiKV. - if len(indexIDs) == 0 { - return nil - } - if len(partitionIDs) == 0 { - return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now) - } - for _, pID := range partitionIDs { - if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pID, indexIDs, now); err != nil { - return errors.Trace(err) - } + elemID := ea.allocForIndexID(indexID) + return doInsert(ctx, s, job.ID, elemID, startKey, endKey, now, fmt.Sprintf("index ID is %d", indexID)) } case model.ActionDropColumn: var colName model.CIStr + var ifExists bool var indexIDs []int64 var partitionIDs []int64 - if err := job.DecodeArgs(&colName, &indexIDs, &partitionIDs); err != nil { - return errors.Trace(err) - } - if len(indexIDs) > 0 { - if len(partitionIDs) > 0 { - for _, pid := range partitionIDs { - if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pid, indexIDs, now); err != nil { - return errors.Trace(err) - } - } - } else { - return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now) - } - } - case model.ActionDropColumns: - var colNames []model.CIStr - var ifExists []bool - var indexIDs []int64 - var partitionIDs []int64 - if err := job.DecodeArgs(&colNames, &ifExists, &indexIDs, &partitionIDs); err != nil { + if err := job.DecodeArgs(&colName, &ifExists, &indexIDs, &partitionIDs); err != nil { return errors.Trace(err) } if len(indexIDs) > 0 { if len(partitionIDs) > 0 { for _, pid := range partitionIDs { - if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pid, indexIDs, now); err != nil { + if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pid, indexIDs, now, ea); err != nil { return errors.Trace(err) } } } else { - return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now) + return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now, ea) } } case model.ActionModifyColumn: @@ -416,10 +394,10 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, return nil } if len(partitionIDs) == 0 { - return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now) + return doBatchDeleteIndiceRange(ctx, s, job.ID, job.TableID, indexIDs, now, ea) } for _, pid := range partitionIDs { - if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pid, indexIDs, now); err != nil { + if err := doBatchDeleteIndiceRange(ctx, s, job.ID, pid, indexIDs, now, ea); err != nil { return errors.Trace(err) } } @@ -427,8 +405,8 @@ func insertJobIntoDeleteRangeTable(ctx context.Context, sctx sessionctx.Context, return nil } -func doBatchDeleteIndiceRange(ctx context.Context, s sqlexec.SQLExecutor, jobID, tableID int64, indexIDs []int64, ts uint64) error { - logutil.BgLogger().Info("[ddl] batch insert into delete-range indices", zap.Int64("jobID", jobID), zap.Int64s("elementIDs", indexIDs)) +func doBatchDeleteIndiceRange(ctx context.Context, s sqlexec.SQLExecutor, jobID, tableID int64, indexIDs []int64, ts uint64, ea *elementIDAlloc) error { + logutil.BgLogger().Info("[ddl] batch insert into delete-range indices", zap.Int64("jobID", jobID), zap.Int64("tableID", tableID), zap.Int64s("indexIDs", indexIDs)) paramsList := make([]interface{}, 0, len(indexIDs)*5) var buf strings.Builder buf.WriteString(insertDeleteRangeSQLPrefix) @@ -441,14 +419,15 @@ func doBatchDeleteIndiceRange(ctx context.Context, s sqlexec.SQLExecutor, jobID, if i != len(indexIDs)-1 { buf.WriteString(",") } - paramsList = append(paramsList, jobID, indexID, startKeyEncoded, endKeyEncoded, ts) + elemID := ea.allocForIndexID(indexID) + paramsList = append(paramsList, jobID, elemID, startKeyEncoded, endKeyEncoded, ts) } _, err := s.ExecuteInternal(ctx, buf.String(), paramsList...) return errors.Trace(err) } -func doInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID int64, elementID int64, startKey, endKey kv.Key, ts uint64) error { - logutil.BgLogger().Info("[ddl] insert into delete-range table", zap.Int64("jobID", jobID), zap.Int64("elementID", elementID)) +func doInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID, elementID int64, startKey, endKey kv.Key, ts uint64, comment string) error { + logutil.BgLogger().Info("[ddl] insert into delete-range table", zap.Int64("jobID", jobID), zap.Int64("elementID", elementID), zap.String("comment", comment)) startKeyEncoded := hex.EncodeToString(startKey) endKeyEncoded := hex.EncodeToString(endKey) // set session disk full opt @@ -460,8 +439,8 @@ func doInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID int64, elementID return errors.Trace(err) } -func doBatchInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID int64, tableIDs []int64, ts uint64) error { - logutil.BgLogger().Info("[ddl] batch insert into delete-range table", zap.Int64("jobID", jobID), zap.Int64s("elementIDs", tableIDs)) +func doBatchInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID int64, tableIDs []int64, ts uint64, ea *elementIDAlloc) error { + logutil.BgLogger().Info("[ddl] batch insert into delete-range table", zap.Int64("jobID", jobID), zap.Int64s("tableIDs", tableIDs)) var buf strings.Builder buf.WriteString(insertDeleteRangeSQLPrefix) paramsList := make([]interface{}, 0, len(tableIDs)*5) @@ -474,7 +453,8 @@ func doBatchInsert(ctx context.Context, s sqlexec.SQLExecutor, jobID int64, tabl if i != len(tableIDs)-1 { buf.WriteString(",") } - paramsList = append(paramsList, jobID, tableID, startKeyEncoded, endKeyEncoded, ts) + elemID := ea.allocForTableID(tableID) + paramsList = append(paramsList, jobID, elemID, startKeyEncoded, endKeyEncoded, ts) } // set session disk full opt s.SetDiskFullOpt(kvrpcpb.DiskFullOpt_AllowedOnAlmostFull) diff --git a/ddl/delete_range_util.go b/ddl/delete_range_util.go new file mode 100644 index 0000000000000..32409e26b9792 --- /dev/null +++ b/ddl/delete_range_util.go @@ -0,0 +1,55 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl + +const ( + elemTable byte = 't' + elemPartition byte = 'p' + elemIndex byte = 'i' +) + +type elementObjID struct { + tp byte + id int64 +} + +type elementIDAlloc struct { + objIDs map[elementObjID]int64 +} + +func (e *elementIDAlloc) allocForIndexID(indexID int64) int64 { + return e.alloc(elemIndex, indexID) +} + +func (e *elementIDAlloc) allocForTableID(tableID int64) int64 { + return e.alloc(elemTable, tableID) +} + +func (e *elementIDAlloc) allocForPartitionID(partitionID int64) int64 { + return e.alloc(elemPartition, partitionID) +} + +func (e *elementIDAlloc) alloc(tp byte, schemaObjID int64) int64 { + if e.objIDs == nil { + e.objIDs = make(map[elementObjID]int64) + } + objID := elementObjID{tp: tp, id: schemaObjID} + if elemID, found := e.objIDs[objID]; found { + return elemID + } + newElemID := int64(len(e.objIDs) + 1) + e.objIDs[objID] = newElemID + return newElemID +} diff --git a/ddl/error.go b/ddl/error.go deleted file mode 100644 index f95b5baf0e4a9..0000000000000 --- a/ddl/error.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2020 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ddl - -import ( - "fmt" - - mysql "github.com/pingcap/tidb/errno" - parser_mysql "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/util/dbterror" -) - -var ( - // errWorkerClosed means we have already closed the DDL worker. - errInvalidWorker = dbterror.ClassDDL.NewStd(mysql.ErrInvalidDDLWorker) - // errNotOwner means we are not owner and can't handle DDL jobs. - errNotOwner = dbterror.ClassDDL.NewStd(mysql.ErrNotOwner) - errCantDecodeRecord = dbterror.ClassDDL.NewStd(mysql.ErrCantDecodeRecord) - errInvalidDDLJob = dbterror.ClassDDL.NewStd(mysql.ErrInvalidDDLJob) - errCancelledDDLJob = dbterror.ClassDDL.NewStd(mysql.ErrCancelledDDLJob) - errFileNotFound = dbterror.ClassDDL.NewStd(mysql.ErrFileNotFound) - errRunMultiSchemaChanges = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "multi schema change"), nil)) - errWaitReorgTimeout = dbterror.ClassDDL.NewStdErr(mysql.ErrLockWaitTimeout, mysql.MySQLErrName[mysql.ErrWaitReorgTimeout]) - errInvalidStoreVer = dbterror.ClassDDL.NewStd(mysql.ErrInvalidStoreVersion) - // ErrRepairTableFail is used to repair tableInfo in repair mode. - ErrRepairTableFail = dbterror.ClassDDL.NewStd(mysql.ErrRepairTable) - - // We don't support dropping column with index covered now. - errCantDropColWithIndex = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "drop column with index"), nil)) - errUnsupportedAddColumn = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "add column"), nil)) - errUnsupportedModifyColumn = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "modify column: %s"), nil)) - errUnsupportedModifyCharset = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "modify %s"), nil)) - errUnsupportedModifyCollation = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "modifying collation from %s to %s"), nil)) - errUnsupportedPKHandle = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "drop integer primary key"), nil)) - errUnsupportedCharset = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "charset %s and collate %s"), nil)) - errUnsupportedShardRowIDBits = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "shard_row_id_bits for table with primary key as row id"), nil)) - errUnsupportedAlterTableWithValidation = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("ALTER TABLE WITH VALIDATION is currently unsupported", nil)) - errUnsupportedAlterTableWithoutValidation = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("ALTER TABLE WITHOUT VALIDATION is currently unsupported", nil)) - errUnsupportedAlterTableOption = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("This type of ALTER TABLE is currently unsupported", nil)) - errUnsupportedAlterReplicaForSysTable = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("ALTER table replica for tables in system database is currently unsupported", nil)) - errUnsupportedAlterCacheForSysTable = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("ALTER table cache for tables in system database is currently unsupported", nil)) - errBlobKeyWithoutLength = dbterror.ClassDDL.NewStd(mysql.ErrBlobKeyWithoutLength) - errKeyPart0 = dbterror.ClassDDL.NewStd(mysql.ErrKeyPart0) - errIncorrectPrefixKey = dbterror.ClassDDL.NewStd(mysql.ErrWrongSubKey) - errTooLongKey = dbterror.ClassDDL.NewStd(mysql.ErrTooLongKey) - errKeyColumnDoesNotExits = dbterror.ClassDDL.NewStd(mysql.ErrKeyColumnDoesNotExits) - errInvalidDDLJobVersion = dbterror.ClassDDL.NewStd(mysql.ErrInvalidDDLJobVersion) - errInvalidUseOfNull = dbterror.ClassDDL.NewStd(mysql.ErrInvalidUseOfNull) - errTooManyFields = dbterror.ClassDDL.NewStd(mysql.ErrTooManyFields) - errTooManyKeys = dbterror.ClassDDL.NewStd(mysql.ErrTooManyKeys) - errInvalidSplitRegionRanges = dbterror.ClassDDL.NewStd(mysql.ErrInvalidSplitRegionRanges) - errReorgPanic = dbterror.ClassDDL.NewStd(mysql.ErrReorgPanic) - errFkColumnCannotDrop = dbterror.ClassDDL.NewStd(mysql.ErrFkColumnCannotDrop) - errFKIncompatibleColumns = dbterror.ClassDDL.NewStd(mysql.ErrFKIncompatibleColumns) - - errAlterReplicaForUnsupportedCharsetTable = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "ALTER table replica for table contain %s charset"), nil)) - - errOnlyOnRangeListPartition = dbterror.ClassDDL.NewStd(mysql.ErrOnlyOnRangeListPartition) - // errWrongKeyColumn is for table column cannot be indexed. - errWrongKeyColumn = dbterror.ClassDDL.NewStd(mysql.ErrWrongKeyColumn) - // errWrongKeyColumnFunctionalIndex is for expression cannot be indexed. - errWrongKeyColumnFunctionalIndex = dbterror.ClassDDL.NewStd(mysql.ErrWrongKeyColumnFunctionalIndex) - // errWrongFKOptionForGeneratedColumn is for wrong foreign key reference option on generated columns. - errWrongFKOptionForGeneratedColumn = dbterror.ClassDDL.NewStd(mysql.ErrWrongFKOptionForGeneratedColumn) - // ErrUnsupportedOnGeneratedColumn is for unsupported actions on generated columns. - ErrUnsupportedOnGeneratedColumn = dbterror.ClassDDL.NewStd(mysql.ErrUnsupportedOnGeneratedColumn) - // errGeneratedColumnNonPrior forbids to refer generated column non prior to it. - errGeneratedColumnNonPrior = dbterror.ClassDDL.NewStd(mysql.ErrGeneratedColumnNonPrior) - // errDependentByGeneratedColumn forbids to delete columns which are dependent by generated columns. - errDependentByGeneratedColumn = dbterror.ClassDDL.NewStd(mysql.ErrDependentByGeneratedColumn) - // errJSONUsedAsKey forbids to use JSON as key or index. - errJSONUsedAsKey = dbterror.ClassDDL.NewStd(mysql.ErrJSONUsedAsKey) - // errBlobCantHaveDefault forbids to give not null default value to TEXT/BLOB/JSON. - errBlobCantHaveDefault = dbterror.ClassDDL.NewStd(mysql.ErrBlobCantHaveDefault) - errTooLongIndexComment = dbterror.ClassDDL.NewStd(mysql.ErrTooLongIndexComment) - // ErrInvalidDefaultValue returns for invalid default value for columns. - ErrInvalidDefaultValue = dbterror.ClassDDL.NewStd(mysql.ErrInvalidDefault) - // ErrGeneratedColumnRefAutoInc forbids to refer generated columns to auto-increment columns . - ErrGeneratedColumnRefAutoInc = dbterror.ClassDDL.NewStd(mysql.ErrGeneratedColumnRefAutoInc) - // ErrExpressionIndexCanNotRefer forbids to refer expression index to auto-increment column. - ErrExpressionIndexCanNotRefer = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexRefAutoIncrement) - // ErrUnsupportedAddPartition returns for does not support add partitions. - ErrUnsupportedAddPartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "add partitions"), nil)) - // ErrUnsupportedCoalescePartition returns for does not support coalesce partitions. - ErrUnsupportedCoalescePartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "coalesce partitions"), nil)) - errUnsupportedReorganizePartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "reorganize partition"), nil)) - errUnsupportedCheckPartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "check partition"), nil)) - errUnsupportedOptimizePartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "optimize partition"), nil)) - errUnsupportedRebuildPartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "rebuild partition"), nil)) - errUnsupportedRemovePartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "remove partitioning"), nil)) - errUnsupportedRepairPartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "repair partition"), nil)) - // ErrGeneratedColumnFunctionIsNotAllowed returns for unsupported functions for generated columns. - ErrGeneratedColumnFunctionIsNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrGeneratedColumnFunctionIsNotAllowed) - // ErrGeneratedColumnRowValueIsNotAllowed returns for generated columns referring to row values. - ErrGeneratedColumnRowValueIsNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrGeneratedColumnRowValueIsNotAllowed) - // ErrUnsupportedPartitionByRangeColumns returns for does unsupported partition by range columns. - ErrUnsupportedPartitionByRangeColumns = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "partition by range columns"), nil)) - // ErrFunctionalIndexFunctionIsNotAllowed returns for unsupported functions for functional index. - ErrFunctionalIndexFunctionIsNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexFunctionIsNotAllowed) - // ErrFunctionalIndexRowValueIsNotAllowed returns for functional index referring to row values. - ErrFunctionalIndexRowValueIsNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexRowValueIsNotAllowed) - errUnsupportedCreatePartition = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "partition type, treat as normal table"), nil)) - errTablePartitionDisabled = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("Partitions are ignored because Table Partition is disabled, please set 'tidb_enable_table_partition' if you need to need to enable it", nil)) - errUnsupportedIndexType = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "index type"), nil)) - errWindowInvalidWindowFuncUse = dbterror.ClassDDL.NewStd(mysql.ErrWindowInvalidWindowFuncUse) - - // ErrDupKeyName returns for duplicated key name. - ErrDupKeyName = dbterror.ClassDDL.NewStd(mysql.ErrDupKeyName) - // ErrFkDupName returns for duplicated FK name. - ErrFkDupName = dbterror.ClassDDL.NewStd(mysql.ErrFkDupName) - // ErrInvalidDDLState returns for invalid ddl model object state. - ErrInvalidDDLState = dbterror.ClassDDL.NewStdErr(mysql.ErrInvalidDDLState, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrInvalidDDLState].Raw), nil)) - // ErrUnsupportedModifyPrimaryKey returns an error when add or drop the primary key. - // It's exported for testing. - ErrUnsupportedModifyPrimaryKey = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "%s primary key"), nil)) - // ErrPKIndexCantBeInvisible return an error when primary key is invisible index - ErrPKIndexCantBeInvisible = dbterror.ClassDDL.NewStd(mysql.ErrPKIndexCantBeInvisible) - - // ErrColumnBadNull returns for a bad null value. - ErrColumnBadNull = dbterror.ClassDDL.NewStd(mysql.ErrBadNull) - // ErrBadField forbids to refer to unknown column. - ErrBadField = dbterror.ClassDDL.NewStd(mysql.ErrBadField) - // ErrCantRemoveAllFields returns for deleting all columns. - ErrCantRemoveAllFields = dbterror.ClassDDL.NewStd(mysql.ErrCantRemoveAllFields) - // ErrCantDropFieldOrKey returns for dropping a non-existent field or key. - ErrCantDropFieldOrKey = dbterror.ClassDDL.NewStd(mysql.ErrCantDropFieldOrKey) - // ErrInvalidOnUpdate returns for invalid ON UPDATE clause. - ErrInvalidOnUpdate = dbterror.ClassDDL.NewStd(mysql.ErrInvalidOnUpdate) - // ErrTooLongIdent returns for too long name of database/table/column/index. - ErrTooLongIdent = dbterror.ClassDDL.NewStd(mysql.ErrTooLongIdent) - // ErrWrongDBName returns for wrong database name. - ErrWrongDBName = dbterror.ClassDDL.NewStd(mysql.ErrWrongDBName) - // ErrWrongTableName returns for wrong table name. - ErrWrongTableName = dbterror.ClassDDL.NewStd(mysql.ErrWrongTableName) - // ErrWrongColumnName returns for wrong column name. - ErrWrongColumnName = dbterror.ClassDDL.NewStd(mysql.ErrWrongColumnName) - // ErrWrongUsage returns for wrong ddl syntax usage. - ErrWrongUsage = dbterror.ClassDDL.NewStd(mysql.ErrWrongUsage) - // ErrInvalidGroupFuncUse returns for using invalid group functions. - ErrInvalidGroupFuncUse = dbterror.ClassDDL.NewStd(mysql.ErrInvalidGroupFuncUse) - // ErrTableMustHaveColumns returns for missing column when creating a table. - ErrTableMustHaveColumns = dbterror.ClassDDL.NewStd(mysql.ErrTableMustHaveColumns) - // ErrWrongNameForIndex returns for wrong index name. - ErrWrongNameForIndex = dbterror.ClassDDL.NewStd(mysql.ErrWrongNameForIndex) - // ErrUnknownCharacterSet returns unknown character set. - ErrUnknownCharacterSet = dbterror.ClassDDL.NewStd(mysql.ErrUnknownCharacterSet) - // ErrUnknownCollation returns unknown collation. - ErrUnknownCollation = dbterror.ClassDDL.NewStd(mysql.ErrUnknownCollation) - // ErrCollationCharsetMismatch returns when collation not match the charset. - ErrCollationCharsetMismatch = dbterror.ClassDDL.NewStd(mysql.ErrCollationCharsetMismatch) - // ErrConflictingDeclarations return conflict declarations. - ErrConflictingDeclarations = dbterror.ClassDDL.NewStdErr(mysql.ErrConflictingDeclarations, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrConflictingDeclarations].Raw, "CHARACTER SET ", "%s", "CHARACTER SET ", "%s"), nil)) - // ErrPrimaryCantHaveNull returns All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead - ErrPrimaryCantHaveNull = dbterror.ClassDDL.NewStd(mysql.ErrPrimaryCantHaveNull) - // ErrErrorOnRename returns error for wrong database name in alter table rename - ErrErrorOnRename = dbterror.ClassDDL.NewStd(mysql.ErrErrorOnRename) - // ErrViewSelectClause returns error for create view with select into clause - ErrViewSelectClause = dbterror.ClassDDL.NewStd(mysql.ErrViewSelectClause) - - // ErrNotAllowedTypeInPartition returns not allowed type error when creating table partition with unsupported expression type. - ErrNotAllowedTypeInPartition = dbterror.ClassDDL.NewStd(mysql.ErrFieldTypeNotAllowedAsPartitionField) - // ErrPartitionMgmtOnNonpartitioned returns it's not a partition table. - ErrPartitionMgmtOnNonpartitioned = dbterror.ClassDDL.NewStd(mysql.ErrPartitionMgmtOnNonpartitioned) - // ErrDropPartitionNonExistent returns error in list of partition. - ErrDropPartitionNonExistent = dbterror.ClassDDL.NewStd(mysql.ErrDropPartitionNonExistent) - // ErrSameNamePartition returns duplicate partition name. - ErrSameNamePartition = dbterror.ClassDDL.NewStd(mysql.ErrSameNamePartition) - // ErrRangeNotIncreasing returns values less than value must be strictly increasing for each partition. - ErrRangeNotIncreasing = dbterror.ClassDDL.NewStd(mysql.ErrRangeNotIncreasing) - // ErrPartitionMaxvalue returns maxvalue can only be used in last partition definition. - ErrPartitionMaxvalue = dbterror.ClassDDL.NewStd(mysql.ErrPartitionMaxvalue) - // ErrDropLastPartition returns cannot remove all partitions, use drop table instead. - ErrDropLastPartition = dbterror.ClassDDL.NewStd(mysql.ErrDropLastPartition) - // ErrTooManyPartitions returns too many partitions were defined. - ErrTooManyPartitions = dbterror.ClassDDL.NewStd(mysql.ErrTooManyPartitions) - // ErrPartitionConstDomain returns partition constant is out of partition function domain. - ErrPartitionConstDomain = dbterror.ClassDDL.NewStd(mysql.ErrPartitionConstDomain) - // ErrPartitionFunctionIsNotAllowed returns this partition function is not allowed. - ErrPartitionFunctionIsNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrPartitionFunctionIsNotAllowed) - // ErrPartitionFuncNotAllowed returns partition function returns the wrong type. - ErrPartitionFuncNotAllowed = dbterror.ClassDDL.NewStd(mysql.ErrPartitionFuncNotAllowed) - // ErrUniqueKeyNeedAllFieldsInPf returns must include all columns in the table's partitioning function. - ErrUniqueKeyNeedAllFieldsInPf = dbterror.ClassDDL.NewStd(mysql.ErrUniqueKeyNeedAllFieldsInPf) - // ErrWrongExprInPartitionFunc Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed. - ErrWrongExprInPartitionFunc = dbterror.ClassDDL.NewStd(mysql.ErrWrongExprInPartitionFunc) - // ErrWarnDataTruncated returns data truncated error. - ErrWarnDataTruncated = dbterror.ClassDDL.NewStd(mysql.WarnDataTruncated) - // ErrCoalesceOnlyOnHashPartition returns coalesce partition can only be used on hash/key partitions. - ErrCoalesceOnlyOnHashPartition = dbterror.ClassDDL.NewStd(mysql.ErrCoalesceOnlyOnHashPartition) - // ErrViewWrongList returns create view must include all columns in the select clause - ErrViewWrongList = dbterror.ClassDDL.NewStd(mysql.ErrViewWrongList) - // ErrAlterOperationNotSupported returns when alter operations is not supported. - ErrAlterOperationNotSupported = dbterror.ClassDDL.NewStd(mysql.ErrAlterOperationNotSupportedReason) - // ErrWrongObject returns for wrong object. - ErrWrongObject = dbterror.ClassDDL.NewStd(mysql.ErrWrongObject) - // ErrTableCantHandleFt returns FULLTEXT keys are not supported by table type - ErrTableCantHandleFt = dbterror.ClassDDL.NewStd(mysql.ErrTableCantHandleFt) - // ErrFieldNotFoundPart returns an error when 'partition by columns' are not found in table columns. - ErrFieldNotFoundPart = dbterror.ClassDDL.NewStd(mysql.ErrFieldNotFoundPart) - // ErrWrongTypeColumnValue returns 'Partition column values of incorrect type' - ErrWrongTypeColumnValue = dbterror.ClassDDL.NewStd(mysql.ErrWrongTypeColumnValue) - // ErrValuesIsNotIntType returns 'VALUES value for partition '%-.64s' must have type INT' - ErrValuesIsNotIntType = dbterror.ClassDDL.NewStd(mysql.ErrValuesIsNotIntType) - // ErrFunctionalIndexPrimaryKey returns 'The primary key cannot be a functional index' - ErrFunctionalIndexPrimaryKey = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexPrimaryKey) - // ErrFunctionalIndexOnField returns 'Functional index on a column is not supported. Consider using a regular index instead' - ErrFunctionalIndexOnField = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexOnField) - // ErrInvalidAutoRandom returns when auto_random is used incorrectly. - ErrInvalidAutoRandom = dbterror.ClassDDL.NewStd(mysql.ErrInvalidAutoRandom) - // ErrUnsupportedConstraintCheck returns when use ADD CONSTRAINT CHECK - ErrUnsupportedConstraintCheck = dbterror.ClassDDL.NewStd(mysql.ErrUnsupportedConstraintCheck) - // ErrDerivedMustHaveAlias returns when a sub select statement does not have a table alias. - ErrDerivedMustHaveAlias = dbterror.ClassDDL.NewStd(mysql.ErrDerivedMustHaveAlias) - - // ErrSequenceRunOut returns when the sequence has been run out. - ErrSequenceRunOut = dbterror.ClassDDL.NewStd(mysql.ErrSequenceRunOut) - // ErrSequenceInvalidData returns when sequence values are conflicting. - ErrSequenceInvalidData = dbterror.ClassDDL.NewStd(mysql.ErrSequenceInvalidData) - // ErrSequenceAccessFail returns when sequences are not able to access. - ErrSequenceAccessFail = dbterror.ClassDDL.NewStd(mysql.ErrSequenceAccessFail) - // ErrNotSequence returns when object is not a sequence. - ErrNotSequence = dbterror.ClassDDL.NewStd(mysql.ErrNotSequence) - // ErrUnknownSequence returns when drop / alter unknown sequence. - ErrUnknownSequence = dbterror.ClassDDL.NewStd(mysql.ErrUnknownSequence) - // ErrSequenceUnsupportedTableOption returns when unsupported table option exists in sequence. - ErrSequenceUnsupportedTableOption = dbterror.ClassDDL.NewStd(mysql.ErrSequenceUnsupportedTableOption) - // ErrColumnTypeUnsupportedNextValue is returned when sequence next value is assigned to unsupported column type. - ErrColumnTypeUnsupportedNextValue = dbterror.ClassDDL.NewStd(mysql.ErrColumnTypeUnsupportedNextValue) - // ErrAddColumnWithSequenceAsDefault is returned when the new added column with sequence's nextval as it's default value. - ErrAddColumnWithSequenceAsDefault = dbterror.ClassDDL.NewStd(mysql.ErrAddColumnWithSequenceAsDefault) - // ErrUnsupportedExpressionIndex is returned when create an expression index without allow-expression-index. - ErrUnsupportedExpressionIndex = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "creating expression index containing unsafe functions without allow-expression-index in config"), nil)) - // ErrPartitionExchangePartTable is returned when exchange table partition with another table is partitioned. - ErrPartitionExchangePartTable = dbterror.ClassDDL.NewStd(mysql.ErrPartitionExchangePartTable) - // ErrTablesDifferentMetadata is returned when exchanges tables is not compatible. - ErrTablesDifferentMetadata = dbterror.ClassDDL.NewStd(mysql.ErrTablesDifferentMetadata) - // ErrRowDoesNotMatchPartition is returned when the row record of exchange table does not match the partition rule. - ErrRowDoesNotMatchPartition = dbterror.ClassDDL.NewStd(mysql.ErrRowDoesNotMatchPartition) - // ErrPartitionExchangeForeignKey is returned when exchanged normal table has foreign keys. - ErrPartitionExchangeForeignKey = dbterror.ClassDDL.NewStd(mysql.ErrPartitionExchangeForeignKey) - // ErrCheckNoSuchTable is returned when exchanged normal table is view or sequence. - ErrCheckNoSuchTable = dbterror.ClassDDL.NewStd(mysql.ErrCheckNoSuchTable) - errUnsupportedPartitionType = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message(fmt.Sprintf(mysql.MySQLErrName[mysql.ErrUnsupportedDDLOperation].Raw, "partition type of table %s when exchanging partition"), nil)) - // ErrPartitionExchangeDifferentOption is returned when attribute does not match between partition table and normal table. - ErrPartitionExchangeDifferentOption = dbterror.ClassDDL.NewStd(mysql.ErrPartitionExchangeDifferentOption) - // ErrTableOptionUnionUnsupported is returned when create/alter table with union option. - ErrTableOptionUnionUnsupported = dbterror.ClassDDL.NewStd(mysql.ErrTableOptionUnionUnsupported) - // ErrTableOptionInsertMethodUnsupported is returned when create/alter table with insert method option. - ErrTableOptionInsertMethodUnsupported = dbterror.ClassDDL.NewStd(mysql.ErrTableOptionInsertMethodUnsupported) - - // ErrInvalidPlacementPolicyCheck is returned when txn_scope and commit data changing do not meet the placement policy - ErrInvalidPlacementPolicyCheck = dbterror.ClassDDL.NewStd(mysql.ErrPlacementPolicyCheck) - - // ErrPlacementPolicyWithDirectOption is returned when create/alter table with both placement policy and placement options existed. - ErrPlacementPolicyWithDirectOption = dbterror.ClassDDL.NewStd(mysql.ErrPlacementPolicyWithDirectOption) - - // ErrPlacementPolicyInUse is returned when placement policy is in use in drop/alter. - ErrPlacementPolicyInUse = dbterror.ClassDDL.NewStd(mysql.ErrPlacementPolicyInUse) - - // ErrPlacementDisabled is returned when tidb_enable_alter_placement = 0 - ErrPlacementDisabled = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("Alter Placement Rule is disabled, please set 'tidb_enable_alter_placement' if you need to enable it", nil)) - - // ErrMultipleDefConstInListPart returns multiple definition of same constant in list partitioning. - ErrMultipleDefConstInListPart = dbterror.ClassDDL.NewStd(mysql.ErrMultipleDefConstInListPart) - - // ErrTruncatedWrongValue is returned when data has been truncated during conversion. - ErrTruncatedWrongValue = dbterror.ClassDDL.NewStd(mysql.ErrTruncatedWrongValue) - - // ErrWarnDataOutOfRange is returned when the value in a numeric column that is outside the permissible range of the column data type. - // See https://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html for details - ErrWarnDataOutOfRange = dbterror.ClassDDL.NewStd(mysql.ErrWarnDataOutOfRange) - - // ErrTooLongValueForType is returned when the individual enum element length is too long. - ErrTooLongValueForType = dbterror.ClassDDL.NewStd(mysql.ErrTooLongValueForType) - - // ErrUnknownEngine is returned when the table engine is unknown. - ErrUnknownEngine = dbterror.ClassDDL.NewStd(mysql.ErrUnknownStorageEngine) - - errExchangePartitionDisabled = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("Exchange Partition is disabled, please set 'tidb_enable_exchange_partition' if you need to need to enable it", nil)) - - // ErrPartitionNoTemporary returns when partition at temporary mode - ErrPartitionNoTemporary = dbterror.ClassDDL.NewStd(mysql.ErrPartitionNoTemporary) - - // ErrOptOnTemporaryTable returns when exec unsupported opt at temporary mode - ErrOptOnTemporaryTable = dbterror.ClassDDL.NewStd(mysql.ErrOptOnTemporaryTable) - // ErrOptOnCacheTable returns when exec unsupported opt at cache mode - ErrOptOnCacheTable = dbterror.ClassDDL.NewStd(mysql.ErrOptOnCacheTable) - errUnsupportedOnCommitPreserve = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("TiDB doesn't support ON COMMIT PRESERVE ROWS for now", nil)) - errUnsupportedClusteredSecondaryKey = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("CLUSTERED/NONCLUSTERED keyword is only supported for primary key", nil)) - - // ErrUnsupportedLocalTempTableDDL returns when ddl operation unsupported for local temporary table - ErrUnsupportedLocalTempTableDDL = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("TiDB doesn't support %s for local temporary table", nil)) - // ErrInvalidAttributesSpec is returned when meeting invalid attributes. - ErrInvalidAttributesSpec = dbterror.ClassDDL.NewStd(mysql.ErrInvalidAttributesSpec) - // errFunctionalIndexOnJSONOrGeometryFunction returns when creating expression index and the type of the expression is JSON. - errFunctionalIndexOnJSONOrGeometryFunction = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexOnJSONOrGeometryFunction) - // errDependentByFunctionalIndex returns when the dropped column depends by expression index. - errDependentByFunctionalIndex = dbterror.ClassDDL.NewStd(mysql.ErrDependentByFunctionalIndex) - // errFunctionalIndexOnBlob when the expression of expression index returns blob or text. - errFunctionalIndexOnBlob = dbterror.ClassDDL.NewStd(mysql.ErrFunctionalIndexOnBlob) -) diff --git a/parser/charset/gbk.go b/ddl/export_test.go similarity index 54% rename from parser/charset/gbk.go rename to ddl/export_test.go index 5686c6e1b50f0..708b3474515c5 100644 --- a/parser/charset/gbk.go +++ b/ddl/export_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 PingCAP, Inc. +// Copyright 2022 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -8,22 +8,12 @@ // // 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 charset +package ddl -import "golang.org/x/text/encoding/simplifiedchinese" - -var GBKEncoding = &Encoding{ - enc: simplifiedchinese.GBK, - name: CharsetGBK, - charLength: func(bs []byte) int { - if len(bs) == 0 || bs[0] < 0x80 { - // A byte in the range 00–7F is a single byte that means the same thing as it does in ASCII. - return 1 - } - return 2 - }, - specialCase: GBKCase, +func SetBatchInsertDeleteRangeSize(i int) { + batchInsertDeleteRangeSize = i } diff --git a/ddl/fail_test.go b/ddl/fail_test.go index 387691c30950c..741fa739ca289 100644 --- a/ddl/fail_test.go +++ b/ddl/fail_test.go @@ -11,68 +11,57 @@ // 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 ddl +// +package ddl_test import ( - "context" + "strconv" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testColumnChangeSuite) TestFailBeforeDecodeArgs(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - // create table t_fail (c1 int, c2 int); - tblInfo, err := testTableInfo(d, "t_fail", 2) - c.Assert(err, IsNil) - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - // insert t_fail values (1, 2); - originTable := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - row := types.MakeDatums(1, 2) - _, err = originTable.AddRecord(ctx, row) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) +func TestFailBeforeDecodeArgs(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, testLease) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int);") + tk.MustExec("insert t1 values (1, 2);") + + var tableID int64 + rs := tk.MustQuery("select TIDB_TABLE_ID from information_schema.tables where table_name='t1' and table_schema='test';") + tableIDi, _ := strconv.Atoi(rs.Rows()[0][0].(string)) + tableID = int64(tableIDi) + + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} - tc := &TestDDLCallback{} first := true stateCnt := 0 - tc.onJobRunBefore = func(job *model.Job) { + tc.OnJobRunBeforeExported = func(job *model.Job) { // It can be other schema states except failed schema state. // This schema state can only appear once. if job.SchemaState == model.StateWriteOnly { stateCnt++ } else if job.SchemaState == model.StateWriteReorganization { if first { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/errorBeforeDecodeArgs", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/errorBeforeDecodeArgs", `return(true)`)) first = false } else { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/errorBeforeDecodeArgs"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/errorBeforeDecodeArgs")) } } } d.SetHook(tc) defaultValue := int64(3) - job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c3", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, defaultValue) + jobID := testCreateColumn(tk, t, testNewContext(store), tableID, "c3", "", defaultValue, dom) // Make sure the schema state only appears once. - c.Assert(stateCnt, Equals, 1) - testCheckJobDone(c, d, job, true) + require.Equal(t, 1, stateCnt) + testCheckJobDone(t, store, jobID, true) } diff --git a/ddl/failtest/fail_db_serial_test.go b/ddl/failtest/fail_db_test.go similarity index 85% rename from ddl/failtest/fail_db_serial_test.go rename to ddl/failtest/fail_db_test.go index 1c509ee121e68..874acd12b5bbc 100644 --- a/ddl/failtest/fail_db_serial_test.go +++ b/ddl/failtest/fail_db_test.go @@ -230,10 +230,10 @@ func TestFailSchemaSyncer(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") defer tk.MustExec("drop table if exists t") - originalRetryTimes := domain.SchemaOutOfDateRetryTimes - domain.SchemaOutOfDateRetryTimes = 1 + originalRetryTimes := domain.SchemaOutOfDateRetryTimes.Load() + domain.SchemaOutOfDateRetryTimes.Store(1) defer func() { - domain.SchemaOutOfDateRetryTimes = originalRetryTimes + domain.SchemaOutOfDateRetryTimes.Store(originalRetryTimes) }() require.True(t, s.dom.SchemaValidator.IsStarted()) mockSyncer, ok := s.dom.DDL().SchemaSyncer().(*ddl.MockSchemaSyncer) @@ -317,100 +317,92 @@ func TestGenGlobalIDFail(t *testing.T) { tk.MustExec("admin check table t2") } -func TestAddIndexWorkerNum(t *testing.T) { +// TestRunDDLJobPanicEnableClusteredIndex tests recover panic with cluster index when run ddl job panic. +func TestRunDDLJobPanicEnableClusteredIndex(t *testing.T) { s, clean := createFailDBSuite(t) defer clean() + testAddIndexWorkerNum(t, s, func(tk *testkit.TestKit) { + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1, c3))") + }) +} - tests := []struct { - name string - createTable func(*testkit.TestKit) - }{ - { - "EnableClusteredIndex", - func(tk *testkit.TestKit) { - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1, c3))") - }, - }, - { - "DisableClusteredIndex", - func(tk *testkit.TestKit) { - tk.MustExec("create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1))") - }, - }, - } +// TestRunDDLJobPanicDisableClusteredIndex tests recover panic without cluster index when run ddl job panic. +func TestRunDDLJobPanicDisableClusteredIndex(t *testing.T) { + s, clean := createFailDBSuite(t) + defer clean() + testAddIndexWorkerNum(t, s, func(tk *testkit.TestKit) { + tk.MustExec("create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1))") + }) +} - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - tk := testkit.NewTestKit(t, s.store) - tk.MustExec("create database if not exists test_db") - tk.MustExec("use test_db") - tk.MustExec("drop table if exists test_add_index") - - test.createTable(tk) - - done := make(chan error, 1) - start := -10 - - // first add some rows - for i := start; i < 4090; i += 100 { - dml := "insert into test_add_index values" - end := i + 100 - for k := i; k < end; k++ { - dml += fmt.Sprintf("(%d, %d, %d)", k, k, k) - if k != end-1 { - dml += "," - } - } - tk.MustExec(dml) +func testAddIndexWorkerNum(t *testing.T, s *failedSuite, test func(*testkit.TestKit)) { + tk := testkit.NewTestKit(t, s.store) + tk.MustExec("create database if not exists test_db") + tk.MustExec("use test_db") + tk.MustExec("drop table if exists test_add_index") + + test(tk) + + done := make(chan error, 1) + start := -10 + + // first add some rows + for i := start; i < 4090; i += 100 { + dml := "insert into test_add_index values" + end := i + 100 + for k := i; k < end; k++ { + dml += fmt.Sprintf("(%d, %d, %d)", k, k, k) + if k != end-1 { + dml += "," } + } + tk.MustExec(dml) + } - is := s.dom.InfoSchema() - schemaName := model.NewCIStr("test_db") - tableName := model.NewCIStr("test_add_index") - tbl, err := is.TableByName(schemaName, tableName) - require.NoError(t, err) + is := s.dom.InfoSchema() + schemaName := model.NewCIStr("test_db") + tableName := model.NewCIStr("test_add_index") + tbl, err := is.TableByName(schemaName, tableName) + require.NoError(t, err) + + splitCount := 100 + // Split table to multi region. + tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) + s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), splitCount) + + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + originDDLAddIndexWorkerCnt := variable.GetDDLReorgWorkerCounter() + lastSetWorkerCnt := originDDLAddIndexWorkerCnt + atomic.StoreInt32(&ddl.TestCheckWorkerNumber, lastSetWorkerCnt) + ddl.TestCheckWorkerNumber = lastSetWorkerCnt + defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_worker_cnt=%d", originDDLAddIndexWorkerCnt)) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum", `return(true)`)) - splitCount := 100 - // Split table to multi region. - tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), splitCount) + testutil.SessionExecInGoroutine(s.store, "test_db", "create index c3_index on test_add_index (c3)", done) + checkNum := 0 - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + running := true + for running { + select { + case err = <-done: require.NoError(t, err) - originDDLAddIndexWorkerCnt := variable.GetDDLReorgWorkerCounter() - lastSetWorkerCnt := originDDLAddIndexWorkerCnt + running = false + case wg := <-ddl.TestCheckWorkerNumCh: + lastSetWorkerCnt = int32(rand.Intn(8) + 8) + tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_worker_cnt=%d", lastSetWorkerCnt)) atomic.StoreInt32(&ddl.TestCheckWorkerNumber, lastSetWorkerCnt) - ddl.TestCheckWorkerNumber = lastSetWorkerCnt - defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_worker_cnt=%d", originDDLAddIndexWorkerCnt)) - - require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum", `return(true)`)) - defer func() { - require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum")) - }() - - testutil.SessionExecInGoroutine(s.store, "create index c3_index on test_add_index (c3)", done) - checkNum := 0 - - running := true - for running { - select { - case err = <-done: - require.NoError(t, err) - running = false - case <-ddl.TestCheckWorkerNumCh: - lastSetWorkerCnt = int32(rand.Intn(8) + 8) - tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_worker_cnt=%d", lastSetWorkerCnt)) - atomic.StoreInt32(&ddl.TestCheckWorkerNumber, lastSetWorkerCnt) - checkNum++ - } - } - - require.Greater(t, checkNum, 5) - tk.MustExec("admin check table test_add_index") - tk.MustExec("drop table test_add_index") - }) + checkNum++ + wg.Done() + } } + + require.Greater(t, checkNum, 5) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum")) + tk.MustExec("admin check table test_add_index") + tk.MustExec("drop table test_add_index") } // TestRunDDLJobPanic tests recover panic when run ddl job panic. diff --git a/ddl/failtest/main_test.go b/ddl/failtest/main_test.go index 7c9e3d4bae618..f3ce7d61fe808 100644 --- a/ddl/failtest/main_test.go +++ b/ddl/failtest/main_test.go @@ -25,7 +25,7 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() config.UpdateGlobal(func(conf *config.Config) { conf.TiKVClient.AsyncCommit.SafeWindow = 0 @@ -35,7 +35,8 @@ func TestMain(m *testing.M) { ddl.SetWaitTimeWhenErrorOccurred(time.Microsecond) opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/ddl/foreign_key.go b/ddl/foreign_key.go index 6883390ce5671..f7b1ba5a1086b 100644 --- a/ddl/foreign_key.go +++ b/ddl/foreign_key.go @@ -19,11 +19,12 @@ import ( "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/util/dbterror" ) func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } @@ -51,13 +52,13 @@ func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) return ver, nil default: - return ver, ErrInvalidDDLState.GenWithStack("foreign key", fkInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStack("foreign key", fkInfo.State) } } func onDropForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } @@ -107,7 +108,7 @@ func onDropForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) return ver, nil default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("foreign key", fkInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("foreign key", fkInfo.State) } } diff --git a/ddl/foreign_key_test.go b/ddl/foreign_key_test.go index 0ecab739fb184..43f8b7d065429 100644 --- a/ddl/foreign_key_test.go +++ b/ddl/foreign_key_test.go @@ -18,35 +18,22 @@ import ( "context" "strings" "sync" + "testing" + "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testForeignKeySuite{}) +const testLease = 5 * time.Millisecond -type testForeignKeySuite struct { - store kv.Storage - dbInfo *model.DBInfo - d *ddl - ctx sessionctx.Context -} - -func (s *testForeignKeySuite) SetUpSuite(c *C) { - s.store = testCreateStore(c, "test_foreign") -} - -func (s *testForeignKeySuite) TearDownSuite(c *C) { - err := s.store.Close() - c.Assert(err, IsNil) -} - -func (s *testForeignKeySuite) testCreateForeignKey(c *C, tblInfo *model.TableInfo, fkName string, keys []string, refTable string, refKeys []string, onDelete ast.ReferOptionType, onUpdate ast.ReferOptionType) *model.Job { +func testCreateForeignKey(t *testing.T, d *ddl, ctx sessionctx.Context, dbInfo *model.DBInfo, tblInfo *model.TableInfo, fkName string, keys []string, refTable string, refKeys []string, onDelete ast.ReferOptionType, onUpdate ast.ReferOptionType) *model.Job { FKName := model.NewCIStr(fkName) Keys := make([]model.CIStr, len(keys)) for i, key := range keys { @@ -70,20 +57,21 @@ func (s *testForeignKeySuite) testCreateForeignKey(c *C, tblInfo *model.TableInf } job := &model.Job{ - SchemaID: s.dbInfo.ID, + SchemaID: dbInfo.ID, TableID: tblInfo.ID, Type: model.ActionAddForeignKey, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{fkInfo}, } - err := s.ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - err = s.d.doDDLJob(s.ctx, job) - c.Assert(err, IsNil) + err := ctx.NewTxn(context.Background()) + require.NoError(t, err) + ctx.SetValue(sessionctx.QueryString, "skip") + err = d.DoDDLJob(ctx, job) + require.NoError(t, err) return job } -func testDropForeignKey(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, foreignKeyName string) *model.Job { +func testDropForeignKey(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, foreignKeyName string) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, TableID: tblInfo.ID, @@ -91,10 +79,11 @@ func testDropForeignKey(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBIn BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{model.NewCIStr(foreignKeyName)}, } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } @@ -111,35 +100,40 @@ func getForeignKey(t table.Table, name string) *model.FKInfo { return nil } -func (s *testForeignKeySuite) TestForeignKey(c *C) { +func TestForeignKey(t *testing.T) { + store := createMockStore(t) + defer func() { + err := store.Close() + require.NoError(t, err) + }() + d, err := testNewDDLAndStart( context.Background(), - WithStore(s.store), + WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() - s.d = d - s.dbInfo, err = testSchemaInfo(d, "test_foreign") - c.Assert(err, IsNil) + + dbInfo, err := testSchemaInfo(d, "test_foreign") + require.NoError(t, err) ctx := testNewContext(d) - s.ctx = ctx - testCreateSchema(c, ctx, d, s.dbInfo) + testCreateSchema(t, ctx, d, dbInfo) tblInfo, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) + require.NoError(t, err) err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) + testCreateTable(t, ctx, d, dbInfo, tblInfo) txn, err := ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) // fix data race var mu sync.Mutex @@ -153,7 +147,7 @@ func (s *testForeignKeySuite) TestForeignKey(c *C) { mu.Lock() defer mu.Unlock() var t table.Table - t, err = testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) + t, err = testGetTableWithError(d, dbInfo.ID, tblInfo.ID) if err != nil { hookErr = errors.Trace(err) return @@ -169,20 +163,20 @@ func (s *testForeignKeySuite) TestForeignKey(c *C) { defer d.SetHook(originalHook) d.SetHook(tc) - job := s.testCreateForeignKey(c, tblInfo, "c1_fk", []string{"c1"}, "t2", []string{"c1"}, ast.ReferOptionCascade, ast.ReferOptionSetNull) - testCheckJobDone(c, d, job, true) + job := testCreateForeignKey(t, d, ctx, dbInfo, tblInfo, "c1_fk", []string{"c1"}, "t2", []string{"c1"}, ast.ReferOptionCascade, ast.ReferOptionSetNull) + testCheckJobDone(t, d, job, true) txn, err = ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) mu.Lock() hErr := hookErr ok := checkOK mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + require.NoError(t, hErr) + require.True(t, ok) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) mu.Lock() checkOK = false @@ -196,7 +190,7 @@ func (s *testForeignKeySuite) TestForeignKey(c *C) { mu.Lock() defer mu.Unlock() var t table.Table - t, err = testGetTableWithError(d, s.dbInfo.ID, tblInfo.ID) + t, err = testGetTableWithError(d, dbInfo.ID, tblInfo.ID) if err != nil { hookErr = errors.Trace(err) return @@ -210,23 +204,39 @@ func (s *testForeignKeySuite) TestForeignKey(c *C) { } d.SetHook(tc2) - job = testDropForeignKey(c, ctx, d, s.dbInfo, tblInfo, "c1_fk") - testCheckJobDone(c, d, job, false) + job = testDropForeignKey(t, ctx, d, dbInfo, tblInfo, "c1_fk") + testCheckJobDone(t, d, job, false) mu.Lock() hErr = hookErr ok = checkOK mu.Unlock() - c.Assert(hErr, IsNil) - c.Assert(ok, IsTrue) + require.NoError(t, hErr) + require.True(t, ok) err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) - job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) - testCheckJobDone(c, d, job, false) + job = testDropTable(t, ctx, d, dbInfo, tblInfo) + testCheckJobDone(t, d, job, false) txn, err = ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) +} + +func testCheckJobDone(t *testing.T, d *ddl, job *model.Job, isAdd bool) { + require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + historyJob, err := m.GetHistoryDDLJob(job.ID) + require.NoError(t, err) + checkHistoryJob(t, historyJob) + if isAdd { + require.Equal(t, historyJob.SchemaState, model.StatePublic) + } else { + require.Equal(t, historyJob.SchemaState, model.StateNone) + } + + return nil + })) } diff --git a/ddl/generated_column.go b/ddl/generated_column.go index 232828a0c107e..4bcf7ca5e5913 100644 --- a/ddl/generated_column.go +++ b/ddl/generated_column.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/util/dbterror" ) // columnGenerationInDDL is a struct for validating generated columns in DDL. @@ -44,11 +45,11 @@ func verifyColumnGeneration(colName2Generation map[string]columnGenerationInDDL, if attr.generated && attribute.position <= attr.position { // A generated column definition can refer to other // generated columns occurring earlier in the table. - err := errGeneratedColumnNonPrior.GenWithStackByArgs() + err := dbterror.ErrGeneratedColumnNonPrior.GenWithStackByArgs() return errors.Trace(err) } } else { - err := ErrBadField.GenWithStackByArgs(depCol, "generated column function") + err := dbterror.ErrBadField.GenWithStackByArgs(depCol, "generated column function") return errors.Trace(err) } } @@ -68,7 +69,7 @@ func verifyColumnGenerationSingle(dependColNames map[string]struct{}, cols []*ta if _, ok := dependColNames[col.Name.L]; ok { if col.IsGenerated() && col.Offset >= pos { // Generated column can refer only to generated columns defined prior to it. - return errGeneratedColumnNonPrior.GenWithStackByArgs() + return dbterror.ErrGeneratedColumnNonPrior.GenWithStackByArgs() } } } @@ -85,7 +86,7 @@ func checkDependedColExist(dependCols map[string]struct{}, cols []*table.Column) } if len(dependCols) != 0 { for arbitraryCol := range dependCols { - return ErrBadField.GenWithStackByArgs(arbitraryCol, "generated column function") + return dbterror.ErrBadField.GenWithStackByArgs(arbitraryCol, "generated column function") } } return nil @@ -111,7 +112,7 @@ func findPositionRelativeColumn(cols []*table.Column, pos *ast.ColumnPosition) ( } } if col == nil { - return -1, ErrBadField.GenWithStackByArgs(pos.RelativeColumn, "generated column function") + return -1, dbterror.ErrBadField.GenWithStackByArgs(pos.RelativeColumn, "generated column function") } // Inserted position is after the mentioned column. position = col.Offset + 1 @@ -159,11 +160,11 @@ func isGeneratedRelatedColumn(tblInfo *model.TableInfo, newCol, col *model.Colum if newCol.IsGenerated() || col.IsGenerated() { // TODO: Make it compatible with MySQL error. msg := fmt.Sprintf("newCol IsGenerated %v, oldCol IsGenerated %v", newCol.IsGenerated(), col.IsGenerated()) - return errUnsupportedModifyColumn.GenWithStackByArgs(msg) + return dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) } if ok, dep, _ := hasDependentByGeneratedColumn(tblInfo, col.Name); ok { msg := fmt.Sprintf("oldCol is a dependent column '%s' for generated column", dep) - return errUnsupportedModifyColumn.GenWithStackByArgs(msg) + return dbterror.ErrUnsupportedModifyColumn.GenWithStackByArgs(msg) } return nil } @@ -196,7 +197,7 @@ func checkModifyGeneratedColumn(sctx sessionctx.Context, tbl table.Table, oldCol oldColIsStored := !oldCol.IsGenerated() || oldCol.GeneratedStored newColIsStored := !newCol.IsGenerated() || newCol.GeneratedStored if oldColIsStored != newColIsStored { - return ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Changing the STORED status") + return dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Changing the STORED status") } // rule 2. @@ -329,30 +330,30 @@ func checkIllegalFn4Generated(name string, genType int, expr ast.ExprNode) error if c.hasIllegalFunc { switch genType { case typeColumn: - return ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs(name) + return dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs(name) case typeIndex: - return ErrFunctionalIndexFunctionIsNotAllowed.GenWithStackByArgs(name) + return dbterror.ErrFunctionalIndexFunctionIsNotAllowed.GenWithStackByArgs(name) } } if c.hasAggFunc { - return ErrInvalidGroupFuncUse + return dbterror.ErrInvalidGroupFuncUse } if c.hasRowVal { switch genType { case typeColumn: - return ErrGeneratedColumnRowValueIsNotAllowed.GenWithStackByArgs(name) + return dbterror.ErrGeneratedColumnRowValueIsNotAllowed.GenWithStackByArgs(name) case typeIndex: - return ErrFunctionalIndexRowValueIsNotAllowed.GenWithStackByArgs(name) + return dbterror.ErrFunctionalIndexRowValueIsNotAllowed.GenWithStackByArgs(name) } } if c.hasWindowFunc { - return errWindowInvalidWindowFuncUse.GenWithStackByArgs(name) + return dbterror.ErrWindowInvalidWindowFuncUse.GenWithStackByArgs(name) } if c.otherErr != nil { return c.otherErr } if genType == typeIndex && c.hasNotGAFunc4ExprIdx && !config.GetGlobalConfig().Experimental.AllowsExpressionIndex { - return ErrUnsupportedExpressionIndex + return dbterror.ErrUnsupportedExpressionIndex } return nil } @@ -363,13 +364,13 @@ func checkIndexOrStored(tbl table.Table, oldCol, newCol *table.Column) error { } if newCol.GeneratedStored { - return ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("modifying a stored column") + return dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("modifying a stored column") } for _, idx := range tbl.Indices() { for _, col := range idx.Meta().Columns { if col.Name.L == newCol.Name.L { - return ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("modifying an indexed column") + return dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("modifying an indexed column") } } } @@ -382,7 +383,7 @@ func checkAutoIncrementRef(name string, dependencies map[string]struct{}, tbInfo exists, autoIncrementColumn := infoschema.HasAutoIncrementColumn(tbInfo) if exists { if _, found := dependencies[autoIncrementColumn]; found { - return ErrGeneratedColumnRefAutoInc.GenWithStackByArgs(name) + return dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs(name) } } return nil @@ -393,7 +394,7 @@ func checkExpressionIndexAutoIncrement(name string, dependencies map[string]stru exists, autoIncrementColumn := infoschema.HasAutoIncrementColumn(tbInfo) if exists { if _, found := dependencies[autoIncrementColumn]; found { - return ErrExpressionIndexCanNotRefer.GenWithStackByArgs(name) + return dbterror.ErrExpressionIndexCanNotRefer.GenWithStackByArgs(name) } } return nil diff --git a/ddl/index.go b/ddl/index.go index b817d13ee38c1..805ca0198b8c2 100644 --- a/ddl/index.go +++ b/ddl/index.go @@ -16,6 +16,7 @@ package ddl import ( "context" + "sort" "strings" "sync/atomic" "time" @@ -39,9 +40,9 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" decoder "github.com/pingcap/tidb/util/rowDecoder" - "github.com/pingcap/tidb/util/timeutil" "github.com/prometheus/client_golang/prometheus" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/tikv" @@ -63,7 +64,7 @@ func buildIndexColumns(columns []*model.ColumnInfo, indexPartSpecifications []*a for _, ip := range indexPartSpecifications { col = model.FindColumnInfo(columns, ip.Column.Name.L) if col == nil { - return nil, errKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", ip.Column.Name) + return nil, dbterror.ErrKeyColumnDoesNotExits.GenWithStack("column does not exist: %s", ip.Column.Name) } if err := checkIndexColumn(col, ip.Length); err != nil { @@ -78,7 +79,7 @@ func buildIndexColumns(columns []*model.ColumnInfo, indexPartSpecifications []*a // The sum of all lengths must be shorter than the max length for prefix. if sumLength > config.GetGlobalConfig().MaxIndexLength { - return nil, errTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) + return nil, dbterror.ErrTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) } idxParts = append(idxParts, &model.IndexColumn{ @@ -96,14 +97,14 @@ func checkPKOnGeneratedColumn(tblInfo *model.TableInfo, indexPartSpecifications for _, colName := range indexPartSpecifications { lastCol = getColumnInfoByName(tblInfo, colName.Column.Name.L) if lastCol == nil { - return nil, errKeyColumnDoesNotExits.GenWithStackByArgs(colName.Column.Name) + return nil, dbterror.ErrKeyColumnDoesNotExits.GenWithStackByArgs(colName.Column.Name) } // Virtual columns cannot be used in primary key. if lastCol.IsGenerated() && !lastCol.GeneratedStored { if lastCol.Hidden { - return nil, ErrFunctionalIndexPrimaryKey + return nil, dbterror.ErrFunctionalIndexPrimaryKey } - return nil, ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Defining a virtual generated column as primary key") + return nil, dbterror.ErrUnsupportedOnGeneratedColumn.GenWithStackByArgs("Defining a virtual generated column as primary key") } } @@ -116,7 +117,7 @@ func checkIndexPrefixLength(columns []*model.ColumnInfo, idxColumns []*model.Ind return err } if idxLen > config.GetGlobalConfig().MaxIndexLength { - return errTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) + return dbterror.ErrTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) } return nil } @@ -124,46 +125,46 @@ func checkIndexPrefixLength(columns []*model.ColumnInfo, idxColumns []*model.Ind func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { if col.Flen == 0 && (types.IsTypeChar(col.FieldType.Tp) || types.IsTypeVarchar(col.FieldType.Tp)) { if col.Hidden { - return errors.Trace(errWrongKeyColumnFunctionalIndex.GenWithStackByArgs(col.GeneratedExprString)) + return errors.Trace(dbterror.ErrWrongKeyColumnFunctionalIndex.GenWithStackByArgs(col.GeneratedExprString)) } - return errors.Trace(errWrongKeyColumn.GenWithStackByArgs(col.Name)) + return errors.Trace(dbterror.ErrWrongKeyColumn.GenWithStackByArgs(col.Name)) } // JSON column cannot index. if col.FieldType.Tp == mysql.TypeJSON { if col.Hidden { - return errFunctionalIndexOnJSONOrGeometryFunction + return dbterror.ErrFunctionalIndexOnJSONOrGeometryFunction } - return errors.Trace(errJSONUsedAsKey.GenWithStackByArgs(col.Name.O)) + return errors.Trace(dbterror.ErrJSONUsedAsKey.GenWithStackByArgs(col.Name.O)) } // Length must be specified and non-zero for BLOB and TEXT column indexes. if types.IsTypeBlob(col.FieldType.Tp) { if indexColumnLen == types.UnspecifiedLength { if col.Hidden { - return errFunctionalIndexOnBlob + return dbterror.ErrFunctionalIndexOnBlob } - return errors.Trace(errBlobKeyWithoutLength.GenWithStackByArgs(col.Name.O)) + return errors.Trace(dbterror.ErrBlobKeyWithoutLength.GenWithStackByArgs(col.Name.O)) } if indexColumnLen == types.ErrorLength { - return errors.Trace(errKeyPart0.GenWithStackByArgs(col.Name.O)) + return errors.Trace(dbterror.ErrKeyPart0.GenWithStackByArgs(col.Name.O)) } } // Length can only be specified for specifiable types. if indexColumnLen != types.UnspecifiedLength && !types.IsTypePrefixable(col.FieldType.Tp) { - return errors.Trace(errIncorrectPrefixKey) + return errors.Trace(dbterror.ErrIncorrectPrefixKey) } // Key length must be shorter or equal to the column length. if indexColumnLen != types.UnspecifiedLength && types.IsTypeChar(col.FieldType.Tp) { if col.Flen < indexColumnLen { - return errors.Trace(errIncorrectPrefixKey) + return errors.Trace(dbterror.ErrIncorrectPrefixKey) } // Length must be non-zero for char. if indexColumnLen == types.ErrorLength { - return errors.Trace(errKeyPart0.GenWithStackByArgs(col.Name.O)) + return errors.Trace(dbterror.ErrKeyPart0.GenWithStackByArgs(col.Name.O)) } } @@ -176,7 +177,7 @@ func checkIndexColumn(col *model.ColumnInfo, indexColumnLen int) error { } // Specified length must be shorter than the max length for prefix. if indexColumnLen > config.GetGlobalConfig().MaxIndexLength { - return errTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) + return dbterror.ErrTooLongKey.GenWithStackByArgs(config.GetGlobalConfig().MaxIndexLength) } return nil } @@ -197,7 +198,7 @@ func getIndexColumnLength(col *model.ColumnInfo, colLen int) (int, error) { // Different charsets occupy different numbers of bytes on each character. desc, err := charset.GetCharsetInfo(col.Charset) if err != nil { - return 0, errUnsupportedCharset.GenWithStackByArgs(col.Charset, col.Collate) + return 0, dbterror.ErrUnsupportedCharset.GenWithStackByArgs(col.Charset, col.Collate) } return desc.Maxlen * length, nil case mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeShort: @@ -305,10 +306,16 @@ func onRenameIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } if tblInfo.TableCacheStatusType != model.TableCacheStatusDisable { - return ver, errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Rename Index")) + return ver, errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Rename Index")) } idx := tblInfo.FindIndexByName(from.L) + if job.MultiSchemaInfo != nil && job.MultiSchemaInfo.Revertible { + job.MarkNonRevertible() + // Store the mark and enter the next DDL handling loop. + return updateVersionAndTableInfoWithCheck(t, job, tblInfo, false) + } + idx.Name = to if ver, err = updateVersionAndTableInfo(t, job, tblInfo, true); err != nil { job.State = model.JobStateCancelled @@ -401,12 +408,12 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo // Handle normal job. schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } if tblInfo.TableCacheStatusType != model.TableCacheStatusDisable { - return ver, errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Create Index")) + return ver, errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Create Index")) } var ( @@ -433,7 +440,7 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo indexInfo := tblInfo.FindIndexByName(indexName.L) if indexInfo != nil && indexInfo.State == model.StatePublic { job.State = model.JobStateCancelled - err = ErrDupKeyName.GenWithStack("index already exist %s", indexName) + err = dbterror.ErrDupKeyName.GenWithStack("index already exist %s", indexName) if isPK { err = infoschema.ErrMultiplePriKey } @@ -454,13 +461,8 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo if indexInfo == nil { if len(hiddenCols) > 0 { - pos := &ast.ColumnPosition{Tp: ast.ColumnPositionNone} for _, hiddenCol := range hiddenCols { - _, _, _, err = createColumnInfo(tblInfo, hiddenCol, pos) - if err != nil { - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } + createColumnInfo(tblInfo, hiddenCol) } } if err = checkAddColumnTooManyColumns(len(tblInfo.Columns)); err != nil { @@ -557,41 +559,12 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo return ver, errors.Trace(err) } - elements := []*meta.Element{{ID: indexInfo.ID, TypeKey: meta.IndexElementKey}} - reorgInfo, err := getReorgInfo(d, t, job, tbl, elements) - if err != nil || reorgInfo.first { - // If we run reorg firstly, we should update the job snapshot version - // and then run the reorg next time. - return ver, errors.Trace(err) - } - - err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (addIndexErr error) { - defer util.Recover(metrics.LabelDDL, "onCreateIndex", - func() { - addIndexErr = errCancelledDDLJob.GenWithStack("add table `%v` index `%v` panic", tblInfo.Name, indexInfo.Name) - }, false) - return w.addTableIndex(tbl, indexInfo, reorgInfo) - }) - if err != nil { - if errWaitReorgTimeout.Equal(err) { - // if timeout, we should return, check for the owner and re-wait job done. - return ver, nil - } - if kv.ErrKeyExists.Equal(err) || errCancelledDDLJob.Equal(err) || errCantDecodeRecord.Equal(err) { - logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err)) - ver, err = convertAddIdxJob2RollbackJob(t, job, tblInfo, indexInfo, err) - if err1 := t.RemoveDDLReorgHandle(job, reorgInfo.elements); err1 != nil { - logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback, RemoveDDLReorgHandle failed", zap.String("job", job.String()), zap.Error(err1)) - } - } - // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. - w.reorgCtx.cleanNotifyReorgCancel() - return ver, errors.Trace(err) + var done bool + done, ver, err = doReorgWorkForCreateIndexMultiSchema(w, d, t, job, tbl, indexInfo) + if !done { + return ver, err } - // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. - w.reorgCtx.cleanNotifyReorgCancel() - indexInfo.State = model.StatePublic // Set column index flag. addIndexColumnFlag(tblInfo, indexInfo) if isPK { @@ -599,6 +572,8 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo return ver, errors.Trace(err) } } + + indexInfo.State = model.StatePublic ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) if err != nil { return ver, errors.Trace(err) @@ -606,26 +581,91 @@ func (w *worker) onCreateIndex(d *ddlCtx, t *meta.Meta, job *model.Job, isPK boo // Finish this job. job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) default: - err = ErrInvalidDDLState.GenWithStackByArgs("index", tblInfo.State) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", tblInfo.State) } return ver, errors.Trace(err) } +func doReorgWorkForCreateIndexMultiSchema(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, + tbl table.Table, indexInfo *model.IndexInfo) (done bool, ver int64, err error) { + if job.MultiSchemaInfo != nil { + if job.IsCancelling() { + logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback", + zap.String("job", job.String()), zap.Error(err)) + w.reorgCtx.cleanNotifyReorgCancel() + ver, err = convertAddIdxJob2RollbackJob(t, job, tbl.Meta(), indexInfo, dbterror.ErrCancelledDDLJob) + return false, ver, err + } + if job.MultiSchemaInfo.Revertible { + done, ver, err = doReorgWorkForCreateIndex(w, d, t, job, tbl, indexInfo) + if done { + job.MarkNonRevertible() + done = false + } + return done, ver, err + } + return true, ver, err + } + return doReorgWorkForCreateIndex(w, d, t, job, tbl, indexInfo) +} + +func doReorgWorkForCreateIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, + tbl table.Table, indexInfo *model.IndexInfo) (done bool, ver int64, err error) { + elements := []*meta.Element{{ID: indexInfo.ID, TypeKey: meta.IndexElementKey}} + reorgInfo, err := getReorgInfo(w.JobContext, d, t, job, tbl, elements) + if err != nil || reorgInfo.first { + // If we run reorg firstly, we should update the job snapshot version + // and then run the reorg next time. + return false, ver, errors.Trace(err) + } + + err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (addIndexErr error) { + defer util.Recover(metrics.LabelDDL, "onCreateIndex", + func() { + addIndexErr = dbterror.ErrCancelledDDLJob.GenWithStack("add table `%v` index `%v` panic", tbl.Meta().Name, indexInfo.Name) + }, false) + return w.addTableIndex(tbl, indexInfo, reorgInfo) + }) + if err != nil { + if dbterror.ErrWaitReorgTimeout.Equal(err) { + // if timeout, we should return, check for the owner and re-wait job done. + return false, ver, nil + } + if kv.ErrKeyExists.Equal(err) || dbterror.ErrCancelledDDLJob.Equal(err) || dbterror.ErrCantDecodeRecord.Equal(err) { + logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err)) + ver, err = convertAddIdxJob2RollbackJob(t, job, tbl.Meta(), indexInfo, err) + if err1 := t.RemoveDDLReorgHandle(job, reorgInfo.elements); err1 != nil { + logutil.BgLogger().Warn("[ddl] run add index job failed, convert job to rollback, RemoveDDLReorgHandle failed", zap.String("job", job.String()), zap.Error(err1)) + } + } + // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. + w.reorgCtx.cleanNotifyReorgCancel() + return false, ver, errors.Trace(err) + } + // Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs. + w.reorgCtx.cleanNotifyReorgCancel() + return true, ver, errors.Trace(err) +} + func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { - tblInfo, indexInfo, err := checkDropIndex(t, job) + tblInfo, indexInfo, ifExists, err := checkDropIndex(t, job) if err != nil { + if ifExists && dbterror.ErrCantDropFieldOrKey.Equal(err) { + job.Warning = toTError(err) + job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) + return ver, nil + } return ver, errors.Trace(err) } if tblInfo.TableCacheStatusType != model.TableCacheStatusDisable { - return ver, errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Drop Index")) + return ver, errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("Drop Index")) } - dependentHiddenCols := make([]*model.ColumnInfo, 0) - for _, indexColumn := range indexInfo.Columns { - if tblInfo.Columns[indexColumn.Offset].Hidden { - dependentHiddenCols = append(dependentHiddenCols, tblInfo.Columns[indexColumn.Offset]) - } + if job.MultiSchemaInfo != nil && job.MultiSchemaInfo.Revertible { + job.MarkNonRevertible() + job.SchemaState = indexInfo.State + return updateVersionAndTableInfo(t, job, tblInfo, false) } originalState := indexInfo.State @@ -656,25 +696,11 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.SchemaState = model.StateDeleteReorganization case model.StateDeleteReorganization: // reorganization -> absent - if len(dependentHiddenCols) > 0 { - firstHiddenOffset := dependentHiddenCols[0].Offset - for i := 0; i < len(dependentHiddenCols); i++ { - // Set this column's offset to the last and reset all following columns' offsets. - adjustColumnInfoInDropColumn(tblInfo, firstHiddenOffset) - } - } - - newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) - for _, idx := range tblInfo.Indices { - if idx.Name.L != indexInfo.Name.L { - newIndices = append(newIndices, idx) - } - } - tblInfo.Indices = newIndices // Set column index flag. dropIndexColumnFlag(tblInfo, indexInfo) + removeDependentHiddenColumns(tblInfo, indexInfo) + removeIndexInfo(tblInfo, indexInfo) - tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-len(dependentHiddenCols)] failpoint.Inject("mockExceedErrorLimit", func(val failpoint.Value) { if val.(bool) { panic("panic test in cancelling add index") @@ -697,202 +723,83 @@ func onDropIndex(t *meta.Meta, job *model.Job) (ver int64, _ error) { job.Args = append(job.Args, indexInfo.ID, getPartitionIDs(tblInfo)) } default: - err = ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) } return ver, errors.Trace(err) } -func checkDropIndex(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.IndexInfo, error) { +func removeDependentHiddenColumns(tblInfo *model.TableInfo, idxInfo *model.IndexInfo) { + hiddenColOffs := make([]int, 0) + for _, indexColumn := range idxInfo.Columns { + col := tblInfo.Columns[indexColumn.Offset] + if col.Hidden { + hiddenColOffs = append(hiddenColOffs, col.Offset) + } + } + // Sort the offset in descending order. + sort.Slice(hiddenColOffs, func(i, j int) bool { + return hiddenColOffs[i] > hiddenColOffs[j] + }) + // Move all the dependent hidden columns to the end. + endOffset := len(tblInfo.Columns) - 1 + for _, offset := range hiddenColOffs { + tblInfo.MoveColumnInfo(offset, endOffset) + } + tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-len(hiddenColOffs)] +} + +func removeIndexInfo(tblInfo *model.TableInfo, idxInfo *model.IndexInfo) { + indices := tblInfo.Indices + offset := -1 + for i, idx := range indices { + if idxInfo.ID == idx.ID { + offset = i + break + } + } + if offset == -1 { + // The target index has been removed. + return + } + // Swap the target index to the end and remove it. + indices[offset], indices[len(indices)-1] = indices[len(indices)-1], indices[offset] + tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-1] +} + +func checkDropIndex(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.IndexInfo, bool /* ifExists */, error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { - return nil, nil, errors.Trace(err) + return nil, nil, false, errors.Trace(err) } var indexName model.CIStr - if err = job.DecodeArgs(&indexName); err != nil { + var ifExists bool + if err = job.DecodeArgs(&indexName, &ifExists); err != nil { job.State = model.JobStateCancelled - return nil, nil, errors.Trace(err) + return nil, nil, false, errors.Trace(err) } indexInfo := tblInfo.FindIndexByName(indexName.L) if indexInfo == nil { job.State = model.JobStateCancelled - return nil, nil, ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) + return nil, nil, ifExists, dbterror.ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) } // Double check for drop index on auto_increment column. err = checkDropIndexOnAutoIncrementColumn(tblInfo, indexInfo) if err != nil { job.State = model.JobStateCancelled - return nil, nil, autoid.ErrWrongAutoKey + return nil, nil, false, autoid.ErrWrongAutoKey } // Check that drop primary index will not cause invisible implicit primary index. if err := checkInvisibleIndexesOnPK(tblInfo, []*model.IndexInfo{indexInfo}, job); err != nil { - return nil, nil, errors.Trace(err) - } - - return tblInfo, indexInfo, nil -} - -func onDropIndexes(t *meta.Meta, job *model.Job) (ver int64, _ error) { - tblInfo, indexNames, ifExists, err := getSchemaInfos(t, job) - if err != nil { - return ver, errors.Trace(err) - } - if tblInfo.TableCacheStatusType != model.TableCacheStatusDisable { - return ver, errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("Drop Indexes")) - } - - indexInfos, err := checkDropIndexes(tblInfo, job, indexNames, ifExists) - if err != nil { - return ver, errors.Trace(err) - } - - if len(indexInfos) == 0 { job.State = model.JobStateCancelled - return ver, nil - } - - dependentHiddenCols := make([]*model.ColumnInfo, 0) - for _, indexInfo := range indexInfos { - for _, indexColumn := range indexInfo.Columns { - if tblInfo.Columns[indexColumn.Offset].Hidden { - dependentHiddenCols = append(dependentHiddenCols, tblInfo.Columns[indexColumn.Offset]) - } - } + return nil, nil, false, errors.Trace(err) } - originalState := indexInfos[0].State - switch indexInfos[0].State { - case model.StatePublic: - // public -> write only - setIndicesState(indexInfos, model.StateWriteOnly) - setColumnsState(dependentHiddenCols, model.StateWriteOnly) - for _, colInfo := range dependentHiddenCols { - adjustColumnInfoInDropColumn(tblInfo, colInfo.Offset) - } - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateWriteOnly - case model.StateWriteOnly: - // write only -> delete only - setIndicesState(indexInfos, model.StateDeleteOnly) - setColumnsState(dependentHiddenCols, model.StateDeleteOnly) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateDeleteOnly - case model.StateDeleteOnly: - // delete only -> reorganization - setIndicesState(indexInfos, model.StateDeleteReorganization) - setColumnsState(dependentHiddenCols, model.StateDeleteReorganization) - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.SchemaState = model.StateDeleteReorganization - case model.StateDeleteReorganization: - // reorganization -> absent - indexIDs := make([]int64, 0, len(indexInfos)) - indexNames := make(map[string]bool, len(indexInfos)) - for _, indexInfo := range indexInfos { - indexNames[indexInfo.Name.L] = true - indexIDs = append(indexIDs, indexInfo.ID) - } - - newIndices := make([]*model.IndexInfo, 0, len(tblInfo.Indices)) - for _, idx := range tblInfo.Indices { - if _, ok := indexNames[idx.Name.L]; !ok { - newIndices = append(newIndices, idx) - } - } - tblInfo.Indices = newIndices - - // Set column index flag. - for _, indexInfo := range indexInfos { - dropIndexColumnFlag(tblInfo, indexInfo) - } - - tblInfo.Columns = tblInfo.Columns[:len(tblInfo.Columns)-len(dependentHiddenCols)] - - ver, err = updateVersionAndTableInfoWithCheck(t, job, tblInfo, originalState != model.StateNone) - if err != nil { - return ver, errors.Trace(err) - } - - job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo) - job.Args = append(job.Args, indexIDs, getPartitionIDs(tblInfo)) - default: - err = ErrInvalidDDLState.GenWithStackByArgs("index", indexInfos[0].State) - } - - return ver, errors.Trace(err) -} - -func getSchemaInfos(t *meta.Meta, job *model.Job) (*model.TableInfo, []model.CIStr, []bool, error) { - schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) - if err != nil { - return nil, nil, nil, errors.Trace(err) - } - - var indexNames []model.CIStr - var ifExists []bool - if err = job.DecodeArgs(&indexNames, &ifExists); err != nil { - return nil, nil, nil, errors.Trace(err) - } - - return tblInfo, indexNames, ifExists, nil -} - -func checkDropIndexes(tblInfo *model.TableInfo, job *model.Job, indexNames []model.CIStr, ifExists []bool) ([]*model.IndexInfo, error) { - var warnings []*errors.Error - indexInfos := make([]*model.IndexInfo, 0, len(indexNames)) - UniqueIndexNames := make(map[model.CIStr]bool, len(indexNames)) - for i, indexName := range indexNames { - // Double check the index is exists. - indexInfo := tblInfo.FindIndexByName(indexName.L) - if indexInfo == nil { - if ifExists[i] { - warnings = append(warnings, toTError(ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName))) - continue - } - job.State = model.JobStateCancelled - return nil, ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) - } - - // Double check for drop index on auto_increment column. - if err := checkDropIndexOnAutoIncrementColumn(tblInfo, indexInfo); err != nil { - job.State = model.JobStateCancelled - return nil, autoid.ErrWrongAutoKey - } - - // Check for dropping duplicate indexes. - if UniqueIndexNames[indexName] { - if !ifExists[i] { - job.State = model.JobStateCancelled - return nil, ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName) - } - warnings = append(warnings, toTError(ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName))) - } - UniqueIndexNames[indexName] = true - - indexInfos = append(indexInfos, indexInfo) - } - - // Check that drop primary index will not cause invisible implicit primary index. - if err := checkInvisibleIndexesOnPK(tblInfo, indexInfos, job); err != nil { - return nil, errors.Trace(err) - } - - job.MultiSchemaInfo = &model.MultiSchemaInfo{Warnings: warnings} - - return indexInfos, nil + return tblInfo, indexInfo, false, nil } func checkInvisibleIndexesOnPK(tblInfo *model.TableInfo, indexInfos []*model.IndexInfo, job *model.Job) error { @@ -949,7 +856,7 @@ func checkDropIndexOnAutoIncrementColumn(tblInfo *model.TableInfo, indexInfo *mo func checkRenameIndex(t *meta.Meta, job *model.Job) (*model.TableInfo, model.CIStr, model.CIStr, error) { var from, to model.CIStr schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return nil, from, to, errors.Trace(err) } @@ -978,7 +885,7 @@ func checkAlterIndexVisibility(t *meta.Meta, job *model.Job) (*model.TableInfo, ) schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return nil, indexName, invisible, errors.Trace(err) } @@ -1043,7 +950,7 @@ func newAddIndexWorker(sessCtx sessionctx.Context, worker *worker, id int, t tab rowDecoder: rowDecoder, defaultVals: make([]types.Datum, len(t.WritableCols())), rowMap: make(map[int64]types.Datum, len(decodeColMap)), - metricCounter: metrics.BackfillTotalCounter.WithLabelValues("add_idx_speed"), + metricCounter: metrics.BackfillTotalCounter.WithLabelValues("add_idx_rate"), sqlMode: sqlMode, }, index: index, @@ -1060,22 +967,21 @@ var mockNotOwnerErrOnce uint32 // getIndexRecord gets index columns values use w.rowDecoder, and generate indexRecord. func (w *baseIndexWorker) getIndexRecord(idxInfo *model.IndexInfo, handle kv.Handle, recordKey []byte) (*indexRecord, error) { cols := w.table.WritableCols() - sysZone := timeutil.SystemLocation() failpoint.Inject("MockGetIndexRecordErr", func(val failpoint.Value) { if valStr, ok := val.(string); ok { switch valStr { case "cantDecodeRecordErr": - failpoint.Return(nil, errors.Trace(errCantDecodeRecord.GenWithStackByArgs("index", + failpoint.Return(nil, errors.Trace(dbterror.ErrCantDecodeRecord.GenWithStackByArgs("index", errors.New("mock can't decode record error")))) case "modifyColumnNotOwnerErr": if idxInfo.Name.O == "_Idx$_idx" && handle.IntValue() == 7168 && atomic.CompareAndSwapUint32(&mockNotOwnerErrOnce, 0, 1) { - failpoint.Return(nil, errors.Trace(errNotOwner)) + failpoint.Return(nil, errors.Trace(dbterror.ErrNotOwner)) } case "addIdxNotOwnerErr": // For the case of the old TiDB version(do not exist the element information) is upgraded to the new TiDB version. // First step, we need to exit "addPhysicalTableIndex". if idxInfo.Name.O == "idx2" && handle.IntValue() == 6144 && atomic.CompareAndSwapUint32(&mockNotOwnerErrOnce, 1, 2) { - failpoint.Return(nil, errors.Trace(errNotOwner)) + failpoint.Return(nil, errors.Trace(dbterror.ErrNotOwner)) } } } @@ -1094,16 +1000,6 @@ func (w *baseIndexWorker) getIndexRecord(idxInfo *model.IndexInfo, handle kv.Han return nil, errors.Trace(err) } - if idxColumnVal.Kind() == types.KindMysqlTime { - t := idxColumnVal.GetMysqlTime() - if t.Type() == mysql.TypeTimestamp && sysZone != time.UTC { - err := t.ConvertTimeZone(sysZone, time.UTC) - if err != nil { - return nil, errors.Trace(err) - } - idxColumnVal.SetMysqlTime(t) - } - } idxVal[j] = idxColumnVal } @@ -1129,11 +1025,11 @@ func (w *baseIndexWorker) getNextKey(taskRange reorgBackfillTask, taskDone bool) return taskRange.endKey.Next() } -func (w *baseIndexWorker) updateRowDecoder(handle kv.Handle, recordKey []byte, rawRecord []byte) error { - sysZone := timeutil.SystemLocation() - _, err := w.rowDecoder.DecodeAndEvalRowWithMap(w.sessCtx, handle, rawRecord, time.UTC, sysZone, w.rowMap) +func (w *baseIndexWorker) updateRowDecoder(handle kv.Handle, rawRecord []byte) error { + sysZone := w.sessCtx.GetSessionVars().StmtCtx.TimeZone + _, err := w.rowDecoder.DecodeAndEvalRowWithMap(w.sessCtx, handle, rawRecord, sysZone, w.rowMap) if err != nil { - return errors.Trace(errCantDecodeRecord.GenWithStackByArgs("index", err)) + return errors.Trace(dbterror.ErrCantDecodeRecord.GenWithStackByArgs("index", err)) } return nil } @@ -1152,7 +1048,7 @@ func (w *baseIndexWorker) fetchRowColVals(txn kv.Transaction, taskRange reorgBac // taskDone means that the reorged handle is out of taskRange.endHandle. taskDone := false oprStartTime := startTime - err := iterateSnapshotRows(w.sessCtx.GetStore(), w.priority, w.table, txn.StartTS(), taskRange.startKey, taskRange.endKey, + err := iterateSnapshotRows(w.ddlWorker.JobContext, w.sessCtx.GetStore(), w.priority, w.table, txn.StartTS(), taskRange.startKey, taskRange.endKey, func(handle kv.Handle, recordKey kv.Key, rawRow []byte) (bool, error) { oprEndTime := time.Now() logSlowOperations(oprEndTime.Sub(oprStartTime), "iterateSnapshotRows in baseIndexWorker fetchRowColVals", 0) @@ -1165,7 +1061,7 @@ func (w *baseIndexWorker) fetchRowColVals(txn kv.Transaction, taskRange reorgBac } // Decode one row, generate records of this row. - err := w.updateRowDecoder(handle, recordKey, rawRow) + err := w.updateRowDecoder(handle, rawRow) if err != nil { return false, err } @@ -1308,6 +1204,9 @@ func (w *addIndexWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (taskC taskCtx.addedCount = 0 taskCtx.scanCount = 0 txn.SetOption(kv.Priority, w.priority) + if tagger := w.ddlWorker.getResourceGroupTaggerForTopSQL(); tagger != nil { + txn.SetOption(kv.ResourceGroupTagger, tagger) + } idxRecords, nextKey, taskDone, err := w.fetchRowColVals(txn, handleRange) if err != nil { @@ -1337,7 +1236,7 @@ func (w *addIndexWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (taskC } // Create the index. - handle, err := w.index.Create(w.sessCtx, txn, idxRecord.vals, idxRecord.handle, idxRecord.rsData) + handle, err := w.index.Create(w.sessCtx, txn, idxRecord.vals, idxRecord.handle, idxRecord.rsData, table.WithIgnoreAssertion) if err != nil { if kv.ErrKeyExists.Equal(err) && idxRecord.handle.Equal(handle) { // Index already exists, skip it. @@ -1369,7 +1268,7 @@ func (w *worker) addTableIndex(t table.Table, idx *model.IndexInfo, reorgInfo *r for !finish { p := tbl.GetPartition(reorgInfo.PhysicalTableID) if p == nil { - return errCancelledDDLJob.GenWithStack("Can not find partition id %d for table %d", reorgInfo.PhysicalTableID, t.Meta().ID) + return dbterror.ErrCancelledDDLJob.GenWithStack("Can not find partition id %d for table %d", reorgInfo.PhysicalTableID, t.Meta().ID) } err = w.addPhysicalTableIndex(p, idx, reorgInfo) if err != nil { @@ -1418,7 +1317,7 @@ func (w *worker) updateReorgInfo(t table.PartitionedTable, reorg *reorgInfo) (bo if err != nil { return false, errors.Trace(err) } - start, end, err := getTableRange(reorg.d, t.GetPartition(pid), currentVer.Ver, reorg.Job.Priority) + start, end, err := getTableRange(w.JobContext, reorg.d, t.GetPartition(pid), currentVer.Ver, reorg.Job.Priority) if err != nil { return false, errors.Trace(err) } @@ -1501,7 +1400,7 @@ func newCleanUpIndexWorker(sessCtx sessionctx.Context, worker *worker, id int, t rowDecoder: rowDecoder, defaultVals: make([]types.Datum, len(t.WritableCols())), rowMap: make(map[int64]types.Datum, len(decodeColMap)), - metricCounter: metrics.BackfillTotalCounter.WithLabelValues("clean_up_idx_speed"), + metricCounter: metrics.BackfillTotalCounter.WithLabelValues("cleanup_idx_rate"), sqlMode: sqlMode, }, } @@ -1519,6 +1418,9 @@ func (w *cleanUpIndexWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (t taskCtx.addedCount = 0 taskCtx.scanCount = 0 txn.SetOption(kv.Priority, w.priority) + if tagger := w.ddlWorker.getResourceGroupTaggerForTopSQL(); tagger != nil { + txn.SetOption(kv.ResourceGroupTagger, tagger) + } idxRecords, nextKey, taskDone, err := w.fetchRowColVals(txn, handleRange) if err != nil { @@ -1561,7 +1463,7 @@ func (w *worker) cleanupGlobalIndexes(tbl table.PartitionedTable, partitionIDs [ for !finish { p := tbl.GetPartition(reorgInfo.PhysicalTableID) if p == nil { - return errCancelledDDLJob.GenWithStack("Can not find partition id %d for table %d", reorgInfo.PhysicalTableID, tbl.Meta().ID) + return dbterror.ErrCancelledDDLJob.GenWithStack("Can not find partition id %d for table %d", reorgInfo.PhysicalTableID, tbl.Meta().ID) } err = w.cleanupPhysicalTableIndex(p, reorgInfo) if err != nil { @@ -1599,7 +1501,7 @@ func (w *worker) updateReorgInfoForPartitions(t table.PartitionedTable, reorg *r if err != nil { return false, errors.Trace(err) } - start, end, err := getTableRange(reorg.d, t.GetPartition(pid), currentVer.Ver, reorg.Job.Priority) + start, end, err := getTableRange(w.JobContext, reorg.d, t.GetPartition(pid), currentVer.Ver, reorg.Job.Priority) if err != nil { return false, errors.Trace(err) } @@ -1614,17 +1516,43 @@ func (w *worker) updateReorgInfoForPartitions(t table.PartitionedTable, reorg *r return false, errors.Trace(err) } -func findIndexesByColName(indexes []*model.IndexInfo, colName string) ([]*model.IndexInfo, []int) { - idxInfos := make([]*model.IndexInfo, 0, len(indexes)) - offsets := make([]int, 0, len(indexes)) - for _, idxInfo := range indexes { - for i, c := range idxInfo.Columns { - if strings.EqualFold(colName, c.Name.L) { - idxInfos = append(idxInfos, idxInfo) - offsets = append(offsets, i) +type indexesToChange struct { + indexInfo *model.IndexInfo + isModifying bool // whether the index is being modifying by another 'modify column' job + idxOffset int // index offset in tblInfo.Indices + colOffset int // column offset in idxInfo.Columns +} + +// findIndexesByColName finds the indexes that covering the given column, and deduplicate +// the indexes by original name. +func findIndexesByColName(tblInfo *model.TableInfo, colName model.CIStr) []indexesToChange { + var result []indexesToChange + for i, idxInfo := range tblInfo.Indices { + name, origName := idxInfo.Name.O, getChangingIndexOriginName(idxInfo) + isModifying := len(name) != len(origName) + for j, idxCol := range idxInfo.Columns { + if idxCol.Name.L != colName.L { + continue + } + r := indexesToChange{indexInfo: idxInfo, isModifying: isModifying, idxOffset: i, colOffset: j} + if !isModifying { + result = append(result, r) break } + // Deduplicate the index info by original name. + var dedup bool + for k, rs := range result { + if !rs.isModifying && origName == rs.indexInfo.Name.O { + result[k] = r + dedup = true + break + } + } + if !dedup { + result = append(result, r) + } + break } } - return idxInfos, offsets + return result } diff --git a/ddl/index_change_test.go b/ddl/index_change_test.go index f59a78cbd6b12..6baf9523d007a 100644 --- a/ddl/index_change_test.go +++ b/ddl/index_change_test.go @@ -12,136 +12,74 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ddl +package ddl_test import ( "context" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testIndexChangeSuite{}) - -type testIndexChangeSuite struct { - store kv.Storage - dbInfo *model.DBInfo -} - -func (s *testIndexChangeSuite) SetUpSuite(c *C) { - s.store = testCreateStore(c, "test_index_change") - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - s.dbInfo, err = testSchemaInfo(d, "test_index_change") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, s.dbInfo) -} - -func (s *testIndexChangeSuite) TearDownSuite(c *C) { - s.store.Close() -} - -func (s *testIndexChangeSuite) TestIndexChange(c *C) { - d, err := testNewDDLAndStart( - context.Background(), - WithStore(s.store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() - // create table t (c1 int primary key, c2 int); - tblInfo, err := testTableInfo(d, "t", 2) - c.Assert(err, IsNil) - tblInfo.Columns[0].Flag = mysql.PriKeyFlag | mysql.NotNullFlag - tblInfo.PKIsHandle = true - ctx := testNewContext(d) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d, s.dbInfo, tblInfo) - originTable := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) - - // insert t values (1, 1), (2, 2), (3, 3) - _, err = originTable.AddRecord(ctx, types.MakeDatums(1, 1)) - c.Assert(err, IsNil) - _, err = originTable.AddRecord(ctx, types.MakeDatums(2, 2)) - c.Assert(err, IsNil) - _, err = originTable.AddRecord(ctx, types.MakeDatums(3, 3)) - c.Assert(err, IsNil) - - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - tc := &TestDDLCallback{} +func TestIndexChange(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c1 int primary key, c2 int)") + tk.MustExec("insert t values (1, 1), (2, 2), (3, 3);") + + d := dom.DDL() + tc := &ddl.TestDDLCallback{Do: dom} // set up hook prevState := model.StateNone addIndexDone := false + var jobID int64 var ( deleteOnlyTable table.Table writeOnlyTable table.Table publicTable table.Table - checkErr error ) - tc.onJobUpdated = func(job *model.Job) { + tc.OnJobUpdatedExported = func(job *model.Job) { if job.SchemaState == prevState { return } - ctx1 := testNewContext(d) + jobID = job.ID + ctx1 := testNewContext(store) prevState = job.SchemaState + require.NoError(t, dom.Reload()) + tbl, exist := dom.InfoSchema().TableByID(job.TableID) + require.True(t, exist) switch job.SchemaState { case model.StateDeleteOnly: - deleteOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } + deleteOnlyTable = tbl case model.StateWriteOnly: - writeOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - err = s.checkAddWriteOnly(d, ctx1, deleteOnlyTable, writeOnlyTable) - if err != nil { - checkErr = errors.Trace(err) - } + writeOnlyTable = tbl + err := checkAddWriteOnlyForAddIndex(ctx1, deleteOnlyTable, writeOnlyTable) + require.NoError(t, err) case model.StatePublic: - if job.GetRowCount() != 3 { - checkErr = errors.Errorf("job's row count %d != 3", job.GetRowCount()) - } - publicTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - err = s.checkAddPublic(d, ctx1, writeOnlyTable, publicTable) - if err != nil { - checkErr = errors.Trace(err) - } + require.Equalf(t, int64(3), job.GetRowCount(), "job's row count %d != 3", job.GetRowCount()) + publicTable = tbl + err := checkAddPublicForAddIndex(ctx1, writeOnlyTable, publicTable) + require.NoError(t, err) if job.State == model.JobStateSynced { addIndexDone = true } } } d.SetHook(tc) - testCreateIndex(c, ctx, d, s.dbInfo, originTable.Meta(), false, "c2", "c2") + tk.MustExec("alter table t add index c2(c2)") // We need to make sure onJobUpdated is called in the first hook. // After testCreateIndex(), onJobUpdated() may not be called when job.state is Sync. // If we skip this check, prevState may wrongly set to StatePublic. @@ -151,50 +89,39 @@ func (s *testIndexChangeSuite) TestIndexChange(c *C) { } time.Sleep(50 * time.Millisecond) } - c.Check(checkErr, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - c.Assert(txn.Commit(context.Background()), IsNil) + v := getSchemaVer(t, tk.Session()) + checkHistoryJobArgs(t, tk.Session(), jobID, &historyJobArgs{ver: v, tbl: publicTable.Meta()}) + prevState = model.StateNone var noneTable table.Table - tc.onJobUpdated = func(job *model.Job) { + tc.OnJobUpdatedExported = func(job *model.Job) { + jobID = job.ID if job.SchemaState == prevState { return } prevState = job.SchemaState var err error - ctx1 := testNewContext(d) + require.NoError(t, dom.Reload()) + tbl, exist := dom.InfoSchema().TableByID(job.TableID) + require.True(t, exist) + ctx1 := testNewContext(store) switch job.SchemaState { case model.StateWriteOnly: - writeOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - err = s.checkDropWriteOnly(d, ctx1, publicTable, writeOnlyTable) - if err != nil { - checkErr = errors.Trace(err) - } + writeOnlyTable = tbl + err = checkDropWriteOnly(ctx1, publicTable, writeOnlyTable) + require.NoError(t, err) case model.StateDeleteOnly: - deleteOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - err = s.checkDropDeleteOnly(d, ctx1, writeOnlyTable, deleteOnlyTable) - if err != nil { - checkErr = errors.Trace(err) - } + deleteOnlyTable = tbl + err = checkDropDeleteOnly(ctx1, writeOnlyTable, deleteOnlyTable) + require.NoError(t, err) case model.StateNone: - noneTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID) - if err != nil { - checkErr = errors.Trace(err) - } - if len(noneTable.Indices()) != 0 { - checkErr = errors.New("index should have been dropped") - } + noneTable = tbl + require.Equalf(t, 0, len(noneTable.Indices()), "index should have been dropped") } } - testDropIndex(c, ctx, d, s.dbInfo, publicTable.Meta(), "c2") - c.Check(checkErr, IsNil) + tk.MustExec("alter table t drop index c2") + v = getSchemaVer(t, tk.Session()) + checkHistoryJobArgs(t, tk.Session(), jobID, &historyJobArgs{ver: v, tbl: noneTable.Meta()}) } func checkIndexExists(ctx sessionctx.Context, tbl table.Table, indexValue interface{}, handle int64, exists bool) error { @@ -216,7 +143,7 @@ func checkIndexExists(ctx sessionctx.Context, tbl table.Table, indexValue interf return nil } -func (s *testIndexChangeSuite) checkAddWriteOnly(d *ddl, ctx sessionctx.Context, delOnlyTbl, writeOnlyTbl table.Table) error { +func checkAddWriteOnlyForAddIndex(ctx sessionctx.Context, delOnlyTbl, writeOnlyTbl table.Table) error { // DeleteOnlyTable: insert t values (4, 4); err := ctx.NewTxn(context.Background()) if err != nil { @@ -289,7 +216,7 @@ func (s *testIndexChangeSuite) checkAddWriteOnly(d *ddl, ctx sessionctx.Context, return nil } -func (s *testIndexChangeSuite) checkAddPublic(d *ddl, ctx sessionctx.Context, writeTbl, publicTbl table.Table) error { +func checkAddPublicForAddIndex(ctx sessionctx.Context, writeTbl, publicTbl table.Table) error { // WriteOnlyTable: insert t values (6, 6) err := ctx.NewTxn(context.Background()) if err != nil { @@ -363,7 +290,7 @@ func (s *testIndexChangeSuite) checkAddPublic(d *ddl, ctx sessionctx.Context, wr return txn.Commit(context.Background()) } -func (s *testIndexChangeSuite) checkDropWriteOnly(d *ddl, ctx sessionctx.Context, publicTbl, writeTbl table.Table) error { +func checkDropWriteOnly(ctx sessionctx.Context, publicTbl, writeTbl table.Table) error { // WriteOnlyTable insert t values (8, 8) err := ctx.NewTxn(context.Background()) if err != nil { @@ -407,7 +334,7 @@ func (s *testIndexChangeSuite) checkDropWriteOnly(d *ddl, ctx sessionctx.Context return txn.Commit(context.Background()) } -func (s *testIndexChangeSuite) checkDropDeleteOnly(d *ddl, ctx sessionctx.Context, writeTbl, delTbl table.Table) error { +func checkDropDeleteOnly(ctx sessionctx.Context, writeTbl, delTbl table.Table) error { // WriteOnlyTable insert t values (9, 9) err := ctx.NewTxn(context.Background()) if err != nil { diff --git a/ddl/index_modify_test.go b/ddl/index_modify_test.go new file mode 100644 index 0000000000000..639c204287e3f --- /dev/null +++ b/ddl/index_modify_test.go @@ -0,0 +1,1372 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "math" + "math/rand" + "strconv" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" + testddlutil "github.com/pingcap/tidb/ddl/testutil" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/dbterror" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" +) + +const indexModifyLease = 600 * time.Millisecond + +func TestAddPrimaryKey1(t *testing.T) { + testAddIndex(t, testPlain, "create table test_add_index (c1 bigint, c2 bigint, c3 bigint, unique key(c1))", "primary") +} + +func TestAddPrimaryKey2(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) + partition by range (c3) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "primary") +} + +func TestAddPrimaryKey3(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) + partition by hash (c3) partitions 4;`, "primary") +} + +func TestAddPrimaryKey4(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, key(c1)) + partition by range columns (c3) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "primary") +} + +func TestAddIndex1(t *testing.T) { + testAddIndex(t, testPlain, + "create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1))", "") +} + +func TestAddIndex1WithShardRowID(t *testing.T) { + testAddIndex(t, testPartition|testShardRowID, + "create table test_add_index (c1 bigint, c2 bigint, c3 bigint) SHARD_ROW_ID_BITS = 4 pre_split_regions = 4;", "") +} + +func TestAddIndex2(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) + partition by range (c1) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "") +} + +func TestAddIndex2WithShardRowID(t *testing.T) { + testAddIndex(t, testPartition|testShardRowID, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) + SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 + partition by range (c1) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "") +} + +func TestAddIndex3(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) + partition by hash (c1) partitions 4;`, "") +} + +func TestAddIndex3WithShardRowID(t *testing.T) { + testAddIndex(t, testPartition|testShardRowID, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) + SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 + partition by hash (c1) partitions 4;`, "") +} + +func TestAddIndex4(t *testing.T) { + testAddIndex(t, testPartition, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) + partition by range columns (c1) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "") +} + +func TestAddIndex4WithShardRowID(t *testing.T) { + testAddIndex(t, testPartition|testShardRowID, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint) + SHARD_ROW_ID_BITS = 4 pre_split_regions = 4 + partition by range columns (c1) ( + partition p0 values less than (3440), + partition p1 values less than (61440), + partition p2 values less than (122880), + partition p3 values less than (204800), + partition p4 values less than maxvalue)`, "") +} + +func TestAddIndex5(t *testing.T) { + testAddIndex(t, testClusteredIndex, + `create table test_add_index (c1 bigint, c2 bigint, c3 bigint, primary key(c2, c3))`, "") +} + +type testAddIndexType uint8 + +const ( + testPlain testAddIndexType = 1 + testPartition testAddIndexType = 1 << 1 + testClusteredIndex testAddIndexType = 1 << 2 + testShardRowID testAddIndexType = 1 << 3 +) + +func testAddIndex(t *testing.T, tp testAddIndexType, createTableSQL, idxTp string) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + isTestPartition := (testPartition & tp) > 0 + isTestShardRowID := (testShardRowID & tp) > 0 + if isTestShardRowID { + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("set global tidb_scatter_region = 1") + defer func() { + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) + tk.MustExec("set global tidb_scatter_region = 0") + }() + } + if isTestPartition { + tk.MustExec("set @@session.tidb_enable_table_partition = '1';") + } else if (testClusteredIndex & tp) > 0 { + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + } + tk.MustExec("drop table if exists test_add_index") + tk.MustExec(createTableSQL) + + done := make(chan error, 1) + start := -10 + num := defaultBatchSize + // first add some rows + batchInsert(tk, "test_add_index", start, num) + + // Add some discrete rows. + maxBatch := 20 + batchCnt := 100 + otherKeys := make([]int, 0, batchCnt*maxBatch) + // Make sure there are no duplicate keys. + base := defaultBatchSize * 20 + for i := 1; i < batchCnt; i++ { + if isTestShardRowID { + base = i % 4 << 61 + } + n := base + i*defaultBatchSize + i + for j := 0; j < rand.Intn(maxBatch); j++ { + n += j + sql := fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", n, n, n) + tk.MustExec(sql) + otherKeys = append(otherKeys, n) + } + } + // Encounter the value of math.MaxInt64 in middle of + v := math.MaxInt64 - defaultBatchSize/2 + tk.MustExec(fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", v, v, v)) + otherKeys = append(otherKeys, v) + + addIdxSQL := fmt.Sprintf("alter table test_add_index add %s key c3_index(c3)", idxTp) + testddlutil.SessionExecInGoroutine(store, "test", addIdxSQL, done) + + deletedKeys := make(map[int]struct{}) + + ticker := time.NewTicker(indexModifyLease / 2) + defer ticker.Stop() +LOOP: + for { + select { + case err := <-done: + if err == nil { + break LOOP + } + require.NoError(t, err) + case <-ticker.C: + // When the server performance is particularly poor, + // the adding index operation can not be completed. + // So here is a limit to the number of rows inserted. + if num > defaultBatchSize*10 { + break + } + step := 5 + // delete some rows, and add some data + for i := num; i < num+step; i++ { + n := rand.Intn(num) + deletedKeys[n] = struct{}{} + sql := fmt.Sprintf("delete from test_add_index where c1 = %d", n) + tk.MustExec(sql) + sql = fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", i, i, i) + tk.MustExec(sql) + } + num += step + } + } + + if isTestShardRowID { + rows := tk.MustQuery("show table test_add_index regions").Rows() + require.GreaterOrEqual(t, len(rows), 16) + tk.MustExec("admin check table test_add_index") + return + } + + // get exists keys + keys := make([]int, 0, num) + for i := start; i < num; i++ { + if _, ok := deletedKeys[i]; ok { + continue + } + keys = append(keys, i) + } + keys = append(keys, otherKeys...) + + // test index key + expectedRows := make([][]interface{}, 0, len(keys)) + for _, key := range keys { + expectedRows = append(expectedRows, []interface{}{fmt.Sprintf("%v", key)}) + } + tk.MustQuery(fmt.Sprintf("select c1 from test_add_index where c3 >= %d order by c1", start)).Check(expectedRows) + tk.MustExec("admin check table test_add_index") + if isTestPartition { + return + } + + // TODO: Support explain in future. + // rows := tk.MustQuery("explain select c1 from test_add_index where c3 >= 100").Rows() + // ay := dumpRows(c, rows) + // require.Contains(t, fmt.Sprintf("%v", ay), "c3_index") + + // get all row handles + require.NoError(t, tk.Session().NewTxn(context.Background())) + tbl := external.GetTableByName(t, tk, "test", "test_add_index") + handles := kv.NewHandleMap() + err := tables.IterRecords(tbl, tk.Session(), tbl.Cols(), + func(h kv.Handle, data []types.Datum, cols []*table.Column) (bool, error) { + handles.Set(h, struct{}{}) + return true, nil + }) + require.NoError(t, err) + + // check in index + var nidx table.Index + idxName := "c3_index" + if len(idxTp) != 0 { + idxName = "primary" + } + for _, tidx := range tbl.Indices() { + if tidx.Meta().Name.L == idxName { + nidx = tidx + break + } + } + // Make sure there is index with name c3_index. + require.NotNil(t, nidx) + require.Greater(t, nidx.Meta().ID, int64(0)) + txn, err := tk.Session().Txn(true) + require.NoError(t, err) + require.NoError(t, txn.Rollback()) + + require.NoError(t, tk.Session().NewTxn(context.Background())) + tk.MustExec("admin check table test_add_index") + tk.MustExec("drop table test_add_index") +} + +func TestAddIndexForGeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(y year NOT NULL DEFAULT '2155')") + for i := 0; i < 50; i++ { + tk.MustExec("insert into t values (?)", i) + } + tk.MustExec("insert into t values()") + tk.MustExec("ALTER TABLE t ADD COLUMN y1 year as (y + 2)") + tk.MustExec("ALTER TABLE t ADD INDEX idx_y(y1)") + + tbl := external.GetTableByName(t, tk, "test", "t") + for _, idx := range tbl.Indices() { + require.False(t, strings.EqualFold(idx.Meta().Name.L, "idx_c2")) + } + // NOTE: this test case contains a bug, it should be uncommented after the bug is fixed. + // TODO: Fix bug https://github.com/pingcap/tidb/issues/12181 + // tk.MustExec("delete from t where y = 2155") + // tk.MustExec("alter table t add index idx_y(y1)") + // tk.MustExec("alter table t drop index idx_y") + + // Fix issue 9311. + tk.MustExec("drop table if exists gcai_table") + tk.MustExec("create table gcai_table (id int primary key);") + tk.MustExec("insert into gcai_table values(1);") + tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d date DEFAULT '9999-12-31';") + tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d1 date as (DATE_SUB(d, INTERVAL 31 DAY));") + tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx(d1);") + tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30")) + tk.MustQuery("select d1 from gcai_table use index(idx)").Check(testkit.Rows("9999-11-30")) + tk.MustExec("admin check table gcai_table") + // The column is PKIsHandle in generated column expression. + tk.MustExec("ALTER TABLE gcai_table ADD COLUMN id1 int as (id+5);") + tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx1(id1);") + tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30 6")) + tk.MustQuery("select id1 from gcai_table use index(idx1)").Check(testkit.Rows("6")) + tk.MustExec("admin check table gcai_table") +} + +// TestAddPrimaryKeyRollback1 is used to test scenarios that will roll back when a duplicate primary key is encountered. +func TestAddPrimaryKeyRollback1(t *testing.T) { + idxName := "PRIMARY" + addIdxSQL := "alter table t1 add primary key c3_index (c3);" + errMsg := "[kv:1062]Duplicate entry '" + strconv.Itoa(defaultBatchSize*2-10) + "' for key 'PRIMARY'" + testAddIndexRollback(t, idxName, addIdxSQL, errMsg, false) +} + +// TestAddPrimaryKeyRollback2 is used to test scenarios that will roll back when a null primary key is encountered. +func TestAddPrimaryKeyRollback2(t *testing.T) { + idxName := "PRIMARY" + addIdxSQL := "alter table t1 add primary key c3_index (c3);" + errMsg := "[ddl:1138]Invalid use of NULL value" + testAddIndexRollback(t, idxName, addIdxSQL, errMsg, true) +} + +func TestAddUniqueIndexRollback(t *testing.T) { + idxName := "c3_index" + addIdxSQL := "create unique index c3_index on t1 (c3)" + errMsg := "[kv:1062]Duplicate entry '" + strconv.Itoa(defaultBatchSize*2-10) + "' for key 'c3_index'" + testAddIndexRollback(t, idxName, addIdxSQL, errMsg, false) +} + +func testAddIndexRollback(t *testing.T, idxName, addIdxSQL, errMsg string, hasNullValsInKey bool) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))") + // defaultBatchSize is equal to ddl.defaultBatchSize + base := defaultBatchSize * 2 + count := base + // add some rows + batchInsert(tk, "t1", 0, count) + // add some null rows + if hasNullValsInKey { + for i := count - 10; i < count; i++ { + tk.MustExec("insert into t1 values (?, ?, null)", i+10, i) + } + } else { + // add some duplicate rows + for i := count - 10; i < count; i++ { + tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) + } + } + + done := make(chan error, 1) + go backgroundExec(store, addIdxSQL, done) + + times := 0 + ticker := time.NewTicker(indexModifyLease / 2) + defer ticker.Stop() +LOOP: + for { + select { + case err := <-done: + require.EqualError(t, err, errMsg) + break LOOP + case <-ticker.C: + if times >= 10 { + break + } + step := 5 + // delete some rows, and add some data + for i := count; i < count+step; i++ { + n := rand.Intn(count) + // (2048, 2038, 2038) and (2038, 2038, 2038) + // Don't delete rows where c1 is 2048 or 2038, otherwise, the entry value in duplicated error message would change. + if n == defaultBatchSize*2-10 || n == defaultBatchSize*2 { + continue + } + tk.MustExec("delete from t1 where c1 = ?", n) + tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) + } + count += step + times++ + } + } + + tbl := external.GetTableByName(t, tk, "test", "t1") + for _, tidx := range tbl.Indices() { + require.False(t, strings.EqualFold(tidx.Meta().Name.L, idxName)) + } + + // delete duplicated/null rows, then add index + for i := base - 10; i < base; i++ { + tk.MustExec("delete from t1 where c1 = ?", i+10) + } + tk.MustExec(addIdxSQL) + tk.MustExec("drop table t1") +} + +func TestAddIndexWithSplitTable(t *testing.T) { + createSQL := "CREATE TABLE test_add_index(a bigint PRIMARY KEY AUTO_RANDOM(4), b varchar(255), c bigint)" + stSQL := fmt.Sprintf("SPLIT TABLE test_add_index BETWEEN (%d) AND (%d) REGIONS 16;", math.MinInt64, math.MaxInt64) + testAddIndexWithSplitTable(t, createSQL, stSQL) +} + +func TestAddIndexWithShardRowID(t *testing.T) { + createSQL := "create table test_add_index(a bigint, b bigint, c bigint) SHARD_ROW_ID_BITS = 4 pre_split_regions = 4;" + testAddIndexWithSplitTable(t, createSQL, "") +} + +func testAddIndexWithSplitTable(t *testing.T, createSQL, splitTableSQL string) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + hasAutoRandomField := len(splitTableSQL) > 0 + if !hasAutoRandomField { + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("set global tidb_scatter_region = 1") + defer func() { + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) + tk.MustExec("set global tidb_scatter_region = 0") + }() + } + tk.MustExec(createSQL) + + batchInsertRows := func(tk *testkit.TestKit, needVal bool, tbl string, start, end int) error { + dml := fmt.Sprintf("insert into %s values", tbl) + for i := start; i < end; i++ { + if needVal { + dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) + } else { + dml += "()" + } + if i != end-1 { + dml += "," + } + } + _, err := tk.Exec(dml) + return err + } + + done := make(chan error, 1) + start := -20 + num := defaultBatchSize + // Add some discrete rows. + goCnt := 10 + errCh := make(chan error, goCnt) + for i := 0; i < goCnt; i++ { + base := (i % 8) << 60 + go func(b int, eCh chan error) { + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + eCh <- batchInsertRows(tk1, !hasAutoRandomField, "test_add_index", base+start, base+num) + }(base, errCh) + } + for i := 0; i < goCnt; i++ { + err := <-errCh + require.NoError(t, err) + } + + if hasAutoRandomField { + tk.MustQuery(splitTableSQL).Check(testkit.Rows("15 1")) + } + tk.MustQuery("select @@session.tidb_wait_split_region_finish").Check(testkit.Rows("1")) + rows := tk.MustQuery("show table test_add_index regions").Rows() + require.Len(t, rows, 16) + addIdxSQL := "alter table test_add_index add index idx(a)" + testddlutil.SessionExecInGoroutine(store, "test", addIdxSQL, done) + + ticker := time.NewTicker(indexModifyLease / 5) + defer ticker.Stop() + num = 0 +LOOP: + for { + select { + case err := <-done: + if err == nil { + break LOOP + } + require.NoError(t, err) + case <-ticker.C: + // When the server performance is particularly poor, + // the adding index operation can not be completed. + // So here is a limit to the number of rows inserted. + if num >= 1000 { + break + } + step := 20 + // delete, insert and update some data + for i := num; i < num+step; i++ { + sql := fmt.Sprintf("delete from test_add_index where a = %d", i+1) + tk.MustExec(sql) + if hasAutoRandomField { + sql = "insert into test_add_index values ()" + } else { + sql = fmt.Sprintf("insert into test_add_index values (%d, %d, %d)", i, i, i) + } + tk.MustExec(sql) + sql = fmt.Sprintf("update test_add_index set b = %d", i*10) + tk.MustExec(sql) + } + num += step + } + } + + tk.MustExec("admin check table test_add_index") +} + +func TestAddAnonymousIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t_anonymous_index (c1 int, c2 int, C3 int)") + tk.MustExec("alter table t_anonymous_index add index (c1, c2)") + // for dropping empty index + err := tk.ExecToErr("alter table t_anonymous_index drop index") + require.Error(t, err) + // The index name is c1 when adding index (c1, c2). + tk.MustExec("alter table t_anonymous_index drop index c1") + tbl := external.GetTableByName(t, tk, "test", "t_anonymous_index") + require.Len(t, tbl.Indices(), 0) + // for adding some indices that the first column name is c1 + tk.MustExec("alter table t_anonymous_index add index (c1)") + err = tk.ExecToErr("alter table t_anonymous_index add index c1 (c2)") + require.Error(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_anonymous_index") + require.Len(t, tbl.Indices(), 1) + require.Equal(t, "c1", tbl.Indices()[0].Meta().Name.L) + // The MySQL will be a warning. + tk.MustExec("alter table t_anonymous_index add index c1_3 (c1)") + tk.MustExec("alter table t_anonymous_index add index (c1, c2, C3)") + // The MySQL will be a warning. + tk.MustExec("alter table t_anonymous_index add index (c1)") + tbl = external.GetTableByName(t, tk, "test", "t_anonymous_index") + require.Len(t, tbl.Indices(), 4) + tk.MustExec("alter table t_anonymous_index drop index c1") + tk.MustExec("alter table t_anonymous_index drop index c1_2") + tk.MustExec("alter table t_anonymous_index drop index c1_3") + tk.MustExec("alter table t_anonymous_index drop index c1_4") + // for case-insensitive + tk.MustExec("alter table t_anonymous_index add index (C3)") + tk.MustExec("alter table t_anonymous_index drop index c3") + tk.MustExec("alter table t_anonymous_index add index c3 (C3)") + tk.MustExec("alter table t_anonymous_index drop index C3") + // for anonymous index with column name `primary` + tk.MustExec("create table t_primary (`primary` int, b int, key (`primary`))") + tbl = external.GetTableByName(t, tk, "test", "t_primary") + require.Equal(t, "primary_2", tbl.Indices()[0].Meta().Name.L) + tk.MustExec("alter table t_primary add index (`primary`);") + tbl = external.GetTableByName(t, tk, "test", "t_primary") + require.Equal(t, "primary_2", tbl.Indices()[0].Meta().Name.L) + require.Equal(t, "primary_3", tbl.Indices()[1].Meta().Name.L) + tk.MustExec("alter table t_primary add primary key(b);") + tbl = external.GetTableByName(t, tk, "test", "t_primary") + require.Equal(t, "primary_2", tbl.Indices()[0].Meta().Name.L) + require.Equal(t, "primary_3", tbl.Indices()[1].Meta().Name.L) + require.Equal(t, "primary", tbl.Indices()[2].Meta().Name.L) + tk.MustExec("create table t_primary_2 (`primary` int, key primary_2 (`primary`), key (`primary`))") + tbl = external.GetTableByName(t, tk, "test", "t_primary_2") + require.Equal(t, "primary_2", tbl.Indices()[0].Meta().Name.L) + require.Equal(t, "primary_3", tbl.Indices()[1].Meta().Name.L) + tk.MustExec("create table t_primary_3 (`primary_2` int, key(`primary_2`), `primary` int, key(`primary`));") + tbl = external.GetTableByName(t, tk, "test", "t_primary_3") + require.Equal(t, "primary_2", tbl.Indices()[0].Meta().Name.L) + require.Equal(t, "primary_3", tbl.Indices()[1].Meta().Name.L) +} + +func TestAddIndexWithPK(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tests := []struct { + name string + mode variable.ClusteredIndexDefMode + }{ + { + "ClusteredIndexDefModeIntOnly", + variable.ClusteredIndexDefModeIntOnly, + }, + { + "ClusteredIndexDefModeOn", + variable.ClusteredIndexDefModeOn, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + tk.Session().GetSessionVars().EnableClusteredIndex = test.mode + tk.MustExec("drop table if exists test_add_index_with_pk") + tk.MustExec("create table test_add_index_with_pk(a int not null, b int not null default '0', primary key(a))") + tk.MustExec("insert into test_add_index_with_pk values(1, 2)") + tk.MustExec("alter table test_add_index_with_pk add index idx (a)") + tk.MustQuery("select a from test_add_index_with_pk").Check(testkit.Rows("1")) + tk.MustExec("insert into test_add_index_with_pk values(2, 2)") + tk.MustExec("alter table test_add_index_with_pk add index idx1 (a, b)") + tk.MustQuery("select * from test_add_index_with_pk").Check(testkit.Rows("1 2", "2 2")) + tk.MustExec("drop table if exists test_add_index_with_pk1") + tk.MustExec("create table test_add_index_with_pk1(a int not null, b int not null default '0', c int, d int, primary key(c))") + tk.MustExec("insert into test_add_index_with_pk1 values(1, 1, 1, 1)") + tk.MustExec("alter table test_add_index_with_pk1 add index idx (c)") + tk.MustExec("insert into test_add_index_with_pk1 values(2, 2, 2, 2)") + tk.MustQuery("select * from test_add_index_with_pk1").Check(testkit.Rows("1 1 1 1", "2 2 2 2")) + tk.MustExec("drop table if exists test_add_index_with_pk2") + tk.MustExec("create table test_add_index_with_pk2(a int not null, b int not null default '0', c int unsigned, d int, primary key(c))") + tk.MustExec("insert into test_add_index_with_pk2 values(1, 1, 1, 1)") + tk.MustExec("alter table test_add_index_with_pk2 add index idx (c)") + tk.MustExec("insert into test_add_index_with_pk2 values(2, 2, 2, 2)") + tk.MustQuery("select * from test_add_index_with_pk2").Check(testkit.Rows("1 1 1 1", "2 2 2 2")) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, primary key(a, b));") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("create index idx on t (a, b);") + }) + } +} + +func TestCancelAddPrimaryKey(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) + defer clean() + idxName := "primary" + addIdxSQL := "alter table t1 add primary key idx_c2 (c2);" + testCancelAddIndex(t, store, dom, idxName, addIdxSQL) + + // Check the column's flag when the "add primary key" failed. + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + require.NoError(t, tk.Session().NewTxn(context.Background())) + tbl := external.GetTableByName(t, tk, "test", "t1") + col1Flag := tbl.Cols()[1].Flag + require.True(t, !mysql.HasNotNullFlag(col1Flag) && !mysql.HasPreventNullInsertFlag(col1Flag) && mysql.HasUnsignedFlag(col1Flag)) +} + +func TestCancelAddIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) + defer clean() + idxName := "c3_index" + addIdxSQL := "create unique index c3_index on t1 (c3)" + testCancelAddIndex(t, store, dom, idxName, addIdxSQL) +} + +func testCancelAddIndex(t *testing.T, store kv.Storage, dom *domain.Domain, idxName, addIdxSQL string) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int unsigned, c3 int, unique key(c1))") + + d := dom.DDL() + + // defaultBatchSize is equal to ddl.defaultBatchSize + count := defaultBatchSize * 32 + start := 0 + for i := start; i < count; i += defaultBatchSize { + batchInsert(tk, "t1", i, i+defaultBatchSize) + } + + hook := &ddl.TestDDLCallback{Do: dom} + originBatchSize := tk.MustQuery("select @@global.tidb_ddl_reorg_batch_size") + // Set batch size to lower try to slow down add-index reorganization, This if for hook to cancel this ddl job. + tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 32") + defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", originBatchSize.Rows()[0][0])) + // let hook.OnJobUpdatedExported has chance to cancel the job. + // the hook.OnJobUpdatedExported is called when the job is updated, runReorgJob will wait ddl.ReorgWaitTimeout, then return the ddl.runDDLJob. + // After that ddl call d.hook.OnJobUpdated(job), so that we can canceled the job in this test case. + var checkErr error + hook.OnJobUpdatedExported, _, checkErr = backgroundExecOnJobUpdatedExported(t, tk, store, hook, idxName) + originalHook := d.GetHook() + jobIDExt := wrapJobIDExtCallback(hook) + d.SetHook(jobIDExt) + done := make(chan error, 1) + go backgroundExec(store, addIdxSQL, done) + + times := 0 + ticker := time.NewTicker(indexModifyLease / 2) + defer ticker.Stop() +LOOP: + for { + select { + case err := <-done: + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + break LOOP + case <-ticker.C: + if times >= 10 { + break + } + step := 5 + // delete some rows, and add some data + for i := count; i < count+step; i++ { + n := rand.Intn(count) + tk.MustExec("delete from t1 where c1 = ?", n) + tk.MustExec("insert into t1 values (?, ?, ?)", i+10, i, i) + } + count += step + times++ + } + } + d.SetHook(originalHook) +} + +func backgroundExecOnJobUpdatedExported(t *testing.T, tk *testkit.TestKit, store kv.Storage, hook *ddl.TestDDLCallback, idxName string) (func(*model.Job), *model.IndexInfo, error) { + var checkErr error + first := true + c3IdxInfo := &model.IndexInfo{} + hook.OnJobUpdatedExported = func(job *model.Job) { + addIndexNotFirstReorg := (job.Type == model.ActionAddIndex || job.Type == model.ActionAddPrimaryKey) && + job.SchemaState == model.StateWriteReorganization && job.SnapshotVer != 0 + // If the action is adding index and the state is writing reorganization, it want to test the case of cancelling the job when backfilling indexes. + // When the job satisfies this case of addIndexNotFirstReorg, the worker will start to backfill indexes. + if !addIndexNotFirstReorg { + // Get the index's meta. + if c3IdxInfo.ID != 0 { + return + } + tbl := external.GetTableByName(t, tk, "test", "t1") + for _, index := range tbl.Indices() { + if !tables.IsIndexWritable(index) { + continue + } + if index.Meta().Name.L == idxName { + *c3IdxInfo = *index.Meta() + } + } + return + } + // The job satisfies the case of addIndexNotFirst for the first time, the worker hasn't finished a batch of backfill indexes. + if first { + first = false + return + } + if checkErr != nil { + return + } + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + return + } + jobIDs := []int64{job.ID} + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + // It only tests cancel one DDL job. + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + txn, err = hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + err = txn.Commit(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + } + } + return hook.OnJobUpdatedExported, c3IdxInfo, checkErr +} + +// TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started. +func TestCancelAddIndex1(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(c1 int, c2 int)") + for i := 0; i < 50; i++ { + tk.MustExec("insert into t values (?, ?)", i, i) + } + + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization && job.SnapshotVer == 0 { + jobIDs := []int64{job.ID} + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + + checkErr = txn.Commit(context.Background()) + } + } + originalHook := dom.DDL().GetHook() + dom.DDL().SetHook(hook) + err := tk.ExecToErr("alter table t add index idx_c2(c2)") + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + + dom.DDL().SetHook(originalHook) + tbl := external.GetTableByName(t, tk, "test", "t") + for _, idx := range tbl.Indices() { + require.False(t, strings.EqualFold(idx.Meta().Name.L, "idx_c2")) + } + tk.MustExec("alter table t add index idx_c2(c2)") + tk.MustExec("alter table t drop index idx_c2") +} + +func TestAddGlobalIndex(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableGlobalIndex = true + }) + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table test_t1 (a int, b int) partition by range (b)" + + " (partition p0 values less than (10), " + + " partition p1 values less than (maxvalue));") + tk.MustExec("insert test_t1 values (1, 1)") + tk.MustExec("alter table test_t1 add unique index p_a (a);") + tk.MustExec("insert test_t1 values (2, 11)") + tbl := external.GetTableByName(t, tk, "test", "test_t1") + tblInfo := tbl.Meta() + indexInfo := tblInfo.FindIndexByName("p_a") + require.NotNil(t, indexInfo) + require.True(t, indexInfo.Global) + + require.NoError(t, tk.Session().NewTxn(context.Background())) + txn, err := tk.Session().Txn(true) + require.NoError(t, err) + + // check row 1 + pid := tblInfo.Partition.Definitions[0].ID + idxVals := []types.Datum{types.NewDatum(1)} + rowVals := []types.Datum{types.NewDatum(1), types.NewDatum(1)} + checkGlobalIndexRow(t, tk.Session(), tblInfo, indexInfo, pid, idxVals, rowVals) + + // check row 2 + pid = tblInfo.Partition.Definitions[1].ID + idxVals = []types.Datum{types.NewDatum(2)} + rowVals = []types.Datum{types.NewDatum(2), types.NewDatum(11)} + checkGlobalIndexRow(t, tk.Session(), tblInfo, indexInfo, pid, idxVals, rowVals) + require.NoError(t, txn.Commit(context.Background())) + + // Test add global Primary Key index + tk.MustExec("create table test_t2 (a int, b int) partition by range (b)" + + " (partition p0 values less than (10), " + + " partition p1 values less than (maxvalue));") + tk.MustExec("insert test_t2 values (1, 1)") + tk.MustExec("alter table test_t2 add primary key (a) nonclustered;") + tk.MustExec("insert test_t2 values (2, 11)") + tbl = external.GetTableByName(t, tk, "test", "test_t2") + tblInfo = tbl.Meta() + indexInfo = tblInfo.FindIndexByName("primary") + require.NotNil(t, indexInfo) + require.True(t, indexInfo.Global) + + require.NoError(t, tk.Session().NewTxn(context.Background())) + txn, err = tk.Session().Txn(true) + require.NoError(t, err) + + // check row 1 + pid = tblInfo.Partition.Definitions[0].ID + idxVals = []types.Datum{types.NewDatum(1)} + rowVals = []types.Datum{types.NewDatum(1), types.NewDatum(1)} + checkGlobalIndexRow(t, tk.Session(), tblInfo, indexInfo, pid, idxVals, rowVals) + + // check row 2 + pid = tblInfo.Partition.Definitions[1].ID + idxVals = []types.Datum{types.NewDatum(2)} + rowVals = []types.Datum{types.NewDatum(2), types.NewDatum(11)} + checkGlobalIndexRow(t, tk.Session(), tblInfo, indexInfo, pid, idxVals, rowVals) + + require.NoError(t, txn.Commit(context.Background())) +} + +// checkGlobalIndexRow reads one record from global index and check. Only support int handle. +func checkGlobalIndexRow( + t *testing.T, + ctx sessionctx.Context, + tblInfo *model.TableInfo, + indexInfo *model.IndexInfo, + pid int64, + idxVals []types.Datum, + rowVals []types.Datum, +) { + require.NoError(t, ctx.NewTxn(context.Background())) + txn, err := ctx.Txn(true) + require.NoError(t, err) + sc := ctx.GetSessionVars().StmtCtx + + tblColMap := make(map[int64]*types.FieldType, len(tblInfo.Columns)) + for _, col := range tblInfo.Columns { + tblColMap[col.ID] = &col.FieldType + } + + // Check local index entry does not exist. + localPrefix := tablecodec.EncodeTableIndexPrefix(pid, indexInfo.ID) + it, err := txn.Iter(localPrefix, nil) + require.NoError(t, err) + // no local index entry. + require.False(t, it.Valid() && it.Key().HasPrefix(localPrefix)) + it.Close() + + // Check global index entry. + encodedValue, err := codec.EncodeKey(sc, nil, idxVals...) + require.NoError(t, err) + key := tablecodec.EncodeIndexSeekKey(tblInfo.ID, indexInfo.ID, encodedValue) + require.NoError(t, err) + value, err := txn.Get(context.Background(), key) + require.NoError(t, err) + idxColInfos := tables.BuildRowcodecColInfoForIndexColumns(indexInfo, tblInfo) + colVals, err := tablecodec.DecodeIndexKV(key, value, len(indexInfo.Columns), tablecodec.HandleDefault, idxColInfos) + require.NoError(t, err) + require.Len(t, colVals, len(idxVals)+2) + for i, val := range idxVals { + _, d, err := codec.DecodeOne(colVals[i]) + require.NoError(t, err) + require.Equal(t, val, d) + } + _, d, err := codec.DecodeOne(colVals[len(idxVals)+1]) // pid + require.NoError(t, err) + require.Equal(t, pid, d.GetInt64()) + + _, d, err = codec.DecodeOne(colVals[len(idxVals)]) // handle + require.NoError(t, err) + h := kv.IntHandle(d.GetInt64()) + rowKey := tablecodec.EncodeRowKey(pid, h.Encoded()) + rowValue, err := txn.Get(context.Background(), rowKey) + require.NoError(t, err) + rowValueDatums, err := tablecodec.DecodeRowToDatumMap(rowValue, tblColMap, time.UTC) + require.NoError(t, err) + require.NotNil(t, rowValueDatums) + for i, val := range rowVals { + require.Equal(t, val, rowValueDatums[tblInfo.Columns[i].ID]) + } +} + +func TestDropIndexes(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, indexModifyLease) + defer clean() + // drop multiple indexes + createSQL := "create table test_drop_indexes (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));" + dropIdxSQL := "alter table test_drop_indexes drop index i1, drop index i2;" + idxNames := []string{"i1", "i2"} + testDropIndexes(t, store, createSQL, dropIdxSQL, idxNames) + + createSQL = "create table test_drop_indexes (id int, c1 int, c2 int, primary key(id) nonclustered, unique key i1(c1), key i2(c2));" + dropIdxSQL = "alter table test_drop_indexes drop primary key, drop index i1;" + idxNames = []string{"primary", "i1"} + testDropIndexes(t, store, createSQL, dropIdxSQL, idxNames) + + createSQL = "create table test_drop_indexes (uuid varchar(32), c1 int, c2 int, primary key(uuid), unique key i1(c1), key i2(c2));" + dropIdxSQL = "alter table test_drop_indexes drop primary key, drop index i1, drop index i2;" + idxNames = []string{"primary", "i1", "i2"} + testDropIndexes(t, store, createSQL, dropIdxSQL, idxNames) + + testDropIndexesIfExists(t, store) + testDropIndexesFromPartitionedTable(t, store) + testCancelDropIndexes(t, store, dom.DDL()) +} + +func testDropIndexes(t *testing.T, store kv.Storage, createSQL, dropIdxSQL string, idxNames []string) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists test_drop_indexes") + tk.MustExec(createSQL) + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + done := make(chan error, 1) + + num := 100 + // add some rows + for i := 0; i < num; i++ { + tk.MustExec("insert into test_drop_indexes values (?, ?, ?)", i, i, i) + } + idxIDs := make([]int64, 0, 3) + for _, idxName := range idxNames { + idxIDs = append(idxIDs, external.GetIndexID(t, tk, "test", "test_drop_indexes", idxName)) + } + testddlutil.SessionExecInGoroutine(store, "test", dropIdxSQL, done) + + ticker := time.NewTicker(indexModifyLease / 2) + defer ticker.Stop() +LOOP: + for { + select { + case err := <-done: + if err == nil { + break LOOP + } + require.NoError(t, err) + case <-ticker.C: + step := 5 + // delete some rows, and add some data + for i := num; i < num+step; i++ { + n := rand.Intn(num) + tk.MustExec("update test_drop_indexes set c2 = 1 where c1 = ?", n) + tk.MustExec("insert into test_drop_indexes values (?, ?, ?)", i, i, i) + } + num += step + } + } +} + +func testDropIndexesIfExists(t *testing.T, store kv.Storage) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists test_drop_indexes_if_exists;") + tk.MustExec("create table test_drop_indexes_if_exists (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2));") + + // Drop different indexes. + tk.MustGetErrMsg( + "alter table test_drop_indexes_if_exists drop index i1, drop index i3;", + "[ddl:1091]index i3 doesn't exist", + ) + tk.MustExec("alter table test_drop_indexes_if_exists drop index i1, drop index if exists i3;") + tk.MustQuery("show warnings;").Check(testkit.RowsWithSep("|", "Note|1091|index i3 doesn't exist")) + + // Verify the impact of deletion order when dropping duplicate indexes. + tk.MustGetErrCode( + "alter table test_drop_indexes_if_exists drop index i2, drop index i2;", + errno.ErrUnsupportedDDLOperation, + ) + tk.MustGetErrCode( + "alter table test_drop_indexes_if_exists drop index if exists i2, drop index i2;", + errno.ErrUnsupportedDDLOperation, + ) + tk.MustGetErrCode( + "alter table test_drop_indexes_if_exists drop index i2, drop index if exists i2;", + errno.ErrUnsupportedDDLOperation, + ) +} + +func testDropIndexesFromPartitionedTable(t *testing.T, store kv.Storage) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists test_drop_indexes_from_partitioned_table;") + tk.MustExec(` + create table test_drop_indexes_from_partitioned_table (id int, c1 int, c2 int, primary key(id), key i1(c1), key i2(c2)) + partition by range(id) (partition p0 values less than (6), partition p1 values less than maxvalue); + `) + for i := 0; i < 20; i++ { + tk.MustExec("insert into test_drop_indexes_from_partitioned_table values (?, ?, ?)", i, i, i) + } + tk.MustExec("alter table test_drop_indexes_from_partitioned_table drop index i1, drop index if exists i2;") + tk.MustExec("alter table test_drop_indexes_from_partitioned_table add index i1(c1)") + tk.MustExec("alter table test_drop_indexes_from_partitioned_table drop index i1, drop index if exists i1;") + tk.MustExec("alter table test_drop_indexes_from_partitioned_table drop column c1, drop column c2;") + tk.MustExec("alter table test_drop_indexes_from_partitioned_table add column c1 int") + tk.MustExec("alter table test_drop_indexes_from_partitioned_table drop column c1, drop column if exists c1;") +} + +func testCancelDropIndexes(t *testing.T, store kv.Storage, d ddl.DDL) { + indexesName := []string{"idx_c1", "idx_c2"} + addIdxesSQL := "alter table t add index idx_c1 (c1);alter table t add index idx_c2 (c2);" + dropIdxesSQL := "alter table t drop index idx_c1;alter table t drop index idx_c2;" + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(c1 int, c2 int)") + defer tk.MustExec("drop table t;") + for i := 0; i < 5; i++ { + tk.MustExec("insert into t values (?, ?)", i, i) + } + testCases := []struct { + needAddIndex bool + jobState model.JobState + JobSchemaState model.SchemaState + cancelSucc bool + }{ + // model.JobStateNone means the jobs is canceled before the first run. + // if we cancel successfully, we need to set needAddIndex to false in the next test case. Otherwise, set needAddIndex to true. + {true, model.JobStateQueueing, model.StateNone, true}, + {false, model.JobStateRunning, model.StateWriteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteOnly, false}, + {true, model.JobStateRunning, model.StateDeleteReorganization, false}, + } + var checkErr error + hook := &ddl.TestDDLCallback{} + var jobID int64 + testCase := &testCases[0] + hook.OnJobRunBeforeExported = func(job *model.Job) { + if (job.Type == model.ActionDropIndex || job.Type == model.ActionDropPrimaryKey) && + job.State == testCase.jobState && job.SchemaState == testCase.JobSchemaState { + jobID = job.ID + jobIDs := []int64{job.ID} + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.TODO()) + if err != nil { + checkErr = errors.Trace(err) + return + } + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + checkErr = txn.Commit(context.Background()) + } + } + originalHook := d.GetHook() + d.SetHook(hook) + for i := range testCases { + testCase = &testCases[i] + if testCase.needAddIndex { + tk.MustExec(addIdxesSQL) + } + err := tk.ExecToErr(dropIdxesSQL) + tbl := external.GetTableByName(t, tk, "test", "t") + + var indexInfos []*model.IndexInfo + for _, idxName := range indexesName { + indexInfo := tbl.Meta().FindIndexByName(idxName) + if indexInfo != nil { + indexInfos = append(indexInfos, indexInfo) + } + } + + if testCase.cancelSucc { + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + require.NotNil(t, indexInfos) + require.Equal(t, model.StatePublic, indexInfos[0].State) + } else { + require.NoError(t, err) + require.EqualError(t, checkErr, admin.ErrCannotCancelDDLJob.GenWithStackByArgs(jobID).Error()) + require.Nil(t, indexInfos) + } + } + d.SetHook(originalHook) + tk.MustExec(addIdxesSQL) + tk.MustExec(dropIdxesSQL) +} + +func TestDropPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + idxName := "primary" + createSQL := "create table test_drop_index (c1 int, c2 int, c3 int, unique key(c1), primary key(c3) nonclustered)" + dropIdxSQL := "alter table test_drop_index drop primary key;" + testDropIndex(t, store, createSQL, dropIdxSQL, idxName) +} + +func TestDropIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + idxName := "c3_index" + createSQL := "create table test_drop_index (c1 int, c2 int, c3 int, unique key(c1), key c3_index(c3))" + dropIdxSQL := "alter table test_drop_index drop index c3_index;" + testDropIndex(t, store, createSQL, dropIdxSQL, idxName) +} + +func testDropIndex(t *testing.T, store kv.Storage, createSQL, dropIdxSQL, idxName string) { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists test_drop_index") + tk.MustExec(createSQL) + done := make(chan error, 1) + tk.MustExec("delete from test_drop_index") + + num := 100 + // add some rows + for i := 0; i < num; i++ { + tk.MustExec("insert into test_drop_index values (?, ?, ?)", i, i, i) + } + testddlutil.SessionExecInGoroutine(store, "test", dropIdxSQL, done) + + ticker := time.NewTicker(indexModifyLease / 2) + defer ticker.Stop() +LOOP: + for { + select { + case err := <-done: + if err == nil { + break LOOP + } + require.NoError(t, err) + case <-ticker.C: + step := 5 + // delete some rows, and add some data + for i := num; i < num+step; i++ { + n := rand.Intn(num) + tk.MustExec("update test_drop_index set c2 = 1 where c1 = ?", n) + tk.MustExec("insert into test_drop_index values (?, ?, ?)", i, i, i) + } + num += step + } + } + + rows := tk.MustQuery("explain select c1 from test_drop_index where c3 >= 0") + require.NotContains(t, fmt.Sprintf("%v", rows), idxName) + + tk.MustExec("drop table test_drop_index") +} + +func TestAddMultiColumnsIndexClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists test_add_multi_col_index_clustered;") + tk.MustExec("create database test_add_multi_col_index_clustered;") + tk.MustExec("use test_add_multi_col_index_clustered;") + + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("create table t (a int, b varchar(10), c int, primary key (a, b));") + tk.MustExec("insert into t values (1, '1', 1), (2, '2', NULL), (3, '3', 3);") + tk.MustExec("create index idx on t (a, c);") + + tk.MustExec("admin check index t idx;") + tk.MustExec("admin check table t;") + + tk.MustExec("insert into t values (5, '5', 5), (6, '6', NULL);") + + tk.MustExec("admin check index t idx;") + tk.MustExec("admin check table t;") +} + +func TestAddIndexWithDupCols(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + err1 := infoschema.ErrColumnExists.GenWithStackByArgs("b") + err2 := infoschema.ErrColumnExists.GenWithStackByArgs("B") + + tk.MustExec("create table test_add_index_with_dup (a int, b int)") + err := tk.ExecToErr("create index c on test_add_index_with_dup(b, a, b)") + require.ErrorIs(t, err, errors.Cause(err1)) + err = tk.ExecToErr("create index c on test_add_index_with_dup(b, a, B)") + require.ErrorIs(t, err, errors.Cause(err2)) + err = tk.ExecToErr("alter table test_add_index_with_dup add index c (b, a, b)") + require.ErrorIs(t, err, errors.Cause(err1)) + err = tk.ExecToErr("alter table test_add_index_with_dup add index c (b, a, B)") + require.ErrorIs(t, err, errors.Cause(err2)) + + tk.MustExec("drop table test_add_index_with_dup") +} + +func TestAnonymousIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("DROP TABLE IF EXISTS t") + tk.MustExec("create table t(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb int, b int)") + tk.MustExec("alter table t add index bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(b)") + tk.MustExec("alter table t add index (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)") + rows := tk.MustQuery("show index from t where key_name='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'").Rows() + require.Len(t, rows, 1) + rows = tk.MustQuery("show index from t where key_name='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_2'").Rows() + require.Len(t, rows, 1) +} + +func TestAddIndexWithDupIndex(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, indexModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + err1 := dbterror.ErrDupKeyName.GenWithStack("index already exist %s", "idx") + err2 := dbterror.ErrDupKeyName.GenWithStack("index already exist %s; "+ + "a background job is trying to add the same index, "+ + "please check by `ADMIN SHOW DDL JOBS`", "idx") + + // When there is already an duplicate index, show error message. + tk.MustExec("create table test_add_index_with_dup (a int, key idx (a))") + err := tk.ExecToErr("alter table test_add_index_with_dup add index idx (a)") + require.ErrorIs(t, err, errors.Cause(err1)) + + // When there is another session adding duplicate index with state other than + // StatePublic, show explicit error message. + tbl := external.GetTableByName(t, tk, "test", "test_add_index_with_dup") + indexInfo := tbl.Meta().FindIndexByName("idx") + indexInfo.State = model.StateNone + err = tk.ExecToErr("alter table test_add_index_with_dup add index idx (a)") + require.ErrorIs(t, err, errors.Cause(err2)) +} diff --git a/ddl/integration_test.go b/ddl/integration_test.go new file mode 100644 index 0000000000000..0ecd18baa2660 --- /dev/null +++ b/ddl/integration_test.go @@ -0,0 +1,153 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "fmt" + "testing" + + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestDefaultValueIsBinaryString(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tests := []struct { + colTp string + defVal string + result string + }{ + {"char(10) charset gbk", "0xC4E3BAC3", "你好"}, + {"char(10) charset gbk", "'好'", "好"}, + {"varchar(10) charset gbk", "0xC4E3BAC3", "你好"}, + {"char(10) charset utf8mb4", "0xE4BDA0E5A5BD", "你好"}, + {"char(10) charset utf8mb4", "0b111001001011100010010110111001111001010110001100", "世界"}, + {"bit(48)", "0xE4BDA0E5A5BD", "你好"}, + {"enum('你好')", "0xE4BDA0E5A5BD", "你好"}, + {"set('你好')", "0xE4BDA0E5A5BD", "你好"}, + } + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + for _, tt := range tests { + tk.MustExec("drop table if exists t;") + template := "create table t (a %s default %s);" + tk.MustExec(fmt.Sprintf(template, tt.colTp, tt.defVal)) + tk.MustExec("insert into t values (default);") + tk.MustQuery("select a from t;").Check(testkit.Rows(tt.result)) + } + + // Test invalid default value. + tk.MustExec("drop table if exists t;") + // 0xE4BDA0E5A5BD81 is an invalid utf-8 string. + tk.MustGetErrMsg("create table t (a char(20) charset utf8mb4 default 0xE4BDA0E5A5BD81);", + "[ddl:1067]Invalid default value for 'a'") + tk.MustGetErrMsg("create table t (a blob default 0xE4BDA0E5A5BD81);", + "[ddl:1101]BLOB/TEXT/JSON column 'a' can't have a default value") +} + +// https://github.com/pingcap/tidb/issues/30740. +func TestDefaultValueInEnum(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + // The value 0x91 should not cause panic. + tk.MustExec("create table t(a enum('a', 0x91) charset gbk);") + tk.MustExec("insert into t values (1), (2);") // Use 1-base index to locate the value. + tk.MustQuery("select a from t;").Check(testkit.Rows("a", "")) // 0x91 is truncate. + tk.MustExec("drop table t;") + tk.MustExec("create table t (a enum('a', 0x91)) charset gbk;") // Test for table charset. + tk.MustExec("insert into t values (1), (2);") + tk.MustQuery("select a from t;").Check(testkit.Rows("a", "")) + tk.MustExec("drop table t;") + tk.MustGetErrMsg("create table t(a set('a', 0x91, '') charset gbk);", + "[types:1291]Column 'a' has duplicated value '' in SET") + // Test valid utf-8 string value in enum. Note that the binary literal only can be decoded to utf-8. + tk.MustExec("create table t (a enum('a', 0xE4BDA0E5A5BD) charset gbk);") + tk.MustExec("insert into t values (1), (2);") + tk.MustQuery("select a from t;").Check(testkit.Rows("a", "你好")) +} + +func TestDDLStatementsBackFill(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + needReorg := false + dom.DDL().SetHook(&ddl.TestDDLCallback{ + Do: dom, + OnJobUpdatedExported: func(job *model.Job) { + if job.SchemaState == model.StateWriteReorganization { + needReorg = true + } + }, + }) + tk.MustExec("create table t (a int, b char(65));") + tk.MustExec("insert into t values (1, '123');") + testCases := []struct { + ddlSQL string + expectedNeedReorg bool + }{ + {"alter table t modify column a bigint;", false}, + {"alter table t modify column b char(255);", false}, + {"alter table t modify column a varchar(100);", true}, + {"create table t1 (a int, b int);", false}, + {"alter table t1 add index idx_a(a);", true}, + {"alter table t1 add primary key(b) nonclustered;", true}, + {"alter table t1 drop primary key;", false}, + } + for _, tc := range testCases { + needReorg = false + tk.MustExec(tc.ddlSQL) + require.Equal(t, tc.expectedNeedReorg, needReorg, tc) + } +} + +func TestSchema(t *testing.T) { + _, clean := testkit.CreateMockStore(t) + defer clean() + + ddl.ExportTestSchema(t) +} + +func TestDDLOnCachedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tests := []struct { + sql string + result string + }{ + {"drop table t", "[ddl:8242]'Drop Table' is unsupported on cache tables."}, + {"create index t_id on t (id)", "[ddl:8242]'Create Index' is unsupported on cache tables."}, + {"alter table t drop index c", "[ddl:8242]'Alter Table' is unsupported on cache tables."}, + {"alter table t add column (d int)", "[ddl:8242]'Alter Table' is unsupported on cache tables."}, + {"truncate table t", "[ddl:8242]'Truncate Table' is unsupported on cache tables."}, + {"rename table t to t1", "[ddl:8242]'Rename Table' is unsupported on cache tables."}, + } + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("create table t (id int, c int, index(c));") + tk.MustExec("alter table t cache;") + + for _, tt := range tests { + tk.MustGetErrMsg(tt.sql, tt.result) + } + + tk.MustExec("alter table t nocache;") + tk.MustExec("drop table if exists t;") +} diff --git a/ddl/label/attributes.go b/ddl/label/attributes.go index b7169411fa6e2..b797f66e73168 100644 --- a/ddl/label/attributes.go +++ b/ddl/label/attributes.go @@ -136,7 +136,7 @@ func (labels *Labels) Add(label Label) error { } s1 := label.Restore() s2 := l.Restore() - return fmt.Errorf("%w: '%s' and '%s'", ErrConflictingAttributes, s1, s2) + return fmt.Errorf("'%s' and '%s' are conflicted", s1, s2) } *labels = append(*labels, label) diff --git a/ddl/label/attributes_test.go b/ddl/label/attributes_test.go index 38ea9f3e52ada..fcf53db3706b8 100644 --- a/ddl/label/attributes_test.go +++ b/ddl/label/attributes_test.go @@ -126,7 +126,7 @@ func TestAddLabels(t *testing.T) { name string labels Labels label Label - err error + err bool } labels, err := NewLabels([]string{"merge_option=allow"}) @@ -145,12 +145,12 @@ func TestAddLabels(t *testing.T) { "normal", labels, label, - nil, + false, }, { "duplicated attributes, skip", l1, l2, - nil, + false, }, { "duplicated attributes, skip", @@ -159,24 +159,24 @@ func TestAddLabels(t *testing.T) { Value: "allow", }), label, - nil, + false, }, { "conflict attributes", l3, l2, - ErrConflictingAttributes, + true, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { err = test.labels.Add(test.label) - if test.err == nil { + if test.err { + require.Error(t, err) + } else { require.NoError(t, err) require.Equal(t, test.label, test.labels[len(test.labels)-1]) - } else { - require.ErrorIs(t, err, test.err) } }) } diff --git a/ddl/label/errors.go b/ddl/label/errors.go index 42ed053bc1a1c..430a767b9a43c 100644 --- a/ddl/label/errors.go +++ b/ddl/label/errors.go @@ -19,6 +19,4 @@ import "errors" var ( // ErrInvalidAttributesFormat is from attributes.go ErrInvalidAttributesFormat = errors.New("attributes should be in format 'key=value'") - // ErrConflictingAttributes is from attributes.go - ErrConflictingAttributes = errors.New("conflicting attributes") ) diff --git a/ddl/label/main_test.go b/ddl/label/main_test.go index 25784de1cd97e..570afb3bb4e05 100644 --- a/ddl/label/main_test.go +++ b/ddl/label/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/ddl/main_test.go b/ddl/main_test.go new file mode 100644 index 0000000000000..17d0940008ee0 --- /dev/null +++ b/ddl/main_test.go @@ -0,0 +1,102 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "os" + "strconv" + "testing" + "time" + + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/meta/autoid" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/testbridge" + "github.com/tikv/client-go/v2/tikv" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + tikv.EnableFailpoints() + + domain.SchemaOutOfDateRetryInterval.Store(50 * time.Millisecond) + domain.SchemaOutOfDateRetryTimes.Store(50) + + autoid.SetStep(5000) + ddl.ReorgWaitTimeout = 30 * time.Millisecond + ddl.SetBatchInsertDeleteRangeSize(2) + + config.UpdateGlobal(func(conf *config.Config) { + // Test for table lock. + conf.EnableTableLock = true + conf.Log.SlowThreshold = 10000 + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + conf.Experimental.AllowsExpressionIndex = true + }) + + _, err := infosync.GlobalInfoSyncerInit(context.Background(), "t", func() uint64 { return 1 }, nil, true) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "ddl: infosync.GlobalInfoSyncerInit: %v\n", err) + os.Exit(1) + } + + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + + goleak.VerifyTestMain(m, opts...) +} + +func wrapJobIDExtCallback(oldCallback ddl.Callback) *testDDLJobIDCallback { + return &testDDLJobIDCallback{ + Callback: oldCallback, + jobID: 0, + } +} + +func checkDelRangeCnt(tk *testkit.TestKit, jobID int64, cnt int) { + query := `select sum(cnt) from + (select count(1) cnt from mysql.gc_delete_range where job_id = ? union all + select count(1) cnt from mysql.gc_delete_range_done where job_id = ?) as gdr;` + tk.MustQuery(query, jobID, jobID).Check(testkit.Rows(strconv.Itoa(cnt))) +} + +type testDDLJobIDCallback struct { + ddl.Callback + jobID int64 +} + +func (t *testDDLJobIDCallback) OnJobUpdated(job *model.Job) { + if t.jobID == 0 { + t.jobID = job.ID + } + if t.Callback != nil { + t.Callback.OnJobUpdated(job) + } +} + +func (t *testDDLJobIDCallback) Clear() { + t.jobID = 0 +} diff --git a/ddl/mock.go b/ddl/mock.go index 48372be8641f7..7f470cc979a7f 100644 --- a/ddl/mock.go +++ b/ddl/mock.go @@ -26,7 +26,7 @@ import ( "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" ) var _ util.SchemaSyncer = &MockSchemaSyncer{} diff --git a/ddl/modify_column_test.go b/ddl/modify_column_test.go new file mode 100644 index 0000000000000..8c68b74b25aad --- /dev/null +++ b/ddl/modify_column_test.go @@ -0,0 +1,989 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" +) + +func batchInsert(tk *testkit.TestKit, tbl string, start, end int) { + dml := fmt.Sprintf("insert into %s values", tbl) + for i := start; i < end; i++ { + dml += fmt.Sprintf("(%d, %d, %d)", i, i, i) + if i != end-1 { + dml += "," + } + } + tk.MustExec(dml) +} + +func TestModifyColumnReorgInfo(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int, index idx(c2), index idx1(c1, c2));") + + sql := "alter table t1 change c2 c2 mediumint;" + // defaultBatchSize is equal to ddl.defaultBatchSize + base := defaultBatchSize * 8 + // add some rows + batchInsert(tk, "t1", 0, base) + // Make sure the count of regions more than backfill workers. + tk.MustQuery("split table t1 between (0) and (8192) regions 8;").Check(testkit.Rows("8 1")) + + tbl := external.GetTableByName(t, tk, "test", "t1") + + // Check insert null before job first update. + hook := &ddl.TestDDLCallback{Do: dom} + var checkErr error + var currJob *model.Job + var elements []*meta.Element + ctx := mock.NewContext() + ctx.Store = store + times := 0 + hook.OnJobRunBeforeExported = func(job *model.Job) { + if tbl.Meta().ID != job.TableID || checkErr != nil || job.SchemaState != model.StateWriteReorganization { + return + } + if job.Type == model.ActionModifyColumn { + if times == 0 { + times++ + return + } + currJob = job + var ( + newCol *model.ColumnInfo + oldColName *model.CIStr + modifyColumnTp byte + updatedAutoRandomBits uint64 + changingCol *model.ColumnInfo + changingIdxs []*model.IndexInfo + ) + pos := &ast.ColumnPosition{} + checkErr = job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs) + elements = ddl.BuildElements(changingCol, changingIdxs) + } + if job.Type == model.ActionAddIndex { + if times == 1 { + times++ + return + } + tbl := external.GetTableByName(t, tk, "test", "t1") + indexInfo := tbl.Meta().FindIndexByName("idx2") + elements = []*meta.Element{{ID: indexInfo.ID, TypeKey: meta.IndexElementKey}} + } + } + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("cantDecodeRecordErr")`)) + dom.DDL().SetHook(hook) + err := tk.ExecToErr(sql) + require.EqualError(t, err, "[ddl:8202]Cannot decode index value, because mock can't decode record error") + require.NoError(t, checkErr) + // Check whether the reorg information is cleaned up when executing "modify column" failed. + checkReorgHandle := func(gotElements, expectedElements []*meta.Element) { + for i, e := range gotElements { + require.Equal(t, expectedElements[i], e) + } + require.NoError(t, ctx.NewTxn(context.Background())) + txn, err := ctx.Txn(true) + require.NoError(t, err) + m := meta.NewMeta(txn) + e, start, end, physicalID, err := m.GetDDLReorgHandle(currJob) + require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err)) + require.Nil(t, e) + require.Nil(t, start) + require.Nil(t, end) + require.Zero(t, physicalID) + } + expectedElements := []*meta.Element{ + {ID: 4, TypeKey: meta.ColumnElementKey}, + {ID: 3, TypeKey: meta.IndexElementKey}, + {ID: 4, TypeKey: meta.IndexElementKey}} + checkReorgHandle(elements, expectedElements) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr")) + tk.MustExec("admin check table t1") + + // Check whether the reorg information is cleaned up when executing "modify column" successfully. + // Test encountering a "notOwnerErr" error which caused the processing backfill job to exit halfway. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("modifyColumnNotOwnerErr")`)) + tk.MustExec(sql) + expectedElements = []*meta.Element{ + {ID: 5, TypeKey: meta.ColumnElementKey}, + {ID: 5, TypeKey: meta.IndexElementKey}, + {ID: 6, TypeKey: meta.IndexElementKey}} + checkReorgHandle(elements, expectedElements) + tk.MustExec("admin check table t1") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr")) + + // Test encountering a "notOwnerErr" error which caused the processing backfill job to exit halfway. + // During the period, the old TiDB version(do not exist the element information) is upgraded to the new TiDB version. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr", `return("addIdxNotOwnerErr")`)) + tk.MustExec("alter table t1 add index idx2(c1)") + expectedElements = []*meta.Element{ + {ID: 7, TypeKey: meta.IndexElementKey}} + checkReorgHandle(elements, expectedElements) + tk.MustExec("admin check table t1") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockGetIndexRecordErr")) +} + +func TestModifyColumnNullToNotNullWithChangingVal2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockInsertValueAfterCheckNull", `return("insert into test.tt values (NULL, NULL)")`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockInsertValueAfterCheckNull")) + }() + + tk.MustExec("drop table if exists tt;") + tk.MustExec(`create table tt (a bigint, b int, unique index idx(a));`) + tk.MustExec("insert into tt values (1,1),(2,2),(3,3);") + err := tk.ExecToErr("alter table tt modify a int not null;") + require.EqualError(t, err, "[ddl:1265]Data truncated for column 'a' at row 1") + tk.MustExec("drop table tt") +} + +func TestModifyColumnNullToNotNull(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, 600*time.Millisecond) + defer clean() + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + + tk1.MustExec("use test") + tk2.MustExec("use test") + + tk1.MustExec("create table t1 (c1 int, c2 int)") + + tbl := external.GetTableByName(t, tk1, "test", "t1") + + // Check insert null before job first update. + hook := &ddl.TestDDLCallback{Do: dom} + tk1.MustExec("delete from t1") + once := sync.Once{} + var checkErr error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if tbl.Meta().ID != job.TableID { + return + } + once.Do(func() { + checkErr = tk2.ExecToErr("insert into t1 values ()") + }) + } + dom.DDL().SetHook(hook) + err := tk1.ExecToErr("alter table t1 change c2 c2 int not null") + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:1138]Invalid use of NULL value") + tk1.MustQuery("select * from t1").Check(testkit.Rows(" ")) + + // Check insert error when column has PreventNullInsertFlag. + tk1.MustExec("delete from t1") + hook.OnJobRunBeforeExported = func(job *model.Job) { + if tbl.Meta().ID != job.TableID { + return + } + + if job.State != model.JobStateRunning { + return + } + // now c2 has PreventNullInsertFlag, an error is expected. + checkErr = tk2.ExecToErr("insert into t1 values ()") + } + dom.DDL().SetHook(hook) + tk1.MustExec("alter table t1 change c2 c2 int not null") + require.EqualError(t, checkErr, "[table:1048]Column 'c2' cannot be null") + + c2 := external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) + require.True(t, mysql.HasNotNullFlag(c2.Flag)) + require.False(t, mysql.HasPreventNullInsertFlag(c2.Flag)) + err = tk1.ExecToErr("insert into t1 values ();") + require.EqualError(t, err, "[table:1364]Field 'c2' doesn't have a default value") +} + +func TestModifyColumnNullToNotNullWithChangingVal(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, 600*time.Millisecond) + defer clean() + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + + tk1.MustExec("use test") + tk2.MustExec("use test") + + tk1.MustExec("create table t1 (c1 int, c2 int)") + + tbl := external.GetTableByName(t, tk1, "test", "t1") + + // Check insert null before job first update. + hook := &ddl.TestDDLCallback{Do: dom} + tk1.MustExec("delete from t1") + once := sync.Once{} + var checkErr error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if tbl.Meta().ID != job.TableID { + return + } + once.Do(func() { + checkErr = tk2.ExecToErr("insert into t1 values ()") + }) + } + dom.DDL().SetHook(hook) + err := tk1.ExecToErr("alter table t1 change c2 c2 tinyint not null") + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:1265]Data truncated for column 'c2' at row 1") + tk1.MustQuery("select * from t1").Check(testkit.Rows(" ")) + + // Check insert error when column has PreventNullInsertFlag. + tk1.MustExec("delete from t1") + hook.OnJobRunBeforeExported = func(job *model.Job) { + if tbl.Meta().ID != job.TableID { + return + } + + if job.State != model.JobStateRunning { + return + } + // now c2 has PreventNullInsertFlag, an error is expected. + checkErr = tk2.ExecToErr("insert into t1 values ()") + } + dom.DDL().SetHook(hook) + tk1.MustExec("alter table t1 change c2 c2 tinyint not null") + require.EqualError(t, checkErr, "[table:1048]Column 'c2' cannot be null") + + c2 := external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) + require.True(t, mysql.HasNotNullFlag(c2.Flag)) + require.False(t, mysql.HasPreventNullInsertFlag(c2.Flag)) + require.EqualError(t, tk1.ExecToErr("insert into t1 values ()"), "[table:1364]Field 'c2' doesn't have a default value") + + c2 = external.GetModifyColumn(t, tk1, "test", "t1", "c2", false) + require.Equal(t, mysql.TypeTiny, c2.FieldType.Tp) +} + +func TestModifyColumnBetweenStringTypes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // varchar to varchar + tk.MustExec("create table tt (a varchar(10));") + tk.MustExec("insert into tt values ('111'),('10000');") + tk.MustExec("alter table tt change a a varchar(5);") + mvc := external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, 5, mvc.FieldType.Flen) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustGetErrMsg("alter table tt change a a varchar(4);", "[types:1265]Data truncated for column 'a', value is '10000'") + tk.MustExec("alter table tt change a a varchar(100);") + tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) + + // char to char + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt (a char(10));") + tk.MustExec("insert into tt values ('111'),('10000');") + tk.MustExec("alter table tt change a a char(5);") + mc := external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, 5, mc.FieldType.Flen) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") + tk.MustExec("alter table tt change a a char(100);") + tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) + + // binary to binary + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt (a binary(10));") + tk.MustExec("insert into tt values ('111'),('10000');") + tk.MustGetErrMsg("alter table tt change a a binary(5);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") + mb := external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, 10, mb.FieldType.Flen) + tk.MustQuery("select * from tt").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00", "10000\x00\x00\x00\x00\x00")) + tk.MustGetErrMsg("alter table tt change a a binary(4);", "[types:1265]Data truncated for column 'a', value is '111\x00\x00\x00\x00\x00\x00\x00'") + tk.MustExec("alter table tt change a a binary(12);") + tk.MustQuery("select * from tt").Check(testkit.Rows("111\x00\x00\x00\x00\x00\x00\x00\x00\x00", "10000\x00\x00\x00\x00\x00\x00\x00")) + tk.MustQuery("select length(a) from tt").Check(testkit.Rows("12", "12")) + + // varbinary to varbinary + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt (a varbinary(10));") + tk.MustExec("insert into tt values ('111'),('10000');") + tk.MustExec("alter table tt change a a varbinary(5);") + mvb := external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, 5, mvb.FieldType.Flen) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustGetErrMsg("alter table tt change a a varbinary(4);", "[types:1265]Data truncated for column 'a', value is '10000'") + tk.MustExec("alter table tt change a a varbinary(12);") + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustQuery("select length(a) from tt").Check(testkit.Rows("3", "5")) + + // varchar to char + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt (a varchar(10));") + tk.MustExec("insert into tt values ('111'),('10000');") + + tk.MustExec("alter table tt change a a char(10);") + c2 := external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, mysql.TypeString, c2.FieldType.Tp) + require.Equal(t, 10, c2.FieldType.Flen) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustGetErrMsg("alter table tt change a a char(4);", "[types:1265]Data truncated for column 'a', value is '10000'") + + // char to text + tk.MustExec("alter table tt change a a text;") + c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, mysql.TypeBlob, c2.FieldType.Tp) + + // text to set + tk.MustGetErrMsg("alter table tt change a a set('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") + tk.MustExec("alter table tt change a a set('111', '10000');") + c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, mysql.TypeSet, c2.FieldType.Tp) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + + // set to set + tk.MustExec("alter table tt change a a set('10000', '111');") + c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, mysql.TypeSet, c2.FieldType.Tp) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + + // set to enum + tk.MustGetErrMsg("alter table tt change a a enum('111', '2222');", "[types:1265]Data truncated for column 'a', value is '10000'") + tk.MustExec("alter table tt change a a enum('111', '10000');") + c2 = external.GetModifyColumn(t, tk, "test", "tt", "a", false) + require.Equal(t, mysql.TypeEnum, c2.FieldType.Tp) + tk.MustQuery("select * from tt").Check(testkit.Rows("111", "10000")) + tk.MustExec("alter table tt change a a enum('10000', '111');") + tk.MustQuery("select * from tt where a = 1").Check(testkit.Rows("10000")) + tk.MustQuery("select * from tt where a = 2").Check(testkit.Rows("111")) + + // no-strict mode + tk.MustExec(`set @@sql_mode="";`) + tk.MustExec("alter table tt change a a enum('111', '2222');") + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1265|Data truncated for column 'a', value is '10000'")) + + tk.MustExec("drop table tt;") +} + +func TestModifyColumnCharset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t_mcc(a varchar(8) charset utf8, b varchar(8) charset utf8)") + + result := tk.MustQuery(`show create table t_mcc`) + result.Check(testkit.Rows( + "t_mcc CREATE TABLE `t_mcc` (\n" + + " `a` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n" + + " `b` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + tk.MustExec("alter table t_mcc modify column a varchar(8);") + tbl := external.GetTableByName(t, tk, "test", "t_mcc") + tbl.Meta().Version = model.TableInfoVersion0 + // When the table version is TableInfoVersion0, the following statement don't change "b" charset. + // So the behavior is not compatible with MySQL. + tk.MustExec("alter table t_mcc modify column b varchar(8);") + result = tk.MustQuery(`show create table t_mcc`) + result.Check(testkit.Rows( + "t_mcc CREATE TABLE `t_mcc` (\n" + + " `a` varchar(8) DEFAULT NULL,\n" + + " `b` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + +} + +func TestModifyColumnTime_TimeToYear(t *testing.T) { + outOfRangeCode := uint16(1264) + tests := []testModifyColumnTimeCase{ + // time to year, it's reasonable to return current year and discard the time (even if MySQL may get data out of range error). + {"time", `"30 20:00:12"`, "year", "", outOfRangeCode}, + {"time", `"30 20:00"`, "year", "", outOfRangeCode}, + {"time", `"30 20"`, "year", "", outOfRangeCode}, + {"time", `"20:00:12"`, "year", "", outOfRangeCode}, + {"time", `"20:00"`, "year", "", outOfRangeCode}, + {"time", `"12"`, "year", "2012", 0}, + {"time", `"200012"`, "year", "", outOfRangeCode}, + {"time", `200012`, "year", "", outOfRangeCode}, + {"time", `0012`, "year", "2012", 0}, + {"time", `12`, "year", "2012", 0}, + {"time", `"30 20:00:12.498"`, "year", "", outOfRangeCode}, + {"time", `"20:00:12.498"`, "year", "", outOfRangeCode}, + {"time", `"200012.498"`, "year", "", outOfRangeCode}, + {"time", `200012.498`, "year", "", outOfRangeCode}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimeToDate(t *testing.T) { + now := time.Now().UTC() + now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + timeToDate1 := now.Format("2006-01-02") + timeToDate2 := now.AddDate(0, 0, 30).Format("2006-01-02") + tests := []testModifyColumnTimeCase{ + // time to date + {"time", `"30 20:00:12"`, "date", timeToDate2, 0}, + {"time", `"30 20:00"`, "date", timeToDate2, 0}, + {"time", `"30 20"`, "date", timeToDate2, 0}, + {"time", `"20:00:12"`, "date", timeToDate1, 0}, + {"time", `"20:00"`, "date", timeToDate1, 0}, + {"time", `"12"`, "date", timeToDate1, 0}, + {"time", `"200012"`, "date", timeToDate1, 0}, + {"time", `200012`, "date", timeToDate1, 0}, + {"time", `0012`, "date", timeToDate1, 0}, + {"time", `12`, "date", timeToDate1, 0}, + {"time", `"30 20:00:12.498"`, "date", timeToDate2, 0}, + {"time", `"20:00:12.498"`, "date", timeToDate1, 0}, + {"time", `"200012.498"`, "date", timeToDate1, 0}, + {"time", `200012.498`, "date", timeToDate1, 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimeToDatetime(t *testing.T) { + now := time.Now().UTC() + now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + timeToDatetime1 := now.Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToDatetime2 := now.Add(20 * time.Hour).Format("2006-01-02 15:04:05") + timeToDatetime3 := now.Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToDatetime4 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToDatetime5 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Format("2006-01-02 15:04:05") + tests := []testModifyColumnTimeCase{ + // time to datetime + {"time", `"30 20:00:12"`, "datetime", timeToDatetime4, 0}, + {"time", `"30 20:00"`, "datetime", timeToDatetime5, 0}, + {"time", `"30 20"`, "datetime", timeToDatetime5, 0}, + {"time", `"20:00:12"`, "datetime", timeToDatetime1, 0}, + {"time", `"20:00"`, "datetime", timeToDatetime2, 0}, + {"time", `"12"`, "datetime", timeToDatetime3, 0}, + {"time", `"200012"`, "datetime", timeToDatetime1, 0}, + {"time", `200012`, "datetime", timeToDatetime1, 0}, + {"time", `0012`, "datetime", timeToDatetime3, 0}, + {"time", `12`, "datetime", timeToDatetime3, 0}, + {"time", `"30 20:00:12.498"`, "datetime", timeToDatetime4, 0}, + {"time", `"20:00:12.498"`, "datetime", timeToDatetime1, 0}, + {"time", `"200012.498"`, "datetime", timeToDatetime1, 0}, + {"time", `200012.498`, "datetime", timeToDatetime1, 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimeToTimestamp(t *testing.T) { + now := time.Now().UTC() + now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + timeToTimestamp1 := now.Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToTimestamp2 := now.Add(20 * time.Hour).Format("2006-01-02 15:04:05") + timeToTimestamp3 := now.Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToTimestamp4 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Add(12 * time.Second).Format("2006-01-02 15:04:05") + timeToTimestamp5 := now.AddDate(0, 0, 30).Add(20 * time.Hour).Format("2006-01-02 15:04:05") + tests := []testModifyColumnTimeCase{ + // time to timestamp + {"time", `"30 20:00:12"`, "timestamp", timeToTimestamp4, 0}, + {"time", `"30 20:00"`, "timestamp", timeToTimestamp5, 0}, + {"time", `"30 20"`, "timestamp", timeToTimestamp5, 0}, + {"time", `"20:00:12"`, "timestamp", timeToTimestamp1, 0}, + {"time", `"20:00"`, "timestamp", timeToTimestamp2, 0}, + {"time", `"12"`, "timestamp", timeToTimestamp3, 0}, + {"time", `"200012"`, "timestamp", timeToTimestamp1, 0}, + {"time", `200012`, "timestamp", timeToTimestamp1, 0}, + {"time", `0012`, "timestamp", timeToTimestamp3, 0}, + {"time", `12`, "timestamp", timeToTimestamp3, 0}, + {"time", `"30 20:00:12.498"`, "timestamp", timeToTimestamp4, 0}, + {"time", `"20:00:12.498"`, "timestamp", timeToTimestamp1, 0}, + {"time", `"200012.498"`, "timestamp", timeToTimestamp1, 0}, + {"time", `200012.498`, "timestamp", timeToTimestamp1, 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DateToTime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // date to time + {"date", `"2019-01-02"`, "time", "00:00:00", 0}, + {"date", `"19-01-02"`, "time", "00:00:00", 0}, + {"date", `"20190102"`, "time", "00:00:00", 0}, + {"date", `"190102"`, "time", "00:00:00", 0}, + {"date", `20190102`, "time", "00:00:00", 0}, + {"date", `190102`, "time", "00:00:00", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DateToYear(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // date to year + {"date", `"2019-01-02"`, "year", "2019", 0}, + {"date", `"19-01-02"`, "year", "2019", 0}, + {"date", `"20190102"`, "year", "2019", 0}, + {"date", `"190102"`, "year", "2019", 0}, + {"date", `20190102`, "year", "2019", 0}, + {"date", `190102`, "year", "2019", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DateToDatetime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // date to datetime + {"date", `"2019-01-02"`, "datetime", "2019-01-02 00:00:00", 0}, + {"date", `"19-01-02"`, "datetime", "2019-01-02 00:00:00", 0}, + {"date", `"20190102"`, "datetime", "2019-01-02 00:00:00", 0}, + {"date", `"190102"`, "datetime", "2019-01-02 00:00:00", 0}, + {"date", `20190102`, "datetime", "2019-01-02 00:00:00", 0}, + {"date", `190102`, "datetime", "2019-01-02 00:00:00", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DateToTimestamp(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // date to timestamp + {"date", `"2019-01-02"`, "timestamp", "2019-01-02 00:00:00", 0}, + {"date", `"19-01-02"`, "timestamp", "2019-01-02 00:00:00", 0}, + {"date", `"20190102"`, "timestamp", "2019-01-02 00:00:00", 0}, + {"date", `"190102"`, "timestamp", "2019-01-02 00:00:00", 0}, + {"date", `20190102`, "timestamp", "2019-01-02 00:00:00", 0}, + {"date", `190102`, "timestamp", "2019-01-02 00:00:00", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimestampToYear(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // timestamp to year + {"timestamp", `"2006-01-02 15:04:05"`, "year", "2006", 0}, + {"timestamp", `"06-01-02 15:04:05"`, "year", "2006", 0}, + {"timestamp", `"20060102150405"`, "year", "2006", 0}, + {"timestamp", `"060102150405"`, "year", "2006", 0}, + {"timestamp", `20060102150405`, "year", "2006", 0}, + {"timestamp", `060102150405`, "year", "2006", 0}, + {"timestamp", `"2006-01-02 23:59:59.506"`, "year", "2006", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimestampToTime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // timestamp to time + {"timestamp", `"2006-01-02 15:04:05"`, "time", "15:04:05", 0}, + {"timestamp", `"06-01-02 15:04:05"`, "time", "15:04:05", 0}, + {"timestamp", `"20060102150405"`, "time", "15:04:05", 0}, + {"timestamp", `"060102150405"`, "time", "15:04:05", 0}, + {"timestamp", `20060102150405`, "time", "15:04:05", 0}, + {"timestamp", `060102150405`, "time", "15:04:05", 0}, + {"timestamp", `"2006-01-02 23:59:59.506"`, "time", "00:00:00", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimestampToDate(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // timestamp to date + {"timestamp", `"2006-01-02 15:04:05"`, "date", "2006-01-02", 0}, + {"timestamp", `"06-01-02 15:04:05"`, "date", "2006-01-02", 0}, + {"timestamp", `"20060102150405"`, "date", "2006-01-02", 0}, + {"timestamp", `"060102150405"`, "date", "2006-01-02", 0}, + {"timestamp", `20060102150405`, "date", "2006-01-02", 0}, + {"timestamp", `060102150405`, "date", "2006-01-02", 0}, + {"timestamp", `"2006-01-02 23:59:59.506"`, "date", "2006-01-03", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_TimestampToDatetime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // timestamp to datetime + {"timestamp", `"2006-01-02 15:04:05"`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `"06-01-02 15:04:05"`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `"20060102150405"`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `"060102150405"`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `20060102150405`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `060102150405`, "datetime", "2006-01-02 15:04:05", 0}, + {"timestamp", `"2006-01-02 23:59:59.506"`, "datetime", "2006-01-03 00:00:00", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DatetimeToYear(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // datetime to year + {"datetime", `"2006-01-02 15:04:05"`, "year", "2006", 0}, + {"datetime", `"06-01-02 15:04:05"`, "year", "2006", 0}, + {"datetime", `"20060102150405"`, "year", "2006", 0}, + {"datetime", `"060102150405"`, "year", "2006", 0}, + {"datetime", `20060102150405`, "year", "2006", 0}, + {"datetime", `060102150405`, "year", "2006", 0}, + {"datetime", `"2006-01-02 23:59:59.506"`, "year", "2006", 0}, + {"datetime", `"1000-01-02 23:59:59"`, "year", "", errno.ErrWarnDataOutOfRange}, + {"datetime", `"9999-01-02 23:59:59"`, "year", "", errno.ErrWarnDataOutOfRange}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DatetimeToTime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // datetime to time + {"datetime", `"2006-01-02 15:04:05"`, "time", "15:04:05", 0}, + {"datetime", `"06-01-02 15:04:05"`, "time", "15:04:05", 0}, + {"datetime", `"20060102150405"`, "time", "15:04:05", 0}, + {"datetime", `"060102150405"`, "time", "15:04:05", 0}, + {"datetime", `20060102150405`, "time", "15:04:05", 0}, + {"datetime", `060102150405`, "time", "15:04:05", 0}, + {"datetime", `"2006-01-02 23:59:59.506"`, "time", "00:00:00", 0}, + {"datetime", `"1000-01-02 23:59:59"`, "time", "23:59:59", 0}, + {"datetime", `"9999-01-02 23:59:59"`, "time", "23:59:59", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DatetimeToDate(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // datetime to date + {"datetime", `"2006-01-02 15:04:05"`, "date", "2006-01-02", 0}, + {"datetime", `"06-01-02 15:04:05"`, "date", "2006-01-02", 0}, + {"datetime", `"20060102150405"`, "date", "2006-01-02", 0}, + {"datetime", `"060102150405"`, "date", "2006-01-02", 0}, + {"datetime", `20060102150405`, "date", "2006-01-02", 0}, + {"datetime", `060102150405`, "date", "2006-01-02", 0}, + {"datetime", `"2006-01-02 23:59:59.506"`, "date", "2006-01-03", 0}, + {"datetime", `"1000-01-02 23:59:59"`, "date", "1000-01-02", 0}, + {"datetime", `"9999-01-02 23:59:59"`, "date", "9999-01-02", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_DatetimeToTimestamp(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // datetime to timestamp + {"datetime", `"2006-01-02 15:04:05"`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `"06-01-02 15:04:05"`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `"20060102150405"`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `"060102150405"`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `20060102150405`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `060102150405`, "timestamp", "2006-01-02 15:04:05", 0}, + {"datetime", `"2006-01-02 23:59:59.506"`, "timestamp", "2006-01-03 00:00:00", 0}, + {"datetime", `"1971-01-02 23:59:59"`, "timestamp", "1971-01-02 23:59:59", 0}, + {"datetime", `"2009-01-02 23:59:59"`, "timestamp", "2009-01-02 23:59:59", 0}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_YearToTime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // year to time + // failed cases are not handled by TiDB + {"year", `"2019"`, "time", "00:20:19", 0}, + {"year", `2019`, "time", "00:20:19", 0}, + {"year", `"00"`, "time", "00:20:00", 0}, + {"year", `"69"`, "time", "", errno.ErrTruncatedWrongValue}, + {"year", `"70"`, "time", "", errno.ErrTruncatedWrongValue}, + {"year", `"99"`, "time", "", errno.ErrTruncatedWrongValue}, + {"year", `00`, "time", "00:00:00", 0}, + {"year", `69`, "time", "", errno.ErrTruncatedWrongValue}, + {"year", `70`, "time", "", errno.ErrTruncatedWrongValue}, + {"year", `99`, "time", "", errno.ErrTruncatedWrongValue}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_YearToDate(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // year to date + {"year", `"2019"`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `2019`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `"00"`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `"69"`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `"70"`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `"99"`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `00`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `69`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `70`, "date", "", errno.ErrTruncatedWrongValue}, + {"year", `99`, "date", "", errno.ErrTruncatedWrongValue}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_YearToDatetime(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // year to datetime + {"year", `"2019"`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `2019`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `"00"`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `"69"`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `"70"`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `"99"`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `00`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `69`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `70`, "datetime", "", errno.ErrTruncatedWrongValue}, + {"year", `99`, "datetime", "", errno.ErrTruncatedWrongValue}, + } + testModifyColumnTime(t, tests) +} + +func TestModifyColumnTime_YearToTimestamp(t *testing.T) { + tests := []testModifyColumnTimeCase{ + // year to timestamp + {"year", `"2019"`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `2019`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `"00"`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `"69"`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `"70"`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `"99"`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `00`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `69`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `70`, "timestamp", "", errno.ErrTruncatedWrongValue}, + {"year", `99`, "timestamp", "", errno.ErrTruncatedWrongValue}, + } + testModifyColumnTime(t, tests) +} + +type testModifyColumnTimeCase struct { + from string + value string + to string + expect string + err uint16 +} + +func testModifyColumnTime(t *testing.T, tests []testModifyColumnTimeCase) { + limit := variable.GetDDLErrorCountLimit() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_ddl_error_count_limit = 3") + + // Set time zone to UTC. + originalTz := tk.Session().GetSessionVars().TimeZone + tk.Session().GetSessionVars().TimeZone = time.UTC + defer func() { + tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %v", limit)) + tk.Session().GetSessionVars().TimeZone = originalTz + }() + + for _, test := range tests { + comment := fmt.Sprintf("%+v", test) + tk.MustExec("drop table if exists t_mc") + tk.MustExec(fmt.Sprintf("create table t_mc(a %s)", test.from)) + tk.MustExec(fmt.Sprintf(`insert into t_mc (a) values (%s)`, test.value)) + _, err := tk.Exec(fmt.Sprintf(`alter table t_mc modify a %s`, test.to)) + if test.err != 0 { + require.Error(t, err, comment) + require.Regexp(t, fmt.Sprintf(".*[ddl:%d].*", test.err), err.Error(), comment) + continue + } + require.NoError(t, err, comment) + tk.MustQuery("select a from t_mc").Check(testkit.Rows(test.expect)) + } +} + +func TestModifyColumnTypeWithWarnings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // Test normal warnings. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a decimal(5,2))") + tk.MustExec("insert into t values(111.22),(111.22),(111.22),(111.22),(333.4)") + // 111.22 will be truncated the fraction .22 as .2 with truncated warning for each row. + tk.MustExec("alter table t modify column a decimal(4,1)") + // there should 4 rows of warnings corresponding to the origin rows. + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect DECIMAL value: '111.22'", + "Warning 1292 Truncated incorrect DECIMAL value: '111.22'", + "Warning 1292 Truncated incorrect DECIMAL value: '111.22'", + "Warning 1292 Truncated incorrect DECIMAL value: '111.22'")) + + // Test the strict warnings is treated as errors under the strict mode. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a decimal(5,2))") + tk.MustExec("insert into t values(111.22),(111.22),(111.22),(33.4)") + // Since modify column a from decimal(5,2) to decimal(3,1), the first three rows with 111.22 will overflows the target types. + err := tk.ExecToErr("alter table t modify column a decimal(3,1)") + require.EqualError(t, err, "[types:1690]DECIMAL value is out of range in '(3, 1)'") + + // Test the strict warnings is treated as warnings under the non-strict mode. + tk.MustExec("set @@sql_mode=\"\"") + tk.MustExec("alter table t modify column a decimal(3,1)") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1690 DECIMAL value is out of range in '(3, 1)'", + "Warning 1690 DECIMAL value is out of range in '(3, 1)'", + "Warning 1690 DECIMAL value is out of range in '(3, 1)'")) +} + +// TestModifyColumnTypeWhenInterception is to test modifying column type with warnings intercepted by +// reorg timeout, not owner error and so on. +func TestModifyColumnTypeWhenInterception(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // Test normal warnings. + tk.MustExec("create table t(a int primary key, b decimal(4,2))") + + count := defaultBatchSize * 4 + // Add some rows. + dml := "insert into t values" + for i := 1; i <= count; i++ { + dml += fmt.Sprintf("(%d, %f)", i, 11.22) + if i != count { + dml += "," + } + } + tk.MustExec(dml) + // Make the regions scale like: [1, 1024), [1024, 2048), [2048, 3072), [3072, 4096] + tk.MustQuery("split table t between(0) and (4096) regions 4") + + d := dom.DDL() + hook := &ddl.TestDDLCallback{} + var checkMiddleWarningCount bool + var checkMiddleAddedCount bool + // Since the `DefTiDBDDLReorgWorkerCount` is 4, every worker will be assigned with one region + // for the first time. Here we mock the insert failure/reorg timeout in region [2048, 3072) + // which will lead next handle be set to 2048 and partial warnings be stored into ddl job. + // Since the existence of reorg batch size, only the last reorg batch [2816, 3072) of kv + // range [2048, 3072) fail to commit, the rest of them all committed successfully. So the + // addedCount and warnings count in the job are all equal to `4096 - reorg batch size`. + // In the next round of this ddl job, the last reorg batch will be finished. + var middleWarningsCount = int64(defaultBatchSize*4 - defaultReorgBatchSize) + hook.OnJobUpdatedExported = func(job *model.Job) { + if job.SchemaState == model.StateWriteReorganization || job.SnapshotVer != 0 { + if len(job.ReorgMeta.WarningsCount) == len(job.ReorgMeta.Warnings) { + for _, v := range job.ReorgMeta.WarningsCount { + if v == middleWarningsCount { + checkMiddleWarningCount = true + } + } + } + if job.RowCount == middleWarningsCount { + checkMiddleAddedCount = true + } + } + } + d.SetHook(hook) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/MockReorgTimeoutInOneRegion", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/MockReorgTimeoutInOneRegion")) + }() + tk.MustExec("alter table t modify column b decimal(3,1)") + require.True(t, checkMiddleWarningCount) + require.True(t, checkMiddleAddedCount) + + res := tk.MustQuery("show warnings") + require.Len(t, res.Rows(), count) +} + +func TestModifyColumnRollBack(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int default 1, index (c1))") + + var c2 *table.Column + var checkErr error + hook := &ddl.TestDDLCallback{Do: dom} + hook.OnJobUpdatedExported = func(job *model.Job) { + if checkErr != nil { + return + } + + tbl := external.GetTableByName(t, tk, "test", "t1") + for _, col := range tbl.Cols() { + if col.Name.L == "c2" { + c2 = col + } + } + if mysql.HasPreventNullInsertFlag(c2.Flag) { + tk.MustGetErrCode("insert into t1(c2) values (null);", errno.ErrBadNull) + } + + hookCtx := mock.NewContext() + hookCtx.Store = store + err := hookCtx.NewTxn(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + return + } + + jobIDs := []int64{job.ID} + txn, err := hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + errs, err := admin.CancelJobs(txn, jobIDs) + if err != nil { + checkErr = errors.Trace(err) + return + } + // It only tests cancel one DDL job. + if errs[0] != nil { + checkErr = errors.Trace(errs[0]) + return + } + + txn, err = hookCtx.Txn(true) + if err != nil { + checkErr = errors.Trace(err) + return + } + err = txn.Commit(context.Background()) + if err != nil { + checkErr = errors.Trace(err) + } + } + + dom.DDL().SetHook(hook) + done := make(chan error, 1) + go backgroundExec(store, "alter table test.t1 change c2 c2 bigint not null;", done) + + err := <-done + require.EqualError(t, err, "[ddl:8214]Cancelled DDL job") + tk.MustExec("insert into t1(c2) values (null);") + + tbl := external.GetTableByName(t, tk, "test", "t1") //nolint:typecheck + for _, col := range tbl.Cols() { + if col.Name.L == "c2" { + c2 = col + } + } + require.False(t, mysql.HasNotNullFlag(c2.Flag)) + tk.MustExec("drop table t1") +} diff --git a/ddl/multi_schema_change.go b/ddl/multi_schema_change.go new file mode 100644 index 0000000000000..88968b486d8fa --- /dev/null +++ b/ddl/multi_schema_change.go @@ -0,0 +1,343 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl + +import ( + "sync" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/util/dbterror" +) + +func (d *ddl) MultiSchemaChange(ctx sessionctx.Context, ti ast.Ident) error { + schema, t, err := d.getSchemaAndTableByIdent(ctx, ti) + if err != nil { + return errors.Trace(err) + } + job := &model.Job{ + SchemaID: schema.ID, + TableID: t.Meta().ID, + SchemaName: schema.Name.L, + Type: model.ActionMultiSchemaChange, + BinlogInfo: &model.HistoryInfo{}, + Args: nil, + MultiSchemaInfo: ctx.GetSessionVars().StmtCtx.MultiSchemaInfo, + } + err = checkMultiSchemaInfo(ctx.GetSessionVars().StmtCtx.MultiSchemaInfo, t) + if err != nil { + return errors.Trace(err) + } + ctx.GetSessionVars().StmtCtx.MultiSchemaInfo = nil + err = d.DoDDLJob(ctx, job) + return d.callHookOnChanged(err) +} + +func onMultiSchemaChange(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { + if job.MultiSchemaInfo.Revertible { + // Handle the rolling back job. + if job.IsRollingback() { + // Rollback/cancel the sub-jobs in reverse order. + for i := len(job.MultiSchemaInfo.SubJobs) - 1; i >= 0; i-- { + sub := job.MultiSchemaInfo.SubJobs[i] + if isFinished(sub) { + continue + } + proxyJob := cloneFromSubJob(job, sub) + ver, err = w.runDDLJob(d, t, proxyJob) + mergeBackToSubJob(proxyJob, sub) + if i == 0 && isFinished(sub) { + job.State = model.JobStateRollbackDone + } + return ver, err + } + // The last rollback/cancelling sub-job is done. + job.State = model.JobStateRollbackDone + return ver, nil + } + + // The sub-jobs are normally running. + // Run the first executable sub-job. + for i, sub := range job.MultiSchemaInfo.SubJobs { + if !sub.Revertible || isFinished(sub) { + // Skip the sub jobs which related schema states + // are in the last revertible point. + // If a sub job is finished here, it should be a noop job. + continue + } + proxyJob := cloneFromSubJob(job, sub) + ver, err = w.runDDLJob(d, t, proxyJob) + mergeBackToSubJob(proxyJob, sub) + handleRevertibleException(job, sub, i, proxyJob.Error) + return ver, err + } + // All the sub-jobs are non-revertible. + job.MultiSchemaInfo.Revertible = false + // Step the sub-jobs to the non-revertible states all at once. + for _, sub := range job.MultiSchemaInfo.SubJobs { + if isFinished(sub) { + continue + } + proxyJob := cloneFromSubJob(job, sub) + ver, err = w.runDDLJob(d, t, proxyJob) + mergeBackToSubJob(proxyJob, sub) + } + return ver, err + } + // Run the rest non-revertible sub-jobs one by one. + for _, sub := range job.MultiSchemaInfo.SubJobs { + if isFinished(sub) { + continue + } + proxyJob := cloneFromSubJob(job, sub) + ver, err = w.runDDLJob(d, t, proxyJob) + mergeBackToSubJob(proxyJob, sub) + return ver, err + } + job.State = model.JobStateDone + return ver, err +} + +func isFinished(job *model.SubJob) bool { + return job.State == model.JobStateDone || + job.State == model.JobStateRollbackDone || + job.State == model.JobStateCancelled +} + +func cloneFromSubJob(job *model.Job, sub *model.SubJob) *model.Job { + return &model.Job{ + ID: job.ID, + Type: sub.Type, + SchemaID: job.SchemaID, + TableID: job.TableID, + SchemaName: job.SchemaName, + State: sub.State, + Warning: sub.Warning, + Error: nil, + ErrorCount: 0, + RowCount: sub.RowCount, + Mu: sync.Mutex{}, + CtxVars: sub.CtxVars, + Args: sub.Args, + RawArgs: sub.RawArgs, + SchemaState: sub.SchemaState, + SnapshotVer: sub.SnapshotVer, + RealStartTS: job.RealStartTS, + StartTS: job.StartTS, + DependencyID: job.DependencyID, + Query: job.Query, + BinlogInfo: job.BinlogInfo, + Version: job.Version, + ReorgMeta: job.ReorgMeta, + MultiSchemaInfo: &model.MultiSchemaInfo{Revertible: sub.Revertible}, + Priority: job.Priority, + SeqNum: job.SeqNum, + } +} + +func mergeBackToSubJob(job *model.Job, sub *model.SubJob) { + sub.Revertible = job.MultiSchemaInfo.Revertible + sub.SchemaState = job.SchemaState + sub.SnapshotVer = job.SnapshotVer + sub.Args = job.Args + sub.State = job.State + sub.Warning = job.Warning + sub.RowCount = job.RowCount +} + +func handleRevertibleException(job *model.Job, subJob *model.SubJob, idx int, err *terror.Error) { + if !isAbnormal(subJob) { + return + } + job.State = model.JobStateRollingback + job.Error = err + // Flush the cancelling state and cancelled state to sub-jobs. + for _, sub := range job.MultiSchemaInfo.SubJobs { + switch sub.State { + case model.JobStateRunning: + sub.State = model.JobStateCancelling + case model.JobStateNone: + sub.State = model.JobStateCancelled + } + } +} + +func isAbnormal(job *model.SubJob) bool { + return job.State == model.JobStateCancelling || + job.State == model.JobStateCancelled || + job.State == model.JobStateRollingback || + job.State == model.JobStateRollbackDone +} + +func appendToSubJobs(m *model.MultiSchemaInfo, job *model.Job) error { + err := fillMultiSchemaInfo(m, job) + if err != nil { + return err + } + m.SubJobs = append(m.SubJobs, &model.SubJob{ + Type: job.Type, + Args: job.Args, + RawArgs: job.RawArgs, + SchemaState: job.SchemaState, + SnapshotVer: job.SnapshotVer, + Revertible: true, + CtxVars: job.CtxVars, + }) + return nil +} + +func fillMultiSchemaInfo(info *model.MultiSchemaInfo, job *model.Job) (err error) { + switch job.Type { + case model.ActionAddColumn: + col := job.Args[0].(*table.Column) + pos := job.Args[1].(*ast.ColumnPosition) + info.AddColumns = append(info.AddColumns, col.Name) + if pos != nil && pos.Tp == ast.ColumnPositionAfter { + info.RelativeColumns = append(info.RelativeColumns, pos.RelativeColumn.Name) + } + case model.ActionDropColumn: + colName := job.Args[0].(model.CIStr) + info.DropColumns = append(info.DropColumns, colName) + case model.ActionDropIndex, model.ActionDropPrimaryKey: + indexName := job.Args[0].(model.CIStr) + info.DropIndexes = append(info.DropIndexes, indexName) + case model.ActionAddIndex, model.ActionAddPrimaryKey: + indexName := job.Args[1].(model.CIStr) + indexPartSpecifications := job.Args[2].([]*ast.IndexPartSpecification) + info.AddIndexes = append(info.AddIndexes, indexName) + for _, indexPartSpecification := range indexPartSpecifications { + info.RelativeColumns = append(info.RelativeColumns, indexPartSpecification.Column.Name) + } + case model.ActionRenameIndex: + from := job.Args[0].(model.CIStr) + to := job.Args[1].(model.CIStr) + info.AddIndexes = append(info.AddIndexes, to) + info.DropIndexes = append(info.DropIndexes, from) + case model.ActionModifyColumn: + newCol := *job.Args[0].(**model.ColumnInfo) + oldColName := job.Args[1].(model.CIStr) + pos := job.Args[2].(*ast.ColumnPosition) + if newCol.Name.L != oldColName.L { + info.AddColumns = append(info.AddColumns, newCol.Name) + info.DropColumns = append(info.DropColumns, oldColName) + } else { + info.RelativeColumns = append(info.RelativeColumns, newCol.Name) + } + if pos != nil && pos.Tp == ast.ColumnPositionAfter { + info.RelativeColumns = append(info.RelativeColumns, pos.RelativeColumn.Name) + } + default: + return dbterror.ErrRunMultiSchemaChanges + } + return nil +} + +func checkOperateSameColumn(info *model.MultiSchemaInfo) error { + modifyCols := make(map[string]struct{}) + modifyIdx := make(map[string]struct{}) + + checkColumns := func(colNames []model.CIStr, addToModifyCols bool) error { + for _, colName := range colNames { + name := colName.L + if _, ok := modifyCols[name]; ok { + return dbterror.ErrOperateSameColumn.GenWithStackByArgs(name) + } + if addToModifyCols { + modifyCols[name] = struct{}{} + } + } + return nil + } + + checkIndexes := func(idxNames []model.CIStr, addToModifyIdx bool) error { + for _, idxName := range idxNames { + name := idxName.L + if _, ok := modifyIdx[name]; ok { + return dbterror.ErrOperateSameColumn.GenWithStackByArgs(name) + } + if addToModifyIdx { + modifyIdx[name] = struct{}{} + } + } + return nil + } + + if err := checkColumns(info.AddColumns, true); err != nil { + return err + } + if err := checkColumns(info.DropColumns, true); err != nil { + return err + } + if err := checkIndexes(info.AddIndexes, true); err != nil { + return err + } + if err := checkIndexes(info.DropIndexes, true); err != nil { + return err + } + + return checkColumns(info.RelativeColumns, false) +} + +func checkMultiSchemaInfo(info *model.MultiSchemaInfo, t table.Table) error { + err := checkOperateSameColumn(info) + if err != nil { + return err + } + + err = checkVisibleColumnCnt(t, len(info.AddColumns), len(info.DropColumns)) + if err != nil { + return err + } + + return checkAddColumnTooManyColumns(len(t.Cols()) + len(info.AddColumns) - len(info.DropColumns)) +} + +func appendMultiChangeWarningsToOwnerCtx(ctx sessionctx.Context, job *model.Job) { + if job.MultiSchemaInfo == nil || job.Type != model.ActionMultiSchemaChange { + return + } + for _, sub := range job.MultiSchemaInfo.SubJobs { + if sub.Warning != nil { + ctx.GetSessionVars().StmtCtx.AppendNote(sub.Warning) + } + } +} + +// rollingBackMultiSchemaChange updates a multi-schema change job +// from cancelling state to rollingback state. +func rollingBackMultiSchemaChange(job *model.Job) error { + if !job.MultiSchemaInfo.Revertible { + // Cannot rolling back because the jobs are non-revertible. + // Resume the job state to running. + job.State = model.JobStateRunning + return nil + } + // Mark all the jobs to cancelling. + for _, sub := range job.MultiSchemaInfo.SubJobs { + switch sub.State { + case model.JobStateRunning: + sub.State = model.JobStateCancelling + case model.JobStateNone: + sub.State = model.JobStateCancelled + } + } + job.State = model.JobStateRollingback + return dbterror.ErrCancelledDDLJob +} diff --git a/ddl/multi_schema_change_test.go b/ddl/multi_schema_change_test.go new file mode 100644 index 0000000000000..bc07f98a27060 --- /dev/null +++ b/ddl/multi_schema_change_test.go @@ -0,0 +1,929 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "strconv" + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/admin" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMultiSchemaChangeAddColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + + // Test add multiple columns in multiple specs. + tk.MustExec("create table t (a int);") + tk.MustExec("insert into t values (1);") + tk.MustExec("alter table t add column b int default 2, add column c int default 3;") + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + + // Test add multiple columns in one spec. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int);") + tk.MustExec("insert into t values (1);") + tk.MustExec("alter table t add column (b int default 2, c int default 3);") + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("alter table t add column (d int default 4, e int default 5);") + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3 4 5")) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t add column if not exists (b int default 2, c int default 3);") + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + tk.MustExec("alter table t add column if not exists (c int default 3, d int default 4);") + tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1060 Duplicate column name 'c'")) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3 4")) + + // Test referencing previous column in multi-schema change is not supported. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int);") + tk.MustGetErrCode("alter table t add column b int after a, add column c int after b", errno.ErrBadField) + tk.MustGetErrCode("alter table t add column c int after b, add column b int", errno.ErrBadField) + + // Test add multiple columns with different position. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec(`alter table t + add column d int default 4 first, + add column e int default 5 after b, + add column f int default 6 after b;`) + tk.MustQuery("select * from t;").Check(testkit.Rows("4 1 2 6 5 3")) + + // Test [if not exists] for adding columns. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t add column b int default 2, add column if not exists a int;") + tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1060 Duplicate column name 'a'")) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2")) + + // Test add columns with same name + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, c int default 4);") + tk.MustGetErrCode("alter table t add column b int default 2, add column b int default 3", errno.ErrUnsupportedDDLOperation) +} + +func TestMultiSchemaChangeAddColumnsCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + originHook := dom.DDL().GetHook() + + tk.MustExec("create table t (a int);") + tk.MustExec("insert into t values (1);") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'c' is in write-reorg. + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(hook) + sql := "alter table t add column b int default 2, add column c int default 3, add column d int default 4;" + tk.MustGetErrCode(sql, errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + hook.MustCancelDone(t) + tk.MustQuery("select * from t;").Check(testkit.Rows("1")) +} + +func TestMultiSchemaChangeAddColumnsParallel(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + tk.MustExec("create table t (a int default 1);") + tk.MustExec("insert into t values ();") + putTheSameDDLJobTwice(t, func() { + tk.MustExec("alter table t add column if not exists b int default 2, " + + "add column if not exists c int default 3;") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Note 1060 Duplicate column name 'b'", + "Note 1060 Duplicate column name 'c'", + )) + }) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int);") + putTheSameDDLJobTwice(t, func() { + tk.MustGetErrCode("alter table t add column b int, add column c int;", errno.ErrDupFieldName) + }) +} + +func TestMultiSchemaChangeDropColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + + // Test drop all columns + tk.MustExec("create table t (a int, b int);") + tk.MustGetErrCode("alter table t drop column a, drop column b;", errno.ErrCantRemoveAllFields) + + // Test drop multiple columns in multiple specs + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, d int, e int);") + tk.MustExec("insert into t values (1, 2, 3, 4, 5);") + tk.MustExec("alter table t drop column a, drop column d, drop column b;") + tk.MustQuery("select * from t;").Check(testkit.Rows("3 5")) + + // Test drop same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, c int default 4);") + tk.MustGetErrCode("alter table t drop column a, drop column a", errno.ErrUnsupportedDDLOperation) + + // Test drop if exists column. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t drop column if exists c, drop column a;") + tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1091 Can't DROP 'c'; check that column/key exists")) + tk.MustQuery("select * from t;").Check(testkit.Rows("2")) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t drop column a, drop column if exists d, drop column c;") + tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1091 Can't DROP 'd'; check that column/key exists")) + tk.MustQuery("select * from t;").Check(testkit.Rows("2")) +} + +func TestMultiSchemaChangeDropColumnsCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + originHook := dom.DDL().GetHook() + + // Test for cancelling the job in a middle state. + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3, d int default 4);") + tk.MustExec("insert into t values ();") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'a' is in delete-reorg. + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StateDeleteReorganization + }) + dom.DDL().SetHook(hook) + tk.MustExec("alter table t drop column b, drop column a, drop column d;") + dom.DDL().SetHook(originHook) + hook.MustCancelFailed(t) + tk.MustQuery("select * from t;").Check(testkit.Rows("3")) + + // Test for cancelling the job in public. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3, d int default 4);") + tk.MustExec("insert into t values ();") + hook = newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'a' is in public. + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StatePublic + }) + dom.DDL().SetHook(hook) + tk.MustGetErrCode("alter table t drop column b, drop column a, drop column d;", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + hook.MustCancelDone(t) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3 4")) +} + +func TestMultiSchemaChangeDropIndexedColumnsCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + originHook := dom.DDL().GetHook() + + // Test for cancelling the job in a middle state. + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3, d int default 4, " + + "index(a), index(b), index(c), index(d));") + tk.MustExec("insert into t values ();") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'a' is in delete-reorg. + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StateDeleteReorganization + }) + jobIDExt := wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(composeHooks(dom, jobIDExt, hook)) + tk.MustExec("alter table t drop column b, drop column a, drop column d;") + dom.DDL().SetHook(originHook) + hook.MustCancelFailed(t) + tk.MustQuery("select * from t;").Check(testkit.Rows("3")) + checkDelRangeCnt(tk, jobIDExt.jobID, 3) +} + +func TestMultiSchemaChangeDropColumnsParallel(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + tk.MustExec("create table t (a int, b int, c int);") + putTheSameDDLJobTwice(t, func() { + tk.MustExec("alter table t drop column if exists b, drop column if exists c;") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Note 1091 column b doesn't exist", + "Note 1091 column c doesn't exist")) + }) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + putTheSameDDLJobTwice(t, func() { + tk.MustGetErrCode("alter table t drop column b, drop column a;", errno.ErrCantDropFieldOrKey) + }) +} + +func TestMultiSchemaChangeAddDropColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + + // [a, b] -> [+c, -a, +d, -b] -> [c, d] + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t add column c int default 3, drop column a, add column d int default 4, drop column b;") + tk.MustQuery("select * from t;").Check(testkit.Rows("3 4")) + + // [a, b] -> [-a, -b, +c, +d] -> [c, d] + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t drop column a, drop column b, add column c int default 3, add column d int default 4;") + tk.MustQuery("select * from t;").Check(testkit.Rows("3 4")) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t add column c int default 3 after a, add column d int default 4 first, drop column a, drop column b;", errno.ErrUnsupportedDDLOperation) +} + +func TestMultiSchemaChangeRenameColumns(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + originHook := dom.DDL().GetHook() + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + + // unsupported ddl operations + { + // Test add and rename to same column name + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t rename column b to c, add column c int", errno.ErrUnsupportedDDLOperation) + + // Test add column related with rename column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t rename column b to c, add column e int after b", errno.ErrUnsupportedDDLOperation) + + // Test drop and rename with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t drop column b, rename column b to c", errno.ErrUnsupportedDDLOperation) + + // Test add index and rename with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, index t(a, b));") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t rename column b to c, add index t1(a, b)", errno.ErrUnsupportedDDLOperation) + } + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, index t(a, b));") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t rename column b to c, add column e int default 3") + tk.MustQuery("select c from t").Check(testkit.Rows("2")) + tk.MustQuery("select * from t").Check(testkit.Rows("1 2 3")) + + // Test cancel job with renameIndex + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int default 1, b int default 2)") + tk.MustExec("insert into t values ()") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'c' is in write-reorg. + return job.MultiSchemaInfo.SubJobs[0].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(hook) + tk.MustGetErrCode("alter table t add column c int default 3, rename column b to d;", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + tk.MustQuery("select b from t").Check(testkit.Rows("2")) + tk.MustGetErrCode("select d from t", errno.ErrBadField) +} + +func TestMultiSchemaChangeAlterColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + + // Test alter and drop with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t alter column b set default 3, drop column b", errno.ErrUnsupportedDDLOperation) +} + +func TestMultiSchemaChangeChangeColumns(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + originHook := dom.DDL().GetHook() + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + + // unsupported ddl operations + { + // Test change and drop with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t change column b c double, drop column b", errno.ErrUnsupportedDDLOperation) + + // Test change and add with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t change column b c double, add column c int", errno.ErrUnsupportedDDLOperation) + + // Test add index and rename with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, index t(a, b));") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t change column b c double, add index t1(a, b)", errno.ErrUnsupportedDDLOperation) + } + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, index t(a, b));") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t rename column b to c, change column a e bigint default 3;") + tk.MustQuery("select e,c from t").Check(testkit.Rows("1 2")) + tk.MustExec("truncate table t;") + tk.MustExec("insert into t values ();") + tk.MustQuery("select e,c from t").Check(testkit.Rows("3 2")) + + // Test cancel job with renameIndex + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int default 1, b int default 2)") + tk.MustExec("insert into t values ()") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'c' is in write-reorg. + return job.MultiSchemaInfo.SubJobs[0].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(hook) + tk.MustGetErrCode("alter table t add column c int default 3, change column b d bigint default 4;", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + tk.MustQuery("select b from t").Check(testkit.Rows("2")) + tk.MustGetErrCode("select d from t", errno.ErrBadField) +} + +func TestMultiSchemaChangeAddIndexes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + + // Test add multiple indexes with same column. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("alter table t add index t(a, b), add index t1(a);") + tk.MustExec("alter table t add index t2(a), add index t3(a, b);") + tk.MustQuery("select * from t use index (t, t1, t2, t3);").Check(testkit.Rows("1 2 3")) + tk.MustExec("admin check table t;") + + // Test add multiple indexes with same name. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int)") + tk.MustGetErrCode("alter table t add index t(a), add index t(b)", errno.ErrUnsupportedDDLOperation) + + // Test add indexes with drop column. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int)") + tk.MustGetErrCode("alter table t add index t(a), drop column a", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add index t(a, b), drop column a", errno.ErrUnsupportedDDLOperation) +} + +func TestMultiSchemaChangeAddIndexesCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + originHook := dom.DDL().GetHook() + + // Test cancel successfully. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + jobIDExt := wrapJobIDExtCallback(originHook) + cancelHook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel the job when index 't2' is in write-reorg. + return job.MultiSchemaInfo.SubJobs[2].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(composeHooks(dom, jobIDExt, cancelHook)) + tk.MustGetErrCode("alter table t "+ + "add index t(a, b), add index t1(a), "+ + "add index t2(a), add index t3(a, b);", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + cancelHook.MustCancelDone(t) + tk.MustQuery("show index from t;").Check(testkit.Rows( /* no index */ )) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + tk.MustExec("admin check table t;") + // Check the adding indexes are put to del-ranges. + checkDelRangeCnt(tk, jobIDExt.jobID, 3) + + // Test cancel failed when some sub-jobs have been finished. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + cancelHook = newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel the job when index 't1' is in public. + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StatePublic + }) + dom.DDL().SetHook(cancelHook) + tk.MustExec("alter table t add index t(a, b), add index t1(a), " + + "add index t2(a), add index t3(a, b);") + dom.DDL().SetHook(originHook) + cancelHook.MustCancelFailed(t) + tk.MustQuery("select * from t use index(t, t1, t2, t3);").Check(testkit.Rows("1 2 3")) + tk.MustExec("admin check table t;") +} + +func TestMultiSchemaChangeDropIndexes(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + originHook := dom.DDL().GetHook() + + jobIDExt := wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(jobIDExt) + + // Test drop same index. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index t(a));") + tk.MustGetErrCode("alter table t drop index t, drop index t", errno.ErrUnsupportedDDLOperation) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (id int, c1 int, c2 int, primary key(id) nonclustered, key i1(c1), key i2(c2), key i3(c1, c2));") + tk.MustExec("insert into t values (1, 2, 3);") + jobIDExt.Clear() + tk.MustExec("alter table t drop index i1, drop index i2;") + tk.MustGetErrCode("select * from t use index(i1);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index(i2);", errno.ErrKeyDoesNotExist) + checkDelRangeCnt(tk, jobIDExt.jobID, 2) + jobIDExt.Clear() + tk.MustExec("alter table t drop index i3, drop primary key;") + tk.MustGetErrCode("select * from t use index(primary);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index(i3);", errno.ErrKeyDoesNotExist) + checkDelRangeCnt(tk, jobIDExt.jobID, 2) + + // Test drop index with drop column. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3, index t(a))") + tk.MustExec("insert into t values ();") + jobIDExt.Clear() + tk.MustExec("alter table t drop index t, drop column a") + tk.MustGetErrCode("select * from t force index(t)", errno.ErrKeyDoesNotExist) + checkDelRangeCnt(tk, jobIDExt.jobID, 1) + + dom.DDL().SetHook(originHook) +} + +func TestMultiSchemaChangeDropIndexesCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + originHook := dom.DDL().GetHook() + + // Test for cancelling the job in a middle state. + tk.MustExec("create table t (a int, b int, index(a), unique index(b), index idx(a, b));") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StateDeleteOnly + }) + dom.DDL().SetHook(hook) + tk.MustExec("alter table t drop index a, drop index b, drop index idx;") + dom.DDL().SetHook(originHook) + hook.MustCancelFailed(t) + tk.MustGetErrCode("select * from t use index (a);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index (b);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index (idx);", errno.ErrKeyDoesNotExist) + + // Test for cancelling the job in none state. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, index(a), unique index(b), index idx(a, b));") + hook = newCancelJobHook(store, dom, func(job *model.Job) bool { + return job.MultiSchemaInfo.SubJobs[1].SchemaState == model.StateNone + }) + dom.DDL().SetHook(hook) + tk.MustGetErrCode("alter table t drop index a, drop index b, drop index idx;", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + hook.MustCancelDone(t) + tk.MustQuery("select * from t use index (a);").Check(testkit.Rows()) + tk.MustQuery("select * from t use index (b);").Check(testkit.Rows()) + tk.MustQuery("select * from t use index (idx);").Check(testkit.Rows()) +} + +func TestMultiSchemaChangeDropIndexesParallel(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + tk.MustExec("create table t (a int, b int, c int, index(a), index(b), index(c));") + putTheSameDDLJobTwice(t, func() { + tk.MustExec("alter table t drop index if exists b, drop index if exists c;") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Note 1091 index b doesn't exist", + "Note 1091 index c doesn't exist")) + }) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index (a), index(b), index(c));") + putTheSameDDLJobTwice(t, func() { + tk.MustGetErrCode("alter table t drop index b, drop index a;", errno.ErrCantDropFieldOrKey) + }) +} + +func TestMultiSchemaChangeAddDropIndexes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + + // Test add and drop same index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, index t(a))") + tk.MustGetErrCode("alter table t drop index t, add index t(b)", errno.ErrDupKeyName) + + // Test add and drop same index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, index t(a))") + tk.MustGetErrCode("alter table t add index t1(b), drop index t1", errno.ErrCantDropFieldOrKey) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index (a), index(b), index(c));") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("alter table t add index aa(a), drop index a, add index cc(c), drop index b, drop index c, add index bb(b);") + tk.MustQuery("select * from t use index(aa, bb, cc);").Check(testkit.Rows("1 2 3")) + tk.MustGetErrCode("select * from t use index(a);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index(b);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index(c);", errno.ErrKeyDoesNotExist) + tk.MustExec("admin check table t;") +} + +func TestMultiSchemaChangeRenameIndexes(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + originHook := dom.DDL().GetHook() + + // Test rename index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, index t(a), index t1(b))") + tk.MustExec("alter table t rename index t to x, rename index t1 to x1") + tk.MustExec("select * from t use index (x);") + tk.MustExec("select * from t use index (x1);") + tk.MustGetErrCode("select * from t use index (t);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index (t1);", errno.ErrKeyDoesNotExist) + + // Test drop and rename same index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, index t(a))") + tk.MustGetErrCode("alter table t drop index t, rename index t to t1", errno.ErrUnsupportedDDLOperation) + + // Test add and rename to same index name. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, index t(a))") + tk.MustGetErrCode("alter table t add index t1(b), rename index t to t1", errno.ErrUnsupportedDDLOperation) + + // Test drop column with rename index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3, index t(a))") + tk.MustExec("insert into t values ();") + jobIDExt := wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(jobIDExt) + tk.MustExec("alter table t drop column a, rename index t to x") + tk.MustGetErrCode("select * from t use index (x);", errno.ErrKeyDoesNotExist) + tk.MustQuery("select * from t;").Check(testkit.Rows("2 3")) + checkDelRangeCnt(tk, jobIDExt.jobID, 1) + + // Test cancel job with renameIndex + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int default 1, b int default 2, index t(a))") + tk.MustExec("insert into t values ()") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + // Cancel job when the column 'c' is in write-reorg. + return job.MultiSchemaInfo.SubJobs[0].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(hook) + tk.MustGetErrCode("alter table t add column c int default 3, rename index t to t1;", errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + tk.MustQuery("select * from t use index (t);").Check(testkit.Rows("1 2")) + tk.MustGetErrCode("select * from t use index (t1);", errno.ErrKeyDoesNotExist) +} + +func TestMultiSchemaChangeModifyColumns(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + originHook := dom.DDL().GetHook() + + // unsupported ddl operations + { + // Test modify and drop with same column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t modify column b double, drop column b", errno.ErrUnsupportedDDLOperation) + + // Test modify column related with dropped column + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2, c int default 3);") + tk.MustExec("insert into t values ();") + tk.MustGetErrCode("alter table t modify column b double after c, drop column c", errno.ErrUnsupportedDDLOperation) + } + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int default 1, b int default 2);") + tk.MustExec("insert into t values ();") + tk.MustExec("alter table t modify column b double default 2 after a, add column c int default 3 after a;") + tk.MustQuery("select * from t").Check(testkit.Rows("1 3 2")) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int);") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("alter table t modify column a bigint, modify column b bigint;") + tk.MustExec("insert into t values (9223372036854775807, 9223372036854775807, 1);") + tk.MustQuery("select * from t;").Check( + testkit.Rows("1 2 3", "9223372036854775807 9223372036854775807 1")) + + // Modify index-covered columns. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index i1(a), index i2(b), index i3(c), index i4(a, b), index i5(a, b, c));") + tk.MustExec("insert into t values (1, 2, 3);") + jobIDExt := wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(jobIDExt) + tk.MustExec("alter table t modify column a tinyint, modify column b tinyint, modify column c tinyint;") + dom.DDL().SetHook(originHook) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + tk.MustQuery("select * from t use index(i1, i2, i3, i4, i5);").Check(testkit.Rows("1 2 3")) + tk.MustExec("admin check table t;") + checkDelRangeCnt(tk, jobIDExt.jobID, 8) + + // Modify index-covered columns with position change. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index i1(a), index i2(b), index i3(c), index i4(a, b), index i5(a, b, c));") + tk.MustExec("insert into t values (1, 2, 3);") + jobIDExt = wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(jobIDExt) + tk.MustExec("alter table t modify column a tinyint after c, modify column b tinyint, modify column c tinyint first;") + dom.DDL().SetHook(originHook) + tk.MustQuery("select * from t;").Check(testkit.Rows("3 2 1")) + tk.MustQuery("select * from t use index(i1, i2, i3, i4, i5);").Check(testkit.Rows("3 2 1")) + tk.MustExec("admin check table t;") + checkDelRangeCnt(tk, jobIDExt.jobID, 8) + + // Modify columns that require and don't require reorganization of data. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b int, c int, index i1(a), index i2(c, b));") + tk.MustExec("insert into t values (1, 2, 3), (11, 22, 33);") + jobIDExt = wrapJobIDExtCallback(originHook) + dom.DDL().SetHook(jobIDExt) + tk.MustExec("alter table t modify column b char(255) after c, modify column a bigint;") + tk.MustQuery("select * from t;").Check(testkit.Rows("1 3 2", "11 33 22")) + tk.MustQuery("select * from t use index(i1, i2);").Check(testkit.Rows("1 3 2", "11 33 22")) + tk.MustExec("admin check table t;") + checkDelRangeCnt(tk, jobIDExt.jobID, 1) // only i2 has tmp index. +} + +func TestMultiSchemaChangeModifyColumnsCancelled(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + originHook := dom.DDL().GetHook() + + // Test for cancelling the job in a middle state. + tk.MustExec("create table t (a int, b int, c int, index i1(a), unique index i2(b), index i3(a, b));") + tk.MustExec("insert into t values (1, 2, 3);") + hook := newCancelJobHook(store, dom, func(job *model.Job) bool { + return job.MultiSchemaInfo.SubJobs[2].SchemaState == model.StateWriteReorganization + }) + dom.DDL().SetHook(hook) + sql := "alter table t modify column a tinyint, modify column b bigint, modify column c char(20);" + tk.MustGetErrCode(sql, errno.ErrCancelledDDLJob) + dom.DDL().SetHook(originHook) + hook.MustCancelDone(t) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 2 3")) + tk.MustQuery("select * from t use index (i1, i2, i3);").Check(testkit.Rows("1 2 3")) + tk.MustExec("admin check table t;") + tk.MustQuery("select data_type from information_schema.columns where table_name = 't' and column_name = 'c';"). + Check(testkit.Rows("int")) +} + +func TestMultiSchemaChangeMix(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1;") + + tk.MustExec("create table t (a int, b int, c int, index i1(c), index i2(c));") + tk.MustExec("insert into t values (1, 2, 3);") + tk.MustExec("alter table t add column d int default 4, add index i3(c), " + + "drop column a, drop column if exists z, add column if not exists e int default 5, " + + "drop index i2, add column f int default 6, drop column b, drop index i1, add column if not exists c int;") + tk.MustQuery("select * from t;").Check(testkit.Rows("3 4 5 6")) + tk.MustGetErrCode("select * from t use index (i1);", errno.ErrKeyDoesNotExist) + tk.MustGetErrCode("select * from t use index (i2);", errno.ErrKeyDoesNotExist) + tk.MustQuery("select * from t use index (i3);").Check(testkit.Rows("3 4 5 6")) +} + +func TestMultiSchemaChangeAdminShowDDLJobs(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + originHook := dom.DDL().GetHook() + hook := &ddl.TestDDLCallback{Do: dom} + hook.OnJobRunBeforeExported = func(job *model.Job) { + assert.Equal(t, model.ActionMultiSchemaChange, job.Type) + if job.MultiSchemaInfo.SubJobs[0].SchemaState == model.StateDeleteOnly { + newTk := testkit.NewTestKit(t, store) + rows := newTk.MustQuery("admin show ddl jobs 1").Rows() + // 1 history job and 1 running job with 2 subjobs + assert.Equal(t, len(rows), 4) + assert.Equal(t, rows[1][1], "test") + assert.Equal(t, rows[1][2], "t") + assert.Equal(t, rows[1][3], "add index /* subjob */") + assert.Equal(t, rows[1][4], "delete only") + assert.Equal(t, rows[1][len(rows[1])-1], "running") + + assert.Equal(t, rows[2][3], "add index /* subjob */") + assert.Equal(t, rows[2][4], "none") + assert.Equal(t, rows[2][len(rows[2])-1], "none") + } + } + + tk.MustExec("create table t (a int, b int, c int)") + tk.MustExec("insert into t values (1, 2, 3)") + + dom.DDL().SetHook(hook) + tk.MustExec("alter table t add index t(a), add index t1(b)") + dom.DDL().SetHook(originHook) +} + +func composeHooks(dom *domain.Domain, cbs ...ddl.Callback) ddl.Callback { + return &ddl.TestDDLCallback{ + Do: dom, + OnJobRunBeforeExported: func(job *model.Job) { + for _, c := range cbs { + c.OnJobRunBefore(job) + } + }, + OnJobUpdatedExported: func(job *model.Job) { + for _, c := range cbs { + c.OnJobUpdated(job) + } + }, + } +} + +type idxIDExt struct { + store kv.Storage + idxNameToID map[string]int64 + getIdxErr error + + ddl.TestDDLCallback +} + +func newIdxIDExtHook(store kv.Storage, dom *domain.Domain) *idxIDExt { + return &idxIDExt{store: store, idxNameToID: map[string]int64{}, TestDDLCallback: ddl.TestDDLCallback{Do: dom}} +} + +func (i *idxIDExt) OnJobUpdated(job *model.Job) { + i.getIdxErr = kv.RunInNewTxn(context.Background(), i.store, false, + func(ctx context.Context, txn kv.Transaction) error { + t := meta.NewMeta(txn) + tbl, err := t.GetTable(job.SchemaID, job.TableID) + if err != nil { + return err + } + for _, idx := range tbl.Indices { + if _, found := i.idxNameToID[idx.Name.L]; !found { + i.idxNameToID[idx.Name.L] = idx.ID + } + } + return nil + }) +} + +func (i *idxIDExt) IndexID(name string) int64 { + id, ok := i.idxNameToID[name] + if !ok { + return -1 + } + return id +} + +type cancelOnceHook struct { + store kv.Storage + triggered bool + cancelErr error + pred func(job *model.Job) bool + + ddl.TestDDLCallback +} + +func (c *cancelOnceHook) OnJobUpdated(job *model.Job) { + if c.triggered || !c.pred(job) { + return + } + c.triggered = true + c.cancelErr = kv.RunInNewTxn(context.Background(), c.store, false, + func(ctx context.Context, txn kv.Transaction) error { + errs, err := admin.CancelJobs(txn, []int64{job.ID}) + if errs[0] != nil { + return errs[0] + } + return err + }) +} + +func (c *cancelOnceHook) MustCancelDone(t *testing.T) { + require.True(t, c.triggered) + require.NoError(t, c.cancelErr) +} + +func (c *cancelOnceHook) MustCancelFailed(t *testing.T) { + require.True(t, c.triggered) + require.Contains(t, c.cancelErr.Error(), strconv.Itoa(errno.ErrCannotCancelDDLJob)) +} + +func newCancelJobHook(store kv.Storage, dom *domain.Domain, + pred func(job *model.Job) bool) *cancelOnceHook { + return &cancelOnceHook{ + store: store, + pred: pred, + TestDDLCallback: ddl.TestDDLCallback{Do: dom}, + } +} + +func putTheSameDDLJobTwice(t *testing.T, fn func()) { + err := failpoint.Enable("github.com/pingcap/tidb/ddl/mockParallelSameDDLJobTwice", `return(true)`) + require.NoError(t, err) + fn() + err = failpoint.Disable("github.com/pingcap/tidb/ddl/mockParallelSameDDLJobTwice") + require.NoError(t, err) +} diff --git a/ddl/options.go b/ddl/options.go index 980412e41fa2e..e4c59e5d3b5b7 100644 --- a/ddl/options.go +++ b/ddl/options.go @@ -19,7 +19,7 @@ import ( "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" ) // Option represents an option to initialize the DDL module diff --git a/ddl/options_test.go b/ddl/options_test.go index 1fe257072eaab..ccd8471c04250 100644 --- a/ddl/options_test.go +++ b/ddl/options_test.go @@ -22,12 +22,16 @@ import ( "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" ) func TestOptions(t *testing.T) { client, err := clientv3.NewFromURL("test") require.NoError(t, err) + defer func() { + err := client.Close() + require.NoError(t, err) + }() callback := &ddl.BaseCallback{} lease := time.Second * 3 store := &mock.Store{} diff --git a/ddl/partition.go b/ddl/partition.go index 6f6d3b8b0ff59..3a24fa414cbab 100644 --- a/ddl/partition.go +++ b/ddl/partition.go @@ -48,6 +48,7 @@ import ( tidbutil "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/slice" @@ -62,7 +63,7 @@ const ( func checkAddPartition(t *meta.Meta, job *model.Job) (*model.TableInfo, *model.PartitionInfo, []model.PartitionDefinition, error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return nil, nil, nil, errors.Trace(err) } @@ -132,6 +133,14 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v } } + if tblInfo.TiFlashReplica != nil { + // Must set placement rule, and make sure it succeeds. + if err := infosync.ConfigureTiFlashPDForPartitions(true, &tblInfo.Partition.AddingDefinitions, tblInfo.TiFlashReplica.Count, &tblInfo.TiFlashReplica.LocationLabels, tblInfo.ID); err != nil { + logutil.BgLogger().Error("ConfigureTiFlashPDForPartitions fails", zap.Error(err)) + return ver, errors.Trace(err) + } + } + bundles, err := alterTablePartitionBundles(t, tblInfo, tblInfo.Partition.AddingDefinitions) if err != nil { job.State = model.JobStateCancelled @@ -166,6 +175,12 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v } } + // When TiFlash Replica is ready, we must move them into `AvailablePartitionIDs`. + if tblInfo.TiFlashReplica != nil && tblInfo.TiFlashReplica.Available { + for _, d := range partInfo.Definitions { + tblInfo.TiFlashReplica.AvailablePartitionIDs = append(tblInfo.TiFlashReplica.AvailablePartitionIDs, d.ID) + } + } // For normal and replica finished table, move the `addingDefinitions` into `Definitions`. updatePartitionInfo(tblInfo) @@ -178,7 +193,7 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) asyncNotifyEvent(d, &util.Event{Tp: model.ActionAddTablePartition, TableInfo: tblInfo, PartInfo: partInfo}) default: - err = ErrInvalidDDLState.GenWithStackByArgs("partition", job.SchemaState) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("partition", job.SchemaState) } return ver, errors.Trace(err) @@ -187,6 +202,17 @@ func (w *worker) onAddTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (v func alterTablePartitionBundles(t *meta.Meta, tblInfo *model.TableInfo, addingDefinitions []model.PartitionDefinition) ([]*placement.Bundle, error) { var bundles []*placement.Bundle + // tblInfo do not include added partitions, so we should add them first + tblInfo = tblInfo.Clone() + p := *tblInfo.Partition + p.Definitions = append([]model.PartitionDefinition{}, p.Definitions...) + p.Definitions = append(tblInfo.Partition.Definitions, addingDefinitions...) + tblInfo.Partition = &p + + if tblInfo.TiFlashReplica != nil && tblInfo.TiFlashReplica.Count > 0 && tableHasPlacementSettings(tblInfo) { + return nil, errors.Trace(dbterror.ErrIncompatibleTiFlashAndPlacement) + } + // bundle for table should be recomputed because it includes some default configs for partitions tblBundle, err := placement.NewTableBundle(t, tblInfo) if err != nil { @@ -232,7 +258,7 @@ func rollbackAddingPartitionInfo(tblInfo *model.TableInfo) ([]int64, []string, [ for _, one := range tblInfo.Partition.AddingDefinitions { physicalTableIDs = append(physicalTableIDs, one.ID) partNames = append(partNames, one.Name.L) - if one.PlacementPolicyRef != nil || one.DirectPlacementOpts != nil { + if one.PlacementPolicyRef != nil { rollbackBundles = append(rollbackBundles, placement.NewBundle(one.ID)) } } @@ -246,7 +272,7 @@ func checkAddPartitionValue(meta *model.TableInfo, part *model.PartitionInfo) er newDefs, oldDefs := part.Definitions, meta.Partition.Definitions rangeValue := oldDefs[len(oldDefs)-1].LessThan[0] if strings.EqualFold(rangeValue, "MAXVALUE") { - return errors.Trace(ErrPartitionMaxvalue) + return errors.Trace(dbterror.ErrPartitionMaxvalue) } currentRangeValue, err := strconv.Atoi(rangeValue) @@ -259,7 +285,7 @@ func checkAddPartitionValue(meta *model.TableInfo, part *model.PartitionInfo) er if ifMaxvalue && i == len(newDefs)-1 { return nil } else if ifMaxvalue && i != len(newDefs)-1 { - return errors.Trace(ErrPartitionMaxvalue) + return errors.Trace(dbterror.ErrPartitionMaxvalue) } nextRangeValue, err := strconv.Atoi(newDefs[i].LessThan[0]) @@ -267,7 +293,7 @@ func checkAddPartitionValue(meta *model.TableInfo, part *model.PartitionInfo) er return errors.Trace(err) } if nextRangeValue <= currentRangeValue { - return errors.Trace(ErrRangeNotIncreasing) + return errors.Trace(dbterror.ErrRangeNotIncreasing) } currentRangeValue = nextRangeValue } @@ -312,6 +338,9 @@ func checkPartitionReplica(replicaCount uint64, addingDefinitions []model.Partit return needWait, errors.Trace(err) } tiflashPeerAtLeastOne := checkTiFlashPeerStoreAtLeastOne(stores, regionState.Meta.Peers) + failpoint.Inject("ForceTiflashNotAvailable", func(v failpoint.Value) { + tiflashPeerAtLeastOne = v.(bool) + }) // It's unnecessary to wait all tiflash peer to be replicated. // Here only make sure that tiflash peer count > 0 (at least one). if tiflashPeerAtLeastOne { @@ -353,7 +382,7 @@ func buildTablePartitionInfo(ctx sessionctx.Context, s *ast.PartitionOptions, tb } if strings.EqualFold(ctx.GetSessionVars().EnableTablePartition, "OFF") { - ctx.GetSessionVars().StmtCtx.AppendWarning(errTablePartitionDisabled) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrTablePartitionDisabled) return nil } @@ -383,7 +412,7 @@ func buildTablePartitionInfo(ctx sessionctx.Context, s *ast.PartitionOptions, tb } if !enable { - ctx.GetSessionVars().StmtCtx.AppendWarning(errUnsupportedCreatePartition.GenWithStack(fmt.Sprintf("Unsupported partition type %v, treat as normal table", s.Tp))) + ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedCreatePartition.GenWithStack(fmt.Sprintf("Unsupported partition type %v, treat as normal table", s.Tp))) return nil } @@ -437,14 +466,6 @@ func buildPartitionDefinitionsInfo(ctx sessionctx.Context, defs []*ast.Partition return nil, err } - for idx := range partitions { - def := &partitions[idx] - def.PlacementPolicyRef, def.DirectPlacementOpts, err = checkAndNormalizePlacement(ctx, def.PlacementPolicyRef, def.DirectPlacementOpts, nil, nil) - if err != nil { - return nil, err - } - } - return partitions, nil } @@ -457,19 +478,6 @@ func setPartitionPlacementFromOptions(partition *model.PartitionDefinition, opti // when policy x is altered. for _, opt := range options { switch opt.Tp { - case ast.TableOptionPlacementPrimaryRegion, ast.TableOptionPlacementRegions, - ast.TableOptionPlacementFollowerCount, ast.TableOptionPlacementVoterCount, - ast.TableOptionPlacementLearnerCount, ast.TableOptionPlacementSchedule, - ast.TableOptionPlacementConstraints, ast.TableOptionPlacementLeaderConstraints, - ast.TableOptionPlacementLearnerConstraints, ast.TableOptionPlacementFollowerConstraints, - ast.TableOptionPlacementVoterConstraints: - if partition.DirectPlacementOpts == nil { - partition.DirectPlacementOpts = &model.PlacementSettings{} - } - err := SetDirectPlacementOpt(partition.DirectPlacementOpts, ast.PlacementOptionType(opt.Tp), opt.StrValue, opt.UintValue) - if err != nil { - return err - } case ast.TableOptionPlacementPolicy: partition.PlacementPolicyRef = &model.PolicyRefInfo{ Name: model.NewCIStr(opt.StrValue), @@ -633,15 +641,15 @@ func checkPartitionValuesIsInt(ctx sessionctx.Context, def *ast.PartitionDefinit case types.KindUint64, types.KindNull: case types.KindInt64: if mysql.HasUnsignedFlag(tp.Flag) && val.GetInt64() < 0 { - return ErrPartitionConstDomain.GenWithStackByArgs() + return dbterror.ErrPartitionConstDomain.GenWithStackByArgs() } default: - return ErrValuesIsNotIntType.GenWithStackByArgs(def.Name) + return dbterror.ErrValuesIsNotIntType.GenWithStackByArgs(def.Name) } _, err = val.ConvertTo(ctx.GetSessionVars().StmtCtx, tp) if err != nil && !types.ErrOverflow.Equal(err) { - return ErrWrongTypeColumnValue.GenWithStackByArgs() + return dbterror.ErrWrongTypeColumnValue.GenWithStackByArgs() } } @@ -653,7 +661,7 @@ func checkPartitionNameUnique(pi *model.PartitionInfo) error { partNames := make(map[string]struct{}, len(newPars)) for _, newPar := range newPars { if _, ok := partNames[newPar.Name.L]; ok { - return ErrSameNamePartition.GenWithStackByArgs(newPar.Name) + return dbterror.ErrSameNamePartition.GenWithStackByArgs(newPar.Name) } partNames[newPar.Name.L] = struct{}{} } @@ -671,7 +679,7 @@ func checkAddPartitionNameUnique(tbInfo *model.TableInfo, pi *model.PartitionInf newPars := pi.Definitions for _, newPar := range newPars { if _, ok := partNames[newPar.Name.L]; ok { - return ErrSameNamePartition.GenWithStackByArgs(newPar.Name) + return dbterror.ErrSameNamePartition.GenWithStackByArgs(newPar.Name) } partNames[newPar.Name.L] = struct{}{} } @@ -684,15 +692,15 @@ func checkAndOverridePartitionID(newTableInfo, oldTableInfo *model.TableInfo) er return nil } if oldTableInfo.Partition == nil { - return ErrRepairTableFail.GenWithStackByArgs("Old table doesn't have partitions") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Old table doesn't have partitions") } if newTableInfo.Partition.Type != oldTableInfo.Partition.Type { - return ErrRepairTableFail.GenWithStackByArgs("Partition type should be the same") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Partition type should be the same") } // Check whether partitionType is hash partition. if newTableInfo.Partition.Type == model.PartitionTypeHash { if newTableInfo.Partition.Num != oldTableInfo.Partition.Num { - return ErrRepairTableFail.GenWithStackByArgs("Hash partition num should be the same") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Hash partition num should be the same") } } for i, newOne := range newTableInfo.Partition.Definitions { @@ -707,7 +715,7 @@ func checkAndOverridePartitionID(newTableInfo, oldTableInfo *model.TableInfo) er } } if !found { - return ErrRepairTableFail.GenWithStackByArgs("Partition " + newOne.Name.L + " has lost") + return dbterror.ErrRepairTableFail.GenWithStackByArgs("Partition " + newOne.Name.L + " has lost") } } return nil @@ -724,7 +732,7 @@ func checkPartitionFuncValid(ctx sessionctx.Context, tblInfo *model.TableInfo, e return errors.Trace(exprChecker.err) } if len(exprChecker.columns) == 0 { - return errors.Trace(ErrWrongExprInPartitionFunc) + return errors.Trace(dbterror.ErrWrongExprInPartitionFunc) } return nil } @@ -734,7 +742,7 @@ func checkPartitionFuncValid(ctx sessionctx.Context, tblInfo *model.TableInfo, e // Based on mysql code to check whether field is valid, every time related type has check_valid_arguments_processor function. func checkResultOK(ok bool) error { if !ok { - return errors.Trace(ErrWrongExprInPartitionFunc) + return errors.Trace(dbterror.ErrWrongExprInPartitionFunc) } return nil @@ -755,10 +763,10 @@ func checkPartitionFuncType(ctx sessionctx.Context, expr ast.ExprNode, tblInfo * } if col, ok := expr.(*ast.ColumnNameExpr); ok { - return errors.Trace(ErrNotAllowedTypeInPartition.GenWithStackByArgs(col.Name.Name.L)) + return errors.Trace(dbterror.ErrNotAllowedTypeInPartition.GenWithStackByArgs(col.Name.Name.L)) } - return errors.Trace(ErrPartitionFuncNotAllowed.GenWithStackByArgs("PARTITION")) + return errors.Trace(dbterror.ErrPartitionFuncNotAllowed.GenWithStackByArgs("PARTITION")) } // checkRangePartitionValue checks whether `less than value` is strictly increasing for each partition. @@ -778,7 +786,7 @@ func checkRangePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) var prevRangeValue interface{} for i := 0; i < len(defs); i++ { if strings.EqualFold(defs[i].LessThan[0], partitionMaxValue) { - return errors.Trace(ErrPartitionMaxvalue) + return errors.Trace(dbterror.ErrPartitionMaxvalue) } currentRangeValue, fromExpr, err := getRangeValue(ctx, defs[i].LessThan[0], isUnsigned) @@ -797,11 +805,11 @@ func checkRangePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) if isUnsigned { if currentRangeValue.(uint64) <= prevRangeValue.(uint64) { - return errors.Trace(ErrRangeNotIncreasing) + return errors.Trace(dbterror.ErrRangeNotIncreasing) } } else { if currentRangeValue.(int64) <= prevRangeValue.(int64) { - return errors.Trace(ErrRangeNotIncreasing) + return errors.Trace(dbterror.ErrRangeNotIncreasing) } } prevRangeValue = currentRangeValue @@ -822,7 +830,7 @@ func checkListPartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) e partitionsValuesMap := make(map[string]struct{}) for _, s := range expStr { if _, ok := partitionsValuesMap[s]; ok { - return errors.Trace(ErrMultipleDefConstInListPart) + return errors.Trace(dbterror.ErrMultipleDefConstInListPart) } partitionsValuesMap[s] = struct{}{} } @@ -846,7 +854,7 @@ func formatListPartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo) for _, colName := range pi.Columns { colInfo := findColumnByName(colName.L, tblInfo) if colInfo == nil { - return nil, errors.Trace(ErrFieldNotFoundPart) + return nil, errors.Trace(dbterror.ErrFieldNotFoundPart) } colTps = append(colTps, colInfo.FieldType.Clone()) cols = append(cols, colInfo) @@ -920,31 +928,40 @@ func getRangeValue(ctx sessionctx.Context, str string, unsigned bool) (interface return res, true, nil } } - return 0, false, ErrNotAllowedTypeInPartition.GenWithStackByArgs(str) + return 0, false, dbterror.ErrNotAllowedTypeInPartition.GenWithStackByArgs(str) } // checkDropTablePartition checks if the partition exists and does not allow deleting the last existing partition in the table. func checkDropTablePartition(meta *model.TableInfo, partLowerNames []string) error { pi := meta.Partition if pi.Type != model.PartitionTypeRange && pi.Type != model.PartitionTypeList { - return errOnlyOnRangeListPartition.GenWithStackByArgs("DROP") + return dbterror.ErrOnlyOnRangeListPartition.GenWithStackByArgs("DROP") } + + // To be error compatible with MySQL, we need to do this first! + // see https://github.com/pingcap/tidb/issues/31681#issuecomment-1015536214 oldDefs := pi.Definitions + if len(oldDefs) <= len(partLowerNames) { + return errors.Trace(dbterror.ErrDropLastPartition) + } + + dupCheck := make(map[string]bool) for _, pn := range partLowerNames { found := false for _, def := range oldDefs { if def.Name.L == pn { + if _, ok := dupCheck[pn]; ok { + return errors.Trace(dbterror.ErrDropPartitionNonExistent.GenWithStackByArgs("DROP")) + } + dupCheck[pn] = true found = true break } } if !found { - return errors.Trace(ErrDropPartitionNonExistent.GenWithStackByArgs(pn)) + return errors.Trace(dbterror.ErrDropPartitionNonExistent.GenWithStackByArgs("DROP")) } } - if len(oldDefs) == len(partLowerNames) { - return errors.Trace(ErrDropLastPartition) - } return nil } @@ -1035,7 +1052,7 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -1107,7 +1124,7 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( elements = append(elements, &meta.Element{ID: idxInfo.ID, TypeKey: meta.IndexElementKey}) } } - reorgInfo, err := getReorgInfoFromPartitions(d, t, job, tbl, physicalTableIDs, elements) + reorgInfo, err := getReorgInfoFromPartitions(w.JobContext, d, t, job, tbl, physicalTableIDs, elements) if err != nil || reorgInfo.first { // If we run reorg firstly, we should update the job snapshot version @@ -1117,12 +1134,12 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (dropIndexErr error) { defer tidbutil.Recover(metrics.LabelDDL, "onDropTablePartition", func() { - dropIndexErr = errCancelledDDLJob.GenWithStack("drop partition panic") + dropIndexErr = dbterror.ErrCancelledDDLJob.GenWithStack("drop partition panic") }, false) return w.cleanupGlobalIndexes(pt, physicalTableIDs, reorgInfo) }) if err != nil { - if errWaitReorgTimeout.Equal(err) { + if dbterror.ErrWaitReorgTimeout.Equal(err) { // if timeout, we should return, check for the owner and re-wait job done. return ver, nil } @@ -1145,7 +1162,7 @@ func (w *worker) onDropTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) ( // A background job will be created to delete old partition data. job.Args = []interface{}{physicalTableIDs} default: - err = ErrInvalidDDLState.GenWithStackByArgs("partition", job.SchemaState) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("partition", job.SchemaState) } return ver, errors.Trace(err) } @@ -1158,13 +1175,13 @@ func onTruncateTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, e job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } pi := tblInfo.GetPartitionInfo() if pi == nil { - return ver, errors.Trace(ErrPartitionMgmtOnNonpartitioned) + return ver, errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } newPartitions := make([]model.PartitionDefinition, 0, len(oldIDs)) @@ -1190,6 +1207,15 @@ func onTruncateTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, e // Clear the tiflash replica available status. if tblInfo.TiFlashReplica != nil { + e := infosync.ConfigureTiFlashPDForPartitions(true, &newPartitions, tblInfo.TiFlashReplica.Count, &tblInfo.TiFlashReplica.LocationLabels, tblInfo.ID) + failpoint.Inject("FailTiFlashTruncatePartition", func() { + e = errors.New("enforced error") + }) + if e != nil { + logutil.BgLogger().Error("ConfigureTiFlashPDForPartitions fails", zap.Error(e)) + job.State = model.JobStateCancelled + return ver, e + } tblInfo.TiFlashReplica.Available = false // Set partition replica become unavailable. for _, oldID := range oldIDs { @@ -1288,7 +1314,7 @@ func (w *worker) onExchangeTablePartition(d *ddlCtx, t *meta.Meta, job *model.Jo return ver, errors.Trace(err) } - nt, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + nt, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -1303,7 +1329,7 @@ func (w *worker) onExchangeTablePartition(d *ddlCtx, t *meta.Meta, job *model.Jo if pt.State != model.StatePublic { job.State = model.JobStateCancelled - return ver, ErrInvalidDDLState.GenWithStack("table %s is not in public, but %s", pt.Name, pt.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStack("table %s is not in public, but %s", pt.Name, pt.State) } err = checkExchangePartition(pt, nt) @@ -1541,7 +1567,7 @@ func checkExchangePartitionRecordValidation(w *worker, pt *model.TableInfo, inde sql, paramList = buildCheckSQLForListColumnsPartition(pi, index, schemaName, tableName) } default: - return errUnsupportedPartitionType.GenWithStackByArgs(pt.Name.O) + return dbterror.ErrUnsupportedPartitionType.GenWithStackByArgs(pt.Name.O) } var ctx sessionctx.Context @@ -1551,17 +1577,13 @@ func checkExchangePartitionRecordValidation(w *worker, pt *model.TableInfo, inde } defer w.sessPool.put(ctx) - stmt, err := ctx.(sqlexec.RestrictedSQLExecutor).ParseWithParams(w.ddlJobCtx, sql, paramList...) - if err != nil { - return errors.Trace(err) - } - rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(w.ddlJobCtx, stmt) + rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(w.ddlJobCtx, nil, sql, paramList...) if err != nil { return errors.Trace(err) } rowCount := len(rows) if rowCount != 0 { - return errors.Trace(ErrRowDoesNotMatchPartition) + return errors.Trace(dbterror.ErrRowDoesNotMatchPartition) } return nil } @@ -1646,14 +1668,28 @@ func getInValues(pi *model.PartitionInfo, index int) []string { func checkAddPartitionTooManyPartitions(piDefs uint64) error { if piDefs > uint64(PartitionCountLimit) { - return errors.Trace(ErrTooManyPartitions) + return errors.Trace(dbterror.ErrTooManyPartitions) } return nil } func checkAddPartitionOnTemporaryMode(tbInfo *model.TableInfo) error { if tbInfo.Partition != nil && tbInfo.TempTableType != model.TempTableNone { - return ErrPartitionNoTemporary + return dbterror.ErrPartitionNoTemporary + } + return nil +} + +func checkPartitionColumnsUnique(tbInfo *model.TableInfo) error { + if len(tbInfo.Partition.Columns) <= 1 { + return nil + } + var columnsMap = make(map[string]struct{}) + for _, col := range tbInfo.Partition.Columns { + if _, ok := columnsMap[col.L]; ok { + return dbterror.ErrSameNamePartitionField.GenWithStackByArgs(col.L) + } + columnsMap[col.L] = struct{}{} } return nil } @@ -1716,10 +1752,10 @@ func checkPartitioningKeysConstraints(sctx sessionctx.Context, s *ast.CreateTabl for _, index := range tblInfo.Indices { if index.Unique && !checkUniqueKeyIncludePartKey(partCols, index.Columns) { if index.Primary { - return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY KEY") + return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY KEY") } if !config.GetGlobalConfig().EnableGlobalIndex { - return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX") + return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX") } } } @@ -1730,7 +1766,7 @@ func checkPartitioningKeysConstraints(sctx sessionctx.Context, s *ast.CreateTabl Length: types.UnspecifiedLength, }} if !checkUniqueKeyIncludePartKey(partCols, indexCols) { - return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY KEY") + return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY KEY") } } return nil @@ -1784,7 +1820,7 @@ func (cne *columnNameExtractor) Leave(node ast.Node) (ast.Node, bool) { cne.extractedColumns = append(cne.extractedColumns, info) return node, true } - cne.err = ErrBadField.GenWithStackByArgs(c.Name.Name.O, "expression") + cne.err = dbterror.ErrBadField.GenWithStackByArgs(c.Name.Name.O, "expression") return nil, false } return node, true @@ -1935,7 +1971,7 @@ func (p *partitionExprChecker) extractColumns(_ sessionctx.Context, _ *model.Tab } colInfo := findColumnByName(columnNameExpr.Name.Name.L, p.tbInfo) if colInfo == nil { - return errors.Trace(ErrBadField.GenWithStackByArgs(columnNameExpr.Name.Name.L, "partition function")) + return errors.Trace(dbterror.ErrBadField.GenWithStackByArgs(columnNameExpr.Name.Name.L, "partition function")) } p.columns = append(p.columns, colInfo) @@ -1960,7 +1996,7 @@ func checkPartitionExprAllowed(_ sessionctx.Context, tb *model.TableInfo, e ast. *ast.TimeUnitExpr: return nil } - return errors.Trace(ErrPartitionFunctionIsNotAllowed) + return errors.Trace(dbterror.ErrPartitionFunctionIsNotAllowed) } func checkPartitionExprArgs(_ sessionctx.Context, tblInfo *model.TableInfo, e ast.ExprNode) error { @@ -1992,7 +2028,7 @@ func checkPartitionExprArgs(_ sessionctx.Context, tblInfo *model.TableInfo, e as ast.TimeUnitSecond, ast.TimeUnitMicrosecond, ast.TimeUnitHourMicrosecond, ast.TimeUnitMinuteMicrosecond, ast.TimeUnitSecondMicrosecond: return errors.Trace(checkResultOK(hasTimeArgs(argsType...))) default: - return errors.Trace(ErrWrongExprInPartitionFunc) + return errors.Trace(dbterror.ErrWrongExprInPartitionFunc) } case ast.DateDiff: return errors.Trace(checkResultOK(slice.AllOf(argsType, func(i int) bool { @@ -2002,7 +2038,7 @@ func checkPartitionExprArgs(_ sessionctx.Context, tblInfo *model.TableInfo, e as case ast.Abs, ast.Ceiling, ast.Floor, ast.Mod: has := hasTimestampArgs(argsType...) if has { - return errors.Trace(ErrWrongExprInPartitionFunc) + return errors.Trace(dbterror.ErrWrongExprInPartitionFunc) } } return nil @@ -2017,7 +2053,7 @@ func collectArgsType(tblInfo *model.TableInfo, exprs ...ast.ExprNode) ([]byte, e } columnInfo := findColumnByName(col.Name.Name.L, tblInfo) if columnInfo == nil { - return nil, errors.Trace(ErrBadField.GenWithStackByArgs(col.Name.Name.L, "partition function")) + return nil, errors.Trace(dbterror.ErrBadField.GenWithStackByArgs(col.Name.Name.L, "partition function")) } ts = append(ts, columnInfo.Tp) } @@ -2055,7 +2091,7 @@ func checkNoTimestampArgs(tbInfo *model.TableInfo, exprs ...ast.ExprNode) error return err } if hasTimestampArgs(argsType...) { - return errors.Trace(ErrWrongExprInPartitionFunc) + return errors.Trace(dbterror.ErrWrongExprInPartitionFunc) } return nil } diff --git a/ddl/partition_test.go b/ddl/partition_test.go index f2cdd1c4e3597..4484dcb07dde8 100644 --- a/ddl/partition_test.go +++ b/ddl/partition_test.go @@ -16,55 +16,43 @@ package ddl import ( "context" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testPartitionSuite{}) - -type testPartitionSuite struct { - store kv.Storage -} - -func (s *testPartitionSuite) SetUpSuite(c *C) { - s.store = testCreateStore(c, "test_store") -} - -func (s *testPartitionSuite) TearDownSuite(c *C) { - err := s.store.Close() - c.Assert(err, IsNil) -} - -func (s *testPartitionSuite) TestDropAndTruncatePartition(c *C) { +func TestDropAndTruncatePartition(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + require.NoError(t, store.Close()) + }() d, err := testNewDDLAndStart( context.Background(), - WithStore(s.store), + WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, d.Stop()) }() dbInfo, err := testSchemaInfo(d, "test_partition") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) // generate 5 partition in tableInfo. - tblInfo, partIDs := buildTableInfoWithPartition(c, d) + tblInfo, partIDs := buildTableInfoWithPartition(t, d) ctx := testNewContext(d) - testCreateTable(c, ctx, d, dbInfo, tblInfo) - - testDropPartition(c, ctx, d, dbInfo, tblInfo, []string{"p0", "p1"}) - - testTruncatePartition(c, ctx, d, dbInfo, tblInfo, []int64{partIDs[3], partIDs[4]}) + testCreateTable(t, ctx, d, dbInfo, tblInfo) + testDropPartition(t, ctx, d, dbInfo, tblInfo, []string{"p0", "p1"}) + testTruncatePartition(t, ctx, d, dbInfo, tblInfo, []int64{partIDs[3], partIDs[4]}) } -func buildTableInfoWithPartition(c *C, d *ddl) (*model.TableInfo, []int64) { +func buildTableInfoWithPartition(t *testing.T, d *ddl) (*model.TableInfo, []int64) { tbl := &model.TableInfo{ Name: model.NewCIStr("t"), } @@ -76,14 +64,14 @@ func buildTableInfoWithPartition(c *C, d *ddl) (*model.TableInfo, []int64) { ID: allocateColumnID(tbl), } genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) + require.NoError(t, err) tbl.ID = genIDs[0] tbl.Columns = []*model.ColumnInfo{col} tbl.Charset = "utf8" tbl.Collate = "utf8_bin" partIDs, err := d.genGlobalIDs(5) - c.Assert(err, IsNil) + require.NoError(t, err) partInfo := &model.PartitionInfo{ Type: model.PartitionTypeRange, Expr: tbl.Columns[0].Name.L, @@ -130,12 +118,13 @@ func buildDropPartitionJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, partN } } -func testDropPartition(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, partNames []string) *model.Job { +func testDropPartition(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, partNames []string) *model.Job { job := buildDropPartitionJob(dbInfo, tblInfo, partNames) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } @@ -149,11 +138,12 @@ func buildTruncatePartitionJob(dbInfo *model.DBInfo, tblInfo *model.TableInfo, p } } -func testTruncatePartition(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, pids []int64) *model.Job { +func testTruncatePartition(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, pids []int64) *model.Job { job := buildTruncatePartitionJob(dbInfo, tblInfo, pids) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } diff --git a/ddl/placement/bundle.go b/ddl/placement/bundle.go index fe160c7653565..71e61a839de60 100644 --- a/ddl/placement/bundle.go +++ b/ddl/placement/bundle.go @@ -85,49 +85,43 @@ func NewBundleFromConstraintsOptions(options *model.PlacementSettings) (*Bundle, return nil, fmt.Errorf("%w: LeaderConstraints conflicts with Constraints", err) } } - if len(LeaderConstraints) > 0 { - Rules = append(Rules, NewRule(Leader, 1, LeaderConstraints)) - } else if followerCount == 0 { - return nil, fmt.Errorf("%w: you must at least provide common/leader constraints, or set some followers", ErrInvalidPlacementOptions) - } - - if followerCount > 0 { - // if user did not specify leader, add one - if len(LeaderConstraints) == 0 { - Rules = append(Rules, NewRule(Leader, 1, NewConstraintsDirect())) - } + Rules = append(Rules, NewRule(Leader, 1, LeaderConstraints)) - FollowerRules, err := NewRules(Voter, followerCount, followerConstraints) - if err != nil { - return nil, fmt.Errorf("%w: invalid FollowerConstraints", err) + FollowerRules, err := NewRules(Voter, followerCount, followerConstraints) + if err != nil { + return nil, fmt.Errorf("%w: invalid FollowerConstraints", err) + } + for _, rule := range FollowerRules { + // give a default of 2 followers + if rule.Count == 0 { + rule.Count = 2 } - for _, rule := range FollowerRules { - for _, cnst := range CommonConstraints { - if err := rule.Constraints.Add(cnst); err != nil { - return nil, fmt.Errorf("%w: FollowerConstraints conflicts with Constraints", err) - } + for _, cnst := range CommonConstraints { + if err := rule.Constraints.Add(cnst); err != nil { + return nil, fmt.Errorf("%w: FollowerConstraints conflicts with Constraints", err) } } - Rules = append(Rules, FollowerRules...) - } else if followerConstraints != "" { - return nil, fmt.Errorf("%w: specify follower constraints without specify how many followers to be placed", ErrInvalidPlacementOptions) } + Rules = append(Rules, FollowerRules...) - if learnerCount > 0 { - LearnerRules, err := NewRules(Learner, learnerCount, learnerConstraints) - if err != nil { - return nil, fmt.Errorf("%w: invalid LearnerConstraints", err) + LearnerRules, err := NewRules(Learner, learnerCount, learnerConstraints) + if err != nil { + return nil, fmt.Errorf("%w: invalid LearnerConstraints", err) + } + for _, rule := range LearnerRules { + if rule.Count == 0 { + if len(rule.Constraints) > 0 { + return nil, fmt.Errorf("%w: specify learner constraints without specify how many learners to be placed", ErrInvalidPlacementOptions) + } } - for _, rule := range LearnerRules { - for _, cnst := range CommonConstraints { - if err := rule.Constraints.Add(cnst); err != nil { - return nil, fmt.Errorf("%w: LearnerConstraints conflicts with Constraints", err) - } + for _, cnst := range CommonConstraints { + if err := rule.Constraints.Add(cnst); err != nil { + return nil, fmt.Errorf("%w: LearnerConstraints conflicts with Constraints", err) } } - Rules = append(Rules, LearnerRules...) - } else if learnerConstraints != "" { - return nil, fmt.Errorf("%w: specify learner constraints without specify how many learners to be placed", ErrInvalidPlacementOptions) + if rule.Count > 0 { + Rules = append(Rules, rule) + } } return &Bundle{Rules: Rules}, nil @@ -159,18 +153,20 @@ func NewBundleFromSugarOptions(options *model.PlacementSettings) (*Bundle, error } schedule := options.Schedule - primaryIndex := 0 - // regions must include the primary - // but we don't see empty primaryRegion and regions as an error - if primaryRegion != "" || len(regions) > 0 { - sort.Strings(regions) - primaryIndex = sort.SearchStrings(regions, primaryRegion) - if primaryIndex >= len(regions) || regions[primaryIndex] != primaryRegion { - return nil, fmt.Errorf("%w: primary region must be included in regions", ErrInvalidPlacementOptions) - } + var Rules []*Rule + + // in case empty primaryRegion and regions, just return an empty bundle + if primaryRegion == "" && len(regions) == 0 { + Rules = append(Rules, NewRule(Voter, followers+1, NewConstraintsDirect())) + return &Bundle{Rules: Rules}, nil } - var Rules []*Rule + // regions must include the primary + sort.Strings(regions) + primaryIndex := sort.SearchStrings(regions, primaryRegion) + if primaryIndex >= len(regions) || regions[primaryIndex] != primaryRegion { + return nil, fmt.Errorf("%w: primary region must be included in regions", ErrInvalidPlacementOptions) + } // primaryCount only makes sense when len(regions) > 0 // but we will compute it here anyway for reusing code @@ -180,20 +176,20 @@ func NewBundleFromSugarOptions(options *model.PlacementSettings) (*Bundle, error primaryCount = uint64(math.Ceil(float64(followers+1) / float64(len(regions)))) case "majority_in_primary": // calculate how many replicas need to be in the primary region for quorum - primaryCount = uint64(math.Ceil(float64(followers+1)/2 + 1)) + primaryCount = (followers+1)/2 + 1 default: return nil, fmt.Errorf("%w: unsupported schedule %s", ErrInvalidPlacementOptions, schedule) } - if len(regions) == 0 { - Rules = append(Rules, NewRule(Voter, followers+1, NewConstraintsDirect())) - } else { - Rules = append(Rules, NewRule(Voter, primaryCount, NewConstraintsDirect(NewConstraintDirect("region", In, primaryRegion)))) + Rules = append(Rules, NewRule(Voter, primaryCount, NewConstraintsDirect(NewConstraintDirect("region", In, primaryRegion)))) + if followers+1 > primaryCount { + // delete primary from regions + regions = regions[:primaryIndex+copy(regions[primaryIndex:], regions[primaryIndex+1:])] - if followers+1 > primaryCount { - // delete primary from regions - regions = regions[:primaryIndex+copy(regions[primaryIndex:], regions[primaryIndex+1:])] + if len(regions) > 0 { Rules = append(Rules, NewRule(Follower, followers+1-primaryCount, NewConstraintsDirect(NewConstraintDirect("region", In, regions...)))) + } else { + Rules = append(Rules, NewRule(Follower, followers+1-primaryCount, NewConstraintsDirect())) } } @@ -423,7 +419,7 @@ func (b *Bundle) GetLeaderDC(dcLabelKey string) (string, bool) { // If table is a partitioned table, it also contains the rules that inherited from table for every partition. // The bundle does not contain the rules specified independently by each partition func NewTableBundle(t *meta.Meta, tbInfo *model.TableInfo) (*Bundle, error) { - bundle, err := newBundleFromPolicyOrDirectOptions(t, tbInfo.PlacementPolicyRef, tbInfo.DirectPlacementOpts) + bundle, err := newBundleFromPolicy(t, tbInfo.PlacementPolicyRef) if err != nil { return nil, err } @@ -446,7 +442,7 @@ func NewTableBundle(t *meta.Meta, tbInfo *model.TableInfo) (*Bundle, error) { // It only contains the rules specified independently by the partition. // That is to say the inherited rules from table is not included. func NewPartitionBundle(t *meta.Meta, def model.PartitionDefinition) (*Bundle, error) { - bundle, err := newBundleFromPolicyOrDirectOptions(t, def.PlacementPolicyRef, def.DirectPlacementOpts) + bundle, err := newBundleFromPolicy(t, def.PlacementPolicyRef) if err != nil { return nil, err } @@ -498,11 +494,7 @@ func NewFullTableBundles(t *meta.Meta, tbInfo *model.TableInfo) ([]*Bundle, erro return bundles, nil } -func newBundleFromPolicyOrDirectOptions(t *meta.Meta, ref *model.PolicyRefInfo, directOpts *model.PlacementSettings) (*Bundle, error) { - if directOpts != nil { - return NewBundleFromOptions(directOpts) - } - +func newBundleFromPolicy(t *meta.Meta, ref *model.PolicyRefInfo) (*Bundle, error) { if ref != nil { policy, err := t.GetPolicy(ref.ID) if err != nil { diff --git a/ddl/placement/bundle_test.go b/ddl/placement/bundle_test.go index 225f17f398552..b59f349609f87 100644 --- a/ddl/placement/bundle_test.go +++ b/ddl/placement/bundle_test.go @@ -16,48 +16,45 @@ package placement import ( "encoding/hex" - "errors" + "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testBundleSuite{}) - -type testBundleSuite struct{} - -func (s *testBundleSuite) TestEmpty(c *C) { +func TestEmpty(t *testing.T) { bundle := &Bundle{ID: GroupID(1)} - c.Assert(bundle.IsEmpty(), IsTrue) + require.True(t, bundle.IsEmpty()) bundle = &Bundle{ID: GroupID(1), Index: 1} - c.Assert(bundle.IsEmpty(), IsFalse) + require.False(t, bundle.IsEmpty()) bundle = &Bundle{ID: GroupID(1), Override: true} - c.Assert(bundle.IsEmpty(), IsFalse) + require.False(t, bundle.IsEmpty()) bundle = &Bundle{ID: GroupID(1), Rules: []*Rule{{ID: "434"}}} - c.Assert(bundle.IsEmpty(), IsFalse) + require.False(t, bundle.IsEmpty()) bundle = &Bundle{ID: GroupID(1), Index: 1, Override: true} - c.Assert(bundle.IsEmpty(), IsFalse) + require.False(t, bundle.IsEmpty()) } -func (s *testBundleSuite) TestClone(c *C) { +func TestCloneBundle(t *testing.T) { bundle := &Bundle{ID: GroupID(1), Rules: []*Rule{{ID: "434"}}} newBundle := bundle.Clone() newBundle.ID = GroupID(2) newBundle.Rules[0] = &Rule{ID: "121"} - c.Assert(bundle, DeepEquals, &Bundle{ID: GroupID(1), Rules: []*Rule{{ID: "434"}}}) - c.Assert(newBundle, DeepEquals, &Bundle{ID: GroupID(2), Rules: []*Rule{{ID: "121"}}}) + require.Equal(t, &Bundle{ID: GroupID(1), Rules: []*Rule{{ID: "434"}}}, bundle) + require.Equal(t, &Bundle{ID: GroupID(2), Rules: []*Rule{{ID: "121"}}}, newBundle) } -func (s *testBundleSuite) TestObjectID(c *C) { +func TestObjectID(t *testing.T) { type TestCase struct { name string bundleID string @@ -72,20 +69,19 @@ func (s *testBundleSuite) TestObjectID(c *C) { {"id of negatives", "TiDB_DDL_-10", 0, ErrInvalidBundleID}, {"id of positive integer", "TiDB_DDL_10", 10, nil}, } - for _, t := range tests { - comment := Commentf("%s", t.name) - bundle := Bundle{ID: t.bundleID} + for _, test := range tests { + bundle := Bundle{ID: test.bundleID} id, err := bundle.ObjectID() - if t.err == nil { - c.Assert(err, IsNil, comment) - c.Assert(id, Equals, t.expectedID, comment) + if test.err == nil { + require.NoError(t, err, test.name) + require.Equal(t, test.expectedID, id, test.name) } else { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + require.ErrorIs(t, err, test.err, test.name) } } } -func (s *testBundleSuite) TestGetLeaderDCByBundle(c *C) { +func TestGetLeaderDCByBundle(t *testing.T) { testcases := []struct { name string bundle *Bundle @@ -330,49 +326,48 @@ func (s *testBundleSuite) TestGetLeaderDCByBundle(c *C) { }, } for _, testcase := range testcases { - comment := Commentf("%s", testcase.name) result, ok := testcase.bundle.GetLeaderDC("zone") if len(testcase.expectedDC) > 0 { - c.Assert(ok, Equals, true, comment) + require.True(t, ok, testcase.name) } else { - c.Assert(ok, Equals, false, comment) + require.False(t, ok, testcase.name) } - c.Assert(result, Equals, testcase.expectedDC, comment) + require.Equal(t, testcase.expectedDC, result, testcase.name) } } -func (s *testBundleSuite) TestString(c *C) { +func TestString(t *testing.T) { bundle := &Bundle{ ID: GroupID(1), } rules1, err := NewRules(Voter, 3, `["+zone=sh", "+zone=sh"]`) - c.Assert(err, IsNil) + require.NoError(t, err) rules2, err := NewRules(Voter, 4, `["-zone=sh", "+zone=bj"]`) - c.Assert(err, IsNil) + require.NoError(t, err) bundle.Rules = append(rules1, rules2...) - c.Assert(bundle.String(), Equals, `{"group_id":"TiDB_DDL_1","group_index":0,"group_override":false,"rules":[{"group_id":"","id":"","start_key":"","end_key":"","role":"voter","count":3,"label_constraints":[{"key":"zone","op":"in","values":["sh"]}],"location_labels":["region","zone","rack","host"],"isolation_level":"region"},{"group_id":"","id":"","start_key":"","end_key":"","role":"voter","count":4,"label_constraints":[{"key":"zone","op":"notIn","values":["sh"]},{"key":"zone","op":"in","values":["bj"]}],"location_labels":["region","zone","rack","host"],"isolation_level":"region"}]}`) + require.Equal(t, "{\"group_id\":\"TiDB_DDL_1\",\"group_index\":0,\"group_override\":false,\"rules\":[{\"group_id\":\"\",\"id\":\"\",\"start_key\":\"\",\"end_key\":\"\",\"role\":\"voter\",\"count\":3,\"label_constraints\":[{\"key\":\"zone\",\"op\":\"in\",\"values\":[\"sh\"]}]},{\"group_id\":\"\",\"id\":\"\",\"start_key\":\"\",\"end_key\":\"\",\"role\":\"voter\",\"count\":4,\"label_constraints\":[{\"key\":\"zone\",\"op\":\"notIn\",\"values\":[\"sh\"]},{\"key\":\"zone\",\"op\":\"in\",\"values\":[\"bj\"]}]}]}", bundle.String()) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/placement/MockMarshalFailure", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/placement/MockMarshalFailure", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/placement/MockMarshalFailure"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/placement/MockMarshalFailure")) }() - c.Assert(bundle.String(), Equals, "") + require.Equal(t, "", bundle.String()) } -func (s *testBundleSuite) TestNew(c *C) { - c.Assert(NewBundle(3), DeepEquals, &Bundle{ID: GroupID(3)}) - c.Assert(NewBundle(-1), DeepEquals, &Bundle{ID: GroupID(-1)}) +func TestNewBundle(t *testing.T) { + require.Equal(t, &Bundle{ID: GroupID(3)}, NewBundle(3)) + require.Equal(t, &Bundle{ID: GroupID(-1)}, NewBundle(-1)) _, err := NewBundleFromConstraintsOptions(nil) - c.Assert(err, NotNil) + require.Error(t, err) _, err = NewBundleFromSugarOptions(nil) - c.Assert(err, NotNil) + require.Error(t, err) _, err = NewBundleFromOptions(nil) - c.Assert(err, NotNil) + require.Error(t, err) } -func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { +func TestNewBundleFromOptions(t *testing.T) { type TestCase struct { name string input *model.PlacementSettings @@ -416,6 +411,21 @@ func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { }, }) + tests = append(tests, TestCase{ + name: "sugar syntax: normal case 2", + input: &model.PlacementSettings{ + PrimaryRegion: "us", + Regions: "us", + Schedule: "majority_in_primary", + }, + output: []*Rule{ + NewRule(Voter, 2, NewConstraintsDirect( + NewConstraintDirect("region", In, "us"), + )), + NewRule(Follower, 1, NewConstraintsDirect()), + }, + }) + tests = append(tests, TestCase{ name: "sugar syntax: few followers", input: &model.PlacementSettings{ @@ -517,11 +527,11 @@ func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { input: &model.PlacementSettings{ PrimaryRegion: "sh", Regions: "bj,sh", - Followers: 5, + Followers: 4, Schedule: "majority_in_primary", }, output: []*Rule{ - NewRule(Voter, 4, NewConstraintsDirect( + NewRule(Voter, 3, NewConstraintsDirect( NewConstraintDirect("region", In, "sh"), )), NewRule(Follower, 2, NewConstraintsDirect( @@ -534,7 +544,6 @@ func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { name: "direct syntax: normal case 1", input: &model.PlacementSettings{ Constraints: "[+region=us]", - Followers: 2, }, output: []*Rule{ NewRule(Leader, 1, NewConstraintsDirect( @@ -572,7 +581,10 @@ func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { LeaderConstraints: "[+region=as]", FollowerConstraints: "[-region=us]", }, - err: ErrInvalidPlacementOptions, + output: []*Rule{ + NewRule(Leader, 1, NewConstraintsDirect(NewConstraintDirect("region", In, "as"))), + NewRule(Voter, 2, NewConstraintsDirect(NewConstraintDirect("region", NotIn, "us"))), + }, }) tests = append(tests, TestCase{ @@ -668,42 +680,63 @@ func (s *testBundleSuite) TestNewBundleFromOptions(c *C) { err: ErrInvalidConstraintsFormat, }) - for _, t := range tests { - bundle, err := newBundleFromOptions(t.input) - comment := Commentf("[%s]\nerr1 %s\nerr2 %s", t.name, err, t.err) - if t.err != nil { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + tests = append(tests, TestCase{ + name: "direct syntax: learner dict constraints", + input: &model.PlacementSettings{ + LearnerConstraints: `{"+region=us": 2}`, + }, + output: []*Rule{ + NewRule(Leader, 1, NewConstraintsDirect()), + NewRule(Voter, 2, NewConstraintsDirect()), + NewRule(Learner, 2, NewConstraintsDirect(NewConstraintDirect("region", In, "us"))), + }, + }) + + tests = append(tests, TestCase{ + name: "direct syntax: learner dict constraints, with count", + input: &model.PlacementSettings{ + LearnerConstraints: `{"+region=us": 2}`, + Learners: 4, + }, + err: ErrInvalidConstraintsRelicas, + }) + + for _, test := range tests { + bundle, err := newBundleFromOptions(test.input) + comment := fmt.Sprintf("[%s]\nerr1 %s\nerr2 %s", test.name, err, test.err) + if test.err != nil { + require.ErrorIs(t, err, test.err, comment) } else { - c.Assert(err, IsNil, comment) - matchRules(t.output, bundle.Rules, comment.CheckCommentString(), c) + require.NoError(t, err, comment) + matchRules(test.output, bundle.Rules, comment, t) } } } -func (s *testBundleSuite) TestResetBundleWithSingleRule(c *C) { +func TestResetBundleWithSingleRule(t *testing.T) { bundle := &Bundle{ ID: GroupID(1), } rules, err := NewRules(Voter, 3, `["+zone=sh", "+zone=sh"]`) - c.Assert(err, IsNil) + require.NoError(t, err) bundle.Rules = rules bundle.Reset(RuleIndexTable, []int64{3}) - c.Assert(bundle.ID, Equals, GroupID(3)) - c.Assert(bundle.Override, Equals, true) - c.Assert(bundle.Index, Equals, RuleIndexTable) - c.Assert(bundle.Rules, HasLen, 1) - c.Assert(bundle.Rules[0].GroupID, Equals, bundle.ID) + require.Equal(t, GroupID(3), bundle.ID) + require.Equal(t, true, bundle.Override) + require.Equal(t, RuleIndexTable, bundle.Index) + require.Len(t, bundle.Rules, 1) + require.Equal(t, bundle.ID, bundle.Rules[0].GroupID) startKey := hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(3))) - c.Assert(bundle.Rules[0].StartKeyHex, Equals, startKey) + require.Equal(t, startKey, bundle.Rules[0].StartKeyHex) endKey := hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(4))) - c.Assert(bundle.Rules[0].EndKeyHex, Equals, endKey) + require.Equal(t, endKey, bundle.Rules[0].EndKeyHex) } -func (s *testBundleSuite) TestResetBundleWithMultiRules(c *C) { +func TestResetBundleWithMultiRules(t *testing.T) { // build a bundle with three rules. bundle, err := NewBundleFromOptions(&model.PlacementSettings{ LeaderConstraints: `["+zone=bj"]`, @@ -713,129 +746,129 @@ func (s *testBundleSuite) TestResetBundleWithMultiRules(c *C) { LearnerConstraints: `["+zone=cd"]`, Constraints: `["+disk=ssd"]`, }) - c.Assert(err, IsNil) - c.Assert(len(bundle.Rules), Equals, 3) + require.NoError(t, err) + require.Equal(t, 3, len(bundle.Rules)) // test if all the three rules are basic rules even the start key are not set. bundle.Reset(RuleIndexTable, []int64{1, 2, 3}) - c.Assert(bundle.ID, Equals, GroupID(1)) - c.Assert(bundle.Index, Equals, RuleIndexTable) - c.Assert(bundle.Override, Equals, true) - c.Assert(len(bundle.Rules), Equals, 3*3) + require.Equal(t, GroupID(1), bundle.ID) + require.Equal(t, RuleIndexTable, bundle.Index) + require.Equal(t, true, bundle.Override) + require.Equal(t, 3*3, len(bundle.Rules)) // for id 1. startKey := hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(1))) endKey := hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(2))) - c.Assert(bundle.Rules[0].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[0].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[1].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[1].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[2].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[2].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[0].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[0].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[1].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[1].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[2].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[2].EndKeyHex) // for id 2. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(2))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(3))) - c.Assert(bundle.Rules[3].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[3].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[4].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[4].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[5].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[5].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[3].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[3].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[4].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[4].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[5].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[5].EndKeyHex) // for id 3. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(3))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(4))) - c.Assert(bundle.Rules[6].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[6].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[7].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[7].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[8].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[8].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[6].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[6].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[7].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[7].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[8].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[8].EndKeyHex) // test if bundle has redundant rules. // for now, the bundle has 9 rules, each table id or partition id has the three with them. // once we reset this bundle for another ids, for example, adding partitions. we should // extend the basic rules(3 of them) to the new partition id. bundle.Reset(RuleIndexTable, []int64{1, 3, 4, 5}) - c.Assert(bundle.ID, Equals, GroupID(1)) - c.Assert(bundle.Index, Equals, RuleIndexTable) - c.Assert(bundle.Override, Equals, true) - c.Assert(len(bundle.Rules), Equals, 3*4) + require.Equal(t, GroupID(1), bundle.ID) + require.Equal(t, RuleIndexTable, bundle.Index) + require.Equal(t, true, bundle.Override) + require.Equal(t, 3*4, len(bundle.Rules)) // for id 1. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(1))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(2))) - c.Assert(bundle.Rules[0].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[0].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[1].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[1].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[2].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[2].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[0].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[0].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[1].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[1].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[2].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[2].EndKeyHex) // for id 3. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(3))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(4))) - c.Assert(bundle.Rules[3].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[3].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[4].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[4].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[5].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[5].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[3].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[3].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[4].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[4].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[5].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[5].EndKeyHex) // for id 4. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(4))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(5))) - c.Assert(bundle.Rules[6].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[6].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[7].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[7].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[8].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[8].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[6].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[6].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[7].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[7].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[8].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[8].EndKeyHex) // for id 5. startKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(5))) endKey = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(6))) - c.Assert(bundle.Rules[9].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[9].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[10].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[10].EndKeyHex, Equals, endKey) - c.Assert(bundle.Rules[11].StartKeyHex, Equals, startKey) - c.Assert(bundle.Rules[11].EndKeyHex, Equals, endKey) + require.Equal(t, startKey, bundle.Rules[9].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[9].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[10].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[10].EndKeyHex) + require.Equal(t, startKey, bundle.Rules[11].StartKeyHex) + require.Equal(t, endKey, bundle.Rules[11].EndKeyHex) } -func (s *testBundleSuite) TestTidy(c *C) { +func TestTidy(t *testing.T) { bundle := &Bundle{ ID: GroupID(1), } rules0, err := NewRules(Voter, 1, `["+zone=sh", "+zone=sh"]`) - c.Assert(err, IsNil) - c.Assert(rules0, HasLen, 1) + require.NoError(t, err) + require.Len(t, rules0, 1) rules0[0].Count = 0 // test prune useless rules rules1, err := NewRules(Voter, 4, `["-zone=sh", "+zone=bj"]`) - c.Assert(err, IsNil) - c.Assert(rules1, HasLen, 1) + require.NoError(t, err) + require.Len(t, rules1, 1) rules2, err := NewRules(Voter, 4, `["-zone=sh", "+zone=bj"]`) - c.Assert(err, IsNil) + require.NoError(t, err) bundle.Rules = append(bundle.Rules, rules0...) bundle.Rules = append(bundle.Rules, rules1...) bundle.Rules = append(bundle.Rules, rules2...) err = bundle.Tidy() - c.Assert(err, IsNil) - c.Assert(bundle.Rules, HasLen, 2) - c.Assert(bundle.Rules[0].ID, Equals, "1") - c.Assert(bundle.Rules[0].Constraints, HasLen, 3) - c.Assert(bundle.Rules[0].Constraints[2], DeepEquals, Constraint{ + require.NoError(t, err) + require.Len(t, bundle.Rules, 2) + require.Equal(t, "1", bundle.Rules[0].ID) + require.Len(t, bundle.Rules[0].Constraints, 3) + require.Equal(t, Constraint{ Op: NotIn, Key: EngineLabelKey, Values: []string{EngineLabelTiFlash}, - }) - c.Assert(bundle.Rules[1].ID, Equals, "2") + }, bundle.Rules[0].Constraints[2]) + require.Equal(t, "2", bundle.Rules[1].ID) // merge rules3, err := NewRules(Follower, 4, "") - c.Assert(err, IsNil) - c.Assert(rules3, HasLen, 1) + require.NoError(t, err) + require.Len(t, rules3, 1) rules4, err := NewRules(Follower, 5, "") - c.Assert(err, IsNil) - c.Assert(rules4, HasLen, 1) + require.NoError(t, err) + require.Len(t, rules4, 1) rules0[0].Role = Voter bundle.Rules = append(bundle.Rules, rules0...) @@ -843,19 +876,19 @@ func (s *testBundleSuite) TestTidy(c *C) { bundle.Rules = append(bundle.Rules, rules4...) chkfunc := func() { - c.Assert(err, IsNil) - c.Assert(bundle.Rules, HasLen, 3) - c.Assert(bundle.Rules[0].ID, Equals, "0") - c.Assert(bundle.Rules[1].ID, Equals, "1") - c.Assert(bundle.Rules[2].ID, Equals, "follower") - c.Assert(bundle.Rules[2].Count, Equals, 9) - c.Assert(bundle.Rules[2].Constraints, DeepEquals, Constraints{ + require.NoError(t, err) + require.Len(t, bundle.Rules, 3) + require.Equal(t, "0", bundle.Rules[0].ID) + require.Equal(t, "1", bundle.Rules[1].ID) + require.Equal(t, "follower", bundle.Rules[2].ID) + require.Equal(t, 9, bundle.Rules[2].Count) + require.Equal(t, Constraints{ { Op: NotIn, Key: EngineLabelKey, Values: []string{EngineLabelTiFlash}, }, - }) + }, bundle.Rules[2].Constraints) } err = bundle.Tidy() chkfunc() @@ -869,15 +902,13 @@ func (s *testBundleSuite) TestTidy(c *C) { // it should be stable bundle2 := bundle.Clone() err = bundle2.Tidy() - c.Assert(err, IsNil) - c.Assert(bundle2, DeepEquals, bundle) + require.NoError(t, err) + require.Equal(t, bundle, bundle2) bundle.Rules[2].Constraints = append(bundle.Rules[2].Constraints, Constraint{ Op: In, Key: EngineLabelKey, Values: []string{EngineLabelTiFlash}, }) - c.Log(bundle.Rules[2]) - err = bundle.Tidy() - c.Assert(errors.Is(err, ErrConflictingConstraints), IsTrue) + require.ErrorIs(t, bundle.Tidy(), ErrConflictingConstraints) } diff --git a/ddl/placement/common.go b/ddl/placement/common.go index 6a17c13388d6a..8421a6cbbc33e 100644 --- a/ddl/placement/common.go +++ b/ddl/placement/common.go @@ -35,6 +35,8 @@ const ( RuleIndexTable = 40 // RuleIndexPartition is the index for a rule of partition. RuleIndexPartition = 80 + // RuleIndexTiFlash is the index for a rule of TiFlash. + RuleIndexTiFlash = 120 ) const ( diff --git a/ddl/placement/common_test.go b/ddl/placement/common_test.go index 75c3285965dbd..b22226f29c948 100644 --- a/ddl/placement/common_test.go +++ b/ddl/placement/common_test.go @@ -17,19 +17,11 @@ package placement import ( "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -func TestT(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&testCommonSuite{}) - -type testCommonSuite struct{} - -func (t *testCommonSuite) TestGroup(c *C) { - c.Assert(GroupID(1), Equals, "TiDB_DDL_1") - c.Assert(GroupID(90), Equals, "TiDB_DDL_90") - c.Assert(GroupID(-1), Equals, "TiDB_DDL_-1") +func TestGroup(t *testing.T) { + require.Equal(t, "TiDB_DDL_1", GroupID(1)) + require.Equal(t, "TiDB_DDL_90", GroupID(90)) + require.Equal(t, "TiDB_DDL_-1", GroupID(-1)) } diff --git a/ddl/placement/constraint_test.go b/ddl/placement/constraint_test.go index a83aaa0098ab1..739d7bf6b5ba6 100644 --- a/ddl/placement/constraint_test.go +++ b/ddl/placement/constraint_test.go @@ -15,23 +15,20 @@ package placement import ( - "errors" + "fmt" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testConstraintSuite{}) - -type testConstraintSuite struct{} - -func (t *testConstraintSuite) TestNewFromYaml(c *C) { +func TestNewFromYaml(t *testing.T) { _, err := NewConstraintsFromYaml([]byte("[]")) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = NewConstraintsFromYaml([]byte("]")) - c.Assert(err, NotNil) + require.Error(t, err) } -func (t *testConstraintSuite) TestNew(c *C) { +func TestNewConstraint(t *testing.T) { type TestCase struct { name string input string @@ -114,19 +111,19 @@ func (t *testConstraintSuite) TestNew(c *C) { }, } - for _, t := range tests { - label, err := NewConstraint(t.input) - comment := Commentf("%s: %v", t.name, err) - if t.err == nil { - c.Assert(err, IsNil, comment) - c.Assert(label, DeepEquals, t.label, comment) + for _, test := range tests { + label, err := NewConstraint(test.input) + comment := fmt.Sprintf("%s: %v", test.name, err) + if test.err == nil { + require.NoError(t, err, comment) + require.Equal(t, test.label, label, comment) } else { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + require.ErrorIs(t, err, test.err, comment) } } } -func (t *testConstraintSuite) TestRestore(c *C) { +func TestRestoreConstraint(t *testing.T) { type TestCase struct { name string input Constraint @@ -136,7 +133,7 @@ func (t *testConstraintSuite) TestRestore(c *C) { var tests []TestCase input, err := NewConstraint("+zone=bj") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ name: "normal, op in", input: input, @@ -144,7 +141,7 @@ func (t *testConstraintSuite) TestRestore(c *C) { }) input, err = NewConstraint("+ zone = bj ") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ name: "normal with spaces, op in", input: input, @@ -152,7 +149,7 @@ func (t *testConstraintSuite) TestRestore(c *C) { }) input, err = NewConstraint("- zone = bj ") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ name: "normal with spaces, op not in", input: input, @@ -189,19 +186,19 @@ func (t *testConstraintSuite) TestRestore(c *C) { err: ErrInvalidConstraintFormat, }) - for _, t := range tests { - output, err := t.input.Restore() - comment := Commentf("%s: %v", t.name, err) - if t.err == nil { - c.Assert(err, IsNil, comment) - c.Assert(output, Equals, t.output, comment) + for _, test := range tests { + output, err := test.input.Restore() + comment := fmt.Sprintf("%s: %v", test.name, err) + if test.err == nil { + require.NoError(t, err, comment) + require.Equal(t, test.output, output, comment) } else { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + require.ErrorIs(t, err, test.err, comment) } } } -func (t *testConstraintSuite) TestCompatibleWith(c *C) { +func TestCompatibleWith(t *testing.T) { type TestCase struct { name string i1 Constraint @@ -211,9 +208,9 @@ func (t *testConstraintSuite) TestCompatibleWith(c *C) { var tests []TestCase i1, err := NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) i2, err := NewConstraint("-zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "case 2", i1, i2, @@ -221,9 +218,9 @@ func (t *testConstraintSuite) TestCompatibleWith(c *C) { }) i1, err = NewConstraint("+zone=bj") - c.Assert(err, IsNil) + require.NoError(t, err) i2, err = NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "case 3", i1, i2, @@ -231,9 +228,9 @@ func (t *testConstraintSuite) TestCompatibleWith(c *C) { }) i1, err = NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) i2, err = NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "case 1", i1, i2, @@ -241,9 +238,9 @@ func (t *testConstraintSuite) TestCompatibleWith(c *C) { }) i1, err = NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) i2, err = NewConstraint("+dc=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "normal 1", i1, i2, @@ -251,17 +248,16 @@ func (t *testConstraintSuite) TestCompatibleWith(c *C) { }) i1, err = NewConstraint("-zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) i2, err = NewConstraint("-zone=bj") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "normal 2", i1, i2, ConstraintCompatible, }) - for _, t := range tests { - comment := Commentf("%s", t.name) - c.Assert(t.i1.CompatibleWith(&t.i2), Equals, t.output, comment) + for _, test := range tests { + require.Equal(t, test.output, test.i1.CompatibleWith(&test.i2), test.name) } } diff --git a/ddl/placement/constraints_test.go b/ddl/placement/constraints_test.go index ef15c878943c9..17a4b03843255 100644 --- a/ddl/placement/constraints_test.go +++ b/ddl/placement/constraints_test.go @@ -15,30 +15,27 @@ package placement import ( - "errors" + "fmt" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testConstraintsSuite{}) - -type testConstraintsSuite struct{} - -func (t *testConstraintsSuite) TestNew(c *C) { +func TestNewConstraints(t *testing.T) { _, err := NewConstraints(nil) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = NewConstraints([]string{}) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = NewConstraints([]string{"+zonesh"}) - c.Assert(errors.Is(err, ErrInvalidConstraintFormat), IsTrue) + require.ErrorIs(t, err, ErrInvalidConstraintFormat) _, err = NewConstraints([]string{"+zone=sh", "-zone=sh"}) - c.Assert(errors.Is(err, ErrConflictingConstraints), IsTrue) + require.ErrorIs(t, err, ErrConflictingConstraints) } -func (t *testConstraintsSuite) TestAdd(c *C) { +func TestAdd(t *testing.T) { type TestCase struct { name string labels Constraints @@ -48,9 +45,9 @@ func (t *testConstraintsSuite) TestAdd(c *C) { var tests []TestCase labels, err := NewConstraints([]string{"+zone=sh"}) - c.Assert(err, IsNil) + require.NoError(t, err) label, err := NewConstraint("-zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "always false match", labels, label, @@ -58,9 +55,9 @@ func (t *testConstraintsSuite) TestAdd(c *C) { }) labels, err = NewConstraints([]string{"+zone=sh"}) - c.Assert(err, IsNil) + require.NoError(t, err) label, err = NewConstraint("+zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "duplicated constraints, skip", labels, label, @@ -78,7 +75,7 @@ func (t *testConstraintsSuite) TestAdd(c *C) { }) labels, err = NewConstraints([]string{"+zone=sh"}) - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "invalid label in operand", labels, Constraint{Op: "["}, @@ -98,28 +95,28 @@ func (t *testConstraintsSuite) TestAdd(c *C) { }) labels, err = NewConstraints([]string{"+zone=sh"}) - c.Assert(err, IsNil) + require.NoError(t, err) label, err = NewConstraint("-zone=bj") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "normal", labels, label, nil, }) - for _, t := range tests { - err := t.labels.Add(t.label) - comment := Commentf("%s: %v", t.name, err) - if t.err == nil { - c.Assert(err, IsNil, comment) - c.Assert(t.labels[len(t.labels)-1], DeepEquals, t.label, comment) + for _, test := range tests { + err := test.labels.Add(test.label) + comment := fmt.Sprintf("%s: %v", test.name, err) + if test.err == nil { + require.NoError(t, err, comment) + require.Equal(t, test.label, test.labels[len(test.labels)-1], comment) } else { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + require.ErrorIs(t, err, test.err, comment) } } } -func (t *testConstraintsSuite) TestRestore(c *C) { +func TestRestoreConstraints(t *testing.T) { type TestCase struct { name string input Constraints @@ -136,9 +133,9 @@ func (t *testConstraintsSuite) TestRestore(c *C) { }) input1, err := NewConstraint("+zone=bj") - c.Assert(err, IsNil) + require.NoError(t, err) input2, err := NewConstraint("-zone=sh") - c.Assert(err, IsNil) + require.NoError(t, err) tests = append(tests, TestCase{ "normal2", Constraints{input1, input2}, @@ -157,14 +154,14 @@ func (t *testConstraintsSuite) TestRestore(c *C) { ErrInvalidConstraintFormat, }) - for _, t := range tests { - res, err := t.input.Restore() - comment := Commentf("%s: %v", t.name, err) - if t.err == nil { - c.Assert(err, IsNil, comment) - c.Assert(res, Equals, t.output, comment) + for _, test := range tests { + res, err := test.input.Restore() + comment := fmt.Sprintf("%s: %v", test.name, err) + if test.err == nil { + require.NoError(t, err, comment) + require.Equal(t, test.output, res, comment) } else { - c.Assert(errors.Is(err, t.err), IsTrue, comment) + require.ErrorIs(t, err, test.err, comment) } } } diff --git a/ddl/placement/errors.go b/ddl/placement/errors.go index 4f98e0fa4c2ec..b609827bd4ce7 100644 --- a/ddl/placement/errors.go +++ b/ddl/placement/errors.go @@ -43,4 +43,8 @@ var ( ErrNoRulesToDrop = errors.New("no rule of such role to drop") // ErrInvalidPlacementOptions is from bundle.go. ErrInvalidPlacementOptions = errors.New("invalid placement option") + // ErrInvalidConstraintsMappingWrongSeparator is wrong separator in mapping. + ErrInvalidConstraintsMappingWrongSeparator = errors.New("mappings use a colon and space (“: â€) to mark each key/value pair") + // ErrInvalidConstraintsMappingNoColonFound is no colon found in mapping. + ErrInvalidConstraintsMappingNoColonFound = errors.New("no colon found") ) diff --git a/ddl/placement/meta_bundle_test.go b/ddl/placement/meta_bundle_test.go index 0306458c1a745..f53599bd2e14c 100644 --- a/ddl/placement/meta_bundle_test.go +++ b/ddl/placement/meta_bundle_test.go @@ -19,8 +19,8 @@ import ( "encoding/hex" "encoding/json" "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/ddl/placement" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" @@ -28,20 +28,21 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/codec" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testMetaBundleSuite{}) - -type testMetaBundleSuite struct { +type metaBundleSuite struct { policy1 *model.PolicyInfo policy2 *model.PolicyInfo + policy3 *model.PolicyInfo tbl1 *model.TableInfo tbl2 *model.TableInfo tbl3 *model.TableInfo tbl4 *model.TableInfo } -func (s *testMetaBundleSuite) SetUpSuite(c *C) { +func createMetaBundleSuite() *metaBundleSuite { + s := new(metaBundleSuite) s.policy1 = &model.PolicyInfo{ ID: 11, Name: model.NewCIStr("p1"), @@ -60,6 +61,14 @@ func (s *testMetaBundleSuite) SetUpSuite(c *C) { }, State: model.StatePublic, } + s.policy3 = &model.PolicyInfo{ + ID: 13, + Name: model.NewCIStr("p3"), + PlacementSettings: &model.PlacementSettings{ + LeaderConstraints: "[+region=bj]", + }, + State: model.StatePublic, + } s.tbl1 = &model.TableInfo{ ID: 101, Name: model.NewCIStr("t1"), @@ -82,11 +91,6 @@ func (s *testMetaBundleSuite) SetUpSuite(c *C) { ID: 1002, Name: model.NewCIStr("par2"), }, - { - ID: 1003, - Name: model.NewCIStr("par3"), - DirectPlacementOpts: &model.PlacementSettings{PrimaryRegion: "r3", Regions: "r3"}, - }, }, }, } @@ -105,183 +109,175 @@ func (s *testMetaBundleSuite) SetUpSuite(c *C) { Name: model.NewCIStr("par1"), }, { - ID: 1002, - Name: model.NewCIStr("par2"), - DirectPlacementOpts: &model.PlacementSettings{PrimaryRegion: "r2", Regions: "r2"}, - }, - { - ID: 1003, - Name: model.NewCIStr("par3"), + ID: 1002, + Name: model.NewCIStr("par2"), }, }, }, } s.tbl3 = &model.TableInfo{ - ID: 103, - Name: model.NewCIStr("t3"), - DirectPlacementOpts: &model.PlacementSettings{ - LeaderConstraints: "[+region=bj]", - }, + ID: 103, + Name: model.NewCIStr("t3"), + PlacementPolicyRef: &model.PolicyRefInfo{ID: 13, Name: model.NewCIStr("p3")}, } s.tbl4 = &model.TableInfo{ ID: 104, Name: model.NewCIStr("t4"), } + return s } -func (s *testMetaBundleSuite) prepareMeta(c *C, store kv.Storage) { - c.Assert(kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - c.Assert(t.CreatePolicy(s.policy1), IsNil) - c.Assert(t.CreatePolicy(s.policy2), IsNil) +func (s *metaBundleSuite) prepareMeta(t *testing.T, store kv.Storage) { + err := kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + require.NoError(t, m.CreatePolicy(s.policy1)) + require.NoError(t, m.CreatePolicy(s.policy2)) + require.NoError(t, m.CreatePolicy(s.policy3)) return nil - }), IsNil) + }) + require.NoError(t, err) } -func (s *testMetaBundleSuite) TestNewTableBundle(c *C) { - store := newMockStore(c) - defer func() { - c.Assert(store.Close(), IsNil) - }() - s.prepareMeta(c, store) - c.Assert(kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) +func TestNewTableBundle(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { require.NoError(t, store.Close()) }() + + s := createMetaBundleSuite() + s.prepareMeta(t, store) + require.NoError(t, kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) // tbl1 - bundle, err := placement.NewTableBundle(t, s.tbl1) - c.Assert(err, IsNil) - s.checkTableBundle(c, s.tbl1, bundle) + bundle, err := placement.NewTableBundle(m, s.tbl1) + require.NoError(t, err) + s.checkTableBundle(t, s.tbl1, bundle) // tbl2 - bundle, err = placement.NewTableBundle(t, s.tbl2) - c.Assert(err, IsNil) - s.checkTableBundle(c, s.tbl2, bundle) + bundle, err = placement.NewTableBundle(m, s.tbl2) + require.NoError(t, err) + s.checkTableBundle(t, s.tbl2, bundle) // tbl3 - bundle, err = placement.NewTableBundle(t, s.tbl3) - c.Assert(err, IsNil) - s.checkTableBundle(c, s.tbl3, bundle) + bundle, err = placement.NewTableBundle(m, s.tbl3) + require.NoError(t, err) + s.checkTableBundle(t, s.tbl3, bundle) // tbl4 - bundle, err = placement.NewTableBundle(t, s.tbl4) - c.Assert(err, IsNil) - s.checkTableBundle(c, s.tbl4, bundle) + bundle, err = placement.NewTableBundle(m, s.tbl4) + require.NoError(t, err) + s.checkTableBundle(t, s.tbl4, bundle) return nil - }), IsNil) + })) } -func (s *testMetaBundleSuite) TestNewPartitionBundle(c *C) { - store := newMockStore(c) - defer func() { - c.Assert(store.Close(), IsNil) - }() - s.prepareMeta(c, store) +func TestNewPartitionBundle(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { require.NoError(t, store.Close()) }() + + s := createMetaBundleSuite() + s.prepareMeta(t, store) - c.Assert(kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) + require.NoError(t, kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) // tbl1.par0 - bundle, err := placement.NewPartitionBundle(t, s.tbl1.Partition.Definitions[0]) - c.Assert(err, IsNil) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[0], bundle) + bundle, err := placement.NewPartitionBundle(m, s.tbl1.Partition.Definitions[0]) + require.NoError(t, err) + s.checkPartitionBundle(t, s.tbl1.Partition.Definitions[0], bundle) // tbl1.par1 - bundle, err = placement.NewPartitionBundle(t, s.tbl1.Partition.Definitions[1]) - c.Assert(err, IsNil) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[1], bundle) - - // tbl1.par3 - bundle, err = placement.NewPartitionBundle(t, s.tbl1.Partition.Definitions[3]) - c.Assert(err, IsNil) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[3], bundle) + bundle, err = placement.NewPartitionBundle(m, s.tbl1.Partition.Definitions[1]) + require.NoError(t, err) + s.checkPartitionBundle(t, s.tbl1.Partition.Definitions[1], bundle) return nil - }), IsNil) + })) } -func (s *testMetaBundleSuite) TestNewPartitionListBundles(c *C) { - store := newMockStore(c) - defer func() { - c.Assert(store.Close(), IsNil) - }() - s.prepareMeta(c, store) +func TestNewPartitionListBundles(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { require.NoError(t, store.Close()) }() + + s := createMetaBundleSuite() + s.prepareMeta(t, store) - c.Assert(kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) + require.NoError(t, kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) - bundles, err := placement.NewPartitionListBundles(t, s.tbl1.Partition.Definitions) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 2) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[1], bundles[0]) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[3], bundles[1]) + bundles, err := placement.NewPartitionListBundles(m, s.tbl1.Partition.Definitions) + require.NoError(t, err) + require.Len(t, bundles, 1) + s.checkPartitionBundle(t, s.tbl1.Partition.Definitions[1], bundles[0]) - bundles, err = placement.NewPartitionListBundles(t, []model.PartitionDefinition{}) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 0) + bundles, err = placement.NewPartitionListBundles(m, []model.PartitionDefinition{}) + require.NoError(t, err) + require.Len(t, bundles, 0) - bundles, err = placement.NewPartitionListBundles(t, []model.PartitionDefinition{ + bundles, err = placement.NewPartitionListBundles(m, []model.PartitionDefinition{ s.tbl1.Partition.Definitions[0], s.tbl1.Partition.Definitions[2], }) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 0) + require.NoError(t, err) + require.Len(t, bundles, 0) return nil - }), IsNil) + })) } -func (s *testMetaBundleSuite) TestNewFullTableBundles(c *C) { - store := newMockStore(c) - defer func() { - c.Assert(store.Close(), IsNil) - }() - s.prepareMeta(c, store) - - c.Assert(kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - - bundles, err := placement.NewFullTableBundles(t, s.tbl1) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 3) - s.checkTableBundle(c, s.tbl1, bundles[0]) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[1], bundles[1]) - s.checkPartitionBundle(c, s.tbl1.Partition.Definitions[3], bundles[2]) - - bundles, err = placement.NewFullTableBundles(t, s.tbl2) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 2) - s.checkPartitionBundle(c, s.tbl2.Partition.Definitions[0], bundles[0]) - s.checkPartitionBundle(c, s.tbl2.Partition.Definitions[2], bundles[1]) - - bundles, err = placement.NewFullTableBundles(t, s.tbl3) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 1) - s.checkTableBundle(c, s.tbl3, bundles[0]) - - bundles, err = placement.NewFullTableBundles(t, s.tbl4) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 0) +func TestNewFullTableBundles(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { require.NoError(t, store.Close()) }() + + s := createMetaBundleSuite() + s.prepareMeta(t, store) + + require.NoError(t, kv.RunInNewTxn(context.TODO(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + + bundles, err := placement.NewFullTableBundles(m, s.tbl1) + require.NoError(t, err) + require.Len(t, bundles, 2) + s.checkTableBundle(t, s.tbl1, bundles[0]) + s.checkPartitionBundle(t, s.tbl1.Partition.Definitions[1], bundles[1]) + + bundles, err = placement.NewFullTableBundles(m, s.tbl2) + require.NoError(t, err) + require.Len(t, bundles, 1) + s.checkPartitionBundle(t, s.tbl2.Partition.Definitions[0], bundles[0]) + + bundles, err = placement.NewFullTableBundles(m, s.tbl3) + require.NoError(t, err) + require.Len(t, bundles, 1) + s.checkTableBundle(t, s.tbl3, bundles[0]) + + bundles, err = placement.NewFullTableBundles(m, s.tbl4) + require.NoError(t, err) + require.Len(t, bundles, 0) return nil - }), IsNil) + })) } -func (s *testMetaBundleSuite) checkTwoJSONObjectEquals(c *C, expected interface{}, got interface{}) { +func (s *metaBundleSuite) checkTwoJSONObjectEquals(t *testing.T, expected interface{}, got interface{}) { expectedJSON, err := json.Marshal(expected) - c.Assert(err, IsNil) + require.NoError(t, err) expectedStr := string(expectedJSON) gotJSON, err := json.Marshal(got) - c.Assert(err, IsNil) + require.NoError(t, err) gotStr := string(gotJSON) - c.Assert(gotStr, Equals, expectedStr) + require.Equal(t, expectedStr, gotStr) } -func (s *testMetaBundleSuite) checkTableBundle(c *C, tbl *model.TableInfo, got *placement.Bundle) { - if tbl.PlacementPolicyRef == nil && tbl.DirectPlacementOpts == nil { - c.Assert(got, IsNil) +func (s *metaBundleSuite) checkTableBundle(t *testing.T, tbl *model.TableInfo, got *placement.Bundle) { + if tbl.PlacementPolicyRef == nil { + require.Nil(t, got) return } @@ -289,7 +285,7 @@ func (s *testMetaBundleSuite) checkTableBundle(c *C, tbl *model.TableInfo, got * ID: fmt.Sprintf("TiDB_DDL_%d", tbl.ID), Index: placement.RuleIndexTable, Override: true, - Rules: s.expectedRules(c, tbl.PlacementPolicyRef, tbl.DirectPlacementOpts), + Rules: s.expectedRules(t, tbl.PlacementPolicyRef), } for idx, rule := range expected.Rules { @@ -302,7 +298,7 @@ func (s *testMetaBundleSuite) checkTableBundle(c *C, tbl *model.TableInfo, got * if tbl.Partition != nil { for _, par := range tbl.Partition.Definitions { - rules := s.expectedRules(c, tbl.PlacementPolicyRef, tbl.DirectPlacementOpts) + rules := s.expectedRules(t, tbl.PlacementPolicyRef) for idx, rule := range rules { rule.GroupID = expected.ID rule.Index = placement.RuleIndexPartition @@ -314,12 +310,12 @@ func (s *testMetaBundleSuite) checkTableBundle(c *C, tbl *model.TableInfo, got * } } - s.checkTwoJSONObjectEquals(c, expected, got) + s.checkTwoJSONObjectEquals(t, expected, got) } -func (s *testMetaBundleSuite) checkPartitionBundle(c *C, def model.PartitionDefinition, got *placement.Bundle) { - if def.PlacementPolicyRef == nil && def.DirectPlacementOpts == nil { - c.Assert(got, IsNil) +func (s *metaBundleSuite) checkPartitionBundle(t *testing.T, def model.PartitionDefinition, got *placement.Bundle) { + if def.PlacementPolicyRef == nil { + require.Nil(t, got) return } @@ -327,7 +323,7 @@ func (s *testMetaBundleSuite) checkPartitionBundle(c *C, def model.PartitionDefi ID: fmt.Sprintf("TiDB_DDL_%d", def.ID), Index: placement.RuleIndexPartition, Override: true, - Rules: s.expectedRules(c, def.PlacementPolicyRef, def.DirectPlacementOpts), + Rules: s.expectedRules(t, def.PlacementPolicyRef), } for idx, rule := range expected.Rules { @@ -338,42 +334,31 @@ func (s *testMetaBundleSuite) checkPartitionBundle(c *C, def model.PartitionDefi rule.EndKeyHex = hex.EncodeToString(codec.EncodeBytes(nil, tablecodec.GenTablePrefix(def.ID+1))) } - s.checkTwoJSONObjectEquals(c, expected, got) + s.checkTwoJSONObjectEquals(t, expected, got) } -func (s *testMetaBundleSuite) expectedRules(c *C, ref *model.PolicyRefInfo, direct *model.PlacementSettings) []*placement.Rule { - c.Assert(ref != nil && direct != nil, IsFalse) - - var settings *model.PlacementSettings - if ref != nil { - var policy *model.PolicyInfo - switch ref.ID { - case s.policy1.ID: - policy = s.policy1 - case s.policy2.ID: - policy = s.policy2 - default: - c.FailNow() - } - c.Assert(ref.Name, Equals, policy.Name) - settings = policy.PlacementSettings +func (s *metaBundleSuite) expectedRules(t *testing.T, ref *model.PolicyRefInfo) []*placement.Rule { + if ref == nil { + return []*placement.Rule{} } - if direct != nil { - settings = direct + var policy *model.PolicyInfo + switch ref.ID { + case s.policy1.ID: + policy = s.policy1 + case s.policy2.ID: + policy = s.policy2 + case s.policy3.ID: + policy = s.policy3 + default: + t.FailNow() } - if settings == nil { - return []*placement.Rule{} - } + require.Equal(t, policy.Name, ref.Name) + settings := policy.PlacementSettings bundle, err := placement.NewBundleFromOptions(settings) - c.Assert(err, IsNil) - return bundle.Rules -} + require.NoError(t, err) -func newMockStore(c *C) kv.Storage { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - return store + return bundle.Rules } diff --git a/ddl/placement/rule.go b/ddl/placement/rule.go index 216714789aec9..dcce5653c05c2 100644 --- a/ddl/placement/rule.go +++ b/ddl/placement/rule.go @@ -16,6 +16,7 @@ package placement import ( "fmt" + "regexp" "strings" "gopkg.in/yaml.v2" @@ -37,6 +38,19 @@ const ( // Rule is the core placement rule struct. Check https://github.com/tikv/pd/blob/master/server/schedule/placement/rule.go. type Rule struct { + GroupID string `json:"group_id"` + ID string `json:"id"` + Index int `json:"index,omitempty"` + Override bool `json:"override,omitempty"` + StartKeyHex string `json:"start_key"` + EndKeyHex string `json:"end_key"` + Role PeerRoleType `json:"role"` + Count int `json:"count"` + Constraints Constraints `json:"label_constraints,omitempty"` +} + +// TiFlashRule extends Rule with other necessary fields. +type TiFlashRule struct { GroupID string `json:"group_id"` ID string `json:"id"` Index int `json:"index,omitempty"` @@ -54,14 +68,24 @@ type Rule struct { // consistent the behavior of creating new rules. func NewRule(role PeerRoleType, replicas uint64, cnst Constraints) *Rule { return &Rule{ - Role: role, - Count: int(replicas), - Constraints: cnst, - LocationLabels: []string{"region", "zone", "rack", "host"}, - IsolationLevel: "region", + Role: role, + Count: int(replicas), + Constraints: cnst, } } +var wrongSeparatorRegexp = regexp.MustCompile(`[^"':]+:\d`) + +func getYamlMapFormatError(str string) error { + if !strings.Contains(str, ":") { + return ErrInvalidConstraintsMappingNoColonFound + } + if wrongSeparatorRegexp.MatchString(str) { + return ErrInvalidConstraintsMappingWrongSeparator + } + return nil +} + // NewRules constructs []*Rule from a yaml-compatible representation of // 'array' or 'dict' constraints. // Refer to https://github.com/pingcap/tidb/blob/master/docs/design/2020-06-24-placement-rules-in-sql.md. @@ -72,11 +96,6 @@ func NewRules(role PeerRoleType, replicas uint64, cnstr string) ([]*Rule, error) constraints1, err1 := NewConstraintsFromYaml(cnstbytes) if err1 == nil { - // can not emit REPLICAS with an array or empty label - if replicas == 0 { - return rules, fmt.Errorf("%w: should be positive", ErrInvalidConstraintsRelicas) - } - rules = append(rules, NewRule(role, replicas, constraints1)) return rules, nil } @@ -84,20 +103,17 @@ func NewRules(role PeerRoleType, replicas uint64, cnstr string) ([]*Rule, error) constraints2 := map[string]int{} err2 := yaml.UnmarshalStrict(cnstbytes, &constraints2) if err2 == nil { - ruleCnt := 0 + if replicas != 0 { + return rules, fmt.Errorf("%w: should not specify replicas=%d when using dict syntax", ErrInvalidConstraintsRelicas, replicas) + } + for labels, cnt := range constraints2 { if cnt <= 0 { + if err := getYamlMapFormatError(string(cnstbytes)); err != nil { + return rules, err + } return rules, fmt.Errorf("%w: count of labels '%s' should be positive, but got %d", ErrInvalidConstraintsMapcnt, labels, cnt) } - ruleCnt += cnt - } - - if replicas == 0 { - replicas = uint64(ruleCnt) - } - - if int(replicas) < ruleCnt { - return rules, fmt.Errorf("%w: should be larger or equal to the number of total replicas, but REPLICAS=%d < total=%d", ErrInvalidConstraintsRelicas, replicas, ruleCnt) } for labels, cnt := range constraints2 { @@ -108,11 +124,6 @@ func NewRules(role PeerRoleType, replicas uint64, cnstr string) ([]*Rule, error) rules = append(rules, NewRule(role, uint64(cnt), labelConstraints)) } - - remain := int(replicas) - ruleCnt - if remain > 0 { - rules = append(rules, NewRule(role, uint64(remain), nil)) - } return rules, nil } @@ -120,8 +131,7 @@ func NewRules(role PeerRoleType, replicas uint64, cnstr string) ([]*Rule, error) } // Clone is used to duplicate a RuleOp for safe modification. -// Note that it is a shallow copy: LocationLabels and Constraints -// is not cloned. +// Note that it is a shallow copy: Constraints is not cloned. func (r *Rule) Clone() *Rule { n := &Rule{} *n = *r diff --git a/ddl/placement/rule_test.go b/ddl/placement/rule_test.go index 9432448127a4a..bee9807b486bd 100644 --- a/ddl/placement/rule_test.go +++ b/ddl/placement/rule_test.go @@ -16,41 +16,38 @@ package placement import ( "errors" + "fmt" + "reflect" + "testing" - . "github.com/pingcap/check" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testRuleSuite{}) - -type testRuleSuite struct{} - -func (t *testRuleSuite) TestClone(c *C) { +func TestClone(t *testing.T) { rule := &Rule{ID: "434"} newRule := rule.Clone() newRule.ID = "121" - c.Assert(rule, DeepEquals, &Rule{ID: "434"}) - c.Assert(newRule, DeepEquals, &Rule{ID: "121"}) + require.Equal(t, &Rule{ID: "434"}, rule) + require.Equal(t, &Rule{ID: "121"}, newRule) } -func matchRules(t1, t2 []*Rule, prefix string, c *C) { - c.Assert(len(t2), Equals, len(t1), Commentf(prefix)) +func matchRules(t1, t2 []*Rule, prefix string, t *testing.T) { + require.Equal(t, len(t2), len(t1), prefix) for i := range t1 { found := false for j := range t2 { - ok, _ := DeepEquals.Check([]interface{}{t2[j], t1[i]}, []string{}) + ok := reflect.DeepEqual(t2[j], t1[i]) if ok { found = true break } } - if !found { - c.Errorf("%s\n\ncan not found %d rule\n%+v\n%+v", prefix, i, t1[i], t2) - } + require.True(t, found, "%s\n\ncan not found %d rule\n%+v\n%+v", prefix, i, t1[i], t2) } } -func (t *testRuleSuite) TestNewRuleAndNewRules(c *C) { +func TestNewRuleAndNewRules(t *testing.T) { type TestCase struct { name string input string @@ -58,7 +55,7 @@ func (t *testRuleSuite) TestNewRuleAndNewRules(c *C) { output []*Rule err error } - tests := []TestCase{} + var tests []TestCase tests = append(tests, TestCase{ name: "empty constraints", @@ -73,11 +70,13 @@ func (t *testRuleSuite) TestNewRuleAndNewRules(c *C) { name: "zero replicas", input: "", replicas: 0, - err: ErrInvalidConstraintsRelicas, + output: []*Rule{ + NewRule(Voter, 0, NewConstraintsDirect()), + }, }) tests = append(tests, TestCase{ - name: "normal array constraints", + name: "normal list constraints", input: `["+zone=sh", "+region=sh"]`, replicas: 3, output: []*Rule{ @@ -89,9 +88,8 @@ func (t *testRuleSuite) TestNewRuleAndNewRules(c *C) { }) tests = append(tests, TestCase{ - name: "normal object constraints", - input: `{"+zone=sh,-zone=bj":2, "+zone=sh": 1}`, - replicas: 3, + name: "normal dict constraints", + input: `{"+zone=sh,-zone=bj":2, "+zone=sh": 1}`, output: []*Rule{ NewRule(Voter, 2, NewConstraintsDirect( NewConstraintDirect("zone", In, "sh"), @@ -104,85 +102,51 @@ func (t *testRuleSuite) TestNewRuleAndNewRules(c *C) { }) tests = append(tests, TestCase{ - name: "normal object constraints, with extra count", + name: "normal dict constraints, with count", input: "{'+zone=sh,-zone=bj':2, '+zone=sh': 1}", replicas: 4, - output: []*Rule{ - NewRule(Voter, 2, NewConstraintsDirect( - NewConstraintDirect("zone", In, "sh"), - NewConstraintDirect("zone", NotIn, "bj"), - )), - NewRule(Voter, 1, NewConstraintsDirect( - NewConstraintDirect("zone", In, "sh"), - )), - NewRule(Voter, 1, NewConstraintsDirect()), - }, - }) - - tests = append(tests, TestCase{ - name: "normal object constraints, without count", - input: "{'+zone=sh,-zone=bj':2, '+zone=sh': 1}", - output: []*Rule{ - NewRule(Voter, 2, NewConstraintsDirect( - NewConstraintDirect("zone", In, "sh"), - NewConstraintDirect("zone", NotIn, "bj"), - )), - NewRule(Voter, 1, NewConstraintsDirect( - NewConstraintDirect("zone", In, "sh"), - )), - }, - }) - - tests = append(tests, TestCase{ - name: "zero count in object constraints", - input: `{"+zone=sh,-zone=bj":0, "+zone=sh": 1}`, - replicas: 3, - err: ErrInvalidConstraintsMapcnt, + err: ErrInvalidConstraintsRelicas, }) tests = append(tests, TestCase{ - name: "overlarge total count in object constraints", - input: `{"+ne=sh,-zone=bj":1, "+zone=sh": 4}`, - replicas: 3, - err: ErrInvalidConstraintsRelicas, + name: "zero count in dict constraints", + input: `{"+zone=sh,-zone=bj":0, "+zone=sh": 1}`, + err: ErrInvalidConstraintsMapcnt, }) tests = append(tests, TestCase{ - name: "invalid array", - input: `["+ne=sh", "+zone=sh"`, + name: "invalid list constraints", + input: `["ne=sh", "+zone=sh"]`, replicas: 3, err: ErrInvalidConstraintsFormat, }) tests = append(tests, TestCase{ - name: "invalid array constraints", - input: `["ne=sh", "+zone=sh"]`, - replicas: 3, - err: ErrInvalidConstraintsFormat, + name: "invalid dict constraints", + input: `{+ne=sh,-zone=bj:1, "+zone=sh": 4`, + err: ErrInvalidConstraintsFormat, }) tests = append(tests, TestCase{ - name: "invalid map", - input: `{+ne=sh,-zone=bj:1, "+zone=sh": 4`, - replicas: 5, - err: ErrInvalidConstraintsFormat, + name: "invalid dict constraints", + input: `{"nesh,-zone=bj":1, "+zone=sh": 4}`, + err: ErrInvalidConstraintFormat, }) tests = append(tests, TestCase{ - name: "invalid map constraints", - input: `{"nesh,-zone=bj":1, "+zone=sh": 4}`, - replicas: 6, - err: ErrInvalidConstraintFormat, + name: "invalid dict separator", + input: `{+region=us-east-2:2}`, + err: ErrInvalidConstraintsMappingWrongSeparator, }) - for _, t := range tests { - comment := Commentf("[%s]", t.name) - output, err := NewRules(Voter, t.replicas, t.input) - if t.err == nil { - c.Assert(err, IsNil, comment) - matchRules(t.output, output, comment.CheckCommentString(), c) + for _, tt := range tests { + comment := fmt.Sprintf("[%s]", tt.name) + output, err := NewRules(Voter, tt.replicas, tt.input) + if tt.err == nil { + require.NoError(t, err, comment) + matchRules(tt.output, output, comment, t) } else { - c.Assert(errors.Is(err, t.err), IsTrue, Commentf("[%s]\n%s\n%s\n", t.name, err, t.err)) + require.True(t, errors.Is(err, tt.err), "[%s]\n%s\n%s\n", tt.name, err, tt.err) } } } diff --git a/ddl/placement_policy.go b/ddl/placement_policy.go index 3ccba4ef346f6..601b382cbeadf 100644 --- a/ddl/placement_policy.go +++ b/ddl/placement_policy.go @@ -24,25 +24,52 @@ import ( "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/util/dbterror" ) func onCreatePlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { policyInfo := &model.PolicyInfo{} - if err := job.DecodeArgs(policyInfo); err != nil { + var orReplace bool + if err := job.DecodeArgs(policyInfo, &orReplace); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } policyInfo.State = model.StateNone - err := checkPlacementPolicyNotExistAndCancelExistJob(d, t, job, policyInfo) - if err != nil { + if err := checkPolicyValidation(policyInfo.PlacementSettings); err != nil { + job.State = model.JobStateCancelled return ver, errors.Trace(err) } - err = checkPolicyValidation(policyInfo.PlacementSettings) + + existPolicy, err := getPlacementPolicyByName(d, t, policyInfo.Name) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } + + if existPolicy != nil { + if !orReplace { + job.State = model.JobStateCancelled + return ver, infoschema.ErrPlacementPolicyExists.GenWithStackByArgs(existPolicy.Name) + } + + replacePolicy := existPolicy.Clone() + replacePolicy.PlacementSettings = policyInfo.PlacementSettings + if err = updateExistPlacementPolicy(t, replacePolicy); err != nil { + job.State = model.JobStateCancelled + return ver, errors.Trace(err) + } + + job.SchemaID = replacePolicy.ID + ver, err = updateSchemaVersion(t, job) + if err != nil { + return ver, errors.Trace(err) + } + // Finish this job. + job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, nil) + return ver, nil + } + switch policyInfo.State { case model.StateNone: // none -> public @@ -62,7 +89,7 @@ func onCreatePlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64 return ver, nil default: // We can't enter here. - return ver, ErrInvalidDDLState.GenWithStackByArgs("policy", policyInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("policy", policyInfo.State) } } @@ -84,33 +111,32 @@ func getPolicyInfo(t *meta.Meta, policyID int64) (*model.PolicyInfo, error) { return policy, nil } -func checkPlacementPolicyNotExistAndCancelExistJob(d *ddlCtx, t *meta.Meta, job *model.Job, info *model.PolicyInfo) error { +func getPlacementPolicyByName(d *ddlCtx, t *meta.Meta, policyName model.CIStr) (*model.PolicyInfo, error) { currVer, err := t.GetSchemaVersion() if err != nil { - return err + return nil, err } + is := d.infoCache.GetLatest() if is.SchemaMetaVersion() == currVer { // Use cached policy. - _, ok := is.PolicyByName(info.Name) + policy, ok := is.PolicyByName(policyName) if ok { - job.State = model.JobStateCancelled - return infoschema.ErrPlacementPolicyExists.GenWithStackByArgs(info.Name) + return policy, nil } - return nil + return nil, nil } // Check in meta directly. policies, err := t.ListPolicies() if err != nil { - return errors.Trace(err) + return nil, errors.Trace(err) } for _, policy := range policies { - if policy.Name.L == info.Name.L { - job.State = model.JobStateCancelled - return infoschema.ErrPlacementPolicyExists.GenWithStackByArgs(info.Name) + if policy.Name.L == policyName.L { + return policy, nil } } - return nil + return nil, nil } func checkPlacementPolicyExistAndCancelNonExistJob(t *meta.Meta, job *model.Job, policyID int64) (*model.PolicyInfo, error) { @@ -158,7 +184,7 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err = checkPlacementPolicyNotInUse(d, t, policyInfo) if err != nil { - if ErrPlacementPolicyInUse.Equal(err) { + if dbterror.ErrPlacementPolicyInUse.Equal(err) { job.State = model.JobStateCancelled } return ver, errors.Trace(err) @@ -203,12 +229,12 @@ func onDropPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, // Finish this job. By now policy don't consider the binlog sync. job.FinishDBJob(model.JobStateDone, model.StateNone, ver, nil) default: - err = ErrInvalidDDLState.GenWithStackByArgs("policy", policyInfo.State) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("policy", policyInfo.State) } return ver, errors.Trace(err) } -func onAlterPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onAlterPlacementPolicy(t *meta.Meta, job *model.Job) (ver int64, _ error) { alterPolicy := &model.PolicyInfo{} if err := job.DecodeArgs(alterPolicy); err != nil { job.State = model.JobStateCancelled @@ -225,24 +251,40 @@ func onAlterPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err = checkPolicyValidation(newPolicyInfo.PlacementSettings) if err != nil { + return ver, errors.Trace(err) + } + + if err = updateExistPlacementPolicy(t, &newPolicyInfo); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } - err = t.UpdatePolicy(&newPolicyInfo) + ver, err = updateSchemaVersion(t, job) if err != nil { return ver, errors.Trace(err) } - dbIDs, partIDs, tblInfos, err := getPlacementPolicyDependedObjectsIDs(t, oldPolicy) + // Finish this job. + job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, nil) + return ver, nil +} + +func updateExistPlacementPolicy(t *meta.Meta, policy *model.PolicyInfo) error { + err := t.UpdatePolicy(policy) if err != nil { - return ver, errors.Trace(err) + return errors.Trace(err) } + + dbIDs, partIDs, tblInfos, err := getPlacementPolicyDependedObjectsIDs(t, policy) + if err != nil { + return errors.Trace(err) + } + if len(dbIDs)+len(tblInfos)+len(partIDs) != 0 { // build bundle from new placement policy. - bundle, err := placement.NewBundleFromOptions(newPolicyInfo.PlacementSettings) + bundle, err := placement.NewBundleFromOptions(policy.PlacementSettings) if err != nil { - return ver, errors.Trace(err) + return errors.Trace(err) } // Do the http request only when the rules is existed. bundles := make([]*placement.Bundle, 0, len(tblInfos)+len(partIDs)) @@ -264,19 +306,11 @@ func onAlterPlacementPolicy(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, } err = infosync.PutRuleBundlesWithDefaultRetry(context.TODO(), bundles) if err != nil { - job.State = model.JobStateCancelled - return ver, errors.Wrapf(err, "failed to notify PD the placement rules") + return errors.Wrapf(err, "failed to notify PD the placement rules") } } - ver, err = updateSchemaVersion(t, job) - if err != nil { - return ver, errors.Trace(err) - } - - // Finish this job. - job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, nil) - return ver, nil + return nil } func checkPlacementPolicyNotInUse(d *ddlCtx, t *meta.Meta, policy *model.PolicyInfo) error { @@ -295,7 +329,7 @@ func checkPlacementPolicyNotInUse(d *ddlCtx, t *meta.Meta, policy *model.PolicyI func checkPlacementPolicyNotInUseFromInfoSchema(is infoschema.InfoSchema, policy *model.PolicyInfo) error { for _, dbInfo := range is.AllSchemas() { if ref := dbInfo.PlacementPolicyRef; ref != nil && ref.ID == policy.ID { - return ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) + return dbterror.ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) } for _, tbl := range is.SchemaTables(dbInfo.Name) { @@ -349,7 +383,7 @@ func checkPlacementPolicyNotInUseFromMeta(t *meta.Meta, policy *model.PolicyInfo for _, dbInfo := range schemas { if ref := dbInfo.PlacementPolicyRef; ref != nil && ref.ID == policy.ID { - return ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) + return dbterror.ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) } tables, err := t.ListTables(dbInfo.ID) @@ -368,16 +402,32 @@ func checkPlacementPolicyNotInUseFromMeta(t *meta.Meta, policy *model.PolicyInfo func checkPlacementPolicyNotUsedByTable(tblInfo *model.TableInfo, policy *model.PolicyInfo) error { if ref := tblInfo.PlacementPolicyRef; ref != nil && ref.ID == policy.ID { - return ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) + return dbterror.ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) } if tblInfo.Partition != nil { for _, partition := range tblInfo.Partition.Definitions { if ref := partition.PlacementPolicyRef; ref != nil && ref.ID == policy.ID { - return ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) + return dbterror.ErrPlacementPolicyInUse.GenWithStackByArgs(policy.Name) } } } return nil } + +func tableHasPlacementSettings(tblInfo *model.TableInfo) bool { + if tblInfo.PlacementPolicyRef != nil { + return true + } + + if tblInfo.Partition != nil { + for _, def := range tblInfo.Partition.Definitions { + if def.PlacementPolicyRef != nil { + return true + } + } + } + + return false +} diff --git a/ddl/placement_policy_ddl_test.go b/ddl/placement_policy_ddl_test.go index 28efb3bae3e3c..8f12a44a5bb90 100644 --- a/ddl/placement_policy_ddl_test.go +++ b/ddl/placement_policy_ddl_test.go @@ -15,132 +15,137 @@ package ddl import ( "context" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" ) -func testPlacementPolicyInfo(c *C, d *ddl, name string, settings *model.PlacementSettings) *model.PolicyInfo { +func testPlacementPolicyInfo(t *testing.T, d *ddl, name string, settings *model.PlacementSettings) *model.PolicyInfo { policy := &model.PolicyInfo{ Name: model.NewCIStr(name), PlacementSettings: settings, } genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) + require.NoError(t, err) policy.ID = genIDs[0] return policy } -func testCreatePlacementPolicy(c *C, ctx sessionctx.Context, d *ddl, policyInfo *model.PolicyInfo) *model.Job { +func testCreatePlacementPolicy(t *testing.T, ctx sessionctx.Context, d *ddl, policyInfo *model.PolicyInfo) *model.Job { job := &model.Job{ SchemaName: policyInfo.Name.L, Type: model.ActionCreatePlacementPolicy, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{policyInfo}, } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) - v := getSchemaVer(c, ctx) + v := getSchemaVer(t, ctx) policyInfo.State = model.StatePublic - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v}) policyInfo.State = model.StateNone return job } -func (s *testDDLSuite) TestPlacementPolicyInUse(c *C) { - store := testCreateStore(c, "test_placement_policy_in_use") +func TestPlacementPolicyInUse(t *testing.T) { + store := createMockStore(t) defer func() { - err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, store.Close()) }() ctx := context.Background() d, err := testNewDDLAndStart(ctx, WithStore(store)) - c.Assert(err, IsNil) + require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() sctx := testNewContext(d) db1, err := testSchemaInfo(d, "db1") - c.Assert(err, IsNil) - testCreateSchema(c, sctx, d, db1) + require.NoError(t, err) + testCreateSchema(t, sctx, d, db1) db1.State = model.StatePublic db2, err := testSchemaInfo(d, "db2") - c.Assert(err, IsNil) - testCreateSchema(c, sctx, d, db2) + require.NoError(t, err) + testCreateSchema(t, sctx, d, db2) db2.State = model.StatePublic policySettings := &model.PlacementSettings{PrimaryRegion: "r1", Regions: "r1,r2"} - p1 := testPlacementPolicyInfo(c, d, "p1", policySettings) - p2 := testPlacementPolicyInfo(c, d, "p2", policySettings) - p3 := testPlacementPolicyInfo(c, d, "p3", policySettings) - p4 := testPlacementPolicyInfo(c, d, "p4", policySettings) - p5 := testPlacementPolicyInfo(c, d, "p5", policySettings) - testCreatePlacementPolicy(c, sctx, d, p1) - testCreatePlacementPolicy(c, sctx, d, p2) - testCreatePlacementPolicy(c, sctx, d, p3) - testCreatePlacementPolicy(c, sctx, d, p4) - testCreatePlacementPolicy(c, sctx, d, p5) + p1 := testPlacementPolicyInfo(t, d, "p1", policySettings) + p2 := testPlacementPolicyInfo(t, d, "p2", policySettings) + p3 := testPlacementPolicyInfo(t, d, "p3", policySettings) + p4 := testPlacementPolicyInfo(t, d, "p4", policySettings) + p5 := testPlacementPolicyInfo(t, d, "p5", policySettings) + testCreatePlacementPolicy(t, sctx, d, p1) + testCreatePlacementPolicy(t, sctx, d, p2) + testCreatePlacementPolicy(t, sctx, d, p3) + testCreatePlacementPolicy(t, sctx, d, p4) + testCreatePlacementPolicy(t, sctx, d, p5) t1, err := testTableInfo(d, "t1", 1) - c.Assert(err, IsNil) + require.NoError(t, err) t1.PlacementPolicyRef = &model.PolicyRefInfo{ID: p1.ID, Name: p1.Name} - testCreateTable(c, sctx, d, db1, t1) + testCreateTable(t, sctx, d, db1, t1) t1.State = model.StatePublic db1.Tables = append(db1.Tables, t1) t2, err := testTableInfo(d, "t2", 1) - c.Assert(err, IsNil) + require.NoError(t, err) t2.PlacementPolicyRef = &model.PolicyRefInfo{ID: p1.ID, Name: p1.Name} - testCreateTable(c, sctx, d, db2, t2) + testCreateTable(t, sctx, d, db2, t2) t2.State = model.StatePublic db2.Tables = append(db2.Tables, t2) t3, err := testTableInfo(d, "t3", 1) - c.Assert(err, IsNil) + require.NoError(t, err) t3.PlacementPolicyRef = &model.PolicyRefInfo{ID: p2.ID, Name: p2.Name} - testCreateTable(c, sctx, d, db1, t3) + testCreateTable(t, sctx, d, db1, t3) t3.State = model.StatePublic db1.Tables = append(db1.Tables, t3) dbP, err := testSchemaInfo(d, "db_p") - c.Assert(err, IsNil) + require.NoError(t, err) dbP.PlacementPolicyRef = &model.PolicyRefInfo{ID: p4.ID, Name: p4.Name} dbP.State = model.StatePublic - testCreateSchema(c, sctx, d, dbP) + testCreateSchema(t, sctx, d, dbP) - t4 := testTableInfoWithPartition(c, d, "t4", 1) + t4 := testTableInfoWithPartition(t, d, "t4", 1) t4.Partition.Definitions[0].PlacementPolicyRef = &model.PolicyRefInfo{ID: p5.ID, Name: p5.Name} - testCreateTable(c, sctx, d, db1, t4) + testCreateTable(t, sctx, d, db1, t4) t4.State = model.StatePublic db1.Tables = append(db1.Tables, t4) - builder, err := infoschema.NewBuilder(store, nil, nil).InitWithDBInfos( + builder, err := infoschema.NewBuilder(store, nil).InitWithDBInfos( []*model.DBInfo{db1, db2, dbP}, nil, []*model.PolicyInfo{p1, p2, p3, p4, p5}, 1, ) - c.Assert(err, IsNil) + require.NoError(t, err) is := builder.Build() for _, policy := range []*model.PolicyInfo{p1, p2, p4, p5} { - c.Assert(ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromInfoSchema(is, policy)), IsTrue) - c.Assert(kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { + require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromInfoSchema(is, policy))) + require.NoError(t, kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) - c.Assert(ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromMeta(m, policy)), IsTrue) + require.True(t, dbterror.ErrPlacementPolicyInUse.Equal(checkPlacementPolicyNotInUseFromMeta(m, policy))) return nil - }), IsNil) + })) } - c.Assert(checkPlacementPolicyNotInUseFromInfoSchema(is, p3), IsNil) - c.Assert(kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { + require.NoError(t, checkPlacementPolicyNotInUseFromInfoSchema(is, p3)) + require.NoError(t, kv.RunInNewTxn(ctx, sctx.GetStore(), false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) - c.Assert(checkPlacementPolicyNotInUseFromMeta(m, p3), IsNil) + require.NoError(t, checkPlacementPolicyNotInUseFromMeta(m, p3)) return nil - }), IsNil) + })) } diff --git a/ddl/placement_policy_test.go b/ddl/placement_policy_test.go index 1cdb8da5d5661..8a70a0e2cc1c0 100644 --- a/ddl/placement_policy_test.go +++ b/ddl/placement_policy_test.go @@ -20,11 +20,12 @@ import ( "fmt" "math" "strconv" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" mysql "github.com/pingcap/tidb/errno" @@ -34,64 +35,54 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/gcworker" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/stretchr/testify/require" ) -func clearAllBundles(c *C) { - bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - clearBundles := make([]*placement.Bundle, 0, len(bundles)) - for _, bundle := range bundles { - clearBundles = append(clearBundles, &placement.Bundle{ID: bundle.ID}) - } - err = infosync.PutRuleBundles(context.TODO(), clearBundles) - c.Assert(err, IsNil) -} - -func checkExistTableBundlesInPD(c *C, do *domain.Domain, dbName string, tbName string) { +func checkExistTableBundlesInPD(t *testing.T, do *domain.Domain, dbName string, tbName string) { tblInfo, err := do.InfoSchema().TableByName(model.NewCIStr(dbName), model.NewCIStr(tbName)) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(kv.RunInNewTxn(context.TODO(), do.Store(), false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - checkTableBundlesInPD(c, t, tblInfo.Meta()) + require.NoError(t, kv.RunInNewTxn(context.TODO(), do.Store(), false, func(ctx context.Context, txn kv.Transaction) error { + tt := meta.NewMeta(txn) + checkTableBundlesInPD(t, tt, tblInfo.Meta()) return nil - }), IsNil) + })) } -func checkAllBundlesNotChange(c *C, bundles []*placement.Bundle) { +func checkAllBundlesNotChange(t *testing.T, bundles []*placement.Bundle) { currentBundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) + require.NoError(t, err) bundlesMap := make(map[string]*placement.Bundle) for _, bundle := range currentBundles { bundlesMap[bundle.ID] = bundle } - c.Assert(len(bundlesMap), Equals, len(currentBundles)) - c.Assert(len(currentBundles), Equals, len(bundles)) + require.Equal(t, len(currentBundles), len(bundlesMap)) + require.Equal(t, len(bundles), len(currentBundles)) for _, bundle := range bundles { got, ok := bundlesMap[bundle.ID] - c.Assert(ok, IsTrue) + require.True(t, ok) expectedJSON, err := json.Marshal(bundle) - c.Assert(err, IsNil) + require.NoError(t, err) gotJSON, err := json.Marshal(got) - c.Assert(err, IsNil) - c.Assert(string(gotJSON), Equals, string(expectedJSON)) + require.NoError(t, err) + require.Equal(t, string(expectedJSON), string(gotJSON)) } } -func checkTableBundlesInPD(c *C, t *meta.Meta, tblInfo *model.TableInfo) { +func checkTableBundlesInPD(t *testing.T, tt *meta.Meta, tblInfo *model.TableInfo) { checks := make([]*struct { ID string bundle *placement.Bundle }, 0) - bundle, err := placement.NewTableBundle(t, tblInfo) - c.Assert(err, IsNil) + bundle, err := placement.NewTableBundle(tt, tblInfo) + require.NoError(t, err) checks = append(checks, &struct { ID string bundle *placement.Bundle @@ -99,8 +90,8 @@ func checkTableBundlesInPD(c *C, t *meta.Meta, tblInfo *model.TableInfo) { if tblInfo.Partition != nil { for _, def := range tblInfo.Partition.Definitions { - bundle, err := placement.NewPartitionBundle(t, def) - c.Assert(err, IsNil) + bundle, err := placement.NewPartitionBundle(tt, def) + require.NoError(t, err) checks = append(checks, &struct { ID string bundle *placement.Bundle @@ -110,30 +101,29 @@ func checkTableBundlesInPD(c *C, t *meta.Meta, tblInfo *model.TableInfo) { for _, check := range checks { got, err := infosync.GetRuleBundle(context.TODO(), check.ID) - c.Assert(err, IsNil) + require.NoError(t, err) if check.bundle == nil { - c.Assert(got.IsEmpty(), IsTrue) + require.True(t, got.IsEmpty()) } else { expectedJSON, err := json.Marshal(check.bundle) - c.Assert(err, IsNil) + require.NoError(t, err) gotJSON, err := json.Marshal(got) - c.Assert(err, IsNil) - c.Assert(string(gotJSON), Equals, string(expectedJSON)) + require.NoError(t, err) + require.Equal(t, string(expectedJSON), string(gotJSON)) } } } -func (s *testDBSuite6) TestPlacementPolicy(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestPlacementPolicy(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists x") - originalHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook) - - hook := &ddl.TestDDLCallback{} + hook := &ddl.TestDDLCallback{Do: dom} var policyID int64 hook.OnJobUpdatedExported = func(job *model.Job) { if policyID != 0 { @@ -145,7 +135,7 @@ func (s *testDBSuite6) TestPlacementPolicy(c *C) { return } } - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) tk.MustExec("create placement policy x " + "LEARNERS=1 " + @@ -154,24 +144,24 @@ func (s *testDBSuite6) TestPlacementPolicy(c *C) { "FOLLOWER_CONSTRAINTS=\"[+disk=ssd]\"") checkFunc := func(policyInfo *model.PolicyInfo) { - c.Assert(policyInfo.ID != 0, Equals, true) - c.Assert(policyInfo.Name.L, Equals, "x") - c.Assert(policyInfo.Followers, Equals, uint64(3)) - c.Assert(policyInfo.FollowerConstraints, Equals, "[+disk=ssd]") - c.Assert(policyInfo.Voters, Equals, uint64(0)) - c.Assert(policyInfo.VoterConstraints, Equals, "") - c.Assert(policyInfo.Learners, Equals, uint64(1)) - c.Assert(policyInfo.LearnerConstraints, Equals, "[+region=cn-west-1]") - c.Assert(policyInfo.State, Equals, model.StatePublic) - c.Assert(policyInfo.Schedule, Equals, "") + require.Equal(t, true, policyInfo.ID != 0) + require.Equal(t, "x", policyInfo.Name.L) + require.Equal(t, uint64(3), policyInfo.Followers) + require.Equal(t, "[+disk=ssd]", policyInfo.FollowerConstraints) + require.Equal(t, uint64(0), policyInfo.Voters) + require.Equal(t, "", policyInfo.VoterConstraints) + require.Equal(t, uint64(1), policyInfo.Learners) + require.Equal(t, "[+region=cn-west-1]", policyInfo.LearnerConstraints) + require.Equal(t, model.StatePublic, policyInfo.State) + require.Equal(t, "", policyInfo.Schedule) } // Check the policy is correctly reloaded in the information schema. - po := testGetPolicyByNameFromIS(c, tk.Se, "x") + po := testGetPolicyByNameFromIS(t, tk.Session(), "x") checkFunc(po) // Check the policy is correctly written in the kv meta. - po = testGetPolicyByIDFromMeta(c, s.store, policyID) + po = testGetPolicyByIDFromMeta(t, store, policyID) checkFunc(po) tk.MustGetErrCode("create placement policy x "+ @@ -192,8 +182,8 @@ func (s *testDBSuite6) TestPlacementPolicy(c *C) { tk.MustQuery("show warnings").Check(testkit.Rows("Note 8238 Placement policy 'X' already exists")) bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(0, Equals, len(bundles)) + require.NoError(t, err) + require.Equal(t, len(bundles), 0) tk.MustExec("drop placement policy x") tk.MustGetErrCode("drop placement policy x", mysql.ErrPlacementPolicyNotExists) @@ -203,10 +193,107 @@ func (s *testDBSuite6) TestPlacementPolicy(c *C) { // TODO: privilege check & constraint syntax check. } -func (s *testDBSuite6) TestPlacementFollowers(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreatePlacementPolicyWithInfo(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists tp") + tk.MustExec("drop placement policy if exists p") + tk.MustExec("create placement policy p " + + "LEARNERS=1 " + + "LEARNER_CONSTRAINTS=\"[+region=cn-west-1]\" " + + "FOLLOWERS=3 " + + "FOLLOWER_CONSTRAINTS=\"[+disk=ssd]\"") + defer tk.MustExec("drop placement policy if exists p") + defer tk.MustExec("drop placement policy if exists p2") + tk.MustExec(`CREATE TABLE tp(id int) placement policy p PARTITION BY RANGE (id) ( +PARTITION p0 VALUES LESS THAN (100) PLACEMENT POLICY p, +PARTITION p1 VALUES LESS THAN (1000)) +`) + defer tk.MustExec("drop table if exists tp") + + oldPolicy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p")) + oldPolicy = oldPolicy.Clone() + require.True(t, ok) + + // create a non exist policy + for _, onExist := range []ddl.OnExist{ddl.OnExistReplace, ddl.OnExistIgnore, ddl.OnExistError} { + newPolicy := oldPolicy.Clone() + newPolicy.Name = model.NewCIStr("p2") + newPolicy.Followers = 2 + newPolicy.LearnerConstraints = "[+zone=z2]" + tk.Session().SetValue(sessionctx.QueryString, "skip") + err := dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), onExist) + require.NoError(t, err) + // old policy should not be changed + found, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p")) + require.True(t, ok) + checkPolicyEquals(t, oldPolicy, found) + checkExistTableBundlesInPD(t, dom, "test", "tp") + + // new created policy + found, ok = dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) + // ID of the created policy should be reassigned + require.NotEqual(t, newPolicy.ID, found.ID) + newPolicy.ID = found.ID + checkPolicyEquals(t, newPolicy, found) + tk.MustExec("drop placement policy if exists p2") + } + + // create same name policy with on exists error + newPolicy := oldPolicy.Clone() + newPolicy.ID = oldPolicy.ID + 1 + tk.Session().SetValue(sessionctx.QueryString, "skip") + err := dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), ddl.OnExistError) + require.Error(t, err) + require.True(t, infoschema.ErrPlacementPolicyExists.Equal(err)) + found, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p")) + require.True(t, ok) + checkPolicyEquals(t, oldPolicy, found) + checkExistTableBundlesInPD(t, dom, "test", "tp") + + // create same name policy with on exist ignore + newPolicy = oldPolicy.Clone() + newPolicy.ID = oldPolicy.ID + 1 + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), ddl.OnExistIgnore) + require.NoError(t, err) + found, ok = dom.InfoSchema().PolicyByName(model.NewCIStr("p")) + require.True(t, ok) + checkPolicyEquals(t, oldPolicy, found) + checkExistTableBundlesInPD(t, dom, "test", "tp") + + // create same name policy with on exist replace + newPolicy = oldPolicy.Clone() + newPolicy.ID = oldPolicy.ID + 1 + newPolicy.Followers = 1 + newPolicy.LearnerConstraints = "[+zone=z1]" + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), ddl.OnExistReplace) + require.NoError(t, err) + found, ok = dom.InfoSchema().PolicyByName(model.NewCIStr("p")) + require.True(t, ok) + // when replace a policy the old policy's id should not be changed + newPolicy.ID = oldPolicy.ID + checkPolicyEquals(t, newPolicy, found) + checkExistTableBundlesInPD(t, dom, "test", "tp") +} + +func checkPolicyEquals(t *testing.T, expected *model.PolicyInfo, actual *model.PolicyInfo) { + require.Equal(t, expected.ID, actual.ID) + require.Equal(t, expected.Name, actual.Name) + require.Equal(t, *expected.PlacementSettings, *actual.PlacementSettings) + require.Equal(t, expected.State, actual.State) +} + +func TestPlacementFollowers(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - defer tk.MustExec("drop table if exists t1") defer tk.MustExec("drop placement policy if exists x") tk.MustExec("drop placement policy if exists x") @@ -215,16 +302,9 @@ func (s *testDBSuite6) TestPlacementFollowers(c *C) { tk.MustExec("drop placement policy if exists x") tk.MustExec("create placement policy x FOLLOWERS=4") tk.MustGetErrMsg("alter placement policy x FOLLOWERS=99", "invalid placement option: followers should be less than or equal to 8: 99") - - tk.MustExec("drop table if exists t1") - tk.MustGetErrMsg("create table t1 (a int) followers=99;", "invalid placement option: followers should be less than or equal to 8: 99") - - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int) followers=4;") - tk.MustGetErrMsg("alter table t1 followers=99;", "invalid placement option: followers should be less than or equal to 8: 99") } -func testGetPolicyByIDFromMeta(c *C, store kv.Storage, policyID int64) *model.PolicyInfo { +func testGetPolicyByIDFromMeta(t *testing.T, store kv.Storage, policyID int64) *model.PolicyInfo { var ( policyInfo *model.PolicyInfo err error @@ -237,23 +317,25 @@ func testGetPolicyByIDFromMeta(c *C, store kv.Storage, policyID int64) *model.Po } return nil }) - c.Assert(err1, IsNil) - c.Assert(policyInfo, NotNil) + require.Nil(t, err1) + require.NotNil(t, policyInfo) return policyInfo } -func testGetPolicyByNameFromIS(c *C, ctx sessionctx.Context, policy string) *model.PolicyInfo { +func testGetPolicyByNameFromIS(t *testing.T, ctx sessionctx.Context, policy string) *model.PolicyInfo { dom := domain.GetDomain(ctx) // Make sure the table schema is the new schema. err := dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) po, ok := dom.InfoSchema().PolicyByName(model.NewCIStr(policy)) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) return po } -func (s *testDBSuite6) TestPlacementValidation(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPlacementValidation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists x") @@ -292,8 +374,8 @@ func (s *testDBSuite6) TestPlacementValidation(c *C) { tk.MustExec("drop placement policy if exists x") } else { err := tk.ExecToErr(sql) - c.Assert(err, NotNil, Commentf(ca.name)) - c.Assert(err.Error(), Equals, ca.errmsg, Commentf(ca.name)) + require.NotNil(t, err) + require.EqualErrorf(t, err, ca.errmsg, ca.name) } } @@ -306,97 +388,18 @@ func (s *testDBSuite6) TestPlacementValidation(c *C) { tk.MustExec("alter placement policy x primary_region=\"cn-east-1\" regions=\"cn-east-1,cn-east\"") } else { err := tk.ExecToErr(sql) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ca.errmsg) + require.Error(t, err) + require.Equal(t, ca.errmsg, err.Error()) tk.MustQuery("show placement where target='POLICY x'").Check(testkit.Rows("POLICY x PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east\" NULL")) } } tk.MustExec("drop placement policy x") } -func (s *testDBSuite6) TestSkipPlacementValidation(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop placement policy if exists x") - tk.MustExec("drop placement policy if exists y") - tk.MustExec("drop table if exists t, t_range_p") - - tk.MustExec("create placement policy `y` followers=2;") - tk.MustExec("alter database test placement policy='y'") - tk.MustQuery(`show create database test`).Check(testutil.RowsWithSep("|", - "test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`y` */", - )) - - tk.MustQuery(`select @@PLACEMENT_CHECKS;`).Check(testkit.Rows("1")) - tk.MustGetErrCode("create table t(a int) PLACEMENT POLICY=\"x\"", mysql.ErrPlacementPolicyNotExists) - - tk.MustExec("SET PLACEMENT_CHECKS = 0;") - tk.MustQuery(`select @@PLACEMENT_CHECKS;`).Check(testkit.Rows("0")) - - // Test for `Create` - // Test `CREATE DATABASE`: Skip the check, and create database with default placement option. - tk.MustExec("create database db_skip_validation PLACEMENT POLICY=\"x\"") - tk.MustQuery(`show create database db_skip_validation`).Check(testutil.RowsWithSep("|", - "db_skip_validation CREATE DATABASE `db_skip_validation` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", - )) - // Test `CREATE TABLE`: Skip the check, and inherit from the database placement policy when create table - tk.MustExec("create table t(a int) PLACEMENT POLICY=\"x\"") - tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + - " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`y` */")) - // Test `CREATE PARTITION`: Skip the check, and inherit from the table placement policy when create partition - tk.MustExec("create table t_range_p(id int) placement policy y partition by range(id) (" + - "PARTITION p0 VALUES LESS THAN (100)," + - "PARTITION p1 VALUES LESS THAN (1000) placement policy x)", - ) - tk.MustQuery("show create table t_range_p").Check(testkit.Rows("t_range_p CREATE TABLE `t_range_p` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`y` */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100),\n" + - " PARTITION `p1` VALUES LESS THAN (1000))", - )) - - // Test for `ALTER` - // Test `ALTER DATABASE`: Skip the check, keep the original opts. - tk.MustExec("alter database db_skip_validation PLACEMENT POLICY=\"x\"") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) - tk.MustQuery(`show create database db_skip_validation`).Check(testutil.RowsWithSep("|", - "db_skip_validation CREATE DATABASE `db_skip_validation` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", - )) - // Test `ALTER TABLE`: Skip the check, keep the original opts. - tk.MustExec("alter table t PLACEMENT POLICY=\"x\"") - tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + - " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`y` */")) - // Test `ALTER PARTITION`: Skip the check, keep the original opts. - tk.MustExec("alter table t_range_p PARTITION p1 placement policy y;") - tk.MustExec("alter table t_range_p PARTITION p0 placement policy x;") - tk.MustQuery("show create table t_range_p").Check(testkit.Rows("t_range_p CREATE TABLE `t_range_p` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`y` */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100),\n" + - " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`y` */)", - )) - tk.MustExec("alter table t_range_p PARTITION p1 placement policy x;") - tk.MustQuery("show create table t_range_p").Check(testkit.Rows("t_range_p CREATE TABLE `t_range_p` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`y` */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100),\n" + - " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`y` */)", - )) - - tk.MustExec("SET PLACEMENT_CHECKS = 1;") - tk.MustExec("drop table if exists t, t_range_p") - tk.MustExec("alter database test placement policy='default'") - tk.MustExec("drop database db_skip_validation;") - tk.MustExec("drop placement policy if exists y;") -} - -func (s *testDBSuite6) TestResetSchemaPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestResetSchemaPlacement(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists TestResetPlacementDB;") tk.MustExec("create placement policy `TestReset` followers=4;") tk.MustGetErrCode("create placement policy `default` followers=4;", mysql.ErrReservedSyntax) @@ -405,42 +408,42 @@ func (s *testDBSuite6) TestResetSchemaPlacement(c *C) { tk.MustExec("create database TestResetPlacementDB placement policy `TestReset`;") tk.MustExec("use TestResetPlacementDB") // Test for `=default` - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ "/*T![placement] PLACEMENT POLICY=`TestReset` */", )) tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY=default;") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) // Test for `SET DEFAULT` tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY=`TestReset`;") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ "/*T![placement] PLACEMENT POLICY=`TestReset` */", )) tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY SET DEFAULT") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) // Test for `= 'DEFAULT'` tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY=`TestReset`;") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ "/*T![placement] PLACEMENT POLICY=`TestReset` */", )) tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY = 'DEFAULT'") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) // Test for "= `DEFAULT`" tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY=`TestReset`;") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ "/*T![placement] PLACEMENT POLICY=`TestReset` */", )) tk.MustExec("ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY = `DEFAULT`") - tk.MustQuery(`show create database TestResetPlacementDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestResetPlacementDB`).Check(testkit.RowsWithSep("|", "TestResetPlacementDB CREATE DATABASE `TestResetPlacementDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) @@ -448,27 +451,40 @@ func (s *testDBSuite6) TestResetSchemaPlacement(c *C) { tk.MustExec("drop database TestResetPlacementDB;") } -func (s *testDBSuite6) TestCreateOrReplacePlacementPolicy(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateOrReplacePlacementPolicy(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists x") + tk.MustExec("drop table if exists tp") // If the policy does not exist, CREATE OR REPLACE PLACEMENT POLICY is the same as CREATE PLACEMENT POLICY tk.MustExec("create or replace placement policy x primary_region=\"cn-east-1\" regions=\"cn-east-1,cn-east\"") defer tk.MustExec("drop placement policy if exists x") tk.MustQuery("show create placement policy x").Check(testkit.Rows("x CREATE PLACEMENT POLICY `x` PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east\"")) + // create a table refers the policy + tk.MustExec(`CREATE TABLE tp(id int) placement policy x PARTITION BY RANGE (id) ( +PARTITION p0 VALUES LESS THAN (100) PLACEMENT POLICY x, +PARTITION p1 VALUES LESS THAN (1000)) +`) + defer tk.MustExec("drop table if exists tp") + // If the policy does exist, CREATE OR REPLACE PLACEMENT_POLICY is the same as ALTER PLACEMENT POLICY. tk.MustExec("create or replace placement policy x primary_region=\"cn-east-1\" regions=\"cn-east-1\"") tk.MustQuery("show create placement policy x").Check(testkit.Rows("x CREATE PLACEMENT POLICY `x` PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1\"")) + checkExistTableBundlesInPD(t, dom, "test", "tp") // Cannot be used together with the if not exists clause. Ref: https://mariadb.com/kb/en/create-view tk.MustGetErrMsg("create or replace placement policy if not exists x primary_region=\"cn-east-1\" regions=\"cn-east-1\"", "[ddl:1221]Incorrect usage of OR REPLACE and IF NOT EXISTS") } -func (s *testDBSuite6) TestAlterPlacementPolicy(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestAlterPlacementPolicy(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists x") tk.MustExec("drop table if exists tp") @@ -482,22 +498,22 @@ func (s *testDBSuite6) TestAlterPlacementPolicy(c *C) { );`) defer tk.MustExec("drop table if exists tp") - policy, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("x")) - c.Assert(ok, IsTrue) + policy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("x")) + require.True(t, ok) // test for normal cases tk.MustExec("alter placement policy x PRIMARY_REGION=\"bj\" REGIONS=\"bj,sh\"") tk.MustQuery("show placement where target='POLICY x'").Check(testkit.Rows("POLICY x PRIMARY_REGION=\"bj\" REGIONS=\"bj,sh\" NULL")) - tk.MustQuery("select * from information_schema.placement_rules where policy_name = 'x'").Check(testkit.Rows(strconv.FormatInt(policy.ID, 10) + " def x bj bj,sh 0 0")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + tk.MustQuery("select * from information_schema.placement_policies where policy_name = 'x'").Check(testkit.Rows(strconv.FormatInt(policy.ID, 10) + " def x bj bj,sh 2 0")) + checkExistTableBundlesInPD(t, dom, "test", "tp") tk.MustExec("alter placement policy x " + "PRIMARY_REGION=\"bj\" " + "REGIONS=\"bj\" " + "SCHEDULE=\"EVEN\"") tk.MustQuery("show placement where target='POLICY x'").Check(testkit.Rows("POLICY x PRIMARY_REGION=\"bj\" REGIONS=\"bj\" SCHEDULE=\"EVEN\" NULL")) - tk.MustQuery("select * from INFORMATION_SCHEMA.PLACEMENT_RULES WHERE POLICY_NAME='x'").Check(testkit.Rows(strconv.FormatInt(policy.ID, 10) + " def x bj bj EVEN 0 0")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + tk.MustQuery("select * from INFORMATION_SCHEMA.PLACEMENT_POLICIES WHERE POLICY_NAME='x'").Check(testkit.Rows(strconv.FormatInt(policy.ID, 10) + " def x bj bj EVEN 2 0")) + checkExistTableBundlesInPD(t, dom, "test", "tp") tk.MustExec("alter placement policy x " + "LEADER_CONSTRAINTS=\"[+region=us-east-1]\" " + @@ -506,10 +522,10 @@ func (s *testDBSuite6) TestAlterPlacementPolicy(c *C) { tk.MustQuery("show placement where target='POLICY x'").Check( testkit.Rows("POLICY x LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" NULL"), ) - tk.MustQuery("SELECT POLICY_NAME,LEADER_CONSTRAINTS,FOLLOWER_CONSTRAINTS,FOLLOWERS FROM information_schema.PLACEMENT_RULES WHERE POLICY_NAME = 'x'").Check( + tk.MustQuery("SELECT POLICY_NAME,LEADER_CONSTRAINTS,FOLLOWER_CONSTRAINTS,FOLLOWERS FROM information_schema.PLACEMENT_POLICIES WHERE POLICY_NAME = 'x'").Check( testkit.Rows("x [+region=us-east-1] [+region=us-east-2] 3"), ) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") tk.MustExec("alter placement policy x " + "VOTER_CONSTRAINTS=\"[+region=bj]\" " + @@ -521,73 +537,43 @@ func (s *testDBSuite6) TestAlterPlacementPolicy(c *C) { testkit.Rows("POLICY x CONSTRAINTS=\"[+disk=ssd]\" VOTERS=5 VOTER_CONSTRAINTS=\"[+region=bj]\" LEARNERS=3 LEARNER_CONSTRAINTS=\"[+region=sh]\" NULL"), ) tk.MustQuery("SELECT " + - "CATALOG_NAME,POLICY_NAME,SCHEMA_NAME,TABLE_NAME,PARTITION_NAME," + + "CATALOG_NAME,POLICY_NAME," + "PRIMARY_REGION,REGIONS,CONSTRAINTS,LEADER_CONSTRAINTS,FOLLOWER_CONSTRAINTS,LEARNER_CONSTRAINTS," + - "SCHEDULE,FOLLOWERS,LEARNERS FROM INFORMATION_SCHEMA.placement_rules WHERE POLICY_NAME='x'").Check( - testkit.Rows("def x [+disk=ssd] [+region=sh] 0 3"), + "SCHEDULE,FOLLOWERS,LEARNERS FROM INFORMATION_SCHEMA.placement_policies WHERE POLICY_NAME='x'").Check( + testkit.Rows("def x [+disk=ssd] [+region=sh] 2 3"), ) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // test alter not exist policies tk.MustExec("drop table tp") tk.MustExec("drop placement policy x") tk.MustGetErrCode("alter placement policy x REGIONS=\"bj,sh\"", mysql.ErrPlacementPolicyNotExists) tk.MustGetErrCode("alter placement policy x2 REGIONS=\"bj,sh\"", mysql.ErrPlacementPolicyNotExists) - tk.MustQuery("select * from INFORMATION_SCHEMA.PLACEMENT_RULES WHERE POLICY_NAME='x'").Check(testkit.Rows()) + tk.MustQuery("select * from INFORMATION_SCHEMA.PLACEMENT_POLICIES WHERE POLICY_NAME='x'").Check(testkit.Rows()) } -func (s *testDBSuite6) TestCreateTableWithPlacementPolicy(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithPlacementPolicy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t,t_range_p,t_hash_p,t_list_p") + tk.MustExec("drop placement policy if exists x") + tk.MustExec("drop placement policy if exists y") + defer func() { + tk.MustExec("drop table if exists t,t_range_p,t_hash_p,t_list_p") + tk.MustExec("drop placement policy if exists x") + tk.MustExec("drop placement policy if exists y") + }() - // Direct placement option: special constraints may be incompatible with common constraint. - _, err := tk.Exec("create table t(a int) " + + // special constraints may be incompatible with common constraint. + _, err := tk.Exec("create placement policy pn " + "FOLLOWERS=2 " + "FOLLOWER_CONSTRAINTS=\"[+zone=cn-east-1]\" " + "CONSTRAINTS=\"[+disk=ssd,-zone=cn-east-1]\"") - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, ".*conflicting label constraints.*") - - tk.MustExec("create table t(a int) " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 ") - defer tk.MustExec("DROP TABLE IF EXISTS t") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t PRIMARY_REGION="cn-east-1" REGIONS="cn-east-1, cn-east-2" FOLLOWERS=2`)) - checkExistTableBundlesInPD(c, s.dom, "test", "t") - - tbl := testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef, IsNil) - c.Assert(tbl.Meta().DirectPlacementOpts, NotNil) - - checkFunc := func(policySetting *model.PlacementSettings) { - c.Assert(policySetting.PrimaryRegion, Equals, "cn-east-1") - c.Assert(policySetting.Regions, Equals, "cn-east-1, cn-east-2") - c.Assert(policySetting.Followers, Equals, uint64(2)) - c.Assert(policySetting.FollowerConstraints, Equals, "") - c.Assert(policySetting.Voters, Equals, uint64(0)) - c.Assert(policySetting.VoterConstraints, Equals, "") - c.Assert(policySetting.Learners, Equals, uint64(0)) - c.Assert(policySetting.LearnerConstraints, Equals, "") - c.Assert(policySetting.Constraints, Equals, "") - c.Assert(policySetting.Schedule, Equals, "") - } - checkFunc(tbl.Meta().DirectPlacementOpts) - tk.MustQuery("SELECT * FROM information_schema.placement_rules WHERE TABLE_NAME = 't'").Check(testkit.Rows(" def test t cn-east-1 cn-east-1, cn-east-2 2 0")) - tk.MustExec("drop table if exists t") - - // Direct placement option and placement policy can't co-exist. - _, err = tk.Exec("create table t(a int) " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 " + - "CONSTRAINTS=\"[+disk=ssd]\" " + - "PLACEMENT POLICY=\"x\"") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'x' can't co-exist with direct placement options") + require.Error(t, err) + require.Regexp(t, ".*conflicting label constraints.*", err.Error()) // Only placement policy should check the policy existence. tk.MustGetErrCode("create table t(a int)"+ @@ -600,60 +586,55 @@ func (s *testDBSuite6) TestCreateTableWithPlacementPolicy(c *C) { "CONSTRAINTS=\"[+region=bj]\" ") tk.MustExec("create table t(a int)" + "PLACEMENT POLICY=\"x\"") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t x `)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t x`)) tk.MustExec("create table t_range_p(id int) placement policy x partition by range(id) (" + "PARTITION p0 VALUES LESS THAN (100)," + "PARTITION p1 VALUES LESS THAN (1000) placement policy y," + - "PARTITION p2 VALUES LESS THAN (10000) PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1, cn-east-2\" FOLLOWERS=2 )", + "PARTITION p2 VALUES LESS THAN (10000))", ) tk.MustExec("set tidb_enable_list_partition=1") tk.MustExec("create table t_list_p(name varchar(10)) placement policy x partition by list columns(name) (" + "PARTITION p0 VALUES IN ('a', 'b')," + "PARTITION p1 VALUES IN ('c', 'd') placement policy y," + - "PARTITION p2 VALUES IN ('e', 'f') PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1, cn-east-2\" FOLLOWERS=2 )", + "PARTITION p2 VALUES IN ('e', 'f'))", ) tk.MustExec("create table t_hash_p(id int) placement policy x partition by HASH(id) PARTITIONS 4") - policyX := testGetPolicyByName(c, tk.Se, "x", true) - c.Assert(policyX.Name.L, Equals, "x") - c.Assert(policyX.ID != 0, Equals, true) + policyX := testGetPolicyByName(t, tk.Session(), "x", true) + require.Equal(t, "x", policyX.Name.L) + require.Equal(t, true, policyX.ID != 0) - policyY := testGetPolicyByName(c, tk.Se, "y", true) - c.Assert(policyY.Name.L, Equals, "y") - c.Assert(policyY.ID != 0, Equals, true) + policyY := testGetPolicyByName(t, tk.Session(), "y", true) + require.Equal(t, "y", policyY.Name.L) + require.Equal(t, true, policyY.ID != 0) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef.Name.L, Equals, "x") - c.Assert(tbl.Meta().PlacementPolicyRef.ID, Equals, policyX.ID) - tk.MustQuery("SELECT * FROM information_schema.placement_rules WHERE TABLE_NAME = 't'").Check(testkit.Rows()) + tbl := external.GetTableByName(t, tk, "test", "t") + require.NotNil(t, tbl) + require.NotNil(t, tbl.Meta().PlacementPolicyRef) + require.Equal(t, "x", tbl.Meta().PlacementPolicyRef.Name.L) + require.Equal(t, policyX.ID, tbl.Meta().PlacementPolicyRef.ID) tk.MustExec("drop table if exists t") checkPartitionTableFunc := func(tblName string) { - tbl = testGetTableByName(c, tk.Se, "test", tblName) - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef.Name.L, Equals, "x") - c.Assert(tbl.Meta().PlacementPolicyRef.ID, Equals, policyX.ID) - c.Assert(tbl.Meta().DirectPlacementOpts, IsNil) + tbl = external.GetTableByName(t, tk, "test", tblName) + require.NotNil(t, tbl) + require.NotNil(t, tbl.Meta().PlacementPolicyRef) + require.Equal(t, "x", tbl.Meta().PlacementPolicyRef.Name.L) + require.Equal(t, policyX.ID, tbl.Meta().PlacementPolicyRef.ID) - c.Assert(tbl.Meta().Partition, NotNil) - c.Assert(len(tbl.Meta().Partition.Definitions), Equals, 3) + require.NotNil(t, tbl.Meta().Partition) + require.Equal(t, 3, len(tbl.Meta().Partition.Definitions)) p0 := tbl.Meta().Partition.Definitions[0] - c.Assert(p0.PlacementPolicyRef, IsNil) - c.Assert(p0.DirectPlacementOpts, IsNil) + require.Nil(t, p0.PlacementPolicyRef) p1 := tbl.Meta().Partition.Definitions[1] - c.Assert(p1.PlacementPolicyRef, NotNil) - c.Assert(p1.PlacementPolicyRef.Name.L, Equals, "y") - c.Assert(p1.PlacementPolicyRef.ID, Equals, policyY.ID) - c.Assert(p1.DirectPlacementOpts, IsNil) + require.NotNil(t, p1.PlacementPolicyRef) + require.Equal(t, "y", p1.PlacementPolicyRef.Name.L) + require.Equal(t, policyY.ID, p1.PlacementPolicyRef.ID) p2 := tbl.Meta().Partition.Definitions[2] - c.Assert(p0.PlacementPolicyRef, IsNil) - checkFunc(p2.DirectPlacementOpts) + require.Nil(t, p2.PlacementPolicyRef) } checkPartitionTableFunc("t_range_p") @@ -662,48 +643,146 @@ func (s *testDBSuite6) TestCreateTableWithPlacementPolicy(c *C) { checkPartitionTableFunc("t_list_p") tk.MustExec("drop table if exists t_list_p") - tbl = testGetTableByName(c, tk.Se, "test", "t_hash_p") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef, NotNil) - c.Assert(tbl.Meta().PlacementPolicyRef.Name.L, Equals, "x") - c.Assert(tbl.Meta().PlacementPolicyRef.ID, Equals, policyX.ID) - c.Assert(tbl.Meta().DirectPlacementOpts, IsNil) + tbl = external.GetTableByName(t, tk, "test", "t_hash_p") + require.NotNil(t, tbl) + require.NotNil(t, tbl.Meta().PlacementPolicyRef) + require.Equal(t, "x", tbl.Meta().PlacementPolicyRef.Name.L) + require.Equal(t, policyX.ID, tbl.Meta().PlacementPolicyRef.ID) for _, p := range tbl.Meta().Partition.Definitions { - c.Assert(p.PlacementPolicyRef, IsNil) - c.Assert(p.DirectPlacementOpts, IsNil) + require.Nil(t, p.PlacementPolicyRef) } - tk.MustExec("drop table if exists t_hash_p") +} - tk.MustExec("create table t(a int)" + - "FOLLOWERS=2 " + - "CONSTRAINTS=\"[+disk=ssd]\" ") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t CONSTRAINTS="[+disk=ssd]" FOLLOWERS=2`)) - - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(tbl, NotNil) - c.Assert(tbl.Meta().DirectPlacementOpts, NotNil) - - checkFunc = func(policySetting *model.PlacementSettings) { - c.Assert(policySetting.PrimaryRegion, Equals, "") - c.Assert(policySetting.Regions, Equals, "") - c.Assert(policySetting.Followers, Equals, uint64(2)) - c.Assert(policySetting.FollowerConstraints, Equals, "") - c.Assert(policySetting.Voters, Equals, uint64(0)) - c.Assert(policySetting.VoterConstraints, Equals, "") - c.Assert(policySetting.Learners, Equals, uint64(0)) - c.Assert(policySetting.LearnerConstraints, Equals, "") - c.Assert(policySetting.Constraints, Equals, "[+disk=ssd]") - c.Assert(policySetting.Schedule, Equals, "") +func getClonedTable(dom *domain.Domain, dbName string, tableName string) (*model.TableInfo, error) { + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(dbName), model.NewCIStr(tableName)) + if err != nil { + return nil, err } - checkFunc(tbl.Meta().DirectPlacementOpts) - tk.MustQuery("SELECT * FROM information_schema.placement_rules WHERE TABLE_NAME = 't'").Check(testkit.Rows(" def test t [+disk=ssd] 2 0")) - tk.MustExec("drop table if exists t") - tk.MustExec("drop placement policy if exists x") - tk.MustExec("drop placement policy if exists y") + + tblMeta := tbl.Meta() + tblMeta = tblMeta.Clone() + policyRef := *tblMeta.PlacementPolicyRef + tblMeta.PlacementPolicyRef = &policyRef + return tblMeta, nil } -func (s *testDBSuite6) TestDropPlacementPolicyInUse(c *C) { - tk := testkit.NewTestKit(c, s.store) +func getClonedDatabase(dom *domain.Domain, dbName string) (*model.DBInfo, bool) { + db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr(dbName)) + if !ok { + return nil, ok + } + + db = db.Clone() + policyRef := *db.PlacementPolicyRef + db.PlacementPolicyRef = &policyRef + return db, true +} + +func TestCreateTableWithInfoPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop database if exists test2") + tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p1 followers=1") + defer tk.MustExec("drop placement policy if exists p1") + tk.MustExec("create table t1(a int) placement policy p1") + defer tk.MustExec("drop table if exists t1") + tk.MustExec("create database test2") + defer tk.MustExec("drop database if exists test2") + + tbl, err := getClonedTable(dom, "test", "t1") + require.NoError(t, err) + policy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) + require.Equal(t, policy.ID, tbl.PlacementPolicyRef.ID) + + tk.MustExec("alter table t1 placement policy='default'") + tk.MustExec("drop placement policy p1") + tk.MustExec("create placement policy p1 followers=2") + tk.Session().SetValue(sessionctx.QueryString, "skip") + require.Nil(t, dom.DDL().CreateTableWithInfo(tk.Session(), model.NewCIStr("test2"), tbl, ddl.OnExistError)) + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `a` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustQuery("show create table test2.t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `a` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) + tk.MustQuery("show placement where target='TABLE test2.t1'").Check(testkit.Rows("TABLE test2.t1 FOLLOWERS=2 PENDING")) + + // The ref id for new table should be the new policy id + tbl2, err := getClonedTable(dom, "test2", "t1") + require.NoError(t, err) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) + require.Equal(t, policy2.ID, tbl2.PlacementPolicyRef.ID) + require.True(t, policy2.ID != policy.ID) + + // Test policy not exists + tbl2.Name = model.NewCIStr("t3") + tbl2.PlacementPolicyRef.Name = model.NewCIStr("pxx") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreateTableWithInfo(tk.Session(), model.NewCIStr("test2"), tbl2, ddl.OnExistError) + require.Equal(t, "[schema:8239]Unknown placement policy 'pxx'", err.Error()) +} + +func TestCreateSchemaWithInfoPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop database if exists test2") + tk.MustExec("drop database if exists test3") + tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p1 followers=1") + defer tk.MustExec("drop placement policy if exists p1") + tk.MustExec("create database test2 placement policy p1") + defer tk.MustExec("drop database if exists test2") + defer tk.MustExec("drop database if exists test3") + + db, ok := getClonedDatabase(dom, "test2") + require.True(t, ok) + policy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) + require.Equal(t, policy.ID, db.PlacementPolicyRef.ID) + + db2 := db.Clone() + db2.Name = model.NewCIStr("test3") + tk.MustExec("alter database test2 placement policy='default'") + tk.MustExec("drop placement policy p1") + tk.MustExec("create placement policy p1 followers=2") + tk.Session().SetValue(sessionctx.QueryString, "skip") + require.Nil(t, dom.DDL().CreateSchemaWithInfo(tk.Session(), db2, ddl.OnExistError)) + tk.MustQuery("show create database test2").Check(testkit.Rows("test2 CREATE DATABASE `test2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + tk.MustQuery("show create database test3").Check(testkit.Rows("test3 CREATE DATABASE `test3` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`p1` */")) + tk.MustQuery("show placement where target='DATABASE test3'").Check(testkit.Rows("DATABASE test3 FOLLOWERS=2 SCHEDULED")) + + // The ref id for new table should be the new policy id + db2, ok = getClonedDatabase(dom, "test3") + require.True(t, ok) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) + require.Equal(t, policy2.ID, db2.PlacementPolicyRef.ID) + require.True(t, policy2.ID != policy.ID) + + // Test policy not exists + db2.Name = model.NewCIStr("test4") + db2.PlacementPolicyRef.Name = model.NewCIStr("p2") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err := dom.DDL().CreateSchemaWithInfo(tk.Session(), db2, ddl.OnExistError) + require.Equal(t, "[schema:8239]Unknown placement policy 'p2'", err.Error()) +} + +func TestDropPlacementPolicyInUse(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create database if not exists test2") tk.MustExec("drop table if exists test.t11, test.t12, test2.t21, test2.t21, test2.t22") @@ -731,7 +810,7 @@ func (s *testDBSuite6) TestDropPlacementPolicyInUse(c *C) { defer tk.MustExec("drop placement policy if exists p2") tk.MustExec("create table test.t12 (id int) placement policy 'p2'") defer tk.MustExec("drop table if exists test.t12") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't12'").Check(testkit.Rows(`def test t12 p2 `)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't12'").Check(testkit.Rows(`def test t12 p2`)) // p3 is used by test2.t22 tk.MustExec("create placement policy p3 " + @@ -751,28 +830,28 @@ func (s *testDBSuite6) TestDropPlacementPolicyInUse(c *C) { tk.MustExec("create database test_p placement policy 'p4'") defer tk.MustExec("drop database if exists test_p") - txn, err := s.store.Begin() - c.Assert(err, IsNil) + txn, err := store.Begin() + require.NoError(t, err) defer func() { - c.Assert(txn.Rollback(), IsNil) + require.Nil(t, txn.Rollback()) }() for _, policyName := range []string{"p1", "p2", "p3", "p4"} { err := tk.ExecToErr(fmt.Sprintf("drop placement policy %s", policyName)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:8241]Placement policy '%s' is still in use", policyName)) + require.Equal(t, fmt.Sprintf("[ddl:8241]Placement policy '%s' is still in use", policyName), err.Error()) err = tk.ExecToErr(fmt.Sprintf("drop placement policy if exists %s", policyName)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:8241]Placement policy '%s' is still in use", policyName)) + require.Equal(t, fmt.Sprintf("[ddl:8241]Placement policy '%s' is still in use", policyName), err.Error()) } } -func testGetPolicyByName(c *C, ctx sessionctx.Context, name string, mustExist bool) *model.PolicyInfo { +func testGetPolicyByName(t *testing.T, ctx sessionctx.Context, name string, mustExist bool) *model.PolicyInfo { dom := domain.GetDomain(ctx) // Make sure the table schema is the new schema. err := dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) po, ok := dom.InfoSchema().PolicyByName(model.NewCIStr(name)) if mustExist { - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) } return po } @@ -804,38 +883,40 @@ func testGetPolicyDependency(storage kv.Storage, name string) []int64 { return ids } -func (s *testDBSuite6) TestPolicyCacheAndPolicyDependency(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPolicyCacheAndPolicyDependency(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists x") // Test policy cache. tk.MustExec("create placement policy x primary_region=\"r1\" regions=\"r1,r2\" schedule=\"EVEN\";") - po := testGetPolicyByName(c, tk.Se, "x", true) - c.Assert(po, NotNil) - tk.MustQuery("show placement").Check(testkit.Rows("POLICY x PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" NULL")) + po := testGetPolicyByName(t, tk.Session(), "x", true) + require.NotNil(t, po) + tk.MustQuery("show placement where target='POLICY x'").Check(testkit.Rows("POLICY x PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" NULL")) tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int) placement policy \"x\"") defer tk.MustExec("drop table if exists t") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t BASE TABLE x `)) - tbl := testGetTableByName(c, tk.Se, "test", "t") + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t BASE TABLE x`)) + tbl := external.GetTableByName(t, tk, "test", "t") // Test policy dependency cache. - dependencies := testGetPolicyDependency(s.store, "x") - c.Assert(dependencies, NotNil) - c.Assert(len(dependencies), Equals, 1) - c.Assert(dependencies[0], Equals, tbl.Meta().ID) + dependencies := testGetPolicyDependency(store, "x") + require.NotNil(t, dependencies) + require.Equal(t, 1, len(dependencies)) + require.Equal(t, tbl.Meta().ID, dependencies[0]) tk.MustExec("drop table if exists t2") tk.MustExec("create table t2 (a int) placement policy \"x\"") defer tk.MustExec("drop table if exists t2") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t BASE TABLE x `)) - tbl2 := testGetTableByName(c, tk.Se, "test", "t2") + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't'").Check(testkit.Rows(`def test t BASE TABLE x`)) + tbl2 := external.GetTableByName(t, tk, "test", "t2") - dependencies = testGetPolicyDependency(s.store, "x") - c.Assert(dependencies, NotNil) - c.Assert(len(dependencies), Equals, 2) + dependencies = testGetPolicyDependency(store, "x") + require.NotNil(t, dependencies) + require.Equal(t, 2, len(dependencies)) in := func() bool { for _, one := range dependencies { if one == tbl2.Meta().ID { @@ -844,51 +925,55 @@ func (s *testDBSuite6) TestPolicyCacheAndPolicyDependency(c *C) { } return false } - c.Assert(in(), Equals, true) + require.Equal(t, true, in()) // Test drop policy can't succeed cause there are still some table depend on them. _, err := tk.Exec("drop placement policy x") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8241]Placement policy 'x' is still in use") + require.Error(t, err) + require.Equal(t, "[ddl:8241]Placement policy 'x' is still in use", err.Error()) // Drop depended table t firstly. tk.MustExec("drop table if exists t") - dependencies = testGetPolicyDependency(s.store, "x") - c.Assert(dependencies, NotNil) - c.Assert(len(dependencies), Equals, 1) - c.Assert(dependencies[0], Equals, tbl2.Meta().ID) + dependencies = testGetPolicyDependency(store, "x") + require.NotNil(t, dependencies) + require.Equal(t, 1, len(dependencies)) + require.Equal(t, tbl2.Meta().ID, dependencies[0]) _, err = tk.Exec("drop placement policy x") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8241]Placement policy 'x' is still in use") + require.Error(t, err) + require.Equal(t, "[ddl:8241]Placement policy 'x' is still in use", err.Error()) // Drop depended table t2 secondly. tk.MustExec("drop table if exists t2") - dependencies = testGetPolicyDependency(s.store, "x") - c.Assert(dependencies, NotNil) - c.Assert(len(dependencies), Equals, 0) + dependencies = testGetPolicyDependency(store, "x") + require.NotNil(t, dependencies) + require.Equal(t, 0, len(dependencies)) - po = testGetPolicyByName(c, tk.Se, "x", true) - c.Assert(po, NotNil) + po = testGetPolicyByName(t, tk.Session(), "x", true) + require.NotNil(t, po) tk.MustExec("drop placement policy x") - po = testGetPolicyByName(c, tk.Se, "x", false) - c.Assert(po, IsNil) - dependencies = testGetPolicyDependency(s.store, "x") - c.Assert(dependencies, NotNil) - c.Assert(len(dependencies), Equals, 0) + po = testGetPolicyByName(t, tk.Session(), "x", false) + require.Nil(t, po) + dependencies = testGetPolicyDependency(store, "x") + require.NotNil(t, dependencies) + require.Equal(t, 0, len(dependencies)) } -func (s *testDBSuite6) TestAlterTablePartitionWithPlacementPolicy(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestAlterTablePartitionWithPlacementPolicy(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) defer func() { tk.MustExec("drop table if exists t1") tk.MustExec("drop placement policy if exists x") }() tk.MustExec("use test") tk.MustExec("drop table if exists t1") + tk.MustExec("drop placement policy if exists x") + // Direct placement option: special constraints may be incompatible with common constraint. tk.MustExec("create table t1 (c int) PARTITION BY RANGE (c) " + "(PARTITION p0 VALUES LESS THAN (6)," + @@ -896,54 +981,7 @@ func (s *testDBSuite6) TestAlterTablePartitionWithPlacementPolicy(c *C) { "PARTITION p2 VALUES LESS THAN (16)," + "PARTITION p3 VALUES LESS THAN (21));") defer tk.MustExec("drop table if exists t1") - tk.MustQuery("SELECT " + - "CATALOG_NAME,POLICY_NAME,SCHEMA_NAME,TABLE_NAME,PARTITION_NAME," + - "PRIMARY_REGION,REGIONS,CONSTRAINTS,LEADER_CONSTRAINTS,FOLLOWER_CONSTRAINTS,LEARNER_CONSTRAINTS," + - "SCHEDULE,FOLLOWERS,LEARNERS FROM INFORMATION_SCHEMA.placement_rules WHERE table_NAME='t1'").Check( - testkit.Rows()) - checkExistTableBundlesInPD(c, s.dom, "test", "t1") - - tk.MustExec("alter table t1 partition p0 " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 ") - - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Partitions WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't1' AND PARTITION_NAME = 'p0'").Check(testkit.Rows(`def test t1 p0 PRIMARY_REGION="cn-east-1" REGIONS="cn-east-1, cn-east-2" FOLLOWERS=2`)) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Partitions WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't1' AND PARTITION_NAME = 'p1'").Check(testkit.Rows(`def test t1 p1 `)) - tbl := testGetTableByName(c, tk.Se, "test", "t1") - c.Assert(tbl, NotNil) - ptDef := testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") - c.Assert(ptDef.PlacementPolicyRef, IsNil) - c.Assert(ptDef.DirectPlacementOpts, NotNil) - checkExistTableBundlesInPD(c, s.dom, "test", "t1") - - checkFunc := func(policySetting *model.PlacementSettings) { - c.Assert(policySetting.PrimaryRegion, Equals, "cn-east-1") - c.Assert(policySetting.Regions, Equals, "cn-east-1, cn-east-2") - c.Assert(policySetting.Followers, Equals, uint64(2)) - c.Assert(policySetting.FollowerConstraints, Equals, "") - c.Assert(policySetting.Voters, Equals, uint64(0)) - c.Assert(policySetting.VoterConstraints, Equals, "") - c.Assert(policySetting.Learners, Equals, uint64(0)) - c.Assert(policySetting.LearnerConstraints, Equals, "") - c.Assert(policySetting.Constraints, Equals, "") - c.Assert(policySetting.Schedule, Equals, "") - } - checkFunc(ptDef.DirectPlacementOpts) - tk.MustQuery("SELECT " + - "CATALOG_NAME,POLICY_NAME,SCHEMA_NAME,TABLE_NAME,PARTITION_NAME," + - "PRIMARY_REGION,REGIONS,CONSTRAINTS,LEADER_CONSTRAINTS,FOLLOWER_CONSTRAINTS,LEARNER_CONSTRAINTS," + - "SCHEDULE,FOLLOWERS,LEARNERS FROM INFORMATION_SCHEMA.placement_rules WHERE TABLE_NAME='t1'").Check( - testkit.Rows("def test t1 p0 cn-east-1 cn-east-1, cn-east-2 2 0")) - - //Direct placement option and placement policy can't co-exist. - _, err := tk.Exec("alter table t1 partition p0 " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 " + - "PLACEMENT POLICY=\"x\"") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'x' can't co-exist with direct placement options") + checkExistTableBundlesInPD(t, dom, "test", "t1") // Only placement policy should check the policy existence. tk.MustGetErrCode("alter table t1 partition p0 "+ @@ -952,49 +990,26 @@ func (s *testDBSuite6) TestAlterTablePartitionWithPlacementPolicy(c *C) { "FOLLOWERS=2 ") tk.MustExec("alter table t1 partition p0 " + "PLACEMENT POLICY=\"x\"") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Partitions WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't1' AND PARTITION_NAME = 'p0'").Check(testkit.Rows(`def test t1 p0 x `)) - checkExistTableBundlesInPD(c, s.dom, "test", "t1") - - ptDef = testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") - c.Assert(ptDef, NotNil) - c.Assert(ptDef.PlacementPolicyRef, NotNil) - c.Assert(ptDef.PlacementPolicyRef.Name.L, Equals, "x") - c.Assert(ptDef.PlacementPolicyRef.ID != 0, Equals, true) - - tk.MustExec("alter table t1 partition p0 " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 ") - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Partitions WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't1' AND PARTITION_NAME = 'p0'").Check(testkit.Rows("def test t1 p0 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1, cn-east-2\" FOLLOWERS=2")) - - ptDef = testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") - c.Assert(ptDef, NotNil) - c.Assert(ptDef.DirectPlacementOpts, NotNil) - checkExistTableBundlesInPD(c, s.dom, "test", "t1") - - checkFunc = func(policySetting *model.PlacementSettings) { - c.Assert(policySetting.PrimaryRegion, Equals, "cn-east-1") - c.Assert(policySetting.Regions, Equals, "cn-east-1, cn-east-2") - c.Assert(policySetting.Followers, Equals, uint64(2)) - c.Assert(policySetting.FollowerConstraints, Equals, "") - c.Assert(policySetting.Voters, Equals, uint64(0)) - c.Assert(policySetting.VoterConstraints, Equals, "") - c.Assert(policySetting.Learners, Equals, uint64(0)) - c.Assert(policySetting.LearnerConstraints, Equals, "") - c.Assert(policySetting.Constraints, Equals, "") - c.Assert(policySetting.Schedule, Equals, "") - } - checkFunc(ptDef.DirectPlacementOpts) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Partitions WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 't1' AND PARTITION_NAME = 'p0'").Check(testkit.Rows(`def test t1 p0 x`)) + checkExistTableBundlesInPD(t, dom, "test", "t1") + + policyX, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("x")) + require.True(t, ok) + ptDef := testGetPartitionDefinitionsByName(t, tk.Session(), "test", "t1", "p0") + require.NotNil(t, ptDef) + require.NotNil(t, ptDef.PlacementPolicyRef) + require.Equal(t, "x", ptDef.PlacementPolicyRef.Name.L) + require.Equal(t, policyX.ID, ptDef.PlacementPolicyRef.ID) } -func testGetPartitionDefinitionsByName(c *C, ctx sessionctx.Context, db string, table string, ptName string) model.PartitionDefinition { +func testGetPartitionDefinitionsByName(t *testing.T, ctx sessionctx.Context, db string, table string, ptName string) model.PartitionDefinition { dom := domain.GetDomain(ctx) // Make sure the table schema is the new schema. err := dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - c.Assert(err, IsNil) - c.Assert(tbl, NotNil) + require.NoError(t, err) + require.NotNil(t, tbl) var ptDef model.PartitionDefinition for _, def := range tbl.Meta().Partition.Definitions { if ptName == def.Name.L { @@ -1005,30 +1020,41 @@ func testGetPartitionDefinitionsByName(c *C, ctx sessionctx.Context, db string, return ptDef } -func (s *testDBSuite6) TestPolicyInheritance(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestPolicyInheritance(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t, t0") - tk.MustExec("drop placement policy if exists x") + + tk.MustExec("drop database if exists mydb") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + defer func() { + tk.MustExec("drop database if exists mydb") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + }() // test table inherit database's placement rules. - tk.MustExec("create database mydb constraints=\"[+zone=hangzhou]\"") - tk.MustQuery("show create database mydb").Check(testkit.Rows("mydb CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] CONSTRAINTS=\"[+zone=hangzhou]\" */")) + tk.MustExec("create placement policy p1 constraints=\"[+zone=hangzhou]\"") + tk.MustExec("create database mydb placement policy p1") + tk.MustQuery("show create database mydb").Check(testkit.Rows("mydb CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`p1` */")) tk.MustExec("use mydb") tk.MustExec("create table t(a int)") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] CONSTRAINTS=\"[+zone=hangzhou]\" */")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t") + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) + checkExistTableBundlesInPD(t, dom, "mydb", "t") tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int) constraints=\"[+zone=suzhou]\"") + tk.MustExec("create placement policy p2 constraints=\"[+zone=suzhou]\"") + tk.MustExec("create table t(a int) placement policy p2") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] CONSTRAINTS=\"[+zone=suzhou]\" */")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t") + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p2` */")) + checkExistTableBundlesInPD(t, dom, "mydb", "t") tk.MustExec("drop table if exists t") // test create table like should not inherit database's placement rules. @@ -1036,58 +1062,64 @@ func (s *testDBSuite6) TestPolicyInheritance(c *C) { tk.MustQuery("show create table t0").Check(testkit.Rows("t0 CREATE TABLE `t0` (\n" + " `a` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t0") + checkExistTableBundlesInPD(t, dom, "mydb", "t0") tk.MustExec("create table t1 like t0") tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t1") + checkExistTableBundlesInPD(t, dom, "mydb", "t1") tk.MustExec("drop table if exists t0, t") // table will inherit db's placement rules, which is shared by all partition as default one. tk.MustExec("create table t(a int) partition by range(a) (partition p0 values less than (100), partition p1 values less than (200))") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] CONSTRAINTS=\"[+zone=hangzhou]\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`a`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (200))")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t") + checkExistTableBundlesInPD(t, dom, "mydb", "t") tk.MustExec("drop table if exists t") // partition's specified placement rules will override the default one. - tk.MustExec("create table t(a int) partition by range(a) (partition p0 values less than (100) constraints=\"[+zone=suzhou]\", partition p1 values less than (200))") + tk.MustExec("create table t(a int) partition by range(a) (partition p0 values less than (100) placement policy p2, partition p1 values less than (200))") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] CONSTRAINTS=\"[+zone=hangzhou]\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`a`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] CONSTRAINTS=\"[+zone=suzhou]\" */,\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + " PARTITION `p1` VALUES LESS THAN (200))")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t") + checkExistTableBundlesInPD(t, dom, "mydb", "t") tk.MustExec("drop table if exists t") // test partition override table's placement rules. tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int) CONSTRAINTS=\"[+zone=suzhou]\" partition by range(a) (partition p0 values less than (100) CONSTRAINTS=\"[+zone=changzhou]\", partition p1 values less than (200))") + tk.MustExec("create table t(a int) placement policy p2 partition by range(a) (partition p0 values less than (100) placement policy p1, partition p1 values less than (200))") tk.MustQuery("show create table t").Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] CONSTRAINTS=\"[+zone=suzhou]\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p2` */\n" + "PARTITION BY RANGE (`a`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] CONSTRAINTS=\"[+zone=changzhou]\" */,\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + " PARTITION `p1` VALUES LESS THAN (200))")) - checkExistTableBundlesInPD(c, s.dom, "mydb", "t") + checkExistTableBundlesInPD(t, dom, "mydb", "t") } -func (s *testDBSuite6) TestDatabasePlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDatabasePlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists db2") tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") defer tk.MustExec("drop placement policy p1") - policy, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + tk.MustExec("create placement policy p2 primary_region='r2' regions='r1,r2'") + defer tk.MustExec("drop placement policy p2") + + policy1, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) tk.MustExec(`create database db2`) defer tk.MustExec("drop database db2") @@ -1095,40 +1127,41 @@ func (s *testDBSuite6) TestDatabasePlacement(c *C) { "db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) + // alter with policy tk.MustExec("alter database db2 placement policy p1") tk.MustQuery("show create database db2").Check(testkit.Rows( "db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`p1` */", )) - db, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).SchemaByName(model.NewCIStr("db2")) - c.Assert(ok, IsTrue) - c.Assert(db.PlacementPolicyRef.ID, Equals, policy.ID) - c.Assert(db.DirectPlacementOpts, IsNil) + db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("db2")) + require.True(t, ok) + require.Equal(t, policy1.ID, db.PlacementPolicyRef.ID) - // alter with direct placement - tk.MustExec("alter database db2 primary_region='r2' regions='r1,r2'") + tk.MustExec("alter database db2 placement policy p2") tk.MustQuery("show create database db2").Check(testkit.Rows( - "db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r1,r2\" */", + "db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`p2` */", )) + db, ok = dom.InfoSchema().SchemaByName(model.NewCIStr("db2")) + require.True(t, ok) + require.Equal(t, policy2.ID, db.PlacementPolicyRef.ID) + // reset with placement policy 'default' tk.MustExec("alter database db2 placement policy default") tk.MustQuery("show create database db2").Check(testkit.Rows( "db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) + db, ok = dom.InfoSchema().SchemaByName(model.NewCIStr("db2")) + require.True(t, ok) + require.Nil(t, db.PlacementPolicyRef) + // error invalid policy err := tk.ExecToErr("alter database db2 placement policy px") - c.Assert(err.Error(), Equals, "[schema:8239]Unknown placement policy 'px'") - - // error when policy and direct options both set - err = tk.ExecToErr("alter database db2 placement policy p1 primary_region='r2' regions='r2'") - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'p1' can't co-exist with direct placement options") - - // error for invalid placement opt - err = tk.ExecToErr("alter database db2 primary_region='r2' regions='r2' leader_constraints='[+region=bj]'") - c.Assert(err.Error(), Equals, "invalid placement option: should be [LEADER/VOTER/LEARNER/FOLLOWER]_CONSTRAINTS=.. [VOTERS/FOLLOWERS/LEARNERS]=.., mixed other sugar options PRIMARY_REGION=\"r2\" REGIONS=\"r2\" LEADER_CONSTRAINTS=\"[+region=bj]\"") + require.Equal(t, "[schema:8239]Unknown placement policy 'px'", err.Error()) // failed alter has no effect tk.MustQuery("show create database db2").Check(testkit.Rows( @@ -1136,106 +1169,129 @@ func (s *testDBSuite6) TestDatabasePlacement(c *C) { )) } -func (s *testDBSuite6) TestDropDatabaseGCPlacement(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestDropDatabaseGCPlacement(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists db2") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") tk.MustExec("use test") - tk.MustExec("create table t (id int) primary_region='r0' regions='r0'") + tk.MustExec("create placement policy p1 primary_region='r0' regions='r0'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") + + tk.MustExec("create table t (id int) placement policy p1") defer tk.MustExec("drop table if exists t") tk.MustExec("create database db2") + defer tk.MustExec("drop database if exists db2") + tk.MustExec("create table db2.t0 (id int)") - tk.MustExec("create table db2.t1 (id int) primary_region='r1' regions='r1,r2'") - tk.MustExec(`create table db2.t2 (id int) primary_region='r1' regions='r1,r2' PARTITION BY RANGE (id) ( - PARTITION p0 VALUES LESS THAN (100) primary_region='r2' regions='r2', + tk.MustExec("create table db2.t1 (id int) placement policy p1") + tk.MustExec(`create table db2.t2 (id int) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p2, PARTITION p1 VALUES LESS THAN (1000) )`) - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) - t, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + is := dom.InfoSchema() + tt, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tk.MustExec("drop database db2") bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 4) + require.NoError(t, err) + require.Equal(t, 4, len(bundles)) - gcWorker, err := gcworker.NewMockGCWorker(s.store) - c.Assert(err, IsNil) - c.Assert(gcWorker.DeleteRanges(context.TODO(), math.MaxInt64), IsNil) + gcWorker, err := gcworker.NewMockGCWorker(store) + require.NoError(t, err) + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) bundles, err = infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 1) - c.Assert(bundles[0].ID, Equals, placement.GroupID(t.Meta().ID)) + require.NoError(t, err) + require.Equal(t, 1, len(bundles)) + require.Equal(t, placement.GroupID(tt.Meta().ID), bundles[0].ID) } -func (s *testDBSuite6) TestDropTableGCPlacement(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestDropTableGCPlacement(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists t0,t1") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + + tk.MustExec("create placement policy p1 primary_region='r0' regions='r0'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") tk.MustExec("create table t0 (id int)") defer tk.MustExec("drop table if exists t0") - tk.MustExec("create table t1 (id int) primary_region='r1' regions='r1,r2'") + tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") - tk.MustExec(`create table t2 (id int) primary_region='r1' regions='r1,r2' PARTITION BY RANGE (id) ( - PARTITION p0 VALUES LESS THAN (100) primary_region='r2' regions='r2', + tk.MustExec(`create table t2 (id int) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p2, PARTITION p1 VALUES LESS THAN (1000) )`) defer tk.MustExec("drop table if exists t2") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := dom.InfoSchema() t1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop table t2") bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 3) + require.NoError(t, err) + require.Equal(t, 3, len(bundles)) - gcWorker, err := gcworker.NewMockGCWorker(s.store) - c.Assert(err, IsNil) - c.Assert(gcWorker.DeleteRanges(context.TODO(), math.MaxInt64), IsNil) + gcWorker, err := gcworker.NewMockGCWorker(store) + require.NoError(t, err) + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) bundles, err = infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 1) - c.Assert(bundles[0].ID, Equals, placement.GroupID(t1.Meta().ID)) + require.NoError(t, err) + require.Equal(t, 1, len(bundles)) + require.Equal(t, placement.GroupID(t1.Meta().ID), bundles[0].ID) } -func (s *testDBSuite6) TestAlterTablePlacement(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestAlterTablePlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tp") tk.MustExec("drop placement policy if exists p1") @@ -1243,8 +1299,8 @@ func (s *testDBSuite6) TestAlterTablePlacement(c *C) { tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") defer tk.MustExec("drop placement policy p1") - policy, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + policy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) tk.MustExec(`CREATE TABLE tp (id INT) PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), @@ -1258,7 +1314,7 @@ func (s *testDBSuite6) TestAlterTablePlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // alter with policy tk.MustExec("alter table tp placement policy p1") @@ -1270,22 +1326,10 @@ func (s *testDBSuite6) TestAlterTablePlacement(c *C) { "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - tb, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tb.Meta().PlacementPolicyRef.ID, Equals, policy.ID) - c.Assert(tb.Meta().DirectPlacementOpts, IsNil) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") - - // alter with direct placement - tk.MustExec("alter table tp primary_region='r2' regions='r1,r2'") - tk.MustQuery("show create table tp").Check(testkit.Rows("" + - "tp CREATE TABLE `tp` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r1,r2\" */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100),\n" + - " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, policy.ID, tb.Meta().PlacementPolicyRef.ID) + checkExistTableBundlesInPD(t, dom, "test", "tp") // reset with placement policy 'default' tk.MustExec("alter table tp placement policy default") @@ -1296,19 +1340,11 @@ func (s *testDBSuite6) TestAlterTablePlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // error invalid policy err = tk.ExecToErr("alter table tp placement policy px") - c.Assert(err.Error(), Equals, "[schema:8239]Unknown placement policy 'px'") - - // error when policy and direct options both set - err = tk.ExecToErr("alter table tp placement policy p1 primary_region='r2' regions='r2'") - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'p1' can't co-exist with direct placement options") - - // error for invalid placement opt - err = tk.ExecToErr("alter table tp primary_region='r2' regions='r2' leader_constraints='[+region=bj]'") - c.Assert(err.Error(), Equals, "invalid placement option: should be [LEADER/VOTER/LEARNER/FOLLOWER]_CONSTRAINTS=.. [VOTERS/FOLLOWERS/LEARNERS]=.., mixed other sugar options PRIMARY_REGION=\"r2\" REGIONS=\"r2\" LEADER_CONSTRAINTS=\"[+region=bj]\"") + require.Equal(t, "[schema:8239]Unknown placement policy 'px'", err.Error()) // failed alter has no effect tk.MustQuery("show create table tp").Check(testkit.Rows("" + @@ -1318,73 +1354,89 @@ func (s *testDBSuite6) TestAlterTablePlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") } -func (s *testDBSuite6) TestDropTablePartitionGCPlacement(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestDropTablePartitionGCPlacement(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists t0,t1") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + tk.MustExec("drop placement policy if exists p3") + + tk.MustExec("create placement policy p1 primary_region='r0' regions='r0'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") + + tk.MustExec("create placement policy p3 primary_region='r2' regions='r2'") + defer tk.MustExec("drop placement policy if exists p2") tk.MustExec("create table t0 (id int)") defer tk.MustExec("drop table if exists t0") - tk.MustExec("create table t1 (id int) primary_region='r1' regions='r1,r2'") + tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") - tk.MustExec(`create table t2 (id int) primary_region='r1' regions='r1,r2' PARTITION BY RANGE (id) ( - PARTITION p0 VALUES LESS THAN (100) primary_region='r2' regions='r2', - PARTITION p1 VALUES LESS THAN (1000) primary_region='r3' regions='r3' + tk.MustExec(`create table t2 (id int) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p2, + PARTITION p1 VALUES LESS THAN (1000) placement policy p3 )`) defer tk.MustExec("drop table if exists t2") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := dom.InfoSchema() t1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) t2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("alter table t2 drop partition p0") bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 4) + require.NoError(t, err) + require.Equal(t, 4, len(bundles)) - gcWorker, err := gcworker.NewMockGCWorker(s.store) - c.Assert(err, IsNil) - c.Assert(gcWorker.DeleteRanges(context.TODO(), math.MaxInt64), IsNil) + gcWorker, err := gcworker.NewMockGCWorker(store) + require.NoError(t, err) + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) bundles, err = infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 3) + require.NoError(t, err) + require.Equal(t, 3, len(bundles)) bundlesMap := make(map[string]*placement.Bundle) for _, bundle := range bundles { bundlesMap[bundle.ID] = bundle } _, ok := bundlesMap[placement.GroupID(t1.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().Partition.Definitions[1].ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) } -func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestAlterTablePartitionPlacement(t *testing.T) { + // clearAllBundles(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tp") tk.MustExec("drop placement policy if exists p0") @@ -1396,8 +1448,8 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") defer tk.MustExec("drop placement policy p1") - policy, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + policy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) tk.MustExec(`CREATE TABLE tp (id INT) placement policy p0 PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), @@ -1411,7 +1463,7 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // alter with policy tk.MustExec("alter table tp partition p0 placement policy p1") @@ -1423,32 +1475,10 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - tb, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tb.Meta().Partition.Definitions[0].PlacementPolicyRef.ID, Equals, policy.ID) - c.Assert(tb.Meta().Partition.Definitions[0].DirectPlacementOpts, IsNil) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") - - // alter with direct placement - tk.MustExec("alter table tp partition p1 primary_region='r2' regions='r1,r2'") - tk.MustQuery("show create table tp").Check(testkit.Rows("" + - "tp CREATE TABLE `tp` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p0` */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + - " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r1,r2\" */)")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") - - tk.MustExec("alter table tp partition p1 primary_region='r3' regions='r3,r4'") - tk.MustQuery("show create table tp").Check(testkit.Rows("" + - "tp CREATE TABLE `tp` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p0` */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + - " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PRIMARY_REGION=\"r3\" REGIONS=\"r3,r4\" */)")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, policy.ID, tb.Meta().Partition.Definitions[0].PlacementPolicyRef.ID) + checkExistTableBundlesInPD(t, dom, "test", "tp") // reset with placement policy 'default' tk.MustExec("alter table tp partition p1 placement policy default") @@ -1459,7 +1489,7 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") tk.MustExec("alter table tp partition p0 placement policy default") tk.MustQuery("show create table tp").Check(testkit.Rows("" + @@ -1469,23 +1499,15 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // error invalid policy err = tk.ExecToErr("alter table tp partition p1 placement policy px") - c.Assert(err.Error(), Equals, "[schema:8239]Unknown placement policy 'px'") - - // error when policy and direct options both set - err = tk.ExecToErr("alter table tp partition p0 placement policy p1 primary_region='r2' regions='r2'") - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'p1' can't co-exist with direct placement options") - - // error for invalid placement opt - err = tk.ExecToErr("alter table tp partition p1 primary_region='r2' regions='r2' leader_constraints='[+region=bj]'") - c.Assert(err.Error(), Equals, "invalid placement option: should be [LEADER/VOTER/LEARNER/FOLLOWER]_CONSTRAINTS=.. [VOTERS/FOLLOWERS/LEARNERS]=.., mixed other sugar options PRIMARY_REGION=\"r2\" REGIONS=\"r2\" LEADER_CONSTRAINTS=\"[+region=bj]\"") + require.Equal(t, "[schema:8239]Unknown placement policy 'px'", err.Error()) // error invalid partition name - err = tk.ExecToErr("alter table tp partition p2 primary_region='r2' regions='r2'") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p2' in table 'tp'") + err = tk.ExecToErr("alter table tp partition p2 placement policy p1") + require.Equal(t, "[table:1735]Unknown partition 'p2' in table 'tp'", err.Error()) // failed alter has no effect tk.MustQuery("show create table tp").Check(testkit.Rows("" + @@ -1495,23 +1517,29 @@ func (s *testDBSuite6) TestAlterTablePartitionPlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") } -func (s *testDBSuite6) TestAddPartitionWithPlacement(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestAddPartitionWithPlacement(t *testing.T) { + // clearAllBundles(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tp") tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") defer tk.MustExec("drop placement policy p1") - policy, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + tk.MustExec("create placement policy p2 primary_region='r2' regions='r2'") + defer tk.MustExec("drop placement policy p2") - tk.MustExec(`CREATE TABLE tp (id INT) PARTITION BY RANGE (id) ( + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) + + tk.MustExec(`CREATE TABLE tp (id INT) PLACEMENT POLICY p1 PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), PARTITION p1 VALUES LESS THAN (1000) );`) @@ -1519,63 +1547,58 @@ func (s *testDBSuite6) TestAddPartitionWithPlacement(c *C) { tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") // Add partitions tk.MustExec(`alter table tp add partition ( - partition p2 values less than (10000) placement policy p1, - partition p3 values less than (100000) primary_region="r1" regions="r1,r2", + partition p2 values less than (10000) placement policy p2, + partition p3 values less than (100000), partition p4 values less than (1000000) placement policy default )`) tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000),\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + - " PARTITION `p3` VALUES LESS THAN (100000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */,\n" + + " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + + " PARTITION `p3` VALUES LESS THAN (100000),\n" + " PARTITION `p4` VALUES LESS THAN (1000000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") - tb, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tb.Meta().Partition.Definitions[2].PlacementPolicyRef.ID, Equals, policy.ID) + tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, policy2.ID, tb.Meta().Partition.Definitions[2].PlacementPolicyRef.ID) // error invalid policy err = tk.ExecToErr("alter table tp add partition (partition p5 values less than (10000000) placement policy px)") - c.Assert(err.Error(), Equals, "[schema:8239]Unknown placement policy 'px'") - - // error when policy and direct options both set - err = tk.ExecToErr("alter table tp add partition (partition p5 values less than (10000000) placement policy p1 primary_region='r2' regions='r2')") - c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'p1' can't co-exist with direct placement options") - - // error for invalid placement opt - err = tk.ExecToErr("alter table tp add partition (partition p5 values less than (10000000) primary_region='r2' regions='r2' leader_constraints='[+region=bj]')") - c.Assert(err.Error(), Equals, "invalid placement option: should be [LEADER/VOTER/LEARNER/FOLLOWER]_CONSTRAINTS=.. [VOTERS/FOLLOWERS/LEARNERS]=.., mixed other sugar options PRIMARY_REGION=\"r2\" REGIONS=\"r2\" LEADER_CONSTRAINTS=\"[+region=bj]\"") + require.Equal(t, "[schema:8239]Unknown placement policy 'px'", err.Error()) // failed alter has no effect tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000),\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + - " PARTITION `p3` VALUES LESS THAN (100000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */,\n" + + " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + + " PARTITION `p3` VALUES LESS THAN (100000),\n" + " PARTITION `p4` VALUES LESS THAN (1000000))")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + checkExistTableBundlesInPD(t, dom, "test", "tp") } -func (s *testDBSuite6) TestTruncateTableWithPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateTableWithPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists t1, tp") tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop placement policy if exists p2") @@ -1586,44 +1609,44 @@ func (s *testDBSuite6) TestTruncateTableWithPlacement(c *C) { tk.MustExec("create placement policy p2 primary_region='r2' regions='r2'") defer tk.MustExec("drop placement policy p2") - policy1, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + policy1, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) - policy2, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p2")) - c.Assert(ok, IsTrue) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) - tk.MustExec(`CREATE TABLE t1 (id INT) primary_region="r1" regions="r1"`) + tk.MustExec(`CREATE TABLE t1 (id INT) placement policy p1`) defer tk.MustExec("drop table t1") // test for normal table tk.MustQuery("show create table t1").Check(testkit.Rows("" + "t1 CREATE TABLE `t1` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */")) + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) - t1, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + t1, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) tk.MustExec("TRUNCATE TABLE t1") tk.MustQuery("show create table t1").Check(testkit.Rows("" + "t1 CREATE TABLE `t1` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */")) - newT1, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(newT1.Meta().ID != t1.Meta().ID, IsTrue) + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) + newT1, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + require.True(t, newT1.Meta().ID != t1.Meta().ID) // test for partitioned table tk.MustExec(`CREATE TABLE tp (id INT) placement policy p1 PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), PARTITION p1 VALUES LESS THAN (1000) placement policy p2, - PARTITION p2 VALUES LESS THAN (10000) primary_region="r1" regions="r1,r2" + PARTITION p2 VALUES LESS THAN (10000) );`) defer tk.MustExec("drop table tp") - tp, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tp.Meta().PlacementPolicyRef.ID, Equals, policy1.ID) - c.Assert(tp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID, Equals, policy2.ID) + tp, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, policy1.ID, tp.Meta().PlacementPolicyRef.ID) + require.Equal(t, policy2.ID, tp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID) tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + @@ -1631,84 +1654,97 @@ func (s *testDBSuite6) TestTruncateTableWithPlacement(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */)")) + " PARTITION `p2` VALUES LESS THAN (10000))")) tk.MustExec("TRUNCATE TABLE tp") - newTp, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(newTp.Meta().ID != tp.Meta().ID, IsTrue) - c.Assert(newTp.Meta().PlacementPolicyRef.ID, Equals, policy1.ID) - c.Assert(newTp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID, Equals, policy2.ID) + newTp, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.True(t, newTp.Meta().ID != tp.Meta().ID) + require.Equal(t, policy1.ID, newTp.Meta().PlacementPolicyRef.ID) + require.Equal(t, policy2.ID, newTp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID) for i := range []int{0, 1, 2} { - c.Assert(newTp.Meta().Partition.Definitions[i].ID != tp.Meta().Partition.Definitions[i].ID, IsTrue) + require.True(t, newTp.Meta().Partition.Definitions[i].ID != tp.Meta().Partition.Definitions[i].ID) } } -func (s *testDBSuite6) TestTruncateTableGCWithPlacement(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestTruncateTableGCWithPlacement(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists t0,t1") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + + tk.MustExec("create placement policy p1 primary_region='r0' regions='r0'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") tk.MustExec("create table t0 (id int)") defer tk.MustExec("drop table if exists t0") - tk.MustExec("create table t1 (id int) primary_region='r1' regions='r1,r2'") + tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") - tk.MustExec(`create table t2 (id int) primary_region='r1' regions='r1,r2' PARTITION BY RANGE (id) ( - PARTITION p0 VALUES LESS THAN (100) primary_region='r2' regions='r2', + tk.MustExec(`create table t2 (id int) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p2, PARTITION p1 VALUES LESS THAN (1000) )`) defer tk.MustExec("drop table if exists t2") tk.MustExec("truncate table t2") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := dom.InfoSchema() t1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) t2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 5) + require.NoError(t, err) + require.Equal(t, 5, len(bundles)) - gcWorker, err := gcworker.NewMockGCWorker(s.store) - c.Assert(err, IsNil) - c.Assert(gcWorker.DeleteRanges(context.TODO(), math.MaxInt64), IsNil) + gcWorker, err := gcworker.NewMockGCWorker(store) + require.NoError(t, err) + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) bundles, err = infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 3) + require.NoError(t, err) + require.Equal(t, 3, len(bundles)) bundlesMap := make(map[string]*placement.Bundle) for _, bundle := range bundles { bundlesMap[bundle.ID] = bundle } _, ok := bundlesMap[placement.GroupID(t1.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().Partition.Definitions[0].ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) } -func (s *testDBSuite6) TestTruncateTablePartitionWithPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateTablePartitionWithPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1, tp") + + tk.MustExec("drop table if exists tp") tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop placement policy if exists p2") tk.MustExec("drop placement policy if exists p3") @@ -1722,41 +1758,38 @@ func (s *testDBSuite6) TestTruncateTablePartitionWithPlacement(c *C) { tk.MustExec("create placement policy p3 primary_region='r3' regions='r3'") defer tk.MustExec("drop placement policy p3") - policy1, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) - - policy2, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p2")) - c.Assert(ok, IsTrue) + policy1, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) - policy3, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p3")) - c.Assert(ok, IsTrue) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) - tk.MustExec(`CREATE TABLE t1 (id INT) primary_region="r1" regions="r1"`) - defer tk.MustExec("drop table t1") + policy3, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p3")) + require.True(t, ok) // test for partitioned table tk.MustExec(`CREATE TABLE tp (id INT) placement policy p1 PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), PARTITION p1 VALUES LESS THAN (1000) placement policy p2, PARTITION p2 VALUES LESS THAN (10000) placement policy p3, - PARTITION p3 VALUES LESS THAN (100000) primary_region="r2" regions="r2" + PARTITION p3 VALUES LESS THAN (100000) );`) defer tk.MustExec("drop table tp") - tp, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) + tp, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) tk.MustExec("ALTER TABLE tp TRUNCATE partition p1,p3") - newTp, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(newTp.Meta().ID, Equals, tp.Meta().ID) - c.Assert(newTp.Meta().PlacementPolicyRef.ID, Equals, policy1.ID) - c.Assert(newTp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID, Equals, policy2.ID) - c.Assert(newTp.Meta().Partition.Definitions[2].PlacementPolicyRef.ID, Equals, policy3.ID) - c.Assert(newTp.Meta().Partition.Definitions[0].ID, Equals, tp.Meta().Partition.Definitions[0].ID) - c.Assert(newTp.Meta().Partition.Definitions[1].ID != tp.Meta().Partition.Definitions[1].ID, IsTrue) - c.Assert(newTp.Meta().Partition.Definitions[2].ID, Equals, tp.Meta().Partition.Definitions[2].ID) - c.Assert(newTp.Meta().Partition.Definitions[3].ID != tp.Meta().Partition.Definitions[3].ID, IsTrue) + newTp, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, tp.Meta().ID, newTp.Meta().ID) + require.Equal(t, policy1.ID, newTp.Meta().PlacementPolicyRef.ID) + require.Equal(t, policy2.ID, newTp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID) + require.Equal(t, policy3.ID, newTp.Meta().Partition.Definitions[2].PlacementPolicyRef.ID) + require.Equal(t, tp.Meta().Partition.Definitions[0].ID, newTp.Meta().Partition.Definitions[0].ID) + require.True(t, newTp.Meta().Partition.Definitions[1].ID != tp.Meta().Partition.Definitions[1].ID) + require.Equal(t, tp.Meta().Partition.Definitions[2].ID, newTp.Meta().Partition.Definitions[2].ID) + require.True(t, newTp.Meta().Partition.Definitions[3].ID != tp.Meta().Partition.Definitions[3].ID) tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + @@ -1766,78 +1799,90 @@ func (s *testDBSuite6) TestTruncateTablePartitionWithPlacement(c *C) { "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PLACEMENT POLICY=`p3` */,\n" + - " PARTITION `p3` VALUES LESS THAN (100000) /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r2\" */)")) + " PARTITION `p3` VALUES LESS THAN (100000))")) } -func (s *testDBSuite6) TestTruncatePartitionGCWithPlacement(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestTruncatePartitionGCWithPlacement(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + + tk.MustExec("create placement policy p1 primary_region='r0' regions='r0'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") tk.MustExec("create table t0 (id int)") defer tk.MustExec("drop table if exists t0") - tk.MustExec("create table t1 (id int) primary_region='r1' regions='r1,r2'") + tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") - tk.MustExec(`create table t2 (id int) primary_region='r1' regions='r1,r2' PARTITION BY RANGE (id) ( - PARTITION p0 VALUES LESS THAN (100) primary_region='r2' regions='r2', + tk.MustExec(`create table t2 (id int) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p2, PARTITION p1 VALUES LESS THAN (1000) )`) defer tk.MustExec("drop table if exists t2") tk.MustExec("alter table t2 truncate partition p0") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := dom.InfoSchema() t1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) t2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) bundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 4) + require.NoError(t, err) + require.Equal(t, 4, len(bundles)) - gcWorker, err := gcworker.NewMockGCWorker(s.store) - c.Assert(err, IsNil) - c.Assert(gcWorker.DeleteRanges(context.TODO(), math.MaxInt64), IsNil) + gcWorker, err := gcworker.NewMockGCWorker(store) + require.NoError(t, err) + require.Nil(t, gcWorker.DeleteRanges(context.TODO(), math.MaxInt64)) bundles, err = infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) - c.Assert(len(bundles), Equals, 3) + require.NoError(t, err) + require.Equal(t, 3, len(bundles)) bundlesMap := make(map[string]*placement.Bundle) for _, bundle := range bundles { bundlesMap[bundle.ID] = bundle } _, ok := bundlesMap[placement.GroupID(t1.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) _, ok = bundlesMap[placement.GroupID(t2.Meta().Partition.Definitions[0].ID)] - c.Assert(ok, IsTrue) + require.True(t, ok) } -func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) +func TestExchangePartitionWithPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_enable_exchange_partition=1") tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2, tp") tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop placement policy if exists p2") + tk.MustExec("drop placement policy if exists p3") tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") defer tk.MustExec("drop placement policy p1") @@ -1845,11 +1890,14 @@ func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { tk.MustExec("create placement policy p2 primary_region='r2' regions='r2'") defer tk.MustExec("drop placement policy p2") - policy1, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p1")) - c.Assert(ok, IsTrue) + tk.MustExec("create placement policy p3 primary_region='r3' regions='r3'") + defer tk.MustExec("drop placement policy p3") + + policy1, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) - policy2, ok := tk.Se.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(model.NewCIStr("p2")) - c.Assert(ok, IsTrue) + policy2, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p2")) + require.True(t, ok) tk.MustExec(`CREATE TABLE t1 (id INT) placement policy p1`) defer tk.MustExec("drop table t1") @@ -1857,27 +1905,26 @@ func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { tk.MustExec(`CREATE TABLE t2 (id INT)`) defer tk.MustExec("drop table t2") - t1, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + t1, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) t1ID := t1.Meta().ID - t2, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + t2, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) t2ID := t2.Meta().ID - tk.MustExec(`CREATE TABLE tp (id INT) primary_region="r1" regions="r1" PARTITION BY RANGE (id) ( + tk.MustExec(`CREATE TABLE tp (id INT) placement policy p3 PARTITION BY RANGE (id) ( PARTITION p0 VALUES LESS THAN (100), PARTITION p1 VALUES LESS THAN (1000) placement policy p2, - PARTITION p2 VALUES LESS THAN (10000) primary_region="r1" regions="r1,r2" + PARTITION p2 VALUES LESS THAN (10000) );`) defer tk.MustExec("drop table tp") - tp, err := tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) + tp, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) tpID := tp.Meta().ID par0ID := tp.Meta().Partition.Definitions[0].ID par1ID := tp.Meta().Partition.Definitions[1].ID - par2ID := tp.Meta().Partition.Definitions[2].ID // exchange par0, t1 tk.MustExec("alter table tp exchange partition p0 with table t1") @@ -1888,23 +1935,21 @@ func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p3` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */)")) - tp, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tp.Meta().ID, Equals, tpID) - c.Assert(tp.Meta().Partition.Definitions[0].ID, Equals, t1ID) - c.Assert(tp.Meta().Partition.Definitions[0].DirectPlacementOpts, IsNil) - c.Assert(tp.Meta().Partition.Definitions[0].PlacementPolicyRef, IsNil) - t1, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(t1.Meta().ID, Equals, par0ID) - c.Assert(t1.Meta().DirectPlacementOpts, IsNil) - c.Assert(t1.Meta().PlacementPolicyRef.ID, Equals, policy1.ID) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + " PARTITION `p2` VALUES LESS THAN (10000))")) + tp, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, tpID, tp.Meta().ID) + require.Equal(t, t1ID, tp.Meta().Partition.Definitions[0].ID) + require.Nil(t, tp.Meta().Partition.Definitions[0].PlacementPolicyRef) + t1, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, par0ID, t1.Meta().ID) + require.Equal(t, policy1.ID, t1.Meta().PlacementPolicyRef.ID) + checkExistTableBundlesInPD(t, dom, "test", "tp") // exchange par0, t2 tk.MustExec("alter table tp exchange partition p0 with table t2") @@ -1915,23 +1960,21 @@ func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p3` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */)")) - tp, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tp.Meta().ID, Equals, tpID) - c.Assert(tp.Meta().Partition.Definitions[0].ID, Equals, t2ID) - c.Assert(tp.Meta().Partition.Definitions[0].DirectPlacementOpts, IsNil) - c.Assert(tp.Meta().Partition.Definitions[0].PlacementPolicyRef, IsNil) - t2, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(t2.Meta().ID, Equals, t1ID) - c.Assert(t2.Meta().DirectPlacementOpts, IsNil) - c.Assert(t2.Meta().PlacementPolicyRef, IsNil) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + " PARTITION `p2` VALUES LESS THAN (10000))")) + tp, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, tpID, tp.Meta().ID) + require.Equal(t, t2ID, tp.Meta().Partition.Definitions[0].ID) + require.Nil(t, tp.Meta().Partition.Definitions[0].PlacementPolicyRef) + t2, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + require.Equal(t, t1ID, t2.Meta().ID) + require.Nil(t, t2.Meta().PlacementPolicyRef) + checkExistTableBundlesInPD(t, dom, "test", "tp") // exchange par1, t1 tk.MustExec("alter table tp exchange partition p1 with table t1") @@ -1942,67 +1985,42 @@ func (s *testDBSuite6) TestExchangePartitionWithPlacement(c *C) { tk.MustQuery("show create table tp").Check(testkit.Rows("" + "tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */\n" + - "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100),\n" + - " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */)")) - tp, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tp.Meta().ID, Equals, tpID) - c.Assert(tp.Meta().Partition.Definitions[1].ID, Equals, par0ID) - c.Assert(tp.Meta().Partition.Definitions[1].DirectPlacementOpts, IsNil) - c.Assert(tp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID, Equals, policy2.ID) - t1, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(t1.Meta().ID, Equals, par1ID) - c.Assert(t1.Meta().DirectPlacementOpts, IsNil) - c.Assert(t1.Meta().PlacementPolicyRef.ID, Equals, policy1.ID) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") - - // exchange par2, t2 - tk.MustExec("alter table tp exchange partition p2 with table t2") - tk.MustQuery("show create table t2").Check(testkit.Rows("" + - "t2 CREATE TABLE `t2` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustQuery("show create table tp").Check(testkit.Rows("" + - "tp CREATE TABLE `tp` (\n" + - " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p3` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p2` */,\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */)")) - tp, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) - c.Assert(err, IsNil) - c.Assert(tp.Meta().ID, Equals, tpID) - c.Assert(tp.Meta().Partition.Definitions[2].ID, Equals, t1ID) - c.Assert(tp.Meta().Partition.Definitions[2].DirectPlacementOpts.PrimaryRegion, Equals, "r1") - c.Assert(tp.Meta().Partition.Definitions[2].DirectPlacementOpts.Regions, Equals, "r1,r2") - c.Assert(tp.Meta().Partition.Definitions[2].PlacementPolicyRef, IsNil) - t2, err = tk.Se.GetInfoSchema().(infoschema.InfoSchema).TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(t2.Meta().ID, Equals, par2ID) - c.Assert(t2.Meta().DirectPlacementOpts, IsNil) - c.Assert(t2.Meta().PlacementPolicyRef, IsNil) - checkExistTableBundlesInPD(c, s.dom, "test", "tp") + " PARTITION `p2` VALUES LESS THAN (10000))")) + tp, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("tp")) + require.NoError(t, err) + require.Equal(t, tpID, tp.Meta().ID) + require.Equal(t, par0ID, tp.Meta().Partition.Definitions[1].ID) + require.Equal(t, policy2.ID, tp.Meta().Partition.Definitions[1].PlacementPolicyRef.ID) + t1, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + require.Equal(t, par1ID, t1.Meta().ID) + require.Equal(t, policy1.ID, t1.Meta().PlacementPolicyRef.ID) + checkExistTableBundlesInPD(t, dom, "test", "tp") } -func (s *testDBSuite6) TestPDFail(c *C) { +func TestPDFail(t *testing.T) { defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/domain/infosync/putRuleBundlesError"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/infosync/putRuleBundlesError")) }() - - clearAllBundles(c) - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + // clearAllBundles(t) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop table if exists t1, t2, tp") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") tk.MustExec("create placement policy p1 primary_region=\"cn-east-1\" regions=\"cn-east-1,cn-east\"") defer tk.MustExec("drop placement policy if exists p1") + tk.MustExec("create placement policy p2 followers=1") + defer tk.MustExec("drop placement policy if exists p2") + tk.MustExec("create table t1(id int)") defer tk.MustExec("drop table if exists t1") @@ -2012,59 +2030,59 @@ func (s *testDBSuite6) TestPDFail(c *C) { );`) defer tk.MustExec("drop table if exists tp") existBundles, err := infosync.GetAllRuleBundles(context.TODO()) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/domain/infosync/putRuleBundlesError", "return(true)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/infosync/putRuleBundlesError", "return(true)")) // alter policy err = tk.ExecToErr("alter placement policy p1 primary_region='rx' regions='rx'") - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) tk.MustQuery("show create placement policy p1").Check(testkit.Rows("p1 CREATE PLACEMENT POLICY `p1` PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east\"")) - checkAllBundlesNotChange(c, existBundles) + checkAllBundlesNotChange(t, existBundles) // create table err = tk.ExecToErr("create table t2 (id int) placement policy p1") - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) err = tk.ExecToErr("show create table t2") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) - checkAllBundlesNotChange(c, existBundles) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) + checkAllBundlesNotChange(t, existBundles) // alter table err = tk.ExecToErr("alter table t1 placement policy p1") - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - checkAllBundlesNotChange(c, existBundles) + checkAllBundlesNotChange(t, existBundles) // add partition err = tk.ExecToErr("alter table tp add partition (" + "partition p2 values less than (10000) placement policy p1," + - "partition p3 values less than (100000) primary_region=\"r1\" regions=\"r1,r2\"" + + "partition p3 values less than (100000)" + ")") - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) tk.MustQuery("show create table tp").Check(testkit.Rows("tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p1` */)")) - checkAllBundlesNotChange(c, existBundles) + checkAllBundlesNotChange(t, existBundles) // alter partition - err = tk.ExecToErr(`alter table tp PARTITION p1 primary_region="r2" regions="r2,r3"`) - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + err = tk.ExecToErr(`alter table tp PARTITION p1 placement policy p2`) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) tk.MustQuery("show create table tp").Check(testkit.Rows("tp CREATE TABLE `tp` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p1` */)")) - checkAllBundlesNotChange(c, existBundles) + checkAllBundlesNotChange(t, existBundles) // exchange partition tk.MustExec("alter table tp exchange partition p1 with table t1") - c.Assert(infosync.ErrHTTPServiceError.Equal(err), IsTrue) + require.True(t, infosync.ErrHTTPServiceError.Equal(err)) tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) @@ -2074,23 +2092,24 @@ func (s *testDBSuite6) TestPDFail(c *C) { "PARTITION BY RANGE (`id`)\n" + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000) /*T![placement] PLACEMENT POLICY=`p1` */)")) - checkAllBundlesNotChange(c, existBundles) + checkAllBundlesNotChange(t, existBundles) } -func (s *testDBSuite6) TestRecoverTableWithPlacementPolicy(c *C) { - clearAllBundles(c) - failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`) +func TestRecoverTableWithPlacementPolicy(t *testing.T) { + // clearAllBundles(t) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed", `return`)) defer func(originGC bool) { - failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/ignoreDeleteRangeFailed")) if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) - ddl.EmulatorGCDisable() - - tk := testkit.NewTestKit(c, s.store) + }(util.IsEmulatorGCEnable()) + util.EmulatorGCDisable() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop placement policy if exists p2") @@ -2123,12 +2142,12 @@ func (s *testDBSuite6) TestRecoverTableWithPlacementPolicy(c *C) { tk.MustExec("recover table tp1") tk.MustQuery("show create table tp1").Check(testkit.Rows("tp1 CREATE TABLE `tp1` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r2,r3\" */,\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000),\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r3\" REGIONS=\"r3,r4\" */)")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp1") + " PARTITION `p2` VALUES LESS THAN (10000))")) + checkExistTableBundlesInPD(t, dom, "test", "tp1") // test flashback tk.MustExec(`CREATE TABLE tp2 (id INT) placement policy p1 PARTITION BY RANGE (id) ( @@ -2143,12 +2162,12 @@ func (s *testDBSuite6) TestRecoverTableWithPlacementPolicy(c *C) { tk.MustExec("flashback table tp2") tk.MustQuery("show create table tp2").Check(testkit.Rows("tp2 CREATE TABLE `tp2` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r2,r3\" */,\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000),\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r3\" REGIONS=\"r3,r4\" */)")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp2") + " PARTITION `p2` VALUES LESS THAN (10000))")) + checkExistTableBundlesInPD(t, dom, "test", "tp2") // test recover after police drop tk.MustExec("drop table tp2") @@ -2159,10 +2178,10 @@ func (s *testDBSuite6) TestRecoverTableWithPlacementPolicy(c *C) { tk.MustExec("flashback table tp2 to tp3") tk.MustQuery("show create table tp3").Check(testkit.Rows("tp3 CREATE TABLE `tp3` (\n" + " `id` int(11) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" */\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + "PARTITION BY RANGE (`id`)\n" + - "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PRIMARY_REGION=\"r2\" REGIONS=\"r2,r3\" */,\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + " PARTITION `p1` VALUES LESS THAN (1000),\n" + - " PARTITION `p2` VALUES LESS THAN (10000) /*T![placement] PRIMARY_REGION=\"r3\" REGIONS=\"r3,r4\" */)")) - checkExistTableBundlesInPD(c, s.dom, "test", "tp3") + " PARTITION `p2` VALUES LESS THAN (10000))")) + checkExistTableBundlesInPD(t, dom, "test", "tp3") } diff --git a/ddl/placement_sql_test.go b/ddl/placement_sql_test.go index 62d6f36db1c4a..c7df990a2094b 100644 --- a/ddl/placement_sql_test.go +++ b/ddl/placement_sql_test.go @@ -15,31 +15,33 @@ package ddl_test import ( - "context" "fmt" "sort" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/domain" mysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" ) // TODO: Remove in https://github.com/pingcap/tidb/issues/27971 or change to use SQL PLACEMENT POLICY -func (s *testDBSuite1) TestPlacementPolicyCache(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPlacementPolicyCache(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableAlterPlacement = true tk.MustExec("set @@tidb_enable_exchange_partition = 1") defer func() { tk.MustExec("set @@tidb_enable_exchange_partition = 0") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") - tk.Se.GetSessionVars().EnableAlterPlacement = false }() initTable := func() []string { @@ -48,10 +50,10 @@ func (s *testDBSuite1) TestPlacementPolicyCache(c *C) { tk.MustExec(`create table t1(id int) partition by range(id) (partition p0 values less than (100), partition p1 values less than (200))`) - is := s.dom.InfoSchema() + is := dom.InfoSchema() tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) partDefs := tb.Meta().GetPartitionInfo().Definitions sort.Slice(partDefs, func(i, j int) bool { return partDefs[i].Name.L < partDefs[j].Name.L }) @@ -98,14 +100,14 @@ func (s *testDBSuite1) TestPlacementPolicyCache(c *C) { //tk.MustQuery("select * from information_schema.placement_policy").Check(testkit.Rows()) } -func (s *testSerialDBSuite) TestTxnScopeConstraint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTxnScopeConstraint(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") - tk.Se.GetSessionVars().EnableAlterPlacement = true defer func() { tk.MustExec("drop table if exists t1") - tk.Se.GetSessionVars().EnableAlterPlacement = false }() tk.MustExec(`create table t1 (c int) @@ -116,10 +118,10 @@ PARTITION BY RANGE (c) ( PARTITION p3 VALUES LESS THAN (21) );`) - is := s.dom.InfoSchema() + is := dom.InfoSchema() tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) partDefs := tb.Meta().GetPartitionInfo().Definitions for _, def := range partDefs { @@ -224,12 +226,8 @@ PARTITION BY RANGE (c) ( } for _, testcase := range testCases { - c.Log(testcase.name) failpoint.Enable("tikvclient/injectTxnScope", fmt.Sprintf(`return("%v")`, testcase.zone)) - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) - tk.Se = se tk.MustExec("use test") tk.MustExec("set global tidb_enable_local_txn = on;") tk.MustExec(fmt.Sprintf("set @@txn_scope = %v", testcase.txnScope)) @@ -242,33 +240,26 @@ PARTITION BY RANGE (c) ( _, err = tk.Exec(testcase.sql) } if testcase.err == nil { - c.Assert(err, IsNil) + require.NoError(t, err) } else { - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, testcase.err.Error()) + require.Error(t, err) + require.Regexp(t, testcase.err.Error(), err.Error()) } tk.MustExec("set global tidb_enable_local_txn = off;") failpoint.Disable("tikvclient/injectTxnScope") } } -func (s *testDBSuite6) TestCreateSchemaWithPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop schema if exists SchemaDirectPlacementTest") +func TestCreateSchemaWithPlacement(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop schema if exists SchemaPolicyPlacementTest") - tk.Se.GetSessionVars().EnableAlterPlacement = true defer func() { - tk.MustExec("drop schema if exists SchemaDirectPlacementTest") tk.MustExec("drop schema if exists SchemaPolicyPlacementTest") tk.MustExec("drop placement policy if exists PolicySchemaTest") tk.MustExec("drop placement policy if exists PolicyTableTest") - tk.Se.GetSessionVars().EnableAlterPlacement = false }() - - tk.MustExec(`CREATE SCHEMA SchemaDirectPlacementTest PRIMARY_REGION='nl' REGIONS = "se,nz,nl" FOLLOWERS=3`) - tk.MustQuery("SHOW CREATE SCHEMA schemadirectplacementtest").Check(testkit.Rows("SchemaDirectPlacementTest CREATE DATABASE `SchemaDirectPlacementTest` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PRIMARY_REGION=\"nl\" REGIONS=\"se,nz,nl\" FOLLOWERS=3 */")) - tk.MustQuery("SELECT * FROM information_schema.placement_rules WHERE SCHEMA_NAME='SchemaDirectPlacementTest'").Check(testkit.Rows(" def SchemaDirectPlacementTest nl se,nz,nl 3 0")) - tk.MustExec(`CREATE PLACEMENT POLICY PolicySchemaTest LEADER_CONSTRAINTS = "[+region=nl]" FOLLOWER_CONSTRAINTS="[+region=se]" FOLLOWERS=4 LEARNER_CONSTRAINTS="[+region=be]" LEARNERS=4`) tk.MustExec(`CREATE PLACEMENT POLICY PolicyTableTest LEADER_CONSTRAINTS = "[+region=tl]" FOLLOWER_CONSTRAINTS="[+region=tf]" FOLLOWERS=2 LEARNER_CONSTRAINTS="[+region=tle]" LEARNERS=1`) tk.MustQuery("SHOW PLACEMENT like 'POLICY %PolicySchemaTest%'").Check(testkit.Rows("POLICY PolicySchemaTest LEADER_CONSTRAINTS=\"[+region=nl]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=se]\" LEARNERS=4 LEARNER_CONSTRAINTS=\"[+region=be]\" NULL")) @@ -276,26 +267,6 @@ func (s *testDBSuite6) TestCreateSchemaWithPlacement(c *C) { tk.MustExec("CREATE SCHEMA SchemaPolicyPlacementTest PLACEMENT POLICY = `PolicySchemaTest`") tk.MustQuery("SHOW CREATE SCHEMA SCHEMAPOLICYPLACEMENTTEST").Check(testkit.Rows("SchemaPolicyPlacementTest CREATE DATABASE `SchemaPolicyPlacementTest` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ /*T![placement] PLACEMENT POLICY=`PolicySchemaTest` */")) - tk.MustExec(`CREATE TABLE SchemaDirectPlacementTest.UseSchemaDefault (a int unsigned primary key, b varchar(255))`) - tk.MustQuery(`SHOW CREATE TABLE SchemaDirectPlacementTest.UseSchemaDefault`).Check(testkit.Rows( - "UseSchemaDefault CREATE TABLE `UseSchemaDefault` (\n" + - " `a` int(10) unsigned NOT NULL,\n" + - " `b` varchar(255) DEFAULT NULL,\n" + - " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"nl\" REGIONS=\"se,nz,nl\" FOLLOWERS=3 */")) - tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.schemata WHERE SCHEMA_NAME='SchemaDirectPlacementTest'").Check(testkit.Rows(`def SchemaDirectPlacementTest utf8mb4 utf8mb4_bin PRIMARY_REGION="nl" REGIONS="se,nz,nl" FOLLOWERS=3`)) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaDirectPlacementTest' AND TABLE_NAME = 'UseSchemaDefault'").Check(testkit.Rows(`def SchemaDirectPlacementTest UseSchemaDefault PRIMARY_REGION="nl" REGIONS="se,nz,nl" FOLLOWERS=3`)) - - tk.MustExec(`CREATE TABLE SchemaDirectPlacementTest.UseDirectPlacement (a int unsigned primary key, b varchar(255)) PRIMARY_REGION="se" REGIONS="se"`) - - tk.MustQuery(`SHOW CREATE TABLE SchemaDirectPlacementTest.UseDirectPlacement`).Check(testkit.Rows( - "UseDirectPlacement CREATE TABLE `UseDirectPlacement` (\n" + - " `a` int(10) unsigned NOT NULL,\n" + - " `b` varchar(255) DEFAULT NULL,\n" + - " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" */")) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaDirectPlacementTest' AND TABLE_NAME = 'UseDirectPlacement'").Check(testkit.Rows("def SchemaDirectPlacementTest UseDirectPlacement PRIMARY_REGION=\"se\" REGIONS=\"se\"")) - tk.MustExec(`CREATE TABLE SchemaPolicyPlacementTest.UseSchemaDefault (a int unsigned primary key, b varchar(255))`) tk.MustQuery(`SHOW CREATE TABLE SchemaPolicyPlacementTest.UseSchemaDefault`).Check(testkit.Rows( "UseSchemaDefault CREATE TABLE `UseSchemaDefault` (\n" + @@ -303,8 +274,8 @@ func (s *testDBSuite6) TestCreateSchemaWithPlacement(c *C) { " `b` varchar(255) DEFAULT NULL,\n" + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`PolicySchemaTest` */")) - tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.schemata WHERE SCHEMA_NAME='SchemaPolicyPlacementTest'").Check(testkit.Rows(`def SchemaPolicyPlacementTest utf8mb4 utf8mb4_bin PolicySchemaTest `)) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaPolicyPlacementTest' AND TABLE_NAME = 'UseSchemaDefault'").Check(testkit.Rows(`def SchemaPolicyPlacementTest UseSchemaDefault PolicySchemaTest `)) + tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.schemata WHERE SCHEMA_NAME='SchemaPolicyPlacementTest'").Check(testkit.Rows(`def SchemaPolicyPlacementTest utf8mb4 utf8mb4_bin PolicySchemaTest`)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaPolicyPlacementTest' AND TABLE_NAME = 'UseSchemaDefault'").Check(testkit.Rows(`def SchemaPolicyPlacementTest UseSchemaDefault PolicySchemaTest`)) tk.MustExec(`CREATE TABLE SchemaPolicyPlacementTest.UsePolicy (a int unsigned primary key, b varchar(255)) PLACEMENT POLICY = "PolicyTableTest"`) tk.MustQuery(`SHOW CREATE TABLE SchemaPolicyPlacementTest.UsePolicy`).Check(testkit.Rows( @@ -313,28 +284,19 @@ func (s *testDBSuite6) TestCreateSchemaWithPlacement(c *C) { " `b` varchar(255) DEFAULT NULL,\n" + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`PolicyTableTest` */")) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaPolicyPlacementTest' AND TABLE_NAME = 'UsePolicy'").Check(testkit.Rows(`def SchemaPolicyPlacementTest UsePolicy PolicyTableTest `)) - - is := s.dom.InfoSchema() - - db, ok := is.SchemaByName(model.NewCIStr("SchemaDirectPlacementTest")) - c.Assert(ok, IsTrue) - c.Assert(db.PlacementPolicyRef, IsNil) - c.Assert(db.DirectPlacementOpts, NotNil) - c.Assert(db.DirectPlacementOpts.PrimaryRegion, Matches, "nl") - c.Assert(db.DirectPlacementOpts.Regions, Matches, "se,nz,nl") - c.Assert(db.DirectPlacementOpts.Followers, Equals, uint64(3)) - c.Assert(db.DirectPlacementOpts.Learners, Equals, uint64(0)) - - db, ok = is.SchemaByName(model.NewCIStr("SchemaPolicyPlacementTest")) - c.Assert(ok, IsTrue) - c.Assert(db.PlacementPolicyRef, NotNil) - c.Assert(db.DirectPlacementOpts, IsNil) - c.Assert(db.PlacementPolicyRef.Name.O, Equals, "PolicySchemaTest") + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='SchemaPolicyPlacementTest' AND TABLE_NAME = 'UsePolicy'").Check(testkit.Rows(`def SchemaPolicyPlacementTest UsePolicy PolicyTableTest`)) + + is := dom.InfoSchema() + db, ok := is.SchemaByName(model.NewCIStr("SchemaPolicyPlacementTest")) + require.True(t, ok) + require.NotNil(t, db.PlacementPolicyRef) + require.Equal(t, "PolicySchemaTest", db.PlacementPolicyRef.Name.O) } -func (s *testDBSuite6) TestAlterDBPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterDBPlacement(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists TestAlterDB;") tk.MustExec("create database TestAlterDB;") tk.MustExec("use TestAlterDB") @@ -349,126 +311,495 @@ func (s *testDBSuite6) TestAlterDBPlacement(c *C) { // Policy Test // Test for Non-Exist policy tk.MustGetErrCode("ALTER DATABASE TestAlterDB PLACEMENT POLICY=`alter_z`;", mysql.ErrPlacementPolicyNotExists) - tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.schemata WHERE SCHEMA_NAME='TestAlterDB'").Check(testkit.Rows(`def TestAlterDB utf8mb4 utf8mb4_bin `)) + tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.schemata WHERE SCHEMA_NAME='TestAlterDB'").Check(testkit.Rows(`def TestAlterDB utf8mb4 utf8mb4_bin `)) tk.MustExec("ALTER DATABASE TestAlterDB PLACEMENT POLICY=`alter_x`;") // Test for information_schema.schemata - tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.schemata WHERE SCHEMA_NAME='TestAlterDB'").Check(testkit.Rows(`def TestAlterDB utf8mb4 utf8mb4_bin alter_x `)) + tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.schemata WHERE SCHEMA_NAME='TestAlterDB'").Check(testkit.Rows(`def TestAlterDB utf8mb4 utf8mb4_bin alter_x`)) // Test for Show Create Database - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create database TestAlterDB`).Check(testkit.RowsWithSep("|", "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ "/*T![placement] PLACEMENT POLICY=`alter_x` */", )) // Test for Alter Placement Policy affect table created. tk.MustExec("create table t(a int);") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ "/*T![placement] PLACEMENT POLICY=`alter_x` */", )) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't'").Check(testkit.Rows(`def TestAlterDB t alter_x `)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't'").Check(testkit.Rows(`def TestAlterDB t alter_x`)) // Test for Alter Default Placement Policy, And will not update the old table options. tk.MustExec("ALTER DATABASE TestAlterDB DEFAULT PLACEMENT POLICY=`alter_y`;") tk.MustExec("create table t2(a int);") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ "/*T![placement] PLACEMENT POLICY=`alter_x` */", )) - tk.MustQuery(`show create table t2`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t2`).Check(testkit.RowsWithSep("|", "t2 CREATE TABLE `t2` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ "/*T![placement] PLACEMENT POLICY=`alter_y` */", )) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't2'").Check(testkit.Rows(`def TestAlterDB t2 alter_y `)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't2'").Check(testkit.Rows(`def TestAlterDB t2 alter_y`)) // Reset Test tk.MustExec("drop database if exists TestAlterDB;") - tk.MustExec("create database TestAlterDB;") + tk.MustExec("create database TestAlterDB PLACEMENT POLICY alter_x;") tk.MustExec("use TestAlterDB") - // DirectOption Test - tk.MustExec("ALTER DATABASE TestAlterDB PRIMARY_REGION=\"se\" FOLLOWERS=2 REGIONS=\"se\";") - // Test for information_schema.schemata - tk.MustQuery("SELECT CATALOG_NAME, SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.schemata WHERE SCHEMA_NAME='TestAlterDB'").Check(testkit.Rows(`def TestAlterDB utf8mb4 utf8mb4_bin PRIMARY_REGION="se" REGIONS="se" FOLLOWERS=2`)) - // Test for Show Create Database - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", - "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ - "/*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2 */", - )) // Test for Alter Placement Rule affect table created. tk.MustExec("create table t3(a int);") - tk.MustQuery(`show create table t3`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t3`).Check(testkit.RowsWithSep("|", "t3 CREATE TABLE `t3` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ - "/*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2 */", + "/*T![placement] PLACEMENT POLICY=`alter_x` */", )) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't3'").Check(testkit.Rows("def TestAlterDB t3 PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2")) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't3'").Check(testkit.Rows(`def TestAlterDB t3 alter_x`)) + // Test for override default option - tk.MustExec("create table t4(a int) PLACEMENT POLICY=\"alter_x\";") - tk.MustQuery(`show create table t4`).Check(testutil.RowsWithSep("|", + tk.MustExec("create table t4(a int) PLACEMENT POLICY=\"alter_y\";") + tk.MustQuery(`show create table t4`).Check(testkit.RowsWithSep("|", "t4 CREATE TABLE `t4` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ - "/*T![placement] PLACEMENT POLICY=`alter_x` */", + "/*T![placement] PLACEMENT POLICY=`alter_y` */", )) - tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME, TIDB_DIRECT_PLACEMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't4'").Check(testkit.Rows(`def TestAlterDB t4 alter_x `)) + tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TIDB_PLACEMENT_POLICY_NAME FROM information_schema.Tables WHERE TABLE_SCHEMA='TestAlterDB' AND TABLE_NAME = 't4'").Check(testkit.Rows(`def TestAlterDB t4 alter_y`)) - // Hybrid Test - // Test for alter both policy and direct options. - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", + // Test alter to another policy + tk.MustExec("ALTER DATABASE TestAlterDB PLACEMENT POLICY=`alter_y`;") + tk.MustQuery(`show create database TestAlterDB`).Check(testkit.RowsWithSep("|", "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ - "/*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2 */", - )) - tk.MustGetErrCode("ALTER DATABASE TestAlterDB PLACEMENT POLICY=`alter_x` FOLLOWERS=2;", mysql.ErrPlacementPolicyWithDirectOption) - tk.MustGetErrCode("ALTER DATABASE TestAlterDB DEFAULT PLACEMENT POLICY=`alter_y` PRIMARY_REGION=\"se\" FOLLOWERS=2;", mysql.ErrPlacementPolicyWithDirectOption) - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", - "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ - "/*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2 */", - )) - // Test for change direct options to policy. - tk.MustExec("ALTER DATABASE TestAlterDB PLACEMENT POLICY=`alter_x`;") - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", - "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ - "/*T![placement] PLACEMENT POLICY=`alter_x` */", - )) - // Test for change policy to direct options. - tk.MustExec("ALTER DATABASE TestAlterDB PRIMARY_REGION=\"se\" FOLLOWERS=2 REGIONS=\"se\" ;") - tk.MustQuery(`show create database TestAlterDB`).Check(testutil.RowsWithSep("|", - "TestAlterDB CREATE DATABASE `TestAlterDB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ "+ - "/*T![placement] PRIMARY_REGION=\"se\" REGIONS=\"se\" FOLLOWERS=2 */", + "/*T![placement] PLACEMENT POLICY=`alter_y` */", )) } -func (s *testDBSuite6) TestEnablePlacementCheck(c *C) { - - tk := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set @@global.tidb_enable_alter_placement=1") - c.Assert(err, IsNil) - - tk.MustExec("drop database if exists TestPlacementDB;") - tk.MustExec("create database TestPlacementDB;") - tk.MustExec("use TestPlacementDB;") - tk.MustExec("drop placement policy if exists placement_x;") - tk.MustExec("create placement policy placement_x PRIMARY_REGION=\"cn-east-1\", REGIONS=\"cn-east-1\";") - se.GetSessionVars().EnableAlterPlacement = true - tk.MustExec("create table t(c int) partition by range (c) (partition p1 values less than (200) followers=2);") +func TestPlacementMode(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop database if exists db1") + tk.MustExec("drop database if exists db2") + tk.MustExec("drop table if exists t1,t2,t3,t4") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + + // default should be strict + tk.MustQuery("select @@tidb_placement_mode").Check(testkit.Rows("STRICT")) + + // prepare policy, db and tables + tk.MustExec("create placement policy p1 followers=4") + defer tk.MustExec("drop placement policy if exists p1") + tk.MustExec("create database db1 placement policy p1") + defer tk.MustExec("drop database if exists db1") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("create placement policy p2 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p2") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("create table t1(id int) placement policy p1") + defer tk.MustExec("drop table if exists t1") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("create table t2(id int) PARTITION BY RANGE (id) (" + + "PARTITION p0 VALUES LESS THAN (100) placement policy p1," + + "PARTITION p1 VALUES LESS THAN (1000))") + defer tk.MustExec("drop table if exists t2") + tk.MustQuery("show warnings").Check(testkit.Rows()) + + existPolicy, ok := dom.InfoSchema().PolicyByName(model.NewCIStr("p1")) + require.True(t, ok) + + // invalid values + err := tk.ExecToErr("set tidb_placement_mode='aaa'") + require.EqualError(t, err, "[variable:1231]Variable 'tidb_placement_mode' can't be set to the value of 'aaa'") + + // ignore mode + tk.MustExec("set tidb_placement_mode='ignore'") + tk.MustQuery("select @@tidb_placement_mode").Check(testkit.Rows("IGNORE")) + + // create placement policy in ignore mode (policy name exists) + tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p1'").Check(testkit.Rows("POLICY p1 FOLLOWERS=4 NULL")) + + // create placement policy in ignore mode (policy name not exists) + tk.MustExec("create placement policy p3 primary_region='r1' regions='r1'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p3'").Check(testkit.Rows()) + + // create placement policy with info in ignore mode (policy name exists) + newPolicy := existPolicy.Clone() + newPolicy.Followers = 8 + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p1'").Check(testkit.Rows("POLICY p1 FOLLOWERS=4 NULL")) + + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy.Clone(), ddl.OnExistReplace) + require.NoError(t, err) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p1'").Check(testkit.Rows("POLICY p1 FOLLOWERS=4 NULL")) + + // create placement policy in ignore mode (policy name not exists) + newPolicy = existPolicy.Clone() + newPolicy.Name = model.NewCIStr("p3") + newPolicy.Followers = 8 + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreatePlacementPolicyWithInfo(tk.Session(), newPolicy, ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p3'").Check(testkit.Rows()) + + // alter placement policy in ignore mode (policy exists) + tk.MustExec("alter placement policy p1 primary_region='r1' regions='r1'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p1'").Check(testkit.Rows("POLICY p1 FOLLOWERS=4 NULL")) + + // alter placement policy in ignore mode (policy not exists) + tk.MustExec("alter placement policy p3 primary_region='r1' regions='r1'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p3'").Check(testkit.Rows()) + + // drop placement policy in ignore mode (policy exists) + tk.MustExec("drop placement policy p1") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p1'").Check(testkit.Rows("POLICY p1 FOLLOWERS=4 NULL")) + + // drop placement policy in ignore mode (policy not exists) + tk.MustExec("drop placement policy p3") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show placement where target='POLICY p3'").Check(testkit.Rows()) + + // create database in ignore mode (ref exist policy) + tk.MustExec("create database db2 placement policy p1") + defer tk.MustExec("drop database if exists db2") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + tk.MustExec("drop database db2") + + // create database in ignore mode (ref non exist policy) + tk.MustExec("create database db2 placement policy pxxx") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + + // alter database in ignore mode (policy exists) + tk.MustExec("alter database db2 placement policy p1") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + + // alter database in ignore mode (policy not exists) + tk.MustExec("alter database db2 placement policy px") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + + // alter database in ignore mode (other alter should succeed) + tk.MustExec("alter database db2 placement policy px DEFAULT CHARACTER SET 'ascii'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET ascii */")) + + // create table in ignore mode (ref exist policy) + tk.MustExec("create table t3(id int) placement policy p1") + defer tk.MustExec("drop table if exists t3") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t3").Check(testkit.Rows("t3 CREATE TABLE `t3` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // create table like in ignore mode + tk.MustExec("drop table if exists t3") + tk.MustExec("create table t3 like t1") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t3").Check(testkit.Rows("t3 CREATE TABLE `t3` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // create table in ignore mode (db has placement) + tk.MustExec("create table db1.t1(id int)") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table db1.t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // create partitioned table in ignore mode (ref exist policy) + tk.MustExec("CREATE TABLE t4 (id INT) PLACEMENT POLICY p1 PARTITION BY RANGE (id) (" + + "PARTITION p0 VALUES LESS THAN (100) PLACEMENT POLICY p3," + + "PARTITION p1 VALUES LESS THAN (1000) PLACEMENT POLICY p1," + + "PARTITION p2 VALUES LESS THAN (10000)," + + "PARTITION p3 VALUES LESS THAN (100000) PLACEMENT POLICY p2)") + defer tk.MustExec("drop table if exists t4") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t4").Check(testkit.Rows("t4 CREATE TABLE `t4` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000),\n" + + " PARTITION `p3` VALUES LESS THAN (100000))")) + + // create partitioned table in ignore mode (ref non exist policy) + tk.MustExec("drop table t4") + tk.MustExec("CREATE TABLE t4 (id INT) PLACEMENT POLICY pxxx PARTITION BY RANGE (id) (" + + "PARTITION p0 VALUES LESS THAN (100) PLACEMENT POLICY pyyy," + + "PARTITION p1 VALUES LESS THAN (1000) PLACEMENT POLICY pzzz," + + "PARTITION p2 VALUES LESS THAN (10000)," + + "PARTITION p3 VALUES LESS THAN (100000) PLACEMENT POLICY pttt)") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t4").Check(testkit.Rows("t4 CREATE TABLE `t4` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000),\n" + + " PARTITION `p3` VALUES LESS THAN (100000))")) + + // alter table placement in ignore mode (policy exists) + tk.MustExec("alter table t1 placement policy p2") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) + + // alter table placement in ignore mode (policy not exists) + tk.MustExec("alter table t1 placement policy p3") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */")) + + // alter table in ignore mode (other alter should succeed) + tk.MustExec("alter table t1 placement policy p2 comment='aaa'") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='aaa' /*T![placement] PLACEMENT POLICY=`p1` */")) + + // add partition in ignore mode (policy exists) + tk.MustExec("alter table t2 add partition (partition p2 values less than(10000) placement policy p1)") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000))")) + + // add partition in ignore mode (policy not exists) + tk.MustExec("alter table t2 add partition (partition p3 values less than(100000) placement policy p3)") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000),\n" + + " PARTITION `p3` VALUES LESS THAN (100000))")) + + // alter partition placement in ignore mode (policy exists) + tk.MustExec("alter table t2 partition p0 placement policy p1") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000),\n" + + " PARTITION `p3` VALUES LESS THAN (100000))")) + + // alter partition placement in ignore mode (policy not exists) + tk.MustExec("alter table t2 partition p0 placement policy p3") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Placement is ignored when TIDB_PLACEMENT_MODE is 'IGNORE'")) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000),\n" + + " PARTITION `p2` VALUES LESS THAN (10000),\n" + + " PARTITION `p3` VALUES LESS THAN (100000))")) + + // create tableWithInfo in ignore mode + tk.MustExec("drop table if exists t2") + tbl, err := getClonedTableFromDomain("test", "t1", dom) + require.NoError(t, err) + require.NotNil(t, tbl.PlacementPolicyRef) + tbl.Name = model.NewCIStr("t2") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreateTableWithInfo(tk.Session(), model.NewCIStr("test"), tbl, ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='aaa'")) + + // createTableWithInfo in ignore mode (policy not exists) + tk.MustExec("drop table if exists t2") + tbl, err = getClonedTableFromDomain("test", "t1", dom) + require.NoError(t, err) + require.NotNil(t, tbl.PlacementPolicyRef) + tbl.Name = model.NewCIStr("t2") + tbl.PlacementPolicyRef.Name = model.NewCIStr("pxx") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreateTableWithInfo(tk.Session(), model.NewCIStr("test"), tbl, ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show create table t2").Check(testkit.Rows("t2 CREATE TABLE `t2` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='aaa'")) + + // createSchemaWithInfo in ignore mode + tk.MustExec("drop database if exists db2") + db1, ok := getClonedDatabaseFromDomain("db1", dom) + require.True(t, ok) + require.NotNil(t, db1.PlacementPolicyRef) + db1.Name = model.NewCIStr("db2") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreateSchemaWithInfo(tk.Session(), db1, ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + + // createSchemaWithInfo in ignore mode (policy not exists) + tk.MustExec("drop database if exists db2") + db1, ok = getClonedDatabaseFromDomain("db1", dom) + require.True(t, ok) + require.NotNil(t, db1.PlacementPolicyRef) + db1.Name = model.NewCIStr("db2") + db1.PlacementPolicyRef.Name = model.NewCIStr("pxx") + tk.Session().SetValue(sessionctx.QueryString, "skip") + err = dom.DDL().CreateSchemaWithInfo(tk.Session(), db1, ddl.OnExistError) + require.NoError(t, err) + tk.MustQuery("show create database db2").Check(testkit.Rows("db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) + +} + +func TestPlacementTiflashCheck(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) defer func() { - tk.MustExec("drop database if exists TestPlacementDB;") - tk.MustExec("drop placement policy if exists placement_x;") + err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") + require.NoError(t, err) }() - tk.Se.GetSessionVars().EnableAlterPlacement = false - tk.MustGetErrCode("create database TestPlacementDB2 followers=2;", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter database TestPlacementDB placement policy=placement_x", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("create table t (c int) FOLLOWERS=2;", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t voters=2;", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("create table m (c int) partition by range (c) (partition p1 values less than (200) followers=2);", mysql.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t partition p1 placement policy=\"placement_x\";", mysql.ErrUnsupportedDDLOperation) + tk.MustExec("use test") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop table if exists tp") + + tk.MustExec("create placement policy p1 primary_region='r1' regions='r1'") + defer tk.MustExec("drop placement policy if exists p1") + + tk.MustExec(`CREATE TABLE tp (id INT) PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100), + PARTITION p1 VALUES LESS THAN (1000) + )`) + defer tk.MustExec("drop table if exists tp") + tk.MustExec("alter table tp set tiflash replica 1") + + err := tk.ExecToErr("alter table tp placement policy p1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + err = tk.ExecToErr("alter table tp partition p0 placement policy p1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + tk.MustQuery("show create table tp").Check(testkit.Rows("" + + "tp CREATE TABLE `tp` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + + " PARTITION `p1` VALUES LESS THAN (1000))")) + + tk.MustExec("drop table tp") + tk.MustExec(`CREATE TABLE tp (id INT) placement policy p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100), + PARTITION p1 VALUES LESS THAN (1000) + )`) + err = tk.ExecToErr("alter table tp set tiflash replica 1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + tk.MustQuery("show create table tp").Check(testkit.Rows("" + + "tp CREATE TABLE `tp` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + + " PARTITION `p1` VALUES LESS THAN (1000))")) + + tk.MustExec("drop table tp") + tk.MustExec(`CREATE TABLE tp (id INT) PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) placement policy p1 , + PARTITION p1 VALUES LESS THAN (1000) + )`) + err = tk.ExecToErr("alter table tp set tiflash replica 1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + tk.MustQuery("show create table tp").Check(testkit.Rows("" + + "tp CREATE TABLE `tp` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000))")) + + tk.MustExec("drop table tp") + tk.MustExec(`CREATE TABLE tp (id INT) PLACEMENT POLICY p1 PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100), + PARTITION p1 VALUES LESS THAN (1000) + )`) + err = tk.ExecToErr("alter table tp set tiflash replica 1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + tk.MustQuery("show create table tp").Check(testkit.Rows("" + + "tp CREATE TABLE `tp` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p1` */\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100),\n" + + " PARTITION `p1` VALUES LESS THAN (1000))")) + + tk.MustExec("drop table tp") + tk.MustExec(`CREATE TABLE tp (id INT) PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (100) PLACEMENT POLICY p1, + PARTITION p1 VALUES LESS THAN (1000) + )`) + err = tk.ExecToErr("alter table tp set tiflash replica 1") + require.True(t, dbterror.ErrIncompatibleTiFlashAndPlacement.Equal(err)) + tk.MustQuery("show create table tp").Check(testkit.Rows("" + + "tp CREATE TABLE `tp` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" + + "PARTITION BY RANGE (`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (100) /*T![placement] PLACEMENT POLICY=`p1` */,\n" + + " PARTITION `p1` VALUES LESS THAN (1000))")) +} + +func getClonedTableFromDomain(dbName string, tableName string, dom *domain.Domain) (*model.TableInfo, error) { + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(dbName), model.NewCIStr(tableName)) + if err != nil { + return nil, err + } + + tblMeta := tbl.Meta() + tblMeta = tblMeta.Clone() + policyRef := *tblMeta.PlacementPolicyRef + tblMeta.PlacementPolicyRef = &policyRef + return tblMeta, nil +} + +func getClonedDatabaseFromDomain(dbName string, dom *domain.Domain) (*model.DBInfo, bool) { + db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr(dbName)) + if !ok { + return nil, ok + } + + db = db.Clone() + policyRef := *db.PlacementPolicyRef + db.PlacementPolicyRef = &policyRef + return db, true } diff --git a/ddl/primary_key_handle_test.go b/ddl/primary_key_handle_test.go new file mode 100644 index 0000000000000..ee9c318d6a2a2 --- /dev/null +++ b/ddl/primary_key_handle_test.go @@ -0,0 +1,616 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "fmt" + "math" + "strconv" + "strings" + "testing" + + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/testutils" +) + +func getTableMaxHandle(t *testing.T, d ddl.DDL, tbl table.Table, store kv.Storage) (kv.Handle, bool) { + ver, err := store.CurrentVersion(kv.GlobalTxnScope) + require.NoError(t, err) + maxHandle, emptyTable, err := d.GetTableMaxHandle(ddl.NewJobContext(), ver.Ver, tbl.(table.PhysicalTable)) + require.NoError(t, err) + return maxHandle, emptyTable +} + +func checkTableMaxHandle(t *testing.T, d ddl.DDL, tbl table.Table, store kv.Storage, expectedEmpty bool, expectedMaxHandle kv.Handle) { + maxHandle, emptyHandle := getTableMaxHandle(t, d, tbl, store) + require.Equal(t, expectedEmpty, emptyHandle) + if expectedEmpty { + require.True(t, emptyHandle) + require.Nil(t, maxHandle) + } else { + require.False(t, emptyHandle) + testutil.HandleEqual(t, expectedMaxHandle, maxHandle) + } +} + +func TestPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + + // Test add/drop primary key on a plain table. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b varchar(10));") + tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustExec("alter table t add primary key(a) nonclustered;") + tk.MustExec("alter table t drop primary key;") + tk.MustExec("alter table t add primary key(a) nonclustered;") + tk.MustExec("drop index `primary` on t;") + tk.MustExec("alter table t add primary key(a);") // implicit nonclustered + tk.MustExec("drop index `primary` on t;") + tk.MustGetErrCode("drop index `primary` on t;", errno.ErrCantDropFieldOrKey) + + // Test add/drop primary key on a PKIsHandle table. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b varchar(10), primary key(a) clustered);") + tk.MustGetErrCode("alter table t drop primary key;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", mysql.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered + tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered + + // Test add/drop primary key on a nonclustered primary key table. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b varchar(10), primary key(a) nonclustered);") + tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", errno.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered + tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered + tk.MustExec("alter table t drop primary key;") + + // Test add/drop primary key on a CommonHandle key table. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b varchar(10), primary key(b) clustered);") + tk.MustGetErrCode("alter table t drop primary key;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", errno.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered + tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) + tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered + + // Test add/drop primary key when the column&index name is `primary`. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (`primary` int);") + tk.MustExec("alter table t add index (`primary`);") + tk.MustGetErrCode("drop index `primary` on t;", errno.ErrCantDropFieldOrKey) + + // The primary key cannot be invisible, for the case pk_is_handle. + tk.MustExec("drop table if exists t;") + tk.MustGetErrCode("create table t(c1 int not null, primary key(c1) invisible);", errno.ErrPKIndexCantBeInvisible) + tk.MustExec("create table t (a int, b int not null, primary key(a), unique(b) invisible);") + tk.MustExec("drop table t;") +} + +func TestMultiRegionGetTableEndHandle(t *testing.T) { + var cluster testutils.Cluster + store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + })) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a bigint PRIMARY KEY, b int)") + var builder strings.Builder + _, _ = fmt.Fprintf(&builder, "insert into t values ") + for i := 0; i < 1000; i++ { + _, _ = fmt.Fprintf(&builder, "(%v, %v),", i, i) + } + sql := builder.String() + tk.MustExec(sql[:len(sql)-1]) + + // Get table ID for split. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + d := dom.DDL() + + // Split the table. + tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) + cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(999)) + + tk.MustExec("insert into t values(10000, 1000)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(10000)) + + tk.MustExec("insert into t values(-1, 1000)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(10000)) +} + +func TestGetTableEndHandle(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + // TestGetTableEndHandle test ddl.GetTableMaxHandle method, which will return the max row id of the table. + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // PK is handle. + tk.MustExec("create table t(a bigint PRIMARY KEY, b int)") + + is := dom.InfoSchema() + d := dom.DDL() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + // test empty table + checkTableMaxHandle(t, d, tbl, store, true, nil) + + tk.MustExec("insert into t values(-1, 1)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(-1)) + + tk.MustExec("insert into t values(9223372036854775806, 1)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(9223372036854775806)) + + tk.MustExec("insert into t values(9223372036854775807, 1)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(9223372036854775807)) + + tk.MustExec("insert into t values(10, 1)") + tk.MustExec("insert into t values(102149142, 1)") + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(9223372036854775807)) + + tk.MustExec("create table t1(a bigint PRIMARY KEY, b int)") + + var builder strings.Builder + _, _ = fmt.Fprintf(&builder, "insert into t1 values ") + for i := 0; i < 1000; i++ { + _, _ = fmt.Fprintf(&builder, "(%v, %v),", i, i) + } + sql := builder.String() + tk.MustExec(sql[:len(sql)-1]) + + is = dom.InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + checkTableMaxHandle(t, d, tbl, store, false, kv.IntHandle(999)) + + // Test PK is not handle + tk.MustExec("create table t2(a varchar(255))") + + is = dom.InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + checkTableMaxHandle(t, d, tbl, store, true, nil) + + builder.Reset() + _, _ = fmt.Fprintf(&builder, "insert into t2 values ") + for i := 0; i < 1000; i++ { + _, _ = fmt.Fprintf(&builder, "(%v),", i) + } + sql = builder.String() + tk.MustExec(sql[:len(sql)-1]) + + result := tk.MustQuery("select MAX(_tidb_rowid) from t2") + maxHandle, emptyTable := getTableMaxHandle(t, d, tbl, store) + result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) + require.False(t, emptyTable) + + tk.MustExec("insert into t2 values(100000)") + result = tk.MustQuery("select MAX(_tidb_rowid) from t2") + maxHandle, emptyTable = getTableMaxHandle(t, d, tbl, store) + result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) + require.False(t, emptyTable) + + tk.MustExec(fmt.Sprintf("insert into t2 values(%v)", math.MaxInt64-1)) + result = tk.MustQuery("select MAX(_tidb_rowid) from t2") + maxHandle, emptyTable = getTableMaxHandle(t, d, tbl, store) + result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) + require.False(t, emptyTable) + + tk.MustExec(fmt.Sprintf("insert into t2 values(%v)", math.MaxInt64)) + result = tk.MustQuery("select MAX(_tidb_rowid) from t2") + maxHandle, emptyTable = getTableMaxHandle(t, d, tbl, store) + result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) + require.False(t, emptyTable) + + tk.MustExec("insert into t2 values(100)") + result = tk.MustQuery("select MAX(_tidb_rowid) from t2") + maxHandle, emptyTable = getTableMaxHandle(t, d, tbl, store) + result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) + require.False(t, emptyTable) +} + +func TestMultiRegionGetTableEndCommonHandle(t *testing.T) { + var cluster testutils.Cluster + store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + })) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + + tk.MustExec("create table t(a varchar(20), b int, c float, d bigint, primary key (a, b, c))") + var builder strings.Builder + _, _ = fmt.Fprintf(&builder, "insert into t values ") + for i := 0; i < 1000; i++ { + _, _ = fmt.Fprintf(&builder, "('%v', %v, %v, %v),", i, i, i, i) + } + sql := builder.String() + tk.MustExec(sql[:len(sql)-1]) + + // Get table ID for split. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + d := dom.DDL() + + // Split the table. + tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) + cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "999", 999, 999)) + + tk.MustExec("insert into t values('a', 1, 1, 1)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "a", 1, 1)) + + tk.MustExec("insert into t values('0000', 1, 1, 1)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "a", 1, 1)) +} + +func TestGetTableEndCommonHandle(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + + tk.MustExec("create table t(a varchar(15), b bigint, c int, primary key (a, b))") + tk.MustExec("create table t1(a varchar(15), b bigint, c int, primary key (a(2), b))") + + is := dom.InfoSchema() + d := dom.DDL() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + // test empty table + checkTableMaxHandle(t, d, tbl, store, true, nil) + + tk.MustExec("insert into t values('abc', 1, 10)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "abc", 1)) + + tk.MustExec("insert into t values('abchzzzzzzzz', 1, 10)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "abchzzzzzzzz", 1)) + tk.MustExec("insert into t values('a', 1, 10)") + tk.MustExec("insert into t values('ab', 1, 10)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "abchzzzzzzzz", 1)) + + // Test MaxTableRowID with prefixed primary key. + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + d = dom.DDL() + checkTableMaxHandle(t, d, tbl, store, true, nil) + tk.MustExec("insert into t1 values('abccccc', 1, 10)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "ab", 1)) + tk.MustExec("insert into t1 values('azzzz', 1, 10)") + checkTableMaxHandle(t, d, tbl, store, false, testutil.MustNewCommonHandle(t, "az", 1)) +} + +func TestAutoRandomChangeFromAutoInc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set @@tidb_allow_remove_auto_inc = 1;") + + // Basic usages. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_increment primary key);") + tk.MustExec("insert into t values (), (), ();") + tk.MustExec("alter table t modify column a bigint auto_random(3);") + tk.MustExec("insert into t values (), (), ();") + rows := tk.MustQuery("show table t next_row_id;").Rows() + require.Len(t, rows, 1, fmt.Sprintf("query result: %v", rows)) + require.Len(t, rows[0], 5, fmt.Sprintf("query result: %v", rows)) + require.Equal(t, "AUTO_RANDOM", rows[0][4]) + + // Changing from auto_inc unique key is not allowed. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_increment unique key);") + tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_increment unique key, b bigint auto_random primary key);") + tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) + + // Changing from non-auto-inc column is not allowed. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint);") + tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint primary key);") + tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) + + // Changing from non BIGINT auto_inc pk column is not allowed. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int auto_increment primary key);") + tk.MustGetErrCode("alter table t modify column a int auto_random;", errno.ErrInvalidAutoRandom) + tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) + + // Changing from auto_random to auto_increment is not allowed. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_random primary key);") + // "Unsupported modify column: can't set auto_increment" + tk.MustGetErrCode("alter table t modify column a bigint auto_increment;", errno.ErrUnsupportedDDLOperation) + + // Large auto_increment number overflows auto_random. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_increment primary key);") + tk.MustExec("insert into t values (1<<(64-5));") + // "max allowed auto_random shard bits is 3, but got 4 on column `a`" + tk.MustGetErrCode("alter table t modify column a bigint auto_random(4);", errno.ErrInvalidAutoRandom) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a bigint auto_increment primary key);") + tk.MustExec("insert into t values (1<<(64-6));") + tk.MustExec("alter table t modify column a bigint auto_random(4);") +} + +func TestAutoRandomExchangePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists auto_random_db") + defer tk.MustExec("drop database if exists auto_random_db") + + tk.MustExec("use auto_random_db") + + tk.MustExec("set @@tidb_enable_exchange_partition=1") + defer tk.MustExec("set @@tidb_enable_exchange_partition=0") + + tk.MustExec("drop table if exists e1, e2, e3, e4;") + + tk.MustExec("create table e1 (a bigint primary key clustered auto_random(3)) partition by hash(a) partitions 1;") + + tk.MustExec("create table e2 (a bigint primary key);") + tk.MustGetErrCode("alter table e1 exchange partition p0 with table e2;", errno.ErrTablesDifferentMetadata) + + tk.MustExec("create table e3 (a bigint primary key auto_random(2));") + tk.MustGetErrCode("alter table e1 exchange partition p0 with table e3;", errno.ErrTablesDifferentMetadata) + tk.MustExec("insert into e1 values (), (), ()") + + tk.MustExec("create table e4 (a bigint primary key auto_random(3));") + tk.MustExec("insert into e4 values ()") + tk.MustExec("alter table e1 exchange partition p0 with table e4;") + + tk.MustQuery("select count(*) from e1").Check(testkit.Rows("1")) + tk.MustExec("insert into e1 values ()") + tk.MustQuery("select count(*) from e1").Check(testkit.Rows("2")) + + tk.MustQuery("select count(*) from e4").Check(testkit.Rows("3")) + tk.MustExec("insert into e4 values ()") + tk.MustQuery("select count(*) from e4").Check(testkit.Rows("4")) +} + +func TestAutoRandomIncBitsIncrementAndOffset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists auto_random_db") + defer tk.MustExec("drop database if exists auto_random_db") + tk.MustExec("use auto_random_db") + tk.MustExec("drop table if exists t") + + recreateTable := func() { + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a bigint auto_random(6) primary key clustered)") + } + truncateTable := func() { + _, _ = tk.Exec("delete from t") + } + insertTable := func() { + tk.MustExec("insert into t values ()") + } + assertIncBitsValues := func(values ...int) { + mask := strings.Repeat("1", 64-1-6) + sql := fmt.Sprintf(`select a & b'%s' from t order by a & b'%s' asc`, mask, mask) + vs := make([]string, len(values)) + for i, value := range values { + vs[i] = strconv.Itoa(value) + } + tk.MustQuery(sql).Check(testkit.Rows(vs...)) + } + + const truncate, recreate = true, false + expect := func(vs ...int) []int { return vs } + testCase := []struct { + setupAction bool // truncate or recreate + increment int // @@auto_increment_increment + offset int // @@auto_increment_offset + results []int // the implicit allocated auto_random incremental-bit part of values + }{ + {recreate, 5, 10, expect(10, 15, 20)}, + {recreate, 2, 10, expect(10, 12, 14)}, + {truncate, 5, 10, expect(15, 20, 25)}, + {truncate, 10, 10, expect(30, 40, 50)}, + {truncate, 5, 10, expect(55, 60, 65)}, + } + for _, tc := range testCase { + switch tc.setupAction { + case recreate: + recreateTable() + case truncate: + truncateTable() + } + tk.Session().GetSessionVars().AutoIncrementIncrement = tc.increment + tk.Session().GetSessionVars().AutoIncrementOffset = tc.offset + for range tc.results { + insertTable() + } + assertIncBitsValues(tc.results...) + } +} + +func TestInvisibleIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t,t1,t2,t3,t4,t5,t6") + + // The DDL statement related to invisible index. + showIndexes := "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't'" + // 1. Create table with invisible index + tk.MustExec("create table t (a int, b int, unique (a) invisible)") + tk.MustQuery(showIndexes).Check(testkit.Rows("a NO")) + tk.MustExec("insert into t values (1, 2)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2")) + // 2. Drop invisible index + tk.MustExec("alter table t drop index a") + tk.MustQuery(showIndexes).Check(testkit.Rows()) + tk.MustExec("insert into t values (3, 4)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4")) + // 3. Add an invisible index + tk.MustExec("alter table t add index (b) invisible") + tk.MustQuery(showIndexes).Check(testkit.Rows("b NO")) + tk.MustExec("insert into t values (5, 6)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6")) + // 4. Drop it + tk.MustExec("alter table t drop index b") + tk.MustQuery(showIndexes).Check(testkit.Rows()) + tk.MustExec("insert into t values (7, 8)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8")) + // 5. Create a multiple-column invisible index + tk.MustExec("alter table t add index a_b(a, b) invisible") + tk.MustQuery(showIndexes).Check(testkit.Rows("a_b NO", "a_b NO")) + tk.MustExec("insert into t values (9, 10)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8", "9 10")) + // 6. Drop it + tk.MustExec("alter table t drop index a_b") + tk.MustQuery(showIndexes).Check(testkit.Rows()) + tk.MustExec("insert into t values (11, 12)") + tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8", "9 10", "11 12")) + + // Limitation: Primary key cannot be invisible index + tk.MustGetErrCode("create table t1 (a int, primary key (a) nonclustered invisible)", errno.ErrPKIndexCantBeInvisible) + tk.MustGetErrCode("create table t1 (a int, b int, primary key (a, b) nonclustered invisible)", errno.ErrPKIndexCantBeInvisible) + tk.MustExec("create table t1 (a int, b int)") + tk.MustGetErrCode("alter table t1 add primary key(a) nonclustered invisible", errno.ErrPKIndexCantBeInvisible) + tk.MustGetErrCode("alter table t1 add primary key(a, b) nonclustered invisible", errno.ErrPKIndexCantBeInvisible) + + // Implicit primary key cannot be invisible index + // Create a implicit primary key + tk.MustGetErrCode("create table t2(a int not null, unique (a) invisible)", errno.ErrPKIndexCantBeInvisible) + tk.MustGetErrCode("create table t2(a int auto_increment, unique key (a) invisible);", errno.ErrPKIndexCantBeInvisible) + // Column `a` become implicit primary key after DDL statement on itself + tk.MustExec("create table t2(a int not null)") + tk.MustGetErrCode("alter table t2 add unique (a) invisible", errno.ErrPKIndexCantBeInvisible) + tk.MustExec("create table t3(a int, unique index (a) invisible)") + tk.MustGetErrCode("alter table t3 modify column a int not null", errno.ErrPKIndexCantBeInvisible) + // Only first unique column can be implicit primary + tk.MustExec("create table t4(a int not null, b int not null, unique (a), unique (b) invisible)") + showIndexes = "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't4'" + tk.MustQuery(showIndexes).Check(testkit.Rows("a YES", "b NO")) + tk.MustExec("insert into t4 values (1, 2)") + tk.MustQuery("select * from t4").Check(testkit.Rows("1 2")) + tk.MustGetErrCode("create table t5(a int not null, b int not null, unique (b) invisible, unique (a))", errno.ErrPKIndexCantBeInvisible) + // Column `b` become implicit primary key after DDL statement on other columns + tk.MustExec("create table t5(a int not null, b int not null, unique (a), unique (b) invisible)") + tk.MustGetErrCode("alter table t5 drop index a", errno.ErrPKIndexCantBeInvisible) + tk.MustGetErrCode("alter table t5 modify column a int null", errno.ErrPKIndexCantBeInvisible) + // If these is a explicit primary key, no key will become implicit primary key + tk.MustExec("create table t6 (a int not null, b int, unique (a) invisible, primary key(b) nonclustered)") + showIndexes = "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't6'" + tk.MustQuery(showIndexes).Check(testkit.Rows("a NO", "PRIMARY YES")) + tk.MustExec("insert into t6 values (1, 2)") + tk.MustQuery("select * from t6").Check(testkit.Rows("1 2")) + tk.MustGetErrCode("alter table t6 drop primary key", errno.ErrPKIndexCantBeInvisible) + res := tk.MustQuery("show index from t6 where Key_name='PRIMARY';") + require.Len(t, res.Rows(), 1) +} + +func TestCreateClusteredIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("CREATE TABLE t1 (a int primary key, b int)") + tk.MustExec("CREATE TABLE t2 (a varchar(255) primary key, b int)") + tk.MustExec("CREATE TABLE t3 (a int, b int, c int, primary key (a, b))") + tk.MustExec("CREATE TABLE t4 (a int, b int, c int)") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + require.True(t, tbl.Meta().PKIsHandle) + require.False(t, tbl.Meta().IsCommonHandle) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + require.True(t, tbl.Meta().IsCommonHandle) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) + require.NoError(t, err) + require.True(t, tbl.Meta().IsCommonHandle) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t4")) + require.NoError(t, err) + require.False(t, tbl.Meta().IsCommonHandle) + + tk.MustExec("CREATE TABLE t5 (a varchar(255) primary key nonclustered, b int)") + tk.MustExec("CREATE TABLE t6 (a int, b int, c int, primary key (a, b) nonclustered)") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t5")) + require.NoError(t, err) + require.False(t, tbl.Meta().IsCommonHandle) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t6")) + require.NoError(t, err) + require.False(t, tbl.Meta().IsCommonHandle) + + tk.MustExec("CREATE TABLE t21 like t2") + tk.MustExec("CREATE TABLE t31 like t3") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t21")) + require.NoError(t, err) + require.True(t, tbl.Meta().IsCommonHandle) + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t31")) + require.NoError(t, err) + require.True(t, tbl.Meta().IsCommonHandle) + + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.MustExec("CREATE TABLE t7 (a varchar(255) primary key, b int)") + is = domain.GetDomain(tk.Session()).InfoSchema() + tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t7")) + require.NoError(t, err) + require.False(t, tbl.Meta().IsCommonHandle) +} diff --git a/ddl/reorg.go b/ddl/reorg.go index d1a8f5b0b4b59..7c3445f375d37 100644 --- a/ddl/reorg.go +++ b/ddl/reorg.go @@ -40,6 +40,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tidb/util/ranger" @@ -89,7 +90,10 @@ func newContext(store kv.Storage) sessionctx.Context { c := mock.NewContext() c.Store = store c.GetSessionVars().SetStatusFlag(mysql.ServerStatusAutocommit, false) - c.GetSessionVars().StmtCtx.TimeZone = time.UTC + + tz := *time.UTC + c.GetSessionVars().TimeZone = &tz + c.GetSessionVars().StmtCtx.TimeZone = &tz return c } @@ -199,7 +203,7 @@ func (w *worker) runReorgJob(t *meta.Meta, reorgInfo *reorgInfo, tblInfo *model. SQLMode: mysql.ModeNone, Warnings: make(map[errors.ErrorID]*terror.Error), WarningsCount: make(map[errors.ErrorID]int64), - Location: time.Local, + Location: &model.TimeZoneLocation{Name: time.UTC.String(), Offset: 0}, } } if w.reorgCtx.doneCh == nil { @@ -265,8 +269,8 @@ func (w *worker) runReorgJob(t *meta.Meta, reorgInfo *reorgInfo, tblInfo *model. w.reorgCtx.setNextKey(nil) w.reorgCtx.setRowCount(0) w.reorgCtx.resetWarnings() - // We return errWaitReorgTimeout here too, so that outer loop will break. - return errWaitReorgTimeout + // We return dbterror.ErrWaitReorgTimeout here too, so that outer loop will break. + return dbterror.ErrWaitReorgTimeout case <-time.After(waitTimeout): rowCount, doneKey, currentElement := w.reorgCtx.getRowCountAndKey() // Update a job's RowCount. @@ -291,7 +295,7 @@ func (w *worker) runReorgJob(t *meta.Meta, reorgInfo *reorgInfo, tblInfo *model. zap.String("doneKey", tryDecodeToHandleString(doneKey)), zap.Error(err)) // If timeout, we will return, check the owner and retry to wait job done again. - return errWaitReorgTimeout + return dbterror.ErrWaitReorgTimeout } return nil } @@ -341,11 +345,7 @@ func getTableTotalCount(w *worker, tblInfo *model.TableInfo) int64 { return statistics.PseudoRowCount } sql := "select table_rows from information_schema.tables where tidb_table_id=%?;" - stmt, err := executor.ParseWithParams(w.ddlJobCtx, sql, tblInfo.ID) - if err != nil { - return statistics.PseudoRowCount - } - rows, _, err := executor.ExecRestrictedStmt(w.ddlJobCtx, stmt) + rows, _, err := executor.ExecRestrictedSQL(w.ddlJobCtx, nil, sql, tblInfo.ID) if err != nil { return statistics.PseudoRowCount } @@ -358,18 +358,18 @@ func getTableTotalCount(w *worker, tblInfo *model.TableInfo) int64 { func (w *worker) isReorgRunnable(d *ddlCtx) error { if isChanClosed(w.ctx.Done()) { // Worker is closed. So it can't do the reorganizational job. - return errInvalidWorker.GenWithStack("worker is closed") + return dbterror.ErrInvalidWorker.GenWithStack("worker is closed") } if w.reorgCtx.isReorgCanceled() { // Job is cancelled. So it can't be done. - return errCancelledDDLJob + return dbterror.ErrCancelledDDLJob } if !d.isOwner() { // If it's not the owner, we will try later, so here just returns an error. logutil.BgLogger().Info("[ddl] DDL worker is not the DDL owner", zap.String("ID", d.uuid)) - return errors.Trace(errNotOwner) + return errors.Trace(dbterror.ErrNotOwner) } return nil } @@ -438,7 +438,7 @@ func getColumnsTypes(columns []*model.ColumnInfo) []*types.FieldType { } // buildDescTableScan builds a desc table scan upon tblInfo. -func (dc *ddlCtx) buildDescTableScan(ctx context.Context, startTS uint64, tbl table.PhysicalTable, +func (dc *ddlCtx) buildDescTableScan(ctx *JobContext, startTS uint64, tbl table.PhysicalTable, handleCols []*model.ColumnInfo, limit uint64) (distsql.SelectResult, error) { sctx := newContext(dc.store) dagPB, err := buildDescTableScanDAG(sctx, tbl, handleCols, limit) @@ -459,6 +459,7 @@ func (dc *ddlCtx) buildDescTableScan(ctx context.Context, startTS uint64, tbl ta SetKeepOrder(true). SetConcurrency(1).SetDesc(true) + builder.Request.ResourceGroupTagger = ctx.getResourceGroupTaggerForTopSQL() builder.Request.NotFillCache = true builder.Request.Priority = kv.PriorityLow @@ -467,7 +468,7 @@ func (dc *ddlCtx) buildDescTableScan(ctx context.Context, startTS uint64, tbl ta return nil, errors.Trace(err) } - result, err := distsql.Select(ctx, sctx, kvReq, getColumnsTypes(handleCols), statistics.NewQueryFeedback(0, nil, 0, false)) + result, err := distsql.Select(ctx.ddlJobCtx, sctx, kvReq, getColumnsTypes(handleCols), statistics.NewQueryFeedback(0, nil, 0, false)) if err != nil { return nil, errors.Trace(err) } @@ -475,7 +476,7 @@ func (dc *ddlCtx) buildDescTableScan(ctx context.Context, startTS uint64, tbl ta } // GetTableMaxHandle gets the max handle of a PhysicalTable. -func (dc *ddlCtx) GetTableMaxHandle(startTS uint64, tbl table.PhysicalTable) (maxHandle kv.Handle, emptyTable bool, err error) { +func (dc *ddlCtx) GetTableMaxHandle(ctx *JobContext, startTS uint64, tbl table.PhysicalTable) (maxHandle kv.Handle, emptyTable bool, err error) { var handleCols []*model.ColumnInfo var pkIdx *model.IndexInfo tblInfo := tbl.Meta() @@ -497,7 +498,6 @@ func (dc *ddlCtx) GetTableMaxHandle(startTS uint64, tbl table.PhysicalTable) (ma handleCols = []*model.ColumnInfo{model.NewExtraHandleColInfo()} } - ctx := context.Background() // build a desc scan of tblInfo, which limit is 1, we can use it to retrieve the last handle of the table. result, err := dc.buildDescTableScan(ctx, startTS, tbl, handleCols, 1) if err != nil { @@ -506,7 +506,7 @@ func (dc *ddlCtx) GetTableMaxHandle(startTS uint64, tbl table.PhysicalTable) (ma defer terror.Call(result.Close) chk := chunk.New(getColumnsTypes(handleCols), 1, 1) - err = result.Next(ctx, chk) + err = result.Next(ctx.ddlJobCtx, chk) if err != nil { return nil, false, errors.Trace(err) } @@ -542,9 +542,9 @@ func buildCommonHandleFromChunkRow(sctx *stmtctx.StatementContext, tblInfo *mode } // getTableRange gets the start and end handle of a table (or partition). -func getTableRange(d *ddlCtx, tbl table.PhysicalTable, snapshotVer uint64, priority int) (startHandleKey, endHandleKey kv.Key, err error) { +func getTableRange(ctx *JobContext, d *ddlCtx, tbl table.PhysicalTable, snapshotVer uint64, priority int) (startHandleKey, endHandleKey kv.Key, err error) { // Get the start handle of this partition. - err = iterateSnapshotRows(d.store, priority, tbl, snapshotVer, nil, nil, + err = iterateSnapshotRows(ctx, d.store, priority, tbl, snapshotVer, nil, nil, func(h kv.Handle, rowKey kv.Key, rawRecord []byte) (bool, error) { startHandleKey = rowKey return false, nil @@ -552,7 +552,7 @@ func getTableRange(d *ddlCtx, tbl table.PhysicalTable, snapshotVer uint64, prior if err != nil { return startHandleKey, endHandleKey, errors.Trace(err) } - maxHandle, isEmptyTable, err := d.GetTableMaxHandle(snapshotVer, tbl) + maxHandle, isEmptyTable, err := d.GetTableMaxHandle(ctx, snapshotVer, tbl) if err != nil { return startHandleKey, nil, errors.Trace(err) } @@ -574,12 +574,12 @@ func getValidCurrentVersion(store kv.Storage) (ver kv.Version, err error) { if err != nil { return ver, errors.Trace(err) } else if ver.Ver <= 0 { - return ver, errInvalidStoreVer.GenWithStack("invalid storage current version %d", ver.Ver) + return ver, dbterror.ErrInvalidStoreVer.GenWithStack("invalid storage current version %d", ver.Ver) } return ver, nil } -func getReorgInfo(d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, elements []*meta.Element) (*reorgInfo, error) { +func getReorgInfo(ctx *JobContext, d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, elements []*meta.Element) (*reorgInfo, error) { var ( element *meta.Element start kv.Key @@ -616,7 +616,7 @@ func getReorgInfo(d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, elem } else { tb = tbl.(table.PhysicalTable) } - start, end, err = getTableRange(d, tb, ver.Ver, job.Priority) + start, end, err = getTableRange(ctx, d, tb, ver.Ver, job.Priority) if err != nil { return nil, errors.Trace(err) } @@ -671,7 +671,7 @@ func getReorgInfo(d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, elem return &info, nil } -func getReorgInfoFromPartitions(d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, partitionIDs []int64, elements []*meta.Element) (*reorgInfo, error) { +func getReorgInfoFromPartitions(ctx *JobContext, d *ddlCtx, t *meta.Meta, job *model.Job, tbl table.Table, partitionIDs []int64, elements []*meta.Element) (*reorgInfo, error) { var ( element *meta.Element start kv.Key @@ -688,7 +688,7 @@ func getReorgInfoFromPartitions(d *ddlCtx, t *meta.Meta, job *model.Job, tbl tab } pid = partitionIDs[0] tb := tbl.(table.PartitionedTable).GetPartition(pid) - start, end, err = getTableRange(d, tb, ver.Ver, job.Priority) + start, end, err = getTableRange(ctx, d, tb, ver.Ver, job.Priority) if err != nil { return nil, errors.Trace(err) } diff --git a/ddl/reorg_test.go b/ddl/reorg_test.go index 461b5d6cb688a..192d5de89d8c2 100644 --- a/ddl/reorg_test.go +++ b/ddl/reorg_test.go @@ -16,14 +16,17 @@ package ddl import ( "context" + "fmt" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) type testCtxKeyType int @@ -34,162 +37,183 @@ func (k testCtxKeyType) String() string { const testCtxKey testCtxKeyType = 0 -func (s *testDDLSuite) TestReorg(c *C) { - store := testCreateStore(c, "test_reorg") - defer func() { - err := store.Close() - c.Assert(err, IsNil) - }() +func TestReorg(t *testing.T) { + tests := []struct { + isCommonHandle bool + handle kv.Handle + startKey kv.Handle + endKey kv.Handle + }{ + { + false, + kv.IntHandle(100), + kv.IntHandle(1), + kv.IntHandle(0), + }, + { + true, + testutil.MustNewCommonHandle(t, "a", 100, "string"), + testutil.MustNewCommonHandle(t, 100, "string"), + testutil.MustNewCommonHandle(t, 101, "string"), + }, + } - d, err := testNewDDLAndStart( - context.Background(), - WithStore(store), - WithLease(testLease), - ) - c.Assert(err, IsNil) - defer func() { - err := d.Stop() - c.Assert(err, IsNil) - }() + for _, test := range tests { + t.Run(fmt.Sprintf("isCommandHandle(%v)", test.isCommonHandle), func(t *testing.T) { + store := createMockStore(t) + defer func() { + require.NoError(t, store.Close()) + }() - time.Sleep(testLease) + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + err := d.Stop() + require.NoError(t, err) + }() - ctx := testNewContext(d) + time.Sleep(testLease) - ctx.SetValue(testCtxKey, 1) - c.Assert(ctx.Value(testCtxKey), Equals, 1) - ctx.ClearValue(testCtxKey) + ctx := testNewContext(d) + + ctx.SetValue(testCtxKey, 1) + require.Equal(t, ctx.Value(testCtxKey), 1) + ctx.ClearValue(testCtxKey) - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err := ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Set([]byte("a"), []byte("b")) - c.Assert(err, IsNil) - err = txn.Rollback() - c.Assert(err, IsNil) - - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Set([]byte("a"), []byte("b")) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - - rowCount := int64(10) - handle := s.NewHandle().Int(100).Common("a", 100, "string") - f := func() error { - d.generalWorker().reorgCtx.setRowCount(rowCount) - d.generalWorker().reorgCtx.setNextKey(handle.Encoded()) - time.Sleep(1*ReorgWaitTimeout + 100*time.Millisecond) - return nil - } - job := &model.Job{ - ID: 1, - SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. - } - err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - m := meta.NewMeta(txn) - e := &meta.Element{ID: 333, TypeKey: meta.IndexElementKey} - rInfo := &reorgInfo{ - Job: job, - currElement: e, - } - mockTbl := tables.MockTableFromMeta(&model.TableInfo{IsCommonHandle: s.IsCommonHandle, CommonHandleVersion: 1}) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) - c.Assert(err, NotNil) - - // The longest to wait for 5 seconds to make sure the function of f is returned. - for i := 0; i < 1000; i++ { - time.Sleep(5 * time.Millisecond) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) - if err == nil { - c.Assert(job.RowCount, Equals, rowCount) - c.Assert(d.generalWorker().reorgCtx.rowCount, Equals, int64(0)) - - // Test whether reorgInfo's Handle is update. - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) err = ctx.NewTxn(context.Background()) - c.Assert(err, IsNil) - - m = meta.NewMeta(txn) - info, err1 := getReorgInfo(d.ddlCtx, m, job, mockTbl, nil) - c.Assert(err1, IsNil) - c.Assert(info.StartKey, DeepEquals, kv.Key(handle.Encoded())) - c.Assert(info.currElement, DeepEquals, e) - _, doneHandle, _ := d.generalWorker().reorgCtx.getRowCountAndKey() - c.Assert(doneHandle, IsNil) - break - } - } - c.Assert(err, IsNil) - - job = &model.Job{ - ID: 2, - SchemaID: 1, - Type: model.ActionCreateSchema, - Args: []interface{}{model.NewCIStr("test")}, - SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. - } + require.NoError(t, err) + txn, err := ctx.Txn(true) + require.NoError(t, err) + err = txn.Set([]byte("a"), []byte("b")) + require.NoError(t, err) + err = txn.Rollback() + require.NoError(t, err) - element := &meta.Element{ID: 123, TypeKey: meta.ColumnElementKey} - info := &reorgInfo{ - Job: job, - d: d.ddlCtx, - currElement: element, - StartKey: s.NewHandle().Int(1).Common(100, "string").Encoded(), - EndKey: s.NewHandle().Int(0).Common(101, "string").Encoded(), - PhysicalTableID: 456, + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + err = txn.Set([]byte("a"), []byte("b")) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + + rowCount := int64(10) + handle := test.handle + f := func() error { + d.generalWorker().reorgCtx.setRowCount(rowCount) + d.generalWorker().reorgCtx.setNextKey(handle.Encoded()) + time.Sleep(1*ReorgWaitTimeout + 100*time.Millisecond) + return nil + } + job := &model.Job{ + ID: 1, + SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. + } + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + m := meta.NewMeta(txn) + e := &meta.Element{ID: 333, TypeKey: meta.IndexElementKey} + rInfo := &reorgInfo{ + Job: job, + currElement: e, + } + mockTbl := tables.MockTableFromMeta(&model.TableInfo{IsCommonHandle: test.isCommonHandle, CommonHandleVersion: 1}) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) + require.Error(t, err) + + // The longest to wait for 5 seconds to make sure the function of f is returned. + for i := 0; i < 1000; i++ { + time.Sleep(5 * time.Millisecond) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, f) + if err == nil { + require.Equal(t, job.RowCount, rowCount) + require.Equal(t, d.generalWorker().reorgCtx.rowCount, int64(0)) + + // Test whether reorgInfo's Handle is update. + err = txn.Commit(context.Background()) + require.NoError(t, err) + err = ctx.NewTxn(context.Background()) + require.NoError(t, err) + + m = meta.NewMeta(txn) + info, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, nil) + require.NoError(t, err1) + require.Equal(t, info.StartKey, kv.Key(handle.Encoded())) + require.Equal(t, info.currElement, e) + _, doneHandle, _ := d.generalWorker().reorgCtx.getRowCountAndKey() + require.Nil(t, doneHandle) + break + } + } + require.NoError(t, err) + + job = &model.Job{ + ID: 2, + SchemaID: 1, + Type: model.ActionCreateSchema, + Args: []interface{}{model.NewCIStr("test")}, + SnapshotVer: 1, // Make sure it is not zero. So the reorgInfo's first is false. + } + + element := &meta.Element{ID: 123, TypeKey: meta.ColumnElementKey} + info := &reorgInfo{ + Job: job, + d: d.ddlCtx, + currElement: element, + StartKey: test.startKey.Encoded(), + EndKey: test.endKey.Encoded(), + PhysicalTableID: 456, + } + err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + var err1 error + _, err1 = getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) + require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err1)) + require.Equal(t, job.SnapshotVer, uint64(0)) + return nil + }) + require.NoError(t, err) + job.SnapshotVer = uint64(1) + err = info.UpdateReorgMeta(info.StartKey) + require.NoError(t, err) + err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + info1, err1 := getReorgInfo(NewJobContext(), d.ddlCtx, m, job, mockTbl, []*meta.Element{element}) + require.NoError(t, err1) + require.Equal(t, info1.currElement, info.currElement) + require.Equal(t, info1.StartKey, info.StartKey) + require.Equal(t, info1.EndKey, info.EndKey) + require.Equal(t, info1.PhysicalTableID, info.PhysicalTableID) + return nil + }) + require.NoError(t, err) + + err = d.Stop() + require.NoError(t, err) + err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, func() error { + time.Sleep(4 * testLease) + return nil + }) + require.Error(t, err) + txn, err = ctx.Txn(true) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + }) } - err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - var err1 error - _, err1 = getReorgInfo(d.ddlCtx, t, job, mockTbl, []*meta.Element{element}) - c.Assert(meta.ErrDDLReorgElementNotExist.Equal(err1), IsTrue) - c.Assert(job.SnapshotVer, Equals, uint64(0)) - return nil - }) - c.Assert(err, IsNil) - job.SnapshotVer = uint64(1) - err = info.UpdateReorgMeta(info.StartKey) - c.Assert(err, IsNil) - err = kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - info1, err1 := getReorgInfo(d.ddlCtx, t, job, mockTbl, []*meta.Element{element}) - c.Assert(err1, IsNil) - c.Assert(info1.currElement, DeepEquals, info.currElement) - c.Assert(info1.StartKey, DeepEquals, info.StartKey) - c.Assert(info1.EndKey, DeepEquals, info.EndKey) - c.Assert(info1.PhysicalTableID, Equals, info.PhysicalTableID) - return nil - }) - c.Assert(err, IsNil) - - err = d.Stop() - c.Assert(err, IsNil) - err = d.generalWorker().runReorgJob(m, rInfo, mockTbl.Meta(), d.lease, func() error { - time.Sleep(4 * testLease) - return nil - }) - c.Assert(err, NotNil) - txn, err = ctx.Txn(true) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - s.RerunWithCommonHandleEnabled(c, s.TestReorg) } -func (s *testDDLSuite) TestReorgOwner(c *C) { - store := testCreateStore(c, "test_reorg_owner") +func TestReorgOwner(t *testing.T) { + store := createMockStore(t) defer func() { - err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, store.Close()) }() d1, err := testNewDDLAndStart( @@ -197,65 +221,69 @@ func (s *testDDLSuite) TestReorgOwner(c *C) { WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d1.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() ctx := testNewContext(d1) - testCheckOwner(c, d1, true) + testCheckOwner(t, d1, true) d2, err := testNewDDLAndStart( context.Background(), WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d2.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() dbInfo, err := testSchemaInfo(d1, "test_reorg") - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d1, dbInfo) + require.NoError(t, err) + testCreateSchema(t, ctx, d1, dbInfo) tblInfo, err := testTableInfo(d1, "t", 3) - c.Assert(err, IsNil) - testCreateTable(c, ctx, d1, dbInfo, tblInfo) - t := testGetTable(c, d1, dbInfo.ID, tblInfo.ID) + require.NoError(t, err) + testCreateTable(t, ctx, d1, dbInfo, tblInfo) + tbl := testGetTable(t, d1, dbInfo.ID, tblInfo.ID) num := 10 for i := 0; i < num; i++ { - _, err := t.AddRecord(ctx, types.MakeDatums(i, i, i)) - c.Assert(err, IsNil) + _, err := tbl.AddRecord(ctx, types.MakeDatums(i, i, i)) + require.NoError(t, err) } txn, err := ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) tc := &TestDDLCallback{} tc.onJobRunBefore = func(job *model.Job) { if job.SchemaState == model.StateDeleteReorganization { err = d1.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) } } d1.SetHook(tc) - testDropSchema(c, ctx, d1, dbInfo) + testDropSchema(t, ctx, d1, dbInfo) err = kv.RunInNewTxn(context.Background(), d1.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - db, err1 := t.GetDatabase(dbInfo.ID) - c.Assert(err1, IsNil) - c.Assert(db, IsNil) + m := meta.NewMeta(txn) + db, err1 := m.GetDatabase(dbInfo.ID) + require.NoError(t, err1) + require.Nil(t, db) return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) +} + +func testCheckOwner(t *testing.T, d *ddl, expectedVal bool) { + require.Equal(t, d.isOwner(), expectedVal) } diff --git a/ddl/repair_table_test.go b/ddl/repair_table_test.go new file mode 100644 index 0000000000000..b24ddae15b387 --- /dev/null +++ b/ddl/repair_table_test.go @@ -0,0 +1,242 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/domainutil" + "github.com/stretchr/testify/require" +) + +const repairTableLease = 600 * time.Millisecond + +func TestRepairTable(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable")) + }() + + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, repairTableLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // Test repair table when TiDB is not in repair mode. + tk.MustExec("CREATE TABLE t (a int primary key nonclustered, b varchar(10));") + tk.MustGetErrMsg("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));", "[ddl:8215]Failed to repair table: TiDB is not in REPAIR MODE") + + // Test repair table when the repaired list is empty. + domainutil.RepairInfo.SetRepairMode(true) + tk.MustGetErrMsg("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));", "[ddl:8215]Failed to repair table: repair list is empty") + + // Test repair table when it's database isn't in repairInfo. + domainutil.RepairInfo.SetRepairTableList([]string{"test.other_table"}) + tk.MustGetErrMsg("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));", "[ddl:8215]Failed to repair table: database test is not in repair") + + // Test repair table when the table isn't in repairInfo. + tk.MustExec("CREATE TABLE other_table (a int, b varchar(1), key using hash(b));") + tk.MustGetErrMsg("admin repair table t CREATE TABLE t (a float primary key, b varchar(5));", "[ddl:8215]Failed to repair table: table t is not in repair") + + // Test user can't access to the repaired table. + tk.MustGetErrMsg("select * from other_table", "[schema:1146]Table 'test.other_table' doesn't exist") + + // Test create statement use the same name with what is in repaired. + tk.MustGetErrMsg("CREATE TABLE other_table (a int);", "[ddl:1103]Incorrect table name 'other_table'%!(EXTRA string=this table is in repair)") + + // Test column lost in repair table. + tk.MustGetErrMsg("admin repair table other_table CREATE TABLE other_table (a int, c char(1));", "[ddl:8215]Failed to repair table: Column c has lost") + + // Test column type should be the same. + tk.MustGetErrMsg("admin repair table other_table CREATE TABLE other_table (a bigint, b varchar(1), key using hash(b));", "[ddl:8215]Failed to repair table: Column a type should be the same") + + // Test index lost in repair table. + tk.MustGetErrMsg("admin repair table other_table CREATE TABLE other_table (a int unique);", "[ddl:8215]Failed to repair table: Index a has lost") + + // Test index type should be the same. + tk.MustGetErrMsg("admin repair table other_table CREATE TABLE other_table (a int, b varchar(2) unique)", "[ddl:8215]Failed to repair table: Index b type should be the same") + + // Test sub create statement in repair statement with the same name. + tk.MustExec("admin repair table other_table CREATE TABLE other_table (a int);") + + // Test whether repair table name is case-sensitive. + domainutil.RepairInfo.SetRepairMode(true) + domainutil.RepairInfo.SetRepairTableList([]string{"test.other_table2"}) + tk.MustExec("CREATE TABLE otHer_tAblE2 (a int, b varchar(1));") + tk.MustExec("admin repair table otHer_tAblE2 CREATE TABLE otHeR_tAbLe (a int, b varchar(2));") + repairTable := external.GetTableByName(t, tk, "test", "otHeR_tAbLe") //nolint:typecheck + require.Equal(t, "otHeR_tAbLe", repairTable.Meta().Name.O) + + // Test memory and system database is not for repair. + domainutil.RepairInfo.SetRepairMode(true) + domainutil.RepairInfo.SetRepairTableList([]string{"test.xxx"}) + tk.MustGetErrMsg("admin repair table performance_schema.xxx CREATE TABLE yyy (a int);", "[ddl:8215]Failed to repair table: memory or system database is not for repair") + + // Test the repair detail. + turnRepairModeAndInit(true) + defer turnRepairModeAndInit(false) + // Domain reload the tableInfo and add it into repairInfo. + tk.MustExec("CREATE TABLE origin (a int primary key nonclustered auto_increment, b varchar(10), c int);") + // Repaired tableInfo has been filtered by `domain.InfoSchema()`, so get it in repairInfo. + originTableInfo, _ := domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") + + hook := &ddl.TestDDLCallback{Do: dom} + var repairErr error + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type != model.ActionRepairTable { + return + } + if job.TableID != originTableInfo.ID { + repairErr = errors.New("table id should be the same") + return + } + if job.SchemaState != model.StateNone { + repairErr = errors.New("repair job state should be the none") + return + } + // Test whether it's readable, when repaired table is still stateNone. + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + _, repairErr = tk.Exec("select * from origin") + // Repaired tableInfo has been filtered by `domain.InfoSchema()`, here will get an error cause user can't get access to it. + if repairErr != nil && terror.ErrorEqual(repairErr, infoschema.ErrTableNotExists) { + repairErr = nil + } + } + originalHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originalHook) + dom.DDL().SetHook(hook) + + // Exec the repair statement to override the tableInfo. + tk.MustExec("admin repair table origin CREATE TABLE origin (a int primary key nonclustered auto_increment, b varchar(5), c int);") + require.NoError(t, repairErr) + + // Check the repaired tableInfo is exactly the same with old one in tableID, indexID, colID. + // testGetTableByName will extract the Table from `domain.InfoSchema()` directly. + repairTable = external.GetTableByName(t, tk, "test", "origin") //nolint:typecheck + require.Equal(t, originTableInfo.ID, repairTable.Meta().ID) + require.Equal(t, 3, len(repairTable.Meta().Columns)) + require.Equal(t, originTableInfo.Columns[0].ID, repairTable.Meta().Columns[0].ID) + require.Equal(t, originTableInfo.Columns[1].ID, repairTable.Meta().Columns[1].ID) + require.Equal(t, originTableInfo.Columns[2].ID, repairTable.Meta().Columns[2].ID) + require.Equal(t, 1, len(repairTable.Meta().Indices)) + require.Equal(t, originTableInfo.Columns[0].ID, repairTable.Meta().Indices[0].ID) + require.Equal(t, originTableInfo.AutoIncID, repairTable.Meta().AutoIncID) + + require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[0].Tp) + require.Equal(t, mysql.TypeVarchar, repairTable.Meta().Columns[1].Tp) + require.Equal(t, 5, repairTable.Meta().Columns[1].Flen) + require.Equal(t, mysql.TypeLong, repairTable.Meta().Columns[2].Tp) + + // Exec the show create table statement to make sure new tableInfo has been set. + result := tk.MustQuery("show create table origin") + require.Equal(t, "CREATE TABLE `origin` (\n `a` int(11) NOT NULL AUTO_INCREMENT,\n `b` varchar(5) DEFAULT NULL,\n `c` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", result.Rows()[0][1]) +} + +func turnRepairModeAndInit(on bool) { + list := make([]string, 0) + if on { + list = append(list, "test.origin") + } + domainutil.RepairInfo.SetRepairMode(on) + domainutil.RepairInfo.SetRepairTableList(list) +} + +func TestRepairTableWithPartition(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/repairFetchCreateTable")) + }() + store, clean := testkit.CreateMockStoreWithSchemaLease(t, repairTableLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists origin") + + turnRepairModeAndInit(true) + defer turnRepairModeAndInit(false) + // Domain reload the tableInfo and add it into repairInfo. + tk.MustExec("create table origin (a int not null) partition by RANGE(a) (" + + "partition p10 values less than (10)," + + "partition p30 values less than (30)," + + "partition p50 values less than (50)," + + "partition p70 values less than (70)," + + "partition p90 values less than (90));") + // Test for some old partition has lost. + tk.MustGetErrMsg("admin repair table origin create table origin (a int not null) partition by RANGE(a) ("+ + "partition p10 values less than (10),"+ + "partition p30 values less than (30),"+ + "partition p50 values less than (50),"+ + "partition p90 values less than (90),"+ + "partition p100 values less than (100));", "[ddl:8215]Failed to repair table: Partition p100 has lost") + + // Test for some partition changed the condition. + tk.MustGetErrMsg("admin repair table origin create table origin (a int not null) partition by RANGE(a) ("+ + "partition p10 values less than (10),"+ + "partition p20 values less than (25),"+ + "partition p50 values less than (50),"+ + "partition p90 values less than (90));", "[ddl:8215]Failed to repair table: Partition p20 has lost") + + // Test for some partition changed the partition name. + tk.MustGetErrMsg("admin repair table origin create table origin (a int not null) partition by RANGE(a) ("+ + "partition p10 values less than (10),"+ + "partition p30 values less than (30),"+ + "partition pNew values less than (50),"+ + "partition p90 values less than (90));", "[ddl:8215]Failed to repair table: Partition pnew has lost") + + originTableInfo, _ := domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") + tk.MustExec("admin repair table origin create table origin_rename (a int not null) partition by RANGE(a) (" + + "partition p10 values less than (10)," + + "partition p30 values less than (30)," + + "partition p50 values less than (50)," + + "partition p90 values less than (90));") + repairTable := external.GetTableByName(t, tk, "test", "origin_rename") //nolint:typecheck + require.Equal(t, originTableInfo.ID, repairTable.Meta().ID) + require.Equal(t, 1, len(repairTable.Meta().Columns)) + require.Equal(t, originTableInfo.Columns[0].ID, repairTable.Meta().Columns[0].ID) + require.Equal(t, 4, len(repairTable.Meta().Partition.Definitions)) + require.Equal(t, originTableInfo.Partition.Definitions[0].ID, repairTable.Meta().Partition.Definitions[0].ID) + require.Equal(t, originTableInfo.Partition.Definitions[1].ID, repairTable.Meta().Partition.Definitions[1].ID) + require.Equal(t, originTableInfo.Partition.Definitions[2].ID, repairTable.Meta().Partition.Definitions[2].ID) + require.Equal(t, originTableInfo.Partition.Definitions[4].ID, repairTable.Meta().Partition.Definitions[3].ID) + + // Test hash partition. + tk.MustExec("drop table if exists origin") + domainutil.RepairInfo.SetRepairMode(true) + domainutil.RepairInfo.SetRepairTableList([]string{"test.origin"}) + tk.MustExec("create table origin (a varchar(1), b int not null, c int, key idx(c)) partition by hash(b) partitions 30") + + // Test partition num in repair should be exactly same with old one, other wise will cause partition semantic problem. + tk.MustGetErrMsg("admin repair table origin create table origin (a varchar(2), b int not null, c int, key idx(c)) partition by hash(b) partitions 20", "[ddl:8215]Failed to repair table: Hash partition num should be the same") + + originTableInfo, _ = domainutil.RepairInfo.GetRepairedTableInfoByTableName("test", "origin") + tk.MustExec("admin repair table origin create table origin (a varchar(3), b int not null, c int, key idx(c)) partition by hash(b) partitions 30") + repairTable = external.GetTableByName(t, tk, "test", "origin") //nolint:typecheck + require.Equal(t, originTableInfo.ID, repairTable.Meta().ID) + require.Equal(t, 30, len(repairTable.Meta().Partition.Definitions)) + require.Equal(t, originTableInfo.Partition.Definitions[0].ID, repairTable.Meta().Partition.Definitions[0].ID) + require.Equal(t, originTableInfo.Partition.Definitions[1].ID, repairTable.Meta().Partition.Definitions[1].ID) + require.Equal(t, originTableInfo.Partition.Definitions[29].ID, repairTable.Meta().Partition.Definitions[29].ID) +} diff --git a/ddl/restart_test.go b/ddl/restart_test.go index e1cf6d15fee84..cd1e330cd3fa7 100644 --- a/ddl/restart_test.go +++ b/ddl/restart_test.go @@ -19,17 +19,25 @@ package ddl import ( "context" "errors" + "testing" "time" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) // this test file include some test that will cause data race, mainly because restartWorkers modify d.ctx +func getDDLSchemaVer(t *testing.T, d *ddl) int64 { + m, err := d.Stats(nil) + require.NoError(t, err) + v := m[ddlSchemaVersion] + return v.(int64) +} + // restartWorkers is like the function of d.start. But it won't initialize the "workers" and create a new worker. // It only starts the original workers. func (d *ddl) restartWorkers(ctx context.Context) { @@ -54,7 +62,7 @@ func (d *ddl) restartWorkers(ctx context.Context) { } // runInterruptedJob should be called concurrently with restartWorkers -func runInterruptedJob(c *C, d *ddl, job *model.Job, doneCh chan error) { +func runInterruptedJob(d *ddl, job *model.Job, doneCh chan error) { ctx := mock.NewContext() ctx.Store = d.store @@ -63,11 +71,12 @@ func runInterruptedJob(c *C, d *ddl, job *model.Job, doneCh chan error) { err error ) - err = d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + err = d.DoDDLJob(ctx, job) if errors.Is(err, context.Canceled) { endlessLoopTime := time.Now().Add(time.Minute) for history == nil { - // imitate doDDLJob's logic, quit only find history + // imitate DoDDLJob's logic, quit only find history history, _ = d.getHistoryDDLJob(job.ID) if history != nil { err = history.Error @@ -83,32 +92,30 @@ func runInterruptedJob(c *C, d *ddl, job *model.Job, doneCh chan error) { doneCh <- err } -func testRunInterruptedJob(c *C, d *ddl, job *model.Job) { +func testRunInterruptedJob(t *testing.T, d *ddl, job *model.Job) { done := make(chan error, 1) - go runInterruptedJob(c, d, job, done) + go runInterruptedJob(d, job, done) ticker := time.NewTicker(d.lease * 1) defer ticker.Stop() -LOOP: for { select { case <-ticker.C: err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) d.restartWorkers(context.Background()) time.Sleep(time.Millisecond * 20) case err := <-done: - c.Assert(err, IsNil) - break LOOP + require.Nil(t, err) + return } } } -func (s *testSchemaSuite) TestSchemaResume(c *C) { - store := testCreateStore(c, "test_schema_resume") +func TestSchemaResume(t *testing.T) { + store := createMockStore(t) defer func() { - err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, store.Close()) }() d1, err := testNewDDLAndStart( @@ -116,39 +123,37 @@ func (s *testSchemaSuite) TestSchemaResume(c *C) { WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - err := d1.Stop() - c.Assert(err, IsNil) + require.NoError(t, d1.Stop()) }() - testCheckOwner(c, d1, true) + testCheckOwner(t, d1, true) dbInfo, err := testSchemaInfo(d1, "test_restart") - c.Assert(err, IsNil) + require.NoError(t, err) job := &model.Job{ SchemaID: dbInfo.ID, Type: model.ActionCreateSchema, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{dbInfo}, } - testRunInterruptedJob(c, d1, job) - testCheckSchemaState(c, d1, dbInfo, model.StatePublic) + testRunInterruptedJob(t, d1, job) + testCheckSchemaState(t, d1, dbInfo, model.StatePublic) job = &model.Job{ SchemaID: dbInfo.ID, Type: model.ActionDropSchema, BinlogInfo: &model.HistoryInfo{}, } - testRunInterruptedJob(c, d1, job) - testCheckSchemaState(c, d1, dbInfo, model.StateNone) + testRunInterruptedJob(t, d1, job) + testCheckSchemaState(t, d1, dbInfo, model.StateNone) } -func (s *testStatSuite) TestStat(c *C) { - store := testCreateStore(c, "test_stat") +func TestStat(t *testing.T) { + store := createMockStore(t) defer func() { - err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, store.Close()) }() d, err := testNewDDLAndStart( @@ -156,15 +161,14 @@ func (s *testStatSuite) TestStat(c *C) { WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, d.Stop()) }() dbInfo, err := testSchemaInfo(d, "test_restart") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) // TODO: Get this information from etcd. // m, err := d.Stats(nil) @@ -179,84 +183,72 @@ func (s *testStatSuite) TestStat(c *C) { } done := make(chan error, 1) - go runInterruptedJob(c, d, job, done) + go runInterruptedJob(d, job, done) ticker := time.NewTicker(d.lease * 1) defer ticker.Stop() - ver := s.getDDLSchemaVer(c, d) + ver := getDDLSchemaVer(t, d) LOOP: for { select { case <-ticker.C: err := d.Stop() - c.Assert(err, IsNil) - c.Assert(s.getDDLSchemaVer(c, d), GreaterEqual, ver) + require.Nil(t, err) + require.GreaterOrEqual(t, getDDLSchemaVer(t, d), ver) d.restartWorkers(context.Background()) time.Sleep(time.Millisecond * 20) case err := <-done: // TODO: Get this information from etcd. // m, err := d.Stats(nil) - c.Assert(err, IsNil) + require.Nil(t, err) break LOOP } } } -var _ = Suite(&testTableSuite{}) - -type testTableSuite struct { - store kv.Storage - dbInfo *model.DBInfo - - d *ddl -} +func TestTableResume(t *testing.T) { + store := createMockStore(t) + defer func() { + require.NoError(t, store.Close()) + }() -func (s *testTableSuite) SetUpSuite(c *C) { - s.store = testCreateStore(c, "test_table") - ddl, err := testNewDDLAndStart( + d, err := testNewDDLAndStart( context.Background(), - WithStore(s.store), + WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) - s.d = ddl - - s.dbInfo, err = testSchemaInfo(s.d, "test_table") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(s.d), s.d, s.dbInfo) -} - -func (s *testTableSuite) TearDownSuite(c *C) { - testDropSchema(c, testNewContext(s.d), s.d, s.dbInfo) - err := s.d.Stop() - c.Assert(err, IsNil) - err = s.store.Close() - c.Assert(err, IsNil) -} + require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() -func (s *testTableSuite) TestTableResume(c *C) { - d := s.d + dbInfo, err := testSchemaInfo(d, "test_table") + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) + defer func() { + testDropSchema(t, testNewContext(d), d, dbInfo) + }() - testCheckOwner(c, d, true) + testCheckOwner(t, d, true) tblInfo, err := testTableInfo(d, "t1", 3) - c.Assert(err, IsNil) + require.NoError(t, err) job := &model.Job{ - SchemaID: s.dbInfo.ID, + SchemaID: dbInfo.ID, TableID: tblInfo.ID, Type: model.ActionCreateTable, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{tblInfo}, } - testRunInterruptedJob(c, d, job) - testCheckTableState(c, d, s.dbInfo, tblInfo, model.StatePublic) + testRunInterruptedJob(t, d, job) + testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) job = &model.Job{ - SchemaID: s.dbInfo.ID, + SchemaID: dbInfo.ID, TableID: tblInfo.ID, Type: model.ActionDropTable, BinlogInfo: &model.HistoryInfo{}, } - testRunInterruptedJob(c, d, job) - testCheckTableState(c, d, s.dbInfo, tblInfo, model.StateNone) + testRunInterruptedJob(t, d, job) + testCheckTableState(t, d, dbInfo, tblInfo, model.StateNone) } diff --git a/ddl/rollingback.go b/ddl/rollingback.go index ab4e863fb7134..6711838b271a8 100644 --- a/ddl/rollingback.go +++ b/ddl/rollingback.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" "go.uber.org/zap" ) @@ -60,7 +61,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T } // the second args will be used in onDropIndex. - job.Args = []interface{}{indexInfo.Name, getPartitionIDs(tblInfo)} + job.Args = []interface{}{indexInfo.Name, false /* ifExists */, getPartitionIDs(tblInfo)} // If add index job rollbacks in write reorganization state, its need to delete all keys which has been added. // Its work is the same as drop index job do. // The write reorganization state in add index job that likes write only state in drop index job. @@ -80,7 +81,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T // to rollback add index operations. job.SnapshotVer == 0 indicates the workers are not started. func convertNotStartAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, occuredErr error) (ver int64, err error) { schemaID := job.SchemaID - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } @@ -100,7 +101,7 @@ func convertNotStartAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, occuredE indexInfo := tblInfo.FindIndexByName(indexName.L) if indexInfo == nil { job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } return convertAddIdxJob2RollbackJob(t, job, tblInfo, indexInfo, occuredErr) } @@ -115,39 +116,39 @@ func rollingbackModifyColumn(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) // column type change workers are started. we have to ask them to exit. logutil.Logger(w.logCtx).Info("[ddl] run the cancelling DDL job", zap.String("job", job.String())) w.reorgCtx.notifyReorgCancel() - // Give the this kind of ddl one more round to run, the errCancelledDDLJob should be fetched from the bottom up. + // Give the this kind of ddl one more round to run, the dbterror.ErrCancelledDDLJob should be fetched from the bottom up. return w.onModifyColumn(d, t, job) } - _, tblInfo, oldCol, jp, err := getModifyColumnInfo(t, job) + _, tblInfo, oldCol, modifyInfo, err := getModifyColumnInfo(t, job) if err != nil { return ver, err } - if !needChangeColumnData(oldCol, jp.newCol) { + if !needChangeColumnData(oldCol, modifyInfo.newCol) { // Normal-type rolling back if job.SchemaState == model.StateNone { // When change null to not null, although state is unchanged with none, the oldCol flag's has been changed to preNullInsertFlag. // To roll back this kind of normal job, it is necessary to mark the state as JobStateRollingback to restore the old col's flag. - if jp.modifyColumnTp == mysql.TypeNull && tblInfo.Columns[oldCol.Offset].Flag|mysql.PreventNullInsertFlag != 0 { + if modifyInfo.modifyColumnTp == mysql.TypeNull && tblInfo.Columns[oldCol.Offset].Flag|mysql.PreventNullInsertFlag != 0 { job.State = model.JobStateRollingback - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } // Normal job with stateNone can be cancelled directly. job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } // StatePublic couldn't be cancelled. job.State = model.JobStateRunning return ver, nil } // reorg-type rolling back - if jp.changingCol == nil { - // The job hasn't been handled and we cancel it directly. + if modifyInfo.changingCol == nil { + // The job hasn't been handled, so cancel it directly. job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } // The job has been in its middle state (but the reorg worker hasn't started) and we roll it back here. job.State = model.JobStateRollingback - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } func rollingbackAddColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { @@ -157,53 +158,25 @@ func rollingbackAddColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { } if columnInfo == nil { job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } originalState := columnInfo.State columnInfo.State = model.StateDeleteOnly job.SchemaState = model.StateDeleteOnly - job.Args = []interface{}{col.Name} + job.Args = []interface{}{col.Name, false /* ifExists */} ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfo.State) if err != nil { return ver, errors.Trace(err) } job.State = model.JobStateRollingback - return ver, errCancelledDDLJob -} - -func rollingbackAddColumns(t *meta.Meta, job *model.Job) (ver int64, err error) { - tblInfo, columnInfos, _, _, _, _, err := checkAddColumns(t, job) - if err != nil { - return ver, errors.Trace(err) - } - if len(columnInfos) == 0 { - job.State = model.JobStateCancelled - return ver, errCancelledDDLJob - } - - colNames := make([]model.CIStr, len(columnInfos)) - originalState := columnInfos[0].State - for i, columnInfo := range columnInfos { - columnInfos[i].State = model.StateDeleteOnly - colNames[i] = columnInfo.Name - } - ifExists := make([]bool, len(columnInfos)) - - job.SchemaState = model.StateDeleteOnly - job.Args = []interface{}{colNames, ifExists} - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != columnInfos[0].State) - if err != nil { - return ver, errors.Trace(err) - } - job.State = model.JobStateRollingback - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } func rollingbackDropColumn(t *meta.Meta, job *model.Job) (ver int64, err error) { - _, colInfo, idxInfos, err := checkDropColumn(t, job) + _, colInfo, idxInfos, _, err := checkDropColumn(t, job) if err != nil { return ver, errors.Trace(err) } @@ -219,14 +192,14 @@ func rollingbackDropColumn(t *meta.Meta, job *model.Job) (ver int64, err error) return ver, nil case model.StatePublic: default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) } } // StatePublic means when the job is not running yet. if colInfo.State == model.StatePublic { job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } // In the state of drop column `write only -> delete only -> reorganization`, // We can not rollback now, so just continue to drop column. @@ -234,41 +207,10 @@ func rollingbackDropColumn(t *meta.Meta, job *model.Job) (ver int64, err error) return ver, nil } -func rollingbackDropColumns(t *meta.Meta, job *model.Job) (ver int64, err error) { - _, colInfos, _, idxInfos, err := checkDropColumns(t, job) - if err != nil { - return ver, errors.Trace(err) - } - - for _, indexInfo := range idxInfos { - switch indexInfo.State { - case model.StateWriteOnly, model.StateDeleteOnly, model.StateDeleteReorganization, model.StateNone: - // We can not rollback now, so just continue to drop index. - // In function isJobRollbackable will let job rollback when state is StateNone. - // When there is no index related to the drop columns job it is OK, but when there has indices, we should - // make sure the job is not rollback. - job.State = model.JobStateRunning - return ver, nil - case model.StatePublic: - default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) - } - } - - // StatePublic means when the job is not running yet. - if colInfos[0].State == model.StatePublic { - job.State = model.JobStateCancelled - return ver, errCancelledDDLJob - } - // In the state of drop columns `write only -> delete only -> reorganization`, - // We can not rollback now, so just continue to drop columns. - job.State = model.JobStateRunning - return ver, nil -} - func rollingbackDropIndex(t *meta.Meta, job *model.Job) (ver int64, err error) { - _, indexInfo, err := checkDropIndex(t, job) + _, indexInfo, _, err := checkDropIndex(t, job) if err != nil { + job.State = model.JobStateCancelled return ver, errors.Trace(err) } @@ -280,47 +222,10 @@ func rollingbackDropIndex(t *meta.Meta, job *model.Job) (ver int64, err error) { return ver, nil case model.StatePublic: job.State = model.JobStateCancelled - return ver, errCancelledDDLJob - default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) - } -} - -func rollingbackDropIndexes(t *meta.Meta, job *model.Job) (ver int64, err error) { - tblInfo, indexNames, ifExists, err := getSchemaInfos(t, job) - if err != nil { - return ver, errors.Trace(err) - } - - indexInfos, err := checkDropIndexes(tblInfo, job, indexNames, ifExists) - if err != nil { - return ver, errors.Trace(err) - } - - indexInfo := indexInfos[0] - originalState := indexInfo.State - switch indexInfo.State { - case model.StateWriteOnly, model.StateDeleteOnly, model.StateDeleteReorganization, model.StateNone: - // We can not rollback now, so just continue to drop index. - // Normally won't fetch here, because there is a check when canceling DDL jobs. See function: IsJobRollbackable. - job.State = model.JobStateRunning - return ver, nil - case model.StatePublic: - job.State = model.JobStateRollbackDone - for _, indexInfo := range indexInfos { - indexInfo.State = model.StatePublic - } + return ver, dbterror.ErrCancelledDDLJob default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) - } - - job.SchemaState = indexInfo.State - ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != indexInfo.State) - if err != nil { - return ver, errors.Trace(err) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("index", indexInfo.State) } - job.FinishTableJob(model.JobStateRollbackDone, model.StatePublic, ver, tblInfo) - return ver, errCancelledDDLJob } func rollingbackAddIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, isPK bool) (ver int64, err error) { @@ -332,7 +237,7 @@ func rollingbackAddIndex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job, isP ver, err = w.onCreateIndex(d, t, job, isPK) } else { // add index workers are not started, remove the indexInfo in tableInfo. - ver, err = convertNotStartAddIdxJob2RollbackJob(t, job, errCancelledDDLJob) + ver, err = convertNotStartAddIdxJob2RollbackJob(t, job, dbterror.ErrCancelledDDLJob) } return } @@ -360,10 +265,10 @@ func rollingbackAddTablePartition(t *meta.Meta, job *model.Job) (ver int64, err // addingDefinitions' len = 0 means the job hasn't reached the replica-only state. if len(addingDefinitions) == 0 { job.State = model.JobStateCancelled - return ver, errors.Trace(errCancelledDDLJob) + return ver, errors.Trace(dbterror.ErrCancelledDDLJob) } // addingDefinitions is also in tblInfo, here pass the tblInfo as parameter directly. - return convertAddTablePartitionJob2RollbackJob(t, job, errCancelledDDLJob, tblInfo) + return convertAddTablePartitionJob2RollbackJob(t, job, dbterror.ErrCancelledDDLJob, tblInfo) } func rollingbackDropTableOrView(t *meta.Meta, job *model.Job) error { @@ -375,14 +280,14 @@ func rollingbackDropTableOrView(t *meta.Meta, job *model.Job) error { // Normally won't fetch here, because there is check when cancel ddl jobs. see function: isJobRollbackable. if tblInfo.State == model.StatePublic { job.State = model.JobStateCancelled - return errCancelledDDLJob + return dbterror.ErrCancelledDDLJob } job.State = model.JobStateRunning return nil } func rollingbackDropTablePartition(t *meta.Meta, job *model.Job) (ver int64, err error) { - _, err = getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + _, err = GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -398,7 +303,7 @@ func rollingbackDropSchema(t *meta.Meta, job *model.Job) error { // Normally won't fetch here, because there is check when cancel ddl jobs. see function: isJobRollbackable. if dbInfo.State == model.StatePublic { job.State = model.JobStateCancelled - return errCancelledDDLJob + return dbterror.ErrCancelledDDLJob } job.State = model.JobStateRunning return nil @@ -413,7 +318,7 @@ func rollingbackRenameIndex(t *meta.Meta, job *model.Job) (ver int64, err error) idx := tblInfo.FindIndexByName(from.L) if idx.State == model.StatePublic { job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } job.State = model.JobStateRunning return ver, errors.Trace(err) @@ -423,7 +328,7 @@ func cancelOnlyNotHandledJob(job *model.Job) (ver int64, err error) { // We can only cancel the not handled job. if job.SchemaState == model.StateNone { job.State = model.JobStateCancelled - return ver, errCancelledDDLJob + return ver, dbterror.ErrCancelledDDLJob } job.State = model.JobStateRunning @@ -432,7 +337,7 @@ func cancelOnlyNotHandledJob(job *model.Job) (ver int64, err error) { } func rollingbackTruncateTable(t *meta.Meta, job *model.Job) (ver int64, err error) { - _, err = getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + _, err = GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -443,8 +348,6 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) switch job.Type { case model.ActionAddColumn: ver, err = rollingbackAddColumn(t, job) - case model.ActionAddColumns: - ver, err = rollingbackAddColumns(t, job) case model.ActionAddIndex: ver, err = rollingbackAddIndex(w, d, t, job, false) case model.ActionAddPrimaryKey: @@ -453,12 +356,8 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) ver, err = rollingbackAddTablePartition(t, job) case model.ActionDropColumn: ver, err = rollingbackDropColumn(t, job) - case model.ActionDropColumns: - ver, err = rollingbackDropColumns(t, job) case model.ActionDropIndex, model.ActionDropPrimaryKey: ver, err = rollingbackDropIndex(t, job) - case model.ActionDropIndexes: - ver, err = rollingbackDropIndexes(t, job) case model.ActionDropTable, model.ActionDropView, model.ActionDropSequence: err = rollingbackDropTableOrView(t, job) case model.ActionDropTablePartition: @@ -478,9 +377,11 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) model.ActionModifyTableAutoIdCache, model.ActionAlterIndexVisibility, model.ActionExchangeTablePartition, model.ActionModifySchemaDefaultPlacement: ver, err = cancelOnlyNotHandledJob(job) + case model.ActionMultiSchemaChange: + err = rollingBackMultiSchemaChange(job) default: job.State = model.JobStateCancelled - err = errCancelledDDLJob + err = dbterror.ErrCancelledDDLJob } if err != nil { @@ -489,9 +390,9 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) } job.ErrorCount++ - if errCancelledDDLJob.Equal(err) { + if dbterror.ErrCancelledDDLJob.Equal(err) { // The job is normally cancelled. - if !job.Error.Equal(errCancelledDDLJob) { + if !job.Error.Equal(dbterror.ErrCancelledDDLJob) { job.Error = terror.GetErrClass(job.Error).Synthesize(terror.ErrCode(job.Error.Code()), fmt.Sprintf("DDL job rollback, error msg: %s", terror.ToSQLError(job.Error).Message)) } diff --git a/ddl/rollingback_test.go b/ddl/rollingback_test.go index e8c43edbca406..dcc3a455d9957 100644 --- a/ddl/rollingback_test.go +++ b/ddl/rollingback_test.go @@ -17,26 +17,27 @@ package ddl_test import ( "context" "strconv" + "testing" - . "github.com/pingcap/check" - errors2 "github.com/pingcap/errors" + "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testRollingBackSuite{&testDBSuite{}}) +// TestCancelJobMeetError is used to test canceling ddl job failure when convert ddl job to a rolling back job. +func TestCancelAddIndexJobError(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() -type testRollingBackSuite struct{ *testDBSuite } - -// TestCancelJobMeetError is used to test canceling ddl job failure when convert ddl job to a rollingback job. -func (s *testRollingBackSuite) TestCancelAddIndexJobError(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk1 := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk1 := testkit.NewTestKit(t, store) tk.MustExec("use test") tk1.MustExec("use test") @@ -44,16 +45,16 @@ func (s *testRollingBackSuite) TestCancelAddIndexJobError(c *C) { tk.MustExec("insert into t_cancel_add_index values(1),(2),(3)") tk.MustExec("set @@global.tidb_ddl_error_count_limit=3") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockConvertAddIdxJob2RollbackJobError", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockConvertAddIdxJob2RollbackJobError", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockConvertAddIdxJob2RollbackJobError"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockConvertAddIdxJob2RollbackJobError")) }() - tbl := testGetTableByName(c, tk.Se, "test", "t_cancel_add_index") - c.Assert(tbl, NotNil) + tbl := external.GetTableByName(t, tk, "test", "t_cancel_add_index") //nolint:typecheck + require.NotNil(t, tbl) - d := s.dom.DDL() - hook := &ddl.TestDDLCallback{Do: s.dom} + d := dom.DDL() + hook := &ddl.TestDDLCallback{Do: dom} var ( checkErr error jobID int64 @@ -80,23 +81,22 @@ func (s *testRollingBackSuite) TestCancelAddIndexJobError(c *C) { } } } - d.(ddl.DDLForTest).SetHook(hook) + d.SetHook(hook) // This will hang on stateDeleteOnly, and the job will be canceled. - _, err := tk.Exec("alter table t_cancel_add_index add index idx(a)") - c.Assert(err, NotNil) - c.Assert(checkErr, IsNil) - c.Assert(err.Error(), Equals, "[ddl:-1]rollback DDL job error count exceed the limit 3, cancelled it now") + err := tk.ExecToErr("alter table t_cancel_add_index add index idx(a)") + require.NoError(t, checkErr) + require.EqualError(t, err, "[ddl:-1]rollback DDL job error count exceed the limit 3, cancelled it now") // Verification of the history job state. var job *model.Job - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) var err1 error - job, err1 = t.GetHistoryDDLJob(jobID) - return errors2.Trace(err1) + job, err1 = m.GetHistoryDDLJob(jobID) + return errors.Trace(err1) }) - c.Assert(err, IsNil) - c.Assert(job.ErrorCount, Equals, int64(4)) - c.Assert(job.Error.Error(), Equals, "[ddl:-1]rollback DDL job error count exceed the limit 3, cancelled it now") + require.NoError(t, err) + require.Equal(t, int64(4), job.ErrorCount) + require.EqualError(t, job.Error, "[ddl:-1]rollback DDL job error count exceed the limit 3, cancelled it now") } diff --git a/ddl/sanity_check.go b/ddl/sanity_check.go new file mode 100644 index 0000000000000..74d5f35959495 --- /dev/null +++ b/ddl/sanity_check.go @@ -0,0 +1,207 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl + +import ( + "context" + "flag" + "fmt" + "strings" + + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/util/sqlexec" +) + +func checkRangeCntByTableIDs(physicalTableIDs []int64, cnt int64) { + if len(physicalTableIDs) > 0 { + if len(physicalTableIDs) != int(cnt) { + panic("should not happened" + fmt.Sprintf("expect count: %d, real count: %d", len(physicalTableIDs), cnt)) + } + } else if cnt != 1 { + panic("should not happened" + fmt.Sprintf("expect count: %d, real count: %d", 1, cnt)) + } +} + +func checkRangeCntByTableIDsAndIndexIDs(partitionTableIDs []int64, indexIDs []int64, cnt int64) { + if len(indexIDs) == 0 { + return + } + expectedCnt := len(indexIDs) + if len(partitionTableIDs) > 0 { + expectedCnt *= len(partitionTableIDs) + } + if expectedCnt != int(cnt) { + panic("should not happened" + fmt.Sprintf("expect count: %d, real count: %d", expectedCnt, cnt)) + } +} + +func (d *ddl) checkDeleteRangeCnt(job *model.Job) { + sctx, _ := d.sessPool.get() + s, _ := sctx.(sqlexec.SQLExecutor) + defer func() { + d.sessPool.put(sctx) + }() + + query := `select sum(cnt) from + (select count(1) cnt from mysql.gc_delete_range where job_id = %? union all + select count(1) cnt from mysql.gc_delete_range_done where job_id = %?) as gdr;` + rs, err := s.ExecuteInternal(context.TODO(), query, job.ID, job.ID) + if err != nil { + if strings.Contains(err.Error(), "Not Supported") { + return + } + panic(err) + } + defer func() { + _ = rs.Close() + }() + req := rs.NewChunk(nil) + err = rs.Next(context.TODO(), req) + if err != nil { + panic("should not happened, err:" + err.Error()) + } + cnt, _ := req.GetRow(0).GetMyDecimal(0).ToInt() + + switch job.Type { + case model.ActionDropSchema: + var tableIDs []int64 + if err := job.DecodeArgs(&tableIDs); err != nil { + panic("should not happened") + } + if len(tableIDs) != int(cnt) { + panic("should not happened" + fmt.Sprintf("expect count: %d, real count: %d", len(tableIDs), cnt)) + } + case model.ActionDropTable, model.ActionTruncateTable: + var startKey kv.Key + var physicalTableIDs []int64 + var ruleIDs []string + if err := job.DecodeArgs(&startKey, &physicalTableIDs, &ruleIDs); err != nil { + panic("should not happened") + } + checkRangeCntByTableIDs(physicalTableIDs, cnt) + case model.ActionDropTablePartition, model.ActionTruncateTablePartition: + var physicalTableIDs []int64 + if err := job.DecodeArgs(&physicalTableIDs); err != nil { + panic("should not happened") + } + if len(physicalTableIDs) != int(cnt) { + panic("should not happened" + fmt.Sprintf("expect count: %d, real count: %d", len(physicalTableIDs), cnt)) + } + case model.ActionAddIndex, model.ActionAddPrimaryKey: + var indexID int64 + var partitionIDs []int64 + if err := job.DecodeArgs(&indexID, &partitionIDs); err != nil { + panic("should not happened") + } + checkRangeCntByTableIDs(partitionIDs, cnt) + case model.ActionDropIndex, model.ActionDropPrimaryKey: + var indexName interface{} + var indexID int64 + var partitionIDs []int64 + if err := job.DecodeArgs(&indexName, &indexID, &partitionIDs); err != nil { + panic("should not happened") + } + checkRangeCntByTableIDsAndIndexIDs(partitionIDs, []int64{indexID}, cnt) + case model.ActionDropColumn: + var colName model.CIStr + var indexIDs []int64 + var partitionIDs []int64 + if err := job.DecodeArgs(&colName, &indexIDs, &partitionIDs); err != nil { + panic("should not happened") + } + checkRangeCntByTableIDsAndIndexIDs(partitionIDs, indexIDs, cnt) + case model.ActionModifyColumn: + var indexIDs []int64 + var partitionIDs []int64 + if err := job.DecodeArgs(&indexIDs, &partitionIDs); err != nil { + panic("should not happened") + } + checkRangeCntByTableIDsAndIndexIDs(partitionIDs, indexIDs, cnt) + } +} + +// checkHistoryJobInTest does some sanity check to make sure something is correct after DDL complete. +// It's only check during the test environment, so it would panic directly. +// These checks may be controlled by configuration in the future. +func (d *ddl) checkHistoryJobInTest(ctx sessionctx.Context, historyJob *model.Job) { + if !(flag.Lookup("test.v") != nil || flag.Lookup("check.v") != nil) { + return + } + + // Check delete range. + if jobNeedGC(historyJob) { + d.checkDeleteRangeCnt(historyJob) + } + + // Check binlog. + if historyJob.BinlogInfo.FinishedTS == 0 { + panic(fmt.Sprintf("job ID %d, BinlogInfo.FinishedTS is 0", historyJob.ID)) + } + + // Check DDL query. + switch historyJob.Type { + case model.ActionUpdateTiFlashReplicaStatus, model.ActionUnlockTable: + if historyJob.Query != "" { + panic(fmt.Sprintf("job ID %d, type %s, query %s", historyJob.ID, historyJob.Type.String(), historyJob.Query)) + } + return + default: + if historyJob.Query == "skip" { + // Skip the check if the test explicitly set the query. + return + } + } + p := parser.New() + p.SetSQLMode(ctx.GetSessionVars().SQLMode) + p.SetParserConfig(ctx.GetSessionVars().BuildParserConfig()) + stmt, _, err := p.ParseSQL(historyJob.Query) + if err != nil { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s, err %s", historyJob.ID, historyJob.Query, err.Error())) + } + if len(stmt) != 1 && historyJob.Type != model.ActionCreateTables { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + for _, st := range stmt { + switch historyJob.Type { + case model.ActionCreatePlacementPolicy: + if _, ok := st.(*ast.CreatePlacementPolicyStmt); !ok { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + case model.ActionCreateTable: + if _, ok := st.(*ast.CreateTableStmt); !ok { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + case model.ActionCreateSchema: + if _, ok := st.(*ast.CreateDatabaseStmt); !ok { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + case model.ActionCreateTables: + _, isCreateTable := st.(*ast.CreateTableStmt) + _, isCreateSeq := st.(*ast.CreateSequenceStmt) + _, isCreateView := st.(*ast.CreateViewStmt) + if !isCreateTable && !isCreateSeq && !isCreateView { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + default: + if _, ok := st.(ast.DDLNode); !ok { + panic(fmt.Sprintf("job ID %d, parse ddl job failed, query %s", historyJob.ID, historyJob.Query)) + } + } + } +} diff --git a/ddl/schema.go b/ddl/schema.go index 7604037addd40..53acfb77cd072 100644 --- a/ddl/schema.go +++ b/ddl/schema.go @@ -142,11 +142,8 @@ func onModifySchemaCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ } func onModifySchemaDefaultPlacement(t *meta.Meta, job *model.Job) (ver int64, _ error) { - var ( - placementPolicyRef *model.PolicyRefInfo - directPlacementOpts *model.PlacementSettings - ) - if err := job.DecodeArgs(&placementPolicyRef, &directPlacementOpts); err != nil { + var placementPolicyRef *model.PolicyRefInfo + if err := job.DecodeArgs(&placementPolicyRef); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } @@ -162,15 +159,13 @@ func onModifySchemaDefaultPlacement(t *meta.Meta, job *model.Job) (ver int64, _ // Notice: dbInfo.DirectPlacementOpts and dbInfo.PlacementPolicyRef can not be both not nil, which checked before constructing ddl job. // So that we can just check the two situation that do not need ddl: 1. DB.DP == DDL.DP && nil == nil 2. nil == nil && DB.PP == DDL.PP - if (directPlacementOpts != nil && dbInfo.DirectPlacementOpts != nil && *dbInfo.DirectPlacementOpts == *directPlacementOpts) || - (placementPolicyRef != nil && dbInfo.PlacementPolicyRef != nil && *dbInfo.PlacementPolicyRef == *placementPolicyRef) { + if placementPolicyRef != nil && dbInfo.PlacementPolicyRef != nil && *dbInfo.PlacementPolicyRef == *placementPolicyRef { job.FinishDBJob(model.JobStateDone, model.StatePublic, ver, dbInfo) return ver, nil } // If placementPolicyRef and directPlacementOpts are both nil, And placement of dbInfo is not nil, it will remove all placement options. dbInfo.PlacementPolicyRef = placementPolicyRef - dbInfo.DirectPlacementOpts = directPlacementOpts if err = t.UpdateDatabase(dbInfo); err != nil { return ver, errors.Trace(err) diff --git a/ddl/schema_test.go b/ddl/schema_test.go index 2ad14b417d8ec..0b99510974589 100644 --- a/ddl/schema_test.go +++ b/ddl/schema_test.go @@ -19,7 +19,6 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" @@ -31,16 +30,6 @@ import ( "github.com/stretchr/testify/require" ) -var _ = Suite(&testSchemaSuite{}) - -type testSchemaSuite struct{} - -func (s *testSchemaSuite) SetUpSuite(c *C) { -} - -func (s *testSchemaSuite) TearDownSuite(c *C) { -} - func testSchemaInfo(d *ddl, name string) (*model.DBInfo, error) { dbInfo := &model.DBInfo{ Name: model.NewCIStr(name), @@ -53,36 +42,19 @@ func testSchemaInfo(d *ddl, name string) (*model.DBInfo, error) { return dbInfo, nil } -func testCreateSchema(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - Type: model.ActionCreateSchema, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{dbInfo}, - } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - - v := getSchemaVer(c, ctx) - dbInfo.State = model.StatePublic - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo}) - dbInfo.State = model.StateNone - return job -} - -func testCreateSchemaT(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) *model.Job { +func testCreateSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, Type: model.ActionCreateSchema, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{dbInfo}, } - err := d.doDDLJob(ctx, job) - require.NoError(t, err) + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) - v := getSchemaVerT(t, ctx) + v := getSchemaVer(t, ctx) dbInfo.State = model.StatePublic - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo}) dbInfo.State = model.StateNone return job } @@ -95,25 +67,18 @@ func buildDropSchemaJob(dbInfo *model.DBInfo) *model.Job { } } -func testDropSchema(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) (*model.Job, int64) { +func testDropSchema(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) (*model.Job, int64) { job := buildDropSchemaJob(dbInfo) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - ver := getSchemaVer(c, ctx) - return job, ver -} - -func testDropSchemaT(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo) (*model.Job, int64) { - job := buildDropSchemaJob(dbInfo) - err := d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) require.NoError(t, err) - ver := getSchemaVerT(t, ctx) + ver := getSchemaVer(t, ctx) return job, ver } -func isDDLJobDone(c *C, t *meta.Meta) bool { +func isDDLJobDone(test *testing.T, t *meta.Meta) bool { job, err := t.GetDDLJobByIdx(0) - c.Assert(err, IsNil) + require.NoError(test, err) if job == nil { return true } @@ -122,29 +87,29 @@ func isDDLJobDone(c *C, t *meta.Meta) bool { return false } -func testCheckSchemaState(c *C, d *ddl, dbInfo *model.DBInfo, state model.SchemaState) { +func testCheckSchemaState(test *testing.T, d *ddl, dbInfo *model.DBInfo, state model.SchemaState) { isDropped := true for { err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { t := meta.NewMeta(txn) info, err := t.GetDatabase(dbInfo.ID) - c.Assert(err, IsNil) + require.NoError(test, err) if state == model.StateNone { - isDropped = isDDLJobDone(c, t) + isDropped = isDDLJobDone(test, t) if !isDropped { return nil } - c.Assert(info, IsNil) + require.Nil(test, info) return nil } - c.Assert(info.Name, DeepEquals, dbInfo.Name) - c.Assert(info.State, Equals, state) + require.Equal(test, info.Name, dbInfo.Name) + require.Equal(test, info.State, state) return nil }) - c.Assert(err, IsNil) + require.NoError(test, err) if isDropped { break @@ -152,60 +117,60 @@ func testCheckSchemaState(c *C, d *ddl, dbInfo *model.DBInfo, state model.Schema } } -func (s *testSchemaSuite) TestSchema(c *C) { - store := testCreateStore(c, "test_schema") +func ExportTestSchema(t *testing.T) { + store := createMockStore(t) defer func() { err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, err) }() d, err := testNewDDLAndStart( context.Background(), WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() ctx := testNewContext(d) dbInfo, err := testSchemaInfo(d, "test_schema") - c.Assert(err, IsNil) + require.NoError(t, err) // create a database. - job := testCreateSchema(c, ctx, d, dbInfo) - testCheckSchemaState(c, d, dbInfo, model.StatePublic) - testCheckJobDone(c, d, job, true) + job := testCreateSchema(t, ctx, d, dbInfo) + testCheckSchemaState(t, d, dbInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) /*** to drop the schema with two tables. ***/ // create table t with 100 records. tblInfo1, err := testTableInfo(d, "t", 3) - c.Assert(err, IsNil) - tJob1 := testCreateTable(c, ctx, d, dbInfo, tblInfo1) - testCheckTableState(c, d, dbInfo, tblInfo1, model.StatePublic) - testCheckJobDone(c, d, tJob1, true) - tbl1 := testGetTable(c, d, dbInfo.ID, tblInfo1.ID) + require.NoError(t, err) + tJob1 := testCreateTable(t, ctx, d, dbInfo, tblInfo1) + testCheckTableState(t, d, dbInfo, tblInfo1, model.StatePublic) + testCheckJobDone(t, d, tJob1, true) + tbl1 := testGetTable(t, d, dbInfo.ID, tblInfo1.ID) for i := 1; i <= 100; i++ { _, err := tbl1.AddRecord(ctx, types.MakeDatums(i, i, i)) - c.Assert(err, IsNil) + require.NoError(t, err) } // create table t1 with 1034 records. tblInfo2, err := testTableInfo(d, "t1", 3) - c.Assert(err, IsNil) - tJob2 := testCreateTable(c, ctx, d, dbInfo, tblInfo2) - testCheckTableState(c, d, dbInfo, tblInfo2, model.StatePublic) - testCheckJobDone(c, d, tJob2, true) - tbl2 := testGetTable(c, d, dbInfo.ID, tblInfo2.ID) + require.NoError(t, err) + tJob2 := testCreateTable(t, ctx, d, dbInfo, tblInfo2) + testCheckTableState(t, d, dbInfo, tblInfo2, model.StatePublic) + testCheckJobDone(t, d, tJob2, true) + tbl2 := testGetTable(t, d, dbInfo.ID, tblInfo2.ID) for i := 1; i <= 1034; i++ { _, err := tbl2.AddRecord(ctx, types.MakeDatums(i, i, i)) - c.Assert(err, IsNil) + require.NoError(t, err) } - job, v := testDropSchema(c, ctx, d, dbInfo) - testCheckSchemaState(c, d, dbInfo, model.StateNone) + job, v := testDropSchema(t, ctx, d, dbInfo) + testCheckSchemaState(t, d, dbInfo, model.StateNone) ids := make(map[int64]struct{}) ids[tblInfo1.ID] = struct{}{} ids[tblInfo2.ID] = struct{}{} - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo, tblIDs: ids}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, db: dbInfo, tblIDs: ids}) // Drop a non-existent database. job = &model.Job{ @@ -213,25 +178,26 @@ func (s *testSchemaSuite) TestSchema(c *C) { Type: model.ActionDropSchema, BinlogInfo: &model.HistoryInfo{}, } - err = d.doDDLJob(ctx, job) - c.Assert(terror.ErrorEqual(err, infoschema.ErrDatabaseDropExists), IsTrue, Commentf("err %v", err)) + ctx.SetValue(sessionctx.QueryString, "skip") + err = d.DoDDLJob(ctx, job) + require.True(t, terror.ErrorEqual(err, infoschema.ErrDatabaseDropExists), "err %v", err) // Drop a database without a table. dbInfo1, err := testSchemaInfo(d, "test1") - c.Assert(err, IsNil) - job = testCreateSchema(c, ctx, d, dbInfo1) - testCheckSchemaState(c, d, dbInfo1, model.StatePublic) - testCheckJobDone(c, d, job, true) - job, _ = testDropSchema(c, ctx, d, dbInfo1) - testCheckSchemaState(c, d, dbInfo1, model.StateNone) - testCheckJobDone(c, d, job, false) + require.NoError(t, err) + job = testCreateSchema(t, ctx, d, dbInfo1) + testCheckSchemaState(t, d, dbInfo1, model.StatePublic) + testCheckJobDone(t, d, job, true) + job, _ = testDropSchema(t, ctx, d, dbInfo1) + testCheckSchemaState(t, d, dbInfo1, model.StateNone) + testCheckJobDone(t, d, job, false) } -func (s *testSchemaSuite) TestSchemaWaitJob(c *C) { - store := testCreateStore(c, "test_schema_wait") +func TestSchemaWaitJob(t *testing.T) { + store := createMockStore(t) defer func() { err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, err) }() d1, err := testNewDDLAndStart( @@ -239,23 +205,23 @@ func (s *testSchemaSuite) TestSchemaWaitJob(c *C) { WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d1.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() - testCheckOwner(c, d1, true) + testCheckOwner(t, d1, true) d2, err := testNewDDLAndStart( context.Background(), WithStore(store), WithLease(testLease*4), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := d2.Stop() - c.Assert(err, IsNil) + require.NoError(t, err) }() ctx := testNewContext(d2) @@ -263,17 +229,17 @@ func (s *testSchemaSuite) TestSchemaWaitJob(c *C) { d2.ownerManager.RetireOwner() dbInfo, err := testSchemaInfo(d2, "test_schema") - c.Assert(err, IsNil) - testCreateSchema(c, ctx, d2, dbInfo) - testCheckSchemaState(c, d2, dbInfo, model.StatePublic) + require.NoError(t, err) + testCreateSchema(t, ctx, d2, dbInfo) + testCheckSchemaState(t, d2, dbInfo, model.StatePublic) // d2 must not be owner. - c.Assert(d2.ownerManager.IsOwner(), IsFalse) + require.False(t, d2.ownerManager.IsOwner()) genIDs, err := d2.genGlobalIDs(1) - c.Assert(err, IsNil) + require.NoError(t, err) schemaID := genIDs[0] - doDDLJobErr(c, schemaID, 0, model.ActionCreateSchema, []interface{}{dbInfo}, ctx, d2) + doDDLJobErr(t, schemaID, 0, model.ActionCreateSchema, []interface{}{dbInfo}, ctx, d2) } func testGetSchemaInfoWithError(d *ddl, schemaID int64) (*model.DBInfo, error) { @@ -292,3 +258,31 @@ func testGetSchemaInfoWithError(d *ddl, schemaID int64) (*model.DBInfo, error) { } return dbInfo, nil } + +func doDDLJobErr(t *testing.T, schemaID, tableID int64, tp model.ActionType, args []interface{}, ctx sessionctx.Context, d *ddl) *model.Job { + job := &model.Job{ + SchemaID: schemaID, + TableID: tableID, + Type: tp, + Args: args, + BinlogInfo: &model.HistoryInfo{}, + } + // TODO: check error detail + require.Error(t, d.DoDDLJob(ctx, job)) + testCheckJobCancelled(t, d.store, job, nil) + + return job +} + +func testCheckJobCancelled(t *testing.T, store kv.Storage, job *model.Job, state *model.SchemaState) { + require.NoError(t, kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + historyJob, err := m.GetHistoryDDLJob(job.ID) + require.NoError(t, err) + require.True(t, historyJob.IsCancelled() || historyJob.IsRollbackDone(), "history job %s", historyJob) + if state != nil { + require.Equal(t, historyJob.SchemaState, *state) + } + return nil + })) +} diff --git a/ddl/sequence.go b/ddl/sequence.go index 2b6ebb08c3a1d..e2ba2d620cc6b 100644 --- a/ddl/sequence.go +++ b/ddl/sequence.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/util/dbterror" math2 "github.com/pingcap/tidb/util/math" ) @@ -65,7 +66,7 @@ func onCreateSequence(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ err asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateSequence, TableInfo: tbInfo}) return ver, nil default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("sequence", tbInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("sequence", tbInfo.State) } } @@ -105,7 +106,9 @@ func handleSequenceOptions(seqOptions []*ast.SequenceOption, sequenceInfo *model maxSetFlag = true case ast.SequenceCache: sequenceInfo.CacheValue = op.IntValue + sequenceInfo.Cache = true case ast.SequenceNoCache: + sequenceInfo.CacheValue = 0 sequenceInfo.Cache = false case ast.SequenceCycle: sequenceInfo.Cycle = true @@ -140,13 +143,13 @@ func handleSequenceOptions(seqOptions []*ast.SequenceOption, sequenceInfo *model } func validateSequenceOptions(seqInfo *model.SequenceInfo) bool { - // To ensure that cache * increment will never overflows. + // To ensure that cache * increment will never overflow. var maxIncrement int64 if seqInfo.Increment == 0 { // Increment shouldn't be set as 0. return false } - if seqInfo.CacheValue <= 0 { + if seqInfo.Cache && seqInfo.CacheValue <= 0 { // Cache value should be bigger than 0. return false } @@ -176,12 +179,12 @@ func buildSequenceInfo(stmt *ast.CreateSequenceStmt, ident ast.Ident) (*model.Se case ast.TableOptionEngine: // TableOptionEngine will always be 'InnoDB', thus we do nothing in this branch to avoid error happening. default: - return nil, ErrSequenceUnsupportedTableOption.GenWithStackByArgs(op.StrValue) + return nil, dbterror.ErrSequenceUnsupportedTableOption.GenWithStackByArgs(op.StrValue) } } handleSequenceOptions(stmt.SeqOptions, sequenceInfo) if !validateSequenceOptions(sequenceInfo) { - return nil, ErrSequenceInvalidData.GenWithStackByArgs(ident.Schema.L, ident.Name.L) + return nil, dbterror.ErrSequenceInvalidData.GenWithStackByArgs(ident.Schema.L, ident.Name.L) } return sequenceInfo, nil } @@ -205,7 +208,9 @@ func alterSequenceOptions(sequenceOptions []*ast.SequenceOption, ident ast.Ident oldSequence.MaxValue = op.IntValue case ast.SequenceCache: oldSequence.CacheValue = op.IntValue + oldSequence.Cache = true case ast.SequenceNoCache: + oldSequence.CacheValue = 0 oldSequence.Cache = false case ast.SequenceCycle: oldSequence.Cycle = true @@ -219,7 +224,7 @@ func alterSequenceOptions(sequenceOptions []*ast.SequenceOption, ident ast.Ident } } if !validateSequenceOptions(oldSequence) { - return false, 0, ErrSequenceInvalidData.GenWithStackByArgs(ident.Schema.L, ident.Name.L) + return false, 0, dbterror.ErrSequenceInvalidData.GenWithStackByArgs(ident.Schema.L, ident.Name.L) } if restartWithFlag { return true, restartValue, nil diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index b121586d33629..2ec8a77bf5270 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -16,24 +16,26 @@ package ddl_test import ( "strconv" + "testing" + "time" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/ddl" mysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testSequenceSuite{&testDBSuite{}}) - -type testSequenceSuite struct{ *testDBSuite } - -func (s *testSequenceSuite) TestCreateSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") tk.MustGetErrCode("create sequence `seq `", mysql.ErrWrongTableName) @@ -62,40 +64,44 @@ func (s *testSequenceSuite) TestCreateSequence(c *C) { tk.MustGetErrCode("create sequence seq CHARSET=utf8", mysql.ErrSequenceUnsupportedTableOption) _, err := tk.Exec("create sequence seq comment=\"test\"") - c.Assert(err, IsNil) - - sequenceTable := testGetTableByName(c, s.s, "test", "seq") - c.Assert(sequenceTable.Meta().IsSequence(), Equals, true) - c.Assert(sequenceTable.Meta().Sequence.Increment, Equals, model.DefaultSequenceIncrementValue) - c.Assert(sequenceTable.Meta().Sequence.Start, Equals, model.DefaultPositiveSequenceStartValue) - c.Assert(sequenceTable.Meta().Sequence.MinValue, Equals, model.DefaultPositiveSequenceMinValue) - c.Assert(sequenceTable.Meta().Sequence.MaxValue, Equals, model.DefaultPositiveSequenceMaxValue) - c.Assert(sequenceTable.Meta().Sequence.Cache, Equals, true) - c.Assert(sequenceTable.Meta().Sequence.CacheValue, Equals, model.DefaultSequenceCacheValue) - c.Assert(sequenceTable.Meta().Sequence.Cycle, Equals, false) + require.NoError(t, err) + + sequenceTable := external.GetTableByName(t, tk, "test", "seq") + + require.Equal(t, true, sequenceTable.Meta().IsSequence()) + require.Equal(t, model.DefaultSequenceIncrementValue, sequenceTable.Meta().Sequence.Increment) + require.Equal(t, model.DefaultPositiveSequenceStartValue, sequenceTable.Meta().Sequence.Start) + require.Equal(t, model.DefaultPositiveSequenceMinValue, sequenceTable.Meta().Sequence.MinValue) + require.Equal(t, model.DefaultPositiveSequenceMaxValue, sequenceTable.Meta().Sequence.MaxValue) + require.Equal(t, true, sequenceTable.Meta().Sequence.Cache) + require.Equal(t, model.DefaultSequenceCacheValue, sequenceTable.Meta().Sequence.CacheValue) + require.Equal(t, false, sequenceTable.Meta().Sequence.Cycle) // Test create privilege. tk.MustExec("drop user if exists myuser@localhost") tk.MustExec("create user myuser@localhost") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + tk1.SetSession(se) // grant the myuser the access to database test. tk.MustExec("grant select on test.* to 'myuser'@'localhost'") tk1.MustExec("use test") _, err = tk1.Exec("create sequence my_seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]CREATE command denied to user 'myuser'@'localhost' for table 'my_seq'") + require.Error(t, err) + require.EqualError(t, err, "[planner:1142]CREATE command denied to user 'myuser'@'localhost' for table 'my_seq'") } // Test for sequence still works with a infoschema attached by temporary table -func (s *testSequenceSuite) TestIssue28881(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue28881(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists s") tk.MustExec("create sequence s") @@ -106,8 +112,11 @@ func (s *testSequenceSuite) TestIssue28881(c *C) { tk.MustQuery("select lastval(s)").Check(testkit.Rows("1")) } -func (s *testSequenceSuite) TestDropSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") @@ -117,49 +126,49 @@ func (s *testSequenceSuite) TestDropSequence(c *C) { // Test non-existed sequence can't drop successfully. tk.MustExec("create sequence seq") _, err := tk.Exec("drop sequence seq, seq2") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'test.seq2'") + require.Error(t, err) + require.EqualError(t, err, "[schema:4139]Unknown SEQUENCE: 'test.seq2'") // Test the specified object is not sequence. tk.MustExec("create table seq3 (a int)") _, err = tk.Exec("drop sequence seq3") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, ddl.ErrWrongObject), IsTrue) + require.Error(t, err) + require.True(t, terror.ErrorEqual(err, dbterror.ErrWrongObject)) // Test schema is not exist. _, err = tk.Exec("drop sequence unknown.seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'unknown.seq'") + require.Error(t, err) + require.EqualError(t, err, "[schema:4139]Unknown SEQUENCE: 'unknown.seq'") // Test drop sequence successfully. tk.MustExec("create sequence seq") _, err = tk.Exec("drop sequence seq") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("drop sequence seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'test.seq'") + require.Error(t, err) + require.EqualError(t, err, "[schema:4139]Unknown SEQUENCE: 'test.seq'") // Test drop table when the object is a sequence. tk.MustExec("create sequence seq") _, err = tk.Exec("drop table seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.seq'") + require.Error(t, err) + require.EqualError(t, err, "[schema:1051]Unknown table 'test.seq'") // Test drop view when the object is a sequence. _, err = tk.Exec("drop view seq") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, ddl.ErrWrongObject), IsTrue) + require.Error(t, err) + require.True(t, terror.ErrorEqual(err, dbterror.ErrWrongObject)) tk.MustExec("drop sequence seq") // Test drop privilege. tk.MustExec("drop user if exists myuser@localhost") tk.MustExec("create user myuser@localhost") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + tk1.SetSession(se) // grant the myuser the access to database test. tk.MustExec("create sequence my_seq") @@ -167,16 +176,19 @@ func (s *testSequenceSuite) TestDropSequence(c *C) { tk1.MustExec("use test") _, err = tk1.Exec("drop sequence my_seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]DROP command denied to user 'myuser'@'localhost' for table 'my_seq'") + require.Error(t, err) + require.EqualError(t, err, "[planner:1142]DROP command denied to user 'myuser'@'localhost' for table 'my_seq'") // Test for `drop sequence if exists`. tk.MustExec("drop sequence if exists seq_if_exists") tk.MustQuery("show warnings;").Check(testkit.Rows("Note 4139 Unknown SEQUENCE: 'test.seq_if_exists'")) } -func (s *testSequenceSuite) TestShowCreateSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop sequence if exists seq") @@ -187,11 +199,11 @@ func (s *testSequenceSuite) TestShowCreateSequence(c *C) { tk.MustExec("drop user if exists myuser@localhost") tk.MustExec("create user myuser@localhost") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + tk1.SetSession(se) // Grant the myuser the access to table t in database test, but sequence seq. tk.MustExec("grant select on test.t to 'myuser'@'localhost'") @@ -199,8 +211,8 @@ func (s *testSequenceSuite) TestShowCreateSequence(c *C) { tk1.MustExec("use test") tk1.MustExec("show create table t") _, err = tk1.Exec("show create sequence seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]SHOW command denied to user 'myuser'@'localhost' for table 'seq'") + require.Error(t, err) + require.EqualError(t, err, "[planner:1142]SHOW command denied to user 'myuser'@'localhost' for table 'seq'") // Grant the myuser the access to sequence seq in database test. tk.MustExec("grant select on test.seq to 'myuser'@'localhost'") @@ -244,8 +256,8 @@ func (s *testSequenceSuite) TestShowCreateSequence(c *C) { tk.MustExec("drop sequence if exists seq") tk.MustExec("create table seq (a int)") err = tk.QueryToErr("show create sequence seq") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[executor:1347]'test.seq' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[executor:1347]'test.seq' is not SEQUENCE") tk.MustExec("drop table if exists seq") // Test use the show create sequence result to create sequence. @@ -256,8 +268,11 @@ func (s *testSequenceSuite) TestShowCreateSequence(c *C) { tk.MustExec(showString) } -func (s *testSequenceSuite) TestSequenceAsDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceAsDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") tk.MustExec("create sequence seq") @@ -295,8 +310,11 @@ func (s *testSequenceSuite) TestSequenceAsDefaultValue(c *C) { tk.MustExec("alter table t5 change column c c int default next value for seq") } -func (s *testSequenceSuite) TestSequenceFunction(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceFunction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") tk.MustExec("drop sequence if exists seq1") @@ -372,7 +390,7 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select nextval(seq)").Check(testkit.Rows("3")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("8")) err := tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") tk.MustExec("drop sequence if exists seq") tk.MustExec("create sequence seq increment = 3 start = 3 maxvalue = 9 nocycle") @@ -380,7 +398,7 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select nextval(seq)").Check(testkit.Rows("6")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("9")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") // test negative-growth sequence tk.MustExec("drop sequence if exists seq") @@ -408,14 +426,14 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-2")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-6")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") tk.MustExec("drop sequence if exists seq") tk.MustExec("create sequence seq increment = -3 start = 2 minvalue -2 maxvalue 10") tk.MustQuery("select nextval(seq)").Check(testkit.Rows("2")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-1")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") // test sequence setval function. tk.MustExec("drop sequence if exists seq") @@ -441,14 +459,14 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select setval(seq, 8)").Check(testkit.Rows("8")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("10")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") tk.MustQuery("select setval(seq, 11)").Check(testkit.Rows("11")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") // set value can be bigger than maxvalue. tk.MustQuery("select setval(seq, 100)").Check(testkit.Rows("100")) err = tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") // test setval in second cache round. tk.MustExec("drop sequence if exists seq") @@ -458,22 +476,22 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select setval(seq, 20)").Check(testkit.Rows("20")) // the next value will not be base on next value. tk.MustQuery("select nextval(seq)").Check(testkit.Rows("25")) - sequenceTable := testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable := external.GetTableByName(t, tk, "test", "seq") tc, ok := sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round := tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(95)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(95), end) + require.Equal(t, int64(0), round) // exhausted the sequence first round in cycle. tk.MustQuery("select setval(seq, 95)").Check(testkit.Rows("95")) // make sequence alloc the next batch. tk.MustQuery("select nextval(seq)").Check(testkit.Rows("1")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(91)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(91), end) + require.Equal(t, int64(1), round) tk.MustQuery("select setval(seq, 15)").Check(testkit.Rows("15")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("21")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("31")) @@ -483,41 +501,41 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select setval(seq, -20)").Check(testkit.Rows("")) tk.MustQuery("select setval(seq, 20)").Check(testkit.Rows("20")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-10")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(-6)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(-6), end) + require.Equal(t, int64(1), round) // test setval in negative-growth sequence. tk.MustExec("drop sequence if exists seq") tk.MustExec("create sequence seq increment -3 start 5 maxvalue 10 minvalue -10 cache 3 cycle") tk.MustQuery("select nextval(seq)").Check(testkit.Rows("5")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(-1)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(-1), end) + require.Equal(t, int64(0), round) // exhausted the sequence first cache batch. tk.MustQuery("select setval(seq, -2)").Check(testkit.Rows("-2")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-4")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(-10)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(-10), end) + require.Equal(t, int64(0), round) // exhausted the sequence second cache batch. tk.MustQuery("select setval(seq, -10)").Check(testkit.Rows("-10")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("10")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(4)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(4), end) + require.Equal(t, int64(1), round) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("7")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("4")) // test the sequence negative rebase. @@ -529,12 +547,12 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select setval(seq, 20)").Check(testkit.Rows("")) tk.MustQuery("select setval(seq, -20)").Check(testkit.Rows("-20")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("10")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(6)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(6), end) + require.Equal(t, int64(1), round) // test sequence lastval function. tk.MustExec("drop sequence if exists seq") @@ -557,34 +575,34 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustExec("create sequence seq increment 3 start 3 maxvalue 14 cache 3 cycle") tk.MustQuery("select lastval(seq)").Check(testkit.Rows("")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("3")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(9)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(9), end) + require.Equal(t, int64(0), round) // invalidate the current sequence cache. tk.MustQuery("select setval(seq, 10)").Check(testkit.Rows("10")) tk.MustQuery("select lastval(seq)").Check(testkit.Rows("3")) // trigger the next sequence cache. tk.MustQuery("select nextval(seq)").Check(testkit.Rows("12")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(14)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(14), end) + require.Equal(t, int64(0), round) // invalidate the current sequence cache. tk.MustQuery("select setval(seq, 13)").Check(testkit.Rows("13")) tk.MustQuery("select lastval(seq)").Check(testkit.Rows("12")) // trigger the next sequence cache. tk.MustQuery("select nextval(seq)").Check(testkit.Rows("1")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(7)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(7), end) + require.Equal(t, int64(1), round) tk.MustQuery("select lastval(seq)").Check(testkit.Rows("1")) // test lastval in negative-growth sequence cycle and cache. @@ -592,22 +610,22 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustExec("create sequence seq increment -3 start -2 maxvalue 10 minvalue -10 cache 3 cycle") tk.MustQuery("select lastval(seq)").Check(testkit.Rows("")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-2")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(-8)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(-8), end) + require.Equal(t, int64(0), round) // invalidate the current sequence cache. tk.MustQuery("select setval(seq, -8)").Check(testkit.Rows("-8")) tk.MustQuery("select lastval(seq)").Check(testkit.Rows("-2")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("10")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(4)) - c.Assert(round, Equals, int64(1)) + require.Equal(t, int64(4), end) + require.Equal(t, int64(1), round) tk.MustQuery("select lastval(seq)").Check(testkit.Rows("10")) tk.MustExec("drop sequence if exists seq") @@ -615,12 +633,12 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustQuery("select nextval(seq)").Check(testkit.Rows("1")) tk.MustQuery("select setval(seq, -8)").Check(testkit.Rows("-8")) tk.MustQuery("select nextval(seq)").Check(testkit.Rows("-9")) - sequenceTable = testGetTableByName(c, tk.Se, "test", "seq") + sequenceTable = external.GetTableByName(t, tk, "test", "seq") tc, ok = sequenceTable.(*tables.TableCommon) - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() - c.Assert(end, Equals, int64(-10)) - c.Assert(round, Equals, int64(0)) + require.Equal(t, int64(-10), end) + require.Equal(t, int64(0), round) // Test the sequence seek formula will overflow Int64. tk.MustExec("drop sequence if exists seq") @@ -644,25 +662,25 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustExec("drop view if exists seq1") tk.MustExec("create table seq(a int)") _, err = tk.Exec("select nextval(seq)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq' is not SEQUENCE") _, err = tk.Exec("select lastval(seq)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq' is not SEQUENCE") _, err = tk.Exec("select setval(seq, 10)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq' is not SEQUENCE") tk.MustExec("create view seq1 as select * from seq") _, err = tk.Exec("select nextval(seq1)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq1' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq1' is not SEQUENCE") _, err = tk.Exec("select lastval(seq1)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq1' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq1' is not SEQUENCE") _, err = tk.Exec("select setval(seq1, 10)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.seq1' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.seq1' is not SEQUENCE") tk.MustExec("drop sequence if exists seq") tk.MustExec("drop table if exists seq") tk.MustExec("drop view if exists seq") @@ -683,10 +701,10 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { // test the current value already satisfied setval in other session. tk.MustExec("create sequence seq") tk.MustQuery("select setval(seq, 100)").Check(testkit.Rows("100")) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - tk1 := testkit.NewTestKit(c, s.store) - tk1.Se = se + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + tk1 := testkit.NewTestKit(t, store) + tk1.SetSession(se) tk1.MustExec("use test") tk1.MustQuery("select setval(seq, 50)").Check(testkit.Rows("")) tk1.MustQuery("select nextval(seq)").Check(testkit.Rows("101")) @@ -711,18 +729,21 @@ func (s *testSequenceSuite) TestSequenceFunction(c *C) { tk.MustExec("insert into t values(1),(2)") tk.MustQuery("select nextval(seq), t.a from t").Check(testkit.Rows("1 1", "2 2")) _, err = tk.Exec("select nextval(t), t.a from t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.t' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.t' is not SEQUENCE") _, err = tk.Exec("select nextval(seq), nextval(t), t.a from t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1347]'test.t' is not SEQUENCE") + require.Error(t, err) + require.EqualError(t, err, "[schema:1347]'test.t' is not SEQUENCE") tk.MustQuery("select nextval(seq)").Check(testkit.Rows("3")) tk.MustExec("drop sequence seq") tk.MustExec("drop table t") } -func (s *testSequenceSuite) TestInsertSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") tk.MustExec("drop table if exists t") @@ -786,11 +807,14 @@ func (s *testSequenceSuite) TestInsertSequence(c *C) { setSQL := "select setval(seq," + strconv.FormatInt(model.DefaultPositiveSequenceMaxValue+1, 10) + ")" tk.MustQuery(setSQL).Check(testkit.Rows("9223372036854775807")) err := tk.QueryToErr("select nextval(seq)") - c.Assert(err.Error(), Equals, "[table:4135]Sequence 'test.seq' has run out") + require.EqualError(t, err, "[table:4135]Sequence 'test.seq' has run out") } -func (s *testSequenceSuite) TestUnflodSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUnflodSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // test insert into select from. tk.MustExec("drop sequence if exists seq") @@ -854,9 +878,11 @@ func (s *testSequenceSuite) TestUnflodSequence(c *C) { // single insert consume: 50.498672ms // after this PR: // single insert consume: 33.213615ms -// Notice: use go test -check.b Benchmarkxxx to test it. -func (s *testSequenceSuite) BenchmarkInsertCacheDefaultExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) +func BenchmarkInsertCacheDefaultExpr(b *testing.B) { + store, clean := testkit.CreateMockStore(b) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(b, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") tk.MustExec("drop table if exists t") @@ -870,14 +896,17 @@ func (s *testSequenceSuite) BenchmarkInsertCacheDefaultExpr(c *C) { sql += ",()" } } - c.ResetTimer() - for i := 0; i < c.N; i++ { + b.ResetTimer() + for i := 0; i < b.N; i++ { tk.MustExec(sql) } } -func (s *testSequenceSuite) TestSequenceFunctionPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceFunctionPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test sequence function privilege. @@ -888,11 +917,11 @@ func (s *testSequenceSuite) TestSequenceFunctionPrivilege(c *C) { tk.MustExec("drop user if exists myuser@localhost") tk.MustExec("create user myuser@localhost") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + tk1.SetSession(se) // grant the myuser the create access to the sequence. tk.MustExec("grant insert on test.t to 'myuser'@'localhost'") @@ -900,22 +929,22 @@ func (s *testSequenceSuite) TestSequenceFunctionPrivilege(c *C) { // INSERT privilege required to use nextval. tk1.MustExec("use test") err = tk1.QueryToErr("select nextval(seq)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") + require.Error(t, err) + require.EqualError(t, err, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") _, err = tk1.Exec("insert into t values()") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") + require.Error(t, err) + require.EqualError(t, err, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") // SELECT privilege required to use lastval. err = tk1.QueryToErr("select lastval(seq)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1142]SELECT command denied to user 'myuser'@'localhost' for table 'seq'") + require.Error(t, err) + require.EqualError(t, err, "[expression:1142]SELECT command denied to user 'myuser'@'localhost' for table 'seq'") // INSERT privilege required to use setval. err = tk1.QueryToErr("select setval(seq, 10)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") + require.Error(t, err) + require.EqualError(t, err, "[expression:1142]INSERT command denied to user 'myuser'@'localhost' for table 'seq'") // grant the myuser the SELECT & UPDATE access to sequence seq. tk.MustExec("grant SELECT, INSERT on test.seq to 'myuser'@'localhost'") @@ -950,8 +979,11 @@ func (s *testSequenceSuite) TestSequenceFunctionPrivilege(c *C) { // So under current situation, TiDB will // [1]: forbid the new added column has sequence as it's default value. // [2]: allow the altered column with sequence as default value. -func (s *testSequenceSuite) TestSequenceDefaultLogic(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceDefaultLogic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") @@ -979,18 +1011,21 @@ func (s *testSequenceSuite) TestSequenceDefaultLogic(c *C) { } // Close issue #17945, sequence cache shouldn't be negative. -func (s *testSequenceSuite) TestSequenceCacheShouldNotBeNegative(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceCacheShouldNotBeNegative(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") _, err := tk.Exec("create sequence seq cache -1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:4136]Sequence 'test.seq' values are conflicting") + require.Error(t, err) + require.EqualError(t, err, "[ddl:4136]Sequence 'test.seq' values are conflicting") _, err = tk.Exec("create sequence seq cache 0") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:4136]Sequence 'test.seq' values are conflicting") + require.Error(t, err) + require.EqualError(t, err, "[ddl:4136]Sequence 'test.seq' values are conflicting") // This will error because // 1: maxvalue = -1 by default @@ -999,14 +1034,17 @@ func (s *testSequenceSuite) TestSequenceCacheShouldNotBeNegative(c *C) { // `seqInfo.CacheValue < (math.MaxInt64-absIncrement)/absIncrement` will // ensure there is enough value for one cache allocation at least. _, err = tk.Exec("create sequence seq INCREMENT -9223372036854775807 cache 1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:4136]Sequence 'test.seq' values are conflicting") + require.Error(t, err) + require.EqualError(t, err, "[ddl:4136]Sequence 'test.seq' values are conflicting") tk.MustExec("create sequence seq cache 1") } -func (s *testSequenceSuite) TestAlterSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists seq") @@ -1063,8 +1101,11 @@ func (s *testSequenceSuite) TestAlterSequence(c *C) { tk.MustExec("drop sequence if exists seq") } -func (s *testSequenceSuite) TestAlterSequencePrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterSequencePrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + session.SetSchemaLease(600 * time.Millisecond) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists my_seq") tk.MustExec("create sequence my_seq") @@ -1073,18 +1114,36 @@ func (s *testSequenceSuite) TestAlterSequencePrivilege(c *C) { tk.MustExec("drop user if exists myuser@localhost") tk.MustExec("create user myuser@localhost") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + tk1.SetSession(se) // grant the myuser the access to database test. tk.MustExec("grant select on test.* to 'myuser'@'localhost'") tk1.MustExec("use test") _, err = tk1.Exec("alter sequence my_seq increment = 2") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]ALTER command denied to user 'myuser'@'localhost' for table 'my_seq'") + require.Error(t, err) + require.EqualError(t, err, "[planner:1142]ALTER command denied to user 'myuser'@'localhost' for table 'my_seq'") tk.MustExec("drop sequence if exists my_seq") } + +func TestDdl_AlterSequenceIssue31265(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create sequence seq cache=1 nocache") + tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB")) + + tk.MustExec("create sequence cache_to_nocache_seq;") + tk.MustExec("alter sequence cache_to_nocache_seq nocache;") + tk.MustQuery("show create sequence cache_to_nocache_seq;").Check(testkit.Rows("cache_to_nocache_seq CREATE SEQUENCE `cache_to_nocache_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB")) + + tk.MustExec("create sequence nocache_to_cache_seq nocache;") + tk.MustExec("alter sequence nocache_to_cache_seq cache 10;") + tk.MustQuery("show create sequence nocache_to_cache_seq;").Check(testkit.Rows("nocache_to_cache_seq CREATE SEQUENCE `nocache_to_cache_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 10 nocycle ENGINE=InnoDB")) +} diff --git a/ddl/serial_test.go b/ddl/serial_test.go index 51dccd346b336..73d08a441e8ee 100644 --- a/ddl/serial_test.go +++ b/ddl/serial_test.go @@ -18,17 +18,17 @@ import ( "context" "fmt" "math" - "strconv" "strings" "sync" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/ddl/util" ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" @@ -40,379 +40,80 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util/admin" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/gcutil" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" - . "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" ) -// Make it serial because config is modified in test cases. -var _ = SerialSuites(&testSerialSuite{}) - -// TODO(tangenta): Move all the parallel tests out of this file. -var _ = Suite(&testIntegrationSuite7{&testIntegrationSuite{}}) - -type testSerialSuite struct { - CommonHandleSuite - store kv.Storage - cluster testutils.Cluster - dom *domain.Domain +func TestTruncateAllPartitions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table partition_table (v int) partition by hash (v) partitions 10") + tk.MustExec("insert into partition_table values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)") + tk.MustExec("alter table partition_table truncate partition all") + tk.MustQuery("select count(*) from partition_table").Check(testkit.Rows("0")) } -func (s *testSerialSuite) SetUpSuite(c *C) { - session.SetSchemaLease(200 * time.Millisecond) - session.DisableStats4Test() - config.UpdateGlobal(func(conf *config.Config) { - // Update config here. - }) - - ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) - - var err error - s.store, err = mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} +func TestIssue23872(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") -func (s *testSerialSuite) TearDownSuite(c *C) { - if s.dom != nil { - s.dom.Close() - } - if s.store != nil { - s.store.Close() + for _, test := range []struct { + sql string + flag uint + }{ + { + "create table t(id smallint,id1 int, primary key (id))", + mysql.NotNullFlag | mysql.PriKeyFlag | mysql.NoDefaultValueFlag, + }, + { + "create table t(a int default 1, primary key(a))", + mysql.NotNullFlag | mysql.PriKeyFlag, + }, + } { + tk.MustExec("drop table if exists t") + tk.MustExec(test.sql) + rs, err := tk.Exec("select * from t") + require.NoError(t, err) + cols := rs.Fields() + require.NoError(t, rs.Close()) + require.Equal(t, test.flag, cols[0].Column.Flag) } } -func (s *testSerialSuite) TestChangeMaxIndexLength(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestChangeMaxIndexLength(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.MaxIndexLength = config.DefMaxOfMaxIndexLength }) - tk.MustExec("drop table if exists t;") - tk.MustExec("drop table if exists t1;") - - tk.MustExec("create table t (c1 varchar(3073), index(c1)) charset = ascii;") - tk.MustExec(fmt.Sprintf("create table t1 (c1 varchar(%d), index(c1)) charset = ascii;", config.DefMaxOfMaxIndexLength)) - _, err := tk.Exec(fmt.Sprintf("create table t2 (c1 varchar(%d), index(c1)) charset = ascii;", config.DefMaxOfMaxIndexLength+1)) - c.Assert(err.Error(), Equals, "[ddl:1071]Specified key was too long; max key length is 12288 bytes") - tk.MustExec("drop table t, t1") -} - -func (s *testIntegrationSuite7) TestPrimaryKey(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_primary_key;") - tk.MustExec("create database test_primary_key;") - tk.MustExec("use test_primary_key;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - - // Test add/drop primary key on a plain table. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int, b varchar(10));") - tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustExec("alter table t add primary key(a) nonclustered;") - tk.MustExec("alter table t drop primary key;") - tk.MustExec("alter table t add primary key(a) nonclustered;") - tk.MustExec("drop index `primary` on t;") - tk.MustExec("alter table t add primary key(a);") // implicit nonclustered - tk.MustExec("drop index `primary` on t;") - tk.MustGetErrCode("drop index `primary` on t;", errno.ErrCantDropFieldOrKey) - - // Test add/drop primary key on a PKIsHandle table. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int, b varchar(10), primary key(a) clustered);") - tk.MustGetErrCode("alter table t drop primary key;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", mysql.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered - tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered - - // Test add/drop primary key on a nonclustered primary key table. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int, b varchar(10), primary key(a) nonclustered);") - tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", errno.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered - tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered - tk.MustExec("alter table t drop primary key;") - - // Test add/drop primary key on a CommonHandle key table. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int, b varchar(10), primary key(b) clustered);") - tk.MustGetErrCode("alter table t drop primary key;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(a) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(a) nonclustered;", errno.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(a);", errno.ErrMultiplePriKey) // implicit nonclustered - tk.MustGetErrCode("alter table t add primary key(b) clustered;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("alter table t add primary key(b) nonclustered;", errno.ErrMultiplePriKey) - tk.MustGetErrCode("alter table t add primary key(b);", errno.ErrMultiplePriKey) // implicit nonclustered - - // Test add/drop primary key when the column&index name is `primary`. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (`primary` int);") - tk.MustExec("alter table t add index (`primary`);") - tk.MustGetErrCode("drop index `primary` on t;", errno.ErrCantDropFieldOrKey) - - // The primary key cannot be invisible, for the case pk_is_handle. - tk.MustExec("drop table if exists t;") - tk.MustGetErrCode("create table t(c1 int not null, primary key(c1) invisible);", errno.ErrPKIndexCantBeInvisible) - tk.MustExec("create table t (a int, b int not null, primary key(a), unique(b) invisible);") - tk.MustExec("drop table t;") -} - -func (s *testIntegrationSuite7) TestDropAutoIncrementIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int(11) not null auto_increment key, b int(11), c bigint, unique key (a, b, c))") - tk.MustExec("alter table t1 drop index a") -} - -func (s *testIntegrationSuite7) TestMultiRegionGetTableEndHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_get_endhandle") - tk.MustExec("create database test_get_endhandle") - tk.MustExec("use test_get_endhandle") - - tk.MustExec("create table t(a bigint PRIMARY KEY, b int)") - var builder strings.Builder - fmt.Fprintf(&builder, "insert into t values ") - for i := 0; i < 1000; i++ { - fmt.Fprintf(&builder, "(%v, %v),", i, i) - } - sql := builder.String() - tk.MustExec(sql[:len(sql)-1]) - - // Get table ID for split. - dom := domain.GetDomain(tk.Se) - is := dom.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - d := s.dom.DDL() - testCtx := newTestMaxTableRowIDContext(c, d, tbl) - - // Split the table. - tableStart := tablecodec.GenTableRecordPrefix(tblID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) - - maxHandle, emptyTable := getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, Equals, kv.IntHandle(999)) - - tk.MustExec("insert into t values(10000, 1000)") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, Equals, kv.IntHandle(10000)) - - tk.MustExec("insert into t values(-1, 1000)") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, Equals, kv.IntHandle(10000)) -} - -func (s *testIntegrationSuite7) TestGetTableEndHandle(c *C) { - // TestGetTableEndHandle test ddl.GetTableMaxHandle method, which will return the max row id of the table. - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_get_endhandle") - tk.MustExec("create database test_get_endhandle") - tk.MustExec("use test_get_endhandle") - // Test PK is handle. - tk.MustExec("create table t(a bigint PRIMARY KEY, b int)") - - is := s.dom.InfoSchema() - d := s.dom.DDL() - tbl, err := is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t")) - c.Assert(err, IsNil) - - testCtx := newTestMaxTableRowIDContext(c, d, tbl) - // test empty table - checkGetMaxTableRowID(testCtx, s.store, true, nil) - - tk.MustExec("insert into t values(-1, 1)") - checkGetMaxTableRowID(testCtx, s.store, false, kv.IntHandle(-1)) - - tk.MustExec("insert into t values(9223372036854775806, 1)") - checkGetMaxTableRowID(testCtx, s.store, false, kv.IntHandle(9223372036854775806)) - - tk.MustExec("insert into t values(9223372036854775807, 1)") - checkGetMaxTableRowID(testCtx, s.store, false, kv.IntHandle(9223372036854775807)) - - tk.MustExec("insert into t values(10, 1)") - tk.MustExec("insert into t values(102149142, 1)") - checkGetMaxTableRowID(testCtx, s.store, false, kv.IntHandle(9223372036854775807)) - - tk.MustExec("create table t1(a bigint PRIMARY KEY, b int)") - - var builder strings.Builder - fmt.Fprintf(&builder, "insert into t1 values ") - for i := 0; i < 1000; i++ { - fmt.Fprintf(&builder, "(%v, %v),", i, i) - } - sql := builder.String() - tk.MustExec(sql[:len(sql)-1]) - - is = s.dom.InfoSchema() - testCtx.tbl, err = is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - checkGetMaxTableRowID(testCtx, s.store, false, kv.IntHandle(999)) - - // Test PK is not handle - tk.MustExec("create table t2(a varchar(255))") - - is = s.dom.InfoSchema() - testCtx.tbl, err = is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - checkGetMaxTableRowID(testCtx, s.store, true, nil) - - builder.Reset() - fmt.Fprintf(&builder, "insert into t2 values ") - for i := 0; i < 1000; i++ { - fmt.Fprintf(&builder, "(%v),", i) - } - sql = builder.String() - tk.MustExec(sql[:len(sql)-1]) - - result := tk.MustQuery("select MAX(_tidb_rowid) from t2") - maxHandle, emptyTable := getMaxTableHandle(testCtx, s.store) - result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) - c.Assert(emptyTable, IsFalse) - - tk.MustExec("insert into t2 values(100000)") - result = tk.MustQuery("select MAX(_tidb_rowid) from t2") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) - c.Assert(emptyTable, IsFalse) - - tk.MustExec(fmt.Sprintf("insert into t2 values(%v)", math.MaxInt64-1)) - result = tk.MustQuery("select MAX(_tidb_rowid) from t2") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) - c.Assert(emptyTable, IsFalse) - - tk.MustExec(fmt.Sprintf("insert into t2 values(%v)", math.MaxInt64)) - result = tk.MustQuery("select MAX(_tidb_rowid) from t2") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) - c.Assert(emptyTable, IsFalse) - - tk.MustExec("insert into t2 values(100)") - result = tk.MustQuery("select MAX(_tidb_rowid) from t2") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - result.Check(testkit.Rows(fmt.Sprintf("%v", maxHandle.IntValue()))) - c.Assert(emptyTable, IsFalse) -} - -func (s *testIntegrationSuite7) TestMultiRegionGetTableEndCommonHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_get_endhandle") - tk.MustExec("create database test_get_endhandle") - tk.MustExec("use test_get_endhandle") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - - tk.MustExec("create table t(a varchar(20), b int, c float, d bigint, primary key (a, b, c))") - var builder strings.Builder - fmt.Fprintf(&builder, "insert into t values ") - for i := 0; i < 1000; i++ { - fmt.Fprintf(&builder, "('%v', %v, %v, %v),", i, i, i, i) - } - sql := builder.String() - tk.MustExec(sql[:len(sql)-1]) - - // Get table ID for split. - dom := domain.GetDomain(tk.Se) - is := dom.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - d := s.dom.DDL() - testCtx := newTestMaxTableRowIDContext(c, d, tbl) - - // Split the table. - tableStart := tablecodec.GenTableRecordPrefix(tblID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) - - maxHandle, emptyTable := getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, HandleEquals, MustNewCommonHandle(c, "999", 999, 999)) - - tk.MustExec("insert into t values('a', 1, 1, 1)") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, HandleEquals, MustNewCommonHandle(c, "a", 1, 1)) - - tk.MustExec("insert into t values('0000', 1, 1, 1)") - maxHandle, emptyTable = getMaxTableHandle(testCtx, s.store) - c.Assert(emptyTable, IsFalse) - c.Assert(maxHandle, HandleEquals, MustNewCommonHandle(c, "a", 1, 1)) -} - -func (s *testIntegrationSuite7) TestGetTableEndCommonHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_get_endhandle") - tk.MustExec("create database test_get_endhandle") - tk.MustExec("use test_get_endhandle") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - - tk.MustExec("create table t(a varchar(15), b bigint, c int, primary key (a, b))") - tk.MustExec("create table t1(a varchar(15), b bigint, c int, primary key (a(2), b))") - - is := s.dom.InfoSchema() - d := s.dom.DDL() - tbl, err := is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t")) - c.Assert(err, IsNil) - testCtx := newTestMaxTableRowIDContext(c, d, tbl) - - // test empty table - checkGetMaxTableRowID(testCtx, s.store, true, nil) - tk.MustExec("insert into t values('abc', 1, 10)") - expectedHandle := MustNewCommonHandle(c, "abc", 1) - checkGetMaxTableRowID(testCtx, s.store, false, expectedHandle) - tk.MustExec("insert into t values('abchzzzzzzzz', 1, 10)") - expectedHandle = MustNewCommonHandle(c, "abchzzzzzzzz", 1) - checkGetMaxTableRowID(testCtx, s.store, false, expectedHandle) - tk.MustExec("insert into t values('a', 1, 10)") - tk.MustExec("insert into t values('ab', 1, 10)") - checkGetMaxTableRowID(testCtx, s.store, false, expectedHandle) - - // Test MaxTableRowID with prefixed primary key. - tbl, err = is.TableByName(model.NewCIStr("test_get_endhandle"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - d = s.dom.DDL() - testCtx = newTestMaxTableRowIDContext(c, d, tbl) - checkGetMaxTableRowID(testCtx, s.store, true, nil) - tk.MustExec("insert into t1 values('abccccc', 1, 10)") - expectedHandle = MustNewCommonHandle(c, "ab", 1) - checkGetMaxTableRowID(testCtx, s.store, false, expectedHandle) - tk.MustExec("insert into t1 values('azzzz', 1, 10)") - expectedHandle = MustNewCommonHandle(c, "az", 1) - checkGetMaxTableRowID(testCtx, s.store, false, expectedHandle) + tk.MustExec("create table t (c1 varchar(3073), index(c1)) charset = ascii") + tk.MustExec(fmt.Sprintf("create table t1 (c1 varchar(%d), index(c1)) charset = ascii;", config.DefMaxOfMaxIndexLength)) + err := tk.ExecToErr(fmt.Sprintf("create table t2 (c1 varchar(%d), index(c1)) charset = ascii;", config.DefMaxOfMaxIndexLength+1)) + require.EqualError(t, err, "[ddl:1071]Specified key was too long; max key length is 12288 bytes") } -func (s *testSerialSuite) TestCreateTableWithLike(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTableWithLike(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // for the same database tk.MustExec("create database ctwl_db") tk.MustExec("use ctwl_db") @@ -426,22 +127,21 @@ func (s *testSerialSuite) TestCreateTableWithLike(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("10 1")) tk.MustQuery("select * from t1").Check(testkit.Rows("1 11")) tk.MustQuery("select * from t2").Check(testkit.Rows("1 12")) - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() + is := domain.GetDomain(tk.Session()).InfoSchema() tbl1, err := is.TableByName(model.NewCIStr("ctwl_db"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tbl1Info := tbl1.Meta() - c.Assert(tbl1Info.ForeignKeys, IsNil) - c.Assert(tbl1Info.PKIsHandle, Equals, true) + require.Nil(t, tbl1Info.ForeignKeys) + require.True(t, tbl1Info.PKIsHandle) col := tbl1Info.Columns[0] hasNotNull := mysql.HasNotNullFlag(col.Flag) - c.Assert(hasNotNull, IsTrue) + require.True(t, hasNotNull) tbl2, err := is.TableByName(model.NewCIStr("ctwl_db"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) tbl2Info := tbl2.Meta() - c.Assert(tbl2Info.ForeignKeys, IsNil) - c.Assert(tbl2Info.PKIsHandle, Equals, true) - c.Assert(mysql.HasNotNullFlag(tbl2Info.Columns[0].Flag), IsTrue) + require.Nil(t, tbl2Info.ForeignKeys) + require.True(t, tbl2Info.PKIsHandle) + require.True(t, mysql.HasNotNullFlag(tbl2Info.Columns[0].Flag)) // for different databases tk.MustExec("create database ctwl_db1") @@ -449,57 +149,57 @@ func (s *testSerialSuite) TestCreateTableWithLike(c *C) { tk.MustExec("create table t1 like ctwl_db.t") tk.MustExec("insert into t1 set c2=11") tk.MustQuery("select * from t1").Check(testkit.Rows("1 11")) - is = domain.GetDomain(ctx).InfoSchema() + is = domain.GetDomain(tk.Session()).InfoSchema() tbl1, err = is.TableByName(model.NewCIStr("ctwl_db1"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(tbl1.Meta().ForeignKeys, IsNil) + require.NoError(t, err) + require.Nil(t, tbl1.Meta().ForeignKeys) // for table partition tk.MustExec("use ctwl_db") tk.MustExec("create table pt1 (id int) partition by range columns (id) (partition p0 values less than (10))") - tk.MustExec("insert into pt1 values (1),(2),(3),(4);") - tk.MustExec("create table ctwl_db1.pt1 like ctwl_db.pt1;") + tk.MustExec("insert into pt1 values (1),(2),(3),(4)") + tk.MustExec("create table ctwl_db1.pt1 like ctwl_db.pt1") tk.MustQuery("select * from ctwl_db1.pt1").Check(testkit.Rows()) // Test create table like for partition table. atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) tk.MustExec("use test") - tk.MustExec("set @@global.tidb_scatter_region=1;") - tk.MustExec("drop table if exists partition_t;") + tk.MustExec("set @@global.tidb_scatter_region=1") + tk.MustExec("drop table if exists partition_t") tk.MustExec("create table partition_t (a int, b int,index(a)) partition by hash (a) partitions 3") - tk.MustExec("drop table if exists t1;") + tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 like partition_t") re := tk.MustQuery("show table t1 regions") rows := re.Rows() - c.Assert(len(rows), Equals, 3) - tbl := testGetTableByName(c, tk.Se, "test", "t1") + require.Len(t, rows, 3) + tbl := external.GetTableByName(t, tk, "test", "t1") partitionDef := tbl.Meta().GetPartitionInfo().Definitions - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[0].ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[1].ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[2].ID)) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[0].ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[1].ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[2].ID), rows[2][1]) // Test pre-split table region when create table like. tk.MustExec("drop table if exists t_pre") - tk.MustExec("create table t_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2;") - tk.MustExec("drop table if exists t2;") + tk.MustExec("create table t_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2") + tk.MustExec("drop table if exists t2") tk.MustExec("create table t2 like t_pre") re = tk.MustQuery("show table t2 regions") rows = re.Rows() // Table t2 which create like t_pre should have 4 regions now. - c.Assert(len(rows), Equals, 4) - tbl = testGetTableByName(c, tk.Se, "test", "t2") - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID)) + require.Len(t, rows, 4) + tbl = external.GetTableByName(t, tk, "test", "t2") + require.Equal(t, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID), rows[3][1]) // Test after truncate table the region is also splited. tk.MustExec("truncate table t2") re = tk.MustQuery("show table t2 regions") rows = re.Rows() - c.Assert(len(rows), Equals, 4) - tbl = testGetTableByName(c, tk.Se, "test", "t2") - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID)) + require.Equal(t, 4, len(rows)) + tbl = external.GetTableByName(t, tk, "test", "t2") + require.Equal(t, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID), rows[3][1]) defer atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) @@ -528,64 +228,61 @@ func (s *testSerialSuite) TestCreateTableWithLike(c *C) { tk.MustExec("drop database ctwl_db1") } -func (s *testSerialSuite) TestCreateTableWithLikeAtTemporaryMode(c *C) { - tk := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set @@global.tidb_enable_alter_placement=1") - c.Assert(err, IsNil) +func TestCreateTableWithLikeAtTemporaryMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Test create table like at temporary mode. tk.MustExec("use test") - tk.MustExec("drop table if exists temporary_table;") + tk.MustExec("drop table if exists temporary_table") tk.MustExec("create global temporary table temporary_table (a int, b int,index(a)) on commit delete rows") - tk.MustExec("drop table if exists temporary_table_t1;") - _, err = tk.Exec("create table temporary_table_t1 like temporary_table") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) - tk.MustExec("drop table if exists temporary_table;") + tk.MustExec("drop table if exists temporary_table_t1") + err := tk.ExecToErr("create table temporary_table_t1 like temporary_table") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error(), err.Error()) + tk.MustExec("drop table if exists temporary_table") // Test create temporary table like. // Test auto_random. tk.MustExec("drop table if exists auto_random_table") - _, err = tk.Exec("create table auto_random_table (a bigint primary key auto_random(3), b varchar(255));") + err = tk.ExecToErr("create table auto_random_table (a bigint primary key auto_random(3), b varchar(255))") defer tk.MustExec("drop table if exists auto_random_table") tk.MustExec("drop table if exists auto_random_temporary_global") - _, err = tk.Exec("create global temporary table auto_random_temporary_global like auto_random_table on commit delete rows;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error()) + err = tk.ExecToErr("create global temporary table auto_random_temporary_global like auto_random_table on commit delete rows") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error(), err.Error()) // Test pre split regions. tk.MustExec("drop table if exists table_pre_split") - _, err = tk.Exec("create table table_pre_split(id int) shard_row_id_bits = 2 pre_split_regions=2;") + err = tk.ExecToErr("create table table_pre_split(id int) shard_row_id_bits = 2 pre_split_regions=2") defer tk.MustExec("drop table if exists table_pre_split") tk.MustExec("drop table if exists temporary_table_pre_split") - _, err = tk.Exec("create global temporary table temporary_table_pre_split like table_pre_split ON COMMIT DELETE ROWS;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) + err = tk.ExecToErr("create global temporary table temporary_table_pre_split like table_pre_split ON COMMIT DELETE ROWS") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error(), err.Error()) // Test shard_row_id_bits. tk.MustExec("drop table if exists shard_row_id_table, shard_row_id_temporary_table, shard_row_id_table_plus, shard_row_id_temporary_table_plus") - _, err = tk.Exec("create table shard_row_id_table (a int) shard_row_id_bits = 5;") - _, err = tk.Exec("create global temporary table shard_row_id_temporary_table like shard_row_id_table on commit delete rows;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) - tk.MustExec("create table shard_row_id_table_plus (a int);") - tk.MustExec("create global temporary table shard_row_id_temporary_table_plus (a int) on commit delete rows;") + err = tk.ExecToErr("create table shard_row_id_table (a int) shard_row_id_bits = 5") + err = tk.ExecToErr("create global temporary table shard_row_id_temporary_table like shard_row_id_table on commit delete rows") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error(), err.Error()) + tk.MustExec("create table shard_row_id_table_plus (a int)") + tk.MustExec("create global temporary table shard_row_id_temporary_table_plus (a int) on commit delete rows") defer tk.MustExec("drop table if exists shard_row_id_table, shard_row_id_temporary_table, shard_row_id_table_plus, shard_row_id_temporary_table_plus") - _, err = tk.Exec("alter table shard_row_id_temporary_table_plus shard_row_id_bits = 4;") - c.Assert(err.Error(), Equals, ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) + err = tk.ExecToErr("alter table shard_row_id_temporary_table_plus shard_row_id_bits = 4") + require.Equal(t, dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error(), err.Error()) // Test partition. - tk.MustExec("drop table if exists global_partition_table;") - tk.MustExec("create table global_partition_table (a int, b int) partition by hash(a) partitions 3;") - defer tk.MustExec("drop table if exists global_partition_table;") - tk.MustGetErrCode("create global temporary table global_partition_temp_table like global_partition_table ON COMMIT DELETE ROWS;", - errno.ErrPartitionNoTemporary) + tk.MustExec("drop table if exists global_partition_table") + tk.MustExec("create table global_partition_table (a int, b int) partition by hash(a) partitions 3") + defer tk.MustExec("drop table if exists global_partition_table") + tk.MustGetErrCode("create global temporary table global_partition_temp_table like global_partition_table ON COMMIT DELETE ROWS;", errno.ErrPartitionNoTemporary) // Test virtual columns. tk.MustExec("drop table if exists test_gv_ddl, test_gv_ddl_temp") tk.MustExec(`create table test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored)`) tk.MustExec(`create global temporary table test_gv_ddl_temp like test_gv_ddl on commit delete rows;`) defer tk.MustExec("drop table if exists test_gv_ddl_temp, test_gv_ddl") - is := tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_gv_ddl")) - c.Assert(err, IsNil) + require.NoError(t, err) testCases := []struct { generatedExprString string generatedStored bool @@ -595,146 +292,158 @@ func (s *testSerialSuite) TestCreateTableWithLikeAtTemporaryMode(c *C) { {"`b` + 2", true}, } for i, column := range table.Meta().Columns { - c.Assert(column.GeneratedExprString, Equals, testCases[i].generatedExprString) - c.Assert(column.GeneratedStored, Equals, testCases[i].generatedStored) + require.Equal(t, testCases[i].generatedExprString, column.GeneratedExprString) + require.Equal(t, testCases[i].generatedStored, column.GeneratedStored) } result := tk.MustQuery(`DESC test_gv_ddl_temp`) result.Check(testkit.Rows(`a int(11) YES `, `b int(11) YES VIRTUAL GENERATED`, `c int(11) YES STORED GENERATED`)) - tk.MustExec("begin;") + tk.MustExec("begin") tk.MustExec("insert into test_gv_ddl_temp values (1, default, default)") tk.MustQuery("select * from test_gv_ddl_temp").Check(testkit.Rows("1 9 11")) - _, err = tk.Exec("commit") - c.Assert(err, IsNil) + err = tk.ExecToErr("commit") + require.NoError(t, err) // Test foreign key. tk.MustExec("drop table if exists test_foreign_key, t1") - tk.MustExec("create table t1 (a int, b int);") - tk.MustExec("create table test_foreign_key (c int,d int,foreign key (d) references t1 (b));") - defer tk.MustExec("drop table if exists test_foreign_key, t1;") - tk.MustExec("create global temporary table test_foreign_key_temp like test_foreign_key on commit delete rows;") - is = tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("create table test_foreign_key (c int,d int,foreign key (d) references t1 (b))") + defer tk.MustExec("drop table if exists test_foreign_key, t1") + tk.MustExec("create global temporary table test_foreign_key_temp like test_foreign_key on commit delete rows") + is = tk.Session().GetInfoSchema().(infoschema.InfoSchema) table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_foreign_key_temp")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := table.Meta() - c.Assert(len(tableInfo.ForeignKeys), Equals, 0) + require.Equal(t, 0, len(tableInfo.ForeignKeys)) // Issue 25613. // Test from->normal, to->normal. tk.MustExec("drop table if exists tb1, tb2") - tk.MustExec("create table tb1(id int);") + tk.MustExec("create table tb1(id int)") tk.MustExec("create table tb2 like tb1") defer tk.MustExec("drop table if exists tb1, tb2") - tk.MustQuery("show create table tb2;").Check(testkit.Rows("tb2 CREATE TABLE `tb2` (\n" + + tk.MustQuery("show create table tb2").Check(testkit.Rows("tb2 CREATE TABLE `tb2` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // Test from->normal, to->global temporary. tk.MustExec("drop table if exists tb3, tb4") - tk.MustExec("create table tb3(id int);") - tk.MustExec("create global temporary table tb4 like tb3 on commit delete rows;") + tk.MustExec("create table tb3(id int)") + tk.MustExec("create global temporary table tb4 like tb3 on commit delete rows") defer tk.MustExec("drop table if exists tb3, tb4") - tk.MustQuery("show create table tb4;").Check(testkit.Rows("tb4 CREATE GLOBAL TEMPORARY TABLE `tb4` (\n" + + tk.MustQuery("show create table tb4").Check(testkit.Rows("tb4 CREATE GLOBAL TEMPORARY TABLE `tb4` (\n" + " `id` int(11) DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ON COMMIT DELETE ROWS")) // Test from->global temporary, to->normal. tk.MustExec("drop table if exists tb5, tb6") - tk.MustExec("create global temporary table tb5(id int) on commit delete rows;") - _, err = tk.Exec("create table tb6 like tb5;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) + tk.MustExec("create global temporary table tb5(id int) on commit delete rows") + err = tk.ExecToErr("create table tb6 like tb5") + require.EqualError(t, err, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) defer tk.MustExec("drop table if exists tb5, tb6") // Test from->global temporary, to->global temporary. tk.MustExec("drop table if exists tb7, tb8") - tk.MustExec("create global temporary table tb7(id int) on commit delete rows;") - _, err = tk.Exec("create global temporary table tb8 like tb7 on commit delete rows;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) + tk.MustExec("create global temporary table tb7(id int) on commit delete rows") + err = tk.ExecToErr("create global temporary table tb8 like tb7 on commit delete rows") + require.EqualError(t, err, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) defer tk.MustExec("drop table if exists tb7, tb8") // Test from->normal, to->local temporary tk.MustExec("drop table if exists tb11, tb12") tk.MustExec("create table tb11 (i int primary key, j int)") tk.MustExec("create temporary table tb12 like tb11") - tk.MustQuery("show create table tb12;").Check(testkit.Rows("tb12 CREATE TEMPORARY TABLE `tb12` (\n" + + tk.MustQuery("show create table tb12").Check(testkit.Rows("tb12 CREATE TEMPORARY TABLE `tb12` (\n" + " `i` int(11) NOT NULL,\n `j` int(11) DEFAULT NULL,\n PRIMARY KEY (`i`) /*T![clustered_index] CLUSTERED */\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("create temporary table if not exists tb12 like tb11;") - c.Assert(tk.Se.(sessionctx.Context).GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, - infoschema.ErrTableExists.GenWithStackByArgs("test.tb12").Error()) + tk.MustExec("create temporary table if not exists tb12 like tb11") + err = infoschema.ErrTableExists.GenWithStackByArgs("test.tb12") + require.EqualError(t, err, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error()) defer tk.MustExec("drop table if exists tb11, tb12") // Test from->local temporary, to->local temporary tk.MustExec("drop table if exists tb13, tb14") tk.MustExec("create temporary table tb13 (i int primary key, j int)") - _, err = tk.Exec("create temporary table tb14 like tb13;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) + err = tk.ExecToErr("create temporary table tb14 like tb13") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error(), err.Error()) defer tk.MustExec("drop table if exists tb13, tb14") // Test from->local temporary, to->normal tk.MustExec("drop table if exists tb15, tb16") tk.MustExec("create temporary table tb15 (i int primary key, j int)") - _, err = tk.Exec("create table tb16 like tb15;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error()) + err = tk.ExecToErr("create table tb16 like tb15") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error(), err.Error()) defer tk.MustExec("drop table if exists tb15, tb16") tk.MustExec("drop table if exists table_pre_split, tmp_pre_split") - tk.MustExec("create table table_pre_split(id int) shard_row_id_bits=2 pre_split_regions=2;") - _, err = tk.Exec("create temporary table tmp_pre_split like table_pre_split") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) + tk.MustExec("create table table_pre_split(id int) shard_row_id_bits=2 pre_split_regions=2") + err = tk.ExecToErr("create temporary table tmp_pre_split like table_pre_split") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error(), err.Error()) defer tk.MustExec("drop table if exists table_pre_split, tmp_pre_split") tk.MustExec("drop table if exists table_shard_row_id, tmp_shard_row_id") - tk.MustExec("create table table_shard_row_id(id int) shard_row_id_bits=2;") - _, err = tk.Exec("create temporary table tmp_shard_row_id like table_shard_row_id") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error()) + tk.MustExec("create table table_shard_row_id(id int) shard_row_id_bits=2") + err = tk.ExecToErr("create temporary table tmp_shard_row_id like table_shard_row_id") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error(), err.Error()) defer tk.MustExec("drop table if exists table_shard_row_id, tmp_shard_row_id") tk.MustExec("drop table if exists partition_table, tmp_partition_table") - tk.MustExec("create table partition_table (a int, b int) partition by hash(a) partitions 3;") + tk.MustExec("create table partition_table (a int, b int) partition by hash(a) partitions 3") tk.MustGetErrCode("create temporary table tmp_partition_table like partition_table", errno.ErrPartitionNoTemporary) defer tk.MustExec("drop table if exists partition_table, tmp_partition_table") - tk.MustExec("drop table if exists foreign_key_table1, foreign_key_table2, foreign_key_tmp;") - tk.MustExec("create table foreign_key_table1 (a int, b int);") - tk.MustExec("create table foreign_key_table2 (c int,d int,foreign key (d) references foreign_key_table1 (b));") + tk.MustExec("drop table if exists foreign_key_table1, foreign_key_table2, foreign_key_tmp") + tk.MustExec("create table foreign_key_table1 (a int, b int)") + tk.MustExec("create table foreign_key_table2 (c int,d int,foreign key (d) references foreign_key_table1 (b))") tk.MustExec("create temporary table foreign_key_tmp like foreign_key_table2") - is = tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema) + is = tk.Session().GetInfoSchema().(infoschema.InfoSchema) table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("foreign_key_tmp")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo = table.Meta() - c.Assert(len(tableInfo.ForeignKeys), Equals, 0) - defer tk.MustExec("drop table if exists foreign_key_table1, foreign_key_table2, foreign_key_tmp;") + require.Equal(t, 0, len(tableInfo.ForeignKeys)) + defer tk.MustExec("drop table if exists foreign_key_table1, foreign_key_table2, foreign_key_tmp") // Test for placement tk.MustExec("drop placement policy if exists p1") tk.MustExec("create placement policy p1 primary_region='r1' regions='r1,r2'") defer tk.MustExec("drop placement policy p1") - tk.MustExec("drop table if exists placement_table1, placement_table1") + tk.MustExec("drop table if exists placement_table1") tk.MustExec("create table placement_table1(id int) placement policy p1") defer tk.MustExec("drop table if exists placement_table1") - tk.MustExec("create table placement_table2(id int) LEADER_CONSTRAINTS='[+region=hz]' FOLLOWERS=3") - defer tk.MustExec("drop table if exists placement_table2") - - _, err = tk.Exec("create global temporary table g_tmp_placement1 like placement_table1 on commit delete rows") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error()) - _, err = tk.Exec("create global temporary table g_tmp_placement2 like placement_table2 on commit delete rows") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error()) - - _, err = tk.Exec("create temporary table l_tmp_placement1 like placement_table1") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error()) - _, err = tk.Exec("create temporary table l_tmp_placement2 like placement_table2") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error()) + + err = tk.ExecToErr("create global temporary table g_tmp_placement1 like placement_table1 on commit delete rows") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error(), err.Error()) + err = tk.ExecToErr("create temporary table l_tmp_placement1 like placement_table1") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("placement").Error(), err.Error()) +} + +func createMockStoreAndDomain(t *testing.T) (store kv.Storage, dom *domain.Domain, clean func()) { + session.SetSchemaLease(200 * time.Millisecond) + session.DisableStats4Test() + ddl.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) + + var err error + store, err = mockstore.NewMockStore() + require.NoError(t, err) + dom, err = session.BootstrapSession(store) + require.NoError(t, err) + clean = func() { + dom.Close() + require.NoError(t, store.Close()) + } + return } // TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started. -func (s *testSerialSuite) TestCancelAddIndexPanic(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/errorMockPanic", `return(true)`), IsNil) +func TestCancelAddIndexPanic(t *testing.T) { + store, dom, clean := createMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/errorMockPanic", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/errorMockPanic"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/errorMockPanic")) }() - tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(c1 int, c2 int)") - defer tk.MustExec("drop table t;") + defer tk.MustExec("drop table t") for i := 0; i < 5; i++ { tk.MustExec("insert into t values (?, ?)", i, i) } @@ -747,7 +456,7 @@ func (s *testSerialSuite) TestCancelAddIndexPanic(c *C) { if job.Type == model.ActionAddIndex && job.State == model.JobStateRunning && job.SchemaState == model.StateWriteReorganization && job.SnapshotVer != 0 { jobIDs := []int64{job.ID} hookCtx := mock.NewContext() - hookCtx.Store = s.store + hookCtx.Store = store err := hookCtx.NewTxn(context.Background()) if err != nil { checkErr = errors.Trace(err) @@ -775,39 +484,39 @@ func (s *testSerialSuite) TestCancelAddIndexPanic(c *C) { checkErr = txn.Commit(context.Background()) } } - origHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) rs, err := tk.Exec("alter table t add index idx_c2(c2)") if rs != nil { - rs.Close() + require.NoError(t, rs.Close()) } - c.Assert(checkErr, IsNil) - c.Assert(err, NotNil) + require.NoError(t, checkErr) + require.Error(t, err) errMsg := err.Error() // Cancelling the job can either succeed or not, it depends on whether the cancelled job takes affect. // For now, there's no way to guarantee that cancelling will always take effect. // TODO: After issue #17904 is fixed, there is no need to tolerate it here. - c.Assert(strings.HasPrefix(errMsg, "[ddl:8214]Cancelled DDL job") || strings.HasPrefix(errMsg, "[ddl:8211]DDL job rollback"), IsTrue) + require.True(t, strings.HasPrefix(errMsg, "[ddl:8214]Cancelled DDL job") || strings.HasPrefix(errMsg, "[ddl:8211]DDL job rollback")) } -func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRecoverTableByJobID(t *testing.T) { + store, _, clean := createMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_recover") tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") - tk.MustExec("create table t_recover (a int);") + tk.MustExec("create table t_recover (a int)") defer func(originGC bool) { if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(util.IsEmulatorGCEnable()) // disable emulator GC. // Otherwise emulator GC will delete table record as soon as possible after execute drop table ddl. - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) timeAfterDrop := time.Now().Add(48 * 60 * 60 * time.Second).Format(gcTimeFormat) @@ -822,23 +531,22 @@ func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { getDDLJobID := func(table, tp string) int64 { rs, err := tk.Exec("admin show ddl jobs") - c.Assert(err, IsNil) - rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + rows, err := session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) for _, row := range rows { if row.GetString(1) == table && row.GetString(3) == tp { return row.GetInt64(0) } } - c.Errorf("can't find %s table of %s", tp, table) + require.FailNowf(t, "can't find %s table of %s", tp, table) return -1 } jobID := getDDLJobID("test_recover", "drop table") // if GC safe point is not exists in mysql.tidb - _, err := tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "can not get 'tikv_gc_safe_point'") + err := tk.ExecToErr(fmt.Sprintf("recover table by job %d", jobID)) + require.EqualError(t, err, "can not get 'tikv_gc_safe_point'") // set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) @@ -846,21 +554,21 @@ func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) tk.MustExec("DROP TABLE t_recover") - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.EnableGC(tk.Session()) + require.NoError(t, err) // recover job is before GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeAfterDrop)) - _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "snapshot is older than GC safe point"), Equals, true) + err = tk.ExecToErr(fmt.Sprintf("recover table by job %d", jobID)) + require.Error(t, err) + require.Contains(t, err.Error(), "snapshot is older than GC safe point") // set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // if there is a new table with the same name, should return failed. - tk.MustExec("create table t_recover (a int);") - _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) - c.Assert(err.Error(), Equals, infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) + tk.MustExec("create table t_recover (a int)") + err = tk.ExecToErr(fmt.Sprintf("recover table by job %d", jobID)) + require.EqualError(t, err, infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) // drop the new table with the same name, then recover table. tk.MustExec("drop table t_recover") @@ -869,18 +577,18 @@ func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3")) // check recover table autoID. tk.MustExec("insert into t_recover values (4),(5),(6)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) // recover table by none exits job. - _, err = tk.Exec(fmt.Sprintf("recover table by job %d", 10000000)) - c.Assert(err, NotNil) + err = tk.ExecToErr(fmt.Sprintf("recover table by job %d", 10000000)) + require.Error(t, err) // Disable GC by manual first, then after recover table, the GC enable status should also be disabled. - err = gcutil.DisableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.DisableGC(tk.Session()) + require.NoError(t, err) tk.MustExec("delete from t_recover where a > 1") tk.MustExec("drop table t_recover") @@ -889,10 +597,10 @@ func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1")) // check recover table autoID. tk.MustExec("insert into t_recover values (7),(8),(9)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "7", "8", "9")) // Test for recover truncate table. tk.MustExec("truncate table t_recover") @@ -900,30 +608,32 @@ func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { jobID = getDDLJobID("test_recover", "truncate table") tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) tk.MustExec("insert into t_recover values (10)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9", "10")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "7", "8", "9", "10")) - gcEnable, err := gcutil.CheckGCEnable(tk.Se) - c.Assert(err, IsNil) - c.Assert(gcEnable, Equals, false) + gcEnable, err := gcutil.CheckGCEnable(tk.Session()) + require.NoError(t, err) + require.Equal(t, false, gcEnable) } -func (s *testSerialSuite) TestRecoverTableByJobIDFail(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRecoverTableByJobIDFail(t *testing.T) { + store, dom, clean := createMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_recover") tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") - tk.MustExec("create table t_recover (a int);") + tk.MustExec("create table t_recover (a int)") defer func(originGC bool) { if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(util.IsEmulatorGCEnable()) // disable emulator GC. - // Otherwise emulator GC will delete table record as soon as possible after execute drop table ddl. - ddl.EmulatorGCDisable() + // Otherwise, emulator GC will delete table record as soon as possible after execute drop table util. + util.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') @@ -934,65 +644,65 @@ func (s *testSerialSuite) TestRecoverTableByJobIDFail(c *C) { tk.MustExec("drop table t_recover") rs, err := tk.Exec("admin show ddl jobs") - c.Assert(err, IsNil) - rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + rows, err := session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) row := rows[0] - c.Assert(row.GetString(1), Equals, "test_recover") - c.Assert(row.GetString(3), Equals, "drop table") + require.Equal(t, "test_recover", row.GetString(1)) + require.Equal(t, "drop table", row.GetString(3)) jobID := row.GetInt64(0) // enableGC first - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err = gcutil.EnableGC(tk.Session()) + require.NoError(t, err) tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // set hook hook := &ddl.TestDDLCallback{} hook.OnJobRunBeforeExported = func(job *model.Job) { if job.Type == model.ActionRecoverTable { - c.Assert(failpoint.Enable("tikvclient/mockCommitError", `return(true)`), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("tikvclient/mockCommitError", `return(true)`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`)) } } - origHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) // do recover table. tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) - c.Assert(failpoint.Disable("tikvclient/mockCommitError"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr"), IsNil) + require.NoError(t, failpoint.Disable("tikvclient/mockCommitError")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr")) // make sure enable GC after recover table. - enable, err := gcutil.CheckGCEnable(tk.Se) - c.Assert(err, IsNil) - c.Assert(enable, Equals, true) + enable, err := gcutil.CheckGCEnable(tk.Session()) + require.NoError(t, err) + require.Equal(t, true, enable) // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3")) // check recover table autoID. tk.MustExec("insert into t_recover values (4),(5),(6)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) } -func (s *testSerialSuite) TestRecoverTableByTableNameFail(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRecoverTableByTableNameFail(t *testing.T) { + store, dom, clean := createMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_recover") tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") - tk.MustExec("create table t_recover (a int);") + tk.MustExec("create table t_recover (a int)") defer func(originGC bool) { if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(util.IsEmulatorGCEnable()) // disable emulator GC. // Otherwise emulator GC will delete table record as soon as possible after execute drop table ddl. - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') @@ -1003,82 +713,84 @@ func (s *testSerialSuite) TestRecoverTableByTableNameFail(c *C) { tk.MustExec("drop table t_recover") // enableGC first - err := gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) + err := gcutil.EnableGC(tk.Session()) + require.NoError(t, err) tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // set hook hook := &ddl.TestDDLCallback{} hook.OnJobRunBeforeExported = func(job *model.Job) { if job.Type == model.ActionRecoverTable { - c.Assert(failpoint.Enable("tikvclient/mockCommitError", `return(true)`), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("tikvclient/mockCommitError", `return(true)`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`)) } } - origHook := s.dom.DDL().GetHook() - defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) + dom.DDL().SetHook(hook) // do recover table. tk.MustExec("recover table t_recover") - c.Assert(failpoint.Disable("tikvclient/mockCommitError"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr"), IsNil) + require.NoError(t, failpoint.Disable("tikvclient/mockCommitError")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr")) // make sure enable GC after recover table. - enable, err := gcutil.CheckGCEnable(tk.Se) - c.Assert(err, IsNil) - c.Assert(enable, Equals, true) + enable, err := gcutil.CheckGCEnable(tk.Session()) + require.NoError(t, err) + require.True(t, enable) // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3")) // check recover table autoID. tk.MustExec("insert into t_recover values (4),(5),(6)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + tk.MustQuery("select * from t_recover").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) } -func (s *testSerialSuite) TestCancelJobByErrorCountLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit", `return(true)`), IsNil) +func TestCancelJobByErrorCountLimit(t *testing.T) { + store, _, clean := createMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockExceedErrorLimit")) }() tk.MustExec("use test") tk.MustExec("drop table if exists t") limit := variable.GetDDLErrorCountLimit() tk.MustExec("set @@global.tidb_ddl_error_count_limit = 16") - err := ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) + err := ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %d", limit)) - _, err = tk.Exec("create table t (a int)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1]DDL job rollback, error msg: mock do job error") + err = tk.ExecToErr("create table t (a int)") + require.EqualError(t, err, "[ddl:-1]DDL job rollback, error msg: mock do job error") } -func (s *testSerialSuite) TestTruncateTableUpdateSchemaVersionErr(c *C) { - tk := testkit.NewTestKit(c, s.store) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/mockTruncateTableUpdateVersionError", `return(true)`), IsNil) +func TestTruncateTableUpdateSchemaVersionErr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockTruncateTableUpdateVersionError", `return(true)`)) tk.MustExec("use test") tk.MustExec("drop table if exists t") limit := variable.GetDDLErrorCountLimit() tk.MustExec("set @@global.tidb_ddl_error_count_limit = 5") - err := ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) + err := ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) defer tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %d", limit)) tk.MustExec("create table t (a int)") - _, err = tk.Exec("truncate table t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:-1]DDL job rollback, error msg: mock update version error") + err = tk.ExecToErr("truncate table t") + require.EqualError(t, err, "[ddl:-1]DDL job rollback, error msg: mock update version error") // Disable fail point. - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/mockTruncateTableUpdateVersionError"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockTruncateTableUpdateVersionError")) tk.MustExec("truncate table t") } -func (s *testSerialSuite) TestCanceledJobTakeTime(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCanceledJobTakeTime(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_cjtt(a int)") @@ -1086,20 +798,18 @@ func (s *testSerialSuite) TestCanceledJobTakeTime(c *C) { once := sync.Once{} hook.OnJobUpdatedExported = func(job *model.Job) { once.Do(func() { - err := kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - err := t.GetAutoIDAccessors(job.SchemaID, job.TableID).Del() + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + err := m.GetAutoIDAccessors(job.SchemaID, job.TableID).Del() if err != nil { return err } - return t.DropTableOrView(job.SchemaID, job.TableID) + return m.DropTableOrView(job.SchemaID, job.TableID) }) - c.Assert(err, IsNil) + require.NoError(t, err) }) } - origHook := s.dom.DDL().GetHook() - s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) + dom.DDL().SetHook(hook) originalWT := ddl.GetWaitTimeWhenErrorOccurred() ddl.SetWaitTimeWhenErrorOccurred(1 * time.Second) @@ -1107,14 +817,14 @@ func (s *testSerialSuite) TestCanceledJobTakeTime(c *C) { startTime := time.Now() tk.MustGetErrCode("alter table t_cjtt add column b int", mysql.ErrNoSuchTable) sub := time.Since(startTime) - c.Assert(sub, Less, ddl.GetWaitTimeWhenErrorOccurred()) + require.Less(t, sub, ddl.GetWaitTimeWhenErrorOccurred()) } -func (s *testSerialSuite) TestTableLocksEnable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableLocksEnable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - defer tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int)") // Test for enable table lock config. @@ -1125,34 +835,38 @@ func (s *testSerialSuite) TestTableLocksEnable(c *C) { tk.MustExec("lock tables t1 write") tk.MustQuery("SHOW WARNINGS").Check(testkit.Rows("Warning 1235 LOCK TABLES is not supported. To enable this experimental feature, set 'enable-table-lock' in the configuration file.")) - checkTableLock(c, tk.Se, "test", "t1", model.TableLockNone) + tbl := external.GetTableByName(t, tk, "test", "t1") + dom := domain.GetDomain(tk.Session()) + require.NoError(t, dom.Reload()) + require.Nil(t, tbl.Meta().Lock) tk.MustExec("unlock tables") tk.MustQuery("SHOW WARNINGS").Check(testkit.Rows("Warning 1235 UNLOCK TABLES is not supported. To enable this experimental feature, set 'enable-table-lock' in the configuration file.")) } -func (s *testSerialDBSuite) TestAutoRandomOnTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomOnTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists auto_random_temporary") - _, err := tk.Exec("create global temporary table auto_random_temporary (a bigint primary key auto_random(3), b varchar(255)) on commit delete rows;") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error()) - _, err = tk.Exec("create temporary table t(a bigint key auto_random);") - c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error()) + err := tk.ExecToErr("create global temporary table auto_random_temporary (a bigint primary key auto_random(3), b varchar(255)) on commit delete rows") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error(), err.Error()) + err = tk.ExecToErr("create temporary table t(a bigint key auto_random)") + require.Equal(t, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error(), err.Error()) } -func (s *testSerialDBSuite) TestAutoRandom(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandom(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists auto_random_db") - defer tk.MustExec("drop database if exists auto_random_db") tk.MustExec("use auto_random_db") databaseName, tableName := "auto_random_db", "t" - tk.MustExec("drop table if exists t") tk.MustExec("set @@allow_auto_random_explicit_insert = true") assertInvalidAutoRandomErr := func(sql string, errMsg string, args ...interface{}) { - _, err := tk.Exec(sql) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ddl.ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(errMsg, args...)).Error()) + err := tk.ExecToErr(sql) + require.EqualError(t, err, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(fmt.Sprintf(errMsg, args...)).Error()) } assertPKIsNotHandle := func(sql, errCol string) { @@ -1335,8 +1049,8 @@ func (s *testSerialDBSuite) TestAutoRandom(c *C) { mustExecAndDrop(sql, func() { note := fmt.Sprintf(autoid.AutoRandomAvailableAllocTimesNote, times) result := fmt.Sprintf("Note|1105|%s", note) - tk.MustQuery("show warnings").Check(RowsWithSep("|", result)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", result)) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) }) } assertShowWarningCorrect("create table t (a bigint auto_random(15) primary key)", 281474976710655) @@ -1361,181 +1075,33 @@ func (s *testSerialDBSuite) TestAutoRandom(c *C) { }) } -func (s *testIntegrationSuite7) TestAutoRandomChangeFromAutoInc(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("set @@tidb_allow_remove_auto_inc = 1;") - - // Basic usages. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_increment primary key);") - tk.MustExec("insert into t values (), (), ();") - tk.MustExec("alter table t modify column a bigint auto_random(3);") - tk.MustExec("insert into t values (), (), ();") - rows := tk.MustQuery("show table t next_row_id;").Rows() - c.Assert(len(rows), Equals, 1, Commentf("query result: %v", rows)) - c.Assert(len(rows[0]), Equals, 5, Commentf("query result: %v", rows)) - c.Assert(rows[0][4], Equals, "AUTO_RANDOM") - - // Changing from auto_inc unique key is not allowed. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_increment unique key);") - tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_increment unique key, b bigint auto_random primary key);") - tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) - - // Changing from non-auto-inc column is not allowed. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint);") - tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint primary key);") - tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) - - // Changing from non BIGINT auto_inc pk column is not allowed. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int auto_increment primary key);") - tk.MustGetErrCode("alter table t modify column a int auto_random;", errno.ErrInvalidAutoRandom) - tk.MustGetErrCode("alter table t modify column a bigint auto_random;", errno.ErrInvalidAutoRandom) - - // Changing from auto_random to auto_increment is not allowed. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_random primary key);") - // "Unsupported modify column: can't set auto_increment" - tk.MustGetErrCode("alter table t modify column a bigint auto_increment;", errno.ErrUnsupportedDDLOperation) - - // Large auto_increment number overflows auto_random. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_increment primary key);") - tk.MustExec("insert into t values (1<<(64-5));") - // "max allowed auto_random shard bits is 3, but got 4 on column `a`" - tk.MustGetErrCode("alter table t modify column a bigint auto_random(4);", errno.ErrInvalidAutoRandom) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a bigint auto_increment primary key);") - tk.MustExec("insert into t values (1<<(64-6));") - tk.MustExec("alter table t modify column a bigint auto_random(4);") -} - -func (s *testIntegrationSuite7) TestAutoRandomExchangePartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomWithPreSplitRegion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists auto_random_db") - defer tk.MustExec("drop database if exists auto_random_db") - tk.MustExec("use auto_random_db") - tk.MustExec("set @@tidb_enable_exchange_partition=1") - defer tk.MustExec("set @@tidb_enable_exchange_partition=0") - - tk.MustExec("drop table if exists e1, e2, e3, e4;") - - tk.MustExec("create table e1 (a bigint primary key clustered auto_random(3)) partition by hash(a) partitions 1;") - - tk.MustExec("create table e2 (a bigint primary key);") - tk.MustGetErrCode("alter table e1 exchange partition p0 with table e2;", errno.ErrTablesDifferentMetadata) - - tk.MustExec("create table e3 (a bigint primary key auto_random(2));") - tk.MustGetErrCode("alter table e1 exchange partition p0 with table e3;", errno.ErrTablesDifferentMetadata) - tk.MustExec("insert into e1 values (), (), ()") - - tk.MustExec("create table e4 (a bigint primary key auto_random(3));") - tk.MustExec("insert into e4 values ()") - tk.MustExec("alter table e1 exchange partition p0 with table e4;") - - tk.MustQuery("select count(*) from e1").Check(testkit.Rows("1")) - tk.MustExec("insert into e1 values ()") - tk.MustQuery("select count(*) from e1").Check(testkit.Rows("2")) - - tk.MustQuery("select count(*) from e4").Check(testkit.Rows("3")) - tk.MustExec("insert into e4 values ()") - tk.MustQuery("select count(*) from e4").Check(testkit.Rows("4")) -} - -func (s *testIntegrationSuite7) TestAutoRandomIncBitsIncrementAndOffset(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists auto_random_db") - defer tk.MustExec("drop database if exists auto_random_db") - tk.MustExec("use auto_random_db") - tk.MustExec("drop table if exists t") - - recreateTable := func() { - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a bigint auto_random(6) primary key clustered)") - } - truncateTable := func() { - _, _ = tk.Exec("delete from t") - } - insertTable := func() { - tk.MustExec("insert into t values ()") - } - assertIncBitsValues := func(values ...int) { - mask := strings.Repeat("1", 64-1-6) - sql := fmt.Sprintf(`select a & b'%s' from t order by a & b'%s' asc`, mask, mask) - vs := make([]string, len(values)) - for i, value := range values { - vs[i] = strconv.Itoa(value) - } - tk.MustQuery(sql).Check(testkit.Rows(vs...)) - } - - const truncate, recreate = true, false - expect := func(vs ...int) []int { return vs } - testCase := []struct { - setupAction bool // truncate or recreate - increment int // @@auto_increment_increment - offset int // @@auto_increment_offset - results []int // the implicit allocated auto_random incremental-bit part of values - }{ - {recreate, 5, 10, expect(10, 15, 20)}, - {recreate, 2, 10, expect(10, 12, 14)}, - {truncate, 5, 10, expect(15, 20, 25)}, - {truncate, 10, 10, expect(30, 40, 50)}, - {truncate, 5, 10, expect(55, 60, 65)}, - } - for _, tc := range testCase { - switch tc.setupAction { - case recreate: - recreateTable() - case truncate: - truncateTable() - } - tk.Se.GetSessionVars().AutoIncrementIncrement = tc.increment - tk.Se.GetSessionVars().AutoIncrementOffset = tc.offset - for range tc.results { - insertTable() - } - assertIncBitsValues(tc.results...) - } -} - -func (s *testSerialSuite) TestAutoRandomWithPreSplitRegion(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists auto_random_db;") - defer tk.MustExec("drop database if exists auto_random_db;") - tk.MustExec("use auto_random_db;") - tk.MustExec("drop table if exists t;") - origin := atomic.LoadUint32(&ddl.EnableSplitTableRegion) atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) defer atomic.StoreUint32(&ddl.EnableSplitTableRegion, origin) - tk.MustExec("set @@global.tidb_scatter_region=1;") + tk.MustExec("set @@global.tidb_scatter_region=1") // Test pre-split table region for auto_random table. - tk.MustExec("create table t (a bigint auto_random(2) primary key clustered, b int) pre_split_regions=2;") - re := tk.MustQuery("show table t regions;") + tk.MustExec("create table t (a bigint auto_random(2) primary key clustered, b int) pre_split_regions=2") + re := tk.MustQuery("show table t regions") rows := re.Rows() - c.Assert(len(rows), Equals, 4) - tbl := testGetTableByName(c, tk.Se, "auto_random_db", "t") - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID)) + require.Len(t, rows, 4) + tbl := external.GetTableByName(t, tk, "auto_random_db", "t") //nolint:typecheck + require.Equal(t, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID), rows[3][1]) } -func (s *testSerialSuite) TestModifyingColumn4NewCollations(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - - tk := testkit.NewTestKit(c, s.store) +func TestModifyingColumn4NewCollations(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database dct") tk.MustExec("use dct") tk.MustExec("create table t(b varchar(10) collate utf8_bin, c varchar(10) collate utf8_general_ci) collate utf8_bin") @@ -1567,14 +1133,15 @@ func (s *testSerialSuite) TestModifyingColumn4NewCollations(c *C) { tk.MustExec("alter database dct charset utf8mb4 collate utf8mb4_general_ci") } -func (s *testSerialSuite) TestForbidUnsupportedCollations(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestForbidUnsupportedCollations(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) mustGetUnsupportedCollation := func(sql string, coll string) { tk.MustGetErrMsg(sql, fmt.Sprintf("[ddl:1273]Unsupported collation when new collation is enabled: '%s'", coll)) } + // Test default collation of database. mustGetUnsupportedCollation("create database ucd charset utf8mb4 collate utf8mb4_roman_ci", "utf8mb4_roman_ci") mustGetUnsupportedCollation("create database ucd charset utf8 collate utf8_roman_ci", "utf8_roman_ci") @@ -1603,139 +1170,13 @@ func (s *testSerialSuite) TestForbidUnsupportedCollations(c *C) { // mustGetUnsupportedCollation("alter table t convert to collate utf8mb4_unicode_ci", "utf8mb4_unicode_ci") } -func (s *testIntegrationSuite7) TestInvisibleIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t,t1,t2,t3,t4,t5,t6") - - // The DDL statement related to invisible index. - showIndexes := "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't'" - // 1. Create table with invisible index - tk.MustExec("create table t (a int, b int, unique (a) invisible)") - tk.MustQuery(showIndexes).Check(testkit.Rows("a NO")) - tk.MustExec("insert into t values (1, 2)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2")) - // 2. Drop invisible index - tk.MustExec("alter table t drop index a") - tk.MustQuery(showIndexes).Check(testkit.Rows()) - tk.MustExec("insert into t values (3, 4)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4")) - // 3. Add an invisible index - tk.MustExec("alter table t add index (b) invisible") - tk.MustQuery(showIndexes).Check(testkit.Rows("b NO")) - tk.MustExec("insert into t values (5, 6)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6")) - // 4. Drop it - tk.MustExec("alter table t drop index b") - tk.MustQuery(showIndexes).Check(testkit.Rows()) - tk.MustExec("insert into t values (7, 8)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8")) - // 5. Create a multiple-column invisible index - tk.MustExec("alter table t add index a_b(a, b) invisible") - tk.MustQuery(showIndexes).Check(testkit.Rows("a_b NO", "a_b NO")) - tk.MustExec("insert into t values (9, 10)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8", "9 10")) - // 6. Drop it - tk.MustExec("alter table t drop index a_b") - tk.MustQuery(showIndexes).Check(testkit.Rows()) - tk.MustExec("insert into t values (11, 12)") - tk.MustQuery("select * from t").Check(testkit.Rows("1 2", "3 4", "5 6", "7 8", "9 10", "11 12")) - - // Limitation: Primary key cannot be invisible index - tk.MustGetErrCode("create table t1 (a int, primary key (a) nonclustered invisible)", errno.ErrPKIndexCantBeInvisible) - tk.MustGetErrCode("create table t1 (a int, b int, primary key (a, b) nonclustered invisible)", errno.ErrPKIndexCantBeInvisible) - tk.MustExec("create table t1 (a int, b int)") - tk.MustGetErrCode("alter table t1 add primary key(a) nonclustered invisible", errno.ErrPKIndexCantBeInvisible) - tk.MustGetErrCode("alter table t1 add primary key(a, b) nonclustered invisible", errno.ErrPKIndexCantBeInvisible) - - // Implicit primary key cannot be invisible index - // Create a implicit primary key - tk.MustGetErrCode("create table t2(a int not null, unique (a) invisible)", errno.ErrPKIndexCantBeInvisible) - tk.MustGetErrCode("create table t2(a int auto_increment, unique key (a) invisible);", errno.ErrPKIndexCantBeInvisible) - // Column `a` become implicit primary key after DDL statement on itself - tk.MustExec("create table t2(a int not null)") - tk.MustGetErrCode("alter table t2 add unique (a) invisible", errno.ErrPKIndexCantBeInvisible) - tk.MustExec("create table t3(a int, unique index (a) invisible)") - tk.MustGetErrCode("alter table t3 modify column a int not null", errno.ErrPKIndexCantBeInvisible) - // Only first unique column can be implicit primary - tk.MustExec("create table t4(a int not null, b int not null, unique (a), unique (b) invisible)") - showIndexes = "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't4'" - tk.MustQuery(showIndexes).Check(testkit.Rows("a YES", "b NO")) - tk.MustExec("insert into t4 values (1, 2)") - tk.MustQuery("select * from t4").Check(testkit.Rows("1 2")) - tk.MustGetErrCode("create table t5(a int not null, b int not null, unique (b) invisible, unique (a))", errno.ErrPKIndexCantBeInvisible) - // Column `b` become implicit primary key after DDL statement on other columns - tk.MustExec("create table t5(a int not null, b int not null, unique (a), unique (b) invisible)") - tk.MustGetErrCode("alter table t5 drop index a", errno.ErrPKIndexCantBeInvisible) - tk.MustGetErrCode("alter table t5 modify column a int null", errno.ErrPKIndexCantBeInvisible) - // If these is a explicit primary key, no key will become implicit primary key - tk.MustExec("create table t6 (a int not null, b int, unique (a) invisible, primary key(b) nonclustered)") - showIndexes = "select index_name, is_visible from information_schema.statistics where table_schema = 'test' and table_name = 't6'" - tk.MustQuery(showIndexes).Check(testkit.Rows("a NO", "PRIMARY YES")) - tk.MustExec("insert into t6 values (1, 2)") - tk.MustQuery("select * from t6").Check(testkit.Rows("1 2")) - tk.MustGetErrCode("alter table t6 drop primary key", errno.ErrPKIndexCantBeInvisible) - res := tk.MustQuery("show index from t6 where Key_name='PRIMARY';") - c.Check(len(res.Rows()), Equals, 1) -} - -func (s *testIntegrationSuite7) TestCreateClusteredIndex(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("CREATE TABLE t1 (a int primary key, b int)") - tk.MustExec("CREATE TABLE t2 (a varchar(255) primary key, b int)") - tk.MustExec("CREATE TABLE t3 (a int, b int, c int, primary key (a, b))") - tk.MustExec("CREATE TABLE t4 (a int, b int, c int)") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().PKIsHandle, IsTrue) - c.Assert(tbl.Meta().IsCommonHandle, IsFalse) - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsTrue) - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t3")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsTrue) - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t4")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsFalse) - - tk.MustExec("CREATE TABLE t5 (a varchar(255) primary key nonclustered, b int)") - tk.MustExec("CREATE TABLE t6 (a int, b int, c int, primary key (a, b) nonclustered)") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t5")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsFalse) - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t6")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsFalse) - - tk.MustExec("CREATE TABLE t21 like t2") - tk.MustExec("CREATE TABLE t31 like t3") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t21")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsTrue) - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t31")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsTrue) - - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - tk.MustExec("CREATE TABLE t7 (a varchar(255) primary key, b int)") - is = domain.GetDomain(ctx).InfoSchema() - tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t7")) - c.Assert(err, IsNil) - c.Assert(tbl.Meta().IsCommonHandle, IsFalse) -} - -func (s *testSerialDBSuite) TestCreateTableNoBlock(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime", `return(true)`), IsNil) +func TestCreateTableNoBlock(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime")) }() save := variable.GetDDLErrorCountLimit() tk.MustExec("set @@global.tidb_ddl_error_count_limit = 1") @@ -1743,14 +1184,16 @@ func (s *testSerialDBSuite) TestCreateTableNoBlock(c *C) { tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %v", save)) }() + tk.MustExec("use test") tk.MustExec("drop table if exists t") - _, err := tk.Exec("create table t(a int)") - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("create table t(a int)")) } -func (s *testSerialSuite) TestCheckEnumLength(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t1,t2,t3,t4,t5") +func TestCheckEnumLength(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustGetErrCode("create table t1 (a enum('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))", errno.ErrTooLongValueForType) tk.MustGetErrCode("create table t1 (a set('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))", errno.ErrTooLongValueForType) tk.MustExec("create table t2 (id int primary key)") @@ -1759,12 +1202,10 @@ func (s *testSerialSuite) TestCheckEnumLength(c *C) { config.UpdateGlobal(func(conf *config.Config) { conf.EnableEnumLengthLimit = false }) - _, err := tk.Exec("create table t3 (a enum('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))") - c.Assert(err, IsNil) + tk.MustExec("create table t3 (a enum('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))") tk.MustExec("insert into t3 values(1)") tk.MustQuery("select a from t3").Check(testkit.Rows("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) - _, err = tk.Exec("create table t4 (a set('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))") - c.Assert(err, IsNil) + tk.MustExec("create table t4 (a set('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))") config.UpdateGlobal(func(conf *config.Config) { conf.EnableEnumLengthLimit = true @@ -1774,12 +1215,18 @@ func (s *testSerialSuite) TestCheckEnumLength(c *C) { tk.MustExec("drop table if exists t1,t2,t3,t4,t5") } -func (s *testSerialSuite) TestGetReverseKey(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGetReverseKey(t *testing.T) { + var cluster testutils.Cluster + store, dom, clean := testkit.CreateMockStoreAndDomain(t, + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + })) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database db_get") tk.MustExec("use db_get") - tk.MustExec("drop table if exists test_get") - tk.MustExec("create table test_get(a bigint not null primary key, b bigint);") + tk.MustExec("create table test_get(a bigint not null primary key, b bigint)") insertVal := func(val int) { sql := fmt.Sprintf("insert into test_get value(%d, %d)", val, val) @@ -1793,12 +1240,12 @@ func (s *testSerialSuite) TestGetReverseKey(c *C) { insertVal(math.MaxInt64 - 1) // Get table ID for split. - is := s.dom.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("db_get"), model.NewCIStr("test_get")) - c.Assert(err, IsNil) + require.NoError(t, err) // Split the table. tableStart := tablecodec.GenTableRecordPrefix(tbl.Meta().ID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 4) + cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 4) tk.MustQuery("select * from test_get order by a").Check(testkit.Rows("-9223372036854775808 -9223372036854775808", "-9223372036854775807 -9223372036854775807", @@ -1811,10 +1258,11 @@ func (s *testSerialSuite) TestGetReverseKey(c *C) { minKey := tablecodec.EncodeRecordKey(tbl.RecordPrefix(), kv.IntHandle(math.MinInt64)) maxKey := tablecodec.EncodeRecordKey(tbl.RecordPrefix(), kv.IntHandle(math.MaxInt64)) checkRet := func(startKey, endKey, retKey kv.Key) { - h, err := ddl.GetMaxRowID(s.store, 0, tbl, startKey, endKey) - c.Assert(err, IsNil) - c.Assert(h.Cmp(retKey), Equals, 0) + h, err := ddl.GetMaxRowID(store, 0, tbl, startKey, endKey) + require.NoError(t, err) + require.Equal(t, 0, h.Cmp(retKey)) } + // [minInt64, minInt64] checkRet(minKey, minKey, minKey) // [minInt64, 1<<64-1] @@ -1831,27 +1279,20 @@ func (s *testSerialSuite) TestGetReverseKey(c *C) { checkRet(startKey, endKey, endKey) } -func (s *testSerialDBSuite) TestLocalTemporaryTableBlockedDDL(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestLocalTemporaryTableBlockedDDL(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t1 (id int)") tk.MustExec("create temporary table tmp1 (id int primary key, a int unique, b int)") - err := tk.ExecToErr("rename table tmp1 to tmp2") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("alter table tmp1 add column c int") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("alter table tmp1 add index b(b)") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("create index a on tmp1(b)") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("drop index a on tmp1") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("lock tables tmp1 read") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("lock tables tmp1 write") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("lock tables t1 read, tmp1 read") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) - err = tk.ExecToErr("admin cleanup table lock tmp1") - c.Assert(ddl.ErrUnsupportedLocalTempTableDDL.Equal(err), IsTrue) + require.ErrorIs(t, tk.ExecToErr("rename table tmp1 to tmp2"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("alter table tmp1 add column c int"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("alter table tmp1 add index b(b)"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("create index a on tmp1(b)"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("drop index a on tmp1"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("lock tables tmp1 read"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("lock tables tmp1 write"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("lock tables t1 read, tmp1 read"), dbterror.ErrUnsupportedLocalTempTableDDL) + require.ErrorIs(t, tk.ExecToErr("admin cleanup table lock tmp1"), dbterror.ErrUnsupportedLocalTempTableDDL) } diff --git a/ddl/session_pool.go b/ddl/session_pool.go index 7a57c1b2f18d6..9545af18da187 100644 --- a/ddl/session_pool.go +++ b/ddl/session_pool.go @@ -15,6 +15,7 @@ package ddl import ( + "fmt" "sync" "github.com/ngaut/pools" @@ -48,7 +49,7 @@ func (sg *sessionPool) get() (sessionctx.Context, error) { sg.mu.Lock() if sg.mu.closed { sg.mu.Unlock() - return nil, errors.Errorf("sessionPool is closed.") + return nil, errors.Errorf("sessionPool is closed") } sg.mu.Unlock() @@ -58,7 +59,10 @@ func (sg *sessionPool) get() (sessionctx.Context, error) { return nil, errors.Trace(err) } - ctx := resource.(sessionctx.Context) + ctx, ok := resource.(sessionctx.Context) + if !ok { + return nil, fmt.Errorf("sessionPool resource get %v", ctx) + } ctx.GetSessionVars().SetStatusFlag(mysql.ServerStatusAutocommit, true) ctx.GetSessionVars().InRestrictedSQL = true return ctx, nil diff --git a/ddl/stat_test.go b/ddl/stat_test.go index 933cde0ae95a4..d721cbfa7b39f 100644 --- a/ddl/stat_test.go +++ b/ddl/stat_test.go @@ -16,39 +16,18 @@ package ddl import ( "context" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testStatSuite{}) -var _ = SerialSuites(&testSerialStatSuite{}) - -type testStatSuite struct { -} - -func (s *testStatSuite) SetUpSuite(c *C) { -} - -func (s *testStatSuite) TearDownSuite(c *C) { -} - -type testSerialStatSuite struct { -} - -func (s *testStatSuite) getDDLSchemaVer(c *C, d *ddl) int64 { - m, err := d.Stats(nil) - c.Assert(err, IsNil) - v := m[ddlSchemaVersion] - return v.(int64) -} - -func (s *testSerialStatSuite) TestDDLStatsInfo(c *C) { - store := testCreateStore(c, "test_stat") +func TestDDLStatsInfo(t *testing.T) { + store := createMockStore(t) defer func() { - err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, store.Close()) }() d, err := testNewDDLAndStart( @@ -56,55 +35,56 @@ func (s *testSerialStatSuite) TestDDLStatsInfo(c *C) { WithStore(store), WithLease(testLease), ) - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { - err := d.Stop() - c.Assert(err, IsNil) + require.NoError(t, d.Stop()) }() dbInfo, err := testSchemaInfo(d, "test_stat") - c.Assert(err, IsNil) - testCreateSchema(c, testNewContext(d), d, dbInfo) + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) tblInfo, err := testTableInfo(d, "t", 2) - c.Assert(err, IsNil) + require.NoError(t, err) ctx := testNewContext(d) - testCreateTable(c, ctx, d, dbInfo, tblInfo) + testCreateTable(t, ctx, d, dbInfo, tblInfo) - t := testGetTable(c, d, dbInfo.ID, tblInfo.ID) + m := testGetTable(t, d, dbInfo.ID, tblInfo.ID) // insert t values (1, 1), (2, 2), (3, 3) - _, err = t.AddRecord(ctx, types.MakeDatums(1, 1)) - c.Assert(err, IsNil) - _, err = t.AddRecord(ctx, types.MakeDatums(2, 2)) - c.Assert(err, IsNil) - _, err = t.AddRecord(ctx, types.MakeDatums(3, 3)) - c.Assert(err, IsNil) + _, err = m.AddRecord(ctx, types.MakeDatums(1, 1)) + require.NoError(t, err) + _, err = m.AddRecord(ctx, types.MakeDatums(2, 2)) + require.NoError(t, err) + _, err = m.AddRecord(ctx, types.MakeDatums(3, 3)) + require.NoError(t, err) txn, err := ctx.Txn(true) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) job := buildCreateIdxJob(dbInfo, tblInfo, true, "idx", "c1") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/checkBackfillWorkerNum")) }() done := make(chan error, 1) go func() { - done <- d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + done <- d.DoDDLJob(ctx, job) }() exit := false for !exit { select { case err := <-done: - c.Assert(err, IsNil) + require.NoError(t, err) exit = true - case <-TestCheckWorkerNumCh: + case wg := <-TestCheckWorkerNumCh: varMap, err := d.Stats(nil) - c.Assert(err, IsNil) - c.Assert(varMap[ddlJobReorgHandle], Equals, "1") + wg.Done() + require.NoError(t, err) + require.Equal(t, varMap[ddlJobReorgHandle], "1") } } } diff --git a/ddl/table.go b/ddl/table.go index cd2b818450c57..dbbbcd1653f86 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -39,25 +39,20 @@ import ( "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" tidb_util "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/gcutil" + "github.com/pingcap/tidb/util/logutil" + "go.uber.org/zap" ) const tiflashCheckTiDBHTTPAPIHalfInterval = 2500 * time.Millisecond -func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { - failpoint.Inject("mockExceedErrorLimit", func(val failpoint.Value) { - if val.(bool) { - failpoint.Return(ver, errors.New("mock do job error")) - } - }) - +// DANGER: it is an internal function used by onCreateTable and onCreateTables, for reusing code. Be careful. +// 1. it expects the argument of job has been deserialized. +// 2. it won't call updateSchemaVersion, FinishTableJob and asyncNotifyEvent. +func createTable(d *ddlCtx, t *meta.Meta, job *model.Job) (*model.TableInfo, error) { schemaID := job.SchemaID - tbInfo := &model.TableInfo{} - if err := job.DecodeArgs(tbInfo); err != nil { - // Invalid arguments, cancel this job. - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } + tbInfo := job.Args[0].(*model.TableInfo) tbInfo.State = model.StateNone err := checkTableNotExists(d, t, schemaID, tbInfo.Name.L) @@ -65,12 +60,7 @@ func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) if infoschema.ErrDatabaseNotExists.Equal(err) || infoschema.ErrTableExists.Equal(err) { job.State = model.JobStateCancelled } - return ver, errors.Trace(err) - } - - ver, err = updateSchemaVersion(t, job) - if err != nil { - return ver, errors.Trace(err) + return tbInfo, errors.Trace(err) } switch tbInfo.State { @@ -80,40 +70,134 @@ func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) tbInfo.UpdateTS = t.StartTS err = createTableOrViewWithCheck(t, job, schemaID, tbInfo) if err != nil { - return ver, errors.Trace(err) + return tbInfo, errors.Trace(err) } failpoint.Inject("checkOwnerCheckAllVersionsWaitTime", func(val failpoint.Value) { if val.(bool) { - failpoint.Return(ver, errors.New("mock create table error")) + failpoint.Return(tbInfo, errors.New("mock create table error")) } }) // build table & partition bundles if any. if err = checkAllTablePlacementPoliciesExistAndCancelNonExistJob(t, job, tbInfo); err != nil { - return ver, errors.Trace(err) + return tbInfo, errors.Trace(err) + } + + if tbInfo.TiFlashReplica != nil { + replicaInfo := tbInfo.TiFlashReplica + if pi := tbInfo.GetPartitionInfo(); pi != nil { + logutil.BgLogger().Info("Set TiFlash replica pd rule for partitioned table when creating", zap.Int64("tableID", tbInfo.ID)) + if e := infosync.ConfigureTiFlashPDForPartitions(false, &pi.Definitions, replicaInfo.Count, &replicaInfo.LocationLabels, tbInfo.ID); e != nil { + job.State = model.JobStateCancelled + return tbInfo, errors.Trace(e) + } + // Partitions that in adding mid-state. They have high priorities, so we should set accordingly pd rules. + if e := infosync.ConfigureTiFlashPDForPartitions(true, &pi.AddingDefinitions, replicaInfo.Count, &replicaInfo.LocationLabels, tbInfo.ID); e != nil { + job.State = model.JobStateCancelled + return tbInfo, errors.Trace(e) + } + } else { + logutil.BgLogger().Info("Set TiFlash replica pd rule when creating", zap.Int64("tableID", tbInfo.ID)) + if e := infosync.ConfigureTiFlashPDForTable(tbInfo.ID, replicaInfo.Count, &replicaInfo.LocationLabels); e != nil { + job.State = model.JobStateCancelled + return tbInfo, errors.Trace(e) + } + } } bundles, err := placement.NewFullTableBundles(t, tbInfo) if err != nil { job.State = model.JobStateCancelled - return ver, errors.Trace(err) + return tbInfo, errors.Trace(err) } // Send the placement bundle to PD. err = infosync.PutRuleBundlesWithDefaultRetry(context.TODO(), bundles) if err != nil { job.State = model.JobStateCancelled - return ver, errors.Wrapf(err, "failed to notify PD the placement rules") + return tbInfo, errors.Wrapf(err, "failed to notify PD the placement rules") } - // Finish this job. - job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo) - asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateTable, TableInfo: tbInfo}) - return ver, nil + return tbInfo, nil default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("table", tbInfo.State) + return tbInfo, dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tbInfo.State) + } +} + +func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { + failpoint.Inject("mockExceedErrorLimit", func(val failpoint.Value) { + if val.(bool) { + failpoint.Return(ver, errors.New("mock do job error")) + } + }) + + // just decode, createTable will use it as Args[0] + tbInfo := &model.TableInfo{} + if err := job.DecodeArgs(tbInfo); err != nil { + // Invalid arguments, cancel this job. + job.State = model.JobStateCancelled + return ver, errors.Trace(err) + } + + tbInfo, err := createTable(d, t, job) + if err != nil { + return ver, errors.Trace(err) + } + + ver, err = updateSchemaVersion(t, job) + if err != nil { + return ver, errors.Trace(err) + } + + // Finish this job. + job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo) + asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateTable, TableInfo: tbInfo}) + return ver, errors.Trace(err) +} + +func onCreateTables(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, error) { + var ver int64 + + args := []*model.TableInfo{} + err := job.DecodeArgs(&args) + if err != nil { + // Invalid arguments, cancel this job. + job.State = model.JobStateCancelled + return ver, errors.Trace(err) } + + // We don't construct jobs for every table, but only tableInfo + // The following loop creates a stub job for every table + // + // &*job clones a stub job from the ActionCreateTables job + stubJob := &*job + stubJob.Args = make([]interface{}, 1) + for i := range args { + stubJob.TableID = args[i].ID + stubJob.Args[0] = args[i] + tbInfo, err := createTable(d, t, stubJob) + if err != nil { + job.State = model.JobStateCancelled + return ver, errors.Trace(err) + } + args[i] = tbInfo + } + + ver, err = updateSchemaVersion(t, job) + if err != nil { + return ver, errors.Trace(err) + } + + job.State = model.JobStateDone + job.SchemaState = model.StatePublic + job.BinlogInfo.SetTableInfos(ver, args) + + for i := range args { + asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateTable, TableInfo: args[i]}) + } + + return ver, errors.Trace(err) } func createTableOrViewWithCheck(t *meta.Meta, job *model.Job, schemaID int64, tbInfo *model.TableInfo) error { @@ -187,11 +271,11 @@ func onCreateView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateView, TableInfo: tbInfo}) return ver, nil default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("table", tbInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tbInfo.State) } } -func onDropTableOrView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) { +func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) { tblInfo, err := checkTableExistAndCancelNonExistJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) @@ -245,7 +329,7 @@ func onDropTableOrView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ er startKey := tablecodec.EncodeTablePrefix(job.TableID) job.Args = append(job.Args, startKey, oldIDs, ruleIDs) default: - err = ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) } return ver, errors.Trace(err) @@ -319,14 +403,8 @@ func (w *worker) onRecoverTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in job.Args[checkFlagIndexInJobArgs] = recoverTableCheckFlagDisableGC } - bundles, err := placement.NewFullTableBundles(t, tblInfo) - if err != nil { - job.State = model.JobStateCancelled - return ver, errors.Trace(err) - } - - // Send the placement bundle to PD. - err = infosync.PutRuleBundlesWithDefaultRetry(context.TODO(), bundles) + // Clear all placement when recover + err = clearTablePlacementAndBundles(tblInfo) if err != nil { job.State = model.JobStateCancelled return ver, errors.Wrapf(err, "failed to notify PD the placement rules") @@ -401,11 +479,35 @@ func (w *worker) onRecoverTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in // Finish this job. job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) } return ver, nil } +func clearTablePlacementAndBundles(tblInfo *model.TableInfo) error { + var bundles []*placement.Bundle + if tblInfo.PlacementPolicyRef != nil { + tblInfo.PlacementPolicyRef = nil + bundles = append(bundles, placement.NewBundle(tblInfo.ID)) + } + + if tblInfo.Partition != nil { + for i := range tblInfo.Partition.Definitions { + par := &tblInfo.Partition.Definitions[i] + if par.PlacementPolicyRef != nil { + par.PlacementPolicyRef = nil + bundles = append(bundles, placement.NewBundle(par.ID)) + } + } + } + + if len(bundles) == 0 { + return nil + } + + return infosync.PutRuleBundlesWithDefaultRetry(context.TODO(), bundles) +} + // mockRecoverTableCommitErrOnce uses to make sure // `mockRecoverTableCommitErr` only mock error once. var mockRecoverTableCommitErrOnce uint32 @@ -456,7 +558,8 @@ func getTable(store kv.Storage, schemaID int64, tblInfo *model.TableInfo) (table return tbl, errors.Trace(err) } -func getTableInfoAndCancelFaultJob(t *meta.Meta, job *model.Job, schemaID int64) (*model.TableInfo, error) { +// GetTableInfoAndCancelFaultJob is exported for test. +func GetTableInfoAndCancelFaultJob(t *meta.Meta, job *model.Job, schemaID int64) (*model.TableInfo, error) { tblInfo, err := checkTableExistAndCancelNonExistJob(t, job, schemaID) if err != nil { return nil, errors.Trace(err) @@ -464,7 +567,7 @@ func getTableInfoAndCancelFaultJob(t *meta.Meta, job *model.Job, schemaID int64) if tblInfo.State != model.StatePublic { job.State = model.JobStateCancelled - return nil, ErrInvalidDDLState.GenWithStack("table %s is not in public, but %s", tblInfo.Name, tblInfo.State) + return nil, dbterror.ErrInvalidDDLState.GenWithStack("table %s is not in public, but %s", tblInfo.Name, tblInfo.State) } return tblInfo, nil @@ -473,6 +576,11 @@ func getTableInfoAndCancelFaultJob(t *meta.Meta, job *model.Job, schemaID int64) func checkTableExistAndCancelNonExistJob(t *meta.Meta, job *model.Job, schemaID int64) (*model.TableInfo, error) { tblInfo, err := getTableInfo(t, job.TableID, schemaID) if err == nil { + // Check if table name is renamed. + if job.TableName != "" && tblInfo.Name.L != job.TableName && job.Type != model.ActionRepairTable { + job.State = model.JobStateCancelled + return nil, infoschema.ErrTableNotExists.GenWithStackByArgs(job.SchemaName, job.TableName) + } return tblInfo, nil } if infoschema.ErrDatabaseNotExists.Equal(err) || infoschema.ErrTableNotExists.Equal(err) { @@ -515,7 +623,7 @@ func onTruncateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ erro job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } @@ -558,7 +666,7 @@ func onTruncateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ erro for i := range oldPartitionIDs { newDef := &newDefs[i] newID := newDef.ID - if newDef.PlacementPolicyRef != nil || newDef.DirectPlacementOpts != nil { + if newDef.PlacementPolicyRef != nil { oldIDs = append(oldIDs, oldPartitionIDs[i]) newIDs = append(newIDs, newID) } @@ -578,8 +686,22 @@ func onTruncateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ erro return 0, errors.Wrapf(err, "failed to update the label rule to PD") } - // Clear the tiflash replica available status. + // Clear the TiFlash replica available status. if tblInfo.TiFlashReplica != nil { + // Set PD rules for TiFlash + if pi := tblInfo.GetPartitionInfo(); pi != nil { + if e := infosync.ConfigureTiFlashPDForPartitions(true, &pi.Definitions, tblInfo.TiFlashReplica.Count, &tblInfo.TiFlashReplica.LocationLabels, tblInfo.ID); e != nil { + logutil.BgLogger().Error("ConfigureTiFlashPDForPartitions fails", zap.Error(err)) + job.State = model.JobStateCancelled + return ver, errors.Trace(e) + } + } else { + if e := infosync.ConfigureTiFlashPDForTable(newTableID, tblInfo.TiFlashReplica.Count, &tblInfo.TiFlashReplica.LocationLabels); e != nil { + logutil.BgLogger().Error("ConfigureTiFlashPDForTable fails", zap.Error(err)) + job.State = model.JobStateCancelled + return ver, errors.Trace(e) + } + } tblInfo.TiFlashReplica.AvailablePartitionIDs = nil tblInfo.TiFlashReplica.Available = false } @@ -641,7 +763,7 @@ func onRebaseAutoID(store kv.Storage, t *meta.Meta, job *model.Job, tp autoid.Al job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -686,7 +808,7 @@ func onModifyTableAutoIDCache(t *meta.Meta, job *model.Job) (int64, error) { return 0, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, errors.Trace(err) } @@ -707,7 +829,7 @@ func (w *worker) onShardRowID(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int6 job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -793,31 +915,34 @@ func onRenameTables(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error tableNames := []*model.CIStr{} tableIDs := []int64{} oldSchemaNames := []*model.CIStr{} - if err := job.DecodeArgs(&oldSchemaIDs, &newSchemaIDs, &tableNames, &tableIDs, &oldSchemaNames); err != nil { + oldTableNames := []*model.CIStr{} + if err := job.DecodeArgs(&oldSchemaIDs, &newSchemaIDs, &tableNames, &tableIDs, &oldSchemaNames, &oldTableNames); err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err) } - tblInfo := &model.TableInfo{} + var tblInfos = make([]*model.TableInfo, 0, len(tableNames)) var err error for i, oldSchemaID := range oldSchemaIDs { job.TableID = tableIDs[i] - ver, tblInfo, err = checkAndRenameTables(t, job, oldSchemaID, newSchemaIDs[i], oldSchemaNames[i], tableNames[i]) + job.TableName = oldTableNames[i].L + ver, tblInfo, err := checkAndRenameTables(t, job, oldSchemaID, newSchemaIDs[i], oldSchemaNames[i], tableNames[i]) if err != nil { return ver, errors.Trace(err) } + tblInfos = append(tblInfos, tblInfo) } ver, err = updateSchemaVersion(t, job) if err != nil { return ver, errors.Trace(err) } - job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) + job.FinishMultipleTableJob(model.JobStateDone, model.StatePublic, ver, tblInfos) return ver, nil } func checkAndRenameTables(t *meta.Meta, job *model.Job, oldSchemaID, newSchemaID int64, oldSchemaName, tableName *model.CIStr) (ver int64, tblInfo *model.TableInfo, _ error) { - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, oldSchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, oldSchemaID) if err != nil { return ver, tblInfo, errors.Trace(err) } @@ -879,7 +1004,7 @@ func onModifyTableComment(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -906,7 +1031,7 @@ func onModifyTableCharsetAndCollate(t *meta.Meta, job *model.Job) (ver int64, _ return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -949,14 +1074,19 @@ func (w *worker) onSetTableFlashReplica(t *meta.Meta, job *model.Job) (ver int64 return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } + if replicaInfo.Count > 0 && tableHasPlacementSettings(tblInfo) { + job.State = model.JobStateCancelled + return ver, errors.Trace(dbterror.ErrIncompatibleTiFlashAndPlacement) + } + // Ban setting replica count for tables in system database. if tidb_util.IsMemOrSysDB(job.SchemaName) { - return ver, errors.Trace(errUnsupportedAlterReplicaForSysTable) + return ver, errors.Trace(dbterror.ErrUnsupportedAlterReplicaForSysTable) } err = w.checkTiFlashReplicaCount(replicaInfo.Count) @@ -964,6 +1094,25 @@ func (w *worker) onSetTableFlashReplica(t *meta.Meta, job *model.Job) (ver int64 job.State = model.JobStateCancelled return ver, errors.Trace(err) } + // We should check this first, in order to avoid creating redundant DDL jobs. + if pi := tblInfo.GetPartitionInfo(); pi != nil { + logutil.BgLogger().Info("Set TiFlash replica pd rule for partitioned table", zap.Int64("tableID", tblInfo.ID)) + if e := infosync.ConfigureTiFlashPDForPartitions(false, &pi.Definitions, replicaInfo.Count, &replicaInfo.Labels, tblInfo.ID); e != nil { + job.State = model.JobStateCancelled + return ver, errors.Trace(e) + } + // Partitions that in adding mid-state. They have high priorities, so we should set accordingly pd rules. + if e := infosync.ConfigureTiFlashPDForPartitions(true, &pi.AddingDefinitions, replicaInfo.Count, &replicaInfo.Labels, tblInfo.ID); e != nil { + job.State = model.JobStateCancelled + return ver, errors.Trace(e) + } + } else { + logutil.BgLogger().Info("Set TiFlash replica pd rule", zap.Int64("tableID", tblInfo.ID)) + if e := infosync.ConfigureTiFlashPDForTable(tblInfo.ID, replicaInfo.Count, &replicaInfo.Labels); e != nil { + job.State = model.JobStateCancelled + return ver, errors.Trace(e) + } + } if replicaInfo.Count > 0 { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -1000,7 +1149,7 @@ func onUpdateFlashReplicaStatus(t *meta.Meta, job *model.Job) (ver int64, _ erro return ver, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, errors.Trace(err) } @@ -1160,7 +1309,7 @@ func onRepairTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) tblInfo.State = model.StateNone // Check the old DB and old table exist. - _, err := getTableInfoAndCancelFaultJob(t, job, schemaID) + _, err := GetTableInfoAndCancelFaultJob(t, job, schemaID) if err != nil { return ver, errors.Trace(err) } @@ -1186,7 +1335,7 @@ func onRepairTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) asyncNotifyEvent(d, &util.Event{Tp: model.ActionRepairTable, TableInfo: tblInfo}) return ver, nil default: - return ver, ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("table", tblInfo.State) } } @@ -1198,7 +1347,7 @@ func onAlterTableAttributes(t *meta.Meta, job *model.Job) (ver int64, err error) return 0, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, err } @@ -1230,7 +1379,7 @@ func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, e job.State = model.JobStateCancelled return 0, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, err } @@ -1263,17 +1412,21 @@ func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, e func onAlterTablePartitionPlacement(t *meta.Meta, job *model.Job) (ver int64, err error) { var partitionID int64 policyRefInfo := &model.PolicyRefInfo{} - placementSettings := &model.PlacementSettings{} - err = job.DecodeArgs(&partitionID, &policyRefInfo, &placementSettings) + err = job.DecodeArgs(&partitionID, &policyRefInfo) if err != nil { job.State = model.JobStateCancelled return 0, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, err } + if tblInfo.TiFlashReplica != nil && tblInfo.TiFlashReplica.Count > 0 { + job.State = model.JobStateCancelled + return 0, errors.Trace(dbterror.ErrIncompatibleTiFlashAndPlacement) + } + ptInfo := tblInfo.GetPartitionInfo() var partitionDef *model.PartitionDefinition definitions := ptInfo.Definitions @@ -1281,8 +1434,7 @@ func onAlterTablePartitionPlacement(t *meta.Meta, job *model.Job) (ver int64, er for i := range definitions { if partitionID == definitions[i].ID { def := &definitions[i] - oldPartitionEnablesPlacement = def.PlacementPolicyRef != nil || def.DirectPlacementOpts != nil - def.DirectPlacementOpts = placementSettings + oldPartitionEnablesPlacement = def.PlacementPolicyRef != nil def.PlacementPolicyRef = policyRefInfo partitionDef = &definitions[i] break @@ -1329,26 +1481,28 @@ func onAlterTablePartitionPlacement(t *meta.Meta, job *model.Job) (ver int64, er func onAlterTablePlacement(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { policyRefInfo := &model.PolicyRefInfo{} - placementSettings := &model.PlacementSettings{} - err = job.DecodeArgs(&policyRefInfo, &placementSettings) + err = job.DecodeArgs(&policyRefInfo) if err != nil { job.State = model.JobStateCancelled return 0, errors.Trace(err) } - tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tblInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, err } + if tblInfo.TiFlashReplica != nil && tblInfo.TiFlashReplica.Count > 0 { + job.State = model.JobStateCancelled + return 0, errors.Trace(dbterror.ErrIncompatibleTiFlashAndPlacement) + } + if _, err = checkPlacementPolicyRefValidAndCanNonValidJob(t, job, policyRefInfo); err != nil { return 0, errors.Trace(err) } - oldTableEnablesPlacement := tblInfo.PlacementPolicyRef != nil || tblInfo.DirectPlacementOpts != nil + oldTableEnablesPlacement := tblInfo.PlacementPolicyRef != nil tblInfo.PlacementPolicyRef = policyRefInfo - tblInfo.DirectPlacementOpts = placementSettings - ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) if err != nil { return ver, errors.Trace(err) @@ -1421,7 +1575,7 @@ func updateLabelRules(job *model.Job, tblInfo *model.TableInfo, oldRules map[str } func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { - tbInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tbInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, errors.Trace(err) } @@ -1432,11 +1586,11 @@ func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { } if tbInfo.TempTableType != model.TempTableNone { - return ver, errors.Trace(ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache")) + return ver, errors.Trace(dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("alter temporary table cache")) } if tbInfo.Partition != nil { - return ver, errors.Trace(ErrOptOnCacheTable.GenWithStackByArgs("partition mode")) + return ver, errors.Trace(dbterror.ErrOptOnCacheTable.GenWithStackByArgs("partition mode")) } switch tbInfo.TableCacheStatusType { @@ -1458,13 +1612,13 @@ func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo) default: job.State = model.JobStateCancelled - err = ErrInvalidDDLState.GenWithStackByArgs("alter table cache", tbInfo.TableCacheStatusType.String()) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("alter table cache", tbInfo.TableCacheStatusType.String()) } return ver, err } func onAlterNoCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { - tbInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tbInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return 0, errors.Trace(err) } @@ -1493,7 +1647,7 @@ func onAlterNoCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) { job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo) default: job.State = model.JobStateCancelled - err = ErrInvalidDDLState.GenWithStackByArgs("alter table no cache", tbInfo.TableCacheStatusType.String()) + err = dbterror.ErrInvalidDDLState.GenWithStackByArgs("alter table no cache", tbInfo.TableCacheStatusType.String()) } return ver, err } diff --git a/ddl/table_lock.go b/ddl/table_lock.go index 07498a160932a..ec4d00b6dbb55 100644 --- a/ddl/table_lock.go +++ b/ddl/table_lock.go @@ -19,6 +19,7 @@ import ( "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/util/dbterror" ) func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { @@ -39,7 +40,7 @@ func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { for i, tl := range arg.LockTables { job.SchemaID = tl.SchemaID job.TableID = tl.TableID - tbInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tbInfo, err := GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, err } @@ -59,7 +60,7 @@ func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { job.SchemaID = arg.LockTables[arg.IndexOfLock].SchemaID job.TableID = arg.LockTables[arg.IndexOfLock].TableID var tbInfo *model.TableInfo - tbInfo, err = getTableInfoAndCancelFaultJob(t, job, job.SchemaID) + tbInfo, err = GetTableInfoAndCancelFaultJob(t, job, job.SchemaID) if err != nil { return ver, err } @@ -92,7 +93,7 @@ func onLockTables(t *meta.Meta, job *model.Job) (ver int64, err error) { } default: job.State = model.JobStateCancelled - return ver, ErrInvalidDDLState.GenWithStackByArgs("table lock", tbInfo.Lock.State) + return ver, dbterror.ErrInvalidDDLState.GenWithStackByArgs("table lock", tbInfo.Lock.State) } } diff --git a/ddl/table_modify_test.go b/ddl/table_modify_test.go new file mode 100644 index 0000000000000..2cb1e88ad2933 --- /dev/null +++ b/ddl/table_modify_test.go @@ -0,0 +1,294 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "testing" + "time" + + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/admin" + "github.com/stretchr/testify/require" +) + +const tableModifyLease = 600 * time.Millisecond + +func TestCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tableModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("CREATE TABLE `t` (`a` double DEFAULT 1.0 DEFAULT now() DEFAULT 2.0 );") + tk.MustExec("CREATE TABLE IF NOT EXISTS `t` (`a` double DEFAULT 1.0 DEFAULT now() DEFAULT 2.0 );") + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + cols := tbl.Cols() + require.Len(t, cols, 1) + col := cols[0] + require.Equal(t, "a", col.Name.L) + d, ok := col.DefaultValue.(string) + require.True(t, ok) + require.Equal(t, "2.0", d) + + tk.MustExec("drop table t") + tk.MustGetErrCode("CREATE TABLE `t` (`a` int) DEFAULT CHARSET=abcdefg", errno.ErrUnknownCharacterSet) + + tk.MustExec("CREATE TABLE `collateTest` (`a` int, `b` varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci") + expects := "collateTest CREATE TABLE `collateTest` (\n `a` int(11) DEFAULT NULL,\n `b` varchar(10) COLLATE utf8_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci" + tk.MustQuery("show create table collateTest").Check(testkit.Rows(expects)) + + tk.MustGetErrCode("CREATE TABLE `collateTest2` (`a` int) CHARSET utf8 COLLATE utf8mb4_unicode_ci", errno.ErrCollationCharsetMismatch) + tk.MustGetErrCode("CREATE TABLE `collateTest3` (`a` int) COLLATE utf8mb4_unicode_ci CHARSET utf8", errno.ErrConflictingDeclarations) + + tk.MustExec("CREATE TABLE `collateTest4` (`a` int) COLLATE utf8_uniCOde_ci") + expects = "collateTest4 CREATE TABLE `collateTest4` (\n `a` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci" + tk.MustQuery("show create table collateTest4").Check(testkit.Rows(expects)) + + tk.MustExec("create database test2 default charset utf8 collate utf8_general_ci") + tk.MustExec("use test2") + tk.MustExec("create table dbCollateTest (a varchar(10))") + expects = "dbCollateTest CREATE TABLE `dbCollateTest` (\n `a` varchar(10) COLLATE utf8_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci" + tk.MustQuery("show create table dbCollateTest").Check(testkit.Rows(expects)) + + // test for enum column + tk.MustExec("use test") + tk.MustGetErrCode("create table t_enum (a enum('e','e'));", errno.ErrDuplicatedValueInType) + + tk = testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustGetErrCode("create table t_enum (a enum('e','E')) charset=utf8 collate=utf8_general_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a enum('abc','Abc')) charset=utf8 collate=utf8_general_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a enum('e','E')) charset=utf8 collate=utf8_unicode_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a enum('ss','ß')) charset=utf8 collate=utf8_unicode_ci;", errno.ErrDuplicatedValueInType) + // test for set column + tk.MustGetErrCode("create table t_enum (a set('e','e'));", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a set('e','E')) charset=utf8 collate=utf8_general_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a set('abc','Abc')) charset=utf8 collate=utf8_general_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrMsg("create table t_enum (a enum('B','b')) charset=utf8 collate=utf8_general_ci;", "[types:1291]Column 'a' has duplicated value 'b' in ENUM") + tk.MustGetErrCode("create table t_enum (a set('e','E')) charset=utf8 collate=utf8_unicode_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrCode("create table t_enum (a set('ss','ß')) charset=utf8 collate=utf8_unicode_ci;", errno.ErrDuplicatedValueInType) + tk.MustGetErrMsg("create table t_enum (a enum('ss','ß')) charset=utf8 collate=utf8_unicode_ci;", "[types:1291]Column 'a' has duplicated value 'ß' in ENUM") + + // test for table option "union" not supported + tk.MustExec("use test") + tk.MustExec("CREATE TABLE x (a INT) ENGINE = MyISAM;") + tk.MustExec("CREATE TABLE y (a INT) ENGINE = MyISAM;") + tk.MustGetErrCode("CREATE TABLE z (a INT) ENGINE = MERGE UNION = (x, y);", errno.ErrTableOptionUnionUnsupported) + tk.MustGetErrCode("ALTER TABLE x UNION = (y);", errno.ErrTableOptionUnionUnsupported) + tk.MustExec("drop table x;") + tk.MustExec("drop table y;") + + // test for table option "insert method" not supported + tk.MustExec("use test") + tk.MustExec("CREATE TABLE x (a INT) ENGINE = MyISAM;") + tk.MustExec("CREATE TABLE y (a INT) ENGINE = MyISAM;") + tk.MustGetErrCode("CREATE TABLE z (a INT) ENGINE = MERGE INSERT_METHOD=LAST;", errno.ErrTableOptionInsertMethodUnsupported) + tk.MustGetErrCode("ALTER TABLE x INSERT_METHOD=LAST;", errno.ErrTableOptionInsertMethodUnsupported) + tk.MustExec("drop table x;") + tk.MustExec("drop table y;") +} + +func TestLockTableReadOnly(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tableModifyLease) + defer clean() + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2.MustExec("use test") + tk1.MustExec("drop table if exists t1,t2") + defer func() { + tk1.MustExec("alter table t1 read write") + tk1.MustExec("alter table t2 read write") + tk1.MustExec("drop table if exists t1,t2") + }() + tk1.MustExec("create table t1 (a int key, b int)") + tk1.MustExec("create table t2 (a int key)") + + tk1.MustExec("alter table t1 read only") + tk1.MustQuery("select * from t1") + tk2.MustQuery("select * from t1") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("insert into t1 set a=1, b=2"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk1.ExecToErr("update t1 set a=1"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk1.ExecToErr("delete from t1"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("insert into t1 set a=1, b=2"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("update t1 set a=1"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("delete from t1"), infoschema.ErrTableLocked)) + + tk2.MustExec("alter table t1 read only") + require.True(t, terror.ErrorEqual(tk2.ExecToErr("insert into t1 set a=1, b=2"), infoschema.ErrTableLocked)) + + tk1.MustExec("alter table t1 read write") + tk1.MustExec("lock tables t1 read") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + tk1.MustExec("lock tables t1 write") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + tk1.MustExec("lock tables t1 write local") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("alter table t1 read only"), infoschema.ErrTableLocked)) + tk1.MustExec("unlock tables") + + tk1.MustExec("alter table t1 read only") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("lock tables t1 read"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("lock tables t1 read"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk1.ExecToErr("lock tables t1 write"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("lock tables t1 write"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk1.ExecToErr("lock tables t1 write local"), infoschema.ErrTableLocked)) + require.True(t, terror.ErrorEqual(tk2.ExecToErr("lock tables t1 write local"), infoschema.ErrTableLocked)) + tk1.MustExec("admin cleanup table lock t1") + tk2.MustExec("insert into t1 set a=1, b=2") + + tk1.MustExec("set tidb_enable_amend_pessimistic_txn = 1") + tk1.MustExec("begin pessimistic") + tk1.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 2")) + tk2.MustExec("update t1 set b = 3") + tk2.MustExec("alter table t1 read only") + tk2.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 3")) + tk1.MustQuery("select * from t1 where a = 1").Check(testkit.Rows("1 2")) + tk1.MustExec("update t1 set b = 4") + require.True(t, terror.ErrorEqual(tk1.ExecToErr("commit"), domain.ErrInfoSchemaChanged)) + tk2.MustExec("alter table t1 read write") +} + +// TestConcurrentLockTables test concurrent lock/unlock tables. +func TestConcurrentLockTables(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, tableModifyLease) + defer clean() + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2.MustExec("use test") + tk1.MustExec("create table t1 (a int)") + + // Test concurrent lock tables read. + sql1 := "lock tables t1 read" + sql2 := "lock tables t1 read" + testParallelExecSQL(t, store, dom, sql1, sql2, tk1.Session(), tk2.Session(), func(t *testing.T, err1, err2 error) { + require.NoError(t, err1) + require.NoError(t, err2) + }) + tk1.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test concurrent lock tables write. + sql1 = "lock tables t1 write" + sql2 = "lock tables t1 write" + testParallelExecSQL(t, store, dom, sql1, sql2, tk1.Session(), tk2.Session(), func(t *testing.T, err1, err2 error) { + require.NoError(t, err1) + require.True(t, terror.ErrorEqual(err2, infoschema.ErrTableLocked)) + }) + tk1.MustExec("unlock tables") + tk2.MustExec("unlock tables") + + // Test concurrent lock tables write local. + sql1 = "lock tables t1 write local" + sql2 = "lock tables t1 write local" + testParallelExecSQL(t, store, dom, sql1, sql2, tk1.Session(), tk2.Session(), func(t *testing.T, err1, err2 error) { + require.NoError(t, err1) + require.True(t, terror.ErrorEqual(err2, infoschema.ErrTableLocked)) + }) + + tk1.MustExec("unlock tables") + tk2.MustExec("unlock tables") +} + +func testParallelExecSQL(t *testing.T, store kv.Storage, dom *domain.Domain, sql1, sql2 string, se1, se2 session.Session, f func(t *testing.T, err1, err2 error)) { + callback := &ddl.TestDDLCallback{} + times := 0 + callback.OnJobRunBeforeExported = func(job *model.Job) { + if times != 0 { + return + } + var qLen int + for { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + jobs, err1 := admin.GetDDLJobs(txn) + if err1 != nil { + return err1 + } + qLen = len(jobs) + return nil + }) + require.NoError(t, err) + if qLen == 2 { + break + } + time.Sleep(5 * time.Millisecond) + } + times++ + } + d := dom.DDL() + originalCallback := d.GetHook() + defer d.SetHook(originalCallback) + d.SetHook(callback) + + var wg util.WaitGroupWrapper + var err1 error + var err2 error + ch := make(chan struct{}) + // Make sure the sql1 is put into the DDLJobQueue. + go func() { + var qLen int + for { + err := kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + jobs, err3 := admin.GetDDLJobs(txn) + if err3 != nil { + return err3 + } + qLen = len(jobs) + return nil + }) + require.NoError(t, err) + if qLen == 1 { + // Make sure sql2 is executed after the sql1. + close(ch) + break + } + time.Sleep(5 * time.Millisecond) + } + }() + wg.Run(func() { + _, err1 = se1.Execute(context.Background(), sql1) + }) + wg.Run(func() { + <-ch + _, err2 = se2.Execute(context.Background(), sql2) + }) + + wg.Wait() + f(t, err1, err2) +} + +func TestUnsupportedAlterTableOption(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tableModifyLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a char(10) not null,b char(20)) shard_row_id_bits=6") + tk.MustGetErrCode("alter table t pre_split_regions=6", errno.ErrUnsupportedDDLOperation) +} diff --git a/ddl/table_test.go b/ddl/table_test.go index f366c090b1686..105c80479f3fa 100644 --- a/ddl/table_test.go +++ b/ddl/table_test.go @@ -16,6 +16,7 @@ package ddl import ( "context" + "fmt" "testing" "github.com/pingcap/errors" @@ -30,39 +31,42 @@ import ( "github.com/stretchr/testify/require" ) -func testCreateTableT(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { +func testRenameTable( + t *testing.T, + ctx sessionctx.Context, + d *ddl, + newSchemaID, oldSchemaID int64, + oldSchemaName model.CIStr, + tblInfo *model.TableInfo, +) *model.Job { job := &model.Job{ - SchemaID: dbInfo.ID, + SchemaID: newSchemaID, TableID: tblInfo.ID, - Type: model.ActionCreateTable, + Type: model.ActionRenameTable, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{tblInfo}, + Args: []interface{}{oldSchemaID, tblInfo.Name, oldSchemaName}, } - err := d.doDDLJob(ctx, job) - require.NoError(t, err) + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) - v := getSchemaVerT(t, ctx) + v := getSchemaVer(t, ctx) tblInfo.State = model.StatePublic - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) tblInfo.State = model.StateNone return job } -func testRenameTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID, oldSchemaID int64, oldSchemaName model.CIStr, tblInfo *model.TableInfo) *model.Job { +func testRenameTables(t *testing.T, ctx sessionctx.Context, d *ddl, oldSchemaIDs, newSchemaIDs []int64, newTableNames []*model.CIStr, oldTableIDs []int64, oldSchemaNames, oldTableNames []*model.CIStr) *model.Job { job := &model.Job{ - SchemaID: newSchemaID, - TableID: tblInfo.ID, - Type: model.ActionRenameTable, + Type: model.ActionRenameTables, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{oldSchemaID, tblInfo.Name, oldSchemaName}, + Args: []interface{}{oldSchemaIDs, newSchemaIDs, newTableNames, oldTableIDs, oldSchemaNames, oldTableNames}, } - err := d.doDDLJob(ctx, job) - require.NoError(t, err) + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) - v := getSchemaVerT(t, ctx) - tblInfo.State = model.StatePublic - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - tblInfo.State = model.StateNone + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: nil}) return job } @@ -81,11 +85,12 @@ func testLockTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{arg}, } - err := d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) require.NoError(t, err) - v := getSchemaVerT(t, ctx) - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v}) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v}) return job } @@ -108,21 +113,6 @@ func checkTableLockedTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *m require.NoError(t, err) } -func testDropTableT(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionDropTable, - BinlogInfo: &model.HistoryInfo{}, - } - err := d.doDDLJob(ctx, job) - require.NoError(t, err) - - v := getSchemaVerT(t, ctx) - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - return job -} - func testTruncateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { genIDs, err := d.genGlobalIDs(1) require.NoError(t, err) @@ -134,39 +124,16 @@ func testTruncateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *mod BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{newTableID}, } - err = d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + err = d.DoDDLJob(ctx, job) require.NoError(t, err) - v := getSchemaVerT(t, ctx) + v := getSchemaVer(t, ctx) tblInfo.ID = newTableID - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } -func testCheckTableStateT(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - tt := meta.NewMeta(txn) - info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) - require.NoError(t, err) - - if state == model.StateNone { - require.Nil(t, info) - return nil - } - - require.EqualValues(t, tblInfo.Name, info.Name) - require.Equal(t, state, info.State) - return nil - }) - require.NoError(t, err) -} - -func testGetTableT(t *testing.T, d *ddl, schemaID int64, tableID int64) table.Table { - tbl, err := testGetTableWithError(d, schemaID, tableID) - require.NoError(t, err) - return tbl -} - func testGetTableWithError(d *ddl, schemaID, tableID int64) (table.Table, error) { var tblInfo *model.TableInfo err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { @@ -195,82 +162,84 @@ func testGetTableWithError(d *ddl, schemaID, tableID int64) (table.Table, error) func TestTable(t *testing.T) { store, err := mockstore.NewMockStore() require.NoError(t, err) - ddl, err := testNewDDLAndStart( + defer func() { + require.NoError(t, store.Close()) + }() + d, err := testNewDDLAndStart( context.Background(), WithStore(store), WithLease(testLease), ) require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() - dbInfo, err := testSchemaInfo(ddl, "test_table") + dbInfo, err := testSchemaInfo(d, "test_table") require.NoError(t, err) - testCreateSchemaT(t, testNewContext(ddl), ddl, dbInfo) + testCreateSchema(t, testNewContext(d), d, dbInfo) - ctx := testNewContext(ddl) + ctx := testNewContext(d) - tblInfo, err := testTableInfo(ddl, "t", 3) + tblInfo, err := testTableInfo(d, "t", 3) require.NoError(t, err) - job := testCreateTableT(t, ctx, ddl, dbInfo, tblInfo) - testCheckTableStateT(t, ddl, dbInfo, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) + job := testCreateTable(t, ctx, d, dbInfo, tblInfo) + testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) // Create an existing table. - newTblInfo, err := testTableInfo(ddl, "t", 3) + newTblInfo, err := testTableInfo(d, "t", 3) require.NoError(t, err) - doDDLJobErrT(t, dbInfo.ID, newTblInfo.ID, model.ActionCreateTable, []interface{}{newTblInfo}, ctx, ddl) + doDDLJobErr(t, dbInfo.ID, newTblInfo.ID, model.ActionCreateTable, []interface{}{newTblInfo}, ctx, d) count := 2000 - tbl := testGetTableT(t, ddl, dbInfo.ID, tblInfo.ID) + tbl := testGetTable(t, d, dbInfo.ID, tblInfo.ID) for i := 1; i <= count; i++ { _, err := tbl.AddRecord(ctx, types.MakeDatums(i, i, i)) require.NoError(t, err) } - job = testDropTableT(t, ctx, ddl, dbInfo, tblInfo) - testCheckJobDoneT(t, ddl, job, false) + job = testDropTable(t, ctx, d, dbInfo, tblInfo) + testCheckJobDone(t, d, job, false) // for truncate table - tblInfo, err = testTableInfo(ddl, "tt", 3) + tblInfo, err = testTableInfo(d, "tt", 3) require.NoError(t, err) - job = testCreateTableT(t, ctx, ddl, dbInfo, tblInfo) - testCheckTableStateT(t, ddl, dbInfo, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) - job = testTruncateTable(t, ctx, ddl, dbInfo, tblInfo) - testCheckTableStateT(t, ddl, dbInfo, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) + job = testCreateTable(t, ctx, d, dbInfo, tblInfo) + testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + job = testTruncateTable(t, ctx, d, dbInfo, tblInfo) + testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) // for rename table - dbInfo1, err := testSchemaInfo(ddl, "test_rename_table") + dbInfo1, err := testSchemaInfo(d, "test_rename_table") require.NoError(t, err) - testCreateSchemaT(t, testNewContext(ddl), ddl, dbInfo1) - job = testRenameTable(t, ctx, ddl, dbInfo1.ID, dbInfo.ID, dbInfo.Name, tblInfo) - testCheckTableStateT(t, ddl, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) - - job = testLockTable(t, ctx, ddl, dbInfo1.ID, tblInfo, model.TableLockWrite) - testCheckTableStateT(t, ddl, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) - checkTableLockedTest(t, ddl, dbInfo1, tblInfo, ddl.GetID(), ctx.GetSessionVars().ConnectionID, model.TableLockWrite) + testCreateSchema(t, testNewContext(d), d, dbInfo1) + job = testRenameTable(t, ctx, d, dbInfo1.ID, dbInfo.ID, dbInfo.Name, tblInfo) + testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + + job = testLockTable(t, ctx, d, dbInfo1.ID, tblInfo, model.TableLockWrite) + testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + checkTableLockedTest(t, d, dbInfo1, tblInfo, d.GetID(), ctx.GetSessionVars().ConnectionID, model.TableLockWrite) // for alter cache table - job = testAlterCacheTable(t, ctx, ddl, dbInfo1.ID, tblInfo) - testCheckTableStateT(t, ddl, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) - checkTableCacheTest(t, ddl, dbInfo1, tblInfo) + job = testAlterCacheTable(t, ctx, d, dbInfo1.ID, tblInfo) + testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + checkTableCacheTest(t, d, dbInfo1, tblInfo) // for alter no cache table - job = testAlterNoCacheTable(t, ctx, ddl, dbInfo1.ID, tblInfo) - testCheckTableStateT(t, ddl, dbInfo1, tblInfo, model.StatePublic) - testCheckJobDoneT(t, ddl, job, true) - checkTableNoCacheTest(t, ddl, dbInfo1, tblInfo) + job = testAlterNoCacheTable(t, ctx, d, dbInfo1.ID, tblInfo) + testCheckTableState(t, d, dbInfo1, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + checkTableNoCacheTest(t, d, dbInfo1, tblInfo) - testDropSchemaT(t, testNewContext(ddl), ddl, dbInfo) - err = ddl.Stop() - require.NoError(t, err) - err = store.Close() - require.NoError(t, err) + testDropSchema(t, testNewContext(d), d, dbInfo) } func checkTableCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { tt := meta.NewMeta(txn) info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) require.NoError(t, err) @@ -278,20 +247,18 @@ func checkTableCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *mo require.NotNil(t, info.TableCacheStatusType) require.Equal(t, model.TableCacheStatusEnable, info.TableCacheStatusType) return nil - }) - require.NoError(t, err) + })) } func checkTableNoCacheTest(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { tt := meta.NewMeta(txn) info, err := tt.GetTable(dbInfo.ID, tblInfo.ID) require.NoError(t, err) require.NotNil(t, info) require.Equal(t, model.TableCacheStatusDisable, info.TableCacheStatusType) return nil - }) - require.NoError(t, err) + })) } func testAlterCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { @@ -302,16 +269,16 @@ func testAlterCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchema BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{}, } - err := d.doDDLJob(ctx, job) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) require.NoError(t, err) - v := getSchemaVerT(t, ctx) - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v}) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v}) return job } func testAlterNoCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job { - job := &model.Job{ SchemaID: newSchemaID, TableID: tblInfo.ID, @@ -319,10 +286,111 @@ func testAlterNoCacheTable(t *testing.T, ctx sessionctx.Context, d *ddl, newSche BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{}, } - err := d.doDDLJob(ctx, job) - require.NoError(t, err) + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) - v := getSchemaVerT(t, ctx) - checkHistoryJobArgsT(t, ctx, job.ID, &historyJobArgs{ver: v}) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v}) return job } + +func TestRenameTables(t *testing.T) { + store, err := mockstore.NewMockStore() + defer func() { + require.NoError(t, store.Close()) + }() + require.NoError(t, err) + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() + + dbInfo, err := testSchemaInfo(d, "test_table") + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) + + ctx := testNewContext(d) + var tblInfos = make([]*model.TableInfo, 0, 2) + var newTblInfos = make([]*model.TableInfo, 0, 2) + for i := 1; i < 3; i++ { + tableName := fmt.Sprintf("t%d", i) + tblInfo, err := testTableInfo(d, tableName, 3) + require.NoError(t, err) + job := testCreateTable(t, ctx, d, dbInfo, tblInfo) + testCheckTableState(t, d, dbInfo, tblInfo, model.StatePublic) + testCheckJobDone(t, d, job, true) + tblInfos = append(tblInfos, tblInfo) + + newTableName := fmt.Sprintf("tt%d", i) + tblInfo, err = testTableInfo(d, newTableName, 3) + require.NoError(t, err) + newTblInfos = append(newTblInfos, tblInfo) + } + + job := testRenameTables(t, ctx, d, []int64{dbInfo.ID, dbInfo.ID}, []int64{dbInfo.ID, dbInfo.ID}, []*model.CIStr{&newTblInfos[0].Name, &newTblInfos[1].Name}, []int64{tblInfos[0].ID, tblInfos[1].ID}, []*model.CIStr{&dbInfo.Name, &dbInfo.Name}, []*model.CIStr{&tblInfos[0].Name, &tblInfos[1].Name}) + + txn, _ := ctx.Txn(true) + historyJob, _ := meta.NewMeta(txn).GetHistoryDDLJob(job.ID) + wantTblInfos := historyJob.BinlogInfo.MultipleTableInfos + require.Equal(t, wantTblInfos[0].Name.L, "tt1") + require.Equal(t, wantTblInfos[1].Name.L, "tt2") +} + +func TestCreateTables(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + require.NoError(t, store.Close()) + }() + d, err := testNewDDLAndStart( + context.Background(), + WithStore(store), + WithLease(testLease), + ) + require.NoError(t, err) + defer func() { + require.NoError(t, d.Stop()) + }() + + dbInfo, err := testSchemaInfo(d, "test_table") + require.NoError(t, err) + testCreateSchema(t, testNewContext(d), d, dbInfo) + + ctx := testNewContext(d) + + var infos []*model.TableInfo + genIDs, err := d.genGlobalIDs(3) + require.NoError(t, err) + + infos = append(infos, &model.TableInfo{ + ID: genIDs[0], + Name: model.NewCIStr("s1"), + }) + infos = append(infos, &model.TableInfo{ + ID: genIDs[1], + Name: model.NewCIStr("s2"), + }) + infos = append(infos, &model.TableInfo{ + ID: genIDs[2], + Name: model.NewCIStr("s3"), + }) + + job := &model.Job{ + SchemaID: dbInfo.ID, + Type: model.ActionCreateTables, + BinlogInfo: &model.HistoryInfo{}, + Args: []interface{}{infos}, + } + ctx.SetValue(sessionctx.QueryString, "skip") + err = d.DoDDLJob(ctx, job) + require.NoError(t, err) + + testGetTable(t, d, dbInfo.ID, genIDs[0]) + testGetTable(t, d, dbInfo.ID, genIDs[1]) + testGetTable(t, d, dbInfo.ID, genIDs[2]) +} diff --git a/ddl/testutil/testutil.go b/ddl/testutil/testutil.go index 3b4d2911f0bcb..a18d0e045fb3c 100644 --- a/ddl/testutil/testutil.go +++ b/ddl/testutil/testutil.go @@ -28,8 +28,8 @@ import ( ) // SessionExecInGoroutine export for testing. -func SessionExecInGoroutine(s kv.Storage, sql string, done chan error) { - ExecMultiSQLInGoroutine(s, "test_db", []string{sql}, done) +func SessionExecInGoroutine(s kv.Storage, dbName, sql string, done chan error) { + ExecMultiSQLInGoroutine(s, dbName, []string{sql}, done) } // ExecMultiSQLInGoroutine exports for testing. @@ -53,7 +53,7 @@ func ExecMultiSQLInGoroutine(s kv.Storage, dbName string, multiSQL []string, don return } if rs != nil { - done <- errors.Errorf("RecordSet should be empty.") + done <- errors.Errorf("RecordSet should be empty") return } done <- nil diff --git a/ddl/tiflash_replica_test.go b/ddl/tiflash_replica_test.go new file mode 100644 index 0000000000000..5aee99eac0792 --- /dev/null +++ b/ddl/tiflash_replica_test.go @@ -0,0 +1,446 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ddl_test + +import ( + "context" + "fmt" + "math" + "strings" + "sync" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/stretchr/testify/require" +) + +const tiflashReplicaLease = 600 * time.Millisecond + +func TestSetTableFlashReplica(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tiflashReplicaLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t_flash(a int, b int)") + + tbl := external.GetTableByName(t, tk, "test", "t_flash") + require.Nil(t, tbl.Meta().TiFlashReplica) + + tk.MustExec("alter table t_flash set tiflash replica 2 location labels 'a','b';") + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.NotNil(t, tbl.Meta().TiFlashReplica) + require.Equal(t, uint64(2), tbl.Meta().TiFlashReplica.Count) + require.Equal(t, "a,b", strings.Join(tbl.Meta().TiFlashReplica.LocationLabels, ",")) + + tk.MustExec("alter table t_flash set tiflash replica 0") + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.Nil(t, tbl.Meta().TiFlashReplica) + + // Test set tiflash replica for partition table. + tk.MustExec("drop table if exists t_flash;") + tk.MustExec("create table t_flash(a int, b int) partition by hash(a) partitions 3") + tk.MustExec("alter table t_flash set tiflash replica 2 location labels 'a','b';") + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.NotNil(t, tbl.Meta().TiFlashReplica) + require.Equal(t, uint64(2), tbl.Meta().TiFlashReplica.Count) + require.Equal(t, "a,b", strings.Join(tbl.Meta().TiFlashReplica.LocationLabels, ",")) + + // Use table ID as physical ID, mock for partition feature was not enabled. + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tbl.Meta().ID, true) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.NotNil(t, tbl.Meta().TiFlashReplica) + require.True(t, tbl.Meta().TiFlashReplica.Available) + require.Len(t, tbl.Meta().TiFlashReplica.AvailablePartitionIDs, 0) + + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tbl.Meta().ID, false) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.False(t, tbl.Meta().TiFlashReplica.Available) + + // Mock for partition 0 replica was available. + partition := tbl.Meta().Partition + require.Len(t, partition.Definitions, 3) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.False(t, tbl.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID}, tbl.Meta().TiFlashReplica.AvailablePartitionIDs) + + // Mock for partition 0 replica become unavailable. + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, false) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.False(t, tbl.Meta().TiFlashReplica.Available) + require.Len(t, tbl.Meta().TiFlashReplica.AvailablePartitionIDs, 0) + + // Mock for partition 0, 1,2 replica was available. + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[1].ID, true) + require.NoError(t, err) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[2].ID, true) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.True(t, tbl.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID, partition.Definitions[2].ID}, tbl.Meta().TiFlashReplica.AvailablePartitionIDs) + + // Mock for partition 1 replica was unavailable. + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[1].ID, false) + require.NoError(t, err) + tbl = external.GetTableByName(t, tk, "test", "t_flash") + require.Equal(t, false, tbl.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID, partition.Definitions[2].ID}, tbl.Meta().TiFlashReplica.AvailablePartitionIDs) + + // Test for update table replica with unknown table ID. + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), math.MaxInt64, false) + require.EqualError(t, err, "[schema:1146]Table which ID = 9223372036854775807 does not exist.") + + // Test for FindTableByPartitionID. + is := domain.GetDomain(tk.Session()).InfoSchema() + tbl, dbInfo, _ := is.FindTableByPartitionID(partition.Definitions[0].ID) + require.NotNil(t, tbl) + require.NotNil(t, dbInfo) + require.Equal(t, "t_flash", tbl.Meta().Name.L) + tbl, dbInfo, _ = is.FindTableByPartitionID(tbl.Meta().ID) + require.Nil(t, tbl) + require.Nil(t, dbInfo) + err = failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") + require.NoError(t, err) + + // Test for set replica count more than the tiflash store count. + tk.MustExec("drop table if exists t_flash;") + tk.MustExec("create table t_flash(a int, b int)") + tk.MustGetErrMsg("alter table t_flash set tiflash replica 2 location labels 'a','b';", "the tiflash replica count: 2 should be less than the total tiflash server count: 0") +} + +func TestSetTiFlashReplicaForTemporaryTable(t *testing.T) { + // test for tiflash replica + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount")) + }() + + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tiflashReplicaLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create global temporary table temp(id int) on commit delete rows") + tk.MustExec("create temporary table temp2(id int)") + tk.MustGetErrCode("alter table temp set tiflash replica 1", errno.ErrOptOnTemporaryTable) + tk.MustGetErrCode("alter table temp2 set tiflash replica 1", errno.ErrUnsupportedDDLOperation) + tk.MustExec("drop table temp, temp2") + + tk.MustExec("drop table if exists normal") + tk.MustExec("create table normal(id int)") + tk.MustExec("alter table normal set tiflash replica 1") + tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='normal'").Check(testkit.Rows("1")) + tk.MustExec("create global temporary table temp like normal on commit delete rows") + tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='temp'").Check(testkit.Rows()) + tk.MustExec("drop table temp") + tk.MustExec("create temporary table temp like normal") + tk.MustQuery("select REPLICA_COUNT from information_schema.tiflash_replica where table_schema='test' and table_name='temp'").Check(testkit.Rows()) +} + +func TestSetTableFlashReplicaForSystemTable(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tiflashReplicaLease) + defer clean() + + tk := testkit.NewTestKit(t, store) + sysTables := make([]string, 0, 24) + memOrSysDB := []string{"MySQL", "INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "METRICS_SCHEMA"} + for _, db := range memOrSysDB { + tk.MustExec("use " + db) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + rows := tk.MustQuery("show tables").Rows() + for i := 0; i < len(rows); i++ { + sysTables = append(sysTables, rows[i][0].(string)) + } + for _, one := range sysTables { + _, err := tk.Exec(fmt.Sprintf("alter table `%s` set tiflash replica 1", one)) + if db == "MySQL" { + require.Equal(t, "[ddl:8200]ALTER table replica for tables in system database is currently unsupported", err.Error()) + } else { + require.Equal(t, fmt.Sprintf("[planner:1142]ALTER command denied to user 'root'@'%%' for table '%s'", strings.ToLower(one)), err.Error()) + } + + } + sysTables = sysTables[:0] + } +} + +func TestSkipSchemaChecker(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) + defer func() { + err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") + require.NoError(t, err) + }() + + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tiflashReplicaLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int)") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + // Test skip schema checker for ActionSetTiFlashReplica. + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1;") + tk2.MustExec("alter table t1 set tiflash replica 2 location labels 'a','b';") + tk.MustExec("commit") + + // Test skip schema checker for ActionUpdateTiFlashReplicaStatus. + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1;") + tb := external.GetTableByName(t, tk, "test", "t1") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tk.MustExec("commit") + + // Test can't skip schema checker. + tk.MustExec("begin") + tk.MustExec("insert into t1 set a=1;") + tk2.MustExec("alter table t1 add column b int;") + err = tk.ExecToErr("commit") + require.True(t, terror.ErrorEqual(domain.ErrInfoSchemaChanged, err)) +} + +// TestCreateTableWithLike2 tests create table with like when refer table have non-public column/index. +func TestCreateTableWithLike2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, tiflashReplicaLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (a int, b int, c int, index idx1(c));") + + tbl1 := external.GetTableByName(t, tk, "test", "t1") + doneCh := make(chan error, 2) + hook := &ddl.TestDDLCallback{Do: dom} + var onceChecker sync.Map + hook.OnJobRunBeforeExported = func(job *model.Job) { + if job.Type != model.ActionAddColumn && job.Type != model.ActionDropColumn && + job.Type != model.ActionAddIndex && job.Type != model.ActionDropIndex { + return + } + if job.TableID != tbl1.Meta().ID { + return + } + + if job.SchemaState == model.StateDeleteOnly { + if _, ok := onceChecker.Load(job.ID); ok { + return + } + + onceChecker.Store(job.ID, true) + go backgroundExec(store, "create table t2 like t1", doneCh) + } + } + originalHook := dom.DDL().GetHook() + defer dom.DDL().SetHook(originalHook) + dom.DDL().SetHook(hook) + + // create table when refer table add column + tk.MustExec("alter table t1 add column d int") + checkTbl2 := func() { + err := <-doneCh + require.NoError(t, err) + tk.MustExec("alter table t2 add column e int") + t2Info := external.GetTableByName(t, tk, "test", "t2") + require.Equal(t, len(t2Info.Cols()), len(t2Info.Meta().Columns)) + } + checkTbl2() + + // create table when refer table drop column + tk.MustExec("drop table t2;") + tk.MustExec("alter table t1 drop column b;") + checkTbl2() + + // create table when refer table add index + tk.MustExec("drop table t2;") + tk.MustExec("alter table t1 add index idx2(a);") + checkTbl2 = func() { + err := <-doneCh + require.NoError(t, err) + tk.MustExec("alter table t2 add column e int") + tbl2 := external.GetTableByName(t, tk, "test", "t2") + require.Equal(t, len(tbl2.Cols()), len(tbl2.Meta().Columns)) + + for i := 0; i < len(tbl2.Meta().Indices); i++ { + require.Equal(t, model.StatePublic, tbl2.Meta().Indices[i].State) + } + } + checkTbl2() + + // create table when refer table drop index. + tk.MustExec("drop table t2;") + tk.MustExec("alter table t1 drop index idx2;") + checkTbl2() + + // Test for table has tiflash replica. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) + defer func() { + err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") + require.NoError(t, err) + }() + + dom.DDL().SetHook(originalHook) + tk.MustExec("drop table if exists t1,t2;") + tk.MustExec("create table t1 (a int) partition by hash(a) partitions 2;") + tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") + t1 := external.GetTableByName(t, tk, "test", "t1") + // Mock for all partitions replica was available. + partition := t1.Meta().Partition + require.Equal(t, 2, len(partition.Definitions)) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[1].ID, true) + require.NoError(t, err) + t1 = external.GetTableByName(t, tk, "test", "t1") + require.NotNil(t, t1.Meta().TiFlashReplica) + require.True(t, t1.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}, t1.Meta().TiFlashReplica.AvailablePartitionIDs) + + tk.MustExec("create table t2 like t1") + t2 := external.GetTableByName(t, tk, "test", "t2") + require.Equal(t, t1.Meta().TiFlashReplica.Count, t2.Meta().TiFlashReplica.Count) + require.Equal(t, t1.Meta().TiFlashReplica.LocationLabels, t2.Meta().TiFlashReplica.LocationLabels) + require.False(t, t2.Meta().TiFlashReplica.Available) + require.Len(t, t2.Meta().TiFlashReplica.AvailablePartitionIDs, 0) + // Test for not affecting the original table. + t1 = external.GetTableByName(t, tk, "test", "t1") + require.NotNil(t, t1.Meta().TiFlashReplica) + require.True(t, t1.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}, t1.Meta().TiFlashReplica.AvailablePartitionIDs) +} + +func TestTruncateTable2(t *testing.T) { + store, clean := testkit.CreateMockStoreWithSchemaLease(t, tiflashReplicaLease) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table truncate_table (c1 int, c2 int)") + tk.MustExec("insert truncate_table values (1, 1), (2, 2)") + is := domain.GetDomain(tk.Session()).InfoSchema() + oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("truncate_table")) + require.NoError(t, err) + oldTblID := oldTblInfo.Meta().ID + + tk.MustExec("truncate table truncate_table") + + tk.MustExec("insert truncate_table values (3, 3), (4, 4)") + tk.MustQuery("select * from truncate_table").Check(testkit.Rows("3 3", "4 4")) + + is = domain.GetDomain(tk.Session()).InfoSchema() + newTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("truncate_table")) + require.NoError(t, err) + require.Greater(t, newTblInfo.Meta().ID, oldTblID) + + // Verify that the old table data has been deleted by background worker. + tablePrefix := tablecodec.EncodeTablePrefix(oldTblID) + hasOldTableData := true + for i := 0; i < waitForCleanDataRound; i++ { + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { + it, err1 := txn.Iter(tablePrefix, nil) + if err1 != nil { + return err1 + } + if !it.Valid() { + hasOldTableData = false + } else { + hasOldTableData = it.Key().HasPrefix(tablePrefix) + } + it.Close() + return nil + }) + require.NoError(t, err) + if !hasOldTableData { + break + } + time.Sleep(waitForCleanDataInterval) + } + require.False(t, hasOldTableData) + + // Test for truncate table should clear the tiflash available status. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount")) + }() + + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1 (a int);") + tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") + t1 := external.GetTableByName(t, tk, "test", "t1") + // Mock for table tiflash replica was available. + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), t1.Meta().ID, true) + require.NoError(t, err) + t1 = external.GetTableByName(t, tk, "test", "t1") + require.NotNil(t, t1.Meta().TiFlashReplica) + require.True(t, t1.Meta().TiFlashReplica.Available) + + tk.MustExec("truncate table t1") + t2 := external.GetTableByName(t, tk, "test", "t1") + require.Equal(t, t1.Meta().TiFlashReplica.Count, t2.Meta().TiFlashReplica.Count) + require.Equal(t, t1.Meta().TiFlashReplica.LocationLabels, t2.Meta().TiFlashReplica.LocationLabels) + require.False(t, t2.Meta().TiFlashReplica.Available) + require.Len(t, t2.Meta().TiFlashReplica.AvailablePartitionIDs, 0) + + // Test for truncate partition should clear the tiflash available status. + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1 (a int) partition by hash(a) partitions 2;") + tk.MustExec("alter table t1 set tiflash replica 3 location labels 'a','b';") + t1 = external.GetTableByName(t, tk, "test", "t1") + // Mock for all partitions replica was available. + partition := t1.Meta().Partition + require.Equal(t, 2, len(partition.Definitions)) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[0].ID, true) + require.NoError(t, err) + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.Definitions[1].ID, true) + require.NoError(t, err) + t1 = external.GetTableByName(t, tk, "test", "t1") + require.NotNil(t, t1.Meta().TiFlashReplica) + require.True(t, t1.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[0].ID, partition.Definitions[1].ID}, t1.Meta().TiFlashReplica.AvailablePartitionIDs) + + tk.MustExec("alter table t1 truncate partition p0") + t2 = external.GetTableByName(t, tk, "test", "t1") + require.Equal(t, t1.Meta().TiFlashReplica.Count, t2.Meta().TiFlashReplica.Count) + require.Equal(t, t1.Meta().TiFlashReplica.LocationLabels, t2.Meta().TiFlashReplica.LocationLabels) + require.False(t, t2.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[1].ID}, t2.Meta().TiFlashReplica.AvailablePartitionIDs) + // Test for truncate twice. + tk.MustExec("alter table t1 truncate partition p0") + t2 = external.GetTableByName(t, tk, "test", "t1") + require.Equal(t, t1.Meta().TiFlashReplica.Count, t2.Meta().TiFlashReplica.Count) + require.Equal(t, t1.Meta().TiFlashReplica.LocationLabels, t2.Meta().TiFlashReplica.LocationLabels) + require.False(t, t2.Meta().TiFlashReplica.Available) + require.Equal(t, []int64{partition.Definitions[1].ID}, t2.Meta().TiFlashReplica.AvailablePartitionIDs) + +} diff --git a/ddl/util/dead_table_lock_checker.go b/ddl/util/dead_table_lock_checker.go index f05c1aa9534fa..b77be4d54412d 100644 --- a/ddl/util/dead_table_lock_checker.go +++ b/ddl/util/dead_table_lock_checker.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" ) diff --git a/ddl/util/main_test.go b/ddl/util/main_test.go index 3dc8c61daacda..eef260a706759 100644 --- a/ddl/util/main_test.go +++ b/ddl/util/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), } goleak.VerifyTestMain(m, opts...) } diff --git a/ddl/util/syncer.go b/ddl/util/syncer.go index 287d49fa35c34..aa3cad4976fb4 100644 --- a/ddl/util/syncer.go +++ b/ddl/util/syncer.go @@ -31,9 +31,9 @@ import ( "github.com/pingcap/tidb/parser/terror" tidbutil "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/clientv3/concurrency" - "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3/concurrency" "go.uber.org/zap" ) diff --git a/ddl/util/syncer_serial_test.go b/ddl/util/syncer_test.go similarity index 96% rename from ddl/util/syncer_serial_test.go rename to ddl/util/syncer_test.go index b1cea5d787a09..75ca82c5bd698 100644 --- a/ddl/util/syncer_serial_test.go +++ b/ddl/util/syncer_test.go @@ -18,7 +18,6 @@ import ( "context" "fmt" "runtime" - "sync" "testing" "time" @@ -29,11 +28,12 @@ import ( "github.com/pingcap/tidb/owner" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/etcdserver" - "go.etcd.io/etcd/integration" - "go.etcd.io/etcd/mvcc/mvccpb" + "go.etcd.io/etcd/api/v3/mvccpb" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/tests/v3/integration" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -45,6 +45,7 @@ func TestSyncerSimple(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) origin := CheckVersFirstWaitTime CheckVersFirstWaitTime = 0 @@ -108,12 +109,10 @@ func TestSyncerSimple(t *testing.T) { require.NoError(t, d1.SchemaSyncer().Init(ctx)) // for watchCh - wg := sync.WaitGroup{} - wg.Add(1) + var wg util.WaitGroupWrapper currentVer := int64(123) var checkErr string - go func() { - defer wg.Done() + wg.Run(func() { select { case resp := <-d.SchemaSyncer().GlobalVersionCh(): if len(resp.Events) < 1 { @@ -125,7 +124,7 @@ func TestSyncerSimple(t *testing.T) { checkErr = "get update version failed" return } - }() + }) // for update latestSchemaVersion require.NoError(t, d.SchemaSyncer().OwnerUpdateGlobalVersion(ctx, currentVer)) diff --git a/ddl/util/util.go b/ddl/util/util.go index 62dba84cb4e62..d4836a187f832 100644 --- a/ddl/util/util.go +++ b/ddl/util/util.go @@ -15,9 +15,11 @@ package util import ( + "bytes" "context" "encoding/hex" "strings" + "time" "github.com/pingcap/errors" "github.com/pingcap/tidb/kv" @@ -26,6 +28,8 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/sqlexec" + "github.com/tikv/client-go/v2/tikvrpc" + atomicutil "go.uber.org/atomic" ) const ( @@ -102,14 +106,23 @@ func loadDeleteRangesFromTable(ctx sessionctx.Context, table string, safePoint u } // CompleteDeleteRange moves a record from gc_delete_range table to gc_delete_range_done table. -// NOTE: This function WILL NOT start and run in a new transaction internally. func CompleteDeleteRange(ctx sessionctx.Context, dr DelRangeTask) error { - _, err := ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), recordDoneDeletedRangeSQL, dr.JobID, dr.ElementID) + _, err := ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "BEGIN") if err != nil { return errors.Trace(err) } - return RemoveFromGCDeleteRange(ctx, dr.JobID, dr.ElementID) + _, err = ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), recordDoneDeletedRangeSQL, dr.JobID, dr.ElementID) + if err != nil { + return errors.Trace(err) + } + + err = RemoveFromGCDeleteRange(ctx, dr.JobID, dr.ElementID) + if err != nil { + return errors.Trace(err) + } + _, err = ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "COMMIT") + return errors.Trace(err) } // RemoveFromGCDeleteRange is exported for ddl pkg to use. @@ -176,11 +189,7 @@ func LoadGlobalVars(ctx context.Context, sctx sessionctx.Context, varNames []str paramNames = append(paramNames, name) } buf.WriteString(")") - stmt, err := e.ParseWithParams(ctx, buf.String(), paramNames...) - if err != nil { - return errors.Trace(err) - } - rows, _, err := e.ExecRestrictedStmt(ctx, stmt) + rows, _, err := e.ExecRestrictedSQL(ctx, nil, buf.String(), paramNames...) if err != nil { return errors.Trace(err) } @@ -194,3 +203,51 @@ func LoadGlobalVars(ctx context.Context, sctx sessionctx.Context, varNames []str } return nil } + +// GetTimeZone gets the session location's zone name and offset. +func GetTimeZone(sctx sessionctx.Context) (string, int) { + loc := sctx.GetSessionVars().Location() + name := loc.String() + if name != "" { + _, err := time.LoadLocation(name) + if err == nil { + return name, 0 + } + } + _, offset := time.Now().In(loc).Zone() + return "UTC", offset +} + +// enableEmulatorGC means whether to enable emulator GC. The default is enable. +// In some unit tests, we want to stop emulator GC, then wen can set enableEmulatorGC to 0. +var emulatorGCEnable = atomicutil.NewInt32(1) + +// EmulatorGCEnable enables emulator gc. It exports for testing. +func EmulatorGCEnable() { + emulatorGCEnable.Store(1) +} + +// EmulatorGCDisable disables emulator gc. It exports for testing. +func EmulatorGCDisable() { + emulatorGCEnable.Store(0) +} + +// IsEmulatorGCEnable indicates whether emulator GC enabled. It exports for testing. +func IsEmulatorGCEnable() bool { + return emulatorGCEnable.Load() == 1 +} + +var internalResourceGroupTag = []byte{0} + +// GetInternalResourceGroupTaggerForTopSQL only use for testing. +func GetInternalResourceGroupTaggerForTopSQL() tikvrpc.ResourceGroupTagger { + tagger := func(req *tikvrpc.Request) { + req.ResourceGroupTag = internalResourceGroupTag + } + return tagger +} + +// IsInternalResourceGroupTaggerForTopSQL use for testing. +func IsInternalResourceGroupTaggerForTopSQL(tag []byte) bool { + return bytes.Equal(tag, internalResourceGroupTag) +} diff --git a/ddl/util_test.go b/ddl/util_test.go index 85baca2ffdd43..20d538f3dab81 100644 --- a/ddl/util_test.go +++ b/ddl/util_test.go @@ -15,24 +15,23 @@ package ddl import ( - "bytes" "context" "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" - "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -func testTableInfoWith2IndexOnFirstColumn(c *C, d *ddl, name string, num int) *model.TableInfo { +func testTableInfoWith2IndexOnFirstColumn(t *testing.T, d *ddl, name string, num int) *model.TableInfo { normalInfo, err := testTableInfo(d, name, num) - c.Assert(err, IsNil) + require.NoError(t, err) idxs := make([]*model.IndexInfo, 0, 2) for i := range idxs { idx := &model.IndexInfo{ @@ -79,11 +78,11 @@ func testTableInfo(d *ddl, name string, num int) (*model.TableInfo, error) { } // testTableInfoWithPartition creates a test table with num int columns and with no index. -func testTableInfoWithPartition(c *C, d *ddl, name string, num int) *model.TableInfo { +func testTableInfoWithPartition(t *testing.T, d *ddl, name string, num int) *model.TableInfo { tblInfo, err := testTableInfo(d, name, num) - c.Assert(err, IsNil) + require.NoError(t, err) genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) + require.NoError(t, err) pid := genIDs[0] tblInfo.Partition = &model.PartitionInfo{ Type: model.PartitionTypeRange, @@ -100,15 +99,15 @@ func testTableInfoWithPartition(c *C, d *ddl, name string, num int) *model.Table } // testTableInfoWithPartitionLessThan creates a test table with num int columns and one partition specified with lessthan. -func testTableInfoWithPartitionLessThan(c *C, d *ddl, name string, num int, lessthan string) *model.TableInfo { - tblInfo := testTableInfoWithPartition(c, d, name, num) +func testTableInfoWithPartitionLessThan(t *testing.T, d *ddl, name string, num int, lessthan string) *model.TableInfo { + tblInfo := testTableInfoWithPartition(t, d, name, num) tblInfo.Partition.Definitions[0].LessThan = []string{lessthan} return tblInfo } -func testAddedNewTablePartitionInfo(c *C, d *ddl, tblInfo *model.TableInfo, partName, lessthan string) *model.PartitionInfo { +func testAddedNewTablePartitionInfo(t *testing.T, d *ddl, tblInfo *model.TableInfo, partName, lessthan string) *model.PartitionInfo { genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) + require.NoError(t, err) pid := genIDs[0] // the new added partition should change the partition state to state none at the beginning. return &model.PartitionInfo{ @@ -123,44 +122,7 @@ func testAddedNewTablePartitionInfo(c *C, d *ddl, tblInfo *model.TableInfo, part } } -// testViewInfo creates a test view with num int columns. -func testViewInfo(c *C, d *ddl, name string, num int) *model.TableInfo { - tblInfo := &model.TableInfo{ - Name: model.NewCIStr(name), - } - genIDs, err := d.genGlobalIDs(1) - c.Assert(err, IsNil) - tblInfo.ID = genIDs[0] - - cols := make([]*model.ColumnInfo, num) - viewCols := make([]model.CIStr, num) - - var stmtBuffer bytes.Buffer - stmtBuffer.WriteString("SELECT ") - for i := range cols { - col := &model.ColumnInfo{ - Name: model.NewCIStr(fmt.Sprintf("c%d", i+1)), - Offset: i, - State: model.StatePublic, - } - - col.ID = allocateColumnID(tblInfo) - cols[i] = col - viewCols[i] = col.Name - stmtBuffer.WriteString(cols[i].Name.L + ",") - } - stmtBuffer.WriteString("1 FROM t") - - view := model.ViewInfo{Cols: viewCols, Security: model.SecurityDefiner, Algorithm: model.AlgorithmMerge, - SelectStmt: stmtBuffer.String(), CheckOption: model.CheckOptionCascaded, Definer: &auth.UserIdentity{CurrentUser: true}} - - tblInfo.View = &view - tblInfo.Columns = cols - - return tblInfo -} - -func testCreateTable(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { +func testCreateTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, TableID: tblInfo.ID, @@ -168,90 +130,51 @@ func testCreateTable(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, BinlogInfo: &model.HistoryInfo{}, Args: []interface{}{tblInfo}, } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) - - v := getSchemaVer(c, ctx) - tblInfo.State = model.StatePublic - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) - tblInfo.State = model.StateNone - return job -} - -func testCreateView(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { - job := &model.Job{ - SchemaID: dbInfo.ID, - TableID: tblInfo.ID, - Type: model.ActionCreateView, - BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{tblInfo, false, 0}, - } - - c.Assert(tblInfo.IsView(), IsTrue) - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) + ctx.SetValue(sessionctx.QueryString, "skip") + err := d.DoDDLJob(ctx, job) + require.NoError(t, err) - v := getSchemaVer(c, ctx) + v := getSchemaVer(t, ctx) tblInfo.State = model.StatePublic - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) tblInfo.State = model.StateNone return job } -func testDropTable(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { +func testDropTable(t *testing.T, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) *model.Job { job := &model.Job{ SchemaID: dbInfo.ID, TableID: tblInfo.ID, Type: model.ActionDropTable, BinlogInfo: &model.HistoryInfo{}, } - err := d.doDDLJob(ctx, job) - c.Assert(err, IsNil) + ctx.SetValue(sessionctx.QueryString, "skip") + require.NoError(t, d.DoDDLJob(ctx, job)) - v := getSchemaVer(c, ctx) - checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) + v := getSchemaVer(t, ctx) + checkHistoryJobArgs(t, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo}) return job } -func testCheckTableState(c *C, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { - err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { - t := meta.NewMeta(txn) - info, err := t.GetTable(dbInfo.ID, tblInfo.ID) - c.Assert(err, IsNil) +func testCheckTableState(t *testing.T, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, state model.SchemaState) { + require.NoError(t, kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error { + m := meta.NewMeta(txn) + info, err := m.GetTable(dbInfo.ID, tblInfo.ID) + require.NoError(t, err) if state == model.StateNone { - c.Assert(info, IsNil) + require.NoError(t, err) return nil } - c.Assert(info.Name, DeepEquals, tblInfo.Name) - c.Assert(info.State, Equals, state) + require.Equal(t, info.Name, tblInfo.Name) + require.Equal(t, info.State, state) return nil - }) - c.Assert(err, IsNil) + })) } -func testGetTable(c *C, d *ddl, schemaID int64, tableID int64) table.Table { +func testGetTable(t *testing.T, d *ddl, schemaID int64, tableID int64) table.Table { tbl, err := testGetTableWithError(d, schemaID, tableID) - c.Assert(err, IsNil) + require.NoError(t, err) return tbl } - -// for drop indexes -func createTestTableForDropIndexes(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, name string, num int) *model.TableInfo { - tableInfo, err := testTableInfo(d, name, num) - c.Assert(err, IsNil) - var idxs []*model.IndexInfo - for i := 0; i < num; i++ { - idxName := model.NewCIStr(fmt.Sprintf("i%d", i+1)) - idx := &model.IndexInfo{ - Name: idxName, - State: model.StatePublic, - Columns: []*model.IndexColumn{{Name: model.NewCIStr(fmt.Sprintf("c%d", i+1))}}, - } - idxs = append(idxs, idx) - } - tableInfo.Indices = idxs - testCreateTable(c, ctx, d, dbInfo, tableInfo) - return tableInfo -} diff --git a/distsql/distsql.go b/distsql/distsql.go index 2f952da2a7d3c..06104f0e368f9 100644 --- a/distsql/distsql.go +++ b/distsql/distsql.go @@ -20,22 +20,26 @@ import ( "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/logutil" - "github.com/pingcap/tidb/util/memory" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/pingcap/tidb/util/trxevents" "github.com/pingcap/tipb/go-tipb" + "github.com/tikv/client-go/v2/tikvrpc/interceptor" "go.uber.org/zap" ) // DispatchMPPTasks dispatches all tasks and returns an iterator. -func DispatchMPPTasks(ctx context.Context, sctx sessionctx.Context, tasks []*kv.MPPDispatchRequest, fieldTypes []*types.FieldType, planIDs []int, rootID int) (SelectResult, error) { +func DispatchMPPTasks(ctx context.Context, sctx sessionctx.Context, tasks []*kv.MPPDispatchRequest, fieldTypes []*types.FieldType, planIDs []int, rootID int, startTs uint64) (SelectResult, error) { + ctx = WithSQLKvExecCounterInterceptor(ctx, sctx.GetSessionVars().StmtCtx) _, allowTiFlashFallback := sctx.GetSessionVars().AllowFallbackToTiKV[kv.TiFlash] - resp := sctx.GetMPPClient().DispatchMPPTasks(ctx, sctx.GetSessionVars().KVVars, tasks, allowTiFlashFallback) + resp := sctx.GetMPPClient().DispatchMPPTasks(ctx, sctx.GetSessionVars().KVVars, tasks, allowTiFlashFallback, startTs) if resp == nil { return nil, errors.New("client returns nil response") } @@ -74,9 +78,7 @@ func Select(ctx context.Context, sctx sessionctx.Context, kvReq *kv.Request, fie hook.(func(*kv.Request))(kvReq) } - if !sctx.GetSessionVars().EnableStreaming { - kvReq.Streaming = false - } + kvReq.Streaming = false enabledRateLimitAction := sctx.GetSessionVars().EnabledRateLimitAction originalSQL := sctx.GetSessionVars().StmtCtx.OriginalSQL eventCb := func(event trxevents.TransactionEvent) { @@ -88,7 +90,15 @@ func Select(ctx context.Context, sctx sessionctx.Context, kvReq *kv.Request, fie zap.String("stmt", originalSQL)) } } - resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars, sctx.GetSessionVars().StmtCtx.MemTracker, enabledRateLimitAction, eventCb) + + ctx = WithSQLKvExecCounterInterceptor(ctx, sctx.GetSessionVars().StmtCtx) + option := &kv.ClientSendOption{ + SessionMemTracker: sctx.GetSessionVars().StmtCtx.MemTracker, + EnabledRateLimitAction: enabledRateLimitAction, + EventCb: eventCb, + EnableCollectExecutionInfo: config.GetGlobalConfig().EnableCollectExecutionInfo, + } + resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars, option) if resp == nil { return nil, errors.New("client returns nil response") } @@ -128,6 +138,7 @@ func Select(ctx context.Context, sctx sessionctx.Context, kvReq *kv.Request, fie memTracker: kvReq.MemTracker, encodeType: encodetype, storeType: kvReq.StoreType, + paging: kvReq.Paging, }, nil } @@ -149,8 +160,9 @@ func SelectWithRuntimeStats(ctx context.Context, sctx sessionctx.Context, kvReq // Analyze do a analyze request. func Analyze(ctx context.Context, client kv.Client, kvReq *kv.Request, vars interface{}, - isRestrict bool, sessionMemTracker *memory.Tracker) (SelectResult, error) { - resp := client.Send(ctx, kvReq, vars, sessionMemTracker, false, nil) + isRestrict bool, stmtCtx *stmtctx.StatementContext) (SelectResult, error) { + ctx = WithSQLKvExecCounterInterceptor(ctx, stmtCtx) + resp := client.Send(ctx, kvReq, vars, &kv.ClientSendOption{}) if resp == nil { return nil, errors.New("client returns nil response") } @@ -173,7 +185,7 @@ func Analyze(ctx context.Context, client kv.Client, kvReq *kv.Request, vars inte func Checksum(ctx context.Context, client kv.Client, kvReq *kv.Request, vars interface{}) (SelectResult, error) { // FIXME: As BR have dependency of `Checksum` and TiDB also introduced BR as dependency, Currently we can't edit // Checksum function signature. The two-way dependence should be removed in future. - resp := client.Send(ctx, kvReq, vars, nil, false, nil) + resp := client.Send(ctx, kvReq, vars, &kv.ClientSendOption{}) if resp == nil { return nil, errors.New("client returns nil response") } @@ -205,9 +217,6 @@ func canUseChunkRPC(ctx sessionctx.Context) bool { if !ctx.GetSessionVars().EnableChunkRPC { return false } - if ctx.GetSessionVars().EnableStreaming { - return false - } if !checkAlignment() { return false } @@ -244,3 +253,15 @@ func init() { systemEndian = tipb.Endian_LittleEndian } } + +// WithSQLKvExecCounterInterceptor binds an interceptor for client-go to count the +// number of SQL executions of each TiKV (if any). +func WithSQLKvExecCounterInterceptor(ctx context.Context, stmtCtx *stmtctx.StatementContext) context.Context { + if topsqlstate.TopSQLEnabled() && stmtCtx.KvExecCounter != nil { + // Unlike calling Transaction or Snapshot interface, in distsql package we directly + // face tikv Request. So we need to manually bind RPCInterceptor to ctx. Instead of + // calling SetRPCInterceptor on Transaction or Snapshot. + return interceptor.WithRPCInterceptor(ctx, stmtCtx.KvExecCounter.RPCInterceptor()) + } + return ctx +} diff --git a/distsql/distsql_test.go b/distsql/distsql_test.go index 6ff4a5cb284e5..15d9919cca0ba 100644 --- a/distsql/distsql_test.go +++ b/distsql/distsql_test.go @@ -152,36 +152,6 @@ func TestSelectResultRuntimeStats(t *testing.T) { require.Equal(t, expect, s1.String()) } -func TestSelectStreaming(t *testing.T) { - response, colTypes := createSelectStreaming(t, 1, 2) - // Test Next. - chk := chunk.New(colTypes, 32, 32) - numAllRows := 0 - for { - err := response.Next(context.TODO(), chk) - require.NoError(t, err) - numAllRows += chk.NumRows() - if chk.NumRows() == 0 { - break - } - } - require.Equal(t, 2, numAllRows) - require.NoError(t, response.Close()) -} - -func TestSelectStreamingWithNextRaw(t *testing.T) { - response, _ := createSelectStreaming(t, 1, 2) - data, err := response.NextRaw(context.TODO()) - require.NoError(t, err) - require.Len(t, data, 16) -} - -func TestSelectStreamingChunkSize(t *testing.T) { - response, colTypes := createSelectStreaming(t, 100, 1000000) - testChunkSize(t, response, colTypes) - require.NoError(t, response.Close()) -} - func TestAnalyze(t *testing.T) { sctx := newMockSessionContext() sctx.GetSessionVars().EnableChunkRPC = false @@ -191,7 +161,7 @@ func TestAnalyze(t *testing.T) { Build() require.NoError(t, err) - response, err := Analyze(context.TODO(), sctx.GetClient(), request, tikvstore.DefaultVars, true, sctx.GetSessionVars().StmtCtx.MemTracker) + response, err := Analyze(context.TODO(), sctx.GetClient(), request, tikvstore.DefaultVars, true, sctx.GetSessionVars().StmtCtx) require.NoError(t, err) result, ok := response.(*selectResult) @@ -462,7 +432,7 @@ func createSelectNormal(t *testing.T, batch, totalRows int, planIDs []int, sctx require.True(t, ok) require.Equal(t, "general", result.sqlType) require.Equal(t, "dag", result.label) - require.Equal(t, len(colTypes), result.rowLen) + require.Len(t, colTypes, result.rowLen) resp, ok := result.resp.(*mockResponse) require.True(t, ok) @@ -472,44 +442,3 @@ func createSelectNormal(t *testing.T, batch, totalRows int, planIDs []int, sctx return result, colTypes } - -func createSelectStreaming(t *testing.T, batch, totalRows int) (*streamResult, []*types.FieldType) { - request, err := (&RequestBuilder{}).SetKeyRanges(nil). - SetDAGRequest(&tipb.DAGRequest{}). - SetDesc(false). - SetKeepOrder(false). - SetFromSessionVars(variable.NewSessionVars()). - SetStreaming(true). - Build() - require.NoError(t, err) - - // 4 int64 types. - colTypes := []*types.FieldType{ - { - Tp: mysql.TypeLonglong, - Flen: mysql.MaxIntWidth, - Decimal: 0, - Flag: mysql.BinaryFlag, - Charset: charset.CharsetBin, - Collate: charset.CollationBin, - }, - } - colTypes = append(colTypes, colTypes[0]) - colTypes = append(colTypes, colTypes[0]) - colTypes = append(colTypes, colTypes[0]) - - sctx := newMockSessionContext() - sctx.GetSessionVars().EnableStreaming = true - - response, err := Select(context.TODO(), sctx, request, colTypes, statistics.NewQueryFeedback(0, nil, 0, false)) - require.NoError(t, err) - result, ok := response.(*streamResult) - require.True(t, ok) - require.Equal(t, len(colTypes), result.rowLen) - - resp, ok := result.resp.(*mockResponse) - require.True(t, ok) - resp.total = totalRows - resp.batch = batch - return result, colTypes -} diff --git a/distsql/main_test.go b/distsql/main_test.go index 1aaddbe954620..052afbf350c46 100644 --- a/distsql/main_test.go +++ b/distsql/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/distsql/request_builder.go b/distsql/request_builder.go index a2c67992868a9..3ffb78c002cb3 100644 --- a/distsql/request_builder.go +++ b/distsql/request_builder.go @@ -36,6 +36,7 @@ import ( "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/pingcap/tipb/go-tipb" ) @@ -216,6 +217,12 @@ func (builder *RequestBuilder) SetAllowBatchCop(batchCop bool) *RequestBuilder { return builder } +// SetPartitionIDAndRanges sets `PartitionIDAndRanges` property. +func (builder *RequestBuilder) SetPartitionIDAndRanges(PartitionIDAndRanges []kv.PartitionIDAndRanges) *RequestBuilder { + builder.PartitionIDAndRanges = PartitionIDAndRanges + return builder +} + func (builder *RequestBuilder) getIsolationLevel() kv.IsoLevel { switch builder.Tp { case kv.ReqTypeAnalyze: @@ -243,11 +250,19 @@ func (builder *RequestBuilder) SetFromSessionVars(sv *variable.SessionVars) *Req // Concurrency may be set to 1 by SetDAGRequest builder.Request.Concurrency = sv.DistSQLScanConcurrency() } - builder.Request.IsolationLevel = builder.getIsolationLevel() + replicaReadType := sv.GetReplicaRead() + if sv.StmtCtx.WeakConsistency { + builder.Request.IsolationLevel = kv.RC + } else if sv.StmtCtx.RCCheckTS { + builder.Request.IsolationLevel = kv.RCCheckTS + replicaReadType = kv.ReplicaReadLeader + } else { + builder.Request.IsolationLevel = builder.getIsolationLevel() + } builder.Request.NotFillCache = sv.StmtCtx.NotFillCache builder.Request.TaskID = sv.StmtCtx.TaskID builder.Request.Priority = builder.getKVPriority(sv) - builder.Request.ReplicaRead = sv.GetReplicaRead() + builder.Request.ReplicaRead = replicaReadType builder.SetResourceGroupTagger(sv.StmtCtx) return builder } @@ -292,13 +307,18 @@ func (builder *RequestBuilder) SetFromInfoSchema(pis interface{}) *RequestBuilde // SetResourceGroupTagger sets the request resource group tagger. func (builder *RequestBuilder) SetResourceGroupTagger(sc *stmtctx.StatementContext) *RequestBuilder { - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { builder.Request.ResourceGroupTagger = sc.GetResourceGroupTagger() } return builder } func (builder *RequestBuilder) verifyTxnScope() error { + // Stale Read uses the calculated TSO for the read, + // so there is no need to check the TxnScope here. + if builder.IsStaleness { + return nil + } if builder.ReadReplicaScope == "" { builder.ReadReplicaScope = kv.GlobalReplicaScope } diff --git a/distsql/request_builder_test.go b/distsql/request_builder_test.go index 81ea73513cfa1..8d571656fadd4 100644 --- a/distsql/request_builder_test.go +++ b/distsql/request_builder_test.go @@ -270,7 +270,6 @@ func TestRequestBuilder1(t *testing.T) { IsolationLevel: 0, Priority: 0, NotFillCache: false, - SyncLog: false, Streaming: false, ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, @@ -352,7 +351,6 @@ func TestRequestBuilder2(t *testing.T) { IsolationLevel: 0, Priority: 0, NotFillCache: false, - SyncLog: false, Streaming: false, ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, @@ -400,7 +398,6 @@ func TestRequestBuilder3(t *testing.T) { IsolationLevel: 0, Priority: 0, NotFillCache: false, - SyncLog: false, Streaming: false, ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, @@ -449,7 +446,6 @@ func TestRequestBuilder4(t *testing.T) { Priority: 0, Streaming: true, NotFillCache: false, - SyncLog: false, ReplicaRead: kv.ReplicaReadLeader, ReadReplicaScope: kv.GlobalReplicaScope, } @@ -493,7 +489,6 @@ func TestRequestBuilder5(t *testing.T) { IsolationLevel: kv.RC, Priority: 1, NotFillCache: true, - SyncLog: false, Streaming: false, ReadReplicaScope: kv.GlobalReplicaScope, } @@ -524,7 +519,6 @@ func TestRequestBuilder6(t *testing.T) { IsolationLevel: 0, Priority: 0, NotFillCache: true, - SyncLog: false, Streaming: false, ReadReplicaScope: kv.GlobalReplicaScope, } @@ -561,7 +555,6 @@ func TestRequestBuilder7(t *testing.T) { IsolationLevel: 0, Priority: 0, NotFillCache: false, - SyncLog: false, Streaming: false, ReplicaRead: replicaRead.replicaReadType, ReadReplicaScope: kv.GlobalReplicaScope, diff --git a/distsql/select_result.go b/distsql/select_result.go index 3ac7f1db94a97..b2eef6e6f5300 100644 --- a/distsql/select_result.go +++ b/distsql/select_result.go @@ -152,7 +152,8 @@ type selectResult struct { durationReported bool memTracker *memory.Tracker - stats *selectResultRuntimeStats + stats *selectResultRuntimeStats + paging bool } func (r *selectResult) fetchResp(ctx context.Context) error { @@ -206,7 +207,11 @@ func (r *selectResult) fetchResp(ctx context.Context) error { // final round of fetch // TODO: Add a label to distinguish between success or failure. // https://github.com/pingcap/tidb/issues/11397 - metrics.DistSQLQueryHistogram.WithLabelValues(r.label, r.sqlType).Observe(r.fetchDuration.Seconds()) + if r.paging { + metrics.DistSQLQueryHistogram.WithLabelValues(r.label, r.sqlType, "paging").Observe(r.fetchDuration.Seconds()) + } else { + metrics.DistSQLQueryHistogram.WithLabelValues(r.label, r.sqlType, "common").Observe(r.fetchDuration.Seconds()) + } r.durationReported = true } return nil diff --git a/distsql/stream.go b/distsql/stream.go index 73d8f96b8fe79..526b2693de54d 100644 --- a/distsql/stream.go +++ b/distsql/stream.go @@ -82,7 +82,7 @@ func (r *streamResult) readDataFromResponse(ctx context.Context, resp kv.Respons if !r.durationReported { // TODO: Add a label to distinguish between success or failure. // https://github.com/pingcap/tidb/issues/11397 - metrics.DistSQLQueryHistogram.WithLabelValues(r.label, r.sqlType).Observe(r.fetchDuration.Seconds()) + metrics.DistSQLQueryHistogram.WithLabelValues(r.label, r.sqlType, "streaming").Observe(r.fetchDuration.Seconds()) r.durationReported = true } return true, nil @@ -94,7 +94,7 @@ func (r *streamResult) readDataFromResponse(ctx context.Context, resp kv.Respons return false, errors.Trace(err) } if stream.Error != nil { - return false, errors.Errorf("stream response error: [%d]%s\n", stream.Error.Code, stream.Error.Msg) + return false, errors.Errorf("stream response error: [%d]%s", stream.Error.Code, stream.Error.Msg) } for _, warning := range stream.Warnings { r.ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ClassTiKV.Synthesize(terror.ErrCode(warning.Code), warning.Msg)) diff --git a/docs/design/2020-06-24-placement-rules-in-sql.md b/docs/design/2020-06-24-placement-rules-in-sql.md index 7e95d80047f6d..5ca760585f61c 100644 --- a/docs/design/2020-06-24-placement-rules-in-sql.md +++ b/docs/design/2020-06-24-placement-rules-in-sql.md @@ -1,7 +1,7 @@ # Defining placement rules in SQL - Author(s): [djshow832](https://github.com/djshow832) (Ming Zhang), [morgo](https://github.com/morgo) (Morgan Tocker) -- Last updated: 2021-11-28 +- Last updated: 2022-01-06 - Discussion PR: https://github.com/pingcap/tidb/pull/26221 - Tracking Issue: https://github.com/pingcap/tidb/issues/18030 - Original Document (Chinese): https://docs.google.com/document/d/18Kdhi90dv33muF9k_VAIccNLeGf-DdQyUc8JlWF9Gok @@ -64,29 +64,22 @@ This proposal makes some intentional decisions so that both categories of use-ca ### New Syntax Overview -There are two ways to specify placement rules: +The new syntax is based on a `PLACEMENT POLICY` statement and the ability to assign a placement policy to a schema, table or partition: -1. By assigning placement directly on a database, table or partition (direct assignment) -2. By creating a new `PLACEMENT POLICY` and then applying the placement policy to a database, table or partition (placement policy) - -Using a `PLACEMENT POLICY` will be recommended for compliance requirements, since it can allow administrators to better keep track of usage. This can be seen as similar to how complex environments will use `ROLES` for management instead of directly assigning privileges to users. - -Both syntaxes are considered [`table_option`](https://dev.mysql.com/doc/refman/8.0/en/alter-table.html)s, and available in both `CREATE TABLE` and `ALTER TABLE` contexts. - -The two methods **are mutually exclusive**. Specifying both in a `CREATE`/`ALTER` statement will result in an error. Specifying a `PLACEMENT POLICY` on a table with direct assignment options will clear those options. +```sql +CREATE PLACEMENT POLICY policyName [placementOptions]; +CREATE TABLE t1 (a INT) PLACEMENT POLICY=policyName; +``` -#### Direct Assignment +An earlier, experimental, version of this proposal featured the ability to assign placementOptions directly to objects (tables or partitions). **This is no longer supported**. -Creating a new table with directly assigned constraints. The leader is in `us-east-1` region, the followers are in `us-east-1` and `us-east-2`: +A `PLACEMENT POLICY` allows administrators to better keep track of usage. This can be seen as similar to how complex environments will use `ROLES` for management instead of directly assigning privileges to users. For example: ```sql -CREATE TABLE t1 ( - id INT NOT NULL PRIMARY KEY, - b VARCHAR(100) -) PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2"; +CREATE PLACEMENT POLICY `standardplacement` PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2" ``` -In this context, "REGION" and "REGIONS" are syntactic sugar which map to the label `region`. The following labels have special reserved words (the plural is used in contexts such as followers where multiple is possible): +In this context, "PRIMARY_REGION" and "REGIONS" are syntactic sugar which map to the label `region`. The following labels have special reserved words (the plural is used in contexts such as followers where multiple is possible): - `host` and `hosts`: expected to be the same physical machine or hypervisor. - `rack` and `racks`: similar to host; a group of machines that are physically close together and may suffer from many of the same failures. - `zone` and `zones`: similar to an AWS zone; much larger degree of blast radius isolation from a rack, but still vulnerable to issues such as a natural disaster. @@ -94,14 +87,6 @@ In this context, "REGION" and "REGIONS" are syntactic sugar which map to the lab To use additional labels not in this list, see "Advanced Placement" below. -#### Explicit Placement Syntax - -Creating a new `PLACEMENT POLICY`: - -```sql -CREATE PLACEMENT POLICY `standardplacement` PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2" -``` - Creating a new table with the `PLACEMENT POLICY` assigned: ```sql @@ -128,9 +113,7 @@ Behavior notes: - Placement Policy names are case insensitive, and follow the same rules as tables/other identifiers for length (64 chars) and special characters. - The full placement policy can be seen with `SHOW CREATE PLACEMENT POLICY x`. This is useful for shorthand usage by DBAs, and consistent with other database objects. - It is possible to update the definition of a placement policy with `ALTER PLACEMENT POLICY x LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,+region=us-east-2:1}";` This is modeled on the statement `ALTER VIEW` (where the view needs to be redefined). When `ALTER PLACEMENT POLICY x` is executed, all tables that use this placement policy will need to be updated in PD. -- The statement `DROP PLACEMENT POLICY` should execute without error. If any partitions currently use this policy, they will be converted to the policy used by the table they belong to. If any tables use this policy, they will be converted to the policy used by the database they belong to. If any databases use this policy, they will be converted to the default placement policy. This is modeled on the behavior of dropping a `ROLE` that might be assigned to users. - The statement `RENAME PLACEMENT POLICY x TO y` renames a placement policy. The `SHOW CREATE TABLE` output of all databases, tables and partitions that used this placement policy should be updated to the new name. -- You can not use **both** a placement policy and direct assignment. If you alter specify both in a `CREATE TABLE` or `ALTER TABLE` an error will be returned. If you specify a `PLACEMENT POLICY` in an `ALTER TABLE` statement, it will unset other placement options ({FOLLOWERS,LEARNERS}=N, {FOLLOWER,LEARNER}_CONSTRAINTS, CONSTRAINTS, PRIMARY_REGION, REGIONS, SCHEDULE). #### Advanced Placement @@ -160,19 +143,17 @@ The placement policy above has 4 followers: Behavior notes: -* Advanced placement is available in the context of `CREATE|ALTER PLACEMENT POLICY`, `CREATE|ALTER DATABASE` and `CREATE|ALTER TABLE`. i.e. the usage of all placement syntax is expected to be the same in all contexts. +* Advanced placement is available in the context of `CREATE|ALTER PLACEMENT POLICY`, i.e. the usage of all placement syntax is expected to be the same in all contexts. * It is possible to set `CONSTRAINTS`, `LEADER_CONSTRAINTS`, `FOLLOWER_CONSTRAINTS` and `LEARNER_CONSTRAINTS`. Assuming that both `CONSTRAINTS` and `FOLLOWER_CONSTRAINTS` are specified, the conditions are "AND"ed together. * See "Constraints configuration" below for a full set of rules and syntax for constraints. #### Metadata commands -Besides `SHOW CREATE PLACEMENT POLICY x` and `SHOW CREATE TABLE t1` it should be possible to summarize all placement for a database system. This is beneficial for compliance scenarios. +Besides `SHOW CREATE PLACEMENT POLICY x`, it should be possible to summarize all placement for a database system. This is beneficial for compliance scenarios. -##### information_schema.placement_rules +##### information_schema.placement_policies -A new system table `information_schema.placement_rules` is added to view all explicit placement rules. An explicit rule is one that has been defined by the user and does not use inheritance rules, such as how partitions will use the same rules as the table they belong to. - -The table definition is as follows: +A new system table `information_schema.placement_policies` is added to view all placement policies. The table definition is as follows: ```sql +----------------------+---------------+------+------+---------+-------+ @@ -180,43 +161,32 @@ The table definition is as follows: +----------------------+---------------+------+------+---------+-------+ | POLICY_ID | bigint(64) | NO | | NULL | | | CATALOG_NAME | varchar(512) | NO | | NULL | | -| POLICY_NAME | varchar(64) | YES | | NULL | | -| SCHEMA_NAME | varchar(64) | YES | | NULL | | -| TABLE_NAME | varchar(64) | YES | | NULL | | -| PARTITION_NAME | varchar(64) | YES | | NULL | | -| PRIMARY_REGION | varchar(1024) | NO | | NULL | | -| REGIONS | varchar(1024) | NO | | NULL | | -| CONSTRAINTS | varchar(1024) | NO | | NULL | | -| LEADER_CONSTRAINTS | varchar(1024) | NO | | NULL | | -| FOLLOWER_CONSTRAINTS | varchar(1024) | NO | | NULL | | -| LEARNER_CONSTRAINTS | varchar(1024) | NO | | NULL | | -| SCHEDULE | varchar(20) | NO | | NULL | | -| FOLLOWERS | bigint(64) | NO | | NULL | | -| LEARNERS | bigint(64) | NO | | NULL | | +| POLICY_NAME | varchar(64) | NO | | NULL | | +| PRIMARY_REGION | varchar(1024) | YES | | NULL | | +| REGIONS | varchar(1024) | YES | | NULL | | +| CONSTRAINTS | varchar(1024) | YES | | NULL | | +| LEADER_CONSTRAINTS | varchar(1024) | YES | | NULL | | +| FOLLOWER_CONSTRAINTS | varchar(1024) | YES | | NULL | | +| LEARNER_CONSTRAINTS | varchar(1024) | YES | | NULL | | +| SCHEDULE | varchar(20) | YES | | NULL | | +| FOLLOWERS | bigint(64) | YES | | NULL | | +| LEARNERS | bigint(64) | YES | | NULL | | +----------------------+---------------+------+------+---------+-------+ -15 rows in set (0.00 sec) ``` ##### information_schema.tables and information_schema.partitions -The information_schema tables for `tables` and `partitions` should be modified to have additional fields for `tidb_placement_policy_name` and `tidb_direct_placement`: +The information_schema tables for `tables` and `partitions` should be modified to have an additional field for `tidb_placement_policy_name`: ```golang {name: "TIDB_PLACEMENT_POLICY_NAME", tp: mysql.TypeVarchar, size: 64}, -{name: "TIDB_DIRECT_PLACEMENT", tp: mysql.TypeVarchar, size: 1024} ``` This helps make the information match what is available in `SHOW CREATE TABLE`, but in a structured format. ##### SHOW PLACEMENT -The `information_schema.placement_rules` table only contains stored placement rules, and users cannot query the effective rule of one object from it. - -For example, table `t` has two partitions `p0` and `p1`, and a placement rule is added on `t`. If the user wants to query the working rule of `p0`, he will find no placement rule is defined for `p0` through the system table. Based on the inheritance rules for partitioned tables the user needs to query the placement rule on `t`. This procedure is annoying. - -To simplify the procedure, a `SHOW PLACEMENT` statement is provided to summarize the effective rules for one specified object. - -The statement is in such a format: +In addition to `information_schema.tables` and `information_schema.partitions`, a summary of the placement for a schema or table can be provided with `SHOW PLACEMENT`. The `placement` column in `SHOW PLACEMENT` shows the canonical version of the rules for an object (table or partition) with placement policies expanded. This is helpful for returning the canonical set of rules (which can get complicated since partitions inherit placement from tables, but can also be manually specified): ```sql SHOW PLACEMENT FOR [{DATABASE | SCHEMA} schema_name] [TABLE table_name [PARTITION partition_name]]; @@ -279,6 +249,8 @@ SHOW PLACEMENT LIKE 'POLICY standardpol%'; This will match for `PLACEMENT POLICY` names such as `standardpolicy`. +The `scheduling_state` is one of `SCHEDULED`, `INPROGRESS`, or `PENDING`. `PENDING` means the placement rule is semantically valid, but might not be able to be scheduled based on the current topology of the cluster. + ### Updates to Existing Syntax #### CREATE DATABASE / ALTER DATABASE @@ -300,7 +272,7 @@ CREATE TABLE mydb.t3 (a INT) PLACEMENT POLICY=`companystandardpolicy`; #### SHOW CREATE TABLE -The output of `SHOW CREATE TABLE` should describe any placement options that are either explicitly specified, or inherited from the default placement from `CREATE DATABASE` / `ALTER DATABASE`. This should be escaped in TiDB feature-specific comment syntax. i.e. +The output of `SHOW CREATE TABLE` should escape placement policies in TiDB feature-specific comment syntax. i.e. ```sql use test; @@ -326,13 +298,6 @@ CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`acdc` */; -ALTER TABLE t3 PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2,us-west-1,us-west-2"; -SHOW CREATE TABLE t3; ---> -CREATE TABLE `t3` ( - `a` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PRIMARY_REGION="us-east-1" REGIONS="us-east-1,us-east-2,us-west-1,us-west-2" */; - ``` This helps ensure the highest level of compatibility between both TiDB versions and MySQL. @@ -380,15 +345,6 @@ For example, `+region=us-east-1,+region=us-east-2,-disk=hdd` is equivalent to: Field `location_labels` in PD placement rule configuration is used to isolate replicas to different zones to improve availability. For now, the global configuration can be used as the default `location_labels` for all placement rules defined in SQL, so it's unnecessary to specify it. -`PLACEMENT` also supports adding TiFlash replicas for a table, as the statement `ALTER TABLE table_name SET TIFLASH REPLICA count` does. For example: - -```sql -ALTER TABLE t1 - LEARNER_CONSTRAINTS="[+engine=tiflash]" LEARNERS=1; -``` - -The only way to judge whether it’s adding a TiFlash replica is to check the label. If it contains `engine=tiflash`, then it’s adding or removing a TiFlash replica. This logic is conventional in PD for now. - #### Specifying role count The roles `FOLLOWERS` and `LEARNERS` also support an optional count in *list* format. For example: @@ -401,8 +357,8 @@ CREATE PLACEMENT POLICY `standardplacement2` LEADER_CONSTRAINTS="[+region=us-eas If the constraints is specified as a dictionary (e.g. `{"+region=us-east-1":1}`) the count is not applicable and an error is returned: ```sql -FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=3 // technically accurate, but an error -FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=2 // an error +FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=3; -- technically accurate, but an error +FOLLOWER_CONSTRAINTS="{+region=us-east-1:1,-region=us-east-2:2}" FOLLOWERS=2; -- an error ``` For dictionary format, the count is inferred by the constraint. The following constraint creates 4 followers: @@ -456,7 +412,6 @@ When placement policies are specified, they should be validated for correctness: 1. The `FOLLOWERS` count should respect raft quorum expectations. The default is `2` (which creates raft groups of 3). If the number is odd, it could lead to split brain scenarios, so a warning should be issued. Warnings should also be issued for a count less than 2 (this might be useful for development environments, so an error is not returned) 2. A policy that is impossible based on the current topology (region=us-east-1 and followers=2, but there is only 1 store in us-east-1) should be a warning. This allows for some transitional topologies. 3. If the constraints are specified as a dictionary, specifying the count (i.e. `FOLLOWERS=n`) is prohibited. -4. Specifying both direct placement rules (`{FOLLOWERS,LEARNERS}=N, {FOLLOWER,LEARNER}_CONSTRAINTS, CONSTRAINTS, PRIMARY_REGION, REGIONS, SCHEDULE`) and a `PLACEMENT POLICY` is prohibited. #### Skipping Policy Validation @@ -464,12 +419,14 @@ It should be possible to skip policy validation. This can be seen as similar to ```sql SET FOREIGN_KEY_CHECKS=0; -SET PLACEMENT_CHECKS=0; +SET tidb_placement_mode='IGNORE'; CREATE TABLE t3 (a int) PLACEMENT POLICY `mycompanypolicy`; ``` -If a table is imported when `PLACEMENT_CHECKS` is `OFF`, and the placement policy does not validate, then the same rules of fallback apply as in the case `DROP PLACEMENT POLICY` (where policy is still in use). +If a table is imported when `tidb_placement_mode='IGNORE'`, and the placement policy does not validate, then the same rules of fallback apply as in the case `DROP PLACEMENT POLICY` (where policy is still in use). + +The default value for `tidb_placement_mode` is `STRICT`. The option is an enum, and in future we may add support for a `WARN` mode. #### Ambiguous and edge cases @@ -507,14 +464,14 @@ The semantics of partitioning are different to the default database policy. When ```sql CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) + PLACEMENT POLICY='companystandardpolicy' PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY='storeonhdd', PARTITION p1 VALUES LESS THAN (2005), PARTITION p2 VALUES LESS THAN (2010), PARTITION p3 VALUES LESS THAN (2015), PARTITION p4 VALUES LESS THAN MAXVALUE PLACEMENT POLICY='storeonfastssd' - ) -PLACEMENT POLICY='companystandardpolicy'; + ); ``` In this example, partition `p0` uses the policy `storeonhdd`, partition `p4` uses the policy `storeonfastssd` and the remaining partitions use the policy `companystandardpolicy`. Assuming the following `ALTER TABLE` statement is executed, only partitions `p1`-`p3` will be updated: @@ -570,18 +527,20 @@ CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) ALTER TABLE t1 PLACEMENT POLICY="xyz"; --> CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) + PLACEMENT POLICY="xyz" PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY="acdc", PARTITION p1 VALUES LESS THAN (2005) - ) PLACEMENT POLICY="xyz"; + ); ALTER TABLE t1 PARTITION p0 PLACEMENT POLICY=DEFAULT; --> CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) + PLACEMENT POLICY="xyz" PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (2000), PARTITION p1 VALUES LESS THAN (2005) - ) PLACEMENT POLICY="xyz"; + ); ``` @@ -610,7 +569,7 @@ The fact that the DDL procedure in TiDB is mature helps to achieve some features - DDL is rollbackable as the middle states can transform from one to another - Updating schema version guarantees all active transactions are based on the same version of placement rules -The actual "completion" of the DDL job as far as TiDB is concerned is that PD has been notified of the placement rules for all of the affected regions. PD will then asynchronously apply the placement rules to all of the regions, and this progress is not observable via `ADMIN SHOW DDL JOBS`. The progress of scheduling can be observed via `SHOW PLACEMENT` or by reading `information_schema.placement_rules`. +The actual "completion" of the DDL job as far as TiDB is concerned is that PD has been notified of the placement rules for all of the affected regions. PD will then asynchronously apply the placement rules to all of the regions, and this progress is not observable via `ADMIN SHOW DDL JOBS`. The progress of scheduling can be observed via `SHOW PLACEMENT` or by reading `information_schema.placement_policies`. ### Privilege management @@ -618,7 +577,8 @@ Privilege management is quite straightforward: * `ALTER [DATABASE|TABLE]` statement requires `Alter` privilege * `CREATE TABLE` statement requires `Create` privilege -* `information_schema.placement_rules` and `SHOW PLACEMENT` only shows the placement rules on the objects that visible to the current user +* `SHOW PLACEMENT` only shows the placement rules on the objects that visible to the current user +* `information_schema.placement_policies` requires `CREATE TABLE` privilege (it doesn't reveal anything about tables, but any user who creates a table can specify a placement policy, and needs to know the possible names of policies) * `ADMIN SHOW DDL` requires `Super` privilege * `CREATE PLACEMENT POLICY`, `DROP PLACEMENT POLICY` and `ALTER PLACEMENT POLICY` require `PLACEMENT_ADMIN` (a new dynamic privilege). This is because these objects have global scope. @@ -626,9 +586,7 @@ Privilege management is quite straightforward: ### Storing Placement Policies -Placement policies will be stored in a table in the `mysql` schema. The policy name must be globally unique, but the definition of the table is not described in this proposal. - -Because the implementation is TiDB specific (does not require any compatibility with MySQL), it is up to the implementer to decide. +Placement policies will be stored in the internal meta data system, similar to tables or views. The policy name must be globally unique, but the definition of the table is not described in this proposal. ### Storage Consistency @@ -684,8 +642,9 @@ There needs a way to map the placement rules in SQL to PD placement rule configu However, an object (database, table, partition) may have multiple rules for a single role. For example: ```sql -ALTER TABLE t +CREATE PLACEMENT POLICY p1 FOLLOWER_CONSTRAINTS="{+region=us-east-1:2,+region=us-east-2:1}"; +CREATE TABLE t1 (a int) PLACEMENT POLICY p1; ``` It needs 2 placement rules for `follower` in the PD placement rule configuration, because each rule can only specify one `count`. To make `id` unique, a unique identifier must be appended to `id`. DDL job ID plus an index in the job is a good choice. @@ -869,6 +828,7 @@ CREATE PLACEMENT POLICY storeonfastssd CONSTRAINTS="[+disk=ssd]"; CREATE PLACEMENT POLICY storeonhdd CONSTRAINTS="[+disk=hdd]"; CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) + PLACEMENT POLICY='companystandardpolicy' PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY='storeonhdd', PARTITION p1 VALUES LESS THAN (2005), @@ -876,7 +836,7 @@ CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) PARTITION p3 VALUES LESS THAN (2015), PARTITION p4 VALUES LESS THAN MAXVALUE PLACEMENT POLICY='storeonfastssd' ) -PLACEMENT POLICY='companystandardpolicy'; +; ``` ### Optimization: Multi-tenancy / control of shared resources @@ -974,7 +934,7 @@ Assuming that global indexes can be added to the TiDB server, this use-case can For investigation, we looked at the implementation of placement rules in various databases (CockroachDB, Yugabyte, OceanBase). -The idea of using a `PLACEMENT POLICY` was inspired by how OceanBase has Placement Groups, which are then applied to tables. But the usage as proposed here is optional, which allows for more flexibility for casual cases. The idea of using a Placement Group can also be seen as similar to using a "tablespace" in a traditional database, but it's not completely the same since the choice is less binary (constraints allow the placement of roles for leaders, followers, learners). +The idea of using a `PLACEMENT POLICY` was inspired by how OceanBase has Placement Groups, which are then applied to tables. The idea of using a Placement Group/Placement Policy can also be seen as similar to using a "tablespace" in a traditional database. CockroachDB does not look to have something directly comparable to `PLACEMENT POLICY`, but it does have the ability to specify "replication zones" for "system ranges" such as default, meta, liveness, system, timeseries. Before dropping `ALTER TABLE t1 ADD PLACEMENT` from this proposal, it was investigated the CockroachDB does not support this syntax, presumably for simplification and minimising similar risks of misconfiguration. @@ -982,7 +942,6 @@ CockroachDB does not look to have something directly comparable to `PLACEMENT PO - In this proposal, placement policies are global-level and not specific to a database. This simplifies the configuration, but makes it restrictive for multi-tenant scenarios where a schema-per-tenant is provided. This is because creating or modifying placement policies requires a privilege which is cluster scoped (`PLACEMENT_ADMIN`). The limitation is that "tenants" will be able to `CREATE TABLE (..) PLACEMENT POLICY=x`, but they will not be able to `CREATE PLACEMENT POLICY x` or `ALTER PLACEMENT POLICY x` - Complex scenarios may exist where there is not a column in the current table which can be used to partition the table into different regions, but instead there is a column which is a foreign key to another table from which this information can be determined. In this scenario, the user will be required to "denormalize" the usage and move the parent_id into the child table so geo-partitioning is possible. -- Because direct assignment and `PLACEMENT POLICY` are mutually exclusive, it results in some scenarios where users that just want to make one small change on a placement policy need to create a new policy. This is intentional to limit the risk of misconfiguration. - The name `REGION` is ambigous, since we are using it for placement as well as to refer to a chunk of data. We could avoid region here, but the problem is it is the most used term for a geographic location of a data center. We recommend instead calling both region but in documentation refering to them as "data regions" and "placement regions". ## Unresolved Questions @@ -1031,6 +990,11 @@ This specific semantic will be the hardest to implement because of the other dep ## Changelog +* 20221-01-06: + - Removed Direct placement options, and support only placement policies. + - Renamed infoschema tables to make sense based on direct placement removal. + - Incorporate change from `PLACEMENT_CHECKS` to `tidb_placement_mode`. + * 2021-11-29: - Updated limits on object length. - Removed built-in placement policies (not supported for now, need additional discussion due to `DEFAULT` conflicts.) diff --git a/docs/design/2021-07-29-hidden-sysvars.md b/docs/design/2021-07-29-hidden-sysvars.md index 59989da7a7099..c7473ebd6a4ca 100644 --- a/docs/design/2021-07-29-hidden-sysvars.md +++ b/docs/design/2021-07-29-hidden-sysvars.md @@ -39,7 +39,6 @@ There are currently ~20 hidden system variables: | tidb_enable_pipelined_window_function | ‘Pipelined window function’ feature | #1 Stable | | tidb_enable_change_multi_schema | ‘Change multi schema in one statement’ feature. | #3 In Development Feature | | tidb_enable_point_get_cache | ‘point get cache’ feature | #2 Experimental | -| tidb_enable_alter_placement | placement rules in SQL feature | #3 In Development Feature | | tidb_enable_extended_stats | ‘extended stats’ feature | #2 Experimental | | tidb_partition_prune_mode | Is partition prune mode dynamic or static | #2 Experimental | | tidb_enable_async_commit | Support Async Commit PRD | #1 Stable | @@ -51,10 +50,8 @@ There are currently ~20 hidden system variables: | tidb_track_aggregate_memory_usage | Track memory usage of aggregate executor | #1 Stable | | tidb_enable_top_sql | Top SQL (Sprint3) 总设计文档 | #2 Experimental | | tidb_top_sql_agent_address | Parameters for Top SQL | #4 Non-boolean Experimental | -| tidb_top_sql_precision_seconds | "" | #4 Non-boolean Experimental | -| tidb_top_sql_max_statement_count | "" | #4 Non-boolean Experimental | -| tidb_top_sql_max_collect | "" | #4 Non-boolean Experimental | -| tidb_top_sql_report_interval_seconds | "" | #4 Non-boolean Experimental | +| tidb_top_sql_max_time_series_count | "" | #4 Non-boolean Experimental | +| tidb_top_sql_max_meta_count | "" | #4 Non-boolean Experimental | ## Detailed Design diff --git a/docs/design/2021-08-18-charsets.md b/docs/design/2021-08-18-charsets.md index 441f5b0917d6b..b048341f818e6 100644 --- a/docs/design/2021-08-18-charsets.md +++ b/docs/design/2021-08-18-charsets.md @@ -245,3 +245,72 @@ The third stage - Basically support all string-related functions already supported by TiDB. - Support the use of alter statement, support to modify the charset of the column. + +# Add New Charset + +### Encoding + +Define how character encode and decode, the main work is to implement [the encoding interface](https://github.com/pingcap/tidb/blob/7fd298d916c30ed0060db3581be58b448325819e/parser/charset/encoding.go#L65-L87) + +```golang +// Encoding provide encode/decode functions for a string with a specific charset. +type Encoding interface { + // Name is the name of the encoding. + Name() string + // Tp is the type of the encoding. + Tp() EncodingTp + // Peek returns the next char. + Peek(src []byte) []byte + // MbLen returns multiple byte length, if the next character is single byte, return 0. + MbLen(string) int + // IsValid checks whether the utf-8 bytes can be convert to valid string in current encoding. + IsValid(src []byte) bool + // Foreach iterates the characters in in current encoding. + Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) + // Transform map the bytes in src to dest according to Op. + // **the caller should initialize the dest if it wants to avoid memory alloc every time, or else it will always make a new one** + // **the returned array may be the alias of `src`, edit the returned array on your own risk** + Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) + // ToUpper change a string to uppercase. + ToUpper(src string) string + // ToLower change a string to lowercase. + ToLower(src string) string +} +``` +### Collation + +#### [New Collation](https://docs.pingcap.com/tidb/stable/character-set-and-collation#new-framework-for-collations) + +TiDB have no collation with the default config, all the collation will be ignored. After tidb 4.0, the collation framework is supported and uses a config to control it. After a new charset is added into TiDB, the related collation should also be added. + + +For example, `gb18030` charset have 3 different collations +```sql +| gb18030_bin | gb18030 | 249 | | Yes | 1 | PAD SPACE | +| gb18030_chinese_ci | gb18030 | 248 | Yes | Yes | 2 | PAD SPACE | +| gb18030_unicode_520_ci | gb18030 | 250 | | Yes | 8 | PAD SPACE | +``` + +We should at least implement `gb18030_bin` and `gb18030_chinese_ci` collations. + +If the collation framework is not used, the `gb18030_bin` should be the default collation, otherwise, the `gb18030_chinese_ci` should be the default collation. + +Add a new collation should implement the [Collator interface](https://github.com/pingcap/tidb/blob/7fd298d916c30ed0060db3581be58b448325819e/util/collate/collate.go#L62-L71) + +```golang +// Collator provides functionality for comparing strings for a given +// collation order. +type Collator interface { + // Compare returns an integer comparing the two strings. The result will be 0 if a == b, -1 if a < b, and +1 if a > b. + Compare(a, b string) int + // Key returns the collate key for str. If the collation is padding, make sure the PadLen >= len(rune[]str) in opt. + Key(str string) []byte + // Pattern get a collation-aware WildcardPattern. + Pattern() WildcardPattern +} +``` + +Then, add the charset and related collations into the support list to make tidb recognize it. + +### TikV +Many expressions have been pushed down to tikv, we should also make tikv support the [charset](https://github.com/tikv/tikv/blob/da1c069a2f9b5222ddbd32820a5a2ae1de50c78c/components/tidb_query_datatype/src/codec/collation/mod.rs#L98) and [collation](https://github.com/tikv/tikv/blob/da1c069a2f9b5222ddbd32820a5a2ae1de50c78c/components/tidb_query_datatype/src/codec/collation/mod.rs#L68). \ No newline at end of file diff --git a/docs/design/2021-09-22-data-consistency.md b/docs/design/2021-09-22-data-consistency.md new file mode 100644 index 0000000000000..ba752be4f5109 --- /dev/null +++ b/docs/design/2021-09-22-data-consistency.md @@ -0,0 +1,144 @@ +# Proposal: Reduce Data inconsistencies + +- Author(s): [Li Su](http://github.com/lysu), [Ziqian Qin](http://github.com/ekexium) +- Tracking Issue: https://github.com/pingcap/tidb/issues/26833 + +## Table of Contents + +- [Table of Contents](#table-of-contents) + +- [Introduction](#introduction) +- [Motivation or Background](#motivation-or-background) +- [Detailed Design](#detailed-design) + +- [Test Design](#test-design) + + - [Regression Tests](#regression-tests) + - [System Tests](#system-tests) + - [Performance Tests](#performance-tests) + +- [Impacts & Risks](#impacts--risks) + +## Introduction + +The document proposes an enhancement that reduces data inconsistency issues in TiDB. The feature also includes an +enhancement in the logging and error handling of data inconsistency issues to help diagnosis. + +## Motivation or Background + +TiDB occasionally encounters data index inconsistencies, i.e., row data and indices of the same record are +inconsistent (in their numbers or content). Inconsistent data indices in production environments can have a very bad +impact on users, including but not limited to + +- Read errors: errors are reported when reading or writing inconsistent data +- Data error: data can be read but the result is incorrect +- Data Loss: Data written cannot be read + +It is very difficult for support engineers to locate data index inconsistencies when they occur. + +- Multiple possible causes of data errors +- Inconsistency phenomenon cannot easily imply its cause +- Difficulty in collecting information available for investigation on the cause + +In short, the serious impact of the problem and the difficulty of troubleshooting is the main reason why we need to +invest in improvement at present. + +## Detailed Design + +There are two methods to reduce data corruption from happening and spreading. And we have separate system variables to +enable them. + +`tidb_enable_mutation_checker`, takes value of `ON` or `OFF`. + +`tidb_txn_assertion_level`, takes value of `OFF`, `FAST`, or `STRICT`. Details will be discussed later. + +### Assertion + +Based on the operator characteristics and the information that the operator has already checked, some assertions can be +made with regard to the data being mutated. The assertions are pushed down to TiKV and are executed before writing. DML +operators (e.g. UpdateExec, InsertExec) are encapsulated in tables to make KV modifications to memDB: + +- Put KV: Add or update KV pairs +- Del KV: delete KV pair + +While the data is modified, the KV pair modified to memDB is additionally set with 4 new Assertion Flags (occupying a +total of 2 bits): + +- None(00): There is currently no Assertion for KV, but subsequent modifications in the transaction can overwrite this + value [default Flag] +- Unknown(11): KV pair cannot be asserted, and subsequent modifications within the transaction cannot be overwritten +- MustExist(10): Key must exist in storage, subsequent modifications within the transaction cannot be overwritten +- MustNotExist(01): Key must not exist in the storage, subsequent modifications within the transaction cannot be + overwritten + +The flags in MemDB, like the KV data, are first set to the current stage of the statement. After that, if the statement +reports an error and the statement rolls back, the flags will be invalidated. If the statement is executed successfully +and is submitted, the flags will take effect in the transaction. The assertion information is sent to TiKV in the +prewrite stage of 2PC. TiKV performs additional checks based on the assertions before modifying data. If the assertions +fail, TiKV rejects the request. + +For pessimistic transactions, prewrite requests may not read the previous value of the key. In this case, we let the +pessimistic lock requests return the existence information of the key and cache it in the client(TiDB) side. Before +committing the transaction, the client(TiDB) side will use the information to check assertions, so that doesn't have to +be the overhead of reads in TiKV. Some keys in pessimistic transactions are not pessimistically locked, so we have 2 +strategies to deal with this situation: the `FAST` mode just ignores the keys, and the `STRICT` mode will read all keys +in TiKV. + +### Check Mutations + +The basic idea is to ensure that the transaction will not write inconsistent data when the data before the transaction +is consistent. + +For possible errors in the executor: Assume that the set of row values before and after the transaction are V1 and V2 +respectively, and the data indices are consistent before the transaction is executed. The condition of data consistency +after the transaction's commitment is V1-V2 = { Del_{index}.value }, V2-V1 = { Put_{index}.value }. + +## Test Design + +The main quality objectives of this project include correctness, effectiveness, efficiency, ease of use, and +compatibility. The test part involves two parts: ensuring correctness (including compatibility) and measuring +effectiveness. + +Correctness: There will be no false positives when the data is correct + +Effectiveness: + +1. Reject transactions with inconsistent mutations +2. Report errors as soon as possible for existing problematic data to prevent the spread of errors + +### Regression tests + +Regression tests are useful to check correctness since all tests should not report data inconsistency errors. + +### System tests + +Specific system test cases need to be constructed. Cases should at least involve the following parts + +- Encoding related + - Collation + - Row format + - Charset + - Time zone +- Table structure + - Concurrent DDL + - Clustered index + - Prefix index + - Expression index + +### Performance Tests + +The enhancement should have little impact on performance, including latency, throughput, memory and CPU consumption. + +Standard sysbench and TPC-C tests are needed. + +## Impacts & Risks + +According to the performance tests, the following impacts and risks are expected: + +In the `STRICT` assertion mode, pessimistic transactions results in a notable increase in the scheduler CPU usage and +the number of kvdb get and seek operations. + +The mutation checker can increase the TiDB CPU usage. When the CPU becomes the bottleneck of TiDB, introducing the +enhancement may decrease the throughput by 1.5%, and increase P95 latency by 2.4%. + + diff --git a/docs/design/2021-12-08-instance-scope.md b/docs/design/2021-12-08-instance-scope.md new file mode 100644 index 0000000000000..9b6a58199b297 --- /dev/null +++ b/docs/design/2021-12-08-instance-scope.md @@ -0,0 +1,305 @@ +# TiDB Design Documents + +- Author(s): [morgo](http://github.com/morgo) +- Discussion PR: https://github.com/pingcap/tidb/pull/30558 +- Tracking Issue: https://github.com/pingcap/tidb/issues/30366 + +## Table of Contents + +* [Introduction](#introduction) +* [Motivation or Background](#motivation-or-background) +* [Detailed Design](#detailed-design) +* [Behavior Changes](#behavior-changes) +* [Documentation Changes](#documentation-changes) +* [Test Design](#test-design) +* [Impacts & Risks](#impacts--risks) +* [Investigation & Alternatives](#investigation--alternatives) +* [Unresolved Questions](#unresolved-questions) + +## Introduction + +Currently, TiDB has two primary methods of configuration: + +- The configuration file (in `.toml` format) ([Docs](https://docs.pingcap.com/tidb/stable/tidb-configuration-file)) +- Using MySQL compatible system variables (`SET GLOBAL sysvar=x`, `SET SESSION sysvar=x`) ([Docs](https://docs.pingcap.com/tidb/stable/system-variables)) + +Both the **semantics** and **naming conventions** differ between these two methods: + +1. Configuration file settings only apply to a single TiDB server instance. Making changes to settings managed by the configuration file requires restarting the TiDB server. +2. System variables _natively_ manage settings that have _session_ (connection) or _global_ (cluster-wide) scope. However, some _session_ scoped variables are used to allow instance configuration. This is not a feature that is natively supported, and the usage is often confusing. +3. The configuration file uses a hierarchy of sections such as `[performance]` or `[experimental]`. +4. System variables use a flat naming convention (but often use a prefix of `tidb_feature_XXX`). Thus mapping between the two is not straight forward. + +This proposal introduces _native_ support for `INSTANCE` scoped variables, such that system variables offer the superset of functionality of configuration files. It does this using a much simplified implementation from earlier proposals: an individual system variable **must not** permit both `GLOBAL` and `INSTANCE` scope. Implementing this restriction is key to this proposal; since it avoids a confusing set of precedence rules which are hard to understand. For alternative proposals see "investigation and alternatives". + +## Motivation or Background + +The motivation for this proposal is ease of use and maintainability: + +1. It's not clear if each setting should be a configuration file setting or a system variable (we usually choose system variables, but there is no clear rule). After this proposal is implemented, we can make every setting available as a system variable (even if read-only). +2. We are being asked to make additional configuration file settings dynamically configuration (via a system variable). When we do this, the naming is inconsistent. After this proposal is implemented, we can allow the `.toml` file to support an `[instance]` section where the flat named for system variables can be used. This makes it identical to how system variables are configured in MySQL. +3. The current system is hard for users. It's hard to explain the two systems, and hard to explain the differences between them. Often "INSTANCE" scoped system variables are incorrectly documented as `SESSION`, since it's not a native behavior. Explaining how `SESSION` scope is hijacked is difficult for MySQL users to understand, because usually changes in a different session should not affect your session. + +## Detailed Design + +### Stage 1: Initial Implementation + +From a user-oriented point of view, setting an instance scoped sysvar is the same as setting a `GLOBAL` variable: + +```sql +SET GLOBAL max_connections=1234; +``` + +Because `INSTANCE` and `GLOBAL` are mutually exclusive, the only semantic difference is that changes to `INSTANCE` scoped variables are not persisted and are not propagated to other TiDB servers. + +From a sysvar framework perspective the changes required are quite minimal. A new scope is added, and validating if setting permits `GLOBAL` scope also permits `INSTANCE` scope: + +``` ++++ b/sessionctx/variable/sysvar.go +@@ -56,6 +56,8 @@ const ( + ScopeGlobal ScopeFlag = 1 << 0 + // ScopeSession means the system variable can only be changed in current session. + ScopeSession ScopeFlag = 1 << 1 ++ // ScopeInstance means it is similar to global but doesn't propagate to other TiDB servers. ++ ScopeInstance ScopeFlag = 1 << 2 + + // TypeStr is the default + TypeStr TypeFlag = 0 +@@ -257,6 +259,11 @@ func (sv *SysVar) HasGlobalScope() bool { + return sv.Scope&ScopeGlobal != 0 + } + ++// HasInstanceScope returns true if the scope for the sysVar includes global or instance ++func (sv *SysVar) HasInstanceScope() bool { ++ return sv.Scope&ScopeInstance != 0 ++} ++ + // Validate checks if system variable satisfies specific restriction. + func (sv *SysVar) Validate(vars *SessionVars, value string, scope ScopeFlag) (string, error) { + // Check that the scope is correct first. +@@ -313,7 +320,7 @@ func (sv *SysVar) validateScope(scope ScopeFlag) error { + if sv.ReadOnly || sv.Scope == ScopeNone { + return ErrIncorrectScope.FastGenByArgs(sv.Name, "read only") + } +- if scope == ScopeGlobal && !sv.HasGlobalScope() { ++ if scope == ScopeGlobal && !(sv.HasGlobalScope() || sv.HasInstanceScope()) { +``` + +The session package handles loading/saving `GLOBAL` variable values. It will need minor changes to make `INSTANCE` Scope a noop operation (since persistence is not supported, and in the initial implementation a `GetGlobal()` function will be used to retrieve the instance value: + +``` ++++ b/session/session.go +@@ -1103,6 +1103,10 @@ func (s *session) GetGlobalSysVar(name string) (string, error) { + return "", variable.ErrUnknownSystemVar.GenWithStackByArgs(name) + } + ++ if sv.HasInstanceScope() { // has INSTANCE scope only, not pure global ++ return "", errors.New("variable has only instance scope and no GetGlobal func. Not sure how to handle yet.") ++ } ++ + sysVar, err := domain.GetDomain(s).GetGlobalVar(name) + if err != nil { + // The sysvar exists, but there is no cache entry yet. +@@ -1121,6 +1125,7 @@ func (s *session) GetGlobalSysVar(name string) (string, error) { + } + + // SetGlobalSysVar implements GlobalVarAccessor.SetGlobalSysVar interface. ++// it is used for setting instance scope as well. + func (s *session) SetGlobalSysVar(name, value string) (err error) { + sv := variable.GetSysVar(name) + if sv == nil { +@@ -1132,6 +1137,9 @@ func (s *session) SetGlobalSysVar(name, value string) (err error) { + if err = sv.SetGlobalFromHook(s.sessionVars, value, false); err != nil { + return err + } ++ if sv.HasInstanceScope() { // skip for INSTANCE scope ++ return nil ++ } + if sv.GlobalConfigName != "" { + domain.GetDomain(s).NotifyGlobalConfigChange(sv.GlobalConfigName, variable.OnOffToTrueFalse(value)) + } +@@ -1148,6 +1156,9 @@ func (s *session) SetGlobalSysVarOnly(name, value string) (err error) { + if err = sv.SetGlobalFromHook(s.sessionVars, value, true); err != nil { + return err + } ++ if !sv.HasInstanceScope() { // skip for INSTANCE scope ++ return nil ++ } + return s.replaceGlobalVariablesTableValue(context.TODO(), sv.Name, value) + } +``` + +A "non-native" `INSTANCE` variable can be changed to a native one as follows: + +``` ++ {Scope: ScopeInstance, Name: TiDBGeneralLog, Value: BoolToOnOff(DefTiDBGeneralLog), Type: TypeBool, skipInit: true, SetGlobal: func(s *SessionVars, val string) error { + ProcessGeneralLog.Store(TiDBOptOn(val)) + return nil +- }, GetSession: func(s *SessionVars) (string, error) { ++ }, GetGlobal: func(s *SessionVars) (string, error) { + return BoolToOnOff(ProcessGeneralLog.Load()), nil + }}, +``` + +This introduces a compatibility issue, since users who have previously configured instance scope with `SET [SESSION] tidb_general_log = x` will receive an error because the scope is wrong. This can be fixed by adding a legacy mode to the sysvar framework which allows `INSTANCE` scoped variables to be set with either `SET GLOBAL` or `SET SESSION`: + +```sql +SET GLOBAL tidb_enable_legacy_instance_scope = 1; +``` + +We can default to `TRUE` for now, but should revisit this in the future. + +### Stage 2: Mapping All Configuration File Settings to System Variables + +The second stage is to map all configuration file settings to system variable names. In MySQL any configuration file setting is also available as a system variable (even if it is read only), which makes it possible to get the configuration of the cluster with `SHOW GLOBAL VARIABLES`. Once this step is complete, it should also be possible to offer an `[instance]` section of the configuration file which accepts the system variable names (and finally consistent naming between the two systems). We can then modify the example configuration files to be based on the flat `[instance]` configuration: + +``` +# tidb.toml +[instance] +max_connections = 1234 +tidb_general_log = "/path/to/file" +``` + +The default will be that we map variables as read-only, so we don't need to think about the specific cases (i.e. you can't easily change the socket or port). This helps us achieve completeness first, and then we can then evaluate which ones can be made dynamic. + +The mapping system should consider all current instance variable mappings such as `log.enable-slow-log` to `tidb_enable_slow_log`. The earlier instance scoped variables proposal has an [example mapping table](https://docs.google.com/document/d/1RuajYAFVsjJCwCBpIYF--9jtgxDZZcz3cbP-iVuLxJI/edit?n=2020-09-15_Design_Doc_for_Instance_Variables#) which can be used as a guideline for how to create new system variable names. + +Because variables can be configured through either an "sysvar name" (under `[instance]`) or a hierarchical name, we will need to decide which is the alias versus the actual name (the actual name appears in results like `SELECT * FROM INFORMATION_SCHEMA.CLUSTER_CONFIG`). I propose for this stage the original name is still the source of truth, but in refactoring (stage 3) we switch it. + +### Stage 3: Refactoring + +The use of a `GetGlobal()` and `SetGlobal()` func for each instance scoped system variable is not ideal. It is possible to refactor the system variable framework so that instance scope is stored in a map, and the values are updated automatically by `SET GLOBAL` on an instance scoped variable. On startup, as the configuration file is parsed it will update the values in the map. This seems like a better approach than the current use of Setters/Getters, and because there is a prescribed way of doing it we can correctly handle the data races that are common with our current incorrect usage of calling `config.GetGlobalConfig()`. + +Thus, the source of truth for instance scoped variables moves from the `config` package to another part of the server (likely `domain`). See [issue #30366](https://github.com/pingcap/tidb/issues/30366). + +Because at this stage the source of truth is now no longer the `config` package, we will also need to decide how to handle features like `INFORMATION_SCHEMA.CLUSTER_CONFIG`. If it refers to the config file, it will not necessarily reflect the current configuration of the cluster. Because every instance setting will now have a system variable name (which becomes the unified name), I recommend that we deprecate `CLUSTER_CONFIG` for TiDB. We can change `CLUSTER_CONFIG` to read from the new source of truth and maintain both for some versions to support upgrades. + +## Behavior Changes + +There are **very few** known scenarios where a system variable is *currently both* instance and global scoped, but each of these will require behavior changes. Here is a script to detect them: + +``` +package main + +import ( + "fmt" + + _ "github.com/go-sql-driver/mysql" + "github.com/pingcap/tidb/sessionctx/variable" +) + +func main() { + for _, v := range variable.GetSysVars() { + if v.HasGlobalScope() && v.HasSessionScope() && (v.GetSession != nil || v.SetSession != nil) && (v.GetGlobal != nil || v.SetGlobal != nil) { + fmt.Printf("%s\n", v.Name) + } + } +} +``` + +**Output:** + +``` +tidb_store_limit +tidb_stmt_summary_internal_query +tidb_enable_stmt_summary +tidb_stmt_summary_max_sql_length +tidb_stmt_summary_max_stmt_count +tidb_capture_plan_baselines +tidb_stmt_summary_refresh_interval +tidb_stmt_summary_history_size +``` + +Changes can be grouped into the following: + +1. `tidb_store_limit`: This has now been converted to global-only, see [issue #30515 (merged)](https://github.com/pingcap/tidb/issues/30515). +2. `tidb_stmt_summary_XXX`, `tidb_enable_stmt_summary` and `tidb_capture_plan_baselines` (features work together): The recommendation discussed with the feature maintainers is to convert to global only. + +The change to `tidb_store_limit` is unlikely to affect users, since the feature was not working correctly. However, the change to statement summary and capture plan baselines is a behavior change which might affect some users. + +## Documentation Changes + +For the purposes of user-communication we don't need to use the terminology `INSTANCE`. We will remove more of the confusion by instead referring to the difference between these as whether it "persists to [the] cluster". This also aligns closer to the syntax that users will be using. Consider the following example changes which are easier to read (the current text also doesn't actually explain that to set an `INSTANCE` variable you must use `SET SESSION`, so it actually communicates a lot more in fewer words): + +``` ++++ b/system-variables.md +@@ -6,13 +6,11 @@ aliases: ['/tidb/dev/tidb-specific-system-variables','/docs/dev/system-variables + + # System Variables + +-TiDB system variables behave similar to MySQL with some differences, in that settings might apply on a `SESSION`, `INSTANCE`, or `GLOBAL` scope, or on a scope that combines `SESSION`, `INSTANCE`, or `GLOBAL`. ++TiDB system variables behave similar to MySQL, in that settings apply on a `SESSION` or `GLOBAL` scope: + +-- Changes to `GLOBAL` scoped variables **only apply to new connection sessions with TiDB**. Currently active connection sessions are not affected. These changes are persisted and valid after restarts. +-- Changes to `INSTANCE` scoped variables apply to all active or new connection sessions with the current TiDB instance immediately after the changes are made. Other TiDB instances are not affected. These changes are not persisted and become invalid after TiDB restarts. +-- Variables can also have `NONE` scope. These variables are read-only, and are typically used to convey static information that will not change after a TiDB server has started. +- +-Variables can be set with the [`SET` statement](/sql-statements/sql-statement-set-variable.md) on a per-session, instance or global basis: ++- Changes on a `SESSION` scope will only affect the current session. ++- Changes on a `GLOBAL` scope apply immediately, provided that the variable is not also `SESSION` scoped. In which case all sessions (including your session) will continue to use their current session value. ++- Changes are made using the [`SET` statement](/sql-statements/sql-statement-set-variable.md): + + ```sql + # These two identical statements change a session variable +@@ -26,9 +24,9 @@ SET GLOBAL tidb_distsql_scan_concurrency = 10; + + > **Note:** + > +-> Executing `SET GLOBAL` applies immediately on the TiDB server where the statement was issued. A notification is then sent to all TiDB servers to refresh their system variable cache, which will start immediately as a background operation. Because there is a risk that some TiDB servers might miss the notification, the system variable cache is also refreshed automatically every 30 seconds. This helps ensure that all servers are operating with the same configuration. ++> Several `GLOBAL` variables persist to the TiDB cluster. For variables that specify `Persists to Cluster: Yes` a notification is sent to all TiDB servers to refresh their system variable cache when the global variable is changed. Adding additional TiDB servers (or restarting existing TiDB servers) will automatically use the persisted configuration value. For variables that specify `Persists to Cluster: No` any changes only apply to the local TiDB instance that you are connected to. In order to retain any values set, you will need to specify them in your `tidb.toml` configuration file. + > +-> TiDB differs from MySQL in that `GLOBAL` scoped variables **persist** through TiDB server restarts. Additionally, TiDB presents several MySQL variables as both readable and settable. This is required for compatibility, because it is common for both applications and connectors to read MySQL variables. For example, JDBC connectors both read and set query cache settings, despite not relying on the behavior. ++> Additionally, TiDB presents several MySQL variables as both readable and settable. This is required for compatibility, because it is common for both applications and connectors to read MySQL variables. For example, JDBC connectors both read and set query cache settings, despite not relying on the behavior. + + > **Note:** + > +@@ -47,6 +45,7 @@ SET GLOBAL tidb_distsql_scan_concurrency = 10; + ### allow_auto_random_explicit_insert New in v4.0.3 + + - Scope: SESSION | GLOBAL ++- Persists to cluster: Yes + - Default value: `OFF` + - Determines whether to allow explicitly specifying the values of the column with the `AUTO_RANDOM` attribute in the `INSERT` statement. + +@@ -166,7 +165,8 @@ mysql> SELECT * FROM t1; + + ### ddl_slow_threshold + +-- Scope: INSTANCE ++- Scope: GLOBAL ++- Persists to cluster: No + - Default value: `300` + - Unit: Milliseconds + - Log DDL operations whose execution time exceeds the threshold value. +``` + +What this does mean is that each variable that includes `GLOBAL` or `INSTANCE` scope needs a new line added in Docs. But this can be [auto-generated](https://github.com/pingcap/docs/pull/5720) from the sysvar source code. + +## Impacts & Risks + +The biggest risk is that we can not agree on a reduced scope of implementation and the project extends to cover increased scope. Configuration management is a classic example of a [bikeshed problem](https://en.wikipedia.org/wiki/Law_of_triviality), and we will likely need to make some tradeoffs to get anywhere. + +Many of the alternatives are difficult to implement because they break compatibility (we need to live with `GLOBAL` means cluster `GLOBAL`, and there is no `SET CLUSTER`) or they break rolling upgrade scenarios because we currently have no specific rules of the minimum version of TiDB which can be upgraded from. + +## Investigation & Alternatives + +- There is no equivalent functionality to reference in MySQL since it does not have the native concept of a cluster _in the context of configuration_. +- An [earlier proposal](https://docs.google.com/document/d/1RuajYAFVsjJCwCBpIYF--9jtgxDZZcz3cbP-iVuLxJI/edit) for `INSTANCE` scope, with rules for precedence (same author) +- CockroachDB has cluster level settings and node-level settings. Most settings are cluster level, and [node-level](https://www.cockroachlabs.com/docs/v21.2/cockroach-start) needs to be parsed as arguments when starting the server. + +### SET INSTANCE syntax + +A small behavior change (still with the restriction that `INSTANCE` and `GLOBAL` are mutually exclusive) proposes adding `SET INSTANCE` as explicit syntax to set an instance-scoped variable. This would require the following modifications to be complete: +- `SHOW INSTANCE VARIABLES` will need to return variables that have `NONE` or `INSTANCE` scope (and `SHOW VARIABLES` continues to return all variables). +- The parser will need to support `SET INSTANCE` syntax and the `@@instance.variable` syntax +- Various parser ast code will also need modifying because a boolean can no longer reflect the scope. + +The advantage of this proposal is that the documentation and usage is clearer. The disadvantage is that because MySQL does not have an instance scope (global scope in MySQL is instance-like) it could create strange behaviors with compatibility sysvars which are implemented. This **only** affects `INSTANCE` variables which are *not already* `ScopeNone` (so Port, Socket, GrantTables, LogBin are not affected). The only currently known example that is affected is `max_connections`, which is currently a noop in system variables, but available in the configuration file as `max-server-connections` (it is presumed it would be [mapped](https://docs.google.com/document/d/1RuajYAFVsjJCwCBpIYF--9jtgxDZZcz3cbP-iVuLxJI/edit?n=2020-09-15_Design_Doc_for_Instance_Variables#) to `max_connections` in Stage 2). + +This means that `SET GLOBAL max_connections` would need to return an error in TiDB, because the correct syntax is `SET INSTANCE max_connections`. There is a known failover use-case to execute `SET GLOBAL max_connections = 1` + `SET GLOBAL [super_]read_only = 1` to disable writes. However, this already does not work in TiDB as there is no support for `SET GLOBAL [super_]read_only=1`. Thus, removing this compatibility does not appear to be a blocking issue. + +However, the IBG support team rejects this proposal based on the expectation that there will be further tool compatibility issues not yet discovered. As MySQL does not have `SET INSTANCE` scope, users will also not be used to using this syntax. + +## Unresolved Questions + +- None \ No newline at end of file diff --git a/docs/design/2022-01-04-integer-shard-index.md b/docs/design/2022-01-04-integer-shard-index.md new file mode 100644 index 0000000000000..6c630a51f0e90 --- /dev/null +++ b/docs/design/2022-01-04-integer-shard-index.md @@ -0,0 +1,447 @@ +# Integer shard index + +- Tracking Issue: https://github.com/pingcap/tidb/issues/31040 + +Here is a table definition as bellow. The service writes data monotonically on the field `id2`, so the index `hotIndex` becomes a hot index which hinders the scalability of a TiDB cluster. The service executes point SELECT and point UPDATE by the `hotIndex`. + +```sql +CREATE TABLE test(id1 INT PRIMARY, id2 INT, id3 INT, UNIQUE KEY hotIndex(id2)); + +INSERT INTO test values(val1,val2,val3); +UPDATE test SET id3 = val3 WHERE id2 = val2; +SELECT * FROM test WHERE id2 = val2; +``` + +The Integer shard index realized by this design doc can scatter `hotIndex` and ensure the service sqls still use the unique key `hotIndex`. Here is the new table definition including shard index as bellow. + +```sql +CREATE TABLE test(id1 INT PRIMARY, id2 INT, id3 INT, UNIQUE KEY hotIndex((tidb_shard(id2)),id2)); +``` + +Do we need to modify service sqls above? No, we don't. Optimizer can recognize the shard index and add `tidb_shard(id2) = shardVal` to the `WHERE` clause automatically. Here is the final form of service sqls processed by optimizer as bellow. So, we don't need to modify service sqls and theses sqls can still use the unique index `hotIndex` + +```sql +UPDATE test SET id3 = val3 WHERE tidb_shard(id2) = 8 AND id2 = 100; +SELECT * FROM test WHERE tidb_shard(id2) = 8 AND id2 = 100; +``` + + + +## Summary + +Hot index reduces the write scalability of the TiDB cluster when the written data is monotonically increasing. We find out a proposal to solve the problem that is using an expression index to scatter the hot index, the new expression index is called a shard index. + +The followers is the scalability of hot index and shard index. + +| threads | tidb | tikv | tidb CPU | tikv CPU | duration(95) | QPS(K) | scalability | remark | +| ------- | ---- | ---- | -------- | -------- | ---------------------------- | ------ | ----------- | ------ | +| 800 | 3 | 3 | 4700 | 3350 | insert: 60.5 update:110 | 49.8 | | | +| 800 | 3 | 3 | 4400 | 3000 | insert: 61 update:111 | 49 | | | +| 800 | 3 | 4 | 5000 | 3500 | insert: 57 update:103 | 53 | 19.30% | round1 | +| 800 | 3 | 4 | 5100 | 3600 | insert: 56 update:100 | 54 | 30.60% | round2 | + +​ hot index scalability + + + +| threads | tidb | tikv | tidb CPU | tikv CPU | duration | QPS | scalability | remark | +| ------- | ---- | ---- | -------- | -------- | --------------------------- | ---- | ----------- | ------ | +| 800 | 3 | 3 | 5200 | 3100 | insert: 60 update:110 | 47.5 | | | +| 800 | 3 | 3 | 5200 | 3000 | insert: 60 update:110 | 47.2 | | | +| 800 | 3 | 4 | 6200 | 3800 | insert: 56.5 update:88 | 57.5 | 63.20% | round1 | +| 800 | 3 | 4 | 6250 | 3800 | insert: 56.5 update:88 | 58.5 | 71.40% | round2 | + +​ shard index scalability + + + +Computing formula of scalability is as bellow: `qps1` is the qps before expansion, `tikv1` is the tikv node count before expansion; `qps2` is the qps after expansion, `tikv2` is the tikv node count afterexpansion. + +CNF 200 + + + +## Detailed design + +We made a new built-in function "tidb_shard()" as the expression prefix of shard index. There is only one integer parameter for tidb_shard function. What index is a shard index? It must meet the follower rules. + +- It is an unique index +- The first field of index is tidb_shard(`a`) , the column `a` is integer type and is the second field of the index. + +When querying based on the original index field, the TiDB optimizer should automatically recognize the shard index and add the expression field `tidb_shard(a) = val` to the query condition. + +How to solve the hot index problem by shard index? For example, the definition of a table is `test(id int primary key clustered, a int, b int, unique key idx_a(a))` . The index `idx_a` is a hot index because of monotonically increasing data. We modify the definition of the index `idx_a` as follows `unique key idx_a((tidb_shard(a)),a)`. The written data of index `idx_a` is not monotonically increasing now. But here is a question, how the optimizer of TiDB chooses the index for original queries that are designed for `idx_a(a)`? e.g. `SELECT * FROM test WHERE a = 100`, it can't use the unique index 'idx_a((tidb_shard(a)),a' any more. We add a new rule for TiDB optimizer, if the access condition of a query contains all the fields of shard index except the first `tidb_shard(a)` expression, The optimizer adds the expression`tidb_shard(a) = xxx` to the access condition and the new query statement is like `SELECT * FROM test WHERE tidb_shard(a) = 8 AND a = 100`, so that the query can use the shard index. + +### tidb_shard function + +#### dsciription + +Only support an integer parameter. It transforms an integer number to a value in the range [0, 255]. e.g. `tidb_shard(100)` is the value `8` . + +#### principle + +It calculate the hash value of the input parameter, and get the mod value by 256. + +```go +func (b *builtinTidbShardSig) evalInt(row chunk.Row) (int64, bool, error) { + shardKeyInt, isNull, err := b.args[0].EvalInt(b.ctx, row) + if isNull || err != nil { + return 0, true, err + } + var hashed uint64 + if hashed, err = vitess.HashUint64(uint64(shardKeyInt)); err != nil { + return 0, true, err + } + hashed = hashed % tidbShardBucketCount + return int64(hashed), false, nil +} +``` + + + +### Add expression to access condition by optimizer + +The optimizer should add the expresion `tidb_shard(xxx) = yyy` to the access condition, so that a the query can use shard index. + +The follower are the functions used to add the expresion `tidb_shard(xxx) = yyy` to the access condition. They are Introduced in order of function call. + + + +#### (ds *DataSource) PredicatePushDown + +The entry point to add the `tidb_shard` expression is the function as bellow. We must add it before access condition was pushed down. Maybe this work should be done after sql parse, we do it here just for simplify the work. + +```go + +func (ds *DataSource) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { + predicates = expression.PropagateConstant(ds.ctx, predicates) + predicates = DeleteTrueExprs(ds, predicates) + // Add tidb_shard() prefix to the condtion for shard index in some scenarios + // TODO: remove it to the place building logical plan + predicates = ds.AddPrefix4ShardIndexes(ds.ctx, predicates) + ds.allConds = predicates + ds.pushedDownConds, predicates = expression.PushDownExprs(ds.ctx.GetSessionVars().StmtCtx, predicates, ds.ctx.GetClient(), kv.UnSpecified) + appendDataSourcePredicatePushDownTraceStep(ds, opt) + return predicates, ds +} +``` + +#### (ds *DataSource) AddPrefix4ShardIndexes + +`AddPrefix4ShardIndexes` is the interface to add expression prefix for shard index. Pay attention, just for shard index! + +```go +// AddPrefix4ShardIndexes Add expression prefix for shard index. e.g. an index is test.uk(tidb_shard(a), a). +// It transforms the sql "SELECT * FROM test WHERE a = 10" to +// "SELECT * FROM test WHERE tidb_shard(a) = val AND a = 10", val is the value of tidb_shard(10). +// It also transforms the sql "SELECT * FROM test WHERE a IN (10, 20, 30)" to +// "SELECT * FROM test WHERE tidb_shard(a) = val1 AND a = 10 OR tidb_shard(a) = val2 AND a = 20" +// @param[in] conds the original condtion of this datasource +// @retval - the new condition after adding expression prefix +func (ds *DataSource) AddPrefix4ShardIndexes(sc sessionctx.Context, conds []expression.Expression) []expression.Expression { + if !ds.containExprPrefixUk { + return conds + } + + var err error + newConds := make([]expression.Expression, 0, len(conds)) + newConds = append(newConds, conds...) + + for _, path := range ds.possibleAccessPaths { + if path.IsTablePath() || !path.IsUkShardIndex() { + continue + } + newConds, err = ds.addExprPrefixCond(sc, path, newConds) + if err != nil { + logutil.BgLogger().Error("Add tidb_shard expression failed", zap.Error(err)) + return conds + } + } + + return newConds +} +``` + +#### (ds *DataSource) addExprPrefixCond + +`addExprPrefixCond` is the wrapper for `addExprPrefix4ShardIndex` + +```go +func (ds *DataSource) addExprPrefixCond(sc sessionctx.Context, path *util.AccessPath, + conds []expression.Expression) ([]expression.Expression, error) { + IdxCols, IdxColLens := + expression.IndexInfo2PrefixCols(ds.Columns, ds.schema.Columns, path.Index) + if len(IdxCols) == 0 { + return conds, nil + } + + adder := &exprPrefixAdder{ + sctx: sc, + OrigConds: conds, + cols: IdxCols, + lengths: IdxColLens, + } + + return adder.addExprPrefix4ShardIndex() +} +``` + +#### (adder *exprPrefixAdder) addExprPrefix4ShardIndex + +`addExprPrefix4ShardIndex` is the wrapper for `addExprPrefix4DNFCond` and `addExprPrefix4CNFCond`. `addExprPrefix4DNFCond` is used to process `OR` expression, `addExprPrefix4CNFCond` is used to process `AND` expression. + +```Go +// if original condition is a LogicOr expression, such as `WHERE a = 1 OR a = 10`, +// call the function AddExprPrefix4DNFCond to add prefix expression tidb_shard(a) = xxx for shard index. +// Otherwise, if the condition is `WHERE a = 1`, `WHERE a = 1 AND b = 10`, `WHERE a IN (1, 2, 3)`......, +// call the function AddExprPrefix4CNFCond to add prefix expression for shard index. +func (adder *exprPrefixAdder) addExprPrefix4ShardIndex() ([]expression.Expression, error) { + if len(adder.OrigConds) == 1 { + if sf, ok := adder.OrigConds[0].(*expression.ScalarFunction); ok && sf.FuncName.L == ast.LogicOr { + return adder.addExprPrefix4DNFCond(sf) + } + } + return adder.addExprPrefix4CNFCond(adder.OrigConds) +} +``` + + + +#### (adder *exprPrefixAdder) addExprPrefix4DNFCond + +- function declaration + + +```go +// add the prefix expression for DNF condition, e.g. `WHERE a = 1 OR a = 10`, ...... +// The condition returned is `WHERE (tidb_shard(a) = 214 AND a = 1) OR (tidb_shard(a) = 142 AND a = 10)` +// @param[in] condition the original condtion of the datasoure. e.g. `WHERE a = 1 OR a = 10`. +// condtion is `a = 1 OR a = 10` +// @return - the new condition after adding expression prefix. It's still a LogicOr expression. +func (adder *exprPrefixAdder) addExprPrefix4DNFCond(condition *expression.ScalarFunction) ([]expression.Expression, error) +``` + +- Function Process + - Extract evrey binary expression from `condition` to a expression.Expression slice `dnfItems`. + - Make a new expression.Expression slice `newAccessItems` to store new condtions after processing tidb_shard prefix. + - Traverse every `item` in slice `dnfItems`, if it's a `LogicAnd` expression, extracts every binary expression from it to a slice `cnfItems` and calls function `addExprPrefix4CNFCond(cnfItems)` to add tidb_shard prefix if need; if it's a `ast.EQ` or a `ast.In` expression, calls function `addExprPrefix4CNFCond([]Expression{item})` to add tidb_shard prefix if need. + - Make a new `LogicOR` condition by `newAccessItems`, return it. + + + +#### (adder *exprPrefixAdder) addExprPrefix4CNFCond + +Call the function `ranger.AddExpr4EqAndInCondition` to process `AND` expression. + +```go +// add the prefix expression for CNF condition, e.g. `WHERE a = 1`, `WHERE a = 1 AND b = 10`, ...... +// @param[in] conds the original condtion of the datasoure. e.g. `WHERE t1.a = 1 AND t1.b = 10 AND t2.a = 20`. +// if current datasource is `t1`, conds is {t1.a = 1, t1.b = 10}. if current datasource is +// `t2`, conds is {t2.a = 20} +// @return - the new condition after adding expression prefix +func (adder *exprPrefixAdder) addExprPrefix4CNFCond(conds []expression.Expression) ([]expression.Expression, error) { + + newCondtionds, err := ranger.AddExpr4EqAndInCondition(adder.sctx, + conds, adder.cols) + + return newCondtionds, err +} +``` + +##### AddExpr4EqAndInCondition + +The core function that adds `tidb_shard(x) = xxx` to the accessCond. + +- function declaration + +```go +// AddExpr4EqAndInCondition add the `tidb_shard(x) = xxx` prefix +// Add tidb_shard() for EQ and IN function. e.g. input condition is `WHERE a = 1`, +// output condition is `WHERE tidb_shard(a) = 214 AND a = 1`. e.g. input condition +// is `WHERE a IN (1, ,2 ,3)`, output condition is `WHERE (tidb_shard(a) = 214 AND a = 1) +// OR (tidb_shard(a) = 143 AND a = 2) OR (tidb_shard(a) = 156 AND a = 3)` +// @param[in] conditions the original condition to be processed +// @param[in] cols the columns of shard index, such as [tidb_shard(a), a, ...] +// @param[in] lengths the length for every column of shard index +// @retval - the new condition after adding tidb_shard() prefix +func AddExpr4EqAndInCondition(sctx sessionctx.Context, conditions []expression.Expression, + cols []*expression.Column) ([]expression.Expression, error) +``` + +- Function Process + - Traverse every `cond` in slice `conditions`, place the `cond` to a new slice `accesses` according to the index definition field order. + - Traverse every `cond` in slice `accesses`, if the `cond` is not a `ast.EQ` or `ast.In` expression, do nothing and return, otherwise extract the column value from `cond` and store it to slice `columnValues`. + - Call the function `NeedAddGcColumn4ShardIndex` to judge if necessary to add `tidb_shard` prefix for `conditions`, if not, do nothing and return; otherwise call function `AddGcColumnCond` to add `tidb_shard` prefix for `conditions`. + + + +##### NeedAddGcColumn4ShardIndex + +Check whether to add `tidb_shard(x) = xxx` to the access condition. + +- function declaration + +```go +// NeedAddGcColumn4ShardIndex check whether to add `tidb_shard(x) = xxx` +// @param[in] cols the columns of shard index, such as [tidb_shard(a), a, ...] +// @param[in] accessCond the condtions relative to the index and arranged by the index column order. +// e.g. the index is uk(tidb_shard(a), a, b) and the where clause is +// `WHERE b = 1 AND a = 2 AND c = 3`, the param accessCond is {a = 2, b = 1} that is +// only relative to uk's columns. +// @param[in] columnValues the values of index columns in param accessCond. if accessCond is {a = 2, b = 1}, +// columnValues is {2, 1}. if accessCond the "IN" function like `a IN (1, 2)`, columnValues +// is empty. +// @retval - return true if it needs to addr tidb_shard() prefix, ohterwise return false +func NeedAddGcColumn4ShardIndex( + cols []*expression.Column, + accessCond []expression.Expression, + columnValues []*valueInfo) bool +``` + +- Function Process + - The columns of shard index shoude be more than 2, like `(tidb_shard(a),a,...)`. + - The first column of index must be a generated column and the expression must be `tidb_shard` built-in function. + - The argument of `tidb_shard` must be a column other than expression or else, and it must be the second column of the index. + + + +##### AddGcColumnCond + +`AddGcColumnCond` is the wrapper function for `AddGcColumn4EqCond` and `AddGcColumn4InCond`. + +```go +// AddGcColumnCond add the `tidb_shard(x) = xxx` to the condition +// @param[in] cols the columns of shard index, such as [tidb_shard(a), a, ...] +// @param[in] accessCond the condtions relative to the index and arranged by the index column order. +// e.g. the index is uk(tidb_shard(a), a, b) and the where clause is +// `WHERE b = 1 AND a = 2 AND c = 3`, the param accessCond is {a = 2, b = 1} that is +// only relative to uk's columns. +// @param[in] columnValues the values of index columns in param accessCond. if accessCond is {a = 2, b = 1}, +// columnValues is {2, 1}. if accessCond the "IN" function like `a IN (1, 2)`, columnValues +// is empty. +// @retval - []expression.Expression the new condtions after adding `tidb_shard() = xxx` prefix +// error if error gernerated, return error +func AddGcColumnCond(sctx sessionctx.Context, + cols []*expression.Column, + accessesCond []expression.Expression, + columnValues []*valueInfo) ([]expression.Expression, error) { + + if cond := accessesCond[1]; cond != nil { + if f, ok := cond.(*expression.ScalarFunction); ok { + switch f.FuncName.L { + case ast.EQ: + return AddGcColumn4EqCond(sctx, cols, accessesCond, columnValues) + case ast.In: + return AddGcColumn4InCond(sctx, cols, accessesCond) + } + } + } + + return accessesCond, nil +} +``` + + + +##### AddGcColumn4EqCond + +Add the `tidb_shard(x) = xxx` prefix for equal access condition. + +- function declaration + +```go +// AddGcColumn4EqCond add the `tidb_shard(x) = xxx` prefix for equal condition +// For param explanation, please refer to the function `AddGcColumnCond`. +// @retval - []expression.Expression the new condtions after adding `tidb_shard() = xxx` prefix +// []*valueInfo the values of every columns in the returned new condtions +// error if error gernerated, return error +func AddGcColumn4EqCond(sctx sessionctx.Context, + cols []*expression.Column, + accessesCond []expression.Expression, + columnValues []*valueInfo) ([]expression.Expression, error) +``` + +- Function Process + - Traverse every `ColumnValue` in slice `columnValues`, calculate the value of `tidb_shard` by `ColumnValue` and store it to the variable`evaluated`. + - Make a new expression `tidb_shard(columnName) = evaluated` and store it to `accessesCond[0]` + + + +##### AddGcColumn4InCond + + Add the `tidb_shard(x) = xxx` for `IN` condition. + +- function declaration + +```go +// AddGcColumn4InCond add the `tidb_shard(x) = xxx` for `IN` condition +// For param explanation, please refer to the function `AddGcColumnCond`. +// @retval - []expression.Expression the new condtions after adding `tidb_shard() = xxx` prefix +// error if error gernerated, return error +func AddGcColumn4InCond(sctx sessionctx.Context, + cols []*expression.Column, + accessesCond []expression.Expression) ([]expression.Expression, error) +``` + +- Function Process + +Traverse every `argument` from `In` expression, calculate the `value` of `tidb_shard` with `argument` and make a new expression `tidb_shard(columnName) = value`, then make a `LogicAnd` like `tidb_shard(a) = 8 AND a = 100`. When process the second or above argument , add the `LogicAnd` to the `LogicOR` expression, like `tidb_shard(a) = 8 AND a = 100 OR tidb_shard(a) = 8 AND a = 100`. + + + +## Drawbacks + +Using the shard index to replace the hot index my decrease a little of the performance when the TiDB cluster is small and the pressure of workload is not high, But it can increase the scalability obviously. + + + +## Alternatives + +We can use expression index directly other than as the prefix of a index. e.g. replace `index idx(a)` to `indx idx(expr(a))` , it seems more simpler. But `expr(a)` and `(a)` don't correspond one to one, the PointGet plan becomes IndexRangeScan and the selection operation `WEHRE a = xxx` must be executed in the tidb-server or tikv. So the performance may be dropped a lot. + + + +## Unresolved questions + +### Shard Index Only Support Unique Secondary Index + +The shard index is only valid for unique secondary index, not for primary key or non-unique secondary index, and it must meet the follower rules. + +- It is an unique index +- The first field of index is tidb_shard(`a`) , the column `a` is integer type and is the second field of the index. + +### Non-equivalent Condition Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query ` SELECT * FROM A WHERE a > 100 `.The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more. + +### `AND` Expression Mixing With `OR` Expression Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for all "AND" expression or all "OR" expression or none of them in `WHERE` clause. If "and" expression mixing with "or" expression in `WHERE` clause, it can't use index. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query ` SELECT * FROM A WHERE ((a=100 and b = 100) or a = 200) and b = 300 `. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more. + +### Group By Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. It does nothings for `GROUP BY ` clause. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query ` SELECT SUM(a) FROM A GROUP BY a `. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more and it needs to be grouped in tidb-server. + +### Order By Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. It does nothing for `ORDER BY ` clause. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query ` SELECT a FROM A ORDER BY a `. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more and it needs to be orderedin tidb-server. + +### Join Condition Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. It does nothing for the `ON` clause. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query ` SELECT * FROM B JOIN A ON B.a = A.a`. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more. + +### Where Subquery Can't Use Index + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. It does nothing for the sub-query clause. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a)` for query `SELECT * FROM A WHERE A.a IN (SELECT B.a FROM B WHERE B.a > 100) `. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, optimizer doesn't choose index for the query above any more. + +### Joint Index May Be Invalid + +The proposal only adds expression `tidb_shard(?) = ?` for equivalent condition in `WHERE` clause. If the access condition in `WHERE` clause only use part of a joint index, this proposal may leads to index useless. e.g. If there is a unique index `uk(a)` on table `A` , optimizer chooses index scan by `uk(a, b)` for query ` SELECT * FROM A WHERE A.a = 10`. The index definition is changed to `uk(tidb_shard(a), a, b)` by this proposal, optimizer doesn't choose index for the query above any more. + +### FastPlan May Be Invalid + +It can't adds expression `tidb_shard(?) = ?` to access condition in the FastPlan process. So, the FastPlan process is invalid for shard index. e.g. If there is a unique index `uk(a)` on table `A` , optimizer makes a PointGet plan by FastPlan process for query ` SELECT * FROM A WHERE A.a = 100`. The index definition is changed to `uk(tidb_shard(a), a)` by this proposal, FastPlan can't recognize it is a shard index field in `WHERE` clause. + +### Shard Index Can't Use Prepare Plan Cache + +If there is a generated column on a table, the queries about this table can't use prepare plan cache. Shard index uses the expression `tidb_shard(a)` as the first field, and it makes a generated column. So the table with shard index can't use prepare plan cache. diff --git a/docs/design/2022-03-03-rc-read-tso-optimization.md b/docs/design/2022-03-03-rc-read-tso-optimization.md new file mode 100644 index 0000000000000..ce9647e1418be --- /dev/null +++ b/docs/design/2022-03-03-rc-read-tso-optimization.md @@ -0,0 +1,35 @@ +# Read-Committed Read With Timestamp Check + +- Author(s): cfzjywxk +- Last updated: March. 3, 2022 +- Discussion at: + +## Motivation + +For the `read-committed` isolation level, each read request in a single transaction will need to fetch a new `ts` to read the latest committed data. +If the workload is a read-heavy one whose read QPS is significantly higher than writes or there're few read-write conflicts, fetching ts each time will increase the query lantecy. + +The new ts itself is used to ensure the most recent data will be returned, if the data version does not change frequently then it's unnecessary to fetch a new timestamp every time. +The ts fetching could be processed in an optimistic way that ts fetching happens only when a more recent data version is encoutered, this saves the cost of many unncessary ts fetching. + +## Detailed Design + +Introduce another system variable `tidb_rc_read_check_ts` to enable the "lazy ts fetch" read mode. It will take effect for all the in-transaction select statements when the transaction mode is `pessimistic` and the isolation level is `read-committed`. + +The execution flow is like this: + +1. If the query is executed first time, do not fetch a new `for_update_ts` and just use the last valid one(`start_ts` for the first time). +2. Do build the plan and executor like before. +3. If the execution is successful, a `resultSet` will be returned. +4. The connection layer will drive the response procesure and call `Next` function using the returned `resultSet`. +5. The read executor will try to fetch data to fill in a data `chunk`. The bottommost executor could be a `pointGet`, `batchPointGet` or a coprocessor task. What's different is a `RcReadCheckTS` flag will be set on all these read requests. +6. The read executor in the storage layer will check the read results, if a more recent version does exist then a `WriteConflict` error is reported. +7. For data write record, do check if it's newer than the current `read_ts`. +8. For lock record, return `ErrKeyIsLocked` even though the `lock.ts` is greater than the `read_ts` as the `read_ts` could be a stale one. +9. If no error is returned then the query is finished. Otherwise if there's no `chunk` responsed to the client yet, retry the whole query fetching a new global ts to do the read like normal. + + +## Compatibility + +The default behaviours of the `read-committed` isolation level will not change. One thing different is that if the user client uses `COM_STMT_FETCH` like utility to read data from `TiDB`, +there could be problem if the returned first chunk result is already used by the client but an error is reported processing next result chunk. diff --git a/docs/design/imgs/scalability-formula.png b/docs/design/imgs/scalability-formula.png new file mode 100644 index 0000000000000..e435309e7ac7a Binary files /dev/null and b/docs/design/imgs/scalability-formula.png differ diff --git a/docs/tidb_http_api.md b/docs/tidb_http_api.md index 7a7e6d27a20d8..c9d63f5ea4e6b 100644 --- a/docs/tidb_http_api.md +++ b/docs/tidb_http_api.md @@ -214,6 +214,11 @@ "value": { "info": { "writes": [ + { + "type": 1, + "start_ts": 423158426542538752, + "commit_ts": 423158426543587328 + }, { "start_ts": 423158426542538752, "commit_ts": 423158426543587328, @@ -231,6 +236,21 @@ } ``` + *Hint: The meaning of the MVCC operation type:* + + ```protobuf + enum Op { + Put = 0; + Del = 1; + Lock = 2; + Rollback = 3; + // insert operation has a constraint that key should not exist before. + Insert = 4; + PessimisticLock = 5; + CheckNotExists = 6; + } + ``` + 1. Get MVCC Information of the first key in the table with a specified start ts ```shell @@ -283,10 +303,10 @@ timezone.* } ``` - *Hint: On a partitioned table, use the `table(partition)` pattern as the table name, `test(p1)` for example:* + *Hint: On a partitioned table, use the `table(partition)` pattern as the table name, `t1(p1)` for example:* ```shell - $curl http://127.0.0.1:10080/mvcc/index/test(p1)/t1/idx/1\?a\=A + $curl http://127.0.0.1:10080/mvcc/index/test/t1(p1)/idx/1\?a\=A ``` If the handle is clustered, also specify the primary key column values in the query string @@ -436,6 +456,8 @@ timezone.* curl -X POST http://{TiDBIP}:10080/ddl/owner/resign ``` + **Note**: If you request a TiDB that is not ddl owner, the response will be `This node is not a ddl owner, can't be resigned.` + 1. Get all TiDB DDL job history information. ```shell @@ -448,8 +470,6 @@ timezone.* curl http://{TiDBIP}:10080/ddl/history?limit={number} ``` - **Note**: If you request a tidb that is not ddl owner, the response will be `This node is not a ddl owner, can't be resigned.` - 1. Download TiDB debug info ```shell @@ -522,6 +542,13 @@ timezone.* curl -X POST -d "tidb_enable_1pc=0" http://{TiDBIP}:10080/settings ``` +1. Enable/disable the mutation checker + + ```shell + curl -X POST -d "tidb_enable_mutation_checker=1" http://{TiDBIP}:10080/settings + curl -X POST -d "tidb_enable_mutation_checker=0" http://{TiDBIP}:10080/settings + ``` + 1. Get/Set the size of the Ballast Object ```shell diff --git a/domain/db_test.go b/domain/db_test.go index b91a43d94c20c..990ec2ad41a70 100644 --- a/domain/db_test.go +++ b/domain/db_test.go @@ -19,13 +19,13 @@ import ( "testing" "time" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/stretchr/testify/require" ) -// SubTestDomainSession is batched in TestDomainSerial -func SubTestDomainSession(t *testing.T) { +func TestDomainSession(t *testing.T) { lease := 50 * time.Millisecond store, err := mockstore.NewMockStore() require.NoError(t, err) @@ -36,6 +36,7 @@ func SubTestDomainSession(t *testing.T) { session.SetSchemaLease(lease) domain, err := session.BootstrapSession(store) require.NoError(t, err) + ddl.DisableTiFlashPoll(domain.DDL()) defer domain.Close() // for NotifyUpdatePrivilege diff --git a/domain/domain.go b/domain/domain.go index d3a9664b97fe7..af1e46a0f0cbf 100644 --- a/domain/domain.go +++ b/domain/domain.go @@ -25,7 +25,6 @@ import ( "unsafe" "github.com/ngaut/pools" - "github.com/ngaut/sync2" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/bindinfo" @@ -50,6 +49,7 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/telemetry" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/domainutil" @@ -57,8 +57,10 @@ import ( "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" "github.com/tikv/client-go/v2/txnkv/transaction" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/clientv3/concurrency" + pd "github.com/tikv/pd/client" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3/concurrency" + atomicutil "go.uber.org/atomic" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/keepalive" @@ -84,18 +86,20 @@ type Domain struct { sysVarCache sysVarCache // replaces GlobalVariableCache slowQuery *topNSlowQueries expensiveQueryHandle *expensivequery.Handle - wg sync.WaitGroup - statsUpdating sync2.AtomicInt32 + wg util.WaitGroupWrapper + statsUpdating atomicutil.Int32 cancel context.CancelFunc indexUsageSyncLease time.Duration - planReplayer *planReplayer + dumpFileGcChecker *dumpFileGcChecker + expiredTimeStamp4PC types.Time serverID uint64 serverIDSession *concurrency.Session - isLostConnectionToPD sync2.AtomicInt32 // !0: true, 0: false. - renewLeaseCh chan func() // It is used to call the renewLease function of the cache table. + isLostConnectionToPD atomicutil.Int32 // !0: true, 0: false. onClose func() sysExecutorFactory func(*Domain) (pools.Resource, error) + + sysProcesses SysProcesses } // loadInfoSchema loads infoschema at startTS. @@ -160,7 +164,7 @@ func (do *Domain) loadInfoSchema(startTS uint64) (infoschema.InfoSchema, bool, i return nil, false, currentSchemaVersion, nil, err } - newISBuilder, err := infoschema.NewBuilder(do.Store(), do.renewLeaseCh, do.sysFacHack).InitWithDBInfos(schemas, bundles, policies, neededSchemaVersion) + newISBuilder, err := infoschema.NewBuilder(do.Store(), do.sysFacHack).InitWithDBInfos(schemas, bundles, policies, neededSchemaVersion) if err != nil { return nil, false, currentSchemaVersion, nil, err } @@ -282,7 +286,7 @@ func (do *Domain) tryLoadSchemaDiffs(m *meta.Meta, usedVersion, newVersion int64 } diffs = append(diffs, diff) } - builder := infoschema.NewBuilder(do.Store(), do.renewLeaseCh, do.sysFacHack).InitWithOldInfoSchema(do.infoCache.GetLatest()) + builder := infoschema.NewBuilder(do.Store(), do.sysFacHack).InitWithOldInfoSchema(do.infoCache.GetLatest()) phyTblIDs := make([]int64, 0, len(diffs)) actions := make([]uint64, 0, len(diffs)) for _, diff := range diffs { @@ -335,6 +339,22 @@ func (do *Domain) GetSnapshotMeta(startTS uint64) (*meta.Meta, error) { return meta.NewSnapshotMeta(snapshot), nil } +// ExpiredTimeStamp4PC gets expiredTimeStamp4PC from domain. +func (do *Domain) ExpiredTimeStamp4PC() types.Time { + do.m.Lock() + defer do.m.Unlock() + + return do.expiredTimeStamp4PC +} + +// SetExpiredTimeStamp4PC sets the expiredTimeStamp4PC from domain. +func (do *Domain) SetExpiredTimeStamp4PC(time types.Time) { + do.m.Lock() + defer do.m.Unlock() + + do.expiredTimeStamp4PC = time +} + // DDL gets DDL from domain. func (do *Domain) DDL() ddl.DDL { return do.ddl @@ -345,12 +365,9 @@ func (do *Domain) InfoSyncer() *infosync.InfoSyncer { return do.info } -// NotifyGlobalConfigChange notify global config syncer to store the global config into PD(etcd). +// NotifyGlobalConfigChange notify global config syncer to store the global config into PD. func (do *Domain) NotifyGlobalConfigChange(name, value string) { - if do.globalCfgSyncer == nil { - return - } - do.globalCfgSyncer.Notify(name, value) + do.globalCfgSyncer.Notify(pd.GlobalConfigItem{Name: name, Value: value}) } // GetGlobalConfigSyncer exports for testing. @@ -686,7 +703,9 @@ func (do *Domain) Close() { } do.slowQuery.Close() - do.cancel() + if do.cancel != nil { + do.cancel() + } do.wg.Wait() do.sysSessionPool.Close() variable.UnregisterStatistics(do.bindHandle) @@ -699,7 +718,7 @@ func (do *Domain) Close() { const resourceIdleTimeout = 3 * time.Minute // resources in the ResourcePool will be recycled after idleTimeout // NewDomain creates a new domain. Should not create multiple domains for the same store. -func NewDomain(store kv.Storage, ddlLease time.Duration, statsLease time.Duration, idxUsageSyncLease time.Duration, planReplayerGCLease time.Duration, factory pools.Factory, onClose func()) *Domain { +func NewDomain(store kv.Storage, ddlLease time.Duration, statsLease time.Duration, idxUsageSyncLease time.Duration, dumpFileGcLease time.Duration, factory pools.Factory, onClose func()) *Domain { capacity := 200 // capacity of the sysSessionPool size do := &Domain{ store: store, @@ -709,13 +728,14 @@ func NewDomain(store kv.Storage, ddlLease time.Duration, statsLease time.Duratio infoCache: infoschema.NewCache(16), slowQuery: newTopNSlowQueries(30, time.Hour*24*7, 500), indexUsageSyncLease: idxUsageSyncLease, - planReplayer: &planReplayer{planReplayerGCLease: planReplayerGCLease}, + dumpFileGcChecker: &dumpFileGcChecker{gcLease: dumpFileGcLease, paths: []string{GetPlanReplayerDirName(), GetOptimizerTraceDirName()}}, onClose: onClose, - renewLeaseCh: make(chan func(), 10), + expiredTimeStamp4PC: types.NewTime(types.ZeroCoreTime, mysql.TypeTimestamp, types.DefaultFsp), } do.SchemaValidator = NewSchemaValidator(ddlLease, do) do.expensiveQueryHandle = expensivequery.NewExpensiveQueryHandle(do.exit) + do.sysProcesses = SysProcesses{mu: &sync.RWMutex{}, procMap: make(map[uint64]sessionctx.Context)} return do } @@ -790,13 +810,38 @@ func (do *Domain) Init(ddlLease time.Duration, sysExecutorFactory func(*Domain) do.ddl = d } }) + + if config.GetGlobalConfig().Experimental.EnableGlobalKill { + if do.etcdClient != nil { + err := do.acquireServerID(ctx) + if err != nil { + logutil.BgLogger().Error("acquire serverID failed", zap.Error(err)) + do.isLostConnectionToPD.Store(1) // will retry in `do.serverIDKeeper` + } else { + do.isLostConnectionToPD.Store(0) + } + + do.wg.Add(1) + go do.serverIDKeeper() + } else { + // set serverID for standalone deployment to enable 'KILL'. + atomic.StoreUint64(&do.serverID, serverIDForStandalone) + } + } + // step 1: prepare the info/schema syncer which domain reload needed. skipRegisterToDashboard := config.GetGlobalConfig().SkipRegisterToDashboard do.info, err = infosync.GlobalInfoSyncerInit(ctx, do.ddl.GetID(), do.ServerID, do.etcdClient, skipRegisterToDashboard) if err != nil { return err } - do.globalCfgSyncer = globalconfigsync.NewGlobalConfigSyncer(do.etcdClient) + + var pdClient pd.Client + if store, ok := do.store.(kv.StorageWithPD); ok { + pdClient = store.GetPDClient() + } + do.globalCfgSyncer = globalconfigsync.NewGlobalConfigSyncer(pdClient) + err = do.ddl.SchemaSyncer().Init(ctx) if err != nil { return err @@ -812,24 +857,6 @@ func (do *Domain) Init(ddlLease time.Duration, sysExecutorFactory func(*Domain) return err } - if config.GetGlobalConfig().Experimental.EnableGlobalKill { - if do.etcdClient != nil { - err := do.acquireServerID(ctx) - if err != nil { - logutil.BgLogger().Error("acquire serverID failed", zap.Error(err)) - do.isLostConnectionToPD.Set(1) // will retry in `do.serverIDKeeper` - } else { - do.isLostConnectionToPD.Set(0) - } - - do.wg.Add(1) - go do.serverIDKeeper() - } else { - // set serverID for standalone deployment to enable 'KILL'. - atomic.StoreUint64(&do.serverID, serverIDForStandalone) - } - } - // Only when the store is local that the lease value is 0. // If the store is local, it doesn't need loadSchemaInLoop. if ddlLease > 0 { @@ -837,10 +864,9 @@ func (do *Domain) Init(ddlLease time.Duration, sysExecutorFactory func(*Domain) // Local store needs to get the change information for every DDL state in each session. go do.loadSchemaInLoop(ctx, ddlLease) } - do.wg.Add(4) + do.wg.Add(3) go do.topNSlowQueryLoop() go do.infoSyncerKeeper() - go do.renewLease() go do.globalConfigSyncerKeeper() if !skipRegisterToDashboard { do.wg.Add(1) @@ -859,9 +885,9 @@ type sessionPool struct { } } -func newSessionPool(cap int, factory pools.Factory) *sessionPool { +func newSessionPool(capacity int, factory pools.Factory) *sessionPool { return &sessionPool{ - resources: make(chan pools.Resource, cap), + resources: make(chan pools.Resource, capacity), factory: factory, } } @@ -913,6 +939,11 @@ func (do *Domain) SysSessionPool() *sessionPool { return do.sysSessionPool } +// SysProcTracker returns the system processes tracker. +func (do *Domain) SysProcTracker() sessionctx.SysProcTracker { + return &do.sysProcesses +} + // GetEtcdClient returns the etcd client. func (do *Domain) GetEtcdClient() *clientv3.Client { return do.etcdClient @@ -1090,7 +1121,9 @@ func (do *Domain) globalBindHandleWorkerLoop(owner owner.Manager) { logutil.BgLogger().Error("update bindinfo failed", zap.Error(err)) } do.bindHandle.DropInvalidBindRecord() - if variable.TiDBOptOn(variable.CapturePlanBaseline.GetVal()) { + // Get Global + optVal, err := do.GetGlobalVar(variable.TiDBCapturePlanBaseline) + if err == nil && variable.TiDBOptOn(optVal) { do.bindHandle.CaptureBaselines() } do.bindHandle.SaveEvolveTasksToStore() @@ -1189,23 +1222,23 @@ func (do *Domain) TelemetryRotateSubWindowLoop(ctx sessionctx.Context) { }() } -// PlanReplayerLoop creates a goroutine that handles `exit` and `gc`. -func (do *Domain) PlanReplayerLoop() { +// DumpFileGcCheckerLoop creates a goroutine that handles `exit` and `gc`. +func (do *Domain) DumpFileGcCheckerLoop() { do.wg.Add(1) go func() { - gcTicker := time.NewTicker(do.planReplayer.planReplayerGCLease) + gcTicker := time.NewTicker(do.dumpFileGcChecker.gcLease) defer func() { gcTicker.Stop() do.wg.Done() - logutil.BgLogger().Info("PlanReplayerLoop exited.") - util.Recover(metrics.LabelDomain, "PlanReplayerLoop", nil, false) + logutil.BgLogger().Info("dumpFileGcChecker exited.") + util.Recover(metrics.LabelDomain, "dumpFileGcCheckerLoop", nil, false) }() for { select { case <-do.exit: return case <-gcTicker.C: - do.planReplayer.planReplayerGC(time.Hour) + do.dumpFileGcChecker.gcDumpFiles(time.Hour) } } }() @@ -1218,7 +1251,7 @@ func (do *Domain) StatsHandle() *handle.Handle { // CreateStatsHandle is used only for test. func (do *Domain) CreateStatsHandle(ctx sessionctx.Context) error { - h, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool) + h, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses) if err != nil { return err } @@ -1228,27 +1261,36 @@ func (do *Domain) CreateStatsHandle(ctx sessionctx.Context) error { // StatsUpdating checks if the stats worker is updating. func (do *Domain) StatsUpdating() bool { - return do.statsUpdating.Get() > 0 + return do.statsUpdating.Load() > 0 } // SetStatsUpdating sets the value of stats updating. func (do *Domain) SetStatsUpdating(val bool) { if val { - do.statsUpdating.Set(1) + do.statsUpdating.Store(1) } else { - do.statsUpdating.Set(0) + do.statsUpdating.Store(0) } } // RunAutoAnalyze indicates if this TiDB server starts auto analyze worker and can run auto analyze job. var RunAutoAnalyze = true +// LoadAndUpdateStatsLoop loads and updates stats info. +func (do *Domain) LoadAndUpdateStatsLoop(ctxs []sessionctx.Context) error { + if err := do.UpdateTableStatsLoop(ctxs[0]); err != nil { + return err + } + do.StartLoadStatsSubWorkers(ctxs[1:]) + return nil +} + // UpdateTableStatsLoop creates a goroutine loads stats info and updates stats info in a loop. // It will also start a goroutine to analyze tables automatically. // It should be called only once in BootstrapSession. func (do *Domain) UpdateTableStatsLoop(ctx sessionctx.Context) error { ctx.GetSessionVars().InRestrictedSQL = true - statsHandle, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool) + statsHandle, err := handle.NewHandle(ctx, do.statsLease, do.sysSessionPool, &do.sysProcesses) if err != nil { return err } @@ -1256,8 +1298,7 @@ func (do *Domain) UpdateTableStatsLoop(ctx sessionctx.Context) error { do.ddl.RegisterStatsHandle(statsHandle) // Negative stats lease indicates that it is in test, it does not need update. if do.statsLease >= 0 { - do.wg.Add(1) - go do.loadStatsWorker() + do.wg.Run(do.loadStatsWorker) } owner := do.newOwnerManager(handle.StatsPrompt, handle.StatsOwnerKey) if do.indexUsageSyncLease > 0 { @@ -1267,16 +1308,25 @@ func (do *Domain) UpdateTableStatsLoop(ctx sessionctx.Context) error { if do.statsLease <= 0 { return nil } - do.wg.Add(1) do.SetStatsUpdating(true) - go do.updateStatsWorker(ctx, owner) + do.wg.Run(func() { do.updateStatsWorker(ctx, owner) }) if RunAutoAnalyze { - do.wg.Add(1) - go do.autoAnalyzeWorker(owner) + do.wg.Run(func() { do.autoAnalyzeWorker(owner) }) } + do.wg.Run(func() { do.gcAnalyzeHistory(owner) }) return nil } +// StartLoadStatsSubWorkers starts sub workers with new sessions to load stats concurrently. +func (do *Domain) StartLoadStatsSubWorkers(ctxList []sessionctx.Context) { + statsHandle := do.StatsHandle() + for i, ctx := range ctxList { + statsHandle.StatsLoad.SubCtxs[i] = ctx + do.wg.Add(1) + go statsHandle.SubLoadWorker(ctx, do.exit, &do.wg) + } +} + func (do *Domain) newOwnerManager(prompt, ownerKey string) owner.Manager { id := do.ddl.OwnerManager().ID() var statsOwner owner.Manager @@ -1302,7 +1352,6 @@ func (do *Domain) loadStatsWorker() { loadTicker := time.NewTicker(lease) defer func() { loadTicker.Stop() - do.wg.Done() logutil.BgLogger().Info("loadStatsWorker exited.") }() statsHandle := do.StatsHandle() @@ -1371,14 +1420,15 @@ func (do *Domain) updateStatsWorker(ctx sessionctx.Context, owner owner.Manager) gcStatsTicker := time.NewTicker(100 * lease) dumpFeedbackTicker := time.NewTicker(200 * lease) loadFeedbackTicker := time.NewTicker(5 * lease) + dumpColStatsUsageTicker := time.NewTicker(100 * lease) statsHandle := do.StatsHandle() defer func() { + dumpColStatsUsageTicker.Stop() loadFeedbackTicker.Stop() dumpFeedbackTicker.Stop() gcStatsTicker.Stop() deltaUpdateTicker.Stop() do.SetStatsUpdating(false) - do.wg.Done() logutil.BgLogger().Info("updateStatsWorker exited.") }() for { @@ -1421,6 +1471,11 @@ func (do *Domain) updateStatsWorker(ctx sessionctx.Context, owner owner.Manager) if err != nil { logutil.BgLogger().Debug("GC stats failed", zap.Error(err)) } + case <-dumpColStatsUsageTicker.C: + err := statsHandle.DumpColStatsUsageToKV() + if err != nil { + logutil.BgLogger().Debug("dump column stats usage failed", zap.Error(err)) + } } } } @@ -1431,7 +1486,6 @@ func (do *Domain) autoAnalyzeWorker(owner owner.Manager) { analyzeTicker := time.NewTicker(do.statsLease) defer func() { analyzeTicker.Stop() - do.wg.Done() logutil.BgLogger().Info("autoAnalyzeWorker exited.") }() for { @@ -1446,6 +1500,32 @@ func (do *Domain) autoAnalyzeWorker(owner owner.Manager) { } } +func (do *Domain) gcAnalyzeHistory(owner owner.Manager) { + defer util.Recover(metrics.LabelDomain, "gcAnalyzeHistory", nil, false) + const gcInterval = time.Hour + statsHandle := do.StatsHandle() + gcTicker := time.NewTicker(gcInterval) + defer func() { + gcTicker.Stop() + logutil.BgLogger().Info("gcAnalyzeHistory exited.") + }() + for { + select { + case <-gcTicker.C: + if owner.IsOwner() { + const DaysToKeep = 7 + updateTime := time.Now().AddDate(0, 0, -DaysToKeep) + err := statsHandle.DeleteAnalyzeJobs(updateTime) + if err != nil { + logutil.BgLogger().Warn("gc analyze history failed", zap.Error(err)) + } + } + case <-do.exit: + return + } + } +} + // ExpensiveQueryHandle returns the expensive query handle. func (do *Domain) ExpensiveQueryHandle() *expensivequery.Handle { return do.expensiveQueryHandle @@ -1511,7 +1591,7 @@ func (do *Domain) ServerID() uint64 { // IsLostConnectionToPD indicates lost connection to PD or not. func (do *Domain) IsLostConnectionToPD() bool { - return do.isLostConnectionToPD.Get() != 0 + return do.isLostConnectionToPD.Load() != 0 } const ( @@ -1613,7 +1693,8 @@ func (do *Domain) acquireServerID(ctx context.Context) error { } for { - randServerID := rand.Int63n(int64(util.MaxServerID)) + 1 // get a random serverID: [1, MaxServerID] #nosec G404 + // get a random serverID: [1, MaxServerID] + randServerID := rand.Int63n(int64(util.MaxServerID)) + 1 // #nosec G404 key := fmt.Sprintf("%s/%v", serverIDEtcdPath, randServerID) cmp := clientv3.Compare(clientv3.CreateRevision(key), "=", 0) value := "0" @@ -1688,7 +1769,7 @@ func (do *Domain) serverIDKeeper() { onConnectionToPDRestored := func() { logutil.BgLogger().Info("restored connection to PD") - do.isLostConnectionToPD.Set(0) + do.isLostConnectionToPD.Store(0) lastSucceedTimestamp = time.Now() if err := do.info.StoreServerInfo(context.Background()); err != nil { @@ -1698,7 +1779,7 @@ func (do *Domain) serverIDKeeper() { onConnectionToPDLost := func() { logutil.BgLogger().Warn("lost connection to PD") - do.isLostConnectionToPD.Set(1) + do.isLostConnectionToPD.Store(1) // Kill all connections when lost connection to PD, // to avoid the possibility that another TiDB instance acquires the same serverID and generates a same connection ID, @@ -1742,24 +1823,11 @@ func (do *Domain) MockInfoCacheAndLoadInfoSchema(is infoschema.InfoSchema) { do.infoCache.Insert(is, 0) } -func (do *Domain) renewLease() { - defer func() { - do.wg.Done() - logutil.BgLogger().Info("renew lease goroutine exited.") - }() - for { - select { - case <-do.exit: - close(do.renewLeaseCh) - return - case op := <-do.renewLeaseCh: - op() - } - } -} - func init() { initByLDFlagsForGlobalKill() + telemetry.GetDomainInfoSchema = func(ctx sessionctx.Context) infoschema.InfoSchema { + return GetDomain(ctx).InfoSchema() + } } var ( @@ -1769,3 +1837,56 @@ var ( ErrInfoSchemaChanged = dbterror.ClassDomain.NewStdErr(errno.ErrInfoSchemaChanged, mysql.Message(errno.MySQLErrName[errno.ErrInfoSchemaChanged].Raw+". "+kv.TxnRetryableMark, nil)) ) + +// SysProcesses holds the sys processes infos +type SysProcesses struct { + mu *sync.RWMutex + procMap map[uint64]sessionctx.Context +} + +// Track tracks the sys process into procMap +func (s *SysProcesses) Track(id uint64, proc sessionctx.Context) error { + s.mu.Lock() + defer s.mu.Unlock() + if oldProc, ok := s.procMap[id]; ok && oldProc != proc { + return errors.Errorf("The ID is in use: %v", id) + } + s.procMap[id] = proc + proc.GetSessionVars().ConnectionID = id + atomic.StoreUint32(&proc.GetSessionVars().Killed, 0) + return nil +} + +// UnTrack removes the sys process from procMap +func (s *SysProcesses) UnTrack(id uint64) { + s.mu.Lock() + defer s.mu.Unlock() + if proc, ok := s.procMap[id]; ok { + delete(s.procMap, id) + proc.GetSessionVars().ConnectionID = 0 + atomic.StoreUint32(&proc.GetSessionVars().Killed, 0) + } +} + +// GetSysProcessList gets list of system ProcessInfo +func (s *SysProcesses) GetSysProcessList() map[uint64]*util.ProcessInfo { + s.mu.RLock() + defer s.mu.RUnlock() + rs := make(map[uint64]*util.ProcessInfo) + for connID, proc := range s.procMap { + // if session is still tracked in this map, it's not returned to sysSessionPool yet + if pi := proc.ShowProcess(); pi != nil && pi.ID == connID { + rs[connID] = pi + } + } + return rs +} + +// KillSysProcess kills sys process with specified ID +func (s *SysProcesses) KillSysProcess(id uint64) { + s.mu.Lock() + defer s.mu.Unlock() + if proc, ok := s.procMap[id]; ok { + atomic.StoreUint32(&proc.GetSessionVars().Killed, 1) + } +} diff --git a/domain/domain_test.go b/domain/domain_test.go index a7915b62580ea..ff85c1074cc3c 100644 --- a/domain/domain_test.go +++ b/domain/domain_test.go @@ -34,6 +34,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/session/txninfo" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/util" @@ -42,15 +43,16 @@ import ( "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/tikv" - "go.etcd.io/etcd/integration" + "go.etcd.io/etcd/tests/v3/integration" ) -// SubTestInfo is batched in TestDomainSerial -func SubTestInfo(t *testing.T) { +func TestInfo(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) + if !unixSocketAvailable() { t.Skip("ETCD use ip:port as unix socket address, skip when it is unavailable.") } @@ -65,7 +67,7 @@ func SubTestInfo(t *testing.T) { mockStore := &mockEtcdBackend{ Storage: s, - pdAddrs: []string{cluster.Members[0].GRPCAddr()}} + pdAddrs: []string{cluster.Members[0].GRPCURL()}} ddlLease := 80 * time.Millisecond dom := NewDomain(mockStore, ddlLease, 0, 0, 0, mockFactory, nil) defer func() { @@ -85,6 +87,7 @@ func SubTestInfo(t *testing.T) { ddl.WithInfoCache(dom.infoCache), ddl.WithLease(ddlLease), ) + ddl.DisableTiFlashPoll(dom.ddl) require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/MockReplaceDDL", `return(true)`)) require.NoError(t, dom.Init(ddlLease, sysMockFactory)) require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/MockReplaceDDL")) @@ -132,7 +135,7 @@ func SubTestInfo(t *testing.T) { Col: "utf8_bin", } ctx := mock.NewContext() - require.NoError(t, dom.ddl.CreateSchema(ctx, model.NewCIStr("aaa"), cs, nil, nil)) + require.NoError(t, dom.ddl.CreateSchema(ctx, model.NewCIStr("aaa"), cs, nil)) require.NoError(t, dom.Reload()) require.Equal(t, int64(1), dom.InfoSchema().SchemaMetaVersion()) @@ -153,8 +156,7 @@ func SubTestInfo(t *testing.T) { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/infosync/FailPlacement")) } -// SubTestDomain is batched in TestDomainSerial -func SubTestDomain(t *testing.T) { +func TestDomain(t *testing.T) { store, err := mockstore.NewMockStore() require.NoError(t, err) @@ -166,6 +168,7 @@ func SubTestDomain(t *testing.T) { ctx := mock.NewContext() ctx.Store = dom.Store() dd := dom.DDL() + ddl.DisableTiFlashPoll(dd) require.NotNil(t, dd) require.Equal(t, 80*time.Millisecond, dd.GetLease()) @@ -174,10 +177,12 @@ func SubTestDomain(t *testing.T) { Chs: "utf8", Col: "utf8_bin", } - err = dd.CreateSchema(ctx, model.NewCIStr("aaa"), cs, nil, nil) + ctx.SetValue(sessionctx.QueryString, "skip") + err = dd.CreateSchema(ctx, model.NewCIStr("aaa"), cs, nil) require.NoError(t, err) // Test for fetchSchemasWithTables when "tables" isn't nil. + ctx.SetValue(sessionctx.QueryString, "skip") err = dd.CreateTable(ctx, &ast.CreateTableStmt{Table: &ast.TableName{ Schema: model.NewCIStr("aaa"), Name: model.NewCIStr("tbl")}}) @@ -231,7 +236,8 @@ func SubTestDomain(t *testing.T) { require.Equal(t, tblInfo2, tbl.Meta()) // Test for tryLoadSchemaDiffs when "isTooOldSchema" is false. - err = dd.CreateSchema(ctx, model.NewCIStr("bbb"), cs, nil, nil) + ctx.SetValue(sessionctx.QueryString, "skip") + err = dd.CreateSchema(ctx, model.NewCIStr("bbb"), cs, nil) require.NoError(t, err) err = dom.Reload() @@ -320,14 +326,14 @@ func SubTestDomain(t *testing.T) { // For schema check, it tests for getting the result of "ResultUnknown". schemaChecker := NewSchemaChecker(dom, is.SchemaMetaVersion(), nil) - originalRetryTime := SchemaOutOfDateRetryTimes - originalRetryInterval := SchemaOutOfDateRetryInterval + originalRetryTime := SchemaOutOfDateRetryTimes.Load() + originalRetryInterval := SchemaOutOfDateRetryInterval.Load() // Make sure it will retry one time and doesn't take a long time. - SchemaOutOfDateRetryTimes = 1 - SchemaOutOfDateRetryInterval = int64(time.Millisecond * 1) + SchemaOutOfDateRetryTimes.Store(1) + SchemaOutOfDateRetryInterval.Store(time.Millisecond * 1) defer func() { - SchemaOutOfDateRetryTimes = originalRetryTime - SchemaOutOfDateRetryInterval = originalRetryInterval + SchemaOutOfDateRetryTimes.Store(originalRetryTime) + SchemaOutOfDateRetryInterval.Store(originalRetryInterval) }() dom.SchemaValidator.Stop() _, err = schemaChecker.Check(uint64(123456)) @@ -438,3 +444,11 @@ func (msm *mockSessionManager) UpdateTLSConfig(*tls.Config) {} func (msm *mockSessionManager) ServerID() uint64 { return 1 } + +func (msm *mockSessionManager) StoreInternalSession(se interface{}) {} + +func (msm *mockSessionManager) DeleteInternalSession(se interface{}) {} + +func (msm *mockSessionManager) GetInternalSessionStartTSList() []uint64 { + return nil +} diff --git a/domain/globalconfigsync/globalconfig.go b/domain/globalconfigsync/globalconfig.go index f6c6c86d276d9..5bbb6a260e3c8 100644 --- a/domain/globalconfigsync/globalconfig.go +++ b/domain/globalconfigsync/globalconfig.go @@ -17,58 +17,39 @@ package globalconfigsync import ( "context" - "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" + pd "github.com/tikv/pd/client" "go.uber.org/zap" ) -const ( - globalConfigPath = "/global/config/" - keyOpDefaultRetryCnt = 5 -) - -// GlobalConfigSyncer stores global config into etcd. +// GlobalConfigSyncer is used to sync pd global config. type GlobalConfigSyncer struct { - etcdCli *clientv3.Client - NotifyCh chan ConfigEntry + pd pd.Client + NotifyCh chan pd.GlobalConfigItem } -// NewGlobalConfigSyncer returns a new GlobalConfigSyncer. -func NewGlobalConfigSyncer(etcdCli *clientv3.Client) *GlobalConfigSyncer { +// NewGlobalConfigSyncer creates a GlobalConfigSyncer. +func NewGlobalConfigSyncer(p pd.Client) *GlobalConfigSyncer { return &GlobalConfigSyncer{ - etcdCli: etcdCli, - NotifyCh: make(chan ConfigEntry, 8), + pd: p, + NotifyCh: make(chan pd.GlobalConfigItem, 8), } } -// ConfigEntry contain the global config Name and Value. -type ConfigEntry struct { - Name string - Value string -} - -// Notify sends the config entry into notify channel. -func (c *GlobalConfigSyncer) Notify(name, value string) { - c.NotifyCh <- ConfigEntry{Name: name, Value: value} -} - -// StoreGlobalConfig stores the global config into etcd. -func (c *GlobalConfigSyncer) StoreGlobalConfig(ctx context.Context, entry ConfigEntry) error { - if c.etcdCli == nil { +// StoreGlobalConfig is used to store global config. +func (s *GlobalConfigSyncer) StoreGlobalConfig(ctx context.Context, item pd.GlobalConfigItem) error { + if s.pd == nil { return nil } - - key := globalConfigPath + entry.Name - err := util.PutKVToEtcd(ctx, c.etcdCli, keyOpDefaultRetryCnt, key, entry.Value) + err := s.pd.StoreGlobalConfig(ctx, []pd.GlobalConfigItem{item}) if err != nil { return err } - logutil.BgLogger().Info("store global config", zap.String("Name", entry.Name), zap.String("Value", entry.Value)) + logutil.BgLogger().Info("store global config", zap.String("name", item.Name), zap.String("value", item.Value)) return nil } -// SetEtcdClient exports for testing. -func (c *GlobalConfigSyncer) SetEtcdClient(etcdCli *clientv3.Client) { - c.etcdCli = etcdCli +// Notify pushes global config to internal channel and will be sync into pd's GlobalConfig. +func (s *GlobalConfigSyncer) Notify(globalConfigItem pd.GlobalConfigItem) { + s.NotifyCh <- globalConfigItem } diff --git a/domain/globalconfigsync/globalconfig_test.go b/domain/globalconfigsync/globalconfig_test.go index c7be9137ddf68..7cc40acfd992e 100644 --- a/domain/globalconfigsync/globalconfig_test.go +++ b/domain/globalconfigsync/globalconfig_test.go @@ -21,37 +21,54 @@ import ( "time" "github.com/pingcap/tidb/domain/globalconfigsync" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/util/testbridge" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/integration" + pd "github.com/tikv/pd/client" + "go.etcd.io/etcd/tests/v3/integration" "go.uber.org/goleak" ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) } func TestGlobalConfigSyncer(t *testing.T) { - syncer := globalconfigsync.NewGlobalConfigSyncer(nil) - syncer.Notify("a", "b") - require.Equal(t, len(syncer.NotifyCh), 1) - entry := <-syncer.NotifyCh - require.Equal(t, entry.Name, "a") - err := syncer.StoreGlobalConfig(context.Background(), entry) + if runtime.GOOS == "windows" { + t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") + } + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + err := store.Close() + require.NoError(t, err) + }() + client := store.(kv.StorageWithPD).GetPDClient() + syncer := globalconfigsync.NewGlobalConfigSyncer(client) + syncer.Notify(pd.GlobalConfigItem{Name: "a", Value: "b"}) + err = syncer.StoreGlobalConfig(context.Background(), <-syncer.NotifyCh) + require.NoError(t, err) + items, err := client.LoadGlobalConfig(context.Background(), []string{"a"}) require.NoError(t, err) + require.Equal(t, len(items), 1) + require.Equal(t, items[0].Name, "/global/config/a") + require.Equal(t, items[0].Value, "b") } func TestStoreGlobalConfig(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) + store, err := mockstore.NewMockStore() require.NoError(t, err) defer func() { @@ -63,32 +80,25 @@ func TestStoreGlobalConfig(t *testing.T) { require.NoError(t, err) defer domain.Close() - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - defer cluster.Terminate(t) - domain.GetGlobalConfigSyncer().SetEtcdClient(cluster.RandClient()) - se, err := session.CreateSession4Test(store) require.NoError(t, err) _, err = se.Execute(context.Background(), "set @@global.tidb_enable_top_sql=1;") require.NoError(t, err) - for i := 0; i < 20; i++ { - resp, err := cluster.RandClient().Get(context.Background(), "/global/config/enable_resource_metering") + time.Sleep(100 * time.Millisecond) + client := + store.(kv.StorageWithPD).GetPDClient() + // enable top sql will be translated to enable_resource_metering + items, err := client.LoadGlobalConfig(context.Background(), []string{"enable_resource_metering"}) require.NoError(t, err) - require.NotNil(t, resp, nil) - - if len(resp.Kvs) == 0 { - // writing to ectd is async, so we should retry if not synced yet - time.Sleep(100 * time.Millisecond) + if len(items) == 1 && items[0].Value == "" { continue } - - require.Equal(t, len(resp.Kvs), 1) - require.Equal(t, resp.Kvs[0].Key, []byte("/global/config/enable_resource_metering")) - require.Equal(t, resp.Kvs[0].Value, []byte("true")) + require.Len(t, items, 1) + require.Equal(t, items[0].Name, "/global/config/enable_resource_metering") + require.Equal(t, items[0].Value, "true") return } - - require.Fail(t, "timeout for waiting etcd synced") + require.Fail(t, "timeout for waiting global config synced") } diff --git a/domain/infosync/info.go b/domain/infosync/info.go index fc58783ff3108..d7c6a15ec4cc5 100644 --- a/domain/infosync/info.go +++ b/domain/infosync/info.go @@ -16,7 +16,6 @@ package infosync import ( "context" - "encoding/hex" "encoding/json" "fmt" "io" @@ -38,9 +37,12 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/owner" + "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/binloginfo" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/types" util2 "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/dbterror" @@ -49,9 +51,8 @@ import ( "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/versioninfo" "github.com/tikv/client-go/v2/oracle" - "github.com/tikv/client-go/v2/tikv" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/clientv3/concurrency" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3/concurrency" "go.uber.org/zap" ) @@ -91,18 +92,19 @@ var ErrPrometheusAddrIsNotSet = dbterror.ClassDomain.NewStd(errno.ErrPrometheusA // InfoSyncer stores server info to etcd when the tidb-server starts and delete when tidb-server shuts down. type InfoSyncer struct { - etcdCli *clientv3.Client - info *ServerInfo - serverInfoPath string - minStartTS uint64 - minStartTSPath string - manager util2.SessionManager - session *concurrency.Session - topologySession *concurrency.Session - prometheusAddr string - modifyTime time.Time - labelRuleManager LabelRuleManager - placementManager PlacementManager + etcdCli *clientv3.Client + info *ServerInfo + serverInfoPath string + minStartTS uint64 + minStartTSPath string + manager util2.SessionManager + session *concurrency.Session + topologySession *concurrency.Session + prometheusAddr string + modifyTime time.Time + labelRuleManager LabelRuleManager + placementManager PlacementManager + tiflashPlacementManager TiFlashPlacementManager } // ServerInfo is server static information. @@ -184,9 +186,11 @@ func GlobalInfoSyncerInit(ctx context.Context, id string, serverIDGetter func() if etcdCli != nil { is.labelRuleManager = initLabelRuleManager(etcdCli.Endpoints()) is.placementManager = initPlacementManager(etcdCli.Endpoints()) + is.tiflashPlacementManager = initTiFlashPlacementManager(etcdCli.Endpoints()) } else { is.labelRuleManager = initLabelRuleManager([]string{}) is.placementManager = initPlacementManager([]string{}) + is.tiflashPlacementManager = initTiFlashPlacementManager([]string{}) } setGlobalInfoSyncer(is) return is, nil @@ -228,6 +232,42 @@ func initPlacementManager(addrs []string) PlacementManager { return &PDPlacementManager{addrs: addrs} } +func initTiFlashPlacementManager(addrs []string) TiFlashPlacementManager { + if len(addrs) == 0 { + m := mockTiFlashPlacementManager{} + return &m + } + logutil.BgLogger().Warn("init TiFlashPlacementManager", zap.Strings("pd addrs", addrs)) + return &TiFlashPDPlacementManager{addrs: addrs} +} + +// GetMockTiFlash can only be used in tests to get MockTiFlash +func GetMockTiFlash() *MockTiFlash { + is, err := getGlobalInfoSyncer() + if err != nil { + return nil + } + + m, ok := is.tiflashPlacementManager.(*mockTiFlashPlacementManager) + if ok { + return m.tiflash + } + return nil +} + +// SetMockTiFlash can only be used in tests to set MockTiFlash +func SetMockTiFlash(tiflash *MockTiFlash) { + is, err := getGlobalInfoSyncer() + if err != nil { + return + } + + m, ok := is.tiflashPlacementManager.(*mockTiFlashPlacementManager) + if ok { + m.tiflash = tiflash + } +} + // GetServerInfo gets self server static information. func GetServerInfo() (*ServerInfo, error) { is, err := getGlobalInfoSyncer() @@ -385,30 +425,6 @@ func doRequestWithFailpoint(req *http.Request) (resp *http.Response, err error) return util2.InternalHTTPClient().Do(req) } -// GetReplicationState is used to check if regions in the given keyranges are replicated from PD. -func GetReplicationState(ctx context.Context, startKey []byte, endKey []byte) (bool, error) { - is, err := getGlobalInfoSyncer() - if err != nil { - return false, err - } - - if is.etcdCli == nil { - return false, nil - } - - addrs := is.etcdCli.Endpoints() - - if len(addrs) == 0 { - return false, errors.Errorf("pd unavailable") - } - - res, err := doRequest(ctx, addrs, fmt.Sprintf("%s/replicated?startKey=%s&endKey=%s", pdapi.Regions, hex.EncodeToString(startKey), hex.EncodeToString(endKey)), "GET", nil) - if err == nil && res != nil { - return string(res) == "true\n", nil - } - return false, err -} - // GetAllRuleBundles is used to get all rule bundles from PD. It is used to load full rules from PD while fullload infoschema. func GetAllRuleBundles(ctx context.Context) ([]*placement.Bundle, error) { is, err := getGlobalInfoSyncer() @@ -596,6 +612,7 @@ func (is *InfoSyncer) ReportMinStartTS(store kv.Storage) { return } pl := is.manager.ShowProcessList() + innerSessionStartTSList := is.manager.GetInternalSessionStartTSList() // Calculate the lower limit of the start timestamp to avoid extremely old transaction delaying GC. currentVer, err := store.CurrentVersion(kv.GlobalTxnScope) @@ -604,7 +621,8 @@ func (is *InfoSyncer) ReportMinStartTS(store kv.Storage) { return } now := oracle.GetTimeFromTS(currentVer.Ver) - startTSLowerLimit := oracle.GoTimeToLowerLimitStartTS(now, tikv.MaxTxnTimeUse) + // GCMaxWaitTime is in seconds, GCMaxWaitTime * 1000 converts it to milliseconds. + startTSLowerLimit := oracle.GoTimeToLowerLimitStartTS(now, variable.GCMaxWaitTime.Load()*1000) minStartTS := oracle.GoTimeToTS(now) for _, info := range pl { @@ -613,7 +631,15 @@ func (is *InfoSyncer) ReportMinStartTS(store kv.Storage) { } } - is.minStartTS = minStartTS + for _, innerTS := range innerSessionStartTSList { + kv.PrintLongTimeInternalTxn(now, innerTS, false) + if innerTS > startTSLowerLimit && innerTS < minStartTS { + minStartTS = innerTS + } + } + + is.minStartTS = kv.GetMinInnerTxnStartTS(now, startTSLowerLimit, minStartTS) + err = is.storeMinStartTS(context.Background()) if err != nil { logutil.BgLogger().Error("update minStartTS failed", zap.Error(err)) @@ -856,7 +882,7 @@ func getServerInfo(id string, serverIDGetter func() uint64) *ServerInfo { failpoint.Inject("mockServerInfo", func(val failpoint.Value) { if val.(bool) { - info.StartTimestamp = 1282967700000 + info.StartTimestamp = 1282967700 info.Labels = map[string]string{ "foo": "bar", } @@ -925,3 +951,135 @@ func GetLabelRules(ctx context.Context, ruleIDs []string) (map[string]*label.Rul } return is.labelRuleManager.GetLabelRules(ctx, ruleIDs) } + +// SetTiFlashPlacementRule is a helper function to set placement rule. +// It is discouraged to use SetTiFlashPlacementRule directly, +// use `ConfigureTiFlashPDForTable`/`ConfigureTiFlashPDForPartitions` instead. +func SetTiFlashPlacementRule(ctx context.Context, rule placement.TiFlashRule) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + logutil.BgLogger().Info("SetTiFlashPlacementRule", zap.String("ruleID", rule.ID)) + return is.tiflashPlacementManager.SetPlacementRule(ctx, rule) +} + +// DeleteTiFlashPlacementRule is to delete placement rule for certain group. +func DeleteTiFlashPlacementRule(ctx context.Context, group string, ruleID string) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + logutil.BgLogger().Info("DeleteTiFlashPlacementRule", zap.String("ruleID", ruleID)) + return is.tiflashPlacementManager.DeletePlacementRule(ctx, group, ruleID) +} + +// GetTiFlashGroupRules to get all placement rule in a certain group. +func GetTiFlashGroupRules(ctx context.Context, group string) ([]placement.TiFlashRule, error) { + is, err := getGlobalInfoSyncer() + if err != nil { + return nil, errors.Trace(err) + } + return is.tiflashPlacementManager.GetGroupRules(ctx, group) +} + +// PostTiFlashAccelerateSchedule sends `regions/accelerate-schedule` request. +func PostTiFlashAccelerateSchedule(ctx context.Context, tableID int64) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + logutil.BgLogger().Info("PostTiFlashAccelerateSchedule", zap.Int64("tableID", tableID)) + return is.tiflashPlacementManager.PostAccelerateSchedule(ctx, tableID) +} + +// GetTiFlashPDRegionRecordStats is a helper function calling `/stats/region`. +func GetTiFlashPDRegionRecordStats(ctx context.Context, tableID int64, stats *helper.PDRegionStats) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + return is.tiflashPlacementManager.GetPDRegionRecordStats(ctx, tableID, stats) +} + +// GetTiFlashStoresStat gets the TiKV store information by accessing PD's api. +func GetTiFlashStoresStat(ctx context.Context) (*helper.StoresStat, error) { + is, err := getGlobalInfoSyncer() + if err != nil { + return nil, errors.Trace(err) + } + return is.tiflashPlacementManager.GetStoresStat(ctx) +} + +// CloseTiFlashManager closes TiFlash manager. +func CloseTiFlashManager(ctx context.Context) { + is, err := getGlobalInfoSyncer() + if err != nil { + return + } + is.tiflashPlacementManager.Close(ctx) +} + +// ConfigureTiFlashPDForTable configures pd rule for unpartitioned tables. +func ConfigureTiFlashPDForTable(id int64, count uint64, locationLabels *[]string) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + ctx := context.Background() + logutil.BgLogger().Info("ConfigureTiFlashPDForTable", zap.Int64("tableID", id), zap.Uint64("count", count)) + ruleNew := MakeNewRule(id, count, *locationLabels) + if e := is.tiflashPlacementManager.SetPlacementRule(ctx, *ruleNew); e != nil { + return errors.Trace(e) + } + return nil +} + +// ConfigureTiFlashPDForPartitions configures pd rule for all partition in partitioned tables. +func ConfigureTiFlashPDForPartitions(accel bool, definitions *[]model.PartitionDefinition, count uint64, locationLabels *[]string, tableID int64) error { + is, err := getGlobalInfoSyncer() + if err != nil { + return errors.Trace(err) + } + ctx := context.Background() + for _, p := range *definitions { + logutil.BgLogger().Info("ConfigureTiFlashPDForPartitions", zap.Int64("tableID", tableID), zap.Int64("partID", p.ID), zap.Bool("accel", accel), zap.Uint64("count", count)) + ruleNew := MakeNewRule(p.ID, count, *locationLabels) + if e := is.tiflashPlacementManager.SetPlacementRule(ctx, *ruleNew); e != nil { + return errors.Trace(e) + } + if accel { + e := is.tiflashPlacementManager.PostAccelerateSchedule(ctx, p.ID) + if e != nil { + return errors.Trace(e) + } + } + } + return nil +} + +// StoreInternalSession is the entry function for store an internal session to SessionManager. +func StoreInternalSession(se interface{}) { + is, err := getGlobalInfoSyncer() + if err != nil { + return + } + sm := is.GetSessionManager() + if sm == nil { + return + } + sm.StoreInternalSession(se) +} + +// DeleteInternalSession is the entry function for delete an internal session from SessionManager. +func DeleteInternalSession(se interface{}) { + is, err := getGlobalInfoSyncer() + if err != nil { + return + } + sm := is.GetSessionManager() + if sm == nil { + return + } + sm.DeleteInternalSession(se) +} diff --git a/domain/infosync/info_test.go b/domain/infosync/info_test.go index 001a106632230..5042e897c1fd6 100644 --- a/domain/infosync/info_test.go +++ b/domain/infosync/info_test.go @@ -32,14 +32,15 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/util/testbridge" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/integration" + "go.etcd.io/etcd/tests/v3/integration" "go.uber.org/goleak" ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), } goleak.VerifyTestMain(m, opts...) } @@ -48,6 +49,7 @@ func TestTopology(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -72,7 +74,7 @@ func TestTopology(t *testing.T) { topology, err := info.getTopologyFromEtcd(ctx) require.NoError(t, err) - require.Equal(t, int64(1282967700000), topology.StartTimestamp) + require.Equal(t, int64(1282967700), topology.StartTimestamp) v, ok := topology.Labels["foo"] require.True(t, ok) @@ -97,7 +99,7 @@ func TestTopology(t *testing.T) { dir := path.Dir(s) require.Equal(t, dir, topology.DeployPath) - require.Equal(t, int64(1282967700000), topology.StartTimestamp) + require.Equal(t, int64(1282967700), topology.StartTimestamp) require.Equal(t, info.getTopologyInfo(), *topology) // check ttl key @@ -210,3 +212,65 @@ func TestPutBundlesRetry(t *testing.T) { require.True(t, got.IsEmpty()) }) } + +func TestTiFlashManager(t *testing.T) { + ctx := context.Background() + _, err := GlobalInfoSyncerInit(ctx, "test", func() uint64 { return 1 }, nil, false) + tiflash := NewMockTiFlash() + SetMockTiFlash(tiflash) + + require.NoError(t, err) + + // SetTiFlashPlacementRule/GetTiFlashGroupRules + rule := MakeNewRule(1, 2, []string{"a"}) + require.NoError(t, SetTiFlashPlacementRule(ctx, *rule)) + rules, err := GetTiFlashGroupRules(ctx, "tiflash") + require.NoError(t, err) + require.Equal(t, 1, len(rules)) + require.Equal(t, "table-1-r", rules[0].ID) + require.Equal(t, 2, rules[0].Count) + require.Equal(t, []string{"a"}, rules[0].LocationLabels) + require.Equal(t, false, rules[0].Override, false) + require.Equal(t, placement.RuleIndexTiFlash, rules[0].Index) + + // PostTiFlashAccelerateSchedule + require.Nil(t, PostTiFlashAccelerateSchedule(ctx, 1)) + z, ok := tiflash.SyncStatus[1] + require.Equal(t, true, ok) + require.Equal(t, true, z.Accel) + + // GetTiFlashStoresStat + stats, err := GetTiFlashStoresStat(ctx) + require.NoError(t, err) + require.Equal(t, 1, stats.Count) + + // DeleteTiFlashPlacementRule + require.NoError(t, DeleteTiFlashPlacementRule(ctx, "tiflash", rule.ID)) + rules, err = GetTiFlashGroupRules(ctx, "tiflash") + require.NoError(t, err) + require.Equal(t, 0, len(rules)) + + // ConfigureTiFlashPDForTable + require.Nil(t, ConfigureTiFlashPDForTable(1, 2, &[]string{"a"})) + rules, err = GetTiFlashGroupRules(ctx, "tiflash") + require.NoError(t, err) + require.Equal(t, 1, len(rules)) + + // ConfigureTiFlashPDForPartitions + ConfigureTiFlashPDForPartitions(true, &[]model.PartitionDefinition{ + { + ID: 2, + Name: model.NewCIStr("p"), + LessThan: []string{}, + }, + }, 3, &[]string{}, 100) + rules, err = GetTiFlashGroupRules(ctx, "tiflash") + require.NoError(t, err) + // Have table 1 and 2 + require.Equal(t, 2, len(rules)) + z, ok = tiflash.SyncStatus[2] + require.Equal(t, true, ok) + require.Equal(t, true, z.Accel) + + CloseTiFlashManager(ctx) +} diff --git a/domain/infosync/region.go b/domain/infosync/region.go new file mode 100644 index 0000000000000..8f72d289b57da --- /dev/null +++ b/domain/infosync/region.go @@ -0,0 +1,86 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package infosync + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/util/pdapi" +) + +// PlacementScheduleState is the returned third-valued state from GetReplicationState(). For convenience, the string of PD is deserialized into an enum first. +type PlacementScheduleState int + +const ( + // PlacementScheduleStatePending corresponds to "PENDING" from PD. + PlacementScheduleStatePending PlacementScheduleState = iota + // PlacementScheduleStateInProgress corresponds to "INPROGRESS" from PD. + PlacementScheduleStateInProgress + // PlacementScheduleStateScheduled corresponds to "REPLICATED" from PD. + PlacementScheduleStateScheduled +) + +func (t PlacementScheduleState) String() string { + switch t { + case PlacementScheduleStateScheduled: + return "SCHEDULED" + case PlacementScheduleStateInProgress: + return "INPROGRESS" + case PlacementScheduleStatePending: + return "PENDING" + default: + return "PENDING" + } +} + +// GetReplicationState is used to check if regions in the given keyranges are replicated from PD. +func GetReplicationState(ctx context.Context, startKey []byte, endKey []byte) (PlacementScheduleState, error) { + is, err := getGlobalInfoSyncer() + if err != nil { + return PlacementScheduleStatePending, err + } + + if is.etcdCli == nil { + return PlacementScheduleStatePending, nil + } + + addrs := is.etcdCli.Endpoints() + + if len(addrs) == 0 { + return PlacementScheduleStatePending, errors.Errorf("pd unavailable") + } + + res, err := doRequest(ctx, addrs, fmt.Sprintf("%s/replicated?startKey=%s&endKey=%s", pdapi.Regions, hex.EncodeToString(startKey), hex.EncodeToString(endKey)), "GET", nil) + if err == nil && res != nil { + st := PlacementScheduleStatePending + // it should not fail + var state string + _ = json.Unmarshal(res, &state) + switch state { + case "REPLICATED": + st = PlacementScheduleStateScheduled + case "INPROGRESS": + st = PlacementScheduleStateInProgress + case "PENDING": + st = PlacementScheduleStatePending + } + return st, nil + } + return PlacementScheduleStatePending, err +} diff --git a/domain/infosync/tiflash_manager.go b/domain/infosync/tiflash_manager.go new file mode 100644 index 0000000000000..4f655c3206df6 --- /dev/null +++ b/domain/infosync/tiflash_manager.go @@ -0,0 +1,611 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package infosync + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "path" + "strconv" + "strings" + "sync" + "time" + + "github.com/gorilla/mux" + "github.com/pingcap/errors" + "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/pdapi" + "go.uber.org/zap" +) + +// TiFlashPlacementManager manages placement settings for TiFlash. +type TiFlashPlacementManager interface { + // SetPlacementRule is a helper function to set placement rule. + SetPlacementRule(ctx context.Context, rule placement.TiFlashRule) error + // DeletePlacementRule is to delete placement rule for certain group. + DeletePlacementRule(ctx context.Context, group string, ruleID string) error + // GetGroupRules to get all placement rule in a certain group. + GetGroupRules(ctx context.Context, group string) ([]placement.TiFlashRule, error) + // PostAccelerateSchedule sends `regions/accelerate-schedule` request. + PostAccelerateSchedule(ctx context.Context, tableID int64) error + // GetPDRegionRecordStats is a helper function calling `/stats/region`. + GetPDRegionRecordStats(ctx context.Context, tableID int64, stats *helper.PDRegionStats) error + // GetStoresStat gets the TiKV store information by accessing PD's api. + GetStoresStat(ctx context.Context) (*helper.StoresStat, error) + // Close is to close TiFlashPlacementManager + Close(ctx context.Context) +} + +// TiFlashPDPlacementManager manages placement with pd for TiFlash. +type TiFlashPDPlacementManager struct { + addrs []string +} + +// Close is called to close TiFlashPDPlacementManager. +func (m *TiFlashPDPlacementManager) Close(ctx context.Context) { + +} + +// SetPlacementRule is a helper function to set placement rule. +func (m *TiFlashPDPlacementManager) SetPlacementRule(ctx context.Context, rule placement.TiFlashRule) error { + if rule.Count == 0 { + return m.DeletePlacementRule(ctx, rule.GroupID, rule.ID) + } + j, _ := json.Marshal(rule) + buf := bytes.NewBuffer(j) + res, err := doRequest(ctx, m.addrs, path.Join(pdapi.Config, "rule"), "POST", buf) + if err != nil { + return errors.Trace(err) + } + if res == nil { + return fmt.Errorf("TiFlashPDPlacementManager returns error in SetPlacementRule") + } + return nil +} + +// DeletePlacementRule is to delete placement rule for certain group. +func (m *TiFlashPDPlacementManager) DeletePlacementRule(ctx context.Context, group string, ruleID string) error { + res, err := doRequest(ctx, m.addrs, path.Join(pdapi.Config, "rule", group, ruleID), "DELETE", nil) + if err != nil { + return errors.Trace(err) + } + if res == nil { + return fmt.Errorf("TiFlashPDPlacementManager returns error in DeletePlacementRule") + } + return nil +} + +// GetGroupRules to get all placement rule in a certain group. +func (m *TiFlashPDPlacementManager) GetGroupRules(ctx context.Context, group string) ([]placement.TiFlashRule, error) { + res, err := doRequest(ctx, m.addrs, path.Join(pdapi.Config, "rules", "group", group), "GET", nil) + if err != nil { + return nil, errors.Trace(err) + } + if res == nil { + return nil, fmt.Errorf("TiFlashPDPlacementManager returns error in GetGroupRules") + } + + var rules []placement.TiFlashRule + err = json.Unmarshal(res, &rules) + if err != nil { + return nil, errors.Trace(err) + } + + return rules, nil +} + +// PostAccelerateSchedule sends `regions/accelerate-schedule` request. +func (m *TiFlashPDPlacementManager) PostAccelerateSchedule(ctx context.Context, tableID int64) error { + startKey := tablecodec.GenTableRecordPrefix(tableID) + endKey := tablecodec.EncodeTablePrefix(tableID + 1) + startKey = codec.EncodeBytes([]byte{}, startKey) + endKey = codec.EncodeBytes([]byte{}, endKey) + + input := map[string]string{ + "start_key": hex.EncodeToString(startKey), + "end_key": hex.EncodeToString(endKey), + } + j, err := json.Marshal(input) + if err != nil { + return errors.Trace(err) + } + buf := bytes.NewBuffer(j) + res, err := doRequest(ctx, m.addrs, "/pd/api/v1/regions/accelerate-schedule", "POST", buf) + if err != nil { + return errors.Trace(err) + } + if res == nil { + return fmt.Errorf("TiFlashPDPlacementManager returns error in PostAccelerateSchedule") + } + return nil +} + +// GetPDRegionRecordStats is a helper function calling `/stats/region`. +func (m *TiFlashPDPlacementManager) GetPDRegionRecordStats(ctx context.Context, tableID int64, stats *helper.PDRegionStats) error { + startKey := tablecodec.GenTableRecordPrefix(tableID) + endKey := tablecodec.EncodeTablePrefix(tableID + 1) + startKey = codec.EncodeBytes([]byte{}, startKey) + endKey = codec.EncodeBytes([]byte{}, endKey) + + p := fmt.Sprintf("/pd/api/v1/stats/region?start_key=%s&end_key=%s", + url.QueryEscape(string(startKey)), + url.QueryEscape(string(endKey))) + res, err := doRequest(ctx, m.addrs, p, "GET", nil) + if err != nil { + return errors.Trace(err) + } + if res == nil { + return fmt.Errorf("TiFlashPDPlacementManager returns error in GetPDRegionRecordStats") + } + + err = json.Unmarshal(res, stats) + if err != nil { + return errors.Trace(err) + } + return nil +} + +// GetStoresStat gets the TiKV store information by accessing PD's api. +func (m *TiFlashPDPlacementManager) GetStoresStat(ctx context.Context) (*helper.StoresStat, error) { + var storesStat helper.StoresStat + res, err := doRequest(ctx, m.addrs, pdapi.Stores, "GET", nil) + if err != nil { + return nil, errors.Trace(err) + } + if res == nil { + return nil, fmt.Errorf("TiFlashPDPlacementManager returns error in GetStoresStat") + } + + err = json.Unmarshal(res, &storesStat) + if err != nil { + return nil, errors.Trace(err) + } + return &storesStat, err +} + +type mockTiFlashPlacementManager struct { + sync.Mutex + // Set to nil if there is no need to set up a mock TiFlash server. + // Otherwise use NewMockTiFlash to create one. + tiflash *MockTiFlash +} + +func makeBaseRule() placement.TiFlashRule { + return placement.TiFlashRule{ + GroupID: "tiflash", + ID: "", + Index: placement.RuleIndexTiFlash, + Override: false, + Role: placement.Learner, + Count: 2, + Constraints: []placement.Constraint{ + { + Key: "engine", + Op: placement.In, + Values: []string{"tiflash"}, + }, + }, + } +} + +// MakeNewRule creates a pd rule for TiFlash. +func MakeNewRule(ID int64, Count uint64, LocationLabels []string) *placement.TiFlashRule { + ruleID := fmt.Sprintf("table-%v-r", ID) + startKey := tablecodec.GenTableRecordPrefix(ID) + endKey := tablecodec.EncodeTablePrefix(ID + 1) + startKey = codec.EncodeBytes([]byte{}, startKey) + endKey = codec.EncodeBytes([]byte{}, endKey) + + ruleNew := makeBaseRule() + ruleNew.ID = ruleID + ruleNew.StartKeyHex = startKey.String() + ruleNew.EndKeyHex = endKey.String() + ruleNew.Count = int(Count) + ruleNew.LocationLabels = LocationLabels + + return &ruleNew +} + +type mockTiFlashTableInfo struct { + Regions []int + Accel bool +} + +func (m *mockTiFlashTableInfo) String() string { + regionStr := "" + for _, s := range m.Regions { + regionStr = regionStr + strconv.Itoa(s) + "\n" + } + if regionStr == "" { + regionStr = "\n" + } + return fmt.Sprintf("%v\n%v", len(m.Regions), regionStr) +} + +// MockTiFlash mocks a TiFlash, with necessary Pd support. +type MockTiFlash struct { + sync.Mutex + StatusAddr string + StatusServer *httptest.Server + SyncStatus map[int]mockTiFlashTableInfo + GlobalTiFlashPlacementRules map[string]placement.TiFlashRule + PdEnabled bool + TiflashDelay time.Duration + StartTime time.Time +} + +func (tiflash *MockTiFlash) setUpMockTiFlashHTTPServer() { + tiflash.Lock() + defer tiflash.Unlock() + // mock TiFlash http server + router := mux.NewRouter() + server := httptest.NewServer(router) + // mock store stats stat + statusAddr := strings.TrimPrefix(server.URL, "http://") + statusAddrVec := strings.Split(statusAddr, ":") + statusPort, _ := strconv.Atoi(statusAddrVec[1]) + router.HandleFunc("/tiflash/sync-status/{tableid:\\d+}", func(w http.ResponseWriter, req *http.Request) { + tiflash.Lock() + defer tiflash.Unlock() + params := mux.Vars(req) + tableID, err := strconv.Atoi(params["tableid"]) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + table, ok := tiflash.SyncStatus[tableID] + if !ok { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("0\n\n")) + return + } + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(table.String())) + }) + router.HandleFunc("/config", func(w http.ResponseWriter, req *http.Request) { + tiflash.Lock() + defer tiflash.Unlock() + s := fmt.Sprintf("{\n \"engine-store\": {\n \"http_port\": %v\n }\n}", statusPort) + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(s)) + }) + tiflash.StatusServer = server + tiflash.StatusAddr = statusAddr +} + +// NewMockTiFlash creates a MockTiFlash with a mocked TiFlash server. +func NewMockTiFlash() *MockTiFlash { + tiflash := &MockTiFlash{ + StatusAddr: "", + StatusServer: nil, + SyncStatus: make(map[int]mockTiFlashTableInfo), + GlobalTiFlashPlacementRules: make(map[string]placement.TiFlashRule), + PdEnabled: true, + TiflashDelay: 0, + StartTime: time.Now(), + } + tiflash.setUpMockTiFlashHTTPServer() + return tiflash +} + +// HandleSetPlacementRule is mock function for SetTiFlashPlacementRule. +func (tiflash *MockTiFlash) HandleSetPlacementRule(rule placement.TiFlashRule) error { + tiflash.Lock() + defer tiflash.Unlock() + if !tiflash.PdEnabled { + logutil.BgLogger().Info("pd server is manually disabled, just quit") + return nil + } + + if rule.Count == 0 { + delete(tiflash.GlobalTiFlashPlacementRules, rule.ID) + } else { + tiflash.GlobalTiFlashPlacementRules[rule.ID] = rule + } + // Pd shall schedule TiFlash, we can mock here + tid := 0 + _, err := fmt.Sscanf(rule.ID, "table-%d-r", &tid) + if err != nil { + return errors.New("Can't parse rule") + } + // Set up mock TiFlash replica + f := func() { + if z, ok := tiflash.SyncStatus[tid]; ok { + z.Regions = []int{1} + tiflash.SyncStatus[tid] = z + } else { + tiflash.SyncStatus[tid] = mockTiFlashTableInfo{ + Regions: []int{1}, + Accel: false, + } + } + } + if tiflash.TiflashDelay > 0 { + go func() { + time.Sleep(tiflash.TiflashDelay) + logutil.BgLogger().Warn("TiFlash replica is available after delay", zap.Duration("duration", tiflash.TiflashDelay)) + f() + }() + } else { + f() + } + return nil +} + +// HandleDeletePlacementRule is mock function for DeleteTiFlashPlacementRule. +func (tiflash *MockTiFlash) HandleDeletePlacementRule(group string, ruleID string) { + tiflash.Lock() + defer tiflash.Unlock() + delete(tiflash.GlobalTiFlashPlacementRules, ruleID) +} + +// HandleGetGroupRules is mock function for GetTiFlashGroupRules. +func (tiflash *MockTiFlash) HandleGetGroupRules(group string) ([]placement.TiFlashRule, error) { + tiflash.Lock() + defer tiflash.Unlock() + var result = make([]placement.TiFlashRule, 0) + for _, item := range tiflash.GlobalTiFlashPlacementRules { + result = append(result, item) + } + return result, nil +} + +// HandlePostAccelerateSchedule is mock function for PostAccelerateSchedule +func (tiflash *MockTiFlash) HandlePostAccelerateSchedule(endKey string) error { + tiflash.Lock() + defer tiflash.Unlock() + tableID := helper.GetTiFlashTableIDFromEndKey(endKey) + + table, ok := tiflash.SyncStatus[int(tableID)] + if ok { + table.Accel = true + tiflash.SyncStatus[int(tableID)] = table + } else { + tiflash.SyncStatus[int(tableID)] = mockTiFlashTableInfo{ + Regions: []int{}, + Accel: true, + } + } + return nil +} + +// HandleGetPDRegionRecordStats is mock function for GetPDRegionRecordStats. +// It currently always returns 1 Region for convenience. +func (tiflash *MockTiFlash) HandleGetPDRegionRecordStats(_ int64) helper.PDRegionStats { + return helper.PDRegionStats{ + Count: 1, + EmptyCount: 1, + StorageSize: 1, + StorageKeys: 1, + StoreLeaderCount: map[uint64]int{1: 1}, + StorePeerCount: map[uint64]int{1: 1}, + } +} + +// HandleGetStoresStat is mock function for GetStoresStat. +// It returns address of our mocked TiFlash server. +func (tiflash *MockTiFlash) HandleGetStoresStat() *helper.StoresStat { + tiflash.Lock() + defer tiflash.Unlock() + return &helper.StoresStat{ + Count: 1, + Stores: []helper.StoreStat{ + { + Store: helper.StoreBaseStat{ + ID: 1, + Address: "127.0.0.1:3930", + State: 0, + StateName: "Up", + Version: "4.0.0-alpha", + StatusAddress: tiflash.StatusAddr, + GitHash: "mock-tikv-githash", + StartTimestamp: tiflash.StartTime.Unix(), + Labels: []helper.StoreLabel{{ + Key: "engine", + Value: "tiflash", + }}, + }, + }, + }, + } +} + +// Compare supposed rule, and we actually get from TableInfo +func isRuleMatch(rule placement.TiFlashRule, startKey string, endKey string, count int, labels []string) bool { + // Compute startKey + if rule.StartKeyHex == startKey && rule.EndKeyHex == endKey { + ok := false + for _, c := range rule.Constraints { + if c.Key == "engine" && len(c.Values) == 1 && c.Values[0] == "tiflash" && c.Op == placement.In { + ok = true + break + } + } + if !ok { + return false + } + + if len(rule.LocationLabels) == len(labels) { + for i, lb := range labels { + if lb != rule.LocationLabels[i] { + return false + } + } + } else { + return false + } + + if rule.Count != count { + return false + } + if rule.Role != placement.Learner { + return false + } + } else { + return false + } + return true +} + +// CheckPlacementRule find if a given rule precisely matches already set rules. +func (tiflash *MockTiFlash) CheckPlacementRule(rule placement.TiFlashRule) bool { + tiflash.Lock() + defer tiflash.Unlock() + for _, r := range tiflash.GlobalTiFlashPlacementRules { + if isRuleMatch(rule, r.StartKeyHex, r.EndKeyHex, r.Count, r.LocationLabels) { + return true + } + } + return false +} + +// GetPlacementRule find a rule by name. +func (tiflash *MockTiFlash) GetPlacementRule(ruleName string) (*placement.TiFlashRule, bool) { + tiflash.Lock() + defer tiflash.Unlock() + if r, ok := tiflash.GlobalTiFlashPlacementRules[ruleName]; ok { + p := r + return &p, ok + } + return nil, false +} + +// CleanPlacementRules cleans all placement rules. +func (tiflash *MockTiFlash) CleanPlacementRules() { + tiflash.Lock() + defer tiflash.Unlock() + tiflash.GlobalTiFlashPlacementRules = make(map[string]placement.TiFlashRule) +} + +// PlacementRulesLen gets length of all currently set placement rules. +func (tiflash *MockTiFlash) PlacementRulesLen() int { + tiflash.Lock() + defer tiflash.Unlock() + return len(tiflash.GlobalTiFlashPlacementRules) +} + +// GetTableSyncStatus returns table sync status by given tableID. +func (tiflash *MockTiFlash) GetTableSyncStatus(tableID int) (*mockTiFlashTableInfo, bool) { + tiflash.Lock() + defer tiflash.Unlock() + if r, ok := tiflash.SyncStatus[tableID]; ok { + p := r + return &p, ok + } + return nil, false +} + +// PdSwitch controls if pd is enabled. +func (tiflash *MockTiFlash) PdSwitch(enabled bool) { + tiflash.Lock() + defer tiflash.Unlock() + tiflash.PdEnabled = enabled +} + +// SetPlacementRule is a helper function to set placement rule. +func (m *mockTiFlashPlacementManager) SetPlacementRule(ctx context.Context, rule placement.TiFlashRule) error { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return nil + } + return m.tiflash.HandleSetPlacementRule(rule) +} + +// DeletePlacementRule is to delete placement rule for certain group. +func (m *mockTiFlashPlacementManager) DeletePlacementRule(ctx context.Context, group string, ruleID string) error { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return nil + } + logutil.BgLogger().Info("Remove TiFlash rule", zap.String("ruleID", ruleID)) + m.tiflash.HandleDeletePlacementRule(group, ruleID) + return nil +} + +// GetGroupRules to get all placement rule in a certain group. +func (m *mockTiFlashPlacementManager) GetGroupRules(ctx context.Context, group string) ([]placement.TiFlashRule, error) { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return []placement.TiFlashRule{}, nil + } + return m.tiflash.HandleGetGroupRules(group) +} + +// PostAccelerateSchedule sends `regions/accelerate-schedule` request. +func (m *mockTiFlashPlacementManager) PostAccelerateSchedule(ctx context.Context, tableID int64) error { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return nil + } + endKey := tablecodec.EncodeTablePrefix(tableID + 1) + endKey = codec.EncodeBytes([]byte{}, endKey) + return m.tiflash.HandlePostAccelerateSchedule(hex.EncodeToString(endKey)) +} + +// GetPDRegionRecordStats is a helper function calling `/stats/region`. +func (m *mockTiFlashPlacementManager) GetPDRegionRecordStats(ctx context.Context, tableID int64, stats *helper.PDRegionStats) error { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return nil + } + *stats = m.tiflash.HandleGetPDRegionRecordStats(tableID) + return nil +} + +// GetStoresStat gets the TiKV store information by accessing PD's api. +func (m *mockTiFlashPlacementManager) GetStoresStat(ctx context.Context) (*helper.StoresStat, error) { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return nil, &MockTiFlashError{"MockTiFlash is not accessible"} + } + return m.tiflash.HandleGetStoresStat(), nil +} + +// Close is called to close mockTiFlashPlacementManager. +func (m *mockTiFlashPlacementManager) Close(ctx context.Context) { + m.Lock() + defer m.Unlock() + if m.tiflash == nil { + return + } + if m.tiflash.StatusServer != nil { + m.tiflash.StatusServer.Close() + } +} + +// MockTiFlashError represents MockTiFlash error +type MockTiFlashError struct { + Message string +} + +func (me *MockTiFlashError) Error() string { + return me.Message +} diff --git a/domain/main_test.go b/domain/main_test.go index 069ed9590f222..1896313761270 100644 --- a/domain/main_test.go +++ b/domain/main_test.go @@ -17,24 +17,16 @@ package domain_test import ( "testing" - . "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/util/testbridge" "go.uber.org/goleak" ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) } - -// TestDomainSerial handles tests in serial -func TestDomainSerial(t *testing.T) { - // these tests should run in serial for failpoint is global - t.Run("info", SubTestInfo) - t.Run("domain", SubTestDomain) - t.Run("domainSession", SubTestDomainSession) -} diff --git a/domain/plan_replayer.go b/domain/plan_replayer.go index 37fbbc50472b9..b207f904a6608 100644 --- a/domain/plan_replayer.go +++ b/domain/plan_replayer.go @@ -16,7 +16,6 @@ package domain import ( "errors" - "fmt" "io/ioutil" "os" "path/filepath" @@ -29,9 +28,12 @@ import ( "go.uber.org/zap" ) -type planReplayer struct { +// dumpFileGcChecker is used to gc dump file in circle +// For now it is used by `plan replayer` and `trace plan` statement +type dumpFileGcChecker struct { sync.Mutex - planReplayerGCLease time.Duration + gcLease time.Duration + paths []string } // GetPlanReplayerDirName returns plan replayer directory path. @@ -56,32 +58,37 @@ func parseTime(s string) (time.Time, error) { return time.Unix(0, i), nil } -func (p *planReplayer) planReplayerGC(t time.Duration) { +func (p *dumpFileGcChecker) gcDumpFiles(t time.Duration) { p.Lock() defer p.Unlock() - path := GetPlanReplayerDirName() + for _, path := range p.paths { + p.gcDumpFilesByPath(path, t) + } +} + +func (p *dumpFileGcChecker) gcDumpFilesByPath(path string, t time.Duration) { files, err := ioutil.ReadDir(path) if err != nil { if !os.IsNotExist(err) { - logutil.BgLogger().Warn("[PlanReplayer] open plan replayer directory failed", zap.Error(err)) + logutil.BgLogger().Warn("[dumpFileGcChecker] open plan replayer directory failed", zap.Error(err)) } - return } gcTime := time.Now().Add(-t) for _, f := range files { - createTime, err := parseTime(f.Name()) + fileName := f.Name() + createTime, err := parseTime(fileName) if err != nil { - logutil.BgLogger().Warn("[PlanReplayer] parseTime failed", zap.Error(err)) + logutil.BgLogger().Error("[dumpFileGcChecker] parseTime failed", zap.Error(err), zap.String("filename", fileName)) continue } if !createTime.After(gcTime) { err := os.Remove(filepath.Join(path, f.Name())) if err != nil { - logutil.BgLogger().Warn("[PlanReplayer] remove file failed", zap.Error(err)) + logutil.BgLogger().Warn("[dumpFileGcChecker] remove file failed", zap.Error(err), zap.String("filename", fileName)) continue } - logutil.BgLogger().Info(fmt.Sprintf("[PlanReplayer] GC %s", f.Name())) + logutil.BgLogger().Info("dumpFileGcChecker successful", zap.String("filename", fileName)) } } } diff --git a/domain/plan_replayer_test.go b/domain/plan_replayer_test.go index f21abfd1fe5e8..7b44db9b8d239 100644 --- a/domain/plan_replayer_test.go +++ b/domain/plan_replayer_test.go @@ -29,14 +29,16 @@ func TestPlanReplayerGC(t *testing.T) { time := startTime.UnixNano() fileName := fmt.Sprintf("replayer_single_xxxxxx_%v.zip", time) err := os.MkdirAll(GetPlanReplayerDirName(), os.ModePerm) - require.Nil(t, err) + require.NoError(t, err) path := filepath.Join(GetPlanReplayerDirName(), fileName) zf, err := os.Create(path) - require.Nil(t, err) + require.NoError(t, err) zf.Close() - handler := &planReplayer{} - handler.planReplayerGC(0) + handler := &dumpFileGcChecker{ + paths: []string{GetPlanReplayerDirName()}, + } + handler.gcDumpFiles(0) _, err = os.Stat(path) require.NotNil(t, err) @@ -47,7 +49,7 @@ func TestPlanReplayerParseTime(t *testing.T) { nowTime := time.Now() name1 := fmt.Sprintf("replayer_single_xxxxxx_%v.zip", nowTime.UnixNano()) pt, err := parseTime(name1) - require.Nil(t, err) + require.NoError(t, err) require.True(t, pt.Equal(nowTime)) name2 := fmt.Sprintf("replayer_single_xxxxxx_%v1.zip", nowTime.UnixNano()) diff --git a/domain/schema_checker.go b/domain/schema_checker.go index 4ca32461f5ed0..5251cc4541f5d 100644 --- a/domain/schema_checker.go +++ b/domain/schema_checker.go @@ -15,12 +15,12 @@ package domain import ( - "sync/atomic" "time" "github.com/pingcap/tidb/metrics" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/txnkv/transaction" + atomicutil "go.uber.org/atomic" ) // SchemaChecker is used for checking schema-validity. @@ -38,9 +38,9 @@ func (i intSchemaVer) SchemaMetaVersion() int64 { var ( // SchemaOutOfDateRetryInterval is the backoff time before retrying. - SchemaOutOfDateRetryInterval = int64(500 * time.Millisecond) + SchemaOutOfDateRetryInterval = atomicutil.NewDuration(500 * time.Millisecond) // SchemaOutOfDateRetryTimes is the max retry count when the schema is out of date. - SchemaOutOfDateRetryTimes = int32(10) + SchemaOutOfDateRetryTimes = atomicutil.NewInt32(10) ) // NewSchemaChecker creates a new schema checker. @@ -59,8 +59,8 @@ func (s *SchemaChecker) Check(txnTS uint64) (*transaction.RelatedSchemaChange, e // CheckBySchemaVer checks if the schema version valid or not at txnTS. func (s *SchemaChecker) CheckBySchemaVer(txnTS uint64, startSchemaVer tikv.SchemaVer) (*transaction.RelatedSchemaChange, error) { - schemaOutOfDateRetryInterval := atomic.LoadInt64(&SchemaOutOfDateRetryInterval) - schemaOutOfDateRetryTimes := int(atomic.LoadInt32(&SchemaOutOfDateRetryTimes)) + schemaOutOfDateRetryInterval := SchemaOutOfDateRetryInterval.Load() + schemaOutOfDateRetryTimes := int(SchemaOutOfDateRetryTimes.Load()) for i := 0; i < schemaOutOfDateRetryTimes; i++ { relatedChange, CheckResult := s.SchemaValidator.Check(txnTS, startSchemaVer.SchemaMetaVersion(), s.relatedTableIDs) switch CheckResult { @@ -70,7 +70,7 @@ func (s *SchemaChecker) CheckBySchemaVer(txnTS uint64, startSchemaVer tikv.Schem metrics.SchemaLeaseErrorCounter.WithLabelValues("changed").Inc() return relatedChange, ErrInfoSchemaChanged case ResultUnknown: - time.Sleep(time.Duration(schemaOutOfDateRetryInterval)) + time.Sleep(schemaOutOfDateRetryInterval) } } diff --git a/domain/schema_validator.go b/domain/schema_validator.go index 7d6a3cf35c21c..bbdf8f8d6641e 100644 --- a/domain/schema_validator.go +++ b/domain/schema_validator.go @@ -185,14 +185,20 @@ func (s *schemaValidator) isRelatedTablesChanged(currVer int64, tableIDs []int64 } changedTblMap := make(map[int64]uint64) + changedSchemaVers := make([]int64, 0) for _, item := range newerDeltas { + affected := false for i, tblID := range item.relatedIDs { for _, relatedTblID := range tableIDs { if tblID == relatedTblID { changedTblMap[tblID] |= item.relatedActions[i] + affected = true } } } + if affected { + changedSchemaVers = append(changedSchemaVers, item.schemaVersion) + } } if len(changedTblMap) > 0 { tblIds := make([]int64, 0, len(changedTblMap)) @@ -207,6 +213,8 @@ func (s *schemaValidator) isRelatedTablesChanged(currVer int64, tableIDs []int64 res.PhyTblIDS = tblIds res.ActionTypes = actionTypes res.Amendable = true + logutil.BgLogger().Info("schema of tables in the transaction are changed", zap.Int64s("conflicted table IDs", tblIds), + zap.Int64("transaction schema", currVer), zap.Int64s("schema versions that changed the tables", changedSchemaVers)) return res, true } return res, false diff --git a/domain/schema_validator_test.go b/domain/schema_validator_test.go index 2eb56d69e0cc1..fb3aa7ecfb4d4 100644 --- a/domain/schema_validator_test.go +++ b/domain/schema_validator_test.go @@ -16,11 +16,11 @@ package domain import ( "math/rand" - "sync" "testing" "time" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/txnkv/transaction" @@ -38,9 +38,8 @@ func subTestSchemaValidatorGeneral(t *testing.T) { leaseGrantCh := make(chan leaseGrantItem) oracleCh := make(chan uint64) exit := make(chan struct{}) - var wg sync.WaitGroup - wg.Add(1) - go serverFunc(lease, leaseGrantCh, oracleCh, exit, &wg) + var wg util.WaitGroupWrapper + wg.Run(func() { serverFunc(lease, leaseGrantCh, oracleCh, exit) }) validator := NewSchemaValidator(lease, nil).(*schemaValidator) require.True(t, validator.IsStarted()) @@ -246,8 +245,7 @@ func getGreaterVersionItem(t *testing.T, lease time.Duration, leaseGrantCh chan // serverFunc plays the role as a remote server, runs in a separate goroutine. // It can grant lease and provide timestamp oracle. // Caller should communicate with it through channel to mock network. -func serverFunc(lease time.Duration, requireLease chan leaseGrantItem, oracleCh chan uint64, exit chan struct{}, wg *sync.WaitGroup) { - defer wg.Done() +func serverFunc(lease time.Duration, requireLease chan leaseGrantItem, oracleCh chan uint64, exit chan struct{}) { var version int64 leaseTS := uint64(time.Now().UnixNano()) ticker := time.NewTicker(lease) diff --git a/domain/sysvar_cache.go b/domain/sysvar_cache.go index d89ba88a76ee0..a0389b7e4bff4 100644 --- a/domain/sysvar_cache.go +++ b/domain/sysvar_cache.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/stmtsummary" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" storekv "github.com/tikv/client-go/v2/kv" pd "github.com/tikv/pd/client" "go.uber.org/zap" @@ -94,11 +95,7 @@ func (do *Domain) fetchTableValues(ctx sessionctx.Context) (map[string]string, e tableContents := make(map[string]string) // Copy all variables from the table to tableContents exec := ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.Background(), `SELECT variable_name, variable_value FROM mysql.global_variables`) - if err != nil { - return tableContents, err - } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, `SELECT variable_name, variable_value FROM mysql.global_variables`) if err != nil { return nil, err } @@ -167,6 +164,8 @@ func (do *Domain) rebuildSysVarCache(ctx sessionctx.Context) error { func (do *Domain) checkEnableServerGlobalVar(name, sVal string) { var err error switch name { + case variable.TiDBMemQuotaBindingCache: + variable.MemQuotaBindingCache.Store(variable.TidbOptInt64(sVal, variable.DefTiDBMemQuotaBindingCache)) case variable.TiDBTSOClientBatchMaxWaitTime: var val float64 val, err = strconv.ParseFloat(sVal, 64) @@ -188,58 +187,71 @@ func (do *Domain) checkEnableServerGlobalVar(name, sVal string) { case variable.TiDBEnableLocalTxn: variable.EnableLocalTxn.Store(variable.TiDBOptOn(sVal)) case variable.TiDBEnableStmtSummary: - err = stmtsummary.StmtSummaryByDigestMap.SetEnabled(sVal, false) + err = stmtsummary.StmtSummaryByDigestMap.SetEnabled(variable.TiDBOptOn(sVal)) case variable.TiDBStmtSummaryInternalQuery: - err = stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(sVal, false) + err = stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(variable.TiDBOptOn(sVal)) case variable.TiDBStmtSummaryRefreshInterval: - err = stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(sVal, false) + err = stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(variable.TidbOptInt64(sVal, variable.DefTiDBStmtSummaryRefreshInterval)) case variable.TiDBStmtSummaryHistorySize: - err = stmtsummary.StmtSummaryByDigestMap.SetHistorySize(sVal, false) + err = stmtsummary.StmtSummaryByDigestMap.SetHistorySize(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryHistorySize)) case variable.TiDBStmtSummaryMaxStmtCount: - err = stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(sVal, false) + err = stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(uint(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryMaxStmtCount))) case variable.TiDBStmtSummaryMaxSQLLength: - err = stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(sVal, false) - case variable.TiDBCapturePlanBaseline: - variable.CapturePlanBaseline.Set(sVal, false) - case variable.TiDBEnableTopSQL: - variable.TopSQLVariable.Enable.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBTopSQLPrecisionSeconds: + err = stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(variable.TidbOptInt(sVal, variable.DefTiDBStmtSummaryMaxSQLLength)) + case variable.TiDBTopSQLMaxTimeSeriesCount: var val int64 val, err = strconv.ParseInt(sVal, 10, 64) if err != nil { break } - variable.TopSQLVariable.PrecisionSeconds.Store(val) - case variable.TiDBTopSQLMaxStatementCount: + topsqlstate.GlobalState.MaxStatementCount.Store(val) + case variable.TiDBTopSQLMaxMetaCount: var val int64 val, err = strconv.ParseInt(sVal, 10, 64) if err != nil { break } - variable.TopSQLVariable.MaxStatementCount.Store(val) - case variable.TiDBTopSQLMaxCollect: + topsqlstate.GlobalState.MaxCollect.Store(val) + case variable.TiDBRestrictedReadOnly: + variable.RestrictedReadOnly.Store(variable.TiDBOptOn(sVal)) + case variable.TiDBSuperReadOnly: + variable.VarTiDBSuperReadOnly.Store(variable.TiDBOptOn(sVal)) + case variable.TiDBStoreLimit: var val int64 val, err = strconv.ParseInt(sVal, 10, 64) if err != nil { break } - variable.TopSQLVariable.MaxCollect.Store(val) - case variable.TiDBTopSQLReportIntervalSeconds: + storekv.StoreLimit.Store(val) + case variable.TiDBTableCacheLease: var val int64 val, err = strconv.ParseInt(sVal, 10, 64) if err != nil { break } - variable.TopSQLVariable.ReportIntervalSeconds.Store(val) - case variable.TiDBRestrictedReadOnly: - variable.RestrictedReadOnly.Store(variable.TiDBOptOn(sVal)) - case variable.TiDBStoreLimit: + variable.TableCacheLease.Store(val) + case variable.TiDBGCMaxWaitTime: var val int64 val, err = strconv.ParseInt(sVal, 10, 64) if err != nil { break } - storekv.StoreLimit.Store(val) + variable.GCMaxWaitTime.Store(val) + case variable.TiDBPersistAnalyzeOptions: + variable.PersistAnalyzeOptions.Store(variable.TiDBOptOn(sVal)) + case variable.TiDBEnableColumnTracking: + variable.EnableColumnTracking.Store(variable.TiDBOptOn(sVal)) + case variable.TiDBStatsLoadSyncWait: + var val int64 + val, err = strconv.ParseInt(sVal, 10, 64) + if err != nil { + break + } + variable.StatsLoadSyncWait.Store(val) + case variable.TiDBStatsLoadPseudoTimeout: + variable.StatsLoadPseudoTimeout.Store(variable.TiDBOptOn(sVal)) + case variable.TiDBTxnCommitBatchSize: + storekv.TxnCommitBatchSize.Store(uint64(variable.TidbOptInt64(sVal, int64(storekv.DefTxnCommitBatchSize)))) } if err != nil { logutil.BgLogger().Error(fmt.Sprintf("load global variable %s error", name), zap.Error(err)) diff --git a/dumpling/export/block_allow_list_test.go b/dumpling/export/block_allow_list_test.go index 3ce55497d589b..640e9cef7e4dc 100644 --- a/dumpling/export/block_allow_list_test.go +++ b/dumpling/export/block_allow_list_test.go @@ -6,8 +6,8 @@ import ( "strings" "testing" - "github.com/pingcap/tidb-tools/pkg/filter" - tf "github.com/pingcap/tidb-tools/pkg/table-filter" + "github.com/pingcap/tidb/util/filter" + tf "github.com/pingcap/tidb/util/table-filter" "github.com/stretchr/testify/require" "github.com/pingcap/tidb/br/pkg/version" diff --git a/dumpling/export/config.go b/dumpling/export/config.go index 017e4aa9294bb..726c9fcf23afc 100644 --- a/dumpling/export/config.go +++ b/dumpling/export/config.go @@ -17,14 +17,13 @@ import ( "github.com/docker/go-units" "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - "github.com/pingcap/tidb-tools/pkg/utils" + "github.com/pingcap/tidb/br/pkg/storage" + "github.com/pingcap/tidb/br/pkg/version" + "github.com/pingcap/tidb/util" + filter "github.com/pingcap/tidb/util/table-filter" "github.com/prometheus/client_golang/prometheus" "github.com/spf13/pflag" "go.uber.org/zap" - - "github.com/pingcap/tidb/br/pkg/storage" - "github.com/pingcap/tidb/br/pkg/version" ) const ( @@ -45,6 +44,8 @@ const ( flagConsistency = "consistency" flagSnapshot = "snapshot" flagNoViews = "no-views" + flagNoSequences = "no-sequences" + flagSortByPk = "order-by-primary-key" flagStatusAddr = "status-addr" flagRows = "rows" flagWhere = "where" @@ -78,10 +79,12 @@ const ( // Config is the dump config for dumpling type Config struct { storage.BackendOptions + ExtStorage storage.ExternalStorage `json:"-"` AllowCleartextPasswords bool SortByPk bool NoViews bool + NoSequences bool NoHeader bool NoSchemas bool NoData bool @@ -133,6 +136,8 @@ type Config struct { SessionParams map[string]interface{} Labels prometheus.Labels `json:"-"` Tables DatabaseTables + + CollationCompatible string } // ServerInfoUnknown is the unknown database type to dumpling @@ -145,36 +150,38 @@ var ServerInfoUnknown = version.ServerInfo{ func DefaultConfig() *Config { allFilter, _ := filter.Parse([]string{"*.*"}) return &Config{ - Databases: nil, - Host: "127.0.0.1", - User: "root", - Port: 3306, - Password: "", - Threads: 4, - Logger: nil, - StatusAddr: ":8281", - FileSize: UnspecifiedSize, - StatementSize: DefaultStatementSize, - OutputDirPath: ".", - ServerInfo: ServerInfoUnknown, - SortByPk: true, - Tables: nil, - Snapshot: "", - Consistency: consistencyTypeAuto, - NoViews: true, - Rows: UnspecifiedSize, - Where: "", - FileType: "", - NoHeader: false, - NoSchemas: false, - NoData: false, - CsvNullValue: "\\N", - SQL: "", - TableFilter: allFilter, - DumpEmptyDatabase: true, - SessionParams: make(map[string]interface{}), - OutputFileTemplate: DefaultOutputFileTemplate, - PosAfterConnect: false, + Databases: nil, + Host: "127.0.0.1", + User: "root", + Port: 3306, + Password: "", + Threads: 4, + Logger: nil, + StatusAddr: ":8281", + FileSize: UnspecifiedSize, + StatementSize: DefaultStatementSize, + OutputDirPath: ".", + ServerInfo: ServerInfoUnknown, + SortByPk: true, + Tables: nil, + Snapshot: "", + Consistency: consistencyTypeAuto, + NoViews: true, + NoSequences: true, + Rows: UnspecifiedSize, + Where: "", + FileType: "", + NoHeader: false, + NoSchemas: false, + NoData: false, + CsvNullValue: "\\N", + SQL: "", + TableFilter: allFilter, + DumpEmptyDatabase: true, + SessionParams: make(map[string]interface{}), + OutputFileTemplate: DefaultOutputFileTemplate, + PosAfterConnect: false, + CollationCompatible: LooseCollationCompatible, } } @@ -226,6 +233,8 @@ func (conf *Config) DefineFlags(flags *pflag.FlagSet) { flags.String(flagConsistency, consistencyTypeAuto, "Consistency level during dumping: {auto|none|flush|lock|snapshot}") flags.String(flagSnapshot, "", "Snapshot position (uint64 or MySQL style string timestamp). Valid only when consistency=snapshot") flags.BoolP(flagNoViews, "W", true, "Do not dump views") + flags.Bool(flagNoSequences, true, "Do not dump sequences") + flags.Bool(flagSortByPk, true, "Sort dump results by primary key through order by sql") flags.String(flagStatusAddr, ":8281", "dumpling API server and pprof addr") flags.Uint64P(flagRows, "r", UnspecifiedSize, "If specified, dumpling will split table into chunks and concurrently dump them to different files to improve efficiency. For TiDB v3.0+, specify this will make dumpling split table with each file one TiDB region(no matter how many rows is).\n"+ "If not specified, dumpling will dump table without inner-concurrency which could be relatively slow. default unlimited") @@ -322,6 +331,14 @@ func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error { if err != nil { return errors.Trace(err) } + conf.NoSequences, err = flags.GetBool(flagNoSequences) + if err != nil { + return errors.Trace(err) + } + conf.SortByPk, err = flags.GetBool(flagSortByPk) + if err != nil { + return errors.Trace(err) + } conf.StatusAddr, err = flags.GetString(flagStatusAddr) if err != nil { return errors.Trace(err) @@ -532,6 +549,9 @@ func ParseCompressType(compressType string) (storage.CompressType, error) { } func (conf *Config) createExternalStorage(ctx context.Context) (storage.ExternalStorage, error) { + if conf.ExtStorage != nil { + return conf.ExtStorage, nil + } b, err := storage.ParseBackend(conf.OutputDirPath, &conf.BackendOptions) if err != nil { return nil, errors.Trace(err) @@ -555,6 +575,9 @@ const ( defaultDumpGCSafePointTTL = 5 * 60 defaultEtcdDialTimeOut = 3 * time.Second + LooseCollationCompatible = "loose" + StrictCollationCompatible = "strict" + dumplingServiceSafePointPrefix = "dumpling" ) @@ -592,7 +615,7 @@ func registerTLSConfig(conf *Config) error { return errors.Trace(err) } } - tlsConfig, err = utils.ToTLSConfigWithVerifyByRawbytes(conf.Security.SSLCABytes, + tlsConfig, err = util.ToTLSConfigWithVerifyByRawbytes(conf.Security.SSLCABytes, conf.Security.SSLCertBytes, conf.Security.SSLKEYBytes, []string{}) if err != nil { return errors.Trace(err) diff --git a/dumpling/export/config_test.go b/dumpling/export/config_test.go index 80c8046d1faa5..a0e34b208292d 100644 --- a/dumpling/export/config_test.go +++ b/dumpling/export/config_test.go @@ -3,12 +3,11 @@ package export import ( - "github.com/pingcap/tidb/br/pkg/version" "testing" - "github.com/stretchr/testify/require" - + "github.com/pingcap/tidb/br/pkg/version" tcontext "github.com/pingcap/tidb/dumpling/context" + "github.com/stretchr/testify/require" ) func TestCreateExternalStorage(t *testing.T) { diff --git a/dumpling/export/conn.go b/dumpling/export/conn.go new file mode 100644 index 0000000000000..c6723865b7003 --- /dev/null +++ b/dumpling/export/conn.go @@ -0,0 +1,108 @@ +// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0. + +package export + +import ( + "database/sql" + + "github.com/pingcap/errors" + "go.uber.org/zap" + + "github.com/pingcap/tidb/br/pkg/utils" + tcontext "github.com/pingcap/tidb/dumpling/context" +) + +// BaseConn wraps connection instance. +type BaseConn struct { + DBConn *sql.Conn + + backOffer backOfferResettable + rebuildConnFn func(*sql.Conn, bool) (*sql.Conn, error) +} + +func newBaseConn(conn *sql.Conn, shouldRetry bool, rebuildConnFn func(*sql.Conn, bool) (*sql.Conn, error)) *BaseConn { + baseConn := &BaseConn{DBConn: conn} + baseConn.backOffer = newRebuildConnBackOffer(shouldRetry) + if shouldRetry { + baseConn.rebuildConnFn = rebuildConnFn + } + return baseConn +} + +// QuerySQL defines query statement, and connect to real DB. +func (conn *BaseConn) QuerySQL(tctx *tcontext.Context, handleOneRow func(*sql.Rows) error, reset func(), query string, args ...interface{}) error { + retryTime := 0 + err := utils.WithRetry(tctx, func() (err error) { + retryTime++ + if retryTime > 1 && conn.rebuildConnFn != nil { + conn.DBConn, err = conn.rebuildConnFn(conn.DBConn, false) + if err != nil { + return + } + } + err = simpleQueryWithArgs(tctx, conn.DBConn, handleOneRow, query, args...) + if err != nil { + tctx.L().Info("cannot execute query", zap.Int("retryTime", retryTime), zap.String("sql", query), + zap.Any("args", args), zap.Error(err)) + reset() + return err + } + return nil + }, conn.backOffer) + conn.backOffer.Reset() + return err +} + +// QuerySQLWithColumns defines query statement, and connect to real DB and get results for special column names +func (conn *BaseConn) QuerySQLWithColumns(tctx *tcontext.Context, columns []string, query string, args ...interface{}) ([][]string, error) { + retryTime := 0 + var results [][]string + err := utils.WithRetry(tctx, func() (err error) { + retryTime++ + if retryTime > 1 && conn.rebuildConnFn != nil { + conn.DBConn, err = conn.rebuildConnFn(conn.DBConn, false) + if err != nil { + return + } + } + rows, err := conn.DBConn.QueryContext(tctx, query, args...) + if err != nil { + tctx.L().Info("cannot execute query", zap.Int("retryTime", retryTime), zap.String("sql", query), + zap.Any("args", args), zap.Error(err)) + return errors.Annotatef(err, "sql: %s", query) + } + results, err = GetSpecifiedColumnValuesAndClose(rows, columns...) + if err != nil { + tctx.L().Info("cannot execute query", zap.Int("retryTime", retryTime), zap.String("sql", query), + zap.Any("args", args), zap.Error(err)) + results = nil + return errors.Annotatef(err, "sql: %s", query) + } + return err + }, conn.backOffer) + conn.backOffer.Reset() + return results, err +} + +// ExecSQL defines exec statement, and connect to real DB. +func (conn *BaseConn) ExecSQL(tctx *tcontext.Context, canRetryFunc func(sql.Result, error) error, query string, args ...interface{}) error { + retryTime := 0 + err := utils.WithRetry(tctx, func() (err error) { + retryTime++ + if retryTime > 1 && conn.rebuildConnFn != nil { + conn.DBConn, err = conn.rebuildConnFn(conn.DBConn, false) + if err != nil { + return + } + } + res, err := conn.DBConn.ExecContext(tctx, query, args...) + if err = canRetryFunc(res, err); err != nil { + tctx.L().Info("cannot execute query", zap.Int("retryTime", retryTime), zap.String("sql", query), + zap.Any("args", args), zap.Error(err)) + return err + } + return nil + }, conn.backOffer) + conn.backOffer.Reset() + return err +} diff --git a/dumpling/export/dump.go b/dumpling/export/dump.go index 385a6841b32dc..0e1087e9eebb3 100755 --- a/dumpling/export/dump.go +++ b/dumpling/export/dump.go @@ -52,13 +52,26 @@ type Dumper struct { dbHandle *sql.DB tidbPDClientForGC pd.Client - selectTiDBTableRegionFunc func(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) + selectTiDBTableRegionFunc func(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) totalTables int64 charsetAndDefaultCollationMap map[string]string } // NewDumper returns a new Dumper func NewDumper(ctx context.Context, conf *Config) (*Dumper, error) { + failpoint.Inject("setExtStorage", func(val failpoint.Value) { + path := val.(string) + b, err := storage.ParseBackend(path, nil) + if err != nil { + panic(err) + } + s, err := storage.New(context.Background(), b, &storage.ExternalStorageOptions{}) + if err != nil { + panic(err) + } + conf.ExtStorage = s + }) + tctx, cancelFn := tcontext.Background().WithContext(ctx).WithCancel() d := &Dumper{ tctx: tctx, @@ -154,10 +167,12 @@ func (d *Dumper) Dump() (dumpErr error) { tctx.L().Info("get global metadata failed", log.ShortError(err)) } - //init charset and default collation map - d.charsetAndDefaultCollationMap, err = GetCharsetAndDefaultCollation(tctx.Context, metaConn) - if err != nil { - return err + if d.conf.CollationCompatible == StrictCollationCompatible { + //init charset and default collation map + d.charsetAndDefaultCollationMap, err = GetCharsetAndDefaultCollation(tctx.Context, metaConn) + if err != nil { + return err + } } // for other consistencies, we should get table list after consistency is set up and GlobalMetaData is cached @@ -172,7 +187,7 @@ func (d *Dumper) Dump() (dumpErr error) { atomic.StoreInt64(&d.totalTables, int64(calculateTableCount(conf.Tables))) - rebuildConn := func(conn *sql.Conn) (*sql.Conn, error) { + rebuildConn := func(conn *sql.Conn, updateMeta bool) (*sql.Conn, error) { // make sure that the lock connection is still alive err1 := conCtrl.PingContext(tctx) if err1 != nil { @@ -186,7 +201,7 @@ func (d *Dumper) Dump() (dumpErr error) { } conn = newConn // renew the master status after connection. dm can't close safe-mode until dm reaches current pos - if conf.PosAfterConnect { + if updateMeta && conf.PosAfterConnect { err1 = m.recordGlobalMetaData(conn, conf.ServerInfo.ServerType, true) if err1 != nil { return conn, errors.Trace(err1) @@ -244,16 +259,17 @@ func (d *Dumper) Dump() (dumpErr error) { fmt.Printf("tidb_mem_quota_query == %s\n", s) } }) + baseConn := newBaseConn(metaConn, canRebuildConn(conf.Consistency, conf.TransactionalConsistency), rebuildConn) if conf.SQL == "" { - if err = d.dumpDatabases(writerCtx, metaConn, taskChan); err != nil && !errors.ErrorEqual(err, context.Canceled) { + if err = d.dumpDatabases(writerCtx, baseConn, taskChan); err != nil && !errors.ErrorEqual(err, context.Canceled) { return err } } else { - d.dumpSQL(writerCtx, taskChan) + d.dumpSQL(writerCtx, baseConn, taskChan) } close(taskChan) - _ = metaConn.Close() + _ = baseConn.DBConn.Close() if err := wg.Wait(); err != nil { summary.CollectFailureUnit("dump table data", err) return errors.Trace(err) @@ -266,7 +282,7 @@ func (d *Dumper) Dump() (dumpErr error) { } func (d *Dumper) startWriters(tctx *tcontext.Context, wg *errgroup.Group, taskChan <-chan Task, - rebuildConnFn func(*sql.Conn) (*sql.Conn, error)) ([]*Writer, func(), error) { + rebuildConnFn func(*sql.Conn, bool) (*sql.Conn, error)) ([]*Writer, func(), error) { conf, pool := d.conf, d.dbHandle writers := make([]*Writer, conf.Threads) for i := 0; i < conf.Threads; i++ { @@ -309,14 +325,14 @@ func (d *Dumper) startWriters(tctx *tcontext.Context, wg *errgroup.Group, taskCh return writers, tearDown, nil } -func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *sql.Conn, taskChan chan<- Task) error { +func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *BaseConn, taskChan chan<- Task) error { conf := d.conf allTables := conf.Tables // policy should be created before database // placement policy in other server type can be different, so we only handle the tidb server if conf.ServerInfo.ServerType == version.ServerTypeTiDB { - policyNames, err := ListAllPlacementPolicyNames(metaConn) + policyNames, err := ListAllPlacementPolicyNames(tctx, metaConn) if err != nil { errCause := errors.Cause(err) if mysqlErr, ok := errCause.(*mysql.MySQLError); ok && mysqlErr.Number == ErrNoSuchTable { @@ -327,7 +343,7 @@ func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *sql.Conn, taskC } } for _, policy := range policyNames { - createPolicySQL, err := ShowCreatePlacementPolicy(metaConn, policy) + createPolicySQL, err := ShowCreatePlacementPolicy(tctx, metaConn, policy) if err != nil { return errors.Trace(err) } @@ -343,15 +359,17 @@ func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *sql.Conn, taskC parser1 := parser.New() for dbName, tables := range allTables { if !conf.NoSchemas { - createDatabaseSQL, err := ShowCreateDatabase(metaConn, dbName) + createDatabaseSQL, err := ShowCreateDatabase(tctx, metaConn, dbName) if err != nil { return errors.Trace(err) } + // adjust db collation - createDatabaseSQL, err = adjustDatabaseCollation(tctx, parser1, createDatabaseSQL, d.charsetAndDefaultCollationMap) + createDatabaseSQL, err = adjustDatabaseCollation(tctx, d.conf.CollationCompatible, parser1, createDatabaseSQL, d.charsetAndDefaultCollationMap) if err != nil { return errors.Trace(err) } + task := NewTaskDatabaseMeta(dbName, createDatabaseSQL) ctxDone := d.sendTaskToChan(tctx, task, taskChan) if ctxDone { @@ -368,19 +386,27 @@ func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *sql.Conn, taskC } if !conf.NoSchemas { - if table.Type == TableTypeView { + switch table.Type { + case TableTypeView: task := NewTaskViewMeta(dbName, table.Name, meta.ShowCreateTable(), meta.ShowCreateView()) ctxDone := d.sendTaskToChan(tctx, task, taskChan) if ctxDone { return tctx.Err() } - } else { + case TableTypeSequence: + task := NewTaskSequenceMeta(dbName, table.Name, meta.ShowCreateTable()) + ctxDone := d.sendTaskToChan(tctx, task, taskChan) + if ctxDone { + return tctx.Err() + } + default: // adjust table collation - newCreateSQL, err := adjustTableCollation(tctx, parser1, meta.ShowCreateTable(), d.charsetAndDefaultCollationMap) + newCreateSQL, err := adjustTableCollation(tctx, d.conf.CollationCompatible, parser1, meta.ShowCreateTable(), d.charsetAndDefaultCollationMap) if err != nil { return errors.Trace(err) } meta.(*tableMeta).showCreateTable = newCreateSQL + task := NewTaskTableMeta(dbName, table.Name, meta.ShowCreateTable()) ctxDone := d.sendTaskToChan(tctx, task, taskChan) if ctxDone { @@ -401,7 +427,10 @@ func (d *Dumper) dumpDatabases(tctx *tcontext.Context, metaConn *sql.Conn, taskC } // adjustDatabaseCollation adjusts db collation and return new create sql and collation -func adjustDatabaseCollation(tctx *tcontext.Context, parser *parser.Parser, originSQL string, charsetAndDefaultCollationMap map[string]string) (string, error) { +func adjustDatabaseCollation(tctx *tcontext.Context, collationCompatible string, parser *parser.Parser, originSQL string, charsetAndDefaultCollationMap map[string]string) (string, error) { + if collationCompatible != StrictCollationCompatible { + return originSQL, nil + } stmt, err := parser.ParseOneStmt(originSQL, "", "") if err != nil { tctx.L().Warn("parse create database error, maybe tidb parser doesn't support it", zap.String("originSQL", originSQL), log.ShortError(err)) @@ -443,7 +472,10 @@ func adjustDatabaseCollation(tctx *tcontext.Context, parser *parser.Parser, orig } // adjustTableCollation adjusts table collation -func adjustTableCollation(tctx *tcontext.Context, parser *parser.Parser, originSQL string, charsetAndDefaultCollationMap map[string]string) (string, error) { +func adjustTableCollation(tctx *tcontext.Context, collationCompatible string, parser *parser.Parser, originSQL string, charsetAndDefaultCollationMap map[string]string) (string, error) { + if collationCompatible != StrictCollationCompatible { + return originSQL, nil + } stmt, err := parser.ParseOneStmt(originSQL, "", "") if err != nil { tctx.L().Warn("parse create table error, maybe tidb parser doesn't support it", zap.String("originSQL", originSQL), log.ShortError(err)) @@ -519,14 +551,14 @@ func adjustColumnsCollation(tctx *tcontext.Context, createStmt *ast.CreateTableS } } -func (d *Dumper) dumpTableData(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta, taskChan chan<- Task) error { +func (d *Dumper) dumpTableData(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, taskChan chan<- Task) error { conf := d.conf if conf.NoData { return nil } // Update total rows - fieldName, _ := pickupPossibleField(meta, conn) + fieldName, _ := pickupPossibleField(tctx, meta, conn) c := estimateCount(tctx, meta.DatabaseName(), meta.TableName(), conn, fieldName, conf) AddCounter(estimateTotalRowsCounter, conf.Labels, float64(c)) @@ -536,7 +568,7 @@ func (d *Dumper) dumpTableData(tctx *tcontext.Context, conn *sql.Conn, meta Tabl return d.concurrentDumpTable(tctx, conn, meta, taskChan) } -func (d *Dumper) buildConcatTask(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta) (*TaskTableData, error) { +func (d *Dumper) buildConcatTask(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) (*TaskTableData, error) { tableChan := make(chan Task, 128) errCh := make(chan error, 1) go func() { @@ -609,7 +641,7 @@ func (d *Dumper) dumpWholeTableDirectly(tctx *tcontext.Context, meta TableMeta, return nil } -func (d *Dumper) sequentialDumpTable(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta, taskChan chan<- Task) error { +func (d *Dumper) sequentialDumpTable(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, taskChan chan<- Task) error { conf := d.conf if conf.ServerInfo.ServerType == version.ServerTypeTiDB { task, err := d.buildConcatTask(tctx, conn, meta) @@ -627,7 +659,7 @@ func (d *Dumper) sequentialDumpTable(tctx *tcontext.Context, conn *sql.Conn, met zap.String("database", meta.DatabaseName()), zap.String("table", meta.TableName())) } - orderByClause, err := buildOrderByClause(conf, conn, meta.DatabaseName(), meta.TableName(), meta.HasImplicitRowID()) + orderByClause, err := buildOrderByClause(tctx, conf, conn, meta.DatabaseName(), meta.TableName(), meta.HasImplicitRowID()) if err != nil { return err } @@ -635,7 +667,7 @@ func (d *Dumper) sequentialDumpTable(tctx *tcontext.Context, conn *sql.Conn, met } // concurrentDumpTable tries to split table into several chunks to dump -func (d *Dumper) concurrentDumpTable(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta, taskChan chan<- Task) error { +func (d *Dumper) concurrentDumpTable(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, taskChan chan<- Task) error { conf := d.conf db, tbl := meta.DatabaseName(), meta.TableName() if conf.ServerInfo.ServerType == version.ServerTypeTiDB && @@ -652,12 +684,12 @@ func (d *Dumper) concurrentDumpTable(tctx *tcontext.Context, conn *sql.Conn, met } } - orderByClause, err := buildOrderByClause(conf, conn, db, tbl, meta.HasImplicitRowID()) + orderByClause, err := buildOrderByClause(tctx, conf, conn, db, tbl, meta.HasImplicitRowID()) if err != nil { return err } - field, err := pickupPossibleField(meta, conn) + field, err := pickupPossibleField(tctx, meta, conn) if err != nil || field == "" { // skip split chunk logic if not found proper field tctx.L().Info("fallback to sequential dump due to no proper field. This won't influence the whole dump process", @@ -680,7 +712,7 @@ func (d *Dumper) concurrentDumpTable(tctx *tcontext.Context, conn *sql.Conn, met return d.dumpWholeTableDirectly(tctx, meta, taskChan, "", orderByClause, 0, 1) } - min, max, err := d.selectMinAndMaxIntValue(conn, db, tbl, field) + min, max, err := d.selectMinAndMaxIntValue(tctx, conn, db, tbl, field) if err != nil { tctx.L().Info("fallback to sequential dump due to cannot get bounding values. This won't influence the whole dump process", log.ShortError(err)) @@ -738,8 +770,8 @@ func (d *Dumper) sendTaskToChan(tctx *tcontext.Context, task Task, taskChan chan } } -func (d *Dumper) selectMinAndMaxIntValue(conn *sql.Conn, db, tbl, field string) (*big.Int, *big.Int, error) { - tctx, conf, zero := d.tctx, d.conf, &big.Int{} +func (d *Dumper) selectMinAndMaxIntValue(tctx *tcontext.Context, conn *BaseConn, db, tbl, field string) (*big.Int, *big.Int, error) { + conf, zero := d.conf, &big.Int{} query := fmt.Sprintf("SELECT MIN(`%s`),MAX(`%s`) FROM `%s`.`%s`", escapeString(field), escapeString(field), escapeString(db), escapeString(tbl)) if conf.Where != "" { @@ -749,8 +781,11 @@ func (d *Dumper) selectMinAndMaxIntValue(conn *sql.Conn, db, tbl, field string) var smin sql.NullString var smax sql.NullString - row := conn.QueryRowContext(tctx, query) - err := row.Scan(&smin, &smax) + err := conn.QuerySQL(tctx, func(rows *sql.Rows) error { + err := rows.Scan(&smin, &smax) + rows.Close() + return err + }, func() {}, query) if err != nil { return zero, zero, errors.Annotatef(err, "can't get min/max values to split chunks, query: %s", query) } @@ -771,7 +806,7 @@ func (d *Dumper) selectMinAndMaxIntValue(conn *sql.Conn, db, tbl, field string) return min, max, nil } -func (d *Dumper) concurrentDumpTiDBTables(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta, taskChan chan<- Task) error { +func (d *Dumper) concurrentDumpTiDBTables(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, taskChan chan<- Task) error { db, tbl := meta.DatabaseName(), meta.TableName() var ( @@ -790,7 +825,7 @@ func (d *Dumper) concurrentDumpTiDBTables(tctx *tcontext.Context, conn *sql.Conn zap.String("database", db), zap.String("table", tbl)) var partitions []string if d.conf.ServerInfo.ServerVersion.Compare(*gcSafePointVersion) >= 0 { - partitions, err = GetPartitionNames(conn, db, tbl) + partitions, err = GetPartitionNames(tctx, conn, db, tbl) } if err == nil { if len(partitions) == 0 { @@ -806,7 +841,7 @@ func (d *Dumper) concurrentDumpTiDBTables(tctx *tcontext.Context, conn *sql.Conn return d.sendConcurrentDumpTiDBTasks(tctx, meta, taskChan, handleColNames, handleVals, "", 0, len(handleVals)+1) } -func (d *Dumper) concurrentDumpTiDBPartitionTables(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta, taskChan chan<- Task, partitions []string) error { +func (d *Dumper) concurrentDumpTiDBPartitionTables(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, taskChan chan<- Task, partitions []string) error { db, tbl := meta.DatabaseName(), meta.TableName() tctx.L().Debug("dumping TiDB tables with TABLE REGIONS for partition table", zap.String("database", db), zap.String("table", tbl), zap.Strings("partitions", partitions)) @@ -815,7 +850,7 @@ func (d *Dumper) concurrentDumpTiDBPartitionTables(tctx *tcontext.Context, conn totalChunk := 0 cachedHandleVals := make([][][]string, len(partitions)) - handleColNames, _, err := selectTiDBRowKeyFields(conn, meta, checkTiDBTableRegionPkFields) + handleColNames, _, err := selectTiDBRowKeyFields(tctx, conn, meta, checkTiDBTableRegionPkFields) if err != nil { return err } @@ -870,27 +905,28 @@ func (d *Dumper) L() log.Logger { return d.tctx.L() } -func selectTiDBTableSample(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { - pkFields, pkColTypes, err := selectTiDBRowKeyFields(conn, meta, nil) +func selectTiDBTableSample(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { + pkFields, pkColTypes, err := selectTiDBRowKeyFields(tctx, conn, meta, nil) if err != nil { return nil, nil, errors.Trace(err) } query := buildTiDBTableSampleQuery(pkFields, meta.DatabaseName(), meta.TableName()) - rows, err := conn.QueryContext(tctx, query) - if err != nil { - return nil, nil, errors.Trace(err) - } pkValNum := len(pkFields) - iter := newRowIter(rows, pkValNum) - defer iter.Close() + var iter SQLRowIter rowRec := MakeRowReceiver(pkColTypes) buf := new(bytes.Buffer) - for iter.HasNext() { + err = conn.QuerySQL(tctx, func(rows *sql.Rows) error { + if iter == nil { + iter = &rowIter{ + rows: rows, + args: make([]interface{}, pkValNum), + } + } err = iter.Decode(rowRec) if err != nil { - return nil, nil, errors.Trace(err) + return errors.Trace(err) } pkValRow := make([]string, 0, pkValNum) for _, rec := range rowRec.receivers { @@ -899,10 +935,21 @@ func selectTiDBTableSample(tctx *tcontext.Context, conn *sql.Conn, meta TableMet buf.Reset() } pkVals = append(pkVals, pkValRow) - iter.Next() + return nil + }, func() { + if iter != nil { + iter.Close() + iter = nil + } + rowRec = MakeRowReceiver(pkColTypes) + pkVals = pkVals[:0] + buf.Reset() + }, query) + if err == nil && iter != nil && iter.Error() != nil { + err = iter.Error() } - iter.Close() - return pkFields, pkVals, iter.Error() + + return pkFields, pkVals, err } func buildTiDBTableSampleQuery(pkFields []string, dbName, tblName string) string { @@ -915,11 +962,11 @@ func buildTiDBTableSampleQuery(pkFields []string, dbName, tblName string) string return fmt.Sprintf(template, pks, escapeString(dbName), escapeString(tblName), pks) } -func selectTiDBRowKeyFields(conn *sql.Conn, meta TableMeta, checkPkFields func([]string, []string) error) (pkFields, pkColTypes []string, err error) { +func selectTiDBRowKeyFields(tctx *tcontext.Context, conn *BaseConn, meta TableMeta, checkPkFields func([]string, []string) error) (pkFields, pkColTypes []string, err error) { if meta.HasImplicitRowID() { pkFields, pkColTypes = []string{"_tidb_rowid"}, []string{"BIGINT"} } else { - pkFields, pkColTypes, err = GetPrimaryKeyAndColumnTypes(conn, meta) + pkFields, pkColTypes, err = GetPrimaryKeyAndColumnTypes(tctx, conn, meta) if err == nil { if checkPkFields != nil { err = checkPkFields(pkFields, pkColTypes) @@ -940,8 +987,8 @@ func checkTiDBTableRegionPkFields(pkFields, pkColTypes []string) (err error) { return } -func selectTiDBTableRegion(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { - pkFields, _, err = selectTiDBRowKeyFields(conn, meta, checkTiDBTableRegionPkFields) +func selectTiDBTableRegion(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { + pkFields, _, err = selectTiDBRowKeyFields(tctx, conn, meta, checkTiDBTableRegionPkFields) if err != nil { return } @@ -956,7 +1003,7 @@ func selectTiDBTableRegion(tctx *tcontext.Context, conn *sql.Conn, meta TableMet ) dbName, tableName := meta.DatabaseName(), meta.TableName() logger := tctx.L().With(zap.String("database", dbName), zap.String("table", tableName)) - err = simpleQueryWithArgs(conn, func(rows *sql.Rows) error { + err = conn.QuerySQL(tctx, func(rows *sql.Rows) error { rowID++ err = rows.Scan(&startKey, &decodedKey) if err != nil { @@ -982,38 +1029,33 @@ func selectTiDBTableRegion(tctx *tcontext.Context, conn *sql.Conn, meta TableMet pkVals = append(pkVals, []string{pkVal}) } return nil + }, func() { + pkFields = pkFields[:0] + pkVals = pkVals[:0] }, tableRegionSQL, dbName, tableName) return pkFields, pkVals, errors.Trace(err) } -func selectTiDBPartitionRegion(tctx *tcontext.Context, conn *sql.Conn, dbName, tableName, partition string) (pkVals [][]string, err error) { - var ( - rows *sql.Rows - startKeys []string - ) +func selectTiDBPartitionRegion(tctx *tcontext.Context, conn *BaseConn, dbName, tableName, partition string) (pkVals [][]string, err error) { + var startKeys [][]string const ( partitionRegionSQL = "SHOW TABLE `%s`.`%s` PARTITION(`%s`) REGIONS" regionRowKey = "r_" ) logger := tctx.L().With(zap.String("database", dbName), zap.String("table", tableName), zap.String("partition", partition)) - rows, err = conn.QueryContext(tctx, fmt.Sprintf(partitionRegionSQL, escapeString(dbName), escapeString(tableName), escapeString(partition))) - if err != nil { - err = errors.Trace(err) - return - } - startKeys, err = GetSpecifiedColumnValueAndClose(rows, "START_KEY") + startKeys, err = conn.QuerySQLWithColumns(tctx, []string{"START_KEY"}, fmt.Sprintf(partitionRegionSQL, escapeString(dbName), escapeString(tableName), escapeString(partition))) if err != nil { return } for rowID, startKey := range startKeys { - if rowID == 0 { + if rowID == 0 || len(startKey) != 1 { continue } - pkVal, err2 := extractTiDBRowIDFromDecodedKey(regionRowKey, startKey) + pkVal, err2 := extractTiDBRowIDFromDecodedKey(regionRowKey, startKey[0]) if err2 != nil { logger.Debug("show table region start key doesn't have rowID", - zap.Int("rowID", rowID), zap.String("startKey", startKey), log.ShortError(err2)) + zap.Int("rowID", rowID), zap.String("startKey", startKey[0]), zap.Error(err2)) } else { pkVals = append(pkVals, []string{pkVal}) } @@ -1053,6 +1095,9 @@ func prepareTableListToDump(tctx *tcontext.Context, conf *Config, db *sql.Conn) if !conf.NoViews { tableTypes = append(tableTypes, TableTypeView) } + if !conf.NoSequences { + tableTypes = append(tableTypes, TableTypeSequence) + } ifSeqExists, err := CheckIfSeqExists(db) if err != nil { @@ -1060,7 +1105,6 @@ func prepareTableListToDump(tctx *tcontext.Context, conf *Config, db *sql.Conn) } var listType listTableType if ifSeqExists { - tctx.L().Warn("dumpling tableType `sequence` is unsupported for now") listType = listTableByShowFullTables } else { listType = getListTableTypeByConf(conf) @@ -1075,9 +1119,9 @@ func prepareTableListToDump(tctx *tcontext.Context, conf *Config, db *sql.Conn) return nil } -func dumpTableMeta(tctx *tcontext.Context, conf *Config, conn *sql.Conn, db string, table *TableInfo) (TableMeta, error) { +func dumpTableMeta(tctx *tcontext.Context, conf *Config, conn *BaseConn, db string, table *TableInfo) (TableMeta, error) { tbl := table.Name - selectField, selectLen, err := buildSelectField(conn, db, tbl, conf.CompleteInsert) + selectField, selectLen, err := buildSelectField(tctx, conn, db, tbl, conf.CompleteInsert) if err != nil { return nil, err } @@ -1086,17 +1130,19 @@ func dumpTableMeta(tctx *tcontext.Context, conf *Config, conn *sql.Conn, db stri hasImplicitRowID bool ) if conf.ServerInfo.ServerType == version.ServerTypeTiDB { - hasImplicitRowID, err = SelectTiDBRowID(conn, db, tbl) + hasImplicitRowID, err = SelectTiDBRowID(tctx, conn, db, tbl) if err != nil { tctx.L().Info("check implicit rowID failed", zap.String("database", db), zap.String("table", tbl), log.ShortError(err)) } } // If all columns are generated - if selectField == "" { - colTypes, err = GetColumnTypes(conn, "*", db, tbl) - } else { - colTypes, err = GetColumnTypes(conn, selectField, db, tbl) + if table.Type == TableTypeBase { + if selectField == "" { + colTypes, err = GetColumnTypes(tctx, conn, "*", db, tbl) + } else { + colTypes, err = GetColumnTypes(tctx, conn, selectField, db, tbl) + } } if err != nil { return nil, err @@ -1118,17 +1164,27 @@ func dumpTableMeta(tctx *tcontext.Context, conf *Config, conn *sql.Conn, db stri if conf.NoSchemas { return meta, nil } - if table.Type == TableTypeView { + switch table.Type { + case TableTypeView: viewName := table.Name - createTableSQL, createViewSQL, err1 := ShowCreateView(conn, db, viewName) + createTableSQL, createViewSQL, err1 := ShowCreateView(tctx, conn, db, viewName) if err1 != nil { return meta, err1 } meta.showCreateTable = createTableSQL meta.showCreateView = createViewSQL return meta, nil + case TableTypeSequence: + sequenceName := table.Name + createSequenceSQL, err2 := ShowCreateSequence(tctx, conn, db, sequenceName, conf) + if err2 != nil { + return meta, err2 + } + meta.showCreateTable = createSequenceSQL + return meta, nil } - createTableSQL, err := ShowCreateTable(conn, db, tbl) + + createTableSQL, err := ShowCreateTable(tctx, conn, db, tbl) if err != nil { return nil, err } @@ -1136,11 +1192,14 @@ func dumpTableMeta(tctx *tcontext.Context, conf *Config, conn *sql.Conn, db stri return meta, nil } -func (d *Dumper) dumpSQL(tctx *tcontext.Context, taskChan chan<- Task) { +func (d *Dumper) dumpSQL(tctx *tcontext.Context, metaConn *BaseConn, taskChan chan<- Task) { conf := d.conf meta := &tableMeta{} data := newTableData(conf.SQL, 0, true) task := NewTaskTableData(meta, data, 0, 1) + c := detectEstimateRows(tctx, metaConn, fmt.Sprintf("EXPLAIN %s", conf.SQL), []string{"rows", "estRows", "count"}) + AddCounter(estimateTotalRowsCounter, conf.Labels, float64(c)) + atomic.StoreInt64(&d.totalTables, int64(1)) d.sendTaskToChan(tctx, task, taskChan) } @@ -1424,7 +1483,7 @@ func (d *Dumper) renewSelectTableRegionFuncForLowerTiDB(tctx *tcontext.Context) // reference: https://github.com/pingcap/tidb/blob/c497d5c/dumpling/export/dump.go#L775 // To avoid this function continuously returning errors and confusing users because we fail to init this function at first, // selectTiDBTableRegionFunc is set to always return an ignorable error at first. - d.selectTiDBTableRegionFunc = func(_ *tcontext.Context, _ *sql.Conn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { + d.selectTiDBTableRegionFunc = func(_ *tcontext.Context, _ *BaseConn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { return nil, nil, errors.Annotatef(emptyHandleValsErr, "table: `%s`.`%s`", escapeString(meta.DatabaseName()), escapeString(meta.TableName())) } dbHandle, err := openDBFunc("mysql", conf.GetDSN("")) @@ -1490,8 +1549,8 @@ func (d *Dumper) renewSelectTableRegionFuncForLowerTiDB(tctx *tcontext.Context) } } - d.selectTiDBTableRegionFunc = func(tctx *tcontext.Context, conn *sql.Conn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { - pkFields, _, err = selectTiDBRowKeyFields(conn, meta, checkTiDBTableRegionPkFields) + d.selectTiDBTableRegionFunc = func(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) (pkFields []string, pkVals [][]string, err error) { + pkFields, _, err = selectTiDBRowKeyFields(tctx, conn, meta, checkTiDBTableRegionPkFields) if err != nil { return } diff --git a/dumpling/export/dump_test.go b/dumpling/export/dump_test.go index cdf32eb1e3cb5..dffcf5a407e1d 100644 --- a/dumpling/export/dump_test.go +++ b/dumpling/export/dump_test.go @@ -9,10 +9,10 @@ import ( "time" "github.com/DATA-DOG/go-sqlmock" - "github.com/pingcap/errors" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" + "github.com/pingcap/errors" "github.com/pingcap/tidb/br/pkg/version" tcontext "github.com/pingcap/tidb/dumpling/context" "github.com/pingcap/tidb/parser" @@ -26,6 +26,7 @@ func TestDumpBlock(t *testing.T) { }() mock.ExpectQuery(fmt.Sprintf("SHOW CREATE DATABASE `%s`", escapeString(database))). + WillDelayFor(time.Second). WillReturnRows(sqlmock.NewRows([]string{"Database", "Create Database"}). AddRow("test", "CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */")) mock.ExpectQuery(fmt.Sprintf("SELECT DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '%s'", escapeString(database))). @@ -36,6 +37,7 @@ func TestDumpBlock(t *testing.T) { defer cancel() conn, err := db.Conn(tctx) require.NoError(t, err) + baseConn := newBaseConn(conn, true, nil) d := &Dumper{ tctx: tctx, @@ -52,14 +54,16 @@ func TestDumpBlock(t *testing.T) { time.Sleep(time.Second) return context.Canceled }) + writerCtx := tctx.WithContext(writingCtx) // simulate taskChan is full taskChan := make(chan Task, 1) taskChan <- &TaskDatabaseMeta{} d.conf.Tables = DatabaseTables{}.AppendTable(database, nil) d.conf.ServerInfo.ServerType = version.ServerTypeMySQL - require.ErrorIs(t, d.dumpDatabases(writerCtx, conn, taskChan), context.Canceled) require.ErrorIs(t, wg.Wait(), writerErr) + // if writerCtx is canceled , QuerySQL in `dumpDatabases` will return sqlmock.ErrCancelled + require.ErrorIs(t, d.dumpDatabases(writerCtx, baseConn, taskChan), sqlmock.ErrCancelled) } func TestDumpTableMeta(t *testing.T) { @@ -73,6 +77,7 @@ func TestDumpTableMeta(t *testing.T) { defer cancel() conn, err := db.Conn(tctx) require.NoError(t, err) + baseConn := newBaseConn(conn, true, nil) conf := DefaultConfig() conf.NoSchemas = true @@ -90,7 +95,7 @@ func TestDumpTableMeta(t *testing.T) { } mock.ExpectQuery(fmt.Sprintf("SELECT \\* FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) - meta, err := dumpTableMeta(tctx, conf, conn, database, &TableInfo{Type: TableTypeBase, Name: table}) + meta, err := dumpTableMeta(tctx, conf, baseConn, database, &TableInfo{Type: TableTypeBase, Name: table}) require.NoError(t, err) require.Equal(t, database, meta.DatabaseName()) require.Equal(t, table, meta.TableName()) @@ -142,8 +147,15 @@ func TestAdjustDatabaseCollation(t *testing.T) { "CREATE DATABASE `test` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci", } charsetAndDefaultCollationMap := map[string]string{"utf8mb4": "utf8mb4_general_ci"} + + for _, originSQL := range originSQLs { + newSQL, err := adjustDatabaseCollation(tctx, LooseCollationCompatible, parser1, originSQL, charsetAndDefaultCollationMap) + require.NoError(t, err) + require.Equal(t, originSQL, newSQL) + } + for i, originSQL := range originSQLs { - newSQL, err := adjustDatabaseCollation(tctx, parser1, originSQL, charsetAndDefaultCollationMap) + newSQL, err := adjustDatabaseCollation(tctx, StrictCollationCompatible, parser1, originSQL, charsetAndDefaultCollationMap) require.NoError(t, err) require.Equal(t, expectedSQLs[i], newSQL) } @@ -182,9 +194,17 @@ func TestAdjustTableCollation(t *testing.T) { } charsetAndDefaultCollationMap := map[string]string{"utf8mb4": "utf8mb4_general_ci"} + + for _, originSQL := range originSQLs { + newSQL, err := adjustTableCollation(tctx, LooseCollationCompatible, parser1, originSQL, charsetAndDefaultCollationMap) + require.NoError(t, err) + require.Equal(t, originSQL, newSQL) + } + for i, originSQL := range originSQLs { - newSQL, err := adjustTableCollation(tctx, parser1, originSQL, charsetAndDefaultCollationMap) + newSQL, err := adjustTableCollation(tctx, StrictCollationCompatible, parser1, originSQL, charsetAndDefaultCollationMap) require.NoError(t, err) require.Equal(t, expectedSQLs[i], newSQL) } + } diff --git a/dumpling/export/main_test.go b/dumpling/export/main_test.go index 8ea24d1c51e82..0803bf84a8203 100644 --- a/dumpling/export/main_test.go +++ b/dumpling/export/main_test.go @@ -49,6 +49,7 @@ func TestMain(m *testing.M) { RegisterMetrics(registry) opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/dumpling/export/prepare.go b/dumpling/export/prepare.go index 777b366c65a78..1d9d05304c7cf 100644 --- a/dumpling/export/prepare.go +++ b/dumpling/export/prepare.go @@ -15,11 +15,12 @@ import ( ) const ( - outputFileTemplateSchema = "schema" - outputFileTemplateTable = "table" - outputFileTemplateView = "view" - outputFileTemplateData = "data" - outputFileTemplatePolicy = "placement-policy" + outputFileTemplateSchema = "schema" + outputFileTemplateTable = "table" + outputFileTemplateView = "view" + outputFileTemplateSequence = "sequence" + outputFileTemplateData = "data" + outputFileTemplatePolicy = "placement-policy" defaultOutputFileTemplateBase = ` {{- define "objectName" -}} diff --git a/dumpling/export/retry.go b/dumpling/export/retry.go index 13f4931d72a0c..b1866c06065d7 100644 --- a/dumpling/export/retry.go +++ b/dumpling/export/retry.go @@ -8,9 +8,10 @@ import ( "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" - "github.com/pingcap/tidb-tools/pkg/dbutil" + "github.com/pingcap/tidb/util/dbutil" "go.uber.org/zap" + "github.com/pingcap/tidb/br/pkg/utils" tcontext "github.com/pingcap/tidb/dumpling/context" ) @@ -23,9 +24,14 @@ const ( ErrNoSuchTable uint16 = 1146 ) -func newDumpChunkBackoffer(shouldRetry bool) *dumpChunkBackoffer { // revive:disable-line:flag-parameter +type backOfferResettable interface { + utils.Backoffer + Reset() +} + +func newRebuildConnBackOffer(shouldRetry bool) backOfferResettable { // revive:disable-line:flag-parameter if !shouldRetry { - return &dumpChunkBackoffer{ + return &noopBackoffer{ attempt: 1, } } @@ -47,10 +53,6 @@ func (b *dumpChunkBackoffer) NextBackoff(err error) time.Duration { if _, ok := err.(*mysql.MySQLError); ok && !dbutil.IsRetryableError(err) { b.attempt = 0 return 0 - } else if _, ok := err.(*writerError); ok { - // the uploader writer's retry logic is already done in aws client. needn't retry here - b.attempt = 0 - return 0 } b.delayTime = 2 * b.delayTime b.attempt-- @@ -64,6 +66,28 @@ func (b *dumpChunkBackoffer) Attempt() int { return b.attempt } +func (b *dumpChunkBackoffer) Reset() { + b.attempt = dumpChunkRetryTime + b.delayTime = dumpChunkWaitInterval +} + +type noopBackoffer struct { + attempt int +} + +func (b *noopBackoffer) NextBackoff(err error) time.Duration { + b.attempt-- + return time.Duration(0) +} + +func (b *noopBackoffer) Attempt() int { + return b.attempt +} + +func (b *noopBackoffer) Reset() { + b.attempt = 1 +} + func newLockTablesBackoffer(tctx *tcontext.Context, blockList map[string]map[string]interface{}) *lockTablesBackoffer { return &lockTablesBackoffer{ tctx: tctx, diff --git a/dumpling/export/sql.go b/dumpling/export/sql.go index 27a1bfb92c27f..430068a434021 100644 --- a/dumpling/export/sql.go +++ b/dumpling/export/sql.go @@ -16,11 +16,15 @@ import ( "github.com/go-sql-driver/mysql" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "go.uber.org/multierr" "go.uber.org/zap" + "github.com/pingcap/tidb/br/pkg/version" dbconfig "github.com/pingcap/tidb/config" tcontext "github.com/pingcap/tidb/dumpling/context" "github.com/pingcap/tidb/dumpling/log" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/helper" ) @@ -57,59 +61,63 @@ func ShowTables(db *sql.Conn) ([]string, error) { // ShowCreateDatabase constructs the create database SQL for a specified database // returns (createDatabaseSQL, error) -func ShowCreateDatabase(db *sql.Conn, database string) (string, error) { +func ShowCreateDatabase(tctx *tcontext.Context, db *BaseConn, database string) (string, error) { var oneRow [2]string handleOneRow := func(rows *sql.Rows) error { return rows.Scan(&oneRow[0], &oneRow[1]) } query := fmt.Sprintf("SHOW CREATE DATABASE `%s`", escapeString(database)) - err := simpleQuery(db, query, handleOneRow) - if mysqlErr, ok := errors.Cause(err).(*mysql.MySQLError); ok { - // Falling back to simple create statement for MemSQL/SingleStore, because of this: - // ERROR 1706 (HY000): Feature 'SHOW CREATE DATABASE' is not supported by MemSQL. - if mysqlErr.Number == 1706 { - return fmt.Sprintf("CREATE DATABASE `%s`", escapeString(database)), nil + err := db.QuerySQL(tctx, handleOneRow, func() { + oneRow[0], oneRow[1] = "", "" + }, query) + if multiErrs := multierr.Errors(err); len(multiErrs) > 0 { + for _, multiErr := range multiErrs { + if mysqlErr, ok := errors.Cause(multiErr).(*mysql.MySQLError); ok { + // Falling back to simple create statement for MemSQL/SingleStore, because of this: + // ERROR 1706 (HY000): Feature 'SHOW CREATE DATABASE' is not supported by MemSQL. + if strings.Contains(mysqlErr.Error(), "SHOW CREATE DATABASE") { + return fmt.Sprintf("CREATE DATABASE `%s`", escapeString(database)), nil + } + } } } - if err != nil { - return "", errors.Annotatef(err, "sql: %s", query) - } - return oneRow[1], nil + return oneRow[1], err } // ShowCreateTable constructs the create table SQL for a specified table // returns (createTableSQL, error) -func ShowCreateTable(db *sql.Conn, database, table string) (string, error) { +func ShowCreateTable(tctx *tcontext.Context, db *BaseConn, database, table string) (string, error) { var oneRow [2]string handleOneRow := func(rows *sql.Rows) error { return rows.Scan(&oneRow[0], &oneRow[1]) } query := fmt.Sprintf("SHOW CREATE TABLE `%s`.`%s`", escapeString(database), escapeString(table)) - err := simpleQuery(db, query, handleOneRow) + err := db.QuerySQL(tctx, handleOneRow, func() { + oneRow[0], oneRow[1] = "", "" + }, query) if err != nil { - return "", errors.Annotatef(err, "sql: %s", query) + return "", err } return oneRow[1], nil } // ShowCreatePlacementPolicy constructs the create policy SQL for a specified table -// returns (createPoilicySQL, error) -func ShowCreatePlacementPolicy(db *sql.Conn, policy string) (string, error) { +// returns (createPolicySQL, error) +func ShowCreatePlacementPolicy(tctx *tcontext.Context, db *BaseConn, policy string) (string, error) { var oneRow [2]string handleOneRow := func(rows *sql.Rows) error { return rows.Scan(&oneRow[0], &oneRow[1]) } query := fmt.Sprintf("SHOW CREATE PLACEMENT POLICY `%s`", escapeString(policy)) - err := simpleQuery(db, query, handleOneRow) - if err != nil { - return "", errors.Annotatef(err, "sql: %s", query) - } - return oneRow[1], nil + err := db.QuerySQL(tctx, handleOneRow, func() { + oneRow[0], oneRow[1] = "", "" + }, query) + return oneRow[1], err } // ShowCreateView constructs the create view SQL for a specified view // returns (createFakeTableSQL, createViewSQL, error) -func ShowCreateView(db *sql.Conn, database, view string) (createFakeTableSQL string, createRealViewSQL string, err error) { +func ShowCreateView(tctx *tcontext.Context, db *BaseConn, database, view string) (createFakeTableSQL string, createRealViewSQL string, err error) { var fieldNames []string handleFieldRow := func(rows *sql.Rows) error { var oneRow [6]sql.NullString @@ -130,9 +138,11 @@ func ShowCreateView(db *sql.Conn, database, view string) (createFakeTableSQL str // Build createTableSQL query := fmt.Sprintf("SHOW FIELDS FROM `%s`.`%s`", escapeString(database), escapeString(view)) - err = simpleQuery(db, query, handleFieldRow) + err = db.QuerySQL(tctx, handleFieldRow, func() { + fieldNames = []string{} + }, query) if err != nil { - return "", "", errors.Annotatef(err, "sql: %s", query) + return "", "", err } fmt.Fprintf(&createTableSQL, "CREATE TABLE `%s`(\n", escapeString(view)) createTableSQL.WriteString(strings.Join(fieldNames, ",\n")) @@ -142,9 +152,13 @@ func ShowCreateView(db *sql.Conn, database, view string) (createFakeTableSQL str fmt.Fprintf(&createViewSQL, "DROP TABLE IF EXISTS `%s`;\n", escapeString(view)) fmt.Fprintf(&createViewSQL, "DROP VIEW IF EXISTS `%s`;\n", escapeString(view)) query = fmt.Sprintf("SHOW CREATE VIEW `%s`.`%s`", escapeString(database), escapeString(view)) - err = simpleQuery(db, query, handleOneRow) + err = db.QuerySQL(tctx, handleOneRow, func() { + for i := range oneRow { + oneRow[i] = "" + } + }, query) if err != nil { - return "", "", errors.Annotatef(err, "sql: %s", query) + return "", "", err } // The result for `show create view` SQL // mysql> show create view v1; @@ -161,6 +175,60 @@ func ShowCreateView(db *sql.Conn, database, view string) (createFakeTableSQL str return createTableSQL.String(), createViewSQL.String(), nil } +// ShowCreateSequence constructs the create sequence SQL for a specified sequence +// returns (createSequenceSQL, error) +func ShowCreateSequence(tctx *tcontext.Context, db *BaseConn, database, sequence string, conf *Config) (string, error) { + var oneRow [2]string + handleOneRow := func(rows *sql.Rows) error { + return rows.Scan(&oneRow[0], &oneRow[1]) + } + var ( + createSequenceSQL strings.Builder + nextNotCachedValue int64 + ) + query := fmt.Sprintf("SHOW CREATE SEQUENCE `%s`.`%s`", escapeString(database), escapeString(sequence)) + err := db.QuerySQL(tctx, handleOneRow, func() { + oneRow[0], oneRow[1] = "", "" + }, query) + if err != nil { + return "", err + } + createSequenceSQL.WriteString(oneRow[1]) + createSequenceSQL.WriteString(";\n") + + switch conf.ServerInfo.ServerType { + case version.ServerTypeTiDB: + // Get next not allocated auto increment id of the whole cluster + query := fmt.Sprintf("SHOW TABLE `%s`.`%s` NEXT_ROW_ID", escapeString(database), escapeString(sequence)) + results, err := db.QuerySQLWithColumns(tctx, []string{"NEXT_GLOBAL_ROW_ID", "ID_TYPE"}, query) + if err != nil { + return "", err + } + for _, oneRow := range results { + nextGlobalRowId, idType := oneRow[0], oneRow[1] + if idType == "SEQUENCE" { + nextNotCachedValue, _ = strconv.ParseInt(nextGlobalRowId, 10, 64) + } + } + fmt.Fprintf(&createSequenceSQL, "SELECT SETVAL(`%s`,%d);\n", escapeString(sequence), nextNotCachedValue) + case version.ServerTypeMariaDB: + var oneRow1 string + handleOneRow1 := func(rows *sql.Rows) error { + return rows.Scan(&oneRow1) + } + query := fmt.Sprintf("SELECT NEXT_NOT_CACHED_VALUE FROM `%s`.`%s`", escapeString(database), escapeString(sequence)) + err := db.QuerySQL(tctx, handleOneRow1, func() { + oneRow1 = "" + }, query) + if err != nil { + return "", err + } + nextNotCachedValue, _ = strconv.ParseInt(oneRow1, 10, 64) + fmt.Fprintf(&createSequenceSQL, "SELECT SETVAL(`%s`,%d);\n", escapeString(sequence), nextNotCachedValue) + } + return createSequenceSQL.String(), nil +} + // SetCharset builds the set charset SQLs func SetCharset(w *strings.Builder, characterSet, collationConnection string) { w.WriteString("SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;\n") @@ -203,7 +271,7 @@ func ListAllDatabasesTables(tctx *tcontext.Context, db *sql.Conn, databaseNames for _, schema := range databaseNames { dbTables[schema] = make([]*TableInfo, 0) } - if err = simpleQueryWithArgs(db, func(rows *sql.Rows) error { + if err = simpleQueryWithArgs(tctx, db, func(rows *sql.Rows) error { var ( sqlAvgRowLength sql.NullInt64 err2 error @@ -234,7 +302,7 @@ func ListAllDatabasesTables(tctx *tcontext.Context, db *sql.Conn, databaseNames dbTables[schema] = make([]*TableInfo, 0) query := fmt.Sprintf("SHOW FULL TABLES FROM `%s` WHERE %s", escapeString(schema), strings.Join(tableTypeConditions, " OR ")) - if err = simpleQueryWithArgs(db, func(rows *sql.Rows) error { + if err = simpleQueryWithArgs(tctx, db, func(rows *sql.Rows) error { var err2 error if err2 = rows.Scan(&table, &tableTypeStr); err != nil { return errors.Trace(err2) @@ -294,23 +362,21 @@ func ListAllDatabasesTables(tctx *tcontext.Context, db *sql.Conn, databaseNames return dbTables, nil } -func ListAllPlacementPolicyNames(db *sql.Conn) ([]string, error) { +func ListAllPlacementPolicyNames(tctx *tcontext.Context, db *BaseConn) ([]string, error) { var policyList []string var policy string - const query = "select distinct policy_name from information_schema.placement_rules where policy_name is not null;" - rows, err := db.QueryContext(context.Background(), query) - if err != nil { - return policyList, errors.Annotatef(err, "sql: %s", query) - } - defer rows.Close() - for rows.Next() { + const query = "select distinct policy_name from information_schema.placement_policies where policy_name is not null;" + err := db.QuerySQL(tctx, func(rows *sql.Rows) error { err := rows.Scan(&policy) if err != nil { - return policyList, errors.Trace(err) + return errors.Trace(err) } policyList = append(policyList, policy) - } - return policyList, errors.Annotatef(rows.Err(), "sql: %s", query) + return nil + }, func() { + policyList = policyList[:0] + }, query) + return policyList, errors.Annotatef(err, "sql: %s", query) } // SelectVersion gets the version information from the database server @@ -370,14 +436,14 @@ func buildSelectQuery(database, table, fields, partition, where, orderByClause s return query.String() } -func buildOrderByClause(conf *Config, db *sql.Conn, database, table string, hasImplicitRowID bool) (string, error) { // revive:disable-line:flag-parameter +func buildOrderByClause(tctx *tcontext.Context, conf *Config, db *BaseConn, database, table string, hasImplicitRowID bool) (string, error) { // revive:disable-line:flag-parameter if !conf.SortByPk { return "", nil } if hasImplicitRowID { return orderByTiDBRowID, nil } - cols, err := GetPrimaryKeyColumns(db, database, table) + cols, err := GetPrimaryKeyColumns(tctx, db, database, table) if err != nil { return "", errors.Trace(err) } @@ -385,18 +451,22 @@ func buildOrderByClause(conf *Config, db *sql.Conn, database, table string, hasI } // SelectTiDBRowID checks whether this table has _tidb_rowid column -func SelectTiDBRowID(db *sql.Conn, database, table string) (bool, error) { - const errBadFieldCode = 1054 +func SelectTiDBRowID(tctx *tcontext.Context, db *BaseConn, database, table string) (bool, error) { tiDBRowIDQuery := fmt.Sprintf("SELECT _tidb_rowid from `%s`.`%s` LIMIT 1", escapeString(database), escapeString(table)) - _, err := db.ExecContext(context.Background(), tiDBRowIDQuery) - if err != nil { - errMsg := strings.ToLower(err.Error()) - if strings.Contains(errMsg, fmt.Sprintf("%d", errBadFieldCode)) { - return false, nil + hasImplictRowID := false + err := db.ExecSQL(tctx, func(_ sql.Result, err error) error { + if err != nil { + hasImplictRowID = false + errMsg := strings.ToLower(err.Error()) + if strings.Contains(errMsg, fmt.Sprintf("%d", errno.ErrBadField)) { + return nil + } + return errors.Annotatef(err, "sql: %s", tiDBRowIDQuery) } - return false, errors.Annotatef(err, "sql: %s", tiDBRowIDQuery) - } - return true, nil + hasImplictRowID = true + return nil + }, tiDBRowIDQuery) + return hasImplictRowID, err } // GetSuitableRows gets suitable rows for each table @@ -417,26 +487,35 @@ func GetSuitableRows(avgRowLength uint64) uint64 { } // GetColumnTypes gets *sql.ColumnTypes from a specified table -func GetColumnTypes(db *sql.Conn, fields, database, table string) ([]*sql.ColumnType, error) { +func GetColumnTypes(tctx *tcontext.Context, db *BaseConn, fields, database, table string) ([]*sql.ColumnType, error) { query := fmt.Sprintf("SELECT %s FROM `%s`.`%s` LIMIT 1", fields, escapeString(database), escapeString(table)) - rows, err := db.QueryContext(context.Background(), query) + var colTypes []*sql.ColumnType + err := db.QuerySQL(tctx, func(rows *sql.Rows) error { + var err error + colTypes, err = rows.ColumnTypes() + if err == nil { + err = rows.Close() + } + failpoint.Inject("ChaosBrokenMetaConn", func(_ failpoint.Value) { + failpoint.Return(errors.New("connection is closed")) + }) + return errors.Annotatef(err, "sql: %s", query) + }, func() { + colTypes = nil + }, query) if err != nil { - return nil, errors.Annotatef(err, "sql: %s", query) - } - defer rows.Close() - if err = rows.Err(); err != nil { - return nil, errors.Annotatef(err, "sql: %s", query) + return nil, err } - return rows.ColumnTypes() + return colTypes, nil } // GetPrimaryKeyAndColumnTypes gets all primary columns and their types in ordinal order -func GetPrimaryKeyAndColumnTypes(conn *sql.Conn, meta TableMeta) ([]string, []string, error) { +func GetPrimaryKeyAndColumnTypes(tctx *tcontext.Context, conn *BaseConn, meta TableMeta) ([]string, []string, error) { var ( colNames, colTypes []string err error ) - colNames, err = GetPrimaryKeyColumns(conn, meta.DatabaseName(), meta.TableName()) + colNames, err = GetPrimaryKeyColumns(tctx, conn, meta.DatabaseName(), meta.TableName()) if err != nil { return nil, nil, err } @@ -449,16 +528,13 @@ func GetPrimaryKeyAndColumnTypes(conn *sql.Conn, meta TableMeta) ([]string, []st } // GetPrimaryKeyColumns gets all primary columns in ordinal order -func GetPrimaryKeyColumns(db *sql.Conn, database, table string) ([]string, error) { +func GetPrimaryKeyColumns(tctx *tcontext.Context, db *BaseConn, database, table string) ([]string, error) { priKeyColsQuery := fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", escapeString(database), escapeString(table)) - rows, err := db.QueryContext(context.Background(), priKeyColsQuery) - if err != nil { - return nil, errors.Annotatef(err, "sql: %s", priKeyColsQuery) - } - results, err := GetSpecifiedColumnValuesAndClose(rows, "KEY_NAME", "COLUMN_NAME") + results, err := db.QuerySQLWithColumns(tctx, []string{"KEY_NAME", "COLUMN_NAME"}, priKeyColsQuery) if err != nil { - return nil, errors.Annotatef(err, "sql: %s", priKeyColsQuery) + return nil, err } + cols := make([]string, 0, len(results)) for _, oneRow := range results { keyName, columnName := oneRow[0], oneRow[1] @@ -472,17 +548,13 @@ func GetPrimaryKeyColumns(db *sql.Conn, database, table string) ([]string, error // getNumericIndex picks up indices according to the following priority: // primary key > unique key with the smallest count > key with the max cardinality // primary key with multi cols is before unique key with single col because we will sort result by primary keys -func getNumericIndex(db *sql.Conn, meta TableMeta) (string, error) { +func getNumericIndex(tctx *tcontext.Context, db *BaseConn, meta TableMeta) (string, error) { database, table := meta.DatabaseName(), meta.TableName() colName2Type := string2Map(meta.ColumnNames(), meta.ColumnTypes()) keyQuery := fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", escapeString(database), escapeString(table)) - rows, err := db.QueryContext(context.Background(), keyQuery) - if err != nil { - return "", errors.Annotatef(err, "sql: %s", keyQuery) - } - results, err := GetSpecifiedColumnValuesAndClose(rows, "NON_UNIQUE", "SEQ_IN_INDEX", "KEY_NAME", "COLUMN_NAME", "CARDINALITY") + results, err := db.QuerySQLWithColumns(tctx, []string{"NON_UNIQUE", "SEQ_IN_INDEX", "KEY_NAME", "COLUMN_NAME", "CARDINALITY"}, keyQuery) if err != nil { - return "", errors.Annotatef(err, "sql: %s", keyQuery) + return "", err } type keyColumnPair struct { colName string @@ -838,20 +910,14 @@ func createConnWithConsistency(ctx context.Context, db *sql.DB, repeatableRead b // buildSelectField returns the selecting fields' string(joined by comma(`,`)), // and the number of writable fields. -func buildSelectField(db *sql.Conn, dbName, tableName string, completeInsert bool) (string, int, error) { // revive:disable-line:flag-parameter +func buildSelectField(tctx *tcontext.Context, db *BaseConn, dbName, tableName string, completeInsert bool) (string, int, error) { // revive:disable-line:flag-parameter query := fmt.Sprintf("SHOW COLUMNS FROM `%s`.`%s`", escapeString(dbName), escapeString(tableName)) - rows, err := db.QueryContext(context.Background(), query) + results, err := db.QuerySQLWithColumns(tctx, []string{"FIELD", "EXTRA"}, query) if err != nil { - return "", 0, errors.Annotatef(err, "sql: %s", query) + return "", 0, err } - defer rows.Close() availableFields := make([]string, 0) - hasGenerateColumn := false - results, err := GetSpecifiedColumnValuesAndClose(rows, "FIELD", "EXTRA") - if err != nil { - return "", 0, errors.Annotatef(err, "sql: %s", query) - } for _, oneRow := range results { fieldName, extra := oneRow[0], oneRow[1] switch extra { @@ -1052,34 +1118,41 @@ func (o *oneStrColumnTable) handleOneRow(rows *sql.Rows) error { return nil } -func simpleQuery(conn *sql.Conn, sql string, handleOneRow func(*sql.Rows) error) error { - return simpleQueryWithArgs(conn, handleOneRow, sql) +func simpleQuery(conn *sql.Conn, query string, handleOneRow func(*sql.Rows) error) error { + return simpleQueryWithArgs(context.Background(), conn, handleOneRow, query) } -func simpleQueryWithArgs(conn *sql.Conn, handleOneRow func(*sql.Rows) error, sql string, args ...interface{}) error { - rows, err := conn.QueryContext(context.Background(), sql, args...) +func simpleQueryWithArgs(ctx context.Context, conn *sql.Conn, handleOneRow func(*sql.Rows) error, query string, args ...interface{}) error { + var ( + rows *sql.Rows + err error + ) + if len(args) > 0 { + rows, err = conn.QueryContext(ctx, query, args...) + } else { + rows, err = conn.QueryContext(ctx, query) + } if err != nil { - return errors.Annotatef(err, "sql: %s, args: %s", sql, args) + return errors.Annotatef(err, "sql: %s, args: %s", query, args) } defer rows.Close() for rows.Next() { if err := handleOneRow(rows); err != nil { rows.Close() - return errors.Annotatef(err, "sql: %s, args: %s", sql, args) + return errors.Annotatef(err, "sql: %s, args: %s", query, args) } } - rows.Close() - return errors.Annotatef(rows.Err(), "sql: %s, args: %s", sql, args) + return errors.Annotatef(rows.Err(), "sql: %s, args: %s", query, args) } -func pickupPossibleField(meta TableMeta, db *sql.Conn) (string, error) { +func pickupPossibleField(tctx *tcontext.Context, meta TableMeta, db *BaseConn) (string, error) { // try using _tidb_rowid first if meta.HasImplicitRowID() { return "_tidb_rowid", nil } // try to use pk or uk - fieldName, err := getNumericIndex(db, meta) + fieldName, err := getNumericIndex(tctx, db, meta) if err != nil { return "", err } @@ -1088,7 +1161,7 @@ func pickupPossibleField(meta TableMeta, db *sql.Conn) (string, error) { return fieldName, nil } -func estimateCount(tctx *tcontext.Context, dbName, tableName string, db *sql.Conn, field string, conf *Config) uint64 { +func estimateCount(tctx *tcontext.Context, dbName, tableName string, db *BaseConn, field string, conf *Config) uint64 { var query string if strings.TrimSpace(field) == "*" || strings.TrimSpace(field) == "" { query = fmt.Sprintf("EXPLAIN SELECT * FROM `%s`.`%s`", escapeString(dbName), escapeString(tableName)) @@ -1130,44 +1203,39 @@ func estimateCount(tctx *tcontext.Context, dbName, tableName string, db *sql.Con return 0 } -func detectEstimateRows(tctx *tcontext.Context, db *sql.Conn, query string, fieldNames []string) uint64 { - rows, err := db.QueryContext(tctx, query) - if err != nil { - tctx.L().Info("can't estimate rows from db", - zap.String("query", query), log.ShortError(err)) - return 0 - } - defer rows.Close() - rows.Next() - columns, err := rows.Columns() - if err != nil { - tctx.L().Info("can't get columns when estimate rows from db", - zap.String("query", query), log.ShortError(err)) - return 0 - } - err = rows.Err() - if err != nil { - tctx.L().Info("rows meet some error during the query when estimate rows", - zap.String("query", query), log.ShortError(err)) - return 0 - } - addr := make([]interface{}, len(columns)) - oneRow := make([]sql.NullString, len(columns)) - fieldIndex := -1 - for i := range oneRow { - addr[i] = &oneRow[i] - } -found: - for i := range oneRow { - for _, fieldName := range fieldNames { - if strings.EqualFold(columns[i], fieldName) { - fieldIndex = i - break found +func detectEstimateRows(tctx *tcontext.Context, db *BaseConn, query string, fieldNames []string) uint64 { + var ( + fieldIndex int + oneRow []sql.NullString + ) + err := db.QuerySQL(tctx, func(rows *sql.Rows) error { + columns, err := rows.Columns() + if err != nil { + return errors.Trace(err) + } + addr := make([]interface{}, len(columns)) + oneRow = make([]sql.NullString, len(columns)) + fieldIndex = -1 + found: + for i := range oneRow { + for _, fieldName := range fieldNames { + if strings.EqualFold(columns[i], fieldName) { + fieldIndex = i + break found + } } } - } - err = rows.Scan(addr...) - if err != nil || fieldIndex < 0 { + if fieldIndex == -1 { + rows.Close() + return nil + } + + for i := range oneRow { + addr[i] = &oneRow[i] + } + return rows.Scan(addr...) + }, func() {}, query) + if err != nil || fieldIndex == -1 { tctx.L().Info("can't estimate rows from db", zap.String("query", query), zap.Int("fieldIndex", fieldIndex), log.ShortError(err)) return 0 @@ -1176,10 +1244,9 @@ found: estRows, err := strconv.ParseFloat(oneRow[fieldIndex].String, 64) if err != nil { tctx.L().Info("can't get parse estimate rows from db", - zap.String("query", query), log.ShortError(err)) + zap.String("query", query), zap.String("estRows", oneRow[fieldIndex].String), log.ShortError(err)) return 0 } - return uint64(estRows) } @@ -1231,10 +1298,10 @@ func escapeString(s string) string { } // GetPartitionNames get partition names from a specified table -func GetPartitionNames(db *sql.Conn, schema, table string) (partitions []string, err error) { +func GetPartitionNames(tctx *tcontext.Context, db *BaseConn, schema, table string) (partitions []string, err error) { partitions = make([]string, 0) var partitionName sql.NullString - err = simpleQueryWithArgs(db, func(rows *sql.Rows) error { + err = db.QuerySQL(tctx, func(rows *sql.Rows) error { err := rows.Scan(&partitionName) if err != nil { return errors.Trace(err) @@ -1243,6 +1310,8 @@ func GetPartitionNames(db *sql.Conn, schema, table string) (partitions []string, partitions = append(partitions, partitionName.String) } return nil + }, func() { + partitions = partitions[:0] }, "SELECT PARTITION_NAME from INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?", schema, table) return } @@ -1438,5 +1507,8 @@ func GetCharsetAndDefaultCollation(ctx context.Context, db *sql.Conn) (map[strin if err = rows.Close(); err != nil { return nil, errors.Annotatef(err, "sql: %s", query) } + if rows.Err() != nil { + return nil, errors.Annotatef(err, "sql: %s", query) + } return charsetAndDefaultCollation, err } diff --git a/dumpling/export/sql_test.go b/dumpling/export/sql_test.go index 4fd8cb31276b8..82ba0addeab49 100644 --- a/dumpling/export/sql_test.go +++ b/dumpling/export/sql_test.go @@ -20,7 +20,6 @@ import ( "github.com/go-sql-driver/mysql" "github.com/DATA-DOG/go-sqlmock" - "github.com/coreos/go-semver/semver" "github.com/pingcap/errors" "github.com/stretchr/testify/require" @@ -65,15 +64,17 @@ func TestBuildSelectAllQuery(t *testing.T) { // Test TiDB server. mockConf.ServerInfo.ServerType = version.ServerTypeTiDB + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) - orderByClause, err := buildOrderByClause(mockConf, conn, database, table, true) + orderByClause, err := buildOrderByClause(tctx, mockConf, baseConn, database, table, true) require.NoError(t, err) mock.ExpectQuery("SHOW COLUMNS FROM"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err := buildSelectField(conn, database, table, false) + selectedField, _, err := buildSelectField(tctx, baseConn, database, table, false) require.NoError(t, err) q := buildSelectQuery(database, table, selectedField, "", "", orderByClause) @@ -83,14 +84,14 @@ func TestBuildSelectAllQuery(t *testing.T) { WillReturnRows(sqlmock.NewRows(showIndexHeaders). AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", "")) - orderByClause, err = buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err) mock.ExpectQuery("SHOW COLUMNS FROM"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err = buildSelectField(conn, database, table, false) + selectedField, _, err = buildSelectField(tctx, baseConn, database, table, false) require.NoError(t, err) q = buildSelectQuery(database, table, selectedField, "", "", orderByClause) @@ -108,14 +109,14 @@ func TestBuildSelectAllQuery(t *testing.T) { mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows(showIndexHeaders). AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", "")) - orderByClause, err := buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err := buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err, comment) mock.ExpectQuery("SHOW COLUMNS FROM"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err = buildSelectField(conn, database, table, false) + selectedField, _, err = buildSelectField(tctx, baseConn, database, table, false) require.NoError(t, err, comment) q = buildSelectQuery(database, table, selectedField, "", "", orderByClause) @@ -134,14 +135,14 @@ func TestBuildSelectAllQuery(t *testing.T) { mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows(showIndexHeaders)) - orderByClause, err := buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err := buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err, comment) mock.ExpectQuery("SHOW COLUMNS FROM"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err = buildSelectField(conn, "test", "t", false) + selectedField, _, err = buildSelectField(tctx, baseConn, "test", "t", false) require.NoError(t, err, comment) q := buildSelectQuery(database, table, selectedField, "", "", orderByClause) @@ -162,7 +163,7 @@ func TestBuildSelectAllQuery(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err := buildSelectField(conn, "test", "t", false) + selectedField, _, err := buildSelectField(tctx, baseConn, "test", "t", false) require.NoError(t, err, comment) q := buildSelectQuery(database, table, selectedField, "", "", "") @@ -180,6 +181,8 @@ func TestBuildOrderByClause(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) mockConf := defaultConfigForTest(t) mockConf.SortByPk = true @@ -187,21 +190,21 @@ func TestBuildOrderByClause(t *testing.T) { // Test TiDB server. mockConf.ServerInfo.ServerType = version.ServerTypeTiDB - orderByClause, err := buildOrderByClause(mockConf, conn, database, table, true) + orderByClause, err := buildOrderByClause(tctx, mockConf, baseConn, database, table, true) require.NoError(t, err) require.Equal(t, orderByTiDBRowID, orderByClause) mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows(showIndexHeaders).AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", "")) - orderByClause, err = buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err) require.Equal(t, "ORDER BY `id`", orderByClause) // Test table with primary key. mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows(showIndexHeaders).AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", "")) - orderByClause, err = buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err) require.Equal(t, "ORDER BY `id`", orderByClause) @@ -210,7 +213,7 @@ func TestBuildOrderByClause(t *testing.T) { WillReturnRows(sqlmock.NewRows(showIndexHeaders). AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", ""). AddRow(table, 0, "PRIMARY", 2, "name", "A", 0, nil, nil, "", "BTREE", "", "")) - orderByClause, err = buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err) require.Equal(t, "ORDER BY `id`,`name`", orderByClause) @@ -218,7 +221,7 @@ func TestBuildOrderByClause(t *testing.T) { mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)). WillReturnRows(sqlmock.NewRows(showIndexHeaders)) - orderByClause, err = buildOrderByClause(mockConf, conn, database, table, false) + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) require.NoError(t, err) require.Equal(t, "", orderByClause) @@ -227,10 +230,24 @@ func TestBuildOrderByClause(t *testing.T) { for _, hasImplicitRowID := range []bool{false, true} { comment := fmt.Sprintf("current hasImplicitRowID: %v", hasImplicitRowID) - orderByClause, err := buildOrderByClause(mockConf, conn, database, table, hasImplicitRowID) + orderByClause, err := buildOrderByClause(tctx, mockConf, baseConn, database, table, hasImplicitRowID) require.NoError(t, err, comment) require.Equal(t, "", orderByClause, comment) } + + // Test build OrderByClause with retry + baseConn = newBaseConn(conn, true, func(conn *sql.Conn, b bool) (*sql.Conn, error) { + return conn, nil + }) + query := fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table) + mock.ExpectQuery(query).WillReturnError(errors.New("invalid connection")) + mock.ExpectQuery(query).WillReturnError(errors.New("invalid connection")) + mock.ExpectQuery(query).WillReturnRows(sqlmock.NewRows(showIndexHeaders).AddRow(table, 0, "PRIMARY", 1, "id", "A", 0, nil, nil, "", "BTREE", "", "")) + mockConf.SortByPk = true + orderByClause, err = buildOrderByClause(tctx, mockConf, baseConn, database, table, false) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) + require.Equal(t, "ORDER BY `id`", orderByClause) } func TestBuildSelectField(t *testing.T) { @@ -242,13 +259,15 @@ func TestBuildSelectField(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) // generate columns not found mock.ExpectQuery("SHOW COLUMNS FROM"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). AddRow("id", "int(11)", "NO", "PRI", nil, "")) - selectedField, _, err := buildSelectField(conn, "test", "t", false) + selectedField, _, err := buildSelectField(tctx, baseConn, "test", "t", false) require.Equal(t, "*", selectedField) require.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) @@ -260,7 +279,7 @@ func TestBuildSelectField(t *testing.T) { AddRow("name", "varchar(12)", "NO", "", nil, ""). AddRow("quo`te", "varchar(12)", "NO", "UNI", nil, "")) - selectedField, _, err = buildSelectField(conn, "test", "t", true) + selectedField, _, err = buildSelectField(tctx, baseConn, "test", "t", true) require.Equal(t, "`id`,`name`,`quo``te`", selectedField) require.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) @@ -273,10 +292,25 @@ func TestBuildSelectField(t *testing.T) { AddRow("quo`te", "varchar(12)", "NO", "UNI", nil, ""). AddRow("generated", "varchar(12)", "NO", "", nil, "VIRTUAL GENERATED")) - selectedField, _, err = buildSelectField(conn, "test", "t", false) + selectedField, _, err = buildSelectField(tctx, baseConn, "test", "t", false) require.Equal(t, "`id`,`name`,`quo``te`", selectedField) require.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) + + // Test build SelectField with retry + baseConn = newBaseConn(conn, true, func(conn *sql.Conn, b bool) (*sql.Conn, error) { + return conn, nil + }) + mock.ExpectQuery("SHOW COLUMNS FROM").WillReturnError(errors.New("invalid connection")) + mock.ExpectQuery("SHOW COLUMNS FROM").WillReturnError(errors.New("invalid connection")) + mock.ExpectQuery("SHOW COLUMNS FROM"). + WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). + AddRow("id", "int(11)", "NO", "PRI", nil, "")) + + selectedField, _, err = buildSelectField(tctx, baseConn, "test", "t", false) + require.Equal(t, "*", selectedField) + require.NoError(t, err) + require.NoError(t, mock.ExpectationsWereMet()) } func TestParseSnapshotToTSO(t *testing.T) { @@ -316,6 +350,8 @@ func TestShowCreateView(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) mock.ExpectQuery("SHOW FIELDS FROM `test`.`v`"). WillReturnRows(sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}). @@ -325,13 +361,53 @@ func TestShowCreateView(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"View", "Create View", "character_set_client", "collation_connection"}). AddRow("v", "CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` (`a`) AS SELECT `t`.`a` AS `a` FROM `test`.`t`", "utf8", "utf8_general_ci")) - createTableSQL, createViewSQL, err := ShowCreateView(conn, "test", "v") + createTableSQL, createViewSQL, err := ShowCreateView(tctx, baseConn, "test", "v") require.NoError(t, err) require.Equal(t, "CREATE TABLE `v`(\n`a` int\n)ENGINE=MyISAM;\n", createTableSQL) require.Equal(t, "DROP TABLE IF EXISTS `v`;\nDROP VIEW IF EXISTS `v`;\nSET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;\nSET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;\nSET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;\nSET character_set_client = utf8;\nSET character_set_results = utf8;\nSET collation_connection = utf8_general_ci;\nCREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` (`a`) AS SELECT `t`.`a` AS `a` FROM `test`.`t`;\nSET character_set_client = @PREV_CHARACTER_SET_CLIENT;\nSET character_set_results = @PREV_CHARACTER_SET_RESULTS;\nSET collation_connection = @PREV_COLLATION_CONNECTION;\n", createViewSQL) require.NoError(t, mock.ExpectationsWereMet()) } +func TestShowCreateSequence(t *testing.T) { + conf := defaultConfigForTest(t) + db, mock, err := sqlmock.New() + require.NoError(t, err) + defer func() { + require.NoError(t, db.Close()) + }() + + conn, err := db.Conn(context.Background()) + require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) + + conf.ServerInfo.ServerType = version.ServerTypeTiDB + mock.ExpectQuery("SHOW CREATE SEQUENCE `test`.`s`"). + WillReturnRows(sqlmock.NewRows([]string{"Sequence", "Create Sequence"}). + AddRow("s", "CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB")) + mock.ExpectQuery("SHOW TABLE `test`.`s` NEXT_ROW_ID"). + WillReturnRows(sqlmock.NewRows([]string{"DB_NAME", "TABLE_NAME", "COLUMN_NAME", "NEXT_GLOBAL_ROW_ID", "ID_TYPE"}). + AddRow("test", "s", nil, 1001, "SEQUENCE")) + + createSequenceSQL, err := ShowCreateSequence(tctx, baseConn, "test", "s", conf) + require.NoError(t, err) + require.Equal(t, "CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;\nSELECT SETVAL(`s`,1001);\n", createSequenceSQL) + require.NoError(t, mock.ExpectationsWereMet()) + + conf.ServerInfo.ServerType = version.ServerTypeMariaDB + mock.ExpectQuery("SHOW CREATE SEQUENCE `test`.`s`"). + WillReturnRows(sqlmock.NewRows([]string{"Table", "Create Table"}). + AddRow("s", "CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB")) + mock.ExpectQuery("SELECT NEXT_NOT_CACHED_VALUE FROM `test`.`s`"). + WillReturnRows(sqlmock.NewRows([]string{"next_not_cached_value"}). + AddRow(1001)) + + createSequenceSQL, err = ShowCreateSequence(tctx, baseConn, "test", "s", conf) + require.NoError(t, err) + require.Equal(t, "CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;\nSELECT SETVAL(`s`,1001);\n", createSequenceSQL) + require.NoError(t, mock.ExpectationsWereMet()) +} + func TestShowCreatePolicy(t *testing.T) { db, mock, err := sqlmock.New() require.NoError(t, err) @@ -339,14 +415,16 @@ func TestShowCreatePolicy(t *testing.T) { require.NoError(t, db.Close()) }() + tctx := tcontext.Background().WithLogger(appLogger) conn, err := db.Conn(context.Background()) require.NoError(t, err) + baseConn := newBaseConn(conn, true, nil) mock.ExpectQuery("SHOW CREATE PLACEMENT POLICY `policy_x`"). WillReturnRows(sqlmock.NewRows([]string{"Policy", "Create Policy"}). AddRow("policy_x", "CREATE PLACEMENT POLICY `policy_x` LEARNERS=1")) - createPolicySQL, err := ShowCreatePlacementPolicy(conn, "policy_x") + createPolicySQL, err := ShowCreatePlacementPolicy(tctx, baseConn, "policy_x") require.NoError(t, err) require.Equal(t, "CREATE PLACEMENT POLICY `policy_x` LEARNERS=1", createPolicySQL) require.NoError(t, mock.ExpectationsWereMet()) @@ -360,22 +438,24 @@ func TestListPolicyNames(t *testing.T) { require.NoError(t, db.Close()) }() + tctx := tcontext.Background().WithLogger(appLogger) conn, err := db.Conn(context.Background()) + baseConn := newBaseConn(conn, true, nil) require.NoError(t, err) - mock.ExpectQuery("select distinct policy_name from information_schema.placement_rules where policy_name is not null;"). + mock.ExpectQuery("select distinct policy_name from information_schema.placement_policies where policy_name is not null;"). WillReturnRows(sqlmock.NewRows([]string{"policy_name"}). AddRow("policy_x")) - policies, err := ListAllPlacementPolicyNames(conn) + policies, err := ListAllPlacementPolicyNames(tctx, baseConn) require.NoError(t, err) require.Equal(t, []string{"policy_x"}, policies) require.NoError(t, mock.ExpectationsWereMet()) // some old tidb version doesn't support placement rules returns error - expectedErr := &mysql.MySQLError{Number: ErrNoSuchTable, Message: "Table 'information_schema.placement_rules' doesn't exist"} - mock.ExpectExec("select distinct policy_name from information_schema.placement_rules where policy_name is not null;"). + expectedErr := &mysql.MySQLError{Number: ErrNoSuchTable, Message: "Table 'information_schema.placement_policies' doesn't exist"} + mock.ExpectExec("select distinct policy_name from information_schema.placement_policies where policy_name is not null;"). WillReturnError(expectedErr) - policies, err = ListAllPlacementPolicyNames(conn) + _, err = ListAllPlacementPolicyNames(tctx, baseConn) if mysqlErr, ok := err.(*mysql.MySQLError); ok { require.Equal(t, mysqlErr.Number, ErrNoSuchTable) } @@ -418,20 +498,22 @@ func TestSelectTiDBRowID(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) database, table := "test", "t" // _tidb_rowid is unavailable, or PKIsHandle. mock.ExpectExec("SELECT _tidb_rowid from `test`.`t`"). WillReturnError(errors.New(`1054, "Unknown column '_tidb_rowid' in 'field list'"`)) - hasImplicitRowID, err := SelectTiDBRowID(conn, database, table) + hasImplicitRowID, err := SelectTiDBRowID(tctx, baseConn, database, table) require.NoError(t, err) require.False(t, hasImplicitRowID) // _tidb_rowid is available. mock.ExpectExec("SELECT _tidb_rowid from `test`.`t`"). WillReturnResult(sqlmock.NewResult(0, 0)) - hasImplicitRowID, err = SelectTiDBRowID(conn, database, table) + hasImplicitRowID, err = SelectTiDBRowID(tctx, baseConn, database, table) require.NoError(t, err) require.True(t, hasImplicitRowID) @@ -439,7 +521,7 @@ func TestSelectTiDBRowID(t *testing.T) { expectedErr := errors.New("mock error") mock.ExpectExec("SELECT _tidb_rowid from `test`.`t`"). WillReturnError(expectedErr) - hasImplicitRowID, err = SelectTiDBRowID(conn, database, table) + hasImplicitRowID, err = SelectTiDBRowID(tctx, baseConn, database, table) require.ErrorIs(t, errors.Cause(err), expectedErr) require.False(t, hasImplicitRowID) } @@ -453,7 +535,7 @@ func TestBuildTableSampleQueries(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) - + baseConn := newBaseConn(conn, true, nil) tctx, cancel := tcontext.Background().WithLogger(appLogger).WithCancel() d := &Dumper{ @@ -731,7 +813,7 @@ func TestBuildTableSampleQueries(t *testing.T) { } } - require.NoError(t, d.concurrentDumpTable(tctx, conn, meta, taskChan)) + require.NoError(t, d.concurrentDumpTable(tctx, baseConn, meta, taskChan)) require.NoError(t, mock.ExpectationsWereMet()) orderByClause := buildOrderByClauseString(handleColNames) @@ -863,7 +945,7 @@ func TestBuildRegionQueriesWithoutPartition(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) - + baseConn := newBaseConn(conn, true, nil) tctx, cancel := tcontext.Background().WithLogger(appLogger).WithCancel() d := &Dumper{ @@ -997,7 +1079,7 @@ func TestBuildRegionQueriesWithoutPartition(t *testing.T) { mock.ExpectQuery(fmt.Sprintf("SHOW INDEX FROM `%s`.`%s`", database, table)).WillReturnRows(rows) mock.ExpectQuery("SHOW INDEX FROM").WillReturnRows(sqlmock.NewRows(showIndexHeaders)) } - require.NoError(t, d.concurrentDumpTable(tctx, conn, meta, taskChan)) + require.NoError(t, d.concurrentDumpTable(tctx, baseConn, meta, taskChan)) require.NoError(t, mock.ExpectationsWereMet()) for i, w := range testCase.expectedWhereClauses { @@ -1022,7 +1104,7 @@ func TestBuildRegionQueriesWithPartitions(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) - + baseConn := newBaseConn(conn, true, nil) tctx, cancel := tcontext.Background().WithLogger(appLogger).WithCancel() d := &Dumper{ @@ -1195,7 +1277,7 @@ func TestBuildRegionQueriesWithPartitions(t *testing.T) { } orderByClause := buildOrderByClauseString(handleColNames) - require.NoError(t, d.concurrentDumpTable(tctx, conn, meta, taskChan)) + require.NoError(t, d.concurrentDumpTable(tctx, baseConn, meta, taskChan)) require.NoError(t, mock.ExpectationsWereMet()) chunkIdx := 0 @@ -1257,7 +1339,7 @@ func TestBuildVersion3RegionQueries(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) - + baseConn := newBaseConn(conn, true, nil) tctx, cancel := tcontext.Background().WithLogger(appLogger).WithCancel() oldOpenFunc := openDBFunc defer func() { @@ -1503,7 +1585,7 @@ func TestBuildVersion3RegionQueries(t *testing.T) { } orderByClause := buildOrderByClauseString(handleColNames) - require.NoError(t, d.concurrentDumpTable(tctx, conn, meta, taskChan)) + require.NoError(t, d.concurrentDumpTable(tctx, baseConn, meta, taskChan)) require.NoError(t, mock.ExpectationsWereMet()) chunkIdx := 0 @@ -1579,6 +1661,8 @@ func TestPickupPossibleField(t *testing.T) { conn, err := db.Conn(context.Background()) require.NoError(t, err) + tctx := tcontext.Background().WithLogger(appLogger) + baseConn := newBaseConn(conn, true, nil) meta := &mockTableIR{ dbName: database, @@ -1702,7 +1786,7 @@ func TestPickupPossibleField(t *testing.T) { mock.ExpectQuery(query).WillReturnRows(rows) } - field, err := pickupPossibleField(meta, conn) + field, err := pickupPossibleField(tctx, meta, baseConn) if expectedErr != nil { require.ErrorIs(t, err, expectedErr) } else { @@ -1760,13 +1844,3 @@ func TestGetCharsetAndDefaultCollation(t *testing.T) { require.Equal(t, "utf8mb4_0900_ai_ci", charsetAndDefaultCollation["utf8mb4"]) require.Equal(t, "latin1_swedish_ci", charsetAndDefaultCollation["latin1"]) } - -func makeVersion(major, minor, patch int64, preRelease string) *semver.Version { - return &semver.Version{ - Major: major, - Minor: minor, - Patch: patch, - PreRelease: semver.PreRelease(preRelease), - Metadata: "", - } -} diff --git a/dumpling/export/sql_type.go b/dumpling/export/sql_type.go index 511fd43870750..d12a8e61757c4 100644 --- a/dumpling/export/sql_type.go +++ b/dumpling/export/sql_type.go @@ -11,10 +11,9 @@ import ( var colTypeRowReceiverMap = map[string]func() RowReceiverStringer{} var ( - nullValue = "NULL" - quotationMark = []byte{'\''} - twoQuotationMarks = []byte{'\'', '\''} - doubleQuotationMark = []byte{'"'} + nullValue = "NULL" + quotationMark = []byte{'\''} + twoQuotationMarks = []byte{'\'', '\''} ) // There are two kinds of scenes to use this dataType diff --git a/dumpling/export/task.go b/dumpling/export/task.go index a9e5874fa350b..36d88c3e3454c 100644 --- a/dumpling/export/task.go +++ b/dumpling/export/task.go @@ -34,6 +34,14 @@ type TaskViewMeta struct { CreateViewSQL string } +// TaskSequenceMeta is a dumping sequence metadata task +type TaskSequenceMeta struct { + Task + DatabaseName string + SequenceName string + CreateSequenceSQL string +} + // TaskPolicyMeta is a dumping view metadata task type TaskPolicyMeta struct { Task @@ -77,6 +85,15 @@ func NewTaskViewMeta(dbName, tblName, createTableSQL, createViewSQL string) *Tas } } +// NewTaskSequenceMeta returns a new dumping sequence metadata task +func NewTaskSequenceMeta(dbName, tblName, createSequenceSQL string) *TaskSequenceMeta { + return &TaskSequenceMeta{ + DatabaseName: dbName, + SequenceName: tblName, + CreateSequenceSQL: createSequenceSQL, + } +} + // NewTaskPolicyMeta returns a new dumping placement policy metadata task func NewTaskPolicyMeta(policyName, createPolicySQL string) *TaskPolicyMeta { return &TaskPolicyMeta{ @@ -110,6 +127,11 @@ func (t *TaskViewMeta) Brief() string { return fmt.Sprintf("meta of view '%s'.'%s'", t.DatabaseName, t.ViewName) } +// Brief implements task.Brief +func (t *TaskSequenceMeta) Brief() string { + return fmt.Sprintf("meta of sequence '%s'.'%s'", t.DatabaseName, t.SequenceName) +} + // Brief implements task.Brief func (t *TaskPolicyMeta) Brief() string { return fmt.Sprintf("meta of placement policy '%s'", t.PolicyName) diff --git a/dumpling/export/util.go b/dumpling/export/util.go index 2b4875679df97..cd91008139284 100644 --- a/dumpling/export/util.go +++ b/dumpling/export/util.go @@ -10,7 +10,7 @@ import ( "time" "github.com/pingcap/errors" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "github.com/pingcap/tidb/br/pkg/version" tcontext "github.com/pingcap/tidb/dumpling/context" diff --git a/dumpling/export/test_util.go b/dumpling/export/util_for_test.go similarity index 100% rename from dumpling/export/test_util.go rename to dumpling/export/util_for_test.go diff --git a/dumpling/export/writer.go b/dumpling/export/writer.go index 7520ff670462f..2f0668adc580b 100644 --- a/dumpling/export/writer.go +++ b/dumpling/export/writer.go @@ -29,7 +29,7 @@ type Writer struct { receivedTaskCount int - rebuildConnFn func(*sql.Conn) (*sql.Conn, error) + rebuildConnFn func(*sql.Conn, bool) (*sql.Conn, error) finishTaskCallBack func(Task) finishTableCallBack func(Task) } @@ -99,6 +99,8 @@ func (w *Writer) handleTask(task Task) error { return w.WriteTableMeta(t.DatabaseName, t.TableName, t.CreateTableSQL) case *TaskViewMeta: return w.WriteViewMeta(t.DatabaseName, t.ViewName, t.CreateTableSQL, t.CreateViewSQL) + case *TaskSequenceMeta: + return w.WriteSequenceMeta(t.DatabaseName, t.SequenceName, t.CreateSequenceSQL) case *TaskPolicyMeta: return w.WritePolicyMeta(t.PolicyName, t.CreatePolicySQL) case *TaskTableData: @@ -164,6 +166,16 @@ func (w *Writer) WriteViewMeta(db, view, createTableSQL, createViewSQL string) e return writeMetaToFile(tctx, db, createViewSQL, w.extStorage, fileNameView+".sql", conf.CompressType) } +// WriteSequenceMeta writes sequence meta to a file +func (w *Writer) WriteSequenceMeta(db, sequence, createSQL string) error { + tctx, conf := w.tctx, w.conf + fileName, err := (&outputFileNamer{DB: db, Table: sequence}).render(conf.OutputFileTemplate, outputFileTemplateSequence) + if err != nil { + return err + } + return writeMetaToFile(tctx, db, createSQL, w.extStorage, fileName+".sql", conf.CompressType) +} + // WriteTableData writes table data to a file with retry func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int) error { tctx, conf, conn := w.tctx, w.conf, w.conn @@ -181,7 +193,7 @@ func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int zap.String("table", meta.TableName()), zap.Int("chunkIndex", currentChunk), zap.NamedError("lastError", lastErr)) // don't rebuild connection when dump for the first time if retryTime > 1 { - conn, err = w.rebuildConnFn(conn) + conn, err = w.rebuildConnFn(conn, true) w.conn = conn if err != nil { return @@ -199,7 +211,7 @@ func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int } defer ir.Close() return w.tryToWriteTableData(tctx, meta, ir, currentChunk) - }, newDumpChunkBackoffer(canRebuildConn(conf.Consistency, conf.TransactionalConsistency))) + }, newRebuildConnBackOffer(canRebuildConn(conf.Consistency, conf.TransactionalConsistency))) } func (w *Writer) tryToWriteTableData(tctx *tcontext.Context, meta TableMeta, ir TableDataIR, curChkIdx int) error { @@ -259,7 +271,6 @@ func writeMetaToFile(tctx *tcontext.Context, target, metaSQL string, s storage.E metaSQL: metaSQL, specCmts: []string{ "/*!40101 SET NAMES binary*/;", - "/*T![placement] SET PLACEMENT_CHECKS = 0*/;", }, }, fileWriter) } diff --git a/dumpling/export/writer_serial_test.go b/dumpling/export/writer_serial_test.go index a606784a1bd6b..bc392adf6cc76 100644 --- a/dumpling/export/writer_serial_test.go +++ b/dumpling/export/writer_serial_test.go @@ -121,16 +121,16 @@ func TestWriteInsertInCsv(t *testing.T) { bf := storage.NewBufferWriter() // test nullValue - opt := &csvOption{separator: []byte(","), delimiter: doubleQuotationMark, nullValue: "\\N"} + opt := &csvOption{separator: []byte(","), delimiter: []byte{'"'}, nullValue: "\\N"} conf := configForWriteCSV(cfg, true, opt) n, err := WriteInsertInCsv(tcontext.Background(), conf, tableIR, tableIR, bf) require.Equal(t, uint64(4), n) require.NoError(t, err) - expected := "1,\"male\",\"bob@mail.com\",\"020-1234\",\\N\n" + - "2,\"female\",\"sarah@mail.com\",\"020-1253\",\"healthy\"\n" + - "3,\"male\",\"john@mail.com\",\"020-1256\",\"healthy\"\n" + - "4,\"female\",\"sarah@mail.com\",\"020-1235\",\"healthy\"\n" + expected := "1,\"male\",\"bob@mail.com\",\"020-1234\",\\N\r\n" + + "2,\"female\",\"sarah@mail.com\",\"020-1253\",\"healthy\"\r\n" + + "3,\"male\",\"john@mail.com\",\"020-1256\",\"healthy\"\r\n" + + "4,\"female\",\"sarah@mail.com\",\"020-1235\",\"healthy\"\r\n" require.Equal(t, expected, bf.String()) require.Equal(t, float64(len(data)), ReadGauge(finishedRowsGauge, conf.Labels)) require.Equal(t, float64(len(expected)), ReadGauge(finishedSizeGauge, conf.Labels)) @@ -146,10 +146,10 @@ func TestWriteInsertInCsv(t *testing.T) { require.Equal(t, uint64(4), n) require.NoError(t, err) - expected = "1,'male','bob@mail.com','020-1234',\\N\n" + - "2,'female','sarah@mail.com','020-1253','healthy'\n" + - "3,'male','john@mail.com','020-1256','healthy'\n" + - "4,'female','sarah@mail.com','020-1235','healthy'\n" + expected = "1,'male','bob@mail.com','020-1234',\\N\r\n" + + "2,'female','sarah@mail.com','020-1253','healthy'\r\n" + + "3,'male','john@mail.com','020-1256','healthy'\r\n" + + "4,'female','sarah@mail.com','020-1235','healthy'\r\n" require.Equal(t, expected, bf.String()) require.Equal(t, float64(len(data)), ReadGauge(finishedRowsGauge, conf.Labels)) require.Equal(t, float64(len(expected)), ReadGauge(finishedSizeGauge, conf.Labels)) @@ -165,10 +165,10 @@ func TestWriteInsertInCsv(t *testing.T) { require.Equal(t, uint64(4), n) require.NoError(t, err) - expected = "1;'male';'bob@mail.com';'020-1234';\\N\n" + - "2;'female';'sarah@mail.com';'020-1253';'healthy'\n" + - "3;'male';'john@mail.com';'020-1256';'healthy'\n" + - "4;'female';'sarah@mail.com';'020-1235';'healthy'\n" + expected = "1;'male';'bob@mail.com';'020-1234';\\N\r\n" + + "2;'female';'sarah@mail.com';'020-1253';'healthy'\r\n" + + "3;'male';'john@mail.com';'020-1256';'healthy'\r\n" + + "4;'female';'sarah@mail.com';'020-1235';'healthy'\r\n" require.Equal(t, expected, bf.String()) require.Equal(t, float64(len(data)), ReadGauge(finishedRowsGauge, conf.Labels)) require.Equal(t, float64(len(expected)), ReadGauge(finishedSizeGauge, conf.Labels)) @@ -186,11 +186,11 @@ func TestWriteInsertInCsv(t *testing.T) { require.Equal(t, uint64(4), n) require.NoError(t, err) - expected = "maidma&;,?magenderma&;,?maemamailma&;,?maphone_numberma&;,?mastatusma\n" + - "1&;,?mamamalema&;,?mabob@mamail.comma&;,?ma020-1234ma&;,?\\N\n" + - "2&;,?mafemamalema&;,?masarah@mamail.comma&;,?ma020-1253ma&;,?mahealthyma\n" + - "3&;,?mamamalema&;,?majohn@mamail.comma&;,?ma020-1256ma&;,?mahealthyma\n" + - "4&;,?mafemamalema&;,?masarah@mamail.comma&;,?ma020-1235ma&;,?mahealthyma\n" + expected = "maidma&;,?magenderma&;,?maemamailma&;,?maphone_numberma&;,?mastatusma\r\n" + + "1&;,?mamamalema&;,?mabob@mamail.comma&;,?ma020-1234ma&;,?\\N\r\n" + + "2&;,?mafemamalema&;,?masarah@mamail.comma&;,?ma020-1253ma&;,?mahealthyma\r\n" + + "3&;,?mamamalema&;,?majohn@mamail.comma&;,?ma020-1256ma&;,?mahealthyma\r\n" + + "4&;,?mafemamalema&;,?masarah@mamail.comma&;,?ma020-1235ma&;,?mahealthyma\r\n" require.Equal(t, expected, bf.String()) require.Equal(t, float64(len(data)), ReadGauge(finishedRowsGauge, conf.Labels)) require.Equal(t, float64(len(expected)), ReadGauge(finishedSizeGauge, conf.Labels)) @@ -217,15 +217,15 @@ func TestWriteInsertInCsvReturnsError(t *testing.T) { bf := storage.NewBufferWriter() // test nullValue - opt := &csvOption{separator: []byte(","), delimiter: doubleQuotationMark, nullValue: "\\N"} + opt := &csvOption{separator: []byte(","), delimiter: []byte{'"'}, nullValue: "\\N"} conf := configForWriteCSV(cfg, true, opt) n, err := WriteInsertInCsv(tcontext.Background(), conf, tableIR, tableIR, bf) require.Equal(t, uint64(3), n) require.ErrorIs(t, err, rowErr) - expected := "1,\"male\",\"bob@mail.com\",\"020-1234\",\\N\n" + - "2,\"female\",\"sarah@mail.com\",\"020-1253\",\"healthy\"\n" + - "3,\"male\",\"john@mail.com\",\"020-1256\",\"healthy\"\n" + expected := "1,\"male\",\"bob@mail.com\",\"020-1234\",\\N\r\n" + + "2,\"female\",\"sarah@mail.com\",\"020-1253\",\"healthy\"\r\n" + + "3,\"male\",\"john@mail.com\",\"020-1256\",\"healthy\"\r\n" require.Equal(t, expected, bf.String()) require.Equal(t, float64(0), ReadGauge(finishedRowsGauge, conf.Labels)) require.Equal(t, float64(0), ReadGauge(finishedSizeGauge, conf.Labels)) diff --git a/dumpling/export/writer_test.go b/dumpling/export/writer_test.go index 9c577e8ab848a..e516bfef029c2 100644 --- a/dumpling/export/writer_test.go +++ b/dumpling/export/writer_test.go @@ -34,7 +34,7 @@ func TestWriteDatabaseMeta(t *testing.T) { bytes, err := ioutil.ReadFile(p) require.NoError(t, err) - require.Equal(t, "/*!40101 SET NAMES binary*/;\n/*T![placement] SET PLACEMENT_CHECKS = 0*/;\nCREATE DATABASE `test`;\n", string(bytes)) + require.Equal(t, "/*!40101 SET NAMES binary*/;\nCREATE DATABASE `test`;\n", string(bytes)) } func TestWritePolicyMeta(t *testing.T) { @@ -54,7 +54,7 @@ func TestWritePolicyMeta(t *testing.T) { bytes, err := ioutil.ReadFile(p) require.NoError(t, err) - require.Equal(t, "/*!40101 SET NAMES binary*/;\n/*T![placement] SET PLACEMENT_CHECKS = 0*/;\ncreate placement policy `y` followers=2;\n", string(bytes)) + require.Equal(t, "/*!40101 SET NAMES binary*/;\ncreate placement policy `y` followers=2;\n", string(bytes)) } func TestWriteTableMeta(t *testing.T) { @@ -73,7 +73,7 @@ func TestWriteTableMeta(t *testing.T) { require.NoError(t, err) bytes, err := ioutil.ReadFile(p) require.NoError(t, err) - require.Equal(t, "/*!40101 SET NAMES binary*/;\n/*T![placement] SET PLACEMENT_CHECKS = 0*/;\nCREATE TABLE t (a INT);\n", string(bytes)) + require.Equal(t, "/*!40101 SET NAMES binary*/;\nCREATE TABLE t (a INT);\n", string(bytes)) } func TestWriteViewMeta(t *testing.T) { @@ -84,7 +84,7 @@ func TestWriteViewMeta(t *testing.T) { writer, clean := createTestWriter(config, t) defer clean() - specCmt := "/*!40101 SET NAMES binary*/;\n/*T![placement] SET PLACEMENT_CHECKS = 0*/;\n" + specCmt := "/*!40101 SET NAMES binary*/;\n" createTableSQL := "CREATE TABLE `v`(\n`a` int\n)ENGINE=MyISAM;\n" createViewSQL := "DROP TABLE IF EXISTS `v`;\nDROP VIEW IF EXISTS `v`;\nSET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;\nSET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;\nSET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;\nSET character_set_client = utf8;\nSET character_set_results = utf8;\nSET collation_connection = utf8_general_ci;\nCREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` (`a`) AS SELECT `t`.`a` AS `a` FROM `test`.`t`;\nSET character_set_client = @PREV_CHARACTER_SET_CLIENT;\nSET character_set_results = @PREV_CHARACTER_SET_RESULTS;\nSET collation_connection = @PREV_COLLATION_CONNECTION;\n" err := writer.WriteViewMeta("test", "v", createTableSQL, createViewSQL) diff --git a/dumpling/export/writer_util.go b/dumpling/export/writer_util.go index 2ccbefad372f9..73eb66b0a1da6 100755 --- a/dumpling/export/writer_util.go +++ b/dumpling/export/writer_util.go @@ -226,7 +226,7 @@ func WriteInsert(pCtx *tcontext.Context, cfg *Config, meta TableMeta, tblIR Tabl } counter++ wp.AddFileSize(uint64(bf.Len()-lastBfSize) + 2) // 2 is for ",\n" and ";\n" - failpoint.Inject("ChaosBrokenMySQLConn", func(_ failpoint.Value) { + failpoint.Inject("ChaosBrokenWriterConn", func(_ failpoint.Value) { failpoint.Return(0, errors.New("connection is closed")) }) @@ -344,6 +344,7 @@ func WriteInsertInCsv(pCtx *tcontext.Context, cfg *Config, meta TableMeta, tblIR bf.Write(opt.separator) } } + bf.WriteByte('\r') bf.WriteByte('\n') } wp.currentFileSize += uint64(bf.Len()) @@ -359,6 +360,7 @@ func WriteInsertInCsv(pCtx *tcontext.Context, cfg *Config, meta TableMeta, tblIR counter++ wp.currentFileSize += uint64(bf.Len()-lastBfSize) + 1 // 1 is for "\n" + bf.WriteByte('\r') bf.WriteByte('\n') if bf.Len() >= lengthLimit { select { diff --git a/dumpling/tests/all_generate_column/run.sh b/dumpling/tests/all_generate_column/run.sh index b7a11fb6b1d8a..cf8f186829e27 100644 --- a/dumpling/tests/all_generate_column/run.sh +++ b/dumpling/tests/all_generate_column/run.sh @@ -17,10 +17,10 @@ export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists $DB_NAME;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" # build data with generate column full_name -run_sql "create table $DB_NAME.$TABLE_NAME(a int as (1), b int as (2)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;" +run_sql "create table $DB_NAME.$TABLE_NAME(a int as (1), b int as (2)) ENGINE=InnoDB;" # insert 100 records run_sql "insert into $DB_NAME.$TABLE_NAME values $(seq -s, 100 | sed 's/,*$//g' | sed "s/[0-9]*/()/g");" diff --git a/dumpling/tests/basic/run.sh b/dumpling/tests/basic/run.sh index 516fffeff2c30..c93915cc34e0f 100644 --- a/dumpling/tests/basic/run.sh +++ b/dumpling/tests/basic/run.sh @@ -11,7 +11,7 @@ SEQUENCE_NAME="s" # Test for simple case. run_sql "drop database if exists \`$DB_NAME\`;" -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (a int);" run_sql "insert into \`$DB_NAME\`.\`$TABLE_NAME\` values (1), (2);" @@ -28,7 +28,7 @@ echo "version info count is ${cnt}" # Test for simple WHERE case. run_sql "drop database if exists \`$DB_NAME\`;" -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (a int);" seq 10 | xargs -I_ run_sql "insert into \`$DB_NAME\`.\`$TABLE_NAME\` values (_);" @@ -43,7 +43,7 @@ echo "expected ${expected}, actual ${actual}" # Test for OR WHERE case. Better dump MySQL here because Dumpling has some special handle for concurrently dump TiDB tables. export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists \`$DB_NAME\`;" -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (a int primary key, b int);" seq 0 99 | xargs -I_ run_sql "insert into \`$DB_NAME\`.\`$TABLE_NAME\` (a,b) values (_, 99-_);" @@ -73,20 +73,20 @@ echo "expected 1 return error when specifying --filetype sql and --sql, actual $ export DUMPLING_TEST_PORT=4000 # Test for --sql option. run_sql "drop database if exists \`$DB_NAME\`;" -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create sequence \`$DB_NAME\`.\`$SEQUENCE_NAME\` increment by 1;" run_dumpling --sql "select nextval(\`$DB_NAME\`.\`$SEQUENCE_NAME\`)" -actual=$(sed -n '2p' ${DUMPLING_OUTPUT_DIR}/result.000000000.csv) -echo "expected 1, actual ${actual}" -[ "$actual" = 1 ] +actual=$(sed -n '2p' ${DUMPLING_OUTPUT_DIR}/result.000000000.csv | sed "s/\r/r/g") +echo "expected 1r, actual ${actual}" +[ "$actual" = "1r" ] run_dumpling --sql "select nextval(\`$DB_NAME\`.\`$SEQUENCE_NAME\`)" -actual=$(sed -n '2p' ${DUMPLING_OUTPUT_DIR}/result.000000000.csv) -echo "expected 2, actual ${actual}" -[ "$actual" = 2 ] +actual=$(sed -n '2p' ${DUMPLING_OUTPUT_DIR}/result.000000000.csv | sed "s/\r/r/g") +echo "expected 2r, actual ${actual}" +[ "$actual" = "2r" ] # Test for dump with sequence run_dumpling | tee ${DUMPLING_OUTPUT_DIR}/dumpling.log diff --git a/dumpling/tests/chaos/run.sh b/dumpling/tests/chaos/run.sh index d7c0b7d955446..5150340af9530 100755 --- a/dumpling/tests/chaos/run.sh +++ b/dumpling/tests/chaos/run.sh @@ -12,7 +12,7 @@ TABLE_NAME="t" run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table $DB_NAME.$TABLE_NAME (a int(255));" # insert 100 records @@ -20,7 +20,7 @@ run_sql "insert into $DB_NAME.$TABLE_NAME values $(seq -s, 100 | sed 's/,*$//g' # dumping with consistency none export DUMPLING_TEST_DATABASE=$DB_NAME -export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/ChaosBrokenMySQLConn=1*return" +export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/ChaosBrokenWriterConn=1*return;github.com/pingcap/tidb/dumpling/export/ChaosBrokenMetaConn=1*return" run_dumpling --consistency=none --loglevel debug # check data record count diff --git a/dumpling/tests/consistency/run.sh b/dumpling/tests/consistency/run.sh index 0c514615e47f1..afd916b0d250d 100644 --- a/dumpling/tests/consistency/run.sh +++ b/dumpling/tests/consistency/run.sh @@ -12,7 +12,7 @@ TABLE_NAME="t" run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table $DB_NAME.$TABLE_NAME (a int(255));" # insert 100 records diff --git a/dumpling/tests/e2e/run.sh b/dumpling/tests/e2e/run.sh index f0c79ecb146f6..f5da32acc33e0 100644 --- a/dumpling/tests/e2e/run.sh +++ b/dumpling/tests/e2e/run.sh @@ -17,7 +17,7 @@ export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists $DB_NAME;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table $DB_NAME.$TABLE_NAME (a int(255), b blob);" # insert 100 records diff --git a/dumpling/tests/empty_database/run.sh b/dumpling/tests/empty_database/run.sh index 67ee1c0479709..d97b538ccc1f4 100644 --- a/dumpling/tests/empty_database/run.sh +++ b/dumpling/tests/empty_database/run.sh @@ -11,7 +11,7 @@ DB_NAME="empty_test" run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" # dumping export DUMPLING_TEST_DATABASE=$DB_NAME diff --git a/dumpling/tests/external_storage/run.sh b/dumpling/tests/external_storage/run.sh new file mode 100644 index 0000000000000..ab35ebc802e5e --- /dev/null +++ b/dumpling/tests/external_storage/run.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. + +set -eu +cur=$(cd `dirname $0`; pwd) + +DB_NAME="ext_storage" +TABLE_NAME="t" + +# Test for simple case. +run_sql "drop database if exists \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" +run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (a int);" +run_sql "insert into \`$DB_NAME\`.\`$TABLE_NAME\` values (1), (2);" + +export GO_FAILPOINTS="github.com/pingcap/tidb/dumpling/export/setExtStorage=return(\"$DUMPLING_TEST_DIR/set_by_failpoint\")" +run_dumpling -f "$DB_NAME.$TABLE_NAME" -L ${DUMPLING_OUTPUT_DIR}/dumpling.log + +files=`ls $DUMPLING_TEST_DIR/set_by_failpoint | wc -l` +[ "$files" = 4 ] diff --git a/dumpling/tests/file_size/run.sh b/dumpling/tests/file_size/run.sh index ed8879f62b42d..6b0577dc2e514 100644 --- a/dumpling/tests/file_size/run.sh +++ b/dumpling/tests/file_size/run.sh @@ -5,7 +5,7 @@ set -eu run_sql "drop database if exists file_size" -run_sql "create database file_size" +run_sql "create database file_size DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" export DUMPLING_TEST_DATABASE=file_size run_sql "create table t (a varchar(255))" diff --git a/dumpling/tests/ignore_generate_column/run.sh b/dumpling/tests/ignore_generate_column/run.sh index 6812e2b3bca51..678143f0d0fa3 100644 --- a/dumpling/tests/ignore_generate_column/run.sh +++ b/dumpling/tests/ignore_generate_column/run.sh @@ -17,10 +17,10 @@ export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists $DB_NAME;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" # build data with generate column full_name -run_sql "create table $DB_NAME.$TABLE_NAME(first_name varchar(14) NOT NULL, last_name varchar(16) NOT NULL, full_name VARCHAR(30) AS (CONCAT(first_name,'-',last_name))) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;" +run_sql "create table $DB_NAME.$TABLE_NAME(first_name varchar(14) NOT NULL, last_name varchar(16) NOT NULL, full_name VARCHAR(30) AS (CONCAT(first_name,'-',last_name))) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" # insert 100 records run_sql "insert into $DB_NAME.$TABLE_NAME (first_name, last_name) values $(seq -s, 100 | sed 's/,*$//g' | sed "s/[0-9]*/('a', 'b')/g");" diff --git a/dumpling/tests/naughty_strings/naughty_strings.escape-schema.sql b/dumpling/tests/naughty_strings/naughty_strings.escape-schema.sql deleted file mode 100644 index 58ef275e2dde3..0000000000000 --- a/dumpling/tests/naughty_strings/naughty_strings.escape-schema.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE `escape` ( - `a` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - diff --git a/dumpling/tests/no_table_and_db_name/run.sh b/dumpling/tests/no_table_and_db_name/run.sh index b13333dbcd574..972111acf6f92 100644 --- a/dumpling/tests/no_table_and_db_name/run.sh +++ b/dumpling/tests/no_table_and_db_name/run.sh @@ -13,7 +13,7 @@ assert() { TEST_NAME=no_table_and_db_name run_sql "drop database if exists $TEST_NAME" -run_sql "create database $TEST_NAME" +run_sql "create database $TEST_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" export DUMPLING_TEST_DATABASE=no_table_and_db_name run_sql "create table t (a varchar(255))" diff --git a/dumpling/tests/null_unique_index/run.sh b/dumpling/tests/null_unique_index/run.sh index 23e1c19b4f1f6..691dfecbf5ab4 100644 --- a/dumpling/tests/null_unique_index/run.sh +++ b/dumpling/tests/null_unique_index/run.sh @@ -11,7 +11,7 @@ DB_NAME="null_unique_key" run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table \`$DB_NAME\`.\`t\` (a int unique key, b int);" run_sql "insert into \`$DB_NAME\`.\`t\` values (1, 2), (NULL, 1);" diff --git a/dumpling/tests/placement_policy/result/x-placement-policy-create.sql b/dumpling/tests/placement_policy/result/x-placement-policy-create.sql index 0b68c742ee1cf..8a41e6c2a3522 100644 --- a/dumpling/tests/placement_policy/result/x-placement-policy-create.sql +++ b/dumpling/tests/placement_policy/result/x-placement-policy-create.sql @@ -1,3 +1,2 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; /*T![placement] CREATE PLACEMENT POLICY `x` PRIMARY_REGION="cn-east-1" REGIONS="cn-east-1,cn-east" */; diff --git a/dumpling/tests/placement_policy/result/x1-placement-policy-create.sql b/dumpling/tests/placement_policy/result/x1-placement-policy-create.sql index d2dafe29b2a85..d5e7f8ad8dda5 100644 --- a/dumpling/tests/placement_policy/result/x1-placement-policy-create.sql +++ b/dumpling/tests/placement_policy/result/x1-placement-policy-create.sql @@ -1,3 +1,2 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; /*T![placement] CREATE PLACEMENT POLICY `x1` FOLLOWERS=4 */; diff --git a/dumpling/tests/placement_policy/run.sh b/dumpling/tests/placement_policy/run.sh index a5c1409e0db16..e164315793267 100644 --- a/dumpling/tests/placement_policy/run.sh +++ b/dumpling/tests/placement_policy/run.sh @@ -9,7 +9,7 @@ export DUMPLING_TEST_PORT=4000 run_sql "drop database if exists policy" run_sql "drop placement policy if exists x" run_sql "drop placement policy if exists x1" -run_sql "create database policy" +run_sql "create database policy DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" export DUMPLING_TEST_DATABASE="policy" diff --git a/dumpling/tests/primary_key/run.sh b/dumpling/tests/primary_key/run.sh index a0e8c21492d23..a4009a0470a21 100644 --- a/dumpling/tests/primary_key/run.sh +++ b/dumpling/tests/primary_key/run.sh @@ -5,7 +5,7 @@ set -eu run_sql "drop database if exists primary_key" -run_sql "create database primary_key" +run_sql "create database primary_key DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" export DUMPLING_TEST_DATABASE=primary_key for data in "$DUMPLING_BASE_NAME"/data/*; do diff --git a/dumpling/tests/quote/data/quote-database-schema-create-mysql57.sql b/dumpling/tests/quote/data/quote-database-schema-create-mysql57.sql index 0790882615b9f..a5df1c26b6c8b 100755 --- a/dumpling/tests/quote/data/quote-database-schema-create-mysql57.sql +++ b/dumpling/tests/quote/data/quote-database-schema-create-mysql57.sql @@ -1,3 +1,2 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; -CREATE DATABASE `quo``te/database` CHARACTER SET = latin1 COLLATE = latin1_swedish_ci; +CREATE DATABASE `quo``te/database` /*!40100 DEFAULT CHARACTER SET latin1 */; diff --git a/dumpling/tests/quote/data/quote-database-schema-create.sql b/dumpling/tests/quote/data/quote-database-schema-create.sql index d4a6ef081cc11..d895b4678b912 100755 --- a/dumpling/tests/quote/data/quote-database-schema-create.sql +++ b/dumpling/tests/quote/data/quote-database-schema-create.sql @@ -1,3 +1,2 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; -CREATE DATABASE `quo``te/database` CHARACTER SET = latin1 ENCRYPTION = 'N' COLLATE = latin1_swedish_ci; +CREATE DATABASE `quo``te/database` /*!40100 DEFAULT CHARACTER SET latin1 */ /*!80016 DEFAULT ENCRYPTION='N' */; diff --git a/dumpling/tests/quote/data/quote-database.quote-table-schema-mysql57.sql b/dumpling/tests/quote/data/quote-database.quote-table-schema-mysql57.sql index 85b0d7b70acf6..b3c55dee26330 100755 --- a/dumpling/tests/quote/data/quote-database.quote-table-schema-mysql57.sql +++ b/dumpling/tests/quote/data/quote-database.quote-table-schema-mysql57.sql @@ -1,3 +1,7 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; -CREATE TABLE `quo``te/table` (`quo``te/col` INT(11) NOT NULL,`a` INT(11) DEFAULT NULL,`gen``id` INT(11) GENERATED ALWAYS AS(`quo``te/col`) VIRTUAL,PRIMARY KEY(`quo``te/col`)) ENGINE = InnoDB DEFAULT CHARACTER SET = LATIN1 DEFAULT COLLATE = LATIN1_SWEDISH_CI; +CREATE TABLE `quo``te/table` ( + `quo``te/col` int(11) NOT NULL, + `a` int(11) DEFAULT NULL, + `gen``id` int(11) GENERATED ALWAYS AS (`quo``te/col`) VIRTUAL, + PRIMARY KEY (`quo``te/col`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; diff --git a/dumpling/tests/quote/data/quote-database.quote-table-schema.sql b/dumpling/tests/quote/data/quote-database.quote-table-schema.sql index 2a42478f5c1c9..61bfcc50d113f 100755 --- a/dumpling/tests/quote/data/quote-database.quote-table-schema.sql +++ b/dumpling/tests/quote/data/quote-database.quote-table-schema.sql @@ -1,3 +1,7 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; -CREATE TABLE `quo``te/table` (`quo``te/col` INT NOT NULL,`a` INT DEFAULT NULL,`gen``id` INT GENERATED ALWAYS AS(`quo``te/col`) VIRTUAL,PRIMARY KEY(`quo``te/col`)) ENGINE = InnoDB DEFAULT CHARACTER SET = LATIN1 DEFAULT COLLATE = LATIN1_SWEDISH_CI; +CREATE TABLE `quo``te/table` ( + `quo``te/col` int NOT NULL, + `a` int DEFAULT NULL, + `gen``id` int GENERATED ALWAYS AS (`quo``te/col`) VIRTUAL, + PRIMARY KEY (`quo``te/col`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; diff --git a/dumpling/tests/rows/run.sh b/dumpling/tests/rows/run.sh index 1473e4f3a2cdd..84175b025b9b2 100644 --- a/dumpling/tests/rows/run.sh +++ b/dumpling/tests/rows/run.sh @@ -17,7 +17,7 @@ export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database \`$DB_NAME\`;" +run_sql "create database \`$DB_NAME\` DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table \`$DB_NAME\`.\`$TABLE_NAME\` (id int not null auto_increment primary key, a varchar(24));" # insert 100 records diff --git a/dumpling/tests/rows_extreme_int/run.sh b/dumpling/tests/rows_extreme_int/run.sh index 5f9772c8c2c3d..625be84150a2b 100644 --- a/dumpling/tests/rows_extreme_int/run.sh +++ b/dumpling/tests/rows_extreme_int/run.sh @@ -18,7 +18,7 @@ export DUMPLING_TEST_PORT=3306 run_sql "drop database if exists \`$DB_NAME\`;" # build data on mysql -run_sql "create database $DB_NAME;" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" run_sql "create table $DB_NAME.$TABLE_NAME (id int not null auto_increment primary key, a varchar(24));" run_sql "create table $DB_NAME.$TABLE_NAME2 (id bigint unsigned not null auto_increment primary key, a varchar(24));" diff --git a/dumpling/tests/s3/import.go b/dumpling/tests/s3/import.go new file mode 100644 index 0000000000000..0489be3fa7a80 --- /dev/null +++ b/dumpling/tests/s3/import.go @@ -0,0 +1,99 @@ +// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0. + +package main + +import ( + "context" + "database/sql" + "fmt" + "os" + + _ "github.com/go-sql-driver/mysql" + "github.com/pingcap/errors" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" +) + +const ( + flagDatabase = "database" + flagTable = "table" + flagPort = "port" + flagWorker = "worker" +) + +var rootCmd *cobra.Command + +func main() { + rootCmd = &cobra.Command{} + rootCmd.Flags().StringP(flagDatabase, "B", "s3", "Database to import") + rootCmd.Flags().StringP(flagTable, "T", "t", "Table to import") + rootCmd.Flags().IntP(flagPort, "P", 4000, "TCP/IP port to connect to") + rootCmd.Flags().IntP(flagWorker, "w", 16, "Workers to import synchronously") + + rootCmd.RunE = func(cmd *cobra.Command, args []string) error { + database, err := cmd.Flags().GetString(flagDatabase) + if err != nil { + return errors.Trace(err) + } + table, err := cmd.Flags().GetString(flagTable) + if err != nil { + return errors.Trace(err) + } + port, err := cmd.Flags().GetInt(flagPort) + if err != nil { + return errors.Trace(err) + } + worker, err := cmd.Flags().GetInt(flagWorker) + if err != nil { + return errors.Trace(err) + } + + dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4", "root", "", "127.0.0.1", port, database) + db, err := sql.Open("mysql", dsn) + if err != nil { + return errors.Trace(err) + } + + tableTemp := `CREATE TABLE IF NOT EXISTS %s ( + a VARCHAR(11) +)` + _, err = db.Exec(fmt.Sprintf(tableTemp, table)) + if err != nil { + return errors.Trace(err) + } + + query := fmt.Sprintf("insert into %s values('aaaaaaaaaa')", table) // nolint:gosec + for i := 1; i < 10000; i++ { + query += ",('aaaaaaaaaa')" + } + ch := make(chan struct{}, worker) + for i := 0; i < worker; i++ { + ch <- struct{}{} + } + var eg *errgroup.Group + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + eg, ctx = errgroup.WithContext(ctx) + for i := 0; i < 500; i++ { + if ctx.Err() != nil { + break + } + <-ch + eg.Go(func() error { + _, err := db.ExecContext(ctx, query) + if err != nil { + cancel() + return errors.Trace(err) + } + ch <- struct{}{} + return nil + }) + } + return eg.Wait() + } + + if err := rootCmd.Execute(); err != nil { + fmt.Printf("fail to import data, err: %v", err) + os.Exit(2) + } +} diff --git a/dumpling/tests/s3/run.sh b/dumpling/tests/s3/run.sh index 1f013b0990f5e..a5011e4707946 100755 --- a/dumpling/tests/s3/run.sh +++ b/dumpling/tests/s3/run.sh @@ -2,7 +2,7 @@ # # Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. -set -eux +set -eu echo "starting localstack writing to ${DUMPLING_OUTPUT_DIR}" mkdir -p "${DUMPLING_OUTPUT_DIR}" @@ -40,13 +40,12 @@ TABLE_NAME="t" # drop database on mysql run_sql "drop database if exists \`$DB_NAME\`;" - # build data on mysql -run_sql "create database $DB_NAME;" -run_sql "create table $DB_NAME.$TABLE_NAME (a int(255));" +run_sql "create database $DB_NAME DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" -# insert 100 records -run_sql "insert into $DB_NAME.$TABLE_NAME values $(seq -s, 100 | sed 's/,*$//g' | sed "s/[0-9]*/('1')/g");" +# load 50MB data into MySQL +(cd "$(dirname "$0")" && GO111MODULE=on go build -o out) +$DUMPLING_BASE_NAME/out -B $DB_NAME -T $TABLE_NAME -P 3306 -w 16 # run dumpling! HOST_DIR=${DUMPLING_OUTPUT_DIR} @@ -58,10 +57,28 @@ export AWS_SECRET_ACCESS_KEY="$MINIO_SECRET_KEY" run_dumpling --s3.endpoint="http://$S3_ENDPOINT/" ls "${HOST_DIR}" -curl -o "${HOST_DIR}/s3-schema-create.sql" http://$S3_ENDPOINT/mybucket/dump/s3-schema-create.sql -curl -o "${HOST_DIR}/s3.t-schema.sql" http://$S3_ENDPOINT/mybucket/dump/s3.t-schema.sql -curl -o "${HOST_DIR}/s3.t.000000000.sql" http://$S3_ENDPOINT/mybucket/dump/s3.t.000000000.sql +file_should_exist "$DBPATH/mybucket/dump/s3-schema-create.sql" +file_should_exist "$DBPATH/mybucket/dump/s3.t-schema.sql" +file_should_exist "$DBPATH/mybucket/dump/s3.t.000000000.sql" + +cnt=`grep -o "('aaaaaaaaaa')" $DBPATH/mybucket/dump/s3.t.000000000.sql|wc -l` +echo "1st records count is ${cnt}" +[ $cnt = 5000000 ] + +# run dumpling with compress option +mv "$DBPATH/mybucket/dump" "$DBPATH/mybucket/expect" +run_dumpling --s3.endpoint="http://$S3_ENDPOINT/" --compress "gzip" +file_should_exist "$DBPATH/mybucket/dump/s3-schema-create.sql.gz" +file_should_exist "$DBPATH/mybucket/dump/s3.t-schema.sql.gz" +file_should_exist "$DBPATH/mybucket/dump/s3.t.000000000.sql.gz" + +gzip "$DBPATH/mybucket/dump/s3-schema-create.sql.gz" -d +diff "$DBPATH/mybucket/expect/s3-schema-create.sql" "$DBPATH/mybucket/dump/s3-schema-create.sql" -file_should_exist "$HOST_DIR/s3-schema-create.sql" -file_should_exist "$HOST_DIR/s3.t-schema.sql" -file_should_exist "$HOST_DIR/s3.t.000000000.sql" +gzip "$DBPATH/mybucket/dump/s3.t-schema.sql.gz" -d +diff "$DBPATH/mybucket/expect/s3.t-schema.sql" "$DBPATH/mybucket/dump/s3.t-schema.sql" + +gzip "$DBPATH/mybucket/dump/s3.t.000000000.sql.gz" -d +diff "$DBPATH/mybucket/expect/s3.t.000000000.sql" "$DBPATH/mybucket/dump/s3.t.000000000.sql" + +run_sql "drop database if exists \`$DB_NAME\`;" diff --git a/dumpling/tests/sequences/data/sequences.s-schema-sequence-expect.sql b/dumpling/tests/sequences/data/sequences.s-schema-sequence-expect.sql new file mode 100644 index 0000000000000..0fb6daa6fc5ad --- /dev/null +++ b/dumpling/tests/sequences/data/sequences.s-schema-sequence-expect.sql @@ -0,0 +1,3 @@ +/*!40101 SET NAMES binary*/; +CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`s`,1001); diff --git a/dumpling/tests/sequences/run.sh b/dumpling/tests/sequences/run.sh new file mode 100644 index 0000000000000..23449ca1119d6 --- /dev/null +++ b/dumpling/tests/sequences/run.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. + +set -eu + +export DUMPLING_TEST_PORT=4000 + +run_sql "drop database if exists sequences;" +run_sql "create database sequences DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" +export DUMPLING_TEST_DATABASE="sequences" + +run_sql "create sequence s start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;" +run_sql "select nextval(s);" + +# test --no-sequences +run_dumpling --no-sequences +file_not_exist "$DUMPLING_OUTPUT_DIR/sequences.s-schema-sequence.sql" + +rm -rf $DUMPLING_OUTPUT_DIR +run_dumpling --no-sequences=false +diff "$DUMPLING_BASE_NAME/data/sequences.s-schema-sequence-expect.sql" "$DUMPLING_OUTPUT_DIR/sequences.s-schema-sequence.sql" +file_not_exist "$DUMPLING_OUTPUT_DIR/sequences.s.000000000.sql" + +# test --no-schemas +rm -rf $DUMPLING_OUTPUT_DIR +run_dumpling --no-schemas +file_not_exist "$DUMPLING_OUTPUT_DIR/sequences-schema-create.sql" +file_not_exist "$DUMPLING_OUTPUT_DIR/sequences.s-schema-sequence.sql" +file_not_exist "$DUMPLING_OUTPUT_DIR/sequences.s.000000000.sql" diff --git a/dumpling/tests/tls/run.sh b/dumpling/tests/tls/run.sh index 0e25226109a16..37709acc0697f 100755 --- a/dumpling/tests/tls/run.sh +++ b/dumpling/tests/tls/run.sh @@ -15,7 +15,7 @@ run_sql 'grant all on tls.* to dumper;' # make some sample data. export DUMPLING_TEST_USER=dumper run_sql 'drop database if exists tls;' $WITH_TLS -run_sql 'create database tls;' $WITH_TLS +run_sql 'create database tls DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;' $WITH_TLS export DUMPLING_TEST_DATABASE=tls run_sql 'create table t (a int);' $WITH_TLS run_sql 'insert into t values (1), (2), (3);' $WITH_TLS diff --git a/dumpling/tests/views/data/views-schema-create.sql b/dumpling/tests/views/data/views-schema-create.sql index 2c9d318c1708c..af5ca6d166d0e 100644 --- a/dumpling/tests/views/data/views-schema-create.sql +++ b/dumpling/tests/views/data/views-schema-create.sql @@ -1,3 +1,2 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; CREATE DATABASE `views` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */ /*!80016 DEFAULT ENCRYPTION='N' */; diff --git a/dumpling/tests/views/data/views.v-schema-view.sql b/dumpling/tests/views/data/views.v-schema-view.sql index 4533ab5c9d668..06d73e73fe664 100644 --- a/dumpling/tests/views/data/views.v-schema-view.sql +++ b/dumpling/tests/views/data/views.v-schema-view.sql @@ -1,5 +1,4 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; DROP TABLE IF EXISTS `v`; DROP VIEW IF EXISTS `v`; SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT; diff --git a/dumpling/tests/views/data/views.v-schema.sql b/dumpling/tests/views/data/views.v-schema.sql index f3054eacd2cff..8e6bf5d441640 100644 --- a/dumpling/tests/views/data/views.v-schema.sql +++ b/dumpling/tests/views/data/views.v-schema.sql @@ -1,5 +1,4 @@ /*!40101 SET NAMES binary*/; -/*T![placement] SET PLACEMENT_CHECKS = 0*/; CREATE TABLE `v`( `a` int, `b` int diff --git a/errno/errcode.go b/errno/errcode.go index ea1fb86ea7e8c..e2b33faf628aa 100644 --- a/errno/errcode.go +++ b/errno/errcode.go @@ -657,6 +657,7 @@ const ( ErrBinlogUnsafeLimit = 1668 ErrBinlogUnsafeInsertDelayed = 1669 ErrBinlogUnsafeAutoincColumns = 1671 + ErrBinlogUnsafeSystemFunction = 1674 ErrBinlogUnsafeNontransAfterTrans = 1675 ErrMessageAndStatement = 1676 ErrInsideTransactionPreventsSwitchBinlogFormat = 1679 @@ -841,6 +842,7 @@ const ( ErrUnresolvedHintName = 3128 ErrInvalidJSONText = 3140 ErrInvalidJSONPath = 3143 + ErrInvalidJSONCharset = 3144 ErrInvalidTypeForJSON = 3146 ErrInvalidJSONPathWildcard = 3149 ErrInvalidJSONContainsPathType = 3150 @@ -898,6 +900,7 @@ const ( ErrWrongKeyColumnFunctionalIndex = 3761 ErrFunctionalIndexOnField = 3762 ErrGeneratedColumnRowValueIsNotAllowed = 3764 + ErrDefValGeneratedNamedFunctionIsNotAllowed = 3770 ErrFKIncompatibleColumns = 3780 ErrFunctionalIndexRowValueIsNotAllowed = 3800 ErrDependentByFunctionalIndex = 3837 @@ -1006,11 +1009,16 @@ const ( ErrMultiStatementDisabled = 8130 ErrPartitionStatsMissing = 8131 ErrNotSupportedWithSem = 8132 - ErrDataInConsistentExtraIndex = 8133 - ErrDataInConsistentMisMatchIndex = 8134 + ErrDataInconsistentMismatchCount = 8133 + ErrDataInconsistentMismatchIndex = 8134 ErrAsOf = 8135 ErrVariableNoLongerSupported = 8136 ErrAnalyzeMissColumn = 8137 + ErrInconsistentRowValue = 8138 + ErrInconsistentHandle = 8139 + ErrInconsistentIndexedValue = 8140 + ErrAssertionFailed = 8141 + ErrInstanceScope = 8142 // Error codes used by TiDB ddl package ErrUnsupportedDDLOperation = 8200 @@ -1036,7 +1044,7 @@ const ( ErrWriteOnSnapshot = 8220 ErrInvalidKey = 8221 ErrInvalidIndexKey = 8222 - ErrDataInConsistent = 8223 + ErrDataInconsistent = 8223 ErrDDLJobNotFound = 8224 ErrCancelFinishedDDLJob = 8225 ErrCannotCancelDDLJob = 8226 diff --git a/errno/errname.go b/errno/errname.go index 607672e19b816..ff8d139e541cc 100644 --- a/errno/errname.go +++ b/errno/errname.go @@ -661,6 +661,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrBinlogUnsafeLimit: mysql.Message("The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.", nil), ErrBinlogUnsafeInsertDelayed: mysql.Message("The statement is unsafe because it uses INSERT DELAYED. This is unsafe because the times when rows are inserted cannot be predicted.", nil), ErrBinlogUnsafeAutoincColumns: mysql.Message("Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTOINCREMENT column. Inserted values cannot be logged correctly.", nil), + ErrBinlogUnsafeSystemFunction: mysql.Message("Statement is unsafe because it uses a system function that may return a different value on the slave", nil), ErrBinlogUnsafeNontransAfterTrans: mysql.Message("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction.", nil), ErrMessageAndStatement: mysql.Message("%s Statement: %s", nil), ErrInsideTransactionPreventsSwitchBinlogFormat: mysql.Message("Cannot modify @@session.binlogFormat inside a transaction", nil), @@ -826,6 +827,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrRowInWrongPartition: mysql.Message("Found a row in wrong partition %s", []int{0}), ErrGeneratedColumnFunctionIsNotAllowed: mysql.Message("Expression of generated column '%s' contains a disallowed function.", nil), ErrGeneratedColumnRowValueIsNotAllowed: mysql.Message("Expression of generated column '%s' cannot refer to a row value", nil), + ErrDefValGeneratedNamedFunctionIsNotAllowed: mysql.Message("Default value expression of column '%s' contains a disallowed function: `%s`.", nil), ErrUnsupportedAlterInplaceOnVirtualColumn: mysql.Message("INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions.", nil), ErrWrongFKOptionForGeneratedColumn: mysql.Message("Cannot define foreign key with %s clause on a generated column.", nil), ErrBadGeneratedColumn: mysql.Message("The value specified for generated column '%s' in table '%s' is not allowed.", nil), @@ -844,6 +846,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrInvalidJSONData: mysql.Message("Invalid JSON data provided to function %s: %s", nil), ErrInvalidJSONText: mysql.Message("Invalid JSON text: %-.192s", []int{0}), ErrInvalidJSONPath: mysql.Message("Invalid JSON path expression %s.", nil), + ErrInvalidJSONCharset: mysql.Message("Cannot create a JSON value from a string with CHARACTER SET '%s'.", nil), ErrInvalidTypeForJSON: mysql.Message("Invalid data type for JSON data in argument %d to function %s; a JSON string or JSON type is required.", nil), ErrInvalidJSONPathWildcard: mysql.Message("In this situation, path expressions may not contain the * and ** tokens.", nil), ErrInvalidJSONContainsPathType: mysql.Message("The second argument can only be either 'one' or 'all'.", nil), @@ -999,7 +1002,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrWriteOnSnapshot: mysql.Message("write on snapshot", nil), ErrInvalidKey: mysql.Message("invalid key", nil), ErrInvalidIndexKey: mysql.Message("invalid index key", nil), - ErrDataInConsistent: mysql.Message("index:%#v != record:%#v", []int{0, 1}), + ErrDataInconsistent: mysql.Message("data inconsistency in table: %s, index: %s, handle: %s, index-values:%#v != record-values:%#v", []int{2, 3, 4}), ErrDDLReorgElementNotExist: mysql.Message("DDL reorg element does not exist", nil), ErrDDLJobNotFound: mysql.Message("DDL Job:%v not found", nil), ErrCancelFinishedDDLJob: mysql.Message("This job:%v is finished, so can't be cancelled", nil), @@ -1007,8 +1010,13 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrUnknownAllocatorType: mysql.Message("Invalid allocator type", nil), ErrAutoRandReadFailed: mysql.Message("Failed to read auto-random value from storage engine", nil), ErrInvalidIncrementAndOffset: mysql.Message("Invalid auto_increment settings: auto_increment_increment: %d, auto_increment_offset: %d, both of them must be in range [1..65535]", nil), - ErrDataInConsistentExtraIndex: mysql.Message("handle %#v, index:%#v != record:%#v", []int{0, 1, 2}), - ErrDataInConsistentMisMatchIndex: mysql.Message("col %s, handle %#v, index:%#v != record:%#v, compare err:%#v", []int{1, 2, 3, 4}), + ErrDataInconsistentMismatchCount: mysql.Message("data inconsistency in table: %s, index: %s, index-count:%d != record-count:%d", nil), + ErrDataInconsistentMismatchIndex: mysql.Message("data inconsistency in table: %s, index: %s, col: %s, handle: %#v, index-values:%#v != record-values:%#v, compare err:%#v", []int{3, 4, 5, 6}), + ErrInconsistentRowValue: mysql.Message("writing inconsistent data in table: %s, expected-values:{%s} != record-values:{%s}", []int{1, 2}), + ErrInconsistentHandle: mysql.Message("writing inconsistent data in table: %s, index: %s, index-handle:%#v != record-handle:%#v, index: %#v, record: %#v", []int{2, 3, 4, 5}), + ErrInconsistentIndexedValue: mysql.Message("writing inconsistent data in table: %s, index: %s, col: %s, indexed-value:{%s} != record-value:{%s}", []int{3, 4}), + ErrAssertionFailed: mysql.Message("assertion failed: key: %s, assertion: %s, start_ts: %v, existing start ts: %v, existing commit ts: %v", []int{0}), + ErrInstanceScope: mysql.Message("modifying %s will require SET GLOBAL in a future version of TiDB", nil), ErrWarnOptimizerHintInvalidInteger: mysql.Message("integer value is out of range in '%s'", nil), ErrWarnOptimizerHintUnsupportedHint: mysql.Message("Optimizer hint %s is not supported by TiDB and is ignored", nil), @@ -1056,7 +1064,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrMultiStatementDisabled: mysql.Message("client has multi-statement capability disabled. Run SET GLOBAL tidb_multi_statement_mode='ON' after you understand the security risk", nil), ErrAsOf: mysql.Message("invalid as of timestamp: %s", nil), ErrVariableNoLongerSupported: mysql.Message("option '%s' is no longer supported. Reason: %s", nil), - ErrInvalidAttributesSpec: mysql.Message("Invalid attributes '%s': %s", nil), + ErrInvalidAttributesSpec: mysql.Message("Invalid attributes: %s", nil), ErrPlacementPolicyExists: mysql.Message("Placement policy '%-.192s' already exists", nil), ErrPlacementPolicyNotExists: mysql.Message("Unknown placement policy '%-.192s'", nil), ErrPlacementPolicyWithDirectOption: mysql.Message("Placement policy '%s' can't co-exist with direct placement options", nil), diff --git a/errno/main_test.go b/errno/main_test.go index a38aae7f1cb39..f0064431962cc 100644 --- a/errno/main_test.go +++ b/errno/main_test.go @@ -22,6 +22,6 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() os.Exit(m.Run()) } diff --git a/errors.toml b/errors.toml index 87094603930e3..d6a059a213db0 100644 --- a/errors.toml +++ b/errors.toml @@ -226,6 +226,271 @@ error = ''' the system table isn't supported for restoring yet ''' +["Lighting:Restore:ErrChecksumMismatch"] +error = ''' +checksum mismatched remote vs local => (checksum: %d vs %d) (total_kvs: %d vs %d) (total_bytes:%d vs %d) +''' + +["Lightning:Checkpoint:ErrCheckpointNotFound"] +error = ''' +checkpoint not found +''' + +["Lightning:Checkpoint:ErrCleanCheckpoint"] +error = ''' +clean checkpoint error +''' + +["Lightning:Checkpoint:ErrInitCheckpoint"] +error = ''' +init checkpoint error +''' + +["Lightning:Checkpoint:ErrInvalidCheckpoint"] +error = ''' +invalid checkpoint +''' + +["Lightning:Checkpoint:ErrOpenCheckpoint"] +error = ''' +open checkpoint error +''' + +["Lightning:Checkpoint:ErrReadCheckpoint"] +error = ''' +read checkpoint error +''' + +["Lightning:Checkpoint:ErrUnknownCheckpointDriver"] +error = ''' +unknown checkpoint driver '%s' +''' + +["Lightning:Checkpoint:ErrUpdateCheckpoint"] +error = ''' +update checkpoint error +''' + +["Lightning:Common:ErrInvalidArgument"] +error = ''' +invalid argument +''' + +["Lightning:Common:ErrUnknown"] +error = ''' +unknown error +''' + +["Lightning:Common:ErrVersionMismatch"] +error = ''' +version mismatch +''' + +["Lightning:Config:ErrInvalidConfig"] +error = ''' +invalid config +''' + +["Lightning:Config:ErrInvalidSortedKVDir"] +error = ''' +invalid sorted-kv-dir '%s' for local backend, please change the config or delete the path +''' + +["Lightning:Config:ErrInvalidTLSConfig"] +error = ''' +invalid tls config +''' + +["Lightning:Config:ErrParseConfigFile"] +error = ''' +cannot parse config file '%s' +''' + +["Lightning:Config:ErrReadConfigFile"] +error = ''' +cannot read config file '%s' +''' + +["Lightning:DB:ErrDBConnect"] +error = ''' +failed to connect database +''' + +["Lightning:DB:ErrInitErrManager"] +error = ''' +init error manager error +''' + +["Lightning:DB:ErrInitMetaManager"] +error = ''' +init meta manager error +''' + +["Lightning:KV:ErrCheckKVVersion"] +error = ''' +check tikv version error +''' + +["Lightning:KV:ErrCheckMultiIngest"] +error = ''' +check multi-ingest support error +''' + +["Lightning:KV:ErrCreateKVClient"] +error = ''' +create kv client error +''' + +["Lightning:Loader:ErrInvalidSchemaFile"] +error = ''' +invalid schema file +''' + +["Lightning:Loader:ErrTableRoute"] +error = ''' +table route error +''' + +["Lightning:MetaMgr:ErrMetaMgrUnknown"] +error = ''' +unknown error occur on meta manager +''' + +["Lightning:PD:ErrCreatePDClient"] +error = ''' +create pd client error +''' + +["Lightning:PD:ErrPauseGC"] +error = ''' +pause gc error +''' + +["Lightning:PD:ErrUpdatePD"] +error = ''' +update pd error +''' + +["Lightning:PreCheck:ErrCheckCSVHeader"] +error = ''' +check csv header error +''' + +["Lightning:PreCheck:ErrCheckClusterRegion"] +error = ''' +check tikv cluster region error +''' + +["Lightning:PreCheck:ErrCheckDataSource"] +error = ''' +check data source error +''' + +["Lightning:PreCheck:ErrCheckLocalResource"] +error = ''' +check local storage resource error +''' + +["Lightning:PreCheck:ErrCheckTableEmpty"] +error = ''' +check table empty error +''' + +["Lightning:PreCheck:ErrCheckpointSchemaConflict"] +error = ''' +checkpoint schema conflict +''' + +["Lightning:PreCheck:ErrPreCheckFailed"] +error = ''' +tidb-lightning pre-check failed: %s +''' + +["Lightning:PreCheck:ErrSystemRequirementNotMet"] +error = ''' +system requirement not met +''' + +["Lightning:Restore:ErrAllocTableRowIDs"] +error = ''' +allocate table row id error +''' + +["Lightning:Restore:ErrCheckLocalFile"] +error = ''' +cannot find local file for table: %s engineDir: %s +''' + +["Lightning:Restore:ErrCreateSchema"] +error = ''' +create schema failed, table: %s, stmt: %s +''' + +["Lightning:Restore:ErrEncodeKV"] +error = ''' +encode kv error in file %s at offset %d +''' + +["Lightning:Restore:ErrInvalidMetaStatus"] +error = ''' +invalid meta status: '%s' +''' + +["Lightning:Restore:ErrInvalidSchemaStmt"] +error = ''' +invalid schema statement: '%s' +''' + +["Lightning:Restore:ErrOpenDuplicateDB"] +error = ''' +open duplicate db error +''' + +["Lightning:Restore:ErrRestoreTable"] +error = ''' +restore table %s failed +''' + +["Lightning:Restore:ErrSchemaNotExists"] +error = ''' +table `%s`.`%s` schema not found +''' + +["Lightning:Restore:ErrTableIsChecksuming"] +error = ''' +table '%s' is checksuming +''' + +["Lightning:Restore:ErrUnknownBackend"] +error = ''' +unknown backend %s +''' + +["Lightning:Restore:ErrUnknownColumns"] +error = ''' +unknown columns in header (%s) for table %s +''' + +["Lightning:Storage:ErrEmptySourceDir"] +error = ''' +data-source-dir '%s' doesn't exist or contains no files +''' + +["Lightning:Storage:ErrInvalidPermission"] +error = ''' +invalid permission +''' + +["Lightning:Storage:ErrInvalidStorageConfig"] +error = ''' +invalid data-source-dir +''' + +["Lightning:Storage:ErrStorageUnknown"] +error = ''' +unknown storage error +''' + ["admin:8003"] error = ''' TiDB admin check table failed. @@ -233,7 +498,7 @@ TiDB admin check table failed. ["admin:8223"] error = ''' -index:%#v != record:%#v +data inconsistency in table: %s, index: %s, handle: %s, index-values:%#v != record-values:%#v ''' ["admin:8224"] @@ -301,6 +566,26 @@ error = ''' Invalid default value for '%-.192s' ''' +["ddl:1069"] +error = ''' +Too many keys specified; max %d keys allowed +''' + +["ddl:1071"] +error = ''' +Specified key was too long; max key length is %d bytes +''' + +["ddl:1072"] +error = ''' +Key column '%-.192s' doesn't exist in table +''' + +["ddl:1089"] +error = ''' +Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys +''' + ["ddl:1090"] error = ''' You can't delete all columns with ALTER TABLE; use DROP TABLE instead @@ -311,6 +596,11 @@ error = ''' Can't DROP '%-.192s'; check that column/key exists ''' +["ddl:1101"] +error = ''' +BLOB/TEXT/JSON column '%-.192s' can't have a default value +''' + ["ddl:1102"] error = ''' Incorrect database name '%-.100s' @@ -336,11 +626,31 @@ error = ''' Unknown character set: '%-.64s' ''' +["ddl:1117"] +error = ''' +Too many columns +''' + +["ddl:1138"] +error = ''' +Invalid use of NULL value +''' + ["ddl:1166"] error = ''' Incorrect column name '%-.100s' ''' +["ddl:1167"] +error = ''' +The used storage engine can't index column '%-.192s' +''' + +["ddl:1170"] +error = ''' +BLOB/TEXT column '%-.192s' used in key specification without a key length +''' + ["ddl:1171"] error = ''' All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead @@ -351,6 +661,11 @@ error = ''' Can't open table ''' +["ddl:1205"] +error = ''' +Timeout waiting for data reorganization +''' + ["ddl:1214"] error = ''' The used table type doesn't support FULLTEXT indexes @@ -361,6 +676,11 @@ error = ''' Incorrect usage of %s and %s ''' +["ddl:1246"] +error = ''' +Converting column '%s' from %s to %s +''' + ["ddl:1248"] error = ''' Every derived table must have its own alias @@ -426,6 +746,16 @@ error = ''' In definition of view, derived table or common table expression, SELECT list and column names list have different column counts ''' +["ddl:1391"] +error = ''' +Key part '%-.192s' length cannot be 0 +''' + +["ddl:1470"] +error = ''' +String '%-.70s' is too long for %s (should be no longer than %d) +''' + ["ddl:1481"] error = ''' MAXVALUE can only be used in last partition definition @@ -486,6 +816,11 @@ error = ''' COALESCE PARTITION can only be used on HASH/KEY partitions ''' +["ddl:1512"] +error = ''' +%-.64s PARTITION can only be used on RANGE/LIST partitions +''' + ["ddl:1517"] error = ''' Duplicate partition name %-.192s @@ -506,6 +841,16 @@ error = ''' This partition function is not allowed ''' +["ddl:1567"] +error = ''' +Incorrect partition name +''' + +["ddl:1652"] +error = ''' +Duplicate partition field name '%-.192s' +''' + ["ddl:1654"] error = ''' Partition column values of incorrect type @@ -516,6 +861,16 @@ error = ''' Field '%-.192s' is of a not allowed type for this type of partitioning ''' +["ddl:1674"] +error = ''' +Statement is unsafe because it uses a system function that may return a different value on the slave +''' + +["ddl:1688"] +error = ''' +Comment for index '%-.64s' is too long (max = %d) +''' + ["ddl:1697"] error = ''' VALUES value for partition '%-.64s' must have type INT @@ -551,6 +906,11 @@ error = ''' Duplicate foreign key constraint name '%s' ''' +["ddl:1828"] +error = ''' +Cannot drop column '%-.192s': needed in a foreign key constraint '%-.192s' +''' + ["ddl:1846"] error = ''' %s is not supported. Reason: %s. Try %s. @@ -561,16 +921,36 @@ error = ''' Expression of generated column '%s' contains a disallowed function. ''' +["ddl:3104"] +error = ''' +Cannot define foreign key with %s clause on a generated column. +''' + ["ddl:3106"] error = ''' '%s' is not supported for generated columns. ''' +["ddl:3107"] +error = ''' +Generated column can refer only to generated columns defined prior to it. +''' + +["ddl:3108"] +error = ''' +Column '%s' has a generated column dependency. +''' + ["ddl:3109"] error = ''' Generated column '%s' cannot refer to auto-increment column. ''' +["ddl:3152"] +error = ''' +JSON column '%-.192s' cannot be used in key specification. +''' + ["ddl:3505"] error = ''' Too long enumeration/set value for column %s. @@ -581,6 +961,16 @@ error = ''' A primary key index cannot be invisible ''' +["ddl:3593"] +error = ''' +You cannot use the window function '%s' in this context.' +''' + +["ddl:3753"] +error = ''' +Cannot create an expression index on a function that returns a JSON or GEOMETRY value +''' + ["ddl:3754"] error = ''' Expression index '%s' cannot refer to an auto-increment column @@ -591,11 +981,21 @@ error = ''' The primary key cannot be an expression index ''' +["ddl:3757"] +error = ''' +Cannot create an expression index on an expression that returns a BLOB or TEXT. Please consider using CAST +''' + ["ddl:3758"] error = ''' Expression of expression index '%s' contains a disallowed function ''' +["ddl:3761"] +error = ''' +The used storage engine cannot index the expression '%s' +''' + ["ddl:3762"] error = ''' Expression index on a column is not supported. Consider using a regular index instead @@ -606,11 +1006,26 @@ error = ''' Expression of generated column '%s' cannot refer to a row value ''' +["ddl:3770"] +error = ''' +Default value expression of column '%s' contains a disallowed function: `%s`. +''' + +["ddl:3780"] +error = ''' +Referencing column '%s' in foreign key constraint '%s' are incompatible +''' + ["ddl:3800"] error = ''' Expression of expression index '%s' cannot refer to a row value ''' +["ddl:3837"] +error = ''' +Column '%s' has an expression index dependency and cannot be dropped or renamed +''' + ["ddl:4135"] error = ''' Sequence '%-.64s.%-.64s' has run out @@ -643,7 +1058,32 @@ error = ''' ["ddl:8200"] error = ''' -Unsupported partition by range columns +Unsupported shard_row_id_bits for table with primary key as row id +''' + +["ddl:8201"] +error = ''' +TiDB server is not a DDL owner +''' + +["ddl:8202"] +error = ''' +Cannot decode %s value, because %v +''' + +["ddl:8203"] +error = ''' +Invalid DDL worker +''' + +["ddl:8204"] +error = ''' +Invalid DDL job +''' + +["ddl:8207"] +error = ''' +Invalid storage current version: %d ''' ["ddl:8210"] @@ -651,6 +1091,26 @@ error = ''' Invalid %!s(MISSING) state: %!v(MISSING) ''' +["ddl:8211"] +error = ''' +Reorg worker panic +''' + +["ddl:8212"] +error = ''' +Failed to split region ranges: %s +''' + +["ddl:8213"] +error = ''' +Version %d of DDL job is greater than current one: %d +''' + +["ddl:8214"] +error = ''' +Cancelled DDL job +''' + ["ddl:8215"] error = ''' Failed to repair table: %s @@ -698,7 +1158,7 @@ Placement policy didn't meet the constraint, reason: %s ["ddl:8237"] error = ''' -Invalid attributes '%s': %s +Invalid attributes: %s ''' ["ddl:8240"] @@ -918,12 +1378,17 @@ Export failed: %s ["executor:8133"] error = ''' -handle %#v, index:%#v != record:%#v +data inconsistency in table: %s, index: %s, index-count:%d != record-count:%d ''' ["executor:8134"] error = ''' -col %s, handle %#v, index:%#v != record:%#v, compare err:%#v +data inconsistency in table: %s, index: %s, col: %s, handle: %#v, index-values:%#v != record-values:%#v, compare err:%#v +''' + +["executor:8142"] +error = ''' +modifying %s will require SET GLOBAL in a future version of TiDB ''' ["executor:8212"] @@ -1006,6 +1471,11 @@ error = ''' Invalid JSON path expression %s. ''' +["json:3144"] +error = ''' +Cannot create a JSON value from a string with CHARACTER SET '%s'. +''' + ["json:3149"] error = ''' In this situation, path expressions may not contain the * and ** tokens. @@ -1276,6 +1746,11 @@ error = ''' View '%-.192s.%-.192s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them ''' +["planner:1391"] +error = ''' +Key part '%-.192s' length cannot be 0 +''' + ["planner:1462"] error = ''' `%-.192s`.`%-.192s` contains view recursion @@ -1806,6 +2281,21 @@ error = ''' column %s can't be in none state ''' +["table:8138"] +error = ''' +writing inconsistent data in table: %s, expected-values:{%s} != record-values:{%s} +''' + +["table:8139"] +error = ''' +writing inconsistent data in table: %s, index: %s, index-handle:%#v != record-handle:%#v, index: %#v, record: %#v +''' + +["table:8140"] +error = ''' +writing inconsistent data in table: %s, index: %s, col: %s, indexed-value:{%s} != record-value:{%s} +''' + ["tikv:1105"] error = ''' Unknown error @@ -1826,6 +2316,11 @@ error = ''' Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set. ''' +["tikv:8141"] +error = ''' +assertion failed: key: %s, assertion: %s, start_ts: %v, existing start ts: %v, existing commit ts: %v +''' + ["tikv:8229"] error = ''' TTL manager has timed out, pessimistic locks may expire, please commit or rollback this transaction diff --git a/executor/adapter.go b/executor/adapter.go index 87f87a9712516..b4c4888565c0e 100644 --- a/executor/adapter.go +++ b/executor/adapter.go @@ -46,6 +46,7 @@ import ( "github.com/pingcap/tidb/plugin" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" @@ -57,6 +58,7 @@ import ( "github.com/pingcap/tidb/util/stmtsummary" "github.com/pingcap/tidb/util/stringutil" "github.com/pingcap/tidb/util/topsql" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" tikverr "github.com/tikv/client-go/v2/error" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/util" @@ -233,6 +235,7 @@ func (a *ExecStmt) PointGet(ctx context.Context, is infoschema.InfoSchema) (*rec ctx = opentracing.ContextWithSpan(ctx, span1) } ctx = a.setPlanLabelForTopSQL(ctx) + a.observeStmtBeginForTopSQL() startTs := uint64(math.MaxUint64) err := a.Ctx.InitTxnWithStartTS(startTs) if err != nil { @@ -262,6 +265,12 @@ func (a *ExecStmt) PointGet(ctx context.Context, is infoschema.InfoSchema) (*rec a.PsStmt.Executor = newExecutor } pointExecutor := a.PsStmt.Executor.(*PointGetExecutor) + + failpoint.Inject("assertTxnManagerInShortPointGetPlan", func() { + sessiontxn.RecordAssert(a.Ctx, "assertTxnManagerInShortPointGetPlan", true) + sessiontxn.AssertTxnManagerInfoSchema(a.Ctx, is) + }) + if err = pointExecutor.Open(ctx); err != nil { terror.Call(pointExecutor.Close) return nil, err @@ -297,7 +306,17 @@ func (a *ExecStmt) RebuildPlan(ctx context.Context) (int64, error) { if err := plannercore.Preprocess(a.Ctx, a.StmtNode, plannercore.InTxnRetry, plannercore.WithPreprocessorReturn(ret)); err != nil { return 0, err } - a.InfoSchema = ret.InfoSchema + + failpoint.Inject("assertTxnManagerInRebuildPlan", func() { + if is, ok := a.Ctx.Value(sessiontxn.AssertTxnInfoSchemaAfterRetryKey).(infoschema.InfoSchema); ok { + a.Ctx.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is) + a.Ctx.SetValue(sessiontxn.AssertTxnInfoSchemaAfterRetryKey, nil) + } + sessiontxn.RecordAssert(a.Ctx, "assertTxnManagerInRebuildPlan", true) + sessiontxn.AssertTxnManagerInfoSchema(a.Ctx, ret.InfoSchema) + }) + + a.InfoSchema = sessiontxn.GetTxnManager(a.Ctx).GetTxnInfoSchema() a.SnapshotTS = ret.LastSnapshotTS a.IsStaleness = ret.IsStaleness a.ReplicaReadScope = ret.ReadReplicaScope @@ -314,12 +333,15 @@ func (a *ExecStmt) RebuildPlan(ctx context.Context) (int64, error) { } func (a *ExecStmt) setPlanLabelForTopSQL(ctx context.Context) context.Context { - if a.Plan == nil || !variable.TopSQLEnabled() { + if !topsqlstate.TopSQLEnabled() { return ctx } vars := a.Ctx.GetSessionVars() normalizedSQL, sqlDigest := vars.StmtCtx.SQLDigest() normalizedPlan, planDigest := getPlanDigest(a.Ctx, a.Plan) + if len(normalizedPlan) == 0 { + return ctx + } return topsql.AttachSQLInfo(ctx, normalizedSQL, sqlDigest, normalizedPlan, planDigest, vars.InRestrictedSQL) } @@ -383,6 +405,7 @@ func (a *ExecStmt) Exec(ctx context.Context) (_ sqlexec.RecordSet, err error) { } // ExecuteExec will rewrite `a.Plan`, so set plan label should be executed after `a.buildExecutor`. ctx = a.setPlanLabelForTopSQL(ctx) + a.observeStmtBeginForTopSQL() if err = e.Open(ctx); err != nil { terror.Call(e.Close) @@ -409,6 +432,19 @@ func (a *ExecStmt) Exec(ctx context.Context) (_ sqlexec.RecordSet, err error) { } } + failpoint.Inject("mockDelayInnerSessionExecute", func() { + var curTxnStartTS uint64 + if cmd != mysql.ComSleep || sctx.GetSessionVars().InTxn() { + curTxnStartTS = sctx.GetSessionVars().TxnCtx.StartTS + } + if sctx.GetSessionVars().SnapshotTS != 0 { + curTxnStartTS = sctx.GetSessionVars().SnapshotTS + } + logutil.BgLogger().Info("Enable mockDelayInnerSessionExecute when execute statement", + zap.Uint64("startTS", curTxnStartTS)) + time.Sleep(200 * time.Millisecond) + }) + isPessimistic := sctx.GetSessionVars().TxnCtx.IsPessimistic // Special handle for "select for update statement" in pessimistic transaction. @@ -480,6 +516,27 @@ func (a *ExecStmt) handleNoDelay(ctx context.Context, e Executor, isPessimistic return false, nil, nil } +func isNoResultPlan(p plannercore.Plan) bool { + if p.Schema().Len() == 0 { + return true + } + + // Currently this is only for the "DO" statement. Take "DO 1, @a=2;" as an example: + // the Projection has two expressions and two columns in the schema, but we should + // not return the result of the two expressions. + switch raw := p.(type) { + case *plannercore.LogicalProjection: + if raw.CalculateNoDelay { + return true + } + case *plannercore.PhysicalProjection: + if raw.CalculateNoDelay { + return true + } + } + return false +} + // getMaxExecutionTime get the max execution timeout value. func getMaxExecutionTime(sctx sessionctx.Context) uint64 { if sctx.GetSessionVars().StmtCtx.HasMaxExecutionTime { @@ -636,7 +693,7 @@ func (a *ExecStmt) handlePessimisticDML(ctx context.Context, e Executor) error { keys = filterTemporaryTableKeys(sctx.GetSessionVars(), keys) seVars := sctx.GetSessionVars() keys = filterLockTableKeys(seVars.StmtCtx, keys) - lockCtx := newLockCtx(seVars, seVars.LockWaitTimeout) + lockCtx := newLockCtx(seVars, seVars.LockWaitTimeout, len(keys)) var lockKeyStats *util.LockKeysDetails ctx = context.WithValue(ctx, util.LockKeysDetailCtxKey, &lockKeyStats) startLocking := time.Now() @@ -687,6 +744,7 @@ func UpdateForUpdateTS(seCtx sessionctx.Context, newForUpdateTS uint64) error { } seCtx.GetSessionVars().TxnCtx.SetForUpdateTS(newForUpdateTS) txn.SetOption(kv.SnapshotTS, seCtx.GetSessionVars().TxnCtx.GetForUpdateTS()) + seCtx.GetSessionVars().TxnCtx.LastRcReadTs = newForUpdateTS return nil } @@ -753,6 +811,10 @@ func (a *ExecStmt) handlePessimisticLockError(ctx context.Context, err error) (E a.Ctx.GetSessionVars().StmtCtx.ResetForRetry() a.Ctx.GetSessionVars().RetryInfo.ResetOffset() + failpoint.Inject("assertTxnManagerAfterPessimisticLockErrorRetry", func() { + sessiontxn.RecordAssert(a.Ctx, "assertTxnManagerAfterPessimisticLockErrorRetry", true) + }) + if err = e.Open(ctx); err != nil { return nil, err } @@ -807,6 +869,11 @@ func (a *ExecStmt) buildExecutor() (Executor, error) { return nil, errors.Trace(b.err) } + failpoint.Inject("assertTxnManagerAfterBuildExecutor", func() { + sessiontxn.RecordAssert(a.Ctx, "assertTxnManagerAfterBuildExecutor", true) + sessiontxn.AssertTxnManagerInfoSchema(b.ctx, b.is) + }) + // ExecuteExec is not a real Executor, we only use it to build another Executor from a prepared statement. if executorExec, ok := e.(*ExecuteExec); ok { err := executorExec.Build(b) @@ -896,6 +963,7 @@ func (a *ExecStmt) FinishExecuteStmt(txnTS uint64, err error, hasMoreResults boo // `LowSlowQuery` and `SummaryStmt` must be called before recording `PrevStmt`. a.LogSlowQuery(txnTS, succ, hasMoreResults) a.SummaryStmt(succ) + a.observeStmtFinishedForTopSQL() if sessVars.StmtCtx.IsTiFlash.Load() { if succ { totalTiFlashQuerySuccCounter.Inc() @@ -915,6 +983,10 @@ func (a *ExecStmt) FinishExecuteStmt(txnTS uint64, err error, hasMoreResults boo sessVars.DurationParse = 0 // Clean the stale read flag when statement execution finish sessVars.StmtCtx.IsStaleness = false + + if sessVars.StmtCtx.ReadFromTableCache { + metrics.ReadFromTableCacheCounter.Inc() + } } // CloseRecordSet will finish the execution of current statement and do some record work @@ -1116,6 +1188,17 @@ func getEncodedPlan(sctx sessionctx.Context, p plannercore.Plan, genHint bool) ( } if genHint { hints := plannercore.GenHintsFromPhysicalPlan(p) + for _, tableHint := range sctx.GetSessionVars().StmtCtx.OriginalTableHints { + // some hints like 'memory_quota' cannot be extracted from the PhysicalPlan directly, + // so we have to iterate all hints from the customer and keep some other necessary hints. + switch tableHint.HintName.L { + case "memory_quota", "use_toja", "no_index_merge", "max_execution_time", + plannercore.HintAggToCop, plannercore.HintIgnoreIndex, + plannercore.HintReadFromStorage, plannercore.HintLimitToCop: + hints = append(hints, tableHint) + } + } + hintStr = hint.RestoreOptimizerHints(hints) sctx.GetSessionVars().StmtCtx.SetPlanHint(hintStr) } @@ -1193,8 +1276,14 @@ func (a *ExecStmt) SummaryStmt(succ bool) { if tikvExecDetailRaw != nil { tikvExecDetail = *(tikvExecDetailRaw.(*util.ExecDetails)) } + if stmtCtx.WaitLockLeaseTime > 0 { + if execDetail.BackoffSleep == nil { + execDetail.BackoffSleep = make(map[string]time.Duration) + } execDetail.BackoffSleep["waitLockLeaseForCacheTable"] = stmtCtx.WaitLockLeaseTime + execDetail.BackoffTime += stmtCtx.WaitLockLeaseTime + execDetail.TimeDetail.WaitTime += stmtCtx.WaitLockLeaseTime } stmtExecInfo := &stmtsummary.StmtExecInfo{ SchemaName: strings.ToLower(sessVars.CurrentDB), @@ -1247,3 +1336,40 @@ func (a *ExecStmt) GetTextToLog() string { } return sql } + +func (a *ExecStmt) observeStmtBeginForTopSQL() { + vars := a.Ctx.GetSessionVars() + if vars == nil { + return + } + if stats := a.Ctx.GetStmtStats(); stats != nil && topsqlstate.TopSQLEnabled() { + sqlDigest, planDigest := a.getSQLPlanDigest() + stats.OnExecutionBegin(sqlDigest, planDigest) + // This is a special logic prepared for TiKV's SQLExecCount. + vars.StmtCtx.KvExecCounter = stats.CreateKvExecCounter(sqlDigest, planDigest) + } +} + +func (a *ExecStmt) observeStmtFinishedForTopSQL() { + vars := a.Ctx.GetSessionVars() + if vars == nil { + return + } + if stats := a.Ctx.GetStmtStats(); stats != nil && topsqlstate.TopSQLEnabled() { + sqlDigest, planDigest := a.getSQLPlanDigest() + execDuration := time.Since(vars.StartTime) + vars.DurationParse + stats.OnExecutionFinished(sqlDigest, planDigest, execDuration) + } +} + +func (a *ExecStmt) getSQLPlanDigest() ([]byte, []byte) { + var sqlDigest, planDigest []byte + vars := a.Ctx.GetSessionVars() + if _, d := vars.StmtCtx.SQLDigest(); d != nil { + sqlDigest = d.Bytes() + } + if _, d := vars.StmtCtx.GetPlanDigest(); d != nil { + planDigest = d.Bytes() + } + return sqlDigest, planDigest +} diff --git a/executor/admin.go b/executor/admin.go index fec0fec14ca94..abbef043b4819 100644 --- a/executor/admin.go +++ b/executor/admin.go @@ -35,7 +35,6 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/timeutil" @@ -295,15 +294,11 @@ func (e *RecoverIndexExec) buildTableScan(ctx context.Context, txn kv.Transactio func buildRecoverIndexKeyRanges(sctx *stmtctx.StatementContext, tid int64, startHandle kv.Handle) ([]kv.KeyRange, error) { var startKey []byte if startHandle == nil { - startKey = tablecodec.EncodeRowKey(tid, []byte{codec.NilFlag}) + startKey = tablecodec.GenTableRecordPrefix(tid).Next() } else { - startKey = tablecodec.EncodeRowKey(tid, startHandle.Next().Encoded()) + startKey = tablecodec.EncodeRowKey(tid, startHandle.Encoded()).PrefixNext() } - maxVal, err := codec.EncodeKey(sctx, nil, types.MaxValueDatum()) - if err != nil { - return nil, errors.Trace(err) - } - endKey := tablecodec.EncodeRowKey(tid, maxVal) + endKey := tablecodec.GenTableRecordPrefix(tid).PrefixNext() return []kv.KeyRange{{StartKey: startKey, EndKey: endKey}}, nil } @@ -344,6 +339,9 @@ func (e *RecoverIndexExec) backfillIndex(ctx context.Context) (int64, int64, err break } currentHandle = result.currentHandle + if currentHandle.Next().Compare(result.currentHandle) <= 0 { + break // There is no more handles in the table. + } } return totalAddedCnt, totalScanCnt, nil } @@ -467,7 +465,7 @@ func (e *RecoverIndexExec) backfillIndexInTxn(ctx context.Context, txn kv.Transa return result, err } - _, err = e.index.Create(e.ctx, txn, row.idxVals, row.handle, row.rsData) + _, err = e.index.Create(e.ctx, txn, row.idxVals, row.handle, row.rsData, table.WithIgnoreAssertion) if err != nil { return result, err } diff --git a/executor/admin_test.go b/executor/admin_test.go index 72aa436babe9b..3a89fdb0894b1 100644 --- a/executor/admin_test.go +++ b/executor/admin_test.go @@ -17,22 +17,34 @@ package executor_test import ( "context" "fmt" + "os" + "strings" "testing" "time" "github.com/pingcap/errors" + "github.com/pingcap/log" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain" mysql "github.com/pingcap/tidb/errno" - "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/logutil/consistency" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) func TestAdminCheckIndexRange(t *testing.T) { @@ -153,6 +165,7 @@ func TestAdminCheckIndexInCacheTable(t *testing.T) { tk.MustExec("admin check table cache_admin_test;") tk.MustExec("admin check index cache_admin_test c1;") tk.MustExec("admin check index cache_admin_test c2;") + tk.MustExec("alter table cache_admin_test nocache;") tk.MustExec("drop table if exists cache_admin_test;") tk.MustExec(`drop table if exists check_index_test;`) @@ -163,6 +176,7 @@ func TestAdminCheckIndexInCacheTable(t *testing.T) { result.Check(testkit.Rows("1 ef 3", "2 cd 2")) result = tk.MustQuery("admin check index check_index_test a_b (3, 5);") result.Check(testkit.Rows("-1 hi 4", "1 ef 3")) + tk.MustExec("alter table check_index_test nocache;") tk.MustExec("drop table if exists check_index_test;") tk.MustExec("drop table if exists cache_admin_table_with_index_test;") @@ -173,8 +187,12 @@ func TestAdminCheckIndexInCacheTable(t *testing.T) { tk.MustExec("alter table cache_admin_table_without_index_test cache") tk.MustExec("admin checksum table cache_admin_table_with_index_test;") tk.MustExec("admin checksum table cache_admin_table_without_index_test;") + + tk.MustExec("alter table cache_admin_table_with_index_test nocache;") + tk.MustExec("alter table cache_admin_table_without_index_test nocache;") tk.MustExec("drop table if exists cache_admin_table_with_index_test,cache_admin_table_without_index_test;") } + func TestAdminRecoverIndex(t *testing.T) { store, domain, clean := testkit.CreateMockStoreAndDomain(t) defer clean() @@ -227,7 +245,7 @@ func TestAdminRecoverIndex(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.True(t, executor.ErrAdminCheckTable.Equal(err)) + require.True(t, consistency.ErrAdminCheckInconsistent.Equal(err)) err = tk.ExecToErr("admin check index admin_test c2") require.Error(t, err) @@ -324,12 +342,12 @@ func TestClusteredIndexAdminRecoverIndex(t *testing.T) { // Some index entries are missed. txn, err := store.Begin() require.NoError(t, err) - cHandle := testkit.MustNewCommonHandle(t, "1", "3") + cHandle := testutil.MustNewCommonHandle(t, "1", "3") err = indexOpr.Delete(sc, txn, types.MakeDatums(2), cHandle) require.NoError(t, err) err = txn.Commit(context.Background()) require.NoError(t, err) - tk.MustGetErrCode("admin check table t", mysql.ErrAdminCheckTable) + tk.MustGetErrCode("admin check table t", mysql.ErrDataInconsistent) tk.MustGetErrCode("admin check index t idx", mysql.ErrAdminCheckTable) tk.MustQuery("SELECT COUNT(*) FROM t USE INDEX(idx)").Check(testkit.Rows("2")) @@ -368,7 +386,7 @@ func TestAdminRecoverPartitionTableIndex(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.True(t, executor.ErrAdminCheckTable.Equal(err)) + require.True(t, consistency.ErrAdminCheckInconsistent.Equal(err)) r := tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)") r.Check(testkit.Rows("2")) @@ -466,6 +484,18 @@ func TestAdminRecoverIndex1(t *testing.T) { tk.MustExec("admin check index admin_test `primary`") } +// https://github.com/pingcap/tidb/issues/32915. +func TestAdminRecoverIndexEdge(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id bigint(20) primary key, col varchar(255) unique key);") + tk.MustExec("insert into t values(9223372036854775807, 'test');") + tk.MustQuery("admin recover index t col;").Check(testkit.Rows("0 1")) +} + func TestAdminCleanupIndex(t *testing.T) { store, domain, clean := testkit.CreateMockStoreAndDomain(t) defer clean() @@ -783,17 +813,17 @@ func TestClusteredAdminCleanupIndex(t *testing.T) { handle kv.Handle idxVal []types.Datum }{ - {testkit.MustNewCommonHandle(t, "c1_10", "c3_10"), types.MakeDatums(10)}, - {testkit.MustNewCommonHandle(t, "c1_10", "c3_11"), types.MakeDatums(11)}, - {testkit.MustNewCommonHandle(t, "c1_12", "c3_12"), types.MakeDatums(12)}, + {testutil.MustNewCommonHandle(t, "c1_10", "c3_10"), types.MakeDatums(10)}, + {testutil.MustNewCommonHandle(t, "c1_10", "c3_11"), types.MakeDatums(11)}, + {testutil.MustNewCommonHandle(t, "c1_12", "c3_12"), types.MakeDatums(12)}, } c3DanglingIdx := []struct { handle kv.Handle idxVal []types.Datum }{ - {testkit.MustNewCommonHandle(t, "c1_13", "c3_13"), types.MakeDatums("c3_13")}, - {testkit.MustNewCommonHandle(t, "c1_14", "c3_14"), types.MakeDatums("c3_14")}, - {testkit.MustNewCommonHandle(t, "c1_15", "c3_15"), types.MakeDatums("c3_15")}, + {testutil.MustNewCommonHandle(t, "c1_13", "c3_13"), types.MakeDatums("c3_13")}, + {testutil.MustNewCommonHandle(t, "c1_14", "c3_14"), types.MakeDatums("c3_14")}, + {testutil.MustNewCommonHandle(t, "c1_15", "c3_15"), types.MakeDatums("c3_15")}, } txn, err := store.Begin() require.NoError(t, err) @@ -866,8 +896,8 @@ func TestAdminCheckPartitionTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test_p") require.Error(t, err) - require.EqualError(t, err, fmt.Sprintf("[executor:8003]admin_test_p err:[admin:8223]index: != record:&admin.RecordData{Handle:%d, Values:[]types.Datum{types.Datum{k:0x1, decimal:0x0, length:0x0, i:%d, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}}}", i, i)) - require.True(t, executor.ErrAdminCheckTable.Equal(err)) + require.EqualError(t, err, fmt.Sprintf("[admin:8223]data inconsistency in table: admin_test_p, index: idx, handle: %d, index-values:\"\" != record-values:\"handle: %d, values: [KindInt64 %d]\"", i, i, i)) + require.True(t, consistency.ErrAdminCheckInconsistent.Equal(err)) // TODO: fix admin recover for partition table. // r := tk.MustQuery("admin recover index admin_test_p idx") // r.Check(testkit.Rows("0 0")) @@ -894,7 +924,8 @@ func TestAdminCheckPartitionTableFailed(t *testing.T) { err = txn.Commit(context.Background()) require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test_p") - require.EqualError(t, err, fmt.Sprintf("[executor:8133]handle %d, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:%d, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:", i+8, i+8)) + require.Error(t, err) + require.EqualError(t, err, fmt.Sprintf("[admin:8223]data inconsistency in table: admin_test_p, index: idx, handle: %d, index-values:\"handle: %d, values: [KindInt64 %d KindInt64 %d]\" != record-values:\"\"", i+8, i+8, i+8, i+8)) // TODO: fix admin recover for partition table. txn, err = store.Begin() require.NoError(t, err) @@ -916,7 +947,8 @@ func TestAdminCheckPartitionTableFailed(t *testing.T) { err = txn.Commit(context.Background()) require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test_p") - require.EqualError(t, err, fmt.Sprintf("[executor:8134]col c2, handle %d, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:%d, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, decimal:0x0, length:0x0, i:%d, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}, compare err:", i, i+8, i)) + require.Error(t, err) + require.EqualError(t, err, fmt.Sprintf("[executor:8134]data inconsistency in table: admin_test_p, index: idx, col: c2, handle: \"%d\", index-values:\"KindInt64 %d\" != record-values:\"KindInt64 %d\", compare err:", i, i+8, i)) // TODO: fix admin recover for partition table. txn, err = store.Begin() require.NoError(t, err) @@ -928,11 +960,381 @@ func TestAdminCheckPartitionTableFailed(t *testing.T) { } } +const dbName, tblName = "test", "admin_test" + +type inconsistencyTestKit struct { + *testkit.AsyncTestKit + uniqueIndex table.Index + plainIndex table.Index + ctx context.Context + sctx *stmtctx.StatementContext + t *testing.T +} + +type kitOpt struct { + pkColType string + idxColType string + ukColType string + clustered string +} + +func newDefaultOpt() *kitOpt { + return &kitOpt{ + pkColType: "int", + idxColType: "int", + ukColType: "varchar(255)", + } +} + +func newInconsistencyKit(t *testing.T, tk *testkit.AsyncTestKit, opt *kitOpt) *inconsistencyTestKit { + ctx := tk.OpenSession(context.Background(), dbName) + se := testkit.TryRetrieveSession(ctx) + i := &inconsistencyTestKit{ + AsyncTestKit: tk, + ctx: ctx, + sctx: se.GetSessionVars().StmtCtx, + t: t, + } + tk.MustExec(i.ctx, "drop table if exists "+tblName) + tk.MustExec(i.ctx, + fmt.Sprintf("create table %s (c1 %s, c2 %s, c3 %s, primary key(c1) %s, index uk1(c2), index k2(c3))", + tblName, opt.pkColType, opt.idxColType, opt.ukColType, opt.clustered), + ) + i.rebuild() + return i +} + +func (tk *inconsistencyTestKit) rebuild() { + tk.MustExec(tk.ctx, "truncate table "+tblName) + is := domain.GetDomain(testkit.TryRetrieveSession(tk.ctx)).InfoSchema() + tbl, err := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName)) + require.NoError(tk.t, err) + tk.uniqueIndex = tables.NewIndex(tbl.Meta().ID, tbl.Meta(), tbl.Meta().Indices[0]) + tk.plainIndex = tables.NewIndex(tbl.Meta().ID, tbl.Meta(), tbl.Meta().Indices[1]) +} + +type logEntry struct { + entry zapcore.Entry + fields []zapcore.Field +} + +func (l *logEntry) checkMsg(t *testing.T, msg string) { + require.Equal(t, msg, l.entry.Message) +} + +func (l *logEntry) checkField(t *testing.T, requireFields ...zapcore.Field) { + for _, rf := range requireFields { + var f *zapcore.Field + for i, field := range l.fields { + if field.Equals(rf) { + f = &l.fields[i] + break + } + } + require.NotNilf(t, f, "matched log fields %s:%s not found in log", rf.Key, rf) + } + +} + +func (l *logEntry) checkFieldNotEmpty(t *testing.T, fieldName string) { + var f *zapcore.Field + for i, field := range l.fields { + if field.Key == fieldName { + f = &l.fields[i] + break + } + } + require.NotNilf(t, f, "log field %s not found in log", fieldName) + require.NotEmpty(t, f.String) +} + +type logHook struct { + zapcore.Core + logs []logEntry + enc zapcore.Encoder + messageFilter string +} + +func (h *logHook) Write(entry zapcore.Entry, fields []zapcore.Field) error { + h.logs = append(h.logs, logEntry{entry: entry, fields: fields}) + return nil +} + +func (h *logHook) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { + if len(h.messageFilter) > 0 && !strings.Contains(entry.Message, h.messageFilter) { + return nil + } + return ce.AddCore(entry, h) +} + +func (h *logHook) encode(entry *logEntry) (string, error) { + buffer, err := h.enc.EncodeEntry(entry.entry, entry.fields) + if err != nil { + return "", err + } + return buffer.String(), nil +} + +func (h *logHook) checkLogCount(t *testing.T, expected int) { + logsStr := make([]string, len(h.logs)) + for i, item := range h.logs { + var err error + logsStr[i], err = h.encode(&item) + require.NoError(t, err) + } + // Check the length of strings, so that in case the test fails, the error message will be printed. + require.Len(t, logsStr, expected) +} + +func withLogHook(ctx context.Context, msgFilter string) (newCtx context.Context, hook *logHook) { + conf := &log.Config{Level: os.Getenv("log_level"), File: log.FileLogConfig{}} + _, r, _ := log.InitLogger(conf) + enc := log.NewTextEncoder(&config.GetGlobalConfig().Log.ToLogConfig().Config) + hook = &logHook{r.Core, nil, enc, msgFilter} + logger := zap.New(hook) + newCtx = context.WithValue(ctx, logutil.CtxLogKey, logger) + return +} + +func TestCheckFailReport(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := newInconsistencyKit(t, testkit.NewAsyncTestKit(t, store), newDefaultOpt()) + + // row more than unique index + func() { + defer tk.rebuild() + + tk.MustExec(tk.ctx, fmt.Sprintf("insert into %s values(1, 1, '10')", tblName)) + txn, err := store.Begin() + require.NoError(t, err) + require.NoError(t, tk.uniqueIndex.Delete(tk.sctx, txn, types.MakeDatums(1), kv.IntHandle(1))) + require.NoError(t, txn.Commit(tk.ctx)) + + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 1, index-values:\"\" != record-values:\"handle: 1, values: [KindInt64 1]\"", err.Error()) + hook.checkLogCount(t, 1) + hook.logs[0].checkMsg(t, "admin check found data inconsistency") + hook.logs[0].checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "uk1"), + zap.Stringer("row_id", kv.IntHandle(1)), + ) + hook.logs[0].checkFieldNotEmpty(t, "row_mvcc") + }() + + // row more than plain index + func() { + defer tk.rebuild() + + tk.MustExec(tk.ctx, fmt.Sprintf("insert into %s values(1, 1, '10')", tblName)) + txn, err := store.Begin() + require.NoError(t, err) + require.NoError(t, tk.plainIndex.Delete(tk.sctx, txn, []types.Datum{types.NewStringDatum("10")}, kv.IntHandle(1))) + require.NoError(t, txn.Commit(tk.ctx)) + + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: k2, handle: 1, index-values:\"\" != record-values:\"handle: 1, values: [KindString 10]\"", err.Error()) + hook.checkLogCount(t, 1) + hook.logs[0].checkMsg(t, "admin check found data inconsistency") + hook.logs[0].checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "k2"), + zap.Stringer("row_id", kv.IntHandle(1)), + ) + hook.logs[0].checkFieldNotEmpty(t, "row_mvcc") + }() + + // row is missed for plain key + func() { + defer tk.rebuild() + + txn, err := store.Begin() + require.NoError(t, err) + _, err = tk.plainIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewStringDatum("100")}, kv.IntHandle(1), nil) + require.NoError(t, err) + require.NoError(t, txn.Commit(tk.ctx)) + + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: k2, handle: 1, index-values:\"handle: 1, values: [KindString 100 KindInt64 1]\" != record-values:\"\"", err.Error()) + hook.checkLogCount(t, 1) + logEntry := hook.logs[0] + logEntry.checkMsg(t, "admin check found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "k2"), + zap.Stringer("row_id", kv.IntHandle(1)), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc") + logEntry.checkFieldNotEmpty(t, "index_mvcc") + + // test inconsistency check in index lookup + ctx, hook = withLogHook(tk.ctx, "") + rs, err := tk.Exec(ctx, "select * from admin_test use index(k2) where c3 = '100'") + require.NoError(t, err) + _, err = session.GetRows4Test(ctx, testkit.TryRetrieveSession(ctx), rs) + require.Error(t, err) + require.Equal(t, "[executor:8133]data inconsistency in table: admin_test, index: k2, index-count:1 != record-count:0", err.Error()) + hook.checkLogCount(t, 1) + logEntry = hook.logs[0] + logEntry.checkMsg(t, "indexLookup found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "k2"), + zap.Int64("table_cnt", 0), + zap.Int64("index_cnt", 1), + zap.String("missing_handles", `[1]`), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc_0") + }() + + // row is missed for unique key + func() { + defer tk.rebuild() + + txn, err := store.Begin() + require.NoError(t, err) + _, err = tk.uniqueIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewIntDatum(10)}, kv.IntHandle(1), nil) + require.NoError(t, err) + require.NoError(t, txn.Commit(tk.ctx)) + + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 1, index-values:\"handle: 1, values: [KindInt64 10 KindInt64 1]\" != record-values:\"\"", err.Error()) + hook.checkLogCount(t, 1) + logEntry := hook.logs[0] + logEntry.checkMsg(t, "admin check found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "uk1"), + zap.Stringer("row_id", kv.IntHandle(1)), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc") + logEntry.checkFieldNotEmpty(t, "index_mvcc") + + // test inconsistency check in point-get + ctx, hook = withLogHook(tk.ctx, "") + rs, err := tk.Exec(ctx, "select * from admin_test use index(uk1) where c2 = 10") + require.NoError(t, err) + _, err = session.GetRows4Test(ctx, testkit.TryRetrieveSession(ctx), rs) + require.Error(t, err) + hook.checkLogCount(t, 1) + logEntry = hook.logs[0] + logEntry.checkMsg(t, "indexLookup found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "uk1"), + zap.Int64("table_cnt", 0), + zap.Int64("index_cnt", 1), + zap.String("missing_handles", `[1]`), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc_0") + }() + + // handle match but value is different for uk + func() { + defer tk.rebuild() + + tk.MustExec(tk.ctx, fmt.Sprintf("insert into %s values(1, 10, '100')", tblName)) + txn, err := store.Begin() + require.NoError(t, err) + require.NoError(t, tk.uniqueIndex.Delete(tk.sctx, txn, []types.Datum{types.NewIntDatum(10)}, kv.IntHandle(1))) + _, err = tk.uniqueIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewIntDatum(20)}, kv.IntHandle(1), nil) + require.NoError(t, err) + require.NoError(t, txn.Commit(tk.ctx)) + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[executor:8134]data inconsistency in table: admin_test, index: uk1, col: c2, handle: \"1\", index-values:\"KindInt64 20\" != record-values:\"KindInt64 10\", compare err:", err.Error()) + hook.checkLogCount(t, 1) + logEntry := hook.logs[0] + logEntry.checkMsg(t, "admin check found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "uk1"), + zap.Stringer("row_id", kv.IntHandle(1)), + zap.String("col", "c2"), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc") + logEntry.checkFieldNotEmpty(t, "index_mvcc") + }() + + // handle match but value is different for plain key + func() { + defer tk.rebuild() + + tk.MustExec(tk.ctx, fmt.Sprintf("insert into %s values(1, 10, '100')", tblName)) + txn, err := store.Begin() + require.NoError(t, err) + require.NoError(t, tk.plainIndex.Delete(tk.sctx, txn, []types.Datum{types.NewStringDatum("100")}, kv.IntHandle(1))) + _, err = tk.plainIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewStringDatum("200")}, kv.IntHandle(1), nil) + require.NoError(t, err) + require.NoError(t, txn.Commit(tk.ctx)) + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, "[executor:8134]data inconsistency in table: admin_test, index: k2, col: c3, handle: \"1\", index-values:\"KindString 200\" != record-values:\"KindString 100\", compare err:", err.Error()) + hook.checkLogCount(t, 1) + logEntry := hook.logs[0] + logEntry.checkMsg(t, "admin check found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "k2"), + zap.Stringer("row_id", kv.IntHandle(1)), + zap.String("col", "c3"), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc") + logEntry.checkFieldNotEmpty(t, "index_mvcc") + }() + + // test binary column. + opt := newDefaultOpt() + opt.clustered = "clustered" + opt.pkColType = "varbinary(300)" + opt.idxColType = "varbinary(300)" + opt.ukColType = "varbinary(300)" + tk = newInconsistencyKit(t, testkit.NewAsyncTestKit(t, store), newDefaultOpt()) + func() { + defer tk.rebuild() + + txn, err := store.Begin() + require.NoError(t, err) + encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.NewBytesDatum([]byte{1, 0, 1, 0, 0, 1, 1})) + require.Nil(t, err) + hd, err := kv.NewCommonHandle(encoded) + require.NoError(t, err) + _, err = tk.uniqueIndex.Create(mock.NewContext(), txn, []types.Datum{types.NewBytesDatum([]byte{1, 1, 0, 1, 1, 1, 1, 0})}, hd, nil) + require.NoError(t, err) + require.NoError(t, txn.Commit(tk.ctx)) + + ctx, hook := withLogHook(tk.ctx, "inconsistency") + _, err = tk.Exec(ctx, "admin check table admin_test") + require.Error(t, err) + require.Equal(t, `[admin:8223]data inconsistency in table: admin_test, index: uk1, handle: 282574488403969, index-values:"handle: 282574488403969, values: [KindInt64 282578800083201 KindInt64 282574488403969]" != record-values:""`, err.Error()) + hook.checkLogCount(t, 1) + logEntry := hook.logs[0] + logEntry.checkMsg(t, "admin check found data inconsistency") + logEntry.checkField(t, + zap.String("table_name", "admin_test"), + zap.String("index_name", "uk1"), + zap.Stringer("row_id", kv.IntHandle(282574488403969)), + ) + logEntry.checkFieldNotEmpty(t, "row_mvcc") + logEntry.checkFieldNotEmpty(t, "index_mvcc") + }() +} + func TestAdminCheckTable(t *testing.T) { // test NULL value. store, clean := testkit.CreateMockStore(t) defer clean() - tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`CREATE TABLE test_null ( @@ -1157,12 +1559,12 @@ func TestAdminCheckTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8003]admin_test err:[admin:8223]index: != record:&admin.RecordData{Handle:-1, Values:[]types.Datum{types.Datum{k:0x1, decimal:0x0, length:0x0, i:-10, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}}}") - require.True(t, executor.ErrAdminCheckTable.Equal(err)) + require.EqualError(t, err, "[admin:8223]data inconsistency in table: admin_test, index: c2, handle: -1, index-values:\"\" != record-values:\"handle: -1, values: [KindInt64 -10]\"") + require.True(t, consistency.ErrAdminCheckInconsistent.Equal(err)) tk.MustExec("set @@tidb_redact_log=1;") err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8003]admin_test err:[admin:8223]index:\"?\" != record:\"?\"") + require.EqualError(t, err, "[admin:8223]data inconsistency in table: admin_test, index: c2, handle: ?, index-values:\"?\" != record-values:\"?\"") tk.MustExec("set @@tidb_redact_log=0;") r := tk.MustQuery("admin recover index admin_test c2") r.Check(testkit.Rows("1 7")) @@ -1179,11 +1581,11 @@ func TestAdminCheckTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8133]handle 0, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:0, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:") + require.EqualError(t, err, "[admin:8223]data inconsistency in table: admin_test, index: c2, handle: 0, index-values:\"handle: 0, values: [KindInt64 0 KindInt64 0]\" != record-values:\"\"") tk.MustExec("set @@tidb_redact_log=1;") err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8133]handle \"?\", index:\"?\" != record:\"?\"") + require.EqualError(t, err, "[admin:8223]data inconsistency in table: admin_test, index: c2, handle: ?, index-values:\"?\" != record-values:\"?\"") tk.MustExec("set @@tidb_redact_log=0;") // Add one row of index. @@ -1202,11 +1604,11 @@ func TestAdminCheckTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle 2, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:13, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, decimal:0x0, length:0x0, i:12, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}, compare err:") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"2\", index-values:\"KindInt64 13\" != record-values:\"KindInt64 12\", compare err:") tk.MustExec("set @@tidb_redact_log=1;") err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle \"?\", index:\"?\" != record:\"?\", compare err:\"?\"") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"?\", index-values:\"?\" != record-values:\"?\", compare err:\"?\"") tk.MustExec("set @@tidb_redact_log=0;") // Table count = index count. @@ -1221,11 +1623,11 @@ func TestAdminCheckTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle 10, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:19, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, decimal:0x0, length:0x0, i:20, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}, compare err:") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"10\", index-values:\"KindInt64 19\" != record-values:\"KindInt64 20\", compare err:") tk.MustExec("set @@tidb_redact_log=1;") err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle \"?\", index:\"?\" != record:\"?\", compare err:\"?\"") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"?\", index-values:\"?\" != record-values:\"?\", compare err:\"?\"") tk.MustExec("set @@tidb_redact_log=0;") // Table count = index count. @@ -1240,11 +1642,11 @@ func TestAdminCheckTableFailed(t *testing.T) { require.NoError(t, err) err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle 10, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:19, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, decimal:0x0, length:0x0, i:20, collation:\"\", b:[]uint8(nil), x:interface {}(nil)}, compare err:") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"10\", index-values:\"KindInt64 19\" != record-values:\"KindInt64 20\", compare err:") tk.MustExec("set @@tidb_redact_log=1;") err = tk.ExecToErr("admin check table admin_test") require.Error(t, err) - require.EqualError(t, err, "[executor:8134]col c2, handle \"?\", index:\"?\" != record:\"?\", compare err:\"?\"") + require.EqualError(t, err, "[executor:8134]data inconsistency in table: admin_test, index: c2, col: c2, handle: \"?\", index-values:\"?\" != record-values:\"?\", compare err:\"?\"") tk.MustExec("set @@tidb_redact_log=0;") // Recover records. diff --git a/executor/aggfuncs/builder.go b/executor/aggfuncs/builder.go index e5d9eafbd2a0c..4da578936d96e 100644 --- a/executor/aggfuncs/builder.go +++ b/executor/aggfuncs/builder.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" "go.uber.org/zap" ) @@ -377,7 +378,8 @@ func buildMaxMin(aggFuncDesc *aggregation.AggFuncDesc, ordinal int, isMax bool) ordinal: ordinal, retTp: aggFuncDesc.RetTp, }, - isMax: isMax, + isMax: isMax, + collator: collate.GetCollator(aggFuncDesc.RetTp.Collate), } evalType, fieldType := aggFuncDesc.RetTp.EvalType(), aggFuncDesc.RetTp if fieldType.Tp == mysql.TypeBit { diff --git a/executor/aggfuncs/func_avg.go b/executor/aggfuncs/func_avg.go index 17203aad50b7e..15713eedab880 100644 --- a/executor/aggfuncs/func_avg.go +++ b/executor/aggfuncs/func_avg.go @@ -81,7 +81,7 @@ func (e *baseAvgDecimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Par if frac == -1 { frac = mysql.MaxDecimalScale } - err = finalResult.Round(finalResult, frac, types.ModeHalfEven) + err = finalResult.Round(finalResult, frac, types.ModeHalfUp) if err != nil { return err } @@ -276,7 +276,7 @@ func (e *avgOriginal4DistinctDecimal) AppendFinalResult2Chunk(sctx sessionctx.Co if frac == -1 { frac = mysql.MaxDecimalScale } - err = finalResult.Round(finalResult, frac, types.ModeHalfEven) + err = finalResult.Round(finalResult, frac, types.ModeHalfUp) if err != nil { return err } diff --git a/executor/aggfuncs/func_first_row.go b/executor/aggfuncs/func_first_row.go index d93724d0eda4b..88f9d2bf75c5e 100644 --- a/executor/aggfuncs/func_first_row.go +++ b/executor/aggfuncs/func_first_row.go @@ -485,7 +485,7 @@ func (e *firstRow4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr P if frac == -1 { frac = mysql.MaxDecimalScale } - err := p.val.Round(&p.val, frac, types.ModeHalfEven) + err := p.val.Round(&p.val, frac, types.ModeHalfUp) if err != nil { return err } diff --git a/executor/aggfuncs/func_json_arrayagg_test.go b/executor/aggfuncs/func_json_arrayagg_test.go index 6f9ff09f9ed81..1649037dc6b39 100644 --- a/executor/aggfuncs/func_json_arrayagg_test.go +++ b/executor/aggfuncs/func_json_arrayagg_test.go @@ -29,7 +29,7 @@ import ( func TestMergePartialResult4JsonArrayagg(t *testing.T) { typeList := []byte{mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeString, mysql.TypeJSON} - var tests []aggTest + tests := make([]aggTest, 0, len(typeList)) numRows := 5 for _, argType := range typeList { entries1 := make([]interface{}, 0) @@ -66,7 +66,7 @@ func TestMergePartialResult4JsonArrayagg(t *testing.T) { func TestJsonArrayagg(t *testing.T) { typeList := []byte{mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeString, mysql.TypeJSON} - var tests []aggTest + tests := make([]aggTest, 0, len(typeList)) numRows := 5 for _, argType := range typeList { @@ -129,7 +129,7 @@ func jsonArrayaggMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (m func TestMemJsonArrayagg(t *testing.T) { typeList := []byte{mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeString, mysql.TypeJSON} - var tests []aggMemTest + tests := make([]aggMemTest, 0, len(typeList)) numRows := 5 for _, argType := range typeList { tests = append(tests, buildAggMemTester(ast.AggFuncJsonArrayagg, argType, numRows, aggfuncs.DefPartialResult4JsonArrayagg+aggfuncs.DefSliceSize, jsonArrayaggMemDeltaGens, false)) diff --git a/executor/aggfuncs/func_max_min.go b/executor/aggfuncs/func_max_min.go index 504c179516b91..73e49264472fb 100644 --- a/executor/aggfuncs/func_max_min.go +++ b/executor/aggfuncs/func_max_min.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/stringutil" ) @@ -234,7 +235,8 @@ type partialResult4MaxMinSet struct { type baseMaxMinAggFunc struct { baseAggFunc - isMax bool + isMax bool + collator collate.Collator } type maxMin4Int struct { @@ -820,7 +822,7 @@ func (e *maxMin4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Par if frac == -1 { frac = mysql.MaxDecimalScale } - err := p.val.Round(&p.val, frac, types.ModeHalfEven) + err := p.val.Round(&p.val, frac, types.ModeHalfUp) if err != nil { return err } @@ -1494,7 +1496,7 @@ func (e *maxMin4Enum) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup [ continue } en := d.GetMysqlEnum() - if e.isMax && en.Name > p.val.Name || !e.isMax && en.Name < p.val.Name { + if e.isMax && e.collator.Compare(en.Name, p.val.Name) > 0 || !e.isMax && e.collator.Compare(en.Name, p.val.Name) < 0 { oldMem := len(p.val.Name) newMem := len(en.Name) memDelta += int64(newMem - oldMem) @@ -1513,7 +1515,7 @@ func (e *maxMin4Enum) MergePartialResult(sctx sessionctx.Context, src, dst Parti *p2 = *p1 return 0, nil } - if e.isMax && p1.val.Name > p2.val.Name || !e.isMax && p1.val.Name < p2.val.Name { + if e.isMax && e.collator.Compare(p1.val.Name, p2.val.Name) > 0 || !e.isMax && e.collator.Compare(p1.val.Name, p2.val.Name) < 0 { p2.val, p2.isNull = p1.val, false } return 0, nil @@ -1561,7 +1563,7 @@ func (e *maxMin4Set) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup [] continue } s := d.GetMysqlSet() - if e.isMax && s.Name > p.val.Name || !e.isMax && s.Name < p.val.Name { + if e.isMax && e.collator.Compare(s.Name, p.val.Name) > 0 || !e.isMax && e.collator.Compare(s.Name, p.val.Name) < 0 { oldMem := len(p.val.Name) newMem := len(s.Name) memDelta += int64(newMem - oldMem) @@ -1580,7 +1582,7 @@ func (e *maxMin4Set) MergePartialResult(sctx sessionctx.Context, src, dst Partia *p2 = *p1 return 0, nil } - if e.isMax && p1.val.Name > p2.val.Name || !e.isMax && p1.val.Name < p2.val.Name { + if e.isMax && e.collator.Compare(p1.val.Name, p2.val.Name) > 0 || !e.isMax && e.collator.Compare(p1.val.Name, p2.val.Name) < 0 { p2.val, p2.isNull = p1.val, false } return 0, nil diff --git a/executor/aggfuncs/func_sum.go b/executor/aggfuncs/func_sum.go index 1d0bf624172cb..0e153a51d98d2 100644 --- a/executor/aggfuncs/func_sum.go +++ b/executor/aggfuncs/func_sum.go @@ -178,7 +178,7 @@ func (e *sum4Decimal) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Partia if frac == -1 { frac = mysql.MaxDecimalScale } - err := p.val.Round(&p.val, frac, types.ModeHalfEven) + err := p.val.Round(&p.val, frac, types.ModeHalfUp) if err != nil { return err } diff --git a/executor/aggfuncs/main_test.go b/executor/aggfuncs/main_test.go index f46a63bba4d9a..de63aaa396469 100644 --- a/executor/aggfuncs/main_test.go +++ b/executor/aggfuncs/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/executor/aggregate_test.go b/executor/aggregate_test.go index 976775ce5dc4c..5d2e45cb5b3ce 100644 --- a/executor/aggregate_test.go +++ b/executor/aggregate_test.go @@ -25,7 +25,6 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/executor" @@ -799,7 +798,7 @@ func TestOnlyFullGroupBy(t *testing.T) { // tk.MustQuery("select * from (select * from t) as e group by a") // tk.MustQuery("select * from (select * from t) as e group by b,d") // err = tk.ExecToErr("select * from (select * from t) as e group by b,c") - // c.Assert(terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), IsTrue) + // require.Truef(t, terror.ErrorEqual(err, plannercore.ErrFieldNotInGroupBy), "err %v", err) // test order by tk.MustQuery("select c from t group by c,d order by d") @@ -928,18 +927,6 @@ func TestHaving(t *testing.T) { tk.MustQuery("select 1 from t group by c1 having sum(abs(c2 + c3)) = c1").Check(testkit.Rows("1")) } -func TestIssue26496(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - - tk.MustExec("drop table if exists UK_NSPRE_19416") - tk.MustExec("CREATE TABLE `UK_NSPRE_19416` ( `COL1` binary(20) DEFAULT NULL, `COL2` varchar(20) DEFAULT NULL, `COL4` datetime DEFAULT NULL, `COL3` bigint(20) DEFAULT NULL, `COL5` float DEFAULT NULL, UNIQUE KEY `UK_COL1` (`COL1`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin") - tk.MustExec("insert into `UK_NSPRE_19416`(col1) values (0xc5b428e2ebc1b78f0b183899a8df55c88a333f86), (0x004dad637b37cc4a9742484ab93f97ede2ab8bd5), (0x550c4a4390ba14fd6d382dd29063e10210c99381)") - tk.MustQuery("select t1.col1, count(t2.col1) from UK_NSPRE_19416 as t1 left join UK_NSPRE_19416 as t2 on t1.col1 = t2.col1 where t1.col1 in (0x550C4A4390BA14FD6D382DD29063E10210C99381, 0x004DAD637B37CC4A9742484AB93F97EDE2AB8BD5, 0xC5B428E2EBC1B78F0B183899A8DF55C88A333F86) group by t1.col1, t2.col1 having t1.col1 in (0x9B4B48FEBA9225BACF8F9ADEAEE810AEC26DC7A2, 0x25A6C4FAD832F8E0267AAA504CFAE767565C8B84, 0xE26E5B0080EC5A8156DACE67D13B239500E540E6)").Check(nil) -} - func TestAggEliminator(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1390,7 +1377,7 @@ func TestIssue20658(t *testing.T) { } tk.MustExec(fmt.Sprintf("insert into t values %s;", insertSQL.String())) - mustParseAndSort := func(rows [][]interface{}, cmt CommentInterface) []float64 { + mustParseAndSort := func(rows [][]interface{}, cmt string) []float64 { ret := make([]float64, len(rows)) for i := 0; i < len(rows); i++ { rowStr := rows[i][0].(string) @@ -1408,9 +1395,9 @@ func TestIssue20658(t *testing.T) { for _, sql := range sqls { tk.MustExec("set @@tidb_streamagg_concurrency = 1;") exp := tk.MustQuery(sql).Rows() - expected := mustParseAndSort(exp, Commentf("sql: %s; seed: %d", sql, randSeed)) + expected := mustParseAndSort(exp, fmt.Sprintf("sql: %s; seed: %d", sql, randSeed)) for _, con := range []int{2, 4, 8} { - comment := Commentf("sql: %s; concurrency: %d, seed: %d", sql, con, randSeed) + comment := fmt.Sprintf("sql: %s; concurrency: %d, seed: %d", sql, con, randSeed) tk.MustExec(fmt.Sprintf("set @@tidb_streamagg_concurrency=%d;", con)) er := tk.MustQuery("explain format = 'brief' " + sql).Rows() ok := false diff --git a/executor/analyze.go b/executor/analyze.go index 372108764babd..d9bec2de62ca6 100644 --- a/executor/analyze.go +++ b/executor/analyze.go @@ -43,13 +43,13 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" derr "github.com/pingcap/tidb/store/driver/error" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" @@ -59,6 +59,7 @@ import ( "github.com/pingcap/tidb/util/timeutil" "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/tikv" + atomicutil "go.uber.org/atomic" "go.uber.org/zap" ) @@ -67,9 +68,10 @@ var _ Executor = &AnalyzeExec{} // AnalyzeExec represents Analyze executor. type AnalyzeExec struct { baseExecutor - tasks []*analyzeTask - wg *sync.WaitGroup - opts map[ast.AnalyzeOptionType]uint64 + tasks []*analyzeTask + wg util.WaitGroupWrapper + opts map[ast.AnalyzeOptionType]uint64 + OptionsMap map[int64]core.V2AnalyzeOptions } var ( @@ -91,17 +93,25 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { } taskCh := make(chan *analyzeTask, len(e.tasks)) resultsCh := make(chan *statistics.AnalyzeResults, len(e.tasks)) - e.wg.Add(concurrency) + if len(e.tasks) < concurrency { + concurrency = len(e.tasks) + } for i := 0; i < concurrency; i++ { - go e.analyzeWorker(taskCh, resultsCh, i == 0) + e.wg.Run(func() { e.analyzeWorker(taskCh, resultsCh) }) } for _, task := range e.tasks { - statistics.AddNewAnalyzeJob(task.job) + AddNewAnalyzeJob(e.ctx, task.job) } + failpoint.Inject("mockKillPendingAnalyzeJob", func() { + domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + }) for _, task := range e.tasks { taskCh <- task } close(taskCh) + e.wg.Wait() + close(resultsCh) + statsHandle := domain.GetDomain(e.ctx).StatsHandle() panicCnt := 0 @@ -123,10 +133,16 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { // The meaning of key in map is the structure that used to store the tableID and indexID. // The meaning of value in map is some additional information needed to build global-level stats. globalStatsMap := make(map[globalStatsKey]globalStatsInfo) - finishJobWithLogFn := func(ctx context.Context, job *statistics.AnalyzeJob, meetError bool) { - job.Finish(meetError) + finishJobWithLogFn := func(ctx context.Context, job *statistics.AnalyzeJob, analyzeErr error) { + FinishAnalyzeJob(e.ctx, job, analyzeErr) if job != nil { - logutil.Logger(ctx).Info(fmt.Sprintf("analyze table `%s`.`%s` has %s", job.DBName, job.TableName, job.State), + var state string + if analyzeErr != nil { + state = statistics.AnalyzeFailed + } else { + state = statistics.AnalyzeFinished + } + logutil.Logger(ctx).Info(fmt.Sprintf("analyze table `%s`.`%s` has %s", job.DBName, job.TableName, state), zap.String("partition", job.PartitionName), zap.String("job info", job.JobInfo), zap.Time("start time", job.StartTime), @@ -146,7 +162,7 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { } else { logutil.Logger(ctx).Error("analyze failed", zap.Error(err)) } - finishJobWithLogFn(ctx, results.Job, true) + finishJobWithLogFn(ctx, results.Job, err) continue } if results.TableID.IsPartitionTable() && needGlobalStats { @@ -174,20 +190,30 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { if err1 := statsHandle.SaveTableStatsToStorage(results, results.TableID.IsPartitionTable() && needGlobalStats); err1 != nil { err = err1 logutil.Logger(ctx).Error("save table stats to storage failed", zap.Error(err)) - finishJobWithLogFn(ctx, results.Job, true) + finishJobWithLogFn(ctx, results.Job, err) } else { - finishJobWithLogFn(ctx, results.Job, false) + finishJobWithLogFn(ctx, results.Job, nil) + // Dump stats to historical storage. + if err := e.recordHistoricalStats(results.TableID.TableID); err != nil { + logutil.BgLogger().Error("record historical stats failed", zap.Error(err)) + } } } - for _, task := range e.tasks { - statistics.MoveToHistory(task.job) - } + failpoint.Inject("mockKillFinishedAnalyzeJob", func() { + domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + }) if err != nil { return err } if needGlobalStats { for globalStatsID, info := range globalStatsMap { - globalStats, err := statsHandle.MergePartitionStats2GlobalStatsByTableID(e.ctx, e.opts, e.ctx.GetInfoSchema().(infoschema.InfoSchema), globalStatsID.tableID, info.isIndex, info.histIDs) + globalOpts := e.opts + if e.OptionsMap != nil { + if v2Options, ok := e.OptionsMap[globalStatsID.tableID]; ok { + globalOpts = v2Options.FilledOpts + } + } + globalStats, err := statsHandle.MergePartitionStats2GlobalStatsByTableID(e.ctx, globalOpts, e.ctx.GetInfoSchema().(infoschema.InfoSchema), globalStatsID.tableID, info.isIndex, info.histIDs) if err != nil { if types.ErrPartitionStatsMissing.Equal(err) { // When we find some partition-level stats are missing, we need to report warning. @@ -203,12 +229,84 @@ func (e *AnalyzeExec) Next(ctx context.Context, req *chunk.Chunk) error { if err != nil { logutil.Logger(ctx).Error("save global-level stats to storage failed", zap.Error(err)) } + // Dump stats to historical storage. + if err := e.recordHistoricalStats(globalStatsID.tableID); err != nil { + logutil.BgLogger().Error("record historical stats failed", zap.Error(err)) + } } } } + err = e.saveAnalyzeOptsV2() + if err != nil { + e.ctx.GetSessionVars().StmtCtx.AppendWarning(err) + } return statsHandle.Update(e.ctx.GetInfoSchema().(infoschema.InfoSchema)) } +func (e *AnalyzeExec) saveAnalyzeOptsV2() error { + if !variable.PersistAnalyzeOptions.Load() || len(e.OptionsMap) == 0 { + return nil + } + sql := new(strings.Builder) + sqlexec.MustFormatSQL(sql, "REPLACE INTO mysql.analyze_options (table_id,sample_num,sample_rate,buckets,topn,column_choice,column_ids) VALUES ") + idx := 0 + for _, opts := range e.OptionsMap { + sampleNum := opts.RawOpts[ast.AnalyzeOptNumSamples] + sampleRate := float64(0) + if val, ok := opts.RawOpts[ast.AnalyzeOptSampleRate]; ok { + sampleRate = math.Float64frombits(val) + } + buckets := opts.RawOpts[ast.AnalyzeOptNumBuckets] + topn := int64(-1) + if val, ok := opts.RawOpts[ast.AnalyzeOptNumTopN]; ok { + topn = int64(val) + } + colChoice := opts.ColChoice.String() + colIDs := make([]string, len(opts.ColumnList)) + for i, colInfo := range opts.ColumnList { + colIDs[i] = strconv.FormatInt(colInfo.ID, 10) + } + colIDStrs := strings.Join(colIDs, ",") + sqlexec.MustFormatSQL(sql, "(%?,%?,%?,%?,%?,%?,%?)", opts.PhyTableID, sampleNum, sampleRate, buckets, topn, colChoice, colIDStrs) + if idx < len(e.OptionsMap)-1 { + sqlexec.MustFormatSQL(sql, ",") + } + idx += 1 + } + exec := e.ctx.(sqlexec.RestrictedSQLExecutor) + _, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, sql.String()) + if err != nil { + return err + } + return nil +} + +func (e *AnalyzeExec) recordHistoricalStats(tableID int64) error { + statsHandle := domain.GetDomain(e.ctx).StatsHandle() + historicalStatsEnabled, err := statsHandle.CheckHistoricalStatsEnable() + if err != nil { + return errors.Errorf("check tidb_enable_historical_stats failed: %v", err) + } + if !historicalStatsEnabled { + return nil + } + + is := domain.GetDomain(e.ctx).InfoSchema() + tbl, existed := is.TableByID(tableID) + if !existed { + return errors.Errorf("cannot get table by id %d", tableID) + } + tblInfo := tbl.Meta() + dbInfo, existed := is.SchemaByTable(tblInfo) + if !existed { + return errors.Errorf("cannot get DBInfo by TableID %d", tableID) + } + if _, err := statsHandle.RecordHistoricalStatsToStorage(dbInfo.Name.O, tblInfo); err != nil { + return errors.Errorf("record table %s.%s's historical stats failed", dbInfo.Name.O, tblInfo.Name.O) + } + return nil +} + func getBuildStatsConcurrency(ctx sessionctx.Context) (int, error) { sessionVars := ctx.GetSessionVars() concurrency, err := variable.GetSessionOrGlobalSystemVar(sessionVars, variable.TiDBBuildStatsConcurrency) @@ -241,7 +339,7 @@ type analyzeTask struct { var errAnalyzeWorkerPanic = errors.New("analyze worker panic") -func (e *AnalyzeExec) analyzeWorker(taskCh <-chan *analyzeTask, resultsCh chan<- *statistics.AnalyzeResults, isCloseChanThread bool) { +func (e *AnalyzeExec) analyzeWorker(taskCh <-chan *analyzeTask, resultsCh chan<- *statistics.AnalyzeResults) { var task *analyzeTask defer func() { if r := recover(); r != nil { @@ -255,11 +353,6 @@ func (e *AnalyzeExec) analyzeWorker(taskCh <-chan *analyzeTask, resultsCh chan<- Job: task.job, } } - e.wg.Done() - if isCloseChanThread { - e.wg.Wait() - close(resultsCh) - } }() for { var ok bool @@ -267,7 +360,7 @@ func (e *AnalyzeExec) analyzeWorker(taskCh <-chan *analyzeTask, resultsCh chan<- if !ok { break } - task.job.Start() + StartAnalyzeJob(e.ctx, task.job) switch task.taskType { case colTask: resultsCh <- analyzeColumnsPushdown(task.colExec) @@ -400,7 +493,7 @@ func (e *AnalyzeIndexExec) fetchAnalyzeResult(ranges []*ranger.Range, isNullRang return err } ctx := context.TODO() - result, err := distsql.Analyze(ctx, e.ctx.GetClient(), kvReq, e.ctx.GetSessionVars().KVVars, e.ctx.GetSessionVars().InRestrictedSQL, e.ctx.GetSessionVars().StmtCtx.MemTracker) + result, err := distsql.Analyze(ctx, e.ctx.GetClient(), kvReq, e.ctx.GetSessionVars().KVVars, e.ctx.GetSessionVars().InRestrictedSQL, e.ctx.GetSessionVars().StmtCtx) if err != nil { return err } @@ -428,7 +521,7 @@ func (e *AnalyzeIndexExec) open(ranges []*ranger.Range, considerNull bool) error } func updateIndexResult( - ctx *stmtctx.StatementContext, + ctx sessionctx.Context, resp *tipb.AnalyzeIndexResp, job *statistics.AnalyzeJob, hist *statistics.Histogram, @@ -450,9 +543,9 @@ func updateIndexResult( needCMS := cms != nil respHist := statistics.HistogramFromProto(resp.Hist) if job != nil { - job.Update(int64(respHist.TotalRowCount())) + UpdateAnalyzeJob(ctx, job, int64(respHist.TotalRowCount())) } - hist, err = statistics.MergeHistograms(ctx, hist, respHist, numBuckets, statsVer) + hist, err = statistics.MergeHistograms(ctx.GetSessionVars().StmtCtx, hist, respHist, numBuckets, statsVer) if err != nil { return nil, nil, nil, nil, err } @@ -492,6 +585,15 @@ func (e *AnalyzeIndexExec) buildStatsFromResult(result distsql.SelectResult, nee statsVer = int(*e.analyzePB.IdxReq.Version) } for { + failpoint.Inject("mockKillRunningAnalyzeIndexJob", func() { + domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + }) + if atomic.LoadUint32(&e.ctx.GetSessionVars().Killed) == 1 { + return nil, nil, nil, nil, errors.Trace(ErrQueryInterrupted) + } + failpoint.Inject("mockSlowAnalyzeIndex", func() { + time.Sleep(1000 * time.Second) + }) data, err := result.NextRaw(context.TODO()) if err != nil { return nil, nil, nil, nil, err @@ -504,7 +606,7 @@ func (e *AnalyzeIndexExec) buildStatsFromResult(result distsql.SelectResult, nee if err != nil { return nil, nil, nil, nil, err } - hist, cms, fms, topn, err = updateIndexResult(e.ctx.GetSessionVars().StmtCtx, resp, e.job, hist, cms, fms, topn, + hist, cms, fms, topn, err = updateIndexResult(e.ctx, resp, e.job, hist, cms, fms, topn, e.idxInfo, int(e.opts[ast.AnalyzeOptNumBuckets]), int(e.opts[ast.AnalyzeOptNumTopN]), statsVer) if err != nil { return nil, nil, nil, nil, err @@ -604,8 +706,11 @@ func analyzeColumnsPushdown(colExec *AnalyzeColumnsExec) *statistics.AnalyzeResu // subIndexWorkerWg is better to be initialized in handleNDVForSpecialIndexes, however if we do so, golang would // report unexpected/unreasonable data race error on subIndexWorkerWg when running TestAnalyzeVirtualCol test // case with `-race` flag now. - colExec.subIndexWorkerWg = &sync.WaitGroup{} - go colExec.handleNDVForSpecialIndexes(specialIndexes, idxNDVPushDownCh) + var wg util.WaitGroupWrapper + wg.Run(func() { + colExec.handleNDVForSpecialIndexes(specialIndexes, idxNDVPushDownCh) + }) + defer wg.Wait() count, hists, topns, fmSketches, extStats, err := colExec.buildSamplingStats(ranges, collExtStats, specialIndexesOffsets, idxNDVPushDownCh) if err != nil { return &statistics.AnalyzeResults{Err: err, Job: colExec.job} @@ -717,9 +822,8 @@ type AnalyzeColumnsExec struct { indexes []*model.IndexInfo core.AnalyzeInfo - subIndexWorkerWg *sync.WaitGroup - samplingBuilderWg *sync.WaitGroup - samplingMergeWg *sync.WaitGroup + samplingBuilderWg *notifyErrorWaitGroupWrapper + samplingMergeWg *util.WaitGroupWrapper schemaForVirtualColEval *expression.Schema baseCount int64 @@ -763,7 +867,7 @@ func (e *AnalyzeColumnsExec) buildResp(ranges []*ranger.Range) (distsql.SelectRe return nil, err } ctx := context.TODO() - result, err := distsql.Analyze(ctx, e.ctx.GetClient(), kvReq, e.ctx.GetSessionVars().KVVars, e.ctx.GetSessionVars().InRestrictedSQL, e.ctx.GetSessionVars().StmtCtx.MemTracker) + result, err := distsql.Analyze(ctx, e.ctx.GetClient(), kvReq, e.ctx.GetSessionVars().KVVars, e.ctx.GetSessionVars().InRestrictedSQL, e.ctx.GetSessionVars().StmtCtx) if err != nil { return nil, err } @@ -807,9 +911,18 @@ func (e AnalyzeColumnsExec) decodeSampleDataWithVirtualColumn( return nil } -func readDataAndSendTask(handler *tableResultHandler, mergeTaskCh chan []byte) error { +func readDataAndSendTask(ctx sessionctx.Context, handler *tableResultHandler, mergeTaskCh chan []byte) error { defer close(mergeTaskCh) for { + failpoint.Inject("mockKillRunningV2AnalyzeJob", func() { + domain.GetDomain(ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + }) + if atomic.LoadUint32(&ctx.GetSessionVars().Killed) == 1 { + return errors.Trace(ErrQueryInterrupted) + } + failpoint.Inject("mockSlowAnalyzeV2", func() { + time.Sleep(1000 * time.Second) + }) data, err := handler.nextRaw(context.TODO()) if err != nil { return errors.Trace(err) @@ -856,12 +969,12 @@ func (e *AnalyzeColumnsExec) buildSamplingStats( } mergeResultCh := make(chan *samplingMergeResult, statsConcurrency) mergeTaskCh := make(chan []byte, statsConcurrency) - e.samplingMergeWg = &sync.WaitGroup{} + e.samplingMergeWg = &util.WaitGroupWrapper{} e.samplingMergeWg.Add(statsConcurrency) for i := 0; i < statsConcurrency; i++ { go e.subMergeWorker(mergeResultCh, mergeTaskCh, l, i == 0) } - if err = readDataAndSendTask(e.resultHandler, mergeTaskCh); err != nil { + if err = readDataAndSendTask(e.ctx, e.resultHandler, mergeTaskCh); err != nil { return 0, nil, nil, nil, nil, err } @@ -929,13 +1042,16 @@ func (e *AnalyzeColumnsExec) buildSamplingStats( fmSketches = make([]*statistics.FMSketch, 0, totalLen) buildResultChan := make(chan error, totalLen) buildTaskChan := make(chan *samplingBuildTask, totalLen) - e.samplingBuilderWg = &sync.WaitGroup{} - e.samplingBuilderWg.Add(statsConcurrency) + if totalLen < statsConcurrency { + statsConcurrency = totalLen + } + e.samplingBuilderWg = newNotifyErrorWaitGroupWrapper(buildResultChan) sampleCollectors := make([]*statistics.SampleCollector, len(e.colsInfo)) + exitCh := make(chan struct{}) + e.samplingBuilderWg.Add(statsConcurrency) for i := 0; i < statsConcurrency; i++ { - go e.subBuildWorker(buildResultChan, buildTaskChan, hists, topns, sampleCollectors, i == 0) + e.samplingBuilderWg.Run(func() { e.subBuildWorker(buildResultChan, buildTaskChan, hists, topns, sampleCollectors, exitCh) }) } - for i, col := range e.colsInfo { buildTaskChan <- &samplingBuildTask{ id: col.ID, @@ -949,6 +1065,8 @@ func (e *AnalyzeColumnsExec) buildSamplingStats( indexPushedDownResult := <-idxNDVPushDownCh if indexPushedDownResult.err != nil { + close(exitCh) + e.samplingBuilderWg.Wait() return 0, nil, nil, nil, nil, indexPushedDownResult.err } for _, offset := range indexesWithVirtualColOffsets { @@ -1020,12 +1138,16 @@ func (e *AnalyzeColumnsExec) handleNDVForSpecialIndexes(indexInfos []*model.Inde statsConcurrncy, err := getBuildStatsConcurrency(e.ctx) taskCh := make(chan *analyzeTask, len(tasks)) for _, task := range tasks { - statistics.AddNewAnalyzeJob(task.job) + AddNewAnalyzeJob(e.ctx, task.job) } resultsCh := make(chan *statistics.AnalyzeResults, len(tasks)) - e.subIndexWorkerWg.Add(statsConcurrncy) + if len(tasks) < statsConcurrncy { + statsConcurrncy = len(tasks) + } + var subIndexWorkerWg = NewAnalyzeResultsNotifyWaitGroupWrapper(resultsCh) + subIndexWorkerWg.Add(statsConcurrncy) for i := 0; i < statsConcurrncy; i++ { - go e.subIndexWorkerForNDV(taskCh, resultsCh, i == 0) + subIndexWorkerWg.Run(func() { e.subIndexWorkerForNDV(taskCh, resultsCh) }) } for _, task := range tasks { taskCh <- task @@ -1041,15 +1163,14 @@ func (e *AnalyzeColumnsExec) handleNDVForSpecialIndexes(indexInfos []*model.Inde break } if results.Err != nil { - results.Job.Finish(true) err = results.Err + FinishAnalyzeJob(e.ctx, results.Job, err) if err == errAnalyzeWorkerPanic { panicCnt++ } continue } - results.Job.Finish(false) - statistics.MoveToHistory(results.Job) + FinishAnalyzeJob(e.ctx, results.Job, nil) totalResult.results[results.Ars[0].Hist[0].ID] = results } if err != nil { @@ -1059,25 +1180,20 @@ func (e *AnalyzeColumnsExec) handleNDVForSpecialIndexes(indexInfos []*model.Inde } // subIndexWorker receive the task for each index and return the result for them. -func (e *AnalyzeColumnsExec) subIndexWorkerForNDV(taskCh chan *analyzeTask, resultsCh chan *statistics.AnalyzeResults, isFirstToCloseCh bool) { +func (e *AnalyzeColumnsExec) subIndexWorkerForNDV(taskCh chan *analyzeTask, resultsCh chan *statistics.AnalyzeResults) { var task *analyzeTask defer func() { if r := recover(); r != nil { buf := make([]byte, 4096) stackSize := runtime.Stack(buf, false) buf = buf[:stackSize] - logutil.BgLogger().Error("analyze worker panicked", zap.String("stack", string(buf))) + logutil.BgLogger().Error("analyze worker panicked", zap.Any("recover", r), zap.String("stack", string(buf))) metrics.PanicCounter.WithLabelValues(metrics.LabelAnalyze).Inc() resultsCh <- &statistics.AnalyzeResults{ Err: errAnalyzeWorkerPanic, Job: task.job, } } - e.subIndexWorkerWg.Done() - if isFirstToCloseCh { - e.subIndexWorkerWg.Wait() - close(resultsCh) - } }() for { var ok bool @@ -1085,7 +1201,7 @@ func (e *AnalyzeColumnsExec) subIndexWorkerForNDV(taskCh chan *analyzeTask, resu if !ok { break } - task.job.Start() + StartAnalyzeJob(e.ctx, task.job) if task.taskType != idxTask { resultsCh <- &statistics.AnalyzeResults{ Err: errors.Errorf("incorrect analyze type"), @@ -1210,7 +1326,7 @@ func (e *AnalyzeColumnsExec) subMergeWorker(resultCh chan<- *samplingMergeResult } subCollector := statistics.NewRowSampleCollector(int(e.analyzePB.ColReq.SampleSize), e.analyzePB.ColReq.GetSampleRate(), l) subCollector.Base().FromProto(colResp.RowCollector) - e.job.Update(subCollector.Base().Count) + UpdateAnalyzeJob(e.ctx, e.job, subCollector.Base().Count) retCollector.MergeCollector(subCollector) } resultCh <- &samplingMergeResult{collector: retCollector} @@ -1224,21 +1340,16 @@ type samplingBuildTask struct { slicePos int } -func (e *AnalyzeColumnsExec) subBuildWorker(resultCh chan error, taskCh chan *samplingBuildTask, hists []*statistics.Histogram, topns []*statistics.TopN, collectors []*statistics.SampleCollector, isClosedChanThread bool) { +func (e *AnalyzeColumnsExec) subBuildWorker(resultCh chan error, taskCh chan *samplingBuildTask, hists []*statistics.Histogram, topns []*statistics.TopN, collectors []*statistics.SampleCollector, exitCh chan struct{}) { defer func() { if r := recover(); r != nil { buf := make([]byte, 4096) stackSize := runtime.Stack(buf, false) buf = buf[:stackSize] - logutil.BgLogger().Error("analyze worker panicked", zap.String("stack", string(buf))) + logutil.BgLogger().Error("analyze worker panicked", zap.Any("recover", r), zap.String("stack", string(buf))) metrics.PanicCounter.WithLabelValues(metrics.LabelAnalyze).Inc() resultCh <- errAnalyzeWorkerPanic } - e.samplingBuilderWg.Done() - if isClosedChanThread { - e.samplingBuilderWg.Wait() - close(resultCh) - } }() failpoint.Inject("mockAnalyzeSamplingBuildWorkerPanic", func() { panic("failpoint triggered") @@ -1246,93 +1357,97 @@ func (e *AnalyzeColumnsExec) subBuildWorker(resultCh chan error, taskCh chan *sa colLen := len(e.colsInfo) workLoop: for { - task, ok := <-taskCh - if !ok { - break - } - var collector *statistics.SampleCollector - if task.isColumn { - if e.colsInfo[task.slicePos].IsGenerated() && !e.colsInfo[task.slicePos].GeneratedStored { - hists[task.slicePos] = nil - topns[task.slicePos] = nil - continue + select { + case task, ok := <-taskCh: + if !ok { + break workLoop } - sampleItems := make([]*statistics.SampleItem, 0, task.rootRowCollector.Base().Samples.Len()) - for j, row := range task.rootRowCollector.Base().Samples { - if row.Columns[task.slicePos].IsNull() { + var collector *statistics.SampleCollector + if task.isColumn { + if e.colsInfo[task.slicePos].IsGenerated() && !e.colsInfo[task.slicePos].GeneratedStored { + hists[task.slicePos] = nil + topns[task.slicePos] = nil continue } - val := row.Columns[task.slicePos] - ft := e.colsInfo[task.slicePos].FieldType - // When it's new collation data, we need to use its collate key instead of original value because only - // the collate key can ensure the correct ordering. - // This is also corresponding to similar operation in (*statistics.Column).GetColumnRowCount(). - if ft.EvalType() == types.ETString && ft.Tp != mysql.TypeEnum && ft.Tp != mysql.TypeSet { - val.SetBytes(collate.GetCollator(ft.Collate).Key(val.GetString())) + sampleItems := make([]*statistics.SampleItem, 0, task.rootRowCollector.Base().Samples.Len()) + for j, row := range task.rootRowCollector.Base().Samples { + if row.Columns[task.slicePos].IsNull() { + continue + } + val := row.Columns[task.slicePos] + ft := e.colsInfo[task.slicePos].FieldType + // When it's new collation data, we need to use its collate key instead of original value because only + // the collate key can ensure the correct ordering. + // This is also corresponding to similar operation in (*statistics.Column).GetColumnRowCount(). + if ft.EvalType() == types.ETString && ft.Tp != mysql.TypeEnum && ft.Tp != mysql.TypeSet { + val.SetBytes(collate.GetCollator(ft.Collate).Key(val.GetString())) + } + sampleItems = append(sampleItems, &statistics.SampleItem{ + Value: val, + Ordinal: j, + }) } - sampleItems = append(sampleItems, &statistics.SampleItem{ - Value: val, - Ordinal: j, - }) - } - collector = &statistics.SampleCollector{ - Samples: sampleItems, - NullCount: task.rootRowCollector.Base().NullCount[task.slicePos], - Count: task.rootRowCollector.Base().Count - task.rootRowCollector.Base().NullCount[task.slicePos], - FMSketch: task.rootRowCollector.Base().FMSketches[task.slicePos], - TotalSize: task.rootRowCollector.Base().TotalSizes[task.slicePos], - } - } else { - var tmpDatum types.Datum - var err error - idx := e.indexes[task.slicePos-colLen] - sampleItems := make([]*statistics.SampleItem, 0, task.rootRowCollector.Base().Samples.Len()) - for _, row := range task.rootRowCollector.Base().Samples { - if len(idx.Columns) == 1 && row.Columns[idx.Columns[0].Offset].IsNull() { - continue + collector = &statistics.SampleCollector{ + Samples: sampleItems, + NullCount: task.rootRowCollector.Base().NullCount[task.slicePos], + Count: task.rootRowCollector.Base().Count - task.rootRowCollector.Base().NullCount[task.slicePos], + FMSketch: task.rootRowCollector.Base().FMSketches[task.slicePos], + TotalSize: task.rootRowCollector.Base().TotalSizes[task.slicePos], } + } else { + var tmpDatum types.Datum + var err error + idx := e.indexes[task.slicePos-colLen] + sampleItems := make([]*statistics.SampleItem, 0, task.rootRowCollector.Base().Samples.Len()) + for _, row := range task.rootRowCollector.Base().Samples { + if len(idx.Columns) == 1 && row.Columns[idx.Columns[0].Offset].IsNull() { + continue + } - b := make([]byte, 0, 8) - for _, col := range idx.Columns { - if col.Length != types.UnspecifiedLength { - row.Columns[col.Offset].Copy(&tmpDatum) - ranger.CutDatumByPrefixLen(&tmpDatum, col.Length, &e.colsInfo[col.Offset].FieldType) - b, err = codec.EncodeKey(e.ctx.GetSessionVars().StmtCtx, b, tmpDatum) + b := make([]byte, 0, 8) + for _, col := range idx.Columns { + if col.Length != types.UnspecifiedLength { + row.Columns[col.Offset].Copy(&tmpDatum) + ranger.CutDatumByPrefixLen(&tmpDatum, col.Length, &e.colsInfo[col.Offset].FieldType) + b, err = codec.EncodeKey(e.ctx.GetSessionVars().StmtCtx, b, tmpDatum) + if err != nil { + resultCh <- err + continue workLoop + } + continue + } + b, err = codec.EncodeKey(e.ctx.GetSessionVars().StmtCtx, b, row.Columns[col.Offset]) if err != nil { resultCh <- err continue workLoop } - continue - } - b, err = codec.EncodeKey(e.ctx.GetSessionVars().StmtCtx, b, row.Columns[col.Offset]) - if err != nil { - resultCh <- err - continue workLoop } + sampleItems = append(sampleItems, &statistics.SampleItem{ + Value: types.NewBytesDatum(b), + }) + } + collector = &statistics.SampleCollector{ + Samples: sampleItems, + NullCount: task.rootRowCollector.Base().NullCount[task.slicePos], + Count: task.rootRowCollector.Base().Count - task.rootRowCollector.Base().NullCount[task.slicePos], + FMSketch: task.rootRowCollector.Base().FMSketches[task.slicePos], + TotalSize: task.rootRowCollector.Base().TotalSizes[task.slicePos], } - sampleItems = append(sampleItems, &statistics.SampleItem{ - Value: types.NewBytesDatum(b), - }) } - collector = &statistics.SampleCollector{ - Samples: sampleItems, - NullCount: task.rootRowCollector.Base().NullCount[task.slicePos], - Count: task.rootRowCollector.Base().Count - task.rootRowCollector.Base().NullCount[task.slicePos], - FMSketch: task.rootRowCollector.Base().FMSketches[task.slicePos], - TotalSize: task.rootRowCollector.Base().TotalSizes[task.slicePos], + if task.isColumn { + collectors[task.slicePos] = collector } + hist, topn, err := statistics.BuildHistAndTopN(e.ctx, int(e.opts[ast.AnalyzeOptNumBuckets]), int(e.opts[ast.AnalyzeOptNumTopN]), task.id, collector, task.tp, task.isColumn) + if err != nil { + resultCh <- err + continue + } + hists[task.slicePos] = hist + topns[task.slicePos] = topn + resultCh <- nil + case <-exitCh: + return } - if task.isColumn { - collectors[task.slicePos] = collector - } - hist, topn, err := statistics.BuildHistAndTopN(e.ctx, int(e.opts[ast.AnalyzeOptNumBuckets]), int(e.opts[ast.AnalyzeOptNumTopN]), task.id, collector, task.tp, task.isColumn) - if err != nil { - resultCh <- err - continue - } - hists[task.slicePos] = hist - topns[task.slicePos] = topn - resultCh <- nil } } @@ -1373,6 +1488,15 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo } } for { + failpoint.Inject("mockKillRunningV1AnalyzeJob", func() { + domain.GetDomain(e.ctx).SysProcTracker().KillSysProcess(util.GetAutoAnalyzeProcID()) + }) + if atomic.LoadUint32(&e.ctx.GetSessionVars().Killed) == 1 { + return nil, nil, nil, nil, nil, errors.Trace(ErrQueryInterrupted) + } + failpoint.Inject("mockSlowAnalyzeV1", func() { + time.Sleep(1000 * time.Second) + }) data, err1 := e.resultHandler.nextRaw(context.TODO()) if err1 != nil { return nil, nil, nil, nil, nil, err1 @@ -1380,7 +1504,6 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo if data == nil { break } - sc := e.ctx.GetSessionVars().StmtCtx var colResp *tipb.AnalyzeColumnsResp if e.analyzePB.Tp == tipb.AnalyzeType_TypeMixed { resp := &tipb.AnalyzeMixedResp{} @@ -1389,7 +1512,7 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo return nil, nil, nil, nil, nil, err } colResp = resp.ColumnsResp - handleHist, handleCms, handleFms, handleTopn, err = updateIndexResult(sc, resp.IndexResp, nil, handleHist, + handleHist, handleCms, handleFms, handleTopn, err = updateIndexResult(e.ctx, resp.IndexResp, nil, handleHist, handleCms, handleFms, handleTopn, e.commonHandle, int(e.opts[ast.AnalyzeOptNumBuckets]), int(e.opts[ast.AnalyzeOptNumTopN]), statsVer) @@ -1400,6 +1523,7 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo colResp = &tipb.AnalyzeColumnsResp{} err = colResp.Unmarshal(data) } + sc := e.ctx.GetSessionVars().StmtCtx rowCount := int64(0) if hasPkHist(e.handleCols) { respHist := statistics.HistogramFromProto(colResp.PkHist) @@ -1414,7 +1538,7 @@ func (e *AnalyzeColumnsExec) buildStats(ranges []*ranger.Range, needExtStats boo rowCount = respSample.Count + respSample.NullCount collectors[i].MergeSampleCollector(sc, respSample) } - e.job.Update(rowCount) + UpdateAnalyzeJob(e.ctx, e.job, rowCount) } timeZone := e.ctx.GetSessionVars().Location() if hasPkHist(e.handleCols) { @@ -1569,13 +1693,7 @@ type AnalyzeFastExec struct { func (e *AnalyzeFastExec) calculateEstimateSampleStep() (err error) { exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - var stmt ast.StmtNode - stmt, err = exec.ParseWithParams(context.TODO(), "select flag from mysql.stats_histograms where table_id = %?", e.tableID.GetStatisticsID()) - if err != nil { - return - } - var rows []chunk.Row - rows, _, err = exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, "select flag from mysql.stats_histograms where table_id = %?", e.tableID.GetStatisticsID()) if err != nil { return } @@ -1854,6 +1972,7 @@ func (e *AnalyzeFastExec) handleScanTasks(bo *tikv.Backoffer) (keysSize int, err snapshot.SetOption(kv.ReplicaRead, kv.ReplicaReadFollower) } setResourceGroupTaggerForTxn(e.ctx.GetSessionVars().StmtCtx, snapshot) + setRPCInterceptorOfExecCounterForTxn(e.ctx.GetSessionVars(), snapshot) for _, t := range e.scanTasks { iter, err := snapshot.Iter(kv.Key(t.StartKey), kv.Key(t.EndKey)) if err != nil { @@ -1875,6 +1994,7 @@ func (e *AnalyzeFastExec) handleSampTasks(workID int, step uint32, err *error) { snapshot.SetOption(kv.IsolationLevel, kv.SI) snapshot.SetOption(kv.Priority, kv.PriorityLow) setResourceGroupTaggerForTxn(e.ctx.GetSessionVars().StmtCtx, snapshot) + setRPCInterceptorOfExecCounterForTxn(e.ctx.GetSessionVars(), snapshot) readReplicaType := e.ctx.GetSessionVars().GetReplicaRead() if readReplicaType.IsFollowerRead() { snapshot.SetOption(kv.ReplicaRead, readReplicaType) @@ -2201,3 +2321,141 @@ func analyzePKIncremental(colExec *analyzePKIncrementalExec) *statistics.Analyze Snapshot: colExec.snapshot, } } + +// AddNewAnalyzeJob records the new analyze job. +func AddNewAnalyzeJob(ctx sessionctx.Context, job *statistics.AnalyzeJob) { + if job == nil { + return + } + statsHandle := domain.GetDomain(ctx).StatsHandle() + err := statsHandle.InsertAnalyzeJob(job, ctx.GetSessionVars().ConnectionID) + if err != nil { + logutil.BgLogger().Error("failed to insert analyze job", zap.Error(err)) + } +} + +// StartAnalyzeJob marks the state of the analyze job as running and sets the start time. +func StartAnalyzeJob(ctx sessionctx.Context, job *statistics.AnalyzeJob) { + if job == nil || job.ID == nil { + return + } + job.StartTime = time.Now() + job.Progress.SetLastDumpTime(job.StartTime) + exec := ctx.(sqlexec.RestrictedSQLExecutor) + const sql = "UPDATE mysql.analyze_jobs SET start_time = CONVERT_TZ(%?, '+00:00', @@TIME_ZONE), state = %? WHERE id = %?" + _, _, err := exec.ExecRestrictedSQL(context.TODO(), []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseSessionPool}, sql, job.StartTime.UTC().Format(types.TimeFormat), statistics.AnalyzeRunning, *job.ID) + if err != nil { + logutil.BgLogger().Warn("failed to update analyze job", zap.String("update", fmt.Sprintf("%s->%s", statistics.AnalyzePending, statistics.AnalyzeRunning)), zap.Error(err)) + } +} + +// UpdateAnalyzeJob updates count of the processed rows when increment reaches a threshold. +func UpdateAnalyzeJob(ctx sessionctx.Context, job *statistics.AnalyzeJob, rowCount int64) { + if job == nil || job.ID == nil { + return + } + delta := job.Progress.Update(rowCount) + if delta == 0 { + return + } + exec := ctx.(sqlexec.RestrictedSQLExecutor) + const sql = "UPDATE mysql.analyze_jobs SET processed_rows = processed_rows + %? WHERE id = %?" + _, _, err := exec.ExecRestrictedSQL(context.TODO(), []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseSessionPool}, sql, delta, *job.ID) + if err != nil { + logutil.BgLogger().Warn("failed to update analyze job", zap.String("update", fmt.Sprintf("process %v rows", delta)), zap.Error(err)) + } +} + +// FinishAnalyzeJob updates the state of the analyze job to finished/failed according to `meetError` and sets the end time. +func FinishAnalyzeJob(ctx sessionctx.Context, job *statistics.AnalyzeJob, analyzeErr error) { + if job == nil || job.ID == nil { + return + } + job.EndTime = time.Now() + var sql string + var args []interface{} + // process_id is used to see which process is running the analyze job and kill the analyze job. After the analyze job + // is finished(or failed), process_id is useless and we set it to NULL to avoid `kill tidb process_id` wrongly. + if analyzeErr != nil { + sql = "UPDATE mysql.analyze_jobs SET processed_rows = processed_rows + %?, end_time = CONVERT_TZ(%?, '+00:00', @@TIME_ZONE), state = %?, fail_reason = %?, process_id = NULL WHERE id = %?" + args = []interface{}{job.Progress.GetDeltaCount(), job.EndTime.UTC().Format(types.TimeFormat), statistics.AnalyzeFailed, analyzeErr.Error(), *job.ID} + } else { + sql = "UPDATE mysql.analyze_jobs SET processed_rows = processed_rows + %?, end_time = CONVERT_TZ(%?, '+00:00', @@TIME_ZONE), state = %?, process_id = NULL WHERE id = %?" + args = []interface{}{job.Progress.GetDeltaCount(), job.EndTime.UTC().Format(types.TimeFormat), statistics.AnalyzeFinished, *job.ID} + } + exec := ctx.(sqlexec.RestrictedSQLExecutor) + _, _, err := exec.ExecRestrictedSQL(context.TODO(), []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseSessionPool}, sql, args...) + if err != nil { + var state string + if analyzeErr != nil { + state = statistics.AnalyzeFailed + } else { + state = statistics.AnalyzeFinished + } + logutil.BgLogger().Warn("failed to update analyze job", zap.String("update", fmt.Sprintf("%s->%s", statistics.AnalyzeRunning, state)), zap.Error(err)) + } +} + +// analyzeResultsNotifyWaitGroupWrapper is a wrapper for sync.WaitGroup +// Please add all goroutine count when to `Add` to avoid exiting in advance. +type analyzeResultsNotifyWaitGroupWrapper struct { + sync.WaitGroup + notify chan *statistics.AnalyzeResults + cnt atomicutil.Uint64 +} + +// NewAnalyzeResultsNotifyWaitGroupWrapper is to create analyzeResultsNotifyWaitGroupWrapper +func NewAnalyzeResultsNotifyWaitGroupWrapper(notify chan *statistics.AnalyzeResults) *analyzeResultsNotifyWaitGroupWrapper { + return &analyzeResultsNotifyWaitGroupWrapper{ + notify: notify, + cnt: *atomicutil.NewUint64(0), + } +} + +// Run runs a function in a goroutine and calls done when function returns. +// Please DO NOT use panic in the cb function. +func (w *analyzeResultsNotifyWaitGroupWrapper) Run(exec func()) { + old := w.cnt.Inc() - 1 + go func(cnt uint64) { + defer func() { + w.Done() + if cnt == 0 { + w.Wait() + close(w.notify) + } + }() + exec() + }(old) +} + +// notifyErrorWaitGroupWrapper is a wrapper for sync.WaitGroup +// Please add all goroutine count when to `Add` to avoid exiting in advance. +type notifyErrorWaitGroupWrapper struct { + sync.WaitGroup + notify chan error + cnt atomicutil.Uint64 +} + +// newNotifyErrorWaitGroupWrapper is to create notifyErrorWaitGroupWrapper +func newNotifyErrorWaitGroupWrapper(notify chan error) *notifyErrorWaitGroupWrapper { + return ¬ifyErrorWaitGroupWrapper{ + notify: notify, + cnt: *atomicutil.NewUint64(0), + } +} + +// Run runs a function in a goroutine and calls done when function returns. +// Please DO NOT use panic in the cb function. +func (w *notifyErrorWaitGroupWrapper) Run(exec func()) { + old := w.cnt.Inc() - 1 + go func(cnt uint64) { + defer func() { + w.Done() + if cnt == 0 { + w.Wait() + close(w.notify) + } + }() + exec() + }(old) +} diff --git a/executor/analyze_test.go b/executor/analyze_test.go index 3ee10fe9a3626..9b15adfcaeb12 100644 --- a/executor/analyze_test.go +++ b/executor/analyze_test.go @@ -16,6 +16,7 @@ package executor_test import ( "context" + "encoding/json" "fmt" "strconv" "strings" @@ -24,14 +25,18 @@ import ( "testing" "time" + "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" @@ -178,12 +183,10 @@ func TestAnalyzeRestrict(t *testing.T) { } func TestAnalyzeParameters(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - tk := testkit.NewTestKit(t, store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") @@ -239,12 +242,10 @@ func TestAnalyzeParameters(t *testing.T) { } func TestAnalyzeTooLongColumns(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - tk := testkit.NewTestKit(t, store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a json)") @@ -349,7 +350,7 @@ func TestAnalyzeFastSample(t *testing.T) { } handleCols := core.BuildHandleColsForAnalyze(tk.Session(), tblInfo, true, nil) - var colsInfo []*model.ColumnInfo + var colsInfo []*model.ColumnInfo // nolint: prealloc var indicesInfo []*model.IndexInfo for _, col := range tblInfo.Columns { if mysql.HasPriKeyFlag(col.Flag) { @@ -660,15 +661,15 @@ func TestFailedAnalyzeRequest(t *testing.T) { tk.MustExec("set @@tidb_analyze_version = 1") require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/buildStatsFromResult", `return(true)`)) _, err := tk.Exec("analyze table t") + require.NotNil(t, err) require.Equal(t, "mock buildStatsFromResult error", err.Error()) require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/buildStatsFromResult")) } func TestExtractTopN(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_extract_topn") tk.MustExec("use test_extract_topn") @@ -720,12 +721,10 @@ func TestExtractTopN(t *testing.T) { } func TestHashInTopN(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - tk := testkit.NewTestKit(t, store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b float, c decimal(30, 10), d varchar(20))") @@ -814,11 +813,11 @@ func TestNormalAnalyzeOnCommonHandle(t *testing.T) { } func TestDefaultValForAnalyze(t *testing.T) { - t.Skip("skip race test") store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) - + tk.MustExec("set @@tidb_analyze_version=1") + defer tk.MustExec("set @@tidb_analyze_version=2") tk.MustExec("drop database if exists test_default_val_for_analyze;") tk.MustExec("create database test_default_val_for_analyze;") tk.MustExec("use test_default_val_for_analyze") @@ -833,10 +832,10 @@ func TestDefaultValForAnalyze(t *testing.T) { tk.MustQuery("select @@tidb_enable_fast_analyze").Check(testkit.Rows("0")) tk.MustQuery("select @@session.tidb_enable_fast_analyze").Check(testkit.Rows("0")) tk.MustExec("analyze table t with 0 topn;") - tk.MustQuery("explain format = 'brief' select * from t where a = 1").Check(testkit.Rows("IndexReader_6 512.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 512.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false")) - tk.MustQuery("explain format = 'brief' select * from t where a = 999").Check(testkit.Rows("IndexReader_6 0.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.00 cop[tikv] table:t, index:a(a) range:[999,999], keep order:false")) + tk.MustQuery("explain format = 'brief' select * from t where a = 1").Check(testkit.Rows("IndexReader 512.00 root index:IndexRangeScan", + "└─IndexRangeScan 512.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false")) + tk.MustQuery("explain format = 'brief' select * from t where a = 999").Check(testkit.Rows("IndexReader 0.00 root index:IndexRangeScan", + "└─IndexRangeScan 0.00 cop[tikv] table:t, index:a(a) range:[999,999], keep order:false")) tk.MustExec("drop table t;") tk.MustExec("create table t (a int, key(a));") @@ -847,8 +846,8 @@ func TestDefaultValForAnalyze(t *testing.T) { tk.MustExec("insert into t values (?)", i) } tk.MustExec("analyze table t with 0 topn;") - tk.MustQuery("explain format = 'brief' select * from t where a = 1").Check(testkit.Rows("IndexReader_6 1.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false")) + tk.MustQuery("explain format = 'brief' select * from t where a = 1").Check(testkit.Rows("IndexReader 1.00 root index:IndexRangeScan", + "└─IndexRangeScan 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false")) } func TestAnalyzeFullSamplingOnIndexWithVirtualColumnOrPrefixColumn(t *testing.T) { @@ -953,14 +952,14 @@ func TestAdjustSampleRateNote(t *testing.T) { result := tk.MustQuery("show stats_meta where table_name = 't'") require.Equal(t, "220000", result.Rows()[0][5]) tk.MustExec("analyze table t") - tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 0.500000 for table test.t.")) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 0.500000 for table test.t")) tk.MustExec("insert into t values(1),(1),(1)") require.NoError(t, statsHandle.DumpStatsDeltaToKV(handle.DumpAll)) require.NoError(t, statsHandle.Update(is)) result = tk.MustQuery("show stats_meta where table_name = 't'") require.Equal(t, "3", result.Rows()[0][5]) tk.MustExec("analyze table t") - tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.")) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t")) } func TestFastAnalyze4GlobalStats(t *testing.T) { @@ -979,7 +978,7 @@ func TestFastAnalyze4GlobalStats(t *testing.T) { tk.MustExec("create table test_fast_gstats(a int, b int) PARTITION BY HASH(a) PARTITIONS 2;") tk.MustExec("insert into test_fast_gstats values(1,1),(3,3),(4,4),(2,2),(5,5);") err := tk.ExecToErr("analyze table test_fast_gstats;") - require.EqualError(t, err, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently.") + require.EqualError(t, err, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently") } func TestAnalyzeIndex(t *testing.T) { @@ -1009,28 +1008,12 @@ func TestAnalyzeIndex(t *testing.T) { } func TestAnalyzeIncremental(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() - dom, err := session.BootstrapSession(store) - require.NoError(t, err) tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_analyze_version = 1") - tk.Session().GetSessionVars().EnableStreaming = false - testAnalyzeIncremental(tk, t, dom) -} - -func TestAnalyzeIncrementalStreaming(t *testing.T) { - t.Skip("unistore hasn't support streaming yet.") - store, clean := testkit.CreateMockStore(t) - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.Session().GetSessionVars().EnableStreaming = true testAnalyzeIncremental(tk, t, dom) } @@ -1115,25 +1098,7 @@ func testAnalyzeIncremental(tk *testkit.TestKit, t *testing.T, dom *domain.Domai require.Equal(t, "[stats]: global statistics for partitioned tables unavailable in ANALYZE INCREMENTAL", err.Error()) } -func TestIssue27429(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table test.t(id int, value varchar(20) charset utf8mb4 collate utf8mb4_general_ci, value1 varchar(20) charset utf8mb4 collate utf8mb4_bin)") - tk.MustExec("insert into test.t values (1, 'abc', 'abc '),(4, 'Abc', 'abc'),(3,'def', 'def ');") - - tk.MustQuery("select upper(group_concat(distinct value order by 1)) from test.t;").Check(testkit.Rows("ABC,DEF")) - tk.MustQuery("select upper(group_concat(distinct value)) from test.t;").Check(testkit.Rows("ABC,DEF")) -} - func TestIssue20874(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1233,3 +1198,1743 @@ func TestAnalyzeSamplingWorkPanic(t *testing.T) { require.NotNil(t, err) require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockAnalyzeSamplingMergeWorkerPanic")) } + +func TestSmallTableAnalyzeV2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/calcSampleRateByStorageCount", "return(1)")) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("create table small_table_inject_pd(a int)") + tk.MustExec("insert into small_table_inject_pd values(1), (2), (3), (4), (5)") + tk.MustExec("analyze table small_table_inject_pd") + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.small_table_inject_pd")) + tk.MustExec(` +create table small_table_inject_pd_with_partition( + a int +) partition by range(a) ( + partition p0 values less than (5), + partition p1 values less than (10), + partition p2 values less than (15) +)`) + tk.MustExec("insert into small_table_inject_pd_with_partition values(1), (6), (11)") + tk.MustExec("analyze table small_table_inject_pd_with_partition") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.small_table_inject_pd_with_partition's partition p0", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.small_table_inject_pd_with_partition's partition p1", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.small_table_inject_pd_with_partition's partition p2", + )) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/calcSampleRateByStorageCount")) +} + +func TestSavedAnalyzeOptions(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + }() + tk.MustExec("set global tidb_persist_analyze_options = true") + originalVal2 := tk.MustQuery("select @@tidb_auto_analyze_ratio").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_ratio = %v", originalVal2)) + }() + tk.MustExec("set global tidb_auto_analyze_ratio = 0.01") + originalVal3 := handle.AutoAnalyzeMinCnt + defer func() { + handle.AutoAnalyzeMinCnt = originalVal3 + }() + handle.AutoAnalyzeMinCnt = 0 + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") + tk.MustExec("insert into t values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,7,7),(8,8,8),(9,9,9)") + + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + tk.MustExec("analyze table t with 1 topn, 2 buckets") + is := dom.InfoSchema() + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + tbl := h.GetTableStats(tableInfo) + lastVersion := tbl.Version + col0 := tbl.Columns[tableInfo.Columns[0].ID] + require.Equal(t, 2, len(col0.Buckets)) + col1 := tbl.Columns[tableInfo.Columns[1].ID] + require.Equal(t, 1, len(col1.TopN.TopN)) + require.Equal(t, 2, len(col1.Buckets)) + col2 := tbl.Columns[tableInfo.Columns[2].ID] + require.Equal(t, 2, len(col2.Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs := tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tbl.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "1", rs.Rows()[0][4]) + + // auto-analyze uses the table-level options + tk.MustExec("insert into t values (10,10,10)") + require.Nil(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.Nil(t, h.Update(is)) + h.HandleAutoAnalyze(is) + tbl = h.GetTableStats(tableInfo) + require.Greater(t, tbl.Version, lastVersion) + lastVersion = tbl.Version + col0 = tbl.Columns[tableInfo.Columns[0].ID] + require.Equal(t, 2, len(col0.Buckets)) + + // manual analyze uses the table-level persisted options by merging the new options + tk.MustExec("analyze table t columns a,b with 1 samplerate, 3 buckets") + tbl = h.GetTableStats(tableInfo) + require.Greater(t, tbl.Version, lastVersion) + lastVersion = tbl.Version + col0 = tbl.Columns[tableInfo.Columns[0].ID] + require.Equal(t, 3, len(col0.Buckets)) + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + col1 = tbl.Columns[tableInfo.Columns[1].ID] + require.Equal(t, 1, len(col1.TopN.TopN)) + col2 = tbl.Columns[tableInfo.Columns[2].ID] + require.Less(t, col2.LastUpdateVersion, col0.LastUpdateVersion) // not updated since removed from list + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tbl.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "1", rs.Rows()[0][2]) + require.Equal(t, "3", rs.Rows()[0][3]) + require.Equal(t, "1", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + colIDStrs := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10), strconv.FormatInt(tableInfo.Columns[1].ID, 10)}, ",") + require.Equal(t, colIDStrs, rs.Rows()[0][6]) + + // disable option persistence + tk.MustExec("set global tidb_persist_analyze_options = false") + // manual analyze will neither use the pre-persisted options nor persist new options + tk.MustExec("analyze table t with 2 topn") + tbl = h.GetTableStats(tableInfo) + require.Greater(t, tbl.Version, lastVersion) + col0 = tbl.Columns[tableInfo.Columns[0].ID] + require.NotEqual(t, 3, len(col0.Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tbl.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.NotEqual(t, "2", rs.Rows()[0][4]) +} + +func TestSavedPartitionAnalyzeOptions(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal)) + }() + tk.MustExec("set global tidb_persist_analyze_options = true") + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") + createTable := `CREATE TABLE t (a int, b int, c varchar(10), primary key(a), index idx(b)) +PARTITION BY RANGE ( a ) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20) +)` + tk.MustExec(createTable) + tk.MustExec("insert into t values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),(11,11,11),(12,12,12),(13,13,13),(14,14,14)") + + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + // analyze partition only sets options of partition + tk.MustExec("analyze table t partition p0 with 1 topn, 3 buckets") + is := dom.InfoSchema() + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + pi := tableInfo.GetPartitionInfo() + require.NotNil(t, pi) + p0 := h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + lastVersion := p0.Version + require.Equal(t, 3, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs := tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "3", rs.Rows()[0][3]) + require.Equal(t, "1", rs.Rows()[0][4]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][3]) + require.Equal(t, "-1", rs.Rows()[0][4]) + + // merge partition & table level options + tk.MustExec("analyze table t columns a,b with 0 topn, 2 buckets") + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + p0 = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + p1 := h.GetPartitionStats(tableInfo, pi.Definitions[1].ID) + require.Greater(t, p0.Version, lastVersion) + lastVersion = p0.Version + require.Equal(t, 2, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + require.Equal(t, 2, len(p1.Columns[tableInfo.Columns[0].ID].Buckets)) + // check column c is not analyzed + require.Less(t, p0.Columns[tableInfo.Columns[2].ID].LastUpdateVersion, p0.Columns[tableInfo.Columns[0].ID].LastUpdateVersion) + require.Less(t, p1.Columns[tableInfo.Columns[2].ID].LastUpdateVersion, p1.Columns[tableInfo.Columns[0].ID].LastUpdateVersion) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + colIDStrsAB := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10), strconv.FormatInt(tableInfo.Columns[1].ID, 10)}, ",") + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + + // analyze partition only updates this partition, and set different collist + tk.MustExec("analyze table t partition p1 columns a,c with 1 buckets") + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + p0 = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + p1 = h.GetPartitionStats(tableInfo, pi.Definitions[1].ID) + require.Equal(t, p0.Version, lastVersion) + require.Greater(t, p1.Version, lastVersion) + lastVersion = p1.Version + require.Equal(t, 1, len(p1.Columns[tableInfo.Columns[0].ID].Buckets)) + require.Equal(t, 2, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + // only column c of p1 is re-analyzed + require.Equal(t, 1, len(p1.Columns[tableInfo.Columns[2].ID].Buckets)) + require.NotEqual(t, 1, len(p0.Columns[tableInfo.Columns[2].ID].Buckets)) + colIDStrsABC := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10), strconv.FormatInt(tableInfo.Columns[1].ID, 10), strconv.FormatInt(tableInfo.Columns[2].ID, 10)}, ",") + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "1", rs.Rows()[0][3]) + require.Equal(t, colIDStrsABC, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + + // analyze partition without options uses saved partition options + tk.MustExec("analyze table t partition p0") + p0 = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + require.Greater(t, p0.Version, lastVersion) + lastVersion = p0.Version + require.Equal(t, 2, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + + // merge options of statement's, partition's and table's + tk.MustExec("analyze table t partition p0 with 3 buckets") + p0 = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + require.Greater(t, p0.Version, lastVersion) + require.Equal(t, 3, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "3", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + + // add new partitions, use table options as default + tk.MustExec("ALTER TABLE t ADD PARTITION (PARTITION p2 VALUES LESS THAN (30))") + tk.MustExec("insert into t values (21,21,21),(22,22,22),(23,23,23),(24,24,24)") + tk.MustExec("analyze table t partition p2") + is = dom.InfoSchema() + table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo = table.Meta() + pi = tableInfo.GetPartitionInfo() + p2 := h.GetPartitionStats(tableInfo, pi.Definitions[2].ID) + require.Equal(t, 2, len(p2.Columns[tableInfo.Columns[0].ID].Buckets)) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p2.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrsAB, rs.Rows()[0][6]) + + // set analyze version back to 1, will not use persisted + tk.MustExec("set @@session.tidb_analyze_version = 1") + tk.MustExec("analyze table t partition p2") + pi = tableInfo.GetPartitionInfo() + p2 = h.GetPartitionStats(tableInfo, pi.Definitions[2].ID) + require.NotEqual(t, 2, len(p2.Columns[tableInfo.Columns[0].ID].Buckets)) + + // drop column + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("alter table t drop column b") + tk.MustExec("analyze table t") + colIDStrsA := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10)}, ",") + colIDStrsAC := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10), strconv.FormatInt(tableInfo.Columns[2].ID, 10)}, ",") + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, colIDStrsA, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, colIDStrsA, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, colIDStrsAC, rs.Rows()[0][6]) + + // drop partition + tk.MustExec("alter table t drop partition p1") + is = dom.InfoSchema() // refresh infoschema + require.Nil(t, h.GCStats(is, time.Duration(0))) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 0, len(rs.Rows())) + + // drop table + tk.MustExec("drop table t") + is = dom.InfoSchema() // refresh infoschema + require.Nil(t, h.GCStats(is, time.Duration(0))) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + //require.Equal(t, len(rs.Rows()), 0) TODO + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 0, len(rs.Rows())) +} + +func TestSavedPartitionAnalyzeOptionsDynamic(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal)) + }() + tk.MustExec("set global tidb_persist_analyze_options = true") + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'dynamic'") + createTable := `CREATE TABLE t (a int, b int, c varchar(10), primary key(a), index idx(b)) +PARTITION BY RANGE ( a ) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20) +)` + tk.MustExec(createTable) + tk.MustExec("insert into t values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),(11,11,11),(12,12,12),(13,13,13),(14,14,14)") + + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + is := dom.InfoSchema() + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + pi := tableInfo.GetPartitionInfo() + require.NotNil(t, pi) + + // analyze partition only sets options of partition + tk.MustExec("analyze table t partition p0 with 1 topn, 3 buckets") + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + tbl := h.GetTableStats(tableInfo) + lastVersion := tbl.Version + // no global stats since partition stats missing + require.Equal(t, 0, len(tbl.Columns[tableInfo.Columns[0].ID].Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs := tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(pi.Definitions[0].ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "3", rs.Rows()[0][3]) + require.Equal(t, "1", rs.Rows()[0][4]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][3]) + require.Equal(t, "-1", rs.Rows()[0][4]) + + // merge partition & table level options + tk.MustExec("analyze table t columns a,b with 0 topn, 2 buckets") + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + tbl = h.GetTableStats(tableInfo) + require.Greater(t, tbl.Version, lastVersion) + lastVersion = tbl.Version + p0 := h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + p1 := h.GetPartitionStats(tableInfo, pi.Definitions[1].ID) + require.Equal(t, 2, len(p0.Columns[tableInfo.Columns[0].ID].Buckets)) + require.Equal(t, 2, len(p1.Columns[tableInfo.Columns[0].ID].Buckets)) + // merged global stats + require.Equal(t, 2, len(tbl.Columns[tableInfo.Columns[0].ID].Buckets)) + // check column c is not analyzed + require.Less(t, tbl.Columns[tableInfo.Columns[2].ID].LastUpdateVersion, tbl.Columns[tableInfo.Columns[0].ID].LastUpdateVersion) + require.Less(t, p0.Columns[tableInfo.Columns[2].ID].LastUpdateVersion, p0.Columns[tableInfo.Columns[0].ID].LastUpdateVersion) + require.Less(t, p1.Columns[tableInfo.Columns[2].ID].LastUpdateVersion, p1.Columns[tableInfo.Columns[0].ID].LastUpdateVersion) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tbl.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + colIDStrs := strings.Join([]string{strconv.FormatInt(tableInfo.Columns[0].ID, 10), strconv.FormatInt(tableInfo.Columns[1].ID, 10)}, ",") + require.Equal(t, colIDStrs, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrs, rs.Rows()[0][6]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "0", rs.Rows()[0][2]) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "0", rs.Rows()[0][4]) + require.Equal(t, "LIST", rs.Rows()[0][5]) + require.Equal(t, colIDStrs, rs.Rows()[0][6]) + + // analyze partition only updates this partition, and set different collist + tk.MustExec("analyze table t partition p1 columns a,c with 1 buckets") + tk.MustQuery("select * from t where b > 1 and c > 1") + require.NoError(t, h.LoadNeededHistograms()) + tbl = h.GetTableStats(tableInfo) + require.Greater(t, tbl.Version, lastVersion) + p0 = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) + p1 = h.GetPartitionStats(tableInfo, pi.Definitions[1].ID) + require.Equal(t, 1, len(p1.Columns[tableInfo.Columns[0].ID].Buckets)) + require.Equal(t, 2, len(tbl.Columns[tableInfo.Columns[0].ID].Buckets)) + // check column c is analyzed, but only global stats loaded + require.Equal(t, 0, len(p1.Columns[tableInfo.Columns[2].ID].Buckets)) + require.Equal(t, 2, len(tbl.Columns[tableInfo.Columns[2].ID].Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tbl.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p1.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "1", rs.Rows()[0][3]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(p0.PhysicalID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) +} + +func TestSavedAnalyzeOptionsForMultipleTables(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal)) + }() + tk.MustExec("set global tidb_persist_analyze_options = true") + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") + tk.MustExec("create table t1(a int, b int, c int, primary key(a), key idx(b))") + tk.MustExec("insert into t1 values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,7,7),(8,8,8),(9,9,9)") + tk.MustExec("create table t2(a int, b int, c int, primary key(a), key idx(b))") + tk.MustExec("insert into t2 values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,7,7),(8,8,8),(9,9,9)") + + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + + tk.MustExec("analyze table t1 with 1 topn, 3 buckets") + tk.MustExec("analyze table t2 with 0 topn, 2 buckets") + tk.MustExec("analyze table t1,t2 with 2 topn") + is := dom.InfoSchema() + table1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.NoError(t, err) + table2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.NoError(t, err) + tableInfo1 := table1.Meta() + tableInfo2 := table2.Meta() + tblStats1 := h.GetTableStats(tableInfo1) + tblStats2 := h.GetTableStats(tableInfo2) + tbl1Col0 := tblStats1.Columns[tableInfo1.Columns[0].ID] + tbl2Col0 := tblStats2.Columns[tableInfo2.Columns[0].ID] + require.Equal(t, 3, len(tbl1Col0.Buckets)) + require.Equal(t, 2, len(tbl2Col0.Buckets)) + // The columns are: table_id, sample_num, sample_rate, buckets, topn, column_choice, column_ids. + rs := tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo1.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "3", rs.Rows()[0][3]) + require.Equal(t, "2", rs.Rows()[0][4]) + rs = tk.MustQuery("select * from mysql.analyze_options where table_id=" + strconv.FormatInt(tableInfo2.ID, 10)) + require.Equal(t, 1, len(rs.Rows())) + require.Equal(t, "2", rs.Rows()[0][3]) + require.Equal(t, "2", rs.Rows()[0][4]) +} + +func TestSavedAnalyzeColumnOptions(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + }() + tk.MustExec("set global tidb_persist_analyze_options = true") + originalVal2 := tk.MustQuery("select @@tidb_auto_analyze_ratio").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_ratio = %v", originalVal2)) + }() + tk.MustExec("set global tidb_auto_analyze_ratio = 0.01") + originalVal3 := handle.AutoAnalyzeMinCnt + defer func() { + handle.AutoAnalyzeMinCnt = originalVal3 + }() + handle.AutoAnalyzeMinCnt = 0 + originalVal4 := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal4)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("create table t(a int, b int, c int)") + tk.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3),(4,4,4)") + + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblInfo := tbl.Meta() + tk.MustExec("select * from t where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + tk.MustExec("analyze table t predicate columns") + require.NoError(t, h.LoadNeededHistograms()) + tblStats := h.GetTableStats(tblInfo) + lastVersion := tblStats.Version + // column b is analyzed + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[0].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[1].ID].LastUpdateVersion) + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[2].ID].LastUpdateVersion) + tk.MustQuery(fmt.Sprintf("select column_choice, column_ids from mysql.analyze_options where table_id = %v", tblInfo.ID)).Check(testkit.Rows("PREDICATE ")) + + tk.MustExec("select * from t where c > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + // manually analyze uses the saved option(predicate columns). + tk.MustExec("analyze table t") + require.NoError(t, h.LoadNeededHistograms()) + tblStats = h.GetTableStats(tblInfo) + require.Less(t, lastVersion, tblStats.Version) + lastVersion = tblStats.Version + // column b, c are analyzed + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[0].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[1].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[2].ID].LastUpdateVersion) + + tk.MustExec("insert into t values (5,5,5),(6,6,6)") + require.Nil(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.Nil(t, h.Update(is)) + // auto analyze uses the saved option(predicate columns). + h.HandleAutoAnalyze(is) + tblStats = h.GetTableStats(tblInfo) + require.Less(t, lastVersion, tblStats.Version) + lastVersion = tblStats.Version + // column b, c are analyzed + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[0].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[1].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[2].ID].LastUpdateVersion) + + tk.MustExec("analyze table t columns a") + tblStats = h.GetTableStats(tblInfo) + require.Less(t, lastVersion, tblStats.Version) + lastVersion = tblStats.Version + // column a is analyzed + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[0].ID].LastUpdateVersion) + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[1].ID].LastUpdateVersion) + require.Greater(t, lastVersion, tblStats.Columns[tblInfo.Columns[2].ID].LastUpdateVersion) + tk.MustQuery(fmt.Sprintf("select column_choice, column_ids from mysql.analyze_options where table_id = %v", tblInfo.ID)).Check(testkit.Rows(fmt.Sprintf("LIST %v", tblInfo.Columns[0].ID))) + + tk.MustExec("analyze table t all columns") + tblStats = h.GetTableStats(tblInfo) + require.Less(t, lastVersion, tblStats.Version) + lastVersion = tblStats.Version + // column a, b, c are analyzed + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[0].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[1].ID].LastUpdateVersion) + require.Equal(t, lastVersion, tblStats.Columns[tblInfo.Columns[2].ID].LastUpdateVersion) + tk.MustQuery(fmt.Sprintf("select column_choice, column_ids from mysql.analyze_options where table_id = %v", tblInfo.ID)).Check(testkit.Rows("ALL ")) +} + +func TestAnalyzeColumnsWithPrimaryKey(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("create table t (a int, b int, c int primary key)") + tk.MustExec("insert into t values (1,1,1), (1,1,2), (2,2,3), (2,2,4), (3,3,5), (4,3,6), (5,4,7), (6,4,8), (null,null,9)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where a > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "a", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 2, len(rows)) + require.Equal(t, "a", rows[0][3]) + require.Equal(t, "c", rows[1][3]) + + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 9")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t a 0 1 2", + "test t a 0 2 2", + "test t c 0 1 1", + "test t c 0 2 1")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 6 1 8 2 1", + "0 2 0 0 8 0 0", // column b is not analyzed + "0 3 9 0 9 2 1", + )) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t a 0 0 3 1 3 5 0", + "test t a 0 1 4 1 6 6 0", + "test t c 0 0 4 1 3 6 0", + "test t c 0 1 7 1 7 9 0")) + }(val) + } +} + +func TestAnalyzeColumnsWithIndex(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("create table t (a int, b int, c int, d int, index idx_b_d(b, d))") + tk.MustExec("insert into t values (1,1,null,1), (2,1,9,1), (1,1,8,1), (2,2,7,2), (1,3,7,3), (2,4,6,4), (1,4,6,5), (2,4,6,5), (1,5,6,5)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns c with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Columns b,d are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where c > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "c", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 3, len(rows)) + require.Equal(t, "b", rows[0][3]) + require.Equal(t, "c", rows[1][3]) + require.Equal(t, "d", rows[2][3]) + + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 9")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t b 0 1 3", + "test t b 0 4 3", + "test t c 0 6 4", + "test t c 0 7 2", + "test t d 0 1 3", + "test t d 0 5 3", + "test t idx_b_d 1 (1, 1) 3", + "test t idx_b_d 1 (4, 5) 2")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 0 0 9 0 0", // column a is not analyzed + "0 2 5 0 9 2 1", + "0 3 4 1 8 2 -0.07", + "0 4 5 0 9 2 1", + "1 1 6 0 18 2 0")) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t b 0 0 2 1 2 3 0", + "test t b 0 1 3 1 5 5 0", + "test t c 0 0 2 1 8 9 0", + "test t d 0 0 2 1 2 3 0", + "test t d 0 1 3 1 4 4 0", + "test t idx_b_d 1 0 3 1 (2, 2) (4, 4) 0", + "test t idx_b_d 1 1 4 1 (5, 5) (5, 5) 0")) + }(val) + } +} + +func TestAnalyzeColumnsWithClusteredIndex(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("create table t (a int, b int, c int, d int, primary key(b, d) clustered)") + tk.MustExec("insert into t values (1,1,null,1), (2,2,9,2), (1,3,8,3), (2,4,7,4), (1,5,7,5), (2,6,6,6), (1,7,6,7), (2,8,6,8), (1,9,6,9)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns c with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Columns b,d are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where c > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "c", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 3, len(rows)) + require.Equal(t, "b", rows[0][3]) + require.Equal(t, "c", rows[1][3]) + require.Equal(t, "d", rows[2][3]) + + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 9")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t PRIMARY 1 (1, 1) 1", + "test t PRIMARY 1 (2, 2) 1", + "test t b 0 1 1", + "test t b 0 2 1", + "test t c 0 6 4", + "test t c 0 7 2", + "test t d 0 1 1", + "test t d 0 2 1")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 0 0 9 0 0", // column a is not analyzed + "0 2 9 0 9 2 1", + "0 3 4 1 8 2 -0.07", + "0 4 9 0 9 2 1", + "1 1 9 0 18 2 0")) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t PRIMARY 1 0 4 1 (3, 3) (6, 6) 0", + "test t PRIMARY 1 1 7 1 (7, 7) (9, 9) 0", + "test t b 0 0 4 1 3 6 0", + "test t b 0 1 7 1 7 9 0", + "test t c 0 0 2 1 8 9 0", + "test t d 0 0 4 1 3 6 0", + "test t d 0 1 7 1 7 9 0")) + }(val) + } +} + +func TestAnalyzeColumnsWithDynamicPartitionTable(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + tk.MustExec("create table t (a int, b int, c int, index idx(c)) partition by range (a) (partition p0 values less than (10), partition p1 values less than maxvalue)") + tk.MustExec("insert into t values (1,2,1), (2,4,1), (3,6,1), (4,8,2), (4,8,2), (5,10,3), (5,10,4), (5,10,5), (null,null,6), (11,22,7), (12,24,8), (13,26,9), (14,28,10), (15,30,11), (16,32,12), (16,32,13), (16,32,13), (16,32,14), (17,34,14), (17,34,14)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + defs := tbl.Meta().Partition.Definitions + p0ID := defs[0].ID + p1ID := defs[1].ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1", + "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where a < 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, []interface{}{"test", "t", "global", "a"}, rows[0][:4]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 6, len(rows)) + require.Equal(t, []interface{}{"test", "t", "global", "a"}, rows[0][:4]) + require.Equal(t, []interface{}{"test", "t", "global", "c"}, rows[1][:4]) + require.Equal(t, []interface{}{"test", "t", "p0", "a"}, rows[2][:4]) + require.Equal(t, []interface{}{"test", "t", "p0", "c"}, rows[3][:4]) + require.Equal(t, []interface{}{"test", "t", "p1", "a"}, rows[4][:4]) + require.Equal(t, []interface{}{"test", "t", "p1", "c"}, rows[5][:4]) + + rows = tk.MustQuery("show stats_meta where db_name = 'test' and table_name = 't'").Sort().Rows() + require.Equal(t, 3, len(rows)) + require.Equal(t, []interface{}{"test", "t", "global", "0", "20"}, append(rows[0][:3], rows[0][4:]...)) + require.Equal(t, []interface{}{"test", "t", "p0", "0", "9"}, append(rows[1][:3], rows[1][4:]...)) + require.Equal(t, []interface{}{"test", "t", "p1", "0", "11"}, append(rows[2][:3], rows[2][4:]...)) + + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t global a 0 16 4", + "test t global a 0 5 3", + "test t global c 0 1 3", + "test t global c 0 14 3", + "test t p0 a 0 4 2", + "test t p0 a 0 5 3", + "test t p0 c 0 1 3", + "test t p0 c 0 2 2", + "test t p1 a 0 16 4", + "test t p1 a 0 17 2", + "test t p1 c 0 13 2", + "test t p1 c 0 14 3")) + + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t global idx 1 1 3", + "test t global idx 1 14 3", + "test t p0 idx 1 1 3", + "test t p0 idx 1 2 2", + "test t p1 idx 1 13 2", + "test t p1 idx 1 14 3")) + + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t global a 0 0 5 2 1 4 0", + "test t global a 0 1 12 2 17 17 0", + "test t global c 0 0 6 1 2 6 0", + "test t global c 0 1 14 2 13 13 0", + "test t p0 a 0 0 2 1 1 2 0", + "test t p0 a 0 1 3 1 3 3 0", + "test t p0 c 0 0 3 1 3 5 0", + "test t p0 c 0 1 4 1 6 6 0", + "test t p1 a 0 0 3 1 11 13 0", + "test t p1 a 0 1 5 1 14 15 0", + "test t p1 c 0 0 4 1 7 10 0", + "test t p1 c 0 1 6 1 11 12 0")) + + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t global idx 1 0 6 1 2 6 0", + "test t global idx 1 1 14 2 13 13 0", + "test t p0 idx 1 0 3 1 3 5 0", + "test t p0 idx 1 1 4 1 6 6 0", + "test t p1 idx 1 0 4 1 7 10 0", + "test t p1 idx 1 1 6 1 11 12 0")) + + tk.MustQuery("select table_id, is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms order by table_id, is_index, hist_id asc").Check( + testkit.Rows(fmt.Sprintf("%d 0 1 12 1 19 2 0", tblID), // global, a + fmt.Sprintf("%d 0 3 14 0 20 2 0", tblID), // global, c + fmt.Sprintf("%d 1 1 14 0 0 2 0", tblID), // global, idx + fmt.Sprintf("%d 0 1 5 1 8 2 1", p0ID), // p0, a + fmt.Sprintf("%d 0 2 0 0 8 0 0", p0ID), // p0, b, not analyzed + fmt.Sprintf("%d 0 3 6 0 9 2 1", p0ID), // p0, c + fmt.Sprintf("%d 1 1 6 0 9 2 0", p0ID), // p0, idx + fmt.Sprintf("%d 0 1 7 0 11 2 1", p1ID), // p1, a + fmt.Sprintf("%d 0 2 0 0 11 0 0", p1ID), // p1, b, not analyzed + fmt.Sprintf("%d 0 3 8 0 11 2 1", p1ID), // p1, c + fmt.Sprintf("%d 1 1 8 0 11 2 0", p1ID), // p1, idx + )) + }(val) + } +} + +func TestAnalyzeColumnsWithStaticPartitionTable(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec("create table t (a int, b int, c int, index idx(c)) partition by range (a) (partition p0 values less than (10), partition p1 values less than maxvalue)") + tk.MustExec("insert into t values (1,2,1), (2,4,1), (3,6,1), (4,8,2), (4,8,2), (5,10,3), (5,10,4), (5,10,5), (null,null,6), (11,22,7), (12,24,8), (13,26,9), (14,28,10), (15,30,11), (16,32,12), (16,32,13), (16,32,13), (16,32,14), (17,34,14), (17,34,14)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + defs := tbl.Meta().Partition.Definitions + p0ID := defs[0].ID + p1ID := defs[1].ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1", + "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where a < 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, []interface{}{"test", "t", "global", "a"}, rows[0][:4]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 4, len(rows)) + require.Equal(t, []interface{}{"test", "t", "p0", "a"}, rows[0][:4]) + require.Equal(t, []interface{}{"test", "t", "p0", "c"}, rows[1][:4]) + require.Equal(t, []interface{}{"test", "t", "p1", "a"}, rows[2][:4]) + require.Equal(t, []interface{}{"test", "t", "p1", "c"}, rows[3][:4]) + + rows = tk.MustQuery("show stats_meta where db_name = 'test' and table_name = 't'").Sort().Rows() + require.Equal(t, 2, len(rows)) + require.Equal(t, []interface{}{"test", "t", "p0", "0", "9"}, append(rows[0][:3], rows[0][4:]...)) + require.Equal(t, []interface{}{"test", "t", "p1", "0", "11"}, append(rows[1][:3], rows[1][4:]...)) + + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t p0 a 0 4 2", + "test t p0 a 0 5 3", + "test t p0 c 0 1 3", + "test t p0 c 0 2 2", + "test t p1 a 0 16 4", + "test t p1 a 0 17 2", + "test t p1 c 0 13 2", + "test t p1 c 0 14 3")) + + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t p0 idx 1 1 3", + "test t p0 idx 1 2 2", + "test t p1 idx 1 13 2", + "test t p1 idx 1 14 3")) + + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t p0 a 0 0 2 1 1 2 0", + "test t p0 a 0 1 3 1 3 3 0", + "test t p0 c 0 0 3 1 3 5 0", + "test t p0 c 0 1 4 1 6 6 0", + "test t p1 a 0 0 3 1 11 13 0", + "test t p1 a 0 1 5 1 14 15 0", + "test t p1 c 0 0 4 1 7 10 0", + "test t p1 c 0 1 6 1 11 12 0")) + + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t p0 idx 1 0 3 1 3 5 0", + "test t p0 idx 1 1 4 1 6 6 0", + "test t p1 idx 1 0 4 1 7 10 0", + "test t p1 idx 1 1 6 1 11 12 0")) + + tk.MustQuery("select table_id, is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms order by table_id, is_index, hist_id asc").Check( + testkit.Rows(fmt.Sprintf("%d 0 1 5 1 8 2 1", p0ID), // p0, a + fmt.Sprintf("%d 0 2 0 0 8 0 0", p0ID), // p0, b, not analyzed + fmt.Sprintf("%d 0 3 6 0 9 2 1", p0ID), // p0, c + fmt.Sprintf("%d 1 1 6 0 9 2 0", p0ID), // p0, idx + fmt.Sprintf("%d 0 1 7 0 11 2 1", p1ID), // p1, a + fmt.Sprintf("%d 0 2 0 0 11 0 0", p1ID), // p1, b, not analyzed + fmt.Sprintf("%d 0 3 8 0 11 2 1", p1ID), // p1, c + fmt.Sprintf("%d 1 1 8 0 11 2 0", p1ID), // p1, idx + )) + }(val) + } +} + +func TestAnalyzeColumnsWithExtendedStats(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set @@tidb_enable_extended_stats = on") + tk.MustExec("create table t (a int, b int, c int)") + tk.MustExec("alter table t add stats_extended s1 correlation(b,c)") + tk.MustExec("insert into t values (5,1,1), (4,2,2), (3,3,3), (2,4,4), (1,5,5)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "b", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() + require.Equal(t, 2, len(rows)) + require.Equal(t, "b", rows[0][3]) + require.Equal(t, "c", rows[1][3]) + + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 5")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t b 0 1 1", + "test t b 0 2 1", + "test t c 0 1 1", + "test t c 0 2 1")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 0 0 5 0 0", // column a is not analyzed + "0 2 5 0 5 2 1", + "0 3 5 0 5 2 1", + )) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t b 0 0 2 1 3 4 0", + "test t b 0 1 3 1 5 5 0", + "test t c 0 0 2 1 3 4 0", + "test t c 0 1 3 1 5 5 0")) + rows = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, []interface{}{"test", "t", "s1", "[b,c]", "correlation", "1.000000"}, rows[0][:len(rows[0])-1]) + }(val) + } +} + +func TestAnalyzeColumnsWithVirtualColumnIndex(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("create table t (a int, b int, c int as (b+1), index idx(c))") + tk.MustExec("insert into t (a,b) values (1,1), (2,2), (3,3), (4,4), (5,4), (6,5), (7,5), (8,5), (null,null)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", + )) + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "b", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + // virtual column c is skipped when dumping stats into disk, so only the stats of column b are updated + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "b", rows[0][3]) + + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 9")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t b 0 4 2", + "test t b 0 5 3", + "test t idx 1 5 2", + "test t idx 1 6 3")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 0 0 0 0", // column a is not analyzed + "0 2 5 1 2 1", + "0 3 0 0 0 0", // column c is not analyzed + "1 1 5 1 2 0")) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t b 0 0 2 1 1 2 0", + "test t b 0 1 3 1 3 3 0", + "test t idx 1 0 2 1 2 3 0", + "test t idx 1 1 3 1 4 4 0")) + }(val) + } +} + +func TestAnalyzeColumnsAfterAnalyzeAll(t *testing.T) { + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("create table t (a int, b int)") + tk.MustExec("insert into t (a,b) values (1,1), (1,1), (2,2), (2,2), (3,3), (4,4)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblID := tbl.Meta().ID + + tk.MustExec("analyze table t with 2 topn, 2 buckets") + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 6")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t a 0 1 2", + "test t a 0 2 2", + "test t b 0 1 2", + "test t b 0 2 2")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 4 0 6 2 1", + "0 2 4 0 6 2 1")) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t a 0 0 2 1 3 4 0", + "test t b 0 0 2 1 3 4 0")) + + tk.MustExec("insert into t (a,b) values (1,1), (6,6)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, "b", rows[0][3]) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + } + + // Column a is not analyzed in second ANALYZE. We keep the outdated stats of column a rather than delete them. + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 8")) + tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_idx, value, count + testkit.Rows("test t a 0 1 2", + "test t a 0 2 2", + "test t b 0 1 3", + "test t b 0 2 2")) + tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( + testkit.Rows("0 1 4 0 8 2 1", // tot_col_size of column a is updated to 8 by DumpStatsDeltaToKV + "0 2 5 0 8 2 0.76")) + tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( + // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv + testkit.Rows("test t a 0 0 2 1 3 4 0", + "test t b 0 0 2 1 3 4 0", + "test t b 0 1 3 1 6 6 0")) + tk.MustQuery(fmt.Sprintf("select hist_id from mysql.stats_histograms where version = (select version from mysql.stats_meta where table_id = %d)", tblID)).Check(testkit.Rows("2")) + }(val) + } +} + +func TestAnalyzeColumnsErrorAndWarning(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int)") + + // analyze version 1 doesn't support `ANALYZE COLUMNS c1, ..., cn`/`ANALYZE PREDICATE COLUMNS` currently + tk.MustExec("set @@tidb_analyze_version = 1") + err := tk.ExecToErr("analyze table t columns a") + require.Equal(t, "Only the analyze version 2 supports analyzing the specified columns", err.Error()) + err = tk.ExecToErr("analyze table t predicate columns") + require.Equal(t, "Only the analyze version 2 supports analyzing predicate columns", err.Error()) + + tk.MustExec("set @@tidb_analyze_version = 2") + // invalid column + err = tk.ExecToErr("analyze table t columns c") + terr := errors.Cause(err).(*terror.Error) + require.Equal(t, errors.ErrCode(errno.ErrAnalyzeMissColumn), terr.Code()) + + // If no predicate column is collected, analyze predicate columns gives a warning and falls back to analyze all columns. + tk.MustExec("analyze table t predicate columns") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 No predicate column has been collected yet for table test.t so all columns are analyzed", + )) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Rows() + require.Equal(t, 2, len(rows)) + + for _, val := range []model.ColumnChoice{model.ColumnList, model.PredicateColumns} { + func(choice model.ColumnChoice) { + tk.MustExec("set @@tidb_analyze_version = 1") + tk.MustExec("analyze table t") + tk.MustExec("set @@tidb_analyze_version = 2") + switch choice { + case model.ColumnList: + tk.MustExec("analyze table t columns b") + case model.PredicateColumns: + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b > 1") + require.NoError(t, dom.StatsHandle().DumpColStatsUsageToKV()) + tk.MustExec("analyze table t predicate columns") + } + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t", + "Warning 1105 Table test.t has version 1 statistics so all the columns must be analyzed to overwrite the current statistics", + )) + }(val) + } +} + +func TestRecordHistoryStatsAfterAnalyze(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set global tidb_enable_historical_stats = 0") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10))") + + h := dom.StatsHandle() + is := dom.InfoSchema() + tableInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + // 1. switch off the tidb_enable_historical_stats, and there is no records in table `mysql.stats_history` + rows := tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_history where table_id = '%d'", tableInfo.Meta().ID)).Rows() + num, _ := strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 0) + + tk.MustExec("analyze table t with 2 topn") + rows = tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_history where table_id = '%d'", tableInfo.Meta().ID)).Rows() + num, _ = strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 0) + + // 2. switch on the tidb_enable_historical_stats and do analyze + tk.MustExec("set global tidb_enable_historical_stats = 1") + defer tk.MustExec("set global tidb_enable_historical_stats = 0") + tk.MustExec("analyze table t with 2 topn") + rows = tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_history where table_id = '%d'", tableInfo.Meta().ID)).Rows() + num, _ = strconv.Atoi(rows[0][0].(string)) + require.GreaterOrEqual(t, num, 1) + + // 3. dump current stats json + dumpJSONTable, err := h.DumpStatsToJSON("test", tableInfo.Meta(), nil) + require.NoError(t, err) + jsOrigin, _ := json.Marshal(dumpJSONTable) + + // 4. get the historical stats json + rows = tk.MustQuery(fmt.Sprintf("select * from mysql.stats_history where table_id = '%d' and create_time = ("+ + "select create_time from mysql.stats_history where table_id = '%d' order by create_time desc limit 1) "+ + "order by seq_no", tableInfo.Meta().ID, tableInfo.Meta().ID)).Rows() + num = len(rows) + require.GreaterOrEqual(t, num, 1) + data := make([][]byte, num) + for i, row := range rows { + data[i] = []byte(row[1].(string)) + } + jsonTbl, err := handle.BlocksToJSONTable(data) + require.NoError(t, err) + jsCur, err := json.Marshal(jsonTbl) + require.NoError(t, err) + // 5. historical stats must be equal to the current stats + require.JSONEq(t, string(jsOrigin), string(jsCur)) +} + +func TestRecordHistoryStatsMetaAfterAnalyze(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set global tidb_enable_historical_stats = 0") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("analyze table test.t") + + h := dom.StatsHandle() + is := dom.InfoSchema() + tableInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + // 1. switch off the tidb_enable_historical_stats, and there is no record in table `mysql.stats_meta_history` + tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_meta_history where table_id = '%d'", tableInfo.Meta().ID)).Check(testkit.Rows("0")) + // insert demo tuples, and there is no record either. + insertNums := 5 + for i := 0; i < insertNums; i++ { + tk.MustExec("insert into test.t (a,b) values (1,1), (2,2), (3,3)") + err := h.DumpStatsDeltaToKV(handle.DumpDelta) + require.NoError(t, err) + } + tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_meta_history where table_id = '%d'", tableInfo.Meta().ID)).Check(testkit.Rows("0")) + + // 2. switch on the tidb_enable_historical_stats and insert tuples to produce count/modifyCount delta change. + tk.MustExec("set global tidb_enable_historical_stats = 1") + defer tk.MustExec("set global tidb_enable_historical_stats = 0") + + for i := 0; i < insertNums; i++ { + tk.MustExec("insert into test.t (a,b) values (1,1), (2,2), (3,3)") + err := h.DumpStatsDeltaToKV(handle.DumpDelta) + require.NoError(t, err) + } + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta_history where table_id = '%d' order by create_time", tableInfo.Meta().ID)).Sort().Check( + testkit.Rows("18 18", "21 21", "24 24", "27 27", "30 30")) +} + +func checkAnalyzeStatus(t *testing.T, tk *testkit.TestKit, jobInfo, status, failReason, comment string, timeLimit int64) { + rows := tk.MustQuery("show analyze status where table_schema = 'test' and table_name = 't' and partition_name = ''").Rows() + require.Equal(t, 1, len(rows), comment) + require.Equal(t, jobInfo, rows[0][3], comment) + require.Equal(t, status, rows[0][7], comment) + require.Equal(t, failReason, rows[0][8], comment) + if timeLimit <= 0 { + return + } + const layout = "2006-01-02 15:04:05" + startTime, err := time.Parse(layout, rows[0][5].(string)) + require.NoError(t, err, comment) + endTime, err := time.Parse(layout, rows[0][6].(string)) + require.NoError(t, err, comment) + require.Less(t, endTime.Sub(startTime), time.Duration(timeLimit)*time.Second, comment) +} + +func testKillAutoAnalyze(t *testing.T, ver int) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) + oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) + handle.AutoAnalyzeMinCnt = 0 + defer func() { + handle.AutoAnalyzeMinCnt = 1000 + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_start_time='%v'", oriStart)) + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", oriEnd)) + }() + tk.MustExec(fmt.Sprintf("set @@tidb_analyze_version = %v", ver)) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int)") + tk.MustExec("insert into t values (1,2), (3,4)") + is := dom.InfoSchema() + h := dom.StatsHandle() + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + tk.MustExec("analyze table t") + tk.MustExec("insert into t values (5,6), (7,8), (9, 10)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + lastVersion := h.GetTableStats(tableInfo).Version + tk.MustExec("set global tidb_auto_analyze_start_time='00:00 +0000'") + tk.MustExec("set global tidb_auto_analyze_end_time='23:59 +0000'") + jobInfo := "auto analyze " + if ver == 1 { + jobInfo += "columns" + } else { + jobInfo += "table all columns with 256 buckets, 500 topn, 1 samplerate" + } + // kill auto analyze when it is pending/running/finished + for _, status := range []string{"pending", "running", "finished"} { + func() { + comment := fmt.Sprintf("kill %v analyze job", status) + tk.MustExec("delete from mysql.analyze_jobs") + mockAnalyzeStatus := "github.com/pingcap/tidb/executor/mockKill" + strings.Title(status) + if status == "running" { + mockAnalyzeStatus += "V" + strconv.Itoa(ver) + } + mockAnalyzeStatus += "AnalyzeJob" + require.NoError(t, failpoint.Enable(mockAnalyzeStatus, "return")) + defer func() { + require.NoError(t, failpoint.Disable(mockAnalyzeStatus)) + }() + if status == "pending" || status == "running" { + mockSlowAnalyze := "github.com/pingcap/tidb/executor/mockSlowAnalyzeV" + strconv.Itoa(ver) + require.NoError(t, failpoint.Enable(mockSlowAnalyze, "return")) + defer func() { + require.NoError(t, failpoint.Disable(mockSlowAnalyze)) + }() + } + require.True(t, h.HandleAutoAnalyze(is), comment) + currentVersion := h.GetTableStats(tableInfo).Version + if status == "finished" { + // If we kill a finished job, after kill command the status is still finished and the table stats are updated. + checkAnalyzeStatus(t, tk, jobInfo, "finished", "", comment, -1) + require.Greater(t, currentVersion, lastVersion, comment) + } else { + // If we kill a pending/running job, after kill command the status is failed and the table stats are not updated. + // We expect the killed analyze stops quickly. Specifically, end_time - start_time < 10s. + checkAnalyzeStatus(t, tk, jobInfo, "failed", executor.ErrQueryInterrupted.Error(), comment, 10) + require.Equal(t, currentVersion, lastVersion, comment) + } + }() + } +} + +func TestKillAutoAnalyzeV1(t *testing.T) { + testKillAutoAnalyze(t, 1) +} + +func TestKillAutoAnalyzeV2(t *testing.T) { + testKillAutoAnalyze(t, 2) +} + +func TestKillAutoAnalyzeIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) + oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) + handle.AutoAnalyzeMinCnt = 0 + defer func() { + handle.AutoAnalyzeMinCnt = 1000 + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_start_time='%v'", oriStart)) + tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", oriEnd)) + }() + tk.MustExec("set @@tidb_analyze_version = 1") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int)") + tk.MustExec("insert into t values (1,2), (3,4)") + is := dom.InfoSchema() + h := dom.StatsHandle() + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + tk.MustExec("analyze table t") + tk.MustExec("alter table t add index idx(b)") + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tblInfo := tbl.Meta() + lastVersion := h.GetTableStats(tblInfo).Version + tk.MustExec("set global tidb_auto_analyze_start_time='00:00 +0000'") + tk.MustExec("set global tidb_auto_analyze_end_time='23:59 +0000'") + const jobInfo = "auto analyze index idx" + // kill auto analyze when it is pending/running/finished + for _, status := range []string{"pending", "running", "finished"} { + func() { + comment := fmt.Sprintf("kill %v analyze job", status) + tk.MustExec("delete from mysql.analyze_jobs") + mockAnalyzeStatus := "github.com/pingcap/tidb/executor/mockKill" + strings.Title(status) + if status == "running" { + mockAnalyzeStatus += "AnalyzeIndexJob" + } else { + mockAnalyzeStatus += "AnalyzeJob" + } + require.NoError(t, failpoint.Enable(mockAnalyzeStatus, "return")) + defer func() { + require.NoError(t, failpoint.Disable(mockAnalyzeStatus)) + }() + if status == "pending" || status == "running" { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockSlowAnalyzeIndex", "return")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockSlowAnalyzeIndex")) + }() + } + require.True(t, h.HandleAutoAnalyze(dom.InfoSchema()), comment) + currentVersion := h.GetTableStats(tblInfo).Version + if status == "finished" { + // If we kill a finished job, after kill command the status is still finished and the index stats are updated. + checkAnalyzeStatus(t, tk, jobInfo, "finished", "", comment, -1) + require.Greater(t, currentVersion, lastVersion, comment) + } else { + // If we kill a pending/running job, after kill command the status is failed and the index stats are not updated. + // We expect the killed analyze stops quickly. Specifically, end_time - start_time < 10s. + checkAnalyzeStatus(t, tk, jobInfo, "failed", executor.ErrQueryInterrupted.Error(), comment, 10) + require.Equal(t, currentVersion, lastVersion, comment) + } + }() + } +} + +func TestAnalyzeJob(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + for _, result := range []string{statistics.AnalyzeFinished, statistics.AnalyzeFailed} { + tk := testkit.NewTestKit(t, store) + tk.MustExec("delete from mysql.analyze_jobs") + se := tk.Session() + job := &statistics.AnalyzeJob{ + DBName: "test", + TableName: "t", + PartitionName: "", + JobInfo: "table all columns with 256 buckets, 500 topn, 1 samplerate", + } + executor.AddNewAnalyzeJob(se, job) + require.NotNil(t, job.ID) + rows := tk.MustQuery("show analyze status").Rows() + require.Len(t, rows, 1) + require.Equal(t, job.DBName, rows[0][0]) + require.Equal(t, job.TableName, rows[0][1]) + require.Equal(t, job.PartitionName, rows[0][2]) + require.Equal(t, job.JobInfo, rows[0][3]) + require.Equal(t, "0", rows[0][4]) + require.Equal(t, "", rows[0][5]) + require.Equal(t, "", rows[0][6]) + require.Equal(t, statistics.AnalyzePending, rows[0][7]) + require.Equal(t, "", rows[0][8]) + serverInfo, err := infosync.GetServerInfo() + require.NoError(t, err) + addr := fmt.Sprintf("%s:%d", serverInfo.IP, serverInfo.Port) + require.Equal(t, addr, rows[0][9]) + connID := strconv.FormatUint(tk.Session().GetSessionVars().ConnectionID, 10) + require.Equal(t, connID, rows[0][10]) + + executor.StartAnalyzeJob(se, job) + rows = tk.MustQuery("show analyze status").Rows() + checkTime := func(val interface{}) { + str, ok := val.(string) + require.True(t, ok) + _, err := time.Parse("2006-01-02 15:04:05", str) + require.NoError(t, err) + } + checkTime(rows[0][5]) + require.Equal(t, statistics.AnalyzeRunning, rows[0][7]) + + // UpdateAnalyzeJob requires the interval between two updates to mysql.analyze_jobs is more than 5 second. + // Hence we fake last dump time as 10 second ago in order to make update to mysql.analyze_jobs happen. + lastDumpTime := time.Now().Add(-10 * time.Second) + job.Progress.SetLastDumpTime(lastDumpTime) + const smallCount int64 = 100 + executor.UpdateAnalyzeJob(se, job, smallCount) + // Delta count doesn't reach threshold so we don't dump it to mysql.analyze_jobs + require.Equal(t, smallCount, job.Progress.GetDeltaCount()) + require.Equal(t, lastDumpTime, job.Progress.GetLastDumpTime()) + rows = tk.MustQuery("show analyze status").Rows() + require.Equal(t, "0", rows[0][4]) + + const largeCount int64 = 15000000 + executor.UpdateAnalyzeJob(se, job, largeCount) + // Delta count reaches threshold so we dump it to mysql.analyze_jobs and update last dump time. + require.Equal(t, int64(0), job.Progress.GetDeltaCount()) + require.True(t, job.Progress.GetLastDumpTime().After(lastDumpTime)) + lastDumpTime = job.Progress.GetLastDumpTime() + rows = tk.MustQuery("show analyze status").Rows() + require.Equal(t, strconv.FormatInt(smallCount+largeCount, 10), rows[0][4]) + + executor.UpdateAnalyzeJob(se, job, largeCount) + // We have just updated mysql.analyze_jobs in the previous step so we don't update it until 5 second passes or the analyze job is over. + require.Equal(t, largeCount, job.Progress.GetDeltaCount()) + require.Equal(t, lastDumpTime, job.Progress.GetLastDumpTime()) + rows = tk.MustQuery("show analyze status").Rows() + require.Equal(t, strconv.FormatInt(smallCount+largeCount, 10), rows[0][4]) + + var analyzeErr error + if result == statistics.AnalyzeFailed { + analyzeErr = errors.Errorf("analyze meets error") + } + executor.FinishAnalyzeJob(se, job, analyzeErr) + rows = tk.MustQuery("show analyze status").Rows() + require.Equal(t, strconv.FormatInt(smallCount+2*largeCount, 10), rows[0][4]) + checkTime(rows[0][6]) + require.Equal(t, result, rows[0][7]) + if result == statistics.AnalyzeFailed { + require.Equal(t, analyzeErr.Error(), rows[0][8]) + } else { + require.Equal(t, "", rows[0][8]) + } + // process_id is set to NULL after the analyze job is finished/failed. + require.Equal(t, "", rows[0][10]) + } +} + +func TestShowAanalyzeStatusJobInfo(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + originalVal2 := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal2)) + }() + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("set global tidb_persist_analyze_options = 0") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int, d int, index idx_b_d(b, d))") + tk.MustExec("insert into t values (1,1,null,1), (2,1,9,1), (1,1,8,1), (2,2,7,2), (1,3,7,3), (2,4,6,4), (1,4,6,5), (2,4,6,5), (1,5,6,5)") + tk.MustExec("analyze table t columns c with 2 topn, 2 buckets") + checkJobInfo := func(expected string) { + rows := tk.MustQuery("show analyze status where table_schema = 'test' and table_name = 't'").Rows() + require.Equal(t, 1, len(rows)) + require.Equal(t, expected, rows[0][3]) + tk.MustExec("delete from mysql.analyze_jobs") + } + checkJobInfo("analyze table columns b, c, d with 2 buckets, 2 topn, 1 samplerate") + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where c > 1") + h := dom.StatsHandle() + require.NoError(t, h.DumpColStatsUsageToKV()) + tk.MustExec("analyze table t predicate columns with 2 topn, 2 buckets") + checkJobInfo("analyze table columns b, c, d with 2 buckets, 2 topn, 1 samplerate") + tk.MustExec("analyze table t") + checkJobInfo("analyze table all columns with 256 buckets, 500 topn, 1 samplerate") + tk.MustExec("set global tidb_persist_analyze_options = 1") + tk.MustExec("analyze table t columns a with 1 topn, 3 buckets") + checkJobInfo("analyze table columns a, b, d with 3 buckets, 1 topn, 1 samplerate") + tk.MustExec("analyze table t") + checkJobInfo("analyze table columns a, b, d with 3 buckets, 1 topn, 1 samplerate") +} diff --git a/executor/batch_checker.go b/executor/batch_checker.go index 7b214d7e54196..76eea024bc3d3 100644 --- a/executor/batch_checker.go +++ b/executor/batch_checker.go @@ -259,8 +259,9 @@ func getOldRow(ctx context.Context, sctx sessionctx.Context, txn kv.Transaction, } } } - if col.IsGenerated() { + if col.IsGenerated() && col.State == model.StatePublic { // only the virtual column needs fill back. + // Insert doesn't fill the generated columns at non-public state. if !col.GeneratedStored { val, err := genExprs[gIdx].Eval(chunk.MutRowFromDatums(oldRow).ToRow()) if err != nil { diff --git a/executor/batch_point_get.go b/executor/batch_point_get.go index c30bf507d6d9d..8abf8843b26bf 100644 --- a/executor/batch_point_get.go +++ b/executor/batch_point_get.go @@ -37,6 +37,7 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/hack" + "github.com/pingcap/tidb/util/logutil/consistency" "github.com/pingcap/tidb/util/math" "github.com/pingcap/tidb/util/rowcodec" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" @@ -116,6 +117,9 @@ func (e *BatchPointGetExec) Open(context.Context) error { } else { snapshot = e.ctx.GetSnapshotWithTS(e.snapshotTS) } + if e.ctx.GetSessionVars().StmtCtx.RCCheckTS { + snapshot.SetOption(kv.IsolationLevel, kv.RCCheckTS) + } if e.cacheTable != nil { snapshot = cacheTableSnapshot{snapshot, e.cacheTable} } @@ -128,7 +132,7 @@ func (e *BatchPointGetExec) Open(context.Context) error { stmtCtx.RuntimeStatsColl.RegisterStats(e.id, e.stats) } replicaReadType := e.ctx.GetSessionVars().GetReplicaRead() - if replicaReadType.IsFollowerRead() { + if replicaReadType.IsFollowerRead() && !e.ctx.GetSessionVars().StmtCtx.RCCheckTS { snapshot.SetOption(kv.ReplicaRead, replicaReadType) } snapshot.SetOption(kv.TaskID, stmtCtx.TaskID) @@ -150,6 +154,7 @@ func (e *BatchPointGetExec) Open(context.Context) error { }) } setResourceGroupTaggerForTxn(stmtCtx, snapshot) + setRPCInterceptorOfExecCounterForTxn(sessVars, snapshot) var batchGetter kv.BatchGetter = snapshot if txn.Valid() { lock := e.tblInfo.Lock @@ -474,9 +479,24 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error { for i, key := range keys { val := values[string(key)] if len(val) == 0 { - if e.idxInfo != nil && (!e.tblInfo.IsCommonHandle || !e.idxInfo.Primary) { - return kv.ErrNotExist.GenWithStack("inconsistent extra index %s, handle %d not found in table", - e.idxInfo.Name.O, e.handles[i]) + if e.idxInfo != nil && (!e.tblInfo.IsCommonHandle || !e.idxInfo.Primary) && + !e.ctx.GetSessionVars().StmtCtx.WeakConsistency { + return (&consistency.Reporter{ + HandleEncode: func(_ kv.Handle) kv.Key { + return key + }, + IndexEncode: func(_ *consistency.RecordData) kv.Key { + return indexKeys[i] + }, + Tbl: e.tblInfo, + Idx: e.idxInfo, + Sctx: e.ctx, + }).ReportLookupInconsistent(ctx, + 1, 0, + e.handles[i:i+1], + e.handles, + []consistency.RecordData{{}}, + ) } continue } @@ -523,7 +543,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error { // LockKeys locks the keys for pessimistic transaction. func LockKeys(ctx context.Context, seCtx sessionctx.Context, lockWaitTime int64, keys ...kv.Key) error { txnCtx := seCtx.GetSessionVars().TxnCtx - lctx := newLockCtx(seCtx.GetSessionVars(), lockWaitTime) + lctx := newLockCtx(seCtx.GetSessionVars(), lockWaitTime, len(keys)) if txnCtx.IsPessimistic { lctx.InitReturnValues(len(keys)) } diff --git a/executor/benchmark_test.go b/executor/benchmark_test.go index 3dbe99ad96554..a36ad9eba5f39 100644 --- a/executor/benchmark_test.go +++ b/executor/benchmark_test.go @@ -40,7 +40,6 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/benchdaily" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/disk" "github.com/pingcap/tidb/util/memory" @@ -1303,7 +1302,7 @@ func (tc indexJoinTestCase) getMockDataSourceOptByRows(rows int) mockDataSourceP } } -func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) Executor { +func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) (Executor, error) { outerCols, innerCols := tc.columns(), tc.columns() joinSchema := expression.NewSchema(outerCols...) joinSchema.Append(innerCols...) @@ -1317,6 +1316,13 @@ func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, for i := range keyOff2IdxOff { keyOff2IdxOff[i] = i } + + readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope). + newDataReaderBuilder(&mockPhysicalIndexReader{e: innerDS}) + if err != nil { + return nil, err + } + e := &IndexLookUpJoin{ baseExecutor: newBaseExecutor(tc.ctx, joinSchema, 1, outerDS), outerCtx: outerCtx{ @@ -1325,7 +1331,7 @@ func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, hashCols: tc.outerHashKeyIdx, }, innerCtx: innerCtx{ - readerBuilder: &dataReaderBuilder{Plan: &mockPhysicalIndexReader{e: innerDS}, executorBuilder: newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope)}, + readerBuilder: readerBuilder, rowTypes: rightTypes, colLens: colLens, keyCols: tc.innerJoinKeyIdx, @@ -1338,21 +1344,24 @@ func prepare4IndexInnerHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, lastColHelper: nil, } e.joinResult = newFirstChunk(e) - return e + return e, nil } -func prepare4IndexOuterHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) Executor { - e := prepare4IndexInnerHashJoin(tc, outerDS, innerDS).(*IndexLookUpJoin) - idxHash := &IndexNestedLoopHashJoin{IndexLookUpJoin: *e} +func prepare4IndexOuterHashJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) (Executor, error) { + e, err := prepare4IndexInnerHashJoin(tc, outerDS, innerDS) + if err != nil { + return nil, err + } + idxHash := &IndexNestedLoopHashJoin{IndexLookUpJoin: *e.(*IndexLookUpJoin)} concurrency := tc.concurrency idxHash.joiners = make([]joiner, concurrency) for i := 0; i < concurrency; i++ { - idxHash.joiners[i] = e.joiner.Clone() + idxHash.joiners[i] = e.(*IndexLookUpJoin).joiner.Clone() } - return idxHash + return idxHash, nil } -func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) Executor { +func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, innerDS *mockDataSource) (Executor, error) { outerCols, innerCols := tc.columns(), tc.columns() joinSchema := expression.NewSchema(outerCols...) joinSchema.Append(innerCols...) @@ -1381,6 +1390,13 @@ func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, inne compareFuncs = append(compareFuncs, expression.GetCmpFunction(nil, outerJoinKeys[i], innerJoinKeys[i])) outerCompareFuncs = append(outerCompareFuncs, expression.GetCmpFunction(nil, outerJoinKeys[i], outerJoinKeys[i])) } + + readerBuilder, err := newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope). + newDataReaderBuilder(&mockPhysicalIndexReader{e: innerDS}) + if err != nil { + return nil, err + } + e := &IndexLookUpMergeJoin{ baseExecutor: newBaseExecutor(tc.ctx, joinSchema, 2, outerDS), outerMergeCtx: outerMergeCtx{ @@ -1391,7 +1407,7 @@ func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, inne compareFuncs: outerCompareFuncs, }, innerMergeCtx: innerMergeCtx{ - readerBuilder: &dataReaderBuilder{Plan: &mockPhysicalIndexReader{e: innerDS}, executorBuilder: newExecutorBuilder(tc.ctx, nil, nil, 0, false, oracle.GlobalTxnScope)}, + readerBuilder: readerBuilder, rowTypes: rightTypes, joinKeys: innerJoinKeys, colLens: colLens, @@ -1409,7 +1425,7 @@ func prepare4IndexMergeJoin(tc *indexJoinTestCase, outerDS *mockDataSource, inne joiners[i] = newJoiner(tc.ctx, 0, false, defaultValues, nil, leftTypes, rightTypes, nil) } e.joiners = joiners - return e + return e, nil } type indexJoinType int8 @@ -1431,13 +1447,18 @@ func benchmarkIndexJoinExecWithCase( for i := 0; i < b.N; i++ { b.StopTimer() var exec Executor + var err error switch execType { case indexInnerHashJoin: - exec = prepare4IndexInnerHashJoin(tc, outerDS, innerDS) + exec, err = prepare4IndexInnerHashJoin(tc, outerDS, innerDS) case indexOuterHashJoin: - exec = prepare4IndexOuterHashJoin(tc, outerDS, innerDS) + exec, err = prepare4IndexOuterHashJoin(tc, outerDS, innerDS) case indexMergeJoin: - exec = prepare4IndexMergeJoin(tc, outerDS, innerDS) + exec, err = prepare4IndexMergeJoin(tc, outerDS, innerDS) + } + + if err != nil { + b.Fatal(err) } tmpCtx := context.Background() @@ -1446,7 +1467,7 @@ func benchmarkIndexJoinExecWithCase( innerDS.prepareChunks() b.StartTimer() - if err := exec.Open(tmpCtx); err != nil { + if err = exec.Open(tmpCtx); err != nil { b.Fatal(err) } for { @@ -2101,9 +2122,3 @@ func BenchmarkPipelinedRowNumberWindowFunctionExecution(b *testing.B) { b.ReportAllocs() } - -func TestBenchDaily(t *testing.T) { - benchdaily.Run( - BenchmarkReadLastLinesOfHugeLine, - ) -} diff --git a/executor/bind.go b/executor/bind.go index 08f2b7bc6e523..aed1ee3460e68 100644 --- a/executor/bind.go +++ b/executor/bind.go @@ -37,6 +37,7 @@ type SQLBindExec struct { db string isGlobal bool bindAst ast.StmtNode + newStatus string } // Next implements the Executor Next interface. @@ -55,6 +56,8 @@ func (e *SQLBindExec) Next(ctx context.Context, req *chunk.Chunk) error { return e.evolveBindings() case plannercore.OpReloadBindings: return e.reloadBindings() + case plannercore.OpSetBindingStatus: + return e.setBindingStatus() default: return errors.Errorf("unsupported SQL bind operation: %v", e.sqlBindOp) } @@ -77,6 +80,23 @@ func (e *SQLBindExec) dropSQLBind() error { return domain.GetDomain(e.ctx).BindHandle().DropBindRecord(e.normdOrigSQL, e.db, bindInfo) } +func (e *SQLBindExec) setBindingStatus() error { + var bindInfo *bindinfo.Binding + if e.bindSQL != "" { + bindInfo = &bindinfo.Binding{ + BindSQL: e.bindSQL, + Charset: e.charset, + Collation: e.collation, + } + } + ok, err := domain.GetDomain(e.ctx).BindHandle().SetBindRecordStatus(e.normdOrigSQL, bindInfo, e.newStatus) + if err == nil && !ok { + warningMess := errors.New("There are no bindings can be set the status. Please check the SQL text") + e.ctx.GetSessionVars().StmtCtx.AppendWarning(warningMess) + } + return err +} + func (e *SQLBindExec) createSQLBind() error { // For audit log, SQLBindExec execute "explain" statement internally, save and recover stmtctx // is necessary to avoid 'create binding' been recorded as 'explain'. @@ -89,7 +109,7 @@ func (e *SQLBindExec) createSQLBind() error { BindSQL: e.bindSQL, Charset: e.charset, Collation: e.collation, - Status: bindinfo.Using, + Status: bindinfo.Enabled, Source: bindinfo.Manual, } record := &bindinfo.BindRecord{ diff --git a/executor/brie.go b/executor/brie.go index 9be7349c494a8..be4cb1a54d7df 100644 --- a/executor/brie.go +++ b/executor/brie.go @@ -15,6 +15,7 @@ package executor import ( + "bytes" "context" "net/url" "strings" @@ -25,13 +26,6 @@ import ( "github.com/pingcap/errors" backuppb "github.com/pingcap/kvproto/pkg/brpb" "github.com/pingcap/kvproto/pkg/encryptionpb" - filter "github.com/pingcap/tidb-tools/pkg/table-filter" - "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" - pd "github.com/tikv/pd/client" - "github.com/pingcap/tidb/br/pkg/glue" "github.com/pingcap/tidb/br/pkg/storage" "github.com/pingcap/tidb/br/pkg/task" @@ -40,6 +34,11 @@ import ( "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta/autoid" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" @@ -47,7 +46,9 @@ import ( "github.com/pingcap/tidb/util/printer" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/sqlexec" + filter "github.com/pingcap/tidb/util/table-filter" "github.com/tikv/client-go/v2/oracle" + pd "github.com/tikv/pd/client" ) const clearInterval = 10 * time.Minute @@ -285,9 +286,9 @@ func (b *executorBuilder) buildBRIE(s *ast.BRIEStmt, schema *expression.Schema) cfg.TableFilter = filter.All() } - if tidbCfg.LowerCaseTableNames != 0 { - cfg.TableFilter = filter.CaseInsensitive(cfg.TableFilter) - } + // table options are stored in original case, but comparison + // is expected to be performed insensitive. + cfg.TableFilter = filter.CaseInsensitive(cfg.TableFilter) switch s.Kind { case ast.BRIEKindBackup: @@ -462,11 +463,7 @@ func (gs *tidbGlueSession) CreateSession(store kv.Storage) (glue.Session, error) // These queries execute without privilege checking, since the calling statements // such as BACKUP and RESTORE have already been privilege checked. func (gs *tidbGlueSession) Execute(ctx context.Context, sql string) error { - stmt, err := gs.se.(sqlexec.RestrictedSQLExecutor).ParseWithParams(ctx, sql) - if err != nil { - return err - } - _, _, err = gs.se.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(ctx, stmt) + _, _, err := gs.se.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, nil, sql) return err } @@ -479,17 +476,30 @@ func (gs *tidbGlueSession) ExecuteInternal(ctx context.Context, sql string, args // CreateDatabase implements glue.Session func (gs *tidbGlueSession) CreateDatabase(ctx context.Context, schema *model.DBInfo) error { d := domain.GetDomain(gs.se).DDL() + // 512 is defaultCapOfCreateTable. + result := bytes.NewBuffer(make([]byte, 0, 512)) + if err := ConstructResultOfShowCreateDatabase(gs.se, schema, true, result); err != nil { + return err + } + gs.se.SetValue(sessionctx.QueryString, result.String()) schema = schema.Clone() if len(schema.Charset) == 0 { schema.Charset = mysql.DefaultCharset } - return d.CreateSchemaWithInfo(gs.se, schema, ddl.OnExistIgnore, true) + return d.CreateSchemaWithInfo(gs.se, schema, ddl.OnExistIgnore) } // CreateTable implements glue.Session func (gs *tidbGlueSession) CreateTable(ctx context.Context, dbName model.CIStr, table *model.TableInfo) error { d := domain.GetDomain(gs.se).DDL() + // 512 is defaultCapOfCreateTable. + result := bytes.NewBuffer(make([]byte, 0, 512)) + if err := ConstructResultOfShowCreateTable(gs.se, table, autoid.Allocators{}, result); err != nil { + return err + } + gs.se.SetValue(sessionctx.QueryString, result.String()) + // Clone() does not clone partitions yet :( table = table.Clone() if table.Partition != nil { @@ -498,13 +508,26 @@ func (gs *tidbGlueSession) CreateTable(ctx context.Context, dbName model.CIStr, table.Partition = &newPartition } - return d.CreateTableWithInfo(gs.se, dbName, table, ddl.OnExistIgnore, true) + return d.CreateTableWithInfo(gs.se, dbName, table, ddl.OnExistIgnore) +} + +// CreatePlacementPolicy implements glue.Session +func (gs *tidbGlueSession) CreatePlacementPolicy(ctx context.Context, policy *model.PolicyInfo) error { + gs.se.SetValue(sessionctx.QueryString, ConstructResultOfShowCreatePlacementPolicy(policy)) + d := domain.GetDomain(gs.se).DDL() + // the default behaviour is ignoring duplicated policy during restore. + return d.CreatePlacementPolicyWithInfo(gs.se, policy, ddl.OnExistIgnore) } // Close implements glue.Session func (gs *tidbGlueSession) Close() { } +// GetGlobalVariables implements glue.Session. +func (gs *tidbGlueSession) GetGlobalVariable(name string) (string, error) { + return gs.se.GetSessionVars().GlobalVarsAccessor.GetTiDBTableValue(name) +} + // Open implements glue.Glue func (gs *tidbGlueSession) Open(string, pd.SecurityOption) (kv.Storage, error) { return gs.se.GetStore(), nil diff --git a/executor/builder.go b/executor/builder.go index 78c94fd02f1aa..a2394c0537df8 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -17,6 +17,7 @@ package executor import ( "bytes" "context" + "fmt" "math" "sort" "strconv" @@ -30,7 +31,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/diagnosticspb" - "github.com/pingcap/log" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor/aggfuncs" @@ -46,6 +46,7 @@ import ( plannerutil "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/table" @@ -62,6 +63,7 @@ import ( "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/rowcodec" + "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/timeutil" "github.com/pingcap/tipb/go-tipb" "go.uber.org/zap" @@ -85,7 +87,8 @@ var ( type executorBuilder struct { ctx sessionctx.Context is infoschema.InfoSchema - snapshotTS uint64 // The consistent snapshot timestamp for the executor to read data. + snapshotTS uint64 // The ts for snapshot-read. A select statement without for update will use this ts + forUpdateTS uint64 // The ts should be used by insert/update/delete/select-for-update statement snapshotTSCached bool err error // err is set when there is error happened during Executor building process. hasLock bool @@ -96,6 +99,14 @@ type executorBuilder struct { inUpdateStmt bool inDeleteStmt bool inInsertStmt bool + inSelectLockStmt bool + + // forDataReaderBuilder indicates whether the builder is used by a dataReaderBuilder. + // When forDataReader is true, the builder should use the dataReaderTS as the executor read ts. This is because + // dataReaderBuilder can be used in concurrent goroutines, so we must ensure that getting the ts should be thread safe and + // can return a correct value even if the session context has already been destroyed + forDataReaderBuilder bool + dataReaderTS uint64 } // CTEStorages stores resTbl and iterInTbl for CTEExec. @@ -111,6 +122,7 @@ func newExecutorBuilder(ctx sessionctx.Context, is infoschema.InfoSchema, ti *Te ctx: ctx, is: is, Ti: ti, + snapshotTSCached: isStaleness, snapshotTS: snapshotTS, isStaleness: isStaleness, readReplicaScope: replicaReadScope, @@ -300,14 +312,6 @@ func (b *executorBuilder) buildCancelDDLJobs(v *plannercore.CancelDDLJobs) Execu baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), jobIDs: v.JobIDs, } - // Run within a new transaction. If it runs within the session transaction, commit failure won't be reported to the user. - errInTxn := kv.RunInNewTxn(context.Background(), e.ctx.GetStore(), true, func(ctx context.Context, txn kv.Transaction) (err error) { - e.errs, err = admin.CancelJobs(txn, e.jobIDs) - return - }) - if errInTxn != nil { - b.err = errInTxn - } return e } @@ -360,10 +364,13 @@ func (b *executorBuilder) buildShowDDL(v *plannercore.ShowDDL) Executor { } func (b *executorBuilder) buildShowDDLJobs(v *plannercore.PhysicalShowDDLJobs) Executor { + loc := b.ctx.GetSessionVars().Location() + ddlJobRetriever := DDLJobRetriever{TZLoc: loc} e := &ShowDDLJobsExec{ - jobNumber: int(v.JobNumber), - is: b.is, - baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), + jobNumber: int(v.JobNumber), + is: b.is, + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), + DDLJobRetriever: ddlJobRetriever, } return e } @@ -490,7 +497,7 @@ func (b *executorBuilder) buildRecoverIndex(v *plannercore.RecoverIndex) Executo idxName := strings.ToLower(v.IndexName) index := tables.GetWritableIndexByName(idxName, t) if index == nil { - b.err = errors.Errorf("index `%v` is not found in table `%v`.", v.IndexName, v.Table.Name.O) + b.err = errors.Errorf("index `%v` is not found in table `%v`", v.IndexName, v.Table.Name.O) return nil } e := &RecoverIndexExec{ @@ -550,7 +557,7 @@ func (b *executorBuilder) buildCleanupIndex(v *plannercore.CleanupIndex) Executo } if index == nil { - b.err = errors.Errorf("index `%v` is not found in table `%v`.", v.IndexName, v.Table.Name.O) + b.err = errors.Errorf("index `%v` is not found in table `%v`", v.IndexName, v.Table.Name.O) return nil } e := &CleanupIndexExec{ @@ -629,12 +636,16 @@ func (b *executorBuilder) buildDeallocate(v *plannercore.Deallocate) Executor { } func (b *executorBuilder) buildSelectLock(v *plannercore.PhysicalLock) Executor { + if !b.inSelectLockStmt { + b.inSelectLockStmt = true + defer func() { b.inSelectLockStmt = false }() + } b.hasLock = true if b.err = b.updateForUpdateTSIfNeeded(v.Children()[0]); b.err != nil { return nil } // Build 'select for update' using the 'for update' ts. - b.snapshotTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() + b.forUpdateTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() src := b.build(v.Children()[0]) if b.err != nil { @@ -648,10 +659,10 @@ func (b *executorBuilder) buildSelectLock(v *plannercore.PhysicalLock) Executor return src } e := &SelectLockExec{ - baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID(), src), - Lock: v.Lock, - tblID2Handle: v.TblID2Handle, - partitionedTable: v.PartitionedTable, + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID(), src), + Lock: v.Lock, + tblID2Handle: v.TblID2Handle, + tblID2PhysTblIDCol: v.TblID2PhysTblIDCol, } // filter out temporary tables because they do not store any record in tikv and should not write any lock @@ -667,16 +678,6 @@ func (b *executorBuilder) buildSelectLock(v *plannercore.PhysicalLock) Executor } } - if len(e.partitionedTable) > 0 { - schema := v.Schema() - e.tblID2PIDColumnIndex = make(map[int64]int) - for i := 0; i < len(v.ExtraPIDInfo.Columns); i++ { - col := v.ExtraPIDInfo.Columns[i] - tblID := v.ExtraPIDInfo.TblIDs[i] - offset := schema.ColumnIndex(col) - e.tblID2PIDColumnIndex[tblID] = offset - } - } return e } @@ -718,12 +719,6 @@ func (b *executorBuilder) buildPrepare(v *plannercore.Prepare) Executor { } func (b *executorBuilder) buildExecute(v *plannercore.Execute) Executor { - b.snapshotTS = v.SnapshotTS - b.isStaleness = v.IsStaleness - b.readReplicaScope = v.ReadReplicaScope - if b.snapshotTS != 0 { - b.is, b.err = domain.GetDomain(b.ctx).GetSnapshotInfoSchema(b.snapshotTS) - } e := &ExecuteExec{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), is: b.is, @@ -734,6 +729,34 @@ func (b *executorBuilder) buildExecute(v *plannercore.Execute) Executor { plan: v.Plan, outputNames: v.OutputNames(), } + + failpoint.Inject("assertStaleReadValuesSameWithExecuteAndBuilder", func() { + // This fail point is used to assert the behavior after refactoring is exactly the same with the previous implement. + // Some variables in `plannercore.Execute` is deprecated and only be used for asserting now. + if b.snapshotTS != v.SnapshotTS { + panic(fmt.Sprintf("%d != %d", b.snapshotTS, v.SnapshotTS)) + } + + if b.isStaleness != v.IsStaleness { + panic(fmt.Sprintf("%v != %v", b.isStaleness, v.IsStaleness)) + } + + if b.readReplicaScope != v.ReadReplicaScope { + panic(fmt.Sprintf("%s != %s", b.readReplicaScope, v.ReadReplicaScope)) + } + + if v.SnapshotTS != 0 { + is, err := domain.GetDomain(b.ctx).GetSnapshotInfoSchema(b.snapshotTS) + if err != nil { + panic(err) + } + + if b.is.SchemaMetaVersion() != is.SchemaMetaVersion() { + panic(fmt.Sprintf("%d != %d", b.is.SchemaMetaVersion(), is.SchemaMetaVersion())) + } + } + }) + failpoint.Inject("assertExecutePrepareStatementStalenessOption", func(val failpoint.Value) { vs := strings.Split(val.(string), "_") assertTS, assertTxnScope := vs[0], vs[1] @@ -763,6 +786,7 @@ func (b *executorBuilder) buildShow(v *plannercore.PhysicalShow) Executor { IfNotExists: v.IfNotExists, GlobalScope: v.GlobalScope, Extended: v.Extended, + Extractor: v.Extractor, } if e.Tp == ast.ShowMasterStatus { // show master status need start ts. @@ -820,7 +844,7 @@ func (b *executorBuilder) buildInsert(v *plannercore.Insert) Executor { return nil } } - b.snapshotTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() + b.forUpdateTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() selectExec := b.build(v.SelectPlan) if b.err != nil { return nil @@ -1066,7 +1090,6 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco return x } us := &UnionScanExec{baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID(), reader)} - us.cacheTable = v.CacheTable // Get the handle column index of the below Plan. us.belowHandleCols = v.HandleCols us.mutableRow = chunk.MutRowFromTypes(retTypes(us)) @@ -1082,6 +1105,13 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco us.collators = append(us.collators, collate.GetCollator(tp.Collate)) } + startTS, err := b.getSnapshotTS() + sessionVars := b.ctx.GetSessionVars() + if err != nil { + b.err = err + return nil + } + switch x := reader.(type) { case *TableReaderExecutor: us.desc = x.desc @@ -1089,6 +1119,7 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco us.columns = x.columns us.table = x.table us.virtualColumnIndex = x.virtualColumnIndex + us.handleCachedTable(b, x, sessionVars, startTS) case *IndexReaderExecutor: us.desc = x.desc for _, ic := range x.index.Columns { @@ -1102,6 +1133,7 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco us.conditions, us.conditionsWithVirCol = plannercore.SplitSelCondsWithVirtualColumn(v.Conditions) us.columns = x.columns us.table = x.table + us.handleCachedTable(b, x, sessionVars, startTS) case *IndexLookUpExecutor: us.desc = x.desc for _, ic := range x.index.Columns { @@ -1116,6 +1148,7 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco us.columns = x.columns us.table = x.table us.virtualColumnIndex = buildVirtualColumnIndex(us.Schema(), us.columns) + us.handleCachedTable(b, x, sessionVars, startTS) case *IndexMergeReaderExecutor: // IndexMergeReader doesn't care order for now. So we will not set desc and useIndex. us.conditions, us.conditionsWithVirCol = plannercore.SplitSelCondsWithVirtualColumn(v.Conditions) @@ -1129,6 +1162,33 @@ func (b *executorBuilder) buildUnionScanFromReader(reader Executor, v *plannerco return us } +type bypassDataSourceExecutor interface { + dataSourceExecutor + setDummy() +} + +func (us *UnionScanExec) handleCachedTable(b *executorBuilder, x bypassDataSourceExecutor, vars *variable.SessionVars, startTS uint64) { + tbl := x.Table() + if tbl.Meta().TableCacheStatusType == model.TableCacheStatusEnable { + cachedTable := tbl.(table.CachedTable) + // Determine whether the cache can be used. + leaseDuration := time.Duration(variable.TableCacheLease.Load()) * time.Second + cacheData, loading := cachedTable.TryReadFromCache(startTS, leaseDuration) + if cacheData != nil { + vars.StmtCtx.ReadFromTableCache = true + x.setDummy() + us.cacheTable = cacheData + } else if loading { + // continue + } else { + if !b.inUpdateStmt && !b.inDeleteStmt && !b.inInsertStmt && !vars.StmtCtx.InExplainStmt { + store := b.ctx.GetStore() + cachedTable.UpdateLockForRead(context.Background(), store, startTS, leaseDuration) + } + } + } +} + // buildMergeJoin builds MergeJoinExec executor. func (b *executorBuilder) buildMergeJoin(v *plannercore.PhysicalMergeJoin) Executor { leftExec := b.build(v.Children()[0]) @@ -1474,8 +1534,24 @@ func (b *executorBuilder) buildTableDual(v *plannercore.PhysicalTableDual) Execu return e } -// `getSnapshotTS` returns the timestamp of the snapshot that a reader should read. +// `getSnapshotTS` returns for-update-ts if in insert/update/delete/lock statement otherwise the isolation read ts +// Please notice that in RC isolation, the above two ts are the same func (b *executorBuilder) getSnapshotTS() (uint64, error) { + if b.forDataReaderBuilder { + return b.dataReaderTS, nil + } + + if (b.inInsertStmt || b.inUpdateStmt || b.inDeleteStmt || b.inSelectLockStmt) && b.forUpdateTS != 0 { + return b.forUpdateTS, nil + } + + return b.getReadTS() +} + +// getReadTS returns the ts used by select (without for-update clause). The return value is affected by the isolation level +// and some stale/historical read contexts. For example, it will return txn.StartTS in RR and return +// the current timestamp in RC isolation +func (b *executorBuilder) getReadTS() (uint64, error) { // `refreshForUpdateTSForRC` should always be invoked before returning the cached value to // ensure the correct value is returned even the `snapshotTS` field is already set by other // logics. However for `IndexLookUpMergeJoin` and `IndexLookUpHashJoin`, it requires caching the @@ -1624,6 +1700,14 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo timeRange: v.QueryTimeRange, }, } + case strings.ToLower(infoschema.TableTiKVRegionPeers): + return &MemTableReaderExec{ + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), + table: v.Table, + retriever: &tikvRegionPeersRetriever{ + extractor: v.Extractor.(*plannercore.TikvRegionPeersExtractor), + }, + } case strings.ToLower(infoschema.TableSchemata), strings.ToLower(infoschema.TableStatistics), strings.ToLower(infoschema.TableTiDBIndexes), @@ -1645,7 +1729,6 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo strings.ToLower(infoschema.TableProcesslist), strings.ToLower(infoschema.ClusterTableProcesslist), strings.ToLower(infoschema.TableTiKVRegionStatus), - strings.ToLower(infoschema.TableTiKVRegionPeers), strings.ToLower(infoschema.TableTiDBHotRegions), strings.ToLower(infoschema.TableSessionVar), strings.ToLower(infoschema.TableConstraints), @@ -1658,13 +1741,14 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo strings.ToLower(infoschema.TableClientErrorsSummaryByUser), strings.ToLower(infoschema.TableClientErrorsSummaryByHost), strings.ToLower(infoschema.TableAttributes), - strings.ToLower(infoschema.TablePlacementRules): + strings.ToLower(infoschema.TablePlacementPolicies): return &MemTableReaderExec{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), table: v.Table, retriever: &memtableRetriever{ - table: v.Table, - columns: v.Columns, + table: v.Table, + columns: v.Columns, + extractor: v.Extractor, }, } case strings.ToLower(infoschema.TableTiDBTrx), @@ -1714,8 +1798,9 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), table: v.Table, retriever: &hugeMemTableRetriever{ - table: v.Table, - columns: v.Columns, + table: v.Table, + columns: v.Columns, + extractor: v.Extractor.(*plannercore.ColumnsTableExtractor), }, } @@ -1740,9 +1825,12 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo }, } case strings.ToLower(infoschema.TableDDLJobs): + loc := b.ctx.GetSessionVars().Location() + ddlJobRetriever := DDLJobRetriever{TZLoc: loc} return &DDLJobsReaderExec{ - baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), - is: b.is, + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), + is: b.is, + DDLJobRetriever: ddlJobRetriever, } case strings.ToLower(infoschema.TableTiFlashTables), strings.ToLower(infoschema.TableTiFlashSegments): @@ -1997,7 +2085,7 @@ func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor { if b.err = b.updateForUpdateTSIfNeeded(v.SelectPlan); b.err != nil { return nil } - b.snapshotTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() + b.forUpdateTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() selExec := b.build(v.SelectPlan) if b.err != nil { return nil @@ -2034,7 +2122,7 @@ func getAssignFlag(ctx sessionctx.Context, v *plannercore.Update, schemaLen int) } for _, assign := range v.OrderedList { if !ctx.GetSessionVars().AllowWriteRowID && assign.Col.ID == model.ExtraHandleID { - return nil, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.") + return nil, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported") } tblIdx, found := v.TblColPosInfos.FindTblIdx(assign.Col.Index) if found { @@ -2054,7 +2142,7 @@ func (b *executorBuilder) buildDelete(v *plannercore.Delete) Executor { if b.err = b.updateForUpdateTSIfNeeded(v.SelectPlan); b.err != nil { return nil } - b.snapshotTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() + b.forUpdateTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() selExec := b.build(v.SelectPlan) if b.err != nil { return nil @@ -2107,6 +2195,15 @@ func (b *executorBuilder) refreshForUpdateTSForRC() error { defer func() { b.snapshotTS = b.ctx.GetSessionVars().TxnCtx.GetForUpdateTS() }() + // The first time read-consistency read is executed and `RcReadCheckTS` is enabled, try to use + // the last valid ts as the for update read ts. + if b.ctx.GetSessionVars().StmtCtx.RCCheckTS { + rcReadTS := b.ctx.GetSessionVars().TxnCtx.LastRcReadTs + if rcReadTS == 0 { + rcReadTS = b.ctx.GetSessionVars().TxnCtx.StartTS + } + return UpdateForUpdateTS(b.ctx, rcReadTS) + } future := b.ctx.GetSessionVars().TxnCtx.GetStmtFutureForRC() if future == nil { return nil @@ -2215,8 +2312,56 @@ func (b *executorBuilder) buildAnalyzeIndexIncremental(task plannercore.AnalyzeI return analyzeTask } +func describeV2AnalyzeJobInfo(task plannercore.AnalyzeColumnsTask, autoAnalyze string, opts map[ast.AnalyzeOptionType]uint64, sampleRate float64) string { + var b strings.Builder + b.WriteString(autoAnalyze) + b.WriteString("analyze table") + cols := task.ColsInfo + if cols[len(cols)-1].ID == model.ExtraHandleID { + cols = cols[:len(cols)-1] + } + if len(cols) < len(task.TblInfo.Columns) { + b.WriteString(" columns ") + for i, col := range cols { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(col.Name.O) + } + } else { + b.WriteString(" all columns") + } + var needComma bool + b.WriteString(" with ") + printOption := func(optType ast.AnalyzeOptionType) { + if val, ok := opts[optType]; ok { + if needComma { + b.WriteString(", ") + } else { + needComma = true + } + b.WriteString(fmt.Sprintf("%v %s", val, strings.ToLower(ast.AnalyzeOptionString[optType]))) + } + } + printOption(ast.AnalyzeOptNumBuckets) + printOption(ast.AnalyzeOptNumTopN) + if opts[ast.AnalyzeOptNumSamples] != 0 { + printOption(ast.AnalyzeOptNumSamples) + } else { + if needComma { + b.WriteString(", ") + } else { + needComma = true + } + b.WriteString(fmt.Sprintf("%v samplerate", sampleRate)) + } + return b.String() +} + func (b *executorBuilder) buildAnalyzeSamplingPushdown(task plannercore.AnalyzeColumnsTask, opts map[ast.AnalyzeOptionType]uint64, autoAnalyze string, schemaForVirtualColEval *expression.Schema) *analyzeTask { - job := &statistics.AnalyzeJob{DBName: task.DBName, TableName: task.TableName, PartitionName: task.PartitionName, JobInfo: autoAnalyze + "analyze table"} + if task.V2Options != nil { + opts = task.V2Options.FilledOpts + } availableIdx := make([]*model.IndexInfo, 0, len(task.Indexes)) colGroups := make([]*tipb.AnalyzeColumnGroup, 0, len(task.Indexes)) if len(task.Indexes) > 0 { @@ -2254,6 +2399,35 @@ func (b *executorBuilder) buildAnalyzeSamplingPushdown(task plannercore.AnalyzeC failpoint.Inject("injectBaseModifyCount", func(val failpoint.Value) { modifyCount = int64(val.(int)) }) + sampleRate := new(float64) + if opts[ast.AnalyzeOptNumSamples] == 0 { + *sampleRate = math.Float64frombits(opts[ast.AnalyzeOptSampleRate]) + if *sampleRate < 0 { + *sampleRate = b.getAdjustedSampleRate(b.ctx, task) + if task.PartitionName != "" { + sc.AppendNote(errors.Errorf( + "Analyze use auto adjusted sample rate %f for table %s.%s's partition %s", + *sampleRate, + task.DBName, + task.TableName, + task.PartitionName, + )) + } else { + sc.AppendNote(errors.Errorf( + "Analyze use auto adjusted sample rate %f for table %s.%s", + *sampleRate, + task.DBName, + task.TableName, + )) + } + } + } + job := &statistics.AnalyzeJob{ + DBName: task.DBName, + TableName: task.TableName, + PartitionName: task.PartitionName, + JobInfo: describeV2AnalyzeJobInfo(task, autoAnalyze, opts, *sampleRate), + } base := baseAnalyzeExec{ ctx: b.ctx, tableID: task.TableID, @@ -2278,29 +2452,6 @@ func (b *executorBuilder) buildAnalyzeSamplingPushdown(task plannercore.AnalyzeC baseCount: count, baseModifyCnt: modifyCount, } - sampleRate := new(float64) - if opts[ast.AnalyzeOptNumSamples] == 0 { - *sampleRate = math.Float64frombits(opts[ast.AnalyzeOptSampleRate]) - if *sampleRate < 0 { - *sampleRate = b.getAdjustedSampleRate(b.ctx, task.TableID.GetStatisticsID(), task.TblInfo) - if task.PartitionName != "" { - sc.AppendNote(errors.Errorf( - "Analyze use auto adjusted sample rate %f for table %s.%s's partition %s.", - *sampleRate, - task.DBName, - task.TableName, - task.PartitionName, - )) - } else { - sc.AppendNote(errors.Errorf( - "Analyze use auto adjusted sample rate %f for table %s.%s.", - *sampleRate, - task.DBName, - task.TableName, - )) - } - } - } e.analyzePB.ColReq = &tipb.AnalyzeColumnsReq{ BucketSize: int64(opts[ast.AnalyzeOptNumBuckets]), SampleSize: int64(opts[ast.AnalyzeOptNumSamples]), @@ -2320,19 +2471,20 @@ func (b *executorBuilder) buildAnalyzeSamplingPushdown(task plannercore.AnalyzeC } // getAdjustedSampleRate calculate the sample rate by the table size. If we cannot get the table size. We use the 0.001 as the default sample rate. -func (b *executorBuilder) getAdjustedSampleRate(sctx sessionctx.Context, tid int64, tblInfo *model.TableInfo) float64 { +func (b *executorBuilder) getAdjustedSampleRate(sctx sessionctx.Context, task plannercore.AnalyzeColumnsTask) float64 { statsHandle := domain.GetDomain(sctx).StatsHandle() defaultRate := 0.001 if statsHandle == nil { return defaultRate } var statsTbl *statistics.Table - if tid == tblInfo.ID { - statsTbl = statsHandle.GetTableStats(tblInfo) + tid := task.TableID.GetStatisticsID() + if tid == task.TblInfo.ID { + statsTbl = statsHandle.GetTableStats(task.TblInfo) } else { - statsTbl = statsHandle.GetPartitionStats(tblInfo, tid) + statsTbl = statsHandle.GetPartitionStats(task.TblInfo, tid) } - approxiCount, hasPD := b.getApproximateTableCountFromPD(sctx, tid) + approxiCount, hasPD := b.getApproximateTableCountFromStorage(sctx, tid, task) // If there's no stats meta and no pd, return the default rate. if statsTbl == nil && !hasPD { return defaultRate @@ -2345,7 +2497,7 @@ func (b *executorBuilder) getAdjustedSampleRate(sctx sessionctx.Context, tid int // To do a workaround for this issue, we check the approxiCount from the pd side to do a comparison. // If the count from the stats_meta is extremely smaller than the approximate count from the pd, // we think that we meet this issue and use the approximate count to calculate the sample rate. - if float64(statsTbl.Count*100) < approxiCount { + if float64(statsTbl.Count*5) < approxiCount { // Confirmed by TiKV side, the experience error rate of the approximate count is about 20%. // So we increase the number to 150000 to reduce this error rate. return math.Min(1, 150000/approxiCount) @@ -2359,18 +2511,45 @@ func (b *executorBuilder) getAdjustedSampleRate(sctx sessionctx.Context, tid int return math.Min(1, 110000/float64(statsTbl.Count)) } -func (b *executorBuilder) getApproximateTableCountFromPD(sctx sessionctx.Context, tid int64) (float64, bool) { +func (b *executorBuilder) getApproximateTableCountFromStorage(sctx sessionctx.Context, tid int64, task plannercore.AnalyzeColumnsTask) (float64, bool) { tikvStore, ok := sctx.GetStore().(helper.Storage) if !ok { return 0, false } regionStats := &helper.PDRegionStats{} pdHelper := helper.NewHelper(tikvStore) - err := pdHelper.GetPDRegionStats(tid, regionStats) + err := pdHelper.GetPDRegionStats(tid, regionStats, true) + failpoint.Inject("calcSampleRateByStorageCount", func() { + // Force the TiDB thinking that there's PD and the count of region is small. + err = nil + regionStats.Count = 1 + // Set a very large approximate count. + regionStats.StorageKeys = 1000000 + }) + if err != nil { + return 0, false + } + // If this table is not small, we directly use the count from PD, + // since for a small table, it's possible that it's data is in the same region with part of another large table. + // Thus, we use the number of the regions of the table's table KV to decide whether the table is small. + if regionStats.Count > 2 { + return float64(regionStats.StorageKeys), true + } + // Otherwise, we use count(*) to calc it's size, since it's very small, the table data can be filled in no more than 2 regions. + sql := new(strings.Builder) + sqlexec.MustFormatSQL(sql, "select count(*) from %n.%n", task.DBName, task.TableName) + if task.PartitionName != "" { + sqlexec.MustFormatSQL(sql, " partition(%n)", task.PartitionName) + } + rows, _, err := b.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(context.TODO(), nil, sql.String()) if err != nil { return 0, false } - return float64(regionStats.StorageKeys), true + // If the record set is nil, there's something wrong with the execution. The COUNT(*) would always return one row. + if len(rows) == 0 || rows[0].Len() == 0 { + return 0, false + } + return float64(rows[0].GetInt64(0)), true } func (b *executorBuilder) buildAnalyzeColumnsPushdown(task plannercore.AnalyzeColumnsTask, opts map[ast.AnalyzeOptionType]uint64, autoAnalyze string, schemaForVirtualColEval *expression.Schema) *analyzeTask { @@ -2598,8 +2777,8 @@ func (b *executorBuilder) buildAnalyze(v *plannercore.Analyze) Executor { e := &AnalyzeExec{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), tasks: make([]*analyzeTask, 0, len(v.ColTasks)+len(v.IdxTasks)), - wg: &sync.WaitGroup{}, opts: v.Opts, + OptionsMap: v.OptionsMap, } enableFastAnalyze := b.ctx.GetSessionVars().EnableFastAnalyze autoAnalyze := "" @@ -2728,6 +2907,22 @@ func (b *executorBuilder) corColInAccess(p plannercore.PhysicalPlan) bool { return false } +func (b *executorBuilder) newDataReaderBuilder(p plannercore.PhysicalPlan) (*dataReaderBuilder, error) { + ts, err := b.getSnapshotTS() + if err != nil { + return nil, err + } + + builderForDataReader := *b + builderForDataReader.forDataReaderBuilder = true + builderForDataReader.dataReaderTS = ts + + return &dataReaderBuilder{ + Plan: p, + executorBuilder: &builderForDataReader, + }, nil +} + func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) Executor { outerExec := b.build(v.Children()[1-v.InnerChildIdx]) if b.err != nil { @@ -2799,6 +2994,13 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) break } } + + readerBuilder, err := b.newDataReaderBuilder(innerPlan) + if err != nil { + b.err = err + return nil + } + e := &IndexLookUpJoin{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID(), outerExec), outerCtx: outerCtx{ @@ -2807,7 +3009,7 @@ func (b *executorBuilder) buildIndexLookUpJoin(v *plannercore.PhysicalIndexJoin) filter: outerFilter, }, innerCtx: innerCtx{ - readerBuilder: &dataReaderBuilder{Plan: innerPlan, executorBuilder: b}, + readerBuilder: readerBuilder, rowTypes: innerTypes, hashTypes: innerHashTypes, colLens: v.IdxColLens, @@ -2909,6 +3111,12 @@ func (b *executorBuilder) buildIndexLookUpMergeJoin(v *plannercore.PhysicalIndex } executorCounterIndexLookUpJoin.Inc() + readerBuilder, err := b.newDataReaderBuilder(innerPlan) + if err != nil { + b.err = err + return nil + } + e := &IndexLookUpMergeJoin{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID(), outerExec), outerMergeCtx: outerMergeCtx{ @@ -2920,7 +3128,7 @@ func (b *executorBuilder) buildIndexLookUpMergeJoin(v *plannercore.PhysicalIndex compareFuncs: v.OuterCompareFuncs, }, innerMergeCtx: innerMergeCtx{ - readerBuilder: &dataReaderBuilder{Plan: innerPlan, executorBuilder: b}, + readerBuilder: readerBuilder, rowTypes: innerTypes, joinKeys: v.InnerJoinKeys, keyCols: innerKeyCols, @@ -2979,7 +3187,10 @@ func buildNoRangeTableReader(b *executorBuilder, v *plannercore.PhysicalTableRea if err != nil { return nil, err } - ts := v.GetTableScan() + ts, err := v.GetTableScan() + if err != nil { + return nil, err + } if err = b.validCanReadTemporaryOrCacheTable(ts.Table); err != nil { return nil, err } @@ -3010,10 +3221,7 @@ func buildNoRangeTableReader(b *executorBuilder, v *plannercore.PhysicalTableRea plans: v.TablePlans, tablePlan: v.GetTablePlan(), storeType: v.StoreType, - batchCop: v.BatchCop, - } - if tbl.Meta().Partition != nil { - e.extraPIDColumnIndex = extraPIDColumnIndex(v.Schema()) + batchCop: v.ReadReqType == plannercore.BatchCop, } e.buildVirtualColumnInfo() if containsLimit(dagReq.Executors) { @@ -3045,15 +3253,6 @@ func buildNoRangeTableReader(b *executorBuilder, v *plannercore.PhysicalTableRea return e, nil } -func extraPIDColumnIndex(schema *expression.Schema) offsetOptional { - for idx, col := range schema.Columns { - if col.ID == model.ExtraPidColID { - return newOffset(idx) - } - } - return 0 -} - func (b *executorBuilder) buildMPPGather(v *plannercore.PhysicalTableReader) Executor { startTs, err := b.getSnapshotTS() if err != nil { @@ -3089,18 +3288,25 @@ func (b *executorBuilder) buildTableReader(v *plannercore.PhysicalTableReader) E if useMPPExecution(b.ctx, v) { return b.buildMPPGather(v) } + ts, err := v.GetTableScan() + if err != nil { + b.err = err + return nil + } ret, err := buildNoRangeTableReader(b, v) if err != nil { b.err = err return nil } - - ts := v.GetTableScan() if err = b.validCanReadTemporaryOrCacheTable(ts.Table); err != nil { b.err = err return nil } + if ret.table.Meta().TempTableType != model.TempTableNone { + ret.dummy = true + } + ret.ranges = ts.Ranges sctx := b.ctx.GetSessionVars().StmtCtx sctx.TableIDs = append(sctx.TableIDs, ts.Table.ID) @@ -3328,6 +3534,10 @@ func (b *executorBuilder) buildIndexReader(v *plannercore.PhysicalIndexReader) E return nil } + if ret.table.Meta().TempTableType != model.TempTableNone { + ret.dummy = true + } + ret.ranges = is.Ranges sctx := b.ctx.GetSessionVars().StmtCtx sctx.IndexNames = append(sctx.IndexNames, is.Table.Name.O+":"+is.Index.Name.O) @@ -3378,8 +3588,8 @@ func buildTableReq(b *executorBuilder, schemaLen int, plans []plannercore.Physic return tableReq, tableStreaming, tbl, err } -func buildIndexReq(b *executorBuilder, schemaLen, handleLen int, plans []plannercore.PhysicalPlan) (dagReq *tipb.DAGRequest, streaming bool, err error) { - indexReq, indexStreaming, err := constructDAGReq(b.ctx, plans, kv.TiKV) +func buildIndexReq(ctx sessionctx.Context, schemaLen, handleLen int, plans []plannercore.PhysicalPlan) (dagReq *tipb.DAGRequest, streaming bool, err error) { + indexReq, indexStreaming, err := constructDAGReq(ctx, plans, kv.TiKV) if err != nil { return nil, false, err } @@ -3405,10 +3615,15 @@ func buildNoRangeIndexLookUpReader(b *executorBuilder, v *plannercore.PhysicalIn // Should output pid col. handleLen++ } - indexReq, indexStreaming, err := buildIndexReq(b, len(is.Index.Columns), handleLen, v.IndexPlans) + indexReq, indexStreaming, err := buildIndexReq(b.ctx, len(is.Index.Columns), handleLen, v.IndexPlans) if err != nil { return nil, err } + indexPaging := false + if v.Paging { + indexPaging = true + indexStreaming = false + } tableReq, tableStreaming, tbl, err := buildTableReq(b, v.Schema().Len(), v.TablePlans) if err != nil { return nil, err @@ -3418,6 +3633,12 @@ func buildNoRangeIndexLookUpReader(b *executorBuilder, v *plannercore.PhysicalIn if err != nil { return nil, err } + + readerBuilder, err := b.newDataReaderBuilder(nil) + if err != nil { + return nil, err + } + e := &IndexLookUpExecutor{ baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), dagPB: indexReq, @@ -3430,7 +3651,8 @@ func buildNoRangeIndexLookUpReader(b *executorBuilder, v *plannercore.PhysicalIn columns: ts.Columns, indexStreaming: indexStreaming, tableStreaming: tableStreaming, - dataReaderBuilder: &dataReaderBuilder{executorBuilder: b}, + indexPaging: indexPaging, + dataReaderBuilder: readerBuilder, corColInIdxSide: b.corColInDistPlan(v.IndexPlans), corColInTblSide: b.corColInDistPlan(v.TablePlans), corColInAccess: b.corColInAccess(v.IndexPlans[0]), @@ -3440,9 +3662,6 @@ func buildNoRangeIndexLookUpReader(b *executorBuilder, v *plannercore.PhysicalIn tblPlans: v.TablePlans, PushedLimit: v.PushedLimit, } - if ok, _ := ts.IsPartition(); ok { - e.extraPIDColumnIndex = extraPIDColumnIndex(v.Schema()) - } if containsLimit(indexReq.Executors) { e.feedback = statistics.NewQueryFeedback(0, nil, 0, is.Desc) @@ -3487,6 +3706,10 @@ func (b *executorBuilder) buildIndexLookUpReader(v *plannercore.PhysicalIndexLoo return nil } + if ret.table.Meta().TempTableType != model.TempTableNone { + ret.dummy = true + } + ts := v.TablePlans[0].(*plannercore.PhysicalTableScan) ret.ranges = is.Ranges @@ -3532,6 +3755,8 @@ func buildNoRangeIndexMergeReader(b *executorBuilder, v *plannercore.PhysicalInd descs := make([]bool, 0, partialPlanCount) feedbacks := make([]*statistics.QueryFeedback, 0, partialPlanCount) ts := v.TablePlans[0].(*plannercore.PhysicalTableScan) + isCorColInPartialFilters := make([]bool, 0, partialPlanCount) + isCorColInPartialAccess := make([]bool, 0, partialPlanCount) for i := 0; i < partialPlanCount; i++ { var tempReq *tipb.DAGRequest var tempStreaming bool @@ -3542,7 +3767,7 @@ func buildNoRangeIndexMergeReader(b *executorBuilder, v *plannercore.PhysicalInd feedbacks = append(feedbacks, feedback) if is, ok := v.PartialPlans[i][0].(*plannercore.PhysicalIndexScan); ok { - tempReq, tempStreaming, err = buildIndexReq(b, len(is.Index.Columns), ts.HandleCols.NumCols(), v.PartialPlans[i]) + tempReq, tempStreaming, err = buildIndexReq(b.ctx, len(is.Index.Columns), ts.HandleCols.NumCols(), v.PartialPlans[i]) descs = append(descs, is.Desc) indexes = append(indexes, is.Index) } else { @@ -3558,8 +3783,11 @@ func buildNoRangeIndexMergeReader(b *executorBuilder, v *plannercore.PhysicalInd tempReq.CollectRangeCounts = &collect partialReqs = append(partialReqs, tempReq) partialStreamings = append(partialStreamings, tempStreaming) + isCorColInPartialFilters = append(isCorColInPartialFilters, b.corColInDistPlan(v.PartialPlans[i])) + isCorColInPartialAccess = append(isCorColInPartialAccess, b.corColInAccess(v.PartialPlans[i][0])) } tableReq, tableStreaming, tblInfo, err := buildTableReq(b, v.Schema().Len(), v.TablePlans) + isCorColInTableFilter := b.corColInDistPlan(v.TablePlans) if err != nil { return nil, err } @@ -3567,22 +3795,31 @@ func buildNoRangeIndexMergeReader(b *executorBuilder, v *plannercore.PhysicalInd if err != nil { return nil, err } + + readerBuilder, err := b.newDataReaderBuilder(nil) + if err != nil { + return nil, err + } + e := &IndexMergeReaderExecutor{ - baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), - dagPBs: partialReqs, - startTS: startTS, - table: tblInfo, - indexes: indexes, - descs: descs, - tableRequest: tableReq, - columns: ts.Columns, - partialStreamings: partialStreamings, - tableStreaming: tableStreaming, - partialPlans: v.PartialPlans, - tblPlans: v.TablePlans, - dataReaderBuilder: &dataReaderBuilder{executorBuilder: b}, - feedbacks: feedbacks, - handleCols: ts.HandleCols, + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()), + dagPBs: partialReqs, + startTS: startTS, + table: tblInfo, + indexes: indexes, + descs: descs, + tableRequest: tableReq, + columns: ts.Columns, + partialStreamings: partialStreamings, + tableStreaming: tableStreaming, + partialPlans: v.PartialPlans, + tblPlans: v.TablePlans, + dataReaderBuilder: readerBuilder, + feedbacks: feedbacks, + handleCols: ts.HandleCols, + isCorColInPartialFilters: isCorColInPartialFilters, + isCorColInTableFilter: isCorColInTableFilter, + isCorColInPartialAccess: isCorColInPartialAccess, } collectTable := false e.tableRequest.CollectRangeCounts = &collectTable @@ -3700,7 +3937,11 @@ func (builder *dataReaderBuilder) buildExecutorForIndexJoinInternal(ctx context. func (builder *dataReaderBuilder) buildUnionScanForIndexJoin(ctx context.Context, v *plannercore.PhysicalUnionScan, values []*indexJoinLookUpContent, indexRanges []*ranger.Range, keyOff2IdxOff []int, cwc *plannercore.ColWithCmpFuncManager, canReorderHandles bool, memTracker *memory.Tracker, interruptSignal *atomic.Value) (Executor, error) { - childBuilder := &dataReaderBuilder{Plan: v.Children()[0], executorBuilder: builder.executorBuilder} + childBuilder, err := builder.newDataReaderBuilder(v.Children()[0]) + if err != nil { + return nil, err + } + reader, err := childBuilder.buildExecutorForIndexJoin(ctx, values, indexRanges, keyOff2IdxOff, cwc, canReorderHandles, memTracker, interruptSignal) if err != nil { return nil, err @@ -3721,28 +3962,41 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte return nil, err } tbInfo := e.table.Meta() - if v.IsCommonHandle { - if tbInfo.GetPartitionInfo() == nil || !builder.ctx.GetSessionVars().UseDynamicPartitionPrune() { + if tbInfo.GetPartitionInfo() == nil || !builder.ctx.GetSessionVars().UseDynamicPartitionPrune() { + if v.IsCommonHandle { kvRanges, err := buildKvRangesForIndexJoin(e.ctx, getPhysicalTableID(e.table), -1, lookUpContents, indexRanges, keyOff2IdxOff, cwc, memTracker, interruptSignal) if err != nil { return nil, err } return builder.buildTableReaderFromKvRanges(ctx, e, kvRanges) } - - tbl, _ := builder.is.TableByID(tbInfo.ID) - pt := tbl.(table.PartitionedTable) - pe, err := tbl.(interface { - PartitionExpr() (*tables.PartitionExpr, error) - }).PartitionExpr() - if err != nil { - return nil, err - } - var kvRanges []kv.KeyRange + handles, _ := dedupHandles(lookUpContents) + return builder.buildTableReaderFromHandles(ctx, e, handles, canReorderHandles) + } + tbl, _ := builder.is.TableByID(tbInfo.ID) + pt := tbl.(table.PartitionedTable) + pe, err := tbl.(interface { + PartitionExpr() (*tables.PartitionExpr, error) + }).PartitionExpr() + if err != nil { + return nil, err + } + partitionInfo := &v.PartitionInfo + usedPartitionList, err := partitionPruning(e.ctx, pt, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) + if err != nil { + return nil, err + } + usedPartitions := make(map[int64]table.PhysicalTable, len(usedPartitionList)) + for _, p := range usedPartitionList { + usedPartitions[p.GetPhysicalID()] = p + } + var kvRanges []kv.KeyRange + if v.IsCommonHandle { if len(lookUpContents) > 0 && keyColumnsIncludeAllPartitionColumns(lookUpContents[0].keyCols, pe) { - // In this case we can use dynamic partition pruning. locateKey := make([]types.Datum, e.Schema().Len()) kvRanges = make([]kv.KeyRange, 0, len(lookUpContents)) + // lookUpContentsByPID groups lookUpContents by pid(partition) so that kv ranges for same partition can be merged. + lookUpContentsByPID := make(map[int64][]*indexJoinLookUpContent) for _, content := range lookUpContents { for i, date := range content.keys { locateKey[content.keyCols[i]] = date @@ -3752,22 +4006,23 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte return nil, err } pid := p.GetPhysicalID() - tmp, err := buildKvRangesForIndexJoin(e.ctx, pid, -1, []*indexJoinLookUpContent{content}, indexRanges, keyOff2IdxOff, cwc, nil, interruptSignal) + if _, ok := usedPartitions[pid]; !ok { + continue + } + lookUpContentsByPID[pid] = append(lookUpContentsByPID[pid], content) + } + for pid, contents := range lookUpContentsByPID { + // buildKvRanges for each partition. + tmp, err := buildKvRangesForIndexJoin(e.ctx, pid, -1, contents, indexRanges, keyOff2IdxOff, cwc, nil, interruptSignal) if err != nil { return nil, err } kvRanges = append(kvRanges, tmp...) } } else { - partitionInfo := &v.PartitionInfo - partitions, err := partitionPruning(e.ctx, pt, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) - if err != nil { - return nil, err - } - kvRanges = make([]kv.KeyRange, 0, len(partitions)*len(lookUpContents)) - for _, p := range partitions { - pid := p.GetPhysicalID() - tmp, err := buildKvRangesForIndexJoin(e.ctx, pid, -1, lookUpContents, indexRanges, keyOff2IdxOff, cwc, memTracker, interruptSignal) + kvRanges = make([]kv.KeyRange, 0, len(usedPartitions)*len(lookUpContents)) + for _, p := range usedPartitionList { + tmp, err := buildKvRangesForIndexJoin(e.ctx, p.GetPhysicalID(), -1, lookUpContents, indexRanges, keyOff2IdxOff, cwc, memTracker, interruptSignal) if err != nil { return nil, err } @@ -3778,22 +4033,7 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte } handles, lookUpContents := dedupHandles(lookUpContents) - if tbInfo.GetPartitionInfo() == nil { - return builder.buildTableReaderFromHandles(ctx, e, handles, canReorderHandles) - } - if !builder.ctx.GetSessionVars().UseDynamicPartitionPrune() { - return builder.buildTableReaderFromHandles(ctx, e, handles, canReorderHandles) - } - tbl, _ := builder.is.TableByID(tbInfo.ID) - pt := tbl.(table.PartitionedTable) - pe, err := tbl.(interface { - PartitionExpr() (*tables.PartitionExpr, error) - }).PartitionExpr() - if err != nil { - return nil, err - } - var kvRanges []kv.KeyRange if len(lookUpContents) > 0 && keyColumnsIncludeAllPartitionColumns(lookUpContents[0].keyCols, pe) { locateKey := make([]types.Datum, e.Schema().Len()) kvRanges = make([]kv.KeyRange, 0, len(lookUpContents)) @@ -3806,19 +4046,16 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte return nil, err } pid := p.GetPhysicalID() + if _, ok := usedPartitions[pid]; !ok { + continue + } handle := kv.IntHandle(content.keys[0].GetInt64()) tmp := distsql.TableHandlesToKVRanges(pid, []kv.Handle{handle}) kvRanges = append(kvRanges, tmp...) } } else { - partitionInfo := &v.PartitionInfo - partitions, err := partitionPruning(e.ctx, pt, partitionInfo.PruningConds, partitionInfo.PartitionNames, partitionInfo.Columns, partitionInfo.ColumnNames) - if err != nil { - return nil, err - } - for _, p := range partitions { - pid := p.GetPhysicalID() - tmp := distsql.TableHandlesToKVRanges(pid, handles) + for _, p := range usedPartitionList { + tmp := distsql.TableHandlesToKVRanges(p.GetPhysicalID(), handles) kvRanges = append(kvRanges, tmp...) } } @@ -3851,8 +4088,8 @@ type kvRangeBuilderFromRangeAndPartition struct { } func (h kvRangeBuilderFromRangeAndPartition) buildKeyRangeSeparately(ranges []*ranger.Range) ([]int64, [][]kv.KeyRange, error) { - var ret [][]kv.KeyRange - var pids []int64 + ret := make([][]kv.KeyRange, 0, len(h.partitions)) + pids := make([]int64, 0, len(h.partitions)) for _, p := range h.partitions { pid := p.GetPhysicalID() meta := p.Meta() @@ -3866,7 +4103,7 @@ func (h kvRangeBuilderFromRangeAndPartition) buildKeyRangeSeparately(ranges []*r return pids, ret, nil } -func (h kvRangeBuilderFromRangeAndPartition) buildKeyRange(_ int64, ranges []*ranger.Range) ([]kv.KeyRange, error) { +func (h kvRangeBuilderFromRangeAndPartition) buildKeyRange(ranges []*ranger.Range) ([]kv.KeyRange, error) { var ret []kv.KeyRange for _, p := range h.partitions { pid := p.GetPhysicalID() @@ -4353,6 +4590,7 @@ func (b *executorBuilder) buildSQLBindExec(v *plannercore.SQLBindPlan) Executor db: v.Db, isGlobal: v.IsGlobal, bindAst: v.BindStmt, + newStatus: v.NewStatus, } return e } @@ -4603,19 +4841,9 @@ func (b *executorBuilder) buildCTE(v *plannercore.PhysicalCTE) Executor { // 2. Build tables to store intermediate results. chkSize := b.ctx.GetSessionVars().MaxChunkSize tps := seedExec.base().retFieldTypes + // iterOutTbl will be constructed in CTEExec.Open(). var resTbl cteutil.Storage var iterInTbl cteutil.Storage - var iterOutTbl cteutil.Storage - - if v.RecurPlan != nil { - // For non-recursive CTE, the result will be put into resTbl directly. - // So no need to build iterOutTbl. - iterOutTbl := cteutil.NewStorageRowContainer(tps, chkSize) - if err := iterOutTbl.OpenAndRef(); err != nil { - b.err = err - return nil - } - } storageMap, ok := b.ctx.GetSessionVars().StmtCtx.CTEStorageMap.(map[int]*CTEStorages) if !ok { @@ -4664,13 +4892,13 @@ func (b *executorBuilder) buildCTE(v *plannercore.PhysicalCTE) Executor { recursiveExec: recursiveExec, resTbl: resTbl, iterInTbl: iterInTbl, - iterOutTbl: iterOutTbl, chkIdx: 0, isDistinct: v.CTE.IsDistinct, sel: sel, hasLimit: v.CTE.HasLimit, limitBeg: v.CTE.LimitBeg, limitEnd: v.CTE.LimitEnd, + isInApply: v.CTE.IsInApply, } } @@ -4741,25 +4969,18 @@ func (b *executorBuilder) getCacheTable(tblInfo *model.TableInfo, startTS uint64 b.err = errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(b.ctx.GetSessionVars().CurrentDB, tblInfo.Name)) return nil } - cacheData := tbl.(table.CachedTable).TryReadFromCache(startTS) + sessVars := b.ctx.GetSessionVars() + leaseDuration := time.Duration(variable.TableCacheLease.Load()) * time.Second + cacheData, loading := tbl.(table.CachedTable).TryReadFromCache(startTS, leaseDuration) if cacheData != nil { - b.ctx.GetSessionVars().StmtCtx.ReadFromTableCache = true + sessVars.StmtCtx.ReadFromTableCache = true return cacheData - } - if !b.ctx.GetSessionVars().StmtCtx.InExplainStmt && !b.inDeleteStmt && !b.inUpdateStmt { - go func() { - defer func() { - if r := recover(); r != nil { - logutil.BgLogger().Error("panic in the recoverable goroutine", - zap.Reflect("r", r), - zap.Stack("stack trace")) - } - }() - err := tbl.(table.CachedTable).UpdateLockForRead(context.Background(), b.ctx.GetStore(), startTS) - if err != nil { - log.Warn("Update Lock Info Error") - } - }() + } else if loading { + // continue + } else { + if !b.ctx.GetSessionVars().StmtCtx.InExplainStmt && !b.inDeleteStmt && !b.inUpdateStmt { + tbl.(table.CachedTable).UpdateLockForRead(context.Background(), b.ctx.GetStore(), startTS, leaseDuration) + } } return nil } diff --git a/executor/change.go b/executor/change.go index 7233863501660..a261cbf9c14c9 100644 --- a/executor/change.go +++ b/executor/change.go @@ -19,9 +19,9 @@ import ( "strings" "github.com/pingcap/errors" - "github.com/pingcap/tidb-tools/tidb-binlog/node" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/tidb-binlog/node" "github.com/pingcap/tidb/util/chunk" ) diff --git a/executor/checksum.go b/executor/checksum.go index 69fd6ed319e75..013fd3be2226f 100644 --- a/executor/checksum.go +++ b/executor/checksum.go @@ -128,7 +128,7 @@ func (e *ChecksumTableExec) checksumWorker(taskCh <-chan *checksumTask, resultCh } func (e *ChecksumTableExec) handleChecksumRequest(req *kv.Request) (resp *tipb.ChecksumResponse, err error) { - ctx := context.TODO() + ctx := distsql.WithSQLKvExecCounterInterceptor(context.TODO(), e.ctx.GetSessionVars().StmtCtx) res, err := distsql.Checksum(ctx, e.ctx.GetClient(), req, e.ctx.GetSessionVars().KVVars) if err != nil { return nil, err diff --git a/executor/chunk_size_control_test.go b/executor/chunk_size_control_test.go index 310e5092695bd..bae8614e5ab3d 100644 --- a/executor/chunk_size_control_test.go +++ b/executor/chunk_size_control_test.go @@ -19,33 +19,32 @@ import ( "fmt" "strings" "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/tikvrpc" ) -var ( - _ = Suite(&testChunkSizeControlSuite{}) -) - +// nolint: unused, deadcode type testSlowClient struct { sync.RWMutex tikv.Client regionDelay map[uint64]time.Duration } +// nolint: unused, deadcode func (c *testSlowClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { regionID := req.RegionId delay := c.GetDelay(regionID) @@ -55,12 +54,14 @@ func (c *testSlowClient) SendRequest(ctx context.Context, addr string, req *tikv return c.Client.SendRequest(ctx, addr, req, timeout) } +// nolint: unused, deadcode func (c *testSlowClient) SetDelay(regionID uint64, dur time.Duration) { c.Lock() defer c.Unlock() c.regionDelay[regionID] = dur } +// nolint: unused, deadcode func (c *testSlowClient) GetDelay(regionID uint64) time.Duration { c.RLock() defer c.RUnlock() @@ -72,9 +73,9 @@ func manipulateCluster(cluster testutils.Cluster, splitKeys [][]byte) []uint64 { if len(splitKeys) == 0 { return nil } - region, _ := cluster.GetRegionByKey(splitKeys[0]) + region, _, _ := cluster.GetRegionByKey(splitKeys[0]) for _, key := range splitKeys { - if r, _ := cluster.GetRegionByKey(key); r.Id != region.Id { + if r, _, _ := cluster.GetRegionByKey(key); r.Id != region.Id { panic("all split keys should belong to the same region") } } @@ -95,146 +96,138 @@ func generateTableSplitKeyForInt(tid int64, splitNum []int) [][]byte { return results } -func generateIndexSplitKeyForInt(tid, idx int64, splitNum []int) [][]byte { - results := make([][]byte, 0, len(splitNum)) - for _, num := range splitNum { - d := new(types.Datum) - d.SetInt64(int64(num)) - b, err := codec.EncodeKey(nil, nil, *d) - if err != nil { - panic(err) - } - results = append(results, tablecodec.EncodeIndexSeekKey(tid, idx, b)) - } - return results -} - -type testChunkSizeControlKit struct { - store kv.Storage - dom *domain.Domain - tk *testkit.TestKit - client *testSlowClient - cluster testutils.Cluster -} - -type testChunkSizeControlSuite struct { - m map[string]*testChunkSizeControlKit -} - -func (s *testChunkSizeControlSuite) SetUpSuite(c *C) { - c.Skip("not stable because coprocessor may result in goroutine leak") - tableSQLs := map[string]string{} - tableSQLs["Limit&TableScan"] = "create table t (a int, primary key (a))" - tableSQLs["Limit&IndexScan"] = "create table t (a int, index idx_a(a))" - - s.m = make(map[string]*testChunkSizeControlKit) - for name, sql := range tableSQLs { - // BootstrapSession is not thread-safe, so we have to prepare all resources in SetUp. - kit := new(testChunkSizeControlKit) - s.m[name] = kit - kit.client = &testSlowClient{regionDelay: make(map[uint64]time.Duration)} - - var err error - kit.store, err = mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - kit.cluster = c - }), - mockstore.WithClientHijacker(func(c tikv.Client) tikv.Client { - kit.client.Client = c - return kit.client - }), - ) - c.Assert(err, IsNil) - - // init domain - kit.dom, err = session.BootstrapSession(kit.store) - c.Assert(err, IsNil) - - // create the test table - kit.tk = testkit.NewTestKitWithInit(c, kit.store) - kit.tk.MustExec(sql) - } -} - -func (s *testChunkSizeControlSuite) getKit(name string) ( - kv.Storage, *domain.Domain, *testkit.TestKit, *testSlowClient, testutils.Cluster) { - x := s.m[name] - return x.store, x.dom, x.tk, x.client, x.cluster -} - -func (s *testChunkSizeControlSuite) TestLimitAndTableScan(c *C) { - _, dom, tk, client, cluster := s.getKit("Limit&TableScan") - defer client.Close() - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) +func TestLimitAndTableScan(t *testing.T) { + t.Skip("not stable because coprocessor may result in goroutine leak") + kit, clean := createChunkSizeControlKit(t, "create table t (a int, primary key (a))") + defer clean() + tbl, err := kit.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tid := tbl.Meta().ID // construct two regions split by 100 splitKeys := generateTableSplitKeyForInt(tid, []int{100}) - regionIDs := manipulateCluster(cluster, splitKeys) + regionIDs := manipulateCluster(kit.cluster, splitKeys) noDelayThreshold := time.Millisecond * 100 delayDuration := time.Second delayThreshold := delayDuration * 9 / 10 - tk.MustExec("insert into t values (1)") // insert one record into region1, and set a delay duration - client.SetDelay(regionIDs[0], delayDuration) + kit.tk.MustExec("insert into t values (1)") // insert one record into region1, and set a delay duration + kit.client.SetDelay(regionIDs[0], delayDuration) - results := tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") - cost := s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Not(Less), delayThreshold) // have to wait for region1 + results := kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") + cost := parseTimeCost(t, results.Rows()[0]) + require.GreaterOrEqual(t, cost, delayThreshold) // have to wait for region1 - tk.MustExec("insert into t values (101)") // insert one record into region2 - results = tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") - cost = s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Less, noDelayThreshold) // region2 return quickly + kit.tk.MustExec("insert into t values (101)") // insert one record into region2 + results = kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") + cost = parseTimeCost(t, results.Rows()[0]) + require.Less(t, cost, noDelayThreshold) // region2 return quickly - results = tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 2") - cost = s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Not(Less), delayThreshold) // have to wait + results = kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 2") + cost = parseTimeCost(t, results.Rows()[0]) + require.GreaterOrEqual(t, cost, delayThreshold) // have to wait } -func (s *testChunkSizeControlSuite) TestLimitAndIndexScan(c *C) { - _, dom, tk, client, cluster := s.getKit("Limit&IndexScan") - defer client.Close() - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) +func TestLimitAndIndexScan(t *testing.T) { + t.Skip("not stable because coprocessor may result in goroutine leak") + kit, clean := createChunkSizeControlKit(t, "create table t (a int, index idx_a(a))") + defer clean() + tbl, err := kit.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tid := tbl.Meta().ID idx := tbl.Meta().Indices[0].ID // construct two regions split by 100 splitKeys := generateIndexSplitKeyForInt(tid, idx, []int{100}) - regionIDs := manipulateCluster(cluster, splitKeys) + regionIDs := manipulateCluster(kit.cluster, splitKeys) noDelayThreshold := time.Millisecond * 100 delayDuration := time.Second delayThreshold := delayDuration * 9 / 10 - tk.MustExec("insert into t values (1)") // insert one record into region1, and set a delay duration - client.SetDelay(regionIDs[0], delayDuration) + kit.tk.MustExec("insert into t values (1)") // insert one record into region1, and set a delay duration + kit.client.SetDelay(regionIDs[0], delayDuration) - results := tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") - cost := s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Not(Less), delayThreshold) // have to wait for region1 + results := kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") + cost := parseTimeCost(t, results.Rows()[0]) + require.GreaterOrEqual(t, cost, delayThreshold) // have to wait for region1 - tk.MustExec("insert into t values (101)") // insert one record into region2 - results = tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") - cost = s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Less, noDelayThreshold) // region2 return quickly + kit.tk.MustExec("insert into t values (101)") // insert one record into region2 + results = kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 1") + cost = parseTimeCost(t, results.Rows()[0]) + require.Less(t, cost, noDelayThreshold) // region2 return quickly - results = tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 2") - cost = s.parseTimeCost(c, results.Rows()[0]) - c.Assert(cost, Not(Less), delayThreshold) // have to wait + results = kit.tk.MustQuery("explain analyze select * from t where t.a > 0 and t.a < 200 limit 2") + cost = parseTimeCost(t, results.Rows()[0]) + require.GreaterOrEqual(t, cost, delayThreshold) // have to wait } -func (s *testChunkSizeControlSuite) parseTimeCost(c *C, line []interface{}) time.Duration { +// nolint: unused, deadcode +func parseTimeCost(t *testing.T, line []interface{}) time.Duration { lineStr := fmt.Sprintf("%v", line) idx := strings.Index(lineStr, "time:") - c.Assert(idx, Not(Equals), -1) + require.NotEqual(t, -1, idx) lineStr = lineStr[idx+len("time:"):] idx = strings.Index(lineStr, ",") - c.Assert(idx, Not(Equals), -1) + require.NotEqual(t, -1, idx) timeStr := lineStr[:idx] d, err := time.ParseDuration(timeStr) - c.Assert(err, IsNil) + require.NoError(t, err) return d } + +// nolint: unused, deadcode +func generateIndexSplitKeyForInt(tid, idx int64, splitNum []int) [][]byte { + results := make([][]byte, 0, len(splitNum)) + for _, num := range splitNum { + d := new(types.Datum) + d.SetInt64(int64(num)) + b, err := codec.EncodeKey(nil, nil, *d) + if err != nil { + panic(err) + } + results = append(results, tablecodec.EncodeIndexSeekKey(tid, idx, b)) + } + return results +} + +// nolint: unused, deadcode +type chunkSizeControlKit struct { + store kv.Storage + dom *domain.Domain + tk *testkit.TestKit + client *testSlowClient + cluster testutils.Cluster +} + +// nolint: unused, deadcode +func createChunkSizeControlKit(t *testing.T, sql string) (*chunkSizeControlKit, func()) { + // BootstrapSession is not thread-safe, so we have to prepare all resources in SetUp. + kit := new(chunkSizeControlKit) + kit.client = &testSlowClient{regionDelay: make(map[uint64]time.Duration)} + + var err error + kit.store, err = mockstore.NewMockStore( + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + kit.cluster = c + }), + mockstore.WithClientHijacker(func(c tikv.Client) tikv.Client { + kit.client.Client = c + return kit.client + }), + ) + require.NoError(t, err) + + // init domain + kit.dom, err = session.BootstrapSession(kit.store) + require.NoError(t, err) + + // create the test table + kit.tk = testkit.NewTestKit(t, kit.store) + kit.tk.MustExec("use test") + kit.tk.MustExec(sql) + return kit, func() { + kit.dom.Close() + require.NoError(t, kit.store.Close()) + } +} diff --git a/executor/collation_test.go b/executor/collation_test.go index 83d0b7251d6bd..d4b957ee413d6 100644 --- a/executor/collation_test.go +++ b/executor/collation_test.go @@ -21,15 +21,11 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) func TestVecGroupChecker(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tp := &types.FieldType{Tp: mysql.TypeVarchar} col0 := &expression.Column{ RetType: tp, diff --git a/executor/compiler.go b/executor/compiler.go index 74a878b4d3293..37bc939eb57c1 100644 --- a/executor/compiler.go +++ b/executor/compiler.go @@ -27,6 +27,7 @@ import ( "github.com/pingcap/tidb/planner" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessiontxn" ) var ( @@ -57,12 +58,23 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (*ExecStm ret := &plannercore.PreprocessorReturn{} pe := &plannercore.PreprocessExecuteISUpdate{ExecuteInfoSchemaUpdate: planner.GetExecuteForUpdateReadIS, Node: stmtNode} - err := plannercore.Preprocess(c.Ctx, stmtNode, plannercore.WithPreprocessorReturn(ret), plannercore.WithExecuteInfoSchemaUpdate(pe)) + err := plannercore.Preprocess(c.Ctx, + stmtNode, + plannercore.WithPreprocessorReturn(ret), + plannercore.WithExecuteInfoSchemaUpdate(pe), + plannercore.InitTxnContextProvider, + ) if err != nil { return nil, err } - finalPlan, names, err := planner.Optimize(ctx, c.Ctx, stmtNode, ret.InfoSchema) + failpoint.Inject("assertTxnManagerInCompile", func() { + sessiontxn.RecordAssert(c.Ctx, "assertTxnManagerInCompile", true) + sessiontxn.AssertTxnManagerInfoSchema(c.Ctx, ret.InfoSchema) + }) + + is := sessiontxn.GetTxnManager(c.Ctx).GetTxnInfoSchema() + finalPlan, names, err := planner.Optimize(ctx, c.Ctx, stmtNode, is) if err != nil { return nil, err } @@ -85,7 +97,7 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (*ExecStm SnapshotTS: ret.LastSnapshotTS, IsStaleness: ret.IsStaleness, ReplicaReadScope: ret.ReadReplicaScope, - InfoSchema: ret.InfoSchema, + InfoSchema: is, Plan: finalPlan, LowerPriority: lowerPriority, Text: stmtNode.Text(), @@ -353,7 +365,13 @@ func GetStmtLabel(stmtNode ast.StmtNode) string { } return "DropTable" case *ast.ExplainStmt: - return "Explain" + if _, ok := x.Stmt.(*ast.ShowStmt); ok { + return "DescTable" + } + if x.Analyze { + return "ExplainAnalyzeSQL" + } + return "ExplainSQL" case *ast.InsertStmt: if x.IsReplace { return "Replace" diff --git a/executor/copr_cache_test.go b/executor/copr_cache_test.go new file mode 100644 index 0000000000000..3d9e73f7cd212 --- /dev/null +++ b/executor/copr_cache_test.go @@ -0,0 +1,89 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "strconv" + "strings" + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/testutils" + "github.com/tikv/client-go/v2/tikv" +) + +func TestIntegrationCopCache(t *testing.T) { + originConfig := config.GetGlobalConfig() + config.StoreGlobalConfig(config.NewConfig()) + defer config.StoreGlobalConfig(originConfig) + + cli := ®ionProperityClient{} + hijackClient := func(c tikv.Client) tikv.Client { + cli.Client = c + return cli + } + var cluster testutils.Cluster + store, dom, clean := testkit.CreateMockStoreAndDomain(t, + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + }), + mockstore.WithClientHijacker(hijackClient)) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int primary key)") + + tblInfo, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tid := tblInfo.Meta().ID + tk.MustExec(`insert into t values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)`) + tableStart := tablecodec.GenTableRecordPrefix(tid) + cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 6) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/cophandler/mockCopCacheInUnistore", `return(123)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/cophandler/mockCopCacheInUnistore")) + }() + + rows := tk.MustQuery("explain analyze select * from t where t.a < 10").Rows() + require.Equal(t, "9", rows[0][2]) + require.Contains(t, rows[0][5], "cop_task: {num: 5") + require.Contains(t, rows[0][5], "copr_cache_hit_ratio: 0.00") + + rows = tk.MustQuery("explain analyze select * from t").Rows() + require.Equal(t, "12", rows[0][2]) + require.Contains(t, rows[0][5], "cop_task: {num: 6") + hitRatioIdx := strings.Index(rows[0][5].(string), "copr_cache_hit_ratio:") + len("copr_cache_hit_ratio: ") + require.GreaterOrEqual(t, hitRatioIdx, len("copr_cache_hit_ratio: ")) + hitRatio, err := strconv.ParseFloat(rows[0][5].(string)[hitRatioIdx:hitRatioIdx+4], 64) + require.NoError(t, err) + require.Greater(t, hitRatio, float64(0)) + + // Test for cop cache disabled. + cfg := config.NewConfig() + cfg.TiKVClient.CoprCache.CapacityMB = 0 + config.StoreGlobalConfig(cfg) + rows = tk.MustQuery("explain analyze select * from t where t.a < 10").Rows() + require.Equal(t, "9", rows[0][2]) + require.Contains(t, rows[0][5], "copr_cache: disabled") +} diff --git a/executor/cte.go b/executor/cte.go index 8345bf5e57f5d..7ee4a78dc417b 100644 --- a/executor/cte.go +++ b/executor/cte.go @@ -89,6 +89,11 @@ type CTEExec struct { memTracker *memory.Tracker diskTracker *disk.Tracker + + // isInApply indicates whether CTE is in inner side of Apply + // and should resTbl/iterInTbl be reset for each outer row of Apply. + // Because we reset them when SQL is finished instead of when CTEExec.Close() is called. + isInApply bool } // Open implements the Executor interface. @@ -114,6 +119,9 @@ func (e *CTEExec) Open(ctx context.Context) (err error) { if err = e.recursiveExec.Open(ctx); err != nil { return err } + // For non-recursive CTE, the result will be put into resTbl directly. + // So no need to build iterOutTbl. + // Construct iterOutTbl in Open() instead of buildCTE(), because its destruct is in Close(). recursiveTypes := e.recursiveExec.base().retFieldTypes e.iterOutTbl = cteutil.NewStorageRowContainer(recursiveTypes, e.maxChunkSize) if err = e.iterOutTbl.OpenAndRef(); err != nil { @@ -210,6 +218,11 @@ func (e *CTEExec) Close() (err error) { } } } + if e.isInApply { + if err = e.reopenTbls(); err != nil { + return err + } + } return e.baseExecutor.Close() } @@ -217,8 +230,6 @@ func (e *CTEExec) Close() (err error) { func (e *CTEExec) computeSeedPart(ctx context.Context) (err error) { e.curIter = 0 e.iterInTbl.SetIter(e.curIter) - // This means iterInTbl's can be read. - defer close(e.iterInTbl.GetBegCh()) chks := make([]*chunk.Chunk, 0, 10) for { if e.limitDone(e.iterInTbl) { @@ -371,7 +382,6 @@ func (e *CTEExec) setupTblsForNewIteration() (err error) { if err = e.iterInTbl.Reopen(); err != nil { return err } - defer close(e.iterInTbl.GetBegCh()) if e.isDistinct { // Already deduplicated by resTbl, adding directly is ok. for _, chk := range chks { @@ -398,7 +408,9 @@ func (e *CTEExec) reset() { } func (e *CTEExec) reopenTbls() (err error) { - e.hashTbl = newConcurrentMapHashTable() + if e.isDistinct { + e.hashTbl = newConcurrentMapHashTable() + } if err := e.resTbl.Reopen(); err != nil { return err } diff --git a/executor/cte_table_reader.go b/executor/cte_table_reader.go index efd5a0387e6cb..4afd8aabbb79f 100644 --- a/executor/cte_table_reader.go +++ b/executor/cte_table_reader.go @@ -41,9 +41,6 @@ func (e *CTETableReaderExec) Open(ctx context.Context) error { func (e *CTETableReaderExec) Next(ctx context.Context, req *chunk.Chunk) (err error) { req.Reset() - // Wait until iterInTbl can be read. This is controlled by corresponding CTEExec. - <-e.iterInTbl.GetBegCh() - // We should read `iterInTbl` from the beginning when the next iteration starts. // Can not directly judge whether to start the next iteration based on e.chkIdx, // because some operators(Selection) may use forloop to read all data in `iterInTbl`. diff --git a/executor/cte_test.go b/executor/cte_test.go index bf6d33ede4a42..bfc99c0ae89e6 100644 --- a/executor/cte_test.go +++ b/executor/cte_test.go @@ -22,13 +22,15 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) func TestBasicCTE(t *testing.T) { - store, close := testkit.CreateMockStore(t) - defer close() + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") @@ -76,8 +78,8 @@ func TestBasicCTE(t *testing.T) { } func TestUnionDistinct(t *testing.T) { - store, close := testkit.CreateMockStore(t) - defer close() + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") @@ -103,8 +105,8 @@ func TestUnionDistinct(t *testing.T) { } func TestCTEMaxRecursionDepth(t *testing.T) { - store, close := testkit.CreateMockStore(t) - defer close() + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") @@ -144,8 +146,8 @@ func TestCTEMaxRecursionDepth(t *testing.T) { } func TestCTEWithLimit(t *testing.T) { - store, close := testkit.CreateMockStore(t) - defer close() + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") @@ -357,8 +359,8 @@ func TestSpillToDisk(t *testing.T) { conf.OOMUseTmpStorage = true }) - store, close := testkit.CreateMockStore(t) - defer close() + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") @@ -408,3 +410,33 @@ func TestSpillToDisk(t *testing.T) { } rows.Check(testkit.Rows(resRows...)) } + +func TestCTEExecError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists src;") + tk.MustExec("create table src(first int, second int);") + + insertStr := fmt.Sprintf("insert into src values (%d, %d)", rand.Intn(1000), rand.Intn(1000)) + for i := 0; i < 1000; i++ { + insertStr += fmt.Sprintf(",(%d, %d)", rand.Intn(1000), rand.Intn(1000)) + } + insertStr += ";" + tk.MustExec(insertStr) + + // Increase projection concurrency and decrease chunk size + // to increase the probability of reproducing the problem. + tk.MustExec("set tidb_max_chunk_size = 32") + tk.MustExec("set tidb_projection_concurrency = 20") + for i := 0; i < 10; i++ { + err := tk.QueryToErr("with recursive cte(iter, first, second, result) as " + + "(select 1, first, second, first+second from src " + + " union all " + + "select iter+1, second, result, second+result from cte where iter < 80 )" + + "select * from cte") + require.True(t, terror.ErrorEqual(err, types.ErrOverflow)) + } +} diff --git a/executor/ddl.go b/executor/ddl.go index ac97d95d2fa5a..1c940c70dff74 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -36,6 +36,7 @@ import ( "github.com/pingcap/tidb/util/admin" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/gcutil" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" @@ -185,18 +186,7 @@ func (e *DDLExec) Next(ctx context.Context, req *chunk.Chunk) (err error) { case *ast.AlterSequenceStmt: err = e.executeAlterSequence(x) case *ast.CreatePlacementPolicyStmt: - if x.OrReplace && x.IfNotExists { - err = ddl.ErrWrongUsage.GenWithStackByArgs("OR REPLACE", "IF NOT EXISTS") - break - } err = e.executeCreatePlacementPolicy(x) - if x.OrReplace && errors.ErrorEqual(err, infoschema.ErrPlacementPolicyExists) { - alterStmt := &ast.AlterPlacementPolicyStmt{ - PolicyName: x.PolicyName, - PlacementOptions: x.PlacementOptions, - } - err = e.executeAlterPlacementPolicy(alterStmt) - } case *ast.DropPlacementPolicyStmt: err = e.executeDropPlacementPolicy(x) case *ast.AlterPlacementPolicyStmt: @@ -237,7 +227,7 @@ func (e *DDLExec) executeRenameTable(s *ast.RenameTableStmt) error { if len(s.TableToTables) == 1 { oldIdent := ast.Ident{Schema: s.TableToTables[0].OldTable.Schema, Name: s.TableToTables[0].OldTable.Name} if _, ok := e.getLocalTemporaryTable(oldIdent.Schema, oldIdent.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("RENAME TABLE") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("RENAME TABLE") } newIdent := ast.Ident{Schema: s.TableToTables[0].NewTable.Schema, Name: s.TableToTables[0].NewTable.Name} err = domain.GetDomain(e.ctx).DDL().RenameTable(e.ctx, oldIdent, newIdent, isAlterTable) @@ -247,7 +237,7 @@ func (e *DDLExec) executeRenameTable(s *ast.RenameTableStmt) error { for _, tables := range s.TableToTables { oldIdent := ast.Ident{Schema: tables.OldTable.Schema, Name: tables.OldTable.Name} if _, ok := e.getLocalTemporaryTable(oldIdent.Schema, oldIdent.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("RENAME TABLE") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("RENAME TABLE") } newIdent := ast.Ident{Schema: tables.NewTable.Schema, Name: tables.NewTable.Name} oldIdents = append(oldIdents, oldIdent) @@ -260,7 +250,6 @@ func (e *DDLExec) executeRenameTable(s *ast.RenameTableStmt) error { func (e *DDLExec) executeCreateDatabase(s *ast.CreateDatabaseStmt) error { var opt *ast.CharsetOpt - var directPlacementOpts *model.PlacementSettings var placementPolicyRef *model.PolicyRefInfo var err error sessionVars := e.ctx.GetSessionVars() @@ -289,19 +278,6 @@ func (e *DDLExec) executeCreateDatabase(s *ast.CreateDatabaseStmt) error { case ast.DatabaseOptionCollate: opt.Col = val.Value explicitCollation = true - case ast.DatabaseOptionPlacementPrimaryRegion, ast.DatabaseOptionPlacementRegions, - ast.DatabaseOptionPlacementFollowerCount, ast.DatabaseOptionPlacementLeaderConstraints, - ast.DatabaseOptionPlacementLearnerCount, ast.DatabaseOptionPlacementVoterCount, - ast.DatabaseOptionPlacementSchedule, ast.DatabaseOptionPlacementConstraints, - ast.DatabaseOptionPlacementFollowerConstraints, ast.DatabaseOptionPlacementVoterConstraints, - ast.DatabaseOptionPlacementLearnerConstraints: - if directPlacementOpts == nil { - directPlacementOpts = &model.PlacementSettings{} - } - err := ddl.SetDirectPlacementOpt(directPlacementOpts, ast.PlacementOptionType(val.Tp), val.Value, val.UintValue) - if err != nil { - return err - } case ast.DatabaseOptionPlacementPolicy: placementPolicyRef = &model.PolicyRefInfo{ Name: model.NewCIStr(val.Value), @@ -331,7 +307,7 @@ func (e *DDLExec) executeCreateDatabase(s *ast.CreateDatabaseStmt) error { } - err = domain.GetDomain(e.ctx).DDL().CreateSchema(e.ctx, model.NewCIStr(s.Name), opt, directPlacementOpts, placementPolicyRef) + err = domain.GetDomain(e.ctx).DDL().CreateSchema(e.ctx, model.NewCIStr(s.Name), opt, placementPolicyRef) if err != nil { if infoschema.ErrDatabaseExists.Equal(err) && s.IfNotExists { err = nil @@ -367,7 +343,7 @@ func (e *DDLExec) createSessionTemporaryTable(s *ast.CreateTableStmt) error { return err } - tbInfo, err := ddl.BuildSessionTemporaryTableInfo(e.ctx, is, s, dbInfo.Charset, dbInfo.Collate, dbInfo.PlacementPolicyRef, dbInfo.DirectPlacementOpts) + tbInfo, err := ddl.BuildSessionTemporaryTableInfo(e.ctx, is, s, dbInfo.Charset, dbInfo.Collate, dbInfo.PlacementPolicyRef) if err != nil { return err } @@ -391,7 +367,7 @@ func (e *DDLExec) executeCreateView(s *ast.CreateViewStmt) error { func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error { ident := ast.Ident{Schema: s.Table.Schema, Name: s.Table.Name} if _, ok := e.getLocalTemporaryTable(ident.Schema, ident.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("CREATE INDEX") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("CREATE INDEX") } err := domain.GetDomain(e.ctx).DDL().CreateIndex(e.ctx, ident, s.KeyType, model.NewCIStr(s.IndexName), @@ -506,11 +482,7 @@ func (e *DDLExec) dropTableObject(objects []*ast.TableName, obt objectType, ifEx zap.String("table", fullti.Name.O), ) exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), "admin check table %n.%n", fullti.Schema.O, fullti.Name.O) - if err != nil { - return err - } - _, _, err = exec.ExecRestrictedStmt(context.TODO(), stmt) + _, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, "admin check table %n.%n", fullti.Schema.O, fullti.Name.O) if err != nil { return err } @@ -566,7 +538,7 @@ func (e *DDLExec) dropLocalTemporaryTables(localTempTables []*ast.TableName) err func (e *DDLExec) executeDropIndex(s *ast.DropIndexStmt) error { ti := ast.Ident{Schema: s.Table.Schema, Name: s.Table.Name} if _, ok := e.getLocalTemporaryTable(ti.Schema, ti.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("DROP INDEX") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("DROP INDEX") } err := domain.GetDomain(e.ctx).DDL().DropIndex(e.ctx, ti, model.NewCIStr(s.IndexName), s.IfExists) @@ -579,7 +551,7 @@ func (e *DDLExec) executeDropIndex(s *ast.DropIndexStmt) error { func (e *DDLExec) executeAlterTable(ctx context.Context, s *ast.AlterTableStmt) error { ti := ast.Ident{Schema: s.Table.Schema, Name: s.Table.Name} if _, ok := e.getLocalTemporaryTable(ti.Schema, ti.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ALTER TABLE") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ALTER TABLE") } err := domain.GetDomain(e.ctx).DDL().AlterTable(ctx, e.ctx, ti, s.Specs) @@ -621,10 +593,6 @@ func (e *DDLExec) executeRecoverTable(s *ast.RecoverTableStmt) error { return err } - if tblInfo, err = recoverTablePlacement(m, tblInfo); err != nil { - return err - } - recoverInfo := &ddl.RecoverInfo{ SchemaID: job.SchemaID, TableInfo: tblInfo, @@ -639,40 +607,6 @@ func (e *DDLExec) executeRecoverTable(s *ast.RecoverTableStmt) error { return err } -// recoverTablePlacement is used when recover/flashback table. -// It will replace the placement policy of table with the direct options because the original policy may be deleted -func recoverTablePlacement(snapshotMeta *meta.Meta, tblInfo *model.TableInfo) (*model.TableInfo, error) { - if ref := tblInfo.PlacementPolicyRef; ref != nil { - policy, err := snapshotMeta.GetPolicy(ref.ID) - if err != nil { - return nil, errors.Trace(err) - } - - tblInfo.PlacementPolicyRef = nil - tblInfo.DirectPlacementOpts = policy.PlacementSettings - } - - if tblInfo.Partition != nil { - for idx := range tblInfo.Partition.Definitions { - def := &tblInfo.Partition.Definitions[idx] - ref := def.PlacementPolicyRef - if ref == nil { - continue - } - - policy, err := snapshotMeta.GetPolicy(ref.ID) - if err != nil { - return nil, errors.Trace(err) - } - - def.PlacementPolicyRef = nil - def.DirectPlacementOpts = policy.PlacementSettings - } - } - - return tblInfo, nil -} - func (e *DDLExec) getRecoverTableByJobID(s *ast.RecoverTableStmt, t *meta.Meta, dom *domain.Domain) (*model.Job, *model.TableInfo, error) { job, err := t.GetHistoryDDLJob(s.JobID) if err != nil { @@ -799,10 +733,6 @@ func (e *DDLExec) executeFlashbackTable(s *ast.FlashBackTableStmt) error { return err } - if tblInfo, err = recoverTablePlacement(m, tblInfo); err != nil { - return err - } - recoverInfo := &ddl.RecoverInfo{ SchemaID: job.SchemaID, TableInfo: tblInfo, @@ -825,7 +755,7 @@ func (e *DDLExec) executeLockTables(s *ast.LockTablesStmt) error { for _, tb := range s.TableLocks { if _, ok := e.getLocalTemporaryTable(tb.Table.Schema, tb.Table.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("LOCK TABLES") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("LOCK TABLES") } } @@ -844,7 +774,7 @@ func (e *DDLExec) executeUnlockTables(_ *ast.UnlockTablesStmt) error { func (e *DDLExec) executeCleanupTableLock(s *ast.CleanupTableLockStmt) error { for _, tb := range s.Tables { if _, ok := e.getLocalTemporaryTable(tb.Schema, tb.Name); ok { - return ddl.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ADMIN CLEANUP TABLE LOCK") + return dbterror.ErrUnsupportedLocalTempTableDDL.GenWithStackByArgs("ADMIN CLEANUP TABLE LOCK") } } return domain.GetDomain(e.ctx).DDL().CleanupTableLock(e.ctx, s.Tables) diff --git a/executor/ddl_test.go b/executor/ddl_test.go index eb3f344e0c3fb..5a6368dab3df5 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -20,11 +20,10 @@ import ( "math" "strconv" "strings" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/ddl" ddltestutil "github.com/pingcap/tidb/ddl/testutil" ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain" @@ -38,18 +37,21 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" ) -func (s *testSuite6) TestTruncateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists truncate_test;`) tk.MustExec(`create table truncate_test (a int)`) @@ -65,21 +67,25 @@ func (s *testSuite6) TestTruncateTable(c *C) { // 1. Execute the SQL of "begin"; // 2. A SQL that will fail to execute; // 3. Execute DDL. -func (s *testSuite6) TestInTxnExecDDLFail(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInTxnExecDDLFail(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (i int key);") tk.MustExec("insert into t values (1);") tk.MustExec("begin;") tk.MustExec("insert into t values (1);") _, err := tk.Exec("truncate table t;") - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'") + require.EqualError(t, err, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'") result := tk.MustQuery("select count(*) from t") result.Check(testkit.Rows("1")) } -func (s *testSuite6) TestInTxnExecDDLInvalid(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInTxnExecDDLInvalid(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (c_int int, c_str varchar(40));") @@ -89,18 +95,20 @@ func (s *testSuite6) TestInTxnExecDDLInvalid(c *C) { tk.MustExec("alter table t add index idx_4 (c_str);") } -func (s *testSuite6) TestCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test create an exist database _, err := tk.Exec("CREATE database test") - c.Assert(err, NotNil) + require.Error(t, err) // Test create an exist table tk.MustExec("CREATE TABLE create_test (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") _, err = tk.Exec("CREATE TABLE create_test (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") - c.Assert(err, NotNil) + require.Error(t, err) // Test "if not exist" tk.MustExec("CREATE TABLE if not exists test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") @@ -109,65 +117,65 @@ func (s *testSuite6) TestCreateTable(c *C) { tk.MustExec(`create table issue312_1 (c float(24));`) tk.MustExec(`create table issue312_2 (c float(25));`) rs, err := tk.Exec(`desc issue312_1`) - c.Assert(err, IsNil) + require.NoError(t, err) ctx := context.Background() req := rs.NewChunk(nil) it := chunk.NewIterator4Chunk(req) for { err1 := rs.Next(ctx, req) - c.Assert(err1, IsNil) + require.NoError(t, err1) if req.NumRows() == 0 { break } for row := it.Begin(); row != it.End(); row = it.Next() { - c.Assert(row.GetString(1), Equals, "float") + require.Equal(t, "float", row.GetString(1)) } } rs, err = tk.Exec(`desc issue312_2`) - c.Assert(err, IsNil) + require.NoError(t, err) req = rs.NewChunk(nil) it = chunk.NewIterator4Chunk(req) for { err1 := rs.Next(ctx, req) - c.Assert(err1, IsNil) + require.NoError(t, err1) if req.NumRows() == 0 { break } for row := it.Begin(); row != it.End(); row = it.Next() { - c.Assert(req.GetRow(0).GetString(1), Equals, "double") + require.Equal(t, "double", req.GetRow(0).GetString(1)) } } - c.Assert(rs.Close(), IsNil) + require.NoError(t, rs.Close()) // test multiple collate specified in column when create. tk.MustExec("drop table if exists test_multiple_column_collate;") tk.MustExec("create table test_multiple_column_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") - t, err := domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("test_multiple_column_collate")) - c.Assert(err, IsNil) - c.Assert(t.Cols()[0].Charset, Equals, "utf8") - c.Assert(t.Cols()[0].Collate, Equals, "utf8_general_ci") - c.Assert(t.Meta().Charset, Equals, "utf8mb4") - c.Assert(t.Meta().Collate, Equals, "utf8mb4_bin") + tt, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("test_multiple_column_collate")) + require.NoError(t, err) + require.Equal(t, "utf8", tt.Cols()[0].Charset) + require.Equal(t, "utf8_general_ci", tt.Cols()[0].Collate) + require.Equal(t, "utf8mb4", tt.Meta().Charset) + require.Equal(t, "utf8mb4_bin", tt.Meta().Collate) tk.MustExec("drop table if exists test_multiple_column_collate;") tk.MustExec("create table test_multiple_column_collate (a char(1) charset utf8 collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") - t, err = domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("test_multiple_column_collate")) - c.Assert(err, IsNil) - c.Assert(t.Cols()[0].Charset, Equals, "utf8") - c.Assert(t.Cols()[0].Collate, Equals, "utf8_general_ci") - c.Assert(t.Meta().Charset, Equals, "utf8mb4") - c.Assert(t.Meta().Collate, Equals, "utf8mb4_bin") + tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("test_multiple_column_collate")) + require.NoError(t, err) + require.Equal(t, "utf8", tt.Cols()[0].Charset) + require.Equal(t, "utf8_general_ci", tt.Cols()[0].Collate) + require.Equal(t, "utf8mb4", tt.Meta().Charset) + require.Equal(t, "utf8mb4_bin", tt.Meta().Collate) // test Err case for multiple collate specified in column when create. tk.MustExec("drop table if exists test_err_multiple_collate;") _, err = tk.Exec("create table test_err_multiple_collate (a char(1) charset utf8mb4 collate utf8_unicode_ci collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ddl.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_unicode_ci", "utf8mb4").Error()) + require.Error(t, err) + require.Equal(t, dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_unicode_ci", "utf8mb4").Error(), err.Error()) tk.MustExec("drop table if exists test_err_multiple_collate;") _, err = tk.Exec("create table test_err_multiple_collate (a char(1) collate utf8_unicode_ci collate utf8mb4_general_ci) charset utf8mb4 collate utf8mb4_bin") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ddl.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_general_ci", "utf8").Error()) + require.Error(t, err) + require.Equal(t, dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_general_ci", "utf8").Error(), err.Error()) // table option is auto-increment tk.MustExec("drop table if exists create_auto_increment_test;") @@ -195,11 +203,13 @@ func (s *testSuite6) TestCreateTable(c *C) { tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1051 Unknown table 'test.t_if_exists'")) tk.MustExec("create table if not exists t1_if_exists(c int)") tk.MustExec("drop table if exists t1_if_exists,t2_if_exists,t3_if_exists") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1051|Unknown table 'test.t2_if_exists'", "Note|1051|Unknown table 'test.t3_if_exists'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|1051|Unknown table 'test.t2_if_exists'", "Note|1051|Unknown table 'test.t3_if_exists'")) } -func (s *testSuite6) TestCreateView(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // create an source table tk.MustExec("CREATE TABLE source_table (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") @@ -207,10 +217,10 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustExec("CREATE VIEW view_t AS select id , name from source_table") defer tk.MustExec("DROP VIEW IF EXISTS view_t") _, err := tk.Exec("CREATE VIEW view_t AS select id , name from source_table") - c.Assert(err.Error(), Equals, "[schema:1050]Table 'test.view_t' already exists") + require.EqualError(t, err, "[schema:1050]Table 'test.view_t' already exists") // create view on nonexistent table _, err = tk.Exec("create view v1 (c,d) as select a,b from t1") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.t1' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.t1' doesn't exist") // simple view tk.MustExec("create table t1 (a int ,b int)") tk.MustExec("insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10)") @@ -226,26 +236,26 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustExec("create view v5 as select * from t1") tk.MustExec("create view v6 (c,d) as select * from t1") _, err = tk.Exec("create view v7 (c,d,e) as select * from t1") - c.Assert(err.Error(), Equals, ddl.ErrViewWrongList.Error()) + require.Equal(t, dbterror.ErrViewWrongList.Error(), err.Error()) // drop multiple views in a statement tk.MustExec("drop view v1,v2,v3,v4,v5,v6") // view with variable tk.MustExec("create view v1 (c,d) as select a,b+@@global.max_user_connections from t1") _, err = tk.Exec("create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections") - c.Assert(err.Error(), Equals, "[schema:1050]Table 'test.v1' already exists") + require.EqualError(t, err, "[schema:1050]Table 'test.v1' already exists") tk.MustExec("drop view v1") // view with different col counts _, err = tk.Exec("create view v1 (c,d,e) as select a,b from t1 ") - c.Assert(err.Error(), Equals, ddl.ErrViewWrongList.Error()) + require.Equal(t, dbterror.ErrViewWrongList.Error(), err.Error()) _, err = tk.Exec("create view v1 (c) as select a,b from t1 ") - c.Assert(err.Error(), Equals, ddl.ErrViewWrongList.Error()) + require.Equal(t, dbterror.ErrViewWrongList.Error(), err.Error()) // view with or_replace flag tk.MustExec("drop view if exists v1") tk.MustExec("create view v1 (c,d) as select a,b from t1") tk.MustExec("create or replace view v1 (c,d) as select a,b from t1 ") tk.MustExec("create table if not exists t1 (a int ,b int)") _, err = tk.Exec("create or replace view t1 as select * from t1") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "t1", "VIEW").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "t1", "VIEW").Error(), err.Error()) // create view using prepare tk.MustExec(`prepare stmt from "create view v10 (x) as select 1";`) tk.MustExec("execute stmt") @@ -254,7 +264,7 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustExec("drop table if exists t1, t2") tk.MustExec("drop view if exists v") _, err = tk.Exec("create view v as select * from t1 union select * from t2") - c.Assert(terror.ErrorEqual(err, infoschema.ErrTableNotExists), IsTrue) + require.True(t, terror.ErrorEqual(err, infoschema.ErrTableNotExists)) tk.MustExec("create table t1(a int, b int)") tk.MustExec("create table t2(a int, b int)") tk.MustExec("insert into t1 values(1,2), (1,1), (1,2)") @@ -263,13 +273,13 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustQuery("select * from v").Sort().Check(testkit.Rows("1 1", "1 2", "1 3")) tk.MustExec("alter table t1 drop column a") _, err = tk.Exec("select * from v") - c.Assert(terror.ErrorEqual(err, plannercore.ErrViewInvalid), IsTrue) + require.True(t, terror.ErrorEqual(err, plannercore.ErrViewInvalid)) tk.MustExec("alter table t1 add column a int") tk.MustQuery("select * from v").Sort().Check(testkit.Rows("1 1", "1 3", " 1", " 2")) tk.MustExec("alter table t1 drop column a") tk.MustExec("alter table t2 drop column b") _, err = tk.Exec("select * from v") - c.Assert(terror.ErrorEqual(err, plannercore.ErrViewInvalid), IsTrue) + require.True(t, terror.ErrorEqual(err, plannercore.ErrViewInvalid)) tk.MustExec("drop view v") tk.MustExec("create view v as (select * from t1)") @@ -282,24 +292,35 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustQuery("show warnings;").Check(testkit.Rows("Note 1051 Unknown table 'test.v_if_exists'")) tk.MustExec("create view v1_if_exists as (select * from t1)") tk.MustExec("drop view if exists v1_if_exists,v2_if_exists,v3_if_exists") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1051|Unknown table 'test.v2_if_exists'", "Note|1051|Unknown table 'test.v3_if_exists'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|1051|Unknown table 'test.v2_if_exists'", "Note|1051|Unknown table 'test.v3_if_exists'")) // Test for create nested view. tk.MustExec("create table test_v_nested(a int)") tk.MustExec("create definer='root'@'localhost' view v_nested as select * from test_v_nested") tk.MustExec("create definer='root'@'localhost' view v_nested2 as select * from v_nested") _, err = tk.Exec("create or replace definer='root'@'localhost' view v_nested as select * from v_nested2") - c.Assert(terror.ErrorEqual(err, plannercore.ErrNoSuchTable), IsTrue) + require.True(t, terror.ErrorEqual(err, plannercore.ErrNoSuchTable)) tk.MustExec("drop table test_v_nested") tk.MustExec("drop view v_nested, v_nested2") // Refer https://github.com/pingcap/tidb/issues/25876 err = tk.ExecToErr("create view v_stale as select * from source_table as of timestamp current_timestamp(3)") - c.Assert(terror.ErrorEqual(err, executor.ErrViewInvalid), IsTrue, Commentf("err %s", err)) + require.Truef(t, terror.ErrorEqual(err, executor.ErrViewInvalid), "err %s", err) + + // Refer https://github.com/pingcap/tidb/issues/32682 + tk.MustExec("drop view if exists v1,v2;") + tk.MustExec("drop table if exists t1;") + tk.MustExec("CREATE TABLE t1(a INT, b INT);") + err = tk.ExecToErr("CREATE DEFINER=1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost VIEW v1 AS SELECT a FROM t1;") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL' is too long for user name (should be no longer than 32)") + err = tk.ExecToErr("CREATE DEFINER=some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X VIEW v2 AS SELECT b FROM t1;") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String 'host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345' is too long for host name (should be no longer than 255)") } -func (s *testSuite6) TestViewRecursion(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestViewRecursion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists t(a int)") tk.MustExec("create definer='root'@'localhost' view recursive_view1 as select * from t") @@ -307,21 +328,25 @@ func (s *testSuite6) TestViewRecursion(c *C) { tk.MustExec("drop table t") tk.MustExec("rename table recursive_view2 to t") _, err := tk.Exec("select * from recursive_view1") - c.Assert(terror.ErrorEqual(err, plannercore.ErrViewRecursive), IsTrue) + require.True(t, terror.ErrorEqual(err, plannercore.ErrViewRecursive)) tk.MustExec("drop view recursive_view1, t") } -func (s *testSuite6) TestIssue16250(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16250(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists t(a int)") tk.MustExec("create view view_issue16250 as select * from t") _, err := tk.Exec("truncate table view_issue16250") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.view_issue16250' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.view_issue16250' doesn't exist") } -func (s *testSuite6) TestIssue24771(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue24771(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists zy_tab;`) tk.MustExec(`create table if not exists zy_tab ( @@ -358,21 +383,25 @@ func (s *testSuite6) TestIssue24771(c *C) { tk.MustQuery(`select * from v_st_2`) } -func (s testSuite6) TestTruncateSequence(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateSequence(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create sequence if not exists seq") _, err := tk.Exec("truncate table seq") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.seq' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.seq' doesn't exist") tk.MustExec("create sequence if not exists seq1 start 10 increment 2 maxvalue 10000 cycle") _, err = tk.Exec("truncate table seq1") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.seq1' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.seq1' doesn't exist") tk.MustExec("drop sequence if exists seq") tk.MustExec("drop sequence if exists seq1") } -func (s *testSuite6) TestCreateViewWithOverlongColName(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateViewWithOverlongColName(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int)") defer tk.MustExec("drop table t") @@ -415,41 +444,43 @@ func (s *testSuite6) TestCreateViewWithOverlongColName(c *C) { tk.MustExec("drop view v ") err := tk.ExecToErr("create view v(`" + strings.Repeat("b", 65) + "`) as select a from t;") - c.Assert(err.Error(), Equals, "[ddl:1059]Identifier name 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' is too long") + require.EqualError(t, err, "[ddl:1059]Identifier name 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' is too long") } -func (s *testSuite6) TestCreateDropDatabase(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateDropDatabase(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists drop_test;") tk.MustExec("drop database if exists drop_test;") tk.MustExec("create database drop_test;") tk.MustExec("use drop_test;") tk.MustExec("drop database drop_test;") _, err := tk.Exec("drop table t;") - c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error()) + require.Equal(t, plannercore.ErrNoDB.Error(), err.Error()) err = tk.ExecToErr("select * from t;") - c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error()) + require.Equal(t, plannercore.ErrNoDB.Error(), err.Error()) _, err = tk.Exec("drop database mysql") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("create database charset_test charset ascii;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET ascii */", )) tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test charset binary;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET binary */", )) tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test collate utf8_general_ci;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */", )) tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test charset utf8 collate utf8_general_ci;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */", )) tk.MustGetErrMsg("create database charset_test charset utf8 collate utf8mb4_unicode_ci;", "[ddl:1253]COLLATION 'utf8mb4_unicode_ci' is not valid for CHARACTER SET 'utf8'") @@ -459,25 +490,27 @@ func (s *testSuite6) TestCreateDropDatabase(c *C) { tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET ascii */", )) tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test collate utf8mb4_general_ci;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */", )) tk.MustExec("drop database charset_test;") tk.MustExec("create database charset_test charset utf8mb4;") - tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create database charset_test;").Check(testkit.RowsWithSep("|", "charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) } -func (s *testSuite6) TestCreateDropTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateDropTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists drop_test (a int)") tk.MustExec("drop table if exists drop_test") @@ -485,29 +518,30 @@ func (s *testSuite6) TestCreateDropTable(c *C) { tk.MustExec("drop table drop_test") _, err := tk.Exec("drop table mysql.gc_delete_range") - c.Assert(err, NotNil) + require.Error(t, err) } -func (s *testSuite6) TestCreateDropView(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateDropView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create or replace view drop_test as select 1,2") _, err := tk.Exec("drop table drop_test") - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.drop_test'") + require.EqualError(t, err, "[schema:1051]Unknown table 'test.drop_test'") - _, err = tk.Exec("drop view if exists drop_test") - c.Assert(err, IsNil) + tk.MustExec("drop view if exists drop_test") _, err = tk.Exec("drop view mysql.gc_delete_range") - c.Assert(err.Error(), Equals, "Drop tidb system table 'mysql.gc_delete_range' is forbidden") + require.EqualError(t, err, "Drop tidb system table 'mysql.gc_delete_range' is forbidden") _, err = tk.Exec("drop view drop_test") - c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.drop_test'") + require.EqualError(t, err, "[schema:1051]Unknown table 'test.drop_test'") tk.MustExec("create table t_v(a int)") _, err = tk.Exec("drop view t_v") - c.Assert(err.Error(), Equals, "[ddl:1347]'test.t_v' is not VIEW") + require.EqualError(t, err, "[ddl:1347]'test.t_v' is not VIEW") tk.MustExec("create table t_v1(a int, b int);") tk.MustExec("create table t_v2(a int, b int);") @@ -517,8 +551,10 @@ func (s *testSuite6) TestCreateDropView(c *C) { testkit.Rows("def test v SELECT `test`.`t_v2`.`a` AS `a`,`test`.`t_v2`.`b` AS `b` FROM `test`.`t_v2` CASCADED NO @ DEFINER utf8mb4 utf8mb4_bin")) } -func (s *testSuite6) TestCreateDropIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateDropIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists drop_test (a int)") tk.MustExec("create index idx_a on drop_test (a)") @@ -526,8 +562,10 @@ func (s *testSuite6) TestCreateDropIndex(c *C) { tk.MustExec("drop table drop_test") } -func (s *testSuite6) TestAlterTableAddColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists alter_test (c1 int)") tk.MustExec("insert into alter_test values(1)") @@ -535,87 +573,93 @@ func (s *testSuite6) TestAlterTableAddColumn(c *C) { time.Sleep(1 * time.Millisecond) now := time.Now().Add(-1 * time.Millisecond).Format(types.TimeFormat) r, err := tk.Exec("select c2 from alter_test") - c.Assert(err, IsNil) + require.NoError(t, err) req := r.NewChunk(nil) err = r.Next(context.Background(), req) - c.Assert(err, IsNil) + require.NoError(t, err) row := req.GetRow(0) - c.Assert(row.Len(), Equals, 1) - c.Assert(now, GreaterEqual, row.GetTime(0).String()) - c.Assert(r.Close(), IsNil) + require.Equal(t, 1, row.Len()) + require.GreaterOrEqual(t, now, row.GetTime(0).String()) + require.Nil(t, r.Close()) tk.MustExec("alter table alter_test add column c3 varchar(50) default 'CURRENT_TIMESTAMP'") tk.MustQuery("select c3 from alter_test").Check(testkit.Rows("CURRENT_TIMESTAMP")) tk.MustExec("create or replace view alter_view as select c1,c2 from alter_test") _, err = tk.Exec("alter table alter_view add column c4 varchar(50)") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop view alter_view") tk.MustExec("create sequence alter_seq") _, err = tk.Exec("alter table alter_seq add column c int") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop sequence alter_seq") } -func (s *testSuite6) TestAlterTableAddColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableAddColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table if not exists alter_test (c1 int)") tk.MustExec("insert into alter_test values(1)") tk.MustExec("alter table alter_test add column c2 timestamp default current_timestamp, add column c8 varchar(50) default 'CURRENT_TIMESTAMP'") tk.MustExec("alter table alter_test add column (c7 timestamp default current_timestamp, c3 varchar(50) default 'CURRENT_TIMESTAMP')") r, err := tk.Exec("select c2 from alter_test") - c.Assert(err, IsNil) + require.NoError(t, err) req := r.NewChunk(nil) err = r.Next(context.Background(), req) - c.Assert(err, IsNil) + require.NoError(t, err) row := req.GetRow(0) - c.Assert(row.Len(), Equals, 1) - c.Assert(r.Close(), IsNil) + require.Equal(t, 1, row.Len()) + require.Nil(t, r.Close()) tk.MustQuery("select c3 from alter_test").Check(testkit.Rows("CURRENT_TIMESTAMP")) tk.MustExec("create or replace view alter_view as select c1,c2 from alter_test") _, err = tk.Exec("alter table alter_view add column (c4 varchar(50), c5 varchar(50))") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop view alter_view") tk.MustExec("create sequence alter_seq") _, err = tk.Exec("alter table alter_seq add column (c1 int, c2 varchar(10))") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop sequence alter_seq") } -func (s *testSuite6) TestAddNotNullColumnNoDefault(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAddNotNullColumnNoDefault(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table nn (c1 int)") tk.MustExec("insert nn values (1), (2)") tk.MustExec("alter table nn add column c2 int not null") - tbl, err := domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("nn")) - c.Assert(err, IsNil) + tbl, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("nn")) + require.NoError(t, err) col2 := tbl.Meta().Columns[1] - c.Assert(col2.DefaultValue, IsNil) - c.Assert(col2.OriginDefaultValue, Equals, "0") + require.Nil(t, col2.DefaultValue) + require.Equal(t, "0", col2.OriginDefaultValue) tk.MustQuery("select * from nn").Check(testkit.Rows("1 0", "2 0")) _, err = tk.Exec("insert nn (c1) values (3)") - c.Check(err, NotNil) + require.Error(t, err) tk.MustExec("set sql_mode=''") tk.MustExec("insert nn (c1) values (3)") tk.MustQuery("select * from nn").Check(testkit.Rows("1 0", "2 0", "3 0")) } -func (s *testSuite6) TestAlterTableModifyColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterTableModifyColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists mc") tk.MustExec("create table mc(c1 int, c2 varchar(10), c3 bit)") _, err := tk.Exec("alter table mc modify column c1 short") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("alter table mc modify column c1 bigint") _, err = tk.Exec("alter table mc modify column c2 blob") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("alter table mc modify column c2 varchar(8)") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("alter table mc modify column c2 varchar(11)") tk.MustExec("alter table mc modify column c2 text(13)") tk.MustExec("alter table mc modify column c2 text") @@ -623,75 +667,58 @@ func (s *testSuite6) TestAlterTableModifyColumn(c *C) { result := tk.MustQuery("show create table mc") createSQL := result.Rows()[0][1] expected := "CREATE TABLE `mc` (\n `c1` bigint(20) DEFAULT NULL,\n `c2` text DEFAULT NULL,\n `c3` bit(1) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + require.Equal(t, expected, createSQL) tk.MustExec("create or replace view alter_view as select c1,c2 from mc") _, err = tk.Exec("alter table alter_view modify column c2 text") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_view", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop view alter_view") tk.MustExec("create sequence alter_seq") _, err = tk.Exec("alter table alter_seq modify column c int") - c.Assert(err.Error(), Equals, ddl.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error()) + require.Equal(t, dbterror.ErrWrongObject.GenWithStackByArgs("test", "alter_seq", "BASE TABLE").Error(), err.Error()) tk.MustExec("drop sequence alter_seq") // test multiple collate modification in column. tk.MustExec("drop table if exists modify_column_multiple_collate") tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") _, err = tk.Exec("alter table modify_column_multiple_collate modify column a char(1) collate utf8mb4_bin;") - c.Assert(err, IsNil) - t, err := domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("modify_column_multiple_collate")) - c.Assert(err, IsNil) - c.Assert(t.Cols()[0].Charset, Equals, "utf8mb4") - c.Assert(t.Cols()[0].Collate, Equals, "utf8mb4_bin") - c.Assert(t.Meta().Charset, Equals, "utf8mb4") - c.Assert(t.Meta().Collate, Equals, "utf8mb4_bin") + require.NoError(t, err) + tt, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("modify_column_multiple_collate")) + require.NoError(t, err) + require.Equal(t, "utf8mb4", tt.Cols()[0].Charset) + require.Equal(t, "utf8mb4_bin", tt.Cols()[0].Collate) + require.Equal(t, "utf8mb4", tt.Meta().Charset) + require.Equal(t, "utf8mb4_bin", tt.Meta().Collate) tk.MustExec("drop table if exists modify_column_multiple_collate;") tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") _, err = tk.Exec("alter table modify_column_multiple_collate modify column a char(1) charset utf8mb4 collate utf8mb4_bin;") - c.Assert(err, IsNil) - t, err = domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("modify_column_multiple_collate")) - c.Assert(err, IsNil) - c.Assert(t.Cols()[0].Charset, Equals, "utf8mb4") - c.Assert(t.Cols()[0].Collate, Equals, "utf8mb4_bin") - c.Assert(t.Meta().Charset, Equals, "utf8mb4") - c.Assert(t.Meta().Collate, Equals, "utf8mb4_bin") + require.NoError(t, err) + tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("modify_column_multiple_collate")) + require.NoError(t, err) + require.Equal(t, "utf8mb4", tt.Cols()[0].Charset) + require.Equal(t, "utf8mb4_bin", tt.Cols()[0].Collate) + require.Equal(t, "utf8mb4", tt.Meta().Charset) + require.Equal(t, "utf8mb4_bin", tt.Meta().Collate) // test Err case for multiple collate modification in column. tk.MustExec("drop table if exists err_modify_multiple_collate;") tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") _, err = tk.Exec("alter table err_modify_multiple_collate modify column a char(1) charset utf8mb4 collate utf8_bin;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ddl.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_bin", "utf8mb4").Error()) + require.Error(t, err) + require.Equal(t, dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_bin", "utf8mb4").Error(), err.Error()) tk.MustExec("drop table if exists err_modify_multiple_collate;") tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin") _, err = tk.Exec("alter table err_modify_multiple_collate modify column a char(1) collate utf8_bin collate utf8mb4_bin;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, ddl.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_bin", "utf8").Error()) + require.Error(t, err) + require.Equal(t, dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_bin", "utf8").Error(), err.Error()) } -func (s *testSuite6) TestDefaultDBAfterDropCurDB(c *C) { - tk := testkit.NewTestKit(c, s.store) - - testSQL := `create database if not exists test_db CHARACTER SET latin1 COLLATE latin1_swedish_ci;` - tk.MustExec(testSQL) - - testSQL = `use test_db;` - tk.MustExec(testSQL) - tk.MustQuery(`select database();`).Check(testkit.Rows("test_db")) - tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows("latin1")) - tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows("latin1_swedish_ci")) - - testSQL = `drop database test_db;` - tk.MustExec(testSQL) - tk.MustQuery(`select database();`).Check(testkit.Rows("")) - tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows(mysql.DefaultCharset)) - tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows(mysql.DefaultCollationName)) -} - -func (s *testSuite6) TestColumnCharsetAndCollate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestColumnCharsetAndCollate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) dbName := "col_charset_collate" tk.MustExec("create database " + dbName) tk.MustExec("use " + dbName) @@ -752,7 +779,7 @@ func (s *testSuite6) TestColumnCharsetAndCollate(c *C) { errMsg: "", }, } - sctx := tk.Se.(sessionctx.Context) + sctx := tk.Session() dm := domain.GetDomain(sctx) for i, tt := range tests { tblName := fmt.Sprintf("t%d", i) @@ -760,29 +787,31 @@ func (s *testSuite6) TestColumnCharsetAndCollate(c *C) { if tt.errMsg == "" { tk.MustExec(sql) is := dm.InfoSchema() - c.Assert(is, NotNil) + require.NotNil(t, is) tb, err := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName)) - c.Assert(err, IsNil) - c.Assert(tb.Meta().Columns[0].Charset, Equals, tt.exptCharset, Commentf(sql)) - c.Assert(tb.Meta().Columns[0].Collate, Equals, tt.exptCollate, Commentf(sql)) + require.NoError(t, err) + require.Equalf(t, tt.exptCharset, tb.Meta().Columns[0].Charset, sql) + require.Equalf(t, tt.exptCollate, tb.Meta().Columns[0].Collate, sql) } else { _, err := tk.Exec(sql) - c.Assert(err, NotNil, Commentf(sql)) + require.Errorf(t, err, sql) } } tk.MustExec("drop database " + dbName) } -func (s *testSuite6) TestTooLargeIdentifierLength(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTooLargeIdentifierLength(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // for database. dbName1, dbName2 := strings.Repeat("a", mysql.MaxDatabaseNameLength), strings.Repeat("a", mysql.MaxDatabaseNameLength+1) tk.MustExec(fmt.Sprintf("create database %s", dbName1)) tk.MustExec(fmt.Sprintf("drop database %s", dbName1)) _, err := tk.Exec(fmt.Sprintf("create database %s", dbName2)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", dbName2)) + require.Equal(t, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", dbName2), err.Error()) // for table. tk.MustExec("use test") @@ -790,7 +819,7 @@ func (s *testSuite6) TestTooLargeIdentifierLength(c *C) { tk.MustExec(fmt.Sprintf("create table %s(c int)", tableName1)) tk.MustExec(fmt.Sprintf("drop table %s", tableName1)) _, err = tk.Exec(fmt.Sprintf("create table %s(c int)", tableName2)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", tableName2)) + require.Equal(t, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", tableName2), err.Error()) // for column. tk.MustExec("drop table if exists t;") @@ -798,7 +827,7 @@ func (s *testSuite6) TestTooLargeIdentifierLength(c *C) { tk.MustExec(fmt.Sprintf("create table t(%s int)", columnName1)) tk.MustExec("drop table t") _, err = tk.Exec(fmt.Sprintf("create table t(%s int)", columnName2)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", columnName2)) + require.Equal(t, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", columnName2), err.Error()) // for index. tk.MustExec("create table t(c int);") @@ -806,16 +835,18 @@ func (s *testSuite6) TestTooLargeIdentifierLength(c *C) { tk.MustExec(fmt.Sprintf("create index %s on t(c)", indexName1)) tk.MustExec(fmt.Sprintf("drop index %s on t", indexName1)) _, err = tk.Exec(fmt.Sprintf("create index %s on t(c)", indexName2)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", indexName2)) + require.Equal(t, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", indexName2), err.Error()) // for create table with index. tk.MustExec("drop table t;") _, err = tk.Exec(fmt.Sprintf("create table t(c int, index %s(c));", indexName2)) - c.Assert(err.Error(), Equals, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", indexName2)) + require.Equal(t, fmt.Sprintf("[ddl:1059]Identifier name '%s' is too long", indexName2), err.Error()) } -func (s *testSuite8) TestShardRowIDBits(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShardRowIDBits(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (a int) shard_row_id_bits = 15") @@ -823,16 +854,16 @@ func (s *testSuite8) TestShardRowIDBits(c *C) { tk.MustExec("insert into t values (?)", i) } - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) - assertCountAndShard := func(t table.Table, expectCount int) { + assertCountAndShard := func(tt table.Table, expectCount int) { var hasShardedID bool var count int - c.Assert(tk.Se.NewTxn(context.Background()), IsNil) - err = tables.IterRecords(t, tk.Se, nil, func(h kv.Handle, rec []types.Datum, cols []*table.Column) (more bool, err error) { - c.Assert(h.IntValue(), GreaterEqual, int64(0)) + require.NoError(t, tk.Session().NewTxn(context.Background())) + err = tables.IterRecords(tt, tk.Session(), nil, func(h kv.Handle, rec []types.Datum, cols []*table.Column) (more bool, err error) { + require.GreaterOrEqual(t, h.IntValue(), int64(0)) first8bits := h.IntValue() >> 56 if first8bits > 0 { hasShardedID = true @@ -840,9 +871,9 @@ func (s *testSuite8) TestShardRowIDBits(c *C) { count++ return true, nil }) - c.Assert(err, IsNil) - c.Assert(count, Equals, expectCount) - c.Assert(hasShardedID, IsTrue) + require.NoError(t, err) + require.Equal(t, expectCount, count) + require.True(t, hasShardedID) } assertCountAndShard(tbl, 100) @@ -876,22 +907,22 @@ func (s *testSuite8) TestShardRowIDBits(c *C) { // Hack an existing table with shard_row_id_bits and primary key as handle db, ok := dom.InfoSchema().SchemaByName(model.NewCIStr("test")) - c.Assert(ok, IsTrue) + require.True(t, ok) tbl, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("auto")) tblInfo := tbl.Meta() tblInfo.ShardRowIDBits = 5 tblInfo.MaxShardRowIDBits = 5 - err = kv.RunInNewTxn(context.Background(), s.store, false, func(ctx context.Context, txn kv.Transaction) error { + err = kv.RunInNewTxn(context.Background(), store, false, func(ctx context.Context, txn kv.Transaction) error { m := meta.NewMeta(txn) _, err = m.GenSchemaVersion() - c.Assert(err, IsNil) - c.Assert(m.UpdateTable(db.ID, tblInfo), IsNil) + require.NoError(t, err) + require.Nil(t, m.UpdateTable(db.ID, tblInfo)) return nil }) - c.Assert(err, IsNil) + require.NoError(t, err) err = dom.Reload() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("insert auto(b) values (1), (3), (5)") tk.MustQuery("select id from auto order by id").Check(testkit.Rows("1", "2", "3")) @@ -907,11 +938,11 @@ func (s *testSuite8) TestShardRowIDBits(c *C) { tbl, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("auto")) assertCountAndShard(tbl, 100) prevB, err := strconv.Atoi(tk.MustQuery("select b from auto where a=0").Rows()[0][0].(string)) - c.Assert(err, IsNil) + require.NoError(t, err) for i := 1; i < 100; i++ { b, err := strconv.Atoi(tk.MustQuery(fmt.Sprintf("select b from auto where a=%d", i)).Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(b, Greater, prevB) + require.NoError(t, err) + require.Greater(t, b, prevB) prevB = b } @@ -921,26 +952,24 @@ func (s *testSuite8) TestShardRowIDBits(c *C) { defer tk.MustExec("drop table if exists t1") tbl, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) maxID := 1<<(64-15-1) - 1 - alloc := tbl.Allocators(tk.Se).Get(autoid.RowIDAllocType) + alloc := tbl.Allocators(tk.Session()).Get(autoid.RowIDAllocType) err = alloc.Rebase(context.Background(), int64(maxID)-1, false) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("insert into t1 values(1)") // continue inserting will fail. _, err = tk.Exec("insert into t1 values(2)") - c.Assert(autoid.ErrAutoincReadFailed.Equal(err), IsTrue, Commentf("err:%v", err)) + require.Truef(t, autoid.ErrAutoincReadFailed.Equal(err), "err:%v", err) _, err = tk.Exec("insert into t1 values(3)") - c.Assert(autoid.ErrAutoincReadFailed.Equal(err), IsTrue, Commentf("err:%v", err)) + require.Truef(t, autoid.ErrAutoincReadFailed.Equal(err), "err:%v", err) } -type testAutoRandomSuite struct { - *baseTestSuite -} - -func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomBitsData(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_auto_random_bits") defer tk.MustExec("drop database if exists test_auto_random_bits") @@ -948,8 +977,8 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { tk.MustExec("drop table if exists t") extractAllHandles := func() []int64 { - allHds, err := ddltestutil.ExtractAllTableHandles(tk.Se, "test_auto_random_bits", "t") - c.Assert(err, IsNil) + allHds, err := ddltestutil.ExtractAllTableHandles(tk.Session(), "test_auto_random_bits", "t") + require.NoError(t, err) return allHds } @@ -963,18 +992,18 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { tk.MustExec("drop table t") // Test auto random id number. - c.Assert(len(allHandles), Equals, 100) + require.Equal(t, 100, len(allHandles)) // Test the handles are not all zero. allZero := true for _, h := range allHandles { allZero = allZero && (h>>(64-16)) == 0 } - c.Assert(allZero, IsFalse) + require.False(t, allZero) // Test non-shard-bits part of auto random id is monotonic increasing and continuous. orderedHandles := testutil.MaskSortHandles(allHandles, 15, mysql.TypeLonglong) size := int64(len(allHandles)) for i := int64(1); i <= size; i++ { - c.Assert(i, Equals, orderedHandles[i-1]) + require.Equal(t, orderedHandles[i-1], i) } // Test explicit insert. @@ -984,8 +1013,8 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { tk.MustExec(fmt.Sprintf("insert into t values(%d, %d)", i+autoRandBitsUpperBound, i)) } _, err := tk.Exec("insert into t (b) values (0)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error()) + require.Error(t, err) + require.Equal(t, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error(), err.Error()) tk.MustExec("drop table t") // Test overflow. @@ -994,16 +1023,16 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { // so firstly we rebase auto_rand to the position before overflow. tk.MustExec(fmt.Sprintf("insert into t values (%d, %d)", autoRandBitsUpperBound, 1)) _, err = tk.Exec("insert into t (b) values (0)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error()) + require.Error(t, err) + require.Equal(t, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error(), err.Error()) tk.MustExec("drop table t") tk.MustExec("create table t (a bigint primary key auto_random(15), b int)") tk.MustExec("insert into t values (1, 2)") tk.MustExec(fmt.Sprintf("update t set a = %d where a = 1", autoRandBitsUpperBound)) _, err = tk.Exec("insert into t (b) values (0)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error()) + require.Error(t, err) + require.Equal(t, autoid.ErrAutoRandReadFailed.GenWithStackByArgs().Error(), err.Error()) tk.MustExec("drop table t") // Test insert negative integers explicitly won't trigger rebase. @@ -1016,10 +1045,10 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { orderedHandles = testutil.MaskSortHandles(extractAllHandles(), 15, mysql.TypeLonglong) size = int64(len(allHandles)) for i := int64(0); i < 100; i++ { - c.Assert(orderedHandles[i], Equals, i-100) + require.Equal(t, i-100, orderedHandles[i]) } for i := int64(100); i < size; i++ { - c.Assert(orderedHandles[i], Equals, i-99) + require.Equal(t, i-99, orderedHandles[i]) } tk.MustExec("drop table t") @@ -1030,7 +1059,7 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { } for _, h := range extractAllHandles() { // Sign bit should be reserved. - c.Assert(h > 0, IsTrue) + require.True(t, h > 0) } tk.MustExec("drop table t") @@ -1043,7 +1072,7 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { signBitUnused = signBitUnused && (h > 0) } // Sign bit should be used for shard. - c.Assert(signBitUnused, IsFalse) + require.False(t, signBitUnused) tk.MustExec("drop table t;") // Test rename table does not affect incremental part of auto_random ID. @@ -1064,44 +1093,46 @@ func (s *testAutoRandomSuite) TestAutoRandomBitsData(c *C) { for _, h := range extractAllHandles() { uniqueHandles[h&((1<<(63-5))-1)] = struct{}{} } - c.Assert(len(uniqueHandles), Equals, 30) + require.Equal(t, 30, len(uniqueHandles)) tk.MustExec("drop database test_auto_random_bits_rename;") tk.MustExec("drop table t;") } -func (s *testAutoRandomSuite) TestAutoRandomTableOption(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomTableOption(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // test table option is auto-random tk.MustExec("drop table if exists auto_random_table_option") tk.MustExec("create table auto_random_table_option (a bigint auto_random(5) key) auto_random_base = 1000") - t, err := domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("auto_random_table_option")) - c.Assert(err, IsNil) - c.Assert(t.Meta().AutoRandID, Equals, int64(1000)) + tt, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("auto_random_table_option")) + require.NoError(t, err) + require.Equal(t, int64(1000), tt.Meta().AutoRandID) tk.MustExec("insert into auto_random_table_option values (),(),(),(),()") - allHandles, err := ddltestutil.ExtractAllTableHandles(tk.Se, "test", "auto_random_table_option") - c.Assert(err, IsNil) - c.Assert(len(allHandles), Equals, 5) + allHandles, err := ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "auto_random_table_option") + require.NoError(t, err) + require.Equal(t, 5, len(allHandles)) // Test non-shard-bits part of auto random id is monotonic increasing and continuous. orderedHandles := testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) size := int64(len(allHandles)) for i := int64(0); i < size; i++ { - c.Assert(i+1000, Equals, orderedHandles[i]) + require.Equal(t, orderedHandles[i], i+1000) } tk.MustExec("drop table if exists alter_table_auto_random_option") tk.MustExec("create table alter_table_auto_random_option (a bigint primary key auto_random(4), b int)") - t, err = domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("alter_table_auto_random_option")) - c.Assert(err, IsNil) - c.Assert(t.Meta().AutoRandID, Equals, int64(0)) + tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("alter_table_auto_random_option")) + require.NoError(t, err) + require.Equal(t, int64(0), tt.Meta().AutoRandID) tk.MustExec("insert into alter_table_auto_random_option values(),(),(),(),()") - allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Se, "test", "alter_table_auto_random_option") - c.Assert(err, IsNil) + allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "alter_table_auto_random_option") + require.NoError(t, err) orderedHandles = testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) size = int64(len(allHandles)) for i := int64(0); i < size; i++ { - c.Assert(orderedHandles[i], Equals, i+1) + require.Equal(t, i+1, orderedHandles[i]) } tk.MustExec("delete from alter_table_auto_random_option") @@ -1110,24 +1141,24 @@ func (s *testAutoRandomSuite) TestAutoRandomTableOption(c *C) { // value is not what we rebased, because the local cache is dropped, here we choose // a quite big value to do this. tk.MustExec("alter table alter_table_auto_random_option auto_random_base = 3000000") - t, err = domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("alter_table_auto_random_option")) - c.Assert(err, IsNil) - c.Assert(t.Meta().AutoRandID, Equals, int64(3000000)) + tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("alter_table_auto_random_option")) + require.NoError(t, err) + require.Equal(t, int64(3000000), tt.Meta().AutoRandID) tk.MustExec("insert into alter_table_auto_random_option values(),(),(),(),()") - allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Se, "test", "alter_table_auto_random_option") - c.Assert(err, IsNil) + allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "alter_table_auto_random_option") + require.NoError(t, err) orderedHandles = testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) size = int64(len(allHandles)) for i := int64(0); i < size; i++ { - c.Assert(orderedHandles[i], Equals, i+3000000) + require.Equal(t, i+3000000, orderedHandles[i]) } tk.MustExec("drop table alter_table_auto_random_option") // Alter auto_random_base on non auto_random table. tk.MustExec("create table alter_auto_random_normal (a int)") _, err = tk.Exec("alter table alter_auto_random_normal auto_random_base = 100") - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), autoid.AutoRandomRebaseNotApplicable), IsTrue, Commentf(err.Error())) + require.Error(t, err) + require.Contains(t, err.Error(), autoid.AutoRandomRebaseNotApplicable) } // Test filter different kind of allocators. @@ -1136,8 +1167,10 @@ func (s *testAutoRandomSuite) TestAutoRandomTableOption(c *C) { // 2: ActionRebaseAutoID : it will drop row-id-type allocator. // 3: ActionModifyTableAutoIdCache : it will drop row-id-type allocator. // 3: ActionRebaseAutoRandomBase : it will drop auto-rand-type allocator. -func (s *testAutoRandomSuite) TestFilterDifferentAllocators(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestFilterDifferentAllocators(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") @@ -1145,33 +1178,33 @@ func (s *testAutoRandomSuite) TestFilterDifferentAllocators(c *C) { tk.MustExec("create table t(a bigint auto_random(5) key, b int auto_increment unique)") tk.MustExec("insert into t values()") tk.MustQuery("select b from t").Check(testkit.Rows("1")) - allHandles, err := ddltestutil.ExtractAllTableHandles(tk.Se, "test", "t") - c.Assert(err, IsNil) - c.Assert(len(allHandles), Equals, 1) + allHandles, err := ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "t") + require.NoError(t, err) + require.Equal(t, 1, len(allHandles)) orderedHandles := testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) - c.Assert(orderedHandles[0], Equals, int64(1)) + require.Equal(t, int64(1), orderedHandles[0]) tk.MustExec("delete from t") // Test rebase auto_increment. tk.MustExec("alter table t auto_increment 3000000") tk.MustExec("insert into t values()") tk.MustQuery("select b from t").Check(testkit.Rows("3000000")) - allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Se, "test", "t") - c.Assert(err, IsNil) - c.Assert(len(allHandles), Equals, 1) + allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "t") + require.NoError(t, err) + require.Equal(t, 1, len(allHandles)) orderedHandles = testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) - c.Assert(orderedHandles[0], Equals, int64(2)) + require.Equal(t, int64(2), orderedHandles[0]) tk.MustExec("delete from t") // Test rebase auto_random. tk.MustExec("alter table t auto_random_base 3000000") tk.MustExec("insert into t values()") tk.MustQuery("select b from t").Check(testkit.Rows("3000001")) - allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Se, "test", "t") - c.Assert(err, IsNil) - c.Assert(len(allHandles), Equals, 1) + allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "t") + require.NoError(t, err) + require.Equal(t, 1, len(allHandles)) orderedHandles = testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) - c.Assert(orderedHandles[0], Equals, int64(3000000)) + require.Equal(t, int64(3000000), orderedHandles[0]) tk.MustExec("delete from t") // Test rename table. @@ -1179,17 +1212,19 @@ func (s *testAutoRandomSuite) TestFilterDifferentAllocators(c *C) { tk.MustExec("insert into t1 values()") res := tk.MustQuery("select b from t1") strInt64, err := strconv.ParseInt(res.Rows()[0][0].(string), 10, 64) - c.Assert(err, IsNil) - c.Assert(strInt64, Greater, int64(3000002)) - allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Se, "test", "t1") - c.Assert(err, IsNil) - c.Assert(len(allHandles), Equals, 1) + require.NoError(t, err) + require.Greater(t, strInt64, int64(3000002)) + allHandles, err = ddltestutil.ExtractAllTableHandles(tk.Session(), "test", "t1") + require.NoError(t, err) + require.Equal(t, 1, len(allHandles)) orderedHandles = testutil.MaskSortHandles(allHandles, 5, mysql.TypeLonglong) - c.Assert(orderedHandles[0], Greater, int64(3000001)) + require.Greater(t, orderedHandles[0], int64(3000001)) } -func (s *testSuite6) TestMaxHandleAddIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMaxHandleAddIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a bigint PRIMARY KEY, b int)") @@ -1205,26 +1240,28 @@ func (s *testSuite6) TestMaxHandleAddIndex(c *C) { tk.MustExec("admin check table t1") } -func (s *testSerialSuite) TestSetDDLReorgWorkerCnt(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetDDLReorgWorkerCnt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - err := ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgWorkerCounter(), Equals, int32(variable.DefTiDBDDLReorgWorkerCount)) + err := ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(variable.DefTiDBDDLReorgWorkerCount), variable.GetDDLReorgWorkerCounter()) tk.MustExec("set @@global.tidb_ddl_reorg_worker_cnt = 1") - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgWorkerCounter(), Equals, int32(1)) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(1), variable.GetDDLReorgWorkerCounter()) tk.MustExec("set @@global.tidb_ddl_reorg_worker_cnt = 100") - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgWorkerCounter(), Equals, int32(100)) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(100), variable.GetDDLReorgWorkerCounter()) _, err = tk.Exec("set @@global.tidb_ddl_reorg_worker_cnt = invalid_val") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), "err %v", err) tk.MustExec("set @@global.tidb_ddl_reorg_worker_cnt = 100") - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgWorkerCounter(), Equals, int32(100)) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(100), variable.GetDDLReorgWorkerCounter()) tk.MustExec("set @@global.tidb_ddl_reorg_worker_cnt = -1") tk.MustQuery("SHOW WARNINGS").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_ddl_reorg_worker_cnt value: '-1'")) tk.MustQuery("select @@global.tidb_ddl_reorg_worker_cnt").Check(testkit.Rows("1")) @@ -1244,29 +1281,31 @@ func (s *testSerialSuite) TestSetDDLReorgWorkerCnt(c *C) { tk.MustQuery("select @@global.tidb_ddl_reorg_worker_cnt").Check(testkit.Rows("256")) } -func (s *testSerialSuite) TestSetDDLReorgBatchSize(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetDDLReorgBatchSize(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - err := ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgBatchSize(), Equals, int32(variable.DefTiDBDDLReorgBatchSize)) + err := ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(variable.DefTiDBDDLReorgBatchSize), variable.GetDDLReorgBatchSize()) tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 1") tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_ddl_reorg_batch_size value: '1'")) - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgBatchSize(), Equals, variable.MinDDLReorgBatchSize) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, variable.MinDDLReorgBatchSize, variable.GetDDLReorgBatchSize()) tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_reorg_batch_size = %v", variable.MaxDDLReorgBatchSize+1)) tk.MustQuery("show warnings;").Check(testkit.Rows(fmt.Sprintf("Warning 1292 Truncated incorrect tidb_ddl_reorg_batch_size value: '%d'", variable.MaxDDLReorgBatchSize+1))) - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgBatchSize(), Equals, variable.MaxDDLReorgBatchSize) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, variable.MaxDDLReorgBatchSize, variable.GetDDLReorgBatchSize()) _, err = tk.Exec("set @@global.tidb_ddl_reorg_batch_size = invalid_val") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), "err %v", err) tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = 100") - err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLReorgBatchSize(), Equals, int32(100)) + err = ddlutil.LoadDDLReorgVars(context.Background(), tk.Session()) + require.NoError(t, err) + require.Equal(t, int32(100), variable.GetDDLReorgBatchSize()) tk.MustExec("set @@global.tidb_ddl_reorg_batch_size = -1") tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_ddl_reorg_batch_size value: '-1'")) @@ -1281,77 +1320,81 @@ func (s *testSerialSuite) TestSetDDLReorgBatchSize(c *C) { res.Check(testkit.Rows("1000")) } -func (s *testSuite6) TestIllegalFunctionCall4GeneratedColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIllegalFunctionCall4GeneratedColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test create an exist database _, err := tk.Exec("CREATE database test") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("create table t1 (b double generated always as (rand()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error(), err.Error()) _, err = tk.Exec("create table t1 (a varchar(64), b varchar(1024) generated always as (load_file(a)) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error(), err.Error()) _, err = tk.Exec("create table t1 (a datetime generated always as (curdate()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error(), err.Error()) _, err = tk.Exec("create table t1 (a datetime generated always as (current_time()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error(), err.Error()) _, err = tk.Exec("create table t1 (a datetime generated always as (current_timestamp()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error(), err.Error()) _, err = tk.Exec("create table t1 (a datetime, b varchar(10) generated always as (localtime()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error(), err.Error()) _, err = tk.Exec("create table t1 (a varchar(1024) generated always as (uuid()) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("a").Error(), err.Error()) _, err = tk.Exec("create table t1 (a varchar(1024), b varchar(1024) generated always as (is_free_lock(a)) virtual);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("b").Error(), err.Error()) tk.MustExec("create table t1 (a bigint not null primary key auto_increment, b bigint, c bigint as (b + 1));") _, err = tk.Exec("alter table t1 add column d varchar(1024) generated always as (database());") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("d").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("d").Error(), err.Error()) tk.MustExec("alter table t1 add column d bigint generated always as (b + 1); ") _, err = tk.Exec("alter table t1 modify column d bigint generated always as (connection_id());") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("d").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("d").Error(), err.Error()) _, err = tk.Exec("alter table t1 change column c cc bigint generated always as (connection_id());") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("cc").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnFunctionIsNotAllowed.GenWithStackByArgs("cc").Error(), err.Error()) } -func (s *testSuite6) TestGeneratedColumnRelatedDDL(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGeneratedColumnRelatedDDL(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test create an exist database _, err := tk.Exec("CREATE database test") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("create table t1 (a bigint not null primary key auto_increment, b bigint as (a + 1));") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("b").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("b").Error(), err.Error()) tk.MustExec("create table t1 (a bigint not null primary key auto_increment, b bigint, c bigint as (b + 1));") _, err = tk.Exec("alter table t1 add column d bigint generated always as (a + 1);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("d").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("d").Error(), err.Error()) tk.MustExec("alter table t1 add column d bigint generated always as (b + 1);") _, err = tk.Exec("alter table t1 modify column d bigint generated always as (a + 1);") - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("d").Error()) + require.Equal(t, dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("d").Error(), err.Error()) // This mysql compatibility check can be disabled using tidb_enable_auto_increment_in_generated tk.MustExec("set session tidb_enable_auto_increment_in_generated = 1;") tk.MustExec("alter table t1 modify column d bigint generated always as (a + 1);") _, err = tk.Exec("alter table t1 add column e bigint as (z + 1);") - c.Assert(err.Error(), Equals, ddl.ErrBadField.GenWithStackByArgs("z", "generated column function").Error()) + require.Equal(t, dbterror.ErrBadField.GenWithStackByArgs("z", "generated column function").Error(), err.Error()) tk.MustExec("drop table t1;") @@ -1362,48 +1405,52 @@ func (s *testSuite6) TestGeneratedColumnRelatedDDL(c *C) { tk.MustQuery("select * from t1").Check(testkit.Rows("1 2 3")) } -func (s *testSuite6) TestSetDDLErrorCountLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetDDLErrorCountLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - err := ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLErrorCountLimit(), Equals, int64(variable.DefTiDBDDLErrorCountLimit)) + err := ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) + require.Equal(t, int64(variable.DefTiDBDDLErrorCountLimit), variable.GetDDLErrorCountLimit()) tk.MustExec("set @@global.tidb_ddl_error_count_limit = -1") tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_ddl_error_count_limit value: '-1'")) - err = ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLErrorCountLimit(), Equals, int64(0)) + err = ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) + require.Equal(t, int64(0), variable.GetDDLErrorCountLimit()) tk.MustExec(fmt.Sprintf("set @@global.tidb_ddl_error_count_limit = %v", uint64(math.MaxInt64)+1)) tk.MustQuery("show warnings;").Check(testkit.Rows(fmt.Sprintf("Warning 1292 Truncated incorrect tidb_ddl_error_count_limit value: '%d'", uint64(math.MaxInt64)+1))) - err = ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLErrorCountLimit(), Equals, int64(math.MaxInt64)) + err = ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) + require.Equal(t, int64(math.MaxInt64), variable.GetDDLErrorCountLimit()) _, err = tk.Exec("set @@global.tidb_ddl_error_count_limit = invalid_val") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), "err %v", err) tk.MustExec("set @@global.tidb_ddl_error_count_limit = 100") - err = ddlutil.LoadDDLVars(tk.Se) - c.Assert(err, IsNil) - c.Assert(variable.GetDDLErrorCountLimit(), Equals, int64(100)) + err = ddlutil.LoadDDLVars(tk.Session()) + require.NoError(t, err) + require.Equal(t, int64(100), variable.GetDDLErrorCountLimit()) res := tk.MustQuery("select @@global.tidb_ddl_error_count_limit") res.Check(testkit.Rows("100")) } // Test issue #9205, fix the precision problem for time type default values // See https://github.com/pingcap/tidb/issues/9205 for details -func (s *testSuite6) TestIssue9205(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue9205(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(c time DEFAULT '12:12:12.8');`) - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` time DEFAULT '12:12:13'\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", )) tk.MustExec(`alter table t add column c1 time default '12:12:12.000000';`) - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` time DEFAULT '12:12:13',\n"+ @@ -1412,7 +1459,7 @@ func (s *testSuite6) TestIssue9205(c *C) { )) tk.MustExec(`alter table t alter column c1 set default '2019-02-01 12:12:10.4';`) - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` time DEFAULT '12:12:13',\n"+ @@ -1421,7 +1468,7 @@ func (s *testSuite6) TestIssue9205(c *C) { )) tk.MustExec(`alter table t modify c1 time DEFAULT '770:12:12.000000';`) - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` time DEFAULT '12:12:13',\n"+ @@ -1430,48 +1477,52 @@ func (s *testSuite6) TestIssue9205(c *C) { )) } -func (s *testSuite6) TestCheckDefaultFsp(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCheckDefaultFsp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) _, err := tk.Exec("create table t ( tt timestamp default now(1));") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tt'") _, err = tk.Exec("create table t ( tt timestamp(1) default current_timestamp);") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tt'") _, err = tk.Exec("create table t ( tt timestamp(1) default now(2));") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tt'") tk.MustExec("create table t ( tt timestamp(1) default now(1));") tk.MustExec("create table t2 ( tt timestamp default current_timestamp());") tk.MustExec("create table t3 ( tt timestamp default current_timestamp(0));") _, err = tk.Exec("alter table t add column ttt timestamp default now(2);") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'ttt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'ttt'") _, err = tk.Exec("alter table t add column ttt timestamp(5) default current_timestamp;") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'ttt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'ttt'") _, err = tk.Exec("alter table t add column ttt timestamp(5) default now(2);") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'ttt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'ttt'") _, err = tk.Exec("alter table t modify column tt timestamp(1) default now();") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tt'") _, err = tk.Exec("alter table t modify column tt timestamp(4) default now(5);") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tt'") _, err = tk.Exec("alter table t change column tt tttt timestamp(4) default now(5);") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tttt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tttt'") _, err = tk.Exec("alter table t change column tt tttt timestamp(1) default now();") - c.Assert(err.Error(), Equals, "[ddl:1067]Invalid default value for 'tttt'") + require.EqualError(t, err, "[ddl:1067]Invalid default value for 'tttt'") } -func (s *testSuite6) TestTimestampMinDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTimestampMinDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tdv;") tk.MustExec("create table tdv(a int);") @@ -1479,12 +1530,18 @@ func (s *testSuite6) TestTimestampMinDefaultValue(c *C) { } // this test will change the fail-point `mockAutoIDChange`, so we move it to the `testRecoverTable` suite -func (s *testRecoverTable) TestRenameTable(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) +func TestRenameTable(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("drop database if exists rename1") + tk.MustExec("drop database if exists rename2") + tk.MustExec("drop database if exists rename3") tk.MustExec("create database rename1") tk.MustExec("create database rename2") @@ -1534,34 +1591,43 @@ func (s *testRecoverTable) TestRenameTable(c *C) { result = tk.MustQuery("select * from rename2.t1") result.Check(testkit.Rows("1", "100000", "100001")) _, err := tk.Exec("insert rename1.t values ()") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("drop database rename1") tk.MustExec("drop database rename2") } -func (s *testSuite6) TestAutoIncrementColumnErrorMessage(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoIncrementColumnErrorMessage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Test create an exist database _, err := tk.Exec("CREATE database test") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("CREATE TABLE t1 (t1_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY);") _, err = tk.Exec("CREATE INDEX idx1 ON t1 ((t1_id + t1_id));") - c.Assert(err.Error(), Equals, ddl.ErrExpressionIndexCanNotRefer.GenWithStackByArgs("idx1").Error()) + require.Equal(t, dbterror.ErrExpressionIndexCanNotRefer.GenWithStackByArgs("idx1").Error(), err.Error()) // This mysql compatibility check can be disabled using tidb_enable_auto_increment_in_generated tk.MustExec("SET SESSION tidb_enable_auto_increment_in_generated = 1;") tk.MustExec("CREATE INDEX idx1 ON t1 ((t1_id + t1_id));") } -func (s *testRecoverTable) TestRenameMultiTables(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) +func TestRenameMultiTables(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("drop database if exists rename1") + tk.MustExec("drop database if exists rename2") + tk.MustExec("drop database if exists rename3") + tk.MustExec("drop database if exists rename4") tk.MustExec("create database rename1") tk.MustExec("create database rename2") @@ -1577,14 +1643,14 @@ func (s *testRecoverTable) TestRenameMultiTables(c *C) { tk.MustExec("insert rename2.t2 values ()") tk.MustExec("drop database rename3") tk.MustExec("insert rename4.t4 values ()") - tk.MustQuery("select * from rename2.t2").Check(testkit.Rows("1", "2")) - tk.MustQuery("select * from rename4.t4").Check(testkit.Rows("1", "2")) + tk.MustQuery("select * from rename2.t2").Check(testkit.Rows("1", "5001")) + tk.MustQuery("select * from rename4.t4").Check(testkit.Rows("1", "5001")) // Rename a table to another table in the same database. tk.MustExec("rename table rename2.t2 to rename2.t1, rename4.t4 to rename4.t3") tk.MustExec("insert rename2.t1 values ()") - tk.MustQuery("select * from rename2.t1").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select * from rename2.t1").Check(testkit.Rows("1", "5001", "10001")) tk.MustExec("insert rename4.t3 values ()") - tk.MustQuery("select * from rename4.t3").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select * from rename4.t3").Check(testkit.Rows("1", "5001", "10001")) tk.MustExec("drop database rename2") tk.MustExec("drop database rename4") @@ -1603,7 +1669,7 @@ func (s *testRecoverTable) TestRenameMultiTables(c *C) { tk.MustExec("use rename3") tk.MustExec("create table rename3.t3 (a int primary key auto_increment)") tk.MustGetErrCode("rename table rename1.t1 to rename1.t2, rename1.t1 to rename3.t3", errno.ErrTableExists) - tk.MustGetErrCode("rename table rename1.t1 to rename1.t2, rename1.t1 to rename3.t4", errno.ErrFileNotFound) + tk.MustGetErrCode("rename table rename1.t1 to rename1.t2, rename1.t1 to rename3.t4", errno.ErrNoSuchTable) tk.MustExec("drop database rename1") tk.MustExec("drop database rename2") tk.MustExec("drop database rename3") diff --git a/executor/delete.go b/executor/delete.go index 2d4425653c090..c327236ee0f18 100644 --- a/executor/delete.go +++ b/executor/delete.go @@ -122,7 +122,7 @@ func (e *DeleteExec) deleteSingleTableByChunk(ctx context.Context) error { datumRow := make([]types.Datum, 0, len(fields)) for i, field := range fields { - if columns[i].ID == model.ExtraPidColID { + if columns[i].ID == model.ExtraPidColID || columns[i].ID == model.ExtraPhysTblID { continue } @@ -159,6 +159,9 @@ func (e *DeleteExec) doBatchDelete(ctx context.Context) error { func (e *DeleteExec) composeTblRowMap(tblRowMap tableRowMapType, colPosInfos []plannercore.TblColPosInfo, joinedRow []types.Datum) error { // iterate all the joined tables, and got the copresonding rows in joinedRow. for _, info := range colPosInfos { + if unmatchedOuterRow(info, joinedRow) { + continue + } if tblRowMap[info.TblID] == nil { tblRowMap[info.TblID] = kv.NewHandleMap() } diff --git a/executor/distsql.go b/executor/distsql.go index 1c31130dc53b5..25a0c8612c0c2 100644 --- a/executor/distsql.go +++ b/executor/distsql.go @@ -21,6 +21,7 @@ import ( "runtime" "runtime/trace" "sort" + "strings" "sync" "sync/atomic" "time" @@ -48,6 +49,7 @@ import ( "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/logutil/consistency" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tipb/go-tipb" @@ -194,25 +196,38 @@ type IndexReaderExecutor struct { memTracker *memory.Tracker selectResultHook // for testing + + // If dummy flag is set, this is not a real IndexReader, it just provides the KV ranges for UnionScan. + // Used by the temporary table, cached table. + dummy bool +} + +// Table implements the dataSourceExecutor interface. +func (e *IndexReaderExecutor) Table() table.Table { + return e.table +} + +func (e *IndexReaderExecutor) setDummy() { + e.dummy = true } // Close clears all resources hold by current object. func (e *IndexReaderExecutor) Close() (err error) { - if e.table != nil && e.table.Meta().TempTableType != model.TempTableNone { - return nil - } - if e.result != nil { err = e.result.Close() } e.result = nil + e.kvRanges = e.kvRanges[:0] + if e.dummy { + return nil + } e.ctx.StoreQueryFeedback(e.feedback) return err } // Next implements the Executor Next interface. func (e *IndexReaderExecutor) Next(ctx context.Context, req *chunk.Chunk) error { - if e.table != nil && e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { req.Reset() return nil } @@ -282,7 +297,7 @@ func (e *IndexReaderExecutor) open(ctx context.Context, kvRanges []kv.KeyRange) // Treat temporary table as dummy table, avoid sending distsql request to TiKV. // In a test case IndexReaderExecutor is mocked and e.table is nil. // Avoid sending distsql request to TIKV. - if e.table != nil && e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { return nil } @@ -335,7 +350,7 @@ type IndexLookUpExecutor struct { partitionTableMode bool // if this executor is accessing a partition table prunedPartitions []table.PhysicalTable // partition tables need to access partitionRangeMap map[int64][]*ranger.Range - partitionKVRanges [][]kv.KeyRange // kvRanges of each partition table + partitionKVRanges [][]kv.KeyRange // kvRanges of each prunedPartitions // All fields above are immutable. @@ -361,6 +376,7 @@ type IndexLookUpExecutor struct { indexStreaming bool tableStreaming bool + indexPaging bool corColInIdxSide bool corColInTblSide bool @@ -374,11 +390,12 @@ type IndexLookUpExecutor struct { stats *IndexLookUpRunTimeStats - // extraPIDColumnIndex is used for partition reader to add an extra partition ID column, default -1 - extraPIDColumnIndex offsetOptional - // cancelFunc is called when close the executor cancelFunc context.CancelFunc + + // If dummy flag is set, this is not a real IndexLookUpReader, it just provides the KV ranges for UnionScan. + // Used by the temporary table, cached table. + dummy bool } type getHandleType int8 @@ -394,6 +411,15 @@ type checkIndexValue struct { idxTblCols []*table.Column } +// Table implements the dataSourceExecutor interface. +func (e *IndexLookUpExecutor) Table() table.Table { + return e.table +} + +func (e *IndexLookUpExecutor) setDummy() { + e.dummy = true +} + // Open implements the Executor Open interface. func (e *IndexLookUpExecutor) Open(ctx context.Context) error { var err error @@ -410,7 +436,7 @@ func (e *IndexLookUpExecutor) Open(ctx context.Context) error { } // Treat temporary table as dummy table, avoid sending distsql request to TiKV. - if e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { return nil } @@ -560,6 +586,7 @@ func (e *IndexLookUpExecutor) startIndexWorker(ctx context.Context, workCh chan< SetDesc(e.desc). SetKeepOrder(e.keepOrder). SetStreaming(e.indexStreaming). + SetPaging(e.indexPaging). SetReadReplicaScope(e.readReplicaScope). SetIsStaleness(e.isStaleness). SetFromSessionVars(e.ctx.GetSessionVars()). @@ -577,6 +604,9 @@ func (e *IndexLookUpExecutor) startIndexWorker(ctx context.Context, workCh chan< if finished { break } + if worker.PushedLimit != nil && worker.scannedKeys >= worker.PushedLimit.Count+worker.PushedLimit.Offset { + break + } // init kvReq, result and worker for this partition kvReq, err := builder.SetKeyRanges(kvRange).Build() @@ -599,7 +629,7 @@ func (e *IndexLookUpExecutor) startIndexWorker(ctx context.Context, workCh chan< // fetch data from this partition ctx1, cancel := context.WithCancel(ctx) - _, fetchErr := worker.fetchHandles(ctx1, result) + fetchErr := worker.fetchHandles(ctx1, result) if fetchErr != nil { // this error is synced in fetchHandles(), don't sync it again e.feedback.Invalidate() } @@ -651,18 +681,17 @@ func (e *IndexLookUpExecutor) buildTableReader(ctx context.Context, task *lookup table = task.partitionTable } tableReaderExec := &TableReaderExecutor{ - baseExecutor: newBaseExecutor(e.ctx, e.schema, e.getTableRootPlanID()), - table: table, - dagPB: e.tableRequest, - startTS: e.startTS, - readReplicaScope: e.readReplicaScope, - isStaleness: e.isStaleness, - columns: e.columns, - streaming: e.tableStreaming, - feedback: statistics.NewQueryFeedback(0, nil, 0, false), - corColInFilter: e.corColInTblSide, - plans: e.tblPlans, - extraPIDColumnIndex: e.extraPIDColumnIndex, + baseExecutor: newBaseExecutor(e.ctx, e.schema, e.getTableRootPlanID()), + table: table, + dagPB: e.tableRequest, + startTS: e.startTS, + readReplicaScope: e.readReplicaScope, + isStaleness: e.isStaleness, + columns: e.columns, + streaming: e.tableStreaming, + feedback: statistics.NewQueryFeedback(0, nil, 0, false), + corColInFilter: e.corColInTblSide, + plans: e.tblPlans, } tableReaderExec.buildVirtualColumnInfo() tableReader, err := e.dataReaderBuilder.buildTableReaderFromHandles(ctx, tableReaderExec, task.handles, true) @@ -675,7 +704,8 @@ func (e *IndexLookUpExecutor) buildTableReader(ctx context.Context, task *lookup // Close implements Exec Close interface. func (e *IndexLookUpExecutor) Close() error { - if e.table.Meta().TempTableType != model.TempTableNone { + e.kvRanges = e.kvRanges[:0] + if e.dummy { return nil } @@ -703,7 +733,7 @@ func (e *IndexLookUpExecutor) Close() error { // Next implements Exec Next interface. func (e *IndexLookUpExecutor) Next(ctx context.Context, req *chunk.Chunk) error { - if e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { req.Reset() return nil } @@ -796,6 +826,8 @@ type indexWorker struct { *checkIndexValue // PushedLimit is used to skip the preceding and tailing handles when Limit is sunk into IndexLookUpReader. PushedLimit *plannercore.PushedDownLimit + // scannedKeys indicates how many keys be scanned + scannedKeys uint64 // partitionTable indicates if this worker is accessing a particular partition table. partitionTable table.PhysicalTable } @@ -811,7 +843,7 @@ func (w *indexWorker) syncErr(err error) { // fetchHandles fetches a batch of handles from index data and builds the index lookup tasks. // The tasks are sent to workCh to be further processed by tableWorker, and sent to e.resultCh // at the same time to keep data ordered. -func (w *indexWorker) fetchHandles(ctx context.Context, result distsql.SelectResult) (count uint64, err error) { +func (w *indexWorker) fetchHandles(ctx context.Context, result distsql.SelectResult) (err error) { defer func() { if r := recover(); r != nil { buf := make([]byte, 4096) @@ -835,23 +867,22 @@ func (w *indexWorker) fetchHandles(ctx context.Context, result distsql.SelectRes } for { startTime := time.Now() - handles, retChunk, scannedKeys, err := w.extractTaskHandles(ctx, chk, result, count) + handles, retChunk, err := w.extractTaskHandles(ctx, chk, result) finishFetch := time.Now() if err != nil { w.syncErr(err) - return count, err + return err } - count += scannedKeys if len(handles) == 0 { - return count, nil + return nil } task := w.buildTableTask(handles, retChunk) finishBuild := time.Now() select { case <-ctx.Done(): - return count, nil + return nil case <-w.finished: - return count, nil + return nil case w.workCh <- task: w.resultCh <- task } @@ -863,8 +894,8 @@ func (w *indexWorker) fetchHandles(ctx context.Context, result distsql.SelectRes } } -func (w *indexWorker) extractTaskHandles(ctx context.Context, chk *chunk.Chunk, idxResult distsql.SelectResult, count uint64) ( - handles []kv.Handle, retChk *chunk.Chunk, scannedKeys uint64, err error) { +func (w *indexWorker) extractTaskHandles(ctx context.Context, chk *chunk.Chunk, idxResult distsql.SelectResult) ( + handles []kv.Handle, retChk *chunk.Chunk, err error) { numColsWithoutPid := chk.NumCols() if w.idxLookup.index.Global { numColsWithoutPid = numColsWithoutPid - 1 @@ -882,10 +913,10 @@ func (w *indexWorker) extractTaskHandles(ctx context.Context, chk *chunk.Chunk, for len(handles) < w.batchSize { requiredRows := w.batchSize - len(handles) if checkLimit { - if w.PushedLimit.Offset+w.PushedLimit.Count <= scannedKeys+count { - return handles, nil, scannedKeys, nil + if w.PushedLimit.Offset+w.PushedLimit.Count <= w.scannedKeys { + return handles, nil, nil } - leftCnt := w.PushedLimit.Offset + w.PushedLimit.Count - scannedKeys - count + leftCnt := w.PushedLimit.Offset + w.PushedLimit.Count - w.scannedKeys if uint64(requiredRows) > leftCnt { requiredRows = int(leftCnt) } @@ -894,29 +925,28 @@ func (w *indexWorker) extractTaskHandles(ctx context.Context, chk *chunk.Chunk, startTime := time.Now() err = errors.Trace(idxResult.Next(ctx, chk)) if err != nil { - return handles, nil, scannedKeys, err + return handles, nil, err } if w.idxLookup.stats != nil { w.idxLookup.stats.indexScanBasicStats.Record(time.Since(startTime), chk.NumRows()) } if chk.NumRows() == 0 { - return handles, retChk, scannedKeys, nil + return handles, retChk, nil } for i := 0; i < chk.NumRows(); i++ { - scannedKeys++ + w.scannedKeys++ if checkLimit { - if (count + scannedKeys) <= w.PushedLimit.Offset { - // Skip the preceding Offset handles. + if w.scannedKeys <= w.PushedLimit.Offset { continue } - if (count + scannedKeys) > (w.PushedLimit.Offset + w.PushedLimit.Count) { + if w.scannedKeys > (w.PushedLimit.Offset + w.PushedLimit.Count) { // Skip the handles after Offset+Count. - return handles, nil, scannedKeys, nil + return handles, nil, nil } } h, err := w.idxLookup.getHandle(chk.GetRow(i), handleOffset, w.idxLookup.isCommonHandle(), getHandleFromIndex) if err != nil { - return handles, retChk, scannedKeys, err + return handles, retChk, err } handles = append(handles, h) } @@ -931,7 +961,7 @@ func (w *indexWorker) extractTaskHandles(ctx context.Context, chk *chunk.Chunk, if w.batchSize > w.maxBatchSize { w.batchSize = w.maxBatchSize } - return handles, retChk, scannedKeys, nil + return handles, retChk, nil } func (w *indexWorker) buildTableTask(handles []kv.Handle, retChk *chunk.Chunk) *lookupTableTask { @@ -1137,15 +1167,52 @@ func (w *tableWorker) compareData(ctx context.Context, task *lookupTableTask, ta collators = append(collators, collate.GetCollator(tp.Collate)) } + ir := func() *consistency.Reporter { + return &consistency.Reporter{ + HandleEncode: func(handle kv.Handle) kv.Key { + return tablecodec.EncodeRecordKey(w.idxLookup.table.RecordPrefix(), handle) + }, + IndexEncode: func(idxRow *consistency.RecordData) kv.Key { + var idx table.Index + for _, v := range w.idxLookup.table.Indices() { + if strings.EqualFold(v.Meta().Name.String(), w.idxLookup.index.Name.O) { + idx = v + break + } + } + if idx == nil { + return nil + } + k, _, err := idx.GenIndexKey(w.idxLookup.ctx.GetSessionVars().StmtCtx, idxRow.Values[:len(idx.Meta().Columns)], idxRow.Handle, nil) + if err != nil { + return nil + } + return k + }, + Tbl: tblInfo, + Idx: w.idxLookup.index, + Sctx: w.idxLookup.ctx, + } + } + for { err := Next(ctx, tableReader, chk) if err != nil { return errors.Trace(err) } + + // If ctx is cancelled, `Next` may return empty result when the actual data is not empty. To avoid producing + // false-positive error logs that cause confusion, exit in this case. + select { + case <-ctx.Done(): + return nil + default: + } + if chk.NumRows() == 0 { task.indexOrder.Range(func(h kv.Handle, val interface{}) bool { idxRow := task.idxRows.GetRow(val.(int)) - err = ErrDataInConsistentExtraIndex.GenWithStackByArgs(h, idxRow.GetDatum(0, w.idxColTps[0]), nil) + err = ir().ReportAdminCheckInconsistent(ctx, h, &consistency.RecordData{Handle: h, Values: getDatumRow(&idxRow, w.idxColTps)}, nil) return false }) if err != nil { @@ -1180,12 +1247,32 @@ func (w *tableWorker) compareData(ctx context.Context, task *lookupTableTask, ta tablecodec.TruncateIndexValue(&idxVal, w.idxLookup.index.Columns[i], col.ColumnInfo) cmpRes, err := idxVal.Compare(sctx, &vals[i], collators[i]) if err != nil { - return ErrDataInConsistentMisMatchIndex.GenWithStackByArgs(col.Name, - handle, idxRow.GetDatum(i, tp), vals[i], err) + fts := make([]*types.FieldType, 0, len(w.idxTblCols)) + for _, c := range w.idxTblCols { + fts = append(fts, &c.FieldType) + } + return ir().ReportAdminCheckInconsistentWithColInfo(ctx, + handle, + col.Name.O, + idxRow.GetDatum(i, tp), + vals[i], + err, + &consistency.RecordData{Handle: handle, Values: getDatumRow(&idxRow, fts)}, + ) } if cmpRes != 0 { - return ErrDataInConsistentMisMatchIndex.GenWithStackByArgs(col.Name, - handle, idxRow.GetDatum(i, tp), vals[i], err) + fts := make([]*types.FieldType, 0, len(w.idxTblCols)) + for _, c := range w.idxTblCols { + fts = append(fts, &c.FieldType) + } + return ir().ReportAdminCheckInconsistentWithColInfo(ctx, + handle, + col.Name.O, + idxRow.GetDatum(i, tp), + vals[i], + err, + &consistency.RecordData{Handle: handle, Values: getDatumRow(&idxRow, fts)}, + ) } } } @@ -1193,6 +1280,18 @@ func (w *tableWorker) compareData(ctx context.Context, task *lookupTableTask, ta return nil } +func getDatumRow(r *chunk.Row, fields []*types.FieldType) []types.Datum { + datumRow := make([]types.Datum, 0, r.Chunk().NumCols()) + for colIdx := 0; colIdx < r.Chunk().NumCols(); colIdx++ { + if colIdx >= len(fields) { + break + } + datum := r.GetDatum(colIdx, fields[colIdx]) + datumRow = append(datumRow, datum) + } + return datumRow +} + // executeTask executes the table look up tasks. We will construct a table reader and send request by handles. // Then we hold the returning rows and finish this task. func (w *tableWorker) executeTask(ctx context.Context, task *lookupTableTask) error { @@ -1252,7 +1351,8 @@ func (w *tableWorker) executeTask(ctx context.Context, task *lookupTableTask) er sort.Sort(task) } - if handleCnt != len(task.rows) && !util.HasCancelled(ctx) { + if handleCnt != len(task.rows) && !util.HasCancelled(ctx) && + !w.idxLookup.ctx.GetSessionVars().StmtCtx.WeakConsistency { if len(w.idxLookup.tblPlans) == 1 { obtainedHandlesMap := kv.NewHandleMap() for _, row := range task.rows { @@ -1262,26 +1362,22 @@ func (w *tableWorker) executeTask(ctx context.Context, task *lookupTableTask) er } obtainedHandlesMap.Set(handle, true) } - - if w.idxLookup.ctx.GetSessionVars().EnableRedactLog { - logutil.Logger(ctx).Error("inconsistent index handles", - zap.String("table_name", w.idxLookup.index.Table.O), - zap.String("index", w.idxLookup.index.Name.O), - zap.Int("index_cnt", handleCnt), - zap.Int("table_cnt", len(task.rows))) - } else { - logutil.Logger(ctx).Error("inconsistent index handles", - zap.String("table_name", w.idxLookup.index.Table.O), - zap.String("index", w.idxLookup.index.Name.O), - zap.Int("index_cnt", handleCnt), zap.Int("table_cnt", len(task.rows)), - zap.String("missing_handles", fmt.Sprint(GetLackHandles(task.handles, obtainedHandlesMap))), - zap.String("total_handles", fmt.Sprint(task.handles))) - } - - // table scan in double read can never has conditions according to convertToIndexScan. - // if this table scan has no condition, the number of rows it returns must equal to the length of handles. - return errors.Errorf("inconsistent index %s handle count %d isn't equal to value count %d", - w.idxLookup.index.Name.O, handleCnt, len(task.rows)) + missHds := GetLackHandles(task.handles, obtainedHandlesMap) + return (&consistency.Reporter{ + HandleEncode: func(hd kv.Handle) kv.Key { + return tablecodec.EncodeRecordKey(w.idxLookup.table.RecordPrefix(), hd) + }, + Tbl: w.idxLookup.table.Meta(), + Idx: w.idxLookup.index, + Sctx: w.idxLookup.ctx, + }).ReportLookupInconsistent(ctx, + handleCnt, + len(task.rows), + missHds, + task.handles, + nil, + //missRecords, + ) } } diff --git a/executor/distsql_test.go b/executor/distsql_test.go index a832b8913f66c..c8909b6c53326 100644 --- a/executor/distsql_test.go +++ b/executor/distsql_test.go @@ -21,22 +21,24 @@ import ( "math/rand" "runtime/pprof" "strings" + "testing" "time" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/copr" + "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/israce" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/testutils" ) +// checkGoroutineExists // nolint:unused func checkGoroutineExists(keyword string) bool { buf := new(bytes.Buffer) @@ -49,13 +51,20 @@ func checkGoroutineExists(keyword string) bool { return strings.Contains(str, keyword) } -func (s *testSuite3) TestCopClientSend(c *C) { - c.Skip("not stable") - if _, ok := s.store.GetClient().(*copr.CopClient); !ok { +func TestCopClientSend(t *testing.T) { + t.Skip("not stable") + var cluster testutils.Cluster + store, dom, clean := testkit.CreateMockStoreAndDomain(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + cluster = c + })) + defer clean() + if _, ok := store.GetClient().(*copr.CopClient); !ok { // Make sure the store is tikv store. return } - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table copclient (id int primary key)") @@ -67,53 +76,52 @@ func (s *testSuite3) TestCopClientSend(c *C) { tk.MustExec("insert copclient values " + strings.Join(values, ",")) // Get table ID for split. - dom := domain.GetDomain(tk.Se) is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("copclient")) - c.Assert(err, IsNil) + require.NoError(t, err) tblID := tbl.Meta().ID // Split the table. tableStart := tablecodec.GenTableRecordPrefix(tblID) - s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) + cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 100) ctx := context.Background() // Send coprocessor request when the table split. rs, err := tk.Exec("select sum(id) from copclient") - c.Assert(err, IsNil) + require.NoError(t, err) req := rs.NewChunk(nil) err = rs.Next(ctx, req) - c.Assert(err, IsNil) - c.Assert(req.GetRow(0).GetMyDecimal(0).String(), Equals, "499500") - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + require.Equal(t, "499500", req.GetRow(0).GetMyDecimal(0).String()) + require.NoError(t, rs.Close()) // Split one region. key := tablecodec.EncodeRowKeyWithHandle(tblID, kv.IntHandle(500)) - region, _ := s.cluster.GetRegionByKey(key) - peerID := s.cluster.AllocID() - s.cluster.Split(region.GetId(), s.cluster.AllocID(), key, []uint64{peerID}, peerID) + region, _, _ := cluster.GetRegionByKey(key) + peerID := cluster.AllocID() + cluster.Split(region.GetId(), cluster.AllocID(), key, []uint64{peerID}, peerID) // Check again. rs, err = tk.Exec("select sum(id) from copclient") - c.Assert(err, IsNil) + require.NoError(t, err) req = rs.NewChunk(nil) err = rs.Next(ctx, req) - c.Assert(err, IsNil) - c.Assert(req.GetRow(0).GetMyDecimal(0).String(), Equals, "499500") - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + require.Equal(t, "499500", req.GetRow(0).GetMyDecimal(0).String()) + require.NoError(t, rs.Close()) // Check there is no goroutine leak. rs, err = tk.Exec("select * from copclient order by id") - c.Assert(err, IsNil) + require.NoError(t, err) req = rs.NewChunk(nil) err = rs.Next(ctx, req) - c.Assert(err, IsNil) - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + require.NoError(t, rs.Close()) keyword := "(*copIterator).work" - c.Check(checkGoroutineExists(keyword), IsFalse) + require.False(t, checkGoroutineExists(keyword)) } -func (s *testSuite3) TestGetLackHandles(c *C) { +func TestGetLackHandles(t *testing.T) { expectedHandles := []kv.Handle{kv.IntHandle(1), kv.IntHandle(2), kv.IntHandle(3), kv.IntHandle(4), kv.IntHandle(5), kv.IntHandle(6), kv.IntHandle(7), kv.IntHandle(8), kv.IntHandle(9), kv.IntHandle(10)} handlesMap := kv.NewHandleMap() @@ -124,8 +132,8 @@ func (s *testSuite3) TestGetLackHandles(c *C) { // expected handles 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 // obtained handles 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 diffHandles := executor.GetLackHandles(expectedHandles, handlesMap) - c.Assert(diffHandles, HasLen, 0) - c.Assert(handlesMap.Len(), Equals, 0) + require.Len(t, diffHandles, 0) + require.Equal(t, 0, handlesMap.Len()) // expected handles 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 // obtained handles 2, 3, 4, 6, 7, 8, 9 @@ -136,19 +144,25 @@ func (s *testSuite3) TestGetLackHandles(c *C) { handlesMap.Set(kv.IntHandle(5), true) handlesMap.Set(kv.IntHandle(10), true) diffHandles = executor.GetLackHandles(expectedHandles, handlesMap) - c.Assert(retHandles, DeepEquals, diffHandles) + require.Equal(t, diffHandles, retHandles) // deep equal } -func (s *testSuite3) TestBigIntPK(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBigIntPK(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t(a bigint unsigned primary key, b int, c int, index idx(a, b))") tk.MustExec("insert into t values(1, 1, 1), (9223372036854775807, 2, 2)") tk.MustQuery("select * from t use index(idx) order by a").Check(testkit.Rows("1 1 1", "9223372036854775807 2 2")) } -func (s *testSuite3) TestCorColToRanges(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCorColToRanges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only-full-group-by tk.MustExec("drop table if exists t") @@ -163,8 +177,11 @@ func (s *testSuite3) TestCorColToRanges(c *C) { tk.MustQuery("select t.c in (select count(*) from t s use index(idx), t t1 where s.b = t.a and s.c = t1.a) from t order by 1 desc").Check(testkit.Rows("1", "0", "0", "0", "0", "0", "0", "0", "0")) } -func (s *testSuiteP1) TestUniqueKeyNullValueSelect(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUniqueKeyNullValueSelect(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") // test null in unique-key @@ -189,8 +206,11 @@ func (s *testSuiteP1) TestUniqueKeyNullValueSelect(c *C) { } // TestIssue10178 contains tests for https://github.com/pingcap/tidb/issues/10178 . -func (s *testSuite3) TestIssue10178(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10178(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint unsigned primary key)") @@ -200,58 +220,63 @@ func (s *testSuite3) TestIssue10178(c *C) { tk.MustQuery("select * from t where a < 9223372036854775808").Check(testkit.Rows("9223372036854775807")) } -func (s *testSuite3) TestInconsistentIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInconsistentIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, index idx_a(a))") - is := s.domain.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) idx := tbl.Meta().FindIndexByName("idx_a") idxOp := tables.NewIndex(tbl.Meta().ID, tbl.Meta(), idx) ctx := mock.NewContext() - ctx.Store = s.store + ctx.Store = store for i := 0; i < 10; i++ { tk.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i+10, i)) - c.Assert(tk.QueryToErr("select * from t where a>=0"), IsNil) + require.NoError(t, tk.QueryToErr("select * from t where a>=0")) } for i := 0; i < 10; i++ { tk.MustExec(fmt.Sprintf("update t set a=%d where a=%d", i, i+10)) - c.Assert(tk.QueryToErr("select * from t where a>=0"), IsNil) + require.NoError(t, tk.QueryToErr("select * from t where a>=0")) } for i := 0; i < 10; i++ { - txn, err := s.store.Begin() - c.Assert(err, IsNil) + txn, err := store.Begin() + require.NoError(t, err) _, err = idxOp.Create(ctx, txn, types.MakeDatums(i+10), kv.IntHandle(100+i), nil) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) err = tk.QueryToErr("select * from t use index(idx_a) where a >= 0") - c.Assert(err.Error(), Equals, fmt.Sprintf("inconsistent index idx_a handle count %d isn't equal to value count 10", i+11)) - + require.Equal(t, fmt.Sprintf("[executor:8133]data inconsistency in table: t, index: idx_a, index-count:%d != record-count:10", i+11), err.Error()) // if has other conditions, the inconsistent index check doesn't work. err = tk.QueryToErr("select * from t where a>=0 and b<10") - c.Assert(err, IsNil) + require.NoError(t, err) } // fix inconsistent problem to pass CI for i := 0; i < 10; i++ { - txn, err := s.store.Begin() - c.Assert(err, IsNil) + txn, err := store.Begin() + require.NoError(t, err) err = idxOp.Delete(ctx.GetSessionVars().StmtCtx, txn, types.MakeDatums(i+10), kv.IntHandle(100+i)) - c.Assert(err, IsNil) + require.NoError(t, err) err = txn.Commit(context.Background()) - c.Assert(err, IsNil) + require.NoError(t, err) } } -func (s *testSuite3) TestPushLimitDownIndexLookUpReader(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushLimitDownIndexLookUpReader(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists tbl") tk.MustExec("create table tbl(a int, b int, c int, key idx_b_c(b,c))") @@ -265,16 +290,19 @@ func (s *testSuite3) TestPushLimitDownIndexLookUpReader(c *C) { tk.MustQuery("select * from tbl use index(idx_b_c) where b > 1 and c > 1 limit 2,1").Check(testkit.Rows("4 4 4")) } -func (s *testSuite3) TestPartitionTableIndexLookUpReader(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTableIndexLookUpReader(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(`create table t (a int, b int, key(a)) - partition by range (a) ( - partition p1 values less than (10), - partition p2 values less than (20), - partition p3 values less than (30), - partition p4 values less than (40))`) + partition by range (a) ( + partition p1 values less than (10), + partition p2 values less than (20), + partition p3 values less than (30), + partition p4 values less than (40))`) tk.MustExec(`insert into t values (1, 1), (2, 2), (11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)`) tk.MustExec(`set tidb_partition_prune_mode='dynamic'`) @@ -287,21 +315,24 @@ func (s *testSuite3) TestPartitionTableIndexLookUpReader(c *C) { tk.MustQuery("select * from t where a>=1 and a<15 order by a").Check(testkit.Rows("1 1", "2 2", "11 11", "12 12")) tk.MustQuery("select * from t where a>=1 and a<15 order by a limit 1").Check(testkit.Rows("1 1")) tk.MustQuery("select * from t where a>=1 and a<15 order by a limit 3").Check(testkit.Rows("1 1", "2 2", "11 11")) + tk.MustQuery("select * from t where a>=1 and a<15 limit 3").Check(testkit.Rows("1 1", "2 2", "11 11")) + tk.MustQuery("select * from t where a between 1 and 15 limit 3").Check(testkit.Rows("1 1", "2 2", "11 11")) + tk.MustQuery("select * from t where a between 1 and 15 limit 3 offset 1").Check(testkit.Rows("2 2", "11 11", "12 12")) } -func (s *testSuite3) TestPartitionTableRandomlyIndexLookUpReader(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTableRandomlyIndexLookUpReader(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(`create table t (a int, b int, key(a)) - partition by range (a) ( - partition p1 values less than (10), - partition p2 values less than (20), - partition p3 values less than (30), - partition p4 values less than (40))`) + partition by range (a) ( + partition p1 values less than (10), + partition p2 values less than (20), + partition p3 values less than (30), + partition p4 values less than (40))`) tk.MustExec("create table tnormal (a int, b int, key(a))") values := make([]string, 0, 128) for i := 0; i < 128; i++ { @@ -326,7 +357,7 @@ func (s *testSuite3) TestPartitionTableRandomlyIndexLookUpReader(c *C) { } } -func (s *testSuite3) TestIndexLookUpStats(c *C) { +func TestIndexLookUpStats(t *testing.T) { stats := &executor.IndexLookUpRunTimeStats{ FetchHandleTotal: int64(5 * time.Second), FetchHandle: int64(2 * time.Second), @@ -335,14 +366,17 @@ func (s *testSuite3) TestIndexLookUpStats(c *C) { TableTaskNum: 2, Concurrency: 1, } - c.Assert(stats.String(), Equals, "index_task: {total_time: 5s, fetch_handle: 2s, build: 1s, wait: 2s}, table_task: {total_time: 2s, num: 2, concurrency: 1}") - c.Assert(stats.String(), Equals, stats.Clone().String()) + require.Equal(t, "index_task: {total_time: 5s, fetch_handle: 2s, build: 1s, wait: 2s}, table_task: {total_time: 2s, num: 2, concurrency: 1}", stats.String()) + require.Equal(t, stats.Clone().String(), stats.String()) stats.Merge(stats.Clone()) - c.Assert(stats.String(), Equals, "index_task: {total_time: 10s, fetch_handle: 4s, build: 2s, wait: 4s}, table_task: {total_time: 4s, num: 4, concurrency: 2}") + require.Equal(t, "index_task: {total_time: 10s, fetch_handle: 4s, build: 2s, wait: 4s}, table_task: {total_time: 4s, num: 4, concurrency: 2}", stats.String()) } -func (s *testSuite3) TestIndexLookUpGetResultChunk(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexLookUpGetResultChunk(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists tbl") tk.MustExec("create table tbl(a int, b int, c int, key idx_a(a))") @@ -353,11 +387,11 @@ func (s *testSuite3) TestIndexLookUpGetResultChunk(c *C) { tk.MustQuery("select * from tbl use index(idx_a) where a > 10 order by a asc limit 4,1").Check(testkit.Rows("15 15 15")) } -func (s *testSuite3) TestPartitionTableIndexJoinIndexLookUp(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTableIndexJoinIndexLookUp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec(`create table t (a int, b int, key(a)) partition by hash(a) partitions 4`) diff --git a/executor/errors.go b/executor/errors.go index f6e0f87d08e6b..46d0fdd1ee62d 100644 --- a/executor/errors.go +++ b/executor/errors.go @@ -53,19 +53,19 @@ var ( ErrIllegalPrivilegeLevel = dbterror.ClassExecutor.NewStd(mysql.ErrIllegalPrivilegeLevel) ErrInvalidSplitRegionRanges = dbterror.ClassExecutor.NewStd(mysql.ErrInvalidSplitRegionRanges) ErrViewInvalid = dbterror.ClassExecutor.NewStd(mysql.ErrViewInvalid) + ErrInstanceScope = dbterror.ClassExecutor.NewStd(mysql.ErrInstanceScope) - ErrBRIEBackupFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEBackupFailed) - ErrBRIERestoreFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIERestoreFailed) - ErrBRIEImportFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEImportFailed) - ErrBRIEExportFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEExportFailed) - ErrCTEMaxRecursionDepth = dbterror.ClassExecutor.NewStd(mysql.ErrCTEMaxRecursionDepth) - ErrDataInConsistentExtraIndex = dbterror.ClassExecutor.NewStd(mysql.ErrDataInConsistentExtraIndex) - ErrDataInConsistentMisMatchIndex = dbterror.ClassExecutor.NewStd(mysql.ErrDataInConsistentMisMatchIndex) - ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem) - ErrPluginIsNotLoaded = dbterror.ClassExecutor.NewStd(mysql.ErrPluginIsNotLoaded) - ErrSetPasswordAuthPlugin = dbterror.ClassExecutor.NewStd(mysql.ErrSetPasswordAuthPlugin) - ErrFuncNotEnabled = dbterror.ClassExecutor.NewStdErr(mysql.ErrNotSupportedYet, parser_mysql.Message("%-.32s is not supported. To enable this experimental feature, set '%-.32s' in the configuration file.", nil)) + ErrBRIEBackupFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEBackupFailed) + ErrBRIERestoreFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIERestoreFailed) + ErrBRIEImportFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEImportFailed) + ErrBRIEExportFailed = dbterror.ClassExecutor.NewStd(mysql.ErrBRIEExportFailed) + ErrCTEMaxRecursionDepth = dbterror.ClassExecutor.NewStd(mysql.ErrCTEMaxRecursionDepth) + ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem) + ErrPluginIsNotLoaded = dbterror.ClassExecutor.NewStd(mysql.ErrPluginIsNotLoaded) + ErrSetPasswordAuthPlugin = dbterror.ClassExecutor.NewStd(mysql.ErrSetPasswordAuthPlugin) + ErrFuncNotEnabled = dbterror.ClassExecutor.NewStdErr(mysql.ErrNotSupportedYet, parser_mysql.Message("%-.32s is not supported. To enable this experimental feature, set '%-.32s' in the configuration file.", nil)) + ErrWrongStringLength = dbterror.ClassDDL.NewStd(mysql.ErrWrongStringLength) errUnsupportedFlashbackTmpTable = dbterror.ClassDDL.NewStdErr(mysql.ErrUnsupportedDDLOperation, parser_mysql.Message("Recover/flashback table is not supported on temporary tables", nil)) errTruncateWrongInsertValue = dbterror.ClassTable.NewStdErr(mysql.ErrTruncatedWrongValue, parser_mysql.Message("Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %d", nil)) ) diff --git a/executor/executor.go b/executor/executor.go index eee07f8774ed0..9b491a0a84614 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -45,7 +45,6 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/planner" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/privilege" "github.com/pingcap/tidb/sessionctx" @@ -65,9 +64,11 @@ import ( "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/resourcegrouptag" "github.com/pingcap/tidb/util/topsql" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" tikverr "github.com/tikv/client-go/v2/error" tikvstore "github.com/tikv/client-go/v2/kv" tikvutil "github.com/tikv/client-go/v2/util" + atomicutil "go.uber.org/atomic" "go.uber.org/zap" ) @@ -102,6 +103,21 @@ var ( GlobalDiskUsageTracker *disk.Tracker ) +var ( + _ dataSourceExecutor = &TableReaderExecutor{} + _ dataSourceExecutor = &IndexReaderExecutor{} + _ dataSourceExecutor = &IndexLookUpExecutor{} + _ dataSourceExecutor = &IndexMergeReaderExecutor{} +) + +// dataSourceExecutor is a table DataSource converted Executor. +// Currently, there are TableReader/IndexReader/IndexLookUp/IndexMergeReader. +// Note, partition reader is special and the caller should handle it carefully. +type dataSourceExecutor interface { + Executor + Table() table.Table +} + type baseExecutor struct { ctx sessionctx.Context id int @@ -304,6 +320,16 @@ type CancelDDLJobsExec struct { errs []error } +// Open implements the Executor Open interface. +func (e *CancelDDLJobsExec) Open(ctx context.Context) error { + // We want to use a global transaction to execute the admin command, so we don't use e.ctx here. + errInTxn := kv.RunInNewTxn(context.Background(), e.ctx.GetStore(), true, func(ctx context.Context, txn kv.Transaction) (err error) { + e.errs, err = admin.CancelJobs(txn, e.jobIDs) + return + }) + return errInTxn +} + // Next implements the Executor Next interface. func (e *CancelDDLJobsExec) Next(ctx context.Context, req *chunk.Chunk) error { req.GrowAndReset(e.maxChunkSize) @@ -312,7 +338,7 @@ func (e *CancelDDLJobsExec) Next(ctx context.Context, req *chunk.Chunk) error { } numCurBatch := mathutil.Min(req.Capacity(), len(e.jobIDs)-e.cursor) for i := e.cursor; i < e.cursor+numCurBatch; i++ { - req.AppendString(0, fmt.Sprintf("%d", e.jobIDs[i])) + req.AppendString(0, strconv.FormatInt(e.jobIDs[i], 10)) if e.errs[i] != nil { req.AppendString(1, fmt.Sprintf("error: %v", e.errs[i])) } else { @@ -446,6 +472,7 @@ type DDLJobRetriever struct { is infoschema.InfoSchema activeRoles []*auth.RoleIdentity cacheJobs []*model.Job + TZLoc *time.Location } func (e *DDLJobRetriever) initial(txn kv.Transaction) error { @@ -472,6 +499,16 @@ func (e *DDLJobRetriever) appendJobToChunk(req *chunk.Chunk, job *model.Job, che if job.BinlogInfo.TableInfo != nil { tableName = job.BinlogInfo.TableInfo.Name.L } + if job.BinlogInfo.MultipleTableInfos != nil { + tablenames := new(strings.Builder) + for i, affect := range job.BinlogInfo.MultipleTableInfos { + if i > 0 { + fmt.Fprintf(tablenames, ",") + } + fmt.Fprintf(tablenames, "%s", affect.Name.L) + } + tableName = tablenames.String() + } if len(schemaName) == 0 && job.BinlogInfo.DBInfo != nil { schemaName = job.BinlogInfo.DBInfo.Name.L } @@ -484,8 +521,9 @@ func (e *DDLJobRetriever) appendJobToChunk(req *chunk.Chunk, job *model.Job, che tableName = getTableName(e.is, job.TableID) } - startTime := ts2Time(job.StartTS) - finishTime := ts2Time(finishTS) + createTime := ts2Time(job.StartTS, e.TZLoc) + startTime := ts2Time(job.RealStartTS, e.TZLoc) + finishTime := ts2Time(finishTS, e.TZLoc) // Check the privilege. if checker != nil && !checker.RequestVerification(e.activeRoles, strings.ToLower(schemaName), strings.ToLower(tableName), "", mysql.AllPrivMask) { @@ -500,20 +538,41 @@ func (e *DDLJobRetriever) appendJobToChunk(req *chunk.Chunk, job *model.Job, che req.AppendInt64(5, job.SchemaID) req.AppendInt64(6, job.TableID) req.AppendInt64(7, job.RowCount) - req.AppendTime(8, startTime) - if finishTS > 0 { - req.AppendTime(9, finishTime) + req.AppendTime(8, createTime) + if job.RealStartTS > 0 { + req.AppendTime(9, startTime) } else { req.AppendNull(9) } - req.AppendString(10, job.State.String()) + if finishTS > 0 { + req.AppendTime(10, finishTime) + } else { + req.AppendNull(10) + } + req.AppendString(11, job.State.String()) + if job.Type == model.ActionMultiSchemaChange { + for _, subJob := range job.MultiSchemaInfo.SubJobs { + req.AppendInt64(0, job.ID) + req.AppendString(1, schemaName) + req.AppendString(2, tableName) + req.AppendString(3, subJob.Type.String()+" /* subjob */") + req.AppendString(4, subJob.SchemaState.String()) + req.AppendInt64(5, job.SchemaID) + req.AppendInt64(6, job.TableID) + req.AppendInt64(7, subJob.RowCount) + req.AppendNull(8) + req.AppendNull(9) + req.AppendNull(10) + req.AppendString(11, subJob.State.String()) + } + } } -func ts2Time(timestamp uint64) types.Time { - duration := time.Duration(math.Pow10(9-int(types.DefaultFsp))) * time.Nanosecond +func ts2Time(timestamp uint64, loc *time.Location) types.Time { + duration := time.Duration(math.Pow10(9-types.DefaultFsp)) * time.Nanosecond t := model.TSConvert2Time(timestamp) t.Truncate(duration) - return types.NewTime(types.FromGoTime(t), mysql.TypeDatetime, types.DefaultFsp) + return types.NewTime(types.FromGoTime(t.In(loc)), mysql.TypeDatetime, types.DefaultFsp) } // ShowDDLJobQueriesExec represents a show DDL job queries executor. @@ -684,6 +743,7 @@ func (e *CheckTableExec) Open(ctx context.Context) error { // Close implements the Executor Close interface. func (e *CheckTableExec) Close() error { var firstErr error + close(e.exitCh) for _, src := range e.srcs { if err := src.Close(); err != nil && firstErr == nil { firstErr = err @@ -717,19 +777,13 @@ func (e *CheckTableExec) checkIndexHandle(ctx context.Context, src *IndexLookUpE for { err = Next(ctx, src, chk) if err != nil { + e.retCh <- errors.Trace(err) break } if chk.NumRows() == 0 { break } - - select { - case <-e.exitCh: - return nil - default: - } } - e.retCh <- errors.Trace(err) return errors.Trace(err) } @@ -759,45 +813,57 @@ func (e *CheckTableExec) Next(ctx context.Context, req *chunk.Chunk) error { if greater == admin.IdxCntGreater { err = e.checkTableIndexHandle(ctx, e.indexInfos[idxOffset]) } else if greater == admin.TblCntGreater { - err = e.checkTableRecord(idxOffset) - } - if err != nil && admin.ErrDataInConsistent.Equal(err) { - return ErrAdminCheckTable.GenWithStack("%v err:%v", e.table.Meta().Name, err) + err = e.checkTableRecord(ctx, idxOffset) } return errors.Trace(err) } // The number of table rows is equal to the number of index rows. // TODO: Make the value of concurrency adjustable. And we can consider the number of records. - concurrency := 3 - wg := sync.WaitGroup{} - for i := range e.srcs { - wg.Add(1) - go func(num int) { - defer wg.Done() + if len(e.srcs) == 1 { + return e.checkIndexHandle(ctx, e.srcs[0]) + } + taskCh := make(chan *IndexLookUpExecutor, len(e.srcs)) + failure := atomicutil.NewBool(false) + concurrency := mathutil.Min(3, len(e.srcs)) + var wg util.WaitGroupWrapper + for _, src := range e.srcs { + taskCh <- src + } + for i := 0; i < concurrency; i++ { + wg.Run(func() { util.WithRecovery(func() { - err1 := e.checkIndexHandle(ctx, e.srcs[num]) - if err1 != nil { - logutil.Logger(ctx).Info("check index handle failed", zap.Error(err1)) + for { + if fail := failure.Load(); fail { + return + } + select { + case src := <-taskCh: + err1 := e.checkIndexHandle(ctx, src) + if err1 != nil { + failure.Store(true) + logutil.Logger(ctx).Info("check index handle failed", zap.Error(err1)) + return + } + case <-e.exitCh: + return + default: + return + } } }, e.handlePanic) - }(i) - - if (i+1)%concurrency == 0 { - wg.Wait() - } + }) } - - for i := 0; i < len(e.srcs); i++ { - err = <-e.retCh - if err != nil { - return errors.Trace(err) - } + wg.Wait() + select { + case err := <-e.retCh: + return errors.Trace(err) + default: + return nil } - return nil } -func (e *CheckTableExec) checkTableRecord(idxOffset int) error { +func (e *CheckTableExec) checkTableRecord(ctx context.Context, idxOffset int) error { idxInfo := e.indexInfos[idxOffset] txn, err := e.ctx.Txn(true) if err != nil { @@ -805,7 +871,7 @@ func (e *CheckTableExec) checkTableRecord(idxOffset int) error { } if e.table.Meta().GetPartitionInfo() == nil { idx := tables.NewIndex(e.table.Meta().ID, e.table.Meta(), idxInfo) - return admin.CheckRecordAndIndex(e.ctx, txn, e.table, idx) + return admin.CheckRecordAndIndex(ctx, e.ctx, txn, e.table, idx) } info := e.table.Meta().GetPartitionInfo() @@ -813,7 +879,7 @@ func (e *CheckTableExec) checkTableRecord(idxOffset int) error { pid := def.ID partition := e.table.(table.PartitionedTable).GetPartition(pid) idx := tables.NewIndex(def.ID, e.table.Meta(), idxInfo) - if err := admin.CheckRecordAndIndex(e.ctx, txn, partition, idx); err != nil { + if err := admin.CheckRecordAndIndex(ctx, e.ctx, txn, partition, idx); err != nil { return errors.Trace(err) } } @@ -890,21 +956,47 @@ type SelectLockExec struct { Lock *ast.SelectLockInfo keys []kv.Key + // The children may be a join of multiple tables, so we need a map. tblID2Handle map[int64][]plannercore.HandleCols - // All the partition tables in the children of this executor. - partitionedTable []table.PartitionedTable + // When SelectLock work on a partition table, we need the partition ID + // (Physical Table ID) instead of the 'logical' table ID to calculate + // the lock KV. In that case, the Physical Table ID is extracted + // from the row key in the store and as an extra column in the chunk row. + + // tblID2PhyTblIDCol is used for partitioned tables. + // The child executor need to return an extra column containing + // the Physical Table ID (i.e. from which partition the row came from) + // Used during building + tblID2PhysTblIDCol map[int64]*expression.Column - // When SelectLock work on the partition table, we need the partition ID - // instead of table ID to calculate the lock KV. In that case, partition ID is store as an - // extra column in the chunk row. - // tblID2PIDColumnIndex stores the column index in the chunk row. The children may be join - // of multiple tables, so the map struct is used. - tblID2PIDColumnIndex map[int64]int + // Used during execution + // Map from logic tableID to column index where the physical table id is stored + // For dynamic prune mode, model.ExtraPhysTblID columns are requested from + // storage and used for physical table id + // For static prune mode, model.ExtraPhysTblID is still sent to storage/Protobuf + // but could be filled in by the partitions TableReaderExecutor + // due to issues with chunk handling between the TableReaderExecutor and the + // SelectReader result. + tblID2PhysTblIDColIdx map[int64]int } // Open implements the Executor Open interface. func (e *SelectLockExec) Open(ctx context.Context) error { + if len(e.tblID2PhysTblIDCol) > 0 { + e.tblID2PhysTblIDColIdx = make(map[int64]int) + cols := e.Schema().Columns + for i := len(cols) - 1; i >= 0; i-- { + if cols[i].ID == model.ExtraPhysTblID { + for tblID, col := range e.tblID2PhysTblIDCol { + if cols[i].UniqueID == col.UniqueID { + e.tblID2PhysTblIDColIdx[tblID] = i + break + } + } + } + } + } return e.baseExecutor.Open(ctx) } @@ -923,23 +1015,17 @@ func (e *SelectLockExec) Next(ctx context.Context, req *chunk.Chunk) error { if req.NumRows() > 0 { iter := chunk.NewIterator4Chunk(req) for row := iter.Begin(); row != iter.End(); row = iter.Next() { - - for id, cols := range e.tblID2Handle { - physicalID := id - if len(e.partitionedTable) > 0 { - // Replace the table ID with partition ID. - // The partition ID is returned as an extra column from the table reader. - if offset, ok := e.tblID2PIDColumnIndex[id]; ok { - physicalID = row.GetInt64(offset) - } - } - + for tblID, cols := range e.tblID2Handle { for _, col := range cols { handle, err := col.BuildHandle(row) if err != nil { return err } - e.keys = append(e.keys, tablecodec.EncodeRowKeyWithHandle(physicalID, handle)) + physTblID := tblID + if physTblColIdx, ok := e.tblID2PhysTblIDColIdx[tblID]; ok { + physTblID = row.GetInt64(physTblColIdx) + } + e.keys = append(e.keys, tablecodec.EncodeRowKeyWithHandle(physTblID, handle)) } } } @@ -952,22 +1038,14 @@ func (e *SelectLockExec) Next(ctx context.Context, req *chunk.Chunk) error { lockWaitTime = int64(e.Lock.WaitSec) * 1000 } - if len(e.tblID2Handle) > 0 { - for id := range e.tblID2Handle { - e.updateDeltaForTableID(id) - } - } - if len(e.partitionedTable) > 0 { - for _, p := range e.partitionedTable { - pid := p.Meta().ID - e.updateDeltaForTableID(pid) - } + for id := range e.tblID2Handle { + e.updateDeltaForTableID(id) } - return doLockKeys(ctx, e.ctx, newLockCtx(e.ctx.GetSessionVars(), lockWaitTime), e.keys...) + return doLockKeys(ctx, e.ctx, newLockCtx(e.ctx.GetSessionVars(), lockWaitTime, len(e.keys)), e.keys...) } -func newLockCtx(seVars *variable.SessionVars, lockWaitTime int64) *tikvstore.LockCtx { +func newLockCtx(seVars *variable.SessionVars, lockWaitTime int64, numKeys int) *tikvstore.LockCtx { lockCtx := tikvstore.NewLockCtx(seVars.TxnCtx.GetForUpdateTS(), lockWaitTime, seVars.StmtCtx.GetLockWaitStartTime()) lockCtx.Killed = &seVars.Killed lockCtx.PessimisticLockWaited = &seVars.StmtCtx.PessimisticLockWaited @@ -1000,6 +1078,9 @@ func newLockCtx(seVars *variable.SessionVars, lockWaitTime int64) *tikvstore.Loc rec := deadlockhistory.ErrDeadlockToDeadlockRecord(deadlock) deadlockhistory.GlobalDeadlockHistory.Push(rec) } + if lockCtx.ForUpdateTS > 0 && seVars.AssertionLevel != variable.AssertionLevelOff { + lockCtx.InitCheckExistence(numKeys) + } return lockCtx } @@ -1695,9 +1776,11 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.IsStaleness = false sc.LockTableIDs = make(map[int64]struct{}) sc.EnableOptimizeTrace = false - sc.LogicalOptimizeTrace = nil + sc.OptimizeTracer = nil sc.OptimizerCETrace = nil + sc.SysdateIsNow = ctx.GetSessionVars().SysdateIsNow + sc.InitMemTracker(memory.LabelForSQLText, vars.MemQuotaQuery) sc.InitDiskTracker(memory.LabelForSQLText, -1) sc.MemTracker.AttachToGlobalTracker(GlobalMemoryUsageTracker) @@ -1718,7 +1801,7 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.MemTracker.SetActionOnExceed(action) } if execStmt, ok := s.(*ast.ExecuteStmt); ok { - prepareStmt, err := planner.GetPreparedStmt(execStmt, vars) + prepareStmt, err := plannercore.GetPreparedStmt(execStmt, vars) if err != nil { return err } @@ -1730,15 +1813,20 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { goCtx = pprof.WithLabels(goCtx, pprof.Labels("sql", util.QueryStrForLog(prepareStmt.NormalizedSQL))) pprof.SetGoroutineLabels(goCtx) } - if variable.TopSQLEnabled() && prepareStmt.SQLDigest != nil { + if topsqlstate.TopSQLEnabled() && prepareStmt.SQLDigest != nil { topsql.AttachSQLInfo(goCtx, prepareStmt.NormalizedSQL, prepareStmt.SQLDigest, "", nil, vars.InRestrictedSQL) } + if s, ok := prepareStmt.PreparedAst.Stmt.(*ast.SelectStmt); ok { + if s.LockInfo == nil { + sc.WeakConsistency = isWeakConsistencyRead(ctx, execStmt) + } + } } // execute missed stmtID uses empty sql sc.OriginalSQL = s.Text() if explainStmt, ok := s.(*ast.ExplainStmt); ok { sc.InExplainStmt = true - sc.IgnoreExplainIDSuffix = (strings.ToLower(explainStmt.Format) == types.ExplainFormatBrief) + sc.IgnoreExplainIDSuffix = strings.ToLower(explainStmt.Format) == types.ExplainFormatBrief sc.InVerboseExplain = strings.ToLower(explainStmt.Format) == types.ExplainFormatVerbose s = explainStmt.Stmt } @@ -1779,6 +1867,8 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.InCreateOrAlterStmt = true sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode() sc.IgnoreZeroInDate = !vars.SQLMode.HasNoZeroInDateMode() || !vars.StrictSQLMode || sc.AllowInvalidDate + sc.NoZeroDate = vars.SQLMode.HasNoZeroDateMode() + sc.TruncateAsWarning = !vars.StrictSQLMode case *ast.LoadDataStmt: sc.DupKeyAsWarning = true sc.BadNullAsWarning = true @@ -1806,6 +1896,12 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.Priority = opts.Priority sc.NotFillCache = !opts.SQLCache } + sc.WeakConsistency = isWeakConsistencyRead(ctx, stmt) + // Try to mark the `RCCheckTS` flag for the first time execution of in-transaction read requests + // using read-consistency isolation level. + if NeedSetRCCheckTSFlag(ctx, stmt) { + sc.RCCheckTS = true + } case *ast.SetOprStmt: sc.InSelectStmt = true sc.OverflowAsWarning = true @@ -1829,6 +1925,9 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.IgnoreZeroInDate = true sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode() } + sc.SkipUTF8Check = vars.SkipUTF8Check + sc.SkipASCIICheck = vars.SkipASCIICheck + sc.SkipUTF8MB4Check = !globalConfig.CheckMb4ValueInUTF8.Load() vars.PreparedParams = vars.PreparedParams[:0] if priority := mysql.PriorityEnum(atomic.LoadInt32(&variable.ForcePriority)); priority != mysql.NoPriority { sc.Priority = priority @@ -1910,7 +2009,31 @@ func FillVirtualColumnValue(virtualRetTypes []*types.FieldType, virtualColumnInd } func setResourceGroupTaggerForTxn(sc *stmtctx.StatementContext, snapshot kv.Snapshot) { - if snapshot != nil && variable.TopSQLEnabled() { + if snapshot != nil && topsqlstate.TopSQLEnabled() { snapshot.SetOption(kv.ResourceGroupTagger, sc.GetResourceGroupTagger()) } } + +// setRPCInterceptorOfExecCounterForTxn binds an interceptor for client-go to count +// the number of SQL executions of each TiKV. +func setRPCInterceptorOfExecCounterForTxn(vars *variable.SessionVars, snapshot kv.Snapshot) { + if snapshot != nil && topsqlstate.TopSQLEnabled() && vars.StmtCtx.KvExecCounter != nil { + snapshot.SetOption(kv.RPCInterceptor, vars.StmtCtx.KvExecCounter.RPCInterceptor()) + } +} + +func isWeakConsistencyRead(ctx sessionctx.Context, node ast.Node) bool { + sessionVars := ctx.GetSessionVars() + return sessionVars.ConnectionID > 0 && sessionVars.ReadConsistency.IsWeak() && + plannercore.IsAutoCommitTxn(ctx) && plannercore.IsReadOnly(node, sessionVars) +} + +// NeedSetRCCheckTSFlag checks whether it's needed to set `RCCheckTS` flag in current stmtctx. +func NeedSetRCCheckTSFlag(ctx sessionctx.Context, node ast.Node) bool { + sessionVars := ctx.GetSessionVars() + if sessionVars.ConnectionID > 0 && sessionVars.RcReadCheckTS && sessionVars.InTxn() && + sessionVars.IsPessimisticReadConsistency() && !sessionVars.RetryInfo.Retrying && plannercore.IsReadOnly(node, sessionVars) { + return true + } + return false +} diff --git a/executor/executor_failpoint_test.go b/executor/executor_failpoint_test.go new file mode 100644 index 0000000000000..fc0ab306fd157 --- /dev/null +++ b/executor/executor_failpoint_test.go @@ -0,0 +1,562 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "context" + "fmt" + "strconv" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/store/copr" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/deadlockhistory" + "github.com/stretchr/testify/require" +) + +func TestTiDBLastTxnInfoCommitMode(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.TiKVClient.AsyncCommit.SafeWindow = time.Second + }) + + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int primary key, v int)") + tk.MustExec("insert into t values (1, 1)") + + tk.MustExec("set @@tidb_enable_async_commit = 1") + tk.MustExec("set @@tidb_enable_1pc = 0") + tk.MustExec("update t set v = v + 1 where a = 1") + rows := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + t.Log(rows) + require.Equal(t, `"async_commit"`, rows[0][0]) + require.Equal(t, "false", rows[0][1]) + require.Equal(t, "false", rows[0][2]) + + tk.MustExec("set @@tidb_enable_async_commit = 0") + tk.MustExec("set @@tidb_enable_1pc = 1") + tk.MustExec("update t set v = v + 1 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + require.Equal(t, `"1pc"`, rows[0][0]) + require.Equal(t, "false", rows[0][1]) + require.Equal(t, "false", rows[0][2]) + + tk.MustExec("set @@tidb_enable_async_commit = 0") + tk.MustExec("set @@tidb_enable_1pc = 0") + tk.MustExec("update t set v = v + 1 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + require.Equal(t, `"2pc"`, rows[0][0]) + require.Equal(t, "false", rows[0][1]) + require.Equal(t, "false", rows[0][2]) + + require.NoError(t, failpoint.Enable("tikvclient/invalidMaxCommitTS", "return")) + defer func() { + require.NoError(t, failpoint.Disable("tikvclient/invalidMaxCommitTS")) + }() + + tk.MustExec("set @@tidb_enable_async_commit = 1") + tk.MustExec("set @@tidb_enable_1pc = 0") + tk.MustExec("update t set v = v + 1 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + t.Log(rows) + require.Equal(t, `"2pc"`, rows[0][0]) + require.Equal(t, "true", rows[0][1]) + require.Equal(t, "false", rows[0][2]) + + tk.MustExec("set @@tidb_enable_async_commit = 0") + tk.MustExec("set @@tidb_enable_1pc = 1") + tk.MustExec("update t set v = v + 1 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + t.Log(rows) + require.Equal(t, `"2pc"`, rows[0][0]) + require.Equal(t, "false", rows[0][1]) + require.Equal(t, "true", rows[0][2]) + + tk.MustExec("set @@tidb_enable_async_commit = 1") + tk.MustExec("set @@tidb_enable_1pc = 1") + tk.MustExec("update t set v = v + 1 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() + t.Log(rows) + require.Equal(t, `"2pc"`, rows[0][0]) + require.Equal(t, "true", rows[0][1]) + require.Equal(t, "true", rows[0][2]) +} + +func TestPointGetRepeatableRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec(`create table point_get (a int, b int, c int, + primary key k_a(a), + unique key k_b(b))`) + tk1.MustExec("insert into point_get values (1, 1, 1)") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + var ( + step1 = "github.com/pingcap/tidb/executor/pointGetRepeatableReadTest-step1" + step2 = "github.com/pingcap/tidb/executor/pointGetRepeatableReadTest-step2" + ) + + require.NoError(t, failpoint.Enable(step1, "return")) + require.NoError(t, failpoint.Enable(step2, "pause")) + + updateWaitCh := make(chan struct{}) + go func() { + ctx := context.WithValue(context.Background(), "pointGetRepeatableReadTest", updateWaitCh) + ctx = failpoint.WithHook(ctx, func(ctx context.Context, fpname string) bool { + return fpname == step1 || fpname == step2 + }) + rs, err := tk1.Session().Execute(ctx, "select c from point_get where b = 1") + require.NoError(t, err) + result := tk1.ResultSetToResultWithCtx(ctx, rs[0], "execute sql fail") + result.Check(testkit.Rows("1")) + }() + + <-updateWaitCh // Wait `POINT GET` first time `get` + require.NoError(t, failpoint.Disable(step1)) + tk2.MustExec("update point_get set b = 2, c = 2 where a = 1") + require.NoError(t, failpoint.Disable(step2)) +} + +func TestBatchPointGetRepeatableRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec(`create table batch_point_get (a int, b int, c int, unique key k_b(a, b, c))`) + tk1.MustExec("insert into batch_point_get values (1, 1, 1), (2, 3, 4), (3, 4, 5)") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + var ( + step1 = "github.com/pingcap/tidb/executor/batchPointGetRepeatableReadTest-step1" + step2 = "github.com/pingcap/tidb/executor/batchPointGetRepeatableReadTest-step2" + ) + + require.NoError(t, failpoint.Enable(step1, "return")) + require.NoError(t, failpoint.Enable(step2, "pause")) + + updateWaitCh := make(chan struct{}) + go func() { + ctx := context.WithValue(context.Background(), "batchPointGetRepeatableReadTest", updateWaitCh) + ctx = failpoint.WithHook(ctx, func(ctx context.Context, fpname string) bool { + return fpname == step1 || fpname == step2 + }) + rs, err := tk1.Session().Execute(ctx, "select c from batch_point_get where (a, b, c) in ((1, 1, 1))") + require.NoError(t, err) + result := tk1.ResultSetToResultWithCtx(ctx, rs[0], "execute sql fail") + result.Check(testkit.Rows("1")) + }() + + <-updateWaitCh // Wait `POINT GET` first time `get` + require.NoError(t, failpoint.Disable(step1)) + tk2.MustExec("update batch_point_get set b = 2, c = 2 where a = 1") + require.NoError(t, failpoint.Disable(step2)) +} + +func TestSplitRegionTimeout(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + require.NoError(t, failpoint.Enable("tikvclient/mockSplitRegionTimeout", `return(true)`)) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a varchar(100),b int, index idx1(b,a))") + tk.MustExec(`split table t index idx1 by (10000,"abcd"),(10000000);`) + tk.MustExec(`set @@tidb_wait_split_region_timeout=1`) + // result 0 0 means split 0 region and 0 region finish scatter regions before timeout. + tk.MustQuery(`split table t between (0) and (10000) regions 10`).Check(testkit.Rows("0 0")) + require.NoError(t, failpoint.Disable("tikvclient/mockSplitRegionTimeout")) + + // Test scatter regions timeout. + require.NoError(t, failpoint.Enable("tikvclient/mockScatterRegionTimeout", `return(true)`)) + tk.MustQuery(`split table t between (0) and (10000) regions 10`).Check(testkit.Rows("10 1")) + require.NoError(t, failpoint.Disable("tikvclient/mockScatterRegionTimeout")) + + // Test pre-split with timeout. + tk.MustExec("drop table if exists t") + tk.MustExec("set @@global.tidb_scatter_region=1;") + require.NoError(t, failpoint.Enable("tikvclient/mockScatterRegionTimeout", `return(true)`)) + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + start := time.Now() + tk.MustExec("create table t (a int, b int) partition by hash(a) partitions 5;") + require.Less(t, time.Since(start).Seconds(), 10.0) + require.NoError(t, failpoint.Disable("tikvclient/mockScatterRegionTimeout")) +} + +func TestTSOFail(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int)`) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/mockGetTSFail", "return")) + ctx := failpoint.WithHook(context.Background(), func(ctx context.Context, fpname string) bool { + return fpname == "github.com/pingcap/tidb/session/mockGetTSFail" + }) + _, err := tk.Session().Execute(ctx, `select * from t`) + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/mockGetTSFail")) +} + +func TestKillTableReader(t *testing.T) { + var retry = "github.com/tikv/client-go/v2/locate/mockRetrySendReqToRegion" + defer func() { + require.NoError(t, failpoint.Disable(retry)) + }() + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int)") + tk.MustExec("insert into t values (1),(2),(3)") + tk.MustExec("set @@tidb_distsql_scan_concurrency=1") + atomic.StoreUint32(&tk.Session().GetSessionVars().Killed, 0) + require.NoError(t, failpoint.Enable(retry, `return(true)`)) + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + time.Sleep(1 * time.Second) + err := tk.QueryToErr("select * from t") + require.Error(t, err) + require.Equal(t, int(executor.ErrQueryInterrupted.Code()), int(terror.ToSQLError(errors.Cause(err).(*terror.Error)).Code)) + }() + atomic.StoreUint32(&tk.Session().GetSessionVars().Killed, 1) + wg.Wait() +} + +func TestCollectCopRuntimeStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("set tidb_enable_collect_execution_info=1;") + require.NoError(t, failpoint.Enable("tikvclient/tikvStoreRespResult", `return(true)`)) + rows := tk.MustQuery("explain analyze select * from t1").Rows() + require.Len(t, rows, 2) + explain := fmt.Sprintf("%v", rows[0]) + require.Regexp(t, ".*rpc_num: 2, .*regionMiss:.*", explain) + require.NoError(t, failpoint.Disable("tikvclient/tikvStoreRespResult")) +} + +func TestCoprocessorOOMTiCase(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`set @@tidb_wait_split_region_finish=1`) + // create table for non keep-order case + tk.MustExec("drop table if exists t5") + tk.MustExec("create table t5(id int)") + tk.MustQuery(`split table t5 between (0) and (10000) regions 10`).Check(testkit.Rows("9 1")) + // create table for keep-order case + tk.MustExec("drop table if exists t6") + tk.MustExec("create table t6(id int, index(id))") + tk.MustQuery(`split table t6 between (0) and (10000) regions 10`).Check(testkit.Rows("10 1")) + tk.MustQuery("split table t6 INDEX id between (0) and (10000) regions 10;").Check(testkit.Rows("10 1")) + count := 10 + for i := 0; i < count; i++ { + tk.MustExec(fmt.Sprintf("insert into t5 (id) values (%v)", i)) + tk.MustExec(fmt.Sprintf("insert into t6 (id) values (%v)", i)) + } + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionLog + }) + testcases := []struct { + name string + sql string + }{ + { + name: "keep Order", + sql: "select id from t6 order by id", + }, + { + name: "non keep Order", + sql: "select id from t5", + }, + } + + f := func() { + for _, testcase := range testcases { + t.Log(testcase.name) + // larger than one copResponse, smaller than 2 copResponse + quota := 2*copr.MockResponseSizeForTest - 100 + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + tk.SetSession(se) + tk.MustExec("use test") + tk.MustExec(fmt.Sprintf("set @@tidb_mem_quota_query=%v;", quota)) + var expect []string + for i := 0; i < count; i++ { + expect = append(expect, fmt.Sprintf("%v", i)) + } + tk.MustQuery(testcase.sql).Sort().Check(testkit.Rows(expect...)) + // assert oom action worked by max consumed > memory quota + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), int64(quota)) + se.Close() + } + } + + // ticase-4169, trigger oom action twice after workers consuming all the data + err := failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4169", `return(true)`) + require.NoError(t, err) + f() + err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4169") + require.NoError(t, err) + // ticase-4170, trigger oom action twice after iterator receiving all the data. + err = failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4170", `return(true)`) + require.NoError(t, err) + f() + err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4170") + require.NoError(t, err) + // ticase-4171, trigger oom before reading or consuming any data + err = failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4171", `return(true)`) + require.NoError(t, err) + f() + err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4171") + require.NoError(t, err) +} + +func TestIssue21441(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/issue21441", `return`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/issue21441")) + }() + + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec(`insert into t values(1),(2),(3)`) + tk.Session().GetSessionVars().InitChunkSize = 1 + tk.Session().GetSessionVars().MaxChunkSize = 1 + sql := ` +select a from t union all +select a from t union all +select a from t union all +select a from t union all +select a from t union all +select a from t union all +select a from t union all +select a from t` + tk.MustQuery(sql).Sort().Check(testkit.Rows( + "1", "1", "1", "1", "1", "1", "1", "1", + "2", "2", "2", "2", "2", "2", "2", "2", + "3", "3", "3", "3", "3", "3", "3", "3", + )) + + tk.MustQuery("select a from (" + sql + ") t order by a limit 4").Check(testkit.Rows("1", "1", "1", "1")) + tk.MustQuery("select a from (" + sql + ") t order by a limit 7, 4").Check(testkit.Rows("1", "2", "2", "2")) + + tk.MustExec("set @@tidb_executor_concurrency = 2") + require.Equal(t, 2, tk.Session().GetSessionVars().UnionConcurrency()) + tk.MustQuery("select a from (" + sql + ") t order by a limit 4").Check(testkit.Rows("1", "1", "1", "1")) + tk.MustQuery("select a from (" + sql + ") t order by a limit 7, 4").Check(testkit.Rows("1", "2", "2", "2")) +} + +func TestTxnWriteThroughputSLI(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int key, b int)") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput", "return(true)")) + defer func() { + err := failpoint.Disable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput") + require.NoError(t, err) + }() + + mustExec := func(sql string) { + tk.MustExec(sql) + tk.Session().GetTxnWriteThroughputSLI().FinishExecuteStmt(time.Second, tk.Session().AffectedRows(), tk.Session().GetSessionVars().InTxn()) + } + errExec := func(sql string) { + err := tk.ExecToErr(sql) + require.Error(t, err) + tk.Session().GetTxnWriteThroughputSLI().FinishExecuteStmt(time.Second, tk.Session().AffectedRows(), tk.Session().GetSessionVars().InTxn()) + } + + // Test insert in small txn + mustExec("insert into t values (1,3),(2,4)") + writeSLI := tk.Session().GetTxnWriteThroughputSLI() + require.False(t, writeSLI.IsInvalid()) + require.True(t, writeSLI.IsSmallTxn()) + require.Equal(t, "invalid: false, affectRow: 2, writeSize: 58, readKeys: 0, writeKeys: 2, writeTime: 1s", tk.Session().GetTxnWriteThroughputSLI().String()) + tk.Session().GetTxnWriteThroughputSLI().Reset() + + // Test insert ... select ... from + mustExec("insert into t select b, a from t") + require.True(t, writeSLI.IsInvalid()) + require.True(t, writeSLI.IsSmallTxn()) + require.Equal(t, "invalid: true, affectRow: 2, writeSize: 58, readKeys: 0, writeKeys: 2, writeTime: 1s", tk.Session().GetTxnWriteThroughputSLI().String()) + tk.Session().GetTxnWriteThroughputSLI().Reset() + + // Test for delete + mustExec("delete from t") + require.Equal(t, "invalid: false, affectRow: 4, writeSize: 76, readKeys: 0, writeKeys: 4, writeTime: 1s", tk.Session().GetTxnWriteThroughputSLI().String()) + tk.Session().GetTxnWriteThroughputSLI().Reset() + + // Test insert not in small txn + mustExec("begin") + for i := 0; i < 20; i++ { + mustExec(fmt.Sprintf("insert into t values (%v,%v)", i, i)) + require.True(t, writeSLI.IsSmallTxn()) + } + // The statement which affect rows is 0 shouldn't record into time. + mustExec("select count(*) from t") + mustExec("select * from t") + mustExec("insert into t values (20,20)") + require.False(t, writeSLI.IsSmallTxn()) + mustExec("commit") + require.False(t, writeSLI.IsInvalid()) + require.Equal(t, "invalid: false, affectRow: 21, writeSize: 609, readKeys: 0, writeKeys: 21, writeTime: 22s", tk.Session().GetTxnWriteThroughputSLI().String()) + tk.Session().GetTxnWriteThroughputSLI().Reset() + + // Test invalid when transaction has replace ... select ... from ... statement. + mustExec("delete from t") + tk.Session().GetTxnWriteThroughputSLI().Reset() + mustExec("begin") + mustExec("insert into t values (1,3),(2,4)") + mustExec("replace into t select b, a from t") + mustExec("commit") + require.True(t, writeSLI.IsInvalid()) + require.Equal(t, "invalid: true, affectRow: 4, writeSize: 116, readKeys: 0, writeKeys: 4, writeTime: 3s", tk.Session().GetTxnWriteThroughputSLI().String()) + tk.Session().GetTxnWriteThroughputSLI().Reset() + + // Test clean last failed transaction information. + err := failpoint.Disable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput") + require.NoError(t, err) + mustExec("begin") + mustExec("insert into t values (1,3),(2,4)") + errExec("commit") + require.Equal(t, "invalid: false, affectRow: 0, writeSize: 0, readKeys: 0, writeKeys: 0, writeTime: 0s", tk.Session().GetTxnWriteThroughputSLI().String()) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput", "return(true)")) + mustExec("begin") + mustExec("insert into t values (5, 6)") + mustExec("commit") + require.Equal(t, "invalid: false, affectRow: 1, writeSize: 29, readKeys: 0, writeKeys: 1, writeTime: 2s", tk.Session().GetTxnWriteThroughputSLI().String()) + + // Test for reset + tk.Session().GetTxnWriteThroughputSLI().Reset() + require.Equal(t, "invalid: false, affectRow: 0, writeSize: 0, readKeys: 0, writeKeys: 0, writeTime: 0s", tk.Session().GetTxnWriteThroughputSLI().String()) +} + +func TestDeadlocksTable(t *testing.T) { + deadlockhistory.GlobalDeadlockHistory.Clear() + deadlockhistory.GlobalDeadlockHistory.Resize(10) + + occurTime := time.Date(2021, 5, 10, 1, 2, 3, 456789000, time.Local) + rec := &deadlockhistory.DeadlockRecord{ + OccurTime: occurTime, + IsRetryable: false, + WaitChain: []deadlockhistory.WaitChainItem{ + { + TryLockTxn: 101, + SQLDigest: "aabbccdd", + Key: []byte("k1"), + AllSQLDigests: nil, + TxnHoldingLock: 102, + }, + { + TryLockTxn: 102, + SQLDigest: "ddccbbaa", + Key: []byte("k2"), + AllSQLDigests: []string{"sql1"}, + TxnHoldingLock: 101, + }, + }, + } + deadlockhistory.GlobalDeadlockHistory.Push(rec) + + occurTime2 := time.Date(2022, 6, 11, 2, 3, 4, 987654000, time.Local) + rec2 := &deadlockhistory.DeadlockRecord{ + OccurTime: occurTime2, + IsRetryable: true, + WaitChain: []deadlockhistory.WaitChainItem{ + { + TryLockTxn: 201, + AllSQLDigests: []string{}, + TxnHoldingLock: 202, + }, + { + TryLockTxn: 202, + AllSQLDigests: []string{"sql1", "sql2, sql3"}, + TxnHoldingLock: 203, + }, + { + TryLockTxn: 203, + TxnHoldingLock: 201, + }, + }, + } + deadlockhistory.GlobalDeadlockHistory.Push(rec2) + + // `Push` sets the record's ID, and ID in a single DeadlockHistory is monotonically increasing. We must get it here + // to know what it is. + id1 := strconv.FormatUint(rec.ID, 10) + id2 := strconv.FormatUint(rec2.ID, 10) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/sqlDigestRetrieverSkipRetrieveGlobal", "return")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/sqlDigestRetrieverSkipRetrieveGlobal")) + }() + + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustQuery("select * from information_schema.deadlocks").Check( + testkit.RowsWithSep("/", + id1+"/2021-05-10 01:02:03.456789/0/101/aabbccdd//6B31//102", + id1+"/2021-05-10 01:02:03.456789/0/102/ddccbbaa//6B32//101", + id2+"/2022-06-11 02:03:04.987654/1/201/////202", + id2+"/2022-06-11 02:03:04.987654/1/202/////203", + id2+"/2022-06-11 02:03:04.987654/1/203/////201", + )) +} diff --git a/executor/executor_issue_test.go b/executor/executor_issue_test.go new file mode 100644 index 0000000000000..a844a4666734c --- /dev/null +++ b/executor/executor_issue_test.go @@ -0,0 +1,1246 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "context" + "fmt" + "math/rand" + "strings" + "testing" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/statistics" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" + "github.com/stretchr/testify/require" +) + +func TestIssue23993(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // Real cast to time should return NULL + tk.MustExec("drop table if exists t_issue_23993") + tk.MustExec("create table t_issue_23993(a double)") + tk.MustExec("insert into t_issue_23993 values(-790822912)") + tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) + tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) + // Int cast to time should return NULL + tk.MustExec("drop table if exists t_issue_23993") + tk.MustExec("create table t_issue_23993(a int)") + tk.MustExec("insert into t_issue_23993 values(-790822912)") + tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) + tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) + // Decimal cast to time should return NULL + tk.MustExec("drop table if exists t_issue_23993") + tk.MustExec("create table t_issue_23993(a decimal)") + tk.MustExec("insert into t_issue_23993 values(-790822912)") + tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) + tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) + // String cast to time should not return NULL + tk.MustExec("drop table if exists t_issue_23993") + tk.MustExec("create table t_issue_23993(a varchar(255))") + tk.MustExec("insert into t_issue_23993 values('-790822912')") + tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("-838:59:59")) + tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows("-790822912")) +} + +func TestIssue22201(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustQuery("SELECT HEX(WEIGHT_STRING('ab' AS BINARY(1000000000000000000)));").Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1301 Result of cast_as_binary() was larger than max_allowed_packet (67108864) - truncated")) + tk.MustQuery("SELECT HEX(WEIGHT_STRING('ab' AS char(1000000000000000000)));").Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1301 Result of weight_string() was larger than max_allowed_packet (67108864) - truncated")) +} + +func TestIssue22941(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists m, mp") + tk.MustExec(`CREATE TABLE m ( + mid varchar(50) NOT NULL, + ParentId varchar(50) DEFAULT NULL, + PRIMARY KEY (mid), + KEY ind_bm_parent (ParentId,mid) + )`) + // mp should have more columns than m + tk.MustExec(`CREATE TABLE mp ( + mpid bigint(20) unsigned NOT NULL DEFAULT '0', + mid varchar(50) DEFAULT NULL COMMENT '模å—主键', + sid int, + PRIMARY KEY (mpid) + );`) + + tk.MustExec(`insert into mp values("1","1","0");`) + tk.MustExec(`insert into m values("0", "0");`) + rs := tk.MustQuery(`SELECT ( SELECT COUNT(1) FROM m WHERE ParentId = c.mid ) expand, bmp.mpid, bmp.mpid IS NULL,bmp.mpid IS NOT NULL, sid FROM m c LEFT JOIN mp bmp ON c.mid = bmp.mid WHERE c.ParentId = '0'`) + rs.Check(testkit.Rows("1 1 0 ")) + + rs = tk.MustQuery(`SELECT bmp.mpid, bmp.mpid IS NULL,bmp.mpid IS NOT NULL FROM m c LEFT JOIN mp bmp ON c.mid = bmp.mid WHERE c.ParentId = '0'`) + rs.Check(testkit.Rows(" 1 0")) +} + +func TestIssue23609(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("CREATE TABLE `t1` (\n `a` timestamp NULL DEFAULT NULL,\n `b` year(4) DEFAULT NULL,\n KEY `a` (`a`),\n KEY `b` (`b`)\n)") + tk.MustExec("insert into t1 values(\"2002-10-03 04:28:53\",2000), (\"2002-10-03 04:28:53\",2002), (NULL, 2002)") + tk.MustQuery("select /*+ inl_join (x,y) */ * from t1 x cross join t1 y on x.a=y.b").Check(testkit.Rows()) + tk.MustQuery("select * from t1 x cross join t1 y on x.a>y.b order by x.a, x.b, y.a, y.b").Check(testkit.Rows("2002-10-03 04:28:53 2000 2002", "2002-10-03 04:28:53 2000 2002-10-03 04:28:53 2000", "2002-10-03 04:28:53 2000 2002-10-03 04:28:53 2002", "2002-10-03 04:28:53 2002 2002", "2002-10-03 04:28:53 2002 2002-10-03 04:28:53 2000", "2002-10-03 04:28:53 2002 2002-10-03 04:28:53 2002")) + tk.MustQuery("select * from t1 where a = b").Check(testkit.Rows()) + tk.MustQuery("select * from t1 where a < b").Check(testkit.Rows()) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) +} + +func TestIssue24091(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + defer tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int) partition by hash (a div 0) partitions 10;") + tk.MustExec("insert into t values (NULL);") + + tk.MustQuery("select null div 0;").Check(testkit.Rows("")) + tk.MustQuery("select * from t;").Check(testkit.Rows("")) +} + +func TestIssue24210(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // for ProjectionExec + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockProjectionExecBaseExecutorOpenReturnedError", `return(true)`)) + err := tk.ExecToErr("select a from (select 1 as a, 2 as b) t") + require.EqualError(t, err, "mock ProjectionExec.baseExecutor.Open returned error") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockProjectionExecBaseExecutorOpenReturnedError")) + + // for HashAggExec + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockHashAggExecBaseExecutorOpenReturnedError", `return(true)`)) + err = tk.ExecToErr("select sum(a) from (select 1 as a, 2 as b) t group by b") + require.EqualError(t, err, "mock HashAggExec.baseExecutor.Open returned error") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockHashAggExecBaseExecutorOpenReturnedError")) + + // for StreamAggExec + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockStreamAggExecBaseExecutorOpenReturnedError", `return(true)`)) + err = tk.ExecToErr("select sum(a) from (select 1 as a, 2 as b) t") + require.EqualError(t, err, "mock StreamAggExec.baseExecutor.Open returned error") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockStreamAggExecBaseExecutorOpenReturnedError")) + + // for SelectionExec + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockSelectionExecBaseExecutorOpenReturnedError", `return(true)`)) + err = tk.ExecToErr("select * from (select rand() as a) t where a > 0") + require.EqualError(t, err, "mock SelectionExec.baseExecutor.Open returned error") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockSelectionExecBaseExecutorOpenReturnedError")) +} + +func TestIssue25506(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists tbl_3, tbl_23") + tk.MustExec("create table tbl_3 (col_15 bit(20))") + tk.MustExec("insert into tbl_3 values (0xFFFF)") + tk.MustExec("insert into tbl_3 values (0xFF)") + tk.MustExec("create table tbl_23 (col_15 bit(15))") + tk.MustExec("insert into tbl_23 values (0xF)") + tk.MustQuery("(select col_15 from tbl_23) union all (select col_15 from tbl_3 for update) order by col_15").Check(testkit.Rows("\x00\x00\x0F", "\x00\x00\xFF", "\x00\xFF\xFF")) +} + +func TestIssue26348(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t") + tk.MustExec(`CREATE TABLE t ( +a varchar(8) DEFAULT NULL, +b varchar(8) DEFAULT NULL, +c decimal(20,2) DEFAULT NULL, +d decimal(15,8) DEFAULT NULL +);`) + tk.MustExec(`insert into t values(20210606, 20210606, 50000.00, 5.04600000);`) + tk.MustQuery(`select a * c *(d/36000) from t;`).Check(testkit.Rows("141642663.71666598")) + tk.MustQuery(`select cast(a as double) * cast(c as double) *cast(d/36000 as double) from t;`).Check(testkit.Rows("141642663.71666598")) + tk.MustQuery("select 20210606*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666599297980")) + + // differs from MySQL cause constant-fold . + tk.MustQuery("select \"20210606\"*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666598")) + tk.MustQuery("select cast(\"20210606\" as double)*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666598")) +} + +func TestIssue26532(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustQuery("select greatest(cast(\"2020-01-01 01:01:01\" as datetime), cast(\"2019-01-01 01:01:01\" as datetime) )union select null;").Sort().Check(testkit.Rows("2020-01-01 01:01:01", "")) + tk.MustQuery("select least(cast(\"2020-01-01 01:01:01\" as datetime), cast(\"2019-01-01 01:01:01\" as datetime) )union select null;").Sort().Check(testkit.Rows("2019-01-01 01:01:01", "")) + tk.MustQuery("select greatest(\"2020-01-01 01:01:01\" ,\"2019-01-01 01:01:01\" )union select null;").Sort().Check(testkit.Rows("2020-01-01 01:01:01", "")) + tk.MustQuery("select least(\"2020-01-01 01:01:01\" , \"2019-01-01 01:01:01\" )union select null;").Sort().Check(testkit.Rows("2019-01-01 01:01:01", "")) +} + +func TestIssue25447(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int, b varchar(8))") + tk.MustExec("insert into t1 values(1,'1')") + tk.MustExec("create table t2(a int , b varchar(8) GENERATED ALWAYS AS (c) VIRTUAL, c varchar(8), PRIMARY KEY (a))") + tk.MustExec("insert into t2(a) values(1)") + tk.MustQuery("select /*+ tidb_inlj(t2) */ t2.b, t1.b from t1 join t2 ON t2.a=t1.a").Check(testkit.Rows(" 1")) +} + +func TestIssue23602(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("USE test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("CREATE TABLE t (a bigint unsigned PRIMARY KEY)") + defer tk.MustExec("DROP TABLE t") + tk.MustExec("INSERT INTO t VALUES (0),(1),(2),(3),(18446744073709551600),(18446744073709551605),(18446744073709551610),(18446744073709551615)") + tk.MustExec("ANALYZE TABLE t") + tk.MustQuery(`EXPLAIN FORMAT = 'brief' SELECT a FROM t WHERE a >= 0x1 AND a <= 0x2`).Check(testkit.Rows( + "TableReader 2.00 root data:TableRangeScan]\n" + + "[└─TableRangeScan 2.00 cop[tikv] table:t range:[1,2], keep order:false")) + tk.MustQuery(`EXPLAIN FORMAT = 'brief' SELECT a FROM t WHERE a BETWEEN 0x1 AND 0x2`).Check(testkit.Rows( + "TableReader 2.00 root data:TableRangeScan]\n" + + "[└─TableRangeScan 2.00 cop[tikv] table:t range:[1,2], keep order:false")) + tk.MustQuery("SELECT a FROM t WHERE a BETWEEN 0xFFFFFFFFFFFFFFF5 AND X'FFFFFFFFFFFFFFFA'").Check(testkit.Rows("18446744073709551605", "18446744073709551610")) +} + +func TestIssue28935(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_enable_vectorized_expression=true") + tk.MustQuery(`select trim(leading from " a "), trim(both from " a "), trim(trailing from " a ")`).Check(testkit.Rows("a a a")) + tk.MustQuery(`select trim(leading null from " a "), trim(both null from " a "), trim(trailing null from " a ")`).Check(testkit.Rows(" ")) + tk.MustQuery(`select trim(null from " a ")`).Check(testkit.Rows("")) + + tk.MustExec("set @@tidb_enable_vectorized_expression=false") + tk.MustQuery(`select trim(leading from " a "), trim(both from " a "), trim(trailing from " a ")`).Check(testkit.Rows("a a a")) + tk.MustQuery(`select trim(leading null from " a "), trim(both null from " a "), trim(trailing null from " a ")`).Check(testkit.Rows(" ")) + tk.MustQuery(`select trim(null from " a ")`).Check(testkit.Rows("")) +} + +func TestIssue29412(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t29142_1") + tk.MustExec("drop table if exists t29142_2") + tk.MustExec("create table t29142_1(a int);") + tk.MustExec("create table t29142_2(a double);") + tk.MustExec("insert into t29142_1 value(20);") + tk.MustQuery("select sum(distinct a) as x from t29142_1 having x > some ( select a from t29142_2 where x in (a));").Check(nil) +} + +func TestIssue28650(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1(a int, index(a));") + tk.MustExec("create table t2(a int, c int, b char(50), index(a,c,b));") + tk.MustExec("set tidb_enable_rate_limit_action=off;") + + var wg util.WaitGroupWrapper + sql := `explain analyze + select /*+ stream_agg(@sel_1) stream_agg(@sel_3) %s(@sel_2 t2)*/ count(1) from + ( + SELECT t2.a AS t2_external_user_ext_id, t2.b AS t2_t1_ext_id FROM t2 INNER JOIN (SELECT t1.a AS d_t1_ext_id FROM t1 GROUP BY t1.a) AS anon_1 ON anon_1.d_t1_ext_id = t2.a WHERE t2.c = 123 AND t2.b + IN ("%s") ) tmp` + + sqls := make([]string, 2) + wg.Run(func() { + inElems := make([]string, 1000) + for i := 0; i < len(inElems); i++ { + inElems[i] = fmt.Sprintf("wm_%dbDgAAwCD-v1QB%dxky-g_dxxQCw", rand.Intn(100), rand.Intn(100)) + } + sqls[0] = fmt.Sprintf(sql, "inl_join", strings.Join(inElems, "\",\"")) + sqls[1] = fmt.Sprintf(sql, "inl_hash_join", strings.Join(inElems, "\",\"")) + }) + + tk.MustExec("insert into t1 select rand()*400;") + for i := 0; i < 10; i++ { + tk.MustExec("insert into t1 select rand()*400 from t1;") + } + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionCancel + }) + defer func() { + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionLog + }) + }() + wg.Wait() + for _, sql := range sqls { + tk.MustExec("set @@tidb_mem_quota_query = 1073741824") // 1GB + require.Nil(t, tk.QueryToErr(sql)) + tk.MustExec("set @@tidb_mem_quota_query = 33554432") // 32MB, out of memory during executing + require.True(t, strings.Contains(tk.QueryToErr(sql).Error(), "Out Of Memory Quota!")) + tk.MustExec("set @@tidb_mem_quota_query = 65536") // 64KB, out of memory during building the plan + func() { + defer func() { + r := recover() + require.NotNil(t, r) + err := errors.Errorf("%v", r) + require.True(t, strings.Contains(err.Error(), "Out Of Memory Quota!")) + }() + tk.MustExec(sql) + }() + } +} + +func TestIssue30289(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + fpName := "github.com/pingcap/tidb/executor/issue30289" + require.NoError(t, failpoint.Enable(fpName, `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable(fpName)) + }() + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + err := tk.QueryToErr("select /*+ hash_join(t1) */ * from t t1 join t t2 on t1.a=t2.a") + require.Regexp(t, "issue30289 build return error", err.Error()) +} + +func TestIssue29498(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("DROP TABLE IF EXISTS t1;") + tk.MustExec("CREATE TABLE t1 (t3 TIME(3), d DATE, t TIME);") + tk.MustExec("INSERT INTO t1 VALUES ('00:00:00.567', '2002-01-01', '00:00:02');") + + res := tk.MustQuery("SELECT CONCAT(IFNULL(t3, d)) AS col1 FROM t1;") + row := res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp+3+1, len(row)) + require.Equal(t, "00:00:00.567", row[len(row)-12:]) + + res = tk.MustQuery("SELECT IFNULL(t3, d) AS col1 FROM t1;") + row = res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp+3+1, len(row)) + require.Equal(t, "00:00:00.567", row[len(row)-12:]) + + res = tk.MustQuery("SELECT CONCAT(IFNULL(t, d)) AS col1 FROM t1;") + row = res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp, len(row)) + require.Equal(t, "00:00:02", row[len(row)-8:]) + + res = tk.MustQuery("SELECT IFNULL(t, d) AS col1 FROM t1;") + row = res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp, len(row)) + require.Equal(t, "00:00:02", row[len(row)-8:]) + + res = tk.MustQuery("SELECT CONCAT(xx) FROM (SELECT t3 AS xx FROM t1 UNION SELECT d FROM t1) x ORDER BY -xx LIMIT 1;") + row = res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp+3+1, len(row)) + require.Equal(t, "00:00:00.567", row[len(row)-12:]) + + res = tk.MustQuery("SELECT CONCAT(CASE WHEN d IS NOT NULL THEN t3 ELSE d END) AS col1 FROM t1;") + row = res.Rows()[0][0].(string) + require.Equal(t, mysql.MaxDatetimeWidthNoFsp+3+1, len(row)) + require.Equal(t, "00:00:00.567", row[len(row)-12:]) +} + +func TestIssue30971(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (id int);") + tk.MustExec("create table t2 (id int, c int);") + + testCases := []struct { + sql string + fields int + }{ + // Fix a bug that the column length field returned to client is incorrect using MySQL prepare protocol. + {"select * from t1 union select 1 from t1", 1}, + {"select c from t2 union select * from t1", 1}, + {"select * from t1", 1}, + {"select * from t2 where c in (select * from t1)", 2}, + {"insert into t1 values (?)", 0}, + {"update t1 set id = ?", 0}, + } + for _, test := range testCases { + _, _, fields, err := tk.Session().PrepareStmt(test.sql) + require.NoError(t, err) + require.Len(t, fields, test.fields) + } +} + +func TestIndexJoin31494(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1(a int(11) default null, b int(11) default null, key(b));") + insertStr := "insert into t1 values(1, 1)" + for i := 1; i < 32768; i++ { + insertStr += fmt.Sprintf(", (%d, %d)", i, i) + } + tk.MustExec(insertStr) + tk.MustExec("create table t2(a int(11) default null, b int(11) default null, c int(11) default null)") + insertStr = "insert into t2 values(1, 1, 1)" + for i := 1; i < 32768; i++ { + insertStr += fmt.Sprintf(", (%d, %d, %d)", i, i, i) + } + tk.MustExec(insertStr) + sm := &mockSessionManager1{ + PS: make([]*util.ProcessInfo, 0), + } + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionCancel + }) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("set @@tidb_mem_quota_query=2097152;") + // This bug will be reproduced in 10 times. + for i := 0; i < 10; i++ { + err := tk.QueryToErr("select /*+ inl_join(t1) */ * from t1 right join t2 on t1.b=t2.b;") + require.Error(t, err) + require.Regexp(t, "Out Of Memory Quota!.*", err.Error()) + err = tk.QueryToErr("select /*+ inl_hash_join(t1) */ * from t1 right join t2 on t1.b=t2.b;") + require.Error(t, err) + require.Regexp(t, "Out Of Memory Quota!.*", err.Error()) + } +} + +// Details at https://github.com/pingcap/tidb/issues/31038 +func TestFix31038(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableCollectExecutionInfo = false + }) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t123") + tk.MustExec("create table t123 (id int);") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/copr/disable-collect-execution", `return(true)`)) + tk.MustQuery("select * from t123;") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/copr/disable-collect-execution")) +} + +func TestFix31530(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk2.MustExec("use test") + defer func() { + tk.MustExec("drop table if exists t1") + }() + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (id int primary key, v int)") + tk.MustExec("insert into t1 values(1, 10)") + tk.MustExec("begin pessimistic") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 10")) + + // update t1 before session1 transaction not finished + tk2.MustExec("update t1 set v=11 where id=1") + + tk.MustQuery("(select 'a' as c, id, v from t1 for update) union all (select 'b', id, v from t1) order by c").Check(testkit.Rows("a 1 11", "b 1 10")) + tk.MustQuery("(select 'a' as c, id, v from t1) union all (select 'b', id, v from t1 for update) order by c").Check(testkit.Rows("a 1 10", "b 1 11")) + tk.MustQuery("(select 'a' as c, id, v from t1 where id=1 for update) union all (select 'b', id, v from t1 where id=1) order by c").Check(testkit.Rows("a 1 11", "b 1 10")) + tk.MustQuery("(select 'a' as c, id, v from t1 where id=1) union all (select 'b', id, v from t1 where id=1 for update) order by c").Check(testkit.Rows("a 1 10", "b 1 11")) + tk.MustExec("rollback") +} + +func TestFix31537(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE trade ( + t_id bigint(16) NOT NULL AUTO_INCREMENT, + t_dts datetime NOT NULL, + t_st_id char(4) NOT NULL, + t_tt_id char(3) NOT NULL, + t_is_cash tinyint(1) NOT NULL, + t_s_symb char(15) NOT NULL, + t_qty mediumint(7) NOT NULL, + t_bid_price decimal(8,2) NOT NULL, + t_ca_id bigint(12) NOT NULL, + t_exec_name varchar(49) NOT NULL, + t_trade_price decimal(8,2) DEFAULT NULL, + t_chrg decimal(10,2) NOT NULL, + t_comm decimal(10,2) NOT NULL, + t_tax decimal(10,2) NOT NULL, + t_lifo tinyint(1) NOT NULL, + PRIMARY KEY (t_id) /*T![clustered_index] CLUSTERED */, + KEY i_t_ca_id_dts (t_ca_id,t_dts), + KEY i_t_s_symb_dts (t_s_symb,t_dts), + CONSTRAINT fk_trade_st FOREIGN KEY (t_st_id) REFERENCES status_type (st_id), + CONSTRAINT fk_trade_tt FOREIGN KEY (t_tt_id) REFERENCES trade_type (tt_id), + CONSTRAINT fk_trade_s FOREIGN KEY (t_s_symb) REFERENCES security (s_symb), + CONSTRAINT fk_trade_ca FOREIGN KEY (t_ca_id) REFERENCES customer_account (ca_id) +) ;`) + tk.MustExec(`CREATE TABLE trade_history ( + th_t_id bigint(16) NOT NULL, + th_dts datetime NOT NULL, + th_st_id char(4) NOT NULL, + PRIMARY KEY (th_t_id,th_st_id) /*T![clustered_index] NONCLUSTERED */, + KEY i_th_t_id_dts (th_t_id,th_dts), + CONSTRAINT fk_trade_history_t FOREIGN KEY (th_t_id) REFERENCES trade (t_id), + CONSTRAINT fk_trade_history_st FOREIGN KEY (th_st_id) REFERENCES status_type (st_id) +); +`) + tk.MustExec(`CREATE TABLE status_type ( + st_id char(4) NOT NULL, + st_name char(10) NOT NULL, + PRIMARY KEY (st_id) /*T![clustered_index] NONCLUSTERED */ +);`) + tk.MustQuery(`trace plan SELECT T_ID, T_S_SYMB, T_QTY, ST_NAME, TH_DTS FROM ( SELECT T_ID AS ID FROM TRADE WHERE T_CA_ID = 43000014236 ORDER BY T_DTS DESC LIMIT 10 ) T, TRADE, TRADE_HISTORY, STATUS_TYPE WHERE TRADE.T_ID = ID AND TRADE_HISTORY.TH_T_ID = TRADE.T_ID AND STATUS_TYPE.ST_ID = TRADE_HISTORY.TH_ST_ID ORDER BY TH_DTS DESC LIMIT 30;`) +} + +func TestIssue30382(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_enable_list_partition = ON;") + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1 (c_int int, c_str varchar(40), c_decimal decimal(12, 6), primary key (c_int) , key(c_str(2)) , key(c_decimal) ) partition by list (c_int) ( partition p0 values IN (1, 5, 9, 13, 17, 21, 25, 29, 33, 37), partition p1 values IN (2, 6, 10, 14, 18, 22, 26, 30, 34, 38), partition p2 values IN (3, 7, 11, 15, 19, 23, 27, 31, 35, 39), partition p3 values IN (4, 8, 12, 16, 20, 24, 28, 32, 36, 40)) ;") + tk.MustExec("create table t2 (c_int int, c_str varchar(40), c_decimal decimal(12, 6), primary key (c_int) , key(c_str) , key(c_decimal) ) partition by hash (c_int) partitions 4;") + tk.MustExec("insert into t1 values (6, 'musing mayer', 1.280), (7, 'wizardly heisenberg', 6.589), (8, 'optimistic swirles', 9.633), (9, 'hungry haslett', 2.659), (10, 'stupefied wiles', 2.336);") + tk.MustExec("insert into t2 select * from t1 ;") + tk.MustExec("begin;") + tk.MustQuery("select * from t1 where c_str <> any (select c_str from t2 where c_decimal < 5) for update;").Sort().Check(testkit.Rows( + "10 stupefied wiles 2.336000", + "6 musing mayer 1.280000", + "7 wizardly heisenberg 6.589000", + "8 optimistic swirles 9.633000", + "9 hungry haslett 2.659000")) + tk.MustQuery("explain format = 'brief' select * from t1 where c_str <> any (select c_str from t2 where c_decimal < 5) for update;").Check(testkit.Rows( + "SelectLock 6400.00 root for update 0", + "└─HashJoin 6400.00 root CARTESIAN inner join, other cond:or(gt(Column#8, 1), or(ne(test.t1.c_str, Column#7), if(ne(Column#9, 0), NULL, 0)))", + " ├─Selection(Build) 0.80 root ne(Column#10, 0)", + " │ └─StreamAgg 1.00 root funcs:max(Column#17)->Column#7, funcs:count(distinct Column#18)->Column#8, funcs:sum(Column#19)->Column#9, funcs:count(1)->Column#10", + " │ └─Projection 3323.33 root test.t2.c_str, test.t2.c_str, cast(isnull(test.t2.c_str), decimal(20,0) BINARY)->Column#19", + " │ └─TableReader 3323.33 root partition:all data:Selection", + " │ └─Selection 3323.33 cop[tikv] lt(test.t2.c_decimal, 5)", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 8000.00 root partition:all data:Selection", + " └─Selection 8000.00 cop[tikv] if(isnull(test.t1.c_str), NULL, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo")) + tk.MustExec("commit") +} + +func Test12201(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists e") + tk.MustExec("create table e (e enum('a', 'b'))") + tk.MustExec("insert into e values ('a'), ('b')") + tk.MustQuery("select * from e where case 1 when 0 then e end").Check(testkit.Rows()) + tk.MustQuery("select * from e where case 1 when 1 then e end").Check(testkit.Rows("a", "b")) + tk.MustQuery("select * from e where case e when 1 then e end").Check(testkit.Rows("a")) + tk.MustQuery("select * from e where case 1 when e then e end").Check(testkit.Rows("a")) +} + +func TestIssue21451(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (en enum('c', 'b', 'a'));") + tk.MustExec("insert into t values ('a'), ('b'), ('c');") + tk.MustQuery("select max(en) from t;").Check(testkit.Rows("c")) + tk.MustQuery("select min(en) from t;").Check(testkit.Rows("a")) + tk.MustQuery("select * from t order by en;").Check(testkit.Rows("c", "b", "a")) + + tk.MustExec("drop table t") + tk.MustExec("create table t(s set('c', 'b', 'a'));") + tk.MustExec("insert into t values ('a'), ('b'), ('c');") + tk.MustQuery("select max(s) from t;").Check(testkit.Rows("c")) + tk.MustQuery("select min(s) from t;").Check(testkit.Rows("a")) + + tk.MustExec("drop table t") + tk.MustExec("create table t(id int, en enum('c', 'b', 'a'))") + tk.MustExec("insert into t values (1, 'a'),(2, 'b'), (3, 'c'), (1, 'c');") + tk.MustQuery("select id, max(en) from t where id=1 group by id;").Check(testkit.Rows("1 c")) + tk.MustQuery("select id, min(en) from t where id=1 group by id;").Check(testkit.Rows("1 a")) + tk.MustExec("drop table t") + + tk.MustExec("create table t(id int, s set('c', 'b', 'a'));") + tk.MustExec("insert into t values (1, 'a'),(2, 'b'), (3, 'c'), (1, 'c');") + tk.MustQuery("select id, max(s) from t where id=1 group by id;").Check(testkit.Rows("1 c")) + tk.MustQuery("select id, min(s) from t where id=1 group by id;").Check(testkit.Rows("1 a")) + + tk.MustExec("drop table t") + tk.MustExec("create table t(e enum('e','d','c','b','a'))") + tk.MustExec("insert into t values ('e'),('d'),('c'),('b'),('a');") + tk.MustQuery("select * from t order by e limit 1;").Check(testkit.Rows("e")) + + tk.MustExec("drop table t") + tk.MustExec("create table t(s set('e', 'd', 'c', 'b', 'a'))") + tk.MustExec("insert into t values ('e'),('d'),('c'),('b'),('a');") + tk.MustQuery("select * from t order by s limit 1;").Check(testkit.Rows("e")) + tk.MustExec("drop table t") +} + +func TestIssue15563(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustQuery("select distinct 0.7544678906163867 / 0.68234634;").Check(testkit.Rows("1.10569639842486251190")) +} + +func TestIssue22231(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_issue_22231") + tk.MustExec("create table t_issue_22231(a datetime)") + tk.MustExec("insert into t_issue_22231 values('2020--05-20 01:22:12')") + tk.MustQuery("select * from t_issue_22231 where a >= '2020-05-13 00:00:00 00:00:00' and a <= '2020-05-28 23:59:59 00:00:00'").Check(testkit.Rows("2020-05-20 01:22:12")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-13 00:00:00 00:00:00'", "Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) + + tk.MustQuery("select cast('2020-10-22 10:31-10:12' as datetime)").Check(testkit.Rows("2020-10-22 10:31:10")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-10-22 10:31-10:12'")) + tk.MustQuery("select cast('2020-05-28 23:59:59 00:00:00' as datetime)").Check(testkit.Rows("2020-05-28 23:59:59")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) + tk.MustExec("drop table if exists t_issue_22231") +} + +// TestIssue2612 is related with https://github.com/pingcap/tidb/issues/2612 +func TestIssue2612(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t ( + create_at datetime NOT NULL DEFAULT '1000-01-01 00:00:00', + finish_at datetime NOT NULL DEFAULT '1000-01-01 00:00:00');`) + tk.MustExec(`insert into t values ('2016-02-13 15:32:24', '2016-02-11 17:23:22');`) + rs, err := tk.Exec(`select timediff(finish_at, create_at) from t;`) + require.NoError(t, err) + req := rs.NewChunk(nil) + err = rs.Next(context.Background(), req) + require.NoError(t, err) + require.Equal(t, "-46:09:02", req.GetRow(0).GetDuration(0, 0).String()) + require.Nil(t, rs.Close()) +} + +// TestIssue345 is related with https://github.com/pingcap/tidb/issues/345 +func TestIssue345(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t1, t2`) + tk.MustExec(`create table t1 (c1 int);`) + tk.MustExec(`create table t2 (c2 int);`) + tk.MustExec(`insert into t1 values (1);`) + tk.MustExec(`insert into t2 values (2);`) + tk.MustExec(`update t1, t2 set t1.c1 = 2, t2.c2 = 1;`) + tk.MustExec(`update t1, t2 set c1 = 2, c2 = 1;`) + tk.MustExec(`update t1 as a, t2 as b set a.c1 = 2, b.c2 = 1;`) + + // Check t1 content + r := tk.MustQuery("SELECT * FROM t1;") + r.Check(testkit.Rows("2")) + // Check t2 content + r = tk.MustQuery("SELECT * FROM t2;") + r.Check(testkit.Rows("1")) + + tk.MustExec(`update t1 as a, t2 as t1 set a.c1 = 1, t1.c2 = 2;`) + // Check t1 content + r = tk.MustQuery("SELECT * FROM t1;") + r.Check(testkit.Rows("1")) + // Check t2 content + r = tk.MustQuery("SELECT * FROM t2;") + r.Check(testkit.Rows("2")) + + _, err := tk.Exec(`update t1 as a, t2 set t1.c1 = 10;`) + require.Error(t, err) +} + +func TestIssue5055(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t1, t2`) + tk.MustExec(`create table t1 (a int);`) + tk.MustExec(`create table t2 (a int);`) + tk.MustExec(`insert into t1 values(1);`) + tk.MustExec(`insert into t2 values(1);`) + result := tk.MustQuery("select tbl1.* from (select t1.a, 1 from t1) tbl1 left join t2 tbl2 on tbl1.a = tbl2.a order by tbl1.a desc limit 1;") + result.Check(testkit.Rows("1 1")) +} + +// TestIssue4024 This tests https://github.com/pingcap/tidb/issues/4024 +func TestIssue4024(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database test2") + tk.MustExec("use test2") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t values(1)") + tk.MustExec("use test") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t values(1)") + tk.MustExec("update t, test2.t set test2.t.a=2") + tk.MustQuery("select * from t").Check(testkit.Rows("1")) + tk.MustQuery("select * from test2.t").Check(testkit.Rows("2")) + tk.MustExec("update test.t, test2.t set test.t.a=3") + tk.MustQuery("select * from t").Check(testkit.Rows("3")) + tk.MustQuery("select * from test2.t").Check(testkit.Rows("2")) +} + +func TestIssue5666(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@profiling=1") + tk.MustQuery("SELECT QUERY_ID, SUM(DURATION) AS SUM_DURATION FROM INFORMATION_SCHEMA.PROFILING GROUP BY QUERY_ID;").Check(testkit.Rows("0 0")) +} + +func TestIssue5341(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop table if exists test.t") + tk.MustExec("create table test.t(a char)") + tk.MustExec("insert into test.t value('a')") + tk.MustQuery("select * from test.t where a < 1 order by a limit 0;").Check(testkit.Rows()) +} + +func TestIssue16921(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a float);") + tk.MustExec("create index a on t(a);") + tk.MustExec("insert into t values (1.0), (NULL), (0), (2.0);") + tk.MustQuery("select `a` from `t` use index (a) where !`a`;").Check(testkit.Rows("0")) + tk.MustQuery("select `a` from `t` ignore index (a) where !`a`;").Check(testkit.Rows("0")) + tk.MustQuery("select `a` from `t` use index (a) where `a`;").Check(testkit.Rows("1", "2")) + tk.MustQuery("select `a` from `t` ignore index (a) where `a`;").Check(testkit.Rows("1", "2")) + tk.MustQuery("select a from t use index (a) where not a is true;").Check(testkit.Rows("", "0")) + tk.MustQuery("select a from t use index (a) where not not a is true;").Check(testkit.Rows("1", "2")) + tk.MustQuery("select a from t use index (a) where not not a;").Check(testkit.Rows("1", "2")) + tk.MustQuery("select a from t use index (a) where not not not a is true;").Check(testkit.Rows("", "0")) + tk.MustQuery("select a from t use index (a) where not not not a;").Check(testkit.Rows("0")) +} + +func TestIssue19100(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1 (c decimal);") + tk.MustExec("create table t2 (c decimal, key(c));") + tk.MustExec("insert into t1 values (null);") + tk.MustExec("insert into t2 values (null);") + tk.MustQuery("select count(*) from t1 where not c;").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from t2 where not c;").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from t1 where c;").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from t2 where c;").Check(testkit.Rows("0")) +} + +func TestIssue27232(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a timestamp)") + tk.MustExec("insert into t values (\"1970-07-23 10:04:59\"), (\"2038-01-19 03:14:07\")") + tk.MustQuery("select * from t where date_sub(a, interval 10 month) = date_sub(\"1970-07-23 10:04:59\", interval 10 month)").Check(testkit.Rows("1970-07-23 10:04:59")) + tk.MustQuery("select * from t where timestampadd(hour, 1, a ) = timestampadd(hour, 1, \"2038-01-19 03:14:07\")").Check(testkit.Rows("2038-01-19 03:14:07")) +} + +func TestIssue15718(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt(a decimal(10, 0), b varchar(1), c time);") + tk.MustExec("insert into tt values(0, '2', null), (7, null, '1122'), (NULL, 'w', null), (NULL, '2', '3344'), (NULL, NULL, '0'), (7, 'f', '33');") + tk.MustQuery("select a and b as d, a or c as e from tt;").Check(testkit.Rows("0 ", " 1", "0 ", " 1", " ", "0 1")) + + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table tt(a decimal(10, 0), b varchar(1), c time);") + tk.MustExec("insert into tt values(0, '2', '123'), (7, null, '1122'), (null, 'w', null);") + tk.MustQuery("select a and b as d, a, b from tt order by d limit 1;").Check(testkit.Rows(" 7 ")) + tk.MustQuery("select b or c as d, b, c from tt order by d limit 1;").Check(testkit.Rows(" w ")) + + tk.MustExec("drop table if exists t0;") + tk.MustExec("CREATE TABLE t0(c0 FLOAT);") + tk.MustExec("INSERT INTO t0(c0) VALUES (NULL);") + tk.MustQuery("SELECT * FROM t0 WHERE NOT(0 OR t0.c0);").Check(testkit.Rows()) +} + +func TestIssue15767(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists tt;") + tk.MustExec("create table t(a int, b char);") + tk.MustExec("insert into t values (1,'s'),(2,'b'),(1,'c'),(2,'e'),(1,'a');") + tk.MustExec("insert into t select * from t;") + tk.MustExec("insert into t select * from t;") + tk.MustExec("insert into t select * from t;") + tk.MustQuery("select b, count(*) from ( select b from t order by a limit 20 offset 2) as s group by b order by b;").Check(testkit.Rows("a 6", "c 7", "s 7")) +} + +func TestIssue16025(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t0;") + tk.MustExec("CREATE TABLE t0(c0 NUMERIC PRIMARY KEY);") + tk.MustExec("INSERT IGNORE INTO t0(c0) VALUES (NULL);") + tk.MustQuery("SELECT * FROM t0 WHERE c0;").Check(testkit.Rows()) +} + +func TestIssue16854(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE `t` ( `a` enum('WAITING','PRINTED','STOCKUP','CHECKED','OUTSTOCK','PICKEDUP','WILLBACK','BACKED') DEFAULT NULL)") + tk.MustExec("insert into t values(1),(2),(3),(4),(5),(6),(7);") + for i := 0; i < 7; i++ { + tk.MustExec("insert into t select * from t;") + } + tk.MustExec("set @@tidb_max_chunk_size=100;") + tk.MustQuery("select distinct a from t order by a").Check(testkit.Rows("WAITING", "PRINTED", "STOCKUP", "CHECKED", "OUTSTOCK", "PICKEDUP", "WILLBACK")) + tk.MustExec("drop table t") + + tk.MustExec("CREATE TABLE `t` ( `a` set('WAITING','PRINTED','STOCKUP','CHECKED','OUTSTOCK','PICKEDUP','WILLBACK','BACKED') DEFAULT NULL)") + tk.MustExec("insert into t values(1),(2),(3),(4),(5),(6),(7);") + for i := 0; i < 7; i++ { + tk.MustExec("insert into t select * from t;") + } + tk.MustExec("set @@tidb_max_chunk_size=100;") + tk.MustQuery("select distinct a from t order by a").Check(testkit.Rows("WAITING", "PRINTED", "WAITING,PRINTED", "STOCKUP", "WAITING,STOCKUP", "PRINTED,STOCKUP", "WAITING,PRINTED,STOCKUP")) + tk.MustExec("drop table t") +} + +func issue20975Prepare(t *testing.T, store kv.Storage) (*testkit.TestKit, *testkit.TestKit) { + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec("drop table if exists t1, t2") + tk2.MustExec("use test") + tk1.MustExec("create table t1(id int primary key, c int)") + tk1.MustExec("insert into t1 values(1, 10), (2, 20)") + return tk1, tk2 +} + +func TestIssue20975UpdateNoChange(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975Prepare(t, store) + tk1.MustExec("begin pessimistic") + tk1.MustExec("update t1 set c=c") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975Prepare(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdatePointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975Prepare(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id=1 for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id=1 for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdateBatchPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975Prepare(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id in (1, 2) for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id in (1, 2) for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func issue20975PreparePartitionTable(t *testing.T, store kv.Storage) (*testkit.TestKit, *testkit.TestKit) { + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec("drop table if exists t1, t2") + tk2.MustExec("use test") + tk1.MustExec(`create table t1(id int primary key, c int) partition by range (id) ( + partition p1 values less than (10), + partition p2 values less than (20) + )`) + tk1.MustExec("insert into t1 values(1, 10), (2, 20), (11, 30), (12, 40)") + return tk1, tk2 +} + +func TestIssue20975UpdateNoChangeWithPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975PreparePartitionTable(t, store) + + tk1.MustExec("begin pessimistic") + tk1.MustExec("update t1 set c=c") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdateWithPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := issue20975PreparePartitionTable(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdatePointGetWithPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1, tk2 := issue20975PreparePartitionTable(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id=1 for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id=12 for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id=1 for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id=12 for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func TestIssue20975SelectForUpdateBatchPointGetWithPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1, tk2 := issue20975PreparePartitionTable(t, store) + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id in (1, 2) for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id in (11, 12) for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") + + tk1.MustExec("begin") + tk1.MustExec("select * from t1 where id in (1, 11) for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id in (1, 2) for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id in (11, 12) for update") + tk2.MustExec("create table t2(a int)") + tk1.MustExec("commit") + + tk1.MustExec("begin pessimistic") + tk1.MustExec("select * from t1 where id in (1, 11) for update") + tk2.MustExec("drop table t2") + tk1.MustExec("commit") +} + +func TestIssue20305(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t2 (a year(4))") + tk.MustExec("insert into t2 values(69)") + tk.MustQuery("select * from t2 where a <= 69").Check(testkit.Rows("2069")) + // the following test is a regression test that matches MySQL's behavior. + tk.MustExec("drop table if exists t3") + tk.MustExec("CREATE TABLE `t3` (`y` year DEFAULT NULL, `a` int DEFAULT NULL)") + tk.MustExec("INSERT INTO `t3` VALUES (2069, 70), (2010, 11), (2155, 2156), (2069, 69)") + tk.MustQuery("SELECT * FROM `t3` where y <= a").Check(testkit.Rows("2155 2156")) +} + +func TestIssue22817(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t3") + tk.MustExec("create table t3 (a year)") + tk.MustExec("insert into t3 values (1991), (\"1992\"), (\"93\"), (94)") + tk.MustQuery("select * from t3 where a >= NULL").Check(testkit.Rows()) +} + +func TestIssue13953(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE `t` (`id` int(11) DEFAULT NULL, `tp_bigint` bigint(20) DEFAULT NULL )") + tk.MustExec("insert into t values(0,1),(1,9215570218099803537)") + tk.MustQuery("select A.tp_bigint,B.id from t A join t B on A.id < B.id * 16 where A.tp_bigint = B.id;").Check( + testkit.Rows("1 1")) +} + +func Test17780(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t0") + tk.MustExec("create table t0 (c0 double)") + tk.MustExec("insert into t0 values (1e30)") + tk.MustExec("update t0 set c0=0 where t0.c0 like 0") + // the update should not affect c0 + tk.MustQuery("select count(*) from t0 where c0 = 0").Check(testkit.Rows("0")) +} + +func TestIssue9918(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a year)") + tk.MustExec("insert into t values(0)") + tk.MustQuery("select cast(a as char) from t").Check(testkit.Rows("0000")) +} + +func Test13004(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + // see https://dev.mysql.com/doc/refman/5.6/en/date-and-time-literals.html, timestamp here actually produces a datetime + tk.MustQuery("SELECT TIMESTAMP '9999-01-01 00:00:00'").Check(testkit.Rows("9999-01-01 00:00:00")) +} + +func Test12178(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists ta") + tk.MustExec("create table ta(id decimal(60,2))") + tk.MustExec("insert into ta values (JSON_EXTRACT('{\"c\": \"1234567890123456789012345678901234567890123456789012345\"}', '$.c'))") + tk.MustQuery("select * from ta").Check(testkit.Rows("1234567890123456789012345678901234567890123456789012345.00")) +} + +func Test11883(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (f1 json)") + tk.MustExec("insert into t1(f1) values ('\"asd\"'),('\"asdf\"'),('\"asasas\"')") + tk.MustQuery("select f1 from t1 where json_extract(f1,\"$\") in (\"asd\",\"asasas\",\"asdf\")").Check(testkit.Rows("\"asd\"", "\"asdf\"", "\"asasas\"")) + tk.MustQuery("select f1 from t1 where json_extract(f1, '$') = 'asd'").Check(testkit.Rows("\"asd\"")) + // MySQL produces empty row for the following SQL, I doubt it should be MySQL's bug. + tk.MustQuery("select f1 from t1 where case json_extract(f1,\"$\") when \"asd\" then 1 else 0 end").Check(testkit.Rows("\"asd\"")) + tk.MustExec("delete from t1") + tk.MustExec("insert into t1 values ('{\"a\": 1}')") + // the first value in the tuple should be interpreted as string instead of JSON, so no row will be returned + tk.MustQuery("select f1 from t1 where f1 in ('{\"a\": 1}', 'asdf', 'asdf')").Check(testkit.Rows()) + // and if we explicitly cast it into a JSON value, the check will pass + tk.MustQuery("select f1 from t1 where f1 in (cast('{\"a\": 1}' as JSON), 'asdf', 'asdf')").Check(testkit.Rows("{\"a\": 1}")) + tk.MustQuery("select json_extract('\"asd\"', '$') = 'asd'").Check(testkit.Rows("1")) + tk.MustQuery("select json_extract('\"asd\"', '$') <=> 'asd'").Check(testkit.Rows("1")) + tk.MustQuery("select json_extract('\"asd\"', '$') <> 'asd'").Check(testkit.Rows("0")) + tk.MustQuery("select json_extract('{\"f\": 1.0}', '$.f') = 1.0").Check(testkit.Rows("1")) + tk.MustQuery("select json_extract('{\"f\": 1.0}', '$.f') = '1.0'").Check(testkit.Rows("0")) + tk.MustQuery("select json_extract('{\"n\": 1}', '$') = '{\"n\": 1}'").Check(testkit.Rows("0")) + tk.MustQuery("select json_extract('{\"n\": 1}', '$') <> '{\"n\": 1}'").Check(testkit.Rows("1")) +} + +func Test15492(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int)") + tk.MustExec("insert into t values (2, 20), (1, 10), (3, 30)") + tk.MustQuery("select a + 1 as field1, a as field2 from t order by field1, field2 limit 2").Check(testkit.Rows("2 1", "3 2")) +} + +func TestIssue23567(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + oriProbability := statistics.FeedbackProbability.Load() + statistics.FeedbackProbability.Store(1.0) + defer func() { statistics.FeedbackProbability.Store(oriProbability) }() + failpoint.Enable("github.com/pingcap/tidb/statistics/feedbackNoNDVCollect", `return("")`) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a bigint unsigned, b int, primary key(a))") + tk.MustExec("insert into t values (1, 1), (2, 2)") + tk.MustExec("analyze table t") + // The SQL should not panic. + tk.MustQuery("select count(distinct b) from t") + failpoint.Disable("github.com/pingcap/tidb/statistics/feedbackNoNDVCollect") +} + +func TestIssue33038(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t, t1") + tk.MustExec("create table t (id int, c int as (id))") + tk.MustExec("begin") + tk.MustExec("insert into t(id) values (1),(2),(3),(4)") + tk.MustExec("insert into t(id) select id from t") + tk.MustExec("insert into t(id) select id from t") + tk.MustExec("insert into t(id) select id from t") + tk.MustExec("insert into t(id) select id from t") + tk.MustExec("insert into t(id) values (5)") + tk.MustQuery("select * from t where c = 5").Check(testkit.Rows("5 5")) + + tk.MustExec("use test") + tk.MustExec("set @@tidb_max_chunk_size=16") + tk.MustExec("create table t1 (id int, c int as (id))") + tk.MustExec("insert into t1(id) values (1),(2),(3),(4)") + tk.MustExec("insert into t1(id) select id from t1") + tk.MustExec("insert into t1(id) select id from t1") + tk.MustExec("insert into t1(id) select id from t1") + tk.MustExec("insert into t1(id) values (5)") + tk.MustExec("alter table t1 cache") + + for { + tk.MustQuery("select * from t1 where c = 5").Check(testkit.Rows("5 5")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } +} + +func TestIssue33214(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (col enum('a', 'b', 'c') default null)") + tk.MustExec("insert into t values ('a'), ('b'), ('c'), (null), ('c')") + tk.MustExec("alter table t cache") + for { + tk.MustQuery("select col from t t1 where (select count(*) from t t2 where t2.col = t1.col or t2.col = 'sdf') > 1;").Check(testkit.Rows("c", "c")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } +} diff --git a/executor/executor_legacy_test.go b/executor/executor_legacy_test.go new file mode 100644 index 0000000000000..9c634158c3bea --- /dev/null +++ b/executor/executor_legacy_test.go @@ -0,0 +1,3544 @@ +// Copyright 2015 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "context" + "fmt" + "math" + "net" + "os" + "reflect" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + . "github.com/pingcap/check" + "github.com/pingcap/errors" + "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/meta" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/planner" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/server" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/admin" + "github.com/pingcap/tidb/util/memory" + "github.com/pingcap/tidb/util/mock" + "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/util/testleak" + "github.com/tikv/client-go/v2/oracle" + "github.com/tikv/client-go/v2/testutils" + "github.com/tikv/client-go/v2/tikv" + "github.com/tikv/client-go/v2/tikvrpc" + "google.golang.org/grpc" +) + +func TestT(t *testing.T) { + CustomVerboseFlag = true + *CustomParallelSuiteFlag = true + + TestingT(t) +} + +var _ = Suite(&testSuite{&baseTestSuite{}}) +var _ = Suite(&testSuiteP2{&baseTestSuite{}}) +var _ = SerialSuites(&testSuiteWithCliBaseCharset{}) +var _ = Suite(&testSuite2{&baseTestSuite{}}) +var _ = Suite(&testSuite3{&baseTestSuite{}}) +var _ = SerialSuites(&testClusterTableSuite{}) +var _ = SerialSuites(&testSerialSuite1{&baseTestSuite{}}) +var _ = SerialSuites(&testSerialSuite{&baseTestSuite{}}) + +type testSuite struct{ *baseTestSuite } +type testSuiteP2 struct{ *baseTestSuite } +type testSerialSuite struct{ *baseTestSuite } + +type baseTestSuite struct { + cluster testutils.Cluster + store kv.Storage + domain *domain.Domain + *parser.Parser +} + +func (s *baseTestSuite) SetUpSuite(c *C) { + s.Parser = parser.New() + store, err := mockstore.NewMockStore( + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockstore.BootstrapWithSingleStore(c) + s.cluster = c + }), + ) + c.Assert(err, IsNil) + s.store = store + session.SetSchemaLease(0) + session.DisableStats4Test() + d, err := session.BootstrapSession(s.store) + c.Assert(err, IsNil) + se, err := session.CreateSession4Test(s.store) + c.Assert(err, IsNil) + se.Close() + d.SetStatsUpdating(true) + s.domain = d +} + +func (s *baseTestSuite) TearDownSuite(c *C) { + s.domain.Close() + c.Assert(s.store.Close(), IsNil) +} + +func (s *testSuite) TearDownTest(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + r := tk.MustQuery("show tables") + for _, tb := range r.Rows() { + tableName := tb[0] + tk.MustExec(fmt.Sprintf("drop table %v", tableName)) + } +} + +func (s *testSuite3) TestAdmin(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists admin_test") + tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1))") + tk.MustExec("insert admin_test (c1) values (1),(2),(NULL)") + + ctx := context.Background() + // cancel DDL jobs test + r, err := tk.Exec("admin cancel ddl jobs 1") + c.Assert(err, IsNil, Commentf("err %v", err)) + req := r.NewChunk(nil) + err = r.Next(ctx, req) + c.Assert(err, IsNil) + row := req.GetRow(0) + c.Assert(row.Len(), Equals, 2) + c.Assert(row.GetString(0), Equals, "1") + c.Assert(row.GetString(1), Matches, "*DDL Job:1 not found") + + // show ddl test; + r, err = tk.Exec("admin show ddl") + c.Assert(err, IsNil) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + c.Assert(err, IsNil) + row = req.GetRow(0) + c.Assert(row.Len(), Equals, 6) + txn, err := s.store.Begin() + c.Assert(err, IsNil) + ddlInfo, err := admin.GetDDLInfo(txn) + c.Assert(err, IsNil) + c.Assert(row.GetInt64(0), Equals, ddlInfo.SchemaVer) + // TODO: Pass this test. + // rowOwnerInfos := strings.Split(row.Data[1].GetString(), ",") + // ownerInfos := strings.Split(ddlInfo.Owner.String(), ",") + // c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0]) + serverInfo, err := infosync.GetServerInfoByID(ctx, row.GetString(1)) + c.Assert(err, IsNil) + c.Assert(row.GetString(2), Equals, serverInfo.IP+":"+ + strconv.FormatUint(uint64(serverInfo.Port), 10)) + c.Assert(row.GetString(3), Equals, "") + req = r.NewChunk(nil) + err = r.Next(ctx, req) + c.Assert(err, IsNil) + c.Assert(req.NumRows() == 0, IsTrue) + err = txn.Rollback() + c.Assert(err, IsNil) + + // show DDL jobs test + r, err = tk.Exec("admin show ddl jobs") + c.Assert(err, IsNil) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + c.Assert(err, IsNil) + row = req.GetRow(0) + c.Assert(row.Len(), Equals, 12) + txn, err = s.store.Begin() + c.Assert(err, IsNil) + historyJobs, err := admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) + c.Assert(len(historyJobs), Greater, 1) + c.Assert(len(row.GetString(1)), Greater, 0) + c.Assert(err, IsNil) + c.Assert(row.GetInt64(0), Equals, historyJobs[0].ID) + c.Assert(err, IsNil) + + r, err = tk.Exec("admin show ddl jobs 20") + c.Assert(err, IsNil) + req = r.NewChunk(nil) + err = r.Next(ctx, req) + c.Assert(err, IsNil) + row = req.GetRow(0) + c.Assert(row.Len(), Equals, 12) + c.Assert(row.GetInt64(0), Equals, historyJobs[0].ID) + c.Assert(err, IsNil) + + // show DDL job queries test + tk.MustExec("use test") + tk.MustExec("drop table if exists admin_test2") + tk.MustExec("create table admin_test2 (c1 int, c2 int, c3 int default 1, index (c1))") + result := tk.MustQuery(`admin show ddl job queries 1, 1, 1`) + result.Check(testkit.Rows()) + result = tk.MustQuery(`admin show ddl job queries 1, 2, 3, 4`) + result.Check(testkit.Rows()) + historyJobs, err = admin.GetHistoryDDLJobs(txn, admin.DefNumHistoryJobs) + result = tk.MustQuery(fmt.Sprintf("admin show ddl job queries %d", historyJobs[0].ID)) + result.Check(testkit.Rows(historyJobs[0].Query)) + c.Assert(err, IsNil) + + // check table test + tk.MustExec("create table admin_test1 (c1 int, c2 int default 1, index (c1))") + tk.MustExec("insert admin_test1 (c1) values (21),(22)") + r, err = tk.Exec("admin check table admin_test, admin_test1") + c.Assert(err, IsNil) + c.Assert(r, IsNil) + // error table name + err = tk.ExecToErr("admin check table admin_test_error") + c.Assert(err, NotNil) + // different index values + sctx := tk.Se.(sessionctx.Context) + dom := domain.GetDomain(sctx) + is := dom.InfoSchema() + c.Assert(is, NotNil) + tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("admin_test")) + c.Assert(err, IsNil) + c.Assert(tb.Indices(), HasLen, 1) + _, err = tb.Indices()[0].Create(mock.NewContext(), txn, types.MakeDatums(int64(10)), kv.IntHandle(1), nil) + c.Assert(err, IsNil) + err = txn.Commit(context.Background()) + c.Assert(err, IsNil) + errAdmin := tk.ExecToErr("admin check table admin_test") + c.Assert(errAdmin, NotNil) + + if config.CheckTableBeforeDrop { + err = tk.ExecToErr("drop table admin_test") + c.Assert(err.Error(), Equals, errAdmin.Error()) + + // Drop inconsistency index. + tk.MustExec("alter table admin_test drop index c1") + tk.MustExec("admin check table admin_test") + } + // checksum table test + tk.MustExec("create table checksum_with_index (id int, count int, PRIMARY KEY(id), KEY(count))") + tk.MustExec("create table checksum_without_index (id int, count int, PRIMARY KEY(id))") + r, err = tk.Exec("admin checksum table checksum_with_index, checksum_without_index") + c.Assert(err, IsNil) + res := tk.ResultSetToResult(r, Commentf("admin checksum table")) + // Mocktikv returns 1 for every table/index scan, then we will xor the checksums of a table. + // For "checksum_with_index", we have two checksums, so the result will be 1^1 = 0. + // For "checksum_without_index", we only have one checksum, so the result will be 1. + res.Sort().Check(testkit.Rows("test checksum_with_index 0 2 2", "test checksum_without_index 1 1 1")) + + tk.MustExec("drop table if exists t1;") + tk.MustExec("CREATE TABLE t1 (c2 BOOL, PRIMARY KEY (c2));") + tk.MustExec("INSERT INTO t1 SET c2 = '0';") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c3 DATETIME NULL DEFAULT '2668-02-03 17:19:31';") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx2 (c3);") + tk.MustExec("ALTER TABLE t1 ADD COLUMN c4 bit(10) default 127;") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx3 (c4);") + tk.MustExec("admin check table t1;") + + // Test admin show ddl jobs table name after table has been droped. + tk.MustExec("drop table if exists t1;") + re := tk.MustQuery("admin show ddl jobs 1") + rows := re.Rows() + c.Assert(len(rows), Equals, 1) + c.Assert(rows[0][2], Equals, "t1") + + // Test for reverse scan get history ddl jobs when ddl history jobs queue has multiple regions. + txn, err = s.store.Begin() + c.Assert(err, IsNil) + historyJobs, err = admin.GetHistoryDDLJobs(txn, 20) + c.Assert(err, IsNil) + + // Split region for history ddl job queues. + m := meta.NewMeta(txn) + startKey := meta.DDLJobHistoryKey(m, 0) + endKey := meta.DDLJobHistoryKey(m, historyJobs[0].ID) + s.cluster.SplitKeys(startKey, endKey, int(historyJobs[0].ID/5)) + + historyJobs2, err := admin.GetHistoryDDLJobs(txn, 20) + c.Assert(err, IsNil) + c.Assert(historyJobs, DeepEquals, historyJobs2) +} + +func (s *testSuiteP2) TestAdminShowDDLJobs(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("create database if not exists test_admin_show_ddl_jobs") + tk.MustExec("use test_admin_show_ddl_jobs") + tk.MustExec("create table t (a int);") + + re := tk.MustQuery("admin show ddl jobs 1") + row := re.Rows()[0] + c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") + jobID, err := strconv.Atoi(row[0].(string)) + c.Assert(err, IsNil) + + err = kv.RunInNewTxn(context.Background(), s.store, true, func(ctx context.Context, txn kv.Transaction) error { + t := meta.NewMeta(txn) + job, err := t.GetHistoryDDLJob(int64(jobID)) + c.Assert(err, IsNil) + c.Assert(job, NotNil) + // Test for compatibility. Old TiDB version doesn't have SchemaName field, and the BinlogInfo maybe nil. + // See PR: 11561. + job.BinlogInfo = nil + job.SchemaName = "" + err = t.AddHistoryDDLJob(job, true) + c.Assert(err, IsNil) + return nil + }) + c.Assert(err, IsNil) + + re = tk.MustQuery("admin show ddl jobs 1") + row = re.Rows()[0] + c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") + + re = tk.MustQuery("admin show ddl jobs 1 where job_type='create table'") + row = re.Rows()[0] + c.Assert(row[1], Equals, "test_admin_show_ddl_jobs") + c.Assert(row[10], Equals, "") + + // Test the START_TIME and END_TIME field. + tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) + re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") + row = re.Rows()[0] + createTime, err := types.ParseDatetime(nil, row[8].(string)) + c.Assert(err, IsNil) + startTime, err := types.ParseDatetime(nil, row[9].(string)) + c.Assert(err, IsNil) + endTime, err := types.ParseDatetime(nil, row[10].(string)) + c.Assert(err, IsNil) + tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) + re = tk.MustQuery("admin show ddl jobs where end_time is not NULL") + row2 := re.Rows()[0] + c.Assert(row[8], Not(Equals), row2[8]) + c.Assert(row[9], Not(Equals), row2[9]) + c.Assert(row[10], Not(Equals), row2[10]) + createTime2, err := types.ParseDatetime(nil, row2[8].(string)) + c.Assert(err, IsNil) + startTime2, err := types.ParseDatetime(nil, row2[9].(string)) + c.Assert(err, IsNil) + endTime2, err := types.ParseDatetime(nil, row2[10].(string)) + c.Assert(err, IsNil) + loc, err := time.LoadLocation("Asia/Shanghai") + c.Assert(err, IsNil) + loc2, err := time.LoadLocation("Europe/Amsterdam") + c.Assert(err, IsNil) + t, err := createTime.GoTime(loc) + c.Assert(err, IsNil) + t2, err := createTime2.GoTime(loc2) + c.Assert(err, IsNil) + c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) + t, err = startTime.GoTime(loc) + c.Assert(err, IsNil) + t2, err = startTime2.GoTime(loc2) + c.Assert(err, IsNil) + c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) + t, err = endTime.GoTime(loc) + c.Assert(err, IsNil) + t2, err = endTime2.GoTime(loc2) + c.Assert(err, IsNil) + c.Assert(t.In(time.UTC), Equals, t2.In(time.UTC)) +} + +func (s *testSuiteP2) TestAdminShowDDLJobsInfo(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("drop database if exists test_admin_show_ddl_jobs") + tk.MustExec("drop placement policy if exists x") + tk.MustExec("drop placement policy if exists y") + defer func() { + tk.MustExec("drop database if exists test_admin_show_ddl_jobs") + tk.MustExec("drop placement policy if exists x") + tk.MustExec("drop placement policy if exists y") + }() + + // Test for issue: https://github.com/pingcap/tidb/issues/29915 + tk.MustExec("create placement policy x followers=4;") + tk.MustExec("create placement policy y " + + "PRIMARY_REGION=\"cn-east-1\" " + + "REGIONS=\"cn-east-1, cn-east-2\" " + + "FOLLOWERS=2") + tk.MustExec("create database if not exists test_admin_show_ddl_jobs") + tk.MustExec("use test_admin_show_ddl_jobs") + + tk.MustExec("create table t (a int);") + tk.MustExec("create table t1 (a int);") + + tk.MustExec("alter table t placement policy x;") + c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table placement") + + tk.MustExec("rename table t to tt, t1 to tt1") + c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "rename tables") + + tk.MustExec("create table tt2 (c int) PARTITION BY RANGE (c) " + + "(PARTITION p0 VALUES LESS THAN (6)," + + "PARTITION p1 VALUES LESS THAN (11)," + + "PARTITION p2 VALUES LESS THAN (16)," + + "PARTITION p3 VALUES LESS THAN (21));") + tk.MustExec("alter table tt2 partition p0 placement policy y") + c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table partition placement") + + tk.MustExec("alter table tt1 cache") + c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table cache") + tk.MustExec("alter table tt1 nocache") + c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table nocache") +} + +func (s *testSuiteP2) TestAdminChecksumOfPartitionedTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("USE test;") + tk.MustExec("DROP TABLE IF EXISTS admin_checksum_partition_test;") + tk.MustExec("CREATE TABLE admin_checksum_partition_test (a INT) PARTITION BY HASH(a) PARTITIONS 4;") + tk.MustExec("INSERT INTO admin_checksum_partition_test VALUES (1), (2);") + + r := tk.MustQuery("ADMIN CHECKSUM TABLE admin_checksum_partition_test;") + r.Check(testkit.Rows("test admin_checksum_partition_test 1 5 5")) +} + +func (s *testSuiteP2) TestUnion(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + testSQL := `drop table if exists union_test; create table union_test(id int);` + tk.MustExec(testSQL) + + testSQL = `drop table if exists union_test;` + tk.MustExec(testSQL) + testSQL = `create table union_test(id int);` + tk.MustExec(testSQL) + testSQL = `insert union_test values (1),(2)` + tk.MustExec(testSQL) + + testSQL = `select * from (select id from union_test union select id from union_test) t order by id;` + r := tk.MustQuery(testSQL) + r.Check(testkit.Rows("1", "2")) + + r = tk.MustQuery("select 1 union all select 1") + r.Check(testkit.Rows("1", "1")) + + r = tk.MustQuery("select 1 union all select 1 union select 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1, 1") + r.Check(testkit.Rows("2")) + + r = tk.MustQuery("select id from union_test union all (select 1) order by id desc") + r.Check(testkit.Rows("2", "1", "1")) + + r = tk.MustQuery("select id as a from union_test union (select 1) order by a desc") + r.Check(testkit.Rows("2", "1")) + + r = tk.MustQuery(`select null as a union (select "abc") order by a`) + r.Check(testkit.Rows("", "abc")) + + r = tk.MustQuery(`select "abc" as a union (select 1) order by a`) + r.Check(testkit.Rows("1", "abc")) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c int, d int)") + tk.MustExec("insert t1 values (NULL, 1)") + tk.MustExec("insert t1 values (1, 1)") + tk.MustExec("insert t1 values (1, 2)") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2 (c int, d int)") + tk.MustExec("insert t2 values (1, 3)") + tk.MustExec("insert t2 values (1, 1)") + tk.MustExec("drop table if exists t3") + tk.MustExec("create table t3 (c int, d int)") + tk.MustExec("insert t3 values (3, 2)") + tk.MustExec("insert t3 values (4, 3)") + r = tk.MustQuery(`select sum(c1), c2 from (select c c1, d c2 from t1 union all select d c1, c c2 from t2 union all select c c1, d c2 from t3) x group by c2 order by c2`) + r.Check(testkit.Rows("5 1", "4 2", "4 3")) + + tk.MustExec("drop table if exists t1, t2, t3") + tk.MustExec("create table t1 (a int primary key)") + tk.MustExec("create table t2 (a int primary key)") + tk.MustExec("create table t3 (a int primary key)") + tk.MustExec("insert t1 values (7), (8)") + tk.MustExec("insert t2 values (1), (9)") + tk.MustExec("insert t3 values (2), (3)") + r = tk.MustQuery("select * from t1 union all select * from t2 union all (select * from t3) order by a limit 2") + r.Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (a int)") + tk.MustExec("create table t2 (a int)") + tk.MustExec("insert t1 values (2), (1)") + tk.MustExec("insert t2 values (3), (4)") + r = tk.MustQuery("select * from t1 union all (select * from t2) order by a limit 1") + r.Check(testkit.Rows("1")) + r = tk.MustQuery("select (select * from t1 where a != t.a union all (select * from t2 where a != t.a) order by a limit 1) from t1 t") + r.Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int unsigned primary key auto_increment, c1 int, c2 int, index c1_c2 (c1, c2))") + tk.MustExec("insert into t (c1, c2) values (1, 1)") + tk.MustExec("insert into t (c1, c2) values (1, 2)") + tk.MustExec("insert into t (c1, c2) values (2, 3)") + r = tk.MustQuery("select * from (select * from t where t.c1 = 1 union select * from t where t.id = 1) s order by s.id") + r.Check(testkit.Rows("1 1 1", "2 1 2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (f1 DATE)") + tk.MustExec("INSERT INTO t VALUES ('1978-11-26')") + r = tk.MustQuery("SELECT f1+0 FROM t UNION SELECT f1+0 FROM t") + r.Check(testkit.Rows("19781126")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a int, b int)") + tk.MustExec("INSERT INTO t VALUES ('1', '1')") + r = tk.MustQuery("select b from (SELECT * FROM t UNION ALL SELECT a, b FROM t order by a) t") + r.Check(testkit.Rows("1", "1")) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a DECIMAL(4,2))") + tk.MustExec("INSERT INTO t VALUE(12.34)") + r = tk.MustQuery("SELECT 1 AS c UNION select a FROM t") + r.Sort().Check(testkit.Rows("1.00", "12.34")) + + // #issue3771 + r = tk.MustQuery("SELECT 'a' UNION SELECT CONCAT('a', -4)") + r.Sort().Check(testkit.Rows("a", "a-4")) + + // test race + tk.MustQuery("SELECT @x:=0 UNION ALL SELECT @x:=0 UNION ALL SELECT @x") + + // test field tp + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("CREATE TABLE t1 (a date)") + tk.MustExec("CREATE TABLE t2 (a date)") + tk.MustExec("SELECT a from t1 UNION select a FROM t2") + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` date DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + + // Move from session test. + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (c double);") + tk.MustExec("create table t2 (c double);") + tk.MustExec("insert into t1 value (73);") + tk.MustExec("insert into t2 value (930);") + // If set unspecified column flen to 0, it will cause bug in union. + // This test is used to prevent the bug reappear. + tk.MustQuery("select c from t1 union (select c from t2) order by c").Check(testkit.Rows("73", "930")) + + // issue 5703 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a date)") + tk.MustExec("insert into t value ('2017-01-01'), ('2017-01-02')") + r = tk.MustQuery("(select a from t where a < 0) union (select a from t where a > 0) order by a") + r.Check(testkit.Rows("2017-01-01", "2017-01-02")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t value(0),(0)") + tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1")) + tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10")) + tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10")) + tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4")) + + err := tk.ExecToErr("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp") + c.Assert(err, NotNil) + terr := errors.Cause(err).(*terror.Error) + c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) + + err = tk.ExecToErr("select 1 from (select a from t order by a union all select a from t limit 1) tmp") + c.Assert(err, NotNil) + terr = errors.Cause(err).(*terror.Error) + c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) + + _, err = tk.Exec("(select a from t order by a) union all select a from t limit 1 union all select a from t limit 1") + c.Assert(terror.ErrorEqual(err, plannercore.ErrWrongUsage), IsTrue, Commentf("err %v", err)) + + _, err = tk.Exec("(select a from t limit 1) union all select a from t limit 1") + c.Assert(err, IsNil) + _, err = tk.Exec("(select a from t order by a) union all select a from t order by a") + c.Assert(err, IsNil) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t value(1),(2),(3)") + + tk.MustQuery("(select a from t order by a limit 2) union all (select a from t order by a desc limit 2) order by a desc limit 1,2").Check(testkit.Rows("2", "2")) + tk.MustQuery("select a from t union all select a from t order by a desc limit 5").Check(testkit.Rows("3", "3", "2", "2", "1")) + tk.MustQuery("(select a from t order by a desc limit 2) union all select a from t group by a order by a").Check(testkit.Rows("1", "2", "2", "3", "3")) + tk.MustQuery("(select a from t order by a desc limit 2) union all select 33 as a order by a desc limit 2").Check(testkit.Rows("33", "3")) + + tk.MustQuery("select 1 union select 1 union all select 1").Check(testkit.Rows("1", "1")) + tk.MustQuery("select 1 union all select 1 union select 1").Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec(`create table t1(a bigint, b bigint);`) + tk.MustExec(`create table t2(a bigint, b bigint);`) + tk.MustExec(`insert into t1 values(1, 1);`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t1 select * from t1;`) + tk.MustExec(`insert into t2 values(1, 1);`) + tk.MustExec(`set @@tidb_init_chunk_size=2;`) + tk.MustExec(`set @@sql_mode="";`) + tk.MustQuery(`select count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("128")) + tk.MustQuery(`select tmp.a, count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("1 128")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t value(1 ,2)") + tk.MustQuery("select a, b from (select a, 0 as d, b from t union all select a, 0 as d, b from t) test;").Check(testkit.Rows("1 2", "1 2")) + + // #issue 8141 + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("insert into t1 value(1,2),(1,1),(2,2),(2,2),(3,2),(3,2)") + tk.MustExec("set @@tidb_init_chunk_size=2;") + tk.MustQuery("select count(*) from (select a as c, a as d from t1 union all select a, b from t1) t;").Check(testkit.Rows("12")) + + // #issue 8189 and #issue 8199 + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") + tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") + tk.MustExec("insert into t2 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustQuery("select a from t1 union select a from t1 order by (select a+1);").Check(testkit.Rows("1", "2", "3")) + + // #issue 8201 + for i := 0; i < 4; i++ { + tk.MustQuery("SELECT(SELECT 0 AS a FROM dual UNION SELECT 1 AS a FROM dual ORDER BY a ASC LIMIT 1) AS dev").Check(testkit.Rows("0")) + } + + // #issue 8231 + tk.MustExec("drop table if exists t1") + tk.MustExec("CREATE TABLE t1 (uid int(1))") + tk.MustExec("INSERT INTO t1 SELECT 150") + tk.MustQuery("SELECT 'a' UNION SELECT uid FROM t1 order by 1 desc;").Check(testkit.Rows("a", "150")) + + // #issue 8196 + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") + tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") + tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") + tk.MustExec("insert into t2 values(3,'c'),(4,'d'),(5,'f'),(6,'e')") + tk.MustExec("analyze table t1") + tk.MustExec("analyze table t2") + _, err = tk.Exec("(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b") + c.Assert(err.Error(), Equals, "[planner:1250]Table 't1' from one of the SELECTs cannot be used in global ORDER clause") + + // #issue 9900 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b decimal(6, 3))") + tk.MustExec("insert into t values(1, 1.000)") + tk.MustQuery("select count(distinct a), sum(distinct a), avg(distinct a) from (select a from t union all select b from t) tmp;").Check(testkit.Rows("1 1.000 1.0000000")) + + // #issue 23832 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a bit(20), b float, c double, d int)") + tk.MustExec("insert into t values(10, 10, 10, 10), (1, -1, 2, -2), (2, -2, 1, 1), (2, 1.1, 2.1, 10.1)") + tk.MustQuery("select a from t union select 10 order by a").Check(testkit.Rows("1", "2", "10")) +} + +func (s *testSuite2) TestUnionLimit(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists union_limit") + tk.MustExec("create table union_limit (id int) partition by hash(id) partitions 30") + for i := 0; i < 60; i++ { + tk.MustExec(fmt.Sprintf("insert into union_limit values (%d)", i)) + } + // Cover the code for worker count limit in the union executor. + tk.MustQuery("select * from union_limit limit 10") +} + +func (s *testSuiteP2) TestToPBExpr(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values (1.1, 1.1)") + tk.MustExec("insert t values (2.4, 2.4)") + tk.MustExec("insert t values (3.3, 2.7)") + result := tk.MustQuery("select * from t where a < 2.399999") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where a > 1.5") + result.Check(testkit.Rows("2.400000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where a <= 1.1") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where b >= 3") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where not (b = 1)") + result.Check(testkit.Rows("2.400000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where b&1 = a|1") + result.Check(testkit.Rows("1.100000 1")) + result = tk.MustQuery("select * from t where b != 2 and b <=> 3") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where b in (3)") + result.Check(testkit.Rows("3.300000 3")) + result = tk.MustQuery("select * from t where b not in (1, 2)") + result.Check(testkit.Rows("3.300000 3")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a varchar(255), b int)") + tk.MustExec("insert t values ('abc123', 1)") + tk.MustExec("insert t values ('ab123', 2)") + result = tk.MustQuery("select * from t where a like 'ab%'") + result.Check(testkit.Rows("abc123 1", "ab123 2")) + result = tk.MustQuery("select * from t where a like 'ab_12'") + result.Check(nil) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int primary key)") + tk.MustExec("insert t values (1)") + tk.MustExec("insert t values (2)") + result = tk.MustQuery("select * from t where not (a = 1)") + result.Check(testkit.Rows("2")) + result = tk.MustQuery("select * from t where not(not (a = 1))") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select * from t where not(a != 1 and a != 2)") + result.Check(testkit.Rows("1", "2")) +} + +func (s *testSuiteP2) TestDatumXAPI(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values (1.1, 1.1)") + tk.MustExec("insert t values (2.2, 2.2)") + tk.MustExec("insert t values (3.3, 2.7)") + result := tk.MustQuery("select * from t where a > 1.5") + result.Check(testkit.Rows("2.200000 2", "3.300000 3")) + result = tk.MustQuery("select * from t where b > 1.5") + result.Check(testkit.Rows("2.200000 2", "3.300000 3")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a time(3), b time, index idx_a (a))") + tk.MustExec("insert t values ('11:11:11', '11:11:11')") + tk.MustExec("insert t values ('11:11:12', '11:11:12')") + tk.MustExec("insert t values ('11:11:13', '11:11:13')") + result = tk.MustQuery("select * from t where a > '11:11:11.5'") + result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) + result = tk.MustQuery("select * from t where b > '11:11:11.5'") + result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) +} + +func (s *testSuiteP2) TestSQLMode(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a tinyint not null)") + tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") + _, err := tk.Exec("insert t values ()") + c.Check(err, NotNil) + + _, err = tk.Exec("insert t values ('1000')") + c.Check(err, NotNil) + + tk.MustExec("create table if not exists tdouble (a double(3,2))") + _, err = tk.Exec("insert tdouble values (10.23)") + c.Check(err, NotNil) + + tk.MustExec("set sql_mode = ''") + tk.MustExec("insert t values ()") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value")) + tk.MustExec("insert t values (null)") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert ignore t values (null)") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert t select null") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) + tk.MustExec("insert t values (1000)") + tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "0", "127")) + + tk.MustExec("insert tdouble values (10.23)") + tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99")) + + tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") + tk.MustExec("set @@global.sql_mode = ''") + + tk2 := testkit.NewTestKit(c, s.store) + tk2.MustExec("use test") + tk2.MustExec("drop table if exists t2") + tk2.MustExec("create table t2 (a varchar(3))") + tk2.MustExec("insert t2 values ('abcd')") + tk2.MustQuery("select * from t2").Check(testkit.Rows("abc")) + + // session1 is still in strict mode. + _, err = tk.Exec("insert t2 values ('abcd')") + c.Check(err, NotNil) + // Restore original global strict mode. + tk.MustExec("set @@global.sql_mode = 'STRICT_TRANS_TABLES'") +} + +func (s *testSuiteP2) TestTableDual(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + result := tk.MustQuery("Select 1") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select 1 from dual") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select count(*) from dual") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("Select 1 from dual where 1") + result.Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int primary key)") + tk.MustQuery("select t1.* from t t1, t t2 where t1.a=t2.a and 1=0").Check(testkit.Rows()) +} + +func (s *testSuiteP2) TestTableScan(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use information_schema") + result := tk.MustQuery("select * from schemata") + // There must be these tables: information_schema, mysql, performance_schema and test. + c.Assert(len(result.Rows()), GreaterEqual, 4) + tk.MustExec("use test") + tk.MustExec("create database mytest") + rowStr1 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mysql", "utf8mb4", "utf8mb4_bin", nil, nil) + rowStr2 := fmt.Sprintf("%s %s %s %s %v %v", "def", "mytest", "utf8mb4", "utf8mb4_bin", nil, nil) + tk.MustExec("use information_schema") + result = tk.MustQuery("select * from schemata where schema_name = 'mysql'") + result.Check(testkit.Rows(rowStr1)) + result = tk.MustQuery("select * from schemata where schema_name like 'my%'") + result.Check(testkit.Rows(rowStr1, rowStr2)) + result = tk.MustQuery("select 1 from tables limit 1") + result.Check(testkit.Rows("1")) +} + +func (s *testSuiteP2) TestAdapterStatement(c *C) { + se, err := session.CreateSession4Test(s.store) + c.Check(err, IsNil) + se.GetSessionVars().TxnCtx.InfoSchema = domain.GetDomain(se).InfoSchema() + compiler := &executor.Compiler{Ctx: se} + stmtNode, err := s.ParseOneStmt("select 1", "", "") + c.Check(err, IsNil) + stmt, err := compiler.Compile(context.TODO(), stmtNode) + c.Check(err, IsNil) + c.Check(stmt.OriginText(), Equals, "select 1") + + stmtNode, err = s.ParseOneStmt("create table test.t (a int)", "", "") + c.Check(err, IsNil) + stmt, err = compiler.Compile(context.TODO(), stmtNode) + c.Check(err, IsNil) + c.Check(stmt.OriginText(), Equals, "create table test.t (a int)") +} + +func (s *testSuiteP2) TestIsPointGet(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use mysql") + ctx := tk.Se.(sessionctx.Context) + tests := map[string]bool{ + "select * from help_topic where name='aaa'": false, + "select 1 from help_topic where name='aaa'": false, + "select * from help_topic where help_topic_id=1": true, + "select * from help_topic where help_category_id=1": false, + } + + for sqlStr, result := range tests { + stmtNode, err := s.ParseOneStmt(sqlStr, "", "") + c.Check(err, IsNil) + preprocessorReturn := &plannercore.PreprocessorReturn{} + err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) + c.Check(err, IsNil) + p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) + c.Check(err, IsNil) + ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) + c.Assert(err, IsNil) + c.Assert(ret, Equals, result) + } +} + +func (s *testSuiteP2) TestClusteredIndexIsPointGet(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("drop database if exists test_cluster_index_is_point_get;") + tk.MustExec("create database test_cluster_index_is_point_get;") + tk.MustExec("use test_cluster_index_is_point_get;") + + tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a varchar(255), b int, c char(10), primary key (c, a));") + ctx := tk.Se.(sessionctx.Context) + + tests := map[string]bool{ + "select 1 from t where a='x'": false, + "select * from t where c='x'": false, + "select * from t where a='x' and c='x'": true, + "select * from t where a='x' and c='x' and b=1": false, + } + for sqlStr, result := range tests { + stmtNode, err := s.ParseOneStmt(sqlStr, "", "") + c.Check(err, IsNil) + preprocessorReturn := &plannercore.PreprocessorReturn{} + err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) + c.Check(err, IsNil) + p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) + c.Check(err, IsNil) + ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) + c.Assert(err, IsNil) + c.Assert(ret, Equals, result) + } +} + +func (s *testSuiteP2) TestRow(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c int, d int)") + tk.MustExec("insert t values (1, 1)") + tk.MustExec("insert t values (1, 3)") + tk.MustExec("insert t values (2, 1)") + tk.MustExec("insert t values (2, 3)") + result := tk.MustQuery("select * from t where (c, d) < (2,2)") + result.Check(testkit.Rows("1 1", "1 3", "2 1")) + result = tk.MustQuery("select * from t where (1,2,3) > (3,2,1)") + result.Check(testkit.Rows()) + result = tk.MustQuery("select * from t where row(1,2,3) > (3,2,1)") + result.Check(testkit.Rows()) + result = tk.MustQuery("select * from t where (c, d) = (select * from t where (c,d) = (1,1))") + result.Check(testkit.Rows("1 1")) + result = tk.MustQuery("select * from t where (c, d) = (select * from t k where (t.c,t.d) = (c,d))") + result.Check(testkit.Rows("1 1", "1 3", "2 1", "2 3")) + result = tk.MustQuery("select (1, 2, 3) < (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 3)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) <= (2, 1, 4)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (2, 3, 4) >= (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) = (2, 3, 4)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select (2, 3, 4) != (2, 3, 4)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select row(1, 1) in (row(1, 1))") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 0) in (row(1, 1))") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select row(1, 1) in (select 1, 1)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 1) > row(1, 0)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select row(1, 1) > (select 1, 0)") + result.Check(testkit.Rows("1")) + result = tk.MustQuery("select 1 > (select 1)") + result.Check(testkit.Rows("0")) + result = tk.MustQuery("select (select 1)") + result.Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("insert t1 values (1,2),(1,null)") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2 (c int, d int)") + tk.MustExec("insert t2 values (0,0)") + + tk.MustQuery("select * from t2 where (1,2) in (select * from t1)").Check(testkit.Rows("0 0")) + tk.MustQuery("select * from t2 where (1,2) not in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (1,1) not in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (1,null) in (select * from t1)").Check(testkit.Rows()) + tk.MustQuery("select * from t2 where (null,null) in (select * from t1)").Check(testkit.Rows()) + + tk.MustExec("delete from t1 where a=1 and b=2") + tk.MustQuery("select (1,1) in (select * from t2) from t1").Check(testkit.Rows("0")) + tk.MustQuery("select (1,1) not in (select * from t2) from t1").Check(testkit.Rows("1")) + tk.MustQuery("select (1,1) in (select 1,1 from t2) from t1").Check(testkit.Rows("1")) + tk.MustQuery("select (1,1) not in (select 1,1 from t2) from t1").Check(testkit.Rows("0")) + + // MySQL 5.7 returns 1 for these 2 queries, which is wrong. + tk.MustQuery("select (1,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) + tk.MustQuery("select (t1.a,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) + + tk.MustQuery("select (1,null) in (select * from t1)").Check(testkit.Rows("")) + tk.MustQuery("select (1,null) not in (select * from t1)").Check(testkit.Rows("")) +} + +func (s *testSuiteP2) TestColumnName(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c int, d int)") + // disable only full group by + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") + rs, err := tk.Exec("select 1 + c, count(*) from t") + c.Check(err, IsNil) + fields := rs.Fields() + c.Check(len(fields), Equals, 2) + c.Check(fields[0].Column.Name.L, Equals, "1 + c") + c.Check(fields[0].ColumnAsName.L, Equals, "1 + c") + c.Check(fields[1].Column.Name.L, Equals, "count(*)") + c.Check(fields[1].ColumnAsName.L, Equals, "count(*)") + c.Assert(rs.Close(), IsNil) + rs, err = tk.Exec("select (c) > all (select c from t) from t") + c.Check(err, IsNil) + fields = rs.Fields() + c.Check(len(fields), Equals, 1) + c.Check(fields[0].Column.Name.L, Equals, "(c) > all (select c from t)") + c.Check(fields[0].ColumnAsName.L, Equals, "(c) > all (select c from t)") + c.Assert(rs.Close(), IsNil) + tk.MustExec("begin") + tk.MustExec("insert t values(1,1)") + rs, err = tk.Exec("select c d, d c from t") + c.Check(err, IsNil) + fields = rs.Fields() + c.Check(len(fields), Equals, 2) + c.Check(fields[0].Column.Name.L, Equals, "c") + c.Check(fields[0].ColumnAsName.L, Equals, "d") + c.Check(fields[1].Column.Name.L, Equals, "d") + c.Check(fields[1].ColumnAsName.L, Equals, "c") + c.Assert(rs.Close(), IsNil) + // Test case for query a column of a table. + // In this case, all attributes have values. + rs, err = tk.Exec("select c as a from t as t2") + c.Check(err, IsNil) + fields = rs.Fields() + c.Check(fields[0].Column.Name.L, Equals, "c") + c.Check(fields[0].ColumnAsName.L, Equals, "a") + c.Check(fields[0].Table.Name.L, Equals, "t") + c.Check(fields[0].TableAsName.L, Equals, "t2") + c.Check(fields[0].DBName.L, Equals, "test") + c.Assert(rs.Close(), IsNil) + // Test case for query a expression which only using constant inputs. + // In this case, the table, org_table and database attributes will all be empty. + rs, err = tk.Exec("select hour(1) as a from t as t2") + c.Check(err, IsNil) + fields = rs.Fields() + c.Check(fields[0].Column.Name.L, Equals, "a") + c.Check(fields[0].ColumnAsName.L, Equals, "a") + c.Check(fields[0].Table.Name.L, Equals, "") + c.Check(fields[0].TableAsName.L, Equals, "") + c.Check(fields[0].DBName.L, Equals, "") + c.Assert(rs.Close(), IsNil) + // Test case for query a column wrapped with parentheses and unary plus. + // In this case, the column name should be its original name. + rs, err = tk.Exec("select (c), (+c), +(c), +(+(c)), ++c from t") + c.Check(err, IsNil) + fields = rs.Fields() + for i := 0; i < 5; i++ { + c.Check(fields[i].Column.Name.L, Equals, "c") + c.Check(fields[i].ColumnAsName.L, Equals, "c") + } + c.Assert(rs.Close(), IsNil) + + // Test issue https://github.com/pingcap/tidb/issues/9639 . + // Both window function and expression appear in final result field. + tk.MustExec("set @@tidb_enable_window_function = 1") + rs, err = tk.Exec("select 1+1, row_number() over() num from t") + c.Check(err, IsNil) + fields = rs.Fields() + c.Assert(fields[0].Column.Name.L, Equals, "1+1") + c.Assert(fields[0].ColumnAsName.L, Equals, "1+1") + c.Assert(fields[1].Column.Name.L, Equals, "num") + c.Assert(fields[1].ColumnAsName.L, Equals, "num") + tk.MustExec("set @@tidb_enable_window_function = 0") + c.Assert(rs.Close(), IsNil) + + rs, err = tk.Exec("select if(1,c,c) from t;") + c.Check(err, IsNil) + fields = rs.Fields() + c.Assert(fields[0].Column.Name.L, Equals, "if(1,c,c)") + // It's a compatibility issue. Should be empty instead. + c.Assert(fields[0].ColumnAsName.L, Equals, "if(1,c,c)") + c.Assert(rs.Close(), IsNil) +} + +func (s *testSuiteP2) TestSelectVar(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (d int)") + tk.MustExec("insert into t values(1), (2), (1)") + // This behavior is different from MySQL. + result := tk.MustQuery("select @a, @a := d+1 from t") + result.Check(testkit.Rows(" 2", "2 3", "3 2")) + // Test for PR #10658. + tk.MustExec("select SQL_BIG_RESULT d from t group by d") + tk.MustExec("select SQL_SMALL_RESULT d from t group by d") + tk.MustExec("select SQL_BUFFER_RESULT d from t group by d") +} + +func (s *testSuiteP2) TestHistoryRead(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists history_read") + tk.MustExec("create table history_read (a int)") + tk.MustExec("insert history_read values (1)") + + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20060102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + + // Set snapshot to a time before save point will fail. + _, err := tk.Exec("set @@tidb_snapshot = '2006-01-01 15:04:05.999999'") + c.Assert(terror.ErrorEqual(err, variable.ErrSnapshotTooOld), IsTrue, Commentf("err %v", err)) + // SnapshotTS Is not updated if check failed. + c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) + + // Setting snapshot to a time in the future will fail. (One day before the 2038 problem) + _, err = tk.Exec("set @@tidb_snapshot = '2038-01-18 03:14:07'") + c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") + // SnapshotTS Is not updated if check failed. + c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) + + curVer1, _ := s.store.CurrentVersion(kv.GlobalTxnScope) + time.Sleep(time.Millisecond) + snapshotTime := time.Now() + time.Sleep(time.Millisecond) + curVer2, _ := s.store.CurrentVersion(kv.GlobalTxnScope) + tk.MustExec("insert history_read values (2)") + tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) + tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") + ctx := tk.Se.(sessionctx.Context) + snapshotTS := ctx.GetSessionVars().SnapshotTS + c.Assert(snapshotTS, Greater, curVer1.Ver) + c.Assert(snapshotTS, Less, curVer2.Ver) + tk.MustQuery("select * from history_read").Check(testkit.Rows("1")) + _, err = tk.Exec("insert history_read values (2)") + c.Assert(err, NotNil) + _, err = tk.Exec("update history_read set a = 3 where a = 1") + c.Assert(err, NotNil) + _, err = tk.Exec("delete from history_read where a = 1") + c.Assert(err, NotNil) + tk.MustExec("set @@tidb_snapshot = ''") + tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) + tk.MustExec("insert history_read values (3)") + tk.MustExec("update history_read set a = 4 where a = 3") + tk.MustExec("delete from history_read where a = 1") + + time.Sleep(time.Millisecond) + snapshotTime = time.Now() + time.Sleep(time.Millisecond) + tk.MustExec("alter table history_read add column b int") + tk.MustExec("insert history_read values (8, 8), (9, 9)") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) + tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) + tsoStr := strconv.FormatUint(oracle.GoTimeToTS(snapshotTime), 10) + + tk.MustExec("set @@tidb_snapshot = '" + tsoStr + "'") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) + + tk.MustExec("set @@tidb_snapshot = ''") + tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) +} + +func (s *testSuite2) TestLowResolutionTSORead(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("set @@autocommit=1") + tk.MustExec("use test") + tk.MustExec("drop table if exists low_resolution_tso") + tk.MustExec("create table low_resolution_tso(a int)") + tk.MustExec("insert low_resolution_tso values (1)") + + // enable low resolution tso + c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsFalse) + _, err := tk.Exec("set @@tidb_low_resolution_tso = 'on'") + c.Assert(err, IsNil) + c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsTrue) + + time.Sleep(3 * time.Second) + tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("1")) + _, err = tk.Exec("update low_resolution_tso set a = 2") + c.Assert(err, NotNil) + tk.MustExec("set @@tidb_low_resolution_tso = 'off'") + tk.MustExec("update low_resolution_tso set a = 2") + tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("2")) +} + +func (s *testSuite2) TestStaleReadFutureTime(c *C) { + tk := testkit.NewTestKit(c, s.store) + // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) + _, err := tk.Exec("set @@tx_read_ts = '2038-01-18 03:14:07'") + c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") + // TxnReadTS Is not updated if check failed. + c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) +} + +const ( + checkDDLAddIndexPriority = 1 +) + +type checkRequestClient struct { + tikv.Client + priority kvrpcpb.CommandPri + lowPriorityCnt uint32 + mu struct { + sync.RWMutex + checkFlags uint32 + } +} + +func (c *checkRequestClient) getCheckPriority() kvrpcpb.CommandPri { + return (kvrpcpb.CommandPri)(atomic.LoadInt32((*int32)(&c.priority))) +} + +func (c *checkRequestClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { + resp, err := c.Client.SendRequest(ctx, addr, req, timeout) + c.mu.RLock() + checkFlags := c.mu.checkFlags + c.mu.RUnlock() + if checkFlags == checkDDLAddIndexPriority { + if req.Type == tikvrpc.CmdScan { + if c.getCheckPriority() != req.Priority { + return nil, errors.New("fail to set priority") + } + } else if req.Type == tikvrpc.CmdPrewrite { + if c.getCheckPriority() == kvrpcpb.CommandPri_Low { + atomic.AddUint32(&c.lowPriorityCnt, 1) + } + } + } + return resp, err +} + +type testSuiteWithCliBaseCharset struct { + testSuiteWithCliBase +} + +type testSuiteWithCliBase struct { + store kv.Storage + dom *domain.Domain + cli *checkRequestClient +} + +func (s *testSuiteWithCliBase) SetUpSuite(c *C) { + cli := &checkRequestClient{} + hijackClient := func(c tikv.Client) tikv.Client { + cli.Client = c + return cli + } + s.cli = cli + + var err error + s.store, err = mockstore.NewMockStore( + mockstore.WithClientHijacker(hijackClient), + ) + c.Assert(err, IsNil) + session.SetStatsLease(0) + s.dom, err = session.BootstrapSession(s.store) + c.Assert(err, IsNil) + s.dom.SetStatsUpdating(true) +} + +func (s *testSuiteWithCliBase) TearDownSuite(c *C) { + s.dom.Close() + s.store.Close() +} + +func (s *testSuiteWithCliBase) TearDownTest(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + r := tk.MustQuery("show tables") + for _, tb := range r.Rows() { + tableName := tb[0] + tk.MustExec(fmt.Sprintf("drop table %v", tableName)) + } +} + +func (s *testSuite3) TestYearTypeDeleteIndex(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a YEAR, PRIMARY KEY(a));") + tk.MustExec("insert into t set a = '2151';") + tk.MustExec("delete from t;") + tk.MustExec("admin check table t") +} + +func (s *testSuite3) TestForSelectScopeInUnion(c *C) { + // A union B for update, the "for update" option belongs to union statement, so + // it should works on both A and B. + tk1 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(c, s.store) + tk1.MustExec("use test") + tk1.MustExec("drop table if exists t") + tk1.MustExec("create table t(a int)") + tk1.MustExec("insert into t values (1)") + + tk1.MustExec("begin") + // 'For update' would act on the second select. + tk1.MustQuery("select 1 as a union select a from t for update") + + tk2.MustExec("use test") + tk2.MustExec("update t set a = a + 1") + + // As tk1 use select 'for update', it should detect conflict and fail. + _, err := tk1.Exec("commit") + c.Assert(err, NotNil) + + tk1.MustExec("begin") + tk1.MustQuery("select 1 as a union select a from t limit 5 for update") + tk1.MustQuery("select 1 as a union select a from t order by a for update") + + tk2.MustExec("update t set a = a + 1") + + _, err = tk1.Exec("commit") + c.Assert(err, NotNil) +} + +func (s *testSuite3) TestUnsignedDecimalOverflow(c *C) { + tests := []struct { + input interface{} + hasErr bool + err string + }{{ + -1, + true, + "Out of range value for column", + }, { + "-1.1e-1", + true, + "Out of range value for column", + }, { + -1.1, + true, + "Out of range value for column", + }, { + -0, + false, + "", + }, + } + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a decimal(10,2) unsigned)") + for _, t := range tests { + res, err := tk.Exec("insert into t values (?)", t.input) + if res != nil { + defer res.Close() + } + if t.hasErr { + c.Assert(err, NotNil) + c.Assert(strings.Contains(err.Error(), t.err), IsTrue) + } else { + c.Assert(err, IsNil) + } + if res != nil { + c.Assert(res.Close(), IsNil) + } + } + + tk.MustExec("set sql_mode=''") + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?)", -1) + r := tk.MustQuery("select a from t limit 1") + r.Check(testkit.Rows("0.00")) +} + +func (s *testSuite3) TestIndexJoinTableDualPanic(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists a") + tk.MustExec("create table a (f1 int, f2 varchar(32), primary key (f1))") + tk.MustExec("insert into a (f1,f2) values (1,'a'), (2,'b'), (3,'c')") + // TODO here: index join cause the data race of txn. + tk.MustQuery("select /*+ inl_merge_join(a) */ a.* from a inner join (select 1 as k1,'k2-1' as k2) as k on a.f1=k.k1;"). + Check(testkit.Rows("1 a")) +} + +func (s *testSuite3) TestSortLeftJoinWithNullColumnInRightChildPanic(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int)") + tk.MustExec("create table t2(a int)") + tk.MustExec("insert into t1(a) select 1;") + tk.MustQuery("select b.n from t1 left join (select a as a, null as n from t2) b on b.a = t1.a order by t1.a"). + Check(testkit.Rows("")) +} + +func (s *testSuite3) TestMaxOneRow(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t1`) + tk.MustExec(`drop table if exists t2`) + tk.MustExec(`create table t1(a double, b double);`) + tk.MustExec(`create table t2(a double, b double);`) + tk.MustExec(`insert into t1 values(1, 1), (2, 2), (3, 3);`) + tk.MustExec(`insert into t2 values(0, 0);`) + tk.MustExec(`set @@tidb_init_chunk_size=1;`) + rs, err := tk.Exec(`select (select t1.a from t1 where t1.a > t2.a) as a from t2;`) + c.Assert(err, IsNil) + + err = rs.Next(context.TODO(), rs.NewChunk(nil)) + c.Assert(err.Error(), Equals, "[executor:1242]Subquery returns more than 1 row") + + c.Assert(rs.Close(), IsNil) +} + +func (s *testSuiteP2) TestCurrentTimestampValueSelection(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t,t1") + + tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))") + tk.MustExec("insert into t (id) values (1)") + rs := tk.MustQuery("select t0, t1, t2 from t where id = 1") + t0 := rs.Rows()[0][0].(string) + t1 := rs.Rows()[0][1].(string) + t2 := rs.Rows()[0][2].(string) + c.Assert(len(strings.Split(t0, ".")), Equals, 1) + c.Assert(len(strings.Split(t1, ".")[1]), Equals, 1) + c.Assert(len(strings.Split(t2, ".")[1]), Equals, 2) + tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1")) + tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1")) + time.Sleep(time.Second) + tk.MustExec("update t set t0 = now() where id = 1") + rs = tk.MustQuery("select t2 from t where id = 1") + newT2 := rs.Rows()[0][0].(string) + c.Assert(newT2 != t2, IsTrue) + + tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))") + tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))") + rs = tk.MustQuery("select a, b, c from t1 where id = 1") + a := rs.Rows()[0][0].(string) + b := rs.Rows()[0][1].(string) + d := rs.Rows()[0][2].(string) + c.Assert(len(strings.Split(a, ".")), Equals, 1) + c.Assert(strings.Split(b, ".")[1], Equals, "00") + c.Assert(len(strings.Split(d, ".")[1]), Equals, 3) +} + +func (s *testSuite3) TestRowID(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.MustExec(`create table t(a varchar(10), b varchar(10), c varchar(1), index idx(a, b, c));`) + tk.MustExec(`insert into t values('a', 'b', 'c');`) + tk.MustExec(`insert into t values('a', 'b', 'c');`) + tk.MustQuery(`select b, _tidb_rowid from t use index(idx) where a = 'a';`).Check(testkit.Rows( + `b 1`, + `b 2`, + )) + tk.MustExec(`begin;`) + tk.MustExec(`select * from t for update`) + tk.MustQuery(`select distinct b from t use index(idx) where a = 'a';`).Check(testkit.Rows(`b`)) + tk.MustExec(`commit;`) + + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a varchar(5) primary key)`) + tk.MustExec(`insert into t values('a')`) + tk.MustQuery("select *, _tidb_rowid from t use index(`primary`) where _tidb_rowid=1").Check(testkit.Rows("a 1")) +} + +func (s *testSuite3) TestDoSubquery(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int)`) + _, err := tk.Exec(`do 1 in (select * from t)`) + c.Assert(err, IsNil, Commentf("err %v", err)) + tk.MustExec(`insert into t values(1)`) + r, err := tk.Exec(`do 1 in (select * from t)`) + c.Assert(err, IsNil, Commentf("err %v", err)) + c.Assert(r, IsNil, Commentf("result of Do not empty")) +} + +func (s *testSuite3) TestSubqueryTableAlias(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + + tk.MustExec("set sql_mode = ''") + tk.MustGetErrCode("select a, b from (select 1 a) ``, (select 2 b) ``;", mysql.ErrDerivedMustHaveAlias) + tk.MustGetErrCode("select a, b from (select 1 a) `x`, (select 2 b) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select a, b from (select 1 a), (select 2 b);", mysql.ErrDerivedMustHaveAlias) + // ambiguous column name + tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrDerivedMustHaveAlias) + tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) + tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrDerivedMustHaveAlias) + + tk.MustExec("set sql_mode = 'oracle';") + tk.MustQuery("select a, b from (select 1 a) ``, (select 2 b) ``;").Check(testkit.Rows("1 2")) + tk.MustQuery("select a, b from (select 1 a) `x`, (select 2 b) `x`;").Check(testkit.Rows("1 2")) + tk.MustQuery("select a, b from (select 1 a), (select 2 b);").Check(testkit.Rows("1 2")) + // ambiguous column name + tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrNonUniq) + tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) + tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) + tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrNonUniq) +} + +func (s *testSuite3) TestSelectHashPartitionTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists th`) + tk.MustExec("set @@session.tidb_enable_table_partition = '1';") + tk.MustExec(`create table th (a int, b int) partition by hash(a) partitions 3;`) + defer tk.MustExec(`drop table if exists th`) + tk.MustExec(`insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);`) + tk.MustExec("insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8);") + tk.MustQuery("select b from th order by a").Check(testkit.Rows("-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8")) + tk.MustQuery(" select * from th where a=-2;").Check(testkit.Rows("-2 -2")) + tk.MustQuery(" select * from th where a=5;").Check(testkit.Rows("5 5")) +} + +func (s *testSuite) TestSelectView(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table view_t (a int,b int)") + tk.MustExec("insert into view_t values(1,2)") + tk.MustExec("create definer='root'@'localhost' view view1 as select * from view_t") + tk.MustExec("create definer='root'@'localhost' view view2(c,d) as select * from view_t") + tk.MustExec("create definer='root'@'localhost' view view3(c,d) as select a,b from view_t") + tk.MustExec("create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb;") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("drop table view_t;") + tk.MustExec("create table view_t(c int,d int)") + err := tk.ExecToErr("select * from view1") + c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + err = tk.ExecToErr("select * from view2") + c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + err = tk.ExecToErr("select * from view3") + c.Assert(err.Error(), Equals, plannercore.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error()) + tk.MustExec("drop table view_t;") + tk.MustExec("create table view_t(a int,b int,c int)") + tk.MustExec("insert into view_t values(1,2,3)") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("alter table view_t drop column a") + tk.MustExec("alter table view_t add column a int after b") + tk.MustExec("update view_t set a=1;") + tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) + tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) + tk.MustExec("drop table view_t;") + tk.MustExec("drop view view1,view2,view3,view4;") + + tk.MustExec("set @@tidb_enable_window_function = 1") + defer func() { + tk.MustExec("set @@tidb_enable_window_function = 0") + }() + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") + result := tk.MustQuery("select * from v") + result.Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) + tk.MustExec("drop view v;") +} + +type testSuite2 struct { + *baseTestSuite +} + +func (s *testSuite2) TearDownTest(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + r := tk.MustQuery("show full tables") + for _, tb := range r.Rows() { + tableName := tb[0] + if tb[1] == "VIEW" { + tk.MustExec(fmt.Sprintf("drop view %v", tableName)) + } else if tb[1] == "SEQUENCE" { + tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) + } else { + tk.MustExec(fmt.Sprintf("drop table %v", tableName)) + } + } +} + +type testSuite3 struct { + *baseTestSuite +} + +func (s *testSuite3) TearDownTest(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + r := tk.MustQuery("show full tables") + for _, tb := range r.Rows() { + tableName := tb[0] + if tb[1] == "VIEW" { + tk.MustExec(fmt.Sprintf("drop view %v", tableName)) + } else if tb[1] == "SEQUENCE" { + tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) + } else { + tk.MustExec(fmt.Sprintf("drop table %v", tableName)) + } + } +} + +type testSerialSuite1 struct { + *baseTestSuite +} + +func (s *testSerialSuite1) TearDownTest(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + r := tk.MustQuery("show full tables") + for _, tb := range r.Rows() { + tableName := tb[0] + if tb[1] == "VIEW" { + tk.MustExec(fmt.Sprintf("drop view %v", tableName)) + } else if tb[1] == "SEQUENCE" { + tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) + } else { + tk.MustExec(fmt.Sprintf("drop table %v", tableName)) + } + } +} + +func (s *testSuiteP2) TestStrToDateBuiltin(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%!') from dual`).Check(testkit.Rows("2019-01-01")) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) + tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) + tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('a18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('69/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('70/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) + tk.MustQuery(`select str_to_date('8/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) + tk.MustQuery(`select str_to_date('8/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) + tk.MustQuery(`select str_to_date('18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('a18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('69/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('70/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) + tk.MustQuery(`select str_to_date('018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("0018-10-22")) + tk.MustQuery(`select str_to_date('2018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('018/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18/10/22','%y0/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18/10/22','%Y0/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18a/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18a/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('20188/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018510522','%Y5%m5%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018^10^22','%Y^%m^%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018@10@22','%Y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018%10%22','%Y%%m%%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018(10(22','%Y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018\10\22','%Y\%m\%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('2018=10=22','%Y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018+10+22','%Y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('2018_10_22','%Y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('69510522','%y5%m5%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('69^10^22','%y^%m^%d') from dual`).Check(testkit.Rows("2069-10-22")) + tk.MustQuery(`select str_to_date('18@10@22','%y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18%10%22','%y%%m%%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18(10(22','%y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18\10\22','%y\%m\%d') from dual`).Check(testkit.Rows("")) + tk.MustQuery(`select str_to_date('18+10+22','%y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18=10=22','%y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`select str_to_date('18_10_22','%y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 11:22:33 PM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 23:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33 AM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 00:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 12:22:33")) + tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 00:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 00:22:33")) +} + +func (s *testSuiteP2) TestAddDateBuiltinWithWarnings(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") + result := tk.MustQuery(`select date_add('2001-01-00', interval -2 hour);`) + result.Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '2001-01-00'")) +} + +func (s *testSuiteP2) TestStrToDateBuiltinWithWarnings(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") + tk.MustExec("use test") + tk.MustQuery(`SELECT STR_TO_DATE('0000-1-01', '%Y-%m-%d');`).Check(testkit.Rows("")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1411 Incorrect datetime value: '0000-1-01' for function str_to_date")) +} + +func (s *testSuiteP2) TestReadPartitionedTable(c *C) { + // Test three reader on partitioned table. + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists pt") + tk.MustExec("create table pt (a int, b int, index i_b(b)) partition by range (a) (partition p1 values less than (2), partition p2 values less than (4), partition p3 values less than (6))") + for i := 0; i < 6; i++ { + tk.MustExec(fmt.Sprintf("insert into pt values(%d, %d)", i, i)) + } + // Table reader + tk.MustQuery("select * from pt order by a").Check(testkit.Rows("0 0", "1 1", "2 2", "3 3", "4 4", "5 5")) + // Index reader + tk.MustQuery("select b from pt where b = 3").Check(testkit.Rows("3")) + // Index lookup + tk.MustQuery("select a from pt where b = 3").Check(testkit.Rows("3")) +} + +func (s *testSuiteP2) TestIssue10435(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(i int, j int, k int)") + tk.MustExec("insert into t1 VALUES (1,1,1),(2,2,2),(3,3,3),(4,4,4)") + tk.MustExec("INSERT INTO t1 SELECT 10*i,j,5*j FROM t1 UNION SELECT 20*i,j,5*j FROM t1 UNION SELECT 30*i,j,5*j FROM t1") + + tk.MustExec("set @@session.tidb_enable_window_function=1") + tk.MustQuery("SELECT SUM(i) OVER W FROM t1 WINDOW w AS (PARTITION BY j ORDER BY i) ORDER BY 1+SUM(i) OVER w").Check( + testkit.Rows("1", "2", "3", "4", "11", "22", "31", "33", "44", "61", "62", "93", "122", "124", "183", "244"), + ) +} + +func (s *testSuiteWithCliBaseCharset) TestCharsetFeature(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("set names gbk;") + tk.MustQuery("select @@character_set_connection;").Check(testkit.Rows("gbk")) + tk.MustQuery("select @@collation_connection;").Check(testkit.Rows("gbk_chinese_ci")) + tk.MustExec("set @@character_set_client=gbk;") + tk.MustQuery("select @@character_set_client;").Check(testkit.Rows("gbk")) + tk.MustExec("set names utf8mb4;") + tk.MustExec("set @@character_set_connection=gbk;") + tk.MustQuery("select @@character_set_connection;").Check(testkit.Rows("gbk")) + tk.MustQuery("select @@collation_connection;").Check(testkit.Rows("gbk_chinese_ci")) + + tk.MustGetErrCode("select _gbk 'a';", errno.ErrUnknownCharacterSet) + + tk.MustExec("use test") + tk.MustExec("create table t1(a char(10) charset gbk);") + tk.MustExec("create table t2(a char(10) charset gbk collate gbk_bin);") + tk.MustExec("create table t3(a char(10)) charset gbk;") + tk.MustExec("alter table t3 add column b char(10) charset gbk;") + tk.MustQuery("show create table t3").Check(testkit.Rows("t3 CREATE TABLE `t3` (\n" + + " `a` char(10) DEFAULT NULL,\n" + + " `b` char(10) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci", + )) + tk.MustExec("create table t4(a char(10));") + tk.MustExec("alter table t4 add column b char(10) charset gbk;") + tk.MustQuery("show create table t4").Check(testkit.Rows("t4 CREATE TABLE `t4` (\n" + + " `a` char(10) DEFAULT NULL,\n" + + " `b` char(10) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", + )) + tk.MustExec("create table t5(a char(20), b char(20) charset utf8, c binary) charset gbk collate gbk_bin;") + + tk.MustExec("create database test_gbk charset gbk;") + tk.MustExec("use test_gbk") + tk.MustExec("create table t1(a char(10));") + tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `a` char(10) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci", + )) +} + +func (s *testSuiteWithCliBaseCharset) TestCharsetFeatureCollation(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t" + + "(ascii_char char(10) character set ascii," + + "gbk_char char(10) character set gbk collate gbk_bin," + + "latin_char char(10) character set latin1," + + "utf8mb4_char char(10) character set utf8mb4)", + ) + tk.MustExec("insert into t values ('a', 'a', 'a', 'a'), ('a', 'å•Š', '€', 'ã…‚');") + tk.MustQuery("select collation(concat(ascii_char, gbk_char)) from t;").Check(testkit.Rows("gbk_bin", "gbk_bin")) + tk.MustQuery("select collation(concat(gbk_char, ascii_char)) from t;").Check(testkit.Rows("gbk_bin", "gbk_bin")) + tk.MustQuery("select collation(concat(utf8mb4_char, gbk_char)) from t;").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin")) + tk.MustQuery("select collation(concat(gbk_char, utf8mb4_char)) from t;").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin")) + tk.MustQuery("select collation(concat('å•Š', convert('å•Š' using gbk) collate gbk_bin));").Check(testkit.Rows("gbk_bin")) + tk.MustQuery("select collation(concat(_latin1 'a', convert('å•Š' using gbk) collate gbk_bin));").Check(testkit.Rows("gbk_bin")) + + tk.MustGetErrCode("select collation(concat(latin_char, gbk_char)) from t;", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select collation(concat(convert('€' using latin1), convert('å•Š' using gbk) collate gbk_bin));", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select collation(concat(utf8mb4_char, gbk_char collate gbk_bin)) from t;", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select collation(concat('ã…‚', convert('å•Š' using gbk) collate gbk_bin));", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select collation(concat(ascii_char collate ascii_bin, gbk_char)) from t;", mysql.ErrCantAggregate2collations) +} + +func (s *testSuiteWithCliBaseCharset) TestCharsetWithPrefixIndex(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(20) charset gbk, b char(20) charset gbk, primary key (a(2)));") + tk.MustExec("insert into t values ('a', '中文'), ('中文', '中文'), ('一二三', '一二三'), ('b', '一二三');") + tk.MustQuery("select * from t").Check(testkit.Rows("a 中文", "中文 中文", "一二三 一二三", "b 一二三")) + tk.MustExec("drop table t") + tk.MustExec("create table t(a char(20) charset gbk, b char(20) charset gbk, unique index idx_a(a(2)));") + tk.MustExec("insert into t values ('a', '中文'), ('中文', '中文'), ('一二三', '一二三'), ('b', '一二三');") + tk.MustQuery("select * from t").Check(testkit.Rows("a 中文", "中文 中文", "一二三 一二三", "b 一二三")) +} + +func (s *testSuite) TestSummaryFailedUpdate(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int as(-a))") + tk.MustExec("insert into t(a) values(1), (3), (7)") + sm := &mockSessionManager1{ + PS: make([]*util.ProcessInfo, 0), + } + tk.Se.SetSessionManager(sm) + s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionCancel + }) + c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + tk.MustExec("set @@tidb_mem_quota_query=1") + err := tk.ExecToErr("update t set t.a = t.a - 1 where t.a in (select a from t where a < 4)") + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + tk.MustExec("set @@tidb_mem_quota_query=1000000000") + tk.MustQuery("select stmt_type from information_schema.statements_summary where digest_text = 'update `t` set `t` . `a` = `t` . `a` - ? where `t` . `a` in ( select `a` from `t` where `a` < ? )'").Check(testkit.Rows("Update")) +} + +func (s *testSuite) TestOOMPanicAction(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int primary key, b double);") + tk.MustExec("insert into t values (1,1)") + sm := &mockSessionManager1{ + PS: make([]*util.ProcessInfo, 0), + } + tk.Se.SetSessionManager(sm) + s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = config.OOMActionCancel + }) + tk.MustExec("set @@tidb_mem_quota_query=1;") + err := tk.QueryToErr("select sum(b) from t group by a;") + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + + // Test insert from select oom panic. + tk.MustExec("drop table if exists t,t1") + tk.MustExec("create table t (a bigint);") + tk.MustExec("create table t1 (a bigint);") + tk.MustExec("set @@tidb_mem_quota_query=200;") + _, err = tk.Exec("insert into t1 values (1),(2),(3),(4),(5);") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + _, err = tk.Exec("replace into t1 values (1),(2),(3),(4),(5);") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + tk.MustExec("set @@tidb_mem_quota_query=10000") + tk.MustExec("insert into t1 values (1),(2),(3),(4),(5);") + tk.MustExec("set @@tidb_mem_quota_query=10;") + _, err = tk.Exec("insert into t select a from t1 order by a desc;") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + _, err = tk.Exec("replace into t select a from t1 order by a desc;") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + + tk.MustExec("set @@tidb_mem_quota_query=10000") + tk.MustExec("insert into t values (1),(2),(3),(4),(5);") + // Set the memory quota to 244 to make this SQL panic during the DeleteExec + // instead of the TableReaderExec. + tk.MustExec("set @@tidb_mem_quota_query=244;") + _, err = tk.Exec("delete from t") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + + tk.MustExec("set @@tidb_mem_quota_query=10000;") + tk.MustExec("delete from t1") + tk.MustExec("insert into t1 values(1)") + tk.MustExec("insert into t values (1),(2),(3),(4),(5);") + tk.MustExec("set @@tidb_mem_quota_query=244;") + _, err = tk.Exec("delete t, t1 from t join t1 on t.a = t1.a") + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") + + tk.MustExec("set @@tidb_mem_quota_query=100000;") + tk.MustExec("truncate table t") + tk.MustExec("insert into t values(1),(2),(3)") + // set the memory to quota to make the SQL panic during UpdateExec instead + // of TableReader. + tk.MustExec("set @@tidb_mem_quota_query=244;") + _, err = tk.Exec("update t set a = 4") + c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") +} + +func (s *testSuiteP2) TestPointGetPreparedPlan(c *C) { + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("drop database if exists ps_text") + defer tk1.MustExec("drop database if exists ps_text") + tk1.MustExec("create database ps_text") + tk1.MustExec("use ps_text") + + tk1.MustExec(`create table t (a int, b int, c int, + primary key k_a(a), + unique key k_b(b))`) + tk1.MustExec("insert into t values (1, 1, 1)") + tk1.MustExec("insert into t values (2, 2, 2)") + tk1.MustExec("insert into t values (3, 3, 3)") + + pspk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where a = ?") + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + pspk2Id, _, _, err := tk1.Se.PrepareStmt("select * from t where ? = a ") + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[pspk2Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + + ctx := context.Background() + // first time plan generated + rs, err := tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + // using the generated plan but with different params + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) + + // unique index + psuk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where b = ? ") + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[psuk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + // test schema changed, cached plan should be invalidated + tk1.MustExec("alter table t add column col4 int default 10 after c") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) + + tk1.MustExec("alter table t drop index k_b") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + tk1.MustExec(`insert into t values(4, 3, 3, 11)`) + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10", "4 3 3 11")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + tk1.MustExec("delete from t where a = 4") + tk1.MustExec("alter table t add index k_b(b)") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + // use pk again + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(3)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) +} + +func (s *testSuiteP2) TestPointGetPreparedPlanWithCommitMode(c *C) { + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("drop database if exists ps_text") + defer tk1.MustExec("drop database if exists ps_text") + tk1.MustExec("create database ps_text") + tk1.MustExec("use ps_text") + + tk1.MustExec(`create table t (a int, b int, c int, + primary key k_a(a), + unique key k_b(b))`) + tk1.MustExec("insert into t values (1, 1, 1)") + tk1.MustExec("insert into t values (2, 2, 2)") + tk1.MustExec("insert into t values (3, 3, 3)") + + pspk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where a = ?") + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + + ctx := context.Background() + // first time plan generated + rs, err := tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) + + // using the generated plan but with different params + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + // next start a non autocommit txn + tk1.MustExec("set autocommit = 0") + tk1.MustExec("begin") + // try to exec using point get plan(this plan should not go short path) + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + // update rows + tk2 := testkit.NewTestKit(c, s.store) + tk2.MustExec("use ps_text") + tk2.MustExec("update t set c = c + 10 where c = 1") + + // try to point get again + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) + + // try to update in session 1 + tk1.MustExec("update t set c = c + 10 where c = 1") + _, err = tk1.Exec("commit") + c.Assert(kv.ErrWriteConflict.Equal(err), IsTrue, Commentf("error: %s", err)) + + // verify + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 11")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) + c.Assert(err, IsNil) + tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) + + tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 11")) +} + +func (s *testSuiteP2) TestPointUpdatePreparedPlan(c *C) { + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("drop database if exists pu_test") + defer tk1.MustExec("drop database if exists pu_test") + tk1.MustExec("create database pu_test") + tk1.MustExec("use pu_test") + + tk1.MustExec(`create table t (a int, b int, c int, + primary key k_a(a), + unique key k_b(b))`) + tk1.MustExec("insert into t values (1, 1, 1)") + tk1.MustExec("insert into t values (2, 2, 2)") + tk1.MustExec("insert into t values (3, 3, 3)") + + updateID1, pc, _, err := tk1.Se.PrepareStmt(`update t set c = c + 1 where a = ?`) + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[updateID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + c.Assert(pc, Equals, 1) + updateID2, pc, _, err := tk1.Se.PrepareStmt(`update t set c = c + 2 where ? = a`) + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[updateID2].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + c.Assert(pc, Equals, 1) + + ctx := context.Background() + // first time plan generated + rs, err := tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4")) + + // using the generated plan but with different params + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) + + // updateID2 + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID2, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 8")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID2, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10")) + + // unique index + updUkID1, _, _, err := tk1.Se.PrepareStmt(`update t set c = c + 10 where b = ?`) + c.Assert(err, IsNil) + tk1.Se.GetSessionVars().PreparedStmts[updUkID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 20")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 30")) + + // test schema changed, cached plan should be invalidated + tk1.MustExec("alter table t add column col4 int default 10 after c") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 31 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 32 10")) + + tk1.MustExec("alter table t drop index k_b") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 42 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 52 10")) + + tk1.MustExec("alter table t add unique index k_b(b)") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 62 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 72 10")) + + tk1.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1 10")) + tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2 10")) +} + +func (s *testSuiteP2) TestPointUpdatePreparedPlanWithCommitMode(c *C) { + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("drop database if exists pu_test2") + defer tk1.MustExec("drop database if exists pu_test2") + tk1.MustExec("create database pu_test2") + tk1.MustExec("use pu_test2") + + tk1.MustExec(`create table t (a int, b int, c int, + primary key k_a(a), + unique key k_b(b))`) + tk1.MustExec("insert into t values (1, 1, 1)") + tk1.MustExec("insert into t values (2, 2, 2)") + tk1.MustExec("insert into t values (3, 3, 3)") + + ctx := context.Background() + updateID1, _, _, err := tk1.Se.PrepareStmt(`update t set c = c + 1 where a = ?`) + tk1.Se.GetSessionVars().PreparedStmts[updateID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + c.Assert(err, IsNil) + + // first time plan generated + rs, err := tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) + + // next start a non autocommit txn + tk1.MustExec("set autocommit = 0") + tk1.MustExec("begin") + // try to exec using point get plan(this plan should not go short path) + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) + + // update rows + tk2 := testkit.NewTestKit(c, s.store) + tk2.MustExec("use pu_test2") + tk2.MustExec(`prepare pu2 from "update t set c = c + 2 where ? = a "`) + tk2.MustExec("set @p3 = 3") + tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) + tk2.MustExec("execute pu2 using @p3") + tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 7")) + tk2.MustExec("execute pu2 using @p3") + tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) + + // try to update in session 1 + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) + _, err = tk1.Exec("commit") + c.Assert(kv.ErrWriteConflict.Equal(err), IsTrue, Commentf("error: %s", err)) + + // verify + tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1")) + tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2")) + tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) + tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2")) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) + + // again next start a non autocommit txn + tk1.MustExec("set autocommit = 0") + tk1.MustExec("begin") + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10")) + + rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) + c.Assert(rs, IsNil) + c.Assert(err, IsNil) + tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11")) + tk1.MustExec("commit") + + tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11")) +} + +type testClusterTableSuite struct { + testSuiteWithCliBase + rpcserver *grpc.Server + listenAddr string +} + +func (s *testClusterTableSuite) SetUpSuite(c *C) { + s.testSuiteWithCliBase.SetUpSuite(c) + s.rpcserver, s.listenAddr = s.setUpRPCService(c, "127.0.0.1:0") +} + +func (s *testClusterTableSuite) setUpRPCService(c *C, addr string) (*grpc.Server, string) { + sm := &mockSessionManager1{} + sm.PS = append(sm.PS, &util.ProcessInfo{ + ID: 1, + User: "root", + Host: "127.0.0.1", + Command: mysql.ComQuery, + }) + lis, err := net.Listen("tcp", addr) + c.Assert(err, IsNil) + srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) + port := lis.Addr().(*net.TCPAddr).Port + addr = fmt.Sprintf("127.0.0.1:%d", port) + go func() { + err = srv.Serve(lis) + c.Assert(err, IsNil) + }() + config.UpdateGlobal(func(conf *config.Config) { + conf.Status.StatusPort = uint(port) + }) + return srv, addr +} +func (s *testClusterTableSuite) TearDownSuite(c *C) { + if s.rpcserver != nil { + s.rpcserver.Stop() + s.rpcserver = nil + } + s.testSuiteWithCliBase.TearDownSuite(c) +} + +func (s *testClusterTableSuite) TestSlowQuery(c *C) { + logData0 := "" + logData1 := ` +# Time: 2020-02-15T18:00:01.000000+08:00 +select 1; +# Time: 2020-02-15T19:00:05.000000+08:00 +select 2;` + logData2 := ` +# Time: 2020-02-16T18:00:01.000000+08:00 +select 3; +# Time: 2020-02-16T18:00:05.000000+08:00 +select 4;` + logData3 := ` +# Time: 2020-02-16T19:00:00.000000+08:00 +select 5; +# Time: 2020-02-17T18:00:05.000000+08:00 +select 6;` + logData4 := ` +# Time: 2020-05-14T19:03:54.314615176+08:00 +select 7;` + logData := []string{logData0, logData1, logData2, logData3, logData4} + + fileName0 := "tidb-slow-2020-02-14T19-04-05.01.log" + fileName1 := "tidb-slow-2020-02-15T19-04-05.01.log" + fileName2 := "tidb-slow-2020-02-16T19-04-05.01.log" + fileName3 := "tidb-slow-2020-02-17T18-00-05.01.log" + fileName4 := "tidb-slow.log" + fileNames := []string{fileName0, fileName1, fileName2, fileName3, fileName4} + + prepareLogs(c, logData, fileNames) + defer func() { + removeFiles(fileNames) + }() + tk := testkit.NewTestKitWithInit(c, s.store) + loc, err := time.LoadLocation("Asia/Shanghai") + c.Assert(err, IsNil) + tk.Se.GetSessionVars().TimeZone = loc + tk.MustExec("use information_schema") + cases := []struct { + prepareSQL string + sql string + result []string + }{ + { + sql: "select count(*),min(time),max(time) from %s where time > '2019-01-26 21:51:00' and time < now()", + result: []string{"7|2020-02-15 18:00:01.000000|2020-05-14 19:03:54.314615"}, + }, + { + sql: "select count(*),min(time),max(time) from %s where time > '2020-02-15 19:00:00' and time < '2020-02-16 18:00:02'", + result: []string{"2|2020-02-15 19:00:05.000000|2020-02-16 18:00:01.000000"}, + }, + { + sql: "select count(*),min(time),max(time) from %s where time > '2020-02-16 18:00:02' and time < '2020-02-17 17:00:00'", + result: []string{"2|2020-02-16 18:00:05.000000|2020-02-16 19:00:00.000000"}, + }, + { + sql: "select count(*),min(time),max(time) from %s where time > '2020-02-16 18:00:02' and time < '2020-02-17 20:00:00'", + result: []string{"3|2020-02-16 18:00:05.000000|2020-02-17 18:00:05.000000"}, + }, + { + sql: "select count(*),min(time),max(time) from %s", + result: []string{"1|2020-05-14 19:03:54.314615|2020-05-14 19:03:54.314615"}, + }, + { + sql: "select count(*),min(time) from %s where time > '2020-02-16 20:00:00'", + result: []string{"1|2020-02-17 18:00:05.000000"}, + }, + { + sql: "select count(*) from %s where time > '2020-02-17 20:00:00'", + result: []string{"0"}, + }, + { + sql: "select query from %s where time > '2019-01-26 21:51:00' and time < now()", + result: []string{"select 1;", "select 2;", "select 3;", "select 4;", "select 5;", "select 6;", "select 7;"}, + }, + // Test for different timezone. + { + prepareSQL: "set @@time_zone = '+00:00'", + sql: "select time from %s where time = '2020-02-17 10:00:05.000000'", + result: []string{"2020-02-17 10:00:05.000000"}, + }, + { + prepareSQL: "set @@time_zone = '+02:00'", + sql: "select time from %s where time = '2020-02-17 12:00:05.000000'", + result: []string{"2020-02-17 12:00:05.000000"}, + }, + // Test for issue 17224 + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from %s where time = '2020-05-14 19:03:54.314615'", + result: []string{"2020-05-14 19:03:54.314615"}, + }, + } + for _, cas := range cases { + if len(cas.prepareSQL) > 0 { + tk.MustExec(cas.prepareSQL) + } + sql := fmt.Sprintf(cas.sql, "slow_query") + tk.MustQuery(sql).Check(testkit.RowsWithSep("|", cas.result...)) + sql = fmt.Sprintf(cas.sql, "cluster_slow_query") + tk.MustQuery(sql).Check(testkit.RowsWithSep("|", cas.result...)) + } +} + +func (s *testClusterTableSuite) TestIssue20236(c *C) { + logData0 := "" + logData1 := ` +# Time: 2020-02-15T18:00:01.000000+08:00 +select 1; +# Time: 2020-02-15T19:00:05.000000+08:00 +select 2; +# Time: 2020-02-15T20:00:05.000000+08:00` + logData2 := `select 3; +# Time: 2020-02-16T18:00:01.000000+08:00 +select 4; +# Time: 2020-02-16T18:00:05.000000+08:00 +select 5;` + logData3 := ` +# Time: 2020-02-16T19:00:00.000000+08:00 +select 6; +# Time: 2020-02-17T18:00:05.000000+08:00 +select 7; +# Time: 2020-02-17T19:00:00.000000+08:00` + logData4 := `select 8; +# Time: 2020-02-17T20:00:00.000000+08:00 +select 9 +# Time: 2020-05-14T19:03:54.314615176+08:00 +select 10;` + logData := []string{logData0, logData1, logData2, logData3, logData4} + + fileName0 := "tidb-slow-2020-02-14T19-04-05.01.log" + fileName1 := "tidb-slow-2020-02-15T19-04-05.01.log" + fileName2 := "tidb-slow-2020-02-16T19-04-05.01.log" + fileName3 := "tidb-slow-2020-02-17T18-00-05.01.log" + fileName4 := "tidb-slow.log" + fileNames := []string{fileName0, fileName1, fileName2, fileName3, fileName4} + prepareLogs(c, logData, fileNames) + defer func() { + removeFiles(fileNames) + }() + tk := testkit.NewTestKitWithInit(c, s.store) + loc, err := time.LoadLocation("Asia/Shanghai") + c.Assert(err, IsNil) + tk.Se.GetSessionVars().TimeZone = loc + tk.MustExec("use information_schema") + cases := []struct { + prepareSQL string + sql string + result []string + }{ + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from cluster_slow_query where time > '2020-02-17 12:00:05.000000' and time < '2020-05-14 20:00:00.000000'", + result: []string{"2020-02-17 18:00:05.000000", "2020-02-17 19:00:00.000000", "2020-05-14 19:03:54.314615"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from cluster_slow_query where time > '2020-02-17 12:00:05.000000' and time < '2020-05-14 20:00:00.000000' order by time desc", + result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from cluster_slow_query where (time > '2020-02-15 18:00:00' and time < '2020-02-15 20:01:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-14 20:00:00') order by time", + result: []string{"2020-02-15 18:00:01.000000", "2020-02-15 19:00:05.000000", "2020-02-17 18:00:05.000000", "2020-02-17 19:00:00.000000", "2020-05-14 19:03:54.314615"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from cluster_slow_query where (time > '2020-02-15 18:00:00' and time < '2020-02-15 20:01:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-14 20:00:00') order by time desc", + result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000", "2020-02-15 19:00:05.000000", "2020-02-15 18:00:01.000000"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select count(*) from cluster_slow_query where time > '2020-02-15 18:00:00.000000' and time < '2020-05-14 20:00:00.000000' order by time desc", + result: []string{"9"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select count(*) from cluster_slow_query where (time > '2020-02-16 18:00:00' and time < '2020-05-14 20:00:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-17 20:00:00')", + result: []string{"6"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select count(*) from cluster_slow_query where time > '2020-02-16 18:00:00.000000' and time < '2020-02-17 20:00:00.000000' order by time desc", + result: []string{"5"}, + }, + { + prepareSQL: "set @@time_zone = '+08:00'", + sql: "select time from cluster_slow_query where time > '2020-02-16 18:00:00.000000' and time < '2020-05-14 20:00:00.000000' order by time desc limit 3", + result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000"}, + }, + } + for _, cas := range cases { + if len(cas.prepareSQL) > 0 { + tk.MustExec(cas.prepareSQL) + } + tk.MustQuery(cas.sql).Check(testkit.RowsWithSep("|", cas.result...)) + } +} + +func (s *testClusterTableSuite) TestSQLDigestTextRetriever(c *C) { + tkInit := testkit.NewTestKitWithInit(c, s.store) + tkInit.MustExec("set global tidb_enable_stmt_summary = 1") + tkInit.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) + tkInit.MustExec("drop table if exists test_sql_digest_text_retriever") + tkInit.MustExec("create table test_sql_digest_text_retriever (id int primary key, v int)") + + tk := testkit.NewTestKitWithInit(c, s.store) + c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + tk.MustExec("insert into test_sql_digest_text_retriever values (1, 1)") + + insertNormalized, insertDigest := parser.NormalizeDigest("insert into test_sql_digest_text_retriever values (1, 1)") + _, updateDigest := parser.NormalizeDigest("update test_sql_digest_text_retriever set v = v + 1 where id = 1") + r := &expression.SQLDigestTextRetriever{ + SQLDigestsMap: map[string]string{ + insertDigest.String(): "", + updateDigest.String(): "", + }, + } + err := r.RetrieveLocal(context.Background(), tk.Se) + c.Assert(err, IsNil) + c.Assert(r.SQLDigestsMap[insertDigest.String()], Equals, insertNormalized) + c.Assert(r.SQLDigestsMap[updateDigest.String()], Equals, "") +} + +func (s *testClusterTableSuite) TestFunctionDecodeSQLDigests(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + tk.MustExec("set global tidb_enable_stmt_summary = 1") + tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) + tk.MustExec("drop table if exists test_func_decode_sql_digests") + tk.MustExec("create table test_func_decode_sql_digests(id int primary key, v int)") + + q1 := "begin" + norm1, digest1 := parser.NormalizeDigest(q1) + q2 := "select @@tidb_current_ts" + norm2, digest2 := parser.NormalizeDigest(q2) + q3 := "select id, v from test_func_decode_sql_digests where id = 1 for update" + norm3, digest3 := parser.NormalizeDigest(q3) + + // TIDB_DECODE_SQL_DIGESTS function doesn't actually do "decoding", instead it queries `statements_summary` and it's + // variations for the corresponding statements. + // Execute the statements so that the queries will be saved into statements_summary table. + tk.MustExec(q1) + // Save the ts to query the transaction from tidb_trx. + ts, err := strconv.ParseUint(tk.MustQuery(q2).Rows()[0][0].(string), 10, 64) + c.Assert(err, IsNil) + c.Assert(ts, Greater, uint64(0)) + tk.MustExec(q3) + tk.MustExec("rollback") + + // Test statements truncating. + decoded := fmt.Sprintf(`["%s","%s","%s"]`, norm1, norm2, norm3) + digests := fmt.Sprintf(`["%s","%s","%s"]`, digest1, digest2, digest3) + tk.MustQuery("select tidb_decode_sql_digests(?, 0)", digests).Check(testkit.Rows(decoded)) + // The three queries are shorter than truncate length, equal to truncate length and longer than truncate length respectively. + tk.MustQuery("select tidb_decode_sql_digests(?, ?)", digests, len(norm2)).Check(testkit.Rows( + "[\"begin\",\"select @@tidb_current_ts\",\"select `id` , `v` from `...\"]")) + + // Empty array. + tk.MustQuery("select tidb_decode_sql_digests('[]')").Check(testkit.Rows("[]")) + + // NULL + tk.MustQuery("select tidb_decode_sql_digests(null)").Check(testkit.Rows("")) + + // Array containing wrong types and not-existing digests (maps to null). + tk.MustQuery("select tidb_decode_sql_digests(?)", fmt.Sprintf(`["%s",1,null,"%s",{"a":1},[2],"%s","","abcde"]`, digest1, digest2, digest3)). + Check(testkit.Rows(fmt.Sprintf(`["%s",null,null,"%s",null,null,"%s",null,null]`, norm1, norm2, norm3))) + + // Not JSON array (throws warnings) + tk.MustQuery(`select tidb_decode_sql_digests('{"a":1}')`).Check(testkit.Rows("")) + tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: '{"a":1}'`)) + tk.MustQuery(`select tidb_decode_sql_digests('aabbccdd')`).Check(testkit.Rows("")) + tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: 'aabbccdd'`)) + + // Invalid argument count. + tk.MustGetErrCode("select tidb_decode_sql_digests('a', 1, 2)", 1582) + tk.MustGetErrCode("select tidb_decode_sql_digests()", 1582) +} + +func (s *testClusterTableSuite) TestFunctionDecodeSQLDigestsPrivilege(c *C) { + dropUserTk := testkit.NewTestKitWithInit(c, s.store) + c.Assert(dropUserTk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + + tk := testkit.NewTestKitWithInit(c, s.store) + c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + tk.MustExec("create user 'testuser'@'localhost'") + defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") + c.Assert(tk.Se.Auth(&auth.UserIdentity{ + Username: "testuser", + Hostname: "localhost", + }, nil, nil), IsTrue) + err := tk.ExecToErr("select tidb_decode_sql_digests('[\"aa\"]')") + c.Assert(err, NotNil) + c.Assert(err.Error(), Equals, "[expression:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") + + tk = testkit.NewTestKitWithInit(c, s.store) + c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + tk.MustExec("create user 'testuser2'@'localhost'") + defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") + tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") + c.Assert(tk.Se.Auth(&auth.UserIdentity{ + Username: "testuser2", + Hostname: "localhost", + }, nil, nil), IsTrue) + _ = tk.MustQuery("select tidb_decode_sql_digests('[\"aa\"]')") +} + +func prepareLogs(c *C, logData []string, fileNames []string) { + writeFile := func(file string, data string) { + f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) + c.Assert(err, IsNil) + _, err = f.Write([]byte(data)) + c.Assert(f.Close(), IsNil) + c.Assert(err, IsNil) + } + + for i, log := range logData { + writeFile(fileNames[i], log) + } +} + +func removeFiles(fileNames []string) { + for _, fileName := range fileNames { + os.Remove(fileName) + } +} + +func (s *testSuiteP2) TestApplyCache(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int);") + tk.MustExec("insert into t values (1),(1),(1),(1),(1),(1),(1),(1),(1);") + tk.MustExec("analyze table t;") + result := tk.MustQuery("explain analyze SELECT count(1) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;") + c.Assert(result.Rows()[1][0], Equals, "└─Apply_39") + var ( + ind int + flag bool + ) + value := (result.Rows()[1][5]).(string) + for ind = 0; ind < len(value)-5; ind++ { + if value[ind:ind+5] == "cache" { + flag = true + break + } + } + c.Assert(flag, Equals, true) + c.Assert(value[ind:], Equals, "cache:ON, cacheHitRatio:88.889%") + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int);") + tk.MustExec("insert into t values (1),(2),(3),(4),(5),(6),(7),(8),(9);") + tk.MustExec("analyze table t;") + result = tk.MustQuery("explain analyze SELECT count(1) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;") + c.Assert(result.Rows()[1][0], Equals, "└─Apply_39") + flag = false + value = (result.Rows()[1][5]).(string) + for ind = 0; ind < len(value)-5; ind++ { + if value[ind:ind+5] == "cache" { + flag = true + break + } + } + c.Assert(flag, Equals, true) + c.Assert(value[ind:], Equals, "cache:OFF") +} + +// For issue 17256 +func (s *testSuite) TestGenerateColumnReplace(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int as (a + 1) virtual not null, unique index idx(b));") + tk.MustExec("REPLACE INTO `t1` (`a`) VALUES (2);") + tk.MustExec("REPLACE INTO `t1` (`a`) VALUES (2);") + tk.MustQuery("select * from t1").Check(testkit.Rows("2 3")) + tk.MustExec("insert into `t1` (`a`) VALUES (2) on duplicate key update a = 3;") + tk.MustQuery("select * from t1").Check(testkit.Rows("3 4")) +} + +func (s *testSerialSuite) TestPrevStmtDesensitization(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec(fmt.Sprintf("set @@session.%v=1", variable.TiDBRedactLog)) + defer tk.MustExec(fmt.Sprintf("set @@session.%v=0", variable.TiDBRedactLog)) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, unique key (a))") + tk.MustExec("begin") + tk.MustExec("insert into t values (1),(2)") + c.Assert(tk.Se.GetSessionVars().PrevStmt.String(), Equals, "insert into `t` values ( ? ) , ( ? )") + c.Assert(tk.ExecToErr("insert into t values (1)").Error(), Equals, `[kv:1062]Duplicate entry '?' for key 'a'`) +} + +func (s *testSuite) TestIssue19372(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1 (c_int int, c_str varchar(40), key(c_str));") + tk.MustExec("create table t2 like t1;") + tk.MustExec("insert into t1 values (1, 'a'), (2, 'b'), (3, 'c');") + tk.MustExec("insert into t2 select * from t1;") + tk.MustQuery("select (select t2.c_str from t2 where t2.c_str <= t1.c_str and t2.c_int in (1, 2) order by t2.c_str limit 1) x from t1 order by c_int;").Check(testkit.Rows("a", "a", "a")) +} + +func (s *testSerialSuite1) TestIndexLookupRuntimeStats(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int, index(a))") + tk.MustExec("insert into t1 values (1,2),(2,3),(3,4)") + sql := "explain analyze select * from t1 use index(a) where a > 1;" + rows := tk.MustQuery(sql).Rows() + c.Assert(len(rows), Equals, 3) + explain := fmt.Sprintf("%v", rows[0]) + c.Assert(explain, Matches, ".*time:.*loops:.*index_task:.*table_task: {total_time.*num.*concurrency.*}.*") + indexExplain := fmt.Sprintf("%v", rows[1]) + tableExplain := fmt.Sprintf("%v", rows[2]) + c.Assert(indexExplain, Matches, ".*time:.*loops:.*cop_task:.*") + c.Assert(tableExplain, Matches, ".*time:.*loops:.*cop_task:.*") +} + +func (s *testSerialSuite1) TestHashAggRuntimeStats(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("insert into t1 values (1,2),(2,3),(3,4)") + sql := "explain analyze SELECT /*+ HASH_AGG() */ count(*) FROM t1 WHERE a < 10;" + rows := tk.MustQuery(sql).Rows() + c.Assert(len(rows), Equals, 5) + explain := fmt.Sprintf("%v", rows[0]) + c.Assert(explain, Matches, ".*time:.*loops:.*partial_worker:{wall_time:.*concurrency:.*task_num:.*tot_wait:.*tot_exec:.*tot_time:.*max:.*p95:.*}.*final_worker:{wall_time:.*concurrency:.*task_num:.*tot_wait:.*tot_exec:.*tot_time:.*max:.*p95:.*}.*") +} + +func (s *testSerialSuite1) TestIndexMergeRuntimeStats(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1") + tk.MustExec("set @@tidb_enable_index_merge = 1") + tk.MustExec("create table t1(id int primary key, a int, b int, c int, d int)") + tk.MustExec("create index t1a on t1(a)") + tk.MustExec("create index t1b on t1(b)") + tk.MustExec("insert into t1 values(1,1,1,1,1),(2,2,2,2,2),(3,3,3,3,3),(4,4,4,4,4),(5,5,5,5,5)") + sql := "explain analyze select /*+ use_index_merge(t1, primary, t1a) */ * from t1 where id < 2 or a > 4;" + rows := tk.MustQuery(sql).Rows() + c.Assert(len(rows), Equals, 4) + explain := fmt.Sprintf("%v", rows[0]) + c.Assert(explain, Matches, ".*time:.*loops:.*index_task:{fetch_handle:.*, merge:.*}.*table_task:{num.*concurrency.*fetch_row.*wait_time.*}.*") + tableRangeExplain := fmt.Sprintf("%v", rows[1]) + indexExplain := fmt.Sprintf("%v", rows[2]) + tableExplain := fmt.Sprintf("%v", rows[3]) + c.Assert(tableRangeExplain, Matches, ".*time:.*loops:.*cop_task:.*") + c.Assert(indexExplain, Matches, ".*time:.*loops:.*cop_task:.*") + c.Assert(tableExplain, Matches, ".*time:.*loops:.*cop_task:.*") + tk.MustExec("set @@tidb_enable_collect_execution_info=0;") + sql = "select /*+ use_index_merge(t1, primary, t1a) */ * from t1 where id < 2 or a > 4 order by a" + tk.MustQuery(sql).Check(testkit.Rows("1 1 1 1 1", "5 5 5 5 5")) +} + +func (s *testSuite) TestCollectDMLRuntimeStats(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (a int, b int, unique index (a))") + + testSQLs := []string{ + "insert ignore into t1 values (5,5);", + "insert into t1 values (5,5) on duplicate key update a=a+1;", + "replace into t1 values (5,6),(6,7)", + "update t1 set a=a+1 where a=6;", + } + + getRootStats := func() string { + info := tk.Se.ShowProcess() + c.Assert(info, NotNil) + p, ok := info.Plan.(plannercore.Plan) + c.Assert(ok, IsTrue) + stats := tk.Se.GetSessionVars().StmtCtx.RuntimeStatsColl.GetRootStats(p.ID()) + return stats.String() + } + for _, sql := range testSQLs { + tk.MustExec(sql) + c.Assert(getRootStats(), Matches, "time.*loops.*Get.*num_rpc.*total_time.*") + } + + // Test for lock keys stats. + tk.MustExec("begin pessimistic") + tk.MustExec("update t1 set b=b+1") + c.Assert(getRootStats(), Matches, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustQuery("select * from t1 for update").Check(testkit.Rows("5 6", "7 7")) + c.Assert(getRootStats(), Matches, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustExec("insert ignore into t1 values (9,9)") + c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}}}.*") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustExec("insert into t1 values (10,10) on duplicate key update a=a+1") + c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}.*") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustExec("insert into t1 values (1,2)") + c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, insert:.*") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustExec("insert ignore into t1 values(11,11) on duplicate key update `a`=`a`+1") + c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:.*}") + tk.MustExec("rollback") + + tk.MustExec("begin pessimistic") + tk.MustExec("replace into t1 values (1,4)") + c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prefetch:.*, rpc:.*") + tk.MustExec("rollback") +} + +func (s *testSuite) TestIssue13758(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (pk int(11) primary key, a int(11) not null, b int(11), key idx_b(b), key idx_a(a))") + tk.MustExec("insert into `t1` values (1,1,0),(2,7,6),(3,2,null),(4,1,null),(5,4,5)") + tk.MustExec("create table t2 (a int)") + tk.MustExec("insert into t2 values (1),(null)") + tk.MustQuery("select (select a from t1 use index(idx_a) where b >= t2.a order by a limit 1) as field from t2").Check(testkit.Rows( + "4", + "", + )) +} + +func (s *testSuite) TestIssue20237(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t, s") + tk.MustExec("create table t(a date, b float)") + tk.MustExec("create table s(b float)") + tk.MustExec(`insert into t values(NULL,-37), ("2011-11-04",105), ("2013-03-02",-22), ("2006-07-02",-56), (NULL,124), (NULL,111), ("2018-03-03",-5);`) + tk.MustExec(`insert into s values(-37),(105),(-22),(-56),(124),(105),(111),(-5);`) + tk.MustQuery(`select count(distinct t.a, t.b) from t join s on t.b= s.b;`).Check(testkit.Rows("4")) +} + +func (s *testSerialSuite) TestIssue19148(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a decimal(16, 2));") + tk.MustExec("select * from t where a > any_value(a);") + ctx := tk.Se.(sessionctx.Context) + is := domain.GetDomain(ctx).InfoSchema() + tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + c.Assert(err, IsNil) + c.Assert(int(tblInfo.Meta().Columns[0].Flag), Equals, 0) +} + +func (s *testSuite) TestIssue19667(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a DATETIME)") + tk.MustExec("INSERT INTO t VALUES('1988-04-17 01:59:59')") + tk.MustQuery(`SELECT DATE_ADD(a, INTERVAL 1 SECOND) FROM t`).Check(testkit.Rows("1988-04-17 02:00:00")) +} + +func (s *testSuite) TestZeroDateTimeCompatibility(c *C) { + tk := testkit.NewTestKit(c, s.store) + + SQLs := []string{ + `select YEAR(0000-00-00), YEAR("0000-00-00")`, + `select MONTH(0000-00-00), MONTH("0000-00-00")`, + `select DAYOFMONTH(0000-00-00), DAYOFMONTH("0000-00-00")`, + `select QUARTER(0000-00-00), QUARTER("0000-00-00")`, + `select EXTRACT(DAY FROM 0000-00-00), EXTRACT(DAY FROM "0000-00-00")`, + `select EXTRACT(MONTH FROM 0000-00-00), EXTRACT(MONTH FROM "0000-00-00")`, + `select EXTRACT(YEAR FROM 0000-00-00), EXTRACT(YEAR FROM "0000-00-00")`, + `select EXTRACT(WEEK FROM 0000-00-00), EXTRACT(WEEK FROM "0000-00-00")`, + `select EXTRACT(QUARTER FROM 0000-00-00), EXTRACT(QUARTER FROM "0000-00-00")`, + } + for _, t := range SQLs { + tk.MustQuery(t).Check(testkit.Rows("0 ")) + c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) + } + + SQLs = []string{ + `select DAYOFWEEK(0000-00-00), DAYOFWEEK("0000-00-00")`, + `select DAYOFYEAR(0000-00-00), DAYOFYEAR("0000-00-00")`, + } + for _, t := range SQLs { + tk.MustQuery(t).Check(testkit.Rows(" ")) + c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2)) + } + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(v1 datetime, v2 datetime(3))") + tk.MustExec("insert ignore into t values(0,0)") + + SQLs = []string{ + `select YEAR(v1), YEAR(v2) from t`, + `select MONTH(v1), MONTH(v2) from t`, + `select DAYOFMONTH(v1), DAYOFMONTH(v2) from t`, + `select QUARTER(v1), QUARTER(v2) from t`, + `select EXTRACT(DAY FROM v1), EXTRACT(DAY FROM v2) from t`, + `select EXTRACT(MONTH FROM v1), EXTRACT(MONTH FROM v2) from t`, + `select EXTRACT(YEAR FROM v1), EXTRACT(YEAR FROM v2) from t`, + `select EXTRACT(WEEK FROM v1), EXTRACT(WEEK FROM v2) from t`, + `select EXTRACT(QUARTER FROM v1), EXTRACT(QUARTER FROM v2) from t`, + } + for _, t := range SQLs { + tk.MustQuery(t).Check(testkit.Rows("0 0")) + c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + } + + SQLs = []string{ + `select DAYOFWEEK(v1), DAYOFWEEK(v2) from t`, + `select DAYOFYEAR(v1), DAYOFYEAR(v2) from t`, + } + for _, t := range SQLs { + tk.MustQuery(t).Check(testkit.Rows(" ")) + c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2)) + } +} + +// https://github.com/pingcap/tidb/issues/24165. +func (s *testSuite) TestInvalidDateValueInCreateTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + + // Test for sql mode 'NO_ZERO_IN_DATE'. + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE';") + tk.MustGetErrCode("create table t (a datetime default '2999-00-00 00:00:00');", errno.ErrInvalidDefault) + tk.MustExec("create table t (a datetime);") + tk.MustGetErrCode("alter table t modify column a datetime default '2999-00-00 00:00:00';", errno.ErrInvalidDefault) + tk.MustExec("drop table if exists t;") + + // Test for sql mode 'NO_ZERO_DATE'. + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_DATE';") + tk.MustGetErrCode("create table t (a datetime default '0000-00-00 00:00:00');", errno.ErrInvalidDefault) + tk.MustExec("create table t (a datetime);") + tk.MustGetErrCode("alter table t modify column a datetime default '0000-00-00 00:00:00';", errno.ErrInvalidDefault) + tk.MustExec("drop table if exists t;") + + // Remove NO_ZERO_DATE and NO_ZERO_IN_DATE. + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES';") + // Test create table with zero datetime as a default value. + tk.MustExec("create table t (a datetime default '2999-00-00 00:00:00');") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a datetime default '0000-00-00 00:00:00');") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a datetime);") + tk.MustExec("alter table t modify column a datetime default '2999-00-00 00:00:00';") + tk.MustExec("alter table t modify column a datetime default '0000-00-00 00:00:00';") + tk.MustExec("drop table if exists t;") + + // Test create table with invalid datetime(02-30) as a default value. + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES';") + tk.MustGetErrCode("create table t (a datetime default '2999-02-30 00:00:00');", errno.ErrInvalidDefault) + tk.MustExec("drop table if exists t;") + // NO_ZERO_IN_DATE and NO_ZERO_DATE have nothing to do with invalid datetime(02-30). + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE';") + tk.MustGetErrCode("create table t (a datetime default '2999-02-30 00:00:00');", errno.ErrInvalidDefault) + tk.MustExec("drop table if exists t;") + // ALLOW_INVALID_DATES allows invalid datetime(02-30). + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,ALLOW_INVALID_DATES';") + tk.MustExec("create table t (a datetime default '2999-02-30 00:00:00');") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a datetime);") + tk.MustExec("alter table t modify column a datetime default '2999-02-30 00:00:00';") + tk.MustExec("drop table if exists t;") +} + +func (s *testSuite) TestOOMActionPriority(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t0") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("drop table if exists t3") + tk.MustExec("drop table if exists t4") + tk.MustExec("create table t0(a int)") + tk.MustExec("insert into t0 values(1)") + tk.MustExec("create table t1(a int)") + tk.MustExec("insert into t1 values(1)") + tk.MustExec("create table t2(a int)") + tk.MustExec("insert into t2 values(1)") + tk.MustExec("create table t3(a int)") + tk.MustExec("insert into t3 values(1)") + tk.MustExec("create table t4(a int)") + tk.MustExec("insert into t4 values(1)") + tk.MustQuery("select * from t0 join t1 join t2 join t3 join t4 order by t0.a").Check(testkit.Rows("1 1 1 1 1")) + action := tk.Se.GetSessionVars().StmtCtx.MemTracker.GetFallbackForTest() + // check the first 5 actions is rate limit. + for i := 0; i < 5; i++ { + c.Assert(action.GetPriority(), Equals, int64(memory.DefRateLimitPriority)) + action = action.GetFallback() + } + for action.GetFallback() != nil { + c.Assert(action.GetPriority(), Equals, int64(memory.DefSpillPriority)) + action = action.GetFallback() + } + c.Assert(action.GetPriority(), Equals, int64(memory.DefLogPriority)) +} + +func (s testSuite) TestTrackAggMemoryUsage(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test") + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t values(1)") + + tk.MustExec("set tidb_track_aggregate_memory_usage = off;") + rows := tk.MustQuery("explain analyze select /*+ HASH_AGG() */ sum(a) from t").Rows() + c.Assert(rows[0][7], Equals, "N/A") + rows = tk.MustQuery("explain analyze select /*+ STREAM_AGG() */ sum(a) from t").Rows() + c.Assert(rows[0][7], Equals, "N/A") + tk.MustExec("set tidb_track_aggregate_memory_usage = on;") + rows = tk.MustQuery("explain analyze select /*+ HASH_AGG() */ sum(a) from t").Rows() + c.Assert(rows[0][7], Not(Equals), "N/A") + rows = tk.MustQuery("explain analyze select /*+ STREAM_AGG() */ sum(a) from t").Rows() + c.Assert(rows[0][7], Not(Equals), "N/A") +} + +func (s *testSuiteP2) TestProjectionBitType(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t(k1 int, v bit(34) DEFAULT b'111010101111001001100111101111111', primary key(k1) clustered);") + tk.MustExec("create table t1(k1 int, v bit(34) DEFAULT b'111010101111001001100111101111111', primary key(k1) nonclustered);") + tk.MustExec("insert into t(k1) select 1;") + tk.MustExec("insert into t1(k1) select 1;") + + tk.MustExec("set @@tidb_enable_vectorized_expression = 0;") + // following SQL should returns same result + tk.MustQuery("(select * from t where false) union(select * from t for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) + tk.MustQuery("(select * from t1 where false) union(select * from t1 for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) + + tk.MustExec("set @@tidb_enable_vectorized_expression = 1;") + tk.MustQuery("(select * from t where false) union(select * from t for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) + tk.MustQuery("(select * from t1 where false) union(select * from t1 for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) +} + +func (s testSerialSuite) TestExprBlackListForEnum(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a enum('a','b','c'), b enum('a','b','c'), c int, index idx(b,a));") + tk.MustExec("insert into t values(1,1,1),(2,2,2),(3,3,3);") + + checkFuncPushDown := func(rows [][]interface{}, keyWord string) bool { + for _, line := range rows { + // Agg/Expr push down + if line[2].(string) == "cop[tikv]" && strings.Contains(line[4].(string), keyWord) { + return true + } + // access index + if line[2].(string) == "cop[tikv]" && strings.Contains(line[3].(string), keyWord) { + return true + } + } + return false + } + + // Test agg(enum) push down + tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows := tk.MustQuery("desc format='brief' select /*+ HASH_AGG() */ max(a) from t;").Rows() + c.Assert(checkFuncPushDown(rows, "max"), IsFalse) + rows = tk.MustQuery("desc format='brief' select /*+ STREAM_AGG() */ max(a) from t;").Rows() + c.Assert(checkFuncPushDown(rows, "max"), IsFalse) + + tk.MustExec("delete from mysql.expr_pushdown_blacklist;") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = tk.MustQuery("desc format='brief' select /*+ HASH_AGG() */ max(a) from t;").Rows() + c.Assert(checkFuncPushDown(rows, "max"), IsTrue) + rows = tk.MustQuery("desc format='brief' select /*+ STREAM_AGG() */ max(a) from t;").Rows() + c.Assert(checkFuncPushDown(rows, "max"), IsTrue) + + // Test expr(enum) push down + tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() + c.Assert(checkFuncPushDown(rows, "plus"), IsFalse) + rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() + c.Assert(checkFuncPushDown(rows, "plus"), IsFalse) + + tk.MustExec("delete from mysql.expr_pushdown_blacklist;") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() + c.Assert(checkFuncPushDown(rows, "plus"), IsTrue) + rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() + c.Assert(checkFuncPushDown(rows, "plus"), IsTrue) + + // Test enum index + tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = tk.MustQuery("desc format='brief' select * from t where b = 1;").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) + rows = tk.MustQuery("desc format='brief' select * from t where b = 'a';").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) + rows = tk.MustQuery("desc format='brief' select * from t where b > 1;").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) + rows = tk.MustQuery("desc format='brief' select * from t where b > 'a';").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) + + tk.MustExec("delete from mysql.expr_pushdown_blacklist;") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a = 1;").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) + rows = tk.MustQuery("desc format='brief' select * from t where b = 'a' and a = 'a';").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) + rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a > 1;").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) + rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a > 'a'").Rows() + c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) +} + +func (s *testSuite) TestIssue24933(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("drop view if exists v;") + tk.MustExec("create table t(a int);") + tk.MustExec("insert into t values(1), (2), (3);") + + tk.MustExec("create definer='root'@'localhost' view v as select count(*) as c1 from t;") + rows := tk.MustQuery("select * from v;") + rows.Check(testkit.Rows("3")) + + // Test subquery and outer field is wildcard. + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(*) from t) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("3")) + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select avg(a) from t group by a) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("1.0000", "2.0000", "3.0000")) + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select sum(a) from t group by a) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("1", "2", "3")) + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select group_concat(a) from t group by a) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("1", "2", "3")) + + // Test alias names. + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(0) as c1 from t) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("3")) + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(*) as c1 from t) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("3")) + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select group_concat(a) as `concat(a)` from t group by a) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("1", "2", "3")) + + // Test firstrow. + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select a from t group by a) s;") + rows = tk.MustQuery("select * from v order by 1;") + rows.Check(testkit.Rows("1", "2", "3")) + + // Test direct select. + err := tk.ExecToErr("SELECT `s`.`count(a)` FROM (SELECT COUNT(`a`) FROM `test`.`t`) AS `s`") + c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 's.count(a)' in 'field list'") + + tk.MustExec("drop view v;") + tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(a) from t) s;") + rows = tk.MustQuery("select * from v") + rows.Check(testkit.Rows("3")) + + // Test window function. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(c1 int);") + tk.MustExec("insert into t values(111), (222), (333);") + tk.MustExec("drop view if exists v;") + tk.MustExec("create definer='root'@'localhost' view v as (select * from (select row_number() over (order by c1) from t) s);") + rows = tk.MustQuery("select * from v;") + rows.Check(testkit.Rows("1", "2", "3")) + tk.MustExec("drop view if exists v;") + tk.MustExec("create definer='root'@'localhost' view v as (select * from (select c1, row_number() over (order by c1) from t) s);") + rows = tk.MustQuery("select * from v;") + rows.Check(testkit.Rows("111 1", "222 2", "333 3")) + + // Test simple expr. + tk.MustExec("drop view if exists v;") + tk.MustExec("create definer='root'@'localhost' view v as (select * from (select c1 or 0 from t) s)") + rows = tk.MustQuery("select * from v;") + rows.Check(testkit.Rows("1", "1", "1")) + rows = tk.MustQuery("select `c1 or 0` from v;") + rows.Check(testkit.Rows("1", "1", "1")) + + tk.MustExec("drop view v;") +} + +func (s *testSuite) TestTableSampleTemporaryTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20160102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + + tk.MustExec("use test") + tk.MustExec("drop table if exists tmp1") + tk.MustExec("create global temporary table tmp1 " + + "(id int not null primary key, code int not null, value int default null, unique key code(code))" + + "on commit delete rows") + + tk.MustExec("use test") + tk.MustExec("drop table if exists tmp2") + tk.MustExec("create temporary table tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));") + + // sleep 1us to make test stale + time.Sleep(time.Microsecond) + + // test tablesample return empty for global temporary table + tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + + tk.MustExec("begin") + tk.MustExec("insert into tmp1 values (1, 1, 1)") + tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + tk.MustExec("commit") + + // tablesample for global temporary table should not return error for compatibility of tools like dumpling + tk.MustExec("set @@tidb_snapshot=NOW(6)") + tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + + tk.MustExec("begin") + tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + tk.MustExec("commit") + tk.MustExec("set @@tidb_snapshot=''") + + // test tablesample returns error for local temporary table + tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") + + tk.MustExec("begin") + tk.MustExec("insert into tmp2 values (1, 1, 1)") + tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") + tk.MustExec("commit") + tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") +} + +func (s *testSuite) TestCTEWithIndexLookupJoinDeadLock(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table t (a int(11) default null,b int(11) default null,key b (b),key ba (b))") + tk.MustExec("create table t1 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") + tk.MustExec("create table t2 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") + // It's easy to reproduce this problem in 30 times execution of IndexLookUpJoin. + for i := 0; i < 30; i++ { + tk.MustExec("with cte as (with cte1 as (select * from t2 use index(idx_ab) where a > 1 and b > 1) select * from cte1) select /*+use_index(t1 idx_ab)*/ * from cte join t1 on t1.a=cte.a;") + } +} + +func (s *testSuite) TestGetResultRowsCount(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int)") + for i := 1; i <= 10; i++ { + tk.MustExec(fmt.Sprintf("insert into t values (%v)", i)) + } + cases := []struct { + sql string + row int64 + }{ + {"select * from t", 10}, + {"select * from t where a < 0", 0}, + {"select * from t where a <= 3", 3}, + {"insert into t values (11)", 0}, + {"replace into t values (12)", 0}, + {"update t set a=13 where a=12", 0}, + } + + for _, ca := range cases { + if strings.HasPrefix(ca.sql, "select") { + tk.MustQuery(ca.sql) + } else { + tk.MustExec(ca.sql) + } + info := tk.Se.ShowProcess() + c.Assert(info, NotNil) + p, ok := info.Plan.(plannercore.Plan) + c.Assert(ok, IsTrue) + cnt := executor.GetResultRowsCount(tk.Se, p) + c.Assert(ca.row, Equals, cnt, Commentf("sql: %v", ca.sql)) + } +} + +func checkFileName(s string) bool { + files := []string{ + "config.toml", + "meta.txt", + "stats/test.t_dump_single.json", + "schema/test.t_dump_single.schema.txt", + "variables.toml", + "sqls.sql", + "session_bindings.sql", + "global_bindings.sql", + "explain.txt", + } + for _, f := range files { + if strings.Compare(f, s) == 0 { + return true + } + } + return false +} + +// Test invoke Close without invoking Open before for each operators. +func (s *testSerialSuite) TestUnreasonablyClose(c *C) { + defer testleak.AfterTest(c)() + + is := infoschema.MockInfoSchema([]*model.TableInfo{plannercore.MockSignedTable(), plannercore.MockUnsignedTable()}) + se, err := session.CreateSession4Test(s.store) + c.Assert(err, IsNil) + _, err = se.Execute(context.Background(), "use test") + c.Assert(err, IsNil) + // To enable the shuffleExec operator. + _, err = se.Execute(context.Background(), "set @@tidb_merge_join_concurrency=4") + c.Assert(err, IsNil) + + var opsNeedsCovered = []plannercore.PhysicalPlan{ + &plannercore.PhysicalHashJoin{}, + &plannercore.PhysicalMergeJoin{}, + &plannercore.PhysicalIndexJoin{}, + &plannercore.PhysicalIndexHashJoin{}, + &plannercore.PhysicalTableReader{}, + &plannercore.PhysicalIndexReader{}, + &plannercore.PhysicalIndexLookUpReader{}, + &plannercore.PhysicalIndexMergeReader{}, + &plannercore.PhysicalApply{}, + &plannercore.PhysicalHashAgg{}, + &plannercore.PhysicalStreamAgg{}, + &plannercore.PhysicalLimit{}, + &plannercore.PhysicalSort{}, + &plannercore.PhysicalTopN{}, + &plannercore.PhysicalCTE{}, + &plannercore.PhysicalCTETable{}, + &plannercore.PhysicalMaxOneRow{}, + &plannercore.PhysicalProjection{}, + &plannercore.PhysicalSelection{}, + &plannercore.PhysicalTableDual{}, + &plannercore.PhysicalWindow{}, + &plannercore.PhysicalShuffle{}, + &plannercore.PhysicalUnionAll{}, + } + executorBuilder := executor.NewMockExecutorBuilderForTest(se, is, nil, math.MaxUint64, false, "global") + + var opsNeedsCoveredMask uint64 = 1< t1.a) AS a from t as t1) t", + "select /*+ hash_agg() */ count(f) from t group by a", + "select /*+ stream_agg() */ count(f) from t group by a", + "select * from t order by a, f", + "select * from t order by a, f limit 1", + "select * from t limit 1", + "select (select t1.a from t t1 where t1.a > t2.a) as a from t t2;", + "select a + 1 from t", + "select count(*) a from t having a > 1", + "select * from t where a = 1.1", + "with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1", + "select /*+use_index_merge(t, c_d_e, f)*/ * from t where c < 1 or f > 2", + "select sum(f) over (partition by f) from t", + "select /*+ merge_join(t1)*/ * from t t1 join t t2 on t1.d = t2.d", + "select a from t union all select a from t", + } { + comment := Commentf("case:%v sql:%s", i, tc) + c.Assert(err, IsNil, comment) + stmt, err := s.ParseOneStmt(tc, "", "") + c.Assert(err, IsNil, comment) + + err = se.NewTxn(context.Background()) + c.Assert(err, IsNil, comment) + p, _, err := planner.Optimize(context.TODO(), se, stmt, is) + c.Assert(err, IsNil, comment) + // This for loop level traverses the plan tree to get which operators are covered. + for child := []plannercore.PhysicalPlan{p.(plannercore.PhysicalPlan)}; len(child) != 0; { + newChild := make([]plannercore.PhysicalPlan, 0, len(child)) + for _, ch := range child { + found := false + for k, t := range opsNeedsCovered { + if reflect.TypeOf(t) == reflect.TypeOf(ch) { + opsAlreadyCoveredMask |= 1 << k + found = true + break + } + } + c.Assert(found, IsTrue, Commentf("case: %v sql: %s operator %v is not registered in opsNeedsCoveredMask", i, tc, reflect.TypeOf(ch))) + switch x := ch.(type) { + case *plannercore.PhysicalCTE: + newChild = append(newChild, x.RecurPlan) + newChild = append(newChild, x.SeedPlan) + continue + case *plannercore.PhysicalShuffle: + newChild = append(newChild, x.DataSources...) + newChild = append(newChild, x.Tails...) + continue + } + newChild = append(newChild, ch.Children()...) + } + child = newChild + } + + e := executorBuilder.Build(p) + + func() { + defer func() { + r := recover() + buf := make([]byte, 4096) + stackSize := runtime.Stack(buf, false) + buf = buf[:stackSize] + c.Assert(r, IsNil, Commentf("case: %v\n sql: %s\n error stack: %v", i, tc, string(buf))) + }() + c.Assert(e.Close(), IsNil, comment) + }() + } + // The following code is used to make sure all the operators registered + // in opsNeedsCoveredMask are covered. + commentBuf := strings.Builder{} + if opsAlreadyCoveredMask != opsNeedsCoveredMask { + for i := range opsNeedsCovered { + if opsAlreadyCoveredMask&(1<") - - // Test the START_TIME and END_TIME field. - re = tk.MustQuery("admin show ddl jobs where job_type = 'create table' and start_time > str_to_date('20190101','%Y%m%d%H%i%s')") - row = re.Rows()[0] - c.Assert(row[2], Equals, "t") - c.Assert(row[9], Equals, "") -} - -func (s *testSuiteP2) TestAdminShowDDLJobsInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_admin_show_ddl_jobs") - defer tk.MustExec("drop database if exists test_admin_show_ddl_jobs") - tk.MustExec("use test_admin_show_ddl_jobs") - tk.MustExec("drop table if exists t, t1;") - tk.MustExec("create table t (a int);") - tk.MustExec("create table t1 (a int);") - - // Test for issue: https://github.com/pingcap/tidb/issues/29915 - tk.MustExec("drop placement policy if exists x;") - tk.MustExec("create placement policy x followers=4;") - tk.MustExec("alter table t placement policy x;") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table placement") - - tk.MustExec("rename table t to tt, t1 to tt1") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "rename tables") - - tk.MustExec("create table tt2 (c int) PARTITION BY RANGE (c) " + - "(PARTITION p0 VALUES LESS THAN (6)," + - "PARTITION p1 VALUES LESS THAN (11)," + - "PARTITION p2 VALUES LESS THAN (16)," + - "PARTITION p3 VALUES LESS THAN (21));") - tk.MustExec("alter table tt2 partition p0 " + - "PRIMARY_REGION=\"cn-east-1\" " + - "REGIONS=\"cn-east-1, cn-east-2\" " + - "FOLLOWERS=2 ") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table partition placement") - - tk.MustExec("alter table tt1 cache") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table cache") - tk.MustExec("alter table tt1 nocache") - c.Assert(tk.MustQuery("admin show ddl jobs 1").Rows()[0][3], Equals, "alter table nocache") -} - -func (s *testSuiteP2) TestAdminChecksumOfPartitionedTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("USE test;") - tk.MustExec("DROP TABLE IF EXISTS admin_checksum_partition_test;") - tk.MustExec("CREATE TABLE admin_checksum_partition_test (a INT) PARTITION BY HASH(a) PARTITIONS 4;") - tk.MustExec("INSERT INTO admin_checksum_partition_test VALUES (1), (2);") - - r := tk.MustQuery("ADMIN CHECKSUM TABLE admin_checksum_partition_test;") - r.Check(testkit.Rows("test admin_checksum_partition_test 1 5 5")) -} - -func (s *baseTestSuite) fillData(tk *testkit.TestKit, table string) { - tk.MustExec("use test") - tk.MustExec(fmt.Sprintf("create table %s(id int not null default 1, name varchar(255), PRIMARY KEY(id));", table)) - - // insert data - tk.MustExec(fmt.Sprintf("insert INTO %s VALUES (1, \"hello\");", table)) - tk.CheckExecResult(1, 0) - tk.MustExec(fmt.Sprintf("insert into %s values (2, \"hello\");", table)) - tk.CheckExecResult(1, 0) + require.Len(t, tk.MustQuery("show table status").Rows(), 1) } -type testCase struct { - data1 []byte - data2 []byte - expected []string - restData []byte - expectedMsg string -} - -func checkCases(tests []testCase, ld *executor.LoadDataInfo, - t *testing.T, tk *testkit2.TestKit, ctx sessionctx.Context, selectSQL, deleteSQL string) { - origin := ld.IgnoreLines - for _, tt := range tests { - ld.IgnoreLines = origin - require.Nil(t, ctx.NewTxn(context.Background())) - ctx.GetSessionVars().StmtCtx.DupKeyAsWarning = true - ctx.GetSessionVars().StmtCtx.BadNullAsWarning = true - ctx.GetSessionVars().StmtCtx.InLoadDataStmt = true - ctx.GetSessionVars().StmtCtx.InDeleteStmt = false - data, reachLimit, err1 := ld.InsertData(context.Background(), tt.data1, tt.data2) - require.NoError(t, err1) - require.False(t, reachLimit) - err1 = ld.CheckAndInsertOneBatch(context.Background(), ld.GetRows(), ld.GetCurBatchCnt()) - require.NoError(t, err1) - ld.SetMaxRowsInBatch(20000) - if tt.restData == nil { - require.Len(t, data, 0, "data1:%v, data2:%v, data:%v", string(tt.data1), string(tt.data2), string(data)) - } else { - require.Equal(t, tt.restData, data, "data1:%v, data2:%v, data:%v", string(tt.data1), string(tt.data2), string(data)) - } - ld.SetMessage() - require.Equal(t, tt.expectedMsg, tk.Session().LastMessage()) - ctx.StmtCommit() - txn, err := ctx.Txn(true) - require.NoError(t, err) - err = txn.Commit(context.Background()) - require.NoError(t, err) - r := tk.MustQuery(selectSQL) - r.Check(testutil.RowsWithSep("|", tt.expected...)) - tk.MustExec(deleteSQL) - } -} - -func (s *testSuiteP1) TestSelectWithoutFrom(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectWithoutFrom(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - - r := tk.MustQuery("select 1 + 2*3;") - r.Check(testkit.Rows("7")) - - r = tk.MustQuery(`select _utf8"string";`) - r.Check(testkit.Rows("string")) - - r = tk.MustQuery("select 1 order by 1;") - r.Check(testkit.Rows("1")) + tk.MustQuery("select 1 + 2*3;").Check(testkit.Rows("7")) + tk.MustQuery(`select _utf8"string";`).Check(testkit.Rows("string")) + tk.MustQuery("select 1 order by 1;").Check(testkit.Rows("1")) } // TestSelectBackslashN Issue 3685. -func (s *testSuiteP1) TestSelectBackslashN(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectBackslashN(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) sql := `select \N;` - r := tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err := tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields := rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "NULL") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "NULL", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select "\N";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("N")) + tk.MustQuery(sql).Check(testkit.Rows("N")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) tk.MustExec("use test;") tk.MustExec("create table test (`\\N` int);") tk.MustExec("insert into test values (1);") tk.CheckExecResult(1, 0) sql = "select * from test;" - r = tk.MustQuery(sql) - r.Check(testkit.Rows("1")) + tk.MustQuery(sql).Check(testkit.Rows("1")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `\N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `\N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select \N from test;` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(err, IsNil) - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `NULL`) - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + require.Len(t, fields, 1) + require.Equal(t, `NULL`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select (\N) from test;` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `NULL`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `NULL`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select `\\N` from test;" - r = tk.MustQuery(sql) - r.Check(testkit.Rows("1")) + tk.MustQuery(sql).Check(testkit.Rows("1")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `\N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `\N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select (`\\N`) from test;" - r = tk.MustQuery(sql) - r.Check(testkit.Rows("1")) + tk.MustQuery(sql).Check(testkit.Rows("1")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `\N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `\N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select '\N' from test;` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("N")) + tk.MustQuery(sql).Check(testkit.Rows("N")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select ('\N') from test;` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("N")) + tk.MustQuery(sql).Check(testkit.Rows("N")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `N`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `N`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) } // TestSelectNull Issue #4053. -func (s *testSuiteP1) TestSelectNull(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectNull(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) sql := `select nUll;` - r := tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err := tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields := rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `NULL`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `NULL`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select (null);` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `NULL`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `NULL`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select null+NULL;` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("")) + tk.MustQuery(sql).Check(testkit.Rows("")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(err, IsNil) - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `null+NULL`) - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + require.Len(t, fields, 1) + require.Equal(t, `null+NULL`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) } // TestSelectStringLiteral Issue #3686. -func (s *testSuiteP1) TestSelectStringLiteral(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectStringLiteral(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) sql := `select 'abc';` - r := tk.MustQuery(sql) - r.Check(testkit.Rows("abc")) + tk.MustQuery(sql).Check(testkit.Rows("abc")) rs, err := tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields := rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `abc`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `abc`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select (('abc'));` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("abc")) + tk.MustQuery(sql).Check(testkit.Rows("abc")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `abc`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `abc`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select 'abc'+'def';` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("0")) + tk.MustQuery(sql).Check(testkit.Rows("0")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, `'abc'+'def'`) - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, `'abc'+'def'`, fields[0].Column.Name.O) + require.NoError(t, rs.Close()) // Below checks whether leading invalid chars are trimmed. sql = "select '\n';" - r = tk.MustQuery(sql) - r.Check(testkit.Rows("\n")) + tk.MustQuery(sql).Check(testkit.Rows("\n")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select '\t col';" // Lowercased letter is a valid char. rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "col") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "col", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select '\t Col';" // Uppercased letter is a valid char. rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "Col") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "Col", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select '\n\t 中文 col';" // Chinese char is a valid char. rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "中文 col") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "中文 col", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select ' \r\n .col';" // Punctuation is a valid char. rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, ".col") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, ".col", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = "select ' 😆col';" // Emoji is a valid char. rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "😆col") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "😆col", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) // Below checks whether trailing invalid chars are preserved. sql = `select 'abc ';` rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "abc ") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "abc ", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select ' abc 123 ';` rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "abc 123 ") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "abc 123 ", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) // Issue #4239. sql = `select 'a' ' ' 'string';` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("a string")) + tk.MustQuery(sql).Check(testkit.Rows("a string")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "a") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "a", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select 'a' " " "string";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("a string")) + tk.MustQuery(sql).Check(testkit.Rows("a string")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "a") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "a", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select 'string' 'string';` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("stringstring")) + tk.MustQuery(sql).Check(testkit.Rows("stringstring")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "string") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "string", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select "ss" "a";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("ssa")) + tk.MustQuery(sql).Check(testkit.Rows("ssa")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "ss") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "ss", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select "ss" "a" "b";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("ssab")) + tk.MustQuery(sql).Check(testkit.Rows("ssab")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "ss") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "ss", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select "ss" "a" ' ' "b";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("ssa b")) + tk.MustQuery(sql).Check(testkit.Rows("ssa b")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "ss") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "ss", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) sql = `select "ss" "a" ' ' "b" ' ' "d";` - r = tk.MustQuery(sql) - r.Check(testkit.Rows("ssa b d")) + tk.MustQuery(sql).Check(testkit.Rows("ssa b d")) rs, err = tk.Exec(sql) - c.Check(err, IsNil) + require.NoError(t, err) fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.O, Equals, "ss") - c.Assert(rs.Close(), IsNil) + require.Len(t, fields, 1) + require.Equal(t, "ss", fields[0].Column.Name.O) + require.NoError(t, rs.Close()) } -func (s *testSuiteP1) TestSelectLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - s.fillData(tk, "select_limit") + tk.MustExec("create table select_limit(id int not null default 1, name varchar(255), PRIMARY KEY(id));") + // insert data + tk.MustExec("insert INTO select_limit VALUES (1, \"hello\");") + tk.CheckExecResult(1, 0) + tk.MustExec("insert into select_limit values (2, \"hello\");") + tk.CheckExecResult(1, 0) tk.MustExec("insert INTO select_limit VALUES (3, \"hello\");") tk.CheckExecResult(1, 0) tk.MustExec("insert INTO select_limit VALUES (4, \"hello\");") tk.CheckExecResult(1, 0) - r := tk.MustQuery("select * from select_limit limit 1;") - r.Check(testkit.Rows("1 hello")) + tk.MustQuery("select * from select_limit limit 1;").Check(testkit.Rows("1 hello")) - r = tk.MustQuery("select id from (select * from select_limit limit 1) k where id != 1;") - r.Check(testkit.Rows()) + tk.MustQuery("select id from (select * from select_limit limit 1) k where id != 1;").Check(testkit.Rows()) - r = tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 0;") - r.Check(testkit.Rows("1 hello", "2 hello", "3 hello", "4 hello")) + tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 0;").Check(testkit.Rows("1 hello", "2 hello", "3 hello", "4 hello")) - r = tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 1;") - r.Check(testkit.Rows("2 hello", "3 hello", "4 hello")) + tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 1;").Check(testkit.Rows("2 hello", "3 hello", "4 hello")) - r = tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 3;") - r.Check(testkit.Rows("4 hello")) + tk.MustQuery("select * from select_limit limit 18446744073709551615 offset 3;").Check(testkit.Rows("4 hello")) err := tk.ExecToErr("select * from select_limit limit 18446744073709551616 offset 3;") - c.Assert(err, NotNil) + require.Error(t, err) } -func (s *testSuiteP1) TestSelectOrderBy(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectOrderBy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - s.fillData(tk, "select_order_test") + tk.MustExec("create table select_order_test(id int not null default 1, name varchar(255), PRIMARY KEY(id));") - // Test star field - r := tk.MustQuery("select * from select_order_test where id = 1 order by id limit 1 offset 0;") - r.Check(testkit.Rows("1 hello")) - - r = tk.MustQuery("select id from select_order_test order by id desc limit 1 ") - r.Check(testkit.Rows("2")) - - r = tk.MustQuery("select id from select_order_test order by id + 1 desc limit 1 ") - r.Check(testkit.Rows("2")) + // insert data + tk.MustExec("insert INTO select_order_test VALUES (1, \"hello\");") + tk.CheckExecResult(1, 0) + tk.MustExec("insert into select_order_test values (2, \"hello\");") + tk.CheckExecResult(1, 0) + // Test star field + tk.MustQuery("select * from select_order_test where id = 1 order by id limit 1 offset 0;").Check(testkit.Rows("1 hello")) + tk.MustQuery("select id from select_order_test order by id desc limit 1 ").Check(testkit.Rows("2")) + tk.MustQuery("select id from select_order_test order by id + 1 desc limit 1 ").Check(testkit.Rows("2")) // Test limit - r = tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 0;") - r.Check(testkit.Rows("1 hello")) - + tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 0;").Check(testkit.Rows("1 hello")) // Test limit - r = tk.MustQuery("select id as c1, name from select_order_test order by 2, id limit 1 offset 0;") - r.Check(testkit.Rows("1 hello")) - + tk.MustQuery("select id as c1, name from select_order_test order by 2, id limit 1 offset 0;").Check(testkit.Rows("1 hello")) // Test limit overflow - r = tk.MustQuery("select * from select_order_test order by name, id limit 100 offset 0;") - r.Check(testkit.Rows("1 hello", "2 hello")) - + tk.MustQuery("select * from select_order_test order by name, id limit 100 offset 0;").Check(testkit.Rows("1 hello", "2 hello")) // Test offset overflow - r = tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 100;") - r.Check(testkit.Rows()) - + tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 100;").Check(testkit.Rows()) // Test limit exceeds int range. - r = tk.MustQuery("select id from select_order_test order by name, id limit 18446744073709551615;") - r.Check(testkit.Rows("1", "2")) - + tk.MustQuery("select id from select_order_test order by name, id limit 18446744073709551615;").Check(testkit.Rows("1", "2")) // Test multiple field - r = tk.MustQuery("select id, name from select_order_test where id = 1 group by id, name limit 1 offset 0;") - r.Check(testkit.Rows("1 hello")) + tk.MustQuery("select id, name from select_order_test where id = 1 group by id, name limit 1 offset 0;").Check(testkit.Rows("1 hello")) // Test limit + order by for i := 3; i <= 10; i += 1 { @@ -1094,28 +551,22 @@ func (s *testSuiteP1) TestSelectOrderBy(c *C) { tk.MustExec(fmt.Sprintf("insert INTO select_order_test VALUES (%d, \"zz\");", i)) } tk.MustExec("insert INTO select_order_test VALUES (1501, \"aa\");") - r = tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 3;") - r.Check(testkit.Rows("11 hh")) + tk.MustQuery("select * from select_order_test order by name, id limit 1 offset 3;").Check(testkit.Rows("11 hh")) tk.MustExec("drop table select_order_test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c int, d int)") tk.MustExec("insert t values (1, 1)") tk.MustExec("insert t values (1, 2)") tk.MustExec("insert t values (1, 3)") - r = tk.MustQuery("select 1-d as d from t order by d;") - r.Check(testkit.Rows("-2", "-1", "0")) - r = tk.MustQuery("select 1-d as d from t order by d + 1;") - r.Check(testkit.Rows("0", "-1", "-2")) - r = tk.MustQuery("select t.d from t order by d;") - r.Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select 1-d as d from t order by d;").Check(testkit.Rows("-2", "-1", "0")) + tk.MustQuery("select 1-d as d from t order by d + 1;").Check(testkit.Rows("0", "-1", "-2")) + tk.MustQuery("select t.d from t order by d;").Check(testkit.Rows("1", "2", "3")) tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, c int)") tk.MustExec("insert t values (1, 2, 3)") - r = tk.MustQuery("select b from (select a,b from t order by a,c) t") - r.Check(testkit.Rows("2")) - r = tk.MustQuery("select b from (select a,b from t order by a,c limit 1) t") - r.Check(testkit.Rows("2")) + tk.MustQuery("select b from (select a,b from t order by a,c) t").Check(testkit.Rows("2")) + tk.MustQuery("select b from (select a,b from t order by a,c limit 1) t").Check(testkit.Rows("2")) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, index idx(a))") tk.MustExec("insert into t values(1, 1), (2, 2)") @@ -1133,16 +584,18 @@ func (s *testSuiteP1) TestSelectOrderBy(c *C) { // Test double read which needs to keep order. tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, key b (b))") - tk.Se.GetSessionVars().IndexLookupSize = 3 + tk.Session().GetSessionVars().IndexLookupSize = 3 for i := 0; i < 10; i++ { tk.MustExec(fmt.Sprintf("insert into t values(%d, %d)", i, 10-i)) } tk.MustQuery("select a from t use index(b) order by b").Check(testkit.Rows("9", "8", "7", "6", "5", "4", "3", "2", "1", "0")) } -func (s *testSuiteP1) TestOrderBy(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t") +func TestOrderBy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t (c1 int, c2 int, c3 varchar(20))") tk.MustExec("insert into t values (1, 2, 'abc'), (2, 1, 'bcd')") @@ -1163,444 +616,26 @@ func (s *testSuiteP1) TestOrderBy(c *C) { tk.MustQuery("select c1, c2 from t order by binary c3").Check(testkit.Rows("1 2", "2 1")) } -func (s *testSuiteP1) TestSelectErrorRow(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - err := tk.ExecToErr("select row(1, 1) from test") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test group by row(1, 1);") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test order by row(1, 1);") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test having row(1, 1);") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select (select 1, 1) from test;") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test group by (select 1, 1);") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test order by (select 1, 1);") - c.Assert(err, NotNil) - - err = tk.ExecToErr("select * from test having (select 1, 1);") - c.Assert(err, NotNil) -} - -// TestIssue2612 is related with https://github.com/pingcap/tidb/issues/2612 -func (s *testSuiteP1) TestIssue2612(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t ( - create_at datetime NOT NULL DEFAULT '1000-01-01 00:00:00', - finish_at datetime NOT NULL DEFAULT '1000-01-01 00:00:00');`) - tk.MustExec(`insert into t values ('2016-02-13 15:32:24', '2016-02-11 17:23:22');`) - rs, err := tk.Exec(`select timediff(finish_at, create_at) from t;`) - c.Assert(err, IsNil) - req := rs.NewChunk(nil) - err = rs.Next(context.Background(), req) - c.Assert(err, IsNil) - c.Assert(req.GetRow(0).GetDuration(0, 0).String(), Equals, "-46:09:02") - c.Assert(rs.Close(), IsNil) -} - -// TestIssue345 is related with https://github.com/pingcap/tidb/issues/345 -func (s *testSuiteP1) TestIssue345(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec(`drop table if exists t1, t2`) - tk.MustExec(`create table t1 (c1 int);`) - tk.MustExec(`create table t2 (c2 int);`) - tk.MustExec(`insert into t1 values (1);`) - tk.MustExec(`insert into t2 values (2);`) - tk.MustExec(`update t1, t2 set t1.c1 = 2, t2.c2 = 1;`) - tk.MustExec(`update t1, t2 set c1 = 2, c2 = 1;`) - tk.MustExec(`update t1 as a, t2 as b set a.c1 = 2, b.c2 = 1;`) - - // Check t1 content - r := tk.MustQuery("SELECT * FROM t1;") - r.Check(testkit.Rows("2")) - // Check t2 content - r = tk.MustQuery("SELECT * FROM t2;") - r.Check(testkit.Rows("1")) - - tk.MustExec(`update t1 as a, t2 as t1 set a.c1 = 1, t1.c2 = 2;`) - // Check t1 content - r = tk.MustQuery("SELECT * FROM t1;") - r.Check(testkit.Rows("1")) - // Check t2 content - r = tk.MustQuery("SELECT * FROM t2;") - r.Check(testkit.Rows("2")) - - _, err := tk.Exec(`update t1 as a, t2 set t1.c1 = 10;`) - c.Assert(err, NotNil) -} - -func (s *testSuiteP1) TestIssue5055(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec(`drop table if exists t1, t2`) - tk.MustExec(`create table t1 (a int);`) - tk.MustExec(`create table t2 (a int);`) - tk.MustExec(`insert into t1 values(1);`) - tk.MustExec(`insert into t2 values(1);`) - result := tk.MustQuery("select tbl1.* from (select t1.a, 1 from t1) tbl1 left join t2 tbl2 on tbl1.a = tbl2.a order by tbl1.a desc limit 1;") - result.Check(testkit.Rows("1 1")) -} - -func (s *testSuiteWithData) TestSetOperation(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t1, t2, t3`) - tk.MustExec(`create table t1(a int)`) - tk.MustExec(`create table t2 like t1`) - tk.MustExec(`create table t3 like t1`) - tk.MustExec(`insert into t1 values (1),(1),(2),(3),(null)`) - tk.MustExec(`insert into t2 values (1),(2),(null),(null)`) - tk.MustExec(`insert into t3 values (2),(3)`) - - var input []string - var output []struct { - SQL string - Plan []string - Res []string - } - s.testData.GetTestCases(c, &input, &output) - for i, tt := range input { - s.testData.OnRecord(func() { - output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) - }) - tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) - tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) - } -} - -func (s *testSuiteWithData) TestSetOperationOnDiffColType(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t1, t2, t3`) - tk.MustExec(`create table t1(a int, b int)`) - tk.MustExec(`create table t2(a int, b varchar(20))`) - tk.MustExec(`create table t3(a int, b decimal(30,10))`) - tk.MustExec(`insert into t1 values (1,1),(1,1),(2,2),(3,3),(null,null)`) - tk.MustExec(`insert into t2 values (1,'1'),(2,'2'),(null,null),(null,'3')`) - tk.MustExec(`insert into t3 values (2,2.1),(3,3)`) - - var input []string - var output []struct { - SQL string - Plan []string - Res []string - } - s.testData.GetTestCases(c, &input, &output) - for i, tt := range input { - s.testData.OnRecord(func() { - output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) - }) - tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) - tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) - } -} - -// issue-23038: wrong key range of index scan for year column -func (s *testSuiteWithData) TestIndexScanWithYearCol(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (c1 year(4), c2 int, key(c1));") - tk.MustExec("insert into t values(2001, 1);") - - var input []string - var output []struct { - SQL string - Plan []string - Res []string - } - s.testData.GetTestCases(c, &input, &output) - for i, tt := range input { - s.testData.OnRecord(func() { - output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) - }) - tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) - tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) - } -} - -func (s *testSuiteP2) TestUnion(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - testSQL := `drop table if exists union_test; create table union_test(id int);` - tk.MustExec(testSQL) - - testSQL = `drop table if exists union_test;` - tk.MustExec(testSQL) - testSQL = `create table union_test(id int);` - tk.MustExec(testSQL) - testSQL = `insert union_test values (1),(2)` - tk.MustExec(testSQL) - - testSQL = `select * from (select id from union_test union select id from union_test) t order by id;` - r := tk.MustQuery(testSQL) - r.Check(testkit.Rows("1", "2")) - - r = tk.MustQuery("select 1 union all select 1") - r.Check(testkit.Rows("1", "1")) - - r = tk.MustQuery("select 1 union all select 1 union select 1") - r.Check(testkit.Rows("1")) - - r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1") - r.Check(testkit.Rows("1")) - - r = tk.MustQuery("select 1 as a union (select 2) order by a limit 1, 1") - r.Check(testkit.Rows("2")) - - r = tk.MustQuery("select id from union_test union all (select 1) order by id desc") - r.Check(testkit.Rows("2", "1", "1")) - - r = tk.MustQuery("select id as a from union_test union (select 1) order by a desc") - r.Check(testkit.Rows("2", "1")) - - r = tk.MustQuery(`select null as a union (select "abc") order by a`) - r.Check(testkit.Rows("", "abc")) - - r = tk.MustQuery(`select "abc" as a union (select 1) order by a`) - r.Check(testkit.Rows("1", "abc")) - - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c int, d int)") - tk.MustExec("insert t1 values (NULL, 1)") - tk.MustExec("insert t1 values (1, 1)") - tk.MustExec("insert t1 values (1, 2)") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2 (c int, d int)") - tk.MustExec("insert t2 values (1, 3)") - tk.MustExec("insert t2 values (1, 1)") - tk.MustExec("drop table if exists t3") - tk.MustExec("create table t3 (c int, d int)") - tk.MustExec("insert t3 values (3, 2)") - tk.MustExec("insert t3 values (4, 3)") - r = tk.MustQuery(`select sum(c1), c2 from (select c c1, d c2 from t1 union all select d c1, c c2 from t2 union all select c c1, d c2 from t3) x group by c2 order by c2`) - r.Check(testkit.Rows("5 1", "4 2", "4 3")) - - tk.MustExec("drop table if exists t1, t2, t3") - tk.MustExec("create table t1 (a int primary key)") - tk.MustExec("create table t2 (a int primary key)") - tk.MustExec("create table t3 (a int primary key)") - tk.MustExec("insert t1 values (7), (8)") - tk.MustExec("insert t2 values (1), (9)") - tk.MustExec("insert t3 values (2), (3)") - r = tk.MustQuery("select * from t1 union all select * from t2 union all (select * from t3) order by a limit 2") - r.Check(testkit.Rows("1", "2")) - - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1 (a int)") - tk.MustExec("create table t2 (a int)") - tk.MustExec("insert t1 values (2), (1)") - tk.MustExec("insert t2 values (3), (4)") - r = tk.MustQuery("select * from t1 union all (select * from t2) order by a limit 1") - r.Check(testkit.Rows("1")) - r = tk.MustQuery("select (select * from t1 where a != t.a union all (select * from t2 where a != t.a) order by a limit 1) from t1 t") - r.Check(testkit.Rows("1", "2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (id int unsigned primary key auto_increment, c1 int, c2 int, index c1_c2 (c1, c2))") - tk.MustExec("insert into t (c1, c2) values (1, 1)") - tk.MustExec("insert into t (c1, c2) values (1, 2)") - tk.MustExec("insert into t (c1, c2) values (2, 3)") - r = tk.MustQuery("select * from (select * from t where t.c1 = 1 union select * from t where t.id = 1) s order by s.id") - r.Check(testkit.Rows("1 1 1", "2 1 2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (f1 DATE)") - tk.MustExec("INSERT INTO t VALUES ('1978-11-26')") - r = tk.MustQuery("SELECT f1+0 FROM t UNION SELECT f1+0 FROM t") - r.Check(testkit.Rows("19781126")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a int, b int)") - tk.MustExec("INSERT INTO t VALUES ('1', '1')") - r = tk.MustQuery("select b from (SELECT * FROM t UNION ALL SELECT a, b FROM t order by a) t") - r.Check(testkit.Rows("1", "1")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a DECIMAL(4,2))") - tk.MustExec("INSERT INTO t VALUE(12.34)") - r = tk.MustQuery("SELECT 1 AS c UNION select a FROM t") - r.Sort().Check(testkit.Rows("1.00", "12.34")) - - // #issue3771 - r = tk.MustQuery("SELECT 'a' UNION SELECT CONCAT('a', -4)") - r.Sort().Check(testkit.Rows("a", "a-4")) - - // test race - tk.MustQuery("SELECT @x:=0 UNION ALL SELECT @x:=0 UNION ALL SELECT @x") - - // test field tp - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("CREATE TABLE t1 (a date)") - tk.MustExec("CREATE TABLE t2 (a date)") - tk.MustExec("SELECT a from t1 UNION select a FROM t2") - tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` date DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // Move from session test. - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1 (c double);") - tk.MustExec("create table t2 (c double);") - tk.MustExec("insert into t1 value (73);") - tk.MustExec("insert into t2 value (930);") - // If set unspecified column flen to 0, it will cause bug in union. - // This test is used to prevent the bug reappear. - tk.MustQuery("select c from t1 union (select c from t2) order by c").Check(testkit.Rows("73", "930")) - - // issue 5703 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a date)") - tk.MustExec("insert into t value ('2017-01-01'), ('2017-01-02')") - r = tk.MustQuery("(select a from t where a < 0) union (select a from t where a > 0) order by a") - r.Check(testkit.Rows("2017-01-01", "2017-01-02")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t value(0),(0)") - tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1")) - tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10")) - tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10")) - tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4")) - - err := tk.ExecToErr("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp") - c.Assert(err, NotNil) - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) - - err = tk.ExecToErr("select 1 from (select a from t order by a union all select a from t limit 1) tmp") - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongUsage)) - - _, err = tk.Exec("(select a from t order by a) union all select a from t limit 1 union all select a from t limit 1") - c.Assert(terror.ErrorEqual(err, plannercore.ErrWrongUsage), IsTrue, Commentf("err %v", err)) - - _, err = tk.Exec("(select a from t limit 1) union all select a from t limit 1") - c.Assert(err, IsNil) - _, err = tk.Exec("(select a from t order by a) union all select a from t order by a") - c.Assert(err, IsNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t value(1),(2),(3)") - - tk.MustQuery("(select a from t order by a limit 2) union all (select a from t order by a desc limit 2) order by a desc limit 1,2").Check(testkit.Rows("2", "2")) - tk.MustQuery("select a from t union all select a from t order by a desc limit 5").Check(testkit.Rows("3", "3", "2", "2", "1")) - tk.MustQuery("(select a from t order by a desc limit 2) union all select a from t group by a order by a").Check(testkit.Rows("1", "2", "2", "3", "3")) - tk.MustQuery("(select a from t order by a desc limit 2) union all select 33 as a order by a desc limit 2").Check(testkit.Rows("33", "3")) - - tk.MustQuery("select 1 union select 1 union all select 1").Check(testkit.Rows("1", "1")) - tk.MustQuery("select 1 union all select 1 union select 1").Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t1, t2") - tk.MustExec(`create table t1(a bigint, b bigint);`) - tk.MustExec(`create table t2(a bigint, b bigint);`) - tk.MustExec(`insert into t1 values(1, 1);`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t1 select * from t1;`) - tk.MustExec(`insert into t2 values(1, 1);`) - tk.MustExec(`set @@tidb_init_chunk_size=2;`) - tk.MustExec(`set @@sql_mode="";`) - tk.MustQuery(`select count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("128")) - tk.MustQuery(`select tmp.a, count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("1 128")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int)") - tk.MustExec("insert into t value(1 ,2)") - tk.MustQuery("select a, b from (select a, 0 as d, b from t union all select a, 0 as d, b from t) test;").Check(testkit.Rows("1 2", "1 2")) - - // #issue 8141 - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(a int, b int)") - tk.MustExec("insert into t1 value(1,2),(1,1),(2,2),(2,2),(3,2),(3,2)") - tk.MustExec("set @@tidb_init_chunk_size=2;") - tk.MustQuery("select count(*) from (select a as c, a as d from t1 union all select a, b from t1) t;").Check(testkit.Rows("12")) - - // #issue 8189 and #issue 8199 - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") - tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") - tk.MustExec("insert into t2 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustQuery("select a from t1 union select a from t1 order by (select a+1);").Check(testkit.Rows("1", "2", "3")) - - // #issue 8201 - for i := 0; i < 4; i++ { - tk.MustQuery("SELECT(SELECT 0 AS a FROM dual UNION SELECT 1 AS a FROM dual ORDER BY a ASC LIMIT 1) AS dev").Check(testkit.Rows("0")) - } - - // #issue 8231 - tk.MustExec("drop table if exists t1") - tk.MustExec("CREATE TABLE t1 (uid int(1))") - tk.MustExec("INSERT INTO t1 SELECT 150") - tk.MustQuery("SELECT 'a' UNION SELECT uid FROM t1 order by 1 desc;").Check(testkit.Rows("a", "150")) - - // #issue 8196 - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)") - tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')") - tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)") - tk.MustExec("insert into t2 values(3,'c'),(4,'d'),(5,'f'),(6,'e')") - tk.MustExec("analyze table t1") - tk.MustExec("analyze table t2") - _, err = tk.Exec("(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b") - c.Assert(err.Error(), Equals, "[planner:1250]Table 't1' from one of the SELECTs cannot be used in global ORDER clause") - - // #issue 9900 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b decimal(6, 3))") - tk.MustExec("insert into t values(1, 1.000)") - tk.MustQuery("select count(distinct a), sum(distinct a), avg(distinct a) from (select a from t union all select b from t) tmp;").Check(testkit.Rows("1 1.000 1.0000000")) - - // #issue 23832 - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a bit(20), b float, c double, d int)") - tk.MustExec("insert into t values(10, 10, 10, 10), (1, -1, 2, -2), (2, -2, 1, 1), (2, 1.1, 2.1, 10.1)") - tk.MustQuery("select a from t union select 10 order by a").Check(testkit.Rows("1", "2", "10")) -} - -func (s *testSuite2) TestUnionLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectErrorRow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists union_limit") - tk.MustExec("create table union_limit (id int) partition by hash(id) partitions 30") - for i := 0; i < 60; i++ { - tk.MustExec(fmt.Sprintf("insert into union_limit values (%d)", i)) - } - // Cover the code for worker count limit in the union executor. - tk.MustQuery("select * from union_limit limit 10") + require.Error(t, tk.ExecToErr("select row(1, 1) from test")) + require.Error(t, tk.ExecToErr("select * from test group by row(1, 1);")) + require.Error(t, tk.ExecToErr("select * from test order by row(1, 1);")) + require.Error(t, tk.ExecToErr("select * from test having row(1, 1);")) + require.Error(t, tk.ExecToErr("select (select 1, 1) from test;")) + require.Error(t, tk.ExecToErr("select * from test group by (select 1, 1);")) + require.Error(t, tk.ExecToErr("select * from test order by (select 1, 1);")) + require.Error(t, tk.ExecToErr("select * from test having (select 1, 1);")) } -func (s *testSuiteP1) TestNeighbouringProj(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNeighbouringProj(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - - tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int)") tk.MustExec("create table t2(a int, b int)") tk.MustExec("insert into t1 value(1, 1), (2, 2)") @@ -1610,12 +645,13 @@ func (s *testSuiteP1) TestNeighbouringProj(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint, b bigint, c bigint);") tk.MustExec("insert into t values(1, 1, 1), (2, 2, 2), (3, 3, 3);") - rs := tk.MustQuery("select cast(count(a) as signed), a as another, a from t group by a order by cast(count(a) as signed), a limit 10;") - rs.Check(testkit.Rows("1 1 1", "1 2 2", "1 3 3")) + tk.MustQuery("select cast(count(a) as signed), a as another, a from t group by a order by cast(count(a) as signed), a limit 10;").Check(testkit.Rows("1 1 1", "1 2 2", "1 3 3")) } -func (s *testSuiteP1) TestIn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t (c1 int primary key, c2 int, key c (c2));`) @@ -1623,15 +659,16 @@ func (s *testSuiteP1) TestIn(c *C) { tk.MustExec(fmt.Sprintf("insert t values(%d, %d)", i, i)) } queryStr := `select c2 from t where c1 in ('7', '10', '112', '111', '98', '106', '100', '9', '18', '17') order by c2` - r := tk.MustQuery(queryStr) - r.Check(testkit.Rows("7", "9", "10", "17", "18", "98", "100", "106", "111", "112")) + tk.MustQuery(queryStr).Check(testkit.Rows("7", "9", "10", "17", "18", "98", "100", "106", "111", "112")) queryStr = `select c2 from t where c1 in ('7a')` tk.MustQuery(queryStr).Check(testkit.Rows("7")) } -func (s *testSuiteP1) TestTablePKisHandleScan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTablePKisHandleScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int PRIMARY KEY AUTO_INCREMENT)") @@ -1687,126 +724,43 @@ func (s *testSuiteP1) TestTablePKisHandleScan(c *C) { } for _, tt := range tests { - result := tk.MustQuery(tt.sql) - result.Check(tt.result) + tk.MustQuery(tt.sql).Check(tt.result) } } -func (s *testSuite8) TestIndexScan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexReverseOrder(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int unique)") - tk.MustExec("insert t values (-1), (2), (3), (5), (6), (7), (8), (9)") - result := tk.MustQuery("select a from t where a < 0 or (a >= 2.1 and a < 5.1) or ( a > 5.9 and a <= 7.9) or a > '8.1'") - result.Check(testkit.Rows("-1", "3", "5", "6", "7", "9")) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int unique)") - tk.MustExec("insert t values (0)") - result = tk.MustQuery("select NULL from t ") - result.Check(testkit.Rows("")) - // test for double read - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int unique, b int)") - tk.MustExec("insert t values (5, 0)") - tk.MustExec("insert t values (4, 0)") - tk.MustExec("insert t values (3, 0)") - tk.MustExec("insert t values (2, 0)") - tk.MustExec("insert t values (1, 0)") - tk.MustExec("insert t values (0, 0)") - result = tk.MustQuery("select * from t order by a limit 3") - result.Check(testkit.Rows("0 0", "1 0", "2 0")) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int unique, b int)") - tk.MustExec("insert t values (0, 1)") - tk.MustExec("insert t values (1, 2)") - tk.MustExec("insert t values (2, 1)") - tk.MustExec("insert t values (3, 2)") - tk.MustExec("insert t values (4, 1)") - tk.MustExec("insert t values (5, 2)") - result = tk.MustQuery("select * from t where a < 5 and b = 1 limit 2") - result.Check(testkit.Rows("0 1", "2 1")) - tk.MustExec("drop table if exists tab1") - tk.MustExec("CREATE TABLE tab1(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col3 INTEGER, col4 FLOAT)") - tk.MustExec("CREATE INDEX idx_tab1_0 on tab1 (col0)") - tk.MustExec("CREATE INDEX idx_tab1_1 on tab1 (col1)") - tk.MustExec("CREATE INDEX idx_tab1_3 on tab1 (col3)") - tk.MustExec("CREATE INDEX idx_tab1_4 on tab1 (col4)") - tk.MustExec("INSERT INTO tab1 VALUES(1,37,20.85,30,10.69)") - result = tk.MustQuery("SELECT pk FROM tab1 WHERE ((col3 <= 6 OR col3 < 29 AND (col0 < 41)) OR col3 > 42) AND col1 >= 96.1 AND col3 = 30 AND col3 > 17 AND (col0 BETWEEN 36 AND 42)") - result.Check(testkit.Rows()) - tk.MustExec("drop table if exists tab1") - tk.MustExec("CREATE TABLE tab1(pk INTEGER PRIMARY KEY, a INTEGER, b INTEGER)") - tk.MustExec("CREATE INDEX idx_tab1_0 on tab1 (a)") - tk.MustExec("INSERT INTO tab1 VALUES(1,1,1)") - tk.MustExec("INSERT INTO tab1 VALUES(2,2,1)") - tk.MustExec("INSERT INTO tab1 VALUES(3,1,2)") - tk.MustExec("INSERT INTO tab1 VALUES(4,2,2)") - result = tk.MustQuery("SELECT * FROM tab1 WHERE pk <= 3 AND a = 1") - result.Check(testkit.Rows("1 1 1", "3 1 2")) - result = tk.MustQuery("SELECT * FROM tab1 WHERE pk <= 4 AND a = 1 AND b = 2") - result.Check(testkit.Rows("3 1 2")) - tk.MustExec("CREATE INDEX idx_tab1_1 on tab1 (b, a)") - result = tk.MustQuery("SELECT pk FROM tab1 WHERE b > 1") - result.Check(testkit.Rows("3", "4")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a varchar(3), index(a))") - tk.MustExec("insert t values('aaa'), ('aab')") - result = tk.MustQuery("select * from t where a >= 'aaaa' and a < 'aabb'") - result.Check(testkit.Rows("aab")) - - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a int primary key, b int, c int, index(c))") - tk.MustExec("insert t values(1, 1, 1), (2, 2, 2), (4, 4, 4), (3, 3, 3), (5, 5, 5)") - // Test for double read and top n. - result = tk.MustQuery("select a from t where c >= 2 order by b desc limit 1") - result.Check(testkit.Rows("5")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a varchar(50) primary key, b int, c int, index idx(b))") - tk.MustExec("insert into t values('aa', 1, 1)") - tk.MustQuery("select * from t use index(idx) where a > 'a'").Check(testkit.Rows("aa 1 1")) - - // fix issue9636 - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE `t` (a int, KEY (a))") - result = tk.MustQuery(`SELECT * FROM (SELECT * FROM (SELECT a as d FROM t WHERE a IN ('100')) AS x WHERE x.d < "123" ) tmp_count`) - result.Check(testkit.Rows()) -} - -func (s *testSuiteP1) TestIndexReverseOrder(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key auto_increment, b int, index idx (b))") - tk.MustExec("insert t (b) values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)") - result := tk.MustQuery("select b from t order by b desc") - result.Check(testkit.Rows("9", "8", "7", "6", "5", "4", "3", "2", "1", "0")) - result = tk.MustQuery("select b from t where b <3 or (b >=6 and b < 8) order by b desc") - result.Check(testkit.Rows("7", "6", "2", "1", "0")) - + tk.MustExec("create table t (a int primary key auto_increment, b int, index idx (b))") + tk.MustExec("insert t (b) values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)") + tk.MustQuery("select b from t order by b desc").Check(testkit.Rows("9", "8", "7", "6", "5", "4", "3", "2", "1", "0")) + tk.MustQuery("select b from t where b <3 or (b >=6 and b < 8) order by b desc").Check(testkit.Rows("7", "6", "2", "1", "0")) + tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, index idx (b, a))") tk.MustExec("insert t values (0, 2), (1, 2), (2, 2), (0, 1), (1, 1), (2, 1), (0, 0), (1, 0), (2, 0)") - result = tk.MustQuery("select b, a from t order by b, a desc") - result.Check(testkit.Rows("0 2", "0 1", "0 0", "1 2", "1 1", "1 0", "2 2", "2 1", "2 0")) + tk.MustQuery("select b, a from t order by b, a desc").Check(testkit.Rows("0 2", "0 1", "0 0", "1 2", "1 1", "1 0", "2 2", "2 1", "2 0")) } -func (s *testSuiteP1) TestTableReverseOrder(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableReverseOrder(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int primary key auto_increment, b int)") tk.MustExec("insert t (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9)") - result := tk.MustQuery("select b from t order by a desc") - result.Check(testkit.Rows("9", "8", "7", "6", "5", "4", "3", "2", "1")) - result = tk.MustQuery("select a from t where a <3 or (a >=6 and a < 8) order by a desc") - result.Check(testkit.Rows("7", "6", "2", "1")) + tk.MustQuery("select b from t order by a desc").Check(testkit.Rows("9", "8", "7", "6", "5", "4", "3", "2", "1")) + tk.MustQuery("select a from t where a <3 or (a >=6 and a < 8) order by a desc").Check(testkit.Rows("7", "6", "2", "1")) } -func (s *testSuiteP1) TestDefaultNull(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDefaultNull(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int primary key auto_increment, b int default 1, c int)") @@ -1821,21 +775,23 @@ func (s *testSuiteP1) TestDefaultNull(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("1 1 ")) } -func (s *testSuiteP1) TestUnsignedPKColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUnsignedPKColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int unsigned primary key, b int, c int, key idx_ba (b, c, a));") tk.MustExec("insert t values (1, 1, 1)") - result := tk.MustQuery("select * from t;") - result.Check(testkit.Rows("1 1 1")) + tk.MustQuery("select * from t;").Check(testkit.Rows("1 1 1")) tk.MustExec("update t set c=2 where a=1;") - result = tk.MustQuery("select * from t where b=1;") - result.Check(testkit.Rows("1 1 2")) + tk.MustQuery("select * from t where b=1;").Check(testkit.Rows("1 1 2")) } -func (s *testSuiteP1) TestJSON(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJSON(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test_json") @@ -1848,63 +804,35 @@ func (s *testSuiteP1) TestJSON(c *C) { tk.MustExec(`insert into test_json (id, a) values (5, '4.0')`) tk.MustExec(`insert into test_json (id, a) values (6, '"string"')`) - result := tk.MustQuery(`select tj.a from test_json tj order by tj.id`) - result.Check(testkit.Rows(`{"a": [1, "2", {"aa": "bb"}, 4], "b": true}`, "null", "", "true", "3", "4", `"string"`)) + tk.MustQuery(`select tj.a from test_json tj order by tj.id`).Check(testkit.Rows(`{"a": [1, "2", {"aa": "bb"}, 4], "b": true}`, "null", "", "true", "3", "4", `"string"`)) // Check json_type function - result = tk.MustQuery(`select json_type(a) from test_json tj order by tj.id`) - result.Check(testkit.Rows("OBJECT", "NULL", "", "BOOLEAN", "INTEGER", "DOUBLE", "STRING")) + tk.MustQuery(`select json_type(a) from test_json tj order by tj.id`).Check(testkit.Rows("OBJECT", "NULL", "", "BOOLEAN", "INTEGER", "DOUBLE", "STRING")) // Check json compare with primitives. - result = tk.MustQuery(`select a from test_json tj where a = 3`) - result.Check(testkit.Rows("3")) - result = tk.MustQuery(`select a from test_json tj where a = 4.0`) - result.Check(testkit.Rows("4")) - result = tk.MustQuery(`select a from test_json tj where a = true`) - result.Check(testkit.Rows("true")) - result = tk.MustQuery(`select a from test_json tj where a = "string"`) - result.Check(testkit.Rows(`"string"`)) + tk.MustQuery(`select a from test_json tj where a = 3`).Check(testkit.Rows("3")) + tk.MustQuery(`select a from test_json tj where a = 4.0`).Check(testkit.Rows("4")) + tk.MustQuery(`select a from test_json tj where a = true`).Check(testkit.Rows("true")) + tk.MustQuery(`select a from test_json tj where a = "string"`).Check(testkit.Rows(`"string"`)) // Check cast(true/false as JSON). - result = tk.MustQuery(`select cast(true as JSON)`) - result.Check(testkit.Rows(`true`)) - result = tk.MustQuery(`select cast(false as JSON)`) - result.Check(testkit.Rows(`false`)) + tk.MustQuery(`select cast(true as JSON)`).Check(testkit.Rows(`true`)) + tk.MustQuery(`select cast(false as JSON)`).Check(testkit.Rows(`false`)) // Check two json grammar sugar. - result = tk.MustQuery(`select a->>'$.a[2].aa' as x, a->'$.b' as y from test_json having x is not null order by id`) - result.Check(testkit.Rows(`bb true`)) - result = tk.MustQuery(`select a->'$.a[2].aa' as x, a->>'$.b' as y from test_json having x is not null order by id`) - result.Check(testkit.Rows(`"bb" true`)) + tk.MustQuery(`select a->>'$.a[2].aa' as x, a->'$.b' as y from test_json having x is not null order by id`).Check(testkit.Rows(`bb true`)) + tk.MustQuery(`select a->'$.a[2].aa' as x, a->>'$.b' as y from test_json having x is not null order by id`).Check(testkit.Rows(`"bb" true`)) // Check some DDL limits for TEXT/BLOB/JSON column. - var err error - var terr *terror.Error - - _, err = tk.Exec(`create table test_bad_json(a json default '{}')`) - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrBlobCantHaveDefault)) - - _, err = tk.Exec(`create table test_bad_json(a blob default 'hello')`) - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrBlobCantHaveDefault)) - - _, err = tk.Exec(`create table test_bad_json(a text default 'world')`) - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrBlobCantHaveDefault)) + tk.MustGetErrCode(`create table test_bad_json(a json default '{}')`, mysql.ErrBlobCantHaveDefault) + tk.MustGetErrCode(`create table test_bad_json(a blob default 'hello')`, mysql.ErrBlobCantHaveDefault) + tk.MustGetErrCode(`create table test_bad_json(a text default 'world')`, mysql.ErrBlobCantHaveDefault) // check json fields cannot be used as key. - _, err = tk.Exec(`create table test_bad_json(id int, a json, key (a))`) - c.Assert(err, NotNil) - terr = errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrJSONUsedAsKey)) + tk.MustGetErrCode(`create table test_bad_json(id int, a json, key (a))`, mysql.ErrJSONUsedAsKey) // check CAST AS JSON. - result = tk.MustQuery(`select CAST('3' AS JSON), CAST('{}' AS JSON), CAST(null AS JSON)`) - result.Check(testkit.Rows(`3 {} `)) + tk.MustQuery(`select CAST('3' AS JSON), CAST('{}' AS JSON), CAST(null AS JSON)`).Check(testkit.Rows(`3 {} `)) tk.MustQuery("select a, count(1) from test_json group by a order by a").Check(testkit.Rows( " 1", @@ -1933,40 +861,38 @@ func (s *testSuiteP1) TestJSON(c *C) { // "1234567890123456789012345678901234567890123456789012345.12")) } -func (s *testSuiteP1) TestMultiUpdate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`CREATE TABLE test_mu (a int primary key, b int, c int)`) tk.MustExec(`INSERT INTO test_mu VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9)`) // Test INSERT ... ON DUPLICATE UPDATE set_lists. tk.MustExec(`INSERT INTO test_mu VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE b = 3, c = b`) - result := tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`) - result.Check(testkit.Rows(`1 3 3`, `4 5 6`, `7 8 9`)) + tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`).Check(testkit.Rows(`1 3 3`, `4 5 6`, `7 8 9`)) tk.MustExec(`INSERT INTO test_mu VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = 2, b = c+5`) - result = tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`) - result.Check(testkit.Rows(`1 7 2`, `4 5 6`, `7 8 9`)) + tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`).Check(testkit.Rows(`1 7 2`, `4 5 6`, `7 8 9`)) // Test UPDATE ... set_lists. tk.MustExec(`UPDATE test_mu SET b = 0, c = b WHERE a = 4`) - result = tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`) - result.Check(testkit.Rows(`1 7 2`, `4 0 5`, `7 8 9`)) + tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`).Check(testkit.Rows(`1 7 2`, `4 0 5`, `7 8 9`)) tk.MustExec(`UPDATE test_mu SET c = 8, b = c WHERE a = 4`) - result = tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`) - result.Check(testkit.Rows(`1 7 2`, `4 5 8`, `7 8 9`)) + tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`).Check(testkit.Rows(`1 7 2`, `4 5 8`, `7 8 9`)) tk.MustExec(`UPDATE test_mu SET c = b, b = c WHERE a = 7`) - result = tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`) - result.Check(testkit.Rows(`1 7 2`, `4 5 8`, `7 9 8`)) + tk.MustQuery(`SELECT * FROM test_mu ORDER BY a`).Check(testkit.Rows(`1 7 2`, `4 5 8`, `7 9 8`)) } -func (s *testSuiteP1) TestGeneratedColumnWrite(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGeneratedColumnWrite(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - _, err := tk.Exec(`CREATE TABLE test_gc_write (a int primary key auto_increment, b int, c int as (a+8) virtual)`) - c.Assert(err.Error(), Equals, ddl.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("c").Error()) + tk.MustGetErrMsg(`CREATE TABLE test_gc_write (a int primary key auto_increment, b int, c int as (a+8) virtual)`, dbterror.ErrGeneratedColumnRefAutoInc.GenWithStackByArgs("c").Error()) tk.MustExec(`CREATE TABLE test_gc_write (a int primary key auto_increment, b int, c int as (b+8) virtual)`) tk.MustExec(`CREATE TABLE test_gc_write_1 (a int primary key, b int, c int)`) @@ -2003,88 +929,71 @@ func (s *testSuiteP1) TestGeneratedColumnWrite(c *C) { {`insert into test_gc_write (b, c) select a, b from test_gc_write`, mysql.ErrBadGeneratedColumn}, } for _, tt := range tests { - _, err := tk.Exec(tt.stmt) if tt.err != 0 { - c.Assert(err, NotNil, Commentf("sql is `%v`", tt.stmt)) - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(tt.err), Commentf("sql is %v", tt.stmt)) + tk.MustGetErrCode(tt.stmt, tt.err) } else { - c.Assert(err, IsNil) + tk.MustExec(tt.stmt) } } } // TestGeneratedColumnRead tests select generated columns from table. // They should be calculated from their generation expressions. -func (s *testSuiteP1) TestGeneratedColumnRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGeneratedColumnRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`CREATE TABLE test_gc_read(a int primary key, b int, c int as (a+b), d int as (a*b) stored, e int as (c*2))`) - result := tk.MustQuery(`SELECT generation_expression FROM information_schema.columns WHERE table_name = 'test_gc_read' AND column_name = 'd'`) - result.Check(testkit.Rows("`a` * `b`")) + tk.MustQuery(`SELECT generation_expression FROM information_schema.columns WHERE table_name = 'test_gc_read' AND column_name = 'd'`).Check(testkit.Rows("`a` * `b`")) // Insert only column a and b, leave c and d be calculated from them. tk.MustExec(`INSERT INTO test_gc_read (a, b) VALUES (0,null),(1,2),(3,4)`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`)) tk.MustExec(`INSERT INTO test_gc_read SET a = 5, b = 10`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 10 15 50 30`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 10 15 50 30`)) tk.MustExec(`REPLACE INTO test_gc_read (a, b) VALUES (5, 6)`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 6 11 30 22`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 6 11 30 22`)) tk.MustExec(`INSERT INTO test_gc_read (a, b) VALUES (5, 8) ON DUPLICATE KEY UPDATE b = 9`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 9 14 45 28`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `5 9 14 45 28`)) // Test select only-generated-column-without-dependences. - result = tk.MustQuery(`SELECT c, d FROM test_gc_read`) - result.Check(testkit.Rows(` `, `3 2`, `7 12`, `14 45`)) + tk.MustQuery(`SELECT c, d FROM test_gc_read`).Check(testkit.Rows(` `, `3 2`, `7 12`, `14 45`)) // Test select only virtual generated column that refers to other virtual generated columns. - result = tk.MustQuery(`SELECT e FROM test_gc_read`) - result.Check(testkit.Rows(``, `6`, `14`, `28`)) + tk.MustQuery(`SELECT e FROM test_gc_read`).Check(testkit.Rows(``, `6`, `14`, `28`)) // Test order of on duplicate key update list. tk.MustExec(`INSERT INTO test_gc_read (a, b) VALUES (5, 8) ON DUPLICATE KEY UPDATE a = 6, b = a`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `6 6 12 36 24`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `6 6 12 36 24`)) tk.MustExec(`INSERT INTO test_gc_read (a, b) VALUES (6, 8) ON DUPLICATE KEY UPDATE b = 8, a = b`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) // Test where-conditions on virtual/stored generated columns. - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 7`) - result.Check(testkit.Rows(`3 4 7 12 14`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 7`).Check(testkit.Rows(`3 4 7 12 14`)) - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE d = 64`) - result.Check(testkit.Rows(`8 8 16 64 32`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE d = 64`).Check(testkit.Rows(`8 8 16 64 32`)) - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE e = 6`) - result.Check(testkit.Rows(`1 2 3 2 6`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE e = 6`).Check(testkit.Rows(`1 2 3 2 6`)) // Test update where-conditions on virtual/generated columns. tk.MustExec(`UPDATE test_gc_read SET a = a + 100 WHERE c = 7`) - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 107`) - result.Check(testkit.Rows(`103 4 107 412 214`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 107`).Check(testkit.Rows(`103 4 107 412 214`)) // Test update where-conditions on virtual/generated columns. tk.MustExec(`UPDATE test_gc_read m SET m.a = m.a + 100 WHERE c = 107`) - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 207`) - result.Check(testkit.Rows(`203 4 207 812 414`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE c = 207`).Check(testkit.Rows(`203 4 207 812 414`)) tk.MustExec(`UPDATE test_gc_read SET a = a - 200 WHERE d = 812`) - result = tk.MustQuery(`SELECT * FROM test_gc_read WHERE d = 12`) - result.Check(testkit.Rows(`3 4 7 12 14`)) + tk.MustQuery(`SELECT * FROM test_gc_read WHERE d = 12`).Check(testkit.Rows(`3 4 7 12 14`)) tk.MustExec(`INSERT INTO test_gc_read set a = 4, b = d + 1`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 2 3 2 6`, `3 4 7 12 14`, `4 `, `8 8 16 64 32`)) tk.MustExec(`DELETE FROM test_gc_read where a = 4`) @@ -2092,75 +1001,58 @@ func (s *testSuiteP1) TestGeneratedColumnRead(c *C) { tk.MustExec(`CREATE TABLE test_gc_help(a int primary key, b int, c int, d int, e int)`) tk.MustExec(`INSERT INTO test_gc_help(a, b, c, d, e) SELECT * FROM test_gc_read`) - result = tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.c = t2.c ORDER BY t1.a`) - result.Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) + tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.c = t2.c ORDER BY t1.a`).Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) - result = tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.d = t2.d ORDER BY t1.a`) - result.Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) + tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.d = t2.d ORDER BY t1.a`).Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) - result = tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.e = t2.e ORDER BY t1.a`) - result.Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) + tk.MustQuery(`SELECT t1.* FROM test_gc_read t1 JOIN test_gc_help t2 ON t1.e = t2.e ORDER BY t1.a`).Check(testkit.Rows(`1 2 3 2 6`, `3 4 7 12 14`, `8 8 16 64 32`)) // Test generated column in subqueries. - result = tk.MustQuery(`SELECT * FROM test_gc_read t WHERE t.a not in (SELECT t.a FROM test_gc_read t where t.c > 5)`) - result.Sort().Check(testkit.Rows(`0 `, `1 2 3 2 6`)) - - result = tk.MustQuery(`SELECT * FROM test_gc_read t WHERE t.c in (SELECT t.c FROM test_gc_read t where t.c > 5)`) - result.Sort().Check(testkit.Rows(`3 4 7 12 14`, `8 8 16 64 32`)) + tk.MustQuery(`SELECT * FROM test_gc_read t WHERE t.a not in (SELECT t.a FROM test_gc_read t where t.c > 5)`).Sort().Check(testkit.Rows(`0 `, `1 2 3 2 6`)) + tk.MustQuery(`SELECT * FROM test_gc_read t WHERE t.c in (SELECT t.c FROM test_gc_read t where t.c > 5)`).Sort().Check(testkit.Rows(`3 4 7 12 14`, `8 8 16 64 32`)) - result = tk.MustQuery(`SELECT tt.b FROM test_gc_read tt WHERE tt.a = (SELECT max(t.a) FROM test_gc_read t WHERE t.c = tt.c) ORDER BY b`) - result.Check(testkit.Rows(`2`, `4`, `8`)) + tk.MustQuery(`SELECT tt.b FROM test_gc_read tt WHERE tt.a = (SELECT max(t.a) FROM test_gc_read t WHERE t.c = tt.c) ORDER BY b`).Check(testkit.Rows(`2`, `4`, `8`)) // Test aggregation on virtual/stored generated columns. - result = tk.MustQuery(`SELECT c, sum(a) aa, max(d) dd, sum(e) ee FROM test_gc_read GROUP BY c ORDER BY aa`) - result.Check(testkit.Rows(` 0 `, `3 1 2 6`, `7 3 12 14`, `16 8 64 32`)) + tk.MustQuery(`SELECT c, sum(a) aa, max(d) dd, sum(e) ee FROM test_gc_read GROUP BY c ORDER BY aa`).Check(testkit.Rows(` 0 `, `3 1 2 6`, `7 3 12 14`, `16 8 64 32`)) - result = tk.MustQuery(`SELECT a, sum(c), sum(d), sum(e) FROM test_gc_read GROUP BY a ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 3 2 6`, `3 7 12 14`, `8 16 64 32`)) + tk.MustQuery(`SELECT a, sum(c), sum(d), sum(e) FROM test_gc_read GROUP BY a ORDER BY a`).Check(testkit.Rows(`0 `, `1 3 2 6`, `3 7 12 14`, `8 16 64 32`)) // Test multi-update on generated columns. tk.MustExec(`UPDATE test_gc_read m, test_gc_read n SET m.b = m.b + 10, n.b = n.b + 10`) - result = tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`) - result.Check(testkit.Rows(`0 `, `1 12 13 12 26`, `3 14 17 42 34`, `8 18 26 144 52`)) + tk.MustQuery(`SELECT * FROM test_gc_read ORDER BY a`).Check(testkit.Rows(`0 `, `1 12 13 12 26`, `3 14 17 42 34`, `8 18 26 144 52`)) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") tk.MustExec("insert into t values(8)") tk.MustExec("update test_gc_read set a = a+1 where a in (select a from t)") - result = tk.MustQuery("select * from test_gc_read order by a") - result.Check(testkit.Rows(`0 `, `1 12 13 12 26`, `3 14 17 42 34`, `9 18 27 162 54`)) + tk.MustQuery("select * from test_gc_read order by a").Check(testkit.Rows(`0 `, `1 12 13 12 26`, `3 14 17 42 34`, `9 18 27 162 54`)) // Test different types between generation expression and generated column. tk.MustExec(`CREATE TABLE test_gc_read_cast(a VARCHAR(255), b VARCHAR(255), c INT AS (JSON_EXTRACT(a, b)), d INT AS (JSON_EXTRACT(a, b)) STORED)`) tk.MustExec(`INSERT INTO test_gc_read_cast (a, b) VALUES ('{"a": "3"}', '$.a')`) - result = tk.MustQuery(`SELECT c, d FROM test_gc_read_cast`) - result.Check(testkit.Rows(`3 3`)) + tk.MustQuery(`SELECT c, d FROM test_gc_read_cast`).Check(testkit.Rows(`3 3`)) tk.MustExec(`CREATE TABLE test_gc_read_cast_1(a VARCHAR(255), b VARCHAR(255), c ENUM("red", "yellow") AS (JSON_UNQUOTE(JSON_EXTRACT(a, b))))`) tk.MustExec(`INSERT INTO test_gc_read_cast_1 (a, b) VALUES ('{"a": "yellow"}', '$.a')`) - result = tk.MustQuery(`SELECT c FROM test_gc_read_cast_1`) - result.Check(testkit.Rows(`yellow`)) + tk.MustQuery(`SELECT c FROM test_gc_read_cast_1`).Check(testkit.Rows(`yellow`)) tk.MustExec(`CREATE TABLE test_gc_read_cast_2( a JSON, b JSON AS (a->>'$.a'))`) tk.MustExec(`INSERT INTO test_gc_read_cast_2(a) VALUES ('{"a": "{ \\\"key\\\": \\\"\\u6d4b\\\" }"}')`) - result = tk.MustQuery(`SELECT b FROM test_gc_read_cast_2`) - result.Check(testkit.Rows(`{"key": "测"}`)) + tk.MustQuery(`SELECT b FROM test_gc_read_cast_2`).Check(testkit.Rows(`{"key": "测"}`)) tk.MustExec(`CREATE TABLE test_gc_read_cast_3( a JSON, b JSON AS (a->>'$.a'), c INT AS (b * 3.14) )`) tk.MustExec(`INSERT INTO test_gc_read_cast_3(a) VALUES ('{"a": "5"}')`) - result = tk.MustQuery(`SELECT c FROM test_gc_read_cast_3`) - result.Check(testkit.Rows(`16`)) + tk.MustQuery(`SELECT c FROM test_gc_read_cast_3`).Check(testkit.Rows(`16`)) - _, err := tk.Exec(`INSERT INTO test_gc_read_cast_1 (a, b) VALUES ('{"a": "invalid"}', '$.a')`) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr(`INSERT INTO test_gc_read_cast_1 (a, b) VALUES ('{"a": "invalid"}', '$.a')`)) // Test read generated columns after drop some irrelevant column tk.MustExec(`DROP TABLE IF EXISTS test_gc_read_m`) tk.MustExec(`CREATE TABLE test_gc_read_m (a int primary key, b int, c int as (a+1), d int as (c*2))`) tk.MustExec(`INSERT INTO test_gc_read_m(a) values (1), (2)`) tk.MustExec(`ALTER TABLE test_gc_read_m DROP b`) - result = tk.MustQuery(`SELECT * FROM test_gc_read_m`) - result.Check(testkit.Rows(`1 2 4`, `2 3 6`)) + tk.MustQuery(`SELECT * FROM test_gc_read_m`).Check(testkit.Rows(`1 2 4`, `2 3 6`)) // Test not null generated columns. tk.MustExec(`CREATE TABLE test_gc_read_1(a int primary key, b int, c int as (a+b) not null, d int as (a*b) stored)`) @@ -2174,20 +1066,19 @@ func (s *testSuiteP1) TestGeneratedColumnRead(c *C) { {`insert into test_gc_read_2(a, b) values (1, null)`, mysql.ErrBadNull}, } for _, tt := range tests { - _, err := tk.Exec(tt.stmt) if tt.err != 0 { - c.Assert(err, NotNil) - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(tt.err)) + tk.MustGetErrCode(tt.stmt, tt.err) } else { - c.Assert(err, IsNil) + tk.MustExec(tt.stmt) } } } // TestGeneratedColumnRead tests generated columns using point get and batch point get -func (s *testSuiteP1) TestGeneratedColumnPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGeneratedColumnPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tu") tk.MustExec("CREATE TABLE tu(a int, b int, c int GENERATED ALWAYS AS (a + b) VIRTUAL, d int as (a * b) stored, " + @@ -2214,2138 +1105,57 @@ func (s *testSuiteP1) TestGeneratedColumnPointGet(c *C) { tk.MustExec("drop table if exists tu") } -func (s *testSuiteP2) TestToPBExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values (1.1, 1.1)") - tk.MustExec("insert t values (2.4, 2.4)") - tk.MustExec("insert t values (3.3, 2.7)") - result := tk.MustQuery("select * from t where a < 2.399999") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where a > 1.5") - result.Check(testkit.Rows("2.400000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where a <= 1.1") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where b >= 3") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where not (b = 1)") - result.Check(testkit.Rows("2.400000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where b&1 = a|1") - result.Check(testkit.Rows("1.100000 1")) - result = tk.MustQuery("select * from t where b != 2 and b <=> 3") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where b in (3)") - result.Check(testkit.Rows("3.300000 3")) - result = tk.MustQuery("select * from t where b not in (1, 2)") - result.Check(testkit.Rows("3.300000 3")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a varchar(255), b int)") - tk.MustExec("insert t values ('abc123', 1)") - tk.MustExec("insert t values ('ab123', 2)") - result = tk.MustQuery("select * from t where a like 'ab%'") - result.Check(testkit.Rows("abc123 1", "ab123 2")) - result = tk.MustQuery("select * from t where a like 'ab_12'") - result.Check(nil) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key)") - tk.MustExec("insert t values (1)") - tk.MustExec("insert t values (2)") - result = tk.MustQuery("select * from t where not (a = 1)") - result.Check(testkit.Rows("2")) - result = tk.MustQuery("select * from t where not(not (a = 1))") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select * from t where not(a != 1 and a != 2)") - result.Check(testkit.Rows("1", "2")) -} - -func (s *testSuiteP2) TestDatumXAPI(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a decimal(10,6), b decimal, index idx_b (b))") - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values (1.1, 1.1)") - tk.MustExec("insert t values (2.2, 2.2)") - tk.MustExec("insert t values (3.3, 2.7)") - result := tk.MustQuery("select * from t where a > 1.5") - result.Check(testkit.Rows("2.200000 2", "3.300000 3")) - result = tk.MustQuery("select * from t where b > 1.5") - result.Check(testkit.Rows("2.200000 2", "3.300000 3")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a time(3), b time, index idx_a (a))") - tk.MustExec("insert t values ('11:11:11', '11:11:11')") - tk.MustExec("insert t values ('11:11:12', '11:11:12')") - tk.MustExec("insert t values ('11:11:13', '11:11:13')") - result = tk.MustQuery("select * from t where a > '11:11:11.5'") - result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) - result = tk.MustQuery("select * from t where b > '11:11:11.5'") - result.Check(testkit.Rows("11:11:12.000 11:11:12", "11:11:13.000 11:11:13")) -} - -func (s *testSuiteP2) TestSQLMode(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a tinyint not null)") - tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") - _, err := tk.Exec("insert t values ()") - c.Check(err, NotNil) - - _, err = tk.Exec("insert t values ('1000')") - c.Check(err, NotNil) - - tk.MustExec("create table if not exists tdouble (a double(3,2))") - _, err = tk.Exec("insert tdouble values (10.23)") - c.Check(err, NotNil) - - tk.MustExec("set sql_mode = ''") - tk.MustExec("insert t values ()") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value")) - tk.MustExec("insert t values (null)") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert ignore t values (null)") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert t select null") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null")) - tk.MustExec("insert t values (1000)") - tk.MustQuery("select * from t order by a").Check(testkit.Rows("0", "0", "0", "0", "127")) - - tk.MustExec("insert tdouble values (10.23)") - tk.MustQuery("select * from tdouble").Check(testkit.Rows("9.99")) - - tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES'") - tk.MustExec("set @@global.sql_mode = ''") - - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - tk2.MustExec("drop table if exists t2") - tk2.MustExec("create table t2 (a varchar(3))") - tk2.MustExec("insert t2 values ('abcd')") - tk2.MustQuery("select * from t2").Check(testkit.Rows("abc")) - - // session1 is still in strict mode. - _, err = tk.Exec("insert t2 values ('abcd')") - c.Check(err, NotNil) - // Restore original global strict mode. - tk.MustExec("set @@global.sql_mode = 'STRICT_TRANS_TABLES'") -} - -func (s *testSuiteP2) TestTableDual(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - result := tk.MustQuery("Select 1") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select 1 from dual") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select count(*) from dual") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("Select 1 from dual where 1") - result.Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int primary key)") - tk.MustQuery("select t1.* from t t1, t t2 where t1.a=t2.a and 1=0").Check(testkit.Rows()) -} - -func (s *testSuiteP2) TestTableScan(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use information_schema") - result := tk.MustQuery("select * from schemata") - // There must be these tables: information_schema, mysql, performance_schema and test. - c.Assert(len(result.Rows()), GreaterEqual, 4) +func TestUnionAutoSignedCast(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("create database mytest") - rowStr1 := fmt.Sprintf("%s %s %s %s %v %v %v", "def", "mysql", "utf8mb4", "utf8mb4_bin", nil, nil, nil) - rowStr2 := fmt.Sprintf("%s %s %s %s %v %v %v", "def", "mytest", "utf8mb4", "utf8mb4_bin", nil, nil, nil) - tk.MustExec("use information_schema") - result = tk.MustQuery("select * from schemata where schema_name = 'mysql'") - result.Check(testkit.Rows(rowStr1)) - result = tk.MustQuery("select * from schemata where schema_name like 'my%'") - result.Check(testkit.Rows(rowStr1, rowStr2)) - result = tk.MustQuery("select 1 from tables limit 1") - result.Check(testkit.Rows("1")) -} - -func (s *testSuiteP2) TestAdapterStatement(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) - se.GetSessionVars().TxnCtx.InfoSchema = domain.GetDomain(se).InfoSchema() - compiler := &executor.Compiler{Ctx: se} - stmtNode, err := s.ParseOneStmt("select 1", "", "") - c.Check(err, IsNil) - stmt, err := compiler.Compile(context.TODO(), stmtNode) - c.Check(err, IsNil) - c.Check(stmt.OriginText(), Equals, "select 1") - - stmtNode, err = s.ParseOneStmt("create table test.t (a int)", "", "") - c.Check(err, IsNil) - stmt, err = compiler.Compile(context.TODO(), stmtNode) - c.Check(err, IsNil) - c.Check(stmt.OriginText(), Equals, "create table test.t (a int)") -} - -func (s *testSuiteP2) TestIsPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use mysql") - ctx := tk.Se.(sessionctx.Context) - tests := map[string]bool{ - "select * from help_topic where name='aaa'": false, - "select 1 from help_topic where name='aaa'": false, - "select * from help_topic where help_topic_id=1": true, - "select * from help_topic where help_category_id=1": false, - } - - for sqlStr, result := range tests { - stmtNode, err := s.ParseOneStmt(sqlStr, "", "") - c.Check(err, IsNil) - preprocessorReturn := &plannercore.PreprocessorReturn{} - err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) - c.Check(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) - c.Check(err, IsNil) - ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) - c.Assert(err, IsNil) - c.Assert(ret, Equals, result) - } -} - -func (s *testSuiteP2) TestClusteredIndexIsPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_cluster_index_is_point_get;") - tk.MustExec("create database test_cluster_index_is_point_get;") - tk.MustExec("use test_cluster_index_is_point_get;") - - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a varchar(255), b int, c char(10), primary key (c, a));") - ctx := tk.Se.(sessionctx.Context) - - tests := map[string]bool{ - "select 1 from t where a='x'": false, - "select * from t where c='x'": false, - "select * from t where a='x' and c='x'": true, - "select * from t where a='x' and c='x' and b=1": false, - } - for sqlStr, result := range tests { - stmtNode, err := s.ParseOneStmt(sqlStr, "", "") - c.Check(err, IsNil) - preprocessorReturn := &plannercore.PreprocessorReturn{} - err = plannercore.Preprocess(ctx, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) - c.Check(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), ctx, stmtNode, preprocessorReturn.InfoSchema) - c.Check(err, IsNil) - ret, err := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx, p) - c.Assert(err, IsNil) - c.Assert(ret, Equals, result) - } -} - -func (s *testSerialSuite) TestPointGetRepeatableRead(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - tk1.MustExec(`create table point_get (a int, b int, c int, - primary key k_a(a), - unique key k_b(b))`) - tk1.MustExec("insert into point_get values (1, 1, 1)") - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - var ( - step1 = "github.com/pingcap/tidb/executor/pointGetRepeatableReadTest-step1" - step2 = "github.com/pingcap/tidb/executor/pointGetRepeatableReadTest-step2" - ) - - c.Assert(failpoint.Enable(step1, "return"), IsNil) - c.Assert(failpoint.Enable(step2, "pause"), IsNil) - - updateWaitCh := make(chan struct{}) - go func() { - ctx := context.WithValue(context.Background(), "pointGetRepeatableReadTest", updateWaitCh) - ctx = failpoint.WithHook(ctx, func(ctx context.Context, fpname string) bool { - return fpname == step1 || fpname == step2 - }) - rs, err := tk1.Se.Execute(ctx, "select c from point_get where b = 1") - c.Assert(err, IsNil) - result := tk1.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute sql fail")) - result.Check(testkit.Rows("1")) - }() - - <-updateWaitCh // Wait `POINT GET` first time `get` - c.Assert(failpoint.Disable(step1), IsNil) - tk2.MustExec("update point_get set b = 2, c = 2 where a = 1") - c.Assert(failpoint.Disable(step2), IsNil) -} - -func (s *testSerialSuite) TestBatchPointGetRepeatableRead(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - tk1.MustExec(`create table batch_point_get (a int, b int, c int, unique key k_b(a, b, c))`) - tk1.MustExec("insert into batch_point_get values (1, 1, 1), (2, 3, 4), (3, 4, 5)") - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - var ( - step1 = "github.com/pingcap/tidb/executor/batchPointGetRepeatableReadTest-step1" - step2 = "github.com/pingcap/tidb/executor/batchPointGetRepeatableReadTest-step2" - ) - - c.Assert(failpoint.Enable(step1, "return"), IsNil) - c.Assert(failpoint.Enable(step2, "pause"), IsNil) + tk.MustExec("drop table if exists t1,t2") + tk.MustExec("create table t1 (id int, i int, b bigint, d double, dd decimal)") + tk.MustExec("create table t2 (id int, i int unsigned, b bigint unsigned, d double unsigned, dd decimal unsigned)") + tk.MustExec("insert into t1 values(1, -1, -1, -1.1, -1)") + tk.MustExec("insert into t2 values(2, 1, 1, 1.1, 1)") + tk.MustQuery("select * from t1 union select * from t2 order by id"). + Check(testkit.Rows("1 -1 -1 -1.1 -1", "2 1 1 1.1 1")) + tk.MustQuery("select id, i, b, d, dd from t2 union select id, i, b, d, dd from t1 order by id"). + Check(testkit.Rows("1 -1 -1 -1.1 -1", "2 1 1 1.1 1")) + tk.MustQuery("select id, i from t2 union select id, cast(i as unsigned int) from t1 order by id"). + Check(testkit.Rows("1 18446744073709551615", "2 1")) + tk.MustQuery("select dd from t2 union all select dd from t2"). + Check(testkit.Rows("1", "1")) - updateWaitCh := make(chan struct{}) - go func() { - ctx := context.WithValue(context.Background(), "batchPointGetRepeatableReadTest", updateWaitCh) - ctx = failpoint.WithHook(ctx, func(ctx context.Context, fpname string) bool { - return fpname == step1 || fpname == step2 - }) - rs, err := tk1.Se.Execute(ctx, "select c from batch_point_get where (a, b, c) in ((1, 1, 1))") - c.Assert(err, IsNil) - result := tk1.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute sql fail")) - result.Check(testkit.Rows("1")) - }() - - <-updateWaitCh // Wait `POINT GET` first time `get` - c.Assert(failpoint.Disable(step1), IsNil) - tk2.MustExec("update batch_point_get set b = 2, c = 2 where a = 1") - c.Assert(failpoint.Disable(step2), IsNil) -} + tk.MustExec("drop table if exists t3,t4") + tk.MustExec("create table t3 (id int, v int)") + tk.MustExec("create table t4 (id int, v double unsigned)") + tk.MustExec("insert into t3 values (1, -1)") + tk.MustExec("insert into t4 values (2, 1)") + tk.MustQuery("select id, v from t3 union select id, v from t4 order by id"). + Check(testkit.Rows("1 -1", "2 1")) + tk.MustQuery("select id, v from t4 union select id, v from t3 order by id"). + Check(testkit.Rows("1 -1", "2 1")) -func (s *testSerialSuite) TestSplitRegionTimeout(c *C) { - c.Assert(failpoint.Enable("tikvclient/mockSplitRegionTimeout", `return(true)`), IsNil) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a varchar(100),b int, index idx1(b,a))") - tk.MustExec(`split table t index idx1 by (10000,"abcd"),(10000000);`) - tk.MustExec(`set @@tidb_wait_split_region_timeout=1`) - // result 0 0 means split 0 region and 0 region finish scatter regions before timeout. - tk.MustQuery(`split table t between (0) and (10000) regions 10`).Check(testkit.Rows("0 0")) - err := failpoint.Disable("tikvclient/mockSplitRegionTimeout") - c.Assert(err, IsNil) - - // Test scatter regions timeout. - c.Assert(failpoint.Enable("tikvclient/mockScatterRegionTimeout", `return(true)`), IsNil) - tk.MustQuery(`split table t between (0) and (10000) regions 10`).Check(testkit.Rows("10 1")) - err = failpoint.Disable("tikvclient/mockScatterRegionTimeout") - c.Assert(err, IsNil) - - // Test pre-split with timeout. - tk.MustExec("drop table if exists t") - tk.MustExec("set @@global.tidb_scatter_region=1;") - c.Assert(failpoint.Enable("tikvclient/mockScatterRegionTimeout", `return(true)`), IsNil) - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - start := time.Now() - tk.MustExec("create table t (a int, b int) partition by hash(a) partitions 5;") - c.Assert(time.Since(start).Seconds(), Less, 10.0) - err = failpoint.Disable("tikvclient/mockScatterRegionTimeout") - c.Assert(err, IsNil) + tk.MustExec("drop table if exists t5,t6,t7") + tk.MustExec("create table t5 (id int, v bigint unsigned)") + tk.MustExec("create table t6 (id int, v decimal)") + tk.MustExec("create table t7 (id int, v bigint)") + tk.MustExec("insert into t5 values (1, 1)") + tk.MustExec("insert into t6 values (2, -1)") + tk.MustExec("insert into t7 values (3, -1)") + tk.MustQuery("select id, v from t5 union select id, v from t6 order by id"). + Check(testkit.Rows("1 1", "2 -1")) + tk.MustQuery("select id, v from t5 union select id, v from t7 union select id, v from t6 order by id"). + Check(testkit.Rows("1 1", "2 -1", "3 -1")) } -func (s *testSuiteP2) TestRow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateClustered(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c int, d int)") - tk.MustExec("insert t values (1, 1)") - tk.MustExec("insert t values (1, 3)") - tk.MustExec("insert t values (2, 1)") - tk.MustExec("insert t values (2, 3)") - result := tk.MustQuery("select * from t where (c, d) < (2,2)") - result.Check(testkit.Rows("1 1", "1 3", "2 1")) - result = tk.MustQuery("select * from t where (1,2,3) > (3,2,1)") - result.Check(testkit.Rows()) - result = tk.MustQuery("select * from t where row(1,2,3) > (3,2,1)") - result.Check(testkit.Rows()) - result = tk.MustQuery("select * from t where (c, d) = (select * from t where (c,d) = (1,1))") - result.Check(testkit.Rows("1 1")) - result = tk.MustQuery("select * from t where (c, d) = (select * from t k where (t.c,t.d) = (c,d))") - result.Check(testkit.Rows("1 1", "1 3", "2 1", "2 3")) - result = tk.MustQuery("select (1, 2, 3) < (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 3)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) <= (2, 1, 4)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (2, 3, 4) >= (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) = (2, 3, 4)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select (2, 3, 4) != (2, 3, 4)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select row(1, 1) in (row(1, 1))") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 0) in (row(1, 1))") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select row(1, 1) in (select 1, 1)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 1) > row(1, 0)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select row(1, 1) > (select 1, 0)") - result.Check(testkit.Rows("1")) - result = tk.MustQuery("select 1 > (select 1)") - result.Check(testkit.Rows("0")) - result = tk.MustQuery("select (select 1)") - result.Check(testkit.Rows("1")) - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int)") - tk.MustExec("insert t1 values (1,2),(1,null)") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2 (c int, d int)") - tk.MustExec("insert t2 values (0,0)") - - tk.MustQuery("select * from t2 where (1,2) in (select * from t1)").Check(testkit.Rows("0 0")) - tk.MustQuery("select * from t2 where (1,2) not in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (1,1) not in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (1,null) in (select * from t1)").Check(testkit.Rows()) - tk.MustQuery("select * from t2 where (null,null) in (select * from t1)").Check(testkit.Rows()) - - tk.MustExec("delete from t1 where a=1 and b=2") - tk.MustQuery("select (1,1) in (select * from t2) from t1").Check(testkit.Rows("0")) - tk.MustQuery("select (1,1) not in (select * from t2) from t1").Check(testkit.Rows("1")) - tk.MustQuery("select (1,1) in (select 1,1 from t2) from t1").Check(testkit.Rows("1")) - tk.MustQuery("select (1,1) not in (select 1,1 from t2) from t1").Check(testkit.Rows("0")) - - // MySQL 5.7 returns 1 for these 2 queries, which is wrong. - tk.MustQuery("select (1,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) - tk.MustQuery("select (t1.a,null) not in (select 1,1 from t2) from t1").Check(testkit.Rows("")) - - tk.MustQuery("select (1,null) in (select * from t1)").Check(testkit.Rows("")) - tk.MustQuery("select (1,null) not in (select * from t1)").Check(testkit.Rows("")) -} - -func (s *testSuiteP2) TestColumnName(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c int, d int)") - // disable only full group by - tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") - rs, err := tk.Exec("select 1 + c, count(*) from t") - c.Check(err, IsNil) - fields := rs.Fields() - c.Check(len(fields), Equals, 2) - c.Check(fields[0].Column.Name.L, Equals, "1 + c") - c.Check(fields[0].ColumnAsName.L, Equals, "1 + c") - c.Check(fields[1].Column.Name.L, Equals, "count(*)") - c.Check(fields[1].ColumnAsName.L, Equals, "count(*)") - c.Assert(rs.Close(), IsNil) - rs, err = tk.Exec("select (c) > all (select c from t) from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(len(fields), Equals, 1) - c.Check(fields[0].Column.Name.L, Equals, "(c) > all (select c from t)") - c.Check(fields[0].ColumnAsName.L, Equals, "(c) > all (select c from t)") - c.Assert(rs.Close(), IsNil) - tk.MustExec("begin") - tk.MustExec("insert t values(1,1)") - rs, err = tk.Exec("select c d, d c from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(len(fields), Equals, 2) - c.Check(fields[0].Column.Name.L, Equals, "c") - c.Check(fields[0].ColumnAsName.L, Equals, "d") - c.Check(fields[1].Column.Name.L, Equals, "d") - c.Check(fields[1].ColumnAsName.L, Equals, "c") - c.Assert(rs.Close(), IsNil) - // Test case for query a column of a table. - // In this case, all attributes have values. - rs, err = tk.Exec("select c as a from t as t2") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(fields[0].Column.Name.L, Equals, "c") - c.Check(fields[0].ColumnAsName.L, Equals, "a") - c.Check(fields[0].Table.Name.L, Equals, "t") - c.Check(fields[0].TableAsName.L, Equals, "t2") - c.Check(fields[0].DBName.L, Equals, "test") - c.Assert(rs.Close(), IsNil) - // Test case for query a expression which only using constant inputs. - // In this case, the table, org_table and database attributes will all be empty. - rs, err = tk.Exec("select hour(1) as a from t as t2") - c.Check(err, IsNil) - fields = rs.Fields() - c.Check(fields[0].Column.Name.L, Equals, "a") - c.Check(fields[0].ColumnAsName.L, Equals, "a") - c.Check(fields[0].Table.Name.L, Equals, "") - c.Check(fields[0].TableAsName.L, Equals, "") - c.Check(fields[0].DBName.L, Equals, "") - c.Assert(rs.Close(), IsNil) - // Test case for query a column wrapped with parentheses and unary plus. - // In this case, the column name should be its original name. - rs, err = tk.Exec("select (c), (+c), +(c), +(+(c)), ++c from t") - c.Check(err, IsNil) - fields = rs.Fields() - for i := 0; i < 5; i++ { - c.Check(fields[i].Column.Name.L, Equals, "c") - c.Check(fields[i].ColumnAsName.L, Equals, "c") - } - c.Assert(rs.Close(), IsNil) - - // Test issue https://github.com/pingcap/tidb/issues/9639 . - // Both window function and expression appear in final result field. - tk.MustExec("set @@tidb_enable_window_function = 1") - rs, err = tk.Exec("select 1+1, row_number() over() num from t") - c.Check(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].Column.Name.L, Equals, "1+1") - c.Assert(fields[0].ColumnAsName.L, Equals, "1+1") - c.Assert(fields[1].Column.Name.L, Equals, "num") - c.Assert(fields[1].ColumnAsName.L, Equals, "num") - tk.MustExec("set @@tidb_enable_window_function = 0") - c.Assert(rs.Close(), IsNil) - - rs, err = tk.Exec("select if(1,c,c) from t;") - c.Check(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].Column.Name.L, Equals, "if(1,c,c)") - // It's a compatibility issue. Should be empty instead. - c.Assert(fields[0].ColumnAsName.L, Equals, "if(1,c,c)") - c.Assert(rs.Close(), IsNil) -} - -func (s *testSuiteP2) TestSelectVar(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (d int)") - tk.MustExec("insert into t values(1), (2), (1)") - // This behavior is different from MySQL. - result := tk.MustQuery("select @a, @a := d+1 from t") - result.Check(testkit.Rows(" 2", "2 3", "3 2")) - // Test for PR #10658. - tk.MustExec("select SQL_BIG_RESULT d from t group by d") - tk.MustExec("select SQL_SMALL_RESULT d from t group by d") - tk.MustExec("select SQL_BUFFER_RESULT d from t group by d") -} - -func (s *testSuiteP2) TestHistoryRead(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists history_read") - tk.MustExec("create table history_read (a int)") - tk.MustExec("insert history_read values (1)") - - // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. - safePointName := "tikv_gc_safe_point" - safePointValue := "20060102-15:04:05 -0700" - safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" - updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') - ON DUPLICATE KEY - UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) - tk.MustExec(updateSafePoint) - - // Set snapshot to a time before save point will fail. - _, err := tk.Exec("set @@tidb_snapshot = '2006-01-01 15:04:05.999999'") - c.Assert(terror.ErrorEqual(err, variable.ErrSnapshotTooOld), IsTrue, Commentf("err %v", err)) - // SnapshotTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - - // Setting snapshot to a time in the future will fail. (One day before the 2038 problem) - _, err = tk.Exec("set @@tidb_snapshot = '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") - // SnapshotTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - - curVer1, _ := s.store.CurrentVersion(kv.GlobalTxnScope) - time.Sleep(time.Millisecond) - snapshotTime := time.Now() - time.Sleep(time.Millisecond) - curVer2, _ := s.store.CurrentVersion(kv.GlobalTxnScope) - tk.MustExec("insert history_read values (2)") - tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) - tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") - ctx := tk.Se.(sessionctx.Context) - snapshotTS := ctx.GetSessionVars().SnapshotTS - c.Assert(snapshotTS, Greater, curVer1.Ver) - c.Assert(snapshotTS, Less, curVer2.Ver) - tk.MustQuery("select * from history_read").Check(testkit.Rows("1")) - _, err = tk.Exec("insert history_read values (2)") - c.Assert(err, NotNil) - _, err = tk.Exec("update history_read set a = 3 where a = 1") - c.Assert(err, NotNil) - _, err = tk.Exec("delete from history_read where a = 1") - c.Assert(err, NotNil) - tk.MustExec("set @@tidb_snapshot = ''") - tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2")) - tk.MustExec("insert history_read values (3)") - tk.MustExec("update history_read set a = 4 where a = 3") - tk.MustExec("delete from history_read where a = 1") - - time.Sleep(time.Millisecond) - snapshotTime = time.Now() - time.Sleep(time.Millisecond) - tk.MustExec("alter table history_read add column b int") - tk.MustExec("insert history_read values (8, 8), (9, 9)") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) - tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) - tsoStr := strconv.FormatUint(oracle.GoTimeToTS(snapshotTime), 10) - - tk.MustExec("set @@tidb_snapshot = '" + tsoStr + "'") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4")) - - tk.MustExec("set @@tidb_snapshot = ''") - tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 ", "4 ", "8 8", "9 9")) -} - -func (s *testSuite2) TestLowResolutionTSORead(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@autocommit=1") - tk.MustExec("use test") - tk.MustExec("drop table if exists low_resolution_tso") - tk.MustExec("create table low_resolution_tso(a int)") - tk.MustExec("insert low_resolution_tso values (1)") - - // enable low resolution tso - c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsFalse) - _, err := tk.Exec("set @@tidb_low_resolution_tso = 'on'") - c.Assert(err, IsNil) - c.Assert(tk.Se.GetSessionVars().LowResolutionTSO, IsTrue) - - time.Sleep(3 * time.Second) - tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("1")) - _, err = tk.Exec("update low_resolution_tso set a = 2") - c.Assert(err, NotNil) - tk.MustExec("set @@tidb_low_resolution_tso = 'off'") - tk.MustExec("update low_resolution_tso set a = 2") - tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("2")) -} - -func (s *testSuite2) TestStaleReadFutureTime(c *C) { - tk := testkit.NewTestKit(c, s.store) - // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) - _, err := tk.Exec("set @@tx_read_ts = '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") - // TxnReadTS Is not updated if check failed. - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) -} - -func (s *testSuite) TestScanControlSelection(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int primary key, b int, c int, index idx_b(b))") - tk.MustExec("insert into t values (1, 1, 1), (2, 1, 1), (3, 1, 2), (4, 2, 3)") - tk.MustQuery("select (select count(1) k from t s where s.b = t1.c) from t t1").Sort().Check(testkit.Rows("0", "1", "3", "3")) -} - -func (s *testSuite) TestSimpleDAG(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int primary key, b int, c int)") - tk.MustExec("insert into t values (1, 1, 1), (2, 1, 1), (3, 1, 2), (4, 2, 3)") - tk.MustQuery("select a from t").Check(testkit.Rows("1", "2", "3", "4")) - tk.MustQuery("select * from t where a = 4").Check(testkit.Rows("4 2 3")) - tk.MustQuery("select a from t limit 1").Check(testkit.Rows("1")) - tk.MustQuery("select a from t order by a desc").Check(testkit.Rows("4", "3", "2", "1")) - tk.MustQuery("select a from t order by a desc limit 1").Check(testkit.Rows("4")) - tk.MustQuery("select a from t order by b desc limit 1").Check(testkit.Rows("4")) - tk.MustQuery("select a from t where a < 3").Check(testkit.Rows("1", "2")) - tk.MustQuery("select a from t where b > 1").Check(testkit.Rows("4")) - tk.MustQuery("select a from t where b > 1 and a < 3").Check(testkit.Rows()) - tk.MustQuery("select count(*) from t where b > 1 and a < 3").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from t").Check(testkit.Rows("4")) - tk.MustQuery("select count(*), c from t group by c order by c").Check(testkit.Rows("2 1", "1 2", "1 3")) - tk.MustQuery("select sum(c) as s from t group by b order by s").Check(testkit.Rows("3", "4")) - tk.MustQuery("select avg(a) as s from t group by b order by s").Check(testkit.Rows("2.0000", "4.0000")) - tk.MustQuery("select sum(distinct c) from t group by b").Check(testkit.Rows("3", "3")) - - tk.MustExec("create index i on t(c,b)") - tk.MustQuery("select a from t where c = 1").Check(testkit.Rows("1", "2")) - tk.MustQuery("select a from t where c = 1 and a < 2").Check(testkit.Rows("1")) - tk.MustQuery("select a from t where c = 1 order by a limit 1").Check(testkit.Rows("1")) - tk.MustQuery("select count(*) from t where c = 1 ").Check(testkit.Rows("2")) - tk.MustExec("create index i1 on t(b)") - tk.MustQuery("select c from t where b = 2").Check(testkit.Rows("3")) - tk.MustQuery("select * from t where b = 2").Check(testkit.Rows("4 2 3")) - tk.MustQuery("select count(*) from t where b = 1").Check(testkit.Rows("3")) - tk.MustQuery("select * from t where b = 1 and a > 1 limit 1").Check(testkit.Rows("2 1 1")) - - // Test time push down. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (id int, c1 datetime);") - tk.MustExec("insert into t values (1, '2015-06-07 12:12:12')") - tk.MustQuery("select id from t where c1 = '2015-06-07 12:12:12'").Check(testkit.Rows("1")) - - // Test issue 17816 - tk.MustExec("drop table if exists t0") - tk.MustExec("CREATE TABLE t0(c0 INT)") - tk.MustExec("INSERT INTO t0 VALUES (100000)") - tk.MustQuery("SELECT * FROM t0 WHERE NOT SPACE(t0.c0)").Check(testkit.Rows("100000")) -} - -func (s *testSuite) TestTimestampTimeZone(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (ts timestamp)") - tk.MustExec("set time_zone = '+00:00'") - tk.MustExec("insert into t values ('2017-04-27 22:40:42')") - // The timestamp will get different value if time_zone session variable changes. - tests := []struct { - timezone string - expect string - }{ - {"+10:00", "2017-04-28 08:40:42"}, - {"-6:00", "2017-04-27 16:40:42"}, - } - for _, tt := range tests { - tk.MustExec(fmt.Sprintf("set time_zone = '%s'", tt.timezone)) - tk.MustQuery("select * from t").Check(testkit.Rows(tt.expect)) - } - - // For issue https://github.com/pingcap/tidb/issues/3467 - tk.MustExec("drop table if exists t1") - tk.MustExec(`CREATE TABLE t1 ( - id bigint(20) NOT NULL AUTO_INCREMENT, - uid int(11) DEFAULT NULL, - datetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - ip varchar(128) DEFAULT NULL, - PRIMARY KEY (id), - KEY i_datetime (datetime), - KEY i_userid (uid) - );`) - tk.MustExec(`INSERT INTO t1 VALUES (123381351,1734,"2014-03-31 08:57:10","127.0.0.1");`) - r := tk.MustQuery("select datetime from t1;") // Cover TableReaderExec - r.Check(testkit.Rows("2014-03-31 08:57:10")) - r = tk.MustQuery("select datetime from t1 where datetime='2014-03-31 08:57:10';") - r.Check(testkit.Rows("2014-03-31 08:57:10")) // Cover IndexReaderExec - r = tk.MustQuery("select * from t1 where datetime='2014-03-31 08:57:10';") - r.Check(testkit.Rows("123381351 1734 2014-03-31 08:57:10 127.0.0.1")) // Cover IndexLookupExec - - // For issue https://github.com/pingcap/tidb/issues/3485 - tk.MustExec("set time_zone = 'Asia/Shanghai'") - tk.MustExec("drop table if exists t1") - tk.MustExec(`CREATE TABLE t1 ( - id bigint(20) NOT NULL AUTO_INCREMENT, - datetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id) - );`) - tk.MustExec(`INSERT INTO t1 VALUES (123381351,"2014-03-31 08:57:10");`) - r = tk.MustQuery(`select * from t1 where datetime="2014-03-31 08:57:10";`) - r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) - tk.MustExec(`alter table t1 add key i_datetime (datetime);`) - r = tk.MustQuery(`select * from t1 where datetime="2014-03-31 08:57:10";`) - r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) - r = tk.MustQuery(`select * from t1;`) - r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) - r = tk.MustQuery("select datetime from t1 where datetime='2014-03-31 08:57:10';") - r.Check(testkit.Rows("2014-03-31 08:57:10")) -} - -func (s *testSuite) TestTimestampDefaultValueTimeZone(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set time_zone = '+08:00'") - tk.MustExec(`create table t (a int, b timestamp default "2019-01-17 14:46:14")`) - tk.MustExec("insert into t set a=1") - r := tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 14:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("set time_zone = '+00:00'") - tk.MustExec("insert into t set a=2") - r = tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 06:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - r = tk.MustQuery(`select a,b from t order by a`) - r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14")) - // Test the column's version is greater than ColumnInfoVersion1. - sctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(sctx).InfoSchema() - c.Assert(is, NotNil) - tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tb.Cols()[1].Version = model.ColumnInfoVersion1 + 1 - tk.MustExec("insert into t set a=3") - r = tk.MustQuery(`select a,b from t order by a`) - r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14", "3 2019-01-17 06:46:14")) - tk.MustExec("delete from t where a=3") - // Change time zone back. - tk.MustExec("set time_zone = '+08:00'") - r = tk.MustQuery(`select a,b from t order by a`) - r.Check(testkit.Rows("1 2019-01-17 14:46:14", "2 2019-01-17 14:46:14")) - tk.MustExec("set time_zone = '-08:00'") - r = tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-16 22:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - - // test zero default value in multiple time zone. - defer tk.MustExec(fmt.Sprintf("set @@sql_mode='%s'", tk.MustQuery("select @@sql_mode").Rows()[0][0])) - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';") - tk.MustExec("drop table if exists t") - tk.MustExec("set time_zone = '+08:00'") - tk.MustExec(`create table t (a int, b timestamp default "0000-00-00 00")`) - tk.MustExec("insert into t set a=1") - r = tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("set time_zone = '+00:00'") - tk.MustExec("insert into t set a=2") - r = tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustExec("set time_zone = '-08:00'") - tk.MustExec("insert into t set a=3") - r = tk.MustQuery(`show create table t`) - r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - r = tk.MustQuery(`select a,b from t order by a`) - r.Check(testkit.Rows("1 0000-00-00 00:00:00", "2 0000-00-00 00:00:00", "3 0000-00-00 00:00:00")) - - // test add timestamp column default current_timestamp. - tk.MustExec(`drop table if exists t`) - tk.MustExec(`set time_zone = 'Asia/Shanghai'`) - tk.MustExec(`create table t (a int)`) - tk.MustExec(`insert into t set a=1`) - tk.MustExec(`alter table t add column b timestamp not null default current_timestamp;`) - timeIn8 := tk.MustQuery("select b from t").Rows()[0][0] - tk.MustExec(`set time_zone = '+00:00'`) - timeIn0 := tk.MustQuery("select b from t").Rows()[0][0] - c.Assert(timeIn8 != timeIn0, IsTrue, Commentf("%v == %v", timeIn8, timeIn0)) - datumTimeIn8, err := expression.GetTimeValue(tk.Se, timeIn8, mysql.TypeTimestamp, 0) - c.Assert(err, IsNil) - tIn8To0 := datumTimeIn8.GetMysqlTime() - timeZoneIn8, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) - err = tIn8To0.ConvertTimeZone(timeZoneIn8, time.UTC) - c.Assert(err, IsNil) - c.Assert(timeIn0 == tIn8To0.String(), IsTrue, Commentf("%v != %v", timeIn0, tIn8To0.String())) - - // test add index. - tk.MustExec(`alter table t add index(b);`) - tk.MustExec("admin check table t") - tk.MustExec(`set time_zone = '+05:00'`) - tk.MustExec("admin check table t") -} - -func (s *testSuite) TestTiDBCurrentTS(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0")) - tk.MustExec("begin") - rows := tk.MustQuery("select @@tidb_current_ts").Rows() - tsStr := rows[0][0].(string) - txn, err := tk.Se.Txn(true) - c.Assert(err, IsNil) - c.Assert(tsStr, Equals, fmt.Sprintf("%d", txn.StartTS())) - tk.MustExec("begin") - rows = tk.MustQuery("select @@tidb_current_ts").Rows() - newTsStr := rows[0][0].(string) - txn, err = tk.Se.Txn(true) - c.Assert(err, IsNil) - c.Assert(newTsStr, Equals, fmt.Sprintf("%d", txn.StartTS())) - c.Assert(newTsStr, Not(Equals), tsStr) - tk.MustExec("commit") - tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0")) - - _, err = tk.Exec("set @@tidb_current_ts = '1'") - c.Assert(terror.ErrorEqual(err, variable.ErrIncorrectScope), IsTrue, Commentf("err %v", err)) -} - -func (s *testSuite) TestTiDBLastTxnInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key)") - tk.MustQuery("select @@tidb_last_txn_info").Check(testkit.Rows("")) - - tk.MustExec("insert into t values (1)") - rows1 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() - c.Assert(rows1[0][0].(string), Greater, "0") - c.Assert(rows1[0][0].(string), Less, rows1[0][1].(string)) - - tk.MustExec("begin") - tk.MustQuery("select a from t where a = 1").Check(testkit.Rows("1")) - rows2 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows() - tk.MustExec("commit") - rows3 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() - c.Assert(rows2[0][0], Equals, rows1[0][0]) - c.Assert(rows2[0][1], Equals, rows1[0][1]) - c.Assert(rows3[0][0], Equals, rows1[0][0]) - c.Assert(rows3[0][1], Equals, rows1[0][1]) - c.Assert(rows2[0][1], Less, rows2[0][2]) - - tk.MustExec("begin") - tk.MustExec("update t set a = a + 1 where a = 1") - rows4 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows() - tk.MustExec("commit") - rows5 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() - c.Assert(rows4[0][0], Equals, rows1[0][0]) - c.Assert(rows4[0][1], Equals, rows1[0][1]) - c.Assert(rows4[0][2], Equals, rows5[0][0]) - c.Assert(rows4[0][1], Less, rows4[0][2]) - c.Assert(rows4[0][2], Less, rows5[0][1]) - - tk.MustExec("begin") - tk.MustExec("update t set a = a + 1 where a = 2") - tk.MustExec("rollback") - rows6 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() - c.Assert(rows6[0][0], Equals, rows5[0][0]) - c.Assert(rows6[0][1], Equals, rows5[0][1]) - - tk.MustExec("begin optimistic") - tk.MustExec("insert into t values (2)") - _, err := tk.Exec("commit") - c.Assert(err, NotNil) - rows7 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), json_extract(@@tidb_last_txn_info, '$.error')").Rows() - c.Assert(rows7[0][0], Greater, rows5[0][0]) - c.Assert(rows7[0][1], Equals, "0") - c.Assert(strings.Contains(err.Error(), rows7[0][1].(string)), IsTrue) - - _, err = tk.Exec("set @@tidb_last_txn_info = '{}'") - c.Assert(terror.ErrorEqual(err, variable.ErrIncorrectScope), IsTrue, Commentf("err %v", err)) -} - -func (s *testSerialSuite) TestTiDBLastTxnInfoCommitMode(c *C) { - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.TiKVClient.AsyncCommit.SafeWindow = time.Second - }) - - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key, v int)") - tk.MustExec("insert into t values (1, 1)") - - tk.MustExec("set @@tidb_enable_async_commit = 1") - tk.MustExec("set @@tidb_enable_1pc = 0") - tk.MustExec("update t set v = v + 1 where a = 1") - rows := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Log(rows) - c.Assert(rows[0][0], Equals, `"async_commit"`) - c.Assert(rows[0][1], Equals, "false") - c.Assert(rows[0][2], Equals, "false") - - tk.MustExec("set @@tidb_enable_async_commit = 0") - tk.MustExec("set @@tidb_enable_1pc = 1") - tk.MustExec("update t set v = v + 1 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Assert(rows[0][0], Equals, `"1pc"`) - c.Assert(rows[0][1], Equals, "false") - c.Assert(rows[0][2], Equals, "false") - - tk.MustExec("set @@tidb_enable_async_commit = 0") - tk.MustExec("set @@tidb_enable_1pc = 0") - tk.MustExec("update t set v = v + 1 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Assert(rows[0][0], Equals, `"2pc"`) - c.Assert(rows[0][1], Equals, "false") - c.Assert(rows[0][2], Equals, "false") - - c.Assert(failpoint.Enable("tikvclient/invalidMaxCommitTS", "return"), IsNil) - defer func() { - c.Assert(failpoint.Disable("tikvclient/invalidMaxCommitTS"), IsNil) - }() - - tk.MustExec("set @@tidb_enable_async_commit = 1") - tk.MustExec("set @@tidb_enable_1pc = 0") - tk.MustExec("update t set v = v + 1 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Log(rows) - c.Assert(rows[0][0], Equals, `"2pc"`) - c.Assert(rows[0][1], Equals, "true") - c.Assert(rows[0][2], Equals, "false") - - tk.MustExec("set @@tidb_enable_async_commit = 0") - tk.MustExec("set @@tidb_enable_1pc = 1") - tk.MustExec("update t set v = v + 1 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Log(rows) - c.Assert(rows[0][0], Equals, `"2pc"`) - c.Assert(rows[0][1], Equals, "false") - c.Assert(rows[0][2], Equals, "true") - - tk.MustExec("set @@tidb_enable_async_commit = 1") - tk.MustExec("set @@tidb_enable_1pc = 1") - tk.MustExec("update t set v = v + 1 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.txn_commit_mode'), json_extract(@@tidb_last_txn_info, '$.async_commit_fallback'), json_extract(@@tidb_last_txn_info, '$.one_pc_fallback')").Rows() - c.Log(rows) - c.Assert(rows[0][0], Equals, `"2pc"`) - c.Assert(rows[0][1], Equals, "true") - c.Assert(rows[0][2], Equals, "true") -} - -func (s *testSuite) TestTiDBLastQueryInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key, v int)") - tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.start_ts')").Check(testkit.Rows("0 0")) - - toUint64 := func(str interface{}) uint64 { - res, err := strconv.ParseUint(str.(string), 10, 64) - c.Assert(err, IsNil) - return res - } - - tk.MustExec("select * from t") - rows := tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(rows[0][0], Equals, rows[0][1]) - - tk.MustExec("insert into t values (1, 10)") - rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(rows[0][0], Equals, rows[0][1]) - // tidb_last_txn_info is still valid after checking query info. - rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(rows[0][0].(string), Less, rows[0][1].(string)) - - tk.MustExec("begin pessimistic") - tk.MustExec("select * from t") - rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(rows[0][0], Equals, rows[0][1]) - - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - tk2.MustExec("update t set v = 11 where a = 1") - - tk.MustExec("select * from t") - rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(rows[0][0], Equals, rows[0][1]) - - tk.MustExec("update t set v = 12 where a = 1") - rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(toUint64(rows[0][0]), Less, toUint64(rows[0][1])) - - tk.MustExec("commit") - - tk.MustExec("set transaction isolation level read committed") - tk.MustExec("begin pessimistic") - tk.MustExec("select * from t") - rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() - c.Assert(toUint64(rows[0][0]), Greater, uint64(0)) - c.Assert(toUint64(rows[0][0]), Less, toUint64(rows[0][1])) - - tk.MustExec("rollback") -} - -func (s *testSuite) TestSelectForUpdate(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use test") - - tk.MustExec("drop table if exists t, t1") - - txn, err := tk.Se.Txn(true) - c.Assert(kv.ErrInvalidTxn.Equal(err), IsTrue) - c.Assert(txn.Valid(), IsFalse) - tk.MustExec("create table t (c1 int, c2 int, c3 int)") - tk.MustExec("insert t values (11, 2, 3)") - tk.MustExec("insert t values (12, 2, 3)") - tk.MustExec("insert t values (13, 2, 3)") - - tk.MustExec("create table t1 (c1 int)") - tk.MustExec("insert t1 values (11)") - - // conflict - tk1.MustExec("begin") - tk1.MustQuery("select * from t where c1=11 for update") - - tk2.MustExec("begin") - tk2.MustExec("update t set c2=211 where c1=11") - tk2.MustExec("commit") - - _, err = tk1.Exec("commit") - c.Assert(err, NotNil) - - // no conflict for subquery. - tk1.MustExec("begin") - tk1.MustQuery("select * from t where exists(select null from t1 where t1.c1=t.c1) for update") - - tk2.MustExec("begin") - tk2.MustExec("update t set c2=211 where c1=12") - tk2.MustExec("commit") - - tk1.MustExec("commit") - - // not conflict - tk1.MustExec("begin") - tk1.MustQuery("select * from t where c1=11 for update") - - tk2.MustExec("begin") - tk2.MustExec("update t set c2=22 where c1=12") - tk2.MustExec("commit") - - tk1.MustExec("commit") - - // not conflict, auto commit - tk1.MustExec("set @@autocommit=1;") - tk1.MustQuery("select * from t where c1=11 for update") - - tk2.MustExec("begin") - tk2.MustExec("update t set c2=211 where c1=11") - tk2.MustExec("commit") - - tk1.MustExec("commit") - - // conflict - tk1.MustExec("begin") - tk1.MustQuery("select * from (select * from t for update) t join t1 for update") - - tk2.MustExec("begin") - tk2.MustExec("update t1 set c1 = 13") - tk2.MustExec("commit") - - _, err = tk1.Exec("commit") - c.Assert(err, NotNil) - -} - -func (s *testSuite) TestSelectForUpdateOf(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - - tk.MustExec("drop table if exists t, t1") - tk.MustExec("create table t (i int)") - tk.MustExec("create table t1 (i int)") - tk.MustExec("insert t values (1)") - tk.MustExec("insert t1 values (1)") - - tk.MustExec("begin pessimistic") - tk.MustQuery("select * from t, t1 where t.i = t1.i for update of t").Check(testkit.Rows("1 1")) - - tk1.MustExec("begin pessimistic") - - // no lock for t - tk1.MustQuery("select * from t1 for update").Check(testkit.Rows("1")) - - // meet lock for t1 - err := tk1.ExecToErr("select * from t for update nowait") - c.Assert(terror.ErrorEqual(err, error2.ErrLockAcquireFailAndNoWaitSet), IsTrue, Commentf("error: ", err)) - - // t1 rolled back, tk1 acquire the lock - tk.MustExec("rollback") - tk1.MustQuery("select * from t for update nowait").Check(testkit.Rows("1")) - - tk1.MustExec("rollback") -} - -func (s *testSuite) TestEmptyEnum(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (e enum('Y', 'N'))") - tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") - _, err := tk.Exec("insert into t values (0)") - c.Assert(terror.ErrorEqual(err, types.ErrTruncated), IsTrue, Commentf("err %v", err)) - _, err = tk.Exec("insert into t values ('abc')") - c.Assert(terror.ErrorEqual(err, types.ErrTruncated), IsTrue, Commentf("err %v", err)) - - tk.MustExec("set sql_mode=''") - tk.MustExec("insert into t values (0)") - tk.MustQuery("select * from t").Check(testkit.Rows("")) - tk.MustExec("insert into t values ('abc')") - tk.MustQuery("select * from t").Check(testkit.Rows("", "")) - tk.MustExec("insert into t values (null)") - tk.MustQuery("select * from t").Check(testkit.Rows("", "", "")) - - // Test https://github.com/pingcap/tidb/issues/29525. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (id int auto_increment primary key, c1 enum('a', '', 'c'));") - tk.MustExec("insert into t(c1) values (0);") - tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ")) - tk.MustExec("alter table t change c1 c1 enum('a', '') not null;") - tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ")) - tk.MustExec("insert into t(c1) values (0);") - tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ", "2 0 ")) -} - -// TestIssue4024 This tests https://github.com/pingcap/tidb/issues/4024 -func (s *testSuite) TestIssue4024(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database test2") - tk.MustExec("use test2") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t values(1)") - tk.MustExec("use test") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t values(1)") - tk.MustExec("update t, test2.t set test2.t.a=2") - tk.MustQuery("select * from t").Check(testkit.Rows("1")) - tk.MustQuery("select * from test2.t").Check(testkit.Rows("2")) - tk.MustExec("update test.t, test2.t set test.t.a=3") - tk.MustQuery("select * from t").Check(testkit.Rows("3")) - tk.MustQuery("select * from test2.t").Check(testkit.Rows("2")) -} - -const ( - checkRequestOff = iota - checkRequestSyncLog - checkDDLAddIndexPriority -) - -type checkRequestClient struct { - tikv.Client - priority kvrpcpb.CommandPri - lowPriorityCnt uint32 - mu struct { - sync.RWMutex - checkFlags uint32 - syncLog bool - } -} - -func (c *checkRequestClient) setCheckPriority(priority kvrpcpb.CommandPri) { - atomic.StoreInt32((*int32)(&c.priority), int32(priority)) -} - -func (c *checkRequestClient) getCheckPriority() kvrpcpb.CommandPri { - return (kvrpcpb.CommandPri)(atomic.LoadInt32((*int32)(&c.priority))) -} - -func (c *checkRequestClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { - resp, err := c.Client.SendRequest(ctx, addr, req, timeout) - c.mu.RLock() - checkFlags := c.mu.checkFlags - c.mu.RUnlock() - if checkFlags == checkRequestSyncLog { - switch req.Type { - case tikvrpc.CmdPrewrite, tikvrpc.CmdCommit: - c.mu.RLock() - syncLog := c.mu.syncLog - c.mu.RUnlock() - if syncLog != req.SyncLog { - return nil, errors.New("fail to set sync log") - } - } - } else if checkFlags == checkDDLAddIndexPriority { - if req.Type == tikvrpc.CmdScan { - if c.getCheckPriority() != req.Priority { - return nil, errors.New("fail to set priority") - } - } else if req.Type == tikvrpc.CmdPrewrite { - if c.getCheckPriority() == kvrpcpb.CommandPri_Low { - atomic.AddUint32(&c.lowPriorityCnt, 1) - } - } - } - return resp, err -} - -type testSuiteWithCliBaseCharset struct { - testSuiteWithCliBase -} - -func (s *testSuiteWithCliBaseCharset) SetUpSuite(c *C) { - collate.SetCharsetFeatEnabledForTest(true) - s.testSuiteWithCliBase.SetUpSuite(c) -} - -func (s *testSuiteWithCliBaseCharset) TearDownSuite(c *C) { - s.testSuiteWithCliBase.TearDownSuite(c) - collate.SetCharsetFeatEnabledForTest(false) -} - -type testSuiteWithCliBase struct { - store kv.Storage - dom *domain.Domain - cli *checkRequestClient -} - -type testSuite1 struct { - testSuiteWithCliBase -} - -type testSerialSuite2 struct { - testSuiteWithCliBase -} - -func (s *testSuiteWithCliBase) SetUpSuite(c *C) { - cli := &checkRequestClient{} - hijackClient := func(c tikv.Client) tikv.Client { - cli.Client = c - return cli - } - s.cli = cli - - var err error - s.store, err = mockstore.NewMockStore( - mockstore.WithClientHijacker(hijackClient), - ) - c.Assert(err, IsNil) - session.SetStatsLease(0) - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - s.dom.SetStatsUpdating(true) -} - -func (s *testSuiteWithCliBase) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *testSuiteWithCliBase) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } -} - -func (s *testSuite2) TestAddIndexPriority(c *C) { - cli := &checkRequestClient{} - hijackClient := func(c tikv.Client) tikv.Client { - cli.Client = c - return cli - } - - store, err := mockstore.NewMockStore( - mockstore.WithClientHijacker(hijackClient), - ) - c.Assert(err, IsNil) - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() - - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test") - tk.MustExec("create table t1 (id int, v int)") - - // Insert some data to make sure plan build IndexLookup for t1. - for i := 0; i < 10; i++ { - tk.MustExec(fmt.Sprintf("insert into t1 values (%d, %d)", i, i)) - } - - cli.mu.Lock() - cli.mu.checkFlags = checkDDLAddIndexPriority - cli.mu.Unlock() - - cli.setCheckPriority(kvrpcpb.CommandPri_Low) - tk.MustExec("alter table t1 add index t1_index (id);") - - c.Assert(atomic.LoadUint32(&cli.lowPriorityCnt) > 0, IsTrue) - - cli.mu.Lock() - cli.mu.checkFlags = checkRequestOff - cli.mu.Unlock() - - tk.MustExec("alter table t1 drop index t1_index;") - tk.MustExec("SET SESSION tidb_ddl_reorg_priority = 'PRIORITY_NORMAL'") - - cli.mu.Lock() - cli.mu.checkFlags = checkDDLAddIndexPriority - cli.mu.Unlock() - - cli.setCheckPriority(kvrpcpb.CommandPri_Normal) - tk.MustExec("alter table t1 add index t1_index (id);") - - cli.mu.Lock() - cli.mu.checkFlags = checkRequestOff - cli.mu.Unlock() - - tk.MustExec("alter table t1 drop index t1_index;") - tk.MustExec("SET SESSION tidb_ddl_reorg_priority = 'PRIORITY_HIGH'") - - cli.mu.Lock() - cli.mu.checkFlags = checkDDLAddIndexPriority - cli.mu.Unlock() - - cli.setCheckPriority(kvrpcpb.CommandPri_High) - tk.MustExec("alter table t1 add index t1_index (id);") - - cli.mu.Lock() - cli.mu.checkFlags = checkRequestOff - cli.mu.Unlock() -} - -func (s *testSuite1) TestAlterTableComment(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t_1") - tk.MustExec("create table t_1 (c1 int, c2 int, c3 int default 1, index (c1)) comment = 'test table';") - tk.MustExec("alter table `t_1` comment 'this is table comment';") - result := tk.MustQuery("select table_comment from information_schema.tables where table_name = 't_1';") - result.Check(testkit.Rows("this is table comment")) - tk.MustExec("alter table `t_1` comment 'table t comment';") - result = tk.MustQuery("select table_comment from information_schema.tables where table_name = 't_1';") - result.Check(testkit.Rows("table t comment")) -} - -func (s *testSuite) TestTimezonePushDown(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t (ts timestamp)") - defer tk.MustExec("drop table t") - tk.MustExec(`insert into t values ("2018-09-13 10:02:06")`) - - systemTZ := timeutil.SystemLocation() - c.Assert(systemTZ.String(), Not(Equals), "System") - c.Assert(systemTZ.String(), Not(Equals), "Local") - ctx := context.Background() - count := 0 - ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { - count += 1 - dagReq := new(tipb.DAGRequest) - err := proto.Unmarshal(req.Data, dagReq) - c.Assert(err, IsNil) - c.Assert(dagReq.GetTimeZoneName(), Equals, systemTZ.String()) - }) - _, err := tk.Se.Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`) - c.Assert(err, IsNil) - - tk.MustExec(`set time_zone="System"`) - _, err = tk.Se.Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`) - c.Assert(err, IsNil) - - c.Assert(count, Equals, 2) // Make sure the hook function is called. -} - -func (s *testSuite) TestNotFillCacheFlag(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t (id int primary key)") - defer tk.MustExec("drop table t") - tk.MustExec("insert into t values (1)") - - tests := []struct { - sql string - expect bool - }{ - {"select SQL_NO_CACHE * from t", true}, - {"select SQL_CACHE * from t", false}, - {"select * from t", false}, - } - count := 0 - ctx := context.Background() - for _, test := range tests { - ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { - count++ - if req.NotFillCache != test.expect { - c.Errorf("sql=%s, expect=%v, get=%v", test.sql, test.expect, req.NotFillCache) - } - }) - rs, err := tk.Se.Execute(ctx1, test.sql) - c.Assert(err, IsNil) - tk.ResultSetToResult(rs[0], Commentf("sql: %v", test.sql)) - } - c.Assert(count, Equals, len(tests)) // Make sure the hook function is called. -} - -func (s *testSuite1) TestSyncLog(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - cli := s.cli - cli.mu.Lock() - cli.mu.checkFlags = checkRequestSyncLog - cli.mu.syncLog = true - cli.mu.Unlock() - tk.MustExec("create table t (id int primary key)") - cli.mu.Lock() - cli.mu.syncLog = false - cli.mu.Unlock() - tk.MustExec("insert into t values (1)") - - cli.mu.Lock() - cli.mu.checkFlags = checkRequestOff - cli.mu.Unlock() -} - -func (s *testSuite) TestHandleTransfer(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t(a int, index idx(a))") - tk.MustExec("insert into t values(1), (2), (4)") - tk.MustExec("begin") - tk.MustExec("update t set a = 3 where a = 4") - // test table scan read whose result need handle. - tk.MustQuery("select * from t ignore index(idx)").Check(testkit.Rows("1", "2", "3")) - tk.MustExec("insert into t values(4)") - // test single read whose result need handle - tk.MustQuery("select * from t use index(idx)").Check(testkit.Rows("1", "2", "3", "4")) - tk.MustQuery("select * from t use index(idx) order by a desc").Check(testkit.Rows("4", "3", "2", "1")) - tk.MustExec("update t set a = 5 where a = 3") - tk.MustQuery("select * from t use index(idx)").Check(testkit.Rows("1", "2", "4", "5")) - tk.MustExec("commit") - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int, index idx(a))") - tk.MustExec("insert into t values(3, 3), (1, 1), (2, 2)") - // Second test double read. - tk.MustQuery("select * from t use index(idx) order by a").Check(testkit.Rows("1 1", "2 2", "3 3")) -} - -func (s *testSuite) TestBit(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(2))") - tk.MustExec("insert into t values (0), (1), (2), (3)") - _, err := tk.Exec("insert into t values (4)") - c.Assert(err, NotNil) - _, err = tk.Exec("insert into t values ('a')") - c.Assert(err, NotNil) - r, err := tk.Exec("select * from t where c1 = 2") - c.Assert(err, IsNil) - req := r.NewChunk(nil) - err = r.Next(context.Background(), req) - c.Assert(err, IsNil) - c.Assert(types.BinaryLiteral(req.GetRow(0).GetBytes(0)), DeepEquals, types.NewBinaryLiteralFromUint(2, -1)) - r.Close() - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(31))") - tk.MustExec("insert into t values (0x7fffffff)") - _, err = tk.Exec("insert into t values (0x80000000)") - c.Assert(err, NotNil) - _, err = tk.Exec("insert into t values (0xffffffff)") - c.Assert(err, NotNil) - tk.MustExec("insert into t values ('123')") - tk.MustExec("insert into t values ('1234')") - _, err = tk.Exec("insert into t values ('12345)") - c.Assert(err, NotNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(62))") - tk.MustExec("insert into t values ('12345678')") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(61))") - _, err = tk.Exec("insert into t values ('12345678')") - c.Assert(err, NotNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(32))") - tk.MustExec("insert into t values (0x7fffffff)") - tk.MustExec("insert into t values (0xffffffff)") - _, err = tk.Exec("insert into t values (0x1ffffffff)") - c.Assert(err, NotNil) - tk.MustExec("insert into t values ('1234')") - _, err = tk.Exec("insert into t values ('12345')") - c.Assert(err, NotNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(64))") - tk.MustExec("insert into t values (0xffffffffffffffff)") - tk.MustExec("insert into t values ('12345678')") - _, err = tk.Exec("insert into t values ('123456789')") - c.Assert(err, NotNil) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c1 bit(64))") - tk.MustExec("insert into t values (0xffffffffffffffff)") - tk.MustExec("insert into t values ('12345678')") - tk.MustQuery("select * from t where c1").Check(testkit.Rows("\xff\xff\xff\xff\xff\xff\xff\xff", "12345678")) -} - -func (s *testSuite) TestEnum(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c enum('a', 'b', 'c'))") - tk.MustExec("insert into t values ('a'), (2), ('c')") - tk.MustQuery("select * from t where c = 'a'").Check(testkit.Rows("a")) - - tk.MustQuery("select c + 1 from t where c = 2").Check(testkit.Rows("3")) - - tk.MustExec("delete from t") - tk.MustExec("insert into t values ()") - tk.MustExec("insert into t values (null), ('1')") - tk.MustQuery("select c + 1 from t where c = 1").Check(testkit.Rows("2")) - - tk.MustExec("delete from t") - tk.MustExec("insert into t values(1), (2), (3)") - tk.MustQuery("select * from t where c").Check(testkit.Rows("a", "b", "c")) -} - -func (s *testSuite) TestSet(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c set('a', 'b', 'c'))") - tk.MustExec("insert into t values ('a'), (2), ('c'), ('a,b'), ('b,a')") - tk.MustQuery("select * from t where c = 'a'").Check(testkit.Rows("a")) - - tk.MustQuery("select * from t where c = 'a,b'").Check(testkit.Rows("a,b", "a,b")) - - tk.MustQuery("select c + 1 from t where c = 2").Check(testkit.Rows("3")) - - tk.MustExec("delete from t") - tk.MustExec("insert into t values ()") - tk.MustExec("insert into t values (null), ('1')") - tk.MustQuery("select c + 1 from t where c = 1").Check(testkit.Rows("2")) - - tk.MustExec("delete from t") - tk.MustExec("insert into t values(3)") - tk.MustQuery("select * from t where c").Check(testkit.Rows("a,b")) -} - -func (s *testSuite) TestSubqueryInValues(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (id int, name varchar(20))") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (gid int)") - - tk.MustExec("insert into t1 (gid) value (1)") - tk.MustExec("insert into t (id, name) value ((select gid from t1) ,'asd')") - tk.MustQuery("select * from t").Check(testkit.Rows("1 asd")) -} - -func (s *testSuite) TestEnhancedRangeAccess(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key, b int)") - tk.MustExec("insert into t values(1, 2), (2, 1)") - tk.MustQuery("select * from t where (a = 1 and b = 2) or (a = 2 and b = 1)").Check(testkit.Rows("1 2", "2 1")) - tk.MustQuery("select * from t where (a = 1 and b = 1) or (a = 2 and b = 2)").Check(nil) -} - -// TestMaxInt64Handle Issue #4810 -func (s *testSuite) TestMaxInt64Handle(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id bigint, PRIMARY KEY (id))") - tk.MustExec("insert into t values(9223372036854775807)") - tk.MustExec("select * from t where id = 9223372036854775807") - tk.MustQuery("select * from t where id = 9223372036854775807;").Check(testkit.Rows("9223372036854775807")) - tk.MustQuery("select * from t").Check(testkit.Rows("9223372036854775807")) - _, err := tk.Exec("insert into t values(9223372036854775807)") - c.Assert(err, NotNil) - tk.MustExec("delete from t where id = 9223372036854775807") - tk.MustQuery("select * from t").Check(nil) -} - -func (s *testSuite) TestTableScanWithPointRanges(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id int, PRIMARY KEY (id))") - tk.MustExec("insert into t values(1), (5), (10)") - tk.MustQuery("select * from t where id in(1, 2, 10)").Check(testkit.Rows("1", "10")) -} - -func (s *testSuite) TestUnsignedPk(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id bigint unsigned primary key)") - var num1, num2 uint64 = math.MaxInt64 + 1, math.MaxInt64 + 2 - tk.MustExec(fmt.Sprintf("insert into t values(%v), (%v), (1), (2)", num1, num2)) - num1Str := strconv.FormatUint(num1, 10) - num2Str := strconv.FormatUint(num2, 10) - tk.MustQuery("select * from t order by id").Check(testkit.Rows("1", "2", num1Str, num2Str)) - tk.MustQuery("select * from t where id not in (2)").Check(testkit.Rows(num1Str, num2Str, "1")) - tk.MustExec("drop table t") - tk.MustExec("create table t(a bigint unsigned primary key, b int, index idx(b))") - tk.MustExec("insert into t values(9223372036854775808, 1), (1, 1)") - tk.MustQuery("select * from t use index(idx) where b = 1 and a < 2").Check(testkit.Rows("1 1")) - tk.MustQuery("select * from t use index(idx) where b = 1 order by b, a").Check(testkit.Rows("1 1", "9223372036854775808 1")) -} - -func (s *testSuite) TestSignedCommonHandle(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(k1 int, k2 int, primary key(k1, k2))") - tk.MustExec("insert into t(k1, k2) value(-100, 1), (-50, 1), (0, 0), (1, 1), (3, 3)") - tk.MustQuery("select k1 from t order by k1").Check(testkit.Rows("-100", "-50", "0", "1", "3")) - tk.MustQuery("select k1 from t order by k1 desc").Check(testkit.Rows("3", "1", "0", "-50", "-100")) - tk.MustQuery("select k1 from t where k1 < -51").Check(testkit.Rows("-100")) - tk.MustQuery("select k1 from t where k1 < -1").Check(testkit.Rows("-100", "-50")) - tk.MustQuery("select k1 from t where k1 <= 0").Check(testkit.Rows("-100", "-50", "0")) - tk.MustQuery("select k1 from t where k1 < 2").Check(testkit.Rows("-100", "-50", "0", "1")) - tk.MustQuery("select k1 from t where k1 < -1 and k1 > -90").Check(testkit.Rows("-50")) -} - -func (s *testSuite) TestIssue5666(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@profiling=1") - tk.MustQuery("SELECT QUERY_ID, SUM(DURATION) AS SUM_DURATION FROM INFORMATION_SCHEMA.PROFILING GROUP BY QUERY_ID;").Check(testkit.Rows("0 0")) -} - -func (s *testSuite) TestIssue5341(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop table if exists test.t") - tk.MustExec("create table test.t(a char)") - tk.MustExec("insert into test.t value('a')") - tk.MustQuery("select * from test.t where a < 1 order by a limit 0;").Check(testkit.Rows()) -} - -func (s *testSuite) TestContainDotColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists test.t1") - tk.MustExec("create table test.t1(t1.a char)") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2(a char, t2.b int)") - - tk.MustExec("drop table if exists t3") - _, err := tk.Exec("create table t3(s.a char);") - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrWrongTableName)) -} - -func (s *testSuite) TestCheckIndex(c *C) { - s.ctx = mock.NewContext() - s.ctx.Store = s.store - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - defer se.Close() - - _, err = se.Execute(context.Background(), "create database test_admin") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_admin") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "create table t (pk int primary key, c int default 1, c1 int default 1, unique key c(c))") - c.Assert(err, IsNil) - is := s.domain.InfoSchema() - db := model.NewCIStr("test_admin") - dbInfo, ok := is.SchemaByName(db) - c.Assert(ok, IsTrue) - tblName := model.NewCIStr("t") - tbl, err := is.TableByName(db, tblName) - c.Assert(err, IsNil) - tbInfo := tbl.Meta() - - alloc := autoid.NewAllocator(s.store, dbInfo.ID, tbInfo.ID, false, autoid.RowIDAllocType) - tb, err := tables.TableFromMeta(autoid.NewAllocators(alloc), tbInfo) - c.Assert(err, IsNil) - - _, err = se.Execute(context.Background(), "admin check index t c") - c.Assert(err, IsNil) - - _, err = se.Execute(context.Background(), "admin check index t C") - c.Assert(err, IsNil) - - // set data to: - // index data (handle, data): (1, 10), (2, 20) - // table data (handle, data): (1, 10), (2, 20) - recordVal1 := types.MakeDatums(int64(1), int64(10), int64(11)) - recordVal2 := types.MakeDatums(int64(2), int64(20), int64(21)) - c.Assert(s.ctx.NewTxn(context.Background()), IsNil) - _, err = tb.AddRecord(s.ctx, recordVal1) - c.Assert(err, IsNil) - _, err = tb.AddRecord(s.ctx, recordVal2) - c.Assert(err, IsNil) - txn, err := s.ctx.Txn(true) - c.Assert(err, IsNil) - c.Assert(txn.Commit(context.Background()), IsNil) - - mockCtx := mock.NewContext() - idx := tb.Indices()[0] - sc := &stmtctx.StatementContext{TimeZone: time.Local} - - _, err = se.Execute(context.Background(), "admin check index t idx_inexistent") - c.Assert(strings.Contains(err.Error(), "not exist"), IsTrue) - - // set data to: - // index data (handle, data): (1, 10), (2, 20), (3, 30) - // table data (handle, data): (1, 10), (2, 20), (4, 40) - txn, err = s.store.Begin() - c.Assert(err, IsNil) - _, err = idx.Create(mockCtx, txn, types.MakeDatums(int64(30)), kv.IntHandle(3), nil) - c.Assert(err, IsNil) - key := tablecodec.EncodeRowKey(tb.Meta().ID, kv.IntHandle(4).Encoded()) - setColValue(c, txn, key, types.NewDatum(int64(40))) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "admin check index t c") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[executor:8133]handle 3, index:types.Datum{k:0x1, decimal:0x0, length:0x0, i:30, collation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:") - - // set data to: - // index data (handle, data): (1, 10), (2, 20), (3, 30), (4, 40) - // table data (handle, data): (1, 10), (2, 20), (4, 40) - txn, err = s.store.Begin() - c.Assert(err, IsNil) - _, err = idx.Create(mockCtx, txn, types.MakeDatums(int64(40)), kv.IntHandle(4), nil) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "admin check index t c") - c.Assert(strings.Contains(err.Error(), "table count 3 != index(c) count 4"), IsTrue) - - // set data to: - // index data (handle, data): (1, 10), (4, 40) - // table data (handle, data): (1, 10), (2, 20), (4, 40) - txn, err = s.store.Begin() - c.Assert(err, IsNil) - err = idx.Delete(sc, txn, types.MakeDatums(int64(30)), kv.IntHandle(3)) - c.Assert(err, IsNil) - err = idx.Delete(sc, txn, types.MakeDatums(int64(20)), kv.IntHandle(2)) - c.Assert(err, IsNil) - err = txn.Commit(context.Background()) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "admin check index t c") - c.Assert(strings.Contains(err.Error(), "table count 3 != index(c) count 2"), IsTrue) - - // TODO: pass the case below: - // set data to: - // index data (handle, data): (1, 10), (4, 40), (2, 30) - // table data (handle, data): (1, 10), (2, 20), (4, 40) -} - -func setColValue(c *C, txn kv.Transaction, key kv.Key, v types.Datum) { - row := []types.Datum{v, {}} - colIDs := []int64{2, 3} - sc := &stmtctx.StatementContext{TimeZone: time.Local} - rd := rowcodec.Encoder{Enable: true} - value, err := tablecodec.EncodeRow(sc, row, colIDs, nil, nil, &rd) - c.Assert(err, IsNil) - err = txn.Set(key, value) - c.Assert(err, IsNil) -} - -func (s *testSuite) TestCheckTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - - // Test 'admin check table' when the table has a unique index with null values. - tk.MustExec("use test") - tk.MustExec("drop table if exists admin_test;") - tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2));") - tk.MustExec("insert admin_test (c1, c2) values (1, 1), (2, 2), (NULL, NULL);") - tk.MustExec("admin check table admin_test;") -} - -func (s *testSuite) TestCheckTableClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists admin_test;") - tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, primary key (c1, c2), index (c1), unique key(c2));") - tk.MustExec("insert admin_test (c1, c2) values (1, 1), (2, 2), (3, 3);") - tk.MustExec("admin check table admin_test;") -} - -func (s *testSuite) TestCoprocessorStreamingFlag(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("create table t (id int, value int, index idx(id))") - // Add some data to make statistics work. - for i := 0; i < 100; i++ { - tk.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i, i)) - } - - tests := []struct { - sql string - expect bool - }{ - {"select * from t", true}, // TableReader - {"select * from t where id = 5", true}, // IndexLookup - {"select * from t where id > 5", true}, // Filter - {"select * from t limit 3", false}, // Limit - {"select avg(id) from t", false}, // Aggregate - {"select * from t order by value limit 3", false}, // TopN - } - - ctx := context.Background() - for _, test := range tests { - ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { - if req.Streaming != test.expect { - c.Errorf("sql=%s, expect=%v, get=%v", test.sql, test.expect, req.Streaming) - } - }) - rs, err := tk.Se.Execute(ctx1, test.sql) - c.Assert(err, IsNil) - tk.ResultSetToResult(rs[0], Commentf("sql: %v", test.sql)) - } -} - -func (s *testSuite) TestIncorrectLimitArg(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a bigint);`) - tk.MustExec(`prepare stmt1 from 'select * from t limit ?';`) - tk.MustExec(`prepare stmt2 from 'select * from t limit ?, ?';`) - tk.MustExec(`set @a = -1;`) - tk.MustExec(`set @b = 1;`) - - var err error - _, err = tk.Se.Execute(context.TODO(), `execute stmt1 using @a;`) - c.Assert(err.Error(), Equals, `[planner:1210]Incorrect arguments to LIMIT`) - - _, err = tk.Se.Execute(context.TODO(), `execute stmt2 using @b, @a;`) - c.Assert(err.Error(), Equals, `[planner:1210]Incorrect arguments to LIMIT`) -} - -func (s *testSuite) TestLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a bigint, b bigint);`) - tk.MustExec(`insert into t values(1, 1), (2, 2), (3, 30), (4, 40), (5, 5), (6, 6);`) - tk.MustQuery(`select * from t order by a limit 1, 1;`).Check(testkit.Rows( - "2 2", - )) - tk.MustQuery(`select * from t order by a limit 1, 2;`).Check(testkit.Rows( - "2 2", - "3 30", - )) - tk.MustQuery(`select * from t order by a limit 1, 3;`).Check(testkit.Rows( - "2 2", - "3 30", - "4 40", - )) - tk.MustQuery(`select * from t order by a limit 1, 4;`).Check(testkit.Rows( - "2 2", - "3 30", - "4 40", - "5 5", - )) - - // test inline projection - tk.MustQuery(`select a from t where a > 0 limit 1, 1;`).Check(testkit.Rows( - "2", - )) - tk.MustQuery(`select a from t where a > 0 limit 1, 2;`).Check(testkit.Rows( - "2", - "3", - )) - tk.MustQuery(`select b from t where a > 0 limit 1, 3;`).Check(testkit.Rows( - "2", - "30", - "40", - )) - tk.MustQuery(`select b from t where a > 0 limit 1, 4;`).Check(testkit.Rows( - "2", - "30", - "40", - "5", - )) - - // test @@tidb_init_chunk_size=2 - tk.MustExec(`set @@tidb_init_chunk_size=2;`) - tk.MustQuery(`select * from t where a > 0 limit 2, 1;`).Check(testkit.Rows( - "3 30", - )) - tk.MustQuery(`select * from t where a > 0 limit 2, 2;`).Check(testkit.Rows( - "3 30", - "4 40", - )) - tk.MustQuery(`select * from t where a > 0 limit 2, 3;`).Check(testkit.Rows( - "3 30", - "4 40", - "5 5", - )) - tk.MustQuery(`select * from t where a > 0 limit 2, 4;`).Check(testkit.Rows( - "3 30", - "4 40", - "5 5", - "6 6", - )) - - // test inline projection - tk.MustQuery(`select a from t order by a limit 2, 1;`).Check(testkit.Rows( - "3", - )) - tk.MustQuery(`select b from t order by a limit 2, 2;`).Check(testkit.Rows( - "30", - "40", - )) - tk.MustQuery(`select a from t order by a limit 2, 3;`).Check(testkit.Rows( - "3", - "4", - "5", - )) - tk.MustQuery(`select b from t order by a limit 2, 4;`).Check(testkit.Rows( - "30", - "40", - "5", - "6", - )) -} - -func (s *testSuite) TestCoprocessorStreamingWarning(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a double)") - tk.MustExec("insert into t value(1.2)") - tk.MustExec("set @@session.tidb_enable_streaming = 1") - - result := tk.MustQuery("select * from t where a/0 > 1") - result.Check(testkit.Rows()) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1365|Division by 0")) -} - -func (s *testSuite3) TestYearTypeDeleteIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a YEAR, PRIMARY KEY(a));") - tk.MustExec("insert into t set a = '2151';") - tk.MustExec("delete from t;") - tk.MustExec("admin check table t") -} - -func (s *testSuite3) TestForSelectScopeInUnion(c *C) { - // A union B for update, the "for update" option belongs to union statement, so - // it should works on both A and B. - tk1 := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) - tk1.MustExec("use test") - tk1.MustExec("drop table if exists t") - tk1.MustExec("create table t(a int)") - tk1.MustExec("insert into t values (1)") - - tk1.MustExec("begin") - // 'For update' would act on the second select. - tk1.MustQuery("select 1 as a union select a from t for update") - - tk2.MustExec("use test") - tk2.MustExec("update t set a = a + 1") - - // As tk1 use select 'for update', it should detect conflict and fail. - _, err := tk1.Exec("commit") - c.Assert(err, NotNil) - - tk1.MustExec("begin") - tk1.MustQuery("select 1 as a union select a from t limit 5 for update") - tk1.MustQuery("select 1 as a union select a from t order by a for update") - - tk2.MustExec("update t set a = a + 1") - - _, err = tk1.Exec("commit") - c.Assert(err, NotNil) -} - -func (s *testSuite3) TestUnsignedDecimalOverflow(c *C) { - tests := []struct { - input interface{} - hasErr bool - err string - }{{ - -1, - true, - "Out of range value for column", - }, { - "-1.1e-1", - true, - "Out of range value for column", - }, { - -1.1, - true, - "Out of range value for column", - }, { - -0, - false, - "", - }, - } - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a decimal(10,2) unsigned)") - for _, t := range tests { - res, err := tk.Exec("insert into t values (?)", t.input) - if res != nil { - defer res.Close() - } - if t.hasErr { - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), t.err), IsTrue) - } else { - c.Assert(err, IsNil) - } - if res != nil { - c.Assert(res.Close(), IsNil) - } - } - - tk.MustExec("set sql_mode=''") - tk.MustExec("delete from t") - tk.MustExec("insert into t values (?)", -1) - r := tk.MustQuery("select a from t limit 1") - r.Check(testkit.Rows("0.00")) -} - -func (s *testSuite3) TestIndexJoinTableDualPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists a") - tk.MustExec("create table a (f1 int, f2 varchar(32), primary key (f1))") - tk.MustExec("insert into a (f1,f2) values (1,'a'), (2,'b'), (3,'c')") - // TODO here: index join cause the data race of txn. - tk.MustQuery("select /*+ inl_merge_join(a) */ a.* from a inner join (select 1 as k1,'k2-1' as k2) as k on a.f1=k.k1;"). - Check(testkit.Rows("1 a")) -} - -func (s *testSuite3) TestSortLeftJoinWithNullColumnInRightChildPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1(a int)") - tk.MustExec("create table t2(a int)") - tk.MustExec("insert into t1(a) select 1;") - tk.MustQuery("select b.n from t1 left join (select a as a, null as n from t2) b on b.a = t1.a order by t1.a"). - Check(testkit.Rows("")) -} - -func (s *testSuiteP1) TestUnionAutoSignedCast(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2") - tk.MustExec("create table t1 (id int, i int, b bigint, d double, dd decimal)") - tk.MustExec("create table t2 (id int, i int unsigned, b bigint unsigned, d double unsigned, dd decimal unsigned)") - tk.MustExec("insert into t1 values(1, -1, -1, -1.1, -1)") - tk.MustExec("insert into t2 values(2, 1, 1, 1.1, 1)") - tk.MustQuery("select * from t1 union select * from t2 order by id"). - Check(testkit.Rows("1 -1 -1 -1.1 -1", "2 1 1 1.1 1")) - tk.MustQuery("select id, i, b, d, dd from t2 union select id, i, b, d, dd from t1 order by id"). - Check(testkit.Rows("1 -1 -1 -1.1 -1", "2 1 1 1.1 1")) - tk.MustQuery("select id, i from t2 union select id, cast(i as unsigned int) from t1 order by id"). - Check(testkit.Rows("1 18446744073709551615", "2 1")) - tk.MustQuery("select dd from t2 union all select dd from t2"). - Check(testkit.Rows("1", "1")) - - tk.MustExec("drop table if exists t3,t4") - tk.MustExec("create table t3 (id int, v int)") - tk.MustExec("create table t4 (id int, v double unsigned)") - tk.MustExec("insert into t3 values (1, -1)") - tk.MustExec("insert into t4 values (2, 1)") - tk.MustQuery("select id, v from t3 union select id, v from t4 order by id"). - Check(testkit.Rows("1 -1", "2 1")) - tk.MustQuery("select id, v from t4 union select id, v from t3 order by id"). - Check(testkit.Rows("1 -1", "2 1")) - - tk.MustExec("drop table if exists t5,t6,t7") - tk.MustExec("create table t5 (id int, v bigint unsigned)") - tk.MustExec("create table t6 (id int, v decimal)") - tk.MustExec("create table t7 (id int, v bigint)") - tk.MustExec("insert into t5 values (1, 1)") - tk.MustExec("insert into t6 values (2, -1)") - tk.MustExec("insert into t7 values (3, -1)") - tk.MustQuery("select id, v from t5 union select id, v from t6 order by id"). - Check(testkit.Rows("1 1", "2 -1")) - tk.MustQuery("select id, v from t5 union select id, v from t7 union select id, v from t6 order by id"). - Check(testkit.Rows("1 1", "2 -1", "3 -1")) -} - -func (s *testSuiteP1) TestUpdateClustered(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - - type resultChecker struct { - check string - assert []string + type resultChecker struct { + check string + assert []string } for _, clustered := range []string{"", "clustered"} { @@ -4506,232 +1316,11 @@ func (s *testSuiteP1) TestUpdateClustered(c *C) { } } -func (s *testSuite6) TestUpdateJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7") - tk.MustExec("create table t1(k int, v int)") - tk.MustExec("create table t2(k int, v int)") - tk.MustExec("create table t3(id int auto_increment, k int, v int, primary key(id))") - tk.MustExec("create table t4(k int, v int)") - tk.MustExec("create table t5(v int, k int, primary key(k))") - tk.MustExec("insert into t1 values (1, 1)") - tk.MustExec("insert into t4 values (3, 3)") - tk.MustExec("create table t6 (id int, v longtext)") - tk.MustExec("create table t7 (x int, id int, v longtext, primary key(id))") - - // test the normal case that update one row for a single table. - tk.MustExec("update t1 set v = 0 where k = 1") - tk.MustQuery("select k, v from t1 where k = 1").Check(testkit.Rows("1 0")) - - // test the case that the table with auto_increment or none-null columns as the right table of left join. - tk.MustExec("update t1 left join t3 on t1.k = t3.k set t1.v = 1") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 1")) - tk.MustQuery("select id, k, v from t3").Check(testkit.Rows()) - - // test left join and the case that the right table has no matching record but has updated the right table columns. - tk.MustExec("update t1 left join t2 on t1.k = t2.k set t1.v = t2.v, t2.v = 3") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 ")) - tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - - // test the case that the update operation in the left table references data in the right table while data of the right table columns is modified. - tk.MustExec("update t1 left join t2 on t1.k = t2.k set t2.v = 3, t1.v = t2.v") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 ")) - tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - - // test right join and the case that the left table has no matching record but has updated the left table columns. - tk.MustExec("update t2 right join t1 on t2.k = t1.k set t2.v = 4, t1.v = 0") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 0")) - tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - - // test the case of right join and left join at the same time. - tk.MustExec("update t1 left join t2 on t1.k = t2.k right join t4 on t4.k = t2.k set t1.v = 4, t2.v = 4, t4.v = 4") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 0")) - tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - tk.MustQuery("select k, v from t4").Check(testkit.Rows("3 4")) - - // test normal left join and the case that the right table has matching rows. - tk.MustExec("insert t2 values (1, 10)") - tk.MustExec("update t1 left join t2 on t1.k = t2.k set t2.v = 11") - tk.MustQuery("select k, v from t2").Check(testkit.Rows("1 11")) - - // test the case of continuously joining the same table and updating the unmatching records. - tk.MustExec("update t1 t11 left join t2 on t11.k = t2.k left join t1 t12 on t2.v = t12.k set t12.v = 233, t11.v = 111") - tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 111")) - tk.MustQuery("select k, v from t2").Check(testkit.Rows("1 11")) - - // test the left join case that the left table has records but all records are null. - tk.MustExec("delete from t1") - tk.MustExec("delete from t2") - tk.MustExec("insert into t1 values (null, null)") - tk.MustExec("update t1 left join t2 on t1.k = t2.k set t1.v = 1") - tk.MustQuery("select k, v from t1").Check(testkit.Rows(" 1")) - - // test the case that the right table of left join has an primary key. - tk.MustExec("insert t5 values(0, 0)") - tk.MustExec("update t1 left join t5 on t1.k = t5.k set t1.v = 2") - tk.MustQuery("select k, v from t1").Check(testkit.Rows(" 2")) - tk.MustQuery("select k, v from t5").Check(testkit.Rows("0 0")) - - tk.MustExec("insert into t6 values (1, NULL)") - tk.MustExec("insert into t7 values (5, 1, 'a')") - tk.MustExec("update t6, t7 set t6.v = t7.v where t6.id = t7.id and t7.x = 5") - tk.MustQuery("select v from t6").Check(testkit.Rows("a")) - - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1(id int primary key, v int, gv int GENERATED ALWAYS AS (v * 2) STORED)") - tk.MustExec("create table t2(id int, v int)") - tk.MustExec("update t1 tt1 inner join (select count(t1.id) a, t1.id from t1 left join t2 on t1.id = t2.id group by t1.id) x on tt1.id = x.id set tt1.v = tt1.v + x.a") -} - -func (s *testSuite3) TestMaxOneRow(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t1`) - tk.MustExec(`drop table if exists t2`) - tk.MustExec(`create table t1(a double, b double);`) - tk.MustExec(`create table t2(a double, b double);`) - tk.MustExec(`insert into t1 values(1, 1), (2, 2), (3, 3);`) - tk.MustExec(`insert into t2 values(0, 0);`) - tk.MustExec(`set @@tidb_init_chunk_size=1;`) - rs, err := tk.Exec(`select (select t1.a from t1 where t1.a > t2.a) as a from t2;`) - c.Assert(err, IsNil) - - err = rs.Next(context.TODO(), rs.NewChunk(nil)) - c.Assert(err.Error(), Equals, "[executor:1242]Subquery returns more than 1 row") - - c.Assert(rs.Close(), IsNil) -} - -func (s *testSuiteP2) TestCurrentTimestampValueSelection(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t,t1") - - tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))") - tk.MustExec("insert into t (id) values (1)") - rs := tk.MustQuery("select t0, t1, t2 from t where id = 1") - t0 := rs.Rows()[0][0].(string) - t1 := rs.Rows()[0][1].(string) - t2 := rs.Rows()[0][2].(string) - c.Assert(len(strings.Split(t0, ".")), Equals, 1) - c.Assert(len(strings.Split(t1, ".")[1]), Equals, 1) - c.Assert(len(strings.Split(t2, ".")[1]), Equals, 2) - tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1")) - tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1")) - tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1")) - time.Sleep(time.Second) - tk.MustExec("update t set t0 = now() where id = 1") - rs = tk.MustQuery("select t2 from t where id = 1") - newT2 := rs.Rows()[0][0].(string) - c.Assert(newT2 != t2, IsTrue) - - tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))") - tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))") - rs = tk.MustQuery("select a, b, c from t1 where id = 1") - a := rs.Rows()[0][0].(string) - b := rs.Rows()[0][1].(string) - d := rs.Rows()[0][2].(string) - c.Assert(len(strings.Split(a, ".")), Equals, 1) - c.Assert(strings.Split(b, ".")[1], Equals, "00") - c.Assert(len(strings.Split(d, ".")[1]), Equals, 3) -} - -func (s *testSuite3) TestRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - tk.MustExec(`create table t(a varchar(10), b varchar(10), c varchar(1), index idx(a, b, c));`) - tk.MustExec(`insert into t values('a', 'b', 'c');`) - tk.MustExec(`insert into t values('a', 'b', 'c');`) - tk.MustQuery(`select b, _tidb_rowid from t use index(idx) where a = 'a';`).Check(testkit.Rows( - `b 1`, - `b 2`, - )) - tk.MustExec(`begin;`) - tk.MustExec(`select * from t for update`) - tk.MustQuery(`select distinct b from t use index(idx) where a = 'a';`).Check(testkit.Rows(`b`)) - tk.MustExec(`commit;`) - - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t(a varchar(5) primary key)`) - tk.MustExec(`insert into t values('a')`) - tk.MustQuery("select *, _tidb_rowid from t use index(`primary`) where _tidb_rowid=1").Check(testkit.Rows("a 1")) -} - -func (s *testSuite3) TestDoSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t(a int)`) - _, err := tk.Exec(`do 1 in (select * from t)`) - c.Assert(err, IsNil, Commentf("err %v", err)) - tk.MustExec(`insert into t values(1)`) - r, err := tk.Exec(`do 1 in (select * from t)`) - c.Assert(err, IsNil, Commentf("err %v", err)) - c.Assert(r, IsNil, Commentf("result of Do not empty")) -} - -func (s *testSuite3) TestSubqueryTableAlias(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - - tk.MustExec("set sql_mode = ''") - tk.MustGetErrCode("select a, b from (select 1 a) ``, (select 2 b) ``;", mysql.ErrDerivedMustHaveAlias) - tk.MustGetErrCode("select a, b from (select 1 a) `x`, (select 2 b) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select a, b from (select 1 a), (select 2 b);", mysql.ErrDerivedMustHaveAlias) - // ambiguous column name - tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrDerivedMustHaveAlias) - tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonuniqTable) - tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrDerivedMustHaveAlias) - - tk.MustExec("set sql_mode = 'oracle';") - tk.MustQuery("select a, b from (select 1 a) ``, (select 2 b) ``;").Check(testkit.Rows("1 2")) - tk.MustQuery("select a, b from (select 1 a) `x`, (select 2 b) `x`;").Check(testkit.Rows("1 2")) - tk.MustQuery("select a, b from (select 1 a), (select 2 b);").Check(testkit.Rows("1 2")) - // ambiguous column name - tk.MustGetErrCode("select a from (select 1 a) ``, (select 2 a) ``;", mysql.ErrNonUniq) - tk.MustGetErrCode("select a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) - tk.MustGetErrCode("select x.a from (select 1 a) `x`, (select 2 a) `x`;", mysql.ErrNonUniq) - tk.MustGetErrCode("select a from (select 1 a), (select 2 a);", mysql.ErrNonUniq) -} - -func (s *testSerialSuite) TestTSOFail(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists t`) - tk.MustExec(`create table t(a int)`) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockGetTSFail", "return"), IsNil) - ctx := failpoint.WithHook(context.Background(), func(ctx context.Context, fpname string) bool { - return fpname == "github.com/pingcap/tidb/session/mockGetTSFail" - }) - _, err := tk.Se.Execute(ctx, `select * from t`) - c.Assert(err, NotNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockGetTSFail"), IsNil) -} - -func (s *testSuite3) TestSelectHashPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test`) - tk.MustExec(`drop table if exists th`) - tk.MustExec("set @@session.tidb_enable_table_partition = '1';") - tk.MustExec(`create table th (a int, b int) partition by hash(a) partitions 3;`) - defer tk.MustExec(`drop table if exists th`) - tk.MustExec(`insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);`) - tk.MustExec("insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8);") - tk.MustQuery("select b from th order by a").Check(testkit.Rows("-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8")) - tk.MustQuery(" select * from th where a=-2;").Check(testkit.Rows("-2 -2")) - tk.MustQuery(" select * from th where a=5;").Check(testkit.Rows("5 5")) -} - -func (s *testSuiteP1) TestSelectPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.MustExec(`drop table if exists th, tr, tl`) tk.MustExec("set @@session.tidb_enable_list_partition = ON;") tk.MustExec(`create table th (a int, b int) partition by hash(a) partitions 3;`) tk.MustExec(`create table tr (a int, b int) @@ -4744,7 +1333,6 @@ func (s *testSuiteP1) TestSelectPartition(c *C) { partition p1 values in (1,2,10,11,19,20), partition p2 values in (4,12,13,14,18), partition p3 values in (7,8,15,16,null));`) - defer tk.MustExec(`drop table if exists th, tr, tl`) tk.MustExec(`insert into th values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);`) tk.MustExec("insert into th values (-1,-1),(-2,-2),(-3,-3),(-4,-4),(-5,-5),(-6,-6),(-7,-7),(-8,-8);") tk.MustExec(`insert into tr values (-3,-3),(3,3),(4,4),(7,7),(8,8);`) @@ -4762,12 +1350,9 @@ func (s *testSuiteP1) TestSelectPartition(c *C) { tk.MustQuery("select b from tl partition (p0,P3) order by a").Check(testkit.Rows("", "3", "7", "8")) // test select unknown partition error - err := tk.ExecToErr("select b from th partition (p0,p4)") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p4' in table 'th'") - err = tk.ExecToErr("select b from tr partition (r1,r4)") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'r4' in table 'tr'") - err = tk.ExecToErr("select b from tl partition (p0,p4)") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p4' in table 'tl'") + tk.MustGetErrMsg("select b from th partition (p0,p4)", "[table:1735]Unknown partition 'p4' in table 'th'") + tk.MustGetErrMsg("select b from tr partition (r1,r4)", "[table:1735]Unknown partition 'r4' in table 'tr'") + tk.MustGetErrMsg("select b from tl partition (p0,p4)", "[table:1735]Unknown partition 'p4' in table 'tl'") // test select partition table in transaction. tk.MustExec("begin") @@ -4794,8 +1379,10 @@ func (s *testSuiteP1) TestSelectPartition(c *C) { tk.MustQuery("select * from tscalar where c1 in (-1)").Check(testkit.Rows()) } -func (s *testSuiteP1) TestDeletePartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDeletePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t1`) tk.MustExec(`create table t1 (a int) partition by range (a) ( @@ -4814,4875 +1401,1601 @@ func (s *testSuiteP1) TestDeletePartition(c *C) { tk.MustQuery("select * from t1").Check(testkit.Rows("31")) } -func (s *testSuite) TestSelectView(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table view_t (a int,b int)") - tk.MustExec("insert into view_t values(1,2)") - tk.MustExec("create definer='root'@'localhost' view view1 as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view2(c,d) as select * from view_t") - tk.MustExec("create definer='root'@'localhost' view view3(c,d) as select a,b from view_t") - tk.MustExec("create definer='root'@'localhost' view view4 as select * from (select * from (select * from view_t) tb1) tb;") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(c int,d int)") - err := tk.ExecToErr("select * from view1") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") - err = tk.ExecToErr("select * from view2") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") - err = tk.ExecToErr("select * from view3") - c.Assert(err.Error(), Equals, plannercore.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error()) - tk.MustExec("drop table view_t;") - tk.MustExec("create table view_t(a int,b int,c int)") - tk.MustExec("insert into view_t values(1,2,3)") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("alter table view_t drop column a") - tk.MustExec("alter table view_t add column a int after b") - tk.MustExec("update view_t set a=1;") - tk.MustQuery("select * from view1;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view2;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view3;").Check(testkit.Rows("1 2")) - tk.MustQuery("select * from view4;").Check(testkit.Rows("1 2")) - tk.MustExec("drop table view_t;") - tk.MustExec("drop view view1,view2,view3,view4;") - - tk.MustExec("set @@tidb_enable_window_function = 1") - defer func() { - tk.MustExec("set @@tidb_enable_window_function = 0") - }() - tk.MustExec("create table t(a int, b int)") - tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create definer='root'@'localhost' view v as select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") - result := tk.MustQuery("select * from v") - result.Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) - tk.MustExec("drop view v;") -} - -type testSuite2 struct { - *baseTestSuite -} - -func (s *testSuite2) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -type testSuite3 struct { - *baseTestSuite -} - -func (s *testSuite3) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -type testSuite4 struct { - *baseTestSuite -} - -func (s *testSuite4) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -type testSuite5 struct { - *baseTestSuite -} - -func (s *testSuite5) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } -} - -type testSuite6 struct { - *baseTestSuite -} - -func (s *testSuite6) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - } +func TestPrepareLoadData(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustGetErrCode(`prepare stmt from "load data local infile '/tmp/load_data_test.csv' into table test";`, mysql.ErrUnsupportedPs) } -type testSuite7 struct { - *baseTestSuite -} +func TestSetOperation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t1, t2, t3`) + tk.MustExec(`create table t1(a int)`) + tk.MustExec(`create table t2 like t1`) + tk.MustExec(`create table t3 like t1`) + tk.MustExec(`insert into t1 values (1),(1),(2),(3),(null)`) + tk.MustExec(`insert into t2 values (1),(2),(null),(null)`) + tk.MustExec(`insert into t3 values (2),(3)`) -func (s *testSuite7) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } + var input []string + var output []struct { + SQL string + Plan []string + Res []string } -} - -type testSuite8 struct { - *baseTestSuite -} - -func (s *testSuite8) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } + executorSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + }) + tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) } } -type testSerialSuite1 struct { - *baseTestSuite -} +func TestSetOperationOnDiffColType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t1, t2, t3`) + tk.MustExec(`create table t1(a int, b int)`) + tk.MustExec(`create table t2(a int, b varchar(20))`) + tk.MustExec(`create table t3(a int, b decimal(30,10))`) + tk.MustExec(`insert into t1 values (1,1),(1,1),(2,2),(3,3),(null,null)`) + tk.MustExec(`insert into t2 values (1,'1'),(2,'2'),(null,null),(null,'3')`) + tk.MustExec(`insert into t3 values (2,2.1),(3,3)`) -func (s *testSerialSuite1) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show full tables") - for _, tb := range r.Rows() { - tableName := tb[0] - if tb[1] == "VIEW" { - tk.MustExec(fmt.Sprintf("drop view %v", tableName)) - } else if tb[1] == "SEQUENCE" { - tk.MustExec(fmt.Sprintf("drop sequence %v", tableName)) - } else { - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } + var input []string + var output []struct { + SQL string + Plan []string + Res []string } -} - -func (s *testSuiteP2) TestStrToDateBuiltin(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%!') from dual`).Check(testkit.Rows("2019-01-01")) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%f') from dual`).Check(testkit.Rows("2019-01-01 00:00:00.000000")) - tk.MustQuery(`select str_to_date('20190101','%Y%m%d%H%i%s') from dual`).Check(testkit.Rows("2019-01-01 00:00:00")) - tk.MustQuery(`select str_to_date('18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('a18/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('69/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('70/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) - tk.MustQuery(`select str_to_date('8/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) - tk.MustQuery(`select str_to_date('8/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2008-10-22")) - tk.MustQuery(`select str_to_date('18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('a18/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('69/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('70/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("1970-10-22")) - tk.MustQuery(`select str_to_date('018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("0018-10-22")) - tk.MustQuery(`select str_to_date('2018/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('018/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18/10/22','%y0/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18/10/22','%Y0/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18a/10/22','%y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18a/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('20188/10/22','%Y/%m/%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018510522','%Y5%m5%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018^10^22','%Y^%m^%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018@10@22','%Y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018%10%22','%Y%%m%%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018(10(22','%Y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018\10\22','%Y\%m\%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('2018=10=22','%Y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018+10+22','%Y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('2018_10_22','%Y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('69510522','%y5%m5%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('69^10^22','%y^%m^%d') from dual`).Check(testkit.Rows("2069-10-22")) - tk.MustQuery(`select str_to_date('18@10@22','%y@%m@%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18%10%22','%y%%m%%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18(10(22','%y(%m(%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18\10\22','%y\%m\%d') from dual`).Check(testkit.Rows("")) - tk.MustQuery(`select str_to_date('18+10+22','%y+%m+%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18=10=22','%y=%m=%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`select str_to_date('18_10_22','%y_%m_%d') from dual`).Check(testkit.Rows("2018-10-22")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 11:22:33 PM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 23:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33 AM', '%Y-%m-%d %r')`).Check(testkit.Rows("2020-07-04 00:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 12:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 12:22:33")) - tk.MustQuery(`SELECT STR_TO_DATE('2020-07-04 00:22:33', '%Y-%m-%d %T')`).Check(testkit.Rows("2020-07-04 00:22:33")) -} - -func (s *testSuiteP2) TestAddDateBuiltinWithWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") - result := tk.MustQuery(`select date_add('2001-01-00', interval -2 hour);`) - result.Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '2001-01-00'")) -} - -func (s *testSuiteP2) TestIssue27232(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a timestamp)") - tk.MustExec("insert into t values (\"1970-07-23 10:04:59\"), (\"2038-01-19 03:14:07\")") - tk.MustQuery("select * from t where date_sub(a, interval 10 month) = date_sub(\"1970-07-23 10:04:59\", interval 10 month)").Check(testkit.Rows("1970-07-23 10:04:59")) - tk.MustQuery("select * from t where timestampadd(hour, 1, a ) = timestampadd(hour, 1, \"2038-01-19 03:14:07\")").Check(testkit.Rows("2038-01-19 03:14:07")) -} - -func (s *testSuiteP2) TestStrToDateBuiltinWithWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@sql_mode='NO_ZERO_DATE'") - tk.MustExec("use test") - tk.MustQuery(`SELECT STR_TO_DATE('0000-1-01', '%Y-%m-%d');`).Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1411 Incorrect datetime value: '0000-1-01' for function str_to_date")) -} - -func (s *testSuiteP2) TestReadPartitionedTable(c *C) { - // Test three reader on partitioned table. - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists pt") - tk.MustExec("create table pt (a int, b int, index i_b(b)) partition by range (a) (partition p1 values less than (2), partition p2 values less than (4), partition p3 values less than (6))") - for i := 0; i < 6; i++ { - tk.MustExec(fmt.Sprintf("insert into pt values(%d, %d)", i, i)) + executorSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + }) + tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) } - // Table reader - tk.MustQuery("select * from pt order by a").Check(testkit.Rows("0 0", "1 1", "2 2", "3 3", "4 4", "5 5")) - // Index reader - tk.MustQuery("select b from pt where b = 3").Check(testkit.Rows("3")) - // Index lookup - tk.MustQuery("select a from pt where b = 3").Check(testkit.Rows("3")) -} - -func (s *testSplitTable) TestSplitRegion(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t, t1") - tk.MustExec("create table t(a varchar(100),b int, index idx1(b,a))") - tk.MustExec(`split table t index idx1 by (10000,"abcd"),(10000000);`) - _, err := tk.Exec(`split table t index idx1 by ("abcd");`) - c.Assert(err, NotNil) - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.WarnDataTruncated)) - - // Test for split index region. - // Check min value is more than max value. - tk.MustExec(`split table t index idx1 between (0) and (1000000000) regions 10`) - tk.MustGetErrCode(`split table t index idx1 between (2,'a') and (1,'c') regions 10`, errno.ErrInvalidSplitRegionRanges) - - // Check min value is invalid. - _, err = tk.Exec(`split table t index idx1 between () and (1) regions 10`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split index `idx1` region lower value count should more than 0") - - // Check max value is invalid. - _, err = tk.Exec(`split table t index idx1 between (1) and () regions 10`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split index `idx1` region upper value count should more than 0") - - // Check pre-split region num is too large. - _, err = tk.Exec(`split table t index idx1 between (0) and (1000000000) regions 10000`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split index region num exceeded the limit 1000") - - // Check pre-split region num 0 is invalid. - _, err = tk.Exec(`split table t index idx1 between (0) and (1000000000) regions 0`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split index region num should more than 0") - - // Test truncate error msg. - _, err = tk.Exec(`split table t index idx1 between ("aa") and (1000000000) regions 0`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[types:1265]Incorrect value: 'aa' for column 'b'") - - // Test for split table region. - tk.MustExec(`split table t between (0) and (1000000000) regions 10`) - // Check the lower value is more than the upper value. - tk.MustGetErrCode(`split table t between (2) and (1) regions 10`, errno.ErrInvalidSplitRegionRanges) - - // Check the lower value is invalid. - _, err = tk.Exec(`split table t between () and (1) regions 10`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split table region lower value count should be 1") - - // Check upper value is invalid. - _, err = tk.Exec(`split table t between (1) and () regions 10`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split table region upper value count should be 1") - - // Check pre-split region num is too large. - _, err = tk.Exec(`split table t between (0) and (1000000000) regions 10000`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split table region num exceeded the limit 1000") - - // Check pre-split region num 0 is invalid. - _, err = tk.Exec(`split table t between (0) and (1000000000) regions 0`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Split table region num should more than 0") - - // Test truncate error msg. - _, err = tk.Exec(`split table t between ("aa") and (1000000000) regions 10`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[types:1265]Incorrect value: 'aa' for column '_tidb_rowid'") - - // Test split table region step is too small. - tk.MustGetErrCode(`split table t between (0) and (100) regions 10`, errno.ErrInvalidSplitRegionRanges) - - // Test split region by syntax. - tk.MustExec(`split table t by (0),(1000),(1000000)`) - - // Test split region twice to test for multiple batch split region requests. - tk.MustExec("create table t1(a int, b int)") - tk.MustQuery("split table t1 between(0) and (10000) regions 10;").Check(testkit.Rows("9 1")) - tk.MustQuery("split table t1 between(10) and (10010) regions 5;").Check(testkit.Rows("4 1")) - - // Test split region for partition table. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int,b int) partition by hash(a) partitions 5;") - tk.MustQuery("split table t between (0) and (1000000) regions 5;").Check(testkit.Rows("20 1")) - // Test for `split for region` syntax. - tk.MustQuery("split region for partition table t between (1000000) and (100000000) regions 10;").Check(testkit.Rows("45 1")) - - // Test split region for partition table with specified partition. - tk.MustQuery("split table t partition (p1,p2) between (100000000) and (1000000000) regions 5;").Check(testkit.Rows("8 1")) - // Test for `split for region` syntax. - tk.MustQuery("split region for partition table t partition (p3,p4) between (100000000) and (1000000000) regions 5;").Check(testkit.Rows("8 1")) } -func (s *testSplitTable) TestSplitRegionEdgeCase(c *C) { - tk := testkit.NewTestKit(c, s.store) +// issue-23038: wrong key range of index scan for year column +func TestIndexScanWithYearCol(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") - - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a bigint(20) auto_increment primary key);") - tk.MustExec("split table t between (-9223372036854775808) and (9223372036854775807) regions 16;") - - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int(20) auto_increment primary key);") - tk.MustGetErrCode("split table t between (-9223372036854775808) and (9223372036854775807) regions 16;", errno.ErrDataOutOfRange) -} - -func (s *testSplitTable) TestClusterIndexSplitTableIntegration(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("drop database if exists test_cluster_index_index_split_table_integration;") - tk.MustExec("create database test_cluster_index_index_split_table_integration;") - tk.MustExec("use test_cluster_index_index_split_table_integration;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - - tk.MustExec("create table t (a varchar(255), b double, c int, primary key (a, b));") - - // Value list length not match. - lowerMsg := "Split table region lower value count should be 2" - upperMsg := "Split table region upper value count should be 2" - tk.MustGetErrMsg("split table t between ('aaa') and ('aaa', 100.0) regions 10;", lowerMsg) - tk.MustGetErrMsg("split table t between ('aaa', 1.0) and ('aaa', 100.0, 11) regions 10;", upperMsg) - - // Value type not match. - errMsg := "[types:1265]Incorrect value: 'aaa' for column 'b'" - tk.MustGetErrMsg("split table t between ('aaa', 0.0) and (100.0, 'aaa') regions 10;", errMsg) - - // lower bound >= upper bound. - errMsg = "[executor:8212]Failed to split region ranges: Split table `t` region lower value (aaa,0) should less than the upper value (aaa,0)" - tk.MustGetErrMsg("split table t between ('aaa', 0.0) and ('aaa', 0.0) regions 10;", errMsg) - errMsg = "[executor:8212]Failed to split region ranges: Split table `t` region lower value (bbb,0) should less than the upper value (aaa,0)" - tk.MustGetErrMsg("split table t between ('bbb', 0.0) and ('aaa', 0.0) regions 10;", errMsg) - - // Exceed limit 1000. - errMsg = "Split table region num exceeded the limit 1000" - tk.MustGetErrMsg("split table t between ('aaa', 0.0) and ('aaa', 0.1) regions 100000;", errMsg) - - // Split on null values. - errMsg = "[planner:1048]Column 'a' cannot be null" - tk.MustGetErrMsg("split table t between (null, null) and (null, null) regions 1000;", errMsg) - tk.MustGetErrMsg("split table t by (null, null);", errMsg) - - // Success. - tk.MustExec("split table t between ('aaa', 0.0) and ('aaa', 100.0) regions 10;") - tk.MustExec("split table t by ('aaa', 0.0), ('aaa', 20.0), ('aaa', 100.0);") - tk.MustExec("split table t by ('aaa', 100.0), ('qqq', 20.0), ('zzz', 100.0), ('zzz', 1000.0);") - - tk.MustExec("drop table t;") - tk.MustExec("create table t (a int, b int, c int, d int, primary key(a, c, d));") - tk.MustQuery("split table t between (0, 0, 0) and (0, 0, 1) regions 1000;").Check(testkit.Rows("999 1")) - - tk.MustExec("drop table t;") - tk.MustExec("create table t (a int, b int, c int, d int, primary key(d, a, c));") - tk.MustQuery("split table t by (0, 0, 0), (1, 2, 3), (65535, 65535, 65535);").Check(testkit.Rows("3 1")) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a varchar(255), b decimal, c int, primary key (a, b));") - errMsg = "[types:1265]Incorrect value: '' for column 'b'" - tk.MustGetErrMsg("split table t by ('aaa', '')", errMsg) -} + tk.MustExec("create table t (c1 year(4), c2 int, key(c1));") + tk.MustExec("insert into t values(2001, 1);") -func (s *testSplitTable) TestClusterIndexShowTableRegion(c *C) { - tk := testkit.NewTestKit(c, s.store) - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("set global tidb_scatter_region = 1") - tk.MustExec("drop database if exists cluster_index_regions;") - tk.MustExec("create database cluster_index_regions;") - tk.MustExec("use cluster_index_regions;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("create table t (a int, b int, c int, primary key(a, b));") - tk.MustExec("insert t values (1, 1, 1), (2, 2, 2);") - tk.MustQuery("split table t between (1, 0) and (2, 3) regions 2;").Check(testkit.Rows("1 1")) - rows := tk.MustQuery("show table t regions").Rows() - tbl := testGetTableByName(c, tk.Se, "cluster_index_regions", "t") - // Check the region start key. - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_", tbl.Meta().ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_r_03800000000000000183800000000000", tbl.Meta().ID)) - - tk.MustExec("drop table t;") - tk.MustExec("create table t (a int, b int);") - tk.MustQuery("split table t between (0) and (100000) regions 2;").Check(testkit.Rows("1 1")) - rows = tk.MustQuery("show table t regions").Rows() - tbl = testGetTableByName(c, tk.Se, "cluster_index_regions", "t") - // Check the region start key is int64. - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_", tbl.Meta().ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_r_50000", tbl.Meta().ID)) + var input []string + var output []struct { + SQL string + Plan []string + Res []string + } + executorSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + }) + tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) + } } -func (s *testSuiteWithData) TestClusterIndexOuterJoinElimination(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterIndexOuterJoinElimination(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("create table t (a int, b int, c int, primary key(a,b))") rows := tk.MustQuery(`explain format = 'brief' select t1.a from t t1 left join t t2 on t1.a = t2.a and t1.b = t2.b`).Rows() - rowStrs := s.testData.ConvertRowsToStrings(rows) + rowStrs := testdata.ConvertRowsToStrings(rows) for _, row := range rowStrs { // outer join has been eliminated. - c.Assert(strings.Index(row, "Join"), Equals, -1) + require.NotContains(t, row, "Join") } } -func (s *testSplitTable) TestShowTableRegion(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPlanReplayerDumpSingle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t_regions") - tk.MustExec("set global tidb_scatter_region = 1") - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("create table t_regions (a int key, b int, c int, index idx(b), index idx2(c))") - _, err := tk.Exec("split partition table t_regions partition (p1,p2) index idx between (0) and (20000) regions 2;") - c.Assert(err.Error(), Equals, plannercore.ErrPartitionClauseOnNonpartitioned.Error()) - - // Test show table regions. - tk.MustQuery(`split table t_regions between (-10000) and (10000) regions 4;`).Check(testkit.Rows("4 1")) - re := tk.MustQuery("show table t_regions regions") - - // Test show table regions and split table on global temporary table. - tk.MustExec("drop table if exists t_regions_temporary_table") - tk.MustExec("create global temporary table t_regions_temporary_table (a int key, b int, c int, index idx(b), index idx2(c)) ON COMMIT DELETE ROWS;") - // Test show table regions. - _, err = tk.Exec("show table t_regions_temporary_table regions") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("show table regions").Error()) - // Test split table. - _, err = tk.Exec("split table t_regions_temporary_table between (-10000) and (10000) regions 4;") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) - _, err = tk.Exec("split partition table t_regions_temporary_table partition (p1,p2) index idx between (0) and (20000) regions 2;") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) - tk.MustExec("drop table if exists t_regions_temporary_table") - // Test pre split regions - _, err = tk.Exec("create global temporary table temporary_table_pre_split(id int ) pre_split_regions=2 ON COMMIT DELETE ROWS;") - c.Assert(err.Error(), Equals, ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) - - // Test show table regions and split table on local temporary table - tk.MustExec("drop table if exists t_regions_local_temporary_table") - tk.MustExec("create temporary table t_regions_local_temporary_table (a int key, b int, c int, index idx(b), index idx2(c));") - // Test show table regions. - _, err = tk.Exec("show table t_regions_local_temporary_table regions") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("show table regions").Error()) - // Test split table. - _, err = tk.Exec("split table t_regions_local_temporary_table between (-10000) and (10000) regions 4;") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) - _, err = tk.Exec("split partition table t_regions_local_temporary_table partition (p1,p2) index idx between (0) and (20000) regions 2;") - c.Assert(err.Error(), Equals, plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) - tk.MustExec("drop table if exists t_regions_local_temporary_table") - // Test pre split regions - _, err = tk.Exec("create temporary table local_temporary_table_pre_split(id int ) pre_split_regions=2;") - c.Assert(err.Error(), Equals, ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) - - rows := re.Rows() - // Table t_regions should have 5 regions now. - // 4 regions to store record data. - // 1 region to store index data. - c.Assert(len(rows), Equals, 5) - c.Assert(len(rows[0]), Equals, 11) - tbl := testGetTableByName(c, tk.Se, "test", "t_regions") - // Check the region start key. - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID)) - c.Assert(rows[4][2], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) - - // Test show table index regions. - tk.MustQuery(`split table t_regions index idx between (-1000) and (1000) regions 4;`).Check(testkit.Rows("4 1")) - re = tk.MustQuery("show table t_regions index idx regions") - rows = re.Rows() - // The index `idx` of table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 4) - // Check the region start key. - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d.*", tbl.Meta().ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - - re = tk.MustQuery("show table t_regions regions") - rows = re.Rows() - // The index `idx` of table t_regions should have 9 regions now. - // 4 regions to store record data. - // 4 region to store index idx data. - // 1 region to store index idx2 data. - c.Assert(len(rows), Equals, 9) - // Check the region start key. - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID)) - c.Assert(rows[4][1], Matches, fmt.Sprintf("t_%d_", tbl.Meta().ID)) - c.Assert(rows[5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[7][2], Equals, fmt.Sprintf("t_%d_i_2_", tbl.Meta().ID)) - c.Assert(rows[8][2], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) - - // Test unsigned primary key and wait scatter finish. - tk.MustExec("drop table if exists t_regions") - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("create table t_regions (a int unsigned key, b int, index idx(b))") - - // Test show table regions. - tk.MustExec(`set @@session.tidb_wait_split_region_finish=1;`) - tk.MustQuery(`split table t_regions by (2500),(5000),(7500);`).Check(testkit.Rows("3 1")) - re = tk.MustQuery("show table t_regions regions") - rows = re.Rows() - // Table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 4) - tbl = testGetTableByName(c, tk.Se, "test", "t_regions") - // Check the region start key. - c.Assert(rows[0][1], Matches, "t_.*") - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_2500", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_7500", tbl.Meta().ID)) - - // Test show table index regions. - tk.MustQuery(`split table t_regions index idx by (250),(500),(750);`).Check(testkit.Rows("4 1")) - re = tk.MustQuery("show table t_regions index idx regions") - rows = re.Rows() - // The index `idx` of table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 4) - // Check the region start key. - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", tbl.Meta().ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) - - // Test show table regions for partition table when disable split region when create table. - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) - tk.MustExec("drop table if exists partition_t;") - tk.MustExec("set @@session.tidb_enable_table_partition = '1';") - tk.MustExec("create table partition_t (a int, b int,index(a)) partition by hash (a) partitions 3") - re = tk.MustQuery("show table partition_t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][1], Matches, "t_.*") - - // Test show table regions for partition table when enable split region when create table. - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk.MustExec("set @@global.tidb_scatter_region=1;") - tk.MustExec("drop table if exists partition_t;") - tk.MustExec("create table partition_t (a int, b int,index(a)) partition by hash (a) partitions 3") - re = tk.MustQuery("show table partition_t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 3) - tbl = testGetTableByName(c, tk.Se, "test", "partition_t") - partitionDef := tbl.Meta().GetPartitionInfo().Definitions - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[0].ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[1].ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[2].ID)) - - // Test split partition region when add new partition. - tk.MustExec("drop table if exists partition_t;") - tk.MustExec(`create table partition_t (a int, b int,index(a)) PARTITION BY RANGE (a) ( - PARTITION p0 VALUES LESS THAN (10), - PARTITION p1 VALUES LESS THAN (20), - PARTITION p2 VALUES LESS THAN (30));`) - tk.MustExec(`alter table partition_t add partition ( partition p3 values less than (40), partition p4 values less than (50) );`) - re = tk.MustQuery("show table partition_t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 5) - tbl = testGetTableByName(c, tk.Se, "test", "partition_t") - partitionDef = tbl.Meta().GetPartitionInfo().Definitions - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[0].ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[1].ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[2].ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[3].ID)) - c.Assert(rows[4][1], Matches, fmt.Sprintf("t_%d_.*", partitionDef[4].ID)) - - // Test pre-split table region when create table. - tk.MustExec("drop table if exists t_pre") - tk.MustExec("create table t_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2;") - re = tk.MustQuery("show table t_pre regions") - rows = re.Rows() - // Table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 4) - tbl = testGetTableByName(c, tk.Se, "test", "t_pre") - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID)) - - // Test pre-split table region when create table. - tk.MustExec("drop table if exists pt_pre") - tk.MustExec("create table pt_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2 partition by hash(a) partitions 3;") - re = tk.MustQuery("show table pt_pre regions") - rows = re.Rows() - // Table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 12) - tbl = testGetTableByName(c, tk.Se, "test", "pt_pre") - pi := tbl.Meta().GetPartitionInfo().Definitions - c.Assert(len(pi), Equals, 3) - for i, p := range pi { - c.Assert(rows[1+4*i][1], Equals, fmt.Sprintf("t_%d_r_2305843009213693952", p.ID)) - c.Assert(rows[2+4*i][1], Equals, fmt.Sprintf("t_%d_r_4611686018427387904", p.ID)) - c.Assert(rows[3+4*i][1], Equals, fmt.Sprintf("t_%d_r_6917529027641081856", p.ID)) - } - - defer atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) - - // Test split partition table. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int,b int) partition by hash(a) partitions 5;") - tk.MustQuery("split table t between (0) and (4000000) regions 4;").Check(testkit.Rows("15 1")) - re = tk.MustQuery("show table t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 20) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(tbl.Meta().GetPartitionInfo().Definitions), Equals, 5) - for i, p := range tbl.Meta().GetPartitionInfo().Definitions { - c.Assert(rows[i*4+0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*4+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*4+2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*4+3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - } - - // Test split region for partition table with specified partition. - tk.MustQuery("split table t partition (p4) between (1000000) and (2000000) regions 5;").Check(testkit.Rows("4 1")) - re = tk.MustQuery("show table t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 24) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(tbl.Meta().GetPartitionInfo().Definitions), Equals, 5) - for i := 0; i < 4; i++ { - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[i*4+0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*4+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*4+2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*4+3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - } - for i := 4; i < 5; i++ { - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[i*4+0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*4+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*4+2][1], Equals, fmt.Sprintf("t_%d_r_1200000", p.ID)) - c.Assert(rows[i*4+3][1], Equals, fmt.Sprintf("t_%d_r_1400000", p.ID)) - c.Assert(rows[i*4+4][1], Equals, fmt.Sprintf("t_%d_r_1600000", p.ID)) - c.Assert(rows[i*4+5][1], Equals, fmt.Sprintf("t_%d_r_1800000", p.ID)) - c.Assert(rows[i*4+6][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*4+7][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - } - - // Test for show table partition regions. - for i := 0; i < 4; i++ { - re = tk.MustQuery(fmt.Sprintf("show table t partition (p%v) regions", i)) - rows = re.Rows() - c.Assert(len(rows), Equals, 4) - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - } - re = tk.MustQuery("show table t partition (p0, p4) regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 12) - p := tbl.Meta().GetPartitionInfo().Definitions[0] - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - p = tbl.Meta().GetPartitionInfo().Definitions[4] - c.Assert(rows[4][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[5][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[6][1], Equals, fmt.Sprintf("t_%d_r_1200000", p.ID)) - c.Assert(rows[7][1], Equals, fmt.Sprintf("t_%d_r_1400000", p.ID)) - c.Assert(rows[8][1], Equals, fmt.Sprintf("t_%d_r_1600000", p.ID)) - c.Assert(rows[9][1], Equals, fmt.Sprintf("t_%d_r_1800000", p.ID)) - c.Assert(rows[10][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[11][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - // Test for duplicate partition names. - re = tk.MustQuery("show table t partition (p0, p0, p0) regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 4) - p = tbl.Meta().GetPartitionInfo().Definitions[0] - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - - // Test split partition table index. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int,b int,index idx(a)) partition by hash(a) partitions 5;") - tk.MustQuery("split table t between (0) and (4000000) regions 4;").Check(testkit.Rows("20 1")) - tk.MustQuery("split table t index idx between (0) and (4000000) regions 4;").Check(testkit.Rows("20 1")) - re = tk.MustQuery("show table t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 40) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(tbl.Meta().GetPartitionInfo().Definitions), Equals, 5) - for i := 0; i < 5; i++ { - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[i*8+0][1], Equals, fmt.Sprintf("t_%d_r", p.ID)) - c.Assert(rows[i*8+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*8+2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*8+3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - c.Assert(rows[i*8+4][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*8+5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+7][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - } - - // Test split index region for partition table with specified partition. - tk.MustQuery("split table t partition (p4) index idx between (0) and (1000000) regions 5;").Check(testkit.Rows("4 1")) - re = tk.MustQuery("show table t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 44) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(len(tbl.Meta().GetPartitionInfo().Definitions), Equals, 5) - for i := 0; i < 4; i++ { - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[i*8+0][1], Equals, fmt.Sprintf("t_%d_r", p.ID)) - c.Assert(rows[i*8+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*8+2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*8+3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - c.Assert(rows[i*8+4][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*8+5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+7][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - } - for i := 4; i < 5; i++ { - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[i*8+0][1], Equals, fmt.Sprintf("t_%d_r", p.ID)) - c.Assert(rows[i*8+1][1], Equals, fmt.Sprintf("t_%d_r_1000000", p.ID)) - c.Assert(rows[i*8+2][1], Equals, fmt.Sprintf("t_%d_r_2000000", p.ID)) - c.Assert(rows[i*8+3][1], Equals, fmt.Sprintf("t_%d_r_3000000", p.ID)) - c.Assert(rows[i*8+4][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[i*8+5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+7][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+8][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+9][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+10][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[i*8+11][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - } + tk.MustExec("drop table if exists t_dump_single") + tk.MustExec("create table t_dump_single(a int)") + res := tk.MustQuery("plan replayer dump explain select * from t_dump_single") + path := testdata.ConvertRowsToStrings(res.Rows()) - // Test show table partition region on unknown-partition. - err = tk.QueryToErr("show table t partition (p_unknown) index idx regions") - c.Assert(terror.ErrorEqual(err, table.ErrUnknownPartition), IsTrue) - - // Test show table partition index. - for i := 0; i < 4; i++ { - re = tk.MustQuery(fmt.Sprintf("show table t partition (p%v) index idx regions", i)) - rows = re.Rows() - c.Assert(len(rows), Equals, 4) - p := tbl.Meta().GetPartitionInfo().Definitions[i] - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) + reader, err := zip.OpenReader(filepath.Join(domain.GetPlanReplayerDirName(), path[0])) + require.NoError(t, err) + defer func() { require.NoError(t, reader.Close()) }() + for _, file := range reader.File { + require.True(t, checkFileName(file.Name)) } - re = tk.MustQuery("show table t partition (p3,p4) index idx regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 12) - p = tbl.Meta().GetPartitionInfo().Definitions[3] - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[1][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - p = tbl.Meta().GetPartitionInfo().Definitions[4] - c.Assert(rows[4][1], Equals, fmt.Sprintf("t_%d_", p.ID)) - c.Assert(rows[5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[7][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[8][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[9][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[10][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - c.Assert(rows[11][1], Matches, fmt.Sprintf("t_%d_i_1_.*", p.ID)) - - // Test split for the second index. - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int,b int,index idx(a), index idx2(b))") - tk.MustQuery("split table t index idx2 between (0) and (4000000) regions 2;").Check(testkit.Rows("3 1")) - re = tk.MustQuery("show table t regions") - rows = re.Rows() - c.Assert(len(rows), Equals, 4) - tbl = testGetTableByName(c, tk.Se, "test", "t") - c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_i_3_", tbl.Meta().ID)) - c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_", tbl.Meta().ID)) - c.Assert(rows[2][1], Matches, fmt.Sprintf("t_%d_i_2_.*", tbl.Meta().ID)) - c.Assert(rows[3][1], Matches, fmt.Sprintf("t_%d_i_2_.*", tbl.Meta().ID)) - - // Test show table partition region on non-partition table. - err = tk.QueryToErr("show table t partition (p3,p4) index idx regions") - c.Assert(terror.ErrorEqual(err, plannercore.ErrPartitionClauseOnNonpartitioned), IsTrue) -} - -func testGetTableByName(c *C, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - c.Assert(err, IsNil) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - c.Assert(err, IsNil) - return tbl } -func (s *testSuiteP2) TestIssue10435(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropColWithPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(i int, j int, k int)") - tk.MustExec("insert into t1 VALUES (1,1,1),(2,2,2),(3,3,3),(4,4,4)") - tk.MustExec("INSERT INTO t1 SELECT 10*i,j,5*j FROM t1 UNION SELECT 20*i,j,5*j FROM t1 UNION SELECT 30*i,j,5*j FROM t1") - - tk.MustExec("set @@session.tidb_enable_window_function=1") - tk.MustQuery("SELECT SUM(i) OVER W FROM t1 WINDOW w AS (PARTITION BY j ORDER BY i) ORDER BY 1+SUM(i) OVER w").Check( - testkit.Rows("1", "2", "3", "4", "11", "22", "31", "33", "44", "61", "62", "93", "122", "124", "183", "244"), - ) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key, c1 int, c2 int, c3 int, index idx1(c1, c2), index idx2(c3))") + tk.MustExec("set global tidb_enable_change_multi_schema = off") + tk.MustGetErrMsg("alter table t drop column id", "[ddl:8200]Unsupported drop integer primary key") + tk.MustGetErrMsg("alter table t drop column c1", "[ddl:8200]can't drop column c1 with composite index covered or Primary Key covered now") + tk.MustGetErrMsg("alter table t drop column c3", "[ddl:8200]can't drop column c3 with tidb_enable_change_multi_schema is disable") + tk.MustExec("set global tidb_enable_change_multi_schema = on") + tk.MustExec("alter table t drop column c3") } -func (s *testSerialSuite2) TestUnsignedFeedback(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUnsignedFeedback(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() statistics.FeedbackProbability.Store(1.0) defer func() { statistics.FeedbackProbability.Store(oriProbability) }() tk.MustExec("use test") - tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint unsigned, b int, primary key(a))") tk.MustExec("insert into t values (1,1),(2,2)") tk.MustExec("analyze table t") tk.MustQuery("select count(distinct b) from t").Check(testkit.Rows("2")) result := tk.MustQuery("explain analyze select count(distinct b) from t") - c.Assert(result.Rows()[2][4], Equals, "table:t") - c.Assert(result.Rows()[2][6], Equals, "keep order:false") -} - -func (s *testSuiteWithCliBaseCharset) TestCharsetFeature(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustQuery("show charset").Check(testkit.Rows( - "ascii US ASCII ascii_bin 1", - "binary binary binary 1", - "gbk Chinese Internal Code Specification gbk_chinese_ci 2", - "latin1 Latin1 latin1_bin 1", - "utf8 UTF-8 Unicode utf8_bin 3", - "utf8mb4 UTF-8 Unicode utf8mb4_bin 4", - )) - tk.MustQuery("show collation").Check(testkit.Rows( - "ascii_bin ascii 65 Yes Yes 1", - "binary binary 63 Yes Yes 1", - "gbk_bin gbk 87 Yes 1", - "gbk_chinese_ci gbk 28 Yes Yes 1", - "latin1_bin latin1 47 Yes Yes 1", - "utf8_bin utf8 83 Yes Yes 1", - "utf8_general_ci utf8 33 Yes 1", - "utf8_unicode_ci utf8 192 Yes 1", - "utf8mb4_bin utf8mb4 46 Yes Yes 1", - "utf8mb4_general_ci utf8mb4 45 Yes 1", - "utf8mb4_unicode_ci utf8mb4 224 Yes 1", - )) - - tk.MustExec("set names gbk;") - tk.MustQuery("select @@character_set_connection;").Check(testkit.Rows("gbk")) - tk.MustQuery("select @@collation_connection;").Check(testkit.Rows("gbk_chinese_ci")) - tk.MustExec("set @@character_set_client=gbk;") - tk.MustQuery("select @@character_set_client;").Check(testkit.Rows("gbk")) - tk.MustExec("set names utf8mb4;") - tk.MustExec("set @@character_set_connection=gbk;") - tk.MustQuery("select @@character_set_connection;").Check(testkit.Rows("gbk")) - tk.MustQuery("select @@collation_connection;").Check(testkit.Rows("gbk_chinese_ci")) - - tk.MustGetErrCode("select _gbk 'a';", errno.ErrUnknownCharacterSet) - - tk.MustExec("use test") - tk.MustExec("create table t1(a char(10) charset gbk);") - tk.MustExec("create table t2(a char(10) charset gbk collate gbk_bin);") - tk.MustExec("create table t3(a char(10)) charset gbk;") - tk.MustExec("alter table t3 add column b char(10) charset gbk;") - tk.MustQuery("show create table t3").Check(testkit.Rows("t3 CREATE TABLE `t3` (\n" + - " `a` char(10) DEFAULT NULL,\n" + - " `b` char(10) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci", - )) - tk.MustExec("create table t4(a char(10));") - tk.MustExec("alter table t4 add column b char(10) charset gbk;") - tk.MustQuery("show create table t4").Check(testkit.Rows("t4 CREATE TABLE `t4` (\n" + - " `a` char(10) DEFAULT NULL,\n" + - " `b` char(10) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", - )) - - tk.MustExec("create database test_gbk charset gbk;") - tk.MustExec("use test_gbk") - tk.MustExec("create table t1(a char(10));") - tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + - " `a` char(10) DEFAULT NULL\n" + - ") ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci", - )) - - collate.SetNewCollationEnabledForTest(false) - tk.MustQuery("show charset").Check(testkit.Rows( - "ascii US ASCII ascii_bin 1", - "binary binary binary 1", - "gbk Chinese Internal Code Specification gbk_chinese_ci 2", - "latin1 Latin1 latin1_bin 1", - "utf8 UTF-8 Unicode utf8_bin 3", - "utf8mb4 UTF-8 Unicode utf8mb4_bin 4", - )) - tk.MustQuery("show collation").Check(testkit.Rows( - "utf8mb4_bin utf8mb4 46 Yes Yes 1", - "latin1_bin latin1 47 Yes Yes 1", - "binary binary 63 Yes Yes 1", - "ascii_bin ascii 65 Yes Yes 1", - "utf8_bin utf8 83 Yes Yes 1", - )) + require.Equal(t, "table:t", result.Rows()[2][4]) + require.Equal(t, "keep order:false", result.Rows()[2][6]) } -func (s *testSuiteWithCliBaseCharset) TestCharsetFeatureCollation(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t" + - "(ascii_char char(10) character set ascii," + - "gbk_char char(10) character set gbk collate gbk_bin," + - "latin_char char(10) character set latin1," + - "utf8mb4_char char(10) character set utf8mb4)", - ) - tk.MustExec("insert into t values ('a', 'a', 'a', 'a'), ('a', 'å•Š', '€', 'ã…‚');") - tk.MustQuery("select collation(concat(ascii_char, gbk_char)) from t;").Check(testkit.Rows("gbk_bin", "gbk_bin")) - tk.MustQuery("select collation(concat(gbk_char, ascii_char)) from t;").Check(testkit.Rows("gbk_bin", "gbk_bin")) - tk.MustQuery("select collation(concat(utf8mb4_char, gbk_char)) from t;").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin")) - tk.MustQuery("select collation(concat(gbk_char, utf8mb4_char)) from t;").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin")) - tk.MustQuery("select collation(concat('å•Š', convert('å•Š' using gbk) collate gbk_bin));").Check(testkit.Rows("gbk_bin")) - tk.MustQuery("select collation(concat(_latin1 'a', convert('å•Š' using gbk) collate gbk_bin));").Check(testkit.Rows("gbk_bin")) - - tk.MustGetErrCode("select collation(concat(latin_char, gbk_char)) from t;", mysql.ErrCantAggregate2collations) - tk.MustGetErrCode("select collation(concat(convert('€' using latin1), convert('å•Š' using gbk) collate gbk_bin));", mysql.ErrCantAggregate2collations) - tk.MustGetErrCode("select collation(concat(utf8mb4_char, gbk_char collate gbk_bin)) from t;", mysql.ErrCantAggregate2collations) - tk.MustGetErrCode("select collation(concat('ã…‚', convert('å•Š' using gbk) collate gbk_bin));", mysql.ErrCantAggregate2collations) - tk.MustGetErrCode("select collation(concat(ascii_char collate ascii_bin, gbk_char)) from t;", mysql.ErrCantAggregate2collations) -} +func TestAlterTableComment(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite2) TestIssue23567(c *C) { - tk := testkit.NewTestKit(c, s.store) - oriProbability := statistics.FeedbackProbability.Load() - statistics.FeedbackProbability.Store(1.0) - defer func() { statistics.FeedbackProbability.Store(oriProbability) }() - failpoint.Enable("github.com/pingcap/tidb/statistics/feedbackNoNDVCollect", `return("")`) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a bigint unsigned, b int, primary key(a))") - tk.MustExec("insert into t values (1, 1), (2, 2)") - tk.MustExec("analyze table t") - // The SQL should not panic. - tk.MustQuery("select count(distinct b) from t") - failpoint.Disable("github.com/pingcap/tidb/statistics/feedbackNoNDVCollect") + tk.MustExec("drop table if exists t_1") + tk.MustExec("create table t_1 (c1 int, c2 int, c3 int default 1, index (c1)) comment = 'test table';") + tk.MustExec("alter table `t_1` comment 'this is table comment';") + tk.MustQuery("select table_comment from information_schema.tables where table_name = 't_1';").Check(testkit.Rows("this is table comment")) + tk.MustExec("alter table `t_1` comment 'table t comment';") + tk.MustQuery("select table_comment from information_schema.tables where table_name = 't_1';").Check(testkit.Rows("table t comment")) } -func (s *testSuite) TestSummaryFailedUpdate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTimezonePushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int as(-a))") - tk.MustExec("insert into t(a) values(1), (3), (7)") - sm := &mockSessionManager1{ - PS: make([]*util.ProcessInfo, 0), - } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionCancel - }) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("set @@tidb_mem_quota_query=1") - err := tk.ExecToErr("update t set t.a = t.a - 1 where t.a in (select a from t where a < 4)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - tk.MustExec("set @@tidb_mem_quota_query=1000000000") - tk.MustQuery("select stmt_type from information_schema.statements_summary where digest_text = 'update `t` set `t` . `a` = `t` . `a` - ? where `t` . `a` in ( select `a` from `t` where `a` < ? )'").Check(testkit.Rows("Update")) -} + tk.MustExec("create table t (ts timestamp)") + defer tk.MustExec("drop table t") + tk.MustExec(`insert into t values ("2018-09-13 10:02:06")`) -func (s *testSuite) TestOOMPanicAction(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key, b double);") - tk.MustExec("insert into t values (1,1)") - sm := &mockSessionManager1{ - PS: make([]*util.ProcessInfo, 0), - } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionCancel + systemTZ := timeutil.SystemLocation() + require.NotEqual(t, "System", systemTZ.String()) + require.NotEqual(t, "Local", systemTZ.String()) + ctx := context.Background() + count := 0 + ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { + count += 1 + dagReq := new(tipb.DAGRequest) + require.NoError(t, proto.Unmarshal(req.Data, dagReq)) + require.Equal(t, systemTZ.String(), dagReq.GetTimeZoneName()) }) - tk.MustExec("set @@tidb_mem_quota_query=1;") - err := tk.QueryToErr("select sum(b) from t group by a;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - - // Test insert from select oom panic. - tk.MustExec("drop table if exists t,t1") - tk.MustExec("create table t (a bigint);") - tk.MustExec("create table t1 (a bigint);") - tk.MustExec("set @@tidb_mem_quota_query=200;") - _, err = tk.Exec("insert into t1 values (1),(2),(3),(4),(5);") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - _, err = tk.Exec("replace into t1 values (1),(2),(3),(4),(5);") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - tk.MustExec("set @@tidb_mem_quota_query=10000") - tk.MustExec("insert into t1 values (1),(2),(3),(4),(5);") - tk.MustExec("set @@tidb_mem_quota_query=10;") - _, err = tk.Exec("insert into t select a from t1 order by a desc;") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - _, err = tk.Exec("replace into t select a from t1 order by a desc;") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - - tk.MustExec("set @@tidb_mem_quota_query=10000") - tk.MustExec("insert into t values (1),(2),(3),(4),(5);") - // Set the memory quota to 244 to make this SQL panic during the DeleteExec - // instead of the TableReaderExec. - tk.MustExec("set @@tidb_mem_quota_query=244;") - _, err = tk.Exec("delete from t") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - - tk.MustExec("set @@tidb_mem_quota_query=10000;") - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 values(1)") - tk.MustExec("insert into t values (1),(2),(3),(4),(5);") - tk.MustExec("set @@tidb_mem_quota_query=244;") - _, err = tk.Exec("delete t, t1 from t join t1 on t.a = t1.a") - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") - - tk.MustExec("set @@tidb_mem_quota_query=100000;") - tk.MustExec("truncate table t") - tk.MustExec("insert into t values(1),(2),(3)") - // set the memory to quota to make the SQL panic during UpdateExec instead - // of TableReader. - tk.MustExec("set @@tidb_mem_quota_query=244;") - _, err = tk.Exec("update t set a = 4") - c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*") -} - -type testRecoverTable struct { - store kv.Storage - dom *domain.Domain - cluster testutils.Cluster - cli *regionProperityClient -} - -func (s *testRecoverTable) SetUpSuite(c *C) { - cli := ®ionProperityClient{} - hijackClient := func(c tikv.Client) tikv.Client { - cli.Client = c - return cli - } - s.cli = cli - - var err error - s.store, err = mockstore.NewMockStore( - mockstore.WithClientHijacker(hijackClient), - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} - -func (s *testRecoverTable) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *testRecoverTable) TestRecoverTable(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange") - c.Assert(err, IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_recover") - tk.MustExec("use test_recover") - tk.MustExec("drop table if exists t_recover") - tk.MustExec("create table t_recover (a int);") - - timeBeforeDrop, timeAfterDrop, safePointSQL, resetGC := testkit.MockGC(tk) - defer resetGC() - - tk.MustExec("insert into t_recover values (1),(2),(3)") - tk.MustExec("drop table t_recover") - - // if GC safe point is not exists in mysql.tidb - _, err := tk.Exec("recover table t_recover") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "can not get 'tikv_gc_safe_point'") - // set GC safe point - tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) - - // Should recover, and we can drop it straight away. - tk.MustExec("recover table t_recover") - tk.MustExec("drop table t_recover") - - err = gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) - - // recover job is before GC safe point - tk.MustExec(fmt.Sprintf(safePointSQL, timeAfterDrop)) - _, err = tk.Exec("recover table t_recover") - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Can't find dropped/truncated table 't_recover' in GC safe point"), Equals, true) - - // set GC safe point - tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) - // if there is a new table with the same name, should return failed. - tk.MustExec("create table t_recover (a int);") - _, err = tk.Exec("recover table t_recover") - c.Assert(err.Error(), Equals, infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) - - // drop the new table with the same name, then recover table. - tk.MustExec("rename table t_recover to t_recover2") - - // do recover table. - tk.MustExec("recover table t_recover") - - // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) - // check recover table autoID. - tk.MustExec("insert into t_recover values (4),(5),(6)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) - // check rebase auto id. - tk.MustQuery("select a,_tidb_rowid from t_recover;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003")) - - // recover table by none exits job. - _, err = tk.Exec(fmt.Sprintf("recover table by job %d", 10000000)) - c.Assert(err, NotNil) - - // Disable GC by manual first, then after recover table, the GC enable status should also be disabled. - err = gcutil.DisableGC(tk.Se) - c.Assert(err, IsNil) - - tk.MustExec("delete from t_recover where a > 1") - tk.MustExec("drop table t_recover") - - tk.MustExec("recover table t_recover") - - // check recover table meta and data record. - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1")) - // check recover table autoID. - tk.MustExec("insert into t_recover values (7),(8),(9)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9")) - - // Recover truncate table. - tk.MustExec("truncate table t_recover") - tk.MustExec("rename table t_recover to t_recover_new") - tk.MustExec("recover table t_recover") - tk.MustExec("insert into t_recover values (10)") - tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9", "10")) - - // Test for recover one table multiple time. - tk.MustExec("drop table t_recover") - tk.MustExec("flashback table t_recover to t_recover_tmp") - _, err = tk.Exec("recover table t_recover") - c.Assert(infoschema.ErrTableExists.Equal(err), IsTrue) - - gcEnable, err := gcutil.CheckGCEnable(tk.Se) - c.Assert(err, IsNil) - c.Assert(gcEnable, Equals, false) -} - -func (s *testRecoverTable) TestFlashbackTable(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_flashback") - tk.MustExec("use test_flashback") - tk.MustExec("drop table if exists t_flashback") - tk.MustExec("create table t_flashback (a int);") - - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) - defer resetGC() - - // Set GC safe point - tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) - // Set GC enable. - err := gcutil.EnableGC(tk.Se) - c.Assert(err, IsNil) - - tk.MustExec("insert into t_flashback values (1),(2),(3)") - tk.MustExec("drop table t_flashback") - - // Test flash table with not_exist_table_name name. - _, err = tk.Exec("flashback table t_not_exists") - c.Assert(err.Error(), Equals, "Can't find localTemporary/dropped/truncated table: t_not_exists in DDL history jobs") - - // Test flashback table failed by there is already a new table with the same name. - // If there is a new table with the same name, should return failed. - tk.MustExec("create table t_flashback (a int);") - _, err = tk.Exec("flashback table t_flashback") - c.Assert(err.Error(), Equals, infoschema.ErrTableExists.GenWithStackByArgs("t_flashback").Error()) - - // Drop the new table with the same name, then flashback table. - tk.MustExec("rename table t_flashback to t_flashback_tmp") - - // Test for flashback table. - tk.MustExec("flashback table t_flashback") - // Check flashback table meta and data record. - tk.MustQuery("select * from t_flashback;").Check(testkit.Rows("1", "2", "3")) - // Check flashback table autoID. - tk.MustExec("insert into t_flashback values (4),(5),(6)") - tk.MustQuery("select * from t_flashback;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) - // Check rebase auto id. - tk.MustQuery("select a,_tidb_rowid from t_flashback;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003")) - - // Test for flashback to new table. - tk.MustExec("drop table t_flashback") - tk.MustExec("create table t_flashback (a int);") - tk.MustExec("flashback table t_flashback to t_flashback2") - // Check flashback table meta and data record. - tk.MustQuery("select * from t_flashback2;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) - // Check flashback table autoID. - tk.MustExec("insert into t_flashback2 values (7),(8),(9)") - tk.MustQuery("select * from t_flashback2;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) - // Check rebase auto id. - tk.MustQuery("select a,_tidb_rowid from t_flashback2;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003", "7 10001", "8 10002", "9 10003")) - - // Test for flashback one table multiple time. - _, err = tk.Exec("flashback table t_flashback to t_flashback4") - c.Assert(infoschema.ErrTableExists.Equal(err), IsTrue) - - // Test for flashback truncated table to new table. - tk.MustExec("truncate table t_flashback2") - tk.MustExec("flashback table t_flashback2 to t_flashback3") - // Check flashback table meta and data record. - tk.MustQuery("select * from t_flashback3;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) - // Check flashback table autoID. - tk.MustExec("insert into t_flashback3 values (10),(11)") - tk.MustQuery("select * from t_flashback3;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")) - // Check rebase auto id. - tk.MustQuery("select a,_tidb_rowid from t_flashback3;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003", "7 10001", "8 10002", "9 10003", "10 15001", "11 15002")) - - // Test for flashback drop partition table. - tk.MustExec("drop table if exists t_p_flashback") - tk.MustExec("create table t_p_flashback (a int) partition by hash(a) partitions 4;") - tk.MustExec("insert into t_p_flashback values (1),(2),(3)") - tk.MustExec("drop table t_p_flashback") - tk.MustExec("flashback table t_p_flashback") - // Check flashback table meta and data record. - tk.MustQuery("select * from t_p_flashback order by a;").Check(testkit.Rows("1", "2", "3")) - // Check flashback table autoID. - tk.MustExec("insert into t_p_flashback values (4),(5)") - tk.MustQuery("select a,_tidb_rowid from t_p_flashback order by a;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002")) - - // Test for flashback truncate partition table. - tk.MustExec("truncate table t_p_flashback") - tk.MustExec("flashback table t_p_flashback to t_p_flashback1") - // Check flashback table meta and data record. - tk.MustQuery("select * from t_p_flashback1 order by a;").Check(testkit.Rows("1", "2", "3", "4", "5")) - // Check flashback table autoID. - tk.MustExec("insert into t_p_flashback1 values (6)") - tk.MustQuery("select a,_tidb_rowid from t_p_flashback1 order by a;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 10001")) - - tk.MustExec("drop database if exists Test2") - tk.MustExec("create database Test2") - tk.MustExec("use Test2") - tk.MustExec("create table t (a int);") - tk.MustExec("insert into t values (1),(2)") - tk.MustExec("drop table t") - tk.MustExec("flashback table t") - tk.MustQuery("select a from t order by a").Check(testkit.Rows("1", "2")) + _, err := tk.Session().Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`) + require.NoError(t, err) - tk.MustExec("drop table t") - tk.MustExec("drop database if exists Test3") - tk.MustExec("create database Test3") - tk.MustExec("use Test3") - tk.MustExec("create table t (a int);") - tk.MustExec("drop table t") - tk.MustExec("drop database Test3") - tk.MustExec("use Test2") - tk.MustExec("flashback table t") - tk.MustExec("insert into t values (3)") - tk.MustQuery("select a from t order by a").Check(testkit.Rows("1", "2", "3")) -} - -func (s *testRecoverTable) TestRecoverTempTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_recover") - tk.MustExec("use test_recover") - tk.MustExec("drop table if exists t_recover") - tk.MustExec("create global temporary table t_recover (a int) on commit delete rows;") - - tk.MustExec("use test_recover") - tk.MustExec("drop table if exists tmp2_recover") - tk.MustExec("create temporary table tmp2_recover (a int);") - - timeBeforeDrop, _, safePointSQL, resetGC := testkit.MockGC(tk) - defer resetGC() - // Set GC safe point - tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) - - tk.MustExec("drop table t_recover") - tk.MustGetErrCode("recover table t_recover;", errno.ErrUnsupportedDDLOperation) - tk.MustGetErrCode("flashback table t_recover;", errno.ErrUnsupportedDDLOperation) - tk.MustExec("drop table tmp2_recover") - tk.MustGetErrMsg("recover table tmp2_recover;", "Can't find localTemporary/dropped/truncated table: tmp2_recover in DDL history jobs") - tk.MustGetErrMsg("flashback table tmp2_recover;", "Can't find localTemporary/dropped/truncated table: tmp2_recover in DDL history jobs") -} - -func (s *testSuiteP2) TestPointGetPreparedPlan(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("drop database if exists ps_text") - defer tk1.MustExec("drop database if exists ps_text") - tk1.MustExec("create database ps_text") - tk1.MustExec("use ps_text") - - tk1.MustExec(`create table t (a int, b int, c int, - primary key k_a(a), - unique key k_b(b))`) - tk1.MustExec("insert into t values (1, 1, 1)") - tk1.MustExec("insert into t values (2, 2, 2)") - tk1.MustExec("insert into t values (3, 3, 3)") - - pspk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where a = ?") - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - pspk2Id, _, _, err := tk1.Se.PrepareStmt("select * from t where ? = a ") - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[pspk2Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false + tk.MustExec(`set time_zone="System"`) + _, err = tk.Session().Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`) + require.NoError(t, err) - ctx := context.Background() - // first time plan generated - rs, err := tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - // using the generated plan but with different params - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) - - // unique index - psuk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where b = ? ") - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[psuk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - // test schema changed, cached plan should be invalidated - tk1.MustExec("alter table t add column col4 int default 10 after c") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) - - tk1.MustExec("alter table t drop index k_b") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - tk1.MustExec(`insert into t values(4, 3, 3, 11)`) - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10", "4 3 3 11")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - tk1.MustExec("delete from t where a = 4") - tk1.MustExec("alter table t add index k_b(b)") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, psuk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - // use pk again - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk2Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(3)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("3 3 3 10")) + require.Equal(t, 2, count) // Make sure the hook function is called. } -func (s *testSuiteP2) TestPointGetPreparedPlanWithCommitMode(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("drop database if exists ps_text") - defer tk1.MustExec("drop database if exists ps_text") - tk1.MustExec("create database ps_text") - tk1.MustExec("use ps_text") +func TestNotFillCacheFlag(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk1.MustExec(`create table t (a int, b int, c int, - primary key k_a(a), - unique key k_b(b))`) - tk1.MustExec("insert into t values (1, 1, 1)") - tk1.MustExec("insert into t values (2, 2, 2)") - tk1.MustExec("insert into t values (3, 3, 3)") - - pspk1Id, _, _, err := tk1.Se.PrepareStmt("select * from t where a = ?") - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - - ctx := context.Background() - // first time plan generated - rs, err := tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(0)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(nil) - - // using the generated plan but with different params - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - // next start a non autocommit txn - tk1.MustExec("set autocommit = 0") - tk1.MustExec("begin") - // try to exec using point get plan(this plan should not go short path) - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - // update rows - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use ps_text") - tk2.MustExec("update t set c = c + 10 where c = 1") - - // try to point get again - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 1")) - - // try to update in session 1 - tk1.MustExec("update t set c = c + 10 where c = 1") - _, err = tk1.Exec("commit") - c.Assert(kv.ErrWriteConflict.Equal(err), IsTrue, Commentf("error: %s", err)) - - // verify - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("1 1 11")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, pspk1Id, []types.Datum{types.NewDatum(2)}) - c.Assert(err, IsNil) - tk1.ResultSetToResult(rs, Commentf("%v", rs)).Check(testkit.Rows("2 2 2")) - - tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 11")) -} - -func (s *testSuiteP2) TestPointUpdatePreparedPlan(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("drop database if exists pu_test") - defer tk1.MustExec("drop database if exists pu_test") - tk1.MustExec("create database pu_test") - tk1.MustExec("use pu_test") - - tk1.MustExec(`create table t (a int, b int, c int, - primary key k_a(a), - unique key k_b(b))`) - tk1.MustExec("insert into t values (1, 1, 1)") - tk1.MustExec("insert into t values (2, 2, 2)") - tk1.MustExec("insert into t values (3, 3, 3)") - - updateID1, pc, _, err := tk1.Se.PrepareStmt(`update t set c = c + 1 where a = ?`) - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[updateID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - c.Assert(pc, Equals, 1) - updateID2, pc, _, err := tk1.Se.PrepareStmt(`update t set c = c + 2 where ? = a`) - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[updateID2].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - c.Assert(pc, Equals, 1) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (id int primary key)") + tk.MustExec("insert into t values (1)") + tests := []struct { + sql string + expect bool + }{ + {"select SQL_NO_CACHE * from t", true}, + {"select SQL_CACHE * from t", false}, + {"select * from t", false}, + } + count := 0 ctx := context.Background() - // first time plan generated - rs, err := tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4")) - - // using the generated plan but with different params - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) - - // updateID2 - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID2, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 8")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID2, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10")) - - // unique index - updUkID1, _, _, err := tk1.Se.PrepareStmt(`update t set c = c + 10 where b = ?`) - c.Assert(err, IsNil) - tk1.Se.GetSessionVars().PreparedStmts[updUkID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 20")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 30")) - - // test schema changed, cached plan should be invalidated - tk1.MustExec("alter table t add column col4 int default 10 after c") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 31 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 32 10")) - - tk1.MustExec("alter table t drop index k_b") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 42 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 52 10")) - - tk1.MustExec("alter table t add unique index k_b(b)") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 62 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updUkID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 72 10")) - - tk1.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1 10")) - tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2 10")) + for _, test := range tests { + ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { + count++ + comment := fmt.Sprintf("sql=%s, expect=%v, get=%v", test.sql, test.expect, req.NotFillCache) + require.Equal(t, test.expect, req.NotFillCache, comment) + }) + rs, err := tk.Session().Execute(ctx1, test.sql) + require.NoError(t, err) + tk.ResultSetToResult(rs[0], fmt.Sprintf("sql: %v", test.sql)) + } + require.Equal(t, len(tests), count) // Make sure the hook function is called. } -func (s *testSuiteP2) TestPointUpdatePreparedPlanWithCommitMode(c *C) { - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("drop database if exists pu_test2") - defer tk1.MustExec("drop database if exists pu_test2") - tk1.MustExec("create database pu_test2") - tk1.MustExec("use pu_test2") +func TestHandleTransfer(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk1.MustExec(`create table t (a int, b int, c int, - primary key k_a(a), - unique key k_b(b))`) - tk1.MustExec("insert into t values (1, 1, 1)") - tk1.MustExec("insert into t values (2, 2, 2)") - tk1.MustExec("insert into t values (3, 3, 3)") - - ctx := context.Background() - updateID1, _, _, err := tk1.Se.PrepareStmt(`update t set c = c + 1 where a = ?`) - tk1.Se.GetSessionVars().PreparedStmts[updateID1].(*plannercore.CachedPrepareStmt).PreparedAst.UseCache = false - c.Assert(err, IsNil) - - // first time plan generated - rs, err := tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) - - // next start a non autocommit txn - tk1.MustExec("set autocommit = 0") - tk1.MustExec("begin") - // try to exec using point get plan(this plan should not go short path) - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) - - // update rows - tk2 := testkit.NewTestKit(c, s.store) - tk2.MustExec("use pu_test2") - tk2.MustExec(`prepare pu2 from "update t set c = c + 2 where ? = a "`) - tk2.MustExec("set @p3 = 3") - tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5")) - tk2.MustExec("execute pu2 using @p3") - tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 7")) - tk2.MustExec("execute pu2 using @p3") - tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) - - // try to update in session 1 - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6")) - _, err = tk1.Exec("commit") - c.Assert(kv.ErrWriteConflict.Equal(err), IsTrue, Commentf("error: %s", err)) - - // verify - tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1")) - tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2")) - tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) - tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2")) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9")) - - // again next start a non autocommit txn - tk1.MustExec("set autocommit = 0") - tk1.MustExec("begin") - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10")) - - rs, err = tk1.Se.ExecutePreparedStmt(ctx, updateID1, []types.Datum{types.NewDatum(3)}) - c.Assert(rs, IsNil) - c.Assert(err, IsNil) - tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11")) - tk1.MustExec("commit") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int, index idx(a))") + tk.MustExec("insert into t values(1), (2), (4)") + tk.MustExec("begin") + tk.MustExec("update t set a = 3 where a = 4") + // test table scan read whose result need handle. + tk.MustQuery("select * from t ignore index(idx)").Check(testkit.Rows("1", "2", "3")) + tk.MustExec("insert into t values(4)") + // test single read whose result need handle + tk.MustQuery("select * from t use index(idx)").Check(testkit.Rows("1", "2", "3", "4")) + tk.MustQuery("select * from t use index(idx) order by a desc").Check(testkit.Rows("4", "3", "2", "1")) + tk.MustExec("update t set a = 5 where a = 3") + tk.MustQuery("select * from t use index(idx)").Check(testkit.Rows("1", "2", "4", "5")) + tk.MustExec("commit") - tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11")) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, index idx(a))") + tk.MustExec("insert into t values(3, 3), (1, 1), (2, 2)") + // Second test double read. + tk.MustQuery("select * from t use index(idx) order by a").Check(testkit.Rows("1 1", "2 2", "3 3")) } -func (s *testSuite1) TestPartitionHashCode(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec(`create table t(c1 bigint, c2 bigint, c3 bigint, primary key(c1)) - partition by hash (c1) partitions 4;`) - wg := sync.WaitGroup{} - for i := 0; i < 5; i++ { - wg.Add(1) - go func() { - defer wg.Done() - tk1 := testkit.NewTestKitWithInit(c, s.store) - for i := 0; i < 5; i++ { - tk1.MustExec("select * from t") - } - }() - } - wg.Wait() -} +func TestExecutorBit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite1) TestAlterDefaultValue(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t(a int, primary key(a))") - tk.MustExec("insert into t(a) values(1)") - tk.MustExec("alter table t add column b int default 1") - tk.MustExec("alter table t alter b set default 2") - tk.MustQuery("select b from t where a = 1").Check(testkit.Rows("1")) -} - -type testClusterTableSuite struct { - testSuiteWithCliBase - rpcserver *grpc.Server - listenAddr string -} - -func (s *testClusterTableSuite) SetUpSuite(c *C) { - s.testSuiteWithCliBase.SetUpSuite(c) - s.rpcserver, s.listenAddr = s.setUpRPCService(c, "127.0.0.1:0") -} + tk.MustExec("create table t (c1 bit(2))") + tk.MustExec("insert into t values (0), (1), (2), (3)") + err := tk.ExecToErr("insert into t values (4)") + require.Error(t, err) + err = tk.ExecToErr("insert into t values ('a')") + require.Error(t, err) + r, err := tk.Exec("select * from t where c1 = 2") + require.NoError(t, err) + req := r.NewChunk(nil) + err = r.Next(context.Background(), req) + require.NoError(t, err) + require.Equal(t, types.NewBinaryLiteralFromUint(2, -1), types.BinaryLiteral(req.GetRow(0).GetBytes(0))) + require.NoError(t, r.Close()) -func (s *testClusterTableSuite) setUpRPCService(c *C, addr string) (*grpc.Server, string) { - sm := &mockSessionManager1{} - sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 1, - User: "root", - Host: "127.0.0.1", - Command: mysql.ComQuery, - }) - lis, err := net.Listen("tcp", addr) - c.Assert(err, IsNil) - srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) - port := lis.Addr().(*net.TCPAddr).Port - addr = fmt.Sprintf("127.0.0.1:%d", port) - go func() { - err = srv.Serve(lis) - c.Assert(err, IsNil) - }() - config.UpdateGlobal(func(conf *config.Config) { - conf.Status.StatusPort = uint(port) - }) - return srv, addr -} -func (s *testClusterTableSuite) TearDownSuite(c *C) { - if s.rpcserver != nil { - s.rpcserver.Stop() - s.rpcserver = nil - } - s.testSuiteWithCliBase.TearDownSuite(c) -} + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(31))") + tk.MustExec("insert into t values (0x7fffffff)") + err = tk.ExecToErr("insert into t values (0x80000000)") + require.Error(t, err) + err = tk.ExecToErr("insert into t values (0xffffffff)") + require.Error(t, err) + tk.MustExec("insert into t values ('123')") + tk.MustExec("insert into t values ('1234')") + err = tk.ExecToErr("insert into t values ('12345)") + require.Error(t, err) -func (s *testSuiteP1) TestPrepareLoadData(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustGetErrCode(`prepare stmt from "load data local infile '/tmp/load_data_test.csv' into table test";`, mysql.ErrUnsupportedPs) -} + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(62))") + tk.MustExec("insert into t values ('12345678')") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(61))") + err = tk.ExecToErr("insert into t values ('12345678')") + require.Error(t, err) -func (s *testClusterTableSuite) TestSlowQuery(c *C) { - logData0 := "" - logData1 := ` -# Time: 2020-02-15T18:00:01.000000+08:00 -select 1; -# Time: 2020-02-15T19:00:05.000000+08:00 -select 2;` - logData2 := ` -# Time: 2020-02-16T18:00:01.000000+08:00 -select 3; -# Time: 2020-02-16T18:00:05.000000+08:00 -select 4;` - logData3 := ` -# Time: 2020-02-16T19:00:00.000000+08:00 -select 5; -# Time: 2020-02-17T18:00:05.000000+08:00 -select 6;` - logData4 := ` -# Time: 2020-05-14T19:03:54.314615176+08:00 -select 7;` - logData := []string{logData0, logData1, logData2, logData3, logData4} - - fileName0 := "tidb-slow-2020-02-14T19-04-05.01.log" - fileName1 := "tidb-slow-2020-02-15T19-04-05.01.log" - fileName2 := "tidb-slow-2020-02-16T19-04-05.01.log" - fileName3 := "tidb-slow-2020-02-17T18-00-05.01.log" - fileName4 := "tidb-slow.log" - fileNames := []string{fileName0, fileName1, fileName2, fileName3, fileName4} - - prepareLogs(c, logData, fileNames) - defer func() { - removeFiles(fileNames) - }() - tk := testkit.NewTestKitWithInit(c, s.store) - loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) - tk.Se.GetSessionVars().TimeZone = loc - tk.MustExec("use information_schema") - cases := []struct { - prepareSQL string - sql string - result []string - }{ - { - sql: "select count(*),min(time),max(time) from %s where time > '2019-01-26 21:51:00' and time < now()", - result: []string{"7|2020-02-15 18:00:01.000000|2020-05-14 19:03:54.314615"}, - }, - { - sql: "select count(*),min(time),max(time) from %s where time > '2020-02-15 19:00:00' and time < '2020-02-16 18:00:02'", - result: []string{"2|2020-02-15 19:00:05.000000|2020-02-16 18:00:01.000000"}, - }, - { - sql: "select count(*),min(time),max(time) from %s where time > '2020-02-16 18:00:02' and time < '2020-02-17 17:00:00'", - result: []string{"2|2020-02-16 18:00:05.000000|2020-02-16 19:00:00.000000"}, - }, - { - sql: "select count(*),min(time),max(time) from %s where time > '2020-02-16 18:00:02' and time < '2020-02-17 20:00:00'", - result: []string{"3|2020-02-16 18:00:05.000000|2020-02-17 18:00:05.000000"}, - }, - { - sql: "select count(*),min(time),max(time) from %s", - result: []string{"1|2020-05-14 19:03:54.314615|2020-05-14 19:03:54.314615"}, - }, - { - sql: "select count(*),min(time) from %s where time > '2020-02-16 20:00:00'", - result: []string{"1|2020-02-17 18:00:05.000000"}, - }, - { - sql: "select count(*) from %s where time > '2020-02-17 20:00:00'", - result: []string{"0"}, - }, - { - sql: "select query from %s where time > '2019-01-26 21:51:00' and time < now()", - result: []string{"select 1;", "select 2;", "select 3;", "select 4;", "select 5;", "select 6;", "select 7;"}, - }, - // Test for different timezone. - { - prepareSQL: "set @@time_zone = '+00:00'", - sql: "select time from %s where time = '2020-02-17 10:00:05.000000'", - result: []string{"2020-02-17 10:00:05.000000"}, - }, - { - prepareSQL: "set @@time_zone = '+02:00'", - sql: "select time from %s where time = '2020-02-17 12:00:05.000000'", - result: []string{"2020-02-17 12:00:05.000000"}, - }, - // Test for issue 17224 - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from %s where time = '2020-05-14 19:03:54.314615'", - result: []string{"2020-05-14 19:03:54.314615"}, - }, - } - for _, cas := range cases { - if len(cas.prepareSQL) > 0 { - tk.MustExec(cas.prepareSQL) - } - sql := fmt.Sprintf(cas.sql, "slow_query") - tk.MustQuery(sql).Check(testutil.RowsWithSep("|", cas.result...)) - sql = fmt.Sprintf(cas.sql, "cluster_slow_query") - tk.MustQuery(sql).Check(testutil.RowsWithSep("|", cas.result...)) - } -} + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(32))") + tk.MustExec("insert into t values (0x7fffffff)") + tk.MustExec("insert into t values (0xffffffff)") + err = tk.ExecToErr("insert into t values (0x1ffffffff)") + require.Error(t, err) + tk.MustExec("insert into t values ('1234')") + err = tk.ExecToErr("insert into t values ('12345')") + require.Error(t, err) -func (s *testClusterTableSuite) TestIssue20236(c *C) { - logData0 := "" - logData1 := ` -# Time: 2020-02-15T18:00:01.000000+08:00 -select 1; -# Time: 2020-02-15T19:00:05.000000+08:00 -select 2; -# Time: 2020-02-15T20:00:05.000000+08:00` - logData2 := `select 3; -# Time: 2020-02-16T18:00:01.000000+08:00 -select 4; -# Time: 2020-02-16T18:00:05.000000+08:00 -select 5;` - logData3 := ` -# Time: 2020-02-16T19:00:00.000000+08:00 -select 6; -# Time: 2020-02-17T18:00:05.000000+08:00 -select 7; -# Time: 2020-02-17T19:00:00.000000+08:00` - logData4 := `select 8; -# Time: 2020-02-17T20:00:00.000000+08:00 -select 9 -# Time: 2020-05-14T19:03:54.314615176+08:00 -select 10;` - logData := []string{logData0, logData1, logData2, logData3, logData4} - - fileName0 := "tidb-slow-2020-02-14T19-04-05.01.log" - fileName1 := "tidb-slow-2020-02-15T19-04-05.01.log" - fileName2 := "tidb-slow-2020-02-16T19-04-05.01.log" - fileName3 := "tidb-slow-2020-02-17T18-00-05.01.log" - fileName4 := "tidb-slow.log" - fileNames := []string{fileName0, fileName1, fileName2, fileName3, fileName4} - prepareLogs(c, logData, fileNames) - defer func() { - removeFiles(fileNames) - }() - tk := testkit.NewTestKitWithInit(c, s.store) - loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) - tk.Se.GetSessionVars().TimeZone = loc - tk.MustExec("use information_schema") - cases := []struct { - prepareSQL string - sql string - result []string - }{ - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from cluster_slow_query where time > '2020-02-17 12:00:05.000000' and time < '2020-05-14 20:00:00.000000'", - result: []string{"2020-02-17 18:00:05.000000", "2020-02-17 19:00:00.000000", "2020-05-14 19:03:54.314615"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from cluster_slow_query where time > '2020-02-17 12:00:05.000000' and time < '2020-05-14 20:00:00.000000' order by time desc", - result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from cluster_slow_query where (time > '2020-02-15 18:00:00' and time < '2020-02-15 20:01:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-14 20:00:00') order by time", - result: []string{"2020-02-15 18:00:01.000000", "2020-02-15 19:00:05.000000", "2020-02-17 18:00:05.000000", "2020-02-17 19:00:00.000000", "2020-05-14 19:03:54.314615"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from cluster_slow_query where (time > '2020-02-15 18:00:00' and time < '2020-02-15 20:01:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-14 20:00:00') order by time desc", - result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000", "2020-02-15 19:00:05.000000", "2020-02-15 18:00:01.000000"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select count(*) from cluster_slow_query where time > '2020-02-15 18:00:00.000000' and time < '2020-05-14 20:00:00.000000' order by time desc", - result: []string{"9"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select count(*) from cluster_slow_query where (time > '2020-02-16 18:00:00' and time < '2020-05-14 20:00:00') or (time > '2020-02-17 18:00:00' and time < '2020-05-17 20:00:00')", - result: []string{"6"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select count(*) from cluster_slow_query where time > '2020-02-16 18:00:00.000000' and time < '2020-02-17 20:00:00.000000' order by time desc", - result: []string{"5"}, - }, - { - prepareSQL: "set @@time_zone = '+08:00'", - sql: "select time from cluster_slow_query where time > '2020-02-16 18:00:00.000000' and time < '2020-05-14 20:00:00.000000' order by time desc limit 3", - result: []string{"2020-05-14 19:03:54.314615", "2020-02-17 19:00:00.000000", "2020-02-17 18:00:05.000000"}, - }, - } - for _, cas := range cases { - if len(cas.prepareSQL) > 0 { - tk.MustExec(cas.prepareSQL) - } - tk.MustQuery(cas.sql).Check(testutil.RowsWithSep("|", cas.result...)) - } -} + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(64))") + tk.MustExec("insert into t values (0xffffffffffffffff)") + tk.MustExec("insert into t values ('12345678')") + err = tk.ExecToErr("insert into t values ('123456789')") + require.Error(t, err) -func (s *testClusterTableSuite) TestSQLDigestTextRetriever(c *C) { - tkInit := testkit.NewTestKitWithInit(c, s.store) - tkInit.MustExec("set global tidb_enable_stmt_summary = 1") - tkInit.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) - tkInit.MustExec("drop table if exists test_sql_digest_text_retriever") - tkInit.MustExec("create table test_sql_digest_text_retriever (id int primary key, v int)") - - tk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("insert into test_sql_digest_text_retriever values (1, 1)") - - insertNormalized, insertDigest := parser.NormalizeDigest("insert into test_sql_digest_text_retriever values (1, 1)") - _, updateDigest := parser.NormalizeDigest("update test_sql_digest_text_retriever set v = v + 1 where id = 1") - r := &expression.SQLDigestTextRetriever{ - SQLDigestsMap: map[string]string{ - insertDigest.String(): "", - updateDigest.String(): "", - }, - } - err := r.RetrieveLocal(context.Background(), tk.Se) - c.Assert(err, IsNil) - c.Assert(r.SQLDigestsMap[insertDigest.String()], Equals, insertNormalized) - c.Assert(r.SQLDigestsMap[updateDigest.String()], Equals, "") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 bit(64))") + tk.MustExec("insert into t values (0xffffffffffffffff)") + tk.MustExec("insert into t values ('12345678')") + tk.MustQuery("select * from t where c1").Check(testkit.Rows("\xff\xff\xff\xff\xff\xff\xff\xff", "12345678")) } -func (s *testClusterTableSuite) TestFunctionDecodeSQLDigests(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("set global tidb_enable_stmt_summary = 1") - tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) - tk.MustExec("drop table if exists test_func_decode_sql_digests") - tk.MustExec("create table test_func_decode_sql_digests(id int primary key, v int)") - - q1 := "begin" - norm1, digest1 := parser.NormalizeDigest(q1) - q2 := "select @@tidb_current_ts" - norm2, digest2 := parser.NormalizeDigest(q2) - q3 := "select id, v from test_func_decode_sql_digests where id = 1 for update" - norm3, digest3 := parser.NormalizeDigest(q3) - - // TIDB_DECODE_SQL_DIGESTS function doesn't actually do "decoding", instead it queries `statements_summary` and it's - // variations for the corresponding statements. - // Execute the statements so that the queries will be saved into statements_summary table. - tk.MustExec(q1) - // Save the ts to query the transaction from tidb_trx. - ts, err := strconv.ParseUint(tk.MustQuery(q2).Rows()[0][0].(string), 10, 64) - c.Assert(err, IsNil) - c.Assert(ts, Greater, uint64(0)) - tk.MustExec(q3) - tk.MustExec("rollback") +func TestExecutorEnum(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - // Test statements truncating. - decoded := fmt.Sprintf(`["%s","%s","%s"]`, norm1, norm2, norm3) - digests := fmt.Sprintf(`["%s","%s","%s"]`, digest1, digest2, digest3) - tk.MustQuery("select tidb_decode_sql_digests(?, 0)", digests).Check(testkit.Rows(decoded)) - // The three queries are shorter than truncate length, equal to truncate length and longer than truncate length respectively. - tk.MustQuery("select tidb_decode_sql_digests(?, ?)", digests, len(norm2)).Check(testkit.Rows( - "[\"begin\",\"select @@tidb_current_ts\",\"select `id` , `v` from `...\"]")) - - // Empty array. - tk.MustQuery("select tidb_decode_sql_digests('[]')").Check(testkit.Rows("[]")) - - // NULL - tk.MustQuery("select tidb_decode_sql_digests(null)").Check(testkit.Rows("")) - - // Array containing wrong types and not-existing digests (maps to null). - tk.MustQuery("select tidb_decode_sql_digests(?)", fmt.Sprintf(`["%s",1,null,"%s",{"a":1},[2],"%s","","abcde"]`, digest1, digest2, digest3)). - Check(testkit.Rows(fmt.Sprintf(`["%s",null,null,"%s",null,null,"%s",null,null]`, norm1, norm2, norm3))) - - // Not JSON array (throws warnings) - tk.MustQuery(`select tidb_decode_sql_digests('{"a":1}')`).Check(testkit.Rows("")) - tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: '{"a":1}'`)) - tk.MustQuery(`select tidb_decode_sql_digests('aabbccdd')`).Check(testkit.Rows("")) - tk.MustQuery(`show warnings`).Check(testkit.Rows(`Warning 1210 The argument can't be unmarshalled as JSON array: 'aabbccdd'`)) - - // Invalid argument count. - tk.MustGetErrCode("select tidb_decode_sql_digests('a', 1, 2)", 1582) - tk.MustGetErrCode("select tidb_decode_sql_digests()", 1582) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c enum('a', 'b', 'c'))") + tk.MustExec("insert into t values ('a'), (2), ('c')") + tk.MustQuery("select * from t where c = 'a'").Check(testkit.Rows("a")) -func (s *testClusterTableSuite) TestFunctionDecodeSQLDigestsPrivilege(c *C) { - dropUserTk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(dropUserTk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - - tk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("create user 'testuser'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") - c.Assert(tk.Se.Auth(&auth.UserIdentity{ - Username: "testuser", - Hostname: "localhost", - }, nil, nil), IsTrue) - err := tk.ExecToErr("select tidb_decode_sql_digests('[\"aa\"]')") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") - - tk = testkit.NewTestKitWithInit(c, s.store) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk.MustExec("create user 'testuser2'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") - tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") - c.Assert(tk.Se.Auth(&auth.UserIdentity{ - Username: "testuser2", - Hostname: "localhost", - }, nil, nil), IsTrue) - _ = tk.MustQuery("select tidb_decode_sql_digests('[\"aa\"]')") -} + tk.MustQuery("select c + 1 from t where c = 2").Check(testkit.Rows("3")) -func prepareLogs(c *C, logData []string, fileNames []string) { - writeFile := func(file string, data string) { - f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) - c.Assert(err, IsNil) - _, err = f.Write([]byte(data)) - c.Assert(f.Close(), IsNil) - c.Assert(err, IsNil) - } + tk.MustExec("delete from t") + tk.MustExec("insert into t values ()") + tk.MustExec("insert into t values (null), ('1')") + tk.MustQuery("select c + 1 from t where c = 1").Check(testkit.Rows("2")) - for i, log := range logData { - writeFile(fileNames[i], log) - } + tk.MustExec("delete from t") + tk.MustExec("insert into t values(1), (2), (3)") + tk.MustQuery("select * from t where c").Check(testkit.Rows("a", "b", "c")) } -func removeFiles(fileNames []string) { - for _, fileName := range fileNames { - os.Remove(fileName) - } -} +func TestExecutorSet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite1) TestIssue15718(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt(a decimal(10, 0), b varchar(1), c time);") - tk.MustExec("insert into tt values(0, '2', null), (7, null, '1122'), (NULL, 'w', null), (NULL, '2', '3344'), (NULL, NULL, '0'), (7, 'f', '33');") - tk.MustQuery("select a and b as d, a or c as e from tt;").Check(testkit.Rows("0 ", " 1", "0 ", " 1", " ", "0 1")) - - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table tt(a decimal(10, 0), b varchar(1), c time);") - tk.MustExec("insert into tt values(0, '2', '123'), (7, null, '1122'), (null, 'w', null);") - tk.MustQuery("select a and b as d, a, b from tt order by d limit 1;").Check(testkit.Rows(" 7 ")) - tk.MustQuery("select b or c as d, b, c from tt order by d limit 1;").Check(testkit.Rows(" w ")) - - tk.MustExec("drop table if exists t0;") - tk.MustExec("CREATE TABLE t0(c0 FLOAT);") - tk.MustExec("INSERT INTO t0(c0) VALUES (NULL);") - tk.MustQuery("SELECT * FROM t0 WHERE NOT(0 OR t0.c0);").Check(testkit.Rows()) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c set('a', 'b', 'c'))") + tk.MustExec("insert into t values ('a'), (2), ('c'), ('a,b'), ('b,a')") + tk.MustQuery("select * from t where c = 'a'").Check(testkit.Rows("a")) + tk.MustQuery("select * from t where c = 'a,b'").Check(testkit.Rows("a,b", "a,b")) + tk.MustQuery("select c + 1 from t where c = 2").Check(testkit.Rows("3")) + tk.MustExec("delete from t") + tk.MustExec("insert into t values ()") + tk.MustExec("insert into t values (null), ('1')") + tk.MustQuery("select c + 1 from t where c = 1").Check(testkit.Rows("2")) + tk.MustExec("delete from t") + tk.MustExec("insert into t values(3)") + tk.MustQuery("select * from t where c").Check(testkit.Rows("a,b")) } -func (s *testSuite1) TestIssue15767(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists tt;") - tk.MustExec("create table t(a int, b char);") - tk.MustExec("insert into t values (1,'s'),(2,'b'),(1,'c'),(2,'e'),(1,'a');") - tk.MustExec("insert into t select * from t;") - tk.MustExec("insert into t select * from t;") - tk.MustExec("insert into t select * from t;") - tk.MustQuery("select b, count(*) from ( select b from t order by a limit 20 offset 2) as s group by b order by b;").Check(testkit.Rows("a 6", "c 7", "s 7")) -} +func TestSubQueryInValues(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite1) TestIssue16025(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t0;") - tk.MustExec("CREATE TABLE t0(c0 NUMERIC PRIMARY KEY);") - tk.MustExec("INSERT IGNORE INTO t0(c0) VALUES (NULL);") - tk.MustQuery("SELECT * FROM t0 WHERE c0;").Check(testkit.Rows()) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (id int, name varchar(20))") + tk.MustExec("create table t1 (gid int)") + tk.MustExec("insert into t1 (gid) value (1)") + tk.MustExec("insert into t (id, name) value ((select gid from t1) ,'asd')") + tk.MustQuery("select * from t").Check(testkit.Rows("1 asd")) } -func (s *testSuite1) TestIssue16854(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - tk.MustExec("CREATE TABLE `t` ( `a` enum('WAITING','PRINTED','STOCKUP','CHECKED','OUTSTOCK','PICKEDUP','WILLBACK','BACKED') DEFAULT NULL)") - tk.MustExec("insert into t values(1),(2),(3),(4),(5),(6),(7);") - for i := 0; i < 7; i++ { - tk.MustExec("insert into t select * from t;") - } - tk.MustExec("set @@tidb_max_chunk_size=100;") - tk.MustQuery("select distinct a from t order by a").Check(testkit.Rows("WAITING", "PRINTED", "STOCKUP", "CHECKED", "OUTSTOCK", "PICKEDUP", "WILLBACK")) - tk.MustExec("drop table t") +func TestEnhancedRangeAccess(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk.MustExec("CREATE TABLE `t` ( `a` set('WAITING','PRINTED','STOCKUP','CHECKED','OUTSTOCK','PICKEDUP','WILLBACK','BACKED') DEFAULT NULL)") - tk.MustExec("insert into t values(1),(2),(3),(4),(5),(6),(7);") - for i := 0; i < 7; i++ { - tk.MustExec("insert into t select * from t;") - } - tk.MustExec("set @@tidb_max_chunk_size=100;") - tk.MustQuery("select distinct a from t order by a").Check(testkit.Rows("WAITING", "PRINTED", "WAITING,PRINTED", "STOCKUP", "WAITING,STOCKUP", "PRINTED,STOCKUP", "WAITING,PRINTED,STOCKUP")) - tk.MustExec("drop table t") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int primary key, b int)") + tk.MustExec("insert into t values(1, 2), (2, 1)") + tk.MustQuery("select * from t where (a = 1 and b = 2) or (a = 2 and b = 1)").Check(testkit.Rows("1 2", "2 1")) + tk.MustQuery("select * from t where (a = 1 and b = 1) or (a = 2 and b = 2)").Check(nil) } -func (s *testSuite) TestIssue16921(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a float);") - tk.MustExec("create index a on t(a);") - tk.MustExec("insert into t values (1.0), (NULL), (0), (2.0);") - tk.MustQuery("select `a` from `t` use index (a) where !`a`;").Check(testkit.Rows("0")) - tk.MustQuery("select `a` from `t` ignore index (a) where !`a`;").Check(testkit.Rows("0")) - tk.MustQuery("select `a` from `t` use index (a) where `a`;").Check(testkit.Rows("1", "2")) - tk.MustQuery("select `a` from `t` ignore index (a) where `a`;").Check(testkit.Rows("1", "2")) - tk.MustQuery("select a from t use index (a) where not a is true;").Check(testkit.Rows("", "0")) - tk.MustQuery("select a from t use index (a) where not not a is true;").Check(testkit.Rows("1", "2")) - tk.MustQuery("select a from t use index (a) where not not a;").Check(testkit.Rows("1", "2")) - tk.MustQuery("select a from t use index (a) where not not not a is true;").Check(testkit.Rows("", "0")) - tk.MustQuery("select a from t use index (a) where not not not a;").Check(testkit.Rows("0")) -} +// TestMaxInt64Handle Issue #4810 +func TestMaxInt64Handle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite) TestIssue19100(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t1, t2;") - tk.MustExec("create table t1 (c decimal);") - tk.MustExec("create table t2 (c decimal, key(c));") - tk.MustExec("insert into t1 values (null);") - tk.MustExec("insert into t2 values (null);") - tk.MustQuery("select count(*) from t1 where not c;").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from t2 where not c;").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from t1 where c;").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from t2 where c;").Check(testkit.Rows("0")) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id bigint, PRIMARY KEY (id))") + tk.MustExec("insert into t values(9223372036854775807)") + tk.MustExec("select * from t where id = 9223372036854775807") + tk.MustQuery("select * from t where id = 9223372036854775807;").Check(testkit.Rows("9223372036854775807")) + tk.MustQuery("select * from t").Check(testkit.Rows("9223372036854775807")) + err := tk.ExecToErr("insert into t values(9223372036854775807)") + require.Error(t, err) + tk.MustExec("delete from t where id = 9223372036854775807") + tk.MustQuery("select * from t").Check(nil) } -// this is from jira issue #5856 -func (s *testSuite1) TestInsertValuesWithSubQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2(a int, b int, c int)") - defer tk.MustExec("drop table if exists t2") - - // should not reference upper scope - c.Assert(tk.ExecToErr("insert into t2 values (11, 8, (select not b))"), NotNil) - c.Assert(tk.ExecToErr("insert into t2 set a = 11, b = 8, c = (select b))"), NotNil) - - // subquery reference target table is allowed - tk.MustExec("insert into t2 values(1, 1, (select b from t2))") - tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ")) - tk.MustExec("insert into t2 set a = 1, b = 1, c = (select b+1 from t2)") - tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ", "1 1 2")) +func TestTableScanWithPointRanges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - // insert using column should work normally - tk.MustExec("delete from t2") - tk.MustExec("insert into t2 values(2, 4, a)") - tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2")) - tk.MustExec("insert into t2 set a = 3, b = 5, c = b") - tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2", "3 5 5")) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int, PRIMARY KEY (id))") + tk.MustExec("insert into t values(1), (5), (10)") + tk.MustQuery("select * from t where id in(1, 2, 10)").Check(testkit.Rows("1", "10")) } -func (s *testSuite1) TestDIVZeroInPartitionExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(a int) partition by range (10 div a) (partition p0 values less than (10), partition p1 values less than maxvalue)") - defer tk.MustExec("drop table if exists t1") +func TestUnsignedPk(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk.MustExec("set @@sql_mode=''") - tk.MustExec("insert into t1 values (NULL), (0), (1)") - tk.MustExec("set @@sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO'") - tk.MustGetErrCode("insert into t1 values (NULL), (0), (1)", mysql.ErrDivisionByZero) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id bigint unsigned primary key)") + var num1, num2 uint64 = math.MaxInt64 + 1, math.MaxInt64 + 2 + tk.MustExec(fmt.Sprintf("insert into t values(%v), (%v), (1), (2)", num1, num2)) + num1Str := strconv.FormatUint(num1, 10) + num2Str := strconv.FormatUint(num2, 10) + tk.MustQuery("select * from t order by id").Check(testkit.Rows("1", "2", num1Str, num2Str)) + tk.MustQuery("select * from t where id not in (2)").Check(testkit.Rows(num1Str, num2Str, "1")) + tk.MustExec("drop table t") + tk.MustExec("create table t(a bigint unsigned primary key, b int, index idx(b))") + tk.MustExec("insert into t values(9223372036854775808, 1), (1, 1)") + tk.MustQuery("select * from t use index(idx) where b = 1 and a < 2").Check(testkit.Rows("1 1")) + tk.MustQuery("select * from t use index(idx) where b = 1 order by b, a").Check(testkit.Rows("1 1", "9223372036854775808 1")) } -func (s *testSuite1) TestInsertIntoGivenPartitionSet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec(`create table t1( - a int(11) DEFAULT NULL, - b varchar(10) DEFAULT NULL, - UNIQUE KEY idx_a (a)) PARTITION BY RANGE (a) - (PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB, - PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB, - PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB, - PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)`) - defer tk.MustExec("drop table if exists t1") - - // insert into - tk.MustExec("insert into t1 partition(p0) values(1, 'a'), (2, 'b')") - tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b")) - tk.MustExec("insert into t1 partition(p0, p1) values(3, 'c'), (4, 'd')") - tk.MustQuery("select * from t1 partition(p1)").Check(testkit.Rows()) - - tk.MustGetErrMsg("insert into t1 values(1, 'a')", "[kv:1062]Duplicate entry '1' for key 'idx_a'") - tk.MustGetErrMsg("insert into t1 partition(p0, p_non_exist) values(1, 'a')", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") - tk.MustGetErrMsg("insert into t1 partition(p0, p1) values(40, 'a')", "[table:1748]Found a row not matching the given partition set") - - // replace into - tk.MustExec("replace into t1 partition(p0) values(1, 'replace')") - tk.MustExec("replace into t1 partition(p0, p1) values(3, 'replace'), (4, 'replace')") - tk.MustExec("replace into t1 values(1, 'a')") - tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 replace", "4 replace")) - - tk.MustGetErrMsg("replace into t1 partition(p0, p_non_exist) values(1, 'a')", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") - tk.MustGetErrMsg("replace into t1 partition(p0, p1) values(40, 'a')", "[table:1748]Found a row not matching the given partition set") - - tk.MustExec("truncate table t1") - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b char(10))") - defer tk.MustExec("drop table if exists t") - - // insert into general table - tk.MustGetErrMsg("insert into t partition(p0, p1) values(1, 'a')", "[planner:1747]PARTITION () clause on non partitioned table") - - // insert into from select - tk.MustExec("insert into t values(1, 'a'), (2, 'b')") - tk.MustExec("insert into t1 partition(p0) select * from t") - tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b")) - - tk.MustExec("truncate table t") - tk.MustExec("insert into t values(3, 'c'), (4, 'd')") - tk.MustExec("insert into t1 partition(p0, p1) select * from t") - tk.MustQuery("select * from t1 partition(p1) order by a").Check(testkit.Rows()) - tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 c", "4 d")) - - tk.MustGetErrMsg("insert into t1 select 1, 'a'", "[kv:1062]Duplicate entry '1' for key 'idx_a'") - tk.MustGetErrMsg("insert into t1 partition(p0, p_non_exist) select 1, 'a'", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") - tk.MustGetErrMsg("insert into t1 partition(p0, p1) select 40, 'a'", "[table:1748]Found a row not matching the given partition set") - - // replace into from select - tk.MustExec("replace into t1 partition(p0) select 1, 'replace'") - tk.MustExec("truncate table t") - tk.MustExec("insert into t values(3, 'replace'), (4, 'replace')") - tk.MustExec("replace into t1 partition(p0, p1) select * from t") +func TestSignedCommonHandle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk.MustExec("replace into t1 select 1, 'a'") - tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 replace", "4 replace")) - tk.MustGetErrMsg("replace into t1 partition(p0, p_non_exist) select 1, 'a'", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") - tk.MustGetErrMsg("replace into t1 partition(p0, p1) select 40, 'a'", "[table:1748]Found a row not matching the given partition set") + tk := testkit.NewTestKit(t, store) + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("use test") + tk.MustExec("create table t(k1 int, k2 int, primary key(k1, k2))") + tk.MustExec("insert into t(k1, k2) value(-100, 1), (-50, 1), (0, 0), (1, 1), (3, 3)") + tk.MustQuery("select k1 from t order by k1").Check(testkit.Rows("-100", "-50", "0", "1", "3")) + tk.MustQuery("select k1 from t order by k1 desc").Check(testkit.Rows("3", "1", "0", "-50", "-100")) + tk.MustQuery("select k1 from t where k1 < -51").Check(testkit.Rows("-100")) + tk.MustQuery("select k1 from t where k1 < -1").Check(testkit.Rows("-100", "-50")) + tk.MustQuery("select k1 from t where k1 <= 0").Check(testkit.Rows("-100", "-50", "0")) + tk.MustQuery("select k1 from t where k1 < 2").Check(testkit.Rows("-100", "-50", "0", "1")) + tk.MustQuery("select k1 from t where k1 < -1 and k1 > -90").Check(testkit.Rows("-50")) } -func (s *testSuite1) TestUpdateGivenPartitionSet(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1,t2,t3,t4") - tk.MustExec(`create table t1( - a int(11), - b varchar(10) DEFAULT NULL, - primary key idx_a (a)) PARTITION BY RANGE (a) - (PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB, - PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB, - PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB, - PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)`) - - tk.MustExec(`create table t2( - a int(11) DEFAULT NULL, - b varchar(10) DEFAULT NULL) PARTITION BY RANGE (a) - (PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB, - PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB, - PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB, - PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)`) +func TestContainDotColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk.MustExec(`create table t3 (a int(11), b varchar(10) default null)`) - - defer tk.MustExec("drop table if exists t1,t2,t3") - tk.MustExec("insert into t3 values(1, 'a'), (2, 'b'), (11, 'c'), (21, 'd')") - err := tk.ExecToErr("update t3 partition(p0) set a = 40 where a = 2") - c.Assert(err.Error(), Equals, "[planner:1747]PARTITION () clause on non partitioned table") - - // update with primary key change - tk.MustExec("insert into t1 values(1, 'a'), (2, 'b'), (11, 'c'), (21, 'd')") - err = tk.ExecToErr("update t1 partition(p0, p1) set a = 40") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") - err = tk.ExecToErr("update t1 partition(p0) set a = 40 where a = 2") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") - // test non-exist partition. - err = tk.ExecToErr("update t1 partition (p0, p_non_exist) set a = 40") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p_non_exist' in table 't1'") - // test join. - err = tk.ExecToErr("update t1 partition (p0), t3 set t1.a = 40 where t3.a = 2") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table test.t1(t1.a char)") + tk.MustExec("create table t2(a char, t2.b int)") - tk.MustExec("update t1 partition(p0) set a = 3 where a = 2") - tk.MustExec("update t1 partition(p0, p3) set a = 33 where a = 1") + tk.MustGetErrCode("create table t3(s.a char);", mysql.ErrWrongTableName) +} - // update without partition change - tk.MustExec("insert into t2 values(1, 'a'), (2, 'b'), (11, 'c'), (21, 'd')") - err = tk.ExecToErr("update t2 partition(p0, p1) set a = 40") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") - err = tk.ExecToErr("update t2 partition(p0) set a = 40 where a = 2") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") +func TestCheckIndex(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() - tk.MustExec("update t2 partition(p0) set a = 3 where a = 2") - tk.MustExec("update t2 partition(p0, p3) set a = 33 where a = 1") + ctx := mock.NewContext() + ctx.Store = store + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + defer se.Close() - tk.MustExec("create table t4(a int primary key, b int) partition by hash(a) partitions 2") - tk.MustExec("insert into t4(a, b) values(1, 1),(2, 2),(3, 3);") - err = tk.ExecToErr("update t4 partition(p0) set a = 5 where a = 2") - c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set") -} + _, err = se.Execute(context.Background(), "create database test_admin") + require.NoError(t, err) + _, err = se.Execute(context.Background(), "use test_admin") + require.NoError(t, err) + _, err = se.Execute(context.Background(), "create table t (pk int primary key, c int default 1, c1 int default 1, unique key c(c))") + require.NoError(t, err) -func (s *testSuiteP2) TestApplyCache(c *C) { - tk := testkit.NewTestKit(c, s.store) + is := dom.InfoSchema() + db := model.NewCIStr("test_admin") + dbInfo, ok := is.SchemaByName(db) + require.True(t, ok) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int);") - tk.MustExec("insert into t values (1),(1),(1),(1),(1),(1),(1),(1),(1);") - tk.MustExec("analyze table t;") - result := tk.MustQuery("explain analyze SELECT count(1) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;") - c.Assert(result.Rows()[1][0], Equals, "└─Apply_39") - var ( - ind int - flag bool - ) - value := (result.Rows()[1][5]).(string) - for ind = 0; ind < len(value)-5; ind++ { - if value[ind:ind+5] == "cache" { - flag = true - break - } - } - c.Assert(flag, Equals, true) - c.Assert(value[ind:], Equals, "cache:ON, cacheHitRatio:88.889%") + tblName := model.NewCIStr("t") + tbl, err := is.TableByName(db, tblName) + require.NoError(t, err) + tbInfo := tbl.Meta() - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int);") - tk.MustExec("insert into t values (1),(2),(3),(4),(5),(6),(7),(8),(9);") - tk.MustExec("analyze table t;") - result = tk.MustQuery("explain analyze SELECT count(1) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;") - c.Assert(result.Rows()[1][0], Equals, "└─Apply_39") - flag = false - value = (result.Rows()[1][5]).(string) - for ind = 0; ind < len(value)-5; ind++ { - if value[ind:ind+5] == "cache" { - flag = true - break - } - } - c.Assert(flag, Equals, true) - c.Assert(value[ind:], Equals, "cache:OFF") -} + alloc := autoid.NewAllocator(store, dbInfo.ID, tbInfo.ID, false, autoid.RowIDAllocType) + tb, err := tables.TableFromMeta(autoid.NewAllocators(alloc), tbInfo) + require.NoError(t, err) -// For issue 17256 -func (s *testSuite) TestGenerateColumnReplace(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int as (a + 1) virtual not null, unique index idx(b));") - tk.MustExec("REPLACE INTO `t1` (`a`) VALUES (2);") - tk.MustExec("REPLACE INTO `t1` (`a`) VALUES (2);") - tk.MustQuery("select * from t1").Check(testkit.Rows("2 3")) - tk.MustExec("insert into `t1` (`a`) VALUES (2) on duplicate key update a = 3;") - tk.MustQuery("select * from t1").Check(testkit.Rows("3 4")) -} + _, err = se.Execute(context.Background(), "admin check index t c") + require.NoError(t, err) -func (s *testSlowQuery) TestSlowQueryWithoutSlowLog(c *C) { - tk := testkit.NewTestKit(c, s.store) - originCfg := config.GetGlobalConfig() - newCfg := *originCfg - newCfg.Log.SlowQueryFile = "tidb-slow-not-exist.log" - newCfg.Log.SlowThreshold = math.MaxUint64 - config.StoreGlobalConfig(&newCfg) - defer func() { - config.StoreGlobalConfig(originCfg) - }() - tk.MustQuery("select query from information_schema.slow_query").Check(testkit.Rows()) - tk.MustQuery("select query from information_schema.slow_query where time > '2020-09-15 12:16:39' and time < now()").Check(testkit.Rows()) -} + _, err = se.Execute(context.Background(), "admin check index t C") + require.NoError(t, err) -func (s *testSlowQuery) TestSlowQuerySensitiveQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) - originCfg := config.GetGlobalConfig() - newCfg := *originCfg - - f, err := os.CreateTemp("", "tidb-slow-*.log") - c.Assert(err, IsNil) - f.Close() - newCfg.Log.SlowQueryFile = f.Name() - config.StoreGlobalConfig(&newCfg) - defer func() { - tk.MustExec("set tidb_slow_log_threshold=300;") - config.StoreGlobalConfig(originCfg) - err = os.Remove(newCfg.Log.SlowQueryFile) - c.Assert(err, IsNil) - }() - err = logutil.InitLogger(newCfg.Log.ToLogConfig()) - c.Assert(err, IsNil) - - tk.MustExec("set tidb_slow_log_threshold=0;") - tk.MustExec("drop user if exists user_sensitive;") - tk.MustExec("create user user_sensitive identified by '123456789';") - tk.MustExec("alter user 'user_sensitive'@'%' identified by 'abcdefg';") - tk.MustExec("set password for 'user_sensitive'@'%' = 'xyzuvw';") - tk.MustQuery("select query from `information_schema`.`slow_query` " + - "where (query like 'set password%' or query like 'create user%' or query like 'alter user%') " + - "and query like '%user_sensitive%' order by query;"). - Check(testkit.Rows( - "alter user {user_sensitive@% password = ***};", - "create user {user_sensitive@% password = ***};", - "set password for user user_sensitive@%;", - )) -} + // set data to: + // index data (handle, data): (1, 10), (2, 20) + // table data (handle, data): (1, 10), (2, 20) + recordVal1 := types.MakeDatums(int64(1), int64(10), int64(11)) + recordVal2 := types.MakeDatums(int64(2), int64(20), int64(21)) + require.NoError(t, ctx.NewTxn(context.Background())) + _, err = tb.AddRecord(ctx, recordVal1) + require.NoError(t, err) + _, err = tb.AddRecord(ctx, recordVal2) + require.NoError(t, err) + txn, err := ctx.Txn(true) + require.NoError(t, err) + require.NoError(t, txn.Commit(context.Background())) -func (s *testSlowQuery) TestSlowQueryPrepared(c *C) { - tk := testkit.NewTestKit(c, s.store) - originCfg := config.GetGlobalConfig() - newCfg := *originCfg - - f, err := os.CreateTemp("", "tidb-slow-*.log") - c.Assert(err, IsNil) - f.Close() - newCfg.Log.SlowQueryFile = f.Name() - config.StoreGlobalConfig(&newCfg) - defer func() { - tk.MustExec("set tidb_slow_log_threshold=300;") - tk.MustExec("set tidb_redact_log=0;") - config.StoreGlobalConfig(originCfg) - os.Remove(newCfg.Log.SlowQueryFile) - }() - err = logutil.InitLogger(newCfg.Log.ToLogConfig()) - c.Assert(err, IsNil) - - tk.MustExec("set tidb_slow_log_threshold=0;") - tk.MustExec(`prepare mystmt1 from 'select sleep(?), 1';`) - tk.MustExec("SET @num = 0.01;") - tk.MustExec("execute mystmt1 using @num;") - tk.MustQuery("SELECT Query FROM `information_schema`.`slow_query` " + - "where query like 'select%sleep%' order by time desc limit 1"). - Check(testkit.Rows( - "select sleep(?), 1 [arguments: 0.01];", - )) - - tk.MustExec("set tidb_redact_log=1;") - tk.MustExec(`prepare mystmt2 from 'select sleep(?), 2';`) - tk.MustExec("execute mystmt2 using @num;") - tk.MustQuery("SELECT Query FROM `information_schema`.`slow_query` " + - "where query like 'select%sleep%' order by time desc limit 1"). - Check(testkit.Rows( - "select `sleep` ( ? ) , ?;", - )) -} + mockCtx := mock.NewContext() + idx := tb.Indices()[0] + sc := &stmtctx.StatementContext{TimeZone: time.Local} -func (s *testSlowQuery) TestLogSlowLogIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) - f, err := os.CreateTemp("", "tidb-slow-*.log") - c.Assert(err, IsNil) - f.Close() + _, err = se.Execute(context.Background(), "admin check index t idx_inexistent") + require.Error(t, err) + require.Contains(t, err.Error(), "not exist") - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.Log.SlowQueryFile = f.Name() - }) - err = logutil.InitLogger(config.GetGlobalConfig().Log.ToLogConfig()) - c.Assert(err, IsNil) + // set data to: + // index data (handle, data): (1, 10), (2, 20), (3, 30) + // table data (handle, data): (1, 10), (2, 20), (4, 40) + txn, err = store.Begin() + require.NoError(t, err) + _, err = idx.Create(mockCtx, txn, types.MakeDatums(int64(30)), kv.IntHandle(3), nil) + require.NoError(t, err) + key := tablecodec.EncodeRowKey(tb.Meta().ID, kv.IntHandle(4).Encoded()) + setColValue(t, txn, key, types.NewDatum(int64(40))) + err = txn.Commit(context.Background()) + require.NoError(t, err) + _, err = se.Execute(context.Background(), "admin check index t c") + require.Error(t, err) + require.Equal(t, "[admin:8223]data inconsistency in table: t, index: c, handle: 3, index-values:\"handle: 3, values: [KindInt64 30 KindInt64 3]\" != record-values:\"\"", err.Error()) - tk.MustExec("use test") - tk.MustExec("create table t (a int, b int,index idx(a));") - tk.MustExec("set tidb_slow_log_threshold=0;") - tk.MustQuery("select * from t use index (idx) where a in (1) union select * from t use index (idx) where a in (2,3);") - tk.MustExec("set tidb_slow_log_threshold=300;") - tk.MustQuery("select index_names from `information_schema`.`slow_query` " + - "where query like 'select%union%' limit 1"). - Check(testkit.Rows( - "[t:idx]", - )) -} + // set data to: + // index data (handle, data): (1, 10), (2, 20), (3, 30), (4, 40) + // table data (handle, data): (1, 10), (2, 20), (4, 40) + txn, err = store.Begin() + require.NoError(t, err) + _, err = idx.Create(mockCtx, txn, types.MakeDatums(int64(40)), kv.IntHandle(4), nil) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + _, err = se.Execute(context.Background(), "admin check index t c") + require.Error(t, err) + require.Contains(t, err.Error(), "table count 3 != index(c) count 4") -func (s *testSlowQuery) TestSlowQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) - - f, err := os.CreateTemp("", "tidb-slow-*.log") - c.Assert(err, IsNil) - _, err = f.WriteString(` -# Time: 2020-10-13T20:08:13.970563+08:00 -select * from t; -# Time: 2020-10-16T20:08:13.970563+08:00 -select * from t; -`) - c.Assert(err, IsNil) - err = f.Close() - c.Assert(err, IsNil) - executor.ParseSlowLogBatchSize = 1 - originCfg := config.GetGlobalConfig() - newCfg := *originCfg - newCfg.Log.SlowQueryFile = f.Name() - config.StoreGlobalConfig(&newCfg) - defer func() { - executor.ParseSlowLogBatchSize = 64 - config.StoreGlobalConfig(originCfg) - err = os.Remove(newCfg.Log.SlowQueryFile) - c.Assert(err, IsNil) - }() - err = logutil.InitLogger(newCfg.Log.ToLogConfig()) - c.Assert(err, IsNil) - - tk.MustQuery("select count(*) from `information_schema`.`slow_query` where time > '2020-10-16 20:08:13' and time < '2020-10-16 21:08:13'").Check(testkit.Rows("1")) - tk.MustQuery("select count(*) from `information_schema`.`slow_query` where time > '2019-10-13 20:08:13' and time < '2020-10-16 21:08:13'").Check(testkit.Rows("2")) -} + // set data to: + // index data (handle, data): (1, 10), (4, 40) + // table data (handle, data): (1, 10), (2, 20), (4, 40) + txn, err = store.Begin() + require.NoError(t, err) + err = idx.Delete(sc, txn, types.MakeDatums(int64(30)), kv.IntHandle(3)) + require.NoError(t, err) + err = idx.Delete(sc, txn, types.MakeDatums(int64(20)), kv.IntHandle(2)) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + _, err = se.Execute(context.Background(), "admin check index t c") + require.Error(t, err) + require.Contains(t, err.Error(), "table count 3 != index(c) count 2") -func (s *testSerialSuite) TestKillTableReader(c *C) { - var retry = "github.com/tikv/client-go/v2/locate/mockRetrySendReqToRegion" - defer func() { - c.Assert(failpoint.Disable(retry), IsNil) - }() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int)") - tk.MustExec("insert into t values (1),(2),(3)") - tk.MustExec("set @@tidb_distsql_scan_concurrency=1") - atomic.StoreUint32(&tk.Se.GetSessionVars().Killed, 0) - c.Assert(failpoint.Enable(retry, `return(true)`), IsNil) - wg := &sync.WaitGroup{} - wg.Add(1) - go func() { - defer wg.Done() - time.Sleep(1 * time.Second) - err := tk.QueryToErr("select * from t") - c.Assert(err, NotNil) - c.Assert(int(terror.ToSQLError(errors.Cause(err).(*terror.Error)).Code), Equals, int(executor.ErrQueryInterrupted.Code())) - }() - atomic.StoreUint32(&tk.Se.GetSessionVars().Killed, 1) - wg.Wait() + // TODO: pass the case below: + // set data to: + // index data (handle, data): (1, 10), (4, 40), (2, 30) + // table data (handle, data): (1, 10), (2, 20), (4, 40) } -func (s *testSerialSuite) TestPrevStmtDesensitization(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec(fmt.Sprintf("set @@session.%v=1", variable.TiDBRedactLog)) - defer tk.MustExec(fmt.Sprintf("set @@session.%v=0", variable.TiDBRedactLog)) - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int, unique key (a))") - tk.MustExec("begin") - tk.MustExec("insert into t values (1),(2)") - c.Assert(tk.Se.GetSessionVars().PrevStmt.String(), Equals, "insert into `t` values ( ? ) , ( ? )") - c.Assert(tk.ExecToErr("insert into t values (1)").Error(), Equals, `[kv:1062]Duplicate entry '?' for key 'a'`) +func setColValue(t *testing.T, txn kv.Transaction, key kv.Key, v types.Datum) { + row := []types.Datum{v, {}} + colIDs := []int64{2, 3} + sc := &stmtctx.StatementContext{TimeZone: time.Local} + rd := rowcodec.Encoder{Enable: true} + value, err := tablecodec.EncodeRow(sc, row, colIDs, nil, nil, &rd) + require.NoError(t, err) + err = txn.Set(key, value) + require.NoError(t, err) } -func (s *testSuite) TestIssue19372(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1, t2;") - tk.MustExec("create table t1 (c_int int, c_str varchar(40), key(c_str));") - tk.MustExec("create table t2 like t1;") - tk.MustExec("insert into t1 values (1, 'a'), (2, 'b'), (3, 'c');") - tk.MustExec("insert into t2 select * from t1;") - tk.MustQuery("select (select t2.c_str from t2 where t2.c_str <= t1.c_str and t2.c_int in (1, 2) order by t2.c_str limit 1) x from t1 order by c_int;").Check(testkit.Rows("a", "a", "a")) -} +func TestCheckTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite1) TestCollectCopRuntimeStats(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int)") - tk.MustExec("set tidb_enable_collect_execution_info=1;") - c.Assert(failpoint.Enable("tikvclient/tikvStoreRespResult", `return(true)`), IsNil) - rows := tk.MustQuery("explain analyze select * from t1").Rows() - c.Assert(len(rows), Equals, 2) - explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*rpc_num: 2, .*regionMiss:.*") - c.Assert(failpoint.Disable("tikvclient/tikvStoreRespResult"), IsNil) + tk := testkit.NewTestKit(t, store) + // Test 'admin check table' when the table has a unique index with null values. + tk.MustExec("use test") + tk.MustExec("drop table if exists admin_test;") + tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2));") + tk.MustExec("insert admin_test (c1, c2) values (1, 1), (2, 2), (NULL, NULL);") + tk.MustExec("admin check table admin_test;") } -func (s *testSerialSuite1) TestIndexLookupRuntimeStats(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int, index(a))") - tk.MustExec("insert into t1 values (1,2),(2,3),(3,4)") - sql := "explain analyze select * from t1 use index(a) where a > 1;" - rows := tk.MustQuery(sql).Rows() - c.Assert(len(rows), Equals, 3) - explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*time:.*loops:.*index_task:.*table_task: {total_time.*num.*concurrency.*}.*") - indexExplain := fmt.Sprintf("%v", rows[1]) - tableExplain := fmt.Sprintf("%v", rows[2]) - c.Assert(indexExplain, Matches, ".*time:.*loops:.*cop_task:.*") - c.Assert(tableExplain, Matches, ".*time:.*loops:.*cop_task:.*") -} +func TestCheckTableClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite1) TestHashAggRuntimeStats(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int)") - tk.MustExec("insert into t1 values (1,2),(2,3),(3,4)") - sql := "explain analyze SELECT /*+ HASH_AGG() */ count(*) FROM t1 WHERE a < 10;" - rows := tk.MustQuery(sql).Rows() - c.Assert(len(rows), Equals, 5) - explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*time:.*loops:.*partial_worker:{wall_time:.*concurrency:.*task_num:.*tot_wait:.*tot_exec:.*tot_time:.*max:.*p95:.*}.*final_worker:{wall_time:.*concurrency:.*task_num:.*tot_wait:.*tot_exec:.*tot_time:.*max:.*p95:.*}.*") + tk.MustExec("drop table if exists admin_test;") + tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, primary key (c1, c2), index (c1), unique key(c2));") + tk.MustExec("insert admin_test (c1, c2) values (1, 1), (2, 2), (3, 3);") + tk.MustExec("admin check table admin_test;") } -func (s *testSerialSuite1) TestIndexMergeRuntimeStats(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t1") - tk.MustExec("set @@tidb_enable_index_merge = 1") - tk.MustExec("create table t1(id int primary key, a int, b int, c int, d int)") - tk.MustExec("create index t1a on t1(a)") - tk.MustExec("create index t1b on t1(b)") - tk.MustExec("insert into t1 values(1,1,1,1,1),(2,2,2,2,2),(3,3,3,3,3),(4,4,4,4,4),(5,5,5,5,5)") - sql := "explain analyze select /*+ use_index_merge(t1, primary, t1a) */ * from t1 where id < 2 or a > 4;" - rows := tk.MustQuery(sql).Rows() - c.Assert(len(rows), Equals, 4) - explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*time:.*loops:.*index_task:{fetch_handle:.*, merge:.*}.*table_task:{num.*concurrency.*fetch_row.*wait_time.*}.*") - tableRangeExplain := fmt.Sprintf("%v", rows[1]) - indexExplain := fmt.Sprintf("%v", rows[2]) - tableExplain := fmt.Sprintf("%v", rows[3]) - c.Assert(tableRangeExplain, Matches, ".*time:.*loops:.*cop_task:.*") - c.Assert(indexExplain, Matches, ".*time:.*loops:.*cop_task:.*") - c.Assert(tableExplain, Matches, ".*time:.*loops:.*cop_task:.*") - tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - sql = "select /*+ use_index_merge(t1, primary, t1a) */ * from t1 where id < 2 or a > 4 order by a" - tk.MustQuery(sql).Check(testkit.Rows("1 1 1 1 1", "5 5 5 5 5")) -} +func TestCoprocessorStreamingFlag(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite) TestCollectDMLRuntimeStats(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (a int, b int, unique index (a))") - - testSQLs := []string{ - "insert ignore into t1 values (5,5);", - "insert into t1 values (5,5) on duplicate key update a=a+1;", - "replace into t1 values (5,6),(6,7)", - "update t1 set a=a+1 where a=6;", + tk.MustExec("create table t (id int, value int, index idx(id))") + // Add some data to make statistics work. + for i := 0; i < 100; i++ { + tk.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i, i)) } - getRootStats := func() string { - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) - p, ok := info.Plan.(plannercore.Plan) - c.Assert(ok, IsTrue) - stats := tk.Se.GetSessionVars().StmtCtx.RuntimeStatsColl.GetRootStats(p.ID()) - return stats.String() - } - for _, sql := range testSQLs { - tk.MustExec(sql) - c.Assert(getRootStats(), Matches, "time.*loops.*Get.*num_rpc.*total_time.*") + tests := []struct { + sql string + expect bool + }{ + {"select * from t", true}, // TableReader + {"select * from t where id = 5", true}, // IndexLookup + {"select * from t where id > 5", true}, // Filter + {"select * from t limit 3", false}, // Limit + {"select avg(id) from t", false}, // Aggregate + {"select * from t order by value limit 3", false}, // TopN } - // Test for lock keys stats. - tk.MustExec("begin pessimistic") - tk.MustExec("update t1 set b=b+1") - c.Assert(getRootStats(), Matches, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustQuery("select * from t1 for update").Check(testkit.Rows("5 6", "7 7")) - c.Assert(getRootStats(), Matches, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustExec("insert ignore into t1 values (9,9)") - c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}}}.*") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustExec("insert into t1 values (10,10) on duplicate key update a=a+1") - c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}.*") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustExec("insert into t1 values (1,2)") - c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, insert:.*") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustExec("insert ignore into t1 values(11,11) on duplicate key update `a`=`a`+1") - c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:.*}") - tk.MustExec("rollback") - - tk.MustExec("begin pessimistic") - tk.MustExec("replace into t1 values (1,4)") - c.Assert(getRootStats(), Matches, "time:.*, loops:.*, prefetch:.*, rpc:.*") - tk.MustExec("rollback") + ctx := context.Background() + for _, test := range tests { + ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) { + comment := fmt.Sprintf("sql=%s, expect=%v, get=%v", test.sql, test.expect, req.Streaming) + require.Equal(t, test.expect, req.Streaming, comment) + }) + rs, err := tk.Session().Execute(ctx1, test.sql) + require.NoError(t, err) + tk.ResultSetToResult(rs[0], fmt.Sprintf("sql: %v", test.sql)) + } } -func (s *testSuite) TestIssue13758(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1 (pk int(11) primary key, a int(11) not null, b int(11), key idx_b(b), key idx_a(a))") - tk.MustExec("insert into `t1` values (1,1,0),(2,7,6),(3,2,null),(4,1,null),(5,4,5)") - tk.MustExec("create table t2 (a int)") - tk.MustExec("insert into t2 values (1),(null)") - tk.MustQuery("select (select a from t1 use index(idx_a) where b >= t2.a order by a limit 1) as field from t2").Check(testkit.Rows( - "4", - "", - )) -} +func TestIncorrectLimitArg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testCoprCache) SetUpSuite(c *C) { - originConfig := config.GetGlobalConfig() - config.StoreGlobalConfig(config.NewConfig()) - defer config.StoreGlobalConfig(originConfig) - cli := ®ionProperityClient{} - hijackClient := func(c tikv.Client) tikv.Client { - cli.Client = c - return cli - } - var err error - s.store, err = mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cls = c - }), - mockstore.WithClientHijacker(hijackClient), - ) - c.Assert(err, IsNil) - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test;`) + tk.MustExec(`create table t(a bigint);`) + tk.MustExec(`prepare stmt1 from 'select * from t limit ?';`) + tk.MustExec(`prepare stmt2 from 'select * from t limit ?, ?';`) + tk.MustExec(`set @a = -1;`) + tk.MustExec(`set @b = 1;`) -func (s *testCoprCache) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() + tk.MustGetErrMsg(`execute stmt1 using @a;`, `[planner:1210]Incorrect arguments to LIMIT`) + tk.MustGetErrMsg(`execute stmt2 using @b, @a;`, `[planner:1210]Incorrect arguments to LIMIT`) } -func (s *testCoprCache) TestIntegrationCopCache(c *C) { - originConfig := config.GetGlobalConfig() - config.StoreGlobalConfig(config.NewConfig()) - defer config.StoreGlobalConfig(originConfig) +func TestExecutorLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int primary key)") - tblInfo, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tid := tblInfo.Meta().ID - tk.MustExec(`insert into t values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)`) - tableStart := tablecodec.GenTableRecordPrefix(tid) - s.cls.SplitKeys(tableStart, tableStart.PrefixNext(), 6) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/cophandler/mockCopCacheInUnistore", `return(123)`), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/cophandler/mockCopCacheInUnistore"), IsNil) - }() - - rows := tk.MustQuery("explain analyze select * from t where t.a < 10").Rows() - c.Assert(rows[0][2], Equals, "9") - c.Assert(strings.Contains(rows[0][5].(string), "cop_task: {num: 5"), Equals, true) - c.Assert(strings.Contains(rows[0][5].(string), "copr_cache_hit_ratio: 0.00"), Equals, true) - - rows = tk.MustQuery("explain analyze select * from t").Rows() - c.Assert(rows[0][2], Equals, "12") - c.Assert(strings.Contains(rows[0][5].(string), "cop_task: {num: 6"), Equals, true) - hitRatioIdx := strings.Index(rows[0][5].(string), "copr_cache_hit_ratio:") + len("copr_cache_hit_ratio: ") - c.Assert(hitRatioIdx >= len("copr_cache_hit_ratio: "), Equals, true) - hitRatio, err := strconv.ParseFloat(rows[0][5].(string)[hitRatioIdx:hitRatioIdx+4], 64) - c.Assert(err, IsNil) - c.Assert(hitRatio > 0, Equals, true) - - // Test for cop cache disabled. - cfg := config.NewConfig() - cfg.TiKVClient.CoprCache.CapacityMB = 0 - config.StoreGlobalConfig(cfg) - rows = tk.MustQuery("explain analyze select * from t where t.a < 10").Rows() - c.Assert(rows[0][2], Equals, "9") - c.Assert(strings.Contains(rows[0][5].(string), "copr_cache: disabled"), Equals, true) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test;`) + tk.MustExec(`create table t(a bigint, b bigint);`) + tk.MustExec(`insert into t values(1, 1), (2, 2), (3, 30), (4, 40), (5, 5), (6, 6);`) + tk.MustQuery(`select * from t order by a limit 1, 1;`).Check(testkit.Rows("2 2")) + tk.MustQuery(`select * from t order by a limit 1, 2;`).Check(testkit.Rows("2 2", "3 30")) + tk.MustQuery(`select * from t order by a limit 1, 3;`).Check(testkit.Rows("2 2", "3 30", "4 40")) + tk.MustQuery(`select * from t order by a limit 1, 4;`).Check(testkit.Rows("2 2", "3 30", "4 40", "5 5")) -func (s *testSerialSuite) TestCoprocessorOOMTicase(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec(`set @@tidb_wait_split_region_finish=1`) - // create table for non keep-order case - tk.MustExec("drop table if exists t5") - tk.MustExec("create table t5(id int)") - tk.MustQuery(`split table t5 between (0) and (10000) regions 10`).Check(testkit.Rows("9 1")) - // create table for keep-order case - tk.MustExec("drop table if exists t6") - tk.MustExec("create table t6(id int, index(id))") - tk.MustQuery(`split table t6 between (0) and (10000) regions 10`).Check(testkit.Rows("10 1")) - tk.MustQuery("split table t6 INDEX id between (0) and (10000) regions 10;").Check(testkit.Rows("10 1")) - count := 10 - for i := 0; i < count; i++ { - tk.MustExec(fmt.Sprintf("insert into t5 (id) values (%v)", i)) - tk.MustExec(fmt.Sprintf("insert into t6 (id) values (%v)", i)) - } - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionLog - }) - testcases := []struct { - name string - sql string - }{ - { - name: "keep Order", - sql: "select id from t6 order by id", - }, - { - name: "non keep Order", - sql: "select id from t5", - }, - } + // test inline projection + tk.MustQuery(`select a from t where a > 0 limit 1, 1;`).Check(testkit.Rows("2")) + tk.MustQuery(`select a from t where a > 0 limit 1, 2;`).Check(testkit.Rows("2", "3")) + tk.MustQuery(`select b from t where a > 0 limit 1, 3;`).Check(testkit.Rows("2", "30", "40")) + tk.MustQuery(`select b from t where a > 0 limit 1, 4;`).Check(testkit.Rows("2", "30", "40", "5")) - f := func() { - for _, testcase := range testcases { - c.Log(testcase.name) - // larger than one copResponse, smaller than 2 copResponse - quota := 2*copr.MockResponseSizeForTest - 100 - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) - tk.Se = se - tk.MustExec("use test") - tk.MustExec(fmt.Sprintf("set @@tidb_mem_quota_query=%v;", quota)) - var expect []string - for i := 0; i < count; i++ { - expect = append(expect, fmt.Sprintf("%v", i)) - } - tk.MustQuery(testcase.sql).Sort().Check(testkit.Rows(expect...)) - // assert oom action worked by max consumed > memory quota - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(quota)) - se.Close() - } - } + // test @@tidb_init_chunk_size=2 + tk.MustExec(`set @@tidb_init_chunk_size=2;`) + tk.MustQuery(`select * from t where a > 0 limit 2, 1;`).Check(testkit.Rows("3 30")) + tk.MustQuery(`select * from t where a > 0 limit 2, 2;`).Check(testkit.Rows("3 30", "4 40")) + tk.MustQuery(`select * from t where a > 0 limit 2, 3;`).Check(testkit.Rows("3 30", "4 40", "5 5")) + tk.MustQuery(`select * from t where a > 0 limit 2, 4;`).Check(testkit.Rows("3 30", "4 40", "5 5", "6 6")) - // ticase-4169, trigger oom action twice after workers consuming all the data - err := failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4169", `return(true)`) - c.Assert(err, IsNil) - f() - err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4169") - c.Assert(err, IsNil) - // ticase-4170, trigger oom action twice after iterator receiving all the data. - err = failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4170", `return(true)`) - c.Assert(err, IsNil) - f() - err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4170") - c.Assert(err, IsNil) - // ticase-4171, trigger oom before reading or consuming any data - err = failpoint.Enable("github.com/pingcap/tidb/store/copr/ticase-4171", `return(true)`) - c.Assert(err, IsNil) - f() - err = failpoint.Disable("github.com/pingcap/tidb/store/copr/ticase-4171") - c.Assert(err, IsNil) + // test inline projection + tk.MustQuery(`select a from t order by a limit 2, 1;`).Check(testkit.Rows("3")) + tk.MustQuery(`select b from t order by a limit 2, 2;`).Check(testkit.Rows("30", "40")) + tk.MustQuery(`select a from t order by a limit 2, 3;`).Check(testkit.Rows("3", "4", "5")) + tk.MustQuery(`select b from t order by a limit 2, 4;`).Check(testkit.Rows("30", "40", "5", "6")) } -func (s *testSuite) TestIssue20237(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t, s") - tk.MustExec("create table t(a date, b float)") - tk.MustExec("create table s(b float)") - tk.MustExec(`insert into t values(NULL,-37), ("2011-11-04",105), ("2013-03-02",-22), ("2006-07-02",-56), (NULL,124), (NULL,111), ("2018-03-03",-5);`) - tk.MustExec(`insert into s values(-37),(105),(-22),(-56),(124),(105),(111),(-5);`) - tk.MustQuery(`select count(distinct t.a, t.b) from t join s on t.b= s.b;`).Check(testkit.Rows("4")) -} +func TestIndexScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite) TestIssue19148(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a decimal(16, 2));") - tk.MustExec("select * from t where a > any_value(a);") - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() - tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - c.Assert(int(tblInfo.Meta().Columns[0].Flag), Equals, 0) -} + tk.MustExec("create table t (a int unique)") + tk.MustExec("insert t values (-1), (2), (3), (5), (6), (7), (8), (9)") + tk.MustQuery("select a from t where a < 0 or (a >= 2.1 and a < 5.1) or ( a > 5.9 and a <= 7.9) or a > '8.1'").Check(testkit.Rows("-1", "3", "5", "6", "7", "9")) -func (s *testSuite) TestIssue19667(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (a DATETIME)") - tk.MustExec("INSERT INTO t VALUES('1988-04-17 01:59:59')") - tk.MustQuery(`SELECT DATE_ADD(a, INTERVAL 1 SECOND) FROM t`).Check(testkit.Rows("1988-04-17 02:00:00")) -} - -func issue20975Prepare(c *C, store kv.Storage) (*testkit.TestKit, *testkit.TestKit) { - tk1 := testkit.NewTestKit(c, store) - tk2 := testkit.NewTestKit(c, store) - tk1.MustExec("use test") - tk1.MustExec("drop table if exists t1, t2") - tk2.MustExec("use test") - tk1.MustExec("create table t1(id int primary key, c int)") - tk1.MustExec("insert into t1 values(1, 10), (2, 20)") - return tk1, tk2 -} - -func (s *testSuite) TestIssue20975UpdateNoChange(c *C) { - tk1, tk2 := issue20975Prepare(c, s.store) - tk1.MustExec("begin pessimistic") - tk1.MustExec("update t1 set c=c") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") -} - -func (s *testSuite) TestIssue20975SelectForUpdate(c *C) { - tk1, tk2 := issue20975Prepare(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + tk.MustExec("create table t (a int unique)") + tk.MustExec("insert t values (0)") + tk.MustQuery("select NULL from t ").Check(testkit.Rows("")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + // test for double read + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int unique, b int)") + tk.MustExec("insert t values (5, 0)") + tk.MustExec("insert t values (4, 0)") + tk.MustExec("insert t values (3, 0)") + tk.MustExec("insert t values (2, 0)") + tk.MustExec("insert t values (1, 0)") + tk.MustExec("insert t values (0, 0)") + tk.MustQuery("select * from t order by a limit 3").Check(testkit.Rows("0 0", "1 0", "2 0")) -func (s *testSuite) TestIssue20975SelectForUpdatePointGet(c *C) { - tk1, tk2 := issue20975Prepare(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id=1 for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int unique, b int)") + tk.MustExec("insert t values (0, 1)") + tk.MustExec("insert t values (1, 2)") + tk.MustExec("insert t values (2, 1)") + tk.MustExec("insert t values (3, 2)") + tk.MustExec("insert t values (4, 1)") + tk.MustExec("insert t values (5, 2)") + tk.MustQuery("select * from t where a < 5 and b = 1 limit 2").Check(testkit.Rows("0 1", "2 1")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id=1 for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + tk.MustExec("drop table if exists tab1") + tk.MustExec("CREATE TABLE tab1(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col3 INTEGER, col4 FLOAT)") + tk.MustExec("CREATE INDEX idx_tab1_0 on tab1 (col0)") + tk.MustExec("CREATE INDEX idx_tab1_1 on tab1 (col1)") + tk.MustExec("CREATE INDEX idx_tab1_3 on tab1 (col3)") + tk.MustExec("CREATE INDEX idx_tab1_4 on tab1 (col4)") + tk.MustExec("INSERT INTO tab1 VALUES(1,37,20.85,30,10.69)") + tk.MustQuery("SELECT pk FROM tab1 WHERE ((col3 <= 6 OR col3 < 29 AND (col0 < 41)) OR col3 > 42) AND col1 >= 96.1 AND col3 = 30 AND col3 > 17 AND (col0 BETWEEN 36 AND 42)").Check(testkit.Rows()) -func (s *testSuite) TestIssue20975SelectForUpdateBatchPointGet(c *C) { - tk1, tk2 := issue20975Prepare(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id in (1, 2) for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + tk.MustExec("drop table if exists tab1") + tk.MustExec("CREATE TABLE tab1(pk INTEGER PRIMARY KEY, a INTEGER, b INTEGER)") + tk.MustExec("CREATE INDEX idx_tab1_0 on tab1 (a)") + tk.MustExec("INSERT INTO tab1 VALUES(1,1,1)") + tk.MustExec("INSERT INTO tab1 VALUES(2,2,1)") + tk.MustExec("INSERT INTO tab1 VALUES(3,1,2)") + tk.MustExec("INSERT INTO tab1 VALUES(4,2,2)") + tk.MustQuery("SELECT * FROM tab1 WHERE pk <= 3 AND a = 1").Check(testkit.Rows("1 1 1", "3 1 2")) + tk.MustQuery("SELECT * FROM tab1 WHERE pk <= 4 AND a = 1 AND b = 2").Check(testkit.Rows("3 1 2")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id in (1, 2) for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + tk.MustExec("CREATE INDEX idx_tab1_1 on tab1 (b, a)") + tk.MustQuery("SELECT pk FROM tab1 WHERE b > 1").Check(testkit.Rows("3", "4")) -func issue20975PreparePartitionTable(c *C, store kv.Storage) (*testkit.TestKit, *testkit.TestKit) { - tk1 := testkit.NewTestKit(c, store) - tk2 := testkit.NewTestKit(c, store) - tk1.MustExec("use test") - tk1.MustExec("drop table if exists t1, t2") - tk2.MustExec("use test") - tk1.MustExec(`create table t1(id int primary key, c int) partition by range (id) ( - partition p1 values less than (10), - partition p2 values less than (20) - )`) - tk1.MustExec("insert into t1 values(1, 10), (2, 20), (11, 30), (12, 40)") - return tk1, tk2 -} + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a varchar(3), index(a))") + tk.MustExec("insert t values('aaa'), ('aab')") + tk.MustQuery("select * from t where a >= 'aaaa' and a < 'aabb'").Check(testkit.Rows("aab")) -func (s *testSuite) TestIssue20975UpdateNoChangeWithPartitionTable(c *C) { - tk1, tk2 := issue20975PreparePartitionTable(c, s.store) + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE t (a int primary key, b int, c int, index(c))") + tk.MustExec("insert t values(1, 1, 1), (2, 2, 2), (4, 4, 4), (3, 3, 3), (5, 5, 5)") + // Test for double read and top n. + tk.MustQuery("select a from t where c >= 2 order by b desc limit 1").Check(testkit.Rows("5")) - // Set projection concurrency to avoid data race here. - // TODO: remove this line after fixing https://github.com/pingcap/tidb/issues/25496 - tk1.Se.GetSessionVars().Concurrency.SetProjectionConcurrency(0) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a varchar(50) primary key, b int, c int, index idx(b))") + tk.MustExec("insert into t values('aa', 1, 1)") + tk.MustQuery("select * from t use index(idx) where a > 'a'").Check(testkit.Rows("aa 1 1")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("update t1 set c=c") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // fix issue9636 + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE `t` (a int, KEY (a))") + tk.MustQuery(`SELECT * FROM (SELECT * FROM (SELECT a as d FROM t WHERE a IN ('100')) AS x WHERE x.d < "123" ) tmp_count`).Check(testkit.Rows()) } -func (s *testSuite) TestIssue20975SelectForUpdateWithPartitionTable(c *C) { - tk1, tk2 := issue20975PreparePartitionTable(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") +func TestUpdateJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1(k int, v int)") + tk.MustExec("create table t2(k int, v int)") + tk.MustExec("create table t3(id int auto_increment, k int, v int, primary key(id))") + tk.MustExec("create table t4(k int, v int)") + tk.MustExec("create table t5(v int, k int, primary key(k))") + tk.MustExec("insert into t1 values (1, 1)") + tk.MustExec("insert into t4 values (3, 3)") + tk.MustExec("create table t6 (id int, v longtext)") + tk.MustExec("create table t7 (x int, id int, v longtext, primary key(id))") -func (s *testSuite) TestIssue20975SelectForUpdatePointGetWithPartitionTable(c *C) { - tk1, tk2 := issue20975PreparePartitionTable(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id=1 for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // test the normal case that update one row for a single table. + tk.MustExec("update t1 set v = 0 where k = 1") + tk.MustQuery("select k, v from t1 where k = 1").Check(testkit.Rows("1 0")) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id=12 for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") + // test the case that the table with auto_increment or none-null columns as the right table of left join. + tk.MustExec("update t1 left join t3 on t1.k = t3.k set t1.v = 1") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 1")) + tk.MustQuery("select id, k, v from t3").Check(testkit.Rows()) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id=1 for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // test left join and the case that the right table has no matching record but has updated the right table columns. + tk.MustExec("update t1 left join t2 on t1.k = t2.k set t1.v = t2.v, t2.v = 3") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 ")) + tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id=12 for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + // test the case that the update operation in the left table references data in the right table while data of the right table columns is modified. + tk.MustExec("update t1 left join t2 on t1.k = t2.k set t2.v = 3, t1.v = t2.v") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 ")) + tk.MustQuery("select k, v from t2").Check(testkit.Rows()) -func (s *testSuite) TestIssue20975SelectForUpdateBatchPointGetWithPartitionTable(c *C) { - tk1, tk2 := issue20975PreparePartitionTable(c, s.store) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id in (1, 2) for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // test right join and the case that the left table has no matching record but has updated the left table columns. + tk.MustExec("update t2 right join t1 on t2.k = t1.k set t2.v = 4, t1.v = 0") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 0")) + tk.MustQuery("select k, v from t2").Check(testkit.Rows()) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id in (11, 12) for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") + // test the case of right join and left join at the same time. + tk.MustExec("update t1 left join t2 on t1.k = t2.k right join t4 on t4.k = t2.k set t1.v = 4, t2.v = 4, t4.v = 4") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 0")) + tk.MustQuery("select k, v from t2").Check(testkit.Rows()) + tk.MustQuery("select k, v from t4").Check(testkit.Rows("3 4")) - tk1.MustExec("begin") - tk1.MustExec("select * from t1 where id in (1, 11) for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // test normal left join and the case that the right table has matching rows. + tk.MustExec("insert t2 values (1, 10)") + tk.MustExec("update t1 left join t2 on t1.k = t2.k set t2.v = 11") + tk.MustQuery("select k, v from t2").Check(testkit.Rows("1 11")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id in (1, 2) for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") + // test the case of continuously joining the same table and updating the unmatching records. + tk.MustExec("update t1 t11 left join t2 on t11.k = t2.k left join t1 t12 on t2.v = t12.k set t12.v = 233, t11.v = 111") + tk.MustQuery("select k, v from t1").Check(testkit.Rows("1 111")) + tk.MustQuery("select k, v from t2").Check(testkit.Rows("1 11")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id in (11, 12) for update") - tk2.MustExec("create table t2(a int)") - tk1.MustExec("commit") + // test the left join case that the left table has records but all records are null. + tk.MustExec("delete from t1") + tk.MustExec("delete from t2") + tk.MustExec("insert into t1 values (null, null)") + tk.MustExec("update t1 left join t2 on t1.k = t2.k set t1.v = 1") + tk.MustQuery("select k, v from t1").Check(testkit.Rows(" 1")) - tk1.MustExec("begin pessimistic") - tk1.MustExec("select * from t1 where id in (1, 11) for update") - tk2.MustExec("drop table t2") - tk1.MustExec("commit") -} + // test the case that the right table of left join has an primary key. + tk.MustExec("insert t5 values(0, 0)") + tk.MustExec("update t1 left join t5 on t1.k = t5.k set t1.v = 2") + tk.MustQuery("select k, v from t1").Check(testkit.Rows(" 2")) + tk.MustQuery("select k, v from t5").Check(testkit.Rows("0 0")) -func (s *testSuite) TestIssue20305(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t2 (a year(4))") - tk.MustExec("insert into t2 values(69)") - tk.MustQuery("select * from t2 where a <= 69").Check(testkit.Rows("2069")) - // the following test is a regression test that matches MySQL's behavior. - tk.MustExec("drop table if exists t3") - tk.MustExec("CREATE TABLE `t3` (`y` year DEFAULT NULL, `a` int DEFAULT NULL)") - tk.MustExec("INSERT INTO `t3` VALUES (2069, 70), (2010, 11), (2155, 2156), (2069, 69)") - tk.MustQuery("SELECT * FROM `t3` where y <= a").Check(testkit.Rows("2155 2156")) -} + tk.MustExec("insert into t6 values (1, NULL)") + tk.MustExec("insert into t7 values (5, 1, 'a')") + tk.MustExec("update t6, t7 set t6.v = t7.v where t6.id = t7.id and t7.x = 5") + tk.MustQuery("select v from t6").Check(testkit.Rows("a")) -func (s *testSuite) TestIssue22817(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t3") - tk.MustExec("create table t3 (a year)") - tk.MustExec("insert into t3 values (1991), (\"1992\"), (\"93\"), (94)") - tk.MustQuery("select * from t3 where a >= NULL").Check(testkit.Rows()) + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(id int primary key, v int, gv int GENERATED ALWAYS AS (v * 2) STORED)") + tk.MustExec("create table t2(id int, v int)") + tk.MustExec("update t1 tt1 inner join (select count(t1.id) a, t1.id from t1 left join t2 on t1.id = t2.id group by t1.id) x on tt1.id = x.id set tt1.v = tt1.v + x.a") } -func (s *testSuite) TestIssue13953(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestScanControlSelection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE `t` (`id` int(11) DEFAULT NULL, `tp_bigint` bigint(20) DEFAULT NULL )") - tk.MustExec("insert into t values(0,1),(1,9215570218099803537)") - tk.MustQuery("select A.tp_bigint,B.id from t A join t B on A.id < B.id * 16 where A.tp_bigint = B.id;").Check( - testkit.Rows("1 1")) -} - -func (s *testSuite) TestZeroDateTimeCompatibility(c *C) { - SQLs := []string{ - `select YEAR(0000-00-00), YEAR("0000-00-00")`, - `select MONTH(0000-00-00), MONTH("0000-00-00")`, - `select DAYOFWEEK(0000-00-00), DAYOFWEEK("0000-00-00")`, - `select DAYOFMONTH(0000-00-00), DAYOFMONTH("0000-00-00")`, - `select DAYOFYEAR(0000-00-00), DAYOFYEAR("0000-00-00")`, - `select QUARTER(0000-00-00), QUARTER("0000-00-00")`, - `select EXTRACT(DAY FROM 0000-00-00), EXTRACT(DAY FROM "0000-00-00")`, - `select EXTRACT(MONTH FROM 0000-00-00), EXTRACT(MONTH FROM "0000-00-00")`, - `select EXTRACT(YEAR FROM 0000-00-00), EXTRACT(YEAR FROM "0000-00-00")`, - `select EXTRACT(WEEK FROM 0000-00-00), EXTRACT(WEEK FROM "0000-00-00")`, - `select EXTRACT(QUARTER FROM 0000-00-00), EXTRACT(QUARTER FROM "0000-00-00")`, - } - tk := testkit.NewTestKit(c, s.store) - - for _, t := range SQLs { - fmt.Println(t) - tk.MustQuery(t).Check(testkit.Rows("0 ")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - } + tk.MustExec("create table t(a int primary key, b int, c int, index idx_b(b))") + tk.MustExec("insert into t values (1, 1, 1), (2, 1, 1), (3, 1, 2), (4, 2, 3)") + tk.MustQuery("select (select count(1) k from t s where s.b = t1.c) from t t1").Sort().Check(testkit.Rows("0", "1", "3", "3")) } -// https://github.com/pingcap/tidb/issues/24165. -func (s *testSuite) TestInvalidDateValueInCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - - // Test for sql mode 'NO_ZERO_IN_DATE'. - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE';") - tk.MustGetErrCode("create table t (a datetime default '2999-00-00 00:00:00');", errno.ErrInvalidDefault) - tk.MustExec("create table t (a datetime);") - tk.MustGetErrCode("alter table t modify column a datetime default '2999-00-00 00:00:00';", errno.ErrInvalidDefault) - tk.MustExec("drop table if exists t;") +func TestSimpleDAG(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - // Test for sql mode 'NO_ZERO_DATE'. - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_DATE';") - tk.MustGetErrCode("create table t (a datetime default '0000-00-00 00:00:00');", errno.ErrInvalidDefault) - tk.MustExec("create table t (a datetime);") - tk.MustGetErrCode("alter table t modify column a datetime default '0000-00-00 00:00:00';", errno.ErrInvalidDefault) - tk.MustExec("drop table if exists t;") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int primary key, b int, c int)") + tk.MustExec("insert into t values (1, 1, 1), (2, 1, 1), (3, 1, 2), (4, 2, 3)") + tk.MustQuery("select a from t").Check(testkit.Rows("1", "2", "3", "4")) + tk.MustQuery("select * from t where a = 4").Check(testkit.Rows("4 2 3")) + tk.MustQuery("select a from t limit 1").Check(testkit.Rows("1")) + tk.MustQuery("select a from t order by a desc").Check(testkit.Rows("4", "3", "2", "1")) + tk.MustQuery("select a from t order by a desc limit 1").Check(testkit.Rows("4")) + tk.MustQuery("select a from t order by b desc limit 1").Check(testkit.Rows("4")) + tk.MustQuery("select a from t where a < 3").Check(testkit.Rows("1", "2")) + tk.MustQuery("select a from t where b > 1").Check(testkit.Rows("4")) + tk.MustQuery("select a from t where b > 1 and a < 3").Check(testkit.Rows()) + tk.MustQuery("select count(*) from t where b > 1 and a < 3").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from t").Check(testkit.Rows("4")) + tk.MustQuery("select count(*), c from t group by c order by c").Check(testkit.Rows("2 1", "1 2", "1 3")) + tk.MustQuery("select sum(c) as s from t group by b order by s").Check(testkit.Rows("3", "4")) + tk.MustQuery("select avg(a) as s from t group by b order by s").Check(testkit.Rows("2.0000", "4.0000")) + tk.MustQuery("select sum(distinct c) from t group by b").Check(testkit.Rows("3", "3")) - // Remove NO_ZERO_DATE and NO_ZERO_IN_DATE. - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES';") - // Test create table with zero datetime as a default value. - tk.MustExec("create table t (a datetime default '2999-00-00 00:00:00');") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a datetime default '0000-00-00 00:00:00');") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a datetime);") - tk.MustExec("alter table t modify column a datetime default '2999-00-00 00:00:00';") - tk.MustExec("alter table t modify column a datetime default '0000-00-00 00:00:00';") - tk.MustExec("drop table if exists t;") + tk.MustExec("create index i on t(c,b)") + tk.MustQuery("select a from t where c = 1").Check(testkit.Rows("1", "2")) + tk.MustQuery("select a from t where c = 1 and a < 2").Check(testkit.Rows("1")) + tk.MustQuery("select a from t where c = 1 order by a limit 1").Check(testkit.Rows("1")) + tk.MustQuery("select count(*) from t where c = 1 ").Check(testkit.Rows("2")) + tk.MustExec("create index i1 on t(b)") + tk.MustQuery("select c from t where b = 2").Check(testkit.Rows("3")) + tk.MustQuery("select * from t where b = 2").Check(testkit.Rows("4 2 3")) + tk.MustQuery("select count(*) from t where b = 1").Check(testkit.Rows("3")) + tk.MustQuery("select * from t where b = 1 and a > 1 limit 1").Check(testkit.Rows("2 1 1")) - // Test create table with invalid datetime(02-30) as a default value. - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES';") - tk.MustGetErrCode("create table t (a datetime default '2999-02-30 00:00:00');", errno.ErrInvalidDefault) - tk.MustExec("drop table if exists t;") - // NO_ZERO_IN_DATE and NO_ZERO_DATE have nothing to do with invalid datetime(02-30). - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE';") - tk.MustGetErrCode("create table t (a datetime default '2999-02-30 00:00:00');", errno.ErrInvalidDefault) - tk.MustExec("drop table if exists t;") - // ALLOW_INVALID_DATES allows invalid datetime(02-30). - tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,ALLOW_INVALID_DATES';") - tk.MustExec("create table t (a datetime default '2999-02-30 00:00:00');") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a datetime);") - tk.MustExec("alter table t modify column a datetime default '2999-02-30 00:00:00';") - tk.MustExec("drop table if exists t;") -} + // Test time push down. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int, c1 datetime);") + tk.MustExec("insert into t values (1, '2015-06-07 12:12:12')") + tk.MustQuery("select id from t where c1 = '2015-06-07 12:12:12'").Check(testkit.Rows("1")) -func (s *testSuite) TestOOMActionPriority(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") + // Test issue 17816 tk.MustExec("drop table if exists t0") - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("drop table if exists t3") - tk.MustExec("drop table if exists t4") - tk.MustExec("create table t0(a int)") - tk.MustExec("insert into t0 values(1)") - tk.MustExec("create table t1(a int)") - tk.MustExec("insert into t1 values(1)") - tk.MustExec("create table t2(a int)") - tk.MustExec("insert into t2 values(1)") - tk.MustExec("create table t3(a int)") - tk.MustExec("insert into t3 values(1)") - tk.MustExec("create table t4(a int)") - tk.MustExec("insert into t4 values(1)") - tk.MustQuery("select * from t0 join t1 join t2 join t3 join t4 order by t0.a").Check(testkit.Rows("1 1 1 1 1")) - action := tk.Se.GetSessionVars().StmtCtx.MemTracker.GetFallbackForTest() - // check the first 5 actions is rate limit. - for i := 0; i < 5; i++ { - c.Assert(action.GetPriority(), Equals, int64(memory.DefRateLimitPriority)) - action = action.GetFallback() - } - for action.GetFallback() != nil { - c.Assert(action.GetPriority(), Equals, int64(memory.DefSpillPriority)) - action = action.GetFallback() - } - c.Assert(action.GetPriority(), Equals, int64(memory.DefLogPriority)) + tk.MustExec("CREATE TABLE t0(c0 INT)") + tk.MustExec("INSERT INTO t0 VALUES (100000)") + tk.MustQuery("SELECT * FROM t0 WHERE NOT SPACE(t0.c0)").Check(testkit.Rows("100000")) } -func (s *testSerialSuite) TestIssue21441(c *C) { - failpoint.Enable("github.com/pingcap/tidb/executor/issue21441", `return`) - defer failpoint.Disable("github.com/pingcap/tidb/executor/issue21441") +func TestTimestampTimeZone(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - tk.MustExec(`insert into t values(1),(2),(3)`) - tk.Se.GetSessionVars().InitChunkSize = 1 - tk.Se.GetSessionVars().MaxChunkSize = 1 - sql := ` -select a from t union all -select a from t union all -select a from t union all -select a from t union all -select a from t union all -select a from t union all -select a from t union all -select a from t` - tk.MustQuery(sql).Sort().Check(testkit.Rows( - "1", "1", "1", "1", "1", "1", "1", "1", - "2", "2", "2", "2", "2", "2", "2", "2", - "3", "3", "3", "3", "3", "3", "3", "3", - )) + tk.MustExec("create table t (ts timestamp)") + tk.MustExec("set time_zone = '+00:00'") + tk.MustExec("insert into t values ('2017-04-27 22:40:42')") + // The timestamp will get different value if time_zone session variable changes. + tests := []struct { + timezone string + expect string + }{ + {"+10:00", "2017-04-28 08:40:42"}, + {"-6:00", "2017-04-27 16:40:42"}, + } + for _, tt := range tests { + tk.MustExec(fmt.Sprintf("set time_zone = '%s'", tt.timezone)) + tk.MustQuery("select * from t").Check(testkit.Rows(tt.expect)) + } - tk.MustQuery("select a from (" + sql + ") t order by a limit 4").Check(testkit.Rows("1", "1", "1", "1")) - tk.MustQuery("select a from (" + sql + ") t order by a limit 7, 4").Check(testkit.Rows("1", "2", "2", "2")) + // For issue https://github.com/pingcap/tidb/issues/3467 + tk.MustExec("drop table if exists t1") + tk.MustExec(`CREATE TABLE t1 ( + id bigint(20) NOT NULL AUTO_INCREMENT, + uid int(11) DEFAULT NULL, + datetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + ip varchar(128) DEFAULT NULL, + PRIMARY KEY (id), + KEY i_datetime (datetime), + KEY i_userid (uid) + );`) + tk.MustExec(`INSERT INTO t1 VALUES (123381351,1734,"2014-03-31 08:57:10","127.0.0.1");`) + r := tk.MustQuery("select datetime from t1;") // Cover TableReaderExec + r.Check(testkit.Rows("2014-03-31 08:57:10")) + r = tk.MustQuery("select datetime from t1 where datetime='2014-03-31 08:57:10';") + r.Check(testkit.Rows("2014-03-31 08:57:10")) // Cover IndexReaderExec + r = tk.MustQuery("select * from t1 where datetime='2014-03-31 08:57:10';") + r.Check(testkit.Rows("123381351 1734 2014-03-31 08:57:10 127.0.0.1")) // Cover IndexLookupExec - tk.MustExec("set @@tidb_executor_concurrency = 2") - c.Assert(tk.Se.GetSessionVars().UnionConcurrency(), Equals, 2) - tk.MustQuery("select a from (" + sql + ") t order by a limit 4").Check(testkit.Rows("1", "1", "1", "1")) - tk.MustQuery("select a from (" + sql + ") t order by a limit 7, 4").Check(testkit.Rows("1", "2", "2", "2")) + // For issue https://github.com/pingcap/tidb/issues/3485 + tk.MustExec("set time_zone = 'Asia/Shanghai'") + tk.MustExec("drop table if exists t1") + tk.MustExec(`CREATE TABLE t1 ( + id bigint(20) NOT NULL AUTO_INCREMENT, + datetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id) + );`) + tk.MustExec(`INSERT INTO t1 VALUES (123381351,"2014-03-31 08:57:10");`) + r = tk.MustQuery(`select * from t1 where datetime="2014-03-31 08:57:10";`) + r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) + tk.MustExec(`alter table t1 add key i_datetime (datetime);`) + r = tk.MustQuery(`select * from t1 where datetime="2014-03-31 08:57:10";`) + r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) + r = tk.MustQuery(`select * from t1;`) + r.Check(testkit.Rows("123381351 2014-03-31 08:57:10")) + r = tk.MustQuery("select datetime from t1 where datetime='2014-03-31 08:57:10';") + r.Check(testkit.Rows("2014-03-31 08:57:10")) } -func (s *testSuite) Test17780(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t0") - tk.MustExec("create table t0 (c0 double)") - tk.MustExec("insert into t0 values (1e30)") - tk.MustExec("update t0 set c0=0 where t0.c0 like 0") - // the update should not affect c0 - tk.MustQuery("select count(*) from t0 where c0 = 0").Check(testkit.Rows("0")) -} +func TestTimestampDefaultValueTimeZone(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite) TestIssue9918(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a year)") - tk.MustExec("insert into t values(0)") - tk.MustQuery("select cast(a as char) from t").Check(testkit.Rows("0000")) -} + tk.MustExec("set time_zone = '+08:00'") + tk.MustExec(`create table t (a int, b timestamp default "2019-01-17 14:46:14")`) + tk.MustExec("insert into t set a=1") + r := tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 14:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("set time_zone = '+00:00'") + tk.MustExec("insert into t set a=2") + r = tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 06:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + r = tk.MustQuery(`select a,b from t order by a`) + r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14")) + // Test the column's version is greater than ColumnInfoVersion1. + is := domain.GetDomain(tk.Session()).InfoSchema() + require.NotNil(t, is) + tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tb.Cols()[1].Version = model.ColumnInfoVersion1 + 1 + tk.MustExec("insert into t set a=3") + r = tk.MustQuery(`select a,b from t order by a`) + r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14", "3 2019-01-17 06:46:14")) + tk.MustExec("delete from t where a=3") + // Change time zone back. + tk.MustExec("set time_zone = '+08:00'") + r = tk.MustQuery(`select a,b from t order by a`) + r.Check(testkit.Rows("1 2019-01-17 14:46:14", "2 2019-01-17 14:46:14")) + tk.MustExec("set time_zone = '-08:00'") + r = tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-16 22:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) -func (s *testSuite) Test13004(c *C) { - tk := testkit.NewTestKit(c, s.store) - // see https://dev.mysql.com/doc/refman/5.6/en/date-and-time-literals.html, timestamp here actually produces a datetime - tk.MustQuery("SELECT TIMESTAMP '9999-01-01 00:00:00'").Check(testkit.Rows("9999-01-01 00:00:00")) -} + // test zero default value in multiple time zone. + defer tk.MustExec(fmt.Sprintf("set @@sql_mode='%s'", tk.MustQuery("select @@sql_mode").Rows()[0][0])) + tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';") + tk.MustExec("drop table if exists t") + tk.MustExec("set time_zone = '+08:00'") + tk.MustExec(`create table t (a int, b timestamp default "0000-00-00 00")`) + tk.MustExec("insert into t set a=1") + r = tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("set time_zone = '+00:00'") + tk.MustExec("insert into t set a=2") + r = tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustExec("set time_zone = '-08:00'") + tk.MustExec("insert into t set a=3") + r = tk.MustQuery(`show create table t`) + r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + r = tk.MustQuery(`select a,b from t order by a`) + r.Check(testkit.Rows("1 0000-00-00 00:00:00", "2 0000-00-00 00:00:00", "3 0000-00-00 00:00:00")) -func (s *testSuite) Test12178(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists ta") - tk.MustExec("create table ta(id decimal(60,2))") - tk.MustExec("insert into ta values (JSON_EXTRACT('{\"c\": \"1234567890123456789012345678901234567890123456789012345\"}', '$.c'))") - tk.MustQuery("select * from ta").Check(testkit.Rows("1234567890123456789012345678901234567890123456789012345.00")) -} + // test add timestamp column default current_timestamp. + tk.MustExec(`drop table if exists t`) + tk.MustExec(`set time_zone = 'Asia/Shanghai'`) + tk.MustExec(`create table t (a int)`) + tk.MustExec(`insert into t set a=1`) + tk.MustExec(`alter table t add column b timestamp not null default current_timestamp;`) + timeIn8 := tk.MustQuery("select b from t").Rows()[0][0] + tk.MustExec(`set time_zone = '+00:00'`) + timeIn0 := tk.MustQuery("select b from t").Rows()[0][0] + require.NotEqual(t, timeIn8, timeIn0) + datumTimeIn8, err := expression.GetTimeValue(tk.Session(), timeIn8, mysql.TypeTimestamp, 0) + require.NoError(t, err) + tIn8To0 := datumTimeIn8.GetMysqlTime() + timeZoneIn8, err := time.LoadLocation("Asia/Shanghai") + require.NoError(t, err) + err = tIn8To0.ConvertTimeZone(timeZoneIn8, time.UTC) + require.NoError(t, err) + require.Equal(t, tIn8To0.String(), timeIn0) -func (s *testSuite) Test11883(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (f1 json)") - tk.MustExec("insert into t1(f1) values ('\"asd\"'),('\"asdf\"'),('\"asasas\"')") - tk.MustQuery("select f1 from t1 where json_extract(f1,\"$\") in (\"asd\",\"asasas\",\"asdf\")").Check(testkit.Rows("\"asd\"", "\"asdf\"", "\"asasas\"")) - tk.MustQuery("select f1 from t1 where json_extract(f1, '$') = 'asd'").Check(testkit.Rows("\"asd\"")) - // MySQL produces empty row for the following SQL, I doubt it should be MySQL's bug. - tk.MustQuery("select f1 from t1 where case json_extract(f1,\"$\") when \"asd\" then 1 else 0 end").Check(testkit.Rows("\"asd\"")) - tk.MustExec("delete from t1") - tk.MustExec("insert into t1 values ('{\"a\": 1}')") - // the first value in the tuple should be interpreted as string instead of JSON, so no row will be returned - tk.MustQuery("select f1 from t1 where f1 in ('{\"a\": 1}', 'asdf', 'asdf')").Check(testkit.Rows()) - // and if we explicitly cast it into a JSON value, the check will pass - tk.MustQuery("select f1 from t1 where f1 in (cast('{\"a\": 1}' as JSON), 'asdf', 'asdf')").Check(testkit.Rows("{\"a\": 1}")) - tk.MustQuery("select json_extract('\"asd\"', '$') = 'asd'").Check(testkit.Rows("1")) - tk.MustQuery("select json_extract('\"asd\"', '$') <=> 'asd'").Check(testkit.Rows("1")) - tk.MustQuery("select json_extract('\"asd\"', '$') <> 'asd'").Check(testkit.Rows("0")) - tk.MustQuery("select json_extract('{\"f\": 1.0}', '$.f') = 1.0").Check(testkit.Rows("1")) - tk.MustQuery("select json_extract('{\"f\": 1.0}', '$.f') = '1.0'").Check(testkit.Rows("0")) - tk.MustQuery("select json_extract('{\"n\": 1}', '$') = '{\"n\": 1}'").Check(testkit.Rows("0")) - tk.MustQuery("select json_extract('{\"n\": 1}', '$') <> '{\"n\": 1}'").Check(testkit.Rows("1")) -} + // test add index. + tk.MustExec(`alter table t add index(b);`) + tk.MustExec("admin check table t") + tk.MustExec(`set time_zone = '+05:00'`) + tk.MustExec("admin check table t") -func (s *testSuite) Test15492(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int, b int)") - tk.MustExec("insert into t values (2, 20), (1, 10), (3, 30)") - tk.MustQuery("select a + 1 as field1, a as field2 from t order by field1, field2 limit 2").Check(testkit.Rows("2 1", "3 2")) + // 1. add a timestamp general column + // 2. add the index + tk.MustExec(`drop table if exists t`) + // change timezone + tk.MustExec(`set time_zone = 'Asia/Shanghai'`) + tk.MustExec(`create table t(a timestamp default current_timestamp)`) + tk.MustExec(`insert into t set a=now()`) + tk.MustExec(`alter table t add column b timestamp as (a+1) virtual;`) + // change timezone + tk.MustExec(`set time_zone = '+05:00'`) + tk.MustExec(`insert into t set a=now()`) + tk.MustExec(`alter table t add index(b);`) + tk.MustExec("admin check table t") + tk.MustExec(`set time_zone = '-03:00'`) + tk.MustExec("admin check table t") } -func (s testSuite) TestTrackAggMemoryUsage(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTiDBCurrentTS(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk.MustExec("use test") - tk.MustExec("create table t(a int)") - tk.MustExec("insert into t values(1)") - - tk.MustExec("set tidb_track_aggregate_memory_usage = off;") - rows := tk.MustQuery("explain analyze select /*+ HASH_AGG() */ sum(a) from t").Rows() - c.Assert(rows[0][7], Equals, "N/A") - rows = tk.MustQuery("explain analyze select /*+ STREAM_AGG() */ sum(a) from t").Rows() - c.Assert(rows[0][7], Equals, "N/A") - tk.MustExec("set tidb_track_aggregate_memory_usage = on;") - rows = tk.MustQuery("explain analyze select /*+ HASH_AGG() */ sum(a) from t").Rows() - c.Assert(rows[0][7], Not(Equals), "N/A") - rows = tk.MustQuery("explain analyze select /*+ STREAM_AGG() */ sum(a) from t").Rows() - c.Assert(rows[0][7], Not(Equals), "N/A") -} + tk := testkit.NewTestKit(t, store) + tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0")) + tk.MustExec("begin") + rows := tk.MustQuery("select @@tidb_current_ts").Rows() + tsStr := rows[0][0].(string) + txn, err := tk.Session().Txn(true) + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("%d", txn.StartTS()), tsStr) + tk.MustExec("begin") + rows = tk.MustQuery("select @@tidb_current_ts").Rows() + newTsStr := rows[0][0].(string) + txn, err = tk.Session().Txn(true) + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("%d", txn.StartTS()), newTsStr) + require.NotEqual(t, tsStr, newTsStr) + tk.MustExec("commit") + tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0")) -func (s *testSuite) Test12201(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists e") - tk.MustExec("create table e (e enum('a', 'b'))") - tk.MustExec("insert into e values ('a'), ('b')") - tk.MustQuery("select * from e where case 1 when 0 then e end").Check(testkit.Rows()) - tk.MustQuery("select * from e where case 1 when 1 then e end").Check(testkit.Rows("a", "b")) - tk.MustQuery("select * from e where case e when 1 then e end").Check(testkit.Rows("a")) - tk.MustQuery("select * from e where case 1 when e then e end").Check(testkit.Rows("a")) + err = tk.ExecToErr("set @@tidb_current_ts = '1'") + require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err: %v", err)) } -func (s *testSuite) TestIssue21451(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestTiDBLastTxnInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("create table t (en enum('c', 'b', 'a'));") - tk.MustExec("insert into t values ('a'), ('b'), ('c');") - tk.MustQuery("select max(en) from t;").Check(testkit.Rows("c")) - tk.MustQuery("select min(en) from t;").Check(testkit.Rows("a")) - tk.MustQuery("select * from t order by en;").Check(testkit.Rows("c", "b", "a")) - - tk.MustExec("drop table t") - tk.MustExec("create table t(s set('c', 'b', 'a'));") - tk.MustExec("insert into t values ('a'), ('b'), ('c');") - tk.MustQuery("select max(s) from t;").Check(testkit.Rows("c")) - tk.MustQuery("select min(s) from t;").Check(testkit.Rows("a")) - - tk.MustExec("drop table t") - tk.MustExec("create table t(id int, en enum('c', 'b', 'a'))") - tk.MustExec("insert into t values (1, 'a'),(2, 'b'), (3, 'c'), (1, 'c');") - tk.MustQuery("select id, max(en) from t where id=1 group by id;").Check(testkit.Rows("1 c")) - tk.MustQuery("select id, min(en) from t where id=1 group by id;").Check(testkit.Rows("1 a")) - tk.MustExec("drop table t") + tk.MustExec("create table t (a int primary key)") + tk.MustQuery("select @@tidb_last_txn_info").Check(testkit.Rows("")) - tk.MustExec("create table t(id int, s set('c', 'b', 'a'));") - tk.MustExec("insert into t values (1, 'a'),(2, 'b'), (3, 'c'), (1, 'c');") - tk.MustQuery("select id, max(s) from t where id=1 group by id;").Check(testkit.Rows("1 c")) - tk.MustQuery("select id, min(s) from t where id=1 group by id;").Check(testkit.Rows("1 a")) + tk.MustExec("insert into t values (1)") + rows1 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() + require.Greater(t, rows1[0][0].(string), "0") + require.Less(t, rows1[0][0].(string), rows1[0][1].(string)) - tk.MustExec("drop table t") - tk.MustExec("create table t(e enum('e','d','c','b','a'))") - tk.MustExec("insert into t values ('e'),('d'),('c'),('b'),('a');") - tk.MustQuery("select * from t order by e limit 1;").Check(testkit.Rows("e")) + tk.MustExec("begin") + tk.MustQuery("select a from t where a = 1").Check(testkit.Rows("1")) + rows2 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows() + tk.MustExec("commit") + rows3 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() + require.Equal(t, rows1[0][0], rows2[0][0]) + require.Equal(t, rows1[0][1], rows2[0][1]) + require.Equal(t, rows1[0][0], rows3[0][0]) + require.Equal(t, rows1[0][1], rows3[0][1]) + require.Less(t, rows2[0][1], rows2[0][2]) - tk.MustExec("drop table t") - tk.MustExec("create table t(s set('e', 'd', 'c', 'b', 'a'))") - tk.MustExec("insert into t values ('e'),('d'),('c'),('b'),('a');") - tk.MustQuery("select * from t order by s limit 1;").Check(testkit.Rows("e")) - tk.MustExec("drop table t") -} + tk.MustExec("begin") + tk.MustExec("update t set a = a + 1 where a = 1") + rows4 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows() + tk.MustExec("commit") + rows5 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() + require.Equal(t, rows1[0][0], rows4[0][0]) + require.Equal(t, rows1[0][1], rows4[0][1]) + require.Equal(t, rows5[0][0], rows4[0][2]) + require.Less(t, rows4[0][1], rows4[0][2]) + require.Less(t, rows4[0][2], rows5[0][1]) -func (s *testSuite) TestIssue15563(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery("select distinct 0.7544678906163867 / 0.68234634;").Check(testkit.Rows("1.10569639842486251190")) -} + tk.MustExec("begin") + tk.MustExec("update t set a = a + 1 where a = 2") + tk.MustExec("rollback") + rows6 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() + require.Equal(t, rows5[0][0], rows6[0][0]) + require.Equal(t, rows5[0][1], rows6[0][1]) -func (s *testSuite) TestIssue22231(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t_issue_22231") - tk.MustExec("create table t_issue_22231(a datetime)") - tk.MustExec("insert into t_issue_22231 values('2020--05-20 01:22:12')") - tk.MustQuery("select * from t_issue_22231 where a >= '2020-05-13 00:00:00 00:00:00' and a <= '2020-05-28 23:59:59 00:00:00'").Check(testkit.Rows("2020-05-20 01:22:12")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-13 00:00:00 00:00:00'", "Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) - - tk.MustQuery("select cast('2020-10-22 10:31-10:12' as datetime)").Check(testkit.Rows("2020-10-22 10:31:10")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-10-22 10:31-10:12'")) - tk.MustQuery("select cast('2020-05-28 23:59:59 00:00:00' as datetime)").Check(testkit.Rows("2020-05-28 23:59:59")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect datetime value: '2020-05-28 23:59:59 00:00:00'")) - tk.MustExec("drop table if exists t_issue_22231") -} + tk.MustExec("begin optimistic") + tk.MustExec("insert into t values (2)") + err := tk.ExecToErr("commit") + require.Error(t, err) + rows7 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), json_extract(@@tidb_last_txn_info, '$.error')").Rows() + require.Greater(t, rows7[0][0], rows5[0][0]) + require.Equal(t, "0", rows7[0][1]) + require.Contains(t, err.Error(), rows7[0][1]) -func (s *testSuite) TestIssue22201(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustQuery("SELECT HEX(WEIGHT_STRING('ab' AS BINARY(1000000000000000000)));").Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1301 Result of cast_as_binary() was larger than max_allowed_packet (67108864) - truncated")) - tk.MustQuery("SELECT HEX(WEIGHT_STRING('ab' AS char(1000000000000000000)));").Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1301 Result of weight_string() was larger than max_allowed_packet (67108864) - truncated")) + err = tk.ExecToErr("set @@tidb_last_txn_info = '{}'") + require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err: %v", err)) } -func (s *testSuiteP1) TestIssue22941(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists m, mp") - tk.MustExec(`CREATE TABLE m ( - mid varchar(50) NOT NULL, - ParentId varchar(50) DEFAULT NULL, - PRIMARY KEY (mid), - KEY ind_bm_parent (ParentId,mid) - )`) - // mp should have more columns than m - tk.MustExec(`CREATE TABLE mp ( - mpid bigint(20) unsigned NOT NULL DEFAULT '0', - mid varchar(50) DEFAULT NULL COMMENT '模å—主键', - sid int, - PRIMARY KEY (mpid) - );`) - - tk.MustExec(`insert into mp values("1","1","0");`) - tk.MustExec(`insert into m values("0", "0");`) - rs := tk.MustQuery(`SELECT ( SELECT COUNT(1) FROM m WHERE ParentId = c.mid ) expand, bmp.mpid, bmp.mpid IS NULL,bmp.mpid IS NOT NULL, sid FROM m c LEFT JOIN mp bmp ON c.mid = bmp.mid WHERE c.ParentId = '0'`) - rs.Check(testkit.Rows("1 1 0 ")) - - rs = tk.MustQuery(`SELECT bmp.mpid, bmp.mpid IS NULL,bmp.mpid IS NOT NULL FROM m c LEFT JOIN mp bmp ON c.mid = bmp.mid WHERE c.ParentId = '0'`) - rs.Check(testkit.Rows(" 1 0")) -} +func TestTiDBLastQueryInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite) TestTxnWriteThroughputSLI(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int key, b int)") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput", "return(true)"), IsNil) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput") - c.Assert(err, IsNil) - }() - - mustExec := func(sql string) { - tk.MustExec(sql) - tk.Se.GetTxnWriteThroughputSLI().FinishExecuteStmt(time.Second, tk.Se.AffectedRows(), tk.Se.GetSessionVars().InTxn()) - } - errExec := func(sql string) { - _, err := tk.Exec(sql) - c.Assert(err, NotNil) - tk.Se.GetTxnWriteThroughputSLI().FinishExecuteStmt(time.Second, tk.Se.AffectedRows(), tk.Se.GetSessionVars().InTxn()) - } + tk.MustExec("create table t (a int primary key, v int)") + tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.start_ts')").Check(testkit.Rows("0 0")) - // Test insert in small txn - mustExec("insert into t values (1,3),(2,4)") - writeSLI := tk.Se.GetTxnWriteThroughputSLI() - c.Assert(writeSLI.IsInvalid(), Equals, false) - c.Assert(writeSLI.IsSmallTxn(), Equals, true) - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 2, writeSize: 58, readKeys: 0, writeKeys: 2, writeTime: 1s") - tk.Se.GetTxnWriteThroughputSLI().Reset() - - // Test insert ... select ... from - mustExec("insert into t select b, a from t") - c.Assert(writeSLI.IsInvalid(), Equals, true) - c.Assert(writeSLI.IsSmallTxn(), Equals, true) - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: true, affectRow: 2, writeSize: 58, readKeys: 0, writeKeys: 2, writeTime: 1s") - tk.Se.GetTxnWriteThroughputSLI().Reset() - - // Test for delete - mustExec("delete from t") - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 4, writeSize: 76, readKeys: 0, writeKeys: 4, writeTime: 1s") - tk.Se.GetTxnWriteThroughputSLI().Reset() - - // Test insert not in small txn - mustExec("begin") - for i := 0; i < 20; i++ { - mustExec(fmt.Sprintf("insert into t values (%v,%v)", i, i)) - c.Assert(writeSLI.IsSmallTxn(), Equals, true) + toUint64 := func(str interface{}) uint64 { + res, err := strconv.ParseUint(str.(string), 10, 64) + require.NoError(t, err) + return res } - // The statement which affect rows is 0 shouldn't record into time. - mustExec("select count(*) from t") - mustExec("select * from t") - mustExec("insert into t values (20,20)") - c.Assert(writeSLI.IsSmallTxn(), Equals, false) - mustExec("commit") - c.Assert(writeSLI.IsInvalid(), Equals, false) - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 21, writeSize: 609, readKeys: 0, writeKeys: 21, writeTime: 22s") - tk.Se.GetTxnWriteThroughputSLI().Reset() - - // Test invalid when transaction has replace ... select ... from ... statement. - mustExec("delete from t") - tk.Se.GetTxnWriteThroughputSLI().Reset() - mustExec("begin") - mustExec("insert into t values (1,3),(2,4)") - mustExec("replace into t select b, a from t") - mustExec("commit") - c.Assert(writeSLI.IsInvalid(), Equals, true) - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: true, affectRow: 4, writeSize: 116, readKeys: 0, writeKeys: 4, writeTime: 3s") - tk.Se.GetTxnWriteThroughputSLI().Reset() - - // Test clean last failed transaction information. - err := failpoint.Disable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput") - c.Assert(err, IsNil) - mustExec("begin") - mustExec("insert into t values (1,3),(2,4)") - errExec("commit") - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 0, writeSize: 0, readKeys: 0, writeKeys: 0, writeTime: 0s") - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/util/sli/CheckTxnWriteThroughput", "return(true)"), IsNil) - mustExec("begin") - mustExec("insert into t values (5, 6)") - mustExec("commit") - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 1, writeSize: 29, readKeys: 0, writeKeys: 1, writeTime: 2s") - - // Test for reset - tk.Se.GetTxnWriteThroughputSLI().Reset() - c.Assert(tk.Se.GetTxnWriteThroughputSLI().String(), Equals, "invalid: false, affectRow: 0, writeSize: 0, readKeys: 0, writeKeys: 0, writeTime: 0s") -} -func (s *testSuite) TestIssue23993(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - // Real cast to time should return NULL - tk.MustExec("drop table if exists t_issue_23993") - tk.MustExec("create table t_issue_23993(a double)") - tk.MustExec("insert into t_issue_23993 values(-790822912)") - tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) - tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) - // Int cast to time should return NULL - tk.MustExec("drop table if exists t_issue_23993") - tk.MustExec("create table t_issue_23993(a int)") - tk.MustExec("insert into t_issue_23993 values(-790822912)") - tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) - tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) - // Decimal cast to time should return NULL - tk.MustExec("drop table if exists t_issue_23993") - tk.MustExec("create table t_issue_23993(a decimal)") - tk.MustExec("insert into t_issue_23993 values(-790822912)") - tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("")) - tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows()) - // String cast to time should not return NULL - tk.MustExec("drop table if exists t_issue_23993") - tk.MustExec("create table t_issue_23993(a varchar(255))") - tk.MustExec("insert into t_issue_23993 values('-790822912')") - tk.MustQuery("select cast(a as time) from t_issue_23993").Check(testkit.Rows("-838:59:59")) - tk.MustQuery("select a from t_issue_23993 where cast(a as time)").Check(testkit.Rows("-790822912")) -} + tk.MustExec("select * from t") + rows := tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Equal(t, rows[0][1], rows[0][0]) -func (s *testSuiteP2) TestProjectionBitType(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t(k1 int, v bit(34) DEFAULT b'111010101111001001100111101111111', primary key(k1) clustered);") - tk.MustExec("create table t1(k1 int, v bit(34) DEFAULT b'111010101111001001100111101111111', primary key(k1) nonclustered);") - tk.MustExec("insert into t(k1) select 1;") - tk.MustExec("insert into t1(k1) select 1;") - - tk.MustExec("set @@tidb_enable_vectorized_expression = 0;") - // following SQL should returns same result - tk.MustQuery("(select * from t where false) union(select * from t for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) - tk.MustQuery("(select * from t1 where false) union(select * from t1 for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) - - tk.MustExec("set @@tidb_enable_vectorized_expression = 1;") - tk.MustQuery("(select * from t where false) union(select * from t for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) - tk.MustQuery("(select * from t1 where false) union(select * from t1 for update);").Check(testkit.Rows("1 \x01\xd5\xe4\xcf\u007f")) -} + tk.MustExec("insert into t values (1, 10)") + rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Equal(t, rows[0][1], rows[0][0]) + // tidb_last_txn_info is still valid after checking query info. + rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Less(t, rows[0][0].(string), rows[0][1].(string)) -func (s *testSuite) TestIssue23609(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t1") - tk.MustExec("CREATE TABLE `t1` (\n `a` timestamp NULL DEFAULT NULL,\n `b` year(4) DEFAULT NULL,\n KEY `a` (`a`),\n KEY `b` (`b`)\n)") - tk.MustExec("insert into t1 values(\"2002-10-03 04:28:53\",2000), (\"2002-10-03 04:28:53\",2002), (NULL, 2002)") - tk.MustQuery("select /*+ inl_join (x,y) */ * from t1 x cross join t1 y on x.a=y.b").Check(testkit.Rows()) - tk.MustQuery("select * from t1 x cross join t1 y on x.a>y.b order by x.a, x.b, y.a, y.b").Check(testkit.Rows("2002-10-03 04:28:53 2000 2002", "2002-10-03 04:28:53 2000 2002-10-03 04:28:53 2000", "2002-10-03 04:28:53 2000 2002-10-03 04:28:53 2002", "2002-10-03 04:28:53 2002 2002", "2002-10-03 04:28:53 2002 2002-10-03 04:28:53 2000", "2002-10-03 04:28:53 2002 2002-10-03 04:28:53 2002")) - tk.MustQuery("select * from t1 where a = b").Check(testkit.Rows()) - tk.MustQuery("select * from t1 where a < b").Check(testkit.Rows()) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) -} + tk.MustExec("begin pessimistic") + tk.MustExec("select * from t") + rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Equal(t, rows[0][1], rows[0][0]) -func (s *testSuite1) TestIssue24091(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - defer tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int) partition by hash (a div 0) partitions 10;") - tk.MustExec("insert into t values (NULL);") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("update t set v = 11 where a = 1") - tk.MustQuery("select null div 0;").Check(testkit.Rows("")) - tk.MustQuery("select * from t;").Check(testkit.Rows("")) -} + tk.MustExec("select * from t") + rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Equal(t, rows[0][1], rows[0][0]) -func (s *testSerialSuite) TestIssue24210(c *C) { - tk := testkit.NewTestKit(c, s.store) - - // for ProjectionExec - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/mockProjectionExecBaseExecutorOpenReturnedError", `return(true)`), IsNil) - _, err := tk.Exec("select a from (select 1 as a, 2 as b) t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "mock ProjectionExec.baseExecutor.Open returned error") - err = failpoint.Disable("github.com/pingcap/tidb/executor/mockProjectionExecBaseExecutorOpenReturnedError") - c.Assert(err, IsNil) - - // for HashAggExec - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/mockHashAggExecBaseExecutorOpenReturnedError", `return(true)`), IsNil) - _, err = tk.Exec("select sum(a) from (select 1 as a, 2 as b) t group by b") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "mock HashAggExec.baseExecutor.Open returned error") - err = failpoint.Disable("github.com/pingcap/tidb/executor/mockHashAggExecBaseExecutorOpenReturnedError") - c.Assert(err, IsNil) - - // for StreamAggExec - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/mockStreamAggExecBaseExecutorOpenReturnedError", `return(true)`), IsNil) - _, err = tk.Exec("select sum(a) from (select 1 as a, 2 as b) t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "mock StreamAggExec.baseExecutor.Open returned error") - err = failpoint.Disable("github.com/pingcap/tidb/executor/mockStreamAggExecBaseExecutorOpenReturnedError") - c.Assert(err, IsNil) - - // for SelectionExec - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/mockSelectionExecBaseExecutorOpenReturnedError", `return(true)`), IsNil) - _, err = tk.Exec("select * from (select rand() as a) t where a > 0") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "mock SelectionExec.baseExecutor.Open returned error") - err = failpoint.Disable("github.com/pingcap/tidb/executor/mockSelectionExecBaseExecutorOpenReturnedError") - c.Assert(err, IsNil) -} + tk.MustExec("update t set v = 12 where a = 1") + rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Less(t, toUint64(rows[0][0]), toUint64(rows[0][1])) -func (s *testSerialSuite) TestDeadlocksTable(c *C) { - deadlockhistory.GlobalDeadlockHistory.Clear() - deadlockhistory.GlobalDeadlockHistory.Resize(10) + tk.MustExec("commit") - occurTime := time.Date(2021, 5, 10, 1, 2, 3, 456789000, time.Local) - rec := &deadlockhistory.DeadlockRecord{ - OccurTime: occurTime, - IsRetryable: false, - WaitChain: []deadlockhistory.WaitChainItem{ - { - TryLockTxn: 101, - SQLDigest: "aabbccdd", - Key: []byte("k1"), - AllSQLDigests: nil, - TxnHoldingLock: 102, - }, - { - TryLockTxn: 102, - SQLDigest: "ddccbbaa", - Key: []byte("k2"), - AllSQLDigests: []string{"sql1"}, - TxnHoldingLock: 101, - }, - }, - } - deadlockhistory.GlobalDeadlockHistory.Push(rec) + tk.MustExec("set transaction isolation level read committed") + tk.MustExec("begin pessimistic") + tk.MustExec("select * from t") + rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows() + require.Greater(t, toUint64(rows[0][0]), uint64(0)) + require.Less(t, toUint64(rows[0][0]), toUint64(rows[0][1])) - occurTime2 := time.Date(2022, 6, 11, 2, 3, 4, 987654000, time.Local) - rec2 := &deadlockhistory.DeadlockRecord{ - OccurTime: occurTime2, - IsRetryable: true, - WaitChain: []deadlockhistory.WaitChainItem{ - { - TryLockTxn: 201, - AllSQLDigests: []string{}, - TxnHoldingLock: 202, - }, - { - TryLockTxn: 202, - AllSQLDigests: []string{"sql1", "sql2, sql3"}, - TxnHoldingLock: 203, - }, - { - TryLockTxn: 203, - TxnHoldingLock: 201, - }, - }, - } - deadlockhistory.GlobalDeadlockHistory.Push(rec2) - - // `Push` sets the record's ID, and ID in a single DeadlockHistory is monotonically increasing. We must get it here - // to know what it is. - id1 := strconv.FormatUint(rec.ID, 10) - id2 := strconv.FormatUint(rec2.ID, 10) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/sqlDigestRetrieverSkipRetrieveGlobal", "return"), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/expression/sqlDigestRetrieverSkipRetrieveGlobal"), IsNil) - }() - - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery("select * from information_schema.deadlocks").Check( - testutil.RowsWithSep("/", - id1+"/2021-05-10 01:02:03.456789/0/101/aabbccdd//6B31//102", - id1+"/2021-05-10 01:02:03.456789/0/102/ddccbbaa//6B32//101", - id2+"/2022-06-11 02:03:04.987654/1/201/////202", - id2+"/2022-06-11 02:03:04.987654/1/202/////203", - id2+"/2022-06-11 02:03:04.987654/1/203/////201", - )) + tk.MustExec("rollback") } -func (s testSerialSuite) TestExprBlackListForEnum(c *C) { - tk := testkit.NewTestKit(c, s.store) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a enum('a','b','c'), b enum('a','b','c'), c int, index idx(b,a));") - tk.MustExec("insert into t values(1,1,1),(2,2,2),(3,3,3);") - - checkFuncPushDown := func(rows [][]interface{}, keyWord string) bool { - for _, line := range rows { - // Agg/Expr push down - if line[2].(string) == "cop[tikv]" && strings.Contains(line[4].(string), keyWord) { - return true - } - // access index - if line[2].(string) == "cop[tikv]" && strings.Contains(line[3].(string), keyWord) { - return true - } - } - return false - } - - // Test agg(enum) push down - tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows := tk.MustQuery("desc format='brief' select /*+ HASH_AGG() */ max(a) from t;").Rows() - c.Assert(checkFuncPushDown(rows, "max"), IsFalse) - rows = tk.MustQuery("desc format='brief' select /*+ STREAM_AGG() */ max(a) from t;").Rows() - c.Assert(checkFuncPushDown(rows, "max"), IsFalse) - - tk.MustExec("delete from mysql.expr_pushdown_blacklist;") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows = tk.MustQuery("desc format='brief' select /*+ HASH_AGG() */ max(a) from t;").Rows() - c.Assert(checkFuncPushDown(rows, "max"), IsTrue) - rows = tk.MustQuery("desc format='brief' select /*+ STREAM_AGG() */ max(a) from t;").Rows() - c.Assert(checkFuncPushDown(rows, "max"), IsTrue) - - // Test expr(enum) push down - tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() - c.Assert(checkFuncPushDown(rows, "plus"), IsFalse) - rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() - c.Assert(checkFuncPushDown(rows, "plus"), IsFalse) - - tk.MustExec("delete from mysql.expr_pushdown_blacklist;") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() - c.Assert(checkFuncPushDown(rows, "plus"), IsTrue) - rows = tk.MustQuery("desc format='brief' select * from t where a + b;").Rows() - c.Assert(checkFuncPushDown(rows, "plus"), IsTrue) - - // Test enum index - tk.MustExec("insert into mysql.expr_pushdown_blacklist(name) values('enum');") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows = tk.MustQuery("desc format='brief' select * from t where b = 1;").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) - rows = tk.MustQuery("desc format='brief' select * from t where b = 'a';").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) - rows = tk.MustQuery("desc format='brief' select * from t where b > 1;").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) - rows = tk.MustQuery("desc format='brief' select * from t where b > 'a';").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b)"), IsFalse) - - tk.MustExec("delete from mysql.expr_pushdown_blacklist;") - tk.MustExec("admin reload expr_pushdown_blacklist;") - rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a = 1;").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) - rows = tk.MustQuery("desc format='brief' select * from t where b = 'a' and a = 'a';").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) - rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a > 1;").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) - rows = tk.MustQuery("desc format='brief' select * from t where b = 1 and a > 'a'").Rows() - c.Assert(checkFuncPushDown(rows, "index:idx(b, a)"), IsTrue) -} +func TestSelectForUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testResourceTagSuite) TestResourceGroupTag(c *C) { - if israce.RaceEnabled { - c.Skip("unstable, skip it and fix it before 20210622") - } - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int, b int, unique index idx(a));") - tbInfo := testGetTableByName(c, tk.Se, "test", "t") - - // Enable Top SQL - variable.TopSQLVariable.Enable.Store(true) - config.UpdateGlobal(func(conf *config.Config) { - conf.TopSQL.ReceiverAddress = "mock-agent" - }) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook", `return(true)`), IsNil) - defer failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook") - - var sqlDigest, planDigest *parser.Digest - var tagLabel tipb.ResourceGroupTagLabel - checkFn := func() {} - unistore.UnistoreRPCClientSendHook = func(req *tikvrpc.Request) { - var startKey []byte - var ctx *kvrpcpb.Context - switch req.Type { - case tikvrpc.CmdGet: - request := req.Get() - startKey = request.Key - ctx = request.Context - case tikvrpc.CmdBatchGet: - request := req.BatchGet() - startKey = request.Keys[0] - ctx = request.Context - case tikvrpc.CmdPrewrite: - request := req.Prewrite() - startKey = request.Mutations[0].Key - ctx = request.Context - case tikvrpc.CmdCommit: - request := req.Commit() - startKey = request.Keys[0] - ctx = request.Context - case tikvrpc.CmdCop: - request := req.Cop() - startKey = request.Ranges[0].Start - ctx = request.Context - case tikvrpc.CmdPessimisticLock: - request := req.PessimisticLock() - startKey = request.PrimaryLock - ctx = request.Context - } - tid := tablecodec.DecodeTableID(startKey) - if tid != tbInfo.Meta().ID { - return - } - if ctx == nil { - return - } - tag := &tipb.ResourceGroupTag{} - err := tag.Unmarshal(ctx.ResourceGroupTag) - c.Assert(err, IsNil) - sqlDigest = parser.NewDigest(tag.SqlDigest) - planDigest = parser.NewDigest(tag.PlanDigest) - tagLabel = *tag.Label - checkFn() - } - - resetVars := func() { - sqlDigest = parser.NewDigest(nil) - planDigest = parser.NewDigest(nil) - } - - cases := []struct { - sql string - tagLabels map[tipb.ResourceGroupTagLabel]struct{} - ignore bool - }{ - { - sql: "insert into t values(1,1),(2,2),(3,3)", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "select * from t use index (idx) where a=1", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "select * from t use index (idx) where a in (1,2,3)", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "select * from t use index (idx) where a>1", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "select * from t where b>1", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, - }, - }, - { - sql: "select a from t use index (idx) where a>1", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "begin pessimistic", - ignore: true, - }, - { - sql: "insert into t values(4,4)", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "commit", - ignore: true, - }, - { - sql: "update t set a=5,b=5 where a=5", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - { - sql: "replace into t values(6,6)", - tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ - tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, - }, - }, - } - for _, ca := range cases { - resetVars() - commentf := Commentf("%v", ca.sql) - - _, expectSQLDigest := parser.NormalizeDigest(ca.sql) - var expectPlanDigest *parser.Digest - checkCnt := 0 - checkFn = func() { - if ca.ignore { - return - } - if expectPlanDigest == nil { - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) - p, ok := info.Plan.(plannercore.Plan) - c.Assert(ok, IsTrue) - _, expectPlanDigest = plannercore.NormalizePlan(p) - } - c.Assert(sqlDigest.String(), Equals, expectSQLDigest.String(), commentf) - c.Assert(planDigest.String(), Equals, expectPlanDigest.String()) - _, ok := ca.tagLabels[tagLabel] - c.Assert(ok, Equals, true) - checkCnt++ - } - - if strings.HasPrefix(ca.sql, "select") { - tk.MustQuery(ca.sql) - } else { - tk.MustExec(ca.sql) - } - if ca.ignore { - continue - } - c.Assert(checkCnt > 0, IsTrue, commentf) - } -} + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") -func (s *testSuite) TestIssue24933(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk.MustExec("drop table if exists t, t1") - tk.MustExec("use test") - tk.MustExec("drop table if exists t;") - tk.MustExec("drop view if exists v;") - tk.MustExec("create table t(a int);") - tk.MustExec("insert into t values(1), (2), (3);") - - tk.MustExec("create definer='root'@'localhost' view v as select count(*) as c1 from t;") - rows := tk.MustQuery("select * from v;") - rows.Check(testkit.Rows("3")) - - // Test subquery and outer field is wildcard. - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(*) from t) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("3")) - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select avg(a) from t group by a) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("1.0000", "2.0000", "3.0000")) - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select sum(a) from t group by a) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("1", "2", "3")) - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select group_concat(a) from t group by a) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("1", "2", "3")) - - // Test alias names. - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(0) as c1 from t) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("3")) - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(*) as c1 from t) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("3")) - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select group_concat(a) as `concat(a)` from t group by a) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("1", "2", "3")) - - // Test firstrow. - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select a from t group by a) s;") - rows = tk.MustQuery("select * from v order by 1;") - rows.Check(testkit.Rows("1", "2", "3")) - - // Test direct select. - err := tk.ExecToErr("SELECT `s`.`count(a)` FROM (SELECT COUNT(`a`) FROM `test`.`t`) AS `s`") - c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 's.count(a)' in 'field list'") - - tk.MustExec("drop view v;") - tk.MustExec("create definer='root'@'localhost' view v as select * from (select count(a) from t) s;") - rows = tk.MustQuery("select * from v") - rows.Check(testkit.Rows("3")) - - // Test window function. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(c1 int);") - tk.MustExec("insert into t values(111), (222), (333);") - tk.MustExec("drop view if exists v;") - tk.MustExec("create definer='root'@'localhost' view v as (select * from (select row_number() over (order by c1) from t) s);") - rows = tk.MustQuery("select * from v;") - rows.Check(testkit.Rows("1", "2", "3")) - tk.MustExec("drop view if exists v;") - tk.MustExec("create definer='root'@'localhost' view v as (select * from (select c1, row_number() over (order by c1) from t) s);") - rows = tk.MustQuery("select * from v;") - rows.Check(testkit.Rows("111 1", "222 2", "333 3")) - - // Test simple expr. - tk.MustExec("drop view if exists v;") - tk.MustExec("create definer='root'@'localhost' view v as (select * from (select c1 or 0 from t) s)") - rows = tk.MustQuery("select * from v;") - rows.Check(testkit.Rows("1", "1", "1")) - rows = tk.MustQuery("select `c1 or 0` from v;") - rows.Check(testkit.Rows("1", "1", "1")) - - tk.MustExec("drop view v;") -} + txn, err := tk.Session().Txn(true) + require.True(t, kv.ErrInvalidTxn.Equal(err)) + require.False(t, txn.Valid()) + tk.MustExec("create table t (c1 int, c2 int, c3 int)") + tk.MustExec("insert t values (11, 2, 3)") + tk.MustExec("insert t values (12, 2, 3)") + tk.MustExec("insert t values (13, 2, 3)") -func (s *testStaleTxnSuite) TestInvalidReadTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. - safePointName := "tikv_gc_safe_point" - safePointValue := "20160102-15:04:05 -0700" - safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" - updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') - ON DUPLICATE KEY - UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) - tk.MustExec(updateSafePoint) + tk.MustExec("create table t1 (c1 int)") + tk.MustExec("insert t1 values (11)") - tk.MustExec("use test") - tk.MustExec("drop table if exists tmp1") - tk.MustExec("create global temporary table tmp1 " + - "(id int not null primary key, code int not null, value int default null, unique key code(code))" + - "on commit delete rows") - tk.MustExec("use test") - tk.MustExec("drop table if exists tmp2") - tk.MustExec("create temporary table tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("create table tmp3 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("create table tmp4 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("create temporary table tmp5(id int);") - tk.MustExec("create table tmp6 (id int primary key);") - - // sleep 1us to make test stale - time.Sleep(time.Microsecond) - - queries := []struct { - sql string - }{ - { - sql: "select * from tmp1 where id=1", - }, - { - sql: "select * from tmp1 where code=1", - }, - { - sql: "select * from tmp1 where id in (1, 2, 3)", - }, - { - sql: "select * from tmp1 where code in (1, 2, 3)", - }, - { - sql: "select * from tmp1 where id > 1", - }, - { - sql: "select /*+use_index(tmp1, code)*/ * from tmp1 where code > 1", - }, - { - sql: "select /*+use_index(tmp1, code)*/ code from tmp1 where code > 1", - }, - { - sql: "select /*+ use_index_merge(tmp1, primary, code) */ * from tmp1 where id > 1 or code > 2", - }, - } + // conflict + tk1.MustExec("begin") + tk1.MustQuery("select * from t where c1=11 for update") - addStaleReadToSQL := func(sql string) string { - idx := strings.Index(sql, " where ") - if idx < 0 { - return "" - } - return sql[0:idx] + " as of timestamp NOW(6)" + sql[idx:] - } - genLocalTemporarySQL := func(sql string) string { - return strings.Replace(sql, "tmp1", "tmp2", -1) - } + tk2.MustExec("begin") + tk2.MustExec("update t set c2=211 where c1=11") + tk2.MustExec("commit") - for _, query := range queries { - localSQL := genLocalTemporarySQL(query.sql) - queries = append(queries, struct{ sql string }{sql: localSQL}) - } - for _, query := range queries { - sql := addStaleReadToSQL(query.sql) - if sql != "" { - tk.MustGetErrMsg(sql, "can not stale read temporary table") - } - } + err = tk1.ExecToErr("commit") + require.Error(t, err) - tk.MustExec("start transaction read only as of timestamp NOW(6)") - for _, query := range queries { - tk.MustGetErrMsg(query.sql, "can not stale read temporary table") - } - tk.MustExec("commit") + // no conflict for subquery. + tk1.MustExec("begin") + tk1.MustQuery("select * from t where exists(select null from t1 where t1.c1=t.c1) for update") - for _, query := range queries { - tk.MustExec(query.sql) - } + tk2.MustExec("begin") + tk2.MustExec("update t set c2=211 where c1=12") + tk2.MustExec("commit") - // Test normal table when local temporary exits. - tk.MustExec("insert into tmp6 values(1);") - tk.MustExec("set @a=now(6);") - time.Sleep(time.Microsecond) - tk.MustExec("drop table tmp6") - tk.MustExec("create table tmp6 (id int primary key);") - tk.MustQuery("select * from tmp6 as of timestamp(@a) where id=1;").Check(testkit.Rows("1")) - tk.MustQuery("select * from tmp4 as of timestamp(@a), tmp3 as of timestamp(@a) where tmp3.id=1;") - tk.MustGetErrMsg("select * from tmp4 as of timestamp(@a), tmp2 as of timestamp(@a) where tmp2.id=1;", "can not stale read temporary table") - - tk.MustExec("set transaction read only as of timestamp NOW(6)") - tk.MustExec("start transaction") - for _, query := range queries { - tk.MustGetErrMsg(query.sql, "can not stale read temporary table") - } - tk.MustExec("commit") + tk1.MustExec("commit") - for _, query := range queries { - tk.MustExec(query.sql) - } + // not conflict + tk1.MustExec("begin") + tk1.MustQuery("select * from t where c1=11 for update") - tk.MustExec("set @@tidb_snapshot=NOW(6)") - for _, query := range queries { - // forbidden historical read local temporary table - if strings.Contains(query.sql, "tmp2") { - tk.MustGetErrMsg(query.sql, "can not read local temporary table when 'tidb_snapshot' is set") - continue - } - // Will success here for compatibility with some tools like dumping - tk.MustQuery(query.sql).Check(testkit.Rows()) - } -} + tk2.MustExec("begin") + tk2.MustExec("update t set c2=22 where c1=12") + tk2.MustExec("commit") -func (s *testStaleTxnSuite) TestInvalidReadCacheTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. - safePointName := "tikv_gc_safe_point" - safePointValue := "20160102-15:04:05 -0700" - safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" - updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') - ON DUPLICATE KEY - UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) - tk.MustExec(updateSafePoint) - tk.MustExec("use test") - tk.MustExec("drop table if exists cache_tmp1") - tk.MustExec("create table cache_tmp1 " + - "(id int not null primary key, code int not null, value int default null, unique key code(code))") - tk.MustExec("alter table cache_tmp1 cache") - tk.MustExec("drop table if exists cache_tmp2") - tk.MustExec("create table cache_tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("alter table cache_tmp2 cache") - tk.MustExec("drop table if exists cache_tmp3 , cache_tmp4, cache_tmp5") - tk.MustExec("create table cache_tmp3 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("create table cache_tmp4 (id int not null primary key, code int not null, value int default null, unique key code(code));") - tk.MustExec("create table cache_tmp5 (id int primary key);") - // sleep 1us to make test stale - time.Sleep(time.Microsecond) - - queries := []struct { - sql string - }{ - { - sql: "select * from cache_tmp1 where id=1", - }, - { - sql: "select * from cache_tmp1 where code=1", - }, - { - sql: "select * from cache_tmp1 where id in (1, 2, 3)", - }, - { - sql: "select * from cache_tmp1 where code in (1, 2, 3)", - }, - { - sql: "select * from cache_tmp1 where id > 1", - }, - { - sql: "select /*+use_index(cache_tmp1, code)*/ * from cache_tmp1 where code > 1", - }, - { - sql: "select /*+use_index(cache_tmp1, code)*/ code from cache_tmp1 where code > 1", - }, - } + tk1.MustExec("commit") - addStaleReadToSQL := func(sql string) string { - idx := strings.Index(sql, " where ") - if idx < 0 { - return "" - } - return sql[0:idx] + " as of timestamp NOW(6)" + sql[idx:] - } - for _, query := range queries { - sql := addStaleReadToSQL(query.sql) - if sql != "" { - tk.MustGetErrMsg(sql, "can not stale read cache table") - } - } + // not conflict, auto commit + tk1.MustExec("set @@autocommit=1;") + tk1.MustQuery("select * from t where c1=11 for update") - tk.MustExec("start transaction read only as of timestamp NOW(6)") - for _, query := range queries { - tk.MustGetErrMsg(query.sql, "can not stale read cache table") - } - tk.MustExec("commit") + tk2.MustExec("begin") + tk2.MustExec("update t set c2=211 where c1=11") + tk2.MustExec("commit") - for _, query := range queries { - tk.MustExec(query.sql) - } + tk1.MustExec("commit") - // Test normal table when cache table exits. - tk.MustExec("insert into cache_tmp5 values(1);") - tk.MustExec("set @a=now(6);") - time.Sleep(time.Microsecond) - tk.MustExec("drop table cache_tmp5") - tk.MustExec("create table cache_tmp5 (id int primary key);") - tk.MustQuery("select * from cache_tmp5 as of timestamp(@a) where id=1;").Check(testkit.Rows("1")) - tk.MustQuery("select * from cache_tmp4 as of timestamp(@a), cache_tmp3 as of timestamp(@a) where cache_tmp3.id=1;") - tk.MustGetErrMsg("select * from cache_tmp4 as of timestamp(@a), cache_tmp2 as of timestamp(@a) where cache_tmp2.id=1;", "can not stale read cache table") - tk.MustExec("set transaction read only as of timestamp NOW(6)") - tk.MustExec("start transaction") - for _, query := range queries { - tk.MustGetErrMsg(query.sql, "can not stale read cache table") - } - tk.MustExec("commit") + // conflict + tk1.MustExec("begin") + tk1.MustQuery("select * from (select * from t for update) t join t1 for update") - for _, query := range queries { - tk.MustExec(query.sql) - } + tk2.MustExec("begin") + tk2.MustExec("update t1 set c1 = 13") + tk2.MustExec("commit") - tk.MustExec("set @@tidb_snapshot=NOW(6)") - for _, query := range queries { - // enable historical read cache table - tk.MustExec(query.sql) + err = tk1.ExecToErr("commit") + require.Error(t, err) - } } -func (s *testSuite) TestTableSampleTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. - safePointName := "tikv_gc_safe_point" - safePointValue := "20160102-15:04:05 -0700" - safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" - updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') - ON DUPLICATE KEY - UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) - tk.MustExec(updateSafePoint) - - tk.MustExec("use test") - tk.MustExec("drop table if exists tmp1") - tk.MustExec("create global temporary table tmp1 " + - "(id int not null primary key, code int not null, value int default null, unique key code(code))" + - "on commit delete rows") +func TestSelectForUpdateOf(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists tmp2") - tk.MustExec("create temporary table tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));") + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") - // sleep 1us to make test stale - time.Sleep(time.Microsecond) + tk.MustExec("drop table if exists t, t1") + tk.MustExec("create table t (i int)") + tk.MustExec("create table t1 (i int)") + tk.MustExec("insert t values (1)") + tk.MustExec("insert t1 values (1)") - // test tablesample return empty for global temporary table - tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + tk.MustExec("begin pessimistic") + tk.MustQuery("select * from t, t1 where t.i = t1.i for update of t").Check(testkit.Rows("1 1")) - tk.MustExec("begin") - tk.MustExec("insert into tmp1 values (1, 1, 1)") - tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) - tk.MustExec("commit") + tk1.MustExec("begin pessimistic") - // tablesample for global temporary table should not return error for compatibility of tools like dumpling - tk.MustExec("set @@tidb_snapshot=NOW(6)") - tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) + // no lock for t + tk1.MustQuery("select * from t1 for update").Check(testkit.Rows("1")) - tk.MustExec("begin") - tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows()) - tk.MustExec("commit") - tk.MustExec("set @@tidb_snapshot=''") + // meet lock for t1 + err := tk1.ExecToErr("select * from t for update nowait") + require.True(t, terror.ErrorEqual(err, error2.ErrLockAcquireFailAndNoWaitSet), fmt.Sprintf("err: %v", err)) - // test tablesample returns error for local temporary table - tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") + // t1 rolled back, tk1 acquire the lock + tk.MustExec("rollback") + tk1.MustQuery("select * from t for update nowait").Check(testkit.Rows("1")) - tk.MustExec("begin") - tk.MustExec("insert into tmp2 values (1, 1, 1)") - tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") - tk.MustExec("commit") - tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables") + tk1.MustExec("rollback") } -func (s *testSuite) TestIssue25506(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists tbl_3, tbl_23") - tk.MustExec("create table tbl_3 (col_15 bit(20))") - tk.MustExec("insert into tbl_3 values (0xFFFF)") - tk.MustExec("insert into tbl_3 values (0xFF)") - tk.MustExec("create table tbl_23 (col_15 bit(15))") - tk.MustExec("insert into tbl_23 values (0xF)") - tk.MustQuery("(select col_15 from tbl_23) union all (select col_15 from tbl_3 for update) order by col_15").Check(testkit.Rows("\x00\x00\x0F", "\x00\x00\xFF", "\x00\xFF\xFF")) -} +func TestEmptyEnum(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite) TestIssue26348(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("create table t (e enum('Y', 'N'))") + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") + err := tk.ExecToErr("insert into t values (0)") + require.True(t, terror.ErrorEqual(err, types.ErrTruncated), fmt.Sprintf("err: %v", err)) + err = tk.ExecToErr("insert into t values ('abc')") + require.True(t, terror.ErrorEqual(err, types.ErrTruncated), fmt.Sprintf("err: %v", err)) - tk.MustExec("drop table if exists t") - tk.MustExec(`CREATE TABLE t ( -a varchar(8) DEFAULT NULL, -b varchar(8) DEFAULT NULL, -c decimal(20,2) DEFAULT NULL, -d decimal(15,8) DEFAULT NULL -);`) - tk.MustExec(`insert into t values(20210606, 20210606, 50000.00, 5.04600000);`) - tk.MustQuery(`select a * c *(d/36000) from t;`).Check(testkit.Rows("141642663.71666598")) - tk.MustQuery(`select cast(a as double) * cast(c as double) *cast(d/36000 as double) from t;`).Check(testkit.Rows("141642663.71666598")) - tk.MustQuery("select 20210606*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666599297980")) - - // differs from MySQL cause constant-fold . - tk.MustQuery("select \"20210606\"*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666598")) - tk.MustQuery("select cast(\"20210606\" as double)*50000.00*(5.04600000/36000)").Check(testkit.Rows("141642663.71666598")) + tk.MustExec("set sql_mode=''") + tk.MustExec("insert into t values (0)") + tk.MustQuery("select * from t").Check(testkit.Rows("")) + tk.MustExec("insert into t values ('abc')") + tk.MustQuery("select * from t").Check(testkit.Rows("", "")) + tk.MustExec("insert into t values (null)") + tk.MustQuery("select * from t").Check(testkit.Rows("", "", "")) + + // Test https://github.com/pingcap/tidb/issues/29525. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (id int auto_increment primary key, c1 enum('a', '', 'c'));") + tk.MustExec("insert into t(c1) values (0);") + tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ")) + tk.MustExec("alter table t change c1 c1 enum('a', '') not null;") + tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ")) + tk.MustExec("insert into t(c1) values (0);") + tk.MustQuery("select id, c1+0, c1 from t;").Check(testkit.Rows("1 0 ", "2 0 ")) } -func (s *testSuite) TestIssue26532(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionHashCode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustQuery("select greatest(cast(\"2020-01-01 01:01:01\" as datetime), cast(\"2019-01-01 01:01:01\" as datetime) )union select null;").Sort().Check(testkit.Rows("2020-01-01 01:01:01", "")) - tk.MustQuery("select least(cast(\"2020-01-01 01:01:01\" as datetime), cast(\"2019-01-01 01:01:01\" as datetime) )union select null;").Sort().Check(testkit.Rows("2019-01-01 01:01:01", "")) - tk.MustQuery("select greatest(\"2020-01-01 01:01:01\" ,\"2019-01-01 01:01:01\" )union select null;").Sort().Check(testkit.Rows("2020-01-01 01:01:01", "")) - tk.MustQuery("select least(\"2020-01-01 01:01:01\" , \"2019-01-01 01:01:01\" )union select null;").Sort().Check(testkit.Rows("2019-01-01 01:01:01", "")) + tk.MustExec(`create table t(c1 bigint, c2 bigint, c3 bigint, primary key(c1)) partition by hash (c1) partitions 4;`) + var wg util.WaitGroupWrapper + for i := 0; i < 5; i++ { + wg.Run(func() { + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + for i := 0; i < 5; i++ { + tk1.MustExec("select * from t") + } + }) + } + wg.Wait() } -func (s *testSuite) TestIssue25447(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAlterDefaultValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("create table t1(a int, b varchar(8))") - tk.MustExec("insert into t1 values(1,'1')") - tk.MustExec("create table t2(a int , b varchar(8) GENERATED ALWAYS AS (c) VIRTUAL, c varchar(8), PRIMARY KEY (a))") - tk.MustExec("insert into t2(a) values(1)") - tk.MustQuery("select /*+ tidb_inlj(t2) */ t2.b, t1.b from t1 join t2 ON t2.a=t1.a").Check(testkit.Rows(" 1")) + tk.MustExec("create table t(a int, primary key(a))") + tk.MustExec("insert into t(a) values(1)") + tk.MustExec("alter table t add column b int default 1") + tk.MustExec("alter table t alter b set default 2") + tk.MustQuery("select b from t where a = 1").Check(testkit.Rows("1")) } -func (s *testSuite) TestIssue23602(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("USE test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("CREATE TABLE t (a bigint unsigned PRIMARY KEY)") - defer tk.MustExec("DROP TABLE t") - tk.MustExec("INSERT INTO t VALUES (0),(1),(2),(3),(18446744073709551600),(18446744073709551605),(18446744073709551610),(18446744073709551615)") - tk.MustExec("ANALYZE TABLE t") - tk.MustQuery(`EXPLAIN FORMAT = 'brief' SELECT a FROM t WHERE a >= 0x1 AND a <= 0x2`).Check(testkit.Rows( - "TableReader 2.00 root data:TableRangeScan]\n" + - "[└─TableRangeScan 2.00 cop[tikv] table:t range:[1,2], keep order:false")) - tk.MustQuery(`EXPLAIN FORMAT = 'brief' SELECT a FROM t WHERE a BETWEEN 0x1 AND 0x2`).Check(testkit.Rows( - "TableReader 2.00 root data:TableRangeScan]\n" + - "[└─TableRangeScan 2.00 cop[tikv] table:t range:[1,2], keep order:false")) - tk.MustQuery("SELECT a FROM t WHERE a BETWEEN 0xFFFFFFFFFFFFFFF5 AND X'FFFFFFFFFFFFFFFA'").Check(testkit.Rows("18446744073709551605", "18446744073709551610")) -} +// this is from jira issue #5856 +func TestInsertValuesWithSubQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuite) TestCTEWithIndexLookupJoinDeadLock(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("create table t (a int(11) default null,b int(11) default null,key b (b),key ba (b))") - tk.MustExec("create table t1 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") - tk.MustExec("create table t2 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") - // It's easy to reproduce this problem in 30 times execution of IndexLookUpJoin. - for i := 0; i < 30; i++ { - tk.MustExec("with cte as (with cte1 as (select * from t2 use index(idx_ab) where a > 1 and b > 1) select * from cte1) select /*+use_index(t1 idx_ab)*/ * from cte join t1 on t1.a=cte.a;") - } -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2(a int, b int, c int)") + defer tk.MustExec("drop table if exists t2") -func (s *testSuite) TestGetResultRowsCount(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") + // should not reference upper scope + require.Error(t, tk.ExecToErr("insert into t2 values (11, 8, (select not b))")) + require.Error(t, tk.ExecToErr("insert into t2 set a = 11, b = 8, c = (select b))")) + + // subquery reference target table is allowed + tk.MustExec("insert into t2 values(1, 1, (select b from t2))") + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ")) + tk.MustExec("insert into t2 set a = 1, b = 1, c = (select b+1 from t2)") + tk.MustQuery("select * from t2").Check(testkit.Rows("1 1 ", "1 1 2")) + + // insert using column should work normally + tk.MustExec("delete from t2") + tk.MustExec("insert into t2 values(2, 4, a)") + tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2")) + tk.MustExec("insert into t2 set a = 3, b = 5, c = b") + tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2", "3 5 5")) + + // issue #30626 tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int)") - for i := 1; i <= 10; i++ { - tk.MustExec(fmt.Sprintf("insert into t values (%v)", i)) - } - cases := []struct { - sql string - row int64 - }{ - {"select * from t", 10}, - {"select * from t where a < 0", 0}, - {"select * from t where a <= 3", 3}, - {"insert into t values (11)", 0}, - {"replace into t values (12)", 0}, - {"update t set a=13 where a=12", 0}, - } + tk.MustExec("create table t(a int, b int)") + // TODO: should insert success and get (81,1) from the table + tk.MustGetErrMsg( + "insert into t values ( 81, ( select ( SELECT '1' AS `c0` WHERE '1' >= `subq_0`.`c0` ) as `c1` FROM ( SELECT '1' AS `c0` ) AS `subq_0` ) );", + "Insert's SET operation or VALUES_LIST doesn't support complex subqueries now") + tk.MustGetErrMsg( + "insert into t set a = 81, b = (select ( SELECT '1' AS `c0` WHERE '1' >= `subq_0`.`c0` ) as `c1` FROM ( SELECT '1' AS `c0` ) AS `subq_0` );", + "Insert's SET operation or VALUES_LIST doesn't support complex subqueries now") - for _, ca := range cases { - if strings.HasPrefix(ca.sql, "select") { - tk.MustQuery(ca.sql) - } else { - tk.MustExec(ca.sql) - } - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) - p, ok := info.Plan.(plannercore.Plan) - c.Assert(ok, IsTrue) - cnt := executor.GetResultRowsCount(tk.Se, p) - c.Assert(ca.row, Equals, cnt, Commentf("sql: %v", ca.sql)) - } } -func checkFileName(s string) bool { - files := []string{ - "config.toml", - "meta.txt", - "stats/test.t_dump_single.json", - "schema/test.t_dump_single.schema.txt", - "variables.toml", - "sqls.sql", - "session_bindings.sql", - "global_bindings.sql", - "explain.txt", - } - for _, f := range files { - if strings.Compare(f, s) == 0 { - return true - } - } - return false -} +func TestDIVZeroInPartitionExpr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuiteWithData) TestPlanReplayerDumpSingle(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t_dump_single") - tk.MustExec("create table t_dump_single(a int)") - res := tk.MustQuery("plan replayer dump explain select * from t_dump_single") - path := s.testData.ConvertRowsToStrings(res.Rows()) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("create table t1(a int) partition by range (10 div a) (partition p0 values less than (10), partition p1 values less than maxvalue)") - reader, err := zip.OpenReader(filepath.Join(domain.GetPlanReplayerDirName(), path[0])) - c.Assert(err, IsNil) - defer reader.Close() - for _, file := range reader.File { - c.Assert(checkFileName(file.Name), IsTrue) - } + tk.MustExec("set @@sql_mode=''") + tk.MustExec("insert into t1 values (NULL), (0), (1)") + tk.MustExec("set @@sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO'") + tk.MustGetErrCode("insert into t1 values (NULL), (0), (1)", mysql.ErrDivisionByZero) } -func (s *testSuiteP1) TestIssue28935(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("set @@tidb_enable_vectorized_expression=true") - tk.MustQuery(`select trim(leading from " a "), trim(both from " a "), trim(trailing from " a ")`).Check(testkit.Rows("a a a")) - tk.MustQuery(`select trim(leading null from " a "), trim(both null from " a "), trim(trailing null from " a ")`).Check(testkit.Rows(" ")) - tk.MustQuery(`select trim(null from " a ")`).Check(testkit.Rows("")) - - tk.MustExec("set @@tidb_enable_vectorized_expression=false") - tk.MustQuery(`select trim(leading from " a "), trim(both from " a "), trim(trailing from " a ")`).Check(testkit.Rows("a a a")) - tk.MustQuery(`select trim(leading null from " a "), trim(both null from " a "), trim(trailing null from " a ")`).Check(testkit.Rows(" ")) - tk.MustQuery(`select trim(null from " a ")`).Check(testkit.Rows("")) -} +func TestInsertIntoGivenPartitionSet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSuiteP1) TestIssue29412(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t29142_1") - tk.MustExec("drop table if exists t29142_2") - tk.MustExec("create table t29142_1(a int);") - tk.MustExec("create table t29142_2(a double);") - tk.MustExec("insert into t29142_1 value(20);") - tk.MustQuery("select sum(distinct a) as x from t29142_1 having x > some ( select a from t29142_2 where x in (a));").Check(nil) -} + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec(`create table t1( + a int(11) DEFAULT NULL, + b varchar(10) DEFAULT NULL, + UNIQUE KEY idx_a (a)) PARTITION BY RANGE (a) + (PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB, + PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB, + PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)`) -func (s *testSerialSuite) TestIssue28650(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2;") - tk.MustExec("create table t1(a int, index(a));") - tk.MustExec("create table t2(a int, c int, b char(50), index(a,c,b));") - tk.MustExec("set tidb_enable_rate_limit_action=off;") - - wg := &sync.WaitGroup{} - sql := `explain analyze - select /*+ stream_agg(@sel_1) stream_agg(@sel_3) %s(@sel_2 t2)*/ count(1) from - ( - SELECT t2.a AS t2_external_user_ext_id, t2.b AS t2_t1_ext_id FROM t2 INNER JOIN (SELECT t1.a AS d_t1_ext_id FROM t1 GROUP BY t1.a) AS anon_1 ON anon_1.d_t1_ext_id = t2.a WHERE t2.c = 123 AND t2.b - IN ("%s") ) tmp` - - wg.Add(1) - sqls := make([]string, 2) - go func() { - defer wg.Done() - inElems := make([]string, 1000) - for i := 0; i < len(inElems); i++ { - inElems[i] = fmt.Sprintf("wm_%dbDgAAwCD-v1QB%dxky-g_dxxQCw", rand.Intn(100), rand.Intn(100)) - } - sqls[0] = fmt.Sprintf(sql, "inl_join", strings.Join(inElems, "\",\"")) - sqls[1] = fmt.Sprintf(sql, "inl_hash_join", strings.Join(inElems, "\",\"")) - }() + // insert into + tk.MustExec("insert into t1 partition(p0) values(1, 'a'), (2, 'b')") + tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b")) + tk.MustExec("insert into t1 partition(p0, p1) values(3, 'c'), (4, 'd')") + tk.MustQuery("select * from t1 partition(p1)").Check(testkit.Rows()) - tk.MustExec("insert into t1 select rand()*400;") - for i := 0; i < 10; i++ { - tk.MustExec("insert into t1 select rand()*400 from t1;") - } - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionCancel - }) - defer func() { - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionLog - }) - }() - wg.Wait() - for _, sql := range sqls { - tk.MustExec("set @@tidb_mem_quota_query = 1073741824") // 1GB - c.Assert(tk.QueryToErr(sql), IsNil) - tk.MustExec("set @@tidb_mem_quota_query = 33554432") // 32MB, out of memory during executing - c.Assert(strings.Contains(tk.QueryToErr(sql).Error(), "Out Of Memory Quota!"), IsTrue) - tk.MustExec("set @@tidb_mem_quota_query = 65536") // 64KB, out of memory during building the plan - func() { - defer func() { - r := recover() - c.Assert(r, NotNil) - err := errors.Errorf("%v", r) - c.Assert(strings.Contains(err.Error(), "Out Of Memory Quota!"), IsTrue) - }() - tk.MustExec(sql) - }() - } -} + tk.MustGetErrMsg("insert into t1 values(1, 'a')", "[kv:1062]Duplicate entry '1' for key 'idx_a'") + tk.MustGetErrMsg("insert into t1 partition(p0, p_non_exist) values(1, 'a')", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") + tk.MustGetErrMsg("insert into t1 partition(p0, p1) values(40, 'a')", "[table:1748]Found a row not matching the given partition set") -func (s *testSerialSuite) TestIssue30289(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - fpName := "github.com/pingcap/tidb/executor/issue30289" - c.Assert(failpoint.Enable(fpName, `return(true)`), IsNil) - defer func() { - c.Assert(failpoint.Disable(fpName), IsNil) - }() - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int)") - err := tk.QueryToErr("select /*+ hash_join(t1) */ * from t t1 join t t2 on t1.a=t2.a") - c.Assert(err.Error(), Matches, "issue30289 build return error") + // replace into + tk.MustExec("replace into t1 partition(p0) values(1, 'replace')") + tk.MustExec("replace into t1 partition(p0, p1) values(3, 'replace'), (4, 'replace')") + tk.MustExec("replace into t1 values(1, 'a')") + tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 replace", "4 replace")) + + tk.MustGetErrMsg("replace into t1 partition(p0, p_non_exist) values(1, 'a')", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") + tk.MustGetErrMsg("replace into t1 partition(p0, p1) values(40, 'a')", "[table:1748]Found a row not matching the given partition set") + + tk.MustExec("truncate table t1") + + tk.MustExec("create table t(a int, b char(10))") + + // insert into general table + tk.MustGetErrMsg("insert into t partition(p0, p1) values(1, 'a')", "[planner:1747]PARTITION () clause on non partitioned table") + + // insert into from select + tk.MustExec("insert into t values(1, 'a'), (2, 'b')") + tk.MustExec("insert into t1 partition(p0) select * from t") + tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b")) + + tk.MustExec("truncate table t") + tk.MustExec("insert into t values(3, 'c'), (4, 'd')") + tk.MustExec("insert into t1 partition(p0, p1) select * from t") + tk.MustQuery("select * from t1 partition(p1) order by a").Check(testkit.Rows()) + tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 c", "4 d")) + + tk.MustGetErrMsg("insert into t1 select 1, 'a'", "[kv:1062]Duplicate entry '1' for key 'idx_a'") + tk.MustGetErrMsg("insert into t1 partition(p0, p_non_exist) select 1, 'a'", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") + tk.MustGetErrMsg("insert into t1 partition(p0, p1) select 40, 'a'", "[table:1748]Found a row not matching the given partition set") + + // replace into from select + tk.MustExec("replace into t1 partition(p0) select 1, 'replace'") + tk.MustExec("truncate table t") + tk.MustExec("insert into t values(3, 'replace'), (4, 'replace')") + tk.MustExec("replace into t1 partition(p0, p1) select * from t") + + tk.MustExec("replace into t1 select 1, 'a'") + tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 replace", "4 replace")) + tk.MustGetErrMsg("replace into t1 partition(p0, p_non_exist) select 1, 'a'", "[table:1735]Unknown partition 'p_non_exist' in table 't1'") + tk.MustGetErrMsg("replace into t1 partition(p0, p1) select 40, 'a'", "[table:1748]Found a row not matching the given partition set") } -func (s *testSerialSuite) TestIssue29498(c *C) { - tk := testkit.NewTestKit(c, s.store) +// fix issue https://github.com/pingcap/tidb/issues/32871 +func TestBitColumnIn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("DROP TABLE IF EXISTS t1;") - tk.MustExec("CREATE TABLE t1 (t3 TIME(3), d DATE, t TIME);") - tk.MustExec("INSERT INTO t1 VALUES ('00:00:00.567', '2002-01-01', '00:00:02');") - - res := tk.MustQuery("SELECT CONCAT(IFNULL(t3, d)) AS col1 FROM t1;") - row := res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp+3+1) - c.Assert(row[len(row)-12:], Equals, "00:00:00.567") - - res = tk.MustQuery("SELECT IFNULL(t3, d) AS col1 FROM t1;") - row = res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp+3+1) - c.Assert(row[len(row)-12:], Equals, "00:00:00.567") - - res = tk.MustQuery("SELECT CONCAT(IFNULL(t, d)) AS col1 FROM t1;") - row = res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp) - c.Assert(row[len(row)-8:], Equals, "00:00:02") - - res = tk.MustQuery("SELECT IFNULL(t, d) AS col1 FROM t1;") - row = res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp) - c.Assert(row[len(row)-8:], Equals, "00:00:02") - - res = tk.MustQuery("SELECT CONCAT(xx) FROM (SELECT t3 AS xx FROM t1 UNION SELECT d FROM t1) x ORDER BY -xx LIMIT 1;") - row = res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp+3+1) - c.Assert(row[len(row)-12:], Equals, "00:00:00.567") - - res = tk.MustQuery("SELECT CONCAT(CASE WHEN d IS NOT NULL THEN t3 ELSE d END) AS col1 FROM t1;") - row = res.Rows()[0][0].(string) - c.Assert(len(row), Equals, mysql.MaxDatetimeWidthNoFsp+3+1) - c.Assert(row[len(row)-12:], Equals, "00:00:00.567") + tk.MustExec("create table t (id bit(16), key id(id))") + tk.MustExec("insert into t values (65)") + tk.MustQuery("select * from t where id not in (-1,2)").Check(testkit.Rows("\x00A")) + tk.MustGetErrMsg( + "select * from t where id in (-1, -2)", + "[expression:1582]Incorrect parameter count in the call to native function 'in'") } -// Test invoke Close without invoking Open before for each operators. -func (s *testSerialSuite) TestUnreasonablyClose(c *C) { - defer testleak.AfterTest(c)() - - is := infoschema.MockInfoSchema([]*model.TableInfo{plannercore.MockSignedTable(), plannercore.MockUnsignedTable()}) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - // To enable the shuffleExec operator. - _, err = se.Execute(context.Background(), "set @@tidb_merge_join_concurrency=4") - c.Assert(err, IsNil) - - var opsNeedsCovered = []plannercore.PhysicalPlan{ - &plannercore.PhysicalHashJoin{}, - &plannercore.PhysicalMergeJoin{}, - &plannercore.PhysicalIndexJoin{}, - &plannercore.PhysicalIndexHashJoin{}, - &plannercore.PhysicalTableReader{}, - &plannercore.PhysicalIndexReader{}, - &plannercore.PhysicalIndexLookUpReader{}, - &plannercore.PhysicalIndexMergeReader{}, - &plannercore.PhysicalApply{}, - &plannercore.PhysicalHashAgg{}, - &plannercore.PhysicalStreamAgg{}, - &plannercore.PhysicalLimit{}, - &plannercore.PhysicalSort{}, - &plannercore.PhysicalTopN{}, - &plannercore.PhysicalCTE{}, - &plannercore.PhysicalCTETable{}, - &plannercore.PhysicalMaxOneRow{}, - &plannercore.PhysicalProjection{}, - &plannercore.PhysicalSelection{}, - &plannercore.PhysicalTableDual{}, - &plannercore.PhysicalWindow{}, - &plannercore.PhysicalShuffle{}, - &plannercore.PhysicalUnionAll{}, - } - executorBuilder := executor.NewMockExecutorBuilderForTest(se, is, nil, math.MaxUint64, false, "global") - - var opsNeedsCoveredMask uint64 = 1< t1.a) AS a from t as t1) t", - "select /*+ hash_agg() */ count(f) from t group by a", - "select /*+ stream_agg() */ count(f) from t group by a", - "select * from t order by a, f", - "select * from t order by a, f limit 1", - "select * from t limit 1", - "select (select t1.a from t t1 where t1.a > t2.a) as a from t t2;", - "select a + 1 from t", - "select count(*) a from t having a > 1", - "select * from t where a = 1.1", - "with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1", - "select /*+use_index_merge(t, c_d_e, f)*/ * from t where c < 1 or f > 2", - "select sum(f) over (partition by f) from t", - "select /*+ merge_join(t1)*/ * from t t1 join t t2 on t1.d = t2.d", - "select a from t union all select a from t", - } { - comment := Commentf("case:%v sql:%s", i, tc) - c.Assert(err, IsNil, comment) - stmt, err := s.ParseOneStmt(tc, "", "") - c.Assert(err, IsNil, comment) - - err = se.NewTxn(context.Background()) - c.Assert(err, IsNil, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, is) - c.Assert(err, IsNil, comment) - // This for loop level traverses the plan tree to get which operators are covered. - for child := []plannercore.PhysicalPlan{p.(plannercore.PhysicalPlan)}; len(child) != 0; { - newChild := make([]plannercore.PhysicalPlan, 0, len(child)) - for _, ch := range child { - found := false - for k, t := range opsNeedsCovered { - if reflect.TypeOf(t) == reflect.TypeOf(ch) { - opsAlreadyCoveredMask |= 1 << k - found = true - break - } - } - c.Assert(found, IsTrue, Commentf("case: %v sql: %s operator %v is not registered in opsNeedsCoveredMask", i, tc, reflect.TypeOf(ch))) - switch x := ch.(type) { - case *plannercore.PhysicalCTE: - newChild = append(newChild, x.RecurPlan) - newChild = append(newChild, x.SeedPlan) - continue - case *plannercore.PhysicalShuffle: - newChild = append(newChild, x.DataSources...) - newChild = append(newChild, x.Tails...) - continue - } - newChild = append(newChild, ch.Children()...) - } - child = newChild - } +func TestUpdateGivenPartitionSet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - e := executorBuilder.Build(p) - - func() { - defer func() { - r := recover() - buf := make([]byte, 4096) - stackSize := runtime.Stack(buf, false) - buf = buf[:stackSize] - c.Assert(r, IsNil, Commentf("case: %v\n sql: %s\n error stack: %v", i, tc, string(buf))) - }() - c.Assert(e.Close(), IsNil, comment) - }() - } - // The following code is used to make sure all the operators registered - // in opsNeedsCoveredMask are covered. - commentBuf := strings.Builder{} - if opsAlreadyCoveredMask != opsNeedsCoveredMask { - for i := range opsNeedsCovered { - if opsAlreadyCoveredMask&(1< 1", + }, + { + sql: "select /*+use_index(tmp1, code)*/ * from tmp1 where code > 1", + }, + { + sql: "select /*+use_index(tmp1, code)*/ code from tmp1 where code > 1", + }, + { + sql: "select /*+ use_index_merge(tmp1, primary, code) */ * from tmp1 where id > 1 or code > 2", + }, + } + + addStaleReadToSQL := func(sql string) string { + idx := strings.Index(sql, " where ") + if idx < 0 { + return "" + } + return sql[0:idx] + " as of timestamp NOW(6)" + sql[idx:] + } + genLocalTemporarySQL := func(sql string) string { + return strings.Replace(sql, "tmp1", "tmp2", -1) + } + + for _, query := range queries { + localSQL := genLocalTemporarySQL(query.sql) + queries = append(queries, struct{ sql string }{sql: localSQL}) + } + for _, query := range queries { + sql := addStaleReadToSQL(query.sql) + if sql != "" { + tk.MustGetErrMsg(sql, "can not stale read temporary table") + } + } + + tk.MustExec("start transaction read only as of timestamp NOW(6)") + for _, query := range queries { + tk.MustGetErrMsg(query.sql, "can not stale read temporary table") + } + tk.MustExec("commit") + + for _, query := range queries { + tk.MustQuery(query.sql) + } + + // Test normal table when local temporary exits. + tk.MustExec("insert into tmp6 values(1);") + time.Sleep(100 * time.Millisecond) + tk.MustExec("set @a=now(6);") + tk.MustExec("drop table tmp6") + tk.MustExec("create table tmp6 (id int primary key);") + tk.MustQuery("select * from tmp6 as of timestamp(@a) where id=1;").Check(testkit.Rows("1")) + tk.MustQuery("select * from tmp4 as of timestamp(@a), tmp3 as of timestamp(@a) where tmp3.id=1;") + tk.MustGetErrMsg("select * from tmp4 as of timestamp(@a), tmp2 as of timestamp(@a) where tmp2.id=1;", "can not stale read temporary table") + + tk.MustExec("set transaction read only as of timestamp NOW(6)") + tk.MustExec("start transaction") + for _, query := range queries { + tk.MustGetErrMsg(query.sql, "can not stale read temporary table") + } + tk.MustExec("commit") + + for _, query := range queries { + tk.MustExec(query.sql) + } + + tk.MustExec("set @@tidb_snapshot=NOW(6)") + for _, query := range queries { + // forbidden historical read local temporary table + if strings.Contains(query.sql, "tmp2") { + tk.MustGetErrMsg(query.sql, "can not read local temporary table when 'tidb_snapshot' is set") + continue + } + // Will success here for compatibility with some tools like dumping + tk.MustQuery(query.sql).Check(testkit.Rows()) + } +} + +func TestInvalidReadCacheTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20160102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + tk.MustExec("use test") + tk.MustExec("drop table if exists cache_tmp1") + tk.MustExec("create table cache_tmp1 " + + "(id int not null primary key, code int not null, value int default null, unique key code(code))") + tk.MustExec("alter table cache_tmp1 cache") + tk.MustExec("drop table if exists cache_tmp2") + tk.MustExec("create table cache_tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));") + tk.MustExec("alter table cache_tmp2 cache") + tk.MustExec("drop table if exists cache_tmp3 , cache_tmp4, cache_tmp5") + tk.MustExec("create table cache_tmp3 (id int not null primary key, code int not null, value int default null, unique key code(code));") + tk.MustExec("create table cache_tmp4 (id int not null primary key, code int not null, value int default null, unique key code(code));") + tk.MustExec("create table cache_tmp5 (id int primary key);") + // sleep 1us to make test stale + time.Sleep(time.Microsecond) + + queries := []struct { + sql string + }{ + { + sql: "select * from cache_tmp1 where id=1", + }, + { + sql: "select * from cache_tmp1 where code=1", + }, + { + sql: "select * from cache_tmp1 where id in (1, 2, 3)", + }, + { + sql: "select * from cache_tmp1 where code in (1, 2, 3)", + }, + { + sql: "select * from cache_tmp1 where id > 1", + }, + { + sql: "select /*+use_index(cache_tmp1, code)*/ * from cache_tmp1 where code > 1", + }, + { + sql: "select /*+use_index(cache_tmp1, code)*/ code from cache_tmp1 where code > 1", + }, + } + + addStaleReadToSQL := func(sql string) string { + idx := strings.Index(sql, " where ") + if idx < 0 { + return "" + } + return sql[0:idx] + " as of timestamp NOW(6)" + sql[idx:] + } + for _, query := range queries { + sql := addStaleReadToSQL(query.sql) + if sql != "" { + tk.MustGetErrMsg(sql, "can not stale read cache table") + } + } + + tk.MustExec("start transaction read only as of timestamp NOW(6)") + for _, query := range queries { + tk.MustGetErrMsg(query.sql, "can not stale read cache table") + } + tk.MustExec("commit") + + for _, query := range queries { + tk.MustQuery(query.sql) + } + + // Test normal table when cache table exits. + tk.MustExec("insert into cache_tmp5 values(1);") + time.Sleep(100 * time.Millisecond) + tk.MustExec("set @a=now(6);") + tk.MustExec("drop table cache_tmp5") + tk.MustExec("create table cache_tmp5 (id int primary key);") + tk.MustQuery("select * from cache_tmp5 as of timestamp(@a) where id=1;").Check(testkit.Rows("1")) + tk.MustQuery("select * from cache_tmp4 as of timestamp(@a), cache_tmp3 as of timestamp(@a) where cache_tmp3.id=1;") + tk.MustGetErrMsg("select * from cache_tmp4 as of timestamp(@a), cache_tmp2 as of timestamp(@a) where cache_tmp2.id=1;", "can not stale read cache table") + tk.MustExec("set transaction read only as of timestamp NOW(6)") + tk.MustExec("start transaction") + for _, query := range queries { + tk.MustGetErrMsg(query.sql, "can not stale read cache table") + } + tk.MustExec("commit") + + for _, query := range queries { + tk.MustExec(query.sql) + } + + tk.MustExec("set @@tidb_snapshot=NOW(6)") + for _, query := range queries { + // enable historical read cache table + tk.MustExec(query.sql) + + } +} diff --git a/executor/explain_test.go b/executor/explain_test.go index a26f373e10b71..6c5d28a4cad02 100644 --- a/executor/explain_test.go +++ b/executor/explain_test.go @@ -18,21 +18,24 @@ import ( "bytes" "fmt" "strings" + "testing" - . "github.com/pingcap/check" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/parser/auth" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite1) TestExplainPrivileges(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk := testkit.NewTestKit(c, s.store) - tk.Se = se +func TestExplainPrivileges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk := testkit.NewTestKit(t, store) + tk.SetSession(se) tk.MustExec("create database explaindatabase") tk.MustExec("use explaindatabase") @@ -40,11 +43,11 @@ func (s *testSuite1) TestExplainPrivileges(c *C) { tk.MustExec("create view v as select * from t") tk.MustExec(`create user 'explain'@'%'`) - tk1 := testkit.NewTestKit(c, s.store) - se, err = session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + se, err = session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil)) + tk1.SetSession(se) tk.MustExec(`grant select on explaindatabase.v to 'explain'@'%'`) tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "explaindatabase")) @@ -52,7 +55,7 @@ func (s *testSuite1) TestExplainPrivileges(c *C) { tk1.MustExec("use explaindatabase") tk1.MustQuery("select * from v") err = tk1.ExecToErr("explain format = 'brief' select * from v") - c.Assert(err.Error(), Equals, plannercore.ErrViewNoExplain.Error()) + require.Equal(t, plannercore.ErrViewNoExplain.Error(), err.Error()) tk.MustExec(`grant show view on explaindatabase.v to 'explain'@'%'`) tk1.MustQuery("explain format = 'brief' select * from v") @@ -60,11 +63,14 @@ func (s *testSuite1) TestExplainPrivileges(c *C) { tk.MustExec(`revoke select on explaindatabase.v from 'explain'@'%'`) err = tk1.ExecToErr("explain format = 'brief' select * from v") - c.Assert(err.Error(), Equals, plannercore.ErrTableaccessDenied.GenWithStackByArgs("SELECT", "explain", "%", "v").Error()) + require.Equal(t, plannercore.ErrTableaccessDenied.GenWithStackByArgs("SELECT", "explain", "%", "v").Error(), err.Error()) } -func (s *testSuite1) TestExplainCartesianJoin(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainCartesianJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (v int)") @@ -87,12 +93,15 @@ func (s *testSuite1) TestExplainCartesianJoin(c *C) { } } - c.Assert(ok, Equals, ca.isCartesianJoin) + require.Equal(t, ca.isCartesianJoin, ok) } } -func (s *testSuite1) TestExplainWrite(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainWrite(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int)") tk.MustQuery("explain analyze insert into t select 1") @@ -106,28 +115,31 @@ func (s *testSuite1) TestExplainWrite(c *C) { tk.MustQuery("select * from t order by a").Check(testkit.Rows("1", "2", "3")) } -func (s *testSuite1) TestExplainAnalyzeMemory(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainAnalyzeMemory(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (v int, k int, key(k))") tk.MustExec("insert into t values (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)") - s.checkMemoryInfo(c, tk, "explain analyze select * from t order by v") - s.checkMemoryInfo(c, tk, "explain analyze select * from t order by v limit 5") - s.checkMemoryInfo(c, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") - s.checkMemoryInfo(c, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") - s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkMemoryInfo(c, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkMemoryInfo(c, tk, "explain analyze select sum(k) from t group by v") - s.checkMemoryInfo(c, tk, "explain analyze select sum(v) from t group by k") - s.checkMemoryInfo(c, tk, "explain analyze select * from t") - s.checkMemoryInfo(c, tk, "explain analyze select k from t use index(k)") - s.checkMemoryInfo(c, tk, "explain analyze select * from t use index(k)") - s.checkMemoryInfo(c, tk, "explain analyze select v+k from t") + checkMemoryInfo(t, tk, "explain analyze select * from t order by v") + checkMemoryInfo(t, tk, "explain analyze select * from t order by v limit 5") + checkMemoryInfo(t, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") + checkMemoryInfo(t, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") + checkMemoryInfo(t, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkMemoryInfo(t, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkMemoryInfo(t, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkMemoryInfo(t, tk, "explain analyze select sum(k) from t group by v") + checkMemoryInfo(t, tk, "explain analyze select sum(v) from t group by k") + checkMemoryInfo(t, tk, "explain analyze select * from t") + checkMemoryInfo(t, tk, "explain analyze select k from t use index(k)") + checkMemoryInfo(t, tk, "explain analyze select * from t use index(k)") + checkMemoryInfo(t, tk, "explain analyze select v+k from t") } -func (s *testSuite1) checkMemoryInfo(c *C, tk *testkit.TestKit, sql string) { +func checkMemoryInfo(t *testing.T, tk *testkit.TestKit, sql string) { memCol := 6 ops := []string{"Join", "Reader", "Top", "Sort", "LookUp", "Projection", "Selection", "Agg"} rows := tk.MustQuery(sql).Rows() @@ -149,31 +161,34 @@ func (s *testSuite1) checkMemoryInfo(c *C, tk *testkit.TestKit, sql string) { } if shouldHasMem { - c.Assert(strs[memCol], Not(Equals), "N/A") + require.NotEqual(t, "N/A", strs[memCol]) } else { - c.Assert(strs[memCol], Equals, "N/A") + require.Equal(t, "N/A", strs[memCol]) } } } -func (s *testSuite1) TestMemoryAndDiskUsageAfterClose(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestMemoryAndDiskUsageAfterClose(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (v int, k int, key(k))") batch := 128 - limit := tk.Se.GetSessionVars().MaxChunkSize*2 + 10 + limit := tk.Session().GetSessionVars().MaxChunkSize*2 + 10 var buf bytes.Buffer for i := 0; i < limit; { buf.Reset() _, err := buf.WriteString("insert into t values ") - c.Assert(err, IsNil) + require.NoError(t, err) for j := 0; j < batch && i < limit; i, j = i+1, j+1 { if j > 0 { _, err = buf.WriteString(", ") - c.Assert(err, IsNil) + require.NoError(t, err) } _, err = buf.WriteString(fmt.Sprintf("(%v,%v)", i, i)) - c.Assert(err, IsNil) + require.NoError(t, err) } tk.MustExec(buf.String()) } @@ -185,31 +200,34 @@ func (s *testSuite1) TestMemoryAndDiskUsageAfterClose(c *C) { } for _, sql := range SQLs { tk.MustQuery(sql) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.MemTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.DiskTracker.BytesConsumed()) } } -func (s *testSuite2) TestExplainAnalyzeExecutionInfo(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainAnalyzeExecutionInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (v int, k int, key(k))") tk.MustExec("insert into t values (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)") - s.checkExecutionInfo(c, tk, "explain analyze select * from t order by v") - s.checkExecutionInfo(c, tk, "explain analyze select * from t order by v limit 5") - s.checkExecutionInfo(c, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") - s.checkExecutionInfo(c, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") - s.checkExecutionInfo(c, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkExecutionInfo(c, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkExecutionInfo(c, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") - s.checkExecutionInfo(c, tk, "explain analyze select sum(k) from t group by v") - s.checkExecutionInfo(c, tk, "explain analyze select sum(v) from t group by k") - s.checkExecutionInfo(c, tk, "explain analyze select * from t") - s.checkExecutionInfo(c, tk, "explain analyze select k from t use index(k)") - s.checkExecutionInfo(c, tk, "explain analyze select * from t use index(k)") - s.checkExecutionInfo(c, tk, "explain analyze with recursive cte(a) as (select 1 union select a + 1 from cte where a < 1000) select * from cte;") + checkExecutionInfo(t, tk, "explain analyze select * from t order by v") + checkExecutionInfo(t, tk, "explain analyze select * from t order by v limit 5") + checkExecutionInfo(t, tk, "explain analyze select /*+ HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.v = t2.v+1") + checkExecutionInfo(t, tk, "explain analyze select /*+ MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k+1") + checkExecutionInfo(t, tk, "explain analyze select /*+ INL_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkExecutionInfo(t, tk, "explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkExecutionInfo(t, tk, "explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ t1.k from t t1, t t2 where t1.k = t2.k and t1.v=1") + checkExecutionInfo(t, tk, "explain analyze select sum(k) from t group by v") + checkExecutionInfo(t, tk, "explain analyze select sum(v) from t group by k") + checkExecutionInfo(t, tk, "explain analyze select * from t") + checkExecutionInfo(t, tk, "explain analyze select k from t use index(k)") + checkExecutionInfo(t, tk, "explain analyze select * from t use index(k)") + checkExecutionInfo(t, tk, "explain analyze with recursive cte(a) as (select 1 union select a + 1 from cte where a < 1000) select * from cte;") tk.MustExec("CREATE TABLE IF NOT EXISTS nation ( N_NATIONKEY BIGINT NOT NULL,N_NAME CHAR(25) NOT NULL,N_REGIONKEY BIGINT NOT NULL,N_COMMENT VARCHAR(152),PRIMARY KEY (N_NATIONKEY));") tk.MustExec("CREATE TABLE IF NOT EXISTS part ( P_PARTKEY BIGINT NOT NULL,P_NAME VARCHAR(55) NOT NULL,P_MFGR CHAR(25) NOT NULL,P_BRAND CHAR(10) NOT NULL,P_TYPE VARCHAR(25) NOT NULL,P_SIZE BIGINT NOT NULL,P_CONTAINER CHAR(10) NOT NULL,P_RETAILPRICE DECIMAL(15,2) NOT NULL,P_COMMENT VARCHAR(23) NOT NULL,PRIMARY KEY (P_PARTKEY));") @@ -218,7 +236,7 @@ func (s *testSuite2) TestExplainAnalyzeExecutionInfo(c *C) { tk.MustExec("CREATE TABLE IF NOT EXISTS orders ( O_ORDERKEY BIGINT NOT NULL,O_CUSTKEY BIGINT NOT NULL,O_ORDERSTATUS CHAR(1) NOT NULL,O_TOTALPRICE DECIMAL(15,2) NOT NULL,O_ORDERDATE DATE NOT NULL,O_ORDERPRIORITY CHAR(15) NOT NULL,O_CLERK CHAR(15) NOT NULL,O_SHIPPRIORITY BIGINT NOT NULL,O_COMMENT VARCHAR(79) NOT NULL,PRIMARY KEY (O_ORDERKEY),CONSTRAINT FOREIGN KEY ORDERS_FK1 (O_CUSTKEY) references customer(C_CUSTKEY));") tk.MustExec("CREATE TABLE IF NOT EXISTS lineitem ( L_ORDERKEY BIGINT NOT NULL,L_PARTKEY BIGINT NOT NULL,L_SUPPKEY BIGINT NOT NULL,L_LINENUMBER BIGINT NOT NULL,L_QUANTITY DECIMAL(15,2) NOT NULL,L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,L_DISCOUNT DECIMAL(15,2) NOT NULL,L_TAX DECIMAL(15,2) NOT NULL,L_RETURNFLAG CHAR(1) NOT NULL,L_LINESTATUS CHAR(1) NOT NULL,L_SHIPDATE DATE NOT NULL,L_COMMITDATE DATE NOT NULL,L_RECEIPTDATE DATE NOT NULL,L_SHIPINSTRUCT CHAR(25) NOT NULL,L_SHIPMODE CHAR(10) NOT NULL,L_COMMENT VARCHAR(44) NOT NULL,PRIMARY KEY (L_ORDERKEY,L_LINENUMBER),CONSTRAINT FOREIGN KEY LINEITEM_FK1 (L_ORDERKEY) references orders(O_ORDERKEY),CONSTRAINT FOREIGN KEY LINEITEM_FK2 (L_PARTKEY,L_SUPPKEY) references partsupp(PS_PARTKEY, PS_SUPPKEY));") - s.checkExecutionInfo(c, tk, "select nation, o_year, sum(amount) as sum_profit from ( select n_name as nation, extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount from part, supplier, lineitem, partsupp, orders, nation where s_suppkey = l_suppkey and ps_suppkey = l_suppkey and ps_partkey = l_partkey and p_partkey = l_partkey and o_orderkey = l_orderkey and s_nationkey = n_nationkey and p_name like '%dim%' ) as profit group by nation, o_year order by nation, o_year desc;") + checkExecutionInfo(t, tk, "select nation, o_year, sum(amount) as sum_profit from ( select n_name as nation, extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount from part, supplier, lineitem, partsupp, orders, nation where s_suppkey = l_suppkey and ps_suppkey = l_suppkey and ps_partkey = l_partkey and p_partkey = l_partkey and o_orderkey = l_orderkey and s_nationkey = n_nationkey and p_name like '%dim%' ) as profit group by nation, o_year order by nation, o_year desc;") tk.MustExec("drop table if exists nation") tk.MustExec("drop table if exists part") @@ -228,7 +246,7 @@ func (s *testSuite2) TestExplainAnalyzeExecutionInfo(c *C) { tk.MustExec("drop table if exists lineitem") } -func (s *testSuite2) checkExecutionInfo(c *C, tk *testkit.TestKit, sql string) { +func checkExecutionInfo(t *testing.T, tk *testkit.TestKit, sql string) { executionInfoCol := 4 rows := tk.MustQuery(sql).Rows() for _, row := range rows { @@ -236,21 +254,23 @@ func (s *testSuite2) checkExecutionInfo(c *C, tk *testkit.TestKit, sql string) { for i, c := range row { strs[i] = c.(string) } - - c.Assert(strs[executionInfoCol], Not(Equals), "time:0s, loops:0, rows:0") + require.NotEqual(t, "time:0s, loops:0, rows:0", strs[executionInfoCol]) } } -func (s *testSuite2) TestExplainAnalyzeActRowsNotEmpty(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainAnalyzeActRowsNotEmpty(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, index (a))") tk.MustExec("insert into t values (1, 1)") - s.checkActRowsNotEmpty(c, tk, "explain analyze select * from t t1, t t2 where t1.b = t2.a and t1.b = 2333") + checkActRowsNotEmpty(t, tk, "explain analyze select * from t t1, t t2 where t1.b = t2.a and t1.b = 2333") } -func (s *testSuite2) checkActRowsNotEmpty(c *C, tk *testkit.TestKit, sql string) { +func checkActRowsNotEmpty(t *testing.T, tk *testkit.TestKit, sql string) { actRowsCol := 2 rows := tk.MustQuery(sql).Rows() for _, row := range rows { @@ -258,28 +278,34 @@ func (s *testSuite2) checkActRowsNotEmpty(c *C, tk *testkit.TestKit, sql string) for i, c := range row { strs[i] = c.(string) } - - c.Assert(strs[actRowsCol], Not(Equals), "") + require.NotEqual(t, "", strs[actRowsCol]) } } -func checkActRows(c *C, tk *testkit.TestKit, sql string, expected []string) { +func checkActRows(t *testing.T, tk *testkit.TestKit, sql string, expected []string) { actRowsCol := 2 rows := tk.MustQuery("explain analyze " + sql).Rows() - c.Assert(len(rows), Equals, len(expected)) + require.Equal(t, len(expected), len(rows)) for id, row := range rows { strs := make([]string, len(row)) for i, c := range row { strs[i] = c.(string) } - c.Assert(strs[actRowsCol], Equals, expected[id]) + require.Equal(t, expected[id], strs[actRowsCol], fmt.Sprintf("error comparing %s", sql)) } } -func (s *testSuite1) TestCheckActRowsWithUnistore(c *C) { +func TestCheckActRowsWithUnistore(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableCollectExecutionInfo = true + }) + store, clean := testkit.CreateMockStore(t) + defer clean() // testSuite1 use default mockstore which is unistore - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t_unistore_act_rows") tk.MustExec("create table t_unistore_act_rows(a int, b int, index(a, b))") tk.MustExec("insert into t_unistore_act_rows values (1, 0), (1, 0), (2, 0), (2, 1)") @@ -330,12 +356,15 @@ func (s *testSuite1) TestCheckActRowsWithUnistore(c *C) { } for _, test := range tests { - checkActRows(c, tk, test.sql, test.expected) + checkActRows(t, tk, test.sql, test.expected) } } -func (s *testSuite2) TestExplainAnalyzeCTEMemoryAndDiskInfo(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainAnalyzeCTEMemoryAndDiskInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int)") tk.MustExec("insert into t with recursive cte(a) as (select 1 union select a + 1 from cte where a < 1000) select * from cte;") @@ -343,31 +372,37 @@ func (s *testSuite2) TestExplainAnalyzeCTEMemoryAndDiskInfo(c *C) { rows := tk.MustQuery("explain analyze with recursive cte(a) as (select 1 union select a + 1 from cte where a < 1000)" + " select * from cte, t;").Rows() - c.Assert(rows[4][7].(string), Not(Equals), "N/A") - c.Assert(rows[4][8].(string), Equals, "0 Bytes") + require.NotEqual(t, "N/A", rows[4][7].(string)) + require.Equal(t, "0 Bytes", rows[4][8].(string)) tk.MustExec("set @@tidb_mem_quota_query=10240;") rows = tk.MustQuery("explain analyze with recursive cte(a) as (select 1 union select a + 1 from cte where a < 1000)" + " select * from cte, t;").Rows() - c.Assert(rows[4][7].(string), Not(Equals), "N/A") - c.Assert(rows[4][8].(string), Not(Equals), "N/A") + require.NotEqual(t, "N/A", rows[4][7].(string)) + require.NotEqual(t, "N/A", rows[4][8].(string)) } -func (s *testSuite) TestExplainStatementsSummary(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainStatementsSummary(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustQuery("desc select * from information_schema.statements_summary").Check(testkit.Rows( `MemTableScan_4 10000.00 root table:STATEMENTS_SUMMARY `)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest is null").Check(testutil.RowsWithSep("|", + tk.MustQuery("desc select * from information_schema.statements_summary where digest is null").Check(testkit.RowsWithSep("|", `Selection_5|8000.00|root| isnull(Column#5)`, `└─MemTableScan_6|10000.00|root|table:STATEMENTS_SUMMARY|`)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest = 'abcdefg'").Check(testutil.RowsWithSep(" ", + tk.MustQuery("desc select * from information_schema.statements_summary where digest = 'abcdefg'").Check(testkit.RowsWithSep(" ", `MemTableScan_5 10000.00 root table:STATEMENTS_SUMMARY digests: ["abcdefg"]`)) - tk.MustQuery("desc select * from information_schema.statements_summary where digest in ('a','b','c')").Check(testutil.RowsWithSep(" ", + tk.MustQuery("desc select * from information_schema.statements_summary where digest in ('a','b','c')").Check(testkit.RowsWithSep(" ", `MemTableScan_5 10000.00 root table:STATEMENTS_SUMMARY digests: ["a","b","c"]`)) } -func (s *testSuite) TestFix29401(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestFix29401(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists tt123;") tk.MustExec(`CREATE TABLE tt123 ( id int(11) NOT NULL, diff --git a/executor/explain_unit_test.go b/executor/explain_unit_test.go index 668e28e1a51c4..b1aacb6d5cb7f 100644 --- a/executor/explain_unit_test.go +++ b/executor/explain_unit_test.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) var ( @@ -37,11 +38,11 @@ type mockErrorOperator struct { closed bool } -func (e *mockErrorOperator) Open(ctx context.Context) error { +func (e *mockErrorOperator) Open(_ context.Context) error { return nil } -func (e *mockErrorOperator) Next(ctx context.Context, req *chunk.Chunk) error { +func (e *mockErrorOperator) Next(_ context.Context, _ *chunk.Chunk) error { if e.toPanic { panic("next panic") } else { @@ -76,11 +77,9 @@ func TestExplainAnalyzeInvokeNextAndClose(t *testing.T) { explainExec.analyzeExec = &mockOpr tmpCtx := context.Background() _, err := explainExec.generateExplainInfo(tmpCtx) + require.EqualError(t, err, "next error, close error") + require.True(t, mockOpr.closed) - expectedStr := "next error, close error" - if err != nil && (err.Error() != expectedStr || !mockOpr.closed) { - t.Errorf(err.Error()) - } // mockErrorOperator panic explainExec = &ExplainExec{ baseExecutor: baseExec, @@ -89,13 +88,10 @@ func TestExplainAnalyzeInvokeNextAndClose(t *testing.T) { mockOpr = mockErrorOperator{baseExec, true, false} explainExec.analyzeExec = &mockOpr defer func() { - if panicErr := recover(); panicErr == nil || !mockOpr.closed { - t.Errorf("panic test failed: without panic or close() is not called") - } + panicErr := recover() + require.NotNil(t, panicErr) + require.True(t, mockOpr.closed) }() - - _, err = explainExec.generateExplainInfo(tmpCtx) - if err != nil { - t.Errorf(err.Error()) - } + _, _ = explainExec.generateExplainInfo(tmpCtx) + require.FailNow(t, "generateExplainInfo should panic") } diff --git a/executor/explainfor_test.go b/executor/explainfor_test.go index 5befb576c132a..a80d34756fa69 100644 --- a/executor/explainfor_test.go +++ b/executor/explainfor_test.go @@ -20,18 +20,17 @@ import ( "fmt" "math" "strconv" - "sync" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/israce" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) // mockSessionManager is a mocked session manager which is used for test. @@ -61,49 +60,55 @@ func (msm *mockSessionManager1) GetProcessInfo(id uint64) (*util.ProcessInfo, bo return &util.ProcessInfo{}, false } -// Kill implements the SessionManager.Kill interface. -func (msm *mockSessionManager1) Kill(cid uint64, query bool) { +func (msm *mockSessionManager1) StoreInternalSession(se interface{}) { } -func (msm *mockSessionManager1) KillAllConnections() { +func (msm *mockSessionManager1) DeleteInternalSession(se interface{}) { } -func (msm *mockSessionManager1) UpdateTLSConfig(cfg *tls.Config) { +func (msm *mockSessionManager1) GetInternalSessionStartTSList() []uint64 { + return nil } -func (msm *mockSessionManager1) ServerID() uint64 { - return 1 -} +func (msm *mockSessionManager1) Kill(_ uint64, _ bool) {} +func (msm *mockSessionManager1) KillAllConnections() {} +func (msm *mockSessionManager1) UpdateTLSConfig(_ *tls.Config) {} +func (msm *mockSessionManager1) ServerID() uint64 { return 1 } + +func TestExplainFor(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -func (s *testSerialSuite) TestExplainFor(c *C) { - tkRoot := testkit.NewTestKitWithInit(c, s.store) - tkUser := testkit.NewTestKitWithInit(c, s.store) + tkRoot := testkit.NewTestKit(t, store) + tkUser := testkit.NewTestKit(t, store) + + tkRoot.MustExec("use test") tkRoot.MustExec("drop table if exists t1, t2;") tkRoot.MustExec("create table t1(c1 int, c2 int)") tkRoot.MustExec("create table t2(c1 int, c2 int)") tkRoot.MustExec("create user tu@'%'") - tkRoot.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) - tkUser.Se.Auth(&auth.UserIdentity{Username: "tu", Hostname: "localhost", CurrentUser: true, AuthUsername: "tu", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tkRoot.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tkUser.Session().Auth(&auth.UserIdentity{Username: "tu", Hostname: "localhost", CurrentUser: true, AuthUsername: "tu", AuthHostname: "%"}, nil, []byte("012345678901234567890")) tkRoot.MustExec("set @@tidb_enable_collect_execution_info=0;") tkRoot.MustQuery("select * from t1;") - tkRootProcess := tkRoot.Se.ShowProcess() + tkRootProcess := tkRoot.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tkRoot.Se.SetSessionManager(&mockSessionManager1{PS: ps}) - tkUser.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tkUser.Session().SetSessionManager(&mockSessionManager1{PS: ps}) tkRoot.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Check(testkit.Rows( "TableReader_5 10000.00 root data:TableFullScan_4", "└─TableFullScan_4 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", )) tkRoot.MustExec("set @@tidb_enable_collect_execution_info=1;") check := func() { - tkRootProcess = tkRoot.Se.ShowProcess() + tkRootProcess = tkRoot.Session().ShowProcess() ps = []*util.ProcessInfo{tkRootProcess} - tkRoot.Se.SetSessionManager(&mockSessionManager1{PS: ps}) - tkUser.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tkUser.Session().SetSessionManager(&mockSessionManager1{PS: ps}) rows := tkRoot.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(len(rows[0]), Equals, 9) + require.Len(t, rows, 2) + require.Len(t, rows[0], 9) buf := bytes.NewBuffer(nil) for i, row := range rows { if i > 0 { @@ -116,70 +121,77 @@ func (s *testSerialSuite) TestExplainFor(c *C) { buf.WriteString(fmt.Sprintf("%v", v)) } } - c.Assert(buf.String(), Matches, ""+ - "TableReader_5 10000.00 0 root time:.*, loops:1, cop_task: {num:.*, max:.*, proc_keys:.* rpc_num: 1, rpc_time:.*} data:TableFullScan_4 N/A N/A\n"+ - "└─TableFullScan_4 10000.00 0 cop.* table:t1 tikv_task:{time:.*, loops:0} keep order:false, stats:pseudo N/A N/A") + require.Regexp(t, "TableReader_5 10000.00 0 root time:.*, loops:1, cop_task: {num:.*, max:.*, proc_keys:.* rpc_num: 1, rpc_time:.*} data:TableFullScan_4 N/A N/A\n"+ + "└─TableFullScan_4 10000.00 0 cop.* table:t1 tikv_task:{time:.*, loops:0} keep order:false, stats:pseudo N/A N/A", + buf.String()) } tkRoot.MustQuery("select * from t1;") check() tkRoot.MustQuery("explain analyze select * from t1;") check() err := tkUser.ExecToErr(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)) - c.Check(core.ErrAccessDenied.Equal(err), IsTrue) + require.True(t, core.ErrAccessDenied.Equal(err)) err = tkUser.ExecToErr("explain for connection 42") - c.Check(core.ErrNoSuchThread.Equal(err), IsTrue) + require.True(t, core.ErrNoSuchThread.Equal(err)) tkRootProcess.Plan = nil ps = []*util.ProcessInfo{tkRootProcess} - tkRoot.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tkRoot.Session().SetSessionManager(&mockSessionManager1{PS: ps}) tkRoot.MustExec(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)) } -func (s *testSerialSuite) TestExplainForVerbose(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk2 := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("use test;") +func TestExplainForVerbose(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(id int);") tk.MustQuery("select * from t1;") - tkRootProcess := tk.Se.ShowProcess() + tkRootProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) rs := tk.MustQuery("explain format = 'verbose' select * from t1").Rows() rs2 := tk2.MustQuery(fmt.Sprintf("explain format = 'verbose' for connection %d", tkRootProcess.ID)).Rows() - c.Assert(len(rs), Equals, len(rs2)) + require.Len(t, rs, len(rs2)) for i := range rs { - c.Assert(rs[i], DeepEquals, rs2[i]) + require.Equal(t, rs2[i], rs[i]) } tk.MustExec("set @@tidb_enable_collect_execution_info=1;") tk.MustExec("drop table if exists t2") tk.MustExec("create table t2(id int);") tk.MustQuery("select * from t2;") - tkRootProcess = tk.Se.ShowProcess() + tkRootProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkRootProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) rs = tk.MustQuery("explain format = 'verbose' select * from t2").Rows() rs2 = tk2.MustQuery(fmt.Sprintf("explain format = 'verbose' for connection %d", tkRootProcess.ID)).Rows() - c.Assert(len(rs), Equals, len(rs2)) + require.Len(t, rs, len(rs2)) for i := range rs { // "id", "estRows", "estCost", "task", "access object", "operator info" - c.Assert(len(rs[i]), Equals, 6) + require.Len(t, rs[i], 6) // "id", "estRows", "estCost", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk" - c.Assert(len(rs2[i]), Equals, 10) + require.Len(t, rs2[i], 10) for j := 0; j < 3; j++ { - c.Assert(rs[i][j], Equals, rs2[i][j]) + require.Equal(t, rs2[i][j], rs[i][j]) } } } -func (s *testSerialSuite) TestIssue11124(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk2 := testkit.NewTestKitWithInit(c, s.store) +func TestIssue11124(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("drop table if exists kankan1") tk.MustExec("drop table if exists kankan2") @@ -188,20 +200,22 @@ func (s *testSerialSuite) TestIssue11124(c *C) { tk.MustExec("insert into kankan1 values(1, 'a'), (2, 'a');") tk.MustExec("insert into kankan2 values(2, 'z');") tk.MustQuery("select t1.id from kankan1 t1 left join kankan2 t2 on t1.id = t2.id where (case when t1.name='b' then 'case2' when t1.name='a' then 'case1' else NULL end) = 'case1'") - tkRootProcess := tk.Se.ShowProcess() + tkRootProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkRootProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) - tk2.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk2.Session().SetSessionManager(&mockSessionManager1{PS: ps}) rs := tk.MustQuery("explain select t1.id from kankan1 t1 left join kankan2 t2 on t1.id = t2.id where (case when t1.name='b' then 'case2' when t1.name='a' then 'case1' else NULL end) = 'case1'").Rows() rs2 := tk2.MustQuery(fmt.Sprintf("explain for connection %d", tkRootProcess.ID)).Rows() for i := range rs { - c.Assert(rs[i], DeepEquals, rs2[i]) + require.Equal(t, rs2[i], rs[i]) } } -func (s *testSuite) TestExplainMemTablePredicate(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainMemTablePredicate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from METRICS_SCHEMA.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ").Check(testkit.Rows( "MemTableScan_5 10000.00 root table:tidb_query_duration PromQL:histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance)), start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s")) tk.MustQuery("desc select * from METRICS_SCHEMA.up where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13' ").Check(testkit.Rows( @@ -221,8 +235,10 @@ func (s *testSuite) TestExplainMemTablePredicate(c *C) { "MemTableScan_5 10000.00 root table:SLOW_QUERY start_time:2019-12-23 16:10:13.000000, end_time:2019-12-23 16:30:13.000000")) } -func (s *testSuite) TestExplainClusterTable(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainClusterTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from information_schema.cluster_config where type in ('tikv', 'tidb')").Check(testkit.Rows( `MemTableScan_5 10000.00 root table:CLUSTER_CONFIG node_types:["tidb","tikv"]`)) tk.MustQuery("desc select * from information_schema.cluster_config where instance='192.168.1.7:2379'").Check(testkit.Rows( @@ -231,8 +247,10 @@ func (s *testSuite) TestExplainClusterTable(c *C) { `MemTableScan_5 10000.00 root table:CLUSTER_CONFIG node_types:["tidb"], instances:["192.168.1.7:2379"]`)) } -func (s *testSuite) TestInspectionResultTable(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInspectionResultTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from information_schema.inspection_result where rule = 'ddl' and rule = 'config'").Check(testkit.Rows( `MemTableScan_5 10000.00 root table:INSPECTION_RESULT skip_inspection:true`)) tk.MustQuery("desc select * from information_schema.inspection_result where rule in ('ddl', 'config')").Check(testkit.Rows( @@ -243,8 +261,10 @@ func (s *testSuite) TestInspectionResultTable(c *C) { `MemTableScan_5 10000.00 root table:INSPECTION_RESULT rules:["config","ddl"], items:["ddl.lease","raftstore.threadpool"]`)) } -func (s *testSuite) TestInspectionRuleTable(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInspectionRuleTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from information_schema.inspection_rules where type='inspection'").Check(testkit.Rows( `MemTableScan_5 10000.00 root table:INSPECTION_RULES node_types:["inspection"]`)) tk.MustQuery("desc select * from information_schema.inspection_rules where type='inspection' or type='summary'").Check(testkit.Rows( @@ -253,28 +273,27 @@ func (s *testSuite) TestInspectionRuleTable(c *C) { `MemTableScan_5 10000.00 root table:INSPECTION_RULES skip_request: true`)) } -type testPrepareSerialSuite struct { - *baseTestSuite -} +func TestExplainForConnPlanCache(t *testing.T) { + t.Skip("unstable") -func (s *testPrepareSerialSuite) TestExplainForConnPlanCache(c *C) { - c.Skip("unstable") - if israce.RaceEnabled { - c.Skip("skip race test") - } orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - var err error - tk1 := testkit.NewTestKit(c, s.store) - tk1.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) - tk2 := testkit.NewTestKitWithInit(c, s.store) + require.NoError(t, err) + tk1.SetSession(se) + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") tk1.MustExec("use test") tk1.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -284,7 +303,7 @@ func (s *testPrepareSerialSuite) TestExplainForConnPlanCache(c *C) { tk1.MustExec("set @p0='1'") executeQuery := "execute stmt using @p0" - explainQuery := "explain for connection " + strconv.FormatUint(tk1.Se.ShowProcess().ID, 10) + explainQuery := "explain for connection " + strconv.FormatUint(tk1.Session().ShowProcess().ID, 10) explainResult := testkit.Rows( "TableReader_7 10.00 root data:Selection_6", @@ -298,8 +317,8 @@ func (s *testPrepareSerialSuite) TestExplainForConnPlanCache(c *C) { // single test tk1.MustExec(executeQuery) - tk2.Se.SetSessionManager(&mockSessionManager1{ - PS: []*util.ProcessInfo{tk1.Se.ShowProcess()}, + tk2.Session().SetSessionManager(&mockSessionManager1{ + PS: []*util.ProcessInfo{tk1.Session().ShowProcess()}, }) tk2.MustQuery(explainQuery).Check(explainResult) tk1.MustExec(executeQuery) @@ -308,42 +327,41 @@ func (s *testPrepareSerialSuite) TestExplainForConnPlanCache(c *C) { // multiple test, '1000' is both effective and efficient. repeats := 1000 - var wg sync.WaitGroup - wg.Add(2) + var wg util.WaitGroupWrapper - go func() { + wg.Run(func() { for i := 0; i < repeats; i++ { tk1.MustExec(executeQuery) } - wg.Done() - }() + }) - go func() { + wg.Run(func() { for i := 0; i < repeats; i++ { - tk2.Se.SetSessionManager(&mockSessionManager1{ - PS: []*util.ProcessInfo{tk1.Se.ShowProcess()}, + tk2.Session().SetSessionManager(&mockSessionManager1{ + PS: []*util.ProcessInfo{tk1.Session().ShowProcess()}, }) tk2.MustQuery(explainQuery).Check(explainResult) } - wg.Done() - }() + }) wg.Wait() } -func (s *testPrepareSerialSuite) TestSavedPlanPanicPlanCache(c *C) { +func TestSavedPlanPanicPlanCache(t *testing.T) { orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - var err error - tk := testkit.NewTestKit(c, s.store) - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -359,49 +377,54 @@ func (s *testPrepareSerialSuite) TestSavedPlanPanicPlanCache(c *C) { tk.MustExec("set @p = 1") tk.MustQuery("execute stmt using @p").Check(testkit.Rows()) err = tk.ExecToErr("insert into t(a,b,c) values(3,3,3)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:3105]The value specified for generated column 'c' in table 't' is not allowed.") + require.EqualError(t, err, "[planner:3105]The value specified for generated column 'c' in table 't' is not allowed.") } -func (s *testPrepareSerialSuite) TestExplainDotForExplainPlan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainDotForExplainPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) rows := tk.MustQuery("select connection_id()").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) connID := rows[0][0].(string) tk.MustQuery("explain format = 'brief' select 1").Check(testkit.Rows( "Projection 1.00 root 1->Column#1", "└─TableDual 1.00 root rows:1", )) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) tk.MustQuery(fmt.Sprintf("explain format=\"dot\" for connection %s", connID)).Check(nil) } -func (s *testPrepareSerialSuite) TestExplainDotForQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk2 := testkit.NewTestKit(c, s.store) +func TestExplainDotForQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) rows := tk.MustQuery("select connection_id()").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) connID := rows[0][0].(string) tk.MustQuery("select 1") - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) expected := tk2.MustQuery("explain format=\"dot\" select 1").Rows() got := tk.MustQuery(fmt.Sprintf("explain format=\"dot\" for connection %s", connID)).Rows() for i := range got { - c.Assert(got[i], DeepEquals, expected[i]) + require.Equal(t, expected[i], got[i]) } } -func (s *testSuite) TestExplainTableStorage(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainTableStorage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'").Check(testkit.Rows( "MemTableScan_5 10000.00 root table:TABLE_STORAGE_STATS schema:[\"information_schema\"]")) tk.MustQuery("desc select * from information_schema.TABLE_STORAGE_STATS where TABLE_NAME = 'schemata'").Check(testkit.Rows( @@ -410,8 +433,10 @@ func (s *testSuite) TestExplainTableStorage(c *C) { "MemTableScan_5 10000.00 root table:TABLE_STORAGE_STATS schema:[\"information_schema\"], table:[\"schemata\"]")) } -func (s *testSuite) TestInspectionSummaryTable(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInspectionSummaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("desc select * from information_schema.inspection_summary where rule='ddl'").Check(testkit.Rows( `Selection_5 8000.00 root eq(Column#1, "ddl")`, @@ -463,8 +488,10 @@ func (s *testSuite) TestInspectionSummaryTable(c *C) { )) } -func (s *testSuite) TestExplainTiFlashSystemTables(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainTiFlashSystemTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tiflashInstance := "192.168.1.7:3930" database := "test" table := "t" @@ -486,19 +513,21 @@ func (s *testSuite) TestExplainTiFlashSystemTables(c *C) { fmt.Sprintf("MemTableScan_5 10000.00 root table:TIFLASH_SEGMENTS tiflash_instances:[\"%s\"], tidb_databases:[\"%s\"], tidb_tables:[\"%s\"]", tiflashInstance, database, table))) } -func (s *testPrepareSerialSuite) TestPointGetUserVarPlanCache(c *C) { +func TestPointGetUserVarPlanCache(t *testing.T) { orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - tk := testkit.NewTestKitWithInit(c, s.store) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t1") tk.MustExec("CREATE TABLE t1 (a BIGINT, b VARCHAR(40), PRIMARY KEY (a, b))") tk.MustExec("INSERT INTO t1 VALUES (1,'3'),(2,'4')") @@ -510,9 +539,9 @@ func (s *testPrepareSerialSuite) TestPointGetUserVarPlanCache(c *C) { tk.MustQuery("execute stmt using @a").Check(testkit.Rows( "1 3 1 1", )) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use idx_a `Projection_9 1.00 root test.t1.a, test.t1.b, test.t2.a, test.t2.b`, `└─IndexJoin_17 1.00 root inner join, inner:TableReader_13, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)`, @@ -526,9 +555,9 @@ func (s *testPrepareSerialSuite) TestPointGetUserVarPlanCache(c *C) { tk.MustQuery("execute stmt using @a").Check(testkit.Rows( "2 4 2 2", )) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( // can use idx_a `Projection_9 1.00 root test.t1.a, test.t1.b, test.t2.a, test.t2.b`, `└─IndexJoin_17 1.00 root inner join, inner:TableReader_13, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)`, @@ -542,8 +571,10 @@ func (s *testPrepareSerialSuite) TestPointGetUserVarPlanCache(c *C) { )) } -func (s *testPrepareSerialSuite) TestExpressionIndexPreparePlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExpressionIndexPreparePlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -551,11 +582,11 @@ func (s *testPrepareSerialSuite) TestExpressionIndexPreparePlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -565,24 +596,26 @@ func (s *testPrepareSerialSuite) TestExpressionIndexPreparePlanCache(c *C) { tk.MustExec("set @a = 123") tk.MustExec("execute stmt using @a") - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[2][3], Matches, ".*expression_index.*") - c.Assert(res.Rows()[2][4], Matches, ".*[123,123].*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*expression_index.*", res.Rows()[2][3]) + require.Regexp(t, ".*[123,123].*", res.Rows()[2][4]) tk.MustExec("set @a = 1234") tk.MustExec("execute stmt using @a") res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[2][3], Matches, ".*expression_index.*") - c.Assert(res.Rows()[2][4], Matches, ".*[1234,1234].*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*expression_index.*", res.Rows()[2][3]) + require.Regexp(t, ".*[1234,1234].*", res.Rows()[2][4]) } -func (s *testPrepareSerialSuite) TestIssue28259(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue28259(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -590,11 +623,11 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) // test for indexRange tk.MustExec("use test") @@ -607,35 +640,35 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) { tk.MustExec("set @a=5516958330762833919, @b=8551969118506051323, @c=2887622822023883594;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("8502658334322817163")) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 3) - c.Assert(res.Rows()[0][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 3) + require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[2][0]) tk.MustExec("set @a=-1696020282760139948, @b=-2619168038882941276, @c=-4004648990067362699;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[0][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[3][0], Matches, ".*IndexFullScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) + require.Regexp(t, ".*IndexFullScan.*", res.Rows()[3][0]) res = tk.MustQuery("explain format = 'brief' select col1 from UK_GCOL_VIRTUAL_18588 use index(UK_COL1) " + "where col1 between -1696020282760139948 and -2619168038882941276 or col1 < -4004648990067362699;") - c.Assert(len(res.Rows()), Equals, 3) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexFullScan.*") + require.Len(t, res.Rows(), 3) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexFullScan.*", res.Rows()[2][0]) res = tk.MustQuery("explain format = 'brief' select col1 from UK_GCOL_VIRTUAL_18588 use index(UK_COL1) " + "where col1 between 5516958330762833919 and 8551969118506051323 or col1 < 2887622822023883594;") - c.Assert(len(res.Rows()), Equals, 2) - c.Assert(res.Rows()[1][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 2) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[1][0]) tk.MustExec("drop table if exists t;") tk.MustExec("CREATE TABLE t (a int, b int, index idx(a, b));") @@ -643,44 +676,44 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) { tk.MustExec(`prepare stmt from 'select a from t where (a between ? and ? or a < ?) and b < 1;'`) tk.MustExec("set @a=0, @b=2, @c=2;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][4], Equals, "lt(test.t.b, 1), or(and(ge(test.t.a, 0), le(test.t.a, 2)), lt(test.t.a, 2))") - c.Assert(res.Rows()[2][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[4][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Equal(t, "lt(test.t.b, 1), or(and(ge(test.t.a, 0), le(test.t.a, 2)), lt(test.t.a, 2))", res.Rows()[1][4]) + require.Regexp(t, ".*IndexReader.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[4][0]) tk.MustExec("set @a=2, @b=1, @c=1;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][4], Equals, "lt(test.t.b, 1), or(and(ge(test.t.a, 2), le(test.t.a, 1)), lt(test.t.a, 1))") - c.Assert(res.Rows()[2][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[4][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Equal(t, "lt(test.t.b, 1), or(and(ge(test.t.a, 2), le(test.t.a, 1)), lt(test.t.a, 1))", res.Rows()[1][4]) + require.Regexp(t, ".*IndexReader.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[4][0]) res = tk.MustQuery("explain format = 'brief' select a from t use index(idx) " + "where (a between 0 and 2 or a < 2) and b < 1;") - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[1][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[2][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][4], Equals, "lt(test.t.b, 1)") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*IndexReader.*", res.Rows()[1][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[2][0]) + require.Equal(t, "lt(test.t.b, 1)", res.Rows()[2][4]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) res = tk.MustQuery("explain format = 'brief' select a from t use index(idx) " + "where (a between 2 and 1 or a < 1) and b < 1;") - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[1][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[2][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][4], Equals, "lt(test.t.b, 1)") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*IndexReader.*", res.Rows()[1][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[2][0]) + require.Equal(t, "lt(test.t.b, 1)", res.Rows()[2][4]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) // test for indexLookUp tk.MustExec("drop table if exists t;") @@ -689,42 +722,42 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) { tk.MustExec(`prepare stmt from 'select /*+ USE_INDEX(t, idx) */ a from t where (a between ? and ? or a < ?) and b < 1;'`) tk.MustExec("set @a=0, @b=2, @c=2;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 6) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[4][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[5][0], Matches, ".*TableRowIDScan.*") + require.Len(t, res.Rows(), 6) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[4][0]) + require.Regexp(t, ".*TableRowIDScan.*", res.Rows()[5][0]) tk.MustExec("set @a=2, @b=1, @c=1;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 6) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[4][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[5][0], Matches, ".*TableRowIDScan.*") + require.Len(t, res.Rows(), 6) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[4][0]) + require.Regexp(t, ".*TableRowIDScan.*", res.Rows()[5][0]) res = tk.MustQuery("explain format = 'brief' select /*+ USE_INDEX(t, idx) */ a from t use index(idx) " + "where (a between 0 and 2 or a < 2) and b < 1;") - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[2][0]) res = tk.MustQuery("explain format = 'brief' select /*+ USE_INDEX(t, idx) */ a from t use index(idx) " + "where (a between 2 and 1 or a < 1) and b < 1;") - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[2][0]) // test for tableReader tk.MustExec("drop table if exists t;") @@ -733,65 +766,67 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) { tk.MustExec(`prepare stmt from 'select a from t where (a between ? and ? or a < ?) and b < 1;'`) tk.MustExec("set @a=0, @b=2, @c=2;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1")) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][4], Equals, "lt(test.t.b, 1), or(and(ge(test.t.a, 0), le(test.t.a, 2)), lt(test.t.a, 2))") - c.Assert(res.Rows()[2][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[3][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[4][0], Matches, ".*TableRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Equal(t, "lt(test.t.b, 1), or(and(ge(test.t.a, 0), le(test.t.a, 2)), lt(test.t.a, 2))", res.Rows()[1][4]) + require.Regexp(t, ".*TableReader.*", res.Rows()[2][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[3][0]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[4][0]) tk.MustExec("set @a=2, @b=1, @c=1;") tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][4], Equals, "lt(test.t.b, 1), or(and(ge(test.t.a, 2), le(test.t.a, 1)), lt(test.t.a, 1))") - c.Assert(res.Rows()[2][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[3][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[4][0], Matches, ".*TableRangeScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Equal(t, "lt(test.t.b, 1), or(and(ge(test.t.a, 2), le(test.t.a, 1)), lt(test.t.a, 1))", res.Rows()[1][4]) + require.Regexp(t, ".*TableReader.*", res.Rows()[2][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[3][0]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[4][0]) res = tk.MustQuery("explain format = 'brief' select a from t " + "where (a between 0 and 2 or a < 2) and b < 1;") - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[1][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[2][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][4], Equals, "lt(test.t.b, 1)") - c.Assert(res.Rows()[3][0], Matches, ".*TableRangeScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*TableReader.*", res.Rows()[1][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[2][0]) + require.Equal(t, "lt(test.t.b, 1)", res.Rows()[2][4]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[3][0]) res = tk.MustQuery("explain format = 'brief' select a from t " + "where (a between 2 and 1 or a < 1) and b < 1;") - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[1][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[2][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][4], Equals, "lt(test.t.b, 1)") - c.Assert(res.Rows()[3][0], Matches, ".*TableRangeScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*TableReader.*", res.Rows()[1][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[2][0]) + require.Equal(t, "lt(test.t.b, 1)", res.Rows()[2][4]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[3][0]) tk.MustExec("drop table if exists t;") tk.MustExec("CREATE TABLE t (a int primary key, b int, c int, d int);") tk.MustExec(`prepare stmt from 'select * from t where ((a > ? and a < 5 and b > 2) or (a > ? and a < 10 and c > 3)) and d = 5;';`) tk.MustExec("set @a=1, @b=8;") tk.MustQuery("execute stmt using @a,@b;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 4) - c.Assert(res.Rows()[0][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[2][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[3][0], Matches, ".*TableRangeScan.*") + require.Len(t, res.Rows(), 4) + require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) + require.Regexp(t, ".*TableReader.*", res.Rows()[1][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[2][0]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[3][0]) } -func (s *testPrepareSerialSuite) TestIssue28696(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue28696(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -799,11 +834,11 @@ func (s *testPrepareSerialSuite) TestIssue28696(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -815,27 +850,29 @@ func (s *testPrepareSerialSuite) TestIssue28696(c *C) { tk.MustExec("set @a='bbcsa';") tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("4")) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 6) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[4][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[5][0], Matches, ".*TableRowIDScan.*") + require.Len(t, res.Rows(), 6) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[4][0]) + require.Regexp(t, ".*TableRowIDScan.*", res.Rows()[5][0]) res = tk.MustQuery("explain format = 'brief' select a from t1 where b = 'bbcsa';") - c.Assert(len(res.Rows()), Equals, 5) - c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[3][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[4][0], Matches, ".*TableRowIDScan.*") + require.Len(t, res.Rows(), 5) + require.Regexp(t, ".*IndexLookUp.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[2][0]) + require.Regexp(t, ".*Selection.*", res.Rows()[3][0]) + require.Regexp(t, ".*TableRowIDScan.*", res.Rows()[4][0]) } -func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIndexMerge4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -843,11 +880,11 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -871,17 +908,17 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @a,@b,@c,@d,@e;").Check(testkit.Rows("aa 1333053589 1037-12-26 01:38:52")) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 7) - c.Assert(res.Rows()[1][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[2][0], Matches, ".*IndexMerge.*") - c.Assert(res.Rows()[4][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[4][4], Equals, "range:(NULL,\"mm\"), (\"mm\",+inf], keep order:false, stats:pseudo") - c.Assert(res.Rows()[5][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[5][4], Equals, "range:[0198-09-29 20:19:49,0198-09-29 20:19:49], keep order:false, stats:pseudo") + require.Len(t, res.Rows(), 7) + require.Regexp(t, ".*Selection.*", res.Rows()[1][0]) + require.Regexp(t, ".*IndexMerge.*", res.Rows()[2][0]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[4][0]) + require.Equal(t, "range:(NULL,\"mm\"), (\"mm\",+inf], keep order:false, stats:pseudo", res.Rows()[4][4]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[5][0]) + require.Equal(t, "range:[0198-09-29 20:19:49,0198-09-29 20:19:49], keep order:false, stats:pseudo", res.Rows()[5][4]) // test for cluster index in indexMerge tk.MustExec("drop table if exists t;") @@ -891,17 +928,17 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { tk.MustExec("set @a = 0, @b = 3;") tk.MustQuery("execute stmt using @a, @b;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(len(res.Rows()), Equals, 6) - c.Assert(res.Rows()[0][0], Matches, ".*Selection.*") - c.Assert(res.Rows()[1][0], Matches, ".*IndexMerge.*") - c.Assert(res.Rows()[2][0], Matches, ".*TableRangeScan.*") - c.Assert(res.Rows()[2][4], Equals, "range:(0,3), keep order:false, stats:pseudo") - c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*") - c.Assert(res.Rows()[3][4], Equals, "range:(1,+inf], keep order:false, stats:pseudo") + require.Len(t, res.Rows(), 6) + require.Regexp(t, ".*Selection.*", res.Rows()[0][0]) + require.Regexp(t, ".*IndexMerge.*", res.Rows()[1][0]) + require.Regexp(t, ".*TableRangeScan.*", res.Rows()[2][0]) + require.Equal(t, "range:(0,3), keep order:false, stats:pseudo", res.Rows()[2][4]) + require.Regexp(t, ".*IndexRangeScan.*", res.Rows()[3][0]) + require.Equal(t, "range:(1,+inf], keep order:false, stats:pseudo", res.Rows()[3][4]) // test for prefix index tk.MustExec("drop table if exists t1;") @@ -912,20 +949,20 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { tk.MustExec("set @a='bbcsa', @b='ddcdsaf';") tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("4 bbcsa 4")) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(res.Rows()[1][0], Matches, ".*IndexMerge.*") + require.Regexp(t, ".*IndexMerge.*", res.Rows()[1][0]) tk.MustQuery("execute stmt using @b;").Check(testkit.Rows("3 ddcdsaf 3")) tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @b;").Check(testkit.Rows("3 ddcdsaf 3")) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(res.Rows()[1][0], Matches, ".*IndexMerge.*") + require.Regexp(t, ".*IndexMerge.*", res.Rows()[1][0]) // rewrite the origin indexMerge test tk.MustExec("drop table if exists t;") @@ -1003,8 +1040,10 @@ func (s *testPrepareSerialSuite) TestIndexMerge4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) } -func (s *testPrepareSerialSuite) TestSetOperations4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestSetOperations4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1012,11 +1051,11 @@ func (s *testPrepareSerialSuite) TestSetOperations4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1080,8 +1119,10 @@ func (s *testPrepareSerialSuite) TestSetOperations4PlanCache(c *C) { tk.MustQuery("execute stmt;").Sort().Check(testkit.Rows("1", "1")) } -func (s *testPrepareSerialSuite) TestSPM4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestSPM4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1089,11 +1130,11 @@ func (s *testPrepareSerialSuite) TestSPM4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1103,37 +1144,37 @@ func (s *testPrepareSerialSuite) TestSPM4PlanCache(c *C) { tk.MustExec("admin reload bindings;") res := tk.MustQuery("explain format = 'brief' select * from t;") - c.Assert(res.Rows()[0][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[1][0], Matches, ".*TableFullScan.*") + require.Regexp(t, ".*TableReader.*", res.Rows()[0][0]) + require.Regexp(t, ".*TableFullScan.*", res.Rows()[1][0]) tk.MustExec("prepare stmt from 'select * from t;';") tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tkProcess := tk.Se.ShowProcess() + tkProcess := tk.Session().ShowProcess() ps := []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) - c.Assert(res.Rows()[0][0], Matches, ".*TableReader.*") - c.Assert(res.Rows()[1][0], Matches, ".*TableFullScan.*") + require.Regexp(t, ".*TableReader.*", res.Rows()[0][0]) + require.Regexp(t, ".*TableFullScan.*", res.Rows()[1][0]) tk.MustExec("create global binding for select * from t using select * from t use index(idx_a);") res = tk.MustQuery("explain format = 'brief' select * from t;") - c.Assert(res.Rows()[0][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[1][0], Matches, ".*IndexFullScan.*") + require.Regexp(t, ".*IndexReader.*", res.Rows()[0][0]) + require.Regexp(t, ".*IndexFullScan.*", res.Rows()[1][0]) tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) tk.MustQuery("execute stmt;").Check(testkit.Rows()) // The bindSQL has changed, the previous cache is invalid. tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) tk.MustQuery("execute stmt;").Check(testkit.Rows()) - tkProcess = tk.Se.ShowProcess() + tkProcess = tk.Session().ShowProcess() ps = []*util.ProcessInfo{tkProcess} - tk.Se.SetSessionManager(&mockSessionManager1{PS: ps}) + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10)) // We can use the new binding. - c.Assert(res.Rows()[0][0], Matches, ".*IndexReader.*") - c.Assert(res.Rows()[1][0], Matches, ".*IndexFullScan.*") + require.Regexp(t, ".*IndexReader.*", res.Rows()[0][0]) + require.Regexp(t, ".*IndexFullScan.*", res.Rows()[1][0]) tk.MustQuery("execute stmt;").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute stmt;").Check(testkit.Rows()) @@ -1143,8 +1184,10 @@ func (s *testPrepareSerialSuite) TestSPM4PlanCache(c *C) { tk.MustExec("admin reload bindings;") } -func (s *testPrepareSerialSuite) TestHint4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestHint4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1152,11 +1195,11 @@ func (s *testPrepareSerialSuite) TestHint4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1174,8 +1217,10 @@ func (s *testPrepareSerialSuite) TestHint4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } -func (s *testPrepareSerialSuite) TestSelectView4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestSelectView4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1183,11 +1228,11 @@ func (s *testPrepareSerialSuite) TestSelectView4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1221,11 +1266,11 @@ func (s *testPrepareSerialSuite) TestSelectView4PlanCache(c *C) { tk.MustExec("drop table view_t;") tk.MustExec("create table view_t(c int,d int)") err = tk.ExecToErr("execute stmt1;") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + require.Equal(t, "[planner:1356]View 'test.view1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", err.Error()) err = tk.ExecToErr("execute stmt2") - c.Assert(err.Error(), Equals, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them") + require.Equal(t, "[planner:1356]View 'test.view2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", err.Error()) err = tk.ExecToErr("execute stmt3") - c.Assert(err.Error(), Equals, core.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error()) + require.Equal(t, core.ErrViewInvalid.GenWithStackByArgs("test", "view3").Error(), err.Error()) tk.MustExec("drop table view_t;") tk.MustExec("create table view_t(a int,b int,c int)") tk.MustExec("insert into view_t values(1,2,3)") @@ -1293,8 +1338,10 @@ func (s *testPrepareSerialSuite) TestSelectView4PlanCache(c *C) { tk.MustExec("drop view v;") } -func (s *testPrepareSerialSuite) TestInvisibleIndex4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInvisibleIndex4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1302,11 +1349,11 @@ func (s *testPrepareSerialSuite) TestInvisibleIndex4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1320,15 +1367,17 @@ func (s *testPrepareSerialSuite) TestInvisibleIndex4PlanCache(c *C) { tk.MustExec("ALTER TABLE t ALTER INDEX idx_c INVISIBLE;") err = tk.ExecToErr("select * from t use index(idx_c) where c1 > 1;") - c.Assert(err.Error(), Equals, "[planner:1176]Key 'idx_c' doesn't exist in table 't'") + require.Equal(t, "[planner:1176]Key 'idx_c' doesn't exist in table 't'", err.Error()) err = tk.ExecToErr("execute stmt;") - c.Assert(err.Error(), Equals, "[planner:1176]Key 'idx_c' doesn't exist in table 't'") + require.Equal(t, "[planner:1176]Key 'idx_c' doesn't exist in table 't'", err.Error()) } -func (s *testPrepareSerialSuite) TestCTE4PlanCache(c *C) { +func TestCTE4PlanCache(t *testing.T) { // CTE can not be cached, because part of it will be treated as a subquery. - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1336,11 +1385,11 @@ func (s *testPrepareSerialSuite) TestCTE4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1392,7 +1441,7 @@ func (s *testPrepareSerialSuite) TestCTE4PlanCache(c *C) { tk.MustExec("set @a=1, @b=2, @c=3, @d=4, @e=5, @f=0;") tk.MustQuery("execute stmt using @f, @a, @f").Check(testkit.Rows("1")) - tk.MustQuery("execute stmt using @a, @b, @a").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @a, @b, @a").Sort().Check(testkit.Rows("1", "2")) tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) tk.MustExec("prepare stmt from 'with recursive c(p) as (select ?), cte(a, b) as (select 1, 1 union select a+?, 1 from cte, c where a < ?) select * from cte order by 1, 2;';") @@ -1401,8 +1450,10 @@ func (s *testPrepareSerialSuite) TestCTE4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } -func (s *testPrepareSerialSuite) TestValidity4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestValidity4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1410,11 +1461,11 @@ func (s *testPrepareSerialSuite) TestValidity4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1441,13 +1492,15 @@ func (s *testPrepareSerialSuite) TestValidity4PlanCache(c *C) { tk.MustQuery("execute stmt;").Check(testkit.Rows("1")) tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) - tk.MustExec("use test") + tk.MustExec("use test") // still read plan_cache.t and can hit the cache tk.MustQuery("execute stmt;").Check(testkit.Rows("1")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) } -func (s *testPrepareSerialSuite) TestListPartition4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestListPartition4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1455,11 +1508,11 @@ func (s *testPrepareSerialSuite) TestListPartition4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1475,9 +1528,11 @@ func (s *testPrepareSerialSuite) TestListPartition4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } -func (s *testSerialSuite) TestMoreSessions4PlanCache(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk2 := testkit.NewTestKitWithInit(c, s.store) +func TestMoreSessions4PlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { @@ -1485,11 +1540,11 @@ func (s *testSerialSuite) TestMoreSessions4PlanCache(c *C) { }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("use test;") @@ -1501,14 +1556,14 @@ func (s *testSerialSuite) TestMoreSessions4PlanCache(c *C) { tk.MustQuery("execute stmt").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) - tk2.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk2.SetSession(se) tk2.MustExec("use test;") - err = tk2.ExecToErr("execute stmt;") - c.Assert(err.Error(), Equals, "[planner:8111]Prepared statement not found") + require.EqualError(t, tk2.ExecToErr("execute stmt;"), "[planner:8111]Prepared statement not found") tk2.MustExec("prepare stmt from 'select * from t;';") tk2.MustQuery("execute stmt").Check(testkit.Rows()) tk2.MustQuery("execute stmt").Check(testkit.Rows()) @@ -1518,12 +1573,14 @@ func (s *testSerialSuite) TestMoreSessions4PlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testSuite) TestIssue28792(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue28792(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("CREATE TABLE t12(a INT, b INT)") tk.MustExec("CREATE TABLE t97(a INT, b INT UNIQUE NOT NULL);") r1 := tk.MustQuery("EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 on t12.b = t97.b;").Rows() r2 := tk.MustQuery("EXPLAIN SELECT t12.a, t12.b FROM t12 LEFT JOIN t97 use index () on t12.b = t97.b;").Rows() - c.Assert(r1, DeepEquals, r2) + require.Equal(t, r2, r1) } diff --git a/executor/grant_test.go b/executor/grant_test.go index 240e9e5e41154..05d64b0d7b698 100644 --- a/executor/grant_test.go +++ b/executor/grant_test.go @@ -261,6 +261,17 @@ func TestCreateUserWhenGrant(t *testing.T) { tk.MustExec(`DROP USER IF EXISTS 'test'@'%'`) } +func TestCreateUserWithTooLongName(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + err := tk.ExecToErr("CREATE USER '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost'") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL' is too long for user name (should be no longer than 32)") + err = tk.ExecToErr("CREATE USER 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X'") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String 'host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345' is too long for host name (should be no longer than 255)") +} + func TestGrantPrivilegeAtomic(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/executor/hash_table.go b/executor/hash_table.go index b22f98bbef501..5476c5901e4f1 100644 --- a/executor/hash_table.go +++ b/executor/hash_table.go @@ -143,6 +143,7 @@ func (c *hashRowContainer) matchJoinKey(buildRow, probeRow chunk.Row, probeHCtx } // alreadySpilledSafeForTest indicates that records have spilled out into disk. It's thread-safe. +// nolint: unused func (c *hashRowContainer) alreadySpilledSafeForTest() bool { return c.rowContainer.AlreadySpilledSafeForTest() } diff --git a/executor/hot_regions_history_table_test.go b/executor/hot_regions_history_table_test.go new file mode 100644 index 0000000000000..6e5fc3981305c --- /dev/null +++ b/executor/hot_regions_history_table_test.go @@ -0,0 +1,525 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/pingcap/fn" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/pdapi" + "github.com/stretchr/testify/suite" +) + +type mockStoreWithMultiPD struct { + helper.Storage + hosts []string +} + +var hotRegionsResponses = make(map[string]*executor.HistoryHotRegions, 3) + +func (s *mockStoreWithMultiPD) EtcdAddrs() ([]string, error) { return s.hosts, nil } +func (s *mockStoreWithMultiPD) TLSConfig() *tls.Config { panic("not implemented") } +func (s *mockStoreWithMultiPD) StartGCWorker() error { panic("not implemented") } +func (s *mockStoreWithMultiPD) Name() string { return "mockStore" } +func (s *mockStoreWithMultiPD) Describe() string { return "" } + +type hotRegionsHistoryTableSuite struct { + suite.Suite + store kv.Storage + clean func() + httpServers []*httptest.Server + startTime time.Time +} + +func TestHotRegionsHistoryTable(t *testing.T) { + suite.Run(t, new(hotRegionsHistoryTableSuite)) +} + +func (s *hotRegionsHistoryTableSuite) SetupSuite() { + s.store, s.clean = testkit.CreateMockStore(s.T()) + store := &mockStoreWithMultiPD{ + s.store.(helper.Storage), + make([]string, 3), + } + // start 3 PD server with hotRegionsServer and store them in s.store + for i := 0; i < 3; i++ { + httpServer, mockAddr := s.setUpMockPDHTTPServer() + s.Require().NotNil(httpServer) + s.httpServers = append(s.httpServers, httpServer) + store.hosts[i] = mockAddr + } + s.store = store + s.startTime = time.Now() +} + +func writeResp(w http.ResponseWriter, resp interface{}) { + w.WriteHeader(http.StatusOK) + jsonResp, err := json.Marshal(resp) + if err != nil { + writeJSONError(w, http.StatusInternalServerError, "unable to marshal resp", err) + return + } + _, _ = w.Write(jsonResp) +} + +func writeJSONError(w http.ResponseWriter, code int, prefix string, err error) { + type errorResponse struct { + Error string `json:"error"` + } + w.WriteHeader(code) + if err != nil { + prefix += ": " + err.Error() + } + _ = json.NewEncoder(w).Encode(errorResponse{Error: prefix}) +} + +func hisHotRegionsHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + data, err := io.ReadAll(r.Body) + if err != nil { + writeJSONError(w, http.StatusInternalServerError, "unable to read req", err) + return + } + _ = r.Body.Close() + req := &executor.HistoryHotRegionsRequest{} + err = json.Unmarshal(data, req) + if err != nil { + writeJSONError(w, http.StatusInternalServerError, "unable to serialize req", err) + return + } + resp := &executor.HistoryHotRegions{} + for _, typ := range req.HotRegionTypes { + resp.HistoryHotRegion = append(resp.HistoryHotRegion, hotRegionsResponses[typ+r.Host].HistoryHotRegion...) + } + w.WriteHeader(http.StatusOK) + jsonResp, err := json.Marshal(resp) + if err != nil { + writeJSONError(w, http.StatusInternalServerError, "unable to marshal resp", err) + return + } + _, _ = w.Write(jsonResp) +} + +func (s *hotRegionsHistoryTableSuite) setUpMockPDHTTPServer() (*httptest.Server, string) { + // mock PD http server + router := mux.NewRouter() + server := httptest.NewServer(router) + mockAddr := strings.TrimPrefix(server.URL, "http://") + // mock PD API + router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { + return struct { + Version string `json:"version"` + GitHash string `json:"git_hash"` + StartTimestamp int64 `json:"start_timestamp"` + }{ + Version: "4.0.0-alpha", + GitHash: "mock-pd-githash", + StartTimestamp: s.startTime.Unix(), + }, nil + })) + // mock history hot regions response + router.HandleFunc(pdapi.HotHistory, hisHotRegionsHandler) + return server, mockAddr +} + +func (s *hotRegionsHistoryTableSuite) TearDownSuite() { + for _, server := range s.httpServers { + server.Close() + } + s.clean() +} + +func (s *hotRegionsHistoryTableSuite) TestTiDBHotRegionsHistory() { + var unixTimeMs = func(v string) int64 { + t, err := time.ParseInLocation("2006-01-02 15:04:05", v, time.Local) + s.Require().NoError(err) + return t.UnixNano() / int64(time.Millisecond) + } + + tk := testkit.NewTestKit(s.T(), s.store) + tablesPrivTid := external.GetTableByName(s.T(), tk, "mysql", "TABLES_PRIV").Meta().ID + tablesPrivTidStr := strconv.FormatInt(tablesPrivTid, 10) + statsMetaTid := external.GetTableByName(s.T(), tk, "mysql", "STATS_META").Meta().ID + statsMetaTidStr := strconv.FormatInt(statsMetaTid, 10) + + fullHotRegions := [][]string{ + // mysql table_id = 11, table_name = TABLES_PRIV + {"2019-10-10 10:10:11", "MYSQL", "TABLES_PRIV", tablesPrivTidStr, "", "", "1", "1", "11111", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:12", "MYSQL", "TABLES_PRIV", tablesPrivTidStr, "", "", "2", "2", "22222", "0", "0", "WRITE", "99", "99", "99", "99"}, + // mysql table_id = 21, table_name = STATS_META + {"2019-10-10 10:10:13", "MYSQL", "STATS_META", statsMetaTidStr, "", "", "3", "3", "33333", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:14", "MYSQL", "STATS_META", statsMetaTidStr, "", "", "4", "4", "44444", "0", "0", "WRITE", "99", "99", "99", "99"}, + // table_id = 1313, deleted schema + {"2019-10-10 10:10:15", "UNKNOWN", "UNKNOWN", "1313", "UNKNOWN", "", "5", "5", "55555", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:16", "UNKNOWN", "UNKNOWN", "1313", "UNKNOWN", "", "6", "6", "66666", "0", "0", "WRITE", "99", "99", "99", "99"}, + // mysql table_id = 11, index_id = 1, table_name = TABLES_PRIV, index_name = PRIMARY + {"2019-10-10 10:10:17", "MYSQL", "TABLES_PRIV", tablesPrivTidStr, "PRIMARY", "1", "1", "1", "11111", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:18", "MYSQL", "TABLES_PRIV", tablesPrivTidStr, "PRIMARY", "1", "2", "2", "22222", "0", "0", "WRITE", "99", "99", "99", "99"}, + // mysql table_id = 21 ,index_id = 1, table_name = STATS_META, index_name = IDX_VER + {"2019-10-10 10:10:19", "MYSQL", "STATS_META", statsMetaTidStr, "IDX_VER", "1", "3", "3", "33333", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:20", "MYSQL", "STATS_META", statsMetaTidStr, "IDX_VER", "1", "4", "4", "44444", "0", "0", "WRITE", "99", "99", "99", "99"}, + // mysql table_id = 21 ,index_id = 2, table_name = STATS_META, index_name = TBL + {"2019-10-10 10:10:21", "MYSQL", "STATS_META", statsMetaTidStr, "TBL", "2", "5", "5", "55555", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:22", "MYSQL", "STATS_META", statsMetaTidStr, "TBL", "2", "6", "6", "66666", "0", "0", "WRITE", "99", "99", "99", "99"}, + // table_id = 1313, index_id = 1, deleted schema + {"2019-10-10 10:10:23", "UNKNOWN", "UNKNOWN", "1313", "UNKNOWN", "1", "7", "7", "77777", "0", "1", "READ", "99", "99", "99", "99"}, + {"2019-10-10 10:10:24", "UNKNOWN", "UNKNOWN", "1313", "UNKNOWN", "1", "8", "8", "88888", "0", "0", "WRITE", "99", "99", "99", "99"}, + } + + mockDB := &model.DBInfo{} + pdResps := []map[string]*executor.HistoryHotRegions{ + { + core.HotRegionTypeRead: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // mysql table_id = 11, table_name = TABLES_PRIV + {UpdateTime: unixTimeMs("2019-10-10 10:10:11"), RegionID: 1, StoreID: 1, PeerID: 11111, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}).EndKey, + }, + // mysql table_id = 21, table_name = STATS_META + {UpdateTime: unixTimeMs("2019-10-10 10:10:13"), RegionID: 3, StoreID: 3, PeerID: 33333, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}).EndKey, + }, + }, + }, + core.HotRegionTypeWrite: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // mysql table_id = 11, table_name = TABLES_PRIV + {UpdateTime: unixTimeMs("2019-10-10 10:10:12"), RegionID: 2, StoreID: 2, PeerID: 22222, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}).EndKey, + }, + // mysql table_id = 21, table_name = STATS_META + {UpdateTime: unixTimeMs("2019-10-10 10:10:14"), RegionID: 4, StoreID: 4, PeerID: 44444, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}).EndKey, + }, + }, + }, + }, + { + core.HotRegionTypeRead: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // table_id = 1313, deleted schema + {UpdateTime: unixTimeMs("2019-10-10 10:10:15"), RegionID: 5, StoreID: 5, PeerID: 55555, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: 1313}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: 1313}).EndKey, + }, + // mysql table_id = 11, index_id = 1, table_name = TABLES_PRIV, index_name = PRIMARY + {UpdateTime: unixTimeMs("2019-10-10 10:10:17"), RegionID: 1, StoreID: 1, PeerID: 11111, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}, &model.IndexInfo{ID: 1}).EndKey, + }, + }, + }, + core.HotRegionTypeWrite: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // table_id = 1313, deleted schema + {UpdateTime: unixTimeMs("2019-10-10 10:10:16"), RegionID: 6, StoreID: 6, PeerID: 66666, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: 1313}).StartKey, + EndKey: helper.NewTableWithKeyRange(mockDB, &model.TableInfo{ID: 1313}).EndKey, + }, + // mysql table_id = 11, index_id = 1, table_name = TABLES_PRIV, index_name = PRIMARY + {UpdateTime: unixTimeMs("2019-10-10 10:10:18"), RegionID: 2, StoreID: 2, PeerID: 22222, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: tablesPrivTid}, &model.IndexInfo{ID: 1}).EndKey, + }, + }, + }, + }, + { + core.HotRegionTypeRead: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // mysql table_id = 21 ,index_id = 1, table_name = STATS_META, index_name = IDX_VER + {UpdateTime: unixTimeMs("2019-10-10 10:10:19"), RegionID: 3, StoreID: 3, PeerID: 33333, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 1}).EndKey, + }, + // mysql table_id = 21 ,index_id = 2, table_name = STATS_META, index_name = TBL + {UpdateTime: unixTimeMs("2019-10-10 10:10:21"), RegionID: 5, StoreID: 5, PeerID: 55555, IsLearner: false, + IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 2}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 2}).EndKey, + }, + // table_id = 1313, index_id = 1, deleted schema + {UpdateTime: unixTimeMs("2019-10-10 10:10:23"), RegionID: 7, StoreID: 7, PeerID: 77777, IsLeader: true, + HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: 1313}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: 1313}, &model.IndexInfo{ID: 1}).EndKey, + }, + }, + }, + core.HotRegionTypeWrite: { + HistoryHotRegion: []*executor.HistoryHotRegion{ + // mysql table_id = 21 ,index_id = 1, table_name = STATS_META, index_name = IDX_VER + {UpdateTime: unixTimeMs("2019-10-10 10:10:20"), RegionID: 4, StoreID: 4, PeerID: 44444, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 1}).EndKey, + }, + // mysql table_id = 21 ,index_id = 2, table_name = STATS_META, index_name = TBL + {UpdateTime: unixTimeMs("2019-10-10 10:10:22"), RegionID: 6, StoreID: 6, PeerID: 66666, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 2}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: statsMetaTid}, &model.IndexInfo{ID: 2}).EndKey, + }, + // table_id = 1313, index_id = 1, deleted schema + {UpdateTime: unixTimeMs("2019-10-10 10:10:24"), RegionID: 8, StoreID: 8, PeerID: 88888, IsLearner: false, + IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, + StartKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: 1313}, &model.IndexInfo{ID: 1}).StartKey, + EndKey: helper.NewIndexWithKeyRange(mockDB, &model.TableInfo{ID: 1313}, &model.IndexInfo{ID: 1}).EndKey, + }, + }, + }, + }, + } + + var cases = []struct { + conditions []string + reqCount int32 + expected [][]string + }{ + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + }, // time filtered by PD, assume response suit time range, and ignore deleted schemas + expected: [][]string{ + fullHotRegions[0], fullHotRegions[1], fullHotRegions[2], + fullHotRegions[3], + fullHotRegions[6], fullHotRegions[7], fullHotRegions[8], + fullHotRegions[9], fullHotRegions[10], fullHotRegions[11], + }, + }, + { + conditions: []string{ + "update_time>=TIMESTAMP('2019-10-10 10:10:10')", + "update_time<=TIMESTAMP('2019-10-11 10:10:10')", + }, // test support of timestamp + expected: [][]string{ + fullHotRegions[0], fullHotRegions[1], fullHotRegions[2], + fullHotRegions[3], + fullHotRegions[6], fullHotRegions[7], fullHotRegions[8], + fullHotRegions[9], fullHotRegions[10], fullHotRegions[11], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + tablesPrivTidStr, + }, + expected: [][]string{ + fullHotRegions[0], fullHotRegions[1], fullHotRegions[6], fullHotRegions[7], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_name='TABLES_PRIV'", + }, + expected: [][]string{ + fullHotRegions[0], fullHotRegions[1], fullHotRegions[6], fullHotRegions[7], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + statsMetaTidStr, + "index_id=1", + }, + expected: [][]string{ + fullHotRegions[8], fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + statsMetaTidStr, + "index_id=1", + "table_name='TABLES_PRIV'", + }, // table_id != table_name -> nil + expected: [][]string{}, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + statsMetaTidStr, + "index_id=1", + "table_name='STATS_META'", + }, // table_id = table_name + expected: [][]string{ + fullHotRegions[8], fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + statsMetaTidStr, + "index_id=1", + "index_name='UNKNOWN'", + }, // index_id != index_name -> nil + expected: [][]string{}, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "table_id=" + statsMetaTidStr, + "index_id=1", + "index_name='IDX_VER'", + }, // index_id = index_name + expected: [][]string{ + fullHotRegions[8], fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "index_id=1", + "index_name='IDX_VER'", + "table_id>=" + statsMetaTidStr, // unpushed down predicates 21>=21 + }, + expected: [][]string{ + fullHotRegions[8], fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "index_id=1", + "index_name='IDX_VER'", + "table_id>" + statsMetaTidStr, // unpushed down predicates + }, // 21!>21 -> nil + expected: [][]string{}, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "index_id=1", + "index_name='IDX_VER'", + "table_id>=" + statsMetaTidStr, // unpushed down predicates + "db_name='MYSQL'", + }, + expected: [][]string{ + fullHotRegions[8], fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "index_id=1", + "index_name='IDX_VER'", + "table_id>=" + statsMetaTidStr, // unpushed down predicates + "db_name='MYSQL'", + "peer_id>=33334", + }, + expected: [][]string{ + fullHotRegions[9], + }, + }, + { + conditions: []string{ + "update_time>='2019-10-10 10:10:10'", + "update_time<='2019-10-11 10:10:10'", + "index_id=1", + "index_name='IDX_VER'", + "table_id>=" + statsMetaTidStr, // unpushed down predicates + "db_name='UNKNOWN'", + }, + expected: [][]string{}, + }, + } + + // mock http resp + store := s.store.(*mockStoreWithMultiPD) + for i, resp := range pdResps { + for k, v := range resp { + hotRegionsResponses[k+store.hosts[i]] = v + } + } + + for _, cas := range cases { + sql := "select * from information_schema.tidb_hot_regions_history" + if len(cas.conditions) > 0 { + sql = fmt.Sprintf("%s where %s", sql, strings.Join(cas.conditions, " and ")) + } + result := tk.MustQuery(sql) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + s.Require().Lenf(warnings, 0, "unexpected warnings: %+v, sql: %s", warnings, sql) + var expected []string + for _, row := range cas.expected { + expectedRow := row + expected = append(expected, strings.Join(expectedRow, " ")) + } + result.Check(testkit.Rows(expected...)) + } +} + +func (s *hotRegionsHistoryTableSuite) TestTiDBHotRegionsHistoryError() { + tk := testkit.NewTestKit(s.T(), s.store) + + // Test without start time error + rs, err := tk.Exec("select * from information_schema.tidb_hot_regions_history") + s.Require().NoError(err) + _, err = session.ResultSetToStringSlice(context.Background(), tk.Session(), rs) + s.Require().EqualError(err, "denied to scan hot regions, please specified the start time, such as `update_time > '2020-01-01 00:00:00'`") + s.NoError(rs.Close()) + + // Test without end time error. + rs, err = tk.Exec("select * from information_schema.tidb_hot_regions_history where update_time>='2019/08/26 06:18:13.011'") + s.Require().NoError(err) + _, err = session.ResultSetToStringSlice(context.Background(), tk.Session(), rs) + s.Require().EqualError(err, "denied to scan hot regions, please specified the end time, such as `update_time < '2020-01-01 00:00:00'`") + s.NoError(rs.Close()) +} diff --git a/executor/index_lookup_hash_join.go b/executor/index_lookup_hash_join.go index 0beb3e59e66b1..51f21c2491e77 100644 --- a/executor/index_lookup_hash_join.go +++ b/executor/index_lookup_hash_join.go @@ -70,7 +70,8 @@ type IndexNestedLoopHashJoin struct { // taskCh is only used when `keepOuterOrder` is true. taskCh chan *indexHashJoinTask - stats *indexLookUpJoinRuntimeStats + stats *indexLookUpJoinRuntimeStats + prepared bool } type indexHashJoinOuterWorker struct { @@ -120,29 +121,7 @@ type indexHashJoinTask struct { // Open implements the IndexNestedLoopHashJoin Executor interface. func (e *IndexNestedLoopHashJoin) Open(ctx context.Context) error { - // Be careful, very dirty hack in this line!!! - // IndexLookUpJoin need to rebuild executor (the dataReaderBuilder) during - // executing. However `executor.Next()` is lazy evaluation when the RecordSet - // result is drained. - // Lazy evaluation means the saved session context may change during executor's - // building and its running. - // A specific sequence for example: - // - // e := buildExecutor() // txn at build time - // recordSet := runStmt(e) - // session.CommitTxn() // txn closed - // recordSet.Next() - // e.dataReaderBuilder.Build() // txn is used again, which is already closed - // - // The trick here is `getSnapshotTS` will cache snapshot ts in the dataReaderBuilder, - // so even txn is destroyed later, the dataReaderBuilder could still use the - // cached snapshot ts to construct DAG. - _, err := e.innerCtx.readerBuilder.getSnapshotTS() - if err != nil { - return err - } - - err = e.children[0].Open(ctx) + err := e.children[0].Open(ctx) if err != nil { return err } @@ -155,7 +134,6 @@ func (e *IndexNestedLoopHashJoin) Open(ctx context.Context) error { e.ctx.GetSessionVars().StmtCtx.RuntimeStatsColl.RegisterStats(e.id, e.stats) } e.finished.Store(false) - e.startWorkers(ctx) return nil } @@ -211,7 +189,6 @@ func (e *IndexNestedLoopHashJoin) finishJoinWorkers(r interface{}) { e.taskCh <- task } if e.cancelFunc != nil { - e.IndexLookUpJoin.ctxCancelReason.Store(err) e.cancelFunc() } } @@ -230,6 +207,10 @@ func (e *IndexNestedLoopHashJoin) wait4JoinWorkers() { // Next implements the IndexNestedLoopHashJoin Executor interface. func (e *IndexNestedLoopHashJoin) Next(ctx context.Context, req *chunk.Chunk) error { + if !e.prepared { + e.startWorkers(ctx) + e.prepared = true + } req.Reset() if e.keepOuterOrder { return e.runInOrder(ctx, req) @@ -248,9 +229,6 @@ func (e *IndexNestedLoopHashJoin) Next(ctx context.Context, req *chunk.Chunk) er return result.err } case <-ctx.Done(): - if err := e.IndexLookUpJoin.ctxCancelReason.Load(); err != nil { - return err.(error) - } return ctx.Err() } req.SwapColumns(result.chk) @@ -280,9 +258,6 @@ func (e *IndexNestedLoopHashJoin) runInOrder(ctx context.Context, req *chunk.Chu return result.err } case <-ctx.Done(): - if err := e.IndexLookUpJoin.ctxCancelReason.Load(); err != nil { - return err.(error) - } return ctx.Err() } req.SwapColumns(result.chk) @@ -328,6 +303,7 @@ func (e *IndexNestedLoopHashJoin) Close() error { } e.joinChkResourceCh = nil e.finished.Store(false) + e.prepared = false return e.baseExecutor.Close() } @@ -343,7 +319,10 @@ func (ow *indexHashJoinOuterWorker) run(ctx context.Context) { if err != nil { task = &indexHashJoinTask{err: err} if ow.keepOuterOrder { - task.keepOuterOrder, task.resultCh = true, make(chan *indexHashJoinResult, 1) + // The outerBuilder and innerFetcher run concurrently, we may + // get 2 errors at simultaneously. Thus the capacity of task.resultCh + // needs to be initialized to 2 to avoid waiting. + task.keepOuterOrder, task.resultCh = true, make(chan *indexHashJoinResult, 2) ow.pushToChan(ctx, task, ow.taskCh) } ow.pushToChan(ctx, task, ow.innerCh) @@ -502,7 +481,9 @@ func (iw *indexHashJoinInnerWorker) run(ctx context.Context, cancelFunc context. break } err := iw.handleTask(ctx, task, joinResult, h, resultCh) - if err != nil { + if err != nil && !task.keepOuterOrder { + // Only need check non-keep-outer-order case because the + // `joinResult` had been sent to the `resultCh` when err != nil. joinResult.err = err break } @@ -520,19 +501,26 @@ func (iw *indexHashJoinInnerWorker) run(ctx context.Context, cancelFunc context. failpoint.Inject("testIndexHashJoinInnerWorkerErr", func() { joinResult.err = errors.New("mockIndexHashJoinInnerWorkerErr") }) - if joinResult.err != nil { - resultCh <- joinResult - return - } - // When task.keepOuterOrder is TRUE(resultCh != iw.resultCh), the last - // joinResult will be checked when the a task has been processed, thus we do - // not need to check it here again. - if resultCh == iw.resultCh && joinResult.chk != nil && joinResult.chk.NumRows() > 0 { - select { - case resultCh <- joinResult: - case <-ctx.Done(): + // When task.keepOuterOrder is TRUE (resultCh != iw.resultCh): + // - the last joinResult will be handled when the task has been processed, + // thus we DO NOT need to check it here again. + // - we DO NOT check the error here neither, because: + // - if the error is from task.err, the main thread will check the error of each task + // - if the error is from handleTask, the error will be handled in handleTask + // We should not check `task != nil && !task.keepOuterOrder` here since it's + // possible that `join.chk.NumRows > 0` is true even if task == nil. + if resultCh == iw.resultCh { + if joinResult.err != nil { + resultCh <- joinResult return } + if joinResult.chk != nil && joinResult.chk.NumRows() > 0 { + select { + case resultCh <- joinResult: + case <-ctx.Done(): + return + } + } } } @@ -544,12 +532,13 @@ func (iw *indexHashJoinInnerWorker) getNewJoinResult(ctx context.Context) (*inde select { case joinResult.chk, ok = <-iw.joinChkResourceCh: case <-ctx.Done(): - return nil, false + return joinResult, false } return joinResult, ok } func (iw *indexHashJoinInnerWorker) buildHashTableForOuterResult(ctx context.Context, task *indexHashJoinTask, h hash.Hash64) { + failpoint.Inject("IndexHashJoinBuildHashTablePanic", nil) if iw.stats != nil { start := time.Now() defer func() { @@ -561,6 +550,9 @@ func (iw *indexHashJoinInnerWorker) buildHashTableForOuterResult(ctx context.Con for chkIdx := 0; chkIdx < numChks; chkIdx++ { chk := task.outerResult.GetChunk(chkIdx) numRows := chk.NumRows() + if iw.lookup.finished.Load().(bool) { + return + } OUTER: for rowIdx := 0; rowIdx < numRows; rowIdx++ { if task.outerMatch != nil && !task.outerMatch[chkIdx][rowIdx] { @@ -596,16 +588,26 @@ func (iw *indexHashJoinInnerWorker) fetchInnerResults(ctx context.Context, task return iw.innerWorker.fetchInnerResults(ctx, task, lookUpContents) } -func (iw *indexHashJoinInnerWorker) handleHashJoinInnerWorkerPanic(r interface{}) { - if r != nil { - iw.resultCh <- &indexHashJoinResult{err: errors.Errorf("%v", r)} +func (iw *indexHashJoinInnerWorker) handleHashJoinInnerWorkerPanic(resultCh chan *indexHashJoinResult, err error) { + defer func() { + iw.wg.Done() + iw.lookup.workerWg.Done() + }() + if err != nil { + resultCh <- &indexHashJoinResult{err: err} } - iw.wg.Done() } -func (iw *indexHashJoinInnerWorker) handleTask(ctx context.Context, task *indexHashJoinTask, joinResult *indexHashJoinResult, h hash.Hash64, resultCh chan *indexHashJoinResult) error { +func (iw *indexHashJoinInnerWorker) handleTask(ctx context.Context, task *indexHashJoinTask, joinResult *indexHashJoinResult, h hash.Hash64, resultCh chan *indexHashJoinResult) (err error) { defer func() { iw.memTracker.Consume(-iw.memTracker.BytesConsumed()) + if task.keepOuterOrder { + if err != nil { + joinResult.err = err + resultCh <- joinResult + } + close(resultCh) + } }() var joinStartTime time.Time if iw.stats != nil { @@ -620,9 +622,26 @@ func (iw *indexHashJoinInnerWorker) handleTask(ctx context.Context, task *indexH iw.wg = &sync.WaitGroup{} iw.wg.Add(1) // TODO(XuHuaiyu): we may always use the smaller side to build the hashtable. - go util.WithRecovery(func() { iw.buildHashTableForOuterResult(ctx, task, h) }, iw.handleHashJoinInnerWorkerPanic) - err := iw.fetchInnerResults(ctx, task.lookUpJoinTask) + go util.WithRecovery( + func() { + iw.lookup.workerWg.Add(1) + iw.buildHashTableForOuterResult(ctx, task, h) + }, + func(r interface{}) { + var err error + if r != nil { + err = errors.Errorf("%v", r) + } + iw.handleHashJoinInnerWorkerPanic(resultCh, err) + }, + ) + err = iw.fetchInnerResults(ctx, task.lookUpJoinTask) iw.wg.Wait() + // check error after wg.Wait to make sure error message can be sent to + // resultCh even if panic happen in buildHashTableForOuterResult. + failpoint.Inject("IndexHashJoinFetchInnerResultsErr", func() { + err = errors.New("IndexHashJoinFetchInnerResultsErr") + }) if err != nil { return err } @@ -640,7 +659,7 @@ func (iw *indexHashJoinInnerWorker) doJoinUnordered(ctx context.Context, task *i for row := iter.Begin(); row != iter.End(); row = iter.Next() { ok, joinResult = iw.joinMatchedInnerRow2Chunk(ctx, row, task, joinResult, h, iw.joinKeyBuf) if !ok { - return errors.New("indexHashJoinInnerWorker.doJoinUnordered failed") + return joinResult.err } } for chkIdx, outerRowStatus := range task.outerRowStatus { @@ -654,9 +673,6 @@ func (iw *indexHashJoinInnerWorker) doJoinUnordered(ctx context.Context, task *i select { case resultCh <- joinResult: case <-ctx.Done(): - if err := iw.lookup.ctxCancelReason.Load(); err != nil { - return err.(error) - } return ctx.Err() } joinResult, ok = iw.getNewJoinResult(ctx) @@ -772,13 +788,15 @@ func (iw *indexHashJoinInnerWorker) doJoinInOrder(ctx context.Context, task *ind joinResult.src <- joinResult.chk } } - close(resultCh) }() for i, numChunks := 0, task.innerResult.NumChunks(); i < numChunks; i++ { for j, chk := 0, task.innerResult.GetChunk(i); j < chk.NumRows(); j++ { row := chk.GetRow(j) ptr := chunk.RowPtr{ChkIdx: uint32(i), RowIdx: uint32(j)} err = iw.collectMatchedInnerPtrs4OuterRows(ctx, row, ptr, task, h, iw.joinKeyBuf) + failpoint.Inject("TestIssue31129", func() { + err = errors.New("TestIssue31129") + }) if err != nil { return err } @@ -805,9 +823,6 @@ func (iw *indexHashJoinInnerWorker) doJoinInOrder(ctx context.Context, task *ind select { case resultCh <- joinResult: case <-ctx.Done(): - if err := iw.lookup.ctxCancelReason.Load(); err != nil { - return err.(error) - } return ctx.Err() } joinResult, ok = iw.getNewJoinResult(ctx) diff --git a/executor/index_lookup_join.go b/executor/index_lookup_join.go index 4be2f24272ae4..994385566dde3 100644 --- a/executor/index_lookup_join.go +++ b/executor/index_lookup_join.go @@ -84,9 +84,9 @@ type IndexLookUpJoin struct { memTracker *memory.Tracker // track memory usage. - stats *indexLookUpJoinRuntimeStats - ctxCancelReason atomic.Value - finished *atomic.Value + stats *indexLookUpJoinRuntimeStats + finished *atomic.Value + prepared bool } type outerCtx struct { @@ -175,7 +175,6 @@ func (e *IndexLookUpJoin) Open(ctx context.Context) error { e.ctx.GetSessionVars().StmtCtx.RuntimeStatsColl.RegisterStats(e.id, e.stats) } e.cancelFunc = nil - e.startWorkers(ctx) return nil } @@ -259,6 +258,10 @@ func (e *IndexLookUpJoin) newInnerWorker(taskCh chan *lookUpJoinTask) *innerWork // Next implements the Executor interface. func (e *IndexLookUpJoin) Next(ctx context.Context, req *chunk.Chunk) error { + if !e.prepared { + e.startWorkers(ctx) + e.prepared = true + } if e.isOuterJoin { atomic.StoreInt64(&e.requiredRows, int64(req.RequiredRows())) } @@ -318,9 +321,6 @@ func (e *IndexLookUpJoin) getFinishedTask(ctx context.Context) (*lookUpJoinTask, select { case task = <-e.resultCh: case <-ctx.Done(): - if err := e.ctxCancelReason.Load(); err != nil { - return nil, err.(error) - } return nil, ctx.Err() } if task == nil { @@ -333,9 +333,6 @@ func (e *IndexLookUpJoin) getFinishedTask(ctx context.Context) (*lookUpJoinTask, return nil, err } case <-ctx.Done(): - if err := e.ctxCancelReason.Load(); err != nil { - return nil, err.(error) - } return nil, ctx.Err() } @@ -368,8 +365,6 @@ func (ow *outerWorker) run(ctx context.Context, wg *sync.WaitGroup) { err := errors.Errorf("%v", r) task.doneCh <- err ow.pushToChan(ctx, task, ow.resultCh) - ow.lookup.ctxCancelReason.Store(err) - ow.lookup.cancelFunc() } close(ow.resultCh) close(ow.innerCh) @@ -489,8 +484,6 @@ func (iw *innerWorker) run(ctx context.Context, wg *sync.WaitGroup) { err := errors.Errorf("%v", r) // "task != nil" is guaranteed when panic happened. task.doneCh <- err - iw.lookup.ctxCancelReason.Store(err) - iw.lookup.cancelFunc() } wg.Done() }() @@ -706,9 +699,6 @@ func (iw *innerWorker) fetchInnerResults(ctx context.Context, task *lookUpJoinTa for { select { case <-ctx.Done(): - if err := iw.lookup.ctxCancelReason.Load(); err != nil { - return err.(error) - } return ctx.Err() default: } @@ -778,6 +768,7 @@ func (e *IndexLookUpJoin) Close() error { e.memTracker = nil e.task = nil e.finished.Store(false) + e.prepared = false return e.baseExecutor.Close() } diff --git a/executor/index_lookup_join_test.go b/executor/index_lookup_join_test.go index 262190dd1ac81..73c85d521db03 100644 --- a/executor/index_lookup_join_test.go +++ b/executor/index_lookup_join_test.go @@ -22,7 +22,6 @@ import ( "testing" "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/util/israce" "github.com/stretchr/testify/require" ) @@ -471,9 +470,6 @@ func TestIssue27893(t *testing.T) { } func TestPartitionTableIndexJoinAndIndexReader(t *testing.T) { - if israce.RaceEnabled { - t.Skip("exhaustive types test, skip race test") - } store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/executor/index_lookup_merge_join.go b/executor/index_lookup_merge_join.go index 7e4ac6a515ae9..d0ff14924e90a 100644 --- a/executor/index_lookup_merge_join.go +++ b/executor/index_lookup_merge_join.go @@ -73,6 +73,7 @@ type IndexLookUpMergeJoin struct { lastColHelper *plannercore.ColWithCmpFuncManager memTracker *memory.Tracker // track memory usage + prepared bool } type outerMergeCtx struct { @@ -156,35 +157,12 @@ type indexMergeJoinResult struct { // Open implements the Executor interface func (e *IndexLookUpMergeJoin) Open(ctx context.Context) error { - // Be careful, very dirty hack in this line!!! - // IndexLookMergeUpJoin need to rebuild executor (the dataReaderBuilder) during - // executing. However `executor.Next()` is lazy evaluation when the RecordSet - // result is drained. - // Lazy evaluation means the saved session context may change during executor's - // building and its running. - // A specific sequence for example: - // - // e := buildExecutor() // txn at build time - // recordSet := runStmt(e) - // session.CommitTxn() // txn closed - // recordSet.Next() - // e.dataReaderBuilder.Build() // txn is used again, which is already closed - // - // The trick here is `getSnapshotTS` will cache snapshot ts in the dataReaderBuilder, - // so even txn is destroyed later, the dataReaderBuilder could still use the - // cached snapshot ts to construct DAG. - _, err := e.innerMergeCtx.readerBuilder.getSnapshotTS() - if err != nil { - return err - } - - err = e.children[0].Open(ctx) + err := e.children[0].Open(ctx) if err != nil { return err } e.memTracker = memory.NewTracker(e.id, -1) e.memTracker.AttachTo(e.ctx.GetSessionVars().StmtCtx.MemTracker) - e.startWorkers(ctx) return nil } @@ -271,6 +249,10 @@ func (e *IndexLookUpMergeJoin) newInnerMergeWorker(taskCh chan *lookUpMergeJoinT // Next implements the Executor interface func (e *IndexLookUpMergeJoin) Next(ctx context.Context, req *chunk.Chunk) error { + if !e.prepared { + e.startWorkers(ctx) + e.prepared = true + } if e.isOuterJoin { atomic.StoreInt64(&e.requiredRows, int64(req.RequiredRows())) } @@ -753,5 +735,6 @@ func (e *IndexLookUpMergeJoin) Close() error { // cancelFunc control the outer worker and outer worker close the task channel. e.workerWg.Wait() e.memTracker = nil + e.prepared = false return e.baseExecutor.Close() } diff --git a/executor/index_lookup_merge_join_test.go b/executor/index_lookup_merge_join_test.go index 16b74c00d39b4..44bdf29cb8598 100644 --- a/executor/index_lookup_merge_join_test.go +++ b/executor/index_lookup_merge_join_test.go @@ -16,21 +16,25 @@ package executor_test import ( "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/plancodec" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSerialSuite) TestIndexLookupMergeJoinHang(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/IndexMergeJoinMockOOM", `return(true)`), IsNil) +func TestIndexLookupMergeJoinHang(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/IndexMergeJoinMockOOM", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/IndexMergeJoinMockOOM"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/IndexMergeJoinMockOOM")) }() - - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 (a int,b int,index idx(a))") tk.MustExec("create table t2 (a int,b int,index idx(a))") @@ -38,12 +42,14 @@ func (s *testSerialSuite) TestIndexLookupMergeJoinHang(c *C) { tk.MustExec("insert into t2 values (1,1),(2,2),(3,3),(2000,2000)") // Do not hang in index merge join when OOM occurs. err := tk.QueryToErr("select /*+ INL_MERGE_JOIN(t1, t2) */ * from t1, t2 where t1.a = t2.a") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "OOM test index merge join doesn't hang here.") + require.Error(t, err) + require.Equal(t, "OOM test index merge join doesn't hang here.", err.Error()) } -func (s *testSerialSuite) TestIssue28052(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue28052(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -58,13 +64,15 @@ func (s *testSerialSuite) TestIssue28052(c *C) { tk.MustQuery("select /*+ inl_merge_join(t1, t2) */ count(*) from t t1 right join t t2 on t1. `col_year_key_signed` = t2. `col_tinyint_key_signed`").Check(testkit.Rows("1")) } -func (s *testSerialSuite) TestIssue18068(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testIssue18068", `return(true)`), IsNil) +func TestIssue18068(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testIssue18068", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testIssue18068"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testIssue18068")) }() - - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t, s") tk.MustExec("create table t (a int, index idx(a))") tk.MustExec("create table s (a int, index idx(a))") @@ -81,23 +89,29 @@ func (s *testSerialSuite) TestIssue18068(c *C) { tk.MustExec("select /*+ inl_merge_join(s)*/ 1 from t join s on t.a = s.a limit 1") } -func (s *testSuite9) TestIssue18631(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue18631(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, c int, d int, primary key(a,b,c))") tk.MustExec("create table t2(a int, b int, c int, d int, primary key(a,b,c))") tk.MustExec("insert into t1 values(1,1,1,1),(2,2,2,2),(3,3,3,3)") tk.MustExec("insert into t2 values(1,1,1,1),(2,2,2,2)") firstOperator := tk.MustQuery("explain format = 'brief' select /*+ inl_merge_join(t1,t2) */ * from t1 left join t2 on t1.a = t2.a and t1.c = t2.c and t1.b = t2.b order by t1.a desc").Rows()[0][0].(string) - c.Assert(strings.Index(firstOperator, plancodec.TypeIndexMergeJoin), Equals, 0) + require.Equal(t, 0, strings.Index(firstOperator, plancodec.TypeIndexMergeJoin)) tk.MustQuery("select /*+ inl_merge_join(t1,t2) */ * from t1 left join t2 on t1.a = t2.a and t1.c = t2.c and t1.b = t2.b order by t1.a desc").Check(testkit.Rows( "3 3 3 3 ", "2 2 2 2 2 2 2 2", "1 1 1 1 1 1 1 1")) } -func (s *testSuite9) TestIssue19408(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue19408(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 (c_int int, primary key(c_int))") tk.MustExec("create table t2 (c_int int, unique key (c_int)) partition by hash (c_int) partitions 4") @@ -123,8 +137,11 @@ func (s *testSuite9) TestIssue19408(c *C) { tk.MustExec("commit") } -func (s *testSuite9) TestIssue20137(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20137(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 (id bigint(20) unsigned, primary key(id))") tk.MustExec("create table t2 (id bigint(20) unsigned)") @@ -136,9 +153,12 @@ func (s *testSuite9) TestIssue20137(c *C) { testkit.Rows("8738875760185212610 8738875760185212610", "9814441339970117597 9814441339970117597")) } -func (s *testSuiteWithData) TestIndexJoinOnSinglePartitionTable(c *C) { +func TestIndexJoinOnSinglePartitionTable(t *testing.T) { // For issue 19145 - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") for _, val := range []string{string(variable.Static), string(variable.Dynamic)} { tk.MustExec("set @@tidb_partition_prune_mode= '" + val + "'") tk.MustExec("drop table if exists t1, t2") @@ -148,25 +168,28 @@ func (s *testSuiteWithData) TestIndexJoinOnSinglePartitionTable(c *C) { tk.MustExec("insert into t2 values (1, 'Bob')") sql := "select /*+ INL_MERGE_JOIN(t1,t2) */ * from t1 join t2 partition(p0) on t1.c_int = t2.c_int and t1.c_str < t2.c_str" tk.MustQuery(sql).Check(testkit.Rows("1 Alice 1 Bob")) - rows := s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) + rows := testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) // Partition table can't be inner side of index merge join, because it can't keep order. - c.Assert(strings.Index(rows[0], "IndexMergeJoin"), Equals, -1) - c.Assert(len(tk.MustQuery("show warnings").Rows()) > 0, Equals, true) + require.Equal(t, -1, strings.Index(rows[0], "IndexMergeJoin")) + require.Equal(t, true, len(tk.MustQuery("show warnings").Rows()) > 0) sql = "select /*+ INL_HASH_JOIN(t1,t2) */ * from t1 join t2 partition(p0) on t1.c_int = t2.c_int and t1.c_str < t2.c_str" tk.MustQuery(sql).Check(testkit.Rows("1 Alice 1 Bob")) - rows = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) - c.Assert(strings.Index(rows[0], "IndexHashJoin"), Equals, 0) + rows = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) + require.Equal(t, 0, strings.Index(rows[0], "IndexHashJoin")) sql = "select /*+ INL_JOIN(t1,t2) */ * from t1 join t2 partition(p0) on t1.c_int = t2.c_int and t1.c_str < t2.c_str" tk.MustQuery(sql).Check(testkit.Rows("1 Alice 1 Bob")) - rows = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) - c.Assert(strings.Index(rows[0], "IndexJoin"), Equals, 0) + rows = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + sql).Rows()) + require.Equal(t, 0, strings.Index(rows[0], "IndexJoin")) } } -func (s *testSuite9) TestIssue20400(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20400(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t, s") tk.MustExec("create table s(a int, index(a))") tk.MustExec("create table t(a int)") @@ -177,8 +200,11 @@ func (s *testSuite9) TestIssue20400(c *C) { testkit.Rows("1 ")) } -func (s *testSuite9) TestIssue20549(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20549(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("CREATE TABLE `t1` (`id` bigint(20) NOT NULL AUTO_INCREMENT, `t2id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), KEY `t2id` (`t2id`));") tk.MustExec("INSERT INTO `t1` VALUES (1,NULL);") @@ -189,8 +215,11 @@ func (s *testSuite9) TestIssue20549(c *C) { testkit.Rows("1")) } -func (s *testSuite9) TestIssue24473AndIssue25669(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue24473AndIssue25669(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists x, t2, t3") tk.MustExec("CREATE TABLE `x` ( `a` enum('y','b','1','x','0','null') DEFAULT NULL, KEY `a` (`a`));") tk.MustExec("insert into x values(\"x\"),(\"x\"),(\"b\"),(\"y\");") diff --git a/executor/index_merge_reader.go b/executor/index_merge_reader.go index cd27a5049b8b5..66dde5b0e743a 100644 --- a/executor/index_merge_reader.go +++ b/executor/index_merge_reader.go @@ -110,12 +110,28 @@ type IndexMergeReaderExecutor struct { handleCols plannercore.HandleCols stats *IndexMergeRuntimeStat + + // Indicates whether there is correlated column in filter or table/index range. + // We need to refresh dagPBs before send DAGReq to storage. + isCorColInPartialFilters []bool + isCorColInTableFilter bool + isCorColInPartialAccess []bool +} + +// Table implements the dataSourceExecutor interface. +func (e *IndexMergeReaderExecutor) Table() table.Table { + return e.table } // Open implements the Executor Open interface func (e *IndexMergeReaderExecutor) Open(ctx context.Context) (err error) { e.keyRanges = make([][]kv.KeyRange, 0, len(e.partialPlans)) e.initRuntimeStats() + + if err = e.rebuildRangeForCorCol(); err != nil { + return err + } + if !e.partitionTableMode { if e.keyRanges, err = e.buildKeyRangesForTable(e.table); err != nil { return err @@ -138,22 +154,49 @@ func (e *IndexMergeReaderExecutor) Open(ctx context.Context) (err error) { return nil } +func (e *IndexMergeReaderExecutor) rebuildRangeForCorCol() (err error) { + len1 := len(e.partialPlans) + len2 := len(e.isCorColInPartialAccess) + if len1 != len2 { + return errors.Errorf("unexpect length for partialPlans(%d) and isCorColInPartialAccess(%d)", len1, len2) + } + for i, plan := range e.partialPlans { + if e.isCorColInPartialAccess[i] { + switch x := plan[0].(type) { + case *plannercore.PhysicalIndexScan: + e.ranges[i], err = rebuildIndexRanges(e.ctx, x, x.IdxCols, x.IdxColLens) + case *plannercore.PhysicalTableScan: + e.ranges[i], err = x.ResolveCorrelatedColumns() + default: + err = errors.Errorf("unsupported plan type %T", plan[0]) + } + if err != nil { + return err + } + } + } + return nil +} + func (e *IndexMergeReaderExecutor) buildKeyRangesForTable(tbl table.Table) (ranges [][]kv.KeyRange, err error) { + sc := e.ctx.GetSessionVars().StmtCtx for i, plan := range e.partialPlans { _, ok := plan[0].(*plannercore.PhysicalIndexScan) if !ok { - if tbl.Meta().IsCommonHandle { - keyRanges, err := distsql.CommonHandleRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, []int64{getPhysicalTableID(tbl)}, e.ranges[i]) - if err != nil { - return nil, err - } - ranges = append(ranges, keyRanges) - } else { - ranges = append(ranges, nil) + firstPartRanges, secondPartRanges := distsql.SplitRangesAcrossInt64Boundary(e.ranges[i], false, e.descs[i], tbl.Meta().IsCommonHandle) + firstKeyRanges, err := distsql.TableHandleRangesToKVRanges(sc, []int64{getPhysicalTableID(tbl)}, tbl.Meta().IsCommonHandle, firstPartRanges, nil) + if err != nil { + return nil, err + } + secondKeyRanges, err := distsql.TableHandleRangesToKVRanges(sc, []int64{getPhysicalTableID(tbl)}, tbl.Meta().IsCommonHandle, secondPartRanges, nil) + if err != nil { + return nil, err } + keyRanges := append(firstKeyRanges, secondKeyRanges...) + ranges = append(ranges, keyRanges) continue } - keyRange, err := distsql.IndexRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, getPhysicalTableID(tbl), e.indexes[i].ID, e.ranges[i], e.feedbacks[i]) + keyRange, err := distsql.IndexRangesToKVRanges(sc, getPhysicalTableID(tbl), e.indexes[i].ID, e.ranges[i], e.feedbacks[i]) if err != nil { return nil, err } @@ -239,6 +282,24 @@ func (e *IndexMergeReaderExecutor) startPartialIndexWorker(ctx context.Context, defer e.idxWorkerWg.Done() util.WithRecovery( func() { + worker := &partialIndexWorker{ + stats: e.stats, + idxID: e.getPartitalPlanID(workID), + sc: e.ctx, + batchSize: e.maxChunkSize, + maxBatchSize: e.ctx.GetSessionVars().IndexLookupSize, + maxChunkSize: e.maxChunkSize, + } + + if e.isCorColInPartialFilters[workID] { + // We got correlated column, so need to refresh Selection operator. + var err error + if e.dagPBs[workID].Executors, _, err = constructDistExec(e.ctx, e.partialPlans[workID]); err != nil { + worker.syncErr(e.resultCh, err) + return + } + } + var builder distsql.RequestBuilder builder.SetDAGRequest(e.dagPBs[workID]). SetStartTS(e.startTS). @@ -251,15 +312,6 @@ func (e *IndexMergeReaderExecutor) startPartialIndexWorker(ctx context.Context, SetMemTracker(e.memTracker). SetFromInfoSchema(e.ctx.GetInfoSchema()) - worker := &partialIndexWorker{ - stats: e.stats, - idxID: e.getPartitalPlanID(workID), - sc: e.ctx, - batchSize: e.maxChunkSize, - maxBatchSize: e.ctx.GetSessionVars().IndexLookupSize, - maxChunkSize: e.maxChunkSize, - } - for parTblIdx, keyRange := range keyRanges { // check if this executor is closed select { @@ -327,6 +379,7 @@ func (e *IndexMergeReaderExecutor) startPartialTableWorker(ctx context.Context, defer e.idxWorkerWg.Done() util.WithRecovery( func() { + var err error partialTableReader := &TableReaderExecutor{ baseExecutor: newBaseExecutor(e.ctx, ts.Schema(), e.getPartitalPlanID(workID)), dagPB: e.dagPBs[workID], @@ -338,6 +391,7 @@ func (e *IndexMergeReaderExecutor) startPartialTableWorker(ctx context.Context, plans: e.partialPlans[workID], ranges: e.ranges[workID], } + worker := &partialTableWorker{ stats: e.stats, sc: e.ctx, @@ -347,6 +401,14 @@ func (e *IndexMergeReaderExecutor) startPartialTableWorker(ctx context.Context, tableReader: partialTableReader, } + if e.isCorColInPartialFilters[workID] { + if e.dagPBs[workID].Executors, _, err = constructDistExec(e.ctx, e.partialPlans[workID]); err != nil { + worker.syncErr(e.resultCh, err) + return + } + partialTableReader.dagPB = e.dagPBs[workID] + } + for _, tbl := range tbls { // check if this executor is closed select { @@ -357,8 +419,7 @@ func (e *IndexMergeReaderExecutor) startPartialTableWorker(ctx context.Context, // init partialTableReader and partialTableWorker again for the next table partialTableReader.table = tbl - err := partialTableReader.Open(ctx) - if err != nil { + if err = partialTableReader.Open(ctx); err != nil { logutil.Logger(ctx).Error("open Select result failed:", zap.Error(err)) worker.syncErr(e.resultCh, err) break @@ -380,7 +441,7 @@ func (e *IndexMergeReaderExecutor) startPartialTableWorker(ctx context.Context, // release related resources cancel() - if err := worker.tableReader.Close(); err != nil { + if err = worker.tableReader.Close(); err != nil { logutil.Logger(ctx).Error("close Select result failed:", zap.Error(err)) } e.ctx.StoreQueryFeedback(e.feedbacks[workID]) @@ -538,7 +599,7 @@ func (e *IndexMergeReaderExecutor) startIndexMergeTableScanWorker(ctx context.Co } } -func (e *IndexMergeReaderExecutor) buildFinalTableReader(ctx context.Context, tbl table.Table, handles []kv.Handle) (Executor, error) { +func (e *IndexMergeReaderExecutor) buildFinalTableReader(ctx context.Context, tbl table.Table, handles []kv.Handle) (_ Executor, err error) { tableReaderExec := &TableReaderExecutor{ baseExecutor: newBaseExecutor(e.ctx, e.schema, e.getTablePlanRootID()), table: tbl, @@ -551,8 +612,15 @@ func (e *IndexMergeReaderExecutor) buildFinalTableReader(ctx context.Context, tb feedback: statistics.NewQueryFeedback(0, nil, 0, false), plans: e.tblPlans, } + if e.isCorColInTableFilter { + if tableReaderExec.dagPB.Executors, _, err = constructDistExec(e.ctx, e.tblPlans); err != nil { + return nil, err + } + } tableReaderExec.buildVirtualColumnInfo() - tableReader, err := e.dataReaderBuilder.buildTableReaderFromHandles(ctx, tableReaderExec, handles, false) + // Reorder handles because SplitKeyRangesByLocations() requires startKey of kvRanges is ordered. + // Also it's good for performance. + tableReader, err := e.dataReaderBuilder.buildTableReaderFromHandles(ctx, tableReaderExec, handles, true) if err != nil { logutil.Logger(ctx).Error("build table reader from handles failed", zap.Error(err)) return nil, err diff --git a/executor/index_merge_reader_test.go b/executor/index_merge_reader_test.go index 15f8228bbccc0..fb484898ccdfa 100644 --- a/executor/index_merge_reader_test.go +++ b/executor/index_merge_reader_test.go @@ -20,15 +20,19 @@ import ( "regexp" "strconv" "strings" + "testing" + "time" - . "github.com/pingcap/check" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/israce" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite1) TestSingleTableRead(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestSingleTableRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(id int primary key, a int, b int, c int, d int)") tk.MustExec("create index t1a on t1(a)") @@ -46,8 +50,11 @@ func (s *testSuite1) TestSingleTableRead(c *C) { tk.MustQuery("select /*+ use_index_merge(t1, t1a, t1b) */ sum(a) from t1 where a < 2 or b > 4").Check(testkit.Rows("6")) } -func (s *testSuite1) TestJoin(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(id int primary key, a int, b int, c int, d int)") tk.MustExec("create index t1a on t1(a)") @@ -60,8 +67,10 @@ func (s *testSuite1) TestJoin(c *C) { tk.MustQuery("select /*+ use_index_merge(t1, t1a, t1b) */ sum(t1.a) from t1 join t2 on t1.id = t2.id where t1.a < 2 or t1.b > 5").Check(testkit.Rows("1")) } -func (s *testSuite1) TestIndexMergeReaderAndGeneratedColumn(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIndexMergeReaderAndGeneratedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0") tk.MustExec("CREATE TABLE t0(c0 INT AS (1), c1 INT PRIMARY KEY)") @@ -72,8 +81,10 @@ func (s *testSuite1) TestIndexMergeReaderAndGeneratedColumn(c *C) { } // issue 25045 -func (s *testSuite1) TestIndexMergeReaderIssue25045(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIndexMergeReaderIssue25045(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int primary key, b int, c int, key(b), key(c));") @@ -87,8 +98,11 @@ func (s *testSuite1) TestIndexMergeReaderIssue25045(c *C) { tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where c=10 or (b=10 and a=10);").Check(testkit.Rows("10 10 10")) } -func (s *testSuite1) TestIssue16910(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue16910(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("use test;") tk.MustExec("drop table if exists t1, t2, t3;") tk.MustExec("create table t1 (a int not null, b tinyint not null, index (a), index (b)) partition by range (a) (" + @@ -104,19 +118,20 @@ func (s *testSuite1) TestIssue16910(c *C) { tk.MustQuery("select /*+ USE_INDEX_MERGE(t1, a, b) */ * from t1 partition (p0) join t2 partition (p1) on t1.a = t2.a where t1.a < 40 or t1.b < 30;").Check(testkit.Rows("1 1 1 1")) } -func (s *testSuite1) TestIndexMergeCausePanic(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeCausePanic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_index_merge = 1;") tk.MustExec("create table t (a int, b int, c int, primary key(a), key(b))") tk.MustQuery("explain select /*+ inl_join(t2) */ * from t t1 join t t2 on t1.a = t2.a and t1.c = t2.c where t2.a = 1 or t2.b = 1") } -func (s *testSuite1) TestPartitionTableRandomIndexMerge(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTableRandomIndexMerge(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_index_merge=1") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") @@ -174,8 +189,10 @@ func (s *testSuite1) TestPartitionTableRandomIndexMerge(c *C) { } } -func (s *testSuite1) TestIndexMergeWithPreparedStmt(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeWithPreparedStmt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(c1 int, c2 int, c3 int, key(c1), key(c2));") @@ -188,26 +205,29 @@ func (s *testSuite1) TestIndexMergeWithPreparedStmt(c *C) { tk.MustExec("prepare stmt1 from 'select /*+ use_index_merge(t1) */ count(1) from t1 where c1 < ? or c2 < ?';") tk.MustExec("set @a = 10;") tk.MustQuery("execute stmt1 using @a, @a;").Check(testkit.Rows("10")) - tk.Se.SetSessionManager(&mockSessionManager1{ - PS: []*util.ProcessInfo{tk.Se.ShowProcess()}, + tk.Session().SetSessionManager(&mockSessionManager1{ + PS: []*util.ProcessInfo{tk.Session().ShowProcess()}, }) - explainStr := "explain for connection " + strconv.FormatUint(tk.Se.ShowProcess().ID, 10) + explainStr := "explain for connection " + strconv.FormatUint(tk.Session().ShowProcess().ID, 10) res := tk.MustQuery(explainStr) indexMergeLine := res.Rows()[1][0].(string) re, err := regexp.Compile(".*IndexMerge.*") - c.Assert(err, IsNil) - c.Assert(re.MatchString(indexMergeLine), IsTrue) + require.NoError(t, err) + require.True(t, re.MatchString(indexMergeLine)) tk.MustExec("prepare stmt1 from 'select /*+ use_index_merge(t1) */ count(1) from t1 where c1 < ? or c2 < ? and c3';") tk.MustExec("set @a = 10;") tk.MustQuery("execute stmt1 using @a, @a;").Check(testkit.Rows("10")) res = tk.MustQuery(explainStr) indexMergeLine = res.Rows()[1][0].(string) - c.Assert(re.MatchString(indexMergeLine), IsTrue) + require.True(t, re.MatchString(indexMergeLine)) } -func (s *testSuite1) TestIndexMergeInTransaction(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIndexMergeInTransaction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") for i := 0; i < 2; i++ { tk.MustExec("drop table if exists t1;") @@ -232,22 +252,31 @@ func (s *testSuite1) TestIndexMergeInTransaction(c *C) { " └─TableRowIDScan_7 3330.01 cop[tikv] table:t1 keep order:false, stats:pseudo")) // Test with normal key. - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) tk.MustExec("insert into t1 values(1, 1, 1, 1);") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) tk.MustExec("update t1 set c3 = 100 where c3 = 1;") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) tk.MustExec("delete from t1;") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) // Test with primary key, so the partialPlan is TableScan. - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) tk.MustExec("insert into t1 values(1, 1, 1, 1);") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows("1 1 1 1")) tk.MustExec("update t1 set c3 = 100 where c3 = 1;") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) tk.MustExec("delete from t1;") - tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 10) and c3 < 10;").Check(testkit.Rows()) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 10 or c2 < -1) and c3 < 10;").Check(testkit.Rows()) + tk.MustExec("commit;") if i == 1 { tk.MustExec("set tx_isolation = 'REPEATABLE-READ';") @@ -294,7 +323,7 @@ func (s *testSuite1) TestIndexMergeInTransaction(c *C) { // Test partition table. tk.MustExec("drop table if exists t1;") - tk.MustExec(`create table t1(c1 int, c2 int, c3 int, pk int, part int, key(c1), key(c2), key(c3), primary key(pk, part)) + tk.MustExec(`create table t1(c1 int, c2 int, c3 int, pk int, part int, key(c1), key(c2), key(c3), primary key(pk, part)) partition by range(part) ( partition p0 values less than (10), partition p1 values less than (20), @@ -306,27 +335,118 @@ func (s *testSuite1) TestIndexMergeInTransaction(c *C) { tk.MustExec("insert into t1 values(11, 11, 11, 11, 11);") tk.MustExec("insert into t1 values(21, 21, 21, 21, 21);") tk.MustExec("insert into t1 values(31, 31, 31, 31, 31);") - res := tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < 20) and c3 < 20;").Sort() + + res := tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 20) and c3 < 20;").Sort() res.Check(testkit.Rows("1 1 1 1 1", "11 11 11 11 11")) - res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < 20) and c3 < 20;").Sort() + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < -1) and c3 < 20;").Sort() + res.Check(testkit.Rows("1 1 1 1 1", "11 11 11 11 11")) + + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 20) and c3 < 20;").Sort() + res.Check(testkit.Rows("1 1 1 1 1", "11 11 11 11 11")) + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < -1) and c3 < 20;").Sort() res.Check(testkit.Rows("1 1 1 1 1", "11 11 11 11 11")) tk.MustExec("update t1 set c3 = 100 where c3 = 1;") - res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < 20) and c3 < 20;") + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 20) and c3 < 20;") + res.Check(testkit.Rows("11 11 11 11 11")) + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < -1) and c3 < 20;") + res.Check(testkit.Rows("11 11 11 11 11")) + + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 20) and c3 < 20;") res.Check(testkit.Rows("11 11 11 11 11")) - res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < 20) and c3 < 20;") + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < -1) and c3 < 20;") res.Check(testkit.Rows("11 11 11 11 11")) tk.MustExec("delete from t1;") - res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < 20) and c3 < 20;") + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c2 < 20) and c3 < 20;") res.Check(testkit.Rows()) - res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < 20) and c3 < 20;") + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 20 or c2 < -1) and c3 < 20;") + res.Check(testkit.Rows()) + + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < -1 or c2 < 20) and c3 < 20;") + res.Check(testkit.Rows()) + res = tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (pk < 20 or c2 < -1) and c3 < 20;") res.Check(testkit.Rows()) tk.MustExec("commit;") } -func (test *testSerialSuite2) TestIndexMergeReaderMemTracker(c *C) { - tk := testkit.NewTestKit(c, test.store) +func TestIndexMergeReaderInTransIssue30685(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // This is a case generated by sqlgen to test if clustered index is ok. + // Detect the bugs in memIndexMergeReader.getMemRowsHandle(). + tk.MustExec("drop table if exists t1;") + tk.MustExec(`create table t1 (col_30 decimal default 0 , + col_31 char(99) collate utf8_bin default 'sVgzHblmYYtEjVg' not null , + col_37 int unsigned default 377206828 , + primary key idx_16 ( col_37 ) , key idx_19 ( col_31) ) collate utf8mb4_general_ci ;`) + tk.MustExec("begin;") + tk.MustExec("insert ignore into t1 values (388021, '', 416235653);") + tk.MustQuery("select /*+ use_index_merge( t1 ) */ 1 from t1 where ( t1.col_31 in ( 'OiOXzpCs' , 'oaVv' ) or t1.col_37 <= 4059907010 ) and t1.col_30 ;").Check(testkit.Rows("1")) + tk.MustExec("commit;") + + tk.MustExec("drop table if exists tbl_3;") + tk.MustExec(`create table tbl_3 ( col_30 decimal , col_31 char(99) , col_32 smallint , + col_33 tinyint unsigned not null , col_34 char(209) , + col_35 char(110) , col_36 int unsigned , col_37 int unsigned , + col_38 decimal(50,15) not null , col_39 char(104), + primary key ( col_37 ) , unique key ( col_33,col_30,col_36,col_39 ) , + unique key ( col_32,col_35 ) , key ( col_31,col_38 ) , + key ( col_31,col_33,col_32,col_35,col_36 ) , + unique key ( col_38,col_34,col_33,col_31,col_30,col_36,col_35,col_37,col_39 ) , + unique key ( col_39,col_32 ) , unique key ( col_30,col_35,col_31,col_38 ) , + key ( col_38,col_32,col_33 ) )`) + tk.MustExec("begin;") + tk.MustExec("insert ignore into tbl_3 values ( 71,'Fipc',-6676,30,'','FgfK',2464927398,4084082400,5602.5868,'' );") + tk.MustQuery("select /*+ use_index_merge( tbl_3 ) */ 1 from tbl_3 where ( tbl_3.col_37 not in ( 1626615245 , 2433569159 ) or tbl_3.col_38 = 0.06 ) ;").Check(testkit.Rows("1")) + tk.MustExec("commit;") + + // int + int compound type as clustered index pk. + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 int, c2 int, c3 int, c4 int, primary key(c1, c2) /*T![clustered_index] CLUSTERED */, key(c3));") + + tk.MustExec("begin;") + tk.MustExec("insert into t1 values(1, 1, 1, 1);") + tk.MustQuery("explain select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c3 < 10) and c4 < 10;").Check(testkit.Rows( + "UnionScan_6 1841.86 root lt(test.t1.c4, 10), or(lt(test.t1.c1, -1), lt(test.t1.c3, 10))", + "└─IndexMerge_11 1841.86 root ", + " ├─TableRangeScan_7(Build) 3323.33 cop[tikv] table:t1 range:[-inf,-1), keep order:false, stats:pseudo", + " ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c3(c3) range:[-inf,10), keep order:false, stats:pseudo", + " └─Selection_10(Probe) 1841.86 cop[tikv] lt(test.t1.c4, 10)", + " └─TableRowIDScan_9 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo")) + + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c3 < 10) and c4 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c3 < -1) and c4 < 10;").Check(testkit.Rows("1 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < -1 or c3 < -1) and c4 < 10;").Check(testkit.Rows()) + tk.MustExec("commit;") + + // Single int type as clustered index pk. + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 varchar(100), c2 int, c3 int, c4 int, primary key(c1) /*T![clustered_index] CLUSTERED */, key(c3));") + + tk.MustExec("begin;") + tk.MustExec("insert into t1 values('b', 1, 1, 1);") + tk.MustQuery("explain select /*+ use_index_merge(t1) */ * from t1 where (c1 < 'a' or c3 < 10) and c4 < 10;").Check(testkit.Rows( + "UnionScan_6 1841.86 root lt(test.t1.c4, 10), or(lt(test.t1.c1, \"a\"), lt(test.t1.c3, 10))", + "└─IndexMerge_11 1841.86 root ", + " ├─TableRangeScan_7(Build) 3323.33 cop[tikv] table:t1 range:[-inf,\"a\"), keep order:false, stats:pseudo", + " ├─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c3(c3) range:[-inf,10), keep order:false, stats:pseudo", + " └─Selection_10(Probe) 1841.86 cop[tikv] lt(test.t1.c4, 10)", + " └─TableRowIDScan_9 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo")) + + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 'a' or c3 < 10) and c4 < 10;").Check(testkit.Rows("b 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 <= 'b' or c3 < -1) and c4 < 10;").Check(testkit.Rows("b 1 1 1")) + tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where (c1 < 'a' or c3 < -1) and c4 < 10;").Check(testkit.Rows()) + tk.MustExec("commit;") +} + +func TestIndexMergeReaderMemTracker(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("create table t1(c1 int, c2 int, c3 int, key(c1), key(c2), key(c3));") @@ -336,7 +456,7 @@ func (test *testSerialSuite2) TestIndexMergeReaderMemTracker(c *C) { insertStr += fmt.Sprintf(" ,(%d, %d, %d)", i, i, i) } insertStr += ";" - memTracker := tk.Se.GetSessionVars().StmtCtx.MemTracker + memTracker := tk.Session().GetSessionVars().StmtCtx.MemTracker tk.MustExec(insertStr) @@ -346,16 +466,117 @@ func (test *testSerialSuite2) TestIndexMergeReaderMemTracker(c *C) { tk.MustQuery("select /*+ use_index_merge(t1) */ * from t1 where c1 > 1 or c2 > 1") newMaxUsage := memTracker.MaxConsumed() - c.Assert(newMaxUsage, Greater, oriMaxUsage) + require.Greater(t, newMaxUsage, oriMaxUsage) res := tk.MustQuery("explain analyze select /*+ use_index_merge(t1) */ * from t1 where c1 > 1 or c2 > 1") - c.Assert(len(res.Rows()), Equals, 4) + require.Len(t, res.Rows(), 4) // Parse "xxx KB" and check it's greater than 0. memStr := res.Rows()[0][7].(string) re, err := regexp.Compile("[0-9]+ KB") - c.Assert(err, IsNil) - c.Assert(re.MatchString(memStr), IsTrue) + require.NoError(t, err) + require.True(t, re.MatchString(memStr)) bytes, err := strconv.ParseFloat(memStr[:len(memStr)-3], 32) - c.Assert(err, IsNil) - c.Assert(bytes, Greater, 0.0) + require.NoError(t, err) + require.Greater(t, bytes, 0.0) +} + +func TestIndexMergeSplitTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("DROP TABLE IF EXISTS tab2;") + tk.MustExec("CREATE TABLE tab2(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT);") + tk.MustExec("CREATE INDEX idx_tab2_0 ON tab2 (col0 DESC,col3 DESC);") + tk.MustExec("CREATE UNIQUE INDEX idx_tab2_3 ON tab2 (col4,col0 DESC);") + tk.MustExec("CREATE INDEX idx_tab2_4 ON tab2 (col3,col1 DESC);") + tk.MustExec("INSERT INTO tab2 VALUES(0,146,632.63,'shwwd',703,412.47,'xsppr');") + tk.MustExec("INSERT INTO tab2 VALUES(1,81,536.29,'trhdh',49,726.3,'chuxv');") + tk.MustExec("INSERT INTO tab2 VALUES(2,311,541.72,'txrvb',493,581.92,'xtrra');") + tk.MustExec("INSERT INTO tab2 VALUES(3,669,293.27,'vcyum',862,415.14,'nbutk');") + tk.MustExec("INSERT INTO tab2 VALUES(4,681,49.46,'odzhp',106,324.65,'deudp');") + tk.MustExec("INSERT INTO tab2 VALUES(5,319,769.65,'aeqln',855,197.9,'apipa');") + tk.MustExec("INSERT INTO tab2 VALUES(6,610,302.62,'bixap',184,840.31,'vggit');") + tk.MustExec("INSERT INTO tab2 VALUES(7,253,453.21,'gjccm',107,104.5,'lvunv');") + tk.MustExec("SPLIT TABLE tab2 BY (5);") + tk.MustQuery("SELECT /*+ use_index_merge(tab2) */ pk FROM tab2 WHERE (col4 > 565.89 OR col0 > 68 ) and col0 > 10 order by 1;").Check(testkit.Rows("0", "1", "2", "3", "4", "5", "6", "7")) +} + +func TestPessimisticLockOnPartitionForIndexMerge(t *testing.T) { + // Same purpose with TestPessimisticLockOnPartition, but test IndexMergeReader. + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec(`create table t1 (c_datetime datetime, c1 int, c2 int, primary key (c_datetime), key(c1), key(c2)) + partition by range (to_days(c_datetime)) ( + partition p0 values less than (to_days('2020-02-01')), + partition p1 values less than (to_days('2020-04-01')), + partition p2 values less than (to_days('2020-06-01')), + partition p3 values less than maxvalue)`) + tk.MustExec("create table t2 (c_datetime datetime, unique key(c_datetime))") + tk.MustExec("insert into t1 values ('2020-06-26 03:24:00', 1, 1), ('2020-02-21 07:15:33', 2, 2), ('2020-04-27 13:50:58', 3, 3)") + tk.MustExec("insert into t2 values ('2020-01-10 09:36:00'), ('2020-02-04 06:00:00'), ('2020-06-12 03:45:18')") + tk.MustExec("analyze table t1") + tk.MustExec("analyze table t2") + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.MustExec("set @@tidb_partition_prune_mode = 'static'") + + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec("begin pessimistic") + tk.MustQuery(`explain format='brief' select /*+ use_index_merge(t1) */ c1 from t1 join t2 + on t1.c_datetime >= t2.c_datetime + where t1.c1 < 10 or t1.c2 < 10 for update`).Check(testkit.Rows( + "Projection 16635.64 root test.t1.c1", + "└─SelectLock 16635.64 root for update 0", + " └─Projection 16635.64 root test.t1.c1, test.t1._tidb_rowid, test.t1._tidb_tid, test.t2._tidb_rowid", + " └─HashJoin 16635.64 root CARTESIAN inner join, other cond:ge(test.t1.c_datetime, test.t2.c_datetime)", + " ├─IndexReader(Build) 3.00 root index:IndexFullScan", + " │ └─IndexFullScan 3.00 cop[tikv] table:t2, index:c_datetime(c_datetime) keep order:false", + " └─PartitionUnion(Probe) 5545.21 root ", + " ├─IndexMerge 5542.21 root ", + " │ ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t1, partition:p0, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo", + " │ ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t1, partition:p0, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo", + " │ └─TableRowIDScan(Probe) 5542.21 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo", + " ├─IndexMerge 1.00 root ", + " │ ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p1, index:c1(c1) range:[-inf,10), keep order:false", + " │ ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p1, index:c2(c2) range:[-inf,10), keep order:false", + " │ └─TableRowIDScan(Probe) 1.00 cop[tikv] table:t1, partition:p1 keep order:false", + " ├─IndexMerge 1.00 root ", + " │ ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p2, index:c1(c1) range:[-inf,10), keep order:false", + " │ ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p2, index:c2(c2) range:[-inf,10), keep order:false", + " │ └─TableRowIDScan(Probe) 1.00 cop[tikv] table:t1, partition:p2 keep order:false", + " └─IndexMerge 1.00 root ", + " ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p3, index:c1(c1) range:[-inf,10), keep order:false", + " ├─IndexRangeScan(Build) 1.00 cop[tikv] table:t1, partition:p3, index:c2(c2) range:[-inf,10), keep order:false", + " └─TableRowIDScan(Probe) 1.00 cop[tikv] table:t1, partition:p3 keep order:false", + )) + tk.MustQuery(`select /*+ use_index_merge(t1) */ c1 from t1 join t2 + on t1.c_datetime >= t2.c_datetime + where t1.c1 < 10 or t1.c2 < 10 for update`).Sort().Check(testkit.Rows("1", "1", "1", "2", "2", "3", "3")) + tk1.MustExec("begin pessimistic") + + ch := make(chan int32, 5) + go func() { + tk1.MustExec("update t1 set c_datetime = '2020-06-26 03:24:00' where c1 = 1") + ch <- 0 + tk1.MustExec("rollback") + ch <- 0 + }() + + // Leave 50ms for tk1 to run, tk1 should be blocked at the update operation. + time.Sleep(50 * time.Millisecond) + ch <- 1 + + tk.MustExec("commit") + // tk1 should be blocked until tk commit, check the order. + require.Equal(t, <-ch, int32(1)) + require.Equal(t, <-ch, int32(0)) + <-ch // wait for goroutine to quit. + + // TODO: add support for index merge reader in dynamic tidb_partition_prune_mode } diff --git a/executor/infoschema_cluster_table_test.go b/executor/infoschema_cluster_table_test.go new file mode 100644 index 0000000000000..7c3108fd1686e --- /dev/null +++ b/executor/infoschema_cluster_table_test.go @@ -0,0 +1,366 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "crypto/tls" + "fmt" + "net" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/pingcap/failpoint" + "github.com/pingcap/fn" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/server" + "github.com/pingcap/tidb/session/txninfo" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/pdapi" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" +) + +type infosSchemaClusterTableSuite struct { + suite.Suite + store kv.Storage + dom *domain.Domain + clean func() + rpcServer *grpc.Server + httpServer *httptest.Server + mockAddr string + listenAddr string + startTime time.Time +} + +func TestInfoSchemaClusterTable(t *testing.T) { + suite.Run(t, new(infosSchemaClusterTableSuite)) +} + +func (s *infosSchemaClusterTableSuite) SetupSuite() { + s.store, s.dom, s.clean = testkit.CreateMockStoreAndDomain(s.T()) + s.rpcServer, s.listenAddr = s.setUpRPCService("127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() +} + +func (s *infosSchemaClusterTableSuite) setUpRPCService(addr string) (*grpc.Server, string) { + lis, err := net.Listen("tcp", addr) + s.Require().NoError(err) + + // Fix issue 9836 + sm := &mockSessionManager{ + processInfoMap: make(map[uint64]*util.ProcessInfo, 1), + serverID: 1, + } + sm.processInfoMap[1] = &util.ProcessInfo{ + ID: 1, + User: "root", + Host: "127.0.0.1", + Command: mysql.ComQuery, + } + srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) + port := lis.Addr().(*net.TCPAddr).Port + addr = fmt.Sprintf("127.0.0.1:%d", port) + go func() { + s.Require().NoError(srv.Serve(lis)) + }() + config.UpdateGlobal(func(conf *config.Config) { + conf.Status.StatusPort = uint(port) + }) + return srv, addr +} + +func (s *infosSchemaClusterTableSuite) setUpMockPDHTTPServer() (*httptest.Server, string) { + // mock PD http server + router := mux.NewRouter() + srv := httptest.NewServer(router) + // mock store stats stat + mockAddr := strings.TrimPrefix(srv.URL, "http://") + router.Handle(pdapi.Stores, fn.Wrap(func() (*helper.StoresStat, error) { + return &helper.StoresStat{ + Count: 1, + Stores: []helper.StoreStat{ + { + Store: helper.StoreBaseStat{ + ID: 1, + Address: "127.0.0.1:20160", + State: 0, + StateName: "Up", + Version: "4.0.0-alpha", + StatusAddress: mockAddr, + GitHash: "mock-tikv-githash", + StartTimestamp: s.startTime.Unix(), + }, + }, + }, + }, nil + })) + // mock PD API + router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { + return struct { + Version string `json:"version"` + GitHash string `json:"git_hash"` + StartTimestamp int64 `json:"start_timestamp"` + }{ + Version: "4.0.0-alpha", + GitHash: "mock-pd-githash", + StartTimestamp: s.startTime.Unix(), + }, nil + })) + var mockConfig = func() (map[string]interface{}, error) { + configuration := map[string]interface{}{ + "key1": "value1", + "key2": map[string]string{ + "nest1": "n-value1", + "nest2": "n-value2", + }, + "key3": map[string]interface{}{ + "nest1": "n-value1", + "nest2": "n-value2", + "key4": map[string]string{ + "nest3": "n-value4", + "nest4": "n-value5", + }, + }, + } + return configuration, nil + } + // PD config. + router.Handle(pdapi.Config, fn.Wrap(mockConfig)) + // TiDB/TiKV config. + router.Handle("/config", fn.Wrap(mockConfig)) + // PD region. + router.Handle("/pd/api/v1/stats/region", fn.Wrap(func() (*helper.PDRegionStats, error) { + return &helper.PDRegionStats{ + Count: 1, + EmptyCount: 1, + StorageSize: 1, + StorageKeys: 1, + StoreLeaderCount: map[uint64]int{1: 1}, + StorePeerCount: map[uint64]int{1: 1}, + }, nil + })) + return srv, mockAddr +} + +func (s *infosSchemaClusterTableSuite) TearDownSuite() { + s.rpcServer.Stop() + s.httpServer.Close() + s.clean() +} + +type mockSessionManager struct { + processInfoMap map[uint64]*util.ProcessInfo + serverID uint64 +} + +func (sm *mockSessionManager) ShowTxnList() []*txninfo.TxnInfo { + panic("unimplemented!") +} + +func (sm *mockSessionManager) ShowProcessList() map[uint64]*util.ProcessInfo { + return sm.processInfoMap +} + +func (sm *mockSessionManager) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) { + rs, ok := sm.processInfoMap[id] + return rs, ok +} + +func (sm *mockSessionManager) StoreInternalSession(se interface{}) { +} + +func (sm *mockSessionManager) DeleteInternalSession(se interface{}) { +} + +func (sm *mockSessionManager) GetInternalSessionStartTSList() []uint64 { + return nil +} + +func (sm *mockSessionManager) Kill(_ uint64, _ bool) {} + +func (sm *mockSessionManager) KillAllConnections() {} + +func (sm *mockSessionManager) UpdateTLSConfig(_ *tls.Config) {} + +func (sm *mockSessionManager) ServerID() uint64 { + return sm.serverID +} + +func (sm *mockSessionManager) SetServerID(serverID uint64) { + sm.serverID = serverID +} + +type mockStore struct { + helper.Storage + host string +} + +func (s *mockStore) EtcdAddrs() ([]string, error) { return []string{s.host}, nil } +func (s *mockStore) TLSConfig() *tls.Config { panic("not implemented") } +func (s *mockStore) StartGCWorker() error { panic("not implemented") } +func (s *mockStore) Name() string { return "mockStore" } +func (s *mockStore) Describe() string { return "" } + +func (s *infosSchemaClusterTableSuite) TestTiDBClusterInfo() { + mockAddr := s.mockAddr + store := &mockStore{ + s.store.(helper.Storage), + mockAddr, + } + + // information_schema.cluster_info + tk := testkit.NewTestKit(s.T(), store) + tidbStatusAddr := fmt.Sprintf(":%d", config.GetGlobalConfig().Status.StatusPort) + row := func(cols ...string) string { return strings.Join(cols, " ") } + tk.MustQuery("select type, instance, status_address, version, git_hash from information_schema.cluster_info").Check(testkit.Rows( + row("tidb", ":4000", tidbStatusAddr, "None", "None"), + row("pd", mockAddr, mockAddr, "4.0.0-alpha", "mock-pd-githash"), + row("tikv", "store1", "", "", ""), + )) + startTime := s.startTime.Format(time.RFC3339) + tk.MustQuery("select type, instance, start_time from information_schema.cluster_info where type != 'tidb'").Check(testkit.Rows( + row("pd", mockAddr, startTime), + row("tikv", "store1", ""), + )) + + s.Require().NoError(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockStoreTombstone", `return(true)`)) + tk.MustQuery("select type, instance, start_time from information_schema.cluster_info where type = 'tikv'").Check(testkit.Rows()) + s.Require().NoError(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockStoreTombstone")) + + // information_schema.cluster_config + instances := []string{ + "pd,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,0", + "tidb,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,1001", + "tikv,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,0", + } + fpExpr := `return("` + strings.Join(instances, ";") + `")` + s.Require().NoError(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockClusterInfo", fpExpr)) + defer func() { s.Require().NoError(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockClusterInfo")) }() + tk.MustQuery("select type, instance, status_address, version, git_hash, server_id from information_schema.cluster_info").Check(testkit.Rows( + row("pd", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "0"), + row("tidb", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "1001"), + row("tikv", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "0"), + )) + tk.MustQuery("select * from information_schema.cluster_config").Check(testkit.Rows( + "pd 127.0.0.1:11080 key1 value1", + "pd 127.0.0.1:11080 key2.nest1 n-value1", + "pd 127.0.0.1:11080 key2.nest2 n-value2", + "pd 127.0.0.1:11080 key3.key4.nest3 n-value4", + "pd 127.0.0.1:11080 key3.key4.nest4 n-value5", + "pd 127.0.0.1:11080 key3.nest1 n-value1", + "pd 127.0.0.1:11080 key3.nest2 n-value2", + "tidb 127.0.0.1:11080 key1 value1", + "tidb 127.0.0.1:11080 key2.nest1 n-value1", + "tidb 127.0.0.1:11080 key2.nest2 n-value2", + "tidb 127.0.0.1:11080 key3.key4.nest3 n-value4", + "tidb 127.0.0.1:11080 key3.key4.nest4 n-value5", + "tidb 127.0.0.1:11080 key3.nest1 n-value1", + "tidb 127.0.0.1:11080 key3.nest2 n-value2", + "tikv 127.0.0.1:11080 key1 value1", + "tikv 127.0.0.1:11080 key2.nest1 n-value1", + "tikv 127.0.0.1:11080 key2.nest2 n-value2", + "tikv 127.0.0.1:11080 key3.key4.nest3 n-value4", + "tikv 127.0.0.1:11080 key3.key4.nest4 n-value5", + "tikv 127.0.0.1:11080 key3.nest1 n-value1", + "tikv 127.0.0.1:11080 key3.nest2 n-value2", + )) + tk.MustQuery("select TYPE, `KEY`, VALUE from information_schema.cluster_config where `key`='key3.key4.nest4' order by type").Check(testkit.Rows( + "pd key3.key4.nest4 n-value5", + "tidb key3.key4.nest4 n-value5", + "tikv key3.key4.nest4 n-value5", + )) +} + +func (s *infosSchemaClusterTableSuite) TestTableStorageStats() { + tk := testkit.NewTestKit(s.T(), s.store) + err := tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test'") + s.Require().EqualError(err, "pd unavailable") + mockAddr := s.mockAddr + store := &mockStore{ + s.store.(helper.Storage), + mockAddr, + } + + // Test information_schema.TABLE_STORAGE_STATS. + tk = testkit.NewTestKit(s.T(), store) + + // Test not set the schema. + err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS") + s.Require().EqualError(err, "Please specify the 'table_schema'") + + // Test it would get null set when get the sys schema. + tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema';").Check([][]interface{}{}) + tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA in ('information_schema', 'metrics_schema');").Check([][]interface{}{}) + tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema' and TABLE_NAME='schemata';").Check([][]interface{}{}) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, index idx(a))") + tk.MustQuery("select TABLE_NAME, TABLE_SIZE from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' and TABLE_NAME='t';").Check(testkit.Rows("t 1")) + + tk.MustExec("create table t1 (a int, b int, index idx(a))") + tk.MustQuery("select TABLE_NAME, sum(TABLE_SIZE) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' group by TABLE_NAME;").Sort().Check(testkit.Rows( + "t 1", + "t1 1", + )) + tk.MustQuery("select TABLE_SCHEMA, sum(TABLE_SIZE) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' group by TABLE_SCHEMA;").Check(testkit.Rows( + "test 2", + )) + rows := tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql';").Rows() + s.Require().Len(rows, 31) + + // More tests about the privileges. + tk.MustExec("create user 'testuser'@'localhost'") + tk.MustExec("create user 'testuser2'@'localhost'") + tk.MustExec("create user 'testuser3'@'localhost'") + tk1 := testkit.NewTestKit(s.T(), store) + defer tk1.MustExec("drop user 'testuser'@'localhost'") + defer tk1.MustExec("drop user 'testuser2'@'localhost'") + defer tk1.MustExec("drop user 'testuser3'@'localhost'") + + tk.MustExec("grant all privileges on *.* to 'testuser2'@'localhost'") + tk.MustExec("grant select on *.* to 'testuser3'@'localhost'") + s.Require().True(tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser", + Hostname: "localhost", + }, nil, nil)) + + // User has no access to this schema, so the result set is empty. + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) + + s.Require().True(tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser2", + Hostname: "localhost", + }, nil, nil)) + + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("31")) + + s.Require().True(tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser3", + Hostname: "localhost", + }, nil, nil)) + + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("31")) +} diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index 1e4fcae3829ba..557d4593aac75 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -33,7 +33,6 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/deadlock" "github.com/pingcap/tidb/ddl/label" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/expression" @@ -51,13 +50,15 @@ import ( "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/statistics" + "github.com/pingcap/tidb/sessiontxn" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" binaryJson "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/deadlockhistory" "github.com/pingcap/tidb/util/keydecoder" @@ -69,7 +70,6 @@ import ( "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/stmtsummary" "github.com/pingcap/tidb/util/stringutil" - "go.etcd.io/etcd/clientv3" "go.uber.org/zap" ) @@ -81,6 +81,7 @@ type memtableRetriever struct { rowIdx int retrieved bool initialized bool + extractor plannercore.MemTablePredicateExtractor } // retrieve implements the infoschemaRetriever interface @@ -114,7 +115,7 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex case infoschema.TableClusterInfo: err = e.dataForTiDBClusterInfo(sctx) case infoschema.TableAnalyzeStatus: - e.setDataForAnalyzeStatus(sctx) + err = e.setDataForAnalyzeStatus(sctx) case infoschema.TableTiDBIndexes: e.setDataFromIndexes(sctx, dbs) case infoschema.TableViews: @@ -141,8 +142,6 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex e.setDataFromUserPrivileges(sctx) case infoschema.TableTiKVRegionStatus: err = e.setDataForTiKVRegionStatus(sctx) - case infoschema.TableTiKVRegionPeers: - err = e.setDataForTikVRegionPeers(sctx) case infoschema.TableTiDBHotRegions: err = e.setDataForTiDBHotRegions(sctx) case infoschema.TableConstraints: @@ -163,9 +162,9 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex infoschema.TableClientErrorsSummaryByHost: err = e.setDataForClientErrorsSummary(sctx, e.table.Name.O) case infoschema.TableAttributes: - err = e.setDataForAttributes(sctx) - case infoschema.TablePlacementRules: - err = e.setDataFromPlacementRules(ctx, sctx, dbs) + err = e.setDataForAttributes(sctx, is) + case infoschema.TablePlacementPolicies: + err = e.setDataFromPlacementPolicies(sctx) } if err != nil { return nil, err @@ -190,11 +189,7 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex func getRowCountAllTable(ctx context.Context, sctx sessionctx.Context) (map[int64]uint64, error) { exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "select table_id, count from mysql.stats_meta") - if err != nil { - return nil, err - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select table_id, count from mysql.stats_meta") if err != nil { return nil, err } @@ -215,11 +210,7 @@ type tableHistID struct { func getColLengthAllTables(ctx context.Context, sctx sessionctx.Context) (map[tableHistID]uint64, error) { exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "select table_id, hist_id, tot_col_size from mysql.stats_histograms where is_index = 0") - if err != nil { - return nil, err - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select table_id, hist_id, tot_col_size from mysql.stats_histograms where is_index = 0") if err != nil { return nil, err } @@ -354,13 +345,10 @@ func (e *memtableRetriever) setDataFromSchemata(ctx sessionctx.Context, schemas if len(schema.Collate) > 0 { collation = schema.Collate // Overwrite default } - var policyName, directPlacement interface{} + var policyName interface{} if schema.PlacementPolicyRef != nil { policyName = schema.PlacementPolicyRef.Name.O } - if schema.DirectPlacementOpts != nil { - directPlacement = schema.DirectPlacementOpts.String() - } if checker != nil && !checker.RequestVerification(ctx.GetSessionVars().ActiveRoles, schema.Name.L, "", "", mysql.AllPrivMask) { continue @@ -372,7 +360,6 @@ func (e *memtableRetriever) setDataFromSchemata(ctx sessionctx.Context, schemas collation, // DEFAULT_COLLATION_NAME nil, // SQL_PATH policyName, // TIDB_PLACEMENT_POLICY_NAME - directPlacement, // TIDB_DIRECT_PLACEMENT ) rows = append(rows, record) } @@ -466,7 +453,7 @@ func (e *memtableRetriever) setDataForStatisticsInTable(schema *model.DBInfo, ta nullable, // NULLABLE "BTREE", // INDEX_TYPE "", // COMMENT - "", // INDEX_COMMENT + index.Comment, // INDEX_COMMENT visible, // IS_VISIBLE expression, // Expression ) @@ -526,13 +513,17 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc var rows [][]types.Datum createTimeTp := mysql.TypeDatetime + loc := sctx.GetSessionVars().TimeZone + if loc == nil { + loc = time.Local + } for _, schema := range schemas { for _, table := range schema.Tables { collation := table.Collate if collation == "" { collation = mysql.DefaultCollationName } - createTime := types.NewTime(types.FromGoTime(table.GetUpdateTime()), createTimeTp, types.DefaultFsp) + createTime := types.NewTime(types.FromGoTime(table.GetUpdateTime().In(loc)), createTimeTp, types.DefaultFsp) createOptions := "" @@ -543,6 +534,8 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc if !table.IsView() { if table.GetPartitionInfo() != nil { createOptions = "partitioned" + } else if table.TableCacheStatusType == model.TableCacheStatusEnable { + createOptions = "cached=on" } var autoIncID interface{} hasAutoIncID, _ := infoschema.HasAutoIncrementColumn(table) @@ -575,21 +568,17 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc } if table.IsSequence() { tableType = "SEQUENCE" - if rowCount == 0 { - rowCount = 1 - } + // sequence is always 1 row regardless of stats. + rowCount = 1 } if table.HasClusteredIndex() { pkType = "CLUSTERED" } shardingInfo := infoschema.GetShardingInfo(schema, table) - var policyName, directPlacement interface{} + var policyName interface{} if table.PlacementPolicyRef != nil { policyName = table.PlacementPolicyRef.Name.O } - if table.DirectPlacementOpts != nil { - directPlacement = table.DirectPlacementOpts.String() - } record := types.MakeDatums( infoschema.CatalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA @@ -616,7 +605,6 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc shardingInfo, // TIDB_ROW_ID_SHARDING_INFO pkType, // TIDB_PK_TYPE policyName, // TIDB_PLACEMENT_POLICY_NAME - directPlacement, // TIDB_DIRECT_PLACEMENT ) rows = append(rows, record) } else { @@ -646,7 +634,6 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc nil, // TIDB_ROW_ID_SHARDING_INFO pkType, // TIDB_PK_TYPE nil, // TIDB_PLACEMENT_POLICY_NAME - nil, // TIDB_DIRECT_PLACEMENT ) rows = append(rows, record) } @@ -656,7 +643,7 @@ func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionc return nil } -func (e *hugeMemTableRetriever) setDataForColumns(ctx context.Context, sctx sessionctx.Context) error { +func (e *hugeMemTableRetriever) setDataForColumns(ctx context.Context, sctx sessionctx.Context, extractor *plannercore.ColumnsTableExtractor) error { checker := privilege.GetPrivilegeManager(sctx) e.rows = e.rows[:0] batch := 1024 @@ -679,7 +666,7 @@ func (e *hugeMemTableRetriever) setDataForColumns(ctx context.Context, sctx sess } } - e.dataForColumnsInTable(ctx, sctx, schema, table, priv) + e.dataForColumnsInTable(ctx, sctx, schema, table, priv, extractor) if len(e.rows) >= batch { return nil } @@ -689,15 +676,72 @@ func (e *hugeMemTableRetriever) setDataForColumns(ctx context.Context, sctx sess return nil } -func (e *hugeMemTableRetriever) dataForColumnsInTable(ctx context.Context, sctx sessionctx.Context, schema *model.DBInfo, tbl *model.TableInfo, priv mysql.PrivilegeType) { +func (e *hugeMemTableRetriever) dataForColumnsInTable(ctx context.Context, sctx sessionctx.Context, schema *model.DBInfo, tbl *model.TableInfo, priv mysql.PrivilegeType, extractor *plannercore.ColumnsTableExtractor) { if err := tryFillViewColumnType(ctx, sctx, sctx.GetInfoSchema().(infoschema.InfoSchema), schema.Name, tbl); err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(err) return } + var tableSchemaRegexp, tableNameRegexp, columnsRegexp []collate.WildcardPattern + var tableSchemaFilterEnable, + tableNameFilterEnable, columnsFilterEnable bool + if !extractor.SkipRequest { + tableSchemaFilterEnable = extractor.TableSchema.Count() > 0 + tableNameFilterEnable = extractor.TableName.Count() > 0 + columnsFilterEnable = extractor.ColumnName.Count() > 0 + if len(extractor.TableSchemaPatterns) > 0 { + tableSchemaRegexp = make([]collate.WildcardPattern, len(extractor.TableSchemaPatterns)) + for i, pattern := range extractor.TableSchemaPatterns { + tableSchemaRegexp[i] = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + tableSchemaRegexp[i].Compile(pattern, byte('\\')) + } + } + if len(extractor.TableNamePatterns) > 0 { + tableNameRegexp = make([]collate.WildcardPattern, len(extractor.TableNamePatterns)) + for i, pattern := range extractor.TableNamePatterns { + tableNameRegexp[i] = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + tableNameRegexp[i].Compile(pattern, byte('\\')) + } + } + if len(extractor.ColumnNamePatterns) > 0 { + columnsRegexp = make([]collate.WildcardPattern, len(extractor.ColumnNamePatterns)) + for i, pattern := range extractor.ColumnNamePatterns { + columnsRegexp[i] = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + columnsRegexp[i].Compile(pattern, byte('\\')) + } + } + } +ForColumnsTag: for i, col := range tbl.Columns { if col.Hidden { continue } + if !extractor.SkipRequest { + if tableSchemaFilterEnable && !extractor.TableSchema.Exist(schema.Name.L) { + continue + } + if tableNameFilterEnable && !extractor.TableName.Exist(tbl.Name.L) { + continue + } + if columnsFilterEnable && !extractor.ColumnName.Exist(col.Name.L) { + continue + } + for _, re := range tableSchemaRegexp { + if !re.DoMatch(schema.Name.L) { + continue ForColumnsTag + } + } + for _, re := range tableNameRegexp { + if !re.DoMatch(tbl.Name.L) { + continue ForColumnsTag + } + } + for _, re := range columnsRegexp { + if !re.DoMatch(col.Name.L) { + continue ForColumnsTag + } + } + } + var charMaxLen, charOctLen, numericPrecision, numericScale, datetimePrecision interface{} colLen, decimal := col.Flen, col.Decimal defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(col.Tp) @@ -750,6 +794,11 @@ func (e *hugeMemTableRetriever) dataForColumnsInTable(ctx context.Context, sctx var columnDefault interface{} if columnDesc.DefaultValue != nil { columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue) + if col.Tp == mysql.TypeBit { + defaultStr := fmt.Sprintf("%v", columnDesc.DefaultValue) + defaultValBinaryLiteral := types.BinaryLiteral(defaultStr) + columnDefault = defaultValBinaryLiteral.ToBitLiteralString(true) + } } record := types.MakeDatums( infoschema.CatalogVal, // TABLE_CATALOG @@ -837,7 +886,6 @@ func (e *memtableRetriever) setDataFromPartitions(ctx context.Context, sctx sess nil, // TABLESPACE_NAME nil, // TIDB_PARTITION_ID nil, // TIDB_PLACEMENT_POLICY_NAME - nil, // TIDB_DIRECT_PLACEMENT ) rows = append(rows, record) } else { @@ -894,13 +942,10 @@ func (e *memtableRetriever) setDataFromPartitions(ctx context.Context, sctx sess partitionExpr = buf.String() } - var policyName, directPlacement interface{} + var policyName interface{} if pi.PlacementPolicyRef != nil { policyName = pi.PlacementPolicyRef.Name.O } - if pi.DirectPlacementOpts != nil { - directPlacement = pi.DirectPlacementOpts.String() - } record := types.MakeDatums( infoschema.CatalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA @@ -929,7 +974,6 @@ func (e *memtableRetriever) setDataFromPartitions(ctx context.Context, sctx sess nil, // TABLESPACE_NAME pi.ID, // TIDB_PARTITION_ID policyName, // TIDB_PLACEMENT_POLICY_NAME - directPlacement, // TIDB_DIRECT_PLACEMENT ) rows = append(rows, record) } @@ -1160,7 +1204,10 @@ func (e *DDLJobsReaderExec) Next(ctx context.Context, req *chunk.Chunk) error { num := mathutil.Min(req.Capacity(), len(e.runningJobs)-e.cursor) for i := e.cursor; i < e.cursor+num; i++ { e.appendJobToChunk(req, e.runningJobs[i], checker) - req.AppendString(11, e.runningJobs[i].Query) + req.AppendString(12, e.runningJobs[i].Query) + for range e.runningJobs[i].MultiSchemaInfo.SubJobs { + req.AppendString(12, e.runningJobs[i].Query) + } } e.cursor += num count += num @@ -1175,7 +1222,12 @@ func (e *DDLJobsReaderExec) Next(ctx context.Context, req *chunk.Chunk) error { } for _, job := range e.cacheJobs { e.appendJobToChunk(req, job, checker) - req.AppendString(11, job.Query) + req.AppendString(12, job.Query) + if job.Type == model.ActionMultiSchemaChange { + for range job.MultiSchemaInfo.SubJobs { + req.AppendString(12, job.Query) + } + } } e.cursor += len(e.cacheJobs) } @@ -1438,7 +1490,7 @@ func keyColumnUsageInTable(schema *model.DBInfo, table *model.TableInfo) [][]typ return rows } -func (e *memtableRetriever) setDataForTiKVRegionStatus(ctx sessionctx.Context) error { +func (e *memtableRetriever) setDataForTiKVRegionStatus(ctx sessionctx.Context) (err error) { tikvStore, ok := ctx.GetStore().(helper.Storage) if !ok { return errors.New("Information about TiKV region status can be gotten only when the storage is TiKV") @@ -1447,24 +1499,62 @@ func (e *memtableRetriever) setDataForTiKVRegionStatus(ctx sessionctx.Context) e Store: tikvStore, RegionCache: tikvStore.GetRegionCache(), } - regionsInfo, err := tikvHelper.GetRegionsInfo() - if err != nil { - return err + requestByTableRange := false + allRegionsInfo := helper.NewRegionsInfo() + if e.extractor != nil { + extractor, ok := e.extractor.(*plannercore.TiKVRegionStatusExtractor) + if ok && len(extractor.GetTablesID()) > 0 { + for _, tableID := range extractor.GetTablesID() { + regionsInfo, err := e.getRegionsInfoForSingleTable(tikvHelper, tableID) + if err != nil { + return err + } + allRegionsInfo = allRegionsInfo.Merge(regionsInfo) + } + requestByTableRange = true + } + } + if !requestByTableRange { + allRegionsInfo, err = tikvHelper.GetRegionsInfo() + if err != nil { + return err + } } allSchemas := ctx.GetInfoSchema().(infoschema.InfoSchema).AllSchemas() - tableInfos := tikvHelper.GetRegionsTableInfo(regionsInfo, allSchemas) - for i := range regionsInfo.Regions { - tableList := tableInfos[regionsInfo.Regions[i].ID] + tableInfos := tikvHelper.GetRegionsTableInfo(allRegionsInfo, allSchemas) + for i := range allRegionsInfo.Regions { + tableList := tableInfos[allRegionsInfo.Regions[i].ID] if len(tableList) == 0 { - e.setNewTiKVRegionStatusCol(®ionsInfo.Regions[i], nil) + e.setNewTiKVRegionStatusCol(&allRegionsInfo.Regions[i], nil) } for j := range tableList { - e.setNewTiKVRegionStatusCol(®ionsInfo.Regions[i], &tableList[j]) + e.setNewTiKVRegionStatusCol(&allRegionsInfo.Regions[i], &tableList[j]) } } return nil } +func (e *memtableRetriever) getRegionsInfoForSingleTable(helper *helper.Helper, tableID int64) (*helper.RegionsInfo, error) { + sk, ek := tablecodec.GetTableHandleKeyRange(tableID) + sRegion, err := helper.GetRegionByKey(codec.EncodeBytes(nil, sk)) + if err != nil { + return nil, err + } + eRegion, err := helper.GetRegionByKey(codec.EncodeBytes(nil, ek)) + if err != nil { + return nil, err + } + sk, err = hex.DecodeString(sRegion.StartKey) + if err != nil { + return nil, err + } + ek, err = hex.DecodeString(eRegion.EndKey) + if err != nil { + return nil, err + } + return helper.GetRegionsInfoByRange(sk, ek) +} + func (e *memtableRetriever) setNewTiKVRegionStatusCol(region *helper.RegionInfo, table *helper.TableInfo) { row := make([]types.Datum, len(infoschema.TableTiKVRegionStatusCols)) row[0].SetInt64(region.ID) @@ -1481,6 +1571,8 @@ func (e *memtableRetriever) setNewTiKVRegionStatusCol(region *helper.RegionInfo, } else { row[6].SetInt64(0) } + } else { + row[6].SetInt64(0) } row[9].SetInt64(region.Epoch.ConfVer) row[10].SetInt64(region.Epoch.Version) @@ -1495,63 +1587,6 @@ func (e *memtableRetriever) setNewTiKVRegionStatusCol(region *helper.RegionInfo, e.rows = append(e.rows, row) } -func (e *memtableRetriever) setDataForTikVRegionPeers(ctx sessionctx.Context) error { - tikvStore, ok := ctx.GetStore().(helper.Storage) - if !ok { - return errors.New("Information about TiKV region status can be gotten only when the storage is TiKV") - } - tikvHelper := &helper.Helper{ - Store: tikvStore, - RegionCache: tikvStore.GetRegionCache(), - } - regionsInfo, err := tikvHelper.GetRegionsInfo() - if err != nil { - return err - } - for i := range regionsInfo.Regions { - e.setNewTiKVRegionPeersCols(®ionsInfo.Regions[i]) - } - return nil -} - -func (e *memtableRetriever) setNewTiKVRegionPeersCols(region *helper.RegionInfo) { - records := make([][]types.Datum, 0, len(region.Peers)) - pendingPeerIDSet := set.NewInt64Set() - for _, peer := range region.PendingPeers { - pendingPeerIDSet.Insert(peer.ID) - } - downPeerMap := make(map[int64]int64, len(region.DownPeers)) - for _, peerStat := range region.DownPeers { - downPeerMap[peerStat.Peer.ID] = peerStat.DownSec - } - for _, peer := range region.Peers { - row := make([]types.Datum, len(infoschema.TableTiKVRegionPeersCols)) - row[0].SetInt64(region.ID) - row[1].SetInt64(peer.ID) - row[2].SetInt64(peer.StoreID) - if peer.IsLearner { - row[3].SetInt64(1) - } else { - row[3].SetInt64(0) - } - if peer.ID == region.Leader.ID { - row[4].SetInt64(1) - } else { - row[4].SetInt64(0) - } - if downSec, ok := downPeerMap[peer.ID]; ok { - row[5].SetString(downPeer, mysql.DefaultCollationName) - row[6].SetInt64(downSec) - } else if pendingPeerIDSet.Exist(peer.ID) { - row[5].SetString(pendingPeer, mysql.DefaultCollationName) - } else { - row[5].SetString(normalPeer, mysql.DefaultCollationName) - } - records = append(records, row) - } - e.rows = append(e.rows, records...) -} - const ( normalPeer = "NORMAL" pendingPeer = "PENDING" @@ -1654,6 +1689,18 @@ func (e *memtableRetriever) setDataFromTableConstraints(ctx sessionctx.Context, ) rows = append(rows, record) } + // TiDB includes foreign key information for compatibility but foreign keys are not yet enforced. + for _, fk := range tbl.ForeignKeys { + record := types.MakeDatums( + infoschema.CatalogVal, // CONSTRAINT_CATALOG + schema.Name.O, // CONSTRAINT_SCHEMA + fk.Name.O, // CONSTRAINT_NAME + schema.Name.O, // TABLE_SCHEMA + tbl.Name.O, // TABLE_NAME + infoschema.ForeignKeyType, // CONSTRAINT_TYPE + ) + rows = append(rows, record) + } } } e.rows = rows @@ -1781,7 +1828,7 @@ func (e *tableStorageStatsRetriever) setDataForTableStorageStats(ctx sessionctx. for e.curTable < len(e.initialTables) && count < 1024 { table := e.initialTables[e.curTable] tableID := table.ID - err := e.helper.GetPDRegionStats(tableID, &e.stats) + err := e.helper.GetPDRegionStats(tableID, &e.stats, false) if err != nil { return nil, err } @@ -1805,10 +1852,11 @@ func (e *tableStorageStatsRetriever) setDataForTableStorageStats(ctx sessionctx. } func (e *memtableRetriever) setDataFromSessionVar(ctx sessionctx.Context) error { - var rows [][]types.Datum var err error sessionVars := ctx.GetSessionVars() - for _, v := range variable.GetSysVars() { + sysVars := variable.GetSysVars() + rows := make([][]types.Datum, 0, len(sysVars)) + for _, v := range sysVars { var value string value, err = variable.GetSessionOrGlobalSystemVar(sessionVars, v.Name) if err != nil { @@ -1822,41 +1870,70 @@ func (e *memtableRetriever) setDataFromSessionVar(ctx sessionctx.Context) error } // dataForAnalyzeStatusHelper is a helper function which can be used in show_stats.go -func dataForAnalyzeStatusHelper(sctx sessionctx.Context) (rows [][]types.Datum) { +func dataForAnalyzeStatusHelper(sctx sessionctx.Context) (rows [][]types.Datum, err error) { + const maxAnalyzeJobs = 30 + const sql = "SELECT table_schema, table_name, partition_name, job_info, processed_rows, CONVERT_TZ(start_time, @@TIME_ZONE, '+00:00'), CONVERT_TZ(end_time, @@TIME_ZONE, '+00:00'), state, fail_reason, instance, process_id FROM mysql.analyze_jobs ORDER BY update_time DESC LIMIT %?" + exec := sctx.(sqlexec.RestrictedSQLExecutor) + chunkRows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, sql, maxAnalyzeJobs) + if err != nil { + return nil, err + } checker := privilege.GetPrivilegeManager(sctx) - for _, job := range statistics.GetAllAnalyzeJobs() { - job.Lock() + for _, chunkRow := range chunkRows { + dbName := chunkRow.GetString(0) + tableName := chunkRow.GetString(1) + if checker != nil && !checker.RequestVerification(sctx.GetSessionVars().ActiveRoles, dbName, tableName, "", mysql.AllPrivMask) { + continue + } + partitionName := chunkRow.GetString(2) + jobInfo := chunkRow.GetString(3) + processedRows := chunkRow.GetInt64(4) var startTime, endTime interface{} - if job.StartTime.IsZero() { - startTime = nil - } else { - startTime = types.NewTime(types.FromGoTime(job.StartTime), mysql.TypeDatetime, 0) + if !chunkRow.IsNull(5) { + t, err := chunkRow.GetTime(5).GoTime(time.UTC) + if err != nil { + return nil, err + } + startTime = types.NewTime(types.FromGoTime(t.In(sctx.GetSessionVars().TimeZone)), mysql.TypeDatetime, 0) } - if job.EndTime.IsZero() { - endTime = nil - } else { - endTime = types.NewTime(types.FromGoTime(job.EndTime), mysql.TypeDatetime, 0) - } - if checker == nil || checker.RequestVerification(sctx.GetSessionVars().ActiveRoles, job.DBName, job.TableName, "", mysql.AllPrivMask) { - rows = append(rows, types.MakeDatums( - job.DBName, // TABLE_SCHEMA - job.TableName, // TABLE_NAME - job.PartitionName, // PARTITION_NAME - job.JobInfo, // JOB_INFO - job.RowCount, // ROW_COUNT - startTime, // START_TIME - endTime, // END_TIME - job.State, // STATE - )) - } - job.Unlock() + if !chunkRow.IsNull(6) { + t, err := chunkRow.GetTime(6).GoTime(time.UTC) + if err != nil { + return nil, err + } + endTime = types.NewTime(types.FromGoTime(t.In(sctx.GetSessionVars().TimeZone)), mysql.TypeDatetime, 0) + } + state := chunkRow.GetEnum(7).String() + var failReason interface{} + if !chunkRow.IsNull(8) { + failReason = chunkRow.GetString(8) + } + instance := chunkRow.GetString(9) + var procID interface{} + if !chunkRow.IsNull(10) { + procID = chunkRow.GetUint64(10) + } + rows = append(rows, types.MakeDatums( + dbName, // TABLE_SCHEMA + tableName, // TABLE_NAME + partitionName, // PARTITION_NAME + jobInfo, // JOB_INFO + processedRows, // ROW_COUNT + startTime, // START_TIME + endTime, // END_TIME + state, // STATE + failReason, // FAIL_REASON + instance, // INSTANCE + procID, // PROCESS_ID + )) } return } // setDataForAnalyzeStatus gets all the analyze jobs. -func (e *memtableRetriever) setDataForAnalyzeStatus(sctx sessionctx.Context) { - e.rows = dataForAnalyzeStatusHelper(sctx) +func (e *memtableRetriever) setDataForAnalyzeStatus(sctx sessionctx.Context) (err error) { + e.rows, err = dataForAnalyzeStatusHelper(sctx) + return } // setDataForPseudoProfiling returns pseudo data for table profiling when system variable `profiling` is set to `ON`. @@ -2102,7 +2179,7 @@ func (e *stmtSummaryTableRetriever) retrieve(ctx context.Context, sctx sessionct } } user := sctx.GetSessionVars().User - reader := stmtsummary.NewStmtSummaryReader(user, hasPriv(sctx, mysql.ProcessPriv), e.columns, instanceAddr) + reader := stmtsummary.NewStmtSummaryReader(user, hasPriv(sctx, mysql.ProcessPriv), e.columns, instanceAddr, sctx.GetSessionVars().StmtCtx.TimeZone) if e.extractor.Enable { checker := stmtsummary.NewStmtSummaryChecker(e.extractor.Digests) reader.SetChecker(checker) @@ -2513,6 +2590,7 @@ func (r *deadlocksTableRetriever) retrieve(ctx context.Context, sctx sessionctx. type hugeMemTableRetriever struct { dummyCloser + extractor *plannercore.ColumnsTableExtractor table *model.TableInfo columns []*model.ColumnInfo retrieved bool @@ -2541,7 +2619,7 @@ func (e *hugeMemTableRetriever) retrieve(ctx context.Context, sctx sessionctx.Co var err error switch e.table.Name.O { case infoschema.TableColumns: - err = e.setDataForColumns(ctx, sctx) + err = e.setDataForColumns(ctx, sctx, e.extractor) } if err != nil { return nil, err @@ -2615,58 +2693,77 @@ type tiflashInstanceInfo struct { } func (e *TiFlashSystemTableRetriever) initialize(sctx sessionctx.Context, tiflashInstances set.StringSet) error { - store := sctx.GetStore() - if etcd, ok := store.(kv.EtcdBackend); ok { - var addrs []string - var err error - if addrs, err = etcd.EtcdAddrs(); err != nil { + storeInfo, err := infoschema.GetStoreServerInfo(sctx) + if err != nil { + return err + } + + for _, info := range storeInfo { + if info.ServerType != kv.TiFlash.Name() { + continue + } + info.ResolveLoopBackAddr() + if len(tiflashInstances) > 0 && !tiflashInstances.Exist(info.Address) { + continue + } + hostAndStatusPort := strings.Split(info.StatusAddr, ":") + if len(hostAndStatusPort) != 2 { + return errors.Errorf("node status addr: %s format illegal", info.StatusAddr) + } + // fetch tiflash config + configURL := fmt.Sprintf("%s://%s/config", util.InternalHTTPSchema(), info.StatusAddr) + resp, err := util.InternalHTTPClient().Get(configURL) + if err != nil { + sctx.GetSessionVars().StmtCtx.AppendWarning(err) + continue + } + if resp.StatusCode != http.StatusOK { + return errors.Errorf("request %s failed: %s", configURL, resp.Status) + } + // parse http_port or https_port from the fetched config + var nestedConfig map[string]interface{} + if err = json.NewDecoder(resp.Body).Decode(&nestedConfig); err != nil { return err } - if addrs != nil { - domainFromCtx := domain.GetDomain(sctx) - if domainFromCtx != nil { - cli := domainFromCtx.GetEtcdClient() - prefix := "/tiflash/cluster/http_port/" - kv := clientv3.NewKV(cli) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - resp, err := kv.Get(ctx, prefix, clientv3.WithPrefix()) - cancel() - if err != nil { - return errors.Trace(err) - } - for _, ev := range resp.Kvs { - id := string(ev.Key)[len(prefix):] - if len(tiflashInstances) > 0 && !tiflashInstances.Exist(id) { - continue - } - url := fmt.Sprintf("%s://%s", util.InternalHTTPSchema(), ev.Value) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return errors.Trace(err) - } - resp, err := util.InternalHTTPClient().Do(req) - if err != nil { - sctx.GetSessionVars().StmtCtx.AppendWarning(err) - continue - } - resp.Body.Close() - e.instanceInfos = append(e.instanceInfos, tiflashInstanceInfo{ - id: id, - url: url, - }) - e.instanceCount += 1 - } - e.initialized = true - return nil + if engineStoreConfig, ok := nestedConfig["engine-store"]; ok { + foundPort := false + var port interface{} + portProtocol := "" + if httpPort, ok := engineStoreConfig.(map[string]interface{})["http_port"]; ok { + foundPort = true + port = httpPort + portProtocol = "http" + } else if httpsPort, ok := engineStoreConfig.(map[string]interface{})["https_port"]; ok { + foundPort = true + port = httpsPort + portProtocol = "https" + } + if !foundPort { + return errors.Errorf("engine-store.http_port/https_port not found in server %s", info.Address) + } + switch portValue := port.(type) { + case float64: + e.instanceInfos = append(e.instanceInfos, tiflashInstanceInfo{ + id: info.Address, + url: fmt.Sprintf("%s://%s:%d", portProtocol, hostAndStatusPort[0], int(portValue)), + }) + e.instanceCount += 1 + default: + return errors.Errorf("engine-store.http_port value(%p) unexpected in server %s", port, info.Address) } + } else { + return errors.Errorf("engine-store config not found in server %s", info.Address) + } + if err = resp.Body.Close(); err != nil { + return err } - return errors.Errorf("Etcd addrs not found") } - return errors.Errorf("%T not an etcd backend", store) + e.initialized = true + return nil } func (e *TiFlashSystemTableRetriever) dataForTiFlashSystemTables(ctx sessionctx.Context, tidbDatabases string, tidbTables string) ([][]types.Datum, error) { - var columnNames []string + var columnNames []string // nolint: prealloc for _, c := range e.outputCols { if c.Name.O == "TIFLASH_INSTANCE" { continue @@ -2707,7 +2804,7 @@ func (e *TiFlashSystemTableRetriever) dataForTiFlashSystemTables(ctx sessionctx. return nil, errors.Trace(err) } records := strings.Split(string(body), "\n") - var rows [][]types.Datum + rows := make([][]types.Datum, 0, len(records)) for _, record := range records { if len(record) == 0 { continue @@ -2756,10 +2853,10 @@ func (e *TiFlashSystemTableRetriever) dataForTiFlashSystemTables(ctx sessionctx. return rows, nil } -func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context) error { +func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context, is infoschema.InfoSchema) error { checker := privilege.GetPrivilegeManager(ctx) - var rows [][]types.Datum rules, err := infosync.GetAllLabelRules(context.TODO()) + skipValidateTable := false failpoint.Inject("mockOutputOfAttributes", func() { convert := func(i interface{}) []interface{} { return []interface{}{i} @@ -2776,17 +2873,29 @@ func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context) error { }, } err = nil + skipValidateTable = true }) if err != nil { return errors.Wrap(err, "get the label rules failed") } + + rows := make([][]types.Datum, 0, len(rules)) for _, rule := range rules { skip := true - dbName, tableName, err := checkRule(rule) + dbName, tableName, partitionName, err := checkRule(rule) + if err != nil { + return err + } + tableID, err := decodeTableIDFromRule(rule) if err != nil { return err } + + if !skipValidateTable && tableOrPartitionNotExist(dbName, tableName, partitionName, is, tableID) { + continue + } + if tableName != "" && dbName != "" && (checker == nil || checker.RequestVerification(ctx.GetSessionVars().ActiveRoles, dbName, tableName, "", mysql.SelectPriv)) { skip = false } @@ -2817,26 +2926,28 @@ func (e *memtableRetriever) setDataForAttributes(ctx sessionctx.Context) error { return nil } -func (e *memtableRetriever) setDataFromPlacementRules(ctx context.Context, sctx sessionctx.Context, schemas []*model.DBInfo) error { - checker := privilege.GetPrivilegeManager(sctx) - is := sctx.GetInfoSchema().(infoschema.InfoSchema) - var rows [][]types.Datum - +func (e *memtableRetriever) setDataFromPlacementPolicies(sctx sessionctx.Context) error { + is := sessiontxn.GetTxnManager(sctx).GetTxnInfoSchema() + placementPolicies := is.AllPlacementPolicies() + rows := make([][]types.Datum, 0, len(placementPolicies)) // Get global PLACEMENT POLICIES // Currently no privileges needed for seeing global PLACEMENT POLICIES! - for _, policy := range is.AllPlacementPolicies() { + for _, policy := range placementPolicies { // Currently we skip converting syntactic sugar. We might revisit this decision still in the future // I.e.: if PrimaryRegion or Regions are set, // also convert them to LeaderConstraints and FollowerConstraints // for better user experience searching for particular constraints + // Followers == 0 means not set, so the default value 2 will be used + followerCnt := policy.PlacementSettings.Followers + if followerCnt == 0 { + followerCnt = 2 + } + row := types.MakeDatums( policy.ID, infoschema.CatalogVal, // CATALOG policy.Name.O, // Policy Name - nil, // dbName, // SCHEMA - nil, // tbName, // TABLE - nil, // ptName, // PARTITION policy.PlacementSettings.PrimaryRegion, policy.PlacementSettings.Regions, policy.PlacementSettings.Constraints, @@ -2844,109 +2955,16 @@ func (e *memtableRetriever) setDataFromPlacementRules(ctx context.Context, sctx policy.PlacementSettings.FollowerConstraints, policy.PlacementSettings.LearnerConstraints, policy.PlacementSettings.Schedule, - policy.PlacementSettings.Followers, + followerCnt, policy.PlacementSettings.Learners, ) rows = append(rows, row) } - - // Get DIRECT PLACEMENT from schemas/tables/partitions - for _, schema := range schemas { - // Traverse all schemas and all tables (and eventually all partitions) - // to extract any Direct Placement information on Schema/Table/Partition. - // Currently there is no filtering during traversal implemented for queries like - // SELECT * FROM placment_rules WHERE SCHEMA_NAME IN ('schema1', 'schema2') - // or SELECT * FROM placment_rules WHERE SCHEMA_NAME = 'schema1' AND TABLE_NAME = 'table1' - anyTablePriv := false - for _, table := range schema.Tables { - if table.IsView() { - continue - } - // TODO: Filter on table, to avoid iterating over every table if SELECT * FROM placment_rules WHERE TABLE_NAME IN ('t1', 't2') - // Any privilege on the schema or a table within the schema should allow showing the direct placement rules for that schema (on schema level) - if checker != nil && !checker.RequestVerification(sctx.GetSessionVars().ActiveRoles, schema.Name.L, table.Name.L, "", mysql.AllPrivMask) { - continue - } - anyTablePriv = true - if partInfo := table.GetPartitionInfo(); partInfo != nil { - for _, pi := range partInfo.Definitions { - if pi.DirectPlacementOpts != nil { - record := types.MakeDatums( - nil, // PLACEMENT POLICY ID, null since direct placement - infoschema.CatalogVal, // CATALOG - nil, // PLACEMENT POLICY, null since direct placement - schema.Name.O, // SCHEMA - table.Name.O, // TABLE - pi.Name.O, // PARTITION - pi.DirectPlacementOpts.PrimaryRegion, - pi.DirectPlacementOpts.Regions, - pi.DirectPlacementOpts.Constraints, - pi.DirectPlacementOpts.LeaderConstraints, - pi.DirectPlacementOpts.FollowerConstraints, - pi.DirectPlacementOpts.LearnerConstraints, - pi.DirectPlacementOpts.Schedule, - pi.DirectPlacementOpts.Followers, - pi.DirectPlacementOpts.Learners, - ) - rows = append(rows, record) - } - } - } - if table.DirectPlacementOpts == nil { - continue - } - record := types.MakeDatums( - nil, // PLACEMENT POLICY ID, null since direct placement - infoschema.CatalogVal, // CATALOG - nil, // PLACEMENT POLICY, null since direct placement - schema.Name.O, // SCHEMA - table.Name.O, // TABLE - nil, // PARTITION - table.DirectPlacementOpts.PrimaryRegion, - table.DirectPlacementOpts.Regions, - table.DirectPlacementOpts.Constraints, - table.DirectPlacementOpts.LeaderConstraints, - table.DirectPlacementOpts.FollowerConstraints, - table.DirectPlacementOpts.LearnerConstraints, - table.DirectPlacementOpts.Schedule, - table.DirectPlacementOpts.Followers, - table.DirectPlacementOpts.Learners, - ) - rows = append(rows, record) - } - // Any privilege on global level, the schema or any table within that schema - // should allow showing the direct placement rules for that schema (on schema level) - if !anyTablePriv && checker != nil && !checker.RequestVerification(sctx.GetSessionVars().ActiveRoles, schema.Name.L, "", "", mysql.AllPrivMask) { - continue - } - if schema.DirectPlacementOpts == nil { - continue - } - record := types.MakeDatums( - nil, // PLACEMENT POLICY ID, null since direct placement - infoschema.CatalogVal, // CATALOG - nil, // PLACEMENT POLICY, null since direct placement - schema.Name.O, // SCHEMA - nil, // TABLE - nil, // PARTITION - schema.DirectPlacementOpts.PrimaryRegion, - schema.DirectPlacementOpts.Regions, - schema.DirectPlacementOpts.Constraints, - schema.DirectPlacementOpts.LeaderConstraints, - schema.DirectPlacementOpts.FollowerConstraints, - schema.DirectPlacementOpts.LearnerConstraints, - schema.DirectPlacementOpts.Schedule, - schema.DirectPlacementOpts.Followers, - schema.DirectPlacementOpts.Learners, - ) - rows = append(rows, record) - } - e.rows = rows return nil } -func checkRule(rule *label.Rule) (dbName, tableName string, err error) { +func checkRule(rule *label.Rule) (dbName, tableName string, partitionName string, err error) { s := strings.Split(rule.ID, "/") if len(s) < 3 { err = errors.Errorf("invalid label rule ID: %v", rule.ID) @@ -2966,5 +2984,55 @@ func checkRule(rule *label.Rule) (dbName, tableName string, err error) { } dbName = s[1] tableName = s[2] + if len(s) > 3 { + partitionName = s[3] + } return } + +func decodeTableIDFromRule(rule *label.Rule) (tableID int64, err error) { + if len(rule.Data) == 0 { + err = errors.New(fmt.Sprintf("there is no data in rule %s", rule.ID)) + return + } + data := rule.Data[0] + dataMap, ok := data.(map[string]interface{}) + if !ok { + err = errors.New(fmt.Sprintf("get the label rules %s failed", rule.ID)) + return + } + key, err := hex.DecodeString(fmt.Sprintf("%s", dataMap["start_key"])) + if err != nil { + err = errors.New(fmt.Sprintf("decode key from start_key %s in rule %s failed", dataMap["start_key"], rule.ID)) + return + } + _, bs, err := codec.DecodeBytes(key, nil) + if err == nil { + key = bs + } + tableID = tablecodec.DecodeTableID(key) + if tableID == 0 { + err = errors.New(fmt.Sprintf("decode tableID from key %s in rule %s failed", key, rule.ID)) + return + } + return +} + +func tableOrPartitionNotExist(dbName string, tableName string, partitionName string, is infoschema.InfoSchema, tableID int64) (tableNotExist bool) { + if len(partitionName) == 0 { + curTable, _ := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tableName)) + if curTable == nil { + return true + } + curTableID := curTable.Meta().ID + if curTableID != tableID { + return true + } + } else { + _, _, partInfo := is.FindTableByPartitionID(tableID) + if partInfo == nil { + return true + } + } + return false +} diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index 53fd409f0fd2a..5bc5c79749093 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -15,104 +15,31 @@ package executor_test import ( - "crypto/tls" "fmt" - "net" - "net/http/httptest" "strconv" "strings" + "testing" "time" - "github.com/gorilla/mux" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" - "github.com/pingcap/fn" - "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/server" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/statistics/handle" - "github.com/pingcap/tidb/store/helper" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/pdapi" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/stringutil" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" - "google.golang.org/grpc" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testInfoschemaTableSuite{}) - -// this SerialSuites is used to solve the data race caused by TableStatsCacheExpiry, -// if your test not change the TableStatsCacheExpiry variable, please use testInfoschemaTableSuite for test. -var _ = SerialSuites(&testInfoschemaTableSerialSuite{}) - -var _ = SerialSuites(&inspectionSuite{}) - -type testInfoschemaTableSuiteBase struct { - store kv.Storage - dom *domain.Domain -} - -type testInfoschemaTableSuite struct { - testInfoschemaTableSuiteBase -} - -type testInfoschemaTableSerialSuite struct { - testInfoschemaTableSuiteBase -} - -type inspectionSuite struct { - store kv.Storage - dom *domain.Domain -} - -func (s *testInfoschemaTableSuiteBase) SetUpSuite(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - s.store = store - s.dom = dom - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionLog - }) -} - -func (s *testInfoschemaTableSuiteBase) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *inspectionSuite) SetUpSuite(c *C) { - testleak.BeforeTest() - - var err error - s.store, err = mockstore.NewMockStore() - c.Assert(err, IsNil) - session.DisableStats4Test() - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} - -func (s *inspectionSuite) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() - testleak.AfterTest(c)() -} - -func (s *inspectionSuite) TestInspectionTables(c *C) { - c.Skip("unstable, skip it and fix it before 20210624") - tk := testkit.NewTestKit(c, s.store) +func TestInspectionTables(t *testing.T) { + t.Skip("unstable, skip it and fix it before 20210624") + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) instances := []string{ "pd,127.0.0.1:11080,127.0.0.1:10080,mock-version,mock-githash,0", "tidb,127.0.0.1:11080,127.0.0.1:10080,mock-version,mock-githash,1001", @@ -120,8 +47,8 @@ func (s *inspectionSuite) TestInspectionTables(c *C) { } fpName := "github.com/pingcap/tidb/infoschema/mockClusterInfo" fpExpr := `return("` + strings.Join(instances, ";") + `")` - c.Assert(failpoint.Enable(fpName, fpExpr), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, fpExpr)) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() tk.MustQuery("select type, instance, status_address, version, git_hash, server_id from information_schema.cluster_info").Check(testkit.Rows( "pd 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 0", @@ -131,14 +58,14 @@ func (s *inspectionSuite) TestInspectionTables(c *C) { // enable inspection mode inspectionTableCache := map[string]variable.TableSnapshot{} - tk.Se.GetSessionVars().InspectionTableCache = inspectionTableCache + tk.Session().GetSessionVars().InspectionTableCache = inspectionTableCache tk.MustQuery("select type, instance, status_address, version, git_hash, server_id from information_schema.cluster_info").Check(testkit.Rows( "pd 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 0", "tidb 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 1001", "tikv 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 0", )) - c.Assert(inspectionTableCache["cluster_info"].Err, IsNil) - c.Assert(len(inspectionTableCache["cluster_info"].Rows), DeepEquals, 3) + require.NoError(t, inspectionTableCache["cluster_info"].Err) + require.Len(t, inspectionTableCache["cluster_info"].Rows, 3) // check whether is obtain data from cache at the next time inspectionTableCache["cluster_info"].Rows[0][0].SetString("modified-pd", mysql.DefaultCollationName) @@ -147,35 +74,39 @@ func (s *inspectionSuite) TestInspectionTables(c *C) { "tidb 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 1001", "tikv 127.0.0.1:11080 127.0.0.1:10080 mock-version mock-githash 0", )) - tk.Se.GetSessionVars().InspectionTableCache = nil + tk.Session().GetSessionVars().InspectionTableCache = nil } -func (s *testInfoschemaTableSuite) TestProfiling(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestProfiling(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select * from information_schema.profiling").Check(testkit.Rows()) tk.MustExec("set @@profiling=1") tk.MustQuery("select * from information_schema.profiling").Check(testkit.Rows("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0")) } -func (s *testInfoschemaTableSuite) TestSchemataTables(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSchemataTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select * from information_schema.SCHEMATA where schema_name='mysql';").Check( - testkit.Rows("def mysql utf8mb4 utf8mb4_bin ")) + testkit.Rows("def mysql utf8mb4 utf8mb4_bin ")) // Test the privilege of new user for information_schema.schemata. tk.MustExec("create user schemata_tester") - schemataTester := testkit.NewTestKit(c, s.store) + schemataTester := testkit.NewTestKit(t, store) schemataTester.MustExec("use information_schema") - c.Assert(schemataTester.Se.Auth(&auth.UserIdentity{ + require.True(t, schemataTester.Session().Auth(&auth.UserIdentity{ Username: "schemata_tester", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) schemataTester.MustQuery("select count(*) from information_schema.SCHEMATA;").Check(testkit.Rows("1")) schemataTester.MustQuery("select * from information_schema.SCHEMATA where schema_name='mysql';").Check( [][]interface{}{}) schemataTester.MustQuery("select * from information_schema.SCHEMATA where schema_name='INFORMATION_SCHEMA';").Check( - testkit.Rows("def INFORMATION_SCHEMA utf8mb4 utf8mb4_bin ")) + testkit.Rows("def INFORMATION_SCHEMA utf8mb4 utf8mb4_bin ")) // Test the privilege of user with privilege of mysql for information_schema.schemata. tk.MustExec("CREATE ROLE r_mysql_priv;") @@ -184,59 +115,65 @@ func (s *testInfoschemaTableSuite) TestSchemataTables(c *C) { schemataTester.MustExec("set role r_mysql_priv") schemataTester.MustQuery("select count(*) from information_schema.SCHEMATA;").Check(testkit.Rows("2")) schemataTester.MustQuery("select * from information_schema.SCHEMATA;").Check( - testkit.Rows("def INFORMATION_SCHEMA utf8mb4 utf8mb4_bin ", "def mysql utf8mb4 utf8mb4_bin ")) + testkit.Rows("def INFORMATION_SCHEMA utf8mb4 utf8mb4_bin ", "def mysql utf8mb4 utf8mb4_bin ")) } -func (s *testInfoschemaTableSuite) TestTableIDAndIndexID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableIDAndIndexID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop table if exists test.t") tk.MustExec("create table test.t (a int, b int, primary key(a), key k1(b))") tk.MustQuery("select index_id from information_schema.tidb_indexes where table_schema = 'test' and table_name = 't'").Check(testkit.Rows("0", "1")) tblID, err := strconv.Atoi(tk.MustQuery("select tidb_table_id from information_schema.tables where table_schema = 'test' and table_name = 't'").Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(tblID, Greater, 0) + require.NoError(t, err) + require.Greater(t, tblID, 0) } -func (s *testInfoschemaTableSuite) TestSchemataCharacterSet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSchemataCharacterSet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE `foo` DEFAULT CHARACTER SET = 'utf8mb4'") tk.MustQuery("select default_character_set_name, default_collation_name FROM information_schema.SCHEMATA WHERE schema_name = 'foo'").Check( testkit.Rows("utf8mb4 utf8mb4_bin")) tk.MustExec("drop database `foo`") } -func (s *testInfoschemaTableSuite) TestViews(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestViews(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DEFINER='root'@'localhost' VIEW test.v1 AS SELECT 1") tk.MustQuery("select TABLE_COLLATION is null from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='VIEW'").Check(testkit.Rows("1")) tk.MustQuery("SELECT * FROM information_schema.views WHERE table_schema='test' AND table_name='v1'").Check(testkit.Rows("def test v1 SELECT 1 AS `1` CASCADED NO root@localhost DEFINER utf8mb4 utf8mb4_bin")) tk.MustQuery("SELECT table_catalog, table_schema, table_name, table_type, engine, version, row_format, table_rows, avg_row_length, data_length, max_data_length, index_length, data_free, auto_increment, update_time, check_time, table_collation, checksum, create_options, table_comment FROM information_schema.tables WHERE table_schema='test' AND table_name='v1'").Check(testkit.Rows("def test v1 VIEW VIEW")) } -func (s *testInfoschemaTableSuite) TestEngines(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustQuery("select * from information_schema.ENGINES;").Check(testkit.Rows("InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES")) +func TestColumnsTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (bit bit(10) DEFAULT b'100')") + tk.MustQuery("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't'").Check(testkit.Rows( + "def test t bit 1 b'100' YES bit 10 0 bit(10) unsigned select,insert,update,references ")) + tk.MustExec("drop table if exists t") } -func (s *testInfoschemaTableSuite) TestCharacterSetCollations(c *C) { - tk := testkit.NewTestKit(c, s.store) - - // The description column is not important - tk.MustQuery("SELECT default_collate_name, maxlen FROM information_schema.character_sets ORDER BY character_set_name").Check( - testkit.Rows("ascii_bin 1", "binary 1", "latin1_bin 1", "utf8_bin 3", "utf8mb4_bin 4")) - - // The is_default column is not important - // but the id's are used by client libraries and must be stable - tk.MustQuery("SELECT character_set_name, id, sortlen FROM information_schema.collations ORDER BY collation_name").Check( - testkit.Rows("ascii 65 1", "binary 63 1", "latin1 47 1", "utf8 83 1", "utf8mb4 46 1")) - - tk.MustQuery("select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY where COLLATION_NAME='utf8mb4_bin';").Check( - testkit.Rows("utf8mb4_bin utf8mb4")) +func TestEngines(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustQuery("select * from information_schema.ENGINES;").Check(testkit.Rows("InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES")) } // https://github.com/pingcap/tidb/issues/25467. -func (s *testInfoschemaTableSuite) TestDataTypesMaxLengthAndOctLength(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDataTypesMaxLengthAndOctLength(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_oct_length;") tk.MustExec("create database test_oct_length;") tk.MustExec("use test_oct_length;") @@ -268,8 +205,10 @@ func (s *testInfoschemaTableSuite) TestDataTypesMaxLengthAndOctLength(c *C) { } } -func (s *testInfoschemaTableSuite) TestDDLJobs(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDDLJobs(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists test_ddl_jobs") tk.MustQuery("select db_name, job_type from information_schema.DDL_JOBS limit 1").Check( testkit.Rows("test_ddl_jobs create schema")) @@ -288,12 +227,12 @@ func (s *testInfoschemaTableSuite) TestDDLJobs(c *C) { // Test the privilege of new user for information_schema.DDL_JOBS. tk.MustExec("create user DDL_JOBS_tester") - DDLJobsTester := testkit.NewTestKit(c, s.store) + DDLJobsTester := testkit.NewTestKit(t, store) DDLJobsTester.MustExec("use information_schema") - c.Assert(DDLJobsTester.Se.Auth(&auth.UserIdentity{ + require.True(t, DDLJobsTester.Session().Auth(&auth.UserIdentity{ Username: "DDL_JOBS_tester", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) // Test the privilege of user for information_schema.ddl_jobs. DDLJobsTester.MustQuery("select DB_NAME, TABLE_NAME from information_schema.DDL_JOBS where DB_NAME = 'test_ddl_jobs' and TABLE_NAME = 't';").Check( @@ -304,22 +243,31 @@ func (s *testInfoschemaTableSuite) TestDDLJobs(c *C) { DDLJobsTester.MustExec("set role r_priv") DDLJobsTester.MustQuery("select DB_NAME, TABLE_NAME from information_schema.DDL_JOBS where DB_NAME = 'test_ddl_jobs' and TABLE_NAME = 't';").Check( testkit.Rows("test_ddl_jobs t")) + + tk.MustExec("set @@global.tidb_enable_change_multi_schema = 1") + tk.MustExec("create table tt (a int);") + tk.MustExec("alter table tt add index t(a), add column b int") + tk.MustQuery("select db_name, table_name, job_type from information_schema.DDL_JOBS limit 3").Check( + testkit.Rows("test_ddl_jobs tt alter table multi-schema change", "test_ddl_jobs tt add index /* subjob */", "test_ddl_jobs tt add column /* subjob */")) + } -func (s *testInfoschemaTableSuite) TestKeyColumnUsage(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestKeyColumnUsage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='stats_meta' and COLUMN_NAME='table_id';").Check( testkit.Rows("def mysql tbl def mysql stats_meta table_id 1 ")) // test the privilege of new user for information_schema.table_constraints tk.MustExec("create user key_column_tester") - keyColumnTester := testkit.NewTestKit(c, s.store) + keyColumnTester := testkit.NewTestKit(t, store) keyColumnTester.MustExec("use information_schema") - c.Assert(keyColumnTester.Se.Auth(&auth.UserIdentity{ + require.True(t, keyColumnTester.Session().Auth(&auth.UserIdentity{ Username: "key_column_tester", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) keyColumnTester.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with privilege of mysql.gc_delete_range for information_schema.table_constraints @@ -327,19 +275,22 @@ func (s *testInfoschemaTableSuite) TestKeyColumnUsage(c *C) { tk.MustExec("GRANT ALL PRIVILEGES ON mysql.stats_meta TO r_stats_meta;") tk.MustExec("GRANT r_stats_meta TO key_column_tester;") keyColumnTester.MustExec("set role r_stats_meta") - c.Assert(len(keyColumnTester.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='stats_meta';").Rows()), Greater, 0) + rows := keyColumnTester.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='stats_meta';").Rows() + require.Greater(t, len(rows), 0) } -func (s *testInfoschemaTableSuite) TestUserPrivileges(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUserPrivileges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test the privilege of new user for information_schema.table_constraints tk.MustExec("create user constraints_tester") - constraintsTester := testkit.NewTestKit(c, s.store) + constraintsTester := testkit.NewTestKit(t, store) constraintsTester.MustExec("use information_schema") - c.Assert(constraintsTester.Se.Auth(&auth.UserIdentity{ + require.True(t, constraintsTester.Session().Auth(&auth.UserIdentity{ Username: "constraints_tester", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS WHERE TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with privilege of mysql.gc_delete_range for information_schema.table_constraints @@ -347,17 +298,18 @@ func (s *testInfoschemaTableSuite) TestUserPrivileges(c *C) { tk.MustExec("GRANT ALL PRIVILEGES ON mysql.gc_delete_range TO r_gc_delete_range;") tk.MustExec("GRANT r_gc_delete_range TO constraints_tester;") constraintsTester.MustExec("set role r_gc_delete_range") - c.Assert(len(constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Rows()), Greater, 0) + rows := constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Rows() + require.Greater(t, len(rows), 0) constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='tables_priv';").Check([][]interface{}{}) // test the privilege of new user for information_schema tk.MustExec("create user tester1") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use information_schema") - c.Assert(tk1.Se.Auth(&auth.UserIdentity{ + require.True(t, tk1.Session().Auth(&auth.UserIdentity{ Username: "tester1", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) tk1.MustQuery("select * from information_schema.STATISTICS WHERE TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with some privilege for information_schema @@ -365,15 +317,15 @@ func (s *testInfoschemaTableSuite) TestUserPrivileges(c *C) { tk.MustExec("CREATE ROLE r_columns_priv;") tk.MustExec("GRANT ALL PRIVILEGES ON mysql.columns_priv TO r_columns_priv;") tk.MustExec("GRANT r_columns_priv TO tester2;") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use information_schema") - c.Assert(tk2.Se.Auth(&auth.UserIdentity{ + require.True(t, tk2.Session().Auth(&auth.UserIdentity{ Username: "tester2", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) tk2.MustExec("set role r_columns_priv") - result := tk2.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';") - c.Assert(len(result.Rows()), Greater, 0) + rows = tk2.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';").Rows() + require.Greater(t, len(rows), 0) tk2.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='tables_priv' and COLUMN_NAME='Host';").Check( [][]interface{}{}) @@ -382,29 +334,31 @@ func (s *testInfoschemaTableSuite) TestUserPrivileges(c *C) { tk.MustExec("CREATE ROLE r_all_priv;") tk.MustExec("GRANT ALL PRIVILEGES ON mysql.* TO r_all_priv;") tk.MustExec("GRANT r_all_priv TO tester3;") - tk3 := testkit.NewTestKit(c, s.store) + tk3 := testkit.NewTestKit(t, store) tk3.MustExec("use information_schema") - c.Assert(tk3.Se.Auth(&auth.UserIdentity{ + require.True(t, tk3.Session().Auth(&auth.UserIdentity{ Username: "tester3", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) tk3.MustExec("set role r_all_priv") - result = tk3.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';") - c.Assert(len(result.Rows()), Greater, 0) - result = tk3.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='tables_priv' and COLUMN_NAME='Host';") - c.Assert(len(result.Rows()), Greater, 0) + rows = tk3.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';").Rows() + require.Greater(t, len(rows), 0) + rows = tk3.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='tables_priv' and COLUMN_NAME='Host';").Rows() + require.Greater(t, len(rows), 0) } -func (s *testInfoschemaTableSuite) TestUserPrivilegesTable(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk1 := testkit.NewTestKit(c, s.store) +func TestUserPrivilegesTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk1 := testkit.NewTestKit(t, store) // test the privilege of new user for information_schema.user_privileges tk.MustExec("create user usageuser") - c.Assert(tk.Se.Auth(&auth.UserIdentity{ + require.True(t, tk.Session().Auth(&auth.UserIdentity{ Username: "usageuser", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee="'usageuser'@'%'"`).Check(testkit.Rows("'usageuser'@'%' def USAGE NO")) // the usage row disappears when there is a non-dynamic privilege added tk1.MustExec("GRANT SELECT ON *.* to usageuser") @@ -417,75 +371,72 @@ func (s *testInfoschemaTableSuite) TestUserPrivilegesTable(c *C) { tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee="'usageuser'@'%'" ORDER BY privilege_type`).Check(testkit.Rows("'usageuser'@'%' def BACKUP_ADMIN NO", "'usageuser'@'%' def SELECT YES")) } -func (s *testInfoschemaTableSerialSuite) TestDataForTableStatsField(c *C) { - s.dom.SetStatsUpdating(true) +func TestDataForTableStatsField(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() oldExpiryTime := executor.TableStatsCacheExpiry executor.TableStatsCacheExpiry = 0 defer func() { executor.TableStatsCacheExpiry = oldExpiryTime }() - do := s.dom - h := do.StatsHandle() + h := dom.StatsHandle() h.Clear() - is := do.InfoSchema() - tk := testkit.NewTestKit(c, s.store) + is := dom.InfoSchema() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c int, d int, e char(5), index idx(e))") - err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("0 0 0 0")) tk.MustExec(`insert into t(c, d, e) values(1, 2, "c"), (2, 3, "d"), (3, 4, "e")`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("3 18 54 6")) tk.MustExec(`insert into t(c, d, e) values(4, 5, "f")`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("4 18 72 8")) tk.MustExec("delete from t where c >= 3") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("2 18 36 4")) tk.MustExec("delete from t where c=3") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("2 18 36 4")) // Test partition table. tk.MustExec("drop table if exists t") tk.MustExec(`CREATE TABLE t (a int, b int, c varchar(5), primary key(a), index idx(c)) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16))`) - err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) tk.MustExec(`insert into t(a, b, c) values(1, 2, "c"), (7, 3, "d"), (12, 4, "e")`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.tables where table_name='t'").Check( testkit.Rows("3 18 54 6")) } -func (s *testInfoschemaTableSerialSuite) TestPartitionsTable(c *C) { - s.dom.SetStatsUpdating(true) +func TestPartitionsTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() oldExpiryTime := executor.TableStatsCacheExpiry executor.TableStatsCacheExpiry = 0 defer func() { executor.TableStatsCacheExpiry = oldExpiryTime }() - do := s.dom - h := do.StatsHandle() + h := dom.StatsHandle() h.Clear() - is := do.InfoSchema() + is := dom.InfoSchema() - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") testkit.WithPruneMode(tk, variable.Static, func() { - c.Assert(h.RefreshVars(), IsNil) + require.NoError(t, h.RefreshVars()) tk.MustExec("DROP TABLE IF EXISTS `test_partitions`;") tk.MustExec(`CREATE TABLE test_partitions (a int, b int, c varchar(5), primary key(a), index idx(c)) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16));`) - err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) tk.MustExec(`insert into test_partitions(a, b, c) values(1, 2, "c"), (7, 3, "d"), (12, 4, "e");`) tk.MustQuery("select PARTITION_NAME, PARTITION_DESCRIPTION from information_schema.PARTITIONS where table_name='test_partitions';").Check( @@ -499,8 +450,8 @@ func (s *testInfoschemaTableSerialSuite) TestPartitionsTable(c *C) { "0 0 0 0]\n" + "[0 0 0 0]\n" + "[0 0 0 0")) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.PARTITIONS where table_name='test_partitions';").Check( testkit.Rows("" + "1 18 18 2]\n" + @@ -511,11 +462,10 @@ func (s *testInfoschemaTableSerialSuite) TestPartitionsTable(c *C) { // Test for table has no partitions. tk.MustExec("DROP TABLE IF EXISTS `test_partitions_1`;") tk.MustExec(`CREATE TABLE test_partitions_1 (a int, b int, c varchar(5), primary key(a), index idx(c));`) - err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) tk.MustExec(`insert into test_partitions_1(a, b, c) values(1, 2, "c"), (7, 3, "d"), (12, 4, "e");`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustQuery("select PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, INDEX_LENGTH from information_schema.PARTITIONS where table_name='test_partitions_1';").Check( testkit.Rows(" 3 18 54 6")) @@ -536,33 +486,40 @@ func (s *testInfoschemaTableSerialSuite) TestPartitionsTable(c *C) { tk.MustExec("create table test_partitions (a bigint, b date) partition by list columns (a,b) (partition p0 values in ((1,'2020-09-28'),(1,'2020-09-29')));") tk.MustQuery("select PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION from information_schema.partitions where table_name = 'test_partitions';").Check(testkit.Rows("p0 LIST COLUMNS a,b")) pid, err := strconv.Atoi(tk.MustQuery("select TIDB_PARTITION_ID from information_schema.partitions where table_name = 'test_partitions';").Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(pid, Greater, 0) + require.NoError(t, err) + require.Greater(t, pid, 0) tk.MustExec("drop table test_partitions") } -func (s *testInfoschemaTableSuite) TestMetricTables(c *C) { - tk := testkit.NewTestKit(c, s.store) - statistics.ClearHistoryJobs() +func TestMetricTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use information_schema") tk.MustQuery("select count(*) > 0 from `METRICS_TABLES`").Check(testkit.Rows("1")) tk.MustQuery("select * from `METRICS_TABLES` where table_name='tidb_qps'"). - Check(testutil.RowsWithSep("|", "tidb_qps|sum(rate(tidb_server_query_total{$LABEL_CONDITIONS}[$RANGE_DURATION])) by (result,type,instance)|instance,type,result|0|TiDB query processing numbers per second")) + Check(testkit.RowsWithSep("|", "tidb_qps|sum(rate(tidb_server_query_total{$LABEL_CONDITIONS}[$RANGE_DURATION])) by (result,type,instance)|instance,type,result|0|TiDB query processing numbers per second")) } -func (s *testInfoschemaTableSuite) TestTableConstraintsTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableConstraintsTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Check(testkit.Rows("def mysql delete_range_index mysql gc_delete_range UNIQUE")) } -func (s *testInfoschemaTableSuite) TestTableSessionVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableSessionVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select * from information_schema.SESSION_VARIABLES where VARIABLE_NAME='tidb_retry_limit';").Check(testkit.Rows("tidb_retry_limit 10")) } -func (s *testInfoschemaTableSuite) TestForAnalyzeStatus(c *C) { - tk := testkit.NewTestKit(c, s.store) - statistics.ClearHistoryJobs() +func TestForAnalyzeStatus(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("delete from mysql.analyze_jobs") tk.MustExec("use test") tk.MustExec("drop table if exists analyze_test") tk.MustExec("create table analyze_test (a int, b int, index idx(a))") @@ -574,12 +531,12 @@ func (s *testInfoschemaTableSuite) TestForAnalyzeStatus(c *C) { // test the privilege of new user for information_schema.analyze_status tk.MustExec("create user analyze_tester") - analyzeTester := testkit.NewTestKit(c, s.store) + analyzeTester := testkit.NewTestKit(t, store) analyzeTester.MustExec("use information_schema") - c.Assert(analyzeTester.Se.Auth(&auth.UserIdentity{ + require.True(t, analyzeTester.Session().Auth(&auth.UserIdentity{ Username: "analyze_tester", Hostname: "127.0.0.1", - }, nil, nil), IsTrue) + }, nil, nil)) analyzeTester.MustQuery("show analyze status").Check([][]interface{}{}) analyzeTester.MustQuery("select * from information_schema.ANALYZE_STATUS;").Check([][]interface{}{}) @@ -587,375 +544,74 @@ func (s *testInfoschemaTableSuite) TestForAnalyzeStatus(c *C) { tk.MustExec("create table t1 (a int, b int, index idx(a))") tk.MustExec("insert into t1 values (1,2),(3,4)") tk.MustExec("analyze table t1") - tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t1.")) // 1 note. - c.Assert(s.dom.StatsHandle().LoadNeededHistograms(), IsNil) + tk.MustQuery("show warnings").Check(testkit.Rows("Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t1")) // 1 note. + require.NoError(t, dom.StatsHandle().LoadNeededHistograms()) tk.MustExec("CREATE ROLE r_t1 ;") tk.MustExec("GRANT ALL PRIVILEGES ON test.t1 TO r_t1;") tk.MustExec("GRANT r_t1 TO analyze_tester;") analyzeTester.MustExec("set role r_t1") - resultT1 := tk.MustQuery("select * from information_schema.analyze_status where TABLE_NAME='t1'").Sort() - c.Assert(len(resultT1.Rows()), Greater, 0) - for _, row := range resultT1.Rows() { - c.Assert(len(row), Equals, 8) // test length of row - c.Assert(row[6], NotNil) // test `End_time` field + rows := tk.MustQuery("select * from information_schema.analyze_status where TABLE_NAME='t1'").Sort().Rows() + require.Greater(t, len(rows), 0) + for _, row := range rows { + require.Len(t, row, 11) // test length of row + // test `End_time` field + str, ok := row[6].(string) + require.True(t, ok) + _, err := time.Parse("2006-01-02 15:04:05", str) + require.NoError(t, err) + } + rows2 := tk.MustQuery("show analyze status where TABLE_NAME='t1'").Sort().Rows() + require.Equal(t, len(rows), len(rows2)) + for i, row2 := range rows2 { + require.Equal(t, rows[i], row2) } } -func (s *testInfoschemaTableSerialSuite) TestForServersInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) - result := tk.MustQuery("select * from information_schema.TIDB_SERVERS_INFO") - c.Assert(len(result.Rows()), Equals, 1) +func TestForServersInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + rows := tk.MustQuery("select * from information_schema.TIDB_SERVERS_INFO").Rows() + require.Len(t, rows, 1) info, err := infosync.GetServerInfo() - c.Assert(err, IsNil) - c.Assert(info, NotNil) - c.Assert(result.Rows()[0][0], Equals, info.ID) - c.Assert(result.Rows()[0][1], Equals, info.IP) - c.Assert(result.Rows()[0][2], Equals, strconv.FormatInt(int64(info.Port), 10)) - c.Assert(result.Rows()[0][3], Equals, strconv.FormatInt(int64(info.StatusPort), 10)) - c.Assert(result.Rows()[0][4], Equals, info.Lease) - c.Assert(result.Rows()[0][5], Equals, info.Version) - c.Assert(result.Rows()[0][6], Equals, info.GitHash) - c.Assert(result.Rows()[0][7], Equals, info.BinlogStatus) - c.Assert(result.Rows()[0][8], Equals, stringutil.BuildStringFromLabels(info.Labels)) -} - -func (s *testInfoschemaTableSerialSuite) TestForTableTiFlashReplica(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`), IsNil) + require.NoError(t, err) + require.NotNil(t, info) + require.Equal(t, info.ID, rows[0][0]) + require.Equal(t, info.IP, rows[0][1]) + require.Equal(t, strconv.FormatInt(int64(info.Port), 10), rows[0][2]) + require.Equal(t, strconv.FormatInt(int64(info.StatusPort), 10), rows[0][3]) + require.Equal(t, info.Lease, rows[0][4]) + require.Equal(t, info.Version, rows[0][5]) + require.Equal(t, info.GitHash, rows[0][6]) + require.Equal(t, info.BinlogStatus, rows[0][7]) + require.Equal(t, stringutil.BuildStringFromLabels(info.Labels), rows[0][8]) +} + +func TestForTableTiFlashReplica(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`)) defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount") - c.Assert(err, IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount")) }() - tk := testkit.NewTestKit(c, s.store) - statistics.ClearHistoryJobs() + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, index idx(a))") tk.MustExec("alter table t set tiflash replica 2 location labels 'a','b';") tk.MustQuery("select TABLE_SCHEMA,TABLE_NAME,REPLICA_COUNT,LOCATION_LABELS,AVAILABLE, PROGRESS from information_schema.tiflash_replica").Check(testkit.Rows("test t 2 a,b 0 0")) - tbl, err := domain.GetDomain(tk.Se).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + tbl, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tbl.Meta().TiFlashReplica.Available = true tk.MustQuery("select TABLE_SCHEMA,TABLE_NAME,REPLICA_COUNT,LOCATION_LABELS,AVAILABLE, PROGRESS from information_schema.tiflash_replica").Check(testkit.Rows("test t 2 a,b 1 1")) } -var _ = SerialSuites(&testInfoschemaClusterTableSuite{testInfoschemaTableSuiteBase: &testInfoschemaTableSuiteBase{}}) - -type testInfoschemaClusterTableSuite struct { - *testInfoschemaTableSuiteBase - rpcserver *grpc.Server - httpServer *httptest.Server - mockAddr string - listenAddr string - startTime time.Time -} - -func (s *testInfoschemaClusterTableSuite) SetUpSuite(c *C) { - s.testInfoschemaTableSuiteBase.SetUpSuite(c) - s.rpcserver, s.listenAddr = s.setUpRPCService(c, "127.0.0.1:0") - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() -} - -func (s *testInfoschemaClusterTableSuite) setUpRPCService(c *C, addr string) (*grpc.Server, string) { - lis, err := net.Listen("tcp", addr) - c.Assert(err, IsNil) - // Fix issue 9836 - sm := &mockSessionManager{ - processInfoMap: make(map[uint64]*util.ProcessInfo, 1), - serverID: 1, - } - sm.processInfoMap[1] = &util.ProcessInfo{ - ID: 1, - User: "root", - Host: "127.0.0.1", - Command: mysql.ComQuery, - } - srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) - port := lis.Addr().(*net.TCPAddr).Port - addr = fmt.Sprintf("127.0.0.1:%d", port) - go func() { - err = srv.Serve(lis) - c.Assert(err, IsNil) - }() - config.UpdateGlobal(func(conf *config.Config) { - conf.Status.StatusPort = uint(port) - }) - return srv, addr -} - -func (s *testInfoschemaClusterTableSuite) setUpMockPDHTTPServer() (*httptest.Server, string) { - // mock PD http server - router := mux.NewRouter() - server := httptest.NewServer(router) - // mock store stats stat - mockAddr := strings.TrimPrefix(server.URL, "http://") - router.Handle(pdapi.Stores, fn.Wrap(func() (*helper.StoresStat, error) { - return &helper.StoresStat{ - Count: 1, - Stores: []helper.StoreStat{ - { - Store: helper.StoreBaseStat{ - ID: 1, - Address: "127.0.0.1:20160", - State: 0, - StateName: "Up", - Version: "4.0.0-alpha", - StatusAddress: mockAddr, - GitHash: "mock-tikv-githash", - StartTimestamp: s.startTime.Unix(), - }, - }, - }, - }, nil - })) - // mock PD API - router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { - return struct { - Version string `json:"version"` - GitHash string `json:"git_hash"` - StartTimestamp int64 `json:"start_timestamp"` - }{ - Version: "4.0.0-alpha", - GitHash: "mock-pd-githash", - StartTimestamp: s.startTime.Unix(), - }, nil - })) - var mockConfig = func() (map[string]interface{}, error) { - configuration := map[string]interface{}{ - "key1": "value1", - "key2": map[string]string{ - "nest1": "n-value1", - "nest2": "n-value2", - }, - "key3": map[string]interface{}{ - "nest1": "n-value1", - "nest2": "n-value2", - "key4": map[string]string{ - "nest3": "n-value4", - "nest4": "n-value5", - }, - }, - } - return configuration, nil - } - // PD config. - router.Handle(pdapi.Config, fn.Wrap(mockConfig)) - // TiDB/TiKV config. - router.Handle("/config", fn.Wrap(mockConfig)) - // PD region. - router.Handle("/pd/api/v1/stats/region", fn.Wrap(func() (*helper.PDRegionStats, error) { - return &helper.PDRegionStats{ - Count: 1, - EmptyCount: 1, - StorageSize: 1, - StorageKeys: 1, - StoreLeaderCount: map[uint64]int{1: 1}, - StorePeerCount: map[uint64]int{1: 1}, - }, nil - })) - return server, mockAddr -} - -func (s *testInfoschemaClusterTableSuite) TearDownSuite(c *C) { - if s.rpcserver != nil { - s.rpcserver.Stop() - s.rpcserver = nil - } - if s.httpServer != nil { - s.httpServer.Close() - } - s.testInfoschemaTableSuiteBase.TearDownSuite(c) -} - -type mockSessionManager struct { - processInfoMap map[uint64]*util.ProcessInfo - serverID uint64 -} - -func (sm *mockSessionManager) ShowTxnList() []*txninfo.TxnInfo { - panic("unimplemented!") -} - -func (sm *mockSessionManager) ShowProcessList() map[uint64]*util.ProcessInfo { - return sm.processInfoMap -} - -func (sm *mockSessionManager) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) { - rs, ok := sm.processInfoMap[id] - return rs, ok -} - -func (sm *mockSessionManager) Kill(connectionID uint64, query bool) {} - -func (sm *mockSessionManager) KillAllConnections() {} - -func (sm *mockSessionManager) UpdateTLSConfig(cfg *tls.Config) {} - -func (sm *mockSessionManager) ServerID() uint64 { - return sm.serverID -} - -func (sm *mockSessionManager) SetServerID(serverID uint64) { - sm.serverID = serverID -} - -type mockStore struct { - helper.Storage - host string -} - -func (s *mockStore) EtcdAddrs() ([]string, error) { return []string{s.host}, nil } -func (s *mockStore) TLSConfig() *tls.Config { panic("not implemented") } -func (s *mockStore) StartGCWorker() error { panic("not implemented") } -func (s *mockStore) Name() string { return "mockStore" } -func (s *mockStore) Describe() string { return "" } - -func (s *testInfoschemaClusterTableSuite) TestTiDBClusterInfo(c *C) { - mockAddr := s.mockAddr - store := &mockStore{ - s.store.(helper.Storage), - mockAddr, - } - - // information_schema.cluster_info - tk := testkit.NewTestKit(c, store) - tidbStatusAddr := fmt.Sprintf(":%d", config.GetGlobalConfig().Status.StatusPort) - row := func(cols ...string) string { return strings.Join(cols, " ") } - tk.MustQuery("select type, instance, status_address, version, git_hash from information_schema.cluster_info").Check(testkit.Rows( - row("tidb", ":4000", tidbStatusAddr, "None", "None"), - row("pd", mockAddr, mockAddr, "4.0.0-alpha", "mock-pd-githash"), - row("tikv", "store1", "", "", ""), - )) - startTime := s.startTime.Format(time.RFC3339) - tk.MustQuery("select type, instance, start_time from information_schema.cluster_info where type != 'tidb'").Check(testkit.Rows( - row("pd", mockAddr, startTime), - row("tikv", "store1", ""), - )) - - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockStoreTombstone", `return(true)`), IsNil) - tk.MustQuery("select type, instance, start_time from information_schema.cluster_info where type = 'tikv'").Check(testkit.Rows()) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockStoreTombstone"), IsNil) - - // information_schema.cluster_config - instances := []string{ - "pd,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,0", - "tidb,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,1001", - "tikv,127.0.0.1:11080," + mockAddr + ",mock-version,mock-githash,0", - } - fpExpr := `return("` + strings.Join(instances, ";") + `")` - c.Assert(failpoint.Enable("github.com/pingcap/tidb/infoschema/mockClusterInfo", fpExpr), IsNil) - defer func() { c.Assert(failpoint.Disable("github.com/pingcap/tidb/infoschema/mockClusterInfo"), IsNil) }() - tk.MustQuery("select type, instance, status_address, version, git_hash, server_id from information_schema.cluster_info").Check(testkit.Rows( - row("pd", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "0"), - row("tidb", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "1001"), - row("tikv", "127.0.0.1:11080", mockAddr, "mock-version", "mock-githash", "0"), - )) - tk.MustQuery("select * from information_schema.cluster_config").Check(testkit.Rows( - "pd 127.0.0.1:11080 key1 value1", - "pd 127.0.0.1:11080 key2.nest1 n-value1", - "pd 127.0.0.1:11080 key2.nest2 n-value2", - "pd 127.0.0.1:11080 key3.key4.nest3 n-value4", - "pd 127.0.0.1:11080 key3.key4.nest4 n-value5", - "pd 127.0.0.1:11080 key3.nest1 n-value1", - "pd 127.0.0.1:11080 key3.nest2 n-value2", - "tidb 127.0.0.1:11080 key1 value1", - "tidb 127.0.0.1:11080 key2.nest1 n-value1", - "tidb 127.0.0.1:11080 key2.nest2 n-value2", - "tidb 127.0.0.1:11080 key3.key4.nest3 n-value4", - "tidb 127.0.0.1:11080 key3.key4.nest4 n-value5", - "tidb 127.0.0.1:11080 key3.nest1 n-value1", - "tidb 127.0.0.1:11080 key3.nest2 n-value2", - "tikv 127.0.0.1:11080 key1 value1", - "tikv 127.0.0.1:11080 key2.nest1 n-value1", - "tikv 127.0.0.1:11080 key2.nest2 n-value2", - "tikv 127.0.0.1:11080 key3.key4.nest3 n-value4", - "tikv 127.0.0.1:11080 key3.key4.nest4 n-value5", - "tikv 127.0.0.1:11080 key3.nest1 n-value1", - "tikv 127.0.0.1:11080 key3.nest2 n-value2", - )) - tk.MustQuery("select TYPE, `KEY`, VALUE from information_schema.cluster_config where `key`='key3.key4.nest4' order by type").Check(testkit.Rows( - "pd key3.key4.nest4 n-value5", - "tidb key3.key4.nest4 n-value5", - "tikv key3.key4.nest4 n-value5", - )) -} - -func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { - tk := testkit.NewTestKit(c, s.store) - err := tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test'") - c.Assert(err.Error(), Equals, "pd unavailable") - mockAddr := s.mockAddr - store := &mockStore{ - s.store.(helper.Storage), - mockAddr, - } - - // Test information_schema.TABLE_STORAGE_STATS. - tk = testkit.NewTestKit(c, store) - - // Test not set the schema. - err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Please specify the 'table_schema'") - - // Test it would get null set when get the sys schema. - tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema';").Check([][]interface{}{}) - tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA in ('information_schema', 'metrics_schema');").Check([][]interface{}{}) - tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema' and TABLE_NAME='schemata';").Check([][]interface{}{}) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int, b int, index idx(a))") - tk.MustQuery("select TABLE_NAME, TABLE_SIZE from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' and TABLE_NAME='t';").Check(testkit.Rows("t 1")) - - tk.MustExec("create table t1 (a int, b int, index idx(a))") - tk.MustQuery("select TABLE_NAME, sum(TABLE_SIZE) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' group by TABLE_NAME;").Sort().Check(testkit.Rows( - "t 1", - "t1 1", - )) - tk.MustQuery("select TABLE_SCHEMA, sum(TABLE_SIZE) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'test' group by TABLE_SCHEMA;").Check(testkit.Rows( - "test 2", - )) - c.Assert(len(tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql';").Rows()), Equals, 27) - - // More tests about the privileges. - tk.MustExec("create user 'testuser'@'localhost'") - tk.MustExec("create user 'testuser2'@'localhost'") - tk.MustExec("create user 'testuser3'@'localhost'") - tk1 := testkit.NewTestKit(c, store) - defer tk1.MustExec("drop user 'testuser'@'localhost'") - defer tk1.MustExec("drop user 'testuser2'@'localhost'") - defer tk1.MustExec("drop user 'testuser3'@'localhost'") - - tk.MustExec("grant all privileges on *.* to 'testuser2'@'localhost'") - tk.MustExec("grant select on *.* to 'testuser3'@'localhost'") - c.Assert(tk.Se.Auth(&auth.UserIdentity{ - Username: "testuser", - Hostname: "localhost", - }, nil, nil), Equals, true) - - // User has no access to this schema, so the result set is empty. - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) - - c.Assert(tk.Se.Auth(&auth.UserIdentity{ - Username: "testuser2", - Hostname: "localhost", - }, nil, nil), Equals, true) - - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("27")) - - c.Assert(tk.Se.Auth(&auth.UserIdentity{ - Username: "testuser3", - Hostname: "localhost", - }, nil, nil), Equals, true) - - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("27")) -} - -func (s *testInfoschemaTableSuite) TestSequences(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequences(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE SEQUENCE test.seq maxvalue 10000000") tk.MustQuery("SELECT * FROM information_schema.sequences WHERE sequence_schema='test' AND sequence_name='seq'").Check(testkit.Rows("def test seq 1 1000 0 1 10000000 1 1 ")) tk.MustExec("DROP SEQUENCE test.seq") @@ -966,22 +622,25 @@ func (s *testInfoschemaTableSuite) TestSequences(c *C) { tk.MustQuery("SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME , TABLE_TYPE, ENGINE, TABLE_ROWS FROM information_schema.tables WHERE TABLE_TYPE='SEQUENCE' AND TABLE_NAME='seq2'").Check(testkit.Rows("def test seq2 SEQUENCE InnoDB 1")) } -func (s *testInfoschemaTableSuite) TestTiFlashSystemTables(c *C) { - tk := testkit.NewTestKit(c, s.store) - err := tk.QueryToErr("select * from information_schema.TIFLASH_TABLES;") - c.Assert(err.Error(), Equals, "Etcd addrs not found") - err = tk.QueryToErr("select * from information_schema.TIFLASH_SEGMENTS;") - c.Assert(err.Error(), Equals, "Etcd addrs not found") +func TestTiFlashSystemTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("select * from information_schema.TIFLASH_TABLES;") + tk.MustExec("select * from information_schema.TIFLASH_SEGMENTS;") } -func (s *testInfoschemaTableSuite) TestTablesPKType(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestTablesPKType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t_int (a int primary key, b int)") tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_int'").Check(testkit.Rows("CLUSTERED")) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t_implicit (a varchar(64) primary key, b int)") tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_implicit'").Check(testkit.Rows("NONCLUSTERED")) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("create table t_common (a varchar(64) primary key, b int)") tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_common'").Check(testkit.Rows("CLUSTERED")) tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'INFORMATION_SCHEMA' and table_name = 'TABLES'").Check(testkit.Rows("NONCLUSTERED")) diff --git a/executor/insert.go b/executor/insert.go index 2862416ddf04a..953202cf66e56 100644 --- a/executor/insert.go +++ b/executor/insert.go @@ -67,6 +67,7 @@ func (e *InsertExec) exec(ctx context.Context, rows [][]types.Datum) error { return err } setResourceGroupTaggerForTxn(sessVars.StmtCtx, txn) + setRPCInterceptorOfExecCounterForTxn(sessVars, txn) txnSize := txn.Size() sessVars.StmtCtx.AddRecordRows(uint64(len(rows))) // If you use the IGNORE keyword, duplicate-key error that occurs while executing the INSERT statement are ignored. @@ -82,7 +83,7 @@ func (e *InsertExec) exec(ctx context.Context, rows [][]types.Datum) error { return err } } else if ignoreErr { - err := e.batchCheckAndInsert(ctx, rows, e.addRecord) + err := e.batchCheckAndInsert(ctx, rows, e.addRecord, false) if err != nil { return err } @@ -359,7 +360,7 @@ func (e *InsertExec) initEvalBuffer4Dup() { evalBufferTypes = append(evalBufferTypes, &col.FieldType) } if extraLen > 0 { - evalBufferTypes = append(evalBufferTypes, e.SelectExec.base().retFieldTypes[numWritableCols:]...) + evalBufferTypes = append(evalBufferTypes, e.SelectExec.base().retFieldTypes[e.rowLen:]...) } for _, col := range e.Table.Cols() { evalBufferTypes = append(evalBufferTypes, &col.FieldType) @@ -368,7 +369,7 @@ func (e *InsertExec) initEvalBuffer4Dup() { evalBufferTypes = append(evalBufferTypes, types.NewFieldType(mysql.TypeLonglong)) } e.evalBuffer4Dup = chunk.MutRowFromTypes(evalBufferTypes) - e.curInsertVals = chunk.MutRowFromTypes(evalBufferTypes[numWritableCols:]) + e.curInsertVals = chunk.MutRowFromTypes(evalBufferTypes[numWritableCols+extraLen:]) e.row4Update = make([]types.Datum, 0, len(evalBufferTypes)) } diff --git a/executor/insert_common.go b/executor/insert_common.go index 9c7adbb3c4d1a..8d053645a4355 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -35,8 +35,11 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" @@ -161,7 +164,7 @@ func (e *InsertValues) initInsertColumns() error { } if col.Name.L == model.ExtraHandleName.L { if !e.ctx.GetSessionVars().AllowWriteRowID { - return errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.") + return errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported") } e.hasExtraHandle = true } @@ -886,7 +889,7 @@ func (e *InsertValues) adjustAutoRandomDatum(ctx context.Context, d types.Datum, // Use the value if it's not null and not 0. if recordID != 0 { if !e.ctx.GetSessionVars().AllowAutoRandExplicitInsert { - return types.Datum{}, ddl.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomExplicitInsertDisabledErrMsg) + return types.Datum{}, dbterror.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomExplicitInsertDisabledErrMsg) } err = e.rebaseAutoRandomID(ctx, recordID, &c.FieldType) if err != nil { @@ -975,7 +978,7 @@ func (e *InsertValues) adjustImplicitRowID(ctx context.Context, d types.Datum, h // Use the value if it's not null and not 0. if recordID != 0 { if !e.ctx.GetSessionVars().AllowWriteRowID { - return types.Datum{}, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.") + return types.Datum{}, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported") } err = e.rebaseImplicitRowID(ctx, recordID) if err != nil { @@ -1040,7 +1043,9 @@ func (e *InsertValues) collectRuntimeStatsEnabled() bool { // batchCheckAndInsert checks rows with duplicate errors. // All duplicate rows will be ignored and appended as duplicate warnings. -func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.Datum, addRecord func(ctx context.Context, row []types.Datum) error) error { +func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.Datum, + addRecord func(ctx context.Context, row []types.Datum) error, + replace bool) error { // all the rows will be checked, so it is safe to set BatchCheck = true e.ctx.GetSessionVars().StmtCtx.BatchCheck = true if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { @@ -1059,6 +1064,9 @@ func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.D if err != nil { return err } + sessVars := e.ctx.GetSessionVars() + setResourceGroupTaggerForTxn(sessVars.StmtCtx, txn) + setRPCInterceptorOfExecCounterForTxn(sessVars, txn) if e.collectRuntimeStatsEnabled() { if snapshot := txn.GetSnapshot(); snapshot != nil { snapshot.SetOption(kv.CollectRuntimeStats, e.stats.SnapshotRuntimeStats) @@ -1087,10 +1095,16 @@ func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.D if r.handleKey != nil { _, err := txn.Get(ctx, r.handleKey.newKey) if err == nil { - e.ctx.GetSessionVars().StmtCtx.AppendWarning(r.handleKey.dupErr) - continue - } - if !kv.IsErrNotFound(err) { + if replace { + err2 := e.removeRow(ctx, txn, r) + if err2 != nil { + return err2 + } + } else { + e.ctx.GetSessionVars().StmtCtx.AppendWarning(r.handleKey.dupErr) + continue + } + } else if !kv.IsErrNotFound(err) { return err } } @@ -1124,6 +1138,58 @@ func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.D return nil } +func (e *InsertValues) removeRow(ctx context.Context, txn kv.Transaction, r toBeCheckedRow) error { + handle, err := tablecodec.DecodeRowKey(r.handleKey.newKey) + if err != nil { + return err + } + + newRow := r.row + oldRow, err := getOldRow(ctx, e.ctx, txn, r.t, handle, e.GenExprs) + if err != nil { + logutil.BgLogger().Error("get old row failed when replace", + zap.String("handle", handle.String()), + zap.String("toBeInsertedRow", types.DatumsToStrNoErr(r.row))) + if kv.IsErrNotFound(err) { + err = errors.NotFoundf("can not be duplicated row, due to old row not found. handle %s", handle) + } + return err + } + + identical, err := e.equalDatumsAsBinary(oldRow, newRow) + if err != nil { + return err + } + if identical { + return nil + } + + err = r.t.RemoveRecord(e.ctx, handle, oldRow) + if err != nil { + return err + } + e.ctx.GetSessionVars().StmtCtx.AddDeletedRows(1) + + return nil +} + +// equalDatumsAsBinary compare if a and b contains the same datum values in binary collation. +func (e *InsertValues) equalDatumsAsBinary(a []types.Datum, b []types.Datum) (bool, error) { + if len(a) != len(b) { + return false, nil + } + for i, ai := range a { + v, err := ai.Compare(e.ctx.GetSessionVars().StmtCtx, &b[i], collate.GetBinaryCollator()) + if err != nil { + return false, errors.Trace(err) + } + if v != 0 { + return false, nil + } + } + return true, nil +} + func (e *InsertValues) addRecord(ctx context.Context, row []types.Datum) error { return e.addRecordWithAutoIDHint(ctx, row, 0) } diff --git a/executor/insert_test.go b/executor/insert_test.go index ab41475d3e6fa..ce91449f5fe49 100644 --- a/executor/insert_test.go +++ b/executor/insert_test.go @@ -19,65 +19,65 @@ import ( "math" "strconv" "strings" - "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/execdetails" - "github.com/pingcap/tidb/util/israce" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -func (s *testSuite8) TestInsertOnDuplicateKey(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertOnDuplicateKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(a1 bigint primary key, b1 bigint);`) tk.MustExec(`create table t2(a2 bigint primary key, b2 bigint);`) tk.MustExec(`insert into t1 values(1, 100);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t2 values(1, 200);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 select a2, b2 from t2 on duplicate key update b1 = a2;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 1")) tk.MustExec(`insert into t1 select a2, b2 from t2 on duplicate key update b1 = b2;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 200")) tk.MustExec(`insert into t1 select a2, b2 from t2 on duplicate key update a1 = a2;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 200")) tk.MustExec(`insert into t1 select a2, b2 from t2 on duplicate key update b1 = 300;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 300")) tk.MustExec(`insert into t1 values(1, 1) on duplicate key update b1 = 400;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 400")) tk.MustExec(`insert into t1 select 1, 500 from t2 on duplicate key update b1 = 400;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t1;`).Check(testkit.Rows("1 400")) @@ -85,97 +85,97 @@ func (s *testSuite8) TestInsertOnDuplicateKey(c *C) { tk.MustExec(`create table t1(a bigint primary key, b bigint);`) tk.MustExec(`create table t2(a bigint primary key, b bigint);`) _, err := tk.Exec(`insert into t1 select * from t2 on duplicate key update c = t2.b;`) - c.Assert(err.Error(), Equals, `[planner:1054]Unknown column 'c' in 'field list'`) + require.Equal(t, `[planner:1054]Unknown column 'c' in 'field list'`, err.Error()) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(a bigint primary key, b bigint);`) tk.MustExec(`create table t2(a bigint primary key, b bigint);`) _, err = tk.Exec(`insert into t1 select * from t2 on duplicate key update a = b;`) - c.Assert(err.Error(), Equals, `[planner:1052]Column 'b' in field list is ambiguous`) + require.Equal(t, `[planner:1052]Column 'b' in field list is ambiguous`, err.Error()) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(a bigint primary key, b bigint);`) tk.MustExec(`create table t2(a bigint primary key, b bigint);`) _, err = tk.Exec(`insert into t1 select * from t2 on duplicate key update c = b;`) - c.Assert(err.Error(), Equals, `[planner:1054]Unknown column 'c' in 'field list'`) + require.Equal(t, `[planner:1054]Unknown column 'c' in 'field list'`, err.Error()) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(a1 bigint primary key, b1 bigint);`) tk.MustExec(`create table t2(a2 bigint primary key, b2 bigint);`) _, err = tk.Exec(`insert into t1 select * from t2 on duplicate key update a1 = values(b2);`) - c.Assert(err.Error(), Equals, `[planner:1054]Unknown column 'b2' in 'field list'`) + require.Equal(t, `[planner:1054]Unknown column 'b2' in 'field list'`, err.Error()) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(a1 bigint primary key, b1 bigint);`) tk.MustExec(`create table t2(a2 bigint primary key, b2 bigint);`) tk.MustExec(`insert into t1 values(1, 100);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t2 values(1, 200);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 select * from t2 on duplicate key update b1 = values(b1) + b2;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t1`).Check(testkit.Rows("1 400")) tk.MustExec(`insert into t1 select * from t2 on duplicate key update b1 = values(b1) + b2;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t1`).Check(testkit.Rows("1 400")) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(k1 bigint, k2 bigint, val bigint, primary key(k1, k2));`) tk.MustExec(`insert into t (val, k1, k2) values (3, 1, 2);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) tk.MustExec(`insert into t (val, k1, k2) select c, a, b from (select 1 as a, 2 as b, 4 as c) tmp on duplicate key update val = tmp.c;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 4`)) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(k1 double, k2 double, v double, primary key(k1, k2));`) tk.MustExec(`insert into t (v, k1, k2) select c, a, b from (select "3" c, "1" a, "2" b) tmp on duplicate key update v=c;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) tk.MustExec(`insert into t (v, k1, k2) select c, a, b from (select "3" c, "1" a, "2" b) tmp on duplicate key update v=c;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 1 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 2 3`)) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(id int, a int, b int);`) tk.MustExec(`insert into t1 values (1, 1, 1);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 values (2, 2, 1);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 values (3, 3, 1);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`create table t2(a int primary key, b int, unique(b));`) tk.MustExec(`insert into t2 select a, b from t1 order by id on duplicate key update a=t1.a, b=t1.b;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(5)) + require.Equal(t, uint64(5), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 3 Duplicates: 2 Warnings: 0") tk.MustQuery(`select * from t2 order by a;`).Check(testkit.Rows(`3 1`)) tk.MustExec(`drop table if exists t1, t2;`) tk.MustExec(`create table t1(id int, a int, b int);`) tk.MustExec(`insert into t1 values (1, 1, 1);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 values (2, 1, 2);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`insert into t1 values (3, 3, 1);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(1)) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) tk.CheckLastMessage("") tk.MustExec(`create table t2(a int primary key, b int, unique(b));`) tk.MustExec(`insert into t2 select a, b from t1 order by id on duplicate key update a=t1.a, b=t1.b;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(4)) + require.Equal(t, uint64(4), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 3 Duplicates: 1 Warnings: 0") tk.MustQuery(`select * from t2 order by a;`).Check(testkit.Rows(`1 2`, `3 1`)) @@ -187,17 +187,17 @@ func (s *testSuite8) TestInsertOnDuplicateKey(c *C) { tk.MustExec(`insert into t1 values (4, 4, 2, 2);`) tk.MustExec(`create table t2(a int primary key, b int, c int, unique(b), unique(c));`) tk.MustExec(`insert into t2 select a, b, c from t1 order by id on duplicate key update b=t2.b, c=t2.c;`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 4 Duplicates: 0 Warnings: 0") tk.MustQuery(`select * from t2 order by a;`).Check(testkit.Rows(`1 1 1`, `3 2 2`)) tk.MustExec(`drop table if exists t1`) tk.MustExec(`create table t1(a int primary key, b int);`) tk.MustExec(`insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(5)) + require.Equal(t, uint64(5), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 5 Duplicates: 0 Warnings: 0") tk.MustExec(`insert into t1 values(4,14),(5,15),(6,16),(7,17),(8,18) on duplicate key update b=b+10`) - c.Assert(tk.Se.AffectedRows(), Equals, uint64(7)) + require.Equal(t, uint64(7), tk.Session().AffectedRows()) tk.CheckLastMessage("Records: 5 Duplicates: 2 Warnings: 0") tk.MustExec("drop table if exists a, b") @@ -206,9 +206,39 @@ func (s *testSuite8) TestInsertOnDuplicateKey(c *C) { tk.MustExec("insert into a values(1)") tk.MustExec("insert into b values(1, 2)") tk.MustExec("insert into a select x from b ON DUPLICATE KEY UPDATE a.x=b.y") - c.Assert(tk.Se.AffectedRows(), Equals, uint64(2)) + require.Equal(t, uint64(2), tk.Session().AffectedRows()) tk.MustQuery("select * from a").Check(testkit.Rows("2")) + // Test issue 28078. + // Use different types of columns so that there's likely to be error if the types mismatches. + tk.MustExec("drop table if exists a, b") + tk.MustExec("create table a(id int, a1 timestamp, a2 varchar(10), a3 float, unique(id))") + tk.MustExec("create table b(id int, b1 time, b2 varchar(10), b3 int)") + tk.MustExec("insert into a values (1, '2022-01-04 07:02:04', 'a', 1.1), (2, '2022-01-04 07:02:05', 'b', 2.2)") + tk.MustExec("insert into b values (2, '12:34:56', 'c', 10), (3, '01:23:45', 'd', 20)") + tk.MustExec("insert into a (id) select id from b on duplicate key update a.a2 = b.b2, a.a3 = 3.3") + require.Equal(t, uint64(3), tk.Session().AffectedRows()) + tk.MustQuery("select * from a").Check(testkit.RowsWithSep("/", + "1/2022-01-04 07:02:04/a/1.1", + "2/2022-01-04 07:02:05/c/3.3", + "3///")) + tk.MustExec("insert into a (id) select 4 from b where b3 = 20 on duplicate key update a.a3 = b.b3") + require.Equal(t, uint64(1), tk.Session().AffectedRows()) + tk.MustQuery("select * from a").Check(testkit.RowsWithSep("/", + "1/2022-01-04 07:02:04/a/1.1", + "2/2022-01-04 07:02:05/c/3.3", + "3///", + "4///")) + tk.MustExec("insert into a (a2, a3) select 'x', 1.2 from b on duplicate key update a.a2 = b.b3") + require.Equal(t, uint64(2), tk.Session().AffectedRows()) + tk.MustQuery("select * from a").Check(testkit.RowsWithSep("/", + "1/2022-01-04 07:02:04/a/1.1", + "2/2022-01-04 07:02:05/c/3.3", + "3///", + "4///", + "//x/1.2", + "//x/1.2")) + // reproduce insert on duplicate key update bug under new row format. tk.MustExec(`drop table if exists t1`) tk.MustExec(`create table t1(c1 decimal(6,4), primary key(c1))`) @@ -217,29 +247,33 @@ func (s *testSuite8) TestInsertOnDuplicateKey(c *C) { tk.MustQuery(`select * from t1 use index(primary)`).Check(testkit.Rows(`1.0000`)) } -func (s *testSuite8) TestClusterIndexInsertOnDuplicateKey(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterIndexInsertOnDuplicateKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists cluster_index_duplicate_entry_error;") tk.MustExec("create database cluster_index_duplicate_entry_error;") tk.MustExec("use cluster_index_duplicate_entry_error;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("create table t(a char(20), b int, primary key(a));") tk.MustExec("insert into t values('aa', 1), ('bb', 1);") _, err := tk.Exec("insert into t values('aa', 2);") - c.Assert(err, ErrorMatches, ".*Duplicate entry 'aa' for.*") + require.Regexp(t, ".*Duplicate entry 'aa' for.*", err.Error()) tk.MustExec("drop table t;") tk.MustExec("create table t(a char(20), b varchar(30), c varchar(10), primary key(a, b, c));") tk.MustExec("insert into t values ('a', 'b', 'c'), ('b', 'a', 'c');") _, err = tk.Exec("insert into t values ('a', 'b', 'c');") - c.Assert(err, ErrorMatches, ".*Duplicate entry 'a-b-c' for.*") + require.Regexp(t, ".*Duplicate entry 'a-b-c' for.*", err.Error()) } -func (s *testSuite10) TestPaddingCommonHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPaddingCommonHandle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t1;") tk.MustExec(`create table t1(c1 decimal(6,4), primary key(c1))`) tk.MustExec(`insert into t1 set c1 = 0.1`) @@ -247,11 +281,10 @@ func (s *testSuite10) TestPaddingCommonHandle(c *C) { tk.MustQuery(`select * from t1`).Check(testkit.Rows(`1.0000`)) } -func (s *testSuite2) TestInsertReorgDelete(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestInsertReorgDelete(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") inputs := []struct { @@ -302,8 +335,10 @@ func (s *testSuite2) TestInsertReorgDelete(c *C) { } } -func (s *testSuite3) TestUpdateDuplicateKey(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateDuplicateKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) @@ -311,21 +346,23 @@ func (s *testSuite3) TestUpdateDuplicateKey(c *C) { tk.MustExec(`insert into c values(1,2,3);`) tk.MustExec(`insert into c values(1,2,4);`) _, err := tk.Exec(`update c set i=1,j=2,k=4 where i=1 and j=2 and k=3;`) - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1-2-4' for key 'PRIMARY'") + require.EqualError(t, err, "[kv:1062]Duplicate entry '1-2-4' for key 'PRIMARY'") } -func (s *testSuite3) TestInsertWrongValueForField(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertWrongValueForField(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t1(a bigint);`) _, err := tk.Exec(`insert into t1 values("asfasdfsajhlkhlksdaf");`) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue) + require.True(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField)) tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t1(a varchar(10)) charset ascii;`) _, err = tk.Exec(`insert into t1 values('我');`) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue) + require.True(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField)) tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t1(a char(10) charset utf8);`) @@ -347,12 +384,14 @@ func (s *testSuite3) TestInsertWrongValueForField(c *C) { tk.MustExec(`SET @@sql_mode='STRICT_TRANS_TABLES'`) _, err = tk.Exec(`INSERT INTO ts (id, time1) VALUES (2, TIMESTAMP '1018-12-24 00:00:00')`) - c.Assert(err.Error(), Equals, `[table:1292]Incorrect timestamp value: '1018-12-24 00:00:00' for column 'time1' at row 1`) + require.EqualError(t, err, `[table:1292]Incorrect timestamp value: '1018-12-24 00:00:00' for column 'time1' at row 1`) tk.MustExec(`DROP TABLE ts`) } -func (s *testSuite3) TestInsertValueForCastDecimalField(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertValueForCastDecimalField(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t1(a decimal(15,2));`) @@ -361,8 +400,10 @@ func (s *testSuite3) TestInsertValueForCastDecimalField(c *C) { tk.MustQuery(`select cast(a as decimal) from t1;`).Check(testkit.Rows(`9999999999`)) } -func (s *testSuite3) TestInsertDateTimeWithTimeZone(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertDateTimeWithTimeZone(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test;`) tk.MustExec(`set time_zone="+09:00";`) @@ -463,8 +504,10 @@ func (s *testSuite3) TestInsertDateTimeWithTimeZone(c *C) { } } -func (s *testSuite3) TestInsertZeroYear(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertZeroYear(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t1(a year(4));`) @@ -493,8 +536,10 @@ func (s *testSuite3) TestInsertZeroYear(c *C) { )) } -func (s *testSuiteP1) TestAllowInvalidDates(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAllowInvalidDates(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t1, t2, t3, t4;`) tk.MustExec(`create table t1(d date);`) @@ -528,8 +573,10 @@ func (s *testSuiteP1) TestAllowInvalidDates(c *C) { runWithMode("ALLOW_INVALID_DATES") } -func (s *testSuite3) TestInsertWithAutoidSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertWithAutoidSchema(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t1(id int primary key auto_increment, n int);`) tk.MustExec(`create table t2(id int unsigned primary key auto_increment, n int);`) @@ -941,9 +988,9 @@ func (s *testSuite3) TestInsertWithAutoidSchema(c *C) { retryInfo := &variable.RetryInfo{Retrying: true} retryInfo.AddAutoIncrementID(1000) retryInfo.AddAutoIncrementID(1001) - tk.Se.GetSessionVars().RetryInfo = retryInfo + tk.Session().GetSessionVars().RetryInfo = retryInfo tk.MustExec(tt.insert[8:]) - tk.Se.GetSessionVars().RetryInfo = &variable.RetryInfo{} + tk.Session().GetSessionVars().RetryInfo = &variable.RetryInfo{} } else { tk.MustExec(tt.insert) } @@ -957,8 +1004,10 @@ func (s *testSuite3) TestInsertWithAutoidSchema(c *C) { } -func (s *testSuite3) TestPartitionInsertOnDuplicate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionInsertOnDuplicate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t1 (a int,b int,primary key(a,b)) partition by range(a) (partition p0 values less than (100),partition p1 values less than (1000))`) tk.MustExec(`insert into t1 set a=1, b=1`) @@ -983,34 +1032,38 @@ func (s *testSuite3) TestPartitionInsertOnDuplicate(c *C) { tk.MustQuery("select * from t3").Check(testkit.Rows("1 2 3 4 16")) } -func (s *testSuite3) TestBit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t1 (a bit(3))`) _, err := tk.Exec("insert into t1 values(-1)") - c.Assert(types.ErrDataTooLong.Equal(err), IsTrue) - c.Assert(err.Error(), Matches, ".*Data too long for column 'a' at.*") + require.True(t, types.ErrDataTooLong.Equal(err)) + require.Regexp(t, ".*Data too long for column 'a' at.*", err.Error()) _, err = tk.Exec("insert into t1 values(9)") - c.Assert(err.Error(), Matches, ".*Data too long for column 'a' at.*") + require.Regexp(t, ".*Data too long for column 'a' at.*", err.Error()) tk.MustExec(`create table t64 (a bit(64))`) tk.MustExec("insert into t64 values(-1)") tk.MustExec("insert into t64 values(18446744073709551615)") // 2^64 - 1 _, err = tk.Exec("insert into t64 values(18446744073709551616)") // z^64 - c.Assert(err.Error(), Matches, ".*Out of range value for column 'a' at.*") + require.Regexp(t, ".*Out of range value for column 'a' at.*", err.Error()) } -func (s *testSuiteP1) TestAllocateContinuousRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAllocateContinuousRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t1 (a int,b int, key I_a(a));`) - wg := sync.WaitGroup{} + var wg util.WaitGroupWrapper for i := 0; i < 5; i++ { - wg.Add(1) - go func(idx int) { - defer wg.Done() - tk := testkit.NewTestKitWithInit(c, s.store) + idx := i + wg.Run(func() { + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") for j := 0; j < 10; j++ { k := strconv.Itoa(idx*100 + j) sql := "insert into t1(a,b) values (" + k + ", 2)" @@ -1020,66 +1073,72 @@ func (s *testSuiteP1) TestAllocateContinuousRowID(c *C) { tk.MustExec(sql) q := "select _tidb_rowid from t1 where a=" + k rows := tk.MustQuery(q).Rows() - c.Assert(len(rows), Equals, 21) + require.Equal(t, 21, len(rows)) last := 0 for _, r := range rows { - c.Assert(len(r), Equals, 1) + require.Equal(t, 1, len(r)) v, err := strconv.Atoi(r[0].(string)) - c.Assert(err, Equals, nil) + require.Equal(t, nil, err) if last > 0 { - c.Assert(last+1, Equals, v) + require.Equal(t, v, last+1) } last = v } } - }(i) + }) } wg.Wait() } -func (s *testSuite3) TestJiraIssue5366(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJiraIssue5366(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table bug (a varchar(100))`) tk.MustExec(` insert into bug select ifnull(JSON_UNQUOTE(JSON_EXTRACT('[{"amount":2000,"feeAmount":0,"merchantNo":"20190430140319679394","shareBizCode":"20160311162_SECOND"}]', '$[0].merchantNo')),'') merchant_no union SELECT '20180531557' merchant_no;`) tk.MustQuery(`select * from bug`).Sort().Check(testkit.Rows("20180531557", "20190430140319679394")) } -func (s *testSuite3) TestDMLCast(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDMLCast(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t (a int, b double)`) tk.MustExec(`insert into t values (ifnull('',0)+0, 0)`) tk.MustExec(`insert into t values (0, ifnull('',0)+0)`) tk.MustQuery(`select * from t`).Check(testkit.Rows("0 0", "0 0")) _, err := tk.Exec(`insert into t values ('', 0)`) - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec(`insert into t values (0, '')`) - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec(`update t set a = ''`) - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec(`update t set b = ''`) - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("update t set a = ifnull('',0)+0") tk.MustExec("update t set b = ifnull('',0)+0") tk.MustExec("delete from t where a = ''") tk.MustQuery(`select * from t`).Check(testkit.Rows()) } -func (s *testSuite3) TestInsertFloatOverflow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertFloatOverflow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t,t1;`) tk.MustExec("create table t(col1 FLOAT, col2 FLOAT(10,2), col3 DOUBLE, col4 DOUBLE(10,2), col5 DECIMAL, col6 DECIMAL(10,2));") _, err := tk.Exec("insert into t values (-3.402823466E+68, -34028234.6611, -1.7976931348623157E+308, -17976921.34, -9999999999, -99999999.99);") - c.Assert(err.Error(), Equals, "[types:1264]Out of range value for column 'col1' at row 1") + require.EqualError(t, err, "[types:1264]Out of range value for column 'col1' at row 1") _, err = tk.Exec("insert into t values (-34028234.6611, -3.402823466E+68, -1.7976931348623157E+308, -17976921.34, -9999999999, -99999999.99);") - c.Assert(err.Error(), Equals, "[types:1264]Out of range value for column 'col2' at row 1") + require.EqualError(t, err, "[types:1264]Out of range value for column 'col2' at row 1") _, err = tk.Exec("create table t1(id1 float,id2 float)") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("insert ignore into t1 values(999999999999999999999999999999999999999,-999999999999999999999999999999999999999)") - c.Assert(err, IsNil) - tk.MustQuery("select @@warning_count").Check(testutil.RowsWithSep("|", "2")) + require.NoError(t, err) + tk.MustQuery("select @@warning_count").Check(testkit.RowsWithSep("|", "2")) tk.MustQuery("select convert(id1,decimal(65)),convert(id2,decimal(65)) from t1").Check(testkit.Rows("340282346638528860000000000000000000000 -340282346638528860000000000000000000000")) tk.MustExec("drop table if exists t,t1") } @@ -1088,12 +1147,14 @@ func (s *testSuite3) TestInsertFloatOverflow(c *C) { // than that of auto_increment_increment, the value of auto_increment_offset is ignored // (https://dev.mysql.com/doc/refman/8.0/en/replication-options-master.html#sysvar_auto_increment_increment), // This issue is a flaw of the implementation of MySQL and it doesn't exist in TiDB. -func (s *testSuite3) TestAutoIDIncrementAndOffset(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoIDIncrementAndOffset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) // Test for offset is larger than increment. - tk.Se.GetSessionVars().AutoIncrementIncrement = 5 - tk.Se.GetSessionVars().AutoIncrementOffset = 10 + tk.Session().GetSessionVars().AutoIncrementIncrement = 5 + tk.Session().GetSessionVars().AutoIncrementOffset = 10 tk.MustExec(`create table io (a int key auto_increment)`) tk.MustExec(`insert into io values (null),(null),(null)`) tk.MustQuery(`select * from io`).Check(testkit.Rows("10", "15", "20")) @@ -1101,31 +1162,31 @@ func (s *testSuite3) TestAutoIDIncrementAndOffset(c *C) { // Test handle is PK. tk.MustExec(`create table io (a int key auto_increment)`) - tk.Se.GetSessionVars().AutoIncrementOffset = 10 - tk.Se.GetSessionVars().AutoIncrementIncrement = 2 + tk.Session().GetSessionVars().AutoIncrementOffset = 10 + tk.Session().GetSessionVars().AutoIncrementIncrement = 2 tk.MustExec(`insert into io values (),(),()`) tk.MustQuery(`select * from io`).Check(testkit.Rows("10", "12", "14")) tk.MustExec(`delete from io`) // Test reset the increment. - tk.Se.GetSessionVars().AutoIncrementIncrement = 5 + tk.Session().GetSessionVars().AutoIncrementIncrement = 5 tk.MustExec(`insert into io values (),(),()`) tk.MustQuery(`select * from io`).Check(testkit.Rows("15", "20", "25")) tk.MustExec(`delete from io`) - tk.Se.GetSessionVars().AutoIncrementIncrement = 10 + tk.Session().GetSessionVars().AutoIncrementIncrement = 10 tk.MustExec(`insert into io values (),(),()`) tk.MustQuery(`select * from io`).Check(testkit.Rows("30", "40", "50")) tk.MustExec(`delete from io`) - tk.Se.GetSessionVars().AutoIncrementIncrement = 5 + tk.Session().GetSessionVars().AutoIncrementIncrement = 5 tk.MustExec(`insert into io values (),(),()`) tk.MustQuery(`select * from io`).Check(testkit.Rows("55", "60", "65")) tk.MustExec(`drop table io`) // Test handle is not PK. - tk.Se.GetSessionVars().AutoIncrementIncrement = 2 - tk.Se.GetSessionVars().AutoIncrementOffset = 10 + tk.Session().GetSessionVars().AutoIncrementIncrement = 2 + tk.Session().GetSessionVars().AutoIncrementOffset = 10 tk.MustExec(`create table io (a int, b int auto_increment, key(b))`) tk.MustExec(`insert into io(b) values (null),(null),(null)`) // AutoID allocation will take increment and offset into consideration. @@ -1134,62 +1195,102 @@ func (s *testSuite3) TestAutoIDIncrementAndOffset(c *C) { tk.MustQuery(`select _tidb_rowid from io`).Check(testkit.Rows("15", "16", "17")) tk.MustExec(`delete from io`) - tk.Se.GetSessionVars().AutoIncrementIncrement = 10 + tk.Session().GetSessionVars().AutoIncrementIncrement = 10 tk.MustExec(`insert into io(b) values (null),(null),(null)`) tk.MustQuery(`select b from io`).Check(testkit.Rows("20", "30", "40")) tk.MustQuery(`select _tidb_rowid from io`).Check(testkit.Rows("41", "42", "43")) // Test invalid value. - tk.Se.GetSessionVars().AutoIncrementIncrement = -1 - tk.Se.GetSessionVars().AutoIncrementOffset = -2 + tk.Session().GetSessionVars().AutoIncrementIncrement = -1 + tk.Session().GetSessionVars().AutoIncrementOffset = -2 _, err := tk.Exec(`insert into io(b) values (null),(null),(null)`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[autoid:8060]Invalid auto_increment settings: auto_increment_increment: -1, auto_increment_offset: -2, both of them must be in range [1..65535]") + require.Error(t, err) + require.EqualError(t, err, "[autoid:8060]Invalid auto_increment settings: auto_increment_increment: -1, auto_increment_offset: -2, both of them must be in range [1..65535]") tk.MustExec(`delete from io`) - tk.Se.GetSessionVars().AutoIncrementIncrement = 65536 - tk.Se.GetSessionVars().AutoIncrementOffset = 65536 + tk.Session().GetSessionVars().AutoIncrementIncrement = 65536 + tk.Session().GetSessionVars().AutoIncrementOffset = 65536 _, err = tk.Exec(`insert into io(b) values (null),(null),(null)`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[autoid:8060]Invalid auto_increment settings: auto_increment_increment: 65536, auto_increment_offset: 65536, both of them must be in range [1..65535]") + require.Error(t, err) + require.EqualError(t, err, "[autoid:8060]Invalid auto_increment settings: auto_increment_increment: 65536, auto_increment_offset: 65536, both of them must be in range [1..65535]") } -var _ = Suite(&testSuite9{&baseTestSuite{}}) +// Fix https://github.com/pingcap/tidb/issues/32601. +func TestTextTooLongError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // Set strict sql_mode + tk.MustExec("set sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';") + + // For max_allowed_packet default value is big enough to ensure tinytext, text can test correctly. + tk.MustExec(`drop table if exists t1;`) + tk.MustExec("CREATE TABLE t1(c1 TINYTEXT CHARACTER SET utf8mb4);") + _, err := tk.Exec("INSERT INTO t1 (c1) VALUES(REPEAT(X'C385', 128));") + require.EqualError(t, err, "[types:1406]Data too long for column 'c1' at row 1") + + tk.MustExec(`drop table if exists t1;`) + tk.MustExec("CREATE TABLE t1(c1 Text CHARACTER SET utf8mb4);") + _, err = tk.Exec("INSERT INTO t1 (c1) VALUES(REPEAT(X'C385', 32768));") + require.EqualError(t, err, "[types:1406]Data too long for column 'c1' at row 1") + + tk.MustExec(`drop table if exists t1;`) + tk.MustExec("CREATE TABLE t1(c1 mediumtext);") + _, err = tk.Exec("INSERT INTO t1 (c1) VALUES(REPEAT(X'C385', 8777215));") + require.EqualError(t, err, "[types:1406]Data too long for column 'c1' at row 1") + + // For long text, max_allowed_packet default value can not allow 4GB package, skip the test case. + + // Set non strict sql_mode, we are not supposed to raise an error but to truncate the value. + tk.MustExec("set sql_mode = 'ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';") -type testSuite9 struct { - *baseTestSuite + tk.MustExec(`drop table if exists t1;`) + tk.MustExec("CREATE TABLE t1(c1 TINYTEXT CHARACTER SET utf8mb4);") + _, err = tk.Exec("INSERT INTO t1 (c1) VALUES(REPEAT(X'C385', 128));") + require.NoError(t, err) + tk.MustQuery(`select length(c1) from t1;`).Check(testkit.Rows("254")) + + tk.MustExec(`drop table if exists t1;`) + tk.MustExec("CREATE TABLE t1(c1 Text CHARACTER SET utf8mb4);") + _, err = tk.Exec("INSERT INTO t1 (c1) VALUES(REPEAT(X'C385', 32768));") + require.NoError(t, err) + tk.MustQuery(`select length(c1) from t1;`).Check(testkit.Rows("65534")) + // For mediumtext or bigger size, for tikv limit, we will get:ERROR 8025 (HY000): entry too large, the max entry size is 6291456, the size of data is 16777247, no need to test. } -func (s *testSuite9) TestAutoRandomID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists ar`) tk.MustExec(`create table ar (id bigint key clustered auto_random, name char(10))`) tk.MustExec(`insert into ar(id) values (null)`) rs := tk.MustQuery(`select id from ar`) - c.Assert(len(rs.Rows()), Equals, 1) + require.Equal(t, 1, len(rs.Rows())) firstValue, err := strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) + require.NoError(t, err) + require.Greater(t, firstValue, 0) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`delete from ar`) tk.MustExec(`insert into ar(id) values (0)`) rs = tk.MustQuery(`select id from ar`) - c.Assert(len(rs.Rows()), Equals, 1) + require.Equal(t, 1, len(rs.Rows())) firstValue, err = strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) + require.NoError(t, err) + require.Greater(t, firstValue, 0) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`delete from ar`) tk.MustExec(`insert into ar(name) values ('a')`) rs = tk.MustQuery(`select id from ar`) - c.Assert(len(rs.Rows()), Equals, 1) + require.Equal(t, 1, len(rs.Rows())) firstValue, err = strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) + require.NoError(t, err) + require.Greater(t, firstValue, 0) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`drop table ar`) @@ -1197,53 +1298,57 @@ func (s *testSuite9) TestAutoRandomID(c *C) { overflowVal := 1 << (64 - 5) errMsg := fmt.Sprintf(autoid.AutoRandomRebaseOverflow, overflowVal, 1<<(64-16)-1) _, err = tk.Exec(fmt.Sprintf("alter table ar auto_random_base = %d", overflowVal)) - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), errMsg), IsTrue) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), errMsg)) } -func (s *testSuite9) TestMultiAutoRandomID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiAutoRandomID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists ar`) tk.MustExec(`create table ar (id bigint key clustered auto_random, name char(10))`) tk.MustExec(`insert into ar(id) values (null),(null),(null)`) rs := tk.MustQuery(`select id from ar order by id`) - c.Assert(len(rs.Rows()), Equals, 3) + require.Equal(t, 3, len(rs.Rows())) firstValue, err := strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) - c.Assert(rs.Rows()[1][0].(string), Equals, fmt.Sprintf("%d", firstValue+1)) - c.Assert(rs.Rows()[2][0].(string), Equals, fmt.Sprintf("%d", firstValue+2)) + require.NoError(t, err) + require.Greater(t, firstValue, 0) + require.Equal(t, fmt.Sprintf("%d", firstValue+1), rs.Rows()[1][0].(string)) + require.Equal(t, fmt.Sprintf("%d", firstValue+2), rs.Rows()[2][0].(string)) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`delete from ar`) tk.MustExec(`insert into ar(id) values (0),(0),(0)`) rs = tk.MustQuery(`select id from ar order by id`) - c.Assert(len(rs.Rows()), Equals, 3) + require.Equal(t, 3, len(rs.Rows())) firstValue, err = strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) - c.Assert(rs.Rows()[1][0].(string), Equals, fmt.Sprintf("%d", firstValue+1)) - c.Assert(rs.Rows()[2][0].(string), Equals, fmt.Sprintf("%d", firstValue+2)) + require.NoError(t, err) + require.Greater(t, firstValue, 0) + require.Equal(t, fmt.Sprintf("%d", firstValue+1), rs.Rows()[1][0].(string)) + require.Equal(t, fmt.Sprintf("%d", firstValue+2), rs.Rows()[2][0].(string)) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`delete from ar`) tk.MustExec(`insert into ar(name) values ('a'),('a'),('a')`) rs = tk.MustQuery(`select id from ar order by id`) - c.Assert(len(rs.Rows()), Equals, 3) + require.Equal(t, 3, len(rs.Rows())) firstValue, err = strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) - c.Assert(rs.Rows()[1][0].(string), Equals, fmt.Sprintf("%d", firstValue+1)) - c.Assert(rs.Rows()[2][0].(string), Equals, fmt.Sprintf("%d", firstValue+2)) + require.NoError(t, err) + require.Greater(t, firstValue, 0) + require.Equal(t, fmt.Sprintf("%d", firstValue+1), rs.Rows()[1][0].(string)) + require.Equal(t, fmt.Sprintf("%d", firstValue+2), rs.Rows()[2][0].(string)) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`drop table ar`) } -func (s *testSuite9) TestAutoRandomIDAllowZero(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomIDAllowZero(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists ar`) tk.MustExec(`create table ar (id bigint key clustered auto_random, name char(10))`) @@ -1254,26 +1359,28 @@ func (s *testSuite9) TestAutoRandomIDAllowZero(c *C) { tk.MustExec(`insert into ar(id) values (0)`) rs = tk.MustQuery(`select id from ar`) - c.Assert(len(rs.Rows()), Equals, 1) + require.Equal(t, 1, len(rs.Rows())) firstValue, err := strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Equals, 0) + require.NoError(t, err) + require.Equal(t, 0, firstValue) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`delete from ar`) tk.MustExec(`insert into ar(id) values (null)`) rs = tk.MustQuery(`select id from ar`) - c.Assert(len(rs.Rows()), Equals, 1) + require.Equal(t, 1, len(rs.Rows())) firstValue, err = strconv.Atoi(rs.Rows()[0][0].(string)) - c.Assert(err, IsNil) - c.Assert(firstValue, Greater, 0) + require.NoError(t, err) + require.Greater(t, firstValue, 0) tk.MustQuery(`select last_insert_id()`).Check(testkit.Rows(fmt.Sprintf("%d", firstValue))) tk.MustExec(`drop table ar`) } -func (s *testSuite9) TestAutoRandomIDExplicit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomIDExplicit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@allow_auto_random_explicit_insert = true") tk.MustExec(`use test`) @@ -1293,37 +1400,37 @@ func (s *testSuite9) TestAutoRandomIDExplicit(c *C) { tk.MustExec(`drop table ar`) } -func (s *testSuite9) TestInsertErrorMsg(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertErrorMsg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t (a int primary key, b datetime, d date)`) _, err := tk.Exec(`insert into t values (1, '2019-02-11 30:00:00', '2019-01-31')`) - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Incorrect datetime value: '2019-02-11 30:00:00' for column 'b' at row 1"), IsTrue, Commentf("%v", err)) + require.Error(t, err) + require.Contains(t, err.Error(), "Incorrect datetime value: '2019-02-11 30:00:00' for column 'b' at row 1") } -func (s *testSuite9) TestIssue16366(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16366(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test;`) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(c numeric primary key);`) tk.MustExec("insert ignore into t values(null);") _, err := tk.Exec(`insert into t values(0);`) - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Duplicate entry '0' for key 'PRIMARY'"), IsTrue, Commentf("%v", err)) -} - -var _ = SerialSuites(&testSuite10{&baseTestSuite{}}) - -type testSuite10 struct { - *baseTestSuite + require.Error(t, err) + require.Contains(t, err.Error(), "Duplicate entry '0' for key 'PRIMARY'") } -func (s *testSuite10) TestClusterPrimaryTablePlainInsert(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterPrimaryTablePlainInsert(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists t1pk`) tk.MustExec(`create table t1pk(id varchar(200) primary key, v int)`) @@ -1362,10 +1469,12 @@ func (s *testSuite10) TestClusterPrimaryTablePlainInsert(c *C) { Check(testkit.Rows("abc xyz 1 100", "abc xyz 1 101", "abc zzz 1 101")) } -func (s *testSuite10) TestClusterPrimaryTableInsertIgnore(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterPrimaryTableInsertIgnore(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists it1pk`) tk.MustExec(`create table it1pk(id varchar(200) primary key, v int)`) @@ -1388,10 +1497,12 @@ func (s *testSuite10) TestClusterPrimaryTableInsertIgnore(c *C) { tk.MustQuery(`select * from it1pku`).Check(testkit.Rows("abc 1 2", "bbb 2 1")) } -func (s *testSuite10) TestClusterPrimaryTableInsertDuplicate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterPrimaryTableInsertDuplicate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists dt1pi`) tk.MustExec(`create table dt1pi(id varchar(200) primary key, v int)`) @@ -1420,10 +1531,12 @@ func (s *testSuite10) TestClusterPrimaryTableInsertDuplicate(c *C) { tk.MustQuery(`select id1, id2, v from ts1pk`).Check(testkit.Rows("2018-01-01 11:11:12 2018-01-01 11:11:11 2")) } -func (s *testSuite10) TestClusterPrimaryKeyForIndexScan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterPrimaryKeyForIndexScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists pkt1;") tk.MustExec("CREATE TABLE pkt1 (a varchar(255), b int, index idx(b), primary key(a,b));") @@ -1449,10 +1562,10 @@ func (s *testSuite10) TestClusterPrimaryKeyForIndexScan(c *C) { tk.MustExec(sql) cnt++ } - c.Assert(cnt, Equals, 15) + require.Equal(t, 15, cnt) } -func (s *testSuite10) TestInsertRuntimeStat(c *C) { +func TestInsertRuntimeStat(t *testing.T) { stats := &executor.InsertRuntimeStat{ BasicRuntimeStats: &execdetails.BasicRuntimeStats{}, SnapshotRuntimeStats: nil, @@ -1460,20 +1573,19 @@ func (s *testSuite10) TestInsertRuntimeStat(c *C) { Prefetch: 1 * time.Second, } stats.BasicRuntimeStats.Record(5*time.Second, 1) - c.Assert(stats.String(), Equals, "prepare: 3s, check_insert: {total_time: 2s, mem_insert_time: 1s, prefetch: 1s}") - c.Assert(stats.String(), Equals, stats.Clone().String()) + require.Equal(t, "prepare: 3s, check_insert: {total_time: 2s, mem_insert_time: 1s, prefetch: 1s}", stats.String()) + require.Equal(t, stats.Clone().String(), stats.String()) stats.Merge(stats.Clone()) - c.Assert(stats.String(), Equals, "prepare: 6s, check_insert: {total_time: 4s, mem_insert_time: 2s, prefetch: 2s}") + require.Equal(t, "prepare: 6s, check_insert: {total_time: 4s, mem_insert_time: 2s, prefetch: 2s}", stats.String()) } -func (s *testSerialSuite) TestDuplicateEntryMessage(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - - tk := testkit.NewTestKit(c, s.store) +func TestDuplicateEntryMessage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") for _, enable := range []variable.ClusteredIndexDefMode{variable.ClusteredIndexDefModeOn, variable.ClusteredIndexDefModeOff, variable.ClusteredIndexDefModeIntOnly} { - tk.Se.GetSessionVars().EnableClusteredIndex = enable + tk.Session().GetSessionVars().EnableClusteredIndex = enable tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b char(10), unique key(b)) collate utf8mb4_general_ci;") tk.MustExec("insert into t value (34, '12Ak');") @@ -1518,7 +1630,7 @@ func (s *testSerialSuite) TestDuplicateEntryMessage(c *C) { tk.MustExec("create table t (a char(10) collate utf8mb4_unicode_ci, b char(20) collate utf8mb4_general_ci, c int(11), primary key (a, b, c), unique key (a));") tk.MustExec("insert ignore into t values ('$', 'C', 10);") tk.MustExec("insert ignore into t values ('$', 'C', 10);") - tk.MustQuery("show warnings;").Check(testutil.RowsWithSep("|", "Warning|1062|Duplicate entry '$-C-10' for key 'PRIMARY'")) + tk.MustQuery("show warnings;").Check(testkit.RowsWithSep("|", "Warning|1062|Duplicate entry '$-C-10' for key 'PRIMARY'")) tk.MustExec("begin pessimistic;") tk.MustExec("insert into t values ('a7', 'a', 10);") @@ -1534,8 +1646,10 @@ func (s *testSerialSuite) TestDuplicateEntryMessage(c *C) { } } -func (s *testSerialSuite) TestIssue20768(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20768(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a year, primary key(a))") @@ -1550,18 +1664,21 @@ func (s *testSerialSuite) TestIssue20768(c *C) { tk.MustQuery("select /*+ merge_join(t1) */ * from t1 join t2 on t1.a = t2.a").Check(testkit.Rows("0 0")) } -func (s *testSuite9) TestIssue10402(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10402(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table vctt (v varchar(4), c char(4))") tk.MustExec("insert into vctt values ('ab ', 'ab ')") tk.MustQuery("select * from vctt").Check(testkit.Rows("ab ab")) tk.MustExec("delete from vctt") - tk.Se.GetSessionVars().StmtCtx.SetWarnings(nil) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) tk.MustExec("insert into vctt values ('ab\\n\\n\\n', 'ab\\n\\n\\n'), ('ab\\t\\t\\t', 'ab\\t\\t\\t'), ('ab ', 'ab '), ('ab\\r\\r\\r', 'ab\\r\\r\\r')") - c.Check(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(4)) - warns := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Check(fmt.Sprintf("%v", warns), Equals, "[{Warning [types:1265]Data truncated, field len 4, data len 5} {Warning [types:1265]Data truncated, field len 4, data len 5} {Warning [types:1265]Data truncated, field len 4, data len 6} {Warning [types:1265]Data truncated, field len 4, data len 5}]") + require.Equal(t, uint16(4), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Equal(t, "[{Warning [types:1265]Data truncated, field len 4, data len 5} {Warning [types:1265]Data truncated, field len 4, data len 5} {Warning [types:1265]Data truncated, field len 4, data len 6} {Warning [types:1265]Data truncated, field len 4, data len 5}]", + fmt.Sprintf("%v", warns)) tk.MustQuery("select * from vctt").Check(testkit.Rows("ab\n\n ab\n\n", "ab\t\t ab\t\t", "ab ab", "ab\r\r ab\r\r")) tk.MustQuery("select length(v), length(c) from vctt").Check(testkit.Rows("4 4", "4 4", "4 2", "4 4")) } @@ -1585,23 +1702,27 @@ func combination(items []string) func() []string { } // TestDuplicatedEntryErr See https://github.com/pingcap/tidb/issues/24582 -func (s *testSuite10) TestDuplicatedEntryErr(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDuplicatedEntryErr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(a int, b varchar(20), primary key(a,b(3)) clustered);") tk.MustExec("insert into t1 values(1,'aaaaa');") err := tk.ExecToErr("insert into t1 values(1,'aaaaa');") - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1-aaa' for key 'PRIMARY'") + require.EqualError(t, err, "[kv:1062]Duplicate entry '1-aaa' for key 'PRIMARY'") err = tk.ExecToErr("insert into t1 select 1, 'aaa'") - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1-aaa' for key 'PRIMARY'") + require.EqualError(t, err, "[kv:1062]Duplicate entry '1-aaa' for key 'PRIMARY'") tk.MustExec("insert into t1 select 1, 'bb'") err = tk.ExecToErr("insert into t1 select 1, 'bb'") - c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1-bb' for key 'PRIMARY'") + require.EqualError(t, err, "[kv:1062]Duplicate entry '1-bb' for key 'PRIMARY'") } -func (s *testSuite10) TestBinaryLiteralInsertToEnum(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBinaryLiteralInsertToEnum(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists bintest") @@ -1610,8 +1731,10 @@ func (s *testSuite10) TestBinaryLiteralInsertToEnum(c *C) { tk.MustQuery("select * from bintest").Check(testkit.Rows("a")) } -func (s *testSuite10) TestBinaryLiteralInsertToSet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBinaryLiteralInsertToSet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists bintest") @@ -1620,14 +1743,10 @@ func (s *testSuite10) TestBinaryLiteralInsertToSet(c *C) { tk.MustQuery("select * from bintest").Check(testkit.Rows("a")) } -var _ = SerialSuites(&testSuite13{&baseTestSuite{}}) - -type testSuite13 struct { - *baseTestSuite -} - -func (s *testSuite13) TestGlobalTempTableAutoInc(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGlobalTempTableAutoInc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists temp_test") tk.MustExec("create global temporary table temp_test(id int primary key auto_increment) on commit delete rows") @@ -1671,8 +1790,10 @@ func (s *testSuite13) TestGlobalTempTableAutoInc(c *C) { tk.MustExec("commit") } -func (s *testSuite13) TestGlobalTempTableRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGlobalTempTableRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists temp_test") tk.MustExec("create global temporary table temp_test(id int) on commit delete rows") @@ -1706,8 +1827,10 @@ func (s *testSuite13) TestGlobalTempTableRowID(c *C) { tk.MustExec("commit") } -func (s *testSuite13) TestGlobalTempTableParallel(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGlobalTempTableParallel(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists temp_test") tk.MustExec("create global temporary table temp_test(id int primary key auto_increment) on commit delete rows") @@ -1715,12 +1838,11 @@ func (s *testSuite13) TestGlobalTempTableParallel(c *C) { threads := 8 loops := 1 - wg := sync.WaitGroup{} - wg.Add(threads) + var wg util.WaitGroupWrapper insertFunc := func() { - defer wg.Done() - newTk := testkit.NewTestKitWithInit(c, s.store) + newTk := testkit.NewTestKit(t, store) + newTk.MustExec("use test") newTk.MustExec("begin") for i := 0; i < loops; i++ { newTk.MustExec("insert temp_test value(0)") @@ -1732,18 +1854,20 @@ func (s *testSuite13) TestGlobalTempTableParallel(c *C) { } for i := 0; i < threads; i++ { - go insertFunc() + wg.Run(insertFunc) } wg.Wait() } -func (s *testSuite13) TestIssue26762(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26762(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(c1 date);") _, err := tk.Exec("insert into t1 values('2020-02-31');") - c.Assert(err.Error(), Equals, `[table:1292]Incorrect date value: '2020-02-31' for column 'c1' at row 1`) + require.EqualError(t, err, `[table:1292]Incorrect date value: '2020-02-31' for column 'c1' at row 1`) tk.MustExec("set @@sql_mode='ALLOW_INVALID_DATES';") tk.MustExec("insert into t1 values('2020-02-31');") @@ -1751,11 +1875,13 @@ func (s *testSuite13) TestIssue26762(c *C) { tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES';") _, err = tk.Exec("insert into t1 values('2020-02-31');") - c.Assert(err.Error(), Equals, `[table:1292]Incorrect date value: '2020-02-31' for column 'c1' at row 1`) + require.EqualError(t, err, `[table:1292]Incorrect date value: '2020-02-31' for column 'c1' at row 1`) } -func (s *testSuite10) TestStringtoDecimal(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStringtoDecimal(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id decimal(10))") @@ -1769,13 +1895,15 @@ func (s *testSuite10) TestStringtoDecimal(c *C) { tk.MustGetErrCode("insert into t values('1.2.')", errno.ErrTruncatedWrongValueForField) tk.MustGetErrCode("insert into t values('1,999.00')", errno.ErrTruncatedWrongValueForField) tk.MustExec("insert into t values('12e-3')") - tk.MustQuery("show warnings;").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect DECIMAL value: '0.012'")) + tk.MustQuery("show warnings;").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DECIMAL value: '0.012'")) tk.MustQuery("select id from t").Check(testkit.Rows("0")) tk.MustExec("drop table if exists t") } -func (s *testSuite13) TestIssue17745(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue17745(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("drop table if exists tt1") tk.MustExec("create table tt1 (c1 decimal(64))") @@ -1788,12 +1916,14 @@ func (s *testSuite13) TestIssue17745(c *C) { tk.MustExec("drop table if exists tt1") tk.MustGetErrCode("insert into tt1 values(4556414e723532)", errno.ErrIllegalValueForType) tk.MustQuery("select 888888888888888888888888888888888888888888888888888888888888888888888888888888888888").Check(testkit.Rows("99999999999999999999999999999999999999999999999999999999999999999")) - tk.MustQuery("show warnings;").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect DECIMAL value: '888888888888888888888888888888888888888888888888888888888888888888888888888888888'")) + tk.MustQuery("show warnings;").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DECIMAL value: '888888888888888888888888888888888888888888888888888888888888888888888888888888888'")) } // TestInsertIssue29892 test the double type with auto_increment problem, just leverage the serial test suite. -func (s *testAutoRandomSuite) TestInsertIssue29892(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInsertIssue29892(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("set global tidb_txn_mode='optimistic';") @@ -1802,12 +1932,12 @@ func (s *testAutoRandomSuite) TestInsertIssue29892(c *C) { tk.MustExec("create table t(a double auto_increment key, b int)") tk.MustExec("insert into t values (146576794, 1)") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec(`use test`) tk1.MustExec("begin") tk1.MustExec("insert into t(b) select 1") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec(`use test`) tk2.MustExec("begin") tk2.MustExec("insert into t values (146576795, 1)") @@ -1817,13 +1947,15 @@ func (s *testAutoRandomSuite) TestInsertIssue29892(c *C) { // since the origin auto-id (146576795) is cached in retryInfo, it will be fetched again to do the retry again, // which will duplicate with what has been inserted in tk1. _, err := tk1.Exec("commit") - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Duplicate entry"), Equals, true) + require.Error(t, err) + require.Equal(t, true, strings.Contains(err.Error(), "Duplicate entry")) } // https://github.com/pingcap/tidb/issues/29483. -func (s *testSuite13) TestReplaceAllocatingAutoID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReplaceAllocatingAutoID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists replace_auto_id;") tk.MustExec("create database replace_auto_id;") tk.MustExec(`use replace_auto_id;`) @@ -1835,3 +1967,39 @@ func (s *testSuite13) TestReplaceAllocatingAutoID(c *C) { // Note that this error is different from MySQL's duplicated primary key error. tk.MustGetErrCode("REPLACE INTO t1 VALUES (0,'newmaxvalue');", errno.ErrAutoincReadFailed) } + +func TestInsertIntoSelectError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("DROP TABLE IF EXISTS t1;") + tk.MustExec("CREATE TABLE t1(a INT) ENGINE = InnoDB;") + tk.MustExec("INSERT IGNORE into t1(SELECT SLEEP(NULL));") + tk.MustQuery("SHOW WARNINGS;").Check(testkit.Rows("Warning 1210 Incorrect arguments to sleep")) + tk.MustExec("INSERT IGNORE into t1(SELECT SLEEP(-1));") + tk.MustQuery("SHOW WARNINGS;").Check(testkit.Rows("Warning 1210 Incorrect arguments to sleep")) + tk.MustExec("INSERT IGNORE into t1(SELECT SLEEP(1));") + tk.MustQuery("SELECT * FROM t1;").Check(testkit.Rows("0", "0", "0")) + tk.MustExec("DROP TABLE t1;") +} + +// https://github.com/pingcap/tidb/issues/32213. +func TestIssue32213(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + + tk.MustExec("create table test.t1(c1 float)") + tk.MustExec("insert into test.t1 values(999.99)") + tk.MustQuery("select cast(test.t1.c1 as decimal(4, 1)) from test.t1").Check(testkit.Rows("999.9")) + tk.MustQuery("select cast(test.t1.c1 as decimal(5, 1)) from test.t1").Check(testkit.Rows("1000.0")) + + tk.MustExec("drop table if exists test.t1") + tk.MustExec("create table test.t1(c1 decimal(6, 4))") + tk.MustExec("insert into test.t1 values(99.9999)") + tk.MustQuery("select cast(test.t1.c1 as decimal(5, 3)) from test.t1").Check(testkit.Rows("99.999")) + tk.MustQuery("select cast(test.t1.c1 as decimal(6, 3)) from test.t1").Check(testkit.Rows("100.000")) +} diff --git a/executor/inspection_common_test.go b/executor/inspection_common_test.go index 61eb1cfb20e9f..ade12a61e6c4b 100644 --- a/executor/inspection_common_test.go +++ b/executor/inspection_common_test.go @@ -16,16 +16,19 @@ package executor_test import ( "context" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *inspectionSummarySuite) TestInspectionRules(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInspectionRules(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) inspectionCount := len(executor.InspectionRules) summaryCount := len(executor.InspectionSummaryRules) var cases = []struct { @@ -52,10 +55,10 @@ func (s *inspectionSummarySuite) TestInspectionRules(c *C) { for _, ca := range cases { rs, err := tk.Exec(ca.sql) - c.Assert(err, IsNil) - rules, err := session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) - c.Assert(len(rules), Equals, ca.ruleCount) - c.Assert(rs.Close(), IsNil) + require.NoError(t, err) + rules, err := session.ResultSetToStringSlice(context.Background(), tk.Session(), rs) + require.NoError(t, err) + require.Len(t, rules, ca.ruleCount) + require.NoError(t, rs.Close()) } } diff --git a/executor/inspection_profile.go b/executor/inspection_profile.go index 90ea2bc224c5f..15885010dce25 100644 --- a/executor/inspection_profile.go +++ b/executor/inspection_profile.go @@ -167,12 +167,7 @@ func (n *metricNode) getLabelValue(label string) *metricValue { func (n *metricNode) queryRowsByLabel(pb *profileBuilder, query string, handleRowFn func(label string, v float64)) error { exec := pb.sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), query) - if err != nil { - return err - } - - rows, _, err := pb.sctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, query) if err != nil { return err } diff --git a/executor/inspection_result.go b/executor/inspection_result.go index bb26993824684..debcf723a3e64 100644 --- a/executor/inspection_result.go +++ b/executor/inspection_result.go @@ -140,10 +140,7 @@ func (e *inspectionResultRetriever) retrieve(ctx context.Context, sctx sessionct e.statusToInstanceAddress = make(map[string]string) var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "select instance,status_address from information_schema.cluster_info;") - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select instance,status_address from information_schema.cluster_info;") if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("get cluster info failed: %v", err)) } @@ -249,22 +246,14 @@ func (configInspection) inspectDiffConfig(ctx context.Context, sctx sessionctx.C "storage.data-dir", "storage.block-cache.capacity", } - var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "select type, `key`, count(distinct value) as c from information_schema.cluster_config where `key` not in (%?) group by type, `key` having c > 1", ignoreConfigKey) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select type, `key`, count(distinct value) as c from information_schema.cluster_config where `key` not in (%?) group by type, `key` having c > 1", ignoreConfigKey) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("check configuration consistency failed: %v", err)) } generateDetail := func(tp, item string) string { - var rows []chunk.Row - stmt, err := exec.ParseWithParams(ctx, "select value, instance from information_schema.cluster_config where type=%? and `key`=%?;", tp, item) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select value, instance from information_schema.cluster_config where type=%? and `key`=%?;", tp, item) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("check configuration consistency failed: %v", err)) return fmt.Sprintf("the cluster has different config value of %[2]s, execute the sql to see more detail: select * from information_schema.cluster_config where type='%[1]s' and `key`='%[2]s'", @@ -376,12 +365,8 @@ func (c configInspection) checkTiKVBlockCacheSizeConfig(ctx context.Context, sct if !filter.enable(item) { return nil } - var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "select instance,value from information_schema.cluster_config where type='tikv' and `key` = 'storage.block-cache.capacity'") - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select instance,value from information_schema.cluster_config where type='tikv' and `key` = 'storage.block-cache.capacity'") if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("check configuration in reason failed: %v", err)) } @@ -405,10 +390,7 @@ func (c configInspection) checkTiKVBlockCacheSizeConfig(ctx context.Context, sct ipToCount[ip]++ } - stmt, err = exec.ParseWithParams(ctx, "select instance, value from metrics_schema.node_total_memory where time=now()") - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err = exec.ExecRestrictedSQL(ctx, nil, "select instance, value from metrics_schema.node_total_memory where time=now()") if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("check configuration in reason failed: %v", err)) } @@ -471,12 +453,8 @@ func (configInspection) convertReadableSizeToByteSize(sizeStr string) (uint64, e func (versionInspection) inspect(ctx context.Context, sctx sessionctx.Context, filter inspectionFilter) []inspectionResult { exec := sctx.(sqlexec.RestrictedSQLExecutor) - var rows []chunk.Row // check the configuration consistent - stmt, err := exec.ParseWithParams(ctx, "select type, count(distinct git_hash) as c from information_schema.cluster_info group by type having c > 1;") - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "select type, count(distinct git_hash) as c from information_schema.cluster_info group by type having c > 1;") if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("check version consistency failed: %v", err)) } @@ -630,7 +608,6 @@ func (criticalErrorInspection) inspectError(ctx context.Context, sctx sessionctx condition := filter.timeRange.Condition() var results []inspectionResult - var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) sql := new(strings.Builder) for _, rule := range rules { @@ -643,10 +620,7 @@ func (criticalErrorInspection) inspectError(ctx context.Context, sctx sessionctx sql.Reset() fmt.Fprintf(sql, "select `%[1]s`,sum(value) as total from `%[2]s`.`%[3]s` %[4]s group by `%[1]s` having total>=1.0", strings.Join(def.Labels, "`,`"), util.MetricSchemaName.L, rule.tbl, condition) - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) continue @@ -697,15 +671,11 @@ func (criticalErrorInspection) inspectForServerDown(ctx context.Context, sctx se fmt.Fprintf(sql, `select t1.job,t1.instance, t2.min_time from (select instance,job from metrics_schema.up %[1]s group by instance,job having max(value)-min(value)>0) as t1 join (select instance,min(time) as min_time from metrics_schema.up %[1]s and value=0 group by instance,job) as t2 on t1.instance=t2.instance order by job`, condition) - var rows []chunk.Row - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) } - var results []inspectionResult + results := make([]inspectionResult, 0, len(rows)) for _, row := range rows { if row.Len() < 3 { continue @@ -726,10 +696,7 @@ func (criticalErrorInspection) inspectForServerDown(ctx context.Context, sctx se // Check from log. sql.Reset() fmt.Fprintf(sql, "select type,instance,time from information_schema.cluster_log %s and level = 'info' and message like '%%Welcome to'", condition) - stmt, err = exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err = exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) } @@ -843,7 +810,6 @@ func (thresholdCheckInspection) inspectThreshold1(ctx context.Context, sctx sess condition := filter.timeRange.Condition() var results []inspectionResult - var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) sql := new(strings.Builder) for _, rule := range rules { @@ -863,10 +829,7 @@ func (thresholdCheckInspection) inspectThreshold1(ctx context.Context, sctx sess (select instance, max(value) as cpu from metrics_schema.tikv_thread_cpu %[3]s and name like '%[1]s' group by instance) as t1 where t1.cpu > %[2]f;`, rule.component, rule.threshold, condition) } - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) continue @@ -1016,7 +979,6 @@ func (thresholdCheckInspection) inspectThreshold2(ctx context.Context, sctx sess condition := filter.timeRange.Condition() var results []inspectionResult - var rows []chunk.Row sql := new(strings.Builder) exec := sctx.(sqlexec.RestrictedSQLExecutor) for _, rule := range rules { @@ -1036,10 +998,7 @@ func (thresholdCheckInspection) inspectThreshold2(ctx context.Context, sctx sess } else { fmt.Fprintf(sql, "select instance, max(value)/%.0f as max_value from metrics_schema.%s %s group by instance having max_value > %f;", rule.factor, rule.tbl, cond, rule.threshold) } - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) continue @@ -1215,17 +1174,13 @@ func (thresholdCheckInspection) inspectThreshold3(ctx context.Context, sctx sess func checkRules(ctx context.Context, sctx sessionctx.Context, filter inspectionFilter, rules []ruleChecker) []inspectionResult { var results []inspectionResult - var rows []chunk.Row exec := sctx.(sqlexec.RestrictedSQLExecutor) for _, rule := range rules { if !filter.enable(rule.getItem()) { continue } sql := rule.genSQL(filter.timeRange) - stmt, err := exec.ParseWithParams(ctx, sql) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) continue @@ -1244,11 +1199,7 @@ func (c thresholdCheckInspection) inspectForLeaderDrop(ctx context.Context, sctx fmt.Fprintf(sql, `select address,min(value) as mi,max(value) as mx from metrics_schema.pd_scheduler_store_status %s and type='leader_count' group by address having mx-mi>%v`, condition, threshold) exec := sctx.(sqlexec.RestrictedSQLExecutor) - var rows []chunk.Row - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) return nil @@ -1259,10 +1210,7 @@ func (c thresholdCheckInspection) inspectForLeaderDrop(ctx context.Context, sctx sql.Reset() fmt.Fprintf(sql, `select time, value from metrics_schema.pd_scheduler_store_status %s and type='leader_count' and address = '%s' order by time`, condition, address) var subRows []chunk.Row - stmt, err := exec.ParseWithParams(ctx, sql.String()) - if err == nil { - subRows, _, err = exec.ExecRestrictedStmt(ctx, stmt) - } + subRows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql.String()) if err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("execute '%s' failed: %v", sql, err)) continue diff --git a/executor/inspection_result_test.go b/executor/inspection_result_test.go index 7255a44b85ea3..d53040dcfff8e 100644 --- a/executor/inspection_result_test.go +++ b/executor/inspection_result_test.go @@ -17,24 +17,29 @@ package executor_test import ( "context" "fmt" + "net" + "path/filepath" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" + "github.com/pingcap/kvproto/pkg/diagnosticspb" + "github.com/pingcap/sysutil" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" ) -var _ = SerialSuites(&inspectionResultSuite{&testClusterTableBase{}}) - -type inspectionResultSuite struct{ *testClusterTableBase } - -func (s *inspectionResultSuite) TestInspectionResult(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInspectionResult(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") mockData := map[string]variable.TableSnapshot{} // mock configuration inconsistent @@ -106,7 +111,7 @@ func (s *inspectionResultSuite) TestInspectionResult(c *C) { } datetime := func(str string) types.Time { - return s.parseTime(c, tk.Se, str) + return parseTime(t, tk.Session(), str) } // construct some mock abnormal data mockMetric := map[string][][]types.Datum{ @@ -117,8 +122,8 @@ func (s *inspectionResultSuite) TestInspectionResult(c *C) { }, } - ctx := s.setupForInspection(c, mockMetric, mockData) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockMetric, mockData) + defer cleanup() cases := []struct { sql string @@ -166,30 +171,22 @@ func (s *inspectionResultSuite) TestInspectionResult(c *C) { } for _, cs := range cases { - rs, err := tk.Se.Execute(ctx, cs.sql) - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("SQL: %v", cs.sql)) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, 0, Commentf("expected no warning, got: %+v", warnings)) + rs, err := tk.Session().Execute(ctx, cs.sql) + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], fmt.Sprintf("SQL: %v", cs.sql)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expected no warning, got: %+v", warnings) result.Check(testkit.Rows(cs.rows...)) } } -func (s *inspectionResultSuite) parseTime(c *C, se session.Session, str string) types.Time { - t, err := types.ParseTime(se.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t -} - -func (s *inspectionResultSuite) tearDownForInspection(c *C) { - fpName := "github.com/pingcap/tidb/executor/mockMergeMockInspectionTables" - c.Assert(failpoint.Disable(fpName), IsNil) - - fpName2 := "github.com/pingcap/tidb/executor/mockMetricsTableData" - c.Assert(failpoint.Disable(fpName2), IsNil) +func parseTime(t *testing.T, se session.Session, str string) types.Time { + time, err := types.ParseTime(se.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } -func (s *inspectionResultSuite) setupForInspection(c *C, mockData map[string][][]types.Datum, configurations map[string]variable.TableSnapshot) context.Context { +func createInspectionContext(t *testing.T, mockData map[string][][]types.Datum, configurations map[string]variable.TableSnapshot) (context.Context, func()) { // mock tikv configuration. if configurations == nil { configurations = map[string]variable.TableSnapshot{} @@ -228,25 +225,31 @@ func (s *inspectionResultSuite) setupForInspection(c *C, mockData map[string][][ }, } } - fpName := "github.com/pingcap/tidb/executor/mockMergeMockInspectionTables" - c.Assert(failpoint.Enable(fpName, "return"), IsNil) + fpName0 := "github.com/pingcap/tidb/executor/mockMergeMockInspectionTables" + require.NoError(t, failpoint.Enable(fpName0, "return")) // Mock for metric table data. - fpName2 := "github.com/pingcap/tidb/executor/mockMetricsTableData" - c.Assert(failpoint.Enable(fpName2, "return"), IsNil) + fpName1 := "github.com/pingcap/tidb/executor/mockMetricsTableData" + require.NoError(t, failpoint.Enable(fpName1, "return")) ctx := context.WithValue(context.Background(), "__mockInspectionTables", configurations) ctx = context.WithValue(ctx, "__mockMetricsTableData", mockData) ctx = failpoint.WithHook(ctx, func(_ context.Context, currName string) bool { - return fpName2 == currName || currName == fpName + return currName == fpName1 || currName == fpName0 }) - return ctx + return ctx, func() { + require.NoError(t, failpoint.Disable(fpName0)) + require.NoError(t, failpoint.Disable(fpName1)) + } } -func (s *inspectionResultSuite) TestThresholdCheckInspection(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestThresholdCheckInspection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") datetime := func(str string) types.Time { - return s.parseTime(c, tk.Se, str) + return parseTime(t, tk.Session(), str) } // construct some mock abnormal data mockData := map[string][][]types.Datum{ @@ -286,13 +289,13 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection(c *C) { "pd_region_health": {}, } - ctx := s.setupForInspection(c, mockData, nil) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, nil) + defer cleanup() - rs, err := tk.Se.Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance,status_address, value, reference, details from information_schema.inspection_result where rule='threshold-check' order by item") - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err := tk.Session().Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance,status_address, value, reference, details from information_schema.inspection_result where rule='threshold-check' order by item") + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "apply-cpu tikv tikv-0 tikv-0s 10.00 < 1.60, config: raftstore.apply-pool-size=2 the 'apply-cpu' max cpu-usage of tikv-0s tikv is too high", "coprocessor-high-cpu tikv tikv-0 tikv-0s 20.00 < 3.60, config: readpool.coprocessor.high-concurrency=4 the 'coprocessor-high-cpu' max cpu-usage of tikv-0s tikv is too high", @@ -326,19 +329,22 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection(c *C) { } ctx = context.WithValue(ctx, "__mockMetricsTableData", mockData) - rs, err = tk.Se.Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance,status_address, value, reference from information_schema.inspection_result where rule='threshold-check' order by item") - c.Assert(err, IsNil) - result = tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err = tk.Session().Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance,status_address, value, reference from information_schema.inspection_result where rule='threshold-check' order by item") + require.NoError(t, err) + result = tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows("grpc-cpu tikv tikv-0 tikv-0s 7.42 < 7.20, config: server.grpc-concurrency=8")) } -func (s *inspectionResultSuite) TestThresholdCheckInspection2(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestThresholdCheckInspection2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") datetime := func(s string) types.Time { - t, err := types.ParseTime(tk.Se.GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } // construct some mock abnormal data @@ -390,13 +396,13 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection2(c *C) { "pd_region_health": {}, } - ctx := s.setupForInspection(c, mockData, nil) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, nil) + defer cleanup() - rs, err := tk.Se.Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance, status_address, value, reference, details from information_schema.inspection_result where rule='threshold-check' order by item") - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err := tk.Session().Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, type, instance, status_address, value, reference, details from information_schema.inspection_result where rule='threshold-check' order by item") + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "data-block-cache-hit tikv tikv-0 tikv-0s 0.790 > 0.800 min data-block-cache-hit rate of tikv-0s tikv is too low", "filter-block-cache-hit tikv tikv-0 tikv-0s 0.930 > 0.950 min filter-block-cache-hit rate of tikv-0s tikv is too low", @@ -415,12 +421,15 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection2(c *C) { )) } -func (s *inspectionResultSuite) TestThresholdCheckInspection3(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestThresholdCheckInspection3(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") datetime := func(s string) types.Time { - t, err := types.ParseTime(tk.Se.GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } // construct some mock abnormal data @@ -450,16 +459,16 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection3(c *C) { }, } - ctx := s.setupForInspection(c, mockData, nil) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, nil) + defer cleanup() - rs, err := tk.Se.Execute(ctx, `select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ + rs, err := tk.Session().Execute(ctx, `select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ item, type, instance,status_address, value, reference, details from information_schema.inspection_result where rule='threshold-check' and item in ('leader-score-balance','region-score-balance','region-count','region-health','store-available-balance','leader-drop') order by item`) - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "leader-drop tikv tikv-2 tikv-2s 10000 <= 50 tikv-2 tikv has too many leader-drop around time 2020-02-14 05:21:00.000000, leader count from 10000 drop to 0", "leader-drop tikv tikv-0 tikv-0s 5000 <= 50 tikv-0 tikv has too many leader-drop around time 2020-02-14 05:21:00.000000, leader count from 10000 drop to 5000", @@ -470,10 +479,43 @@ func (s *inspectionResultSuite) TestThresholdCheckInspection3(c *C) { "store-available-balance tikv tikv-1 tikv-1s 30.00% < 20.00% tikv-0 max store_available is 100.00, much more than tikv-1 min store_available 70.00")) } -func (s *inspectionResultSuite) TestCriticalErrorInspection(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func createClusterGRPCServer(t testing.TB) map[string]*testServer { + // tp => testServer + testServers := map[string]*testServer{} + + // create gRPC servers + for _, typ := range []string{"tidb", "tikv", "pd"} { + tmpDir := t.TempDir() + + server := grpc.NewServer() + logFile := filepath.Join(tmpDir, fmt.Sprintf("%s.log", typ)) + diagnosticspb.RegisterDiagnosticsServer(server, sysutil.NewDiagnosticsServer(logFile)) - testServers := s.setupClusterGRPCServer(c) + // Find a available port + listener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err, "cannot find available port") + + testServers[typ] = &testServer{ + typ: typ, + server: server, + address: fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), + tmpDir: tmpDir, + logFile: logFile, + } + go func() { + require.NoError(t, server.Serve(listener)) + }() + } + return testServers +} + +func TestCriticalErrorInspection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + testServers := createClusterGRPCServer(t) defer func() { for _, s := range testServers { s.server.Stop() @@ -486,11 +528,11 @@ func (s *inspectionResultSuite) TestCriticalErrorInspection(c *C) { } fpName2 := "github.com/pingcap/tidb/executor/mockClusterLogServerInfo" fpExpr := strings.Join(servers, ";") - c.Assert(failpoint.Enable(fpName2, fmt.Sprintf(`return("%s")`, fpExpr)), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName2), IsNil) }() + require.NoError(t, failpoint.Enable(fpName2, fmt.Sprintf(`return("%s")`, fpExpr))) + defer func() { require.NoError(t, failpoint.Disable(fpName2)) }() datetime := func(str string) types.Time { - return s.parseTime(c, tk.Se, str) + return parseTime(t, tk.Session(), str) } // construct some mock data @@ -556,13 +598,13 @@ func (s *inspectionResultSuite) TestCriticalErrorInspection(c *C) { }, } - ctx := s.setupForInspection(c, mockData, nil) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, nil) + defer cleanup() - rs, err := tk.Se.Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, instance,status_address, value, details from information_schema.inspection_result where rule='critical-error'") - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err := tk.Session().Execute(ctx, "select /*+ time_range('2020-02-12 10:35:00','2020-02-12 10:37:00') */ item, instance,status_address, value, details from information_schema.inspection_result where rule='critical-error'") + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "server-down tikv-0 tikv-0s tikv tikv-0s disconnect with prometheus around time '2020-02-12 10:36:00.000000'", "server-down tidb-1 tidb-1s tidb tidb-1s disconnect with prometheus around time '2020-02-12 10:37:00.000000'", @@ -590,12 +632,15 @@ func (s *inspectionResultSuite) TestCriticalErrorInspection(c *C) { )) } -func (s *inspectionResultSuite) TestNodeLoadInspection(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestNodeLoadInspection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") datetime := func(s string) types.Time { - t, err := types.ParseTime(tk.Se.GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } // construct some mock abnormal data @@ -644,15 +689,16 @@ func (s *inspectionResultSuite) TestNodeLoadInspection(c *C) { }, } - ctx := s.setupForInspection(c, mockData, nil) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, nil) + defer cleanup() - rs, err := tk.Se.Execute(ctx, `select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ + rs, err := tk.Session().Execute(ctx, `select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ item, type, instance, value, reference, details from information_schema.inspection_result where rule='node-load' order by item, value`) - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) + result.Check(testkit.Rows( "cpu-load1 node node-0 28.1 < 28.0 cpu-load1 should less than (cpu_logical_cores * 0.7)", "cpu-load15 node node-1 14.1 < 14.0 cpu-load15 should less than (cpu_logical_cores * 0.7)", @@ -664,12 +710,15 @@ func (s *inspectionResultSuite) TestNodeLoadInspection(c *C) { )) } -func (s *inspectionResultSuite) TestConfigCheckOfStorageBlockCacheSize(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestConfigCheckOfStorageBlockCacheSize(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") datetime := func(s string) types.Time { - t, err := types.ParseTime(tk.Se.GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } configurations := map[string]variable.TableSnapshot{} @@ -691,13 +740,13 @@ func (s *inspectionResultSuite) TestConfigCheckOfStorageBlockCacheSize(c *C) { }, } - ctx := s.setupForInspection(c, mockData, configurations) - defer s.tearDownForInspection(c) + ctx, cleanup := createInspectionContext(t, mockData, configurations) + defer cleanup() - rs, err := tk.Se.Execute(ctx, "select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ * from information_schema.inspection_result where rule='config' and item='storage.block-cache.capacity' order by value") - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err := tk.Session().Execute(ctx, "select /*+ time_range('2020-02-14 04:20:00','2020-02-14 05:23:00') */ * from information_schema.inspection_result where rule='config' and item='storage.block-cache.capacity' order by value") + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equalf(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "config storage.block-cache.capacity tikv 192.168.3.34 1099511627776 < 24159191040 warning There are 1 TiKV server in 192.168.3.34 node, the total 'storage.block-cache.capacity' of TiKV is more than (0.45 * total node memory)", "config storage.block-cache.capacity tikv 192.168.3.33 32212254720 < 24159191040 warning There are 2 TiKV server in 192.168.3.33 node, the total 'storage.block-cache.capacity' of TiKV is more than (0.45 * total node memory)", diff --git a/executor/inspection_summary.go b/executor/inspection_summary.go index ffd235451cebb..ebd3f69abc4f8 100644 --- a/executor/inspection_summary.go +++ b/executor/inspection_summary.go @@ -460,11 +460,7 @@ func (e *inspectionSummaryRetriever) retrieve(ctx context.Context, sctx sessionc util.MetricSchemaName.L, name, cond) } exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, sql) - if err != nil { - return nil, errors.Errorf("execute '%s' failed: %v", sql, err) - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql) if err != nil { return nil, errors.Errorf("execute '%s' failed: %v", sql, err) } diff --git a/executor/inspection_summary_test.go b/executor/inspection_summary_test.go index 754e692dc54b4..4b1f1c0819f1c 100644 --- a/executor/inspection_summary_test.go +++ b/executor/inspection_summary_test.go @@ -16,62 +16,45 @@ package executor_test import ( "context" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/set" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&inspectionSummarySuite{}) - -type inspectionSummarySuite struct { - store kv.Storage - dom *domain.Domain -} - -func (s *inspectionSummarySuite) SetUpSuite(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - s.store = store - s.dom = dom -} - -func (s *inspectionSummarySuite) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *inspectionSummarySuite) TestValidInspectionSummaryRules(c *C) { +func TestValidInspectionSummaryRules(t *testing.T) { for rule, tbls := range executor.InspectionSummaryRules { tables := set.StringSet{} - for _, t := range tbls { - c.Assert(tables.Exist(t), IsFalse, Commentf("duplicate table name: %v in rule: %v", t, rule)) - tables.Insert(t) + for _, tbl := range tbls { + require.False(t, tables.Exist(tbl), "duplicate table name: %v in rule: %v", tbl, rule) + tables.Insert(tbl) - _, found := infoschema.MetricTableMap[t] - c.Assert(found, IsTrue, Commentf("metric table %v not define", t)) + _, found := infoschema.MetricTableMap[tbl] + require.True(t, found, "metric table %v not define", tbl) } } } -func (s *inspectionSummarySuite) TestInspectionSummary(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestInspectionSummary(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) fpName := "github.com/pingcap/tidb/executor/mockMetricsTableData" - c.Assert(failpoint.Enable(fpName, "return"), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, "return")) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() datetime := func(s string) types.Time { - t, err := types.ParseTime(tk.Se.GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) - c.Assert(err, IsNil) - return t + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + require.NoError(t, err) + return time } // construct some mock data @@ -97,10 +80,10 @@ func (s *inspectionSummarySuite) TestInspectionSummary(c *C) { return fpName == fpname }) - rs, err := tk.Se.Execute(ctx, "select * from information_schema.inspection_summary where rule='query-summary' and metrics_name in ('tidb_qps', 'tidb_query_duration')") - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err := tk.Session().Execute(ctx, "select * from information_schema.inspection_summary where rule='query-summary' and metrics_name in ('tidb_qps', 'tidb_query_duration')") + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "query-summary tikv-0 tidb_query_duration Select 0.99 0 0 0 The quantile of TiDB query durations(second)", "query-summary tikv-1 tidb_query_duration Update 0.99 2 1 3 The quantile of TiDB query durations(second)", @@ -111,10 +94,10 @@ func (s *inspectionSummarySuite) TestInspectionSummary(c *C) { )) // Test for select * from information_schema.inspection_summary without specify rules. - rs, err = tk.Se.Execute(ctx, "select * from information_schema.inspection_summary where metrics_name = 'tidb_qps'") - c.Assert(err, IsNil) - result = tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("execute inspect SQL failed")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0), Commentf("unexpected warnings: %+v", tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + rs, err = tk.Session().Execute(ctx, "select * from information_schema.inspection_summary where metrics_name = 'tidb_qps'") + require.NoError(t, err) + result = tk.ResultSetToResultWithCtx(ctx, rs[0], "execute inspect SQL failed") + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount(), "unexpected warnings: %+v", tk.Session().GetSessionVars().StmtCtx.GetWarnings()) result.Check(testkit.Rows( "query-summary tidb-0 tidb_qps Query, Error 1 1 1 TiDB query processing numbers per second", "query-summary tidb-0 tidb_qps Query, OK 0 0 0 TiDB query processing numbers per second", diff --git a/executor/join_pkg_test.go b/executor/join_pkg_test.go index 75af33d7acb5d..b7500ecf144b8 100644 --- a/executor/join_pkg_test.go +++ b/executor/join_pkg_test.go @@ -16,18 +16,21 @@ package executor import ( "context" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -func (s *pkgTestSerialSuite) TestJoinExec(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testRowContainerSpill", "return(true)"), IsNil) - defer func() { c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testRowContainerSpill"), IsNil) }() +func TestJoinExec(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testRowContainerSpill", "return(true)")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testRowContainerSpill")) + }() colTypes := []*types.FieldType{ types.NewFieldType(mysql.TypeLonglong), types.NewFieldType(mysql.TypeDouble), @@ -63,32 +66,32 @@ func (s *pkgTestSerialSuite) TestJoinExec(c *C) { ctx := context.Background() chk := newFirstChunk(exec) err := exec.Open(ctx) - c.Assert(err, IsNil) + require.NoError(t, err) for { err = exec.Next(ctx, chk) - c.Assert(err, IsNil) + require.NoError(t, err) if chk.NumRows() == 0 { break } result.Append(chk, 0, chk.NumRows()) } - c.Assert(exec.rowContainer.alreadySpilledSafeForTest(), Equals, casTest.disk) + require.Equal(t, casTest.disk, exec.rowContainer.alreadySpilledSafeForTest()) err = exec.Close() - c.Assert(err, IsNil) + require.NoError(t, err) } - c.Assert(result.NumCols(), Equals, 4) - c.Assert(result.NumRows(), Equals, casTest.rows) + require.Equal(t, 4, result.NumCols()) + require.Equal(t, casTest.rows, result.NumRows()) visit := make(map[int64]bool, casTest.rows) for i := 0; i < casTest.rows; i++ { val := result.Column(0).Int64s()[i] - c.Assert(result.Column(1).Float64s()[i], Equals, float64(val)) - c.Assert(result.Column(2).Int64s()[i], Equals, val) - c.Assert(result.Column(3).Float64s()[i], Equals, float64(val)) + require.Equal(t, float64(val), result.Column(1).Float64s()[i]) + require.Equal(t, val, result.Column(2).Int64s()[i]) + require.Equal(t, float64(val), result.Column(3).Float64s()[i]) visit[val] = true } for i := 0; i < casTest.rows; i++ { - c.Assert(visit[int64(i)], IsTrue) + require.True(t, visit[int64(i)]) } } @@ -107,7 +110,7 @@ func (s *pkgTestSerialSuite) TestJoinExec(c *C) { } } -func (s *pkgTestSuite) TestHashJoinRuntimeStats(c *C) { +func TestHashJoinRuntimeStats(t *testing.T) { stats := &hashJoinRuntimeStats{ fetchAndBuildHashTable: 2 * time.Second, hashStat: hashStatistic{ @@ -119,13 +122,13 @@ func (s *pkgTestSuite) TestHashJoinRuntimeStats(c *C) { concurrent: 4, maxFetchAndProbe: int64(2 * time.Second), } - c.Assert(stats.String(), Equals, "build_hash_table:{total:2s, fetch:1.9s, build:100ms}, probe:{concurrency:4, total:5s, max:2s, probe:4s, fetch:1s, probe_collision:1}") - c.Assert(stats.String(), Equals, stats.Clone().String()) + require.Equal(t, "build_hash_table:{total:2s, fetch:1.9s, build:100ms}, probe:{concurrency:4, total:5s, max:2s, probe:4s, fetch:1s, probe_collision:1}", stats.String()) + require.Equal(t, stats.Clone().String(), stats.String()) stats.Merge(stats.Clone()) - c.Assert(stats.String(), Equals, "build_hash_table:{total:4s, fetch:3.8s, build:200ms}, probe:{concurrency:4, total:10s, max:2s, probe:8s, fetch:2s, probe_collision:2}") + require.Equal(t, "build_hash_table:{total:4s, fetch:3.8s, build:200ms}, probe:{concurrency:4, total:10s, max:2s, probe:8s, fetch:2s, probe_collision:2}", stats.String()) } -func (s *pkgTestSuite) TestIndexJoinRuntimeStats(c *C) { +func TestIndexJoinRuntimeStats(t *testing.T) { stats := indexLookUpJoinRuntimeStats{ concurrency: 5, probe: int64(time.Second), @@ -138,8 +141,8 @@ func (s *pkgTestSuite) TestIndexJoinRuntimeStats(c *C) { join: int64(150 * time.Millisecond), }, } - c.Assert(stats.String(), Equals, "inner:{total:5s, concurrency:5, task:16, construct:100ms, fetch:300ms, build:250ms, join:150ms}, probe:1s") - c.Assert(stats.String(), Equals, stats.Clone().String()) + require.Equal(t, "inner:{total:5s, concurrency:5, task:16, construct:100ms, fetch:300ms, build:250ms, join:150ms}, probe:1s", stats.String()) + require.Equal(t, stats.Clone().String(), stats.String()) stats.Merge(stats.Clone()) - c.Assert(stats.String(), Equals, "inner:{total:10s, concurrency:5, task:32, construct:200ms, fetch:600ms, build:500ms, join:300ms}, probe:2s") + require.Equal(t, "inner:{total:10s, concurrency:5, task:32, construct:200ms, fetch:600ms, build:500ms, join:300ms}, probe:2s", stats.String()) } diff --git a/executor/join_test.go b/executor/join_test.go index a11e71332d07f..f6fe0b23ecf7b 100644 --- a/executor/join_test.go +++ b/executor/join_test.go @@ -19,44 +19,32 @@ import ( "fmt" "math/rand" "strings" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/executor" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -type testSuiteJoin1 struct { - *baseTestSuite -} - -type testSuiteJoin2 struct { - *baseTestSuite -} - -type testSuiteJoin3 struct { - *baseTestSuite -} - -type testSuiteJoinSerial struct { - *baseTestSuite -} - -func (s *testSuiteJoin1) TestJoinPanic(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinPanic2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set sql_mode = 'ONLY_FULL_GROUP_BY'") tk.MustExec("drop table if exists events") tk.MustExec("create table events (clock int, source int)") tk.MustQuery("SELECT * FROM events e JOIN (SELECT MAX(clock) AS clock FROM events e2 GROUP BY e2.source) e3 ON e3.clock=e.clock") err := tk.ExecToErr("SELECT * FROM events e JOIN (SELECT clock FROM events e2 GROUP BY e2.source) e3 ON e3.clock=e.clock") - c.Check(err, NotNil) + require.Error(t, err) // Test for PR 18983, use to detect race. tk.MustExec("use test") @@ -68,20 +56,24 @@ func (s *testSuiteJoin1) TestJoinPanic(c *C) { tk.MustQuery("select tpj1.b,tpj2.b from tpj1 left join tpj2 on tpj1.id=tpj2.id where tpj1.id=1;").Check(testkit.Rows("1 1")) } -func (s *testSuite) TestJoinInDisk(c *C) { - defer config.RestoreFunc()() +func TestJoinInDisk(t *testing.T) { + origin := config.RestoreFunc() + defer origin() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true + conf.OOMAction = config.OOMActionLog }) - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sm := &mockSessionManager1{ PS: make([]*util.ProcessInfo, 0), } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) // TODO(fengliyuan): how to ensure that it is using disk really? tk.MustExec("set @@tidb_mem_quota_query=1;") @@ -95,14 +87,16 @@ func (s *testSuite) TestJoinInDisk(c *C) { result.Check(testkit.Rows("2 2 2 3")) } -func (s *testSuiteJoin2) TestJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoin2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_index_lookup_join_concurrency = 200") - c.Assert(tk.Se.GetSessionVars().IndexLookupJoinConcurrency(), Equals, 200) + require.Equal(t, 200, tk.Session().GetSessionVars().IndexLookupJoinConcurrency()) tk.MustExec("set @@tidb_index_lookup_join_concurrency = 4") - c.Assert(tk.Se.GetSessionVars().IndexLookupJoinConcurrency(), Equals, 4) + require.Equal(t, 4, tk.Session().GetSessionVars().IndexLookupJoinConcurrency()) tk.MustExec("set @@tidb_index_lookup_size = 2") tk.MustExec("use test") @@ -218,11 +212,11 @@ func (s *testSuiteJoin2) TestJoin(c *C) { // Test that two conflict hints will return warning. tk.MustExec("select /*+ TIDB_INLJ(t) TIDB_SMJ(t) */ * from t join t1 on t.a=t1.a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) tk.MustExec("select /*+ TIDB_INLJ(t) TIDB_HJ(t) */ * from t join t1 on t.a=t1.a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) tk.MustExec("select /*+ TIDB_SMJ(t) TIDB_HJ(t) */ * from t join t1 on t.a=t1.a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") @@ -352,8 +346,10 @@ func (s *testSuiteJoin2) TestJoin(c *C) { tk.MustQuery("select min(t2.b) from t1 right join t2 on t2.a=t1.a right join t3 on t2.a=t3.a left join t4 on t3.a=t4.a").Check(testkit.Rows("1")) } -func (s *testSuiteJoin2) TestJoinCast(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinCast(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) var result *testkit.Result tk.MustExec("use test") @@ -423,7 +419,7 @@ func (s *testSuiteJoin2) TestJoinCast(c *C) { tk.MustExec("insert into t value(18446744073709551615);") tk.MustExec("insert into t1 value(-1);") result = tk.MustQuery("select * from t, t1 where t.c1 = t1.c1;") - c.Check(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) /* Issues 11896 */ tk.MustExec("drop table if exists t;") @@ -433,7 +429,7 @@ func (s *testSuiteJoin2) TestJoinCast(c *C) { tk.MustExec("insert into t value(1);") tk.MustExec("insert into t1 value(1);") result = tk.MustQuery("select * from t, t1 where t.c1 = t1.c1;") - c.Check(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") @@ -443,7 +439,7 @@ func (s *testSuiteJoin2) TestJoinCast(c *C) { tk.MustExec("insert into t1 value(18446744073709551615);") result = tk.MustQuery("select * from t, t1 where t.c1 = t1.c1;") // TODO: MySQL will return one row, because c1 in t1 is 0xffffffff, which equals to -1. - c.Check(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") @@ -538,8 +534,10 @@ func (s *testSuiteJoin2) TestJoinCast(c *C) { tk.MustExec("set @@tidb_init_chunk_size=32") } -func (s *testSuiteJoin1) TestUsing(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUsing(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2, t3, t4") @@ -656,8 +654,10 @@ func (s *testSuiteJoin1) TestUsing(c *C) { tk.MustQuery("select t1.t0, t2.t0 from t1 join t2 using(t0) having t1.t0 > 0").Check(testkit.Rows("1 1")) } -func (s *testSuiteWithData) TestUsingAndNaturalJoinSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUsingAndNaturalJoinSchema(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2, t3, t4") tk.MustExec("create table t1 (c int, b int);") @@ -679,18 +679,20 @@ func (s *testSuiteWithData) TestUsingAndNaturalJoinSchema(c *C) { SQL string Res []string } - s.testData.GetTestCases(c, &input, &output) + executorSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) }) tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) } } -func (s *testSuiteWithData) TestNaturalJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNaturalJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") @@ -705,20 +707,22 @@ func (s *testSuiteWithData) TestNaturalJoin(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + executorSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) } } -func (s *testSuiteJoin3) TestMultiJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t35(a35 int primary key, b35 int, x35 int)") tk.MustExec("create table t40(a40 int primary key, b40 int, x40 int)") @@ -809,8 +813,10 @@ AND b44=a42`) result.Check(testkit.Rows("7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7")) } -func (s *testSuiteJoin3) TestSubquerySameTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSubquerySameTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int)") @@ -821,8 +827,10 @@ func (s *testSuiteJoin3) TestSubquerySameTable(c *C) { result.Check(testkit.Rows("1")) } -func (s *testSuiteJoin3) TestSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_hash_join_concurrency=1") tk.MustExec("set @@tidb_hashagg_partial_concurrency=1") tk.MustExec("set @@tidb_hashagg_final_concurrency=1") @@ -911,10 +919,10 @@ func (s *testSuiteJoin3) TestSubquery(c *C) { result = tk.MustQuery("select (select t.id from t where s.id < 2 and t.id = s.id) from t s") result.Sort().Check(testkit.Rows("1", "", "")) rs, err := tk.Exec("select (select t.id from t where t.id = t.v and t.v != s.id) from t s") - c.Check(err, IsNil) - _, err = session.GetRows4Test(context.Background(), tk.Se, rs) - c.Check(err, NotNil) - c.Check(rs.Close(), IsNil) + require.NoError(t, err) + _, err = session.GetRows4Test(context.Background(), tk.Session(), rs) + require.Error(t, err) + require.NoError(t, rs.Close()) tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists s") @@ -1060,8 +1068,10 @@ func (s *testSuiteJoin3) TestSubquery(c *C) { tk.MustExec("set @@tidb_hash_join_concurrency=5") } -func (s *testSuiteJoin1) TestInSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int)") @@ -1127,8 +1137,10 @@ func (s *testSuiteJoin1) TestInSubquery(c *C) { result.Check(testkit.Rows("2", "2", "1")) } -func (s *testSuiteJoin1) TestJoinLeak(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinLeak(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_hash_join_concurrency=1") tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1139,18 +1151,20 @@ func (s *testSuiteJoin1) TestJoinLeak(c *C) { } tk.MustExec("commit") result, err := tk.Exec("select * from t t1 left join (select 1) t2 on 1") - c.Assert(err, IsNil) + require.NoError(t, err) req := result.NewChunk(nil) err = result.Next(context.Background(), req) - c.Assert(err, IsNil) + require.NoError(t, err) time.Sleep(time.Millisecond) - c.Assert(result.Close(), IsNil) + require.NoError(t, result.Close()) tk.MustExec("set @@tidb_hash_join_concurrency=5") } -func (s *testSuiteJoin1) TestHashJoinExecEncodeDecodeRow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHashJoinExecEncodeDecodeRow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") @@ -1162,8 +1176,10 @@ func (s *testSuiteJoin1) TestHashJoinExecEncodeDecodeRow(c *C) { result.Check(testkit.Rows("2003-06-09 10:51:26")) } -func (s *testSuiteJoin1) TestSubqueryInJoinOn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSubqueryInJoinOn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") @@ -1173,11 +1189,13 @@ func (s *testSuiteJoin1) TestSubqueryInJoinOn(c *C) { tk.MustExec("insert into t2 values (1)") err := tk.ExecToErr("SELECT * FROM t1 JOIN t2 on (t2.id < all (SELECT 1))") - c.Check(err, NotNil) + require.Error(t, err) } -func (s *testSuiteJoin1) TestIssue5255(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue5255(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b date, c float, primary key(a, b))") @@ -1189,8 +1207,10 @@ func (s *testSuiteJoin1) TestIssue5255(c *C) { tk.MustQuery("select /*+ INL_MERGE_JOIN(t1) */ * from t1 join t2 on t1.a=t2.a").Check(testkit.Rows("1 2017-11-29 2.2 1")) } -func (s *testSuiteJoin1) TestIssue5278(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue5278(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, tt") tk.MustExec("create table t(a int, b int)") @@ -1199,24 +1219,28 @@ func (s *testSuiteJoin1) TestIssue5278(c *C) { tk.MustQuery("select * from t left join tt on t.a=tt.a left join t ttt on t.a=ttt.a").Check(testkit.Rows("1 1 1 1")) } -func (s *testSuiteJoin1) TestIssue15850JoinNullValue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15850JoinNullValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustQuery("SELECT * FROM (select null) v NATURAL LEFT JOIN (select null) v1;").Check(testkit.Rows("")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) tk.MustExec("drop table if exists t0;") tk.MustExec("drop view if exists v0;") tk.MustExec("CREATE TABLE t0(c0 TEXT);") tk.MustExec("CREATE VIEW v0(c0) AS SELECT NULL;") tk.MustQuery("SELECT /*+ HASH_JOIN(v0) */ * FROM v0 NATURAL LEFT JOIN t0;").Check(testkit.Rows("")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) tk.MustQuery("SELECT /*+ MERGE_JOIN(v0) */ * FROM v0 NATURAL LEFT JOIN t0;").Check(testkit.Rows("")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) } -func (s *testSuiteJoin1) TestIndexLookupJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexLookupJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_init_chunk_size=2") tk.MustExec("DROP TABLE IF EXISTS t") @@ -1403,13 +1427,15 @@ func (s *testSuiteJoin1) TestIndexLookupJoin(c *C) { tk.MustQuery("select /*+ inl_merge_join(t1)*/ * from t1 join t2 on t2.b=t1.id and t2.a=t1.id;").Check(testkit.Rows("1 1 1")) } -func (s *testSuiteJoinSerial) TestIndexNestedLoopHashJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexNestedLoopHashJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_init_chunk_size=2") tk.MustExec("set @@tidb_index_join_batch_size=10") tk.MustExec("DROP TABLE IF EXISTS t, s") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t(pk int primary key, a int)") for i := 0; i < 100; i++ { tk.MustExec(fmt.Sprintf("insert into t values(%d, %d)", i, i)) @@ -1434,13 +1460,13 @@ func (s *testSuiteJoinSerial) TestIndexNestedLoopHashJoin(c *C) { )) rs := tk.MustQuery("select /*+ INL_HASH_JOIN(s) */ * from t left join s on t.a=s.a order by t.pk") for i, row := range rs.Rows() { - c.Assert(row[0].(string), Equals, fmt.Sprintf("%d", i)) + require.Equal(t, fmt.Sprintf("%d", i), row[0].(string)) } // index hash join with semi join - c.Assert(failpoint.Enable("github.com/pingcap/tidb/planner/core/MockOnlyEnableIndexHashJoin", "return(true)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/core/MockOnlyEnableIndexHashJoin", "return(true)")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/planner/core/MockOnlyEnableIndexHashJoin"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/core/MockOnlyEnableIndexHashJoin")) }() tk.MustExec("drop table t") tk.MustExec("CREATE TABLE `t` ( `l_orderkey` int(11) NOT NULL,`l_linenumber` int(11) NOT NULL,`l_partkey` int(11) DEFAULT NULL,`l_suppkey` int(11) DEFAULT NULL,PRIMARY KEY (`l_orderkey`,`l_linenumber`))") @@ -1457,8 +1483,8 @@ func (s *testSuiteJoinSerial) TestIndexNestedLoopHashJoin(c *C) { tk.MustExec("analyze table t") // test semi join - tk.Se.GetSessionVars().InitChunkSize = 2 - tk.Se.GetSessionVars().MaxChunkSize = 2 + tk.Session().GetSessionVars().InitChunkSize = 2 + tk.Session().GetSessionVars().MaxChunkSize = 2 tk.MustExec("set @@tidb_index_join_batch_size=2") tk.MustQuery("desc format = 'brief' select * from t l1 where exists ( select * from t l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey <> l1.l_suppkey ) order by `l_orderkey`,`l_linenumber`;").Check(testkit.Rows( "Sort 7.20 root test.t.l_orderkey, test.t.l_linenumber", @@ -1541,8 +1567,10 @@ func (s *testSuiteJoinSerial) TestIndexNestedLoopHashJoin(c *C) { tk.MustExec("drop table orders") } -func (s *testSuiteJoin3) TestIssue15686(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15686(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, k;") tk.MustExec("create table k (a int, pk int primary key, index(a));") @@ -1554,8 +1582,10 @@ func (s *testSuiteJoin3) TestIssue15686(c *C) { tk.MustQuery("select /*+ inl_merge_join(t) */ count(*) from k left join t on k.a = t.a and k.pk > t.pk;").Check(testkit.Rows("33")) } -func (s *testSuiteJoin3) TestIssue13449(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue13449(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, s;") tk.MustExec("create table t(a int, index(a));") @@ -1578,8 +1608,10 @@ func (s *testSuiteJoin3) TestIssue13449(c *C) { tk.MustQuery("select /*+ INL_HASH_JOIN(s) */ * from t join s on t.a=s.a order by t.a;").Check(testkit.Rows("1 1", "128 128")) } -func (s *testSuiteJoin3) TestMergejoinOrder(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMergejoinOrder(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2;") tk.MustExec("create table t1(a bigint primary key, b bigint);") @@ -1623,8 +1655,10 @@ func (s *testSuiteJoin3) TestMergejoinOrder(c *C) { )) } -func (s *testSuiteJoin1) TestEmbeddedOuterJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEmbeddedOuterJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int)") @@ -1634,8 +1668,10 @@ func (s *testSuiteJoin1) TestEmbeddedOuterJoin(c *C) { Check(testkit.Rows("1 1 ")) } -func (s *testSuiteJoin1) TestHashJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHashJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int);") @@ -1654,16 +1690,18 @@ func (s *testSuiteJoin1) TestHashJoin(c *C) { // 5 └─Selection_11 9990.00 5 cop[tikv] time:243.395µs, loops:6 not(isnull(test.t1.a)) N/A N/A // 6 └─TableFullScan_10 10000.00 5 cop[tikv] table:t1 time:206.273µs, loops:6 keep order:false, stats:pseudo N/A N/A row := result.Rows() - c.Assert(len(row), Equals, 7) + require.Equal(t, 7, len(row)) innerActRows := row[1][2].(string) - c.Assert(innerActRows, Equals, "0") + require.Equal(t, "0", innerActRows) outerActRows := row[4][2].(string) // FIXME: revert this result to 1 after TableReaderExecutor can handle initChunkSize. - c.Assert(outerActRows, Equals, "5") + require.Equal(t, "5", outerActRows) } -func (s *testSuiteJoin1) TestJoinDifferentDecimals(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinDifferentDecimals(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("Use test") tk.MustExec("Drop table if exists t1") tk.MustExec("Create table t1 (v int)") @@ -1677,12 +1715,14 @@ func (s *testSuiteJoin1) TestJoinDifferentDecimals(c *C) { tk.MustExec("Insert into t2 value (000003.000000)") rst := tk.MustQuery("Select * from t1, t2 where t1.v = t2.v order by t1.v") row := rst.Rows() - c.Assert(len(row), Equals, 3) + require.Equal(t, 3, len(row)) rst.Check(testkit.Rows("1 1.000", "2 2.000", "3 3.000")) } -func (s *testSuiteJoin2) TestNullEmptyAwareSemiJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNullEmptyAwareSemiJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, index idx_a(a), index idb_b(b), index idx_c(c))") @@ -2075,8 +2115,10 @@ func (s *testSuiteJoin2) TestNullEmptyAwareSemiJoin(c *C) { )) } -func (s *testSuiteJoin1) TestScalarFuncNullSemiJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestScalarFuncNullSemiJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") @@ -2091,8 +2133,10 @@ func (s *testSuiteJoin1) TestScalarFuncNullSemiJoin(c *C) { tk.MustQuery("select a in (select a+b from s) from t").Check(testkit.Rows("", "")) } -func (s *testSuiteJoin1) TestInjectProjOnTopN(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInjectProjOnTopN(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") @@ -2104,8 +2148,10 @@ func (s *testSuiteJoin1) TestInjectProjOnTopN(c *C) { )) } -func (s *testSuiteJoin1) TestIssue11544(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue11544(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table 11544t(a int)") tk.MustExec("create table 11544tt(a int, b varchar(10), index idx(a, b(3)))") @@ -2122,8 +2168,10 @@ func (s *testSuiteJoin1) TestIssue11544(c *C) { tk.MustQuery("select /*+ INL_MERGE_JOIN(tt) */ * from 11544t t, 11544tt tt where t.a=tt.a and tt.b in ('aaaaaaa', 'aaaabbb', 'aaaacccc')").Sort().Check(testkit.Rows("1 1 aaaaaaa", "1 1 aaaabbb", "1 1 aaaacccc")) } -func (s *testSuiteJoin1) TestIssue11390(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue11390(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table 11390t (k1 int unsigned, k2 int unsigned, key(k1, k2))") tk.MustExec("insert into 11390t values(1, 1)") @@ -2132,10 +2180,12 @@ func (s *testSuiteJoin1) TestIssue11390(c *C) { tk.MustQuery("select /*+ INL_MERGE_JOIN(t1, t2) */ * from 11390t t1, 11390t t2 where t1.k2 > 0 and t1.k2 = t2.k2 and t2.k1=1;").Check(testkit.Rows("1 1 1 1")) } -func (s *testSuiteJoinSerial) TestOuterTableBuildHashTableIsuse13933(c *C) { +func TestOuterTableBuildHashTableIsuse13933(t *testing.T) { plannercore.ForceUseOuterBuild4Test = true defer func() { plannercore.ForceUseOuterBuild4Test = false }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, s") tk.MustExec("create table t (a int,b int)") @@ -2167,8 +2217,10 @@ func (s *testSuiteJoinSerial) TestOuterTableBuildHashTableIsuse13933(c *C) { " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo")) } -func (s *testSuiteJoin1) TestIssue13177(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue13177(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a varchar(20), b int, c int)") @@ -2207,22 +2259,26 @@ func (s *testSuiteJoin1) TestIssue13177(c *C) { )) } -func (s *testSuiteJoin1) TestIssue14514(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue14514(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (pk varchar(14) primary key, a varchar(12));") tk.MustQuery("select * from (select t1.pk or '/' as c from t as t1 left join t as t2 on t1.a = t2.pk) as t where t.c = 1;").Check(testkit.Rows()) } -func (s *testSuiteJoinSerial) TestOuterMatchStatusIssue14742(c *C) { +func TestOuterMatchStatusIssue14742(t *testing.T) { plannercore.ForceUseOuterBuild4Test = true defer func() { plannercore.ForceUseOuterBuild4Test = false }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists testjoin;") tk.MustExec("create table testjoin(a int);") - tk.Se.GetSessionVars().MaxChunkSize = 2 + tk.Session().GetSessionVars().MaxChunkSize = 2 tk.MustExec("insert into testjoin values (NULL);") tk.MustExec("insert into testjoin values (1);") @@ -2238,13 +2294,15 @@ func (s *testSuiteJoinSerial) TestOuterMatchStatusIssue14742(c *C) { )) } -func (s *testSuiteJoinSerial) TestInlineProjection4HashJoinIssue15316(c *C) { +func TestInlineProjection4HashJoinIssue15316(t *testing.T) { // Two necessary factors to reproduce this issue: // (1) taking HashLeftJoin, i.e., letting the probing tuple lay at the left side of joined tuples // (2) the projection only contains a part of columns from the build side, i.e., pruning the same probe side plannercore.ForcedHashLeftJoin4Test = true defer func() { plannercore.ForcedHashLeftJoin4Test = false }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists S, T") tk.MustExec("create table S (a int not null, b int, c int);") @@ -2272,16 +2330,15 @@ func (s *testSuiteJoinSerial) TestInlineProjection4HashJoinIssue15316(c *C) { " └─TableFullScan 10000.00 cop[tikv] table:S keep order:false, stats:pseudo")) } -func (s *testSuiteJoinSerial) TestIssue18070(c *C) { +func TestIssue18070(t *testing.T) { + restoreFunc := config.RestoreFunc() + defer restoreFunc() config.UpdateGlobal(func(conf *config.Config) { conf.OOMAction = config.OOMActionCancel }) - defer func() { - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = config.OOMActionLog - }) - }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, index(a))") @@ -2290,19 +2347,21 @@ func (s *testSuiteJoinSerial) TestIssue18070(c *C) { tk.MustExec("insert into t2 values(1),(1),(2),(2)") tk.MustExec("set @@tidb_mem_quota_query=1000") err := tk.QueryToErr("select /*+ inl_hash_join(t1)*/ * from t1 join t2 on t1.a = t2.a;") - c.Assert(strings.Contains(err.Error(), "Out Of Memory Quota!"), IsTrue) + require.True(t, strings.Contains(err.Error(), "Out Of Memory Quota!")) fpName := "github.com/pingcap/tidb/executor/mockIndexMergeJoinOOMPanic" - c.Assert(failpoint.Enable(fpName, `panic("ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]")`), IsNil) + require.NoError(t, failpoint.Enable(fpName, `panic("ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]")`)) defer func() { - c.Assert(failpoint.Disable(fpName), IsNil) + require.NoError(t, failpoint.Disable(fpName)) }() err = tk.QueryToErr("select /*+ inl_merge_join(t1)*/ * from t1 join t2 on t1.a = t2.a;") - c.Assert(strings.Contains(err.Error(), "Out Of Memory Quota!"), IsTrue) + require.True(t, strings.Contains(err.Error(), "Out Of Memory Quota!")) } -func (s *testSuiteJoin1) TestIssue18564(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue18564(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, primary key(a), index idx(b,a));") @@ -2313,8 +2372,10 @@ func (s *testSuiteJoin1) TestIssue18564(c *C) { } // test hash join when enum column got invalid value -func (s *testSuiteJoin1) TestInvalidEnumVal(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInvalidEnumVal(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("set sql_mode = '';") tk.MustExec("drop table if exists t1;") @@ -2327,65 +2388,77 @@ func (s *testSuiteJoin1) TestInvalidEnumVal(c *C) { rows.Check(testkit.Rows("a a", " ", " ", " ", " ")) } -func (s *testSuiteJoinSerial) TestIssue18572_1(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue18572_1(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int, b int, index idx(b));") tk.MustExec("insert into t1 values(1, 1);") tk.MustExec("insert into t1 select * from t1;") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinInnerWorkerErr", "return"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinInnerWorkerErr", "return")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinInnerWorkerErr"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinInnerWorkerErr")) }() rs, err := tk.Exec("select /*+ inl_hash_join(t1) */ * from t1 right join t1 t2 on t1.b=t2.b;") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = session.GetRows4Test(context.Background(), nil, rs) - c.Assert(strings.Contains(err.Error(), "mockIndexHashJoinInnerWorkerErr"), IsTrue) - c.Assert(rs.Close(), IsNil) + require.True(t, strings.Contains(err.Error(), "mockIndexHashJoinInnerWorkerErr")) + require.NoError(t, rs.Close()) } -func (s *testSuiteJoinSerial) TestIssue18572_2(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue18572_2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int, b int, index idx(b));") tk.MustExec("insert into t1 values(1, 1);") tk.MustExec("insert into t1 select * from t1;") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinOuterWorkerErr", "return"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinOuterWorkerErr", "return")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinOuterWorkerErr"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinOuterWorkerErr")) }() rs, err := tk.Exec("select /*+ inl_hash_join(t1) */ * from t1 right join t1 t2 on t1.b=t2.b;") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = session.GetRows4Test(context.Background(), nil, rs) - c.Assert(strings.Contains(err.Error(), "mockIndexHashJoinOuterWorkerErr"), IsTrue) - c.Assert(rs.Close(), IsNil) + require.True(t, strings.Contains(err.Error(), "mockIndexHashJoinOuterWorkerErr")) + require.NoError(t, rs.Close()) } -func (s *testSuiteJoinSerial) TestIssue18572_3(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue18572_3(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int, b int, index idx(b));") tk.MustExec("insert into t1 values(1, 1);") tk.MustExec("insert into t1 select * from t1;") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinBuildErr", "return"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testIndexHashJoinBuildErr", "return")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinBuildErr"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testIndexHashJoinBuildErr")) }() rs, err := tk.Exec("select /*+ inl_hash_join(t1) */ * from t1 right join t1 t2 on t1.b=t2.b;") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = session.GetRows4Test(context.Background(), nil, rs) - c.Assert(strings.Contains(err.Error(), "mockIndexHashJoinBuildErr"), IsTrue) - c.Assert(rs.Close(), IsNil) + require.True(t, strings.Contains(err.Error(), "mockIndexHashJoinBuildErr")) + require.NoError(t, rs.Close()) } -func (s *testSuite9) TestApplyOuterAggEmptyInput(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyOuterAggEmptyInput(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int)") tk.MustExec("create table t2(a int)") @@ -2405,8 +2478,11 @@ func (s *testSuite9) TestApplyOuterAggEmptyInput(c *C) { )) } -func (s *testSuite9) TestIssue19112(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue19112(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 ( c_int int, c_decimal decimal(12, 6), key(c_int), unique key(c_decimal) )") tk.MustExec("create table t2 like t1") @@ -2417,8 +2493,11 @@ func (s *testSuite9) TestIssue19112(c *C) { "3 1.010000 3 1.010000")) } -func (s *testSuiteJoin3) TestIssue11896(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue11896(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") // compare bigint to bit(64) tk.MustExec("drop table if exists t") @@ -2471,8 +2550,11 @@ func (s *testSuiteJoin3) TestIssue11896(c *C) { testkit.Rows("1 \x01")) } -func (s *testSuiteJoin3) TestIssue19498(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue19498(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1 (c_int int, primary key (c_int));") @@ -2501,8 +2583,11 @@ func (s *testSuiteJoin3) TestIssue19498(c *C) { rs.Check(testkit.Rows("happy archimedes 2", "happy fermat 2", "happy hypatia 2", "zen sammet 4")) } -func (s *testSuiteJoin3) TestIssue19500(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue19500(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1 (c_int int, primary key (c_int));") tk.MustExec("insert into t1 values (1),(2),(3),(4),(5);") @@ -2516,8 +2601,11 @@ func (s *testSuiteJoin3) TestIssue19500(c *C) { Check(testkit.Rows("", "", "3", "3", "3")) } -func (s *testSuiteJoinSerial) TestExplainAnalyzeJoin(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestExplainAnalyzeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2;") tk.MustExec("create table t1 (a int, b int, unique index (a));") tk.MustExec("create table t2 (a int, b int, unique index (a))") @@ -2525,55 +2613,59 @@ func (s *testSuiteJoinSerial) TestExplainAnalyzeJoin(c *C) { tk.MustExec("insert into t2 values (1,1),(2,2),(3,3),(4,4),(5,5)") // Test for index lookup join. rows := tk.MustQuery("explain analyze select /*+ INL_JOIN(t1, t2) */ * from t1,t2 where t1.a=t2.a;").Rows() - c.Assert(len(rows), Equals, 8) - c.Assert(rows[0][0], Matches, "IndexJoin_.*") - c.Assert(rows[0][5], Matches, "time:.*, loops:.*, inner:{total:.*, concurrency:.*, task:.*, construct:.*, fetch:.*, build:.*}, probe:.*") + require.Equal(t, 8, len(rows)) + require.Regexp(t, "IndexJoin_.*", rows[0][0]) + require.Regexp(t, "time:.*, loops:.*, inner:{total:.*, concurrency:.*, task:.*, construct:.*, fetch:.*, build:.*}, probe:.*", rows[0][5]) // Test for index lookup hash join. rows = tk.MustQuery("explain analyze select /*+ INL_HASH_JOIN(t1, t2) */ * from t1,t2 where t1.a=t2.a;").Rows() - c.Assert(len(rows), Equals, 8) - c.Assert(rows[0][0], Matches, "IndexHashJoin.*") - c.Assert(rows[0][5], Matches, "time:.*, loops:.*, inner:{total:.*, concurrency:.*, task:.*, construct:.*, fetch:.*, build:.*, join:.*}") + require.Equal(t, 8, len(rows)) + require.Regexp(t, "IndexHashJoin.*", rows[0][0]) + require.Regexp(t, "time:.*, loops:.*, inner:{total:.*, concurrency:.*, task:.*, construct:.*, fetch:.*, build:.*, join:.*}", rows[0][5]) // Test for hash join. rows = tk.MustQuery("explain analyze select /*+ HASH_JOIN(t1, t2) */ * from t1,t2 where t1.a=t2.a;").Rows() - c.Assert(len(rows), Equals, 7) - c.Assert(rows[0][0], Matches, "HashJoin.*") - c.Assert(rows[0][5], Matches, "time:.*, loops:.*, build_hash_table:{total:.*, fetch:.*, build:.*}, probe:{concurrency:5, total:.*, max:.*, probe:.*, fetch:.*}") + require.Equal(t, 7, len(rows)) + require.Regexp(t, "HashJoin.*", rows[0][0]) + require.Regexp(t, "time:.*, loops:.*, build_hash_table:{total:.*, fetch:.*, build:.*}, probe:{concurrency:5, total:.*, max:.*, probe:.*, fetch:.*}", rows[0][5]) // Test for index merge join. rows = tk.MustQuery("explain analyze select /*+ INL_MERGE_JOIN(t1, t2) */ * from t1,t2 where t1.a=t2.a;").Rows() - c.Assert(len(rows), Equals, 9) - c.Assert(rows[0][0], Matches, "IndexMergeJoin_.*") - c.Assert(rows[0][5], Matches, fmt.Sprintf(".*Concurrency:%v.*", tk.Se.GetSessionVars().IndexLookupJoinConcurrency())) + require.Len(t, rows, 9) + require.Regexp(t, "IndexMergeJoin_.*", rows[0][0]) + require.Regexp(t, fmt.Sprintf(".*Concurrency:%v.*", tk.Session().GetSessionVars().IndexLookupJoinConcurrency()), rows[0][5]) } -func (s *testSuiteJoinSerial) TestIssue20270(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - err := failpoint.Enable("github.com/pingcap/tidb/executor/killedInJoin2Chunk", "return(true)") - c.Assert(err, IsNil) +func TestIssue20270(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t(c1 int, c2 int)") tk.MustExec("create table t1(c1 int, c2 int)") tk.MustExec("insert into t values(1,1),(2,2)") tk.MustExec("insert into t1 values(2,3),(4,4)") - err = tk.QueryToErr("select /*+ TIDB_HJ(t, t1) */ * from t left join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") - c.Assert(err, Equals, executor.ErrQueryInterrupted) - err = failpoint.Disable("github.com/pingcap/tidb/executor/killedInJoin2Chunk") - c.Assert(err, IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/killedInJoin2Chunk", "return(true)")) + err := tk.QueryToErr("select /*+ TIDB_HJ(t, t1) */ * from t left join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + require.Equal(t, executor.ErrQueryInterrupted, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/killedInJoin2Chunk")) plannercore.ForceUseOuterBuild4Test = true defer func() { plannercore.ForceUseOuterBuild4Test = false }() err = failpoint.Enable("github.com/pingcap/tidb/executor/killedInJoin2ChunkForOuterHashJoin", "return(true)") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("insert into t1 values(1,30),(2,40)") err = tk.QueryToErr("select /*+ TIDB_HJ(t, t1) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") - c.Assert(err, Equals, executor.ErrQueryInterrupted) + require.Equal(t, executor.ErrQueryInterrupted, err) err = failpoint.Disable("github.com/pingcap/tidb/executor/killedInJoin2ChunkForOuterHashJoin") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testSuiteJoinSerial) TestIssue20710(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20710(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists s;") tk.MustExec("create table t(a int, b int)") @@ -2595,27 +2687,33 @@ func (s *testSuiteJoinSerial) TestIssue20710(c *C) { tk.MustQuery("show warnings").Check(testkit.Rows()) } -func (s *testSuiteJoinSerial) TestIssue20779(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20779(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int, b int, index idx(b));") tk.MustExec("insert into t1 values(1, 1);") tk.MustExec("insert into t1 select * from t1;") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testIssue20779", "return"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testIssue20779", "return")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testIssue20779"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testIssue20779")) }() rs, err := tk.Exec("select /*+ inl_hash_join(t2) */ t1.b from t1 left join t1 t2 on t1.b=t2.b order by t1.b;") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = session.GetRows4Test(context.Background(), nil, rs) - c.Assert(err.Error(), Matches, "testIssue20779") - c.Assert(rs.Close(), IsNil) + require.EqualError(t, err, "testIssue20779") + require.NoError(t, rs.Close()) } -func (s *testSuiteJoinSerial) TestIssue20219(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20219(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t,s ") tk.MustExec("CREATE TABLE `t` ( `a` set('a','b','c','d','e','f','g','h','i','j') DEFAULT NULL );") tk.MustExec("insert into t values('i'), ('j');") @@ -2627,8 +2725,11 @@ func (s *testSuiteJoinSerial) TestIssue20219(c *C) { tk.MustQuery("show warnings").Check(testkit.Rows()) } -func (s *testSuiteJoinSerial) TestIssue25902(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue25902(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists tt1,tt2,tt3; ") tk.MustExec("create table tt1 (ts timestamp);") tk.MustExec("create table tt2 (ts varchar(32));") @@ -2644,23 +2745,26 @@ func (s *testSuiteJoinSerial) TestIssue25902(c *C) { tk.MustExec("set @@session.time_zone = @tmp;") } -func (s *testSuiteJoinSerial) TestIssue30211(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue30211(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2;") tk.MustExec("create table t1(a int, index(a));") tk.MustExec("create table t2(a int, index(a));") func() { fpName := "github.com/pingcap/tidb/executor/TestIssue30211" - c.Assert(failpoint.Enable(fpName, `panic("TestIssue30211 IndexJoinPanic")`), IsNil) + require.NoError(t, failpoint.Enable(fpName, `panic("TestIssue30211 IndexJoinPanic")`)) defer func() { - c.Assert(failpoint.Disable(fpName), IsNil) + require.NoError(t, failpoint.Disable(fpName)) }() - err := tk.QueryToErr("select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.a;").Error() - c.Assert(err, Matches, "failpoint panic: TestIssue30211 IndexJoinPanic") + err := tk.QueryToErr("select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.a;") + require.EqualError(t, err, "failpoint panic: TestIssue30211 IndexJoinPanic") + + err = tk.QueryToErr("select /*+ inl_hash_join(t1) */ * from t1 join t2 on t1.a = t2.a;") + require.EqualError(t, err, "failpoint panic: TestIssue30211 IndexJoinPanic") - err = tk.QueryToErr("select /*+ inl_hash_join(t1) */ * from t1 join t2 on t1.a = t2.a;").Error() - c.Assert(err, Matches, "failpoint panic: TestIssue30211 IndexJoinPanic") }() tk.MustExec("insert into t1 values(1),(2);") tk.MustExec("insert into t2 values(1),(1),(2),(2);") @@ -2675,7 +2779,58 @@ func (s *testSuiteJoinSerial) TestIssue30211(c *C) { }) }() err := tk.QueryToErr("select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.a;").Error() - c.Assert(strings.Contains(err, "Out Of Memory Quota"), IsTrue) + require.True(t, strings.Contains(err, "Out Of Memory Quota")) err = tk.QueryToErr("select /*+ inl_hash_join(t1) */ * from t1 join t2 on t1.a = t2.a;").Error() - c.Assert(strings.Contains(err, "Out Of Memory Quota"), IsTrue) + require.True(t, strings.Contains(err, "Out Of Memory Quota")) +} + +func TestIssue31129(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_init_chunk_size=2") + tk.MustExec("set @@tidb_index_join_batch_size=10") + tk.MustExec("DROP TABLE IF EXISTS t, s") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.MustExec("create table t(pk int primary key, a int)") + for i := 0; i < 100; i++ { + tk.MustExec(fmt.Sprintf("insert into t values(%d, %d)", i, i)) + } + tk.MustExec("create table s(a int primary key)") + for i := 0; i < 100; i++ { + tk.MustExec(fmt.Sprintf("insert into s values(%d)", i)) + } + tk.MustExec("analyze table t") + tk.MustExec("analyze table s") + + // Test IndexNestedLoopHashJoin keepOrder. + fpName := "github.com/pingcap/tidb/executor/TestIssue31129" + require.NoError(t, failpoint.Enable(fpName, "return")) + err := tk.QueryToErr("select /*+ INL_HASH_JOIN(s) */ * from t left join s on t.a=s.a order by t.pk") + require.True(t, strings.Contains(err.Error(), "TestIssue31129")) + require.NoError(t, failpoint.Disable(fpName)) + + // Test IndexNestedLoopHashJoin build hash table panic. + fpName = "github.com/pingcap/tidb/executor/IndexHashJoinBuildHashTablePanic" + require.NoError(t, failpoint.Enable(fpName, `panic("IndexHashJoinBuildHashTablePanic")`)) + err = tk.QueryToErr("select /*+ INL_HASH_JOIN(s) */ * from t left join s on t.a=s.a order by t.pk") + require.True(t, strings.Contains(err.Error(), "IndexHashJoinBuildHashTablePanic")) + require.NoError(t, failpoint.Disable(fpName)) + + // Test IndexNestedLoopHashJoin fetch inner fail. + fpName = "github.com/pingcap/tidb/executor/IndexHashJoinFetchInnerResultsErr" + require.NoError(t, failpoint.Enable(fpName, "return")) + err = tk.QueryToErr("select /*+ INL_HASH_JOIN(s) */ * from t left join s on t.a=s.a order by t.pk") + require.True(t, strings.Contains(err.Error(), "IndexHashJoinFetchInnerResultsErr")) + require.NoError(t, failpoint.Disable(fpName)) + + // Test IndexNestedLoopHashJoin build hash table panic and IndexNestedLoopHashJoin fetch inner fail at the same time. + fpName1, fpName2 := "github.com/pingcap/tidb/executor/IndexHashJoinBuildHashTablePanic", "github.com/pingcap/tidb/executor/IndexHashJoinFetchInnerResultsErr" + require.NoError(t, failpoint.Enable(fpName1, `panic("IndexHashJoinBuildHashTablePanic")`)) + require.NoError(t, failpoint.Enable(fpName2, "return")) + err = tk.QueryToErr("select /*+ INL_HASH_JOIN(s) */ * from t left join s on t.a=s.a order by t.pk") + require.True(t, strings.Contains(err.Error(), "IndexHashJoinBuildHashTablePanic")) + require.NoError(t, failpoint.Disable(fpName1)) + require.NoError(t, failpoint.Disable(fpName2)) } diff --git a/executor/joiner_test.go b/executor/joiner_test.go index 2630290fb78f2..ff87d271fdcfd 100644 --- a/executor/joiner_test.go +++ b/executor/joiner_test.go @@ -16,22 +16,16 @@ package executor import ( "math/rand" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testSuiteJoiner{}) - -type testSuiteJoiner struct{} - -func (s *testSuiteJoiner) SetUpSuite(c *C) { -} - -func (s *testSuiteJoiner) TestRequiredRows(c *C) { +func TestRequiredRows(t *testing.T) { joinTypes := []core.JoinType{core.InnerJoin, core.LeftOuterJoin, core.RightOuterJoin} lTypes := [][]byte{ {mysql.TypeLong}, @@ -74,8 +68,8 @@ func (s *testSuiteJoiner) TestRequiredRows(c *C) { it := chunk.NewIterator4Chunk(innerChk) it.Begin() _, _, err := joiner.tryToMatchInners(outerRow, it, result) - c.Assert(err, IsNil) - c.Assert(result.NumRows(), Equals, required) + require.NoError(t, err) + require.Equal(t, required, result.NumRows()) } } } diff --git a/executor/load_data.go b/executor/load_data.go index 1202675ebbce0..5344a14fe8948 100644 --- a/executor/load_data.go +++ b/executor/load_data.go @@ -58,10 +58,7 @@ func (e *LoadDataExec) Next(ctx context.Context, req *chunk.Chunk) error { if !e.IsLocal { return errors.New("Load Data: don't support load data without local field") } - // TODO: support load data with replace field. - if e.OnDuplicate == ast.OnDuplicateKeyHandlingReplace { - return errors.New("Load Data: don't support load data with replace field") - } + e.loadDataInfo.OnDuplicate = e.OnDuplicate // TODO: support lines terminated is "". if len(e.loadDataInfo.LinesInfo.Terminated) == 0 { return errors.New("Load Data: don't support load data terminated is nil") @@ -123,6 +120,7 @@ type LoadDataInfo struct { commitTaskQueue chan CommitTask StopCh chan struct{} QuitCh chan struct{} + OnDuplicate ast.OnDuplicateKeyHandlingType } // FieldMapping inticates the relationship between input field and table column or user variable @@ -157,7 +155,7 @@ func (e *LoadDataInfo) initLoadColumns(columnNames []string) error { } if col.Name.L == model.ExtraHandleName.L { if !e.ctx.GetSessionVars().AllowWriteRowID { - return errors.Errorf("load data statement for _tidb_rowid are not supported.") + return errors.Errorf("load data statement for _tidb_rowid are not supported") } e.hasExtraHandle = true break @@ -363,65 +361,20 @@ func (e *LoadDataInfo) SetMaxRowsInBatch(limit uint64) { e.curBatchCnt = 0 } -// getValidData returns prevData and curData that starts from starting symbol. -// If the data doesn't have starting symbol, prevData is nil and curData is curData[len(curData)-startingLen+1:]. -// If curData size less than startingLen, curData is returned directly. -func (e *LoadDataInfo) getValidData(prevData, curData []byte) ([]byte, []byte) { - startingLen := len(e.LinesInfo.Starting) - if startingLen == 0 { - return prevData, curData - } - - prevLen := len(prevData) - if prevLen > 0 { - // starting symbol in the prevData - idx := strings.Index(string(hack.String(prevData)), e.LinesInfo.Starting) - if idx != -1 { - return prevData[idx:], curData - } - - // starting symbol in the middle of prevData and curData - restStart := curData - if len(curData) >= startingLen { - restStart = curData[:startingLen-1] - } - prevData = append(prevData, restStart...) - idx = strings.Index(string(hack.String(prevData)), e.LinesInfo.Starting) - if idx != -1 { - return prevData[idx:prevLen], curData - } - } - - // starting symbol in the curData +// getValidData returns curData that starts from starting symbol. +// If the data doesn't have starting symbol, return curData[len(curData)-startingLen+1:] and false. +func (e *LoadDataInfo) getValidData(curData []byte) ([]byte, bool) { idx := strings.Index(string(hack.String(curData)), e.LinesInfo.Starting) - if idx != -1 { - return nil, curData[idx:] + if idx == -1 { + return curData[len(curData)-len(e.LinesInfo.Starting)+1:], false } - // no starting symbol - if len(curData) >= startingLen { - curData = curData[len(curData)-startingLen+1:] - } - return nil, curData -} - -func (e *LoadDataInfo) isInQuoter(bs []byte) bool { - inQuoter := false - for i := 0; i < len(bs); i++ { - switch bs[i] { - case e.FieldsInfo.Enclosed: - inQuoter = !inQuoter - case e.FieldsInfo.Escaped: - i++ - default: - } - } - return inQuoter + return curData[idx:], true } -// IndexOfTerminator return index of terminator, if not, return -1. +// indexOfTerminator return index of terminator, if not, return -1. // normally, the field terminator and line terminator is short, so we just use brute force algorithm. -func (e *LoadDataInfo) IndexOfTerminator(bs []byte, inQuoter bool) int { +func (e *LoadDataInfo) indexOfTerminator(bs []byte) int { fieldTerm := []byte(e.FieldsInfo.Terminated) fieldTermLen := len(fieldTerm) lineTerm := []byte(e.LinesInfo.Terminated) @@ -459,15 +412,16 @@ func (e *LoadDataInfo) IndexOfTerminator(bs []byte, inQuoter bool) int { } } atFieldStart := true + inQuoter := false loop: for i := 0; i < len(bs); i++ { - if atFieldStart && bs[i] == e.FieldsInfo.Enclosed { + if atFieldStart && e.FieldsInfo.Enclosed != byte(0) && bs[i] == e.FieldsInfo.Enclosed { inQuoter = !inQuoter atFieldStart = false continue } restLen := len(bs) - i - 1 - if inQuoter && bs[i] == e.FieldsInfo.Enclosed { + if inQuoter && e.FieldsInfo.Enclosed != byte(0) && bs[i] == e.FieldsInfo.Enclosed { // look ahead to see if it is end of line or field. switch cmpTerm(restLen, bs[i+1:]) { case lineTermType: @@ -505,67 +459,32 @@ loop: // getLine returns a line, curData, the next data start index and a bool value. // If it has starting symbol the bool is true, otherwise is false. func (e *LoadDataInfo) getLine(prevData, curData []byte, ignore bool) ([]byte, []byte, bool) { - startingLen := len(e.LinesInfo.Starting) - prevData, curData = e.getValidData(prevData, curData) - if prevData == nil && len(curData) < startingLen { - return nil, curData, false - } - inquotor := e.isInQuoter(prevData) - prevLen := len(prevData) - terminatedLen := len(e.LinesInfo.Terminated) - curStartIdx := 0 - if prevLen < startingLen { - curStartIdx = startingLen - prevLen - } - endIdx := -1 - if len(curData) >= curStartIdx { - if ignore { - endIdx = strings.Index(string(hack.String(curData[curStartIdx:])), e.LinesInfo.Terminated) - } else { - endIdx = e.IndexOfTerminator(curData[curStartIdx:], inquotor) - } - } - if endIdx == -1 { - // no terminated symbol - if len(prevData) == 0 { - return nil, curData, true - } - - // terminated symbol in the middle of prevData and curData + if prevData != nil { curData = append(prevData, curData...) - if ignore { - endIdx = strings.Index(string(hack.String(curData[startingLen:])), e.LinesInfo.Terminated) - } else { - endIdx = e.IndexOfTerminator(curData[startingLen:], inquotor) + } + startLen := len(e.LinesInfo.Starting) + if startLen != 0 { + if len(curData) < startLen { + return nil, curData, false } - if endIdx != -1 { - nextDataIdx := startingLen + endIdx + terminatedLen - return curData[startingLen : startingLen+endIdx], curData[nextDataIdx:], true + var ok bool + curData, ok = e.getValidData(curData) + if !ok { + return nil, curData, false } - // no terminated symbol - return nil, curData, true } - - // terminated symbol in the curData - nextDataIdx := curStartIdx + endIdx + terminatedLen - if len(prevData) == 0 { - return curData[curStartIdx : curStartIdx+endIdx], curData[nextDataIdx:], true - } - - // terminated symbol in the curData - prevData = append(prevData, curData[:nextDataIdx]...) + var endIdx int if ignore { - endIdx = strings.Index(string(hack.String(prevData[startingLen:])), e.LinesInfo.Terminated) + endIdx = strings.Index(string(hack.String(curData[startLen:])), e.LinesInfo.Terminated) } else { - endIdx = e.IndexOfTerminator(prevData[startingLen:], inquotor) + endIdx = e.indexOfTerminator(curData[startLen:]) } - if endIdx >= prevLen { - return prevData[startingLen : startingLen+endIdx], curData[nextDataIdx:], true + + if endIdx == -1 { + return nil, curData, true } - // terminated symbol in the middle of prevData and curData - lineLen := startingLen + endIdx + terminatedLen - return prevData[startingLen : startingLen+endIdx], curData[lineLen-prevLen:], true + return curData[startLen : startLen+endIdx], curData[startLen+endIdx+len(e.LinesInfo.Terminated):], true } // InsertData inserts data into specified table according to the specified format. @@ -640,7 +559,13 @@ func (e *LoadDataInfo) CheckAndInsertOneBatch(ctx context.Context, rows [][]type return err } e.ctx.GetSessionVars().StmtCtx.AddRecordRows(cnt) - err = e.batchCheckAndInsert(ctx, rows[0:cnt], e.addRecordLD) + + replace := false + if e.OnDuplicate == ast.OnDuplicateKeyHandlingReplace { + replace = true + } + + err = e.batchCheckAndInsert(ctx, rows[0:cnt], e.addRecordLD, replace) if err != nil { return err } @@ -652,7 +577,7 @@ func (e *LoadDataInfo) CheckAndInsertOneBatch(ctx context.Context, rows [][]type func (e *LoadDataInfo) SetMessage() { stmtCtx := e.ctx.GetSessionVars().StmtCtx numRecords := stmtCtx.RecordRows() - numDeletes := 0 + numDeletes := stmtCtx.DeletedRows() numSkipped := numRecords - stmtCtx.CopiedRows() numWarnings := stmtCtx.WarningCount() msg := fmt.Sprintf(mysql.MySQLErrName[mysql.ErrLoadInfo].Raw, numRecords, numDeletes, numSkipped, numWarnings) diff --git a/executor/main_test.go b/executor/main_test.go index bff65b72d6a2d..cf07e9c411b94 100644 --- a/executor/main_test.go +++ b/executor/main_test.go @@ -16,7 +16,6 @@ package executor_test import ( "fmt" - "os" "testing" "github.com/pingcap/tidb/config" @@ -32,14 +31,19 @@ import ( var testDataMap = make(testdata.BookKeeper) var prepareMergeSuiteData testdata.TestData var aggMergeSuiteData testdata.TestData +var executorSuiteData testdata.TestData +var pointGetSuiteData testdata.TestData func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - - testDataMap.LoadTestSuiteData("testdata", "prepare_suite") + testbridge.SetupForCommonTest() testDataMap.LoadTestSuiteData("testdata", "agg_suite") - prepareMergeSuiteData = testDataMap["prepare_suite"] + testDataMap.LoadTestSuiteData("testdata", "executor_suite") + testDataMap.LoadTestSuiteData("testdata", "prepare_suite") + testDataMap.LoadTestSuiteData("testdata", "point_get_suite") aggMergeSuiteData = testDataMap["agg_suite"] + executorSuiteData = testDataMap["executor_suite"] + prepareMergeSuiteData = testDataMap["prepare_suite"] + pointGetSuiteData = testDataMap["point_get_suite"] autoid.SetStep(5000) config.UpdateGlobal(func(conf *config.Config) { @@ -47,16 +51,16 @@ func TestMain(m *testing.M) { conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 conf.Experimental.AllowsExpressionIndex = true + conf.OOMAction = config.OOMActionLog }) tikv.EnableFailpoints() - tmpDir := config.GetGlobalConfig().TempStoragePath - _ = os.RemoveAll(tmpDir) // clean the uncleared temp file during the last run. - _ = os.MkdirAll(tmpDir, 0755) opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), goleak.IgnoreTopFunction("gopkg.in/natefinch/lumberjack%2ev2.(*Logger).millRun"), + goleak.IgnoreTopFunction("github.com/tikv/client-go/v2/txnkv/transaction.keepAlive"), } callback := func(i int) int { testDataMap.GenerateOutputIfNeeded() diff --git a/executor/mem_reader.go b/executor/mem_reader.go index d345d11670c6e..1c4b29290b325 100644 --- a/executor/mem_reader.go +++ b/executor/mem_reader.go @@ -15,6 +15,9 @@ package executor import ( + "context" + + "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" @@ -34,7 +37,7 @@ import ( ) type memReader interface { - getMemRows() ([][]types.Datum, error) + getMemRows(ctx context.Context) ([][]types.Datum, error) getMemRowsHandle() ([]kv.Handle, error) } @@ -61,7 +64,12 @@ type memIndexReader struct { cacheTable kv.MemBuffer } -func buildMemIndexReader(us *UnionScanExec, idxReader *IndexReaderExecutor) *memIndexReader { +func buildMemIndexReader(ctx context.Context, us *UnionScanExec, idxReader *IndexReaderExecutor) *memIndexReader { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("buildMemIndexReader", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } kvRanges := idxReader.kvRanges outputOffset := make([]int, 0, len(us.columns)) for _, col := range idxReader.outputColumns { @@ -81,7 +89,12 @@ func buildMemIndexReader(us *UnionScanExec, idxReader *IndexReaderExecutor) *mem } } -func (m *memIndexReader) getMemRows() ([][]types.Datum, error) { +func (m *memIndexReader) getMemRows(ctx context.Context) ([][]types.Datum, error) { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("memIndexReader.getMemRows", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } tps := make([]*types.FieldType, 0, len(m.index.Columns)+1) cols := m.table.Columns for _, col := range m.index.Columns { @@ -167,8 +180,7 @@ type memTableReader struct { buffer allocBuf pkColIDs []int64 cacheTable kv.MemBuffer - // Used when extracting handles from row in memTableReader.getMemRowsHandle. - handleCols plannercore.HandleCols + offsets []int } type allocBuf struct { @@ -177,7 +189,12 @@ type allocBuf struct { rd *rowcodec.BytesDecoder } -func buildMemTableReader(us *UnionScanExec, tblReader *TableReaderExecutor) *memTableReader { +func buildMemTableReader(ctx context.Context, us *UnionScanExec, tblReader *TableReaderExecutor) *memTableReader { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("buildMemTableReader", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } colIDs := make(map[int64]int, len(us.columns)) for i, col := range us.columns { colIDs[col.ID] = i @@ -217,20 +234,32 @@ func buildMemTableReader(us *UnionScanExec, tblReader *TableReaderExecutor) *mem } // TODO: Try to make memXXXReader lazy, There is no need to decode many rows when parent operator only need 1 row. -func (m *memTableReader) getMemRows() ([][]types.Datum, error) { +func (m *memTableReader) getMemRows(ctx context.Context) ([][]types.Datum, error) { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("memTableReader.getMemRows", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) + resultRows := make([]types.Datum, len(m.columns)) + m.offsets = make([]int, len(m.columns)) + for i, col := range m.columns { + m.offsets[i] = m.colIDs[col.ID] + } err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { - row, err := m.decodeRecordKeyValue(key, value) + var err error + resultRows, err = m.decodeRecordKeyValue(key, value, &resultRows) if err != nil { return err } - mutableRow.SetDatums(row...) + mutableRow.SetDatums(resultRows...) matched, _, err := expression.EvalBool(m.ctx, m.conditions, mutableRow.ToRow()) if err != nil || !matched { return err } - m.addedRows = append(m.addedRows, row) + m.addedRows = append(m.addedRows, resultRows) + resultRows = make([]types.Datum, len(m.columns)) return nil }) if err != nil { @@ -244,30 +273,29 @@ func (m *memTableReader) getMemRows() ([][]types.Datum, error) { return m.addedRows, nil } -func (m *memTableReader) decodeRecordKeyValue(key, value []byte) ([]types.Datum, error) { +func (m *memTableReader) decodeRecordKeyValue(key, value []byte, resultRows *[]types.Datum) ([]types.Datum, error) { handle, err := tablecodec.DecodeRowKey(key) if err != nil { return nil, errors.Trace(err) } - return m.decodeRowData(handle, value) + return m.decodeRowData(handle, value, resultRows) } // decodeRowData uses to decode row data value. -func (m *memTableReader) decodeRowData(handle kv.Handle, value []byte) ([]types.Datum, error) { +func (m *memTableReader) decodeRowData(handle kv.Handle, value []byte, resultRows *[]types.Datum) ([]types.Datum, error) { values, err := m.getRowData(handle, value) if err != nil { return nil, err } - ds := make([]types.Datum, 0, len(m.columns)) - for _, col := range m.columns { - offset := m.colIDs[col.ID] - d, err := tablecodec.DecodeColumnValue(values[offset], &col.FieldType, m.ctx.GetSessionVars().Location()) + for i, col := range m.columns { + var datum types.Datum + err := tablecodec.DecodeColumnValueWithDatum(values[m.offsets[i]], &col.FieldType, m.ctx.GetSessionVars().Location(), &datum) if err != nil { return nil, err } - ds = append(ds, d) + (*resultRows)[i] = datum } - return ds, nil + return *resultRows, nil } // getRowData decodes raw byte slice to row data. @@ -329,17 +357,23 @@ func (m *memTableReader) getRowData(handle kv.Handle, value []byte) ([][]byte, e // getMemRowsHandle is called when memIndexMergeReader.partialPlans[i] is TableScan. func (m *memTableReader) getMemRowsHandle() ([]kv.Handle, error) { - rows, err := m.getMemRows() + handles := make([]kv.Handle, 0, 16) + err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { + handle, err := tablecodec.DecodeRowKey(key) + if err != nil { + return err + } + handles = append(handles, handle) + return nil + }) if err != nil { return nil, err } - handles := make([]kv.Handle, 0, len(rows)) - for _, row := range rows { - handle, err := m.handleCols.BuildHandleByDatums(row) - if err != nil { - return nil, err + + if m.desc { + for i, j := 0, len(handles)-1; i < j; i, j = i+1, j-1 { + handles[i], handles[j] = handles[j], handles[i] } - handles = append(handles, handle) } return handles, nil } @@ -455,7 +489,12 @@ type memIndexLookUpReader struct { cacheTable kv.MemBuffer } -func buildMemIndexLookUpReader(us *UnionScanExec, idxLookUpReader *IndexLookUpExecutor) *memIndexLookUpReader { +func buildMemIndexLookUpReader(ctx context.Context, us *UnionScanExec, idxLookUpReader *IndexLookUpExecutor) *memIndexLookUpReader { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("buildMemIndexLookUpReader", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } kvRanges := idxLookUpReader.kvRanges outputOffset := []int{len(idxLookUpReader.index.Columns)} memIdxReader := &memIndexReader{ @@ -487,7 +526,12 @@ func buildMemIndexLookUpReader(us *UnionScanExec, idxLookUpReader *IndexLookUpEx } } -func (m *memIndexLookUpReader) getMemRows() ([][]types.Datum, error) { +func (m *memIndexLookUpReader) getMemRows(ctx context.Context) ([][]types.Datum, error) { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("memIndexLookUpReader.getMemRows", opentracing.ChildOf(span.Context())) + defer span1.Finish() + ctx = opentracing.ContextWithSpan(ctx, span1) + } kvRanges := [][]kv.KeyRange{m.idxReader.kvRanges} tbls := []table.Table{m.table} if m.partitionMode { @@ -535,7 +579,7 @@ func (m *memIndexLookUpReader) getMemRows() ([][]types.Datum, error) { cacheTable: m.cacheTable, } - return memTblReader.getMemRows() + return memTblReader.getMemRows(ctx) } func (m *memIndexLookUpReader) getMemRowsHandle() ([]kv.Handle, error) { @@ -557,7 +601,12 @@ type memIndexMergeReader struct { partitionKVRanges [][][]kv.KeyRange // kv ranges for these partition tables } -func buildMemIndexMergeReader(us *UnionScanExec, indexMergeReader *IndexMergeReaderExecutor) *memIndexMergeReader { +func buildMemIndexMergeReader(ctx context.Context, us *UnionScanExec, indexMergeReader *IndexMergeReaderExecutor) *memIndexMergeReader { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("buildMemIndexMergeReader", opentracing.ChildOf(span.Context())) + defer span1.Finish() + opentracing.ContextWithSpan(ctx, span1) + } indexCount := len(indexMergeReader.indexes) memReaders := make([]memReader, 0, indexCount) for i := 0; i < indexCount; i++ { @@ -577,7 +626,6 @@ func buildMemIndexMergeReader(us *UnionScanExec, indexMergeReader *IndexMergeRea handleBytes: make([]byte, 0, 16), rd: rd, }, - handleCols: indexMergeReader.handleCols, }) } else { outputOffset := []int{len(indexMergeReader.indexes[i].Columns)} @@ -609,7 +657,12 @@ func buildMemIndexMergeReader(us *UnionScanExec, indexMergeReader *IndexMergeRea } } -func (m *memIndexMergeReader) getMemRows() ([][]types.Datum, error) { +func (m *memIndexMergeReader) getMemRows(ctx context.Context) ([][]types.Datum, error) { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("memIndexMergeReader.getMemRows", opentracing.ChildOf(span.Context())) + defer span1.Finish() + ctx = opentracing.ContextWithSpan(ctx, span1) + } tbls := []table.Table{m.table} // [partNum][indexNum][rangeNum] var kvRanges [][][]kv.KeyRange @@ -658,7 +711,7 @@ func (m *memIndexMergeReader) getMemRows() ([][]types.Datum, error) { }, } - return memTblReader.getMemRows() + return memTblReader.getMemRows(ctx) } // Union all handles of different Indexes. diff --git a/executor/memory_test.go b/executor/memory_test.go index 12843f86079e8..b4fdbaeceae7e 100644 --- a/executor/memory_test.go +++ b/executor/memory_test.go @@ -18,112 +18,84 @@ import ( "context" "fmt" "runtime" + "runtime/debug" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testMemoryLeak{}) - -type testMemoryLeak struct { - store kv.Storage - domain *domain.Domain -} - -func (s *testMemoryLeak) SetUpSuite(c *C) { - var err error - s.store, err = mockstore.NewMockStore() - c.Assert(err, IsNil) - s.domain, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) -} - -func (s *testMemoryLeak) TearDownSuite(c *C) { - s.domain.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testMemoryLeak) TestPBMemoryLeak(c *C) { - c.Skip("too slow") - - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "create database test_mem") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test_mem") - c.Assert(err, IsNil) +func TestPBMemoryLeak(t *testing.T) { + debug.SetGCPercent(1000) + defer debug.SetGCPercent(100) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database test_mem") + tk.MustExec("use test_mem") // prepare data totalSize := uint64(256 << 20) // 256MB blockSize := uint64(8 << 10) // 8KB delta := totalSize / 5 numRows := totalSize / blockSize - _, err = se.Execute(context.Background(), fmt.Sprintf("create table t (c varchar(%v))", blockSize)) - c.Assert(err, IsNil) - defer func() { - _, err = se.Execute(context.Background(), "drop table t") - c.Assert(err, IsNil) - }() + tk.MustExec(fmt.Sprintf("create table t (c varchar(%v))", blockSize)) sql := fmt.Sprintf("insert into t values (space(%v))", blockSize) for i := uint64(0); i < numRows; i++ { - _, err = se.Execute(context.Background(), sql) - c.Assert(err, IsNil) + tk.MustExec(sql) } // read data runtime.GC() - allocatedBegin, inUseBegin := s.readMem() - records, err := se.Execute(context.Background(), "select * from t") - c.Assert(err, IsNil) + allocatedBegin, inUseBegin := readMem() + records, err := tk.Session().Execute(context.Background(), "select * from t") + require.NoError(t, err) record := records[0] rowCnt := 0 chk := record.NewChunk(nil) for { - c.Assert(record.Next(context.Background(), chk), IsNil) + require.NoError(t, record.Next(context.Background(), chk)) rowCnt += chk.NumRows() if chk.NumRows() == 0 { break } } - c.Assert(rowCnt, Equals, int(numRows)) + require.Equal(t, int(numRows), rowCnt) // check memory before close runtime.GC() - allocatedAfter, inUseAfter := s.readMem() - c.Assert(allocatedAfter-allocatedBegin, GreaterEqual, totalSize) - c.Assert(s.memDiff(inUseAfter, inUseBegin), Less, delta) + allocatedAfter, inUseAfter := readMem() + require.GreaterOrEqual(t, allocatedAfter-allocatedBegin, totalSize) + require.Less(t, memDiff(inUseAfter, inUseBegin), delta) - se.Close() runtime.GC() - allocatedFinal, inUseFinal := s.readMem() - c.Assert(allocatedFinal-allocatedAfter, Less, delta) - c.Assert(s.memDiff(inUseFinal, inUseAfter), Less, delta) + allocatedFinal, inUseFinal := readMem() + require.Less(t, allocatedFinal-allocatedAfter, delta) + require.Less(t, memDiff(inUseFinal, inUseAfter), delta) } // nolint:unused -func (s *testMemoryLeak) readMem() (allocated, heapInUse uint64) { +func readMem() (allocated, heapInUse uint64) { var stat runtime.MemStats runtime.ReadMemStats(&stat) return stat.TotalAlloc, stat.HeapInuse } // nolint:unused -func (s *testMemoryLeak) memDiff(m1, m2 uint64) uint64 { +func memDiff(m1, m2 uint64) uint64 { if m1 > m2 { return m1 - m2 } return m2 - m1 } -func (s *testMemoryLeak) TestGlobalMemoryTrackerOnCleanUp(c *C) { +func TestGlobalMemoryTrackerOnCleanUp(t *testing.T) { // TODO: assert the memory consume has happened in another way originConsume := executor.GlobalMemoryUsageTracker.BytesConsumed() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int)") @@ -133,12 +105,12 @@ func (s *testMemoryLeak) TestGlobalMemoryTrackerOnCleanUp(c *C) { tk.MustExec("insert t (id) values (2)") tk.MustExec("insert t (id) values (3)") afterConsume := executor.GlobalMemoryUsageTracker.BytesConsumed() - c.Assert(originConsume, Equals, afterConsume) + require.Equal(t, afterConsume, originConsume) // assert update tk.MustExec("update t set id = 4 where id = 1") tk.MustExec("update t set id = 5 where id = 2") tk.MustExec("update t set id = 6 where id = 3") afterConsume = executor.GlobalMemoryUsageTracker.BytesConsumed() - c.Assert(originConsume, Equals, afterConsume) + require.Equal(t, afterConsume, originConsume) } diff --git a/executor/memtable_reader.go b/executor/memtable_reader.go index 1f014e53d26ae..64729e3705dcb 100644 --- a/executor/memtable_reader.go +++ b/executor/memtable_reader.go @@ -40,15 +40,14 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/set" - "github.com/tikv/client-go/v2/tikv" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -272,7 +271,7 @@ func fetchClusterConfig(sctx sessionctx.Context, nodeTypes, nodeAddrs set.String close(ch) // Keep the original order to make the result more stable - var results []result + var results []result // nolint: prealloc for result := range ch { if result.err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(result.err) @@ -350,7 +349,7 @@ func (e *clusterServerInfoRetriever) retrieve(ctx context.Context, sctx sessionc wg.Wait() close(ch) // Keep the original order to make the result more stable - var results []result + var results []result // nolint: prealloc for result := range ch { if result.err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(result.err) @@ -566,7 +565,7 @@ func (e *clusterLogRetriever) startRetrieving( // The retrieve progress may be abort ctx, e.cancel = context.WithCancel(ctx) - var results []chan logStreamResult + var results []chan logStreamResult // nolint: prealloc for _, srv := range serversInfo { typ := srv.ServerType address := srv.Address @@ -767,19 +766,19 @@ type HistoryHotRegions struct { // HistoryHotRegion records each hot region's statistics. // it's the response of PD. type HistoryHotRegion struct { - UpdateTime int64 `json:"update_time,omitempty"` - RegionID uint64 `json:"region_id,omitempty"` - StoreID uint64 `json:"store_id,omitempty"` - PeerID uint64 `json:"peer_id,omitempty"` - IsLearner bool `json:"is_learner,omitempty"` - IsLeader bool `json:"is_leader,omitempty"` - HotRegionType string `json:"hot_region_type,omitempty"` - HotDegree int64 `json:"hot_degree,omitempty"` - FlowBytes float64 `json:"flow_bytes,omitempty"` - KeyRate float64 `json:"key_rate,omitempty"` - QueryRate float64 `json:"query_rate,omitempty"` - StartKey []byte `json:"start_key,omitempty"` - EndKey []byte `json:"end_key,omitempty"` + UpdateTime int64 `json:"update_time"` + RegionID uint64 `json:"region_id"` + StoreID uint64 `json:"store_id"` + PeerID uint64 `json:"peer_id"` + IsLearner bool `json:"is_learner"` + IsLeader bool `json:"is_leader"` + HotRegionType string `json:"hot_region_type"` + HotDegree int64 `json:"hot_degree"` + FlowBytes float64 `json:"flow_bytes"` + KeyRate float64 `json:"key_rate"` + QueryRate float64 `json:"query_rate"` + StartKey string `json:"start_key"` + EndKey string `json:"end_key"` } func (e *hotRegionsHistoryRetriver) initialize(ctx context.Context, sctx sessionctx.Context) ([]chan hotRegionsResult, error) { @@ -893,8 +892,6 @@ func (e *hotRegionsHistoryRetriver) retrieve(ctx context.Context, sctx sessionct } // Merge the results var finalRows [][]types.Datum - allSchemas := sctx.GetInfoSchema().(infoschema.InfoSchema).AllSchemas() - tz := sctx.GetSessionVars().Location() tikvStore, ok := sctx.GetStore().(helper.Storage) if !ok { return nil, errors.New("Information about hot region can be gotten only when the storage is TiKV") @@ -903,14 +900,18 @@ func (e *hotRegionsHistoryRetriver) retrieve(ctx context.Context, sctx sessionct Store: tikvStore, RegionCache: tikvStore.GetRegionCache(), } + tz := sctx.GetSessionVars().Location() + allSchemas := sessiontxn.GetTxnManager(sctx).GetTxnInfoSchema().AllSchemas() + schemas := tikvHelper.FilterMemDBs(allSchemas) + tables := tikvHelper.GetTablesInfoWithKeyRange(schemas) for e.heap.Len() > 0 && len(finalRows) < hotRegionsHistoryBatchSize { minTimeItem := heap.Pop(e.heap).(hotRegionsResult) - row, err := e.getHotRegionRowWithSchemaInfo(minTimeItem.messages.HistoryHotRegion[0], tikvHelper, allSchemas, tz) + rows, err := e.getHotRegionRowWithSchemaInfo(minTimeItem.messages.HistoryHotRegion[0], tikvHelper, tables, tz) if err != nil { return nil, err } - if row != nil { - finalRows = append(finalRows, row) + if rows != nil { + finalRows = append(finalRows, rows...) } minTimeItem.messages.HistoryHotRegion = minTimeItem.messages.HistoryHotRegion[1:] // Fetch next message item @@ -926,74 +927,191 @@ func (e *hotRegionsHistoryRetriver) retrieve(ctx context.Context, sctx sessionct func (e *hotRegionsHistoryRetriver) getHotRegionRowWithSchemaInfo( hisHotRegion *HistoryHotRegion, tikvHelper *helper.Helper, - allSchemas []*model.DBInfo, + tables []helper.TableInfoWithKeyRange, tz *time.Location, -) ([]types.Datum, error) { - _, startKey, _ := codec.DecodeBytes(hisHotRegion.StartKey, []byte{}) - _, endKey, _ := codec.DecodeBytes(hisHotRegion.EndKey, []byte{}) - region := &tikv.KeyLocation{StartKey: startKey, EndKey: endKey} - hotRange, err := helper.NewRegionFrameRange(region) - if err != nil { - return nil, err +) ([][]types.Datum, error) { + regionsInfo := []*helper.RegionInfo{ + { + ID: int64(hisHotRegion.RegionID), + StartKey: hisHotRegion.StartKey, + EndKey: hisHotRegion.EndKey, + }} + regionsTableInfos := tikvHelper.ParseRegionsTableInfos(regionsInfo, tables) + + var rows [][]types.Datum + // Ignore row without corresponding schema. + if tableInfos, ok := regionsTableInfos[int64(hisHotRegion.RegionID)]; ok { + for _, tableInfo := range tableInfos { + updateTimestamp := time.Unix(hisHotRegion.UpdateTime/1000, (hisHotRegion.UpdateTime%1000)*int64(time.Millisecond)) + if updateTimestamp.Location() != tz { + updateTimestamp.In(tz) + } + updateTime := types.NewTime(types.FromGoTime(updateTimestamp), mysql.TypeTimestamp, types.MinFsp) + row := make([]types.Datum, len(infoschema.TableTiDBHotRegionsHistoryCols)) + + row[0].SetMysqlTime(updateTime) + row[1].SetString(strings.ToUpper(tableInfo.DB.Name.O), mysql.DefaultCollationName) + row[2].SetString(strings.ToUpper(tableInfo.Table.Name.O), mysql.DefaultCollationName) + row[3].SetInt64(tableInfo.Table.ID) + if tableInfo.IsIndex { + row[4].SetString(strings.ToUpper(tableInfo.Index.Name.O), mysql.DefaultCollationName) + row[5].SetInt64(tableInfo.Index.ID) + } else { + row[4].SetNull() + row[5].SetNull() + } + row[6].SetInt64(int64(hisHotRegion.RegionID)) + row[7].SetInt64(int64(hisHotRegion.StoreID)) + row[8].SetInt64(int64(hisHotRegion.PeerID)) + if hisHotRegion.IsLearner { + row[9].SetInt64(1) + } else { + row[9].SetInt64(0) + } + if hisHotRegion.IsLeader { + row[10].SetInt64(1) + } else { + row[10].SetInt64(0) + } + row[11].SetString(strings.ToUpper(hisHotRegion.HotRegionType), mysql.DefaultCollationName) + row[12].SetInt64(hisHotRegion.HotDegree) + row[13].SetFloat64(hisHotRegion.FlowBytes) + row[14].SetFloat64(hisHotRegion.KeyRate) + row[15].SetFloat64(hisHotRegion.QueryRate) + rows = append(rows, row) + } } - f := tikvHelper.FindTableIndexOfRegion(allSchemas, hotRange) - // Ignore row without corresponding schema f. - if f == nil { + return rows, nil +} + +type tikvRegionPeersRetriever struct { + dummyCloser + extractor *plannercore.TikvRegionPeersExtractor + retrieved bool +} + +func (e *tikvRegionPeersRetriever) retrieve(ctx context.Context, sctx sessionctx.Context) ([][]types.Datum, error) { + if e.extractor.SkipRequest || e.retrieved { return nil, nil } - row := make([]types.Datum, len(infoschema.TableTiDBHotRegionsHistoryCols)) - updateTimestamp := time.Unix(hisHotRegion.UpdateTime/1000, (hisHotRegion.UpdateTime%1000)*int64(time.Millisecond)) + e.retrieved = true + tikvStore, ok := sctx.GetStore().(helper.Storage) + if !ok { + return nil, errors.New("Information about hot region can be gotten only when the storage is TiKV") + } + tikvHelper := &helper.Helper{ + Store: tikvStore, + RegionCache: tikvStore.GetRegionCache(), + } + + var regionsInfo, regionsInfoByStoreID []helper.RegionInfo + regionMap := make(map[int64]*helper.RegionInfo) + storeMap := make(map[int64]struct{}) - if updateTimestamp.Location() != tz { - updateTimestamp.In(tz) + if len(e.extractor.StoreIDs) == 0 && len(e.extractor.RegionIDs) == 0 { + regionsInfo, err := tikvHelper.GetRegionsInfo() + if err != nil { + return nil, err + } + return e.packTiKVRegionPeersRows(regionsInfo.Regions, storeMap) } - updateTime := types.NewTime(types.FromGoTime(updateTimestamp), mysql.TypeTimestamp, types.MinFsp) - row[0].SetMysqlTime(updateTime) - row[1].SetString(strings.ToUpper(f.DBName), mysql.DefaultCollationName) - row[2].SetString(strings.ToUpper(f.TableName), mysql.DefaultCollationName) - row[3].SetInt64(f.TableID) - if f.IndexName != "" { - row[4].SetString(strings.ToUpper(f.IndexName), mysql.DefaultCollationName) - row[5].SetInt64(f.IndexID) - } else { - row[4].SetNull() - row[5].SetNull() - } - row[6].SetInt64(int64(hisHotRegion.RegionID)) - row[7].SetInt64(int64(hisHotRegion.StoreID)) - row[8].SetInt64(int64(hisHotRegion.PeerID)) - if hisHotRegion.IsLearner { - row[9].SetInt64(1) - } else { - row[9].SetInt64(0) + + for _, storeID := range e.extractor.StoreIDs { + // if a region_id located in 1, 4, 7 store we will get all of them when request any store_id, + // storeMap is used to filter peers on unexpected stores. + storeMap[int64(storeID)] = struct{}{} + storeRegionsInfo, err := tikvHelper.GetStoreRegionsInfo(storeID) + if err != nil { + return nil, err + } + for i, regionInfo := range storeRegionsInfo.Regions { + // regionMap is used to remove dup regions and record the region in regionsInfoByStoreID. + if _, ok := regionMap[regionInfo.ID]; !ok { + regionsInfoByStoreID = append(regionsInfoByStoreID, regionInfo) + regionMap[regionInfo.ID] = &storeRegionsInfo.Regions[i] + } + } } - if hisHotRegion.IsLeader { - row[10].SetInt64(1) - } else { - row[10].SetInt64(0) + + if len(e.extractor.RegionIDs) == 0 { + return e.packTiKVRegionPeersRows(regionsInfoByStoreID, storeMap) } - row[11].SetString(strings.ToUpper(hisHotRegion.HotRegionType), mysql.DefaultCollationName) - if hisHotRegion.HotDegree != 0 { - row[12].SetInt64(hisHotRegion.HotDegree) - } else { - row[12].SetNull() + for _, regionID := range e.extractor.RegionIDs { + regionInfoByStoreID, ok := regionMap[int64(regionID)] + if !ok { + // if there is storeIDs, target region_id is fetched by storeIDs, + // otherwise we need to fetch it from PD. + if len(e.extractor.StoreIDs) == 0 { + regionInfo, err := tikvHelper.GetRegionInfoByID(regionID) + if err != nil { + return nil, err + } + regionsInfo = append(regionsInfo, *regionInfo) + } + } else { + regionsInfo = append(regionsInfo, *regionInfoByStoreID) + } } - if hisHotRegion.FlowBytes != 0 { - row[13].SetFloat64(hisHotRegion.FlowBytes) - } else { - row[13].SetNull() + + return e.packTiKVRegionPeersRows(regionsInfo, storeMap) +} + +func (e *tikvRegionPeersRetriever) isUnexpectedStoreID(storeID int64, storeMap map[int64]struct{}) bool { + if len(e.extractor.StoreIDs) == 0 { + return false } - if hisHotRegion.KeyRate != 0 { - row[14].SetFloat64(hisHotRegion.KeyRate) - } else { - row[14].SetNull() + if _, ok := storeMap[storeID]; ok { + return false } - if hisHotRegion.QueryRate != 0 { - row[15].SetFloat64(hisHotRegion.QueryRate) - } else { - row[15].SetNull() + return true +} + +func (e *tikvRegionPeersRetriever) packTiKVRegionPeersRows( + regionsInfo []helper.RegionInfo, storeMap map[int64]struct{}) ([][]types.Datum, error) { + var rows [][]types.Datum + for _, region := range regionsInfo { + records := make([][]types.Datum, 0, len(region.Peers)) + pendingPeerIDSet := set.NewInt64Set() + for _, peer := range region.PendingPeers { + pendingPeerIDSet.Insert(peer.ID) + } + downPeerMap := make(map[int64]int64, len(region.DownPeers)) + for _, peerStat := range region.DownPeers { + downPeerMap[peerStat.Peer.ID] = peerStat.DownSec + } + for _, peer := range region.Peers { + // isUnexpectedStoreID return true if we should filter this peer. + if e.isUnexpectedStoreID(peer.StoreID, storeMap) { + continue + } + + row := make([]types.Datum, len(infoschema.TableTiKVRegionPeersCols)) + row[0].SetInt64(region.ID) + row[1].SetInt64(peer.ID) + row[2].SetInt64(peer.StoreID) + if peer.IsLearner { + row[3].SetInt64(1) + } else { + row[3].SetInt64(0) + } + if peer.ID == region.Leader.ID { + row[4].SetInt64(1) + } else { + row[4].SetInt64(0) + } + if downSec, ok := downPeerMap[peer.ID]; ok { + row[5].SetString(downPeer, mysql.DefaultCollationName) + row[6].SetInt64(downSec) + } else if pendingPeerIDSet.Exist(peer.ID) { + row[5].SetString(pendingPeer, mysql.DefaultCollationName) + } else { + row[5].SetString(normalPeer, mysql.DefaultCollationName) + } + records = append(records, row) + } + rows = append(rows, records...) } - return row, nil + return rows, nil } diff --git a/executor/memtable_reader_test.go b/executor/memtable_reader_test.go index 9fa51faaa3737..bddc06560cdf0 100644 --- a/executor/memtable_reader_test.go +++ b/executor/memtable_reader_test.go @@ -16,71 +16,43 @@ package executor_test import ( "context" - "crypto/tls" - "encoding/json" "fmt" - "io" - "log" - "net" - "net/http" "net/http/httptest" "os" "path/filepath" "strings" "sync/atomic" + "testing" "time" "github.com/gorilla/mux" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/fn" - "github.com/pingcap/kvproto/pkg/diagnosticspb" "github.com/pingcap/sysutil" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/pdapi" - "github.com/pingcap/tidb/util/testkit" pmodel "github.com/prometheus/common/model" + "github.com/stretchr/testify/require" "google.golang.org/grpc" ) -type testMemTableReaderSuite struct{ *testClusterTableBase } +func TestMetricTableData(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -type testClusterTableBase struct { - store kv.Storage - dom *domain.Domain -} - -func (s *testClusterTableBase) SetUpSuite(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - s.store = store - s.dom = dom -} - -func (s *testClusterTableBase) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *testMemTableReaderSuite) TestMetricTableData(c *C) { fpName := "github.com/pingcap/tidb/executor/mockMetricsPromData" - c.Assert(failpoint.Enable(fpName, "return"), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, "return")) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() // mock prometheus data matrix := pmodel.Matrix{} metric := map[pmodel.LabelName]pmodel.LabelValue{ "instance": "127.0.0.1:10080", } - t, err := time.ParseInLocation("2006-01-02 15:04:05.999", "2019-12-23 20:11:35", time.Local) - c.Assert(err, IsNil) + tt, err := time.ParseInLocation("2006-01-02 15:04:05.999", "2019-12-23 20:11:35", time.Local) + require.NoError(t, err) v1 := pmodel.SamplePair{ - Timestamp: pmodel.Time(t.UnixNano() / int64(time.Millisecond)), + Timestamp: pmodel.Time(tt.UnixNano() / int64(time.Millisecond)), Value: pmodel.SampleValue(0.1), } matrix = append(matrix, &pmodel.SampleStream{Metric: metric, Values: []pmodel.SamplePair{v1}}) @@ -90,7 +62,7 @@ func (s *testMemTableReaderSuite) TestMetricTableData(c *C) { return fpname == fpName }) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use metrics_schema") cases := []struct { @@ -119,14 +91,17 @@ func (s *testMemTableReaderSuite) TestMetricTableData(c *C) { } for _, cas := range cases { - rs, err := tk.Se.Execute(ctx, cas.sql) - c.Assert(err, IsNil) - result := tk.ResultSetToResultWithCtx(ctx, rs[0], Commentf("sql: %s", cas.sql)) + rs, err := tk.Session().Execute(ctx, cas.sql) + require.NoError(t, err) + result := tk.ResultSetToResultWithCtx(ctx, rs[0], fmt.Sprintf("sql: %s", cas.sql)) result.Check(testkit.Rows(cas.exp...)) } } -func (s *testMemTableReaderSuite) TestTiDBClusterConfig(c *C) { +func TestTiDBClusterConfig(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + // mock PD http server router := mux.NewRouter() @@ -176,7 +151,7 @@ func (s *testMemTableReaderSuite) TestTiDBClusterConfig(c *C) { router.Handle("/config", fn.Wrap(mockConfig)) // mock servers - servers := []string{} + var servers []string for _, typ := range []string{"tidb", "tikv", "tiflash", "pd"} { for _, server := range testServers { servers = append(servers, strings.Join([]string{typ, server.address, server.address}, ",")) @@ -185,10 +160,10 @@ func (s *testMemTableReaderSuite) TestTiDBClusterConfig(c *C) { fpName := "github.com/pingcap/tidb/executor/mockClusterConfigServerInfo" fpExpr := strings.Join(servers, ";") - c.Assert(failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr)), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr))) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustQuery("select type, `key`, value from information_schema.cluster_config").Check(testkit.Rows( "tidb key1 value1", "tidb key2.nest1 n-value1", @@ -227,17 +202,17 @@ func (s *testMemTableReaderSuite) TestTiDBClusterConfig(c *C) { "pd key2.nest1 n-value1", "pd key2.nest2 n-value2", )) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, 0, Commentf("unexpected warnigns: %+v", warnings)) - c.Assert(requestCounter, Equals, int32(12)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warnings, 0, fmt.Sprintf("unexpected warnigns: %+v", warnings)) + require.Equal(t, int32(12), requestCounter) // TODO: we need remove it when index usage is GA. rs := tk.MustQuery("show config").Rows() for _, r := range rs { s, ok := r[2].(string) - c.Assert(ok, IsTrue) - c.Assert(strings.Contains(s, "index-usage-sync-lease"), IsFalse) - c.Assert(strings.Contains(s, "INDEX-USAGE-SYNC-LEASE"), IsFalse) + require.True(t, ok) + require.NotContains(t, s, "index-usage-sync-lease") + require.NotContains(t, s, "INDEX-USAGE-SYNC-LEASE") } // type => server index => row @@ -445,15 +420,15 @@ func (s *testMemTableReaderSuite) TestTiDBClusterConfig(c *C) { // reset the request counter requestCounter = 0 tk.MustQuery(ca.sql).Check(testkit.Rows(ca.rows...)) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, 0, Commentf("unexpected warnigns: %+v", warnings)) - c.Assert(requestCounter, Equals, ca.reqCount, Commentf("SQL: %s", ca.sql)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warnings, 0, fmt.Sprintf("unexpected warnigns: %+v", warnings)) + require.Equal(t, ca.reqCount, requestCounter, fmt.Sprintf("SQL: %s", ca.sql)) } } -func (s *testClusterTableBase) writeTmpFile(c *C, dir, filename string, lines []string) { +func writeTmpFile(t *testing.T, dir, filename string, lines []string) { err := os.WriteFile(filepath.Join(dir, filename), []byte(strings.Join(lines, "\n")), os.ModePerm) - c.Assert(err, IsNil, Commentf("write tmp file %s failed", filename)) + require.NoError(t, err, fmt.Sprintf("write tmp file %s failed", filename)) } type testServer struct { @@ -464,72 +439,39 @@ type testServer struct { logFile string } -func (s *testClusterTableBase) setupClusterGRPCServer(c *C) map[string]*testServer { - // tp => testServer - testServers := map[string]*testServer{} - - // create gRPC servers - for _, typ := range []string{"tidb", "tikv", "pd"} { - tmpDir, err := os.MkdirTemp("", typ) - c.Assert(err, IsNil) - - server := grpc.NewServer() - logFile := filepath.Join(tmpDir, fmt.Sprintf("%s.log", typ)) - diagnosticspb.RegisterDiagnosticsServer(server, sysutil.NewDiagnosticsServer(logFile)) - - // Find a available port - listener, err := net.Listen("tcp", "127.0.0.1:0") - c.Assert(err, IsNil, Commentf("cannot find available port")) - - testServers[typ] = &testServer{ - typ: typ, - server: server, - address: fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), - tmpDir: tmpDir, - logFile: logFile, - } - go func() { - if err := server.Serve(listener); err != nil { - log.Fatalf("failed to serve: %v", err) - } - }() - } - return testServers -} - -func (s *testMemTableReaderSuite) TestTiDBClusterLog(c *C) { - testServers := s.setupClusterGRPCServer(c) +func TestTiDBClusterLog(t *testing.T) { + testServers := createClusterGRPCServer(t) defer func() { for _, s := range testServers { s.server.Stop() - c.Assert(os.RemoveAll(s.tmpDir), IsNil, Commentf("remove tmpDir %v failed", s.tmpDir)) + require.NoError(t, os.RemoveAll(s.tmpDir), fmt.Sprintf("remove tmpDir %v failed", s.tmpDir)) } }() // time format of log file var logtime = func(s string) string { - t, err := time.ParseInLocation("2006/01/02 15:04:05.000", s, time.Local) - c.Assert(err, IsNil) - return t.Format("[2006/01/02 15:04:05.000 -07:00]") + tt, err := time.ParseInLocation("2006/01/02 15:04:05.000", s, time.Local) + require.NoError(t, err) + return tt.Format("[2006/01/02 15:04:05.000 -07:00]") } // time format of query output var restime = func(s string) string { - t, err := time.ParseInLocation("2006/01/02 15:04:05.000", s, time.Local) - c.Assert(err, IsNil) - return t.Format("2006/01/02 15:04:05.000") + tt, err := time.ParseInLocation("2006/01/02 15:04:05.000", s, time.Local) + require.NoError(t, err) + return tt.Format("2006/01/02 15:04:05.000") } // prepare log files // TiDB - s.writeTmpFile(c, testServers["tidb"].tmpDir, "tidb.log", []string{ + writeTmpFile(t, testServers["tidb"].tmpDir, "tidb.log", []string{ logtime(`2019/08/26 06:19:13.011`) + ` [INFO] [test log message tidb 1, foo]`, logtime(`2019/08/26 06:19:14.011`) + ` [DEBUG] [test log message tidb 2, foo]`, logtime(`2019/08/26 06:19:15.011`) + ` [error] [test log message tidb 3, foo]`, logtime(`2019/08/26 06:19:16.011`) + ` [trace] [test log message tidb 4, foo]`, logtime(`2019/08/26 06:19:17.011`) + ` [CRITICAL] [test log message tidb 5, foo]`, }) - s.writeTmpFile(c, testServers["tidb"].tmpDir, "tidb-1.log", []string{ + writeTmpFile(t, testServers["tidb"].tmpDir, "tidb-1.log", []string{ logtime(`2019/08/26 06:25:13.011`) + ` [info] [test log message tidb 10, bar]`, logtime(`2019/08/26 06:25:14.011`) + ` [debug] [test log message tidb 11, bar]`, logtime(`2019/08/26 06:25:15.011`) + ` [ERROR] [test log message tidb 12, bar]`, @@ -538,14 +480,14 @@ func (s *testMemTableReaderSuite) TestTiDBClusterLog(c *C) { }) // TiKV - s.writeTmpFile(c, testServers["tikv"].tmpDir, "tikv.log", []string{ + writeTmpFile(t, testServers["tikv"].tmpDir, "tikv.log", []string{ logtime(`2019/08/26 06:19:13.011`) + ` [INFO] [test log message tikv 1, foo]`, logtime(`2019/08/26 06:20:14.011`) + ` [DEBUG] [test log message tikv 2, foo]`, logtime(`2019/08/26 06:21:15.011`) + ` [error] [test log message tikv 3, foo]`, logtime(`2019/08/26 06:22:16.011`) + ` [trace] [test log message tikv 4, foo]`, logtime(`2019/08/26 06:23:17.011`) + ` [CRITICAL] [test log message tikv 5, foo]`, }) - s.writeTmpFile(c, testServers["tikv"].tmpDir, "tikv-1.log", []string{ + writeTmpFile(t, testServers["tikv"].tmpDir, "tikv-1.log", []string{ logtime(`2019/08/26 06:24:15.011`) + ` [info] [test log message tikv 10, bar]`, logtime(`2019/08/26 06:25:16.011`) + ` [debug] [test log message tikv 11, bar]`, logtime(`2019/08/26 06:26:17.011`) + ` [ERROR] [test log message tikv 12, bar]`, @@ -554,14 +496,14 @@ func (s *testMemTableReaderSuite) TestTiDBClusterLog(c *C) { }) // PD - s.writeTmpFile(c, testServers["pd"].tmpDir, "pd.log", []string{ + writeTmpFile(t, testServers["pd"].tmpDir, "pd.log", []string{ logtime(`2019/08/26 06:18:13.011`) + ` [INFO] [test log message pd 1, foo]`, logtime(`2019/08/26 06:19:14.011`) + ` [DEBUG] [test log message pd 2, foo]`, logtime(`2019/08/26 06:20:15.011`) + ` [error] [test log message pd 3, foo]`, logtime(`2019/08/26 06:21:16.011`) + ` [trace] [test log message pd 4, foo]`, logtime(`2019/08/26 06:22:17.011`) + ` [CRITICAL] [test log message pd 5, foo]`, }) - s.writeTmpFile(c, testServers["pd"].tmpDir, "pd-1.log", []string{ + writeTmpFile(t, testServers["pd"].tmpDir, "pd-1.log", []string{ logtime(`2019/08/26 06:23:13.011`) + ` [info] [test log message pd 10, bar]`, logtime(`2019/08/26 06:24:14.011`) + ` [debug] [test log message pd 11, bar]`, logtime(`2019/08/26 06:25:15.011`) + ` [ERROR] [test log message pd 12, bar]`, @@ -906,18 +848,20 @@ func (s *testMemTableReaderSuite) TestTiDBClusterLog(c *C) { } fpName := "github.com/pingcap/tidb/executor/mockClusterLogServerInfo" fpExpr := strings.Join(servers, ";") - c.Assert(failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr)), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr))) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) for _, cas := range cases { sql := "select * from information_schema.cluster_log" if len(cas.conditions) > 0 { sql = fmt.Sprintf("%s where %s", sql, strings.Join(cas.conditions, " and ")) } result := tk.MustQuery(sql) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, 0, Commentf("unexpected warnigns: %+v", warnings)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warnings, 0, fmt.Sprintf("unexpected warnigns: %+v", warnings)) var expected []string for _, row := range cas.expected { expectedRow := []string{ @@ -933,471 +877,23 @@ func (s *testMemTableReaderSuite) TestTiDBClusterLog(c *C) { } } -func (s *testMemTableReaderSuite) TestTiDBClusterLogError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTiDBClusterLogError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) fpName := "github.com/pingcap/tidb/executor/mockClusterLogServerInfo" - c.Assert(failpoint.Enable(fpName, `return("")`), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() + require.NoError(t, failpoint.Enable(fpName, `return("")`)) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() // Test without start time error. - rs, err := tk.Exec("select * from information_schema.cluster_log") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "denied to scan logs, please specified the start time, such as `time > '2020-01-01 00:00:00'`") - c.Assert(rs.Close(), IsNil) + err := tk.QueryToErr("select * from information_schema.cluster_log") + require.EqualError(t, err, "denied to scan logs, please specified the start time, such as `time > '2020-01-01 00:00:00'`") // Test without end time error. - rs, err = tk.Exec("select * from information_schema.cluster_log where time>='2019/08/26 06:18:13.011'") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "denied to scan logs, please specified the end time, such as `time < '2020-01-01 00:00:00'`") - c.Assert(rs.Close(), IsNil) + err = tk.QueryToErr("select * from information_schema.cluster_log where time>='2019/08/26 06:18:13.011'") + require.EqualError(t, err, "denied to scan logs, please specified the end time, such as `time < '2020-01-01 00:00:00'`") // Test without specified message error. - rs, err = tk.Exec("select * from information_schema.cluster_log where time>='2019/08/26 06:18:13.011' and time<'2019/08/26 16:18:13.011'") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "denied to scan full logs (use `SELECT * FROM cluster_log WHERE message LIKE '%'` explicitly if intentionally)") - c.Assert(rs.Close(), IsNil) -} - -type mockStoreWithMultiPD struct { - helper.Storage - hosts []string -} - -var hotRegionsResponses = make(map[string]*executor.HistoryHotRegions, 3) - -func (s *mockStoreWithMultiPD) EtcdAddrs() ([]string, error) { return s.hosts, nil } -func (s *mockStoreWithMultiPD) TLSConfig() *tls.Config { panic("not implemented") } -func (s *mockStoreWithMultiPD) StartGCWorker() error { panic("not implemented") } -func (s *mockStoreWithMultiPD) Name() string { return "mockStore" } -func (s *mockStoreWithMultiPD) Describe() string { return "" } - -var _ = SerialSuites(&testHotRegionsHistoryTableSuite{testInfoschemaTableSuiteBase: &testInfoschemaTableSuiteBase{}}) - -type testHotRegionsHistoryTableSuite struct { - *testInfoschemaTableSuiteBase - httpServers []*httptest.Server - startTime time.Time -} - -func (s *testHotRegionsHistoryTableSuite) SetUpSuite(c *C) { - s.testInfoschemaTableSuiteBase.SetUpSuite(c) - store := &mockStoreWithMultiPD{ - s.store.(helper.Storage), - make([]string, 3), - } - // start 3 PD server with hotRegionsServer and store them in s.store - for i := 0; i < 3; i++ { - httpServer, mockAddr := s.setUpMockPDHTTPServer(c) - c.Assert(httpServer, NotNil) - s.httpServers = append(s.httpServers, httpServer) - store.hosts[i] = mockAddr - } - s.store = store - s.startTime = time.Now() -} - -func writeJSONError(w http.ResponseWriter, code int, prefix string, err error) { - type errorResponse struct { - Error string `json:"error"` - } - w.WriteHeader(code) - if err != nil { - prefix += ": " + err.Error() - } - _ = json.NewEncoder(w).Encode(errorResponse{Error: prefix}) -} - -func hisHotRegionsHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - data, err := io.ReadAll(r.Body) - if err != nil { - writeJSONError(w, http.StatusInternalServerError, "unable to read req", err) - return - } - r.Body.Close() - req := &executor.HistoryHotRegionsRequest{} - err = json.Unmarshal(data, req) - if err != nil { - writeJSONError(w, http.StatusInternalServerError, "unable to serialize req", err) - return - } - resp := &executor.HistoryHotRegions{} - for _, typ := range req.HotRegionTypes { - resp.HistoryHotRegion = append(resp.HistoryHotRegion, hotRegionsResponses[typ+r.Host].HistoryHotRegion...) - } - w.WriteHeader(http.StatusOK) - jsonResp, err := json.Marshal(resp) - if err != nil { - writeJSONError(w, http.StatusInternalServerError, "unable to marshal resp", err) - return - } - w.Write(jsonResp) -} - -func (s *testHotRegionsHistoryTableSuite) setUpMockPDHTTPServer(c *C) (*httptest.Server, string) { - // mock PD http server - router := mux.NewRouter() - server := httptest.NewServer(router) - mockAddr := strings.TrimPrefix(server.URL, "http://") - // mock PD API - router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { - return struct { - Version string `json:"version"` - GitHash string `json:"git_hash"` - StartTimestamp int64 `json:"start_timestamp"` - }{ - Version: "4.0.0-alpha", - GitHash: "mock-pd-githash", - StartTimestamp: s.startTime.Unix(), - }, nil - })) - // mock hisory hot regions response - router.HandleFunc(pdapi.HotHistory, hisHotRegionsHandler) - return server, mockAddr -} - -func (s *testHotRegionsHistoryTableSuite) TearDownSuite(c *C) { - for _, server := range s.httpServers { - server.Close() - } - s.testInfoschemaTableSuiteBase.TearDownSuite(c) -} - -func (s *testHotRegionsHistoryTableSuite) TestTiDBHotRegionsHistory(c *C) { - var unixTimeMs = func(s string) int64 { - t, err := time.ParseInLocation("2006-01-02 15:04:05", s, time.Local) - c.Assert(err, IsNil) - return t.UnixNano() / int64(time.Millisecond) - } - fullHotRegions := [][]string{ - // mysql table_id = 11, record_id = 1, table_name = TABLES_PRIV - {"2019-10-10 10:10:11", "MYSQL", "TABLES_PRIV", "11", "", "", "1", "1", "11111", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:12", "MYSQL", "TABLES_PRIV", "11", "", "", "2", "2", "22222", "0", "0", "WRITE", "99", "99", "99", "99"}, - // mysql table_id = 21, record_id = 1, table_name = STATS_META - {"2019-10-10 10:10:13", "MYSQL", "STATS_META", "21", "", "", "3", "3", "33333", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:14", "MYSQL", "STATS_META", "21", "", "", "4", "4", "44444", "0", "0", "WRITE", "99", "99", "99", "99"}, - // table_id = 131, record_id=1, deleted schema - {"2019-10-10 10:10:15", "UNKONW", "UNKONW", "131", "UNKONW", "", "5", "5", "55555", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:16", "UNKONW", "UNKONW", "131", "UNKONW", "", "6", "6", "66666", "0", "0", "WRITE", "99", "99", "99", "99"}, - // mysql table_id = 11, index_id = 1, index_value = 1, table_name = TABLES_PRIV, index_name = PRIMARY - {"2019-10-10 10:10:17", "MYSQL", "TABLES_PRIV", "11", "PRIMARY", "1", "1", "1", "11111", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:18", "MYSQL", "TABLES_PRIV", "11", "PRIMARY", "1", "2", "2", "22222", "0", "0", "WRITE", "99", "99", "99", "99"}, - // mysql table_id = 21 ,index_id = 1, index_value = 1, table_name = STATS_META, index_name = IDX_VER - {"2019-10-10 10:10:19", "MYSQL", "STATS_META", "21", "IDX_VER", "1", "3", "3", "33333", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:20", "MYSQL", "STATS_META", "21", "IDX_VER", "1", "4", "4", "44444", "0", "0", "WRITE", "99", "99", "99", "99"}, - // mysql table_id = 21 ,index_id = 2, index_value = 1, table_name = STATS_META, index_name = TBL - {"2019-10-10 10:10:21", "MYSQL", "STATS_META", "21", "TBL", "2", "5", "5", "55555", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:22", "MYSQL", "STATS_META", "21", "TBL", "2", "6", "6", "66666", "0", "0", "WRITE", "99", "99", "99", "99"}, - // table_id = 131, index_id = 1, index_value = 1, deleted schema - {"2019-10-10 10:10:23", "UNKONW", "UNKONW", "131", "UNKONW", "1", "5", "5", "55555", "0", "1", "READ", "99", "99", "99", "99"}, - {"2019-10-10 10:10:24", "UNKONW", "UNKONW", "131", "UNKONW", "1", "6", "6", "66666", "0", "0", "WRITE", "99", "99", "99", "99"}, - } - - pdResps := []map[string]*executor.HistoryHotRegions{ - { - core.HotRegionTypeRead: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // mysql table_id = 11, record_id = 1, table_name = TABLES_PRIV - {UpdateTime: unixTimeMs("2019-10-10 10:10:11"), RegionID: 1, StoreID: 1, PeerID: 11111, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 21, record_id = 1, table_name = STATS_META - {UpdateTime: unixTimeMs("2019-10-10 10:10:13"), RegionID: 3, StoreID: 3, PeerID: 33333, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - core.HotRegionTypeWrite: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // mysql table_id = 11, record_id = 1, table_name = TABLES_PRIV - {UpdateTime: unixTimeMs("2019-10-10 10:10:12"), RegionID: 2, StoreID: 2, PeerID: 22222, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 21, record_id = 1, table_name = STATS_META - {UpdateTime: unixTimeMs("2019-10-10 10:10:14"), RegionID: 4, StoreID: 4, PeerID: 44444, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - }, - { - core.HotRegionTypeRead: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // table_id = 131, record_id=1, deleted schema - {UpdateTime: unixTimeMs("2019-10-10 10:10:15"), RegionID: 5, StoreID: 5, PeerID: 55555, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 11, index_id = 1, index_value = 1, table_name = TABLES_PRIV, index_name = PRIMARY - {UpdateTime: unixTimeMs("2019-10-10 10:10:17"), RegionID: 1, StoreID: 1, PeerID: 11111, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - core.HotRegionTypeWrite: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // table_id = 131, record_id=1, deleted schema - {UpdateTime: unixTimeMs("2019-10-10 10:10:16"), RegionID: 6, StoreID: 6, PeerID: 66666, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x72, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 11, index_id = 1, index_value = 1, table_name = TABLES_PRIV, index_name = PRIMARY - {UpdateTime: unixTimeMs("2019-10-10 10:10:18"), RegionID: 2, StoreID: 2, PeerID: 22222, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - }, - { - core.HotRegionTypeRead: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // mysql table_id = 21 ,index_id = 1, index_value = 1, table_name = STATS_META, index_name = IDX_VER - {UpdateTime: unixTimeMs("2019-10-10 10:10:19"), RegionID: 3, StoreID: 3, PeerID: 33333, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 21 ,index_id = 2, index_value = 1, table_name = STATS_META, index_name = TBL - {UpdateTime: unixTimeMs("2019-10-10 10:10:21"), RegionID: 5, StoreID: 5, PeerID: 55555, IsLearner: false, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // table_id = 131, index_id = 1, index_value = 1, deleted schema - {UpdateTime: unixTimeMs("2019-10-10 10:10:23"), RegionID: 5, StoreID: 5, PeerID: 55555, IsLeader: true, HotRegionType: "READ", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - core.HotRegionTypeWrite: { - HistoryHotRegion: []*executor.HistoryHotRegion{ - // mysql table_id = 21 ,index_id = 1, index_value = 1, table_name = STATS_META, index_name = IDX_VER - {UpdateTime: unixTimeMs("2019-10-10 10:10:20"), RegionID: 4, StoreID: 4, PeerID: 44444, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // mysql table_id = 21 ,index_id = 2, index_value = 1, table_name = STATS_META, index_name = TBL - {UpdateTime: unixTimeMs("2019-10-10 10:10:22"), RegionID: 6, StoreID: 6, PeerID: 66666, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x15, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - // table_id = 131, index_id = 1, index_value = 1, deleted schema - {UpdateTime: unixTimeMs("2019-10-10 10:10:24"), RegionID: 6, StoreID: 6, PeerID: 66666, IsLearner: false, IsLeader: false, HotRegionType: "WRITE", HotDegree: 99, FlowBytes: 99, KeyRate: 99, QueryRate: 99, - StartKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}, - EndKey: []byte{0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x83, 0x5f, 0x69, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfa}}, - }, - }, - }, - } - - var cases = []struct { - conditions []string - reqCount int32 - expected [][]string - }{ - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - }, // time filtered by PD, assume response suit time range, and ignore deleted schemas - expected: [][]string{ - fullHotRegions[0], fullHotRegions[1], fullHotRegions[2], - fullHotRegions[3], - fullHotRegions[6], fullHotRegions[7], fullHotRegions[8], - fullHotRegions[9], fullHotRegions[10], fullHotRegions[11], - }, - }, - { - conditions: []string{ - "update_time>=TIMESTAMP('2019-10-10 10:10:10')", - "update_time<=TIMESTAMP('2019-10-11 10:10:10')", - }, // test support of timestamp - expected: [][]string{ - fullHotRegions[0], fullHotRegions[1], fullHotRegions[2], - fullHotRegions[3], - fullHotRegions[6], fullHotRegions[7], fullHotRegions[8], - fullHotRegions[9], fullHotRegions[10], fullHotRegions[11], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=11", - }, - expected: [][]string{ - fullHotRegions[0], fullHotRegions[1], fullHotRegions[6], fullHotRegions[7], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_name='TABLES_PRIV'", - }, - expected: [][]string{ - fullHotRegions[0], fullHotRegions[1], fullHotRegions[6], fullHotRegions[7], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=21", - "index_id=1", - }, - expected: [][]string{ - fullHotRegions[8], fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=21", - "index_id=1", - "table_name='TABLES_PRIV'", - }, // table_id != table_name -> nil - expected: [][]string{}, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=21", - "index_id=1", - "table_name='STATS_META'", - }, // table_id = table_name - expected: [][]string{ - fullHotRegions[8], fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=21", - "index_id=1", - "index_name='UNKONW'", - }, // index_id != index_name -> nil - expected: [][]string{}, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "table_id=21", - "index_id=1", - "index_name='IDX_VER'", - }, // index_id = index_name - expected: [][]string{ - fullHotRegions[8], fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "index_id=1", - "index_name='IDX_VER'", - "table_id>=21", // unpushed down predicates 21>=21 - }, - expected: [][]string{ - fullHotRegions[8], fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "index_id=1", - "index_name='IDX_VER'", - "table_id>21", // unpushed down predicates - }, // 21!>21 -> nil - expected: [][]string{}, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "index_id=1", - "index_name='IDX_VER'", - "table_id>=21", // unpushed down predicates - "db_name='MYSQL'", - }, - expected: [][]string{ - fullHotRegions[8], fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "index_id=1", - "index_name='IDX_VER'", - "table_id>=21", // unpushed down predicates - "db_name='MYSQL'", - "peer_id>=33334", - }, - expected: [][]string{ - fullHotRegions[9], - }, - }, - { - conditions: []string{ - "update_time>='2019-10-10 10:10:10'", - "update_time<='2019-10-11 10:10:10'", - "index_id=1", - "index_name='IDX_VER'", - "table_id>=21", // unpushed down predicates - "db_name='UNKNOW'", - }, - expected: [][]string{}, - }, - } - - // mock http resp - store := s.store.(*mockStoreWithMultiPD) - for i, resp := range pdResps { - for k, v := range resp { - hotRegionsResponses[k+store.hosts[i]] = v - } - } - tk := testkit.NewTestKit(c, s.store) - for _, cas := range cases { - sql := "select * from information_schema.tidb_hot_regions_history" - if len(cas.conditions) > 0 { - sql = fmt.Sprintf("%s where %s", sql, strings.Join(cas.conditions, " and ")) - } - result := tk.MustQuery(sql) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, 0, Commentf("unexpected warnigns: %+v, sql: %s", warnings, sql)) - var expected []string - for _, row := range cas.expected { - expectedRow := row - expected = append(expected, strings.Join(expectedRow, " ")) - } - result.Check(testkit.Rows(expected...)) - } -} - -func (s *testHotRegionsHistoryTableSuite) TestTiDBHotRegionsHistoryError(c *C) { - tk := testkit.NewTestKit(c, s.store) - fpName := "github.com/pingcap/tidb/executor/mockTiDBHotRegionsHistory" - c.Assert(failpoint.Enable(fpName, `return("")`), IsNil) - defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() - - // Test without start time error - rs, err := tk.Exec("select * from information_schema.tidb_hot_regions_history") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "denied to scan hot regions, please specified the start time, such as `update_time > '2020-01-01 00:00:00'`") - c.Assert(rs.Close(), IsNil) - - // Test without end time error. - rs, err = tk.Exec("select * from information_schema.tidb_hot_regions_history where update_time>='2019/08/26 06:18:13.011'") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, rs) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "denied to scan hot regions, please specified the end time, such as `update_time < '2020-01-01 00:00:00'`") - c.Assert(rs.Close(), IsNil) + err = tk.QueryToErr("select * from information_schema.cluster_log where time>='2019/08/26 06:18:13.011' and time<'2019/08/26 16:18:13.011'") + require.EqualError(t, err, "denied to scan full logs (use `SELECT * FROM cluster_log WHERE message LIKE '%'` explicitly if intentionally)") } diff --git a/executor/merge_join_test.go b/executor/merge_join_test.go index 4d616513963e4..9d62becef77b9 100644 --- a/executor/merge_join_test.go +++ b/executor/merge_join_test.go @@ -19,14 +19,14 @@ import ( "fmt" "math/rand" "strconv" - "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) const plan1 = `[[TableScan_12 { @@ -221,47 +221,43 @@ const plan3 = `[[TableScan_12 { "desc": "false" } ]]` -func checkMergeAndRun(tk *testkit.TestKit, c *C, sql string) *testkit.Result { +func checkMergeAndRun(tk *testkit.TestKit, t *testing.T, sql string) *testkit.Result { explainedSQL := "explain format = 'brief' " + sql result := tk.MustQuery(explainedSQL) resultStr := fmt.Sprintf("%v", result.Rows()) - if !strings.ContainsAny(resultStr, "MergeJoin") { - c.Error("Expected MergeJoin in plan.") - } + require.Contains(t, resultStr, "MergeJoin") return tk.MustQuery(sql) } -func checkPlanAndRun(tk *testkit.TestKit, c *C, plan string, sql string) *testkit.Result { +func checkPlanAndRun(tk *testkit.TestKit, t *testing.T, plan string, sql string) *testkit.Result { explainedSQL := "explain format = 'brief' " + sql - tk.MustQuery(explainedSQL) - + /* result := */ tk.MustQuery(explainedSQL) // TODO: Reopen it after refactoring explain. // resultStr := fmt.Sprintf("%v", result.Rows()) - // if plan != resultStr { - // c.Errorf("Plan not match. Obtained:\n %s\nExpected:\n %s\n", resultStr, plan) - // } + // require.Equal(t, resultStr, plan) return tk.MustQuery(sql) } -func (s *testSerialSuite1) TestShuffleMergeJoinInDisk(c *C) { +func TestShuffleMergeJoinInDisk(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true }) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill", "return(true)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill", "return(true)")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill")) }() - - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sm := &mockSessionManager1{ PS: make([]*util.ProcessInfo, 0), } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) tk.MustExec("set @@tidb_mem_quota_query=1;") tk.MustExec("set @@tidb_merge_join_concurrency=4;") @@ -272,34 +268,38 @@ func (s *testSerialSuite1) TestShuffleMergeJoinInDisk(c *C) { tk.MustExec("insert into t values(1,1)") tk.MustExec("insert into t1 values(1,3),(4,4)") - result := checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result := checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows("1 3 1 1")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), Greater, int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.MemTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.DiskTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), int64(0)) } -func (s *testSerialSuite1) TestMergeJoinInDisk(c *C) { - c.Skip("unstable, skip it and fix it before 20210618") - defer config.RestoreFunc()() +func TestMergeJoinInDisk(t *testing.T) { + t.Skip("unstable, skip it and fix it before 20210618") + restore := config.RestoreFunc() + defer restore() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true + conf.OOMAction = config.OOMActionLog + conf.TempStoragePath = t.TempDir() }) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill", "return(true)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill", "return(true)")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testMergeJoinRowContainerSpill")) }() - - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sm := &mockSessionManager1{ PS: make([]*util.ProcessInfo, 0), } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) tk.MustExec("set @@tidb_mem_quota_query=1;") tk.MustExec("drop table if exists t") @@ -309,16 +309,18 @@ func (s *testSerialSuite1) TestMergeJoinInDisk(c *C) { tk.MustExec("insert into t values(1,1)") tk.MustExec("insert into t1 values(1,3),(4,4)") - result := checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result := checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows("1 3 1 1")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), Greater, int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.MemTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.DiskTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), int64(0)) } -func (s *testSuite2) TestMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -328,15 +330,15 @@ func (s *testSuite2) TestMergeJoin(c *C) { tk.MustExec("insert into t values(1,1),(2,2)") tk.MustExec("insert into t1 values(2,3),(4,4)") - result := checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result := checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows("1 1 ")) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows(" 1 1")) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows()) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false") result.Check(testkit.Rows()) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1") result.Check(testkit.Rows("1 1 ", "2 2 2 3")) tk.MustExec("drop table if exists t1") @@ -477,8 +479,10 @@ func (s *testSuite2) TestMergeJoin(c *C) { "4", "3", "2", "1")) } -func (s *testSuite2) TestShuffleMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShuffleMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@session.tidb_merge_join_concurrency = 4;") @@ -489,15 +493,15 @@ func (s *testSuite2) TestShuffleMergeJoin(c *C) { tk.MustExec("insert into t values(1,1),(2,2)") tk.MustExec("insert into t1 values(2,3),(4,4)") - result := checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result := checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows("1 1 ")) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows(" 1 1")) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") result.Check(testkit.Rows()) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false") result.Check(testkit.Rows()) - result = checkMergeAndRun(tk, c, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1") + result = checkMergeAndRun(tk, t, "select /*+ TIDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1") result.Check(testkit.Rows("1 1 ", "2 2 2 3")) tk.MustExec("drop table if exists t1") @@ -638,8 +642,10 @@ func (s *testSuite2) TestShuffleMergeJoin(c *C) { "4", "3", "2", "1")) } -func (s *testSuite2) Test3WaysMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func Test3WaysMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") @@ -651,20 +657,22 @@ func (s *testSuite2) Test3WaysMergeJoin(c *C) { tk.MustExec("insert into t1 values(1,1),(2,2),(3,3)") tk.MustExec("insert into t2 values(2,3),(3,4),(4,5)") tk.MustExec("insert into t3 values(1,2),(2,4),(3,10)") - result := checkPlanAndRun(tk, c, plan1, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") + result := checkPlanAndRun(tk, t, plan1, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) - result = checkPlanAndRun(tk, c, plan2, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") + result = checkPlanAndRun(tk, t, plan2, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) // In below case, t1 side filled with null when no matched join, so that order is not kept and sort appended // On the other hand, t1 order kept so no final sort appended - result = checkPlanAndRun(tk, c, plan3, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1") + result = checkPlanAndRun(tk, t, plan3, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) } -func (s *testSuite2) Test3WaysShuffleMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func Test3WaysShuffleMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@session.tidb_merge_join_concurrency = 4;") @@ -677,20 +685,22 @@ func (s *testSuite2) Test3WaysShuffleMergeJoin(c *C) { tk.MustExec("insert into t1 values(1,1),(2,2),(3,3)") tk.MustExec("insert into t2 values(2,3),(3,4),(4,5)") tk.MustExec("insert into t3 values(1,2),(2,4),(3,10)") - result := checkPlanAndRun(tk, c, plan1, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") + result := checkPlanAndRun(tk, t, plan1, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) - result = checkPlanAndRun(tk, c, plan2, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") + result = checkPlanAndRun(tk, t, plan2, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) // In below case, t1 side filled with null when no matched join, so that order is not kept and sort appended // On the other hand, t1 order kept so no final sort appended - result = checkPlanAndRun(tk, c, plan3, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1") + result = checkPlanAndRun(tk, t, plan3, "select /*+ TIDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1") result.Check(testkit.Rows("2 2 2 3 2 4", "3 3 3 4 3 10")) } -func (s *testSuite2) TestMergeJoinDifferentTypes(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMergeJoinDifferentTypes(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_executor_concurrency = 4;") tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;") tk.MustExec("set @@session.tidb_distsql_scan_concurrency = 15;") @@ -728,8 +738,10 @@ func (s *testSuite2) TestMergeJoinDifferentTypes(c *C) { // TestVectorizedMergeJoin is used to test vectorized merge join with some corner cases. //nolint:gosimple // generates false positive fmt.Sprintf warnings which keep aligned -func (s *testSuiteJoin3) TestVectorizedMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestVectorizedMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") existTableMap := make(map[string]struct{}) runTest := func(ts1, ts2 []int) { @@ -797,21 +809,21 @@ func (s *testSuiteJoin3) TestVectorizedMergeJoin(c *C) { r2 := tk.MustQuery(fmt.Sprintf("select /*+ TIDB_HJ(%s, %s) */ * from %s, %s where %s.a=%s.a and %s.b>5 and %s.b<5", t1, t2, t1, t2, t1, t2, t1, t2, )).Sort() - c.Assert(len(r1.Rows()), Equals, len(r2.Rows())) + require.Equal(t, len(r2.Rows()), len(r1.Rows())) i := 0 n := len(r1.Rows()) for i < n { - c.Assert(len(r1.Rows()[i]), Equals, len(r2.Rows()[i])) + require.Equal(t, len(r2.Rows()[i]), len(r1.Rows()[i])) for j := range r1.Rows()[i] { - c.Assert(r1.Rows()[i][j], Equals, r2.Rows()[i][j]) + require.Equal(t, r2.Rows()[i][j], r1.Rows()[i][j]) } i += rand.Intn((n-i)/5+1) + 1 // just compare parts of results to speed up } } - tk.Se.GetSessionVars().MaxChunkSize = variable.DefInitChunkSize - chunkSize := tk.Se.GetSessionVars().MaxChunkSize + tk.Session().GetSessionVars().MaxChunkSize = variable.DefInitChunkSize + chunkSize := tk.Session().GetSessionVars().MaxChunkSize cases := []struct { t1 []int t2 []int @@ -844,8 +856,10 @@ func (s *testSuiteJoin3) TestVectorizedMergeJoin(c *C) { // TestVectorizedShuffleMergeJoin is used to test vectorized shuffle merge join with some corner cases. //nolint:gosimple // generates false positive fmt.Sprintf warnings which keep aligned -func (s *testSuiteJoin3) TestVectorizedShuffleMergeJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestVectorizedShuffleMergeJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_merge_join_concurrency = 4;") tk.MustExec("use test") existTableMap := make(map[string]struct{}) @@ -915,21 +929,21 @@ func (s *testSuiteJoin3) TestVectorizedShuffleMergeJoin(c *C) { r2 := tk.MustQuery(fmt.Sprintf("select /*+ TIDB_HJ(%s, %s) */ * from %s, %s where %s.a=%s.a and %s.b>5 and %s.b<5", t1, t2, t1, t2, t1, t2, t1, t2, )).Sort() - c.Assert(len(r1.Rows()), Equals, len(r2.Rows())) + require.Equal(t, len(r2.Rows()), len(r1.Rows())) i := 0 n := len(r1.Rows()) for i < n { - c.Assert(len(r1.Rows()[i]), Equals, len(r2.Rows()[i])) + require.Equal(t, len(r2.Rows()[i]), len(r1.Rows()[i])) for j := range r1.Rows()[i] { - c.Assert(r1.Rows()[i][j], Equals, r2.Rows()[i][j]) + require.Equal(t, r2.Rows()[i][j], r1.Rows()[i][j]) } i += rand.Intn((n-i)/5+1) + 1 // just compare parts of results to speed up } } - tk.Se.GetSessionVars().MaxChunkSize = variable.DefInitChunkSize - chunkSize := tk.Se.GetSessionVars().MaxChunkSize + tk.Session().GetSessionVars().MaxChunkSize = variable.DefInitChunkSize + chunkSize := tk.Session().GetSessionVars().MaxChunkSize cases := []struct { t1 []int t2 []int @@ -956,9 +970,11 @@ func (s *testSuiteJoin3) TestVectorizedShuffleMergeJoin(c *C) { } } -func (s *testSuite2) TestMergeJoinWithOtherConditions(c *C) { +func TestMergeJoinWithOtherConditions(t *testing.T) { // more than one inner tuple should be filtered on other conditions - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists R;`) tk.MustExec(`drop table if exists Y;`) @@ -973,9 +989,11 @@ func (s *testSuite2) TestMergeJoinWithOtherConditions(c *C) { )) } -func (s *testSuite2) TestShuffleMergeJoinWithOtherConditions(c *C) { +func TestShuffleMergeJoinWithOtherConditions(t *testing.T) { // more than one inner tuple should be filtered on other conditions - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec("set @@session.tidb_merge_join_concurrency = 4;") tk.MustExec(`drop table if exists R;`) diff --git a/executor/metrics_reader.go b/executor/metrics_reader.go index d6df64dc7a377..3e90897d03192 100644 --- a/executor/metrics_reader.go +++ b/executor/metrics_reader.go @@ -233,11 +233,7 @@ func (e *MetricsSummaryRetriever) retrieve(ctx context.Context, sctx sessionctx. } exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, sql) - if err != nil { - return nil, errors.Errorf("execute '%s' failed: %v", sql, err) - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql) if err != nil { return nil, errors.Errorf("execute '%s' failed: %v", sql, err) } @@ -318,11 +314,7 @@ func (e *MetricsSummaryByLabelRetriever) retrieve(ctx context.Context, sctx sess util.MetricSchemaName.L, name, cond) } exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, sql) - if err != nil { - return nil, errors.Errorf("execute '%s' failed: %v", sql, err) - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, sql) if err != nil { return nil, errors.Errorf("execute '%s' failed: %v", sql, err) } diff --git a/executor/metrics_reader_test.go b/executor/metrics_reader_test.go index bdd6a2bfc8418..46b2bb92666dd 100644 --- a/executor/metrics_reader_test.go +++ b/executor/metrics_reader_test.go @@ -17,17 +17,20 @@ package executor_test import ( "context" "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/planner" plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite7) TestStmtLabel(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStmtLabel(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table label (c1 int primary key, c2 int, c3 int, index (c2))") for i := 0; i < 10; i++ { @@ -60,13 +63,12 @@ func (s *testSuite7) TestStmtLabel(c *C) { } for _, tt := range tests { stmtNode, err := parser.New().ParseOneStmt(tt.sql, "", "") - c.Check(err, IsNil) + require.NoError(t, err) preprocessorReturn := &plannercore.PreprocessorReturn{} - err = plannercore.Preprocess(tk.Se, stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) - c.Check(err, IsNil) - c.Assert(err, IsNil) - _, _, err = planner.Optimize(context.TODO(), tk.Se, stmtNode, preprocessorReturn.InfoSchema) - c.Assert(err, IsNil) - c.Assert(executor.GetStmtLabel(stmtNode), Equals, tt.label) + err = plannercore.Preprocess(tk.Session(), stmtNode, plannercore.WithPreprocessorReturn(preprocessorReturn)) + require.NoError(t, err) + _, _, err = planner.Optimize(context.TODO(), tk.Session(), stmtNode, preprocessorReturn.InfoSchema) + require.NoError(t, err) + require.Equal(t, tt.label, executor.GetStmtLabel(stmtNode)) } } diff --git a/executor/mpp_gather.go b/executor/mpp_gather.go index e64ae56407ae6..3a8ce366742b6 100644 --- a/executor/mpp_gather.go +++ b/executor/mpp_gather.go @@ -65,7 +65,11 @@ func (e *MPPGather) appendMPPDispatchReq(pf *plannercore.Fragment) error { dagReq.EncodeType = tipb.EncodeType_TypeChunk } for _, mppTask := range pf.ExchangeSender.Tasks { - err := updateExecutorTableID(context.Background(), dagReq.RootExecutor, mppTask.TableID, true) + if mppTask.PartitionTableIDs != nil { + err = updateExecutorTableID(context.Background(), dagReq.RootExecutor, true, mppTask.PartitionTableIDs) + } else { + err = updateExecutorTableID(context.Background(), dagReq.RootExecutor, true, []int64{mppTask.TableID}) + } if err != nil { return errors.Trace(err) } @@ -118,7 +122,7 @@ func (e *MPPGather) Open(ctx context.Context) (err error) { failpoint.Return(errors.Errorf("The number of tasks is not right, expect %d tasks but actually there are %d tasks", val.(int), len(e.mppReqs))) } }) - e.respIter, err = distsql.DispatchMPPTasks(ctx, e.ctx, e.mppReqs, e.retFieldTypes, planIDs, e.id) + e.respIter, err = distsql.DispatchMPPTasks(ctx, e.ctx, e.mppReqs, e.retFieldTypes, planIDs, e.id, e.startTS) if err != nil { return errors.Trace(err) } diff --git a/executor/oomtest/oom_test.go b/executor/oomtest/oom_test.go index d592456bb61cd..866f43f567587 100644 --- a/executor/oomtest/oom_test.go +++ b/executor/oomtest/oom_test.go @@ -34,14 +34,15 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() registerHook() domain.RunAutoAnalyze = false config.UpdateGlobal(func(conf *config.Config) { conf.OOMAction = config.OOMActionLog }) opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/executor/opt_rule_blacklist.go b/executor/opt_rule_blacklist.go index 0d915c9eb6966..5773f80efe7a2 100644 --- a/executor/opt_rule_blacklist.go +++ b/executor/opt_rule_blacklist.go @@ -37,11 +37,7 @@ func (e *ReloadOptRuleBlacklistExec) Next(ctx context.Context, _ *chunk.Chunk) e // LoadOptRuleBlacklist loads the latest data from table mysql.opt_rule_blacklist. func LoadOptRuleBlacklist(ctx sessionctx.Context) (err error) { exec := ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), "select HIGH_PRIORITY name from mysql.opt_rule_blacklist") - if err != nil { - return err - } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, "select HIGH_PRIORITY name from mysql.opt_rule_blacklist") if err != nil { return err } diff --git a/executor/parallel_apply_test.go b/executor/parallel_apply_test.go index 809b4c5247e5a..1d775fcc2218a 100644 --- a/executor/parallel_apply_test.go +++ b/executor/parallel_apply_test.go @@ -17,17 +17,17 @@ package executor_test import ( "fmt" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/israce" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -func checkApplyPlan(c *C, tk *testkit.TestKit, sql string, parallel int) { +func checkApplyPlan(t *testing.T, tk *testkit.TestKit, sql string, parallel int) { results := tk.MustQuery("explain analyze " + sql) containApply := false for _, row := range results.Rows() { @@ -38,35 +38,41 @@ func checkApplyPlan(c *C, tk *testkit.TestKit, sql string, parallel int) { if parallel > 1 { str += fmt.Sprintf("%v", parallel) } - c.Assert(strings.Contains(line, str), IsTrue) + require.Contains(t, line, str) } containApply = true break } } - c.Assert(containApply, IsTrue) + require.True(t, containApply) } -func (s *testSuite) TestParallelApply(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestParallelApplyPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int)") tk.MustExec("insert into t values (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (null, null)") q1 := "select t1.b from t t1 where t1.b > (select max(b) from t t2 where t1.a > t2.a)" - checkApplyPlan(c, tk, q1, 0) + checkApplyPlan(t, tk, q1, 0) tk.MustQuery(q1).Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) tk.MustExec("set tidb_enable_parallel_apply=true") - checkApplyPlan(c, tk, q1, 1) + checkApplyPlan(t, tk, q1, 1) tk.MustQuery(q1).Sort().Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) q2 := "select * from t t0 where t0.b <= (select max(t1.b) from t t1 where t1.b > (select max(b) from t t2 where t1.a > t2.a and t0.a > t2.a));" - checkApplyPlan(c, tk, q2, 1) // only the outside apply can be parallel + checkApplyPlan(t, tk, q2, 1) // only the outside apply can be parallel tk.MustQuery(q2).Sort().Check(testkit.Rows("1 1", "2 2", "3 3", "4 4", "5 5", "6 6", "7 7", "8 8", "9 9")) } -func (s *testSuite) TestApplyColumnType(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyColumnType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // int @@ -75,7 +81,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec("insert into t values(1,1), (2,2), (5,5), (2, 4), (5, 2), (9, 4)") tk.MustExec("insert into t1 values(2, 3), (4, 9), (10, 4), (1, 10)") sql := "select * from t where t.b > (select min(t1.b) from t1 where t1.a > t.a)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("5 5")) // varchar @@ -85,7 +91,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec(`insert into t1 values("aa", "bb"), ("aa", "tikv"), ("bb", "cc"), ("bb", "ee")`) tk.MustExec(`insert into t2 values("kk"), ("aa"), ("dd"), ("bb")`) sql = "select (select min(t2.a) from t2 where t2.a > t1.a) from t1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("bb", "bb", "dd", "dd")) // bit @@ -95,7 +101,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec(`insert into t1 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)`) tk.MustExec(`insert into t2 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)`) sql = "select b from t1 where t1.b > (select min(t2.b) from t2 where t2.a < t1.a)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("2", "2", "3", "3", "4", "4")) // char @@ -105,7 +111,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec(`insert into t1 values("abc", 1), ("abc", "5"), ("fff", 4), ("fff", 9), ("tidb", 6), ("tidb", 5)`) tk.MustExec(`insert into t2 values()`) sql = "select t1.b from t1 where t1.b > (select max(t2.b) from t2 where t2.a > t1.a)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows()) // double @@ -115,7 +121,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec("insert into t1 values(1, 2.12), (1, 1.11), (2, 3), (2, 4.56), (5, 55), (5, -4)") tk.MustExec("insert into t2 values(1, 3.22), (3, 4.5), (5, 2.3), (4, 5.55)") sql = "select * from t1 where t1.a < (select avg(t2.a) from t2 where t2.b > t1.b)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 1.11", "1 2.12", "2 3", "2 4.56")) // date @@ -134,7 +140,7 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec(`insert into t1 values("2020-01-01 00:00:00", 1), ("2020-01-01 00:00:00", 2), ("2020-06-06 00:00:00", 3), ("2020-06-06 00:00:00", 4), ("2020-09-08 00:00:00", 4)`) tk.MustExec(`insert into t2 values("2020-01-01 00:00:00", 1), ("2020-01-01 00:00:01", 2), ("2020-08-20 00:00:00", 4)`) sql = "select b from t1 where t1.b >= (select max(t2.b) from t2 where t2.a > t1.a)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("4")) // timestamp @@ -144,12 +150,15 @@ func (s *testSuite) TestApplyColumnType(c *C) { tk.MustExec(`insert into t1 values("2020-01-01 00:00:00", 1), ("2020-01-01 00:00:00", 2), ("2020-06-06 00:00:00", 3), ("2020-06-06 00:00:00", 4), ("2020-09-08 00:00:00", 4)`) tk.MustExec(`insert into t2 values("2020-01-01 00:00:00", 1), ("2020-01-01 00:00:01", 2), ("2020-08-20 00:00:00", 4)`) sql = "select b from t1 where t1.b >= (select max(t2.b) from t2 where t2.a > t1.a)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("4")) } -func (s *testSuite) TestApplyMultiColumnType(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyMultiColumnType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // int & int @@ -158,7 +167,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec("insert into t1 values (1, 1), (1, 1), (2, 2), (2, 3), (2, 3), (1, 1), (1, 1), (2, 2), (2, 3), (2, 3)") tk.MustExec("insert into t2 values (2, 2), (3,3), (-1, 1), (5, 4), (2, 2), (3,3), (-1, 1), (5, 4)") sql := "select (select count(*) from t2 where t2.a > t1.a and t2.b > t1.a) from t1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("4", "4", "4", "4", "4", "4", "6", "6", "6", "6")) // int & char @@ -168,7 +177,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec(`insert into t1 values (1, "a"), (2, "b"), (3, "c"), (1, "a"), (2, "b"), (3, "c")`) tk.MustExec(`insert into t2 values (1, "a"), (2, "b"), (3, "c"), (1, "a"), (2, "b"), (3, "c")`) sql = "select (select sum(t2.a) from t2 where t2.a > t1.a or t2.b < t1.b) from t1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("10", "10", "6", "6", "8", "8")) // int & bit @@ -178,7 +187,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec(`insert into t1 values (1, '1', 1), (2, '2', 4), (3, '3', 6), (4, '4', 8), (1, '1', 1), (2, '2', 4), (3, '3', 6), (4, '4', 8)`) tk.MustExec(`insert into t2 values (1, 1111, 11), (2, 2222, 22), (1, 1111, 11), (2, 2222, 22)`) sql = "select a, c from t1 where (select max(t2.c) from t2 where t2.a > t1.a and t2.b > t1.b) > 4" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 1", "1 1")) // char & char @@ -188,7 +197,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec(`insert into t1 values ('7', '7'), ('8', '8'), ('9', '9'), ('7', '7'), ('8', '8'), ('9', '9')`) tk.MustExec(`insert into t2 values ('7', '7'), ('8', '8'), ('9', '9'), ('7', '7'), ('8', '8'), ('9', '9')`) sql = "select count(*) from t1 where (select sum(t2.a) from t2 where t2.a >= t1.a and t2.b >= t1.b) > 4" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("6")) // enum & char @@ -198,7 +207,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec(`insert into t1 values ('1', 'a'), ('2', 'b'), ('3', 'c'), ('1', 'a'), ('2', 'b'), ('3', 'c')`) tk.MustExec(`insert into t2 values ('1', 100), ('2', 200), ('3', 300), ('4', 400), ('1', 100), ('2', 200), ('3', 300), ('4', 400)`) sql = "select * from t1 where (select sum(t2.b) from t2 where t2.a > t1.a and t2.b * 2 > t1.b) > 0" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 a", "1 a", "2 b", "2 b", "3 c", "3 c")) // char & bit @@ -208,7 +217,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec("insert into t1 values ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4')") tk.MustExec("insert into t2 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)") sql = "select a from t1 where (select sum(t2.b) from t2 where t2.a > t1.a and t2.b < t1.b) > 4" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1", "1", "2", "2", "3", "3")) // int & double @@ -218,7 +227,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec("insert into t1 values (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4), (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4)") tk.MustExec("insert into t2 values (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4), (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4)") sql = "select * from t1 where (select min(t2.a) from t2 where t2.a < t1.a and t2.a > 1 and t2.b < t1.b) > 0" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("3 3.3", "3 3.3", "4 4.4", "4 4.4")) // int & datetime @@ -228,7 +237,7 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec(`insert into t1 values (1, "2020-01-01"), (2, "2020-02-02"), (3, "2020-03-03"), (1, "2020-01-01"), (2, "2020-02-02"), (3, "2020-03-03")`) tk.MustExec(`insert into t2 values (1, "2020-01-01"), (2, "2020-02-02"), (3, "2020-03-03"), (1, "2020-01-01"), (2, "2020-02-02"), (3, "2020-03-03")`) sql = `select * from t1 where (select count(*) from t2 where t2.a >= t1.a and t2.b between t1.b and "2020-09-07 00:00:00") > 1` - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 2020-01-01 00:00:00", "1 2020-01-01 00:00:00", "2 2020-02-02 00:00:00", "2 2020-02-02 00:00:00", "3 2020-03-03 00:00:00", "3 2020-03-03 00:00:00")) // int & int & char @@ -238,13 +247,16 @@ func (s *testSuite) TestApplyMultiColumnType(c *C) { tk.MustExec("insert into t1 values (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (1, 1, '1'), (2, 2, '2'), (3, 3, '3')") tk.MustExec("insert into t2 values (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (1, 1, '1'), (2, 2, '2'), (3, 3, '3')") sql = "select (select min(t2.a) from t2 where t2.a > t1.a and t2.b > t1.b and t2.c > t1.c) from t1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("2", "2", "3", "3", "", "")) } -func (s *testSuite) TestSetTiDBEnableParallelApply(c *C) { +func TestSetTiDBEnableParallelApply(t *testing.T) { // validate the tidb_enable_parallel_apply's value - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=0") tk.MustQuery("select @@tidb_enable_parallel_apply").Check(testkit.Rows("0")) tk.MustExec("set tidb_enable_parallel_apply=1") @@ -253,14 +265,17 @@ func (s *testSuite) TestSetTiDBEnableParallelApply(c *C) { tk.MustQuery("select @@tidb_enable_parallel_apply").Check(testkit.Rows("1")) tk.MustExec("set tidb_enable_parallel_apply=off") tk.MustQuery("select @@tidb_enable_parallel_apply").Check(testkit.Rows("0")) - c.Assert(tk.ExecToErr("set tidb_enable_parallel_apply=-1"), NotNil) - c.Assert(tk.ExecToErr("set tidb_enable_parallel_apply=2"), NotNil) - c.Assert(tk.ExecToErr("set tidb_enable_parallel_apply=1000"), NotNil) - c.Assert(tk.ExecToErr("set tidb_enable_parallel_apply='onnn'"), NotNil) + require.Error(t, tk.ExecToErr("set tidb_enable_parallel_apply=-1")) + require.Error(t, tk.ExecToErr("set tidb_enable_parallel_apply=2")) + require.Error(t, tk.ExecToErr("set tidb_enable_parallel_apply=1000")) + require.Error(t, tk.ExecToErr("set tidb_enable_parallel_apply='onnn'")) } -func (s *testSuite) TestMultipleApply(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestMultipleApply(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // compare apply with constant values @@ -270,7 +285,7 @@ func (s *testSuite) TestMultipleApply(c *C) { tk.MustExec(`insert into t1 values ("1", "a"), ("2", "b"), ("3", "c"), ("4", "d"), ("1", "a"), ("2", "b"), ("3", "c"), ("4", "d")`) tk.MustExec(`insert into t2 values ("1", 1), ("2", 2), ("3", 3), ("4", 4), ("1", 1), ("2", 2), ("3", 3), ("4", 4)`) sql := "select * from t1 where (select sum(t2.b) from t2 where t2.a > t1.a) >= (select sum(t2.b) from t2 where t2.b > t1.b)" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 a", "1 a", "2 b", "2 b", "3 c", "3 c")) // 2 apply operators in where conditions @@ -280,7 +295,7 @@ func (s *testSuite) TestMultipleApply(c *C) { tk.MustExec("insert into t1 values (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4), (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4)") tk.MustExec("insert into t2 values (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4), (1, 1.1), (2, 2.2), (3, 3.3), (4, 4.4)") sql = "select * from t1 where (select min(t2.a) from t2 where t2.a < t1.a and t2.a > 1) * (select min(t2.a) from t2 where t2.b < t1.b) > 1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("3 3.3", "3 3.3", "4 4.4", "4 4.4")) // 2 apply operators and compare it with constant values @@ -290,7 +305,7 @@ func (s *testSuite) TestMultipleApply(c *C) { tk.MustExec("insert into t1 values ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4')") tk.MustExec("insert into t2 values ('1', 1111), ('2', 2222), ('3', 3333), ('4', 4444), ('1', 1111), ('2', 2222), ('3', 3333), ('4', 4444)") sql = "select a from t1 where (select sum(t2.b) from t2 where t2.a > t1.a) > 4 and (select sum(t2.b) from t2 where t2.b > t1.b) > 4" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1", "1", "2", "2", "3", "3")) // multiple fields and where conditions @@ -300,12 +315,15 @@ func (s *testSuite) TestMultipleApply(c *C) { tk.MustExec("insert into t1 values (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (4, 4, '4'), (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (4, 4, '4')") tk.MustExec("insert into t2 values (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (4, 4, '4'), (1, 1, '1'), (2, 2, '2'), (3, 3, '3'), (4, 4, '4')") sql = "select (select min(t2.a) from t2 where t2.a > t1.a and t2.b > t1.b), (select max(t2.a) from t2 where t2.a > t1.a and t2.b > t1.b) from t1 where (select count(*) from t2 where t2.c > t1.c) > 3" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("2 4", "2 4", "3 4", "3 4")) } -func (s *testSuite) TestApplyWithOtherOperators(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyWithOtherOperators(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // hash join @@ -315,7 +333,7 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") tk.MustExec("insert into t2 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") sql := "select /*+ hash_join(t1) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "0", "0", "2", "2", "2", "2", "4", "4", "4", "4")) // merge join @@ -325,7 +343,7 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") tk.MustExec("insert into t2 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") sql = "select /*+ merge_join(t1) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "0", "0", "2", "2", "2", "2", "4", "4", "4", "4")) // index merge join @@ -335,10 +353,10 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3)") tk.MustExec("insert into t2 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") sql = "select /*+ inl_merge_join(t1) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "2", "2", "4", "4")) sql = "select /*+ inl_merge_join(t2) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "2", "2", "4", "4")) // index hash join @@ -348,10 +366,10 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") tk.MustExec("insert into t2 values (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (3, 3)") sql = "select /*+ inl_hash_join(t1) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "0", "0", "2", "2", "2", "2", "4", "4", "4", "4")) sql = "select /*+ inl_hash_join(t2) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "0", "0", "0", "2", "2", "2", "2", "4", "4", "4", "4")) // index join @@ -361,10 +379,10 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3)") tk.MustExec("insert into t2 values (1, 1), (2, 2), (3, 3)") sql = "select /*+ inl_join(t1) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "1", "2")) sql = "select /*+ inl_join(t2) */ (select count(t2.b) from t2 where t1.a > t2.a) from t1, t2 where t1.a = t2.a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("0", "1", "2")) // index merge @@ -372,7 +390,7 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("create table t(a int, b int, c int, index idxa(a), unique index idxb(b))") tk.MustExec("insert into t values (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (1, 5, 1), (2, 6, 2), (3, 7, 3), (4, 8, 4)") sql = "select /*+ use_index_merge(t) */ * from t where (a > 0 or b < 0) and (select count(*) from t t1 where t1.c > t.a) > 0" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1 1 1", "1 5 1", "2 2 2", "2 6 2", "3 3 3", "3 7 3")) // aggregation @@ -380,19 +398,21 @@ func (s *testSuite) TestApplyWithOtherOperators(c *C) { tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (4, 4), (1, 1), (2, 2), (3, 3), (4, 4)") sql = "select /*+ stream_agg() */ a from t where (select count(*) from t1 where t1.b > t.a) > 1 group by a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1")) sql = "select /*+ hash_agg() */ a from t where (select count(*) from t1 where t1.b > t.a) > 1 group by a" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("1")) } -func (s *testSerialSuite) TestApplyWithOtherFeatures(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyWithOtherFeatures(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // collation 1 - collate.SetNewCollationEnabledForTest(true) tk.MustExec("drop table if exists t, t1") tk.MustExec("create table t(a varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, b int)") tk.MustExec("create table t1(a varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, b int)") @@ -405,6 +425,7 @@ func (s *testSerialSuite) TestApplyWithOtherFeatures(c *C) { sql = "select (select min(t1.b) from t1 where t1.a >= t.a and t1.b >= t.b), (select sum(t1.b) from t1 where t1.a >= t.a and t1.b >= t.b) from t" tk.MustQuery(sql).Sort().Check(testkit.Rows("1 10", "2 9", "3 7", "4 4")) collate.SetNewCollationEnabledForTest(false) + defer collate.SetNewCollationEnabledForTest(true) // plan cache orgEnable := core.PreparedPlanCacheEnabled() @@ -423,7 +444,7 @@ func (s *testSerialSuite) TestApplyWithOtherFeatures(c *C) { core.SetPreparedPlanCache(orgEnable) // cluster index - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t, t2") tk.MustExec("create table t(a int, b int, c int, primary key(a, b))") tk.MustExec("create table t2(a int, b int, c int, primary key(a, c))") @@ -431,7 +452,7 @@ func (s *testSerialSuite) TestApplyWithOtherFeatures(c *C) { tk.MustExec("insert into t2 values (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)") sql = "select * from t where (select min(t2.b) from t2 where t2.a > t.a) > 0" tk.MustQuery(sql).Sort().Check(testkit.Rows("1 1 1", "2 2 2", "3 3 3")) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly // partitioning table tk.MustExec("drop table if exists t1, t2") @@ -443,8 +464,11 @@ func (s *testSerialSuite) TestApplyWithOtherFeatures(c *C) { tk.MustQuery(sql).Sort().Check(testkit.Rows("0 15", "0 ", "0 ")) } -func (s *testSuite) TestApplyInDML(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyInDML(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // delete @@ -497,8 +521,11 @@ func (s *testSuite) TestApplyInDML(c *C) { tk.MustQuery(sql).Sort().Check(testkit.Rows("2 5")) } -func (s *testSuite) TestApplyConcurrency(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyConcurrency(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") // tidb_executor_concurrency @@ -507,9 +534,9 @@ func (s *testSuite) TestApplyConcurrency(c *C) { tk.MustExec("create table t2(a int, b int)") sql := "select * from t1 where t1.b > (select sum(t2.b) from t2 where t2.a > t1.a)" tk.MustExec("set tidb_executor_concurrency = 3") - checkApplyPlan(c, tk, sql, 3) + checkApplyPlan(t, tk, sql, 3) tk.MustExec("set tidb_executor_concurrency = 5") - checkApplyPlan(c, tk, sql, 5) + checkApplyPlan(t, tk, sql, 5) // concurrency tk.MustExec("drop table if exists t") @@ -530,8 +557,11 @@ func (s *testSuite) TestApplyConcurrency(c *C) { } } -func (s *testSuite) TestApplyCacheRatio(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyCacheRatio(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int)") tk.MustExec("create table t2(a int, b int)") @@ -550,32 +580,31 @@ func (s *testSuite) TestApplyCacheRatio(c *C) { } // 10% tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (1, 1)") - c.Assert(checkRatio("10.000%"), IsTrue) + require.True(t, checkRatio("10.000%")) tk.MustExec("set tidb_mem_quota_apply_cache = 0") - c.Assert(checkRatio(""), IsFalse) + require.False(t, checkRatio("")) tk.MustExec("set tidb_mem_quota_apply_cache = 33554432") // 20% tk.MustExec("truncate t1") tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (2, 2), (1, 1)") - c.Assert(checkRatio("20.000%"), IsTrue) + require.True(t, checkRatio("20.000%")) tk.MustExec("set tidb_mem_quota_apply_cache = 0") - c.Assert(checkRatio(""), IsFalse) + require.False(t, checkRatio("")) tk.MustExec("set tidb_mem_quota_apply_cache = 33554432") // 50% tk.MustExec("truncate t1") tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)") - c.Assert(checkRatio("50.000%"), IsTrue) + require.True(t, checkRatio("50.000%")) tk.MustExec("set tidb_mem_quota_apply_cache = 0") - c.Assert(checkRatio(""), IsFalse) + require.False(t, checkRatio("")) } -func (s *testSuite) TestApplyGoroutinePanic(c *C) { - if israce.RaceEnabled { - c.Skip("race detected, skip it temporarily and fix it before 20210619") - } - - tk := testkit.NewTestKitWithInit(c, s.store) +func TestApplyGoroutinePanic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int)") @@ -585,26 +614,28 @@ func (s *testSuite) TestApplyGoroutinePanic(c *C) { // no panic sql := "select (select count(*) from t2 where t2.a > t1.a and t2.b > t1.a) from t1" - checkApplyPlan(c, tk, sql, 1) + checkApplyPlan(t, tk, sql, 1) tk.MustQuery(sql).Sort().Check(testkit.Rows("4", "4", "4", "4", "4", "4", "6", "6", "6", "6")) // panic in a inner worker - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/parallelApplyInnerWorkerPanic", "panic"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/parallelApplyInnerWorkerPanic", "panic")) err := tk.QueryToErr(sql) - c.Assert(err, NotNil) // verify errors are not be ignored - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/parallelApplyInnerWorkerPanic"), IsNil) + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/parallelApplyInnerWorkerPanic")) for _, panicName := range []string{"parallelApplyInnerWorkerPanic", "parallelApplyOuterWorkerPanic", "parallelApplyGetCachePanic", "parallelApplySetCachePanic"} { panicPath := fmt.Sprintf("github.com/pingcap/tidb/executor/%v", panicName) - c.Assert(failpoint.Enable(panicPath, "panic"), IsNil) - err := tk.QueryToErr(sql) - c.Assert(err, NotNil) // verify errors are not be ignored - c.Assert(failpoint.Disable(panicPath), IsNil) + require.NoError(t, failpoint.Enable(panicPath, "panic")) + require.Error(t, tk.QueryToErr(sql)) + require.NoError(t, failpoint.Disable(panicPath)) } } -func (s *testSuite) TestIssue24930(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue24930(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set tidb_enable_parallel_apply=true") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int)") diff --git a/executor/partition_table.go b/executor/partition_table.go index f38c2f1b01861..2ec4e6f421cdb 100644 --- a/executor/partition_table.go +++ b/executor/partition_table.go @@ -22,18 +22,20 @@ import ( "github.com/pingcap/tipb/go-tipb" ) -func updateExecutorTableID(ctx context.Context, exec *tipb.Executor, partitionID int64, recursive bool) error { +func updateExecutorTableID(ctx context.Context, exec *tipb.Executor, recursive bool, partitionIDs []int64) error { var child *tipb.Executor switch exec.Tp { case tipb.ExecType_TypeTableScan: - exec.TblScan.TableId = partitionID + exec.TblScan.TableId = partitionIDs[0] // For test coverage. if tmp := ctx.Value("nextPartitionUpdateDAGReq"); tmp != nil { m := tmp.(map[int64]struct{}) - m[partitionID] = struct{}{} + m[partitionIDs[0]] = struct{}{} } + case tipb.ExecType_TypePartitionTableScan: + exec.PartitionTableScan.PartitionIds = partitionIDs case tipb.ExecType_TypeIndexScan: - exec.IdxScan.TableId = partitionID + exec.IdxScan.TableId = partitionIDs[0] case tipb.ExecType_TypeSelection: child = exec.Selection.Child case tipb.ExecType_TypeAggregation, tipb.ExecType_TypeStreamAgg: @@ -54,7 +56,7 @@ func updateExecutorTableID(ctx context.Context, exec *tipb.Executor, partitionID return errors.Trace(fmt.Errorf("unknown new tipb protocol %d", exec.Tp)) } if child != nil && recursive { - return updateExecutorTableID(ctx, child, partitionID, recursive) + return updateExecutorTableID(ctx, child, recursive, partitionIDs) } return nil } diff --git a/executor/partition_table_test.go b/executor/partition_table_test.go index 89e4311aaee09..cb7b2d7633583 100644 --- a/executor/partition_table_test.go +++ b/executor/partition_table_test.go @@ -18,20 +18,26 @@ import ( "fmt" "math/rand" "strings" + "testing" "time" - . "github.com/pingcap/check" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/israce" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/stretchr/testify/require" ) -func (s *partitionTableSuite) TestFourReader(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestFourReader(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists pt") tk.MustExec(`create table pt (id int, c int, key i_id(id), key i_c(c)) partition by range (c) ( partition p0 values less than (4), @@ -52,7 +58,7 @@ partition p2 values less than (10))`) tk.MustQuery("select c from pt").Sort().Check(testkit.Rows("0", "2", "4", "6", "7", "9", "")) tk.MustQuery("select c from pt where c > 10").Check(testkit.Rows()) tk.MustQuery("select c from pt where c > 8").Check(testkit.Rows("9")) - tk.MustQuery("select c from pt where c < 2 or c >= 9").Check(testkit.Rows("0", "9")) + tk.MustQuery("select c from pt where c < 2 or c >= 9").Sort().Check(testkit.Rows("0", "9")) // Index lookup tk.MustQuery("select /*+ use_index(pt, i_id) */ * from pt").Sort().Check(testkit.Rows("0 0", "2 2", "4 4", "6 6", "7 7", "9 9", " ")) @@ -65,8 +71,12 @@ partition p2 values less than (10))`) tk.MustQuery("select /*+ use_index(i_c, i_id) */ * from pt where id = 4 or c < 7").Sort().Check(testkit.Rows("0 0", "2 2", "4 4", "6 6")) } -func (s *partitionTableSuite) TestPartitionIndexJoin(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionIndexJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("set @@session.tidb_enable_table_partition = 1") tk.MustExec("set @@session.tidb_enable_list_partition = 1") for i := 0; i < 3; i++ { @@ -99,9 +109,14 @@ func (s *partitionTableSuite) TestPartitionIndexJoin(c *C) { } } -func (s *partitionTableSuite) TestPartitionUnionScanIndexJoin(c *C) { +func TestPartitionUnionScanIndexJoin(t *testing.T) { // For issue https://github.com/pingcap/tidb/issues/19152 - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 (c_int int, c_str varchar(40), primary key (c_int)) partition by range (c_int) ( partition p0 values less than (10), partition p1 values less than maxvalue)") tk.MustExec("create table t2 (c_int int, c_str varchar(40), primary key (c_int, c_str)) partition by hash (c_int) partitions 4") @@ -114,11 +129,12 @@ func (s *partitionTableSuite) TestPartitionUnionScanIndexJoin(c *C) { tk.MustExec("commit") } -func (s *partitionTableSuite) TestPointGetwithRangeAndListPartitionTable(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPointGetwithRangeAndListPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_pointget_list_hash") tk.MustExec("use test_pointget_list_hash") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -161,35 +177,38 @@ func (s *partitionTableSuite) TestPointGetwithRangeAndListPartitionTable(c *C) { // select a from t where a={x}; // the result is {x} x := rand.Intn(100) + 1 queryRange1 := fmt.Sprintf("select a from trange1 where a=%v", x) - c.Assert(tk.HasPlan(queryRange1, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryRange1, "Point_Get")) // check if PointGet is used tk.MustQuery(queryRange1).Check(testkit.Rows(fmt.Sprintf("%v", x))) queryRange2 := fmt.Sprintf("select a from trange1 where a=%v", x) - c.Assert(tk.HasPlan(queryRange2, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryRange2, "Point_Get")) // check if PointGet is used tk.MustQuery(queryRange2).Check(testkit.Rows(fmt.Sprintf("%v", x))) y := rand.Intn(12) + 1 queryList := fmt.Sprintf("select a from tlist where a=%v", y) - c.Assert(tk.HasPlan(queryList, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryList, "Point_Get")) // check if PointGet is used tk.MustQuery(queryList).Check(testkit.Rows(fmt.Sprintf("%v", y))) } // test table dual queryRange1 := "select a from trange1 where a=200" - c.Assert(tk.HasPlan(queryRange1, "TableDual"), IsTrue) // check if TableDual is used + require.True(t, tk.HasPlan(queryRange1, "TableDual")) // check if TableDual is used tk.MustQuery(queryRange1).Check(testkit.Rows()) queryRange2 := "select a from trange2 where a=200" - c.Assert(tk.HasPlan(queryRange2, "TableDual"), IsTrue) // check if TableDual is used + require.True(t, tk.HasPlan(queryRange2, "TableDual")) // check if TableDual is used tk.MustQuery(queryRange2).Check(testkit.Rows()) queryList := "select a from tlist where a=200" - c.Assert(tk.HasPlan(queryList, "TableDual"), IsTrue) // check if TableDual is used + require.True(t, tk.HasPlan(queryList, "TableDual")) // check if TableDual is used tk.MustQuery(queryList).Check(testkit.Rows()) } -func (s *partitionTableSuite) TestPartitionReaderUnderApply(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionReaderUnderApply(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // For issue 19458. @@ -205,7 +224,7 @@ func (s *partitionTableSuite) TestPartitionReaderUnderApply(c *C) { c_double double DEFAULT NULL, c_decimal decimal(12,6) DEFAULT NULL, PRIMARY KEY (c_int,c_str,c_datetime) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci PARTITION BY RANGE (c_int) (PARTITION p0 VALUES LESS THAN (2) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (4) ENGINE = InnoDB, @@ -245,8 +264,11 @@ func (s *partitionTableSuite) TestPartitionReaderUnderApply(c *C) { "5 naughty swartz 9.524000")) } -func (s *partitionTableSuite) TestImproveCoverage(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestImproveCoverage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table coverage_rr ( pk1 varchar(35) NOT NULL, @@ -261,8 +283,11 @@ PRIMARY KEY (pk1,pk2)) partition by hash(pk2) partitions 4;`) tk.MustQuery("select /*+ INL_MERGE_JOIN(dt, rr) */ * from coverage_dt dt join coverage_rr rr on (dt.pk1 = rr.pk1 and dt.pk2 = rr.pk2);").Sort().Check(testkit.Rows("ios 3 ios 3 2", "linux 5 linux 5 1")) } -func (s *partitionTableSuite) TestPartitionInfoDisable(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionInfoDisable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t_info_null") tk.MustExec(`CREATE TABLE t_info_null ( @@ -287,9 +312,9 @@ func (s *partitionTableSuite) TestPartitionInfoDisable(c *C) { PARTITION p202010 VALUES LESS THAN ("2020-11-01"), PARTITION p202011 VALUES LESS THAN ("2020-12-01") )`) - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t_info_null")) - c.Assert(err, IsNil) + require.NoError(t, err) tbInfo := tbl.Meta() // Mock for a case that the tableInfo.Partition is not nil, but tableInfo.Partition.Enable is false. @@ -305,12 +330,12 @@ func (s *partitionTableSuite) TestPartitionInfoDisable(c *C) { tk.MustQuery("select * from t_info_null where (date = '2020-10-02' or date = '2020-10-06') and app = 'xxx' and media = '19003006'").Check(testkit.Rows()) } -func (s *partitionTableSuite) TestOrderByandLimit(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestOrderByandLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_orderby_limit") tk.MustExec("use test_orderby_limit") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -344,7 +369,7 @@ func (s *partitionTableSuite) TestOrderByandLimit(c *C) { y := rand.Intn(2000) + 1 queryPartition := fmt.Sprintf("select * from trange use index(idx_a) where a > %v order by a, b limit %v;", x, y) queryRegular := fmt.Sprintf("select * from tregular use index(idx_a) where a > %v order by a, b limit %v;", x, y) - c.Assert(tk.HasPlan(queryPartition, "IndexLookUp"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition, "IndexLookUp")) // check if IndexLookUp is used tk.MustQuery(queryPartition).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } @@ -356,7 +381,7 @@ func (s *partitionTableSuite) TestOrderByandLimit(c *C) { y := rand.Intn(2000) + 1 queryPartition := fmt.Sprintf("select * from trange ignore index(idx_a) where a > %v order by a, b limit %v;", x, y) queryRegular := fmt.Sprintf("select * from tregular ignore index(idx_a) where a > %v order by a, b limit %v;", x, y) - c.Assert(tk.HasPlan(queryPartition, "TableReader"), IsTrue) // check if tableReader is used + require.True(t, tk.HasPlan(queryPartition, "TableReader")) // check if tableReader is used tk.MustQuery(queryPartition).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } @@ -368,7 +393,7 @@ func (s *partitionTableSuite) TestOrderByandLimit(c *C) { y := rand.Intn(2000) + 1 queryPartition := fmt.Sprintf("select a from trange use index(idx_a) where a > %v order by a limit %v;", x, y) queryRegular := fmt.Sprintf("select a from tregular use index(idx_a) where a > %v order by a limit %v;", x, y) - c.Assert(tk.HasPlan(queryPartition, "IndexReader"), IsTrue) // check if indexReader is used + require.True(t, tk.HasPlan(queryPartition, "IndexReader")) // check if indexReader is used tk.MustQuery(queryPartition).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } @@ -379,17 +404,18 @@ func (s *partitionTableSuite) TestOrderByandLimit(c *C) { y := rand.Intn(2000) + 1 queryPartition := fmt.Sprintf("select /*+ use_index_merge(thash) */ * from thash where a > 2 or b < 5 order by a, b limit %v;", y) queryRegular := fmt.Sprintf("select * from tregular where a > 2 or b < 5 order by a, b limit %v;", y) - c.Assert(tk.HasPlan(queryPartition, "IndexMerge"), IsTrue) // check if indexMerge is used + require.True(t, tk.HasPlan(queryPartition, "IndexMerge")) // check if indexMerge is used tk.MustQuery(queryPartition).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } } -func (s *partitionTableSuite) TestBatchGetandPointGetwithHashPartition(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestBatchGetandPointGetwithHashPartition(t *testing.T) { + + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_batchget_pointget") tk.MustExec("use test_batchget_pointget") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -415,13 +441,13 @@ func (s *partitionTableSuite) TestBatchGetandPointGetwithHashPartition(c *C) { x := rand.Intn(100) + 1 queryHash := fmt.Sprintf("select a from thash where a=%v", x) queryRegular := fmt.Sprintf("select a from tregular where a=%v", x) - c.Assert(tk.HasPlan(queryHash, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryHash, "Point_Get")) // check if PointGet is used tk.MustQuery(queryHash).Check(tk.MustQuery(queryRegular).Rows()) } // test empty PointGet queryHash := "select a from thash where a=200" - c.Assert(tk.HasPlan(queryHash, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryHash, "Point_Get")) // check if PointGet is used tk.MustQuery(queryHash).Check(testkit.Rows()) // test BatchGet @@ -436,17 +462,17 @@ func (s *partitionTableSuite) TestBatchGetandPointGetwithHashPartition(c *C) { queryHash := fmt.Sprintf("select a from thash where a in (%v)", strings.Join(points, ",")) queryRegular := fmt.Sprintf("select a from tregular where a in (%v)", strings.Join(points, ",")) - c.Assert(tk.HasPlan(queryHash, "Point_Get"), IsTrue) // check if PointGet is used + require.True(t, tk.HasPlan(queryHash, "Point_Get")) // check if PointGet is used tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } } -func (s *partitionTableSuite) TestView(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_view") tk.MustExec("use test_view") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -513,12 +539,12 @@ func (s *partitionTableSuite) TestView(c *C) { } } -func (s *partitionTableSuite) TestDirectReadingwithIndexJoin(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestDirectReadingwithIndexJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_dr_join") tk.MustExec("use test_dr_join") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -526,10 +552,10 @@ func (s *partitionTableSuite) TestDirectReadingwithIndexJoin(c *C) { // hash and range partition tk.MustExec("create table thash (a int, b int, c int, primary key(a), index idx_b(b)) partition by hash(a) partitions 4;") tk.MustExec(`create table trange (a int, b int, c int, primary key(a), index idx_b(b)) partition by range(a) ( -   partition p0 values less than(1000), -   partition p1 values less than(2000), -   partition p2 values less than(3000), -   partition p3 values less than(4000));`) + partition p0 values less than(1000), + partition p1 values less than(2000), + partition p2 values less than(3000), + partition p3 values less than(4000));`) // regualr table tk.MustExec(`create table tnormal (a int, b int, c int, primary key(a), index idx_b(b));`) @@ -626,12 +652,12 @@ func (s *partitionTableSuite) TestDirectReadingwithIndexJoin(c *C) { tk.MustQuery(queryPartition).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } -func (s *partitionTableSuite) TestDynamicPruningUnderIndexJoin(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestDynamicPruningUnderIndexJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database pruing_under_index_join") tk.MustExec("use pruing_under_index_join") @@ -686,12 +712,12 @@ func (s *partitionTableSuite) TestDynamicPruningUnderIndexJoin(c *C) { tk.MustQuery(`select /*+ INL_JOIN(touter, tnormal) */ tnormal.* from touter join tnormal use index(idx_b) on touter.b = tnormal.b`).Sort().Rows()) } -func (s *partitionTableSuite) TestIssue25527(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestIssue25527(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_issue_25527") tk.MustExec("use test_issue_25527") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -725,8 +751,12 @@ func (s *partitionTableSuite) TestIssue25527(c *C) { tk.MustQuery(`select a from t2 where a in (5)`).Check(testkit.Rows("5")) } -func (s *partitionTableSuite) TestIssue25598(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue25598(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_issue_25598") tk.MustExec("use test_issue_25598") tk.MustExec(`CREATE TABLE UK_HP16726 ( @@ -748,11 +778,12 @@ func (s *partitionTableSuite) TestIssue25598(c *C) { tk.MustExec(`explain select t1. col1, t2. col1 from UK_HP16726 as t1 inner join UK_HP16726 as t2 on t1.col1 = t2.col1 where t1.col1 > -9223372036854775808 group by t1.col1, t2.col1 having t1.col1 != 9223372036854775807`) } -func (s *partitionTableSuite) TestBatchGetforRangeandListPartitionTable(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - tk := testkit.NewTestKitWithInit(c, s.store) +func TestBatchGetforRangeandListPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_pointget") tk.MustExec("use test_pointget") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -802,11 +833,11 @@ func (s *partitionTableSuite) TestBatchGetforRangeandListPartitionTable(c *C) { queryRegular1 := fmt.Sprintf("select a from tregular1 where a in (%v)", strings.Join(points, ",")) queryHash := fmt.Sprintf("select a from thash where a in (%v)", strings.Join(points, ",")) - c.Assert(tk.HasPlan(queryHash, "Batch_Point_Get"), IsTrue) // check if BatchGet is used + require.True(t, tk.HasPlan(queryHash, "Batch_Point_Get")) // check if BatchGet is used tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryRange := fmt.Sprintf("select a from trange where a in (%v)", strings.Join(points, ",")) - c.Assert(tk.HasPlan(queryRange, "Batch_Point_Get"), IsTrue) // check if BatchGet is used + require.True(t, tk.HasPlan(queryRange, "Batch_Point_Get")) // check if BatchGet is used tk.MustQuery(queryRange).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) points = make([]string, 0, 10) @@ -816,7 +847,7 @@ func (s *partitionTableSuite) TestBatchGetforRangeandListPartitionTable(c *C) { } queryRegular2 := fmt.Sprintf("select a from tregular2 where a in (%v)", strings.Join(points, ",")) queryList := fmt.Sprintf("select a from tlist where a in (%v)", strings.Join(points, ",")) - c.Assert(tk.HasPlan(queryList, "Batch_Point_Get"), IsTrue) // check if BatchGet is used + require.True(t, tk.HasPlan(queryList, "Batch_Point_Get")) // check if BatchGet is used tk.MustQuery(queryList).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) } @@ -846,16 +877,16 @@ func (s *partitionTableSuite) TestBatchGetforRangeandListPartitionTable(c *C) { } queryRegular := fmt.Sprintf("select a from tregular3 where a in (%v)", strings.Join(points, ",")) queryRange := fmt.Sprintf("select a from trange3 where a in (%v)", strings.Join(points, ",")) - c.Assert(tk.HasPlan(queryRange, "Batch_Point_Get"), IsTrue) // check if BatchGet is used + require.True(t, tk.HasPlan(queryRange, "Batch_Point_Get")) // check if BatchGet is used tk.MustQuery(queryRange).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } -func (s *partitionTableSuite) TestGlobalStatsAndSQLBinding(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestGlobalStatsAndSQLBinding(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_global_stats") tk.MustExec("use test_global_stats") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -894,9 +925,9 @@ func (s *partitionTableSuite) TestGlobalStatsAndSQLBinding(c *C) { tk.MustExec("insert into tlist values " + strings.Join(listVals, ",")) // before analyzing, the planner will choose TableScan to access the 1% of records - c.Assert(tk.HasPlan("select * from thash where a<100", "TableFullScan"), IsTrue) - c.Assert(tk.HasPlan("select * from trange where a<100", "TableFullScan"), IsTrue) - c.Assert(tk.HasPlan("select * from tlist where a<1", "TableFullScan"), IsTrue) + require.True(t, tk.HasPlan("select * from thash where a<100", "TableFullScan")) + require.True(t, tk.HasPlan("select * from trange where a<100", "TableFullScan")) + require.True(t, tk.HasPlan("select * from tlist where a<1", "TableFullScan")) tk.MustExec("analyze table thash") tk.MustExec("analyze table trange") @@ -913,9 +944,9 @@ func (s *partitionTableSuite) TestGlobalStatsAndSQLBinding(c *C) { tk.MustExec("create session binding for select * from tlist where a<100 using select * from tlist ignore index(a) where a<100") // use TableScan again since the Index(a) is ignored - c.Assert(tk.HasPlan("select * from thash where a<100", "TableFullScan"), IsTrue) - c.Assert(tk.HasPlan("select * from trange where a<100", "TableFullScan"), IsTrue) - c.Assert(tk.HasPlan("select * from tlist where a<1", "TableFullScan"), IsTrue) + require.True(t, tk.HasPlan("select * from thash where a<100", "TableFullScan")) + require.True(t, tk.HasPlan("select * from trange where a<100", "TableFullScan")) + require.True(t, tk.HasPlan("select * from tlist where a<1", "TableFullScan")) // drop SQL bindings tk.MustExec("drop session binding for select * from thash where a<100") @@ -928,12 +959,12 @@ func (s *partitionTableSuite) TestGlobalStatsAndSQLBinding(c *C) { tk.MustIndexLookup("select * from tlist where a<1") } -func (s *partitionTableSuite) TestPartitionTableWithDifferentJoin(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestPartitionTableWithDifferentJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_partition_joins") tk.MustExec("use test_partition_joins") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -974,78 +1005,78 @@ func (s *partitionTableSuite) TestPartitionTableWithDifferentJoin(c *C) { // hash_join range partition and hash partition queryHash := fmt.Sprintf("select /*+ hash_join(trange, thash) */ * from trange, thash where trange.b=thash.b and thash.a = %v and trange.a > %v;", x1, x2) queryRegular := fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.b=tregular1.b and tregular1.a = %v and tregular2.a > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ hash_join(trange, thash) */ * from trange, thash where trange.a=thash.a and thash.a > %v;", x1) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.a > %v;", x1) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ hash_join(trange, thash) */ * from trange, thash where trange.a=thash.a and trange.b = thash.b and thash.a > %v;", x1) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.b = tregular2.b and tregular1.a > %v;", x1) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ hash_join(trange, thash) */ * from trange, thash where trange.a=thash.a and thash.a = %v;", x1) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.a = %v;", x1) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // group 2 // hash_join range partition and regular table queryHash = fmt.Sprintf("select /*+ hash_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and trange.a >= %v and tregular1.a > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular2.a >= %v and tregular1.a > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ hash_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and trange.a in (%v, %v, %v);", x1, x2, x3) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular2.a in (%v, %v, %v);", x1, x2, x3) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ hash_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and tregular1.a >= %v;", x1) queryRegular = fmt.Sprintf("select /*+ hash_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular1.a >= %v;", x1) - c.Assert(tk.HasPlan(queryHash, "HashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "HashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // group 3 // merge_join range partition and hash partition queryHash = fmt.Sprintf("select /*+ merge_join(trange, thash) */ * from trange, thash where trange.b=thash.b and thash.a = %v and trange.a > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.b=tregular1.b and tregular1.a = %v and tregular2.a > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ merge_join(trange, thash) */ * from trange, thash where trange.a=thash.a and thash.a > %v;", x1) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.a > %v;", x1) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ merge_join(trange, thash) */ * from trange, thash where trange.a=thash.a and trange.b = thash.b and thash.a > %v;", x1) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.b = tregular2.b and tregular1.a > %v;", x1) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ merge_join(trange, thash) */ * from trange, thash where trange.a=thash.a and thash.a = %v;", x1) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a=tregular1.a and tregular1.a = %v;", x1) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // group 4 // merge_join range partition and regular table queryHash = fmt.Sprintf("select /*+ merge_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and trange.a >= %v and tregular1.a > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular2.a >= %v and tregular1.a > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ merge_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and trange.a in (%v, %v, %v);", x1, x2, x3) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular2.a in (%v, %v, %v);", x1, x2, x3) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ merge_join(trange, tregular1) */ * from trange, tregular1 where trange.a = tregular1.a and tregular1.a >= %v;", x1) queryRegular = fmt.Sprintf("select /*+ merge_join(tregular2, tregular1) */ * from tregular2, tregular1 where tregular2.a = tregular1.a and tregular1.a >= %v;", x1) - c.Assert(tk.HasPlan(queryHash, "MergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "MergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // new table instances @@ -1079,86 +1110,86 @@ func (s *partitionTableSuite) TestPartitionTableWithDifferentJoin(c *C) { // Currently don't support index merge join on two partition tables. Only test warning. queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, trange2) */ * from trange, trange2 where trange.a=trange2.a and trange.a > %v;", x1) // queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v;", x1) - // c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + // require.True(t,tk.HasPlan(queryHash, "IndexMergeJoin")) // tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) tk.MustQuery(queryHash) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, trange2) */ * from trange, trange2 where trange.a=trange2.a and trange.a > %v and trange2.a > %v;", x1, x2) // queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular4.a > %v;", x1, x2) - // c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + // require.True(t,tk.HasPlan(queryHash, "IndexMergeJoin")) // tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) tk.MustQuery(queryHash) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, trange2) */ * from trange, trange2 where trange.a=trange2.a and trange.a > %v and trange.b > %v;", x1, x2) // queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular2.b > %v;", x1, x2) - // c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + // require.True(t,tk.HasPlan(queryHash, "IndexMergeJoin")) // tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) tk.MustQuery(queryHash) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, trange2) */ * from trange, trange2 where trange.a=trange2.a and trange.a > %v and trange2.b > %v;", x1, x2) // queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular4.b > %v;", x1, x2) - // c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + // require.True(t,tk.HasPlan(queryHash, "IndexMergeJoin")) // tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) tk.MustQuery(queryHash) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1815|Optimizer Hint /*+ INL_MERGE_JOIN(trange, trange2) */ is inapplicable")) // group 6 // index_merge_join range partition and regualr table queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, tregular4) */ * from trange, tregular4 where trange.a=tregular4.a and trange.a > %v;", x1) queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v;", x1) - c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexMergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, tregular4) */ * from trange, tregular4 where trange.a=tregular4.a and trange.a > %v and tregular4.a > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular4.a > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexMergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, tregular4) */ * from trange, tregular4 where trange.a=tregular4.a and trange.a > %v and trange.b > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular2.b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexMergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_merge_join(trange, tregular4) */ * from trange, tregular4 where trange.a=tregular4.a and trange.a > %v and tregular4.b > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_merge_join(tregular2, tregular4) */ * from tregular2, tregular4 where tregular2.a=tregular4.a and tregular2.a > %v and tregular4.b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexMergeJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexMergeJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // group 7 // index_hash_join hash partition and hash partition queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, thash2) */ * from thash, thash2 where thash.a = thash2.a and thash.a in (%v, %v);", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a in (%v, %v);", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, thash2) */ * from thash, thash2 where thash.a = thash2.a and thash.a in (%v, %v) and thash2.a in (%v, %v);", x1, x2, x3, x4) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a in (%v, %v) and tregular3.a in (%v, %v);", x1, x2, x3, x4) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, thash2) */ * from thash, thash2 where thash.a = thash2.a and thash.a > %v and thash2.b > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a > %v and tregular3.b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) // group 8 // index_hash_join hash partition and hash partition queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, tregular3) */ * from thash, tregular3 where thash.a = tregular3.a and thash.a in (%v, %v);", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a in (%v, %v);", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, tregular3) */ * from thash, tregular3 where thash.a = tregular3.a and thash.a in (%v, %v) and tregular3.a in (%v, %v);", x1, x2, x3, x4) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a in (%v, %v) and tregular3.a in (%v, %v);", x1, x2, x3, x4) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) queryHash = fmt.Sprintf("select /*+ inl_hash_join(thash, tregular3) */ * from thash, tregular3 where thash.a = tregular3.a and thash.a > %v and tregular3.b > %v;", x1, x2) queryRegular = fmt.Sprintf("select /*+ inl_hash_join(tregular1, tregular3) */ * from tregular1, tregular3 where tregular1.a = tregular3.a and tregular1.a > %v and tregular3.b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryHash, "IndexHashJoin"), IsTrue) + require.True(t, tk.HasPlan(queryHash, "IndexHashJoin")) tk.MustQuery(queryHash).Sort().Check(tk.MustQuery(queryRegular).Sort().Rows()) } @@ -1180,8 +1211,12 @@ type testData4Expression struct { partitions []string } -func (s *partitionTableSuite) TestDateColWithUnequalExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestDateColWithUnequalExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_datetime_unequal_expression") tk.MustExec("create database db_datetime_unequal_expression") tk.MustExec("use db_datetime_unequal_expression") @@ -1211,8 +1246,12 @@ func (s *partitionTableSuite) TestDateColWithUnequalExpression(c *C) { } } -func (s *partitionTableSuite) TestToDaysColWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestToDaysColWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_to_days_expression") tk.MustExec("create database db_to_days_expression") tk.MustExec("use db_to_days_expression") @@ -1242,8 +1281,12 @@ func (s *partitionTableSuite) TestToDaysColWithExpression(c *C) { } } -func (s *partitionTableSuite) TestWeekdayWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestWeekdayWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_weekday_expression") tk.MustExec("create database db_weekday_expression") tk.MustExec("use db_weekday_expression") @@ -1277,8 +1320,12 @@ func (s *partitionTableSuite) TestWeekdayWithExpression(c *C) { } } -func (s *partitionTableSuite) TestFloorUnixTimestampAndIntColWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestFloorUnixTimestampAndIntColWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_floor_unix_timestamp_int_expression") tk.MustExec("create database db_floor_unix_timestamp_int_expression") tk.MustExec("use db_floor_unix_timestamp_int_expression") @@ -1308,8 +1355,12 @@ func (s *partitionTableSuite) TestFloorUnixTimestampAndIntColWithExpression(c *C } } -func (s *partitionTableSuite) TestUnixTimestampAndIntColWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestUnixTimestampAndIntColWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_unix_timestamp_int_expression") tk.MustExec("create database db_unix_timestamp_int_expression") tk.MustExec("use db_unix_timestamp_int_expression") @@ -1339,8 +1390,12 @@ func (s *partitionTableSuite) TestUnixTimestampAndIntColWithExpression(c *C) { } } -func (s *partitionTableSuite) TestDatetimeColAndIntColWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestDatetimeColAndIntColWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_datetime_int_expression") tk.MustExec("create database db_datetime_int_expression") tk.MustExec("use db_datetime_int_expression") @@ -1370,8 +1425,12 @@ func (s *partitionTableSuite) TestDatetimeColAndIntColWithExpression(c *C) { } } -func (s *partitionTableSuite) TestVarcharColAndIntColWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestVarcharColAndIntColWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_varchar_int_expression") tk.MustExec("create database db_varchar_int_expression") tk.MustExec("use db_varchar_int_expression") @@ -1405,8 +1464,12 @@ func (s *partitionTableSuite) TestVarcharColAndIntColWithExpression(c *C) { } } -func (s *partitionTableSuite) TestDynamicPruneModeWithExpression(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestDynamicPruneModeWithExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop database if exists db_equal_expression") tk.MustExec("create database db_equal_expression") tk.MustExec("use db_equal_expression") @@ -1693,12 +1756,12 @@ func (s *partitionTableSuite) TestDynamicPruneModeWithExpression(c *C) { } } -func (s *partitionTableSuite) TestAddDropPartitions(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestAddDropPartitions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_add_drop_partition") tk.MustExec("use test_add_drop_partition") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -1727,12 +1790,12 @@ func (s *partitionTableSuite) TestAddDropPartitions(c *C) { tk.MustPartition(`select * from t where a < 20`, "p1,p2,p3").Sort().Check(testkit.Rows("12", "15", "7")) } -func (s *partitionTableSuite) TestMPPQueryExplainInfo(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestMPPQueryExplainInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database tiflash_partition_test") tk.MustExec("use tiflash_partition_test") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -1741,13 +1804,13 @@ func (s *partitionTableSuite) TestMPPQueryExplainInfo(c *C) { partition p0 values less than (5), partition p1 values less than (10), partition p2 values less than (15))`) - tb := testGetTableByName(c, tk.Se, "tiflash_partition_test", "t") + tb := external.GetTableByName(t, tk, "tiflash_partition_test", "t") for _, partition := range tb.Meta().GetPartitionInfo().Definitions { - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, partition.ID, true) - c.Assert(err, IsNil) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), partition.ID, true) + require.NoError(t, err) } - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec(`insert into t values (2), (7), (12)`) tk.MustExec("set tidb_enforce_mpp=1") tk.MustPartition(`select * from t where a < 3`, "p0").Sort().Check(testkit.Rows("2")) @@ -1757,26 +1820,37 @@ func (s *partitionTableSuite) TestMPPQueryExplainInfo(c *C) { tk.MustPartition(`select * from t where a < 5 union all select * from t where a > 10`, "p2").Sort().Check(testkit.Rows("12", "2")) } -func (s *partitionTableSuite) PartitionPruningInTransaction(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestPartitionPruningInTransaction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_pruning_transaction") defer tk.MustExec(`drop database test_pruning_transaction`) tk.MustExec("use test_pruning_transaction") - tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec(`create table t(a int, b int) partition by range(a) (partition p0 values less than(3), partition p1 values less than (5), partition p2 values less than(11))`) + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec(`begin`) + tk.MustPartitionByList(`select * from t`, []string{"p0", "p1", "p2"}) + tk.MustPartitionByList(`select * from t where a > 3`, []string{"p1", "p2"}) // partition pruning can work in transactions + tk.MustPartitionByList(`select * from t where a > 7`, []string{"p2"}) + tk.MustExec(`rollback`) + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec(`begin`) tk.MustPartition(`select * from t`, "all") - tk.MustPartition(`select * from t where a > 4`, "p1,p2") // partition pruning can work in transactions + tk.MustPartition(`select * from t where a > 3`, "p1,p2") // partition pruning can work in transactions tk.MustPartition(`select * from t where a > 7`, "p2") tk.MustExec(`rollback`) + tk.MustExec("set @@tidb_partition_prune_mode = default") } -func (s *partitionTableSuite) TestIssue25253(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue25253(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database issue25253") defer tk.MustExec("drop database issue25253") tk.MustExec("use issue25253") @@ -1806,12 +1880,12 @@ func (s *partitionTableSuite) TestIssue25253(c *C) { tk.MustQuery(`select * from t`).Check(testkit.Rows()) } -func (s *partitionTableSuite) TestDML(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestDML(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_DML") defer tk.MustExec(`drop database test_DML`) tk.MustExec("use test_DML") @@ -1867,12 +1941,12 @@ func (s *partitionTableSuite) TestDML(c *C) { } } -func (s *partitionTableSuite) TestUnion(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestUnion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_union") defer tk.MustExec(`drop database test_union`) tk.MustExec("use test_union") @@ -1918,12 +1992,12 @@ func (s *partitionTableSuite) TestUnion(c *C) { } } -func (s *partitionTableSuite) TestSubqueries(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestSubqueries(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_subquery") defer tk.MustExec(`drop database test_subquery`) tk.MustExec("use test_subquery") @@ -1984,12 +2058,12 @@ func (s *partitionTableSuite) TestSubqueries(c *C) { } } -func (s *partitionTableSuite) TestSplitRegion(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestSplitRegion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_split_region") tk.MustExec("use test_split_region") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2021,12 +2095,12 @@ func (s *partitionTableSuite) TestSplitRegion(c *C) { tk.MustPartition(`select * from thash where a in (1, 10001, 20001)`, "p1").Sort().Check(result) } -func (s *partitionTableSuite) TestParallelApply(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestParallelApply(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_parallel_apply") tk.MustExec("use test_parallel_apply") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2161,12 +2235,12 @@ func (s *partitionTableSuite) TestParallelApply(c *C) { } } -func (s *partitionTableSuite) TestDirectReadingWithUnionScan(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestDirectReadingWithUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_unionscan") defer tk.MustExec(`drop database test_unionscan`) tk.MustExec("use test_unionscan") @@ -2236,8 +2310,12 @@ func (s *partitionTableSuite) TestDirectReadingWithUnionScan(c *C) { tk.MustExec(`rollback`) } -func (s *partitionTableSuite) TestIssue25030(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue25030(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_issue_25030") tk.MustExec("use test_issue_25030") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2261,12 +2339,12 @@ func (s *partitionTableSuite) TestIssue25030(c *C) { Check(testkit.Rows()) // can work properly without any error or panic } -func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestUnsignedPartitionColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_unsigned_partition") tk.MustExec("use test_unsigned_partition") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2310,7 +2388,7 @@ func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { for tid, tbl := range []string{"tnormal_pk", "trange_pk", "thash_pk"} { // unsigned + TableReader scanSQL := fmt.Sprintf("select * from %v use index(primary) where %v", tbl, scanCond) - c.Assert(tk.HasPlan(scanSQL, "TableReader"), IsTrue) + require.True(t, tk.HasPlan(scanSQL, "TableReader")) r := tk.MustQuery(scanSQL).Sort() if tid == 0 { rScan = r.Rows() @@ -2330,7 +2408,7 @@ func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { // unsigned + BatchGet on PK batchSQL := fmt.Sprintf("select * from %v where %v", tbl, batchCond) - c.Assert(tk.HasPlan(batchSQL, "Batch_Point_Get"), IsTrue) + require.True(t, tk.HasPlan(batchSQL, "Batch_Point_Get")) r = tk.MustQuery(batchSQL).Sort() if tid == 0 { rBatch = r.Rows() @@ -2344,7 +2422,7 @@ func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { for tid, tbl := range []string{"tnormal_uniq", "trange_uniq", "thash_uniq"} { // unsigned + IndexReader scanSQL := fmt.Sprintf("select a from %v use index(a) where %v", tbl, scanCond) - c.Assert(tk.HasPlan(scanSQL, "IndexReader"), IsTrue) + require.True(t, tk.HasPlan(scanSQL, "IndexReader")) r := tk.MustQuery(scanSQL).Sort() if tid == 0 { rScan = r.Rows() @@ -2374,7 +2452,7 @@ func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { // unsigned + BatchGet on UniqueIndex batchSQL := fmt.Sprintf("select * from %v where %v", tbl, batchCond) - c.Assert(tk.HasPlan(batchSQL, "Batch_Point_Get"), IsTrue) + require.True(t, tk.HasPlan(batchSQL, "Batch_Point_Get")) r = tk.MustQuery(batchSQL).Sort() if tid == 0 { rBatch = r.Rows() @@ -2385,12 +2463,12 @@ func (s *partitionTableSuite) TestUnsignedPartitionColumn(c *C) { } } -func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestDirectReadingWithAgg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_dr_agg") tk.MustExec("use test_dr_agg") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2442,12 +2520,12 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from trange where a > %v group by a;", x) queryRegular1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular1 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition1, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from trange where a > %v group by a;", x) queryRegular2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular1 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition2, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) y := rand.Intn(1099) @@ -2455,12 +2533,12 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from trange where a in(%v, %v, %v) group by a;", x, y, z) queryRegular3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular1 where a in(%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition3, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition3, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition3).Sort().Check(tk.MustQuery(queryRegular3).Sort().Rows()) queryPartition4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from trange where a in (%v, %v, %v) group by a;", x, y, z) queryRegular4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular1 where a in (%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition4, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition4, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition4).Sort().Check(tk.MustQuery(queryRegular4).Sort().Rows()) } @@ -2474,12 +2552,12 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from thash where a > %v group by a;", x) queryRegular1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular1 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition1, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from thash where a > %v group by a;", x) queryRegular2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular1 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition2, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) y := rand.Intn(1099) @@ -2487,12 +2565,12 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from thash where a in(%v, %v, %v) group by a;", x, y, z) queryRegular3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular1 where a in(%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition3, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition3, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition3).Sort().Check(tk.MustQuery(queryRegular3).Sort().Rows()) queryPartition4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from thash where a in (%v, %v, %v) group by a;", x, y, z) queryRegular4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular1 where a in (%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition4, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition4, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition4).Sort().Check(tk.MustQuery(queryRegular4).Sort().Rows()) } @@ -2506,12 +2584,12 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tlist where a > %v group by a;", x) queryRegular1 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular2 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition1, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tlist where a > %v group by a;", x) queryRegular2 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular2 where a > %v group by a;", x) - c.Assert(tk.HasPlan(queryPartition2, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) y := rand.Intn(12) + 1 @@ -2519,18 +2597,22 @@ func (s *partitionTableSuite) TestDirectReadingWithAgg(c *C) { queryPartition3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tlist where a in(%v, %v, %v) group by a;", x, y, z) queryRegular3 := fmt.Sprintf("select /*+ stream_agg() */ count(*), sum(b), max(b), a from tregular2 where a in(%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition3, "StreamAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition3, "StreamAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition3).Sort().Check(tk.MustQuery(queryRegular3).Sort().Rows()) queryPartition4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tlist where a in (%v, %v, %v) group by a;", x, y, z) queryRegular4 := fmt.Sprintf("select /*+ hash_agg() */ count(*), sum(b), max(b), a from tregular2 where a in (%v, %v, %v) group by a;", x, y, z) - c.Assert(tk.HasPlan(queryPartition4, "HashAgg"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition4, "HashAgg")) // check if IndexLookUp is used tk.MustQuery(queryPartition4).Sort().Check(tk.MustQuery(queryRegular4).Sort().Rows()) } } -func (s *partitionTableSuite) TestDynamicModeByDefault(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestDynamicModeByDefault(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_dynamic_by_default") tk.MustExec(`create table trange(a int, b int, primary key(a) clustered, index idx_b(b)) partition by range(a) ( @@ -2544,13 +2626,17 @@ func (s *partitionTableSuite) TestDynamicModeByDefault(c *C) { "explain select * from thash where a>=100", } { for _, r := range tk.MustQuery(q).Rows() { - c.Assert(strings.Contains(strings.ToLower(r[0].(string)), "partitionunion"), IsFalse) + require.NotContains(t, strings.ToLower(r[0].(string)), "partitionunion") } } } -func (s *partitionTableSuite) TestIssue24636(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue24636(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_issue_24636") tk.MustExec("use test_issue_24636") @@ -2585,12 +2671,12 @@ func (s *partitionTableSuite) TestIssue24636(c *C) { tk.MustQuery(`select c,j,l from test_partition where c='428ff6a1-bb37-42ac-9883-33d7a29961e6' and a='aaa' limit 0, 200`).Check(testkit.Rows("428ff6a1-bb37-42ac-9883-33d7a29961e6 9 0")) } -func (s *partitionTableSuite) TestIdexMerge(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } +func TestIdexMerge(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() - tk := testkit.NewTestKitWithInit(c, s.store) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_idx_merge") tk.MustExec("use test_idx_merge") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2639,12 +2725,12 @@ func (s *partitionTableSuite) TestIdexMerge(c *C) { queryPartition1 := fmt.Sprintf("select /*+ use_index_merge(trange) */ * from trange where a > %v or b < %v;", x1, x2) queryRegular1 := fmt.Sprintf("select /*+ use_index_merge(tregular1) */ * from tregular1 where a > %v or b < %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition1, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ use_index_merge(trange) */ * from trange where a > %v or b > %v;", x1, x2) queryRegular2 := fmt.Sprintf("select /*+ use_index_merge(tregular1) */ * from tregular1 where a > %v or b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition2, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) } @@ -2655,12 +2741,12 @@ func (s *partitionTableSuite) TestIdexMerge(c *C) { queryPartition1 := fmt.Sprintf("select /*+ use_index_merge(thash) */ * from thash where a > %v or b < %v;", x1, x2) queryRegular1 := fmt.Sprintf("select /*+ use_index_merge(tregualr1) */ * from tregular1 where a > %v or b < %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition1, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ use_index_merge(thash) */ * from thash where a > %v or b > %v;", x1, x2) queryRegular2 := fmt.Sprintf("select /*+ use_index_merge(tregular1) */ * from tregular1 where a > %v or b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition2, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) } @@ -2670,18 +2756,22 @@ func (s *partitionTableSuite) TestIdexMerge(c *C) { x2 := rand.Intn(12) + 1 queryPartition1 := fmt.Sprintf("select /*+ use_index_merge(tlist) */ * from tlist where a > %v or b < %v;", x1, x2) queryRegular1 := fmt.Sprintf("select /*+ use_index_merge(tregular2) */ * from tregular2 where a > %v or b < %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition1, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition1, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition1).Sort().Check(tk.MustQuery(queryRegular1).Sort().Rows()) queryPartition2 := fmt.Sprintf("select /*+ use_index_merge(tlist) */ * from tlist where a > %v or b > %v;", x1, x2) queryRegular2 := fmt.Sprintf("select /*+ use_index_merge(tregular2) */ * from tregular2 where a > %v or b > %v;", x1, x2) - c.Assert(tk.HasPlan(queryPartition2, "IndexMerge"), IsTrue) // check if IndexLookUp is used + require.True(t, tk.HasPlan(queryPartition2, "IndexMerge")) // check if IndexLookUp is used tk.MustQuery(queryPartition2).Sort().Check(tk.MustQuery(queryRegular2).Sort().Rows()) } } -func (s *partitionTableSuite) TestIssue25309(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue25309(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create database test_issue_25309") tk.MustExec("use test_issue_25309") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -2716,8 +2806,17 @@ func (s *partitionTableSuite) TestIssue25309(c *C) { tk.MustQuery(`select tbl_5.* from tbl_500 tbl_5 where col_24 in ( select col_62 from tbl_600 where tbl_5.col_26 < 'hSvHLdQeGBNIyOFXStV' )`).Check(testkit.Rows()) } -func (s *globalIndexSuite) TestGlobalIndexScan(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestGlobalIndexScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + restoreConfig := config.RestoreFunc() + defer restoreConfig() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableGlobalIndex = true + }) + tk.MustExec("use test") tk.MustExec("drop table if exists p") tk.MustExec(`create table p (id int, c int) partition by range (c) ( partition p0 values less than (4), @@ -2728,8 +2827,17 @@ partition p2 values less than (10))`) tk.MustQuery("select id from p use index (idx)").Check(testkit.Rows("1", "3", "5", "7")) } -func (s *globalIndexSuite) TestGlobalIndexDoubleRead(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestGlobalIndexDoubleRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + restoreConfig := config.RestoreFunc() + defer restoreConfig() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableGlobalIndex = true + }) + tk.MustExec("use test") tk.MustExec("drop table if exists p") tk.MustExec(`create table p (id int, c int) partition by range (c) ( partition p0 values less than (4), @@ -2737,11 +2845,14 @@ partition p1 values less than (7), partition p2 values less than (10))`) tk.MustExec("alter table p add unique idx(id)") tk.MustExec("insert into p values (1,3), (3,4), (5,6), (7,9)") - tk.MustQuery("select * from p use index (idx)").Check(testkit.Rows("1 3", "3 4", "5 6", "7 9")) + tk.MustQuery("select * from p use index (idx)").Sort().Check(testkit.Rows("1 3", "3 4", "5 6", "7 9")) } -func (s *partitionTableSuite) TestIssue20028(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20028(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("set @@tidb_partition_prune_mode='static-only'") @@ -2767,8 +2878,11 @@ partition p3 values less than maxvalue)`) tk.MustExec("rollback") } -func (s *partitionTableSuite) TestSelectLockOnPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectLockOnPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists pt") tk.MustExec(`create table pt (id int primary key, k int, c int, index(k)) @@ -2777,7 +2891,7 @@ partition p0 values less than (4), partition p1 values less than (7), partition p2 values less than (11))`) - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") optimisticTableReader := func() { @@ -2787,7 +2901,7 @@ partition p2 values less than (11))`) tk.MustQuery("select id, k from pt ignore index (k) where k = 5 for update").Check(testkit.Rows("5 5")) tk2.MustExec("update pt set c = c + 1 where k = 5") _, err := tk.Exec("commit") - c.Assert(err, NotNil) // Write conflict + require.Error(t, err) // Write conflict } optimisticIndexReader := func() { @@ -2798,7 +2912,7 @@ partition p2 values less than (11))`) tk.MustQuery("select k from pt where k = 5 for update").Check(testkit.Rows("5")) tk2.MustExec("update pt set c = c + 1 where k = 5") _, err := tk.Exec("commit") - c.Assert(err, NotNil) + require.Error(t, err) } optimisticIndexLookUp := func() { @@ -2808,7 +2922,7 @@ partition p2 values less than (11))`) tk.MustQuery("select c, k from pt use index (k) where k = 5 for update").Check(testkit.Rows("5 5")) tk2.MustExec("update pt set c = c + 1 where k = 5") _, err := tk.Exec("commit") - c.Assert(err, NotNil) + require.Error(t, err) } pessimisticTableReader := func() { @@ -2826,7 +2940,7 @@ partition p2 values less than (11))`) // Check the operation in the goroutine is blocked, if not the first result in // the channel should be 1. - c.Assert(<-ch, Equals, 2) + require.Equal(t, 2, <-ch) tk.MustExec("commit") <-ch @@ -2848,7 +2962,7 @@ partition p2 values less than (11))`) ch <- 2 // Check the operation in the goroutine is blocked, - c.Assert(<-ch, Equals, 2) + require.Equal(t, 2, <-ch) tk.MustExec("commit") <-ch @@ -2869,7 +2983,7 @@ partition p2 values less than (11))`) ch <- 2 // Check the operation in the goroutine is blocked, - c.Assert(<-ch, Equals, 2) + require.Equal(t, 2, <-ch) tk.MustExec("commit") <-ch @@ -2877,8 +2991,8 @@ partition p2 values less than (11))`) } partitionModes := []string{ - "'dynamic-only'", - "'static-only'", + "'dynamic'", + "'static'", } testCases := []func(){ optimisticTableReader, @@ -2898,8 +3012,12 @@ partition p2 values less than (11))`) } } -func (s *globalIndexSuite) TestIssue21731(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue21731(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists p, t") tk.MustExec("create table t (a int, b int, unique index idx(a)) partition by list columns(b) (partition p0 values in (1), partition p1 values in (2));") } @@ -2910,17 +3028,17 @@ type testOutput struct { Res []string } -func (s *testSuiteWithData) verifyPartitionResult(tk *testkit.TestKit, input []string, output []testOutput) { +func verifyPartitionResult(tk *testkit.TestKit, input []string, output []testOutput) { for i, tt := range input { var isSelect = false if strings.HasPrefix(strings.ToLower(tt), "select ") { isSelect = true } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt if isSelect { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.UsedPartitions(tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.UsedPartitions(tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) } else { // Just verify SELECT (also avoid double INSERTs during record) output[i].Res = nil @@ -2936,8 +3054,11 @@ func (s *testSuiteWithData) verifyPartitionResult(tk *testkit.TestKit, input []s } } -func (s *testSuiteWithData) TestRangePartitionBoundariesEq(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesEq(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("SET @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("CREATE DATABASE TestRangePartitionBoundaries") @@ -2954,12 +3075,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *testSuiteWithData) TestRangePartitionBoundariesNe(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesNe(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("SET @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("CREATE DATABASE TestRangePartitionBoundariesNe") @@ -2979,12 +3103,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *testSuiteWithData) TestRangePartitionBoundariesBetweenM(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesBetweenM(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE IF NOT EXISTS TestRangePartitionBoundariesBetweenM") defer tk.MustExec("DROP DATABASE TestRangePartitionBoundariesBetweenM") @@ -2999,13 +3126,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *testSuiteWithData) TestRangePartitionBoundariesBetweenS(c *C) { - c.Skip("unstable, skip it and fix it before 20210624") - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesBetweenS(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE IF NOT EXISTS TestRangePartitionBoundariesBetweenS") defer tk.MustExec("DROP DATABASE TestRangePartitionBoundariesBetweenS") @@ -3024,12 +3153,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *testSuiteWithData) TestRangePartitionBoundariesLtM(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesLtM(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("create database TestRangePartitionBoundariesLtM") @@ -3045,12 +3177,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *testSuiteWithData) TestRangePartitionBoundariesLtS(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionBoundariesLtS(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("create database TestRangePartitionBoundariesLtS") @@ -3070,12 +3205,15 @@ PARTITION BY RANGE (a) ( var input []string var output []testOutput - s.testData.GetTestCases(c, &input, &output) - s.verifyPartitionResult(tk, input, output) + executorSuiteData.GetTestCases(t, &input, &output) + verifyPartitionResult(tk, input, output) } -func (s *partitionTableSuite) TestIssue25528(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue25528(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode = 'static'") tk.MustExec("use test") tk.MustExec("create table issue25528 (id int primary key, balance DECIMAL(10, 2), balance2 DECIMAL(10, 2) GENERATED ALWAYS AS (-balance) VIRTUAL, created_at TIMESTAMP) PARTITION BY HASH(id) PARTITIONS 8") @@ -3089,15 +3227,23 @@ func (s *partitionTableSuite) TestIssue25528(c *C) { tk.MustQuery("select * from issue25528 where c1 in (3, 4) order by c2 for update;").Check(testkit.Rows("3 3 3 3", "4 4 4 4")) } -func (s *partitionTableSuite) TestIssue26251(c *C) { - tk1 := testkit.NewTestKit(c, s.store) +func TestIssue26251(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + restoreConfig := config.RestoreFunc() + defer restoreConfig() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableGlobalIndex = true + }) tk1.MustExec("use test") tk1.MustExec("create table tp (id int primary key) partition by range (id) (partition p0 values less than (100));") tk1.MustExec("create table tn (id int primary key);") tk1.MustExec("insert into tp values(1),(2);") tk1.MustExec("insert into tn values(1),(2);") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") tk1.MustExec("begin pessimistic") @@ -3117,6 +3263,339 @@ func (s *partitionTableSuite) TestIssue26251(c *C) { tk1.MustExec("rollback") case <-ch: // Unexpected, test fail. - c.Fail() + t.Fail() + } + + // Clean up + <-ch + tk2.MustExec("rollback") +} + +func TestLeftJoinForUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("create database TestLeftJoinForUpdate") + defer tk1.MustExec("drop database TestLeftJoinForUpdate") + tk1.MustExec("use TestLeftJoinForUpdate") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use TestLeftJoinForUpdate") + tk3 := testkit.NewTestKit(t, store) + tk3.MustExec("use TestLeftJoinForUpdate") + + tk1.MustExec("drop table if exists nt, pt") + tk1.MustExec("create table nt (id int, col varchar(32), primary key (id))") + tk1.MustExec("create table pt (id int, col varchar(32), primary key (id)) partition by hash(id) partitions 4") + + resetData := func() { + tk1.MustExec("truncate table nt") + tk1.MustExec("truncate table pt") + tk1.MustExec("insert into nt values (1, 'hello')") + tk1.MustExec("insert into pt values (2, 'test')") + } + + // ========================== First round of test ================== + // partition table left join normal table. + // ================================================================= + resetData() + ch := make(chan int, 10) + tk1.MustExec("begin pessimistic") + // No union scan + tk1.MustQuery("select * from pt left join nt on pt.id = nt.id for update").Check(testkit.Rows("2 test ")) + go func() { + // Check the key is locked. + tk2.MustExec("update pt set col = 'xxx' where id = 2") + ch <- 2 + }() + + // Union scan + tk1.MustExec("insert into pt values (1, 'world')") + tk1.MustQuery("select * from pt left join nt on pt.id = nt.id for update").Sort().Check(testkit.Rows("1 world 1 hello", "2 test ")) + go func() { + // Check the key is locked. + tk3.MustExec("update nt set col = 'yyy' where id = 1") + ch <- 3 + }() + + // Give chance for the goroutines to run first. + time.Sleep(80 * time.Millisecond) + ch <- 1 + tk1.MustExec("rollback") + + checkOrder := func() { + require.Equal(t, <-ch, 1) + v1 := <-ch + v2 := <-ch + require.True(t, (v1 == 2 && v2 == 3) || (v1 == 3 && v2 == 2)) } + checkOrder() + + // ========================== Another round of test ================== + // normal table left join partition table. + // =================================================================== + resetData() + tk1.MustExec("begin pessimistic") + // No union scan + tk1.MustQuery("select * from nt left join pt on pt.id = nt.id for update").Check(testkit.Rows("1 hello ")) + + // Union scan + tk1.MustExec("insert into pt values (1, 'world')") + tk1.MustQuery("select * from nt left join pt on pt.id = nt.id for update").Check(testkit.Rows("1 hello 1 world")) + go func() { + tk2.MustExec("replace into pt values (1, 'aaa')") + ch <- 2 + }() + go func() { + tk3.MustExec("update nt set col = 'bbb' where id = 1") + ch <- 3 + }() + time.Sleep(80 * time.Millisecond) + ch <- 1 + tk1.MustExec("rollback") + checkOrder() +} + +func TestIssue31024(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("create database TestIssue31024") + defer tk1.MustExec("drop database TestIssue31024") + tk1.MustExec("use TestIssue31024") + tk1.MustExec("create table t1 (c_datetime datetime, c1 int, c2 int, primary key (c_datetime), key(c1), key(c2))" + + " partition by range (to_days(c_datetime)) " + + "( partition p0 values less than (to_days('2020-02-01'))," + + " partition p1 values less than (to_days('2020-04-01'))," + + " partition p2 values less than (to_days('2020-06-01'))," + + " partition p3 values less than maxvalue)") + tk1.MustExec("create table t2 (c_datetime datetime, unique key(c_datetime))") + tk1.MustExec("insert into t1 values ('2020-06-26 03:24:00', 1, 1), ('2020-02-21 07:15:33', 2, 2), ('2020-04-27 13:50:58', 3, 3)") + tk1.MustExec("insert into t2 values ('2020-01-10 09:36:00'), ('2020-02-04 06:00:00'), ('2020-06-12 03:45:18')") + tk1.MustExec("SET GLOBAL tidb_txn_mode = 'pessimistic'") + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use TestIssue31024") + + ch := make(chan int, 10) + tk1.MustExec("set @@tidb_partition_prune_mode='dynamic'") + tk1.MustExec("begin pessimistic") + tk1.MustQuery("select /*+ use_index_merge(t1) */ * from t1 join t2 on t1.c_datetime >= t2.c_datetime where t1.c1 < 10 or t1.c2 < 10 for update") + + go func() { + // Check the key is locked. + tk2.MustExec("set @@tidb_partition_prune_mode='dynamic'") + tk2.MustExec("begin pessimistic") + tk2.MustExec("update t1 set c_datetime = '2020-06-26 03:24:00' where c1 = 1") + ch <- 2 + }() + + // Give chance for the goroutines to run first. + time.Sleep(80 * time.Millisecond) + ch <- 1 + tk1.MustExec("rollback") + + require.Equal(t, <-ch, 1) + require.Equal(t, <-ch, 2) + + tk2.MustExec("rollback") +} + +func TestIssue27346(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("create database TestIssue27346") + defer tk1.MustExec("drop database TestIssue27346") + tk1.MustExec("use TestIssue27346") + + tk1.MustExec("set @@tidb_enable_index_merge=1,@@tidb_partition_prune_mode='dynamic'") + + tk1.MustExec("DROP TABLE IF EXISTS `tbl_18`") + tk1.MustExec("CREATE TABLE `tbl_18` (`col_119` binary(16) NOT NULL DEFAULT 'skPoKiwYUi',`col_120` int(10) unsigned NOT NULL,`col_121` timestamp NOT NULL,`col_122` double NOT NULL DEFAULT '3937.1887880628115',`col_123` bigint(20) NOT NULL DEFAULT '3550098074891542725',PRIMARY KEY (`col_123`,`col_121`,`col_122`,`col_120`) CLUSTERED,UNIQUE KEY `idx_103` (`col_123`,`col_119`,`col_120`),UNIQUE KEY `idx_104` (`col_122`,`col_120`),UNIQUE KEY `idx_105` (`col_119`,`col_120`),KEY `idx_106` (`col_121`,`col_120`,`col_122`,`col_119`),KEY `idx_107` (`col_121`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci PARTITION BY HASH( `col_120` ) PARTITIONS 3") + tk1.MustExec("INSERT INTO tbl_18 (`col_119`, `col_120`, `col_121`, `col_122`, `col_123`) VALUES (X'736b506f4b6977595569000000000000', 672436701, '1974-02-24 00:00:00', 3937.1887880628115e0, -7373106839136381229), (X'736b506f4b6977595569000000000000', 2637316689, '1993-10-29 00:00:00', 3937.1887880628115e0, -4522626077860026631), (X'736b506f4b6977595569000000000000', 831809724, '1995-11-20 00:00:00', 3937.1887880628115e0, -4426441253940231780), (X'736b506f4b6977595569000000000000', 1588592628, '2001-03-28 00:00:00', 3937.1887880628115e0, 1329207475772244999), (X'736b506f4b6977595569000000000000', 3908038471, '2031-06-06 00:00:00', 3937.1887880628115e0, -6562815696723135786), (X'736b506f4b6977595569000000000000', 1674237178, '2001-10-24 00:00:00', 3937.1887880628115e0, -6459065549188938772), (X'736b506f4b6977595569000000000000', 3507075493, '2010-03-25 00:00:00', 3937.1887880628115e0, -4329597025765326929), (X'736b506f4b6977595569000000000000', 1276461709, '2019-07-20 00:00:00', 3937.1887880628115e0, 3550098074891542725)") + + tk1.MustQuery("select col_120,col_122,col_123 from tbl_18 where tbl_18.col_122 = 4763.320888074281 and not( tbl_18.col_121 in ( '2032-11-01' , '1975-05-21' , '1994-05-16' , '1984-01-15' ) ) or not( tbl_18.col_121 >= '2008-10-24' ) order by tbl_18.col_119,tbl_18.col_120,tbl_18.col_121,tbl_18.col_122,tbl_18.col_123 limit 919 for update").Sort().Check(testkit.Rows( + "1588592628 3937.1887880628115 1329207475772244999", + "1674237178 3937.1887880628115 -6459065549188938772", + "2637316689 3937.1887880628115 -4522626077860026631", + "672436701 3937.1887880628115 -7373106839136381229", + "831809724 3937.1887880628115 -4426441253940231780")) + tk1.MustQuery("select /*+ use_index_merge( tbl_18 ) */ col_120,col_122,col_123 from tbl_18 where tbl_18.col_122 = 4763.320888074281 and not( tbl_18.col_121 in ( '2032-11-01' , '1975-05-21' , '1994-05-16' , '1984-01-15' ) ) or not( tbl_18.col_121 >= '2008-10-24' ) order by tbl_18.col_119,tbl_18.col_120,tbl_18.col_121,tbl_18.col_122,tbl_18.col_123 limit 919 for update").Sort().Check(testkit.Rows( + "1588592628 3937.1887880628115 1329207475772244999", + "1674237178 3937.1887880628115 -6459065549188938772", + "2637316689 3937.1887880628115 -4522626077860026631", + "672436701 3937.1887880628115 -7373106839136381229", + "831809724 3937.1887880628115 -4426441253940231780")) +} + +func TestPartitionTableExplain(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database TestPartitionTableExplain") + tk.MustExec("use TestPartitionTableExplain") + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec(`create table t (a int primary key, b int, key (b)) partition by hash(a) (partition P0, partition p1, partition P2)`) + tk.MustExec(`create table t2 (a int, b int)`) + tk.MustExec(`insert into t values (1,1),(2,2),(3,3)`) + tk.MustExec(`insert into t2 values (1,1),(2,2),(3,3)`) + tk.MustExec(`analyze table t`) + tk.MustExec(`analyze table t2`) + tk.MustQuery(`explain format = 'brief' select * from t`).Check(testkit.Rows( + "PartitionUnion 3.00 root ", + "├─TableReader 1.00 root data:TableFullScan", + "│ └─TableFullScan 1.00 cop[tikv] table:t, partition:P0 keep order:false", + "├─TableReader 1.00 root data:TableFullScan", + "│ └─TableFullScan 1.00 cop[tikv] table:t, partition:p1 keep order:false", + "└─TableReader 1.00 root data:TableFullScan", + " └─TableFullScan 1.00 cop[tikv] table:t, partition:P2 keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition(P0,p1)`).Check(testkit.Rows( + "PartitionUnion 2.00 root ", + "├─TableReader 1.00 root data:TableFullScan", + "│ └─TableFullScan 1.00 cop[tikv] table:t, partition:P0 keep order:false", + "└─TableReader 1.00 root data:TableFullScan", + " └─TableFullScan 1.00 cop[tikv] table:t, partition:p1 keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a = 1`).Check(testkit.Rows("Point_Get 1.00 root table:t, partition:p1 handle:1")) + tk.MustQuery(`explain format = 'brief' select * from t where a = 2`).Check(testkit.Rows("Point_Get 1.00 root table:t, partition:P2 handle:2")) + // above ^^ is enough for Issue32719, the below vv for completeness + tk.MustQuery(`explain format = 'brief' select * from t where a = 1 OR a = 2`).Check(testkit.Rows( + "PartitionUnion 2.00 root ", + "├─Batch_Point_Get 1.00 root table:t handle:[1 2], keep order:false, desc:false", + "└─Batch_Point_Get 1.00 root table:t handle:[1 2], keep order:false, desc:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a IN (2,3,4)`).Check(testkit.Rows("Batch_Point_Get 3.00 root table:t handle:[2 3 4], keep order:false, desc:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a IN (2,3)`).Check(testkit.Rows("Batch_Point_Get 2.00 root table:t handle:[2 3], keep order:false, desc:false")) + // above ^^ is for completeness, the below vv is enough for Issue32719 + tk.MustQuery(`explain format = 'brief' select * from t where b = 1`).Check(testkit.Rows( + "PartitionUnion 1.00 root ", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) range:[1,1], keep order:false", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range:[1,1], keep order:false", + "└─IndexReader 1.00 root index:IndexRangeScan", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) range:[1,1], keep order:false")) + // The below vvv is for completeness + tk.MustQuery(`explain format = 'brief' select * from t where b = 2`).Check(testkit.Rows( + "PartitionUnion 1.00 root ", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) range:[2,2], keep order:false", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range:[2,2], keep order:false", + "└─IndexReader 1.00 root index:IndexRangeScan", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) range:[2,2], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b = 1 OR b = 2`).Check(testkit.Rows( + "PartitionUnion 2.00 root ", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) range:[1,2], keep order:false", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range:[1,2], keep order:false", + "└─IndexReader 1.00 root index:IndexRangeScan", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) range:[1,2], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b IN (2,3,4)`).Check(testkit.Rows( + "PartitionUnion 2.00 root ", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) range:[2,2], [3,3], [4,4], keep order:false", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range:[2,2], [3,3], [4,4], keep order:false", + "└─IndexReader 1.00 root index:IndexRangeScan", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) range:[2,2], [3,3], [4,4], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b IN (2,3)`).Check(testkit.Rows( + "PartitionUnion 2.00 root ", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) range:[2,2], [3,3], keep order:false", + "├─IndexReader 1.00 root index:IndexRangeScan", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range:[2,2], [3,3], keep order:false", + "└─IndexReader 1.00 root index:IndexRangeScan", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) range:[2,2], [3,3], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t,t2 where t2.a = 1 and t2.b = t.b`).Check(testkit.Rows( + "Projection 1.00 root testpartitiontableexplain.t.a, testpartitiontableexplain.t.b, testpartitiontableexplain.t2.a, testpartitiontableexplain.t2.b", + "└─HashJoin 1.00 root inner join, equal:[eq(testpartitiontableexplain.t2.b, testpartitiontableexplain.t.b)]", + " ├─TableReader(Build) 1.00 root data:Selection", + " │ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + " │ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + " └─PartitionUnion(Probe) 3.00 root ", + " ├─IndexReader 1.00 root index:IndexFullScan", + " │ └─IndexFullScan 1.00 cop[tikv] table:t, partition:P0, index:b(b) keep order:false", + " ├─IndexReader 1.00 root index:IndexFullScan", + " │ └─IndexFullScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) keep order:false", + " └─IndexReader 1.00 root index:IndexFullScan", + " └─IndexFullScan 1.00 cop[tikv] table:t, partition:P2, index:b(b) keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition (p1),t2 where t2.a = 1 and t2.b = t.b`).Check(testkit.Rows( + "IndexJoin 1.00 root inner join, inner:IndexReader, outer key:testpartitiontableexplain.t2.b, inner key:testpartitiontableexplain.t.b, equal cond:eq(testpartitiontableexplain.t2.b, testpartitiontableexplain.t.b)", + "├─TableReader(Build) 1.00 root data:Selection", + "│ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + "│ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + "└─IndexReader(Probe) 1.00 root index:Selection", + " └─Selection 1.00 cop[tikv] not(isnull(testpartitiontableexplain.t.b))", + " └─IndexRangeScan 1.00 cop[tikv] table:t, partition:p1, index:b(b) range: decided by [eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t,t2 where t2.a = 1 and t2.b = t.b and t.a = 1`).Check(testkit.Rows( + "HashJoin 1.00 root inner join, equal:[eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)]", + "├─TableReader(Build) 1.00 root data:Selection", + "│ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + "│ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + "└─Selection(Probe) 1.00 root not(isnull(testpartitiontableexplain.t.b))", + " └─Point_Get 1.00 root table:t, partition:p1 handle:1")) + + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + tk.MustExec(`analyze table t`) + tk.MustQuery(`explain format = 'brief' select * from t`).Check(testkit.Rows( + "TableReader 3.00 root partition:all data:TableFullScan", + "└─TableFullScan 3.00 cop[tikv] table:t keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition(P0,p1)`).Check(testkit.Rows( + "TableReader 3.00 root partition:P0,p1 data:TableFullScan", + "└─TableFullScan 3.00 cop[tikv] table:t keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a = 1`).Check(testkit.Rows("Point_Get 1.00 root table:t, partition:p1 handle:1")) + tk.MustQuery(`explain format = 'brief' select * from t where a = 2`).Check(testkit.Rows("Point_Get 1.00 root table:t, partition:P2 handle:2")) + tk.MustQuery(`explain format = 'brief' select * from t where a = 1 OR a = 2`).Check(testkit.Rows( + "TableReader 2.00 root partition:p1,P2 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:t range:[1,1], [2,2], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a IN (2,3,4)`).Check(testkit.Rows("Batch_Point_Get 3.00 root table:t handle:[2 3 4], keep order:false, desc:false")) + tk.MustQuery(`explain format = 'brief' select * from t where a IN (2,3)`).Check(testkit.Rows("Batch_Point_Get 2.00 root table:t handle:[2 3], keep order:false, desc:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b = 1`).Check(testkit.Rows( + "IndexReader 1.00 root partition:all index:IndexRangeScan", + "└─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition (P0,p1) where b = 1`).Check(testkit.Rows( + "IndexReader 1.00 root partition:P0,p1 index:IndexRangeScan", + "└─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b = 1 OR b = 2`).Check(testkit.Rows( + "IndexReader 2.00 root partition:all index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t, index:b(b) range:[1,2], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition (p1,P2) where b = 1 OR b = 2`).Check(testkit.Rows( + "IndexReader 2.00 root partition:p1,P2 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t, index:b(b) range:[1,2], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b IN (2,3,4)`).Check(testkit.Rows( + "IndexReader 2.00 root partition:all index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t, index:b(b) range:[2,2], [3,3], [4,4], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t where b IN (2,3)`).Check(testkit.Rows( + "IndexReader 2.00 root partition:all index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t, index:b(b) range:[2,2], [3,3], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t,t2 where t2.a = 1 and t2.b = t.b`).Check(testkit.Rows( + "Projection 1.00 root testpartitiontableexplain.t.a, testpartitiontableexplain.t.b, testpartitiontableexplain.t2.a, testpartitiontableexplain.t2.b", + "└─IndexJoin 1.00 root inner join, inner:IndexReader, outer key:testpartitiontableexplain.t2.b, inner key:testpartitiontableexplain.t.b, equal cond:eq(testpartitiontableexplain.t2.b, testpartitiontableexplain.t.b)", + " ├─TableReader(Build) 1.00 root data:Selection", + " │ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + " │ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + " └─IndexReader(Probe) 1.00 root partition:all index:Selection", + " └─Selection 1.00 cop[tikv] not(isnull(testpartitiontableexplain.t.b))", + " └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range: decided by [eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t partition (p1),t2 where t2.a = 1 and t2.b = t.b`).Check(testkit.Rows( + "Projection 1.00 root testpartitiontableexplain.t.a, testpartitiontableexplain.t.b, testpartitiontableexplain.t2.a, testpartitiontableexplain.t2.b", + "└─IndexJoin 1.00 root inner join, inner:IndexReader, outer key:testpartitiontableexplain.t2.b, inner key:testpartitiontableexplain.t.b, equal cond:eq(testpartitiontableexplain.t2.b, testpartitiontableexplain.t.b)", + " ├─TableReader(Build) 1.00 root data:Selection", + " │ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + " │ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + " └─IndexReader(Probe) 1.00 root partition:p1 index:Selection", + " └─Selection 1.00 cop[tikv] not(isnull(testpartitiontableexplain.t.b))", + " └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range: decided by [eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)], keep order:false")) + tk.MustQuery(`explain format = 'brief' select * from t,t2 where t2.a = 1 and t2.b = t.b and t.a = 1`).Check(testkit.Rows( + "HashJoin 1.00 root inner join, equal:[eq(testpartitiontableexplain.t.b, testpartitiontableexplain.t2.b)]", + "├─TableReader(Build) 1.00 root data:Selection", + "│ └─Selection 1.00 cop[tikv] eq(testpartitiontableexplain.t2.a, 1), not(isnull(testpartitiontableexplain.t2.b))", + "│ └─TableFullScan 3.00 cop[tikv] table:t2 keep order:false", + "└─TableReader(Probe) 1.00 root partition:p1 data:Selection", + " └─Selection 1.00 cop[tikv] not(isnull(testpartitiontableexplain.t.b))", + " └─TableRangeScan 1.00 cop[tikv] table:t range:[1,1], keep order:false")) } diff --git a/executor/pkg_test.go b/executor/pkg_test.go index 71cfec7ed9c1f..48c9678991d9b 100644 --- a/executor/pkg_test.go +++ b/executor/pkg_test.go @@ -17,8 +17,8 @@ package executor import ( "context" "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" @@ -26,18 +26,10 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = Suite(&pkgTestSuite{}) -var _ = SerialSuites(&pkgTestSerialSuite{}) - -type pkgTestSuite struct { -} - -type pkgTestSerialSuite struct { -} - -func (s *pkgTestSuite) TestNestedLoopApply(c *C) { +func TestNestedLoopApply(t *testing.T) { ctx := context.Background() sctx := mock.NewContext() col0 := &expression.Column{Index: 0, RetType: types.NewFieldType(mysql.TypeLong)} @@ -88,20 +80,20 @@ func (s *pkgTestSuite) TestNestedLoopApply(c *C) { it := chunk.NewIterator4Chunk(joinChk) for rowIdx := 1; ; { err := join.Next(ctx, joinChk) - c.Check(err, IsNil) + require.NoError(t, err) if joinChk.NumRows() == 0 { break } for row := it.Begin(); row != it.End(); row = it.Next() { correctResult := fmt.Sprintf("%v %v", rowIdx, rowIdx) obtainedResult := fmt.Sprintf("%v %v", row.GetInt64(0), row.GetInt64(1)) - c.Check(obtainedResult, Equals, correctResult) + require.Equal(t, correctResult, obtainedResult) rowIdx++ } } } -func (s *pkgTestSuite) TestMoveInfoSchemaToFront(c *C) { +func TestMoveInfoSchemaToFront(t *testing.T) { dbss := [][]string{ {}, {"A", "B", "C", "a", "b", "c"}, @@ -124,9 +116,9 @@ func (s *pkgTestSuite) TestMoveInfoSchemaToFront(c *C) { } for i, dbs := range wanted { - c.Check(len(dbss[i]), Equals, len(dbs)) + require.Equal(t, len(dbs), len(dbss[i])) for j, db := range dbs { - c.Check(dbss[i][j], Equals, db) + require.Equal(t, db, dbss[i][j]) } } } diff --git a/executor/plan_replayer.go b/executor/plan_replayer.go index ab3261e6ca6c0..22520d5d3b722 100644 --- a/executor/plan_replayer.go +++ b/executor/plan_replayer.go @@ -119,9 +119,9 @@ func (e *PlanReplayerSingleExec) Next(ctx context.Context, req *chunk.Chunk) err // |_explain // |-explain.txt // -func (e *PlanReplayerSingleExec) dumpSingle(path string) (string, error) { +func (e *PlanReplayerSingleExec) dumpSingle(path string) (fileName string, err error) { // Create path - err := os.MkdirAll(path, os.ModePerm) + err = os.MkdirAll(path, os.ModePerm) if err != nil { return "", errors.AddStack(err) } @@ -134,7 +134,7 @@ func (e *PlanReplayerSingleExec) dumpSingle(path string) (string, error) { return "", err } key := base64.URLEncoding.EncodeToString(b) - fileName := fmt.Sprintf("replayer_single_%v_%v.zip", key, time) + fileName = fmt.Sprintf("replayer_single_%v_%v.zip", key, time) zf, err := os.Create(filepath.Join(path, fileName)) if err != nil { return "", errors.AddStack(err) @@ -143,13 +143,13 @@ func (e *PlanReplayerSingleExec) dumpSingle(path string) (string, error) { // Create zip writer zw := zip.NewWriter(zf) defer func() { - err := zw.Close() + err = zw.Close() if err != nil { - logutil.BgLogger().Warn("Closing zip writer failed", zap.Error(err)) + logutil.BgLogger().Error("Closing zip writer failed", zap.Error(err), zap.String("filename", fileName)) } err = zf.Close() if err != nil { - logutil.BgLogger().Warn("Closing zip file failed", zap.Error(err)) + logutil.BgLogger().Error("Closing zip file failed", zap.Error(err), zap.String("filename", fileName)) } }() diff --git a/executor/point_get.go b/executor/point_get.go index 45f3fa76e263f..65ce73d840172 100644 --- a/executor/point_get.go +++ b/executor/point_get.go @@ -21,7 +21,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/metapb" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/ddl/placement" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" @@ -37,7 +36,9 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/execdetails" + "github.com/pingcap/tidb/util/logutil/consistency" "github.com/pingcap/tidb/util/rowcodec" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" ) @@ -155,6 +156,9 @@ func (e *PointGetExecutor) Open(context.Context) error { } else { e.snapshot = e.ctx.GetSnapshotWithTS(snapshotTS) } + if e.ctx.GetSessionVars().StmtCtx.RCCheckTS { + e.snapshot.SetOption(kv.IsolationLevel, kv.RCCheckTS) + } if e.cacheTable != nil { e.snapshot = cacheTableSnapshot{e.snapshot, e.cacheTable} } @@ -170,7 +174,7 @@ func (e *PointGetExecutor) Open(context.Context) error { e.ctx.GetSessionVars().StmtCtx.RuntimeStatsColl.RegisterStats(e.id, e.stats) } readReplicaType := e.ctx.GetSessionVars().GetReplicaRead() - if readReplicaType.IsFollowerRead() { + if readReplicaType.IsFollowerRead() && !e.ctx.GetSessionVars().StmtCtx.RCCheckTS { e.snapshot.SetOption(kv.ReplicaRead, readReplicaType) } e.snapshot.SetOption(kv.TaskID, e.ctx.GetSessionVars().StmtCtx.TaskID) @@ -191,6 +195,7 @@ func (e *PointGetExecutor) Open(context.Context) error { } }) setResourceGroupTaggerForTxn(e.ctx.GetSessionVars().StmtCtx, e.snapshot) + setRPCInterceptorOfExecCounterForTxn(e.ctx.GetSessionVars(), e.snapshot) return nil } @@ -306,9 +311,24 @@ func (e *PointGetExecutor) Next(ctx context.Context, req *chunk.Chunk) error { return err } if len(val) == 0 { - if e.idxInfo != nil && !isCommonHandleRead(e.tblInfo, e.idxInfo) { - return kv.ErrNotExist.GenWithStack("inconsistent extra index %s, handle %d not found in table", - e.idxInfo.Name.O, e.handle) + if e.idxInfo != nil && !isCommonHandleRead(e.tblInfo, e.idxInfo) && + !e.ctx.GetSessionVars().StmtCtx.WeakConsistency { + return (&consistency.Reporter{ + HandleEncode: func(handle kv.Handle) kv.Key { + return key + }, + IndexEncode: func(idxRow *consistency.RecordData) kv.Key { + return e.idxKey + }, + Tbl: e.tblInfo, + Idx: e.idxInfo, + Sctx: e.ctx, + }).ReportLookupInconsistent(ctx, + 1, 0, + []kv.Handle{e.handle}, + []kv.Handle{e.handle}, + []consistency.RecordData{{}}, + ) } return nil } @@ -362,7 +382,7 @@ func (e *PointGetExecutor) lockKeyIfNeeded(ctx context.Context, key []byte) erro } if e.lock { seVars := e.ctx.GetSessionVars() - lockCtx := newLockCtx(seVars, e.lockWaitTime) + lockCtx := newLockCtx(seVars, e.lockWaitTime, 1) lockCtx.InitReturnValues(1) err := doLockKeys(ctx, e.ctx, lockCtx, key) if err != nil { @@ -427,6 +447,8 @@ func (e *PointGetExecutor) get(ctx context.Context, key kv.Key) ([]byte, error) } func (e *PointGetExecutor) verifyTxnScope() error { + // Stale Read uses the calculated TSO for the read, + // so there is no need to check the TxnScope here. if e.isStaleness { return nil } @@ -453,10 +475,10 @@ func (e *PointGetExecutor) verifyTxnScope() error { return nil } if len(partName) > 0 { - return ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( + return dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( fmt.Sprintf("table %v's partition %v can not be read by %v txn_scope", tblName, partName, txnScope)) } - return ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( + return dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( fmt.Sprintf("table %v can not be read by %v txn_scope", tblName, txnScope)) } diff --git a/executor/point_get_test.go b/executor/point_get_test.go index 131803a95a57f..780cf2a4b1efe 100644 --- a/executor/point_get_test.go +++ b/executor/point_get_test.go @@ -19,71 +19,30 @@ import ( "fmt" "strings" "sync" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" storeerr "github.com/pingcap/tidb/store/driver/error" - "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/codec" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/tikv" ) -type testPointGetSuite struct { - store kv.Storage - dom *domain.Domain - cli *checkRequestClient - testData testutil.TestData -} - -func (s *testPointGetSuite) SetUpSuite(c *C) { - cli := &checkRequestClient{} - hijackClient := func(c tikv.Client) tikv.Client { - cli.Client = c - return cli - } - s.cli = cli - - var err error - s.store, err = mockstore.NewMockStore( - mockstore.WithClientHijacker(hijackClient), - ) - c.Assert(err, IsNil) - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - h := s.dom.StatsHandle() - h.SetLease(0) - s.testData, err = testutil.LoadTestSuiteData("testdata", "point_get_suite") - c.Assert(err, IsNil) -} - -func (s *testPointGetSuite) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testPointGetSuite) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } -} - -func (s *testPointGetSuite) TestPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table point (id int primary key, c int, d varchar(10), unique c_d (c, d))") tk.MustExec("insert point values (1, 1, 'a')") @@ -91,10 +50,10 @@ func (s *testPointGetSuite) TestPointGet(c *C) { tk.MustQuery("select * from point where id = 1 and c = 0").Check(testkit.Rows()) tk.MustQuery("select * from point where id < 0 and c = 1 and d = 'b'").Check(testkit.Rows()) result, err := tk.Exec("select id as ident from point where id = 1") - c.Assert(err, IsNil) + require.NoError(t, err) fields := result.Fields() - c.Assert(fields[0].ColumnAsName.O, Equals, "ident") - c.Assert(result.Close(), IsNil) + require.Equal(t, "ident", fields[0].ColumnAsName.O) + require.NoError(t, result.Close()) tk.MustExec("CREATE TABLE tab3(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT);") tk.MustExec("CREATE UNIQUE INDEX idx_tab3_0 ON tab3 (col4);") @@ -123,8 +82,10 @@ func (s *testPointGetSuite) TestPointGet(c *C) { " ")) } -func (s *testPointGetSuite) TestPointGetOverflow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetOverflow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0") tk.MustExec("CREATE TABLE t0(c1 BOOL UNIQUE)") @@ -142,8 +103,10 @@ func (s *testPointGetSuite) TestPointGetOverflow(c *C) { } // Close issue #22839 -func (s *testPointGetSuite) TestPointGetDataTooLong(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetDataTooLong(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists PK_1389;") tk.MustExec("CREATE TABLE `PK_1389` ( " + @@ -161,8 +124,10 @@ func (s *testPointGetSuite) TestPointGetDataTooLong(c *C) { } // issue #25489 -func (s *testPointGetSuite) TestIssue25489(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue25489(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("use test") @@ -186,7 +151,7 @@ func (s *testPointGetSuite) TestIssue25489(c *C) { PARTITION PMX VALUES LESS THAN (MAXVALUE) ) ;`) query := "select col1, col2 from UK_RP16939 where col1 in (116, 48, -30);" - c.Assert(tk.HasPlan(query, "Batch_Point_Get"), IsFalse) + require.False(t, tk.HasPlan(query, "Batch_Point_Get")) tk.MustQuery(query).Check(testkit.Rows()) tk.MustExec("drop table if exists UK_RP16939;") @@ -204,14 +169,16 @@ func (s *testPointGetSuite) TestIssue25489(c *C) { PARTITION P1 VALUES IN (-22, 63), PARTITION P2 VALUES IN (75, 90) ) ;`) - c.Assert(tk.HasPlan(query, "Batch_Point_Get"), IsFalse) + require.False(t, tk.HasPlan(query, "Batch_Point_Get")) tk.MustQuery(query).Check(testkit.Rows()) tk.MustExec("drop table if exists UK_RP16939;") } // issue #25320 -func (s *testPointGetSuite) TestDistinctPlan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDistinctPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test_distinct;") tk.MustExec(`CREATE TABLE test_distinct ( @@ -223,187 +190,10 @@ func (s *testPointGetSuite) TestDistinctPlan(c *C) { tk.MustQuery("select distinct b from test_distinct where id in (123456789101112131,123456789101112132);").Check(testkit.Rows("223456789101112131")) } -func (s *testPointGetSuite) TestPointGetCharPK(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(4) primary key, b char(4));`) - tk.MustExec(`insert into t values("aa", "bb");`) - - // Test CHAR type. - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustPointGet(`select * from t where a = "aab";`).Check(testkit.Rows()) - - tk.MustExec(`truncate table t;`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows()) - - // Test CHAR BINARY. - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2) binary primary key, b char(2));`) - tk.MustExec(`insert into t values(" ", " ");`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustTableDual(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = "";`).Check(testkit.Rows(` `)) - tk.MustPointGet(`select * from t where a = " ";`).Check(testkit.Rows()) - tk.MustTableDual(`select * from t where a = " ";`).Check(testkit.Rows()) - -} - -func (s *testPointGetSuite) TestPointGetAliasTableCharPK(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2) primary key, b char(2));`) - tk.MustExec(`insert into t values("aa", "bb");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustTableDual(`select * from t tmp where a = "aab";`).Check(testkit.Rows()) - - tk.MustExec(`truncate table t;`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t tmp where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustPointGet(`select * from t tmp where a = "a ";`).Check(testkit.Rows()) - tk.MustTableDual(`select * from t tmp where a = "a ";`).Check(testkit.Rows()) - - // Test CHAR BINARY. - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2) binary primary key, b char(2));`) - tk.MustExec(`insert into t values(" ", " ");`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t tmp where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustPointGet(`select * from t tmp where a = "a ";`).Check(testkit.Rows()) - tk.MustTableDual(`select * from t tmp where a = "a ";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t tmp where a = "";`).Check(testkit.Rows(` `)) - tk.MustPointGet(`select * from t tmp where a = " ";`).Check(testkit.Rows()) - tk.MustTableDual(`select * from t tmp where a = " ";`).Check(testkit.Rows()) - - // Test both wildcard and column name exist in select field list - tk.MustExec(`set @@sql_mode="";`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2) primary key, b char(2));`) - tk.MustExec(`insert into t values("aa", "bb");`) - tk.MustPointGet(`select *, a from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb aa`)) - - // Test using table alias in field list - tk.MustPointGet(`select tmp.* from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustPointGet(`select tmp.a, tmp.b from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustPointGet(`select tmp.*, tmp.a, tmp.b from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb aa bb`)) - tk.MustTableDual(`select tmp.* from t tmp where a = "aab";`).Check(testkit.Rows()) - tk.MustTableDual(`select tmp.a, tmp.b from t tmp where a = "aab";`).Check(testkit.Rows()) - tk.MustTableDual(`select tmp.*, tmp.a, tmp.b from t tmp where a = "aab";`).Check(testkit.Rows()) - - // Test using table alias in where clause - tk.MustPointGet(`select * from t tmp where tmp.a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustPointGet(`select a, b from t tmp where tmp.a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustPointGet(`select *, a, b from t tmp where tmp.a = "aa";`).Check(testkit.Rows(`aa bb aa bb`)) - - // Unknown table name in where clause and field list - err := tk.ExecToErr(`select a from t where xxxxx.a = "aa"`) - c.Assert(err, ErrorMatches, ".*Unknown column 'xxxxx.a' in 'where clause'") - err = tk.ExecToErr(`select xxxxx.a from t where a = "aa"`) - c.Assert(err, ErrorMatches, ".*Unknown column 'xxxxx.a' in 'field list'") - - // When an alias is provided, it completely hides the actual name of the table. - err = tk.ExecToErr(`select a from t tmp where t.a = "aa"`) - c.Assert(err, ErrorMatches, ".*Unknown column 't.a' in 'where clause'") - err = tk.ExecToErr(`select t.a from t tmp where a = "aa"`) - c.Assert(err, ErrorMatches, ".*Unknown column 't.a' in 'field list'") - err = tk.ExecToErr(`select t.* from t tmp where a = "aa"`) - c.Assert(err, ErrorMatches, ".*Unknown table 't'") -} - -func (s *testPointGetSuite) TestIndexLookupChar(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2), b char(2), index idx_1(a));`) - tk.MustExec(`insert into t values("aa", "bb");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustIndexLookup(`select * from t where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustIndexLookup(`select * from t where a = "aab";`).Check(testkit.Rows()) - - // Test query with table alias - tk.MustIndexLookup(`select * from t tmp where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustIndexLookup(`select * from t tmp where a = "aab";`).Check(testkit.Rows()) - - tk.MustExec(`truncate table t;`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustIndexLookup(`select * from t where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustIndexLookup(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustIndexLookup(`select * from t where a = "a ";`).Check(testkit.Rows()) - - // Test CHAR BINARY. - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a char(2) binary, b char(2), index idx_1(a));`) - tk.MustExec(`insert into t values(" ", " ");`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustIndexLookup(`select * from t where a = "a";`).Check(testkit.Rows(`a b`)) - tk.MustIndexLookup(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustIndexLookup(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustIndexLookup(`select * from t where a = "";`).Check(testkit.Rows(` `)) - tk.MustIndexLookup(`select * from t where a = " ";`).Check(testkit.Rows()) - tk.MustIndexLookup(`select * from t where a = " ";`).Check(testkit.Rows()) - tk.MustIndexLookup(`select * from t where a = " ";`).Check(testkit.Rows()) - -} - -func (s *testPointGetSuite) TestPointGetVarcharPK(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec(`use test;`) - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a varchar(2) primary key, b varchar(2));`) - tk.MustExec(`insert into t values("aa", "bb");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "aa";`).Check(testkit.Rows(`aa bb`)) - tk.MustTableDual(`select * from t where a = "aab";`).Check(testkit.Rows()) - - tk.MustExec(`truncate table t;`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "a";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows(`a b `)) - tk.MustTableDual(`select * from t where a = "a ";`).Check(testkit.Rows()) - - // // Test VARCHAR BINARY. - tk.MustExec(`drop table if exists t;`) - tk.MustExec(`create table t(a varchar(2) binary primary key, b varchar(2));`) - tk.MustExec(`insert into t values(" ", " ");`) - tk.MustExec(`insert into t values("a ", "b ");`) - - tk.MustExec(`set @@sql_mode="";`) - tk.MustPointGet(`select * from t where a = "a";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows(`a b `)) - tk.MustTableDual(`select * from t where a = "a ";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = " ";`).Check(testkit.Rows()) - tk.MustPointGet(`select * from t where a = " ";`).Check(testkit.Rows(` `)) - tk.MustTableDual(`select * from t where a = " ";`).Check(testkit.Rows()) - -} - -func (s *testPointGetSuite) TestPointGetBinaryPK(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetBinaryPK(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test;`) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a binary(2) primary key, b binary(2));`) @@ -425,8 +215,10 @@ func (s *testPointGetSuite) TestPointGetBinaryPK(c *C) { tk.MustPointGet(`select * from t where a = "a ";`).Check(testkit.Rows()) } -func (s *testPointGetSuite) TestPointGetAliasTableBinaryPK(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetAliasTableBinaryPK(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test;`) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a binary(2) primary key, b binary(2));`) @@ -448,8 +240,10 @@ func (s *testPointGetSuite) TestPointGetAliasTableBinaryPK(c *C) { tk.MustPointGet(`select * from t tmp where a = "a ";`).Check(testkit.Rows()) } -func (s *testPointGetSuite) TestIndexLookupBinary(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexLookupBinary(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test;`) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a binary(2), b binary(2), index idx_1(a));`) @@ -479,8 +273,11 @@ func (s *testPointGetSuite) TestIndexLookupBinary(c *C) { } -func (s *testPointGetSuite) TestOverflowOrTruncated(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestOverflowOrTruncated(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("create table t6 (id bigint, a bigint, primary key(id), unique key(a));") tk.MustExec("insert into t6 values(9223372036854775807, 9223372036854775807);") tk.MustExec("insert into t6 values(1, 1);") @@ -493,8 +290,10 @@ func (s *testPointGetSuite) TestOverflowOrTruncated(c *C) { tk.MustQuery("select * from t6 where id = '1.123'").Check(testkit.Rows(nilVal...)) } -func (s *testPointGetSuite) TestIssue10448(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10448(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(pk int1 primary key)") @@ -534,15 +333,17 @@ func (s *testPointGetSuite) TestIssue10448(c *C) { tk.MustQuery("desc select * from t where pk = 9223372036854775808").Check(testkit.Rows("Point_Get_1 1.00 root table:t handle:9223372036854775808")) } -func (s *testPointGetSuite) TestIssue10677(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10677(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(pk int1 primary key)") tk.MustExec("insert into t values(1)") - tk.MustQuery("desc select * from t where pk = 1.1").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 1.1").Check(testkit.Rows("TableDual_6 0.00 root rows:0")) tk.MustQuery("select * from t where pk = 1.1").Check(testkit.Rows()) - tk.MustQuery("desc select * from t where pk = '1.1'").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = '1.1'").Check(testkit.Rows("TableDual_6 0.00 root rows:0")) tk.MustQuery("select * from t where pk = '1.1'").Check(testkit.Rows()) tk.MustQuery("desc select * from t where pk = 1").Check(testkit.Rows("Point_Get_1 1.00 root table:t handle:1")) tk.MustQuery("select * from t where pk = 1").Check(testkit.Rows("1")) @@ -552,24 +353,30 @@ func (s *testPointGetSuite) TestIssue10677(c *C) { tk.MustQuery("select * from t where pk = '1.0'").Check(testkit.Rows("1")) } -func (s *testPointGetSuite) TestForUpdateRetry(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestForUpdateRetry(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") _, err := tk.Exec("drop table if exists t") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("create table t(pk int primary key, c int)") tk.MustExec("insert into t values (1, 1), (2, 2)") tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") tk.MustExec("begin") tk.MustQuery("select * from t where pk = 1 for update") - tk2 := testkit.NewTestKitWithInit(c, s.store) + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") tk2.MustExec("update t set c = c + 1 where pk = 1") tk.MustExec("update t set c = c + 1 where pk = 2") _, err = tk.Exec("commit") - c.Assert(session.ErrForUpdateCantRetry.Equal(err), IsTrue) + require.True(t, session.ErrForUpdateCantRetry.Equal(err)) } -func (s *testPointGetSuite) TestPointGetByRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetByRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a varchar(20), b int)") @@ -579,25 +386,38 @@ func (s *testPointGetSuite) TestPointGetByRowID(c *C) { tk.MustQuery("select * from t where t._tidb_rowid = 1").Check(testkit.Rows("aaa 12")) } -func (s *testPointGetSuite) TestSelectCheckVisibility(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetBinaryLiteralString(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a varchar(255) charset gbk primary key /*T![clustered_index] clustered */, b int);") + tk.MustExec("insert into t values ('你好', 1);") + tk.MustPointGet("select * from t where a = 0xC4E3BAC3;").Check(testkit.Rows("你好 1")) +} + +func TestSelectCheckVisibility(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a varchar(10) key, b int,index idx(b))") tk.MustExec("insert into t values('1',1)") tk.MustExec("begin") - txn, err := tk.Se.Txn(false) - c.Assert(err, IsNil) + txn, err := tk.Session().Txn(false) + require.NoError(t, err) ts := txn.StartTS() - store := tk.Se.GetStore().(tikv.Storage) + sessionStore := tk.Session().GetStore().(tikv.Storage) // Update gc safe time for check data visibility. - store.UpdateSPCache(ts+1, time.Now()) + sessionStore.UpdateSPCache(ts+1, time.Now()) checkSelectResultError := func(sql string, expectErr *terror.Error) { re, err := tk.Exec(sql) - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.Background(), tk.Se, re) - c.Assert(err, NotNil) - c.Assert(expectErr.Equal(err), IsTrue) + require.NoError(t, err) + _, err = session.ResultSetToStringSlice(context.Background(), tk.Session(), re) + require.Error(t, err) + require.True(t, expectErr.Equal(err)) } // Test point get. checkSelectResultError("select * from t where a='1'", storeerr.ErrGCTooEarly) @@ -611,34 +431,38 @@ func (s *testPointGetSuite) TestSelectCheckVisibility(c *C) { checkSelectResultError("select * from t", storeerr.ErrGCTooEarly) } -func (s *testPointGetSuite) TestReturnValues(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReturnValues(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t (a varchar(64) primary key, b int)") tk.MustExec("insert t values ('a', 1), ('b', 2), ('c', 3)") tk.MustExec("begin pessimistic") tk.MustQuery("select * from t where a = 'b' for update").Check(testkit.Rows("b 2")) - tid := tk.GetTableID("t") - idxVal, err := codec.EncodeKey(tk.Se.GetSessionVars().StmtCtx, nil, types.NewStringDatum("b")) - c.Assert(err, IsNil) + tid := external.GetTableByName(t, tk, "test", "t").Meta().ID + idxVal, err := codec.EncodeKey(tk.Session().GetSessionVars().StmtCtx, nil, types.NewStringDatum("b")) + require.NoError(t, err) pk := tablecodec.EncodeIndexSeekKey(tid, 1, idxVal) - txnCtx := tk.Se.GetSessionVars().TxnCtx + txnCtx := tk.Session().GetSessionVars().TxnCtx val, ok := txnCtx.GetKeyInPessimisticLockCache(pk) - c.Assert(ok, IsTrue) + require.True(t, ok) handle, err := tablecodec.DecodeHandleInUniqueIndexValue(val, false) - c.Assert(err, IsNil) + require.NoError(t, err) rowKey := tablecodec.EncodeRowKeyWithHandle(tid, handle) _, ok = txnCtx.GetKeyInPessimisticLockCache(rowKey) - c.Assert(ok, IsTrue) + require.True(t, ok) tk.MustExec("rollback") } -func (s *testPointGetSuite) TestClusterIndexPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterIndexPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists pgt") tk.MustExec("create table pgt (a varchar(64), b varchar(64), uk int, v int, primary key(a, b), unique key uuk(uk))") tk.MustExec("insert pgt values ('a', 'a1', 1, 11), ('b', 'b1', 2, 22), ('c', 'c1', 3, 33)") @@ -658,10 +482,12 @@ func (s *testPointGetSuite) TestClusterIndexPointGet(c *C) { tk.MustQuery("select * from snp where id1 = 2").Check(testkit.Rows("2 2 2", "2 3 3")) } -func (s *testPointGetSuite) TestClusterIndexCBOPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterIndexCBOPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t1, t2") tk.MustExec(`create table t1 (a int, b decimal(10,0), c int, primary key(a,b))`) tk.MustExec(`create table t2 (a varchar(20), b int, primary key(a), unique key(b))`) @@ -675,36 +501,38 @@ func (s *testPointGetSuite) TestClusterIndexCBOPointGet(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + pointGetSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { plan := tk.MustQuery("explain format = 'brief' " + tt) res := tk.MustQuery(tt).Sort() - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(res.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) + output[i].Res = testdata.ConvertRowsToStrings(res.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) res.Check(testkit.Rows(output[i].Res...)) } } -func (s *testSerialSuite) mustExecDDL(tk *testkit.TestKit, c *C, sql string) { +func mustExecDDL(tk *testkit.TestKit, t *testing.T, sql string, dom *domain.Domain) { tk.MustExec(sql) - c.Assert(s.domain.Reload(), IsNil) + require.NoError(t, dom.Reload()) } -func (s *testSerialSuite) TestMemCacheReadLock(c *C) { +func TestMemCacheReadLock(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.EnableTableLock = true }) - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnablePointGetCache = true + tk.Session().GetSessionVars().EnablePointGetCache = true defer func() { - tk.Se.GetSessionVars().EnablePointGetCache = false + tk.Session().GetSessionVars().EnablePointGetCache = false tk.MustExec("drop table if exists point") }() @@ -714,10 +542,10 @@ func (s *testSerialSuite) TestMemCacheReadLock(c *C) { tk.MustExec("insert point values (2, 2, 'b')") // Simply check the cached results. - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "lock tables point read", dom) tk.MustQuery("select id from point where id = 1").Check(testkit.Rows("1")) tk.MustQuery("select id from point where id = 1").Check(testkit.Rows("1")) - s.mustExecDDL(tk, c, "unlock tables") + mustExecDDL(tk, t, "unlock tables", dom) cases := []struct { sql string @@ -734,61 +562,63 @@ func (s *testSerialSuite) TestMemCacheReadLock(c *C) { } for _, ca := range cases { - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "lock tables point read", dom) rows := tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1, Commentf("%v", ca.sql)) + require.Lenf(t, rows, 1, "%v", ca.sql) explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) rows = tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) ok := strings.Contains(explain, "num_rpc") - c.Assert(ok, Equals, ca.r1, Commentf("%v", ca.sql)) - s.mustExecDDL(tk, c, "unlock tables") + require.Equalf(t, ok, ca.r1, "%v", ca.sql) + mustExecDDL(tk, t, "unlock tables", dom) rows = tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) // Test cache release after unlocking tables. - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "lock tables point read", dom) rows = tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) rows = tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) ok = strings.Contains(explain, "num_rpc") - c.Assert(ok, Equals, ca.r2, Commentf("%v", ca.sql)) + require.Equal(t, ok, ca.r2, "%v", ca.sql) - s.mustExecDDL(tk, c, "unlock tables") - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "unlock tables", dom) + mustExecDDL(tk, t, "lock tables point read", dom) rows = tk.MustQuery(ca.sql).Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) - s.mustExecDDL(tk, c, "unlock tables") + mustExecDDL(tk, t, "unlock tables", dom) } } -func (s *testSerialSuite) TestPartitionMemCacheReadLock(c *C) { +func TestPartitionMemCacheReadLock(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.EnableTableLock = true }) - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnablePointGetCache = true + tk.Session().GetSessionVars().EnablePointGetCache = true defer func() { - tk.Se.GetSessionVars().EnablePointGetCache = false + tk.Session().GetSessionVars().EnablePointGetCache = false tk.MustExec("drop table if exists point") }() @@ -800,31 +630,33 @@ func (s *testSerialSuite) TestPartitionMemCacheReadLock(c *C) { // Confirm _tidb_rowid will not be duplicated. tk.MustQuery("select distinct(_tidb_rowid) from point order by _tidb_rowid").Check(testkit.Rows("1", "2")) - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "lock tables point read", dom) tk.MustQuery("select _tidb_rowid from point where id = 1").Check(testkit.Rows("1")) - s.mustExecDDL(tk, c, "unlock tables") + mustExecDDL(tk, t, "unlock tables", dom) tk.MustQuery("select _tidb_rowid from point where id = 1").Check(testkit.Rows("1")) tk.MustExec("update point set id = -id") // Test cache release after unlocking tables. - s.mustExecDDL(tk, c, "lock tables point read") + mustExecDDL(tk, t, "lock tables point read", dom) tk.MustQuery("select _tidb_rowid from point where id = 1").Check(testkit.Rows()) tk.MustQuery("select _tidb_rowid from point where id = -1").Check(testkit.Rows("1")) tk.MustQuery("select _tidb_rowid from point where id = -1").Check(testkit.Rows("1")) tk.MustQuery("select _tidb_rowid from point where id = -2").Check(testkit.Rows("2")) - s.mustExecDDL(tk, c, "unlock tables") + mustExecDDL(tk, t, "unlock tables", dom) } -func (s *testPointGetSuite) TestPointGetWriteLock(c *C) { +func TestPointGetWriteLock(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.EnableTableLock = true }) - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table point (id int primary key, c int, d varchar(10), unique c_d (c, d))") tk.MustExec("insert point values (1, 1, 'a')") @@ -834,9 +666,9 @@ func (s *testPointGetSuite) TestPointGetWriteLock(c *C) { `1 1 a`, )) rows := tk.MustQuery("explain analyze select * from point where id = 1").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain := fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) tk.MustExec("unlock tables") tk.MustExec("update point set c = 3 where id = 1") @@ -845,53 +677,51 @@ func (s *testPointGetSuite) TestPointGetWriteLock(c *C) { `1 3 a`, )) rows = tk.MustQuery("explain analyze select * from point where id = 1").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) explain = fmt.Sprintf("%v", rows[0]) - c.Assert(explain, Matches, ".*num_rpc.*") + require.Regexp(t, ".*num_rpc.*", explain) tk.MustExec("unlock tables") } -func (s *testPointGetSuite) TestPointGetLockExistKey(c *C) { - var wg sync.WaitGroup - errCh := make(chan error) - +func TestPointGetLockExistKey(t *testing.T) { testLock := func(rc bool, key string, tableName string) { - doneCh := make(chan struct{}, 1) - tk1, tk2 := testkit.NewTestKit(c, s.store), testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1, tk2 := testkit.NewTestKit(t, store), testkit.NewTestKit(t, store) - errCh <- tk1.ExecToErr("use test") - errCh <- tk2.ExecToErr("use test") - tk1.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk1.MustExec("use test") + tk2.MustExec("use test") + tk1.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - errCh <- tk1.ExecToErr(fmt.Sprintf("drop table if exists %s", tableName)) - errCh <- tk1.ExecToErr(fmt.Sprintf("create table %s(id int, v int, k int, %s key0(id, v))", tableName, key)) - errCh <- tk1.ExecToErr(fmt.Sprintf("insert into %s values(1, 1, 1)", tableName)) + tk1.MustExec(fmt.Sprintf("drop table if exists %s", tableName)) + tk1.MustExec(fmt.Sprintf("create table %s(id int, v int, k int, %s key0(id, v))", tableName, key)) + tk1.MustExec(fmt.Sprintf("insert into %s values(1, 1, 1)", tableName)) if rc { - errCh <- tk1.ExecToErr("set tx_isolation = 'READ-COMMITTED'") - errCh <- tk2.ExecToErr("set tx_isolation = 'READ-COMMITTED'") + tk1.MustExec("set tx_isolation = 'READ-COMMITTED'") + tk2.MustExec("set tx_isolation = 'READ-COMMITTED'") } // select for update - errCh <- tk1.ExecToErr("begin pessimistic") - errCh <- tk2.ExecToErr("begin pessimistic") + tk1.MustExec("begin pessimistic") + tk2.MustExec("begin pessimistic") // lock exist key - errCh <- tk1.ExecToErr(fmt.Sprintf("select * from %s where id = 1 and v = 1 for update", tableName)) + tk1.MustExec(fmt.Sprintf("select * from %s where id = 1 and v = 1 for update", tableName)) // read committed will not lock non-exist key if rc { - errCh <- tk1.ExecToErr(fmt.Sprintf("select * from %s where id = 2 and v = 2 for update", tableName)) + tk1.MustExec(fmt.Sprintf("select * from %s where id = 2 and v = 2 for update", tableName)) } - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(2, 2, 2)", tableName)) - go func() { - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(1, 1, 10)", tableName)) + tk2.MustExec(fmt.Sprintf("insert into %s values(2, 2, 2)", tableName)) + var wg3 util.WaitGroupWrapper + wg3.Run(func() { + tk2.MustExec(fmt.Sprintf("insert into %s values(1, 1, 10)", tableName)) // tk2.MustExec(fmt.Sprintf("insert into %s values(1, 1, 10)", tableName)) - doneCh <- struct{}{} - }() + }) time.Sleep(150 * time.Millisecond) - errCh <- tk1.ExecToErr(fmt.Sprintf("update %s set v = 2 where id = 1 and v = 1", tableName)) - errCh <- tk1.ExecToErr("commit") - <-doneCh - errCh <- tk2.ExecToErr("commit") + tk1.MustExec(fmt.Sprintf("update %s set v = 2 where id = 1 and v = 1", tableName)) + tk1.MustExec("commit") + wg3.Wait() + tk2.MustExec("commit") tk1.MustQuery(fmt.Sprintf("select * from %s", tableName)).Check(testkit.Rows( "1 2 1", "2 2 2", @@ -899,23 +729,23 @@ func (s *testPointGetSuite) TestPointGetLockExistKey(c *C) { )) // update - errCh <- tk1.ExecToErr("begin pessimistic") - errCh <- tk2.ExecToErr("begin pessimistic") + tk1.MustExec("begin pessimistic") + tk2.MustExec("begin pessimistic") // lock exist key - errCh <- tk1.ExecToErr(fmt.Sprintf("update %s set v = 3 where id = 2 and v = 2", tableName)) + tk1.MustExec(fmt.Sprintf("update %s set v = 3 where id = 2 and v = 2", tableName)) // read committed will not lock non-exist key if rc { - errCh <- tk1.ExecToErr(fmt.Sprintf("update %s set v =4 where id = 3 and v = 3", tableName)) + tk1.MustExec(fmt.Sprintf("update %s set v =4 where id = 3 and v = 3", tableName)) } - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(3, 3, 3)", tableName)) - go func() { - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(2, 2, 20)", tableName)) - doneCh <- struct{}{} - }() + tk2.MustExec(fmt.Sprintf("insert into %s values(3, 3, 3)", tableName)) + var wg2 util.WaitGroupWrapper + wg2.Run(func() { + tk2.MustExec(fmt.Sprintf("insert into %s values(2, 2, 20)", tableName)) + }) time.Sleep(150 * time.Millisecond) - errCh <- tk1.ExecToErr("commit") - <-doneCh - errCh <- tk2.ExecToErr("commit") + tk1.MustExec("commit") + wg2.Wait() + tk2.MustExec("commit") tk1.MustQuery(fmt.Sprintf("select * from %s", tableName)).Check(testkit.Rows( "1 2 1", "2 3 2", @@ -925,23 +755,23 @@ func (s *testPointGetSuite) TestPointGetLockExistKey(c *C) { )) // delete - errCh <- tk1.ExecToErr("begin pessimistic") - errCh <- tk2.ExecToErr("begin pessimistic") + tk1.MustExec("begin pessimistic") + tk2.MustExec("begin pessimistic") // lock exist key - errCh <- tk1.ExecToErr(fmt.Sprintf("delete from %s where id = 3 and v = 3", tableName)) + tk1.MustExec(fmt.Sprintf("delete from %s where id = 3 and v = 3", tableName)) // read committed will not lock non-exist key if rc { - errCh <- tk1.ExecToErr(fmt.Sprintf("delete from %s where id = 4 and v = 4", tableName)) + tk1.MustExec(fmt.Sprintf("delete from %s where id = 4 and v = 4", tableName)) } - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(4, 4, 4)", tableName)) - go func() { - errCh <- tk2.ExecToErr(fmt.Sprintf("insert into %s values(3, 3, 30)", tableName)) - doneCh <- struct{}{} - }() + tk2.MustExec(fmt.Sprintf("insert into %s values(4, 4, 4)", tableName)) + var wg1 util.WaitGroupWrapper + wg1.Run(func() { + tk2.MustExec(fmt.Sprintf("insert into %s values(3, 3, 30)", tableName)) + }) time.Sleep(50 * time.Millisecond) - errCh <- tk1.ExecToErr("commit") - <-doneCh - errCh <- tk2.ExecToErr("commit") + tk1.MustExec("commit") + wg1.Wait() + tk2.MustExec("commit") tk1.MustQuery(fmt.Sprintf("select * from %s", tableName)).Check(testkit.Rows( "1 2 1", "2 3 2", @@ -950,9 +780,9 @@ func (s *testPointGetSuite) TestPointGetLockExistKey(c *C) { "4 4 4", "3 3 30", )) - wg.Done() } + var wg sync.WaitGroup for i, one := range []struct { rc bool key string @@ -964,22 +794,20 @@ func (s *testPointGetSuite) TestPointGetLockExistKey(c *C) { } { wg.Add(1) tableName := fmt.Sprintf("t_%d", i) - go testLock(one.rc, one.key, tableName) - } - - go func() { - wg.Wait() - close(errCh) - }() - for err := range errCh { - c.Assert(err, IsNil) + go func(rc bool, key string, tableName string) { + defer wg.Done() + testLock(rc, key, tableName) + }(one.rc, one.key, tableName) } + wg.Wait() } -func (s *testPointGetSuite) TestWithTiDBSnapshot(c *C) { +func TestWithTiDBSnapshot(t *testing.T) { // Fix issue https://github.com/pingcap/tidb/issues/22436 // Point get should not use math.MaxUint64 when variable @@tidb_snapshot is set. - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists xx") tk.MustExec(`create table xx (id int key)`) @@ -995,9 +823,9 @@ func (s *testPointGetSuite) TestWithTiDBSnapshot(c *C) { // Record the current tso. tk.MustExec("begin") - tso := tk.Se.GetSessionVars().TxnCtx.StartTS + tso := tk.Session().GetSessionVars().TxnCtx.StartTS tk.MustExec("rollback") - c.Assert(tso > 0, IsTrue) + require.True(t, tso > 0) // Insert data. tk.MustExec("insert into xx values (8)") @@ -1009,8 +837,10 @@ func (s *testPointGetSuite) TestWithTiDBSnapshot(c *C) { tk.MustQuery("select * from xx").Check(testkit.Rows("1", "7")) } -func (s *testPointGetSuite) TestPointGetIssue25167(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetIssue25167(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int primary key)") diff --git a/executor/prepared.go b/executor/prepared.go index 82a030e76b6c1..f81d2482f979c 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -21,6 +21,7 @@ import ( "time" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/log" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" @@ -30,7 +31,7 @@ import ( "github.com/pingcap/tidb/planner" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" "github.com/pingcap/tidb/util" @@ -38,6 +39,7 @@ import ( "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/topsql" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "go.uber.org/zap" ) @@ -194,14 +196,23 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { SchemaVersion: ret.InfoSchema.SchemaMetaVersion(), } normalizedSQL, digest := parser.NormalizeDigest(prepared.Stmt.Text()) - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { ctx = topsql.AttachSQLInfo(ctx, normalizedSQL, digest, "", nil, vars.InRestrictedSQL) } + var ( + normalizedSQL4PC, digest4PC string + selectStmtNode ast.StmtNode + ) if !plannercore.PreparedPlanCacheEnabled() { prepared.UseCache = false } else { prepared.UseCache = plannercore.CacheableWithCtx(e.ctx, stmt, ret.InfoSchema) + selectStmtNode, normalizedSQL4PC, digest4PC, err = planner.ExtractSelectAndNormalizeDigest(stmt, e.ctx.GetSessionVars().CurrentDB) + if err != nil || selectStmtNode == nil { + normalizedSQL4PC = "" + digest4PC = "" + } } // We try to build the real statement of preparedStmt. @@ -213,12 +224,16 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { var p plannercore.Plan e.ctx.GetSessionVars().PlanID = 0 e.ctx.GetSessionVars().PlanColumnID = 0 + e.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = nil destBuilder, _ := plannercore.NewPlanBuilder().Init(e.ctx, ret.InfoSchema, &hint.BlockHintProcessor{}) p, err = destBuilder.Build(ctx, stmt) if err != nil { return err } - if _, ok := stmt.(*ast.SelectStmt); ok { + // In MySQL prepare protocol, the server need to tell the client how many column the prepared statement would return when executing it. + // For a query with on result, e.g. an insert statement, there will be no result, so 'e.Fields' is not set. + // Usually, p.Schema().Len() == 0 means no result. A special case is the 'do' statement, it looks like 'select' but discard the result. + if !isNoResultPlan(p) { e.Fields = colNames2ResultFields(p.Schema(), p.OutputNames(), vars.CurrentDB) } if e.ID == 0 { @@ -230,11 +245,15 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { preparedObj := &plannercore.CachedPrepareStmt{ PreparedAst: prepared, + StmtDB: e.ctx.GetSessionVars().CurrentDB, + StmtText: stmt.Text(), VisitInfos: destBuilder.GetVisitInfo(), NormalizedSQL: normalizedSQL, SQLDigest: digest, ForUpdateRead: destBuilder.GetIsForUpdateRead(), SnapshotTSEvaluator: ret.SnapshotTSEvaluator, + NormalizedSQL4PC: normalizedSQL4PC, + SQLDigest4PC: digest4PC, } return vars.AddPreparedStmt(e.ID, preparedObj) } @@ -314,10 +333,13 @@ func (e *DeallocateExec) Next(ctx context.Context, req *chunk.Chunk) error { prepared := preparedObj.PreparedAst delete(vars.PreparedStmtNameToID, e.Name) if plannercore.PreparedPlanCacheEnabled() { - bindSQL := planner.GetBindSQL4PlanCache(e.ctx, prepared.Stmt) - e.ctx.PreparedPlanCache().Delete(plannercore.NewPSTMTPlanCacheKey( - vars, id, prepared.SchemaVersion, bindSQL, - )) + cacheKey, err := plannercore.NewPlanCacheKey(vars, preparedObj.StmtText, preparedObj.StmtDB, prepared.SchemaVersion) + if err != nil { + return err + } + if !vars.IgnorePreparedCacheCloseStmt { // keep the plan in cache + e.ctx.PreparedPlanCache().Delete(cacheKey) + } } vars.RemovePreparedStmt(id) return nil @@ -325,7 +347,7 @@ func (e *DeallocateExec) Next(ctx context.Context, req *chunk.Chunk) error { // CompileExecutePreparedStmt compiles a session Execute command to a stmt.Statement. func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, - ID uint32, is infoschema.InfoSchema, snapshotTS uint64, args []types.Datum) (*ExecStmt, bool, bool, error) { + ID uint32, is infoschema.InfoSchema, snapshotTS uint64, replicaReadScope string, args []types.Datum) (*ExecStmt, bool, bool, error) { startTime := time.Now() defer func() { sctx.GetSessionVars().DurationCompile = time.Since(startTime) @@ -334,21 +356,30 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, if err := ResetContextOfStmt(sctx, execStmt); err != nil { return nil, false, false, err } + isStaleness := snapshotTS != 0 + sctx.GetSessionVars().StmtCtx.IsStaleness = isStaleness execStmt.BinaryArgs = args execPlan, names, err := planner.Optimize(ctx, sctx, execStmt, is) if err != nil { return nil, false, false, err } + failpoint.Inject("assertTxnManagerInCompile", func() { + sessiontxn.RecordAssert(sctx, "assertTxnManagerInCompile", true) + sessiontxn.AssertTxnManagerInfoSchema(sctx, is) + }) + stmt := &ExecStmt{ - GoCtx: ctx, - InfoSchema: is, - Plan: execPlan, - StmtNode: execStmt, - Ctx: sctx, - OutputNames: names, - Ti: &TelemetryInfo{}, - SnapshotTS: snapshotTS, + GoCtx: ctx, + InfoSchema: is, + Plan: execPlan, + StmtNode: execStmt, + Ctx: sctx, + OutputNames: names, + Ti: &TelemetryInfo{}, + IsStaleness: isStaleness, + SnapshotTS: snapshotTS, + ReplicaReadScope: replicaReadScope, } if preparedPointer, ok := sctx.GetSessionVars().PreparedStmts[ID]; ok { preparedObj, ok := preparedPointer.(*plannercore.CachedPrepareStmt) diff --git a/executor/prepared_test.go b/executor/prepared_test.go index e24178b9817b2..ceb216d5f102b 100644 --- a/executor/prepared_test.go +++ b/executor/prepared_test.go @@ -22,7 +22,6 @@ import ( "sync/atomic" "testing" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -33,7 +32,6 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/israce" "github.com/stretchr/testify/require" ) @@ -108,7 +106,7 @@ func (sm *mockSessionManager2) ShowProcessList() map[uint64]*util.ProcessInfo { return pl } -func (sm *mockSessionManager2) GetProcessInfo(id uint64) (pi *util.ProcessInfo, notNil bool) { +func (sm *mockSessionManager2) GetProcessInfo(_ uint64) (pi *util.ProcessInfo, notNil bool) { pi = sm.se.ShowProcess() if pi != nil { notNil = true @@ -116,24 +114,26 @@ func (sm *mockSessionManager2) GetProcessInfo(id uint64) (pi *util.ProcessInfo, return } -func (sm *mockSessionManager2) Kill(connectionID uint64, query bool) { +func (sm *mockSessionManager2) Kill(_ uint64, _ bool) { atomic.StoreInt32(&sm.killed, 1) atomic.StoreUint32(&sm.se.GetSessionVars().Killed, 1) } -func (sm *mockSessionManager2) KillAllConnections() {} -func (sm *mockSessionManager2) UpdateTLSConfig(cfg *tls.Config) {} -func (sm *mockSessionManager2) ServerID() uint64 { - return 1 +func (sm *mockSessionManager2) KillAllConnections() {} +func (sm *mockSessionManager2) UpdateTLSConfig(_ *tls.Config) {} +func (sm *mockSessionManager2) ServerID() uint64 { return 1 } + +func (sm *mockSessionManager2) StoreInternalSession(se interface{}) {} + +func (sm *mockSessionManager2) DeleteInternalSession(se interface{}) {} + +func (sm *mockSessionManager2) GetInternalSessionStartTSList() []uint64 { + return nil } func TestPreparedStmtWithHint(t *testing.T) { // see https://github.com/pingcap/tidb/issues/18535 - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) - defer func() { - require.NoError(t, store.Close()) - dom.Close() - }() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() se, err := session.CreateSession4Test(store) require.NoError(t, err) @@ -150,14 +150,40 @@ func TestPreparedStmtWithHint(t *testing.T) { require.Equal(t, int32(1), atomic.LoadInt32(&sm.killed)) } -func TestIssue29850(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) +func TestPreparedNullParam(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { - require.NoError(t, store.Close()) - dom.Close() + plannercore.SetPreparedPlanCache(orgEnable) }() + flags := []bool{false, true} + for _, flag := range flags { + plannercore.SetPreparedPlanCache(flag) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_enable_collect_execution_info=0") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int not null, KEY id (id))") + tk.MustExec("insert into t values (1), (2), (3)") + + tk.MustExec("prepare stmt from 'select * from t where id = ?'") + tk.MustExec("set @a= null") + tk.MustQuery("execute stmt using @a").Check(testkit.Rows()) + + tkProcess := tk.Session().ShowProcess() + ps := []*util.ProcessInfo{tkProcess} + tk.Session().SetSessionManager(&mockSessionManager1{PS: ps}) + tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows( + "TableDual_5 0.00 root rows:0")) + } +} + +func TestIssue29850(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) @@ -228,18 +254,14 @@ func TestIssue29850(t *testing.T) { } func TestIssue28064(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() tk.MustExec("use test") tk.MustExec("drop table if exists t28064") tk.MustExec("CREATE TABLE `t28064` (" + @@ -275,18 +297,14 @@ func TestIssue28064(t *testing.T) { } func TestPreparePlanCache4Blacklist(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -365,18 +383,14 @@ func TestPreparePlanCache4Blacklist(t *testing.T) { } func TestPlanCacheClusterIndex(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn @@ -485,19 +499,14 @@ func TestPlanCacheClusterIndex(t *testing.T) { } func TestPlanCacheWithDifferentVariableTypes(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - require.NoError(t, err) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") @@ -576,18 +585,14 @@ func TestPlanCacheWithDifferentVariableTypes(t *testing.T) { } func TestPlanCacheOperators(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() type ExecCase struct { Parameters []string UseCache bool @@ -918,18 +923,14 @@ func TestPlanCacheOperators(t *testing.T) { } func TestIssue28782(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("prepare stmt from 'SELECT IF(?, 1, 0);';") @@ -937,25 +938,21 @@ func TestIssue28782(t *testing.T) { tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @b;").Check(testkit.Rows("0")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) + // TODO(Reminiscent): Support cache more tableDual plan. + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) tk.MustQuery("execute stmt using @c;").Check(testkit.Rows("0")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } func TestIssue29101(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - tk.MustExec(`use test`) tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec(`CREATE TABLE customer ( @@ -1024,19 +1021,14 @@ func TestIssue29101(t *testing.T) { } func TestIssue28087And28162(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - // issue 28087 tk.MustExec(`use test`) tk.MustExec(`drop table if exists IDT_26207`) @@ -1067,19 +1059,14 @@ func TestIssue28087And28162(t *testing.T) { } func TestParameterPushDown(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - require.NoError(t, err) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t (a int, b int, c int, key(a))`) @@ -1126,19 +1113,14 @@ func TestParameterPushDown(t *testing.T) { } func TestPreparePlanCache4Function(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1157,7 +1139,7 @@ func TestPreparePlanCache4Function(t *testing.T) { tk.MustExec("set @a = 1, @b = null;") tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @b;").Check(testkit.Rows("0")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int);") @@ -1170,19 +1152,14 @@ func TestPreparePlanCache4Function(t *testing.T) { } func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() - tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") @@ -1290,18 +1267,14 @@ func TestPreparePlanCache4DifferentSystemVars(t *testing.T) { } func TestTemporaryTable4PlanCache(t *testing.T) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) tk := testkit.NewTestKit(t, store) - defer func() { - dom.Close() - require.NoError(t, store.Close()) - }() tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("drop table if exists tmp2") @@ -1321,10 +1294,7 @@ func TestTemporaryTable4PlanCache(t *testing.T) { } func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { - if israce.RaceEnabled { - t.Skip("race test for this case takes too long time") - } - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { @@ -1337,7 +1307,6 @@ func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") // create virtual tiflash replica. - dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) require.True(t, exists) @@ -1372,3 +1341,56 @@ func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { require.Equal(t, "select * from `t`", tk.Session().GetSessionVars().PreparedStmts[1].(*plannercore.CachedPrepareStmt).NormalizedSQL) require.Equal(t, "", tk.Session().GetSessionVars().PreparedStmts[1].(*plannercore.CachedPrepareStmt).NormalizedPlan) } + +func TestPreparePC4Binding(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := plannercore.PreparedPlanCacheEnabled() + defer func() { + plannercore.SetPreparedPlanCache(orgEnable) + }() + plannercore.SetPreparedPlanCache(true) // requires plan cache enable + tk := testkit.NewTestKit(t, store) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + + tk.MustExec("prepare stmt from \"select * from t\"") + require.Equal(t, 1, len(tk.Session().GetSessionVars().PreparedStmts)) + require.Equal(t, "select * from `test` . `t`", tk.Session().GetSessionVars().PreparedStmts[1].(*plannercore.CachedPrepareStmt).NormalizedSQL4PC) + + tk.MustQuery("execute stmt") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustExec("create binding for select * from t using select * from t") + res := tk.MustQuery("show session bindings") + require.Equal(t, 1, len(res.Rows())) + + tk.MustQuery("execute stmt") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) +} + +func TestIssue31141(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := plannercore.PreparedPlanCacheEnabled() + defer func() { + plannercore.SetPreparedPlanCache(orgEnable) + }() + plannercore.SetPreparedPlanCache(true) // requires plan cache enable + tk := testkit.NewTestKit(t, store) + + tk.MustExec("set @@tidb_txn_mode = 'pessimistic'") + + // No panic here. + tk.MustExec("prepare stmt1 from 'do 1'") + + tk.MustExec("set @@tidb_txn_mode = 'optimistic'") + tk.MustExec("prepare stmt1 from 'do 1'") +} diff --git a/executor/recover_table_test.go b/executor/recover_table_test.go new file mode 100644 index 0000000000000..4506c8e4e209b --- /dev/null +++ b/executor/recover_table_test.go @@ -0,0 +1,289 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "fmt" + "testing" + "time" + + "github.com/pingcap/failpoint" + ddlutil "github.com/pingcap/tidb/ddl/util" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/gcutil" + "github.com/stretchr/testify/require" +) + +func TestRecoverTable(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) + }() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") + tk.MustExec("drop table if exists t_recover") + tk.MustExec("create table t_recover (a int);") + + timeBeforeDrop, timeAfterDrop, safePointSQL, resetGC := MockGC(tk) + defer resetGC() + + tk.MustExec("insert into t_recover values (1),(2),(3)") + tk.MustExec("drop table t_recover") + + // if GC safe point is not exists in mysql.tidb + tk.MustGetErrMsg("recover table t_recover", "can not get 'tikv_gc_safe_point'") + // set GC safe point + tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) + + // Should recover, and we can drop it straight away. + tk.MustExec("recover table t_recover") + tk.MustExec("drop table t_recover") + + require.NoError(t, gcutil.EnableGC(tk.Session())) + + // recover job is before GC safe point + tk.MustExec(fmt.Sprintf(safePointSQL, timeAfterDrop)) + tk.MustContainErrMsg("recover table t_recover", "Can't find dropped/truncated table 't_recover' in GC safe point") + + // set GC safe point + tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) + // if there is a new table with the same name, should return failed. + tk.MustExec("create table t_recover (a int);") + tk.MustGetErrMsg("recover table t_recover", infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) + + // drop the new table with the same name, then recover table. + tk.MustExec("rename table t_recover to t_recover2") + + // do recover table. + tk.MustExec("recover table t_recover") + + // check recover table meta and data record. + tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) + // check recover table autoID. + tk.MustExec("insert into t_recover values (4),(5),(6)") + tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + // check rebase auto id. + tk.MustQuery("select a,_tidb_rowid from t_recover;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003")) + + // recover table by none exits job. + err := tk.ExecToErr(fmt.Sprintf("recover table by job %d", 10000000)) + require.Error(t, err) + + // Disable GC by manual first, then after recover table, the GC enable status should also be disabled. + require.NoError(t, gcutil.DisableGC(tk.Session())) + + tk.MustExec("delete from t_recover where a > 1") + tk.MustExec("drop table t_recover") + + tk.MustExec("recover table t_recover") + + // check recover table meta and data record. + tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1")) + // check recover table autoID. + tk.MustExec("insert into t_recover values (7),(8),(9)") + tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9")) + + // Recover truncate table. + tk.MustExec("truncate table t_recover") + tk.MustExec("rename table t_recover to t_recover_new") + tk.MustExec("recover table t_recover") + tk.MustExec("insert into t_recover values (10)") + tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "7", "8", "9", "10")) + + // Test for recover one table multiple time. + tk.MustExec("drop table t_recover") + tk.MustExec("flashback table t_recover to t_recover_tmp") + err = tk.ExecToErr("recover table t_recover") + require.True(t, infoschema.ErrTableExists.Equal(err)) + + gcEnable, err := gcutil.CheckGCEnable(tk.Session()) + require.NoError(t, err) + require.False(t, gcEnable) +} + +func TestFlashbackTable(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) + }() + + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists test_flashback") + tk.MustExec("use test_flashback") + tk.MustExec("drop table if exists t_flashback") + tk.MustExec("create table t_flashback (a int);") + + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) + defer resetGC() + + // Set GC safe point + tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) + // Set GC enable. + require.NoError(t, gcutil.EnableGC(tk.Session())) + + tk.MustExec("insert into t_flashback values (1),(2),(3)") + tk.MustExec("drop table t_flashback") + + // Test flash table with not_exist_table_name name. + tk.MustGetErrMsg("flashback table t_not_exists", "Can't find localTemporary/dropped/truncated table: t_not_exists in DDL history jobs") + + // Test flashback table failed by there is already a new table with the same name. + // If there is a new table with the same name, should return failed. + tk.MustExec("create table t_flashback (a int);") + tk.MustGetErrMsg("flashback table t_flashback", infoschema.ErrTableExists.GenWithStackByArgs("t_flashback").Error()) + + // Drop the new table with the same name, then flashback table. + tk.MustExec("rename table t_flashback to t_flashback_tmp") + + // Test for flashback table. + tk.MustExec("flashback table t_flashback") + // Check flashback table meta and data record. + tk.MustQuery("select * from t_flashback;").Check(testkit.Rows("1", "2", "3")) + // Check flashback table autoID. + tk.MustExec("insert into t_flashback values (4),(5),(6)") + tk.MustQuery("select * from t_flashback;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + // Check rebase auto id. + tk.MustQuery("select a,_tidb_rowid from t_flashback;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003")) + + // Test for flashback to new table. + tk.MustExec("drop table t_flashback") + tk.MustExec("create table t_flashback (a int);") + tk.MustExec("flashback table t_flashback to t_flashback2") + // Check flashback table meta and data record. + tk.MustQuery("select * from t_flashback2;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) + // Check flashback table autoID. + tk.MustExec("insert into t_flashback2 values (7),(8),(9)") + tk.MustQuery("select * from t_flashback2;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) + // Check rebase auto id. + tk.MustQuery("select a,_tidb_rowid from t_flashback2;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003", "7 10001", "8 10002", "9 10003")) + + // Test for flashback one table multiple time. + err := tk.ExecToErr("flashback table t_flashback to t_flashback4") + require.True(t, infoschema.ErrTableExists.Equal(err)) + + // Test for flashback truncated table to new table. + tk.MustExec("truncate table t_flashback2") + tk.MustExec("flashback table t_flashback2 to t_flashback3") + // Check flashback table meta and data record. + tk.MustQuery("select * from t_flashback3;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9")) + // Check flashback table autoID. + tk.MustExec("insert into t_flashback3 values (10),(11)") + tk.MustQuery("select * from t_flashback3;").Check(testkit.Rows("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")) + // Check rebase auto id. + tk.MustQuery("select a,_tidb_rowid from t_flashback3;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003", "7 10001", "8 10002", "9 10003", "10 15001", "11 15002")) + + // Test for flashback drop partition table. + tk.MustExec("drop table if exists t_p_flashback") + tk.MustExec("create table t_p_flashback (a int) partition by hash(a) partitions 4;") + tk.MustExec("insert into t_p_flashback values (1),(2),(3)") + tk.MustExec("drop table t_p_flashback") + tk.MustExec("flashback table t_p_flashback") + // Check flashback table meta and data record. + tk.MustQuery("select * from t_p_flashback order by a;").Check(testkit.Rows("1", "2", "3")) + // Check flashback table autoID. + tk.MustExec("insert into t_p_flashback values (4),(5)") + tk.MustQuery("select a,_tidb_rowid from t_p_flashback order by a;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002")) + + // Test for flashback truncate partition table. + tk.MustExec("truncate table t_p_flashback") + tk.MustExec("flashback table t_p_flashback to t_p_flashback1") + // Check flashback table meta and data record. + tk.MustQuery("select * from t_p_flashback1 order by a;").Check(testkit.Rows("1", "2", "3", "4", "5")) + // Check flashback table autoID. + tk.MustExec("insert into t_p_flashback1 values (6)") + tk.MustQuery("select a,_tidb_rowid from t_p_flashback1 order by a;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 10001")) + + tk.MustExec("drop database if exists Test2") + tk.MustExec("create database Test2") + tk.MustExec("use Test2") + tk.MustExec("create table t (a int);") + tk.MustExec("insert into t values (1),(2)") + tk.MustExec("drop table t") + tk.MustExec("flashback table t") + tk.MustQuery("select a from t order by a").Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table t") + tk.MustExec("drop database if exists Test3") + tk.MustExec("create database Test3") + tk.MustExec("use Test3") + tk.MustExec("create table t (a int);") + tk.MustExec("drop table t") + tk.MustExec("drop database Test3") + tk.MustExec("use Test2") + tk.MustExec("flashback table t") + tk.MustExec("insert into t values (3)") + tk.MustQuery("select a from t order by a").Check(testkit.Rows("1", "2", "3")) +} + +func TestRecoverTempTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") + tk.MustExec("drop table if exists t_recover") + tk.MustExec("create global temporary table t_recover (a int) on commit delete rows;") + + tk.MustExec("use test_recover") + tk.MustExec("drop table if exists tmp2_recover") + tk.MustExec("create temporary table tmp2_recover (a int);") + + timeBeforeDrop, _, safePointSQL, resetGC := MockGC(tk) + defer resetGC() + // Set GC safe point + tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) + + tk.MustExec("drop table t_recover") + tk.MustGetErrCode("recover table t_recover;", errno.ErrUnsupportedDDLOperation) + tk.MustGetErrCode("flashback table t_recover;", errno.ErrUnsupportedDDLOperation) + tk.MustExec("drop table tmp2_recover") + tk.MustGetErrMsg("recover table tmp2_recover;", "Can't find localTemporary/dropped/truncated table: tmp2_recover in DDL history jobs") + tk.MustGetErrMsg("flashback table tmp2_recover;", "Can't find localTemporary/dropped/truncated table: tmp2_recover in DDL history jobs") +} + +// MockGC is used to make GC work in the test environment. +func MockGC(tk *testkit.TestKit) (string, string, string, func()) { + originGC := ddlutil.IsEmulatorGCEnable() + resetGC := func() { + if originGC { + ddlutil.EmulatorGCEnable() + } else { + ddlutil.EmulatorGCDisable() + } + } + + // disable emulator GC. + // Otherwise emulator GC will delete table record as soon as possible after execute drop table ddl. + ddlutil.EmulatorGCDisable() + gcTimeFormat := "20060102-15:04:05 -0700 MST" + timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) + timeAfterDrop := time.Now().Add(48 * 60 * 60 * time.Second).Format(gcTimeFormat) + safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + // clear GC variables first. + tk.MustExec("delete from mysql.tidb where variable_name in ( 'tikv_gc_safe_point','tikv_gc_enable' )") + return timeBeforeDrop, timeAfterDrop, safePointSQL, resetGC +} diff --git a/executor/reload_expr_pushdown_blacklist.go b/executor/reload_expr_pushdown_blacklist.go index 81c8ea4f3cccb..1511e7a280195 100644 --- a/executor/reload_expr_pushdown_blacklist.go +++ b/executor/reload_expr_pushdown_blacklist.go @@ -39,11 +39,7 @@ func (e *ReloadExprPushdownBlacklistExec) Next(ctx context.Context, _ *chunk.Chu // LoadExprPushdownBlacklist loads the latest data from table mysql.expr_pushdown_blacklist. func LoadExprPushdownBlacklist(ctx sessionctx.Context) (err error) { exec := ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), "select HIGH_PRIORITY name, store_type from mysql.expr_pushdown_blacklist") - if err != nil { - return err - } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, "select HIGH_PRIORITY name, store_type from mysql.expr_pushdown_blacklist") if err != nil { return err } diff --git a/executor/replace.go b/executor/replace.go index 78e0085aa520e..fe1930639f446 100644 --- a/executor/replace.go +++ b/executor/replace.go @@ -223,6 +223,7 @@ func (e *ReplaceExec) exec(ctx context.Context, newRows [][]types.Datum) error { } } setResourceGroupTaggerForTxn(e.ctx.GetSessionVars().StmtCtx, txn) + setRPCInterceptorOfExecCounterForTxn(e.ctx.GetSessionVars(), txn) prefetchStart := time.Now() // Use BatchGet to fill cache. // It's an optimization and could be removed without affecting correctness. diff --git a/executor/resource_tag_test.go b/executor/resource_tag_test.go new file mode 100644 index 0000000000000..605a7f323b573 --- /dev/null +++ b/executor/resource_tag_test.go @@ -0,0 +1,217 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "strings" + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/parser" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/store/mockstore/unistore" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/pingcap/tipb/go-tipb" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/tikvrpc" +) + +func TestResourceGroupTag(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int, b int, unique index idx(a));") + + tbInfo := external.GetTableByName(t, tk, "test", "t") + + // Enable Top SQL + topsqlstate.EnableTopSQL() + config.UpdateGlobal(func(conf *config.Config) { + conf.TopSQL.ReceiverAddress = "mock-agent" + }) + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook", `return(true)`)) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook")) + }() + + var sqlDigest, planDigest *parser.Digest + var tagLabel tipb.ResourceGroupTagLabel + checkFn := func() {} + unistore.UnistoreRPCClientSendHook = func(req *tikvrpc.Request) { + var startKey []byte + var ctx *kvrpcpb.Context + switch req.Type { + case tikvrpc.CmdGet: + request := req.Get() + startKey = request.Key + ctx = request.Context + case tikvrpc.CmdBatchGet: + request := req.BatchGet() + startKey = request.Keys[0] + ctx = request.Context + case tikvrpc.CmdPrewrite: + request := req.Prewrite() + startKey = request.Mutations[0].Key + ctx = request.Context + case tikvrpc.CmdCommit: + request := req.Commit() + startKey = request.Keys[0] + ctx = request.Context + case tikvrpc.CmdCop: + request := req.Cop() + startKey = request.Ranges[0].Start + ctx = request.Context + case tikvrpc.CmdPessimisticLock: + request := req.PessimisticLock() + startKey = request.PrimaryLock + ctx = request.Context + } + tid := tablecodec.DecodeTableID(startKey) + if tid != tbInfo.Meta().ID { + return + } + if ctx == nil { + return + } + tag := &tipb.ResourceGroupTag{} + err := tag.Unmarshal(ctx.ResourceGroupTag) + require.NoError(t, err) + sqlDigest = parser.NewDigest(tag.SqlDigest) + planDigest = parser.NewDigest(tag.PlanDigest) + tagLabel = *tag.Label + checkFn() + } + + resetVars := func() { + sqlDigest = parser.NewDigest(nil) + planDigest = parser.NewDigest(nil) + } + + cases := []struct { + sql string + tagLabels map[tipb.ResourceGroupTagLabel]struct{} + ignore bool + }{ + { + sql: "insert into t values(1,1),(2,2),(3,3)", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "select * from t use index (idx) where a=1", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "select * from t use index (idx) where a in (1,2,3)", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "select * from t use index (idx) where a>1", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "select * from t where b>1", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, + }, + }, + { + sql: "select a from t use index (idx) where a>1", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "begin pessimistic", + ignore: true, + }, + { + sql: "insert into t values(4,4)", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelRow: {}, + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "commit", + ignore: true, + }, + { + sql: "update t set a=5,b=5 where a=5", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + { + sql: "replace into t values(6,6)", + tagLabels: map[tipb.ResourceGroupTagLabel]struct{}{ + tipb.ResourceGroupTagLabel_ResourceGroupTagLabelIndex: {}, + }, + }, + } + for _, ca := range cases { + resetVars() + + _, expectSQLDigest := parser.NormalizeDigest(ca.sql) + var expectPlanDigest *parser.Digest + checkCnt := 0 + checkFn = func() { + if ca.ignore { + return + } + if expectPlanDigest == nil { + info := tk.Session().ShowProcess() + require.NotNil(t, info) + p, ok := info.Plan.(plannercore.Plan) + require.True(t, ok) + _, expectPlanDigest = plannercore.NormalizePlan(p) + } + require.Equal(t, sqlDigest.String(), expectSQLDigest.String(), "%v", ca.sql) + require.Equal(t, planDigest.String(), expectPlanDigest.String()) + _, ok := ca.tagLabels[tagLabel] + require.True(t, ok) + checkCnt++ + } + + if strings.HasPrefix(ca.sql, "select") { + tk.MustQuery(ca.sql) + } else { + tk.MustExec(ca.sql) + } + if ca.ignore { + continue + } + require.Greater(t, checkCnt, 0, "%v", ca.sql) + } +} diff --git a/executor/revoke_test.go b/executor/revoke_test.go index 185ba00129fdd..92cd7d79517b6 100644 --- a/executor/revoke_test.go +++ b/executor/revoke_test.go @@ -17,19 +17,22 @@ package executor_test import ( "fmt" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite1) TestRevokeGlobal(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRevokeGlobal(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) _, err := tk.Exec(`REVOKE ALL PRIVILEGES ON *.* FROM 'nonexistuser'@'host'`) - c.Assert(err, NotNil) + require.Error(t, err) // Create a new user. createUserSQL := `CREATE USER 'testGlobalRevoke'@'localhost' IDENTIFIED BY '123';` @@ -53,14 +56,16 @@ func (s *testSuite1) TestRevokeGlobal(c *C) { } } -func (s *testSuite1) TestRevokeDBScope(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRevokeDBScope(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Create a new user. tk.MustExec(`CREATE USER 'testDBRevoke'@'localhost' IDENTIFIED BY '123';`) tk.MustExec(`GRANT ALL ON test.* TO 'testDBRevoke'@'localhost';`) _, err := tk.Exec(`REVOKE ALL PRIVILEGES ON nonexistdb.* FROM 'testDBRevoke'@'localhost'`) - c.Assert(err, NotNil) + require.Error(t, err) // Revoke each priv from the user. for _, v := range mysql.AllDBPrivs { @@ -73,28 +78,30 @@ func (s *testSuite1) TestRevokeDBScope(c *C) { } } -func (s *testSuite1) TestRevokeTableScope(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRevokeTableScope(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Create a new user. tk.MustExec(`CREATE USER 'testTblRevoke'@'localhost' IDENTIFIED BY '123';`) tk.MustExec(`CREATE TABLE test.test1(c1 int);`) tk.MustExec(`GRANT ALL PRIVILEGES ON test.test1 TO 'testTblRevoke'@'localhost';`) _, err := tk.Exec(`REVOKE ALL PRIVILEGES ON test.nonexisttable FROM 'testTblRevoke'@'localhost'`) - c.Assert(err, NotNil) + require.Error(t, err) // Make sure all the table privs for new user is Y. res := tk.MustQuery(`SELECT Table_priv FROM mysql.tables_priv WHERE User="testTblRevoke" and host="localhost" and db="test" and Table_name="test1"`) - res.Check(testkit.Rows("Select,Insert,Update,Delete,Create,Drop,Index,Alter,Create View,Show View,References")) + res.Check(testkit.Rows("Select,Insert,Update,Delete,Create,Drop,Index,Alter,Create View,Show View,Trigger,References")) // Revoke each priv from the user. for _, v := range mysql.AllTablePrivs { sql := fmt.Sprintf("REVOKE %s ON test.test1 FROM 'testTblRevoke'@'localhost';", mysql.Priv2Str[v]) tk.MustExec(sql) rows := tk.MustQuery(`SELECT Table_priv FROM mysql.tables_priv WHERE User="testTblRevoke" and host="localhost" and db="test" and Table_name="test1";`).Rows() - c.Assert(rows, HasLen, 1) + require.Len(t, rows, 1) row := rows[0] - c.Assert(row, HasLen, 1) + require.Len(t, row, 1) op := v.SetString() found := false @@ -104,7 +111,7 @@ func (s *testSuite1) TestRevokeTableScope(c *C) { break } } - c.Assert(found, IsFalse, Commentf("%s", mysql.Priv2SetStr[v])) + require.False(t, found, "%s", mysql.Priv2SetStr[v]) } // Revoke all table scope privs. @@ -112,8 +119,10 @@ func (s *testSuite1) TestRevokeTableScope(c *C) { tk.MustQuery(`SELECT Table_priv FROM mysql.Tables_priv WHERE User="testTblRevoke" and host="localhost" and db="test" and Table_name="test1"`).Check(testkit.Rows("")) } -func (s *testSuite1) TestRevokeColumnScope(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRevokeColumnScope(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Create a new user. tk.MustExec(`CREATE USER 'testColRevoke'@'localhost' IDENTIFIED BY '123';`) tk.MustExec(`CREATE TABLE test.test3(c1 int, c2 int);`) @@ -127,11 +136,11 @@ func (s *testSuite1) TestRevokeColumnScope(c *C) { tk.MustExec(grantSQL) rows := tk.MustQuery(checkSQL).Rows() - c.Assert(rows, HasLen, 1) + require.Len(t, rows, 1) row := rows[0] - c.Assert(row, HasLen, 1) + require.Len(t, row, 1) p := fmt.Sprintf("%v", row[0]) - c.Assert(strings.Index(p, mysql.Priv2SetStr[v]), Greater, -1) + require.Greater(t, strings.Index(p, mysql.Priv2SetStr[v]), -1) tk.MustExec(revokeSQL) tk.MustQuery(checkSQL).Check(testkit.Rows("")) @@ -145,18 +154,20 @@ func (s *testSuite1) TestRevokeColumnScope(c *C) { // Make sure all the column privs for granted user are in the Column_priv set. for _, v := range mysql.AllColumnPrivs { rows := tk.MustQuery(`SELECT Column_priv FROM mysql.Columns_priv WHERE User="testCol1Revoke" and host="localhost" and db="test" and Table_name="test3" and Column_name="c2";`).Rows() - c.Assert(rows, HasLen, 1) + require.Len(t, rows, 1) row := rows[0] - c.Assert(row, HasLen, 1) + require.Len(t, row, 1) p := fmt.Sprintf("%v", row[0]) - c.Assert(strings.Index(p, mysql.Priv2SetStr[v]), Greater, -1) + require.Greater(t, strings.Index(p, mysql.Priv2SetStr[v]), -1) } tk.MustExec("REVOKE ALL(c2) ON test3 FROM 'testCol1Revoke'@'localhost'") tk.MustQuery(`SELECT Column_priv FROM mysql.Columns_priv WHERE User="testCol1Revoke" and host="localhost" and db="test" and Table_name="test3"`).Check(testkit.Rows("")) } -func (s *testSuite1) TestRevokeDynamicPrivs(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRevokeDynamicPrivs(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("DROP USER if exists dyn") tk.MustExec("create user dyn") @@ -166,7 +177,7 @@ func (s *testSuite1) TestRevokeDynamicPrivs(c *C) { // try revoking only on test.* - should fail: _, err := tk.Exec("REVOKE BACKUP_Admin,system_variables_admin ON test.* FROM dyn") - c.Assert(terror.ErrorEqual(err, executor.ErrIllegalPrivilegeLevel), IsTrue) + require.True(t, terror.ErrorEqual(err, executor.ErrIllegalPrivilegeLevel)) // privs should still be intact: tk.MustQuery("SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option").Check(testkit.Rows("dyn % BACKUP_ADMIN N")) @@ -195,9 +206,11 @@ func (s *testSuite1) TestRevokeDynamicPrivs(c *C) { tk.MustQuery("SELECT * FROM mysql.global_grants WHERE `Host` = '%' AND `User` = 'dyn' ORDER BY user,host,priv,with_grant_option").Check(testkit.Rows("dyn % SYSTEM_VARIABLES_ADMIN Y")) } -func (s *testSuite1) TestRevokeOnNonExistTable(c *C) { +func TestRevokeOnNonExistTable(t *testing.T) { // issue #28533 - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE d1;") defer tk.MustExec("DROP DATABASE IF EXISTS d1;") diff --git a/executor/rowid_test.go b/executor/rowid_test.go index d7664f1e0fb1c..6a32fb6086977 100644 --- a/executor/rowid_test.go +++ b/executor/rowid_test.go @@ -15,18 +15,23 @@ package executor_test import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite1) TestExportRowID(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.Se.GetSessionVars().AllowWriteRowID = true +func TestExportRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.Session().GetSessionVars().AllowWriteRowID = true defer func() { - tk.Se.GetSessionVars().AllowWriteRowID = false + tk.Session().GetSessionVars().AllowWriteRowID = false }() + tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int)") tk.MustExec("insert t values (1, 7), (1, 8), (1, 9)") @@ -48,25 +53,27 @@ func (s *testSuite1) TestExportRowID(c *C) { tk.MustExec("create table s (a int primary key)") tk.MustExec("insert s values (1)") _, err := tk.Exec("insert s (a, _tidb_rowid) values (1, 2)") - c.Assert(err, NotNil) + require.Error(t, err) err = tk.ExecToErr("select _tidb_rowid from s") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("update s set a = 2 where _tidb_rowid = 1") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("delete from s where _tidb_rowid = 1") - c.Assert(err, NotNil) + require.Error(t, err) // Make sure "AllowWriteRowID" is a session variable. - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") _, err = tk1.Exec("insert into t (a, _tidb_rowid) values(10, 1);") - c.Assert(err.Error(), Equals, "insert, update and replace statements for _tidb_rowid are not supported.") + require.EqualError(t, err, "insert, update and replace statements for _tidb_rowid are not supported") } -func (s *testSuite1) TestNotAllowWriteRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNotAllowWriteRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table tt(id binary(10), c int, primary key(id));") tk.MustExec("insert tt values (1, 10);") // select statement @@ -74,13 +81,13 @@ func (s *testSuite1) TestNotAllowWriteRowID(c *C) { Check(testkit.Rows("1\x00\x00\x00\x00\x00\x00\x00\x00\x00 10 1")) // insert statement _, err := tk.Exec("insert into tt (id, c, _tidb_rowid) values(30000,10,1);") - c.Assert(err.Error(), Equals, "insert, update and replace statements for _tidb_rowid are not supported.") + require.EqualError(t, err, "insert, update and replace statements for _tidb_rowid are not supported") // replace statement _, err = tk.Exec("replace into tt (id, c, _tidb_rowid) values(30000,10,1);") - c.Assert(err.Error(), Equals, "insert, update and replace statements for _tidb_rowid are not supported.") + require.EqualError(t, err, "insert, update and replace statements for _tidb_rowid are not supported") // update statement _, err = tk.Exec("update tt set id = 2, _tidb_rowid = 1 where _tidb_rowid = 1") - c.Assert(err.Error(), Equals, "insert, update and replace statements for _tidb_rowid are not supported.") + require.EqualError(t, err, "insert, update and replace statements for _tidb_rowid are not supported") tk.MustExec("update tt set id = 2 where _tidb_rowid = 1") tk.MustExec("admin check table tt;") tk.MustExec("drop table tt") @@ -91,8 +98,10 @@ func (s *testSuite1) TestNotAllowWriteRowID(c *C) { } // Test for https://github.com/pingcap/tidb/issues/22029. -func (s *testSuite3) TestExplicitInsertRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplicitInsertRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_explicit_insert_rowid;") tk.MustExec("create database test_explicit_insert_rowid;") tk.MustExec("use test_explicit_insert_rowid;") diff --git a/executor/sample.go b/executor/sample.go index 5d57c9a792443..10d2b2f3d1716 100644 --- a/executor/sample.go +++ b/executor/sample.go @@ -17,7 +17,6 @@ package executor import ( "context" "sort" - "time" "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" @@ -154,14 +153,14 @@ func (s *tableRegionSampler) pickRanges(count int) ([]kv.KeyRange, error) { } func (s *tableRegionSampler) writeChunkFromRanges(ranges []kv.KeyRange, req *chunk.Chunk) error { - decLoc, sysLoc := s.ctx.GetSessionVars().Location(), time.UTC + decLoc := s.ctx.GetSessionVars().Location() cols, decColMap, err := s.buildSampleColAndDecodeColMap() if err != nil { return err } rowDecoder := decoder.NewRowDecoder(s.table, cols, decColMap) err = s.scanFirstKVForEachRange(ranges, func(handle kv.Handle, value []byte) error { - _, err := rowDecoder.DecodeAndEvalRowWithMap(s.ctx, handle, value, decLoc, sysLoc, s.rowMap) + _, err := rowDecoder.DecodeAndEvalRowWithMap(s.ctx, handle, value, decLoc, s.rowMap) if err != nil { return err } diff --git a/executor/sample_test.go b/executor/sample_test.go index d200919081e84..4a1ec83c818e0 100644 --- a/executor/sample_test.go +++ b/executor/sample_test.go @@ -15,59 +15,21 @@ package executor_test import ( - "flag" "fmt" "sync/atomic" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/ddl" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util/testkit" - "github.com/tikv/client-go/v2/testutils" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testTableSampleSuite{}) - -type testTableSampleSuite struct { - cluster testutils.Cluster - store kv.Storage - domain *domain.Domain -} - -func (s *testTableSampleSuite) SetUpSuite(c *C) { - flag.Lookup("mockTikv") - useMockTikv := *mockTikv - if useMockTikv { - store, err := mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - s.store = store - session.SetSchemaLease(0) - session.DisableStats4Test() - } - d, err := session.BootstrapSession(s.store) - c.Assert(err, IsNil) - d.SetStatsUpdating(true) - s.domain = d -} - -func (s *testTableSampleSuite) TearDownSuite(c *C) { - s.domain.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testTableSampleSuite) initSampleTest(c *C) *testkit.TestKit { +func createSampleTestkit(t *testing.T, store kv.Storage) *testkit.TestKit { atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_table_sample;") tk.MustExec("create database test_table_sample;") tk.MustExec("use test_table_sample;") @@ -75,10 +37,12 @@ func (s *testTableSampleSuite) initSampleTest(c *C) *testkit.TestKit { return tk } -func (s *testTableSampleSuite) TestTableSampleBasic(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleBasic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int);") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows()) tk.MustExec("insert into t values (0), (1000), (2000);") @@ -88,7 +52,7 @@ func (s *testTableSampleSuite) TestTableSampleBasic(c *C) { tk.MustExec("alter table t add column c int as (a + 1);") tk.MustQuery("select c from t tablesample regions();").Check(testkit.Rows("1")) tk.MustQuery("select c, _tidb_rowid from t tablesample regions();").Check(testkit.Rows("1 1")) - c.Assert(tk.HasPlan("select * from t tablesample regions();", "TableSample"), IsTrue) + require.True(t, tk.HasPlan("select * from t tablesample regions();", "TableSample")) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a BIGINT PRIMARY KEY AUTO_RANDOM(3), b int auto_increment, key(b)) pre_split_regions=8;") @@ -105,14 +69,16 @@ func (s *testTableSampleSuite) TestTableSampleBasic(c *C) { tk.MustQuery("select a from t tablesample regions() limit 2;").Check(testkit.Rows("a", "b")) } -func (s *testTableSampleSuite) TestTableSampleMultiRegions(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleMultiRegions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int) shard_row_id_bits = 2 pre_split_regions = 2;") for i := 0; i < 100; i++ { tk.MustExec("insert into t values (?);", i) } rows := tk.MustQuery("select * from t tablesample regions();").Rows() - c.Assert(len(rows), Equals, 4) + require.Len(t, rows, 4) tk.MustQuery("select a from t tablesample regions() order by a limit 1;").Check(testkit.Rows("0")) tk.MustQuery("select a from t tablesample regions() where a = 0;").Check(testkit.Rows("0")) @@ -121,13 +87,15 @@ func (s *testTableSampleSuite) TestTableSampleMultiRegions(c *C) { tk.MustExec("insert into t2 values (?);", i) } rows = tk.MustQuery("select * from t tablesample regions(), t2 tablesample regions();").Rows() - c.Assert(len(rows), Equals, 16) + require.Len(t, rows, 16) tk.MustQuery("select count(*) from t tablesample regions();").Check(testkit.Rows("4")) tk.MustExec("drop table t2;") } -func (s *testTableSampleSuite) TestTableSampleNoSplitTable(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleNoSplitTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) tk.MustExec("drop table if exists t1;") tk.MustExec("drop table if exists t2;") @@ -136,25 +104,29 @@ func (s *testTableSampleSuite) TestTableSampleNoSplitTable(c *C) { tk.MustExec("insert into t2 values(1);") rows := tk.MustQuery("select * from t1 tablesample regions();").Rows() rows2 := tk.MustQuery("select * from t2 tablesample regions();").Rows() - c.Assert(len(rows), Equals, 0) - c.Assert(len(rows2), Equals, 1) + require.Len(t, rows, 0) + require.Len(t, rows2, 1) } -func (s *testTableSampleSuite) TestTableSamplePlan(c *C) { - tk := s.initSampleTest(c) +func TestTableSamplePlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a bigint, b int default 10);") tk.MustExec("split table t between (0) and (100000) regions 4;") tk.MustExec("insert into t(a) values (1), (2), (3);") rows := tk.MustQuery("explain analyze select a from t tablesample regions();").Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) tableSample := fmt.Sprintf("%v", rows[1]) - c.Assert(tableSample, Matches, ".*TableSample.*") + require.Regexp(t, ".*TableSample.*", tableSample) } -func (s *testTableSampleSuite) TestTableSampleSchema(c *C) { - tk := s.initSampleTest(c) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn +func TestTableSampleSchema(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn // Clustered index tk.MustExec("create table t (a varchar(255) primary key, b bigint);") tk.MustExec("insert into t values ('b', 100), ('y', 100);") @@ -182,8 +154,10 @@ func (s *testTableSampleSuite) TestTableSampleSchema(c *C) { tk.MustQuery("select a from t tablesample regions();").Check(testkit.Rows("1")) } -func (s *testTableSampleSuite) TestTableSampleInvalid(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleInvalid(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int, b varchar(255));") tk.MustExec("insert into t values (1, 'abc');") tk.MustExec("create view v as select * from t;") @@ -196,8 +170,10 @@ func (s *testTableSampleSuite) TestTableSampleInvalid(c *C) { tk.MustGetErrCode("select a from t tablesample ();", errno.ErrInvalidTableSample) } -func (s *testTableSampleSuite) TestTableSampleWithTiDBRowID(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleWithTiDBRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int, b varchar(255));") tk.MustExec("insert into t values (1, 'abc');") tk.MustQuery("select _tidb_rowid from t tablesample regions();").Check(testkit.Rows("1")) @@ -206,19 +182,21 @@ func (s *testTableSampleSuite) TestTableSampleWithTiDBRowID(c *C) { tk.MustQuery("select b, _tidb_rowid, a from t tablesample regions();").Check(testkit.Rows("abc 1 1")) } -func (s *testTableSampleSuite) TestTableSampleWithPartition(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleWithPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int, b varchar(255), primary key (a)) partition by hash(a) partitions 2;") tk.MustExec("insert into t values (1, '1'), (2, '2'), (3, '3');") rows := tk.MustQuery("select * from t tablesample regions();").Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) tk.MustExec("delete from t;") tk.MustExec("insert into t values (1, '1');") rows = tk.MustQuery("select * from t partition (p0) tablesample regions();").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) rows = tk.MustQuery("select * from t partition (p1) tablesample regions();").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) // Test https://github.com/pingcap/tidb/issues/27349. tk.MustExec("drop table if exists t;") @@ -232,8 +210,10 @@ func (s *testTableSampleSuite) TestTableSampleWithPartition(c *C) { Check(testkit.Rows("1", "2", "3")) // The order of _tidb_rowid should be correct. } -func (s *testTableSampleSuite) TestTableSampleGeneratedColumns(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleGeneratedColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int primary key, b int as (a + 1), c int as (b + 1), d int as (c + 1));") tk.MustQuery("split table t between (0) and (10000) regions 4;").Check(testkit.Rows("3 1")) tk.MustExec("insert into t(a) values (1), (2), (2999), (4999), (9999);") @@ -247,8 +227,10 @@ func (s *testTableSampleSuite) TestTableSampleGeneratedColumns(c *C) { testkit.Rows("1 4", "2999 3002", "9999 10002")) } -func (s *testTableSampleSuite) TestTableSampleUnionScanIgnorePendingKV(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleUnionScanIgnorePendingKV(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int primary key);") tk.MustQuery("split table t between (0) and (40000) regions 4;").Check(testkit.Rows("3 1")) tk.MustExec("insert into t values (1), (1000), (10002);") @@ -265,9 +247,12 @@ func (s *testTableSampleSuite) TestTableSampleUnionScanIgnorePendingKV(c *C) { tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows("1000", "10002", "20006", "50000")) } -func (s *testTableSampleSuite) TestTableSampleTransactionConsistency(c *C) { - tk := s.initSampleTest(c) - tk2 := s.initSampleTest(c) +func TestTableSampleTransactionConsistency(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) + tk2 := createSampleTestkit(t, store) + tk.MustExec("create table t (a int primary key);") tk.MustQuery("split table t between (0) and (40000) regions 4;").Check(testkit.Rows("3 1")) tk.MustExec("insert into t values (1), (1000), (10002);") @@ -280,8 +265,10 @@ func (s *testTableSampleSuite) TestTableSampleTransactionConsistency(c *C) { tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows("1", "10002", "20006", "50000")) } -func (s *testTableSampleSuite) TestTableSampleNotSupportedPlanWarning(c *C) { - tk := s.initSampleTest(c) +func TestTableSampleNotSupportedPlanWarning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int primary key, b int, c varchar(255));") tk.MustQuery("split table t between (0) and (10000) regions 5;").Check(testkit.Rows("4 1")) tk.MustExec("insert into t values (1000, 1, '1'), (1001, 1, '1'), (2100, 2, '2'), (4500, 3, '3');") @@ -294,13 +281,15 @@ func (s *testTableSampleSuite) TestTableSampleNotSupportedPlanWarning(c *C) { tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 8128 Invalid TABLESAMPLE: plan not supported")) } -func (s *testTableSampleSuite) TestMaxChunkSize(c *C) { - tk := s.initSampleTest(c) +func TestMaxChunkSize(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createSampleTestkit(t, store) tk.MustExec("create table t (a int) shard_row_id_bits = 2 pre_split_regions = 2;") for i := 0; i < 100; i++ { tk.MustExec("insert into t values (?);", i) } - tk.Se.GetSessionVars().MaxChunkSize = 1 + tk.Session().GetSessionVars().MaxChunkSize = 1 rows := tk.MustQuery("select * from t tablesample regions();").Rows() - c.Assert(len(rows), Equals, 4) + require.Len(t, rows, 4) } diff --git a/executor/select_into.go b/executor/select_into.go index 24de3cd9fb599..5003f1dbf9fd1 100644 --- a/executor/select_into.go +++ b/executor/select_into.go @@ -52,7 +52,8 @@ func (s *SelectIntoExec) Open(ctx context.Context) error { return errors.New("unsupported SelectInto type") } - f, err := os.OpenFile(s.intoOpt.FileName, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + // MySQL-compatible behavior: allow files to be group-readable + f, err := os.OpenFile(s.intoOpt.FileName, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0640) // # nosec G302 if err != nil { return errors.Trace(err) } @@ -211,6 +212,7 @@ func (s *SelectIntoExec) dumpToOutfile() error { return errors.Trace(err) } } + s.ctx.GetSessionVars().StmtCtx.AddAffectedRows(uint64(s.chk.NumRows())) return nil } diff --git a/executor/select_into_test.go b/executor/select_into_test.go index e9d3905e10811..616dcd30c45d6 100644 --- a/executor/select_into_test.go +++ b/executor/select_into_test.go @@ -19,57 +19,61 @@ import ( "os" "path/filepath" "strings" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -func cmpAndRm(expected, outfile string, c *C) { +func cmpAndRm(expected, outfile string, t *testing.T) { content, err := os.ReadFile(outfile) - c.Assert(err, IsNil) - c.Assert(string(content), Equals, expected) - c.Assert(os.Remove(outfile), IsNil) + require.NoError(t, err) + require.Equal(t, expected, string(content)) + require.NoError(t, os.Remove(outfile)) } func randomSelectFilePath(testName string) string { return filepath.Join(os.TempDir(), fmt.Sprintf("select-into-%v-%v.data", testName, time.Now().Nanosecond())) } -func (s *testSuite1) TestSelectIntoFileExists(c *C) { +func TestSelectIntoFileExists(t *testing.T) { outfile := randomSelectFilePath("TestSelectIntoFileExists") defer func() { - c.Assert(os.Remove(outfile), IsNil) + require.NoError(t, os.Remove(outfile)) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) sql := fmt.Sprintf("select 1 into outfile %q", outfile) tk.MustExec(sql) err := tk.ExecToErr(sql) - c.Assert(err, NotNil) - c.Assert(strings.Contains(err.Error(), "already exists") || - strings.Contains(err.Error(), "file exists"), IsTrue, Commentf("err: %v", err)) - c.Assert(strings.Contains(err.Error(), outfile), IsTrue) + require.Error(t, err) + require.Truef(t, strings.Contains(err.Error(), "already exists") || strings.Contains(err.Error(), "file exists"), "err: %v", err) + require.True(t, strings.Contains(err.Error(), outfile)) } -func (s *testSuite1) TestSelectIntoOutfileTypes(c *C) { +func TestSelectIntoOutfileTypes(t *testing.T) { outfile := randomSelectFilePath("TestSelectIntoOutfileTypes") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` ( `a` bit(10) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") tk.MustExec("INSERT INTO `t` VALUES (_binary '\\0'), (_binary '\\1'), (_binary '\\2'), (_binary '\\3');") tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) - cmpAndRm("\x00\x00\n\x001\n\x002\n\x003\n", outfile, c) + cmpAndRm("\x00\x00\n\x001\n\x002\n\x003\n", outfile, t) tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` (col ENUM ('value1','value2','value3'));") tk.MustExec("INSERT INTO t values ('value1'), ('value2');") tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) - cmpAndRm("value1\nvalue2\n", outfile, c) + cmpAndRm("value1\nvalue2\n", outfile, t) tk.MustExec("drop table if exists t") tk.MustExec("create table t ( v json);") @@ -77,7 +81,7 @@ func (s *testSuite1) TestSelectIntoOutfileTypes(c *C) { tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) cmpAndRm(`{"id": 1, "name": "aaa"} {"id": 2, "name": "xxx"} -`, outfile, c) +`, outfile, t) tk.MustExec("drop table if exists t") tk.MustExec("create table t (v tinyint unsigned)") @@ -85,7 +89,7 @@ func (s *testSuite1) TestSelectIntoOutfileTypes(c *C) { tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) cmpAndRm(`0 1 -`, outfile, c) +`, outfile, t) tk.MustExec("drop table if exists t") tk.MustExec("create table t (id float(16,2)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin") @@ -95,12 +99,14 @@ func (s *testSuite1) TestSelectIntoOutfileTypes(c *C) { 2.00 3.40 10.10 -`, outfile, c) +`, outfile, t) } -func (s *testSuite1) TestSelectIntoOutfileFromTable(c *C) { +func TestSelectIntoOutfileFromTable(t *testing.T) { outfile := randomSelectFilePath("TestSelectIntoOutfileFromTable") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -115,80 +121,88 @@ func (s *testSuite1) TestSelectIntoOutfileFromTable(c *C) { 2 2.2 0.20000 b 2000-02-02 00:00:00 2002-02-02 00:00:00 02:02:02 [1, 2] \N \N \N \N 2000-03-03 00:00:00 2003-03-03 00:00:00 03:03:03 [1, 2, 3] 4 4.4 0.40000 d \N \N \N \N -`, outfile, c) +`, outfile, t) + require.Equal(t, uint64(4), tk.Session().GetSessionVars().StmtCtx.AffectedRows()) tk.MustExec(fmt.Sprintf("select * from t into outfile %q fields terminated by ',' enclosed by '\"' escaped by '#'", outfile)) cmpAndRm(`"1","1.1","0.10000","a","2000-01-01 00:00:00","2001-01-01 00:00:00","01:01:01","[1]" "2","2.2","0.20000","b","2000-02-02 00:00:00","2002-02-02 00:00:00","02:02:02","[1, 2]" #N,#N,#N,#N,"2000-03-03 00:00:00","2003-03-03 00:00:00","03:03:03","[1, 2, 3]" "4","4.4","0.40000","d",#N,#N,#N,#N -`, outfile, c) +`, outfile, t) + require.Equal(t, uint64(4), tk.Session().GetSessionVars().StmtCtx.AffectedRows()) tk.MustExec(fmt.Sprintf("select * from t into outfile %q fields terminated by ',' optionally enclosed by '\"' escaped by '#'", outfile)) cmpAndRm(`1,1.1,0.10000,"a","2000-01-01 00:00:00","2001-01-01 00:00:00","01:01:01","[1]" 2,2.2,0.20000,"b","2000-02-02 00:00:00","2002-02-02 00:00:00","02:02:02","[1, 2]" #N,#N,#N,#N,"2000-03-03 00:00:00","2003-03-03 00:00:00","03:03:03","[1, 2, 3]" 4,4.4,0.40000,"d",#N,#N,#N,#N -`, outfile, c) +`, outfile, t) + require.Equal(t, uint64(4), tk.Session().GetSessionVars().StmtCtx.AffectedRows()) tk.MustExec(fmt.Sprintf("select * from t into outfile %q fields terminated by ',' optionally enclosed by '\"' escaped by '#' lines terminated by '<<<\n'", outfile)) cmpAndRm(`1,1.1,0.10000,"a","2000-01-01 00:00:00","2001-01-01 00:00:00","01:01:01","[1]"<<< 2,2.2,0.20000,"b","2000-02-02 00:00:00","2002-02-02 00:00:00","02:02:02","[1, 2]"<<< #N,#N,#N,#N,"2000-03-03 00:00:00","2003-03-03 00:00:00","03:03:03","[1, 2, 3]"<<< 4,4.4,0.40000,"d",#N,#N,#N,#N<<< -`, outfile, c) +`, outfile, t) + require.Equal(t, uint64(4), tk.Session().GetSessionVars().StmtCtx.AffectedRows()) } -func (s *testSuite1) TestSelectIntoOutfileConstant(c *C) { +func TestSelectIntoOutfileConstant(t *testing.T) { outfile := randomSelectFilePath("TestSelectIntoOutfileConstant") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // On windows the outfile name looks like "C:\Users\genius\AppData\Local\Temp\select-into-outfile.data", // fmt.Sprintf("%q") is used otherwise the string become // "C:UsersgeniusAppDataLocalTempselect-into-outfile.data". tk.MustExec(fmt.Sprintf("select 1, 2, 3, '4', '5', '6', 7.7, 8.8, 9.9, null into outfile %q", outfile)) // test constants cmpAndRm(`1 2 3 4 5 6 7.7 8.8 9.9 \N -`, outfile, c) +`, outfile, t) tk.MustExec(fmt.Sprintf("select 1e10, 1e20, 1.234567e8, 0.000123e3, 1.01234567890123456789, 123456789e-10 into outfile %q", outfile)) cmpAndRm(`10000000000 1e20 123456700 0.123 1.01234567890123456789 0.0123456789 -`, outfile, c) +`, outfile, t) } -func (s *testSuite1) TestDeliminators(c *C) { +func TestDeliminators(t *testing.T) { outfile := randomSelectFilePath("TestDeliminators") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("CREATE TABLE `tx` (`a` varbinary(20) DEFAULT NULL,`b` int DEFAULT NULL)") err := tk.ExecToErr(fmt.Sprintf("select * from `tx` into outfile %q fields enclosed by '\"\"'", outfile)) // enclosed by must be a single character - c.Check(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Field separator argument is not what is expected"), IsTrue, Commentf("err: %v", err)) + require.Error(t, err) + require.Truef(t, strings.Contains(err.Error(), "Field separator argument is not what is expected"), "err: %v", err) err = tk.ExecToErr(fmt.Sprintf("select * from `tx` into outfile %q fields escaped by 'gg'", outfile)) // so does escaped by - c.Check(err, NotNil) - c.Assert(strings.Contains(err.Error(), "Field separator argument is not what is expected"), IsTrue, Commentf("err: %v", err)) + require.Error(t, err) + require.Truef(t, strings.Contains(err.Error(), "Field separator argument is not what is expected"), "err: %v", err) // since the above two test cases failed, it should not has outfile remained on disk _, err = os.Stat(outfile) - c.Check(os.IsNotExist(err), IsTrue, Commentf("err: %v", err)) + require.Truef(t, os.IsNotExist(err), "err: %v", err) tk.MustExec("insert into tx values (NULL, NULL);\n") tk.MustExec(fmt.Sprintf("select * from `tx` into outfile %q fields escaped by ''", outfile)) // if escaped by is set as empty, then NULL should not be escaped - cmpAndRm("NULL\tNULL\n", outfile, c) + cmpAndRm("NULL\tNULL\n", outfile, t) tk.MustExec("delete from tx") tk.MustExec("insert into tx values ('d\",\"e\",', 3), ('\\\\', 2)") tk.MustExec(fmt.Sprintf("select * from `tx` into outfile %q FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n'", outfile)) // enclosed by character & escaped by characters should be escaped, no matter what - cmpAndRm("\"d\\\",\\\"e\\\",\",\"3\"\n\"\\\\\",\"2\"\n", outfile, c) + cmpAndRm("\"d\\\",\\\"e\\\",\",\"3\"\n\"\\\\\",\"2\"\n", outfile, t) tk.MustExec("delete from tx") tk.MustExec("insert into tx values ('a\tb', 1)") tk.MustExec(fmt.Sprintf("select * from `tx` into outfile %q FIELDS TERMINATED BY ',' ENCLOSED BY '\"' escaped by '\t' LINES TERMINATED BY '\\n'", outfile)) // enclosed by character & escaped by characters should be escaped, no matter what - cmpAndRm("\"a\t\tb\",\"1\"\n", outfile, c) + cmpAndRm("\"a\t\tb\",\"1\"\n", outfile, t) tk.MustExec("delete from tx") tk.MustExec(`insert into tx values ('d","e",', 1)`) @@ -197,34 +211,34 @@ func (s *testSuite1) TestDeliminators(c *C) { tk.MustExec(`insert into tx values (null, 4)`) tk.MustExec(fmt.Sprintf("select * from `tx` into outfile %q FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n'", outfile)) // line terminator will be escaped - cmpAndRm("\"d\\\",\\\"e\\\",\",\"1\"\n"+"\"\\0\",\"2\"\n"+"\"\r\\\n\b\032\t\",\"3\"\n"+"\\N,\"4\"\n", outfile, c) + cmpAndRm("\"d\\\",\\\"e\\\",\",\"1\"\n"+"\"\\0\",\"2\"\n"+"\"\r\\\n\b\032\t\",\"3\"\n"+"\\N,\"4\"\n", outfile, t) tk.MustExec("create table tb (s char(10), b bit(48), bb blob(6))") tk.MustExec("insert into tb values ('\\0\\b\\n\\r\\t\\Z', _binary '\\0\\b\\n\\r\\t\\Z', unhex('00080A0D091A'))") tk.MustExec(fmt.Sprintf("select * from tb into outfile %q", outfile)) // bit type won't be escaped (verified on MySQL) - cmpAndRm("\\0\b\\\n\r\\\t\032\t"+"\000\b\n\r\t\032\t"+"\\0\b\\\n\r\\\t\032\n", outfile, c) + cmpAndRm("\\0\b\\\n\r\\\t\032\t"+"\000\b\n\r\t\032\t"+"\\0\b\\\n\r\\\t\032\n", outfile, t) tk.MustExec("create table zero (a varchar(10), b varchar(10), c varchar(10))") tk.MustExec("insert into zero values (unhex('00'), _binary '\\0', '\\0')") tk.MustExec(fmt.Sprintf("select * from zero into outfile %q", outfile)) // zero will always be escaped - cmpAndRm("\\0\t\\0\t\\0\n", outfile, c) + cmpAndRm("\\0\t\\0\t\\0\n", outfile, t) tk.MustExec(fmt.Sprintf("select * from zero into outfile %q fields enclosed by '\"'", outfile)) // zero will always be escaped, including when being enclosed - cmpAndRm("\"\\0\"\t\"\\0\"\t\"\\0\"\n", outfile, c) + cmpAndRm("\"\\0\"\t\"\\0\"\t\"\\0\"\n", outfile, t) tk.MustExec("create table tt (a char(10), b char(10), c char(10))") tk.MustExec("insert into tt values ('abcd', 'abcd', 'abcd')") tk.MustExec(fmt.Sprintf("select * from tt into outfile %q fields terminated by 'a-' lines terminated by 'b--'", outfile)) // when not escaped, the first character of both terminators will be escaped - cmpAndRm("\\a\\bcda-\\a\\bcda-\\a\\bcdb--", outfile, c) + cmpAndRm("\\a\\bcda-\\a\\bcda-\\a\\bcdb--", outfile, t) tk.MustExec(fmt.Sprintf("select * from tt into outfile %q fields terminated by 'a-' enclosed by '\"' lines terminated by 'b--'", outfile)) // when escaped, only line terminator's first character will be escaped - cmpAndRm("\"a\\bcd\"a-\"a\\bcd\"a-\"a\\bcd\"b--", outfile, c) + cmpAndRm("\"a\\bcd\"a-\"a\\bcd\"a-\"a\\bcd\"b--", outfile, t) } -func (s *testSuite1) TestDumpReal(c *C) { +func TestDumpReal(t *testing.T) { cases := []struct { val float64 dec int @@ -243,13 +257,15 @@ func (s *testSuite1) TestDumpReal(c *C) { tp := types.NewFieldType(mysql.TypeDouble) tp.Decimal = testCase.dec _, buf := executor.DumpRealOutfile(nil, nil, testCase.val, tp) - c.Assert(string(buf), Equals, testCase.result) + require.Equal(t, testCase.result, string(buf)) } } -func (s *testSuite1) TestEscapeType(c *C) { +func TestEscapeType(t *testing.T) { outfile := randomSelectFilePath("TestEscapeType") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(`create table t ( @@ -264,12 +280,14 @@ func (s *testSuite1) TestEscapeType(c *C) { tk.MustExec(fmt.Sprintf("select * from t into outfile '%v' fields terminated by ',' escaped by '1'", outfile)) cmpAndRm(`1,1,11,11,{"key": 11},11,11 -`, outfile, c) +`, outfile, t) } -func (s *testSuite1) TestYearType(c *C) { +func TestYearType(t *testing.T) { outfile := randomSelectFilePath("TestYearType") - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(time1 year(4) default '2030');") @@ -277,5 +295,5 @@ func (s *testSuite1) TestYearType(c *C) { tk.MustExec("insert into t values ();") tk.MustExec(fmt.Sprintf("select * from t into outfile '%v' fields terminated by ',' optionally enclosed by '\"' lines terminated by '\\n';", outfile)) - cmpAndRm("2010\n2011\n2012\n2030\n", outfile, c) + cmpAndRm("2010\n2011\n2012\n2030\n", outfile, t) } diff --git a/executor/seqtest/main_test.go b/executor/seqtest/main_test.go index 0a85b8ca61055..73f1353e98fc6 100644 --- a/executor/seqtest/main_test.go +++ b/executor/seqtest/main_test.go @@ -23,14 +23,15 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() config.UpdateGlobal(func(conf *config.Config) { conf.TiKVClient.AsyncCommit.SafeWindow = 0 conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 }) opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("github.com/pingcap/tidb/executor.readProjectionInput"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/executor/seqtest/prepared_test.go b/executor/seqtest/prepared_test.go index 42fbf72164e54..912bcf0014619 100644 --- a/executor/seqtest/prepared_test.go +++ b/executor/seqtest/prepared_test.go @@ -24,6 +24,7 @@ import ( "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/parser/mysql" plannercore "github.com/pingcap/tidb/planner/core" @@ -158,12 +159,13 @@ func TestPrepared(t *testing.T) { // Check that ast.Statement created by executor.CompileExecutePreparedStmt has query text. stmt, _, _, err := executor.CompileExecutePreparedStmt(context.TODO(), tk.Session(), stmtID, - tk.Session().GetInfoSchema().(infoschema.InfoSchema), 0, []types.Datum{types.NewDatum(1)}) + tk.Session().GetInfoSchema().(infoschema.InfoSchema), 0, kv.GlobalReplicaScope, []types.Datum{types.NewDatum(1)}) require.NoError(t, err) require.Equal(t, query, stmt.OriginText()) // Check that rebuild plan works. - tk.Session().PrepareTxnCtx(ctx) + err = tk.Session().PrepareTxnCtx(ctx) + require.NoError(t, err) _, err = stmt.RebuildPlan(ctx) require.NoError(t, err) rs, err = stmt.Exec(ctx) @@ -712,11 +714,11 @@ func TestPrepareDealloc(t *testing.T) { tk.MustExec("create table prepare_test (id int PRIMARY KEY, c1 int)") require.Equal(t, 0, tk.Session().PreparedPlanCache().Size()) - tk.MustExec(`prepare stmt1 from 'select * from prepare_test'`) + tk.MustExec(`prepare stmt1 from 'select id from prepare_test'`) tk.MustExec("execute stmt1") - tk.MustExec(`prepare stmt2 from 'select * from prepare_test'`) + tk.MustExec(`prepare stmt2 from 'select c1 from prepare_test'`) tk.MustExec("execute stmt2") - tk.MustExec(`prepare stmt3 from 'select * from prepare_test'`) + tk.MustExec(`prepare stmt3 from 'select id, c1 from prepare_test'`) tk.MustExec("execute stmt3") tk.MustExec(`prepare stmt4 from 'select * from prepare_test'`) tk.MustExec("execute stmt4") @@ -728,6 +730,20 @@ func TestPrepareDealloc(t *testing.T) { tk.MustExec("deallocate prepare stmt3") tk.MustExec("deallocate prepare stmt4") require.Equal(t, 0, tk.Session().PreparedPlanCache().Size()) + + tk.MustExec(`prepare stmt1 from 'select * from prepare_test'`) + tk.MustExec(`execute stmt1`) + tk.MustExec(`prepare stmt2 from 'select * from prepare_test'`) + tk.MustExec(`execute stmt2`) + require.Equal(t, 1, tk.Session().PreparedPlanCache().Size()) // use the same cached plan since they have the same statement + + tk.MustExec(`drop database if exists plan_cache`) + tk.MustExec(`create database plan_cache`) + tk.MustExec(`use plan_cache`) + tk.MustExec(`create table prepare_test (id int PRIMARY KEY, c1 int)`) + tk.MustExec(`prepare stmt3 from 'select * from prepare_test'`) + tk.MustExec(`execute stmt3`) + require.Equal(t, 2, tk.Session().PreparedPlanCache().Size()) // stmt3 has different DB } func TestPreparedIssue8153(t *testing.T) { @@ -872,6 +888,16 @@ func (msm *mockSessionManager1) ServerID() uint64 { func (msm *mockSessionManager1) UpdateTLSConfig(_ *tls.Config) {} +func (msm *mockSessionManager1) StoreInternalSession(se interface{}) { +} + +func (msm *mockSessionManager1) DeleteInternalSession(se interface{}) { +} + +func (msm *mockSessionManager1) GetInternalSessionStartTSList() []uint64 { + return nil +} + func TestPreparedIssue17419(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() diff --git a/executor/seqtest/seq_executor_test.go b/executor/seqtest/seq_executor_test.go index 6b0f3de5f6a2c..8db34810f99ee 100644 --- a/executor/seqtest/seq_executor_test.go +++ b/executor/seqtest/seq_executor_test.go @@ -33,9 +33,8 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" ddltestutil "github.com/pingcap/tidb/ddl/testutil" - "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/kv" @@ -51,9 +50,8 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/util/gcutil" - "github.com/pingcap/tidb/util/testutil" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" @@ -62,7 +60,7 @@ import ( func TestEarlyClose(t *testing.T) { var cluster testutils.Cluster - store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { mockstore.BootstrapWithSingleStore(c) cluster = c })) @@ -81,7 +79,6 @@ func TestEarlyClose(t *testing.T) { tk.MustExec("insert earlyclose values " + strings.Join(values, ",")) // Get table ID for split. - dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("earlyclose")) require.NoError(t, err) @@ -274,7 +271,7 @@ func TestShow(t *testing.T) { tk.MustExec(`create index idx9 on show_index (id) invisible;`) tk.MustExec(`create index expr_idx on show_index ((id*2+1))`) testSQL = "SHOW index from show_index;" - tk.MustQuery(testSQL).Check(testutil.RowsWithSep("|", + tk.MustQuery(testSQL).Check(testkit.RowsWithSep("|", "show_index|0|PRIMARY|1|id|A|0||||BTREE| |YES||YES", "show_index|1|cIdx|1|c|A|0|||YES|HASH||index_comment_for_cIdx|YES||NO", "show_index|1|idx1|1|id|A|0||||HASH| |YES||NO", @@ -327,11 +324,11 @@ func TestShow(t *testing.T) { testSQL = `create database show_test_DB` tk.MustExec(testSQL) testSQL = "show create database show_test_DB;" - tk.MustQuery(testSQL).Check(testutil.RowsWithSep("|", + tk.MustQuery(testSQL).Check(testkit.RowsWithSep("|", "show_test_DB|CREATE DATABASE `show_test_DB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) testSQL = "show create database if not exists show_test_DB;" - tk.MustQuery(testSQL).Check(testutil.RowsWithSep("|", + tk.MustQuery(testSQL).Check(testkit.RowsWithSep("|", "show_test_DB|CREATE DATABASE /*!32312 IF NOT EXISTS*/ `show_test_DB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */", )) @@ -343,7 +340,7 @@ func TestShow(t *testing.T) { // for issue https://github.com/pingcap/tidb/issues/4224 tk.MustExec(`drop table if exists show_test_comment`) tk.MustExec(`create table show_test_comment (id int not null default 0 comment "show_test_comment_id")`) - tk.MustQuery(`show full columns from show_test_comment`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show full columns from show_test_comment`).Check(testkit.RowsWithSep("|", "id|int(11)||NO||0||select,insert,update,references|show_test_comment_id", )) @@ -351,7 +348,7 @@ func TestShow(t *testing.T) { // for issue https://github.com/pingcap/tidb/issues/3747 tk.MustExec(`drop table if exists show_auto_increment`) tk.MustExec(`create table show_auto_increment (id int key auto_increment) auto_increment=4`) - tk.MustQuery(`show create table show_auto_increment`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table show_auto_increment`).Check(testkit.RowsWithSep("|", ""+ "show_auto_increment CREATE TABLE `show_auto_increment` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -362,7 +359,7 @@ func TestShow(t *testing.T) { autoIDStep := autoid.GetStep() tk.MustExec("insert into show_auto_increment values(20)") autoID := autoIDStep + 21 - tk.MustQuery(`show create table show_auto_increment`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table show_auto_increment`).Check(testkit.RowsWithSep("|", ""+ "show_auto_increment CREATE TABLE `show_auto_increment` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -371,7 +368,7 @@ func TestShow(t *testing.T) { )) tk.MustExec(`drop table show_auto_increment`) tk.MustExec(`create table show_auto_increment (id int primary key auto_increment)`) - tk.MustQuery(`show create table show_auto_increment`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table show_auto_increment`).Check(testkit.RowsWithSep("|", ""+ "show_auto_increment CREATE TABLE `show_auto_increment` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -380,7 +377,7 @@ func TestShow(t *testing.T) { )) tk.MustExec("insert into show_auto_increment values(10)") autoID = autoIDStep + 11 - tk.MustQuery(`show create table show_auto_increment`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table show_auto_increment`).Check(testkit.RowsWithSep("|", ""+ "show_auto_increment CREATE TABLE `show_auto_increment` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -392,7 +389,7 @@ func TestShow(t *testing.T) { // for issue https://github.com/pingcap/tidb/issues/4411 tk.MustExec(`drop table if exists show_escape_character`) tk.MustExec(`create table show_escape_character(id int comment 'a\rb\nc\td\0ef')`) - tk.MustQuery(`show create table show_escape_character`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table show_escape_character`).Check(testkit.RowsWithSep("|", ""+ "show_escape_character CREATE TABLE `show_escape_character` (\n"+ " `id` int(11) DEFAULT NULL COMMENT 'a\\rb\\nc d\\0ef'\n"+ @@ -482,7 +479,7 @@ func TestShow(t *testing.T) { // Test get default collate for a specified charset. tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t (a int) default charset=utf8mb4`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin", @@ -494,7 +491,7 @@ func TestShow(t *testing.T) { PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (MAXVALUE))`) - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"+"\nPARTITION BY RANGE (`a`)\n(PARTITION `p0` VALUES LESS THAN (10),\n PARTITION `p1` VALUES LESS THAN (20),\n PARTITION `p2` VALUES LESS THAN (MAXVALUE))", @@ -514,7 +511,7 @@ func TestShow(t *testing.T) { PARTITION p1 VALUES LESS THAN (10,20,'mmm'), PARTITION p2 VALUES LESS THAN (15,30,'sss'), PARTITION p3 VALUES LESS THAN (50,MAXVALUE,MAXVALUE))`) - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` int(11) DEFAULT NULL,\n"+ @@ -526,7 +523,7 @@ func TestShow(t *testing.T) { // Test hash partition tk.MustExec(`drop table if exists t`) tk.MustExec(`CREATE TABLE t (a int) PARTITION BY HASH(a) PARTITIONS 4`) - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ @@ -535,7 +532,7 @@ func TestShow(t *testing.T) { // Test show create table compression type. tk.MustExec(`drop table if exists t1`) tk.MustExec(`CREATE TABLE t1 (c1 INT) COMPRESSION="zlib";`) - tk.MustQuery("show create table t1").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t1").Check(testkit.RowsWithSep("|", "t1 CREATE TABLE `t1` (\n"+ " `c1` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMPRESSION='zlib'", @@ -544,7 +541,7 @@ func TestShow(t *testing.T) { // Test show create table year type tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t(y year unsigned signed zerofill zerofill, x int, primary key(y));`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `y` year(4) NOT NULL,\n"+ " `x` int(11) DEFAULT NULL,\n"+ @@ -554,7 +551,7 @@ func TestShow(t *testing.T) { // Test show create table with zerofill flag tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t(id int primary key, val tinyint(10) zerofill);`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `id` int(11) NOT NULL,\n"+ " `val` tinyint(10) unsigned zerofill DEFAULT NULL,\n"+ @@ -576,7 +573,7 @@ func TestShow(t *testing.T) { c9 year default '2014', c10 enum('2', '3', '4') default 2 );`) - tk.MustQuery(`show columns from t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show columns from t`).Check(testkit.RowsWithSep("|", "c0|int(11)|YES||1|", "c1|int(11)|YES||2|", "c2|bigint(20)|YES||167|", @@ -1199,13 +1196,12 @@ func TestShowForNewCollations(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(t, store) expectRows := testkit.Rows( "ascii_bin ascii 65 Yes Yes 1", "binary binary 63 Yes Yes 1", + "gbk_bin gbk 87 Yes 1", + "gbk_chinese_ci gbk 28 Yes Yes 1", "latin1_bin latin1 47 Yes Yes 1", "utf8_bin utf8 83 Yes Yes 1", "utf8_general_ci utf8 33 Yes 1", @@ -1222,9 +1218,6 @@ func TestForbidUnsupportedCollations(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(t, store) mustGetUnsupportedCollation := func(sql string, coll string) { tk.MustGetErrMsg(sql, fmt.Sprintf("[ddl:1273]Unsupported collation when new collation is enabled: '%s'", coll)) @@ -1409,15 +1402,15 @@ func TestAutoRandRecoverTable(t *testing.T) { tk.MustExec("drop table if exists t_recover_auto_rand") defer func(originGC bool) { if originGC { - ddl.EmulatorGCEnable() + util.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(util.IsEmulatorGCEnable()) // Disable emulator GC. // Otherwise, emulator GC will delete table record as soon as possible after execute drop table ddl. - ddl.EmulatorGCDisable() + util.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') @@ -1484,16 +1477,16 @@ func TestOOMPanicInHashJoinWhenFetchBuildRows(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() - fpName := "github.com/pingcap/tidb/executor/errorFetchBuildSideRowsMockOOMPanic" - require.NoError(t, failpoint.Enable(fpName, `panic("ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]")`)) - defer func() { - require.NoError(t, failpoint.Disable(fpName)) - }() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(c1 int, c2 int)") tk.MustExec("insert into t values(1,1),(2,2)") + fpName := "github.com/pingcap/tidb/executor/errorFetchBuildSideRowsMockOOMPanic" + require.NoError(t, failpoint.Enable(fpName, `panic("ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]")`)) + defer func() { + require.NoError(t, failpoint.Disable(fpName)) + }() err := tk.QueryToErr("select * from t as t2 join t as t1 where t1.c1=t2.c1") require.EqualError(t, err, "failpoint panic: ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]") } diff --git a/executor/set.go b/executor/set.go index 65e21d470cc78..a79055abb5dbe 100644 --- a/executor/set.go +++ b/executor/set.go @@ -115,6 +115,14 @@ func (e *SetExecutor) setSysVariable(ctx context.Context, name string, v *expres } return variable.ErrUnknownSystemVar.GenWithStackByArgs(name) } + + if sysVar.HasInstanceScope() && !v.IsGlobal && sessionVars.EnableLegacyInstanceScope { + // For backward compatibility we will change the v.IsGlobal to true, + // and append a warning saying this will not be supported in future. + v.IsGlobal = true + sessionVars.StmtCtx.AppendWarning(ErrInstanceScope.GenWithStackByArgs(sysVar.Name)) + } + if v.IsGlobal { valStr, err := e.getVarValue(v, sysVar) if err != nil { diff --git a/executor/set_config.go b/executor/set_config.go index 6faf9deec08e1..2d8f4d7e2e385 100644 --- a/executor/set_config.go +++ b/executor/set_config.go @@ -180,7 +180,7 @@ func ConvertConfigItem2JSON(ctx sessionctx.Context, key string, val expression.E var s string s, isNull, err = val.EvalString(ctx, chunk.Row{}) if err == nil && !isNull { - str = fmt.Sprintf(`"%s"`, s) + str = fmt.Sprintf("%q", s) } case types.ETInt: var i int64 diff --git a/executor/set_test.go b/executor/set_test.go index da121e77b2422..9f2d12b9316bf 100644 --- a/executor/set_test.go +++ b/executor/set_test.go @@ -22,8 +22,8 @@ import ( "io" "net/http" "strconv" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/errno" @@ -34,75 +34,45 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/stretchr/testify/require" ) -func (s *testSerialSuite1) TestSetVar(c *C) { - tk := testkit.NewTestKit(c, s.store) - - testSQL := "SET @a = 1;" - tk.MustExec(testSQL) - - testSQL = `SET @a = "1";` - tk.MustExec(testSQL) - - testSQL = "SET @a = null;" - tk.MustExec(testSQL) - - testSQL = "SET @@global.autocommit = 1;" - tk.MustExec(testSQL) +func TestSetVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("SET @a = 1;") + tk.MustExec(`SET @a = "1";`) + tk.MustExec("SET @a = null;") + tk.MustExec("SET @@global.autocommit = 1;") // TODO: this test case should returns error. - // testSQL = "SET @@global.autocommit = null;" - // _, err := tk.Exec(testSQL) + // err := tk.ExecToErr("SET @@global.autocommit = null;") // c.Assert(err, NotNil) - testSQL = "SET @@autocommit = 1;" - tk.MustExec(testSQL) - - testSQL = "SET @@autocommit = null;" - _, err := tk.Exec(testSQL) - c.Assert(err, NotNil) - - errTestSQL := "SET @@date_format = 1;" - _, err = tk.Exec(errTestSQL) - c.Assert(err, NotNil) - - errTestSQL = "SET @@rewriter_enabled = 1;" - _, err = tk.Exec(errTestSQL) - c.Assert(err, NotNil) - - errTestSQL = "SET xxx = abcd;" - _, err = tk.Exec(errTestSQL) - c.Assert(err, NotNil) - - errTestSQL = "SET @@global.a = 1;" - _, err = tk.Exec(errTestSQL) - c.Assert(err, NotNil) - - errTestSQL = "SET @@global.timestamp = 1;" - _, err = tk.Exec(errTestSQL) - c.Assert(err, NotNil) + tk.MustExec("SET @@autocommit = 1;") + require.Error(t, tk.ExecToErr("SET @@autocommit = null;")) + require.Error(t, tk.ExecToErr("SET @@date_format = 1;")) + require.Error(t, tk.ExecToErr("SET @@rewriter_enabled = 1;")) + require.Error(t, tk.ExecToErr("SET xxx = abcd;")) + require.Error(t, tk.ExecToErr("SET @@global.a = 1;")) + require.Error(t, tk.ExecToErr("SET @@global.timestamp = 1;")) // For issue 998 - testSQL = "SET @issue998a=1, @issue998b=5;" - tk.MustExec(testSQL) + tk.MustExec("SET @issue998a=1, @issue998b=5;") tk.MustQuery(`select @issue998a, @issue998b;`).Check(testkit.Rows("1 5")) - testSQL = "SET @@autocommit=0, @issue998a=2;" - tk.MustExec(testSQL) + tk.MustExec("SET @@autocommit=0, @issue998a=2;") tk.MustQuery(`select @issue998a, @@autocommit;`).Check(testkit.Rows("2 0")) - testSQL = "SET @@global.autocommit=1, @issue998b=6;" - tk.MustExec(testSQL) + tk.MustExec("SET @@global.autocommit=1, @issue998b=6;") tk.MustQuery(`select @issue998b, @@global.autocommit;`).Check(testkit.Rows("6 1")) // For issue 4302 - testSQL = "use test;drop table if exists x;create table x(a int);insert into x value(1);" - tk.MustExec(testSQL) - testSQL = "SET @issue4302=(select a from x limit 1);" - tk.MustExec(testSQL) + tk.MustExec("use test;drop table if exists x;create table x(a int);insert into x value(1);") + tk.MustExec("SET @issue4302=(select a from x limit 1);") tk.MustQuery(`select @issue4302;`).Check(testkit.Rows("1")) // Set default @@ -123,34 +93,33 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery(`select @@session.tx_read_only;`).Check(testkit.Rows("0")) // Test session variable states. - vars := tk.Se.(sessionctx.Context).GetSessionVars() - err = tk.Se.CommitTxn(context.TODO()) - c.Assert(err, IsNil) + vars := tk.Session().(sessionctx.Context).GetSessionVars() + require.NoError(t, tk.Session().CommitTxn(context.TODO())) tk.MustExec("set @@autocommit = 1") - c.Assert(vars.InTxn(), IsFalse) - c.Assert(vars.IsAutocommit(), IsTrue) + require.False(t, vars.InTxn()) + require.True(t, vars.IsAutocommit()) tk.MustExec("set @@autocommit = 0") - c.Assert(vars.IsAutocommit(), IsFalse) + require.False(t, vars.IsAutocommit()) tk.MustExec("set @@sql_mode = 'strict_trans_tables'") - c.Assert(vars.StrictSQLMode, IsTrue) + require.True(t, vars.StrictSQLMode) tk.MustExec("set @@sql_mode = ''") - c.Assert(vars.StrictSQLMode, IsFalse) + require.False(t, vars.StrictSQLMode) tk.MustExec("set names utf8") charset, collation := vars.GetCharsetInfo() - c.Assert(charset, Equals, "utf8") - c.Assert(collation, Equals, "utf8_bin") + require.Equal(t, "utf8", charset) + require.Equal(t, "utf8_bin", collation) - tk.MustExec("set names latin1 collate latin1_swedish_ci") + tk.MustExec("set names latin1 collate latin1_bin") charset, collation = vars.GetCharsetInfo() - c.Assert(charset, Equals, "latin1") - c.Assert(collation, Equals, "latin1_swedish_ci") + require.Equal(t, "latin1", charset) + require.Equal(t, "latin1_bin", collation) tk.MustExec("set names utf8 collate default") charset, collation = vars.GetCharsetInfo() - c.Assert(charset, Equals, "utf8") - c.Assert(collation, Equals, "utf8_bin") + require.Equal(t, "utf8", charset) + require.Equal(t, "utf8_bin", collation) expectErrMsg := "[ddl:1273]Unknown collation: 'non_exist_collation'" tk.MustGetErrMsg("set names utf8 collate non_exist_collation", expectErrMsg) @@ -169,23 +138,23 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustExec("set @@session.ddl_slow_threshold=12345") tk.MustQuery("select @@session.ddl_slow_threshold").Check(testkit.Rows("12345")) - c.Assert(variable.DDLSlowOprThreshold, Equals, uint32(12345)) + require.Equal(t, uint32(12345), variable.DDLSlowOprThreshold) tk.MustExec("set session ddl_slow_threshold=\"54321\"") tk.MustQuery("show variables like 'ddl_slow_threshold'").Check(testkit.Rows("ddl_slow_threshold 54321")) - c.Assert(variable.DDLSlowOprThreshold, Equals, uint32(54321)) + require.Equal(t, uint32(54321), variable.DDLSlowOprThreshold) // Test set transaction isolation level, which is equivalent to setting variable "tx_isolation". tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED") tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) // error - _, err = tk.Exec("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err := tk.ExecToErr("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) // Fails - _, err = tk.Exec("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("REPEATABLE-READ")) tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("REPEATABLE-READ")) @@ -194,38 +163,37 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) - _, err = tk.Exec("SET SESSION tx_isolation = 'READ-UNCOMMITTED'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET SESSION tx_isolation = 'READ-UNCOMMITTED'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) // fails - _, err = tk.Exec("SET SESSION transaction_isolation = 'SERIALIZABLE'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET SESSION transaction_isolation = 'SERIALIZABLE'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) // fails - _, err = tk.Exec("SET GLOBAL transaction_isolation = 'SERIALIZABLE'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL transaction_isolation = 'SERIALIZABLE'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("REPEATABLE-READ")) tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("REPEATABLE-READ")) - _, err = tk.Exec("SET GLOBAL transaction_isolation = 'READ-UNCOMMITTED'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL transaction_isolation = 'READ-UNCOMMITTED'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("REPEATABLE-READ")) tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("REPEATABLE-READ")) - _, err = tk.Exec("SET GLOBAL tx_isolation = 'SERIALIZABLE'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL tx_isolation = 'SERIALIZABLE'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("REPEATABLE-READ")) tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("REPEATABLE-READ")) // Even the transaction fail, set session variable would success. tk.MustExec("BEGIN") tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED") - _, err = tk.Exec(`INSERT INTO t VALUES ("sdfsdf")`) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr(`INSERT INTO t VALUES ("sdfsdf")`)) tk.MustExec("COMMIT") tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) @@ -263,8 +231,7 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("DELAYED")) tk.MustExec(`set tidb_force_priority = "abc"`) tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) - _, err = tk.Exec(`set global tidb_force_priority = ""`) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr(`set global tidb_force_priority = ""`)) tk.MustExec("set tidb_constraint_check_in_place = 1") tk.MustQuery(`select @@session.tidb_constraint_check_in_place;`).Check(testkit.Rows("1")) @@ -275,10 +242,8 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery("select @@session.tidb_batch_commit;").Check(testkit.Rows("0")) tk.MustExec("set tidb_batch_commit = 1") tk.MustQuery("select @@session.tidb_batch_commit;").Check(testkit.Rows("1")) - _, err = tk.Exec("set global tidb_batch_commit = 0") - c.Assert(err, NotNil) - _, err = tk.Exec("set global tidb_batch_commit = 2") - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("set global tidb_batch_commit = 0")) + require.Error(t, tk.ExecToErr("set global tidb_batch_commit = 2")) // test skip isolation level check: init tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") @@ -291,13 +256,13 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) // test skip isolation level check: error - _, err = tk.Exec("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) - _, err = tk.Exec("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) @@ -337,10 +302,8 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery(`select @@global.tidb_scatter_region;`).Check(testkit.Rows("1")) tk.MustExec("set global tidb_scatter_region = 0") tk.MustQuery(`select @@global.tidb_scatter_region;`).Check(testkit.Rows("0")) - _, err = tk.Exec("set session tidb_scatter_region = 0") - c.Assert(err, NotNil) - _, err = tk.Exec(`select @@session.tidb_scatter_region;`) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("set session tidb_scatter_region = 0")) + require.Error(t, tk.ExecToErr(`select @@session.tidb_scatter_region;`)) // test for tidb_wait_split_region_timeout tk.MustQuery(`select @@session.tidb_wait_split_region_timeout;`).Check(testkit.Rows(strconv.Itoa(variable.DefWaitSplitRegionTimeout))) @@ -359,7 +322,7 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustExec("set session tidb_backoff_weight = -1") tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_backoff_weight value: '-1'")) tk.MustExec("set global tidb_backoff_weight = 0") - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_backoff_weight value: '0'")) + tk.MustQuery("select @@global.tidb_backoff_weight;").Check(testkit.Rows("0")) tk.MustExec("set global tidb_backoff_weight = 10") tk.MustQuery("select @@global.tidb_backoff_weight;").Check(testkit.Rows("10")) @@ -373,6 +336,14 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustExec("set global tidb_store_limit = 100") tk.MustQuery("select @@global.tidb_store_limit;").Check(testkit.Rows("100")) + tk.MustQuery("select @@global.tidb_txn_commit_batch_size;").Check(testkit.Rows("16384")) + tk.MustExec("set @@global.tidb_txn_commit_batch_size = 100") + tk.MustQuery("select @@global.tidb_txn_commit_batch_size;").Check(testkit.Rows("100")) + tk.MustExec("set @@global.tidb_txn_commit_batch_size = 0") + tk.MustQuery("select @@global.tidb_txn_commit_batch_size;").Check(testkit.Rows("1")) + tk.MustExec("set global tidb_txn_commit_batch_size = 100") + tk.MustQuery("select @@global.tidb_txn_commit_batch_size;").Check(testkit.Rows("100")) + tk.MustQuery("select @@session.tidb_metric_query_step;").Check(testkit.Rows("60")) tk.MustExec("set @@session.tidb_metric_query_step = 120") tk.MustExec("set @@session.tidb_metric_query_step = 9") @@ -418,8 +389,8 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustExec("set @@global.tidb_dml_batch_size = 200") // now permitted due to TiDB #19809 tk.MustQuery("select @@tidb_dml_batch_size;").Check(testkit.Rows("120")) // global only applies to new sessions - _, err = tk.Exec("set tidb_enable_parallel_apply=-1") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue) + err = tk.ExecToErr("set tidb_enable_parallel_apply=-1") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar)) // test for tidb_mem_quota_apply_cache defVal := fmt.Sprintf("%v", variable.DefTiDBMemQuotaApplyCache) @@ -432,6 +403,17 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery(`select @@global.tidb_mem_quota_apply_cache`).Check(testkit.Rows("0")) tk.MustQuery(`select @@tidb_mem_quota_apply_cache`).Check(testkit.Rows("123")) + // test for tidb_mem_quota_bind_cache + defVal = fmt.Sprintf("%v", variable.DefTiDBMemQuotaBindingCache) + tk.MustQuery(`select @@tidb_mem_quota_binding_cache`).Check(testkit.Rows(defVal)) + tk.MustExec(`set global tidb_mem_quota_binding_cache = 1`) + tk.MustQuery(`select @@global.tidb_mem_quota_binding_cache`).Check(testkit.Rows("1")) + tk.MustExec(`set global tidb_mem_quota_binding_cache = 0`) + tk.MustQuery(`select @@global.tidb_mem_quota_binding_cache`).Check(testkit.Rows("0")) + tk.MustExec(`set global tidb_mem_quota_binding_cache = 123`) + tk.MustQuery(`select @@global.tidb_mem_quota_binding_cache`).Check(testkit.Rows("123")) + tk.MustQuery(`select @@global.tidb_mem_quota_binding_cache`).Check(testkit.Rows("123")) + // test for tidb_enable_parallel_apply tk.MustQuery(`select @@tidb_enable_parallel_apply`).Check(testkit.Rows("0")) tk.MustExec(`set global tidb_enable_parallel_apply = 1`) @@ -442,22 +424,22 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustQuery(`select @@global.tidb_enable_parallel_apply`).Check(testkit.Rows("0")) tk.MustQuery(`select @@tidb_enable_parallel_apply`).Check(testkit.Rows("1")) - tk.MustQuery(`select @@session.tidb_general_log;`).Check(testkit.Rows("0")) + tk.MustQuery(`select @@global.tidb_general_log;`).Check(testkit.Rows("0")) tk.MustQuery(`show variables like 'tidb_general_log';`).Check(testkit.Rows("tidb_general_log OFF")) tk.MustExec("set tidb_general_log = 1") - tk.MustQuery(`select @@session.tidb_general_log;`).Check(testkit.Rows("1")) + tk.MustQuery(`select @@global.tidb_general_log;`).Check(testkit.Rows("1")) tk.MustQuery(`show variables like 'tidb_general_log';`).Check(testkit.Rows("tidb_general_log ON")) tk.MustExec("set tidb_general_log = 0") - tk.MustQuery(`select @@session.tidb_general_log;`).Check(testkit.Rows("0")) + tk.MustQuery(`select @@global.tidb_general_log;`).Check(testkit.Rows("0")) tk.MustQuery(`show variables like 'tidb_general_log';`).Check(testkit.Rows("tidb_general_log OFF")) tk.MustExec("set tidb_general_log = on") - tk.MustQuery(`select @@session.tidb_general_log;`).Check(testkit.Rows("1")) + tk.MustQuery(`select @@global.tidb_general_log;`).Check(testkit.Rows("1")) tk.MustQuery(`show variables like 'tidb_general_log';`).Check(testkit.Rows("tidb_general_log ON")) tk.MustExec("set tidb_general_log = off") - tk.MustQuery(`select @@session.tidb_general_log;`).Check(testkit.Rows("0")) + tk.MustQuery(`select @@global.tidb_general_log;`).Check(testkit.Rows("0")) tk.MustQuery(`show variables like 'tidb_general_log';`).Check(testkit.Rows("tidb_general_log OFF")) - c.Assert(tk.ExecToErr("set tidb_general_log = abc"), NotNil) - c.Assert(tk.ExecToErr("set tidb_general_log = 123"), NotNil) + require.Error(t, tk.ExecToErr("set tidb_general_log = abc")) + require.Error(t, tk.ExecToErr("set tidb_general_log = 123")) tk.MustExec(`SET @@character_set_results = NULL;`) tk.MustQuery(`select @@character_set_results;`).Check(testkit.Rows("")) @@ -574,24 +556,57 @@ func (s *testSerialSuite1) TestSetVar(c *C) { tk.MustExec("set global tidb_tso_client_batch_max_wait_time = 10.1") tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_tso_client_batch_max_wait_time value: '10.1'")) tk.MustQuery("select @@tidb_tso_client_batch_max_wait_time").Check(testkit.Rows("10")) - c.Assert(tk.ExecToErr("set tidb_tso_client_batch_max_wait_time = 1"), NotNil) + require.Error(t, tk.ExecToErr("set tidb_tso_client_batch_max_wait_time = 1")) tk.MustQuery("select @@tidb_enable_tso_follower_proxy").Check(testkit.Rows("0")) tk.MustExec("set global tidb_enable_tso_follower_proxy = 1") tk.MustQuery("select @@tidb_enable_tso_follower_proxy").Check(testkit.Rows("1")) tk.MustExec("set global tidb_enable_tso_follower_proxy = 0") tk.MustQuery("select @@tidb_enable_tso_follower_proxy").Check(testkit.Rows("0")) - c.Assert(tk.ExecToErr("set tidb_enable_tso_follower_proxy = 1"), NotNil) + require.Error(t, tk.ExecToErr("set tidb_enable_tso_follower_proxy = 1")) tk.MustQuery("select @@tidb_enable_historical_stats").Check(testkit.Rows("0")) tk.MustExec("set global tidb_enable_historical_stats = 1") tk.MustQuery("select @@tidb_enable_historical_stats").Check(testkit.Rows("1")) tk.MustExec("set global tidb_enable_historical_stats = 0") tk.MustQuery("select @@tidb_enable_historical_stats").Check(testkit.Rows("0")) + + // test for tidb_enable_column_tracking + tk.MustQuery("select @@tidb_enable_column_tracking").Check(testkit.Rows("0")) + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustQuery("select @@tidb_enable_column_tracking").Check(testkit.Rows("1")) + tk.MustExec("set global tidb_enable_column_tracking = 0") + tk.MustQuery("select @@tidb_enable_column_tracking").Check(testkit.Rows("0")) + // When set tidb_enable_column_tracking off, we record the time of the setting operation. + tk.MustQuery("select count(1) from mysql.tidb where variable_name = 'tidb_disable_column_tracking_time' and variable_value is not null").Check(testkit.Rows("1")) + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustQuery("select @@tidb_enable_column_tracking").Check(testkit.Rows("1")) + require.Error(t, tk.ExecToErr("select @@session.tidb_enable_column_tracking")) + require.Error(t, tk.ExecToErr("set tidb_enable_column_tracking = 0")) + require.Error(t, tk.ExecToErr("set global tidb_enable_column_tracking = -1")) + + // test for tidb_ignore_prepared_cache_close_stmt + tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("0")) // default value is 0 + tk.MustExec("set global tidb_ignore_prepared_cache_close_stmt=1") + tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("1")) + tk.MustQuery("show global variables like 'tidb_ignore_prepared_cache_close_stmt'").Check(testkit.Rows("tidb_ignore_prepared_cache_close_stmt ON")) + tk.MustExec("set global tidb_ignore_prepared_cache_close_stmt=0") + tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("0")) + tk.MustQuery("show global variables like 'tidb_ignore_prepared_cache_close_stmt'").Check(testkit.Rows("tidb_ignore_prepared_cache_close_stmt OFF")) + + // test for tidb_remove_orderby_in_subquery + tk.MustQuery("select @@session.tidb_remove_orderby_in_subquery").Check(testkit.Rows("0")) // default value is 0 + tk.MustExec("set session tidb_remove_orderby_in_subquery=1") + tk.MustQuery("select @@session.tidb_remove_orderby_in_subquery").Check(testkit.Rows("1")) + tk.MustQuery("select @@global.tidb_remove_orderby_in_subquery").Check(testkit.Rows("0")) // default value is 0 + tk.MustExec("set global tidb_remove_orderby_in_subquery=1") + tk.MustQuery("select @@global.tidb_remove_orderby_in_subquery").Check(testkit.Rows("1")) } -func (s *testSuite5) TestTruncateIncorrectIntSessionVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTruncateIncorrectIntSessionVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) testCases := []struct { sessionVarName string @@ -621,10 +636,11 @@ func (s *testSuite5) TestTruncateIncorrectIntSessionVar(c *C) { } } -func (s *testSuite5) TestSetCharset(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - ctx := tk.Se.(sessionctx.Context) - sessionVars := ctx.GetSessionVars() +func TestSetCharset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + sessionVars := tk.Session().GetSessionVars() var characterSetVariables = []string{ "character_set_client", @@ -639,8 +655,8 @@ func (s *testSuite5) TestSetCharset(c *C) { check := func(args ...string) { for i, v := range characterSetVariables { sVar, err := variable.GetSessionOrGlobalSystemVar(sessionVars, v) - c.Assert(err, IsNil) - c.Assert(sVar, Equals, args[i], Commentf("%d: %s", i, characterSetVariables[i])) + require.NoError(t, err) + require.Equal(t, args[i], sVar, fmt.Sprintf("%d: %s", i, characterSetVariables[i])) } } @@ -722,9 +738,12 @@ func (s *testSuite5) TestSetCharset(c *C) { ) } -func (s *testSuite5) TestSetCollationAndCharset(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - ctx := tk.Se.(sessionctx.Context) +func TestSetCollationAndCharset(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + ctx := tk.Session().(sessionctx.Context) sessionVars := ctx.GetSessionVars() cases := []struct { @@ -738,48 +757,51 @@ func (s *testSuite5) TestSetCollationAndCharset(c *C) { {variable.CharacterSetServer, variable.CollationServer, "utf8", "utf8_bin"}, } - for _, t := range cases { - tk.MustExec(fmt.Sprintf("set %s = %s;", t.charset, t.expectCharset)) - sVar, ok := sessionVars.GetSystemVar(t.charset) - c.Assert(ok, IsTrue) - c.Assert(sVar, Equals, t.expectCharset) - sVar, ok = sessionVars.GetSystemVar(t.collation) - c.Assert(ok, IsTrue) - c.Assert(sVar, Equals, t.expectCollation) + for _, c := range cases { + tk.MustExec(fmt.Sprintf("set %s = %s;", c.charset, c.expectCharset)) + sVar, ok := sessionVars.GetSystemVar(c.charset) + require.True(t, ok) + require.Equal(t, c.expectCharset, sVar) + sVar, ok = sessionVars.GetSystemVar(c.collation) + require.True(t, ok) + require.Equal(t, c.expectCollation, sVar) } - tk = testkit.NewTestKitWithInit(c, s.store) - ctx = tk.Se.(sessionctx.Context) + tk = testkit.NewTestKit(t, store) + tk.MustExec("use test") + ctx = tk.Session().(sessionctx.Context) sessionVars = ctx.GetSessionVars() - for _, t := range cases { - tk.MustExec(fmt.Sprintf("set %s = %s;", t.collation, t.expectCollation)) - sVar, ok := sessionVars.GetSystemVar(t.charset) - c.Assert(ok, IsTrue) - c.Assert(sVar, Equals, t.expectCharset) - sVar, ok = sessionVars.GetSystemVar(t.collation) - c.Assert(ok, IsTrue) - c.Assert(sVar, Equals, t.expectCollation) + for _, c := range cases { + tk.MustExec(fmt.Sprintf("set %s = %s;", c.collation, c.expectCollation)) + sVar, ok := sessionVars.GetSystemVar(c.charset) + require.True(t, ok) + require.Equal(t, c.expectCharset, sVar) + sVar, ok = sessionVars.GetSystemVar(c.collation) + require.True(t, ok) + require.Equal(t, c.expectCollation, sVar) } } -func (s *testSuite5) TestValidateSetVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestValidateSetVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) - _, err := tk.Exec("set global tidb_distsql_scan_concurrency='fff';") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + err := tk.ExecToErr("set global tidb_distsql_scan_concurrency='fff';") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set global tidb_distsql_scan_concurrency=-2;") tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_distsql_scan_concurrency value: '-2'")) - _, err = tk.Exec("set @@tidb_distsql_scan_concurrency='fff';") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@tidb_distsql_scan_concurrency='fff';") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@tidb_distsql_scan_concurrency=-2;") tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_distsql_scan_concurrency value: '-2'")) - _, err = tk.Exec("set @@tidb_batch_delete='ok';") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@tidb_batch_delete='ok';") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@tidb_batch_delete='On';") tk.MustQuery("select @@tidb_batch_delete;").Check(testkit.Rows("1")) @@ -797,6 +819,7 @@ func (s *testSuite5) TestValidateSetVar(c *C) { tk.MustQuery("select @@tidb_constraint_check_in_place;").Check(testkit.Rows("1")) tk.MustExec("set @@tidb_general_log=0;") + tk.MustQuery(`show warnings`).Check(testkit.Rows(fmt.Sprintf("Warning %d modifying tidb_general_log will require SET GLOBAL in a future version of TiDB", errno.ErrInstanceScope))) tk.MustQuery("select @@tidb_general_log;").Check(testkit.Rows("0")) tk.MustExec("set @@tidb_pprof_sql_cpu=1;") @@ -804,39 +827,36 @@ func (s *testSuite5) TestValidateSetVar(c *C) { tk.MustExec("set @@tidb_pprof_sql_cpu=0;") tk.MustQuery("select @@tidb_pprof_sql_cpu;").Check(testkit.Rows("0")) - tk.MustExec("set @@tidb_enable_streaming=1;") - tk.MustQuery("select @@tidb_enable_streaming;").Check(testkit.Rows("1")) - - _, err = tk.Exec("set @@tidb_batch_delete=3;") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@tidb_batch_delete=3;") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@group_concat_max_len=1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect group_concat_max_len value: '1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect group_concat_max_len value: '1'")) result := tk.MustQuery("select @@group_concat_max_len;") result.Check(testkit.Rows("4")) - _, err = tk.Exec("set @@group_concat_max_len = 18446744073709551616") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@group_concat_max_len = 18446744073709551616") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), fmt.Sprintf("err %v", err)) // Test illegal type - _, err = tk.Exec("set @@group_concat_max_len='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@group_concat_max_len='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@default_week_format=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect default_week_format value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect default_week_format value: '-1'")) result = tk.MustQuery("select @@default_week_format;") result.Check(testkit.Rows("0")) tk.MustExec("set @@default_week_format=9") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect default_week_format value: '9'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect default_week_format value: '9'")) result = tk.MustQuery("select @@default_week_format;") result.Check(testkit.Rows("7")) - _, err = tk.Exec("set @@error_count = 0") - c.Assert(terror.ErrorEqual(err, variable.ErrIncorrectScope), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@error_count = 0") + require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err %v", err)) - _, err = tk.Exec("set @@warning_count = 0") - c.Assert(terror.ErrorEqual(err, variable.ErrIncorrectScope), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@warning_count = 0") + require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err %v", err)) tk.MustExec("set time_zone='SySTeM'") result = tk.MustQuery("select @@time_zone;") @@ -845,118 +865,118 @@ func (s *testSuite5) TestValidateSetVar(c *C) { // The following cases test value out of range and illegal type when setting system variables. // See https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html for more details. tk.MustExec("set @@global.max_connections=100001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '100001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '100001'")) result = tk.MustQuery("select @@global.max_connections;") result.Check(testkit.Rows("100000")) tk.MustExec("set @@global.max_connections=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '-1'")) result = tk.MustQuery("select @@global.max_connections;") result.Check(testkit.Rows("1")) - _, err = tk.Exec("set @@global.max_connections='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.max_connections='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.thread_pool_size=65") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect thread_pool_size value: '65'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect thread_pool_size value: '65'")) result = tk.MustQuery("select @@global.thread_pool_size;") result.Check(testkit.Rows("64")) tk.MustExec("set @@global.thread_pool_size=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect thread_pool_size value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect thread_pool_size value: '-1'")) result = tk.MustQuery("select @@global.thread_pool_size;") result.Check(testkit.Rows("1")) - _, err = tk.Exec("set @@global.thread_pool_size='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.thread_pool_size='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.max_allowed_packet=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_allowed_packet value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_allowed_packet value: '-1'")) result = tk.MustQuery("select @@global.max_allowed_packet;") result.Check(testkit.Rows("1024")) - _, err = tk.Exec("set @@global.max_allowed_packet='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.max_allowed_packet='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.max_connect_errors=18446744073709551615") tk.MustExec("set @@global.max_connect_errors=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connect_errors value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connect_errors value: '-1'")) result = tk.MustQuery("select @@global.max_connect_errors;") result.Check(testkit.Rows("1")) - _, err = tk.Exec("set @@global.max_connect_errors=18446744073709551616") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.max_connect_errors=18446744073709551616") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.max_connections=100001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '100001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '100001'")) result = tk.MustQuery("select @@global.max_connections;") result.Check(testkit.Rows("100000")) tk.MustExec("set @@global.max_connections=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_connections value: '-1'")) result = tk.MustQuery("select @@global.max_connections;") result.Check(testkit.Rows("1")) - _, err = tk.Exec("set @@global.max_connections='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.max_connections='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@max_sort_length=1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '1'")) result = tk.MustQuery("select @@max_sort_length;") result.Check(testkit.Rows("4")) tk.MustExec("set @@max_sort_length=-100") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '-100'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '-100'")) result = tk.MustQuery("select @@max_sort_length;") result.Check(testkit.Rows("4")) tk.MustExec("set @@max_sort_length=8388609") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '8388609'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect max_sort_length value: '8388609'")) result = tk.MustQuery("select @@max_sort_length;") result.Check(testkit.Rows("8388608")) - _, err = tk.Exec("set @@max_sort_length='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@max_sort_length='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.table_definition_cache=399") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '399'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '399'")) result = tk.MustQuery("select @@global.table_definition_cache;") result.Check(testkit.Rows("400")) tk.MustExec("set @@global.table_definition_cache=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '-1'")) result = tk.MustQuery("select @@global.table_definition_cache;") result.Check(testkit.Rows("400")) tk.MustExec("set @@global.table_definition_cache=524289") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '524289'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect table_definition_cache value: '524289'")) result = tk.MustQuery("select @@global.table_definition_cache;") result.Check(testkit.Rows("524288")) - _, err = tk.Exec("set @@global.table_definition_cache='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@global.table_definition_cache='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@old_passwords=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect old_passwords value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect old_passwords value: '-1'")) result = tk.MustQuery("select @@old_passwords;") result.Check(testkit.Rows("0")) tk.MustExec("set @@old_passwords=3") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect old_passwords value: '3'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect old_passwords value: '3'")) result = tk.MustQuery("select @@old_passwords;") result.Check(testkit.Rows("2")) - _, err = tk.Exec("set @@old_passwords='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@old_passwords='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@tmp_table_size=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tmp_table_size value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tmp_table_size value: '-1'")) result = tk.MustQuery("select @@tmp_table_size;") result.Check(testkit.Rows("1024")) tk.MustExec("set @@tmp_table_size=1020") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tmp_table_size value: '1020'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tmp_table_size value: '1020'")) result = tk.MustQuery("select @@tmp_table_size;") result.Check(testkit.Rows("1024")) @@ -968,19 +988,19 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result = tk.MustQuery("select @@tmp_table_size;") result.Check(testkit.Rows("18446744073709551615")) - _, err = tk.Exec("set @@tmp_table_size=18446744073709551616") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@tmp_table_size=18446744073709551616") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) - _, err = tk.Exec("set @@tmp_table_size='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@tmp_table_size='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@tidb_tmp_table_max_size=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '-1'")) result = tk.MustQuery("select @@tidb_tmp_table_max_size;") result.Check(testkit.Rows("1048576")) tk.MustExec("set @@tidb_tmp_table_max_size=1048575") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '1048575'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '1048575'")) result = tk.MustQuery("select @@tidb_tmp_table_max_size;") result.Check(testkit.Rows("1048576")) @@ -993,15 +1013,15 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result.Check(testkit.Rows("137438953472")) tk.MustExec("set @@tidb_tmp_table_max_size=137438953473") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '137438953473'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tmp_table_max_size value: '137438953473'")) result = tk.MustQuery("select @@tidb_tmp_table_max_size;") result.Check(testkit.Rows("137438953472")) - _, err = tk.Exec("set @@tidb_tmp_table_max_size='hello'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongTypeForVar), IsTrue) + err = tk.ExecToErr("set @@tidb_tmp_table_max_size='hello'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongTypeForVar)) tk.MustExec("set @@global.connect_timeout=1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect connect_timeout value: '1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect connect_timeout value: '1'")) result = tk.MustQuery("select @@global.connect_timeout;") result.Check(testkit.Rows("2")) @@ -1010,7 +1030,7 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result.Check(testkit.Rows("31536000")) tk.MustExec("set @@global.connect_timeout=31536001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect connect_timeout value: '31536001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect connect_timeout value: '31536001'")) result = tk.MustQuery("select @@global.connect_timeout;") result.Check(testkit.Rows("31536000")) @@ -1036,8 +1056,8 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result = tk.MustQuery("select @@global.super_read_only;") result.Check(testkit.Rows("0")) - _, err = tk.Exec("set @@global.super_read_only=-1") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@global.super_read_only=-1") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@global.innodb_status_output_locks=-1") result = tk.MustQuery("select @@global.innodb_status_output_locks;") @@ -1055,8 +1075,8 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result = tk.MustQuery("select @@global.innodb_file_per_table;") result.Check(testkit.Rows("1")) - _, err = tk.Exec("set @@global.innodb_ft_enable_stopword=2") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@global.innodb_ft_enable_stopword=2") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@query_cache_type=0") result = tk.MustQuery("select @@query_cache_type;") @@ -1067,64 +1087,64 @@ func (s *testSuite5) TestValidateSetVar(c *C) { result.Check(testkit.Rows("DEMAND")) tk.MustExec("set @@global.sync_binlog=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect sync_binlog value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect sync_binlog value: '-1'")) tk.MustExec("set @@global.sync_binlog=4294967299") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect sync_binlog value: '4294967299'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect sync_binlog value: '4294967299'")) tk.MustExec("set @@global.flush_time=31536001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect flush_time value: '31536001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect flush_time value: '31536001'")) tk.MustExec("set @@global.interactive_timeout=31536001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect interactive_timeout value: '31536001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect interactive_timeout value: '31536001'")) tk.MustExec("set @@global.innodb_commit_concurrency = -1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_commit_concurrency value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_commit_concurrency value: '-1'")) tk.MustExec("set @@global.innodb_commit_concurrency = 1001") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_commit_concurrency value: '1001'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_commit_concurrency value: '1001'")) tk.MustExec("set @@global.innodb_fast_shutdown = -1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_fast_shutdown value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_fast_shutdown value: '-1'")) tk.MustExec("set @@global.innodb_fast_shutdown = 3") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_fast_shutdown value: '3'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_fast_shutdown value: '3'")) tk.MustExec("set @@global.innodb_lock_wait_timeout = 0") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '0'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '0'")) tk.MustExec("set @@global.innodb_lock_wait_timeout = 1073741825") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '1073741825'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '1073741825'")) tk.MustExec("set @@innodb_lock_wait_timeout = 0") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '0'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '0'")) tk.MustExec("set @@innodb_lock_wait_timeout = 1073741825") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '1073741825'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect innodb_lock_wait_timeout value: '1073741825'")) tk.MustExec("set @@global.validate_password_number_count=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect validate_password_number_count value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect validate_password_number_count value: '-1'")) tk.MustExec("set @@global.validate_password_length=-1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect validate_password_length value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect validate_password_length value: '-1'")) tk.MustExec("set @@global.validate_password_length=8") tk.MustQuery("show warnings").Check(testkit.Rows()) - _, err = tk.Exec("set @@tx_isolation=''") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@tx_isolation=''") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) - _, err = tk.Exec("set global tx_isolation=''") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set global tx_isolation=''") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) - _, err = tk.Exec("set @@transaction_isolation=''") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@transaction_isolation=''") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) - _, err = tk.Exec("set global transaction_isolation=''") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set global transaction_isolation=''") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) - _, err = tk.Exec("set global tx_isolation='REPEATABLE-READ1'") - c.Assert(terror.ErrorEqual(err, variable.ErrWrongValueForVar), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set global tx_isolation='REPEATABLE-READ1'") + require.True(t, terror.ErrorEqual(err, variable.ErrWrongValueForVar), fmt.Sprintf("err %v", err)) tk.MustExec("set @@tx_isolation='READ-COMMITTED'") result = tk.MustQuery("select @@tx_isolation;") @@ -1140,15 +1160,17 @@ func (s *testSuite5) TestValidateSetVar(c *C) { tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 0") - _, err = tk.Exec("set @@tx_isolation='SERIALIZABLE'") - c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("set @@tx_isolation='SERIALIZABLE'") + require.True(t, terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), fmt.Sprintf("err %v", err)) tk.MustExec("set global allow_auto_random_explicit_insert=on;") tk.MustQuery("select @@global.allow_auto_random_explicit_insert;").Check(testkit.Rows("1")) } -func (s *testSuite5) TestSelectGlobalVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectGlobalVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select @@global.max_connections;").Check(testkit.Rows("151")) tk.MustQuery("select @@max_connections;").Check(testkit.Rows("151")) @@ -1162,13 +1184,15 @@ func (s *testSuite5) TestSelectGlobalVar(c *C) { // test for unknown variable. err := tk.ExecToErr("select @@invalid") - c.Assert(terror.ErrorEqual(err, variable.ErrUnknownSystemVar), IsTrue, Commentf("err %v", err)) + require.True(t, terror.ErrorEqual(err, variable.ErrUnknownSystemVar), fmt.Sprintf("err %v", err)) err = tk.ExecToErr("select @@global.invalid") - c.Assert(terror.ErrorEqual(err, variable.ErrUnknownSystemVar), IsTrue, Commentf("err %v", err)) + require.True(t, terror.ErrorEqual(err, variable.ErrUnknownSystemVar), fmt.Sprintf("err %v", err)) } -func (s *testSuite5) TestSetConcurrency(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetConcurrency(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test default value tk.MustQuery("select @@tidb_executor_concurrency;").Check(testkit.Rows(strconv.Itoa(variable.DefExecutorConcurrency))) @@ -1185,61 +1209,61 @@ func (s *testSuite5) TestSetConcurrency(c *C) { tk.MustQuery("select @@tidb_index_serial_scan_concurrency;").Check(testkit.Rows(strconv.Itoa(variable.DefIndexSerialScanConcurrency))) - vars := tk.Se.(sessionctx.Context).GetSessionVars() - c.Assert(vars.ExecutorConcurrency, Equals, variable.DefExecutorConcurrency) - c.Assert(vars.IndexLookupConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.IndexLookupJoinConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashJoinConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashAggPartialConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashAggFinalConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.WindowConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.StreamAggConcurrency(), Equals, variable.DefTiDBStreamAggConcurrency) - c.Assert(vars.ProjectionConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.DistSQLScanConcurrency(), Equals, variable.DefDistSQLScanConcurrency) + vars := tk.Session().GetSessionVars() + require.Equal(t, variable.DefExecutorConcurrency, vars.ExecutorConcurrency) + require.Equal(t, variable.DefExecutorConcurrency, vars.IndexLookupConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.IndexLookupJoinConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashJoinConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashAggPartialConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashAggFinalConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.WindowConcurrency()) + require.Equal(t, variable.DefTiDBStreamAggConcurrency, vars.StreamAggConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.ProjectionConcurrency()) + require.Equal(t, variable.DefDistSQLScanConcurrency, vars.DistSQLScanConcurrency()) - c.Assert(vars.IndexSerialScanConcurrency(), Equals, variable.DefIndexSerialScanConcurrency) + require.Equal(t, variable.DefIndexSerialScanConcurrency, vars.IndexSerialScanConcurrency()) // test setting deprecated variables warnTpl := "Warning 1287 '%s' is deprecated and will be removed in a future release. Please use tidb_executor_concurrency instead" checkSet := func(v string) { tk.MustExec(fmt.Sprintf("set @@%s=1;", v)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", fmt.Sprintf(warnTpl, v))) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", fmt.Sprintf(warnTpl, v))) tk.MustQuery(fmt.Sprintf("select @@%s;", v)).Check(testkit.Rows("1")) } checkSet(variable.TiDBIndexLookupConcurrency) - c.Assert(vars.IndexLookupConcurrency(), Equals, 1) + require.Equal(t, 1, vars.IndexLookupConcurrency()) checkSet(variable.TiDBIndexLookupJoinConcurrency) - c.Assert(vars.IndexLookupJoinConcurrency(), Equals, 1) + require.Equal(t, 1, vars.IndexLookupJoinConcurrency()) checkSet(variable.TiDBHashJoinConcurrency) - c.Assert(vars.HashJoinConcurrency(), Equals, 1) + require.Equal(t, 1, vars.HashJoinConcurrency()) checkSet(variable.TiDBHashAggPartialConcurrency) - c.Assert(vars.HashAggPartialConcurrency(), Equals, 1) + require.Equal(t, 1, vars.HashAggPartialConcurrency()) checkSet(variable.TiDBHashAggFinalConcurrency) - c.Assert(vars.HashAggFinalConcurrency(), Equals, 1) + require.Equal(t, 1, vars.HashAggFinalConcurrency()) checkSet(variable.TiDBProjectionConcurrency) - c.Assert(vars.ProjectionConcurrency(), Equals, 1) + require.Equal(t, 1, vars.ProjectionConcurrency()) checkSet(variable.TiDBWindowConcurrency) - c.Assert(vars.WindowConcurrency(), Equals, 1) + require.Equal(t, 1, vars.WindowConcurrency()) checkSet(variable.TiDBStreamAggConcurrency) - c.Assert(vars.StreamAggConcurrency(), Equals, 1) + require.Equal(t, 1, vars.StreamAggConcurrency()) tk.MustExec(fmt.Sprintf("set @@%s=1;", variable.TiDBDistSQLScanConcurrency)) tk.MustQuery(fmt.Sprintf("select @@%s;", variable.TiDBDistSQLScanConcurrency)).Check(testkit.Rows("1")) - c.Assert(vars.DistSQLScanConcurrency(), Equals, 1) + require.Equal(t, 1, vars.DistSQLScanConcurrency()) tk.MustExec("set @@tidb_index_serial_scan_concurrency=4") tk.MustQuery("show warnings").Check(testkit.Rows()) tk.MustQuery("select @@tidb_index_serial_scan_concurrency;").Check(testkit.Rows("4")) - c.Assert(vars.IndexSerialScanConcurrency(), Equals, 4) + require.Equal(t, 4, vars.IndexSerialScanConcurrency()) // test setting deprecated value unset tk.MustExec("set @@tidb_index_lookup_concurrency=-1;") @@ -1251,22 +1275,24 @@ func (s *testSuite5) TestSetConcurrency(c *C) { tk.MustExec("set @@tidb_streamagg_concurrency=-1;") tk.MustExec("set @@tidb_projection_concurrency=-1;") - c.Assert(vars.IndexLookupConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.IndexLookupJoinConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashJoinConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashAggPartialConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.HashAggFinalConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.WindowConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.StreamAggConcurrency(), Equals, variable.DefExecutorConcurrency) - c.Assert(vars.ProjectionConcurrency(), Equals, variable.DefExecutorConcurrency) + require.Equal(t, variable.DefExecutorConcurrency, vars.IndexLookupConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.IndexLookupJoinConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashJoinConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashAggPartialConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.HashAggFinalConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.WindowConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.StreamAggConcurrency()) + require.Equal(t, variable.DefExecutorConcurrency, vars.ProjectionConcurrency()) tk.MustExec("set @@tidb_executor_concurrency=-1;") tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_executor_concurrency value: '-1'")) - c.Assert(vars.ExecutorConcurrency, Equals, 1) + require.Equal(t, 1, vars.ExecutorConcurrency) } -func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnableNoopFunctionsVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) defer func() { // Ensure global settings are reset. @@ -1282,10 +1308,10 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustQuery(`select @@global.tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - _, err := tk.Exec(`select get_lock('lock1', 2);`) - c.Assert(terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) - _, err = tk.Exec(`select release_lock('lock1');`) - c.Assert(terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err := tk.ExecToErr(`select get_lock('lock1', 2);`) + require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) + err = tk.ExecToErr(`select release_lock('lock1');`) + require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) // change session var to 1 tk.MustExec(`set tidb_enable_noop_functions=1;`) @@ -1299,16 +1325,14 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) tk.MustQuery(`select @@global.tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - _, err = tk.Exec(`select get_lock('lock2', 10);`) - c.Assert(terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) - _, err = tk.Exec(`select release_lock('lock2');`) - c.Assert(terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr(`select get_lock('lock2', 10);`) + require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) + err = tk.ExecToErr(`select release_lock('lock2');`) + require.True(t, terror.ErrorEqual(err, expression.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) // set test - _, err = tk.Exec(`set tidb_enable_noop_functions='abc'`) - c.Assert(err, NotNil) - _, err = tk.Exec(`set tidb_enable_noop_functions=11`) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr(`set tidb_enable_noop_functions='abc'`)) + require.Error(t, tk.ExecToErr(`set tidb_enable_noop_functions=11`)) tk.MustExec(`set tidb_enable_noop_functions="off";`) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) tk.MustExec(`set tidb_enable_noop_functions="on";`) @@ -1316,21 +1340,21 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustExec(`set tidb_enable_noop_functions=0;`) tk.MustQuery(`select @@tidb_enable_noop_functions;`).Check(testkit.Rows("OFF")) - _, err = tk.Exec("SET SESSION tx_read_only = 1") - c.Assert(terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET SESSION tx_read_only = 1") + require.True(t, terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) tk.MustExec("SET SESSION tx_read_only = 0") tk.MustQuery("select @@session.tx_read_only").Check(testkit.Rows("0")) tk.MustQuery("select @@session.transaction_read_only").Check(testkit.Rows("0")) - _, err = tk.Exec("SET GLOBAL tx_read_only = 1") // should fail. - c.Assert(terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL tx_read_only = 1") // should fail. + require.True(t, terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) tk.MustExec("SET GLOBAL tx_read_only = 0") tk.MustQuery("select @@global.tx_read_only").Check(testkit.Rows("0")) tk.MustQuery("select @@global.transaction_read_only").Check(testkit.Rows("0")) - _, err = tk.Exec("SET SESSION transaction_read_only = 1") - c.Assert(terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET SESSION transaction_read_only = 1") + require.True(t, terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) tk.MustExec("SET SESSION transaction_read_only = 0") tk.MustQuery("select @@session.tx_read_only").Check(testkit.Rows("0")) tk.MustQuery("select @@session.transaction_read_only").Check(testkit.Rows("0")) @@ -1342,8 +1366,8 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustQuery("select @@session.transaction_read_only").Check(testkit.Rows("1")) // fails on GLOBAL because GLOBAL.tidb_enable_noop_functions still=0 - _, err = tk.Exec("SET GLOBAL transaction_read_only = 1") - c.Assert(terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), IsTrue, Commentf("err %v", err)) + err = tk.ExecToErr("SET GLOBAL transaction_read_only = 1") + require.True(t, terror.ErrorEqual(err, variable.ErrFunctionsNoopImpl), fmt.Sprintf("err %v", err)) tk.MustExec("SET GLOBAL tidb_enable_noop_functions = 1") // now works tk.MustExec("SET GLOBAL transaction_read_only = 1") @@ -1353,8 +1377,7 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustQuery("select @@global.tx_read_only").Check(testkit.Rows("0")) tk.MustQuery("select @@global.transaction_read_only").Check(testkit.Rows("0")) - _, err = tk.Exec("SET tidb_enable_noop_functions = 0") // fails because transaction_read_only/tx_read_only = 1 - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("SET tidb_enable_noop_functions = 0")) // fails because transaction_read_only/tx_read_only = 1 tk.MustExec("SET transaction_read_only = 0") tk.MustExec("SET tidb_enable_noop_functions = 0") // now works. @@ -1366,8 +1389,7 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustExec("SET GLOBAL tidb_enable_noop_functions = 1") tk.MustExec("SET GLOBAL transaction_read_only = 1") // fails - _, err = tk.Exec("SET GLOBAL tidb_enable_noop_functions = 0") - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("SET GLOBAL tidb_enable_noop_functions = 0")) // reset for rest of tests. tk.MustExec("SET GLOBAL transaction_read_only = 0") @@ -1382,14 +1404,15 @@ func (s *testSuite5) TestEnableNoopFunctionsVar(c *C) { tk.MustQuery("select @@global.read_only;").Check(testkit.Rows("1")) tk.MustExec("set global read_only = on") tk.MustQuery("select @@global.read_only;").Check(testkit.Rows("1")) - _, err = tk.Exec("set global read_only = abc") - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr("set global read_only = abc")) } // https://github.com/pingcap/tidb/issues/29670 -func (s *testSuite5) TestDefaultBehavior(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDefaultBehavior(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("SELECT @@default_storage_engine").Check(testkit.Rows("InnoDB")) tk.MustExec("SET GLOBAL default_storage_engine = 'somethingweird'") @@ -1408,13 +1431,14 @@ func (s *testSuite5) TestDefaultBehavior(c *C) { // Try sql_mode option which has validation err := tk.ExecToErr("SET GLOBAL sql_mode = 'DEFAULT'") // illegal now - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, `ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'DEFAULT'`) + require.EqualError(t, err, `ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'DEFAULT'`) tk.MustExec("SET GLOBAL sql_mode = DEFAULT") } -func (s *testSuite5) TestRemovedSysVars(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRemovedSysVars(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test for tidb_enable_noop_functions // In SET context, it just noops: @@ -1427,11 +1451,12 @@ func (s *testSuite5) TestRemovedSysVars(c *C) { // (to avoid presenting dummy data) tk.MustGetErrCode("SELECT @@tidb_slow_log_masking", errno.ErrVariableNoLongerSupported) tk.MustGetErrCode("SELECT @@tidb_enable_global_temporary_table", errno.ErrVariableNoLongerSupported) - } -func (s *testSuite5) TestSetClusterConfig(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetClusterConfig(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") serversInfo := []infoschema.ServerInfo{ @@ -1446,37 +1471,37 @@ func (s *testSuite5) TestSetClusterConfig(c *C) { serverInfoFunc := func(sessionctx.Context) ([]infoschema.ServerInfo, error) { return serversInfo, serverInfoErr } - tk.Se.SetValue(executor.TestSetConfigServerInfoKey, serverInfoFunc) + tk.Session().SetValue(executor.TestSetConfigServerInfoKey, serverInfoFunc) - c.Assert(tk.ExecToErr("set config xxx log.level='info'"), ErrorMatches, "unknown type xxx") - c.Assert(tk.ExecToErr("set config tidb log.level='info'"), ErrorMatches, "TiDB doesn't support to change configs online, please use SQL variables") - c.Assert(tk.ExecToErr("set config '127.0.0.1:1111' log.level='info'"), ErrorMatches, "TiDB doesn't support to change configs online, please use SQL variables") - c.Assert(tk.ExecToErr("set config '127.a.b.c:1234' log.level='info'"), ErrorMatches, "invalid instance 127.a.b.c:1234") // name doesn't resolve. - c.Assert(tk.ExecToErr("set config 'example.com:1111' log.level='info'"), ErrorMatches, "instance example.com:1111 is not found in this cluster") // name resolves. - c.Assert(tk.ExecToErr("set config tikv log.level=null"), ErrorMatches, "can't set config to null") - c.Assert(tk.ExecToErr("set config '1.1.1.1:1111' log.level='info'"), ErrorMatches, "instance 1.1.1.1:1111 is not found in this cluster") + require.EqualError(t, tk.ExecToErr("set config xxx log.level='info'"), "unknown type xxx") + require.EqualError(t, tk.ExecToErr("set config tidb log.level='info'"), "TiDB doesn't support to change configs online, please use SQL variables") + require.EqualError(t, tk.ExecToErr("set config '127.0.0.1:1111' log.level='info'"), "TiDB doesn't support to change configs online, please use SQL variables") + require.EqualError(t, tk.ExecToErr("set config '127.a.b.c:1234' log.level='info'"), "invalid instance 127.a.b.c:1234") // name doesn't resolve. + require.EqualError(t, tk.ExecToErr("set config 'example.com:1111' log.level='info'"), "instance example.com:1111 is not found in this cluster") // name resolves. + require.EqualError(t, tk.ExecToErr("set config tikv log.level=null"), "can't set config to null") + require.EqualError(t, tk.ExecToErr("set config '1.1.1.1:1111' log.level='info'"), "instance 1.1.1.1:1111 is not found in this cluster") httpCnt := 0 - tk.Se.SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { + tk.Session().SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { httpCnt++ return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(nil)}, nil }) tk.MustExec("set config tikv log.level='info'") - c.Assert(httpCnt, Equals, 2) + require.Equal(t, 2, httpCnt) httpCnt = 0 tk.MustExec("set config '127.0.0.1:5555' log.level='info'") - c.Assert(httpCnt, Equals, 1) + require.Equal(t, 1, httpCnt) httpCnt = 0 - tk.Se.SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { + tk.Session().SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { return nil, errors.New("something wrong") }) tk.MustExec("set config tikv log.level='info'") tk.MustQuery("show warnings").Check(testkit.Rows( "Warning 1105 something wrong", "Warning 1105 something wrong")) - tk.Se.SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { + tk.Session().SetValue(executor.TestSetConfigHTTPHandlerKey, func(*http.Request) (*http.Response, error) { return &http.Response{StatusCode: http.StatusBadRequest, Body: io.NopCloser(bytes.NewBufferString("WRONG"))}, nil }) tk.MustExec("set config tikv log.level='info'") @@ -1484,9 +1509,9 @@ func (s *testSuite5) TestSetClusterConfig(c *C) { "Warning 1105 bad request to http://127.0.0.1:5555/config: WRONG", "Warning 1105 bad request to http://127.0.0.1:6666/config: WRONG")) } -func (s *testSuite5) TestSetClusterConfigJSONData(c *C) { +func TestSetClusterConfigJSONData(t *testing.T) { var d types.MyDecimal - c.Assert(d.FromFloat64(123.456), IsNil) + require.NoError(t, d.FromFloat64(123.456)) tyBool := types.NewFieldType(mysql.TypeTiny) tyBool.Flag |= mysql.IsBooleanFlag cases := []struct { @@ -1503,91 +1528,82 @@ func (s *testSuite5) TestSetClusterConfigJSONData(c *C) { {&expression.Constant{Value: types.NewDatum(nil), RetType: types.NewFieldType(mysql.TypeLonglong)}, "", false}, {&expression.Constant{RetType: types.NewFieldType(mysql.TypeJSON)}, "", false}, // unsupported type {nil, "", false}, + {&expression.Constant{Value: types.NewDatum(`["no","no","lz4","lz4","lz4","zstd","zstd"]`), RetType: types.NewFieldType(mysql.TypeString)}, `{"k":"[\"no\",\"no\",\"lz4\",\"lz4\",\"lz4\",\"zstd\",\"zstd\"]"}`, true}, } ctx := mock.NewContext() - for _, t := range cases { - result, err := executor.ConvertConfigItem2JSON(ctx, "k", t.val) - if t.succ { - c.Assert(t.result, Equals, result) + for _, c := range cases { + result, err := executor.ConvertConfigItem2JSON(ctx, "k", c.val) + if c.succ { + require.Equal(t, result, c.result) } else { - c.Assert(err, NotNil) + require.Error(t, err) } } } -func (s *testSerialSuite) TestSetTopSQLVariables(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop", `return(true)`), IsNil) +func TestSetTopSQLVariables(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop", `return(true)`)) defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop") - c.Assert(err, IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop")) }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@global.tidb_enable_top_sql='On';") tk.MustQuery("select @@global.tidb_enable_top_sql;").Check(testkit.Rows("1")) - c.Assert(variable.TopSQLVariable.Enable.Load(), IsTrue) tk.MustExec("set @@global.tidb_enable_top_sql='off';") tk.MustQuery("select @@global.tidb_enable_top_sql;").Check(testkit.Rows("0")) - c.Assert(variable.TopSQLVariable.Enable.Load(), IsFalse) - - tk.MustExec("set @@global.tidb_top_sql_precision_seconds=2;") - tk.MustQuery("select @@global.tidb_top_sql_precision_seconds;").Check(testkit.Rows("2")) - c.Assert(variable.TopSQLVariable.PrecisionSeconds.Load(), Equals, int64(2)) - _, err := tk.Exec("set @@global.tidb_top_sql_precision_seconds='abc';") - c.Assert(err.Error(), Equals, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_precision_seconds'") - tk.MustExec("set @@global.tidb_top_sql_precision_seconds='-1';") - tk.MustQuery("select @@global.tidb_top_sql_precision_seconds;").Check(testkit.Rows("1")) - tk.MustExec("set @@global.tidb_top_sql_precision_seconds=2;") - tk.MustQuery("select @@global.tidb_top_sql_precision_seconds;").Check(testkit.Rows("2")) - c.Assert(variable.TopSQLVariable.PrecisionSeconds.Load(), Equals, int64(2)) - - tk.MustExec("set @@global.tidb_top_sql_max_statement_count=20;") - tk.MustQuery("select @@global.tidb_top_sql_max_statement_count;").Check(testkit.Rows("20")) - c.Assert(variable.TopSQLVariable.MaxStatementCount.Load(), Equals, int64(20)) - _, err = tk.Exec("set @@global.tidb_top_sql_max_statement_count='abc';") - c.Assert(err.Error(), Equals, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_max_statement_count'") - tk.MustExec("set @@global.tidb_top_sql_max_statement_count='-1';") - tk.MustQuery("select @@global.tidb_top_sql_max_statement_count;").Check(testkit.Rows("0")) - tk.MustExec("set @@global.tidb_top_sql_max_statement_count='5001';") - tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_statement_count value: '5001'")) - tk.MustQuery("select @@global.tidb_top_sql_max_statement_count;").Check(testkit.Rows("5000")) - - tk.MustExec("set @@global.tidb_top_sql_max_statement_count=20;") - tk.MustQuery("select @@global.tidb_top_sql_max_statement_count;").Check(testkit.Rows("20")) - c.Assert(variable.TopSQLVariable.MaxStatementCount.Load(), Equals, int64(20)) - - tk.MustExec("set @@global.tidb_top_sql_max_collect=10000;") - tk.MustQuery("select @@global.tidb_top_sql_max_collect;").Check(testkit.Rows("10000")) - c.Assert(variable.TopSQLVariable.MaxCollect.Load(), Equals, int64(10000)) - _, err = tk.Exec("set @@global.tidb_top_sql_max_collect='abc';") - c.Assert(err.Error(), Equals, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_max_collect'") - tk.MustExec("set @@global.tidb_top_sql_max_collect='-1';") - tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_collect value: '-1'")) - tk.MustQuery("select @@global.tidb_top_sql_max_collect;").Check(testkit.Rows("1")) - - tk.MustExec("set @@global.tidb_top_sql_max_collect='10001';") - tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_collect value: '10001'")) - tk.MustQuery("select @@global.tidb_top_sql_max_collect;").Check(testkit.Rows("10000")) - - tk.MustExec("set @@global.tidb_top_sql_max_collect=5000;") - tk.MustQuery("select @@global.tidb_top_sql_max_collect;").Check(testkit.Rows("5000")) - c.Assert(variable.TopSQLVariable.MaxCollect.Load(), Equals, int64(5000)) - - tk.MustExec("set @@global.tidb_top_sql_report_interval_seconds=120;") - tk.MustQuery("select @@global.tidb_top_sql_report_interval_seconds;").Check(testkit.Rows("120")) - c.Assert(variable.TopSQLVariable.ReportIntervalSeconds.Load(), Equals, int64(120)) - _, err = tk.Exec("set @@global.tidb_top_sql_report_interval_seconds='abc';") - c.Assert(err.Error(), Equals, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_report_interval_seconds'") - tk.MustExec("set @@global.tidb_top_sql_report_interval_seconds='5000';") - tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_report_interval_seconds value: '5000'")) - tk.MustQuery("select @@global.tidb_top_sql_report_interval_seconds;").Check(testkit.Rows("3600")) - - tk.MustExec("set @@global.tidb_top_sql_report_interval_seconds=120;") - tk.MustQuery("select @@global.tidb_top_sql_report_interval_seconds;").Check(testkit.Rows("120")) - c.Assert(variable.TopSQLVariable.ReportIntervalSeconds.Load(), Equals, int64(120)) - - // Test for hide top sql variable in show variable. - tk.MustQuery("show variables like '%top_sql%'").Check(testkit.Rows()) - tk.MustQuery("show global variables like '%top_sql%'").Check(testkit.Rows()) + + tk.MustExec("set @@global.tidb_top_sql_max_time_series_count=20;") + tk.MustQuery("select @@global.tidb_top_sql_max_time_series_count;").Check(testkit.Rows("20")) + require.Equal(t, int64(20), topsqlstate.GlobalState.MaxStatementCount.Load()) + err := tk.ExecToErr("set @@global.tidb_top_sql_max_time_series_count='abc';") + require.EqualError(t, err, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_max_time_series_count'") + tk.MustExec("set @@global.tidb_top_sql_max_time_series_count='-1';") + tk.MustQuery("select @@global.tidb_top_sql_max_time_series_count;").Check(testkit.Rows("1")) + tk.MustExec("set @@global.tidb_top_sql_max_time_series_count='5001';") + tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_time_series_count value: '5001'")) + tk.MustQuery("select @@global.tidb_top_sql_max_time_series_count;").Check(testkit.Rows("5000")) + + tk.MustExec("set @@global.tidb_top_sql_max_time_series_count=20;") + tk.MustQuery("select @@global.tidb_top_sql_max_time_series_count;").Check(testkit.Rows("20")) + require.Equal(t, int64(20), topsqlstate.GlobalState.MaxStatementCount.Load()) + + tk.MustExec("set @@global.tidb_top_sql_max_meta_count=10000;") + tk.MustQuery("select @@global.tidb_top_sql_max_meta_count;").Check(testkit.Rows("10000")) + require.Equal(t, int64(10000), topsqlstate.GlobalState.MaxCollect.Load()) + err = tk.ExecToErr("set @@global.tidb_top_sql_max_meta_count='abc';") + require.EqualError(t, err, "[variable:1232]Incorrect argument type to variable 'tidb_top_sql_max_meta_count'") + tk.MustExec("set @@global.tidb_top_sql_max_meta_count='-1';") + tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_meta_count value: '-1'")) + tk.MustQuery("select @@global.tidb_top_sql_max_meta_count;").Check(testkit.Rows("1")) + + tk.MustExec("set @@global.tidb_top_sql_max_meta_count='10001';") + tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_top_sql_max_meta_count value: '10001'")) + tk.MustQuery("select @@global.tidb_top_sql_max_meta_count;").Check(testkit.Rows("10000")) + + tk.MustExec("set @@global.tidb_top_sql_max_meta_count=5000;") + tk.MustQuery("select @@global.tidb_top_sql_max_meta_count;").Check(testkit.Rows("5000")) + require.Equal(t, int64(5000), topsqlstate.GlobalState.MaxCollect.Load()) + + tk.MustQuery("show variables like '%top_sql%'").Check(testkit.Rows("tidb_enable_top_sql OFF", "tidb_top_sql_max_meta_count 5000", "tidb_top_sql_max_time_series_count 20")) + tk.MustQuery("show global variables like '%top_sql%'").Check(testkit.Rows("tidb_enable_top_sql OFF", "tidb_top_sql_max_meta_count 5000", "tidb_top_sql_max_time_series_count 20")) +} + +func TestInstanceScopeSwitching(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // enable 'switching' to SESSION variables + tk.MustExec("set tidb_enable_legacy_instance_scope = 1") + tk.MustExec("set tidb_general_log = 1") + tk.MustQuery(`show warnings`).Check(testkit.Rows(fmt.Sprintf("Warning %d modifying tidb_general_log will require SET GLOBAL in a future version of TiDB", errno.ErrInstanceScope))) + + // disable 'switching' to SESSION variables + tk.MustExec("set tidb_enable_legacy_instance_scope = 0") + tk.MustGetErrCode("set tidb_general_log = 1", errno.ErrGlobalVariable) } diff --git a/executor/show.go b/executor/show.go index 2a4eac148f74e..5e6c9afc93070 100644 --- a/executor/show.go +++ b/executor/show.go @@ -19,7 +19,6 @@ import ( "context" gjson "encoding/json" "fmt" - "reflect" "sort" "strconv" "strings" @@ -27,9 +26,6 @@ import ( "github.com/cznic/mathutil" "github.com/pingcap/errors" - "github.com/pingcap/tidb-tools/pkg/etcd" - "github.com/pingcap/tidb-tools/pkg/utils" - "github.com/pingcap/tidb-tools/tidb-binlog/node" "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" @@ -55,14 +51,17 @@ import ( "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/tidb-binlog/node" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/etcd" "github.com/pingcap/tidb/util/format" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/hint" + "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/set" "github.com/pingcap/tidb/util/sqlexec" @@ -84,6 +83,7 @@ type ShowExec struct { Flag int // Some flag parsed from sql, such as FULL. Roles []*auth.RoleIdentity // Used for show grants. User *auth.UserIdentity // Used by show grants, show create user. + Extractor plannercore.ShowPredicateExtractor is infoschema.InfoSchema @@ -211,9 +211,10 @@ func (e *ShowExec) fetchAll(ctx context.Context) error { return e.fetchShowPrivileges() case ast.ShowBindings: return e.fetchShowBind() + case ast.ShowBindingCacheStatus: + return e.fetchShowBindingCacheStatus(ctx) case ast.ShowAnalyzeStatus: - e.fetchShowAnalyzeStatus() - return nil + return e.fetchShowAnalyzeStatus() case ast.ShowRegions: return e.fetchShowTableRegions() case ast.ShowBuiltins: @@ -339,14 +340,41 @@ func (e *ShowExec) fetchShowBind() error { return nil } -func (e *ShowExec) fetchShowEngines(ctx context.Context) error { +func (e *ShowExec) fetchShowBindingCacheStatus(ctx context.Context) error { exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, `SELECT * FROM information_schema.engines`) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, fmt.Sprintf("SELECT count(*) FROM mysql.bind_info where status = '%s' or status = '%s';", bindinfo.Enabled, bindinfo.Using)) if err != nil { return errors.Trace(err) } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + + handle := domain.GetDomain(e.ctx).BindHandle() + + bindRecords := handle.GetAllBindRecord() + numBindings := 0 + for _, bindRecord := range bindRecords { + for _, binding := range bindRecord.Bindings { + if binding.IsBindingEnabled() { + numBindings++ + } + } + } + + memUsage := handle.GetMemUsage() + memCapacity := handle.GetMemCapacity() + e.appendRow([]interface{}{ + numBindings, + rows[0].GetInt64(0), + memory.FormatBytes(memUsage), + memory.FormatBytes(memCapacity), + }) + return nil +} + +func (e *ShowExec) fetchShowEngines(ctx context.Context) error { + exec := e.ctx.(sqlexec.RestrictedSQLExecutor) + + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, `SELECT * FROM information_schema.engines`) if err != nil { return errors.Trace(err) } @@ -429,14 +457,33 @@ func (e *ShowExec) fetchShowTables() error { return ErrBadDB.GenWithStackByArgs(e.DBName) } // sort for tables - tableNames := make([]string, 0, len(e.is.SchemaTables(e.DBName))) + schemaTables := e.is.SchemaTables(e.DBName) + tableNames := make([]string, 0, len(schemaTables)) activeRoles := e.ctx.GetSessionVars().ActiveRoles - var tableTypes = make(map[string]string) - for _, v := range e.is.SchemaTables(e.DBName) { + var ( + tableTypes = make(map[string]string) + fieldPatternsLike collate.WildcardPattern + FieldFilterEnable bool + fieldFilter string + ) + if e.Extractor != nil { + extractor := (e.Extractor).(*plannercore.ShowTablesTableExtractor) + if extractor.FieldPatterns != "" { + fieldPatternsLike = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + fieldPatternsLike.Compile(extractor.FieldPatterns, byte('\\')) + } + FieldFilterEnable = extractor.Field != "" + fieldFilter = extractor.Field + } + for _, v := range schemaTables { // Test with mysql.AllPrivMask means any privilege would be OK. // TODO: Should consider column privileges, which also make a table visible. if checker != nil && !checker.RequestVerification(activeRoles, e.DBName.O, v.Meta().Name.O, "", mysql.AllPrivMask) { continue + } else if FieldFilterEnable && v.Meta().Name.L != fieldFilter { + continue + } else if fieldPatternsLike != nil && !fieldPatternsLike.DoMatch(v.Meta().Name.L) { + continue } tableNames = append(tableNames, v.Meta().Name.O) if v.Meta().IsView() { @@ -473,17 +520,6 @@ func (e *ShowExec) fetchShowTableStatus(ctx context.Context) error { exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, `SELECT - table_name, engine, version, row_format, table_rows, - avg_row_length, data_length, max_data_length, index_length, - data_free, auto_increment, create_time, update_time, check_time, - table_collation, IFNULL(checksum,''), create_options, table_comment - FROM information_schema.tables - WHERE lower(table_schema)=%? ORDER BY table_name`, e.DBName.L) - if err != nil { - return errors.Trace(err) - } - var snapshot uint64 txn, err := e.ctx.Txn(false) if err != nil { @@ -496,7 +532,13 @@ func (e *ShowExec) fetchShowTableStatus(ctx context.Context) error { snapshot = e.ctx.GetSessionVars().SnapshotTS } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt, sqlexec.ExecOptionWithSnapshot(snapshot)) + rows, _, err := exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionWithSnapshot(snapshot), sqlexec.ExecOptionUseCurSession}, + `SELECT table_name, engine, version, row_format, table_rows, + avg_row_length, data_length, max_data_length, index_length, + data_free, auto_increment, create_time, update_time, check_time, + table_collation, IFNULL(checksum,''), create_options, table_comment + FROM information_schema.tables + WHERE lower(table_schema)=%? ORDER BY table_name`, e.DBName.L) if err != nil { return errors.Trace(err) } @@ -514,10 +556,24 @@ func (e *ShowExec) fetchShowTableStatus(ctx context.Context) error { func (e *ShowExec) fetchShowColumns(ctx context.Context) error { tb, err := e.getTable() - if err != nil { return errors.Trace(err) } + var ( + fieldPatternsLike collate.WildcardPattern + FieldFilterEnable bool + fieldFilter string + ) + if e.Extractor != nil { + extractor := (e.Extractor).(*plannercore.ShowColumnsTableExtractor) + if extractor.FieldPatterns != "" { + fieldPatternsLike = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + fieldPatternsLike.Compile(extractor.FieldPatterns, byte('\\')) + } + FieldFilterEnable = extractor.Field != "" + fieldFilter = extractor.Field + } + checker := privilege.GetPrivilegeManager(e.ctx) activeRoles := e.ctx.GetSessionVars().ActiveRoles if checker != nil && e.ctx.GetSessionVars().User != nil && !checker.RequestVerification(activeRoles, e.DBName.O, tb.Meta().Name.O, "", mysql.InsertPriv|mysql.SelectPriv|mysql.UpdatePriv|mysql.ReferencesPriv) { @@ -536,10 +592,11 @@ func (e *ShowExec) fetchShowColumns(ctx context.Context) error { return err } for _, col := range cols { - if e.Column != nil && e.Column.Name.L != col.Name.L { + if FieldFilterEnable && col.Name.L != fieldFilter { + continue + } else if fieldPatternsLike != nil && !fieldPatternsLike.DoMatch(col.Name.L) { continue } - desc := table.NewColDesc(col) var columnDefault interface{} if desc.DefaultValue != nil { @@ -726,6 +783,20 @@ func (e *ShowExec) fetchShowVariables() (err error) { value string sessionVars = e.ctx.GetSessionVars() ) + var ( + fieldPatternsLike collate.WildcardPattern + FieldFilterEnable bool + fieldFilter string + ) + if e.Extractor != nil { + extractor := (e.Extractor).(*plannercore.ShowVariablesExtractor) + if extractor.FieldPatterns != "" { + fieldPatternsLike = collate.GetCollatorByID(collate.CollationName2ID(mysql.UTF8MB4DefaultCollation)).Pattern() + fieldPatternsLike.Compile(extractor.FieldPatterns, byte('\\')) + } + FieldFilterEnable = extractor.Field != "" + fieldFilter = extractor.Field + } if e.GlobalScope { // Collect global scope variables, // 1. Exclude the variables of ScopeSession in variable.SysVars; @@ -733,6 +804,11 @@ func (e *ShowExec) fetchShowVariables() (err error) { // otherwise, fetch the value from table `mysql.Global_Variables`. for _, v := range variable.GetSysVars() { if v.Scope != variable.ScopeSession { + if FieldFilterEnable && v.Name != fieldFilter { + continue + } else if fieldPatternsLike != nil && !fieldPatternsLike.DoMatch(v.Name) { + continue + } if v.Hidden || e.sysVarHiddenForSem(v.Name) { continue } @@ -750,6 +826,11 @@ func (e *ShowExec) fetchShowVariables() (err error) { // If it is a session only variable, use the default value defined in code, // otherwise, fetch the value from table `mysql.Global_Variables`. for _, v := range variable.GetSysVars() { + if FieldFilterEnable && v.Name != fieldFilter { + continue + } else if fieldPatternsLike != nil && !fieldPatternsLike.DoMatch(v.Name) { + continue + } if v.Hidden || e.sysVarHiddenForSem(v.Name) { continue } @@ -1077,8 +1158,12 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T fmt.Fprintf(buf, " /*T![placement] PLACEMENT POLICY=%s */", stringutil.Escape(tableInfo.PlacementPolicyRef.Name.String(), sqlMode)) } - // add direct placement info here - appendDirectPlacementInfo(tableInfo.DirectPlacementOpts, buf) + if tableInfo.TableCacheStatusType == model.TableCacheStatusEnable { + // This is not meant to be understand by other components, so it's not written as /*T![cached] */ + // For all external components, cached table is just a normal table. + fmt.Fprintf(buf, " /* CACHED ON */") + } + // add partition info here. appendPartitionInfo(tableInfo.Partition, buf, sqlMode) return nil @@ -1213,27 +1298,6 @@ func fetchShowCreateTable4View(ctx sessionctx.Context, tb *model.TableInfo, buf fmt.Fprintf(buf, ") AS %s", tb.View.SelectStmt) } -func appendDirectPlacementInfo(directPlacementOpts *model.PlacementSettings, buf *bytes.Buffer) { - if directPlacementOpts == nil { - return - } - opts := reflect.ValueOf(*directPlacementOpts) - typeOpts := opts.Type() - fmt.Fprintf(buf, " /*T![placement]") - for i := 0; i < opts.NumField(); i++ { - if !opts.Field(i).IsZero() { - v := opts.Field(i).Interface() - switch v.(type) { - case string: - fmt.Fprintf(buf, ` %s="%s"`, strings.ToUpper(typeOpts.Field(i).Tag.Get("json")), v) - case uint64: - fmt.Fprintf(buf, " %s=%d", strings.ToUpper(typeOpts.Field(i).Tag.Get("json")), v) - } - } - } - fmt.Fprintf(buf, " */") -} - func appendPartitionInfo(partitionInfo *model.PartitionInfo, buf *bytes.Buffer, sqlMode mysql.SQLMode) { if partitionInfo == nil { return @@ -1249,7 +1313,7 @@ func appendPartitionInfo(partitionInfo *model.PartitionInfo, buf *bytes.Buffer, defaultPartitionDefinitions = false break } - if len(def.Comment) > 0 || def.DirectPlacementOpts != nil || def.PlacementPolicyRef != nil { + if len(def.Comment) > 0 || def.PlacementPolicyRef != nil { defaultPartitionDefinitions = false break } @@ -1304,10 +1368,6 @@ func appendPartitionInfo(partitionInfo *model.PartitionInfo, buf *bytes.Buffer, if len(def.Comment) > 0 { buf.WriteString(fmt.Sprintf(" COMMENT '%s'", format.OutputFormat(def.Comment))) } - if def.DirectPlacementOpts != nil { - // add direct placement info here - appendDirectPlacementInfo(def.DirectPlacementOpts, buf) - } if def.PlacementPolicyRef != nil { // add placement ref info here fmt.Fprintf(buf, " /*T![placement] PLACEMENT POLICY=%s */", stringutil.Escape(def.PlacementPolicyRef.Name.O, sqlMode)) @@ -1351,13 +1411,14 @@ func ConstructResultOfShowCreateDatabase(ctx sessionctx.Context, dbInfo *model.D // add placement ref info here fmt.Fprintf(buf, " /*T![placement] PLACEMENT POLICY=%s */", stringutil.Escape(dbInfo.PlacementPolicyRef.Name.O, sqlMode)) } - if dbInfo.DirectPlacementOpts != nil { - // add direct placement info here - appendDirectPlacementInfo(dbInfo.DirectPlacementOpts, buf) - } return nil } +// ConstructResultOfShowCreatePlacementPolicy constructs the result for show create placement policy. +func ConstructResultOfShowCreatePlacementPolicy(policyInfo *model.PolicyInfo) string { + return fmt.Sprintf("CREATE PLACEMENT POLICY `%s` %s", policyInfo.Name.O, policyInfo.PlacementSettings.String()) +} + // fetchShowCreateDatabase composes show create database result. func (e *ShowExec) fetchShowCreateDatabase() error { checker := privilege.GetPrivilegeManager(e.ctx) @@ -1386,7 +1447,7 @@ func (e *ShowExec) fetchShowCreatePlacementPolicy() error { if !found { return infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs(e.DBName.O) } - showCreate := fmt.Sprintf("CREATE PLACEMENT POLICY `%s` %s", e.DBName.O, policy.PlacementSettings.String()) + showCreate := ConstructResultOfShowCreatePlacementPolicy(policy) e.appendRow([]interface{}{e.DBName.O, showCreate}) return nil } @@ -1433,11 +1494,7 @@ func (e *ShowExec) fetchShowCreateUser(ctx context.Context) error { exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, `SELECT plugin FROM %n.%n WHERE User=%? AND Host=%?`, mysql.SystemDB, mysql.UserTable, userName, strings.ToLower(hostName)) - if err != nil { - return errors.Trace(err) - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, `SELECT plugin FROM %n.%n WHERE User=%? AND Host=%?`, mysql.SystemDB, mysql.UserTable, userName, strings.ToLower(hostName)) if err != nil { return errors.Trace(err) } @@ -1453,11 +1510,7 @@ func (e *ShowExec) fetchShowCreateUser(ctx context.Context) error { authplugin = rows[0].GetString(0) } - stmt, err = exec.ParseWithParams(ctx, `SELECT Priv FROM %n.%n WHERE User=%? AND Host=%?`, mysql.SystemDB, mysql.GlobalPrivTable, userName, hostName) - if err != nil { - return errors.Trace(err) - } - rows, _, err = exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err = exec.ExecRestrictedSQL(ctx, nil, `SELECT Priv FROM %n.%n WHERE User=%? AND Host=%?`, mysql.SystemDB, mysql.GlobalPrivTable, userName, hostName) if err != nil { return errors.Trace(err) } @@ -1624,7 +1677,7 @@ func (e *ShowExec) fetchShowPumpOrDrainerStatus(kind string) error { if n.State == node.Offline { continue } - e.appendRow([]interface{}{n.NodeID, n.Addr, n.State, n.MaxCommitTS, utils.TSOToRoughTime(n.UpdateTS).Format(types.TimeFormat)}) + e.appendRow([]interface{}{n.NodeID, n.Addr, n.State, n.MaxCommitTS, util.TSOToRoughTime(n.UpdateTS).Format(types.TimeFormat)}) } return nil @@ -1632,7 +1685,7 @@ func (e *ShowExec) fetchShowPumpOrDrainerStatus(kind string) error { // createRegistry returns an ectd registry func createRegistry(urls string) (*node.EtcdRegistry, error) { - ectdEndpoints, err := utils.ParseHostPortAddr(urls) + ectdEndpoints, err := util.ParseHostPortAddr(urls) if err != nil { return nil, errors.Trace(err) } diff --git a/executor/show_placement.go b/executor/show_placement.go index d77c0a31000f1..acd6d9cccecfc 100644 --- a/executor/show_placement.go +++ b/executor/show_placement.go @@ -107,12 +107,7 @@ func (b *showPlacementLabelsResultBuilder) sortMapKeys(m map[string]interface{}) func (e *ShowExec) fetchShowPlacementLabels(ctx context.Context) error { exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, "SELECT DISTINCT LABEL FROM %n.%n", "INFORMATION_SCHEMA", infoschema.TableTiKVStoreStatus) - if err != nil { - return errors.Trace(err) - } - - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, "SELECT DISTINCT LABEL FROM %n.%n", "INFORMATION_SCHEMA", infoschema.TableTiKVStoreStatus) if err != nil { return errors.Trace(err) } @@ -156,11 +151,11 @@ func (e *ShowExec) fetchShowPlacementForDB(ctx context.Context) (err error) { } if placement != nil { - schedule, err := fetchDBScheduled(ctx, nil, dbInfo) + state, err := fetchDBScheduleState(ctx, nil, dbInfo) if err != nil { return err } - e.appendRow([]interface{}{"DATABASE " + dbInfo.Name.String(), placement.String(), toScheduleStateString(schedule)}) + e.appendRow([]interface{}{"DATABASE " + dbInfo.Name.String(), placement.String(), state.String()}) } return nil @@ -179,12 +174,12 @@ func (e *ShowExec) fetchShowPlacementForTable(ctx context.Context) (err error) { } if placement != nil { - schedule, err := fetchTableScheduled(ctx, nil, tblInfo) + state, err := fetchTableScheduleState(ctx, nil, tblInfo) if err != nil { return err } ident := ast.Ident{Schema: e.Table.DBInfo.Name, Name: tblInfo.Name} - e.appendRow([]interface{}{"TABLE " + ident.String(), placement.String(), toScheduleStateString(schedule)}) + e.appendRow([]interface{}{"TABLE " + ident.String(), placement.String(), state.String()}) } return nil @@ -225,7 +220,7 @@ func (e *ShowExec) fetchShowPlacementForPartition(ctx context.Context) (err erro } if placement != nil { - schedule, err := fetchPartitionScheduled(ctx, nil, partition) + state, err := fetchPartitionScheduleState(ctx, nil, partition) if err != nil { return err } @@ -233,7 +228,7 @@ func (e *ShowExec) fetchShowPlacementForPartition(ctx context.Context) (err erro e.appendRow([]interface{}{ fmt.Sprintf("TABLE %s PARTITION %s", tableIndent.String(), partition.Name.String()), placement.String(), - toScheduleStateString(schedule), + state.String(), }) } @@ -245,7 +240,7 @@ func (e *ShowExec) fetchShowPlacement(ctx context.Context) error { return err } - scheduled := make(map[int64]bool) + scheduled := make(map[int64]infosync.PlacementScheduleState) if err := e.fetchAllDBPlacements(ctx, scheduled); err != nil { return err @@ -266,7 +261,7 @@ func (e *ShowExec) fetchAllPlacementPolicies() error { return nil } -func (e *ShowExec) fetchAllDBPlacements(ctx context.Context, scheduleState map[int64]bool) error { +func (e *ShowExec) fetchAllDBPlacements(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState) error { checker := privilege.GetPrivilegeManager(e.ctx) activeRoles := e.ctx.GetSessionVars().ActiveRoles @@ -284,18 +279,18 @@ func (e *ShowExec) fetchAllDBPlacements(ctx context.Context, scheduleState map[i } if placement != nil { - schedule, err := fetchDBScheduled(ctx, scheduleState, dbInfo) + state, err := fetchDBScheduleState(ctx, scheduleState, dbInfo) if err != nil { return err } - e.appendRow([]interface{}{"DATABASE " + dbInfo.Name.String(), placement.String(), toScheduleStateString(schedule)}) + e.appendRow([]interface{}{"DATABASE " + dbInfo.Name.String(), placement.String(), state.String()}) } } return nil } -func (e *ShowExec) fetchAllTablePlacements(ctx context.Context, scheduleState map[int64]bool) error { +func (e *ShowExec) fetchAllTablePlacements(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState) error { checker := privilege.GetPrivilegeManager(e.ctx) activeRoles := e.ctx.GetSessionVars().ActiveRoles @@ -322,11 +317,11 @@ func (e *ShowExec) fetchAllTablePlacements(ctx context.Context, scheduleState ma } if tblPlacement != nil { - schedule, err := fetchTableScheduled(ctx, scheduleState, tblInfo) + state, err := fetchTableScheduleState(ctx, scheduleState, tblInfo) if err != nil { return err } - rows = append(rows, []interface{}{"TABLE " + ident.String(), tblPlacement.String(), toScheduleStateString(schedule)}) + rows = append(rows, []interface{}{"TABLE " + ident.String(), tblPlacement.String(), state.String()}) } if tblInfo.Partition != nil { @@ -338,14 +333,14 @@ func (e *ShowExec) fetchAllTablePlacements(ctx context.Context, scheduleState ma } if partitionPlacement != nil { - schedule, err := fetchPartitionScheduled(ctx, scheduleState, &partition) + state, err := fetchPartitionScheduleState(ctx, scheduleState, &partition) if err != nil { return err } rows = append(rows, []interface{}{ fmt.Sprintf("TABLE %s PARTITION %s", ident.String(), partition.Name.String()), partitionPlacement.String(), - toScheduleStateString(schedule), + state.String(), }) } } @@ -374,29 +369,14 @@ func (e *ShowExec) fetchAllTablePlacements(ctx context.Context, scheduleState ma } func (e *ShowExec) getDBPlacement(dbInfo *model.DBInfo) (*model.PlacementSettings, error) { - placement := dbInfo.DirectPlacementOpts - if placement != nil { - return placement, nil - } - return e.getPolicyPlacement(dbInfo.PlacementPolicyRef) } func (e *ShowExec) getTablePlacement(tblInfo *model.TableInfo) (*model.PlacementSettings, error) { - placement := tblInfo.DirectPlacementOpts - if placement != nil { - return placement, nil - } - return e.getPolicyPlacement(tblInfo.PlacementPolicyRef) } func (e *ShowExec) getPartitionPlacement(tblPlacement *model.PlacementSettings, partition *model.PartitionDefinition) (*model.PlacementSettings, error) { - placement := partition.DirectPlacementOpts - if placement != nil { - return placement, nil - } - placement, err := e.getPolicyPlacement(partition.PlacementPolicyRef) if err != nil { return nil, err @@ -421,7 +401,7 @@ func (e *ShowExec) getPolicyPlacement(policyRef *model.PolicyRefInfo) (settings return policy.PlacementSettings, nil } -func fetchScheduled(ctx context.Context, scheduleState map[int64]bool, id int64) (bool, error) { +func fetchScheduleState(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState, id int64) (infosync.PlacementScheduleState, error) { if s, ok := scheduleState[id]; ok { return s, nil } @@ -434,26 +414,30 @@ func fetchScheduled(ctx context.Context, scheduleState map[int64]bool, id int64) return schedule, err } -func fetchPartitionScheduled(ctx context.Context, scheduleState map[int64]bool, part *model.PartitionDefinition) (bool, error) { - return fetchScheduled(ctx, scheduleState, part.ID) +func fetchPartitionScheduleState(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState, part *model.PartitionDefinition) (infosync.PlacementScheduleState, error) { + return fetchScheduleState(ctx, scheduleState, part.ID) } -func fetchTableScheduled(ctx context.Context, scheduleState map[int64]bool, table *model.TableInfo) (bool, error) { - schedule, err := fetchScheduled(ctx, scheduleState, table.ID) +func fetchTableScheduleState(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState, table *model.TableInfo) (infosync.PlacementScheduleState, error) { + state := infosync.PlacementScheduleStateScheduled + + schedule, err := fetchScheduleState(ctx, scheduleState, table.ID) if err != nil { - return false, err + return state, err } - if !schedule { - return false, nil + state = accumulateState(state, schedule) + if state != infosync.PlacementScheduleStateScheduled { + return state, nil } if table.GetPartitionInfo() != nil { for _, part := range table.GetPartitionInfo().Definitions { - schedule, err = fetchScheduled(ctx, scheduleState, part.ID) + schedule, err = fetchScheduleState(ctx, scheduleState, part.ID) if err != nil { - return false, err + return infosync.PlacementScheduleStatePending, err } - if !schedule { + state = accumulateState(state, schedule) + if state != infosync.PlacementScheduleStateScheduled { break } } @@ -462,26 +446,25 @@ func fetchTableScheduled(ctx context.Context, scheduleState map[int64]bool, tabl return schedule, nil } -func fetchDBScheduled(ctx context.Context, scheduleState map[int64]bool, db *model.DBInfo) (bool, error) { - schedule := true - - var err error +func fetchDBScheduleState(ctx context.Context, scheduleState map[int64]infosync.PlacementScheduleState, db *model.DBInfo) (infosync.PlacementScheduleState, error) { + state := infosync.PlacementScheduleStateScheduled for _, table := range db.Tables { - schedule, err = fetchTableScheduled(ctx, scheduleState, table) + schedule, err := fetchTableScheduleState(ctx, scheduleState, table) if err != nil { - return false, err + return state, err } - if !schedule { + state = accumulateState(state, schedule) + if state != infosync.PlacementScheduleStateScheduled { break } } - - return schedule, nil + return state, nil } -func toScheduleStateString(schedule bool) string { - if schedule { - return "SCHEDULED" +func accumulateState(curr, news infosync.PlacementScheduleState) infosync.PlacementScheduleState { + a, b := int(curr), int(news) + if a > b { + return news } - return "INPROGRESS" + return curr } diff --git a/executor/show_placement_labels_test.go b/executor/show_placement_labels_test.go index 3e3efcd865738..a6d17b6b5e203 100644 --- a/executor/show_placement_labels_test.go +++ b/executor/show_placement_labels_test.go @@ -16,18 +16,14 @@ package executor import ( gjson "encoding/json" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/types/json" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testShowPlacementLabelSuit{}) - -type testShowPlacementLabelSuit struct { -} - -func (s *testShowPlacementLabelSuit) TestShowPlacementLabelsBuilder(c *C) { +func TestShowPlacementLabelsBuilder(t *testing.T) { cases := []struct { stores [][]*helper.StoreLabel expects [][]interface{} @@ -57,9 +53,9 @@ func (s *testShowPlacementLabelSuit) TestShowPlacementLabelsBuilder(c *C) { b := &showPlacementLabelsResultBuilder{} toBinaryJSON := func(obj interface{}) (bj json.BinaryJSON) { d, err := gjson.Marshal(obj) - c.Assert(err, IsNil) + require.NoError(t, err) err = bj.UnmarshalJSON(d) - c.Assert(err, IsNil) + require.NoError(t, err) return } @@ -67,19 +63,19 @@ func (s *testShowPlacementLabelSuit) TestShowPlacementLabelsBuilder(c *C) { for _, store := range ca.stores { bj := toBinaryJSON(store) err := b.AppendStoreLabels(bj) - c.Assert(err, IsNil) + require.NoError(t, err) } rows, err := b.BuildRows() - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, len(ca.expects)) + require.NoError(t, err) + require.Equal(t, len(ca.expects), len(rows)) for idx, expect := range ca.expects { row := rows[idx] bj := toBinaryJSON(expect[1]) - c.Assert(row[0].(string), Equals, expect[0].(string)) - c.Assert(row[1].(json.BinaryJSON).TypeCode, Equals, bj.TypeCode) - c.Assert(row[1].(json.BinaryJSON).Value, BytesEquals, bj.Value) + require.Equal(t, expect[0].(string), row[0].(string)) + require.Equal(t, bj.TypeCode, row[1].(json.BinaryJSON).TypeCode) + require.Equal(t, bj.Value, row[1].(json.BinaryJSON).Value) } } } diff --git a/executor/show_placement_test.go b/executor/show_placement_test.go index f1e4b02c20dfe..61279c7adfc79 100644 --- a/executor/show_placement_test.go +++ b/executor/show_placement_test.go @@ -16,18 +16,21 @@ package executor_test import ( "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite5) TestShowPlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacement(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2, t3, t4, db2.t2") tk.MustExec("drop database if exists db2") tk.MustExec("drop database if exists db3") @@ -57,45 +60,37 @@ func (s *testSuite5) TestShowPlacement(c *C) { defer tk.MustExec("drop placement policy pb1") // prepare database - tk.MustExec("create database db3 LEADER_CONSTRAINTS=\"[+region=hz]\" FOLLOWERS=3") - defer tk.MustExec("drop database if exists db3") - tk.MustExec("create database db2 PLACEMENT POLICY pa2") defer tk.MustExec("drop database if exists db2") // prepare tables - tk.MustExec("create table t2 (id int) LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2") - defer tk.MustExec("drop table if exists t2") - tk.MustExec("create table t1 (id int) placement policy pa1") defer tk.MustExec("drop table if exists t1") - tk.MustExec("create table t3 (id int)") - defer tk.MustExec("drop table if exists t3") + tk.MustExec("create table t2 (id int)") + defer tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t4 (id INT) placement policy pa1 PARTITION BY RANGE (id) (" + + tk.MustExec("CREATE TABLE t3 (id INT) placement policy pa1 PARTITION BY RANGE (id) (" + "PARTITION p0 VALUES LESS THAN (100) placement policy pa2," + - "PARTITION p1 VALUES LESS THAN (1000) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWER_CONSTRAINTS=\"[+region=sh]\" FOLLOWERS=4," + + "PARTITION p1 VALUES LESS THAN (1000)," + "PARTITION p2 VALUES LESS THAN (10000)" + ")") - defer tk.MustExec("drop table if exists t4") + defer tk.MustExec("drop table if exists t3") - tk.MustExec("create table db2.t2 (id int) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2") + tk.MustExec("create table db2.t2 (id int) PLACEMENT POLICY pa2") defer tk.MustExec("drop table if exists db2.t2") tk.MustQuery("show placement").Check(testkit.Rows( "POLICY pa1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" NULL", "POLICY pa2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" NULL", "POLICY pb1 CONSTRAINTS=\"[+disk=ssd]\" VOTERS=5 VOTER_CONSTRAINTS=\"[+region=bj]\" LEARNERS=3 LEARNER_CONSTRAINTS=\"[+region=sh]\" NULL", - "DATABASE db2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" INPROGRESS", - "DATABASE db3 LEADER_CONSTRAINTS=\"[+region=hz]\" FOLLOWERS=3 SCHEDULED", - "TABLE db2.t2 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2 INPROGRESS", - "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE test.t2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 INPROGRESS", - "TABLE test.t4 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE test.t4 PARTITION p0 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" INPROGRESS", - "TABLE test.t4 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" INPROGRESS", - "TABLE test.t4 PARTITION p2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", + "DATABASE db2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" PENDING", + "TABLE db2.t2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" PENDING", + "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t3 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t3 PARTITION p0 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=3 FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" PENDING", + "TABLE test.t3 PARTITION p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t3 PARTITION p2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", )) tk.MustQuery("show placement like 'POLICY%'").Check(testkit.Rows( @@ -114,8 +109,10 @@ func (s *testSuite5) TestShowPlacement(c *C) { )) } -func (s *testSuite5) TestShowPlacementPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacementPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2,t3, db2.t1, db2.t3") tk.MustExec("drop database if exists db2") @@ -135,7 +132,7 @@ func (s *testSuite5) TestShowPlacementPrivilege(c *C) { defer tk.MustExec("drop placement policy p1") // prepare database - tk.MustExec("create database db3 LEADER_CONSTRAINTS=\"[+region=hz]\" FOLLOWERS=3") + tk.MustExec("create database db3 PLACEMENT POLICY p1") defer tk.MustExec("drop database if exists db3") tk.MustExec("create database db2 PLACEMENT POLICY p1") @@ -144,22 +141,19 @@ func (s *testSuite5) TestShowPlacementPrivilege(c *C) { // prepare tables tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") - tk.MustExec("create table t2 (id int) LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2") + tk.MustExec("create table t2 (id int) PLACEMENT POLICY p1") defer tk.MustExec("drop table if exists t2") tk.MustExec("CREATE TABLE t3 (id INT) PARTITION BY RANGE (id) (" + - "PARTITION p1 VALUES LESS THAN (100) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWER_CONSTRAINTS=\"[+region=sh]\" FOLLOWERS=4" + + "PARTITION p1 VALUES LESS THAN (100) PLACEMENT POLICY p1" + ")") defer tk.MustExec("drop table if exists t3") - tk.MustExec("create table db2.t1 (id int) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2") + tk.MustExec("create table db2.t1 (id int) PLACEMENT POLICY p1") defer tk.MustExec("drop table if exists db2.t1") - tk.MustExec("create table db2.t3 (id int) LEADER_CONSTRAINTS=\"[+region=gz]\" FOLLOWERS=2") + tk.MustExec("create table db2.t3 (id int) PLACEMENT POLICY p1") defer tk.MustExec("drop table if exists db2.t3") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) // before grant tk1.MustQuery("show placement").Check(testkit.Rows( @@ -174,16 +168,19 @@ func (s *testSuite5) TestShowPlacementPrivilege(c *C) { // after grant tk1.MustQuery("show placement").Check(testkit.Rows( "POLICY p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" NULL", - "DATABASE db2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE db2.t1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2 INPROGRESS", - "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE test.t3 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" INPROGRESS", + "DATABASE db2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE db2.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t3 PARTITION p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", )) } -func (s *testSuite5) TestShowPlacementForDB(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacementForDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop database if exists db2") tk.MustExec("drop placement policy if exists p1") @@ -193,28 +190,25 @@ func (s *testSuite5) TestShowPlacementForDB(c *C) { "SCHEDULE=\"EVEN\"") defer tk.MustExec("drop placement policy p1") - tk.MustExec("create database db3 LEADER_CONSTRAINTS=\"[+region=hz]\" FOLLOWERS=3") - defer tk.MustExec("drop database if exists db3") - tk.MustExec("create database db2 placement policy p1") defer tk.MustExec("drop database if exists db2") err := tk.QueryToErr("show placement for database dbnoexist") - c.Assert(err.Error(), Equals, "[schema:1049]Unknown database 'dbnoexist'") + require.EqualError(t, err, "[schema:1049]Unknown database 'dbnoexist'") tk.MustQuery("show placement for database test").Check(testkit.Rows()) tk.MustQuery("show placement for database db2").Check(testkit.Rows( "DATABASE db2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" SCHEDULED", )) - tk.MustQuery("show placement for database db3").Check(testkit.Rows( - "DATABASE db3 LEADER_CONSTRAINTS=\"[+region=hz]\" FOLLOWERS=3 SCHEDULED", - )) } -func (s *testSuite5) TestShowPlacementForTableAndPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacementForTableAndPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") tk.MustExec("drop table if exists t1,t2,t3,t4,db2.t1") tk.MustExec("drop database if exists db2") @@ -224,18 +218,14 @@ func (s *testSuite5) TestShowPlacementForTableAndPartition(c *C) { "SCHEDULE=\"EVEN\"") defer tk.MustExec("drop placement policy p1") + tk.MustExec("create placement policy p2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2") + defer tk.MustExec("drop placement policy p2") + // table ref a policy tk.MustExec("create table t1 (id int) placement policy p1") defer tk.MustExec("drop table if exists t1") tk.MustQuery("show placement for table t1").Check(testkit.Rows( - "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - )) - - // table direct setting - tk.MustExec("create table t2 (id int) LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2") - defer tk.MustExec("drop table if exists t2") - tk.MustQuery("show placement for table t2").Check(testkit.Rows( - "TABLE test.t2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 INPROGRESS", + "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", )) // table no placement @@ -244,27 +234,24 @@ func (s *testSuite5) TestShowPlacementForTableAndPartition(c *C) { tk.MustQuery("show placement for table t3").Check(testkit.Rows()) // table do not display partition placement - tk.MustExec("create table t4 (id int) LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 PARTITION BY RANGE (id) (" + - "PARTITION p0 VALUES LESS THAN (100), " + - "PARTITION p1 VALUES LESS THAN (1000) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWER_CONSTRAINTS=\"[+region=sh]\" FOLLOWERS=4," + + tk.MustExec("create table t4 (id int) PLACEMENT POLICY p2 PARTITION BY RANGE (id) (" + + "PARTITION p0 VALUES LESS THAN (100)," + + "PARTITION p1 VALUES LESS THAN (1000)," + "PARTITION p2 VALUES LESS THAN (10000) PLACEMENT POLICY p1" + ")") defer tk.MustExec("drop table if exists t4") tk.MustQuery("show placement for table t4").Check(testkit.Rows( - "TABLE test.t4 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 INPROGRESS", + "TABLE test.t4 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 PENDING", )) // partition inherent table tk.MustQuery("show placement for table t4 partition p0").Check(testkit.Rows( - "TABLE test.t4 PARTITION p0 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 INPROGRESS", + "TABLE test.t4 PARTITION p0 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 PENDING", )) // partition custom placement - tk.MustQuery("show placement for table t4 partition p1").Check(testkit.Rows( - "TABLE test.t4 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" INPROGRESS", - )) tk.MustQuery("show placement for table t4 partition p2").Check(testkit.Rows( - "TABLE test.t4 PARTITION p2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", + "TABLE test.t4 PARTITION p2 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", )) // partition without placement @@ -276,49 +263,57 @@ func (s *testSuite5) TestShowPlacementForTableAndPartition(c *C) { // table name with format db.table tk.MustExec("create database db2") defer tk.MustExec("drop database if exists db2") - tk.MustExec("create table db2.t1 (id int) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2") + tk.MustExec("create table db2.t1 (id int) PLACEMENT POLICY p2") defer tk.MustExec("drop table if exists db2.t1") tk.MustQuery("show placement for table db2.t1").Check(testkit.Rows( - "TABLE db2.t1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2 INPROGRESS", + "TABLE db2.t1 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2 PENDING", )) // not exists err := tk.ExecToErr("show placement for table tn") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.tn' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.tn' doesn't exist") err = tk.ExecToErr("show placement for table dbn.t1") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'dbn.t1' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'dbn.t1' doesn't exist") err = tk.ExecToErr("show placement for table tn partition pn") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.tn' doesn't exist") + require.EqualError(t, err, "[schema:1146]Table 'test.tn' doesn't exist") err = tk.QueryToErr("show placement for table t1 partition pn") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'pn' in table 't1'") + require.EqualError(t, err, "[table:1735]Unknown partition 'pn' in table 't1'") err = tk.QueryToErr("show placement for table t4 partition pn") - c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'pn' in table 't4'") + require.EqualError(t, err, "[table:1735]Unknown partition 'pn' in table 't4'") } -func (s *testSuite5) TestShowPlacementForDBPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacementForDBPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("drop table if exists db2.t1") tk.MustExec("drop database if exists db2") tk.MustExec("drop user if exists user1") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") + + // prepare policy + tk.MustExec("create placement policy p1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\"") + defer tk.MustExec("drop placement policy if exists p1") + tk.MustExec("create placement policy p2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\"") + defer tk.MustExec("drop placement policy if exists p2") // prepare user tk.MustExec("create user user1") defer tk.MustExec("drop user user1") // prepare database - tk.MustExec("create database db2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\"") + tk.MustExec("create database db2 PLACEMENT POLICY p1") defer tk.MustExec("drop database db2") // prepare table - tk.MustExec("create table db2.t1 (id int) PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\"") + tk.MustExec("create table db2.t1 (id int) PLACEMENT POLICY p2") defer tk.MustExec("drop table db2.t1") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) privs := []string{ "all privileges on db2.*", @@ -332,42 +327,53 @@ func (s *testSuite5) TestShowPlacementForDBPrivilege(c *C) { } // before grant - err = tk1.QueryToErr("show placement for database db2") - c.Assert(err.Error(), Equals, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "db2").Error()) + err := tk1.QueryToErr("show placement for database db2") + require.EqualError(t, err, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "db2").Error()) - tk1.MustQuery("show placement").Check(testkit.Rows()) + tk1.MustQuery("show placement").Check(testkit.Rows( + "POLICY p1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" NULL", + "POLICY p2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\" NULL", + )) for _, priv := range privs { // do grant tk.MustExec(fmt.Sprintf("grant %s to 'user1'@'%%'", priv)) tk1.MustQuery("show placement for database db2").Check(testkit.Rows( - "DATABASE db2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" INPROGRESS", + "DATABASE db2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" PENDING", )) tk1.MustQuery("show placement").Check(testkit.Rows( - "DATABASE db2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE db2.t1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\" INPROGRESS", + "POLICY p1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" NULL", + "POLICY p2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\" NULL", + "DATABASE db2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE db2.t1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\" PENDING", )) err = tk1.QueryToErr("show placement for database test") - c.Assert(err.Error(), Equals, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "test").Error()) + require.EqualError(t, err, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "test").Error()) // do revoke tk.MustExec(fmt.Sprintf("revoke %s from 'user1'@'%%'", priv)) err = tk1.QueryToErr("show placement for database db2") - c.Assert(err.Error(), Equals, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "db2").Error()) + require.EqualError(t, err, executor.ErrDBaccessDenied.GenWithStackByArgs("user1", "%", "db2").Error()) - tk1.MustQuery("show placement").Check(testkit.Rows()) + tk1.MustQuery("show placement").Check(testkit.Rows( + "POLICY p1 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r2\" SCHEDULE=\"EVEN\" NULL", + "POLICY p2 PRIMARY_REGION=\"r1\" REGIONS=\"r1,r3\" SCHEDULE=\"EVEN\" NULL", + )) } } -func (s *testSuite5) TestShowPlacementForTableAndPartitionPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPlacementForTableAndPartitionPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop placement policy if exists p1") tk.MustExec("drop table if exists t1,t2,t3,t4,db2.t1") tk.MustExec("drop database if exists db2") tk.MustExec("drop user if exists user1") + tk.MustExec("drop placement policy if exists p1") + tk.MustExec("drop placement policy if exists p2") // prepare user tk.MustExec("create user user1") @@ -384,42 +390,43 @@ func (s *testSuite5) TestShowPlacementForTableAndPartitionPrivilege(c *C) { "SCHEDULE=\"EVEN\"") defer tk.MustExec("drop placement policy p1") + tk.MustExec("create placement policy p2 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWER_CONSTRAINTS=\"[+region=sh]\" FOLLOWERS=4") + defer tk.MustExec("drop placement policy p2") + // prepare tables tk.MustExec("create table t1 (id int) placement policy p1 PARTITION BY RANGE (id) (" + - "PARTITION p1 VALUES LESS THAN (1000) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWER_CONSTRAINTS=\"[+region=sh]\" FOLLOWERS=4" + + "PARTITION p1 VALUES LESS THAN (1000) PLACEMENT POLICY p2" + ")") defer tk.MustExec("drop table if exists t1") - tk.MustExec("create table t2 (id int) LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWERS=2") + tk.MustExec("create table t2 (id int) PLACEMENT POLICY p2") defer tk.MustExec("drop table if exists t2") tk.MustExec("create table t3 (id int)") defer tk.MustExec("drop table if exists t3") - tk.MustExec("create table db2.t1 (id int) LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=2") + tk.MustExec("create table db2.t1 (id int) PLACEMENT POLICY p2") defer tk.MustExec("drop table if exists db2.t1") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) // before grant - err = tk1.ExecToErr("show placement for table test.t1") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) + err := tk1.ExecToErr("show placement for table test.t1") + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) err = tk1.ExecToErr("show placement for table test.t1 partition p1") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) err = tk1.ExecToErr("show placement for table test.t2") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t2").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t2").Error()) err = tk1.ExecToErr("show placement for table test.t3") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t3").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t3").Error()) err = tk1.ExecToErr("show placement for table db2.t1") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) tk1.MustQuery("show placement").Check(testkit.Rows( "POLICY p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" NULL", + "POLICY p2 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" NULL", )) privs := []string{ @@ -437,34 +444,36 @@ func (s *testSuite5) TestShowPlacementForTableAndPartitionPrivilege(c *C) { tk.MustExec(fmt.Sprintf("grant %s to 'user1'@'%%'", priv)) tk1.MustQuery("show placement").Check(testkit.Rows( "POLICY p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" NULL", - "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", - "TABLE test.t1 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" INPROGRESS", + "POLICY p2 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" NULL", + "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", + "TABLE test.t1 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" PENDING", )) tk1.MustQuery("show placement for table test.t1").Check(testkit.Rows( - "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" INPROGRESS", + "TABLE test.t1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" PENDING", )) tk1.MustQuery("show placement for table test.t1 partition p1").Check(testkit.Rows( - "TABLE test.t1 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" INPROGRESS", + "TABLE test.t1 PARTITION p1 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" PENDING", )) err = tk1.ExecToErr("show placement for table test.t2") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t2").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t2").Error()) err = tk1.ExecToErr("show placement for table test.t3") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t3").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t3").Error()) err = tk1.ExecToErr("show placement for table db2.t1") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) // do revoke tk.MustExec(fmt.Sprintf("revoke %s from 'user1'@'%%'", priv)) err = tk1.ExecToErr("show placement for table test.t1") - c.Assert(err.Error(), Equals, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) + require.EqualError(t, err, core.ErrTableaccessDenied.GenWithStackByArgs("SHOW", "user1", "%", "t1").Error()) tk1.MustQuery("show placement").Check(testkit.Rows( "POLICY p1 PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1,cn-east-2\" SCHEDULE=\"EVEN\" NULL", + "POLICY p2 LEADER_CONSTRAINTS=\"[+region=bj]\" FOLLOWERS=4 FOLLOWER_CONSTRAINTS=\"[+region=sh]\" NULL", )) } } diff --git a/executor/show_stats.go b/executor/show_stats.go index 6cfdbc70daa8c..7104372496c25 100644 --- a/executor/show_stats.go +++ b/executor/show_stats.go @@ -447,19 +447,23 @@ func (e *ShowExec) fetchShowHistogramsInFlight() { e.appendRow([]interface{}{statistics.HistogramNeededColumns.Length()}) } -func (e *ShowExec) fetchShowAnalyzeStatus() { - rows := dataForAnalyzeStatusHelper(e.baseExecutor.ctx) +func (e *ShowExec) fetchShowAnalyzeStatus() error { + rows, err := dataForAnalyzeStatusHelper(e.baseExecutor.ctx) + if err != nil { + return err + } for _, row := range rows { for i := range row { e.result.AppendDatum(i, &row[i]) } } + return nil } func (e *ShowExec) fetchShowColumnStatsUsage() error { do := domain.GetDomain(e.ctx) h := do.StatsHandle() - colStatsMap, err := h.LoadColumnStatsUsage() + colStatsMap, err := h.LoadColumnStatsUsage(e.ctx.GetSessionVars().Location()) if err != nil { return err } @@ -500,9 +504,10 @@ func (e *ShowExec) fetchShowColumnStatsUsage() error { for _, db := range dbs { for _, tbl := range db.Tables { pi := tbl.GetPartitionInfo() - if pi == nil || e.ctx.GetSessionVars().UseDynamicPartitionPrune() { - appendTableForColumnStatsUsage(db.Name.O, tbl, pi != nil, nil) - } + // Though partition tables in static pruning mode don't have global stats, we dump predicate columns of partitions with table ID + // rather than partition ID. Hence appendTableForColumnStatsUsage needs to be called for both partition and global in both dynamic + // and static pruning mode. + appendTableForColumnStatsUsage(db.Name.O, tbl, pi != nil, nil) if pi != nil { for i := range pi.Definitions { appendTableForColumnStatsUsage(db.Name.O, tbl, false, &pi.Definitions[i]) diff --git a/executor/show_stats_test.go b/executor/show_stats_test.go index f48fe9988649d..38ac3d46303c1 100644 --- a/executor/show_stats_test.go +++ b/executor/show_stats_test.go @@ -19,10 +19,9 @@ import ( "testing" "time" - "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" ) @@ -311,7 +310,7 @@ func TestShowStatsExtended(t *testing.T) { } func TestShowColumnStatsUsage(t *testing.T) { - store, clean := testkit.CreateMockStore(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -320,7 +319,6 @@ func TestShowColumnStatsUsage(t *testing.T) { tk.MustExec("create table t1 (a int, b int, index idx_a_b(a, b))") tk.MustExec("create table t2 (a int, b int) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than maxvalue)") - dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() t1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) require.NoError(t, err) @@ -352,7 +350,7 @@ func TestShowHistogramsInFlight(t *testing.T) { tk.MustExec("use test") result := tk.MustQuery("show histograms_in_flight") rows := result.Rows() - require.Equal(t, len(rows), 1) + require.Len(t, rows, 1) require.Equal(t, rows[0][0], "0") } @@ -361,7 +359,7 @@ func TestShowAnalyzeStatus(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - statistics.ClearHistoryJobs() + tk.MustExec("delete from mysql.analyze_jobs") tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, primary key(a), index idx(b))") @@ -369,39 +367,54 @@ func TestShowAnalyzeStatus(t *testing.T) { tk.MustExec("set @@tidb_analyze_version=2") tk.MustExec("analyze table t") - result := tk.MustQuery("show analyze status").Sort() - require.Len(t, result.Rows(), 1) - require.Equal(t, "test", result.Rows()[0][0]) - require.Equal(t, "t", result.Rows()[0][1]) - require.Equal(t, "", result.Rows()[0][2]) - require.Equal(t, "analyze table", result.Rows()[0][3]) - require.Equal(t, "2", result.Rows()[0][4]) - require.NotNil(t, result.Rows()[0][5]) - require.NotNil(t, result.Rows()[0][6]) - require.Equal(t, "finished", result.Rows()[0][7]) - - statistics.ClearHistoryJobs() + rows := tk.MustQuery("show analyze status").Rows() + require.Len(t, rows, 1) + require.Equal(t, "test", rows[0][0]) + require.Equal(t, "t", rows[0][1]) + require.Equal(t, "", rows[0][2]) + require.Equal(t, "analyze table all columns with 256 buckets, 500 topn, 1 samplerate", rows[0][3]) + require.Equal(t, "2", rows[0][4]) + checkTime := func(val interface{}) { + str, ok := val.(string) + require.True(t, ok) + _, err := time.Parse("2006-01-02 15:04:05", str) + require.NoError(t, err) + } + checkTime(rows[0][5]) + checkTime(rows[0][6]) + require.Equal(t, "finished", rows[0][7]) + require.Equal(t, "", rows[0][8]) + serverInfo, err := infosync.GetServerInfo() + require.NoError(t, err) + addr := fmt.Sprintf("%s:%d", serverInfo.IP, serverInfo.Port) + require.Equal(t, addr, rows[0][9]) + require.Equal(t, "", rows[0][10]) + tk.MustExec("delete from mysql.analyze_jobs") tk.MustExec("set @@tidb_analyze_version=1") tk.MustExec("analyze table t") - result = tk.MustQuery("show analyze status").Sort() - require.Len(t, result.Rows(), 2) - require.Equal(t, "test", result.Rows()[0][0]) - require.Equal(t, "t", result.Rows()[0][1]) - require.Equal(t, "", result.Rows()[0][2]) - require.Equal(t, "analyze columns", result.Rows()[0][3]) - require.Equal(t, "2", result.Rows()[0][4]) - require.NotNil(t, result.Rows()[0][5]) - require.NotNil(t, result.Rows()[0][6]) - require.Equal(t, "finished", result.Rows()[0][7]) - - require.Len(t, result.Rows(), 2) - require.Equal(t, "test", result.Rows()[1][0]) - require.Equal(t, "t", result.Rows()[1][1]) - require.Equal(t, "", result.Rows()[1][2]) - require.Equal(t, "analyze index idx", result.Rows()[1][3]) - require.Equal(t, "2", result.Rows()[1][4]) - require.NotNil(t, result.Rows()[1][5]) - require.NotNil(t, result.Rows()[1][6]) - require.Equal(t, "finished", result.Rows()[1][7]) + rows = tk.MustQuery("show analyze status").Sort().Rows() + require.Len(t, rows, 2) + require.Equal(t, "test", rows[0][0]) + require.Equal(t, "t", rows[0][1]) + require.Equal(t, "", rows[0][2]) + require.Equal(t, "analyze columns", rows[0][3]) + require.Equal(t, "2", rows[0][4]) + checkTime(rows[0][5]) + checkTime(rows[0][6]) + require.Equal(t, "finished", rows[0][7]) + require.Equal(t, "test", rows[1][0]) + require.Equal(t, "", rows[0][8]) + require.Equal(t, addr, rows[0][9]) + require.Equal(t, "", rows[0][10]) + require.Equal(t, "t", rows[1][1]) + require.Equal(t, "", rows[1][2]) + require.Equal(t, "analyze index idx", rows[1][3]) + require.Equal(t, "2", rows[1][4]) + checkTime(rows[1][5]) + checkTime(rows[1][6]) + require.Equal(t, "finished", rows[1][7]) + require.Equal(t, "", rows[1][8]) + require.Equal(t, addr, rows[1][9]) + require.Equal(t, "", rows[1][10]) } diff --git a/executor/show_test.go b/executor/show_test.go index 34db4d54ae962..2e6f69688b09f 100644 --- a/executor/show_test.go +++ b/executor/show_test.go @@ -18,11 +18,9 @@ import ( "context" "fmt" "strings" + "testing" - "github.com/pingcap/check" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/auth" @@ -32,26 +30,24 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/privilege/privileges" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -func (s *testSuite5) TestShowVisibility(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowVisibility(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database showdatabase") tk.MustExec("use showdatabase") tk.MustExec("create table t1 (id int)") tk.MustExec("create table t2 (id int)") tk.MustExec(`create user 'show'@'%'`) - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil)) // No ShowDatabases privilege, this user would see nothing except INFORMATION_SCHEMA. tk.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA")) @@ -71,14 +67,16 @@ func (s *testSuite5) TestShowVisibility(c *C) { // Grant any global privilege would make show databases available. tk.MustExec(`grant CREATE on *.* to 'show'@'%'`) rows := tk1.MustQuery("show databases").Rows() - c.Assert(len(rows), GreaterEqual, 2) // At least INFORMATION_SCHEMA and showdatabase + require.GreaterOrEqual(t, len(rows), 2) tk.MustExec(`drop user 'show'@'%'`) tk.MustExec("drop database showdatabase") } -func (s *testSuite5) TestShowDatabasesInfoSchemaFirst(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowDatabasesInfoSchemaFirst(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA")) tk.MustExec(`create user 'show'@'%'`) @@ -87,11 +85,8 @@ func (s *testSuite5) TestShowDatabasesInfoSchemaFirst(c *C) { tk.MustExec(`grant select on AAAA.* to 'show'@'%'`) tk.MustExec(`grant select on BBBB.* to 'show'@'%'`) - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil)) tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "AAAA", "BBBB")) tk.MustExec(`drop user 'show'@'%'`) @@ -99,41 +94,45 @@ func (s *testSuite5) TestShowDatabasesInfoSchemaFirst(c *C) { tk.MustExec(`drop database BBBB`) } -func (s *testSuite5) TestShowWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowWarnings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") testSQL := `create table if not exists show_warnings (a int)` tk.MustExec(testSQL) tk.MustExec("set @@sql_mode=''") tk.MustExec("insert show_warnings values ('a')") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: 'a'")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: 'a'")) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: 'a'")) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: 'a'")) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) // Test Warning level 'Error' testSQL = `create table show_warnings (a int)` _, _ = tk.Exec(testSQL) // FIXME: Table 'test.show_warnings' already exists - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Error|1050|Table 'test.show_warnings' already exists")) - tk.MustQuery("select @@error_count").Check(testutil.RowsWithSep("|", "1")) + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Error|1050|Table 'test.show_warnings' already exists")) + tk.MustQuery("select @@error_count").Check(testkit.RowsWithSep("|", "1")) // Test Warning level 'Note' testSQL = `create table show_warnings_2 (a int)` tk.MustExec(testSQL) testSQL = `create table if not exists show_warnings_2 like show_warnings` _, err := tk.Exec(testSQL) - c.Assert(err, IsNil) - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1050|Table 'test.show_warnings_2' already exists")) - tk.MustQuery("select @@warning_count").Check(testutil.RowsWithSep("|", "1")) - tk.MustQuery("select @@warning_count").Check(testutil.RowsWithSep("|", "0")) + require.NoError(t, err) + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|1050|Table 'test.show_warnings_2' already exists")) + tk.MustQuery("select @@warning_count").Check(testkit.RowsWithSep("|", "1")) + tk.MustQuery("select @@warning_count").Check(testkit.RowsWithSep("|", "0")) } -func (s *testSuite5) TestShowErrors(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowErrors(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") testSQL := `create table if not exists show_errors (a int)` tk.MustExec(testSQL) @@ -141,20 +140,22 @@ func (s *testSuite5) TestShowErrors(c *C) { // FIXME: 'test.show_errors' already exists _, _ = tk.Exec(testSQL) - tk.MustQuery("show errors").Check(testutil.RowsWithSep("|", "Error|1050|Table 'test.show_errors' already exists")) + tk.MustQuery("show errors").Check(testkit.RowsWithSep("|", "Error|1050|Table 'test.show_errors' already exists")) } -func (s *testSuite5) TestShowWarningsForExprPushdown(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowWarningsForExprPushdown(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") testSQL := `create table if not exists show_warnings_expr_pushdown (a int, value date)` tk.MustExec(testSQL) // create tiflash replica { - is := domain.GetDomain(tk.Se).InfoSchema() + is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "show_warnings_expr_pushdown" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -166,57 +167,53 @@ func (s *testSuite5) TestShowWarningsForExprPushdown(c *C) { } tk.MustExec("set tidb_allow_mpp=0") tk.MustExec("explain select * from show_warnings_expr_pushdown t where md5(value) = '2020-01-01'") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.")) + require.Equal(t, uint16(1), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.")) tk.MustExec("explain select max(md5(value)) from show_warnings_expr_pushdown group by a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.", "Warning|1105|Aggregation can not be pushed to tiflash because arguments of AggFunc `max` contains unsupported exprs")) + require.Equal(t, uint16(2), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.", "Warning|1105|Aggregation can not be pushed to tiflash because arguments of AggFunc `max` contains unsupported exprs")) tk.MustExec("explain select max(a) from show_warnings_expr_pushdown group by md5(value)") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2)) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.", "Warning|1105|Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs")) + require.Equal(t, uint16(2), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1105|Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.", "Warning|1105|Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs")) tk.MustExec("set tidb_opt_distinct_agg_push_down=0") tk.MustExec("explain select max(distinct a) from show_warnings_expr_pushdown group by value") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0)) - // tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Aggregation can not be pushed to storage layer in non-mpp mode because it contains agg function with distinct")) + require.Equal(t, uint16(0), tk.Session().GetSessionVars().StmtCtx.WarningCount()) + // tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1105|Aggregation can not be pushed to storage layer in non-mpp mode because it contains agg function with distinct")) } -func (s *testSuite5) TestShowGrantsPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowGrantsPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user show_grants") tk.MustExec("show grants for show_grants") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se - err = tk1.QueryToErr("show grants for root") - c.Assert(err.Error(), Equals, executor.ErrDBaccessDenied.GenWithStackByArgs("show_grants", "%", mysql.SystemDB).Error()) + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "%"}, nil, nil)) + err := tk1.QueryToErr("show grants for root") + require.EqualError(t, executor.ErrDBaccessDenied.GenWithStackByArgs("show_grants", "%", mysql.SystemDB), err.Error()) // Test show grants for user with auth host name `%`. - tk2 := testkit.NewTestKit(c, s.store) - se2, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se2.Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "127.0.0.1", AuthUsername: "show_grants", AuthHostname: "%"}, nil, nil), IsTrue) - tk2.Se = se2 + tk2 := testkit.NewTestKit(t, store) + require.True(t, tk2.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "127.0.0.1", AuthUsername: "show_grants", AuthHostname: "%"}, nil, nil)) tk2.MustQuery("show grants") } -func (s *testSuite5) TestShowStatsPrivilege(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowStatsPrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user show_stats") - tk1 := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "show_stats", Hostname: "%"}, nil, nil), IsTrue) - tk1.Se = se + tk1 := testkit.NewTestKit(t, store) + + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_stats", Hostname: "%"}, nil, nil)) eqErr := plannercore.ErrDBaccessDenied.GenWithStackByArgs("show_stats", "%", mysql.SystemDB) - _, err = tk1.Exec("show stats_meta") - c.Assert(err.Error(), Equals, eqErr.Error()) + _, err := tk1.Exec("show stats_meta") + require.EqualError(t, err, eqErr.Error()) _, err = tk1.Exec("SHOW STATS_BUCKETS") - c.Assert(err.Error(), Equals, eqErr.Error()) + require.EqualError(t, err, eqErr.Error()) _, err = tk1.Exec("SHOW STATS_HEALTHY") - c.Assert(err.Error(), Equals, eqErr.Error()) + require.EqualError(t, err, eqErr.Error()) _, err = tk1.Exec("SHOW STATS_HISTOGRAMS") - c.Assert(err.Error(), Equals, eqErr.Error()) + require.EqualError(t, err, eqErr.Error()) tk.MustExec("grant select on mysql.* to show_stats") tk1.MustExec("show stats_meta") tk1.MustExec("SHOW STATS_BUCKETS") @@ -224,55 +221,53 @@ func (s *testSuite5) TestShowStatsPrivilege(c *C) { tk1.MustExec("SHOW STATS_HISTOGRAMS") } -func (s *testSuite5) TestIssue18878(c *C) { - tk := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthHostname: "%"}, nil, nil), IsTrue) - tk.Se = se +func TestIssue18878(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthHostname: "%"}, nil, nil)) tk.MustQuery("select user()").Check(testkit.Rows("root@127.0.0.1")) tk.MustQuery("show grants") tk.MustQuery("select user()").Check(testkit.Rows("root@127.0.0.1")) - err = tk.QueryToErr("show grants for root@127.0.0.1") - c.Assert(err.Error(), Equals, privileges.ErrNonexistingGrant.FastGenByArgs("root", "127.0.0.1").Error()) + err := tk.QueryToErr("show grants for root@127.0.0.1") + require.Equal(t, privileges.ErrNonexistingGrant.FastGenByArgs("root", "127.0.0.1").Error(), err.Error()) err = tk.QueryToErr("show grants for root@localhost") - c.Assert(err.Error(), Equals, privileges.ErrNonexistingGrant.FastGenByArgs("root", "localhost").Error()) + require.Equal(t, privileges.ErrNonexistingGrant.FastGenByArgs("root", "localhost").Error(), err.Error()) err = tk.QueryToErr("show grants for root@1.1.1.1") - c.Assert(err.Error(), Equals, privileges.ErrNonexistingGrant.FastGenByArgs("root", "1.1.1.1").Error()) + require.Equal(t, privileges.ErrNonexistingGrant.FastGenByArgs("root", "1.1.1.1").Error(), err.Error()) tk.MustExec("create user `show_grants`@`127.0.%`") err = tk.QueryToErr("show grants for `show_grants`@`127.0.0.1`") - c.Assert(err.Error(), Equals, privileges.ErrNonexistingGrant.FastGenByArgs("show_grants", "127.0.0.1").Error()) + require.Equal(t, privileges.ErrNonexistingGrant.FastGenByArgs("show_grants", "127.0.0.1").Error(), err.Error()) tk.MustQuery("show grants for `show_grants`@`127.0.%`") } -func (s *testSuite5) TestIssue17794(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue17794(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER 'root'@'8.8.%'") - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "9.9.9.9", AuthHostname: "%"}, nil, nil), IsTrue) - tk.Se = se - - tk1 := testkit.NewTestKit(c, s.store) - se1, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se1.Auth(&auth.UserIdentity{Username: "root", Hostname: "8.8.8.8", AuthHostname: "8.8.%"}, nil, nil), IsTrue) - tk1.Se = se1 + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "9.9.9.9", AuthHostname: "%"}, nil, nil)) + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "8.8.8.8", AuthHostname: "8.8.%"}, nil, nil)) tk.MustQuery("show grants").Check(testkit.Rows("GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION")) tk1.MustQuery("show grants").Check(testkit.Rows("GRANT USAGE ON *.* TO 'root'@'8.8.%'")) } -func (s *testSuite5) TestIssue3641(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue3641(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) _, err := tk.Exec("show tables;") - c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error()) + require.Equal(t, plannercore.ErrNoDB.Error(), err.Error()) _, err = tk.Exec("show table status;") - c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error()) + require.Equal(t, plannercore.ErrNoDB.Error(), err.Error()) } -func (s *testSuite5) TestIssue10549(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10549(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE newdb;") tk.MustExec("CREATE ROLE 'app_developer';") tk.MustExec("GRANT ALL ON newdb.* TO 'app_developer';") @@ -280,35 +275,39 @@ func (s *testSuite5) TestIssue10549(c *C) { tk.MustExec("GRANT 'app_developer' TO 'dev';") tk.MustExec("SET DEFAULT ROLE app_developer TO 'dev';") - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "dev", Hostname: "%", AuthUsername: "dev", AuthHostname: "%"}, nil, nil), IsTrue) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "%", AuthUsername: "dev", AuthHostname: "%"}, nil, nil)) tk.MustQuery("SHOW DATABASES;").Check(testkit.Rows("INFORMATION_SCHEMA", "newdb")) tk.MustQuery("SHOW GRANTS;").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'")) tk.MustQuery("SHOW GRANTS FOR CURRENT_USER").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'")) tk.MustQuery("SHOW GRANTS FOR dev").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'")) } -func (s *testSuite5) TestIssue11165(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue11165(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE ROLE 'r_manager';") tk.MustExec("CREATE USER 'manager'@'localhost';") tk.MustExec("GRANT 'r_manager' TO 'manager'@'localhost';") - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "manager", Hostname: "localhost", AuthUsername: "manager", AuthHostname: "localhost"}, nil, nil), IsTrue) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "manager", Hostname: "localhost", AuthUsername: "manager", AuthHostname: "localhost"}, nil, nil)) tk.MustExec("SET DEFAULT ROLE ALL TO 'manager'@'localhost';") tk.MustExec("SET DEFAULT ROLE NONE TO 'manager'@'localhost';") tk.MustExec("SET DEFAULT ROLE 'r_manager' TO 'manager'@'localhost';") } // TestShow2 is moved from session_test -func (s *testSuite5) TestShow2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShow2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set global autocommit=0") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustQuery("show global variables where variable_name = 'autocommit'").Check(testkit.Rows("autocommit OFF")) tk.MustExec("set global autocommit = 1") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustQuery("show global variables where variable_name = 'autocommit'").Check(testkit.Rows("autocommit ON")) // TODO: Specifying the charset for national char/varchar should not be supported. @@ -388,11 +387,11 @@ func (s *testSuite5) TestShow2(c *C) { tk.MustExec("drop table if exists t") tk.MustExec(`create table if not exists t (c int) comment '注释'`) tk.MustExec("create or replace definer='root'@'localhost' view v as select * from t") - tk.MustQuery(`show columns from t`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,,")) - tk.MustQuery(`describe t`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,,")) - tk.MustQuery(`show columns from v`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,,")) - tk.MustQuery(`describe v`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,,")) - tk.MustQuery("show collation where Charset = 'utf8' and Collation = 'utf8_bin'").Check(testutil.RowsWithSep(",", "utf8_bin,utf8,83,Yes,Yes,1")) + tk.MustQuery(`show columns from t`).Check(testkit.RowsWithSep(",", "c,int(11),YES,,,")) + tk.MustQuery(`describe t`).Check(testkit.RowsWithSep(",", "c,int(11),YES,,,")) + tk.MustQuery(`show columns from v`).Check(testkit.RowsWithSep(",", "c,int(11),YES,,,")) + tk.MustQuery(`describe v`).Check(testkit.RowsWithSep(",", "c,int(11),YES,,,")) + tk.MustQuery("show collation where Charset = 'utf8' and Collation = 'utf8_bin'").Check(testkit.RowsWithSep(",", "utf8_bin,utf8,83,Yes,Yes,1")) tk.MustExec(`drop sequence if exists seq`) tk.MustExec(`create sequence seq`) tk.MustQuery("show tables").Check(testkit.Rows("seq", "t", "v")) @@ -403,14 +402,13 @@ func (s *testSuite5) TestShow2(c *C) { tk.MustQuery("SHOW FULL TABLES in information_schema like 'VIEWS'").Check(testkit.Rows("VIEWS SYSTEM VIEW")) tk.MustQuery("SHOW FULL TABLES in metrics_schema like 'uptime'").Check(testkit.Rows("uptime SYSTEM VIEW")) - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() + is := dom.InfoSchema() tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) createTime := model.TSConvert2Time(tblInfo.Meta().UpdateTS).Format("2006-01-02 15:04:05") // The Hostname is the actual host - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) r := tk.MustQuery("show table status from test like 't'") r.Check(testkit.Rows(fmt.Sprintf("t InnoDB 10 Compact 0 0 0 0 0 0 %s utf8mb4_bin 注释", createTime))) @@ -424,8 +422,10 @@ func (s *testSuite5) TestShow2(c *C) { tk.MustQuery("show grants for current_user").Check(testkit.Rows(`GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION`)) } -func (s *testSuite5) TestShowCreateUser(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateUser(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Create a new user. tk.MustExec(`CREATE USER 'test_show_create_user'@'%' IDENTIFIED BY 'root';`) tk.MustQuery("show create user 'test_show_create_user'@'%'"). @@ -437,57 +437,56 @@ func (s *testSuite5) TestShowCreateUser(c *C) { // Case: the user exists but the host portion doesn't match err := tk.QueryToErr("show create user 'test_show_create_user'@'asdf';") - c.Assert(err.Error(), Equals, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'test_show_create_user'@'asdf'").Error()) + require.Equal(t, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'test_show_create_user'@'asdf'").Error(), err.Error()) // Case: a user that doesn't exist err = tk.QueryToErr("show create user 'aaa'@'localhost';") - c.Assert(err.Error(), Equals, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'aaa'@'localhost'").Error()) + require.Equal(t, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'aaa'@'localhost'").Error(), err.Error()) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, nil) - rows := tk.MustQuery("show create user current_user") - rows.Check(testkit.Rows("CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, nil) + tk.MustQuery("show create user current_user"). + Check(testkit.Rows("CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) - rows = tk.MustQuery("show create user current_user()") - rows.Check(testkit.Rows("CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) + tk.MustQuery("show create user current_user()"). + Check(testkit.Rows("CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) tk.MustExec("create user 'check_priv'") // "show create user" for other user requires the SELECT privilege on mysql database. - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use mysql") - succ := tk1.Se.Auth(&auth.UserIdentity{Username: "check_priv", Hostname: "127.0.0.1", AuthUsername: "test_show", AuthHostname: "asdf"}, nil, nil) - c.Assert(succ, IsTrue) + succ := tk1.Session().Auth(&auth.UserIdentity{Username: "check_priv", Hostname: "127.0.0.1", AuthUsername: "test_show", AuthHostname: "asdf"}, nil, nil) + require.True(t, succ) err = tk1.QueryToErr("show create user 'root'@'%'") - c.Assert(err, NotNil) + require.Error(t, err) // "show create user" for current user doesn't check privileges. - rows = tk1.MustQuery("show create user current_user") - rows.Check(testkit.Rows("CREATE USER 'check_priv'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) + tk1.MustQuery("show create user current_user"). + Check(testkit.Rows("CREATE USER 'check_priv'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK")) // Creating users with `IDENTIFIED WITH 'caching_sha2_password'` tk.MustExec("CREATE USER 'sha_test'@'%' IDENTIFIED WITH 'caching_sha2_password' BY 'temp_passwd'") // Compare only the start of the output as the salt changes every time. - rows = tk.MustQuery("SHOW CREATE USER 'sha_test'@'%'") - c.Assert(rows.Rows()[0][0].(string)[:78], check.Equals, "CREATE USER 'sha_test'@'%' IDENTIFIED WITH 'caching_sha2_password' AS '$A$005$") - + rows := tk.MustQuery("SHOW CREATE USER 'sha_test'@'%'") + require.Equal(t, "CREATE USER 'sha_test'@'%' IDENTIFIED WITH 'caching_sha2_password' AS '$A$005$", rows.Rows()[0][0].(string)[:78]) // Creating users with `IDENTIFIED WITH 'auth-socket'` tk.MustExec("CREATE USER 'sock'@'%' IDENTIFIED WITH 'auth_socket'") // Compare only the start of the output as the salt changes every time. rows = tk.MustQuery("SHOW CREATE USER 'sock'@'%'") - c.Assert(rows.Rows()[0][0].(string), check.Equals, "CREATE USER 'sock'@'%' IDENTIFIED WITH 'auth_socket' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK") - + require.Equal(t, "CREATE USER 'sock'@'%' IDENTIFIED WITH 'auth_socket' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK", rows.Rows()[0][0].(string)) tk.MustExec("CREATE USER 'sock2'@'%' IDENTIFIED WITH 'auth_socket' AS 'sock3'") // Compare only the start of the output as the salt changes every time. rows = tk.MustQuery("SHOW CREATE USER 'sock2'@'%'") - c.Assert(rows.Rows()[0][0].(string), check.Equals, "CREATE USER 'sock2'@'%' IDENTIFIED WITH 'auth_socket' AS 'sock3' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK") + require.Equal(t, "CREATE USER 'sock2'@'%' IDENTIFIED WITH 'auth_socket' AS 'sock3' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK", rows.Rows()[0][0].(string)) } -func (s *testSuite5) TestUnprivilegedShow(c *C) { - - tk := testkit.NewTestKit(c, s.store) +func TestUnprivilegedShow(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE DATABASE testshow") tk.MustExec("USE testshow") tk.MustExec("CREATE TABLE t1 (a int)") @@ -495,66 +494,69 @@ func (s *testSuite5) TestUnprivilegedShow(c *C) { tk.MustExec(`CREATE USER 'lowprivuser'`) // no grants - tk.Se.Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) rs, err := tk.Exec("SHOW TABLE STATUS FROM testshow") - c.Assert(err, IsNil) - c.Assert(rs, NotNil) + require.NoError(t, err) + require.NotNil(t, rs) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) tk.MustExec("GRANT ALL ON testshow.t1 TO 'lowprivuser'") - tk.Se.Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) - ctx := tk.Se.(sessionctx.Context) - is := domain.GetDomain(ctx).InfoSchema() + is := dom.InfoSchema() tblInfo, err := is.TableByName(model.NewCIStr("testshow"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) createTime := model.TSConvert2Time(tblInfo.Meta().UpdateTS).Format("2006-01-02 15:04:05") tk.MustQuery("show table status from testshow").Check(testkit.Rows(fmt.Sprintf("t1 InnoDB 10 Compact 0 0 0 0 0 0 %s utf8mb4_bin ", createTime))) } -func (s *testSuite5) TestCollation(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") rs, err := tk.Exec("show collation;") - c.Assert(err, IsNil) + require.NoError(t, err) fields := rs.Fields() - c.Assert(fields[0].Column.Tp, Equals, mysql.TypeVarchar) - c.Assert(fields[1].Column.Tp, Equals, mysql.TypeVarchar) - c.Assert(fields[2].Column.Tp, Equals, mysql.TypeLonglong) - c.Assert(fields[3].Column.Tp, Equals, mysql.TypeVarchar) - c.Assert(fields[4].Column.Tp, Equals, mysql.TypeVarchar) - c.Assert(fields[5].Column.Tp, Equals, mysql.TypeLonglong) + require.Equal(t, mysql.TypeVarchar, fields[0].Column.Tp) + require.Equal(t, mysql.TypeVarchar, fields[1].Column.Tp) + require.Equal(t, mysql.TypeLonglong, fields[2].Column.Tp) + require.Equal(t, mysql.TypeVarchar, fields[3].Column.Tp) + require.Equal(t, mysql.TypeVarchar, fields[4].Column.Tp) + require.Equal(t, mysql.TypeLonglong, fields[5].Column.Tp) } -func (s *testSuite5) TestShowTableStatus(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowTableStatus(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a bigint);`) - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) // It's not easy to test the result contents because every time the test runs, "Create_time" changed. tk.MustExec("show table status;") rs, err := tk.Exec("show table status;") - c.Assert(err, IsNil) - c.Assert(rs, NotNil) - rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + require.NotNil(t, rs) + rows, err := session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) err = rs.Close() - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, len(rows)) for i := range rows { row := rows[i] - c.Assert(row.GetString(0), Equals, "t") - c.Assert(row.GetString(1), Equals, "InnoDB") - c.Assert(row.GetInt64(2), Equals, int64(10)) - c.Assert(row.GetString(3), Equals, "Compact") + require.Equal(t, "t", row.GetString(0)) + require.Equal(t, "InnoDB", row.GetString(1)) + require.Equal(t, int64(10), row.GetInt64(2)) + require.Equal(t, "Compact", row.GetString(3)) } tk.MustExec(`drop table if exists tp;`) tk.MustExec(`create table tp (a int) @@ -564,38 +566,40 @@ func (s *testSuite5) TestShowTableStatus(c *C) { partition p2 values less than (maxvalue) );`) rs, err = tk.Exec("show table status from test like 'tp';") - c.Assert(err, IsNil) - rows, err = session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) - c.Assert(rows[0].GetString(16), Equals, "partitioned") + require.NoError(t, err) + rows, err = session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) + require.Equal(t, "partitioned", rows[0].GetString(16)) tk.MustExec("create database UPPER_CASE") tk.MustExec("use UPPER_CASE") tk.MustExec("create table t (i int)") rs, err = tk.Exec("show table status") - c.Assert(err, IsNil) - c.Assert(rs, NotNil) - rows, err = session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + require.NotNil(t, rs) + rows, err = session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) err = rs.Close() - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, len(rows)) tk.MustExec("use upper_case") rs, err = tk.Exec("show table status") - c.Assert(err, IsNil) - c.Assert(rs, NotNil) - rows, err = session.GetRows4Test(context.Background(), tk.Se, rs) - c.Assert(err, IsNil) + require.NoError(t, err) + require.NotNil(t, rs) + rows, err = session.GetRows4Test(context.Background(), tk.Session(), rs) + require.NoError(t, err) err = rs.Close() - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, 1) + require.NoError(t, err) + require.Equal(t, 1, len(rows)) tk.MustExec("drop database UPPER_CASE") } -func (s *testSuite5) TestShowSlow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowSlow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // The test result is volatile, because // 1. Slow queries is stored in domain, which may be affected by other tests. // 2. Collecting slow queries is a asynchronous process, check immediately may not get the expected result. @@ -607,54 +611,58 @@ func (s *testSuite5) TestShowSlow(c *C) { tk.MustQuery(`admin show slow top all 3`) } -func (s *testSuite5) TestShowOpenTables(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowOpenTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("show open tables") tk.MustQuery("show open tables in test") } -func (s *testSuite5) TestShowCreateViewDefiner(c *C) { - tk := testkit.NewTestKit(c, s.store) - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%", AuthUsername: "root", AuthHostname: "%"}, nil, nil), IsTrue) - tk.Se = se +func TestShowCreateViewDefiner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%", AuthUsername: "root", AuthHostname: "%"}, nil, nil)) + tk.MustExec("use test") tk.MustExec("create or replace view v1 as select 1") - tk.MustQuery("show create view v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `v1` (`1`) AS SELECT 1 AS `1`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create view v1").Check(testkit.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `v1` (`1`) AS SELECT 1 AS `1`|utf8mb4|utf8mb4_bin")) tk.MustExec("drop view v1") } -func (s *testSuite5) TestShowCreateTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int,b int)") tk.MustExec("drop view if exists v1") tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v1 as select * from t1") - tk.MustQuery("show create table v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS SELECT `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) - tk.MustQuery("show create view v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS SELECT `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create table v1").Check(testkit.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS SELECT `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create view v1").Check(testkit.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS SELECT `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) tk.MustExec("drop view v1") tk.MustExec("drop table t1") tk.MustExec("drop view if exists v") tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v as select JSON_MERGE('{}', '{}') as col;") - tk.MustQuery("show create view v").Check(testutil.RowsWithSep("|", "v|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v` (`col`) AS SELECT JSON_MERGE(_UTF8MB4'{}', _UTF8MB4'{}') AS `col`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create view v").Check(testkit.RowsWithSep("|", "v|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v` (`col`) AS SELECT JSON_MERGE(_UTF8MB4'{}', _UTF8MB4'{}') AS `col`|utf8mb4|utf8mb4_bin")) tk.MustExec("drop view if exists v") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int,b int)") tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v1 as select avg(a),t1.* from t1 group by a") - tk.MustQuery("show create view v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`avg(a)`, `a`, `b`) AS SELECT AVG(`a`) AS `avg(a)`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1` GROUP BY `a`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create view v1").Check(testkit.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`avg(a)`, `a`, `b`) AS SELECT AVG(`a`) AS `avg(a)`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` FROM `test`.`t1` GROUP BY `a`|utf8mb4|utf8mb4_bin")) tk.MustExec("drop view v1") tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v1 as select a+b, t1.* , a as c from t1") - tk.MustQuery("show create view v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a+b`, `a`, `b`, `c`) AS SELECT `a`+`b` AS `a+b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`a` AS `c` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) + tk.MustQuery("show create view v1").Check(testkit.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a+b`, `a`, `b`, `c`) AS SELECT `a`+`b` AS `a+b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`a` AS `c` FROM `test`.`t1`|utf8mb4|utf8mb4_bin")) tk.MustExec("drop table t1") tk.MustExec("drop view v1") // For issue #9211 tk.MustExec("create table t(c int, b int as (c + 1))ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` int(11) DEFAULT NULL,\n"+ @@ -664,7 +672,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec("drop table t") tk.MustExec("create table t(c int, b int as (c + 1) not null)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `c` int(11) DEFAULT NULL,\n"+ @@ -673,7 +681,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { )) tk.MustExec("drop table t") tk.MustExec("create table t ( a char(10) charset utf8 collate utf8_bin, b char(10) as (rtrim(a)));") - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` char(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n"+ @@ -684,7 +692,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec(`drop table if exists different_charset`) tk.MustExec(`create table different_charset(ch1 varchar(10) charset utf8, ch2 varchar(10) charset binary);`) - tk.MustQuery(`show create table different_charset`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table different_charset`).Check(testkit.RowsWithSep("|", ""+ "different_charset CREATE TABLE `different_charset` (\n"+ " `ch1` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n"+ @@ -701,7 +709,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { "`e` varchar(20) default 'cUrrent_tImestamp',\n" + "`f` datetime(2) default current_timestamp(2) on update current_timestamp(2),\n" + "`g` timestamp(2) default current_timestamp(2) on update current_timestamp(2))") - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n"+ @@ -716,7 +724,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec("drop table t") tk.MustExec("create table t (a int, b int) shard_row_id_bits = 4 pre_split_regions=3;") - tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t`").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ @@ -728,7 +736,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // for issue #20446 tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(c int unsigned default 0);") - tk.MustQuery("show create table `t1`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t1`").Check(testkit.RowsWithSep("|", ""+ "t1 CREATE TABLE `t1` (\n"+ " `c` int(10) unsigned DEFAULT '0'\n"+ @@ -762,7 +770,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { "PARTITION `p10` VALUES LESS THAN (11)," + "PARTITION `p11` VALUES LESS THAN (12)," + "PARTITION `p12` VALUES LESS THAN (MAXVALUE))") - tk.MustQuery("show create table log").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table log").Check(testkit.RowsWithSep("|", "log CREATE TABLE `log` (\n"+ " `LOG_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n"+ " `ROUND_ID` bigint(20) unsigned NOT NULL,\n"+ @@ -792,14 +800,14 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // for issue #11831 tk.MustExec("create table ttt4(a varchar(123) default null collate utf8mb4_unicode_ci)engine=innodb default charset=utf8mb4 collate=utf8mb4_unicode_ci;") - tk.MustQuery("show create table `ttt4`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `ttt4`").Check(testkit.RowsWithSep("|", ""+ "ttt4 CREATE TABLE `ttt4` (\n"+ " `a` varchar(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", )) tk.MustExec("create table ttt5(a varchar(123) default null)engine=innodb default charset=utf8mb4 collate=utf8mb4_bin;") - tk.MustQuery("show create table `ttt5`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `ttt5`").Check(testkit.RowsWithSep("|", ""+ "ttt5 CREATE TABLE `ttt5` (\n"+ " `a` varchar(123) DEFAULT NULL\n"+ @@ -810,7 +818,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b real);") tk.MustExec("alter table t add index expr_idx((a*b+1));") - tk.MustQuery("show create table t;").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t;").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ @@ -827,7 +835,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // Test for issue #15633, 'binary' collation should be ignored in the result of 'show create table'. tk.MustExec(`drop table if exists binary_collate`) tk.MustExec(`create table binary_collate(a varchar(10)) default collate=binary;`) - tk.MustQuery(`show create table binary_collate`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table binary_collate`).Check(testkit.RowsWithSep("|", ""+ "binary_collate CREATE TABLE `binary_collate` (\n"+ " `a` varbinary(10) DEFAULT NULL\n"+ @@ -835,7 +843,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { )) tk.MustExec(`drop table if exists binary_collate`) tk.MustExec(`create table binary_collate(a varchar(10)) default charset=binary collate=binary;`) - tk.MustQuery(`show create table binary_collate`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table binary_collate`).Check(testkit.RowsWithSep("|", ""+ "binary_collate CREATE TABLE `binary_collate` (\n"+ " `a` varbinary(10) DEFAULT NULL\n"+ @@ -843,7 +851,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { )) tk.MustExec(`drop table if exists binary_collate`) tk.MustExec(`create table binary_collate(a varchar(10)) default charset=utf8mb4 collate=utf8mb4_bin;`) - tk.MustQuery(`show create table binary_collate`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table binary_collate`).Check(testkit.RowsWithSep("|", ""+ "binary_collate CREATE TABLE `binary_collate` (\n"+ " `a` varchar(10) DEFAULT NULL\n"+ @@ -852,7 +860,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // Test for issue #17 in bug competition, default num and sequence should be shown without quote. tk.MustExec(`drop table if exists default_num`) tk.MustExec("create table default_num(a int default 11)") - tk.MustQuery("show create table default_num").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table default_num").Check(testkit.RowsWithSep("|", ""+ "default_num CREATE TABLE `default_num` (\n"+ " `a` int(11) DEFAULT '11'\n"+ @@ -860,7 +868,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { )) tk.MustExec(`drop table if exists default_varchar`) tk.MustExec("create table default_varchar(a varchar(10) default \"haha\")") - tk.MustQuery("show create table default_varchar").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table default_varchar").Check(testkit.RowsWithSep("|", ""+ "default_varchar CREATE TABLE `default_varchar` (\n"+ " `a` varchar(10) DEFAULT 'haha'\n"+ @@ -868,7 +876,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { )) tk.MustExec(`drop table if exists default_sequence`) tk.MustExec("create table default_sequence(a int default nextval(seq))") - tk.MustQuery("show create table default_sequence").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table default_sequence").Check(testkit.RowsWithSep("|", ""+ "default_sequence CREATE TABLE `default_sequence` (\n"+ " `a` int(11) DEFAULT nextval(`test`.`seq`)\n"+ @@ -881,7 +889,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec(`DROP TABLE IF EXISTS parent, child`) tk.MustExec(`CREATE TABLE child (id INT NOT NULL PRIMARY KEY auto_increment, parent_id INT NOT NULL, INDEX par_ind (parent_id), CONSTRAINT child_ibfk_1 FOREIGN KEY (parent_id) REFERENCES parent(id))`) tk.MustExec(`CREATE TABLE parent ( id INT NOT NULL PRIMARY KEY auto_increment )`) - tk.MustQuery(`show create table child`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table child`).Check(testkit.RowsWithSep("|", ""+ "child CREATE TABLE `child` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -895,7 +903,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // Test Foreign keys + ON DELETE / ON UPDATE tk.MustExec(`DROP TABLE child`) tk.MustExec(`CREATE TABLE child (id INT NOT NULL PRIMARY KEY auto_increment, parent_id INT NOT NULL, INDEX par_ind (parent_id), CONSTRAINT child_ibfk_1 FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE SET NULL ON UPDATE CASCADE)`) - tk.MustQuery(`show create table child`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table child`).Check(testkit.RowsWithSep("|", ""+ "child CREATE TABLE `child` (\n"+ " `id` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -910,12 +918,11 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b char(10) as ('a'));") result := tk.MustQuery("show create table t;").Rows()[0][1] - c.Assert(result, Matches, `(?s).*GENERATED ALWAYS AS \(_utf8mb4'a'\).*`) + require.Regexp(t, `(?s).*GENERATED ALWAYS AS \(_utf8mb4'a'\).*`, result) tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b char(10) as (_utf8'a'));") result = tk.MustQuery("show create table t;").Rows()[0][1] - c.Assert(result, Matches, `(?s).*GENERATED ALWAYS AS \(_utf8'a'\).*`) - + require.Regexp(t, `(?s).*GENERATED ALWAYS AS \(_utf8'a'\).*`, result) // Test show list partition table tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec(`DROP TABLE IF EXISTS t`) @@ -925,7 +932,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { partition p2 values in (4,12,13,14,18), partition p3 values in (7,8,15,16,null) );`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `id` int(11) DEFAULT NULL,\n"+ " `name` varchar(10) DEFAULT NULL,\n"+ @@ -944,7 +951,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { partition p2 values in (4,12,13,14,18), partition p3 values in (7,8,15,16,null) );`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `id` int(11) DEFAULT NULL,\n"+ " `name` varchar(10) DEFAULT NULL,\n"+ @@ -959,7 +966,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { tk.MustExec(`create table t (id int, name varchar(10), unique index idx (id, name)) partition by list columns (id, name) ( partition p0 values in ((3, '1'), (5, '5')), partition p1 values in ((1, '1')));`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `id` int(11) DEFAULT NULL,\n"+ " `name` varchar(10) DEFAULT NULL,\n"+ @@ -970,7 +977,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { " PARTITION `p1` VALUES IN ((1,\"1\")))")) tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec(`create table t (id int primary key, v varchar(255) not null, key idx_v (v) comment 'foo\'bar')`) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `id` int(11) NOT NULL,\n"+ " `v` varchar(255) NOT NULL,\n"+ @@ -980,7 +987,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // For issue #29922 tk.MustExec("CREATE TABLE `thash` (\n `id` bigint unsigned NOT NULL,\n `data` varchar(255) DEFAULT NULL,\n PRIMARY KEY (`id`)\n)\nPARTITION BY HASH (`id`)\n(PARTITION pEven COMMENT = \"Even ids\",\n PARTITION pOdd COMMENT = \"Odd ids\");") - tk.MustQuery("show create table `thash`").Check(testutil.RowsWithSep("|", ""+ + tk.MustQuery("show create table `thash`").Check(testkit.RowsWithSep("|", ""+ "thash CREATE TABLE `thash` (\n"+ " `id` bigint(20) unsigned NOT NULL,\n"+ " `data` varchar(255) DEFAULT NULL,\n"+ @@ -993,7 +1000,7 @@ func (s *testSuite5) TestShowCreateTable(c *C) { // empty edge case tk.MustExec("drop table if exists `thash`") tk.MustExec("CREATE TABLE `thash` (\n `id` bigint unsigned NOT NULL,\n `data` varchar(255) DEFAULT NULL,\n PRIMARY KEY (`id`)\n)\nPARTITION BY HASH (`id`);") - tk.MustQuery("show create table `thash`").Check(testutil.RowsWithSep("|", ""+ + tk.MustQuery("show create table `thash`").Check(testkit.RowsWithSep("|", ""+ "thash CREATE TABLE `thash` (\n"+ " `id` bigint(20) unsigned NOT NULL,\n"+ " `data` varchar(255) DEFAULT NULL,\n"+ @@ -1001,26 +1008,26 @@ func (s *testSuite5) TestShowCreateTable(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY HASH (`id`) PARTITIONS 1", )) + + // default value escape character '\\' display case + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int primary key, b varchar(20) default '\\\\');") + tk.MustQuery("show create table t;").Check(testkit.RowsWithSep("|", + ""+ + "t CREATE TABLE `t` (\n"+ + " `a` int(11) NOT NULL,\n"+ + " `b` varchar(20) DEFAULT '\\\\',\n"+ + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n"+ + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) } -func (s *testSuite5) TestShowCreateTablePlacement(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateTablePlacement(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") defer tk.MustExec(`DROP TABLE IF EXISTS t`) - // case for direct opts - tk.MustExec(`DROP TABLE IF EXISTS t`) - tk.MustExec("create table t(a int) " + - "FOLLOWERS=2 " + - "CONSTRAINTS=\"[+disk=ssd]\"") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", - "t CREATE TABLE `t` (\n"+ - " `a` int(11) DEFAULT NULL\n"+ - ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ - "/*T![placement] FOLLOWERS=2 "+ - "CONSTRAINTS=\"[+disk=ssd]\" */", - )) - // case for policy tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create placement policy x " + @@ -1029,7 +1036,7 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { defer tk.MustExec(`DROP PLACEMENT POLICY IF EXISTS x`) tk.MustExec("create table t(a int)" + "PLACEMENT POLICY=\"x\"") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ @@ -1040,7 +1047,7 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create table t(a int)" + "/*T![placement] PLACEMENT POLICY=\"x\" */") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin "+ @@ -1057,8 +1064,8 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { "PARTITION BY LIST (a)\n" + "(PARTITION pLow VALUES in (1,2,3,5,8) COMMENT 'a comment' placement policy 'x'," + " PARTITION pMid VALUES in (9) COMMENT 'another comment'," + - "partition pMax values IN (10,11,12) PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax values IN (10,11,12))") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ @@ -1066,67 +1073,67 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { "PARTITION BY LIST (`a`)\n"+ "(PARTITION `pLow` VALUES IN (1,2,3,5,8) COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ " PARTITION `pMid` VALUES IN (9) COMMENT 'another comment',\n"+ - " PARTITION `pMax` VALUES IN (10,11,12) /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax` VALUES IN (10,11,12))", )) tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create table t(a int, b varchar(255))" + "PARTITION BY LIST COLUMNS (b)\n" + "(PARTITION pLow VALUES in ('1','2','3','5','8') COMMENT 'a comment' placement policy 'x'," + - "partition pMax values IN ('10','11','12') PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax values IN ('10','11','12'))") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY LIST COLUMNS(`b`)\n"+ "(PARTITION `pLow` VALUES IN (\"1\",\"2\",\"3\",\"5\",\"8\") COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ - " PARTITION `pMax` VALUES IN (\"10\",\"11\",\"12\") /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax` VALUES IN (\"10\",\"11\",\"12\"))", )) tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create table t(a int, b varchar(255))" + "PARTITION BY LIST COLUMNS (a,b)\n" + "(PARTITION pLow VALUES in ((1,'1'),(2,'2'),(3,'3'),(5,'5'),(8,'8')) COMMENT 'a comment' placement policy 'x'," + - "partition pMax values IN ((10,'10'),(11,'11'),(12,'12')) PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax values IN ((10,'10'),(11,'11'),(12,'12')))") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY LIST COLUMNS(`a`,`b`)\n"+ "(PARTITION `pLow` VALUES IN ((1,\"1\"),(2,\"2\"),(3,\"3\"),(5,\"5\"),(8,\"8\")) COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ - " PARTITION `pMax` VALUES IN ((10,\"10\"),(11,\"11\"),(12,\"12\")) /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax` VALUES IN ((10,\"10\"),(11,\"11\"),(12,\"12\")))", )) tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create table t(a int, b varchar(255))" + "PARTITION BY RANGE (a)\n" + "(PARTITION pLow VALUES less than (1000000) COMMENT 'a comment' placement policy 'x'," + - "partition pMax values LESS THAN (MAXVALUE) PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax values LESS THAN (MAXVALUE))") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY RANGE (`a`)\n"+ "(PARTITION `pLow` VALUES LESS THAN (1000000) COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ - " PARTITION `pMax` VALUES LESS THAN (MAXVALUE) /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax` VALUES LESS THAN (MAXVALUE))", )) tk.MustExec(`DROP TABLE IF EXISTS t`) tk.MustExec("create table t(a int, b varchar(255))" + "PARTITION BY RANGE COLUMNS (b)\n" + "(PARTITION pLow VALUES less than ('1000000') COMMENT 'a comment' placement policy 'x'," + - "partition pMax values LESS THAN (MAXVALUE) PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax values LESS THAN (MAXVALUE))") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY RANGE COLUMNS(`b`)\n"+ "(PARTITION `pLow` VALUES LESS THAN (\"1000000\") COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ - " PARTITION `pMax` VALUES LESS THAN (MAXVALUE) /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax` VALUES LESS THAN (MAXVALUE))", )) tk.MustExec(`DROP TABLE IF EXISTS t`) @@ -1137,9 +1144,9 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { "(PARTITION pLow VALUES less than (1000000,'1000000') COMMENT 'a comment' placement policy 'x'," + " PARTITION pMidLow VALUES less than (1000000,MAXVALUE) COMMENT 'another comment' placement policy 'x'," + " PARTITION pMadMax VALUES less than (MAXVALUE,'1000000') COMMENT ='Not a comment' placement policy 'x'," + - "partition pMax values LESS THAN (MAXVALUE, MAXVALUE) PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") + "partition pMax values LESS THAN (MAXVALUE, MAXVALUE))") tk.MustQuery("show warnings").Check(testkit.Rows("Warning 8200 Unsupported partition type RANGE, treat as normal table")) - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ @@ -1150,7 +1157,7 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { tk.MustExec("create table t(a int, b varchar(255))" + "/*T![placement] PLACEMENT POLICY=\"x\" */" + "PARTITION BY HASH (a) PARTITIONS 2") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ @@ -1162,26 +1169,28 @@ func (s *testSuite5) TestShowCreateTablePlacement(c *C) { tk.MustExec("create table t(a int, b varchar(255))" + "PARTITION BY HASH (a)\n" + "(PARTITION pLow COMMENT 'a comment' placement policy 'x'," + - "partition pMax PRIMARY_REGION = 'us-west-1' REGIONS = 'us-west-1,us-west-2')") - tk.MustQuery(`show create table t`).Check(testutil.RowsWithSep("|", ""+ + "partition pMax)") + tk.MustQuery(`show create table t`).Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) DEFAULT NULL,\n"+ " `b` varchar(255) DEFAULT NULL\n"+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n"+ "PARTITION BY HASH (`a`)\n"+ "(PARTITION `pLow` COMMENT 'a comment' /*T![placement] PLACEMENT POLICY=`x` */,\n"+ - " PARTITION `pMax` /*T![placement] PRIMARY_REGION=\"us-west-1\" REGIONS=\"us-west-1,us-west-2\" */)", + " PARTITION `pMax`)", )) tk.MustExec(`DROP TABLE t`) } -func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateTableAutoRandom(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Basic show create table. tk.MustExec("create table auto_random_tbl1 (a bigint primary key auto_random(3), b varchar(255))") - tk.MustQuery("show create table `auto_random_tbl1`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `auto_random_tbl1`").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl1 CREATE TABLE `auto_random_tbl1` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(3) */,\n"+ @@ -1192,7 +1201,7 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { // Implicit auto_random value should be shown explicitly. tk.MustExec("create table auto_random_tbl2 (a bigint auto_random primary key, b char)") - tk.MustQuery("show create table auto_random_tbl2").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table auto_random_tbl2").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl2 CREATE TABLE `auto_random_tbl2` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1203,7 +1212,7 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { // Special version comment can be shown in TiDB with new version. tk.MustExec("create table auto_random_tbl3 (a bigint /*T![auto_rand] auto_random */ primary key)") - tk.MustQuery("show create table auto_random_tbl3").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table auto_random_tbl3").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl3 CREATE TABLE `auto_random_tbl3` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1212,7 +1221,7 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { )) // Test show auto_random table option. tk.MustExec("create table auto_random_tbl4 (a bigint primary key auto_random(5), b varchar(255)) auto_random_base = 100") - tk.MustQuery("show create table `auto_random_tbl4`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `auto_random_tbl4`").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl4 CREATE TABLE `auto_random_tbl4` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1222,7 +1231,7 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { )) // Test implicit auto_random with auto_random table option. tk.MustExec("create table auto_random_tbl5 (a bigint auto_random primary key, b char) auto_random_base 50") - tk.MustQuery("show create table auto_random_tbl5").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table auto_random_tbl5").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl5 CREATE TABLE `auto_random_tbl5` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1232,7 +1241,7 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { )) // Test auto_random table option already with special comment. tk.MustExec("create table auto_random_tbl6 (a bigint /*T![auto_rand] auto_random */ primary key) auto_random_base 200") - tk.MustQuery("show create table auto_random_tbl6").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table auto_random_tbl6").Check(testkit.RowsWithSep("|", ""+ "auto_random_tbl6 CREATE TABLE `auto_random_tbl6` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1242,13 +1251,15 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) { } // TestAutoIdCache overrides testAutoRandomSuite to test auto id cache. -func (s *testAutoRandomSuite) TestAutoIdCache(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoIdCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int auto_increment key) auto_id_cache = 10") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -1257,7 +1268,7 @@ func (s *testAutoRandomSuite) TestAutoIdCache(c *C) { )) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int auto_increment unique, b int key) auto_id_cache 100") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) NOT NULL AUTO_INCREMENT,\n"+ @@ -1268,7 +1279,7 @@ func (s *testAutoRandomSuite) TestAutoIdCache(c *C) { )) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int key) auto_id_cache 5") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` int(11) NOT NULL,\n"+ @@ -1277,15 +1288,17 @@ func (s *testAutoRandomSuite) TestAutoIdCache(c *C) { )) } -func (s *testSuite5) TestShowCreateStmtIgnoreLocalTemporaryTables(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreateStmtIgnoreLocalTemporaryTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // SHOW CREATE VIEW ignores local temporary table with the same name tk.MustExec("drop view if exists v1") tk.MustExec("create view v1 as select 1") tk.MustExec("create temporary table v1 (a int)") - tk.MustQuery("show create table v1").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table v1").Check(testkit.RowsWithSep("|", ""+ "v1 CREATE TEMPORARY TABLE `v1` (\n"+ " `a` int(11) DEFAULT NULL\n"+ @@ -1293,33 +1306,34 @@ func (s *testSuite5) TestShowCreateStmtIgnoreLocalTemporaryTables(c *C) { )) tk.MustExec("drop view v1") err := tk.ExecToErr("show create view v1") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) // SHOW CREATE SEQUENCE ignores local temporary table with the same name tk.MustExec("drop view if exists seq1") tk.MustExec("create sequence seq1") tk.MustExec("create temporary table seq1 (a int)") - tk.MustQuery("show create sequence seq1").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create sequence seq1").Check(testkit.RowsWithSep("|", "seq1 CREATE SEQUENCE `seq1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB", )) tk.MustExec("drop sequence seq1") err = tk.ExecToErr("show create sequence seq1") - c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue) + require.True(t, infoschema.ErrTableNotExists.Equal(err)) } -func (s *testAutoRandomSuite) TestAutoRandomBase(c *C) { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`), IsNil) +func TestAutoRandomBase(t *testing.T) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/meta/autoid/mockAutoIDChange")) }() - - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@allow_auto_random_explicit_insert = true") tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a bigint primary key auto_random(5), b int unique key auto_increment) auto_random_base = 100, auto_increment = 100") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1330,7 +1344,7 @@ func (s *testAutoRandomSuite) TestAutoRandomBase(c *C) { )) tk.MustExec("insert into t(`a`) values (1000)") - tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table t").Check(testkit.RowsWithSep("|", ""+ "t CREATE TABLE `t` (\n"+ " `a` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,\n"+ @@ -1341,8 +1355,10 @@ func (s *testAutoRandomSuite) TestAutoRandomBase(c *C) { )) } -func (s *testSuite5) TestAutoRandomWithLargeSignedShowTableRegions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAutoRandomWithLargeSignedShowTableRegions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database if not exists auto_random_db;") defer tk.MustExec("drop database if exists auto_random_db;") tk.MustExec("use auto_random_db;") @@ -1356,17 +1372,19 @@ func (s *testSuite5) TestAutoRandomWithLargeSignedShowTableRegions(c *C) { Check(testkit.Rows("1 1")) startKey := tk.MustQuery("show table t regions;").Rows()[1][1].(string) idx := strings.Index(startKey, "_r_") - c.Assert(idx == -1, IsFalse) - c.Assert(startKey[idx+3] == '-', IsFalse, Commentf("actual key: %s", startKey)) + require.False(t, idx == -1) + require.Falsef(t, startKey[idx+3] == '-', "actual key: %s", startKey) } -func (s *testSuite5) TestShowEscape(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowEscape(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists `t``abl\"e`") tk.MustExec("create table `t``abl\"e`(`c``olum\"n` int(11) primary key)") - tk.MustQuery("show create table `t``abl\"e`").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table `t``abl\"e`").Check(testkit.RowsWithSep("|", ""+ "t`abl\"e CREATE TABLE `t``abl\"e` (\n"+ " `c``olum\"n` int(11) NOT NULL,\n"+ @@ -1377,7 +1395,7 @@ func (s *testSuite5) TestShowEscape(c *C) { // ANSI_QUOTES will change the SHOW output tk.MustExec("set @old_sql_mode=@@sql_mode") tk.MustExec("set sql_mode=ansi_quotes") - tk.MustQuery("show create table \"t`abl\"\"e\"").Check(testutil.RowsWithSep("|", + tk.MustQuery("show create table \"t`abl\"\"e\"").Check(testkit.RowsWithSep("|", ""+ "t`abl\"e CREATE TABLE \"t`abl\"\"e\" (\n"+ " \"c`olum\"\"n\" int(11) NOT NULL,\n"+ @@ -1389,19 +1407,23 @@ func (s *testSuite5) TestShowEscape(c *C) { tk.MustExec("set sql_mode=@old_sql_mode") } -func (s *testSuite5) TestShowBuiltin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowBuiltin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) res := tk.MustQuery("show builtins;") - c.Assert(res, NotNil) + require.NotNil(t, res) rows := res.Rows() - const builtinFuncNum = 274 - c.Assert(builtinFuncNum, Equals, len(rows)) - c.Assert("abs", Equals, rows[0][0].(string)) - c.Assert("yearweek", Equals, rows[builtinFuncNum-1][0].(string)) + const builtinFuncNum = 275 + require.Equal(t, len(rows), builtinFuncNum) + require.Equal(t, rows[0][0].(string), "abs") + require.Equal(t, rows[builtinFuncNum-1][0].(string), "yearweek") } -func (s *testSuite5) TestShowClusterConfig(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowClusterConfig(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") var confItems [][]types.Datum @@ -1409,7 +1431,7 @@ func (s *testSuite5) TestShowClusterConfig(c *C) { var confFunc executor.TestShowClusterConfigFunc = func() ([][]types.Datum, error) { return confItems, confErr } - tk.Se.SetValue(executor.TestShowClusterConfigKey, confFunc) + tk.Session().SetValue(executor.TestShowClusterConfigKey, confFunc) strs2Items := func(strs ...string) []types.Datum { items := make([]types.Datum, 0, len(strs)) for _, s := range strs { @@ -1431,40 +1453,42 @@ func (s *testSuite5) TestShowClusterConfig(c *C) { "tikv 127.0.0.1:3333 log.level info")) confErr = fmt.Errorf("something unknown error") - c.Assert(tk.QueryToErr("show config"), ErrorMatches, confErr.Error()) + require.EqualError(t, tk.QueryToErr("show config"), confErr.Error()) } -func (s *testSuite5) TestInvisibleCoprCacheConfig(c *C) { - se1, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - tk := testkit.NewTestKitWithSession(c, s.store, se1) +func TestInvisibleCoprCacheConfig(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) rows := tk.MustQuery("show variables like '%config%'").Rows() - c.Assert(len(rows), Equals, 1) + require.Equal(t, 1, len(rows)) configValue := rows[0][1].(string) coprCacheVal := "\t\t\"copr-cache\": {\n" + "\t\t\t\"capacity-mb\": 1000\n" + "\t\t},\n" - c.Assert(strings.Contains(configValue, coprCacheVal), Equals, true) + require.Equal(t, true, strings.Contains(configValue, coprCacheVal)) } -func (s *testSuite5) TestInvisibleGlobalKillConfig(c *C) { - se1, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - tk := testkit.NewTestKitWithSession(c, s.store, se1) +func TestInvisibleGlobalKillConfig(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) rows := tk.MustQuery("show variables like '%config%'").Rows() - c.Assert(len(rows), Equals, 1) + require.Equal(t, 1, len(rows)) configValue := rows[0][1].(string) globalKillVal := "global-kill" - c.Assert(strings.Contains(configValue, globalKillVal), Equals, false) + require.Equal(t, false, strings.Contains(configValue, globalKillVal)) } -func (s *testSerialSuite1) TestShowCreateTableWithIntegerDisplayLengthWarnings(c *C) { +func TestShowCreateTableWithIntegerDisplayLengthWarnings(t *testing.T) { parsertypes.TiDBStrictIntegerDisplayWidth = true defer func() { parsertypes.TiDBStrictIntegerDisplayWidth = false }() - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1523,8 +1547,10 @@ func (s *testSerialSuite1) TestShowCreateTableWithIntegerDisplayLengthWarnings(c ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) } -func (s *testSuite5) TestShowVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) var showSQL string sessionVars := make([]string, 0, len(variable.GetSysVars())) globalVars := make([]string, 0, len(variable.GetSysVars())) @@ -1544,45 +1570,62 @@ func (s *testSuite5) TestShowVar(c *C) { sessionVarsStr := strings.Join(sessionVars, "','") showSQL = "show variables where variable_name in('" + sessionVarsStr + "')" res := tk.MustQuery(showSQL) - c.Check(res.Rows(), HasLen, len(sessionVars)) + require.Len(t, res.Rows(), len(sessionVars)) showSQL = "show global variables where variable_name in('" + sessionVarsStr + "')" res = tk.MustQuery(showSQL) - c.Check(res.Rows(), HasLen, 0) + require.Len(t, res.Rows(), 0) globalVarsStr := strings.Join(globalVars, "','") showSQL = "show variables where variable_name in('" + globalVarsStr + "')" res = tk.MustQuery(showSQL) - c.Check(res.Rows(), HasLen, len(globalVars)) + require.Len(t, res.Rows(), len(globalVars)) showSQL = "show global variables where variable_name in('" + globalVarsStr + "')" res = tk.MustQuery(showSQL) - c.Check(res.Rows(), HasLen, len(globalVars)) + require.Len(t, res.Rows(), len(globalVars)) // Test a known hidden variable. res = tk.MustQuery("show variables like '" + variable.TiDBPartitionPruneMode + "'") - c.Check(res.Rows(), HasLen, 0) + require.Len(t, res.Rows(), 0) res = tk.MustQuery("show global variables like '" + variable.TiDBPartitionPruneMode + "'") - c.Check(res.Rows(), HasLen, 0) + require.Len(t, res.Rows(), 0) // Test Hidden tx_read_ts res = tk.MustQuery("show variables like '%tx_read_ts'") - c.Check(res.Rows(), HasLen, 0) - // Test Hidden tidb_enable_streaming - res = tk.MustQuery("show variables like '%tidb_enable_streaming%';") - c.Check(res.Rows(), HasLen, 0) + require.Len(t, res.Rows(), 0) + + // Test versions' related variables + res = tk.MustQuery("show variables like 'version%'") + for _, row := range res.Rows() { + line := fmt.Sprint(row) + if strings.HasPrefix(line, "version ") { + require.Equal(t, mysql.ServerVersion, line[len("version "):]) + } else if strings.HasPrefix(line, "version_comment ") { + require.Equal(t, variable.GetSysVar(variable.VersionComment), line[len("version_comment "):]) + } + } + + // Test case insensitive case for show session variables + tk.MustExec("SET @@SQL_MODE='NO_BACKSLASH_ESCAPES'") + tk.MustQuery("SHOW SESSION VARIABLES like 'sql_mode'").Check( + testkit.RowsWithSep("|", "sql_mode|NO_BACKSLASH_ESCAPES")) + tk.MustQuery("SHOW SESSION VARIABLES like 'SQL_MODE'").Check( + testkit.RowsWithSep("|", "sql_mode|NO_BACKSLASH_ESCAPES")) } -func (s *testSuite5) TestIssue19507(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue19507(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("CREATE TABLE t2(a int primary key, b int unique, c int not null, unique index (c));") tk.MustQuery("SHOW INDEX IN t2;").Check( - testutil.RowsWithSep("|", "t2|0|PRIMARY|1|a|A|0||||BTREE|||YES||YES", + testkit.RowsWithSep("|", "t2|0|PRIMARY|1|a|A|0||||BTREE|||YES||YES", "t2|0|c|1|c|A|0||||BTREE|||YES||NO", "t2|0|b|1|b|A|0|||YES|BTREE|||YES||NO")) tk.MustExec("CREATE INDEX t2_b_c_index ON t2 (b, c);") tk.MustExec("CREATE INDEX t2_c_b_index ON t2 (c, b);") tk.MustQuery("SHOW INDEX IN t2;").Check( - testutil.RowsWithSep("|", "t2|0|PRIMARY|1|a|A|0||||BTREE|||YES||YES", + testkit.RowsWithSep("|", "t2|0|PRIMARY|1|a|A|0||||BTREE|||YES||YES", "t2|0|c|1|c|A|0||||BTREE|||YES||NO", "t2|0|b|1|b|A|0|||YES|BTREE|||YES||NO", "t2|1|t2_b_c_index|1|b|A|0|||YES|BTREE|||YES||NO", @@ -1592,8 +1635,10 @@ func (s *testSuite5) TestIssue19507(c *C) { } // TestShowPerformanceSchema tests for Issue 19231 -func (s *testSuite5) TestShowPerformanceSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowPerformanceSchema(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Ideally we should create a new performance_schema table here with indices that we run the tests on. // However, its not possible to create a new performance_schema table since its a special in memory table. // Instead the test below uses the default index on the table. @@ -1602,21 +1647,25 @@ func (s *testSuite5) TestShowPerformanceSchema(c *C) { "events_statements_summary_by_digest 0 SCHEMA_NAME 2 DIGEST A 0 YES BTREE YES NO")) } -func (s *testSuite5) TestShowCreatePlacementPolicy(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowCreatePlacementPolicy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE PLACEMENT POLICY xyz PRIMARY_REGION='us-east-1' REGIONS='us-east-1,us-east-2' FOLLOWERS=4") tk.MustQuery("SHOW CREATE PLACEMENT POLICY xyz").Check(testkit.Rows("xyz CREATE PLACEMENT POLICY `xyz` PRIMARY_REGION=\"us-east-1\" REGIONS=\"us-east-1,us-east-2\" FOLLOWERS=4")) // non existent policy err := tk.QueryToErr("SHOW CREATE PLACEMENT POLICY doesnotexist") - c.Assert(err.Error(), Equals, infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs("doesnotexist").Error()) + require.Equal(t, infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs("doesnotexist").Error(), err.Error()) // alter and try second example tk.MustExec("ALTER PLACEMENT POLICY xyz FOLLOWERS=4") tk.MustQuery("SHOW CREATE PLACEMENT POLICY xyz").Check(testkit.Rows("xyz CREATE PLACEMENT POLICY `xyz` FOLLOWERS=4")) tk.MustExec("DROP PLACEMENT POLICY xyz") } -func (s *testSuite5) TestShowTemporaryTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowTemporaryTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create global temporary table t1 (id int) on commit delete rows") tk.MustExec("create global temporary table t3 (i int primary key, j int) on commit delete rows") @@ -1674,3 +1723,111 @@ func (s *testSuite5) TestShowTemporaryTable(c *C) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=2" tk.MustQuery("show create table t7").Check(testkit.Rows("t7 " + expect)) } + +func TestShowCachedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (id int)") + tk.MustExec("alter table t1 cache") + tk.MustQuery("show create table t1").Check( + testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /* CACHED ON */")) + tk.MustQuery("select create_options from information_schema.tables where table_schema = 'test' and table_name = 't1'").Check( + testkit.Rows("cached=on")) + + tk.MustExec("alter table t1 nocache") + tk.MustQuery("show create table t1").Check( + testkit.Rows("t1 CREATE TABLE `t1` (\n" + + " `id` int(11) DEFAULT NULL\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) + tk.MustQuery("select create_options from information_schema.tables where table_schema = 'test' and table_name = 't1'").Check( + testkit.Rows("")) +} + +func TestShowBindingCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int, b int)") + tk.MustExec(`set global tidb_mem_quota_binding_cache = 1`) + tk.MustQuery("select @@global.tidb_mem_quota_binding_cache").Check(testkit.Rows("1")) + tk.MustExec("admin reload bindings;") + res := tk.MustQuery("show global bindings") + require.Equal(t, 0, len(res.Rows())) + + tk.MustExec("create global binding for select * from t using select * from t") + res = tk.MustQuery("show global bindings") + require.Equal(t, 0, len(res.Rows())) + + tk.MustExec(`set global tidb_mem_quota_binding_cache = default`) + tk.MustQuery("select @@global.tidb_mem_quota_binding_cache").Check(testkit.Rows("67108864")) + tk.MustExec("admin reload bindings") + res = tk.MustQuery("show global bindings") + require.Equal(t, 1, len(res.Rows())) + + tk.MustExec("create global binding for select * from t where a > 1 using select * from t where a > 1") + res = tk.MustQuery("show global bindings") + require.Equal(t, 2, len(res.Rows())) +} + +func TestShowBindingCacheStatus(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "0 0 0 Bytes 64 MB")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, index idx_a(a), index idx_b(b))") + result := tk.MustQuery("show global bindings") + rows := result.Rows() + require.Equal(t, len(rows), 0) + tk.MustExec("create global binding for select * from t using select * from t") + + result = tk.MustQuery("show global bindings") + rows = result.Rows() + require.Equal(t, len(rows), 1) + + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "1 1 159 Bytes 64 MB")) + + tk.MustExec(`set global tidb_mem_quota_binding_cache = 250`) + tk.MustQuery(`select @@global.tidb_mem_quota_binding_cache`).Check(testkit.Rows("250")) + tk.MustExec("admin reload bindings;") + tk.MustExec("create global binding for select * from t where a > 1 using select * from t where a > 1") + result = tk.MustQuery("show global bindings") + rows = result.Rows() + require.Equal(t, len(rows), 1) + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "1 2 187 Bytes 250 Bytes")) + + tk.MustExec("drop global binding for select * from t where a > 1") + result = tk.MustQuery("show global bindings") + rows = result.Rows() + require.Equal(t, len(rows), 0) + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "0 1 0 Bytes 250 Bytes")) + + tk.MustExec("admin reload bindings") + result = tk.MustQuery("show global bindings") + rows = result.Rows() + require.Equal(t, len(rows), 1) + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "1 1 159 Bytes 250 Bytes")) + + tk.MustExec("create global binding for select * from t using select * from t use index(idx_a)") + + result = tk.MustQuery("show global bindings") + rows = result.Rows() + require.Equal(t, len(rows), 1) + + tk.MustQuery("show binding_cache status").Check(testkit.Rows( + "1 1 198 Bytes 250 Bytes")) +} diff --git a/executor/simple.go b/executor/simple.go index 82e941eca143f..8fbe8ee40498e 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -42,6 +42,7 @@ import ( "github.com/pingcap/tidb/privilege" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" @@ -160,7 +161,7 @@ func (e *SimpleExec) Next(ctx context.Context, req *chunk.Chunk) (err error) { case *ast.ShutdownStmt: err = e.executeShutdown(x) case *ast.AdminStmt: - err = e.executeAdminReloadStatistics(x) + err = e.executeAdmin(x) } e.done = true return err @@ -785,6 +786,12 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm users := make([]*auth.UserIdentity, 0, len(s.Specs)) for _, spec := range s.Specs { + if len(spec.User.Username) > auth.UserNameMaxLength { + return ErrWrongStringLength.GenWithStackByArgs(spec.User.Username, "user name", auth.UserNameMaxLength) + } + if len(spec.User.Hostname) > auth.HostNameMaxLength { + return ErrWrongStringLength.GenWithStackByArgs(spec.User.Hostname, "host name", auth.HostNameMaxLength) + } if len(users) > 0 { sqlexec.MustFormatSQL(sql, ",") } @@ -966,25 +973,17 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt) if !ok { return errors.Trace(ErrPasswordFormat) } - stmt, err := exec.ParseWithParams(ctx, + _, _, err := exec.ExecRestrictedSQL(ctx, nil, `UPDATE %n.%n SET authentication_string=%?, plugin=%? WHERE Host=%? and User=%?;`, mysql.SystemDB, mysql.UserTable, pwd, spec.AuthOpt.AuthPlugin, strings.ToLower(spec.User.Hostname), spec.User.Username, ) - if err != nil { - return err - } - _, _, err = exec.ExecRestrictedStmt(ctx, stmt) if err != nil { failedUsers = append(failedUsers, spec.User.String()) } } if len(privData) > 0 { - stmt, err := exec.ParseWithParams(ctx, "INSERT INTO %n.%n (Host, User, Priv) VALUES (%?,%?,%?) ON DUPLICATE KEY UPDATE Priv = values(Priv)", mysql.SystemDB, mysql.GlobalPrivTable, spec.User.Hostname, spec.User.Username, string(hack.String(privData))) - if err != nil { - return err - } - _, _, err = exec.ExecRestrictedStmt(ctx, stmt) + _, _, err := exec.ExecRestrictedSQL(ctx, nil, "INSERT INTO %n.%n (Host, User, Priv) VALUES (%?,%?,%?) ON DUPLICATE KEY UPDATE Priv = values(Priv)", mysql.SystemDB, mysql.GlobalPrivTable, spec.User.Hostname, spec.User.Username, string(hack.String(privData))) if err != nil { failedUsers = append(failedUsers, spec.User.String()) } @@ -1088,6 +1087,12 @@ func (e *SimpleExec) executeRenameUser(s *ast.RenameUserStmt) error { for _, userToUser := range s.UserToUsers { oldUser, newUser := userToUser.OldUser, userToUser.NewUser + if len(newUser.Username) > auth.UserNameMaxLength { + return ErrWrongStringLength.GenWithStackByArgs(newUser.Username, "user name", auth.UserNameMaxLength) + } + if len(newUser.Hostname) > auth.HostNameMaxLength { + return ErrWrongStringLength.GenWithStackByArgs(newUser.Hostname, "host name", auth.HostNameMaxLength) + } exists, err := userExistsInternal(sqlExecutor, oldUser.Username, oldUser.Hostname) if err != nil { return err @@ -1358,11 +1363,7 @@ func (e *SimpleExec) executeDropUser(ctx context.Context, s *ast.DropUserStmt) e func userExists(ctx context.Context, sctx sessionctx.Context, name string, host string) (bool, error) { exec := sctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, `SELECT * FROM %n.%n WHERE User=%? AND Host=%?;`, mysql.SystemDB, mysql.UserTable, name, strings.ToLower(host)) - if err != nil { - return false, err - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmt) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, `SELECT * FROM %n.%n WHERE User=%? AND Host=%?;`, mysql.SystemDB, mysql.UserTable, name, strings.ToLower(host)) if err != nil { return false, err } @@ -1441,11 +1442,7 @@ func (e *SimpleExec) executeSetPwd(ctx context.Context, s *ast.SetPwdStmt) error // update mysql.user exec := e.ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(ctx, `UPDATE %n.%n SET authentication_string=%? WHERE User=%? AND Host=%?;`, mysql.SystemDB, mysql.UserTable, pwd, u, strings.ToLower(h)) - if err != nil { - return err - } - _, _, err = exec.ExecRestrictedStmt(ctx, stmt) + _, _, err = exec.ExecRestrictedSQL(ctx, nil, `UPDATE %n.%n SET authentication_string=%? WHERE User=%? AND Host=%?;`, mysql.SystemDB, mysql.UserTable, pwd, u, strings.ToLower(h)) if err != nil { return err } @@ -1538,8 +1535,7 @@ func killRemoteConn(ctx context.Context, sctx sessionctx.Context, connID *util.G if err != nil { return err } - - resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars, sctx.GetSessionVars().StmtCtx.MemTracker, false, nil) + resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars, &kv.ClientSendOption{}) if resp == nil { err := errors.New("client returns nil response") return err @@ -1659,6 +1655,16 @@ func asyncDelayShutdown(p *os.Process, delay time.Duration) { } } +func (e *SimpleExec) executeAdmin(s *ast.AdminStmt) error { + switch s.Tp { + case ast.AdminReloadStatistics: + return e.executeAdminReloadStatistics(s) + case ast.AdminFlushPlanCache: + return e.executeAdminFlushPlanCache(s) + } + return nil +} + func (e *SimpleExec) executeAdminReloadStatistics(s *ast.AdminStmt) error { if s.Tp != ast.AdminReloadStatistics { return errors.New("This AdminStmt is not ADMIN RELOAD STATS_EXTENDED") @@ -1668,3 +1674,25 @@ func (e *SimpleExec) executeAdminReloadStatistics(s *ast.AdminStmt) error { } return domain.GetDomain(e.ctx).StatsHandle().ReloadExtendedStatistics() } + +func (e *SimpleExec) executeAdminFlushPlanCache(s *ast.AdminStmt) error { + if s.Tp != ast.AdminFlushPlanCache { + return errors.New("This AdminStmt is not ADMIN FLUSH PLAN_CACHE") + } + if s.StatementScope == ast.StatementScopeGlobal { + return errors.New("Do not support the 'admin flush global scope.'") + } + if !plannercore.PreparedPlanCacheEnabled() { + e.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.New("The plan cache is disable. So there no need to flush the plan cache")) + return nil + } + now := types.NewTime(types.FromGoTime(time.Now().In(e.ctx.GetSessionVars().StmtCtx.TimeZone)), mysql.TypeTimestamp, 3) + e.ctx.GetSessionVars().LastUpdateTime4PC = now + e.ctx.PreparedPlanCache().DeleteAll() + if s.StatementScope == ast.StatementScopeInstance { + // Record the timestamp. When other sessions want to use the plan cache, + // it will check the timestamp first to decide whether the plan cache should be flushed. + domain.GetDomain(e.ctx).SetExpiredTimeStamp4PC(now) + } + return nil +} diff --git a/executor/simple_test.go b/executor/simple_test.go index b8dc034076ec7..8cb304e2ef43b 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -17,11 +17,10 @@ package executor_test import ( "context" "strconv" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" @@ -32,40 +31,22 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/israce" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -func (s *testSuite3) TestCharsetDatabase(c *C) { - tk := testkit.NewTestKit(c, s.store) - testSQL := `create database if not exists cd_test_utf8 CHARACTER SET utf8 COLLATE utf8_bin;` - tk.MustExec(testSQL) - - testSQL = `create database if not exists cd_test_latin1 CHARACTER SET latin1 COLLATE latin1_swedish_ci;` - tk.MustExec(testSQL) - - testSQL = `use cd_test_utf8;` - tk.MustExec(testSQL) - tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows("utf8")) - tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows("utf8_bin")) - - testSQL = `use cd_test_latin1;` - tk.MustExec(testSQL) - tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows("latin1")) - tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows("latin1_swedish_ci")) -} - -func (s *testSuite3) TestDo(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("do 1, @a:=1") tk.MustQuery("select @a").Check(testkit.Rows("1")) tk.MustExec("use test") tk.MustExec("create table t (i int)") tk.MustExec("insert into t values (1)") - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") tk.MustQuery("select * from t").Check(testkit.Rows("1")) tk.MustExec("do @a := (select * from t where i = 1)") @@ -73,81 +54,100 @@ func (s *testSuite3) TestDo(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("1", "2")) } -func (s *testSuite3) TestSetRoleAllCorner(c *C) { +func TestDoWithAggFunc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("DO sum(1)") + tk.MustExec("DO avg(@e+@f)") + tk.MustExec("DO GROUP_CONCAT(NULLIF(ELT(1, @e), 2.0) ORDER BY 1)") +} + +func TestSetRoleAllCorner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // For user with no role, `SET ROLE ALL` should active // a empty slice, rather than nil. - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("create user set_role_all") - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "set_role_all", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "set_role_all", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `set role all`) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, `select current_role`) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testSuite3) TestCreateRole(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateRole(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user testCreateRole;") tk.MustExec("grant CREATE USER on *.* to testCreateRole;") - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `create role test_create_role;`) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("revoke CREATE USER on *.* from testCreateRole;") tk.MustExec("drop role test_create_role;") tk.MustExec("grant CREATE ROLE on *.* to testCreateRole;") _, err = se.Execute(ctx, `create role test_create_role;`) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop role test_create_role;") _, err = se.Execute(ctx, `create user test_create_role;`) - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("drop user testCreateRole;") } -func (s *testSuite3) TestDropRole(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropRole(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user testCreateRole;") tk.MustExec("create user test_create_role;") tk.MustExec("grant CREATE USER on *.* to testCreateRole;") - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `drop role test_create_role;`) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("revoke CREATE USER on *.* from testCreateRole;") tk.MustExec("create role test_create_role;") tk.MustExec("grant DROP ROLE on *.* to testCreateRole;") _, err = se.Execute(ctx, `drop role test_create_role;`) - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("create user test_create_role;") _, err = se.Execute(ctx, `drop user test_create_role;`) - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("drop user testCreateRole;") tk.MustExec("drop user test_create_role;") } -func (s *testSuite3) TestTransaction(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTransaction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("begin") - ctx := tk.Se.(sessionctx.Context) - c.Assert(inTxn(ctx), IsTrue) + ctx := tk.Session() + require.True(t, inTxn(ctx)) tk.MustExec("commit") - c.Assert(inTxn(ctx), IsFalse) + require.False(t, inTxn(ctx)) tk.MustExec("begin") - c.Assert(inTxn(ctx), IsTrue) + require.True(t, inTxn(ctx)) tk.MustExec("rollback") - c.Assert(inTxn(ctx), IsFalse) + require.False(t, inTxn(ctx)) // Test that begin implicitly commits previous transaction. tk.MustExec("use test") @@ -170,8 +170,10 @@ func inTxn(ctx sessionctx.Context) bool { return (ctx.GetSessionVars().Status & mysql.ServerStatusInTrans) > 0 } -func (s *testSuite6) TestRole(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRole(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Make sure user test not in mysql.User. result := tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test" and Host="localhost"`) result.Check(nil) @@ -191,7 +193,7 @@ func (s *testSuite6) TestRole(c *C) { dropUserSQL := `DROP ROLE IF EXISTS 'test'@'localhost' ;` _, err := tk.Exec(dropUserSQL) - c.Check(err, IsNil) + require.NoError(t, err) result = tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test" and Host="localhost"`) result.Check(nil) @@ -214,10 +216,10 @@ func (s *testSuite6) TestRole(c *C) { grantRoleSQL = `GRANT 'r_1'@'localhost' TO 'r_3'@'localhost', 'r_4'@'localhost';` _, err = tk.Exec(grantRoleSQL) - c.Check(err, NotNil) + require.Error(t, err) // Test grant role for current_user(); - sessionVars := tk.Se.GetSessionVars() + sessionVars := tk.Session().GetSessionVars() originUser := sessionVars.User sessionVars.User = &auth.UserIdentity{Username: "root", Hostname: "localhost", AuthUsername: "root", AuthHostname: "%"} tk.MustExec("grant 'r_1'@'localhost' to current_user();") @@ -243,13 +245,13 @@ func (s *testSuite6) TestRole(c *C) { tk.MustExec("flush privileges") tk.MustExec("SET DEFAULT ROLE r_1, r_2 TO root") _, err = tk.Exec("revoke test@localhost, r_1 from root;") - c.Check(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("revoke `r_2`@`%` from root, u_2;") - c.Check(err, NotNil) + require.Error(t, err) _, err = tk.Exec("revoke `r_2`@`%` from root;") - c.Check(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("revoke `r_1`@`%` from root;") - c.Check(err, IsNil) + require.NoError(t, err) result = tk.MustQuery(`SELECT * FROM mysql.default_roles WHERE DEFAULT_ROLE_USER="test" and DEFAULT_ROLE_HOST="localhost"`) result.Check(nil) result = tk.MustQuery(`SELECT * FROM mysql.default_roles WHERE USER="root" and HOST="%"`) @@ -257,42 +259,46 @@ func (s *testSuite6) TestRole(c *C) { dropRoleSQL = `DROP ROLE 'test'@'localhost', r_1, r_2;` tk.MustExec(dropRoleSQL) - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session().(sessionctx.Context) ctx.GetSessionVars().User = &auth.UserIdentity{Username: "test1", Hostname: "localhost"} - c.Assert(tk.ExecToErr("SET ROLE role1, role2"), NotNil) + require.NotNil(t, tk.ExecToErr("SET ROLE role1, role2")) tk.MustExec("SET ROLE ALL") tk.MustExec("SET ROLE ALL EXCEPT role1, role2") tk.MustExec("SET ROLE DEFAULT") tk.MustExec("SET ROLE NONE") } -func (s *testSuite3) TestRoleAdmin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRoleAdmin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER 'testRoleAdmin';") tk.MustExec("CREATE ROLE 'targetRole';") // Create a new session. - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "testRoleAdmin", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "testRoleAdmin", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "GRANT `targetRole` TO `testRoleAdmin`;") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustExec("GRANT SUPER ON *.* TO `testRoleAdmin`;") _, err = se.Execute(ctx, "GRANT `targetRole` TO `testRoleAdmin`;") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, "REVOKE `targetRole` FROM `testRoleAdmin`;") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("DROP USER 'testRoleAdmin';") tk.MustExec("DROP ROLE 'targetRole';") } -func (s *testSuite3) TestDefaultRole(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDefaultRole(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) createRoleSQL := `CREATE ROLE r_1, r_2, r_3, u_1;` tk.MustExec(createRoleSQL) @@ -304,36 +310,36 @@ func (s *testSuite3) TestDefaultRole(c *C) { setRoleSQL := `SET DEFAULT ROLE r_3 TO u_1;` _, err := tk.Exec(setRoleSQL) - c.Check(err, NotNil) + require.Error(t, err) setRoleSQL = `SET DEFAULT ROLE r_1 TO u_1000;` _, err = tk.Exec(setRoleSQL) - c.Check(err, NotNil) + require.Error(t, err) setRoleSQL = `SET DEFAULT ROLE r_1, r_3 TO u_1;` _, err = tk.Exec(setRoleSQL) - c.Check(err, NotNil) + require.Error(t, err) setRoleSQL = `SET DEFAULT ROLE r_1 TO u_1;` _, err = tk.Exec(setRoleSQL) - c.Check(err, IsNil) + require.NoError(t, err) result := tk.MustQuery(`SELECT DEFAULT_ROLE_USER FROM mysql.default_roles WHERE USER="u_1"`) result.Check(testkit.Rows("r_1")) setRoleSQL = `SET DEFAULT ROLE r_2 TO u_1;` _, err = tk.Exec(setRoleSQL) - c.Check(err, IsNil) + require.NoError(t, err) result = tk.MustQuery(`SELECT DEFAULT_ROLE_USER FROM mysql.default_roles WHERE USER="u_1"`) result.Check(testkit.Rows("r_2")) setRoleSQL = `SET DEFAULT ROLE ALL TO u_1;` _, err = tk.Exec(setRoleSQL) - c.Check(err, IsNil) + require.NoError(t, err) result = tk.MustQuery(`SELECT DEFAULT_ROLE_USER FROM mysql.default_roles WHERE USER="u_1"`) result.Check(testkit.Rows("r_1", "r_2")) setRoleSQL = `SET DEFAULT ROLE NONE TO u_1;` _, err = tk.Exec(setRoleSQL) - c.Check(err, IsNil) + require.NoError(t, err) result = tk.MustQuery(`SELECT DEFAULT_ROLE_USER FROM mysql.default_roles WHERE USER="u_1"`) result.Check(nil) @@ -341,21 +347,25 @@ func (s *testSuite3) TestDefaultRole(c *C) { tk.MustExec(dropRoleSQL) } -func (s *testSuite7) TestSetDefaultRoleAll(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetDefaultRoleAll(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user test_all;") - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "test_all", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "test_all", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "set default role all to test_all;") - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testSuite7) TestUser(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUser(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // Make sure user test not in mysql.User. result := tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test" and Host="localhost"`) result.Check(nil) @@ -374,7 +384,7 @@ func (s *testSuite7) TestUser(c *C) { tk.MustGetErrCode(createUserSQL, mysql.ErrCannotUser) createUserSQL = `CREATE USER IF NOT EXISTS 'test'@'localhost' IDENTIFIED BY '123';` tk.MustExec(createUserSQL) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|3163|User 'test'@'localhost' already exists.")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|3163|User 'test'@'localhost' already exists.")) dropUserSQL := `DROP USER IF EXISTS 'test'@'localhost' ;` tk.MustExec(dropUserSQL) // Create user test. @@ -406,22 +416,23 @@ func (s *testSuite7) TestUser(c *C) { alterUserSQL = `ALTER USER IF EXISTS 'test2'@'localhost' IDENTIFIED BY '222', 'test_not_exist'@'localhost' IDENTIFIED BY '1';` tk.MustExec(alterUserSQL) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|3162|User 'test_not_exist'@'localhost' does not exist.")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|3162|User 'test_not_exist'@'localhost' does not exist.")) result = tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test2" and Host="localhost"`) result.Check(testkit.Rows(auth.EncodePassword("222"))) alterUserSQL = `ALTER USER IF EXISTS'test_not_exist'@'localhost' IDENTIFIED BY '1', 'test3'@'localhost' IDENTIFIED BY '333';` tk.MustExec(alterUserSQL) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|3162|User 'test_not_exist'@'localhost' does not exist.")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|3162|User 'test_not_exist'@'localhost' does not exist.")) result = tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test3" and Host="localhost"`) result.Check(testkit.Rows(auth.EncodePassword("333"))) // Test alter user user(). alterUserSQL = `ALTER USER USER() IDENTIFIED BY '1';` _, err := tk.Exec(alterUserSQL) - c.Check(terror.ErrorEqual(err, errors.New("Session user is empty")), IsTrue, Commentf("err %v", err)) - tk.Se, err = session.CreateSession4Test(s.store) - c.Check(err, IsNil) - ctx := tk.Se.(sessionctx.Context) + require.Truef(t, terror.ErrorEqual(err, errors.New("Session user is empty")), "err %v", err) + sess, err := session.CreateSession4Test(store) + require.NoError(t, err) + tk.SetSession(sess) + ctx := tk.Session().(sessionctx.Context) ctx.GetSessionVars().User = &auth.UserIdentity{Username: "test1", Hostname: "localhost", AuthHostname: "localhost"} tk.MustExec(alterUserSQL) result = tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="test1" and Host="localhost"`) @@ -434,7 +445,7 @@ func (s *testSuite7) TestUser(c *C) { tk.MustExec(createUserSQL) dropUserSQL = `DROP USER IF EXISTS 'test1'@'localhost', 'test2'@'localhost', 'test3'@'localhost' ;` tk.MustExec(dropUserSQL) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|3162|User test2@localhost does not exist.")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Note|3162|User test2@localhost does not exist.")) // Test negative cases without IF EXISTS. createUserSQL = `CREATE USER 'test1'@'localhost', 'test3'@'localhost';` @@ -454,7 +465,7 @@ func (s *testSuite7) TestUser(c *C) { // Test 'identified by password' createUserSQL = `CREATE USER 'test1'@'localhost' identified by password 'xxx';` _, err = tk.Exec(createUserSQL) - c.Assert(terror.ErrorEqual(executor.ErrPasswordFormat, err), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(executor.ErrPasswordFormat, err), "err %v", err) createUserSQL = `CREATE USER 'test1'@'localhost' identified by password '*3D56A309CD04FA2EEF181462E59011F075C89548';` tk.MustExec(createUserSQL) dropUserSQL = `DROP USER 'test1'@'localhost';` @@ -462,7 +473,7 @@ func (s *testSuite7) TestUser(c *C) { // Test drop user meet error _, err = tk.Exec(dropUserSQL) - c.Assert(terror.ErrorEqual(err, executor.ErrCannotUser.GenWithStackByArgs("DROP USER", "")), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(err, executor.ErrCannotUser.GenWithStackByArgs("DROP USER", "")), "err %v", err) createUserSQL = `CREATE USER 'test1'@'localhost'` tk.MustExec(createUserSQL) @@ -471,7 +482,7 @@ func (s *testSuite7) TestUser(c *C) { dropUserSQL = `DROP USER 'test1'@'localhost', 'test2'@'localhost', 'test3'@'localhost';` _, err = tk.Exec(dropUserSQL) - c.Assert(terror.ErrorEqual(err, executor.ErrCannotUser.GenWithStackByArgs("DROP USER", "")), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(err, executor.ErrCannotUser.GenWithStackByArgs("DROP USER", "")), "err %v", err) // Close issue #17639 dropUserSQL = `DROP USER if exists test3@'%'` @@ -503,7 +514,7 @@ func (s *testSuite7) TestUser(c *C) { createUserSQL = `create user foo@localhost identified with 'foobar';` _, err = tk.Exec(createUserSQL) - c.Check(terror.ErrorEqual(err, executor.ErrPluginIsNotLoaded), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(err, executor.ErrPluginIsNotLoaded), "err %v", err) tk.MustExec(`create user joan;`) tk.MustExec(`create user sally;`) @@ -516,8 +527,7 @@ func (s *testSuite7) TestUser(c *C) { tk.MustExec(`grant qa to consultants;`) tk.MustExec("CREATE ROLE `engineering`@`US`;") tk.MustExec("create role `engineering`@`INDIA`;") - _, err = tk.Exec("grant `engineering`@`US` TO `engineering`@`INDIA`;") - c.Check(err, IsNil) + tk.MustExec("grant `engineering`@`US` TO `engineering`@`INDIA`;") tk.MustQuery("select user,host from mysql.user where user='engineering' and host = 'india'"). Check(testkit.Rows("engineering india")) @@ -531,8 +541,10 @@ func (s *testSuite7) TestUser(c *C) { tk.MustQuery("select user from mysql.user where user='engineering' and host = 'us'").Check(testkit.Rows()) } -func (s *testSuite3) TestSetPwd(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetPwd(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) createUserSQL := `CREATE USER 'testpwd'@'localhost' IDENTIFIED BY '';` tk.MustExec(createUserSQL) @@ -553,14 +565,15 @@ func (s *testSuite3) TestSetPwd(c *C) { setPwdSQL := `SET PASSWORD = 'pwd'` // Session user is empty. _, err := tk.Exec(setPwdSQL) - c.Check(err, NotNil) - tk.Se, err = session.CreateSession4Test(s.store) - c.Check(err, IsNil) - ctx := tk.Se.(sessionctx.Context) + require.Error(t, err) + sess, err := session.CreateSession4Test(store) + require.NoError(t, err) + tk.SetSession(sess) + ctx := tk.Session().(sessionctx.Context) ctx.GetSessionVars().User = &auth.UserIdentity{Username: "testpwd1", Hostname: "localhost", AuthUsername: "testpwd1", AuthHostname: "localhost"} // Session user doesn't exist. _, err = tk.Exec(setPwdSQL) - c.Check(terror.ErrorEqual(err, executor.ErrPasswordNoMatch), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(err, executor.ErrPasswordNoMatch), "err %v", err) // normal ctx.GetSessionVars().User = &auth.UserIdentity{Username: "testpwd", Hostname: "localhost", AuthUsername: "testpwd", AuthHostname: "localhost"} tk.MustExec(setPwdSQL) @@ -569,13 +582,15 @@ func (s *testSuite3) TestSetPwd(c *C) { } -func (s *testSuite3) TestKillStmt(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestKillStmt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sm := &mockSessionManager{ serverID: 0, } - tk.Se.SetSessionManager(sm) + tk.Session().SetSessionManager(sm) tk.MustExec("kill 1") result := tk.MustQuery("show warnings") result.Check(testkit.Rows("Warning 1105 Invalid operation. Please use 'KILL TIDB [CONNECTION | QUERY] connectionID' instead")) @@ -602,7 +617,7 @@ func (s *testSuite3) TestKillStmt(c *C) { result.Check(testkit.Rows("Warning 1105 Parse ConnectionID failed: Unexpected connectionID excceeds int64")) // local kill - connID := util.GlobalConnID{Is64bits: true, ServerID: 1, LocalConnID: 101} + connID := util.NewGlobalConnID(1, true) tk.MustExec("kill " + strconv.FormatUint(connID.ID(), 10)) result = tk.MustQuery("show warnings") result.Check(testkit.Rows()) @@ -611,40 +626,40 @@ func (s *testSuite3) TestKillStmt(c *C) { // remote kill is tested in `tests/globalkilltest` } -func (s *testSuite3) TestFlushPrivileges(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestFlushPrivileges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`CREATE USER 'testflush'@'localhost' IDENTIFIED BY '';`) tk.MustExec(`UPDATE mysql.User SET Select_priv='Y' WHERE User="testflush" and Host="localhost"`) // Create a new session. - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "testflush", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "testflush", Hostname: "localhost"}, nil, nil)) ctx := context.Background() // Before flush. _, err = se.Execute(ctx, `SELECT authentication_string FROM mysql.User WHERE User="testflush" and Host="localhost"`) - c.Check(err, NotNil) + require.Error(t, err) tk.MustExec("FLUSH PRIVILEGES") // After flush. _, err = se.Execute(ctx, `SELECT authentication_string FROM mysql.User WHERE User="testflush" and Host="localhost"`) - c.Check(err, IsNil) + require.NoError(t, err) } -type testFlushSuite struct{} - -func (s *testFlushSuite) TestFlushPrivilegesPanic(c *C) { +func TestFlushPrivilegesPanic(t *testing.T) { // Run in a separate suite because this test need to set SkipGrantTable config. store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) + require.NoError(t, err) defer func() { err := store.Close() - c.Assert(err, IsNil) + require.NoError(t, err) }() defer config.RestoreFunc()() @@ -653,19 +668,18 @@ func (s *testFlushSuite) TestFlushPrivilegesPanic(c *C) { }) dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) + require.NoError(t, err) defer dom.Close() - tk := testkit.NewTestKit(c, store) + tk := testkit.NewTestKit(t, store) tk.MustExec("FLUSH PRIVILEGES") } -func (s *testSerialSuite) TestDropPartitionStats(c *C) { - if israce.RaceEnabled { - c.Skip("unstable, skip race test") - } +func TestDropPartitionStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() // Use the testSerialSuite to fix the unstable test - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec(`create database if not exists test_drop_gstats`) tk.MustExec("use test_drop_gstats") tk.MustExec("drop table if exists test_drop_gstats;") @@ -681,13 +695,13 @@ partition by range (a) ( tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("insert into test_drop_gstats values (1), (5), (11), (15), (21), (25)") - c.Assert(s.domain.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.Nil(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) checkPartitionStats := func(names ...string) { rs := tk.MustQuery("show stats_meta").Rows() - c.Assert(len(rs), Equals, len(names)) + require.Equal(t, len(names), len(rs)) for i := range names { - c.Assert(rs[i][2].(string), Equals, names[i]) + require.Equal(t, names[i], rs[i][2].(string)) } } @@ -698,8 +712,8 @@ partition by range (a) ( checkPartitionStats("global", "p1", "global") err := tk.ExecToErr("drop stats test_drop_gstats partition abcde") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "can not found the specified partition name abcde in the table definition") + require.Error(t, err) + require.Equal(t, "can not found the specified partition name abcde in the table definition", err.Error()) tk.MustExec("drop stats test_drop_gstats partition global") checkPartitionStats("global", "p1") @@ -714,40 +728,43 @@ partition by range (a) ( checkPartitionStats("global") } -func (s *testSuite3) TestDropStats(c *C) { - testKit := testkit.NewTestKit(c, s.store) +func TestDropStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") - do := domain.GetDomain(testKit.Se) - is := do.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() - h := do.StatsHandle() + h := dom.StatsHandle() h.Clear() testKit.MustExec("analyze table t") statsTbl := h.GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) testKit.MustExec("drop stats t") - c.Assert(h.Update(is), IsNil) + require.Nil(t, h.Update(is)) statsTbl = h.GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsTrue) + require.True(t, statsTbl.Pseudo) testKit.MustExec("analyze table t") statsTbl = h.GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) h.SetLease(1) testKit.MustExec("drop stats t") - c.Assert(h.Update(is), IsNil) + require.Nil(t, h.Update(is)) statsTbl = h.GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsTrue) + require.True(t, statsTbl.Pseudo) h.SetLease(0) } -func (s *testSuite3) TestDropStatsFromKV(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDropStatsFromKV(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (c1 varchar(20), c2 varchar(20))") tk.MustExec(`insert into t values("1","1"),("2","2"),("3","3"),("4","4")`) @@ -760,9 +777,9 @@ func (s *testSuite3) TestDropStatsFromKV(c *C) { tk.MustQuery("select hist_id from mysql.stats_histograms where table_id = " + tblID).Check( testkit.Rows("1", "2")) ret := tk.MustQuery("select hist_id, bucket_id from mysql.stats_buckets where table_id = " + tblID) - c.Assert(len(ret.Rows()) > 0, IsTrue) + require.True(t, len(ret.Rows()) > 0) ret = tk.MustQuery("select hist_id from mysql.stats_top_n where table_id = " + tblID) - c.Assert(len(ret.Rows()) > 0, IsTrue) + require.True(t, len(ret.Rows()) > 0) tk.MustExec("drop stats t") tk.MustQuery("select modify_count, count from mysql.stats_meta where table_id = " + tblID).Check( @@ -775,29 +792,35 @@ func (s *testSuite3) TestDropStatsFromKV(c *C) { testkit.Rows()) } -func (s *testSuite3) TestFlushTables(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestFlushTables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) _, err := tk.Exec("FLUSH TABLES") - c.Check(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("FLUSH TABLES WITH READ LOCK") - c.Check(err, NotNil) + require.Error(t, err) } -func (s *testSuite3) TestUseDB(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUseDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) _, err := tk.Exec("USE test") - c.Check(err, IsNil) + require.NoError(t, err) _, err = tk.Exec("USE ``") - c.Assert(terror.ErrorEqual(core.ErrNoDB, err), IsTrue, Commentf("err %v", err)) + require.Truef(t, terror.ErrorEqual(core.ErrNoDB, err), "err %v", err) } -func (s *testSuite3) TestStmtAutoNewTxn(c *C) { +func TestStmtAutoNewTxn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // Some statements are like DDL, they commit the previous txn automically. - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // Fix issue https://github.com/pingcap/tidb/issues/10705 @@ -825,104 +848,112 @@ func (s *testSuite3) TestStmtAutoNewTxn(c *C) { tk.MustQuery("select * from auto_new").Check(testkit.Rows("1", "2")) } -func (s *testSuite3) TestIssue9111(c *C) { +func TestIssue9111(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // CREATE USER / DROP USER fails if admin doesn't have insert privilege on `mysql.user` table. - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("create user 'user_admin'@'localhost';") tk.MustExec("grant create user on *.* to 'user_admin'@'localhost';") // Create a new session. - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "user_admin", Hostname: "localhost"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "user_admin", Hostname: "localhost"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `create user test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, `drop user test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) tk.MustExec("revoke create user on *.* from 'user_admin'@'localhost';") tk.MustExec("grant insert, delete on mysql.user to 'user_admin'@'localhost';") _, err = se.Execute(ctx, `create user test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, `drop user test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, `create role test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, `drop role test_create_user`) - c.Check(err, IsNil) + require.NoError(t, err) tk.MustExec("drop user 'user_admin'@'localhost';") } -func (s *testSuite3) TestRoleAtomic(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRoleAtomic(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create role r2;") _, err := tk.Exec("create role r1, r2, r3") - c.Check(err, NotNil) + require.Error(t, err) // Check atomic create role. result := tk.MustQuery(`SELECT user FROM mysql.User WHERE user in ('r1', 'r2', 'r3')`) result.Check(testkit.Rows("r2")) // Check atomic drop role. _, err = tk.Exec("drop role r1, r2, r3") - c.Check(err, NotNil) + require.Error(t, err) result = tk.MustQuery(`SELECT user FROM mysql.User WHERE user in ('r1', 'r2', 'r3')`) result.Check(testkit.Rows("r2")) tk.MustExec("drop role r2;") } -func (s *testSuite3) TestExtendedStatsPrivileges(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExtendedStatsPrivileges(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustExec("create user 'u1'@'%'") - se, err := session.CreateSession4Test(s.store) - c.Check(err, IsNil) + se, err := session.CreateSession4Test(store) + require.NoError(t, err) defer se.Close() - c.Assert(se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil), IsTrue) + require.True(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "set session tidb_enable_extended_stats = on") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, "alter table test.t add stats_extended s1 correlation(a,b)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]ALTER command denied to user 'u1'@'%' for table 't'") + require.Error(t, err) + require.Equal(t, "[planner:1142]ALTER command denied to user 'u1'@'%' for table 't'", err.Error()) tk.MustExec("grant alter on test.* to 'u1'@'%'") _, err = se.Execute(ctx, "alter table test.t add stats_extended s1 correlation(a,b)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]ADD STATS_EXTENDED command denied to user 'u1'@'%' for table 't'") + require.Error(t, err) + require.Equal(t, "[planner:1142]ADD STATS_EXTENDED command denied to user 'u1'@'%' for table 't'", err.Error()) tk.MustExec("grant select on test.* to 'u1'@'%'") _, err = se.Execute(ctx, "alter table test.t add stats_extended s1 correlation(a,b)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]ADD STATS_EXTENDED command denied to user 'u1'@'%' for table 'stats_extended'") + require.Error(t, err) + require.Equal(t, "[planner:1142]ADD STATS_EXTENDED command denied to user 'u1'@'%' for table 'stats_extended'", err.Error()) tk.MustExec("grant insert on mysql.stats_extended to 'u1'@'%'") _, err = se.Execute(ctx, "alter table test.t add stats_extended s1 correlation(a,b)") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(ctx, "alter table t drop stats_extended s1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1142]DROP STATS_EXTENDED command denied to user 'u1'@'%' for table 'stats_extended'") + require.Error(t, err) + require.Equal(t, "[planner:1142]DROP STATS_EXTENDED command denied to user 'u1'@'%' for table 'stats_extended'", err.Error()) tk.MustExec("grant update on mysql.stats_extended to 'u1'@'%'") _, err = se.Execute(ctx, "alter table t drop stats_extended s1") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop user 'u1'@'%'") } -func (s *testSuite3) TestIssue17247(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue17247(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user 'issue17247'") tk.MustExec("grant CREATE USER on *.* to 'issue17247'") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") - c.Assert(tk1.Se.Auth(&auth.UserIdentity{Username: "issue17247", Hostname: "%"}, nil, nil), IsTrue) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "issue17247", Hostname: "%"}, nil, nil)) tk1.MustExec("ALTER USER USER() IDENTIFIED BY 'xxx'") tk1.MustExec("ALTER USER CURRENT_USER() IDENTIFIED BY 'yyy'") tk1.MustExec("ALTER USER CURRENT_USER IDENTIFIED BY 'zzz'") @@ -930,38 +961,44 @@ func (s *testSuite3) TestIssue17247(c *C) { tk.MustExec("ALTER USER 'issue17247'@'%' IDENTIFIED BY PASSWORD '*B50FBDB37F1256824274912F2A1CE648082C3F1F'") // Wrong grammar _, err := tk1.Exec("ALTER USER USER() IDENTIFIED BY PASSWORD '*B50FBDB37F1256824274912F2A1CE648082C3F1F'") - c.Assert(err, NotNil) + require.Error(t, err) } // Close issue #23649. // See https://github.com/pingcap/tidb/issues/23649 -func (s *testSuite3) TestIssue23649(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23649(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("DROP USER IF EXISTS issue23649;") tk.MustExec("CREATE USER issue23649;") _, err := tk.Exec("GRANT bogusrole to issue23649;") - c.Assert(err.Error(), Equals, "[executor:3523]Unknown authorization ID `bogusrole`@`%`") + require.Equal(t, "[executor:3523]Unknown authorization ID `bogusrole`@`%`", err.Error()) _, err = tk.Exec("GRANT bogusrole to nonexisting;") - c.Assert(err.Error(), Equals, "[executor:3523]Unknown authorization ID `bogusrole`@`%`") + require.Equal(t, "[executor:3523]Unknown authorization ID `bogusrole`@`%`", err.Error()) } -func (s *testSuite3) TestSetCurrentUserPwd(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetCurrentUserPwd(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER issue28534;") defer func() { tk.MustExec("DROP USER IF EXISTS issue28534;") }() - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "issue28534", Hostname: "localhost", CurrentUser: true, AuthUsername: "issue28534", AuthHostname: "%"}, nil, nil), IsTrue) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "issue28534", Hostname: "localhost", CurrentUser: true, AuthUsername: "issue28534", AuthHostname: "%"}, nil, nil)) tk.MustExec(`SET PASSWORD FOR CURRENT_USER() = "43582eussi"`) - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) result := tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="issue28534"`) result.Check(testkit.Rows(auth.EncodePassword("43582eussi"))) } -func (s *testSuite3) TestShowGrantsAfterDropRole(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowGrantsAfterDropRole(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER u29473") defer tk.MustExec("DROP USER IF EXISTS u29473") @@ -969,17 +1006,19 @@ func (s *testSuite3) TestShowGrantsAfterDropRole(c *C) { tk.MustExec("GRANT r29473 TO u29473") tk.MustExec("GRANT CREATE USER ON *.* TO u29473") - tk.Se.Auth(&auth.UserIdentity{Username: "u29473", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "u29473", Hostname: "%"}, nil, nil) tk.MustExec("SET ROLE r29473") tk.MustExec("DROP ROLE r29473") tk.MustQuery("SHOW GRANTS").Check(testkit.Rows("GRANT CREATE USER ON *.* TO 'u29473'@'%'")) } -func (s *testSuite3) TestDropRoleAfterRevoke(c *C) { +func TestDropRoleAfterRevoke(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // issue 29781 - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) tk.MustExec("create role r1, r2, r3;") defer tk.MustExec("drop role if exists r1, r2, r3;") @@ -988,3 +1027,25 @@ func (s *testSuite3) TestDropRoleAfterRevoke(c *C) { tk.MustExec("revoke r1, r3 from root;") tk.MustExec("drop role r1;") } + +func TestUserWithSetNames(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("set names gbk;") + + tk.MustExec("drop user if exists '\xd2\xbb'@'localhost';") + tk.MustExec("create user '\xd2\xbb'@'localhost' IDENTIFIED BY '\xd2\xbb';") + + result := tk.MustQuery("SELECT authentication_string FROM mysql.User WHERE User='\xd2\xbb' and Host='localhost';") + result.Check(testkit.Rows(auth.EncodePassword("一"))) + + tk.MustExec("ALTER USER '\xd2\xbb'@'localhost' IDENTIFIED BY '\xd2\xbb\xd2\xbb';") + result = tk.MustQuery("SELECT authentication_string FROM mysql.User WHERE User='\xd2\xbb' and Host='localhost';") + result.Check(testkit.Rows(auth.EncodePassword("一一"))) + + tk.MustExec("RENAME USER '\xd2\xbb'@'localhost' to '\xd2\xbb'") + + tk.MustExec("drop user '\xd2\xbb';") +} diff --git a/executor/slow_query.go b/executor/slow_query.go index de5888f27d0de..789ced21c5b4d 100755 --- a/executor/slow_query.go +++ b/executor/slow_query.go @@ -26,7 +26,6 @@ import ( "sort" "strconv" "strings" - "sync" "sync/atomic" "time" @@ -413,7 +412,7 @@ func decomposeToSlowLogTasks(logs []slowLogBlock, num int) [][]string { func (e *slowQueryRetriever) parseSlowLog(ctx context.Context, sctx sessionctx.Context, reader *bufio.Reader, logNum int) { defer close(e.taskList) - var wg sync.WaitGroup + var wg util.WaitGroupWrapper offset := offset{offset: 0, length: 0} // To limit the num of go routine concurrent := sctx.GetSessionVars().Concurrency.DistSQLScanConcurrency() @@ -447,20 +446,29 @@ func (e *slowQueryRetriever) parseSlowLog(ctx context.Context, sctx sessionctx.C if e.stats != nil { e.stats.readFile += time.Since(startTime) } + failpoint.Inject("mockReadSlowLogSlow", func(val failpoint.Value) { + if val.(bool) { + signals := ctx.Value("signals").([]chan int) + signals[0] <- 1 + <-signals[1] + } + }) for i := range logs { log := logs[i] t := slowLogTask{} t.resultCh = make(chan parsedSlowLog, 1) start := offset - wg.Add(1) ch <- 1 - e.taskList <- t - go func() { - defer wg.Done() + select { + case <-ctx.Done(): + return + case e.taskList <- t: + } + wg.Run(func() { result, err := e.parseLog(ctx, sctx, log, start) e.sendParsedSlowLogCh(ctx, t, parsedSlowLog{result, err}) <-ch - }() + }) offset.offset = e.fileLine offset.length = 0 select { @@ -738,7 +746,7 @@ func getColumnValueFactoryByName(sctx sessionctx.Context, colName string, column return true, nil }, nil case variable.SlowLogPrepared, variable.SlowLogSucc, variable.SlowLogPlanFromCache, variable.SlowLogPlanFromBinding, - variable.SlowLogIsInternalStr, variable.SlowLogIsExplicitTxn, variable.SlowLogIsWriteCacheTable: + variable.SlowLogIsInternalStr, variable.SlowLogIsExplicitTxn, variable.SlowLogIsWriteCacheTable, variable.SlowLogHasMoreResults: return func(row []types.Datum, value string, tz *time.Location, checker *slowLogChecker) (valid bool, err error) { v, err := strconv.ParseBool(value) if err != nil { diff --git a/executor/slow_query_sql_test.go b/executor/slow_query_sql_test.go new file mode 100644 index 0000000000000..fc4593bbb20aa --- /dev/null +++ b/executor/slow_query_sql_test.go @@ -0,0 +1,173 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "fmt" + "math" + "os" + "testing" + + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/logutil" + "github.com/stretchr/testify/require" +) + +func TestSlowQueryWithoutSlowLog(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originCfg := config.GetGlobalConfig() + newCfg := *originCfg + newCfg.Log.SlowQueryFile = "tidb-slow-not-exist.log" + newCfg.Log.SlowThreshold = math.MaxUint64 + config.StoreGlobalConfig(&newCfg) + defer func() { + config.StoreGlobalConfig(originCfg) + }() + tk.MustQuery("select query from information_schema.slow_query").Check(testkit.Rows()) + tk.MustQuery("select query from information_schema.slow_query where time > '2020-09-15 12:16:39' and time < now()").Check(testkit.Rows()) +} + +func TestSlowQuerySensitiveQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originCfg := config.GetGlobalConfig() + newCfg := *originCfg + + f, err := os.CreateTemp("", "tidb-slow-*.log") + require.NoError(t, err) + require.NoError(t, f.Close()) + newCfg.Log.SlowQueryFile = f.Name() + config.StoreGlobalConfig(&newCfg) + defer func() { + tk.MustExec("set tidb_slow_log_threshold=300;") + config.StoreGlobalConfig(originCfg) + require.NoError(t, os.Remove(newCfg.Log.SlowQueryFile)) + }() + require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) + + tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) + tk.MustExec("set tidb_slow_log_threshold=0;") + tk.MustExec("drop user if exists user_sensitive;") + tk.MustExec("create user user_sensitive identified by '123456789';") + tk.MustExec("alter user 'user_sensitive'@'%' identified by 'abcdefg';") + tk.MustExec("set password for 'user_sensitive'@'%' = 'xyzuvw';") + tk.MustQuery("select query from `information_schema`.`slow_query` " + + "where (query like 'set password%' or query like 'create user%' or query like 'alter user%') " + + "and query like '%user_sensitive%' order by query;"). + Check(testkit.Rows( + "alter user {user_sensitive@% password = ***};", + "create user {user_sensitive@% password = ***};", + "set password for user user_sensitive@%;", + )) +} + +func TestSlowQueryPrepared(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originCfg := config.GetGlobalConfig() + newCfg := *originCfg + + f, err := os.CreateTemp("", "tidb-slow-*.log") + require.NoError(t, err) + require.NoError(t, f.Close()) + newCfg.Log.SlowQueryFile = f.Name() + config.StoreGlobalConfig(&newCfg) + defer func() { + tk.MustExec("set tidb_slow_log_threshold=300;") + tk.MustExec("set tidb_redact_log=0;") + config.StoreGlobalConfig(originCfg) + require.NoError(t, os.Remove(newCfg.Log.SlowQueryFile)) + }() + require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) + + tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) + tk.MustExec("set tidb_slow_log_threshold=0;") + tk.MustExec(`prepare mystmt1 from 'select sleep(?), 1';`) + tk.MustExec("SET @num = 0.01;") + tk.MustExec("execute mystmt1 using @num;") + tk.MustQuery("SELECT Query FROM `information_schema`.`slow_query` " + + "where query like 'select%sleep%' order by time desc limit 1"). + Check(testkit.Rows("select sleep(?), 1 [arguments: 0.01];")) + + tk.MustExec("set tidb_redact_log=1;") + tk.MustExec(`prepare mystmt2 from 'select sleep(?), 2';`) + tk.MustExec("execute mystmt2 using @num;") + tk.MustQuery("SELECT Query FROM `information_schema`.`slow_query` " + + "where query like 'select%sleep%' order by time desc limit 1"). + Check(testkit.Rows("select `sleep` ( ? ) , ?;")) +} + +func TestLogSlowLogIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + f, err := os.CreateTemp("", "tidb-slow-*.log") + require.NoError(t, err) + require.NoError(t, f.Close()) + + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.Log.SlowQueryFile = f.Name() + }) + require.NoError(t, logutil.InitLogger(config.GetGlobalConfig().Log.ToLogConfig())) + + tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) + tk.MustExec("use test") + tk.MustExec("create table t (a int, b int,index idx(a));") + tk.MustExec("set tidb_slow_log_threshold=0;") + tk.MustQuery("select * from t use index (idx) where a in (1) union select * from t use index (idx) where a in (2,3);") + tk.MustExec("set tidb_slow_log_threshold=300;") + tk.MustQuery("select index_names from `information_schema`.`slow_query` " + + "where query like 'select%union%' limit 1"). + Check(testkit.Rows("[t:idx]")) +} + +func TestSlowQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + f, err := os.CreateTemp("", "tidb-slow-*.log") + require.NoError(t, err) + _, err = f.WriteString(` +# Time: 2020-10-13T20:08:13.970563+08:00 +select * from t; +# Time: 2020-10-16T20:08:13.970563+08:00 +select * from t; +`) + require.NoError(t, err) + require.NoError(t, f.Close()) + executor.ParseSlowLogBatchSize = 1 + originCfg := config.GetGlobalConfig() + newCfg := *originCfg + newCfg.Log.SlowQueryFile = f.Name() + config.StoreGlobalConfig(&newCfg) + defer func() { + executor.ParseSlowLogBatchSize = 64 + config.StoreGlobalConfig(originCfg) + require.NoError(t, os.Remove(newCfg.Log.SlowQueryFile)) + }() + require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) + + tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) + tk.MustQuery("select count(*) from `information_schema`.`slow_query` where time > '2020-10-16 20:08:13' and time < '2020-10-16 21:08:13'").Check(testkit.Rows("1")) + tk.MustQuery("select count(*) from `information_schema`.`slow_query` where time > '2019-10-13 20:08:13' and time < '2020-10-16 21:08:13'").Check(testkit.Rows("2")) +} diff --git a/executor/slow_query_test.go b/executor/slow_query_test.go index 9828263402ac1..4396edc03892d 100644 --- a/executor/slow_query_test.go +++ b/executor/slow_query_test.go @@ -18,12 +18,13 @@ import ( "bufio" "bytes" "context" + "fmt" "os" + "runtime/pprof" "strings" "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/model" @@ -35,10 +36,10 @@ import ( "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mock" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func parseLog(retriever *slowQueryRetriever, sctx sessionctx.Context, reader *bufio.Reader, logNum int) ([][]types.Datum, error) { +func parseLog(retriever *slowQueryRetriever, sctx sessionctx.Context, reader *bufio.Reader) ([][]types.Datum, error) { retriever.taskList = make(chan slowLogTask, 100) ctx := context.Background() retriever.parseSlowLog(ctx, sctx, reader, 64) @@ -54,7 +55,7 @@ func parseLog(retriever *slowQueryRetriever, sctx sessionctx.Context, reader *bu } func newSlowQueryRetriever() (*slowQueryRetriever, error) { - newISBuilder, err := infoschema.NewBuilder(nil, nil, nil).InitWithDBInfos(nil, nil, nil, 0) + newISBuilder, err := infoschema.NewBuilder(nil, nil).InitWithDBInfos(nil, nil, nil, 0) if err != nil { return nil, err } @@ -66,18 +67,18 @@ func newSlowQueryRetriever() (*slowQueryRetriever, error) { return &slowQueryRetriever{outputCols: tbl.Meta().Columns}, nil } -func parseSlowLog(sctx sessionctx.Context, reader *bufio.Reader, logNum int) ([][]types.Datum, error) { +func parseSlowLog(sctx sessionctx.Context, reader *bufio.Reader) ([][]types.Datum, error) { retriever, err := newSlowQueryRetriever() if err != nil { return nil, err } // Ignore the error is ok for test. terror.Log(retriever.initialize(context.Background(), sctx)) - rows, err := parseLog(retriever, sctx, reader, logNum) + rows, err := parseLog(retriever, sctx, reader) return rows, err } -func (s *testExecSerialSuite) TestParseSlowLogPanic(c *C) { +func TestParseSlowLogPanic(t *testing.T) { slowLogStr := `# Time: 2019-04-28T15:24:04.309074+08:00 # Txn_start_ts: 405888132465033227 @@ -98,21 +99,21 @@ func (s *testExecSerialSuite) TestParseSlowLogPanic(c *C) { # Prev_stmt: update t set i = 1; use test; select * from t;` - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/errorMockParseSlowLogPanic", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/errorMockParseSlowLogPanic", `return(true)`)) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/errorMockParseSlowLogPanic"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/errorMockParseSlowLogPanic")) }() reader := bufio.NewReader(bytes.NewBufferString(slowLogStr)) loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) sctx := mock.NewContext() sctx.GetSessionVars().TimeZone = loc - _, err = parseSlowLog(sctx, reader, 64) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "panic test") + _, err = parseSlowLog(sctx, reader) + require.Error(t, err) + require.Equal(t, err.Error(), "panic test") } -func (s *testExecSuite) TestParseSlowLogFile(c *C) { +func TestParseSlowLogFile(t *testing.T) { slowLogStr := `# Time: 2019-04-28T15:24:04.309074+08:00 # Txn_start_ts: 405888132465033227 @@ -141,16 +142,16 @@ use test; select * from t;` reader := bufio.NewReader(bytes.NewBufferString(slowLogStr)) loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) ctx := mock.NewContext() ctx.GetSessionVars().TimeZone = loc - rows, err := parseSlowLog(ctx, reader, 64) - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, 1) + rows, err := parseSlowLog(ctx, reader) + require.NoError(t, err) + require.Len(t, rows, 1) recordString := "" for i, value := range rows[0] { str, err := value.ToString() - c.Assert(err, IsNil) + require.NoError(t, err) if i > 0 { recordString += "," } @@ -161,19 +162,19 @@ select * from t;` `0,0,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,0.38,0.021,0,0,0,1,637,0,10,10,10,10,100,,,1,42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772,t1:1,t2:2,` + `0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,65536,0,0,0,0,0,` + `Cop_backoff_regionMiss_total_times: 200 Cop_backoff_regionMiss_total_time: 0.2 Cop_backoff_regionMiss_max_time: 0.2 Cop_backoff_regionMiss_max_addr: 127.0.0.1 Cop_backoff_regionMiss_avg_time: 0.2 Cop_backoff_regionMiss_p90_time: 0.2 Cop_backoff_rpcPD_total_times: 200 Cop_backoff_rpcPD_total_time: 0.2 Cop_backoff_rpcPD_max_time: 0.2 Cop_backoff_rpcPD_max_addr: 127.0.0.1 Cop_backoff_rpcPD_avg_time: 0.2 Cop_backoff_rpcPD_p90_time: 0.2 Cop_backoff_rpcTiKV_total_times: 200 Cop_backoff_rpcTiKV_total_time: 0.2 Cop_backoff_rpcTiKV_max_time: 0.2 Cop_backoff_rpcTiKV_max_addr: 127.0.0.1 Cop_backoff_rpcTiKV_avg_time: 0.2 Cop_backoff_rpcTiKV_p90_time: 0.2,` + - `0,0,1,0,1,1,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` + + `0,0,1,0,1,1,0,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` + `update t set i = 1;,select * from t;` - c.Assert(expectRecordString, Equals, recordString) + require.Equal(t, expectRecordString, recordString) // Issue 20928 reader = bufio.NewReader(bytes.NewBufferString(slowLogStr)) - rows, err = parseSlowLog(ctx, reader, 1) - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, 1) + rows, err = parseSlowLog(ctx, reader) + require.NoError(t, err) + require.Len(t, rows, 1) recordString = "" for i, value := range rows[0] { str, err := value.ToString() - c.Assert(err, IsNil) + require.NoError(t, err) if i > 0 { recordString += "," } @@ -184,9 +185,9 @@ select * from t;` `0,0,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,0.38,0.021,0,0,0,1,637,0,10,10,10,10,100,,,1,42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772,t1:1,t2:2,` + `0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,65536,0,0,0,0,0,` + `Cop_backoff_regionMiss_total_times: 200 Cop_backoff_regionMiss_total_time: 0.2 Cop_backoff_regionMiss_max_time: 0.2 Cop_backoff_regionMiss_max_addr: 127.0.0.1 Cop_backoff_regionMiss_avg_time: 0.2 Cop_backoff_regionMiss_p90_time: 0.2 Cop_backoff_rpcPD_total_times: 200 Cop_backoff_rpcPD_total_time: 0.2 Cop_backoff_rpcPD_max_time: 0.2 Cop_backoff_rpcPD_max_addr: 127.0.0.1 Cop_backoff_rpcPD_avg_time: 0.2 Cop_backoff_rpcPD_p90_time: 0.2 Cop_backoff_rpcTiKV_total_times: 200 Cop_backoff_rpcTiKV_total_time: 0.2 Cop_backoff_rpcTiKV_max_time: 0.2 Cop_backoff_rpcTiKV_max_addr: 127.0.0.1 Cop_backoff_rpcTiKV_avg_time: 0.2 Cop_backoff_rpcTiKV_p90_time: 0.2,` + - `0,0,1,0,1,1,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` + + `0,0,1,0,1,1,0,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,` + `update t set i = 1;,select * from t;` - c.Assert(expectRecordString, Equals, recordString) + require.Equal(t, expectRecordString, recordString) // fix sql contain '# ' bug slowLog := bytes.NewBufferString( @@ -203,8 +204,8 @@ select a# from t; select * from t; `) reader = bufio.NewReader(slowLog) - _, err = parseSlowLog(ctx, reader, 64) - c.Assert(err, IsNil) + _, err = parseSlowLog(ctx, reader) + require.NoError(t, err) // test for time format compatibility. slowLog = bytes.NewBufferString( @@ -214,15 +215,15 @@ select * from t; select * from t; `) reader = bufio.NewReader(slowLog) - rows, err = parseSlowLog(ctx, reader, 64) - c.Assert(err, IsNil) - c.Assert(len(rows) == 2, IsTrue) + rows, err = parseSlowLog(ctx, reader) + require.NoError(t, err) + require.Len(t, rows, 2) t0Str, err := rows[0][0].ToString() - c.Assert(err, IsNil) - c.Assert(t0Str, Equals, "2019-04-28 15:24:04.309074") + require.NoError(t, err) + require.Equal(t, t0Str, "2019-04-28 15:24:04.309074") t1Str, err := rows[1][0].ToString() - c.Assert(err, IsNil) - c.Assert(t1Str, Equals, "2019-04-24 19:41:21.716221") + require.NoError(t, err) + require.Equal(t, t1Str, "2019-04-24 19:41:21.716221") // Add parse error check. slowLog = bytes.NewBufferString( @@ -231,17 +232,17 @@ select * from t; select * from t; `) reader = bufio.NewReader(slowLog) - _, err = parseSlowLog(ctx, reader, 64) - c.Assert(err, IsNil) + _, err = parseSlowLog(ctx, reader) + require.NoError(t, err) warnings := ctx.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(warnings, HasLen, 1) - c.Assert(warnings[0].Err.Error(), Equals, "Parse slow log at line 2, failed field is Succ, failed value is abc, error is strconv.ParseBool: parsing \"abc\": invalid syntax") + require.Len(t, warnings, 1) + require.Equal(t, warnings[0].Err.Error(), "Parse slow log at line 2, failed field is Succ, failed value is abc, error is strconv.ParseBool: parsing \"abc\": invalid syntax") } // It changes variable.MaxOfMaxAllowedPacket, so must be stayed in SerialSuite. -func (s *testExecSerialSuite) TestParseSlowLogFileSerial(c *C) { +func TestParseSlowLogFileSerial(t *testing.T) { loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) ctx := mock.NewContext() ctx.GetSessionVars().TimeZone = loc // test for bufio.Scanner: token too long. @@ -255,34 +256,34 @@ select * from t; sql := strings.Repeat("x", int(variable.MaxOfMaxAllowedPacket+1)) slowLog.WriteString(sql) reader := bufio.NewReader(slowLog) - _, err = parseSlowLog(ctx, reader, 64) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "single line length exceeds limit: 65536") + _, err = parseSlowLog(ctx, reader) + require.Error(t, err) + require.EqualError(t, err, "single line length exceeds limit: 65536") variable.MaxOfMaxAllowedPacket = originValue reader = bufio.NewReader(slowLog) - _, err = parseSlowLog(ctx, reader, 64) - c.Assert(err, IsNil) + _, err = parseSlowLog(ctx, reader) + require.NoError(t, err) } -func (s *testExecSuite) TestSlowLogParseTime(c *C) { +func TestSlowLogParseTime(t *testing.T) { t1Str := "2019-01-24T22:32:29.313255+08:00" t2Str := "2019-01-24T22:32:29.313255" t1, err := ParseTime(t1Str) - c.Assert(err, IsNil) + require.NoError(t, err) loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) t2, err := time.ParseInLocation("2006-01-02T15:04:05.999999999", t2Str, loc) - c.Assert(err, IsNil) - c.Assert(t1.Unix(), Equals, t2.Unix()) + require.NoError(t, err) + require.Equal(t, t1.Unix(), t2.Unix()) t1Format := t1.In(loc).Format(logutil.SlowLogTimeFormat) - c.Assert(t1Format, Equals, t1Str) + require.Equal(t, t1Format, t1Str) } // TestFixParseSlowLogFile bugfix // sql select * from INFORMATION_SCHEMA.SLOW_QUERY limit 1; // ERROR 1105 (HY000): string "2019-05-12-11:23:29.61474688" doesn't has a prefix that matches format "2006-01-02-15:04:05.999999999 -0700", err: parsing time "2019-05-12-11:23:29.61474688" as "2006-01-02-15:04:05.999999999 -0700": cannot parse "" as "-0700" -func (s *testExecSuite) TestFixParseSlowLogFile(c *C) { +func TestFixParseSlowLogFile(t *testing.T) { slowLog := bytes.NewBufferString( `# Time: 2019-05-12-11:23:29.614327491 +0800 # Txn_start_ts: 405888132465033227 @@ -309,11 +310,11 @@ select * from t select * from t;`) scanner := bufio.NewReader(slowLog) loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) ctx := mock.NewContext() ctx.GetSessionVars().TimeZone = loc - _, err = parseSlowLog(ctx, scanner, 64) - c.Assert(err, IsNil) + _, err = parseSlowLog(ctx, scanner) + require.NoError(t, err) // Test parser error. slowLog = bytes.NewBufferString( @@ -322,15 +323,14 @@ select * from t;`) select * from t; `) scanner = bufio.NewReader(slowLog) - _, err = parseSlowLog(ctx, scanner, 64) - c.Assert(err, IsNil) + _, err = parseSlowLog(ctx, scanner) + require.NoError(t, err) warnings := ctx.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(warnings, HasLen, 1) - c.Assert(warnings[0].Err.Error(), Equals, "Parse slow log at line 2, failed field is Txn_start_ts, failed value is 405888132465033227#, error is strconv.ParseUint: parsing \"405888132465033227#\": invalid syntax") - + require.Len(t, warnings, 1) + require.Equal(t, warnings[0].Err.Error(), "Parse slow log at line 2, failed field is Txn_start_ts, failed value is 405888132465033227#, error is strconv.ParseUint: parsing \"405888132465033227#\": invalid syntax") } -func (s *testExecSuite) TestSlowQueryRetriever(c *C) { +func TestSlowQueryRetriever(t *testing.T) { logData0 := "" logData1 := ` # Time: 2020-02-15T18:00:01.000000+08:00 @@ -356,7 +356,7 @@ select 7;` fileName2 := "tidb-slow-2020-02-16T19-04-05.01.log" fileName3 := "tidb-slow.log" fileNames := []string{fileName0, fileName1, fileName2, fileName3} - prepareLogs(c, logData, fileNames) + prepareLogs(t, logData, fileNames) defer func() { removeFiles(fileNames) }() @@ -447,7 +447,7 @@ select 7;` } loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) sctx := mock.NewContext() sctx.GetSessionVars().TimeZone = loc sctx.GetSessionVars().SlowQueryFile = fileName3 @@ -455,33 +455,33 @@ select 7;` extractor := &plannercore.SlowQueryExtractor{Enable: len(cas.startTime) > 0 && len(cas.endTime) > 0} if extractor.Enable { startTime, err := ParseTime(cas.startTime) - c.Assert(err, IsNil) + require.NoError(t, err) endTime, err := ParseTime(cas.endTime) - c.Assert(err, IsNil) + require.NoError(t, err) extractor.TimeRanges = []*plannercore.TimeRange{{StartTime: startTime, EndTime: endTime}} } retriever, err := newSlowQueryRetriever() - c.Assert(err, IsNil) + require.NoError(t, err) retriever.extractor = extractor err = retriever.initialize(context.Background(), sctx) - c.Assert(err, IsNil) - comment := Commentf("case id: %v", i) - c.Assert(retriever.files, HasLen, len(cas.files), comment) + require.NoError(t, err) + comment := fmt.Sprintf("case id: %v", i) + require.Equal(t, len(retriever.files), len(cas.files), comment) if len(retriever.files) > 0 { reader := bufio.NewReader(retriever.files[0].file) - rows, err := parseLog(retriever, sctx, reader, 64) - c.Assert(err, IsNil) - c.Assert(len(rows), Equals, len(cas.querys), comment) + rows, err := parseLog(retriever, sctx, reader) + require.NoError(t, err) + require.Equal(t, len(rows), len(cas.querys), comment) for i, row := range rows { - c.Assert(row[len(row)-1].GetString(), Equals, cas.querys[i], comment) + require.Equal(t, row[len(row)-1].GetString(), cas.querys[i], comment) } } for i, file := range retriever.files { - c.Assert(file.file.Name(), Equals, cas.files[i]) - c.Assert(file.file.Close(), IsNil) + require.Equal(t, file.file.Name(), cas.files[i]) + require.NoError(t, file.file.Close()) } - c.Assert(retriever.close(), IsNil) + require.NoError(t, retriever.close()) } } @@ -525,12 +525,12 @@ func TestSplitbyColon(t *testing.T) { } for _, c := range cases { resFields, resValues := splitByColon(c.line) - assert.Equal(t, c.fields, resFields) - assert.Equal(t, c.values, resValues) + require.Equal(t, c.fields, resFields) + require.Equal(t, c.values, resValues) } } -func (s *testExecSuite) TestBatchLogForReversedScan(c *C) { +func TestBatchLogForReversedScan(t *testing.T) { logData0 := "" logData1 := ` # Time: 2020-02-15T18:00:01.000000+08:00 @@ -560,7 +560,7 @@ select 9;` fileName3 := "tidb-slow-2020-02-17T19-04-05.01.log" fileName4 := "tidb-slow.log" fileNames := []string{fileName0, fileName1, fileName2, fileName3, fileName4} - prepareLogs(c, logData, fileNames) + prepareLogs(t, logData, fileNames) defer func() { removeFiles(fileNames) }() @@ -617,7 +617,7 @@ select 9;` } loc, err := time.LoadLocation("Asia/Shanghai") - c.Assert(err, IsNil) + require.NoError(t, err) sctx := mock.NewContext() sctx.GetSessionVars().TimeZone = loc sctx.GetSessionVars().SlowQueryFile = fileName3 @@ -625,41 +625,89 @@ select 9;` extractor := &plannercore.SlowQueryExtractor{Enable: len(cas.startTime) > 0 && len(cas.endTime) > 0, Desc: true} if extractor.Enable { startTime, err := ParseTime(cas.startTime) - c.Assert(err, IsNil) + require.NoError(t, err) endTime, err := ParseTime(cas.endTime) - c.Assert(err, IsNil) + require.NoError(t, err) extractor.TimeRanges = []*plannercore.TimeRange{{StartTime: startTime, EndTime: endTime}} } retriever, err := newSlowQueryRetriever() - c.Assert(err, IsNil) + require.NoError(t, err) retriever.extractor = extractor sctx.GetSessionVars().SlowQueryFile = fileName4 err = retriever.initialize(context.Background(), sctx) - c.Assert(err, IsNil) - comment := Commentf("case id: %v", i) - c.Assert(retriever.files, HasLen, len(cas.files), comment) + require.NoError(t, err) + comment := fmt.Sprintf("case id: %v", i) if len(retriever.files) > 0 { reader := bufio.NewReader(retriever.files[0].file) offset := &offset{length: 0, offset: 0} rows, err := retriever.getBatchLogForReversedScan(context.Background(), reader, offset, 3) - c.Assert(err, IsNil) + require.NoError(t, err) for _, row := range rows { for j, log := range row { - c.Assert(log, Equals, cas.logs[0][j], comment) + require.Equal(t, log, cas.logs[0][j], comment) } } } - c.Assert(retriever.close(), IsNil) + require.NoError(t, retriever.close()) + } +} + +func TestCancelParseSlowLog(t *testing.T) { + fileName := "tidb-slow-2020-02-14T19-04-05.01.log" + slowLog := `# Time: 2019-04-28T15:24:04.309074+08:00 +select * from t;` + prepareLogs(t, []string{slowLog}, []string{fileName}) + defer func() { + removeFiles([]string{fileName}) + }() + sctx := mock.NewContext() + sctx.GetSessionVars().SlowQueryFile = fileName + + retriever, err := newSlowQueryRetriever() + require.NoError(t, err) + var signal1, signal2 = make(chan int, 1), make(chan int, 1) + ctx := context.WithValue(context.Background(), "signals", []chan int{signal1, signal2}) + ctx, cancel := context.WithCancel(ctx) + err = failpoint.Enable("github.com/pingcap/tidb/executor/mockReadSlowLogSlow", "return(true)") + require.NoError(t, err) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockReadSlowLogSlow")) + }() + go func() { + _, err := retriever.retrieve(ctx, sctx) + require.Errorf(t, err, "context canceled") + }() + // Wait for parseSlowLog going to add tasks. + <-signal1 + // Cancel the retriever and then dataForSlowLog exits. + cancel() + // Assume that there are already unprocessed tasks. + retriever.taskList <- slowLogTask{} + // Let parseSlowLog continue. + signal2 <- 1 + // parseSlowLog should exit immediately. + time.Sleep(1 * time.Second) + require.False(t, checkGoroutineExists("parseSlowLog")) +} + +func checkGoroutineExists(keyword string) bool { + buf := new(bytes.Buffer) + profile := pprof.Lookup("goroutine") + err := profile.WriteTo(buf, 1) + if err != nil { + panic(err) } + str := buf.String() + return strings.Contains(str, keyword) } -func prepareLogs(c *C, logData []string, fileNames []string) { +func prepareLogs(t *testing.T, logData []string, fileNames []string) { writeFile := func(file string, data string) { f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = f.Write([]byte(data)) - c.Assert(f.Close(), IsNil) - c.Assert(err, IsNil) + require.NoError(t, err) + require.NoError(t, f.Close()) } for i, log := range logData { diff --git a/executor/sort_test.go b/executor/sort_test.go index aa87075115076..d895e93153a26 100644 --- a/executor/sort_test.go +++ b/executor/sort_test.go @@ -19,45 +19,50 @@ import ( "fmt" "os" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSerialSuite1) TestSortInDisk(c *C) { - s.testSortInDisk(c, false) - s.testSortInDisk(c, true) +func TestSortInDisk(t *testing.T) { + testSortInDisk(t, false) + testSortInDisk(t, true) } -func (s *testSerialSuite1) testSortInDisk(c *C, removeDir bool) { - defer config.RestoreFunc()() +func testSortInDisk(t *testing.T, removeDir bool) { + restore := config.RestoreFunc() + defer restore() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true + conf.OOMAction = config.OOMActionLog + conf.TempStoragePath = t.TempDir() }) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)")) defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill")) }() - - tk := testkit.NewTestKit(c, s.store) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") sm := &mockSessionManager1{ PS: make([]*util.ProcessInfo, 0), } - tk.Se.SetSessionManager(sm) - s.domain.ExpensiveQueryHandle().SetSessionManager(sm) + tk.Session().SetSessionManager(sm) + dom.ExpensiveQueryHandle().SetSessionManager(sm) if removeDir { - c.Assert(os.RemoveAll(config.GetGlobalConfig().TempStoragePath), IsNil) + require.Nil(t, os.RemoveAll(config.GetGlobalConfig().TempStoragePath)) defer func() { _, err := os.Stat(config.GetGlobalConfig().TempStoragePath) if err != nil { - c.Assert(os.IsExist(err), IsTrue) + require.True(t, os.IsExist(err)) } }() } @@ -79,32 +84,34 @@ func (s *testSerialSuite1) testSortInDisk(c *C, removeDir bool) { tk.MustExec(buf.String()) result := tk.MustQuery("select * from t order by c1") for i := 0; i < 1024; i++ { - c.Assert(result.Rows()[i][0].(string), Equals, fmt.Sprint(i)) - c.Assert(result.Rows()[i][1].(string), Equals, fmt.Sprint(i)) - c.Assert(result.Rows()[i][2].(string), Equals, fmt.Sprint(i)) + require.Equal(t, fmt.Sprint(i), result.Rows()[i][0].(string)) + require.Equal(t, fmt.Sprint(i), result.Rows()[i][1].(string)) + require.Equal(t, fmt.Sprint(i), result.Rows()[i][2].(string)) } - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), Greater, int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.MemTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.MemTracker.MaxConsumed(), int64(0)) + require.Equal(t, int64(0), tk.Session().GetSessionVars().StmtCtx.DiskTracker.BytesConsumed()) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.DiskTracker.MaxConsumed(), int64(0)) } -func (s *testSerialSuite1) TestIssue16696(c *C) { +func TestIssue16696(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.OOMUseTmpStorage = true + conf.OOMAction = config.OOMActionLog + conf.TempStoragePath = t.TempDir() }) alarmRatio := variable.MemoryUsageAlarmRatio.Load() variable.MemoryUsageAlarmRatio.Store(0.0) defer variable.MemoryUsageAlarmRatio.Store(alarmRatio) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)"), IsNil) - defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill"), IsNil) - }() - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/testRowContainerSpill", "return(true)"), IsNil) - defer func() { c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/testRowContainerSpill"), IsNil) }() - tk := testkit.NewTestKit(c, s.store) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill", "return(true)")) + defer require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testSortedRowContainerSpill")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/testRowContainerSpill", "return(true)")) + defer require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/testRowContainerSpill")) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `t` (`a` int(11) DEFAULT NULL,`b` int(11) DEFAULT NULL)") @@ -119,10 +126,10 @@ func (s *testSerialSuite1) TestIssue16696(c *C) { line := fmt.Sprintf("%v", row) disk := fmt.Sprintf("%v", row[length-1]) if strings.Contains(line, "Sort") || strings.Contains(line, "HashJoin") { - c.Assert(strings.Contains(disk, "0 Bytes"), IsFalse) - c.Assert(strings.Contains(disk, "MB") || + require.NotContains(t, disk, "0 Bytes") + require.True(t, strings.Contains(disk, "MB") || strings.Contains(disk, "KB") || - strings.Contains(disk, "Bytes"), IsTrue) + strings.Contains(disk, "Bytes")) } } } diff --git a/executor/split.go b/executor/split.go index beca16bfe5d90..89fa8b78f1879 100644 --- a/executor/split.go +++ b/executor/split.go @@ -561,7 +561,7 @@ func (e *SplitTableRegionExec) calculateIntBoundValue() (lowerValue int64, step lowerValue = lowerRecordID } if step < minRegionStepValue { - errMsg := fmt.Sprintf("the region size is too small, expected at least %d, but got %d", step, minRegionStepValue) + errMsg := fmt.Sprintf("the region size is too small, expected at least %d, but got %d", minRegionStepValue, step) return 0, 0, ErrInvalidSplitRegionRanges.GenWithStackByArgs(errMsg) } return lowerValue, step, nil diff --git a/executor/split_table_test.go b/executor/split_table_test.go new file mode 100644 index 0000000000000..d19dbfed2daf5 --- /dev/null +++ b/executor/split_table_test.go @@ -0,0 +1,596 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "fmt" + "sync/atomic" + "testing" + + "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" +) + +func TestSplitTableRegion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a varchar(100),b int, index idx1(b,a))") + tk.MustExec(`split table t index idx1 by (10000,"abcd"),(10000000);`) + tk.MustGetErrCode(`split table t index idx1 by ("abcd");`, mysql.WarnDataTruncated) + + // Test for split index region. + // Check min value is more than max value. + tk.MustExec(`split table t index idx1 between (0) and (1000000000) regions 10`) + tk.MustGetErrCode(`split table t index idx1 between (2,'a') and (1,'c') regions 10`, errno.ErrInvalidSplitRegionRanges) + + // Check min value is invalid. + tk.MustGetErrMsg(`split table t index idx1 between () and (1) regions 10`, "Split index `idx1` region lower value count should more than 0") + + // Check max value is invalid. + tk.MustGetErrMsg(`split table t index idx1 between (1) and () regions 10`, "Split index `idx1` region upper value count should more than 0") + + // Check pre-split region num is too large. + tk.MustGetErrMsg(`split table t index idx1 between (0) and (1000000000) regions 10000`, "Split index region num exceeded the limit 1000") + + // Check pre-split region num 0 is invalid. + tk.MustGetErrMsg(`split table t index idx1 between (0) and (1000000000) regions 0`, "Split index region num should more than 0") + + // Test truncate error msg. + tk.MustGetErrMsg(`split table t index idx1 between ("aa") and (1000000000) regions 0`, "[types:1265]Incorrect value: 'aa' for column 'b'") + + // Test for split table region. + tk.MustExec(`split table t between (0) and (1000000000) regions 10`) + // Check the lower value is more than the upper value. + tk.MustGetErrCode(`split table t between (2) and (1) regions 10`, errno.ErrInvalidSplitRegionRanges) + + // Check the lower value is invalid. + tk.MustGetErrMsg(`split table t between () and (1) regions 10`, "Split table region lower value count should be 1") + + // Check upper value is invalid. + tk.MustGetErrMsg(`split table t between (1) and () regions 10`, "Split table region upper value count should be 1") + + // Check pre-split region num is too large. + tk.MustGetErrMsg(`split table t between (0) and (1000000000) regions 10000`, "Split table region num exceeded the limit 1000") + + // Check pre-split region num 0 is invalid. + tk.MustGetErrMsg(`split table t between (0) and (1000000000) regions 0`, "Split table region num should more than 0") + + // Test truncate error msg. + tk.MustGetErrMsg(`split table t between ("aa") and (1000000000) regions 10`, "[types:1265]Incorrect value: 'aa' for column '_tidb_rowid'") + + // Test split table region step is too small. + tk.MustGetErrCode(`split table t between (0) and (100) regions 10`, errno.ErrInvalidSplitRegionRanges) + + // Test split region by syntax. + tk.MustExec(`split table t by (0),(1000),(1000000)`) + + // Test split region twice to test for multiple batch split region requests. + tk.MustExec("create table t1(a int, b int)") + tk.MustQuery("split table t1 between(0) and (10000) regions 10;").Check(testkit.Rows("9 1")) + tk.MustQuery("split table t1 between(10) and (10010) regions 5;").Check(testkit.Rows("4 1")) + + // Test split region for partition table. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int,b int) partition by hash(a) partitions 5;") + tk.MustQuery("split table t between (0) and (1000000) regions 5;").Check(testkit.Rows("20 1")) + // Test for `split for region` syntax. + tk.MustQuery("split region for partition table t between (1000000) and (100000000) regions 10;").Check(testkit.Rows("45 1")) + + // Test split region for partition table with specified partition. + tk.MustQuery("split table t partition (p1,p2) between (100000000) and (1000000000) regions 5;").Check(testkit.Rows("8 1")) + // Test for `split for region` syntax. + tk.MustQuery("split region for partition table t partition (p3,p4) between (100000000) and (1000000000) regions 5;").Check(testkit.Rows("8 1")) +} + +func TestSplitRegionEdgeCase(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a bigint(20) auto_increment primary key);") + tk.MustExec("split table t between (-9223372036854775808) and (9223372036854775807) regions 16;") + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int(20) auto_increment primary key);") + tk.MustGetErrCode("split table t between (-9223372036854775808) and (9223372036854775807) regions 16;", errno.ErrDataOutOfRange) +} + +func TestClusterIndexSplitTableIntegration(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists test_cluster_index_index_split_table_integration;") + tk.MustExec("create database test_cluster_index_index_split_table_integration;") + tk.MustExec("use test_cluster_index_index_split_table_integration;") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + + tk.MustExec("create table t (a varchar(255), b double, c int, primary key (a, b));") + + // Value list length not match. + lowerMsg := "Split table region lower value count should be 2" + upperMsg := "Split table region upper value count should be 2" + tk.MustGetErrMsg("split table t between ('aaa') and ('aaa', 100.0) regions 10;", lowerMsg) + tk.MustGetErrMsg("split table t between ('aaa', 1.0) and ('aaa', 100.0, 11) regions 10;", upperMsg) + + // Value type not match. + errMsg := "[types:1265]Incorrect value: 'aaa' for column 'b'" + tk.MustGetErrMsg("split table t between ('aaa', 0.0) and (100.0, 'aaa') regions 10;", errMsg) + + // lower bound >= upper bound. + errMsg = "[executor:8212]Failed to split region ranges: Split table `t` region lower value (aaa,0) should less than the upper value (aaa,0)" + tk.MustGetErrMsg("split table t between ('aaa', 0.0) and ('aaa', 0.0) regions 10;", errMsg) + errMsg = "[executor:8212]Failed to split region ranges: Split table `t` region lower value (bbb,0) should less than the upper value (aaa,0)" + tk.MustGetErrMsg("split table t between ('bbb', 0.0) and ('aaa', 0.0) regions 10;", errMsg) + + // Exceed limit 1000. + errMsg = "Split table region num exceeded the limit 1000" + tk.MustGetErrMsg("split table t between ('aaa', 0.0) and ('aaa', 0.1) regions 100000;", errMsg) + + // Split on null values. + errMsg = "[planner:1048]Column 'a' cannot be null" + tk.MustGetErrMsg("split table t between (null, null) and (null, null) regions 1000;", errMsg) + tk.MustGetErrMsg("split table t by (null, null);", errMsg) + + // Success. + tk.MustExec("split table t between ('aaa', 0.0) and ('aaa', 100.0) regions 10;") + tk.MustExec("split table t by ('aaa', 0.0), ('aaa', 20.0), ('aaa', 100.0);") + tk.MustExec("split table t by ('aaa', 100.0), ('qqq', 20.0), ('zzz', 100.0), ('zzz', 1000.0);") + + tk.MustExec("drop table t;") + tk.MustExec("create table t (a int, b int, c int, d int, primary key(a, c, d));") + tk.MustQuery("split table t between (0, 0, 0) and (0, 0, 1) regions 1000;").Check(testkit.Rows("999 1")) + + tk.MustExec("drop table t;") + tk.MustExec("create table t (a int, b int, c int, d int, primary key(d, a, c));") + tk.MustQuery("split table t by (0, 0, 0), (1, 2, 3), (65535, 65535, 65535);").Check(testkit.Rows("3 1")) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a varchar(255), b decimal, c int, primary key (a, b));") + errMsg = "[types:1265]Incorrect value: '' for column 'b'" + tk.MustGetErrMsg("split table t by ('aaa', '')", errMsg) +} + +func TestClusterIndexShowTableRegion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("set global tidb_scatter_region = 1") + tk.MustExec("drop database if exists cluster_index_regions;") + tk.MustExec("create database cluster_index_regions;") + tk.MustExec("use cluster_index_regions;") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("create table t (a int, b int, c int, primary key(a, b));") + tk.MustExec("insert t values (1, 1, 1), (2, 2, 2);") + tk.MustQuery("split table t between (1, 0) and (2, 3) regions 2;").Check(testkit.Rows("1 1")) + rows := tk.MustQuery("show table t regions").Rows() + tbl := external.GetTableByName(t, tk, "cluster_index_regions", "t") + // Check the region start key. + require.Regexp(t, fmt.Sprintf("t_%d_", tbl.Meta().ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_r_03800000000000000183800000000000", tbl.Meta().ID), rows[1][1]) + + tk.MustExec("drop table t;") + tk.MustExec("create table t (a int, b int);") + tk.MustQuery("split table t between (0) and (100000) regions 2;").Check(testkit.Rows("1 1")) + rows = tk.MustQuery("show table t regions").Rows() + tbl = external.GetTableByName(t, tk, "cluster_index_regions", "t") + // Check the region start key is int64. + require.Regexp(t, fmt.Sprintf("t_%d_", tbl.Meta().ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_r_50000", tbl.Meta().ID), rows[1][1]) +} + +func TestShowTableRegion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_regions") + tk.MustExec("set global tidb_scatter_region = 1") + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("create table t_regions (a int key, b int, c int, index idx(b), index idx2(c))") + tk.MustGetErrMsg( + "split partition table t_regions partition (p1,p2) index idx between (0) and (20000) regions 2;", + plannercore.ErrPartitionClauseOnNonpartitioned.Error()) + + // Test show table regions. + tk.MustQuery(`split table t_regions between (-10000) and (10000) regions 4;`).Check(testkit.Rows("4 1")) + re := tk.MustQuery("show table t_regions regions") + + // Test show table regions and split table on global temporary table. + tk.MustExec("drop table if exists t_regions_temporary_table") + tk.MustExec("create global temporary table t_regions_temporary_table (a int key, b int, c int, index idx(b), index idx2(c)) ON COMMIT DELETE ROWS;") + // Test show table regions. + tk.MustGetErrMsg( + "show table t_regions_temporary_table regions", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("show table regions").Error()) + // Test split table. + tk.MustGetErrMsg( + "split table t_regions_temporary_table between (-10000) and (10000) regions 4;", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) + tk.MustGetErrMsg( + "split partition table t_regions_temporary_table partition (p1,p2) index idx between (0) and (20000) regions 2;", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) + tk.MustExec("drop table if exists t_regions_temporary_table") + // Test pre split regions + tk.MustGetErrMsg( + "create global temporary table temporary_table_pre_split(id int ) pre_split_regions=2 ON COMMIT DELETE ROWS;", + dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) + + // Test show table regions and split table on local temporary table + tk.MustExec("drop table if exists t_regions_local_temporary_table") + tk.MustExec("create temporary table t_regions_local_temporary_table (a int key, b int, c int, index idx(b), index idx2(c));") + // Test show table regions. + tk.MustGetErrMsg( + "show table t_regions_local_temporary_table regions", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("show table regions").Error()) + // Test split table. + tk.MustGetErrMsg( + "split table t_regions_local_temporary_table between (-10000) and (10000) regions 4;", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) + tk.MustGetErrMsg( + "split partition table t_regions_local_temporary_table partition (p1,p2) index idx between (0) and (20000) regions 2;", + plannercore.ErrOptOnTemporaryTable.GenWithStackByArgs("split table").Error()) + tk.MustExec("drop table if exists t_regions_local_temporary_table") + // Test pre split regions + tk.MustGetErrMsg( + "create temporary table local_temporary_table_pre_split(id int ) pre_split_regions=2;", + dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error()) + + rows := re.Rows() + // Table t_regions should have 5 regions now. + // 4 regions to store record data. + // 1 region to store index data. + require.Len(t, rows, 5) + require.Len(t, rows[0], 11) + tbl := external.GetTableByName(t, tk, "test", "t_regions") + // Check the region start key. + require.Equal(t, fmt.Sprintf("t_%d_r", tbl.Meta().ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID), rows[3][1]) + require.Equal(t, fmt.Sprintf("t_%d_r", tbl.Meta().ID), rows[4][2]) + + // Test show table index regions. + tk.MustQuery(`split table t_regions index idx between (-1000) and (1000) regions 4;`).Check(testkit.Rows("4 1")) + re = tk.MustQuery("show table t_regions index idx regions") + rows = re.Rows() + // The index `idx` of table t_regions should have 4 regions now. + require.Len(t, rows, 4) + // Check the region start key. + require.Regexp(t, fmt.Sprintf("t_%d.*", tbl.Meta().ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[3][1]) + + re = tk.MustQuery("show table t_regions regions") + rows = re.Rows() + // The index `idx` of table t_regions should have 9 regions now. + // 4 regions to store record data. + // 4 region to store index idx data. + // 1 region to store index idx2 data. + require.Len(t, rows, 9) + // Check the region start key. + require.Equal(t, fmt.Sprintf("t_%d_r", tbl.Meta().ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID), rows[3][1]) + require.Regexp(t, fmt.Sprintf("t_%d_", tbl.Meta().ID), rows[4][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[5][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[6][1]) + require.Equal(t, fmt.Sprintf("t_%d_i_2_", tbl.Meta().ID), rows[7][2]) + require.Equal(t, fmt.Sprintf("t_%d_r", tbl.Meta().ID), rows[8][2]) + + // Test unsigned primary key and wait scatter finish. + tk.MustExec("drop table if exists t_regions") + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("create table t_regions (a int unsigned key, b int, index idx(b))") + + // Test show table regions. + tk.MustExec(`set @@session.tidb_wait_split_region_finish=1;`) + tk.MustQuery(`split table t_regions by (2500),(5000),(7500);`).Check(testkit.Rows("3 1")) + re = tk.MustQuery("show table t_regions regions") + rows = re.Rows() + // Table t_regions should have 4 regions now. + require.Len(t, rows, 4) + tbl = external.GetTableByName(t, tk, "test", "t_regions") + // Check the region start key. + require.Regexp(t, "t_.*", rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2500", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_7500", tbl.Meta().ID), rows[3][1]) + + // Test show table index regions. + tk.MustQuery(`split table t_regions index idx by (250),(500),(750);`).Check(testkit.Rows("4 1")) + re = tk.MustQuery("show table t_regions index idx regions") + rows = re.Rows() + // The index `idx` of table t_regions should have 4 regions now. + require.Len(t, rows, 4) + // Check the region start key. + require.Equal(t, fmt.Sprintf("t_%d_", tbl.Meta().ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID), rows[3][1]) + + // Test show table regions for partition table when disable split region when create table. + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) + tk.MustExec("drop table if exists partition_t;") + tk.MustExec("set @@session.tidb_enable_table_partition = '1';") + tk.MustExec("create table partition_t (a int, b int,index(a)) partition by hash (a) partitions 3") + re = tk.MustQuery("show table partition_t regions") + rows = re.Rows() + require.Len(t, rows, 1) + require.Regexp(t, "t_.*", rows[0][1]) + + // Test show table regions for partition table when enable split region when create table. + atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) + tk.MustExec("set @@global.tidb_scatter_region=1;") + tk.MustExec("drop table if exists partition_t;") + tk.MustExec("create table partition_t (a int, b int,index(a)) partition by hash (a) partitions 3") + re = tk.MustQuery("show table partition_t regions") + rows = re.Rows() + require.Len(t, rows, 3) + tbl = external.GetTableByName(t, tk, "test", "partition_t") + partitionDef := tbl.Meta().GetPartitionInfo().Definitions + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[0].ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[1].ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[2].ID), rows[2][1]) + + // Test split partition region when add new partition. + tk.MustExec("drop table if exists partition_t;") + tk.MustExec(`create table partition_t (a int, b int,index(a)) PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20), + PARTITION p2 VALUES LESS THAN (30));`) + tk.MustExec(`alter table partition_t add partition ( partition p3 values less than (40), partition p4 values less than (50) );`) + re = tk.MustQuery("show table partition_t regions") + rows = re.Rows() + require.Len(t, rows, 5) + tbl = external.GetTableByName(t, tk, "test", "partition_t") + partitionDef = tbl.Meta().GetPartitionInfo().Definitions + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[0].ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[1].ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[2].ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[3].ID), rows[3][1]) + require.Regexp(t, fmt.Sprintf("t_%d_.*", partitionDef[4].ID), rows[4][1]) + + // Test pre-split table region when create table. + tk.MustExec("drop table if exists t_pre") + tk.MustExec("create table t_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2;") + re = tk.MustQuery("show table t_pre regions") + rows = re.Rows() + // Table t_regions should have 4 regions now. + require.Len(t, rows, 4) + tbl = external.GetTableByName(t, tk, "test", "t_pre") + require.Equal(t, fmt.Sprintf("t_%d_r_2305843009213693952", tbl.Meta().ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_4611686018427387904", tbl.Meta().ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_6917529027641081856", tbl.Meta().ID), rows[3][1]) + + // Test pre-split table region when create table. + tk.MustExec("drop table if exists pt_pre") + tk.MustExec("create table pt_pre (a int, b int) shard_row_id_bits = 2 pre_split_regions=2 partition by hash(a) partitions 3;") + re = tk.MustQuery("show table pt_pre regions") + rows = re.Rows() + // Table t_regions should have 4 regions now. + require.Len(t, rows, 12) + tbl = external.GetTableByName(t, tk, "test", "pt_pre") + pi := tbl.Meta().GetPartitionInfo().Definitions + require.Len(t, pi, 3) + for i, p := range pi { + require.Equal(t, fmt.Sprintf("t_%d_r_2305843009213693952", p.ID), rows[1+4*i][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_4611686018427387904", p.ID), rows[2+4*i][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_6917529027641081856", p.ID), rows[3+4*i][1]) + } + + defer atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) + + // Test split partition table. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int,b int) partition by hash(a) partitions 5;") + tk.MustQuery("split table t between (0) and (4000000) regions 4;").Check(testkit.Rows("15 1")) + re = tk.MustQuery("show table t regions") + rows = re.Rows() + require.Len(t, rows, 20) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().GetPartitionInfo().Definitions, 5) + for i, p := range tbl.Meta().GetPartitionInfo().Definitions { + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*4+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*4+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*4+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*4+3][1]) + } + + // Test split region for partition table with specified partition. + tk.MustQuery("split table t partition (p4) between (1000000) and (2000000) regions 5;").Check(testkit.Rows("4 1")) + re = tk.MustQuery("show table t regions") + rows = re.Rows() + require.Len(t, rows, 24) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().GetPartitionInfo().Definitions, 5) + for i := 0; i < 4; i++ { + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*4+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*4+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*4+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*4+3][1]) + } + for i := 4; i < 5; i++ { + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*4+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*4+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1200000", p.ID), rows[i*4+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1400000", p.ID), rows[i*4+3][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1600000", p.ID), rows[i*4+4][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1800000", p.ID), rows[i*4+5][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*4+6][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*4+7][1]) + } + + // Test for show table partition regions. + for i := 0; i < 4; i++ { + re = tk.MustQuery(fmt.Sprintf("show table t partition (p%v) regions", i)) + rows = re.Rows() + require.Len(t, rows, 4) + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[3][1]) + } + re = tk.MustQuery("show table t partition (p0, p4) regions") + rows = re.Rows() + require.Len(t, rows, 12) + p := tbl.Meta().GetPartitionInfo().Definitions[0] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[3][1]) + p = tbl.Meta().GetPartitionInfo().Definitions[4] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[4][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[5][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1200000", p.ID), rows[6][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1400000", p.ID), rows[7][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1600000", p.ID), rows[8][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1800000", p.ID), rows[9][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[10][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[11][1]) + // Test for duplicate partition names. + re = tk.MustQuery("show table t partition (p0, p0, p0) regions") + rows = re.Rows() + require.Len(t, rows, 4) + p = tbl.Meta().GetPartitionInfo().Definitions[0] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[3][1]) + + // Test split partition table index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int,b int,index idx(a)) partition by hash(a) partitions 5;") + tk.MustQuery("split table t between (0) and (4000000) regions 4;").Check(testkit.Rows("20 1")) + tk.MustQuery("split table t index idx between (0) and (4000000) regions 4;").Check(testkit.Rows("20 1")) + re = tk.MustQuery("show table t regions") + rows = re.Rows() + require.Len(t, rows, 40) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().GetPartitionInfo().Definitions, 5) + for i := 0; i < 5; i++ { + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_r", p.ID), rows[i*8+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*8+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*8+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*8+3][1]) + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*8+4][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+5][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+6][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+7][1]) + } + + // Test split index region for partition table with specified partition. + tk.MustQuery("split table t partition (p4) index idx between (0) and (1000000) regions 5;").Check(testkit.Rows("4 1")) + re = tk.MustQuery("show table t regions") + rows = re.Rows() + require.Len(t, rows, 44) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Len(t, tbl.Meta().GetPartitionInfo().Definitions, 5) + for i := 0; i < 4; i++ { + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_r", p.ID), rows[i*8+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*8+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*8+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*8+3][1]) + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*8+4][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+5][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+6][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+7][1]) + } + for i := 4; i < 5; i++ { + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_r", p.ID), rows[i*8+0][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_1000000", p.ID), rows[i*8+1][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_2000000", p.ID), rows[i*8+2][1]) + require.Equal(t, fmt.Sprintf("t_%d_r_3000000", p.ID), rows[i*8+3][1]) + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[i*8+4][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+5][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+6][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+7][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+8][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+9][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+10][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[i*8+11][1]) + } + + // Test show table partition region on unknown-partition. + err := tk.QueryToErr("show table t partition (p_unknown) index idx regions") + require.True(t, terror.ErrorEqual(err, table.ErrUnknownPartition)) + + // Test show table partition index. + for i := 0; i < 4; i++ { + re = tk.MustQuery(fmt.Sprintf("show table t partition (p%v) index idx regions", i)) + rows = re.Rows() + require.Len(t, rows, 4) + p := tbl.Meta().GetPartitionInfo().Definitions[i] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[3][1]) + } + re = tk.MustQuery("show table t partition (p3,p4) index idx regions") + rows = re.Rows() + require.Len(t, rows, 12) + p = tbl.Meta().GetPartitionInfo().Definitions[3] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[0][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[3][1]) + p = tbl.Meta().GetPartitionInfo().Definitions[4] + require.Equal(t, fmt.Sprintf("t_%d_", p.ID), rows[4][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[5][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[6][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[7][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[8][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[9][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[10][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_1_.*", p.ID), rows[11][1]) + + // Test split for the second index. + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int,b int,index idx(a), index idx2(b))") + tk.MustQuery("split table t index idx2 between (0) and (4000000) regions 2;").Check(testkit.Rows("3 1")) + re = tk.MustQuery("show table t regions") + rows = re.Rows() + require.Len(t, rows, 4) + tbl = external.GetTableByName(t, tk, "test", "t") + require.Equal(t, fmt.Sprintf("t_%d_i_3_", tbl.Meta().ID), rows[0][1]) + require.Equal(t, fmt.Sprintf("t_%d_", tbl.Meta().ID), rows[1][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_2_.*", tbl.Meta().ID), rows[2][1]) + require.Regexp(t, fmt.Sprintf("t_%d_i_2_.*", tbl.Meta().ID), rows[3][1]) + + // Test show table partition region on non-partition table. + err = tk.QueryToErr("show table t partition (p3,p4) index idx regions") + require.True(t, terror.ErrorEqual(err, plannercore.ErrPartitionClauseOnNonpartitioned)) +} diff --git a/executor/split_test.go b/executor/split_test.go index 5c9493be4f4ee..e346150ee241c 100644 --- a/executor/split_test.go +++ b/executor/split_test.go @@ -20,9 +20,9 @@ import ( "math" "math/rand" "sort" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" @@ -33,20 +33,10 @@ import ( "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testSplitIndex{}) - -type testSplitIndex struct { -} - -func (s *testSplitIndex) SetUpSuite(c *C) { -} - -func (s *testSplitIndex) TearDownSuite(c *C) { -} - -func (s *testSplitIndex) TestLongestCommonPrefixLen(c *C) { +func TestLongestCommonPrefixLen(t *testing.T) { cases := []struct { s1 string s2 string @@ -64,11 +54,11 @@ func (s *testSplitIndex) TestLongestCommonPrefixLen(c *C) { for _, ca := range cases { re := longestCommonPrefixLen([]byte(ca.s1), []byte(ca.s2)) - c.Assert(re, Equals, ca.l) + require.Equal(t, ca.l, re) } } -func (s *testSplitIndex) TestgetStepValue(c *C) { +func TestGetStepValue(t *testing.T) { cases := []struct { lower []byte upper []byte @@ -86,13 +76,13 @@ func (s *testSplitIndex) TestgetStepValue(c *C) { for _, ca := range cases { l := longestCommonPrefixLen(ca.lower, ca.upper) - c.Assert(l, Equals, ca.l) + require.Equal(t, ca.l, l) v0 := getStepValue(ca.lower[l:], ca.upper[l:], 1) - c.Assert(v0, Equals, ca.v) + require.Equal(t, v0, ca.v) } } -func (s *testSplitIndex) TestSplitIndex(c *C) { +func TestSplitIndex(t *testing.T) { tbInfo := &model.TableInfo{ Name: model.NewCIStr("t1"), ID: rand.Int63(), @@ -144,8 +134,8 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { } valueList, err := e.getSplitIdxKeys() sort.Slice(valueList, func(i, j int) bool { return bytes.Compare(valueList[i], valueList[j]) < 0 }) - c.Assert(err, IsNil) - c.Assert(len(valueList), Equals, e.num+1) + require.NoError(t, err) + require.Len(t, valueList, e.num+1) cases := []struct { value int @@ -173,15 +163,15 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { for _, ca := range cases { // test for minInt64 handle idxValue, _, err := index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(ca.value)}, kv.IntHandle(math.MinInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx := searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) // Test for max int64 handle. idxValue, _, err = index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(ca.value)}, kv.IntHandle(math.MaxInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx = searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) } // Test for varchar index. // range is a ~ z, and split into 26 region. @@ -200,8 +190,8 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { valueList, err = e.getSplitIdxKeys() sort.Slice(valueList, func(i, j int) bool { return bytes.Compare(valueList[i], valueList[j]) < 0 }) - c.Assert(err, IsNil) - c.Assert(len(valueList), Equals, e.num+1) + require.NoError(t, err) + require.Len(t, valueList, e.num+1) cases2 := []struct { value string @@ -221,15 +211,15 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { for _, ca := range cases2 { // test for minInt64 handle idxValue, _, err := index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(ca.value)}, kv.IntHandle(math.MinInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx := searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) // Test for max int64 handle. idxValue, _, err = index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(ca.value)}, kv.IntHandle(math.MaxInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx = searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) } // Test for timestamp index. @@ -252,8 +242,8 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { valueList, err = e.getSplitIdxKeys() sort.Slice(valueList, func(i, j int) bool { return bytes.Compare(valueList[i], valueList[j]) < 0 }) - c.Assert(err, IsNil) - c.Assert(len(valueList), Equals, e.num+1) + require.NoError(t, err) + require.Len(t, valueList, e.num+1) cases3 := []struct { value types.CoreTime @@ -279,19 +269,19 @@ func (s *testSplitIndex) TestSplitIndex(c *C) { value := types.NewTime(ca.value, mysql.TypeTimestamp, types.DefaultFsp) // test for min int64 handle idxValue, _, err := index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(value)}, kv.IntHandle(math.MinInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx := searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) // Test for max int64 handle. idxValue, _, err = index.GenIndexKey(ctx.GetSessionVars().StmtCtx, []types.Datum{types.NewDatum(value)}, kv.IntHandle(math.MaxInt64), nil) - c.Assert(err, IsNil) + require.NoError(t, err) idx = searchLessEqualIdx(valueList, idxValue) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) } } -func (s *testSplitIndex) TestSplitTable(c *C) { +func TestSplitTable(t *testing.T) { tbInfo := &model.TableInfo{ Name: model.NewCIStr("t1"), ID: rand.Int63(), @@ -332,8 +322,8 @@ func (s *testSplitIndex) TestSplitTable(c *C) { num: 10, } valueList, err := e.getSplitTableKeys() - c.Assert(err, IsNil) - c.Assert(len(valueList), Equals, e.num-1) + require.NoError(t, err) + require.Len(t, valueList, e.num-1) cases := []struct { value int @@ -361,13 +351,41 @@ func (s *testSplitIndex) TestSplitTable(c *C) { for _, ca := range cases { // test for minInt64 handle key := tablecodec.EncodeRecordKey(recordPrefix, kv.IntHandle(ca.value)) - c.Assert(err, IsNil) + require.NoError(t, err) idx := searchLessEqualIdx(valueList, key) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) + } +} + +func TestStepShouldLargeThanMinStep(t *testing.T) { + ctx := mock.NewContext() + tbInfo := &model.TableInfo{ + Name: model.NewCIStr("t1"), + ID: rand.Int63(), + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("c0"), + ID: 1, + Offset: 1, + DefaultValue: 0, + State: model.StatePublic, + FieldType: *types.NewFieldType(mysql.TypeLong), + }, + }, + } + e1 := &SplitTableRegionExec{ + baseExecutor: newBaseExecutor(ctx, nil, 0), + tableInfo: tbInfo, + handleCols: core.NewIntHandleCols(&expression.Column{RetType: types.NewFieldType(mysql.TypeLonglong)}), + lower: []types.Datum{types.NewDatum(0)}, + upper: []types.Datum{types.NewDatum(1000)}, + num: 10, } + _, err := e1.getSplitTableKeys() + require.Equal(t, "[executor:8212]Failed to split region ranges: the region size is too small, expected at least 1000, but got 100", err.Error()) } -func (s *testSplitIndex) TestClusterIndexSplitTable(c *C) { +func TestClusterIndexSplitTable(t *testing.T) { tbInfo := &model.TableInfo{ Name: model.NewCIStr("t"), ID: 1, @@ -423,8 +441,8 @@ func (s *testSplitIndex) TestClusterIndexSplitTable(c *C) { num: 10, } valueList, err := e.getSplitTableKeys() - c.Assert(err, IsNil) - c.Assert(len(valueList), Equals, e.num-1) + require.NoError(t, err) + require.Len(t, valueList, e.num-1) cases := []struct { value []types.Datum @@ -453,11 +471,11 @@ func (s *testSplitIndex) TestClusterIndexSplitTable(c *C) { recordPrefix := tablecodec.GenTableRecordPrefix(e.tableInfo.ID) for _, ca := range cases { h, err := e.handleCols.BuildHandleByDatums(ca.value) - c.Assert(err, IsNil) + require.NoError(t, err) key := tablecodec.EncodeRecordKey(recordPrefix, h) - c.Assert(err, IsNil) + require.NoError(t, err) idx := searchLessEqualIdx(valueList, key) - c.Assert(idx, Equals, ca.lessEqualIdx, Commentf("%#v", ca)) + require.Equal(t, idx, ca.lessEqualIdx) } } diff --git a/executor/stale_txn_test.go b/executor/stale_txn_test.go index 03edfbb6b7ae1..083574df72b08 100644 --- a/executor/stale_txn_test.go +++ b/executor/stale_txn_test.go @@ -15,20 +15,33 @@ package executor_test import ( + "context" "fmt" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" ) -func (s *testStaleTxnSerialSuite) TestExactStalenessTransaction(c *C) { +func enableStalereadCommonFailPoint(t *testing.T) func() { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan", "return")) + return func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan")) + } +} + +func TestExactStalenessTransaction(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() testcases := []struct { name string preSQL string @@ -68,30 +81,36 @@ func (s *testStaleTxnSerialSuite) TestExactStalenessTransaction(c *C) { zone: "", }, } - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") for _, testcase := range testcases { - c.Log(testcase.name) - failpoint.Enable("tikvclient/injectTxnScope", - fmt.Sprintf(`return("%v")`, testcase.zone)) + t.Log(testcase.name) + require.NoError(t, failpoint.Enable("tikvclient/injectTxnScope", fmt.Sprintf(`return("%v")`, testcase.zone))) tk.MustExec(testcase.preSQL) tk.MustExec(testcase.sql) - c.Assert(tk.Se.GetSessionVars().TxnCtx.IsStaleness, Equals, testcase.IsStaleness) + require.Equal(t, testcase.IsStaleness, tk.Session().GetSessionVars().TxnCtx.IsStaleness) if testcase.expectPhysicalTS > 0 { - c.Assert(oracle.ExtractPhysical(tk.Se.GetSessionVars().TxnCtx.StartTS), Equals, testcase.expectPhysicalTS) + require.Equal(t, testcase.expectPhysicalTS, oracle.ExtractPhysical(tk.Session().GetSessionVars().TxnCtx.StartTS)) } else if !testcase.IsStaleness { curTS := oracle.ExtractPhysical(oracle.GoTimeToTS(time.Now())) - startTS := oracle.ExtractPhysical(tk.Se.GetSessionVars().TxnCtx.StartTS) - c.Assert(curTS-startTS, Less, time.Second.Milliseconds()) - c.Assert(startTS-curTS, Less, time.Second.Milliseconds()) + startTS := oracle.ExtractPhysical(tk.Session().GetSessionVars().TxnCtx.StartTS) + require.Less(t, curTS-startTS, time.Second.Milliseconds()) + require.Less(t, startTS-curTS, time.Second.Milliseconds()) } tk.MustExec("commit") } - failpoint.Disable("tikvclient/injectTxnScope") + require.NoError(t, failpoint.Disable("tikvclient/injectTxnScope")) } -func (s *testStaleTxnSerialSuite) TestSelectAsOf(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectAsOf(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" @@ -146,23 +165,23 @@ func (s *testStaleTxnSerialSuite) TestSelectAsOf(c *C) { } for _, testcase := range testcases1 { - c.Log(testcase.name) + t.Log(testcase.name) if len(testcase.setTxnSQL) > 0 { tk.MustExec(testcase.setTxnSQL) } - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, testcase.expectPhysicalTS)), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, testcase.expectPhysicalTS))) rs, err := tk.Exec(testcase.sql) if len(testcase.errorStr) != 0 { - c.Assert(err, ErrorMatches, testcase.errorStr) + require.Regexp(t, testcase.errorStr, err.Error()) continue } - c.Assert(err, IsNil, Commentf("sql:%s, error stack %v", testcase.sql, errors.ErrorStack(err))) + require.NoErrorf(t, err, "sql:%s, error stack %v", testcase.sql, errors.ErrorStack(err)) if rs != nil { rs.Close() } - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO")) if len(testcase.setTxnSQL) > 0 { - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) } } @@ -222,29 +241,34 @@ func (s *testStaleTxnSerialSuite) TestSelectAsOf(c *C) { } for _, testcase := range testcases2 { - c.Log(testcase.name) + t.Log(testcase.name) if testcase.preSec > 0 { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix())), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-testcase.preSec)), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix()))) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-testcase.preSec))) } rs, err := tk.Exec(testcase.sql) if len(testcase.errorStr) != 0 { - c.Assert(err, ErrorMatches, testcase.errorStr) + require.Regexp(t, testcase.errorStr, err.Error()) continue } - c.Assert(err, IsNil, Commentf("sql:%s, error stack %v", testcase.sql, errors.ErrorStack(err))) + require.NoError(t, err, "sql:%s, error stack %v", testcase.sql, errors.ErrorStack(err)) if rs != nil { rs.Close() } if testcase.preSec > 0 { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/expression/injectNow"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/injectNow")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO")) } } } -func (s *testStaleTxnSerialSuite) TestStaleReadKVRequest(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleReadKVRequest(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" @@ -290,25 +314,25 @@ func (s *testStaleTxnSerialSuite) TestStaleReadKVRequest(c *C) { } tk.MustExec("set @@tidb_replica_read='closest-replicas'") for _, testcase := range testcases { - failpoint.Enable(testcase.assert, `return("sh")`) + require.NoError(t, failpoint.Enable(testcase.assert, `return("sh")`)) tk.MustExec(`START TRANSACTION READ ONLY AS OF TIMESTAMP NOW(3);`) tk.MustQuery(testcase.sql) tk.MustExec(`commit`) - failpoint.Disable(testcase.assert) + require.NoError(t, failpoint.Disable(testcase.assert)) } for _, testcase := range testcases { - failpoint.Enable(testcase.assert, `return("sh")`) + require.NoError(t, failpoint.Enable(testcase.assert, `return("sh")`)) tk.MustExec(`SET TRANSACTION READ ONLY AS OF TIMESTAMP NOW(3)`) tk.MustExec(`begin;`) tk.MustQuery(testcase.sql) tk.MustExec(`commit`) - failpoint.Disable(testcase.assert) + require.NoError(t, failpoint.Disable(testcase.assert)) } // assert follower read closest read for _, testcase := range testcases { - failpoint.Enable(testcase.assert, `return("sh")`) + require.NoError(t, failpoint.Enable(testcase.assert, `return("sh")`)) tk.MustQuery(testcase.sql) - failpoint.Disable(testcase.assert) + require.NoError(t, failpoint.Disable(testcase.assert)) } tk.MustExec(`insert into t1 (c,d,e) values (1,1,1);`) tk.MustExec(`insert into t1 (c,d,e) values (2,3,5);`) @@ -319,25 +343,30 @@ func (s *testStaleTxnSerialSuite) TestStaleReadKVRequest(c *C) { tk.MustExec(`insert into t1 (c,d,e) values (5,0,5);`) // IndexLookUp Reader Executor rows1 := tk.MustQuery(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%v' use index (idx_d) where c < 5 and d < 5", tsv)).Rows() - c.Assert(rows1, HasLen, 2) + require.Len(t, rows1, 2) // IndexMerge Reader Executor rows2 := tk.MustQuery(fmt.Sprintf("select /*+ USE_INDEX_MERGE(t1, idx_d, idx_e) */ * from t1 AS OF TIMESTAMP '%v' where c <5 and (d =5 or e=5)", tsv)).Rows() - c.Assert(rows2, HasLen, 1) + require.Len(t, rows2, 1) // TableReader Executor rows3 := tk.MustQuery(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%v' where c < 6", tsv)).Rows() - c.Assert(rows3, HasLen, 2) + require.Len(t, rows3, 2) // IndexReader Executor rows4 := tk.MustQuery(fmt.Sprintf("select /*+ USE_INDEX(t1, idx_d) */ d from t1 AS OF TIMESTAMP '%v' where c < 5 and d < 1;", tsv)).Rows() - c.Assert(rows4, HasLen, 0) + require.Len(t, rows4, 0) // point get executor rows5 := tk.MustQuery(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%v' where c = 3;", tsv)).Rows() - c.Assert(rows5, HasLen, 0) + require.Len(t, rows5, 0) rows6 := tk.MustQuery(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%v' where c in (3,4,5);", tsv)).Rows() - c.Assert(rows6, HasLen, 0) + require.Len(t, rows6, 0) } -func (s *testStaleTxnSuite) TestStalenessAndHistoryRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStalenessAndHistoryRead(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" @@ -350,76 +379,81 @@ func (s *testStaleTxnSuite) TestStalenessAndHistoryRead(c *C) { time1 := time.Now() time1TS := oracle.GoTimeToTS(time1) - schemaVer1 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer1 := tk.Session().GetInfoSchema().SchemaMetaVersion() tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key);") tk.MustExec(`drop table if exists t`) time.Sleep(50 * time.Millisecond) time2 := time.Now() time2TS := oracle.GoTimeToTS(time2) - schemaVer2 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer2 := tk.Session().GetInfoSchema().SchemaMetaVersion() // test set txn as of will flush/mutex tidb_snapshot tk.MustExec(fmt.Sprintf(`set @@tidb_snapshot="%s"`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, time1TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, NotNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, time1TS, tk.Session().GetSessionVars().SnapshotTS) + require.NotNil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec(fmt.Sprintf(`SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time2.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, NotNil) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, time2TS) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + require.NotNil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, time2TS, tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) // test tidb_snapshot will flush/mutex set txn as of tk.MustExec(fmt.Sprintf(`SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, time1TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, NotNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, time1TS, tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) + require.NotNil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec(fmt.Sprintf(`set @@tidb_snapshot="%s"`, time2.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, time2TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, NotNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) + require.Equal(t, time2TS, tk.Session().GetSessionVars().SnapshotTS) + require.NotNil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) // test start txn will flush/mutex tidb_snapshot tk.MustExec(fmt.Sprintf(`set @@tidb_snapshot="%s"`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, time1TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, NotNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, time1TS, tk.Session().GetSessionVars().SnapshotTS) + require.NotNil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec(fmt.Sprintf(`START TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time2.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Equals, time2TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, IsNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + require.Equal(t, time2TS, tk.Session().GetSessionVars().TxnCtx.StartTS) + require.Nil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec("commit") - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, IsNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + require.Nil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) // test snapshot mutex with txn tk.MustExec(fmt.Sprintf(`START TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time2.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Equals, time2TS) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, IsNil) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + require.Equal(t, time2TS, tk.Session().GetSessionVars().TxnCtx.StartTS) + require.Nil(t, tk.Session().GetSessionVars().SnapshotInfoschema) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) err := tk.ExecToErr(`set @@tidb_snapshot="2020-10-08 16:45:26";`) - c.Assert(err, ErrorMatches, ".*Transaction characteristics can't be changed while a transaction is in progress") - c.Assert(tk.Se.GetSessionVars().SnapshotTS, Equals, uint64(0)) - c.Assert(tk.Se.GetSessionVars().SnapshotInfoschema, IsNil) + require.Regexp(t, ".*Transaction characteristics can't be changed while a transaction is in progress", err.Error()) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS) + require.Nil(t, tk.Session().GetSessionVars().SnapshotInfoschema) tk.MustExec("commit") // test set txn as of txn mutex with txn tk.MustExec("START TRANSACTION") - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) err = tk.ExecToErr("SET TRANSACTION READ ONLY AS OF TIMESTAMP '2020-10-08 16:46:26'") - c.Assert(err, ErrorMatches, ".*Transaction characteristics can't be changed while a transaction is in progress") - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Regexp(t, ".*Transaction characteristics can't be changed while a transaction is in progress", err.Error()) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) tk.MustExec("commit") } -func (s *testStaleTxnSerialSuite) TestTimeBoundedStalenessTxn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTimeBoundedStalenessTxn(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key);") @@ -463,57 +497,64 @@ func (s *testStaleTxnSerialSuite) TestTimeBoundedStalenessTxn(c *C) { }, } for _, testcase := range testcases { - c.Log(testcase.name) - c.Assert(failpoint.Enable("tikvclient/injectSafeTS", - fmt.Sprintf("return(%v)", testcase.injectSafeTS)), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectSafeTS", - fmt.Sprintf("return(%v)", testcase.injectSafeTS)), IsNil) + t.Log(testcase.name) + require.NoError(t, failpoint.Enable("tikvclient/injectSafeTS", + fmt.Sprintf("return(%v)", testcase.injectSafeTS))) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectSafeTS", + fmt.Sprintf("return(%v)", testcase.injectSafeTS))) tk.MustExec(testcase.sql) if testcase.compareWithSafeTS == 1 { - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Greater, testcase.injectSafeTS) + require.Greater(t, tk.Session().GetSessionVars().TxnCtx.StartTS, testcase.injectSafeTS) } else if testcase.compareWithSafeTS == 0 { - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Equals, testcase.injectSafeTS) + require.Equal(t, testcase.injectSafeTS, tk.Session().GetSessionVars().TxnCtx.StartTS) } else { - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Less, testcase.injectSafeTS) + require.Less(t, tk.Session().GetSessionVars().TxnCtx.StartTS, testcase.injectSafeTS) } tk.MustExec("commit") } - failpoint.Disable("github.com/pingcap/tidb/expression/injectSafeTS") - failpoint.Disable("tikvclient/injectSafeTS") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/injectSafeTS")) + require.NoError(t, failpoint.Disable("tikvclient/injectSafeTS")) } -func (s *testStaleTxnSerialSuite) TestStalenessTransactionSchemaVer(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStalenessTransactionSchemaVer(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key);") - schemaVer1 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer1 := tk.Session().GetInfoSchema().SchemaMetaVersion() time1 := time.Now() tk.MustExec("alter table t add c int") // confirm schema changed - schemaVer2 := tk.Se.GetInfoSchema().SchemaMetaVersion() - c.Assert(schemaVer1, Less, schemaVer2) + schemaVer2 := tk.Session().GetInfoSchema().SchemaMetaVersion() + require.Less(t, schemaVer1, schemaVer2) // get the specific old schema tk.MustExec(fmt.Sprintf(`START TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) // schema changed back to the newest tk.MustExec("commit") - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) // select does not affect the infoschema tk.MustExec(fmt.Sprintf(`SELECT * from t AS OF TIMESTAMP '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) } -func (s *testStaleTxnSerialSuite) TestSetTransactionReadOnlyAsOf(c *C) { +func TestSetTransactionReadOnlyAsOf(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + t1, err := time.Parse(types.TimeFormat, "2016-09-21 09:53:04") - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, s.store) + require.NoError(t, err) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -540,42 +581,45 @@ func (s *testStaleTxnSerialSuite) TestSetTransactionReadOnlyAsOf(c *C) { } for _, testcase := range testcases { if testcase.injectSafeTS > 0 { - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectSafeTS", - fmt.Sprintf("return(%v)", testcase.injectSafeTS)), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectSafeTS", + fmt.Sprintf("return(%v)", testcase.injectSafeTS))) } tk.MustExec(testcase.sql) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, testcase.expectedTS) + require.Equal(t, testcase.expectedTS, tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) tk.MustExec("begin") - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Equals, testcase.expectedTS) + require.Equal(t, testcase.expectedTS, tk.Session().GetSessionVars().TxnCtx.StartTS) tk.MustExec("commit") - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) tk.MustExec("begin") - c.Assert(tk.Se.GetSessionVars().TxnCtx.StartTS, Not(Equals), testcase.expectedTS) + require.NotEqual(t, tk.Session().GetSessionVars().TxnCtx.StartTS, testcase.expectedTS) tk.MustExec("commit") failpoint.Disable("github.com/pingcap/tidb/expression/injectSafeTS") } err = tk.ExecToErr(`SET TRANSACTION READ ONLY as of timestamp tidb_bounded_staleness(invalid1, invalid2')`) - c.Assert(err, NotNil) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Error(t, err) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) tk.MustExec(`SET TRANSACTION READ ONLY as of timestamp '2021-04-21 00:42:12'`) err = tk.ExecToErr(`START TRANSACTION READ ONLY AS OF TIMESTAMP '2020-09-06 00:00:00'`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "start transaction read only as of is forbidden after set transaction read only as of") + require.Error(t, err) + require.Equal(t, "start transaction read only as of is forbidden after set transaction read only as of", err.Error()) tk.MustExec(`SET TRANSACTION READ ONLY as of timestamp '2021-04-21 00:42:12'`) err = tk.ExecToErr(`START TRANSACTION READ ONLY AS OF TIMESTAMP '2020-09-06 00:00:00'`) - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "start transaction read only as of is forbidden after set transaction read only as of") + require.Error(t, err) + require.Equal(t, "start transaction read only as of is forbidden after set transaction read only as of", err.Error()) tk.MustExec("begin") - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(424394603102208000)) + require.Equal(t, uint64(424394603102208000), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) tk.MustExec("commit") tk.MustExec(`START TRANSACTION READ ONLY AS OF TIMESTAMP '2020-09-06 00:00:00'`) } -func (s *testStaleTxnSerialSuite) TestValidateReadOnlyInStalenessTransaction(c *C) { +func TestValidateReadOnlyInStalenessTransaction(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + errMsg1 := ".*only support read-only statement during read-only staleness transactions.*" errMsg2 := ".*select lock hasn't been supported in stale read yet.*" testcases := []struct { @@ -713,7 +757,9 @@ func (s *testStaleTxnSerialSuite) TestValidateReadOnlyInStalenessTransaction(c * errMsg: errMsg1, }, } - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -729,14 +775,14 @@ func (s *testStaleTxnSerialSuite) TestValidateReadOnlyInStalenessTransaction(c * tk.MustExec(`PREPARE stmt2 FROM 'select * from t';`) tk.MustExec(`set @@tidb_enable_noop_functions=1;`) for _, testcase := range testcases { - c.Log(testcase.name) + t.Log(testcase.name) tk.MustExec(`START TRANSACTION READ ONLY AS OF TIMESTAMP NOW(3);`) if testcase.isValidate { tk.MustExec(testcase.sql) } else { err := tk.ExecToErr(testcase.sql) - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, testcase.errMsg) + require.Error(t, err) + require.Regexp(t, testcase.errMsg, err.Error()) } tk.MustExec("commit") tk.MustExec("set transaction read only as of timestamp NOW(3);") @@ -744,16 +790,21 @@ func (s *testStaleTxnSerialSuite) TestValidateReadOnlyInStalenessTransaction(c * tk.MustExec(testcase.sql) } else { err := tk.ExecToErr(testcase.sql) - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, testcase.errMsg) + require.Error(t, err) + require.Regexp(t, testcase.errMsg, err.Error()) } // clean the status tk.MustExec("set transaction read only as of timestamp ''") } } -func (s *testStaleTxnSuite) TestSpecialSQLInStalenessTxn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSpecialSQLInStalenessTxn(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") testcases := []struct { name string @@ -798,16 +849,20 @@ func (s *testStaleTxnSuite) TestSpecialSQLInStalenessTxn(c *C) { } tk.MustExec("CREATE USER 'newuser' IDENTIFIED BY 'mypassword';") for _, testcase := range testcases { - comment := Commentf(testcase.name) tk.MustExec(`START TRANSACTION READ ONLY AS OF TIMESTAMP NOW(3);`) - c.Assert(tk.Se.GetSessionVars().TxnCtx.IsStaleness, Equals, true, comment) + require.Equal(t, true, tk.Session().GetSessionVars().TxnCtx.IsStaleness, testcase.name) tk.MustExec(testcase.sql) - c.Assert(tk.Se.GetSessionVars().TxnCtx.IsStaleness, Equals, testcase.sameSession, comment) + require.Equal(t, testcase.sameSession, tk.Session().GetSessionVars().TxnCtx.IsStaleness, testcase.name) } } -func (s *testStaleTxnSuite) TestAsOfTimestampCompatibility(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAsOfTimestampCompatibility(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -852,17 +907,22 @@ func (s *testStaleTxnSuite) TestAsOfTimestampCompatibility(c *C) { for _, testcase := range testcases { tk.MustExec(testcase.beginSQL) err := tk.ExecToErr(testcase.sql) - c.Assert(err, ErrorMatches, ".*as of timestamp can't be set in transaction.*|.*Transaction characteristics can't be changed while a transaction is in progress") + require.Regexp(t, ".*as of timestamp can't be set in transaction.*|.*Transaction characteristics can't be changed while a transaction is in progress", err.Error()) tk.MustExec("commit") } tk.MustExec(`create table test.table1 (id int primary key, a int);`) - defer tk.MustExec("drop table if exists test.table1;") time1 = time.Now() tk.MustExec(fmt.Sprintf("explain analyze select * from test.table1 as of timestamp '%s' where id = 1;", time1.Format("2006-1-2 15:04:05.000"))) + tk.MustExec("drop table if exists test.table1;") } -func (s *testStaleTxnSuite) TestSetTransactionInfoSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetTransactionInfoSchema(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -876,32 +936,37 @@ func (s *testStaleTxnSuite) TestSetTransactionInfoSchema(c *C) { defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key);") - schemaVer1 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer1 := tk.Session().GetInfoSchema().SchemaMetaVersion() time1 := time.Now() tk.MustExec("alter table t add c int") // confirm schema changed - schemaVer2 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer2 := tk.Session().GetInfoSchema().SchemaMetaVersion() time2 := time.Now() - c.Assert(schemaVer1, Less, schemaVer2) + require.Less(t, schemaVer1, schemaVer2) tk.MustExec(fmt.Sprintf(`SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec("select * from t;") tk.MustExec("alter table t add d int") - schemaVer3 := tk.Se.GetInfoSchema().SchemaMetaVersion() + schemaVer3 := tk.Session().GetInfoSchema().SchemaMetaVersion() tk.MustExec(fmt.Sprintf(`SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time1.Format("2006-1-2 15:04:05.000"))) tk.MustExec("begin;") - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer1) + require.Equal(t, schemaVer1, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec("commit") tk.MustExec(fmt.Sprintf(`SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'`, time2.Format("2006-1-2 15:04:05.000"))) tk.MustExec("begin;") - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer2) + require.Equal(t, schemaVer2, tk.Session().GetInfoSchema().SchemaMetaVersion()) tk.MustExec("commit") - c.Assert(tk.Se.GetInfoSchema().SchemaMetaVersion(), Equals, schemaVer3) + require.Equal(t, schemaVer3, tk.Session().GetInfoSchema().SchemaMetaVersion()) } -func (s *testStaleTxnSerialSuite) TestStaleSelect(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleSelect(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -928,7 +993,7 @@ func (s *testStaleTxnSerialSuite) TestStaleSelect(c *C) { // test stale select in txn tk.MustExec("begin") - c.Assert(tk.ExecToErr(staleSQL), NotNil) + require.NotNil(t, tk.ExecToErr(staleSQL)) tk.MustExec("commit") // test prepared stale select @@ -937,12 +1002,12 @@ func (s *testStaleTxnSerialSuite) TestStaleSelect(c *C) { // test prepared stale select in txn tk.MustExec("begin") - c.Assert(tk.ExecToErr(staleSQL), NotNil) + require.NotNil(t, tk.ExecToErr(staleSQL)) tk.MustExec("commit") // test stale select in stale txn tk.MustExec(fmt.Sprintf(`start transaction read only as of timestamp '%s'`, time2.Format("2006-1-2 15:04:05.000"))) - c.Assert(tk.ExecToErr(staleSQL), NotNil) + require.NotNil(t, tk.ExecToErr(staleSQL)) tk.MustExec("commit") // test prepared stale select with schema change @@ -961,29 +1026,36 @@ func (s *testStaleTxnSerialSuite) TestStaleSelect(c *C) { tk.MustQuery(fmt.Sprintf("select * from t as of timestamp '%s' where c=5", time6.Format("2006-1-2 15:04:05.000"))).Check(testkit.Rows("4 5 ")) } -func (s *testStaleTxnSuite) TestStaleReadFutureTime(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleReadFutureTime(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int)") // Setting tx_read_ts to a time in the future will fail. (One day before the 2038 problem) _, err := tk.Exec("start transaction read only as of timestamp '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") + require.Regexp(t, "cannot set read timestamp to a future time", err.Error()) // Transaction should not be started and read ts should not be set if check fails - c.Assert(tk.Se.GetSessionVars().InTxn(), IsFalse) - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.False(t, tk.Session().GetSessionVars().InTxn()) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) _, err = tk.Exec("set transaction read only as of timestamp '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") - c.Assert(tk.Se.GetSessionVars().TxnReadTS.PeakTxnReadTS(), Equals, uint64(0)) + require.Regexp(t, "cannot set read timestamp to a future time", err.Error()) + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) _, err = tk.Exec("select * from t as of timestamp '2038-01-18 03:14:07'") - c.Assert(err, ErrorMatches, "cannot set read timestamp to a future time") + require.Regexp(t, "cannot set read timestamp to a future time", err.Error()) } -func (s *testStaleTxnSerialSuite) TestStaleReadPrepare(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleReadPrepare(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -1016,16 +1088,33 @@ func (s *testStaleTxnSerialSuite) TestStaleReadPrepare(c *C) { // test prepared stale select in stale txn tk.MustExec(fmt.Sprintf(`start transaction read only as of timestamp '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert("execute p1", NotNil) + _, err := tk.Exec("execute p1") + require.Error(t, err) tk.MustExec("commit") // assert execute prepared statement should be error after set transaction read only as of tk.MustExec(fmt.Sprintf(`set transaction read only as of timestamp '%s'`, time1.Format("2006-1-2 15:04:05.000"))) - c.Assert("execute p1", NotNil) + _, err = tk.Exec("execute p1") + require.Error(t, err) + tk.MustExec("execute p2") + + tk.MustExec("create table t1 (id int, v int)") + tk.MustExec("insert into t1 values (1,10)") + tk.MustExec("set @a=now(6)") + time.Sleep(5 * time.Millisecond) + tk.MustExec("update t1 set v=100 where id=1") + tk.MustQuery("select * from t1").Check(testkit.Rows("1 100")) + tk.MustExec("prepare s1 from 'select * from t1 as of timestamp @a where id=1'") + tk.MustQuery("execute s1").Check(testkit.Rows("1 10")) } -func (s *testStaleTxnSerialSuite) TestStmtCtxStaleFlag(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStmtCtxStaleFlag(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -1111,14 +1200,19 @@ func (s *testStaleTxnSerialSuite) TestStmtCtxStaleFlag(c *C) { failpoint.Enable("github.com/pingcap/tidb/exector/assertStmtCtxIsStaleness", fmt.Sprintf("return(%v)", testcase.hasStaleFlag)) tk.MustExec(testcase.sql) - failpoint.Disable("github.com/pingcap/tidb/exector/assertStmtCtxIsStaleness") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/exector/assertStmtCtxIsStaleness")) // assert stale read flag should be false after each statement execution - c.Assert(tk.Se.GetSessionVars().StmtCtx.IsStaleness, IsFalse) + require.False(t, tk.Session().GetSessionVars().StmtCtx.IsStaleness) } } -func (s *testStaleTxnSerialSuite) TestStaleSessionQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleSessionQuery(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -1134,29 +1228,34 @@ func (s *testStaleTxnSerialSuite) TestStaleSessionQuery(c *C) { now := time.Now() tk.MustExec(`set @@tidb_read_staleness="-1"`) // query will use stale read - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix())), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-1)), IsNil) - c.Assert(tk.MustQuery("select * from t10;").Rows(), HasLen, 1) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/expression/injectNow"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix()))) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-1))) + require.Len(t, tk.MustQuery("select * from t10;").Rows(), 1) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/injectNow")) // begin transaction won't be affected by read staleness tk.MustExec("begin") tk.MustExec("insert into t10(id) values (2);") tk.MustExec("commit") tk.MustExec("insert into t10(id) values (3);") // query will still use staleness read - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix())), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-1)), IsNil) - c.Assert(tk.MustQuery("select * from t10").Rows(), HasLen, 1) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/expression/injectNow"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix()))) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleTSO", fmt.Sprintf(`return(%d)`, now.Unix()-1))) + require.Len(t, tk.MustQuery("select * from t10").Rows(), 1) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleTSO")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/injectNow")) // assert stale read is not exist after empty the variable tk.MustExec(`set @@tidb_read_staleness=""`) - c.Assert(tk.MustQuery("select * from t10").Rows(), HasLen, 3) + require.Len(t, tk.MustQuery("select * from t10").Rows(), 3) } -func (s *testStaleTxnSerialSuite) TestStaleReadCompatibility(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleReadCompatibility(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer tk.MustExec("drop table if exists t") @@ -1171,36 +1270,41 @@ func (s *testStaleTxnSerialSuite) TestStaleReadCompatibility(c *C) { // assert select as of timestamp won't work after set transaction read only as of timestamp tk.MustExec(fmt.Sprintf("set transaction read only as of timestamp '%s';", t1.Format("2006-1-2 15:04:05"))) err := tk.ExecToErr(fmt.Sprintf("select * from t as of timestamp '%s';", t1.Format("2006-1-2 15:04:05"))) - c.Assert(err, NotNil) - c.Assert(err.Error(), Matches, ".*invalid as of timestamp: can't use select as of while already set transaction as of.*") + require.Error(t, err) + require.Regexp(t, ".*invalid as of timestamp: can't use select as of while already set transaction as of.*", err.Error()) // assert set transaction read only as of timestamp is consumed - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 3) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 3) // enable tidb_read_staleness tk.MustExec("set @@tidb_read_staleness='-1'") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, t1.Unix())), IsNil) - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 1) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, t1.Unix()))) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 1) // assert select as of timestamp during tidb_read_staleness - c.Assert(tk.MustQuery(fmt.Sprintf("select * from t as of timestamp '%s'", t2.Format("2006-1-2 15:04:05"))).Rows(), HasLen, 2) + require.Len(t, tk.MustQuery(fmt.Sprintf("select * from t as of timestamp '%s'", t2.Format("2006-1-2 15:04:05"))).Rows(), 2) // assert set transaction as of timestamp during tidb_read_staleness tk.MustExec(fmt.Sprintf("set transaction read only as of timestamp '%s';", t2.Format("2006-1-2 15:04:05"))) - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 2) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 2) // assert begin stale transaction during tidb_read_staleness tk.MustExec(fmt.Sprintf("start transaction read only as of timestamp '%v'", t2.Format("2006-1-2 15:04:05"))) - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 2) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 2) tk.MustExec("commit") // assert session query still is affected by tidb_read_staleness - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 1) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 1) // disable tidb_read_staleness tk.MustExec("set @@tidb_read_staleness=''") - c.Assert(tk.MustQuery("select * from t;").Rows(), HasLen, 3) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/expression/injectNow"), IsNil) + require.Len(t, tk.MustQuery("select * from t;").Rows(), 3) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/expression/injectNow")) } -func (s *testStaleTxnSerialSuite) TestStaleReadNoExtraTSORequest(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStaleReadNoExtraTSORequest(t *testing.T) { + disableCommonFailPoint := enableStalereadCommonFailPoint(t) + defer disableCommonFailPoint() + + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. safePointName := "tikv_gc_safe_point" safePointValue := "20160102-15:04:05 -0700" @@ -1214,34 +1318,104 @@ func (s *testStaleTxnSerialSuite) TestStaleReadNoExtraTSORequest(c *C) { tk.MustExec("create table t (id int);") time.Sleep(3 * time.Second) // statement stale read - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`)) tk.MustQuery("select * from t as of timestamp NOW() - INTERVAL 2 SECOND") - failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest")) // set and statement stale read tk.MustExec("set transaction read only as of timestamp NOW() - INTERVAL 2 SECOND") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`)) tk.MustQuery("select * from t") - failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest")) // stale read transaction - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`)) tk.MustExec("start transaction read only as of timestamp NOW() - INTERVAL 2 SECOND") tk.MustQuery("select * from t") tk.MustExec("commit") - failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest")) // set and stale read transaction tk.MustExec("set transaction read only as of timestamp NOW() - INTERVAL 2 SECOND") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`)) tk.MustExec("begin") tk.MustQuery("select * from t") tk.MustExec("commit") - failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest")) // use tidb_read_staleness tk.MustExec(`set @@tidb_read_staleness='-1'`) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTSONotRequest", `return(true)`)) tk.MustQuery("select * from t") - failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTSONotRequest")) +} + +func TestPlanCacheWithStaleReadByBinaryProto(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (id int primary key, v int)") + tk.MustExec("insert into t1 values(1, 10)") + se := tk.Session() + time.Sleep(time.Millisecond * 100) + tk.MustExec("set @a=now(6)") + time.Sleep(time.Second) + tk.MustExec("update t1 set v=100 where id=1") + stmtID1, _, _, err := se.PrepareStmt("select * from t1 as of timestamp @a where id=1") + require.NoError(t, err) + + for i := 0; i < 3; i++ { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID1, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + } + + stmtID2, _, _, err := se.PrepareStmt("select * from t1 where id=1") + require.NoError(t, err) + for i := 0; i < 2; i++ { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID2, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 100")) + } + tk.MustExec("set @@tx_read_ts=@a") + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID2, nil) + require.NoError(t, err) + // will fail + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) +} + +func TestIssue30872(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_txn_mode='pessimistic'") + tk.MustExec("set tx_isolation = 'READ-COMMITTED'") + tk.MustExec("create table t1 (id int primary key, v int)") + tk.MustExec("insert into t1 values(1, 10)") + time.Sleep(time.Millisecond * 100) + tk.MustExec("set @a=now(6)") + time.Sleep(time.Millisecond * 100) + tk.MustExec("update t1 set v=100 where id=1") + tk.MustExec("set autocommit=0") + tk.MustQuery("select * from t1 as of timestamp @a").Check(testkit.Rows("1 10")) +} + +func TestIssue33728(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (id int primary key, v int)") + err := tk.ExecToErr("select * from t1 as of timestamp NULL") + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: as of timestamp cannot be NULL", err.Error()) + + err = tk.ExecToErr("start transaction read only as of timestamp NULL") + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: as of timestamp cannot be NULL", err.Error()) } diff --git a/executor/statement_context_test.go b/executor/statement_context_test.go index be0548cd6c268..32720bd6cc36b 100644 --- a/executor/statement_context_test.go +++ b/executor/statement_context_test.go @@ -16,13 +16,14 @@ package executor_test import ( "fmt" + "testing" "unicode/utf8" - . "github.com/pingcap/check" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) const ( @@ -30,8 +31,10 @@ const ( nonStrictModeSQL = "set sql_mode = ''" ) -func (s *testSuite1) TestStatementContext(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStatementContext(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table sc (a int)") tk.MustExec("insert sc values (1), (2)") @@ -53,9 +56,9 @@ func (s *testSuite1) TestStatementContext(c *C) { // UPDATE and DELETE do select request first which is handled by coprocessor. // In strict mode we expect error. _, err := tk.Exec("update sc set a = 4 where a > '1x'") - c.Assert(err, NotNil) + require.Error(t, err) _, err = tk.Exec("delete from sc where a < '1x'") - c.Assert(err, NotNil) + require.Error(t, err) tk.MustQuery("select * from sc where a > '1x'").Check(testkit.Rows("3")) // Non-strict mode never returns error. @@ -68,16 +71,16 @@ func (s *testSuite1) TestStatementContext(c *C) { tk.MustExec("create table sc2 (a varchar(255))") // Insert an invalid UTF8 tk.MustExec("insert sc2 values (unhex('4040ffff'))") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Greater, uint16(0)) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.WarningCount(), uint16(0)) tk.MustQuery("select * from sc2").Check(testkit.Rows("@@")) tk.MustExec(strictModeSQL) _, err = tk.Exec("insert sc2 values (unhex('4040ffff'))") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), "err %v", err) tk.MustExec("set @@tidb_skip_utf8_check = '1'") _, err = tk.Exec("insert sc2 values (unhex('4040ffff'))") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery("select length(a) from sc2").Check(testkit.Rows("2", "4")) tk.MustExec("set @@tidb_skip_utf8_check = '0'") @@ -89,17 +92,17 @@ func (s *testSuite1) TestStatementContext(c *C) { tk.MustExec(nonStrictModeSQL) tk.MustExec("insert sc3 values (unhex('4040ffff'))") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Greater, uint16(0)) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.WarningCount(), uint16(0)) tk.MustQuery("select * from sc3").Check(testkit.Rows("@@")) tk.MustExec(strictModeSQL) _, err = tk.Exec("insert sc3 values (unhex('4040ffff'))") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), "err %v", err) tk.MustExec("set @@tidb_skip_ascii_check = '1'") _, err = tk.Exec("insert sc3 values (unhex('4040ffff'))") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery("select length(a) from sc3").Check(testkit.Rows("2", "4")) // no placeholder in ASCII, so just insert '@@'... @@ -112,26 +115,26 @@ func (s *testSuite1) TestStatementContext(c *C) { tk.MustExec("create table t1(a varchar(100) charset utf8);") defer tk.MustExec("drop table if exists t1") tk.MustExec("insert t1 values (unhex('f09f8c80'))") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Greater, uint16(0)) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.WarningCount(), uint16(0)) tk.MustQuery("select * from t1").Check(testkit.Rows("")) tk.MustExec("insert t1 values (unhex('4040f09f8c80'))") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Greater, uint16(0)) + require.Greater(t, tk.Session().GetSessionVars().StmtCtx.WarningCount(), uint16(0)) tk.MustQuery("select * from t1").Check(testkit.Rows("", "@@")) tk.MustQuery("select length(a) from t1").Check(testkit.Rows("0", "2")) tk.MustExec(strictModeSQL) _, err = tk.Exec("insert t1 values (unhex('f09f8c80'))") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), "err %v", err) _, err = tk.Exec("insert t1 values (unhex('F0A48BAE'))") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), IsTrue, Commentf("err %v", err)) + require.Error(t, err) + require.Truef(t, terror.ErrorEqual(err, table.ErrTruncatedWrongValueForField), "err %v", err) config.UpdateGlobal(func(conf *config.Config) { - conf.CheckMb4ValueInUTF8 = false + conf.CheckMb4ValueInUTF8.Store(false) }) tk.MustExec("insert t1 values (unhex('f09f8c80'))") config.UpdateGlobal(func(conf *config.Config) { - conf.CheckMb4ValueInUTF8 = true + conf.CheckMb4ValueInUTF8.Store(true) }) _, err = tk.Exec("insert t1 values (unhex('F0A48BAE'))") - c.Assert(err, NotNil) + require.Error(t, err) } diff --git a/executor/table_reader.go b/executor/table_reader.go index 958b8cc442061..a9decdd55b1a7 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -17,13 +17,14 @@ package executor import ( "context" "sort" + "time" "github.com/opentracing/opentracing-go" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/statistics" @@ -55,7 +56,7 @@ func (sr selectResultHook) SelectResult(ctx context.Context, sctx sessionctx.Con } type kvRangeBuilder interface { - buildKeyRange(pid int64, ranges []*ranger.Range) ([]kv.KeyRange, error) + buildKeyRange(ranges []*ranger.Range) ([]kv.KeyRange, error) buildKeyRangeSeparately(ranges []*ranger.Range) ([]int64, [][]kv.KeyRange, error) } @@ -109,23 +110,18 @@ type TableReaderExecutor struct { // batchCop indicates whether use super batch coprocessor request, only works for TiFlash engine. batchCop bool - // extraPIDColumnIndex is used for partition reader to add an extra partition ID column. - extraPIDColumnIndex offsetOptional + // If dummy flag is set, this is not a real TableReader, it just provides the KV ranges for UnionScan. + // Used by the temporary table, cached table. + dummy bool } -// offsetOptional may be a positive integer, or invalid. -type offsetOptional int - -func newOffset(i int) offsetOptional { - return offsetOptional(i + 1) -} - -func (i offsetOptional) valid() bool { - return i != 0 +// Table implements the dataSourceExecutor interface. +func (e *TableReaderExecutor) Table() table.Table { + return e.table } -func (i offsetOptional) value() int { - return int(i - 1) +func (e *TableReaderExecutor) setDummy() { + e.dummy = true } // Open initializes necessary variables for using this executor. @@ -135,6 +131,10 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { defer span1.Finish() ctx = opentracing.ContextWithSpan(ctx, span1) } + failpoint.Inject("mockSleepInTableReaderNext", func(v failpoint.Value) { + ms := v.(int) + time.Sleep(time.Millisecond * time.Duration(ms)) + }) e.memTracker = memory.NewTracker(e.id, -1) e.memTracker.AttachTo(e.ctx.GetSessionVars().StmtCtx.MemTracker) @@ -180,7 +180,18 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Treat temporary table as dummy table, avoid sending distsql request to TiKV. // Calculate the kv ranges here, UnionScan rely on this kv ranges. // cached table and temporary table are similar - if e.table.Meta() != nil && e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { + if e.desc && len(secondPartRanges) != 0 { + // TiKV support reverse scan and the `resultHandler` process the range order. + // While in UnionScan, it doesn't use reverse scan and reverse the final result rows manually. + // So things are differ, we need to reverse the kv range here. + // TODO: If we refactor UnionScan to use reverse scan, update the code here. + // [9734095886065816708 9734095886065816709] | [1 3] [65535 9734095886065816707] => before the following change + // [1 3] [65535 9734095886065816707] | [9734095886065816708 9734095886065816709] => ranges part reverse here + // [1 3 65535 9734095886065816707 9734095886065816708 9734095886065816709] => scan (normal order) in UnionScan + // [9734095886065816709 9734095886065816708 9734095886065816707 65535 3 1] => rows reverse in UnionScan + firstPartRanges, secondPartRanges = secondPartRanges, firstPartRanges + } kvReq, err := e.buildKVReq(ctx, firstPartRanges) if err != nil { return err @@ -218,7 +229,7 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Next fills data into the chunk passed by its caller. // The task was actually done by tableReaderHandler. func (e *TableReaderExecutor) Next(ctx context.Context, req *chunk.Chunk) error { - if e.table.Meta() != nil && e.table.Meta().TempTableType != model.TempTableNone { + if e.dummy { // Treat temporary table as dummy table, avoid sending distsql request to TiKV. req.Reset() return nil @@ -241,37 +252,19 @@ func (e *TableReaderExecutor) Next(ctx context.Context, req *chunk.Chunk) error return err } - // When 'select ... for update' work on a partitioned table, the table reader should - // add the partition ID as an extra column. The SelectLockExec need this information - // to construct the lock key. - physicalID := getPhysicalTableID(e.table) - if e.extraPIDColumnIndex.valid() { - fillExtraPIDColumn(req, e.extraPIDColumnIndex.value(), physicalID) - } - return nil } -func fillExtraPIDColumn(req *chunk.Chunk, extraPIDColumnIndex int, physicalID int64) { - numRows := req.NumRows() - pidColumn := chunk.NewColumn(types.NewFieldType(mysql.TypeLonglong), numRows) - for i := 0; i < numRows; i++ { - pidColumn.AppendInt64(physicalID) - } - req.SetCol(extraPIDColumnIndex, pidColumn) -} - // Close implements the Executor Close interface. func (e *TableReaderExecutor) Close() error { - if e.table.Meta() != nil && e.table.Meta().TempTableType != model.TempTableNone { - return nil - } - var err error if e.resultHandler != nil { err = e.resultHandler.Close() } e.kvRanges = e.kvRanges[:0] + if e.dummy { + return nil + } e.ctx.StoreQueryFeedback(e.feedback) return err } @@ -280,20 +273,32 @@ func (e *TableReaderExecutor) Close() error { // to fetch all results. func (e *TableReaderExecutor) buildResp(ctx context.Context, ranges []*ranger.Range) (distsql.SelectResult, error) { if e.storeType == kv.TiFlash && e.kvRangeBuilder != nil { - // TiFlash cannot support to access multiple tables/partitions within one KVReq, so we have to build KVReq for each partition separately. - kvReqs, err := e.buildKVReqSeparately(ctx, ranges) - if err != nil { - return nil, err - } - var results []distsql.SelectResult - for _, kvReq := range kvReqs { - result, err := e.SelectResult(ctx, e.ctx, kvReq, retTypes(e), e.feedback, getPhysicalPlanIDs(e.plans), e.id) + if !e.batchCop { + // TiFlash cannot support to access multiple tables/partitions within one KVReq, so we have to build KVReq for each partition separately. + kvReqs, err := e.buildKVReqSeparately(ctx, ranges) if err != nil { return nil, err } - results = append(results, result) + var results []distsql.SelectResult + for _, kvReq := range kvReqs { + result, err := e.SelectResult(ctx, e.ctx, kvReq, retTypes(e), e.feedback, getPhysicalPlanIDs(e.plans), e.id) + if err != nil { + return nil, err + } + results = append(results, result) + } + return distsql.NewSerialSelectResults(results), nil + } + // Use PartitionTable Scan + kvReq, err := e.buildKVReqForPartitionTableScan(ctx, ranges) + if err != nil { + return nil, err + } + result, err := e.SelectResult(ctx, e.ctx, kvReq, retTypes(e), e.feedback, getPhysicalPlanIDs(e.plans), e.id) + if err != nil { + return nil, err } - return distsql.NewSerialSelectResults(results), nil + return result, nil } kvReq, err := e.buildKVReq(ctx, ranges) @@ -314,10 +319,10 @@ func (e *TableReaderExecutor) buildKVReqSeparately(ctx context.Context, ranges [ if err != nil { return nil, err } - var kvReqs []*kv.Request + kvReqs := make([]*kv.Request, 0, len(kvRanges)) for i, kvRange := range kvRanges { e.kvRanges = append(e.kvRanges, kvRange...) - if err := updateExecutorTableID(ctx, e.dagPB.RootExecutor, pids[i], true); err != nil { + if err := updateExecutorTableID(ctx, e.dagPB.RootExecutor, true, []int64{pids[i]}); err != nil { return nil, err } var builder distsql.RequestBuilder @@ -342,11 +347,47 @@ func (e *TableReaderExecutor) buildKVReqSeparately(ctx context.Context, ranges [ return kvReqs, nil } +func (e *TableReaderExecutor) buildKVReqForPartitionTableScan(ctx context.Context, ranges []*ranger.Range) (*kv.Request, error) { + pids, kvRanges, err := e.kvRangeBuilder.buildKeyRangeSeparately(ranges) + if err != nil { + return nil, err + } + partitionIDAndRanges := make([]kv.PartitionIDAndRanges, 0, len(pids)) + for i, kvRange := range kvRanges { + e.kvRanges = append(e.kvRanges, kvRange...) + partitionIDAndRanges = append(partitionIDAndRanges, kv.PartitionIDAndRanges{ + ID: pids[i], + KeyRanges: kvRange, + }) + } + if err := updateExecutorTableID(ctx, e.dagPB.RootExecutor, true, pids); err != nil { + return nil, err + } + var builder distsql.RequestBuilder + reqBuilder := builder.SetPartitionIDAndRanges(partitionIDAndRanges) + kvReq, err := reqBuilder. + SetDAGRequest(e.dagPB). + SetStartTS(e.startTS). + SetDesc(e.desc). + SetKeepOrder(e.keepOrder). + SetStreaming(e.streaming). + SetReadReplicaScope(e.readReplicaScope). + SetFromSessionVars(e.ctx.GetSessionVars()). + SetFromInfoSchema(e.ctx.GetInfoSchema()). + SetMemTracker(e.memTracker). + SetStoreType(e.storeType). + SetAllowBatchCop(e.batchCop).Build() + if err != nil { + return nil, err + } + return kvReq, nil +} + func (e *TableReaderExecutor) buildKVReq(ctx context.Context, ranges []*ranger.Range) (*kv.Request, error) { var builder distsql.RequestBuilder var reqBuilder *distsql.RequestBuilder if e.kvRangeBuilder != nil { - kvRange, err := e.kvRangeBuilder.buildKeyRange(getPhysicalTableID(e.table), ranges) + kvRange, err := e.kvRangeBuilder.buildKeyRange(ranges) if err != nil { return nil, err } diff --git a/executor/table_readers_required_rows_test.go b/executor/table_readers_required_rows_test.go index 69ed5fc7fab7f..73044de929a8e 100644 --- a/executor/table_readers_required_rows_test.go +++ b/executor/table_readers_required_rows_test.go @@ -18,9 +18,9 @@ import ( "context" "fmt" "math/rand" + "testing" "github.com/cznic/mathutil" - . "github.com/pingcap/check" "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tipb/go-tipb" + "github.com/stretchr/testify/require" ) type requiredRowsSelectResult struct { @@ -153,7 +154,7 @@ func buildMockBaseExec(sctx sessionctx.Context) baseExecutor { return baseExec } -func (s *testExecSuite) TestTableReaderRequiredRows(c *C) { +func TestTableReaderRequiredRows(t *testing.T) { maxChunkSize := defaultCtx().GetSessionVars().MaxChunkSize testCases := []struct { totalRows int @@ -184,14 +185,14 @@ func (s *testExecSuite) TestTableReaderRequiredRows(c *C) { sctx := defaultCtx() ctx := mockDistsqlSelectCtxSet(testCase.totalRows, testCase.expectedRowsDS) exec := buildTableReader(sctx) - c.Assert(exec.Open(ctx), IsNil) + require.NoError(t, exec.Open(ctx)) chk := newFirstChunk(exec) for i := range testCase.requiredRows { chk.SetRequiredRows(testCase.requiredRows[i], maxChunkSize) - c.Assert(exec.Next(ctx, chk), IsNil) - c.Assert(chk.NumRows(), Equals, testCase.expectedRows[i]) + require.NoError(t, exec.Next(ctx, chk)) + require.Equal(t, testCase.expectedRows[i], chk.NumRows()) } - c.Assert(exec.Close(), IsNil) + require.NoError(t, exec.Close()) } } @@ -205,7 +206,7 @@ func buildIndexReader(sctx sessionctx.Context) Executor { return e } -func (s *testExecSuite) TestIndexReaderRequiredRows(c *C) { +func TestIndexReaderRequiredRows(t *testing.T) { maxChunkSize := defaultCtx().GetSessionVars().MaxChunkSize testCases := []struct { totalRows int @@ -236,13 +237,13 @@ func (s *testExecSuite) TestIndexReaderRequiredRows(c *C) { sctx := defaultCtx() ctx := mockDistsqlSelectCtxSet(testCase.totalRows, testCase.expectedRowsDS) exec := buildIndexReader(sctx) - c.Assert(exec.Open(ctx), IsNil) + require.NoError(t, exec.Open(ctx)) chk := newFirstChunk(exec) for i := range testCase.requiredRows { chk.SetRequiredRows(testCase.requiredRows[i], maxChunkSize) - c.Assert(exec.Next(ctx, chk), IsNil) - c.Assert(chk.NumRows(), Equals, testCase.expectedRows[i]) + require.NoError(t, exec.Next(ctx, chk)) + require.Equal(t, testCase.expectedRows[i], chk.NumRows()) } - c.Assert(exec.Close(), IsNil) + require.NoError(t, exec.Close()) } } diff --git a/executor/testdata/agg_suite_out.json b/executor/testdata/agg_suite_out.json index abfb0f9d102ef..1937b7f4cc358 100644 --- a/executor/testdata/agg_suite_out.json +++ b/executor/testdata/agg_suite_out.json @@ -54,7 +54,7 @@ " ├─Apply(Build) 1.00 root CARTESIAN left outer join", " │ ├─Apply(Build) 1.00 root CARTESIAN left outer join", " │ │ ├─HashAgg(Build) 1.00 root funcs:sum(Column#28)->Column#9, funcs:firstrow(Column#29)->test.test.a", - " │ │ │ └─Projection 10000.00 root cast(test.test.a, decimal(32,0) BINARY)->Column#28, test.test.a", + " │ │ │ └─Projection 10000.00 root cast(test.test.a, decimal(10,0) BINARY)->Column#28, test.test.a", " │ │ │ └─TableReader 10000.00 root data:TableFullScan", " │ │ │ └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo", " │ │ └─Projection(Probe) 1.00 root ->Column#12", diff --git a/executor/testdata/prepare_suite_out.json b/executor/testdata/prepare_suite_out.json index dafdd1114bbfd..93adc89312160 100644 --- a/executor/testdata/prepare_suite_out.json +++ b/executor/testdata/prepare_suite_out.json @@ -63,7 +63,7 @@ "Projection_3 1.00 root 10->Column#1, cba->Column#2", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "10 cba" ] @@ -253,7 +253,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1234567" ] @@ -270,7 +270,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1" ] @@ -287,7 +287,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "99999" ] @@ -304,7 +304,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:79)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-123456789" ] @@ -321,7 +321,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1234567" ] @@ -338,7 +338,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1" ] @@ -355,7 +355,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-99999" ] @@ -394,7 +394,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1234567" ] @@ -411,7 +411,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1" ] @@ -428,7 +428,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "99999" ] @@ -445,7 +445,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:79)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-123456789" ] @@ -462,7 +462,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1234567" ] @@ -479,7 +479,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1" ] @@ -496,7 +496,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(10,0) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-99999" ] @@ -535,7 +535,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "9.9999" ] @@ -552,7 +552,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1.0000" ] @@ -569,7 +569,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "9.9999" ] @@ -586,7 +586,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:78)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-9.9999" ] @@ -603,7 +603,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-9.9999" ] @@ -620,7 +620,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1.0000" ] @@ -637,7 +637,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(5,4) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-9.9999" ] @@ -676,7 +676,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1234567.123456700000000000000000000000" ] @@ -693,7 +693,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "0.999990000000000000000000000000" ] @@ -710,7 +710,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "99999.000000000000000000000000000000" ] @@ -727,7 +727,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:80)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-123456789.012345678901234567890123456789" ] @@ -744,7 +744,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1234567.123456700000000000000000000000" ] @@ -761,7 +761,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.999990000000000000000000000000" ] @@ -778,7 +778,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(64,30) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-99999.000000000000000000000000000000" ] @@ -817,7 +817,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "1234567.12346" ] @@ -834,7 +834,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "0.99999" ] @@ -851,7 +851,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "99999.00000" ] @@ -868,7 +868,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:79)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-123456789.01235" ] @@ -885,7 +885,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-1234567.12346" ] @@ -902,7 +902,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.99999" ] @@ -919,7 +919,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(15,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-99999.00000" ] @@ -958,7 +958,7 @@ "Projection_3 1.00 root cast(1234567.1234567, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "0.99999" ] @@ -975,7 +975,7 @@ "Projection_3 1.00 root cast(0.99999, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "0.99999" ] @@ -992,7 +992,7 @@ "Projection_3 1.00 root cast(99999.0, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "0.99999" ] @@ -1009,7 +1009,7 @@ "Projection_3 1.00 root cast(-123456789.0123456789012345678901234567890123456789, decima(len:78)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.99999" ] @@ -1026,7 +1026,7 @@ "Projection_3 1.00 root cast(-1234567.1234567, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.99999" ] @@ -1043,7 +1043,7 @@ "Projection_3 1.00 root cast(-0.99999, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.99999" ] @@ -1060,7 +1060,7 @@ "Projection_3 1.00 root cast(-99999.0, decimal(5,5) BINARY)->Column#1", "└─TableDual_4 1.00 root rows:1" ], - "LastPlanUseCache": "1", + "LastPlanUseCache": "0", "Result": [ "-0.99999" ] diff --git a/executor/tiflash_test.go b/executor/tiflash_test.go index 14e7c13e9c17e..e70c717c0227a 100644 --- a/executor/tiflash_test.go +++ b/executor/tiflash_test.go @@ -22,38 +22,30 @@ import ( "strings" "sync" "sync/atomic" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/terror" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/unistore" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util/israce" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" ) -type tiflashTestSuite struct { - store kv.Storage - dom *domain.Domain - *parser.Parser -} - -func (s *tiflashTestSuite) SetUpSuite(c *C) { - var err error - s.store, err = mockstore.NewMockStore( +func createTiFlashStore(t *testing.T) (kv.Storage, func()) { + store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { mockCluster := c.(*unistore.Cluster) _, _, region1 := mockstore.BootstrapWithSingleStore(c) @@ -69,47 +61,36 @@ func (s *tiflashTestSuite) SetUpSuite(c *C) { }), mockstore.WithStoreType(mockstore.EmbedUnistore), ) - - c.Assert(err, IsNil) - - session.SetSchemaLease(0) - session.DisableStats4Test() - - s.dom, err = session.BootstrapSession(s.store) - c.Assert(err, IsNil) - s.dom.SetStatsUpdating(true) -} - -func (s *tiflashTestSuite) TearDownSuite(c *C) { - s.dom.Close() - c.Assert(s.store.Close(), IsNil) + return store, clean } -func (s *tiflashTestSuite) TestNonsupportCharsetTable(c *C) { - collate.SetCharsetFeatEnabledForTest(true) - defer collate.SetCharsetFeatEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestNonsupportCharsetTable(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b char(10) charset gbk collate gbk_bin)") err := tk.ExecToErr("alter table t set tiflash replica 1") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[ddl:8200]Unsupported ALTER table replica for table contain gbk charset") + require.Error(t, err) + require.Equal(t, "[ddl:8200]Unsupported ALTER table replica for table contain gbk charset", err.Error()) tk.MustExec("drop table if exists t") tk.MustExec("create table t(a char(10) charset utf8)") tk.MustExec("alter table t set tiflash replica 1") } -func (s *tiflashTestSuite) TestReadPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReadPartitionTable(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null) partition by hash(a) partitions 2") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,0)") tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") @@ -128,19 +109,27 @@ func (s *tiflashTestSuite) TestReadPartitionTable(c *C) { tk.MustQuery("select /*+ STREAM_AGG() */ count(*) from t").Check(testkit.Rows("5")) tk.MustExec("insert into t values(6,0)") tk.MustQuery("select /*+ STREAM_AGG() */ count(*) from t").Check(testkit.Rows("6")) + // test dynamic prune + union scan + tk.MustExec("set tidb_partition_prune_mode=dynamic") + tk.MustQuery("select /*+ STREAM_AGG() */ count(*) from t").Check(testkit.Rows("6")) + // test dynamic prune + batch cop + union scan + tk.MustExec("set tidb_allow_batch_cop=2") + tk.MustQuery("select /*+ STREAM_AGG() */ count(*) from t").Check(testkit.Rows("6")) tk.MustExec("commit") } -func (s *tiflashTestSuite) TestReadUnsigedPK(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReadUnsigedPK(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") tk.MustExec("create table t(a bigint unsigned not null primary key, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,0)") tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") @@ -149,9 +138,9 @@ func (s *tiflashTestSuite) TestReadUnsigedPK(c *C) { tk.MustExec("create table t1(a bigint unsigned not null primary key, b int not null)") tk.MustExec("alter table t1 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t1") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t1") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t1 values(1,0)") tk.MustExec("insert into t1 values(2,0)") tk.MustExec("insert into t1 values(3,0)") @@ -160,7 +149,6 @@ func (s *tiflashTestSuite) TestReadUnsigedPK(c *C) { tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") tk.MustExec("set @@session.tidb_allow_mpp=ON") - tk.MustExec("set @@session.tidb_opt_broadcast_join=ON") // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side tk.MustExec("set tidb_opt_mpp_outer_join_fixed_build_side=1") @@ -170,15 +158,17 @@ func (s *tiflashTestSuite) TestReadUnsigedPK(c *C) { } // to fix https://github.com/pingcap/tidb/issues/27952 -func (s *tiflashTestSuite) TestJoinRace(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinRace(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,1)") tk.MustExec("insert into t values(2,1)") tk.MustExec("insert into t values(3,1)") @@ -198,27 +188,29 @@ func (s *tiflashTestSuite) TestJoinRace(c *C) { } -func (s *tiflashTestSuite) TestMppExecution(c *C) { +func TestMppExecution(t *testing.T) { if israce.RaceEnabled { - c.Skip("skip race test because of long running") + t.Skip("skip race test because of long running") } - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,0)") tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") tk.MustExec("create table t1(a int primary key, b int not null)") tk.MustExec("alter table t1 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t1") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t1") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t1 values(1,0)") tk.MustExec("insert into t1 values(2,0)") tk.MustExec("insert into t1 values(3,0)") @@ -235,9 +227,9 @@ func (s *tiflashTestSuite) TestMppExecution(c *C) { // test multi-way join tk.MustExec("create table t2(a int primary key, b int not null)") tk.MustExec("alter table t2 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t2") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t2") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t2 values(1,0)") tk.MustExec("insert into t2 values(2,0)") @@ -265,14 +257,14 @@ func (s *tiflashTestSuite) TestMppExecution(c *C) { tk.MustExec("begin") tk.MustQuery("select count(*) from ( select * from t2 group by a, b) A group by A.b").Check(testkit.Rows("3")) tk.MustQuery("select count(*) from t1 where t1.a+100 > ( select count(*) from t2 where t1.a=t2.a and t1.b=t2.b) group by t1.b").Check(testkit.Rows("4")) - txn, err := tk.Se.Txn(true) - c.Assert(err, IsNil) + txn, err := tk.Session().Txn(true) + require.NoError(t, err) ts := txn.StartTS() - taskID := tk.Se.GetSessionVars().AllocMPPTaskID(ts) - c.Assert(taskID, Equals, int64(6)) + taskID := tk.Session().GetSessionVars().AllocMPPTaskID(ts) + require.Equal(t, int64(6), taskID) tk.MustExec("commit") - taskID = tk.Se.GetSessionVars().AllocMPPTaskID(ts + 1) - c.Assert(taskID, Equals, int64(1)) + taskID = tk.Session().GetSessionVars().AllocMPPTaskID(ts + 1) + require.Equal(t, int64(1), taskID) failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(3)`) // all the data is related to one store, so there are three tasks. @@ -282,9 +274,9 @@ func (s *tiflashTestSuite) TestMppExecution(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 decimal(8, 5) not null, c2 decimal(9, 5), c3 decimal(9, 4) , c4 decimal(8, 4) not null)") tk.MustExec("alter table t set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1.00000,1.00000,1.0000,1.0000)") tk.MustExec("insert into t values(1.00010,1.00010,1.0001,1.0001)") tk.MustExec("insert into t values(1.00001,1.00001,1.0000,1.0002)") @@ -295,15 +287,17 @@ func (s *tiflashTestSuite) TestMppExecution(c *C) { tk.MustQuery("select /*+ nth_plan(2) */ t1.c1 from t t1 join t t2 on t1.c1 = t2.c3 order by t1.c1").Check(testkit.Rows("1.00000", "1.00000", "1.00010")) } -func (s *tiflashTestSuite) TestInjectExtraProj(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInjectExtraProj(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint(20))") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values (9223372036854775807)") tk.MustExec("insert into t values (9223372036854775807)") tk.MustExec("insert into t values (9223372036854775807)") @@ -315,10 +309,12 @@ func (s *tiflashTestSuite) TestInjectExtraProj(c *C) { tk.MustQuery("select avg(a), a from t group by a").Check(testkit.Rows("9223372036854775807.0000 9223372036854775807")) } -func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashJoin(c *C) { - c.Skip("too slow") +func TestTiFlashPartitionTableShuffledHashJoin(t *testing.T) { + t.Skip("too slow") - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`create database tiflash_partition_SHJ`) tk.MustExec("use tiflash_partition_SHJ") tk.MustExec(`create table thash (a int, b int) partition by hash(a) partitions 4`) @@ -340,9 +336,9 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashJoin(c *C) { for _, tbl := range []string{`thash`, `trange`, `tlist`, `tnormal`} { tk.MustExec("alter table " + tbl + " set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "tiflash_partition_SHJ", tbl) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "tiflash_partition_SHJ", tbl) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) } vals := make([]string, 0, 100) @@ -355,7 +351,6 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashJoin(c *C) { } tk.MustExec("SET tidb_enforce_mpp=1") - tk.MustExec("SET tidb_opt_broadcast_join=0") tk.MustExec("SET tidb_broadcast_join_threshold_count=0") tk.MustExec("SET tidb_broadcast_join_threshold_size=0") tk.MustExec("set @@session.tidb_isolation_read_engines='tiflash'") @@ -389,10 +384,12 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashJoin(c *C) { } } -func (s *tiflashTestSuite) TestTiFlashPartitionTableReader(c *C) { - c.Skip("too slow") +func TestTiFlashPartitionTableReader(t *testing.T) { + t.Skip("too slow") - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`create database tiflash_partition_tablereader`) tk.MustExec("use tiflash_partition_tablereader") tk.MustExec(`create table thash (a int, b int) partition by hash(a) partitions 4`) @@ -414,9 +411,9 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableReader(c *C) { for _, tbl := range []string{`thash`, `trange`, `tlist`, `tnormal`} { tk.MustExec("alter table " + tbl + " set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "tiflash_partition_tablereader", tbl) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "tiflash_partition_tablereader", tbl) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) } // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side @@ -453,17 +450,19 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableReader(c *C) { } } -func (s *tiflashTestSuite) TestPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTable(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") tk.MustExec("create table t(a int not null primary key, b int not null) partition by hash(a+1) partitions 4") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,0)") tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") @@ -474,7 +473,7 @@ func (s *tiflashTestSuite) TestPartitionTable(c *C) { // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side tk.MustExec("set tidb_opt_mpp_outer_join_fixed_build_side=1") - failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(4)`) + failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(1)`) tk.MustQuery("select count(*) from t").Check(testkit.Rows("4")) failpoint.Disable("github.com/pingcap/tidb/executor/checkTotalMPPTasks") tk.MustExec("set @@session.tidb_partition_prune_mode='static-only'") @@ -485,9 +484,9 @@ func (s *tiflashTestSuite) TestPartitionTable(c *C) { tk.MustExec("create table t1(a int not null primary key, b int not null) partition by hash(a) partitions 4") tk.MustExec("alter table t1 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t1") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t1") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t1 values(1,4)") tk.MustExec("insert into t1 values(2,3)") tk.MustExec("insert into t1 values(3,2)") @@ -495,9 +494,8 @@ func (s *tiflashTestSuite) TestPartitionTable(c *C) { tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") tk.MustExec("set @@session.tidb_allow_mpp=ON") - tk.MustExec("set @@session.tidb_opt_broadcast_join=ON") // test if it is really work. - failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(8)`) + failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(2)`) tk.MustQuery("select count(*) from t1 , t where t1.a = t.a").Check(testkit.Rows("4")) // test partition prune tk.MustQuery("select count(*) from t1 , t where t1.a = t.a and t1.a < 2 and t.a < 2").Check(testkit.Rows("1")) @@ -506,16 +504,16 @@ func (s *tiflashTestSuite) TestPartitionTable(c *C) { // test multi-way join tk.MustExec("create table t2(a int not null primary key, b int not null)") tk.MustExec("alter table t2 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t2") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t2") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t2 values(1,0)") tk.MustExec("insert into t2 values(2,0)") tk.MustExec("insert into t2 values(3,0)") tk.MustExec("insert into t2 values(4,0)") // test with no partition table - failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(9)`) + failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(3)`) tk.MustQuery("select count(*) from t1 , t, t2 where t1.a = t.a and t2.a = t.a").Check(testkit.Rows("4")) failpoint.Disable("github.com/pingcap/tidb/executor/checkTotalMPPTasks") @@ -526,33 +524,35 @@ func (s *tiflashTestSuite) TestPartitionTable(c *C) { PARTITION p3 VALUES LESS THAN (7) );`) tk.MustExec("alter table t3 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t3") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t3") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t3 values(1,0)") tk.MustExec("insert into t3 values(2,2)") tk.MustExec("insert into t3 values(3,4)") tk.MustExec("insert into t3 values(4,6)") - failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(7)`) + failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(2)`) tk.MustQuery("select count(*) from t, t3 where t3.a = t.a and t3.b <= 4").Check(testkit.Rows("3")) failpoint.Disable("github.com/pingcap/tidb/executor/checkTotalMPPTasks") - failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(5)`) + failpoint.Enable("github.com/pingcap/tidb/executor/checkTotalMPPTasks", `return(2)`) tk.MustQuery("select count(*) from t, t3 where t3.a = t.a and t3.b > 10").Check(testkit.Rows("0")) failpoint.Disable("github.com/pingcap/tidb/executor/checkTotalMPPTasks") failpoint.Disable("github.com/pingcap/tidb/executor/checkUseMPP") } -func (s *tiflashTestSuite) TestMppEnum(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppEnum(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b enum('aca','bca','zca'))") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,'aca')") tk.MustExec("insert into t values(2,'bca')") tk.MustExec("insert into t values(3,'zca')") @@ -564,28 +564,30 @@ func (s *tiflashTestSuite) TestMppEnum(c *C) { tk.MustQuery("select t1.b from t t1 join t t2 on t1.a = t2.a order by t1.b").Check(testkit.Rows("aca", "bca", "zca")) } -func (s *tiflashTestSuite) TestTiFlashPlanCacheable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTiFlashPlanCacheable(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + sess, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + tk.SetSession(sess) + require.NoError(t, err) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int);") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("alter table test.t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv, tiflash'") tk.MustExec("insert into t values(1);") tk.MustExec("prepare stmt from 'select /*+ read_from_storage(tiflash[t]) */ * from t;';") @@ -615,8 +617,10 @@ func (s *tiflashTestSuite) TestTiFlashPlanCacheable(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) } -func (s *tiflashTestSuite) TestDispatchTaskRetry(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDispatchTaskRetry(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null)") @@ -625,20 +629,20 @@ func (s *tiflashTestSuite) TestDispatchTaskRetry(c *C) { tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") tk.MustExec("insert into t values(4,0)") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("set @@session.tidb_enforce_mpp=ON") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/mppDispatchTimeout", "3*return(true)"), IsNil) + require.Nil(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/mppDispatchTimeout", "3*return(true)")) tk.MustQuery("select count(*) from t").Check(testkit.Rows("4")) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/mppDispatchTimeout"), IsNil) + require.Nil(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/mppDispatchTimeout")) } -func (s *tiflashTestSuite) TestCancelMppTasks(c *C) { - testleak.BeforeTest() - defer testleak.AfterTest(c)() +func TestCancelMppTasks(t *testing.T) { var hang = "github.com/pingcap/tidb/store/mockstore/unistore/mppRecvHang" - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null)") @@ -647,53 +651,55 @@ func (s *tiflashTestSuite) TestCancelMppTasks(c *C) { tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") tk.MustExec("insert into t values(4,0)") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") tk.MustExec("set @@session.tidb_allow_mpp=ON") // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side tk.MustExec("set tidb_opt_mpp_outer_join_fixed_build_side=1") - atomic.StoreUint32(&tk.Se.GetSessionVars().Killed, 0) - c.Assert(failpoint.Enable(hang, `return(true)`), IsNil) + atomic.StoreUint32(&tk.Session().GetSessionVars().Killed, 0) + require.Nil(t, failpoint.Enable(hang, `return(true)`)) wg := &sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() err := tk.QueryToErr("select count(*) from t as t1 , t where t1.a = t.a") - c.Assert(err, NotNil) - c.Assert(int(terror.ToSQLError(errors.Cause(err).(*terror.Error)).Code), Equals, int(executor.ErrQueryInterrupted.Code())) + require.Error(t, err) + require.Equal(t, int(executor.ErrQueryInterrupted.Code()), int(terror.ToSQLError(errors.Cause(err).(*terror.Error)).Code)) }() time.Sleep(1 * time.Second) - atomic.StoreUint32(&tk.Se.GetSessionVars().Killed, 1) + atomic.StoreUint32(&tk.Session().GetSessionVars().Killed, 1) wg.Wait() - c.Assert(failpoint.Disable(hang), IsNil) + require.Nil(t, failpoint.Disable(hang)) } // all goroutines exit if one goroutine hangs but another return errors -func (s *tiflashTestSuite) TestMppGoroutinesExitFromErrors(c *C) { +func TestMppGoroutinesExitFromErrors(t *testing.T) { // mock non-root tasks return error var mppNonRootTaskError = "github.com/pingcap/tidb/store/copr/mppNonRootTaskError" // mock root tasks hang var hang = "github.com/pingcap/tidb/store/mockstore/unistore/mppRecvHang" - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,0)") tk.MustExec("insert into t values(2,0)") tk.MustExec("insert into t values(3,0)") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(a int not null primary key, b int not null)") tk.MustExec("alter table t1 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t1") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t1") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t1 values(1,0)") tk.MustExec("insert into t1 values(2,0)") tk.MustExec("insert into t1 values(3,0)") @@ -702,18 +708,20 @@ func (s *tiflashTestSuite) TestMppGoroutinesExitFromErrors(c *C) { // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side tk.MustExec("set tidb_opt_mpp_outer_join_fixed_build_side=1") - c.Assert(failpoint.Enable(mppNonRootTaskError, `return(true)`), IsNil) - c.Assert(failpoint.Enable(hang, `return(true)`), IsNil) + require.Nil(t, failpoint.Enable(mppNonRootTaskError, `return(true)`)) + require.Nil(t, failpoint.Enable(hang, `return(true)`)) // generate 2 root tasks, one will hang and another will return errors err = tk.QueryToErr("select count(*) from t as t1 , t where t1.a = t.a") - c.Assert(err, NotNil) - c.Assert(failpoint.Disable(mppNonRootTaskError), IsNil) - c.Assert(failpoint.Disable(hang), IsNil) + require.Error(t, err) + require.Nil(t, failpoint.Disable(mppNonRootTaskError)) + require.Nil(t, failpoint.Disable(hang)) } -func (s *tiflashTestSuite) TestMppUnionAll(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppUnionAll(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists x1") tk.MustExec("create table x1(a int , b int);") @@ -721,12 +729,12 @@ func (s *tiflashTestSuite) TestMppUnionAll(c *C) { tk.MustExec("drop table if exists x2") tk.MustExec("create table x2(a int , b int);") tk.MustExec("alter table x2 set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "x1") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) - tb = testGetTableByName(c, tk.Se, "test", "x2") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "x1") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tb = external.GetTableByName(t, tk, "test", "x2") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into x1 values (1, 1), (2, 2), (3, 3), (4, 4)") tk.MustExec("insert into x2 values (5, 1), (2, 2), (3, 3), (4, 4)") @@ -741,9 +749,9 @@ func (s *tiflashTestSuite) TestMppUnionAll(c *C) { tk.MustExec("drop table if exists x3") tk.MustExec("create table x3(a int , b int);") tk.MustExec("alter table x3 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "x3") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "x3") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into x3 values (2, 2), (2, 3), (2, 4)") // test nested union all @@ -758,9 +766,9 @@ func (s *tiflashTestSuite) TestMppUnionAll(c *C) { tk.MustExec("drop table if exists x4") tk.MustExec("create table x4(a int not null, b int not null);") tk.MustExec("alter table x4 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "x4") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "x4") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("set @@tidb_enforce_mpp=1") tk.MustExec("insert into x4 values (2, 2), (2, 3)") @@ -768,8 +776,10 @@ func (s *tiflashTestSuite) TestMppUnionAll(c *C) { } -func (s *tiflashTestSuite) TestUnionWithEmptyDualTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUnionWithEmptyDualTable(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") @@ -777,12 +787,12 @@ func (s *tiflashTestSuite) TestUnionWithEmptyDualTable(c *C) { tk.MustExec("create table t1 (a int, b int not null, c double)") tk.MustExec("alter table t set tiflash replica 1") tk.MustExec("alter table t1 set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) - tb = testGetTableByName(c, tk.Se, "test", "t1") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tb = external.GetTableByName(t, tk, "test", "t1") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(1,2,3)") tk.MustExec("insert into t1 values(1,2,3)") tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") @@ -790,16 +800,18 @@ func (s *tiflashTestSuite) TestUnionWithEmptyDualTable(c *C) { tk.MustQuery("select count(*) from (select a , b from t union all select a , c from t1 where false) tt").Check(testkit.Rows("1")) } -func (s *tiflashTestSuite) TestAvgOverflow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAvgOverflow(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // avg int tk.MustExec("drop table if exists t") tk.MustExec("create table t (a decimal(1,0))") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t values(9)") for i := 0; i < 16; i++ { tk.MustExec("insert into t select * from t") @@ -813,9 +825,9 @@ func (s *tiflashTestSuite) TestAvgOverflow(c *C) { tk.MustExec("drop table if exists td;") tk.MustExec("create table td (col_bigint bigint(20), col_smallint smallint(6));") tk.MustExec("alter table td set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "td") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "td") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into td values (null, 22876);") tk.MustExec("insert into td values (9220557287087669248, 32767);") tk.MustExec("insert into td values (28030, 32767);") @@ -833,22 +845,24 @@ func (s *tiflashTestSuite) TestAvgOverflow(c *C) { tk.MustExec("drop table if exists td;") } -func (s *tiflashTestSuite) TestMppApply(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppApply(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists x1") tk.MustExec("create table x1(a int primary key, b int);") tk.MustExec("alter table x1 set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "x1") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "x1") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into x1 values(1, 1),(2, 10),(0,11);") tk.MustExec("create table x2(a int primary key, b int);") tk.MustExec("alter table x2 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "x2") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "x2") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into x2 values(1,2),(0,1),(2,-3);") tk.MustExec("analyze table x1, x2;") @@ -863,29 +877,31 @@ func (s *tiflashTestSuite) TestMppApply(c *C) { tk.MustQuery("select /*+ agg_to_cop(), hash_agg()*/ count(*) from x1 where b > any (select x2.a from x2 where x1.a = x2.a);").Check(testkit.Rows("2")) } -func (s *tiflashTestSuite) TestTiFlashVirtualColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTiFlashVirtualColumn(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2,t3") tk.MustExec("create table t1 (a bit(4), b bit(4), c bit(4) generated always as (a) virtual)") tk.MustExec("alter table t1 set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t1") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t1") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t1(a,b) values(b'01',b'01'),(b'10',b'10'),(b'11',b'11')") tk.MustExec("create table t2 (a int, b int, c int generated always as (a) virtual)") tk.MustExec("alter table t2 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t2") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t2") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t2(a,b) values(1,1),(2,2),(3,3)") tk.MustExec("create table t3 (a bit(4), b bit(4), c bit(4) generated always as (b'01'+b'10') virtual)") tk.MustExec("alter table t3 set tiflash replica 1") - tb = testGetTableByName(c, tk.Se, "test", "t3") - err = domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb = external.GetTableByName(t, tk, "test", "t3") + err = domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) tk.MustExec("insert into t3(a,b) values(b'01',b'01'),(b'10',b'10'),(b'11',b'11')") tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") @@ -899,10 +915,12 @@ func (s *tiflashTestSuite) TestTiFlashVirtualColumn(c *C) { tk.MustQuery("select /*+ hash_agg() */ count(*) from t3 where c > b'01'").Check(testkit.Rows("3")) } -func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashAggregation(c *C) { - c.Skip("too slow") +func TestTiFlashPartitionTableShuffledHashAggregation(t *testing.T) { + t.Skip("too slow") - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database tiflash_partition_AGG") tk.MustExec("use tiflash_partition_AGG") tk.MustExec(`create table thash (a int, b int) partition by hash(a) partitions 4`) @@ -924,9 +942,9 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashAggregation(c *C for _, tbl := range []string{`thash`, `trange`, `tlist`, `tnormal`} { tk.MustExec("alter table " + tbl + " set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "tiflash_partition_AGG", tbl) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "tiflash_partition_AGG", tbl) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) } vals := make([]string, 0, 100) @@ -958,7 +976,7 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashAggregation(c *C tk.MustExec(fmt.Sprintf("set @@tidb_partition_prune_mode = '%v'", mode)) for _, tbl := range []string{`thash`, `trange`, `tlist`, `tnormal`} { q := fmt.Sprintf("select /*+ HASH_AGG() */ count(*) from %v t1 where %v", tbl, cond) - c.Assert(tk.HasPlan(q, "HashAgg"), IsTrue) + require.True(t, tk.HasPlan(q, "HashAgg")) if res == nil { res = tk.MustQuery(q).Sort().Rows() } else { @@ -969,10 +987,12 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableShuffledHashAggregation(c *C } } -func (s *tiflashTestSuite) TestTiFlashPartitionTableBroadcastJoin(c *C) { - c.Skip("too slow") +func TestTiFlashPartitionTableBroadcastJoin(t *testing.T) { + t.Skip("too slow") - tk := testkit.NewTestKit(c, s.store) + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database tiflash_partition_BCJ") tk.MustExec("use tiflash_partition_BCJ") tk.MustExec(`create table thash (a int, b int) partition by hash(a) partitions 4`) @@ -994,9 +1014,9 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableBroadcastJoin(c *C) { for _, tbl := range []string{`thash`, `trange`, `tlist`, `tnormal`} { tk.MustExec("alter table " + tbl + " set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "tiflash_partition_BCJ", tbl) - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "tiflash_partition_BCJ", tbl) + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) } vals := make([]string, 0, 100) @@ -1009,7 +1029,6 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableBroadcastJoin(c *C) { } tk.MustExec("set @@session.tidb_isolation_read_engines='tiflash'") tk.MustExec("set @@session.tidb_enforce_mpp=1") - tk.MustExec("set @@session.tidb_opt_broadcast_join=ON") // mock executor does not support use outer table as build side for outer join, so need to // force the inner table as build side tk.MustExec("set tidb_opt_mpp_outer_join_fixed_build_side=1") @@ -1040,15 +1059,17 @@ func (s *tiflashTestSuite) TestTiFlashPartitionTableBroadcastJoin(c *C) { } } -func (s *tiflashTestSuite) TestForbidTiflashDuringStaleRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestForbidTiflashDuringStaleRead(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint(20))") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(c, tk.Se, "test", "t") - err := domain.GetDomain(tk.Se).DDL().UpdateTableReplicaInfo(tk.Se, tb.Meta().ID, true) - c.Assert(err, IsNil) + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) time.Sleep(2 * time.Second) tk.MustExec("insert into t values (9223372036854775807)") tk.MustExec("insert into t values (9223372036854775807)") @@ -1062,8 +1083,8 @@ func (s *tiflashTestSuite) TestForbidTiflashDuringStaleRead(c *C) { fmt.Fprintf(resBuff, "%s\n", row) } res := resBuff.String() - c.Assert(strings.Contains(res, "tiflash"), IsTrue) - c.Assert(strings.Contains(res, "tikv"), IsFalse) + require.Contains(t, res, "tiflash") + require.NotContains(t, res, "tikv") tk.MustExec("set transaction read only as of timestamp now(1)") rows = tk.MustQuery("explain select avg(a) from t").Rows() resBuff = bytes.NewBufferString("") @@ -1071,6 +1092,111 @@ func (s *tiflashTestSuite) TestForbidTiflashDuringStaleRead(c *C) { fmt.Fprintf(resBuff, "%s\n", row) } res = resBuff.String() - c.Assert(strings.Contains(res, "tiflash"), IsFalse) - c.Assert(strings.Contains(res, "tikv"), IsTrue) + require.NotContains(t, res, "tiflash") + require.Contains(t, res, "tikv") +} + +func TestForbidTiFlashIfExtraPhysTableIDIsNeeded(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int not null primary key, b int not null) partition by hash(a) partitions 2") + tk.MustExec("alter table t set tiflash replica 1") + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tk.MustExec("set tidb_partition_prune_mode=dynamic") + tk.MustExec("set tidb_enforce_mpp=1") + + rows := tk.MustQuery("explain select count(*) from t").Rows() + resBuff := bytes.NewBufferString("") + for _, row := range rows { + fmt.Fprintf(resBuff, "%s\n", row) + } + res := resBuff.String() + require.Contains(t, res, "tiflash") + require.NotContains(t, res, "tikv") + + rows = tk.MustQuery("explain select count(*) from t for update").Rows() + resBuff = bytes.NewBufferString("") + for _, row := range rows { + fmt.Fprintf(resBuff, "%s\n", row) + } + res = resBuff.String() + require.NotContains(t, res, "tiflash") + require.Contains(t, res, "tikv") + + tk.MustExec("begin") + rows = tk.MustQuery("explain select count(*) from t").Rows() + resBuff = bytes.NewBufferString("") + for _, row := range rows { + fmt.Fprintf(resBuff, "%s\n", row) + } + res = resBuff.String() + require.Contains(t, res, "tiflash") + require.NotContains(t, res, "tikv") + tk.MustExec("insert into t values(1,2)") + rows = tk.MustQuery("explain select count(*) from t").Rows() + resBuff = bytes.NewBufferString("") + for _, row := range rows { + fmt.Fprintf(resBuff, "%s\n", row) + } + res = resBuff.String() + require.Contains(t, res, "tiflash") + require.NotContains(t, res, "tikv") + tk.MustExec("rollback") +} + +func TestTiflashPartitionTableScan(t *testing.T) { + store, clean := createTiFlashStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(\n a int,\n primary key(a)\n) partition by range(a) (\n partition p1 values less than (10),\n partition p2 values less than (20),\n partition p3 values less than (30),\n partition p4 values less than (40),\n partition p5 values less than (50)\n);") + tk.MustExec("alter table t set tiflash replica 1") + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + time.Sleep(2 * time.Second) + tk.MustExec("insert into t values(1),(11),(21),(31),(41);") + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic';") + tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\";") + // MPP + tk.MustExec("set @@session.tidb_allow_mpp=ON;") + tk.MustQuery("select count(*) from t where a < 12;").Check(testkit.Rows("2")) + + // BatchCop + tk.MustExec("set @@session.tidb_allow_mpp=OFF;") + tk.MustExec("set @@tidb_allow_batch_cop = 2;") + tk.MustQuery("select count(*) from t where a < 12;").Check(testkit.Rows("2")) + + // test retry batch cop + // MPP + wg := sync.WaitGroup{} + wg.Add(1) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcServerBusy", `return(true)`)) + go func() { + time.Sleep(100 * time.Millisecond) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcServerBusy")) + wg.Done() + }() + tk.MustExec("set @@session.tidb_allow_mpp=ON;") + tk.MustQuery("select count(*) from t where a < 12;").Check(testkit.Rows("2")) + wg.Wait() + + // BatchCop + wg.Add(1) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcServerBusy", `return(true)`)) + go func() { + time.Sleep(100 * time.Millisecond) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcServerBusy")) + wg.Done() + }() + tk.MustExec("set @@session.tidb_allow_mpp=OFF;") + tk.MustExec("set @@tidb_allow_batch_cop = 2;") + tk.MustQuery("select count(*) from t where a < 12;").Check(testkit.Rows("2")) + wg.Wait() } diff --git a/executor/tikv_regions_peers_table_test.go b/executor/tikv_regions_peers_table_test.go new file mode 100644 index 0000000000000..0e22a3c0377a6 --- /dev/null +++ b/executor/tikv_regions_peers_table_test.go @@ -0,0 +1,201 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package executor_test + +import ( + "fmt" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/pingcap/fn" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/pdapi" + "github.com/stretchr/testify/require" +) + +var regionsInfo = map[uint64]helper.RegionInfo{ + 1: { + ID: 1, + Peers: []helper.RegionPeer{{ID: 11, StoreID: 1, IsLearner: false}, {ID: 12, StoreID: 2, IsLearner: false}, {ID: 13, StoreID: 3, IsLearner: false}}, + Leader: helper.RegionPeer{ID: 11, StoreID: 1, IsLearner: false}, + }, + 2: { + ID: 2, + Peers: []helper.RegionPeer{{ID: 21, StoreID: 1, IsLearner: false}, {ID: 22, StoreID: 2, IsLearner: false}, {ID: 23, StoreID: 3, IsLearner: false}}, + Leader: helper.RegionPeer{ID: 22, StoreID: 2, IsLearner: false}, + }, + 3: { + ID: 3, + Peers: []helper.RegionPeer{{ID: 31, StoreID: 1, IsLearner: false}, {ID: 32, StoreID: 2, IsLearner: false}, {ID: 33, StoreID: 3, IsLearner: false}}, + Leader: helper.RegionPeer{ID: 33, StoreID: 3, IsLearner: false}, + }, +} + +var storeRegionsInfo = &helper.RegionsInfo{ + Count: 3, + Regions: []helper.RegionInfo{ + regionsInfo[1], + regionsInfo[2], + regionsInfo[3], + }, +} + +var storesRegionsInfo = map[uint64]*helper.RegionsInfo{ + 1: storeRegionsInfo, + 2: storeRegionsInfo, + 3: storeRegionsInfo, +} + +func storesRegionsInfoHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, err := strconv.Atoi(vars["id"]) + if err != nil { + writeJSONError(w, http.StatusBadRequest, "unable to parse id", err) + return + } + writeResp(w, storesRegionsInfo[uint64(id)]) +} + +func regionsInfoHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, err := strconv.Atoi(vars["id"]) + if err != nil { + writeJSONError(w, http.StatusBadRequest, "unable to parse id", err) + return + } + writeResp(w, regionsInfo[uint64(id)]) +} + +func TestTikvRegionPeers(t *testing.T) { + startTime := time.Now() + // mock PD http server + router := mux.NewRouter() + server := httptest.NewServer(router) + // mock store stats stat + mockAddr := strings.TrimPrefix(server.URL, "http://") + // mock PD API + router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { + return struct { + Version string `json:"version"` + GitHash string `json:"git_hash"` + StartTimestamp int64 `json:"start_timestamp"` + }{ + Version: "4.0.0-alpha", + GitHash: "mock-pd-githash", + StartTimestamp: startTime.Unix(), + }, nil + })) + // mock get regionsInfo by store id + router.HandleFunc(pdapi.StoreRegions+"/"+"{id}", storesRegionsInfoHandler) + // mock get regionInfo by region id + router.HandleFunc(pdapi.RegionByID+"/"+"{id}", regionsInfoHandler) + defer server.Close() + + store, clean := testkit.CreateMockStore(t) + defer clean() + + store = &mockStore{ + store.(helper.Storage), + mockAddr, + } + + fullRegionPeers := [][]string{ + {"1", "11", "1", "0", "1", "NORMAL", ""}, + {"1", "12", "2", "0", "0", "NORMAL", ""}, + {"1", "13", "3", "0", "0", "NORMAL", ""}, + + {"2", "21", "1", "0", "0", "NORMAL", ""}, + {"2", "22", "2", "0", "1", "NORMAL", ""}, + {"2", "23", "3", "0", "0", "NORMAL", ""}, + + {"3", "31", "1", "0", "0", "NORMAL", ""}, + {"3", "32", "2", "0", "0", "NORMAL", ""}, + {"3", "33", "3", "0", "1", "NORMAL", ""}, + } + + var cases = []struct { + conditions []string + reqCount int32 + expected [][]string + }{ + { + conditions: []string{ + "store_id in (1,2,3)", + "region_id in (1,2,3)", + }, + expected: fullRegionPeers, + }, + { + conditions: []string{ + "store_id in (1,2)", + "region_id=1", + }, + expected: [][]string{ + fullRegionPeers[0], fullRegionPeers[1], + }, + }, + { + conditions: []string{ + "store_id in (1,2)", + "region_id=1", + "is_leader=1", + }, + expected: [][]string{ + fullRegionPeers[0], + }, + }, + { + conditions: []string{ + "store_id in (1,2)", + "region_id=1", + "is_leader=0", + }, + expected: [][]string{ + fullRegionPeers[1], + }, + }, + { + conditions: []string{ + "store_id =1", + "region_id =1", + "is_leader =0", + }, + expected: [][]string{}, + }, + } + + tk := testkit.NewTestKit(t, store) + for _, cas := range cases { + sql := "select * from information_schema.tikv_region_peers" + if len(cas.conditions) > 0 { + sql = fmt.Sprintf("%s where %s", sql, strings.Join(cas.conditions, " and ")) + } + result := tk.MustQuery(sql) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "unexpected warnings: %+v", warnings) + var expected []string + for _, row := range cas.expected { + expectedRow := row + expected = append(expected, strings.Join(expectedRow, " ")) + } + result.Check(testkit.Rows(expected...)) + } +} diff --git a/executor/trace.go b/executor/trace.go index ac97ce9e987be..bc842802feee6 100644 --- a/executor/trace.go +++ b/executor/trace.go @@ -161,7 +161,7 @@ func (e *TraceExec) nextOptimizerPlanTrace(ctx context.Context, se sessionctx.Co jsonEncoder := json.NewEncoder(&writer) // If we do not set this to false, ">", "<", "&"... will be escaped to "\u003c","\u003e", "\u0026"... jsonEncoder.SetEscapeHTML(false) - err = jsonEncoder.Encode(se.GetSessionVars().StmtCtx.LogicalOptimizeTrace) + err = jsonEncoder.Encode(se.GetSessionVars().StmtCtx.OptimizeTracer) if err != nil { return errors.AddStack(err) } diff --git a/executor/trace_test.go b/executor/trace_test.go index 0771151c63e2a..f8e8e91ddebd7 100644 --- a/executor/trace_test.go +++ b/executor/trace_test.go @@ -15,18 +15,22 @@ package executor_test import ( - . "github.com/pingcap/check" - "github.com/pingcap/tidb/util/testkit" + "testing" + + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSuite1) TestTraceExec(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTraceExec(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") testSQL := `create table trace (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1);` tk.MustExec(testSQL) tk.MustExec("trace insert into trace (c1, c2, c3) values (1, 2, 3)") rows := tk.MustQuery("trace select * from trace where id = 0;").Rows() - c.Assert(len(rows), GreaterEqual, 1) + require.GreaterOrEqual(t, len(rows), 1) // +---------------------------+-----------------+------------+ // | operation | startTS | duration | @@ -40,16 +44,16 @@ func (s *testSuite1) TestTraceExec(c *C) { // | └─recordSet.Next | 22:08:38.249340 | 155.317µs | // +---------------------------+-----------------+------------+ rows = tk.MustQuery("trace format='row' select * from trace where id = 0;").Rows() - c.Assert(len(rows) > 1, IsTrue) - c.Assert(rowsOrdered(rows), IsTrue) + require.Greater(t, len(rows), 1) + require.True(t, rowsOrdered(rows)) rows = tk.MustQuery("trace format='row' delete from trace where id = 0").Rows() - c.Assert(len(rows) > 1, IsTrue) - c.Assert(rowsOrdered(rows), IsTrue) + require.Greater(t, len(rows), 1) + require.True(t, rowsOrdered(rows)) tk.MustExec("trace format='log' insert into trace (c1, c2, c3) values (1, 2, 3)") rows = tk.MustQuery("trace format='log' select * from trace where id = 0;").Rows() - c.Assert(len(rows), GreaterEqual, 1) + require.GreaterOrEqual(t, len(rows), 1) } func rowsOrdered(rows [][]interface{}) bool { @@ -67,12 +71,14 @@ func rowsOrdered(rows [][]interface{}) bool { return true } -func (s *testSuite1) TestTracePlanStmt(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTracePlanStmt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table tp123(id int);") rows := tk.MustQuery("trace plan select * from tp123").Rows() - c.Assert(rows, HasLen, 1) - c.Assert(rows[0], HasLen, 1) - c.Assert(rows[0][0].(string), Matches, ".*zip") + require.Len(t, rows, 1) + require.Len(t, rows[0], 1) + require.Regexp(t, ".*zip", rows[0][0]) } diff --git a/executor/union_scan.go b/executor/union_scan.go index 86b696a8ee988..f57c86ee32cd2 100644 --- a/executor/union_scan.go +++ b/executor/union_scan.go @@ -19,6 +19,7 @@ import ( "fmt" "runtime/trace" + "github.com/opentracing/opentracing-go" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" @@ -61,10 +62,20 @@ type UnionScanExec struct { // cacheTable not nil means it's reading from cached table. cacheTable kv.MemBuffer collators []collate.Collator + + // If partitioned table and the physical table id is encoded in the chuck at this column index + // used with dynamic prune mode + // < 0 if not used. + physTblIDIdx int } // Open implements the Executor Open interface. func (us *UnionScanExec) Open(ctx context.Context) error { + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { + span1 := span.Tracer().StartSpan("UnionScanExec.Open", opentracing.ChildOf(span.Context())) + defer span1.Finish() + ctx = opentracing.ContextWithSpan(ctx, span1) + } if err := us.baseExecutor.Open(ctx); err != nil { return err } @@ -87,6 +98,13 @@ func (us *UnionScanExec) open(ctx context.Context) error { return err } + us.physTblIDIdx = -1 + for i := len(us.columns) - 1; i >= 0; i-- { + if us.columns[i].ID == model.ExtraPhysTblID { + us.physTblIDIdx = i + break + } + } mb := txn.GetMemBuffer() mb.RLock() defer mb.RUnlock() @@ -98,13 +116,13 @@ func (us *UnionScanExec) open(ctx context.Context) error { // 2. build virtual columns and select with virtual columns switch x := reader.(type) { case *TableReaderExecutor: - us.addedRows, err = buildMemTableReader(us, x).getMemRows() + us.addedRows, err = buildMemTableReader(ctx, us, x).getMemRows(ctx) case *IndexReaderExecutor: - us.addedRows, err = buildMemIndexReader(us, x).getMemRows() + us.addedRows, err = buildMemIndexReader(ctx, us, x).getMemRows(ctx) case *IndexLookUpExecutor: - us.addedRows, err = buildMemIndexLookUpReader(us, x).getMemRows() + us.addedRows, err = buildMemIndexLookUpReader(ctx, us, x).getMemRows(ctx) case *IndexMergeReaderExecutor: - us.addedRows, err = buildMemIndexMergeReader(us, x).getMemRows() + us.addedRows, err = buildMemIndexMergeReader(ctx, us, x).getMemRows(ctx) default: err = fmt.Errorf("unexpected union scan children:%T", reader) } @@ -121,7 +139,7 @@ func (us *UnionScanExec) Next(ctx context.Context, req *chunk.Chunk) error { defer us.memBuf.RUnlock() req.GrowAndReset(us.maxChunkSize) mutableRow := chunk.MutRowFromTypes(retTypes(us)) - for i, batchSize := 0, req.Capacity(); i < batchSize; i++ { + for batchSize := req.Capacity(); req.NumRows() < batchSize; { row, err := us.getOneRow(ctx) if err != nil { return err @@ -231,7 +249,13 @@ func (us *UnionScanExec) getSnapshotRow(ctx context.Context) ([]types.Datum, err if err != nil { return nil, err } - checkKey := tablecodec.EncodeRecordKey(us.table.RecordPrefix(), snapshotHandle) + var checkKey kv.Key + if us.physTblIDIdx >= 0 { + tblID := row.GetInt64(us.physTblIDIdx) + checkKey = tablecodec.EncodeRowKeyWithHandle(tblID, snapshotHandle) + } else { + checkKey = tablecodec.EncodeRecordKey(us.table.RecordPrefix(), snapshotHandle) + } if _, err := us.memBufSnap.Get(context.TODO(), checkKey); err == nil { // If src handle appears in added rows, it means there is conflict and the transaction will fail to // commit, but for simplicity, we don't handle it here. diff --git a/executor/union_scan_test.go b/executor/union_scan_test.go index 6133010ec29da..4979af65273bd 100644 --- a/executor/union_scan_test.go +++ b/executor/union_scan_test.go @@ -17,8 +17,12 @@ package executor_test import ( "fmt" "testing" + "time" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/benchdaily" "github.com/stretchr/testify/require" ) @@ -416,3 +420,135 @@ func TestForApplyAndUnionScan(t *testing.T) { tk.MustQuery("select c_int, c_str from t where (select count(*) from t1 where t1.c_int in (t.c_int, t.c_int + 2, t.c_int + 10)) > 2").Check(testkit.Rows()) tk.MustExec("rollback") } + +func TestIssue28073(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (c_int int, c_str varchar(40), primary key (c_int, c_str) , key(c_int)) partition by hash (c_int) partitions 4") + tk.MustExec("create table t2 like t1") + tk.MustExec("insert into t1 values (1, 'flamboyant mcclintock')") + tk.MustExec("insert into t2 select * from t1") + + tk.MustExec("begin") + tk.MustExec("insert into t2 (c_int, c_str) values (2, 'romantic grothendieck')") + tk.MustQuery("select * from t2 left join t1 on t1.c_int = t2.c_int for update").Sort().Check( + testkit.Rows( + "1 flamboyant mcclintock 1 flamboyant mcclintock", + "2 romantic grothendieck ", + )) + tk.MustExec("commit") + + // Check no key is written to table ID 0 + txn, err := store.Begin() + require.NoError(t, err) + start := tablecodec.EncodeTablePrefix(0) + end := tablecodec.EncodeTablePrefix(1) + iter, err := txn.Iter(start, end) + require.NoError(t, err) + + exist := false + for iter.Valid() { + require.Nil(t, iter.Next()) + exist = true + break + } + require.False(t, exist) +} + +func TestIssue32422(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + + tk.MustExec("create table t (id int, c int, index(id));") + tk.MustExec("insert into t values (3,3), (4,4), (5,5);") + tk.MustExec("alter table t cache;") + + var cacheUsed bool + for i := 0; i < 20; i++ { + tk.MustQuery("select id+1, c from t where c = 4;").Check(testkit.Rows("5 4")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + cacheUsed = true + break + } + time.Sleep(50 * time.Millisecond) + } + require.True(t, cacheUsed) + + tk.MustQuery("select id+1, c from t where c = 4;").Check(testkit.Rows("5 4")) + + // Some extra tests. + // Since cached table use UnionScanExec utilities, check what happens when they work together. + // In these cases, the cache data serve as the snapshot, tikv is skipped, and txn membuffer works the same way. + tk.MustExec("begin") + tk.MustQuery("select id+1, c from t where c = 4;").Check(testkit.Rows("5 4")) + tk.MustExec("insert into t values (6, 6)") + // Check for the new added data. + tk.HasPlan("select id+1, c from t where c = 6;", "UnionScan") + tk.MustQuery("select id+1, c from t where c = 6;").Check(testkit.Rows("7 6")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + // Check for the old data. + tk.MustQuery("select id+1, c from t where c = 4;").Check(testkit.Rows("5 4")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + + // Point get + tk.HasPlan("select id+1, c from t where id = 6", "PointGet") + tk.MustQuery("select id+1, c from t where id = 6").Check(testkit.Rows("7 6")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + tk.MustQuery("select id+1, c from t where id = 4").Check(testkit.Rows("5 4")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + + // Index Lookup + tk.HasPlan("select id+1, c from t where id = 6", "IndexLookUp") + tk.MustQuery("select id+1, c from t use index(id) where id = 6").Check(testkit.Rows("7 6")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + tk.MustQuery("select id+1, c from t use index(id) where id = 4").Check(testkit.Rows("5 4")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + + // Index Reader + tk.HasPlan("select id from t where id = 6", "IndexReader") + tk.MustQuery("select id from t use index(id) where id = 6").Check(testkit.Rows("6")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + tk.MustQuery("select id from t use index(id) where id = 4").Check(testkit.Rows("4")) + require.True(t, tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache) + + tk.MustExec("rollback") +} + +func BenchmarkUnionScanRead(b *testing.B) { + store, clean := testkit.CreateMockStore(b) + defer clean() + + tk := testkit.NewTestKit(b, store) + tk.MustExec("use test") + tk.MustExec(`create table t_us ( +c1 varchar(10), +c2 varchar(30), +c3 varchar(1), +c4 varchar(12), +c5 varchar(10), +c6 datetime);`) + tk.MustExec(`begin;`) + for i := 0; i < 8000; i++ { + tk.MustExec("insert into t_us values ('54321', '1234', '1', '000000', '7518', '2014-05-08')") + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + tk.MustQuery("select * from t_us where c1 = '12345'").Check(testkit.Rows()) + } + b.StopTimer() +} + +func TestBenchDaily(t *testing.T) { + benchdaily.Run( + executor.BenchmarkReadLastLinesOfHugeLine, + BenchmarkUnionScanRead, + ) +} diff --git a/executor/update.go b/executor/update.go index 7df144b28196c..ed5c76f44c278 100644 --- a/executor/update.go +++ b/executor/update.go @@ -26,12 +26,12 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/memory" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" ) @@ -96,7 +96,7 @@ func (e *UpdateExec) prepare(row []types.Datum) (err error) { break } } - if e.unmatchedOuterRow(content, row) { + if unmatchedOuterRow(content, row) { updatable = false } e.tableUpdatable = append(e.tableUpdatable, updatable) @@ -211,7 +211,7 @@ func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema, row, n // the inner handle field is filled with a NULL value. // // This fixes: https://github.com/pingcap/tidb/issues/7176. -func (e *UpdateExec) unmatchedOuterRow(tblPos plannercore.TblColPosInfo, waitUpdateRow []types.Datum) bool { +func unmatchedOuterRow(tblPos plannercore.TblColPosInfo, waitUpdateRow []types.Datum) bool { firstHandleIdx := tblPos.HandleCols.GetCol(0) return waitUpdateRow[firstHandleIdx.Index].IsNull() } @@ -271,10 +271,14 @@ func (e *UpdateExec) updateRows(ctx context.Context) (int, error) { txn.GetSnapshot().SetOption(kv.CollectRuntimeStats, e.stats.SnapshotRuntimeStats) } } - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { txn, err := e.ctx.Txn(true) if err == nil { txn.SetOption(kv.ResourceGroupTagger, e.ctx.GetSessionVars().StmtCtx.GetResourceGroupTagger()) + if e.ctx.GetSessionVars().StmtCtx.KvExecCounter != nil { + // Bind an interceptor for client-go to count the number of SQL executions of each TiKV. + txn.SetOption(kv.RPCInterceptor, e.ctx.GetSessionVars().StmtCtx.KvExecCounter.RPCInterceptor()) + } } } for rowIdx := 0; rowIdx < chk.NumRows(); rowIdx++ { diff --git a/executor/update_test.go b/executor/update_test.go index 12211cc33fd66..03217a25ebf39 100644 --- a/executor/update_test.go +++ b/executor/update_test.go @@ -15,80 +15,35 @@ package executor_test import ( - "flag" - "fmt" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util/testkit" - "github.com/tikv/client-go/v2/testutils" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -type testUpdateSuite struct { - cluster testutils.Cluster - store kv.Storage - domain *domain.Domain - *parser.Parser -} - -func (s *testUpdateSuite) SetUpSuite(c *C) { - s.Parser = parser.New() - flag.Lookup("mockTikv") - useMockTikv := *mockTikv - if useMockTikv { - store, err := mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - s.store = store - session.SetSchemaLease(0) - session.DisableStats4Test() - } - d, err := session.BootstrapSession(s.store) - c.Assert(err, IsNil) - d.SetStatsUpdating(true) - s.domain = d -} - -func (s *testUpdateSuite) TearDownSuite(c *C) { - s.domain.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testUpdateSuite) TearDownTest(c *C) { - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } -} - -func (s *testUpdateSuite) TestUpdateGenColInTxn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateGenColInTxn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table t(a bigint, b bigint as (a+1));`) tk.MustExec(`begin;`) tk.MustExec(`insert into t(a) values(1);`) err := tk.ExecToErr(`update t set b=6 where b=2;`) - c.Assert(err.Error(), Equals, "[planner:3105]The value specified for generated column 'b' in table 't' is not allowed.") + require.Equal(t, "[planner:3105]The value specified for generated column 'b' in table 't' is not allowed.", err.Error()) tk.MustExec(`commit;`) tk.MustQuery(`select * from t;`).Check(testkit.Rows( `1 2`)) } -func (s *testUpdateSuite) TestUpdateWithAutoidSchema(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateWithAutoidSchema(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`create table t1(id int primary key auto_increment, n int);`) tk.MustExec(`create table t2(id int primary key, n float auto_increment, key I_n(n));`) @@ -212,21 +167,25 @@ func (s *testUpdateSuite) TestUpdateWithAutoidSchema(c *C) { } } -func (s *testUpdateSuite) TestUpdateSchemaChange(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateSchemaChange(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table t(a bigint, b bigint as (a+1));`) tk.MustExec(`begin;`) tk.MustExec(`insert into t(a) values(1);`) err := tk.ExecToErr(`update t set b=6 where b=2;`) - c.Assert(err.Error(), Equals, "[planner:3105]The value specified for generated column 'b' in table 't' is not allowed.") + require.Equal(t, "[planner:3105]The value specified for generated column 'b' in table 't' is not allowed.", err.Error()) tk.MustExec(`commit;`) tk.MustQuery(`select * from t;`).Check(testkit.Rows( `1 2`)) } -func (s *testUpdateSuite) TestUpdateMultiDatabaseTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateMultiDatabaseTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop database if exists test2") tk.MustExec("create database test2") @@ -235,8 +194,10 @@ func (s *testUpdateSuite) TestUpdateMultiDatabaseTable(c *C) { tk.MustExec("update t, test2.t set test.t.a=1") } -func (s *testUpdateSuite) TestUpdateSwapColumnValues(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestUpdateSwapColumnValues(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1 (c_str varchar(40))") @@ -271,8 +232,10 @@ func (s *testUpdateSuite) TestUpdateSwapColumnValues(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("10 30 -10 -30", "20 30 -20 -30")) } -func (s *testUpdateSuite) TestMultiUpdateOnSameTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiUpdateOnSameTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(x int, y int)") @@ -328,16 +291,13 @@ func (s *testUpdateSuite) TestMultiUpdateOnSameTable(c *C) { `[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`) } -var _ = SerialSuites(&testSuite11{&baseTestSuite{}}) +func TestUpdateClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -type testSuite11 struct { - *baseTestSuite -} - -func (s *testSuite11) TestUpdateClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t(id varchar(200) primary key, v int)`) @@ -386,10 +346,13 @@ func (s *testSuite11) TestUpdateClusterIndex(c *C) { tk.MustQuery("select * from s").Check(testkit.Rows("3 3 10", "5 5 5")) } -func (s *testSuite11) TestDeleteClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDeleteClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t(id varchar(200) primary key, v int)`) @@ -421,10 +384,13 @@ func (s *testSuite11) TestDeleteClusterIndex(c *C) { tk.MustQuery("select * from s1").Check(testkit.Rows("5 5 5")) } -func (s *testSuite11) TestReplaceClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReplaceClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec(`drop table if exists rt1pk`) tk.MustExec(`create table rt1pk(id varchar(200) primary key, v int)`) @@ -448,38 +414,42 @@ func (s *testSuite11) TestReplaceClusterIndex(c *C) { tk.MustQuery(`select * from rt1pk1u`).Check(testkit.Rows("aaa 2 11")) } -func (s *testSuite11) TestPessimisticUpdatePKLazyCheck(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - s.testUpdatePKLazyCheck(c, tk, variable.ClusteredIndexDefModeOn) - s.testUpdatePKLazyCheck(c, tk, variable.ClusteredIndexDefModeOff) - s.testUpdatePKLazyCheck(c, tk, variable.ClusteredIndexDefModeIntOnly) +func TestPessimisticUpdatePKLazyCheck(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + testUpdatePKLazyCheck(t, tk, variable.ClusteredIndexDefModeOn) + testUpdatePKLazyCheck(t, tk, variable.ClusteredIndexDefModeOff) + testUpdatePKLazyCheck(t, tk, variable.ClusteredIndexDefModeIntOnly) } -func (s *testSuite11) testUpdatePKLazyCheck(c *C, tk *testkit.TestKit, clusteredIndex variable.ClusteredIndexDefMode) { - tk.Se.GetSessionVars().EnableClusteredIndex = clusteredIndex +func testUpdatePKLazyCheck(t *testing.T, tk *testkit.TestKit, clusteredIndex variable.ClusteredIndexDefMode) { + tk.Session().GetSessionVars().EnableClusteredIndex = clusteredIndex tk.MustExec(`drop table if exists upk`) tk.MustExec(`create table upk (a int, b int, c int, primary key (a, b))`) tk.MustExec(`insert upk values (1, 1, 1), (2, 2, 2), (3, 3, 3)`) tk.MustExec("begin pessimistic") tk.MustExec("update upk set b = b + 1 where a between 1 and 2") - c.Assert(getPresumeExistsCount(c, tk.Se), Equals, 2) + require.Equal(t, 2, getPresumeExistsCount(t, tk.Session())) _, err := tk.Exec("update upk set a = 3, b = 3 where a between 1 and 2") - c.Assert(kv.ErrKeyExists.Equal(err), IsTrue) + require.True(t, kv.ErrKeyExists.Equal(err)) tk.MustExec("commit") } -func getPresumeExistsCount(c *C, se session.Session) int { +func getPresumeExistsCount(t *testing.T, se session.Session) int { txn, err := se.Txn(false) - c.Assert(err, IsNil) + require.NoError(t, err) buf := txn.GetMemBuffer() it, err := buf.Iter(nil, nil) - c.Assert(err, IsNil) + require.NoError(t, err) presumeNotExistsCnt := 0 for it.Valid() { flags, err1 := buf.GetFlags(it.Key()) - c.Assert(err1, IsNil) + require.Nil(t, err1) err = it.Next() - c.Assert(err, IsNil) + require.NoError(t, err) if flags.HasPresumeKeyNotExists() { presumeNotExistsCnt++ } @@ -487,18 +457,23 @@ func getPresumeExistsCount(c *C, se session.Session) int { return presumeNotExistsCnt } -func (s *testSuite11) TestOutOfRangeWithUnsigned(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOutOfRangeWithUnsigned(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t`) tk.MustExec(`create table t(ts int(10) unsigned NULL DEFAULT NULL)`) tk.MustExec(`insert into t values(1)`) _, err := tk.Exec("update t set ts = IF(ts < (0 - ts), 1,1) where ts>0") - c.Assert(err.Error(), Equals, "[types:1690]BIGINT UNSIGNED value is out of range in '(0 - test.t.ts)'") + require.Equal(t, "[types:1690]BIGINT UNSIGNED value is out of range in '(0 - test.t.ts)'", err.Error()) } -func (s *testPointGetSuite) TestIssue21447(c *C) { - tk1, tk2 := testkit.NewTestKit(c, s.store), testkit.NewTestKit(c, s.store) +func TestIssue21447(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1, tk2 := testkit.NewTestKit(t, store), testkit.NewTestKit(t, store) tk1.MustExec("use test") tk2.MustExec("use test") @@ -521,8 +496,10 @@ func (s *testPointGetSuite) TestIssue21447(c *C) { tk1.MustExec("commit") } -func (s *testSuite11) TestIssue23553(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23553(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists tt`) tk.MustExec(`create table tt (m0 varchar(64), status tinyint not null)`) diff --git a/executor/window_test.go b/executor/window_test.go index 97ce36b4f3258..8b1c91132410d 100644 --- a/executor/window_test.go +++ b/executor/window_test.go @@ -16,13 +16,15 @@ package executor_test import ( "fmt" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" ) -func (s *testSuite7) TestWindowFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestWindowFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_window_concurrency = 1") tk.MustExec("set @@tidb_enable_pipelined_window_function = 0") defer func() { @@ -31,8 +33,10 @@ func (s *testSuite7) TestWindowFunctions(c *C) { doTestWindowFunctions(tk) } -func (s *testSuite7) TestWindowParallelFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestWindowParallelFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_window_concurrency = 4") tk.MustExec("set @@tidb_enable_pipelined_window_function = 0") defer func() { @@ -41,20 +45,23 @@ func (s *testSuite7) TestWindowParallelFunctions(c *C) { doTestWindowFunctions(tk) } -func (s *testSuite7) TestPipelinedWindowFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPipelinedWindowFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_window_concurrency = 1") doTestWindowFunctions(tk) } -func (s *testSuite7) TestPipelinedWindowParallelFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPipelinedWindowParallelFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_window_concurrency = 4") doTestWindowFunctions(tk) } func doTestWindowFunctions(tk *testkit.TestKit) { - var result *testkit.Result tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, c int)") @@ -63,129 +70,129 @@ func doTestWindowFunctions(tk *testkit.TestKit) { tk.MustExec("set @@tidb_enable_window_function = 0") }() tk.MustExec("insert into t values (1,2,3),(4,3,2),(2,3,4)") - result = tk.MustQuery("select count(a) over () from t") - result.Check(testkit.Rows("3", "3", "3")) - result = tk.MustQuery("select sum(a) over () + count(a) over () from t") - result.Check(testkit.Rows("10", "10", "10")) - result = tk.MustQuery("select sum(a) over (partition by a) from t").Sort() - result.Check(testkit.Rows("1", "2", "4")) - result = tk.MustQuery("select 1 + sum(a) over (), count(a) over () from t") - result.Check(testkit.Rows("8 3", "8 3", "8 3")) - result = tk.MustQuery("select sum(t1.a) over() from t t1, t t2") - result.Check(testkit.Rows("21", "21", "21", "21", "21", "21", "21", "21", "21")) - result = tk.MustQuery("select _tidb_rowid, sum(t.a) over() from t") - result.Check(testkit.Rows("1 7", "2 7", "3 7")) - - result = tk.MustQuery("select a, row_number() over() from t") - result.Check(testkit.Rows("1 1", "4 2", "2 3")) - result = tk.MustQuery("select a, row_number() over(partition by a) from t").Sort() - result.Check(testkit.Rows("1 1", "2 1", "4 1")) - - result = tk.MustQuery("select a, sum(a) over(rows between unbounded preceding and 1 following) from t") - result.Check(testkit.Rows("1 5", "4 7", "2 7")) - result = tk.MustQuery("select a, sum(a) over(rows between 1 preceding and 1 following) from t") - result.Check(testkit.Rows("1 5", "4 7", "2 6")) - result = tk.MustQuery("select a, sum(a) over(rows between unbounded preceding and 1 preceding) from t") - result.Check(testkit.Rows("1 ", "4 1", "2 5")) + tk.MustQuery("select count(a) over () from t"). + Check(testkit.Rows("3", "3", "3")) + tk.MustQuery("select sum(a) over () + count(a) over () from t"). + Check(testkit.Rows("10", "10", "10")) + tk.MustQuery("select sum(a) over (partition by a) from t").Sort(). + Check(testkit.Rows("1", "2", "4")) + tk.MustQuery("select 1 + sum(a) over (), count(a) over () from t"). + Check(testkit.Rows("8 3", "8 3", "8 3")) + tk.MustQuery("select sum(t1.a) over() from t t1, t t2"). + Check(testkit.Rows("21", "21", "21", "21", "21", "21", "21", "21", "21")) + tk.MustQuery("select _tidb_rowid, sum(t.a) over() from t"). + Check(testkit.Rows("1 7", "2 7", "3 7")) + + tk.MustQuery("select a, row_number() over() from t"). + Check(testkit.Rows("1 1", "4 2", "2 3")) + tk.MustQuery("select a, row_number() over(partition by a) from t").Sort(). + Check(testkit.Rows("1 1", "2 1", "4 1")) + + tk.MustQuery("select a, sum(a) over(rows between unbounded preceding and 1 following) from t"). + Check(testkit.Rows("1 5", "4 7", "2 7")) + tk.MustQuery("select a, sum(a) over(rows between 1 preceding and 1 following) from t"). + Check(testkit.Rows("1 5", "4 7", "2 6")) + tk.MustQuery("select a, sum(a) over(rows between unbounded preceding and 1 preceding) from t"). + Check(testkit.Rows("1 ", "4 1", "2 5")) tk.MustExec("drop table t") tk.MustExec("create table t(a int, b date)") tk.MustExec("insert into t values (null,null),(1,20190201),(2,20190202),(3,20190203),(5,20190205)") - result = tk.MustQuery("select a, sum(a) over(order by a range between 1 preceding and 2 following) from t") - result.Check(testkit.Rows(" ", "1 6", "2 6", "3 10", "5 5")) - result = tk.MustQuery("select a, sum(a) over(order by a desc range between 1 preceding and 2 following) from t") - result.Check(testkit.Rows("5 8", "3 6", "2 6", "1 3", " ")) - result = tk.MustQuery("select a, b, sum(a) over(order by b range between interval 1 day preceding and interval 2 day following) from t") - result.Check(testkit.Rows(" ", "1 2019-02-01 6", "2 2019-02-02 6", "3 2019-02-03 10", "5 2019-02-05 5")) - result = tk.MustQuery("select a, b, sum(a) over(order by b desc range between interval 1 day preceding and interval 2 day following) from t") - result.Check(testkit.Rows("5 2019-02-05 8", "3 2019-02-03 6", "2 2019-02-02 6", "1 2019-02-01 3", " ")) + tk.MustQuery("select a, sum(a) over(order by a range between 1 preceding and 2 following) from t"). + Check(testkit.Rows(" ", "1 6", "2 6", "3 10", "5 5")) + tk.MustQuery("select a, sum(a) over(order by a desc range between 1 preceding and 2 following) from t"). + Check(testkit.Rows("5 8", "3 6", "2 6", "1 3", " ")) + tk.MustQuery("select a, b, sum(a) over(order by b range between interval 1 day preceding and interval 2 day following) from t"). + Check(testkit.Rows(" ", "1 2019-02-01 6", "2 2019-02-02 6", "3 2019-02-03 10", "5 2019-02-05 5")) + tk.MustQuery("select a, b, sum(a) over(order by b desc range between interval 1 day preceding and interval 2 day following) from t"). + Check(testkit.Rows("5 2019-02-05 8", "3 2019-02-03 6", "2 2019-02-02 6", "1 2019-02-01 3", " ")) tk.MustExec("drop table t") tk.MustExec("CREATE TABLE t (id INTEGER, sex CHAR(1))") tk.MustExec("insert into t values (1, 'M'), (2, 'F'), (3, 'F'), (4, 'F'), (5, 'M'), (10, NULL), (11, NULL)") - result = tk.MustQuery("SELECT sex, id, RANK() OVER (PARTITION BY sex ORDER BY id DESC) FROM t").Sort() - result.Check(testkit.Rows(" 10 2", " 11 1", "F 2 3", "F 3 2", "F 4 1", "M 1 2", "M 5 1")) + tk.MustQuery("SELECT sex, id, RANK() OVER (PARTITION BY sex ORDER BY id DESC) FROM t").Sort(). + Check(testkit.Rows(" 10 2", " 11 1", "F 2 3", "F 3 2", "F 4 1", "M 1 2", "M 5 1")) tk.MustExec("drop table t") tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values (1,1),(1,2),(2,1),(2,2)") - result = tk.MustQuery("select a, b, rank() over() from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) - result = tk.MustQuery("select a, b, rank() over(order by a) from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 1 3", "2 2 3")) - result = tk.MustQuery("select a, b, rank() over(order by a, b) from t") - result.Check(testkit.Rows("1 1 1", "1 2 2", "2 1 3", "2 2 4")) - - result = tk.MustQuery("select a, b, dense_rank() over() from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) - result = tk.MustQuery("select a, b, dense_rank() over(order by a) from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 1 2", "2 2 2")) - result = tk.MustQuery("select a, b, dense_rank() over(order by a, b) from t") - result.Check(testkit.Rows("1 1 1", "1 2 2", "2 1 3", "2 2 4")) - - result = tk.MustQuery("select row_number() over(rows between 1 preceding and 1 following) from t") - result.Check(testkit.Rows("1", "2", "3", "4")) - result = tk.MustQuery("show warnings") - result.Check(testkit.Rows("Note 3599 Window function 'row_number' ignores the frame clause of window '' and aggregates over the whole partition")) - - result = tk.MustQuery("select a, sum(a) over() from t") - result.Check(testkit.Rows("1 6", "1 6", "2 6", "2 6")) - result = tk.MustQuery("select a, sum(a) over(order by a) from t") - result.Check(testkit.Rows("1 2", "1 2", "2 6", "2 6")) - result = tk.MustQuery("select a, sum(a) over(order by a, b) from t") - result.Check(testkit.Rows("1 1", "1 2", "2 4", "2 6")) - - result = tk.MustQuery("select a, first_value(a) over(), last_value(a) over() from t") - result.Check(testkit.Rows("1 1 2", "1 1 2", "2 1 2", "2 1 2")) - result = tk.MustQuery("select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t") - result.Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) - result = tk.MustQuery("select a, first_value(a) over(rows between 1 following and 1 following), last_value(a) over(rows between 1 following and 1 following) from t") - result.Check(testkit.Rows("1 1 1", "1 2 2", "2 2 2", "2 ")) - result = tk.MustQuery("select a, first_value(rand(0)) over(), last_value(rand(0)) over() from t") - result.Check(testkit.Rows("1 0.15522042769493574 0.33109208227236947", "1 0.15522042769493574 0.33109208227236947", - "2 0.15522042769493574 0.33109208227236947", "2 0.15522042769493574 0.33109208227236947")) - - result = tk.MustQuery("select a, b, cume_dist() over() from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) - result = tk.MustQuery("select a, b, cume_dist() over(order by a) from t") - result.Check(testkit.Rows("1 1 0.5", "1 2 0.5", "2 1 1", "2 2 1")) - result = tk.MustQuery("select a, b, cume_dist() over(order by a, b) from t") - result.Check(testkit.Rows("1 1 0.25", "1 2 0.5", "2 1 0.75", "2 2 1")) - - result = tk.MustQuery("select a, nth_value(a, null) over() from t") - result.Check(testkit.Rows("1 ", "1 ", "2 ", "2 ")) - result = tk.MustQuery("select a, nth_value(a, 1) over() from t") - result.Check(testkit.Rows("1 1", "1 1", "2 1", "2 1")) - result = tk.MustQuery("select a, nth_value(a, 4) over() from t") - result.Check(testkit.Rows("1 2", "1 2", "2 2", "2 2")) - result = tk.MustQuery("select a, nth_value(a, 5) over() from t") - result.Check(testkit.Rows("1 ", "1 ", "2 ", "2 ")) - - result = tk.MustQuery("select ntile(3) over() from t") - result.Check(testkit.Rows("1", "1", "2", "3")) - result = tk.MustQuery("select ntile(2) over() from t") - result.Check(testkit.Rows("1", "1", "2", "2")) - result = tk.MustQuery("select ntile(null) over() from t") - result.Check(testkit.Rows("", "", "", "")) - - result = tk.MustQuery("select a, percent_rank() over() from t") - result.Check(testkit.Rows("1 0", "1 0", "2 0", "2 0")) - result = tk.MustQuery("select a, percent_rank() over(order by a) from t") - result.Check(testkit.Rows("1 0", "1 0", "2 0.6666666666666666", "2 0.6666666666666666")) - result = tk.MustQuery("select a, b, percent_rank() over(order by a, b) from t") - result.Check(testkit.Rows("1 1 0", "1 2 0.3333333333333333", "2 1 0.6666666666666666", "2 2 1")) - - result = tk.MustQuery("select a, lead(a) over (), lag(a) over() from t") - result.Check(testkit.Rows("1 1 ", "1 2 1", "2 2 1", "2 2")) - result = tk.MustQuery("select a, lead(a, 0) over(), lag(a, 0) over() from t") - result.Check(testkit.Rows("1 1 1", "1 1 1", "2 2 2", "2 2 2")) - result = tk.MustQuery("select a, lead(a, 1, a) over(), lag(a, 1, a) over() from t") - result.Check(testkit.Rows("1 1 1", "1 2 1", "2 2 1", "2 2 2")) - result = tk.MustQuery("select a, lead(a, 1, 'lead') over(), lag(a, 1, 'lag') over() from t") - result.Check(testkit.Rows("1 1 lag", "1 2 1", "2 2 1", "2 lead 2")) - - result = tk.MustQuery("SELECT CUME_DIST() OVER (ORDER BY null);") - result.Check(testkit.Rows("1")) + tk.MustQuery("select a, b, rank() over() from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) + tk.MustQuery("select a, b, rank() over(order by a) from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 1 3", "2 2 3")) + tk.MustQuery("select a, b, rank() over(order by a, b) from t"). + Check(testkit.Rows("1 1 1", "1 2 2", "2 1 3", "2 2 4")) + + tk.MustQuery("select a, b, dense_rank() over() from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) + tk.MustQuery("select a, b, dense_rank() over(order by a) from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 1 2", "2 2 2")) + tk.MustQuery("select a, b, dense_rank() over(order by a, b) from t"). + Check(testkit.Rows("1 1 1", "1 2 2", "2 1 3", "2 2 4")) + + tk.MustQuery("select row_number() over(rows between 1 preceding and 1 following) from t"). + Check(testkit.Rows("1", "2", "3", "4")) + tk.MustQuery("show warnings"). + Check(testkit.Rows("Note 3599 Window function 'row_number' ignores the frame clause of window '' and aggregates over the whole partition")) + + tk.MustQuery("select a, sum(a) over() from t"). + Check(testkit.Rows("1 6", "1 6", "2 6", "2 6")) + tk.MustQuery("select a, sum(a) over(order by a) from t"). + Check(testkit.Rows("1 2", "1 2", "2 6", "2 6")) + tk.MustQuery("select a, sum(a) over(order by a, b) from t"). + Check(testkit.Rows("1 1", "1 2", "2 4", "2 6")) + + tk.MustQuery("select a, first_value(a) over(), last_value(a) over() from t"). + Check(testkit.Rows("1 1 2", "1 1 2", "2 1 2", "2 1 2")) + tk.MustQuery("select a, first_value(a) over(rows between 1 preceding and 1 following), last_value(a) over(rows between 1 preceding and 1 following) from t"). + Check(testkit.Rows("1 1 1", "1 1 2", "2 1 2", "2 2 2")) + tk.MustQuery("select a, first_value(a) over(rows between 1 following and 1 following), last_value(a) over(rows between 1 following and 1 following) from t"). + Check(testkit.Rows("1 1 1", "1 2 2", "2 2 2", "2 ")) + tk.MustQuery("select a, first_value(rand(0)) over(), last_value(rand(0)) over() from t"). + Check(testkit.Rows("1 0.15522042769493574 0.33109208227236947", "1 0.15522042769493574 0.33109208227236947", + "2 0.15522042769493574 0.33109208227236947", "2 0.15522042769493574 0.33109208227236947")) + + tk.MustQuery("select a, b, cume_dist() over() from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 1 1", "2 2 1")) + tk.MustQuery("select a, b, cume_dist() over(order by a) from t"). + Check(testkit.Rows("1 1 0.5", "1 2 0.5", "2 1 1", "2 2 1")) + tk.MustQuery("select a, b, cume_dist() over(order by a, b) from t"). + Check(testkit.Rows("1 1 0.25", "1 2 0.5", "2 1 0.75", "2 2 1")) + + tk.MustQuery("select a, nth_value(a, null) over() from t"). + Check(testkit.Rows("1 ", "1 ", "2 ", "2 ")) + tk.MustQuery("select a, nth_value(a, 1) over() from t"). + Check(testkit.Rows("1 1", "1 1", "2 1", "2 1")) + tk.MustQuery("select a, nth_value(a, 4) over() from t"). + Check(testkit.Rows("1 2", "1 2", "2 2", "2 2")) + tk.MustQuery("select a, nth_value(a, 5) over() from t"). + Check(testkit.Rows("1 ", "1 ", "2 ", "2 ")) + + tk.MustQuery("select ntile(3) over() from t"). + Check(testkit.Rows("1", "1", "2", "3")) + tk.MustQuery("select ntile(2) over() from t"). + Check(testkit.Rows("1", "1", "2", "2")) + tk.MustQuery("select ntile(null) over() from t"). + Check(testkit.Rows("", "", "", "")) + + tk.MustQuery("select a, percent_rank() over() from t"). + Check(testkit.Rows("1 0", "1 0", "2 0", "2 0")) + tk.MustQuery("select a, percent_rank() over(order by a) from t"). + Check(testkit.Rows("1 0", "1 0", "2 0.6666666666666666", "2 0.6666666666666666")) + tk.MustQuery("select a, b, percent_rank() over(order by a, b) from t"). + Check(testkit.Rows("1 1 0", "1 2 0.3333333333333333", "2 1 0.6666666666666666", "2 2 1")) + + tk.MustQuery("select a, lead(a) over (), lag(a) over() from t"). + Check(testkit.Rows("1 1 ", "1 2 1", "2 2 1", "2 2")) + tk.MustQuery("select a, lead(a, 0) over(), lag(a, 0) over() from t"). + Check(testkit.Rows("1 1 1", "1 1 1", "2 2 2", "2 2 2")) + tk.MustQuery("select a, lead(a, 1, a) over(), lag(a, 1, a) over() from t"). + Check(testkit.Rows("1 1 1", "1 2 1", "2 2 1", "2 2 2")) + tk.MustQuery("select a, lead(a, 1, 'lead') over(), lag(a, 1, 'lag') over() from t"). + Check(testkit.Rows("1 1 lag", "1 2 1", "2 2 1", "2 lead 2")) + + tk.MustQuery("SELECT CUME_DIST() OVER (ORDER BY null);"). + Check(testkit.Rows("1")) tk.MustQuery("select lead(a) over(partition by null) from t").Sort().Check(testkit.Rows("1", "2", "2", "")) @@ -207,43 +214,47 @@ func doTestWindowFunctions(tk *testkit.TestKit) { testkit.Rows(" ", "1.00 ", "2.00 "), ) - result = tk.MustQuery("select sum(a) over w, sum(b) over w from t window w as (order by a)") - result.Check(testkit.Rows("2 3", "2 3", "6 6", "6 6")) - result = tk.MustQuery("select row_number() over w, sum(b) over w from t window w as (order by a)") - result.Check(testkit.Rows("1 3", "2 3", "3 6", "4 6")) - result = tk.MustQuery("select row_number() over w, sum(b) over w from t window w as (rows between 1 preceding and 1 following)") - result.Check(testkit.Rows("1 3", "2 4", "3 5", "4 3")) + tk.MustQuery("select sum(a) over w, sum(b) over w from t window w as (order by a)"). + Check(testkit.Rows("2 3", "2 3", "6 6", "6 6")) + tk.MustQuery("select row_number() over w, sum(b) over w from t window w as (order by a)"). + Check(testkit.Rows("1 3", "2 3", "3 6", "4 6")) + tk.MustQuery("select row_number() over w, sum(b) over w from t window w as (rows between 1 preceding and 1 following)"). + Check(testkit.Rows("1 3", "2 4", "3 5", "4 3")) - tk.Se.GetSessionVars().MaxChunkSize = 1 - result = tk.MustQuery("select a, row_number() over (partition by a) from t").Sort() - result.Check(testkit.Rows("1 1", "1 2", "2 1", "2 2")) + tk.Session().GetSessionVars().MaxChunkSize = 1 + tk.MustQuery("select a, row_number() over (partition by a) from t").Sort(). + Check(testkit.Rows("1 1", "1 2", "2 1", "2 2")) } -func (s *testSuite7) TestWindowFunctionsDataReference(c *C) { +func TestWindowFunctionsDataReference(t *testing.T) { // see https://github.com/pingcap/tidb/issues/11614 - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values (2,1),(2,2),(2,3)") - tk.Se.GetSessionVars().MaxChunkSize = 2 - result := tk.MustQuery("select a, b, rank() over (partition by a order by b) from t") - result.Check(testkit.Rows("2 1 1", "2 2 2", "2 3 3")) - result = tk.MustQuery("select a, b, PERCENT_RANK() over (partition by a order by b) from t") - result.Check(testkit.Rows("2 1 0", "2 2 0.5", "2 3 1")) - result = tk.MustQuery("select a, b, CUME_DIST() over (partition by a order by b) from t") - result.Check(testkit.Rows("2 1 0.3333333333333333", "2 2 0.6666666666666666", "2 3 1")) + tk.Session().GetSessionVars().MaxChunkSize = 2 + tk.MustQuery("select a, b, rank() over (partition by a order by b) from t"). + Check(testkit.Rows("2 1 1", "2 2 2", "2 3 3")) + tk.MustQuery("select a, b, PERCENT_RANK() over (partition by a order by b) from t"). + Check(testkit.Rows("2 1 0", "2 2 0.5", "2 3 1")) + tk.MustQuery("select a, b, CUME_DIST() over (partition by a order by b) from t"). + Check(testkit.Rows("2 1 0.3333333333333333", "2 2 0.6666666666666666", "2 3 1")) // see https://github.com/pingcap/tidb/issues/12415 - result = tk.MustQuery("select b, first_value(b) over (order by b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) from t") - result.Check(testkit.Rows("1 1", "2 1", "3 1")) - result = tk.MustQuery("select b, first_value(b) over (order by b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) from t") - result.Check(testkit.Rows("1 1", "2 1", "3 1")) + tk.MustQuery("select b, first_value(b) over (order by b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) from t"). + Check(testkit.Rows("1 1", "2 1", "3 1")) + tk.MustQuery("select b, first_value(b) over (order by b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) from t"). + Check(testkit.Rows("1 1", "2 1", "3 1")) } -func (s *testSuite7) TestSlidingWindowFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSlidingWindowFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("set @@tidb_enable_pipelined_window_function=0;") defer func() { @@ -261,8 +272,10 @@ func (s *testSuite7) TestSlidingWindowFunctions(c *C) { } } -func (s *testSuite7) TestPipelinedSlidingWindowFunctions(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPipelinedSlidingWindowFunctions(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") idTypes := []string{"FLOAT", "DOUBLE"} useHighPrecisions := []string{"ON", "OFF"} @@ -277,7 +290,6 @@ func (s *testSuite7) TestPipelinedSlidingWindowFunctions(c *C) { } func baseTestSlidingWindowFunctions(tk *testkit.TestKit) { - var result *testkit.Result tk.MustExec("insert into t values (1,'M')") tk.MustExec("insert into t values (2,'F')") tk.MustExec("insert into t values (3,'F')") @@ -289,163 +301,165 @@ func baseTestSlidingWindowFunctions(tk *testkit.TestKit) { tk.MustExec("PREPARE p FROM 'SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN ? PRECEDING and ? PRECEDING) FROM t';") tk.MustExec("SET @p1= 1;") tk.MustExec("SET @p2= 2;") - result = tk.MustQuery("EXECUTE p USING @p1, @p2;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("EXECUTE p USING @p2, @p1;") - result.Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 2", " 2")) + tk.MustQuery("EXECUTE p USING @p1, @p2;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("EXECUTE p USING @p2, @p1;"). + Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 2", " 2")) tk.MustExec("DROP PREPARE p;") tk.MustExec("PREPARE p FROM 'SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN ? FOLLOWING and ? FOLLOWING) FROM t';") tk.MustExec("SET @p1= 1;") tk.MustExec("SET @p2= 2;") - result = tk.MustQuery("EXECUTE p USING @p2, @p1;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("EXECUTE p USING @p1, @p2;") - result.Check(testkit.Rows("M 2", "F 2", "F 2", "F 2", "M 2", " 1", " 0")) + tk.MustQuery("EXECUTE p USING @p2, @p1;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("EXECUTE p USING @p1, @p2;"). + Check(testkit.Rows("M 2", "F 2", "F 2", "F 2", "M 2", " 1", " 0")) tk.MustExec("DROP PREPARE p;") // COUNT ROWS - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 2", "F 2", "F 2", "M 2", " 1", " 0")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 2", " 2")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 2", "F 2", "F 2", "M 2", " 1", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 2", " 2")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) // COUNT RANGE - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 2", "F 2", "F 1", "M 0", " 1", " 0")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 0", " 1")) - result = tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 2", "F 2", "F 1", "M 0", " 1", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 1", "F 2", "F 2", "M 2", " 0", " 1")) + tk.MustQuery("SELECT sex, COUNT(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) // SUM ROWS - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 5", "F 7", "F 9", "F 15", "M 21", " 11", " ")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 3", "F 5", "M 7", " 9", " 15")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 3", "F 6", "F 10", "F 15", "M 25", " 36", " 36")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 5", "F 7", "F 9", "F 15", "M 21", " 11", " ")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 3", "F 5", "M 7", " 9", " 15")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 3", "F 6", "F 10", "F 15", "M 25", " 36", " 36")) // SUM RANGE - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 5", "F 7", "F 9", "F 5", "M ", " 11", " ")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 3", "F 5", "M 7", " ", " 10")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 6", "F 10", "F 14", "F 12", "M 9", " 21", " 21")) - result = tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows(" 21", " 21", "M 12", "F 14", "F 10", "F 6", "M 3")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 5", "F 7", "F 9", "F 5", "M ", " 11", " ")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 3", "F 5", "M 7", " ", " 10")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 6", "F 10", "F 14", "F 12", "M 9", " 21", " 21")) + tk.MustQuery("SELECT sex, SUM(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows(" 21", " 21", "M 12", "F 14", "F 10", "F 6", "M 3")) // AVG ROWS - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2.5", "F 3.5", "F 4.5", "F 7.5", "M 10.5", " 11", " ")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 1.5", "F 2.5", "M 3.5", " 4.5", " 7.5")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 1.5", "F 2", "F 2.5", "F 3", "M 4.166666666666667", " 5.142857142857143", " 5.142857142857143")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2.5", "F 3.5", "F 4.5", "F 7.5", "M 10.5", " 11", " ")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 1.5", "F 2.5", "M 3.5", " 4.5", " 7.5")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 1.5", "F 2", "F 2.5", "F 3", "M 4.166666666666667", " 5.142857142857143", " 5.142857142857143")) // AVG RANGE - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2.5", "F 3.5", "F 4.5", "F 5", "M ", " 11", " ")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 1.5", "F 2.5", "M 3.5", " ", " 10")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 2.5", "F 3.5", "F 4", "M 4.5", " 10.5", " 10.5")) - result = tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows(" 10.5", " 10.5", "M 4", "F 3.5", "F 2.5", "F 2", "M 1.5")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2.5", "F 3.5", "F 4.5", "F 5", "M ", " 11", " ")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 1.5", "F 2.5", "M 3.5", " ", " 10")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 2.5", "F 3.5", "F 4", "M 4.5", " 10.5", " 10.5")) + tk.MustQuery("SELECT sex, AVG(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows(" 10.5", " 10.5", "M 4", "F 3.5", "F 2.5", "F 2", "M 1.5")) // BIT_XOR ROWS - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 1", "F 7", "F 1", "F 15", "M 1", " 11", " 0")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 1", "F 3", "F 1", "M 7", " 1", " 15")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 3", "F 0", "F 4", "F 1", "M 11", " 0", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 1", "F 7", "F 1", "F 15", "M 1", " 11", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 1", "F 3", "F 1", "M 7", " 1", " 15")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 3", "F 0", "F 4", "F 1", "M 11", " 0", " 0")) // BIT_XOR RANGE - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 1", "F 7", "F 1", "F 5", "M 0", " 11", " 0")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M 0", "F 1", "F 3", "F 1", "M 7", " 0", " 10")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 0", "F 4", "F 0", "F 2", "M 1", " 1", " 1")) - result = tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows(" 1", " 1", "M 2", "F 0", "F 4", "F 0", "M 3")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 1", "F 7", "F 1", "F 5", "M 0", " 11", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 0", "F 0", "F 0", "F 0", "M 0", " 0", " 0")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M 0", "F 1", "F 3", "F 1", "M 7", " 0", " 10")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 0", "F 4", "F 0", "F 2", "M 1", " 1", " 1")) + tk.MustQuery("SELECT sex, BIT_XOR(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows(" 1", " 1", "M 2", "F 0", "F 4", "F 0", "M 3")) // MIN ROWS - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M 10", " 11", " ")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 1", "F 2", "M 3", " 4", " 5")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 1", "F 1", "F 1", "F 1", "M 1", " 1", " 1")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M 10", " 11", " ")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 1", "F 2", "M 3", " 4", " 5")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 1", "F 1", "F 1", "F 1", "M 1", " 1", " 1")) // MIN RANGE - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M ", " 11", " ")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 1", "F 2", "M 3", " ", " 10")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 1", "F 1", "F 2", "F 3", "M 4", " 10", " 10")) - result = tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows(" 10", " 10", "M 3", "F 2", "F 1", "F 1", "M 1")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M ", " 11", " ")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 1", "F 2", "M 3", " ", " 10")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 1", "F 1", "F 2", "F 3", "M 4", " 10", " 10")) + tk.MustQuery("SELECT sex, MIN(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows(" 10", " 10", "M 3", "F 2", "F 1", "F 1", "M 1")) // MAX ROWS - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 3", "F 4", "F 5", "F 10", "M 11", " 11", " ")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 2", "F 3", "M 4", " 5", " 10")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M 10", " 11", " 11")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 3", "F 4", "F 5", "F 10", "M 11", " 11", " ")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 2", "F 3", "M 4", " 5", " 10")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING and 3 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 2", "F 3", "F 4", "F 5", "M 10", " 11", " 11")) // MAX RANGE - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 3", "F 4", "F 5", "F 5", "M ", " 11", " ")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;") - result.Check(testkit.Rows("M ", "F 1", "F 2", "F 3", "M 4", " ", " 10")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows("M 3", "F 4", "F 5", "F 5", "M 5", " 11", " 11")) - result = tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;") - result.Check(testkit.Rows(" 11", " 11", "M 5", "F 5", "F 4", "F 3", "M 2")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 1 FOLLOWING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 3", "F 4", "F 5", "F 5", "M ", " 11", " ")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 3 FOLLOWING and 1 FOLLOWING) FROM t;"). + Check(testkit.Rows("M ", "F ", "F ", "F ", "M ", " ", " ")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 2 PRECEDING and 1 PRECEDING) FROM t;"). + Check(testkit.Rows("M ", "F 1", "F 2", "F 3", "M 4", " ", " 10")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows("M 3", "F 4", "F 5", "F 5", "M 5", " 11", " 11")) + tk.MustQuery("SELECT sex, MAX(id) OVER (ORDER BY id DESC RANGE BETWEEN 1 PRECEDING and 2 FOLLOWING) FROM t;"). + Check(testkit.Rows(" 11", " 11", "M 5", "F 5", "F 4", "F 3", "M 2")) } -func (s *testSuite7) TestIssue24264(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue24264(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tbl_2") tk.MustExec("create table tbl_2 ( col_10 char(65) collate utf8mb4_unicode_ci not null , col_11 bigint not null , col_12 datetime not null , col_13 bigint unsigned default 327695751717730004 , col_14 timestamp default '2010-11-18' not null , primary key idx_5 ( col_11,col_13 ) /*T![clustered_index] clustered */ , unique key idx_6 ( col_10,col_11,col_13 ) , unique key idx_7 ( col_14,col_12,col_13 ) )") @@ -472,8 +486,10 @@ func (s *testSuite7) TestIssue24264(c *C) { "")) } -func (s *testSuite7) TestIssue29947(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue29947(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t_tir89b, t_vejdy`) diff --git a/executor/write.go b/executor/write.go index 9b690d1141382..62013156e63d6 100644 --- a/executor/write.go +++ b/executor/write.go @@ -159,7 +159,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old // 4. Fill values into on-update-now fields, only if they are really changed. for i, col := range t.Cols() { if mysql.HasOnUpdateNowFlag(col.Flag) && !modified[i] && !onUpdateSpecified[i] { - if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.Tp, int8(col.Decimal)); err == nil { + if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.Tp, col.Decimal); err == nil { newData[i] = v modified[i] = true } else { diff --git a/executor/write_test.go b/executor/write_test.go index 11e402f446631..179775ae9d631 100644 --- a/executor/write_test.go +++ b/executor/write_test.go @@ -24,7 +24,6 @@ import ( "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/core" @@ -38,9 +37,7 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testutil" "github.com/stretchr/testify/require" ) @@ -304,16 +301,16 @@ func TestInsert(t *testing.T) { tk.MustExec("create view v as select * from t") _, err = tk.Exec("insert into v values(1,2)") - require.EqualError(t, err, "insert into view v is not supported now.") + require.EqualError(t, err, "insert into view v is not supported now") _, err = tk.Exec("replace into v values(1,2)") - require.EqualError(t, err, "replace into view v is not supported now.") + require.EqualError(t, err, "replace into view v is not supported now") tk.MustExec("drop view v") tk.MustExec("create sequence seq") _, err = tk.Exec("insert into seq values()") - require.EqualError(t, err, "insert into sequence seq is not supported now.") + require.EqualError(t, err, "insert into sequence seq is not supported now") _, err = tk.Exec("replace into seq values()") - require.EqualError(t, err, "replace into sequence seq is not supported now.") + require.EqualError(t, err, "replace into sequence seq is not supported now") tk.MustExec("drop sequence seq") // issue 22851 @@ -843,7 +840,7 @@ func TestInsertSetWithDefault(t *testing.T) { tk.MustExec("insert into t1 set a=default(b)+default(a);") tk.MustQuery("select * from t1;").Check(testkit.Rows("30 20")) // With generated columns - tk.MustExec("create table t2 (a int default 10, b int generated always as (-a) virtual, c int generated always as (-a) stored);") + tk.MustExec("create table t2 (a int default 10 primary key, b int generated always as (-a) virtual, c int generated always as (-a) stored);") tk.MustExec("insert into t2 set a=default;") tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10")) tk.MustExec("delete from t2;") @@ -859,11 +856,48 @@ func TestInsertSetWithDefault(t *testing.T) { tk.MustExec("insert into t2 set a=default(a), b=default, c=default;") tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10")) tk.MustExec("delete from t2;") + // Looks like MySQL accepts this, but still the inserted value would be default(b) i.e. ignored tk.MustGetErrCode("insert into t2 set b=default(a);", mysql.ErrBadGeneratedColumn) + // Looks like MySQL accepts this, but inserted values are all NULL tk.MustGetErrCode("insert into t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("insert into t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn) + tk.MustExec("insert into t2 set a=default(a), c=default(c)") tk.MustGetErrCode("insert into t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn) + tk.MustExec("insert into t2 set a=3, b=default, c=default(c) ON DUPLICATE KEY UPDATE b = default(b)") + // This fails most likely due only the generated column is updated -> no change -> duplicate key? + // Too odd to create a bug, better to have it documented by this test instead... + tk.MustGetErrCode("insert into t2 set a=3, b=default, c=default(c) ON DUPLICATE KEY UPDATE b = default(b)", mysql.ErrDupEntry) + tk.MustGetErrCode("insert into t2 set a=3, b=default, c=default(c) ON DUPLICATE KEY UPDATE b = default(a)", mysql.ErrBadGeneratedColumn) + tk.MustQuery("select * from t2").Sort().Check(testkit.Rows("10 -10 -10", "3 -3 -3")) tk.MustExec("drop table t1, t2") + // Issue 29926 + tk.MustExec("create table t1 (a int not null auto_increment,primary key(a), t timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)") + defer tk.MustExec("drop table if exists t1") + tk.MustExec("set @@timestamp = 1637541064") + defer tk.MustExec("set @@timestamp = DEFAULT") + tk.MustExec("insert into t1 set a=default,t=default") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("set @@timestamp = 1637541082") + tk.MustExec("insert into t1 VALUES (default,default)") + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows( + "1 2021-11-22 08:31:04", + "2 2021-11-22 08:31:22")) + tk.MustExec("set @@timestamp = 1637541332") + tk.MustExec("insert into t1 set a=1,t='2001-02-03 04:05:06' ON DUPLICATE KEY UPDATE t = default") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("insert into t1 set a=2,t='2001-02-03 04:05:06' ON DUPLICATE KEY UPDATE t = default(t)") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows( + "1 2021-11-22 08:35:32", + "2 2021-11-22 08:35:32")) + tk.MustExec(`DROP TABLE t1`) + tk.MustExec(`CREATE TABLE t1 (a int default 1 PRIMARY KEY, b int default 2)`) + tk.MustExec(`INSERT INTO t1 VALUES (2,2), (3,3)`) + tk.MustExec(`INSERT INTO t1 VALUES (3,2) ON DUPLICATE KEY UPDATE b = DEFAULT(a)`) + tk.MustExec(`INSERT INTO t1 SET a = 2, b = 3 ON DUPLICATE KEY UPDATE b = DEFAULT(a)`) + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows( + "2 1", + "3 1")) } func TestInsertOnDupUpdateDefault(t *testing.T) { @@ -894,12 +928,18 @@ func TestInsertOnDupUpdateDefault(t *testing.T) { tk.MustQuery("select * from t2").Check(testkit.Rows("3 -3 -3")) tk.MustExec("insert into t2 values (3,default,default) on duplicate key update c=default, b=default, a=4;") tk.MustQuery("select * from t2").Check(testkit.Rows("4 -4 -4")) - tk.MustExec("insert into t2 values (10,default,default) on duplicate key update b=default, a=20, c=default;") - tk.MustQuery("select * from t2").Check(testkit.Rows("4 -4 -4", "10 -10 -10")) - tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update b=default(a);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn) + tk.MustExec("insert into t2 values (4,default,default) on duplicate key update b=default, a=5, c=default;") + tk.MustQuery("select * from t2").Check(testkit.Rows("5 -5 -5")) + tk.MustGetErrCode("insert into t2 values (5,default,default) on duplicate key update b=default(a);", mysql.ErrBadGeneratedColumn) + tk.MustExec("insert into t2 values (5,default,default) on duplicate key update a=default(a), c=default(c)") + tk.MustQuery("select * from t2").Check(testkit.Rows(" ")) + tk.MustExec("delete from t2") + tk.MustExec("insert into t2 (a) values (1);") + tk.MustExec("insert into t2 values (1,default,default) on duplicate key update a=default(b), b=default(b);") + tk.MustQuery("select * from t2").Check(testkit.Rows(" ")) + tk.MustExec("delete from t2") + tk.MustExec("insert into t2 (a) values (1);") + tk.MustGetErrCode("insert into t2 values (1,default,default) on duplicate key update a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn) tk.MustExec("drop table t1, t2") tk.MustExec("set @@tidb_txn_mode = 'pessimistic'") @@ -909,7 +949,7 @@ func TestInsertOnDupUpdateDefault(t *testing.T) { err := tk.ExecToErr("insert into t values (21,'black warlock'), (22, 'dark sloth'), (21, 'cyan song') on duplicate key update c_int = c_int + 1, c_string = concat(c_int, ':', c_string);") require.True(t, kv.ErrKeyExists.Equal(err)) tk.MustExec("commit;") - tk.MustQuery("select * from t order by c_int;").Check(testutil.RowsWithSep("|", "21|silver sight", "22|gold witch", "24|gray singer")) + tk.MustQuery("select * from t order by c_int;").Check(testkit.RowsWithSep("|", "21|silver sight", "22|gold witch", "24|gray singer")) tk.MustExec("drop table t;") } @@ -1091,11 +1131,23 @@ func TestReplace(t *testing.T) { tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1", "2 1 -1 -1", "3 1 -1 -1")) tk.MustGetErrCode("replace t2 set b=default(a);", mysql.ErrBadGeneratedColumn) tk.MustGetErrCode("replace t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("replace t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("replace t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn) + tk.MustGetErrCode("replace t2 set a=default(a), c=default(c);", mysql.ErrNoDefaultForField) + tk.MustGetErrCode("replace t2 set c=default(a);", mysql.ErrBadGeneratedColumn) tk.MustExec("drop table t1, t2") } +func TestReplaceWithCICollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table t (a varchar(20) charset utf8mb4 collate utf8mb4_general_ci primary key);") + tk.MustExec("replace into t(a) values (_binary'A '),(_binary'A');") + tk.MustQuery("select a from t use index(primary);").Check(testkit.Rows("A")) + tk.MustQuery("select a from t ignore index(primary);").Check(testkit.Rows("A")) +} + func TestGeneratedColumnForInsert(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1677,7 +1729,7 @@ func TestDelete(t *testing.T) { tk.MustExec("create sequence seq") _, err = tk.Exec("delete from seq") - require.EqualError(t, err, "delete sequence seq is not supported now.") + require.EqualError(t, err, "delete sequence seq is not supported now") tk.MustExec("drop sequence seq") } @@ -1805,6 +1857,47 @@ func TestQualifiedDelete(t *testing.T) { require.Error(t, err) } +type testCase struct { + data1 []byte + data2 []byte + expected []string + restData []byte + expectedMsg string +} + +func checkCases(tests []testCase, ld *executor.LoadDataInfo, t *testing.T, tk *testkit.TestKit, ctx sessionctx.Context, selectSQL, deleteSQL string) { + origin := ld.IgnoreLines + for _, tt := range tests { + ld.IgnoreLines = origin + require.Nil(t, ctx.NewTxn(context.Background())) + ctx.GetSessionVars().StmtCtx.DupKeyAsWarning = true + ctx.GetSessionVars().StmtCtx.BadNullAsWarning = true + ctx.GetSessionVars().StmtCtx.InLoadDataStmt = true + ctx.GetSessionVars().StmtCtx.InDeleteStmt = false + data, reachLimit, err1 := ld.InsertData(context.Background(), tt.data1, tt.data2) + require.NoError(t, err1) + require.False(t, reachLimit) + err1 = ld.CheckAndInsertOneBatch(context.Background(), ld.GetRows(), ld.GetCurBatchCnt()) + require.NoError(t, err1) + ld.SetMaxRowsInBatch(20000) + comment := fmt.Sprintf("data1:%v, data2:%v, data:%v", string(tt.data1), string(tt.data2), string(data)) + if tt.restData == nil { + require.Len(t, data, 0, comment) + } else { + require.Equal(t, tt.restData, data, comment) + } + ld.SetMessage() + require.Equal(t, tt.expectedMsg, tk.Session().LastMessage()) + ctx.StmtCommit() + txn, err := ctx.Txn(true) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + tk.MustQuery(selectSQL).Check(testkit.RowsWithSep("|", tt.expected...)) + tk.MustExec(deleteSQL) + } +} + func TestLoadDataMissingColumn(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1893,8 +1986,6 @@ func TestLoadData(t *testing.T) { tk.MustExec(createSQL) _, err = tk.Exec("load data infile '/tmp/nonexistence.csv' into table load_data_test") require.Error(t, err) - _, err = tk.Exec("load data local infile '/tmp/nonexistence.csv' replace into table load_data_test") - require.Error(t, err) tk.MustExec("load data local infile '/tmp/nonexistence.csv' ignore into table load_data_test") ctx := tk.Session().(sessionctx.Context) ld, ok := ctx.Value(executor.LoadDataVarKey).(*executor.LoadDataInfo) @@ -2104,33 +2195,14 @@ func TestLoadDataEscape(t *testing.T) { {nil, []byte("7\trtn0ZbN\n"), []string{"7|" + string([]byte{'r', 't', 'n', '0', 'Z', 'b', 'N'})}, nil, trivialMsg}, {nil, []byte("8\trtn0Zb\\N\n"), []string{"8|" + string([]byte{'r', 't', 'n', '0', 'Z', 'b', 'N'})}, nil, trivialMsg}, {nil, []byte("9\ttab\\ tab\n"), []string{"9|tab tab"}, nil, trivialMsg}, + // data broken at escape character. + {[]byte("1\ta string\\"), []byte("\n1\n"), []string{"1|a string\n1"}, nil, trivialMsg}, } deleteSQL := "delete from load_data_test" selectSQL := "select * from load_data_test;" checkCases(tests, ld, t, tk, ctx, selectSQL, deleteSQL) } -func TestLoadDataWithLongContent(t *testing.T) { - e := &executor.LoadDataInfo{ - FieldsInfo: &ast.FieldsClause{Terminated: ",", Escaped: '\\', Enclosed: '"'}, - LinesInfo: &ast.LinesClause{Terminated: "\n"}, - } - tests := []struct { - content string - inQuoter bool - expectedIndex int - }{ - {"123,123\n123,123", false, 7}, - {"123123\\n123123", false, -1}, - {"123123\n123123", true, -1}, - {"123123\n123123\"\n", true, 14}, - } - - for _, tt := range tests { - require.Equal(t, tt.expectedIndex, e.IndexOfTerminator([]byte(tt.content), tt.inQuoter)) - } -} - // TestLoadDataSpecifiedColumns reuse TestLoadDataEscape's test case :-) func TestLoadDataSpecifiedColumns(t *testing.T) { trivialMsg := "Records: 1 Deleted: 0 Skipped: 0 Warnings: 0" @@ -2182,6 +2254,28 @@ func TestLoadDataIgnoreLines(t *testing.T) { checkCases(tests, ld, t, tk, ctx, selectSQL, deleteSQL) } +func TestLoadDataReplace(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("USE test; DROP TABLE IF EXISTS load_data_replace;") + tk.MustExec("CREATE TABLE load_data_replace (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL)") + tk.MustExec("INSERT INTO load_data_replace VALUES(1,'val 1'),(2,'val 2')") + tk.MustExec("LOAD DATA LOCAL INFILE '/tmp/nonexistence.csv' REPLACE INTO TABLE load_data_replace") + ctx := tk.Session().(sessionctx.Context) + ld, ok := ctx.Value(executor.LoadDataVarKey).(*executor.LoadDataInfo) + require.True(t, ok) + defer ctx.SetValue(executor.LoadDataVarKey, nil) + require.NotNil(t, ld) + tests := []testCase{ + {nil, []byte("1\tline1\n2\tline2\n"), []string{"1|line1", "2|line2"}, nil, "Records: 2 Deleted: 2 Skipped: 0 Warnings: 0"}, + {nil, []byte("2\tnew line2\n3\tnew line3\n"), []string{"1|line1", "2|new line2", "3|new line3"}, nil, "Records: 2 Deleted: 1 Skipped: 0 Warnings: 0"}, + } + deleteSQL := "DO 1" + selectSQL := "TABLE load_data_replace;" + checkCases(tests, ld, t, tk, ctx, selectSQL, deleteSQL) +} + // TestLoadDataOverflowBigintUnsigned related to issue 6360 func TestLoadDataOverflowBigintUnsigned(t *testing.T) { store, clean := testkit.CreateMockStore(t) @@ -4137,10 +4231,19 @@ func TestUpdate(t *testing.T) { tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "40 -40 -40")) tk.MustExec("update t2 set a=default(a), b=default, c=default;") tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "1 -1 -1")) + // Same as in MySQL 8.0.27, but still weird behavior: a=default(b) => NULL + tk.MustExec("update t2 set a=default(b), b=default, c=default;") + tk.MustQuery("select * from t2;").Check(testkit.Rows(" ", " ")) tk.MustGetErrCode("update t2 set b=default(a);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("update t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("update t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn) - tk.MustGetErrCode("update t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn) + tk.MustExec("update t2 set a=default(a), c=default(c)") + tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "1 -1 -1")) + // Same as in MySQL 8.0.27, but still weird behavior: a=default(b) => NULL + tk.MustExec("update t2 set a=default(b), b=default(b)") + tk.MustQuery("select * from t2;").Check(testkit.Rows(" ", " ")) + tk.MustExec("update t2 set a=default(a), c=default(c)") + tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "1 -1 -1")) + // Allowed in MySQL, but should probably not be allowed. + tk.MustGetErrCode("update t2 set a=default(a), c=default(a)", mysql.ErrBadGeneratedColumn) tk.MustExec("drop table t1, t2") } @@ -4190,9 +4293,6 @@ func TestListColumnsPartitionWithGlobalIndex(t *testing.T) { } func TestIssue20724(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -4206,9 +4306,6 @@ func TestIssue20724(t *testing.T) { } func TestIssue20840(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -4223,9 +4320,6 @@ func TestIssue20840(t *testing.T) { } func TestIssueInsertPrefixIndexForNonUTF8Collation(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) diff --git a/expression/aggregation/agg_to_pb.go b/expression/aggregation/agg_to_pb.go index d50c7ab4de78c..a2e5b89539acc 100644 --- a/expression/aggregation/agg_to_pb.go +++ b/expression/aggregation/agg_to_pb.go @@ -102,9 +102,48 @@ func AggFuncToPBExpr(sctx sessionctx.Context, client kv.Client, aggFunc *AggFunc sc.AppendWarning(errors.Errorf("Error happened when buildGroupConcat: %s", err.Error())) return nil } - return &tipb.Expr{Tp: tp, Val: codec.EncodeUint(nil, maxLen), Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct, OrderBy: orderBy} + return &tipb.Expr{Tp: tp, Val: codec.EncodeUint(nil, maxLen), Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct, OrderBy: orderBy, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)} } - return &tipb.Expr{Tp: tp, Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct} + return &tipb.Expr{Tp: tp, Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)} +} + +// AggFunctionModeToPB converts aggregate function mode to PB. +func AggFunctionModeToPB(mode AggFunctionMode) (pbMode *tipb.AggFunctionMode) { + pbMode = new(tipb.AggFunctionMode) + switch mode { + case CompleteMode: + *pbMode = tipb.AggFunctionMode_CompleteMode + case FinalMode: + *pbMode = tipb.AggFunctionMode_FinalMode + case Partial1Mode: + *pbMode = tipb.AggFunctionMode_Partial1Mode + case Partial2Mode: + *pbMode = tipb.AggFunctionMode_Partial2Mode + case DedupMode: + *pbMode = tipb.AggFunctionMode_DedupMode + } + return pbMode +} + +// PBAggFuncModeToAggFuncMode converts pb to aggregate function mode. +func PBAggFuncModeToAggFuncMode(pbMode *tipb.AggFunctionMode) (mode AggFunctionMode) { + // Default mode of the aggregate function is PartialMode. + mode = Partial1Mode + if pbMode != nil { + switch *pbMode { + case tipb.AggFunctionMode_CompleteMode: + mode = CompleteMode + case tipb.AggFunctionMode_FinalMode: + mode = FinalMode + case tipb.AggFunctionMode_Partial1Mode: + mode = Partial1Mode + case tipb.AggFunctionMode_Partial2Mode: + mode = Partial2Mode + case tipb.AggFunctionMode_DedupMode: + mode = DedupMode + } + } + return mode } // PBExprToAggFuncDesc converts pb to aggregate function. @@ -149,7 +188,7 @@ func PBExprToAggFuncDesc(ctx sessionctx.Context, aggFunc *tipb.Expr, fieldTps [] base.WrapCastForAggArgs(ctx) return &AggFuncDesc{ baseFuncDesc: base, - Mode: Partial1Mode, + Mode: PBAggFuncModeToAggFuncMode(aggFunc.AggFuncMode), HasDistinct: false, }, nil } diff --git a/expression/aggregation/agg_to_pb_test.go b/expression/aggregation/agg_to_pb_test.go index 9aa886e2d70ea..31558d16c7467 100644 --- a/expression/aggregation/agg_to_pb_test.go +++ b/expression/aggregation/agg_to_pb_test.go @@ -51,13 +51,13 @@ func TestAggFunc2Pb(t *testing.T) { } jsons := []string{ - `{"tp":3002,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, - `{"tp":3001,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":8,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, - `{"tp":3003,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, - `{"tp":3007,"val":"AAAAAAAABAA=","children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":15,"flag":0,"flen":-1,"decimal":-1,"collate":46,"charset":"utf8mb4"},"has_distinct":%v}`, - `{"tp":3005,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, - `{"tp":3004,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, - `{"tp":3006,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":63,"charset":"binary"},"has_distinct":%v}`, + `{"tp":3002,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3001,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":8,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3003,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3007,"val":"AAAAAAAABAA=","children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":15,"flag":0,"flen":-1,"decimal":-1,"collate":-46,"charset":"utf8mb4"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3005,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3004,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, + `{"tp":3006,"children":[{"tp":201,"val":"gAAAAAAAAAE=","sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":false}],"sig":0,"field_type":{"tp":5,"flag":0,"flen":-1,"decimal":-1,"collate":-63,"charset":"binary"},"has_distinct":%v,"aggFuncMode":0}`, } for i, funcName := range funcNames { for _, hasDistinct := range []bool{true, false} { diff --git a/expression/aggregation/avg.go b/expression/aggregation/avg.go index 9dd4b508cc79c..c1e32c92c847f 100644 --- a/expression/aggregation/avg.go +++ b/expression/aggregation/avg.go @@ -86,7 +86,7 @@ func (af *avgFunction) GetResult(evalCtx *AggEvaluateContext) (d types.Datum) { if frac == -1 { frac = mysql.MaxDecimalScale } - err = to.Round(to, mathutil.Min(frac, mysql.MaxDecimalScale), types.ModeHalfEven) + err = to.Round(to, mathutil.Min(frac, mysql.MaxDecimalScale), types.ModeHalfUp) terror.Log(err) d.SetMysqlDecimal(to) } diff --git a/expression/aggregation/base_func.go b/expression/aggregation/base_func.go index 1c639eeb4f14d..a185910c82b97 100644 --- a/expression/aggregation/base_func.go +++ b/expression/aggregation/base_func.go @@ -178,7 +178,7 @@ func (a *baseFuncDesc) typeInfer4ApproxPercentile(ctx sessionctx.Context) error return nil } -// typeInfer4Sum should returns a "decimal", otherwise it returns a "double". +// typeInfer4Sum should return a "decimal", otherwise it returns a "double". // Because child returns integer or decimal type. func (a *baseFuncDesc) typeInfer4Sum(ctx sessionctx.Context) { switch a.Args[0].GetType().Tp { @@ -421,6 +421,7 @@ func (a *baseFuncDesc) WrapCastForAggArgs(ctx sessionctx.Context) { if a.Args[i].GetType().Tp == mysql.TypeNull { continue } + tpOld := a.Args[i].GetType().Tp a.Args[i] = castFunc(ctx, a.Args[i]) if a.Name != ast.AggFuncAvg && a.Name != ast.AggFuncSum { continue @@ -443,5 +444,37 @@ func (a *baseFuncDesc) WrapCastForAggArgs(ctx sessionctx.Context) { originTp := a.Args[i].GetType().Tp *(a.Args[i].GetType()) = *(a.RetTp) a.Args[i].GetType().Tp = originTp + + // refine each mysql integer type to the needed decimal precision for sum + if a.Name == ast.AggFuncSum { + adjustDecimalLenForSumInteger(a.Args[i].GetType(), tpOld) + } + } +} + +func adjustDecimalLenForSumInteger(ft *types.FieldType, tpOld byte) { + if types.IsTypeInteger(tpOld) && ft.Tp == mysql.TypeNewDecimal { + if flen, err := minimalDecimalLenForHoldingInteger(tpOld); err == nil { + ft.Flen = mathutil.Min(ft.Flen, flen+ft.Decimal) + } + } +} + +func minimalDecimalLenForHoldingInteger(tp byte) (int, error) { + switch tp { + case mysql.TypeTiny: + return 3, nil + case mysql.TypeShort: + return 5, nil + case mysql.TypeInt24: + return 8, nil + case mysql.TypeLong: + return 10, nil + case mysql.TypeLonglong: + return 20, nil + case mysql.TypeYear: + return 4, nil + default: + return -1, errors.Errorf("Invalid type: %v", tp) } } diff --git a/expression/aggregation/concat.go b/expression/aggregation/concat.go index 21b3e0d787954..a5f6ae8f0468e 100644 --- a/expression/aggregation/concat.go +++ b/expression/aggregation/concat.go @@ -52,7 +52,7 @@ func (cf *concatFunction) initSeparator(sc *stmtctx.StatementContext, row chunk. return err } if sepDatum.IsNull() { - return errors.Errorf("Invalid separator argument.") + return errors.Errorf("Invalid separator argument") } cf.separator, err = sepDatum.ToString() return err diff --git a/expression/aggregation/main_test.go b/expression/aggregation/main_test.go index 4078dc6cf4b48..40ea88a12c516 100644 --- a/expression/aggregation/main_test.go +++ b/expression/aggregation/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/expression/builtin.go b/expression/builtin.go index 1b67239613498..b693d21145223 100644 --- a/expression/builtin.go +++ b/expression/builtin.go @@ -114,7 +114,7 @@ func newBaseBuiltinFunc(ctx sessionctx.Context, funcName string, args []Expressi // newBaseBuiltinFuncWithTp creates a built-in function signature with specified types of arguments and the return type of the function. // argTps indicates the types of the args, retType indicates the return type of the built-in function. -// Every built-in function needs determined argTps and retType when we create it. +// Every built-in function needs to be determined argTps and retType when we create it. func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Expression, retType types.EvalType, argTps ...types.EvalType) (bf baseBuiltinFunc, err error) { if len(args) != len(argTps) { panic("unexpected length of args and argTps") @@ -187,21 +187,21 @@ func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Ex fieldType = &types.FieldType{ Tp: mysql.TypeDatetime, Flen: mysql.MaxDatetimeWidthWithFsp, - Decimal: int(types.MaxFsp), + Decimal: types.MaxFsp, Flag: mysql.BinaryFlag, } case types.ETTimestamp: fieldType = &types.FieldType{ Tp: mysql.TypeTimestamp, Flen: mysql.MaxDatetimeWidthWithFsp, - Decimal: int(types.MaxFsp), + Decimal: types.MaxFsp, Flag: mysql.BinaryFlag, } case types.ETDuration: fieldType = &types.FieldType{ Tp: mysql.TypeDuration, Flen: mysql.MaxDurationWidthWithFsp, - Decimal: int(types.MaxFsp), + Decimal: types.MaxFsp, Flag: mysql.BinaryFlag, } case types.ETJson: @@ -781,6 +781,7 @@ var funcs = map[string]functionClass{ ast.VitessHash: &vitessHashFunctionClass{baseFunctionClass{ast.VitessHash, 1, 1}}, ast.UUIDToBin: &uuidToBinFunctionClass{baseFunctionClass{ast.UUIDToBin, 1, 2}}, ast.BinToUUID: &binToUUIDFunctionClass{baseFunctionClass{ast.BinToUUID, 1, 2}}, + ast.TiDBShard: &tidbShardFunctionClass{baseFunctionClass{ast.TiDBShard, 1, 1}}, // get_lock() and release_lock() are parsed but do nothing. // It is used for preventing error in Ruby's activerecord migrations. diff --git a/expression/builtin_arithmetic.go b/expression/builtin_arithmetic.go index 6c82a938206ce..4bb4927ff1835 100644 --- a/expression/builtin_arithmetic.go +++ b/expression/builtin_arithmetic.go @@ -90,11 +90,6 @@ func numericContextResultType(ft *types.FieldType) types.EvalType { // type according to the two input parameter's types. func setFlenDecimal4RealOrDecimal(ctx sessionctx.Context, retTp *types.FieldType, arg0, arg1 Expression, isReal bool, isMultiply bool) { a, b := arg0.GetType(), arg1.GetType() - if MaybeOverOptimized4PlanCache(ctx, []Expression{arg0, arg1}) { - // set length and decimal to unspecified if arguments depend on parameters - retTp.Flen, retTp.Decimal = types.UnspecifiedLength, types.UnspecifiedLength - return - } if a.Decimal != types.UnspecifiedLength && b.Decimal != types.UnspecifiedLength { retTp.Decimal = a.Decimal + b.Decimal if !isMultiply { @@ -111,7 +106,7 @@ func setFlenDecimal4RealOrDecimal(ctx sessionctx.Context, retTp *types.FieldType if isMultiply { digitsInt = a.Flen - a.Decimal + b.Flen - b.Decimal } - retTp.Flen = digitsInt + retTp.Decimal + 3 + retTp.Flen = digitsInt + retTp.Decimal + 1 if isReal { retTp.Flen = mathutil.Min(retTp.Flen, mysql.MaxRealWidth) return @@ -128,10 +123,10 @@ func setFlenDecimal4RealOrDecimal(ctx sessionctx.Context, retTp *types.FieldType func (c *arithmeticDivideFunctionClass) setType4DivDecimal(retTp, a, b *types.FieldType) { var deca, decb = a.Decimal, b.Decimal - if deca == int(types.UnspecifiedFsp) { + if deca == types.UnspecifiedFsp { deca = 0 } - if decb == int(types.UnspecifiedFsp) { + if decb == types.UnspecifiedFsp { decb = 0 } retTp.Decimal = deca + precIncrement @@ -726,7 +721,7 @@ func (s *builtinArithmeticDivideDecimalSig) evalDecimal(row chunk.Row) (*types.M } else if err == nil { _, frac := c.PrecisionAndFrac() if frac < s.baseBuiltinFunc.tp.Decimal { - err = c.Round(c, s.baseBuiltinFunc.tp.Decimal, types.ModeHalfEven) + err = c.Round(c, s.baseBuiltinFunc.tp.Decimal, types.ModeHalfUp) } } else if err == types.ErrOverflow { err = types.ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%s / %s)", s.args[0].String(), s.args[1].String())) diff --git a/expression/builtin_arithmetic_test.go b/expression/builtin_arithmetic_test.go index 196caaf535efe..120ce08754cb1 100644 --- a/expression/builtin_arithmetic_test.go +++ b/expression/builtin_arithmetic_test.go @@ -21,7 +21,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/mock" @@ -41,7 +41,7 @@ func TestSetFlenDecimal4RealOrDecimal(t *testing.T) { } setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) require.Equal(t, 1, ret.Decimal) - require.Equal(t, 6, ret.Flen) + require.Equal(t, 4, ret.Flen) b.Flen = 65 setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, false) @@ -72,7 +72,7 @@ func TestSetFlenDecimal4RealOrDecimal(t *testing.T) { } setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) require.Equal(t, 1, ret.Decimal) - require.Equal(t, 8, ret.Flen) + require.Equal(t, 6, ret.Flen) b.Flen = 65 setFlenDecimal4RealOrDecimal(mock.NewContext(), ret, &Constant{RetType: a}, &Constant{RetType: b}, true, true) @@ -315,7 +315,7 @@ func TestArithmeticMultiply(t *testing.T) { val, err := evalBuiltinFunc(sig, chunk.Row{}) if tc.expect[1] == nil { require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.expect[0]), val) + testutil.DatumEqual(t, types.NewDatum(tc.expect[0]), val) } else { require.Error(t, err) require.Regexp(t, tc.expect[1], err.Error()) @@ -388,7 +388,7 @@ func TestArithmeticDivide(t *testing.T) { } val, err := evalBuiltinFunc(sig, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.expect), val) + testutil.DatumEqual(t, types.NewDatum(tc.expect), val) } } @@ -499,7 +499,7 @@ func TestArithmeticIntDivide(t *testing.T) { val, err := evalBuiltinFunc(sig, chunk.Row{}) if tc.expect[1] == nil { require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.expect[0]), val) + testutil.DatumEqual(t, types.NewDatum(tc.expect[0]), val) } else { require.Error(t, err) require.Regexp(t, tc.expect[1], err.Error()) @@ -655,7 +655,7 @@ func TestArithmeticMod(t *testing.T) { require.Equal(t, tipb.ScalarFuncSig_ModDecimal, sig.PbCode()) } require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.expect), val) + testutil.DatumEqual(t, types.NewDatum(tc.expect), val) } } diff --git a/expression/builtin_arithmetic_vec.go b/expression/builtin_arithmetic_vec.go index 07c0965ffe669..42e076b803dc1 100644 --- a/expression/builtin_arithmetic_vec.go +++ b/expression/builtin_arithmetic_vec.go @@ -100,7 +100,7 @@ func (b *builtinArithmeticDivideDecimalSig) vecEvalDecimal(input *chunk.Chunk, r } else if err == nil { _, frac = to.PrecisionAndFrac() if frac < b.baseBuiltinFunc.tp.Decimal { - if err = to.Round(&to, b.baseBuiltinFunc.tp.Decimal, types.ModeHalfEven); err != nil { + if err = to.Round(&to, b.baseBuiltinFunc.tp.Decimal, types.ModeHalfUp); err != nil { return err } } diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index 392fe11953c75..a3c8442773565 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -284,12 +284,7 @@ func (c *castAsStringFunctionClass) getFunction(ctx sessionctx.Context, args []E return nil, err } bf.tp = c.tp - if args[0].GetType().Hybrid() || IsBinaryLiteral(args[0]) { - // When cast from binary to some other charsets, we should check if the binary is valid or not. - // so we build a from_binary function to do this check. - ft := args[0].GetType().Clone() - ft.Charset, ft.Collate = c.tp.Charset, c.tp.Collate - bf.args[0] = BuildFromBinaryFunction(ctx, args[0], ft) + if args[0].GetType().Hybrid() { sig = &builtinCastStringAsStringSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CastStringAsString) return sig, nil @@ -318,6 +313,9 @@ func (c *castAsStringFunctionClass) getFunction(ctx sessionctx.Context, args []E sig = &builtinCastJSONAsStringSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CastJsonAsString) case types.ETString: + // When cast from binary to some other charsets, we should check if the binary is valid or not. + // so we build a from_binary function to do this check. + bf.args[0] = HandleBinaryLiteral(ctx, args[0], &ExprCollation{Charset: c.tp.Charset, Collation: c.tp.Collate}, c.funcName) sig = &builtinCastStringAsStringSig{bf} sig.setPbCode(tipb.ScalarFuncSig_CastStringAsString) default: @@ -591,7 +589,7 @@ func (b *builtinCastIntAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNul if b.args[0].GetType().Tp == mysql.TypeYear { res, err = types.ParseTimeFromYear(b.ctx.GetSessionVars().StmtCtx, val) } else { - res, err = types.ParseTimeFromNum(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Tp, int8(b.tp.Decimal)) + res, err = types.ParseTimeFromNum(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Tp, b.tp.Decimal) } if err != nil { @@ -619,7 +617,7 @@ func (b *builtinCastIntAsDurationSig) evalDuration(row chunk.Row) (res types.Dur if isNull || err != nil { return res, isNull, err } - dur, err := types.NumberToDuration(val, int8(b.tp.Decimal)) + dur, err := types.NumberToDuration(val, b.tp.Decimal) if err != nil { if types.ErrOverflow.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, err) @@ -892,7 +890,7 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er return types.ZeroTime, false, nil } sc := b.ctx.GetSessionVars().StmtCtx - res, err := types.ParseTime(sc, fv, b.tp.Tp, int8(b.tp.Decimal)) + res, err := types.ParseTime(sc, fv, b.tp.Tp, b.tp.Decimal) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } @@ -918,7 +916,7 @@ func (b *builtinCastRealAsDurationSig) evalDuration(row chunk.Row) (res types.Du if isNull || err != nil { return res, isNull, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(val, 'f', -1, 64), int8(b.tp.Decimal)) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(val, 'f', -1, 64), b.tp.Decimal) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -971,7 +969,7 @@ func (b *builtinCastDecimalAsIntSig) evalInt(row chunk.Row) (res int64, isNull b // Round is needed for both unsigned and signed. var to types.MyDecimal - err = val.Round(&to, 0, types.ModeHalfEven) + err = val.Round(&to, 0, types.ModeHalfUp) if err != nil { return 0, true, err } @@ -1070,7 +1068,7 @@ func (b *builtinCastDecimalAsTimeSig) evalTime(row chunk.Row) (res types.Time, i return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTimeFromFloatString(sc, string(val.ToString()), b.tp.Tp, int8(b.tp.Decimal)) + res, err = types.ParseTimeFromFloatString(sc, string(val.ToString()), b.tp.Tp, b.tp.Decimal) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } @@ -1096,7 +1094,7 @@ func (b *builtinCastDecimalAsDurationSig) evalDuration(row chunk.Row) (res types if isNull || err != nil { return res, true, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(val.ToString()), int8(b.tp.Decimal)) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(val.ToString()), b.tp.Decimal) if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) // ErrTruncatedWrongVal needs to be considered NULL. @@ -1290,10 +1288,13 @@ func (b *builtinCastStringAsTimeSig) evalTime(row chunk.Row) (res types.Time, is return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, val, b.tp.Tp, int8(b.tp.Decimal)) + res, err = types.ParseTime(sc, val, b.tp.Tp, b.tp.Decimal) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } + if res.IsZero() && b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { + return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, res.String())) + } if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) @@ -1316,7 +1317,7 @@ func (b *builtinCastStringAsDurationSig) evalDuration(row chunk.Row) (res types. if isNull || err != nil { return res, isNull, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, val, int8(b.tp.Decimal)) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, val, b.tp.Decimal) if types.ErrTruncatedWrongVal.Equal(err) { sc := b.ctx.GetSessionVars().StmtCtx err = sc.HandleTruncate(err) @@ -1348,7 +1349,7 @@ func (b *builtinCastTimeAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu if res, err = res.Convert(sc, b.tp.Tp); err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - res, err = res.RoundFrac(sc, int8(b.tp.Decimal)) + res, err = res.RoundFrac(sc, b.tp.Decimal) if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) @@ -1462,7 +1463,7 @@ func (b *builtinCastTimeAsDurationSig) evalDuration(row chunk.Row) (res types.Du if err != nil { return res, false, err } - res, err = res.RoundFrac(int8(b.tp.Decimal), b.ctx.GetSessionVars().Location()) + res, err = res.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) return res, false, err } @@ -1481,7 +1482,7 @@ func (b *builtinCastDurationAsDurationSig) evalDuration(row chunk.Row) (res type if isNull || err != nil { return res, isNull, err } - res, err = res.RoundFrac(int8(b.tp.Decimal), b.ctx.GetSessionVars().Location()) + res, err = res.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) return res, false, err } @@ -1523,7 +1524,7 @@ func (b *builtinCastDurationAsRealSig) evalReal(row chunk.Row) (res float64, isN if isNull || err != nil { return res, isNull, err } - if val.Fsp, err = types.CheckFsp(int(val.Fsp)); err != nil { + if val.Fsp, err = types.CheckFsp(val.Fsp); err != nil { return res, false, err } res, err = val.ToNumber().ToFloat64() @@ -1545,7 +1546,7 @@ func (b *builtinCastDurationAsDecimalSig) evalDecimal(row chunk.Row) (res *types if isNull || err != nil { return res, isNull, err } - if val.Fsp, err = types.CheckFsp(int(val.Fsp)); err != nil { + if val.Fsp, err = types.CheckFsp(val.Fsp); err != nil { return res, false, err } sc := b.ctx.GetSessionVars().StmtCtx @@ -1579,15 +1580,13 @@ func (b *builtinCastDurationAsStringSig) evalString(row chunk.Row) (res string, func padZeroForBinaryType(s string, tp *types.FieldType, ctx sessionctx.Context) (string, bool, error) { flen := tp.Flen if tp.Tp == mysql.TypeString && types.IsBinaryStr(tp) && len(s) < flen { - sc := ctx.GetSessionVars().StmtCtx valStr, _ := ctx.GetSessionVars().GetSystemVar(variable.MaxAllowedPacket) maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64) if err != nil { return "", false, errors.Trace(err) } if uint64(flen) > maxAllowedPacket { - sc.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("cast_as_binary", maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(ctx, "cast_as_binary", maxAllowedPacket) } padding := make([]byte, flen-len(s)) s = string(append([]byte(s), padding...)) @@ -1615,7 +1614,7 @@ func (b *builtinCastDurationAsTimeSig) evalTime(row chunk.Row) (res types.Time, if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } - res, err = res.RoundFrac(sc, int8(b.tp.Decimal)) + res, err = res.RoundFrac(sc, b.tp.Decimal) return res, false, err } @@ -1735,7 +1734,7 @@ func (b *builtinCastJSONAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu return res, false, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, s, b.tp.Tp, int8(b.tp.Decimal)) + res, err = types.ParseTime(sc, s, b.tp.Tp, b.tp.Decimal) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } @@ -1765,7 +1764,7 @@ func (b *builtinCastJSONAsDurationSig) evalDuration(row chunk.Row) (res types.Du if err != nil { return res, false, err } - res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, s, int8(b.tp.Decimal)) + res, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, s, b.tp.Decimal) if types.ErrTruncatedWrongVal.Equal(err) { sc := b.ctx.GetSessionVars().StmtCtx err = sc.HandleTruncate(err) @@ -1827,11 +1826,21 @@ func BuildCastFunction4Union(ctx sessionctx.Context, expr Expression, tp *types. } // BuildCastCollationFunction builds a ScalarFunction which casts the collation. -func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *ExprCollation) Expression { +func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *ExprCollation, enumOrSetRealTypeIsStr bool) Expression { + if expr.GetType().EvalType() != types.ETString { + return expr + } if expr.GetType().Collate == ec.Collation { return expr } tp := expr.GetType().Clone() + if expr.GetType().Hybrid() { + if enumOrSetRealTypeIsStr { + tp = types.NewFieldType(mysql.TypeVarString) + } else { + return expr + } + } tp.Charset, tp.Collate = ec.Charset, ec.Collation newExpr := BuildCastFunction(ctx, expr, tp) return newExpr @@ -1839,6 +1848,11 @@ func BuildCastCollationFunction(ctx sessionctx.Context, expr Expression, ec *Exp // BuildCastFunction builds a CAST ScalarFunction from the Expression. func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldType) (res Expression) { + argType := expr.GetType() + // If source argument's nullable, then target type should be nullable + if !mysql.HasNotNullFlag(argType.Flag) { + tp.Flag &= ^mysql.NotNullFlag + } expr = TryPushCastIntoControlFunctionForHybridType(ctx, expr, tp) var fc functionClass switch tp.EvalType() { @@ -1856,6 +1870,9 @@ func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldT fc = &castAsJSONFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} case types.ETString: fc = &castAsStringFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} + if expr.GetType().Tp == mysql.TypeBit { + tp.Flen = (expr.GetType().Flen + 7) / 8 + } } f, err := fc.getFunction(ctx, []Expression{expr}) terror.Log(err) @@ -1923,7 +1940,24 @@ func WrapWithCastAsDecimal(ctx sessionctx.Context, expr Expression) Expression { } types.SetBinChsClnFlag(tp) tp.Flag |= expr.GetType().Flag & mysql.UnsignedFlag - return BuildCastFunction(ctx, expr, tp) + castExpr := BuildCastFunction(ctx, expr, tp) + // For const item, we can use find-grained precision and scale by the result. + if castExpr.ConstItem(ctx.GetSessionVars().StmtCtx) { + val, isnull, err := castExpr.EvalDecimal(ctx, chunk.Row{}) + if !isnull && err == nil { + precision, frac := val.PrecisionAndFrac() + castTp := castExpr.GetType() + castTp.Decimal = frac + castTp.Flen = precision + if castTp.Flen > mysql.MaxDecimalWidth { + castTp.Flen = mysql.MaxDecimalWidth + } + if castTp.Decimal > mysql.MaxDecimalScale { + castTp.Decimal = mysql.MaxDecimalScale + } + } + } + return castExpr } // WrapWithCastAsString wraps `expr` with `cast` if the return type of expr is @@ -1938,12 +1972,19 @@ func WrapWithCastAsString(ctx sessionctx.Context, expr Expression) Expression { // into consideration, so we set `expr.GetType().Flen + 3` as the `argLen`. // Since the length of float and double is not accurate, we do not handle // them. - if exprTp.Tp == mysql.TypeNewDecimal && argLen != int(types.UnspecifiedFsp) { + if exprTp.Tp == mysql.TypeNewDecimal && argLen != types.UnspecifiedFsp { argLen += 3 } + if exprTp.EvalType() == types.ETInt { argLen = mysql.MaxIntWidth + // For TypeBit, castAsString will make length as int(( bit_len + 7 ) / 8) bytes due to + // TiKV needs the bit's real len during calculating, eg: ascii(bit). + if exprTp.Tp == mysql.TypeBit { + argLen = (exprTp.Flen + 7) / 8 + } } + // Because we can't control the length of cast(float as char) for now, we can't determine the argLen. if exprTp.Tp == mysql.TypeFloat || exprTp.Tp == mysql.TypeDouble { argLen = -1 @@ -1969,15 +2010,15 @@ func WrapWithCastAsTime(ctx sessionctx.Context, expr Expression, tp *types.Field } switch x := expr.GetType().EvalType(); x { case types.ETInt: - tp.Decimal = int(types.MinFsp) + tp.Decimal = types.MinFsp case types.ETString, types.ETReal, types.ETJson: - tp.Decimal = int(types.MaxFsp) + tp.Decimal = types.MaxFsp case types.ETDatetime, types.ETTimestamp, types.ETDuration: tp.Decimal = expr.GetType().Decimal case types.ETDecimal: tp.Decimal = expr.GetType().Decimal - if tp.Decimal > int(types.MaxFsp) { - tp.Decimal = int(types.MaxFsp) + if tp.Decimal > types.MaxFsp { + tp.Decimal = types.MaxFsp } default: } @@ -2005,7 +2046,7 @@ func WrapWithCastAsDuration(ctx sessionctx.Context, expr Expression) Expression case mysql.TypeDatetime, mysql.TypeTimestamp, mysql.TypeDate: tp.Decimal = x.Decimal default: - tp.Decimal = int(types.MaxFsp) + tp.Decimal = types.MaxFsp } tp.Flen = mysql.MaxDurationWidthNoFsp if tp.Decimal > 0 { diff --git a/expression/builtin_cast_test.go b/expression/builtin_cast_test.go index 0d60f9d8b6e3d..f0d498dd110e9 100644 --- a/expression/builtin_cast_test.go +++ b/expression/builtin_cast_test.go @@ -323,7 +323,7 @@ func TestCastFuncSig(t *testing.T) { var sig builtinFunc durationColumn := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} - durationColumn.RetType.Decimal = int(types.DefaultFsp) + durationColumn.RetType.Decimal = types.DefaultFsp // Test cast as Decimal. castToDecCases := []struct { before *Column @@ -817,7 +817,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToTimeCases { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeDatetime) - tp.Decimal = int(types.DefaultFsp) + tp.Decimal = types.DefaultFsp timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) timeFunc.tp = tp @@ -846,7 +846,7 @@ func TestCastFuncSig(t *testing.T) { castToTimeCases2 := []struct { before *Column after types.Time - fsp int8 + fsp int tp byte row chunk.MutRow }{ @@ -902,7 +902,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToTimeCases2 { args := []Expression{c.before} tp := types.NewFieldType(c.tp) - tp.Decimal = int(c.fsp) + tp.Decimal = c.fsp timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) timeFunc.tp = tp @@ -926,7 +926,7 @@ func TestCastFuncSig(t *testing.T) { resAfter := c.after.String() if c.fsp > 0 { resAfter += "." - for i := 0; i < int(c.fsp); i++ { + for i := 0; i < c.fsp; i++ { resAfter += "0" } } @@ -984,7 +984,7 @@ func TestCastFuncSig(t *testing.T) { for i, c := range castToDurationCases { args := []Expression{c.before} tp := types.NewFieldType(mysql.TypeDuration) - tp.Decimal = int(types.DefaultFsp) + tp.Decimal = types.DefaultFsp durationFunc, err := newBaseBuiltinFunc(ctx, "", args, 0) require.NoError(t, err) durationFunc.tp = tp @@ -1166,7 +1166,7 @@ func TestWrapWithCastAsTypesClasses(t *testing.T) { ctx := createContext(t) durationColumn0 := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} - durationColumn0.RetType.Decimal = int(types.DefaultFsp) + durationColumn0.RetType.Decimal = types.DefaultFsp durationColumn3 := &Column{RetType: types.NewFieldType(mysql.TypeDuration), Index: 0} durationColumn3.RetType.Decimal = 3 cases := []struct { @@ -1420,6 +1420,9 @@ func TestWrapWithCastAsString(t *testing.T) { require.Equal(t, c.ret, res) } } + + expr := BuildCastFunction(ctx, &Constant{RetType: types.NewFieldType(mysql.TypeEnum)}, types.NewFieldType(mysql.TypeVarString)) + require.NotContains(t, expr.String(), "to_binary") } func TestWrapWithCastAsJSON(t *testing.T) { @@ -1495,3 +1498,79 @@ func TestCastStringAsDecimalSigWithUnsignedFlagInUnion(t *testing.T) { require.Equal(t, 0, res.Compare(c.res)) } } + +func TestCastConstAsDecimalFieldType(t *testing.T) { + type testCase struct { + input *Constant + resultFlen int + resultDecimal int + } + allTestCase := []testCase{ + // test int + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(0)}, 1, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(1)}, 1, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-1)}, 1, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(11111)}, 5, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-11111)}, 5, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(1111111111)}, 10, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-1111111111)}, 10, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(111111111111111)}, 15, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-111111111111111)}, 15, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(9223372036854775807)}, 19, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong}, Value: types.NewIntDatum(-9223372036854775808)}, 19, 0}, + // test uint + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(0)}, 1, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(1)}, 1, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(11111)}, 5, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(1111111111)}, 10, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(111111111111111)}, 15, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(9223372036854775807)}, 19, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag}, Value: types.NewUintDatum(18446744073709551615)}, 20, 0}, + // test decimal, use origin fieldType + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 10, Decimal: 5}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 10, 5}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 2, Decimal: 1}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("1"))}, 2, 1}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeNewDecimal, Flen: 30, Decimal: 0}, Value: types.NewDecimalDatum(types.NewDecFromStringForTest("12345"))}, 30, 0}, + // test real + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1.234)}, 4, 3}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1.23456789)}, 9, 8}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(-1234567890.123456789)}, 17, 7}, // float precision lost + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(-1234567890.1234567890123456789)}, 17, 7}, // float precision lost + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e10)}, 11, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e20)}, 21, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e40)}, 41, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e60)}, 61, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e80)}, 65, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-10)}, 10, 10}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-20)}, 20, 20}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDouble, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewFloat64Datum(1e-40)}, 40, 30}, + // test string + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.456")}, 6, 3}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.4560")}, 7, 4}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123.456000000")}, 12, 9}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("123abcde")}, 3, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("1e80")}, 65, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("1e-40")}, 40, 30}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("-1234567890.123456789")}, 19, 9}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}, Value: types.NewStringDatum("-1234567890.1234567890123456789")}, 29, 19}, + // test time + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 3))}, 9, 3}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 6))}, 12, 6}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDuration, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewDurationDatum(types.NewDuration(10, 10, 10, 110, 0))}, 6, 0}, + // test timestamp + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 14, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 17, 3}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeTimestamp, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeTimestamp, 0))}, 20, 6}, + // test datetime + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 14, 0}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 3}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 17, 3}, + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDatetime, Flen: types.UnspecifiedLength, Decimal: 6}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDatetime, 0))}, 20, 6}, + // test date + {&Constant{RetType: &types.FieldType{Tp: mysql.TypeDate, Flen: types.UnspecifiedLength, Decimal: 0}, Value: types.NewTimeDatum(types.NewTime(types.FromDate(2020, 10, 10, 10, 10, 10, 110), mysql.TypeDate, 0))}, 8, 0}, + } + ctx := createContext(t) + for _, tc := range allTestCase { + expr := WrapWithCastAsDecimal(ctx, tc.input) + require.Equal(t, tc.resultFlen, expr.GetType().Flen) + require.Equal(t, tc.resultDecimal, expr.GetType().Decimal) + } +} diff --git a/expression/builtin_cast_vec.go b/expression/builtin_cast_vec.go index 95609069dcba6..dbaf5c27d3ddf 100644 --- a/expression/builtin_cast_vec.go +++ b/expression/builtin_cast_vec.go @@ -44,7 +44,7 @@ func (b *builtinCastIntAsDurationSig) vecEvalDuration(input *chunk.Chunk, result if result.IsNull(i) { continue } - dur, err := types.NumberToDuration(i64s[i], int8(b.tp.Decimal)) + dur, err := types.NumberToDuration(i64s[i], b.tp.Decimal) if err != nil { if types.ErrOverflow.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, err) @@ -335,7 +335,7 @@ func (b *builtinCastDurationAsIntSig) vecEvalInt(input *chunk.Chunk, result *chu i64s := result.Int64s() var duration types.Duration ds := buf.GoDurations() - fsp := int8(b.args[0].GetType().Decimal) + fsp := b.args[0].GetType().Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -376,7 +376,7 @@ func (b *builtinCastIntAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk. times := result.Times() i64s := buf.Int64s() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal var tm types.Time for i := 0; i < n; i++ { @@ -483,7 +483,7 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk result.MergeNulls(buf) times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -529,7 +529,7 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times := result.Times() f64s := buf.Float64s() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if buf.IsNull(i) { continue @@ -608,7 +608,7 @@ func (b *builtinCastDurationAsTimeSig) vecEvalTime(input *chunk.Chunk, result *c ds := buf.GoDurations() times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -939,7 +939,7 @@ func (b *builtinCastStringAsDurationSig) vecEvalDuration(input *chunk.Chunk, res if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, buf.GetString(i), int8(b.tp.Decimal)) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, buf.GetString(i), b.tp.Decimal) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -977,8 +977,8 @@ func (b *builtinCastDurationAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, res var duration types.Duration ds := buf.GoDurations() sc := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.args[0].GetType().Decimal) - if fsp, err = types.CheckFsp(int(fsp)); err != nil { + fsp := b.args[0].GetType().Decimal + if fsp, err = types.CheckFsp(fsp); err != nil { return err } for i := 0; i < n; i++ { @@ -1141,8 +1141,8 @@ func (b *builtinCastDurationAsRealSig) vecEvalReal(input *chunk.Chunk, result *c f64s := result.Float64s() var duration types.Duration - fsp := int8(b.args[0].GetType().Decimal) - if fsp, err = types.CheckFsp(int(fsp)); err != nil { + fsp := b.args[0].GetType().Decimal + if fsp, err = types.CheckFsp(fsp); err != nil { return err } ds := buf.GoDurations() @@ -1213,7 +1213,7 @@ func (b *builtinCastRealAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(f64s[i], 'f', -1, 64), int8(b.tp.Decimal)) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, strconv.FormatFloat(f64s[i], 'f', -1, 64), b.tp.Decimal) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -1257,7 +1257,7 @@ func (b *builtinCastTimeAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if err != nil { return err } - d, err = d.RoundFrac(int8(b.tp.Decimal), b.ctx.GetSessionVars().Location()) + d, err = d.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) if err != nil { return err } @@ -1286,7 +1286,7 @@ func (b *builtinCastDurationAsDurationSig) vecEvalDuration(input *chunk.Chunk, r continue } dur.Duration = v - rd, err = dur.RoundFrac(int8(b.tp.Decimal), b.ctx.GetSessionVars().Location()) + rd, err = dur.RoundFrac(b.tp.Decimal, b.ctx.GetSessionVars().Location()) if err != nil { return err } @@ -1403,7 +1403,7 @@ func (b *builtinCastDecimalAsTimeSig) vecEvalTime(input *chunk.Chunk, result *ch times := result.Times() decimals := buf.Decimals() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if buf.IsNull(i) { continue @@ -1473,7 +1473,7 @@ func (b *builtinCastTimeAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times := result.Times() stmt := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -1687,7 +1687,7 @@ func (b *builtinCastStringAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chu result.MergeNulls(buf) times := result.Times() stmtCtx := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -1700,6 +1700,14 @@ func (b *builtinCastStringAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chu result.SetNull(i, true) continue } + if tm.IsZero() && b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { + err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, tm.String())) + if err != nil { + return err + } + result.SetNull(i, true) + continue + } times[i] = tm if b.tp.Tp == mysql.TypeDate { // Truncate hh:mm:ss part if the type is Date. @@ -1735,7 +1743,7 @@ func (b *builtinCastDecimalAsIntSig) vecEvalInt(input *chunk.Chunk, result *chun // Round is needed for both unsigned and signed. to := d64s[i] - err = d64s[i].Round(&to, 0, types.ModeHalfEven) + err = d64s[i].Round(&to, 0, types.ModeHalfUp) if err != nil { return err } @@ -1785,7 +1793,7 @@ func (b *builtinCastDecimalAsDurationSig) vecEvalDuration(input *chunk.Chunk, re if result.IsNull(i) { continue } - dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(args[i].ToString()), int8(b.tp.Decimal)) + dur, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, string(args[i].ToString()), b.tp.Decimal) if err != nil { if types.ErrTruncatedWrongVal.Equal(err) { err = b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) @@ -1872,7 +1880,7 @@ func (b *builtinCastJSONAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul if err != nil { return nil } - dur, err = types.ParseDuration(ctx, s, int8(b.tp.Decimal)) + dur, err = types.ParseDuration(ctx, s, b.tp.Decimal) if types.ErrTruncatedWrongVal.Equal(err) { err = ctx.HandleTruncate(err) } diff --git a/expression/builtin_cast_vec_test.go b/expression/builtin_cast_vec_test.go index 5e647be3777dd..20e6395537901 100644 --- a/expression/builtin_cast_vec_test.go +++ b/expression/builtin_cast_vec_test.go @@ -110,7 +110,7 @@ var vecBuiltinCastCases = map[string][]vecExprBenchCase{ type dateTimeGenerWithFsp struct { defaultGener - fsp int8 + fsp int } func (g *dateTimeGenerWithFsp) gen() interface{} { diff --git a/expression/builtin_compare.go b/expression/builtin_compare.go index 609ee26dc09e1..7cf894b966669 100644 --- a/expression/builtin_compare.go +++ b/expression/builtin_compare.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/tidb/parser/opcode" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" @@ -416,10 +417,33 @@ func ResolveType4Between(args [3]Expression) types.EvalType { return cmpTp } +// GLCmpStringMode represents Greatest/Least interal string comparison mode +type GLCmpStringMode uint8 + +const ( + // GLCmpStringDirectly Greatest and Least function compares string directly + GLCmpStringDirectly GLCmpStringMode = iota + // GLCmpStringAsDate Greatest/Least function compares string as 'yyyy-mm-dd' format + GLCmpStringAsDate + // GLCmpStringAsDatetime Greatest/Least function compares string as 'yyyy-mm-dd hh:mm:ss' format + GLCmpStringAsDatetime +) + +// GLRetTimeType represents Greatest/Least return time type +type GLRetTimeType uint8 + +const ( + // GLRetNoneTemporal Greatest/Least function returns non temporal time + GLRetNoneTemporal GLRetTimeType = iota + // GLRetDate Greatest/Least function returns date type, 'yyyy-mm-dd' + GLRetDate + // GLRetDatetime Greatest/Least function returns datetime type, 'yyyy-mm-dd hh:mm:ss' + GLRetDatetime +) + // resolveType4Extremum gets compare type for GREATEST and LEAST and BETWEEN (mainly for datetime). -func resolveType4Extremum(args []Expression) (_ types.EvalType, cmpStringAsDatetime bool) { +func resolveType4Extremum(args []Expression) (_ *types.FieldType, fieldTimeType GLRetTimeType, cmpStringMode GLCmpStringMode) { aggType := aggregateType(args) - var temporalItem *types.FieldType if aggType.EvalType().IsStringKind() { for i := range args { @@ -432,13 +456,22 @@ func resolveType4Extremum(args []Expression) (_ types.EvalType, cmpStringAsDatet } } - if !types.IsTypeTemporal(aggType.Tp) && temporalItem != nil { - aggType.Tp = temporalItem.Tp - cmpStringAsDatetime = true + if !types.IsTypeTemporal(aggType.Tp) && temporalItem != nil && types.IsTemporalWithDate(temporalItem.Tp) { + if temporalItem.Tp == mysql.TypeDate { + cmpStringMode = GLCmpStringAsDate + } else { + cmpStringMode = GLCmpStringAsDatetime + } } // TODO: String charset, collation checking are needed. } - return aggType.EvalType(), cmpStringAsDatetime + var timeType = GLRetNoneTemporal + if aggType.Tp == mysql.TypeDate { + timeType = GLRetDate + } else if aggType.Tp == mysql.TypeDatetime || aggType.Tp == mysql.TypeTimestamp { + timeType = GLRetDatetime + } + return aggType, timeType, cmpStringMode } // unsupportedJSONComparison reports warnings while there is a JSON type in least/greatest function's arguments @@ -460,32 +493,28 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre if err = c.verifyArgs(args); err != nil { return nil, err } - tp, cmpStringAsDatetime := resolveType4Extremum(args) - if cmpStringAsDatetime { + resFieldType, fieldTimeType, cmpStringMode := resolveType4Extremum(args) + resTp := resFieldType.EvalType() + argTp := resTp + if cmpStringMode != GLCmpStringDirectly { // Args are temporal and string mixed, we cast all args as string and parse it to temporal mannualy to compare. - tp = types.ETString - } else if tp == types.ETJson { + argTp = types.ETString + } else if resTp == types.ETJson { unsupportedJSONComparison(ctx, args) - tp = types.ETString + argTp = types.ETString + resTp = types.ETString } argTps := make([]types.EvalType, len(args)) for i := range args { - argTps[i] = tp + argTps[i] = argTp } - bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, tp, argTps...) + bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, resTp, argTps...) if err != nil { return nil, err } - switch tp { + switch argTp { case types.ETInt: - // adjust unsigned flag - greastInitUnsignedFlag := false - if isEqualsInitUnsignedFlag(greastInitUnsignedFlag, args) { - bf.tp.Flag &= ^mysql.UnsignedFlag - } else { - bf.tp.Flag |= mysql.UnsignedFlag - } - + bf.tp.Flag |= resFieldType.Flag sig = &builtinGreatestIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_GreatestInt) case types.ETReal: @@ -495,8 +524,11 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre sig = &builtinGreatestDecimalSig{bf} sig.setPbCode(tipb.ScalarFuncSig_GreatestDecimal) case types.ETString: - if cmpStringAsDatetime { - sig = &builtinGreatestCmpStringAsTimeSig{bf} + if cmpStringMode == GLCmpStringAsDate { + sig = &builtinGreatestCmpStringAsTimeSig{bf, true} + sig.setPbCode(tipb.ScalarFuncSig_GreatestCmpStringAsDate) + } else if cmpStringMode == GLCmpStringAsDatetime { + sig = &builtinGreatestCmpStringAsTimeSig{bf, false} sig.setPbCode(tipb.ScalarFuncSig_GreatestCmpStringAsTime) } else { sig = &builtinGreatestStringSig{bf} @@ -506,8 +538,13 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre sig = &builtinGreatestDurationSig{bf} sig.setPbCode(tipb.ScalarFuncSig_GreatestDuration) case types.ETDatetime, types.ETTimestamp: - sig = &builtinGreatestTimeSig{bf} - sig.setPbCode(tipb.ScalarFuncSig_GreatestTime) + if fieldTimeType == GLRetDate { + sig = &builtinGreatestTimeSig{bf, true} + sig.setPbCode(tipb.ScalarFuncSig_GreatestDate) + } else { + sig = &builtinGreatestTimeSig{bf, false} + sig.setPbCode(tipb.ScalarFuncSig_GreatestTime) + } } sig.getRetTp().Flen, sig.getRetTp().Decimal = fixFlenAndDecimalForGreatestAndLeast(args) return sig, nil @@ -648,11 +685,13 @@ func (b *builtinGreatestStringSig) evalString(row chunk.Row) (max string, isNull type builtinGreatestCmpStringAsTimeSig struct { baseBuiltinFunc + cmpAsDate bool } func (b *builtinGreatestCmpStringAsTimeSig) Clone() builtinFunc { newSig := &builtinGreatestCmpStringAsTimeSig{} newSig.cloneFrom(&b.baseBuiltinFunc) + newSig.cmpAsDate = b.cmpAsDate return newSig } @@ -665,13 +704,9 @@ func (b *builtinGreatestCmpStringAsTimeSig) evalString(row chunk.Row) (strRes st if isNull || err != nil { return "", true, err } - t, err := types.ParseDatetime(sc, v) + v, err = doTimeConversionForGL(b.cmpAsDate, b.ctx, sc, v) if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return v, true, err - } - } else { - v = t.String() + return v, true, err } // In MySQL, if the compare result is zero, than we will try to use the string comparison result if i == 0 || strings.Compare(v, strRes) > 0 { @@ -681,13 +716,39 @@ func (b *builtinGreatestCmpStringAsTimeSig) evalString(row chunk.Row) (strRes st return strRes, false, nil } +func doTimeConversionForGL(cmpAsDate bool, ctx sessionctx.Context, sc *stmtctx.StatementContext, strVal string) (string, error) { + var t types.Time + var err error + if cmpAsDate { + t, err = types.ParseDate(sc, strVal) + if err == nil { + t, err = t.Convert(sc, mysql.TypeDate) + } + } else { + t, err = types.ParseDatetime(sc, strVal) + if err == nil { + t, err = t.Convert(sc, mysql.TypeDatetime) + } + } + if err != nil { + if err = handleInvalidTimeError(ctx, err); err != nil { + return "", err + } + } else { + strVal = t.String() + } + return strVal, nil +} + type builtinGreatestTimeSig struct { baseBuiltinFunc + cmpAsDate bool } func (b *builtinGreatestTimeSig) Clone() builtinFunc { newSig := &builtinGreatestTimeSig{} newSig.cloneFrom(&b.baseBuiltinFunc) + newSig.cmpAsDate = b.cmpAsDate return newSig } @@ -701,6 +762,12 @@ func (b *builtinGreatestTimeSig) evalTime(row chunk.Row) (res types.Time, isNull res = v } } + // Convert ETType Time value to MySQL actual type, distinguish date and datetime + sc := b.ctx.GetSessionVars().StmtCtx + resTimeTp := getAccurateTimeTypeForGLRet(b.cmpAsDate) + if res, err = res.Convert(sc, resTimeTp); err != nil { + return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) + } return res, false, nil } @@ -735,32 +802,28 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi if err = c.verifyArgs(args); err != nil { return nil, err } - tp, cmpStringAsDatetime := resolveType4Extremum(args) - if cmpStringAsDatetime { + resFieldType, fieldTimeType, cmpStringMode := resolveType4Extremum(args) + resTp := resFieldType.EvalType() + argTp := resTp + if cmpStringMode != GLCmpStringDirectly { // Args are temporal and string mixed, we cast all args as string and parse it to temporal mannualy to compare. - tp = types.ETString - } else if tp == types.ETJson { + argTp = types.ETString + } else if resTp == types.ETJson { unsupportedJSONComparison(ctx, args) - tp = types.ETString + argTp = types.ETString + resTp = types.ETString } argTps := make([]types.EvalType, len(args)) for i := range args { - argTps[i] = tp + argTps[i] = argTp } - bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, tp, argTps...) + bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, resTp, argTps...) if err != nil { return nil, err } - switch tp { + switch argTp { case types.ETInt: - // adjust unsigned flag - leastInitUnsignedFlag := true - if isEqualsInitUnsignedFlag(leastInitUnsignedFlag, args) { - bf.tp.Flag |= mysql.UnsignedFlag - } else { - bf.tp.Flag &= ^mysql.UnsignedFlag - } - + bf.tp.Flag |= resFieldType.Flag sig = &builtinLeastIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_LeastInt) case types.ETReal: @@ -770,8 +833,11 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi sig = &builtinLeastDecimalSig{bf} sig.setPbCode(tipb.ScalarFuncSig_LeastDecimal) case types.ETString: - if cmpStringAsDatetime { - sig = &builtinLeastCmpStringAsTimeSig{bf} + if cmpStringMode == GLCmpStringAsDate { + sig = &builtinLeastCmpStringAsTimeSig{bf, true} + sig.setPbCode(tipb.ScalarFuncSig_LeastCmpStringAsDate) + } else if cmpStringMode == GLCmpStringAsDatetime { + sig = &builtinLeastCmpStringAsTimeSig{bf, false} sig.setPbCode(tipb.ScalarFuncSig_LeastCmpStringAsTime) } else { sig = &builtinLeastStringSig{bf} @@ -781,8 +847,13 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi sig = &builtinLeastDurationSig{bf} sig.setPbCode(tipb.ScalarFuncSig_LeastDuration) case types.ETDatetime, types.ETTimestamp: - sig = &builtinLeastTimeSig{bf} - sig.setPbCode(tipb.ScalarFuncSig_LeastTime) + if fieldTimeType == GLRetDate { + sig = &builtinLeastTimeSig{bf, true} + sig.setPbCode(tipb.ScalarFuncSig_LeastDate) + } else { + sig = &builtinLeastTimeSig{bf, false} + sig.setPbCode(tipb.ScalarFuncSig_LeastTime) + } } sig.getRetTp().Flen, sig.getRetTp().Decimal = fixFlenAndDecimalForGreatestAndLeast(args) return sig, nil @@ -910,11 +981,13 @@ func (b *builtinLeastStringSig) evalString(row chunk.Row) (min string, isNull bo type builtinLeastCmpStringAsTimeSig struct { baseBuiltinFunc + cmpAsDate bool } func (b *builtinLeastCmpStringAsTimeSig) Clone() builtinFunc { newSig := &builtinLeastCmpStringAsTimeSig{} newSig.cloneFrom(&b.baseBuiltinFunc) + newSig.cmpAsDate = b.cmpAsDate return newSig } @@ -927,13 +1000,9 @@ func (b *builtinLeastCmpStringAsTimeSig) evalString(row chunk.Row) (strRes strin if isNull || err != nil { return "", true, err } - t, err := types.ParseDatetime(sc, v) + v, err = doTimeConversionForGL(b.cmpAsDate, b.ctx, sc, v) if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return v, true, err - } - } else { - v = t.String() + return v, true, err } if i == 0 || strings.Compare(v, strRes) < 0 { strRes = v @@ -945,11 +1014,13 @@ func (b *builtinLeastCmpStringAsTimeSig) evalString(row chunk.Row) (strRes strin type builtinLeastTimeSig struct { baseBuiltinFunc + cmpAsDate bool } func (b *builtinLeastTimeSig) Clone() builtinFunc { newSig := &builtinLeastTimeSig{} newSig.cloneFrom(&b.baseBuiltinFunc) + newSig.cmpAsDate = b.cmpAsDate return newSig } @@ -963,9 +1034,25 @@ func (b *builtinLeastTimeSig) evalTime(row chunk.Row) (res types.Time, isNull bo res = v } } + // Convert ETType Time value to MySQL actual type, distinguish date and datetime + sc := b.ctx.GetSessionVars().StmtCtx + resTimeTp := getAccurateTimeTypeForGLRet(b.cmpAsDate) + if res, err = res.Convert(sc, resTimeTp); err != nil { + return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) + } return res, false, nil } +func getAccurateTimeTypeForGLRet(cmpAsDate bool) byte { + var resTimeTp byte + if cmpAsDate { + resTimeTp = mysql.TypeDate + } else { + resTimeTp = mysql.TypeDatetime + } + return resTimeTp +} + type builtinLeastDurationSig struct { baseBuiltinFunc } @@ -2896,15 +2983,3 @@ func CompareJSON(sctx sessionctx.Context, lhsArg, rhsArg Expression, lhsRow, rhs } return int64(json.CompareBinary(arg0, arg1)), false, nil } - -// isEqualsInitUnsignedFlag can adjust unsigned flag for greatest/least function. -// For greatest, returns unsigned result if there is at least one argument is unsigned. -// For least, returns signed result if there is at least one argument is signed. -func isEqualsInitUnsignedFlag(initUnsigned bool, args []Expression) bool { - for _, arg := range args { - if initUnsigned != mysql.HasUnsignedFlag(arg.GetType().Flag) { - return false - } - } - return true -} diff --git a/expression/builtin_compare_test.go b/expression/builtin_compare_test.go index edc4b7e7ad056..cd204d25a2459 100644 --- a/expression/builtin_compare_test.go +++ b/expression/builtin_compare_test.go @@ -351,6 +351,10 @@ func TestGreatestLeastFunc(t *testing.T) { []interface{}{905969664.0, 4556, "1990-06-16 17:22:56.005534"}, "905969664", "1990-06-16 17:22:56.005534", false, false, }, + { + []interface{}{105969664.0, 120000, types.Duration{Duration: 20*time.Hour + 0*time.Minute + 0*time.Second}}, + "20:00:00", "105969664", false, false, + }, } { f0, err := newFunctionForTest(ctx, ast.Greatest, primitiveValsToConstants(ctx, test.args)...) require.NoError(t, err) diff --git a/expression/builtin_compare_vec.go b/expression/builtin_compare_vec.go index e3bf42864fd94..35663bb8418d6 100644 --- a/expression/builtin_compare_vec.go +++ b/expression/builtin_compare_vec.go @@ -652,14 +652,10 @@ func (b *builtinGreatestCmpStringAsTimeSig) vecEvalString(input *chunk.Chunk, re // NOTE: can't use Column.GetString because it returns an unsafe string, copy the row instead. argTimeStr := string(result.GetBytes(i)) - - argTime, err := types.ParseDatetime(sc, argTimeStr) + var err error + argTimeStr, err = doTimeConversionForGL(b.cmpAsDate, b.ctx, sc, argTimeStr) if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return err - } - } else { - argTimeStr = argTime.String() + return err } if j == 0 || strings.Compare(argTimeStr, dstStrings[i]) > 0 { dstStrings[i] = argTimeStr @@ -737,14 +733,10 @@ func (b *builtinLeastCmpStringAsTimeSig) vecEvalString(input *chunk.Chunk, resul // NOTE: can't use Column.GetString because it returns an unsafe string, copy the row instead. argTimeStr := string(result.GetBytes(i)) - - argTime, err := types.ParseDatetime(sc, argTimeStr) + var err error + argTimeStr, err = doTimeConversionForGL(b.cmpAsDate, b.ctx, sc, argTimeStr) if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return err - } - } else { - argTimeStr = argTime.String() + return err } if j == 0 || strings.Compare(argTimeStr, dstStrings[i]) < 0 { dstStrings[i] = argTimeStr @@ -845,6 +837,15 @@ func (b *builtinGreatestTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk.C } } } + sc := b.ctx.GetSessionVars().StmtCtx + resTimeTp := getAccurateTimeTypeForGLRet(b.cmpAsDate) + for rowIdx := 0; rowIdx < n; rowIdx++ { + resTimes := result.Times() + resTimes[rowIdx], err = resTimes[rowIdx].Convert(sc, resTimeTp) + if err != nil { + return err + } + } return nil } @@ -877,6 +878,15 @@ func (b *builtinLeastTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk.Colu } } } + sc := b.ctx.GetSessionVars().StmtCtx + resTimeTp := getAccurateTimeTypeForGLRet(b.cmpAsDate) + for rowIdx := 0; rowIdx < n; rowIdx++ { + resTimes := result.Times() + resTimes[rowIdx], err = resTimes[rowIdx].Convert(sc, resTimeTp) + if err != nil { + return err + } + } return nil } diff --git a/expression/builtin_compare_vec_generated.go b/expression/builtin_compare_vec_generated.go index e9615296b24c1..f93ba43005e63 100644 --- a/expression/builtin_compare_vec_generated.go +++ b/expression/builtin_compare_vec_generated.go @@ -51,11 +51,7 @@ func (b *builtinLTRealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -93,11 +89,7 @@ func (b *builtinLTDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -133,11 +125,7 @@ func (b *builtinLTStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -175,11 +163,7 @@ func (b *builtinLTTimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -217,11 +201,7 @@ func (b *builtinLTDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -257,11 +237,7 @@ func (b *builtinLTJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val < 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val < 0) } return nil } @@ -299,11 +275,7 @@ func (b *builtinLERealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -341,11 +313,7 @@ func (b *builtinLEDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -381,11 +349,7 @@ func (b *builtinLEStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -423,11 +387,7 @@ func (b *builtinLETimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -465,11 +425,7 @@ func (b *builtinLEDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -505,11 +461,7 @@ func (b *builtinLEJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val <= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val <= 0) } return nil } @@ -547,11 +499,7 @@ func (b *builtinGTRealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -589,11 +537,7 @@ func (b *builtinGTDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -629,11 +573,7 @@ func (b *builtinGTStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -671,11 +611,7 @@ func (b *builtinGTTimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -713,11 +649,7 @@ func (b *builtinGTDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -753,11 +685,7 @@ func (b *builtinGTJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val > 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val > 0) } return nil } @@ -795,11 +723,7 @@ func (b *builtinGERealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -837,11 +761,7 @@ func (b *builtinGEDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -877,11 +797,7 @@ func (b *builtinGEStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -919,11 +835,7 @@ func (b *builtinGETimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -961,11 +873,7 @@ func (b *builtinGEDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -1001,11 +909,7 @@ func (b *builtinGEJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val >= 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val >= 0) } return nil } @@ -1043,11 +947,7 @@ func (b *builtinEQRealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1085,11 +985,7 @@ func (b *builtinEQDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1125,11 +1021,7 @@ func (b *builtinEQStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1167,11 +1059,7 @@ func (b *builtinEQTimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1209,11 +1097,7 @@ func (b *builtinEQDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1249,11 +1133,7 @@ func (b *builtinEQJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val == 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val == 0) } return nil } @@ -1291,11 +1171,7 @@ func (b *builtinNERealSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := types.CompareFloat64(arg0[i], arg1[i]) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } @@ -1333,11 +1209,7 @@ func (b *builtinNEDecimalSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } val := arg0[i].Compare(&arg1[i]) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } @@ -1373,11 +1245,7 @@ func (b *builtinNEStringSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column continue } val := types.CompareString(buf0.GetString(i), buf1.GetString(i), b.collation) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } @@ -1415,11 +1283,7 @@ func (b *builtinNETimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := arg0[i].Compare(arg1[i]) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } @@ -1457,11 +1321,7 @@ func (b *builtinNEDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu continue } val := types.CompareDuration(arg0[i], arg1[i]) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } @@ -1497,11 +1357,7 @@ func (b *builtinNEJSONSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } val := json.CompareBinary(buf0.GetJSON(i), buf1.GetJSON(i)) - if val != 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val != 0) } return nil } diff --git a/expression/builtin_control.go b/expression/builtin_control.go index 51162c6a6ccc5..99ff130e39b85 100644 --- a/expression/builtin_control.go +++ b/expression/builtin_control.go @@ -16,7 +16,6 @@ package expression import ( "github.com/cznic/mathutil" - "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" @@ -172,7 +171,7 @@ func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expre l := len(args) // Fill in each 'THEN' clause parameter type. fieldTps := make([]*types.FieldType, 0, (l+1)/2) - decimal, flen, isBinaryStr, isBinaryFlag := args[1].GetType().Decimal, 0, false, false + decimal, flen, isBinaryFlag := args[1].GetType().Decimal, 0, false for i := 1; i < l; i += 2 { fieldTps = append(fieldTps, args[i].GetType()) decimal = mathutil.Max(decimal, args[i].GetType().Decimal) @@ -181,7 +180,6 @@ func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expre } else if flen != -1 { flen = mathutil.Max(flen, args[i].GetType().Flen) } - isBinaryStr = isBinaryStr || types.IsBinaryStr(args[i].GetType()) isBinaryFlag = isBinaryFlag || !types.IsNonBinaryStr(args[i].GetType()) } if l%2 == 1 { @@ -192,7 +190,6 @@ func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expre } else if flen != -1 { flen = mathutil.Max(flen, args[l-1].GetType().Flen) } - isBinaryStr = isBinaryStr || types.IsBinaryStr(args[l-1].GetType()) isBinaryFlag = isBinaryFlag || !types.IsNonBinaryStr(args[l-1].GetType()) } @@ -207,16 +204,6 @@ func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expre } fieldTp.Decimal, fieldTp.Flen = decimal, flen types.TryToFixFlenOfDatetime(fieldTp) - if fieldTp.EvalType().IsStringKind() && !isBinaryStr { - fieldTp.Charset, fieldTp.Collate = DeriveCollationFromExprs(ctx, args...) - if fieldTp.Charset == charset.CharsetBin && fieldTp.Collate == charset.CollationBin { - // When args are Json and Numerical type(eg. Int), the fieldTp is String. - // Both their charset/collation is binary, but the String need a default charset/collation. - fieldTp.Charset, fieldTp.Collate = charset.GetDefaultCharsetAndCollate() - } - } else { - fieldTp.Charset, fieldTp.Collate = charset.CharsetBin, charset.CollationBin - } if isBinaryFlag { fieldTp.Flag |= mysql.BinaryFlag } @@ -239,6 +226,7 @@ func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expre if err != nil { return nil, err } + fieldTp.Charset, fieldTp.Collate = bf.tp.Charset, bf.tp.Collate bf.tp = fieldTp if fieldTp.Tp == mysql.TypeEnum || fieldTp.Tp == mysql.TypeSet { switch tp { diff --git a/expression/builtin_control_test.go b/expression/builtin_control_test.go index c888e7f4e8dc6..bfbbb3d06cd04 100644 --- a/expression/builtin_control_test.go +++ b/expression/builtin_control_test.go @@ -20,7 +20,7 @@ import ( "time" "github.com/pingcap/tidb/parser/ast" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/stretchr/testify/require" @@ -50,7 +50,7 @@ func TestCaseWhen(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.Ret), d) + testutil.DatumEqual(t, types.NewDatum(tt.Ret), d) } f, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(errors.New("can't convert string to bool"), 1, true))) require.NoError(t, err) @@ -96,7 +96,7 @@ func TestIf(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.Ret), d) + testutil.DatumEqual(t, types.NewDatum(tt.Ret), d) } f, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(errors.New("must error"), 1, 2))) require.NoError(t, err) diff --git a/expression/builtin_convert_charset.go b/expression/builtin_convert_charset.go index fc709cc7c61f0..c21cd32c9205b 100644 --- a/expression/builtin_convert_charset.go +++ b/expression/builtin_convert_charset.go @@ -15,8 +15,10 @@ package expression import ( + "bytes" "fmt" - "unicode/utf8" + "strings" + "unicode" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/ast" @@ -27,6 +29,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/dbterror" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tipb/go-tipb" ) @@ -92,9 +95,9 @@ func (b *builtinInternalToBinarySig) evalString(row chunk.Row) (res string, isNu return res, isNull, err } tp := b.args[0].GetType() - enc := charset.NewEncoding(tp.Charset) - res, err = enc.EncodeString(val) - return res, false, err + enc := charset.FindEncoding(tp.Charset) + ret, err := enc.Transform(nil, hack.Slice(val), charset.OpEncode) + return string(ret), false, err } func (b *builtinInternalToBinarySig) vectorized() bool { @@ -111,19 +114,19 @@ func (b *builtinInternalToBinarySig) vecEvalString(input *chunk.Chunk, result *c if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { return err } - enc := charset.NewEncoding(b.args[0].GetType().Charset) + enc := charset.FindEncoding(b.args[0].GetType().Charset) result.ReserveString(n) - var encodedBuf []byte + encodedBuf := &bytes.Buffer{} for i := 0; i < n; i++ { if buf.IsNull(i) { result.AppendNull() continue } - strBytes, err := enc.Encode(encodedBuf, buf.GetBytes(i)) + val, err := enc.Transform(encodedBuf, buf.GetBytes(i), charset.OpEncode) if err != nil { return err } - result.AppendBytes(strBytes) + result.AppendBytes(val) } return nil } @@ -170,9 +173,14 @@ func (b *builtinInternalFromBinarySig) evalString(row chunk.Row) (res string, is if isNull || err != nil { return val, isNull, err } - transferString := b.getTransferFunc() - tBytes, err := transferString([]byte(val)) - return string(tBytes), false, err + enc := charset.FindEncoding(b.tp.Charset) + valBytes := hack.Slice(val) + ret, err := enc.Transform(nil, valBytes, charset.OpDecode) + if err != nil { + strHex := formatInvalidChars(valBytes) + err = errCannotConvertString.GenWithStackByArgs(strHex, charset.CharsetBin, b.tp.Charset) + } + return string(ret), false, err } func (b *builtinInternalFromBinarySig) vectorized() bool { @@ -189,45 +197,25 @@ func (b *builtinInternalFromBinarySig) vecEvalString(input *chunk.Chunk, result if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { return err } - transferString := b.getTransferFunc() + enc := charset.FindEncoding(b.tp.Charset) + encodedBuf := &bytes.Buffer{} result.ReserveString(n) for i := 0; i < n; i++ { if buf.IsNull(i) { result.AppendNull() continue } - str, err := transferString(buf.GetBytes(i)) + str := buf.GetBytes(i) + val, err := enc.Transform(encodedBuf, str, charset.OpDecode) if err != nil { - return err + strHex := formatInvalidChars(str) + return errCannotConvertString.GenWithStackByArgs(strHex, charset.CharsetBin, b.tp.Charset) } - result.AppendBytes(str) + result.AppendBytes(val) } return nil } -func (b *builtinInternalFromBinarySig) getTransferFunc() func([]byte) ([]byte, error) { - var transferString func([]byte) ([]byte, error) - if b.tp.Charset == charset.CharsetUTF8MB4 || b.tp.Charset == charset.CharsetUTF8 { - transferString = func(s []byte) ([]byte, error) { - if !utf8.Valid(s) { - return nil, errCannotConvertString.GenWithStackByArgs(fmt.Sprintf("%X", s), charset.CharsetBin, b.tp.Charset) - } - return s, nil - } - } else { - enc := charset.NewEncoding(b.tp.Charset) - var buf []byte - transferString = func(s []byte) ([]byte, error) { - str, err := enc.Decode(buf, s) - if err != nil { - return nil, errCannotConvertString.GenWithStackByArgs(fmt.Sprintf("%X", s), charset.CharsetBin, b.tp.Charset) - } - return str, nil - } - } - return transferString -} - // BuildToBinaryFunction builds to_binary function. func BuildToBinaryFunction(ctx sessionctx.Context, expr Expression) (res Expression) { fc := &tidbToBinaryFunctionClass{baseFunctionClass{InternalFuncToBinary, 1, 1}} @@ -258,26 +246,111 @@ func BuildFromBinaryFunction(ctx sessionctx.Context, expr Expression, tp *types. return FoldConstant(res) } +type funcProp int8 + +const ( + funcPropNone funcProp = iota + // The arguments of these functions are wrapped with to_binary(). + // For compatibility reason, legacy charsets arguments are not wrapped. + // Legacy charsets: utf8mb4, utf8, latin1, ascii, binary. + funcPropBinAware + // The arguments of these functions are wrapped with to_binary() or from_binary() according to + // the evaluated result charset and the argument charset. + // For binary argument && string result, wrap it with from_binary(). + // For string argument && binary result, wrap it with to_binary(). + funcPropAuto +) + +// convertActionMap collects from https://dev.mysql.com/doc/refman/8.0/en/string-functions.html. +var convertActionMap = map[funcProp][]string{ + funcPropNone: { + /* args != strings */ + ast.Bin, ast.CharFunc, ast.DateFormat, ast.Oct, ast.Space, + /* only 1 string arg, no implicit conversion */ + ast.CharLength, ast.CharacterLength, ast.FromBase64, ast.Lcase, ast.Left, ast.LoadFile, + ast.Lower, ast.LTrim, ast.Mid, ast.Ord, ast.Quote, ast.Repeat, ast.Reverse, ast.Right, + ast.RTrim, ast.Soundex, ast.Substr, ast.Substring, ast.Ucase, ast.Unhex, ast.Upper, ast.WeightString, + }, + funcPropBinAware: { + /* result is binary-aware */ + ast.ASCII, ast.BitLength, ast.Hex, ast.Length, ast.OctetLength, ast.ToBase64, + /* encrypt functions */ + ast.AesDecrypt, ast.Decode, ast.Encode, ast.PasswordFunc, ast.MD5, ast.SHA, ast.SHA1, + ast.SHA2, ast.Compress, ast.AesEncrypt, + }, + funcPropAuto: { + /* string functions */ ast.Concat, ast.ConcatWS, ast.ExportSet, ast.Field, ast.FindInSet, + ast.InsertFunc, ast.Instr, ast.Lpad, ast.Locate, ast.Lpad, ast.MakeSet, ast.Position, + ast.Replace, ast.Rpad, ast.SubstringIndex, ast.Trim, ast.Elt, + /* operators */ + ast.GE, ast.LE, ast.GT, ast.LT, ast.EQ, ast.NE, ast.NullEQ, ast.If, ast.Ifnull, ast.In, + ast.Case, ast.Cast, + /* string comparing */ + ast.Like, ast.Strcmp, + /* regex */ + ast.Regexp, + /* math */ + ast.CRC32, + }, +} + +var convertFuncsMap = map[string]funcProp{} + +func init() { + for k, fns := range convertActionMap { + for _, f := range fns { + convertFuncsMap[f] = k + } + } +} + // HandleBinaryLiteral wraps `expr` with to_binary or from_binary sig. func HandleBinaryLiteral(ctx sessionctx.Context, expr Expression, ec *ExprCollation, funcName string) Expression { - switch funcName { - case ast.Concat, ast.ConcatWS, ast.Lower, ast.Lcase, ast.Reverse, ast.Upper, ast.Ucase, ast.Quote, ast.Coalesce, - ast.Left, ast.Right, ast.Repeat, ast.Trim, ast.LTrim, ast.RTrim, ast.Substr, ast.SubstringIndex, ast.Replace, - ast.Substring, ast.Mid, ast.Translate, ast.InsertFunc, ast.Lpad, ast.Rpad, ast.Elt, ast.ExportSet, ast.MakeSet, - ast.FindInSet, ast.Regexp, ast.Field, ast.Locate, ast.Instr, ast.Position, ast.GE, ast.LE, ast.GT, ast.LT, ast.EQ, - ast.NE, ast.NullEQ, ast.Strcmp, ast.If, ast.Ifnull, ast.Like, ast.In, ast.DateFormat, ast.TimeFormat: - if ec.Charset == charset.CharsetBin && expr.GetType().Charset != charset.CharsetBin { + argChs, dstChs := expr.GetType().Charset, ec.Charset + switch convertFuncsMap[funcName] { + case funcPropNone: + return expr + case funcPropBinAware: + if isLegacyCharset(argChs) { + return expr + } + return BuildToBinaryFunction(ctx, expr) + case funcPropAuto: + if argChs != charset.CharsetBin && dstChs == charset.CharsetBin { + if isLegacyCharset(argChs) { + return expr + } return BuildToBinaryFunction(ctx, expr) - } else if ec.Charset != charset.CharsetBin && expr.GetType().Charset == charset.CharsetBin { + } else if argChs == charset.CharsetBin && dstChs != charset.CharsetBin { ft := expr.GetType().Clone() ft.Charset, ft.Collate = ec.Charset, ec.Collation return BuildFromBinaryFunction(ctx, expr, ft) } - case ast.Hex, ast.Length, ast.OctetLength, ast.ASCII, ast.ToBase64, ast.AesEncrypt, ast.AesDecrypt, ast.Decode, ast.Encode, - ast.PasswordFunc, ast.MD5, ast.SHA, ast.SHA1, ast.SHA2, ast.Compress: - if _, err := charset.GetDefaultCollationLegacy(expr.GetType().Charset); err != nil { - return BuildToBinaryFunction(ctx, expr) - } } return expr } + +func isLegacyCharset(chs string) bool { + switch chs { + case charset.CharsetUTF8, charset.CharsetUTF8MB4, charset.CharsetASCII, charset.CharsetLatin1, charset.CharsetBin: + return true + } + return false +} + +func formatInvalidChars(src []byte) string { + var sb strings.Builder + const maxBytesToShow = 5 + for i := 0; i < len(src); i++ { + if i > maxBytesToShow { + sb.WriteString("...") + break + } + if src[i] > unicode.MaxASCII { + sb.WriteString(fmt.Sprintf("\\x%X", src[i])) + } else { + sb.Write([]byte{src[i]}) + } + } + return sb.String() +} diff --git a/expression/builtin_encryption.go b/expression/builtin_encryption.go index 134b2c417591c..b66e16fe4f302 100644 --- a/expression/builtin_encryption.go +++ b/expression/builtin_encryption.go @@ -573,17 +573,17 @@ func (b *builtinRandomBytesSig) Clone() builtinFunc { // evalString evals RANDOM_BYTES(len). // See https://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html#function_random-bytes func (b *builtinRandomBytesSig) evalString(row chunk.Row) (string, bool, error) { - len, isNull, err := b.args[0].EvalInt(b.ctx, row) + val, isNull, err := b.args[0].EvalInt(b.ctx, row) if isNull || err != nil { return "", true, err } - if len < 1 || len > 1024 { + if val < 1 || val > 1024 { return "", false, types.ErrOverflow.GenWithStackByArgs("length", "random_bytes") } - buf := make([]byte, len) + buf := make([]byte, val) if n, err := rand.Read(buf); err != nil { return "", true, err - } else if int64(n) != len { + } else if int64(n) != val { return "", false, errors.New("fail to generate random bytes") } return string(buf), false, nil @@ -949,8 +949,7 @@ func (b *builtinUncompressedLengthSig) evalInt(row chunk.Row) (int64, bool, erro sc.AppendWarning(errZlibZData) return 0, false, nil } - len := binary.LittleEndian.Uint32([]byte(payload)[0:4]) - return int64(len), false, nil + return int64(binary.LittleEndian.Uint32([]byte(payload)[0:4])), false, nil } type validatePasswordStrengthFunctionClass struct { diff --git a/expression/builtin_encryption_test.go b/expression/builtin_encryption_test.go index 2dec9405f03db..bda56e7bc4bdb 100644 --- a/expression/builtin_encryption_test.go +++ b/expression/builtin_encryption_test.go @@ -16,6 +16,7 @@ package expression import ( "encoding/hex" + "fmt" "strings" "testing" @@ -91,9 +92,10 @@ func TestSQLEncode(t *testing.T) { d, err := f.Eval(chunk.Row{}) require.NoError(t, err) if test.origin != nil { - result, err := charset.NewEncoding(test.chs).EncodeString(test.origin.(string)) + enc := charset.FindEncoding(test.chs) + result, err := enc.Transform(nil, []byte(test.origin.(string)), charset.OpEncode) require.NoError(t, err) - require.Equal(t, types.NewCollationStringDatum(result, test.chs), d) + require.Equal(t, types.NewCollationStringDatum(string(result), test.chs), d) } else { result := types.NewDatum(test.origin) require.Equal(t, result.GetBytes(), d.GetBytes()) @@ -163,7 +165,8 @@ func TestAESEncrypt(t *testing.T) { testAmbiguousInput(t, ctx, ast.AesEncrypt) // Test GBK String - gbkStr, _ := charset.NewEncoding("gbk").EncodeString("你好") + enc := charset.FindEncoding("gbk") + gbkStr, _ := enc.Transform(nil, []byte("你好"), charset.OpEncode) gbkTests := []struct { mode string chs string @@ -188,19 +191,20 @@ func TestAESEncrypt(t *testing.T) { } for _, tt := range gbkTests { + msg := fmt.Sprintf("%v", tt) err := ctx.GetSessionVars().SetSystemVar(variable.CharacterSetConnection, tt.chs) - require.NoError(t, err) + require.NoError(t, err, msg) err = variable.SetSessionSystemVar(ctx.GetSessionVars(), variable.BlockEncryptionMode, tt.mode) - require.NoError(t, err) + require.NoError(t, err, msg) - args := datumsToConstants([]types.Datum{types.NewDatum(tt.origin)}) + args := primitiveValsToConstants(ctx, []interface{}{tt.origin}) args = append(args, primitiveValsToConstants(ctx, tt.params)...) f, err := fc.getFunction(ctx, args) - require.NoError(t, err) + require.NoError(t, err, msg) crypt, err := evalBuiltinFunc(f, chunk.Row{}) - require.NoError(t, err) - require.Equal(t, types.NewDatum(tt.crypt), toHex(crypt)) + require.NoError(t, err, msg) + require.Equal(t, types.NewDatum(tt.crypt), toHex(crypt), msg) } } @@ -209,21 +213,22 @@ func TestAESDecrypt(t *testing.T) { fc := funcs[ast.AesDecrypt] for _, tt := range aesTests { + msg := fmt.Sprintf("%v", tt) err := variable.SetSessionSystemVar(ctx.GetSessionVars(), variable.BlockEncryptionMode, tt.mode) - require.NoError(t, err) + require.NoError(t, err, msg) args := []types.Datum{fromHex(tt.crypt)} for _, param := range tt.params { args = append(args, types.NewDatum(param)) } f, err := fc.getFunction(ctx, datumsToConstants(args)) - require.NoError(t, err) + require.NoError(t, err, msg) str, err := evalBuiltinFunc(f, chunk.Row{}) - require.NoError(t, err) + require.NoError(t, err, msg) if tt.origin == nil { require.True(t, str.IsNull()) continue } - require.Equal(t, types.NewCollationStringDatum(tt.origin.(string), charset.CollationBin), str) + require.Equal(t, types.NewCollationStringDatum(tt.origin.(string), charset.CollationBin), str, msg) } err := variable.SetSessionSystemVar(ctx.GetSessionVars(), variable.BlockEncryptionMode, "aes-128-ecb") require.NoError(t, err) @@ -231,7 +236,9 @@ func TestAESDecrypt(t *testing.T) { testAmbiguousInput(t, ctx, ast.AesDecrypt) // Test GBK String - gbkStr, _ := charset.NewEncoding("gbk").EncodeString("你好") + enc := charset.FindEncoding("gbk") + r, _ := enc.Transform(nil, []byte("你好"), charset.OpEncode) + gbkStr := string(r) gbkTests := []struct { mode string chs string @@ -256,18 +263,19 @@ func TestAESDecrypt(t *testing.T) { } for _, tt := range gbkTests { + msg := fmt.Sprintf("%v", tt) err := ctx.GetSessionVars().SetSystemVar(variable.CharacterSetConnection, tt.chs) - require.NoError(t, err) + require.NoError(t, err, msg) err = variable.SetSessionSystemVar(ctx.GetSessionVars(), variable.BlockEncryptionMode, tt.mode) - require.NoError(t, err) + require.NoError(t, err, msg) // Set charset and collate except first argument args := datumsToConstants([]types.Datum{fromHex(tt.crypt)}) args = append(args, primitiveValsToConstants(ctx, tt.params)...) f, err := fc.getFunction(ctx, args) - require.NoError(t, err) + require.NoError(t, err, msg) str, err := evalBuiltinFunc(f, chunk.Row{}) - require.NoError(t, err) - require.Equal(t, types.NewCollationStringDatum(tt.origin.(string), charset.CollationBin), str) + require.NoError(t, err, msg) + require.Equal(t, types.NewCollationStringDatum(tt.origin.(string), charset.CollationBin), str, msg) } } diff --git a/expression/builtin_encryption_vec.go b/expression/builtin_encryption_vec.go index 4433463429127..1c2124b8c3001 100644 --- a/expression/builtin_encryption_vec.go +++ b/expression/builtin_encryption_vec.go @@ -567,6 +567,7 @@ func (b *builtinCompressSig) vecEvalString(input *chunk.Chunk, result *chunk.Col // According to doc: Empty strings are stored as empty strings. if len(strBytes) == 0 { result.AppendString("") + continue } compressed, err := deflate(strBytes) diff --git a/expression/builtin_info.go b/expression/builtin_info.go index 22018213ef9e7..2a1d5c7c8e731 100644 --- a/expression/builtin_info.go +++ b/expression/builtin_info.go @@ -616,7 +616,35 @@ type charsetFunctionClass struct { } func (c *charsetFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "CHARSET") + if err := c.verifyArgs(args); err != nil { + return nil, err + } + argsTps := make([]types.EvalType, 0, len(args)) + for _, arg := range args { + argsTps = append(argsTps, arg.GetType().EvalType()) + } + bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argsTps...) + if err != nil { + return nil, err + } + bf.tp.Charset, bf.tp.Collate = ctx.GetSessionVars().GetCharsetInfo() + bf.tp.Flen = 64 + sig := &builtinCharsetSig{bf} + return sig, nil +} + +type builtinCharsetSig struct { + baseBuiltinFunc +} + +func (b *builtinCharsetSig) Clone() builtinFunc { + newSig := &builtinCharsetSig{} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +func (b *builtinCharsetSig) evalString(_ chunk.Row) (string, bool, error) { + return b.args[0].GetType().Charset, false, nil } type coercibilityFunctionClass struct { diff --git a/expression/builtin_info_test.go b/expression/builtin_info_test.go index c6b730882c2e9..6416ebec578d6 100644 --- a/expression/builtin_info_test.go +++ b/expression/builtin_info_test.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" @@ -192,9 +192,9 @@ func TestCharset(t *testing.T) { ctx := createContext(t) fc := funcs[ast.Charset] f, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(nil))) - require.Nil(t, f) - require.Error(t, err) - require.Regexp(t, "FUNCTION CHARSET does not exist$", err.Error()) + require.NotNil(t, f) + require.NoError(t, err) + require.Equal(t, 64, f.getRetTp().Flen) } func TestCoercibility(t *testing.T) { @@ -323,7 +323,7 @@ func TestFormatBytes(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } } @@ -352,6 +352,6 @@ func TestFormatNanoTime(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } } diff --git a/expression/builtin_json.go b/expression/builtin_json.go index 92e427d1b883a..378f00149da9c 100644 --- a/expression/builtin_json.go +++ b/expression/builtin_json.go @@ -848,8 +848,6 @@ func (b *builtinJSONValidStringSig) evalInt(row chunk.Row) (res int64, isNull bo data := hack.Slice(val) if goJSON.Valid(data) { res = 1 - } else { - res = 0 } return res, false, nil } diff --git a/expression/builtin_json_test.go b/expression/builtin_json_test.go index add185d57cc9a..48b47eed331f6 100644 --- a/expression/builtin_json_test.go +++ b/expression/builtin_json_test.go @@ -21,7 +21,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" @@ -49,7 +49,7 @@ func TestJSONType(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Expected"][0], d) + testutil.DatumEqual(t, tt["Expected"][0], d) } } @@ -78,7 +78,7 @@ func TestJSONQuote(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Expected"][0], d) + testutil.DatumEqual(t, tt["Expected"][0], d) } } @@ -982,7 +982,7 @@ func TestJSONValid(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Expected"][0], d) + testutil.DatumEqual(t, tt["Expected"][0], d) } } diff --git a/expression/builtin_like_test.go b/expression/builtin_like_test.go index 87f759ec9cf21..004cd1210858b 100644 --- a/expression/builtin_like_test.go +++ b/expression/builtin_like_test.go @@ -20,7 +20,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" @@ -57,7 +57,7 @@ func TestLike(t *testing.T) { require.NoError(t, err, comment) r, err := evalBuiltinFuncConcurrent(f, chunk.Row{}) require.NoError(t, err, comment) - trequire.DatumEqual(t, types.NewDatum(tt.match), r, comment) + testutil.DatumEqual(t, types.NewDatum(tt.match), r, comment) } } @@ -90,7 +90,7 @@ func TestRegexp(t *testing.T) { match, err := evalBuiltinFunc(f, chunk.Row{}) if tt.err == nil { require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.match), match, fmt.Sprintf("%v", tt)) + testutil.DatumEqual(t, types.NewDatum(tt.match), match, fmt.Sprintf("%v", tt)) } else { require.True(t, terror.ErrorEqual(err, tt.err)) } @@ -98,8 +98,6 @@ func TestRegexp(t *testing.T) { } func TestCILike(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) ctx := createContext(t) tests := []struct { input string @@ -143,7 +141,7 @@ func TestCILike(t *testing.T) { f.setCollator(collate.GetCollator("utf8mb4_general_ci")) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err, comment) - trequire.DatumEqual(t, types.NewDatum(tt.generalMatch), r, comment) + testutil.DatumEqual(t, types.NewDatum(tt.generalMatch), r, comment) } for _, tt := range tests { @@ -155,6 +153,6 @@ func TestCILike(t *testing.T) { f.setCollator(collate.GetCollator("utf8mb4_unicode_ci")) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err, comment) - trequire.DatumEqual(t, types.NewDatum(tt.unicodeMatch), r, comment) + testutil.DatumEqual(t, types.NewDatum(tt.unicodeMatch), r, comment) } } diff --git a/expression/builtin_math.go b/expression/builtin_math.go index 54fae95639142..ee17b4e490ffe 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -393,7 +393,7 @@ func (b *builtinRoundDecSig) evalDecimal(row chunk.Row) (*types.MyDecimal, bool, return nil, isNull, err } to := new(types.MyDecimal) - if err = val.Round(to, 0, types.ModeHalfEven); err != nil { + if err = val.Round(to, 0, types.ModeHalfUp); err != nil { return nil, true, err } return to, false, nil @@ -469,7 +469,7 @@ func (b *builtinRoundWithFracDecSig) evalDecimal(row chunk.Row) (*types.MyDecima return nil, isNull, err } to := new(types.MyDecimal) - if err = val.Round(to, mathutil.Min(int(frac), b.tp.Decimal), types.ModeHalfEven); err != nil { + if err = val.Round(to, mathutil.Min(int(frac), b.tp.Decimal), types.ModeHalfUp); err != nil { return nil, true, err } return to, false, nil diff --git a/expression/builtin_math_test.go b/expression/builtin_math_test.go index 898693d14b394..43282a07c02da 100644 --- a/expression/builtin_math_test.go +++ b/expression/builtin_math_test.go @@ -23,7 +23,8 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" utilMath "github.com/pingcap/tidb/util/math" @@ -53,7 +54,7 @@ func TestAbs(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } } @@ -107,7 +108,7 @@ func TestCeil(t *testing.T) { if test.isNil { require.Equal(t, types.KindNull, result.Kind()) } else { - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } } } @@ -223,7 +224,7 @@ func TestFloor(t *testing.T) { if test.isNil { require.Equal(t, types.KindNull, result.Kind()) } else { - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } } } @@ -403,7 +404,7 @@ func TestPow(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } errTbl := []struct { @@ -480,7 +481,7 @@ func TestRound(t *testing.T) { } v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } } @@ -524,34 +525,42 @@ func TestTruncate(t *testing.T) { require.NotNil(t, f) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } } func TestCRC32(t *testing.T) { ctx := createContext(t) tbl := []struct { - Arg []interface{} - Ret interface{} + input []interface{} + chs string + result int64 + isNull bool }{ - {[]interface{}{nil}, nil}, - {[]interface{}{""}, 0}, - {[]interface{}{-1}, 808273962}, - {[]interface{}{"-1"}, 808273962}, - {[]interface{}{"mysql"}, 2501908538}, - {[]interface{}{"MySQL"}, 3259397556}, - {[]interface{}{"hello"}, 907060870}, + {[]interface{}{nil}, "utf8", 0, true}, + {[]interface{}{""}, "utf8", 0, false}, + {[]interface{}{-1}, "utf8", 808273962, false}, + {[]interface{}{"-1"}, "utf8", 808273962, false}, + {[]interface{}{"mysql"}, "utf8", 2501908538, false}, + {[]interface{}{"MySQL"}, "utf8", 3259397556, false}, + {[]interface{}{"hello"}, "utf8", 907060870, false}, + {[]interface{}{"一二三"}, "utf8", 1785250883, false}, + {[]interface{}{"一"}, "utf8", 2416838398, false}, + {[]interface{}{"一二三"}, "gbk", 3461331449, false}, + {[]interface{}{"一"}, "gbk", 2925846374, false}, } - - Dtbl := tblToDtbl(tbl) - - for _, tt := range Dtbl { - fc := funcs[ast.CRC32] - f, err := fc.getFunction(ctx, datumsToConstants(tt["Arg"])) + for _, c := range tbl { + err := ctx.GetSessionVars().SetSystemVar(variable.CharacterSetConnection, c.chs) require.NoError(t, err) - v, err := evalBuiltinFunc(f, chunk.Row{}) + f, err := newFunctionForTest(ctx, ast.CRC32, primitiveValsToConstants(ctx, c.input)...) + require.NoError(t, err) + d, err := f.Eval(chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + if c.isNull { + require.True(t, d.IsNull()) + } else { + require.Equal(t, c.result, d.GetInt64()) + } } } @@ -650,7 +659,7 @@ func TestSign(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.ret), v) + testutil.DatumEqual(t, types.NewDatum(tt.ret), v) } } @@ -717,7 +726,7 @@ func TestSqrt(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.Ret), v) + testutil.DatumEqual(t, types.NewDatum(tt.Ret), v) } } @@ -728,7 +737,7 @@ func TestPi(t *testing.T) { pi, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(math.Pi), pi) + testutil.DatumEqual(t, types.NewDatum(math.Pi), pi) } func TestRadians(t *testing.T) { @@ -752,7 +761,7 @@ func TestRadians(t *testing.T) { require.NotNil(t, f) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Ret"][0], v) + testutil.DatumEqual(t, tt["Ret"][0], v) } invalidArg := "notNum" diff --git a/expression/builtin_math_vec.go b/expression/builtin_math_vec.go index 13b6a701d5d8e..c0dfa90b870dd 100644 --- a/expression/builtin_math_vec.go +++ b/expression/builtin_math_vec.go @@ -392,7 +392,7 @@ func (b *builtinRoundDecSig) vecEvalDecimal(input *chunk.Chunk, result *chunk.Co if result.IsNull(i) { continue } - if err := d64s[i].Round(buf, 0, types.ModeHalfEven); err != nil { + if err := d64s[i].Round(buf, 0, types.ModeHalfUp); err != nil { return err } d64s[i] = *buf @@ -994,7 +994,7 @@ func (b *builtinRoundWithFracDecSig) vecEvalDecimal(input *chunk.Chunk, result * continue } // TODO: reuse d64[i] and remove the temporary variable tmp. - if err := d64s[i].Round(tmp, mathutil.Min(int(i64s[i]), b.tp.Decimal), types.ModeHalfEven); err != nil { + if err := d64s[i].Round(tmp, mathutil.Min(int(i64s[i]), b.tp.Decimal), types.ModeHalfUp); err != nil { return err } d64s[i] = *tmp diff --git a/expression/builtin_miscellaneous.go b/expression/builtin_miscellaneous.go index 82b43d192c84c..8963132c736cf 100644 --- a/expression/builtin_miscellaneous.go +++ b/expression/builtin_miscellaneous.go @@ -58,6 +58,7 @@ var ( _ functionClass = &uuidToBinFunctionClass{} _ functionClass = &binToUUIDFunctionClass{} _ functionClass = &isUUIDFunctionClass{} + _ functionClass = &tidbShardFunctionClass{} ) var ( @@ -92,6 +93,11 @@ var ( _ builtinFunc = &builtinNameConstDurationSig{} _ builtinFunc = &builtinNameConstStringSig{} _ builtinFunc = &builtinNameConstJSONSig{} + _ builtinFunc = &builtinTidbShardSig{} +) + +const ( + tidbShardBucketCount = 256 ) type sleepFunctionClass struct { @@ -131,7 +137,8 @@ func (b *builtinSleepSig) evalInt(row chunk.Row) (int64, bool, error) { sessVars := b.ctx.GetSessionVars() if isNull || val < 0 { - if sessVars.StrictSQLMode { + // for insert ignore stmt, the StrictSQLMode and ignoreErr should both be considered. + if !sessVars.StmtCtx.BadNullAsWarning { return 0, false, errIncorrectArgs.GenWithStackByArgs("sleep") } err := errIncorrectArgs.GenWithStackByArgs("sleep") @@ -1304,3 +1311,49 @@ func swapStringUUID(str string) string { copy(buf[18:], str[18:]) return string(buf) } + +type tidbShardFunctionClass struct { + baseFunctionClass +} + +func (c *tidbShardFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { + if err := c.verifyArgs(args); err != nil { + return nil, err + } + bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt) + if err != nil { + return nil, err + } + + bf.tp.Flen = 4 //64 bit unsigned + bf.tp.Flag |= mysql.UnsignedFlag + types.SetBinChsClnFlag(bf.tp) + + sig := &builtinTidbShardSig{bf} + sig.setPbCode(tipb.ScalarFuncSig_TiDBShard) + return sig, nil +} + +type builtinTidbShardSig struct { + baseBuiltinFunc +} + +func (b *builtinTidbShardSig) Clone() builtinFunc { + newSig := &builtinTidbShardSig{} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +// evalInt evals tidb_shard(int64). +func (b *builtinTidbShardSig) evalInt(row chunk.Row) (int64, bool, error) { + shardKeyInt, isNull, err := b.args[0].EvalInt(b.ctx, row) + if isNull || err != nil { + return 0, true, err + } + var hashed uint64 + if hashed, err = vitess.HashUint64(uint64(shardKeyInt)); err != nil { + return 0, true, err + } + hashed = hashed % tidbShardBucketCount + return int64(hashed), false, nil +} diff --git a/expression/builtin_miscellaneous_test.go b/expression/builtin_miscellaneous_test.go index f125c1b023df3..9f2ee3be668c0 100644 --- a/expression/builtin_miscellaneous_test.go +++ b/expression/builtin_miscellaneous_test.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/stretchr/testify/require" @@ -56,7 +56,7 @@ func TestInetAton(t *testing.T) { require.NoError(t, err) d, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, tt["Expected"][0], d) + testutil.DatumEqual(t, tt["Expected"][0], d) } } @@ -85,14 +85,14 @@ func TestIsIPv4(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } // test NULL input for is_ipv4 var argNull types.Datum f, _ := fc.getFunction(ctx, datumsToConstants([]types.Datum{argNull})) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(0), r) + testutil.DatumEqual(t, types.NewDatum(0), r) } func TestIsUUID(t *testing.T) { @@ -120,7 +120,7 @@ func TestIsUUID(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum @@ -174,7 +174,7 @@ func TestAnyValue(t *testing.T) { require.NoError(t, err) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.ret), r) + testutil.DatumEqual(t, types.NewDatum(tt.ret), r) } } @@ -197,14 +197,14 @@ func TestIsIPv6(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } // test NULL input for is_ipv6 var argNull types.Datum f, _ := fc.getFunction(ctx, datumsToConstants([]types.Datum{argNull})) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(0), r) + testutil.DatumEqual(t, types.NewDatum(0), r) } func TestInetNtoa(t *testing.T) { @@ -227,7 +227,7 @@ func TestInetNtoa(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum @@ -265,7 +265,7 @@ func TestInet6NtoA(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum @@ -296,7 +296,7 @@ func TestInet6AtoN(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum @@ -325,14 +325,14 @@ func TestIsIPv4Mapped(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum f, _ := fc.getFunction(ctx, datumsToConstants([]types.Datum{argNull})) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(int64(0)), r) + testutil.DatumEqual(t, types.NewDatum(int64(0)), r) } func TestIsIPv4Compat(t *testing.T) { @@ -355,14 +355,14 @@ func TestIsIPv4Compat(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } var argNull types.Datum f, _ := fc.getFunction(ctx, datumsToConstants([]types.Datum{argNull})) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(0), r) + testutil.DatumEqual(t, types.NewDatum(0), r) } func TestNameConst(t *testing.T) { @@ -498,7 +498,7 @@ func TestUUIDToBin(t *testing.T) { if test.isNil { require.Equal(t, types.KindNull, result.Kind()) } else { - trequire.DatumEqual(t, types.NewDatum(test.expect), result) + testutil.DatumEqual(t, types.NewDatum(test.expect), result) } } } @@ -577,3 +577,37 @@ func TestBinToUUID(t *testing.T) { _, err := funcs[ast.BinToUUID].getFunction(ctx, []Expression{NewZero()}) require.NoError(t, err) } + +func TestTidbShard(t *testing.T) { + ctx := createContext(t) + + fc := funcs[ast.TiDBShard] + + // tidb_shard(-1) == 81, ...... + args := makeDatums([]int{-1, 0, 1, 9999999999999999}) + res := makeDatums([]int{81, 167, 214, 63}) + for i, arg := range args { + f, err := fc.getFunction(ctx, datumsToConstants([]types.Datum{arg})) + require.NoError(t, err) + d, err := evalBuiltinFunc(f, chunk.Row{}) + require.NoError(t, err) + testutil.DatumEqual(t, res[i], d) + } + + // tidb_shard("string") always return 167 + args2 := makeDatums([]string{"abc", "ope", "wopddd"}) + res2 := makeDatums([]int{167}) + for _, arg := range args2 { + f, err := fc.getFunction(ctx, datumsToConstants([]types.Datum{arg})) + require.NoError(t, err) + d, err := evalBuiltinFunc(f, chunk.Row{}) + require.NoError(t, err) + testutil.DatumEqual(t, res2[0], d) + } + + args3 := makeDatums([]int{-1, 0, 1, 9999999999999999}) + { + _, err := fc.getFunction(ctx, datumsToConstants(args3)) + require.Error(t, err) + } +} diff --git a/expression/builtin_miscellaneous_vec.go b/expression/builtin_miscellaneous_vec.go index 6e4b16c4cb7dd..31a617cd31f10 100644 --- a/expression/builtin_miscellaneous_vec.go +++ b/expression/builtin_miscellaneous_vec.go @@ -341,7 +341,8 @@ func (b *builtinSleepSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) e sessVars := b.ctx.GetSessionVars() if isNull || val < 0 { - if sessVars.StrictSQLMode { + // for insert ignore stmt, the StrictSQLMode and ignoreErr should both be considered. + if !sessVars.StmtCtx.BadNullAsWarning { return errIncorrectArgs.GenWithStackByArgs("sleep") } err := errIncorrectArgs.GenWithStackByArgs("sleep") diff --git a/expression/builtin_miscellaneous_vec_test.go b/expression/builtin_miscellaneous_vec_test.go index 386f7bc423878..30530bc27a837 100644 --- a/expression/builtin_miscellaneous_vec_test.go +++ b/expression/builtin_miscellaneous_vec_test.go @@ -152,7 +152,7 @@ func TestSleepVectorized(t *testing.T) { warnCnt := counter{} // non-strict model - sessVars.StrictSQLMode = false + sessVars.StmtCtx.BadNullAsWarning = true input.AppendFloat64(0, 1) err = f.vecEvalInt(input, result) require.NoError(t, err) @@ -185,7 +185,7 @@ func TestSleepVectorized(t *testing.T) { require.Equal(t, uint16(warnCnt.add(2)), sessVars.StmtCtx.WarningCount()) // for error case under the strict model - sessVars.StrictSQLMode = true + sessVars.StmtCtx.BadNullAsWarning = false input.Reset() input.AppendNull(0) err = f.vecEvalInt(input, result) diff --git a/expression/builtin_op_test.go b/expression/builtin_op_test.go index 2e05b314d457c..04024c90cb70f 100644 --- a/expression/builtin_op_test.go +++ b/expression/builtin_op_test.go @@ -21,7 +21,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/stretchr/testify/require" @@ -583,7 +583,7 @@ func TestIsTrueOrFalse(t *testing.T) { isTrue, err := evalBuiltinFunc(isTrueSig, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.isTrue), isTrue) + testutil.DatumEqual(t, types.NewDatum(tc.isTrue), isTrue) } for _, tc := range testCases { @@ -593,7 +593,7 @@ func TestIsTrueOrFalse(t *testing.T) { isFalse, err := evalBuiltinFunc(isFalseSig, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tc.isFalse), isFalse) + testutil.DatumEqual(t, types.NewDatum(tc.isFalse), isFalse) } } diff --git a/expression/builtin_other.go b/expression/builtin_other.go index e4a0a57028084..9ffd17b96b7d6 100644 --- a/expression/builtin_other.go +++ b/expression/builtin_other.go @@ -85,7 +85,8 @@ type inFunctionClass struct { } func (c *inFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) { - if err := c.verifyArgs(args); err != nil { + args, err = c.verifyArgs(ctx, args) + if err != nil { return nil, err } argTps := make([]types.EvalType, len(args)) @@ -156,6 +157,27 @@ func (c *inFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) return sig, nil } +func (c *inFunctionClass) verifyArgs(ctx sessionctx.Context, args []Expression) ([]Expression, error) { + columnType := args[0].GetType() + validatedArgs := make([]Expression, 0, len(args)) + for _, arg := range args { + if constant, ok := arg.(*Constant); ok { + switch { + case columnType.Tp == mysql.TypeBit && constant.Value.Kind() == types.KindInt64: + if constant.Value.GetInt64() < 0 { + if MaybeOverOptimized4PlanCache(ctx, args) { + ctx.GetSessionVars().StmtCtx.SkipPlanCache = true + } + continue + } + } + } + validatedArgs = append(validatedArgs, arg) + } + err := c.baseFunctionClass.verifyArgs(validatedArgs) + return validatedArgs, err +} + // nolint:structcheck type baseInSig struct { baseBuiltinFunc diff --git a/expression/builtin_other_test.go b/expression/builtin_other_test.go index f786c1b6aeb81..1e865a93cff7d 100644 --- a/expression/builtin_other_test.go +++ b/expression/builtin_other_test.go @@ -298,8 +298,6 @@ func TestInFunc(t *testing.T) { require.NoError(t, err) require.Equalf(t, tc.res, d.GetValue(), "%v", types.MakeDatums(tc.args)) } - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) strD1 := types.NewCollationStringDatum("a", "utf8_general_ci") strD2 := types.NewCollationStringDatum("Ã", "utf8_general_ci") fn, err := fc.getFunction(ctx, datumsToConstants([]types.Datum{strD1, strD2})) diff --git a/expression/builtin_other_vec_generated_test.go b/expression/builtin_other_vec_generated_test.go index 2c571519086ce..fe5de1ea93d23 100644 --- a/expression/builtin_other_vec_generated_test.go +++ b/expression/builtin_other_vec_generated_test.go @@ -19,6 +19,7 @@ package expression import ( "fmt" "math/rand" + "strconv" "testing" "time" @@ -69,7 +70,7 @@ func (g inGener) gen() interface{} { } return *j case types.ETString: - return fmt.Sprint(randNum) + return strconv.FormatInt(randNum, 10) } return randNum } diff --git a/expression/builtin_string.go b/expression/builtin_string.go index 9ac2eb370d380..a3b6824fdebc4 100644 --- a/expression/builtin_string.go +++ b/expression/builtin_string.go @@ -41,7 +41,6 @@ import ( "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tipb/go-tipb" "go.uber.org/zap" - "golang.org/x/text/transform" ) var ( @@ -174,10 +173,12 @@ func reverseRunes(origin []rune) []rune { // SetBinFlagOrBinStr sets resTp to binary string if argTp is a binary string, // if not, sets the binary flag of resTp to true if argTp has binary flag. +// We need to check if the tp is enum or set, if so, don't add binary flag directly unless it has binary flag. func SetBinFlagOrBinStr(argTp *types.FieldType, resTp *types.FieldType) { + nonEnumOrSet := !(argTp.Tp == mysql.TypeEnum || argTp.Tp == mysql.TypeSet) if types.IsBinaryStr(argTp) { types.SetBinChsClnFlag(resTp) - } else if mysql.HasBinaryFlag(argTp.Flag) || !types.IsNonBinaryStr(argTp) { + } else if mysql.HasBinaryFlag(argTp.Flag) || (!types.IsNonBinaryStr(argTp) && nonEnumOrSet) { resTp.Flag |= mysql.BinaryFlag } } @@ -330,8 +331,7 @@ func (b *builtinConcatSig) evalString(row chunk.Row) (d string, isNull bool, err return d, isNull, err } if uint64(len(s)+len(d)) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "concat", b.maxAllowedPacket) } s = append(s, []byte(d)...) } @@ -435,8 +435,7 @@ func (b *builtinConcatWSSig) evalString(row chunk.Row) (string, bool, error) { targetLength += len(sep) } if uint64(targetLength) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat_ws", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "concat_ws", b.maxAllowedPacket) } strs = append(strs, val) } @@ -640,6 +639,7 @@ func (c *repeatFunctionClass) getFunction(ctx sessionctx.Context, args []Express return nil, errors.Trace(err) } sig := &builtinRepeatSig{bf, maxAllowedPacket} + sig.setPbCode(tipb.ScalarFuncSig_Repeat) return sig, nil } @@ -676,13 +676,9 @@ func (b *builtinRepeatSig) evalString(row chunk.Row) (d string, isNull bool, err } if uint64(byteLength)*uint64(num) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("repeat", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "repeat", b.maxAllowedPacket) } - if int64(byteLength) > int64(b.tp.Flen)/num { - return "", true, nil - } return strings.Repeat(str, int(num)), false, nil } @@ -706,7 +702,7 @@ func (c *lowerFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi sig = &builtinLowerSig{bf} sig.setPbCode(tipb.ScalarFuncSig_Lower) } else { - sig = &builtinLowerUTF8Sig{bf, charset.NewEncoding(argTp.Charset)} + sig = &builtinLowerUTF8Sig{bf} sig.setPbCode(tipb.ScalarFuncSig_LowerUTF8) } return sig, nil @@ -714,15 +710,11 @@ func (c *lowerFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi type builtinLowerUTF8Sig struct { baseBuiltinFunc - encoding *charset.Encoding } func (b *builtinLowerUTF8Sig) Clone() builtinFunc { newSig := &builtinLowerUTF8Sig{} newSig.cloneFrom(&b.baseBuiltinFunc) - if b.encoding != nil { - newSig.encoding = charset.NewEncoding(b.encoding.Name()) - } return newSig } @@ -733,8 +725,8 @@ func (b *builtinLowerUTF8Sig) evalString(row chunk.Row) (d string, isNull bool, if isNull || err != nil { return d, isNull, err } - - return b.encoding.ToLower(d), false, nil + enc := charset.FindEncoding(b.args[0].GetType().Charset) + return enc.ToLower(d), false, nil } type builtinLowerSig struct { @@ -770,12 +762,12 @@ func (c *reverseFunctionClass) getFunction(ctx sessionctx.Context, args []Expres if err != nil { return nil, err } - retTp := *args[0].GetType() - retTp.Tp = mysql.TypeVarString - retTp.Decimal = types.UnspecifiedLength - bf.tp = &retTp + + argTp := args[0].GetType() + bf.tp.Flen = args[0].GetType().Flen + addBinFlag(bf.tp) var sig builtinFunc - if types.IsBinaryStr(bf.tp) { + if types.IsBinaryStr(argTp) { sig = &builtinReverseSig{bf} sig.setPbCode(tipb.ScalarFuncSig_Reverse) } else { @@ -876,8 +868,7 @@ func (b *builtinSpaceSig) evalString(row chunk.Row) (d string, isNull bool, err x = 0 } if uint64(x) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("space", b.maxAllowedPacket)) - return d, true, nil + return d, true, handleAllowedPacketOverflowed(b.ctx, "space", b.maxAllowedPacket) } if x > mysql.MaxBlobWidth { return d, true, nil @@ -905,7 +896,7 @@ func (c *upperFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi sig = &builtinUpperSig{bf} sig.setPbCode(tipb.ScalarFuncSig_Upper) } else { - sig = &builtinUpperUTF8Sig{bf, charset.NewEncoding(argTp.Charset)} + sig = &builtinUpperUTF8Sig{bf} sig.setPbCode(tipb.ScalarFuncSig_UpperUTF8) } return sig, nil @@ -913,15 +904,11 @@ func (c *upperFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi type builtinUpperUTF8Sig struct { baseBuiltinFunc - encoding *charset.Encoding } func (b *builtinUpperUTF8Sig) Clone() builtinFunc { newSig := &builtinUpperUTF8Sig{} newSig.cloneFrom(&b.baseBuiltinFunc) - if b.encoding != nil { - newSig.encoding = charset.NewEncoding(b.encoding.Name()) - } return newSig } @@ -932,8 +919,8 @@ func (b *builtinUpperUTF8Sig) evalString(row chunk.Row) (d string, isNull bool, if isNull || err != nil { return d, isNull, err } - - return b.encoding.ToUpper(d), false, nil + enc := charset.FindEncoding(b.args[0].GetType().Charset) + return enc.ToUpper(d), false, nil } type builtinUpperSig struct { @@ -1141,27 +1128,27 @@ func (b *builtinConvertSig) evalString(row chunk.Row) (string, bool, error) { if isNull || err != nil { return "", true, err } - - // Since charset is already validated and set from getFunction(), there's no - // need to get charset from args again. - encoding, _ := charset.Lookup(b.tp.Charset) - // However, if `b.tp.Charset` is abnormally set to a wrong charset, we still - // return with error. - if encoding == nil { - return "", true, errUnknownCharacterSet.GenWithStackByArgs(b.tp.Charset) + argTp, resultTp := b.args[0].GetType(), b.tp + if !charset.IsSupportedEncoding(resultTp.Charset) { + return "", false, errUnknownCharacterSet.GenWithStackByArgs(resultTp.Charset) } - // if expr is binary string and convert meet error, we should return NULL. - if types.IsBinaryStr(b.args[0].GetType()) { - exprInternal, _, err := transform.String(encoding.NewDecoder(), expr) - return exprInternal, err != nil, nil + if types.IsBinaryStr(argTp) { + // Convert charset binary -> utf8. If it meets error, NULL is returned. + enc := charset.FindEncoding(resultTp.Charset) + ret, err := enc.Transform(nil, hack.Slice(expr), charset.OpDecodeReplace) + return string(ret), err != nil, nil + } else if types.IsBinaryStr(resultTp) { + // Convert charset utf8 -> binary. + enc := charset.FindEncoding(argTp.Charset) + ret, err := enc.Transform(nil, hack.Slice(expr), charset.OpEncode) + return string(ret), false, err } - if types.IsBinaryStr(b.tp) { - enc := charset.NewEncoding(b.args[0].GetType().Charset) - expr, err = enc.EncodeString(expr) - return expr, false, err + enc := charset.FindEncoding(resultTp.Charset) + if !enc.IsValid(hack.Slice(expr)) { + replace, _ := enc.Transform(nil, hack.Slice(expr), charset.OpReplaceNoErr) + return string(replace), false, nil } - enc := charset.NewEncoding(b.tp.Charset) - return string(enc.EncodeInternal(nil, []byte(expr))), false, nil + return expr, false, nil } type substringFunctionClass struct { @@ -2091,8 +2078,7 @@ func (b *builtinLpadSig) evalString(row chunk.Row) (string, bool, error) { targetLength := int(length) if uint64(targetLength) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "lpad", b.maxAllowedPacket) } padStr, isNull, err := b.args[2].EvalString(b.ctx, row) @@ -2140,8 +2126,7 @@ func (b *builtinLpadUTF8Sig) evalString(row chunk.Row) (string, bool, error) { targetLength := int(length) if uint64(targetLength)*uint64(mysql.MaxBytesOfCharacter) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "lpad", b.maxAllowedPacket) } padStr, isNull, err := b.args[2].EvalString(b.ctx, row) @@ -2222,8 +2207,7 @@ func (b *builtinRpadSig) evalString(row chunk.Row) (string, bool, error) { } targetLength := int(length) if uint64(targetLength) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "rpad", b.maxAllowedPacket) } padStr, isNull, err := b.args[2].EvalString(b.ctx, row) @@ -2271,8 +2255,7 @@ func (b *builtinRpadUTF8Sig) evalString(row chunk.Row) (string, bool, error) { targetLength := int(length) if uint64(targetLength)*uint64(mysql.MaxBytesOfCharacter) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "rpad", b.maxAllowedPacket) } padStr, isNull, err := b.args[2].EvalString(b.ctx, row) @@ -2327,12 +2310,7 @@ func (b *builtinBitLengthSig) evalInt(row chunk.Row) (int64, bool, error) { if isNull || err != nil { return 0, isNull, err } - argTp := b.args[0].GetType() - dBytes, err := charset.NewEncoding(argTp.Charset).Encode(nil, hack.Slice(val)) - if err != nil { - return 0, isNull, err - } - return int64(len(dBytes) * 8), false, nil + return int64(len(val) * 8), false, nil } type charFunctionClass struct { @@ -2421,12 +2399,15 @@ func (b *builtinCharSig) evalString(row chunk.Row) (string, bool, error) { } dBytes := b.convertToBytes(bigints) - resultBytes, err := charset.NewEncoding(b.tp.Charset).Decode(nil, dBytes) + enc := charset.FindEncoding(b.tp.Charset) + res, err := enc.Transform(nil, dBytes, charset.OpDecode) if err != nil { b.ctx.GetSessionVars().StmtCtx.AppendWarning(err) - return "", true, nil + if b.ctx.GetSessionVars().StrictSQLMode { + return "", true, nil + } } - return string(resultBytes), false, nil + return string(res), false, nil } type charLengthFunctionClass struct { @@ -2893,43 +2874,19 @@ func (b *builtinOrdSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, isNull, err } - charSet := b.args[0].GetType().Charset - ord, err := chooseOrdFunc(charSet) - if err != nil { - return 0, false, err - } - - enc := charset.NewEncoding(charSet) - leftMost, err := enc.EncodeFirstChar(nil, hack.Slice(str)) - if err != nil { - return 0, false, err - } - return ord(leftMost), false, nil -} - -func chooseOrdFunc(charSet string) (func([]byte) int64, error) { - // use utf8 by default - if charSet == "" { - charSet = charset.CharsetUTF8 - } - desc, err := charset.GetCharsetInfo(charSet) + strBytes := hack.Slice(str) + enc := charset.FindEncoding(b.args[0].GetType().Charset) + w := len(charset.EncodingUTF8Impl.Peek(strBytes)) + res, err := enc.Transform(nil, strBytes[:w], charset.OpEncode) if err != nil { - return nil, err + // Fallback to the first byte. + return calcOrd(strBytes[:1]), false, nil } - if desc.Maxlen == 1 { - return ordSingleByte, nil - } - return ordOthers, nil + // Only the first character is considered. + return calcOrd(res[:len(enc.Peek(res))]), false, nil } -func ordSingleByte(src []byte) int64 { - if len(src) == 0 { - return 0 - } - return int64(src[0]) -} - -func ordOthers(leftMost []byte) int64 { +func calcOrd(leftMost []byte) int64 { var result int64 var factor int64 = 1 for i := len(leftMost) - 1; i >= 0; i-- { @@ -3488,6 +3445,7 @@ func (c *fromBase64FunctionClass) getFunction(ctx sessionctx.Context, args []Exp types.SetBinChsClnFlag(bf.tp) sig := &builtinFromBase64Sig{bf, maxAllowedPacket} + sig.setPbCode(tipb.ScalarFuncSig_FromBase64) return sig, nil } @@ -3528,8 +3486,7 @@ func (b *builtinFromBase64Sig) evalString(row chunk.Row) (string, bool, error) { return "", true, nil } if needDecodeLen > int(b.maxAllowedPacket) { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("from_base64", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "from_base64", b.maxAllowedPacket) } str = strings.Replace(str, "\t", "", -1) @@ -3564,6 +3521,7 @@ func (c *toBase64FunctionClass) getFunction(ctx sessionctx.Context, args []Expre } sig := &builtinToBase64Sig{bf, maxAllowedPacket} + sig.setPbCode(tipb.ScalarFuncSig_ToBase64) return sig, nil } @@ -3614,8 +3572,7 @@ func (b *builtinToBase64Sig) evalString(row chunk.Row) (d string, isNull bool, e return "", true, nil } if needEncodeLen > int(b.maxAllowedPacket) { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("to_base64", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "to_base64", b.maxAllowedPacket) } if b.tp.Flen == -1 || b.tp.Flen > mysql.MaxBlobWidth { b.tp.Flen = mysql.MaxBlobWidth @@ -3720,8 +3677,7 @@ func (b *builtinInsertSig) evalString(row chunk.Row) (string, bool, error) { } if uint64(strLength-length+int64(len(newstr))) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "insert", b.maxAllowedPacket) } return str[0:pos-1] + newstr + str[pos+length-1:], false, nil @@ -3774,8 +3730,7 @@ func (b *builtinInsertUTF8Sig) evalString(row chunk.Row) (string, bool, error) { strHead := string(runes[0 : pos-1]) strTail := string(runes[pos+length-1:]) if uint64(len(strHead)+len(newstr)+len(strTail)) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "insert", b.maxAllowedPacket) } return strHead + newstr + strTail, false, nil } @@ -4043,8 +3998,7 @@ func (b *builtinWeightStringSig) evalString(row chunk.Row) (string, bool, error) str = string(runes[:b.length]) } else if b.length > lenRunes { if uint64(b.length-lenRunes) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("weight_string", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "weight_string", b.maxAllowedPacket) } str += strings.Repeat(" ", b.length-lenRunes) } @@ -4057,8 +4011,7 @@ func (b *builtinWeightStringSig) evalString(row chunk.Row) (string, bool, error) str = str[:b.length] } else if b.length > lenStr { if uint64(b.length-lenStr) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("cast_as_binary", b.maxAllowedPacket)) - return "", true, nil + return "", true, handleAllowedPacketOverflowed(b.ctx, "cast_as_binary", b.maxAllowedPacket) } str += strings.Repeat("\x00", b.length-lenStr) } diff --git a/expression/builtin_string_test.go b/expression/builtin_string_test.go index 8aeea63add9e8..e45e92b2e3b0b 100644 --- a/expression/builtin_string_test.go +++ b/expression/builtin_string_test.go @@ -29,10 +29,9 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -508,7 +507,7 @@ func TestRepeat(t *testing.T) { require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - require.True(t, v.IsNull()) + require.False(t, v.IsNull()) args = []interface{}{"a", uint64(16777216)} f, err = fc.getFunction(ctx, datumsToConstants(types.MakeDatums(args...))) @@ -729,7 +728,7 @@ func TestReverse(t *testing.T) { require.NotNil(t, f) d, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Expect"][0], d) + testutil.DatumEqual(t, c["Expect"][0], d) } } @@ -920,6 +919,7 @@ func TestConvert(t *testing.T) { wrongFunction := f.(*builtinConvertSig) wrongFunction.tp.Charset = "wrongcharset" _, err = evalBuiltinFunc(wrongFunction, chunk.Row{}) + require.Error(t, err) require.Equal(t, "[expression:1115]Unknown character set: 'wrongcharset'", err.Error()) } @@ -1403,13 +1403,7 @@ func TestBitLength(t *testing.T) { func TestChar(t *testing.T) { ctx := createContext(t) - stmtCtx := ctx.GetSessionVars().StmtCtx - origin := stmtCtx.IgnoreTruncate - stmtCtx.IgnoreTruncate = true - defer func() { - stmtCtx.IgnoreTruncate = origin - }() - + ctx.GetSessionVars().StmtCtx.IgnoreTruncate = true tbl := []struct { str string iNum int64 @@ -1418,30 +1412,36 @@ func TestChar(t *testing.T) { result interface{} warnings int }{ - {"65", 66, 67.5, "utf8", "ABD", 0}, // float - {"65", 16740, 67.5, "utf8", "AAdD", 0}, // large num - {"65", -1, 67.5, nil, "A\xff\xff\xff\xffD", 0}, // nagtive int - {"a", -1, 67.5, nil, "\x00\xff\xff\xff\xffD", 0}, // invalid 'a' - // TODO: Uncomment it when issue #29685 be closed - // {"65", -1, 67.5, "utf8", nil, 1}, // with utf8, return nil - // {"a", -1, 67.5, "utf8", nil, 2}, // with utf8, return nil - // TODO: Uncomment it when gbk be added into charsetInfos - // {"1234567", 1234567, 1234567, "gbk", "謬謬謬", 0}, // test char for gbk - // {"123456789", 123456789, 123456789, "gbk", nil, 3}, // invalid 123456789 in gbk - } - for _, v := range tbl { + {"65", 66, 67.5, "utf8", "ABD", 0}, // float + {"65", 16740, 67.5, "utf8", "AAdD", 0}, // large num + {"65", -1, 67.5, nil, "A\xff\xff\xff\xffD", 0}, // negative int + {"a", -1, 67.5, nil, "\x00\xff\xff\xff\xffD", 0}, // invalid 'a' + {"65", -1, 67.5, "utf8", nil, 1}, // with utf8, return nil + {"a", -1, 67.5, "utf8", nil, 1}, // with utf8, return nil + {"1234567", 1234567, 1234567, "gbk", "\u0012謬\u0012謬\u0012謬", 0}, // test char for gbk + {"123456789", 123456789, 123456789, "gbk", nil, 1}, // invalid 123456789 in gbk + } + run := func(i int, result interface{}, warnCnt int, dts ...interface{}) { fc := funcs[ast.CharFunc] - f, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(v.str, v.iNum, v.fNum, v.charset))) - require.NoError(t, err) - require.NotNil(t, f) + f, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(dts...))) + require.NoError(t, err, i) + require.NotNil(t, f, i) r, err := evalBuiltinFunc(f, chunk.Row{}) - require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(v.result), r) - if v.warnings != 0 { - warnings := ctx.GetSessionVars().StmtCtx.GetWarnings() - require.Equal(t, v.warnings, len(warnings)) + require.NoError(t, err, i) + testutil.DatumEqual(t, types.NewDatum(result), r, i) + if warnCnt != 0 { + warnings := ctx.GetSessionVars().StmtCtx.TruncateWarnings(0) + require.Equal(t, warnCnt, len(warnings), fmt.Sprintf("%d: %v", i, warnings)) } } + for i, v := range tbl { + run(i, v.result, v.warnings, v.str, v.iNum, v.fNum, v.charset) + } + // char() returns null only when the sql_mode is strict. + ctx.GetSessionVars().StrictSQLMode = true + run(-1, nil, 1, 123456, "utf8") + ctx.GetSessionVars().StrictSQLMode = false + run(-2, string([]byte{1}), 1, 123456, "utf8") } func TestCharLength(t *testing.T) { @@ -1462,7 +1462,7 @@ func TestCharLength(t *testing.T) { require.NoError(t, err) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(v.result), r) + testutil.DatumEqual(t, types.NewDatum(v.result), r) } // Test binary string @@ -1489,7 +1489,7 @@ func TestCharLength(t *testing.T) { require.NoError(t, err) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(v.result), r) + testutil.DatumEqual(t, types.NewDatum(v.result), r) } } @@ -1517,7 +1517,7 @@ func TestFindInSet(t *testing.T) { require.NoError(t, err) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c.ret), r, fmt.Sprintf("FindInSet(%s, %s)", c.str, c.strlst)) + testutil.DatumEqual(t, types.NewDatum(c.ret), r, fmt.Sprintf("FindInSet(%s, %s)", c.str, c.strlst)) } } @@ -1552,7 +1552,7 @@ func TestField(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c.ret), r) + testutil.DatumEqual(t, types.NewDatum(c.ret), r) } } @@ -1860,7 +1860,7 @@ func TestMakeSet(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c.ret), r) + testutil.DatumEqual(t, types.NewDatum(c.ret), r) } } @@ -1991,7 +1991,7 @@ func TestFormat(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.ret), r) + testutil.DatumEqual(t, types.NewDatum(tt.ret), r) } origConfig := ctx.GetSessionVars().StmtCtx.TruncateAsWarning @@ -2002,7 +2002,7 @@ func TestFormat(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(tt.ret), r, fmt.Sprintf("test %v", tt)) + testutil.DatumEqual(t, types.NewDatum(tt.ret), r, fmt.Sprintf("test %v", tt)) if tt.warnings > 0 { warnings := ctx.GetSessionVars().StmtCtx.GetWarnings() require.Lenf(t, warnings, tt.warnings, "test %v", tt) @@ -2018,22 +2018,22 @@ func TestFormat(t *testing.T) { require.NoError(t, err) require.NotNil(t, f2) r2, err := evalBuiltinFunc(f2, chunk.Row{}) - trequire.DatumEqual(t, types.NewDatum(errors.New("not implemented")), types.NewDatum(err)) - trequire.DatumEqual(t, types.NewDatum(formatTests2.ret), r2) + testutil.DatumEqual(t, types.NewDatum(errors.New("not implemented")), types.NewDatum(err)) + testutil.DatumEqual(t, types.NewDatum(formatTests2.ret), r2) f3, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(formatTests3.number, formatTests3.precision, formatTests3.locale))) require.NoError(t, err) require.NotNil(t, f3) r3, err := evalBuiltinFunc(f3, chunk.Row{}) - trequire.DatumEqual(t, types.NewDatum(errors.New("not support for the specific locale")), types.NewDatum(err)) - trequire.DatumEqual(t, types.NewDatum(formatTests3.ret), r3) + testutil.DatumEqual(t, types.NewDatum(errors.New("not support for the specific locale")), types.NewDatum(err)) + testutil.DatumEqual(t, types.NewDatum(formatTests3.ret), r3) f4, err := fc.getFunction(ctx, datumsToConstants(types.MakeDatums(formatTests4.number, formatTests4.precision, formatTests4.locale))) require.NoError(t, err) require.NotNil(t, f4) r4, err := evalBuiltinFunc(f4, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(formatTests4.ret), r4) + testutil.DatumEqual(t, types.NewDatum(formatTests4.ret), r4) warnings := ctx.GetSessionVars().StmtCtx.GetWarnings() require.Equal(t, 3, len(warnings)) for i := 0; i < 3; i++ { @@ -2187,9 +2187,6 @@ func TestInsert(t *testing.T) { } func TestOrd(t *testing.T) { - // TODO: Remove this and enable test parallel after new charset enabled - collate.SetCharsetFeatEnabledForTest(true) - defer collate.SetCharsetFeatEnabledForTest(false) ctx := createContext(t) cases := []struct { args interface{} @@ -2205,11 +2202,11 @@ func TestOrd(t *testing.T) { {2.3, 50, "", false, false}, {nil, 0, "", true, false}, {"", 0, "", false, false}, - {"你好", 14990752, "", false, false}, - {"ã«ã»ã‚“", 14909867, "", false, false}, - {"한국", 15570332, "", false, false}, - {"ðŸ‘", 4036989325, "", false, false}, - {"×", 55184, "", false, false}, + {"你好", 14990752, "utf8mb4", false, false}, + {"ã«ã»ã‚“", 14909867, "utf8mb4", false, false}, + {"한국", 15570332, "utf8mb4", false, false}, + {"ðŸ‘", 4036989325, "utf8mb4", false, false}, + {"×", 55184, "utf8mb4", false, false}, {"abc", 97, "gbk", false, false}, {"一二三", 53947, "gbk", false, false}, {"àáèé", 43172, "gbk", false, false}, @@ -2256,7 +2253,7 @@ func TestElt(t *testing.T) { require.NoError(t, err) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c.ret), r) + testutil.DatumEqual(t, types.NewDatum(c.ret), r) } } @@ -2317,7 +2314,7 @@ func TestBin(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c["Expected"][0]), r) + testutil.DatumEqual(t, types.NewDatum(c["Expected"][0]), r) } } @@ -2346,7 +2343,7 @@ func TestQuote(t *testing.T) { require.NotNil(t, f) r, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum(c.ret), r) + testutil.DatumEqual(t, types.NewDatum(c.ret), r) } } @@ -2556,16 +2553,16 @@ func TestWeightString(t *testing.T) { {7, "NONE", 0, nil}, {7.0, "NONE", 0, nil}, {"a", "NONE", 0, "a"}, - {"a ", "NONE", 0, "a "}, + {"a ", "NONE", 0, "a"}, {"中", "NONE", 0, "中"}, - {"中 ", "NONE", 0, "中 "}, + {"中 ", "NONE", 0, "中"}, {nil, "CHAR", 5, nil}, {7, "CHAR", 5, nil}, {7.0, "NONE", 0, nil}, - {"a", "CHAR", 5, "a "}, - {"a ", "CHAR", 5, "a "}, - {"中", "CHAR", 5, "中 "}, - {"中 ", "CHAR", 5, "中 "}, + {"a", "CHAR", 5, "a"}, + {"a ", "CHAR", 5, "a"}, + {"中", "CHAR", 5, "中"}, + {"中 ", "CHAR", 5, "中"}, {nil, "BINARY", 5, nil}, {7, "BINARY", 2, "7\x00"}, {7.0, "NONE", 0, nil}, @@ -2665,8 +2662,6 @@ func TestTranslate(t *testing.T) { func TestCIWeightString(t *testing.T) { ctx := createContext(t) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) type weightStringTest struct { str string diff --git a/expression/builtin_string_vec.go b/expression/builtin_string_vec.go index 62c123faf07bd..8232fa36754b1 100644 --- a/expression/builtin_string_vec.go +++ b/expression/builtin_string_vec.go @@ -15,6 +15,7 @@ package expression import ( + "bytes" "encoding/base64" "encoding/hex" "fmt" @@ -30,7 +31,6 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" - "golang.org/x/text/transform" ) func (b *builtinLowerSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { @@ -43,14 +43,24 @@ func (b *builtinLowerSig) vectorized() bool { } func (b *builtinLowerUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - if err := b.args[0].VecEvalString(b.ctx, input, result); err != nil { + n := input.NumRows() + buf, err := b.bufAllocator.get() + if err != nil { return err } - - for i := 0; i < input.NumRows(); i++ { - result.SetRaw(i, []byte(b.encoding.ToLower(result.GetString(i)))) + defer b.bufAllocator.put(buf) + if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { + return err + } + result.ReserveString(n) + enc := charset.FindEncoding(b.args[0].GetType().Charset) + for i := 0; i < n; i++ { + if buf.IsNull(i) { + result.AppendNull() + } else { + result.AppendString(enc.ToLower(buf.GetString(i))) + } } - return nil } @@ -98,7 +108,9 @@ func (b *builtinRepeatSig) vecEvalString(input *chunk.Chunk, result *chunk.Colum str := buf.GetString(i) byteLength := len(str) if uint64(byteLength)*uint64(num) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("repeat", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "repeat", b.maxAllowedPacket); err != nil { + return err + } result.AppendNull() continue } @@ -143,12 +155,23 @@ func (b *builtinStringIsNullSig) vectorized() bool { } func (b *builtinUpperUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - if err := b.args[0].VecEvalString(b.ctx, input, result); err != nil { + n := input.NumRows() + buf, err := b.bufAllocator.get() + if err != nil { return err } - - for i := 0; i < input.NumRows(); i++ { - result.SetRaw(i, []byte(b.encoding.ToUpper(result.GetString(i)))) + defer b.bufAllocator.put(buf) + if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { + return err + } + result.ReserveString(n) + enc := charset.FindEncoding(b.args[0].GetType().Charset) + for i := 0; i < n; i++ { + if buf.IsNull(i) { + result.AppendNull() + } else { + result.AppendString(enc.ToUpper(buf.GetString(i))) + } } return nil } @@ -281,7 +304,10 @@ func (b *builtinSpaceSig) vecEvalString(input *chunk.Chunk, result *chunk.Column num = 0 } if uint64(num) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("space", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "space", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -351,7 +377,10 @@ func (b *builtinConcatSig) vecEvalString(input *chunk.Chunk, result *chunk.Colum } byteBuf = buf.GetBytes(i) if uint64(len(strs[i])+len(byteBuf)) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "concat", b.maxAllowedPacket); err != nil { + return err + } + isNulls[i] = true continue } @@ -578,7 +607,10 @@ func (b *builtinInsertSig) vecEvalString(input *chunk.Chunk, result *chunk.Colum } newstrI := newstr.GetString(i) if uint64(strLength-lengthI+int64(len(newstrI))) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "insert", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -639,7 +671,10 @@ func (b *builtinConcatWSSig) vecEvalString(input *chunk.Chunk, result *chunk.Col targetLengths[i] += len(seps[i]) } if uint64(targetLengths[i]) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat_ws", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "concat_ws", b.maxAllowedPacket); err != nil { + return err + } + isNulls[i] = true continue } @@ -677,49 +712,59 @@ func (b *builtinConvertSig) vecEvalString(input *chunk.Chunk, result *chunk.Colu if err := b.args[0].VecEvalString(b.ctx, input, expr); err != nil { return err } - // Since charset is already validated and set from getFunction(), there's no - // need to get charset from args again. - encoding, _ := charset.Lookup(b.tp.Charset) - // However, if `b.tp.Charset` is abnormally set to a wrong charset, we still - // return with error. - if encoding == nil { - return errUnknownCharacterSet.GenWithStackByArgs(b.tp.Charset) + argTp, resultTp := b.args[0].GetType(), b.tp + result.ReserveString(n) + done := vecEvalStringConvertBinary(result, n, expr, argTp, resultTp) + if done { + return nil } - decoder := encoding.NewDecoder() - isBinaryStr := types.IsBinaryStr(b.args[0].GetType()) - isRetBinary := types.IsBinaryStr(b.tp) - enc := charset.NewEncoding(b.tp.Charset) - if isRetBinary { - enc = charset.NewEncoding(b.args[0].GetType().Charset) + enc := charset.FindEncoding(resultTp.Charset) + encBuf := &bytes.Buffer{} + for i := 0; i < n; i++ { + if expr.IsNull(i) { + result.AppendNull() + continue + } + exprI := expr.GetBytes(i) + if !enc.IsValid(exprI) { + val, _ := enc.Transform(encBuf, exprI, charset.OpReplaceNoErr) + result.AppendBytes(val) + } else { + result.AppendBytes(exprI) + } } + return nil +} - result.ReserveString(n) +func vecEvalStringConvertBinary(result *chunk.Column, n int, expr *chunk.Column, + argTp, resultTp *types.FieldType) (done bool) { + var chs string + var op charset.Op + if types.IsBinaryStr(argTp) { + chs = resultTp.Charset + op = charset.OpDecode + } else if types.IsBinaryStr(resultTp) { + chs = argTp.Charset + op = charset.OpEncode + } else { + return false + } + enc := charset.FindEncoding(chs) + encBuf := &bytes.Buffer{} for i := 0; i < n; i++ { if expr.IsNull(i) { result.AppendNull() continue } - exprI := expr.GetString(i) - if isBinaryStr { - target, _, err := transform.String(decoder, exprI) - if err != nil { - result.AppendNull() - continue - } - result.AppendString(target) + val, err := enc.Transform(encBuf, expr.GetBytes(i), op) + if err != nil { + result.AppendNull() } else { - if isRetBinary { - str, err := enc.EncodeString(exprI) - if err != nil { - return err - } - result.AppendString(str) - continue - } - result.AppendString(string(enc.EncodeInternal(nil, []byte(exprI)))) + result.AppendBytes(val) } + continue } - return nil + return true } func (b *builtinSubstringIndexSig) vectorized() bool { @@ -963,7 +1008,10 @@ func (b *builtinLpadSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) } targetLength := int(i64s[i]) if uint64(targetLength) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "lpad", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -1031,7 +1079,10 @@ func (b *builtinLpadUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Col } targetLength := int(i64s[i]) if uint64(targetLength)*uint64(mysql.MaxBytesOfCharacter) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "lpad", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -1418,7 +1469,10 @@ func (b *builtinRpadSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) } targetLength := int(i64s[i]) if uint64(targetLength) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "rpad", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -1855,7 +1909,10 @@ func (b *builtinInsertUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.C strHead := string(runes[0 : pos-1]) strTail := string(runes[pos+length-1:]) if uint64(len(strHead)+len(newstr)+len(strTail)) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "insert", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -2068,15 +2125,9 @@ func (b *builtinOrdSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) err return err } - charSet := b.args[0].GetType().Charset - ord, err := chooseOrdFunc(charSet) - if err != nil { - return err - } - - enc := charset.NewEncoding(charSet) - var encodedBuf []byte - + enc := charset.FindEncoding(b.args[0].GetType().Charset) + var x [4]byte + encBuf := bytes.NewBuffer(x[:]) result.ResizeInt64(n, false) result.MergeNulls(buf) i64s := result.Int64s() @@ -2084,12 +2135,15 @@ func (b *builtinOrdSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) err if result.IsNull(i) { continue } - str := buf.GetBytes(i) - encoded, err := enc.EncodeFirstChar(encodedBuf, str) + strBytes := buf.GetBytes(i) + w := len(charset.EncodingUTF8Impl.Peek(strBytes)) + val, err := enc.Transform(encBuf, strBytes[:w], charset.OpEncode) if err != nil { - return err + i64s[i] = calcOrd(strBytes[:1]) + continue } - i64s[i] = ord(encoded) + // Only the first character is considered. + i64s[i] = calcOrd(val[:len(enc.Peek(val))]) } return nil } @@ -2231,9 +2285,6 @@ func (b *builtinBitLengthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum return err } - argTp := b.args[0].GetType() - enc := charset.NewEncoding(argTp.Charset) - result.ResizeInt64(n, false) result.MergeNulls(buf) i64s := result.Int64s() @@ -2242,11 +2293,7 @@ func (b *builtinBitLengthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } str := buf.GetBytes(i) - dBytes, err := enc.Encode(nil, str) - if err != nil { - return err - } - i64s[i] = int64(len(dBytes) * 8) + i64s[i] = int64(len(str) * 8) } return nil } @@ -2281,8 +2328,9 @@ func (b *builtinCharSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) for i := 0; i < l-1; i++ { bufint[i] = buf[i].Int64s() } - var resultBytes []byte - enc := charset.NewEncoding(b.tp.Charset) + encBuf := &bytes.Buffer{} + enc := charset.FindEncoding(b.tp.Charset) + hasStrictMode := b.ctx.GetSessionVars().StrictSQLMode for i := 0; i < n; i++ { bigints = bigints[0:0] for j := 0; j < l-1; j++ { @@ -2292,12 +2340,13 @@ func (b *builtinCharSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) bigints = append(bigints, bufint[j][i]) } dBytes := b.convertToBytes(bigints) - - resultBytes, err := enc.Decode(resultBytes, dBytes) + resultBytes, err := enc.Transform(encBuf, dBytes, charset.OpDecode) if err != nil { b.ctx.GetSessionVars().StmtCtx.AppendWarning(err) - result.AppendNull() - continue + if hasStrictMode { + result.AppendNull() + continue + } } result.AppendString(string(resultBytes)) } @@ -2461,7 +2510,10 @@ func (b *builtinToBase64Sig) vecEvalString(input *chunk.Chunk, result *chunk.Col result.AppendNull() continue } else if needEncodeLen > int(b.maxAllowedPacket) { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("to_base64", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "to_base64", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } else if b.tp.Flen == -1 || b.tp.Flen > mysql.MaxBlobWidth { @@ -2550,7 +2602,10 @@ func (b *builtinRpadUTF8Sig) vecEvalString(input *chunk.Chunk, result *chunk.Col } targetLength := int(i64s[i]) if uint64(targetLength)*uint64(mysql.MaxBytesOfCharacter) > b.maxAllowedPacket { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "rpad", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } @@ -2847,7 +2902,10 @@ func (b *builtinFromBase64Sig) vecEvalString(input *chunk.Chunk, result *chunk.C result.AppendNull() continue } else if needDecodeLen > int(b.maxAllowedPacket) { - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("from_base64", b.maxAllowedPacket)) + if err := handleAllowedPacketOverflowed(b.ctx, "from_base64", b.maxAllowedPacket); err != nil { + return err + } + result.AppendNull() continue } diff --git a/expression/builtin_test.go b/expression/builtin_test.go index d5b59c359b700..d9a77a41bb8b2 100644 --- a/expression/builtin_test.go +++ b/expression/builtin_test.go @@ -25,26 +25,25 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/stretchr/testify/require" ) func evalBuiltinFuncConcurrent(f builtinFunc, row chunk.Row) (d types.Datum, err error) { - wg := sync.WaitGroup{} + var wg util.WaitGroupWrapper concurrency := 10 - wg.Add(concurrency) var lock sync.Mutex err = nil for i := 0; i < concurrency; i++ { - go func() { - defer wg.Done() + wg.Run(func() { di, erri := evalBuiltinFunc(f, chunk.Row{}) lock.Lock() if err == nil { d, err = di, erri } lock.Unlock() - }() + }) } wg.Wait() return diff --git a/expression/builtin_time.go b/expression/builtin_time.go index 0c87fe8ec299c..23862fe9f4276 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -39,6 +39,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/parser" "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/oracle" "go.uber.org/zap" @@ -249,7 +250,7 @@ var ( _ builtinFunc = &builtinSubDateDatetimeDecimalSig{} ) -func convertTimeToMysqlTime(t time.Time, fsp int8, roundMode types.RoundMode) (types.Time, error) { +func convertTimeToMysqlTime(t time.Time, fsp int, roundMode types.RoundMode) (types.Time, error) { var tr time.Time var err error if roundMode == types.ModeTruncate { @@ -264,6 +265,13 @@ func convertTimeToMysqlTime(t time.Time, fsp int8, roundMode types.RoundMode) (t return types.NewTime(types.FromGoTime(tr), mysql.TypeDatetime, fsp), nil } +func getDateAddOrSubReturnTypeByUnit(dateType uint8, unit string) uint8 { + if dateType == mysql.TypeDatetime || types.IsClockUnit(unit) { + return mysql.TypeDatetime + } + return mysql.TypeDate +} + type dateFunctionClass struct { baseFunctionClass } @@ -573,7 +581,7 @@ func (b *builtinDurationStringTimeDiffSig) evalDuration(row chunk.Row) (d types. } sc := b.ctx.GetSessionVars().StmtCtx - rhs, _, isDuration, err := convertStringToDuration(sc, rhsStr, int8(b.tp.Decimal)) + rhs, _, isDuration, err := convertStringToDuration(sc, rhsStr, b.tp.Decimal) if err != nil || !isDuration { return d, true, err } @@ -606,7 +614,7 @@ func (b *builtinStringDurationTimeDiffSig) evalDuration(row chunk.Row) (d types. } sc := b.ctx.GetSessionVars().StmtCtx - lhs, _, isDuration, err := convertStringToDuration(sc, lhsStr, int8(b.tp.Decimal)) + lhs, _, isDuration, err := convertStringToDuration(sc, lhsStr, b.tp.Decimal) if err != nil || !isDuration { return d, true, err } @@ -664,7 +672,7 @@ func (b *builtinTimeStringTimeDiffSig) evalDuration(row chunk.Row) (d types.Dura } sc := b.ctx.GetSessionVars().StmtCtx - _, rhs, isDuration, err := convertStringToDuration(sc, rhsStr, int8(b.tp.Decimal)) + _, rhs, isDuration, err := convertStringToDuration(sc, rhsStr, b.tp.Decimal) if err != nil || isDuration { return d, true, err } @@ -697,7 +705,7 @@ func (b *builtinStringTimeTimeDiffSig) evalDuration(row chunk.Row) (d types.Dura } sc := b.ctx.GetSessionVars().StmtCtx - _, lhs, isDuration, err := convertStringToDuration(sc, lhsStr, int8(b.tp.Decimal)) + _, lhs, isDuration, err := convertStringToDuration(sc, lhsStr, b.tp.Decimal) if err != nil || isDuration { return d, true, err } @@ -730,7 +738,7 @@ func (b *builtinStringStringTimeDiffSig) evalDuration(row chunk.Row) (d types.Du } sc := b.ctx.GetSessionVars().StmtCtx - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal lhsDur, lhsTime, lhsIsDuration, err := convertStringToDuration(sc, lhs, fsp) if err != nil { return d, true, err @@ -772,12 +780,12 @@ func (b *builtinNullTimeDiffSig) evalDuration(row chunk.Row) (d types.Duration, // convertStringToDuration converts string to duration, it return types.Time because in some case // it will converts string to datetime. -func convertStringToDuration(sc *stmtctx.StatementContext, str string, fsp int8) (d types.Duration, t types.Time, +func convertStringToDuration(sc *stmtctx.StatementContext, str string, fsp int) (d types.Duration, t types.Time, isDuration bool, err error) { if n := strings.IndexByte(str, '.'); n >= 0 { lenStrFsp := len(str[n+1:]) - if lenStrFsp <= int(types.MaxFsp) { - fsp = mathutil.MaxInt8(int8(lenStrFsp), fsp) + if lenStrFsp <= types.MaxFsp { + fsp = mathutil.Max(lenStrFsp, fsp) } } return types.StrToDuration(sc, str, fsp) @@ -1078,14 +1086,6 @@ func (b *builtinMonthSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, true, handleInvalidTimeError(b.ctx, err) } - if date.IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err = handleInvalidZeroTime(b.ctx, date) - return 0, isNull, err - } - return 0, false, nil - } - return int64(date.Month()), false, nil } @@ -1238,13 +1238,6 @@ func (b *builtinDayOfMonthSig) evalInt(row chunk.Row) (int64, bool, error) { if isNull || err != nil { return 0, true, handleInvalidTimeError(b.ctx, err) } - if arg.IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err = handleInvalidZeroTime(b.ctx, arg) - return 0, isNull, err - } - return 0, false, nil - } return int64(arg.Day()), false, nil } @@ -1284,8 +1277,7 @@ func (b *builtinDayOfWeekSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, true, handleInvalidTimeError(b.ctx, err) } if arg.InvalidZero() { - isNull, err = handleInvalidZeroTime(b.ctx, arg) - return 0, isNull, err + return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) } // 1 is Sunday, 2 is Monday, .... 7 is Saturday return int64(arg.Weekday() + 1), false, nil @@ -1327,8 +1319,7 @@ func (b *builtinDayOfYearSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, isNull, handleInvalidTimeError(b.ctx, err) } if arg.InvalidZero() { - isNull, err := handleInvalidZeroTime(b.ctx, arg) - return 0, isNull, err + return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) } return int64(arg.YearDay()), false, nil @@ -1559,14 +1550,6 @@ func (b *builtinYearSig) evalInt(row chunk.Row) (int64, bool, error) { if isNull || err != nil { return 0, true, handleInvalidTimeError(b.ctx, err) } - - if date.IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err := handleInvalidZeroTime(b.ctx, date) - return 0, isNull, err - } - return 0, false, nil - } return int64(date.Year()), false, nil } @@ -1684,7 +1667,8 @@ func (c *fromUnixTimeFunctionClass) getFunction(ctx sessionctx.Context, args []E argTps = append(argTps, types.ETString) } - isArg0Str := args[0].GetType().EvalType() == types.ETString + arg0Tp := args[0].GetType() + isArg0Str := arg0Tp.EvalType() == types.ETString bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, retTp, argTps...) if err != nil { return nil, err @@ -1697,10 +1681,10 @@ func (c *fromUnixTimeFunctionClass) getFunction(ctx sessionctx.Context, args []E } // Calculate the time fsp. - fsp := int(types.MaxFsp) + fsp := types.MaxFsp if !isArg0Str { - if args[0].GetType().Decimal != types.UnspecifiedLength { - fsp = mathutil.Min(bf.tp.Decimal, args[0].GetType().Decimal) + if arg0Tp.Decimal != types.UnspecifiedLength { + fsp = mathutil.Min(bf.tp.Decimal, arg0Tp.Decimal) } } bf.setDecimalAndFlenForDatetime(fsp) @@ -1710,8 +1694,8 @@ func (c *fromUnixTimeFunctionClass) getFunction(ctx sessionctx.Context, args []E return sig, nil } -func evalFromUnixTime(ctx sessionctx.Context, fsp int8, unixTimeStamp *types.MyDecimal) (res types.Time, isNull bool, err error) { - // 0 <= unixTimeStamp <= INT32_MAX +func evalFromUnixTime(ctx sessionctx.Context, fsp int, unixTimeStamp *types.MyDecimal) (res types.Time, isNull bool, err error) { + // 0 <= unixTimeStamp <= 32536771199.999999 if unixTimeStamp.IsNegative() { return res, true, nil } @@ -1719,7 +1703,9 @@ func evalFromUnixTime(ctx sessionctx.Context, fsp int8, unixTimeStamp *types.MyD if err != nil && !terror.ErrorEqual(err, types.ErrTruncated) { return res, true, err } - if integralPart > int64(math.MaxInt32) { + // The max integralPart should not be larger than 32536771199. + // Refer to https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-28.html + if integralPart > 32536771199 { return res, true, nil } // Split the integral part and fractional part of a decimal timestamp. @@ -1748,7 +1734,7 @@ func evalFromUnixTime(ctx sessionctx.Context, fsp int8, unixTimeStamp *types.MyD sc := ctx.GetSessionVars().StmtCtx tmp := time.Unix(integralPart, fractionalPart).In(sc.TimeZone) - t, err := convertTimeToMysqlTime(tmp, fsp, types.ModeHalfEven) + t, err := convertTimeToMysqlTime(tmp, fsp, types.ModeHalfUp) if err != nil { return res, true, err } @@ -1772,7 +1758,7 @@ func (b *builtinFromUnixTime1ArgSig) evalTime(row chunk.Row) (res types.Time, is if err != nil || isNull { return res, isNull, err } - return evalFromUnixTime(b.ctx, int8(b.tp.Decimal), unixTimeStamp) + return evalFromUnixTime(b.ctx, b.tp.Decimal, unixTimeStamp) } type builtinFromUnixTime2ArgSig struct { @@ -1796,7 +1782,7 @@ func (b *builtinFromUnixTime2ArgSig) evalString(row chunk.Row) (res string, isNu if err != nil || isNull { return "", isNull, err } - t, isNull, err := evalFromUnixTime(b.ctx, int8(b.tp.Decimal), unixTimeStamp) + t, isNull, err := evalFromUnixTime(b.ctx, b.tp.Decimal, unixTimeStamp) if isNull || err != nil { return "", isNull, err } @@ -1852,7 +1838,7 @@ type strToDateFunctionClass struct { baseFunctionClass } -func (c *strToDateFunctionClass) getRetTp(ctx sessionctx.Context, arg Expression) (tp byte, fsp int8) { +func (c *strToDateFunctionClass) getRetTp(ctx sessionctx.Context, arg Expression) (tp byte, fsp int) { tp = mysql.TypeDatetime if _, ok := arg.(*Constant); !ok { return tp, types.MaxFsp @@ -1895,7 +1881,7 @@ func (c *strToDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expr if err != nil { return nil, err } - bf.setDecimalAndFlenForDatetime(int(fsp)) + bf.setDecimalAndFlenForDatetime(fsp) sig = &builtinStrToDateDatetimeSig{bf} sig.setPbCode(tipb.ScalarFuncSig_StrToDateDatetime) case mysql.TypeDuration: @@ -1903,7 +1889,7 @@ func (c *strToDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expr if err != nil { return nil, err } - bf.setDecimalAndFlenForTime(int(fsp)) + bf.setDecimalAndFlenForTime(fsp) sig = &builtinStrToDateDurationSig{bf} sig.setPbCode(tipb.ScalarFuncSig_StrToDateDuration) } @@ -1972,7 +1958,7 @@ func (b *builtinStrToDateDatetimeSig) evalTime(row chunk.Row) (types.Time, bool, return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) } t.SetType(mysql.TypeDatetime) - t.SetFsp(int8(b.tp.Decimal)) + t.SetFsp(b.tp.Decimal) return t, false, nil } @@ -2004,7 +1990,7 @@ func (b *builtinStrToDateDurationSig) evalDuration(row chunk.Row) (types.Duratio if !succ { return types.Duration{}, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) } - t.SetFsp(int8(b.tp.Decimal)) + t.SetFsp(b.tp.Decimal) dur, err := t.ConvertToDuration() return dur, err != nil, err } @@ -2064,7 +2050,7 @@ func (b *builtinSysDateWithFspSig) evalTime(row chunk.Row) (d types.Time, isNull loc := b.ctx.GetSessionVars().Location() now := time.Now().In(loc) - result, err := convertTimeToMysqlTime(now, int8(fsp), types.ModeHalfEven) + result, err := convertTimeToMysqlTime(now, int(fsp), types.ModeHalfUp) if err != nil { return types.ZeroTime, true, err } @@ -2086,7 +2072,7 @@ func (b *builtinSysDateWithoutFspSig) Clone() builtinFunc { func (b *builtinSysDateWithoutFspSig) evalTime(row chunk.Row) (d types.Time, isNull bool, err error) { tz := b.ctx.GetSessionVars().Location() now := time.Now().In(tz) - result, err := convertTimeToMysqlTime(now, 0, types.ModeHalfEven) + result, err := convertTimeToMysqlTime(now, 0, types.ModeHalfUp) if err != nil { return types.ZeroTime, true, err } @@ -2213,7 +2199,7 @@ func (b *builtinCurrentTime1ArgSig) evalDuration(row chunk.Row) (types.Duration, return types.Duration{}, true, err } dur := nowTs.In(tz).Format(types.TimeFSPFormat) - res, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, dur, int8(fsp)) + res, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, dur, int(fsp)) if err != nil { return types.Duration{}, true, err } @@ -2266,14 +2252,14 @@ func (b *builtinTimeSig) evalDuration(row chunk.Row) (res types.Duration, isNull fsp = len(expr) - idx - 1 } - var tmpFsp int8 + var tmpFsp int if tmpFsp, err = types.CheckFsp(fsp); err != nil { return res, isNull, err } - fsp = int(tmpFsp) + fsp = tmpFsp sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseDuration(sc, expr, int8(fsp)) + res, err = types.ParseDuration(sc, expr, fsp) if types.ErrTruncatedWrongVal.Equal(err) { err = sc.HandleTruncate(err) } @@ -2308,7 +2294,7 @@ func (c *timeLiteralFunctionClass) getFunction(ctx sessionctx.Context, args []Ex if err != nil { return nil, err } - bf.setDecimalAndFlenForTime(int(duration.Fsp)) + bf.setDecimalAndFlenForTime(duration.Fsp) sig := &builtinTimeLiteralSig{bf, duration} return sig, nil } @@ -2402,12 +2388,12 @@ func (c *utcTimestampFunctionClass) getFunction(ctx sessionctx.Context, args []E return sig, nil } -func evalUTCTimestampWithFsp(ctx sessionctx.Context, fsp int8) (types.Time, bool, error) { +func evalUTCTimestampWithFsp(ctx sessionctx.Context, fsp int) (types.Time, bool, error) { nowTs, err := getStmtTimestamp(ctx) if err != nil { return types.ZeroTime, true, err } - result, err := convertTimeToMysqlTime(nowTs.UTC(), fsp, types.ModeHalfEven) + result, err := convertTimeToMysqlTime(nowTs.UTC(), fsp, types.ModeHalfUp) if err != nil { return types.ZeroTime, true, err } @@ -2433,13 +2419,13 @@ func (b *builtinUTCTimestampWithArgSig) evalTime(row chunk.Row) (types.Time, boo } if !isNull && num > int64(types.MaxFsp) { - return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v.", num, types.MaxFsp) + return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v", num, types.MaxFsp) } if !isNull && num < int64(types.MinFsp) { - return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", num) + return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6]", num) } - result, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(num)) + result, isNull, err := evalUTCTimestampWithFsp(b.ctx, int(num)) return result, isNull, err } @@ -2456,7 +2442,7 @@ func (b *builtinUTCTimestampWithoutArgSig) Clone() builtinFunc { // evalTime evals UTC_TIMESTAMP(). // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-timestamp func (b *builtinUTCTimestampWithoutArgSig) evalTime(row chunk.Row) (types.Time, bool, error) { - result, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(0)) + result, isNull, err := evalUTCTimestampWithFsp(b.ctx, 0) return result, isNull, err } @@ -2504,7 +2490,7 @@ func GetStmtTimestamp(ctx sessionctx.Context) (time.Time, error) { return tVal.In(tz), nil } -func evalNowWithFsp(ctx sessionctx.Context, fsp int8) (types.Time, bool, error) { +func evalNowWithFsp(ctx sessionctx.Context, fsp int) (types.Time, bool, error) { nowTs, err := getStmtTimestamp(ctx) if err != nil { return types.ZeroTime, true, err @@ -2557,12 +2543,12 @@ func (b *builtinNowWithArgSig) evalTime(row chunk.Row) (types.Time, bool, error) if isNull { fsp = 0 } else if fsp > int64(types.MaxFsp) { - return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v.", fsp, types.MaxFsp) + return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v", fsp, types.MaxFsp) } else if fsp < int64(types.MinFsp) { - return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) + return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsp) } - result, isNull, err := evalNowWithFsp(b.ctx, int8(fsp)) + result, isNull, err := evalNowWithFsp(b.ctx, int(fsp)) return result, isNull, err } @@ -2579,7 +2565,7 @@ func (b *builtinNowWithoutArgSig) Clone() builtinFunc { // evalTime evals NOW() // see: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_now func (b *builtinNowWithoutArgSig) evalTime(row chunk.Row) (types.Time, bool, error) { - result, isNull, err := evalNowWithFsp(b.ctx, int8(0)) + result, isNull, err := evalNowWithFsp(b.ctx, 0) return result, isNull, err } @@ -2690,7 +2676,7 @@ func (b *builtinExtractDatetimeFromStringSig) evalInt(row chunk.Row) (int64, boo } } if dt.IsZero() { - dt.SetFsp(int8(b.args[1].GetType().Decimal)) + dt.SetFsp(b.args[1].GetType().Decimal) if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { isNull, err := handleInvalidZeroTime(b.ctx, dt) return 0, isNull, err @@ -3299,21 +3285,22 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres argTps := []types.EvalType{dateEvalTp, intervalEvalTp, types.ETString} var bf baseBuiltinFunc + unit, _, err := args[2].EvalString(ctx, chunk.Row{}) + if err != nil { + return nil, err + } if dateEvalTp == types.ETDuration { - unit, _, err := args[2].EvalString(ctx, chunk.Row{}) - if err != nil { - return nil, err - } + internalFsp := 0 switch unit { // If the unit has micro second, then the fsp must be the MaxFsp. case "MICROSECOND", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", "HOUR_MICROSECOND", "DAY_MICROSECOND": - internalFsp = int(types.MaxFsp) + internalFsp = types.MaxFsp // If the unit is second, the fsp is related with the arg[1]'s. case "SECOND": - internalFsp = int(types.MaxFsp) + internalFsp = types.MaxFsp if intervalEvalTp != types.ETString { - internalFsp = mathutil.Min(args[1].GetType().Decimal, int(types.MaxFsp)) + internalFsp = mathutil.Min(args[1].GetType().Decimal, types.MaxFsp) } // Otherwise, the fsp should be 0. } @@ -3326,6 +3313,12 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres return nil, err } bf.setDecimalAndFlenForTime(mathutil.Max(arg0Dec, internalFsp)) + } else if dateEvalTp == types.ETString { + bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...) + if err != nil { + return nil, err + } + bf.tp.Flen = mysql.MaxDatetimeFullWidth } else { bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) if err != nil { @@ -3338,10 +3331,17 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres if tp.Decimal > 0 { tp.Flen = tp.Flen + 1 + tp.Decimal } - types.SetBinChsClnFlag(tp) args[0] = BuildCastFunction(ctx, args[0], tp) } bf.setDecimalAndFlenForDatetime(int(types.MaxFsp)) + + if dateEvalTp == types.ETDatetime && args[0].GetType().Tp == mysql.TypeDate { + switch strings.ToUpper(unit) { + // If the unit is YMD, the return type is date. + case "YEAR", "MONTH", "DAY", "YEAR_MONTH": + bf.setDecimalAndFlenForDate() + } + } } switch { @@ -3478,6 +3478,29 @@ func (b *builtinAddDateStringStringSig) evalTime(row chunk.Row) (types.Time, boo return result, isNull || err != nil, err } +func (b *builtinAddDateStringStringSig) evalString(row chunk.Row) (string, bool, error) { + + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), isNull, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.add(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinAddDateStringIntSig struct { baseBuiltinFunc baseDateArithmetical @@ -3511,6 +3534,29 @@ func (b *builtinAddDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool, return result, isNull || err != nil, err } +func (b *builtinAddDateStringIntSig) evalString(row chunk.Row) (string, bool, error) { + + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.add(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinAddDateStringRealSig struct { baseBuiltinFunc baseDateArithmetical @@ -3544,6 +3590,29 @@ func (b *builtinAddDateStringRealSig) evalTime(row chunk.Row) (types.Time, bool, return result, isNull || err != nil, err } +func (b *builtinAddDateStringRealSig) evalString(row chunk.Row) (string, bool, error) { + + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.add(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinAddDateStringDecimalSig struct { baseBuiltinFunc baseDateArithmetical @@ -3577,6 +3646,29 @@ func (b *builtinAddDateStringDecimalSig) evalTime(row chunk.Row) (types.Time, bo return result, isNull || err != nil, err } +func (b *builtinAddDateStringDecimalSig) evalString(row chunk.Row) (string, bool, error) { + + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.add(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinAddDateIntStringSig struct { baseBuiltinFunc baseDateArithmetical @@ -3983,21 +4075,21 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres argTps := []types.EvalType{dateEvalTp, intervalEvalTp, types.ETString} var bf baseBuiltinFunc + unit, _, err := args[2].EvalString(ctx, chunk.Row{}) + if err != nil { + return nil, err + } if dateEvalTp == types.ETDuration { - unit, _, err := args[2].EvalString(ctx, chunk.Row{}) - if err != nil { - return nil, err - } internalFsp := 0 switch unit { // If the unit has micro second, then the fsp must be the MaxFsp. case "MICROSECOND", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", "HOUR_MICROSECOND", "DAY_MICROSECOND": - internalFsp = int(types.MaxFsp) + internalFsp = types.MaxFsp // If the unit is second, the fsp is related with the arg[1]'s. case "SECOND": - internalFsp = int(types.MaxFsp) + internalFsp = types.MaxFsp if intervalEvalTp != types.ETString { - internalFsp = mathutil.Min(args[1].GetType().Decimal, int(types.MaxFsp)) + internalFsp = mathutil.Min(args[1].GetType().Decimal, types.MaxFsp) } // Otherwise, the fsp should be 0. } @@ -4010,6 +4102,12 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres return nil, err } bf.setDecimalAndFlenForTime(mathutil.Max(arg0Dec, internalFsp)) + } else if dateEvalTp == types.ETString { + bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...) + if err != nil { + return nil, err + } + bf.tp.Flen = mysql.MaxDatetimeFullWidth } else { bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) if err != nil { @@ -4022,10 +4120,17 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres if tp.Decimal > 0 { tp.Flen = tp.Flen + 1 + tp.Decimal } - types.SetBinChsClnFlag(tp) args[0] = BuildCastFunction(ctx, args[0], tp) } bf.setDecimalAndFlenForDatetime(int(types.MaxFsp)) + + if dateEvalTp == types.ETDatetime && args[0].GetType().Tp == mysql.TypeDate { + switch strings.ToUpper(unit) { + // If the unit is YMD, the return type is date. + case "YEAR", "MONTH", "DAY", "YEAR_MONTH": + bf.setDecimalAndFlenForDate() + } + } } switch { @@ -4162,6 +4267,28 @@ func (b *builtinSubDateStringStringSig) evalTime(row chunk.Row) (types.Time, boo return result, isNull || err != nil, err } +func (b *builtinSubDateStringStringSig) evalString(row chunk.Row) (string, bool, error) { + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.sub(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinSubDateStringIntSig struct { baseBuiltinFunc baseDateArithmetical @@ -4195,6 +4322,28 @@ func (b *builtinSubDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool, return result, isNull || err != nil, err } +func (b *builtinSubDateStringIntSig) evalString(row chunk.Row) (string, bool, error) { + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.sub(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinSubDateStringRealSig struct { baseBuiltinFunc baseDateArithmetical @@ -4228,6 +4377,27 @@ func (b *builtinSubDateStringRealSig) evalTime(row chunk.Row) (types.Time, bool, return result, isNull || err != nil, err } +func (b *builtinSubDateStringRealSig) evalString(row chunk.Row) (string, bool, error) { + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.sub(b.ctx, date, interval, unit) + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinSubDateStringDecimalSig struct { baseBuiltinFunc baseDateArithmetical @@ -4259,6 +4429,28 @@ func (b *builtinSubDateStringDecimalSig) evalTime(row chunk.Row) (types.Time, bo return result, isNull || err != nil, err } +func (b *builtinSubDateStringDecimalSig) evalString(row chunk.Row) (string, bool, error) { + unit, isNull, err := b.args[2].EvalString(b.ctx, row) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, row, unit) + if isNull || err != nil { + return types.ZeroTime.String(), true, err + } + + result, isNull, err := b.sub(b.ctx, date, interval, unit) + + result.SetType(getDateAddOrSubReturnTypeByUnit(date.Type(), unit)) + return result.String(), isNull, err +} + type builtinSubDateIntStringSig struct { baseBuiltinFunc baseDateArithmetical @@ -5058,7 +5250,7 @@ func (c *timestampLiteralFunctionClass) getFunction(ctx sessionctx.Context, args if err != nil { return nil, err } - bf.setDecimalAndFlenForDatetime(int(tm.Fsp())) + bf.setDecimalAndFlenForDatetime(tm.Fsp()) sig := &builtinTimestampLiteralSig{bf, tm} return sig, nil } @@ -5083,7 +5275,7 @@ func (b *builtinTimestampLiteralSig) evalTime(row chunk.Row) (types.Time, bool, // getFsp4TimeAddSub is used to in function 'ADDTIME' and 'SUBTIME' to evaluate `fsp` for the // second parameter. It's used only if the second parameter is of string type. It's different // from getFsp in that the result of getFsp4TimeAddSub is either 6 or 0. -func getFsp4TimeAddSub(s string) int8 { +func getFsp4TimeAddSub(s string) int { if len(s)-strings.Index(s, ".")-1 == len(s) { return types.MinFsp } @@ -5131,9 +5323,9 @@ func getBf4TimeAddSub(ctx sessionctx.Context, funcName string, args []Expression } switch retTp { case types.ETDatetime: - bf.setDecimalAndFlenForDatetime(mathutil.Min(mathutil.Max(arg0Dec, arg1Dec), int(types.MaxFsp))) + bf.setDecimalAndFlenForDatetime(mathutil.Min(mathutil.Max(arg0Dec, arg1Dec), types.MaxFsp)) case types.ETDuration: - bf.setDecimalAndFlenForTime(mathutil.Min(mathutil.Max(arg0Dec, arg1Dec), int(types.MaxFsp))) + bf.setDecimalAndFlenForTime(mathutil.Min(mathutil.Max(arg0Dec, arg1Dec), types.MaxFsp)) case types.ETString: bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = mysql.TypeString, mysql.MaxDatetimeWidthWithFsp, types.UnspecifiedLength } @@ -5199,21 +5391,16 @@ func strDatetimeSubDuration(sc *stmtctx.StatementContext, d string, arg1 types.D sc.AppendWarning(err) return "", true, nil } - arg1time, err := arg1.ConvertToTime(sc, uint8(types.GetFsp(arg1.String()))) + resultTime, err := arg0.Add(sc, arg1.Neg()) if err != nil { return "", false, err } - tmpDuration := arg0.Sub(sc, &arg1time) fsp := types.MaxFsp - if tmpDuration.MicroSecond() == 0 { + if resultTime.Microsecond() == 0 { fsp = types.MinFsp } - resultDuration, err := tmpDuration.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return "", false, err - } - resultDuration.SetFsp(fsp) - return resultDuration.String(), false, nil + resultTime.SetFsp(fsp) + return resultTime.String(), false, nil } // strDurationSubDuration subtracts duration from duration string, returns a string value. @@ -5556,6 +5743,16 @@ func (b *builtinAddStringAndStringSig) evalString(row chunk.Row) (result string, } return "", true, err } + + check := arg1Str + _, check, err = parser.Number(parser.Space0(check)) + if err == nil { + check, err = parser.Char(check, '-') + if strings.Compare(check, "") != 0 && err == nil { + return "", true, nil + } + } + if isDuration(arg0) { result, err = strDurationAddDuration(sc, arg0, arg1) if err != nil { @@ -5638,7 +5835,7 @@ type convertTzFunctionClass struct { } func (c *convertTzFunctionClass) getDecimal(ctx sessionctx.Context, arg Expression) int { - decimal := int(types.MaxFsp) + decimal := types.MaxFsp if dt, isConstant := arg.(*Constant); isConstant { switch arg.GetType().EvalType() { case types.ETInt: @@ -5652,11 +5849,11 @@ func (c *convertTzFunctionClass) getDecimal(ctx sessionctx.Context, arg Expressi } } } - if decimal > int(types.MaxFsp) { - return int(types.MaxFsp) + if decimal > types.MaxFsp { + return types.MaxFsp } - if decimal < int(types.MinFsp) { - return int(types.MinFsp) + if decimal < types.MinFsp { + return types.MinFsp } return decimal } @@ -5758,7 +5955,7 @@ func (b *builtinConvertTzSig) convertTz(dt types.Time, fromTzStr, toTzStr string } } - return types.NewTime(types.FromGoTime(t.In(toTz)), mysql.TypeDatetime, int8(b.tp.Decimal)), false, nil + return types.NewTime(types.FromGoTime(t.In(toTz)), mysql.TypeDatetime, b.tp.Decimal), false, nil } type makeDateFunctionClass struct { @@ -5885,7 +6082,7 @@ func (b *builtinMakeTimeSig) makeTime(hour int64, minute int64, second float64, second = 59 } fsp := b.tp.Decimal - return types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%02d:%02d:%v", hour, minute, second), int8(fsp)) + return types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%02d:%02d:%v", hour, minute, second), fsp) } // evalDuration evals a builtinMakeTimeIntSig. @@ -6095,11 +6292,6 @@ func (b *builtinQuarterSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, true, handleInvalidTimeError(b.ctx, err) } - if date.IsZero() { - isNull, err := handleInvalidZeroTime(b.ctx, date) - return 0, isNull, err - } - return int64((date.Month() + 2) / 3), false, nil } @@ -6119,10 +6311,10 @@ func (c *secToTimeFunctionClass) getFunction(ctx sessionctx.Context, args []Expr } else { retFsp = argType.Decimal } - if retFsp > int(types.MaxFsp) || retFsp == int(types.UnspecifiedFsp) { - retFsp = int(types.MaxFsp) - } else if retFsp < int(types.MinFsp) { - retFsp = int(types.MinFsp) + if retFsp > types.MaxFsp || retFsp == types.UnspecifiedFsp { + retFsp = types.MaxFsp + } else if retFsp < types.MinFsp { + retFsp = types.MinFsp } bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETReal) if err != nil { @@ -6184,7 +6376,7 @@ func (b *builtinSecToTimeSig) evalDuration(row chunk.Row) (types.Duration, bool, secondDemical = float64(second) + demical var dur types.Duration - dur, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), int8(b.tp.Decimal)) + dur, err = types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), b.tp.Decimal) if err != nil { return types.Duration{}, err != nil, err } @@ -6279,12 +6471,7 @@ func (b *builtinSubDatetimeAndDurationSig) evalTime(row chunk.Row) (types.Time, return types.ZeroDatetime, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - arg1time, err := arg1.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return arg1time, true, err - } - tmpDuration := arg0.Sub(sc, &arg1time) - result, err := tmpDuration.ConvertToTime(sc, arg0.Type()) + result, err := arg0.Add(sc, arg1.Neg()) return result, err != nil, err } @@ -6324,12 +6511,7 @@ func (b *builtinSubDatetimeAndStringSig) evalTime(row chunk.Row) (types.Time, bo } return types.ZeroDatetime, true, err } - arg1time, err := arg1.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return types.ZeroDatetime, true, err - } - tmpDuration := arg0.Sub(sc, &arg1time) - result, err := tmpDuration.ConvertToTime(sc, mysql.TypeDatetime) + result, err := arg0.Add(sc, arg1.Neg()) return result, err != nil, err } @@ -6971,16 +7153,16 @@ func (b *builtinUTCTimeWithArgSig) evalDuration(row chunk.Row) (types.Duration, return types.Duration{}, isNull, err } if fsp > int64(types.MaxFsp) { - return types.Duration{}, true, errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v.", fsp, types.MaxFsp) + return types.Duration{}, true, errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v", fsp, types.MaxFsp) } if fsp < int64(types.MinFsp) { - return types.Duration{}, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) + return types.Duration{}, true, errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsp) } nowTs, err := getStmtTimestamp(b.ctx) if err != nil { return types.Duration{}, true, err } - v, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, nowTs.UTC().Format(types.TimeFSPFormat), int8(fsp)) + v, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, nowTs.UTC().Format(types.TimeFSPFormat), int(fsp)) return v, false, err } @@ -7038,10 +7220,10 @@ func getExpressionFsp(ctx sessionctx.Context, expression Expression) (int, error if isNil || err != nil { return 0, err } - return int(types.GetFsp(str)), nil + return types.GetFsp(str), nil } warpExpr := WrapWithCastAsTime(ctx, expression, types.NewFieldType(mysql.TypeDatetime)) - return mathutil.Min(warpExpr.GetType().Decimal, int(types.MaxFsp)), nil + return mathutil.Min(warpExpr.GetType().Decimal, types.MaxFsp), nil } // tidbParseTsoFunctionClass extracts physical time from a tso @@ -7059,7 +7241,7 @@ func (c *tidbParseTsoFunctionClass) getFunction(ctx sessionctx.Context, args []E return nil, err } - bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = mysql.TypeDate, mysql.MaxDateWidth, int(types.DefaultFsp) + bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = mysql.TypeDate, mysql.MaxDateWidth, types.DefaultFsp sig := &builtinTidbParseTsoSig{bf} return sig, nil } @@ -7235,9 +7417,9 @@ func getFspByIntArg(ctx sessionctx.Context, exps []Expression) (int, error) { return 0, err } if fsp > int64(types.MaxFsp) { - return 0, errors.Errorf("Too-big precision %v specified for 'curtime'. Maximum is %v.", fsp, types.MaxFsp) + return 0, errors.Errorf("Too-big precision %v specified for 'curtime'. Maximum is %v", fsp, types.MaxFsp) } else if fsp < int64(types.MinFsp) { - return 0, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) + return 0, errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsp) } return int(fsp), nil } diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index 425fa976ae587..4d9c610400565 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -30,7 +30,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/mock" @@ -107,7 +107,7 @@ func TestDate(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Expect"][0], v) + testutil.DatumEqual(t, c["Expect"][0], v) } // test year, month and day @@ -137,42 +137,42 @@ func TestDate(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Year"][0], v) + testutil.DatumEqual(t, c["Year"][0], v) fc = funcs[ast.Month] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Month"][0], v) + testutil.DatumEqual(t, c["Month"][0], v) fc = funcs[ast.MonthName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["MonthName"][0], v) + testutil.DatumEqual(t, c["MonthName"][0], v) fc = funcs[ast.DayOfMonth] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfMonth"][0], v) + testutil.DatumEqual(t, c["DayOfMonth"][0], v) fc = funcs[ast.DayOfWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfWeek"][0], v) + testutil.DatumEqual(t, c["DayOfWeek"][0], v) fc = funcs[ast.DayOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfYear"][0], v) + testutil.DatumEqual(t, c["DayOfYear"][0], v) fc = funcs[ast.Weekday] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) @@ -180,35 +180,35 @@ func TestDate(t *testing.T) { require.NotNil(t, f) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekDay"][0], v) + testutil.DatumEqual(t, c["WeekDay"][0], v) fc = funcs[ast.DayName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayName"][0], v) + testutil.DatumEqual(t, c["DayName"][0], v) fc = funcs[ast.Week] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Week"][0], v, fmt.Sprintf("no.%d", ith)) + testutil.DatumEqual(t, c["Week"][0], v, fmt.Sprintf("no.%d", ith)) fc = funcs[ast.WeekOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekOfYear"][0], v) + testutil.DatumEqual(t, c["WeekOfYear"][0], v) fc = funcs[ast.YearWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["YearWeek"][0], v, fmt.Sprintf("no.%d", ith)) + testutil.DatumEqual(t, c["YearWeek"][0], v, fmt.Sprintf("no.%d", ith)) } // test nil @@ -238,42 +238,42 @@ func TestDate(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Year"][0], v) + testutil.DatumEqual(t, c["Year"][0], v) fc = funcs[ast.Month] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Month"][0], v) + testutil.DatumEqual(t, c["Month"][0], v) fc = funcs[ast.MonthName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["MonthName"][0], v) + testutil.DatumEqual(t, c["MonthName"][0], v) fc = funcs[ast.DayOfMonth] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfMonth"][0], v) + testutil.DatumEqual(t, c["DayOfMonth"][0], v) fc = funcs[ast.DayOfWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfWeek"][0], v) + testutil.DatumEqual(t, c["DayOfWeek"][0], v) fc = funcs[ast.DayOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfYear"][0], v) + testutil.DatumEqual(t, c["DayOfYear"][0], v) fc = funcs[ast.Weekday] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) @@ -281,35 +281,35 @@ func TestDate(t *testing.T) { require.NotNil(t, f) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekDay"][0], v) + testutil.DatumEqual(t, c["WeekDay"][0], v) fc = funcs[ast.DayName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayName"][0], v) + testutil.DatumEqual(t, c["DayName"][0], v) fc = funcs[ast.Week] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Week"][0], v) + testutil.DatumEqual(t, c["Week"][0], v) fc = funcs[ast.WeekOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekOfYear"][0], v) + testutil.DatumEqual(t, c["WeekOfYear"][0], v) fc = funcs[ast.YearWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["YearWeek"][0], v) + testutil.DatumEqual(t, c["YearWeek"][0], v) } // test nil with 'NO_ZERO_DATE' set in sql_mode @@ -341,42 +341,42 @@ func TestDate(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Year"][0], v) + testutil.DatumEqual(t, c["Year"][0], v) fc = funcs[ast.Month] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Month"][0], v) + testutil.DatumEqual(t, c["Month"][0], v) fc = funcs[ast.MonthName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["MonthName"][0], v) + testutil.DatumEqual(t, c["MonthName"][0], v) fc = funcs[ast.DayOfMonth] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfMonth"][0], v) + testutil.DatumEqual(t, c["DayOfMonth"][0], v) fc = funcs[ast.DayOfWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfWeek"][0], v) + testutil.DatumEqual(t, c["DayOfWeek"][0], v) fc = funcs[ast.DayOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayOfYear"][0], v) + testutil.DatumEqual(t, c["DayOfYear"][0], v) fc = funcs[ast.Weekday] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) @@ -384,35 +384,35 @@ func TestDate(t *testing.T) { require.NotNil(t, f) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekDay"][0], v) + testutil.DatumEqual(t, c["WeekDay"][0], v) fc = funcs[ast.DayName] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["DayName"][0], v) + testutil.DatumEqual(t, c["DayName"][0], v) fc = funcs[ast.Week] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Week"][0], v) + testutil.DatumEqual(t, c["Week"][0], v) fc = funcs[ast.WeekOfYear] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["WeekOfYear"][0], v) + testutil.DatumEqual(t, c["WeekOfYear"][0], v) fc = funcs[ast.YearWeek] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["YearWeek"][0], v) + testutil.DatumEqual(t, c["YearWeek"][0], v) } } @@ -640,7 +640,7 @@ func TestDateFormat(t *testing.T) { v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) comment := fmt.Sprintf("no.%d\nobtain:%v\nexpect:%v\n", i, v.GetValue(), c["Expect"][0].GetValue()) - trequire.DatumEqual(t, c["Expect"][0], v, comment) + testutil.DatumEqual(t, c["Expect"][0], v, comment) } } @@ -668,35 +668,35 @@ func TestClock(t *testing.T) { require.NoError(t, err) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Hour"][0], v) + testutil.DatumEqual(t, c["Hour"][0], v) fc = funcs[ast.Minute] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Minute"][0], v) + testutil.DatumEqual(t, c["Minute"][0], v) fc = funcs[ast.Second] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Second"][0], v) + testutil.DatumEqual(t, c["Second"][0], v) fc = funcs[ast.MicroSecond] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["MicroSecond"][0], v) + testutil.DatumEqual(t, c["MicroSecond"][0], v) fc = funcs[ast.Time] f, err = fc.getFunction(ctx, datumsToConstants(c["Input"])) require.NoError(t, err) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - trequire.DatumEqual(t, c["Time"][0], v) + testutil.DatumEqual(t, c["Time"][0], v) } // nil @@ -927,6 +927,7 @@ func TestAddTimeSig(t *testing.T) { {"2018-08-16 20:21:01", "00:00:00.000001", "2018-08-16 20:21:01.000001"}, {"1", "xxcvadfgasd", ""}, {"xxcvadfgasd", "1", ""}, + {"2020-05-13 14:01:24", "2020-04-29 05:11:19", ""}, } fc := funcs[ast.AddTime] for _, c := range tbl { @@ -947,7 +948,7 @@ func TestAddTimeSig(t *testing.T) { require.NoError(t, err) res, _, err := du.add(ctx, now, "1", "MICROSECOND") require.NoError(t, err) - require.Equal(t, int8(6), res.Fsp()) + require.Equal(t, 6, res.Fsp()) tbl = []struct { Input string @@ -1035,6 +1036,8 @@ func TestSubTimeSig(t *testing.T) { {"110:00:00", "1 02:00:00", "84:00:00"}, {"2017-01-01 01:01:01.11", "01:01:01.11111", "2016-12-31 23:59:59.998890"}, {"2007-12-31 23:59:59.999999", "1 1:1:1.000002", "2007-12-30 22:58:58.999997"}, + {"1000-01-01 01:00:00.000000", "00:00:00.000001", "1000-01-01 00:59:59.999999"}, + {"1000-01-01 01:00:00.000001", "00:00:00.000001", "1000-01-01 01:00:00"}, {"1", "xxcvadfgasd", ""}, {"xxcvadfgasd", "1", ""}, } @@ -1179,13 +1182,13 @@ func TestSysDate(t *testing.T) { require.Error(t, err) } -func convertToTimeWithFsp(sc *stmtctx.StatementContext, arg types.Datum, tp byte, fsp int8) (d types.Datum, err error) { +func convertToTimeWithFsp(sc *stmtctx.StatementContext, arg types.Datum, tp byte, fsp int) (d types.Datum, err error) { if fsp > types.MaxFsp { fsp = types.MaxFsp } f := types.NewFieldType(tp) - f.Decimal = int(fsp) + f.Decimal = fsp d, err = arg.ConvertTo(sc, f) if err != nil { @@ -1603,7 +1606,7 @@ func TestTimeDiff(t *testing.T) { args []interface{} expectStr string isNil bool - fsp int8 + fsp int flen int getWarning bool }{ @@ -1613,6 +1616,7 @@ func TestTimeDiff(t *testing.T) { {[]interface{}{"10:10:10", "10:9:0"}, "00:01:10", false, 0, 10, false}, {[]interface{}{"2016-12-00 12:00:00", "10:9:0"}, "", true, 0, 10, false}, {[]interface{}{"2016-12-00 12:00:00", ""}, "", true, 0, 10, true}, + {[]interface{}{"00:00:00.000000", "00:00:00.000001"}, "-00:00:00.000001", false, 6, 17, false}, } for _, c := range tests { @@ -1895,7 +1899,7 @@ func TestDateArithFuncs(t *testing.T) { require.NotNil(t, f) v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - require.Equal(t, test.expect, v.GetMysqlTime().String()) + require.Equal(t, test.expect, v.GetString()) } args := types.MakeDatums(date[0], nil, "DAY") @@ -1937,7 +1941,7 @@ func TestDateArithFuncs(t *testing.T) { require.NotNil(t, f) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - require.Equal(t, test.expected, v.GetMysqlTime().String()) + require.Equal(t, test.expected, v.GetString()) } testYears := []struct { @@ -1960,7 +1964,7 @@ func TestDateArithFuncs(t *testing.T) { require.NotNil(t, f) v, err = evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - require.Equal(t, test.expected, v.GetMysqlTime().String()) + require.Equal(t, test.expected, v.GetString()) } testOverflowYears := []struct { @@ -1994,7 +1998,7 @@ func TestDateArithFuncs(t *testing.T) { testDurations := []struct { fc functionClass dur string - fsp int8 + fsp int unit string format interface{} expected string @@ -2576,7 +2580,7 @@ func TestTimeFormat(t *testing.T) { v, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) comment := fmt.Sprintf("no.%d\nobtain:%v\nexpect:%v\n", i, v.GetValue(), c["Expect"][0].GetValue()) - trequire.DatumEqual(t, c["Expect"][0], v, comment) + testutil.DatumEqual(t, c["Expect"][0], v, comment) } } diff --git a/expression/builtin_time_vec.go b/expression/builtin_time_vec.go index 13a0135d267b5..11531945c551d 100644 --- a/expression/builtin_time_vec.go +++ b/expression/builtin_time_vec.go @@ -49,18 +49,6 @@ func (b *builtinMonthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) e if result.IsNull(i) { continue } - if ds[i].IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { - return err - } - result.SetNull(i, isNull) - continue - } - i64s[i] = 0 - continue - } i64s[i] = int64(ds[i].Month()) } return nil @@ -89,18 +77,6 @@ func (b *builtinYearSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) er if result.IsNull(i) { continue } - if ds[i].IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { - return err - } - result.SetNull(i, isNull) - continue - } - i64s[i] = 0 - continue - } i64s[i] = int64(ds[i].Year()) } return nil @@ -162,7 +138,7 @@ func (b *builtinFromUnixTime2ArgSig) vecEvalString(input *chunk.Chunk, result *c result.ReserveString(n) ds := buf1.Decimals() - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if buf1.IsNull(i) || buf2.IsNull(i) { result.AppendNull() @@ -196,7 +172,7 @@ func (b *builtinSysDateWithoutFspSig) vecEvalTime(input *chunk.Chunk, result *ch result.ResizeTime(n, false) times := result.Times() - t, err := convertTimeToMysqlTime(now, 0, types.ModeHalfEven) + t, err := convertTimeToMysqlTime(now, 0, types.ModeHalfUp) if err != nil { return err } @@ -239,17 +215,6 @@ func (b *builtinExtractDatetimeFromStringSig) vecEvalInt(input *chunk.Chunk, res if result.IsNull(i) { continue } - if ds[i].IsZero() { - i64s[i] = 0 - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { - return err - } - result.SetNull(i, isNull) - } - continue - } res, err := types.ExtractDatetimeNum(&ds[i], buf.GetString(i)) if err != nil { return err @@ -451,12 +416,12 @@ func (b *builtinUTCTimeWithArgSig) vecEvalDuration(input *chunk.Chunk, result *c } fsp := i64s[i] if fsp > int64(types.MaxFsp) { - return errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v.", fsp, types.MaxFsp) + return errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v", fsp, types.MaxFsp) } if fsp < int64(types.MinFsp) { - return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) + return errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsp) } - res, err := types.ParseDuration(stmtCtx, utc, int8(fsp)) + res, err := types.ParseDuration(stmtCtx, utc, int(fsp)) if err != nil { return err } @@ -589,15 +554,15 @@ func (b *builtinNowWithArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Col fsps := bufFsp.Int64s() for i := 0; i < n; i++ { - fsp := int8(0) + fsp := 0 if !bufFsp.IsNull(i) { if fsps[i] > int64(types.MaxFsp) { - return errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v.", fsps[i], types.MaxFsp) + return errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v", fsps[i], types.MaxFsp) } if fsps[i] < int64(types.MinFsp) { - return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsps[i]) + return errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsps[i]) } - fsp = int8(fsps[i]) + fsp = int(fsps[i]) } t, isNull, err := evalNowWithFsp(b.ctx, fsp) @@ -810,7 +775,7 @@ func (b *builtinSysDateWithFspSig) vecEvalTime(input *chunk.Chunk, result *chunk if result.IsNull(i) { continue } - t, err := convertTimeToMysqlTime(now, int8(ds[i]), types.ModeHalfEven) + t, err := convertTimeToMysqlTime(now, int(ds[i]), types.ModeHalfUp) if err != nil { return err } @@ -1000,14 +965,6 @@ func (b *builtinQuarterSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) continue } date := ds[i] - if date.IsZero() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { - return err - } - result.SetNull(i, isNull) - continue - } i64s[i] = int64((date.Month() + 2) / 3) } return nil @@ -1133,7 +1090,7 @@ func (b *builtinExtractDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk i64s := result.Int64s() durIs := dur.GoDurations() var duration types.Duration - duration.Fsp = int8(b.args[1].GetType().Decimal) + duration.Fsp = b.args[1].GetType().Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -1197,7 +1154,7 @@ func (b *builtinStrToDateDurationSig) vecEvalDuration(input *chunk.Chunk, result result.SetNull(i, true) continue } - t.SetFsp(int8(b.tp.Decimal)) + t.SetFsp(b.tp.Decimal) dur, err := t.ConvertToDuration() if err != nil { return err @@ -1268,7 +1225,7 @@ func (b *builtinMinuteSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) if result.IsNull(i) { continue } - i64s[i] = int64(buf.GetDuration(i, int(types.UnspecifiedFsp)).Minute()) + i64s[i] = int64(buf.GetDuration(i, types.UnspecifiedFsp).Minute()) } return nil } @@ -1295,7 +1252,7 @@ func (b *builtinSecondSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) if result.IsNull(i) { continue } - i64s[i] = int64(buf.GetDuration(i, int(types.UnspecifiedFsp)).Second()) + i64s[i] = int64(buf.GetDuration(i, types.UnspecifiedFsp).Second()) } return nil } @@ -1306,7 +1263,7 @@ func (b *builtinNowWithoutArgSig) vectorized() bool { func (b *builtinNowWithoutArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() - nowTs, isNull, err := evalNowWithFsp(b.ctx, int8(0)) + nowTs, isNull, err := evalNowWithFsp(b.ctx, 0) if err != nil { return err } @@ -1460,12 +1417,12 @@ func (b *builtinUTCTimestampWithArgSig) vecEvalTime(input *chunk.Chunk, result * } fsp := i64s[i] if fsp > int64(types.MaxFsp) { - return errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v.", fsp, types.MaxFsp) + return errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v", fsp, types.MaxFsp) } if fsp < int64(types.MinFsp) { - return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) + return errors.Errorf("Invalid negative %d specified, must in [0, 6]", fsp) } - res, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(fsp)) + res, isNull, err := evalUTCTimestampWithFsp(b.ctx, int(fsp)) if err != nil { return err } @@ -1544,7 +1501,7 @@ func (b *builtinStrToDateDatetimeSig) vecEvalTime(input *chunk.Chunk, result *ch times := result.Times() sc := b.ctx.GetSessionVars().StmtCtx hasNoZeroDateMode := b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { @@ -1997,7 +1954,7 @@ func (b *builtinSecToTimeSig) vecEvalDuration(input *chunk.Chunk, result *chunk. second = seconds % 60 } secondDemical := float64(second) + demical - duration, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), int8(b.tp.Decimal)) + duration, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), b.tp.Decimal) if err != nil { return err } @@ -2194,11 +2151,10 @@ func (b *builtinDayOfYearSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } if ds[i].InvalidZero() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { + if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil { return err } - result.SetNull(i, isNull) + result.SetNull(i, true) continue } i64s[i] = int64(ds[i].YearDay()) @@ -2224,7 +2180,7 @@ func (b *builtinFromUnixTime1ArgSig) vecEvalTime(input *chunk.Chunk, result *chu result.MergeNulls(buf) ts := result.Times() ds := buf.Decimals() - fsp := int8(b.tp.Decimal) + fsp := b.tp.Decimal for i := 0; i < n; i++ { if result.IsNull(i) { continue @@ -2464,13 +2420,13 @@ func (b *builtinTimeSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Colum fsp = len(expr) - idx - 1 } - var tmpFsp int8 + var tmpFsp int if tmpFsp, err = types.CheckFsp(fsp); err != nil { return err } - fsp = int(tmpFsp) + fsp = tmpFsp - res, err := types.ParseDuration(sc, expr, int8(fsp)) + res, err := types.ParseDuration(sc, expr, fsp) if types.ErrTruncatedWrongVal.Equal(err) { err = sc.HandleTruncate(err) } @@ -2579,11 +2535,10 @@ func (b *builtinDayOfWeekSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colum continue } if ds[i].InvalidZero() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { + if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil { return err } - result.SetNull(i, isNull) + result.SetNull(i, true) continue } i64s[i] = int64(ds[i].Weekday() + 1) @@ -2617,7 +2572,7 @@ func (b *builtinCurrentTime1ArgSig) vecEvalDuration(input *chunk.Chunk, result * result.ResizeGoDuration(n, false) durations := result.GoDurations() for i := 0; i < n; i++ { - res, err := types.ParseDuration(stmtCtx, dur, int8(i64s[i])) + res, err := types.ParseDuration(stmtCtx, dur, int(i64s[i])) if err != nil { return err } @@ -2835,18 +2790,6 @@ func (b *builtinDayOfMonthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Colu if result.IsNull(i) { continue } - if ds[i].IsZero() { - if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() { - isNull, err := handleInvalidZeroTime(b.ctx, ds[i]) - if err != nil { - return err - } - result.SetNull(i, isNull) - continue - } - i64s[i] = 0 - continue - } i64s[i] = int64(ds[i].Day()) } return nil diff --git a/expression/builtin_time_vec_generated.go b/expression/builtin_time_vec_generated.go index 7bc61a0634236..87a89e8208cc6 100644 --- a/expression/builtin_time_vec_generated.go +++ b/expression/builtin_time_vec_generated.go @@ -316,7 +316,7 @@ func (b *builtinAddStringAndDurationSig) vecEvalString(input *chunk.Chunk, resul // calculate sc := b.ctx.GetSessionVars().StmtCtx - fsp1 := int8(b.args[1].GetType().Decimal) + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} var output string var isNull bool @@ -498,8 +498,8 @@ func (b *builtinAddDateAndDurationSig) vecEvalString(input *chunk.Chunk, result // calculate - fsp0 := int8(b.args[0].GetType().Decimal) - fsp1 := int8(b.args[1].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration) @@ -576,7 +576,7 @@ func (b *builtinAddDateAndStringSig) vecEvalString(input *chunk.Chunk, result *c return err } - fsp0 := int8(b.args[0].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration) @@ -677,12 +677,7 @@ func (b *builtinSubDatetimeAndDurationSig) vecEvalTime(input *chunk.Chunk, resul sc := b.ctx.GetSessionVars().StmtCtx arg1Duration := types.Duration{Duration: arg1, Fsp: -1} - arg1time, err := arg1Duration.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return err - } - tmpDuration := arg0.Sub(sc, &arg1time) - output, err := tmpDuration.ConvertToTime(sc, arg0.Type()) + output, err := arg0.Add(sc, arg1Duration.Neg()) if err != nil { return err @@ -751,12 +746,7 @@ func (b *builtinSubDatetimeAndStringSig) vecEvalTime(input *chunk.Chunk, result } return err } - arg1time, err := arg1Duration.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return err - } - tmpDuration := arg0.Sub(sc, &arg1time) - output, err := tmpDuration.ConvertToTime(sc, mysql.TypeDatetime) + output, err := arg0.Add(sc, arg1Duration.Neg()) if err != nil { return err @@ -940,7 +930,7 @@ func (b *builtinSubStringAndDurationSig) vecEvalString(input *chunk.Chunk, resul // calculate sc := b.ctx.GetSessionVars().StmtCtx - fsp1 := int8(b.args[1].GetType().Decimal) + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} var output string var isNull bool @@ -1122,8 +1112,8 @@ func (b *builtinSubDateAndDurationSig) vecEvalString(input *chunk.Chunk, result // calculate - fsp0 := int8(b.args[0].GetType().Decimal) - fsp1 := int8(b.args[1].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Sub(arg1Duration) @@ -1200,7 +1190,7 @@ func (b *builtinSubDateAndStringSig) vecEvalString(input *chunk.Chunk, result *c return err } - fsp0 := int8(b.args[0].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Sub(arg1Duration) @@ -1301,7 +1291,7 @@ func (b *builtinTimeStringTimeDiffSig) vecEvalDuration(input *chunk.Chunk, resul continue } lhsTime := arg0[i] - _, rhsTime, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), int8(b.tp.Decimal)) + _, rhsTime, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -1356,7 +1346,7 @@ func (b *builtinDurationStringTimeDiffSig) vecEvalDuration(input *chunk.Chunk, r continue } lhs.Duration = arg0[i] - rhsDur, _, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), int8(b.tp.Decimal)) + rhsDur, _, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -1460,7 +1450,7 @@ func (b *builtinStringTimeTimeDiffSig) vecEvalDuration(input *chunk.Chunk, resul if result.IsNull(i) { continue } - _, lhsTime, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), int8(b.tp.Decimal)) + _, lhsTime, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -1515,7 +1505,7 @@ func (b *builtinStringDurationTimeDiffSig) vecEvalDuration(input *chunk.Chunk, r if result.IsNull(i) { continue } - lhsDur, _, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), int8(b.tp.Decimal)) + lhsDur, _, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -1571,11 +1561,11 @@ func (b *builtinStringStringTimeDiffSig) vecEvalDuration(input *chunk.Chunk, res if result.IsNull(i) { continue } - lhsDur, lhsTime, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), int8(b.tp.Decimal)) + lhsDur, lhsTime, lhsIsDuration, err := convertStringToDuration(stmtCtx, buf0.GetString(i), b.tp.Decimal) if err != nil { return err } - rhsDur, rhsTime, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), int8(b.tp.Decimal)) + rhsDur, rhsTime, rhsIsDuration, err := convertStringToDuration(stmtCtx, buf1.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -1658,14 +1648,15 @@ func (b *builtinTimeTimeTimeDiffSig) vectorized() bool { return true } -func (b *builtinAddDateStringStringSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinAddDateStringStringSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -1678,24 +1669,38 @@ func (b *builtinAddDateStringStringSig) vecEvalTime(input *chunk.Chunk, result * return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.add(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.add(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -1705,14 +1710,15 @@ func (b *builtinAddDateStringStringSig) vectorized() bool { return true } -func (b *builtinAddDateStringIntSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinAddDateStringIntSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -1725,24 +1731,38 @@ func (b *builtinAddDateStringIntSig) vecEvalTime(input *chunk.Chunk, result *chu return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.add(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.add(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -1752,14 +1772,15 @@ func (b *builtinAddDateStringIntSig) vectorized() bool { return true } -func (b *builtinAddDateStringRealSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinAddDateStringRealSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -1772,24 +1793,38 @@ func (b *builtinAddDateStringRealSig) vecEvalTime(input *chunk.Chunk, result *ch return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.add(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.add(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -1799,14 +1834,15 @@ func (b *builtinAddDateStringRealSig) vectorized() bool { return true } -func (b *builtinAddDateStringDecimalSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinAddDateStringDecimalSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -1819,24 +1855,38 @@ func (b *builtinAddDateStringDecimalSig) vecEvalTime(input *chunk.Chunk, result return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.add(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.add(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -2422,14 +2472,15 @@ func (b *builtinAddDateDurationDecimalSig) vectorized() bool { return true } -func (b *builtinSubDateStringStringSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinSubDateStringStringSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -2442,24 +2493,38 @@ func (b *builtinSubDateStringStringSig) vecEvalTime(input *chunk.Chunk, result * return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.sub(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.sub(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -2469,14 +2534,15 @@ func (b *builtinSubDateStringStringSig) vectorized() bool { return true } -func (b *builtinSubDateStringIntSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinSubDateStringIntSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -2489,24 +2555,38 @@ func (b *builtinSubDateStringIntSig) vecEvalTime(input *chunk.Chunk, result *chu return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.sub(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.sub(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -2516,14 +2596,15 @@ func (b *builtinSubDateStringIntSig) vectorized() bool { return true } -func (b *builtinSubDateStringRealSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinSubDateStringRealSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -2536,24 +2617,38 @@ func (b *builtinSubDateStringRealSig) vecEvalTime(input *chunk.Chunk, result *ch return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.sub(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.sub(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil @@ -2563,14 +2658,15 @@ func (b *builtinSubDateStringRealSig) vectorized() bool { return true } -func (b *builtinSubDateStringDecimalSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error { +func (b *builtinSubDateStringDecimalSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) if err != nil { return err } if isNull { - result.ResizeTime(n, true) + result.ReserveString(n) + result.SetNulls(0, n, true) return nil } @@ -2583,24 +2679,38 @@ func (b *builtinSubDateStringDecimalSig) vecEvalTime(input *chunk.Chunk, result return err } - if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, result); err != nil { + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { return err } - result.MergeNulls(intervalBuf) - resDates := result.Times() + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) for i := 0; i < n; i++ { - if result.IsNull(i) { + if dateBuf.IsNull(i) { + result.AppendNull() continue } - resDate, isNull, err := b.sub(b.ctx, resDates[i], intervalBuf.GetString(i), unit) + resDate, isNull, err := b.sub(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) if err != nil { return err } if isNull { - result.SetNull(i, true) + result.AppendNull() } else { - resDates[i] = resDate + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) } } return nil diff --git a/expression/builtin_time_vec_generated_test.go b/expression/builtin_time_vec_generated_test.go index cd8d2c0571ba8..e41fadeb461d7 100644 --- a/expression/builtin_time_vec_generated_test.go +++ b/expression/builtin_time_vec_generated_test.go @@ -34,7 +34,7 @@ func (g gener) gen() interface{} { if _, ok := result.(string); ok { dg := newDefaultGener(0, types.ETDuration) d := dg.gen().(types.Duration) - if int8(d.Duration)%2 == 0 { + if d.Duration%2 == 0 { d.Fsp = 0 } else { d.Fsp = 1 @@ -287,7 +287,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ ast.AddDate: { // builtinAddDateStringStringSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -297,7 +297,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -307,7 +307,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -317,7 +317,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -327,7 +327,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -337,7 +337,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -347,7 +347,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -357,7 +357,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -367,7 +367,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -377,7 +377,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -387,7 +387,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -397,7 +397,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -407,7 +407,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -417,7 +417,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -427,7 +427,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -437,7 +437,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -447,7 +447,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -457,7 +457,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -467,7 +467,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -477,7 +477,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -488,7 +488,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinAddDateStringIntSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -498,7 +498,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -508,7 +508,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -518,7 +518,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -528,7 +528,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -538,7 +538,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -548,7 +548,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -558,7 +558,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -568,7 +568,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -578,7 +578,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -588,7 +588,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -598,7 +598,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -608,7 +608,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -618,7 +618,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -628,7 +628,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -638,7 +638,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -648,7 +648,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -658,7 +658,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -668,7 +668,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -678,7 +678,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -689,7 +689,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinAddDateStringRealSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -699,7 +699,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -709,7 +709,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -719,7 +719,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -729,7 +729,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -739,7 +739,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -749,7 +749,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -759,7 +759,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -769,7 +769,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -779,7 +779,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -789,7 +789,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -799,7 +799,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -809,7 +809,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -819,7 +819,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -829,7 +829,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -839,7 +839,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -849,7 +849,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -859,7 +859,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -869,7 +869,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -879,7 +879,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -890,7 +890,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinAddDateStringDecimalSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -900,7 +900,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -910,7 +910,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -920,7 +920,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -930,7 +930,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -940,7 +940,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -950,7 +950,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -960,7 +960,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -970,7 +970,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -980,7 +980,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -990,7 +990,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1000,7 +1000,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1010,7 +1010,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1020,7 +1020,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1030,7 +1030,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1040,7 +1040,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1050,7 +1050,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1060,7 +1060,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1070,7 +1070,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -1080,7 +1080,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3506,7 +3506,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ ast.SubDate: { // builtinSubDateStringStringSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3516,7 +3516,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3526,7 +3526,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3536,7 +3536,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3546,7 +3546,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3556,7 +3556,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3566,7 +3566,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3576,7 +3576,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3586,7 +3586,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3596,7 +3596,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3606,7 +3606,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3616,7 +3616,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3626,7 +3626,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3636,7 +3636,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3646,7 +3646,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3656,7 +3656,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3666,7 +3666,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3676,7 +3676,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3686,7 +3686,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3696,7 +3696,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3707,7 +3707,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinSubDateStringIntSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3717,7 +3717,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3727,7 +3727,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3737,7 +3737,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3747,7 +3747,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3757,7 +3757,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3767,7 +3767,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3777,7 +3777,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3787,7 +3787,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3797,7 +3797,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3807,7 +3807,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3817,7 +3817,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3827,7 +3827,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3837,7 +3837,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3847,7 +3847,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3857,7 +3857,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3867,7 +3867,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3877,7 +3877,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3887,7 +3887,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3897,7 +3897,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3908,7 +3908,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinSubDateStringRealSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3918,7 +3918,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3928,7 +3928,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3938,7 +3938,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3948,7 +3948,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3958,7 +3958,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3968,7 +3968,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3978,7 +3978,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3988,7 +3988,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -3998,7 +3998,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4008,7 +4008,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4018,7 +4018,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4028,7 +4028,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4038,7 +4038,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4048,7 +4048,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4058,7 +4058,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4068,7 +4068,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4078,7 +4078,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4088,7 +4088,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4098,7 +4098,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4109,7 +4109,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ }, // builtinSubDateStringDecimalSig { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4119,7 +4119,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4129,7 +4129,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4139,7 +4139,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4149,7 +4149,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4159,7 +4159,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4169,7 +4169,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4179,7 +4179,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4189,7 +4189,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4199,7 +4199,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4209,7 +4209,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4219,7 +4219,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4229,7 +4229,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4239,7 +4239,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4249,7 +4249,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4259,7 +4259,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4269,7 +4269,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4279,7 +4279,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4289,7 +4289,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -4299,7 +4299,7 @@ var vecBuiltinTimeGeneratedCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, diff --git a/expression/builtin_time_vec_test.go b/expression/builtin_time_vec_test.go index 158fcbcc55ed2..3f4adb0635cfa 100644 --- a/expression/builtin_time_vec_test.go +++ b/expression/builtin_time_vec_test.go @@ -217,7 +217,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ }, ast.SubDate: { { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -227,7 +227,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -237,7 +237,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -289,7 +289,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ }, ast.AddDate: { { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -299,7 +299,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -309,7 +309,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, @@ -319,7 +319,7 @@ var vecBuiltinTimeCases = map[string][]vecExprBenchCase{ chunkSize: 128, }, { - retEvalType: types.ETDatetime, + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString}, geners: []dataGenerator{ &dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()}, diff --git a/expression/collation.go b/expression/collation.go index 80a2720c8cfe4..9febc5b423b16 100644 --- a/expression/collation.go +++ b/expression/collation.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" ) @@ -174,7 +175,12 @@ func deriveCoercibilityForColumn(c *Column) Coercibility { if c.RetType.Tp == mysql.TypeNull { return CoercibilityIgnorable } - if c.RetType.EvalType() != types.ETString { + + switch c.RetType.EvalType() { + case types.ETJson: + case types.ETString: + return CoercibilityImplicit + default: return CoercibilityNumeric } return CoercibilityImplicit @@ -182,7 +188,7 @@ func deriveCoercibilityForColumn(c *Column) Coercibility { func deriveCollation(ctx sessionctx.Context, funcName string, args []Expression, retType types.EvalType, argTps ...types.EvalType) (ec *ExprCollation, err error) { switch funcName { - case ast.Concat, ast.ConcatWS, ast.Lower, ast.Lcase, ast.Reverse, ast.Upper, ast.Ucase, ast.Quote, ast.Coalesce: + case ast.Concat, ast.ConcatWS, ast.Lower, ast.Lcase, ast.Reverse, ast.Upper, ast.Ucase, ast.Quote, ast.Coalesce, ast.Greatest, ast.Least: return CheckAndDeriveCollationFromExprs(ctx, funcName, retType, args...) case ast.Left, ast.Right, ast.Repeat, ast.Trim, ast.LTrim, ast.RTrim, ast.Substr, ast.SubstringIndex, ast.Replace, ast.Substring, ast.Mid, ast.Translate: return CheckAndDeriveCollationFromExprs(ctx, funcName, retType, args[0]) @@ -241,7 +247,28 @@ func deriveCollation(ctx sessionctx.Context, funcName string, args []Expression, return ec, nil case ast.Case: // FIXME: case function aggregate collation is not correct. - return CheckAndDeriveCollationFromExprs(ctx, funcName, retType, args...) + // We should only aggregate the `then expression`, + // case ... when ... expression will be rewritten to: + // args: eq scalar func(args: value, condition1), result1, + // eq scalar func(args: value, condition2), result2, + // ... + // else clause + // Or + // args: condition1, result1, + // condition2, result2, + // ... + // else clause + // so, arguments with odd index are the `then expression`. + if argTps[1] == types.ETString { + fieldArgs := make([]Expression, 0) + for i := 1; i < len(args); i += 2 { + fieldArgs = append(fieldArgs, args[i]) + } + if len(args)%2 == 1 { + fieldArgs = append(fieldArgs, args[len(args)-1]) + } + return CheckAndDeriveCollationFromExprs(ctx, funcName, retType, fieldArgs...) + } case ast.Database, ast.User, ast.CurrentUser, ast.Version, ast.CurrentRole, ast.TiDBVersion: chs, coll := charset.GetDefaultCharsetAndCollate() return &ExprCollation{CoercibilitySysconst, UNICODE, chs, coll}, nil @@ -296,6 +323,7 @@ func CheckAndDeriveCollationFromExprs(ctx sessionctx.Context, funcName string, e } func safeConvert(ctx sessionctx.Context, ec *ExprCollation, args ...Expression) bool { + enc := charset.FindEncodingTakeUTF8AsNoop(ec.Charset) for _, arg := range args { if arg.GetType().Charset == ec.Charset { continue @@ -311,7 +339,10 @@ func safeConvert(ctx sessionctx.Context, ec *ExprCollation, args ...Expression) if err != nil { return false } - if !isNull && !isValidString(str, ec.Charset) { + if isNull { + continue + } + if !enc.IsValid(hack.Slice(str)) { return false } } else { @@ -324,25 +355,6 @@ func safeConvert(ctx sessionctx.Context, ec *ExprCollation, args ...Expression) return true } -// isValidString check if str can convert to dstChs charset without data loss. -func isValidString(str string, dstChs string) bool { - switch dstChs { - case charset.CharsetASCII: - return charset.StringValidatorASCII{}.Validate(str) == -1 - case charset.CharsetLatin1: - // For backward compatibility, we do not block SQL like select 'å•Š' = convert('a' using latin1) collate latin1_bin; - return true - case charset.CharsetUTF8, charset.CharsetUTF8MB4: - // String in tidb is actually use utf8mb4 encoding. - return true - case charset.CharsetBinary: - // Convert to binary is always safe. - return true - default: - return charset.StringValidatorOther{Charset: dstChs}.Validate(str) == -1 - } -} - // inferCollation infers collation, charset, coercibility and check the legitimacy. func inferCollation(exprs ...Expression) *ExprCollation { if len(exprs) == 0 { @@ -359,15 +371,24 @@ func inferCollation(exprs ...Expression) *ExprCollation { repertoire := exprs[0].Repertoire() coercibility := exprs[0].Coercibility() dstCharset, dstCollation := exprs[0].GetType().Charset, exprs[0].GetType().Collate + if exprs[0].GetType().EvalType() == types.ETJson { + dstCharset, dstCollation = charset.CharsetUTF8MB4, charset.CollationUTF8MB4 + } unknownCS := false // Aggregate arguments one by one, agg(a, b, c) := agg(agg(a, b), c). for _, arg := range exprs[1:] { + argCharset, argCollation := arg.GetType().Charset, arg.GetType().Collate + // The collation of JSON is always utf8mb4_bin in builtin-func which is same as MySQL + // see details https://github.com/pingcap/tidb/issues/31320#issuecomment-1010599311 + if arg.GetType().EvalType() == types.ETJson { + argCharset, argCollation = charset.CharsetUTF8MB4, charset.CollationUTF8MB4 + } // If one of the arguments is binary charset, we allow it can be used with other charsets. // If they have the same coercibility, let the binary charset one to be the winner because binary has more precedence. - if dstCollation == charset.CollationBin || arg.GetType().Collate == charset.CollationBin { - if coercibility > arg.Coercibility() || (coercibility == arg.Coercibility() && arg.GetType().Collate == charset.CollationBin) { - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + if dstCollation == charset.CollationBin || argCollation == charset.CollationBin { + if coercibility > arg.Coercibility() || (coercibility == arg.Coercibility() && argCollation == charset.CollationBin) { + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation } repertoire |= arg.Repertoire() continue @@ -380,7 +401,7 @@ func inferCollation(exprs ...Expression) *ExprCollation { // 4. constant value is allowed because we can eval and convert it directly. // If we can not aggregate these two collations, we will get CoercibilityNone and wait for an explicit COLLATE clause, if // there is no explicit COLLATE clause, we will get an error. - if dstCharset != arg.GetType().Charset { + if dstCharset != argCharset { switch { case coercibility < arg.Coercibility(): if arg.Repertoire() == ASCII || arg.Coercibility() >= CoercibilitySysconst || isUnicodeCollation(dstCharset) { @@ -388,15 +409,15 @@ func inferCollation(exprs ...Expression) *ExprCollation { continue } case coercibility == arg.Coercibility(): - if (isUnicodeCollation(dstCharset) && !isUnicodeCollation(arg.GetType().Charset)) || (dstCharset == charset.CharsetUTF8MB4 && arg.GetType().Charset == charset.CharsetUTF8) { + if (isUnicodeCollation(dstCharset) && !isUnicodeCollation(argCharset)) || (dstCharset == charset.CharsetUTF8MB4 && argCharset == charset.CharsetUTF8) { repertoire |= arg.Repertoire() continue - } else if (isUnicodeCollation(arg.GetType().Charset) && !isUnicodeCollation(dstCharset)) || (arg.GetType().Charset == charset.CharsetUTF8MB4 && dstCharset == charset.CharsetUTF8) { - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + } else if (isUnicodeCollation(argCharset) && !isUnicodeCollation(dstCharset)) || (argCharset == charset.CharsetUTF8MB4 && dstCharset == charset.CharsetUTF8) { + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation repertoire |= arg.Repertoire() continue } else if repertoire == ASCII && arg.Repertoire() != ASCII { - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation repertoire |= arg.Repertoire() continue } else if repertoire != ASCII && arg.Repertoire() == ASCII { @@ -404,8 +425,8 @@ func inferCollation(exprs ...Expression) *ExprCollation { continue } case coercibility > arg.Coercibility(): - if repertoire == ASCII || coercibility >= CoercibilitySysconst || isUnicodeCollation(arg.GetType().Charset) { - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + if repertoire == ASCII || coercibility >= CoercibilitySysconst || isUnicodeCollation(argCharset) { + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation repertoire |= arg.Repertoire() continue } @@ -420,17 +441,17 @@ func inferCollation(exprs ...Expression) *ExprCollation { // derive to CoercibilityNone and _bin collation. switch { case coercibility == arg.Coercibility(): - if dstCollation == arg.GetType().Collate { + if dstCollation == argCollation { } else if coercibility == CoercibilityExplicit { return nil } else if isBinCollation(dstCollation) { - } else if isBinCollation(arg.GetType().Collate) { - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + } else if isBinCollation(argCollation) { + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation } else { - coercibility, dstCollation, dstCharset = CoercibilityNone, getBinCollation(arg.GetType().Charset), arg.GetType().Charset + coercibility, dstCharset, dstCollation = CoercibilityNone, argCharset, getBinCollation(argCharset) } case coercibility > arg.Coercibility(): - coercibility, dstCharset, dstCollation = arg.Coercibility(), arg.GetType().Charset, arg.GetType().Collate + coercibility, dstCharset, dstCollation = arg.Coercibility(), argCharset, argCollation } repertoire |= arg.Repertoire() } diff --git a/expression/collation_test.go b/expression/collation_test.go index 111fe1241a368..335c55368ec5c 100644 --- a/expression/collation_test.go +++ b/expression/collation_test.go @@ -22,7 +22,6 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" "github.com/stretchr/testify/require" ) @@ -252,6 +251,11 @@ func newColString(chs, coll string) *Column { return column } +func newColJSON() *Column { + column := &Column{RetType: &types.FieldType{Tp: mysql.TypeJSON, Charset: charset.CharsetBinary, Collate: charset.CollationBin}} + return column +} + func newConstInt(coercibility Coercibility) *Constant { constant := &Constant{RetType: &types.FieldType{Tp: mysql.TypeLong, Charset: charset.CharsetBin, Collate: charset.CollationBin}, Value: types.NewDatum(1)} constant.SetCoercibility(coercibility) @@ -508,7 +512,47 @@ func TestDeriveCollation(t *testing.T) { }, { []string{ - ast.Concat, ast.ConcatWS, ast.Coalesce, ast.In, + ast.ExportSet, ast.Elt, ast.MakeSet, + }, + []Expression{ + newColInt(CoercibilityExplicit), + newColJSON(), + newColString(charset.CharsetUTF8MB4, "utf8mb4_unicode_ci"), + }, + []types.EvalType{types.ETInt, types.ETJson}, + types.ETString, + false, + &ExprCollation{CoercibilityImplicit, UNICODE, charset.CharsetUTF8MB4, charset.CollationUTF8MB4}, + }, + { + []string{ + ast.Concat, ast.ConcatWS, ast.Coalesce, ast.Greatest, ast.Least, + }, + []Expression{ + newColString(charset.CharsetGBK, charset.CollationGBKBin), + newColJSON(), + }, + []types.EvalType{types.ETString, types.ETJson}, + types.ETString, + false, + &ExprCollation{CoercibilityImplicit, UNICODE, charset.CharsetUTF8MB4, charset.CollationUTF8MB4}, + }, + { + []string{ + ast.Concat, ast.ConcatWS, ast.Coalesce, ast.Greatest, ast.Least, + }, + []Expression{ + newColJSON(), + newColString(charset.CharsetBinary, charset.CharsetBinary), + }, + []types.EvalType{types.ETJson, types.ETString}, + types.ETString, + false, + &ExprCollation{CoercibilityImplicit, UNICODE, charset.CharsetBinary, charset.CharsetBinary}, + }, + { + []string{ + ast.Concat, ast.ConcatWS, ast.Coalesce, ast.In, ast.Greatest, ast.Least, }, []Expression{ newConstString("a", CoercibilityCoercible, charset.CharsetUTF8MB4, charset.CollationUTF8MB4), @@ -532,6 +576,18 @@ func TestDeriveCollation(t *testing.T) { false, &ExprCollation{CoercibilityCoercible, ASCII, charset.CharsetUTF8MB4, charset.CollationUTF8MB4}, }, + { + []string{ + ast.Lower, ast.Lcase, ast.Reverse, ast.Upper, ast.Ucase, ast.Quote, + }, + []Expression{ + newColJSON(), + }, + []types.EvalType{types.ETString}, + types.ETString, + false, + &ExprCollation{CoercibilityImplicit, UNICODE, charset.CharsetUTF8MB4, charset.CollationUTF8MB4}, + }, { []string{ ast.If, @@ -637,9 +693,6 @@ func TestDeriveCollation(t *testing.T) { } func TestCompareString(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - require.Equal(t, 0, types.CompareString("a", "A", "utf8_general_ci")) require.Equal(t, 0, types.CompareString("À", "A", "utf8_general_ci")) require.Equal(t, 0, types.CompareString("😜", "😃", "utf8_general_ci")) diff --git a/expression/column.go b/expression/column.go index 378eae5bd674a..b30b067fa55f7 100644 --- a/expression/column.go +++ b/expression/column.go @@ -20,6 +20,7 @@ import ( "strings" "github.com/pingcap/errors" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -223,6 +224,8 @@ type Column struct { InOperand bool collationInfo + + CorrelatedColUniqueID int64 } // Equal implements Expression interface. @@ -552,8 +555,8 @@ func ColInfo2Col(cols []*Column, col *model.ColumnInfo) *Column { return nil } -// indexCol2Col finds the corresponding column of the IndexColumn in a column slice. -func indexCol2Col(colInfos []*model.ColumnInfo, cols []*Column, col *model.IndexColumn) *Column { +// IndexCol2Col finds the corresponding column of the IndexColumn in a column slice. +func IndexCol2Col(colInfos []*model.ColumnInfo, cols []*Column, col *model.IndexColumn) *Column { for i, info := range colInfos { if info.Name.L == col.Name.L { if col.Length > 0 && info.FieldType.Flen > col.Length { @@ -576,7 +579,7 @@ func IndexInfo2PrefixCols(colInfos []*model.ColumnInfo, cols []*Column, index *m retCols := make([]*Column, 0, len(index.Columns)) lengths := make([]int, 0, len(index.Columns)) for _, c := range index.Columns { - col := indexCol2Col(colInfos, cols, c) + col := IndexCol2Col(colInfos, cols, c) if col == nil { return retCols, lengths } @@ -598,7 +601,7 @@ func IndexInfo2Cols(colInfos []*model.ColumnInfo, cols []*Column, index *model.I retCols := make([]*Column, 0, len(index.Columns)) lens := make([]int, 0, len(index.Columns)) for _, c := range index.Columns { - col := indexCol2Col(colInfos, cols, c) + col := IndexCol2Col(colInfos, cols, c) if col == nil { retCols = append(retCols, col) lens = append(lens, types.UnspecifiedLength) @@ -662,13 +665,17 @@ func (col *Column) Coercibility() Coercibility { // Repertoire returns the repertoire value which is used to check collations. func (col *Column) Repertoire() Repertoire { - if col.RetType.EvalType() != types.ETString { - return ASCII - } - if col.RetType.Charset == charset.CharsetASCII { + switch col.RetType.EvalType() { + case types.ETJson: + return UNICODE + case types.ETString: + if col.RetType.Charset == charset.CharsetASCII { + return ASCII + } + return UNICODE + default: return ASCII } - return UNICODE } // SortColumns sort columns based on UniqueID. @@ -680,3 +687,31 @@ func SortColumns(cols []*Column) []*Column { }) return sorted } + +// InColumnArray check whether the col is in the cols array +func (col *Column) InColumnArray(cols []*Column) bool { + for _, c := range cols { + if col.Equal(nil, c) { + return true + } + } + return false +} + +// GcColumnExprIsTidbShard check whether the expression is tidb_shard() +func GcColumnExprIsTidbShard(virtualExpr Expression) bool { + if virtualExpr == nil { + return false + } + + f, ok := virtualExpr.(*ScalarFunction) + if !ok { + return false + } + + if f.FuncName.L != ast.TiDBShard { + return false + } + + return true +} diff --git a/expression/column_test.go b/expression/column_test.go index f6fa04e784110..631081a1ebd3a 100644 --- a/expression/column_test.go +++ b/expression/column_test.go @@ -18,6 +18,7 @@ import ( "fmt" "testing" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" @@ -228,3 +229,37 @@ func TestColHybird(t *testing.T) { require.Equal(t, result.GetString(i), v) } } + +func TestInColumnArray(t *testing.T) { + // normal case, col is in column array + col0, col1 := &Column{ID: 0, UniqueID: 0}, &Column{ID: 1, UniqueID: 1} + cols := []*Column{col0, col1} + require.True(t, col0.InColumnArray(cols)) + + // abnormal case, col is not in column array + require.False(t, col0.InColumnArray([]*Column{col1})) + + // abnormal case, input is nil + require.False(t, col0.InColumnArray(nil)) +} + +func TestGcColumnExprIsTidbShard(t *testing.T) { + ctx := mock.NewContext() + + // abnormal case + // nil, not tidb_shard + require.False(t, GcColumnExprIsTidbShard(nil)) + + // `a = 1`, not tidb_shard + ft := types.NewFieldType(mysql.TypeLonglong) + col := &Column{RetType: ft, Index: 0} + d1 := types.NewDatum(1) + con := &Constant{Value: d1, RetType: ft} + expr := NewFunctionInternal(ctx, ast.EQ, ft, col, con) + require.False(t, GcColumnExprIsTidbShard(expr)) + + // normal case + // tidb_shard(a) = 1 + shardExpr := NewFunctionInternal(ctx, ast.TiDBShard, ft, col) + require.True(t, GcColumnExprIsTidbShard(shardExpr)) +} diff --git a/expression/constant.go b/expression/constant.go index 1e5c50a709e9c..31f3733f146c0 100644 --- a/expression/constant.go +++ b/expression/constant.go @@ -32,6 +32,8 @@ import ( func NewOne() *Constant { retT := types.NewFieldType(mysql.TypeTiny) retT.Flag |= mysql.UnsignedFlag // shrink range to avoid integral promotion + retT.Flen = 1 + retT.Decimal = 0 return &Constant{ Value: types.NewDatum(1), RetType: retT, @@ -42,6 +44,8 @@ func NewOne() *Constant { func NewZero() *Constant { retT := types.NewFieldType(mysql.TypeTiny) retT.Flag |= mysql.UnsignedFlag // shrink range to avoid integral promotion + retT.Flen = 1 + retT.Decimal = 0 return &Constant{ Value: types.NewDatum(0), RetType: retT, @@ -50,9 +54,12 @@ func NewZero() *Constant { // NewNull stands for null constant. func NewNull() *Constant { + retT := types.NewFieldType(mysql.TypeTiny) + retT.Flen = 1 + retT.Decimal = 0 return &Constant{ Value: types.NewDatum(nil), - RetType: types.NewFieldType(mysql.TypeTiny), + RetType: retT, } } @@ -227,6 +234,9 @@ func (c *Constant) EvalInt(ctx sessionctx.Context, row chunk.Row) (int64, bool, } else if c.GetType().Hybrid() || dt.Kind() == types.KindString { res, err := dt.ToInt64(ctx.GetSessionVars().StmtCtx) return res, false, err + } else if dt.Kind() == types.KindMysqlBit { + uintVal, err := dt.GetBinaryLiteral().ToInt(ctx.GetSessionVars().StmtCtx) + return int64(uintVal), false, err } return dt.GetInt64(), false, nil } @@ -285,7 +295,7 @@ func (c *Constant) EvalDecimal(ctx sessionctx.Context, row chunk.Row) (*types.My // The decimal may be modified during plan building. _, frac := res.PrecisionAndFrac() if frac < c.GetType().Decimal { - err = res.Round(res, c.GetType().Decimal, types.ModeHalfEven) + err = res.Round(res, c.GetType().Decimal, types.ModeHalfUp) } return res, false, err } diff --git a/expression/constant_test.go b/expression/constant_test.go index 3b01be365121a..37181483e6e79 100644 --- a/expression/constant_test.go +++ b/expression/constant_test.go @@ -488,3 +488,23 @@ func TestGetTypeThreadSafe(t *testing.T) { ft2 := con.GetType() require.NotSame(t, ft1, ft2) } + +func TestSpecificConstant(t *testing.T) { + one := NewOne() + require.Equal(t, one.Value, types.NewDatum(1)) + require.Equal(t, one.RetType.Tp, mysql.TypeTiny) + require.Equal(t, one.RetType.Flen, 1) + require.Equal(t, one.RetType.Decimal, 0) + + zero := NewZero() + require.Equal(t, zero.Value, types.NewDatum(0)) + require.Equal(t, zero.RetType.Tp, mysql.TypeTiny) + require.Equal(t, zero.RetType.Flen, 1) + require.Equal(t, zero.RetType.Decimal, 0) + + null := NewNull() + require.Equal(t, null.Value, types.NewDatum(nil)) + require.Equal(t, null.RetType.Tp, mysql.TypeTiny) + require.Equal(t, null.RetType.Flen, 1) + require.Equal(t, null.RetType.Decimal, 0) +} diff --git a/expression/distsql_builtin.go b/expression/distsql_builtin.go index 47dd46f87b39f..5f344cbad8478 100644 --- a/expression/distsql_builtin.go +++ b/expression/distsql_builtin.go @@ -222,7 +222,15 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti case tipb.ScalarFuncSig_GreatestString: f = &builtinGreatestStringSig{base} case tipb.ScalarFuncSig_GreatestTime: - f = &builtinGreatestTimeSig{base} + f = &builtinGreatestTimeSig{base, false} + case tipb.ScalarFuncSig_GreatestDate: + f = &builtinGreatestTimeSig{base, true} + case tipb.ScalarFuncSig_GreatestCmpStringAsTime: + f = &builtinGreatestCmpStringAsTimeSig{base, false} + case tipb.ScalarFuncSig_GreatestCmpStringAsDate: + f = &builtinGreatestCmpStringAsTimeSig{base, true} + case tipb.ScalarFuncSig_GreatestDuration: + f = &builtinGreatestDurationSig{base} case tipb.ScalarFuncSig_LeastInt: f = &builtinLeastIntSig{base} case tipb.ScalarFuncSig_LeastReal: @@ -232,7 +240,15 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti case tipb.ScalarFuncSig_LeastString: f = &builtinLeastStringSig{base} case tipb.ScalarFuncSig_LeastTime: - f = &builtinLeastTimeSig{base} + f = &builtinLeastTimeSig{base, false} + case tipb.ScalarFuncSig_LeastDate: + f = &builtinLeastTimeSig{base, true} + case tipb.ScalarFuncSig_LeastCmpStringAsTime: + f = &builtinLeastCmpStringAsTimeSig{base, false} + case tipb.ScalarFuncSig_LeastCmpStringAsDate: + f = &builtinLeastCmpStringAsTimeSig{base, true} + case tipb.ScalarFuncSig_LeastDuration: + f = &builtinLeastDurationSig{base} case tipb.ScalarFuncSig_IntervalInt: f = &builtinIntervalIntSig{base, false} // Since interval function won't be pushed down to TiKV, therefore it doesn't matter what value we give to hasNullable case tipb.ScalarFuncSig_IntervalReal: @@ -424,6 +440,8 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinTruncateRealSig{base} case tipb.ScalarFuncSig_TruncateDecimal: f = &builtinTruncateDecimalSig{base} + case tipb.ScalarFuncSig_TruncateUint: + f = &builtinTruncateUintSig{base} case tipb.ScalarFuncSig_LogicalAnd: f = &builtinLogicAndSig{base} case tipb.ScalarFuncSig_LogicalOr: @@ -650,10 +668,10 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinUUIDSig{base} case tipb.ScalarFuncSig_LikeSig: f = &builtinLikeSig{base, nil, false, sync.Once{}} - // case tipb.ScalarFuncSig_RegexpSig: - // f = &builtinRegexpSig{base} - // case tipb.ScalarFuncSig_RegexpUTF8Sig: - // f = &builtinRegexpUTF8Sig{base} + case tipb.ScalarFuncSig_RegexpSig: + f = newBuiltinRegexpSig(base) + case tipb.ScalarFuncSig_RegexpUTF8Sig: + f = newBuiltinRegexpUTF8Sig(base) case tipb.ScalarFuncSig_JsonExtractSig: f = &builtinJSONExtractSig{base} case tipb.ScalarFuncSig_JsonUnquoteSig: @@ -934,6 +952,8 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinCharSig{base} case tipb.ScalarFuncSig_CharLengthUTF8: f = &builtinCharLengthUTF8Sig{base} + case tipb.ScalarFuncSig_CharLength: + f = &builtinCharLengthBinarySig{base} case tipb.ScalarFuncSig_Concat: f = &builtinConcatSig{base, maxAllowedPacket} case tipb.ScalarFuncSig_ConcatWS: @@ -992,6 +1012,8 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinLocate3ArgsSig{base} case tipb.ScalarFuncSig_Lower: f = &builtinLowerSig{base} + case tipb.ScalarFuncSig_LowerUTF8: + f = &builtinLowerUTF8Sig{base} case tipb.ScalarFuncSig_LpadUTF8: f = &builtinLpadUTF8Sig{base, maxAllowedPacket} case tipb.ScalarFuncSig_Lpad: @@ -1050,6 +1072,8 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinUnHexSig{base} case tipb.ScalarFuncSig_Upper: f = &builtinUpperSig{base} + case tipb.ScalarFuncSig_UpperUTF8: + f = &builtinUpperUTF8Sig{base} case tipb.ScalarFuncSig_ToBinary: f = &builtinInternalToBinarySig{base} case tipb.ScalarFuncSig_FromBinary: @@ -1112,6 +1136,8 @@ func PBToExpr(expr *tipb.Expr, tps []*types.FieldType, sc *stmtctx.StatementCont return convertString(expr.Val, expr.FieldType) case tipb.ExprType_Bytes: return &Constant{Value: types.NewBytesDatum(expr.Val), RetType: types.NewFieldType(mysql.TypeString)}, nil + case tipb.ExprType_MysqlBit: + return &Constant{Value: types.NewMysqlBitDatum(expr.Val), RetType: types.NewFieldType(mysql.TypeString)}, nil case tipb.ExprType_Float32: return convertFloat(expr.Val, true) case tipb.ExprType_Float64: @@ -1166,7 +1192,7 @@ func convertTime(data []byte, ftPB *tipb.FieldType, tz *time.Location) (*Constan } var t types.Time t.SetType(ft.Tp) - t.SetFsp(int8(ft.Decimal)) + t.SetFsp(ft.Decimal) err = t.FromPackedUint(v) if err != nil { return nil, err diff --git a/expression/distsql_builtin_test.go b/expression/distsql_builtin_test.go index 5bf90f09bc3cb..7cb7cc972b029 100644 --- a/expression/distsql_builtin_test.go +++ b/expression/distsql_builtin_test.go @@ -793,6 +793,7 @@ func TestEval(t *testing.T) { } func TestPBToExprWithNewCollation(t *testing.T) { + collate.SetNewCollationEnabledForTest(false) sc := new(stmtctx.StatementContext) fieldTps := make([]*types.FieldType, 1) @@ -829,7 +830,6 @@ func TestPBToExprWithNewCollation(t *testing.T) { } collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) for _, cs := range cases { ft := types.NewFieldType(mysql.TypeString) @@ -847,6 +847,28 @@ func TestPBToExprWithNewCollation(t *testing.T) { } } +// Test convert various scalar functions. +func TestPBToScalarFuncExpr(t *testing.T) { + sc := new(stmtctx.StatementContext) + fieldTps := make([]*types.FieldType, 1) + exprs := []*tipb.Expr{ + { + Tp: tipb.ExprType_ScalarFunc, + Sig: tipb.ScalarFuncSig_RegexpSig, + FieldType: ToPBFieldType(newStringFieldType()), + }, + { + Tp: tipb.ExprType_ScalarFunc, + Sig: tipb.ScalarFuncSig_RegexpUTF8Sig, + FieldType: ToPBFieldType(newStringFieldType()), + }, + } + for _, expr := range exprs { + _, err := PBToExpr(expr, fieldTps, sc) + require.NoError(t, err) + } +} + func datumExpr(t *testing.T, d types.Datum) *tipb.Expr { expr := new(tipb.Expr) switch d.Kind() { @@ -963,7 +985,7 @@ func newIntFieldType() *types.FieldType { func newDurFieldType() *types.FieldType { return &types.FieldType{ Tp: mysql.TypeDuration, - Decimal: int(types.DefaultFsp), + Decimal: types.DefaultFsp, } } diff --git a/expression/errors.go b/expression/errors.go index cfadcc6811e02..b30918b35bf5e 100644 --- a/expression/errors.go +++ b/expression/errors.go @@ -89,3 +89,21 @@ func handleDivisionByZeroError(ctx sessionctx.Context) error { sc.AppendWarning(ErrDivisionByZero) return nil } + +// handleAllowedPacketOverflowed reports error or warning depend on the context. +func handleAllowedPacketOverflowed(ctx sessionctx.Context, exprName string, maxAllowedPacketSize uint64) error { + err := errWarnAllowedPacketOverflowed.GenWithStackByArgs(exprName, maxAllowedPacketSize) + sc := ctx.GetSessionVars().StmtCtx + + // insert|update|delete ignore ... + if sc.TruncateAsWarning { + sc.AppendWarning(err) + return nil + } + + if ctx.GetSessionVars().StrictSQLMode && (sc.InInsertStmt || sc.InUpdateStmt || sc.InDeleteStmt) { + return err + } + sc.AppendWarning(err) + return nil +} diff --git a/expression/evaluator_test.go b/expression/evaluator_test.go index 50a27f21f8d48..0da4c2ab2e25c 100644 --- a/expression/evaluator_test.go +++ b/expression/evaluator_test.go @@ -19,7 +19,6 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" @@ -30,12 +29,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestT(t *testing.T) { - CustomVerboseFlag = true - *CustomParallelSuiteFlag = true - TestingT(t) -} - func kindToFieldType(kind byte) types.FieldType { ft := types.FieldType{} switch kind { @@ -110,7 +103,7 @@ func TestSleep(t *testing.T) { fc := funcs[ast.Sleep] // non-strict model - sessVars.StrictSQLMode = false + sessVars.StmtCtx.BadNullAsWarning = true d := make([]types.Datum, 1) f, err := fc.getFunction(ctx, datumsToConstants(d)) require.NoError(t, err) @@ -127,7 +120,7 @@ func TestSleep(t *testing.T) { require.Equal(t, int64(0), ret) // for error case under the strict model - sessVars.StrictSQLMode = true + sessVars.StmtCtx.BadNullAsWarning = false d[0].SetNull() _, err = fc.getFunction(ctx, datumsToConstants(d)) require.NoError(t, err) @@ -552,7 +545,7 @@ func TestUnaryOp(t *testing.T) { require.NoError(t, err) result, err := evalBuiltinFunc(f, chunk.Row{}) require.NoError(t, err) - require.Equal(t, types.NewDatum(tt.result), result, Commentf("%d", i)) + require.Equalf(t, types.NewDatum(tt.result), result, "%d", i) } tbl = []struct { @@ -576,7 +569,7 @@ func TestUnaryOp(t *testing.T) { expect := types.NewDatum(tt.result) ret, err := result.Compare(ctx.GetSessionVars().StmtCtx, &expect, collate.GetBinaryCollator()) require.NoError(t, err) - require.Equal(t, 0, ret, Commentf("%v %s", tt.arg, tt.op)) + require.Equalf(t, 0, ret, "%v %s", tt.arg, tt.op) } } diff --git a/expression/expr_to_pb.go b/expression/expr_to_pb.go index f6796b4c0517c..db89438a7febe 100644 --- a/expression/expr_to_pb.go +++ b/expression/expr_to_pb.go @@ -20,6 +20,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/mysql" + ast "github.com/pingcap/tidb/parser/types" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" @@ -108,6 +109,9 @@ func (pc *PbConverter) encodeDatum(ft *types.FieldType, d types.Datum) (tipb.Exp case types.KindString, types.KindBinaryLiteral: tp = tipb.ExprType_String val = d.GetBytes() + case types.KindMysqlBit: + tp = tipb.ExprType_MysqlBit + val = d.GetBytes() case types.KindBytes: tp = tipb.ExprType_Bytes val = d.GetBytes() @@ -179,7 +183,11 @@ func (pc PbConverter) columnToPBExpr(column *Column) *tipb.Expr { return nil } switch column.GetType().Tp { - case mysql.TypeBit, mysql.TypeSet, mysql.TypeGeometry, mysql.TypeUnspecified: + case mysql.TypeBit: + if !IsPushDownEnabled(ast.TypeStr(column.GetType().Tp), kv.TiKV) { + return nil + } + case mysql.TypeSet, mysql.TypeGeometry, mysql.TypeUnspecified: return nil case mysql.TypeEnum: if !IsPushDownEnabled("enum", kv.UnSpecified) { diff --git a/expression/expr_to_pb_test.go b/expression/expr_to_pb_test.go index 6776a843a3a60..d4c27ba9bca3d 100644 --- a/expression/expr_to_pb_test.go +++ b/expression/expr_to_pb_test.go @@ -28,7 +28,6 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" @@ -131,10 +130,9 @@ func TestColumn2Pb(t *testing.T) { sc := new(stmtctx.StatementContext) client := new(mock.Client) - colExprs = append(colExprs, genColumn(mysql.TypeBit, 1)) - colExprs = append(colExprs, genColumn(mysql.TypeSet, 2)) - colExprs = append(colExprs, genColumn(mysql.TypeGeometry, 4)) - colExprs = append(colExprs, genColumn(mysql.TypeUnspecified, 5)) + colExprs = append(colExprs, genColumn(mysql.TypeSet, 1)) + colExprs = append(colExprs, genColumn(mysql.TypeGeometry, 2)) + colExprs = append(colExprs, genColumn(mysql.TypeUnspecified, 3)) pushed, remained := PushDownExprs(sc, colExprs, client, kv.UnSpecified) require.Len(t, pushed, 0) @@ -169,6 +167,7 @@ func TestColumn2Pb(t *testing.T) { colExprs = append(colExprs, genColumn(mysql.TypeVarString, 22)) colExprs = append(colExprs, genColumn(mysql.TypeString, 23)) colExprs = append(colExprs, genColumn(mysql.TypeEnum, 24)) + colExprs = append(colExprs, genColumn(mysql.TypeBit, 25)) pushed, remained = PushDownExprs(sc, colExprs, client, kv.UnSpecified) require.Len(t, pushed, len(colExprs)) require.Len(t, remained, 0) @@ -176,29 +175,30 @@ func TestColumn2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, colExprs, client) require.NoError(t, err) jsons := []string{ - "{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":2,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAQ=\",\"sig\":0,\"field_type\":{\"tp\":4,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAU=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAY=\",\"sig\":0,\"field_type\":{\"tp\":6,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAc=\",\"sig\":0,\"field_type\":{\"tp\":7,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAg=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAk=\",\"sig\":0,\"field_type\":{\"tp\":9,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAo=\",\"sig\":0,\"field_type\":{\"tp\":10,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAs=\",\"sig\":0,\"field_type\":{\"tp\":11,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAAw=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAA0=\",\"sig\":0,\"field_type\":{\"tp\":13,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAAA8=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABA=\",\"sig\":0,\"field_type\":{\"tp\":245,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABE=\",\"sig\":0,\"field_type\":{\"tp\":246,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABI=\",\"sig\":0,\"field_type\":{\"tp\":249,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABM=\",\"sig\":0,\"field_type\":{\"tp\":250,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABQ=\",\"sig\":0,\"field_type\":{\"tp\":251,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABU=\",\"sig\":0,\"field_type\":{\"tp\":252,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABY=\",\"sig\":0,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABc=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", - "{\"tp\":201,\"val\":\"gAAAAAAAABg=\",\"sig\":0,\"field_type\":{\"tp\":247,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":2,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAQ=\",\"sig\":0,\"field_type\":{\"tp\":4,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAU=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAY=\",\"sig\":0,\"field_type\":{\"tp\":6,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAc=\",\"sig\":0,\"field_type\":{\"tp\":7,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAg=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAk=\",\"sig\":0,\"field_type\":{\"tp\":9,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAo=\",\"sig\":0,\"field_type\":{\"tp\":10,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAs=\",\"sig\":0,\"field_type\":{\"tp\":11,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAAw=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAA0=\",\"sig\":0,\"field_type\":{\"tp\":13,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAAA8=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABA=\",\"sig\":0,\"field_type\":{\"tp\":245,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABE=\",\"sig\":0,\"field_type\":{\"tp\":246,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABI=\",\"sig\":0,\"field_type\":{\"tp\":249,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABM=\",\"sig\":0,\"field_type\":{\"tp\":250,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABQ=\",\"sig\":0,\"field_type\":{\"tp\":251,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABU=\",\"sig\":0,\"field_type\":{\"tp\":252,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABY=\",\"sig\":0,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABc=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABg=\",\"sig\":0,\"field_type\":{\"tp\":247,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":201,\"val\":\"gAAAAAAAABk=\",\"sig\":0,\"field_type\":{\"tp\":16,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", } for i, pbExpr := range pbExprs { require.NotNil(t, pbExprs) @@ -237,13 +237,13 @@ func TestCompareFunc2Pb(t *testing.T) { require.NoError(t, err) require.Len(t, pbExprs, len(compareExprs)) jsons := []string{ - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":100,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":110,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":120,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":130,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":140,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":150,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":160,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":100,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":110,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":120,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":130,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":140,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":150,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":160,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", } for i, pbExpr := range pbExprs { require.NotNil(t, pbExprs) @@ -281,8 +281,8 @@ func TestLikeFunc2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, likeFuncs, client) require.NoError(t, err) results := []string{ - `{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false},{"tp":5,"val":"cGF0dGVybg==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":128,"flen":-1,"decimal":0,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":63,"charset":"binary"},"has_distinct":false}`, - `{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false},{"tp":5,"val":"JWFiYyU=","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":83,"charset":"utf8"},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":128,"flen":-1,"decimal":0,"collate":63,"charset":"binary"},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":63,"charset":"binary"},"has_distinct":false}`, + `{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false},{"tp":5,"val":"cGF0dGVybg==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":128,"flen":-1,"decimal":0,"collate":-83,"charset":"binary"},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":-83,"charset":"binary"},"has_distinct":false}`, + `{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false},{"tp":5,"val":"JWFiYyU=","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8"},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":128,"flen":-1,"decimal":0,"collate":-83,"charset":"binary"},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":-83,"charset":"binary"},"has_distinct":false}`, } for i, pbExpr := range pbExprs { js, err := json.Marshal(pbExpr) @@ -309,11 +309,11 @@ func TestArithmeticalFunc2Pb(t *testing.T) { } jsons := make(map[string]string) - jsons[ast.Plus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":200,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}" - jsons[ast.Minus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":204,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}" - jsons[ast.Mul] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":208,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}" - jsons[ast.Div] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":211,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}" - jsons[ast.Mod] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":215,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}" + jsons[ast.Plus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":200,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}" + jsons[ast.Minus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":204,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}" + jsons[ast.Mul] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":208,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}" + jsons[ast.Div] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":211,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}" + jsons[ast.Mod] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":215,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}" pbExprs, err := ExpressionsToPBList(sc, arithmeticalFuncs, client) require.NoError(t, err) @@ -355,7 +355,7 @@ func TestDateFunc2Pb(t *testing.T) { require.NotNil(t, pbExprs[0]) js, err := json.Marshal(pbExprs[0]) require.NoError(t, err) - require.Equal(t, "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}],\"sig\":6001,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":0,\"decimal\":-1,\"collate\":46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", string(js)) + require.Equal(t, "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}],\"sig\":6001,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":0,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}", string(js)) } func TestLogicalFunc2Pb(t *testing.T) { @@ -382,10 +382,10 @@ func TestLogicalFunc2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, logicalFuncs, client) require.NoError(t, err) jsons := []string{ - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3101,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3102,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3103,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3104,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3101,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3102,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3103,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3104,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", } for i, pbExpr := range pbExprs { js, err := json.Marshal(pbExpr) @@ -418,12 +418,12 @@ func TestBitwiseFunc2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, bitwiseFuncs, client) require.NoError(t, err) jsons := []string{ - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3118,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3119,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3120,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3129,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3130,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3121,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3118,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3119,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3120,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3129,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3130,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3121,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", } for i, pbExpr := range pbExprs { js, err := json.Marshal(pbExpr) @@ -461,9 +461,9 @@ func TestControlFunc2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, controlFuncs, client) require.NoError(t, err) jsons := []string{ - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4208,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":-1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4107,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":24,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4101,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":24,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4208,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":-1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4107,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":24,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4101,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":24,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", "null", } for i, pbExpr := range pbExprs { @@ -493,8 +493,8 @@ func TestOtherFunc2Pb(t *testing.T) { pbExprs, err := ExpressionsToPBList(sc, otherFuncs, client) require.NoError(t, err) jsons := map[string]string{ - ast.Coalesce: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4201,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":0,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", - ast.IsNull: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3116,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false}", + ast.Coalesce: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":4201,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":0,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", + ast.IsNull: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}],\"sig\":3116,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}", } for i, pbExpr := range pbExprs { js, err := json.Marshal(pbExpr) @@ -525,6 +525,16 @@ func TestExprPushDownToFlash(t *testing.T) { require.NoError(t, err) exprs = append(exprs, function) + // lpad + function, err = NewFunction(mock.NewContext(), ast.Lpad, types.NewFieldType(mysql.TypeString), stringColumn, int32Column, stringColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // rpad + function, err = NewFunction(mock.NewContext(), ast.Rpad, types.NewFieldType(mysql.TypeString), stringColumn, int32Column, stringColumn) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.If, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn, intColumn) require.NoError(t, err) exprs = append(exprs, function) @@ -844,11 +854,18 @@ func TestExprPushDownToFlash(t *testing.T) { exprs = append(exprs, function) // Datesub - function, err = NewFunction(mock.NewContext(), ast.DateSub, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, stringColumn) + constStringColumn := new(Constant) + constStringColumn.Value = types.NewStringDatum("day") + constStringColumn.RetType = types.NewFieldType(mysql.TypeString) + function, err = NewFunction(mock.NewContext(), ast.DateSub, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, constStringColumn) require.NoError(t, err) require.Equal(t, tipb.ScalarFuncSig_SubDateDatetimeInt, function.(*ScalarFunction).Function.PbCode()) exprs = append(exprs, function) - function, err = NewFunction(mock.NewContext(), ast.SubDate, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, stringColumn) + function, err = NewFunction(mock.NewContext(), ast.DateSub, types.NewFieldType(mysql.TypeDatetime), stringColumn, intColumn, constStringColumn) + require.NoError(t, err) + require.Equal(t, tipb.ScalarFuncSig_SubDateStringInt, function.(*ScalarFunction).Function.PbCode()) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.SubDate, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, constStringColumn) require.NoError(t, err) require.Equal(t, tipb.ScalarFuncSig_SubDateDatetimeInt, function.(*ScalarFunction).Function.PbCode()) exprs = append(exprs, function) @@ -988,6 +1005,104 @@ func TestExprPushDownToFlash(t *testing.T) { require.NoError(t, err) exprs = append(exprs, function) + // quarter: supported + function, err = NewFunction(mock.NewContext(), ast.Quarter, types.NewFieldType(mysql.TypeLonglong), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // strcmp + function, err = NewFunction(mock.NewContext(), ast.Strcmp, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // DayName: supported + function, err = NewFunction(mock.NewContext(), ast.DayName, types.NewFieldType(mysql.TypeString), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // MonthName: supported + function, err = NewFunction(mock.NewContext(), ast.MonthName, types.NewFieldType(mysql.TypeString), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // regexpUTF8: supported + function, err = NewFunction(mock.NewContext(), ast.Regexp, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // regexp: supported + function, err = NewFunction(mock.NewContext(), ast.Regexp, types.NewFieldType(mysql.TypeLonglong), binaryStringColumn, binaryStringColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // greatest + function, err = NewFunction(mock.NewContext(), ast.Greatest, types.NewFieldType(mysql.TypeLonglong), int32Column, intColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + function, err = NewFunction(mock.NewContext(), ast.Greatest, types.NewFieldType(mysql.TypeDouble), float32Column, intColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // least + function, err = NewFunction(mock.NewContext(), ast.Least, types.NewFieldType(mysql.TypeLonglong), int32Column, intColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + function, err = NewFunction(mock.NewContext(), ast.Least, types.NewFieldType(mysql.TypeDouble), float32Column, intColumn) + require.NoError(t, err) + exprs = append(exprs, function) + // is true + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), int32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), float32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), decimalColumn) + require.NoError(t, err) + exprs = append(exprs, function) + // is true with null + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), int32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), float32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), decimalColumn) + require.NoError(t, err) + exprs = append(exprs, function) + // is false, note seems there is actually no is_false_with_null, so unable to add ut for it + function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), int32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), float32Column) + require.NoError(t, err) + exprs = append(exprs, function) + function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), decimalColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // DayOfWeek + function, err = NewFunction(mock.NewContext(), ast.DayOfWeek, types.NewFieldType(mysql.TypeDatetime), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // DayOfMonth + function, err = NewFunction(mock.NewContext(), ast.DayOfMonth, types.NewFieldType(mysql.TypeDatetime), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // DayOfYear + function, err = NewFunction(mock.NewContext(), ast.DayOfYear, types.NewFieldType(mysql.TypeDatetime), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + + // LastDay + function, err = NewFunction(mock.NewContext(), ast.LastDay, types.NewFieldType(mysql.TypeDatetime), datetimeColumn) + require.NoError(t, err) + exprs = append(exprs, function) + pushed, remained = PushDownExprs(sc, exprs, client, kv.TiFlash) require.Len(t, pushed, len(exprs)) require.Len(t, remained, 0) @@ -1058,14 +1173,16 @@ func TestExprPushDownToTiKV(t *testing.T) { exprs := make([]Expression, 0) //jsonColumn := genColumn(mysql.TypeJSON, 1) - //intColumn := genColumn(mysql.TypeLonglong, 2) + intColumn := genColumn(mysql.TypeLonglong, 2) //realColumn := genColumn(mysql.TypeDouble, 3) //decimalColumn := genColumn(mysql.TypeNewDecimal, 4) stringColumn := genColumn(mysql.TypeString, 5) //datetimeColumn := genColumn(mysql.TypeDatetime, 6) binaryStringColumn := genColumn(mysql.TypeString, 7) + dateColumn := genColumn(mysql.TypeDate, 8) binaryStringColumn.RetType.Collate = charset.CollationBin + // Test exprs that cannot be pushed. function, err := NewFunction(mock.NewContext(), ast.InetAton, types.NewFieldType(mysql.TypeString), stringColumn) require.NoError(t, err) exprs = append(exprs, function) @@ -1101,13 +1218,147 @@ func TestExprPushDownToTiKV(t *testing.T) { pushed, remained := PushDownExprs(sc, exprs, client, kv.TiKV) require.Len(t, pushed, 0) require.Len(t, remained, len(exprs)) + + // Test exprs that can be pushed. + exprs = exprs[:0] + pushed = pushed[:0] + remained = remained[:0] + + substringRelated := []string{ast.Substr, ast.Substring, ast.Mid} + for _, exprName := range substringRelated { + function, err = NewFunction(mock.NewContext(), exprName, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, intColumn) + require.NoError(t, err) + exprs = append(exprs, function) + } + + testcases := []struct { + functionName string + retType *types.FieldType + args []Expression + }{ + { + functionName: ast.CharLength, + retType: types.NewFieldType(mysql.TypeString), + args: []Expression{stringColumn}, + }, + { + functionName: ast.Sin, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Asin, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Cos, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Acos, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Atan, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Cot, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + { + functionName: ast.Atan2, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn, intColumn}, + }, + { + functionName: ast.DateFormat, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn, stringColumn}, + }, + { + functionName: ast.Hour, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.Minute, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.Second, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.Month, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.MicroSecond, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.PI, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{}, + }, + { + functionName: ast.Round, + retType: types.NewFieldType(mysql.TypeDouble), + args: []Expression{intColumn}, + }, + //{ + // functionName: ast.Truncate, + // retType: types.NewFieldType(mysql.TypeDouble), + // args: []Expression{intColumn, intColumn}, + //}, + { + functionName: ast.Date, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.Week, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn}, + }, + { + functionName: ast.DateDiff, + retType: types.NewFieldType(mysql.TypeDate), + args: []Expression{dateColumn, dateColumn}, + }, + { + functionName: ast.Mod, + retType: types.NewFieldType(mysql.TypeInt24), + args: []Expression{intColumn, intColumn}, + }, + } + + for _, tc := range testcases { + function, err = NewFunction(mock.NewContext(), tc.functionName, tc.retType, tc.args...) + require.NoError(t, err) + exprs = append(exprs, function) + } + + pushed, remained = PushDownExprs(sc, exprs, client, kv.TiKV) + require.Len(t, pushed, len(exprs)) + require.Len(t, remained, 0) } func TestExprOnlyPushDownToTiKV(t *testing.T) { sc := new(stmtctx.StatementContext) client := new(mock.Client) - function, err := NewFunction(mock.NewContext(), "dayofyear", types.NewFieldType(mysql.TypeLonglong), genColumn(mysql.TypeDatetime, 1)) + function, err := NewFunction(mock.NewContext(), "weekofyear", types.NewFieldType(mysql.TypeLonglong), genColumn(mysql.TypeDatetime, 1)) require.NoError(t, err) var exprs = make([]Expression, 0) exprs = append(exprs, function) @@ -1137,13 +1388,13 @@ func TestGroupByItem2Pb(t *testing.T) { pbByItem := GroupByItemToPB(sc, client, item) js, err := json.Marshal(pbByItem) require.NoError(t, err) - require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) + require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) item = genColumn(mysql.TypeDouble, 1) pbByItem = GroupByItemToPB(sc, client, item) js, err = json.Marshal(pbByItem) require.NoError(t, err) - require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) + require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) } func TestSortByItem2Pb(t *testing.T) { @@ -1154,25 +1405,22 @@ func TestSortByItem2Pb(t *testing.T) { pbByItem := SortByItemToPB(sc, client, item, false) js, err := json.Marshal(pbByItem) require.NoError(t, err) - require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) + require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) item = genColumn(mysql.TypeDouble, 1) pbByItem = SortByItemToPB(sc, client, item, false) js, err = json.Marshal(pbByItem) require.NoError(t, err) - require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) + require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":false}", string(js)) item = genColumn(mysql.TypeDouble, 1) pbByItem = SortByItemToPB(sc, client, item, true) js, err = json.Marshal(pbByItem) require.NoError(t, err) - require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":true}", string(js)) + require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false},\"desc\":true}", string(js)) } func TestPushCollationDown(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - fc, err := NewFunction(mock.NewContext(), ast.EQ, types.NewFieldType(mysql.TypeUnspecified), genColumn(mysql.TypeVarchar, 0), genColumn(mysql.TypeVarchar, 1)) require.NoError(t, err) client := new(mock.Client) @@ -1197,8 +1445,6 @@ func columnCollation(c *Column, chs, coll string) *Column { } func TestNewCollationsEnabled(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) var colExprs []Expression sc := new(stmtctx.StatementContext) client := new(mock.Client) @@ -1298,7 +1544,7 @@ func TestPushDownSwitcher(t *testing.T) { } var enabled []string for _, funcName := range cases { - args := []Expression{genColumn(mysql.TypeLong, 1)} + args := []Expression{genColumn(mysql.TypeDouble, 1)} fc, err := NewFunction( mock.NewContext(), funcName.name, diff --git a/expression/expression.go b/expression/expression.go index ac0f813269fff..4febd59f557b1 100644 --- a/expression/expression.go +++ b/expression/expression.go @@ -941,6 +941,7 @@ func IsBinaryLiteral(expr Expression) bool { return ok && con.Value.Kind() == types.KindBinaryLiteral } +// supported functions tracked by https://github.com/tikv/tikv/issues/5751 func scalarExprSupportedByTiKV(sf *ScalarFunction) bool { switch sf.FuncName.L { case @@ -949,25 +950,32 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool { // compare functions. ast.LT, ast.LE, ast.EQ, ast.NE, ast.GE, ast.GT, ast.NullEQ, ast.In, ast.IsNull, ast.Like, ast.IsTruthWithoutNull, ast.IsTruthWithNull, ast.IsFalsity, + // ast.Greatest, ast.Least, ast.Interval // arithmetical functions. - ast.Plus, ast.Minus, ast.Mul, ast.Div, ast.Abs, /*ast.Mod,*/ + ast.PI, /* ast.Truncate */ + ast.Plus, ast.Minus, ast.Mul, ast.Div, ast.Abs, ast.Mod, // math functions. ast.Ceil, ast.Ceiling, ast.Floor, ast.Sqrt, ast.Sign, ast.Ln, ast.Log, ast.Log2, ast.Log10, ast.Exp, ast.Pow, // Rust use the llvm math functions, which have different precision with Golang/MySQL(cmath) // open the following switchers if we implement them in coprocessor via `cmath` - // ast.Sin, ast.Asin, ast.Cos, ast.Acos, ast.Tan, ast.Atan, ast.Atan2, ast.Cot, + ast.Sin, ast.Asin, ast.Cos, ast.Acos /* ast.Tan */, ast.Atan, ast.Atan2, ast.Cot, ast.Radians, ast.Degrees, ast.Conv, ast.CRC32, // control flow functions. ast.Case, ast.If, ast.Ifnull, ast.Coalesce, // string functions. - ast.Length, ast.BitLength, ast.Concat, ast.ConcatWS /*ast.Locate,*/, ast.Replace, ast.ASCII, ast.Hex, - ast.Reverse, ast.LTrim, ast.RTrim /*ast.Left,*/, ast.Strcmp, ast.Space, ast.Elt, ast.Field, - InternalFuncFromBinary, InternalFuncToBinary, + // ast.Bin, ast.Unhex, ast.Locate, ast.Ord, ast.Lpad, ast.Rpad, + // ast.Trim, ast.FromBase64, ast.ToBase64, ast.Upper, ast.Lower, ast.InsertFunc, + // ast.MakeSet, ast.SubstringIndex, ast.Instr, ast.Quote, ast.Oct, + // ast.FindInSet, ast.Repeat, + ast.Length, ast.BitLength, ast.Concat, ast.ConcatWS, ast.Replace, ast.ASCII, ast.Hex, + ast.Reverse, ast.LTrim, ast.RTrim, ast.Strcmp, ast.Space, ast.Elt, ast.Field, + InternalFuncFromBinary, InternalFuncToBinary, ast.Mid, ast.Substring, ast.Substr, ast.CharLength, + ast.Right, /* ast.Left */ // json functions. ast.JSONType, ast.JSONExtract, ast.JSONObject, ast.JSONArray, ast.JSONMerge, ast.JSONSet, @@ -976,10 +984,17 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool { ast.JSONUnquote, // date functions. - ast.DateFormat, ast.FromDays /*ast.ToDays,*/, ast.DayOfYear, ast.DayOfMonth, ast.Year, ast.Month, - // FIXME: the coprocessor cannot keep the same behavior with TiDB in current compute framework - // ast.Hour, ast.Minute, ast.Second, ast.MicroSecond, ast.DayName, + ast.Date, ast.Week /* ast.YearWeek, ast.ToSeconds */, ast.DateDiff, + /* ast.TimeDiff, ast.AddTime, ast.SubTime, */ + ast.MonthName, ast.MakeDate, ast.TimeToSec, ast.MakeTime, + ast.DateFormat, + ast.Hour, ast.Minute, ast.Second, ast.MicroSecond, ast.Month, + /* ast.DayName */ ast.DayOfMonth, ast.DayOfWeek, ast.DayOfYear, + /* ast.Weekday */ ast.WeekOfYear, ast.Year, + ast.FromDays, /* ast.ToDays */ ast.PeriodAdd, ast.PeriodDiff, /*ast.TimestampDiff, ast.DateAdd, ast.FromUnixTime,*/ + /* ast.LastDay */ + ast.Sysdate, // encryption functions. ast.MD5, ast.SHA1, ast.UncompressedLength, @@ -992,11 +1007,11 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool { ast.UUID: return true - - // A special case: Only push down Round by signature case ast.Round: switch sf.Function.PbCode() { case tipb.ScalarFuncSig_RoundReal, tipb.ScalarFuncSig_RoundInt, tipb.ScalarFuncSig_RoundDec: + // We don't push round with frac due to mysql's round with frac has its special behavior: + // https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round return true } case ast.Rand: @@ -1035,19 +1050,20 @@ func scalarExprSupportedByFlash(function *ScalarFunction) bool { } case ast.LogicOr, ast.LogicAnd, ast.UnaryNot, ast.BitNeg, ast.Xor, ast.And, ast.Or, - ast.GE, ast.LE, ast.EQ, ast.NE, ast.LT, ast.GT, ast.In, ast.IsNull, ast.Like, + ast.GE, ast.LE, ast.EQ, ast.NE, ast.LT, ast.GT, ast.In, ast.IsNull, ast.Like, ast.Strcmp, ast.Plus, ast.Minus, ast.Div, ast.Mul, ast.Abs, ast.Mod, ast.If, ast.Ifnull, ast.Case, ast.Concat, ast.ConcatWS, - ast.Date, ast.Year, ast.Month, ast.Day, + ast.Date, ast.Year, ast.Month, ast.Day, ast.Quarter, ast.DayName, ast.MonthName, ast.DateDiff, ast.TimestampDiff, ast.DateFormat, ast.FromUnixTime, + ast.DayOfWeek, ast.DayOfMonth, ast.DayOfYear, ast.LastDay, ast.Sqrt, ast.Log, ast.Log2, ast.Log10, ast.Ln, ast.Exp, ast.Pow, ast.Sign, ast.Radians, ast.Degrees, ast.Conv, ast.CRC32, ast.JSONLength, ast.InetNtoa, ast.InetAton, ast.Inet6Ntoa, ast.Inet6Aton, ast.Coalesce, ast.ASCII, ast.Length, ast.Trim, ast.Position, ast.Format, - ast.LTrim, ast.RTrim, + ast.LTrim, ast.RTrim, ast.Lpad, ast.Rpad, ast.Regexp, ast.Hour, ast.Minute, ast.Second, ast.MicroSecond: switch function.Function.PbCode() { case tipb.ScalarFuncSig_InDuration, @@ -1094,12 +1110,12 @@ func scalarExprSupportedByFlash(function *ScalarFunction) bool { } case ast.DateAdd, ast.AddDate: switch function.Function.PbCode() { - case tipb.ScalarFuncSig_AddDateDatetimeInt: + case tipb.ScalarFuncSig_AddDateDatetimeInt, tipb.ScalarFuncSig_AddDateStringInt, tipb.ScalarFuncSig_AddDateStringReal: return true } case ast.DateSub, ast.SubDate: switch function.Function.PbCode() { - case tipb.ScalarFuncSig_SubDateDatetimeInt: + case tipb.ScalarFuncSig_SubDateDatetimeInt, tipb.ScalarFuncSig_SubDateStringInt, tipb.ScalarFuncSig_SubDateStringReal: return true } case ast.UnixTimestamp: @@ -1136,6 +1152,14 @@ func scalarExprSupportedByFlash(function *ScalarFunction) bool { return true case ast.Sysdate: return true + case ast.Least, ast.Greatest: + switch function.Function.PbCode() { + case tipb.ScalarFuncSig_GreatestInt, tipb.ScalarFuncSig_GreatestReal, + tipb.ScalarFuncSig_LeastInt, tipb.ScalarFuncSig_LeastReal: + return true + } + case ast.IsTruthWithNull, ast.IsTruthWithoutNull, ast.IsFalsity: + return true } return false } @@ -1161,6 +1185,7 @@ func canFuncBePushed(sf *ScalarFunction, storeType kv.StoreType) bool { failpoint.Return(true) } } + failpoint.Return(false) }) ret := false diff --git a/expression/function_traits.go b/expression/function_traits.go index 654e52a50bfab..ed0188b13f36a 100644 --- a/expression/function_traits.go +++ b/expression/function_traits.go @@ -49,6 +49,7 @@ var unFoldableFunctions = map[string]struct{}{ ast.NextVal: {}, ast.LastVal: {}, ast.SetVal: {}, + ast.AnyValue: {}, } // DisableFoldFunctions stores functions which prevent child scope functions from being constant folded. diff --git a/expression/generator/compare_vec.go b/expression/generator/compare_vec.go index 33c3f04800913..dac52ca5a1be1 100644 --- a/expression/generator/compare_vec.go +++ b/expression/generator/compare_vec.go @@ -101,11 +101,7 @@ func (b *builtin{{ .compare.CompareName }}{{ .type.TypeName }}Sig) vecEvalInt(in {{- else if eq .type.ETName "Decimal" }} val := arg0[i].Compare(&arg1[i]) {{- end }} - if val {{ .compare.Operator }} 0 { - i64s[i] = 1 - } else { - i64s[i] = 0 - } + i64s[i] = boolToInt64(val {{ .compare.Operator }} 0) } return nil } diff --git a/expression/generator/other_vec.go b/expression/generator/other_vec.go index cb784436f4c47..70806edec60e9 100644 --- a/expression/generator/other_vec.go +++ b/expression/generator/other_vec.go @@ -279,6 +279,7 @@ package expression import ( "fmt" "math/rand" + "strconv" "testing" "time" @@ -329,7 +330,7 @@ func (g inGener) gen() interface{} { } return *j case types.ETString: - return fmt.Sprint(randNum) + return strconv.FormatInt(randNum, 10) } return randNum } diff --git a/expression/generator/time_vec.go b/expression/generator/time_vec.go index 7933358d33474..5d18b9a4a17b4 100644 --- a/expression/generator/time_vec.go +++ b/expression/generator/time_vec.go @@ -175,12 +175,7 @@ func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result {{ else }} sc := b.ctx.GetSessionVars().StmtCtx arg1Duration := types.Duration{Duration: arg1, Fsp: -1} - arg1time, err := arg1Duration.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return err - } - tmpDuration := arg0.Sub(sc, &arg1time) - output, err := tmpDuration.ConvertToTime(sc, arg0.Type()) + output, err := arg0.Add(sc, arg1Duration.Neg()) {{ end }} if err != nil { return err @@ -205,12 +200,7 @@ func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result } return err } - arg1time, err := arg1Duration.ConvertToTime(sc, mysql.TypeDatetime) - if err != nil { - return err - } - tmpDuration := arg0.Sub(sc, &arg1time) - output, err := tmpDuration.ConvertToTime(sc, mysql.TypeDatetime) + output, err := arg0.Add(sc, arg1Duration.Neg()) {{ end }} if err != nil { return err @@ -242,7 +232,7 @@ func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result {{ end }} {{ else if or (eq .SigName "builtinAddStringAndDurationSig") (eq .SigName "builtinSubStringAndDurationSig") }} sc := b.ctx.GetSessionVars().StmtCtx - fsp1 := int8(b.args[1].GetType().Decimal) + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} var output string var isNull bool @@ -309,8 +299,8 @@ func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result } } {{ else if or (eq .SigName "builtinAddDateAndDurationSig") (eq .SigName "builtinSubDateAndDurationSig") }} - fsp0 := int8(b.args[0].GetType().Decimal) - fsp1 := int8(b.args[1].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal + fsp1 := b.args[1].GetType().Decimal arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1} {{ if eq $.FuncName "AddTime" }} sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration) @@ -323,7 +313,7 @@ func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result output := sum.String() {{ else if or (eq .SigName "builtinAddDateAndStringSig") (eq .SigName "builtinSubDateAndStringSig") }} {{ template "ConvertStringToDuration" . }} - fsp0 := int8(b.args[0].GetType().Decimal) + fsp0 := b.args[0].GetType().Decimal {{ if eq $.FuncName "AddTime" }} sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration) {{ else }} @@ -436,7 +426,7 @@ func (b *{{.SigName}}) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) {{ if $BIsDuration }} lhsDur, _, lhsIsDuration, {{- else if $BIsTime }} _, lhsTime, lhsIsDuration, {{- else if $BIsString }} lhsDur, lhsTime, lhsIsDuration, - {{- end }} err := convertStringToDuration(stmtCtx, buf0.GetString(i), int8(b.tp.Decimal)) + {{- end }} err := convertStringToDuration(stmtCtx, buf0.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -462,7 +452,7 @@ func (b *{{.SigName}}) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) {{ if $AIsDuration }} rhsDur, _, rhsIsDuration, {{- else if $AIsTime }}_, rhsTime, rhsIsDuration, {{- else if $AIsString }} rhsDur, rhsTime, rhsIsDuration, - {{- end}} err := convertStringToDuration(stmtCtx, buf1.GetString(i), int8(b.tp.Decimal)) + {{- end}} err := convertStringToDuration(stmtCtx, buf1.GetString(i), b.tp.Decimal) if err != nil { return err } @@ -524,6 +514,69 @@ func (b *{{.SigName}}) vectorized() bool { var addOrSubDate = template.Must(template.New("").Parse(` {{ range .Sigs }} +{{- if eq .TypeA.TypeName "String"}} +func (b *{{.SigName}}) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { +n := input.NumRows() + unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Row{}) + if err != nil { + return err + } + if isNull { + result.ReserveString(n) + result.SetNulls(0, n, true) + return nil + } + + intervalBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(intervalBuf) + if err := b.vecGetIntervalFrom{{.TypeB.ETName}}(&b.baseBuiltinFunc, input, unit, intervalBuf); err != nil { + return err + } + + dateBuf, err := b.bufAllocator.get() + if err != nil { + return err + } + defer b.bufAllocator.put(dateBuf) + if err := b.vecGetDateFromString(&b.baseBuiltinFunc, input, unit, dateBuf); err != nil { + return err + } + + isClockUnit := types.IsClockUnit(unit) + + result.ReserveString(n) + + dateBuf.MergeNulls(intervalBuf) + for i := 0; i < n; i++ { + if dateBuf.IsNull(i) { + result.AppendNull() + continue + } + {{- if eq $.FuncName "AddDate" }} + resDate, isNull, err := b.add(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) + {{- else }} + resDate, isNull, err := b.sub(b.ctx, dateBuf.Times()[i], intervalBuf.GetString(i), unit) + {{- end }} + if err != nil { + return err + } + if isNull { + result.AppendNull() + } else { + dateTp := mysql.TypeDate + if dateBuf.Times()[i].Type() == mysql.TypeDatetime || isClockUnit { + dateTp = mysql.TypeDatetime + } + resDate.SetType(dateTp) + result.AppendString(resDate.String()) + } + } + return nil +} +{{- else }} {{- if eq .TypeA.TypeName "Duration" }} func (b *{{.SigName}}) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error { {{- else }} @@ -604,6 +657,7 @@ func (b *{{.SigName}}) vecEvalTime(input *chunk.Chunk, result *chunk.Column) err } return nil } +{{- end }} func (b *{{.SigName}}) vectorized() bool { return true @@ -675,7 +729,7 @@ func (g gener) gen() interface{} { if _, ok := result.(string); ok { dg := newDefaultGener(0, types.ETDuration) d := dg.gen().(types.Duration) - if int8(d.Duration)%2 == 0 { + if d.Duration%2 == 0 { d.Fsp = 0 } else { d.Fsp = 1 @@ -856,10 +910,10 @@ var timeDiffSigsTmpl = []sig{ } var addDataSigsTmpl = []sig{ - {SigName: "builtinAddDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime}, - {SigName: "builtinAddDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime}, - {SigName: "builtinAddDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime}, - {SigName: "builtinAddDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeDatetime}, + {SigName: "builtinAddDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeString}, + {SigName: "builtinAddDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeString}, + {SigName: "builtinAddDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeString}, + {SigName: "builtinAddDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeString}, {SigName: "builtinAddDateIntStringSig", TypeA: TypeInt, TypeB: TypeString, Output: TypeDatetime}, {SigName: "builtinAddDateIntIntSig", TypeA: TypeInt, TypeB: TypeInt, Output: TypeDatetime}, {SigName: "builtinAddDateIntRealSig", TypeA: TypeInt, TypeB: TypeReal, Output: TypeDatetime}, @@ -875,10 +929,10 @@ var addDataSigsTmpl = []sig{ } var subDataSigsTmpl = []sig{ - {SigName: "builtinSubDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime}, - {SigName: "builtinSubDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime}, - {SigName: "builtinSubDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime}, - {SigName: "builtinSubDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeDatetime}, + {SigName: "builtinSubDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeString}, + {SigName: "builtinSubDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeString}, + {SigName: "builtinSubDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeString}, + {SigName: "builtinSubDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeString}, {SigName: "builtinSubDateIntStringSig", TypeA: TypeInt, TypeB: TypeString, Output: TypeDatetime}, {SigName: "builtinSubDateIntIntSig", TypeA: TypeInt, TypeB: TypeInt, Output: TypeDatetime}, {SigName: "builtinSubDateIntRealSig", TypeA: TypeInt, TypeB: TypeReal, Output: TypeDatetime}, diff --git a/expression/helper.go b/expression/helper.go index 6d1710ccbdba5..c292b954f1723 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -57,7 +57,7 @@ func IsValidCurrentTimestampExpr(exprNode ast.ExprNode, fieldType *types.FieldTy } // GetTimeCurrentTimestamp is used for generating a timestamp for some special cases: cast null value to timestamp type with not null flag. -func GetTimeCurrentTimestamp(ctx sessionctx.Context, tp byte, fsp int8) (d types.Datum, err error) { +func GetTimeCurrentTimestamp(ctx sessionctx.Context, tp byte, fsp int) (d types.Datum, err error) { var t types.Time t, err = getTimeCurrentTimeStamp(ctx, tp, fsp) if err != nil { @@ -67,13 +67,13 @@ func GetTimeCurrentTimestamp(ctx sessionctx.Context, tp byte, fsp int8) (d types return d, nil } -func getTimeCurrentTimeStamp(ctx sessionctx.Context, tp byte, fsp int8) (t types.Time, err error) { +func getTimeCurrentTimeStamp(ctx sessionctx.Context, tp byte, fsp int) (t types.Time, err error) { value := types.NewTime(types.ZeroCoreTime, tp, fsp) defaultTime, err := getStmtTimestamp(ctx) if err != nil { return value, err } - value.SetCoreTime(types.FromGoTime(defaultTime.Truncate(time.Duration(math.Pow10(9-int(fsp))) * time.Nanosecond))) + value.SetCoreTime(types.FromGoTime(defaultTime.Truncate(time.Duration(math.Pow10(9-fsp)) * time.Nanosecond))) if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { err = value.ConvertTimeZone(time.Local, ctx.GetSessionVars().Location()) if err != nil { @@ -84,7 +84,7 @@ func getTimeCurrentTimeStamp(ctx sessionctx.Context, tp byte, fsp int8) (t types } // GetTimeValue gets the time value with type tp. -func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int8) (d types.Datum, err error) { +func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d types.Datum, err error) { var value types.Time sc := ctx.GetSessionVars().StmtCtx diff --git a/expression/integration_serial_test.go b/expression/integration_serial_test.go index 0665f2b2082ba..a28db0ac0d16d 100644 --- a/expression/integration_serial_test.go +++ b/expression/integration_serial_test.go @@ -34,9 +34,7 @@ import ( "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testutil" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" ) @@ -78,13 +76,10 @@ func TestIssue17727(t *testing.T) { tk.MustExec("set @a = '2020-06-12 13:47:58';") tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1591940878")) - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } func TestIssue17891(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -96,10 +91,27 @@ func TestIssue17891(t *testing.T) { tk.MustExec("create table test(id int, value set ('a','b','c') charset utf8mb4 collate utf8mb4_general_ci default 'a,B ,C');") } -func TestIssue20268(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) +func TestIssue31174(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(4) collate utf8_general_ci primary key /*T![clustered_index] clustered */);") + tk.MustExec("insert into t values('`?');") + // The 'like' condition can not be used to construct the range. + tk.HasPlan("select * from t where a like '`%';", "TableFullScan") + tk.MustQuery("select * from t where a like '`%';").Check(testkit.Rows("`?")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(4) collate binary primary key /*T![clustered_index] clustered */);") + tk.MustExec("insert into t values('`?');") + tk.HasPlan("select * from t where a like '`%';", "TableRangeScan") + tk.MustQuery("select * from t where a like '`%';").Check(testkit.Rows("`?\x00\x00")) +} +func TestIssue20268(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -116,8 +128,6 @@ func TestCollationBasic(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("use test") tk.MustExec("create table t_ci(a varchar(10) collate utf8mb4_general_ci, unique key(a))") tk.MustExec("insert into t_ci values ('a')") @@ -175,6 +185,17 @@ func TestCollationBasic(t *testing.T) { tk.MustQuery("select * from t1 where col1 >= 0xc484 and col1 <= 0xc3b3;").Check(testkit.Rows("Ȇ")) tk.MustQuery("select collation(IF('a' < 'B' collate utf8mb4_general_ci, 'smaller', 'greater' collate utf8mb4_unicode_ci));").Check(testkit.Rows("utf8mb4_unicode_ci")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a char(10))") + tk.MustExec("insert into t values ('a')") + tk.MustQuery("select * from t where a in ('b' collate utf8mb4_general_ci, 'A', 3)").Check(testkit.Rows("a")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(`COL2` tinyint(16) DEFAULT NULL);") + tk.MustExec("insert into t values(0);") + tk.MustQuery("select * from t WHERE COL2 IN (0xfc);").Check(testkit.Rows()) + tk.MustQuery("select * from t WHERE COL2 = 0xfc;").Check(testkit.Rows()) } func TestWeightString(t *testing.T) { @@ -182,8 +203,6 @@ func TestWeightString(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) type testCase struct { input []string @@ -257,8 +276,6 @@ func TestCollationCreateIndex(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a varchar(10) collate utf8mb4_general_ci);") @@ -292,8 +309,6 @@ func TestCollateConstantPropagation(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -364,8 +379,6 @@ func TestMixCollation(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustGetErrMsg(`select 'a' collate utf8mb4_bin = 'a' collate utf8mb4_general_ci;`, "[expression:1267]Illegal mix of collations (utf8mb4_bin,EXPLICIT) and (utf8mb4_general_ci,EXPLICIT) for operation '='") @@ -457,8 +470,6 @@ func prepare4Join(tk *testkit.TestKit) { } func TestCollateHashJoin(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -483,8 +494,6 @@ func TestCollateHashJoin(t *testing.T) { } func TestCollateHashJoin2(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -505,8 +514,6 @@ func prepare4Join2(tk *testkit.TestKit) { } func TestCollateMergeJoin(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -531,8 +538,6 @@ func TestCollateMergeJoin(t *testing.T) { } func TestCollateMergeJoin2(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -543,8 +548,6 @@ func TestCollateMergeJoin2(t *testing.T) { } func TestCollateIndexMergeJoin(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -560,8 +563,6 @@ func TestCollateIndexMergeJoin(t *testing.T) { } func TestNewCollationCheckClusterIndexTable(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -589,8 +590,6 @@ func prepare4Collation(tk *testkit.TestKit, hasIndex bool) { } func TestCollateSelection(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -603,8 +602,6 @@ func TestCollateSelection(t *testing.T) { } func TestCollateSort(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -624,8 +621,6 @@ func TestCollateSort(t *testing.T) { } func TestCollateHashAgg(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -652,8 +647,6 @@ func TestCollateHashAgg(t *testing.T) { } func TestCollateStreamAgg(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -670,8 +663,6 @@ func TestCollateStreamAgg(t *testing.T) { } func TestCollateIndexReader(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -688,8 +679,6 @@ func TestCollateIndexReader(t *testing.T) { } func TestCollateIndexLookup(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -707,8 +696,6 @@ func TestCollateIndexLookup(t *testing.T) { } func TestIssue16668(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -721,8 +708,6 @@ func TestIssue16668(t *testing.T) { } func TestIssue27091(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -740,8 +725,6 @@ func TestIssue27091(t *testing.T) { } func TestCollateStringFunction(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -867,9 +850,6 @@ func TestCollateStringFunction(t *testing.T) { } func TestCollateLike(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -903,8 +883,6 @@ func TestCollateLike(t *testing.T) { } func TestCollateSubQuery(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -921,8 +899,6 @@ func TestCollateSubQuery(t *testing.T) { } func TestCollateDDL(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -933,8 +909,6 @@ func TestCollateDDL(t *testing.T) { } func TestNewCollationWithClusterIndex(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -948,8 +922,6 @@ func TestNewCollationWithClusterIndex(t *testing.T) { } func TestNewCollationBinaryFlag(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -993,8 +965,6 @@ func TestNewCollationBinaryFlag(t *testing.T) { } func TestIssue17176(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1010,9 +980,6 @@ func TestIssue17176(t *testing.T) { } func TestIssue18638(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1026,9 +993,6 @@ func TestIssue18638(t *testing.T) { } func TestCollationText(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1043,9 +1007,6 @@ func TestCollationText(t *testing.T) { } func TestIssue18662(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1061,9 +1022,6 @@ func TestIssue18662(t *testing.T) { } func TestIssue19116(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1088,9 +1046,6 @@ func TestIssue19116(t *testing.T) { } func TestIssue17063(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1108,9 +1063,6 @@ func TestIssue17063(t *testing.T) { } func TestIssue11177(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1126,9 +1078,6 @@ func TestIssue11177(t *testing.T) { } func TestIssue19804(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1148,9 +1097,6 @@ func TestIssue19804(t *testing.T) { } func TestIssue20209(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1162,9 +1108,6 @@ func TestIssue20209(t *testing.T) { } func TestIssue18949(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1180,9 +1123,6 @@ func TestIssue18949(t *testing.T) { } func TestClusteredIndexAndNewCollationIndexEncodeDecodeV5(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1197,49 +1137,49 @@ func TestClusteredIndexAndNewCollationIndexEncodeDecodeV5(t *testing.T) { tk.MustExec("insert into t values (1, 'å•Š ', 'å•Š ', 'å•Š ', 'å•Š ', 'å•Š ', 'å•Š ')") // Single Read. - tk.MustQuery("select * from t ").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - - tk.MustQuery("select * from t use index(a)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(ua)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(b)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(ub)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(c)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(uc)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(d)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(ud)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(e)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(ue)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(f)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(uf)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(g)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) - tk.MustQuery("select * from t use index(ug)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t ").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + + tk.MustQuery("select * from t use index(a)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(ua)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(b)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(ub)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(c)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(uc)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(d)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(ud)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(e)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(ue)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(f)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(uf)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(g)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) + tk.MustQuery("select * from t use index(ug)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ")) tk.MustExec("alter table t add column h varchar(10) collate utf8mb4_general_ci default 'ðŸ¸'") tk.MustExec("alter table t add column i varchar(10) collate utf8mb4_general_ci default 'ðŸ¸'") tk.MustExec("alter table t add index h(h)") tk.MustExec("alter table t add unique index uh(h)") - tk.MustQuery("select * from t use index(h)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(uh)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(h)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(uh)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) // Double read. - tk.MustQuery("select * from t use index(a)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(ua)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(b)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(ub)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(c)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(uc)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(d)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(ud)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(e)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) - tk.MustQuery("select * from t use index(ue)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(a)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(ua)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(b)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(ub)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(c)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(uc)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(d)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(ud)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(e)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) + tk.MustQuery("select * from t use index(ue)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸")) tk.MustExec("admin check table t") tk.MustExec("admin recover index t a") tk.MustExec("alter table t add column n char(10) COLLATE utf8mb4_unicode_ci") tk.MustExec("alter table t add index n(n)") tk.MustExec("update t set n = 'å§';") - tk.MustQuery("select * from t").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸,å§")) - tk.MustQuery("select * from t use index(n)").Check(testutil.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸,å§")) + tk.MustQuery("select * from t").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸,å§")) + tk.MustQuery("select * from t use index(n)").Check(testkit.RowsWithSep(",", "1,å•Š,å•Š,å•Š ,å•Š ,å•Š,å•Š ,ðŸ¸,ðŸ¸,å§")) tk.MustExec("admin check table t") tk.MustExec("drop table if exists t;") @@ -1253,9 +1193,6 @@ func TestClusteredIndexAndNewCollationIndexEncodeDecodeV5(t *testing.T) { } func TestClusteredIndexAndNewCollation(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1287,8 +1224,6 @@ func TestClusteredIndexAndNewCollation(t *testing.T) { } func TestIssue20608(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1297,9 +1232,6 @@ func TestIssue20608(t *testing.T) { } func TestIssue20161(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - store, clean := testkit.CreateMockStore(t) defer clean() @@ -1313,8 +1245,6 @@ func TestIssue20161(t *testing.T) { } func TestCollationIndexJoin(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1350,8 +1280,6 @@ func TestCollationIndexJoin(t *testing.T) { } func TestCollationMergeJoin(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1379,8 +1307,6 @@ func TestCollationMergeJoin(t *testing.T) { } func TestIssue20876(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1405,9 +1331,6 @@ func TestLikeWithCollation(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk.MustQuery(`select 'a' like 'A' collate utf8mb4_unicode_ci;`).Check(testkit.Rows("1")) tk.MustGetErrMsg(`select 'a' collate utf8mb4_bin like 'A' collate utf8mb4_unicode_ci;`, "[expression:1267]Illegal mix of collations (utf8mb4_bin,EXPLICIT) and (utf8mb4_unicode_ci,EXPLICIT) for operation 'like'") tk.MustQuery(`select '😛' collate utf8mb4_general_ci like '😋';`).Check(testkit.Rows("1")) @@ -1416,31 +1339,12 @@ func TestLikeWithCollation(t *testing.T) { tk.MustQuery(`select '😛' collate utf8mb4_unicode_ci = '😋';`).Check(testkit.Rows("1")) } -func TestCollationUnion(t *testing.T) { - // For issue 19694. - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - - tk.MustQuery("select cast('2010-09-09' as date) a union select '2010-09-09 ' order by a;").Check(testkit.Rows("2010-09-09", "2010-09-09 ")) - res := tk.MustQuery("select cast('2010-09-09' as date) a union select '2010-09-09 ';") - require.Len(t, res.Rows(), 2) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - res = tk.MustQuery("select cast('2010-09-09' as date) a union select '2010-09-09 ';") - require.Len(t, res.Rows(), 1) -} - func TestCollationPrefixClusteredIndex(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk.MustExec("drop table if exists t") tk.MustExec("create table t (k char(20), v int, primary key (k(4)) clustered, key (k)) collate utf8mb4_general_ci;") tk.MustExec("insert into t values('01233', 1);") @@ -1456,9 +1360,6 @@ func TestIssue23805(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk.MustExec("CREATE TABLE `tbl_5` (" + " `col_25` time NOT NULL DEFAULT '05:35:58'," + " `col_26` blob NOT NULL," + @@ -1474,8 +1375,6 @@ func TestIssue23805(t *testing.T) { } func TestIssue26662(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) store, clean := testkit.CreateMockStore(t) defer clean() @@ -1488,13 +1387,21 @@ func TestIssue26662(t *testing.T) { Check(testkit.Rows()) } +func TestIssue30245(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustGetErrCode("select case 1 when 1 then 'a' collate utf8mb4_unicode_ci else 'b' collate utf8mb4_general_ci end", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select case when 1 then 'a' collate utf8mb4_unicode_ci when 2 then 'b' collate utf8mb4_general_ci end", mysql.ErrCantAggregate2collations) + tk.MustGetErrCode("select case 1 when 1 then 'a' collate utf8mb4_unicode_ci when 2 then 'b' collate utf8mb4_general_ci else 'b' collate utf8mb4_bin end", mysql.ErrCantAggregate3collations) +} + func TestCollationForBinaryLiteral(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE t (`COL1` tinyblob NOT NULL, `COL2` binary(1) NOT NULL, `COL3` bigint(11) NOT NULL, PRIMARY KEY (`COL1`(5),`COL2`,`COL3`) /*T![clustered_index] CLUSTERED */)") @@ -1939,7 +1846,7 @@ func TestTimeBuiltin(t *testing.T) { tk.MustExec(`insert into t select year("0000-00-00 00:00:00")`) tk.MustExec(`set sql_mode="NO_ZERO_DATE";`) // with zero date tk.MustExec(`insert into t select year("0000-00-00 00:00:00")`) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) tk.MustExec(`set sql_mode="NO_ZERO_DATE,STRICT_TRANS_TABLES";`) _, err = tk.Exec(`insert into t select year("0000-00-00 00:00:00");`) require.Error(t, err) @@ -1971,7 +1878,7 @@ func TestTimeBuiltin(t *testing.T) { tk.MustExec(`insert into t select month("0000-00-00 00:00:00")`) tk.MustExec(`set sql_mode="NO_ZERO_DATE";`) tk.MustExec(`insert into t select month("0000-00-00 00:00:00")`) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) tk.MustExec(`set sql_mode="NO_ZERO_DATE,STRICT_TRANS_TABLES";`) _, err = tk.Exec(`insert into t select month("0000-00-00 00:00:00");`) require.Error(t, err) @@ -2004,7 +1911,7 @@ func TestTimeBuiltin(t *testing.T) { _, err = tk.Exec(`update t set a = week("aa", 1)`) require.True(t, terror.ErrorEqual(err, types.ErrWrongValue)) _, err = tk.Exec(`delete from t where a = week("aa", 1)`) - require.True(t, terror.ErrorEqual(err, types.ErrWrongValue)) + require.Equal(t, types.ErrWrongValue.Code(), errors.Cause(err).(*terror.Error).Code(), "err %v", err) // for weekofyear result = tk.MustQuery(`select weekofyear("2012-12-22"), weekofyear("2008-02-20"), weekofyear("aa"), weekofyear(null), weekofyear(11), weekofyear(12.99);`) @@ -2019,7 +1926,7 @@ func TestTimeBuiltin(t *testing.T) { _, err = tk.Exec(`update t set a = weekofyear("aa")`) require.True(t, terror.ErrorEqual(err, types.ErrWrongValue)) _, err = tk.Exec(`delete from t where a = weekofyear("aa")`) - require.True(t, terror.ErrorEqual(err, types.ErrWrongValue)) + require.Equal(t, types.ErrWrongValue.Code(), errors.Cause(err).(*terror.Error).Code(), "err %v", err) // for weekday result = tk.MustQuery(`select weekday("2012-12-20"), weekday("2012-12-21"), weekday("2012-12-22"), weekday("2012-12-23"), weekday("2012-12-24"), weekday("2012-12-25"), weekday("2012-12-26"), weekday("2012-12-27");`) @@ -2033,10 +1940,8 @@ func TestTimeBuiltin(t *testing.T) { result = tk.MustQuery(`select quarter("2012-14-20"), quarter("aa"), quarter(null), quarter(11), quarter(12.99);`) result.Check(testkit.Rows(" ")) result = tk.MustQuery(`select quarter("0000-00-00"), quarter("0000-00-00 00:00:00");`) - result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", - "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'", - "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + result.Check(testkit.Rows("0 0")) + tk.MustQuery("show warnings").Check(testkit.Rows()) result = tk.MustQuery(`select quarter(0), quarter(0.0), quarter(0e1), quarter(0.00);`) result.Check(testkit.Rows("0 0 0 0")) tk.MustQuery("show warnings").Check(testkit.Rows()) @@ -2210,6 +2115,13 @@ func TestTimeBuiltin(t *testing.T) { tk.MustQuery("select subtime(cast('10:10:10' as time), cast('9:10:10' as time))").Check(testkit.Rows("01:00:00")) tk.MustQuery("select subtime('10:10:10', cast('9:10:10' as time))").Check(testkit.Rows("01:00:00")) + // SUBTIME issue #31868 + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a DATETIME(6))") + tk.MustExec(`insert into t values ("1000-01-01 01:00:00.000000"), ("1000-01-01 01:00:00.000001")`) + tk.MustQuery(`SELECT SUBTIME(a, '00:00:00.000001') FROM t ORDER BY a;`).Check(testkit.Rows("1000-01-01 00:59:59.999999", "1000-01-01 01:00:00.000000")) + tk.MustQuery(`SELECT SUBTIME(a, '10:00:00.000001') FROM t ORDER BY a;`).Check(testkit.Rows("0999-12-31 14:59:59.999999", "0999-12-31 15:00:00.000000")) + // ADDTIME & SUBTIME issue #5966 tk.MustExec("drop table if exists t") tk.MustExec("create table t(a datetime, b timestamp, c time, d date, e bit(1))") @@ -2230,34 +2142,34 @@ func TestTimeBuiltin(t *testing.T) { result = tk.MustQuery("select addtime(-32073, 0), addtime(0, -32073);") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) result = tk.MustQuery("select addtime(-32073, c), addtime(c, -32073) from t;") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) result = tk.MustQuery("select addtime(a, -32073), addtime(b, -32073), addtime(d, -32073) from t;") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) result = tk.MustQuery("select subtime(-32073, 0), subtime(0, -32073);") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) result = tk.MustQuery("select subtime(-32073, c), subtime(c, -32073) from t;") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) result = tk.MustQuery("select subtime(a, -32073), subtime(b, -32073), subtime(d, -32073) from t;") result.Check(testkit.Rows(" ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'", "Warning|1292|Truncated incorrect time value: '-32073'")) @@ -2397,11 +2309,11 @@ func TestTimeBuiltin(t *testing.T) { result.Check(testkit.Rows("Friday November 13 2015 10:20:19 AM 15")) result = tk.MustQuery(`SELECT DATE_FORMAT('0000-00-00', '%W %M %e %Y %r %y');`) result.Check(testkit.Rows("")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) result = tk.MustQuery(`SELECT DATE_FORMAT('0', '%W %M %e %Y %r %y'), DATE_FORMAT('0.0', '%W %M %e %Y %r %y'), DATE_FORMAT(0, 0);`) result.Check(testkit.Rows(" 0")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect time value: '0'", "Warning|1292|Incorrect datetime value: '0.0'")) result = tk.MustQuery(`SELECT DATE_FORMAT(0, '%W %M %e %Y %r %y'), DATE_FORMAT(0.0, '%W %M %e %Y %r %y');`) @@ -2449,7 +2361,7 @@ func TestTimeBuiltin(t *testing.T) { tk.MustExec(`update t set a = dayOfMonth("0000-00-00")`) tk.MustExec("set sql_mode = 'NO_ZERO_DATE';") tk.MustExec("insert into t value(dayOfMonth('0000-00-00'))") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) tk.MustExec(`update t set a = dayOfMonth("0000-00-00")`) tk.MustExec("set sql_mode = 'NO_ZERO_DATE,STRICT_TRANS_TABLES';") _, err = tk.Exec("insert into t value(dayOfMonth('0000-00-00'))") @@ -2538,7 +2450,7 @@ func TestTimeBuiltin(t *testing.T) { tk.MustExec(`update t set a = monthname("0000-00-00")`) tk.MustExec("set sql_mode = 'NO_ZERO_DATE'") tk.MustExec("insert into t value(monthname('0000-00-00'))") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) tk.MustExec(`update t set a = monthname("0000-00-00")`) tk.MustExec("set sql_mode = ''") tk.MustExec("insert into t value(monthname('0000-00-00'))") @@ -2549,7 +2461,7 @@ func TestTimeBuiltin(t *testing.T) { require.NoError(t, err) result = tk.MustQuery(`select monthname("2017-12-01"), monthname("0000-00-00"), monthname("0000-01-00"), monthname("0000-01-00 00:00:00")`) result.Check(testkit.Rows("December January January")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'")) // for dayname tk.MustExec(`drop table if exists t`) @@ -2565,7 +2477,7 @@ func TestTimeBuiltin(t *testing.T) { require.NoError(t, err) result = tk.MustQuery(`select dayname("2017-12-01"), dayname("0000-00-00"), dayname("0000-01-00"), dayname("0000-01-00 00:00:00")`) result.Check(testkit.Rows("Friday ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'", "Warning|1292|Incorrect datetime value: '0000-01-00 00:00:00.000000'", "Warning|1292|Incorrect datetime value: '0000-01-00 00:00:00.000000'")) @@ -2617,7 +2529,7 @@ func TestTimeBuiltin(t *testing.T) { // TODO: MySQL returns " ". result.Check(testkit.Rows("0000-00-01 ")) result = tk.MustQuery("show warnings") - result.Sort().Check(testutil.RowsWithSep("|", + result.Sort().Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00'", "Warning|1292|Truncated incorrect datetime value: '01-01-2017'")) @@ -2627,7 +2539,7 @@ func TestTimeBuiltin(t *testing.T) { result = tk.MustQuery("select str_to_date('2020-07-04 11:22:33 PM c', '%Y-%m-%d %r')") result.Check(testkit.Rows("2020-07-04 23:22:33")) result = tk.MustQuery("show warnings") - result.Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect datetime value: '2020-07-04 11:22:33 PM c'")) + result.Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect datetime value: '2020-07-04 11:22:33 PM c'")) result = tk.MustQuery("select str_to_date('11:22:33 PM', ' %r')") result.Check(testkit.Rows("23:22:33")) @@ -3869,7 +3781,7 @@ func TestPreparePlanCache(t *testing.T) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) } -func TestPreparePlanCacheNotForCacheTable(t *testing.T) { +func TestPreparePlanCacheOnCachedTable(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -3890,28 +3802,25 @@ func TestPreparePlanCacheNotForCacheTable(t *testing.T) { tk.MustExec("create table t(a int);") tk.MustExec("alter table t cache") - var useCache bool + var readFromTableCache bool for i := 0; i < 50; i++ { tk.MustQuery("select * from t where a = 1") - if tk.HasPlan("select * from t where a = 1", "Union") { - useCache = true + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + readFromTableCache = true + break } + time.Sleep(50 * time.Millisecond) } - require.True(t, useCache) + require.True(t, readFromTableCache) // already read cache after reading first time - tk.MustQuery("explain format = 'brief' select * from t where a = 1").Check(testkit.Rows( - "Projection 10.00 root test.t.a", - "└─UnionScan 10.00 root eq(test.t.a, 1)", - " └─TableReader 10.00 root data:Selection", - " └─Selection 10.00 cop[tikv] eq(test.t.a, 1)", - " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) - tk.MustExec("prepare stmt from 'select * from t where a = ?';") tk.MustExec("set @a = 1;") tk.MustExec("execute stmt using @a;") tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) tk.MustExec("execute stmt using @a;") - tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) + readFromTableCache = tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache + require.True(t, readFromTableCache) + tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("1")) } func TestIssue16205(t *testing.T) { @@ -4524,8 +4433,8 @@ PARTITION BY RANGE (c) ( tk.MustExec("set global tidb_enable_local_txn = on;") for _, testcase := range testcases { t.Log(testcase.name) - failpoint.Enable("tikvclient/injectTxnScope", - fmt.Sprintf(`return("%v")`, testcase.zone)) + require.NoError(t, failpoint.Enable("tikvclient/injectTxnScope", + fmt.Sprintf(`return("%v")`, testcase.zone))) tk.MustExec(fmt.Sprintf("set @@txn_scope='%v'", testcase.txnScope)) tk.Exec("begin") res, err := tk.Exec(testcase.sql) @@ -4547,7 +4456,7 @@ PARTITION BY RANGE (c) ( } tk.Exec("commit") } - failpoint.Disable("tikvclient/injectTxnScope") + require.NoError(t, failpoint.Disable("tikvclient/injectTxnScope")) tk.MustExec("set global tidb_enable_local_txn = off;") } diff --git a/expression/integration_test.go b/expression/integration_test.go index 79cb81daf90f6..d7a7717e5b34f 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -38,7 +38,6 @@ import ( "github.com/pingcap/tidb/parser/terror" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" @@ -46,10 +45,12 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/kvcache" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/util/versioninfo" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -378,7 +379,6 @@ func TestConvertToBit(t *testing.T) { } func TestStringBuiltin(t *testing.T) { - t.Skip("it has been broken. Please fix it as soon as possible.") store, clean := testkit.CreateMockStore(t) defer clean() @@ -519,16 +519,16 @@ func TestStringBuiltin(t *testing.T) { // for space result = tk.MustQuery(`select space(0), space(2), space(-1), space(1.1), space(1.9)`) - result.Check(testutil.RowsWithSep(",", ", ,, , ")) + result.Check(testkit.RowsWithSep(",", ", ,, , ")) result = tk.MustQuery(`select space("abc"), space("2"), space("1.1"), space(''), space(null)`) - result.Check(testutil.RowsWithSep(",", ", , ,,")) + result.Check(testkit.RowsWithSep(",", ", , ,,")) // for replace tk.MustExec("drop table if exists t") tk.MustExec("create table t(a char(20), b int, c double, d datetime, e time)") tk.MustExec(`insert into t values('www.mysql.com', 1234, 12.34, "2017-01-01 12:01:01", "12:01:01")`) result = tk.MustQuery(`select replace(a, 'mysql', 'pingcap'), replace(b, 2, 55), replace(c, 34, 0), replace(d, '-', '/'), replace(e, '01', '22') from t`) - result.Check(testutil.RowsWithSep(",", "www.pingcap.com,15534,12.0,2017/01/01 12:01:01,12:22:22")) + result.Check(testkit.RowsWithSep(",", "www.pingcap.com,15534,12.0,2017/01/01 12:01:01,12:22:22")) result = tk.MustQuery(`select replace('aaa', 'a', ''), replace(null, 'a', 'b'), replace('a', null, 'b'), replace('a', 'b', null)`) result.Check(testkit.Rows(" ")) @@ -552,7 +552,7 @@ func TestStringBuiltin(t *testing.T) { result = tk.MustQuery(`select substr(a, 3), substr(b, 2, 3), substr(c, -3), substr(d, -8), substr(e, -3, 100) from t`) result.Check(testkit.Rows("kila 234 .45 12:01:01 :01")) result = tk.MustQuery(`select substr('Sakila', 100), substr('Sakila', -100), substr('Sakila', -5, 3), substr('Sakila', 2, -1)`) - result.Check(testutil.RowsWithSep(",", ",,aki,")) + result.Check(testkit.RowsWithSep(",", ",,aki,")) result = tk.MustQuery(`select substr('foobarbar' from 4), substr('Sakila' from -4 for 2)`) result.Check(testkit.Rows("barbar ki")) result = tk.MustQuery(`select substr(null, 2, 3), substr('foo', null, 3), substr('foo', 2, null)`) @@ -583,7 +583,7 @@ func TestStringBuiltin(t *testing.T) { result = tk.MustQuery(`select substring_index('www.pingcap.com', '.', 0), substring_index('www.pingcap.com', '.', 100), substring_index('www.pingcap.com', '.', -100)`) result.Check(testkit.Rows(" www.pingcap.com www.pingcap.com")) result = tk.MustQuery(`select substring_index('www.pingcap.com', 'd', 1), substring_index('www.pingcap.com', '', 1), substring_index('', '.', 1)`) - result.Check(testutil.RowsWithSep(",", "www.pingcap.com,,")) + result.Check(testkit.RowsWithSep(",", "www.pingcap.com,,")) result = tk.MustQuery(`select substring_index(null, '.', 1), substring_index('www.pingcap.com', null, 1), substring_index('www.pingcap.com', '.', null)`) result.Check(testkit.Rows(" ")) @@ -624,13 +624,13 @@ func TestStringBuiltin(t *testing.T) { // for ltrim and rtrim result = tk.MustQuery(`select ltrim(' bar '), ltrim('bar'), ltrim(''), ltrim(null)`) - result.Check(testutil.RowsWithSep(",", "bar ,bar,,")) + result.Check(testkit.RowsWithSep(",", "bar ,bar,,")) result = tk.MustQuery(`select rtrim(' bar '), rtrim('bar'), rtrim(''), rtrim(null)`) - result.Check(testutil.RowsWithSep(",", " bar,bar,,")) + result.Check(testkit.RowsWithSep(",", " bar,bar,,")) result = tk.MustQuery(`select ltrim("\t bar "), ltrim(" \tbar"), ltrim("\n bar"), ltrim("\r bar")`) - result.Check(testutil.RowsWithSep(",", "\t bar ,\tbar,\n bar,\r bar")) + result.Check(testkit.RowsWithSep(",", "\t bar ,\tbar,\n bar,\r bar")) result = tk.MustQuery(`select rtrim(" bar \t"), rtrim("bar\t "), rtrim("bar \n"), rtrim("bar \r")`) - result.Check(testutil.RowsWithSep(",", " bar \t,bar\t,bar \n,bar \r")) + result.Check(testkit.RowsWithSep(",", " bar \t,bar\t,bar \n,bar \r")) // for reverse tk.MustExec(`DROP TABLE IF EXISTS t;`) @@ -645,11 +645,11 @@ func TestStringBuiltin(t *testing.T) { result = tk.MustQuery(`select trim(' bar '), trim(leading 'x' from 'xxxbarxxx'), trim(trailing 'xyz' from 'barxxyz'), trim(both 'x' from 'xxxbarxxx')`) result.Check(testkit.Rows("bar barxxx barx bar")) result = tk.MustQuery(`select trim('\t bar\n '), trim(' \rbar \t')`) - result.Check(testutil.RowsWithSep(",", "\t bar\n,\rbar \t")) + result.Check(testkit.RowsWithSep(",", "\t bar\n,\rbar \t")) result = tk.MustQuery(`select trim(leading from ' bar'), trim('x' from 'xxxbarxxx'), trim('x' from 'bar'), trim('' from ' bar ')`) - result.Check(testutil.RowsWithSep(",", "bar,bar,bar, bar ")) + result.Check(testkit.RowsWithSep(",", "bar,bar,bar, bar ")) result = tk.MustQuery(`select trim(''), trim('x' from '')`) - result.Check(testutil.RowsWithSep(",", ",")) + result.Check(testkit.RowsWithSep(",", ",")) result = tk.MustQuery(`select trim(null from 'bar'), trim('x' from null), trim(null), trim(leading null from 'bar')`) result.Check(testkit.Rows(" ")) @@ -811,6 +811,31 @@ func TestStringBuiltin(t *testing.T) { result = tk.MustQuery("select a,b,concat_ws(',',a,b) from t") result.Check(testkit.Rows("114.57011441 38.04620115 114.57011441,38.04620115", "-38.04620119 38.04620115 -38.04620119,38.04620115")) + + // For issue 31603, only affects unistore. + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 varbinary(100));") + tk.MustExec("insert into t1 values('abc');") + tk.MustQuery("select 1 from t1 where char_length(c1) = 10;").Check(testkit.Rows()) +} + +func TestInvalidStrings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // Test convert invalid string. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a binary(5));") + tk.MustExec("insert into t values (0x1e240), ('ABCDE');") + tk.MustExec("set tidb_enable_vectorized_expression = on;") + tk.MustQuery("select convert(t.a using utf8) from t;").Check(testkit.Rows("", "ABCDE")) + tk.MustQuery("select convert(0x1e240 using utf8);").Check(testkit.Rows("")) + tk.MustExec("set tidb_enable_vectorized_expression = off;") + tk.MustQuery("select convert(t.a using utf8) from t;").Check(testkit.Rows("", "ABCDE")) + tk.MustQuery("select convert(0x1e240 using utf8);").Check(testkit.Rows("")) } func TestEncryptionBuiltin(t *testing.T) { @@ -877,7 +902,7 @@ func TestEncryptionBuiltin(t *testing.T) { result.Check(testkit.Rows(`45ABDD5C4802EFA6771A94C43F805208 45ABDD5C4802EFA6771A94C43F805208 791F1AEB6A6B796E6352BF381895CA0E D0147E2EB856186F146D9F6DE33F9546 `)) result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', 'iv')), HEX(AES_ENCRYPT(b, 'key', 'iv')) from t") result.Check(testkit.Rows("B3800B3A3CB4ECE2051A3E80FE373EAC B3800B3A3CB4ECE2051A3E80FE373EAC")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1618| option ignored", "Warning|1618| option ignored")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1618| option ignored", "Warning|1618| option ignored")) tk.MustExec("SET block_encryption_mode='aes-128-cbc';") result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', '1234567890123456')), HEX(AES_ENCRYPT(b, 'key', '1234567890123456')), HEX(AES_ENCRYPT(c, 'key', '1234567890123456')), HEX(AES_ENCRYPT(d, 'key', '1234567890123456')), HEX(AES_ENCRYPT(e, 'key', '1234567890123456')), HEX(AES_ENCRYPT(f, 'key', '1234567890123456')), HEX(AES_ENCRYPT(g, 'key', '1234567890123456')), HEX(AES_ENCRYPT(h, 'key', '1234567890123456')), HEX(AES_ENCRYPT(i, 'key', '1234567890123456')) from t") result.Check(testkit.Rows("341672829F84CB6B0BE690FEC4C4DAE9 341672829F84CB6B0BE690FEC4C4DAE9 D43734E147A12BB96C6897C4BBABA283 16F2C972411948DCEF3659B726D2CCB04AD1379A1A367FA64242058A50211B67 41E71D0C58967C1F50EEC074523946D1 1117D292E2D39C3EAA3B435371BE56FC 8ACB7ECC0883B672D7BD1CFAA9FA5FAF5B731ADE978244CD581F114D591C2E7E D2B13C30937E3251AEDA73859BA32E4B 2CF4A6051FF248A67598A17AA2C17267")) @@ -1168,6 +1193,16 @@ func TestInfoBuiltin(t *testing.T) { result = tk.MustQuery("select version()") result.Check(testkit.Rows(mysql.ServerVersion)) + // for tidb_version + result = tk.MustQuery("select tidb_version()") + tidbVersionResult := "" + for _, line := range result.Rows() { + tidbVersionResult += fmt.Sprint(line) + } + lines := strings.Split(tidbVersionResult, "\n") + assert.Equal(t, true, strings.Split(lines[0], " ")[2] == mysql.TiDBReleaseVersion, "errors in 'select tidb_version()'") + assert.Equal(t, true, strings.Split(lines[1], " ")[1] == versioninfo.TiDBEdition, "errors in 'select tidb_version()'") + // for row_count tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, PRIMARY KEY (a))") @@ -1459,7 +1494,7 @@ func TestArithmeticBuiltin(t *testing.T) { result.Check(testkit.Rows("2 2 1")) result = tk.MustQuery("SELECT 1.175494351E-37 div 1.7976931348623157E+308, 1.7976931348623157E+308 div -1.7976931348623157E+307, 1 div 1e-82;") result.Check(testkit.Rows("0 -1 ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DECIMAL value: '1.7976931348623157e+308'", "Warning|1292|Truncated incorrect DECIMAL value: '1.7976931348623157e+308'", "Warning|1292|Truncated incorrect DECIMAL value: '-1.7976931348623158e+307'", @@ -1524,7 +1559,7 @@ func TestArithmeticBuiltin(t *testing.T) { tk.MustExec("insert into t value(1.2)") result = tk.MustQuery("select * from t where a/0 > 1") result.Check(testkit.Rows()) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1365|Division by 0")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1365|Division by 0")) tk.MustExec("USE test;") tk.MustExec("DROP TABLE IF EXISTS t;") @@ -1735,14 +1770,14 @@ func TestCompareBuiltin(t *testing.T) { tk.MustQuery("show warnings").Check(testkit.Rows()) result = tk.MustQuery(`select greatest(cast("2017-01-01" as datetime), "123", "234", cast("2018-01-01" as date)), greatest(cast("2017-01-01" as date), "123", null)`) result.Check(testkit.Rows("234 ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect time value: '123'", "Warning|1292|Incorrect time value: '234'", "Warning|1292|Incorrect time value: '123'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect time value: '123'", "Warning|1292|Incorrect time value: '234'", "Warning|1292|Incorrect time value: '123'")) // for least result = tk.MustQuery(`select least(1, 2, 3), least("a", "b", "c"), least(1.1, 1.2, 1.3), least("123a", 1, 2)`) result.Check(testkit.Rows("1 a 1.1 1")) tk.MustQuery("show warnings").Check(testkit.Rows()) result = tk.MustQuery(`select least(cast("2017-01-01" as datetime), "123", "234", cast("2018-01-01" as date)), least(cast("2017-01-01" as date), "123", null)`) result.Check(testkit.Rows("123 ")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Incorrect time value: '123'", "Warning|1292|Incorrect time value: '234'", "Warning|1292|Incorrect time value: '123'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect time value: '123'", "Warning|1292|Incorrect time value: '234'", "Warning|1292|Incorrect time value: '123'")) tk.MustQuery(`select 1 < 17666000000000000000, 1 > 17666000000000000000, 1 = 17666000000000000000`).Check(testkit.Rows("1 0 0")) tk.MustExec("drop table if exists t") @@ -1924,7 +1959,7 @@ func TestAggregationBuiltinGroupConcat(t *testing.T) { tk.MustExec("set @@group_concat_max_len=7") result = tk.MustQuery("select group_concat(a) from t") result.Check(testkit.Rows("hello,h")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning 1260 Some rows were cut by GROUPCONCAT(test.t.a)")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning 1260 Some rows were cut by GROUPCONCAT(test.t.a)")) _, err := tk.Exec("insert into d select group_concat(a) from t") require.Equal(t, errors.ErrCode(mysql.ErrCutValueGroupConcat), errors.Cause(err).(*terror.Error).Code()) @@ -1932,7 +1967,7 @@ func TestAggregationBuiltinGroupConcat(t *testing.T) { _, err = tk.Exec("set sql_mode=''") require.NoError(t, err) tk.MustExec("insert into d select group_concat(a) from t") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning 1260 Some rows were cut by GROUPCONCAT(test.t.a)")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning 1260 Some rows were cut by GROUPCONCAT(test.t.a)")) tk.MustQuery("select * from d").Check(testkit.Rows("hello,h")) } @@ -2292,7 +2327,7 @@ func TestTimeLiteral(t *testing.T) { _, err = tk.Exec("select ADDDATE('2008-01-34', -1);") require.NoError(t, err) - tk.MustQuery("Show warnings;").Check(testutil.RowsWithSep("|", + tk.MustQuery("Show warnings;").Check(testkit.RowsWithSep("|", "Warning|1292|Incorrect datetime value: '2008-01-34'")) } @@ -2541,7 +2576,7 @@ func TestColumnInfoModified(t *testing.T) { testKit.MustExec("drop table if exists tab0") testKit.MustExec("CREATE TABLE tab0(col0 INTEGER, col1 INTEGER, col2 INTEGER)") testKit.MustExec("SELECT + - (- CASE + col0 WHEN + CAST( col0 AS SIGNED ) THEN col1 WHEN 79 THEN NULL WHEN + - col1 THEN col0 / + col0 END ) * - 16 FROM tab0") - ctx := testKit.Session().(sessionctx.Context) + ctx := testKit.Session() is := domain.GetDomain(ctx).InfoSchema() tbl, _ := is.TableByName(model.NewCIStr("test"), model.NewCIStr("tab0")) col := table.FindCol(tbl.Cols(), "col1") @@ -2582,12 +2617,12 @@ func TestIssues(t *testing.T) { tk.MustExec("insert into t values('1e649'),('-1e649');") r = tk.MustQuery(`SELECT * FROM t where c < 1;`) r.Check(testkit.Rows("-1e649")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: '1e649'", "Warning|1292|Truncated incorrect DOUBLE value: '-1e649'")) r = tk.MustQuery(`SELECT * FROM t where c > 1;`) r.Check(testkit.Rows("1e649")) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect DOUBLE value: '1e649'", "Warning|1292|Truncated incorrect DOUBLE value: '-1e649'")) @@ -2673,7 +2708,7 @@ func TestFilterExtractFromDNF(t *testing.T) { ctx := context.Background() for _, tt := range tests { sql := "select * from t where " + tt.exprStr - sctx := tk.Session().(sessionctx.Context) + sctx := tk.Session() sc := sctx.GetSessionVars().StmtCtx stmts, err := session.Parse(sctx, sql) require.NoError(t, err, "error %v, for expr %s", err, tt.exprStr) @@ -2752,14 +2787,17 @@ func TestTiDBDecodeKeyFunc(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() + collate.SetNewCollationEnabledForTest(false) + defer collate.SetNewCollationEnabledForTest(true) + tk := testkit.NewTestKit(t, store) var result *testkit.Result // Row Keys result = tk.MustQuery("select tidb_decode_key( '74800000000000002B5F72800000000000A5D3' )") result.Check(testkit.Rows(`{"_tidb_rowid":42451,"table_id":"43"}`)) - result = tk.MustQuery("select tidb_decode_key( '7480000000000000325f7205bff199999999999a013131000000000000f9' )") - result.Check(testkit.Rows(`{"handle":"{1.1, 11}","table_id":50}`)) + result = tk.MustQuery("select tidb_decode_key( '74800000000000ffff5f7205bff199999999999a013131000000000000f9' )") + result.Check(testkit.Rows(`{"handle":"{1.1, 11}","table_id":65535}`)) // Index Keys result = tk.MustQuery("select tidb_decode_key( '74800000000000019B5F698000000000000001015257303100000000FB013736383232313130FF3900000000000000F8010000000000000000F7' )") @@ -2776,7 +2814,7 @@ func TestTiDBDecodeKeyFunc(t *testing.T) { result.Check(testkit.Rows("7480000000000000FF2E5F728000000011FFE1A3000000000000")) warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() require.Len(t, warns, 1) - require.Error(t, warns[0].Err, "invalid record/index key: 7480000000000000FF2E5F728000000011FFE1A3000000000000") + require.EqualError(t, warns[0].Err, "invalid key: 7480000000000000FF2E5F728000000011FFE1A3000000000000") // Test in real tables. tk.MustExec("use test;") @@ -2839,10 +2877,15 @@ func TestTiDBDecodeKeyFunc(t *testing.T) { result.Check(testkit.Rows(rs)) // https://github.com/pingcap/tidb/issues/27434. - hexKey = "7480000000000000375F69800000000000000103800000000001D4C1023B6458" - sql = fmt.Sprintf("select tidb_decode_key( '%s' )", hexKey) + hexKey = "7480000000000100375F69800000000000000103800000000001D4C1023B6458" + sql = fmt.Sprintf("select tidb_decode_key('%s')", hexKey) tk.MustQuery(sql).Check(testkit.Rows(hexKey)) + // https://github.com/pingcap/tidb/issues/33015. + hexKey = "74800000000000012B5F72800000000000A5D3" + sql = fmt.Sprintf("select tidb_decode_key('%s')", hexKey) + tk.MustQuery(sql).Check(testkit.Rows(`{"_tidb_rowid":42451,"table_id":"299"}`)) + // Test the table with the nonclustered index. const rowID = 10 tk.MustExec("drop table if exists t;") @@ -3454,37 +3497,38 @@ func TestExprPushdown(t *testing.T) { "(4,'511111','611',7,8,9),(5,'611111','711',8,9,10)") // case 1, index scan without double read, some filters can not be pushed to cop task - rows := tk.MustQuery("explain format = 'brief' select col2, col1 from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Rows() + rows := tk.MustQuery("explain format = 'brief' select col2, col1 from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows() require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2])) - require.Equal(t, "eq(substr(test.t.col1, 1, 1), \"4\")", fmt.Sprintf("%v", rows[1][4])) + require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\")", fmt.Sprintf("%v", rows[1][4])) require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[3][2])) require.Equal(t, "like(test.t.col2, \"5%\", 92)", fmt.Sprintf("%v", rows[3][4])) - tk.MustQuery("select col2, col1 from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("511 411111")) - tk.MustQuery("select count(col2) from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("1")) + tk.MustQuery("select col2, col1 from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("511 411111")) + tk.MustQuery("select count(col2) from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1")) // case 2, index scan without double read, none of the filters can be pushed to cop task - rows = tk.MustQuery("explain format = 'brief' select col1, col2 from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Rows() + rows = tk.MustQuery("explain format = 'brief' select col1, col2 from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows() require.Equal(t, "root", fmt.Sprintf("%v", rows[0][2])) - require.Equal(t, "eq(substr(test.t.col1, 1, 1), \"4\"), eq(substr(test.t.col2, 1, 1), \"5\")", fmt.Sprintf("%v", rows[0][4])) - tk.MustQuery("select col1, col2 from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("411111 511")) - tk.MustQuery("select count(col1) from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("1")) + require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), \"5\")", fmt.Sprintf("%v", rows[0][4])) + tk.MustQuery("select col1, col2 from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("411111 511")) + tk.MustQuery("select count(col1) from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1")) // case 3, index scan with double read, some filters can not be pushed to cop task - rows = tk.MustQuery("explain format = 'brief' select id from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Rows() + rows = tk.MustQuery("explain format = 'brief' select id from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows() require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2])) - require.Equal(t, "eq(substr(test.t.col1, 1, 1), \"4\")", fmt.Sprintf("%v", rows[1][4])) + require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\")", fmt.Sprintf("%v", rows[1][4])) require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[3][2])) require.Equal(t, "like(test.t.col2, \"5%\", 92)", fmt.Sprintf("%v", rows[3][4])) - tk.MustQuery("select id from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("3")) - tk.MustQuery("select count(id) from t use index(key1) where col2 like '5%' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("1")) + tk.MustQuery("select id from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("3")) + tk.MustQuery("select count(id) from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1")) // case 4, index scan with double read, none of the filters can be pushed to cop task - rows = tk.MustQuery("explain format = 'brief' select id from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Rows() + rows = tk.MustQuery("explain format = 'brief' select id from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows() require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2])) - require.Equal(t, "eq(substr(test.t.col1, 1, 1), \"4\"), eq(substr(test.t.col2, 1, 1), \"5\")", fmt.Sprintf("%v", rows[1][4])) - tk.MustQuery("select id from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("3")) - tk.MustQuery("select count(id) from t use index(key2) where substr(col2, 1, 1) = '5' and substr(col1, 1, 1) = '4'").Check(testkit.Rows("1")) + require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), \"5\")", fmt.Sprintf("%v", rows[1][4])) + tk.MustQuery("select id from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("3")) + tk.MustQuery("select count(id) from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1")) } + func TestIssue16973(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -4151,7 +4195,7 @@ func TestSelectLimitPlanCache(t *testing.T) { tk.MustQuery("execute stmt").Check(testkit.Rows("1", "2")) } -func TestCollation(t *testing.T) { +func TestCollationAndCharset(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -4161,51 +4205,51 @@ func TestCollation(t *testing.T) { tk.MustExec("create table t (utf8_bin_c varchar(10) charset utf8 collate utf8_bin, utf8_gen_c varchar(10) charset utf8 collate utf8_general_ci, bin_c binary, num_c int, " + "abin char collate ascii_bin, lbin char collate latin1_bin, u4bin char collate utf8mb4_bin, u4ci char collate utf8mb4_general_ci)") tk.MustExec("insert into t values ('a', 'b', 'c', 4, 'a', 'a', 'a', 'a')") - tk.MustQuery("select collation(null)").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(2)").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(2 + 'a')").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(2 + utf8_gen_c) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(2 + utf8_bin_c) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(utf8_bin_c, 2)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(concat(utf8_gen_c, 'abc')) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(concat(utf8_gen_c, null)) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(concat(utf8_gen_c, num_c)) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(concat(utf8_bin_c, utf8_gen_c)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(upper(utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(upper(utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(upper(bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(abin, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(lbin, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(utf8_bin_c, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(utf8_gen_c, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(u4bin, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(u4ci, bin_c)) from t").Check(testkit.Rows("binary")) - tk.MustQuery("select collation(concat(abin, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin")) - tk.MustQuery("select collation(concat(lbin, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin")) - tk.MustQuery("select collation(concat(utf8_bin_c, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin")) - tk.MustQuery("select collation(concat(utf8_gen_c, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin")) - tk.MustQuery("select collation(concat(u4ci, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin")) - tk.MustQuery("select collation(concat(abin, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci")) - tk.MustQuery("select collation(concat(lbin, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci")) - tk.MustQuery("select collation(concat(utf8_bin_c, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci")) - tk.MustQuery("select collation(concat(utf8_gen_c, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci")) - tk.MustQuery("select collation(concat(abin, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(concat(lbin, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(concat(utf8_gen_c, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin")) - tk.MustQuery("select collation(concat(abin, utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(concat(lbin, utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci")) - tk.MustQuery("select collation(concat(abin, lbin)) from t").Check(testkit.Rows("latin1_bin")) + tk.MustQuery("select collation(null), charset(null)").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(2), charset(2)").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(2 + 'a'), charset(2 + 'a')").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(2 + utf8_gen_c), charset(2 + utf8_gen_c) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(2 + utf8_bin_c), charset(2 + utf8_bin_c) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(utf8_bin_c, 2)), charset(concat(utf8_bin_c, 2)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(concat(utf8_gen_c, 'abc')), charset(concat(utf8_gen_c, 'abc')) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(concat(utf8_gen_c, null)), charset(concat(utf8_gen_c, null)) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(concat(utf8_gen_c, num_c)), charset(concat(utf8_gen_c, num_c)) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(concat(utf8_bin_c, utf8_gen_c)), charset(concat(utf8_bin_c, utf8_gen_c)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(upper(utf8_bin_c)), charset(upper(utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(upper(utf8_gen_c)), charset(upper(utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(upper(bin_c)), charset(upper(bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(abin, bin_c)), charset(concat(abin, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(lbin, bin_c)), charset(concat(lbin, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(utf8_bin_c, bin_c)), charset(concat(utf8_bin_c, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(utf8_gen_c, bin_c)), charset(concat(utf8_gen_c, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(u4bin, bin_c)), charset(concat(u4bin, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(u4ci, bin_c)), charset(concat(u4ci, bin_c)) from t").Check(testkit.Rows("binary binary")) + tk.MustQuery("select collation(concat(abin, u4bin)), charset(concat(abin, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin utf8mb4")) + tk.MustQuery("select collation(concat(lbin, u4bin)), charset(concat(lbin, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin utf8mb4")) + tk.MustQuery("select collation(concat(utf8_bin_c, u4bin)), charset(concat(utf8_bin_c, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin utf8mb4")) + tk.MustQuery("select collation(concat(utf8_gen_c, u4bin)), charset(concat(utf8_gen_c, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin utf8mb4")) + tk.MustQuery("select collation(concat(u4ci, u4bin)), charset(concat(u4ci, u4bin)) from t").Check(testkit.Rows("utf8mb4_bin utf8mb4")) + tk.MustQuery("select collation(concat(abin, u4ci)), charset(concat(abin, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) + tk.MustQuery("select collation(concat(lbin, u4ci)), charset(concat(lbin, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) + tk.MustQuery("select collation(concat(utf8_bin_c, u4ci)), charset(concat(utf8_bin_c, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) + tk.MustQuery("select collation(concat(utf8_gen_c, u4ci)), charset(concat(utf8_gen_c, u4ci)) from t").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) + tk.MustQuery("select collation(concat(abin, utf8_bin_c)), charset(concat(abin, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(concat(lbin, utf8_bin_c)), charset(concat(lbin, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(concat(utf8_gen_c, utf8_bin_c)), charset(concat(utf8_gen_c, utf8_bin_c)) from t").Check(testkit.Rows("utf8_bin utf8")) + tk.MustQuery("select collation(concat(abin, utf8_gen_c)), charset(concat(abin, utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(concat(lbin, utf8_gen_c)), charset(concat(lbin, utf8_gen_c)) from t").Check(testkit.Rows("utf8_general_ci utf8")) + tk.MustQuery("select collation(concat(abin, lbin)), charset(concat(abin, lbin)) from t").Check(testkit.Rows("latin1_bin latin1")) tk.MustExec("set names utf8mb4 collate utf8mb4_bin") - tk.MustQuery("select collation('a')").Check(testkit.Rows("utf8mb4_bin")) + tk.MustQuery("select collation('a'), charset('a')").Check(testkit.Rows("utf8mb4_bin utf8mb4")) tk.MustExec("set names utf8mb4 collate utf8mb4_general_ci") - tk.MustQuery("select collation('a')").Check(testkit.Rows("utf8mb4_general_ci")) + tk.MustQuery("select collation('a'), charset('a')").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) tk.MustExec("set names utf8mb4 collate utf8mb4_general_ci") tk.MustExec("set @test_collate_var = 'a'") - tk.MustQuery("select collation(@test_collate_var)").Check(testkit.Rows("utf8mb4_general_ci")) + tk.MustQuery("select collation(@test_collate_var), charset(@test_collate_var)").Check(testkit.Rows("utf8mb4_general_ci utf8mb4")) tk.MustExec("set @test_collate_var = concat(\"a\", \"b\" collate utf8mb4_bin)") - tk.MustQuery("select collation(@test_collate_var)").Check(testkit.Rows("utf8mb4_bin")) + tk.MustQuery("select collation(@test_collate_var), charset(@test_collate_var)").Check(testkit.Rows("utf8mb4_bin utf8mb4")) tk.MustQuery("select locate('1', '123' collate utf8mb4_bin, 2 collate `binary`);").Check(testkit.Rows("0")) tk.MustQuery("select 1 in ('a' collate utf8mb4_bin, 'b' collate utf8mb4_general_ci);").Check(testkit.Rows("0")) @@ -4739,17 +4783,6 @@ func TestIssue17287(t *testing.T) { tk.MustQuery("execute stmt7 using @val2;").Check(testkit.Rows("1589873946")) } -func TestIssue26989(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("set names utf8mb4 collate utf8mb4_general_ci;") - tk.MustQuery("select position('a' in 'AA');").Check(testkit.Rows("0")) - tk.MustQuery("select locate('a', 'AA');").Check(testkit.Rows("0")) - tk.MustQuery("select locate('a', 'a');").Check(testkit.Rows("1")) -} - func TestIssue17898(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -5746,7 +5779,7 @@ func TestVitessHash(t *testing.T) { "(1, 30375298039), " + "(2, 1123), " + "(3, 30573721600), " + - "(4, " + fmt.Sprintf("%d", uint64(math.MaxUint64)) + ")," + + "(4, " + strconv.FormatUint(uint64(math.MaxUint64), 10) + ")," + "(5, 116)," + "(6, null);") @@ -6909,3 +6942,152 @@ func TestIssue30174(t *testing.T) { tk.MustQuery("select * from t2 where c3 in (select c2 from t1);").Check(testkit.Rows()) tk.MustQuery("select * from t2 where c2 in (select c2 from t1);").Check(testkit.Rows()) } + +func TestIssue30264(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // compare Time/Int/Int as string type, return string type + tk.MustQuery("select greatest(time '21:00', year(date'20220101'), 23);").Check(testkit.Rows("23")) + // compare Time/Date/Int as string type, return string type + tk.MustQuery("select greatest(time '21:00', date'891001', 120000);").Check(testkit.Rows("21:00:00")) + // compare Time/Date/Int as string type, return string type + tk.MustQuery("select greatest(time '20:00', date'101001', 120101);").Check(testkit.Rows("20:00:00")) + // compare Date/String/Int as Date type, return string type + tk.MustQuery("select greatest(date'101001', '19990329', 120101);").Check(testkit.Rows("2012-01-01")) + // compare Time/Date as DateTime type, return DateTime type + tk.MustQuery("select greatest(time '20:00', date'691231');").Check(testkit.Rows("2069-12-31 00:00:00")) + // compare Date/Date as Date type, return Date type + tk.MustQuery("select greatest(date '120301', date'691231');").Check(testkit.Rows("2069-12-31")) + // compare Time/Time as Time type, return Time type + tk.MustQuery("select greatest(time '203001', time '2230');").Check(testkit.Rows("20:30:01")) + // compare DateTime/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(timestamp '2021-01-31 00:00:01', timestamp '2021-12-31 12:00:00');").Check(testkit.Rows("2021-12-31 12:00:00")) + // compare Time/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(time '00:00:01', timestamp '2069-12-31 12:00:00');").Check(testkit.Rows("2069-12-31 12:00:00")) + // compare Date/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(date '21000101', timestamp '2069-12-31 12:00:00');").Check(testkit.Rows("2100-01-01 00:00:00")) + // compare JSON/JSON, return JSON type + tk.MustQuery("select greatest(cast('1' as JSON), cast('2' as JSON));").Check(testkit.Rows("2")) + //Original 30264 Issue: + tk.MustQuery("select greatest(time '20:00:00', 120000);").Check(testkit.Rows("20:00:00")) + tk.MustQuery("select greatest(date '2005-05-05', 20010101, 20040404, 20030303);").Check(testkit.Rows("2005-05-05")) + tk.MustQuery("select greatest(date '1995-05-05', 19910101, 20050505, 19930303);").Check(testkit.Rows("2005-05-05")) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1,t2;") + tk.MustExec("CREATE TABLE `t1` (a datetime, b date, c time)") + tk.MustExec("insert into t1 values(timestamp'2021-01-31 00:00:01', '2069-12-31', '20:00:01');") + tk.MustExec("set tidb_enable_vectorized_expression = on;") + // compare Time/Int/Int as string type, return string type + tk.MustQuery("select greatest(c, year(date'20220101'), 23) from t1;").Check(testkit.Rows("23")) + // compare Time/Date/Int as string type, return string type + tk.MustQuery("select greatest(c, date'891001', 120000) from t1;").Check(testkit.Rows("20:00:01")) + // compare Time/Date/Int as string type, return string type + tk.MustQuery("select greatest(c, date'101001', 120101) from t1;").Check(testkit.Rows("20:00:01")) + // compare Date/String/Int as Date type, return string type + tk.MustQuery("select greatest(b, '19990329', 120101) from t1;").Check(testkit.Rows("2069-12-31")) + // compare Time/Date as DateTime type, return DateTime type + tk.MustQuery("select greatest(time '20:00', b) from t1;").Check(testkit.Rows("2069-12-31 00:00:00")) + // compare Date/Date as Date type, return Date type + tk.MustQuery("select greatest(date '120301', b) from t1;").Check(testkit.Rows("2069-12-31")) + // compare Time/Time as Time type, return Time type + tk.MustQuery("select greatest(c, time '2230') from t1;").Check(testkit.Rows("20:00:01")) + // compare DateTime/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(a, timestamp '2021-12-31 12:00:00') from t1;").Check(testkit.Rows("2021-12-31 12:00:00")) + // compare Time/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(c, timestamp '2069-12-31 12:00:00') from t1;").Check(testkit.Rows("2069-12-31 12:00:00")) + // compare Date/DateTime as DateTime type, return DateTime type + tk.MustQuery("select greatest(date '21000101', a) from t1;").Check(testkit.Rows("2100-01-01 00:00:00")) + // compare JSON/JSON, return JSON type + tk.MustQuery("select greatest(cast(a as JSON), cast('3' as JSON)) from t1;").Check(testkit.Rows("3")) +} + +func TestIssue29708(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test;") + tk.MustExec("drop table if exists t1;") + tk.MustExec("CREATE TABLE t1 (a text)character set utf8 ;") + _, err := tk.Exec("INSERT INTO t1 VALUES (REPEAT(0125,200000000));") + require.NotNil(t, err) + tk.MustQuery("select * from t1").Check(nil) + + // test vectorized build-in function + tk.MustExec("insert into t1 (a) values ('a'),('b');") + _, err = tk.Exec("insert into t1 select REPEAT(a,200000000) from t1;") + require.NotNil(t, err) + tk.MustQuery("select a from t1 order by a;").Check([][]interface{}{ + {"a"}, + {"b"}, + }) + + // test cast + _, err = tk.Exec(`insert into t1 values (cast("a" as binary(4294967295)));`) + require.NotNil(t, err) + tk.MustQuery("select a from t1 order by a;").Check([][]interface{}{ + {"a"}, + {"b"}, + }) + + _, err = tk.Exec("INSERT IGNORE INTO t1 VALUES (REPEAT(0125,200000000));") + require.NoError(t, err) + tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1301 Result of repeat() was larger than max_allowed_packet (67108864) - truncated")) + tk.MustQuery("select a from t1 order by a;").Check([][]interface{}{ + {nil}, + {"a"}, + {"b"}, + }) +} + +func TestIssue22206(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tz := tk.Session().GetSessionVars().StmtCtx.TimeZone + result := tk.MustQuery("select from_unixtime(32536771199.999999)") + unixTime := time.Unix(32536771199, 999999000).In(tz).String()[:26] + result.Check(testkit.Rows(unixTime)) + result = tk.MustQuery("select from_unixtime('32536771200.000000')") + result.Check(testkit.Rows("")) + result = tk.MustQuery("select from_unixtime(5000000000);") + unixTime = time.Unix(5000000000, 0).In(tz).String()[:19] + result.Check(testkit.Rows(unixTime)) +} + +func TestIssue32488(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a varchar(32)) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;") + tk.MustExec("insert into t values('Êž'), ('Ä°');") + tk.MustExec("set @@tidb_enable_vectorized_expression = false;") + tk.MustQuery("select binary upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"Ä° i"}, {"êž° Êž"}}) + tk.MustQuery("select distinct upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"Ä° i"}, {"êž° Êž"}}) + tk.MustExec("set @@tidb_enable_vectorized_expression = true;") + tk.MustQuery("select binary upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"Ä° i"}, {"êž° Êž"}}) + tk.MustQuery("select distinct upper(a), lower(a) from t order by upper(a);").Check([][]interface{}{{"Ä° i"}, {"êž° Êž"}}) +} + +func TestIssue33397(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a varchar(32)) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;") + tk.MustExec("insert into t values(''), ('');") + tk.MustExec("set @@tidb_enable_vectorized_expression = true;") + result := tk.MustQuery("select compress(a) from t").Rows() + require.Equal(t, [][]interface{}{{""}, {""}}, result) +} diff --git a/expression/main_test.go b/expression/main_test.go index 9a1e170078f65..3c785e9a95f07 100644 --- a/expression/main_test.go +++ b/expression/main_test.go @@ -32,7 +32,7 @@ import ( var testDataMap = make(testdata.BookKeeper) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() testmain.ShortCircuitForBench(m) config.UpdateGlobal(func(conf *config.Config) { @@ -52,7 +52,8 @@ func TestMain(m *testing.M) { testDataMap.LoadTestSuiteData("testdata", "expression_suite") opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/expression/scalar_function.go b/expression/scalar_function.go index bbc3086ed944f..8e70a1a42af24 100644 --- a/expression/scalar_function.go +++ b/expression/scalar_function.go @@ -176,7 +176,7 @@ func typeInferForNull(args []Expression) { // -1 means try to fold constants if without errors/warnings, otherwise not. func newFunctionImpl(ctx sessionctx.Context, fold int, funcName string, retType *types.FieldType, args ...Expression) (Expression, error) { if retType == nil { - return nil, errors.Errorf("RetType cannot be nil for ScalarFunction.") + return nil, errors.Errorf("RetType cannot be nil for ScalarFunction") } switch funcName { case ast.Cast: @@ -187,6 +187,10 @@ func newFunctionImpl(ctx sessionctx.Context, fold int, funcName string, retType return BuildFromBinaryFunction(ctx, args[0], retType), nil case InternalFuncToBinary: return BuildToBinaryFunction(ctx, args[0]), nil + case ast.Sysdate: + if ctx.GetSessionVars().SysdateIsNow { + funcName = ast.Now + } } fc, ok := funcs[funcName] if !ok { diff --git a/expression/testdata/expression_suite_out.json b/expression/testdata/expression_suite_out.json index 8b89ee1e4dc81..7047b62ba1156 100644 --- a/expression/testdata/expression_suite_out.json +++ b/expression/testdata/expression_suite_out.json @@ -197,8 +197,8 @@ { "SQL": "explain format = 'brief' select * from t1 left join t2 on false", "Result": [ - "HashJoin 80000000.00 root CARTESIAN left outer join", - "├─TableDual(Build) 8000.00 root rows:0", + "HashJoin 10000.00 root CARTESIAN left outer join", + "├─TableDual(Build) 0.00 root rows:0", "└─TableReader(Probe) 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] @@ -206,8 +206,8 @@ { "SQL": "explain format = 'brief' select * from t1 right join t2 on false", "Result": [ - "HashJoin 80000000.00 root CARTESIAN right outer join", - "├─TableDual(Build) 8000.00 root rows:0", + "HashJoin 10000.00 root CARTESIAN right outer join", + "├─TableDual(Build) 0.00 root rows:0", "└─TableReader(Probe) 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ] @@ -215,8 +215,8 @@ { "SQL": "explain format = 'brief' select * from t1 left join t2 on t1.a = 1 and t1.a = 2", "Result": [ - "HashJoin 80000000.00 root CARTESIAN left outer join", - "├─TableDual(Build) 8000.00 root rows:0", + "HashJoin 10000.00 root CARTESIAN left outer join", + "├─TableDual(Build) 0.00 root rows:0", "└─TableReader(Probe) 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] @@ -224,18 +224,18 @@ { "SQL": "explain format = 'brief' select * from t1 left join t2 on t1.a =1 where t1.a = 2", "Result": [ - "HashJoin 80000.00 root CARTESIAN left outer join", - "├─TableReader(Build) 10.00 root data:Selection", - "│ └─Selection 10.00 cop[tikv] eq(test.t1.a, 2)", - "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", - "└─TableDual(Probe) 8000.00 root rows:0" + "HashJoin 10.00 root CARTESIAN left outer join", + "├─TableDual(Build) 0.00 root rows:0", + "└─TableReader(Probe) 10.00 root data:Selection", + " └─Selection 10.00 cop[tikv] eq(test.t1.a, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "SQL": "explain format = 'brief' select * from t1 left join t2 on t2.a = 1 and t2.a = 2", "Result": [ - "HashJoin 80000000.00 root CARTESIAN left outer join", - "├─TableDual(Build) 8000.00 root rows:0", + "HashJoin 10000.00 root CARTESIAN left outer join", + "├─TableDual(Build) 0.00 root rows:0", "└─TableReader(Probe) 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] diff --git a/expression/typeinfer_test.go b/expression/typeinfer_test.go index 639f3a8879601..5ebf61ca8b5e5 100644 --- a/expression/typeinfer_test.go +++ b/expression/typeinfer_test.go @@ -717,9 +717,9 @@ func (s *InferTypeSuite) createTestCase4ArithmeticFuncs() []typeInferTestCase { {"c_int_d + c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_int_d + c_time_d", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"c_int_d + c_double_d", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, - {"c_int_d + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, - {"c_datetime + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, - {"c_bigint_d + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, + {"c_int_d + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, + {"c_datetime + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, + {"c_bigint_d + c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, {"c_double_d + c_decimal", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d + c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d + c_enum", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, @@ -729,9 +729,9 @@ func (s *InferTypeSuite) createTestCase4ArithmeticFuncs() []typeInferTestCase { {"c_int_d - c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_int_d - c_time_d", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"c_int_d - c_double_d", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, - {"c_int_d - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, - {"c_datetime - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, - {"c_bigint_d - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 26, 3}, + {"c_int_d - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, + {"c_datetime - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, + {"c_bigint_d - c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 24, 3}, {"c_double_d - c_decimal", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d - c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d - c_enum", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, @@ -741,9 +741,9 @@ func (s *InferTypeSuite) createTestCase4ArithmeticFuncs() []typeInferTestCase { {"c_int_d * c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_int_d * c_time_d", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"c_int_d * c_double_d", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, - {"c_int_d * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 29, 3}, - {"c_datetime * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 31, 5}, - {"c_bigint_d * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 29, 3}, + {"c_int_d * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 27, 3}, + {"c_datetime * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 29, 5}, + {"c_bigint_d * c_decimal", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 27, 3}, {"c_double_d * c_decimal", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d * c_char", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, {"c_double_d * c_enum", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, types.UnspecifiedLength, types.UnspecifiedLength}, @@ -840,8 +840,8 @@ func (s *InferTypeSuite) createTestCase4ControlFuncs() []typeInferTestCase { {"case when c_int_d > 1 then c_double_d else c_bchar end", mysql.TypeString, charset.CharsetUTF8MB4, mysql.BinaryFlag, 22, types.UnspecifiedLength}, {"case when c_int_d > 2 then c_double_d when c_int_d < 1 then c_decimal else c_double_d end", mysql.TypeDouble, charset.CharsetBin, mysql.BinaryFlag, 22, 3}, {"case when c_double_d > 2 then c_decimal else 1 end", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, 6, 3}, - {"case when c_time is not null then c_time else c_date end", mysql.TypeDatetime, charset.CharsetUTF8MB4, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp + 3 + 1, 3}, - {"case when c_time_d is not null then c_time_d else c_date end", mysql.TypeDatetime, charset.CharsetUTF8MB4, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp, 0}, + {"case when c_time is not null then c_time else c_date end", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp + 3 + 1, 3}, + {"case when c_time_d is not null then c_time_d else c_date end", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp, 0}, {"case when null then null else null end", mysql.TypeNull, charset.CharsetBin, mysql.BinaryFlag, 0, types.UnspecifiedLength}, } } @@ -1059,10 +1059,29 @@ func (s *InferTypeSuite) createTestCase4CompareFuncs() []typeInferTestCase { {"greatest(c_bigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"greatest(c_ubigint_d, c_ubigint_d, c_uint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, mysql.MaxIntWidth, 0}, - {"greatest(c_uint_d, c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, 11, 0}, + {"greatest(c_uint_d, c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 11, 0}, {"least(c_bigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"least(c_ubigint_d, c_ubigint_d, c_uint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, mysql.MaxIntWidth, 0}, {"least(c_uint_d, c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 11, 0}, + + // bigint unsigned + int = Decimal. (compatible with mysql) + {"greatest(c_ubigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, + {"least(c_ubigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, + + // bigint unsgined + bigint = Decimal. (compatible with mysql) + {"greatest(c_bigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, + {"least(c_bigint_d, c_ubigint_d, c_int_d)", mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, + + // xxxint unsgined + xxxint unsigned = bigint unsigned. (not compatible with mysql, mysql is int if xxxint unsigned is smallint/mediumint) + {"greatest(c_ubigint_d, c_ubigint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, mysql.MaxIntWidth, 0}, + {"least(c_ubigint_d, c_ubigint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, mysql.MaxIntWidth, 0}, + + {"greatest(c_uint_d, c_uint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, 10, 0}, + {"least(c_uint_d, c_uint_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag, 10, 0}, + + // xxxint unsgined + xxxint = bigint. (not compatible with mysql, mysql is int if xxxint is smallint/mediumint) + {"greatest(c_int_d, c_uint_d, c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 11, 0}, + {"least(c_int_d, c_uint_d, c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 11, 0}, } } @@ -1223,7 +1242,7 @@ func (s *InferTypeSuite) createTestCase4OtherFuncs() []typeInferTestCase { {"bit_count(c_set )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 2, 0}, {"bit_count(c_enum )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 2, 0}, - {`@varname`, mysql.TypeVarString, charset.CharsetUTF8MB4, 0, mysql.MaxFieldVarCharLength, int(types.UnspecifiedFsp)}, + {`@varname`, mysql.TypeVarString, charset.CharsetUTF8MB4, 0, mysql.MaxFieldVarCharLength, types.UnspecifiedFsp}, } } @@ -1803,9 +1822,9 @@ func (s *InferTypeSuite) createTestCase4TimeFuncs() []typeInferTestCase { {"quarter(c_set )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 1, 0}, {"quarter(c_enum )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 1, 0}, - {"current_time()", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 8, int(types.MinFsp)}, - {"current_time(0)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 8, int(types.MinFsp)}, - {"current_time(6)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 15, int(types.MaxFsp)}, + {"current_time()", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 8, types.MinFsp}, + {"current_time(0)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 8, types.MinFsp}, + {"current_time(6)", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 15, types.MaxFsp}, {"sec_to_time(c_int_d )", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, 10, 0}, {"sec_to_time(c_bigint_d )", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, 10, 0}, @@ -1847,11 +1866,11 @@ func (s *InferTypeSuite) createTestCase4TimeFuncs() []typeInferTestCase { {"time_to_sec(c_set )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 10, 0}, {"time_to_sec(c_enum )", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 10, 0}, - {"str_to_date(c_varchar, '%Y:%m:%d')", mysql.TypeDate, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDateWidth, int(types.MinFsp)}, - {"str_to_date(c_varchar, '%Y:%m:%d %H:%i:%s')", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp, int(types.MinFsp)}, - {"str_to_date(c_varchar, '%Y:%m:%d %H:%i:%s.%f')", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthWithFsp, int(types.MaxFsp)}, - {"str_to_date(c_varchar, '%H:%i:%s')", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDurationWidthNoFsp, int(types.MinFsp)}, - {"str_to_date(c_varchar, '%H:%i:%s.%f')", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDurationWidthWithFsp, int(types.MaxFsp)}, + {"str_to_date(c_varchar, '%Y:%m:%d')", mysql.TypeDate, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDateWidth, types.MinFsp}, + {"str_to_date(c_varchar, '%Y:%m:%d %H:%i:%s')", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthNoFsp, types.MinFsp}, + {"str_to_date(c_varchar, '%Y:%m:%d %H:%i:%s.%f')", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthWithFsp, types.MaxFsp}, + {"str_to_date(c_varchar, '%H:%i:%s')", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDurationWidthNoFsp, types.MinFsp}, + {"str_to_date(c_varchar, '%H:%i:%s.%f')", mysql.TypeDuration, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDurationWidthWithFsp, types.MaxFsp}, {"period_add(c_int_d , c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 6, 0}, {"period_add(c_bigint_d , c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 6, 0}, @@ -1896,7 +1915,7 @@ func (s *InferTypeSuite) createTestCase4TimeFuncs() []typeInferTestCase { {"get_format(DATE, 'USA')", mysql.TypeVarString, charset.CharsetUTF8MB4, mysql.NotNullFlag, 17, types.UnspecifiedLength}, - {"convert_tz(c_time_d, c_text_d, c_text_d)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthWithFsp, int(types.MaxFsp)}, + {"convert_tz(c_time_d, c_text_d, c_text_d)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDatetimeWidthWithFsp, types.MaxFsp}, {"convert_tz('2004-01-01 12:00:00.123', c_text_d, c_text_d)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 23, 3}, {"from_unixtime(20170101.999)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag | mysql.NotNullFlag, 23, 3}, @@ -1906,6 +1925,17 @@ func (s *InferTypeSuite) createTestCase4TimeFuncs() []typeInferTestCase { {"extract(day from c_char)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, {"extract(hour from c_char)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxIntWidth, 0}, + + {"date_add('20121212', interval 1 day)", mysql.TypeVarString, charset.CharsetUTF8MB4, mysql.NotNullFlag, mysql.MaxDatetimeFullWidth, types.UnspecifiedLength}, + {"date_sub('20121212', interval 1 day)", mysql.TypeVarString, charset.CharsetUTF8MB4, mysql.NotNullFlag, mysql.MaxDatetimeFullWidth, types.UnspecifiedLength}, + {"date_add(c_datetime, interval 1 day)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, + {"date_sub(c_datetime, interval 1 day)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, + {"date_add(c_datetime, interval 1 hour)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, + {"date_sub(c_datetime, interval 1 hour)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, + {"date_add(c_date, interval 1 day)", mysql.TypeDate, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDateWidth, 0}, + {"date_sub(c_date, interval 1 day)", mysql.TypeDate, charset.CharsetBin, mysql.BinaryFlag, mysql.MaxDateWidth, 0}, + {"date_add(c_date, interval 1 hour)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, + {"date_sub(c_date, interval 1 hour)", mysql.TypeDatetime, charset.CharsetBin, mysql.BinaryFlag, 26, 6}, } } diff --git a/expression/util.go b/expression/util.go index d7b92329d51f6..109b68f5c9985 100644 --- a/expression/util.go +++ b/expression/util.go @@ -166,8 +166,70 @@ func extractColumns(result []*Column, expr Expression, filter func(*Column) bool return result } -// ExtractColumnsAndCorColumns extracts columns and correlated columns from `expr` and append them to `result`. -func ExtractColumnsAndCorColumns(result []*Column, expr Expression) []*Column { +// ExtractEquivalenceColumns detects the equivalence from CNF exprs. +func ExtractEquivalenceColumns(result [][]Expression, exprs []Expression) [][]Expression { + // exprs are CNF expressions, EQ condition only make sense in the top level of every expr. + for _, expr := range exprs { + result = extractEquivalenceColumns(result, expr) + } + return result +} + +func extractEquivalenceColumns(result [][]Expression, expr Expression) [][]Expression { + switch v := expr.(type) { + case *ScalarFunction: + // a==b, a<=>b, the latter one is evaluated to true when a,b are both null. + if v.FuncName.L == ast.EQ || v.FuncName.L == ast.NullEQ { + args := v.GetArgs() + if len(args) == 2 { + col1, ok1 := args[0].(*Column) + col2, ok2 := args[1].(*Column) + if ok1 && ok2 { + result = append(result, []Expression{col1, col2}) + } + col, ok1 := args[0].(*Column) + scl, ok2 := args[1].(*ScalarFunction) + if ok1 && ok2 { + result = append(result, []Expression{col, scl}) + } + col, ok1 = args[1].(*Column) + scl, ok2 = args[0].(*ScalarFunction) + if ok1 && ok2 { + result = append(result, []Expression{col, scl}) + } + } + return result + } + if v.FuncName.L == ast.In { + args := v.GetArgs() + // only `col in (only 1 element)`, can we build an equivalence here. + if len(args[1:]) == 1 { + col1, ok1 := args[0].(*Column) + col2, ok2 := args[1].(*Column) + if ok1 && ok2 { + result = append(result, []Expression{col1, col2}) + } + col, ok1 := args[0].(*Column) + scl, ok2 := args[1].(*ScalarFunction) + if ok1 && ok2 { + result = append(result, []Expression{col, scl}) + } + col, ok1 = args[1].(*Column) + scl, ok2 = args[0].(*ScalarFunction) + if ok1 && ok2 { + result = append(result, []Expression{col, scl}) + } + } + return result + } + // For Non-EQ function, we don't have to traverse down. + // eg: (a=b or c=d) doesn't make any definitely equivalence assertion. + } + return result +} + +// extractColumnsAndCorColumns extracts columns and correlated columns from `expr` and append them to `result`. +func extractColumnsAndCorColumns(result []*Column, expr Expression) []*Column { switch v := expr.(type) { case *Column: result = append(result, v) @@ -175,8 +237,101 @@ func ExtractColumnsAndCorColumns(result []*Column, expr Expression) []*Column { result = append(result, &v.Column) case *ScalarFunction: for _, arg := range v.GetArgs() { - result = ExtractColumnsAndCorColumns(result, arg) + result = extractColumnsAndCorColumns(result, arg) + } + } + return result +} + +// ExtractConstantEqColumnsOrScalar detects the constant equal relationship from CNF exprs. +func ExtractConstantEqColumnsOrScalar(ctx sessionctx.Context, result []Expression, exprs []Expression) []Expression { + // exprs are CNF expressions, EQ condition only make sense in the top level of every expr. + for _, expr := range exprs { + result = extractConstantEqColumnsOrScalar(ctx, result, expr) + } + return result +} + +func extractConstantEqColumnsOrScalar(ctx sessionctx.Context, result []Expression, expr Expression) []Expression { + switch v := expr.(type) { + case *ScalarFunction: + if v.FuncName.L == ast.EQ || v.FuncName.L == ast.NullEQ { + args := v.GetArgs() + if len(args) == 2 { + col, ok1 := args[0].(*Column) + _, ok2 := args[1].(*Constant) + if ok1 && ok2 { + result = append(result, col) + } + col, ok1 = args[1].(*Column) + _, ok2 = args[0].(*Constant) + if ok1 && ok2 { + result = append(result, col) + } + // take the correlated column as constant here. + col, ok1 = args[0].(*Column) + _, ok2 = args[1].(*CorrelatedColumn) + if ok1 && ok2 { + result = append(result, col) + } + col, ok1 = args[1].(*Column) + _, ok2 = args[0].(*CorrelatedColumn) + if ok1 && ok2 { + result = append(result, col) + } + scl, ok1 := args[0].(*ScalarFunction) + _, ok2 = args[1].(*Constant) + if ok1 && ok2 { + result = append(result, scl) + } + scl, ok1 = args[1].(*ScalarFunction) + _, ok2 = args[0].(*Constant) + if ok1 && ok2 { + result = append(result, scl) + } + // take the correlated column as constant here. + scl, ok1 = args[0].(*ScalarFunction) + _, ok2 = args[1].(*CorrelatedColumn) + if ok1 && ok2 { + result = append(result, scl) + } + scl, ok1 = args[1].(*ScalarFunction) + _, ok2 = args[0].(*CorrelatedColumn) + if ok1 && ok2 { + result = append(result, scl) + } + } + return result + } + if v.FuncName.L == ast.In { + args := v.GetArgs() + allArgsIsConst := true + // only `col in (all same const)`, can col be the constant column. + // eg: a in (1, "1") does, while a in (1, '2') doesn't. + guard := args[1] + for i, v := range args[1:] { + if _, ok := v.(*Constant); !ok { + allArgsIsConst = false + break + } + if i == 0 { + continue + } + if !guard.Equal(ctx, v) { + allArgsIsConst = false + break + } + } + if allArgsIsConst { + if col, ok := args[0].(*Column); ok { + result = append(result, col) + } else if scl, ok := args[0].(*ScalarFunction); ok { + result = append(result, scl) + } + } + return result } + // For Non-EQ function, we don't have to traverse down. } return result } @@ -184,13 +339,13 @@ func ExtractColumnsAndCorColumns(result []*Column, expr Expression) []*Column { // ExtractColumnsAndCorColumnsFromExpressions extracts columns and correlated columns from expressions and append them to `result`. func ExtractColumnsAndCorColumnsFromExpressions(result []*Column, list []Expression) []*Column { for _, expr := range list { - result = ExtractColumnsAndCorColumns(result, expr) + result = extractColumnsAndCorColumns(result, expr) } return result } // ExtractColumnSet extracts the different values of `UniqueId` for columns in expressions. -func ExtractColumnSet(exprs []Expression) *intsets.Sparse { +func ExtractColumnSet(exprs ...Expression) *intsets.Sparse { set := &intsets.Sparse{} for _, expr := range exprs { extractColumnSet(expr, set) @@ -538,6 +693,41 @@ func PushDownNot(ctx sessionctx.Context, expr Expression) Expression { return newExpr } +// ContainOuterNot checks if there is an outer `not`. +func ContainOuterNot(expr Expression) bool { + return containOuterNot(expr, false) +} + +// containOuterNot checks if there is an outer `not`. +// Input `not` means whether there is `not` outside `expr` +// +// eg. +// not(0+(t.a == 1 and t.b == 2)) returns true +// not(t.a) and not(t.b) returns false +func containOuterNot(expr Expression, not bool) bool { + if f, ok := expr.(*ScalarFunction); ok { + switch f.FuncName.L { + case ast.UnaryNot: + return containOuterNot(f.GetArgs()[0], true) + case ast.IsTruthWithNull, ast.IsNull: + return containOuterNot(f.GetArgs()[0], not) + default: + if not { + return true + } + hasNot := false + for _, expr := range f.GetArgs() { + hasNot = hasNot || containOuterNot(expr, not) + if hasNot { + return hasNot + } + } + return hasNot + } + } + return false +} + // Contains tests if `exprs` contains `e`. func Contains(exprs []Expression, e Expression) bool { for _, expr := range exprs { @@ -719,13 +909,13 @@ func DatumToConstant(d types.Datum, tp byte, flag uint) *Constant { } // ParamMarkerExpression generate a getparam function expression. -func ParamMarkerExpression(ctx sessionctx.Context, v *driver.ParamMarkerExpr) (Expression, error) { +func ParamMarkerExpression(ctx sessionctx.Context, v *driver.ParamMarkerExpr, needParam bool) (*Constant, error) { useCache := ctx.GetSessionVars().StmtCtx.UseCache isPointExec := ctx.GetSessionVars().StmtCtx.PointExec tp := types.NewFieldType(mysql.TypeUnspecified) types.DefaultParamTypeForValue(v.GetValue(), tp) value := &Constant{Value: v.Datum, RetType: tp} - if useCache || isPointExec { + if useCache || isPointExec || needParam { value.ParamMarker = &ParamMarker{ order: v.Order, ctx: ctx, @@ -760,7 +950,7 @@ func PosFromPositionExpr(ctx sessionctx.Context, v *ast.PositionExpr) (int, bool if v.P == nil { return v.N, false, nil } - value, err := ParamMarkerExpression(ctx, v.P.(*driver.ParamMarkerExpr)) + value, err := ParamMarkerExpression(ctx, v.P.(*driver.ParamMarkerExpr), false) if err != nil { return 0, true, err } @@ -826,6 +1016,42 @@ func IsRuntimeConstExpr(expr Expression) bool { return false } +// CheckNonDeterministic checks whether the current expression contains a non-deterministic func. +func CheckNonDeterministic(e Expression) bool { + switch x := e.(type) { + case *Constant, *Column, *CorrelatedColumn: + return false + case *ScalarFunction: + if _, ok := unFoldableFunctions[x.FuncName.L]; ok { + return true + } + for _, arg := range x.GetArgs() { + if CheckNonDeterministic(arg) { + return true + } + } + } + return false +} + +// CheckFuncInExpr checks whether there's a given function in the expression. +func CheckFuncInExpr(e Expression, funcName string) bool { + switch x := e.(type) { + case *Constant, *Column, *CorrelatedColumn: + return false + case *ScalarFunction: + if x.FuncName.L == funcName { + return true + } + for _, arg := range x.GetArgs() { + if CheckFuncInExpr(arg, funcName) { + return true + } + } + } + return false +} + // IsMutableEffectsExpr checks if expr contains function which is mutable or has side effects. func IsMutableEffectsExpr(expr Expression) bool { switch x := expr.(type) { @@ -1145,11 +1371,7 @@ func (r *SQLDigestTextRetriever) runFetchDigestQuery(ctx context.Context, sctx s stmt += " where digest in (" + strings.Repeat("%?,", len(inValues)-1) + "%?)" } - stmtNode, err := exec.ParseWithParams(ctx, stmt, inValues...) - if err != nil { - return nil, err - } - rows, _, err := exec.ExecRestrictedStmt(ctx, stmtNode) + rows, _, err := exec.ExecRestrictedSQL(ctx, nil, stmt, inValues...) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index 3c2868df8b118..171473bb1b606 100644 --- a/go.mod +++ b/go.mod @@ -1,104 +1,210 @@ module github.com/pingcap/tidb -go 1.16 +go 1.18 require ( - cloud.google.com/go/storage v1.16.1 + cloud.google.com/go/storage v1.21.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.12.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0 github.com/BurntSushi/toml v0.3.1 github.com/DATA-DOG/go-sqlmock v1.5.0 - github.com/HdrHistogram/hdrhistogram-go v1.1.0 // indirect github.com/Jeffail/gabs/v2 v2.5.1 + github.com/Shopify/sarama v1.29.0 github.com/aws/aws-sdk-go v1.35.3 github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d github.com/carlmjohnson/flagext v0.21.0 github.com/cheggaaa/pb/v3 v3.0.8 github.com/cheynewallace/tabby v1.1.1 github.com/cockroachdb/pebble v0.0.0-20210719141320-8c3bd06debb5 - github.com/coocood/freecache v1.1.1 + github.com/coocood/freecache v1.2.1 github.com/coreos/go-semver v0.3.0 github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8 github.com/danjacques/gofslock v0.0.0-20191023191349-0a45f885bc37 - github.com/dgraph-io/ristretto v0.0.1 - github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 + github.com/dgraph-io/ristretto v0.1.1-0.20220403145359-8e850b710d6d + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 github.com/docker/go-units v0.4.0 - github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect github.com/fsouza/fake-gcs-server v1.19.0 github.com/go-sql-driver/mysql v1.6.0 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 - github.com/golang/snappy v0.0.3 - github.com/google/btree v1.0.0 - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 + github.com/golang/snappy v0.0.4 + github.com/google/btree v1.0.1 + github.com/google/pprof v0.0.0-20211122183932-1daafda22083 github.com/google/uuid v1.1.2 - github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 - github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 - github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/iancoleman/strcase v0.2.0 github.com/jedib0t/go-pretty/v6 v6.2.2 github.com/joho/sqltocsv v0.0.0-20210428211105-a6d6801d59df github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7 - github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef github.com/opentracing/basictracer-go v1.0.0 - github.com/opentracing/opentracing-go v1.1.0 + github.com/opentracing/opentracing-go v1.2.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 - github.com/pingcap/badger v1.5.1-0.20210831093107-2f6cb8008145 - github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712 - github.com/pingcap/errors v0.11.5-0.20211009033009-93128226aaa3 - github.com/pingcap/failpoint v0.0.0-20210316064728-7acb0f0a3dfd + github.com/pingcap/badger v1.5.1-0.20220314162537-ab58fbf40580 + github.com/pingcap/check v0.0.0-20211026125417-57bd13f7b5f0 + github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c + github.com/pingcap/failpoint v0.0.0-20220303073211-00fea37feb66 github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059 - github.com/pingcap/kvproto v0.0.0-20211122024046-03abd340988f - github.com/pingcap/log v0.0.0-20210906054005-afc726e70354 - github.com/pingcap/sysutil v0.0.0-20211208032423-041a72e5860d - github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible + github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73 + github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee + github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4 github.com/pingcap/tidb/parser v0.0.0-20211011031125-9b13dc409c5e - github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba - github.com/prometheus/client_golang v1.5.1 + github.com/pingcap/tipb v0.0.0-20220215045658-d12dec7a7609 + github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.9.1 - github.com/shirou/gopsutil v3.21.3+incompatible + github.com/prometheus/common v0.32.1 + github.com/shirou/gopsutil/v3 v3.21.12 github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0 - github.com/sirupsen/logrus v1.8.1 // indirect - github.com/soheilhy/cmux v0.1.4 - github.com/spf13/cobra v1.0.0 + github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect + github.com/soheilhy/cmux v0.1.5 + github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2 - github.com/tikv/client-go/v2 v2.0.0-rc.0.20211214093715-605f49d3ba50 - github.com/tikv/pd v1.1.0-beta.0.20211118054146-02848d2660ee + github.com/tikv/client-go/v2 v2.0.1-0.20220406091203-f73ec0e675f4 + github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 github.com/twmb/murmur3 v1.1.3 github.com/uber/jaeger-client-go v2.22.1+incompatible - github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/wangjohn/quickselect v0.0.0-20161129230411-ed8402a42d5f github.com/xitongsys/parquet-go v1.5.5-0.20201110004701-b09c49d6d457 github.com/xitongsys/parquet-go-source v0.0.0-20200817004010-026bad9b25d0 - go.etcd.io/etcd v0.5.0-alpha.5.0.20210512015243-d19fbe541bf9 + go.etcd.io/etcd/api/v3 v3.5.2 + go.etcd.io/etcd/client/pkg/v3 v3.5.2 + go.etcd.io/etcd/client/v3 v3.5.2 + go.etcd.io/etcd/server/v3 v3.5.2 + go.etcd.io/etcd/tests/v3 v3.5.2 go.uber.org/atomic v1.9.0 go.uber.org/automaxprocs v1.4.0 go.uber.org/goleak v1.1.12 - go.uber.org/multierr v1.7.0 - go.uber.org/zap v1.19.1 - golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 - golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a + go.uber.org/multierr v1.8.0 + go.uber.org/zap v1.21.0 + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e + golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f golang.org/x/text v0.3.7 - golang.org/x/tools v0.1.5 - google.golang.org/api v0.54.0 - google.golang.org/grpc v1.40.0 - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 + golang.org/x/tools v0.1.8 + google.golang.org/api v0.69.0 + google.golang.org/grpc v1.44.0 gopkg.in/yaml.v2 v2.4.0 modernc.org/mathutil v1.4.1 sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -// cloud.google.com/go/storage will upgrade grpc to v1.40.0 -// we need keep the replacement until go.etcd.io supports the higher version of grpc. -replace google.golang.org/grpc => google.golang.org/grpc v1.29.1 +require ( + cloud.google.com/go v0.100.2 // indirect + cloud.google.com/go/compute v1.2.0 // indirect + cloud.google.com/go/iam v0.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect + github.com/VividCortex/ewma v1.1.1 // indirect + github.com/apache/thrift v0.13.1-0.20201008052519-daf620915714 // indirect + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cockroachdb/errors v1.8.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect + github.com/cockroachdb/redact v1.0.8 // indirect + github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect + github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64 // indirect + github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/eapache/go-resiliency v1.2.0 // indirect + github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect + github.com/eapache/queue v1.1.0 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/golang/glog v1.0.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-cmp v0.5.7 // indirect + github.com/googleapis/gax-go/v2 v2.1.1 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jcmturner/aescts/v2 v2.0.0 // indirect + github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect + github.com/jcmturner/gofork v1.0.0 // indirect + github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect + github.com/jcmturner/rpc/v2 v2.0.3 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/json-iterator/go v1.1.11 // indirect + github.com/klauspost/compress v1.15.1 // indirect + github.com/klauspost/cpuid v1.3.1 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.12 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/ncw/directio v1.0.5 // indirect + github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef // indirect + github.com/pierrec/lz4 v2.6.1+incompatible // indirect + github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 // indirect + github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect + github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect + github.com/tklauser/numcpus v0.3.0 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect + github.com/uber/jaeger-lib v2.4.1+incompatible // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + go.etcd.io/etcd/client/v2 v2.305.2 // indirect + go.etcd.io/etcd/pkg/v3 v3.5.2 // indirect + go.etcd.io/etcd/raft/v3 v3.5.2 // indirect + go.opencensus.io v0.23.0 // indirect + go.opentelemetry.io/contrib v0.20.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect + go.opentelemetry.io/otel v0.20.0 // indirect + go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect + go.opentelemetry.io/otel/metric v0.20.0 // indirect + go.opentelemetry.io/otel/sdk v0.20.0 // indirect + go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect + go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect + go.opentelemetry.io/otel/trace v0.20.0 // indirect + go.opentelemetry.io/proto/otlp v0.7.0 // indirect + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect + golang.org/x/exp v0.0.0-20200513190911-00229845015e // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + sigs.k8s.io/yaml v1.2.0 // indirect +) replace github.com/pingcap/tidb/parser => ./parser // fix potential security issue(CVE-2020-26160) introduced by indirect dependency. replace github.com/dgrijalva/jwt-go => github.com/form3tech-oss/jwt-go v3.2.6-0.20210809144907-32ab6a8243d7+incompatible + +// fix date race in the testify. it can be remove after merging https://github.com/stretchr/testify/pull/1165 +replace github.com/stretchr/testify => github.com/hawkingrei/testify v1.7.1-0.20220318075534-088488aa27f2 diff --git a/go.sum b/go.sum index a6b2d60e60a01..508ffc71c96fe 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= @@ -21,16 +22,27 @@ cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAV cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3 h1:wPBktZFzYBcCZVARvwVKqH1uEj+aLXofJEtrb4oOsio= cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.2.0 h1:EKki8sSdvDU0OO9mAXGwPXOTOgPz2l08R0/IutDH11I= +cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68= +cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -40,10 +52,18 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.16.1 h1:sMEIc4wxvoY3NXG7Rn9iP7jb/2buJgWR1vNXCR/UPfs= -cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4= +cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14= +cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0 h1:KQgdWmEOmaJKxaUUZwHAYh12t+b+ZJf8q3friycK1kA= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0/go.mod h1:ZPW/Z0kLCTdDZaDbYTetxc9Cxl/2lNqxYHYNOF2bti0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.12.0 h1:VBvHGLJbaY0+c66NZHdS9cgjHVYSH6DDa0XJMyrblsI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.12.0/go.mod h1:GJzjM4SR9T0KyX5gKCVyz1ytD8FeWeUPCwtFCt1AyfE= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1 h1:BUYIbDf/mMZ8945v3QkG3OuqGVyS4Iek0AOLwdRAYoc= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0 h1:62Ew5xXg5UCGIXDOM7+y4IL5/6mQJq1nenhBCJAeGX8= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0/go.mod h1:eHWhQKXc1Gv1DvWH//UzgWjWFEo0Pp4pH2vBzjBw8Fc= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -53,63 +73,61 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I= -github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Jeffail/gabs/v2 v2.5.1 h1:ANfZYjpMlfTTKebycu4X1AgkVWumFVDYQl7JwOr4mDk= github.com/Jeffail/gabs/v2 v2.5.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= -github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/ReneKroon/ttlcache/v2 v2.3.0/go.mod h1:zbo6Pv/28e21Z8CzzqgYRArQYGYtjONRxaAKGxzQvG4= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/Shopify/sarama v1.29.0 h1:ARid8o8oieau9XrHI55f/L3EoRAhm9px6sonbD7yuUE= +github.com/Shopify/sarama v1.29.0/go.mod h1:2QpgD79wpdAESqNQMxNc0KYMkycd4slxGdV3TWSVqrU= +github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= -github.com/VividCortex/mysqlerr v0.0.0-20200629151747-c28746d985dd/go.mod h1:f3HiCrHjHBdcm6E83vGaXh1KomZMA2P6aeo3hKx/wg0= -github.com/Xeoncross/go-aesctr-with-hmac v0.0.0-20200623134604-12b17a7ff502/go.mod h1:pmnBM9bxWSiHvC/gSWunUIyDvGn33EkP2CUjxFKtTTM= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alvaroloes/enumer v1.1.2/go.mod h1:FxrjvuXoDAx9isTJrv4c+T410zFi0DtXIT0m65DJ+Wo= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.0.0-20181112125854-24918abba929/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.1-0.20201008052519-daf620915714 h1:Jz3KVLYY5+JO7rDiX0sAuRGtuv2vG01r17Y9nLMWNUw= github.com/apache/thrift v0.13.1-0.20201008052519-daf620915714/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/appleboy/gin-jwt/v2 v2.6.3/go.mod h1:MfPYA4ogzvOcVkRwAxT7quHOtQmVKDpTwxyUrC2DNw0= -github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.30.19/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.35.3 h1:r0puXncSaAfRt7Btml2swUo74Kao+vKhO3VLjwDjK54= github.com/aws/aws-sdk-go v1.35.3/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d h1:rQlvB2AYWme2bIB18r/SipGiMEVJYE9U0z+MGoU/LtQ= github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= -github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 h1:BjkPE3785EwPhhyuFkbINB+2a1xATwk8SNDWnJiD41g= -github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5/go.mod h1:jtAfVaU/2cu1+wdSRPWE2c1N2qeAA3K4RH9pYgqwets= github.com/carlmjohnson/flagext v0.21.0 h1:/c4uK3ie786Z7caXLcIMvePNSSiH3bQVGDvmGLMme60= github.com/carlmjohnson/flagext v0.21.0/go.mod h1:Eenv0epIUAr4NuedNmkzI8WmBmjIxZC239XcKxYS2ac= -github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA= github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA= github.com/cheynewallace/tabby v1.1.1 h1:JvUR8waht4Y0S3JF17G6Vhyt+FRhnqVCkk8l4YrOU54= @@ -117,10 +135,19 @@ github.com/cheynewallace/tabby v1.1.1/go.mod h1:Pba/6cUL8uYqvOc9RkyvFbHGrQ9wShyr github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/datadriven v1.0.0 h1:uhZrAfEayBecH2w2tZmhe20HJ7hDvrrA4x2Bg9YdZKM= github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= @@ -137,27 +164,24 @@ github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcju github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64 h1:W1SHiII3e0jVwvaQFglwu3kS9NLxOeTpvik7MbKCyuQ= github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64/go.mod h1:F86k/6c7aDUdwSUevnLpHS/3Q9hzYCE99jGk2xsHnt0= -github.com/coocood/freecache v1.1.1 h1:uukNF7QKCZEdZ9gAV7WQzvh0SbjwdMF6m3x3rxEkaPc= -github.com/coocood/freecache v1.1.1/go.mod h1:OKrEjkGVoxZhyWAJoeFi5BMLUJm2Tit0kpGkIr7NGYY= +github.com/coocood/freecache v1.2.1 h1:/v1CqMq45NFH9mp/Pt142reundeBM0dVUD3osQBeu/U= +github.com/coocood/freecache v1.2.1/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk= github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2 h1:NnLfQ77q0G4k2Of2c1ceQ0ec6MkLQyDp+IGdVM0D8XM= github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2/go.mod h1:7qG7YFnOALvsx6tKTNmQot8d7cGFXM9TidzvRFLWYwM= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso= @@ -171,57 +195,70 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgraph-io/ristretto v0.0.1 h1:cJwdnj42uV8Jg4+KLrYovLiCgIfz9wtWm6E6KA+1tLs= -github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= +github.com/dgraph-io/ristretto v0.1.1-0.20220403145359-8e850b710d6d h1:Wrc3UKTS+cffkOx0xRGFC+ZesNuTfn0ThvEC72N0krk= +github.com/dgraph-io/ristretto v0.1.1-0.20220403145359-8e850b710d6d/go.mod h1:RAy2GVV4sTWVlNMavv3xhLsk18rxhfhDnombTe6EF5c= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= +github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.6-0.20210809144907-32ab6a8243d7+incompatible h1:0sWoh2EtO7UrQdNTAN+hnU3QXa4AoivplyPLLHkcrLk= github.com/form3tech-oss/jwt-go v3.2.6-0.20210809144907-32ab6a8243d7+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsouza/fake-gcs-server v1.19.0 h1:XyaGOlqo+R5sjT03x2ymk0xepaQlgwhRLTT2IopW0zA= github.com/fsouza/fake-gcs-server v1.19.0/go.mod h1:JtXHY/QzHhtyIxsNfIuQ+XgHtRb5B/w8nqbL5O8zqo0= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= -github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-echarts/go-echarts v1.0.0/go.mod h1:qbmyAb/Rl1f2w7wKba1D4LoNq4U164yO4/wedFbcWyo= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -229,36 +266,22 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/overalls v0.0.0-20180201144345-22ec1a223b7c/go.mod h1:UqxAgEOt89sCiXlrc/ycnx00LVvUO/eS8tMUkWX4R7w= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v0.0.0-20180717141946-636bf0302bc9/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -271,12 +294,14 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -310,12 +335,14 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -327,8 +354,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -342,100 +370,127 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200407044318-7d83b28da2e9/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211122183932-1daafda22083 h1:c8EUapQFi+kjzedr4c6WqbwMdmB95+oDBWZ5XFHFYxY= +github.com/google/pprof v0.0.0-20211122183932-1daafda22083/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.1 h1:zCy2xE9ablevUOrUZc3Dl72Dt+ya2FNAvC2yLYMHzi4= github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hawkingrei/testify v1.7.1-0.20220318075534-088488aa27f2 h1:ISVSMZv3HuDPbTAd76vrHWlomIe8lJOp4KovWngSVpY= +github.com/hawkingrei/testify v1.7.1-0.20220318075534-088488aa27f2/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= -github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= -github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v0.0.0-20180107083740-2aebee971930/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= +github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jedib0t/go-pretty/v6 v6.2.2 h1:o3McN0rQ4X+IU+HduppSp9TwRdGLRW2rhJXy9CJaCRw= github.com/jedib0t/go-pretty/v6 v6.2.2/go.mod h1:+nE9fyyHGil+PuISTCrp7avEdo6bqoMwqZnuiK2r2a0= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/sqltocsv v0.0.0-20210428211105-a6d6801d59df h1:Zrb0IbuLOGHL7nrO2WrcuNWgDTlzFv3zY69QMx4ggQE= github.com/joho/sqltocsv v0.0.0-20210428211105-a6d6801d59df/go.mod h1:mAVCUAYtW9NG31eB30umMSLKcDt6mCUWSjoSn5qBh0k= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/joomcode/errorx v1.0.1/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ= -github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= -github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= @@ -451,57 +506,60 @@ github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= +github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= +github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= -github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= -github.com/mgechev/revive v1.0.2/go.mod h1:rb0dQy1LVAxW9SWy5R3LPUjevzUbUS316U5MFySA2lo= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/minio/sio v0.3.0/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -509,97 +567,87 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk= -github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/directio v1.0.4 h1:CojwI07mCEmRkajgx42Pf8jyCwTs1ji9/Ij9/PJG12k= github.com/ncw/directio v1.0.4/go.mod h1:CKGdcN7StAaqjT7Qack3lAXeX4pjnyc46YeqZH1yWVY= -github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4= +github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk= github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7 h1:7KAv7KMGTTqSmYZtNdcNTgsos+vFzULLwyElndwn+5c= github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7/go.mod h1:iWMfgwqYW+e8n5lC/jjNEhwcjbRDpl5NT7n2h+4UNcI= github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef h1:K0Fn+DoFqNqktdZtdV3bPQ/0cuYh2H4rkg0tytX/07k= github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo6LNmIvEWzsW1hbBQfpUO4JWnuQRmva8= -github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/oleiade/reflections v1.0.1/go.mod h1:rdFxbxq4QXVZWj0F+e9jqjDkc7dbp97vkRixKo2JR60= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/phf/go-queue v0.0.0-20170504031614-9abe38d0371d h1:U+PMnTlV2tu7RuMK5etusZG3Cf+rpow5hqQByeCzJ2g= -github.com/phf/go-queue v0.0.0-20170504031614-9abe38d0371d/go.mod h1:lXfE4PvvTW5xOjO6Mba8zDPyw8M93B6AQ7frTGnMlA8= -github.com/pingcap/badger v1.5.1-0.20210831093107-2f6cb8008145 h1:t7sdxmfyZ3p9K7gD8t5B50TerzTvHuAPYt+VubTVKDY= -github.com/pingcap/badger v1.5.1-0.20210831093107-2f6cb8008145/go.mod h1:LyrqUOHZrUDf9oGi1yoz1+qw9ckSIhQb5eMa1acOLNQ= +github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap/badger v1.5.1-0.20220314162537-ab58fbf40580 h1:MKVFZuqFvAMiDtv3AbihOQ6rY5IE8LWflI1BuZ/hF0Y= +github.com/pingcap/badger v1.5.1-0.20220314162537-ab58fbf40580/go.mod h1:upwDfet29M5y5koWilbWWA6ca3Lr0YVuzwX/DK58Vdk= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= github.com/pingcap/check v0.0.0-20191107115940-caf2b9e6ccf4/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/check v0.0.0-20191216031241-8a5a85928f12/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712 h1:R8gStypOBmpnHEx1qi//SaqxJVI4inOqljg/Aj5/390= -github.com/pingcap/check v0.0.0-20200212061837-5e12011dc712/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= -github.com/pingcap/errcode v0.3.0 h1:IF6LC/4+b1KNwrMlr2rBTUrojFPMexXBcDWZSpNwxjg= -github.com/pingcap/errcode v0.3.0/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= +github.com/pingcap/check v0.0.0-20211026125417-57bd13f7b5f0 h1:HVl5539r48eA+uDuX/ziBmQCxzT1pGrzWbKuXT46Bq0= +github.com/pingcap/check v0.0.0-20211026125417-57bd13f7b5f0/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/errors v0.11.5-0.20190809092503-95897b64e011/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pingcap/errors v0.11.5-0.20200917111840-a15ef68f753d/go.mod h1:g4vx//d6VakjJ0mk7iLBlKA8LFavV/sAVINT/1PFxeQ= -github.com/pingcap/errors v0.11.5-0.20201126102027-b0a155152ca3/go.mod h1:G7x87le1poQzLB/TqvTJI2ILrSgobnq4Ut7luOwvfvI= github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= -github.com/pingcap/errors v0.11.5-0.20211009033009-93128226aaa3 h1:8l9lu9RjWkI/VeqrP+Fn3tvZNPu5GYP0rYLLN5Q46go= -github.com/pingcap/errors v0.11.5-0.20211009033009-93128226aaa3/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= -github.com/pingcap/failpoint v0.0.0-20191029060244-12f4ac2fd11d/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= -github.com/pingcap/failpoint v0.0.0-20200702092429-9f69995143ce/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= -github.com/pingcap/failpoint v0.0.0-20210316064728-7acb0f0a3dfd h1:I8IeI8MNiZVKnwuXhcIIzz6pREcOSbq18Q31KYIzFVM= -github.com/pingcap/failpoint v0.0.0-20210316064728-7acb0f0a3dfd/go.mod h1:IVF+ijPSMZVtx2oIqxAg7ur6EyixtTYfOHwpfmlhqI4= +github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c h1:xpW9bvK+HuuTmyFqUwr+jcCvpVkK7sumiz+ko5H9eq4= +github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= +github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00/go.mod h1:4qGtCB0QK0wBzKtFEGDhxXnSnbQApw1gc9siScUl8ew= +github.com/pingcap/failpoint v0.0.0-20220303073211-00fea37feb66 h1:v+/0tBl7umw+ZxfTeAId/R9pmb8fn2MqsrTHAs8qFAk= +github.com/pingcap/failpoint v0.0.0-20220303073211-00fea37feb66/go.mod h1:4qGtCB0QK0wBzKtFEGDhxXnSnbQApw1gc9siScUl8ew= github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059 h1:Pe2LbxRmbTfAoKJ65bZLmhahmvHm7n9DUxGRQT00208= github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059/go.mod h1:fMRU1BA1y+r89AxUoaAar4JjrhUkVDt0o0Np6V8XbDQ= github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN8dIUmo4Be2+pMRb6f55i+UIYrluu2E= github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= -github.com/pingcap/kvproto v0.0.0-20200411081810-b85805c9476c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20210819164333-bd5706b9d9f2/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20211109071446-a8b4d34474bc/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20211122024046-03abd340988f h1:hjInxK1Ie6CYx7Jy2pYnBdEnWI8jIfr423l9Yh6LRy8= -github.com/pingcap/kvproto v0.0.0-20211122024046-03abd340988f/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220302110454-c696585a961b/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220304032058-ccd676426a27/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73 h1:jKixsi6Iw00hL0+o23hmr8BNzlsQP9pShHTOwyuf/Os= +github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= -github.com/pingcap/log v0.0.0-20210317133921-96f4fcab92a4/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM= -github.com/pingcap/log v0.0.0-20210906054005-afc726e70354 h1:SvWCbCPh1YeHd9yQLksvJYAgft6wLTY1aNG81tpyscQ= -github.com/pingcap/log v0.0.0-20210906054005-afc726e70354/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= -github.com/pingcap/sysutil v0.0.0-20210315073920-cc0985d983a3/go.mod h1:tckvA041UWP+NqYzrJ3fMgC/Hw9wnmQ/tUkp/JaHly8= -github.com/pingcap/sysutil v0.0.0-20210730114356-fcd8a63f68c5/go.mod h1:XsOaV712rUk63aOEKYP9PhXTIE3FMNHmC2r1wX5wElY= -github.com/pingcap/sysutil v0.0.0-20211208032423-041a72e5860d h1:k3/APKZjXOyJrFy8VyYwRlZhMelpD3qBLJNsw3bPl/g= -github.com/pingcap/sysutil v0.0.0-20211208032423-041a72e5860d/go.mod h1:7j18ezaWTao2LHOyMlsc2Dg1vW+mDY9dEbPzVyOlaeM= -github.com/pingcap/tidb-dashboard v0.0.0-20211008050453-a25c25809529/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ= -github.com/pingcap/tidb-dashboard v0.0.0-20211107164327-80363dfbe884/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ= -github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible h1:c7+izmker91NkjkZ6FgTlmD4k1A5FLOAq+li6Ki2/GY= -github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= -github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba h1:Tt5W/maVBUbG+wxg2nfc88Cqj/HiWYb0TJQ2Rfi0UOQ= -github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= +github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee h1:VO2t6IBpfvW34TdtD/G10VvnGqjLic1jzOuHjUb5VqM= +github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= +github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4 h1:HYbcxtnkN3s5tqrZ/z3eJS4j3Db8wMphEm1q10lY/TM= +github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4/go.mod h1:sDCsM39cGiv2vwunZkaFA917vVkqDTGSPbbV7z4Oops= +github.com/pingcap/tipb v0.0.0-20220215045658-d12dec7a7609 h1:BiCS1ZRnW0szOvTAa3gCqWIhyo+hv83SVaBgrUghXIU= +github.com/pingcap/tipb v0.0.0-20220215045658-d12dec7a7609/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -607,13 +655,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -623,17 +674,19 @@ github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7q github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -642,89 +695,66 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil v3.21.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil v3.21.3+incompatible h1:uenXGGa8ESCQq+dbgtl916dmg6PSAz2cXov0uORQ9v8= -github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= +github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0 h1:mj/nMDAwTBiaCqMEs4cYCqF7pO6Np7vhy1D1wcQGz+E= github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0= -github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= -github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI= -github.com/swaggo/http-swagger v0.0.0-20200308142732-58ac5e232fba/go.mod h1:O1lAbCgAAX/KZ80LM/OXwtWFI/5TvZlwxSg8Cq08PV0= -github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= -github.com/swaggo/swag v1.6.3/go.mod h1:wcc83tB4Mb2aNiL/HP4MFeQdpHUrca+Rp/DRNgWAUio= -github.com/swaggo/swag v1.6.6-0.20200529100950-7c765ddd0476/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= -github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= -github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/thoas/go-funk v0.8.0/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2 h1:mbAskLJ0oJfDRtkanvQPiooDH8HvJ2FBh+iKT/OmiQQ= github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2/go.mod h1:2PfKggNGDuadAa0LElHrByyrz4JPZ9fFx6Gs7nx7ZZU= -github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tikv/client-go/v2 v2.0.0-rc.0.20211214093715-605f49d3ba50 h1:B+cAIm2P1/SNsVV1vL9/mRaGUVl/vdgV8MU03O0vY28= -github.com/tikv/client-go/v2 v2.0.0-rc.0.20211214093715-605f49d3ba50/go.mod h1:wRuh+W35daKTiYBld0oBlT6PSkzEVr+pB/vChzJZk+8= -github.com/tikv/pd v1.1.0-beta.0.20211029083450-e65f0c55b6ae/go.mod h1:varH0IE0jJ9E9WN2Ei/N6pajMlPkcXdDEf7f5mmsUVQ= -github.com/tikv/pd v1.1.0-beta.0.20211118054146-02848d2660ee h1:rAAdvQ8Hh36syHr92g0VmZEpkH+40RGQBpFL2121xMs= -github.com/tikv/pd v1.1.0-beta.0.20211118054146-02848d2660ee/go.mod h1:lRbwxBAhnTQR5vqbTzeI/Bj62bD2OvYYuFezo2vrmeI= -github.com/tklauser/go-sysconf v0.3.4 h1:HT8SVixZd3IzLdfs/xlpq0jeSfTX57g1v6wB1EuzV7M= -github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= -github.com/tklauser/numcpus v0.2.1 h1:ct88eFm+Q7m2ZfXJdan1xYoXKlmwsfP+k88q05KvlZc= -github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tikv/client-go/v2 v2.0.1-0.20220406091203-f73ec0e675f4 h1:bi/tuV42dQCu7TTTOwHQW6cHVrV1fhet+Hzo5CUODBQ= +github.com/tikv/client-go/v2 v2.0.1-0.20220406091203-f73ec0e675f4/go.mod h1:0scaG+seu7L56apm+Gjz9vckyO7ABIzM6T7n00mrIXs= +github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 h1:jxgmKOscXSjaFEKQGRyY5qOpK8hLqxs2irb/uDJMtwk= +github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710/go.mod h1:AtvppPwkiyUgQlR1W9qSqfTB+OsOIu19jDCOxOsPkmU= +github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 h1:j6JEOq5QWFker+d7mFQYOhjTZonQ7YkLTHm56dbn+yM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/twmb/murmur3 v1.1.3 h1:D83U0XYKcHRYwYIpBKf3Pks91Z0Byda/9SJ8B6EMRcA= github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= @@ -732,28 +762,16 @@ github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/unrolled/render v1.0.1 h1:VDDnQQVfBMsOsp3VaCJszSO0nkBIVEYoPWeRThk9spY= -github.com/unrolled/render v1.0.1/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/negroni v0.3.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI= -github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/wangjohn/quickselect v0.0.0-20161129230411-ed8402a42d5f h1:9DDCDwOyEy/gId+IEMrFHLuQ5R/WV0KNxWLler8X2OY= github.com/wangjohn/quickselect v0.0.0-20161129230411-ed8402a42d5f/go.mod h1:8sdOQnirw1PrcnTJYkmW1iOHtUmblMmGdUOHyWYycLI= +github.com/xdg/scram v1.0.3/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -767,7 +785,6 @@ github.com/xitongsys/parquet-go-source v0.0.0-20200817004010-026bad9b25d0 h1:a74 github.com/xitongsys/parquet-go-source v0.0.0-20200817004010-026bad9b25d0/go.mod h1:HYhIKsdns7xz80OgkbgJYrtQY7FjHWHKH6cvN7+czGE= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= @@ -776,15 +793,28 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200824191128-ae9734ed278b/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20210512015243-d19fbe541bf9 h1:MNsY1TIsWLNCMT4DzZjFOxbDKfSoULYP0OFjJ8dSxts= -go.etcd.io/etcd v0.5.0-alpha.5.0.20210512015243-d19fbe541bf9/go.mod h1:q+i20RPAmay+xq8LJ3VMOhXCNk4YCk3V7QP91meFavw= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.2 h1:tXok5yLlKyuQ/SXSjtqHc4uzNaMqZi2XsoSPr/LlJXI= +go.etcd.io/etcd/api/v3 v3.5.2/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.2 h1:4hzqQ6hIb3blLyQ8usCU4h3NghkqcsohEQ3o3VetYxE= +go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.2 h1:ymrVwTkefuqA/rPkSW7/B4ApijbPVefRumkY+stNfS0= +go.etcd.io/etcd/client/v2 v2.305.2/go.mod h1:2D7ZejHVMIfog1221iLSYlQRzrtECw3kz4I4VAQm3qI= +go.etcd.io/etcd/client/v3 v3.5.2 h1:WdnejrUtQC4nCxK0/dLTMqKOB+U5TP/2Ya0BJL+1otA= +go.etcd.io/etcd/client/v3 v3.5.2/go.mod h1:kOOaWFFgHygyT0WlSmL8TJiXmMysO/nNUlEsSsN6W4o= +go.etcd.io/etcd/etcdutl/v3 v3.5.2/go.mod h1:f+KEUNxRzqQGq1Y/SsaDN5cmlOGRWgfE3lXEDi5F1Ys= +go.etcd.io/etcd/pkg/v3 v3.5.2 h1:YZUojdoPhOyl5QILYnR8LTUbbNefu/sV4ma+ZMr2tto= +go.etcd.io/etcd/pkg/v3 v3.5.2/go.mod h1:zsXz+9D/kijzRiG/UnFGDTyHKcVp0orwiO8iMLAi+k0= +go.etcd.io/etcd/raft/v3 v3.5.2 h1:uCC37qOXqBvKqTGHGyhASsaCsnTuJugl1GvneJNwHWo= +go.etcd.io/etcd/raft/v3 v3.5.2/go.mod h1:G6pCP1sFgbjod7/KnEHY0vHUViqxjkdt6AiKsD0GRr8= +go.etcd.io/etcd/server/v3 v3.5.2 h1:B6ytJvS4Fmt8nkjzS2/8POf4tuPhFMluE0lWd4dx/7U= +go.etcd.io/etcd/server/v3 v3.5.2/go.mod h1:mlG8znIEz4N/28GABrohZCBM11FqgGVQcpbcyJgh0j0= +go.etcd.io/etcd/tests/v3 v3.5.2 h1:uk7/uMGVebpBDl+roivowHt6gJ5Fnqwik3syDkoSKdo= +go.etcd.io/etcd/tests/v3 v3.5.2/go.mod h1:Jdzbei4uFi9C3xDBfCwckRXjlX0UPooiP4g/zXgBMgQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -793,6 +823,28 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -802,44 +854,43 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0= go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= -go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= -go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -859,7 +910,7 @@ golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8H golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -884,9 +935,12 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -895,14 +949,11 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -920,16 +971,24 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk= +golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -943,8 +1002,10 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a h1:4Kd8OPUx1xgUwrHDaviWZO8MsgoZTZYC3g+8m16RBww= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -958,12 +1019,14 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -972,21 +1035,19 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1001,14 +1062,19 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1018,13 +1084,27 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1035,16 +1115,18 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1055,11 +1137,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1067,11 +1145,10 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191107010934-f79515f33823/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1085,7 +1162,6 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= @@ -1103,25 +1179,24 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1149,8 +1224,17 @@ google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59t google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0 h1:ECJUVngj71QI6XEm7b1sAf8BljU5inEhMbKPR8Lxhhk= google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= +google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= +google.golang.org/api v0.69.0 h1:yHW5s2SFyDapr/43kYtIQmoaaFVW4baLMLwqV4auj2A= +google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1182,8 +1266,10 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -1210,10 +1296,55 @@ google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda h1:iT5uhT54PtbqUsWddv/nnEWdE5e/MTr+Nv3vjxlBP1A= -google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8 h1:divpuJZKgX3Qt7MFDE5v62yu0yQcQbTCD9VJp9leX58= +google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1229,21 +1360,18 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/gometalinter.v2 v2.0.12/go.mod h1:NDRytsqEZyolNuAgTzJkZMkSQM7FIKyzVzGhjB/qfYo= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= @@ -1261,7 +1389,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1269,10 +1396,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.0.6/go.mod h1:KdrTanmfLPPyAOeYGyG+UpDys7/7eeWT1zCq+oekYnU= -gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= -gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1280,8 +1403,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254= modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk= @@ -1296,13 +1417,12 @@ modernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtx modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/y v1.0.1/go.mod h1:Ho86I+LVHEI+LYXoUKlmOMAM1JTXOCfj8qi1T8PsClE= -moul.io/zapgorm2 v1.1.0/go.mod h1:emRfKjNqSzVj5lcgasBdovIXY1jSOwFz2GQZn1Rddks= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 h1:e1sMhtVq9AfcEy8AXNb8eSg6gbzfdpYhoNqnPJa+GzI= diff --git a/infoschema/builder.go b/infoschema/builder.go index 70ca84f5dd6c6..b8e42344b867c 100644 --- a/infoschema/builder.go +++ b/infoschema/builder.go @@ -40,12 +40,16 @@ import ( // Builder builds a new InfoSchema. type Builder struct { is *infoSchema + // dbInfos do not need to be copied everytime applying a diff, instead, + // they can be copied only once over the whole lifespan of Builder. + // This map will indicate which DB has been copied, so that they + // don't need to be copied again. + dirtyDB map[string]bool // TODO: store is only used by autoid allocators // detach allocators from storage, use passed transaction in the feature store kv.Storage - // TODO: renewLeaseCh is only used to pass data between table and domain - renewLeaseCh chan func() - factory func() (pools.Resource, error) + + factory func() (pools.Resource, error) } // ApplyDiff applies SchemaDiff to the new InfoSchema. @@ -67,13 +71,124 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro return b.applyDropPolicy(diff.SchemaID), nil case model.ActionAlterPlacementPolicy: return b.applyAlterPolicy(m, diff) + case model.ActionTruncateTablePartition, model.ActionTruncateTable: + return b.applyTruncateTableOrPartition(m, diff) + case model.ActionDropTable, model.ActionDropTablePartition: + return b.applyDropTableOrParition(m, diff) + case model.ActionRecoverTable: + return b.applyRecoverTable(m, diff) + case model.ActionCreateTables: + return b.applyCreateTables(m, diff) + default: + return b.applyDefaultAction(m, diff) + } +} + +func (b *Builder) applyCreateTables(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { + tblIDs := make([]int64, 0, len(diff.AffectedOpts)) + if diff.AffectedOpts != nil { + for _, opt := range diff.AffectedOpts { + affectedDiff := &model.SchemaDiff{ + Version: diff.Version, + Type: model.ActionCreateTable, + SchemaID: opt.SchemaID, + TableID: opt.TableID, + OldSchemaID: opt.OldSchemaID, + OldTableID: opt.OldTableID, + } + affectedIDs, err := b.ApplyDiff(m, affectedDiff) + if err != nil { + return nil, errors.Trace(err) + } + tblIDs = append(tblIDs, affectedIDs...) + } + } + return tblIDs, nil +} + +func (b *Builder) applyTruncateTableOrPartition(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { + tblIDs, err := b.applyTableUpdate(m, diff) + if err != nil { + return nil, errors.Trace(err) + } + + for _, opt := range diff.AffectedOpts { + if diff.Type == model.ActionTruncateTablePartition { + // Reduce the impact on DML when executing partition DDL. eg. + // While session 1 performs the DML operation associated with partition 1, + // the TRUNCATE operation of session 2 on partition 2 does not cause the operation of session 1 to fail. + tblIDs = append(tblIDs, opt.OldTableID) + } + b.applyPlacementDelete(placement.GroupID(opt.OldTableID)) + err := b.applyPlacementUpdate(placement.GroupID(opt.TableID)) + if err != nil { + return nil, errors.Trace(err) + } + } + return tblIDs, nil +} + +func (b *Builder) applyDropTableOrParition(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { + tblIDs, err := b.applyTableUpdate(m, diff) + if err != nil { + return nil, errors.Trace(err) + } + + for _, opt := range diff.AffectedOpts { + b.applyPlacementDelete(placement.GroupID(opt.OldTableID)) + } + return tblIDs, nil +} + +func (b *Builder) applyRecoverTable(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { + tblIDs, err := b.applyTableUpdate(m, diff) + if err != nil { + return nil, errors.Trace(err) } + + for _, opt := range diff.AffectedOpts { + err := b.applyPlacementUpdate(placement.GroupID(opt.TableID)) + if err != nil { + return nil, errors.Trace(err) + } + } + return tblIDs, nil +} + +func (b *Builder) applyDefaultAction(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { + tblIDs, err := b.applyTableUpdate(m, diff) + if err != nil { + return nil, errors.Trace(err) + } + + for _, opt := range diff.AffectedOpts { + var err error + affectedDiff := &model.SchemaDiff{ + Version: diff.Version, + Type: diff.Type, + SchemaID: opt.SchemaID, + TableID: opt.TableID, + OldSchemaID: opt.OldSchemaID, + OldTableID: opt.OldTableID, + } + affectedIDs, err := b.ApplyDiff(m, affectedDiff) + if err != nil { + return nil, errors.Trace(err) + } + tblIDs = append(tblIDs, affectedIDs...) + } + + return tblIDs, nil +} + +func (b *Builder) applyTableUpdate(m *meta.Meta, diff *model.SchemaDiff) ([]int64, error) { roDBInfo, ok := b.is.SchemaByID(diff.SchemaID) if !ok { return nil, ErrDatabaseNotExists.GenWithStackByArgs( fmt.Sprintf("(Schema ID %d)", diff.SchemaID), ) } + dbInfo := b.getSchemaAndCopyIfNecessary(roDBInfo.Name.L) var oldTableID, newTableID int64 switch diff.Type { case model.ActionCreateTable, model.ActionCreateSequence, model.ActionRecoverTable: @@ -109,14 +224,13 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro return nil, errors.Trace(err) } } - dbInfo := b.copySchemaTables(roDBInfo.Name.L) b.copySortedTables(oldTableID, newTableID) tblIDs := make([]int64, 0, 2) // We try to reuse the old allocator, so the cached auto ID can be reused. var allocs autoid.Allocators if tableIDIsValid(oldTableID) { - if oldTableID == newTableID && diff.Type != model.ActionRenameTable && + if oldTableID == newTableID && (diff.Type != model.ActionRenameTable && diff.Type != model.ActionRenameTables) && diff.Type != model.ActionExchangeTablePartition && // For repairing table in TiDB cluster, given 2 normal node and 1 repair node. // For normal node's information schema, repaired table is existed. @@ -137,7 +251,7 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro fmt.Sprintf("(Schema ID %d)", diff.OldSchemaID), ) } - oldDBInfo := b.copySchemaTables(oldRoDBInfo.Name.L) + oldDBInfo := b.getSchemaAndCopyIfNecessary(oldRoDBInfo.Name.L) tmpIDs = b.applyDropTable(oldDBInfo, oldTableID, tmpIDs) } else { tmpIDs = b.applyDropTable(dbInfo, oldTableID, tmpIDs) @@ -156,53 +270,6 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro return nil, errors.Trace(err) } } - if diff.AffectedOpts != nil { - for _, opt := range diff.AffectedOpts { - switch diff.Type { - case model.ActionTruncateTablePartition: - // Reduce the impact on DML when executing partition DDL. eg. - // While session 1 performs the DML operation associated with partition 1, - // the TRUNCATE operation of session 2 on partition 2 does not cause the operation of session 1 to fail. - tblIDs = append(tblIDs, opt.OldTableID) - b.applyPlacementDelete(placement.GroupID(opt.OldTableID)) - err := b.applyPlacementUpdate(placement.GroupID(opt.TableID)) - if err != nil { - return nil, errors.Trace(err) - } - continue - case model.ActionDropTable, model.ActionDropTablePartition: - b.applyPlacementDelete(placement.GroupID(opt.OldTableID)) - continue - case model.ActionTruncateTable: - b.applyPlacementDelete(placement.GroupID(opt.OldTableID)) - err := b.applyPlacementUpdate(placement.GroupID(opt.TableID)) - if err != nil { - return nil, errors.Trace(err) - } - continue - case model.ActionRecoverTable: - err := b.applyPlacementUpdate(placement.GroupID(opt.TableID)) - if err != nil { - return nil, errors.Trace(err) - } - continue - } - var err error - affectedDiff := &model.SchemaDiff{ - Version: diff.Version, - Type: diff.Type, - SchemaID: opt.SchemaID, - TableID: opt.TableID, - OldSchemaID: opt.OldSchemaID, - OldTableID: opt.OldTableID, - } - affectedIDs, err := b.ApplyDiff(m, affectedDiff) - if err != nil { - return nil, errors.Trace(err) - } - tblIDs = append(tblIDs, affectedIDs...) - } - } return tblIDs, nil } @@ -306,7 +373,7 @@ func (b *Builder) applyModifySchemaCharsetAndCollate(m *meta.Meta, diff *model.S fmt.Sprintf("(Schema ID %d)", diff.SchemaID), ) } - newDbInfo := b.copySchemaTables(di.Name.L) + newDbInfo := b.getSchemaAndCopyIfNecessary(di.Name.L) newDbInfo.Charset = di.Charset newDbInfo.Collate = di.Collate return nil @@ -323,9 +390,8 @@ func (b *Builder) applyModifySchemaDefaultPlacement(m *meta.Meta, diff *model.Sc fmt.Sprintf("(Schema ID %d)", diff.SchemaID), ) } - newDbInfo := b.copySchemaTables(di.Name.L) + newDbInfo := b.getSchemaAndCopyIfNecessary(di.Name.L) newDbInfo.PlacementPolicyRef = di.PlacementPolicyRef - newDbInfo.DirectPlacementOpts = di.DirectPlacementOpts return nil } @@ -577,20 +643,25 @@ func (b *Builder) copyPoliciesMap(oldIS *infoSchema) { } } -// copySchemaTables creates a new schemaTables instance when a table in the database has changed. +// getSchemaAndCopyIfNecessary creates a new schemaTables instance when a table in the database has changed. // It also does modifications on the new one because old schemaTables must be read-only. -// Note: please make sure the dbName is in lowercase. -func (b *Builder) copySchemaTables(dbName string) *model.DBInfo { - oldSchemaTables := b.is.schemaMap[dbName] - newSchemaTables := &schemaTables{ - dbInfo: oldSchemaTables.dbInfo.Copy(), - tables: make(map[string]table.Table, len(oldSchemaTables.tables)), - } - for k, v := range oldSchemaTables.tables { - newSchemaTables.tables[k] = v +// And it will only copy the changed database once in the lifespan of the Builder. +// NOTE: please make sure the dbName is in lowercase. +func (b *Builder) getSchemaAndCopyIfNecessary(dbName string) *model.DBInfo { + if !b.dirtyDB[dbName] { + b.dirtyDB[dbName] = true + oldSchemaTables := b.is.schemaMap[dbName] + newSchemaTables := &schemaTables{ + dbInfo: oldSchemaTables.dbInfo.Copy(), + tables: make(map[string]table.Table, len(oldSchemaTables.tables)), + } + for k, v := range oldSchemaTables.tables { + newSchemaTables.tables[k] = v + } + b.is.schemaMap[dbName] = newSchemaTables + return newSchemaTables.dbInfo } - b.is.schemaMap[dbName] = newSchemaTables - return newSchemaTables.dbInfo + return b.is.schemaMap[dbName].dbInfo } // InitWithDBInfos initializes an empty new InfoSchema with a slice of DBInfo, all placement rules, and schema version. @@ -639,7 +710,7 @@ func (b *Builder) tableFromMeta(alloc autoid.Allocators, tblInfo *model.TableInf return nil, errors.Trace(err) } - err = t.Init(b.renewLeaseCh, tmp.(sqlexec.SQLExecutor)) + err = t.Init(tmp.(sqlexec.SQLExecutor)) if err != nil { return nil, errors.Trace(err) } @@ -683,7 +754,7 @@ func RegisterVirtualTable(dbInfo *model.DBInfo, tableFromMeta tableFromMetaFunc) } // NewBuilder creates a new Builder with a Handle. -func NewBuilder(store kv.Storage, renewCh chan func(), factory func() (pools.Resource, error)) *Builder { +func NewBuilder(store kv.Storage, factory func() (pools.Resource, error)) *Builder { return &Builder{ store: store, is: &infoSchema{ @@ -692,8 +763,8 @@ func NewBuilder(store kv.Storage, renewCh chan func(), factory func() (pools.Res ruleBundleMap: map[string]*placement.Bundle{}, sortedTablesBuckets: make([]sortedTables, bucketCount), }, - renewLeaseCh: renewCh, - factory: factory, + dirtyDB: make(map[string]bool), + factory: factory, } } diff --git a/infoschema/cluster_tables_serial_test.go b/infoschema/cluster_tables_serial_test.go deleted file mode 100644 index d48fb494133e3..0000000000000 --- a/infoschema/cluster_tables_serial_test.go +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package infoschema_test - -import ( - "fmt" - "net" - "net/http/httptest" - "os" - "runtime" - "strings" - "testing" - "time" - - "github.com/gorilla/mux" - "github.com/pingcap/failpoint" - "github.com/pingcap/fn" - "github.com/pingcap/kvproto/pkg/deadlock" - "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser" - "github.com/pingcap/tidb/parser/auth" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/server" - "github.com/pingcap/tidb/store/helper" - "github.com/pingcap/tidb/store/mockstore/mockstorage" - "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/pdapi" - "github.com/pingcap/tidb/util/resourcegrouptag" - "github.com/pingcap/tidb/util/set" - "github.com/pingcap/tidb/util/testutil" - "github.com/pingcap/tipb/go-tipb" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" -) - -type clusterTablesSuite struct { - store kv.Storage - dom *domain.Domain - rpcserver *grpc.Server - httpServer *httptest.Server - mockAddr string - listenAddr string - startTime time.Time -} - -func TestClusterTables(t *testing.T) { - // setup suite - var clean func() - s := new(clusterTablesSuite) - s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) - defer clean() - s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() - defer s.httpServer.Close() - defer s.rpcserver.Stop() - - // subtests - t.Run("ForClusterServerInfo", SubTestForClusterServerInfo(s)) - t.Run("DataLockWaits", SubTestTestDataLockWaits(s)) - t.Run("DataLockWaitsPrivilege", SubTestDataLockWaitsPrivilege(s)) - t.Run("SelectClusterTable", SubTestSelectClusterTable(s)) - t.Run("SelectClusterTablePrivilege", SubTestSelectClusterTablePrivilege(s)) - t.Run("StmtSummaryEvictedCountTable", SubTestStmtSummaryEvictedCountTable(s)) - t.Run("StmtSummaryHistoryTable", SubTestStmtSummaryHistoryTable(s)) - t.Run("Issue26379", SubTestIssue26379(s)) - t.Run("SubTestStmtSummaryResultRows", SubTestStmtSummaryResultRows(s)) -} - -func SubTestForClusterServerInfo(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := testkit.NewTestKit(t, s.store) - instances := []string{ - strings.Join([]string{"tidb", s.listenAddr, s.listenAddr, "mock-version,mock-githash,1001"}, ","), - strings.Join([]string{"pd", s.listenAddr, s.listenAddr, "mock-version,mock-githash,0"}, ","), - strings.Join([]string{"tikv", s.listenAddr, s.listenAddr, "mock-version,mock-githash,0"}, ","), - } - - fpExpr := `return("` + strings.Join(instances, ";") + `")` - fpName := "github.com/pingcap/tidb/infoschema/mockClusterInfo" - require.NoError(t, failpoint.Enable(fpName, fpExpr)) - defer func() { require.NoError(t, failpoint.Disable(fpName)) }() - - cases := []struct { - sql string - types set.StringSet - addrs set.StringSet - names set.StringSet - skipOnDist set.StringSet - }{ - { - sql: "select * from information_schema.CLUSTER_LOAD;", - types: set.NewStringSet("tidb", "tikv", "pd"), - addrs: set.NewStringSet(s.listenAddr), - names: set.NewStringSet("cpu", "memory", "net"), - }, - { - sql: "select * from information_schema.CLUSTER_HARDWARE;", - types: set.NewStringSet("tidb", "tikv", "pd"), - addrs: set.NewStringSet(s.listenAddr), - names: set.NewStringSet("cpu", "memory", "net", "disk"), - // The sysutil package will filter out all disk don't have /dev prefix. - // gopsutil cpu.Info will fail on mac M1 - skipOnDist: set.NewStringSet("windows", "darwin/arm64"), - }, - { - sql: "select * from information_schema.CLUSTER_SYSTEMINFO;", - types: set.NewStringSet("tidb", "tikv", "pd"), - addrs: set.NewStringSet(s.listenAddr), - names: set.NewStringSet("system"), - // This test get empty result and fails on the windows platform. - // Because the underlying implementation use `sysctl` command to get the result - // and there is no such command on windows. - // https://github.com/pingcap/sysutil/blob/2bfa6dc40bcd4c103bf684fba528ae4279c7ec9f/system_info.go#L50 - skipOnDist: set.NewStringSet("windows"), - }, - } - - for _, cas := range cases { - if cas.skipOnDist.Exist(runtime.GOOS+"/"+runtime.GOARCH) || cas.skipOnDist.Exist(runtime.GOOS) { - continue - } - - result := tk.MustQuery(cas.sql) - rows := result.Rows() - require.Greater(t, len(rows), 0) - - gotTypes := set.StringSet{} - gotAddrs := set.StringSet{} - gotNames := set.StringSet{} - - for _, row := range rows { - gotTypes.Insert(row[0].(string)) - gotAddrs.Insert(row[1].(string)) - gotNames.Insert(row[2].(string)) - } - - require.Equalf(t, cas.types, gotTypes, "sql: %s", cas.sql) - require.Equalf(t, cas.addrs, gotAddrs, "sql: %s", cas.sql) - require.Equalf(t, cas.names, gotNames, "sql: %s", cas.sql) - } - } -} - -func SubTestTestDataLockWaits(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - _, digest1 := parser.NormalizeDigest("select * from test_data_lock_waits for update") - _, digest2 := parser.NormalizeDigest("update test_data_lock_waits set f1=1 where id=2") - s.store.(mockstorage.MockLockWaitSetter).SetMockLockWaits([]*deadlock.WaitForEntry{ - {Txn: 1, WaitForTxn: 2, Key: []byte("key1"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(digest1, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, - {Txn: 3, WaitForTxn: 4, Key: []byte("key2"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(digest2, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, - // Invalid digests - {Txn: 5, WaitForTxn: 6, Key: []byte("key3"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(nil, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, - {Txn: 7, WaitForTxn: 8, Key: []byte("key4"), ResourceGroupTag: []byte("asdfghjkl")}, - }) - - tk := s.newTestKitWithRoot(t) - - // Execute one of the query once, so it's stored into statements_summary. - tk.MustExec("create table test_data_lock_waits (id int primary key, f1 int)") - tk.MustExec("select * from test_data_lock_waits for update") - - tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS").Check(testkit.Rows( - "6B657931 1 2 "+digest1.String()+" select * from `test_data_lock_waits` for update", - "6B657932 3 4 "+digest2.String()+" ", - "6B657933 5 6 ", - "6B657934 7 8 ")) - } -} - -func SubTestDataLockWaitsPrivilege(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - dropUserTk := s.newTestKitWithRoot(t) - - tk := s.newTestKitWithRoot(t) - - tk.MustExec("create user 'testuser'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "testuser", - Hostname: "localhost", - }, nil, nil)) - err := tk.QueryToErr("select * from information_schema.DATA_LOCK_WAITS") - require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") - - tk = s.newTestKitWithRoot(t) - tk.MustExec("create user 'testuser2'@'localhost'") - defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") - tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "testuser2", - Hostname: "localhost", - }, nil, nil)) - _ = tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS") - } -} - -func SubTestSelectClusterTable(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := s.newTestKitWithRoot(t) - slowLogFileName := "tidb-slow.log" - prepareSlowLogfile(t, slowLogFileName) - defer func() { require.NoError(t, os.Remove(slowLogFileName)) }() - for i := 0; i < 2; i++ { - tk.MustExec("use information_schema") - tk.MustExec(fmt.Sprintf("set @@tidb_enable_streaming=%d", i)) - tk.MustExec("set @@global.tidb_enable_stmt_summary=1") - tk.MustExec("set time_zone = '+08:00';") - tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("2")) - tk.MustQuery("select time from `CLUSTER_SLOW_QUERY` where time='2019-02-12 19:33:56.571953'").Check(testutil.RowsWithSep("|", "2019-02-12 19:33:56.571953")) - tk.MustQuery("select count(*) from `CLUSTER_PROCESSLIST`").Check(testkit.Rows("1")) - tk.MustQuery("select * from `CLUSTER_PROCESSLIST`").Check(testkit.Rows(fmt.Sprintf(":10080 1 root 127.0.0.1 Query 9223372036 %s 0 0 ", ""))) - tk.MustQuery("select query_time, conn_id from `CLUSTER_SLOW_QUERY` order by time limit 1").Check(testkit.Rows("4.895492 6")) - tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY` group by digest").Check(testkit.Rows("1", "1")) - tk.MustQuery("select digest, count(*) from `CLUSTER_SLOW_QUERY` group by digest order by digest").Check(testkit.Rows("124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc 1", "42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 1")) - tk.MustQuery(`select length(query) as l,time from information_schema.cluster_slow_query where time > "2019-02-12 19:33:56" order by abs(l) desc limit 10;`).Check(testkit.Rows("21 2019-02-12 19:33:56.571953")) - tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY` where time > now() group by digest").Check(testkit.Rows()) - re := tk.MustQuery("select * from `CLUSTER_statements_summary`") - require.NotNil(t, re) - require.Greater(t, len(re.Rows()), 0) - // Test for TiDB issue 14915. - re = tk.MustQuery("select sum(exec_count*avg_mem) from cluster_statements_summary_history group by schema_name,digest,digest_text;") - require.NotNil(t, re) - require.Greater(t, len(re.Rows()), 0) - tk.MustQuery("select * from `CLUSTER_statements_summary_history`") - require.NotNil(t, re) - require.Greater(t, len(re.Rows()), 0) - tk.MustExec("set @@global.tidb_enable_stmt_summary=0") - re = tk.MustQuery("select * from `CLUSTER_statements_summary`") - require.NotNil(t, re) - require.Equal(t, 0, len(re.Rows())) - tk.MustQuery("select * from `CLUSTER_statements_summary_history`") - require.NotNil(t, re) - require.Equal(t, 0, len(re.Rows())) - } - } -} - -func SubTestSelectClusterTablePrivilege(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := testkit.NewTestKit(t, s.store) - slowLogFileName := "tidb-slow.log" - f, err := os.OpenFile(slowLogFileName, os.O_CREATE|os.O_WRONLY, 0644) - require.NoError(t, err) - _, err = f.Write([]byte( - `# Time: 2019-02-12T19:33:57.571953+08:00 -# User@Host: user2 [user2] @ 127.0.0.1 [127.0.0.1] -select * from t2; -# Time: 2019-02-12T19:33:56.571953+08:00 -# User@Host: user1 [user1] @ 127.0.0.1 [127.0.0.1] -select * from t1; -# Time: 2019-02-12T19:33:58.571953+08:00 -# User@Host: user2 [user2] @ 127.0.0.1 [127.0.0.1] -select * from t3; -# Time: 2019-02-12T19:33:59.571953+08:00 -select * from t3; -`)) - require.NoError(t, f.Close()) - require.NoError(t, err) - defer func() { require.NoError(t, os.Remove(slowLogFileName)) }() - tk.MustExec("use information_schema") - tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("4")) - tk.MustQuery("select count(*) from `SLOW_QUERY`").Check(testkit.Rows("4")) - tk.MustQuery("select count(*) from `CLUSTER_PROCESSLIST`").Check(testkit.Rows("1")) - tk.MustQuery("select * from `CLUSTER_PROCESSLIST`").Check(testkit.Rows(fmt.Sprintf(":10080 1 root 127.0.0.1 Query 9223372036 %s 0 0 ", ""))) - tk.MustExec("create user user1") - tk.MustExec("create user user2") - user1 := testkit.NewTestKit(t, s.store) - user1.MustExec("use information_schema") - require.True(t, user1.Session().Auth(&auth.UserIdentity{ - Username: "user1", - Hostname: "127.0.0.1", - }, nil, nil)) - user1.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("1")) - user1.MustQuery("select count(*) from `SLOW_QUERY`").Check(testkit.Rows("1")) - user1.MustQuery("select user,query from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("user1 select * from t1;")) - - user2 := testkit.NewTestKit(t, s.store) - user2.MustExec("use information_schema") - require.True(t, user2.Session().Auth(&auth.UserIdentity{ - Username: "user2", - Hostname: "127.0.0.1", - }, nil, nil)) - user2.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("2")) - user2.MustQuery("select user,query from `CLUSTER_SLOW_QUERY` order by query").Check(testkit.Rows("user2 select * from t2;", "user2 select * from t3;")) - } -} - -func SubTestStmtSummaryEvictedCountTable(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := s.newTestKitWithRoot(t) - // disable refreshing - tk.MustExec("set global tidb_stmt_summary_refresh_interval=9999") - // set information_schema.statements_summary's size to 2 - tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 2") - // no evict happened, no record in cluster evicted table. - tk.MustQuery("select count(*) from information_schema.cluster_statements_summary_evicted;").Check(testkit.Rows("0")) - tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 1") - // cleanup side effects - defer tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 100") - defer tk.MustExec("set global tidb_stmt_summary_refresh_interval = 1800") - // clear information_schema.statements_summary - tk.MustExec("set global tidb_enable_stmt_summary=0") - // statements_summary is off, statements_summary_evicted is empty. - tk.MustQuery("select count(*) from information_schema.cluster_statements_summary_evicted;").Check(testkit.Rows("0")) - tk.MustExec("set global tidb_enable_stmt_summary=1") - - // make a new session for test... - tk = s.newTestKitWithRoot(t) - // first sql - tk.MustExec("show databases;") - // second sql, evict former sql from stmt_summary - tk.MustQuery("select evicted_count from information_schema.cluster_statements_summary_evicted;"). - Check(testkit.Rows("1")) - // after executed the sql above - tk.MustQuery("select evicted_count from information_schema.cluster_statements_summary_evicted;"). - Check(testkit.Rows("2")) - // TODO: Add more tests. - - tk.MustExec("create user 'testuser'@'localhost'") - tk.MustExec("create user 'testuser2'@'localhost'") - tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") - tk1 := s.newTestKitWithRoot(t) - defer tk1.MustExec("drop user 'testuser'@'localhost'") - defer tk1.MustExec("drop user 'testuser2'@'localhost'") - - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "testuser", - Hostname: "localhost", - }, nil, nil)) - - err := tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED") - // This error is come from cop(TiDB) fetch from rpc server. - require.EqualError(t, err, "other error: [planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") - - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "testuser2", - Hostname: "localhost", - }, nil, nil)) - require.NoError(t, tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED")) - } -} - -func SubTestStmtSummaryHistoryTable(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := s.newTestKitWithRoot(t) - tk.MustExec("drop table if exists test_summary") - tk.MustExec("create table test_summary(a int, b varchar(10), key k(a))") - - tk.MustExec("set global tidb_enable_stmt_summary = 1") - tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) - - // Disable refreshing summary. - tk.MustExec("set global tidb_stmt_summary_refresh_interval = 999999999") - tk.MustQuery("select @@global.tidb_stmt_summary_refresh_interval").Check(testkit.Rows("999999999")) - - // Create a new session to test. - tk = s.newTestKitWithRoot(t) - - // Test INSERT - tk.MustExec("insert into test_summary values(1, 'a')") - tk.MustExec("insert into test_summary values(2, 'b')") - tk.MustExec("insert into TEST_SUMMARY VALUES(3, 'c')") - tk.MustExec("/**/insert into test_summary values(4, 'd')") - - sql := "select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys," + - "max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions," + - "max_prewrite_regions, avg_affected_rows, query_sample_text " + - "from information_schema.statements_summary_history " + - "where digest_text like 'insert into `test_summary`%'" - tk.MustQuery(sql).Check(testkit.Rows("Insert test test.test_summary 4 0 0 0 0 0 2 2 1 1 1 insert into test_summary values(1, 'a')")) - - tk.MustExec("set global tidb_stmt_summary_history_size = 0") - tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys, - max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions, - max_prewrite_regions, avg_affected_rows, query_sample_text, plan - from information_schema.statements_summary_history`, - ).Check(testkit.Rows()) - - tk.MustExec("set global tidb_enable_stmt_summary = 0") - tk.MustExec("drop table if exists `table`") - tk.MustExec("set global tidb_stmt_summary_history_size = 1") - tk.MustExec("set global tidb_enable_stmt_summary = 1") - tk.MustExec("create table `table`(`insert` int)") - tk.MustExec("select `insert` from `table`") - - sql = "select digest_text from information_schema.statements_summary_history;" - tk.MustQuery(sql).Check(testkit.Rows( - "select `insert` from `table`", - "create table `table` ( `insert` int )", - "set global `tidb_enable_stmt_summary` = ?", - )) - } -} - -func SubTestIssue26379(s *clusterTablesSuite) func(*testing.T) { - return func(t *testing.T) { - tk := s.newTestKitWithRoot(t) - - // Clear all statements. - tk.MustExec("set session tidb_enable_stmt_summary = 0") - tk.MustExec("set session tidb_enable_stmt_summary = ''") - tk.MustExec("set @@global.tidb_stmt_summary_max_stmt_count=10") - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b varchar(10), c int, d int, key k(a))") - - _, digest1 := parser.NormalizeDigest("select * from t where a = 3") - _, digest2 := parser.NormalizeDigest("select * from t where b = 'b'") - _, digest3 := parser.NormalizeDigest("select * from t where c = 6") - _, digest4 := parser.NormalizeDigest("select * from t where d = 5") - fillStatementCache := func() { - tk.MustQuery("select * from t where a = 3") - tk.MustQuery("select * from t where b = 'b'") - tk.MustQuery("select * from t where c = 6") - tk.MustQuery("select * from t where d = 5") - } - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest1.String())).Check(testkit.Rows(digest1.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest1.String())).Check(testkit.Rows(digest1.String())) - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest2.String())).Check(testkit.Rows(digest2.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest2.String())).Check(testkit.Rows(digest2.String())) - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest3.String())).Check(testkit.Rows(digest3.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest3.String())).Check(testkit.Rows(digest3.String())) - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest4.String())).Check(testkit.Rows(digest4.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest4.String())).Check(testkit.Rows(digest4.String())) - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s' or digest = '%s'", digest1.String(), digest2.String())).Sort().Check(testkit.Rows(digest1.String(), digest2.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' or digest = '%s'", digest1.String(), digest2.String())).Sort().Check(testkit.Rows(digest1.String(), digest2.String())) - re := tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' and digest = '%s'", digest1.String(), digest2.String())) - require.Equal(t, 0, len(re.Rows())) - re = tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' and digest = '%s'", digest1.String(), digest2.String())) - require.Equal(t, 0, len(re.Rows())) - fillStatementCache() - tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest in ('%s', '%s', '%s', '%s')", digest1.String(), digest2.String(), digest3.String(), digest4.String())).Sort().Check(testkit.Rows(digest1.String(), digest4.String(), digest2.String(), digest3.String())) - tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest in ('%s', '%s', '%s', '%s')", digest1.String(), digest2.String(), digest3.String(), digest4.String())).Sort().Check(testkit.Rows(digest1.String(), digest4.String(), digest2.String(), digest3.String())) - fillStatementCache() - tk.MustQuery("select count(*) from information_schema.statements_summary where digest=''").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from information_schema.statements_summary where digest is null").Check(testkit.Rows("1")) - tk.MustQuery("select count(*) from information_schema.cluster_statements_summary where digest=''").Check(testkit.Rows("0")) - tk.MustQuery("select count(*) from information_schema.cluster_statements_summary where digest is null").Check(testkit.Rows("1")) - } -} - -func SubTestStmtSummaryResultRows(s *clusterTablesSuite) func(t *testing.T) { - return func(t *testing.T) { - tk := s.newTestKitWithRoot(t) - tk.MustExec("set global tidb_stmt_summary_refresh_interval=999999999") - tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 3000") - tk.MustExec("set global tidb_stmt_summary_history_size=24") - tk.MustExec("set global tidb_stmt_summary_max_sql_length=4096") - tk.MustExec("set global tidb_enable_stmt_summary=0") - tk.MustExec("set global tidb_enable_stmt_summary=1") - if !config.GetGlobalConfig().EnableCollectExecutionInfo { - tk.MustExec("set @@tidb_enable_collect_execution_info=1") - defer tk.MustExec("set @@tidb_enable_collect_execution_info=0") - } - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int)") - for i := 1; i <= 30; i++ { - tk.MustExec(fmt.Sprintf("insert into t values (%v)", i)) - } - - tk.MustQuery("select * from test.t limit 10;") - tk.MustQuery("select * from test.t limit 20;") - tk.MustQuery("select * from test.t limit 30;") - tk.MustQuery("select MIN_RESULT_ROWS,MAX_RESULT_ROWS,AVG_RESULT_ROWS from information_schema.statements_summary where query_sample_text like 'select%test.t limit%' and MAX_RESULT_ROWS > 10"). - Check(testkit.Rows("10 30 20")) - tk.MustQuery("select MIN_RESULT_ROWS,MAX_RESULT_ROWS,AVG_RESULT_ROWS from information_schema.cluster_statements_summary where query_sample_text like 'select%test.t limit%' and MAX_RESULT_ROWS > 10"). - Check(testkit.Rows("10 30 20")) - } -} - -func (s *clusterTablesSuite) setUpRPCService(t *testing.T, addr string) (*grpc.Server, string) { - lis, err := net.Listen("tcp", addr) - require.NoError(t, err) - // Fix issue 9836 - sm := &mockSessionManager{make(map[uint64]*util.ProcessInfo, 1), nil} - sm.processInfoMap[1] = &util.ProcessInfo{ - ID: 1, - User: "root", - Host: "127.0.0.1", - Command: mysql.ComQuery, - } - srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) - port := lis.Addr().(*net.TCPAddr).Port - addr = fmt.Sprintf("127.0.0.1:%d", port) - go func() { - err = srv.Serve(lis) - require.NoError(t, err) - }() - config.UpdateGlobal(func(conf *config.Config) { - conf.Status.StatusPort = uint(port) - }) - return srv, addr -} - -func (s *clusterTablesSuite) setUpMockPDHTTPServer() (*httptest.Server, string) { - // mock PD http server - router := mux.NewRouter() - srv := httptest.NewServer(router) - // mock store stats stat - mockAddr := strings.TrimPrefix(srv.URL, "http://") - router.Handle(pdapi.Stores, fn.Wrap(func() (*helper.StoresStat, error) { - return &helper.StoresStat{ - Count: 1, - Stores: []helper.StoreStat{ - { - Store: helper.StoreBaseStat{ - ID: 1, - Address: "127.0.0.1:20160", - State: 0, - StateName: "Up", - Version: "4.0.0-alpha", - StatusAddress: mockAddr, - GitHash: "mock-tikv-githash", - StartTimestamp: s.startTime.Unix(), - }, - }, - }, - }, nil - })) - // mock PD API - router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { - return struct { - Version string `json:"version"` - GitHash string `json:"git_hash"` - StartTimestamp int64 `json:"start_timestamp"` - }{ - Version: "4.0.0-alpha", - GitHash: "mock-pd-githash", - StartTimestamp: s.startTime.Unix(), - }, nil - })) - var mockConfig = func() (map[string]interface{}, error) { - configuration := map[string]interface{}{ - "key1": "value1", - "key2": map[string]string{ - "nest1": "n-value1", - "nest2": "n-value2", - }, - "key3": map[string]interface{}{ - "nest1": "n-value1", - "nest2": "n-value2", - "key4": map[string]string{ - "nest3": "n-value4", - "nest4": "n-value5", - }, - }, - } - return configuration, nil - } - // pd config - router.Handle(pdapi.Config, fn.Wrap(mockConfig)) - // TiDB/TiKV config - router.Handle("/config", fn.Wrap(mockConfig)) - return srv, mockAddr -} - -func (s *clusterTablesSuite) newTestKitWithRoot(t *testing.T) *testkit.TestKit { - tk := testkit.NewTestKit(t, s.store) - tk.MustExec("use test") - require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - return tk -} diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go new file mode 100644 index 0000000000000..888e0954e0359 --- /dev/null +++ b/infoschema/cluster_tables_test.go @@ -0,0 +1,698 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package infoschema_test + +import ( + "fmt" + "net" + "net/http/httptest" + "os" + "runtime" + "strings" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/pingcap/failpoint" + "github.com/pingcap/fn" + "github.com/pingcap/kvproto/pkg/deadlock" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/server" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/store/mockstore/mockstorage" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/pdapi" + "github.com/pingcap/tidb/util/resourcegrouptag" + "github.com/pingcap/tidb/util/set" + "github.com/pingcap/tipb/go-tipb" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +type clusterTablesSuite struct { + store kv.Storage + dom *domain.Domain + rpcserver *grpc.Server + httpServer *httptest.Server + mockAddr string + listenAddr string + startTime time.Time +} + +func TestForClusterServerInfo(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + tk := testkit.NewTestKit(t, s.store) + instances := []string{ + strings.Join([]string{"tidb", s.listenAddr, s.listenAddr, "mock-version,mock-githash,1001"}, ","), + strings.Join([]string{"pd", s.listenAddr, s.listenAddr, "mock-version,mock-githash,0"}, ","), + strings.Join([]string{"tikv", s.listenAddr, s.listenAddr, "mock-version,mock-githash,0"}, ","), + } + + fpExpr := `return("` + strings.Join(instances, ";") + `")` + fpName := "github.com/pingcap/tidb/infoschema/mockClusterInfo" + require.NoError(t, failpoint.Enable(fpName, fpExpr)) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() + + cases := []struct { + sql string + types set.StringSet + addrs set.StringSet + names set.StringSet + skipOnDist set.StringSet + }{ + { + sql: "select * from information_schema.CLUSTER_LOAD;", + types: set.NewStringSet("tidb", "tikv", "pd"), + addrs: set.NewStringSet(s.listenAddr), + names: set.NewStringSet("cpu", "memory", "net"), + }, + { + sql: "select * from information_schema.CLUSTER_HARDWARE;", + types: set.NewStringSet("tidb", "tikv", "pd"), + addrs: set.NewStringSet(s.listenAddr), + names: set.NewStringSet("cpu", "memory", "net", "disk"), + // The sysutil package will filter out all disk don't have /dev prefix. + // gopsutil cpu.Info will fail on mac M1 + skipOnDist: set.NewStringSet("windows", "darwin/arm64"), + }, + { + sql: "select * from information_schema.CLUSTER_SYSTEMINFO;", + types: set.NewStringSet("tidb", "tikv", "pd"), + addrs: set.NewStringSet(s.listenAddr), + names: set.NewStringSet("system"), + // This test get empty result and fails on the windows platform. + // Because the underlying implementation use `sysctl` command to get the result + // and there is no such command on windows. + // https://github.com/pingcap/sysutil/blob/2bfa6dc40bcd4c103bf684fba528ae4279c7ec9f/system_info.go#L50 + skipOnDist: set.NewStringSet("windows"), + }, + } + + for _, cas := range cases { + if cas.skipOnDist.Exist(runtime.GOOS+"/"+runtime.GOARCH) || cas.skipOnDist.Exist(runtime.GOOS) { + continue + } + + result := tk.MustQuery(cas.sql) + rows := result.Rows() + require.Greater(t, len(rows), 0) + + gotTypes := set.StringSet{} + gotAddrs := set.StringSet{} + gotNames := set.StringSet{} + + for _, row := range rows { + gotTypes.Insert(row[0].(string)) + gotAddrs.Insert(row[1].(string)) + gotNames.Insert(row[2].(string)) + } + + require.Equalf(t, cas.types, gotTypes, "sql: %s", cas.sql) + require.Equalf(t, cas.addrs, gotAddrs, "sql: %s", cas.sql) + require.Equalf(t, cas.names, gotNames, "sql: %s", cas.sql) + } +} + +func TestTestDataLockWaits(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + _, digest1 := parser.NormalizeDigest("select * from test_data_lock_waits for update") + _, digest2 := parser.NormalizeDigest("update test_data_lock_waits set f1=1 where id=2") + s.store.(mockstorage.MockLockWaitSetter).SetMockLockWaits([]*deadlock.WaitForEntry{ + {Txn: 1, WaitForTxn: 2, Key: []byte("key1"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(digest1, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, + {Txn: 3, WaitForTxn: 4, Key: []byte("key2"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(digest2, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, + // Invalid digests + {Txn: 5, WaitForTxn: 6, Key: []byte("key3"), ResourceGroupTag: resourcegrouptag.EncodeResourceGroupTag(nil, nil, tipb.ResourceGroupTagLabel_ResourceGroupTagLabelUnknown)}, + {Txn: 7, WaitForTxn: 8, Key: []byte("key4"), ResourceGroupTag: []byte("asdfghjkl")}, + }) + + tk := s.newTestKitWithRoot(t) + + // Execute one of the query once, so it's stored into statements_summary. + tk.MustExec("create table test_data_lock_waits (id int primary key, f1 int)") + tk.MustExec("select * from test_data_lock_waits for update") + + tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS").Check(testkit.Rows( + "6B657931 1 2 "+digest1.String()+" select * from `test_data_lock_waits` for update", + "6B657932 3 4 "+digest2.String()+" ", + "6B657933 5 6 ", + "6B657934 7 8 ")) + +} + +func SubTestDataLockWaitsPrivilege(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + dropUserTk := s.newTestKitWithRoot(t) + + tk := s.newTestKitWithRoot(t) + + tk.MustExec("create user 'testuser'@'localhost'") + defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser", + Hostname: "localhost", + }, nil, nil)) + err := tk.QueryToErr("select * from information_schema.DATA_LOCK_WAITS") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") + + tk = s.newTestKitWithRoot(t) + tk.MustExec("create user 'testuser2'@'localhost'") + defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") + tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser2", + Hostname: "localhost", + }, nil, nil)) + _ = tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS") + +} + +func TestSelectClusterTable(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + slowLogFileName := "tidb-slow.log" + prepareSlowLogfile(t, slowLogFileName) + defer func() { require.NoError(t, os.Remove(slowLogFileName)) }() + + tk.MustExec("use information_schema") + tk.MustExec("set @@global.tidb_enable_stmt_summary=1") + tk.MustExec("set time_zone = '+08:00';") + tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("2")) + tk.MustQuery("select time from `CLUSTER_SLOW_QUERY` where time='2019-02-12 19:33:56.571953'").Check(testkit.RowsWithSep("|", "2019-02-12 19:33:56.571953")) + tk.MustQuery("select count(*) from `CLUSTER_PROCESSLIST`").Check(testkit.Rows("1")) + // skip instance and host column because it now includes the TCP socket details (unstable) + tk.MustQuery("select id, user, db, command, time, state, info, digest, mem, disk, txnstart from `CLUSTER_PROCESSLIST`").Check(testkit.Rows(fmt.Sprintf("1 root Query 9223372036 %s 0 0 ", ""))) + tk.MustQuery("select query_time, conn_id from `CLUSTER_SLOW_QUERY` order by time limit 1").Check(testkit.Rows("4.895492 6")) + tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY` group by digest").Check(testkit.Rows("1", "1")) + tk.MustQuery("select digest, count(*) from `CLUSTER_SLOW_QUERY` group by digest order by digest").Check(testkit.Rows("124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc 1", "42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 1")) + tk.MustQuery(`select length(query) as l,time from information_schema.cluster_slow_query where time > "2019-02-12 19:33:56" order by abs(l) desc limit 10;`).Check(testkit.Rows("21 2019-02-12 19:33:56.571953")) + tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY` where time > now() group by digest").Check(testkit.Rows()) + re := tk.MustQuery("select * from `CLUSTER_statements_summary`") + require.NotNil(t, re) + require.Greater(t, len(re.Rows()), 0) + re = tk.MustQuery("select * from `CLUSTER_statements_summary` where table_names REGEXP '\\binformation_schema\\.'") + require.NotNil(t, re) + require.Equal(t, len(re.Rows()), 0) + re = tk.MustQuery("select * from `CLUSTER_statements_summary` where table_names REGEXP 'information_schema\\.'") + require.NotNil(t, re) + require.Greater(t, len(re.Rows()), 0) + // Test for TiDB issue 14915. + re = tk.MustQuery("select sum(exec_count*avg_mem) from cluster_statements_summary_history group by schema_name,digest,digest_text;") + require.NotNil(t, re) + require.Greater(t, len(re.Rows()), 0) + tk.MustQuery("select * from `CLUSTER_statements_summary_history`") + require.NotNil(t, re) + require.Greater(t, len(re.Rows()), 0) + tk.MustExec("set @@global.tidb_enable_stmt_summary=0") + re = tk.MustQuery("select * from `CLUSTER_statements_summary`") + require.NotNil(t, re) + require.Equal(t, 0, len(re.Rows())) + tk.MustQuery("select * from `CLUSTER_statements_summary_history`") + require.NotNil(t, re) + require.Equal(t, 0, len(re.Rows())) +} + +func SubTestSelectClusterTablePrivilege(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := testkit.NewTestKit(t, s.store) + slowLogFileName := "tidb-slow.log" + f, err := os.OpenFile(slowLogFileName, os.O_CREATE|os.O_WRONLY, 0644) + require.NoError(t, err) + _, err = f.Write([]byte( + `# Time: 2019-02-12T19:33:57.571953+08:00 +# User@Host: user2 [user2] @ 127.0.0.1 [127.0.0.1] +select * from t2; +# Time: 2019-02-12T19:33:56.571953+08:00 +# User@Host: user1 [user1] @ 127.0.0.1 [127.0.0.1] +select * from t1; +# Time: 2019-02-12T19:33:58.571953+08:00 +# User@Host: user2 [user2] @ 127.0.0.1 [127.0.0.1] +select * from t3; +# Time: 2019-02-12T19:33:59.571953+08:00 +select * from t3; +`)) + require.NoError(t, f.Close()) + require.NoError(t, err) + defer func() { require.NoError(t, os.Remove(slowLogFileName)) }() + tk.MustExec("use information_schema") + tk.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("4")) + tk.MustQuery("select count(*) from `SLOW_QUERY`").Check(testkit.Rows("4")) + tk.MustQuery("select count(*) from `CLUSTER_PROCESSLIST`").Check(testkit.Rows("1")) + tk.MustQuery("select * from `CLUSTER_PROCESSLIST`").Check(testkit.Rows(fmt.Sprintf(":10080 1 root 127.0.0.1 Query 9223372036 %s 0 0 ", ""))) + tk.MustExec("create user user1") + tk.MustExec("create user user2") + user1 := testkit.NewTestKit(t, s.store) + user1.MustExec("use information_schema") + require.True(t, user1.Session().Auth(&auth.UserIdentity{ + Username: "user1", + Hostname: "127.0.0.1", + }, nil, nil)) + user1.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("1")) + user1.MustQuery("select count(*) from `SLOW_QUERY`").Check(testkit.Rows("1")) + user1.MustQuery("select user,query from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("user1 select * from t1;")) + + user2 := testkit.NewTestKit(t, s.store) + user2.MustExec("use information_schema") + require.True(t, user2.Session().Auth(&auth.UserIdentity{ + Username: "user2", + Hostname: "127.0.0.1", + }, nil, nil)) + user2.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("2")) + user2.MustQuery("select user,query from `CLUSTER_SLOW_QUERY` order by query").Check(testkit.Rows("user2 select * from t2;", "user2 select * from t3;")) +} + +func TestStmtSummaryEvictedCountTable(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + tk := s.newTestKitWithRoot(t) + // disable refreshing + tk.MustExec("set global tidb_stmt_summary_refresh_interval=9999") + // set information_schema.statements_summary's size to 2 + tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 2") + // no evict happened, no record in cluster evicted table. + tk.MustQuery("select count(*) from information_schema.cluster_statements_summary_evicted;").Check(testkit.Rows("0")) + tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 1") + // cleanup side effects + defer tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 100") + defer tk.MustExec("set global tidb_stmt_summary_refresh_interval = 1800") + // clear information_schema.statements_summary + tk.MustExec("set global tidb_enable_stmt_summary=0") + // statements_summary is off, statements_summary_evicted is empty. + tk.MustQuery("select count(*) from information_schema.cluster_statements_summary_evicted;").Check(testkit.Rows("0")) + tk.MustExec("set global tidb_enable_stmt_summary=1") + + // make a new session for test... + tk = s.newTestKitWithRoot(t) + // first sql + tk.MustExec("show databases;") + // second sql, evict former sql from stmt_summary + tk.MustQuery("select evicted_count from information_schema.cluster_statements_summary_evicted;"). + Check(testkit.Rows("1")) + // after executed the sql above + tk.MustQuery("select evicted_count from information_schema.cluster_statements_summary_evicted;"). + Check(testkit.Rows("2")) + // TODO: Add more tests. + + tk.MustExec("create user 'testuser'@'localhost'") + tk.MustExec("create user 'testuser2'@'localhost'") + tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") + tk1 := s.newTestKitWithRoot(t) + defer tk1.MustExec("drop user 'testuser'@'localhost'") + defer tk1.MustExec("drop user 'testuser2'@'localhost'") + + require.True(t, tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser", + Hostname: "localhost", + }, nil, nil)) + + err := tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED") + // This error is come from cop(TiDB) fetch from rpc server. + require.EqualError(t, err, "other error: [planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") + + require.True(t, tk.Session().Auth(&auth.UserIdentity{ + Username: "testuser2", + Hostname: "localhost", + }, nil, nil)) + require.NoError(t, tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED")) +} + +func TestStmtSummaryHistoryTableWithUserTimezone(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + tk := s.newTestKitWithRoot(t) + tk.MustExec("drop table if exists test_summary") + tk.MustExec("create table test_summary(a int, b varchar(10), key k(a))") + + tk.MustExec("set global tidb_enable_stmt_summary = 1") + tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) + + // Disable refreshing summary. + tk.MustExec("set global tidb_stmt_summary_refresh_interval = 999999999") + tk.MustQuery("select @@global.tidb_stmt_summary_refresh_interval").Check(testkit.Rows("999999999")) + + // Create a new session to test. + tk = s.newTestKitWithRoot(t) + tk.MustExec("use test;") + tk.MustExec("set time_zone = '+08:00';") + tk.MustExec("select sleep(0.1);") + r := tk.MustQuery("select FIRST_SEEN, LAST_SEEN, SUMMARY_BEGIN_TIME, SUMMARY_END_TIME from INFORMATION_SCHEMA.STATEMENTS_SUMMARY_HISTORY order by LAST_SEEN limit 1;") + date8First, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][0].(string)) + require.NoError(t, err) + date8Last, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][1].(string)) + require.NoError(t, err) + date8Begin, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][2].(string)) + require.NoError(t, err) + date8End, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][3].(string)) + require.NoError(t, err) + tk.MustExec("set time_zone = '+01:00';") + r = tk.MustQuery("select FIRST_SEEN, LAST_SEEN, SUMMARY_BEGIN_TIME, SUMMARY_END_TIME from INFORMATION_SCHEMA.STATEMENTS_SUMMARY_HISTORY order by LAST_SEEN limit 1;") + date1First, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][0].(string)) + require.NoError(t, err) + date1Last, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][1].(string)) + require.NoError(t, err) + date1Begin, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][2].(string)) + require.NoError(t, err) + date1End, err := time.Parse("2006-01-02 15:04:05", r.Rows()[0][3].(string)) + require.NoError(t, err) + + require.Less(t, date1First.Unix(), date8First.Unix()) + require.Less(t, date1Last.Unix(), date8Last.Unix()) + require.Less(t, date1Begin.Unix(), date8Begin.Unix()) + require.Less(t, date1End.Unix(), date8End.Unix()) +} + +func TestStmtSummaryHistoryTable(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + tk := s.newTestKitWithRoot(t) + tk.MustExec("drop table if exists test_summary") + tk.MustExec("create table test_summary(a int, b varchar(10), key k(a))") + + tk.MustExec("set global tidb_enable_stmt_summary = 1") + tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) + + // Disable refreshing summary. + tk.MustExec("set global tidb_stmt_summary_refresh_interval = 999999999") + tk.MustQuery("select @@global.tidb_stmt_summary_refresh_interval").Check(testkit.Rows("999999999")) + + // Create a new session to test. + tk = s.newTestKitWithRoot(t) + + // Test INSERT + tk.MustExec("insert into test_summary values(1, 'a')") + tk.MustExec("insert into test_summary values(2, 'b')") + tk.MustExec("insert into TEST_SUMMARY VALUES(3, 'c')") + tk.MustExec("/**/insert into test_summary values(4, 'd')") + + sql := "select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys," + + "max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions," + + "max_prewrite_regions, avg_affected_rows, query_sample_text " + + "from information_schema.statements_summary_history " + + "where digest_text like 'insert into `test_summary`%'" + tk.MustQuery(sql).Check(testkit.Rows("Insert test test.test_summary 4 0 0 0 0 0 2 2 1 1 1 insert into test_summary values(1, 'a')")) + + tk.MustExec("set global tidb_stmt_summary_history_size = 0") + tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys, + max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions, + max_prewrite_regions, avg_affected_rows, query_sample_text, plan + from information_schema.statements_summary_history`, + ).Check(testkit.Rows()) + + tk.MustExec("set global tidb_enable_stmt_summary = 0") + tk.MustExec("drop table if exists `table`") + tk.MustExec("set global tidb_stmt_summary_history_size = 1") + tk.MustExec("set global tidb_enable_stmt_summary = 1") + tk.MustExec("create table `table`(`insert` int)") + tk.MustExec("select `insert` from `table`") + + sql = "select digest_text from information_schema.statements_summary_history;" + tk.MustQuery(sql).Check(testkit.Rows( + "select `insert` from `table`", + "create table `table` ( `insert` int )", + "set global `tidb_enable_stmt_summary` = ?", + )) +} + +func TestIssue26379(t *testing.T) { + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + + // Clear all statements. + tk.MustExec("set global tidb_enable_stmt_summary = 0") + tk.MustExec("set global tidb_enable_stmt_summary = 1") + tk.MustExec("set @@global.tidb_stmt_summary_max_stmt_count=10") + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10), c int, d int, key k(a))") + + _, digest1 := parser.NormalizeDigest("select * from t where a = 3") + _, digest2 := parser.NormalizeDigest("select * from t where b = 'b'") + _, digest3 := parser.NormalizeDigest("select * from t where c = 6") + _, digest4 := parser.NormalizeDigest("select * from t where d = 5") + fillStatementCache := func() { + tk.MustQuery("select * from t where a = 3") + tk.MustQuery("select * from t where b = 'b'") + tk.MustQuery("select * from t where c = 6") + tk.MustQuery("select * from t where d = 5") + } + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest1.String())).Check(testkit.Rows(digest1.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest1.String())).Check(testkit.Rows(digest1.String())) + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest2.String())).Check(testkit.Rows(digest2.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest2.String())).Check(testkit.Rows(digest2.String())) + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest3.String())).Check(testkit.Rows(digest3.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest3.String())).Check(testkit.Rows(digest3.String())) + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s'", digest4.String())).Check(testkit.Rows(digest4.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s'", digest4.String())).Check(testkit.Rows(digest4.String())) + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest = '%s' or digest = '%s'", digest1.String(), digest2.String())).Sort().Check(testkit.Rows(digest1.String(), digest2.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' or digest = '%s'", digest1.String(), digest2.String())).Sort().Check(testkit.Rows(digest1.String(), digest2.String())) + re := tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' and digest = '%s'", digest1.String(), digest2.String())) + require.Equal(t, 0, len(re.Rows())) + re = tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest = '%s' and digest = '%s'", digest1.String(), digest2.String())) + require.Equal(t, 0, len(re.Rows())) + fillStatementCache() + tk.MustQuery(fmt.Sprintf("select digest from information_schema.statements_summary where digest in ('%s', '%s', '%s', '%s')", digest1.String(), digest2.String(), digest3.String(), digest4.String())).Sort().Check(testkit.Rows(digest1.String(), digest4.String(), digest2.String(), digest3.String())) + tk.MustQuery(fmt.Sprintf("select digest from information_schema.cluster_statements_summary where digest in ('%s', '%s', '%s', '%s')", digest1.String(), digest2.String(), digest3.String(), digest4.String())).Sort().Check(testkit.Rows(digest1.String(), digest4.String(), digest2.String(), digest3.String())) + fillStatementCache() + tk.MustQuery("select count(*) from information_schema.statements_summary where digest=''").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from information_schema.statements_summary where digest is null").Check(testkit.Rows("1")) + tk.MustQuery("select count(*) from information_schema.cluster_statements_summary where digest=''").Check(testkit.Rows("0")) + tk.MustQuery("select count(*) from information_schema.cluster_statements_summary where digest is null").Check(testkit.Rows("1")) +} + +func TestStmtSummaryResultRows(t *testing.T) { + // setup suite + var clean func() + s := new(clusterTablesSuite) + s.store, s.dom, clean = testkit.CreateMockStoreAndDomain(t) + defer clean() + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0") + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + + tk := s.newTestKitWithRoot(t) + tk.MustExec("set global tidb_stmt_summary_refresh_interval=999999999") + tk.MustExec("set global tidb_stmt_summary_max_stmt_count = 3000") + tk.MustExec("set global tidb_stmt_summary_history_size=24") + tk.MustExec("set global tidb_stmt_summary_max_sql_length=4096") + tk.MustExec("set global tidb_enable_stmt_summary=0") + tk.MustExec("set global tidb_enable_stmt_summary=1") + if !config.GetGlobalConfig().EnableCollectExecutionInfo { + tk.MustExec("set @@tidb_enable_collect_execution_info=1") + defer tk.MustExec("set @@tidb_enable_collect_execution_info=0") + } + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int)") + for i := 1; i <= 30; i++ { + tk.MustExec(fmt.Sprintf("insert into t values (%v)", i)) + } + + tk.MustQuery("select * from test.t limit 10;") + tk.MustQuery("select * from test.t limit 20;") + tk.MustQuery("select * from test.t limit 30;") + tk.MustQuery("select MIN_RESULT_ROWS,MAX_RESULT_ROWS,AVG_RESULT_ROWS from information_schema.statements_summary where query_sample_text like 'select%test.t limit%' and MAX_RESULT_ROWS > 10"). + Check(testkit.Rows("10 30 20")) + tk.MustQuery("select MIN_RESULT_ROWS,MAX_RESULT_ROWS,AVG_RESULT_ROWS from information_schema.cluster_statements_summary where query_sample_text like 'select%test.t limit%' and MAX_RESULT_ROWS > 10"). + Check(testkit.Rows("10 30 20")) +} + +func (s *clusterTablesSuite) setUpRPCService(t *testing.T, addr string) (*grpc.Server, string) { + lis, err := net.Listen("tcp", addr) + require.NoError(t, err) + // Fix issue 9836 + sm := &mockSessionManager{make(map[uint64]*util.ProcessInfo, 1), nil} + sm.processInfoMap[1] = &util.ProcessInfo{ + ID: 1, + User: "root", + Host: "127.0.0.1", + Command: mysql.ComQuery, + } + srv := server.NewRPCServer(config.GetGlobalConfig(), s.dom, sm) + port := lis.Addr().(*net.TCPAddr).Port + addr = fmt.Sprintf("127.0.0.1:%d", port) + go func() { + err = srv.Serve(lis) + require.NoError(t, err) + }() + config.UpdateGlobal(func(conf *config.Config) { + conf.Status.StatusPort = uint(port) + }) + return srv, addr +} + +func (s *clusterTablesSuite) setUpMockPDHTTPServer() (*httptest.Server, string) { + // mock PD http server + router := mux.NewRouter() + srv := httptest.NewServer(router) + // mock store stats stat + mockAddr := strings.TrimPrefix(srv.URL, "http://") + router.Handle(pdapi.Stores, fn.Wrap(func() (*helper.StoresStat, error) { + return &helper.StoresStat{ + Count: 1, + Stores: []helper.StoreStat{ + { + Store: helper.StoreBaseStat{ + ID: 1, + Address: "127.0.0.1:20160", + State: 0, + StateName: "Up", + Version: "4.0.0-alpha", + StatusAddress: mockAddr, + GitHash: "mock-tikv-githash", + StartTimestamp: s.startTime.Unix(), + }, + }, + }, + }, nil + })) + // mock PD API + router.Handle(pdapi.Status, fn.Wrap(func() (interface{}, error) { + return struct { + Version string `json:"version"` + GitHash string `json:"git_hash"` + StartTimestamp int64 `json:"start_timestamp"` + }{ + Version: "4.0.0-alpha", + GitHash: "mock-pd-githash", + StartTimestamp: s.startTime.Unix(), + }, nil + })) + var mockConfig = func() (map[string]interface{}, error) { + configuration := map[string]interface{}{ + "key1": "value1", + "key2": map[string]string{ + "nest1": "n-value1", + "nest2": "n-value2", + }, + "key3": map[string]interface{}{ + "nest1": "n-value1", + "nest2": "n-value2", + "key4": map[string]string{ + "nest3": "n-value4", + "nest4": "n-value5", + }, + }, + } + return configuration, nil + } + // pd config + router.Handle(pdapi.Config, fn.Wrap(mockConfig)) + // TiDB/TiKV config + router.Handle("/config", fn.Wrap(mockConfig)) + return srv, mockAddr +} + +func (s *clusterTablesSuite) newTestKitWithRoot(t *testing.T) *testkit.TestKit { + tk := testkit.NewTestKit(t, s.store) + tk.MustExec("use test") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + return tk +} diff --git a/infoschema/error.go b/infoschema/error.go index 49dc2136d0820..6afcf23177e02 100644 --- a/infoschema/error.go +++ b/infoschema/error.go @@ -78,4 +78,6 @@ var ( ErrWrongObject = dbterror.ClassSchema.NewStd(mysql.ErrWrongObject) // ErrAdminCheckTable returns when the check table in temporary mode. ErrAdminCheckTable = dbterror.ClassSchema.NewStd(mysql.ErrAdminCheckTable) + // ErrEmptyDatabase returns when the database is unexpectedly empty. + ErrEmptyDatabase = dbterror.ClassSchema.NewStd(mysql.ErrBadDB) ) diff --git a/infoschema/infoschema_test.go b/infoschema/infoschema_test.go index f3adc34ed7a15..46e60d924cd69 100644 --- a/infoschema/infoschema_test.go +++ b/infoschema/infoschema_test.go @@ -32,9 +32,10 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testutil" ) func TestBasic(t *testing.T) { @@ -107,7 +108,7 @@ func TestBasic(t *testing.T) { }) require.NoError(t, err) - builder, err := infoschema.NewBuilder(dom.Store(), nil, nil).InitWithDBInfos(dbInfos, nil, nil, 1) + builder, err := infoschema.NewBuilder(dom.Store(), nil).InitWithDBInfos(dbInfos, nil, nil, 1) require.NoError(t, err) txn, err := store.Begin() @@ -253,7 +254,7 @@ func TestInfoTables(t *testing.T) { require.NoError(t, err) }() - builder, err := infoschema.NewBuilder(store, nil, nil).InitWithDBInfos(nil, nil, nil, 0) + builder, err := infoschema.NewBuilder(store, nil).InitWithDBInfos(nil, nil, nil, 0) require.NoError(t, err) is := builder.Build() @@ -291,7 +292,7 @@ func TestInfoTables(t *testing.T) { "PROCESSLIST", "TIDB_TRX", "DEADLOCKS", - "PLACEMENT_RULES", + "PLACEMENT_POLICIES", } for _, tbl := range infoTables { tb, err1 := is.TableByName(util.InformationSchemaName, model.NewCIStr(tbl)) @@ -318,7 +319,7 @@ func TestGetBundle(t *testing.T) { require.NoError(t, err) }() - builder, err := infoschema.NewBuilder(store, nil, nil).InitWithDBInfos(nil, nil, nil, 0) + builder, err := infoschema.NewBuilder(store, nil).InitWithDBInfos(nil, nil, nil, 0) require.NoError(t, err) is := builder.Build() @@ -645,3 +646,14 @@ func TestLocalTemporaryTables(t *testing.T) { require.False(t, ok) require.Nil(t, info) } + +func TestIndexComment(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("DROP TABLE IF EXISTS `t1`;") + tk.MustExec("create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'Abcdefghijabcd', c2 INTEGER COMMENT 'aBcdefghijab',c3 INTEGER COMMENT '01234567890', c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 VARCHAR(100), c9 CHAR(50), c10 DATETIME, c11 DATETIME, c12 DATETIME,c13 DATETIME, INDEX i1 (c1) COMMENT 'i1 comment',INDEX i2(c2) ) COMMENT='ABCDEFGHIJabc';") + tk.MustQuery("SELECT index_comment,char_length(index_comment),COLUMN_NAME FROM information_schema.statistics WHERE table_name='t1' ORDER BY index_comment;").Check(testkit.Rows(" 0 c2", "i1 comment 10 c1")) +} diff --git a/infoschema/main_test.go b/infoschema/main_test.go index 8d3c4dba9623e..7ca5612d5f13d 100644 --- a/infoschema/main_test.go +++ b/infoschema/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/infoschema/perfschema/main_test.go b/infoschema/perfschema/main_test.go index 068cebc3f3cb0..acfdc80447866 100644 --- a/infoschema/perfschema/main_test.go +++ b/infoschema/perfschema/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/infoschema/perfschema/tables.go b/infoschema/perfschema/tables.go index 759629fb6ca2c..1beea67e64a1b 100644 --- a/infoschema/perfschema/tables.go +++ b/infoschema/perfschema/tables.go @@ -382,7 +382,7 @@ func dataForRemoteProfile(ctx sessionctx.Context, nodeType, uri string, isGorout close(ch) // Keep the original order to make the result more stable - var results []result + var results []result // nolint: prealloc for result := range ch { if result.err != nil { ctx.GetSessionVars().StmtCtx.AppendWarning(result.err) diff --git a/infoschema/perfschema/tables_serial_test.go b/infoschema/perfschema/tables_serial_test.go deleted file mode 100644 index f8126a57b2b7c..0000000000000 --- a/infoschema/perfschema/tables_serial_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package perfschema_test - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "runtime/pprof" - "strings" - "testing" - - "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/testkit" - "github.com/stretchr/testify/require" -) - -func TestTiKVProfileCPU(t *testing.T) { - store, clean := newMockStore(t) - defer clean() - - router := http.NewServeMux() - mockServer := httptest.NewServer(router) - mockAddr := strings.TrimPrefix(mockServer.URL, "http://") - defer mockServer.Close() - - // mock tikv profile - copyHandler := func(filename string) http.HandlerFunc { - return func(w http.ResponseWriter, _ *http.Request) { - file, err := os.Open(filepath.Join(currentSourceDir(), filename)) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - defer func() { terror.Log(file.Close()) }() - _, err = io.Copy(w, file) - terror.Log(err) - } - } - router.HandleFunc("/debug/pprof/profile", copyHandler("testdata/tikv.cpu.profile")) - - // failpoint setting - servers := []string{ - strings.Join([]string{"tikv", mockAddr, mockAddr}, ","), - strings.Join([]string{"pd", mockAddr, mockAddr}, ","), - } - fpExpr := strings.Join(servers, ";") - fpName := "github.com/pingcap/tidb/infoschema/perfschema/mockRemoteNodeStatusAddress" - require.NoError(t, failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr))) - defer func() { require.NoError(t, failpoint.Disable(fpName)) }() - - tk := testkit.NewTestKit(t, store) - - tk.MustExec("use performance_schema") - result := tk.MustQuery("select function, percent_abs, percent_rel from tikv_profile_cpu where depth < 3") - - warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - result.Check(testkit.Rows( - "root 100% 100%", - "├─tikv::server::load_statistics::linux::ThreadLoadStatistics::record::h59facb8d680e7794 75.00% 75.00%", - "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 75.00% 100%", - "├─nom::nom::digit::h905aaaeff7d8ec8e 16.07% 16.07%", - "│ ├─ as core::iter::traits::iterator::Iterator>::next::h16936f9061bb75e4 6.25% 38.89%", - "│ ├─Unknown 3.57% 22.22%", - "│ ├─<&u8 as nom::traits::AsChar>::is_dec_digit::he9eacc3fad26ab81 2.68% 16.67%", - "│ ├─<&[u8] as nom::traits::InputIter>::iter_indices::h6192338433683bff 1.79% 11.11%", - "│ └─<&[T] as nom::traits::Slice>>::slice::h38d31f11f84aa302 1.79% 11.11%", - "├─::realloc::h5199c50710ab6f9d 1.79% 1.79%", - "│ └─rallocx 1.79% 100%", - "├─::dealloc::hea83459aa98dd2dc 1.79% 1.79%", - "│ └─sdallocx 1.79% 100%", - "├─::alloc::hc7962e02169a5c56 0.89% 0.89%", - "│ └─mallocx 0.89% 100%", - "├─engine::rocks::util::engine_metrics::flush_engine_iostall_properties::h64a7661c95aa1db7 0.89% 0.89%", - "│ └─rocksdb::rocksdb::DB::get_map_property_cf::h9722f9040411af44 0.89% 100%", - "├─core::ptr::real_drop_in_place::h8def0d99e7136f33 0.89% 0.89%", - "│ └─ as core::ops::drop::Drop>::drop::h9b59b303bffde02c 0.89% 100%", - "├─tikv_util::metrics::threads_linux::ThreadInfoStatistics::record::ha8cc290b3f46af88 0.89% 0.89%", - "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 0.89% 100%", - "├─crossbeam_utils::backoff::Backoff::snooze::h5c121ef4ce616a3c 0.89% 0.89%", - "│ └─core::iter::range::>::next::hdb23ceb766e7a91f 0.89% 100%", - "└─::next::he129c78b3deb639d 0.89% 0.89%", - " └─Unknown 0.89% 100%")) - - // We can use current processe profile to mock profile of PD because the PD has the - // same way of retrieving profile with TiDB. And the purpose of this test case is used - // to make sure all profile HTTP API have been accessed. - accessed := map[string]struct{}{} - handlerFactory := func(name string, debug ...int) func(w http.ResponseWriter, _ *http.Request) { - debugLevel := 0 - if len(debug) > 0 { - debugLevel = debug[0] - } - return func(w http.ResponseWriter, _ *http.Request) { - profile := pprof.Lookup(name) - if profile == nil { - http.Error(w, fmt.Sprintf("profile %s not found", name), http.StatusBadRequest) - return - } - if err := profile.WriteTo(w, debugLevel); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - accessed[name] = struct{}{} - } - } - - // mock PD profile - router.HandleFunc("/pd/api/v1/debug/pprof/profile", copyHandler("../../util/profile/testdata/test.pprof")) - router.HandleFunc("/pd/api/v1/debug/pprof/heap", handlerFactory("heap")) - router.HandleFunc("/pd/api/v1/debug/pprof/mutex", handlerFactory("mutex")) - router.HandleFunc("/pd/api/v1/debug/pprof/allocs", handlerFactory("allocs")) - router.HandleFunc("/pd/api/v1/debug/pprof/block", handlerFactory("block")) - router.HandleFunc("/pd/api/v1/debug/pprof/goroutine", handlerFactory("goroutine", 2)) - - tk.MustQuery("select * from pd_profile_cpu where depth < 3") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - tk.MustQuery("select * from pd_profile_memory where depth < 3") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - tk.MustQuery("select * from pd_profile_mutex where depth < 3") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - tk.MustQuery("select * from pd_profile_allocs where depth < 3") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - tk.MustQuery("select * from pd_profile_block where depth < 3") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - tk.MustQuery("select * from pd_profile_goroutines") - warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() - require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) - - require.Lenf(t, accessed, 5, "expect all HTTP API had been accessed, but found: %v", accessed) -} diff --git a/infoschema/perfschema/tables_test.go b/infoschema/perfschema/tables_test.go index be739a5b6af48..057ba404efec7 100644 --- a/infoschema/perfschema/tables_test.go +++ b/infoschema/perfschema/tables_test.go @@ -15,12 +15,21 @@ package perfschema_test import ( + "fmt" + "io" + "net/http" + "net/http/httptest" + "os" "path/filepath" "runtime" + "runtime/pprof" + "strings" "testing" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/infoschema/perfschema" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/testkit" @@ -44,6 +53,133 @@ func TestPerfSchemaTables(t *testing.T) { tk.MustQuery("select * from events_stages_history_long").Check(testkit.Rows()) } +func TestTiKVProfileCPU(t *testing.T) { + store, clean := newMockStore(t) + defer clean() + + router := http.NewServeMux() + mockServer := httptest.NewServer(router) + mockAddr := strings.TrimPrefix(mockServer.URL, "http://") + defer mockServer.Close() + + // mock tikv profile + copyHandler := func(filename string) http.HandlerFunc { + return func(w http.ResponseWriter, _ *http.Request) { + file, err := os.Open(filepath.Join(currentSourceDir(), filename)) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + defer func() { terror.Log(file.Close()) }() + _, err = io.Copy(w, file) + terror.Log(err) + } + } + router.HandleFunc("/debug/pprof/profile", copyHandler("testdata/tikv.cpu.profile")) + + // failpoint setting + servers := []string{ + strings.Join([]string{"tikv", mockAddr, mockAddr}, ","), + strings.Join([]string{"pd", mockAddr, mockAddr}, ","), + } + fpExpr := strings.Join(servers, ";") + fpName := "github.com/pingcap/tidb/infoschema/perfschema/mockRemoteNodeStatusAddress" + require.NoError(t, failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr))) + defer func() { require.NoError(t, failpoint.Disable(fpName)) }() + + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use performance_schema") + result := tk.MustQuery("select function, percent_abs, percent_rel from tikv_profile_cpu where depth < 3") + + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + result.Check(testkit.Rows( + "root 100% 100%", + "├─tikv::server::load_statistics::linux::ThreadLoadStatistics::record::h59facb8d680e7794 75.00% 75.00%", + "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 75.00% 100%", + "├─nom::nom::digit::h905aaaeff7d8ec8e 16.07% 16.07%", + "│ ├─ as core::iter::traits::iterator::Iterator>::next::h16936f9061bb75e4 6.25% 38.89%", + "│ ├─Unknown 3.57% 22.22%", + "│ ├─<&u8 as nom::traits::AsChar>::is_dec_digit::he9eacc3fad26ab81 2.68% 16.67%", + "│ ├─<&[u8] as nom::traits::InputIter>::iter_indices::h6192338433683bff 1.79% 11.11%", + "│ └─<&[T] as nom::traits::Slice>>::slice::h38d31f11f84aa302 1.79% 11.11%", + "├─::realloc::h5199c50710ab6f9d 1.79% 1.79%", + "│ └─rallocx 1.79% 100%", + "├─::dealloc::hea83459aa98dd2dc 1.79% 1.79%", + "│ └─sdallocx 1.79% 100%", + "├─::alloc::hc7962e02169a5c56 0.89% 0.89%", + "│ └─mallocx 0.89% 100%", + "├─engine::rocks::util::engine_metrics::flush_engine_iostall_properties::h64a7661c95aa1db7 0.89% 0.89%", + "│ └─rocksdb::rocksdb::DB::get_map_property_cf::h9722f9040411af44 0.89% 100%", + "├─core::ptr::real_drop_in_place::h8def0d99e7136f33 0.89% 0.89%", + "│ └─ as core::ops::drop::Drop>::drop::h9b59b303bffde02c 0.89% 100%", + "├─tikv_util::metrics::threads_linux::ThreadInfoStatistics::record::ha8cc290b3f46af88 0.89% 0.89%", + "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 0.89% 100%", + "├─crossbeam_utils::backoff::Backoff::snooze::h5c121ef4ce616a3c 0.89% 0.89%", + "│ └─core::iter::range::>::next::hdb23ceb766e7a91f 0.89% 100%", + "└─::next::he129c78b3deb639d 0.89% 0.89%", + " └─Unknown 0.89% 100%")) + + // We can use current processe profile to mock profile of PD because the PD has the + // same way of retrieving profile with TiDB. And the purpose of this test case is used + // to make sure all profile HTTP API have been accessed. + accessed := map[string]struct{}{} + handlerFactory := func(name string, debug ...int) func(w http.ResponseWriter, _ *http.Request) { + debugLevel := 0 + if len(debug) > 0 { + debugLevel = debug[0] + } + return func(w http.ResponseWriter, _ *http.Request) { + profile := pprof.Lookup(name) + if profile == nil { + http.Error(w, fmt.Sprintf("profile %s not found", name), http.StatusBadRequest) + return + } + if err := profile.WriteTo(w, debugLevel); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + accessed[name] = struct{}{} + } + } + + // mock PD profile + router.HandleFunc("/pd/api/v1/debug/pprof/profile", copyHandler("../../util/profile/testdata/test.pprof")) + router.HandleFunc("/pd/api/v1/debug/pprof/heap", handlerFactory("heap")) + router.HandleFunc("/pd/api/v1/debug/pprof/mutex", handlerFactory("mutex")) + router.HandleFunc("/pd/api/v1/debug/pprof/allocs", handlerFactory("allocs")) + router.HandleFunc("/pd/api/v1/debug/pprof/block", handlerFactory("block")) + router.HandleFunc("/pd/api/v1/debug/pprof/goroutine", handlerFactory("goroutine", 2)) + + tk.MustQuery("select * from pd_profile_cpu where depth < 3") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + tk.MustQuery("select * from pd_profile_memory where depth < 3") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + tk.MustQuery("select * from pd_profile_mutex where depth < 3") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + tk.MustQuery("select * from pd_profile_allocs where depth < 3") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + tk.MustQuery("select * from pd_profile_block where depth < 3") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + tk.MustQuery("select * from pd_profile_goroutines") + warnings = tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Lenf(t, warnings, 0, "expect no warnings, but found: %+v", warnings) + + require.Lenf(t, accessed, 5, "expect all HTTP API had been accessed, but found: %v", accessed) +} + func newMockStore(t *testing.T) (store kv.Storage, clean func()) { var err error store, err = mockstore.NewMockStore() diff --git a/infoschema/tables.go b/infoschema/tables.go index 2e09e91469541..f1a20b9606a95 100644 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -176,8 +176,8 @@ const ( TableDataLockWaits = "DATA_LOCK_WAITS" // TableAttributes is the string constant of attributes table. TableAttributes = "ATTRIBUTES" - // TablePlacementRules is the string constant of placement rules table. - TablePlacementRules = "PLACEMENT_RULES" + // TablePlacementPolicies is the string constant of placement policies table. + TablePlacementPolicies = "PLACEMENT_POLICIES" ) const ( @@ -275,7 +275,7 @@ var tableIDMap = map[string]int64{ ClusterTableStatementsSummaryEvicted: autoid.InformationSchemaDBID + 76, TableAttributes: autoid.InformationSchemaDBID + 77, TableTiDBHotRegionsHistory: autoid.InformationSchemaDBID + 78, - TablePlacementRules: autoid.InformationSchemaDBID + 79, + TablePlacementPolicies: autoid.InformationSchemaDBID + 79, } type columnInfo struct { @@ -360,7 +360,6 @@ var schemataCols = []columnInfo{ {name: "DEFAULT_COLLATION_NAME", tp: mysql.TypeVarchar, size: 32}, {name: "SQL_PATH", tp: mysql.TypeVarchar, size: 512}, {name: "TIDB_PLACEMENT_POLICY_NAME", tp: mysql.TypeVarchar, size: 64}, - {name: "TIDB_DIRECT_PLACEMENT", tp: mysql.TypeVarchar, size: 1024}, } var tablesCols = []columnInfo{ @@ -389,10 +388,9 @@ var tablesCols = []columnInfo{ {name: "TIDB_ROW_ID_SHARDING_INFO", tp: mysql.TypeVarchar, size: 255}, {name: "TIDB_PK_TYPE", tp: mysql.TypeVarchar, size: 64}, {name: "TIDB_PLACEMENT_POLICY_NAME", tp: mysql.TypeVarchar, size: 64}, - {name: "TIDB_DIRECT_PLACEMENT", tp: mysql.TypeVarchar, size: 1024}, } -// See: http://dev.mysql.com/doc/refman/5.7/en/columns-table.html +// See: http://dev.mysql.com/doc/refman/5.7/en/information-schema-columns-table.html var columnsCols = []columnInfo{ {name: "TABLE_CATALOG", tp: mysql.TypeVarchar, size: 512}, {name: "TABLE_SCHEMA", tp: mysql.TypeVarchar, size: 64}, @@ -497,7 +495,7 @@ var keyColumnUsageCols = []columnInfo{ {name: "REFERENCED_COLUMN_NAME", tp: mysql.TypeVarchar, size: 64}, } -// See http://dev.mysql.com/doc/refman/5.7/en/referential-constraints-table.html +// See http://dev.mysql.com/doc/refman/5.7/en/information-schema-referential-constraints-table.html var referConstCols = []columnInfo{ {name: "CONSTRAINT_CATALOG", tp: mysql.TypeVarchar, size: 512, flag: mysql.NotNullFlag}, {name: "CONSTRAINT_SCHEMA", tp: mysql.TypeVarchar, size: 64, flag: mysql.NotNullFlag}, @@ -512,13 +510,13 @@ var referConstCols = []columnInfo{ {name: "REFERENCED_TABLE_NAME", tp: mysql.TypeVarchar, size: 64, flag: mysql.NotNullFlag}, } -// See http://dev.mysql.com/doc/refman/5.7/en/variables-table.html +// See http://dev.mysql.com/doc/refman/5.7/en/information-schema-variables-table.html var sessionVarCols = []columnInfo{ {name: "VARIABLE_NAME", tp: mysql.TypeVarchar, size: 64}, {name: "VARIABLE_VALUE", tp: mysql.TypeVarchar, size: 1024}, } -// See https://dev.mysql.com/doc/refman/5.7/en/plugins-table.html +// See https://dev.mysql.com/doc/refman/5.7/en/information-schema-plugins-table.html var pluginsCols = []columnInfo{ {name: "PLUGIN_NAME", tp: mysql.TypeVarchar, size: 64}, {name: "PLUGIN_VERSION", tp: mysql.TypeVarchar, size: 20}, @@ -533,7 +531,7 @@ var pluginsCols = []columnInfo{ {name: "LOAD_OPTION", tp: mysql.TypeVarchar, size: 64}, } -// See https://dev.mysql.com/doc/refman/5.7/en/partitions-table.html +// See https://dev.mysql.com/doc/refman/5.7/en/information-schema-partitions-table.html var partitionsCols = []columnInfo{ {name: "TABLE_CATALOG", tp: mysql.TypeVarchar, size: 512}, {name: "TABLE_SCHEMA", tp: mysql.TypeVarchar, size: 64}, @@ -562,7 +560,6 @@ var partitionsCols = []columnInfo{ {name: "TABLESPACE_NAME", tp: mysql.TypeVarchar, size: 64}, {name: "TIDB_PARTITION_ID", tp: mysql.TypeLonglong, size: 21}, {name: "TIDB_PLACEMENT_POLICY_NAME", tp: mysql.TypeVarchar, size: 64}, - {name: "TIDB_DIRECT_PLACEMENT", tp: mysql.TypeVarchar, size: 1024}, } var tableConstraintsCols = []columnInfo{ @@ -797,7 +794,7 @@ var tableTiDBIndexesCols = []columnInfo{ {name: "SEQ_IN_INDEX", tp: mysql.TypeLonglong, size: 21}, {name: "COLUMN_NAME", tp: mysql.TypeVarchar, size: 64}, {name: "SUB_PART", tp: mysql.TypeLonglong, size: 21}, - {name: "INDEX_COMMENT", tp: mysql.TypeVarchar, size: 2048}, + {name: "INDEX_COMMENT", tp: mysql.TypeVarchar, size: 1024}, {name: "Expression", tp: mysql.TypeVarchar, size: 64}, {name: "INDEX_ID", tp: mysql.TypeLonglong, size: 21}, {name: "IS_VISIBLE", tp: mysql.TypeVarchar, size: 64}, @@ -872,6 +869,7 @@ var slowQueryCols = []columnInfo{ {name: variable.SlowLogIsWriteCacheTable, tp: mysql.TypeTiny, size: 1}, {name: variable.SlowLogPlanFromCache, tp: mysql.TypeTiny, size: 1}, {name: variable.SlowLogPlanFromBinding, tp: mysql.TypeTiny, size: 1}, + {name: variable.SlowLogHasMoreResults, tp: mysql.TypeTiny, size: 1}, {name: variable.SlowLogPlan, tp: mysql.TypeLongBlob, size: types.UnspecifiedLength}, {name: variable.SlowLogPlanDigest, tp: mysql.TypeVarchar, size: 128}, {name: variable.SlowLogPrevStmt, tp: mysql.TypeLongBlob, size: types.UnspecifiedLength}, @@ -939,11 +937,14 @@ var tableAnalyzeStatusCols = []columnInfo{ {name: "TABLE_SCHEMA", tp: mysql.TypeVarchar, size: 64}, {name: "TABLE_NAME", tp: mysql.TypeVarchar, size: 64}, {name: "PARTITION_NAME", tp: mysql.TypeVarchar, size: 64}, - {name: "JOB_INFO", tp: mysql.TypeVarchar, size: 64}, - {name: "PROCESSED_ROWS", tp: mysql.TypeLonglong, size: 20, flag: mysql.UnsignedFlag}, + {name: "JOB_INFO", tp: mysql.TypeVarchar, size: types.UnspecifiedLength}, + {name: "PROCESSED_ROWS", tp: mysql.TypeLonglong, size: 64, flag: mysql.UnsignedFlag}, {name: "START_TIME", tp: mysql.TypeDatetime}, {name: "END_TIME", tp: mysql.TypeDatetime}, {name: "STATE", tp: mysql.TypeVarchar, size: 64}, + {name: "FAIL_REASON", tp: mysql.TypeVarchar, size: types.UnspecifiedLength}, + {name: "INSTANCE", tp: mysql.TypeVarchar, size: 64}, + {name: "PROCESS_ID", tp: mysql.TypeLonglong, size: 64, flag: mysql.UnsignedFlag}, } // TableTiKVRegionStatusCols is TiKV region status mem table columns. @@ -994,7 +995,7 @@ var tableClusterConfigCols = []columnInfo{ {name: "TYPE", tp: mysql.TypeVarchar, size: 64}, {name: "INSTANCE", tp: mysql.TypeVarchar, size: 64}, {name: "KEY", tp: mysql.TypeVarchar, size: 256}, - {name: "VALUE", tp: mysql.TypeVarchar, size: 128}, + {name: "VALUE", tp: mysql.TypeLongBlob, size: types.UnspecifiedLength}, } var tableClusterLogCols = []columnInfo{ @@ -1163,6 +1164,7 @@ var tableDDLJobsCols = []columnInfo{ {name: "SCHEMA_ID", tp: mysql.TypeLonglong, size: 21}, {name: "TABLE_ID", tp: mysql.TypeLonglong, size: 21}, {name: "ROW_COUNT", tp: mysql.TypeLonglong, size: 21}, + {name: "CREATE_TIME", tp: mysql.TypeDatetime, size: 19}, {name: "START_TIME", tp: mysql.TypeDatetime, size: 19}, {name: "END_TIME", tp: mysql.TypeDatetime, size: 19}, {name: "STATE", tp: mysql.TypeVarchar, size: 64}, @@ -1451,22 +1453,19 @@ var tableAttributesCols = []columnInfo{ {name: "RANGES", tp: mysql.TypeBlob, size: types.UnspecifiedLength}, } -var tablePlacementRulesCols = []columnInfo{ +var tablePlacementPoliciesCols = []columnInfo{ {name: "POLICY_ID", tp: mysql.TypeLonglong, size: 64, flag: mysql.NotNullFlag}, {name: "CATALOG_NAME", tp: mysql.TypeVarchar, size: 512, flag: mysql.NotNullFlag}, - {name: "POLICY_NAME", tp: mysql.TypeVarchar, size: 64}, // Catalog wide policy - {name: "SCHEMA_NAME", tp: mysql.TypeVarchar, size: 64}, // System policy does not have a schema - {name: "TABLE_NAME", tp: mysql.TypeVarchar, size: 64}, // Schema level rules does not have a table - {name: "PARTITION_NAME", tp: mysql.TypeVarchar, size: 64}, // Table level rules does not have a partition - {name: "PRIMARY_REGION", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "REGIONS", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "LEADER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "FOLLOWER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "LEARNER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024, flag: mysql.NotNullFlag}, - {name: "SCHEDULE", tp: mysql.TypeVarchar, size: 20, flag: mysql.NotNullFlag}, // EVEN or MAJORITY_IN_PRIMARY - {name: "FOLLOWERS", tp: mysql.TypeLonglong, size: 64, flag: mysql.NotNullFlag}, - {name: "LEARNERS", tp: mysql.TypeLonglong, size: 64, flag: mysql.NotNullFlag}, + {name: "POLICY_NAME", tp: mysql.TypeVarchar, size: 64, flag: mysql.NotNullFlag}, // Catalog wide policy + {name: "PRIMARY_REGION", tp: mysql.TypeVarchar, size: 1024}, + {name: "REGIONS", tp: mysql.TypeVarchar, size: 1024}, + {name: "CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024}, + {name: "LEADER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024}, + {name: "FOLLOWER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024}, + {name: "LEARNER_CONSTRAINTS", tp: mysql.TypeVarchar, size: 1024}, + {name: "SCHEDULE", tp: mysql.TypeVarchar, size: 20}, // EVEN or MAJORITY_IN_PRIMARY + {name: "FOLLOWERS", tp: mysql.TypeLonglong, size: 64}, + {name: "LEARNERS", tp: mysql.TypeLonglong, size: 64}, } // GetShardingInfo returns a nil or description string for the sharding information of given TableInfo. @@ -1501,6 +1500,8 @@ const ( PrimaryConstraint = "PRIMARY" // UniqueKeyType is the string constant of UNIQUE. UniqueKeyType = "UNIQUE" + // ForeignKeyType is the string constant of Foreign Key. + ForeignKeyType = "FOREIGN KEY" ) // ServerInfo represents the basic server information of single cluster component @@ -1710,7 +1711,7 @@ func GetStoreServerInfo(ctx sessionctx.Context) ([]ServerInfo, error) { if err != nil { return nil, errors.Trace(err) } - var servers []ServerInfo + servers := make([]ServerInfo, 0, len(stores)) for _, store := range stores { failpoint.Inject("mockStoreTombstone", func(val failpoint.Value) { if val.(bool) { @@ -1838,7 +1839,7 @@ var tableNameToColumns = map[string][]columnInfo{ TableDeadlocks: tableDeadlocksCols, TableDataLockWaits: tableDataLockWaitsCols, TableAttributes: tableAttributesCols, - TablePlacementRules: tablePlacementRulesCols, + TablePlacementPolicies: tablePlacementPoliciesCols, } func createInfoSchemaTable(_ autoid.Allocators, meta *model.TableInfo) (table.Table, error) { diff --git a/infoschema/tables_serial_test.go b/infoschema/tables_test.go similarity index 90% rename from infoschema/tables_serial_test.go rename to infoschema/tables_test.go index 71aee026f6afd..56c3389a97580 100644 --- a/infoschema/tables_serial_test.go +++ b/infoschema/tables_test.go @@ -38,10 +38,10 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/session/txninfo" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testutil" "github.com/stretchr/testify/require" ) @@ -113,6 +113,8 @@ func TestInfoSchemaFieldValue(t *testing.T) { tk.MustExec("create table t ( s set('a','bc','def','ghij') default NULL, e1 enum('a', 'ab', 'cdef'), s2 SET('1','2','3','4','1585','ONE','TWO','Y','N','THREE'))") tk.MustQuery("select column_name, character_maximum_length from information_schema.columns where table_schema=Database() and table_name = 't' and column_name = 's'").Check( testkit.Rows("s 13")) + tk.MustQuery("select column_name, character_maximum_length from information_schema.columns where table_schema=Database() and table_name = 't' and column_name = 'S'").Check( + testkit.Rows("s 13")) tk.MustQuery("select column_name, character_maximum_length from information_schema.columns where table_schema=Database() and table_name = 't' and column_name = 's2'").Check( testkit.Rows("s2 30")) tk.MustQuery("select column_name, character_maximum_length from information_schema.columns where table_schema=Database() and table_name = 't' and column_name = 'e1'").Check( @@ -315,6 +317,16 @@ func (sm *mockSessionManager) UpdateTLSConfig(_ *tls.Config) {} func (sm *mockSessionManager) ServerID() uint64 { return 1 } +func (sm *mockSessionManager) StoreInternalSession(se interface{}) { +} + +func (sm *mockSessionManager) DeleteInternalSession(se interface{}) { +} + +func (sm *mockSessionManager) GetInternalSessionStartTSList() []uint64 { + return nil +} + func TestSomeTables(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -556,13 +568,13 @@ func TestSlowQuery(t *testing.T) { tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", slowLogFileName)) tk.MustExec("set time_zone = '+08:00';") re := tk.MustQuery("select * from information_schema.slow_query") - re.Check(testutil.RowsWithSep("|", "2019-02-12 19:33:56.571953|406315658548871171|root|localhost|6|57|0.12|4.895492|0.4|0.2|0.000000003|2|0.000000002|0.00000001|0.000000003|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.3824278|0.161|0.101|0.092|1.71|1|100001|100000|100|10|10|10|100|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|65536|0|0|0|0|10||0|1|0|0|1|0|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;", - "2021-09-08|14:39:54.506967|427578666238083075|root|172.16.0.0|40507|0|0|25.571605962|0.002923536|0.006800973|0.002100764|0|0|0|0.000015801|25.542014572|0|0.002294647|0.000605473|12.483|[tikvRPC regionMiss tikvRPC regionMiss regionMiss]|0|0|624|172064|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|rtdb||0|124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc||0|0|0||0|0|0||856544|0|86.635049185|0.015486658|100.054|0|0||0|1|0|0|0|0||||INSERT INTO ...;", + re.Check(testkit.RowsWithSep("|", "2019-02-12 19:33:56.571953|406315658548871171|root|localhost|6|57|0.12|4.895492|0.4|0.2|0.000000003|2|0.000000002|0.00000001|0.000000003|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.3824278|0.161|0.101|0.092|1.71|1|100001|100000|100|10|10|10|100|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|65536|0|0|0|0|10||0|1|0|0|1|0|0|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;", + "2021-09-08|14:39:54.506967|427578666238083075|root|172.16.0.0|40507|0|0|25.571605962|0.002923536|0.006800973|0.002100764|0|0|0|0.000015801|25.542014572|0|0.002294647|0.000605473|12.483|[tikvRPC regionMiss tikvRPC regionMiss regionMiss]|0|0|624|172064|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|rtdb||0|124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc||0|0|0||0|0|0||856544|0|86.635049185|0.015486658|100.054|0|0||0|1|0|0|0|0|0||||INSERT INTO ...;", )) tk.MustExec("set time_zone = '+00:00';") re = tk.MustQuery("select * from information_schema.slow_query") - re.Check(testutil.RowsWithSep("|", "2019-02-12 11:33:56.571953|406315658548871171|root|localhost|6|57|0.12|4.895492|0.4|0.2|0.000000003|2|0.000000002|0.00000001|0.000000003|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.3824278|0.161|0.101|0.092|1.71|1|100001|100000|100|10|10|10|100|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|65536|0|0|0|0|10||0|1|0|0|1|0|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;", - "2021-09-08|06:39:54.506967|427578666238083075|root|172.16.0.0|40507|0|0|25.571605962|0.002923536|0.006800973|0.002100764|0|0|0|0.000015801|25.542014572|0|0.002294647|0.000605473|12.483|[tikvRPC regionMiss tikvRPC regionMiss regionMiss]|0|0|624|172064|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|rtdb||0|124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc||0|0|0||0|0|0||856544|0|86.635049185|0.015486658|100.054|0|0||0|1|0|0|0|0||||INSERT INTO ...;", + re.Check(testkit.RowsWithSep("|", "2019-02-12 11:33:56.571953|406315658548871171|root|localhost|6|57|0.12|4.895492|0.4|0.2|0.000000003|2|0.000000002|0.00000001|0.000000003|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.3824278|0.161|0.101|0.092|1.71|1|100001|100000|100|10|10|10|100|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|65536|0|0|0|0|10||0|1|0|0|1|0|0|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;", + "2021-09-08|06:39:54.506967|427578666238083075|root|172.16.0.0|40507|0|0|25.571605962|0.002923536|0.006800973|0.002100764|0|0|0|0.000015801|25.542014572|0|0.002294647|0.000605473|12.483|[tikvRPC regionMiss tikvRPC regionMiss regionMiss]|0|0|624|172064|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|rtdb||0|124acb3a0bec903176baca5f9da00b4e7512a41c93b417923f26502edeb324cc||0|0|0||0|0|0||856544|0|86.635049185|0.015486658|100.054|0|0||0|1|0|0|0|0|0||||INSERT INTO ...;", )) // Test for long query. @@ -593,6 +605,35 @@ func TestColumnStatistics(t *testing.T) { tk.MustQuery("select * from information_schema.column_statistics").Check(testkit.Rows()) } +func TestTableIfHasColumn(t *testing.T) { + columnName := variable.SlowLogHasMoreResults + store, clean := testkit.CreateMockStore(t) + defer clean() + slowLogFileName := "tidb-slow.log" + f, err := os.OpenFile(slowLogFileName, os.O_CREATE|os.O_WRONLY, 0644) + require.NoError(t, err) + _, err = f.Write([]byte(`# Time: 2019-02-12T19:33:56.571953+08:00 +# Txn_start_ts: 406315658548871171 +# User@Host: root[root] @ localhost [127.0.0.1] +# Has_more_results: true +INSERT INTO ...; +`)) + require.NoError(t, f.Close()) + require.NoError(t, err) + defer func() { require.NoError(t, os.Remove(slowLogFileName)) }() + tk := testkit.NewTestKit(t, store) + + //check schema + tk.MustQuery(`select COUNT(*) from information_schema.columns +WHERE table_name = 'slow_query' and column_name = '` + columnName + `'`). + Check(testkit.Rows("1")) + + //check select + tk.MustQuery(`select ` + columnName + + ` from information_schema.slow_query`).Check(testkit.Rows("1")) + +} + func TestReloadDropDatabase(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -697,7 +738,7 @@ func TestFormatVersion(t *testing.T) { } } -// Test statements_summary. +// TestStmtSummaryTable Test statements_summary. func TestStmtSummaryTable(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -713,9 +754,7 @@ func TestStmtSummaryTable(t *testing.T) { tk.MustExec("create table t(a int, b varchar(10), key k(a))") // Clear all statements. - tk.MustExec("set session tidb_enable_stmt_summary = 0") - tk.MustExec("set session tidb_enable_stmt_summary = ''") - + tk.MustExec("set global tidb_enable_stmt_summary = 0") tk.MustExec("set global tidb_enable_stmt_summary = 1") tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) @@ -781,12 +820,13 @@ func TestStmtSummaryTable(t *testing.T) { defer func() { require.NoError(t, failpoint.Disable(failpointName)) }() tk.MustQuery("select * from t where a=2") + // sum_cop_task_num is always 0 if tidb_enable_collect_execution_info disabled sql = "select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys, " + "max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions, " + "max_prewrite_regions, avg_affected_rows, query_sample_text, plan " + "from information_schema.statements_summary " + "where digest_text like 'select * from `t`%'" - tk.MustQuery(sql).Check(testkit.Rows("Select test test.t t:k 1 2 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + + tk.MustQuery(sql).Check(testkit.Rows("Select test test.t t:k 1 0 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + "\tIndexLookUp_10 \troot \t100 \t\n" + "\t├─IndexRangeScan_8\tcop[tikv]\t100 \ttable:t, index:k(a), range:[2,2], keep order:false, stats:pseudo\n" + "\t└─TableRowIDScan_9\tcop[tikv]\t100 \ttable:t, keep order:false, stats:pseudo")) @@ -808,16 +848,14 @@ func TestStmtSummaryTable(t *testing.T) { "from information_schema.statements_summary " + "where digest_text like 'select * from `t`%'" tk.MustQuery(sql).Check(testkit.Rows( - "Select test test.t t:k 2 4 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + + "Select test test.t t:k 2 0 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + "\tIndexLookUp_10 \troot \t100 \t\n" + "\t├─IndexRangeScan_8\tcop[tikv]\t100 \ttable:t, index:k(a), range:[2,2], keep order:false, stats:pseudo\n" + "\t└─TableRowIDScan_9\tcop[tikv]\t100 \ttable:t, keep order:false, stats:pseudo")) // Disable it again. tk.MustExec("set global tidb_enable_stmt_summary = false") - tk.MustExec("set session tidb_enable_stmt_summary = false") defer tk.MustExec("set global tidb_enable_stmt_summary = 1") - defer tk.MustExec("set session tidb_enable_stmt_summary = ''") tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("0")) // Create a new session to test @@ -833,8 +871,7 @@ func TestStmtSummaryTable(t *testing.T) { from information_schema.statements_summary`, ).Check(testkit.Rows()) - // Enable it in session scope. - tk.MustExec("set session tidb_enable_stmt_summary = on") + tk.MustExec("SET GLOBAL tidb_enable_stmt_summary = on") // It should work immediately. tk.MustExec("begin") tk.MustExec("insert into t values(1, 'a')") @@ -858,7 +895,7 @@ func TestStmtSummaryTable(t *testing.T) { "max_prewrite_regions, avg_affected_rows, query_sample_text, plan " + "from information_schema.statements_summary " + "where digest_text like 'select * from `t`%'" - tk.MustQuery(sql).Check(testkit.Rows("Select test test.t t:k 1 2 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + + tk.MustQuery(sql).Check(testkit.Rows("Select test test.t t:k 1 0 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + "\tIndexLookUp_10 \troot \t1000 \t\n" + "\t├─IndexRangeScan_8\tcop[tikv]\t1000 \ttable:t, index:k(a), range:[2,2], keep order:false, stats:pseudo\n" + "\t└─TableRowIDScan_9\tcop[tikv]\t1000 \ttable:t, keep order:false, stats:pseudo")) @@ -869,23 +906,6 @@ func TestStmtSummaryTable(t *testing.T) { // Create a new session to test. tk = newTestKitWithRoot(t, store) - tk.MustQuery("select * from t where a=2") - - // Statement summary is still enabled. - sql = "select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys, " + - "max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions, " + - "max_prewrite_regions, avg_affected_rows, query_sample_text, plan " + - "from information_schema.statements_summary " + - "where digest_text like 'select * from `t`%'" - tk.MustQuery(sql).Check(testkit.Rows("Select test test.t t:k 2 4 0 0 0 0 0 0 0 0 0 select * from t where a=2 \tid \ttask \testRows\toperator info\n" + - "\tIndexLookUp_10 \troot \t1000 \t\n" + - "\t├─IndexRangeScan_8\tcop[tikv]\t1000 \ttable:t, index:k(a), range:[2,2], keep order:false, stats:pseudo\n" + - "\t└─TableRowIDScan_9\tcop[tikv]\t1000 \ttable:t, keep order:false, stats:pseudo")) - - // Unset session variable. - tk.MustExec("set session tidb_enable_stmt_summary = ''") - tk.MustQuery("select * from t where a=2") - // Statement summary is disabled. tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, sum_cop_task_num, avg_total_keys, max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions, @@ -954,6 +974,62 @@ func TestStmtSummaryTablePrivilege(t *testing.T) { require.Equal(t, 2, len(result.Rows())) } +func TestCapturePrivilege(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := newTestKitWithRoot(t, store) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10), key k(a))") + defer tk.MustExec("drop table if exists t") + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(a int, b varchar(10), key k(a))") + defer tk.MustExec("drop table if exists t1") + + // Disable refreshing summary. + tk.MustExec("set global tidb_stmt_summary_refresh_interval = 999999999") + tk.MustQuery("select @@global.tidb_stmt_summary_refresh_interval").Check(testkit.Rows("999999999")) + // Clear all statements. + tk.MustExec("set global tidb_enable_stmt_summary = 0") + tk.MustExec("set global tidb_enable_stmt_summary = 1") + + // Create a new user to test statements summary table privilege + tk.MustExec("drop user if exists 'test_user'@'localhost'") + tk.MustExec("create user 'test_user'@'localhost'") + defer tk.MustExec("drop user if exists 'test_user'@'localhost'") + tk.MustExec("grant select on test.t1 to 'test_user'@'localhost'") + tk.MustExec("select * from t where a=1") + tk.MustExec("select * from t where a=1") + tk.MustExec("admin capture bindings") + rows := tk.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk1.Session().Auth(&auth.UserIdentity{ + Username: "test_user", + Hostname: "localhost", + AuthUsername: "test_user", + AuthHostname: "localhost", + }, nil, nil) + + rows = tk1.MustQuery("show global bindings").Rows() + // Ordinary users can not see others' records + require.Len(t, rows, 0) + tk1.MustExec("select * from t1 where b=1") + tk1.MustExec("select * from t1 where b=1") + tk1.MustExec("admin capture bindings") + rows = tk1.MustQuery("show global bindings").Rows() + require.Len(t, rows, 1) + + tk.MustExec("grant all on *.* to 'test_user'@'localhost'") + tk1.MustExec("admin capture bindings") + rows = tk1.MustQuery("show global bindings").Rows() + require.Len(t, rows, 2) +} + func TestIssue18845(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -969,7 +1045,7 @@ func TestIssue18845(t *testing.T) { tk.MustQuery(`select count(*) from information_schema.columns;`) } -// Test statements_summary_history. +// TestStmtSummaryInternalQuery Test statements_summary_history. func TestStmtSummaryInternalQuery(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1028,7 +1104,7 @@ func TestStmtSummaryInternalQuery(t *testing.T) { require.Contains(t, rows[0][0].(string), "Projection") } -// Test error count and warning count. +// TestStmtSummaryErrorCount Test error count and warning count. func TestStmtSummaryErrorCount(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1099,7 +1175,7 @@ func TestStmtSummarySensitiveQuery(t *testing.T) { )) } -// test stmtSummaryEvictedCount +// TestSimpleStmtSummaryEvictedCount test stmtSummaryEvictedCount func TestSimpleStmtSummaryEvictedCount(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -1462,3 +1538,16 @@ func TestReferentialConstraints(t *testing.T) { tk.MustQuery(`SELECT * FROM information_schema.referential_constraints WHERE table_name='t2'`).Check(testkit.Rows("def referconstraints fk_to_t1 def referconstraints PRIMARY NONE NO ACTION NO ACTION t2 t1")) } + +// TestTableConstraintsContainForeignKeys TiDB Issue: https://github.com/pingcap/tidb/issues/28918 +func TestTableConstraintsContainForeignKeys(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("CREATE DATABASE tableconstraints") + tk.MustExec("use tableconstraints") + tk.MustExec("CREATE TABLE `t1` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(25) DEFAULT NULL, PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("CREATE TABLE `t2` (`id` int(11) NOT NULL AUTO_INCREMENT, `t1_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, CONSTRAINT `fk_t2_t1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustQuery("SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_schema = 'tableconstraints' AND table_name = 't2'").Sort().Check(testkit.Rows("def tableconstraints PRIMARY tableconstraints t2 PRIMARY KEY", "def tableconstraints fk_t2_t1 tableconstraints t2 FOREIGN KEY")) + tk.MustQuery("SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_schema = 'tableconstraints' AND table_name = 't1'").Sort().Check(testkit.Rows("def tableconstraints PRIMARY tableconstraints t1 PRIMARY KEY")) +} diff --git a/kv/checker.go b/kv/checker.go index 0d7ca24b8a5b9..7ee5447e21249 100644 --- a/kv/checker.go +++ b/kv/checker.go @@ -41,7 +41,7 @@ func (d RequestTypeSupportedChecker) supportExpr(exprType tipb.ExprType) bool { switch exprType { case tipb.ExprType_Null, tipb.ExprType_Int64, tipb.ExprType_Uint64, tipb.ExprType_String, tipb.ExprType_Bytes, tipb.ExprType_MysqlDuration, tipb.ExprType_MysqlTime, tipb.ExprType_MysqlDecimal, - tipb.ExprType_Float32, tipb.ExprType_Float64, tipb.ExprType_ColumnRef, tipb.ExprType_MysqlEnum: + tipb.ExprType_Float32, tipb.ExprType_Float64, tipb.ExprType_ColumnRef, tipb.ExprType_MysqlEnum, tipb.ExprType_MysqlBit: return true // aggregate functions. // NOTE: tipb.ExprType_GroupConcat is only supported by TiFlash, So checking it for TiKV case outside. diff --git a/kv/error.go b/kv/error.go index f6ad87eb4cdf1..9a6878d57cebd 100644 --- a/kv/error.go +++ b/kv/error.go @@ -54,6 +54,8 @@ var ( pmysql.Message(mysql.MySQLErrName[mysql.ErrWriteConflictInTiDB].Raw+" "+TxnRetryableMark, nil)) // ErrLockExpire is the error when the lock is expired. ErrLockExpire = dbterror.ClassTiKV.NewStd(mysql.ErrLockExpire) + // ErrAssertionFailed is the error when an assertion fails. + ErrAssertionFailed = dbterror.ClassTiKV.NewStd(mysql.ErrAssertionFailed) ) // IsTxnRetryableError checks if the error could safely retry the transaction. diff --git a/kv/fault_injection_test.go b/kv/fault_injection_test.go index c8743284c9a8c..3412b5b717d92 100644 --- a/kv/fault_injection_test.go +++ b/kv/fault_injection_test.go @@ -33,10 +33,10 @@ func TestFaultInjectionBasic(t *testing.T) { storage := NewInjectedStore(newMockStorage(), &cfg) txn, err := storage.Begin() - require.Nil(t, err) + require.NoError(t, err) _, err = storage.Begin(tikv.WithTxnScope(GlobalTxnScope), tikv.WithStartTS(0)) - require.Nil(t, err) + require.NoError(t, err) ver := Version{Ver: 1} snap := storage.GetSnapshot(ver) diff --git a/kv/interface_mock_test.go b/kv/interface_mock_test.go index 2542e6f7e5b55..26f9acf1d6cfb 100644 --- a/kv/interface_mock_test.go +++ b/kv/interface_mock_test.go @@ -30,6 +30,10 @@ type mockTxn struct { valid bool } +func (t *mockTxn) SetAssertion(_ []byte, _ ...FlagsOp) error { + return nil +} + // Commit always returns a retryable error. func (t *mockTxn) Commit(ctx context.Context) error { return ErrTxnRetryable diff --git a/kv/key_test.go b/kv/key_test.go index 96b4fd2d8dfb4..3d3ee3ce5fb1a 100644 --- a/kv/key_test.go +++ b/kv/key_test.go @@ -22,7 +22,7 @@ import ( . "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/sessionctx/stmtctx" - "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/stretchr/testify/assert" @@ -33,13 +33,13 @@ func TestPartialNext(t *testing.T) { sc := &stmtctx.StatementContext{TimeZone: time.Local} // keyA represents a multi column index. keyA, err := codec.EncodeValue(sc, nil, types.NewDatum("abc"), types.NewDatum("def")) - require.Nil(t, err) + require.NoError(t, err) keyB, err := codec.EncodeValue(sc, nil, types.NewDatum("abca"), types.NewDatum("def")) - require.Nil(t, err) + require.NoError(t, err) // We only use first column value to seek. seekKey, err := codec.EncodeValue(sc, nil, types.NewDatum("abc")) - require.Nil(t, err) + require.NoError(t, err) nextKey := Key(seekKey).Next() cmp := bytes.Compare(nextKey, keyA) @@ -125,7 +125,7 @@ func TestHandle(t *testing.T) { assert.Equal(t, -1, ih.Compare(ih2)) assert.Equal(t, "100", ih.String()) - ch := testkit.MustNewCommonHandle(t, 100, "abc") + ch := testutil.MustNewCommonHandle(t, 100, "abc") assert.False(t, ch.IsInt()) ch2 := ch.Next() @@ -174,7 +174,7 @@ func TestHandleMap(t *testing.T) { assert.False(t, ok) assert.Nil(t, v) - ch := testkit.MustNewCommonHandle(t, 100, "abc") + ch := testutil.MustNewCommonHandle(t, 100, "abc") m.Set(ch, "a") v, ok = m.Get(ch) assert.True(t, ok) @@ -186,9 +186,9 @@ func TestHandleMap(t *testing.T) { assert.Nil(t, v) m.Set(ch, "a") - ch2 := testkit.MustNewCommonHandle(t, 101, "abc") + ch2 := testutil.MustNewCommonHandle(t, 101, "abc") m.Set(ch2, "b") - ch3 := testkit.MustNewCommonHandle(t, 99, "def") + ch3 := testutil.MustNewCommonHandle(t, 99, "def") m.Set(ch3, "c") assert.Equal(t, 3, m.Len()) diff --git a/kv/keyflags.go b/kv/keyflags.go index 66f94380c7a50..27f8472cf4779 100644 --- a/kv/keyflags.go +++ b/kv/keyflags.go @@ -20,6 +20,17 @@ type KeyFlags uint8 const ( flagPresumeKNE KeyFlags = 1 << iota flagNeedLocked + + // The following are assertion related flags. + // There are four choices of the two bits: + // * 0: Assertion is not set and can be set later. + // * flagAssertExists: We assert the key exists. + // * flagAssertNotExists: We assert the key doesn't exist. + // * flagAssertExists | flagAssertNotExists: Assertion cannot be made on this key (unknown). + // Once either (or both) of the two flags is set, we say assertion is set (`HasAssertionFlags` becomes true), and + // it's expected to be unchangeable within the current transaction. + flagAssertExists + flagAssertNotExists ) // HasPresumeKeyNotExists returns whether the associated key use lazy check. @@ -32,6 +43,26 @@ func (f KeyFlags) HasNeedLocked() bool { return f&flagNeedLocked != 0 } +// HasAssertExists returns whether the key is asserted to already exist before the current transaction. +func (f KeyFlags) HasAssertExists() bool { + return f&flagAssertExists != 0 && f&flagAssertNotExists == 0 +} + +// HasAssertNotExists returns whether the key is asserted not to exist before the current transaction. +func (f KeyFlags) HasAssertNotExists() bool { + return f&flagAssertNotExists != 0 && f&flagAssertExists == 0 +} + +// HasAssertUnknown returns whether the key is unable to do any assertion. +func (f KeyFlags) HasAssertUnknown() bool { + return f&flagAssertExists != 0 && f&flagAssertNotExists != 0 +} + +// HasAssertionFlags returns whether assertion is set on this key. +func (f KeyFlags) HasAssertionFlags() bool { + return f&flagAssertExists != 0 || f&flagAssertNotExists != 0 +} + // FlagsOp describes KeyFlags modify operation. type FlagsOp uint16 @@ -40,6 +71,14 @@ const ( SetPresumeKeyNotExists FlagsOp = iota // SetNeedLocked marks the associated key need to be acquired lock. SetNeedLocked + // SetAssertExist marks the associated key must exist. + SetAssertExist + // SetAssertNotExist marks the associated key must not exists. + SetAssertNotExist + // SetAssertUnknown marks the associated key is unknown and can not apply other assertion. + SetAssertUnknown + // SetAssertNone marks the associated key without any assert. + SetAssertNone ) // ApplyFlagsOps applys flagspos to origin. @@ -50,6 +89,15 @@ func ApplyFlagsOps(origin KeyFlags, ops ...FlagsOp) KeyFlags { origin |= flagPresumeKNE case SetNeedLocked: origin |= flagNeedLocked + case SetAssertExist: + origin |= flagAssertExists + origin &= ^flagAssertNotExists + case SetAssertNotExist: + origin |= flagAssertNotExists + origin &= ^flagAssertExists + case SetAssertUnknown: + origin |= flagAssertExists + origin |= flagAssertNotExists } } return origin diff --git a/kv/kv.go b/kv/kv.go index 0e83f3daee8a0..58aecb5195891 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -31,6 +31,7 @@ import ( "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/tikvrpc" + pd "github.com/tikv/pd/client" ) // UnCommitIndexKVFlag uses to indicate the index key/value is no need to commit. @@ -182,6 +183,7 @@ type LockCtx = tikvstore.LockCtx // This is not thread safe. type Transaction interface { RetrieverMutator + AssertionProto // Size returns sum of keys and values length. Size() int // Len returns the number of entries in the DB. @@ -235,15 +237,31 @@ type Transaction interface { ClearDiskFullOpt() } +// AssertionProto is an interface defined for the assertion protocol. +type AssertionProto interface { + // SetAssertion sets an assertion for an operation on the key. + // TODO: Use a special type instead of `FlagsOp`. Otherwise there's risk that the assertion flag is incorrectly used + // in other places like `MemBuffer.SetWithFlags`. + SetAssertion(key []byte, assertion ...FlagsOp) error +} + // Client is used to send request to KV layer. type Client interface { // Send sends request to KV layer, returns a Response. - Send(ctx context.Context, req *Request, vars interface{}, sessionMemTracker *memory.Tracker, enabledRateLimitAction bool, eventCb trxevents.EventCallback) Response + Send(ctx context.Context, req *Request, vars interface{}, option *ClientSendOption) Response // IsRequestTypeSupported checks if reqType and subType is supported. IsRequestTypeSupported(reqType, subType int64) bool } +// ClientSendOption wraps options during Client Send +type ClientSendOption struct { + SessionMemTracker *memory.Tracker + EnabledRateLimitAction bool + EventCb trxevents.EventCallback + EnableCollectExecutionInfo bool +} + // ReqTypes. const ( ReqTypeSelect = 101 @@ -295,6 +313,9 @@ type Request struct { Data []byte KeyRanges []KeyRange + // For PartitionTableScan used by tiflash. + PartitionIDAndRanges []PartitionIDAndRanges + // Concurrency is 1, if it only sends the request to a single storage unit when // ResponseIterator.Next is called. If concurrency is greater than 1, the request will be // sent to multiple storage units concurrently. @@ -311,8 +332,6 @@ type Request struct { Desc bool // NotFillCache makes this request do not touch the LRU cache of the underlying storage. NotFillCache bool - // SyncLog decides whether the WAL(write-ahead log) of this request should be synchronized. - SyncLog bool // Streaming indicates using streaming API for this request, result in that one Next() // call would not corresponds to a whole region result. Streaming bool @@ -342,6 +361,12 @@ type Request struct { Paging bool } +// PartitionIDAndRanges used by PartitionTableScan in tiflash. +type PartitionIDAndRanges struct { + ID int64 + KeyRanges []KeyRange +} + const ( // GlobalReplicaScope indicates the default replica scope for tidb to request GlobalReplicaScope = oracle.GlobalTxnScope @@ -447,6 +472,11 @@ type EtcdBackend interface { StartGCWorker() error } +// StorageWithPD is used to get pd client. +type StorageWithPD interface { + GetPDClient() pd.Client +} + // FnKeyCmp is the function for iterator the keys type FnKeyCmp func(key Key) bool @@ -481,4 +511,6 @@ const ( SI IsoLevel = iota // RC stands for 'read committed'. RC + // RCCheckTS stands for 'read consistency read with ts check'. + RCCheckTS ) diff --git a/kv/main_test.go b/kv/main_test.go index e87d9dd2a9916..9a4d9e0891574 100644 --- a/kv/main_test.go +++ b/kv/main_test.go @@ -22,10 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/kv/mpp.go b/kv/mpp.go index 8d2754eb4f239..012a182aacd1a 100644 --- a/kv/mpp.go +++ b/kv/mpp.go @@ -33,6 +33,8 @@ type MPPTask struct { ID int64 // mppTaskID StartTs uint64 TableID int64 // physical table id + + PartitionTableIDs []int64 } // ToPB generates the pb structure. @@ -81,7 +83,7 @@ type MPPClient interface { ConstructMPPTasks(context.Context, *MPPBuildTasksRequest, map[string]time.Time, time.Duration) ([]MPPTaskMeta, error) // DispatchMPPTasks dispatches ALL mpp requests at once, and returns an iterator that transfers the data. - DispatchMPPTasks(ctx context.Context, vars interface{}, reqs []*MPPDispatchRequest, needTriggerFallback bool) Response + DispatchMPPTasks(ctx context.Context, vars interface{}, reqs []*MPPDispatchRequest, needTriggerFallback bool, startTs uint64) Response } // MPPBuildTasksRequest request the stores allocation for a mpp plan fragment. @@ -89,4 +91,6 @@ type MPPClient interface { type MPPBuildTasksRequest struct { KeyRanges []KeyRange StartTS uint64 + + PartitionIDAndRanges []PartitionIDAndRanges } diff --git a/kv/option.go b/kv/option.go index 2a7a17fedcb6c..56a2e58e9196e 100644 --- a/kv/option.go +++ b/kv/option.go @@ -26,7 +26,7 @@ const ( Priority // NotFillCache makes this request do not touch the LRU cache of the underlying storage. NotFillCache - // SyncLog decides whether the WAL(write-ahead log) of this request should be synchronized. + // SyncLog is not used anymore. SyncLog // KeyOnly retrieve only keys, it can be used in scan now. KeyOnly @@ -68,12 +68,19 @@ const ( ResourceGroupTagger // KVFilter indicates the filter to ignore key-values in the transaction's memory buffer. KVFilter - // SnapInterceptor is used for setting the interceptor for snapshot SnapInterceptor // CommitTSUpperBoundChec is used by cached table // The commitTS must be greater than all the write lock lease of the visited cached table. CommitTSUpperBoundCheck + // RPCInterceptor is interceptor.RPCInterceptor on Transaction or Snapshot, used to decorate + // additional logic before and after the underlying client-go RPC request. + RPCInterceptor + // TableToColumnMaps is a map from tableID to a series of maps. The maps are needed when checking data consistency. + // Save them here to reduce redundant computations. + TableToColumnMaps + // AssertionLevel controls how strict the assertions on data during transactions should be. + AssertionLevel ) // ReplicaReadType is the type of replica to read data from diff --git a/kv/txn.go b/kv/txn.go index 7701dcd870b06..dd51b7a2e56fe 100644 --- a/kv/txn.go +++ b/kv/txn.go @@ -17,16 +17,88 @@ package kv import ( "context" "errors" + "fmt" "math" "math/rand" + "sync" "time" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/util/logutil" + "github.com/tikv/client-go/v2/oracle" "go.uber.org/zap" ) +const ( + // TimeToPrintLongTimeInternalTxn is the duration if the internal transaction lasts more than it, + // TiDB prints a log message. + TimeToPrintLongTimeInternalTxn = time.Minute * 5 +) + +var globalInnerTxnTsBox = innerTxnStartTsBox{ + innerTSLock: sync.Mutex{}, + innerTxnStartTsMap: make(map[uint64]struct{}, 256), +} + +type innerTxnStartTsBox struct { + innerTSLock sync.Mutex + innerTxnStartTsMap map[uint64]struct{} +} + +func (ib *innerTxnStartTsBox) storeInnerTxnTS(startTS uint64) { + ib.innerTSLock.Lock() + ib.innerTxnStartTsMap[startTS] = struct{}{} + ib.innerTSLock.Unlock() + +} + +func (ib *innerTxnStartTsBox) deleteInnerTxnTS(startTS uint64) { + ib.innerTSLock.Lock() + delete(ib.innerTxnStartTsMap, startTS) + ib.innerTSLock.Unlock() +} + +// GetMinInnerTxnStartTS get the min StartTS between startTSLowerLimit and curMinStartTS in globalInnerTxnTsBox. +func GetMinInnerTxnStartTS(now time.Time, startTSLowerLimit uint64, + curMinStartTS uint64) uint64 { + return globalInnerTxnTsBox.getMinStartTS(now, startTSLowerLimit, curMinStartTS) +} + +func (ib *innerTxnStartTsBox) getMinStartTS(now time.Time, startTSLowerLimit uint64, + curMinStartTS uint64) uint64 { + minStartTS := curMinStartTS + ib.innerTSLock.Lock() + for innerTS := range ib.innerTxnStartTsMap { + PrintLongTimeInternalTxn(now, innerTS, true) + if innerTS > startTSLowerLimit && innerTS < minStartTS { + minStartTS = innerTS + } + } + ib.innerTSLock.Unlock() + return minStartTS +} + +// PrintLongTimeInternalTxn print the internal transaction information. +// runByFunction true means the transaction is run by `RunInNewTxn`, +// false means the transaction is run by internal session. +func PrintLongTimeInternalTxn(now time.Time, startTS uint64, runByFunction bool) { + if startTS > 0 { + innerTxnStartTime := oracle.GetTimeFromTS(startTS) + if now.Sub(innerTxnStartTime) > TimeToPrintLongTimeInternalTxn { + callerName := "internal session" + if runByFunction { + callerName = "RunInNewTxn" + } + infoHeader := fmt.Sprintf("An internal transaction running by %s lasts long time", callerName) + + logutil.BgLogger().Info(infoHeader, + zap.Duration("time", now.Sub(innerTxnStartTime)), zap.Uint64("startTS", startTS), + zap.Time("start time", innerTxnStartTime)) + } + } +} + // RunInNewTxn will run the f in a new transaction environment. func RunInNewTxn(ctx context.Context, store Storage, retryable bool, f func(ctx context.Context, txn Transaction) error) error { var ( @@ -34,6 +106,11 @@ func RunInNewTxn(ctx context.Context, store Storage, retryable bool, f func(ctx originalTxnTS uint64 txn Transaction ) + + defer func() { + globalInnerTxnTsBox.deleteInnerTxnTS(originalTxnTS) + }() + for i := uint(0); i < maxRetryCnt; i++ { txn, err = store.Begin() if err != nil { @@ -44,6 +121,7 @@ func RunInNewTxn(ctx context.Context, store Storage, retryable bool, f func(ctx // originalTxnTS is used to trace the original transaction when the function is retryable. if i == 0 { originalTxnTS = txn.StartTS() + globalInnerTxnTsBox.storeInnerTxnTS(originalTxnTS) } err = f(ctx, txn) diff --git a/kv/txn_test.go b/kv/txn_test.go index 84f5430c2e6d0..22fc61a482042 100644 --- a/kv/txn_test.go +++ b/kv/txn_test.go @@ -21,6 +21,8 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" ) func TestBackOff(t *testing.T) { @@ -65,3 +67,40 @@ func TestRetryExceedCountError(t *testing.T) { }) assert.NotNil(t, err) } + +func TestInnerTxnStartTsBox(t *testing.T) { + // case1: store and delete + globalInnerTxnTsBox.storeInnerTxnTS(5) + _, ok := globalInnerTxnTsBox.innerTxnStartTsMap[5] + assert.Equal(t, true, ok) + + globalInnerTxnTsBox.deleteInnerTxnTS(5) + _, ok = globalInnerTxnTsBox.innerTxnStartTsMap[5] + assert.Equal(t, false, ok) + + // case2: test for GetMinInnerTxnStartTS + tm0 := time.Date(2022, time.March, 8, 12, 10, 01, 0, time.UTC) + ts0 := oracle.GoTimeToTS(tm0) + tm1 := time.Date(2022, time.March, 10, 12, 10, 01, 0, time.UTC) + ts1 := oracle.GoTimeToTS(tm1) + tm2 := time.Date(2022, time.March, 10, 12, 14, 03, 0, time.UTC) + ts2 := oracle.GoTimeToTS(tm2) + tm3 := time.Date(2022, time.March, 10, 12, 14, 05, 0, time.UTC) + ts3 := oracle.GoTimeToTS(tm3) + tm4 := time.Date(2022, time.March, 10, 12, 15, 0, 0, time.UTC) + lowLimit := oracle.GoTimeToLowerLimitStartTS(tm4, 24*60*60*1000) + minStartTS := oracle.GoTimeToTS(tm4) + + globalInnerTxnTsBox.storeInnerTxnTS(ts0) + globalInnerTxnTsBox.storeInnerTxnTS(ts1) + globalInnerTxnTsBox.storeInnerTxnTS(ts2) + globalInnerTxnTsBox.storeInnerTxnTS(ts3) + + newMinStartTS := GetMinInnerTxnStartTS(tm4, lowLimit, minStartTS) + require.Equal(t, newMinStartTS, ts1) + + globalInnerTxnTsBox.deleteInnerTxnTS(ts0) + globalInnerTxnTsBox.deleteInnerTxnTS(ts1) + globalInnerTxnTsBox.deleteInnerTxnTS(ts2) + globalInnerTxnTsBox.deleteInnerTxnTS(ts3) +} diff --git a/meta/autoid/autoid_test.go b/meta/autoid/autoid_test.go index 16cfc7c64ac1c..e529764918eff 100644 --- a/meta/autoid/autoid_test.go +++ b/meta/autoid/autoid_test.go @@ -30,6 +30,7 @@ import ( "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) @@ -426,7 +427,7 @@ func TestConcurrentAlloc(t *testing.T) { require.NoError(t, err) var mu sync.Mutex - wg := sync.WaitGroup{} + var wg util.WaitGroupWrapper m := map[int64]struct{}{} count := 10 errCh := make(chan error, count) @@ -476,12 +477,11 @@ func TestConcurrentAlloc(t *testing.T) { } } for i := 0; i < count; i++ { - wg.Add(1) - go func(num int) { - defer wg.Done() + num := 1 + wg.Run(func() { time.Sleep(time.Duration(num%10) * time.Microsecond) allocIDs() - }(i) + }) } wg.Wait() diff --git a/meta/autoid/main_test.go b/meta/autoid/main_test.go index a5e8e915db0db..509401d81b105 100644 --- a/meta/autoid/main_test.go +++ b/meta/autoid/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/meta/autoid/seq_autoid_test.go b/meta/autoid/seq_autoid_test.go index c34ce2232b3d8..80568edd1c8ee 100644 --- a/meta/autoid/seq_autoid_test.go +++ b/meta/autoid/seq_autoid_test.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) @@ -193,7 +194,7 @@ func TestConcurrentAllocSequence(t *testing.T) { require.NoError(t, err) var mu sync.Mutex - wg := sync.WaitGroup{} + var wg util.WaitGroupWrapper m := map[int64]struct{}{} count := 10 errCh := make(chan error, count) @@ -226,12 +227,11 @@ func TestConcurrentAllocSequence(t *testing.T) { } } for i := 0; i < count; i++ { - wg.Add(1) - go func(num int) { + num := i + wg.Run(func() { time.Sleep(time.Duration(num%10) * time.Microsecond) allocSequence() - wg.Done() - }(i) + }) } wg.Wait() diff --git a/meta/main_test.go b/meta/main_test.go index 858d4bbb6f6e6..2b58b89851eae 100644 --- a/meta/main_test.go +++ b/meta/main_test.go @@ -22,10 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), } goleak.VerifyTestMain(m, opts...) } diff --git a/meta/meta.go b/meta/meta.go index 24ac94733d5fe..591457252ac10 100644 --- a/meta/meta.go +++ b/meta/meta.go @@ -121,7 +121,6 @@ type Meta struct { // If the current Meta needs to handle a job, jobListKey is the type of the job's list. func NewMeta(txn kv.Transaction, jobListKeys ...JobListKeyType) *Meta { txn.SetOption(kv.Priority, kv.PriorityHigh) - txn.SetOption(kv.SyncLog, struct{}{}) txn.SetDiskFullOpt(kvrpcpb.DiskFullOpt_AllowedOnAlmostFull) t := structure.NewStructure(txn, txn, mMetaPrefix) listKey := DefaultJobListKey @@ -165,6 +164,14 @@ func (m *Meta) GenGlobalIDs(n int) ([]int64, error) { return ids, nil } +// GenPlacementPolicyID generates next placement policy id globally. +func (m *Meta) GenPlacementPolicyID() (int64, error) { + policyIDMutex.Lock() + defer policyIDMutex.Unlock() + + return m.txn.Inc(mPolicyGlobalID, 1) +} + // GetGlobalID gets current global id. func (m *Meta) GetGlobalID() (int64, error) { return m.txn.GetInt64(mNextGlobalIDKey) @@ -284,22 +291,15 @@ func (m *Meta) checkTableNotExists(dbKey []byte, tableKey []byte) error { // CreatePolicy creates a policy. func (m *Meta) CreatePolicy(policy *model.PolicyInfo) error { - if policy.ID != 0 { - policyKey := m.policyKey(policy.ID) - if err := m.checkPolicyNotExists(policyKey); err != nil { - return errors.Trace(err) - } - } else { - // Autofill the policy ID. - policyIDMutex.Lock() - genID, err := m.txn.Inc(mPolicyGlobalID, 1) - if err != nil { - return errors.Trace(err) - } - policyIDMutex.Unlock() - policy.ID = genID + if policy.ID == 0 { + return errors.New("policy.ID is invalid") } + policyKey := m.policyKey(policy.ID) + if err := m.checkPolicyNotExists(policyKey); err != nil { + return errors.Trace(err) + } + data, err := json.Marshal(policy) if err != nil { return errors.Trace(err) @@ -918,6 +918,11 @@ func (m *Meta) GetAllHistoryDDLJobs() ([]*model.Job, error) { return jobs, nil } +// GetHistoryDDLCount the count of all history DDL jobs. +func (m *Meta) GetHistoryDDLCount() (uint64, error) { + return m.txn.HGetLen(mDDLJobHistoryKey) +} + // GetLastNHistoryDDLJobs gets latest N history ddl jobs. func (m *Meta) GetLastNHistoryDDLJobs(num int) ([]*model.Job, error) { pairs, err := m.txn.HGetLastN(mDDLJobHistoryKey, num) @@ -1004,7 +1009,7 @@ func (m *Meta) GetBootstrapVersion() (int64, error) { // FinishBootstrap finishes bootstrap. func (m *Meta) FinishBootstrap(version int64) error { - err := m.txn.Set(mBootstrapKey, []byte(fmt.Sprintf("%d", version))) + err := m.txn.Set(mBootstrapKey, []byte(strconv.FormatInt(version, 10))) return errors.Trace(err) } diff --git a/meta/meta_test.go b/meta/meta_test.go index 29441e3e39c52..cbafd64404163 100644 --- a/meta/meta_test.go +++ b/meta/meta_test.go @@ -19,7 +19,6 @@ import ( "fmt" "math" "strconv" - "sync" "testing" "time" @@ -28,7 +27,8 @@ import ( "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) @@ -49,6 +49,7 @@ func TestPlacementPolicy(t *testing.T) { // test the meta storage of placemnt policy. policy := &model.PolicyInfo{ + ID: 1, Name: model.NewCIStr("aa"), PlacementSettings: &model.PlacementSettings{ PrimaryRegion: "my primary", @@ -171,22 +172,18 @@ func TestMeta(t *testing.T) { require.NoError(t, err) require.Equal(t, int64(1), n) - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + var wg util.WaitGroupWrapper + wg.Run(func() { ids, err := m.GenGlobalIDs(3) require.NoError(t, err) anyMatch(t, ids, []int64{2, 3, 4}, []int64{6, 7, 8}) - }() + }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Run(func() { ids, err := m.GenGlobalIDs(4) require.NoError(t, err) anyMatch(t, ids, []int64{5, 6, 7, 8}, []int64{2, 3, 4, 5}) - }() + }) wg.Wait() n, err = m.GetSchemaVersion() @@ -457,8 +454,8 @@ func TestDDL(t *testing.T) { }, { "kv.CommonHandle", - testkit.MustNewCommonHandle(t, "abc", 1222, "string"), - testkit.MustNewCommonHandle(t, "dddd", 1222, "string"), + testutil.MustNewCommonHandle(t, "abc", 1222, "string"), + testutil.MustNewCommonHandle(t, "dddd", 1222, "string"), }, } diff --git a/metrics/distsql.go b/metrics/distsql.go index 9bec9d7646827..3a4527da510ae 100644 --- a/metrics/distsql.go +++ b/metrics/distsql.go @@ -27,7 +27,7 @@ var ( Name: "handle_query_duration_seconds", Help: "Bucketed histogram of processing time (s) of handled queries.", Buckets: prometheus.ExponentialBuckets(0.0005, 2, 29), // 0.5ms ~ 1.5days - }, []string{LblType, LblSQLType}) + }, []string{LblType, LblSQLType, LblCoprType}) DistSQLScanKeysPartialHistogram = prometheus.NewHistogram( prometheus.HistogramOpts{ diff --git a/metrics/gc_worker.go b/metrics/gc_worker.go index ad20286d5817d..7c136401ede6e 100644 --- a/metrics/gc_worker.go +++ b/metrics/gc_worker.go @@ -16,6 +16,7 @@ package metrics import ( "github.com/prometheus/client_golang/prometheus" + "github.com/tikv/client-go/v2/metrics" ) // Metrics for the GC worker. @@ -69,11 +70,9 @@ var ( Help: "Counter of gc scan lock request more than once in the same region.", }) - GCUnsafeDestroyRangeFailuresCounterVec = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: "tidb", - Subsystem: "tikvclient", - Name: "gc_unsafe_destroy_range_failures", - Help: "Counter of unsafe destroyrange failures", - }, []string{"type"}) + GCUnsafeDestroyRangeFailuresCounterVec *prometheus.CounterVec ) + +func init() { + GCUnsafeDestroyRangeFailuresCounterVec = metrics.TiKVUnsafeDestroyRangeFailuresCounterVec +} diff --git a/metrics/grafana/README.md b/metrics/grafana/README.md new file mode 100644 index 0000000000000..e6419bce9dca1 --- /dev/null +++ b/metrics/grafana/README.md @@ -0,0 +1,14 @@ +## About + +Use [jsonnet](https://github.com/google/go-jsonnet) to generate Grafana-compliant json scripts for use with TiDB. + +Why jsonnet? + +1. jsonnet is a DSL created by Google for json, which is good for advanced json editing work. +2. Grafana provides the [jsonnet library](https://grafana.github.io/grafonnet-lib/) specifically for generating Grafana json, which makes maintaining TiDB's json scripts much easier. + +## Usage + +1. Modify the jsonnet files (e.g. tidb_summary.jsonnet). +2. Run `generate_json.sh` to generate the json files by the jsonnet files. +3. Commit the modifications. diff --git a/metrics/grafana/generate_json.sh b/metrics/grafana/generate_json.sh new file mode 100755 index 0000000000000..7739382813610 --- /dev/null +++ b/metrics/grafana/generate_json.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Copyright 2022 PingCAP, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +go install github.com/google/go-jsonnet/cmd/jsonnet@latest +git clone https://github.com/grafana/grafonnet-lib.git + +export JSONNET_PATH=grafonnet-lib +jsonnet tidb_summary.jsonnet > tidb_summary.json +rm -rf $JSONNET_PATH + diff --git a/metrics/grafana/overview.json b/metrics/grafana/overview.json index ebbfb72ea361c..4017ff43a8126 100644 --- a/metrics/grafana/overview.json +++ b/metrics/grafana/overview.json @@ -153,91 +153,91 @@ ], "targets": [ { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tidb\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tidb\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiDB", "refId": "A" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"pd\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"pd\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "PD", "refId": "B" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tikv\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tikv\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiKV", "refId": "C" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tiflash\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tiflash\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiFlash", "refId": "D" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"pump\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"pump\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Pump", "refId": "E" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"drainer\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"drainer\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Drainer", "refId": "F" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"kafka\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"kafka\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Kafka", "refId": "G" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"zookeeper\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"zookeeper\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Zookeeper", "refId": "H" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"node_exporter\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"node_exporter\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Node_exporter", "refId": "I" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"blackbox_exporter\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"blackbox_exporter\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Blackbox_exporter", "refId": "J" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"grafana\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"grafana\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Grafana", "refId": "K" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", job=\"blackbox_exporter_http\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"blackbox_exporter_http\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Pushgateway", "refId": "L" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"kafka_exporter\"} == 1)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"kafka_exporter\"} == 1)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Kafka_exporter", @@ -331,91 +331,91 @@ ], "targets": [ { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tidb\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tidb\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiDB", "refId": "A" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"pd\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"pd\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "PD", "refId": "B" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tikv\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tikv\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiKV", "refId": "C" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"tiflash\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"tiflash\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "TiFlash", "refId": "D" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"pump\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"pump\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Pump", "refId": "E" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"drainer\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"drainer\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Drainer", "refId": "F" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"kafka\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"kafka\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Kafka", "refId": "G" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"zookeeper\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"zookeeper\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Zookeeper", "refId": "H" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"node_exporter\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"node_exporter\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Node_exporter", "refId": "I" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"blackbox_exporter\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"blackbox_exporter\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Blackbox_exporter", "refId": "J" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"grafana\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"grafana\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Grafana", "refId": "K" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", job=\"blackbox_exporter_http\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"blackbox_exporter_http\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Pushgateway", "refId": "L" }, { - "expr": "\ncount(probe_success{tidb_cluster=\"$tidb_cluster\", group=\"kafka_exporter\"} == 0)", + "expr": "\ncount(probe_success{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", group=\"kafka_exporter\"} == 0)", "format": "time_series", "intervalFactor": 2, "legendFormat": "Kafka_exporter", @@ -497,7 +497,7 @@ "tableColumn": "", "targets": [ { - "expr": "pd_tso_role{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", dc=\"global\"}", + "expr": "pd_tso_role{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", dc=\"global\"}", "format": "time_series", "instant": true, "intervalFactor": 2, @@ -594,7 +594,7 @@ "tableColumn": "", "targets": [ { - "expr": "pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"storage_capacity\"}", + "expr": "pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"storage_capacity\"}", "format": "time_series", "intervalFactor": 2, "refId": "A", @@ -679,7 +679,7 @@ "tableColumn": "", "targets": [ { - "expr": "pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"storage_size\"}", + "expr": "pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"storage_size\"}", "intervalFactor": 2, "refId": "A", "step": 60 @@ -759,7 +759,7 @@ "tableColumn": "", "targets": [ { - "expr": "pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"leader_count\"}", + "expr": "pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"leader_count\"}", "intervalFactor": 2, "refId": "A", "step": 60 @@ -839,7 +839,7 @@ "tableColumn": "", "targets": [ { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_up_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_up_count\"})", "format": "time_series", "interval": "15s", "intervalFactor": 2, @@ -912,7 +912,7 @@ ], "targets": [ { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_disconnected_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_disconnected_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "Disconnect Stores", @@ -920,7 +920,7 @@ "step": 20 }, { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_unhealth_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_unhealth_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "Unhealth Stores", @@ -928,7 +928,7 @@ "step": 20 }, { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_low_space_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_low_space_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "LowSpace Stores", @@ -936,7 +936,7 @@ "step": 20 }, { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_down_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_down_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "Down Stores", @@ -944,7 +944,7 @@ "step": 20 }, { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_offline_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_offline_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "Offline Stores", @@ -952,7 +952,7 @@ "step": 20 }, { - "expr": "sum(pd_cluster_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_tombstone_count\"})", + "expr": "sum(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"store_tombstone_count\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "Tombstone Stores", @@ -1012,7 +1012,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\"}[5m])) by (grpc_method, le))", + "expr": "histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\"}[5m])) by (grpc_method, le))", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -1106,7 +1106,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.98, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (type, le))", + "expr": "histogram_quantile(0.98, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (type, le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-98%", @@ -1114,7 +1114,7 @@ "step": 10 }, { - "expr": "avg(rate(pd_client_request_handle_requests_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[30s])) by (type) / avg(rate(pd_client_request_handle_requests_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[30s])) by (type)", + "expr": "avg(rate(pd_client_request_handle_requests_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (type) / avg(rate(pd_client_request_handle_requests_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (type)", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -1204,14 +1204,14 @@ "steppedLine": false, "targets": [ { - "expr": "pd_regions_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\"}", + "expr": "pd_regions_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", "refId": "A" }, { - "expr": "sum(pd_regions_status{tidb_cluster=\"$tidb_cluster\"}) by (instance, type)", + "expr": "sum(pd_regions_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (instance, type)", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -1302,7 +1302,7 @@ "steppedLine": false, "targets": [ { - "expr": "pd_hotspot_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"hot_write_region_as_leader\"}", + "expr": "pd_hotspot_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"hot_write_region_as_leader\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "store-{{store}}", @@ -1393,7 +1393,7 @@ "steppedLine": false, "targets": [ { - "expr": "pd_hotspot_status{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"hot_read_region_as_leader\"}", + "expr": "pd_hotspot_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\",type=\"hot_read_region_as_leader\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "store-{{store}}", @@ -1483,7 +1483,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(delta(pd_scheduler_region_heartbeat{tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"report\", status=\"ok\"}[1m])) by (store)", + "expr": "sum(delta(pd_scheduler_region_heartbeat{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=\"$instance\", type=\"report\", status=\"ok\"}[1m])) by (store)", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -1575,7 +1575,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(pd_scheduler_region_heartbeat_latency_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[5m])) by (store, le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_scheduler_region_heartbeat_latency_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[5m])) by (store, le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "store-{{store}}", @@ -1686,7 +1686,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_executor_statement_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -1775,7 +1775,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -1783,7 +1783,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 3, "legendFormat": "99", @@ -1791,14 +1791,14 @@ "step": 15 }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95", "refId": "C" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -1887,7 +1887,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} {{type}} {{result}}", @@ -1977,7 +1977,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_server_execute_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(increase(tidb_server_execute_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": " {{type}}", @@ -2073,7 +2073,7 @@ "steppedLine": true, "targets": [ { - "expr": "tidb_server_connections{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2081,7 +2081,7 @@ "step": 10 }, { - "expr": "sum(tidb_server_connections{tidb_cluster=\"$tidb_cluster\"})", + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "total", @@ -2172,7 +2172,7 @@ "steppedLine": false, "targets": [ { - "expr": "process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "process-{{instance}}", @@ -2180,7 +2180,7 @@ "step": 10 }, { - "expr": "go_memstats_heap_inuse_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_inuse_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "legendFormat": "HeapInuse-{{instance}}", "format": "time_series", "intervalFactor": 2, @@ -2266,7 +2266,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -2351,21 +2351,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "A" }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -2454,7 +2454,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -2545,7 +2545,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -2633,7 +2633,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "cmd", @@ -2641,7 +2641,7 @@ "step": 10 }, { - "expr": "sum(rate(pd_client_request_handle_requests_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "expr": "sum(rate(pd_client_request_handle_requests_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "request", @@ -2731,7 +2731,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -2739,14 +2739,14 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", @@ -2836,7 +2836,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_region_err_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_region_err_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -2927,7 +2927,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_lock_resolver_actions_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_lock_resolver_actions_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -3022,7 +3022,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_domain_load_schema_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_domain_load_schema_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3114,7 +3114,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_backoff_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_backoff_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -3226,7 +3226,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", type=\"leader\"}) by (instance)", + "expr": "sum(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"leader\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3235,7 +3235,7 @@ "step": 10 }, { - "expr": "delta(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", type=\"leader\"}[30s]) < -10", + "expr": "delta(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"leader\"}[30s]) < -10", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -3329,7 +3329,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_raftstore_region_count{tidb_cluster=\"$tidb_cluster\", type=\"region\"}) by (instance)", + "expr": "sum(tikv_raftstore_region_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"region\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3419,7 +3419,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", job=\"tikv\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tikv\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3506,7 +3506,7 @@ "steppedLine": false, "targets": [ { - "expr": "avg(process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tikv\"}) by (instance)", + "expr": "avg(process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tikv\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3595,7 +3595,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_engine_size_bytes{tidb_cluster=\"$tidb_cluster\"}) by (instance)", + "expr": "sum(tikv_engine_size_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3684,7 +3684,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_engine_size_bytes{tidb_cluster=\"$tidb_cluster\"}) by (type)", + "expr": "sum(tikv_engine_size_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -3778,7 +3778,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_channel_full_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance, type)", + "expr": "sum(rate(tikv_channel_full_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance, type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{type}}", @@ -3877,7 +3877,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_server_report_failure_msg_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type,instance,store_id)", + "expr": "sum(rate(tikv_server_report_failure_msg_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type,instance,store_id)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{type}} - to - {{store_id}}", @@ -3968,7 +3968,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tikv_scheduler_contex_total{tidb_cluster=\"$tidb_cluster\"}) by (instance)", + "expr": "sum(tikv_scheduler_contex_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4058,7 +4058,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_coprocessor_executor_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tikv_coprocessor_executor_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -4149,7 +4149,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,req))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-99%", @@ -4157,7 +4157,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.95, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,req))", + "expr": "histogram_quantile(0.95, sum(rate(tikv_coprocessor_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,req))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{req}}-95%", @@ -4165,7 +4165,7 @@ "step": 10 }, { - "expr": " sum(rate(tikv_coprocessor_request_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\", req=\"select\"}[1m])) / sum(rate(tikv_coprocessor_request_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", req=\"select\"}[1m]))", + "expr": " sum(rate(tikv_coprocessor_request_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", req=\"select\"}[1m])) / sum(rate(tikv_coprocessor_request_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", req=\"select\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "select-avg", @@ -4173,7 +4173,7 @@ "step": 10 }, { - "expr": " sum(rate(tikv_coprocessor_request_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\", req=\"index\"}[1m])) / sum(rate(tikv_coprocessor_request_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", req=\"index\"}[1m]))", + "expr": " sum(rate(tikv_coprocessor_request_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", req=\"index\"}[1m])) / sum(rate(tikv_coprocessor_request_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", req=\"index\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "index-avg", @@ -4262,7 +4262,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", name=~\"raftstore_.*\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", name=~\"raftstore_.*\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4352,7 +4352,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tikv_thread_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", name=~\"cop_.*\"}[1m])) by (instance)", + "expr": "sum(rate(tikv_thread_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", name=~\"cop_.*\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4491,7 +4491,7 @@ ], "targets": [ { - "expr": "count(node_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", mode=\"user\"}) by (instance)", + "expr": "count(node_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", mode=\"user\"}) by (instance)", "format": "table", "instant": true, "intervalFactor": 2, @@ -4603,7 +4603,7 @@ ], "targets": [ { - "expr": "node_memory_MemTotal_bytes{tidb_cluster=\"$tidb_cluster\"}", + "expr": "node_memory_MemTotal_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "table", "instant": true, "intervalFactor": 2, @@ -4657,7 +4657,7 @@ "steppedLine": false, "targets": [ { - "expr": "100 - avg by (instance) (irate(node_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", mode=\"idle\"}[1m]) ) * 100", + "expr": "100 - avg by (instance) (irate(node_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", mode=\"idle\"}[1m]) ) * 100", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4747,7 +4747,7 @@ "steppedLine": false, "targets": [ { - "expr": "node_load1{tidb_cluster=\"$tidb_cluster\"}", + "expr": "node_load1{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4834,7 +4834,7 @@ "steppedLine": false, "targets": [ { - "expr": "node_memory_MemAvailable_bytes{tidb_cluster=\"$tidb_cluster\"}", + "expr": "node_memory_MemAvailable_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{ instance }}", @@ -4922,14 +4922,14 @@ "steppedLine": false, "targets": [ { - "expr": "irate(node_network_receive_bytes_total{tidb_cluster=\"$tidb_cluster\", device!=\"lo\"}[5m])", + "expr": "irate(node_network_receive_bytes_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", device!=\"lo\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "Inbound: {{instance}}-{{device}}", "refId": "A" }, { - "expr": "irate(node_network_transmit_bytes_total{tidb_cluster=\"$tidb_cluster\", device!=\"lo\"}[5m])", + "expr": "irate(node_network_transmit_bytes_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", device!=\"lo\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "Outbound: {{instance}}-{{device}}", @@ -5018,7 +5018,7 @@ "steppedLine": false, "targets": [ { - "expr": "irate(node_netstat_Tcp_RetransSegs{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "irate(node_netstat_Tcp_RetransSegs{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - TCPSlowStartRetrans", @@ -5108,7 +5108,7 @@ "steppedLine": false, "targets": [ { - "expr": "irate(node_disk_io_time_seconds_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "irate(node_disk_io_time_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} - {{device}}", @@ -5169,6 +5169,26 @@ "tags": [], "templating": { "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [], + "query": "label_values(pd_cluster_status, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, { "allValue": null, "current": {}, @@ -5179,7 +5199,7 @@ "multi": false, "name": "tidb_cluster", "options": [], - "query": "label_values(pd_cluster_status, tidb_cluster)", + "query": "label_values(pd_cluster_status{k8s_cluster=\"$k8s_cluster\"}, tidb_cluster)", "refresh": 2, "regex": "", "sort": 1, @@ -5200,7 +5220,7 @@ "multi": false, "name": "instance", "options": [], - "query": "label_values(pd_cluster_status{tidb_cluster=\"$tidb_cluster\"}, instance)", + "query": "label_values(pd_cluster_status{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}, instance)", "refresh": 1, "regex": "", "skipUrlSync": false, diff --git a/metrics/grafana/performance_overview.json b/metrics/grafana/performance_overview.json new file mode 100644 index 0000000000000..c7cbbe216abb3 --- /dev/null +++ b/metrics/grafana/performance_overview.json @@ -0,0 +1,2859 @@ +{ + "__inputs": [ + { + "name": "DS_TEST-CLUSTER", + "label": "test-cluster", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.1.6" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "${DS_TEST-CLUSTER}", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 1, + "id": null, + "iteration": 1577357354898, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": "${DS_TEST-CLUSTER}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 138, + "panels": [], + "title": "Performance Overview", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "Service Time Per Second, show service time distribution among different components and execution phase.\n1. Total Database Time, the time which tidb cluster is processing application requests.\n2. Per SQL Type dimension\n3. Per parse/compile/execute dimension\n4. Per KV/PD request dimension", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 187, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "database time", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_tikvclient_request_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (type)", + "hide": false, + "interval": "", + "legendFormat": "kv_request - {{type}}", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "tso_wait", + "refId": "C" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_session_parse_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "sql - parse", + "refId": "D" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_session_compile_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "sql - compile", + "refId": "E" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_session_execute_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "sql - execute", + "refId": "F" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (sql_type)", + "hide": false, + "interval": "", + "legendFormat": "sql_type - {{sql_type}}", + "refId": "G" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Database Time Overview", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3528", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3529", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "TiDB statement statistics. Bold red line on right Y axis for Failed Queries per second", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 179, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:1069", + "alias": "Failed", + "color": "#C4162A", + "linewidth": 2, + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "Total", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_server_execute_error_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) ", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Failed", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "QPS", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:822", + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:823", + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "TiDB command total statistics including both successful and failed ones", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 178, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPS By Type", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "TiDB plan cache hit total.", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 91, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_server_plan_cache_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "avg", + "refId": "A", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Queries Using Plan Cache OPS", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3416", + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3417", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "kv/tso request total by command type", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 180, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_tikvclient_request_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_tikvclient_request_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "kv request total", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "tso - cmd", + "refId": "C" + }, + { + "exemplar": true, + "expr": "sum(rate(pd_client_request_handle_requests_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "tso - request", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "KV/TSO Request OPS", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "TiDB current connection counts", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 188, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "tidb_server_connections{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"})", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "total", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "active connections", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connection Count", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3472", + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3473", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "- avg: average cpu usage for all instance.\n- delta: max(cpu utilization) - min(cpu utilization)\n- max: max(cpu utilization)", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 181, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "avg(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",job=\"tidb\"}[1m]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "max(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",job=\"tidb\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "max", + "refId": "C" + }, + { + "exemplar": true, + "expr": "(max(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[1m])) - min(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "delta", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TiDB CPU", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:188", + "decimals": null, + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:189", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "#### CPU: CPU usage for all instance.\n- CPU-Avg: average cpu usage for all instance.\n- CPU-Delta: max(cpu utilization) - min(cpu utilization)\n- CPU-Max: max(cpu utilization)\n\n#### IO MBps: The total bytes of read and write in all TiKV instances.", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 182, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:371", + "alias": "IO-Avg", + "yaxis": 2 + }, + { + "$$hashKey": "object:563", + "alias": "IO-Max", + "yaxis": 2 + }, + { + "$$hashKey": "object:576", + "alias": "IO-Delta", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "avg(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=~\".*tikv\"}[1m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "CPU-Avg", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "max(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=~\".*tikv\"}[1m]))", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU-Max", + "refId": "C" + }, + { + "exemplar": true, + "expr": "(max(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=~\".*tikv\"}[1m])) - min(rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=~\".*tikv\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "CPU-Delta", + "refId": "B" + }, + { + "exemplar": true, + "expr": "avg(sum(rate(tikv_engine_flow_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", db=\"kv\", type=~\"wal_file_bytes|bytes_read|iter_bytes_read\"}[1m])) by (instance))", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "IO-Avg", + "refId": "D" + }, + { + "exemplar": true, + "expr": "max(sum(rate(tikv_engine_flow_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", db=\"kv\", type=~\"wal_file_bytes|bytes_read|iter_bytes_read\"}[1m])) by (instance))", + "hide": false, + "interval": "", + "legendFormat": "IO-Max", + "refId": "E" + }, + { + "exemplar": true, + "expr": "max(sum(rate(tikv_engine_flow_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", db=\"kv\", type=~\"wal_file_bytes|bytes_read|iter_bytes_read\"}[1m])) by (instance)) - min(sum(rate(tikv_engine_flow_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", db=\"kv\", type=~\"wal_file_bytes|bytes_read|iter_bytes_read\"}[1m])) by (instance))", + "hide": false, + "interval": "", + "legendFormat": "IO-Delta", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TiKV CPU/IO MBps", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:208", + "decimals": null, + "format": "percentunit", + "label": "CPU (%)", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:209", + "decimals": null, + "format": "Bps", + "label": "MBps ", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB query durations", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 29 + }, + "hiddenSeries": false, + "id": 80, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m]))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "avg", + "refId": "D" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (le))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (sql_type) / sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (sql_type)", + "hide": false, + "interval": "", + "legendFormat": "avg-{{sql_type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3308", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3309", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "TiDB connection idle durations", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 29 + }, + "hiddenSeries": false, + "id": 171, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tidb_server_conn_idle_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) / sum(rate(tidb_server_conn_idle_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg-in-txn", + "refId": "C" + }, + { + "exemplar": true, + "expr": "(sum(rate(tidb_server_conn_idle_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) / sum(rate(tidb_server_conn_idle_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])))", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "avg-not-in-txn", + "refId": "A", + "step": 30 + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", + "hide": false, + "interval": "", + "legendFormat": "99-in-txn", + "refId": "B" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", + "hide": false, + "interval": "", + "legendFormat": "99-not-in-txn", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connection Idle Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3364", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:3365", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time cost of parsing SQL to AST", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "id": 156, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "95", + "refId": "B" + }, + { + "exemplar": true, + "expr": "(sum(rate(tidb_session_parse_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) / sum(rate(tidb_session_parse_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "instant": false, + "intervalFactor": 2, + "legendFormat": "99", + "refId": "D", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Parse Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1955", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1956", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "the time to build plan", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 36 + }, + "hiddenSeries": false, + "id": 170, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tidb_session_compile_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) / sum(rate(tidb_session_compile_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "D" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compile Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:283", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:284", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time cost of executing the SQL which does not include the time to get the results of the query .", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 36 + }, + "hiddenSeries": false, + "id": 169, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "95", + "refId": "B" + }, + { + "exemplar": true, + "expr": "(sum(rate(tidb_session_execute_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) / sum(rate(tidb_session_execute_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "instant": false, + "intervalFactor": 2, + "legendFormat": "99", + "refId": "A", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Execution Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2109", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2110", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "tidb avg kv request duration", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 44 + }, + "hiddenSeries": false, + "id": 172, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tidb_tikvclient_request_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (type)/ sum(rate(tidb_tikvclient_request_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (type)", + "hide": false, + "interval": "", + "legendFormat": "{{type}}", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg TiDB KV Request Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2161", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2162", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "tikv grpc avg duration", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 44 + }, + "hiddenSeries": false, + "id": 173, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tikv_grpc_msg_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (type)/ sum(rate(tikv_grpc_msg_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (type)", + "hide": false, + "interval": "", + "legendFormat": "{{type}}", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Avg TiKV GRPC Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2263", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2264", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The duration of a client starting to wait for the TS until received the TS result.", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 44 + }, + "hiddenSeries": false, + "id": 77, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(pd_client_cmd_handle_cmds_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) / sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "D" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "999", + "refId": "A", + "step": 10 + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "B" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "90", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "PD TSO Wait Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2315", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2316", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time consumed by processing asynchronous write requests.\nStorage async write duration = store duration + apply duration", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 52 + }, + "hiddenSeries": false, + "id": 185, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tikv_storage_engine_async_request_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"write\"}[1m])) / sum(rate(tikv_storage_engine_async_request_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"write\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_storage_engine_async_request_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"write\"}[30s])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Storage Async Write Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2371", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2372", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The store time duration of each request", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 52 + }, + "hiddenSeries": false, + "id": 183, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(tikv_raftstore_store_duration_secs_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tikv_raftstore_store_duration_secs_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_raftstore_store_duration_secs_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Store Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2520", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2521", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The store time duration of each request", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 52 + }, + "hiddenSeries": false, + "id": 174, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tikv_raftstore_apply_duration_secs_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tikv_raftstore_apply_duration_secs_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_raftstore_apply_duration_secs_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Apply Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2572", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2573", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time consumed when Raft appends log", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 176, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tikv_raftstore_append_log_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tikv_raftstore_append_log_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_raftstore_append_log_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Append Log Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2672", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2673", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time consumed when Raft commits log", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 60 + }, + "hiddenSeries": false, + "id": 177, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tikv_raftstore_commit_log_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tikv_raftstore_commit_log_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_raftstore_commit_log_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Commit Log Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2724", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2725", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "decimals": null, + "description": "The time consumed for Raft to apply logs", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 60 + }, + "hiddenSeries": false, + "id": 186, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "(sum(rate(tikv_raftstore_apply_log_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tikv_raftstore_apply_log_duration_seconds_count{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])))", + "hide": false, + "interval": "", + "legendFormat": "avg", + "refId": "C" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_raftstore_apply_log_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Apply Log Duration", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2776", + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:2777", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [], + "query": "label_values(pd_cluster_status, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "tidb_cluster", + "multi": false, + "name": "tidb_cluster", + "options": [], + "query": "label_values(pd_cluster_status{k8s_cluster=\"$k8s_cluster\"}, tidb_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Test-Cluster-Performance-Overview", + "uid": "eDbRZpnWa", + "version": 1 +} diff --git a/metrics/grafana/tidb.json b/metrics/grafana/tidb.json index f6606d18ef4c6..c0f3f4b771ec7 100644 --- a/metrics/grafana/tidb.json +++ b/metrics/grafana/tidb.json @@ -107,28 +107,28 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95", "refId": "C" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -225,7 +225,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (result)", + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (result)", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -234,7 +234,7 @@ "step": 60 }, { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\", result=\"OK\"}[1m] offset 1d))", + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", result=\"OK\"}[1m] offset 1d))", "format": "time_series", "hide": true, "instant": false, @@ -244,7 +244,7 @@ "step": 90 }, { - "expr": "sum(tidb_server_connections{tidb_cluster=\"$tidb_cluster\"}) * sum(rate(tidb_server_handle_query_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) * sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "hide": true, "instant": false, @@ -344,7 +344,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_executor_statement_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -352,7 +352,7 @@ "step": 30 }, { - "expr": "sum(rate(tidb_executor_statement_total{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "total", @@ -455,7 +455,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}} {{type}} {{result}}", @@ -549,7 +549,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_server_execute_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, instance)", + "expr": "sum(increase(tidb_server_execute_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": " {{type}}-{{instance}}", @@ -635,21 +635,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_process_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_process_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "all_proc_{{sql_type}}", "refId": "A" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_cop_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_cop_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "all_cop_proc_{{sql_type}}", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_wait_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_server_slow_query_wait_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "all_cop_wait_{{sql_type}}", @@ -735,7 +735,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -743,7 +743,7 @@ "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -751,7 +751,7 @@ "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -759,7 +759,7 @@ "refId": "C" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -767,7 +767,7 @@ "refId": "D" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='1'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -775,7 +775,7 @@ "refId": "E" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_conn_idle_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", in_txn='0'}[1m])) by (le,in_txn))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -862,7 +862,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{sql_type}}", @@ -948,7 +948,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{sql_type}}", @@ -1034,7 +1034,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{sql_type}}", @@ -1120,7 +1120,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le,sql_type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{sql_type}}", @@ -1226,7 +1226,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -1322,7 +1322,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{ instance }}", @@ -1417,7 +1417,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -1510,7 +1510,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -1603,7 +1603,7 @@ "steppedLine": false, "targets": [ { - "expr": "increase(tidb_server_execute_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "increase(tidb_server_execute_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}} @ {{instance}}", @@ -1694,7 +1694,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_session_restricted_sql_total{tidb_cluster=\"$tidb_cluster\"}[30s]))", + "expr": "sum(rate(tidb_session_restricted_sql_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "", @@ -1810,7 +1810,7 @@ "steppedLine": false, "targets": [ { - "expr": "(time() - process_start_time_seconds{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"})", + "expr": "(time() - process_start_time_seconds{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"})", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -1907,14 +1907,14 @@ "steppedLine": false, "targets": [ { - "expr": "process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "process-{{instance}}", "refId": "A" }, { - "expr": "go_memstats_heap_sys_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_sys_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "hide": true, "intervalFactor": 1, @@ -1922,14 +1922,14 @@ "refId": "B" }, { - "expr": "go_memstats_heap_inuse_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_inuse_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "HeapInuse-{{instance}}", "refId": "C" }, { - "expr": "go_memstats_heap_alloc_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_alloc_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "hide": true, "intervalFactor": 1, @@ -1937,7 +1937,7 @@ "refId": "D" }, { - "expr": "go_memstats_heap_idle_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_idle_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "hide": true, "intervalFactor": 1, @@ -1945,14 +1945,14 @@ "refId": "E" }, { - "expr": "go_memstats_heap_released_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_heap_released_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "hide": true, "interval": "", "legendFormat": "HeapReleased-{{instance}}", "refId": "F" }, { - "expr": "go_memstats_next_gc_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "go_memstats_next_gc_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "hide": true, "interval": "", "legendFormat": "GCTrigger-{{instance}}", @@ -2056,7 +2056,7 @@ "steppedLine": false, "targets": [ { - "expr": "irate(process_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[30s])", + "expr": "irate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[30s])", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -2065,7 +2065,7 @@ "step": 40 }, { - "expr": "tidb_server_maxprocs{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "tidb_server_maxprocs{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "legendFormat": "limit-{{instance}}", "refId": "B" } @@ -2161,7 +2161,7 @@ "steppedLine": false, "targets": [ { - "expr": "tidb_server_connections{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2169,7 +2169,7 @@ "step": 40 }, { - "expr": "sum(tidb_server_connections{tidb_cluster=\"$tidb_cluster\"})", + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "total", @@ -2259,7 +2259,7 @@ "steppedLine": false, "targets": [ { - "expr": "process_open_fds{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "expr": "process_open_fds{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2356,7 +2356,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tidb_server_disconnection_total{tidb_cluster=\"$tidb_cluster\"}) by (instance, result)", + "expr": "sum(tidb_server_disconnection_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (instance, result)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{result}}", @@ -2446,7 +2446,7 @@ "steppedLine": false, "targets": [ { - "expr": " go_goroutines{tidb_cluster=\"$tidb_cluster\", job=~\"tidb.*\"}", + "expr": " go_goroutines{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=~\"tidb.*\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2534,7 +2534,7 @@ "steppedLine": false, "targets": [ { - "expr": "increase(tidb_server_event_total{tidb_cluster=\"$tidb_cluster\"}[10m])", + "expr": "increase(tidb_server_event_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[10m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-server {{type}}", @@ -2631,7 +2631,7 @@ "steppedLine": false, "targets": [ { - "expr": "tidb_server_prepared_stmts{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_server_prepared_stmts{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2639,7 +2639,7 @@ "step": 40 }, { - "expr": "sum(tidb_server_prepared_stmts{tidb_cluster=\"$tidb_cluster\"})", + "expr": "sum(tidb_server_prepared_stmts{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "total", @@ -2729,7 +2729,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_monitor_keep_alive_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "expr": "sum(increase(tidb_monitor_keep_alive_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -2817,7 +2817,7 @@ "steppedLine": false, "targets": [ { - "expr": "increase(tidb_server_panic_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "increase(tidb_server_panic_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -2825,7 +2825,7 @@ "refId": "A" }, { - "expr": "increase(tidb_server_critical_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "increase(tidb_server_critical_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -2914,7 +2914,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_monitor_time_jump_back_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "expr": "sum(increase(tidb_monitor_time_jump_back_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3000,7 +3000,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_get_token_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_get_token_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99", @@ -3088,7 +3088,7 @@ "steppedLine": false, "targets": [ { - "expr": "tidb_server_critical_error_total{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_server_critical_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -3180,17 +3180,17 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tidb_server_packet_io_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "sum(rate(tidb_server_packet_io_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, - "legendFormat": "{{instance}}-{{type}}-rate", + "legendFormat": "{{type}}-rate", "refId": "A" }, { - "expr": "tidb_server_packet_io_bytes_sum{tidb_cluster=\"$tidb_cluster\"}", + "expr": "sum(tidb_server_packet_io_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (type)", "format": "time_series", "intervalFactor": 1, - "legendFormat": "{{instance}}-{{type}}-total", + "legendFormat": "{{type}}-total", "refId": "B" } ], @@ -3275,7 +3275,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_server_handshake_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "expr": "sum(increase(tidb_server_handshake_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -3386,7 +3386,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, txn_mode)", + "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, txn_mode)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{txn_mode}}", @@ -3480,21 +3480,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99-{{txn_mode}}", "refId": "A" }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95-{{txn_mode}}", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, txn_mode))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80-{{txn_mode}}", @@ -3720,7 +3720,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_session_retry_error_total{tidb_cluster=\"$tidb_cluster\"}[30s])) by (type, sql_type)", + "expr": "sum(rate(tidb_session_retry_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (type, sql_type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{sql_type}}", @@ -3814,21 +3814,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "A" }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_batch_executor_token_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -3923,7 +3923,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type=\"commit\"}[1m])) by (instance)", + "expr": "sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"commit\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -4017,21 +4017,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99-{{type}}", "refId": "A" }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "95-{{type}}", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80-{{type}}", @@ -4200,14 +4200,14 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tidb_tikvclient_txn_write_kv_num_sum{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tidb_tikvclient_txn_write_kv_num_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}-rate", "refId": "A" }, { - "expr": "tidb_tikvclient_txn_write_kv_num_sum{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_tikvclient_txn_write_kv_num_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}-sum", @@ -4440,7 +4440,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80-{{type}}", @@ -4448,14 +4448,14 @@ "step": 40 }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 1, "legendFormat": "95-{{type}}", "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_txn_heart_beat_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99-{{type}}", @@ -4558,7 +4558,7 @@ "steppedLine": false, "targets": [ { - "expr": "rate(tidb_tikvclient_txn_write_size_bytes_sum{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "rate(tidb_tikvclient_txn_write_size_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}-rate", @@ -4566,7 +4566,7 @@ "step": 40 }, { - "expr": "tidb_tikvclient_txn_write_size_bytes_sum{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_tikvclient_txn_write_size_bytes_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}-sum", @@ -4731,7 +4731,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -4739,14 +4739,14 @@ "step": 40 }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 1, "legendFormat": "95", "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_pessimistic_lock_keys_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99", @@ -4842,7 +4842,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_ttl_lifetime_reach_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "expr": "sum(rate(tidb_tikvclient_ttl_lifetime_reach_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}", @@ -4940,7 +4940,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_load_safepoint_total{tidb_cluster=\"$tidb_cluster\", type=\"ok\"}[1m])) by (instance)", + "expr": "sum(rate(tidb_tikvclient_load_safepoint_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"ok\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -5104,21 +5104,21 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_commit_txn_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_commit_txn_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "2PC-{{type}}", "refId": "C" }, { - "expr": "sum(rate(tidb_tikvclient_async_commit_txn_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_async_commit_txn_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "async commit-{{type}}", "refId": "A" }, { - "expr": "sum(rate(tidb_tikvclient_one_pc_txn_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_one_pc_txn_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "1PC-{{type}}", @@ -5225,7 +5225,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, rate(tidb_tikvclient_txn_commit_backoff_count_bucket{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "histogram_quantile(0.99, rate(tidb_tikvclient_txn_commit_backoff_count_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "count - {{instance}}", @@ -5233,7 +5233,7 @@ "step": 40 }, { - "expr": "histogram_quantile(0.99, rate(tidb_tikvclient_txn_commit_backoff_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "histogram_quantile(0.99, rate(tidb_tikvclient_txn_commit_backoff_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -5331,7 +5331,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_safets_update_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (result, store)", + "expr": "sum(rate(tidb_tikvclient_safets_update_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (result, store)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{result}}-store-{{store}}", @@ -5426,7 +5426,7 @@ "steppedLine": false, "targets": [ { - "expr": "tidb_tikvclient_min_safets_gap_seconds{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_tikvclient_min_safets_gap_seconds{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-store-{{store}}", @@ -5475,6 +5475,99 @@ "align": false, "alignLevel": null } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 53 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(irate(tidb_tikvclient_prewrite_assertion_count[30s])) by (type)", + "interval": "", + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Assertion", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:369", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:370", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } } ], "repeat": null, @@ -5540,7 +5633,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -5641,7 +5734,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_compile_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -5742,7 +5835,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, sql_type))", "format": "time_series", "instant": false, "intervalFactor": 2, @@ -5842,7 +5935,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_executor_expensive_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_executor_expensive_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -5940,7 +6033,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_server_plan_cache_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_server_plan_cache_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -6052,14 +6145,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999-{{type}}", "refId": "D" }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -6069,14 +6162,14 @@ "step": 4 }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90-{{type}}", "refId": "B" }, { - "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "interval": "", "intervalFactor": 2, @@ -6168,10 +6261,10 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_distsql_handle_query_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tidb_distsql_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (copr_type)", "format": "time_series", "intervalFactor": 2, - "legendFormat": "", + "legendFormat": "{{copr_type}}", "metric": "tidb_distsql_query_total", "refId": "A", "step": 4 @@ -6261,7 +6354,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_distsql_scan_keys_partial_num_count{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tidb_distsql_scan_keys_partial_num_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "", @@ -6350,21 +6443,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_distsql_scan_keys_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(1, sum(rate(tidb_distsql_scan_keys_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "100", "refId": "A" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_scan_keys_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_scan_keys_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", "refId": "B" }, { - "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_scan_keys_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_scan_keys_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "50", @@ -6450,21 +6543,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(1, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "100", "refId": "A" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_distsql_scan_keys_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "50", @@ -6550,21 +6643,21 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_distsql_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(1, sum(rate(tidb_distsql_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "100", "refId": "A" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_distsql_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", "refId": "B" }, { - "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_partial_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.50, sum(rate(tidb_distsql_partial_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "50", @@ -6657,7 +6750,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_distsql_copr_cache_sum{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_distsql_copr_cache_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -6752,7 +6845,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_cop_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_cop_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -6862,7 +6955,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_backoff_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_backoff_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -6870,14 +6963,14 @@ "step": 40 }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_backoff_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_backoff_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_backoff_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.80, sum(rate(tidb_tikvclient_backoff_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "80", @@ -6972,7 +7065,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_region_err_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_region_err_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -6981,7 +7074,7 @@ "step": 40 }, { - "expr": "sum(rate(tidb_tikvclient_region_err_total{tidb_cluster=\"$tidb_cluster\"}{EXTERNAL_LABELtype=\"server_is_busy\"}[1m]))", + "expr": "sum(rate(tidb_tikvclient_region_err_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}{EXTERNAL_LABELtype=\"server_is_busy\"}[1m]))", "format": "time_series", "hide": true, "intervalFactor": 2, @@ -7073,7 +7166,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_backoff_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_backoff_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -7166,7 +7259,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_lock_resolver_actions_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_lock_resolver_actions_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -7262,7 +7355,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_lock_cleanup_task_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_lock_cleanup_task_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "cleanup_secondary_failure_{{type}}", @@ -7271,7 +7364,7 @@ "step": 40 }, { - "expr": "sum(rate(tidb_tikvclient_load_safepoint_total{tidb_cluster=\"$tidb_cluster\", type=\"fail\"}[1m]))", + "expr": "sum(rate(tidb_tikvclient_load_safepoint_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"fail\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "load_safepoint_failure", @@ -7367,7 +7460,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_replica_selector_failure_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_replica_selector_failure_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{type}}", @@ -7474,7 +7567,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_request_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance, type)", + "expr": "sum(rate(tidb_tikvclient_request_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance, type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{type}}", @@ -7569,7 +7662,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (le, store))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (le, store))", "format": "time_series", "intervalFactor": 2, "legendFormat": "store-{{store}}", @@ -7664,7 +7757,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (le,type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", store!=\"0\"}[1m])) by (le,type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -7757,7 +7850,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_forward_request_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (from_store, to_store, result)", + "expr": "sum(rate(tidb_tikvclient_forward_request_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (from_store, to_store, result)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{from_store}}-to-{{to_store}}-{{result}}", @@ -7850,7 +7943,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_forward_request_counter{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, result)", + "expr": "sum(rate(tidb_tikvclient_forward_request_counter{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, result)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{result}}", @@ -7958,7 +8051,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type!=\"tso\"}[1m])) by (type)", + "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type!=\"tso\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -8051,7 +8144,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999-{{type}}", @@ -8059,14 +8152,14 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99-{{type}}", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_tikvclient_ts_future_wait_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type!~\"tso|tso_async_wait\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90-{{type}}", @@ -8158,7 +8251,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(pd_client_cmd_handle_failed_cmds_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(pd_client_cmd_handle_failed_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -8249,14 +8342,14 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "expr": "sum(rate(pd_client_cmd_handle_cmds_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "cmd", "refId": "C" }, { - "expr": "sum(rate(pd_client_request_handle_requests_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", + "expr": "sum(rate(pd_client_request_handle_requests_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "request", @@ -8346,7 +8439,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -8354,14 +8447,14 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", @@ -8451,7 +8544,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -8459,14 +8552,14 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", @@ -8556,7 +8649,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "999", @@ -8564,14 +8657,14 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", "refId": "B" }, { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"tso_async_wait\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", @@ -8768,7 +8861,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_domain_load_schema_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_domain_load_schema_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -8867,7 +8960,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_domain_load_schema_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance,type)", + "expr": "sum(rate(tidb_domain_load_schema_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance,type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{type}}", @@ -8964,7 +9057,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_session_schema_lease_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "expr": "sum(increase(tidb_session_schema_lease_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -9063,7 +9156,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_domain_load_privilege_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance,type)", + "expr": "sum(rate(tidb_domain_load_privilege_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance,type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{type}}", @@ -9172,12 +9265,20 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_ddl_handle_job_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_ddl_handle_job_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", "refId": "A", "step": 10 + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_ddl_batch_add_idx_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "add index worker", + "refId": "B", + "step": 10 } ], "thresholds": [], @@ -9228,7 +9329,7 @@ "dashLength": 10, "dashes": false, "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB batch add index durations by histogram buckets", + "description": "Some DDLs need to backfill data, for example, adding indexes, column type changes, etc. This metrics shows the number of rows backfilled per second.", "fill": 1, "gridPos": { "h": 7, @@ -9264,25 +9365,18 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_ddl_batch_add_idx_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "sum(rate(tidb_ddl_add_index_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", "refId": "A" - }, - { - "expr": "sum(rate(tidb_ddl_add_index_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}", - "refId": "B" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Batch Add Index Duration 100", + "title": "DDL Backfill Data Rate", "tooltip": { "shared": true, "sort": 0, @@ -9361,7 +9455,7 @@ "steppedLine": false, "targets": [ { - "expr": "tidb_ddl_waiting_jobs{tidb_cluster=\"$tidb_cluster\"}", + "expr": "tidb_ddl_waiting_jobs{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{type}}", @@ -9449,7 +9543,7 @@ "steppedLine": false, "targets": [ { - "expr": "increase(tidb_ddl_worker_operation_total{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "increase(tidb_ddl_worker_operation_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}-{{type}}", @@ -9539,7 +9633,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(increase(tidb_ddl_worker_operation_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type, action, result))", + "expr": "histogram_quantile(0.99, sum(increase(tidb_ddl_worker_operation_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type, action, result))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{action}}-{{result}}", @@ -9627,7 +9721,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_ddl_deploy_syncer_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, type, result))", + "expr": "histogram_quantile(1, sum(rate(tidb_ddl_deploy_syncer_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, type, result))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{result}}", @@ -9715,7 +9809,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_ddl_owner_handle_syncer_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, type, result))", + "expr": "histogram_quantile(1, sum(rate(tidb_ddl_owner_handle_syncer_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, type, result))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{result}}", @@ -9803,7 +9897,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_ddl_update_self_ver_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, result))", + "expr": "histogram_quantile(1, sum(rate(tidb_ddl_update_self_ver_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[2m])) by (le, result))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{result}}", @@ -9889,14 +9983,14 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_ddl_handle_job_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_ddl_handle_job_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{ type }}", "refId": "A" }, { - "expr": "sum(rate(tidb_ddl_handle_job_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tidb_ddl_handle_job_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "total", @@ -9958,7 +10052,7 @@ "x": 12, "y": 33 }, - "id": 193, + "id": 192, "legend": { "alignAsTable": true, "avg": false, @@ -9985,17 +10079,18 @@ "steppedLine": false, "targets": [ { - "expr": "irate(tidb_ddl_add_index_percentage_progress{tidb_cluster=\"$tidb_cluster\", type=\"add_index\"}[1m])", + "expr": "tidb_ddl_backfill_percentage_progress{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"add_index\"}", "format": "time_series", "intervalFactor": 1, - "legendFormat": "{{instance}}", + "legendFormat": "{{instance}}-{{type}}", "refId": "A" }, { - "expr": "irate(tidb_ddl_add_index_percentage_progress{tidb_cluster=\"$tidb_cluster\", type=\"modify_column\"}[1m])", + "expr": "tidb_ddl_backfill_percentage_progress{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"modify_column\"}", + "format": "time_series", "intervalFactor": 1, - "legendFormat": "{{instance}}", + "legendFormat": "{{instance}}-{{type}}", "refId": "B" } ], @@ -10093,7 +10188,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_statistics_auto_analyze_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_statistics_auto_analyze_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "auto analyze duration", @@ -10180,7 +10275,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_auto_analyze_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_statistics_auto_analyze_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10267,7 +10362,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", @@ -10275,14 +10370,14 @@ "step": 30 }, { - "expr": "histogram_quantile(0.90, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.90, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "90", "refId": "B" }, { - "expr": "histogram_quantile(0.50, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.50, sum(rate(tidb_statistics_stats_inaccuracy_rate_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "50", @@ -10368,7 +10463,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_pseudo_estimation_total{tidb_cluster=\"$tidb_cluster\"}[30s])) by (type)", + "expr": "sum(rate(tidb_statistics_pseudo_estimation_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10455,7 +10550,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_dump_feedback_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_statistics_dump_feedback_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10542,7 +10637,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_store_query_feedback_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type) ", + "expr": "sum(rate(tidb_statistics_store_query_feedback_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type) ", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10629,7 +10724,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_high_error_rate_feedback_total{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(rate(tidb_statistics_high_error_rate_feedback_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "hide": false, "intervalFactor": 2, @@ -10716,7 +10811,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_statistics_update_stats_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(rate(tidb_statistics_update_stats_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10810,7 +10905,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(1, sum(rate(tidb_statistics_fast_analyze_status_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(1, sum(rate(tidb_statistics_fast_analyze_status_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -10859,55 +10954,44 @@ "align": false, "alignLevel": null } - } - ], - "repeat": null, - "title": "Statistics", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 13 - }, - "id": 161, - "panels": [ + }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB new session durations for new etcd sessions", - "editable": true, - "error": false, + "description": "", + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, "fill": 1, - "grid": {}, + "fillGradient": 0, "gridPos": { "h": 7, "w": 8, "x": 0, - "y": 150 + "y": 170 }, - "id": 162, + "hiddenSeries": false, + "id": 229, "legend": { - "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, - "rightSide": false, "show": true, "total": false, "values": false }, "lines": true, - "linewidth": 2, + "linewidth": 1, "links": [], - "nullPointMode": "null as zero", + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, "percentage": false, "pointradius": 5, "points": false, @@ -10918,24 +11002,36 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_owner_new_session_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance, result))", + "exemplar": true, + "expr": "sum(rate(tidb_statistics_sync_load_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", + "interval": "", "intervalFactor": 2, - "legendFormat": "{{instance}}-{{result}}", + "legendFormat": "sync-load", "refId": "A", - "step": 10 + "step": 30 + }, + { + "exemplar": true, + "expr": "sum(rate(tidb_statistics_sync_load_timeout_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "timeout", + "refId": "B", + "step": 30 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "New ETCD Session Duration 95", + "title": "Sync Load QPS", "tooltip": { - "msResolution": false, "shared": true, "sort": 0, - "value_type": "cumulative" + "value_type": "individual" }, "type": "graph", "xaxis": { @@ -10947,11 +11043,11 @@ }, "yaxes": [ { - "format": "s", + "format": "short", "label": null, "logBase": 1, "max": null, - "min": "0", + "min": null, "show": true }, { @@ -10974,15 +11070,21 @@ "dashLength": 10, "dashes": false, "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB owner watcher counts", + "description": "", + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, "fill": 1, + "fillGradient": 0, "gridPos": { "h": 7, "w": 8, "x": 8, - "y": 150 + "y": 170 }, - "id": 163, + "hiddenSeries": false, + "id": 230, "legend": { "avg": false, "current": false, @@ -10996,6 +11098,9 @@ "linewidth": 1, "links": [], "nullPointMode": "null", + "options": { + "alertThreshold": true + }, "percentage": false, "pointradius": 5, "points": false, @@ -11006,19 +11111,32 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_owner_watch_owner_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, result, instance)", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(tidb_statistics_sync_load_latency_millis_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", + "interval": "", "intervalFactor": 2, - "legendFormat": "{{type}}-{{result}}-{{instance}}", + "legendFormat": "sync-load", "refId": "A", "step": 30 + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(tidb_statistics_read_stats_latency_millis_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "read-stats", + "refId": "B", + "step": 30 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Owner Watcher OPS", + "title": "Sync Load Latency 95 (ms)", "tooltip": { "shared": true, "sort": 0, @@ -11056,7 +11174,8 @@ } } ], - "title": "Owner", + "repeat": null, + "title": "Statistics", "type": "row" }, { @@ -11065,9 +11184,9 @@ "h": 1, "w": 24, "x": 0, - "y": 14 + "y": 13 }, - "id": 151, + "id": 161, "panels": [ { "aliasColors": {}, @@ -11075,30 +11194,33 @@ "dashLength": 10, "dashes": false, "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB auto id requests per second including single table/global auto id processing and single table auto id rebase processing", + "description": "TiDB new session durations for new etcd sessions", + "editable": true, + "error": false, "fill": 1, + "grid": {}, "gridPos": { "h": 7, - "w": 12, + "w": 8, "x": 0, - "y": 14 + "y": 150 }, - "id": 50, + "id": 162, "legend": { "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, - "rightSide": true, + "rightSide": false, "show": true, "total": false, "values": false }, "lines": true, - "linewidth": 1, + "linewidth": 2, "links": [], - "nullPointMode": "null", + "nullPointMode": "null as zero", "percentage": false, "pointradius": 5, "points": false, @@ -11109,22 +11231,24 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_autoid_operation_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_owner_new_session_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance, result))", "format": "time_series", "intervalFactor": 2, - "legendFormat": "AutoID QPS", - "refId": "A" + "legendFormat": "{{instance}}-{{result}}", + "refId": "A", + "step": 10 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "AutoID QPS", + "title": "New ETCD Session Duration 95", "tooltip": { + "msResolution": false, "shared": true, "sort": 0, - "value_type": "individual" + "value_type": "cumulative" }, "type": "graph", "xaxis": { @@ -11136,11 +11260,11 @@ }, "yaxes": [ { - "format": "short", + "format": "s", "label": null, "logBase": 1, "max": null, - "min": null, + "min": "0", "show": true }, { @@ -11163,22 +11287,20 @@ "dashLength": 10, "dashes": false, "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB auto id requests durations", + "description": "TiDB owner watcher counts", "fill": 1, "gridPos": { "h": 7, - "w": 12, - "x": 12, - "y": 14 + "w": 8, + "x": 8, + "y": 150 }, - "id": 51, + "id": 163, "legend": { - "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, - "rightSide": true, "show": true, "total": false, "values": false @@ -11197,25 +11319,19 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_autoid_operation_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99-{{type}}", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.80, sum(rate(tidb_autoid_operation_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "sum(rate(tidb_owner_watch_owner_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, result, instance)", "format": "time_series", "intervalFactor": 2, - "legendFormat": "80-{{type}}", - "refId": "C" + "legendFormat": "{{type}}-{{result}}-{{instance}}", + "refId": "A", + "step": 30 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "AutoID Duration", + "title": "Owner Watcher OPS", "tooltip": { "shared": true, "sort": 0, @@ -11231,7 +11347,204 @@ }, "yaxes": [ { - "format": "s", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Owner", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 151, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB auto id requests per second including single table/global auto id processing and single table auto id rebase processing", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 50, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_autoid_operation_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "AutoID QPS", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "AutoID QPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB auto id requests durations", + "fill": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 51, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_autoid_operation_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99-{{type}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.80, sum(rate(tidb_autoid_operation_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "80-{{type}}", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "AutoID Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", "label": null, "logBase": 2, "max": null, @@ -11290,7 +11603,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(rate(tidb_tikvclient_region_cache_operations_total{tidb_cluster=\"$tidb_cluster\", result=\"err\"}[1m])) by (type)", + "expr": "sum(rate(tidb_tikvclient_region_cache_operations_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", result=\"err\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11379,7 +11692,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_meta_operation_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_meta_operation_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, type))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11482,7 +11795,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_gc_worker_actions_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(increase(tidb_tikvclient_gc_worker_actions_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11571,7 +11884,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_gc_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_gc_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", "format": "time_series", "intervalFactor": 2, "legendFormat": "99", @@ -11659,7 +11972,7 @@ "steppedLine": false, "targets": [ { - "expr": "max(tidb_tikvclient_gc_config{tidb_cluster=\"$tidb_cluster\"}) by (type)", + "expr": "max(tidb_tikvclient_gc_config{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11745,7 +12058,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_gc_failure{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(increase(tidb_tikvclient_gc_failure{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11833,7 +12146,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_gc_unsafe_destroy_range_failures{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(increase(tidb_tikvclient_gc_unsafe_destroy_range_failures{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -11919,7 +12232,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_gc_region_too_many_locks{tidb_cluster=\"$tidb_cluster\"}[1m]))", + "expr": "sum(increase(tidb_tikvclient_gc_region_too_many_locks{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", "format": "time_series", "intervalFactor": 2, "legendFormat": "Locks Error OPM", @@ -12005,7 +12318,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_gc_action_result{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "expr": "sum(increase(tidb_tikvclient_gc_action_result{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}", @@ -12102,7 +12415,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(tidb_tikvclient_range_task_stats{tidb_cluster=\"$tidb_cluster\"}) by (type, result)", + "expr": "sum(tidb_tikvclient_range_task_stats{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (type, result)", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{type}}-{{result}}", @@ -12195,7 +12508,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_range_task_push_duration_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_range_task_push_duration_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{instance}}", @@ -12298,7 +12611,7 @@ "steppedLine": false, "targets": [ { - "expr": "delta(tidb_tikvclient_batch_client_no_available_connection_total{tidb_cluster=\"$tidb_cluster\"}[30s])", + "expr": "delta(tidb_tikvclient_batch_client_no_available_connection_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}", @@ -12389,7 +12702,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_client_unavailable_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_client_unavailable_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (le, instance))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -12483,7 +12796,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.9999, sum(rate(tidb_tikvclient_batch_client_wait_connection_establish_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.9999, sum(rate(tidb_tikvclient_batch_client_wait_connection_establish_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{instance}}", @@ -12533,7 +12846,7 @@ "alignLevel": null } }, - { + { "aliasColors": {}, "bars": false, "dashLength": 10, @@ -12584,7 +12897,7 @@ "targets": [ { "exemplar": true, - "expr": "rate(tidb_tikvclient_batch_recv_latency_sum{tidb_cluster=\"$tidb_cluster\"}[1m]) / rate(tidb_tikvclient_batch_recv_latency_count{tidb_cluster=\"$tidb_cluster\"}[1m])", + "expr": "rate(tidb_tikvclient_batch_recv_latency_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]) / rate(tidb_tikvclient_batch_recv_latency_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", "hide": false, "interval": "", "legendFormat": "{{instance}}-{{result}}", @@ -12592,7 +12905,7 @@ }, { "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_recv_latency_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_recv_latency_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", "format": "time_series", "hide": true, "interval": "", @@ -12657,14 +12970,695 @@ ], "title": "Batch Client", "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 18, - "style": "dark", - "tags": [], - "templating": { - "list": [ + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 232, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB TopSQL ignore event information ", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "hiddenSeries": false, + "id": 234, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(increase(tidb_topsql_ignored_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ignore Event Per Minute", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 2, + "max": null, + "min": "0.001", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "Durations for different TopSQL report types with 99 percent buckets", + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "hiddenSeries": false, + "id": 239, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_topsql_report_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", result=\"ok\"}[5m])) by (le, type))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tikv_resource_metering_report_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[5m])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "tikv-record", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99 Report Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 2, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "", + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 242, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(increase(tidb_topsql_report_data_total_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, job)", + "hide": false, + "interval": "", + "legendFormat": "{{job}}-{{type}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Report Data Count Per Minute", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "Total TiDB/TiKV TopSQL report count.", + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 243, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "sum(tidb_topsql_report_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) by (type, result)", + "hide": false, + "interval": "", + "legendFormat": "{{type}}-{{result}}", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(increase(tidb_topsql_report_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, result)", + "hide": true, + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(tikv_resource_metering_report_data_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", type=\"sent\"}) by (type)", + "hide": false, + "interval": "", + "legendFormat": "tikv-{{type}}", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Total Report Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 241, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "rate(tidb_server_cpu_profile_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Profiling OPS", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 245, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.5.11", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "rate(tikv_resource_metering_stat_task_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A", + "step": 40 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TiKV Stat Task OPS", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "TopSQL", + "type": "row" + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [], + "query": "label_values(pd_cluster_status, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, { "allValue": null, "current": {}, @@ -12675,7 +13669,7 @@ "multi": false, "name": "tidb_cluster", "options": [], - "query": "label_values(pd_cluster_status, tidb_cluster)", + "query": "label_values(pd_cluster_status{k8s_cluster=\"$k8s_cluster\"}, tidb_cluster)", "refresh": 2, "regex": "", "sort": 1, diff --git a/metrics/grafana/tidb_runtime.json b/metrics/grafana/tidb_runtime.json index 63136f16d0b02..0324f6851de98 100644 --- a/metrics/grafana/tidb_runtime.json +++ b/metrics/grafana/tidb_runtime.json @@ -134,7 +134,7 @@ "steppedLine": false, "targets": [ { - "expr": "process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -142,7 +142,7 @@ "refId": "A" }, { - "expr": "go_memstats_next_gc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / (1 + tidb_server_gogc{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / 100)", + "expr": "go_memstats_next_gc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / (1 + tidb_server_gogc{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / 100)", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -150,7 +150,7 @@ "refId": "H" }, { - "expr": "go_memstats_heap_alloc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_next_gc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / (1 + tidb_server_gogc{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / 100)", + "expr": "go_memstats_heap_alloc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_next_gc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / (1 + tidb_server_gogc{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} / 100)", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -158,7 +158,7 @@ "refId": "C" }, { - "expr": "go_memstats_heap_idle_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_released_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_heap_inuse_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_alloc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "go_memstats_heap_idle_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_released_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_heap_inuse_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_alloc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -166,7 +166,7 @@ "refId": "B" }, { - "expr": "go_memstats_stack_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_mspan_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_mcache_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_buck_hash_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_gc_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_other_sys_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "go_memstats_stack_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_mspan_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_mcache_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_buck_hash_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_gc_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} + go_memstats_other_sys_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -174,7 +174,7 @@ "refId": "D" }, { - "expr": "go_memstats_next_gc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "go_memstats_next_gc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -182,7 +182,7 @@ "refId": "E" }, { - "expr": "(clamp_max(idelta(go_memstats_last_gc_time_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]), 1) * go_memstats_next_gc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) > 0", + "expr": "(clamp_max(idelta(go_memstats_last_gc_time_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[1m]), 1) * go_memstats_next_gc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) > 0", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -287,7 +287,7 @@ "steppedLine": false, "targets": [ { - "expr": "irate(process_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", + "expr": "irate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", "format": "time_series", "hide": false, "interval": "", @@ -297,14 +297,14 @@ "step": 40 }, { - "expr": "(idelta((go_memstats_gc_cpu_fraction{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} * (go_memstats_last_gc_time_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - process_start_time_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) * tidb_server_maxprocs{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"})[30s:]) > 0) / 15", + "expr": "(idelta((go_memstats_gc_cpu_fraction{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} * (go_memstats_last_gc_time_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - process_start_time_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}) * tidb_server_maxprocs{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"})[30s:]) > 0) / 15", "format": "time_series", "intervalFactor": 1, "legendFormat": "gc-cpu", "refId": "C" }, { - "expr": "tidb_server_maxprocs{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "tidb_server_maxprocs{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -405,7 +405,7 @@ "steppedLine": false, "targets": [ { - "expr": "go_memstats_heap_objects{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "go_memstats_heap_objects{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -502,7 +502,7 @@ "steppedLine": false, "targets": [ { - "expr": "go_gc_duration_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile=\"0\"}", + "expr": "go_gc_duration_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile=\"0\"}", "format": "time_series", "hide": false, "instant": false, @@ -512,7 +512,7 @@ "step": 40 }, { - "expr": "go_gc_duration_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile!~\"0|1\"}", + "expr": "go_gc_duration_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile!~\"0|1\"}", "format": "time_series", "instant": false, "intervalFactor": 1, @@ -520,7 +520,7 @@ "refId": "B" }, { - "expr": "go_gc_duration_seconds{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile=\"1\"}", + "expr": "go_gc_duration_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\", quantile=\"1\"}", "format": "time_series", "instant": false, "intervalFactor": 1, @@ -624,28 +624,28 @@ "steppedLine": false, "targets": [ { - "expr": "irate(go_memstats_alloc_bytes_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", + "expr": "irate(go_memstats_alloc_bytes_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "alloc", "refId": "A" }, { - "expr": "irate((go_memstats_alloc_bytes_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_alloc_bytes{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"})[30s:])", + "expr": "irate((go_memstats_alloc_bytes_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"} - go_memstats_heap_alloc_bytes{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"})[30s:])", "format": "time_series", "intervalFactor": 1, "legendFormat": "sweep", "refId": "B" }, { - "expr": "irate(go_memstats_mallocs_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", + "expr": "irate(go_memstats_mallocs_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "alloc-ops", "refId": "C" }, { - "expr": "irate(go_memstats_frees_total{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", + "expr": "irate(go_memstats_frees_total{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])", "format": "time_series", "intervalFactor": 1, "legendFormat": "swepp-ops", @@ -739,14 +739,14 @@ "steppedLine": false, "targets": [ { - "expr": " go_goroutines{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": " go_goroutines{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "goroutines", "refId": "A" }, { - "expr": "go_threads{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", + "expr": "go_threads{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}", "format": "time_series", "intervalFactor": 1, "legendFormat": "threads", @@ -833,14 +833,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{tidb_cluster=\"$tidb_cluster\", store!=\"0\",instance=~\"$instance\"}[30s])) by (le, store))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", store!=\"0\",instance=~\"$instance\"}[30s])) by (le, store))", "format": "time_series", "intervalFactor": 1, "legendFormat": "tidb-to-store{{store}}", "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(tikv_grpc_msg_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!=\"kv_gc\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tikv_grpc_msg_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type!=\"kv_gc\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "tikv-{{instance}}-side", @@ -926,14 +926,14 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[30s])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[30s])) by (le))", "format": "time_series", "intervalFactor": 1, "legendFormat": "tidb-side", "refId": "A" }, { - "expr": "histogram_quantile(0.99, sum(rate(pd_server_handle_tso_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(pd_server_handle_tso_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", "format": "time_series", "intervalFactor": 1, "legendFormat": "pd-side", @@ -982,136 +982,190 @@ } }, { - "cards": { - "cardPadding": null, - "cardRound": null - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateSpectral", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, "datasource": "${DS_TEST-CLUSTER}", "description": "Number of requests in each batch", + "fill": 1, + "fillGradient": 0, "gridPos": { "h": 7, "w": 12, "x": 0, - "y": 36 + "y": 29 }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, + "hiddenSeries": false, "id": 23, "legend": { - "show": false + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true }, + "lines": true, + "linewidth": 1, "links": [], - "reverseYBuckets": false, + "nullPointMode": "null", + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_batch_requests_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le)", - "format": "heatmap", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_requests_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le))", + "format": "time_series", + "interval": "", "intervalFactor": 1, - "legendFormat": "{{le}}", + "legendFormat": "99", "refId": "A", "step": 40 } ], + "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Requests Batch Size", "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, "show": true, - "showHistogram": false + "values": [] }, - "type": "heatmap", - "xAxis": { + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", "show": true }, - "xBucketNumber": null, - "xBucketSize": null, - "yAxis": { - "decimals": null, - "format": "none", + { + "format": "short", + "label": null, "logBase": 1, "max": null, "min": null, - "show": true, - "splitFactor": null - }, - "yBucketBound": "auto", - "yBucketNumber": null, - "yBucketSize": null + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } }, { - "cards": { - "cardPadding": null, - "cardRound": null - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateSpectral", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, "datasource": "${DS_TEST-CLUSTER}", "description": "Number of requests in queue", + "fill": 1, + "fillGradient": 0, "gridPos": { "h": 7, "w": 12, "x": 12, - "y": 36 + "y": 29 }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, + "hiddenSeries": false, "id": 24, "legend": { - "show": false + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true }, + "lines": true, + "linewidth": 1, "links": [], - "reverseYBuckets": false, + "nullPointMode": "null", + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, "targets": [ { - "expr": "sum(increase(tidb_tikvclient_batch_pending_requests_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le)", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_pending_requests_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le))", "format": "heatmap", + "interval": "", "intervalFactor": 1, - "legendFormat": "{{le}}", + "legendFormat": "99", "refId": "A", "step": 40 } ], + "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Pending Requests", "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, "show": true, - "showHistogram": false + "values": [] }, - "type": "heatmap", - "xAxis": { + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", "show": true }, - "xBucketNumber": null, - "xBucketSize": null, - "yAxis": { - "decimals": null, - "format": "none", + { + "format": "short", + "label": null, "logBase": 1, "max": null, "min": null, - "show": true, - "splitFactor": null - }, - "yBucketBound": "auto", - "yBucketNumber": null, - "yBucketSize": null + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } }, { "aliasColors": {}, @@ -1156,7 +1210,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "999", @@ -1164,7 +1218,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99", @@ -1172,7 +1226,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.95, sum(rate(tidb_tikvclient_batch_wait_duration_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "95", @@ -1265,7 +1319,7 @@ "steppedLine": false, "targets": [ { - "expr": "histogram_quantile(0.9999, sum(rate(tidb_tikvclient_batch_send_latency_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.9999, sum(rate(tidb_tikvclient_batch_send_latency_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "9999", @@ -1273,7 +1327,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_batch_send_latency_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.999, sum(rate(tidb_tikvclient_batch_send_latency_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "999", @@ -1281,7 +1335,7 @@ "step": 10 }, { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_send_latency_bucket{tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", + "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_batch_send_latency_bucket{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}[30s])) by (le, instance))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99", @@ -1345,25 +1399,40 @@ "list": [ { "allValue": null, - "current": { - }, + "current": {}, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [], + "query": "label_values(pd_cluster_status, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, "datasource": "${DS_TEST-CLUSTER}", "hide": 2, "includeAll": false, "label": "tidb_cluster", "multi": false, "name": "tidb_cluster", - "options": [ - - ], - "query": "label_values(pd_cluster_status, tidb_cluster)", + "options": [], + "query": "label_values(pd_cluster_status{k8s_cluster=\"$k8s_cluster\"}, tidb_cluster)", "refresh": 2, "regex": "", "sort": 1, "tagValuesQuery": "", - "tags": [ - - ], + "tags": [], "tagsQuery": "", "type": "query", "useTags": false @@ -1372,14 +1441,14 @@ "allValue": null, "current": {}, "datasource": "${DS_TEST-CLUSTER}", - "definition": "label_values(process_start_time_seconds{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}, instance)", + "definition": "label_values(process_start_time_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}, instance)", "hide": 0, "includeAll": true, "label": "instance", "multi": false, "name": "instance", "options": [], - "query": "label_values(process_start_time_seconds{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}, instance)", + "query": "label_values(process_start_time_seconds{k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}, instance)", "refresh": 1, "regex": "", "skipUrlSync": false, diff --git a/metrics/grafana/tidb_summary.json b/metrics/grafana/tidb_summary.json index 0d12628605f2e..00ea4af9492ad 100644 --- a/metrics/grafana/tidb_summary.json +++ b/metrics/grafana/tidb_summary.json @@ -1,3114 +1,1819 @@ { - "__inputs": [ - { - "name": "DS_TEST-CLUSTER", - "label": "test-cluster", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "6.1.6" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "annotations": { - "list": [ + "__inputs": [ { - "builtIn": 1, - "datasource": "${DS_TEST-CLUSTER}", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" + "description": "", + "label": "test-cluster", + "name": "DS_TEST-CLUSTER", + "pluginId": "prometheus", + "pluginName": "Prometheus", + "type": "datasource" } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 1, - "id": null, - "links": [], - "panels": [ - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 140, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB uptime since the last restart.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 184, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pluginVersion": "6.1.6", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "fill": 0, - "lines": false - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(time() - process_start_time_seconds{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"})", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Uptime", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "dtdurations", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB current connection counts.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "fill": 0, - "lines": false - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "tidb_server_connections{tidb_cluster=\"$tidb_cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - }, - { - "expr": "sum(tidb_server_connections{tidb_cluster=\"$tidb_cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "total", - "refId": "B", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Connection Count", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB CPU usage calculated with process CPU running seconds.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 8 - }, - "id": 168, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "fill": 0, - "lines": false - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB process rss memory usage.\nTiDB heap memory size in use.", - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 8 - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "process-{{instance}}", - "refId": "A" - }, - { - "expr": "go_memstats_heap_sys_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 1, - "legendFormat": "HeapSys-{{instance}}", - "refId": "B" - }, - { - "expr": "go_memstats_heap_inuse_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "HeapInuse-{{instance}}", - "refId": "C" - }, - { - "expr": "go_memstats_heap_alloc_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 1, - "legendFormat": "HeapAlloc-{{instance}}", - "refId": "D" - }, - { - "expr": "go_memstats_heap_idle_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 1, - "legendFormat": "HeapIdle-{{instance}}", - "refId": "E" - }, - { - "expr": "go_memstats_heap_released_bytes{tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", - "hide": true, - "interval": "", - "legendFormat": "HeapReleased-{{instance}}", - "refId": "F" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Server", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 138, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB query durations by histogram buckets with different percents.", - "fill": 1, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 2 - }, - "id": 80, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "95", - "refId": "C" - }, - { - "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[30s])) / sum(rate(tidb_server_handle_query_duration_seconds_count{tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[30s]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "avg", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "TiDB failed query statistics by query type.", - "fill": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 2 - }, - "id": 137, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 250, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(tidb_server_execute_error_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": " {{type}}-{{instance}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Failed Query OPS", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "MySQL command processing numbers per second. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 42, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 250, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 1, - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (result)", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "query {{result}}", - "refId": "A", - "step": 60 - }, - { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\", result=\"OK\"}[1m] offset 1d))", - "format": "time_series", - "hide": true, - "instant": false, - "intervalFactor": 2, - "legendFormat": "yesterday", - "refId": "B", - "step": 90 - }, - { - "expr": "sum(tidb_server_connections{tidb_cluster=\"$tidb_cluster\"}) * sum(rate(tidb_server_handle_query_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[1m]))", - "format": "time_series", - "hide": true, - "instant": false, - "intervalFactor": 2, - "legendFormat": "ideal CPS", - "refId": "C", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Command Per Second", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB query total statistics including both successful and failed ones.", - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 9 - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 250, - "sort": "max", - "sortDesc": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 1, - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "lines": false - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}} ", - "refId": "A", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPS By Instance", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "TiDB statement statistics.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, + ], + "__requires": [ ], + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 1, + "hideControls": false, + "id": null, + "links": [ ], + "panels": [ + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, "x": 0, - "y": 16 - }, - "id": 21, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_executor_statement_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}", - "refId": "A", - "step": 30 + "y": 0 + }, + "id": 2, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB uptime since the last restart.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "time() - process_start_time_seconds{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Uptime", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "expr": "sum(rate(tidb_executor_statement_total{tidb_cluster=\"$tidb_cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "total", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "QPS", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB current connection counts.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A" + }, + { + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "total", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Connection Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "MySQL command statistics by command type. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html", - "fill": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 16 - }, - "id": 189, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 250, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_server_query_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": " {{type}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPS by CMD", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB CPU usage calculated with process CPU running seconds.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(process_cpu_seconds_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}[1m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB process rss memory usage.TiDB heap memory size in use.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_resident_memory_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "process-{{instance}}", + "refId": "A" + }, + { + "expr": "go_memstats_heap_inuse_bytes{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", job=\"tidb\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "HeapInuse-{{instance}}", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Query Summary", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Server", + "titleSize": "h6", + "type": "row" }, - "id": 142, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "The time cost of parsing SQL to AST", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, "x": 0, - "y": 3 - }, - "id": 156, - "interval": "", - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_parse_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "99", - "refId": "A", - "step": 30 + "y": 0 + }, + "id": 7, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB query durations by histogram buckets with different percents.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "95", + "refId": "B" + }, + { + "expr": "sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[30s])) / sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type!=\"internal\"}[30s]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "avg", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "95", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Parse Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB failed query statistics by query type.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(tidb_server_execute_error_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{type}}-{{instance}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Failed Query OPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "The time cost of building the query plan", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 154, - "interval": "", - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_compile_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "99", - "refId": "A", - "step": 30 - }, - { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_compile_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "95", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Compile Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "The time cost of executing the SQL which does not include the time to get the results of the query .", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 10 - }, - "id": 169, - "interval": "", - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_execute_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "99", - "refId": "A", - "step": 30 + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "MySQL command processing numbers per second. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (result)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "query {{result}}", + "refId": "A" + }, + { + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", result=\"OK\"}[1m] offset 1d))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "yesterday", + "refId": "B" + }, + { + "expr": "sum(tidb_server_connections{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}) * sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "ideal CPS", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Command Per Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "95", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Execution Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB query total statistics including both successful and failed ones.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPS By Instance", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "decimals": null, - "description": "TiDB plan cache hit total.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 10 - }, - "id": 91, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_server_plan_cache_total{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}", - "refId": "A", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Queries Using Plan Cache OPS", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB statement statistics.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A" + }, + { + "expr": "sum(rate(tidb_executor_statement_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "total", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "QPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "MySQL command statistics by command type. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_server_query_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPS by CMD", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Query Detail", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Query Summary", + "titleSize": "h6", + "type": "row" }, - "id": 141, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB transaction processing counts by type.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, "x": 0, - "y": 4 - }, - "id": 69, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, txn_mode)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}-{{txn_mode}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "TPS", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "y": 0 + }, + "id": 14, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The time cost of parsing SQL to AST", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "95", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Parse Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "Bucketed histogram of transaction execution durations, including retry.", - "fill": 1, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 4 - }, - "id": 72, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99-{{txn_mode}}", - "refId": "A" + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The time cost of building the query plan", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "95", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Compile Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "95-{{txn_mode}}", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "80-{{txn_mode}}", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The max TiDB statements numbers within one transaction.", - "fill": 1, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 74, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(1, sum(rate(tidb_session_transaction_statement_num_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "max", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Max Transaction Statement Num", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The max TiDB transaction retry count.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 67, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(1.0, sum(rate(tidb_session_retry_num_bucket{tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "max", - "refId": "A", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Max Transaction Retry Num", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The time cost of executing the SQL which does not include the time to get the results of the query.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 17, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "95", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Execution Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB plan cache hit total.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 18, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_server_plan_cache_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Queries Using Plan Cache OPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Transaction", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Query Detail", + "titleSize": "h6", + "type": "row" }, - "id": 145, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "KV request durations by store (TiKV). It contains requests that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 5 - }, - "id": 48, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "max", - "sortDesc": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!=\"GC\"}[1m])) by (le, store))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "store-{{store}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "KV Request Duration 99 by store", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "KV request durations by request type. It contains requests that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 5 - }, - "id": 30, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "max", - "sortDesc": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_tikvclient_request_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type!=\"GC\"}[1m])) by (le,type))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "KV Request Duration 99 by type", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "KV request count by request type. It contains requests that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 5 - }, - "id": 172, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_tikvclient_request_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{type}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "KV Request OPS", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB total kv transaction counts. It contains transactions that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 12 - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_tikvclient_txn_cmd_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "KV Transaction OPS", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The max writes bytes of the transaction. It contains transactions that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 12 - }, - "id": 34, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(1, sum(rate(tidb_tikvclient_txn_write_size_bytes_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Max Transaction Write Size Bytes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The max writes kv count of the transaction. It contains transactions that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 12 - }, - "id": 33, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(1, sum(rate(tidb_tikvclient_txn_write_kv_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "B", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Max Transaction Write KV Num", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The max writes regions of the transaction. It contains transactions that are executed automatically by the internal background.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 19 - }, - "id": 44, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(1, sum(rate(tidb_tikvclient_txn_regions_num_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le, instance))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Max Transaction Regions Num", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The duration of TiDB starts to wait for the TSO until received the TS result.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 19 - }, - "id": 77, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "999", - "refId": "A", - "step": 10 - }, - { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_cmd_handle_cmds_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"wait\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "90", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "PD TSO Wait Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "The duration of a client starting to wait for the TS until received the TS result.", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 19 - }, - "id": 78, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.999, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "999", - "refId": "A", - "step": 10 - }, - { - "expr": "histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.90, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\", type=\"tso\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "90", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "PD TSO RPC Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB auto-ID requests per second including single table/global auto-ID processing and single table auto-ID rebase processing.", - "fill": 1, - "gridPos": { - "h": 7, - "w": 12, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, "x": 0, - "y": 26 - }, - "id": 50, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(tidb_autoid_operation_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "AutoID QPS", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true + "y": 0 + }, + "id": 19, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "TiDB transaction processing counts by type.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 20, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(tidb_session_transaction_duration_seconds_count{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[1m])) by (type, txn_mode)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{type}}-{{txn_mode}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "TPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_TEST-CLUSTER}", - "description": "TiDB auto-ID requests durations.", - "fill": 1, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 26 - }, - "id": 51, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(tidb_autoid_operation_duration_seconds_bucket{tidb_cluster=\"$tidb_cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99", - "refId": "B" + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "Bucketed histogram of transaction execution durations, including retry.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 21, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99-{{txn_mode}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "95-{{txn_mode}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", sql_type=\"general\"}[1m])) by (le, txn_mode))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "80-{{txn_mode}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Transaction Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "expr": "sum(rate(tidb_autoid_operation_duration_seconds_sum{tidb_cluster=\"$tidb_cluster\"}[1m])) / sum(rate(tidb_autoid_operation_duration_seconds_count{tidb_cluster=\"$tidb_cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "avg", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "AutoID Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "s", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The max TiDB statements numbers within one transaction.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 22, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(1, sum(rate(tidb_session_transaction_statement_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "max", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Max Transaction Statement Num", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] }, { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The max TiDB transaction retry count.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 23, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(1.0, sum(rate(tidb_session_retry_num_bucket{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\"}[30s])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "max", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Max Transaction Retry Num", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Write Slow", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 18, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "allValue": null, - "current": { - }, - "datasource": "${DS_TEST-CLUSTER}", - "hide": 2, - "includeAll": false, - "label": "tidb_cluster", - "multi": false, - "name": "tidb_cluster", - "options": [ - - ], - "query": "label_values(pd_cluster_status, tidb_cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Transaction", + "titleSize": "h6", + "type": "row" } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Test-Cluster-TiDB-Summary", - "uid": "000000012", - "version": 1 -} \ No newline at end of file + ], + "refresh": "30s", + "rows": [ ], + "schemaVersion": 14, + "style": "dark", + "tags": [ ], + "templating": { + "list": [ + { + "allValue": null, + "current": { }, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "K8s-cluster", + "multi": false, + "name": "k8s_cluster", + "options": [ ], + "query": "label_values(pd_cluster_status, k8s_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { }, + "datasource": "${DS_TEST-CLUSTER}", + "hide": 2, + "includeAll": false, + "label": "tidb_cluster", + "multi": false, + "name": "tidb_cluster", + "options": [ ], + "query": "label_values(pd_cluster_status{k8s_cluster=\"$kuberentes\"}, tidb_cluster)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Test-Cluster-TiDB-Summary", + "version": 0 +} diff --git a/metrics/grafana/tidb_summary.jsonnet b/metrics/grafana/tidb_summary.jsonnet new file mode 100644 index 0000000000000..00ea7bee4410d --- /dev/null +++ b/metrics/grafana/tidb_summary.jsonnet @@ -0,0 +1,453 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +local grafana = import 'grafonnet/grafana.libsonnet'; +local dashboard = grafana.dashboard; +local row = grafana.row; +local graphPanel = grafana.graphPanel; +local prometheus = grafana.prometheus; +local template = grafana.template; + +local myNameFlag = 'DS_TEST-CLUSTER'; +local myDS = '${' + myNameFlag + '}'; + +// A new dashboard +local newDash = dashboard.new( + title='Test-Cluster-TiDB-Summary', + editable=true, + graphTooltip='shared_crosshair', + refresh='30s', + time_from='now-1h', +) +.addInput( + name=myNameFlag, + label='test-cluster', + type='datasource', + pluginId='prometheus', + pluginName='Prometheus', +) +.addTemplate( + template.new( + datasource=myDS, + hide= 2, + label='K8s-cluster', + name='k8s_cluster', + query='label_values(pd_cluster_status, k8s_cluster)', + refresh='time', + sort=1, + ) +) +.addTemplate( + // Default template for tidb-cloud + template.new( + allValues=null, + current=null, + datasource=myDS, + hide='all', + includeAll=false, + label='tidb_cluster', + multi=false, + name='tidb_cluster', + query='label_values(pd_cluster_status{k8s_cluster="$kuberentes"}, tidb_cluster)', + refresh='time', + regex='', + sort=1, + tagValuesQuery='', + ) +); + +// Server row and its panels +local serverRow = row.new(collapse=true, title='Server'); +local uptimeP = graphPanel.new( + title='Uptime', + datasource=myDS, + legend_rightSide=true, + format='s', + description='TiDB uptime since the last restart.', +) +.addTarget( + prometheus.target( + 'time() - process_start_time_seconds{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", job="tidb"}', + legendFormat='{{instance}}', + ) +); + +local connectionP = graphPanel.new( + title='Connection Count', + datasource=myDS, + legend_rightSide=true, + description='TiDB current connection counts.', + format='short', + stack=true, +) +.addTarget( + prometheus.target( + 'tidb_server_connections{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}', + legendFormat='{{instance}}', + ) +) +.addTarget( + prometheus.target( + 'sum(tidb_server_connections{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"})', + legendFormat='total', + ) +); + +local cpuP = graphPanel.new( + title='CPU Usage', + datasource=myDS, + legend_rightSide=true, + description='TiDB CPU usage calculated with process CPU running seconds.', + format='percentunit', +) +.addTarget( + prometheus.target( + 'rate(process_cpu_seconds_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", job="tidb"}[1m])', + legendFormat='{{instance}}', + ) +); + +local memP = graphPanel.new( + title='Memory Usage', + datasource=myDS, + legend_rightSide=true, + description='TiDB process rss memory usage.TiDB heap memory size in use.', + format='bytes', +) +.addTarget( + prometheus.target( + 'process_resident_memory_bytes{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", job="tidb"}', + legendFormat='process-{{instance}}', + ) +) +.addTarget( + prometheus.target( + 'go_memstats_heap_inuse_bytes{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", job="tidb"}', + legendFormat='HeapInuse-{{instance}}', + ) +); + +// Query Summary +local queryRow = row.new(collapse=true, title='Query Summary'); +local durationP = graphPanel.new( + title='Duration', + datasource=myDS, + legend_rightSide=true, + description='TiDB query durations by histogram buckets with different percents.', + format='s', +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type!="internal"}[1m])) by (le))', + legendFormat='99', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.95, sum(rate(tidb_server_handle_query_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type!="internal"}[1m])) by (le))', + legendFormat='95', + ) +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type!="internal"}[30s])) / sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type!="internal"}[30s]))', + legendFormat='avg', + ) +); + +local failedP = graphPanel.new( + title='Failed Query OPS', + datasource=myDS, + legend_rightSide=true, + description='TiDB failed query statistics by query type.', + format='short', +) +.addTarget( + prometheus.target( + 'sum(increase(tidb_server_execute_error_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (type, instance)', + legendFormat='{{type}}-{{instance}}', + ) +); + +local cpsP = graphPanel.new( + title='Command Per Second', + datasource=myDS, + legend_rightSide=true, + description='MySQL command processing numbers per second. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html', + format='short', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_query_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (result)', + legendFormat='query {{result}}', + ) +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_query_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", result="OK"}[1m] offset 1d))', + legendFormat='yesterday', + hide=true, + ) +) +.addTarget( + prometheus.target( + 'sum(tidb_server_connections{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}) * sum(rate(tidb_server_handle_query_duration_seconds_count{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) / sum(rate(tidb_server_handle_query_duration_seconds_sum{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m]))', + legendFormat='ideal CPS', + hide=true, + ) +); + +local cpsByInstP = graphPanel.new( + title='CPS By Instance', + datasource=myDS, + legend_rightSide=true, + description='TiDB query total statistics including both successful and failed ones.', + format='short', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_query_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (instance)', + legendFormat='{{instance}}', + ) +); + +local qpsP = graphPanel.new( + title='QPS', + datasource=myDS, + legend_rightSide=true, + description='TiDB statement statistics.', + format='short', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_executor_statement_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (type)', + legendFormat='{{type}}', + ) +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_executor_statement_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m]))', + legendFormat='total', + ) +); + +local cpsByCMDP = graphPanel.new( + title='CPS by CMD', + datasource=myDS, + legend_rightSide=true, + description='MySQL command statistics by command type. See https://dev.mysql.com/doc/internals/en/text-protocol.html and https://dev.mysql.com/doc/internals/en/prepared-statements.html', + format='short', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_query_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (type)', + legendFormat='{{type}}', + ) +); + +// Query Detail row and its panels +local queryDetailRow = row.new(collapse=true, title='Query Detail'); +local parseP = graphPanel.new( + title='Parse Duration', + datasource=myDS, + legend_rightSide=true, + format='s', + description='The time cost of parsing SQL to AST', +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.99, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='99', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.95, sum(rate(tidb_session_parse_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='95', + ) +); + +local compileP = graphPanel.new( + title='Compile Duration', + datasource=myDS, + legend_rightSide=true, + description='The time cost of building the query plan', + format='s', +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.99, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='99', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.95, sum(rate(tidb_session_compile_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='95', + ) +); + +local exeP = graphPanel.new( + title='Execution Duration', + datasource=myDS, + legend_rightSide=true, + description='The time cost of executing the SQL which does not include the time to get the results of the query.', + format='s', +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.99, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='99', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.95, sum(rate(tidb_session_execute_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le))', + legendFormat='95', + ) +); + +local planCacheP = graphPanel.new( + title='Queries Using Plan Cache OPS', + datasource=myDS, + legend_rightSide=true, + description='TiDB plan cache hit total.', + format='short', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_server_plan_cache_total{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (type)', + legendFormat='{{type}}', + ) +); + +// Transaction row and its panels +local txnRow = row.new(collapse=true, title='Transaction'); +local tpsP = graphPanel.new( + title='TPS', + datasource=myDS, + legend_rightSide=true, + format='short', + description='TiDB transaction processing counts by type.', +) +.addTarget( + prometheus.target( + 'sum(rate(tidb_session_transaction_duration_seconds_count{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[1m])) by (type, txn_mode)', + legendFormat='{{type}}-{{txn_mode}}', + ) +); + +local txnDurationP = graphPanel.new( + title='Transaction Duration', + datasource=myDS, + legend_rightSide=true, + description='Bucketed histogram of transaction execution durations, including retry.', + format='s', +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.99, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le, txn_mode))', + legendFormat='99-{{txn_mode}}', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.95, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le, txn_mode))', + legendFormat='95-{{txn_mode}}', + ) +) +.addTarget( + prometheus.target( + 'histogram_quantile(0.80, sum(rate(tidb_session_transaction_duration_seconds_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster", sql_type="general"}[1m])) by (le, txn_mode))', + legendFormat='80-{{txn_mode}}', + ) +); + +local maxTxnStmtP = graphPanel.new( + title='Max Transaction Statement Num', + datasource=myDS, + legend_rightSide=true, + description='The max TiDB statements numbers within one transaction.', + format='short', +) +.addTarget( + prometheus.target( + 'histogram_quantile(1, sum(rate(tidb_session_transaction_statement_num_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[30s])) by (le))', + legendFormat='max', + ) +); + +local maxTxnRetryP = graphPanel.new( + title='Max Transaction Retry Num', + datasource=myDS, + legend_rightSide=true, + description='The max TiDB transaction retry count.', + format='short', +) +.addTarget( + prometheus.target( + 'histogram_quantile(1.0, sum(rate(tidb_session_retry_num_bucket{k8s_cluster="$k8s_cluster", tidb_cluster="$tidb_cluster"}[30s])) by (le))', + legendFormat='max', + ) +); + +// Merge together. +local panelW = 12; +local panelH = 6; +local rowW = 24; +local rowH = 1; + +local rowPos = {x:0, y:0, w:rowW, h:rowH}; +local leftPanelPos = {x:0, y:0, w:panelW, h:panelH}; +local rightPanelPos = {x:panelW, y:0, w:panelW, h:panelH}; + +newDash +.addPanel( + serverRow + .addPanel(uptimeP, gridPos=leftPanelPos) + .addPanel(connectionP, gridPos=rightPanelPos) + .addPanel(cpuP, gridPos=leftPanelPos) + .addPanel(memP, gridPos=rightPanelPos) + , + gridPos=rowPos +) +.addPanel( + queryRow + .addPanel(durationP, gridPos=leftPanelPos) + .addPanel(failedP, gridPos=rightPanelPos) + .addPanel(cpsP, gridPos=leftPanelPos) + .addPanel(cpsByInstP, gridPos=rightPanelPos) + .addPanel(qpsP, gridPos=leftPanelPos) + .addPanel(cpsByCMDP, gridPos=rightPanelPos) + , + gridPos=rowPos +) +.addPanel( + queryDetailRow + .addPanel(parseP, gridPos=leftPanelPos) + .addPanel(compileP, gridPos=rightPanelPos) + .addPanel(exeP, gridPos=leftPanelPos) + .addPanel(planCacheP, gridPos=rightPanelPos) + , + gridPos=rowPos +) +.addPanel( + txnRow + .addPanel(tpsP, gridPos=leftPanelPos) + .addPanel(txnDurationP, gridPos=rightPanelPos) + .addPanel(maxTxnStmtP, gridPos=leftPanelPos) + .addPanel(maxTxnRetryP, gridPos=rightPanelPos) + , + gridPos=rowPos +) diff --git a/metrics/main_test.go b/metrics/main_test.go index 2e27c2eec0544..d207a172d0eda 100644 --- a/metrics/main_test.go +++ b/metrics/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/metrics/metrics.go b/metrics/metrics.go index f5c1faf5bb3aa..5bbb2ab4a3c01 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -96,6 +96,10 @@ func RegisterMetrics() { prometheus.MustRegister(HandleJobHistogram) prometheus.MustRegister(SignificantFeedbackCounter) prometheus.MustRegister(FastAnalyzeHistogram) + prometheus.MustRegister(SyncLoadCounter) + prometheus.MustRegister(SyncLoadTimeoutCounter) + prometheus.MustRegister(SyncLoadHistogram) + prometheus.MustRegister(ReadStatsHistogram) prometheus.MustRegister(JobsGauge) prometheus.MustRegister(KeepAliveCounter) prometheus.MustRegister(LoadPrivilegeCounter) @@ -108,7 +112,7 @@ func RegisterMetrics() { prometheus.MustRegister(PanicCounter) prometheus.MustRegister(PlanCacheCounter) prometheus.MustRegister(PseudoEstimation) - prometheus.MustRegister(PacketIOHistogram) + prometheus.MustRegister(PacketIOCounter) prometheus.MustRegister(QueryDurationHistogram) prometheus.MustRegister(QueryTotalCounter) prometheus.MustRegister(SchemaLeaseErrorCounter) @@ -139,7 +143,6 @@ func RegisterMetrics() { prometheus.MustRegister(GCJobFailureCounter) prometheus.MustRegister(GCRegionTooManyLocksCounter) prometheus.MustRegister(GCWorkerCounter) - prometheus.MustRegister(GCUnsafeDestroyRangeFailuresCounterVec) prometheus.MustRegister(TotalQueryProcHistogram) prometheus.MustRegister(TotalCopProcHistogram) prometheus.MustRegister(TotalCopWaitHistogram) @@ -158,6 +161,9 @@ func RegisterMetrics() { prometheus.MustRegister(TopSQLReportDurationHistogram) prometheus.MustRegister(TopSQLReportDataHistogram) prometheus.MustRegister(PDApiExecutionHistogram) + prometheus.MustRegister(CPUProfileCounter) + prometheus.MustRegister(ReadFromTableCacheCounter) + prometheus.MustRegister(LoadTableCacheDurationHistogram) tikvmetrics.InitMetrics(TiDB, TiKVClient) tikvmetrics.RegisterMetrics() diff --git a/metrics/server.go b/metrics/server.go index 68f8e8b3abf86..72dc9e4e4b8ba 100644 --- a/metrics/server.go +++ b/metrics/server.go @@ -27,13 +27,12 @@ var ( // Metrics var ( - PacketIOHistogram = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ + PacketIOCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ Namespace: "tidb", Subsystem: "server", Name: "packet_io_bytes", - Help: "Bucketed histogram of packet IO bytes.", - Buckets: prometheus.ExponentialBuckets(4, 4, 21), // 4Bytes ~ 4TB + Help: "Counters of packet IO bytes.", }, []string{LblType}) QueryDurationHistogram = prometheus.NewHistogramVec( @@ -129,6 +128,15 @@ var ( Help: "Counter of query using plan cache.", }, []string{LblType}) + ReadFromTableCacheCounter = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "tidb", + Subsystem: "server", + Name: "read_from_tablecache_total", + Help: "Counter of query read from table cache.", + }, + ) + HandShakeErrorCounter = prometheus.NewCounter( prometheus.CounterOpts{ Namespace: "tidb", @@ -238,6 +246,23 @@ var ( Help: "Bucketed histogram of all pd api execution time (s)", Buckets: prometheus.ExponentialBuckets(0.001, 2, 20), // 1ms ~ 524s }, []string{LblType}) + + CPUProfileCounter = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "tidb", + Subsystem: "server", + Name: "cpu_profile_total", + Help: "Counter of cpu profiling", + }) + + LoadTableCacheDurationHistogram = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Namespace: "tidb", + Subsystem: "server", + Name: "load_table_cache_seconds", + Help: "Duration (us) for loading table cache.", + Buckets: prometheus.ExponentialBuckets(1, 2, 30), // 1us ~ 528s + }) ) // ExecuteErrorToLabel converts an execute error to label. diff --git a/metrics/session.go b/metrics/session.go index 0058104788f21..83df91439d311 100644 --- a/metrics/session.go +++ b/metrics/session.go @@ -142,6 +142,7 @@ const ( LblDb = "db" LblResult = "result" LblSQLType = "sql_type" + LblCoprType = "copr_type" LblGeneral = "general" LblInternal = "internal" LbTxnMode = "txn_mode" diff --git a/metrics/stats.go b/metrics/stats.go index a3347dd597716..c4b74cf088915 100644 --- a/metrics/stats.go +++ b/metrics/stats.go @@ -94,4 +94,38 @@ var ( Help: "Bucketed histogram of some stats in fast analyze.", Buckets: prometheus.ExponentialBuckets(1, 2, 16), }, []string{LblSQLType, LblType}) + + SyncLoadCounter = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "tidb", + Subsystem: "statistics", + Name: "sync_load_total", + Help: "Counter of sync load.", + }) + + SyncLoadTimeoutCounter = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "tidb", + Subsystem: "statistics", + Name: "sync_load_timeout_total", + Help: "Counter of sync load timeout.", + }) + + SyncLoadHistogram = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Namespace: "tidb", + Subsystem: "statistics", + Name: "sync_load_latency_millis", + Help: "Bucketed histogram of latency time (ms) of sync load.", + Buckets: prometheus.ExponentialBuckets(1, 2, 22), // 1ms ~ 1h + }) + + ReadStatsHistogram = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Namespace: "tidb", + Subsystem: "statistics", + Name: "read_stats_latency_millis", + Help: "Bucketed histogram of latency time (ms) of stats read during sync-load.", + Buckets: prometheus.ExponentialBuckets(1, 2, 22), // 1ms ~ 1h + }) ) diff --git a/metrics/telemetry.go b/metrics/telemetry.go index 7db666d8dc737..e98f5a9f5d6d0 100644 --- a/metrics/telemetry.go +++ b/metrics/telemetry.go @@ -52,11 +52,11 @@ type CTEUsageCounter struct { // Sub returns the difference of two counters. func (c CTEUsageCounter) Sub(rhs CTEUsageCounter) CTEUsageCounter { - new := CTEUsageCounter{} - new.NonRecursiveCTEUsed = c.NonRecursiveCTEUsed - rhs.NonRecursiveCTEUsed - new.RecursiveUsed = c.RecursiveUsed - rhs.RecursiveUsed - new.NonCTEUsed = c.NonCTEUsed - rhs.NonCTEUsed - return new + return CTEUsageCounter{ + NonRecursiveCTEUsed: c.NonRecursiveCTEUsed - rhs.NonRecursiveCTEUsed, + RecursiveUsed: c.RecursiveUsed - rhs.RecursiveUsed, + NonCTEUsed: c.NonCTEUsed - rhs.NonCTEUsed, + } } // GetCTECounter gets the TxnCommitCounter. diff --git a/owner/fail_test.go b/owner/fail_test.go index e340ff69970ec..4f93fe278c002 100644 --- a/owner/fail_test.go +++ b/owner/fail_test.go @@ -21,15 +21,15 @@ import ( "net" "os" "runtime" - "sync" "testing" "time" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/parser/terror" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc" ) @@ -52,14 +52,12 @@ func TestFailNewSession(t *testing.T) { require.NoError(t, err) srv := grpc.NewServer(grpc.ConnectionTimeout(time.Minute)) - var stop sync.WaitGroup - stop.Add(1) - go func() { - defer stop.Done() + var stop util.WaitGroupWrapper + stop.Run(func() { err = srv.Serve(ln) assert.NoError(t, err) - }() + }) defer func() { srv.Stop() diff --git a/owner/main_test.go b/owner/main_test.go index ba940ab9a3d5d..1aff62becfd64 100644 --- a/owner/main_test.go +++ b/owner/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), } goleak.VerifyTestMain(m, opts...) } diff --git a/owner/manager.go b/owner/manager.go index 93a0b760c7b81..d7708854ce298 100644 --- a/owner/manager.go +++ b/owner/manager.go @@ -31,10 +31,10 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/clientv3/concurrency" - "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes" - "go.etcd.io/etcd/mvcc/mvccpb" + "go.etcd.io/etcd/api/v3/mvccpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3/concurrency" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -200,7 +200,7 @@ func (m *ownerManager) CampaignOwner() error { func (m *ownerManager) ResignOwner(ctx context.Context) error { elec := (*concurrency.Election)(atomic.LoadPointer(&m.elec)) if elec == nil { - return errors.Errorf("This node is not a ddl owner, can't be resigned.") + return errors.Errorf("This node is not a ddl owner, can't be resigned") } childCtx, cancel := context.WithTimeout(ctx, keyOpDefaultTimeout) diff --git a/owner/manager_test.go b/owner/manager_test.go index af458965a7da3..f2c1f5da0584c 100644 --- a/owner/manager_test.go +++ b/owner/manager_test.go @@ -29,9 +29,9 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/util/logutil" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/clientv3" - "go.etcd.io/etcd/clientv3/concurrency" - "go.etcd.io/etcd/integration" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3/concurrency" + "go.etcd.io/etcd/tests/v3/integration" goctx "golang.org/x/net/context" ) @@ -41,6 +41,7 @@ func TestSingle(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) store, err := mockstore.NewMockStore() require.NoError(t, err) @@ -100,6 +101,7 @@ func TestCluster(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) originalTTL := owner.ManagerSessionTTL owner.ManagerSessionTTL = 3 diff --git a/parser/README.md b/parser/README.md index 3daa9ead1d285..509a7a8a465b8 100644 --- a/parser/README.md +++ b/parser/README.md @@ -7,13 +7,13 @@ The goal of this project is to build a Golang parser that is fully compatible with MySQL syntax, easy to extend, and high performance. Currently, features supported by parser are as follows: -- Highly compatible with MySQL: it supports almost all features of MySQL. For the complete details, see [parser.y](https://github.com/pingcap/parser/blob/master/parser.y) and [hintparser.y](https://github.com/pingcap/parser/blob/master/hintparser.y). +- Highly compatible with MySQL: it supports almost all features of MySQL. For the complete details, see [parser.y](https://github.com/pingcap/tidb/blob/master/parser/parser.y) and [hintparser.y](https://github.com/pingcap/tidb/blob/master/parser/hintparser.y). - Extensible: adding a new syntax requires only a few lines of Yacc and Golang code changes. As an example, see [PR-680](https://github.com/pingcap/parser/pull/680/files). - Good performance: the parser is generated by goyacc in a bottom-up approach. It is efficient to build an AST tree with a state machine. ## How to use it -Please read the [quickstart](https://github.com/pingcap/parser/blob/master/docs/quickstart.md). +Please read the [quickstart](https://github.com/pingcap/tidb/blob/master/parser/docs/quickstart.md). ## Future @@ -24,7 +24,7 @@ Please read the [quickstart](https://github.com/pingcap/parser/blob/master/docs/ ## Getting Help -- [GitHub Issue](https://github.com/pingcap/parser/issues) +- [GitHub Issue](https://github.com/pingcap/tidb/issues) - [Stack Overflow](https://stackoverflow.com/questions/tagged/tidb) - [User Group (Chinese)](https://asktug.com/) @@ -44,13 +44,12 @@ found you are one of the users but not listed here: - [XiaoMi/Gaea](https://github.com/XiaoMi/Gaea) - [sql-machine-learning/sqlflow](https://github.com/sql-machine-learning/sqlflow) - [nooncall/shazam](https://github.com/nooncall/shazam) +- [bytebase/bytebase](https://github.com/bytebase/bytebase) ## Contributing Contributions are welcomed and greatly appreciated. See [Contribution Guide](https://github.com/pingcap/community/blob/master/contributors/README.md) for details on submitting patches and the contribution workflow. -Here is how to [update parser for TiDB](https://github.com/pingcap/parser/blob/master/docs/update-parser-for-tidb.md). - ## Acknowledgments Thanks [cznic](https://github.com/cznic) for providing some great open-source tools. diff --git a/parser/ast/ast.go b/parser/ast/ast.go index 1f76a26ce7e78..dda80b07e105e 100644 --- a/parser/ast/ast.go +++ b/parser/ast/ast.go @@ -18,6 +18,7 @@ package ast import ( "io" + "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/format" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/types" @@ -37,10 +38,12 @@ type Node interface { // children should be skipped. Otherwise, call its children in particular order that // later elements depends on former elements. Finally, return visitor.Leave. Accept(v Visitor) (node Node, ok bool) - // Text returns the original text of the element. + // Text returns the utf8 encoding text of the element. Text() string + // OriginalText returns the original text of the element. + OriginalText() string // SetText sets original text to the Node. - SetText(text string) + SetText(enc charset.Encoding, text string) // SetOriginTextPosition set the start offset of this node in the origin text. SetOriginTextPosition(offset int) // OriginTextPosition get the start offset of this node in the origin text. diff --git a/parser/ast/base.go b/parser/ast/base.go index a1ecc49559ffb..a7dcc9cefdc55 100644 --- a/parser/ast/base.go +++ b/parser/ast/base.go @@ -14,12 +14,19 @@ package ast import ( + "sync" + + "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/types" ) // node is the struct implements Node interface except for Accept method. // Node implementations should embed it in. type node struct { + utf8Text string + enc charset.Encoding + once *sync.Once + text string offset int } @@ -35,12 +42,30 @@ func (n *node) OriginTextPosition() int { } // SetText implements Node interface. -func (n *node) SetText(text string) { +func (n *node) SetText(enc charset.Encoding, text string) { + n.enc = enc n.text = text + n.once = &sync.Once{} } // Text implements Node interface. func (n *node) Text() string { + if n.once == nil { + return n.text + } + n.once.Do(func() { + if n.enc == nil { + n.utf8Text = n.text + return + } + utf8Lit, _ := n.enc.Transform(nil, charset.HackSlice(n.text), charset.OpDecodeReplace) + n.utf8Text = charset.HackString(utf8Lit) + }) + return n.utf8Text +} + +// OriginalText implements Node interface. +func (n *node) OriginalText() string { return n.text } diff --git a/parser/ast/base_test.go b/parser/ast/base_test.go new file mode 100644 index 0000000000000..17a79321b1478 --- /dev/null +++ b/parser/ast/base_test.go @@ -0,0 +1,42 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package ast is the abstract syntax tree parsed from a SQL statement by parser. +// It can be analysed and transformed by optimizer. +package ast + +import ( + "testing" + + "github.com/pingcap/tidb/parser/charset" + "github.com/stretchr/testify/require" +) + +func TestNodeSetText(t *testing.T) { + n := &node{} + tests := []struct { + text string + enc charset.Encoding + expectUTF8Text string + expectText string + }{ + {"你好", nil, "你好", "你好"}, + {"\xd2\xbb", charset.EncodingGBKImpl, "一", "\xd2\xbb"}, + {"\xc1\xd0", charset.EncodingGBKImpl, "列", "\xc1\xd0"}, + } + for _, tt := range tests { + n.SetText(tt.enc, tt.text) + require.Equal(t, tt.expectUTF8Text, n.Text()) + require.Equal(t, tt.expectText, n.OriginalText()) + } +} diff --git a/parser/ast/ddl.go b/parser/ast/ddl.go index 28834697b1961..54b2734b8fde5 100644 --- a/parser/ast/ddl.go +++ b/parser/ast/ddl.go @@ -15,7 +15,6 @@ package ast import ( "github.com/pingcap/errors" - "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/format" "github.com/pingcap/tidb/parser/model" @@ -74,25 +73,16 @@ const ( DatabaseOptionCharset DatabaseOptionCollate DatabaseOptionEncryption - DatabaseOptionPlacementPrimaryRegion = DatabaseOptionType(PlacementOptionPrimaryRegion) - DatabaseOptionPlacementRegions = DatabaseOptionType(PlacementOptionRegions) - DatabaseOptionPlacementFollowerCount = DatabaseOptionType(PlacementOptionFollowerCount) - DatabaseOptionPlacementVoterCount = DatabaseOptionType(PlacementOptionVoterCount) - DatabaseOptionPlacementLearnerCount = DatabaseOptionType(PlacementOptionLearnerCount) - DatabaseOptionPlacementSchedule = DatabaseOptionType(PlacementOptionSchedule) - DatabaseOptionPlacementConstraints = DatabaseOptionType(PlacementOptionConstraints) - DatabaseOptionPlacementLeaderConstraints = DatabaseOptionType(PlacementOptionLeaderConstraints) - DatabaseOptionPlacementLearnerConstraints = DatabaseOptionType(PlacementOptionLearnerConstraints) - DatabaseOptionPlacementFollowerConstraints = DatabaseOptionType(PlacementOptionFollowerConstraints) - DatabaseOptionPlacementVoterConstraints = DatabaseOptionType(PlacementOptionVoterConstraints) - DatabaseOptionPlacementPolicy = DatabaseOptionType(PlacementOptionPolicy) + DatabaseSetTiFlashReplica + DatabaseOptionPlacementPolicy = DatabaseOptionType(PlacementOptionPolicy) ) // DatabaseOption represents database option. type DatabaseOption struct { - Tp DatabaseOptionType - Value string - UintValue uint64 + Tp DatabaseOptionType + Value string + UintValue uint64 + TiFlashReplica *TiFlashReplicaSpec } // Restore implements Node interface. @@ -110,13 +100,26 @@ func (n *DatabaseOption) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("ENCRYPTION") ctx.WritePlain(" = ") ctx.WriteString(n.Value) - case DatabaseOptionPlacementPrimaryRegion, DatabaseOptionPlacementRegions, DatabaseOptionPlacementFollowerCount, DatabaseOptionPlacementLeaderConstraints, DatabaseOptionPlacementLearnerCount, DatabaseOptionPlacementVoterCount, DatabaseOptionPlacementSchedule, DatabaseOptionPlacementConstraints, DatabaseOptionPlacementFollowerConstraints, DatabaseOptionPlacementVoterConstraints, DatabaseOptionPlacementLearnerConstraints, DatabaseOptionPlacementPolicy: + case DatabaseOptionPlacementPolicy: placementOpt := PlacementOption{ - Tp: PlacementOptionType(n.Tp), + Tp: PlacementOptionPolicy, UintValue: n.UintValue, StrValue: n.Value, } return placementOpt.Restore(ctx) + case DatabaseSetTiFlashReplica: + ctx.WriteKeyWord("SET TIFLASH REPLICA ") + ctx.WritePlainf("%d", n.TiFlashReplica.Count) + if len(n.TiFlashReplica.Labels) == 0 { + break + } + ctx.WriteKeyWord(" LOCATION LABELS ") + for i, v := range n.TiFlashReplica.Labels { + if i > 0 { + ctx.WritePlain(", ") + } + ctx.WriteString(v) + } default: return errors.Errorf("invalid DatabaseOptionType: %d", n.Tp) } @@ -172,6 +175,19 @@ type AlterDatabaseStmt struct { // Restore implements Node interface. func (n *AlterDatabaseStmt) Restore(ctx *format.RestoreCtx) error { + if ctx.Flags.HasSkipPlacementRuleForRestoreFlag() && n.isAllPlacementOptions() { + return nil + } + // If all options placement options and RestoreTiDBSpecialComment flag is on, + // we should restore the whole node in special comment. For example, the restore result should be: + // /*T![placement] ALTER DATABASE `db1` PLACEMENT POLICY = `p1` */ + // instead of + // ALTER DATABASE `db1` /*T![placement] PLACEMENT POLICY = `p1` */ + // because altering a database without any options is not a legal syntax in mysql + if n.isAllPlacementOptions() && ctx.Flags.HasTiDBSpecialCommentFlag() { + return restorePlacementStmtInSpecialComment(ctx, n) + } + ctx.WriteKeyWord("ALTER DATABASE") if !n.AlterDefaultDatabase { ctx.WritePlain(" ") @@ -197,6 +213,17 @@ func (n *AlterDatabaseStmt) Accept(v Visitor) (Node, bool) { return v.Leave(n) } +func (n *AlterDatabaseStmt) isAllPlacementOptions() bool { + for _, n := range n.Options { + switch n.Tp { + case DatabaseOptionPlacementPolicy: + default: + return false + } + } + return true +} + // DropDatabaseStmt is a statement to drop a database and all tables in the database. // See https://dev.mysql.com/doc/refman/5.7/en/drop-database.html type DropDatabaseStmt struct { @@ -526,8 +553,9 @@ func (n *ColumnOption) Restore(ctx *format.RestoreCtx) error { pkTp := n.PrimaryKeyTp.String() if len(pkTp) != 0 { ctx.WritePlain(" ") - ctx.WriteWithSpecialComments(tidb.FeatureIDClusteredIndex, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDClusteredIndex, func() error { ctx.WriteKeyWord(pkTp) + return nil }) } case ColumnOptionNotNull: @@ -601,11 +629,12 @@ func (n *ColumnOption) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("STORAGE ") ctx.WriteKeyWord(n.StrValue) case ColumnOptionAutoRandom: - ctx.WriteWithSpecialComments(tidb.FeatureIDAutoRandom, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDAutoRandom, func() error { ctx.WriteKeyWord("AUTO_RANDOM") if n.AutoRandomBitLength != types.UnspecifiedLength { ctx.WritePlainf("(%d)", n.AutoRandomBitLength) } + return nil }) default: return errors.New("An error occurred while splicing ColumnOption") @@ -661,8 +690,9 @@ type IndexOption struct { func (n *IndexOption) Restore(ctx *format.RestoreCtx) error { hasPrevOption := false if n.PrimaryKeyTp != model.PrimaryKeyTypeDefault { - ctx.WriteWithSpecialComments(tidb.FeatureIDClusteredIndex, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDClusteredIndex, func() error { ctx.WriteKeyWord(n.PrimaryKeyTp.String()) + return nil }) hasPrevOption = true } @@ -1199,6 +1229,10 @@ type DropPlacementPolicyStmt struct { // Restore implements Restore interface. func (n *DropPlacementPolicyStmt) Restore(ctx *format.RestoreCtx) error { + if ctx.Flags.HasTiDBSpecialCommentFlag() { + return restorePlacementStmtInSpecialComment(ctx, n) + } + ctx.WriteKeyWord("DROP PLACEMENT POLICY ") if n.IfExists { ctx.WriteKeyWord("IF EXISTS ") @@ -1444,6 +1478,10 @@ type CreatePlacementPolicyStmt struct { // Restore implements Node interface. func (n *CreatePlacementPolicyStmt) Restore(ctx *format.RestoreCtx) error { + if ctx.Flags.HasTiDBSpecialCommentFlag() { + return restorePlacementStmtInSpecialComment(ctx, n) + } + ctx.WriteKeyWord("CREATE ") if n.OrReplace { ctx.WriteKeyWord("OR REPLACE ") @@ -1690,8 +1728,9 @@ type DropIndexStmt struct { func (n *DropIndexStmt) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("DROP INDEX ") if n.IfExists { - ctx.WriteWithSpecialComments("", func() { + _ = ctx.WriteWithSpecialComments("", func() error { ctx.WriteKeyWord("IF EXISTS ") + return nil }) } ctx.WriteName(n.IndexName) @@ -1900,8 +1939,10 @@ type PlacementOption struct { } func (n *PlacementOption) Restore(ctx *format.RestoreCtx) error { - isSupported := true - fn := func() { + if ctx.Flags.HasSkipPlacementRuleForRestoreFlag() { + return nil + } + fn := func() error { switch n.Tp { case PlacementOptionPrimaryRegion: ctx.WriteKeyWord("PRIMARY_REGION ") @@ -1952,16 +1993,12 @@ func (n *PlacementOption) Restore(ctx *format.RestoreCtx) error { ctx.WritePlain("= ") ctx.WriteName(n.StrValue) default: - isSupported = false + return errors.Errorf("invalid PlacementOption: %d", n.Tp) } - } - if !isSupported { - return errors.Errorf("invalid PlacementOption: %d", n.Tp) + return nil } // WriteSpecialComment - ctx.WriteWithSpecialComments(tidb.FeatureIDPlacement, fn) - - return nil + return ctx.WriteWithSpecialComments(tidb.FeatureIDPlacement, fn) } type StatsOptionType int @@ -2014,23 +2051,12 @@ const ( TableOptionTableCheckSum TableOptionUnion TableOptionEncryption - TableOptionPlacementPrimaryRegion = TableOptionType(PlacementOptionPrimaryRegion) - TableOptionPlacementRegions = TableOptionType(PlacementOptionRegions) - TableOptionPlacementFollowerCount = TableOptionType(PlacementOptionFollowerCount) - TableOptionPlacementVoterCount = TableOptionType(PlacementOptionVoterCount) - TableOptionPlacementLearnerCount = TableOptionType(PlacementOptionLearnerCount) - TableOptionPlacementSchedule = TableOptionType(PlacementOptionSchedule) - TableOptionPlacementConstraints = TableOptionType(PlacementOptionConstraints) - TableOptionPlacementLeaderConstraints = TableOptionType(PlacementOptionLeaderConstraints) - TableOptionPlacementLearnerConstraints = TableOptionType(PlacementOptionLearnerConstraints) - TableOptionPlacementFollowerConstraints = TableOptionType(PlacementOptionFollowerConstraints) - TableOptionPlacementVoterConstraints = TableOptionType(PlacementOptionVoterConstraints) - TableOptionPlacementPolicy = TableOptionType(PlacementOptionPolicy) - TableOptionStatsBuckets = TableOptionType(StatsOptionBuckets) - TableOptionStatsTopN = TableOptionType(StatsOptionTopN) - TableOptionStatsColsChoice = TableOptionType(StatsOptionColsChoice) - TableOptionStatsColList = TableOptionType(StatsOptionColList) - TableOptionStatsSampleRate = TableOptionType(StatsOptionSampleRate) + TableOptionPlacementPolicy = TableOptionType(PlacementOptionPolicy) + TableOptionStatsBuckets = TableOptionType(StatsOptionBuckets) + TableOptionStatsTopN = TableOptionType(StatsOptionTopN) + TableOptionStatsColsChoice = TableOptionType(StatsOptionColsChoice) + TableOptionStatsColList = TableOptionType(StatsOptionColList) + TableOptionStatsSampleRate = TableOptionType(StatsOptionSampleRate) ) // RowFormat types @@ -2110,8 +2136,9 @@ func (n *TableOption) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord(n.StrValue) case TableOptionAutoIncrement: if n.BoolValue { - ctx.WriteWithSpecialComments(tidb.FeatureIDForceAutoInc, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDForceAutoInc, func() error { ctx.WriteKeyWord("FORCE") + return nil }) ctx.WritePlain(" ") } @@ -2119,22 +2146,25 @@ func (n *TableOption) Restore(ctx *format.RestoreCtx) error { ctx.WritePlain("= ") ctx.WritePlainf("%d", n.UintValue) case TableOptionAutoIdCache: - ctx.WriteWithSpecialComments(tidb.FeatureIDAutoIDCache, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDAutoIDCache, func() error { ctx.WriteKeyWord("AUTO_ID_CACHE ") ctx.WritePlain("= ") ctx.WritePlainf("%d", n.UintValue) + return nil }) case TableOptionAutoRandomBase: if n.BoolValue { - ctx.WriteWithSpecialComments(tidb.FeatureIDForceAutoInc, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDForceAutoInc, func() error { ctx.WriteKeyWord("FORCE") + return nil }) ctx.WritePlain(" ") } - ctx.WriteWithSpecialComments(tidb.FeatureIDAutoRandomBase, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDAutoRandomBase, func() error { ctx.WriteKeyWord("AUTO_RANDOM_BASE ") ctx.WritePlain("= ") ctx.WritePlainf("%d", n.UintValue) + return nil }) case TableOptionComment: ctx.WriteKeyWord("COMMENT ") @@ -2226,14 +2256,16 @@ func (n *TableOption) Restore(ctx *format.RestoreCtx) error { ctx.WritePlainf("%d", n.UintValue) } case TableOptionShardRowID: - ctx.WriteWithSpecialComments(tidb.FeatureIDTiDB, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDTiDB, func() error { ctx.WriteKeyWord("SHARD_ROW_ID_BITS ") ctx.WritePlainf("= %d", n.UintValue) + return nil }) case TableOptionPreSplitRegion: - ctx.WriteWithSpecialComments(tidb.FeatureIDTiDB, func() { + _ = ctx.WriteWithSpecialComments(tidb.FeatureIDTiDB, func() error { ctx.WriteKeyWord("PRE_SPLIT_REGIONS ") ctx.WritePlainf("= %d", n.UintValue) + return nil }) case TableOptionPackKeys: // TODO: not support @@ -2297,9 +2329,12 @@ func (n *TableOption) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("ENCRYPTION ") ctx.WritePlain("= ") ctx.WriteString(n.StrValue) - case TableOptionPlacementPrimaryRegion, TableOptionPlacementRegions, TableOptionPlacementFollowerCount, TableOptionPlacementLeaderConstraints, TableOptionPlacementLearnerCount, TableOptionPlacementVoterCount, TableOptionPlacementSchedule, TableOptionPlacementConstraints, TableOptionPlacementFollowerConstraints, TableOptionPlacementVoterConstraints, TableOptionPlacementLearnerConstraints, TableOptionPlacementPolicy: + case TableOptionPlacementPolicy: + if ctx.Flags.HasSkipPlacementRuleForRestoreFlag() { + return nil + } placementOpt := PlacementOption{ - Tp: PlacementOptionType(n.Tp), + Tp: PlacementOptionPolicy, UintValue: n.UintValue, StrValue: n.StrValue, } @@ -2659,8 +2694,25 @@ func (n *AlterOrderItem) Restore(ctx *format.RestoreCtx) error { return nil } +func (n *AlterTableSpec) IsAllPlacementRule() bool { + switch n.Tp { + case AlterTablePartitionAttributes, AlterTablePartitionOptions, AlterTableOption, AlterTableAttributes: + for _, o := range n.Options { + if o.Tp != TableOptionPlacementPolicy { + return false + } + } + return true + default: + return false + } +} + // Restore implements Node interface. func (n *AlterTableSpec) Restore(ctx *format.RestoreCtx) error { + if n.IsAllPlacementRule() && ctx.Flags.HasSkipPlacementRuleForRestoreFlag() { + return nil + } switch n.Tp { case AlterTableSetTiFlashReplica: ctx.WriteKeyWord("SET TIFLASH REPLICA ") @@ -2923,17 +2975,37 @@ func (n *AlterTableSpec) Restore(ctx *format.RestoreCtx) error { ctx.WritePlainf("%d", n.Num) } case AlterTablePartitionOptions: - ctx.WriteKeyWord("PARTITION ") - ctx.WriteName(n.PartitionNames[0].O) - ctx.WritePlain(" ") + restoreWithoutSpecialComment := func() error { + origFlags := ctx.Flags + defer func() { + ctx.Flags = origFlags + }() + ctx.Flags &= ^format.RestoreTiDBSpecialComment + ctx.WriteKeyWord("PARTITION ") + ctx.WriteName(n.PartitionNames[0].O) + ctx.WritePlain(" ") - for i, opt := range n.Options { - if i != 0 { - ctx.WritePlain(" ") - } - if err := opt.Restore(ctx); err != nil { - return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.Options[%d] for PARTITION `%s`", i, n.PartitionNames[0].O) + for i, opt := range n.Options { + if i != 0 { + ctx.WritePlain(" ") + } + if err := opt.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.Options[%d] for PARTITION `%s`", i, n.PartitionNames[0].O) + } } + return nil + } + + var err error + if ctx.Flags.HasTiDBSpecialCommentFlag() { + // AlterTablePartitionOptions now only supports placement options, so add put all options to special comment + err = ctx.WriteWithSpecialComments(tidb.FeatureIDPlacement, restoreWithoutSpecialComment) + } else { + err = restoreWithoutSpecialComment() + } + + if err != nil { + return err } case AlterTablePartitionAttributes: ctx.WriteKeyWord("PARTITION ") @@ -3229,13 +3301,36 @@ type AlterTableStmt struct { Specs []*AlterTableSpec } +func (n *AlterTableStmt) HaveOnlyPlacementOptions() bool { + for _, n := range n.Specs { + if n.Tp == AlterTablePartitionOptions { + if !n.IsAllPlacementRule() { + return false + } + } else { + return false + } + + } + return true +} + // Restore implements Node interface. func (n *AlterTableStmt) Restore(ctx *format.RestoreCtx) error { + if ctx.Flags.HasSkipPlacementRuleForRestoreFlag() && n.HaveOnlyPlacementOptions() { + return nil + } ctx.WriteKeyWord("ALTER TABLE ") if err := n.Table.Restore(ctx); err != nil { return errors.Annotate(err, "An error occurred while restore AlterTableStmt.Table") } - for i, spec := range n.Specs { + var specs []*AlterTableSpec + for _, spec := range n.Specs { + if !(spec.IsAllPlacementRule() && ctx.Flags.HasSkipPlacementRuleForRestoreFlag()) { + specs = append(specs, spec) + } + } + for i, spec := range specs { if i == 0 || spec.Tp == AlterTablePartition || spec.Tp == AlterTableRemovePartitioning || spec.Tp == AlterTableImportTablespace || spec.Tp == AlterTableDiscardTablespace { ctx.WritePlain(" ") } else { @@ -3945,6 +4040,13 @@ type AlterPlacementPolicyStmt struct { } func (n *AlterPlacementPolicyStmt) Restore(ctx *format.RestoreCtx) error { + if ctx.Flags.HasSkipPlacementRuleForRestoreFlag() { + return nil + } + if ctx.Flags.HasTiDBSpecialCommentFlag() { + return restorePlacementStmtInSpecialComment(ctx, n) + } + ctx.WriteKeyWord("ALTER PLACEMENT POLICY ") if n.IfExists { ctx.WriteKeyWord("IF EXISTS ") @@ -4009,3 +4111,16 @@ func (n *AlterSequenceStmt) Accept(v Visitor) (Node, bool) { n.Name = node.(*TableName) return v.Leave(n) } + +func restorePlacementStmtInSpecialComment(ctx *format.RestoreCtx, n DDLNode) error { + origFlags := ctx.Flags + defer func() { + ctx.Flags = origFlags + }() + + ctx.Flags |= format.RestoreTiDBSpecialComment + return ctx.WriteWithSpecialComments(tidb.FeatureIDPlacement, func() error { + ctx.Flags &= ^format.RestoreTiDBSpecialComment + return n.Restore(ctx) + }) +} diff --git a/parser/ast/ddl_test.go b/parser/ast/ddl_test.go index af4ecc5a6ca85..beb3a27b97370 100644 --- a/parser/ast/ddl_test.go +++ b/parser/ast/ddl_test.go @@ -533,6 +533,9 @@ func TestAlterTableSpecRestore(t *testing.T) { {"add stats_extended if not exists s1 dependency(a,b)", "ADD STATS_EXTENDED IF NOT EXISTS `s1` DEPENDENCY(`a`, `b`)"}, {"drop stats_extended s1", "DROP STATS_EXTENDED `s1`"}, {"drop stats_extended if exists s1", "DROP STATS_EXTENDED IF EXISTS `s1`"}, + {"placement policy p1", "PLACEMENT POLICY = `p1`"}, + {"placement policy p1 comment='aaa'", "PLACEMENT POLICY = `p1` COMMENT = 'aaa'"}, + {"partition p0 placement policy p1", "PARTITION `p0` PLACEMENT POLICY = `p1`"}, } extractNodeFunc := func(node Node) Node { return node.(*AlterTableStmt).Specs[0] @@ -540,6 +543,19 @@ func TestAlterTableSpecRestore(t *testing.T) { runNodeRestoreTest(t, testCases, "ALTER TABLE t %s", extractNodeFunc) } +func TestAlterTableWithSpecialCommentRestore(t *testing.T) { + testCases := []NodeRestoreTestCase{ + {"placement policy p1", "/*T![placement] PLACEMENT POLICY = `p1` */"}, + {"placement policy p1 comment='aaa'", "/*T![placement] PLACEMENT POLICY = `p1` */ COMMENT = 'aaa'"}, + {"partition p0 placement policy p1", "/*T![placement] PARTITION `p0` PLACEMENT POLICY = `p1` */"}, + } + + extractNodeFunc := func(node Node) Node { + return node.(*AlterTableStmt).Specs[0] + } + runNodeRestoreTestWithFlags(t, testCases, "ALTER TABLE t %s", extractNodeFunc, format.DefaultRestoreFlags|format.RestoreTiDBSpecialComment) +} + func TestAlterTableOptionRestore(t *testing.T) { testCases := []NodeRestoreTestCase{ {"ALTER TABLE t ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8", "ALTER TABLE `t` ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8"}, @@ -628,3 +644,186 @@ func TestDropIndexRestore(t *testing.T) { runNodeRestoreTestWithFlags(t, testCases, "%s", extractNodeFunc, ca.flags) } } + +func TestAlterDatabaseRestore(t *testing.T) { + sourceSQL1 := "alter database db1 charset='ascii'" + sourceSQL2 := "alter database db1 collate='ascii_bin'" + sourceSQL3 := "alter database db1 placement policy p1" + sourceSQL4 := "alter database db1 placement policy p1 charset='ascii'" + + cases := []struct { + sourceSQL string + flags format.RestoreFlags + expectSQL string + }{ + {sourceSQL1, format.DefaultRestoreFlags, "ALTER DATABASE `db1` CHARACTER SET = ascii"}, + {sourceSQL1, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "ALTER DATABASE `db1` CHARACTER SET = ascii"}, + {sourceSQL2, format.DefaultRestoreFlags, "ALTER DATABASE `db1` COLLATE = ascii_bin"}, + {sourceSQL2, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "ALTER DATABASE `db1` COLLATE = ascii_bin"}, + {sourceSQL3, format.DefaultRestoreFlags, "ALTER DATABASE `db1` PLACEMENT POLICY = `p1`"}, + {sourceSQL3, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] ALTER DATABASE `db1` PLACEMENT POLICY = `p1` */"}, + {sourceSQL4, format.DefaultRestoreFlags, "ALTER DATABASE `db1` PLACEMENT POLICY = `p1` CHARACTER SET = ascii"}, + {sourceSQL4, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "ALTER DATABASE `db1` /*T![placement] PLACEMENT POLICY = `p1` */ CHARACTER SET = ascii"}, + } + + extractNodeFunc := func(node Node) Node { + return node + } + + for _, ca := range cases { + testCases := []NodeRestoreTestCase{ + {ca.sourceSQL, ca.expectSQL}, + } + runNodeRestoreTestWithFlags(t, testCases, "%s", extractNodeFunc, ca.flags) + } +} + +func TestCreatePlacementPolicyRestore(t *testing.T) { + sourceSQL1 := "create placement policy p1 primary_region=\"r1\" regions='r1,r2' followers=1" + sourceSQL2 := "create placement policy if not exists p1 primary_region=\"r1\" regions='r1,r2' followers=1" + sourceSQL3 := "create or replace placement policy p1 followers=1" + cases := []struct { + sourceSQL string + flags format.RestoreFlags + expectSQL string + }{ + {sourceSQL1, format.DefaultRestoreFlags, "CREATE PLACEMENT POLICY `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1"}, + {sourceSQL1, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] CREATE PLACEMENT POLICY `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1 */"}, + {sourceSQL2, format.DefaultRestoreFlags, "CREATE PLACEMENT POLICY IF NOT EXISTS `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1"}, + {sourceSQL2, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] CREATE PLACEMENT POLICY IF NOT EXISTS `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1 */"}, + {sourceSQL3, format.DefaultRestoreFlags, "CREATE OR REPLACE PLACEMENT POLICY `p1` FOLLOWERS = 1"}, + {sourceSQL3, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] CREATE OR REPLACE PLACEMENT POLICY `p1` FOLLOWERS = 1 */"}, + } + + extractNodeFunc := func(node Node) Node { + return node + } + + for _, ca := range cases { + testCases := []NodeRestoreTestCase{ + {ca.sourceSQL, ca.expectSQL}, + } + runNodeRestoreTestWithFlags(t, testCases, "%s", extractNodeFunc, ca.flags) + } +} + +func TestAlterPlacementPolicyRestore(t *testing.T) { + sourceSQL := "alter placement policy p1 primary_region=\"r1\" regions='r1,r2' followers=1" + cases := []struct { + flags format.RestoreFlags + expectSQL string + }{ + {format.DefaultRestoreFlags, "ALTER PLACEMENT POLICY `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1"}, + {format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] ALTER PLACEMENT POLICY `p1` PRIMARY_REGION = 'r1' REGIONS = 'r1,r2' FOLLOWERS = 1 */"}, + } + + extractNodeFunc := func(node Node) Node { + return node + } + + for _, ca := range cases { + testCases := []NodeRestoreTestCase{ + {sourceSQL, ca.expectSQL}, + } + runNodeRestoreTestWithFlags(t, testCases, "%s", extractNodeFunc, ca.flags) + } +} + +func TestDropPlacementPolicyRestore(t *testing.T) { + sourceSQL1 := "drop placement policy p1" + sourceSQL2 := "drop placement policy if exists p1" + cases := []struct { + sourceSQL string + flags format.RestoreFlags + expectSQL string + }{ + {sourceSQL1, format.DefaultRestoreFlags, "DROP PLACEMENT POLICY `p1`"}, + {sourceSQL1, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] DROP PLACEMENT POLICY `p1` */"}, + {sourceSQL2, format.DefaultRestoreFlags, "DROP PLACEMENT POLICY IF EXISTS `p1`"}, + {sourceSQL2, format.DefaultRestoreFlags | format.RestoreTiDBSpecialComment, "/*T![placement] DROP PLACEMENT POLICY IF EXISTS `p1` */"}, + } + + extractNodeFunc := func(node Node) Node { + return node + } + + for _, ca := range cases { + testCases := []NodeRestoreTestCase{ + {ca.sourceSQL, ca.expectSQL}, + } + runNodeRestoreTestWithFlags(t, testCases, "%s", extractNodeFunc, ca.flags) + } +} + +func TestRemovePlacementRestore(t *testing.T) { + f := format.DefaultRestoreFlags | format.SkipPlacementRuleForRestore + cases := []struct { + sourceSQL string + expectSQL string + }{ + { + "CREATE TABLE t1 (id BIGINT NOT NULL PRIMARY KEY auto_increment, b varchar(255)) PLACEMENT POLICY=placement1;", + "CREATE TABLE `t1` (`id` BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,`b` VARCHAR(255)) ", + }, + { + "CREATE TABLE `t1` (\n `a` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![placement] PLACEMENT POLICY=`p2` */", + "CREATE TABLE `t1` (`a` INT(11) DEFAULT NULL) ENGINE = InnoDB DEFAULT CHARACTER SET = UTF8MB4 DEFAULT COLLATE = UTF8MB4_BIN ", + }, + { + "CREATE TABLE t4 (firstname VARCHAR(25) NOT NULL,lastname VARCHAR(25) NOT NULL,username VARCHAR(16) NOT NULL,email VARCHAR(35),joined DATE NOT NULL) PARTITION BY RANGE( YEAR(joined) ) (PARTITION p0 VALUES LESS THAN (1960) PLACEMENT POLICY=p1,PARTITION p1 VALUES LESS THAN (1970),PARTITION p2 VALUES LESS THAN (1980),PARTITION p3 VALUES LESS THAN (1990),PARTITION p4 VALUES LESS THAN MAXVALUE);", + "CREATE TABLE `t4` (`firstname` VARCHAR(25) NOT NULL,`lastname` VARCHAR(25) NOT NULL,`username` VARCHAR(16) NOT NULL,`email` VARCHAR(35),`joined` DATE NOT NULL) PARTITION BY RANGE (YEAR(`joined`)) (PARTITION `p0` VALUES LESS THAN (1960) ,PARTITION `p1` VALUES LESS THAN (1970),PARTITION `p2` VALUES LESS THAN (1980),PARTITION `p3` VALUES LESS THAN (1990),PARTITION `p4` VALUES LESS THAN (MAXVALUE))", + }, + { + "ALTER TABLE t3 PLACEMENT POLICY=DEFAULT;", + "ALTER TABLE `t3`", + }, + { + "ALTER TABLE t1 PLACEMENT POLICY=p10", + "ALTER TABLE `t1`", + }, + { + "ALTER TABLE t1 PLACEMENT POLICY=p10, add d text(50)", + "ALTER TABLE `t1` ADD COLUMN `d` TEXT(50)", + }, + { + "alter table tp PARTITION p1 placement policy p2", + "", + }, + { + "alter table t add d text(50) PARTITION p1 placement policy p2", + "ALTER TABLE `t` ADD COLUMN `d` TEXT(50)", + }, + { + "alter table tp set tiflash replica 1 PARTITION p1 placement policy p2", + "ALTER TABLE `tp` SET TIFLASH REPLICA 1", + }, + { + "ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY SET DEFAULT", + "", + }, + + { + "ALTER DATABASE TestResetPlacementDB PLACEMENT POLICY p1 charset utf8mb4", + "ALTER DATABASE `TestResetPlacementDB` CHARACTER SET = utf8mb4", + }, + { + "/*T![placement] ALTER DATABASE `db1` PLACEMENT POLICY = `p1` */", + "", + }, + { + "ALTER PLACEMENT POLICY p3 PRIMARY_REGION='us-east-1' REGIONS='us-east-1,us-east-2,us-west-1';", + "", + }, + } + + extractNodeFunc := func(node Node) Node { + return node + } + + for _, ca := range cases { + testCases := []NodeRestoreTestCase{ + {ca.sourceSQL, ca.expectSQL}, + } + runNodeRestoreTestWithFlagsStmtChange(t, testCases, "%s", extractNodeFunc, f) + } +} diff --git a/parser/ast/dml.go b/parser/ast/dml.go index cd29e293ba875..1da250553bac0 100644 --- a/parser/ast/dml.go +++ b/parser/ast/dml.go @@ -119,7 +119,9 @@ func (*Join) resultSet() {} // We get (t1 join t3) left join t2, the semantics is correct. func NewCrossJoin(left, right ResultSetNode) (n *Join) { rj, ok := right.(*Join) - if !ok || rj.Right == nil { + // don't break the explicit parents name scope constraints. + // this kind of join re-order can be done in logical-phase after the name resolution. + if !ok || rj.Right == nil || rj.ExplicitParens { return &Join{Left: left, Right: right, Tp: CrossJoin} } @@ -690,7 +692,9 @@ type SelectField struct { // Auxiliary stands for if this field is auxiliary. // When we add a Field into SelectField list which is used for having/orderby clause but the field is not in select clause, // we should set its Auxiliary to true. Then the TrimExec will trim the field. - Auxiliary bool + Auxiliary bool + AuxiliaryColInAgg bool + AuxiliaryColInOrderBy bool } // Restore implements Node interface. @@ -2589,6 +2593,7 @@ const ( ShowPrivileges ShowErrors ShowBindings + ShowBindingCacheStatus ShowPumpStatus ShowDrainerStatus ShowOpenTables @@ -2915,6 +2920,8 @@ func (n *ShowStmt) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("SESSION ") } ctx.WriteKeyWord("BINDINGS") + case ShowBindingCacheStatus: + ctx.WriteKeyWord("BINDING_CACHE STATUS") case ShowPumpStatus: ctx.WriteKeyWord("PUMP STATUS") case ShowDrainerStatus: diff --git a/parser/ast/dml_test.go b/parser/ast/dml_test.go index 624717d2d7c54..f7bfd78e25901 100644 --- a/parser/ast/dml_test.go +++ b/parser/ast/dml_test.go @@ -17,6 +17,7 @@ import ( "testing" . "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/format" "github.com/stretchr/testify/require" ) @@ -228,17 +229,17 @@ func TestJoinRestore(t *testing.T) { //{"(select a from t) t1 join t t2, t3;", "((SELECT `a` FROM `t`) AS `t1` JOIN `t` AS `t2`) JOIN `t3`"}, } testChangedCases := []NodeRestoreTestCase{ - {"(a al left join b bl on al.a1 > bl.b1) join (a ar right join b br on ar.a1 > br.b1)", "((`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN `b` AS `br`) LEFT JOIN `a` AS `ar` ON `ar`.`a1`>`br`.`b1`"}, + {"(a al left join b bl on al.a1 > bl.b1) join (a ar right join b br on ar.a1 > br.b1)", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"}, {"a al left join b bl on al.a1 > bl.b1, a ar right join b br on ar.a1 > br.b1", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"}, - {"t1 join (t2 right join t3 on t2.a > t3.a join (t4 right join t5 on t4.a > t5.a))", "(((`t1` JOIN `t2`) RIGHT JOIN `t3` ON `t2`.`a`>`t3`.`a`) JOIN `t5`) LEFT JOIN `t4` ON `t4`.`a`>`t5`.`a`"}, + {"t1 join (t2 right join t3 on t2.a > t3.a join (t4 right join t5 on t4.a > t5.a))", "`t1` JOIN ((`t2` RIGHT JOIN `t3` ON `t2`.`a`>`t3`.`a`) JOIN (`t4` RIGHT JOIN `t5` ON `t4`.`a`>`t5`.`a`))"}, {"t1 join t2 right join t3 on t2.a=t3.a", "(`t1` JOIN `t2`) RIGHT JOIN `t3` ON `t2`.`a`=`t3`.`a`"}, - {"t1 join (t2 right join t3 on t2.a=t3.a)", "(`t1` JOIN `t3`) LEFT JOIN `t2` ON `t2`.`a`=`t3`.`a`"}, + {"t1 join (t2 right join t3 on t2.a=t3.a)", "`t1` JOIN (`t2` RIGHT JOIN `t3` ON `t2`.`a`=`t3`.`a`)"}, } extractNodeFunc := func(node Node) Node { return node.(*SelectStmt).From.TableRefs } runNodeRestoreTest(t, testCases, "select * from %s", extractNodeFunc) - runNodeRestoreTestWithFlagsStmtChange(t, testChangedCases, "select * from %s", extractNodeFunc) + runNodeRestoreTestWithFlagsStmtChange(t, testChangedCases, "select * from %s", extractNodeFunc, format.DefaultRestoreFlags) } func TestTableRefsClauseRestore(t *testing.T) { diff --git a/parser/ast/expressions_test.go b/parser/ast/expressions_test.go index 7f01c84c1049f..27dd16487d2e9 100644 --- a/parser/ast/expressions_test.go +++ b/parser/ast/expressions_test.go @@ -380,7 +380,6 @@ func TestVariableExpr(t *testing.T) { {"@``", "@``"}, {"@", "@``"}, {"@@``", "@@``"}, - {"@@", "@@``"}, {"@@var", "@@`var`"}, {"@@global.b='foo'", "@@GLOBAL.`b`=_UTF8MB4'foo'"}, {"@@session.'C'", "@@SESSION.`c`"}, diff --git a/parser/ast/functions.go b/parser/ast/functions.go index 7775f3dbc2029..9779f7ba446b6 100644 --- a/parser/ast/functions.go +++ b/parser/ast/functions.go @@ -289,6 +289,7 @@ const ( UUIDToBin = "uuid_to_bin" BinToUUID = "bin_to_uuid" VitessHash = "vitess_hash" + TiDBShard = "tidb_shard" // get_lock() and release_lock() is parsed but do nothing. // It is used for preventing error in Ruby's activerecord migrations. GetLock = "get_lock" diff --git a/parser/ast/misc.go b/parser/ast/misc.go index a12d93ff05413..ab42cfbc13192 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/parser/auth" + "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/format" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -50,6 +51,7 @@ var ( _ StmtNode = &KillStmt{} _ StmtNode = &CreateBindingStmt{} _ StmtNode = &DropBindingStmt{} + _ StmtNode = &SetBindingStmt{} _ StmtNode = &ShutdownStmt{} _ StmtNode = &RestartStmt{} _ StmtNode = &RenameUserStmt{} @@ -1680,6 +1682,67 @@ func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) { return v.Leave(n) } +// BindingStatusType defines the status type for the binding +type BindingStatusType int8 + +// Binding status types. +const ( + BindingStatusTypeEnabled BindingStatusType = iota + BindingStatusTypeDisabled +) + +// SetBindingStmt sets sql binding status. +type SetBindingStmt struct { + stmtNode + + BindingStatusType BindingStatusType + OriginNode StmtNode + HintedNode StmtNode +} + +func (n *SetBindingStmt) Restore(ctx *format.RestoreCtx) error { + ctx.WriteKeyWord("SET ") + ctx.WriteKeyWord("BINDING ") + switch n.BindingStatusType { + case BindingStatusTypeEnabled: + ctx.WriteKeyWord("ENABLED ") + case BindingStatusTypeDisabled: + ctx.WriteKeyWord("DISABLED ") + } + ctx.WriteKeyWord("FOR ") + if err := n.OriginNode.Restore(ctx); err != nil { + return errors.Trace(err) + } + if n.HintedNode != nil { + ctx.WriteKeyWord(" USING ") + if err := n.HintedNode.Restore(ctx); err != nil { + return errors.Trace(err) + } + } + return nil +} + +func (n *SetBindingStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SetBindingStmt) + origNode, ok := n.OriginNode.Accept(v) + if !ok { + return n, false + } + n.OriginNode = origNode.(StmtNode) + if n.HintedNode != nil { + hintedNode, ok := n.HintedNode.Accept(v) + if !ok { + return n, false + } + n.HintedNode = hintedNode.(StmtNode) + } + return v.Leave(n) +} + // Extended statistics types. const ( StatsTypeCardinality uint8 = iota @@ -3367,7 +3430,7 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { ctx.WritePlainf("%d", n.HintData.(uint64)) case "nth_plan": ctx.WritePlainf("%d", n.HintData.(int64)) - case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "merge_join", "inl_join", "broadcast_join", "broadcast_join_local", "inl_hash_join", "inl_merge_join": + case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "merge_join", "inl_join", "broadcast_join", "inl_hash_join", "inl_merge_join": for i, table := range n.Tables { if i != 0 { ctx.WritePlain(", ") @@ -3431,6 +3494,33 @@ func (n *TableOptimizerHint) Accept(v Visitor) (Node, bool) { return v.Leave(n) } +// TextString represent a string, it can be a binary literal. +type TextString struct { + Value string + IsBinaryLiteral bool +} + +// TransformTextStrings converts a slice of TextString to strings. +// This is only used by enum/set strings. +func TransformTextStrings(ts []*TextString, _ string) []string { + // The UTF-8 encoding rather than other encoding is used + // because parser is not possible to determine the "real" + // charset that a binary literal string should be converted to. + enc := charset.EncodingUTF8Impl + ret := make([]string, 0, len(ts)) + for _, t := range ts { + if !t.IsBinaryLiteral { + ret = append(ret, t.Value) + } else { + // Validate the binary literal string. + // See https://github.com/pingcap/tidb/issues/30740. + r, _ := enc.Transform(nil, charset.HackSlice(t.Value), charset.OpDecodeNoErr) + ret = append(ret, charset.HackString(r)) + } + } + return ret +} + type BinaryLiteral interface { ToString() string } diff --git a/parser/ast/util_test.go b/parser/ast/util_test.go index d8cb06eee448c..015f5dc5cc4eb 100644 --- a/parser/ast/util_test.go +++ b/parser/ast/util_test.go @@ -120,7 +120,7 @@ type nodeTextCleaner struct { // Enter implements Visitor interface. func (checker *nodeTextCleaner) Enter(in Node) (out Node, skipChildren bool) { - in.SetText("") + in.SetText(nil, "") in.SetOriginTextPosition(0) switch node := in.(type) { case *Constraint: @@ -190,7 +190,7 @@ func runNodeRestoreTestWithFlags(t *testing.T, nodeTestCases []NodeRestoreTestCa // runNodeRestoreTestWithFlagsStmtChange likes runNodeRestoreTestWithFlags but not check if the ASTs are same. // Sometimes the AST are different and it's expected. -func runNodeRestoreTestWithFlagsStmtChange(t *testing.T, nodeTestCases []NodeRestoreTestCase, template string, extractNodeFunc func(node Node) Node) { +func runNodeRestoreTestWithFlagsStmtChange(t *testing.T, nodeTestCases []NodeRestoreTestCase, template string, extractNodeFunc func(node Node) Node, flags RestoreFlags) { p := parser.New() p.EnableWindowFunc(true) for _, testCase := range nodeTestCases { @@ -200,7 +200,7 @@ func runNodeRestoreTestWithFlagsStmtChange(t *testing.T, nodeTestCases []NodeRes comment := fmt.Sprintf("source %#v", testCase) require.NoError(t, err, comment) var sb strings.Builder - err = extractNodeFunc(stmt).Restore(NewRestoreCtx(DefaultRestoreFlags, &sb)) + err = extractNodeFunc(stmt).Restore(NewRestoreCtx(flags, &sb)) require.NoError(t, err, comment) restoreSql := fmt.Sprintf(template, sb.String()) comment = fmt.Sprintf("source %#v; restore %v", testCase, restoreSql) diff --git a/parser/auth/auth.go b/parser/auth/auth.go index 5657c6c276646..884f11c2f9d53 100644 --- a/parser/auth/auth.go +++ b/parser/auth/auth.go @@ -15,10 +15,14 @@ package auth import ( "fmt" - "github.com/pingcap/tidb/parser/format" ) +const ( + UserNameMaxLength = 32 + HostNameMaxLength = 255 +) + // UserIdentity represents username and hostname. type UserIdentity struct { Username string diff --git a/parser/charset/charset.go b/parser/charset/charset.go index 0fdff1b75c13e..728b21dd56d94 100644 --- a/parser/charset/charset.go +++ b/parser/charset/charset.go @@ -52,13 +52,14 @@ var collationsIDMap = make(map[int]*Collation) var collationsNameMap = make(map[string]*Collation) var supportedCollations = make([]*Collation, 0, len(supportedCollationNames)) -// All the supported charsets should be in the following table. -var charsetInfos = map[string]*Charset{ +// CharacterSetInfos: All the supported charsets should be in the following table. +var CharacterSetInfos = map[string]*Charset{ CharsetUTF8: {CharsetUTF8, CollationUTF8, make(map[string]*Collation), "UTF-8 Unicode", 3}, CharsetUTF8MB4: {CharsetUTF8MB4, CollationUTF8MB4, make(map[string]*Collation), "UTF-8 Unicode", 4}, CharsetASCII: {CharsetASCII, CollationASCII, make(map[string]*Collation), "US ASCII", 1}, CharsetLatin1: {CharsetLatin1, CollationLatin1, make(map[string]*Collation), "Latin1", 1}, CharsetBin: {CharsetBin, CollationBin, make(map[string]*Collation), "binary", 1}, + CharsetGBK: {CharsetGBK, CollationGBKBin, make(map[string]*Collation), "Chinese Internal Code Specification", 2}, } // All the names supported collations should be in the following table. @@ -68,6 +69,7 @@ var supportedCollationNames = map[string]struct{}{ CollationASCII: {}, CollationLatin1: {}, CollationBin: {}, + CollationGBKBin: {}, } // TiFlashSupportedCharsets is a map which contains TiFlash supports charsets. @@ -81,8 +83,8 @@ var TiFlashSupportedCharsets = map[string]struct{}{ // GetSupportedCharsets gets descriptions for all charsets supported so far. func GetSupportedCharsets() []*Charset { - charsets := make([]*Charset, 0, len(charsetInfos)) - for _, ch := range charsetInfos { + charsets := make([]*Charset, 0, len(CharacterSetInfos)) + for _, ch := range CharacterSetInfos { charsets = append(charsets, ch) } @@ -144,7 +146,7 @@ func GetDefaultCharsetAndCollate() (string, string) { // GetCharsetInfo returns charset and collation for cs as name. func GetCharsetInfo(cs string) (*Charset, error) { - if c, ok := charsetInfos[strings.ToLower(cs)]; ok { + if c, ok := CharacterSetInfos[strings.ToLower(cs)]; ok { return c, nil } @@ -212,7 +214,8 @@ const ( // CollationLatin1 is the default collation for CharsetLatin1. CollationLatin1 = "latin1_bin" - CollationGBKBin = "gbk_bin" + CollationGBKBin = "gbk_bin" + CollationGBKChineseCI = "gbk_chinese_ci" CharsetARMSCII8 = "armscii8" CharsetBig5 = "big5" @@ -280,7 +283,7 @@ var collations = []*Collation{ {25, "greek", "greek_general_ci", true}, {26, "cp1250", "cp1250_general_ci", true}, {27, "latin2", "latin2_croatian_ci", false}, - {28, "gbk", "gbk_chinese_ci", true}, + {28, "gbk", "gbk_chinese_ci", false}, {29, "cp1257", "cp1257_lithuanian_ci", false}, {30, "latin5", "latin5_turkish_ci", true}, {31, "latin1", "latin1_german2_ci", false}, @@ -328,6 +331,7 @@ var collations = []*Collation{ {73, "keybcs2", "keybcs2_bin", false}, {74, "koi8r", "koi8r_bin", false}, {75, "koi8u", "koi8u_bin", false}, + {76, "utf8", "utf8_tolower_ci", false}, {77, "latin2", "latin2_bin", false}, {78, "latin5", "latin5_bin", false}, {79, "latin7", "latin7_bin", false}, @@ -338,7 +342,7 @@ var collations = []*Collation{ {84, "big5", "big5_bin", false}, {85, "euckr", "euckr_bin", false}, {86, "gb2312", "gb2312_bin", false}, - {87, "gbk", "gbk_bin", false}, + {87, "gbk", "gbk_bin", true}, {88, "sjis", "sjis_bin", false}, {89, "tis620", "tis620_bin", false}, {90, "ucs2", "ucs2_bin", false}, @@ -473,20 +477,76 @@ var collations = []*Collation{ {245, "utf8mb4", "utf8mb4_croatian_ci", false}, {246, "utf8mb4", "utf8mb4_unicode_520_ci", false}, {247, "utf8mb4", "utf8mb4_vietnamese_ci", false}, + {248, "gb18030", "gb18030_chinese_ci", false}, + {249, "gb18030", "gb18030_bin", true}, + {250, "gb18030", "gb18030_unicode_520_ci", false}, {255, "utf8mb4", "utf8mb4_0900_ai_ci", false}, + {256, "utf8mb4", "utf8mb4_de_pb_0900_ai_ci", false}, + {257, "utf8mb4", "utf8mb4_is_0900_ai_ci", false}, + {258, "utf8mb4", "utf8mb4_lv_0900_ai_ci", false}, + {259, "utf8mb4", "utf8mb4_ro_0900_ai_ci", false}, + {260, "utf8mb4", "utf8mb4_sl_0900_ai_ci", false}, + {261, "utf8mb4", "utf8mb4_pl_0900_ai_ci", false}, + {262, "utf8mb4", "utf8mb4_et_0900_ai_ci", false}, + {263, "utf8mb4", "utf8mb4_es_0900_ai_ci", false}, + {264, "utf8mb4", "utf8mb4_sv_0900_ai_ci", false}, + {265, "utf8mb4", "utf8mb4_tr_0900_ai_ci", false}, + {266, "utf8mb4", "utf8mb4_cs_0900_ai_ci", false}, + {267, "utf8mb4", "utf8mb4_da_0900_ai_ci", false}, + {268, "utf8mb4", "utf8mb4_lt_0900_ai_ci", false}, + {269, "utf8mb4", "utf8mb4_sk_0900_ai_ci", false}, + {270, "utf8mb4", "utf8mb4_es_trad_0900_ai_ci", false}, + {271, "utf8mb4", "utf8mb4_la_0900_ai_ci", false}, + {273, "utf8mb4", "utf8mb4_eo_0900_ai_ci", false}, + {274, "utf8mb4", "utf8mb4_hu_0900_ai_ci", false}, + {275, "utf8mb4", "utf8mb4_hr_0900_ai_ci", false}, + {277, "utf8mb4", "utf8mb4_vi_0900_ai_ci", false}, + {278, "utf8mb4", "utf8mb4_0900_as_cs", false}, + {279, "utf8mb4", "utf8mb4_de_pb_0900_as_cs", false}, + {280, "utf8mb4", "utf8mb4_is_0900_as_cs", false}, + {281, "utf8mb4", "utf8mb4_lv_0900_as_cs", false}, + {282, "utf8mb4", "utf8mb4_ro_0900_as_cs", false}, + {283, "utf8mb4", "utf8mb4_sl_0900_as_cs", false}, + {284, "utf8mb4", "utf8mb4_pl_0900_as_cs", false}, + {285, "utf8mb4", "utf8mb4_et_0900_as_cs", false}, + {286, "utf8mb4", "utf8mb4_es_0900_as_cs", false}, + {287, "utf8mb4", "utf8mb4_sv_0900_as_cs", false}, + {288, "utf8mb4", "utf8mb4_tr_0900_as_cs", false}, + {289, "utf8mb4", "utf8mb4_cs_0900_as_cs", false}, + {290, "utf8mb4", "utf8mb4_da_0900_as_cs", false}, + {291, "utf8mb4", "utf8mb4_lt_0900_as_cs", false}, + {292, "utf8mb4", "utf8mb4_sk_0900_as_cs", false}, + {293, "utf8mb4", "utf8mb4_es_trad_0900_as_cs", false}, + {294, "utf8mb4", "utf8mb4_la_0900_as_cs", false}, + {296, "utf8mb4", "utf8mb4_eo_0900_as_cs", false}, + {297, "utf8mb4", "utf8mb4_hu_0900_as_cs", false}, + {298, "utf8mb4", "utf8mb4_hr_0900_as_cs", false}, + {300, "utf8mb4", "utf8mb4_vi_0900_as_cs", false}, + {303, "utf8mb4", "utf8mb4_ja_0900_as_cs", false}, + {304, "utf8mb4", "utf8mb4_ja_0900_as_cs_ks", false}, + {305, "utf8mb4", "utf8mb4_0900_as_ci", false}, + {306, "utf8mb4", "utf8mb4_ru_0900_ai_ci", false}, + {307, "utf8mb4", "utf8mb4_ru_0900_as_cs", false}, + {308, "utf8mb4", "utf8mb4_zh_0900_as_cs", false}, + {309, "utf8mb4", "utf8mb4_0900_bin", false}, {2048, "utf8mb4", "utf8mb4_zh_pinyin_tidb_as_cs", false}, } // AddCharset adds a new charset. // Use only when adding a custom charset to the parser. func AddCharset(c *Charset) { - charsetInfos[c.Name] = c + CharacterSetInfos[c.Name] = c } // RemoveCharset remove a charset. -// Use only when adding a custom charset to the parser. +// Use only when remove a custom charset to the parser. func RemoveCharset(c string) { - delete(charsetInfos, c) + delete(CharacterSetInfos, c) + for i := range supportedCollations { + if supportedCollations[i].Name == c { + supportedCollations = append(supportedCollations[:i], supportedCollations[i+1:]...) + } + } } // AddCollation adds a new collation. @@ -496,14 +556,20 @@ func AddCollation(c *Collation) { collationsNameMap[c.Name] = c if _, ok := supportedCollationNames[c.Name]; ok { - supportedCollations = append(supportedCollations, c) + AddSupportedCollation(c) } - if charset, ok := charsetInfos[c.CharsetName]; ok { + if charset, ok := CharacterSetInfos[c.CharsetName]; ok { charset.Collations[c.Name] = c } } +// AddSupportedCollation adds a new collation into supportedCollations. +// Use only when adding a custom collation to the parser. +func AddSupportedCollation(c *Collation) { + supportedCollations = append(supportedCollations, c) +} + // init method always puts to the end of file. func init() { for _, c := range collations { diff --git a/parser/charset/charset_test.go b/parser/charset/charset_test.go index a359223b92cb4..e09ad6b3c5bba 100644 --- a/parser/charset/charset_test.go +++ b/parser/charset/charset_test.go @@ -82,30 +82,13 @@ func TestGetDefaultCollation(t *testing.T) { charsetNum := 0 for _, collate := range collations { if collate.IsDefault { - if desc, ok := charsetInfos[collate.CharsetName]; ok { + if desc, ok := CharacterSetInfos[collate.CharsetName]; ok { require.Equal(t, desc.DefaultCollation, collate.Name) charsetNum += 1 } } } - require.Equal(t, len(charsetInfos), charsetNum) -} - -func TestSupportedCollations(t *testing.T) { - // All supportedCollation are defined from their names - require.Equal(t, len(supportedCollationNames), len(supportedCollationNames)) - - // The default collations of supported charsets is the subset of supported collations - for _, desc := range GetSupportedCharsets() { - found := false - for _, c := range GetSupportedCollations() { - if desc.DefaultCollation == c.Name { - found = true - break - } - } - require.Truef(t, found, "Charset [%v] is supported but its default collation [%v] is not.", desc.Name, desc.DefaultCollation) - } + require.Equal(t, len(CharacterSetInfos), charsetNum) } func TestGetCharsetDesc(t *testing.T) { diff --git a/parser/charset/encoding.go b/parser/charset/encoding.go index 8bd1b92c9bcf6..cc40c36100571 100644 --- a/parser/charset/encoding.go +++ b/parser/charset/encoding.go @@ -13,212 +13,137 @@ package charset -import ( - "bytes" - "fmt" - "reflect" - "strings" - "unicode" - "unsafe" - - "github.com/cznic/mathutil" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" - "golang.org/x/text/encoding" - "golang.org/x/text/transform" +import "bytes" + +// Make sure all of them implement Encoding interface. +var ( + _ Encoding = &encodingUTF8{} + _ Encoding = &encodingUTF8MB3Strict{} + _ Encoding = &encodingASCII{} + _ Encoding = &encodingLatin1{} + _ Encoding = &encodingBin{} + _ Encoding = &encodingGBK{} ) -var errInvalidCharacterString = terror.ClassParser.NewStd(mysql.ErrInvalidCharacterString) - -type EncodingLabel string - -// Format trim and change the label to lowercase. -func Format(label string) EncodingLabel { - return EncodingLabel(strings.ToLower(strings.Trim(label, "\t\n\r\f "))) -} - -// Formatted is used when the label is already trimmed and it is lowercase. -func Formatted(label string) EncodingLabel { - return EncodingLabel(label) -} - -// Encoding provide a interface to encode/decode a string with specific encoding. -type Encoding struct { - enc encoding.Encoding - name string - charLength func([]byte) int - specialCase unicode.SpecialCase +// IsSupportedEncoding checks if the charset is fully supported. +func IsSupportedEncoding(charset string) bool { + _, ok := encodingMap[charset] + return ok } -// enabled indicates whether the non-utf8 encoding is used. -func (e *Encoding) enabled() bool { - return e != UTF8Encoding -} - -// Name returns the name of the current encoding. -func (e *Encoding) Name() string { - return e.name -} - -// CharLength returns the next character length in bytes. -func (e *Encoding) CharLength(bs []byte) int { - return e.charLength(bs) -} - -// NewEncoding creates a new Encoding. -func NewEncoding(label string) *Encoding { - if len(label) == 0 { - return UTF8Encoding +// FindEncodingTakeUTF8AsNoop finds the encoding according to the charset +// except that utf-8 is treated as no-operation encoding. This is used to +// reduce the overhead of utf-8 validation in some cases. +func FindEncodingTakeUTF8AsNoop(charset string) Encoding { + enc := FindEncoding(charset) + if enc.Tp() == EncodingTpUTF8 { + return EncodingBinImpl } - - if e, exist := encodingMap[Format(label)]; exist { - return e - } - return UTF8Encoding + return enc } -// Encode convert bytes from utf-8 charset to a specific charset. -func (e *Encoding) Encode(dest, src []byte) ([]byte, error) { - if !e.enabled() { - return src, nil +// FindEncoding finds the encoding according to charset. +func FindEncoding(charset string) Encoding { + if len(charset) == 0 { + return EncodingBinImpl } - return e.transform(e.enc.NewEncoder(), dest, src, false) -} - -// EncodeString convert a string from utf-8 charset to a specific charset. -func (e *Encoding) EncodeString(src string) (string, error) { - if !e.enabled() { - return src, nil - } - bs, err := e.transform(e.enc.NewEncoder(), nil, Slice(src), false) - return string(bs), err -} - -// EncodeFirstChar convert first code point of bytes from utf-8 charset to a specific charset. -func (e *Encoding) EncodeFirstChar(dest, src []byte) ([]byte, error) { - srcNextLen := e.nextCharLenInSrc(src, false) - srcEnd := mathutil.Min(srcNextLen, len(src)) - if !e.enabled() { - return src[:srcEnd], nil - } - return e.transform(e.enc.NewEncoder(), dest, src[:srcEnd], false) -} - -// EncodeInternal convert bytes from utf-8 charset to a specific charset, we actually do not do the real convert, just find the inconvertible character and use ? replace. -// The code below is equivalent to -// expr, _ := e.Encode(dest, src) -// ret, _ := e.Decode(nil, expr) -// return ret -func (e *Encoding) EncodeInternal(dest, src []byte) []byte { - if !e.enabled() { - return src - } - if dest == nil { - dest = make([]byte, 0, len(src)) - } - var srcOffset int - - var buf [4]byte - transformer := e.enc.NewEncoder() - for srcOffset < len(src) { - length := UTF8Encoding.CharLength(src[srcOffset:]) - _, _, err := transformer.Transform(buf[:], src[srcOffset:srcOffset+length], true) - if err != nil { - dest = append(dest, byte('?')) - } else { - dest = append(dest, src[srcOffset:srcOffset+length]...) - } - srcOffset += length + if e, exist := encodingMap[charset]; exist { + return e } + return EncodingBinImpl +} + +var encodingMap = map[string]Encoding{ + CharsetUTF8MB4: EncodingUTF8Impl, + CharsetUTF8: EncodingUTF8Impl, + CharsetGBK: EncodingGBKImpl, + CharsetLatin1: EncodingLatin1Impl, + CharsetBin: EncodingBinImpl, + CharsetASCII: EncodingASCIIImpl, +} + +// Encoding provide encode/decode functions for a string with a specific charset. +type Encoding interface { + // Name is the name of the encoding. + Name() string + // Tp is the type of the encoding. + Tp() EncodingTp + // Peek returns the next char. + Peek(src []byte) []byte + // MbLen returns multiple byte length, if the next character is single byte, return 0. + MbLen(string) int + // IsValid checks whether the utf-8 bytes can be convert to valid string in current encoding. + IsValid(src []byte) bool + // Foreach iterates the characters in in current encoding. + Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) + // Transform map the bytes in src to dest according to Op. + // **the caller should initialize the dest if it wants to avoid memory alloc every time, or else it will always make a new one** + // **the returned array may be the alias of `src`, edit the returned array on your own risk** + Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) + // ToUpper change a string to uppercase. + ToUpper(src string) string + // ToLower change a string to lowercase. + ToLower(src string) string +} + +type EncodingTp int8 + +const ( + EncodingTpNone EncodingTp = iota + EncodingTpUTF8 + EncodingTpUTF8MB3Strict + EncodingTpASCII + EncodingTpLatin1 + EncodingTpBin + EncodingTpGBK +) - return dest -} - -// Decode convert bytes from a specific charset to utf-8 charset. -func (e *Encoding) Decode(dest, src []byte) ([]byte, error) { - if !e.enabled() { - return src, nil - } - return e.transform(e.enc.NewDecoder(), dest, src, true) -} +// Op is used by Encoding.Transform. +type Op int16 + +const ( + opFromUTF8 Op = 1 << iota + opToUTF8 + opTruncateTrim + opTruncateReplace + opCollectFrom + opCollectTo + opSkipError +) -// DecodeString convert a string from a specific charset to utf-8 charset. -func (e *Encoding) DecodeString(src string) (string, error) { - if !e.enabled() { - return src, nil - } - bs, err := e.transform(e.enc.NewDecoder(), nil, Slice(src), true) - return string(bs), err -} +const ( + OpReplaceNoErr = opFromUTF8 | opTruncateReplace | opCollectFrom | opSkipError + OpReplace = opFromUTF8 | opTruncateReplace | opCollectFrom + OpEncode = opFromUTF8 | opTruncateTrim | opCollectTo + OpEncodeNoErr = OpEncode | opSkipError + OpEncodeReplace = opFromUTF8 | opTruncateReplace | opCollectTo + OpDecode = opToUTF8 | opTruncateTrim | opCollectTo + OpDecodeNoErr = OpDecode | opSkipError + OpDecodeReplace = opToUTF8 | opTruncateReplace | opCollectTo +) -func (e *Encoding) transform(transformer transform.Transformer, dest, src []byte, isDecoding bool) ([]byte, error) { - if len(dest) < len(src) { - dest = make([]byte, len(src)*2) - } - if len(src) == 0 { - return src, nil - } - var destOffset, srcOffset int - var encodingErr error - for { - srcNextLen := e.nextCharLenInSrc(src[srcOffset:], isDecoding) - srcEnd := mathutil.Min(srcOffset+srcNextLen, len(src)) - nDest, nSrc, err := transformer.Transform(dest[destOffset:], src[srcOffset:srcEnd], false) - if err == transform.ErrShortDst { - dest = enlargeCapacity(dest) - } else if err != nil || isDecoding && beginWithReplacementChar(dest[destOffset:destOffset+nDest]) { - if encodingErr == nil { - encodingErr = e.generateErr(src[srcOffset:], srcNextLen) - } - dest[destOffset] = byte('?') - nDest, nSrc = 1, srcNextLen // skip the source bytes that cannot be decoded normally. +// CountValidBytes counts the first valid bytes in src that +// can be encoded to the current encoding. +func CountValidBytes(e Encoding, src []byte) int { + nSrc := 0 + e.Foreach(src, opFromUTF8, func(from, to []byte, ok bool) bool { + if ok { + nSrc += len(from) } - destOffset += nDest - srcOffset += nSrc - // The source bytes are exhausted. - if srcOffset >= len(src) { - return dest[:destOffset], encodingErr + return ok + }) + return nSrc +} + +// CountValidBytesDecode counts the first valid bytes in src that +// can be decoded to utf-8. +func CountValidBytesDecode(e Encoding, src []byte) int { + nSrc := 0 + e.Foreach(src, opToUTF8, func(from, to []byte, ok bool) bool { + if ok { + nSrc += len(from) } - } -} - -func (e *Encoding) nextCharLenInSrc(srcRest []byte, isDecoding bool) int { - if isDecoding { - if e.charLength != nil { - return e.charLength(srcRest) - } - return len(srcRest) - } - return UTF8Encoding.CharLength(srcRest) -} - -func enlargeCapacity(dest []byte) []byte { - newDest := make([]byte, len(dest)*2) - copy(newDest, dest) - return newDest -} - -func (e *Encoding) generateErr(srcRest []byte, srcNextLen int) error { - cutEnd := mathutil.Min(srcNextLen, len(srcRest)) - invalidBytes := fmt.Sprintf("%X", string(srcRest[:cutEnd])) - return errInvalidCharacterString.GenWithStackByArgs(e.name, invalidBytes) -} - -// replacementBytes are bytes for the replacement rune 0xfffd. -var replacementBytes = []byte{0xEF, 0xBF, 0xBD} - -// beginWithReplacementChar check if dst has the prefix '0xEFBFBD'. -func beginWithReplacementChar(dst []byte) bool { - return bytes.HasPrefix(dst, replacementBytes) -} - -// Slice converts string to slice without copy. -// Use at your own risk. -func Slice(s string) (b []byte) { - pBytes := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - pString := (*reflect.StringHeader)(unsafe.Pointer(&s)) - pBytes.Data = pString.Data - pBytes.Len = pString.Len - pBytes.Cap = pString.Len - return + return ok + }) + return nSrc } diff --git a/parser/charset/encoding_ascii.go b/parser/charset/encoding_ascii.go new file mode 100644 index 0000000000000..cf9100f699111 --- /dev/null +++ b/parser/charset/encoding_ascii.go @@ -0,0 +1,83 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + go_unicode "unicode" + + "golang.org/x/text/encoding" +) + +// EncodingASCIIImpl is the instance of encodingASCII +var EncodingASCIIImpl = &encodingASCII{encodingBase{enc: encoding.Nop}} + +func init() { + EncodingASCIIImpl.self = EncodingASCIIImpl +} + +// encodingASCII is the ASCII encoding. +type encodingASCII struct { + encodingBase +} + +// Name implements Encoding interface. +func (e *encodingASCII) Name() string { + return CharsetASCII +} + +// Tp implements Encoding interface. +func (e *encodingASCII) Tp() EncodingTp { + return EncodingTpASCII +} + +// Peek implements Encoding interface. +func (e *encodingASCII) Peek(src []byte) []byte { + if len(src) == 0 { + return src + } + return src[:1] +} + +// IsValid implements Encoding interface. +func (e *encodingASCII) IsValid(src []byte) bool { + srcLen := len(src) + for i := 0; i < srcLen; i++ { + if src[i] > go_unicode.MaxASCII { + return false + } + } + return true +} + +func (e *encodingASCII) Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) { + if e.IsValid(src) { + return src, nil + } + return e.encodingBase.Transform(dest, src, op) +} + +func (e *encodingASCII) Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) { + for i, w := 0, 0; i < len(src); i += w { + w = 1 + ok := true + if src[i] > go_unicode.MaxASCII { + w = len(EncodingUTF8Impl.Peek(src[i:])) + ok = false + } + if !fn(src[i:i+w], src[i:i+w], ok) { + return + } + } +} diff --git a/parser/charset/encoding_base.go b/parser/charset/encoding_base.go new file mode 100644 index 0000000000000..58abc601318f3 --- /dev/null +++ b/parser/charset/encoding_base.go @@ -0,0 +1,145 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + "fmt" + "reflect" + "strings" + "unsafe" + + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/parser/terror" + "golang.org/x/text/encoding" + "golang.org/x/text/transform" +) + +// ErrInvalidCharacterString returns when the string is invalid in the specific charset. +var ErrInvalidCharacterString = terror.ClassParser.NewStd(mysql.ErrInvalidCharacterString) + +// encodingBase defines some generic functions. +type encodingBase struct { + enc encoding.Encoding + self Encoding +} + +func (b encodingBase) MbLen(_ string) int { + return 0 +} + +func (b encodingBase) ToUpper(src string) string { + return strings.ToUpper(src) +} + +func (b encodingBase) ToLower(src string) string { + return strings.ToLower(src) +} + +func (b encodingBase) IsValid(src []byte) bool { + isValid := true + b.self.Foreach(src, opFromUTF8, func(from, to []byte, ok bool) bool { + isValid = ok + return ok + }) + return isValid +} + +func (b encodingBase) Transform(dest *bytes.Buffer, src []byte, op Op) (result []byte, err error) { + if dest == nil { + dest = &bytes.Buffer{} + dest.Grow(len(src)) + } + dest.Reset() + b.self.Foreach(src, op, func(from, to []byte, ok bool) bool { + if !ok { + if err == nil && (op&opSkipError == 0) { + err = generateEncodingErr(b.self.Name(), from) + } + if op&opTruncateTrim != 0 { + return false + } + if op&opTruncateReplace != 0 { + dest.WriteByte('?') + return true + } + } + if op&opCollectFrom != 0 { + dest.Write(from) + } else if op&opCollectTo != 0 { + dest.Write(to) + } + return true + }) + return dest.Bytes(), err +} + +func (b encodingBase) Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) { + var tfm transform.Transformer + var peek func([]byte) []byte + if op&opFromUTF8 != 0 { + tfm = b.enc.NewEncoder() + peek = EncodingUTF8Impl.Peek + } else { + tfm = b.enc.NewDecoder() + peek = b.self.Peek + } + var buf [4]byte + for i, w := 0, 0; i < len(src); i += w { + w = len(peek(src[i:])) + nDst, _, err := tfm.Transform(buf[:], src[i:i+w], false) + meetErr := err != nil || (op&opToUTF8 != 0 && beginWithReplacementChar(buf[:nDst])) + if !fn(src[i:i+w], buf[:nDst], !meetErr) { + return + } + } +} + +// replacementBytes are bytes for the replacement rune 0xfffd. +var replacementBytes = []byte{0xEF, 0xBF, 0xBD} + +// beginWithReplacementChar check if dst has the prefix '0xEFBFBD'. +func beginWithReplacementChar(dst []byte) bool { + return bytes.HasPrefix(dst, replacementBytes) +} + +// generateEncodingErr generates an invalid string in charset error. +func generateEncodingErr(name string, invalidBytes []byte) error { + arg := fmt.Sprintf("%X", invalidBytes) + return ErrInvalidCharacterString.FastGenByArgs(name, arg) +} + +// HackSlice converts string to slice without copy. +// Use at your own risk. +func HackSlice(s string) (b []byte) { + pBytes := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + pString := (*reflect.StringHeader)(unsafe.Pointer(&s)) + pBytes.Data = pString.Data + pBytes.Len = pString.Len + pBytes.Cap = pString.Len + return +} + +// HackString converts slice to string without copy. +// Use it at your own risk. +func HackString(b []byte) (s string) { + if len(b) == 0 { + return "" + } + pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + pstring := (*reflect.StringHeader)(unsafe.Pointer(&s)) + pstring.Data = pbytes.Data + pstring.Len = pbytes.Len + return +} diff --git a/parser/charset/encoding_bin.go b/parser/charset/encoding_bin.go new file mode 100644 index 0000000000000..3a9bf2e4f8968 --- /dev/null +++ b/parser/charset/encoding_bin.go @@ -0,0 +1,68 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + + "golang.org/x/text/encoding" +) + +// EncodingBinImpl is the instance of encodingBin. +var EncodingBinImpl = &encodingBin{encodingBase{enc: encoding.Nop}} + +func init() { + EncodingBinImpl.self = EncodingBinImpl +} + +// encodingBin is the binary encoding. +type encodingBin struct { + encodingBase +} + +// Name implements Encoding interface. +func (e *encodingBin) Name() string { + return CharsetBin +} + +// Tp implements Encoding interface. +func (e *encodingBin) Tp() EncodingTp { + return EncodingTpBin +} + +// Peek implements Encoding interface. +func (e *encodingBin) Peek(src []byte) []byte { + if len(src) == 0 { + return src + } + return src[:1] +} + +// IsValid implements Encoding interface. +func (e *encodingBin) IsValid(src []byte) bool { + return true +} + +// Foreach implements Encoding interface. +func (e *encodingBin) Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) { + for i := 0; i < len(src); i++ { + if !fn(src[i:i+1], src[i:i+1], true) { + return + } + } +} + +func (e *encodingBin) Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) { + return src, nil +} diff --git a/parser/charset/encoding_gbk.go b/parser/charset/encoding_gbk.go new file mode 100644 index 0000000000000..df8458b7a74d3 --- /dev/null +++ b/parser/charset/encoding_gbk.go @@ -0,0 +1,175 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + "strings" + "unicode" + "unicode/utf8" + + "golang.org/x/text/encoding" + "golang.org/x/text/encoding/simplifiedchinese" +) + +// EncodingGBKImpl is the instance of encodingGBK +var EncodingGBKImpl = &encodingGBK{encodingBase{enc: customGBK{}}} + +func init() { + EncodingGBKImpl.self = EncodingGBKImpl +} + +// encodingGBK is GBK encoding. +type encodingGBK struct { + encodingBase +} + +// Name implements Encoding interface. +func (e *encodingGBK) Name() string { + return CharsetGBK +} + +// Tp implements Encoding interface. +func (e *encodingGBK) Tp() EncodingTp { + return EncodingTpGBK +} + +// Peek implements Encoding interface. +func (e *encodingGBK) Peek(src []byte) []byte { + charLen := 2 + if len(src) == 0 || src[0] < 0x80 { + // A byte in the range 00–7F is a single byte that means the same thing as it does in ASCII. + charLen = 1 + } + if charLen < len(src) { + return src[:charLen] + } + return src +} + +func (e *encodingGBK) MbLen(bs string) int { + if len(bs) < 2 { + return 0 + } + + if 0x81 <= bs[0] && bs[0] <= 0xfe { + if (0x40 <= bs[1] && bs[1] <= 0x7e) || (0x80 <= bs[1] && bs[1] <= 0xfe) { + return 2 + } + } + + return 0 +} + +// ToUpper implements Encoding interface. +func (e *encodingGBK) ToUpper(d string) string { + return strings.ToUpperSpecial(GBKCase, d) +} + +// ToLower implements Encoding interface. +func (e *encodingGBK) ToLower(d string) string { + return strings.ToLowerSpecial(GBKCase, d) +} + +// GBKCase follows https://dev.mysql.com/worklog/task/?id=4583. +var GBKCase = unicode.SpecialCase{ + unicode.CaseRange{Lo: 0x00E0, Hi: 0x00E1, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x00E8, Hi: 0x00EA, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x00EC, Hi: 0x00ED, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x00F2, Hi: 0x00F3, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x00F9, Hi: 0x00FA, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x00FC, Hi: 0x00FC, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x0101, Hi: 0x0101, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x0113, Hi: 0x0113, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x011B, Hi: 0x011B, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x012B, Hi: 0x012B, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x0144, Hi: 0x0144, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x0148, Hi: 0x0148, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x014D, Hi: 0x014D, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x016B, Hi: 0x016B, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01CE, Hi: 0x01CE, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01D0, Hi: 0x01D0, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01D2, Hi: 0x01D2, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01D4, Hi: 0x01D4, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01D6, Hi: 0x01D6, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01D8, Hi: 0x01D8, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01DA, Hi: 0x01DA, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x01DC, Hi: 0x01DC, Delta: [unicode.MaxCase]rune{0, 0, 0}}, + unicode.CaseRange{Lo: 0x216A, Hi: 0x216B, Delta: [unicode.MaxCase]rune{0, 0, 0}}, +} + +// customGBK is a simplifiedchinese.GBK wrapper. +type customGBK struct{} + +// NewCustomGBKEncoder return a custom GBK encoding. +func NewCustomGBKEncoder() *encoding.Encoder { + return customGBK{}.NewEncoder() +} + +// NewDecoder returns simplifiedchinese.GBK.NewDecoder(). +func (c customGBK) NewDecoder() *encoding.Decoder { + return &encoding.Decoder{ + Transformer: customGBKDecoder{ + gbkDecoder: simplifiedchinese.GBK.NewDecoder(), + }, + } +} + +type customGBKDecoder struct { + gbkDecoder *encoding.Decoder +} + +// Transform special treatment for 0x80, +// see https://github.com/pingcap/tidb/issues/30581 get details. +func (c customGBKDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + if len(src) == 0 { + return 0, 0, nil + } + if src[0] == 0x80 { + return utf8.EncodeRune(dst[:], utf8.RuneError), 1, nil + } + return c.gbkDecoder.Transform(dst, src, atEOF) +} + +// Reset is same as simplifiedchinese.GBK.Reset(). +func (c customGBKDecoder) Reset() { + c.gbkDecoder.Reset() +} + +type customGBKEncoder struct { + gbkEncoder *encoding.Encoder +} + +// NewEncoder returns simplifiedchinese.gbk. +func (c customGBK) NewEncoder() *encoding.Encoder { + return &encoding.Encoder{ + Transformer: customGBKEncoder{ + gbkEncoder: simplifiedchinese.GBK.NewEncoder(), + }, + } +} + +// Transform special treatment for `€`, +// see https://github.com/pingcap/tidb/issues/30581 get details. +func (c customGBKEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + if bytes.HasPrefix(src, []byte{0xe2, 0x82, 0xac} /* '€' */) { + return 0, 0, ErrInvalidCharacterString + } + return c.gbkEncoder.Transform(dst, src, atEOF) +} + +// Reset is same as simplifiedchinese.gbk. +func (c customGBKEncoder) Reset() { + c.gbkEncoder.Reset() +} diff --git a/parser/charset/encoding_latin1.go b/parser/charset/encoding_latin1.go new file mode 100644 index 0000000000000..38f9bb601ac4e --- /dev/null +++ b/parser/charset/encoding_latin1.go @@ -0,0 +1,60 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + + "golang.org/x/text/encoding" +) + +// EncodingLatin1Impl is the instance of encodingLatin1. +// TiDB uses utf8 implementation for latin1 charset because of the backward compatibility. +var EncodingLatin1Impl = &encodingLatin1{encodingUTF8{encodingBase{enc: encoding.Nop}}} + +func init() { + EncodingLatin1Impl.self = EncodingLatin1Impl +} + +// encodingLatin1 compatibles with latin1 in old version TiDB. +type encodingLatin1 struct { + encodingUTF8 +} + +// Name implements Encoding interface. +func (e *encodingLatin1) Name() string { + return CharsetLatin1 +} + +// Peek implements Encoding interface. +func (e *encodingLatin1) Peek(src []byte) []byte { + if len(src) == 0 { + return src + } + return src[:1] +} + +// IsValid implements Encoding interface. +func (e *encodingLatin1) IsValid(src []byte) bool { + return true +} + +// Tp implements Encoding interface. +func (e *encodingLatin1) Tp() EncodingTp { + return EncodingTpLatin1 +} + +func (e *encodingLatin1) Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) { + return src, nil +} diff --git a/parser/charset/encoding_table.go b/parser/charset/encoding_table.go index 2de9d957d923a..24d61b07f9ba4 100644 --- a/parser/charset/encoding_table.go +++ b/parser/charset/encoding_table.go @@ -15,10 +15,7 @@ package charset import ( "strings" - go_unicode "unicode" - "unicode/utf8" - "github.com/cznic/mathutil" "golang.org/x/text/encoding" "golang.org/x/text/encoding/charmap" "golang.org/x/text/encoding/japanese" @@ -28,26 +25,17 @@ import ( "golang.org/x/text/encoding/unicode" ) -var encodingMap = map[EncodingLabel]*Encoding{ - CharsetUTF8MB4: UTF8Encoding, - CharsetUTF8: UTF8Encoding, - CharsetGBK: GBKEncoding, - CharsetLatin1: LatinEncoding, - CharsetBin: BinaryEncoding, - CharsetASCII: ASCIIEncoding, -} - // Lookup returns the encoding with the specified label, and its canonical // name. It returns nil and the empty string if label is not one of the // standard encodings for HTML. Matching is case-insensitive and ignores // leading and trailing whitespace. func Lookup(label string) (e encoding.Encoding, name string) { label = strings.ToLower(strings.Trim(label, "\t\n\r\f ")) - return lookup(Formatted(label)) + return lookup(label) } -func lookup(label EncodingLabel) (e encoding.Encoding, name string) { - enc := encodings[string(label)] +func lookup(label string) (e encoding.Encoding, name string) { + enc := encodings[label] return enc.e, enc.name } @@ -274,179 +262,3 @@ var encodings = map[string]struct { "utf-16le": {unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), "utf-16le"}, "x-user-defined": {charmap.XUserDefined, "x-user-defined"}, } - -// TruncateStrategy indicates the way to handle the invalid strings in specific charset. -// - TruncateStrategyEmpty: returns an empty string. -// - TruncateStrategyTrim: returns the valid prefix part of string. -// - TruncateStrategyReplace: returns the whole string, but the invalid characters are replaced with '?'. -type TruncateStrategy int8 - -const ( - TruncateStrategyEmpty TruncateStrategy = iota - TruncateStrategyTrim - TruncateStrategyReplace -) - -var _ StringValidator = StringValidatorASCII{} -var _ StringValidator = StringValidatorUTF8{} -var _ StringValidator = StringValidatorOther{} - -// StringValidator is used to check if a string is valid in the specific charset. -type StringValidator interface { - Validate(str string) (invalidPos int) - Truncate(str string, strategy TruncateStrategy) (result string, invalidPos int) -} - -// StringValidatorASCII checks whether a string is valid ASCII string. -type StringValidatorASCII struct{} - -// Validate checks whether the string is valid in the given charset. -func (s StringValidatorASCII) Validate(str string) int { - _, invalidPos := s.Truncate(str, TruncateStrategyEmpty) - return invalidPos -} - -// Truncate implement the interface StringValidator. -func (s StringValidatorASCII) Truncate(str string, strategy TruncateStrategy) (string, int) { - invalidPos := -1 - for i := 0; i < len(str); i++ { - if str[i] > go_unicode.MaxASCII { - invalidPos = i - break - } - } - if invalidPos == -1 { - // Quick check passed. - return str, -1 - } - switch strategy { - case TruncateStrategyEmpty: - return "", invalidPos - case TruncateStrategyTrim: - return str[:invalidPos], invalidPos - case TruncateStrategyReplace: - result := make([]byte, 0, len(str)) - for i, w := 0, 0; i < len(str); i += w { - w = 1 - if str[i] > go_unicode.MaxASCII { - w = UTF8Encoding.CharLength(Slice(str)[i:]) - w = mathutil.Min(w, len(str)-i) - result = append(result, '?') - continue - } - result = append(result, str[i:i+w]...) - } - return string(result), invalidPos - } - return str, -1 -} - -// StringValidatorUTF8 checks whether a string is valid UTF8 string. -type StringValidatorUTF8 struct { - IsUTF8MB4 bool // Distinguish between "utf8" and "utf8mb4" - CheckMB4ValueInUTF8 bool -} - -// Validate checks whether the string is valid in the given charset. -func (s StringValidatorUTF8) Validate(str string) int { - _, invalidPos := s.Truncate(str, TruncateStrategyEmpty) - return invalidPos -} - -// Truncate implement the interface StringValidator. -func (s StringValidatorUTF8) Truncate(str string, strategy TruncateStrategy) (string, int) { - if str == "" { - return str, -1 - } - if s.IsUTF8MB4 && utf8.ValidString(str) { - // Quick check passed. - return str, -1 - } - doMB4CharCheck := !s.IsUTF8MB4 && s.CheckMB4ValueInUTF8 - var result []byte - if strategy == TruncateStrategyReplace { - result = make([]byte, 0, len(str)) - } - invalidPos := -1 - for i, w := 0, 0; i < len(str); i += w { - var rv rune - rv, w = utf8.DecodeRuneInString(str[i:]) - if (rv == utf8.RuneError && w == 1) || (w > 3 && doMB4CharCheck) { - if invalidPos == -1 { - invalidPos = i - } - switch strategy { - case TruncateStrategyEmpty: - return "", invalidPos - case TruncateStrategyTrim: - return str[:i], invalidPos - case TruncateStrategyReplace: - result = append(result, '?') - continue - } - } - if strategy == TruncateStrategyReplace { - result = append(result, str[i:i+w]...) - } - } - if strategy == TruncateStrategyReplace { - return string(result), invalidPos - } - return str, -1 -} - -// StringValidatorOther checks whether a string is valid string in given charset. -type StringValidatorOther struct { - Charset string -} - -// Validate checks whether the string is valid in the given charset. -func (s StringValidatorOther) Validate(str string) int { - _, invalidPos := s.Truncate(str, TruncateStrategyEmpty) - return invalidPos -} - -// Truncate implement the interface StringValidator. -func (s StringValidatorOther) Truncate(str string, strategy TruncateStrategy) (string, int) { - if str == "" { - return str, -1 - } - enc := NewEncoding(s.Charset) - if !enc.enabled() { - return str, -1 - } - var result []byte - if strategy == TruncateStrategyReplace { - result = make([]byte, 0, len(str)) - } - var buf [4]byte - strBytes := Slice(str) - transformer := enc.enc.NewEncoder() - invalidPos := -1 - for i, w := 0, 0; i < len(str); i += w { - w = UTF8Encoding.CharLength(strBytes[i:]) - w = mathutil.Min(w, len(str)-i) - _, _, err := transformer.Transform(buf[:], strBytes[i:i+w], true) - if err != nil { - if invalidPos == -1 { - invalidPos = i - } - switch strategy { - case TruncateStrategyEmpty: - return "", invalidPos - case TruncateStrategyTrim: - return str[:i], invalidPos - case TruncateStrategyReplace: - result = append(result, '?') - continue - } - } - if strategy == TruncateStrategyReplace { - result = append(result, strBytes[i:i+w]...) - } - } - if strategy == TruncateStrategyReplace { - return string(result), invalidPos - } - return str, -1 -} diff --git a/parser/charset/encoding_test.go b/parser/charset/encoding_test.go index 51f5b53b3e2fd..8322d2f611f06 100644 --- a/parser/charset/encoding_test.go +++ b/parser/charset/encoding_test.go @@ -24,21 +24,21 @@ import ( ) func TestEncoding(t *testing.T) { - enc := charset.NewEncoding(charset.CharsetGBK) + enc := charset.FindEncoding(charset.CharsetGBK) require.Equal(t, charset.CharsetGBK, enc.Name()) txt := []byte("一二三四") e, _ := charset.Lookup("gbk") gbkEncodedTxt, _, err := transform.Bytes(e.NewEncoder(), txt) require.NoError(t, err) - result, err := enc.Decode(nil, gbkEncodedTxt) + result, err := enc.Transform(nil, gbkEncodedTxt, charset.OpDecode) require.NoError(t, err) require.Equal(t, txt, result) - gbkEncodedTxt2, err := enc.Encode(nil, txt) + gbkEncodedTxt2, err := enc.Transform(nil, txt, charset.OpEncode) require.NoError(t, err) require.Equal(t, gbkEncodedTxt2, gbkEncodedTxt) - result, err = enc.Decode(nil, gbkEncodedTxt2) + result, err = enc.Transform(nil, gbkEncodedTxt2, charset.OpDecode) require.NoError(t, err) require.Equal(t, txt, result) @@ -49,16 +49,23 @@ func TestEncoding(t *testing.T) { }{ {"一二三", "涓?簩涓?", false}, // MySQL reports '涓?簩涓'. {"一二三123", "涓?簩涓?23", false}, + {"测试", "娴嬭瘯", true}, {"案1案2", "妗?妗?", false}, {"ç„Šä·è¡é‡¬", "é’å©å½¿é‘¿ï¿ åšž", true}, {"éžæ以伊ä½ä¾", "闉嶆潖浠ヤ紛浣嶄緷", true}, {"移維緯胃èŽè¡£è¬‚é•", "绉è¤è‘£ç»¶?å„钀庤。璎傞仌", false}, {"仆仂仗仞仭仟价伉佚估", "浠嗕粋浠椾粸浠?粺浠蜂級浣氫åŠ", false}, {"ä½ä½—佇佶侈ä¾ä¾˜ä½»ä½©ä½°ä¾‘佯", "浣濅ç¶æµ£å›¦è•‰æ¸šå œç·©æ¸šæ¨¹äº¤æµ£â•€æ¡¨æ¸šæˆœè’‹", true}, + {"\x80", "?", false}, + {"\x80a", "?", false}, + {"\x80aa", "?a", false}, + {"aa\x80ab", "aa?b", false}, + {"a你好\x80a测试", "a浣犲ソ?娴嬭瘯", false}, + {"aa\x80", "aa?", false}, } for _, tc := range GBKCases { cmt := fmt.Sprintf("%v", tc) - result, err = enc.Decode(nil, []byte(tc.utf8Str)) + result, err := enc.Transform(nil, []byte(tc.utf8Str), charset.OpDecodeReplace) if tc.isValid { require.NoError(t, err, cmt) } else { @@ -75,10 +82,14 @@ func TestEncoding(t *testing.T) { {"一二三", "Ò»\xb6\xfe\xc8\xfd", true}, {"ðŸ€", "?", false}, {"valid_string_ðŸ€", "valid_string_?", false}, + {"€", "?", false}, + {"€a", "?a", false}, + {"a€aa", "a?aa", false}, + {"aaa€", "aaa?", false}, } for _, tc := range utf8Cases { cmt := fmt.Sprintf("%v", tc) - result, err = enc.Encode(nil, []byte(tc.utf8Str)) + result, err := enc.Transform(nil, []byte(tc.utf8Str), charset.OpEncodeReplace) if tc.isValid { require.NoError(t, err, cmt) } else { @@ -88,111 +99,53 @@ func TestEncoding(t *testing.T) { } } -func TestStringValidatorASCII(t *testing.T) { - v := charset.StringValidatorASCII{} - testCases := []struct { - str string - strategy charset.TruncateStrategy - expected string - invalidPos int - }{ - {"", charset.TruncateStrategyEmpty, "", -1}, - {"qwerty", charset.TruncateStrategyEmpty, "qwerty", -1}, - {"qwÊrty", charset.TruncateStrategyEmpty, "", 2}, - {"qwÊrty", charset.TruncateStrategyTrim, "qw", 2}, - {"qwÊrty", charset.TruncateStrategyReplace, "qw?rty", 2}, - {"中文", charset.TruncateStrategyEmpty, "", 0}, - {"中文?qwert", charset.TruncateStrategyTrim, "", 0}, - {"中文?qwert", charset.TruncateStrategyReplace, "???qwert", 0}, - } - for _, tc := range testCases { - msg := fmt.Sprintf("%v", tc) - actual, invalidPos := v.Truncate(tc.str, tc.strategy) - require.Equal(t, tc.expected, actual, msg) - require.Equal(t, tc.invalidPos, invalidPos, msg) - } - require.Equal(t, -1, v.Validate("qwerty")) - require.Equal(t, 2, v.Validate("qwÊrty")) - require.Equal(t, 0, v.Validate("中文")) -} - -func TestStringValidatorUTF8(t *testing.T) { - // Test charset "utf8mb4". - v := charset.StringValidatorUTF8{IsUTF8MB4: true} +func TestEncodingValidate(t *testing.T) { oxfffefd := string([]byte{0xff, 0xfe, 0xfd}) testCases := []struct { - str string - strategy charset.TruncateStrategy - expected string - invalidPos int - }{ - {"", charset.TruncateStrategyEmpty, "", -1}, - {"qwerty", charset.TruncateStrategyEmpty, "qwerty", -1}, - {"qwÊrty", charset.TruncateStrategyEmpty, "qwÊrty", -1}, - {"qwÊåˆæ³•å­—符串", charset.TruncateStrategyEmpty, "qwÊåˆæ³•å­—符串", -1}, - {"😂", charset.TruncateStrategyEmpty, "😂", -1}, - {oxfffefd, charset.TruncateStrategyEmpty, "", 0}, - {oxfffefd, charset.TruncateStrategyReplace, "???", 0}, - {"中文" + oxfffefd, charset.TruncateStrategyTrim, "中文", 6}, - {"中文" + oxfffefd, charset.TruncateStrategyReplace, "中文???", 6}, - {string(utf8.RuneError), charset.TruncateStrategyEmpty, "�", -1}, - } - for _, tc := range testCases { - msg := fmt.Sprintf("%v", tc) - actual, invalidPos := v.Truncate(tc.str, tc.strategy) - require.Equal(t, tc.expected, actual, msg) - require.Equal(t, tc.invalidPos, invalidPos, msg) - } - // Test charset "utf8" with checking mb4 value. - v = charset.StringValidatorUTF8{IsUTF8MB4: false, CheckMB4ValueInUTF8: true} - testCases = []struct { - str string - strategy charset.TruncateStrategy - expected string - invalidPos int - }{ - {"", charset.TruncateStrategyEmpty, "", -1}, - {"qwerty", charset.TruncateStrategyEmpty, "qwerty", -1}, - {"qwÊrty", charset.TruncateStrategyEmpty, "qwÊrty", -1}, - {"qwÊåˆæ³•å­—符串", charset.TruncateStrategyEmpty, "qwÊåˆæ³•å­—符串", -1}, - {"😂", charset.TruncateStrategyEmpty, "", 0}, - {"😂", charset.TruncateStrategyReplace, "?", 0}, - {"valid_str😂", charset.TruncateStrategyReplace, "valid_str?", 9}, - {oxfffefd, charset.TruncateStrategyEmpty, "", 0}, - {oxfffefd, charset.TruncateStrategyReplace, "???", 0}, - {"中文" + oxfffefd, charset.TruncateStrategyTrim, "中文", 6}, - {"中文" + oxfffefd, charset.TruncateStrategyReplace, "中文???", 6}, - {string(utf8.RuneError), charset.TruncateStrategyEmpty, "�", -1}, - } - for _, tc := range testCases { - msg := fmt.Sprintf("%v", tc) - actual, invalidPos := v.Truncate(tc.str, tc.strategy) - require.Equal(t, tc.expected, actual, msg) - require.Equal(t, tc.invalidPos, invalidPos, msg) - } -} - -func TestStringValidatorGBK(t *testing.T) { - v := charset.StringValidatorOther{Charset: "gbk"} - testCases := []struct { - str string - strategy charset.TruncateStrategy - expected string - invalidPos int + chs string + str string + expected string + nSrc int + ok bool }{ - {"", charset.TruncateStrategyEmpty, "", -1}, - {"asdf", charset.TruncateStrategyEmpty, "asdf", -1}, - {"中文", charset.TruncateStrategyEmpty, "中文", -1}, - {"À", charset.TruncateStrategyEmpty, "", 0}, - {"À", charset.TruncateStrategyReplace, "?", 0}, - {"中文À中文", charset.TruncateStrategyTrim, "中文", 6}, - {"中文À中文", charset.TruncateStrategyReplace, "中文?中文", 6}, - {"asdfÀ", charset.TruncateStrategyReplace, "asdf?", 4}, + {charset.CharsetASCII, "", "", 0, true}, + {charset.CharsetASCII, "qwerty", "qwerty", 6, true}, + {charset.CharsetASCII, "qwÊrty", "qw?rty", 2, false}, + {charset.CharsetASCII, "中文", "??", 0, false}, + {charset.CharsetASCII, "中文?qwert", "???qwert", 0, false}, + {charset.CharsetUTF8MB4, "", "", 0, true}, + {charset.CharsetUTF8MB4, "qwerty", "qwerty", 6, true}, + {charset.CharsetUTF8MB4, "qwÊrty", "qwÊrty", 7, true}, + {charset.CharsetUTF8MB4, "qwÊåˆæ³•å­—符串", "qwÊåˆæ³•å­—符串", 19, true}, + {charset.CharsetUTF8MB4, "😂", "😂", 4, true}, + {charset.CharsetUTF8MB4, oxfffefd, "???", 0, false}, + {charset.CharsetUTF8MB4, "中文" + oxfffefd, "中文???", 6, false}, + {charset.CharsetUTF8MB4, string(utf8.RuneError), "�", 3, true}, + {charset.CharsetUTF8, "", "", 0, true}, + {charset.CharsetUTF8, "qwerty", "qwerty", 6, true}, + {charset.CharsetUTF8, "qwÊrty", "qwÊrty", 7, true}, + {charset.CharsetUTF8, "qwÊåˆæ³•å­—符串", "qwÊåˆæ³•å­—符串", 19, true}, + {charset.CharsetUTF8, "😂", "?", 0, false}, + {charset.CharsetUTF8, "valid_str😂", "valid_str?", 9, false}, + {charset.CharsetUTF8, oxfffefd, "???", 0, false}, + {charset.CharsetUTF8, "中文" + oxfffefd, "中文???", 6, false}, + {charset.CharsetUTF8, string(utf8.RuneError), "�", 3, true}, + {charset.CharsetGBK, "", "", 0, true}, + {charset.CharsetGBK, "asdf", "asdf", 4, true}, + {charset.CharsetGBK, "中文", "中文", 6, true}, + {charset.CharsetGBK, "À", "?", 0, false}, + {charset.CharsetGBK, "中文À中文", "中文?中文", 6, false}, + {charset.CharsetGBK, "asdfÀ", "asdf?", 4, false}, } for _, tc := range testCases { msg := fmt.Sprintf("%v", tc) - actual, invalidPos := v.Truncate(tc.str, tc.strategy) - require.Equal(t, tc.expected, actual, msg) - require.Equal(t, tc.invalidPos, invalidPos, msg) + enc := charset.FindEncoding(tc.chs) + if tc.chs == charset.CharsetUTF8 { + enc = charset.EncodingUTF8MB3StrictImpl + } + strBytes := []byte(tc.str) + require.Equal(t, tc.ok, enc.IsValid(strBytes), msg) + replace, _ := enc.Transform(nil, strBytes, charset.OpReplaceNoErr) + require.Equal(t, tc.expected, string(replace), msg) } } diff --git a/parser/charset/encoding_utf8.go b/parser/charset/encoding_utf8.go new file mode 100644 index 0000000000000..730c2bfc3d8ad --- /dev/null +++ b/parser/charset/encoding_utf8.go @@ -0,0 +1,136 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "bytes" + "unicode/utf8" + + "golang.org/x/text/encoding" +) + +// EncodingUTF8Impl is the instance of encodingUTF8. +var EncodingUTF8Impl = &encodingUTF8{encodingBase{enc: encoding.Nop}} + +// EncodingUTF8MB3StrictImpl is the instance of encodingUTF8MB3Strict. +var EncodingUTF8MB3StrictImpl = &encodingUTF8MB3Strict{ + encodingUTF8{ + encodingBase{ + enc: encoding.Nop, + }, + }, +} + +func init() { + EncodingUTF8Impl.self = EncodingUTF8Impl + EncodingUTF8MB3StrictImpl.self = EncodingUTF8MB3StrictImpl +} + +// encodingUTF8 is TiDB's default encoding. +type encodingUTF8 struct { + encodingBase +} + +// Name implements Encoding interface. +func (e *encodingUTF8) Name() string { + return CharsetUTF8MB4 +} + +// Tp implements Encoding interface. +func (e *encodingUTF8) Tp() EncodingTp { + return EncodingTpUTF8 +} + +// Peek implements Encoding interface. +func (e *encodingUTF8) Peek(src []byte) []byte { + nextLen := 4 + if len(src) == 0 || src[0] < 0x80 { + nextLen = 1 + } else if src[0] < 0xe0 { + nextLen = 2 + } else if src[0] < 0xf0 { + nextLen = 3 + } + if len(src) < nextLen { + return src + } + return src[:nextLen] +} + +func (e *encodingUTF8) MbLen(bs string) int { + _, size := utf8.DecodeRuneInString(bs) + if size <= 1 { + return 0 + } + return size +} + +// IsValid implements Encoding interface. +func (e *encodingUTF8) IsValid(src []byte) bool { + if utf8.Valid(src) { + return true + } + return e.encodingBase.IsValid(src) +} + +// Transform implements Encoding interface. +func (e *encodingUTF8) Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) { + if e.IsValid(src) { + return src, nil + } + return e.encodingBase.Transform(dest, src, op) +} + +// Foreach implements Encoding interface. +func (e *encodingUTF8) Foreach(src []byte, op Op, fn func(from, to []byte, ok bool) bool) { + var rv rune + for i, w := 0, 0; i < len(src); i += w { + rv, w = utf8.DecodeRune(src[i:]) + meetErr := rv == utf8.RuneError && w == 1 + if !fn(src[i:i+w], src[i:i+w], !meetErr) { + return + } + } +} + +// encodingUTF8MB3Strict is the strict mode of EncodingUTF8MB3. +// MB4 characters are considered invalid. +type encodingUTF8MB3Strict struct { + encodingUTF8 +} + +// IsValid implements Encoding interface. +func (e *encodingUTF8MB3Strict) IsValid(src []byte) bool { + return e.encodingBase.IsValid(src) +} + +// Foreach implements Encoding interface. +func (e *encodingUTF8MB3Strict) Foreach(src []byte, op Op, fn func(srcCh, dstCh []byte, ok bool) bool) { + for i, w := 0, 0; i < len(src); i += w { + var rv rune + rv, w = utf8.DecodeRune(src[i:]) + meetErr := (rv == utf8.RuneError && w == 1) || w > 3 + if !fn(src[i:i+w], src[i:i+w], !meetErr) { + return + } + } +} + +// Transform implements Encoding interface. +func (e *encodingUTF8MB3Strict) Transform(dest *bytes.Buffer, src []byte, op Op) ([]byte, error) { + if e.IsValid(src) { + return src, nil + } + return e.encodingBase.Transform(dest, src, op) +} diff --git a/parser/charset/latin.go b/parser/charset/latin.go deleted file mode 100644 index 04de80d250aef..0000000000000 --- a/parser/charset/latin.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package charset - -import ( - "golang.org/x/text/encoding" - "golang.org/x/text/encoding/charmap" -) - -var ( - LatinEncoding = &Encoding{ - enc: charmap.Windows1252, - name: CharsetLatin1, - charLength: func(bytes []byte) int { - return 1 - }, - specialCase: nil, - } - - BinaryEncoding = &Encoding{ - enc: encoding.Nop, - name: CharsetBin, - charLength: func(bytes []byte) int { - return 1 - }, - specialCase: nil, - } - - ASCIIEncoding = &Encoding{ - enc: encoding.Nop, - name: CharsetASCII, - charLength: func(bytes []byte) int { - return 1 - }, - specialCase: nil, - } -) diff --git a/parser/charset/special_case_tables.go b/parser/charset/special_case_tables.go deleted file mode 100644 index 8a92ee717c566..0000000000000 --- a/parser/charset/special_case_tables.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package charset - -import ( - "strings" - "unicode" -) - -func (e *Encoding) ToUpper(d string) string { - return strings.ToUpperSpecial(e.specialCase, d) -} - -func (e *Encoding) ToLower(d string) string { - return strings.ToLowerSpecial(e.specialCase, d) -} - -func LookupSpecialCase(label string) unicode.SpecialCase { - label = strings.ToLower(strings.Trim(label, "\t\n\r\f ")) - return specailCases[label].c -} - -var specailCases = map[string]struct { - c unicode.SpecialCase -}{ - "utf-8": {nil}, - "ibm866": {nil}, - "iso-8859-2": {nil}, - "iso-8859-3": {nil}, - "iso-8859-4": {nil}, - "iso-8859-5": {nil}, - "iso-8859-6": {nil}, - "iso-8859-7": {nil}, - "iso-8859-8": {nil}, - "iso-8859-8-i": {nil}, - "iso-8859-10": {nil}, - "iso-8859-13": {nil}, - "iso-8859-14": {nil}, - "iso-8859-15": {nil}, - "iso-8859-16": {nil}, - "koi8-r": {nil}, - "macintosh": {nil}, - "windows-874": {nil}, - "windows-1250": {nil}, - "windows-1251": {nil}, - "windows-1252": {nil}, - "windows-1253": {nil}, - "windows-1254": {nil}, - "windows-1255": {nil}, - "windows-1256": {nil}, - "windows-1257": {nil}, - "windows-1258": {nil}, - "x-mac-cyrillic": {nil}, - "gbk": {GBKCase}, - "gb18030": {nil}, - "hz-gb-2312": {nil}, - "big5": {nil}, - "euc-jp": {nil}, - "iso-2022-jp": {nil}, - "shift_jis": {nil}, - "euc-kr": {nil}, - "replacement": {nil}, - "utf-16be": {nil}, - "utf-16le": {nil}, - "x-user-defined": {nil}, -} - -// follow https://dev.mysql.com/worklog/task/?id=4583 for GBK -var GBKCase = unicode.SpecialCase{ - unicode.CaseRange{0x00E0, 0x00E1, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x00E8, 0x00EA, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x00EC, 0x00ED, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x00F2, 0x00F3, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x00F9, 0x00FA, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x00FC, 0x00FC, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x0101, 0x0101, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x0113, 0x0113, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x011B, 0x011B, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x012B, 0x012B, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x0144, 0x0144, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x0148, 0x0148, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x014D, 0x014D, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x016B, 0x016B, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01CE, 0x01CE, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01D0, 0x01D0, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01D2, 0x01D2, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01D4, 0x01D4, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01D6, 0x01D6, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01D8, 0x01D8, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01DA, 0x01DA, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x01DC, 0x01DC, [unicode.MaxCase]rune{0, 0, 0}}, - unicode.CaseRange{0x216A, 0x216B, [unicode.MaxCase]rune{0, 0, 0}}, -} diff --git a/parser/digester.go b/parser/digester.go index ecdab157c0ffd..9cf997beacb94 100644 --- a/parser/digester.go +++ b/parser/digester.go @@ -21,7 +21,6 @@ import ( "reflect" "strings" "sync" - "unicode" "unsafe" "github.com/pingcap/tidb/parser/charset" @@ -170,9 +169,6 @@ func (d *sqlDigester) normalize(sql string) { if tok == invalid { break } - if tok == unicode.ReplacementChar && d.lexer.r.eof() { - break - } if pos.Offset == len(sql) { break } @@ -235,7 +231,7 @@ func (d *sqlDigester) reduceOptimizerHint(tok *token) (reduced bool) { case "force", "use", "ignore": for { tok, _, lit := d.lexer.scan() - if tok == 0 || (tok == unicode.ReplacementChar && d.lexer.r.eof()) { + if (tok == 0 && d.lexer.r.eof()) || tok == invalid { break } if lit == ")" { diff --git a/parser/digester_test.go b/parser/digester_test.go index d69346e2faa7c..2395e7a2a77e0 100644 --- a/parser/digester_test.go +++ b/parser/digester_test.go @@ -54,10 +54,10 @@ func TestNormalize(t *testing.T) { {"select * from `table`", "select * from `table`"}, {"select * from `30`", "select * from `30`"}, {"select * from `select`", "select * from `select`"}, + {"select * from 🥳", "select * from `🥳`"}, // test syntax error, it will be checked by parser, but it should not make normalize dead loop. {"select * from t ignore index(", "select * from `t` ignore index"}, {"select /*+ ", "select "}, - {"select * from 🥳", "select * from"}, {"select 1 / 2", "select ? / ?"}, {"select * from t where a = 40 limit ?, ?", "select * from `t` where `a` = ? limit ..."}, {"select * from t where a > ?", "select * from `t` where `a` > ?"}, diff --git a/parser/docs/quickstart.md b/parser/docs/quickstart.md index f116b240b43b5..a3832f50efdaa 100644 --- a/parser/docs/quickstart.md +++ b/parser/docs/quickstart.md @@ -17,18 +17,20 @@ go mod init colx && touch main.go ## Import Dependencies -First of all, you need to use `go get` to fetch the dependencies through git hash. The git hashes are available in [release page](https://github.com/pingcap/parser/releases). Take `v4.0.2` as an example: +First, you need to use `go get` to fetch the dependencies through git hash. The git hashes are available in [release page](https://github.com/pingcap/tidb/releases). Take `v5.3.0` as an example: ```bash -go get -v github.com/pingcap/parser@3a18f1e +go get -v github.com/pingcap/tidb/parser@4a1b2e9 ``` > **NOTE** +> +> The parser was merged into TiDB repo since v5.3.0. So you can only choose version v5.3.0 or higher in this TiDB repo. > -> You may want to use advanced API on expressions (a kind of AST node), such as numbers, string literals, booleans, nulls, etc. It is strongly recommended to use the `types` package in TiDB repo with the following command: +> You may want to use advanced API on expressions (a kind of AST node), such as numbers, string literals, booleans, nulls, etc. It is strongly recommended using the `types` package in TiDB repo with the following command: > > ```bash -> go get -v github.com/pingcap/tidb/types/parser_driver@328b6d0 +> go get -v github.com/pingcap/tidb/types/parser_driver@4a1b2e9 > ``` > and import it in your golang source code: > ```go @@ -48,17 +50,18 @@ Now, open `main.go` with your favorite editor, and start coding! ## Parse SQL text To convert a SQL text to an AST tree, you need to: -1. Use the [`parser.New()`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#New) function to instantiate a parser, and -2. Invoke the method [`Parse(sql, charset, collation)`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#Parser.Parse) on the parser. +1. Use the [`parser.New()`](https://pkg.go.dev/github.com/pingcap/tidb/parser?tab=doc#New) function to instantiate a parser, and +2. Invoke the method [`Parse(sql, charset, collation)`](https://pkg.go.dev/github.com/pingcap/tidb/parser?tab=doc#Parser.Parse) on the parser. ```go package main import ( "fmt" - "github.com/pingcap/parser" - "github.com/pingcap/parser/ast" - _ "github.com/pingcap/parser/test_driver" + + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" + _ "github.com/pingcap/tidb/parser/test_driver" ) func parse(sql string) (*ast.StmtNode, error) { @@ -80,6 +83,7 @@ func main() { } fmt.Printf("%v\n", *astNode) } + ``` Test the parser by running the following command: @@ -99,19 +103,19 @@ If the parser runs properly, you should get a result like this: > Here are a few things you might want to know: > - To use a parser, a `parser_driver` is required. It decides how to parse the basic data types in SQL. > -> You can use [`github.com/pingcap/parser/test_driver`](https://pkg.go.dev/github.com/pingcap/parser/test_driver) as the `parser_driver` for test. Again, if you need advanced features, please use the `parser_driver` in TiDB (run `go get -v github.com/pingcap/tidb/types/parser_driver@328b6d0` and import it). +> You can use [`github.com/pingcap/tidb/parser/test_driver`](https://pkg.go.dev/github.com/pingcap/tidb/parser/test_driver) as the `parser_driver` for test. Again, if you need advanced features, please use the `parser_driver` in TiDB (run `go get -v github.com/pingcap/tidb/types/parser_driver@4a1b2e9` and import it). > - The instantiated parser object is not goroutine safe. It is better to keep it in a single goroutine. > - The instantiated parser object is not lightweight. It is better to reuse it if possible. -> - The 2nd and 3rd arguments of [`parser.Parse()`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#Parser.Parse) are charset and collation respectively. If you pass an empty string into it, a default value is chosen. +> - The 2nd and 3rd arguments of [`parser.Parse()`](https://pkg.go.dev/github.com/pingcap/tidb/parser?tab=doc#Parser.Parse) are charset and collation respectively. If you pass an empty string into it, a default value is chosen. ## Traverse AST Nodes Now you get the AST tree root of a SQL statement. It is time to extract the column names by traverse. -Parser implements the interface [`ast.Node`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Node) for each kind of AST node, such as SelectStmt, TableName, ColumnName. [`ast.Node`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Node) provides a method `Accept(v Visitor) (node Node, ok bool)` to allow any struct that has implemented [`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Visitor) to traverse itself. +Parser implements the interface [`ast.Node`](https://pkg.go.dev/github.com/pingcap/tidb/parser/ast?tab=doc#Node) for each kind of AST node, such as SelectStmt, TableName, ColumnName. [`ast.Node`](https://pkg.go.dev/github.com/pingcap/tidb/parser/ast?tab=doc#Node) provides a method `Accept(v Visitor) (node Node, ok bool)` to allow any struct that has implemented [`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/tidb/parser/ast?tab=doc#Visitor) to traverse itself. -[`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Visitor) is defined as follows: +[`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/tidb/parser/ast?tab=doc#Visitor) is defined as follows: ```go type Visitor interface { Enter(n Node) (node Node, skipChildren bool) diff --git a/parser/docs/update-parser-for-tidb.md b/parser/docs/update-parser-for-tidb.md deleted file mode 100644 index c1b4d80088387..0000000000000 --- a/parser/docs/update-parser-for-tidb.md +++ /dev/null @@ -1,42 +0,0 @@ -# How to update parser for TiDB - -Assuming that you want to file a PR (pull request) to TiDB, and your PR includes a change in the parser, follow these steps to update the parser in TiDB. - -## Step 1: Make changes in your parser repository - -Fork this repository to your own account and commit the changes to your repository. - -> **Note:** -> -> - Don't forget to run `make test` before you commit! -> - Make sure `parser.go` is updated. - -Suppose the forked repository is `https://github.com/your-repo/parser`. - -## Step 2: Make your parser changes take effect in TiDB and run CI - -1. In your TiDB repository, execute the `replace` instruction to make your parser changes take effect: - - ``` - GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/your-repo/parser@your-branch - ``` - -2. `make dev` to run CI in TiDB. - -3. File a PR to TiDB. - -## Step 3: Merge the PR about the parser to this repository - -File a PR to this repository. **Link the related PR in TiDB in your PR description or comment.** - -This PR will be reviewed, and if everything goes well, it will be merged. - -## Step 4: Update TiDB to use the latest parser - -In your TiDB pull request, modify the `go.mod` file manually or use this command: - -``` -GO111MODULE=on go get -u github.com/pingcap/parser@master -``` - -Make sure the `replace` instruction is changed back to the `require` instruction and the version is the latest. diff --git a/parser/format/format.go b/parser/format/format.go index ef003d6a78d6d..4b9582f49fdd3 100644 --- a/parser/format/format.go +++ b/parser/format/format.go @@ -224,6 +224,7 @@ const ( RestoreStringWithoutDefaultCharset RestoreTiDBSpecialComment + SkipPlacementRuleForRestore ) const ( @@ -300,6 +301,10 @@ func (rf RestoreFlags) HasTiDBSpecialCommentFlag() bool { return rf.has(RestoreTiDBSpecialComment) } +func (rf RestoreFlags) HasSkipPlacementRuleForRestoreFlag() bool { + return rf.has(SkipPlacementRuleForRestore) +} + // RestoreCtx is `Restore` context to hold flags and writer. type RestoreCtx struct { Flags RestoreFlags @@ -325,18 +330,20 @@ func (ctx *RestoreCtx) WriteKeyWord(keyWord string) { fmt.Fprint(ctx.In, keyWord) } -func (ctx *RestoreCtx) WriteWithSpecialComments(featureID string, fn func()) { +func (ctx *RestoreCtx) WriteWithSpecialComments(featureID string, fn func() error) error { if !ctx.Flags.HasTiDBSpecialCommentFlag() { - fn() - return + return fn() } ctx.WritePlain("/*T!") if len(featureID) != 0 { ctx.WritePlainf("[%s]", featureID) } ctx.WritePlain(" ") - fn() + if err := fn(); err != nil { + return err + } ctx.WritePlain(" */") + return nil } // WriteString writes the string into writer diff --git a/parser/format/format_test.go b/parser/format/format_test.go index 955b7fa46e965..429c2c27c19d1 100644 --- a/parser/format/format_test.go +++ b/parser/format/format_test.go @@ -19,6 +19,7 @@ import ( "strings" "testing" + "github.com/pingcap/errors" "github.com/stretchr/testify/require" ) @@ -86,14 +87,23 @@ func TestRestoreSpecialComment(t *testing.T) { var sb strings.Builder sb.Reset() ctx := NewRestoreCtx(RestoreTiDBSpecialComment, &sb) - ctx.WriteWithSpecialComments("fea_id", func() { + require.NoError(t, ctx.WriteWithSpecialComments("fea_id", func() error { ctx.WritePlain("content") - }) + return nil + })) require.Equal(t, "/*T![fea_id] content */", sb.String()) sb.Reset() - ctx.WriteWithSpecialComments("", func() { + require.NoError(t, ctx.WriteWithSpecialComments("", func() error { ctx.WritePlain("shard_row_id_bits") - }) + return nil + })) require.Equal(t, "/*T! shard_row_id_bits */", sb.String()) + + sb.Reset() + err := errors.New("xxxx") + got := ctx.WriteWithSpecialComments("", func() error { + return err + }) + require.Same(t, err, got) } diff --git a/parser/goyacc/main.go b/parser/goyacc/main.go index 1b8fae47cd756..22d78f2998e91 100644 --- a/parser/goyacc/main.go +++ b/parser/goyacc/main.go @@ -324,7 +324,7 @@ func main1(in string) (err error) { } if fn := *oXErrorsGen; fn != "" { - f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0666) + f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0600) if err != nil { return err } diff --git a/parser/hintparser.go b/parser/hintparser.go index 146b3f33bace2..4020f5832970d 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -44,65 +44,65 @@ const ( yyhintDefault = 57415 yyhintEOFCode = 57344 yyhintErrCode = 57345 - hintAggToCop = 57376 - hintBCJoin = 57389 - hintBCJoinPreferLocal = 57390 - hintBKA = 57354 - hintBNL = 57356 + hintAggToCop = 57377 + hintBCJoin = 57390 + hintBKA = 57355 + hintBNL = 57357 hintDupsWeedOut = 57411 hintFalse = 57407 hintFirstMatch = 57412 hintForceIndex = 57401 hintGB = 57410 - hintHashAgg = 57378 - hintHashJoin = 57358 + hintHashAgg = 57379 + hintHashJoin = 57359 hintIdentifier = 57347 - hintIgnoreIndex = 57379 - hintIgnorePlanCache = 57377 - hintIndexMerge = 57362 - hintInlHashJoin = 57380 - hintInlJoin = 57381 - hintInlMergeJoin = 57382 + hintIgnoreIndex = 57380 + hintIgnorePlanCache = 57378 + hintIndexMerge = 57363 + hintInlHashJoin = 57381 + hintInlJoin = 57382 + hintInlMergeJoin = 57383 hintIntLit = 57346 - hintJoinFixedOrder = 57350 - hintJoinOrder = 57351 - hintJoinPrefix = 57352 - hintJoinSuffix = 57353 + hintInvalid = 57348 + hintJoinFixedOrder = 57351 + hintJoinOrder = 57352 + hintJoinPrefix = 57353 + hintJoinSuffix = 57354 hintLimitToCop = 57400 hintLooseScan = 57413 hintMB = 57409 - hintMRR = 57364 + hintMRR = 57365 hintMaterialization = 57414 - hintMaxExecutionTime = 57372 - hintMemoryQuota = 57383 - hintMerge = 57360 - hintNoBKA = 57355 - hintNoBNL = 57357 - hintNoHashJoin = 57359 - hintNoICP = 57366 - hintNoIndexMerge = 57363 - hintNoMRR = 57365 - hintNoMerge = 57361 - hintNoRangeOptimization = 57367 - hintNoSemijoin = 57371 - hintNoSkipScan = 57369 - hintNoSwapJoinInputs = 57384 + hintMaxExecutionTime = 57373 + hintMemoryQuota = 57384 + hintMerge = 57361 + hintNoBKA = 57356 + hintNoBNL = 57358 + hintNoHashJoin = 57360 + hintNoICP = 57367 + hintNoIndexMerge = 57364 + hintNoMRR = 57366 + hintNoMerge = 57362 + hintNoRangeOptimization = 57368 + hintNoSemijoin = 57372 + hintNoSkipScan = 57370 + hintNoSwapJoinInputs = 57385 hintNthPlan = 57399 hintOLAP = 57402 hintOLTP = 57403 hintPartition = 57404 - hintQBName = 57375 - hintQueryType = 57385 - hintReadConsistentReplica = 57386 - hintReadFromStorage = 57387 - hintResourceGroup = 57374 - hintSMJoin = 57388 - hintSemijoin = 57370 - hintSetVar = 57373 - hintSingleAtIdentifier = 57348 - hintSkipScan = 57368 + hintQBName = 57376 + hintQueryType = 57386 + hintReadConsistentReplica = 57387 + hintReadFromStorage = 57388 + hintResourceGroup = 57375 + hintSMJoin = 57389 + hintSemijoin = 57371 + hintSetVar = 57374 + hintSingleAtIdentifier = 57349 + hintSkipScan = 57369 hintStreamAgg = 57391 - hintStringLit = 57349 + hintStringLit = 57350 hintSwapJoinInputs = 57392 hintTiFlash = 57406 hintTiKV = 57405 @@ -115,130 +115,129 @@ const ( hintUseToja = 57396 yyhintMaxDepth = 200 - yyhintTabOfs = -172 + yyhintTabOfs = -170 ) var ( yyhintXLAT = map[int]int{ - 41: 0, // ')' (130x) - 57376: 1, // hintAggToCop (122x) - 57389: 2, // hintBCJoin (122x) - 57390: 3, // hintBCJoinPreferLocal (122x) - 57354: 4, // hintBKA (122x) - 57356: 5, // hintBNL (122x) - 57401: 6, // hintForceIndex (122x) - 57378: 7, // hintHashAgg (122x) - 57358: 8, // hintHashJoin (122x) - 57379: 9, // hintIgnoreIndex (122x) - 57377: 10, // hintIgnorePlanCache (122x) - 57362: 11, // hintIndexMerge (122x) - 57380: 12, // hintInlHashJoin (122x) - 57381: 13, // hintInlJoin (122x) - 57382: 14, // hintInlMergeJoin (122x) - 57350: 15, // hintJoinFixedOrder (122x) - 57351: 16, // hintJoinOrder (122x) - 57352: 17, // hintJoinPrefix (122x) - 57353: 18, // hintJoinSuffix (122x) - 57400: 19, // hintLimitToCop (122x) - 57372: 20, // hintMaxExecutionTime (122x) - 57383: 21, // hintMemoryQuota (122x) - 57360: 22, // hintMerge (122x) - 57364: 23, // hintMRR (122x) - 57355: 24, // hintNoBKA (122x) - 57357: 25, // hintNoBNL (122x) - 57359: 26, // hintNoHashJoin (122x) - 57366: 27, // hintNoICP (122x) - 57363: 28, // hintNoIndexMerge (122x) - 57361: 29, // hintNoMerge (122x) - 57365: 30, // hintNoMRR (122x) - 57367: 31, // hintNoRangeOptimization (122x) - 57371: 32, // hintNoSemijoin (122x) - 57369: 33, // hintNoSkipScan (122x) - 57384: 34, // hintNoSwapJoinInputs (122x) - 57399: 35, // hintNthPlan (122x) - 57375: 36, // hintQBName (122x) - 57385: 37, // hintQueryType (122x) - 57386: 38, // hintReadConsistentReplica (122x) - 57387: 39, // hintReadFromStorage (122x) - 57374: 40, // hintResourceGroup (122x) - 57370: 41, // hintSemijoin (122x) - 57373: 42, // hintSetVar (122x) - 57368: 43, // hintSkipScan (122x) - 57388: 44, // hintSMJoin (122x) - 57391: 45, // hintStreamAgg (122x) - 57392: 46, // hintSwapJoinInputs (122x) - 57397: 47, // hintTimeRange (122x) - 57398: 48, // hintUseCascades (122x) - 57394: 49, // hintUseIndex (122x) - 57393: 50, // hintUseIndexMerge (122x) - 57395: 51, // hintUsePlanCache (122x) - 57396: 52, // hintUseToja (122x) - 44: 53, // ',' (120x) - 57411: 54, // hintDupsWeedOut (100x) - 57412: 55, // hintFirstMatch (100x) - 57413: 56, // hintLooseScan (100x) - 57414: 57, // hintMaterialization (100x) - 57406: 58, // hintTiFlash (100x) - 57405: 59, // hintTiKV (100x) - 57407: 60, // hintFalse (99x) - 57402: 61, // hintOLAP (99x) - 57403: 62, // hintOLTP (99x) - 57408: 63, // hintTrue (99x) - 57410: 64, // hintGB (98x) - 57409: 65, // hintMB (98x) - 57347: 66, // hintIdentifier (97x) - 57348: 67, // hintSingleAtIdentifier (82x) - 93: 68, // ']' (76x) - 57404: 69, // hintPartition (70x) - 46: 70, // '.' (66x) - 61: 71, // '=' (66x) - 40: 72, // '(' (61x) - 57344: 73, // $end (24x) - 57435: 74, // QueryBlockOpt (17x) - 57427: 75, // Identifier (13x) - 57346: 76, // hintIntLit (8x) - 57349: 77, // hintStringLit (5x) - 57417: 78, // CommaOpt (4x) - 57423: 79, // HintTable (4x) - 57424: 80, // HintTableList (4x) - 91: 81, // '[' (3x) - 57416: 82, // BooleanHintName (2x) - 57418: 83, // HintIndexList (2x) - 57420: 84, // HintStorageType (2x) - 57421: 85, // HintStorageTypeAndTable (2x) - 57425: 86, // HintTableListOpt (2x) - 57430: 87, // JoinOrderOptimizerHintName (2x) - 57431: 88, // NullaryHintName (2x) - 57434: 89, // PartitionListOpt (2x) - 57437: 90, // StorageOptimizerHintOpt (2x) - 57438: 91, // SubqueryOptimizerHintName (2x) - 57441: 92, // SubqueryStrategy (2x) - 57442: 93, // SupportedIndexLevelOptimizerHintName (2x) - 57443: 94, // SupportedTableLevelOptimizerHintName (2x) - 57444: 95, // TableOptimizerHintOpt (2x) - 57446: 96, // UnsupportedIndexLevelOptimizerHintName (2x) - 57447: 97, // UnsupportedTableLevelOptimizerHintName (2x) - 57419: 98, // HintQueryType (1x) - 57422: 99, // HintStorageTypeAndTableList (1x) - 57426: 100, // HintTrueOrFalse (1x) - 57428: 101, // IndexNameList (1x) - 57429: 102, // IndexNameListOpt (1x) - 57432: 103, // OptimizerHintList (1x) - 57433: 104, // PartitionList (1x) - 57436: 105, // Start (1x) - 57439: 106, // SubqueryStrategies (1x) - 57440: 107, // SubqueryStrategiesOpt (1x) - 57445: 108, // UnitOfBytes (1x) - 57448: 109, // Value (1x) - 57415: 110, // $default (0x) - 57345: 111, // error (0x) + 41: 0, // ')' (129x) + 57377: 1, // hintAggToCop (121x) + 57390: 2, // hintBCJoin (121x) + 57355: 3, // hintBKA (121x) + 57357: 4, // hintBNL (121x) + 57401: 5, // hintForceIndex (121x) + 57379: 6, // hintHashAgg (121x) + 57359: 7, // hintHashJoin (121x) + 57380: 8, // hintIgnoreIndex (121x) + 57378: 9, // hintIgnorePlanCache (121x) + 57363: 10, // hintIndexMerge (121x) + 57381: 11, // hintInlHashJoin (121x) + 57382: 12, // hintInlJoin (121x) + 57383: 13, // hintInlMergeJoin (121x) + 57351: 14, // hintJoinFixedOrder (121x) + 57352: 15, // hintJoinOrder (121x) + 57353: 16, // hintJoinPrefix (121x) + 57354: 17, // hintJoinSuffix (121x) + 57400: 18, // hintLimitToCop (121x) + 57373: 19, // hintMaxExecutionTime (121x) + 57384: 20, // hintMemoryQuota (121x) + 57361: 21, // hintMerge (121x) + 57365: 22, // hintMRR (121x) + 57356: 23, // hintNoBKA (121x) + 57358: 24, // hintNoBNL (121x) + 57360: 25, // hintNoHashJoin (121x) + 57367: 26, // hintNoICP (121x) + 57364: 27, // hintNoIndexMerge (121x) + 57362: 28, // hintNoMerge (121x) + 57366: 29, // hintNoMRR (121x) + 57368: 30, // hintNoRangeOptimization (121x) + 57372: 31, // hintNoSemijoin (121x) + 57370: 32, // hintNoSkipScan (121x) + 57385: 33, // hintNoSwapJoinInputs (121x) + 57399: 34, // hintNthPlan (121x) + 57376: 35, // hintQBName (121x) + 57386: 36, // hintQueryType (121x) + 57387: 37, // hintReadConsistentReplica (121x) + 57388: 38, // hintReadFromStorage (121x) + 57375: 39, // hintResourceGroup (121x) + 57371: 40, // hintSemijoin (121x) + 57374: 41, // hintSetVar (121x) + 57369: 42, // hintSkipScan (121x) + 57389: 43, // hintSMJoin (121x) + 57391: 44, // hintStreamAgg (121x) + 57392: 45, // hintSwapJoinInputs (121x) + 57397: 46, // hintTimeRange (121x) + 57398: 47, // hintUseCascades (121x) + 57394: 48, // hintUseIndex (121x) + 57393: 49, // hintUseIndexMerge (121x) + 57395: 50, // hintUsePlanCache (121x) + 57396: 51, // hintUseToja (121x) + 44: 52, // ',' (119x) + 57411: 53, // hintDupsWeedOut (99x) + 57412: 54, // hintFirstMatch (99x) + 57413: 55, // hintLooseScan (99x) + 57414: 56, // hintMaterialization (99x) + 57406: 57, // hintTiFlash (99x) + 57405: 58, // hintTiKV (99x) + 57407: 59, // hintFalse (98x) + 57402: 60, // hintOLAP (98x) + 57403: 61, // hintOLTP (98x) + 57408: 62, // hintTrue (98x) + 57410: 63, // hintGB (97x) + 57409: 64, // hintMB (97x) + 57347: 65, // hintIdentifier (96x) + 57349: 66, // hintSingleAtIdentifier (81x) + 93: 67, // ']' (75x) + 57404: 68, // hintPartition (69x) + 46: 69, // '.' (65x) + 61: 70, // '=' (65x) + 40: 71, // '(' (60x) + 57344: 72, // $end (24x) + 57435: 73, // QueryBlockOpt (17x) + 57427: 74, // Identifier (13x) + 57346: 75, // hintIntLit (8x) + 57350: 76, // hintStringLit (5x) + 57417: 77, // CommaOpt (4x) + 57423: 78, // HintTable (4x) + 57424: 79, // HintTableList (4x) + 91: 80, // '[' (3x) + 57416: 81, // BooleanHintName (2x) + 57418: 82, // HintIndexList (2x) + 57420: 83, // HintStorageType (2x) + 57421: 84, // HintStorageTypeAndTable (2x) + 57425: 85, // HintTableListOpt (2x) + 57430: 86, // JoinOrderOptimizerHintName (2x) + 57431: 87, // NullaryHintName (2x) + 57434: 88, // PartitionListOpt (2x) + 57437: 89, // StorageOptimizerHintOpt (2x) + 57438: 90, // SubqueryOptimizerHintName (2x) + 57441: 91, // SubqueryStrategy (2x) + 57442: 92, // SupportedIndexLevelOptimizerHintName (2x) + 57443: 93, // SupportedTableLevelOptimizerHintName (2x) + 57444: 94, // TableOptimizerHintOpt (2x) + 57446: 95, // UnsupportedIndexLevelOptimizerHintName (2x) + 57447: 96, // UnsupportedTableLevelOptimizerHintName (2x) + 57419: 97, // HintQueryType (1x) + 57422: 98, // HintStorageTypeAndTableList (1x) + 57426: 99, // HintTrueOrFalse (1x) + 57428: 100, // IndexNameList (1x) + 57429: 101, // IndexNameListOpt (1x) + 57432: 102, // OptimizerHintList (1x) + 57433: 103, // PartitionList (1x) + 57436: 104, // Start (1x) + 57439: 105, // SubqueryStrategies (1x) + 57440: 106, // SubqueryStrategiesOpt (1x) + 57445: 107, // UnitOfBytes (1x) + 57448: 108, // Value (1x) + 57415: 109, // $default (0x) + 57345: 110, // error (0x) + 57348: 111, // hintInvalid (0x) } yyhintSymNames = []string{ "')'", "hintAggToCop", "hintBCJoin", - "hintBCJoinPreferLocal", "hintBKA", "hintBNL", "hintForceIndex", @@ -347,85 +346,70 @@ var ( "Value", "$default", "error", + "hintInvalid", } yyhintReductions = []struct{ xsym, components int }{ {0, 1}, - {105, 1}, - {103, 1}, - {103, 3}, + {104, 1}, + {102, 1}, + {102, 3}, + {102, 1}, + {102, 3}, + {94, 4}, + {94, 4}, + {94, 4}, + {94, 4}, + {94, 4}, + {94, 4}, + {94, 5}, + {94, 5}, + {94, 5}, + {94, 6}, + {94, 4}, + {94, 4}, + {94, 6}, + {94, 6}, + {94, 5}, + {94, 4}, + {94, 5}, + {89, 5}, + {98, 1}, + {98, 3}, + {84, 4}, + {73, 0}, + {73, 1}, + {77, 0}, + {77, 1}, + {88, 0}, + {88, 4}, {103, 1}, {103, 3}, - {95, 4}, - {95, 4}, - {95, 4}, - {95, 4}, - {95, 4}, - {95, 4}, - {95, 5}, - {95, 5}, - {95, 5}, - {95, 6}, - {95, 4}, - {95, 4}, - {95, 6}, - {95, 6}, - {95, 5}, - {95, 4}, - {95, 5}, - {90, 5}, - {99, 1}, - {99, 3}, - {85, 4}, - {74, 0}, - {74, 1}, - {78, 0}, - {78, 1}, - {89, 0}, - {89, 4}, - {104, 1}, - {104, 3}, - {86, 1}, - {86, 1}, - {80, 2}, - {80, 3}, + {85, 1}, + {85, 1}, + {79, 2}, {79, 3}, - {79, 5}, - {83, 4}, - {102, 0}, - {102, 1}, + {78, 3}, + {78, 5}, + {82, 4}, + {101, 0}, {101, 1}, - {101, 3}, - {107, 0}, - {107, 1}, + {100, 1}, + {100, 3}, + {106, 0}, {106, 1}, - {106, 3}, - {109, 1}, - {109, 1}, - {109, 1}, + {105, 1}, + {105, 3}, {108, 1}, {108, 1}, - {100, 1}, - {100, 1}, - {87, 1}, - {87, 1}, - {87, 1}, - {97, 1}, - {97, 1}, - {97, 1}, - {97, 1}, - {97, 1}, - {97, 1}, - {97, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, + {108, 1}, + {107, 1}, + {107, 1}, + {99, 1}, + {99, 1}, + {86, 1}, + {86, 1}, + {86, 1}, {96, 1}, {96, 1}, {96, 1}, @@ -437,402 +421,414 @@ var ( {93, 1}, {93, 1}, {93, 1}, - {91, 1}, - {91, 1}, + {93, 1}, + {93, 1}, + {93, 1}, + {93, 1}, + {95, 1}, + {95, 1}, + {95, 1}, + {95, 1}, + {95, 1}, + {95, 1}, + {95, 1}, {92, 1}, {92, 1}, {92, 1}, {92, 1}, - {82, 1}, - {82, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {88, 1}, - {98, 1}, - {98, 1}, - {84, 1}, - {84, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, - {75, 1}, + {90, 1}, + {90, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {81, 1}, + {81, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {87, 1}, + {97, 1}, + {97, 1}, + {83, 1}, + {83, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, + {74, 1}, } yyhintXErrors = map[yyhintXError]string{} - yyhintParseTab = [255][]uint16{ + yyhintParseTab = [253][]uint16{ // 0 - {1: 232, 206, 207, 198, 200, 224, 230, 213, 222, 236, 214, 209, 208, 212, 177, 195, 196, 197, 233, 184, 189, 203, 215, 199, 201, 202, 217, 234, 204, 216, 218, 226, 220, 211, 185, 188, 193, 235, 194, 187, 225, 186, 219, 205, 231, 210, 190, 228, 221, 223, 229, 227, 82: 191, 87: 178, 192, 90: 176, 183, 93: 182, 180, 175, 181, 179, 103: 174, 105: 173}, - {73: 172}, - {1: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 324, 73: 171, 78: 424}, - {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 73: 170}, - {1: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 73: 168}, + {1: 229, 204, 196, 198, 221, 227, 210, 219, 233, 211, 206, 205, 209, 175, 193, 194, 195, 230, 182, 187, 201, 212, 197, 199, 200, 214, 231, 202, 213, 215, 223, 217, 208, 183, 186, 191, 232, 192, 185, 222, 184, 216, 203, 228, 207, 188, 225, 218, 220, 226, 224, 81: 189, 86: 176, 190, 89: 174, 181, 92: 180, 178, 173, 179, 177, 102: 172, 104: 171}, + {72: 170}, + {1: 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 320, 72: 169, 77: 420}, + {1: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 72: 168}, + {1: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 72: 166}, // 5 - {72: 421}, - {72: 418}, - {72: 415}, - {72: 410}, - {72: 407}, + {71: 417}, + {71: 414}, + {71: 411}, + {71: 406}, + {71: 403}, // 10 - {72: 396}, - {72: 384}, - {72: 380}, - {72: 376}, - {72: 368}, + {71: 392}, + {71: 380}, + {71: 376}, + {71: 372}, + {71: 364}, // 15 - {72: 365}, - {72: 362}, - {72: 355}, - {72: 350}, - {72: 344}, + {71: 361}, + {71: 358}, + {71: 351}, + {71: 346}, + {71: 340}, // 20 - {72: 341}, - {72: 335}, - {72: 237}, - {72: 115}, - {72: 114}, + {71: 337}, + {71: 331}, + {71: 234}, + {71: 113}, + {71: 112}, // 25 - {72: 113}, - {72: 112}, - {72: 111}, - {72: 110}, - {72: 109}, + {71: 111}, + {71: 110}, + {71: 109}, + {71: 108}, + {71: 107}, // 30 - {72: 108}, - {72: 107}, - {72: 106}, - {72: 105}, - {72: 104}, + {71: 106}, + {71: 105}, + {71: 104}, + {71: 103}, + {71: 102}, // 35 - {72: 103}, - {72: 102}, - {72: 101}, - {72: 100}, - {72: 99}, + {71: 101}, + {71: 100}, + {71: 99}, + {71: 98}, + {71: 97}, // 40 - {72: 98}, - {72: 97}, - {72: 96}, - {72: 95}, - {72: 94}, + {71: 96}, + {71: 95}, + {71: 94}, + {71: 93}, + {71: 92}, // 45 - {72: 93}, - {72: 92}, - {72: 91}, - {72: 90}, - {72: 89}, + {71: 91}, + {71: 90}, + {71: 89}, + {71: 88}, + {71: 87}, // 50 - {72: 88}, - {72: 87}, - {72: 86}, - {72: 85}, - {72: 84}, + {71: 86}, + {71: 85}, + {71: 84}, + {71: 83}, + {71: 78}, // 55 - {72: 79}, - {72: 78}, - {72: 77}, - {72: 76}, - {72: 75}, + {71: 77}, + {71: 76}, + {71: 75}, + {71: 74}, + {71: 73}, // 60 - {72: 74}, - {72: 73}, - {72: 72}, - {72: 71}, - {72: 70}, + {71: 72}, + {71: 71}, + {71: 70}, + {71: 69}, + {57: 143, 143, 66: 236, 73: 235}, // 65 - {58: 145, 145, 67: 239, 74: 238}, - {58: 244, 243, 84: 242, 241, 99: 240}, - {144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 68: 144, 144, 76: 144}, - {332, 53: 333}, - {148, 53: 148}, + {57: 241, 240, 83: 239, 238, 98: 237}, + {142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 67: 142, 142, 75: 142}, + {328, 52: 329}, + {146, 52: 146}, + {80: 242}, // 70 - {81: 245}, - {81: 67}, - {81: 66}, - {1: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 247, 80: 246}, - {53: 330, 68: 329}, + {80: 66}, + {80: 65}, + {1: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 244, 79: 243}, + {52: 326, 67: 325}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 245}, // 75 - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 249, 79: 248}, - {135, 53: 135, 68: 135}, - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 145, 145, 316, 74: 315}, - {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, - {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + {133, 52: 133, 67: 133}, + {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 143, 143, 312, 73: 311}, + {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}, + {62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62}, // 80 - {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}, - {62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62}, - {61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61}, - {60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60}, - {59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59}, + {61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61}, + {60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60}, + {59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59}, + {58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58}, + {57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57}, // 85 - {58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58}, - {57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57}, - {56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56}, - {55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55}, - {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}, + {56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56}, + {55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55}, + {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}, + {53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53}, + {52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52}, // 90 - {53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53}, - {52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52}, - {51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51}, - {50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, - {49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49}, + {51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51}, + {50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, + {49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49}, + {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48}, + {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47}, // 95 - {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48}, - {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47}, - {46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46}, - {45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45}, - {44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44}, + {46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46}, + {45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45}, + {44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44}, + {43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43}, + {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}, // 100 - {43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43}, - {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}, - {41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41}, - {40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}, - {39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39}, + {41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41}, + {40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}, + {39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39}, + {38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38}, + {37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37}, // 105 - {38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38}, - {37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37}, - {36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}, - {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, - {34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34}, + {36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}, + {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, + {34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34}, + {33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33}, + {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, // 110 - {33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33}, - {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - {31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}, - {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, - {29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}, + {31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}, + {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, + {29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}, + {28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, + {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}, // 115 - {28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, - {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}, - {26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26}, - {25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}, - {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}, + {26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26}, + {25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}, + {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}, + {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}, + {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, // 120 - {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}, - {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, - {21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}, - {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, - {19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}, + {21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}, + {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, + {19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}, + {18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18}, + {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}, // 125 - {18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18}, - {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}, - {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, - {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, - {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}, + {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}, + {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, // 130 - {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}, - {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, - {11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, - {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, + {11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, + {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, + {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, + {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, // 135 - {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, - {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, - {6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}, - {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, - {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, // 140 - {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, - {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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}, - {141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 68: 141, 319, 89: 328}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 317}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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}, + {139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 67: 139, 315, 88: 324}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 313}, + {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 143, 143, 73: 314}, + {139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 67: 139, 315, 88: 316}, // 145 - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 145, 145, 74: 318}, - {141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 68: 141, 319, 89: 320}, - {72: 321}, - {132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 68: 132}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 323, 104: 322}, + {71: 317}, + {130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 67: 130}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 319, 103: 318}, + {321, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 320, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 77: 322}, + {137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137}, // 150 - {325, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 324, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 78: 326}, - {139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139}, - {142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 54: 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 77: 142}, - {140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 68: 140}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 327}, + {140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 53: 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 76: 140}, + {138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 67: 138}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 323}, + {136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136}, + {131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 67: 131}, // 155 - {138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138}, - {133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 68: 133}, - {146, 53: 146}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 249, 79: 331}, - {134, 53: 134, 68: 134}, + {144, 52: 144}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 327}, + {132, 52: 132, 67: 132}, + {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 72: 147}, + {57: 241, 240, 83: 239, 330}, // 160 - {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 73: 149}, - {58: 244, 243, 84: 242, 334}, - {147, 53: 147}, - {61: 145, 145, 67: 239, 74: 336}, - {61: 338, 339, 98: 337}, - // 165 - {340}, - {69}, + {145, 52: 145}, + {60: 143, 143, 66: 236, 73: 332}, + {60: 334, 335, 97: 333}, + {336}, {68}, - {1: 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 73: 150}, - {145, 67: 239, 74: 342}, + // 165 + {67}, + {1: 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 72: 148}, + {143, 66: 236, 73: 338}, + {339}, + {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 72: 149}, // 170 - {343}, - {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 73: 151}, - {60: 145, 63: 145, 67: 239, 74: 345}, - {60: 348, 63: 347, 100: 346}, - {349}, + {59: 143, 62: 143, 66: 236, 73: 341}, + {59: 344, 62: 343, 99: 342}, + {345}, + {115}, + {114}, // 175 - {117}, - {116}, - {1: 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 73: 152}, - {77: 351}, - {53: 324, 77: 143, 352}, + {1: 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 72: 150}, + {76: 347}, + {52: 320, 76: 141, 348}, + {76: 349}, + {350}, // 180 - {77: 353}, - {354}, - {1: 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 73: 153}, - {67: 239, 74: 356, 76: 145}, - {76: 357}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 72: 151}, + {66: 236, 73: 352, 75: 143}, + {75: 353}, + {63: 356, 355, 107: 354}, + {357}, // 185 - {64: 360, 359, 108: 358}, - {361}, - {119}, - {118}, - {1: 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 73: 154}, + {117}, + {116}, + {1: 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 72: 152}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 359}, + {360}, // 190 - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 363}, - {364}, - {1: 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 73: 155}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 366}, - {367}, + {1: 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 72: 153}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 362}, + {363}, + {1: 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 72: 154}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 365}, // 195 - {1: 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 73: 156}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 369}, - {71: 370}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 373, 374, 372, 109: 371}, - {375}, - // 200 - {122}, - {121}, + {70: 366}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 369, 370, 368, 108: 367}, + {371}, {120}, - {1: 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 73: 157}, - {67: 239, 74: 377, 76: 145}, + {119}, + // 200 + {118}, + {1: 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 72: 155}, + {66: 236, 73: 373, 75: 143}, + {75: 374}, + {375}, // 205 - {76: 378}, + {1: 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 72: 156}, + {66: 236, 73: 377, 75: 143}, + {75: 378}, {379}, - {1: 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 73: 158}, - {67: 239, 74: 381, 76: 145}, - {76: 382}, + {1: 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 72: 157}, // 210 - {383}, - {1: 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 73: 159}, - {145, 54: 145, 145, 145, 145, 67: 239, 74: 385}, - {126, 54: 389, 390, 391, 392, 92: 388, 106: 387, 386}, - {395}, + {143, 53: 143, 143, 143, 143, 66: 236, 73: 381}, + {124, 53: 385, 386, 387, 388, 91: 384, 105: 383, 382}, + {391}, + {123, 52: 389}, + {122, 52: 122}, // 215 - {125, 53: 393}, - {124, 53: 124}, - {83, 53: 83}, - {82, 53: 82}, - {81, 53: 81}, + {82, 52: 82}, + {81, 52: 81}, + {80, 52: 80}, + {79, 52: 79}, + {53: 385, 386, 387, 388, 91: 390}, // 220 - {80, 53: 80}, - {54: 389, 390, 391, 392, 92: 394}, - {123, 53: 123}, - {1: 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 73: 160}, - {1: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 398, 83: 397}, + {121, 52: 121}, + {1: 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 72: 158}, + {1: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 394, 82: 393}, + {402}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 395}, // 225 - {406}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 249, 79: 399}, - {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 324, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 78: 400}, - {130, 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 403, 101: 402, 401}, - {131}, + {141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 320, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 77: 396}, + {128, 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 399, 100: 398, 397}, + {129}, + {127, 52: 400}, + {126, 52: 126}, // 230 - {129, 53: 404}, - {128, 53: 128}, - {1: 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 405}, - {127, 53: 127}, - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 73: 161}, + {1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 401}, + {125, 52: 125}, + {1: 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 72: 159}, + {1: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 394, 82: 404}, + {405}, // 235 - {1: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 398, 83: 408}, - {409}, - {1: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 73: 162}, - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 413, 80: 412, 86: 411}, - {414}, + {1: 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 72: 160}, + {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 409, 79: 408, 85: 407}, + {410}, + {135, 52: 326}, + {134, 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 245}, // 240 - {137, 53: 330}, - {136, 277, 291, 292, 255, 257, 302, 280, 259, 281, 279, 263, 282, 283, 284, 251, 252, 253, 254, 278, 273, 285, 261, 265, 256, 258, 260, 267, 264, 262, 266, 268, 272, 270, 286, 301, 276, 287, 288, 289, 275, 271, 274, 269, 290, 293, 294, 299, 300, 296, 295, 297, 298, 54: 311, 312, 313, 314, 306, 305, 307, 303, 304, 308, 310, 309, 250, 75: 249, 79: 248}, - {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 73: 163}, - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 413, 80: 412, 86: 416}, - {417}, + {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 72: 161}, + {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 409, 79: 408, 85: 412}, + {413}, + {1: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 72: 162}, + {1: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 244, 79: 415}, // 245 - {1: 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 73: 164}, - {1: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 54: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 239, 74: 247, 80: 419}, - {420, 53: 330}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 73: 165}, - {145, 67: 239, 74: 422}, + {416, 52: 326}, + {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 72: 163}, + {143, 66: 236, 73: 418}, + {419}, + {1: 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 72: 164}, // 250 - {423}, - {1: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 73: 166}, - {1: 232, 206, 207, 198, 200, 224, 230, 213, 222, 236, 214, 209, 208, 212, 177, 195, 196, 197, 233, 184, 189, 203, 215, 199, 201, 202, 217, 234, 204, 216, 218, 226, 220, 211, 185, 188, 193, 235, 194, 187, 225, 186, 219, 205, 231, 210, 190, 228, 221, 223, 229, 227, 82: 191, 87: 178, 192, 90: 426, 183, 93: 182, 180, 425, 181, 179}, - {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 73: 169}, - {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 73: 167}, + {1: 229, 204, 196, 198, 221, 227, 210, 219, 233, 211, 206, 205, 209, 175, 193, 194, 195, 230, 182, 187, 201, 212, 197, 199, 200, 214, 231, 202, 213, 215, 223, 217, 208, 183, 186, 191, 232, 192, 185, 222, 184, 216, 203, 228, 207, 188, 225, 218, 220, 226, 224, 81: 189, 86: 176, 190, 89: 422, 181, 92: 180, 178, 421, 179, 177}, + {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 72: 167}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 72: 165}, } ) @@ -872,7 +868,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) { } func yyhintParse(yylex yyhintLexer, parser *hintParser) int { - const yyError = 111 + const yyError = 110 yyEx, _ := yylex.(yyhintLexerEx) var yyn int diff --git a/parser/hintparser.y b/parser/hintparser.y index 79738887e3ff6..332d53eb7379e 100644 --- a/parser/hintparser.y +++ b/parser/hintparser.y @@ -43,6 +43,7 @@ import ( /*yy:token "%c" */ hintIdentifier + hintInvalid "a special token never used by parser, used by lexer to indicate error" /*yy:token "@%c" */ hintSingleAtIdentifier "identifier with single leading at" @@ -93,7 +94,6 @@ import ( hintReadFromStorage "READ_FROM_STORAGE" hintSMJoin "MERGE_JOIN" hintBCJoin "BROADCAST_JOIN" - hintBCJoinPreferLocal "BROADCAST_JOIN_LOCAL" hintStreamAgg "STREAM_AGG" hintSwapJoinInputs "SWAP_JOIN_INPUTS" hintUseIndexMerge "USE_INDEX_MERGE" @@ -533,7 +533,6 @@ UnsupportedTableLevelOptimizerHintName: SupportedTableLevelOptimizerHintName: "MERGE_JOIN" | "BROADCAST_JOIN" -| "BROADCAST_JOIN_LOCAL" | "INL_JOIN" | "INL_HASH_JOIN" | "SWAP_JOIN_INPUTS" @@ -634,7 +633,6 @@ Identifier: | "READ_FROM_STORAGE" | "MERGE_JOIN" | "BROADCAST_JOIN" -| "BROADCAST_JOIN_LOCAL" | "STREAM_AGG" | "SWAP_JOIN_INPUTS" | "USE_INDEX_MERGE" diff --git a/parser/hintparserimpl.go b/parser/hintparserimpl.go index 2faf988cdbb75..dae3dedb75daa 100644 --- a/parser/hintparserimpl.go +++ b/parser/hintparserimpl.go @@ -16,7 +16,6 @@ package parser import ( "strconv" "strings" - "unicode" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" @@ -51,7 +50,7 @@ func (hs *hintScanner) Lex(lval *yyhintSymType) int { n, e := strconv.ParseUint(lit, 10, 64) if e != nil { hs.AppendError(ErrWarnOptimizerHintInvalidInteger.GenWithStackByArgs(lit)) - return int(unicode.ReplacementChar) + return hintInvalid } lval.number = n return hintIntLit @@ -108,7 +107,7 @@ func (hs *hintScanner) Lex(lval *yyhintSymType) int { } hs.AppendError(ErrWarnOptimizerHintInvalidToken.GenWithStackByArgs(errorTokenType, lit, tok)) - return int(unicode.ReplacementChar) + return hintInvalid } type hintParser struct { diff --git a/parser/lexer.go b/parser/lexer.go index 94358fe51a962..1727b5718b6ae 100644 --- a/parser/lexer.go +++ b/parser/lexer.go @@ -19,7 +19,6 @@ import ( "strconv" "strings" "unicode" - "unicode/utf8" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" @@ -40,7 +39,8 @@ type Scanner struct { r reader buf bytes.Buffer - encoding *charset.Encoding + client charset.Encoding + connection charset.Encoding errs []error warns []error @@ -89,7 +89,9 @@ func (s *Scanner) Errors() (warns []error, errs []error) { // reset resets the sql string to be scanned. func (s *Scanner) reset(sql string) { - s.r = reader{s: sql, p: Pos{Line: 1}} + s.client = charset.FindEncoding(mysql.DefaultCharset) + s.connection = charset.FindEncoding(mysql.DefaultCharset) + s.r = reader{s: sql, p: Pos{Line: 1}, l: len(sql)} s.buf.Reset() s.errs = s.errs[:0] s.warns = s.warns[:0] @@ -145,13 +147,35 @@ func (s *Scanner) AppendWarn(err error) { s.warns = append(s.warns, err) } -func (s *Scanner) tryDecodeToUTF8String(sql string) string { - utf8Lit, err := s.encoding.DecodeString(sql) +// convert2System convert lit from client encoding to system encoding which is utf8mb4. +func (s *Scanner) convert2System(tok int, lit string) (int, string) { + utf8Lit, err := s.client.Transform(nil, charset.HackSlice(lit), charset.OpDecodeReplace) + if err != nil { + s.AppendWarn(err) + } + + return tok, charset.HackString(utf8Lit) +} + +// convert2Connection convert lit from client encoding to connection encoding. +func (s *Scanner) convert2Connection(tok int, lit string) (int, string) { + if mysql.IsUTF8Charset(s.client.Name()) { + return tok, lit + } + utf8Lit, err := s.client.Transform(nil, charset.HackSlice(lit), charset.OpDecodeReplace) if err != nil { s.AppendError(err) + if s.sqlMode.HasStrictMode() && s.client.Tp() == s.connection.Tp() { + return invalid, lit + } s.lastErrorAsWarn() } - return utf8Lit + + // It is definitely valid if `client` is the same with `connection`, so just transform if they are not the same. + if s.client.Tp() != s.connection.Tp() { + utf8Lit, _ = s.connection.Transform(nil, utf8Lit, charset.OpReplaceNoErr) + } + return tok, charset.HackString(utf8Lit) } func (s *Scanner) getNextToken() int { @@ -232,10 +256,9 @@ func (s *Scanner) Lex(v *yySymType) int { case quotedIdentifier, identifier: tok = identifier s.identifierDot = s.r.peek() == '.' - } - - if tok == unicode.ReplacementChar { - return invalid + tok, v.ident = s.convert2System(tok, lit) + case stringLit: + tok, v.ident = s.convert2Connection(tok, lit) } return tok @@ -270,7 +293,7 @@ func (s *Scanner) EnableWindowFunc(val bool) { func (s *Scanner) InheritScanner(sql string) *Scanner { return &Scanner{ r: reader{s: sql}, - encoding: s.encoding, + client: s.client, sqlMode: s.sqlMode, supportWindowFunc: s.supportWindowFunc, } @@ -278,7 +301,9 @@ func (s *Scanner) InheritScanner(sql string) *Scanner { // NewScanner returns a new scanner object. func NewScanner(s string) *Scanner { - return &Scanner{r: reader{s: s}} + lexer := &Scanner{r: reader{s: s}} + lexer.reset(s) + return lexer } func (s *Scanner) handleIdent(lval *yySymType) int { @@ -297,13 +322,15 @@ func (s *Scanner) handleIdent(lval *yySymType) int { return underscoreCS } -func (s *Scanner) skipWhitespace() rune { - return s.r.incAsLongAs(unicode.IsSpace) +func (s *Scanner) skipWhitespace() byte { + return s.r.incAsLongAs(func(b byte) bool { + return unicode.IsSpace(rune(b)) + }) } func (s *Scanner) scan() (tok int, pos Pos, lit string) { ch0 := s.r.peek() - if unicode.IsSpace(ch0) { + if unicode.IsSpace(rune(ch0)) { ch0 = s.skipWhitespace() } pos = s.r.pos() @@ -319,10 +346,7 @@ func (s *Scanner) scan() (tok int, pos Pos, lit string) { // search a trie to get a token. node := &ruleTable - for ch0 >= 0 && ch0 <= 255 { - if node.childs[ch0] == nil || s.r.eof() { - break - } + for !(node.childs[ch0] == nil || s.r.eof()) { node = node.childs[ch0] if node.fn != nil { return node.fn(s) @@ -345,7 +369,7 @@ func startWithXx(s *Scanner) (tok int, pos Pos, lit string) { s.r.inc() tok, lit = hexLit, s.r.data(&pos) } else { - tok = unicode.ReplacementChar + tok = invalid } return } @@ -377,7 +401,7 @@ func startWithBb(s *Scanner) (tok int, pos Pos, lit string) { s.r.inc() tok, lit = bitLit, s.r.data(&pos) } else { - tok = unicode.ReplacementChar + tok = invalid } return } @@ -386,7 +410,7 @@ func startWithBb(s *Scanner) (tok int, pos Pos, lit string) { } func startWithSharp(s *Scanner) (tok int, pos Pos, lit string) { - s.r.incAsLongAs(func(ch rune) bool { + s.r.incAsLongAs(func(ch byte) bool { return ch != '\n' }) return s.scan() @@ -397,7 +421,7 @@ func startWithDash(s *Scanner) (tok int, pos Pos, lit string) { if strings.HasPrefix(s.r.s[pos.Offset:], "--") { remainLen := len(s.r.s[pos.Offset:]) if remainLen == 2 || (remainLen > 2 && unicode.IsSpace(rune(s.r.s[pos.Offset+2]))) { - s.r.incAsLongAs(func(ch rune) bool { + s.r.incAsLongAs(func(ch byte) bool { return ch != '\n' }) return s.scan() @@ -483,7 +507,7 @@ func startWithSlash(s *Scanner) (tok int, pos Pos, lit string) { // standard C-like comment. read until we see '*/' then drop it. for { - if currentCharIsStar || s.r.incAsLongAs(func(ch rune) bool { return ch != '*' }) == '*' { + if currentCharIsStar || s.r.incAsLongAs(func(ch byte) bool { return ch != '*' }) == '*' { switch s.r.readByte() { case '/': // Meets */, means comment end. @@ -549,7 +573,7 @@ func startWithAt(s *Scanner) (tok int, pos Pos, lit string) { case identifier: tok, lit = doubleAtIdentifier, s.r.data(&pos) } - case unicode.ReplacementChar: + case invalid: break default: tok = singleAtIdentifier @@ -591,12 +615,13 @@ func scanQuotedIdent(s *Scanner) (tok int, pos Pos, lit string) { pos = s.r.pos() s.r.inc() s.buf.Reset() - for { - ch := s.r.readByte() - if ch == unicode.ReplacementChar && s.r.eof() { - tok = unicode.ReplacementChar - return + for !s.r.eof() { + tPos := s.r.pos() + if s.r.skipRune(s.client) { + s.buf.WriteString(s.r.data(&tPos)) + continue } + ch := s.r.readByte() if ch == '`' { if s.r.peek() != '`' { // don't return identifier in case that it's interpreted as keyword token later. @@ -605,8 +630,10 @@ func scanQuotedIdent(s *Scanner) (tok int, pos Pos, lit string) { } s.r.inc() } - s.buf.WriteRune(ch) + s.buf.WriteByte(ch) } + tok = invalid + return } func startString(s *Scanner) (tok int, pos Pos, lit string) { @@ -655,43 +682,46 @@ func (mb *lazyBuf) data() string { func (s *Scanner) scanString() (tok int, pos Pos, lit string) { tok, pos = stringLit, s.r.pos() - mb := lazyBuf{false, &s.r, &s.buf, &pos} ending := s.r.readByte() - ch0 := s.r.peek() + s.buf.Reset() for !s.r.eof() { + tPos := s.r.pos() + if s.r.skipRune(s.client) { + s.buf.WriteString(s.r.data(&tPos)) + continue + } + ch0 := s.r.readByte() if ch0 == ending { - s.r.inc() if s.r.peek() != ending { - lit = mb.data() + lit = s.buf.String() return } - str := mb.r.data(&pos) - mb.setUseBuf(str[1 : len(str)-1]) + s.r.inc() + s.buf.WriteByte(ch0) } else if ch0 == '\\' && !s.sqlMode.HasNoBackslashEscapesMode() { - mb.setUseBuf(mb.r.data(&pos)[1:]) - ch0 = handleEscape(s) - } - mb.writeRune(ch0, s.r.w) - if !s.r.eof() { + if s.r.eof() { + break + } + s.handleEscape(s.r.peek(), &s.buf) s.r.inc() - ch0 = s.r.peek() + } else { + s.buf.WriteByte(ch0) } } - tok = unicode.ReplacementChar + tok = invalid return } // handleEscape handles the case in scanString when previous char is '\'. -func handleEscape(s *Scanner) rune { - s.r.inc() - ch0 := s.r.peek() +func (s *Scanner) handleEscape(b byte, buf *bytes.Buffer) { + var ch0 byte /* \" \' \\ \n \0 \b \Z \r \t ==> escape to one char \% \_ ==> preserve both char other ==> remove \ */ - switch ch0 { + switch b { case 'n': ch0 = '\n' case '0': @@ -705,9 +735,12 @@ func handleEscape(s *Scanner) rune { case 't': ch0 = '\t' case '%', '_': - s.buf.WriteByte('\\') + buf.WriteByte('\\') + ch0 = b + default: + ch0 = b } - return ch0 + buf.WriteByte(ch0) } func startWithNumber(s *Scanner) (tok int, pos Pos, lit string) { @@ -787,13 +820,13 @@ func startWithDot(s *Scanner) (tok int, pos Pos, lit string) { } func (s *Scanner) scanOct() { - s.r.incAsLongAs(func(ch rune) bool { + s.r.incAsLongAs(func(ch byte) bool { return ch >= '0' && ch <= '7' }) } func (s *Scanner) scanHex() { - s.r.incAsLongAs(func(ch rune) bool { + s.r.incAsLongAs(func(ch byte) bool { return ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F' @@ -801,7 +834,7 @@ func (s *Scanner) scanHex() { } func (s *Scanner) scanBit() { - s.r.incAsLongAs(func(ch rune) bool { + s.r.incAsLongAs(func(ch byte) bool { return ch == '0' || ch == '1' }) } @@ -881,7 +914,7 @@ func (s *Scanner) scanFeatureIDs() (featureIDs []string) { return nil case expectChar: if isIdentChar(ch) { - b.WriteRune(ch) + b.WriteByte(ch) state = obtainChar break } @@ -889,7 +922,7 @@ func (s *Scanner) scanFeatureIDs() (featureIDs []string) { return nil case obtainChar: if isIdentChar(ch) { - b.WriteRune(ch) + b.WriteByte(ch) state = obtainChar break } else if ch == ',' { @@ -920,39 +953,23 @@ func (s *Scanner) lastErrorAsWarn() { type reader struct { s string p Pos - w int - - peekRune rune - peekRuneUpdated bool + l int } var eof = Pos{-1, -1, -1} func (r *reader) eof() bool { - return r.p.Offset >= len(r.s) + return r.p.Offset >= r.l } // peek() peeks a rune from underlying reader. -// if reader meets EOF, it will return unicode.ReplacementChar. to distinguish from -// the real unicode.ReplacementChar, the caller should call r.eof() again to check. -func (r *reader) peek() rune { - if r.peekRuneUpdated { - return r.peekRune - } +// if reader meets EOF, it will return 0. to distinguish from +// the real 0, the caller should call r.eof() again to check. +func (r *reader) peek() byte { if r.eof() { - return unicode.ReplacementChar - } - v, w := rune(r.s[r.p.Offset]), 1 - if v >= 0x80 { - v, w = utf8.DecodeRuneInString(r.s[r.p.Offset:]) - if v == utf8.RuneError && w == 1 { - v = rune(r.s[r.p.Offset]) // illegal encoding - } + return 0 } - r.w = w - r.peekRune = v - r.peekRuneUpdated = true - return v + return r.s[r.p.Offset] } // inc increase the position offset of the reader. @@ -962,9 +979,8 @@ func (r *reader) inc() { r.p.Line++ r.p.Col = 0 } - r.p.Offset += r.w + r.p.Offset += 1 r.p.Col++ - r.peekRuneUpdated = false } func (r *reader) incN(n int) { @@ -973,9 +989,9 @@ func (r *reader) incN(n int) { } } -func (r *reader) readByte() (ch rune) { +func (r *reader) readByte() (ch byte) { ch = r.peek() - if ch == unicode.ReplacementChar && r.eof() { + if r.eof() { return } r.inc() @@ -987,9 +1003,6 @@ func (r *reader) pos() Pos { } func (r *reader) updatePos(pos Pos) { - if r.p.Offset != pos.Offset { - r.peekRuneUpdated = false - } r.p = pos } @@ -997,15 +1010,25 @@ func (r *reader) data(from *Pos) string { return r.s[from.Offset:r.p.Offset] } -func (r *reader) incAsLongAs(fn func(rune) bool) rune { +func (r *reader) incAsLongAs(fn func(b byte) bool) byte { for { ch := r.peek() if !fn(ch) { return ch } - if ch == unicode.ReplacementChar && r.eof() { + if r.eof() { return 0 } r.inc() } } + +// skipRune skip mb character, return true indicate something has been skipped. +func (r *reader) skipRune(enc charset.Encoding) bool { + if r.s[r.p.Offset] <= unicode.MaxASCII { + return false + } + c := enc.MbLen(r.s[r.p.Offset:]) + r.incN(c) + return c > 0 +} diff --git a/parser/lexer_test.go b/parser/lexer_test.go index 676d0add40450..91d45d559d863 100644 --- a/parser/lexer_test.go +++ b/parser/lexer_test.go @@ -213,13 +213,13 @@ func runLiteralTest(t *testing.T, table []testLiteralValue) { val := l.LexLiteral() switch val.(type) { case int64: - requires.Equal(t, val, v.val, v.str) + requires.Equal(t, v.val, val, v.str) case float64: - requires.Equal(t, val, v.val, v.str) + requires.Equal(t, v.val, val, v.str) case string: - requires.Equal(t, val, v.val, v.str) + requires.Equal(t, v.val, val, v.str) default: - requires.Equal(t, fmt.Sprint(val), v.val, v.str) + requires.Equal(t, v.val, fmt.Sprint(val), v.str) } } } @@ -293,8 +293,40 @@ func TestScanString(t *testing.T) { } } +func TestScanStringWithNoBackslashEscapesMode(t *testing.T) { + table := []struct { + raw string + expect string + }{ + {`' \n\tTest String'`, ` \n\tTest String`}, + {`'\x\B'`, `\x\B`}, + {`'\0\\''"\b\n\r\t\'`, `\0\\'"\b\n\r\t\`}, + {`'\Z'`, `\Z`}, + {`'\%\_'`, `\%\_`}, + {`'hello'`, "hello"}, + {`'"hello"'`, `"hello"`}, + {`'""hello""'`, `""hello""`}, + {`'hel''lo'`, "hel'lo"}, + {`'\'hello'`, `\`}, + {`"hello"`, "hello"}, + {`"'hello'"`, "'hello'"}, + {`"''hello''"`, "''hello''"}, + {`"hel""lo"`, `hel"lo`}, + {`"\"hello"`, `\`}, + {"'한국ì˜ä¸­æ–‡UTF8ãŠã‚ˆã³ãƒ†ã‚­ã‚¹ãƒˆãƒˆãƒ©ãƒƒã‚¯'", "한국ì˜ä¸­æ–‡UTF8ãŠã‚ˆã³ãƒ†ã‚­ã‚¹ãƒˆãƒˆãƒ©ãƒƒã‚¯"}, + } + l := NewScanner("") + l.SetSQLMode(mysql.ModeNoBackslashEscapes) + for _, v := range table { + l.reset(v.raw) + tok, pos, lit := l.scan() + requires.Zero(t, pos.Offset) + requires.Equal(t, stringLit, tok) + requires.Equal(t, v.expect, lit) + } +} + func TestIdentifier(t *testing.T) { - replacementString := string(unicode.ReplacementChar) + "xxx" table := [][2]string{ {`哈哈`, "哈哈"}, {"`numeric`", "numeric"}, @@ -302,7 +334,7 @@ func TestIdentifier(t *testing.T) { {`5number`, `5number`}, {"1_x", "1_x"}, {"0_x", "0_x"}, - {replacementString, replacementString}, + {string(unicode.ReplacementChar) + "xxx", string(unicode.ReplacementChar) + "xxx"}, {"9e", "9e"}, {"0b", "0b"}, {"0b123", "0b123"}, @@ -319,8 +351,8 @@ func TestIdentifier(t *testing.T) { l.reset(item[0]) var v yySymType tok := l.Lex(&v) - requires.Equal(t, identifier, tok) - requires.Equal(t, item[1], v.ident) + requires.Equal(t, identifier, tok, item) + requires.Equal(t, item[1], v.ident, item) } } @@ -329,12 +361,12 @@ func TestSpecialComment(t *testing.T) { tok, pos, lit := l.scan() requires.Equal(t, identifier, tok) requires.Equal(t, "select", lit) - requires.Equal(t, Pos{0, 9, 9}, pos) + requires.Equal(t, Pos{1, 9, 9}, pos) tok, pos, lit = l.scan() requires.Equal(t, intLit, tok) requires.Equal(t, "5", lit) - requires.Equal(t, Pos{1, 1, 16}, pos) + requires.Equal(t, Pos{2, 1, 16}, pos) } func TestFeatureIDsComment(t *testing.T) { @@ -342,12 +374,12 @@ func TestFeatureIDsComment(t *testing.T) { tok, pos, lit := l.scan() requires.Equal(t, identifier, tok) requires.Equal(t, "auto_random", lit) - requires.Equal(t, Pos{0, 16, 16}, pos) + requires.Equal(t, Pos{1, 16, 16}, pos) tok, pos, _ = l.scan() requires.Equal(t, int('('), tok) _, pos, lit = l.scan() requires.Equal(t, "5", lit) - requires.Equal(t, Pos{0, 28, 28}, pos) + requires.Equal(t, Pos{1, 28, 28}, pos) tok, pos, _ = l.scan() requires.Equal(t, int(')'), tok) @@ -544,13 +576,13 @@ func TestVersionDigits(t *testing.T) { input string min int max int - nextChar rune + nextChar byte }{ { input: "12345", min: 5, max: 5, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "12345xyz", @@ -580,7 +612,7 @@ func TestVersionDigits(t *testing.T) { input: "", min: 5, max: 5, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "1234567xyz", @@ -598,7 +630,7 @@ func TestVersionDigits(t *testing.T) { input: "12345", min: 5, max: 6, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "1234xyz", @@ -621,12 +653,12 @@ func TestFeatureIDs(t *testing.T) { tests := []struct { input string featureIDs []string - nextChar rune + nextChar byte }{ { input: "[feature]", featureIDs: []string{"feature"}, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "[feature] xx", @@ -636,17 +668,17 @@ func TestFeatureIDs(t *testing.T) { { input: "[feature1,feature2]", featureIDs: []string{"feature1", "feature2"}, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "[feature1,feature2,feature3]", featureIDs: []string{"feature1", "feature2", "feature3"}, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "[id_en_ti_fier]", featureIDs: []string{"id_en_ti_fier"}, - nextChar: unicode.ReplacementChar, + nextChar: 0, }, { input: "[invalid, whitespace]", diff --git a/parser/misc.go b/parser/misc.go index cbc65d0d6eb4c..ff70e2be56e43 100644 --- a/parser/misc.go +++ b/parser/misc.go @@ -13,23 +13,23 @@ package parser -func isLetter(ch rune) bool { +func isLetter(ch byte) bool { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') } -func isDigit(ch rune) bool { +func isDigit(ch byte) bool { return ch >= '0' && ch <= '9' } -func isIdentChar(ch rune) bool { +func isIdentChar(ch byte) bool { return isLetter(ch) || isDigit(ch) || ch == '_' || ch == '$' || isIdentExtend(ch) } -func isIdentExtend(ch rune) bool { - return ch >= 0x80 && ch <= '\uffff' +func isIdentExtend(ch byte) bool { + return ch >= 0x80 } -func isUserVarChar(ch rune) bool { +func isUserVarChar(ch byte) bool { return isLetter(ch) || isDigit(ch) || ch == '_' || ch == '$' || ch == '.' || isIdentExtend(ch) } @@ -176,6 +176,7 @@ var tokenMap = map[string]int{ "BIGINT": bigIntType, "BINARY": binaryType, "BINDING": binding, + "BINDING_CACHE": bindingCache, "BINDINGS": bindings, "BINLOG": binlog, "BIT_AND": bitAnd, @@ -287,6 +288,7 @@ var tokenMap = map[string]int{ "DESCRIBE": describe, "DIRECTORY": directory, "DISABLE": disable, + "DISABLED": disabled, "DISCARD": discard, "DISK": disk, "DISTINCT": distinct, @@ -303,6 +305,7 @@ var tokenMap = map[string]int{ "DYNAMIC": dynamic, "ELSE": elseKwd, "ENABLE": enable, + "ENABLED": enabled, "ENCLOSED": enclosed, "ENCRYPTION": encryption, "END": end, @@ -797,9 +800,10 @@ var tokenMap = map[string]int{ "WAIT": wait, } -// See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details +// See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details. +// ADDDATE, SESSION_USER, SUBDATE, and SYSTEM_USER are exceptions because they are actually recognized as +// identifiers even in `create table adddate (a int)`. var btFuncTokenMap = map[string]int{ - "ADDDATE": builtinAddDate, "BIT_AND": builtinBitAnd, "BIT_OR": builtinBitOr, "BIT_XOR": builtinBitXor, @@ -818,17 +822,14 @@ var btFuncTokenMap = map[string]int{ "MIN": builtinMin, "NOW": builtinNow, "POSITION": builtinPosition, - "SESSION_USER": builtinUser, "STD": builtinStddevPop, "STDDEV": builtinStddevPop, "STDDEV_POP": builtinStddevPop, "STDDEV_SAMP": builtinStddevSamp, - "SUBDATE": builtinSubDate, "SUBSTR": builtinSubstring, "SUBSTRING": builtinSubstring, "SUM": builtinSum, "SYSDATE": builtinSysDate, - "SYSTEM_USER": builtinUser, "TRANSLATE": builtinTranslate, "TRIM": builtinTrim, "VARIANCE": builtinVarPop, @@ -919,7 +920,6 @@ var hintTokenMap = map[string]int{ "READ_CONSISTENT_REPLICA": hintReadConsistentReplica, "READ_FROM_STORAGE": hintReadFromStorage, "BROADCAST_JOIN": hintBCJoin, - "BROADCAST_JOIN_LOCAL": hintBCJoinPreferLocal, "MERGE_JOIN": hintSMJoin, "STREAM_AGG": hintStreamAgg, "SWAP_JOIN_INPUTS": hintSwapJoinInputs, diff --git a/parser/model/ddl.go b/parser/model/ddl.go index c61372b55e263..f84f95306c56a 100644 --- a/parser/model/ddl.go +++ b/parser/model/ddl.go @@ -67,8 +67,8 @@ const ( ActionCreateSequence ActionType = 34 ActionAlterSequence ActionType = 35 ActionDropSequence ActionType = 36 - ActionAddColumns ActionType = 37 - ActionDropColumns ActionType = 38 + __DEPRECATED_ActionAddColumns ActionType = 37 + __DEPRECATED_ActionDropColumns ActionType = 38 ActionModifyTableAutoIdCache ActionType = 39 ActionRebaseAutoRandomBase ActionType = 40 ActionAlterIndexVisibility ActionType = 41 @@ -82,7 +82,7 @@ const ( __DEPRECATED_ActionAlterTableAlterPartition ActionType = 46 ActionRenameTables ActionType = 47 - ActionDropIndexes ActionType = 48 + __DEPRECATED_ActionDropIndexes ActionType = 48 ActionAlterTableAttributes ActionType = 49 ActionAlterTablePartitionAttributes ActionType = 50 ActionCreatePlacementPolicy ActionType = 51 @@ -94,12 +94,15 @@ const ( ActionAlterCacheTable ActionType = 57 ActionAlterTableStatsOptions ActionType = 58 ActionAlterNoCacheTable ActionType = 59 + ActionCreateTables ActionType = 60 + ActionMultiSchemaChange ActionType = 61 ) var actionMap = map[ActionType]string{ ActionCreateSchema: "create schema", ActionDropSchema: "drop schema", ActionCreateTable: "create table", + ActionCreateTables: "create tables", ActionDropTable: "drop table", ActionAddColumn: "add column", ActionDropColumn: "drop column", @@ -134,8 +137,8 @@ var actionMap = map[ActionType]string{ ActionCreateSequence: "create sequence", ActionAlterSequence: "alter sequence", ActionDropSequence: "drop sequence", - ActionAddColumns: "add multi-columns", - ActionDropColumns: "drop multi-columns", + __DEPRECATED_ActionAddColumns: "add multi-columns", + __DEPRECATED_ActionDropColumns: "drop multi-columns", ActionModifyTableAutoIdCache: "modify auto id cache", ActionRebaseAutoRandomBase: "rebase auto_random ID", ActionAlterIndexVisibility: "alter index visibility", @@ -143,7 +146,7 @@ var actionMap = map[ActionType]string{ ActionAddCheckConstraint: "add check constraint", ActionDropCheckConstraint: "drop check constraint", ActionAlterCheckConstraint: "alter check constraint", - ActionDropIndexes: "drop multi-indexes", + __DEPRECATED_ActionDropIndexes: "drop multi-indexes", ActionAlterTableAttributes: "alter table attributes", ActionAlterTablePartitionPlacement: "alter table partition placement", ActionAlterTablePartitionAttributes: "alter table partition attributes", @@ -155,6 +158,7 @@ var actionMap = map[ActionType]string{ ActionAlterCacheTable: "alter table cache", ActionAlterNoCacheTable: "alter table nocache", ActionAlterTableStatsOptions: "alter table statistics options", + ActionMultiSchemaChange: "alter table multi-schema change", // `ActionAlterTableAlterPartition` is removed and will never be used. // Just left a tombstone here for compatibility. @@ -175,6 +179,9 @@ type HistoryInfo struct { DBInfo *DBInfo TableInfo *TableInfo FinishedTS uint64 + + // MultipleTableInfos is like TableInfo but only for operations updating multiple tables. + MultipleTableInfos []*TableInfo } // AddDBInfo adds schema version and schema information that are used for binlog. @@ -191,11 +198,21 @@ func (h *HistoryInfo) AddTableInfo(schemaVer int64, tblInfo *TableInfo) { h.TableInfo = tblInfo } +// SetTableInfos is like AddTableInfo, but will add multiple table infos to the binlog. +func (h *HistoryInfo) SetTableInfos(schemaVer int64, tblInfos []*TableInfo) { + h.SchemaVersion = schemaVer + h.MultipleTableInfos = make([]*TableInfo, len(tblInfos)) + for i, info := range tblInfos { + h.MultipleTableInfos[i] = info + } +} + // Clean cleans history information. func (h *HistoryInfo) Clean() { h.SchemaVersion = 0 h.DBInfo = nil h.TableInfo = nil + h.MultipleTableInfos = nil } // DDLReorgMeta is meta info of DDL reorganization. @@ -207,7 +224,28 @@ type DDLReorgMeta struct { SQLMode mysql.SQLMode `json:"sql_mode"` Warnings map[errors.ErrorID]*terror.Error `json:"warnings"` WarningsCount map[errors.ErrorID]int64 `json:"warnings_count"` - Location *time.Location `json:"time_location"` + Location *TimeZoneLocation `json:"location"` +} + +// TimeZoneLocation represents a single time zone. +type TimeZoneLocation struct { + Name string `json:"name"` + Offset int `json:"offset"` // seconds east of UTC + location *time.Location +} + +func (tz *TimeZoneLocation) GetLocation() (*time.Location, error) { + if tz.location != nil { + return tz.location, nil + } + + var err error + if tz.Offset == 0 { + tz.location, err = time.LoadLocation(tz.Name) + } else { + tz.location = time.FixedZone(tz.Name, tz.Offset) + } + return tz.location, err } // NewDDLReorgMeta new a DDLReorgMeta. @@ -219,7 +257,35 @@ func NewDDLReorgMeta() *DDLReorgMeta { // MultiSchemaInfo keeps some information for multi schema change. type MultiSchemaInfo struct { - Warnings []*errors.Error + SubJobs []*SubJob `json:"sub_jobs"` + Revertible bool `json:"revertible"` + + AddColumns []CIStr `json:"-"` + DropColumns []CIStr `json:"-"` + AddIndexes []CIStr `json:"-"` + DropIndexes []CIStr `json:"-"` + + RelativeColumns []CIStr `json:"-"` +} + +func NewMultiSchemaInfo() *MultiSchemaInfo { + return &MultiSchemaInfo{ + SubJobs: nil, + Revertible: true, + } +} + +type SubJob struct { + Type ActionType `json:"type"` + Args []interface{} `json:"-"` + RawArgs json.RawMessage `json:"raw_args"` + SchemaState SchemaState `json:"schema_state"` + SnapshotVer uint64 `json:"snapshot_ver"` + Revertible bool `json:"revertible"` + State JobState `json:"state"` + RowCount int64 `json:"row_count"` + Warning *terror.Error `json:"warning"` + CtxVars []interface{} `json:"-"` } // Job is for a DDL operation. @@ -229,7 +295,9 @@ type Job struct { SchemaID int64 `json:"schema_id"` TableID int64 `json:"table_id"` SchemaName string `json:"schema_name"` + TableName string `json:"table_name"` State JobState `json:"state"` + Warning *terror.Error `json:"warning"` Error *terror.Error `json:"err"` // ErrorCount will be increased, every time we meet an error when running job. ErrorCount int64 `json:"err_count"` @@ -261,7 +329,6 @@ type Job struct { Version int64 `json:"version"` // ReorgMeta is meta info of ddl reorganization. - // This field is depreciated. ReorgMeta *DDLReorgMeta `json:"reorg_meta"` // MultiSchemaInfo keeps some warning now for multi schema change. @@ -269,6 +336,9 @@ type Job struct { // Priority is only used to set the operation priority of adding indices. Priority int `json:"priority"` + + // SeqNum is the total order in all DDLs, it's used to identify the order of DDL. + SeqNum uint64 `json:"seq_num"` } // FinishTableJob is called when a job is finished. @@ -279,6 +349,16 @@ func (job *Job) FinishTableJob(jobState JobState, schemaState SchemaState, ver i job.BinlogInfo.AddTableInfo(ver, tblInfo) } +// FinishMultipleTableJob is called when a job is finished. +// It updates the job's state information and adds tblInfos to the binlog. +func (job *Job) FinishMultipleTableJob(jobState JobState, schemaState SchemaState, ver int64, tblInfos []*TableInfo) { + job.State = jobState + job.SchemaState = schemaState + job.BinlogInfo.SchemaVersion = ver + job.BinlogInfo.MultipleTableInfos = tblInfos + job.BinlogInfo.TableInfo = tblInfos[len(tblInfos)-1] +} + // FinishDBJob is called when a job is finished. // It updates the job's state information and adds dbInfo the binlog. func (job *Job) FinishDBJob(jobState JobState, schemaState SchemaState, ver int64, dbInfo *DBInfo) { @@ -287,6 +367,14 @@ func (job *Job) FinishDBJob(jobState JobState, schemaState SchemaState, ver int6 job.BinlogInfo.AddDBInfo(ver, dbInfo) } +// MarkNonRevertible mark the current job to be non-revertible. +// It means the job cannot be cancelled or rollbacked. +func (job *Job) MarkNonRevertible() { + if job.MultiSchemaInfo != nil { + job.MultiSchemaInfo.Revertible = false + } +} + // TSConvert2Time converts timestamp to time. func TSConvert2Time(ts uint64) time.Time { t := int64(ts >> 18) // 18 is for the logical time. @@ -329,6 +417,18 @@ func (job *Job) Encode(updateRawArgs bool) ([]byte, error) { if err != nil { return nil, errors.Trace(err) } + if job.MultiSchemaInfo != nil { + for _, sub := range job.MultiSchemaInfo.SubJobs { + // Only update the args of last executing sub-job. + if sub.Args == nil { + continue + } + sub.RawArgs, err = json.Marshal(sub.Args) + if err != nil { + return nil, errors.Trace(err) + } + } + } } var b []byte @@ -370,8 +470,12 @@ func (job *Job) DecodeArgs(args ...interface{}) error { // String implements fmt.Stringer interface. func (job *Job) String() string { rowCount := job.GetRowCount() - return fmt.Sprintf("ID:%d, Type:%s, State:%s, SchemaState:%s, SchemaID:%d, TableID:%d, RowCount:%d, ArgLen:%d, start time: %v, Err:%v, ErrCount:%d, SnapshotVersion:%v", + ret := fmt.Sprintf("ID:%d, Type:%s, State:%s, SchemaState:%s, SchemaID:%d, TableID:%d, RowCount:%d, ArgLen:%d, start time: %v, Err:%v, ErrCount:%d, SnapshotVersion:%v", job.ID, job.Type, job.State, job.SchemaState, job.SchemaID, job.TableID, rowCount, len(job.Args), TSConvert2Time(job.StartTS), job.Error, job.ErrorCount, job.SnapshotVer) + if job.Type != ActionMultiSchemaChange && job.MultiSchemaInfo != nil { + ret += fmt.Sprintf(", RawArgs:%s", job.RawArgs) + } + return ret } func (job *Job) hasDependentSchema(other *Job) (bool, error) { @@ -454,6 +558,14 @@ func (job *Job) IsRunning() bool { return job.State == JobStateRunning } +func (job *Job) IsQueueing() bool { + return job.State == JobStateQueueing +} + +func (job *Job) NotStarted() bool { + return job.State == JobStateNone || job.State == JobStateQueueing +} + // JobState is for job state. type JobState byte @@ -473,6 +585,8 @@ const ( JobStateSynced JobState = 6 // JobStateCancelling is used to mark the DDL job is cancelled by the client, but the DDL work hasn't handle it. JobStateCancelling JobState = 7 + // JobStateQueueing means the job has not yet been started. + JobStateQueueing JobState = 8 ) // String implements fmt.Stringer interface. @@ -492,6 +606,8 @@ func (s JobState) String() string { return "cancelling" case JobStateSynced: return "synced" + case JobStateQueueing: + return "queueing" default: return "none" } diff --git a/parser/model/model.go b/parser/model/model.go index c08ea8b8b309c..fb50c87e8f02f 100644 --- a/parser/model/model.go +++ b/parser/model/model.go @@ -71,7 +71,7 @@ func (s SchemaState) String() string { case StateGlobalTxnOnly: return "global txn only" default: - return "queueing" + return "none" } } @@ -214,7 +214,16 @@ func FindColumnInfo(cols []*ColumnInfo, name string) *ColumnInfo { return col } } + return nil +} +// FindColumnInfoByID finds ColumnInfo in cols by id. +func FindColumnInfoByID(cols []*ColumnInfo, id int64) *ColumnInfo { + for _, col := range cols { + if col.ID == id { + return col + } + } return nil } @@ -225,6 +234,12 @@ const ExtraHandleID = -1 // ExtraPidColID is the column ID of column which store the partitionID decoded in global index values. const ExtraPidColID = -2 +// ExtraPhysTblID is the column ID of column that should be filled in with the physical table id. +// Primarily used for table partition dynamic prune mode, to return which partition (physical table id) the row came from. +// Using a dedicated id for this, since in the future ExtraPidColID and ExtraPhysTblID may be used for the same request. +// Must be after ExtraPidColID! +const ExtraPhysTblID = -3 + const ( // TableInfoVersion0 means the table info version is 0. // Upgrade from v2.1.1 or v2.1.2 to v2.1.3 and later, and then execute a "change/modify column" statement @@ -266,6 +281,9 @@ var ExtraHandleName = NewCIStr("_tidb_rowid") // ExtraPartitionIdName is the name of ExtraPartitionId Column. var ExtraPartitionIdName = NewCIStr("_tidb_pid") +// ExtraPhysTblIdName is the name of ExtraPhysTblID Column. +var ExtraPhysTblIdName = NewCIStr("_tidb_tid") + // TableInfo provides meta data describing a DB table. type TableInfo struct { ID int64 `json:"id"` @@ -340,8 +358,7 @@ type TableInfo struct { TempTableType `json:"temp_table_type"` TableCacheStatusType `json:"cache_table_status"` - PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` - DirectPlacementOpts *PlacementSettings `json:"placement_settings"` + PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` // StatsOptions is used when do analyze/auto-analyze for each table StatsOptions *StatsOptions `json:"stats_options"` @@ -620,6 +637,50 @@ func (t *TableInfo) IsLocked() bool { return t.Lock != nil && len(t.Lock.Sessions) > 0 } +// MoveColumnInfo moves a column to another offset. +func (t *TableInfo) MoveColumnInfo(from, to int) { + if from == to { + return + } + updatedOffsets := make(map[int]int) + src := t.Columns[from] + if from < to { + for i := from; i < to; i++ { + t.Columns[i] = t.Columns[i+1] + t.Columns[i].Offset = i + updatedOffsets[i+1] = i + } + } else if from > to { + for i := from; i > to; i-- { + t.Columns[i] = t.Columns[i-1] + t.Columns[i].Offset = i + updatedOffsets[i-1] = i + } + } + t.Columns[to] = src + t.Columns[to].Offset = to + updatedOffsets[from] = to + for _, idx := range t.Indices { + for _, idxCol := range idx.Columns { + newOffset, ok := updatedOffsets[idxCol.Offset] + if ok { + idxCol.Offset = newOffset + } + } + } +} + +// ClearPlacement clears all table and partitions' placement settings +func (t *TableInfo) ClearPlacement() { + t.PlacementPolicyRef = nil + if t.Partition != nil { + for i := range t.Partition.Definitions { + def := &t.Partition.Definitions[i] + def.PlacementPolicyRef = nil + } + } +} + // NewExtraHandleColInfo mocks a column info for extra handle column. func NewExtraHandleColInfo() *ColumnInfo { colInfo := &ColumnInfo{ @@ -644,6 +705,17 @@ func NewExtraPartitionIDColInfo() *ColumnInfo { return colInfo } +// NewExtraPhysTblIDColInfo mocks a column info for extra partition id column. +func NewExtraPhysTblIDColInfo() *ColumnInfo { + colInfo := &ColumnInfo{ + ID: ExtraPhysTblID, + Name: ExtraPhysTblIdName, + } + colInfo.Tp = mysql.TypeLonglong + colInfo.Flen, colInfo.Decimal = mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong) + return colInfo +} + // ColumnIsInIndex checks whether c is included in any indices of t. func (t *TableInfo) ColumnIsInIndex(c *ColumnInfo) bool { for _, index := range t.Indices { @@ -832,23 +904,12 @@ func (pi *PartitionInfo) GetNameByID(id int64) string { // see https://github.com/pingcap/parser/pull/1072 for the benchmark. for i := range definitions { if id == definitions[i].ID { - return definitions[i].Name.L + return definitions[i].Name.O } } return "" } -// GetPlacementByID gets the partition placement by ID. -func (pi *PartitionInfo) GetPlacementByID(id int64) (*PolicyRefInfo, *PlacementSettings) { - definitions := pi.Definitions - for i := range definitions { - if id == definitions[i].ID { - return definitions[i].PlacementPolicyRef, definitions[i].DirectPlacementOpts - } - } - return nil, nil -} - func (pi *PartitionInfo) GetStateByID(id int64) SchemaState { for _, pstate := range pi.States { if pstate.ID == id { @@ -899,13 +960,12 @@ type PartitionState struct { // PartitionDefinition defines a single partition. type PartitionDefinition struct { - ID int64 `json:"id"` - Name CIStr `json:"name"` - LessThan []string `json:"less_than"` - InValues [][]string `json:"in_values"` - PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` - DirectPlacementOpts *PlacementSettings `json:"placement_settings"` - Comment string `json:"comment,omitempty"` + ID int64 `json:"id"` + Name CIStr `json:"name"` + LessThan []string `json:"less_than"` + InValues [][]string `json:"in_values"` + PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` + Comment string `json:"comment,omitempty"` } // Clone clones ConstraintInfo. @@ -1085,14 +1145,13 @@ func (fk *FKInfo) Clone() *FKInfo { // DBInfo provides meta data describing a DB. type DBInfo struct { - ID int64 `json:"id"` // Database ID - Name CIStr `json:"db_name"` // DB name. - Charset string `json:"charset"` - Collate string `json:"collate"` - Tables []*TableInfo `json:"-"` // Tables in the DB. - State SchemaState `json:"state"` - PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` - DirectPlacementOpts *PlacementSettings `json:"placement_settings"` + ID int64 `json:"id"` // Database ID + Name CIStr `json:"db_name"` // DB name. + Charset string `json:"charset"` + Collate string `json:"collate"` + Tables []*TableInfo `json:"-"` // Tables in the DB. + State SchemaState `json:"state"` + PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` } // Clone clones DBInfo. @@ -1185,6 +1244,13 @@ type PolicyInfo struct { State SchemaState `json:"state"` } +func (p *PolicyInfo) Clone() *PolicyInfo { + var cloned PolicyInfo + cloned = *p + cloned.PlacementSettings = p.PlacementSettings.Clone() + return &cloned +} + func writeSettingItemToBuilder(sb *strings.Builder, item string) { if sb.Len() != 0 { sb.WriteString(" ") @@ -1241,6 +1307,12 @@ func (p *PlacementSettings) String() string { return sb.String() } +func (p *PlacementSettings) Clone() *PlacementSettings { + var cloned PlacementSettings + cloned = *p + return &cloned +} + type StatsOptions struct { *StatsWindowSettings AutoRecalc bool `json:"auto_recalc"` @@ -1278,13 +1350,13 @@ const ( func (s ColumnChoice) String() string { switch s { case AllColumns: - return "AllColumns" + return "ALL" case PredicateColumns: - return "PredicateColumns" + return "PREDICATE" case ColumnList: - return "ColumnList" + return "LIST" default: - return "" + return "DEFAULT" } } diff --git a/parser/model/model_test.go b/parser/model/model_test.go index 508eaa2713858..e5383591f2cab 100644 --- a/parser/model/model_test.go +++ b/parser/model/model_test.go @@ -32,6 +32,85 @@ func TestT(t *testing.T) { require.Equal(t, "aBC", abc.String()) } +func newColumnForTest(id int64, offset int) *ColumnInfo { + return &ColumnInfo{ + ID: id, + Name: NewCIStr(fmt.Sprintf("c_%d", id)), + Offset: offset, + } +} + +func newIndexForTest(id int64, cols ...*ColumnInfo) *IndexInfo { + idxCols := make([]*IndexColumn, 0, len(cols)) + for _, c := range cols { + idxCols = append(idxCols, &IndexColumn{Offset: c.Offset, Name: c.Name}) + } + return &IndexInfo{ + ID: id, + Name: NewCIStr(fmt.Sprintf("i_%d", id)), + Columns: idxCols, + } +} + +func checkOffsets(t *testing.T, tbl *TableInfo, ids ...int) { + require.Equal(t, len(ids), len(tbl.Columns)) + for i := 0; i < len(ids); i++ { + expected := fmt.Sprintf("c_%d", ids[i]) + require.Equal(t, expected, tbl.Columns[i].Name.L) + require.Equal(t, i, tbl.Columns[i].Offset) + } + for _, col := range tbl.Columns { + for _, idx := range tbl.Indices { + for _, idxCol := range idx.Columns { + if col.Name.L != idxCol.Name.L { + continue + } + // Columns with the same name should have a same offset. + require.Equal(t, col.Offset, idxCol.Offset) + } + } + } +} + +func TestMoveColumnInfo(t *testing.T) { + c0 := newColumnForTest(0, 0) + c1 := newColumnForTest(1, 1) + c2 := newColumnForTest(2, 2) + c3 := newColumnForTest(3, 3) + c4 := newColumnForTest(4, 4) + + i0 := newIndexForTest(0, c0, c1, c2, c3, c4) + i1 := newIndexForTest(1, c4, c2) + i2 := newIndexForTest(2, c0, c4) + i3 := newIndexForTest(3, c1, c2, c3) + i4 := newIndexForTest(4, c3, c2, c1) + + tbl := &TableInfo{ + ID: 1, + Name: NewCIStr("t"), + Columns: []*ColumnInfo{c0, c1, c2, c3, c4}, + Indices: []*IndexInfo{i0, i1, i2, i3, i4}, + } + + // Original offsets: [0, 1, 2, 3, 4] + tbl.MoveColumnInfo(4, 0) + checkOffsets(t, tbl, 4, 0, 1, 2, 3) + tbl.MoveColumnInfo(2, 3) + checkOffsets(t, tbl, 4, 0, 2, 1, 3) + tbl.MoveColumnInfo(3, 2) + checkOffsets(t, tbl, 4, 0, 1, 2, 3) + tbl.MoveColumnInfo(0, 4) + checkOffsets(t, tbl, 0, 1, 2, 3, 4) + tbl.MoveColumnInfo(2, 2) + checkOffsets(t, tbl, 0, 1, 2, 3, 4) + tbl.MoveColumnInfo(0, 0) + checkOffsets(t, tbl, 0, 1, 2, 3, 4) + tbl.MoveColumnInfo(1, 4) + checkOffsets(t, tbl, 0, 2, 3, 4, 1) + tbl.MoveColumnInfo(3, 0) + checkOffsets(t, tbl, 4, 0, 2, 3, 1) +} + func TestModelBasic(t *testing.T) { column := &ColumnInfo{ ID: 1, @@ -143,19 +222,23 @@ func TestJobStartTime(t *testing.T) { BinlogInfo: &HistoryInfo{}, } require.Equal(t, TSConvert2Time(job.StartTS), time.Unix(0, 0)) - require.Equal(t, fmt.Sprintf("ID:123, Type:none, State:none, SchemaState:queueing, SchemaID:0, TableID:0, RowCount:0, ArgLen:0, start time: %s, Err:, ErrCount:0, SnapshotVersion:0", time.Unix(0, 0)), job.String()) + require.Equal(t, fmt.Sprintf("ID:123, Type:none, State:none, SchemaState:none, SchemaID:0, TableID:0, RowCount:0, ArgLen:0, start time: %s, Err:, ErrCount:0, SnapshotVersion:0", time.Unix(0, 0)), job.String()) } func TestJobCodec(t *testing.T) { type A struct { Name string } + tzName, tzOffset := time.Now().In(time.UTC).Zone() job := &Job{ ID: 1, TableID: 2, SchemaID: 1, BinlogInfo: &HistoryInfo{}, Args: []interface{}{NewCIStr("a"), A{Name: "abc"}}, + ReorgMeta: &DDLReorgMeta{ + Location: &TimeZoneLocation{Name: tzName, Offset: tzOffset}, + }, } job.BinlogInfo.AddDBInfo(123, &DBInfo{ID: 1, Name: NewCIStr("test_history_db")}) job.BinlogInfo.AddTableInfo(123, &TableInfo{ID: 1, Name: NewCIStr("test_history_tbl")}) @@ -204,6 +287,8 @@ func TestJobCodec(t *testing.T) { require.Equal(t, NewCIStr(""), name) require.Equal(t, A{Name: ""}, a) require.Greater(t, len(newJob.String()), 0) + require.Equal(t, newJob.ReorgMeta.Location.Name, tzName) + require.Equal(t, newJob.ReorgMeta.Location.Offset, tzOffset) job.BinlogInfo.Clean() b1, err := job.Encode(true) @@ -290,11 +375,8 @@ func TestString(t *testing.T) { {ActionAddIndex, "add index"}, {ActionDropIndex, "drop index"}, {ActionAddColumn, "add column"}, - {ActionAddColumns, "add multi-columns"}, {ActionDropColumn, "drop column"}, - {ActionDropColumns, "drop multi-columns"}, {ActionModifySchemaCharsetAndCollate, "modify schema charset and collate"}, - {ActionDropIndexes, "drop multi-indexes"}, {ActionAlterTablePlacement, "alter table placement"}, {ActionAlterTablePartitionPlacement, "alter table partition placement"}, {ActionAlterNoCacheTable, "alter table nocache"}, @@ -433,3 +515,63 @@ func TestPlacementSettingsString(t *testing.T) { } require.Equal(t, "CONSTRAINTS=\"{+us-east-1:1,+us-east-2:1}\" VOTERS=3 FOLLOWERS=2 LEARNERS=1", settings.String()) } + +func TestPlacementSettingsClone(t *testing.T) { + settings := &PlacementSettings{} + clonedSettings := settings.Clone() + clonedSettings.PrimaryRegion = "r1" + clonedSettings.Regions = "r1,r2" + clonedSettings.Followers = 1 + clonedSettings.Voters = 2 + clonedSettings.Followers = 3 + clonedSettings.Constraints = "[+zone=z1]" + clonedSettings.LearnerConstraints = "[+region=r1]" + clonedSettings.FollowerConstraints = "[+disk=ssd]" + clonedSettings.LeaderConstraints = "[+region=r2]" + clonedSettings.VoterConstraints = "[+zone=z2]" + clonedSettings.Schedule = "even" + require.Equal(t, PlacementSettings{}, *settings) +} + +func TestPlacementPolicyClone(t *testing.T) { + policy := &PolicyInfo{ + PlacementSettings: &PlacementSettings{}, + } + clonedPolicy := policy.Clone() + clonedPolicy.ID = 100 + clonedPolicy.Name = NewCIStr("p2") + clonedPolicy.State = StateDeleteOnly + clonedPolicy.PlacementSettings.Followers = 10 + + require.Equal(t, int64(0), policy.ID) + require.Equal(t, NewCIStr(""), policy.Name) + require.Equal(t, StateNone, policy.State) + require.Equal(t, PlacementSettings{}, *(policy.PlacementSettings)) +} + +func TestLocation(t *testing.T) { + // test offset = 0 + loc := &TimeZoneLocation{} + nLoc, err := loc.GetLocation() + require.NoError(t, err) + require.Equal(t, nLoc.String(), "UTC") + // test loc.location != nil + loc.Name = "Asia/Shanghai" + nLoc, err = loc.GetLocation() + require.NoError(t, err) + require.Equal(t, nLoc.String(), "UTC") + // timezone +05:00 + loc1 := &TimeZoneLocation{Name: "UTC", Offset: 18000} + loc1Byte, err := json.Marshal(loc1) + require.NoError(t, err) + loc2 := &TimeZoneLocation{} + err = json.Unmarshal(loc1Byte, loc2) + require.NoError(t, err) + require.Equal(t, loc2.Offset, loc1.Offset) + require.Equal(t, loc2.Name, loc1.Name) + nLoc, err = loc2.GetLocation() + require.NoError(t, err) + require.Equal(t, nLoc.String(), "UTC") + location := time.FixedZone("UTC", loc1.Offset) + require.Equal(t, nLoc, location) +} diff --git a/parser/mysql/const.go b/parser/mysql/const.go index 81be68bf788f6..b097812f37188 100644 --- a/parser/mysql/const.go +++ b/parser/mysql/const.go @@ -164,8 +164,8 @@ const ( // Auth name information. const ( - AuthNativePassword = "mysql_native_password" - AuthCachingSha2Password = "caching_sha2_password" + AuthNativePassword = "mysql_native_password" // #nosec G101 + AuthCachingSha2Password = "caching_sha2_password" // #nosec G101 AuthSocket = "auth_socket" ) diff --git a/parser/mysql/privs.go b/parser/mysql/privs.go index 93e5db579ad1e..af1c453487a0e 100644 --- a/parser/mysql/privs.go +++ b/parser/mysql/privs.go @@ -77,6 +77,7 @@ var Priv2SetStr = map[PrivilegeType]string{ CreateRolePriv: "Create Role", DropRolePriv: "Drop Role", ShutdownPriv: "Shutdown Role", + TriggerPriv: "Trigger", } // SetStr2Priv is the map for privilege set string to privilege type. @@ -99,6 +100,7 @@ var SetStr2Priv = map[string]PrivilegeType{ "Index": IndexPriv, "Create View": CreateViewPriv, "Show View": ShowViewPriv, + "Trigger": TriggerPriv, } // Priv2UserCol is the privilege to mysql.user table column name. @@ -309,10 +311,10 @@ func (privs Privileges) Has(p PrivilegeType) bool { var AllGlobalPrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ProcessPriv, ReferencesPriv, AlterPriv, ShowDBPriv, SuperPriv, ExecutePriv, IndexPriv, CreateUserPriv, CreateTablespacePriv, TriggerPriv, CreateViewPriv, ShowViewPriv, CreateRolePriv, DropRolePriv, CreateTMPTablePriv, LockTablesPriv, CreateRoutinePriv, AlterRoutinePriv, EventPriv, ShutdownPriv, ReloadPriv, FilePriv, ConfigPriv, ReplicationClientPriv, ReplicationSlavePriv} // AllDBPrivs is all the privileges in database scope. -var AllDBPrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ReferencesPriv, LockTablesPriv, CreateTMPTablePriv, EventPriv, CreateRoutinePriv, AlterRoutinePriv, AlterPriv, ExecutePriv, IndexPriv, CreateViewPriv, ShowViewPriv} +var AllDBPrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ReferencesPriv, LockTablesPriv, CreateTMPTablePriv, EventPriv, CreateRoutinePriv, AlterRoutinePriv, AlterPriv, ExecutePriv, IndexPriv, CreateViewPriv, ShowViewPriv, TriggerPriv} // AllTablePrivs is all the privileges in table scope. -var AllTablePrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, IndexPriv, ReferencesPriv, AlterPriv, CreateViewPriv, ShowViewPriv} +var AllTablePrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, IndexPriv, ReferencesPriv, AlterPriv, CreateViewPriv, ShowViewPriv, TriggerPriv} // AllColumnPrivs is all the privileges in column scope. var AllColumnPrivs = Privileges{SelectPriv, InsertPriv, UpdatePriv, ReferencesPriv} diff --git a/parser/mysql/type.go b/parser/mysql/type.go index be030bd9c81d3..c54d0f8984b63 100644 --- a/parser/mysql/type.go +++ b/parser/mysql/type.go @@ -16,15 +16,15 @@ package mysql // MySQL type information. const ( TypeUnspecified byte = 0 - TypeTiny byte = 1 - TypeShort byte = 2 - TypeLong byte = 3 + TypeTiny byte = 1 // TINYINT + TypeShort byte = 2 // SMALLINT + TypeLong byte = 3 // INT TypeFloat byte = 4 TypeDouble byte = 5 TypeNull byte = 6 TypeTimestamp byte = 7 - TypeLonglong byte = 8 - TypeInt24 byte = 9 + TypeLonglong byte = 8 // BIGINT + TypeInt24 byte = 9 // MEDIUMINT TypeDate byte = 10 /* TypeDuration original name was TypeTime, renamed to TypeDuration to resolve the conflict with Go type Time.*/ TypeDuration byte = 11 diff --git a/parser/parser.go b/parser/parser.go index 5f167d88ee7e8..0000aea425d19 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -54,13 +54,13 @@ type yyXError struct { } const ( - yyDefault = 58103 + yyDefault = 58104 yyEOFCode = 57344 account = 57573 action = 57574 add = 57359 - addDate = 57908 - admin = 57991 + addDate = 57911 + admin = 57994 advise = 57575 after = 57576 against = 57577 @@ -72,15 +72,15 @@ const ( analyze = 57362 and = 57363 andand = 57354 - andnot = 58064 + andnot = 58065 any = 57581 - approxCountDistinct = 57909 - approxPercentile = 57910 + approxCountDistinct = 57912 + approxPercentile = 57913 as = 57364 asc = 57365 ascii = 57582 asof = 57347 - assignmentEq = 58065 + assignmentEq = 58066 attributes = 57583 autoIdCache = 57588 autoIncrement = 57589 @@ -97,2095 +97,2100 @@ const ( bigIntType = 57367 binaryType = 57368 binding = 57599 - bindings = 57600 - binlog = 57601 - bitAnd = 57911 - bitLit = 58063 - bitOr = 57912 - bitType = 57602 - bitXor = 57913 + bindingCache = 57600 + bindings = 57601 + binlog = 57602 + bitAnd = 57914 + bitLit = 58064 + bitOr = 57915 + bitType = 57603 + bitXor = 57916 blobType = 57369 - block = 57603 - boolType = 57605 - booleanType = 57604 + block = 57604 + boolType = 57606 + booleanType = 57605 both = 57370 - bound = 57914 - briefType = 57915 - btree = 57606 - buckets = 57992 - builtinAddDate = 58030 - builtinApproxCountDistinct = 58036 - builtinApproxPercentile = 58037 - builtinBitAnd = 58031 - builtinBitOr = 58032 - builtinBitXor = 58033 - builtinCast = 58034 - builtinCount = 58035 - builtinCurDate = 58038 - builtinCurTime = 58039 - builtinDateAdd = 58040 - builtinDateSub = 58041 - builtinExtract = 58042 - builtinGroupConcat = 58043 - builtinMax = 58044 - builtinMin = 58045 - builtinNow = 58046 - builtinPosition = 58047 - builtinStddevPop = 58052 - builtinStddevSamp = 58053 - builtinSubDate = 58048 - builtinSubstring = 58049 - builtinSum = 58050 - builtinSysDate = 58051 - builtinTranslate = 58054 - builtinTrim = 58055 - builtinUser = 58056 - builtinVarPop = 58057 - builtinVarSamp = 58058 - builtins = 57993 + bound = 57917 + briefType = 57918 + btree = 57607 + buckets = 57995 + builtinApproxCountDistinct = 58038 + builtinApproxPercentile = 58039 + builtinBitAnd = 58033 + builtinBitOr = 58034 + builtinBitXor = 58035 + builtinCast = 58036 + builtinCount = 58037 + builtinCurDate = 58040 + builtinCurTime = 58041 + builtinDateAdd = 58042 + builtinDateSub = 58043 + builtinExtract = 58044 + builtinGroupConcat = 58045 + builtinMax = 58046 + builtinMin = 58047 + builtinNow = 58048 + builtinPosition = 58049 + builtinStddevPop = 58053 + builtinStddevSamp = 58054 + builtinSubstring = 58050 + builtinSum = 58051 + builtinSysDate = 58052 + builtinTranslate = 58055 + builtinTrim = 58056 + builtinUser = 58057 + builtinVarPop = 58058 + builtinVarSamp = 58059 + builtins = 57996 by = 57371 - byteType = 57607 - cache = 57608 + byteType = 57608 + cache = 57609 call = 57372 - cancel = 57994 - capture = 57609 - cardinality = 57995 + cancel = 57997 + capture = 57610 + cardinality = 57998 cascade = 57373 - cascaded = 57610 + cascaded = 57611 caseKwd = 57374 - cast = 57916 - causal = 57611 - chain = 57612 + cast = 57919 + causal = 57612 + chain = 57613 change = 57375 charType = 57377 character = 57376 - charsetKwd = 57613 + charsetKwd = 57614 check = 57378 - checkpoint = 57614 - checksum = 57615 - cipher = 57616 - cleanup = 57617 - client = 57618 - clientErrorsSummary = 57619 - clustered = 57645 - cmSketch = 57996 - coalesce = 57620 + checkpoint = 57615 + checksum = 57616 + cipher = 57617 + cleanup = 57618 + client = 57619 + clientErrorsSummary = 57620 + clustered = 57646 + cmSketch = 57999 + coalesce = 57621 collate = 57379 - collation = 57621 + collation = 57622 column = 57380 - columnFormat = 57622 - columnStatsUsage = 57997 - columns = 57623 - comment = 57625 - commit = 57626 - committed = 57627 - compact = 57628 - compressed = 57629 - compression = 57630 - concurrency = 57631 - config = 57624 - connection = 57632 - consistency = 57633 - consistent = 57634 + columnFormat = 57623 + columnStatsUsage = 58000 + columns = 57624 + comment = 57626 + commit = 57627 + committed = 57628 + compact = 57629 + compressed = 57630 + compression = 57631 + concurrency = 57632 + config = 57625 + connection = 57633 + consistency = 57634 + consistent = 57635 constraint = 57381 - constraints = 57918 - context = 57635 + constraints = 57921 + context = 57636 convert = 57382 - copyKwd = 57917 - correlation = 57998 - cpu = 57636 + copyKwd = 57920 + correlation = 58001 + cpu = 57637 create = 57383 - createTableSelect = 58087 + createTableSelect = 58088 cross = 57384 - csvBackslashEscape = 57637 - csvDelimiter = 57638 - csvHeader = 57639 - csvNotNull = 57640 - csvNull = 57641 - csvSeparator = 57642 - csvTrimLastSeparators = 57643 + csvBackslashEscape = 57638 + csvDelimiter = 57639 + csvHeader = 57640 + csvNotNull = 57641 + csvNull = 57642 + csvSeparator = 57643 + csvTrimLastSeparators = 57644 cumeDist = 57385 - curTime = 57919 - current = 57644 + curTime = 57922 + current = 57645 currentDate = 57386 currentRole = 57390 currentTime = 57387 currentTs = 57388 currentUser = 57389 - cycle = 57646 - data = 57647 + cycle = 57647 + data = 57648 database = 57391 databases = 57392 - dateAdd = 57920 - dateSub = 57921 - dateType = 57649 - datetimeType = 57648 - day = 57650 + dateAdd = 57923 + dateSub = 57924 + dateType = 57650 + datetimeType = 57649 + day = 57651 dayHour = 57393 dayMicrosecond = 57394 dayMinute = 57395 daySecond = 57396 - ddl = 57999 - deallocate = 57651 - decLit = 58060 + ddl = 58002 + deallocate = 57652 + decLit = 58061 decimalType = 57397 defaultKwd = 57398 - definer = 57652 - delayKeyWrite = 57653 + definer = 57653 + delayKeyWrite = 57654 delayed = 57399 deleteKwd = 57400 denseRank = 57401 - dependency = 58000 - depth = 58001 + dependency = 58003 + depth = 58004 desc = 57402 describe = 57403 - directory = 57654 - disable = 57655 - discard = 57656 - disk = 57657 + directory = 57655 + disable = 57656 + disabled = 57657 + discard = 57658 + disk = 57659 distinct = 57404 distinctRow = 57405 div = 57406 - do = 57658 - dotType = 57922 + do = 57660 + dotType = 57925 doubleAtIdentifier = 57351 doubleType = 57407 - drainer = 58002 + drainer = 58005 drop = 57408 dual = 57409 - dump = 57923 - duplicate = 57659 - dynamic = 57660 + dump = 57926 + duplicate = 57661 + dynamic = 57662 elseKwd = 57410 - empty = 58078 - enable = 57661 + empty = 58079 + enable = 57663 + enabled = 57664 enclosed = 57411 - encryption = 57662 - end = 57663 - enforced = 57664 - engine = 57665 - engines = 57666 - enum = 57667 - eq = 58066 + encryption = 57665 + end = 57666 + enforced = 57667 + engine = 57668 + engines = 57669 + enum = 57670 + eq = 58067 yyErrCode = 57345 - errorKwd = 57668 - escape = 57669 + errorKwd = 57671 + escape = 57672 escaped = 57412 - event = 57670 - events = 57671 - evolve = 57672 - exact = 57924 + event = 57673 + events = 57674 + evolve = 57675 + exact = 57927 except = 57415 - exchange = 57673 - exclusive = 57674 - execute = 57675 + exchange = 57676 + exclusive = 57677 + execute = 57678 exists = 57413 - expansion = 57676 - expire = 57677 + expansion = 57679 + expire = 57680 explain = 57414 - exprPushdownBlacklist = 57925 - extended = 57678 - extract = 57926 + exprPushdownBlacklist = 57928 + extended = 57681 + extract = 57929 falseKwd = 57416 - faultsSym = 57679 + faultsSym = 57682 fetch = 57417 - fields = 57680 - file = 57681 - first = 57682 + fields = 57683 + file = 57684 + first = 57685 firstValue = 57418 - fixed = 57683 - flashback = 57927 - floatLit = 58059 + fixed = 57686 + flashback = 57930 + floatLit = 58060 floatType = 57419 - flush = 57684 - follower = 57928 - followerConstraints = 57929 - followers = 57930 - following = 57685 + flush = 57687 + follower = 57931 + followerConstraints = 57932 + followers = 57933 + following = 57688 forKwd = 57420 force = 57421 foreign = 57422 - format = 57686 + format = 57689 from = 57423 - full = 57687 + full = 57690 fulltext = 57424 - function = 57688 - ge = 58067 - general = 57689 + function = 57691 + ge = 58068 + general = 57692 generated = 57425 - getFormat = 57931 - global = 57690 + getFormat = 57934 + global = 57693 grant = 57426 - grants = 57691 + grants = 57694 group = 57427 - groupConcat = 57932 + groupConcat = 57935 groups = 57428 - hash = 57692 + hash = 57695 having = 57429 - help = 57693 - hexLit = 58062 + help = 57696 + hexLit = 58063 highPriority = 57430 - higherThanComma = 58102 - higherThanParenthese = 58096 + higherThanComma = 58103 + higherThanParenthese = 58097 hintComment = 57353 - histogram = 57694 - histogramsInFlight = 58019 - history = 57695 - hosts = 57696 - hour = 57697 + histogram = 57697 + histogramsInFlight = 58022 + history = 57698 + hosts = 57699 + hour = 57700 hourMicrosecond = 57431 hourMinute = 57432 hourSecond = 57433 - identSQLErrors = 57699 - identified = 57698 + identSQLErrors = 57702 + identified = 57701 identifier = 57346 ifKwd = 57434 ignore = 57435 - importKwd = 57700 - imports = 57701 + importKwd = 57703 + imports = 57704 in = 57436 - increment = 57702 - incremental = 57703 + increment = 57705 + incremental = 57706 index = 57437 - indexes = 57704 + indexes = 57707 infile = 57438 inner = 57439 - inplace = 57934 + inplace = 57937 insert = 57446 - insertMethod = 57705 - insertValues = 58085 - instance = 57706 - instant = 57935 + insertMethod = 57708 + insertValues = 58086 + instance = 57709 + instant = 57938 int1Type = 57448 int2Type = 57449 int3Type = 57450 int4Type = 57451 int8Type = 57452 - intLit = 58061 + intLit = 58062 intType = 57447 integerType = 57440 - internal = 57936 + internal = 57939 intersect = 57441 interval = 57442 into = 57443 invalid = 57352 - invisible = 57707 - invoker = 57708 - io = 57709 - ipc = 57710 + invisible = 57710 + invoker = 57711 + io = 57712 + ipc = 57713 is = 57445 - isolation = 57711 - issuer = 57712 - job = 58004 - jobs = 58003 + isolation = 57714 + issuer = 57715 + job = 58007 + jobs = 58006 join = 57453 - jsonArrayagg = 57937 - jsonObjectAgg = 57938 - jsonType = 57713 - jss = 58069 - juss = 58070 + jsonArrayagg = 57940 + jsonObjectAgg = 57941 + jsonType = 57716 + jss = 58070 + juss = 58071 key = 57454 - keyBlockSize = 57714 + keyBlockSize = 57717 keys = 57455 kill = 57456 - labels = 57715 + labels = 57718 lag = 57457 - language = 57716 - last = 57717 - lastBackup = 57718 + language = 57719 + last = 57720 + lastBackup = 57721 lastValue = 57458 - lastval = 57719 - le = 58068 + lastval = 57722 + le = 58069 lead = 57459 - leader = 57939 - leaderConstraints = 57940 + leader = 57942 + leaderConstraints = 57943 leading = 57460 - learner = 57941 - learnerConstraints = 57942 - learners = 57943 + learner = 57944 + learnerConstraints = 57945 + learners = 57946 left = 57461 - less = 57720 - level = 57721 + less = 57723 + level = 57724 like = 57462 limit = 57463 linear = 57465 lines = 57464 - list = 57722 + list = 57725 load = 57466 - local = 57723 + local = 57726 localTime = 57467 localTs = 57468 - location = 57725 + location = 57728 lock = 57469 - locked = 57724 - logs = 57726 + locked = 57727 + logs = 57729 long = 57558 longblobType = 57470 longtextType = 57471 lowPriority = 57472 - lowerThanCharsetKwd = 58088 - lowerThanComma = 58101 - lowerThanCreateTableSelect = 58086 - lowerThanEq = 58098 - lowerThanFunction = 58093 - lowerThanInsertValues = 58084 - lowerThanKey = 58089 - lowerThanLocal = 58090 - lowerThanNot = 58100 - lowerThanOn = 58097 - lowerThanParenthese = 58095 - lowerThanRemove = 58091 - lowerThanSelectOpt = 58079 - lowerThanSelectStmt = 58083 - lowerThanSetKeyword = 58082 - lowerThanStringLitToken = 58081 - lowerThanValueKeyword = 58080 - lowerThenOrder = 58092 - lsh = 58071 - master = 57727 + lowerThanCharsetKwd = 58089 + lowerThanComma = 58102 + lowerThanCreateTableSelect = 58087 + lowerThanEq = 58099 + lowerThanFunction = 58094 + lowerThanInsertValues = 58085 + lowerThanKey = 58090 + lowerThanLocal = 58091 + lowerThanNot = 58101 + lowerThanOn = 58098 + lowerThanParenthese = 58096 + lowerThanRemove = 58092 + lowerThanSelectOpt = 58080 + lowerThanSelectStmt = 58084 + lowerThanSetKeyword = 58083 + lowerThanStringLitToken = 58082 + lowerThanValueKeyword = 58081 + lowerThenOrder = 58093 + lsh = 58072 + master = 57730 match = 57473 - max = 57945 - maxConnectionsPerHour = 57730 - maxQueriesPerHour = 57731 - maxRows = 57732 - maxUpdatesPerHour = 57733 - maxUserConnections = 57734 + max = 57948 + maxConnectionsPerHour = 57733 + maxQueriesPerHour = 57734 + maxRows = 57735 + maxUpdatesPerHour = 57736 + maxUserConnections = 57737 maxValue = 57474 - max_idxnum = 57728 - max_minutes = 57729 - mb = 57735 + max_idxnum = 57731 + max_minutes = 57732 + mb = 57738 mediumIntType = 57476 mediumblobType = 57475 mediumtextType = 57477 - memory = 57736 - merge = 57737 - microsecond = 57738 - min = 57944 - minRows = 57739 - minValue = 57741 - minute = 57740 + memory = 57739 + merge = 57740 + microsecond = 57741 + min = 57947 + minRows = 57742 + minValue = 57744 + minute = 57743 minuteMicrosecond = 57478 minuteSecond = 57479 mod = 57480 - mode = 57742 - modify = 57743 - month = 57744 - names = 57745 - national = 57746 + mode = 57745 + modify = 57746 + month = 57747 + names = 57748 + national = 57749 natural = 57572 - ncharType = 57747 - neg = 58099 - neq = 58072 - neqSynonym = 58073 - never = 57748 - next = 57749 - next_row_id = 57933 - nextval = 57750 - no = 57751 + ncharType = 57750 + neg = 58100 + neq = 58073 + neqSynonym = 58074 + never = 57751 + next = 57752 + next_row_id = 57936 + nextval = 57753 + no = 57754 noWriteToBinLog = 57482 - nocache = 57752 - nocycle = 57753 - nodeID = 58005 - nodeState = 58006 - nodegroup = 57754 - nomaxvalue = 57755 - nominvalue = 57756 - nonclustered = 57757 - none = 57758 + nocache = 57755 + nocycle = 57756 + nodeID = 58008 + nodeState = 58009 + nodegroup = 57757 + nomaxvalue = 57758 + nominvalue = 57759 + nonclustered = 57760 + none = 57761 not = 57481 - not2 = 58077 - now = 57946 - nowait = 57759 + not2 = 58078 + now = 57949 + nowait = 57762 nthValue = 57483 ntile = 57484 null = 57485 - nulleq = 58074 - nulls = 57761 + nulleq = 58075 + nulls = 57764 numericType = 57486 - nvarcharType = 57760 + nvarcharType = 57763 odbcDateType = 57356 odbcTimeType = 57357 odbcTimestampType = 57358 of = 57487 - off = 57762 - offset = 57763 + off = 57765 + offset = 57766 on = 57488 - onDuplicate = 57764 - online = 57765 - only = 57766 - open = 57767 - optRuleBlacklist = 57947 - optimistic = 58007 + onDuplicate = 57767 + online = 57768 + only = 57769 + open = 57770 + optRuleBlacklist = 57950 + optimistic = 58010 optimize = 57489 option = 57490 - optional = 57768 + optional = 57771 optionally = 57491 or = 57492 order = 57493 outer = 57494 outfile = 57444 over = 57495 - packKeys = 57769 - pageSym = 57770 - paramMarker = 58075 - parser = 57771 - partial = 57772 + packKeys = 57772 + pageSym = 57773 + paramMarker = 58076 + parser = 57774 + partial = 57775 partition = 57496 - partitioning = 57773 - partitions = 57774 - password = 57775 - per_db = 57777 - per_table = 57778 - percent = 57776 + partitioning = 57776 + partitions = 57777 + password = 57778 + per_db = 57780 + per_table = 57781 + percent = 57779 percentRank = 57497 - pessimistic = 58008 + pessimistic = 58011 pipes = 57355 - pipesAsOr = 57779 - placement = 57948 - plan = 57949 - planCache = 57950 - plugins = 57780 - policy = 57781 - position = 57951 - preSplitRegions = 57782 - preceding = 57783 + pipesAsOr = 57782 + placement = 57951 + plan = 57952 + planCache = 57953 + plugins = 57783 + policy = 57784 + position = 57954 + preSplitRegions = 57785 + preceding = 57786 precisionType = 57498 - predicate = 57952 - prepare = 57784 - preserve = 57785 + predicate = 57955 + prepare = 57787 + preserve = 57788 primary = 57499 - primaryRegion = 57953 - privileges = 57786 + primaryRegion = 57956 + privileges = 57789 procedure = 57500 - process = 57787 - processlist = 57788 - profile = 57789 - profiles = 57790 - proxy = 57791 - pump = 58009 - purge = 57792 - quarter = 57793 - queries = 57794 - query = 57795 - quick = 57796 + process = 57790 + processlist = 57791 + profile = 57792 + profiles = 57793 + proxy = 57794 + pump = 58012 + purge = 57795 + quarter = 57796 + queries = 57797 + query = 57798 + quick = 57799 rangeKwd = 57501 rank = 57502 - rateLimit = 57797 + rateLimit = 57800 read = 57503 realType = 57504 - rebuild = 57798 - recent = 57954 - recover = 57799 + rebuild = 57801 + recent = 57957 + recover = 57802 recursive = 57505 - redundant = 57800 + redundant = 57803 references = 57506 regexpKwd = 57507 - region = 58029 - regions = 58028 + region = 58032 + regions = 58031 release = 57508 - reload = 57801 - remove = 57802 + reload = 57804 + remove = 57805 rename = 57509 - reorganize = 57803 - repair = 57804 + reorganize = 57806 + repair = 57807 repeat = 57510 - repeatable = 57805 + repeatable = 57808 replace = 57511 - replayer = 57955 - replica = 57806 - replicas = 57807 - replication = 57808 + replayer = 57958 + replica = 57809 + replicas = 57810 + replication = 57811 require = 57512 - required = 57809 - reset = 58027 - respect = 57810 - restart = 57811 - restore = 57812 - restores = 57813 + required = 57812 + reset = 58030 + respect = 57813 + restart = 57814 + restore = 57815 + restores = 57816 restrict = 57513 - resume = 57814 - reverse = 57815 + resume = 57817 + reverse = 57818 revoke = 57514 right = 57515 rlike = 57516 - role = 57816 - rollback = 57817 - routine = 57818 + role = 57819 + rollback = 57820 + routine = 57821 row = 57517 - rowCount = 57819 - rowFormat = 57820 + rowCount = 57822 + rowFormat = 57823 rowNumber = 57519 rows = 57518 - rsh = 58076 - rtree = 57821 - running = 57956 - s3 = 57957 - sampleRate = 58011 - samples = 58010 - san = 57822 - schedule = 57958 - second = 57823 + rsh = 58077 + rtree = 57824 + running = 57959 + s3 = 57960 + sampleRate = 58014 + samples = 58013 + san = 57825 + schedule = 57961 + second = 57826 secondMicrosecond = 57520 - secondaryEngine = 57824 - secondaryLoad = 57825 - secondaryUnload = 57826 - security = 57827 + secondaryEngine = 57827 + secondaryLoad = 57828 + secondaryUnload = 57829 + security = 57830 selectKwd = 57521 - sendCredentialsToTiKV = 57828 - separator = 57829 - sequence = 57830 - serial = 57831 - serializable = 57832 - session = 57833 + sendCredentialsToTiKV = 57831 + separator = 57832 + sequence = 57833 + serial = 57834 + serializable = 57835 + session = 57836 set = 57522 - setval = 57834 - shardRowIDBits = 57835 - share = 57836 - shared = 57837 + setval = 57837 + shardRowIDBits = 57838 + share = 57839 + shared = 57840 show = 57523 - shutdown = 57838 - signed = 57839 - simple = 57840 + shutdown = 57841 + signed = 57842 + simple = 57843 singleAtIdentifier = 57350 - skip = 57841 - skipSchemaFiles = 57842 - slave = 57843 - slow = 57844 + skip = 57844 + skipSchemaFiles = 57845 + slave = 57846 + slow = 57847 smallIntType = 57524 - snapshot = 57845 - some = 57846 - source = 57847 + snapshot = 57848 + some = 57849 + source = 57850 spatial = 57525 - split = 58025 + split = 58028 sql = 57526 sqlBigResult = 57527 - sqlBufferResult = 57848 - sqlCache = 57849 + sqlBufferResult = 57851 + sqlCache = 57852 sqlCalcFoundRows = 57528 - sqlNoCache = 57850 + sqlNoCache = 57853 sqlSmallResult = 57529 - sqlTsiDay = 57851 - sqlTsiHour = 57852 - sqlTsiMinute = 57853 - sqlTsiMonth = 57854 - sqlTsiQuarter = 57855 - sqlTsiSecond = 57856 - sqlTsiWeek = 57857 - sqlTsiYear = 57858 + sqlTsiDay = 57854 + sqlTsiHour = 57855 + sqlTsiMinute = 57856 + sqlTsiMonth = 57857 + sqlTsiQuarter = 57858 + sqlTsiSecond = 57859 + sqlTsiWeek = 57860 + sqlTsiYear = 57861 ssl = 57530 - staleness = 57959 - start = 57859 + staleness = 57962 + start = 57862 starting = 57531 - statistics = 58012 - stats = 58013 - statsAutoRecalc = 57860 - statsBuckets = 58016 + statistics = 58015 + stats = 58016 + statsAutoRecalc = 57863 + statsBuckets = 58019 statsColChoice = 57586 statsColList = 57587 statsExtended = 57532 - statsHealthy = 58017 - statsHistograms = 58015 - statsMeta = 58014 + statsHealthy = 58020 + statsHistograms = 58018 + statsMeta = 58017 statsOptions = 57584 - statsPersistent = 57861 - statsSamplePages = 57862 + statsPersistent = 57864 + statsSamplePages = 57865 statsSampleRate = 57585 - statsTopN = 58018 - status = 57863 - std = 57960 - stddev = 57961 - stddevPop = 57962 - stddevSamp = 57963 - stop = 57964 - storage = 57864 + statsTopN = 58021 + status = 57866 + std = 57963 + stddev = 57964 + stddevPop = 57965 + stddevSamp = 57966 + stop = 57967 + storage = 57867 stored = 57536 straightJoin = 57533 - strict = 57965 - strictFormat = 57865 + strict = 57968 + strictFormat = 57868 stringLit = 57349 - strong = 57966 - subDate = 57967 - subject = 57866 - subpartition = 57867 - subpartitions = 57868 - substring = 57969 - sum = 57968 - super = 57869 - swaps = 57870 - switchesSym = 57871 - system = 57872 - systemTime = 57873 - tableChecksum = 57874 + strong = 57969 + subDate = 57970 + subject = 57869 + subpartition = 57870 + subpartitions = 57871 + substring = 57972 + sum = 57971 + super = 57872 + swaps = 57873 + switchesSym = 57874 + system = 57875 + systemTime = 57876 + tableChecksum = 57877 tableKwd = 57534 - tableRefPriority = 58094 + tableRefPriority = 58095 tableSample = 57535 - tables = 57875 - tablespace = 57876 - target = 57970 - telemetry = 58020 - telemetryID = 58021 - temporary = 57877 - temptable = 57878 + tables = 57878 + tablespace = 57879 + target = 57973 + telemetry = 58023 + telemetryID = 58024 + temporary = 57880 + temptable = 57881 terminated = 57537 - textType = 57879 - than = 57880 + textType = 57882 + than = 57883 then = 57538 - tiFlash = 58023 - tidb = 58022 - tikvImporter = 57881 - timeType = 57883 - timestampAdd = 57971 - timestampDiff = 57972 - timestampType = 57882 + tiFlash = 58026 + tidb = 58025 + tikvImporter = 57884 + timeType = 57886 + timestampAdd = 57974 + timestampDiff = 57975 + timestampType = 57885 tinyIntType = 57540 tinyblobType = 57539 tinytextType = 57541 - tls = 57973 + tls = 57976 to = 57542 - tokudbDefault = 57974 - tokudbFast = 57975 - tokudbLzma = 57976 - tokudbQuickLZ = 57977 - tokudbSmall = 57979 - tokudbSnappy = 57978 - tokudbUncompressed = 57980 - tokudbZlib = 57981 - top = 57982 - topn = 58024 - tp = 57884 - trace = 57885 - traditional = 57886 + tokudbDefault = 57977 + tokudbFast = 57978 + tokudbLzma = 57979 + tokudbQuickLZ = 57980 + tokudbSmall = 57982 + tokudbSnappy = 57981 + tokudbUncompressed = 57983 + tokudbZlib = 57984 + top = 57985 + topn = 58027 + tp = 57887 + trace = 57888 + traditional = 57889 trailing = 57543 - transaction = 57887 + transaction = 57890 trigger = 57544 - triggers = 57888 - trim = 57983 + triggers = 57891 + trim = 57986 trueKwd = 57545 - truncate = 57889 - unbounded = 57890 - uncommitted = 57891 - undefined = 57892 + truncate = 57892 + unbounded = 57893 + uncommitted = 57894 + undefined = 57895 underscoreCS = 57348 - unicodeSym = 57893 + unicodeSym = 57896 union = 57547 unique = 57546 - unknown = 57894 + unknown = 57897 unlock = 57548 unsigned = 57549 update = 57550 usage = 57551 use = 57552 - user = 57895 + user = 57898 using = 57553 utcDate = 57554 utcTime = 57556 utcTimestamp = 57555 - validation = 57896 - value = 57897 + validation = 57899 + value = 57900 values = 57557 - varPop = 57985 - varSamp = 57986 + varPop = 57988 + varSamp = 57989 varbinaryType = 57561 varcharType = 57559 varcharacter = 57560 - variables = 57898 - variance = 57984 + variables = 57901 + variance = 57987 varying = 57562 - verboseType = 57987 - view = 57899 + verboseType = 57990 + view = 57902 virtual = 57563 - visible = 57900 - voter = 57988 - voterConstraints = 57989 - voters = 57990 - wait = 57907 - warnings = 57901 - week = 57902 - weightString = 57903 + visible = 57903 + voter = 57991 + voterConstraints = 57992 + voters = 57993 + wait = 57910 + warnings = 57904 + week = 57905 + weightString = 57906 when = 57564 where = 57565 - width = 58026 + width = 58029 window = 57567 with = 57568 - without = 57904 + without = 57907 write = 57566 - x509 = 57905 + x509 = 57908 xor = 57569 yearMonth = 57570 - yearType = 57906 + yearType = 57909 zerofill = 57571 yyMaxDepth = 200 - yyTabOfs = -2460 + yyTabOfs = -2474 ) var ( yyXLAT = map[int]int{ - 57344: 0, // $end (2168x) - 59: 1, // ';' (2167x) - 57802: 2, // remove (1839x) - 57803: 3, // reorganize (1839x) - 57625: 4, // comment (1775x) - 57864: 5, // storage (1751x) - 57589: 6, // autoIncrement (1740x) - 44: 7, // ',' (1648x) - 57682: 8, // first (1626x) - 57576: 9, // after (1624x) - 57831: 10, // serial (1620x) - 57590: 11, // autoRandom (1619x) - 57622: 12, // columnFormat (1619x) - 57613: 13, // charsetKwd (1611x) - 57775: 14, // password (1607x) - 58028: 15, // regions (1603x) - 57948: 16, // placement (1597x) - 57918: 17, // constraints (1596x) - 57929: 18, // followerConstraints (1596x) - 57930: 19, // followers (1596x) - 57940: 20, // leaderConstraints (1596x) - 57942: 21, // learnerConstraints (1596x) - 57943: 22, // learners (1596x) - 57953: 23, // primaryRegion (1596x) - 57958: 24, // schedule (1596x) - 57989: 25, // voterConstraints (1596x) - 57990: 26, // voters (1596x) - 57615: 27, // checksum (1593x) - 57662: 28, // encryption (1576x) - 57714: 29, // keyBlockSize (1575x) - 57876: 30, // tablespace (1572x) - 57665: 31, // engine (1567x) - 57647: 32, // data (1565x) - 57705: 33, // insertMethod (1563x) - 57732: 34, // maxRows (1563x) - 57739: 35, // minRows (1563x) - 57754: 36, // nodegroup (1563x) - 57632: 37, // connection (1555x) - 57591: 38, // autoRandomBase (1552x) - 58016: 39, // statsBuckets (1550x) - 58018: 40, // statsTopN (1550x) - 57588: 41, // autoIdCache (1549x) - 57593: 42, // avgRowLength (1549x) - 57630: 43, // compression (1549x) - 57653: 44, // delayKeyWrite (1549x) - 57769: 45, // packKeys (1549x) - 57782: 46, // preSplitRegions (1549x) - 57820: 47, // rowFormat (1549x) - 57824: 48, // secondaryEngine (1549x) - 57835: 49, // shardRowIDBits (1549x) - 57860: 50, // statsAutoRecalc (1549x) - 57586: 51, // statsColChoice (1549x) - 57587: 52, // statsColList (1549x) - 57861: 53, // statsPersistent (1549x) - 57862: 54, // statsSamplePages (1549x) - 57585: 55, // statsSampleRate (1549x) - 57874: 56, // tableChecksum (1549x) - 41: 57, // ')' (1484x) - 57573: 58, // account (1483x) - 57814: 59, // resume (1473x) - 57839: 60, // signed (1473x) - 57845: 61, // snapshot (1472x) - 57594: 62, // backend (1471x) - 57614: 63, // checkpoint (1471x) - 57631: 64, // concurrency (1471x) - 57637: 65, // csvBackslashEscape (1471x) - 57638: 66, // csvDelimiter (1471x) - 57639: 67, // csvHeader (1471x) - 57640: 68, // csvNotNull (1471x) - 57641: 69, // csvNull (1471x) - 57642: 70, // csvSeparator (1471x) - 57643: 71, // csvTrimLastSeparators (1471x) - 57718: 72, // lastBackup (1471x) - 57764: 73, // onDuplicate (1471x) - 57765: 74, // online (1471x) - 57797: 75, // rateLimit (1471x) - 57828: 76, // sendCredentialsToTiKV (1471x) - 57842: 77, // skipSchemaFiles (1471x) - 57865: 78, // strictFormat (1471x) - 57881: 79, // tikvImporter (1471x) - 57889: 80, // truncate (1468x) - 57751: 81, // no (1467x) - 57859: 82, // start (1465x) - 57608: 83, // cache (1462x) - 57752: 84, // nocache (1461x) - 57646: 85, // cycle (1460x) - 57741: 86, // minValue (1460x) - 57702: 87, // increment (1459x) - 57753: 88, // nocycle (1459x) - 57755: 89, // nomaxvalue (1459x) - 57756: 90, // nominvalue (1459x) - 57811: 91, // restart (1457x) - 57579: 92, // algorithm (1456x) - 57884: 93, // tp (1456x) - 57645: 94, // clustered (1455x) - 57707: 95, // invisible (1455x) - 57757: 96, // nonclustered (1455x) - 57900: 97, // visible (1455x) - 57623: 98, // columns (1447x) - 57899: 99, // view (1447x) - 57867: 100, // subpartition (1443x) - 57582: 101, // ascii (1442x) - 57607: 102, // byteType (1442x) - 57774: 103, // partitions (1442x) - 57893: 104, // unicodeSym (1442x) - 57906: 105, // yearType (1442x) - 57650: 106, // day (1441x) - 57680: 107, // fields (1441x) - 57823: 108, // second (1440x) - 57858: 109, // sqlTsiYear (1440x) - 57875: 110, // tables (1440x) - 57697: 111, // hour (1439x) - 57738: 112, // microsecond (1439x) - 57740: 113, // minute (1439x) - 57744: 114, // month (1439x) - 57793: 115, // quarter (1439x) - 57851: 116, // sqlTsiDay (1439x) - 57852: 117, // sqlTsiHour (1439x) - 57853: 118, // sqlTsiMinute (1439x) - 57854: 119, // sqlTsiMonth (1439x) - 57855: 120, // sqlTsiQuarter (1439x) - 57856: 121, // sqlTsiSecond (1439x) - 57857: 122, // sqlTsiWeek (1439x) - 57902: 123, // week (1439x) - 57829: 124, // separator (1438x) - 57863: 125, // status (1438x) - 57730: 126, // maxConnectionsPerHour (1437x) - 57731: 127, // maxQueriesPerHour (1437x) - 57733: 128, // maxUpdatesPerHour (1437x) - 57734: 129, // maxUserConnections (1437x) - 57783: 130, // preceding (1437x) - 57616: 131, // cipher (1436x) - 57700: 132, // importKwd (1436x) - 57712: 133, // issuer (1436x) - 57822: 134, // san (1436x) - 57866: 135, // subject (1436x) - 57723: 136, // local (1435x) - 57841: 137, // skip (1435x) - 57600: 138, // bindings (1434x) - 57652: 139, // definer (1434x) - 57692: 140, // hash (1434x) - 57698: 141, // identified (1434x) - 57726: 142, // logs (1434x) - 57795: 143, // query (1434x) - 57810: 144, // respect (1434x) - 57626: 145, // commit (1433x) - 57644: 146, // current (1433x) - 57664: 147, // enforced (1433x) - 57685: 148, // following (1433x) - 57759: 149, // nowait (1433x) - 57766: 150, // only (1433x) - 57817: 151, // rollback (1433x) - 57897: 152, // value (1433x) - 57597: 153, // begin (1432x) - 57599: 154, // binding (1432x) - 57663: 155, // end (1432x) - 57690: 156, // global (1432x) - 57933: 157, // next_row_id (1432x) - 57781: 158, // policy (1432x) - 57952: 159, // predicate (1432x) - 57877: 160, // temporary (1432x) - 57890: 161, // unbounded (1432x) - 57895: 162, // user (1432x) - 57346: 163, // identifier (1431x) - 57763: 164, // offset (1431x) - 57950: 165, // planCache (1431x) - 57784: 166, // prepare (1431x) - 57816: 167, // role (1431x) - 57894: 168, // unknown (1431x) - 57907: 169, // wait (1431x) - 57606: 170, // btree (1430x) - 57648: 171, // datetimeType (1430x) - 57649: 172, // dateType (1430x) - 57683: 173, // fixed (1430x) - 57711: 174, // isolation (1430x) - 57713: 175, // jsonType (1430x) - 57728: 176, // max_idxnum (1430x) - 57736: 177, // memory (1430x) - 57762: 178, // off (1430x) - 57768: 179, // optional (1430x) - 57777: 180, // per_db (1430x) - 57786: 181, // privileges (1430x) - 57809: 182, // required (1430x) - 57821: 183, // rtree (1430x) - 57956: 184, // running (1430x) - 58011: 185, // sampleRate (1430x) - 57830: 186, // sequence (1430x) - 57833: 187, // session (1430x) - 57844: 188, // slow (1430x) - 57883: 189, // timeType (1430x) - 57896: 190, // validation (1430x) - 57898: 191, // variables (1430x) - 57583: 192, // attributes (1429x) - 57655: 193, // disable (1429x) - 57659: 194, // duplicate (1429x) - 57660: 195, // dynamic (1429x) - 57661: 196, // enable (1429x) - 57668: 197, // errorKwd (1429x) - 57684: 198, // flush (1429x) - 57687: 199, // full (1429x) - 57699: 200, // identSQLErrors (1429x) - 57725: 201, // location (1429x) - 57735: 202, // mb (1429x) - 57742: 203, // mode (1429x) - 57748: 204, // never (1429x) - 57949: 205, // plan (1429x) - 57780: 206, // plugins (1429x) - 57788: 207, // processlist (1429x) - 57799: 208, // recover (1429x) - 57804: 209, // repair (1429x) - 57805: 210, // repeatable (1429x) - 58012: 211, // statistics (1429x) - 57868: 212, // subpartitions (1429x) - 58022: 213, // tidb (1429x) - 57882: 214, // timestampType (1429x) - 57904: 215, // without (1429x) - 57991: 216, // admin (1428x) - 57595: 217, // backup (1428x) - 57601: 218, // binlog (1428x) - 57603: 219, // block (1428x) - 57604: 220, // booleanType (1428x) - 57992: 221, // buckets (1428x) - 57995: 222, // cardinality (1428x) - 57612: 223, // chain (1428x) - 57619: 224, // clientErrorsSummary (1428x) - 57996: 225, // cmSketch (1428x) - 57620: 226, // coalesce (1428x) - 57628: 227, // compact (1428x) - 57629: 228, // compressed (1428x) - 57635: 229, // context (1428x) - 57917: 230, // copyKwd (1428x) - 57998: 231, // correlation (1428x) - 57636: 232, // cpu (1428x) - 57651: 233, // deallocate (1428x) - 58000: 234, // dependency (1428x) - 57654: 235, // directory (1428x) - 57656: 236, // discard (1428x) - 57657: 237, // disk (1428x) - 57658: 238, // do (1428x) - 58002: 239, // drainer (1428x) - 57673: 240, // exchange (1428x) - 57675: 241, // execute (1428x) - 57676: 242, // expansion (1428x) - 57927: 243, // flashback (1428x) - 57689: 244, // general (1428x) - 57693: 245, // help (1428x) - 57694: 246, // histogram (1428x) - 57696: 247, // hosts (1428x) - 57934: 248, // inplace (1428x) - 57706: 249, // instance (1428x) - 57935: 250, // instant (1428x) - 57710: 251, // ipc (1428x) - 58004: 252, // job (1428x) - 58003: 253, // jobs (1428x) - 57715: 254, // labels (1428x) - 57724: 255, // locked (1428x) - 57743: 256, // modify (1428x) - 57749: 257, // next (1428x) - 58005: 258, // nodeID (1428x) - 58006: 259, // nodeState (1428x) - 57761: 260, // nulls (1428x) - 57770: 261, // pageSym (1428x) - 58009: 262, // pump (1428x) - 57792: 263, // purge (1428x) - 57798: 264, // rebuild (1428x) - 57800: 265, // redundant (1428x) - 57801: 266, // reload (1428x) - 57812: 267, // restore (1428x) - 57818: 268, // routine (1428x) - 57957: 269, // s3 (1428x) - 58010: 270, // samples (1428x) - 57825: 271, // secondaryLoad (1428x) - 57826: 272, // secondaryUnload (1428x) - 57836: 273, // share (1428x) - 57838: 274, // shutdown (1428x) - 57847: 275, // source (1428x) - 58025: 276, // split (1428x) - 58013: 277, // stats (1428x) - 57584: 278, // statsOptions (1428x) - 57964: 279, // stop (1428x) - 57870: 280, // swaps (1428x) - 57974: 281, // tokudbDefault (1428x) - 57975: 282, // tokudbFast (1428x) - 57976: 283, // tokudbLzma (1428x) - 57977: 284, // tokudbQuickLZ (1428x) - 57979: 285, // tokudbSmall (1428x) - 57978: 286, // tokudbSnappy (1428x) - 57980: 287, // tokudbUncompressed (1428x) - 57981: 288, // tokudbZlib (1428x) - 58024: 289, // topn (1428x) - 57885: 290, // trace (1428x) - 57574: 291, // action (1427x) - 57575: 292, // advise (1427x) - 57577: 293, // against (1427x) - 57578: 294, // ago (1427x) - 57580: 295, // always (1427x) - 57596: 296, // backups (1427x) - 57598: 297, // bernoulli (1427x) - 57602: 298, // bitType (1427x) - 57605: 299, // boolType (1427x) - 57915: 300, // briefType (1427x) - 57993: 301, // builtins (1427x) - 57994: 302, // cancel (1427x) - 57609: 303, // capture (1427x) - 57610: 304, // cascaded (1427x) - 57611: 305, // causal (1427x) - 57617: 306, // cleanup (1427x) - 57618: 307, // client (1427x) - 57621: 308, // collation (1427x) - 57997: 309, // columnStatsUsage (1427x) - 57627: 310, // committed (1427x) - 57624: 311, // config (1427x) - 57633: 312, // consistency (1427x) - 57634: 313, // consistent (1427x) - 57999: 314, // ddl (1427x) - 58001: 315, // depth (1427x) - 57922: 316, // dotType (1427x) - 57923: 317, // dump (1427x) - 57666: 318, // engines (1427x) - 57667: 319, // enum (1427x) - 57671: 320, // events (1427x) - 57672: 321, // evolve (1427x) - 57677: 322, // expire (1427x) - 57925: 323, // exprPushdownBlacklist (1427x) - 57678: 324, // extended (1427x) - 57679: 325, // faultsSym (1427x) - 57686: 326, // format (1427x) - 57688: 327, // function (1427x) - 57691: 328, // grants (1427x) - 58019: 329, // histogramsInFlight (1427x) - 57695: 330, // history (1427x) - 57701: 331, // imports (1427x) - 57703: 332, // incremental (1427x) - 57704: 333, // indexes (1427x) - 57936: 334, // internal (1427x) - 57708: 335, // invoker (1427x) - 57709: 336, // io (1427x) - 57716: 337, // language (1427x) - 57717: 338, // last (1427x) - 57720: 339, // less (1427x) - 57721: 340, // level (1427x) - 57722: 341, // list (1427x) - 57727: 342, // master (1427x) - 57729: 343, // max_minutes (1427x) - 57737: 344, // merge (1427x) - 57746: 345, // national (1427x) - 57747: 346, // ncharType (1427x) - 57750: 347, // nextval (1427x) - 57758: 348, // none (1427x) - 57760: 349, // nvarcharType (1427x) - 57767: 350, // open (1427x) - 58007: 351, // optimistic (1427x) - 57947: 352, // optRuleBlacklist (1427x) - 57771: 353, // parser (1427x) - 57772: 354, // partial (1427x) - 57773: 355, // partitioning (1427x) - 57778: 356, // per_table (1427x) - 57776: 357, // percent (1427x) - 58008: 358, // pessimistic (1427x) - 57785: 359, // preserve (1427x) - 57789: 360, // profile (1427x) - 57790: 361, // profiles (1427x) - 57794: 362, // queries (1427x) - 57954: 363, // recent (1427x) - 58029: 364, // region (1427x) - 57955: 365, // replayer (1427x) - 57806: 366, // replica (1427x) - 58027: 367, // reset (1427x) - 57813: 368, // restores (1427x) - 57827: 369, // security (1427x) - 57832: 370, // serializable (1427x) - 57840: 371, // simple (1427x) - 57843: 372, // slave (1427x) - 58017: 373, // statsHealthy (1427x) - 58015: 374, // statsHistograms (1427x) - 58014: 375, // statsMeta (1427x) - 57965: 376, // strict (1427x) - 57871: 377, // switchesSym (1427x) - 57872: 378, // system (1427x) - 57873: 379, // systemTime (1427x) - 57970: 380, // target (1427x) - 58021: 381, // telemetryID (1427x) - 57878: 382, // temptable (1427x) - 57879: 383, // textType (1427x) - 57880: 384, // than (1427x) - 58023: 385, // tiFlash (1427x) - 57973: 386, // tls (1427x) - 57982: 387, // top (1427x) - 57886: 388, // traditional (1427x) - 57887: 389, // transaction (1427x) - 57888: 390, // triggers (1427x) - 57891: 391, // uncommitted (1427x) - 57892: 392, // undefined (1427x) - 57987: 393, // verboseType (1427x) - 57901: 394, // warnings (1427x) - 58026: 395, // width (1427x) - 57905: 396, // x509 (1427x) - 57908: 397, // addDate (1426x) - 57581: 398, // any (1426x) - 57909: 399, // approxCountDistinct (1426x) - 57910: 400, // approxPercentile (1426x) - 57592: 401, // avg (1426x) - 57911: 402, // bitAnd (1426x) - 57912: 403, // bitOr (1426x) - 57913: 404, // bitXor (1426x) - 57914: 405, // bound (1426x) - 57916: 406, // cast (1426x) - 57919: 407, // curTime (1426x) - 57920: 408, // dateAdd (1426x) - 57921: 409, // dateSub (1426x) - 57669: 410, // escape (1426x) - 57670: 411, // event (1426x) - 57924: 412, // exact (1426x) - 57674: 413, // exclusive (1426x) - 57926: 414, // extract (1426x) - 57681: 415, // file (1426x) - 57928: 416, // follower (1426x) - 57931: 417, // getFormat (1426x) - 57932: 418, // groupConcat (1426x) - 57937: 419, // jsonArrayagg (1426x) - 57938: 420, // jsonObjectAgg (1426x) - 57719: 421, // lastval (1426x) - 57939: 422, // leader (1426x) - 57941: 423, // learner (1426x) - 57945: 424, // max (1426x) - 57944: 425, // min (1426x) - 57745: 426, // names (1426x) - 57946: 427, // now (1426x) - 57951: 428, // position (1426x) - 57787: 429, // process (1426x) - 57791: 430, // proxy (1426x) - 57796: 431, // quick (1426x) - 57807: 432, // replicas (1426x) - 57808: 433, // replication (1426x) - 57815: 434, // reverse (1426x) - 57819: 435, // rowCount (1426x) - 57834: 436, // setval (1426x) - 57837: 437, // shared (1426x) - 57846: 438, // some (1426x) - 57848: 439, // sqlBufferResult (1426x) - 57849: 440, // sqlCache (1426x) - 57850: 441, // sqlNoCache (1426x) - 57959: 442, // staleness (1426x) - 57960: 443, // std (1426x) - 57961: 444, // stddev (1426x) - 57962: 445, // stddevPop (1426x) - 57963: 446, // stddevSamp (1426x) - 57966: 447, // strong (1426x) - 57967: 448, // subDate (1426x) - 57969: 449, // substring (1426x) - 57968: 450, // sum (1426x) - 57869: 451, // super (1426x) - 58020: 452, // telemetry (1426x) - 57971: 453, // timestampAdd (1426x) - 57972: 454, // timestampDiff (1426x) - 57983: 455, // trim (1426x) - 57984: 456, // variance (1426x) - 57985: 457, // varPop (1426x) - 57986: 458, // varSamp (1426x) - 57988: 459, // voter (1426x) - 57903: 460, // weightString (1426x) - 57488: 461, // on (1373x) - 40: 462, // '(' (1289x) - 57568: 463, // with (1189x) - 57349: 464, // stringLit (1173x) - 58077: 465, // not2 (1159x) - 57481: 466, // not (1104x) - 57398: 467, // defaultKwd (1089x) - 57364: 468, // as (1086x) - 57547: 469, // union (1054x) - 57379: 470, // collate (1039x) - 57553: 471, // using (1034x) - 57461: 472, // left (1021x) - 57515: 473, // right (1021x) - 45: 474, // '-' (990x) - 43: 475, // '+' (989x) - 57480: 476, // mod (970x) - 57435: 477, // ignore (945x) - 57496: 478, // partition (941x) - 57415: 479, // except (934x) - 57441: 480, // intersect (933x) - 57485: 481, // null (915x) - 57420: 482, // forKwd (907x) - 57463: 483, // limit (907x) - 57443: 484, // into (904x) - 58066: 485, // eq (901x) - 57469: 486, // lock (900x) - 57557: 487, // values (899x) - 57421: 488, // force (895x) - 57377: 489, // charType (891x) - 57423: 490, // from (891x) - 57417: 491, // fetch (890x) - 57565: 492, // where (889x) - 57493: 493, // order (886x) - 57511: 494, // replace (872x) - 57363: 495, // and (871x) - 58061: 496, // intLit (859x) - 57492: 497, // or (848x) - 57354: 498, // andand (847x) - 57779: 499, // pipesAsOr (847x) - 57569: 500, // xor (847x) - 57522: 501, // set (845x) - 57427: 502, // group (820x) - 57533: 503, // straightJoin (816x) - 57567: 504, // window (808x) - 57429: 505, // having (806x) - 57453: 506, // join (804x) - 57572: 507, // natural (794x) - 57384: 508, // cross (793x) - 57439: 509, // inner (793x) - 57462: 510, // like (792x) - 125: 511, // '}' (790x) - 42: 512, // '*' (785x) - 57518: 513, // rows (778x) - 57552: 514, // use (774x) - 57535: 515, // tableSample (768x) - 57501: 516, // rangeKwd (767x) - 57428: 517, // groups (766x) - 57402: 518, // desc (765x) - 57365: 519, // asc (763x) - 57393: 520, // dayHour (761x) - 57394: 521, // dayMicrosecond (761x) - 57395: 522, // dayMinute (761x) - 57396: 523, // daySecond (761x) - 57431: 524, // hourMicrosecond (761x) - 57432: 525, // hourMinute (761x) - 57433: 526, // hourSecond (761x) - 57478: 527, // minuteMicrosecond (761x) - 57479: 528, // minuteSecond (761x) - 57520: 529, // secondMicrosecond (761x) - 57570: 530, // yearMonth (761x) - 57564: 531, // when (760x) - 57368: 532, // binaryType (758x) - 57436: 533, // in (758x) - 57410: 534, // elseKwd (757x) - 57538: 535, // then (754x) - 60: 536, // '<' (747x) - 62: 537, // '>' (747x) - 58067: 538, // ge (747x) - 57445: 539, // is (747x) - 58068: 540, // le (747x) - 58072: 541, // neq (747x) - 58073: 542, // neqSynonym (747x) - 58074: 543, // nulleq (747x) - 57366: 544, // between (745x) - 47: 545, // '/' (744x) - 37: 546, // '%' (743x) - 38: 547, // '&' (743x) - 94: 548, // '^' (743x) - 124: 549, // '|' (743x) - 57406: 550, // div (743x) - 58071: 551, // lsh (743x) - 58076: 552, // rsh (743x) - 57507: 553, // regexpKwd (737x) - 57516: 554, // rlike (737x) - 57434: 555, // ifKwd (733x) - 57534: 556, // tableKwd (723x) - 57446: 557, // insert (715x) - 57350: 558, // singleAtIdentifier (715x) - 57389: 559, // currentUser (711x) - 57416: 560, // falseKwd (709x) - 57545: 561, // trueKwd (709x) - 58060: 562, // decLit (703x) - 58059: 563, // floatLit (703x) - 57517: 564, // row (702x) - 58062: 565, // hexLit (701x) - 57454: 566, // key (701x) - 58075: 567, // paramMarker (701x) - 123: 568, // '{' (699x) - 58063: 569, // bitLit (699x) - 57442: 570, // interval (698x) - 57355: 571, // pipes (695x) - 57391: 572, // database (694x) - 57413: 573, // exists (694x) - 57378: 574, // check (691x) - 57382: 575, // convert (691x) - 57499: 576, // primary (691x) - 57351: 577, // doubleAtIdentifier (690x) - 58046: 578, // builtinNow (689x) - 57388: 579, // currentTs (689x) - 57467: 580, // localTime (689x) - 57468: 581, // localTs (689x) - 57348: 582, // underscoreCS (689x) - 33: 583, // '!' (687x) - 126: 584, // '~' (687x) - 58030: 585, // builtinAddDate (687x) - 58036: 586, // builtinApproxCountDistinct (687x) - 58037: 587, // builtinApproxPercentile (687x) - 58031: 588, // builtinBitAnd (687x) - 58032: 589, // builtinBitOr (687x) - 58033: 590, // builtinBitXor (687x) - 58034: 591, // builtinCast (687x) - 58035: 592, // builtinCount (687x) - 58038: 593, // builtinCurDate (687x) - 58039: 594, // builtinCurTime (687x) - 58040: 595, // builtinDateAdd (687x) - 58041: 596, // builtinDateSub (687x) - 58042: 597, // builtinExtract (687x) - 58043: 598, // builtinGroupConcat (687x) - 58044: 599, // builtinMax (687x) - 58045: 600, // builtinMin (687x) - 58047: 601, // builtinPosition (687x) - 58052: 602, // builtinStddevPop (687x) - 58053: 603, // builtinStddevSamp (687x) - 58048: 604, // builtinSubDate (687x) - 58049: 605, // builtinSubstring (687x) - 58050: 606, // builtinSum (687x) - 58051: 607, // builtinSysDate (687x) - 58054: 608, // builtinTranslate (687x) - 58055: 609, // builtinTrim (687x) - 58056: 610, // builtinUser (687x) - 58057: 611, // builtinVarPop (687x) - 58058: 612, // builtinVarSamp (687x) - 57374: 613, // caseKwd (687x) - 57385: 614, // cumeDist (687x) - 57386: 615, // currentDate (687x) - 57390: 616, // currentRole (687x) - 57387: 617, // currentTime (687x) - 57401: 618, // denseRank (687x) - 57418: 619, // firstValue (687x) - 57457: 620, // lag (687x) - 57458: 621, // lastValue (687x) - 57459: 622, // lead (687x) - 57483: 623, // nthValue (687x) - 57484: 624, // ntile (687x) - 57497: 625, // percentRank (687x) - 57502: 626, // rank (687x) - 57510: 627, // repeat (687x) - 57519: 628, // rowNumber (687x) - 57554: 629, // utcDate (687x) - 57556: 630, // utcTime (687x) - 57555: 631, // utcTimestamp (687x) - 57546: 632, // unique (684x) - 57381: 633, // constraint (682x) - 57521: 634, // selectKwd (680x) - 57506: 635, // references (679x) - 57425: 636, // generated (675x) - 57376: 637, // character (665x) - 57437: 638, // index (647x) - 57473: 639, // match (637x) - 57542: 640, // to (556x) - 57360: 641, // all (543x) - 46: 642, // '.' (534x) - 57362: 643, // analyze (518x) - 57550: 644, // update (507x) - 58069: 645, // jss (502x) - 58070: 646, // juss (502x) - 57474: 647, // maxValue (500x) - 57464: 648, // lines (493x) - 57371: 649, // by (490x) - 58065: 650, // assignmentEq (488x) - 57512: 651, // require (485x) - 57361: 652, // alter (484x) - 58322: 653, // Identifier (483x) - 58397: 654, // NotKeywordToken (483x) - 58619: 655, // TiDBKeyword (483x) - 58629: 656, // UnReservedKeyword (483x) - 64: 657, // '@' (480x) - 57526: 658, // sql (477x) - 57408: 659, // drop (474x) - 57373: 660, // cascade (473x) - 57503: 661, // read (473x) - 57513: 662, // restrict (473x) - 57347: 663, // asof (471x) - 57383: 664, // create (469x) - 57422: 665, // foreign (469x) - 57424: 666, // fulltext (469x) - 57560: 667, // varcharacter (467x) - 57559: 668, // varcharType (467x) - 57375: 669, // change (466x) - 57397: 670, // decimalType (466x) - 57407: 671, // doubleType (466x) - 57419: 672, // floatType (466x) - 57440: 673, // integerType (466x) - 57447: 674, // intType (466x) - 57504: 675, // realType (466x) - 57509: 676, // rename (466x) - 57566: 677, // write (466x) - 57561: 678, // varbinaryType (465x) - 57359: 679, // add (464x) - 57367: 680, // bigIntType (464x) - 57369: 681, // blobType (464x) - 57448: 682, // int1Type (464x) - 57449: 683, // int2Type (464x) - 57450: 684, // int3Type (464x) - 57451: 685, // int4Type (464x) - 57452: 686, // int8Type (464x) - 57558: 687, // long (464x) - 57470: 688, // longblobType (464x) - 57471: 689, // longtextType (464x) - 57475: 690, // mediumblobType (464x) - 57476: 691, // mediumIntType (464x) - 57477: 692, // mediumtextType (464x) - 57486: 693, // numericType (464x) - 57489: 694, // optimize (464x) - 57524: 695, // smallIntType (464x) - 57539: 696, // tinyblobType (464x) - 57540: 697, // tinyIntType (464x) - 57541: 698, // tinytextType (464x) - 58584: 699, // SubSelect (209x) - 58638: 700, // UserVariable (171x) - 58559: 701, // SimpleIdent (170x) - 58374: 702, // Literal (168x) - 58574: 703, // StringLiteral (168x) - 58395: 704, // NextValueForSequence (167x) - 58299: 705, // FunctionCallGeneric (166x) - 58300: 706, // FunctionCallKeyword (166x) - 58301: 707, // FunctionCallNonKeyword (166x) - 58302: 708, // FunctionNameConflict (166x) - 58303: 709, // FunctionNameDateArith (166x) - 58304: 710, // FunctionNameDateArithMultiForms (166x) - 58305: 711, // FunctionNameDatetimePrecision (166x) - 58306: 712, // FunctionNameOptionalBraces (166x) - 58307: 713, // FunctionNameSequence (166x) - 58558: 714, // SimpleExpr (166x) - 58585: 715, // SumExpr (166x) - 58587: 716, // SystemVariable (166x) - 58649: 717, // Variable (166x) - 58672: 718, // WindowFuncCall (166x) - 58151: 719, // BitExpr (153x) - 58468: 720, // PredicateExpr (130x) - 58154: 721, // BoolPri (127x) - 58266: 722, // Expression (127x) - 58687: 723, // logAnd (96x) - 58688: 724, // logOr (96x) - 58393: 725, // NUM (96x) - 58256: 726, // EqOpt (86x) - 58597: 727, // TableName (75x) - 58575: 728, // StringName (56x) - 57549: 729, // unsigned (47x) - 57495: 730, // over (45x) - 57571: 731, // zerofill (45x) - 57400: 732, // deleteKwd (41x) - 58176: 733, // ColumnName (40x) - 58365: 734, // LengthNum (40x) - 57404: 735, // distinct (36x) - 57405: 736, // distinctRow (36x) - 58677: 737, // WindowingClause (35x) - 57399: 738, // delayed (33x) - 57430: 739, // highPriority (33x) - 57472: 740, // lowPriority (33x) - 58514: 741, // SelectStmt (30x) - 58515: 742, // SelectStmtBasic (30x) - 58517: 743, // SelectStmtFromDualTable (30x) - 58518: 744, // SelectStmtFromTable (30x) - 58534: 745, // SetOprClause (30x) - 58535: 746, // SetOprClauseList (29x) - 58538: 747, // SetOprStmtWithLimitOrderBy (29x) - 58539: 748, // SetOprStmtWoutLimitOrderBy (29x) - 57353: 749, // hintComment (27x) - 58277: 750, // FieldLen (26x) - 58354: 751, // Int64Num (26x) - 58527: 752, // SelectStmtWithClause (26x) - 58537: 753, // SetOprStmt (26x) - 58678: 754, // WithClause (26x) - 58434: 755, // OptWindowingClause (24x) - 58439: 756, // OrderBy (23x) - 58521: 757, // SelectStmtLimit (23x) - 57527: 758, // sqlBigResult (23x) - 57528: 759, // sqlCalcFoundRows (23x) - 57529: 760, // sqlSmallResult (23x) - 58233: 761, // DirectPlacementOption (21x) - 58164: 762, // CharsetKw (20x) - 58640: 763, // Username (20x) - 58632: 764, // UpdateStmtNoWith (18x) - 58232: 765, // DeleteWithoutUsingStmt (17x) - 58267: 766, // ExpressionList (17x) - 58463: 767, // PlacementPolicyOption (17x) - 58323: 768, // IfExists (16x) - 58351: 769, // InsertIntoStmt (16x) - 58461: 770, // PlacementOption (16x) - 58489: 771, // ReplaceIntoStmt (16x) + 57344: 0, // $end (2183x) + 59: 1, // ';' (2182x) + 57805: 2, // remove (1838x) + 57806: 3, // reorganize (1838x) + 57626: 4, // comment (1774x) + 57867: 5, // storage (1750x) + 57589: 6, // autoIncrement (1739x) + 44: 7, // ',' (1658x) + 57685: 8, // first (1638x) + 57576: 9, // after (1636x) + 57834: 10, // serial (1632x) + 57590: 11, // autoRandom (1631x) + 57623: 12, // columnFormat (1631x) + 57778: 13, // password (1600x) + 57614: 14, // charsetKwd (1598x) + 57616: 15, // checksum (1586x) + 57951: 16, // placement (1584x) + 57717: 17, // keyBlockSize (1568x) + 57879: 18, // tablespace (1565x) + 57665: 19, // encryption (1563x) + 57668: 20, // engine (1560x) + 57648: 21, // data (1558x) + 57708: 22, // insertMethod (1556x) + 57735: 23, // maxRows (1556x) + 57742: 24, // minRows (1556x) + 57757: 25, // nodegroup (1556x) + 57633: 26, // connection (1548x) + 57591: 27, // autoRandomBase (1545x) + 58019: 28, // statsBuckets (1543x) + 58021: 29, // statsTopN (1543x) + 57588: 30, // autoIdCache (1542x) + 57593: 31, // avgRowLength (1542x) + 57631: 32, // compression (1542x) + 57654: 33, // delayKeyWrite (1542x) + 57772: 34, // packKeys (1542x) + 57785: 35, // preSplitRegions (1542x) + 57823: 36, // rowFormat (1542x) + 57827: 37, // secondaryEngine (1542x) + 57838: 38, // shardRowIDBits (1542x) + 57863: 39, // statsAutoRecalc (1542x) + 57586: 40, // statsColChoice (1542x) + 57587: 41, // statsColList (1542x) + 57864: 42, // statsPersistent (1542x) + 57865: 43, // statsSamplePages (1542x) + 57585: 44, // statsSampleRate (1542x) + 57877: 45, // tableChecksum (1542x) + 57573: 46, // account (1489x) + 41: 47, // ')' (1486x) + 57817: 48, // resume (1479x) + 57842: 49, // signed (1479x) + 57848: 50, // snapshot (1478x) + 57594: 51, // backend (1477x) + 57615: 52, // checkpoint (1477x) + 57632: 53, // concurrency (1477x) + 57638: 54, // csvBackslashEscape (1477x) + 57639: 55, // csvDelimiter (1477x) + 57640: 56, // csvHeader (1477x) + 57641: 57, // csvNotNull (1477x) + 57642: 58, // csvNull (1477x) + 57643: 59, // csvSeparator (1477x) + 57644: 60, // csvTrimLastSeparators (1477x) + 57721: 61, // lastBackup (1477x) + 57767: 62, // onDuplicate (1477x) + 57768: 63, // online (1477x) + 57800: 64, // rateLimit (1477x) + 57831: 65, // sendCredentialsToTiKV (1477x) + 57845: 66, // skipSchemaFiles (1477x) + 57868: 67, // strictFormat (1477x) + 57884: 68, // tikvImporter (1477x) + 57892: 69, // truncate (1474x) + 57754: 70, // no (1473x) + 57862: 71, // start (1471x) + 57609: 72, // cache (1468x) + 57755: 73, // nocache (1467x) + 57647: 74, // cycle (1466x) + 57744: 75, // minValue (1466x) + 57705: 76, // increment (1465x) + 57756: 77, // nocycle (1465x) + 57758: 78, // nomaxvalue (1465x) + 57759: 79, // nominvalue (1465x) + 57814: 80, // restart (1463x) + 57579: 81, // algorithm (1462x) + 57887: 82, // tp (1462x) + 57646: 83, // clustered (1461x) + 57710: 84, // invisible (1461x) + 57760: 85, // nonclustered (1461x) + 58031: 86, // regions (1461x) + 57903: 87, // visible (1461x) + 57921: 88, // constraints (1454x) + 57932: 89, // followerConstraints (1454x) + 57933: 90, // followers (1454x) + 57943: 91, // leaderConstraints (1454x) + 57945: 92, // learnerConstraints (1454x) + 57946: 93, // learners (1454x) + 57956: 94, // primaryRegion (1454x) + 57961: 95, // schedule (1454x) + 57992: 96, // voterConstraints (1454x) + 57993: 97, // voters (1454x) + 57624: 98, // columns (1453x) + 57902: 99, // view (1453x) + 57870: 100, // subpartition (1449x) + 57582: 101, // ascii (1448x) + 57608: 102, // byteType (1448x) + 57777: 103, // partitions (1448x) + 57896: 104, // unicodeSym (1448x) + 57909: 105, // yearType (1448x) + 57651: 106, // day (1447x) + 57683: 107, // fields (1447x) + 57826: 108, // second (1446x) + 57861: 109, // sqlTsiYear (1446x) + 57878: 110, // tables (1446x) + 57700: 111, // hour (1445x) + 57741: 112, // microsecond (1445x) + 57743: 113, // minute (1445x) + 57747: 114, // month (1445x) + 57796: 115, // quarter (1445x) + 57854: 116, // sqlTsiDay (1445x) + 57855: 117, // sqlTsiHour (1445x) + 57856: 118, // sqlTsiMinute (1445x) + 57857: 119, // sqlTsiMonth (1445x) + 57858: 120, // sqlTsiQuarter (1445x) + 57859: 121, // sqlTsiSecond (1445x) + 57860: 122, // sqlTsiWeek (1445x) + 57866: 123, // status (1445x) + 57905: 124, // week (1445x) + 57832: 125, // separator (1444x) + 57733: 126, // maxConnectionsPerHour (1443x) + 57734: 127, // maxQueriesPerHour (1443x) + 57736: 128, // maxUpdatesPerHour (1443x) + 57737: 129, // maxUserConnections (1443x) + 57786: 130, // preceding (1443x) + 57617: 131, // cipher (1442x) + 57703: 132, // importKwd (1442x) + 57715: 133, // issuer (1442x) + 57825: 134, // san (1442x) + 57869: 135, // subject (1442x) + 57726: 136, // local (1441x) + 57844: 137, // skip (1441x) + 57601: 138, // bindings (1440x) + 57653: 139, // definer (1440x) + 57695: 140, // hash (1440x) + 57701: 141, // identified (1440x) + 57729: 142, // logs (1440x) + 57798: 143, // query (1440x) + 57813: 144, // respect (1440x) + 57627: 145, // commit (1439x) + 57645: 146, // current (1439x) + 57667: 147, // enforced (1439x) + 57688: 148, // following (1439x) + 57346: 149, // identifier (1439x) + 57762: 150, // nowait (1439x) + 57769: 151, // only (1439x) + 57820: 152, // rollback (1439x) + 57900: 153, // value (1439x) + 57597: 154, // begin (1438x) + 57599: 155, // binding (1438x) + 57666: 156, // end (1438x) + 57693: 157, // global (1438x) + 57936: 158, // next_row_id (1438x) + 57784: 159, // policy (1438x) + 57955: 160, // predicate (1438x) + 57880: 161, // temporary (1438x) + 57893: 162, // unbounded (1438x) + 57898: 163, // user (1438x) + 57766: 164, // offset (1437x) + 57953: 165, // planCache (1437x) + 57787: 166, // prepare (1437x) + 57819: 167, // role (1437x) + 57897: 168, // unknown (1437x) + 57910: 169, // wait (1437x) + 57607: 170, // btree (1436x) + 57649: 171, // datetimeType (1436x) + 57650: 172, // dateType (1436x) + 57686: 173, // fixed (1436x) + 57714: 174, // isolation (1436x) + 57716: 175, // jsonType (1436x) + 57728: 176, // location (1436x) + 57731: 177, // max_idxnum (1436x) + 57739: 178, // memory (1436x) + 57765: 179, // off (1436x) + 57771: 180, // optional (1436x) + 57780: 181, // per_db (1436x) + 57789: 182, // privileges (1436x) + 57812: 183, // required (1436x) + 57824: 184, // rtree (1436x) + 57959: 185, // running (1436x) + 58014: 186, // sampleRate (1436x) + 57833: 187, // sequence (1436x) + 57836: 188, // session (1436x) + 57847: 189, // slow (1436x) + 57886: 190, // timeType (1436x) + 57899: 191, // validation (1436x) + 57901: 192, // variables (1436x) + 57583: 193, // attributes (1435x) + 57656: 194, // disable (1435x) + 57661: 195, // duplicate (1435x) + 57662: 196, // dynamic (1435x) + 57663: 197, // enable (1435x) + 57671: 198, // errorKwd (1435x) + 57687: 199, // flush (1435x) + 57690: 200, // full (1435x) + 57702: 201, // identSQLErrors (1435x) + 57738: 202, // mb (1435x) + 57745: 203, // mode (1435x) + 57751: 204, // never (1435x) + 57952: 205, // plan (1435x) + 57783: 206, // plugins (1435x) + 57791: 207, // processlist (1435x) + 57802: 208, // recover (1435x) + 57807: 209, // repair (1435x) + 57808: 210, // repeatable (1435x) + 58015: 211, // statistics (1435x) + 57871: 212, // subpartitions (1435x) + 58025: 213, // tidb (1435x) + 57885: 214, // timestampType (1435x) + 57907: 215, // without (1435x) + 57994: 216, // admin (1434x) + 57595: 217, // backup (1434x) + 57602: 218, // binlog (1434x) + 57604: 219, // block (1434x) + 57605: 220, // booleanType (1434x) + 57995: 221, // buckets (1434x) + 57998: 222, // cardinality (1434x) + 57613: 223, // chain (1434x) + 57620: 224, // clientErrorsSummary (1434x) + 57999: 225, // cmSketch (1434x) + 57621: 226, // coalesce (1434x) + 57629: 227, // compact (1434x) + 57630: 228, // compressed (1434x) + 57636: 229, // context (1434x) + 57920: 230, // copyKwd (1434x) + 58001: 231, // correlation (1434x) + 57637: 232, // cpu (1434x) + 57652: 233, // deallocate (1434x) + 58003: 234, // dependency (1434x) + 57655: 235, // directory (1434x) + 57658: 236, // discard (1434x) + 57659: 237, // disk (1434x) + 57660: 238, // do (1434x) + 58005: 239, // drainer (1434x) + 57676: 240, // exchange (1434x) + 57678: 241, // execute (1434x) + 57679: 242, // expansion (1434x) + 57930: 243, // flashback (1434x) + 57692: 244, // general (1434x) + 57696: 245, // help (1434x) + 57697: 246, // histogram (1434x) + 57699: 247, // hosts (1434x) + 57937: 248, // inplace (1434x) + 57709: 249, // instance (1434x) + 57938: 250, // instant (1434x) + 57713: 251, // ipc (1434x) + 58007: 252, // job (1434x) + 58006: 253, // jobs (1434x) + 57718: 254, // labels (1434x) + 57727: 255, // locked (1434x) + 57746: 256, // modify (1434x) + 57752: 257, // next (1434x) + 58008: 258, // nodeID (1434x) + 58009: 259, // nodeState (1434x) + 57764: 260, // nulls (1434x) + 57773: 261, // pageSym (1434x) + 58012: 262, // pump (1434x) + 57795: 263, // purge (1434x) + 57801: 264, // rebuild (1434x) + 57803: 265, // redundant (1434x) + 57804: 266, // reload (1434x) + 57809: 267, // replica (1434x) + 57815: 268, // restore (1434x) + 57821: 269, // routine (1434x) + 57960: 270, // s3 (1434x) + 58013: 271, // samples (1434x) + 57828: 272, // secondaryLoad (1434x) + 57829: 273, // secondaryUnload (1434x) + 57839: 274, // share (1434x) + 57841: 275, // shutdown (1434x) + 57850: 276, // source (1434x) + 58028: 277, // split (1434x) + 58016: 278, // stats (1434x) + 57584: 279, // statsOptions (1434x) + 57967: 280, // stop (1434x) + 57873: 281, // swaps (1434x) + 58026: 282, // tiFlash (1434x) + 57977: 283, // tokudbDefault (1434x) + 57978: 284, // tokudbFast (1434x) + 57979: 285, // tokudbLzma (1434x) + 57980: 286, // tokudbQuickLZ (1434x) + 57982: 287, // tokudbSmall (1434x) + 57981: 288, // tokudbSnappy (1434x) + 57983: 289, // tokudbUncompressed (1434x) + 57984: 290, // tokudbZlib (1434x) + 58027: 291, // topn (1434x) + 57888: 292, // trace (1434x) + 57574: 293, // action (1433x) + 57575: 294, // advise (1433x) + 57577: 295, // against (1433x) + 57578: 296, // ago (1433x) + 57580: 297, // always (1433x) + 57596: 298, // backups (1433x) + 57598: 299, // bernoulli (1433x) + 57600: 300, // bindingCache (1433x) + 57603: 301, // bitType (1433x) + 57606: 302, // boolType (1433x) + 57918: 303, // briefType (1433x) + 57996: 304, // builtins (1433x) + 57997: 305, // cancel (1433x) + 57610: 306, // capture (1433x) + 57611: 307, // cascaded (1433x) + 57612: 308, // causal (1433x) + 57618: 309, // cleanup (1433x) + 57619: 310, // client (1433x) + 57622: 311, // collation (1433x) + 58000: 312, // columnStatsUsage (1433x) + 57628: 313, // committed (1433x) + 57625: 314, // config (1433x) + 57634: 315, // consistency (1433x) + 57635: 316, // consistent (1433x) + 58002: 317, // ddl (1433x) + 58004: 318, // depth (1433x) + 57657: 319, // disabled (1433x) + 57925: 320, // dotType (1433x) + 57926: 321, // dump (1433x) + 57664: 322, // enabled (1433x) + 57669: 323, // engines (1433x) + 57670: 324, // enum (1433x) + 57674: 325, // events (1433x) + 57675: 326, // evolve (1433x) + 57680: 327, // expire (1433x) + 57928: 328, // exprPushdownBlacklist (1433x) + 57681: 329, // extended (1433x) + 57682: 330, // faultsSym (1433x) + 57689: 331, // format (1433x) + 57691: 332, // function (1433x) + 57694: 333, // grants (1433x) + 58022: 334, // histogramsInFlight (1433x) + 57698: 335, // history (1433x) + 57704: 336, // imports (1433x) + 57706: 337, // incremental (1433x) + 57707: 338, // indexes (1433x) + 57939: 339, // internal (1433x) + 57711: 340, // invoker (1433x) + 57712: 341, // io (1433x) + 57719: 342, // language (1433x) + 57720: 343, // last (1433x) + 57723: 344, // less (1433x) + 57724: 345, // level (1433x) + 57725: 346, // list (1433x) + 57730: 347, // master (1433x) + 57732: 348, // max_minutes (1433x) + 57740: 349, // merge (1433x) + 57749: 350, // national (1433x) + 57750: 351, // ncharType (1433x) + 57753: 352, // nextval (1433x) + 57761: 353, // none (1433x) + 57763: 354, // nvarcharType (1433x) + 57770: 355, // open (1433x) + 58010: 356, // optimistic (1433x) + 57950: 357, // optRuleBlacklist (1433x) + 57774: 358, // parser (1433x) + 57775: 359, // partial (1433x) + 57776: 360, // partitioning (1433x) + 57781: 361, // per_table (1433x) + 57779: 362, // percent (1433x) + 58011: 363, // pessimistic (1433x) + 57788: 364, // preserve (1433x) + 57792: 365, // profile (1433x) + 57793: 366, // profiles (1433x) + 57797: 367, // queries (1433x) + 57957: 368, // recent (1433x) + 58032: 369, // region (1433x) + 57958: 370, // replayer (1433x) + 58030: 371, // reset (1433x) + 57816: 372, // restores (1433x) + 57830: 373, // security (1433x) + 57835: 374, // serializable (1433x) + 57843: 375, // simple (1433x) + 57846: 376, // slave (1433x) + 58020: 377, // statsHealthy (1433x) + 58018: 378, // statsHistograms (1433x) + 58017: 379, // statsMeta (1433x) + 57968: 380, // strict (1433x) + 57874: 381, // switchesSym (1433x) + 57875: 382, // system (1433x) + 57876: 383, // systemTime (1433x) + 57973: 384, // target (1433x) + 58024: 385, // telemetryID (1433x) + 57881: 386, // temptable (1433x) + 57882: 387, // textType (1433x) + 57883: 388, // than (1433x) + 57976: 389, // tls (1433x) + 57985: 390, // top (1433x) + 57889: 391, // traditional (1433x) + 57890: 392, // transaction (1433x) + 57891: 393, // triggers (1433x) + 57894: 394, // uncommitted (1433x) + 57895: 395, // undefined (1433x) + 57990: 396, // verboseType (1433x) + 57904: 397, // warnings (1433x) + 58029: 398, // width (1433x) + 57908: 399, // x509 (1433x) + 57911: 400, // addDate (1432x) + 57581: 401, // any (1432x) + 57912: 402, // approxCountDistinct (1432x) + 57913: 403, // approxPercentile (1432x) + 57592: 404, // avg (1432x) + 57914: 405, // bitAnd (1432x) + 57915: 406, // bitOr (1432x) + 57916: 407, // bitXor (1432x) + 57917: 408, // bound (1432x) + 57919: 409, // cast (1432x) + 57922: 410, // curTime (1432x) + 57923: 411, // dateAdd (1432x) + 57924: 412, // dateSub (1432x) + 57672: 413, // escape (1432x) + 57673: 414, // event (1432x) + 57927: 415, // exact (1432x) + 57677: 416, // exclusive (1432x) + 57929: 417, // extract (1432x) + 57684: 418, // file (1432x) + 57931: 419, // follower (1432x) + 57934: 420, // getFormat (1432x) + 57935: 421, // groupConcat (1432x) + 57940: 422, // jsonArrayagg (1432x) + 57941: 423, // jsonObjectAgg (1432x) + 57722: 424, // lastval (1432x) + 57942: 425, // leader (1432x) + 57944: 426, // learner (1432x) + 57948: 427, // max (1432x) + 57947: 428, // min (1432x) + 57748: 429, // names (1432x) + 57949: 430, // now (1432x) + 57954: 431, // position (1432x) + 57790: 432, // process (1432x) + 57794: 433, // proxy (1432x) + 57799: 434, // quick (1432x) + 57810: 435, // replicas (1432x) + 57811: 436, // replication (1432x) + 57818: 437, // reverse (1432x) + 57822: 438, // rowCount (1432x) + 57837: 439, // setval (1432x) + 57840: 440, // shared (1432x) + 57849: 441, // some (1432x) + 57851: 442, // sqlBufferResult (1432x) + 57852: 443, // sqlCache (1432x) + 57853: 444, // sqlNoCache (1432x) + 57962: 445, // staleness (1432x) + 57963: 446, // std (1432x) + 57964: 447, // stddev (1432x) + 57965: 448, // stddevPop (1432x) + 57966: 449, // stddevSamp (1432x) + 57969: 450, // strong (1432x) + 57970: 451, // subDate (1432x) + 57972: 452, // substring (1432x) + 57971: 453, // sum (1432x) + 57872: 454, // super (1432x) + 58023: 455, // telemetry (1432x) + 57974: 456, // timestampAdd (1432x) + 57975: 457, // timestampDiff (1432x) + 57986: 458, // trim (1432x) + 57987: 459, // variance (1432x) + 57988: 460, // varPop (1432x) + 57989: 461, // varSamp (1432x) + 57991: 462, // voter (1432x) + 57906: 463, // weightString (1432x) + 57488: 464, // on (1371x) + 40: 465, // '(' (1285x) + 57568: 466, // with (1183x) + 58078: 467, // not2 (1171x) + 57349: 468, // stringLit (1171x) + 57481: 469, // not (1116x) + 57364: 470, // as (1084x) + 57398: 471, // defaultKwd (1080x) + 57547: 472, // union (1046x) + 57553: 473, // using (1040x) + 57379: 474, // collate (1031x) + 57461: 475, // left (1027x) + 57515: 476, // right (1027x) + 45: 477, // '-' (996x) + 43: 478, // '+' (995x) + 57480: 479, // mod (976x) + 57415: 480, // except (939x) + 57441: 481, // intersect (938x) + 57435: 482, // ignore (937x) + 57496: 483, // partition (937x) + 57485: 484, // null (925x) + 57420: 485, // forKwd (915x) + 57463: 486, // limit (912x) + 57443: 487, // into (909x) + 57469: 488, // lock (905x) + 58067: 489, // eq (896x) + 57423: 490, // from (896x) + 57417: 491, // fetch (895x) + 57565: 492, // where (895x) + 57557: 493, // values (892x) + 57493: 494, // order (891x) + 57421: 495, // force (887x) + 57522: 496, // set (879x) + 57363: 497, // and (876x) + 57377: 498, // charType (876x) + 57511: 499, // replace (865x) + 58062: 500, // intLit (861x) + 57492: 501, // or (853x) + 57354: 502, // andand (852x) + 57782: 503, // pipesAsOr (852x) + 57569: 504, // xor (852x) + 57427: 505, // group (825x) + 57533: 506, // straightJoin (821x) + 57567: 507, // window (813x) + 57429: 508, // having (811x) + 57453: 509, // join (809x) + 57572: 510, // natural (799x) + 57384: 511, // cross (798x) + 57439: 512, // inner (798x) + 57462: 513, // like (798x) + 125: 514, // '}' (795x) + 42: 515, // '*' (790x) + 57518: 516, // rows (783x) + 57552: 517, // use (779x) + 57535: 518, // tableSample (773x) + 57501: 519, // rangeKwd (772x) + 57428: 520, // groups (771x) + 57402: 521, // desc (770x) + 57365: 522, // asc (768x) + 57393: 523, // dayHour (766x) + 57394: 524, // dayMicrosecond (766x) + 57395: 525, // dayMinute (766x) + 57396: 526, // daySecond (766x) + 57431: 527, // hourMicrosecond (766x) + 57432: 528, // hourMinute (766x) + 57433: 529, // hourSecond (766x) + 57478: 530, // minuteMicrosecond (766x) + 57479: 531, // minuteSecond (766x) + 57520: 532, // secondMicrosecond (766x) + 57570: 533, // yearMonth (766x) + 57564: 534, // when (765x) + 57436: 535, // in (763x) + 57368: 536, // binaryType (762x) + 57410: 537, // elseKwd (762x) + 57538: 538, // then (759x) + 60: 539, // '<' (752x) + 62: 540, // '>' (752x) + 58068: 541, // ge (752x) + 57445: 542, // is (752x) + 58069: 543, // le (752x) + 58073: 544, // neq (752x) + 58074: 545, // neqSynonym (752x) + 58075: 546, // nulleq (752x) + 57366: 547, // between (750x) + 47: 548, // '/' (749x) + 37: 549, // '%' (748x) + 38: 550, // '&' (748x) + 94: 551, // '^' (748x) + 124: 552, // '|' (748x) + 57406: 553, // div (748x) + 58072: 554, // lsh (748x) + 58077: 555, // rsh (748x) + 57507: 556, // regexpKwd (742x) + 57516: 557, // rlike (742x) + 57434: 558, // ifKwd (737x) + 57446: 559, // insert (721x) + 57350: 560, // singleAtIdentifier (719x) + 57389: 561, // currentUser (715x) + 57534: 562, // tableKwd (715x) + 57416: 563, // falseKwd (713x) + 57545: 564, // trueKwd (713x) + 57454: 565, // key (710x) + 58061: 566, // decLit (707x) + 58060: 567, // floatLit (707x) + 57517: 568, // row (706x) + 58063: 569, // hexLit (705x) + 58076: 570, // paramMarker (705x) + 123: 571, // '{' (703x) + 58064: 572, // bitLit (703x) + 57442: 573, // interval (702x) + 57378: 574, // check (700x) + 57355: 575, // pipes (700x) + 57499: 576, // primary (700x) + 57391: 577, // database (698x) + 57413: 578, // exists (698x) + 57382: 579, // convert (695x) + 58048: 580, // builtinNow (694x) + 57388: 581, // currentTs (694x) + 57351: 582, // doubleAtIdentifier (694x) + 57467: 583, // localTime (694x) + 57468: 584, // localTs (694x) + 57348: 585, // underscoreCS (693x) + 57546: 586, // unique (693x) + 33: 587, // '!' (691x) + 126: 588, // '~' (691x) + 58038: 589, // builtinApproxCountDistinct (691x) + 58039: 590, // builtinApproxPercentile (691x) + 58033: 591, // builtinBitAnd (691x) + 58034: 592, // builtinBitOr (691x) + 58035: 593, // builtinBitXor (691x) + 58036: 594, // builtinCast (691x) + 58037: 595, // builtinCount (691x) + 58040: 596, // builtinCurDate (691x) + 58041: 597, // builtinCurTime (691x) + 58042: 598, // builtinDateAdd (691x) + 58043: 599, // builtinDateSub (691x) + 58044: 600, // builtinExtract (691x) + 58045: 601, // builtinGroupConcat (691x) + 58046: 602, // builtinMax (691x) + 58047: 603, // builtinMin (691x) + 58049: 604, // builtinPosition (691x) + 58053: 605, // builtinStddevPop (691x) + 58054: 606, // builtinStddevSamp (691x) + 58050: 607, // builtinSubstring (691x) + 58051: 608, // builtinSum (691x) + 58052: 609, // builtinSysDate (691x) + 58055: 610, // builtinTranslate (691x) + 58056: 611, // builtinTrim (691x) + 58057: 612, // builtinUser (691x) + 58058: 613, // builtinVarPop (691x) + 58059: 614, // builtinVarSamp (691x) + 57374: 615, // caseKwd (691x) + 57381: 616, // constraint (691x) + 57385: 617, // cumeDist (691x) + 57386: 618, // currentDate (691x) + 57390: 619, // currentRole (691x) + 57387: 620, // currentTime (691x) + 57401: 621, // denseRank (691x) + 57418: 622, // firstValue (691x) + 57457: 623, // lag (691x) + 57458: 624, // lastValue (691x) + 57459: 625, // lead (691x) + 57483: 626, // nthValue (691x) + 57484: 627, // ntile (691x) + 57497: 628, // percentRank (691x) + 57502: 629, // rank (691x) + 57510: 630, // repeat (691x) + 57519: 631, // rowNumber (691x) + 57554: 632, // utcDate (691x) + 57556: 633, // utcTime (691x) + 57555: 634, // utcTimestamp (691x) + 57506: 635, // references (688x) + 57425: 636, // generated (684x) + 57521: 637, // selectKwd (672x) + 57376: 638, // character (649x) + 57473: 639, // match (641x) + 57437: 640, // index (637x) + 57542: 641, // to (559x) + 57360: 642, // all (546x) + 46: 643, // '.' (540x) + 57362: 644, // analyze (521x) + 57550: 645, // update (512x) + 58070: 646, // jss (507x) + 58071: 647, // juss (507x) + 57474: 648, // maxValue (503x) + 57464: 649, // lines (496x) + 57371: 650, // by (493x) + 58066: 651, // assignmentEq (492x) + 57512: 652, // require (488x) + 57361: 653, // alter (487x) + 58325: 654, // Identifier (484x) + 58400: 655, // NotKeywordToken (484x) + 58623: 656, // TiDBKeyword (484x) + 58633: 657, // UnReservedKeyword (484x) + 64: 658, // '@' (483x) + 57526: 659, // sql (480x) + 57408: 660, // drop (477x) + 57373: 661, // cascade (476x) + 57503: 662, // read (476x) + 57513: 663, // restrict (476x) + 57347: 664, // asof (474x) + 57383: 665, // create (472x) + 57422: 666, // foreign (472x) + 57424: 667, // fulltext (472x) + 57560: 668, // varcharacter (470x) + 57559: 669, // varcharType (470x) + 57375: 670, // change (469x) + 57397: 671, // decimalType (469x) + 57407: 672, // doubleType (469x) + 57419: 673, // floatType (469x) + 57440: 674, // integerType (469x) + 57447: 675, // intType (469x) + 57504: 676, // realType (469x) + 57509: 677, // rename (469x) + 57566: 678, // write (469x) + 57561: 679, // varbinaryType (468x) + 57359: 680, // add (467x) + 57367: 681, // bigIntType (467x) + 57369: 682, // blobType (467x) + 57448: 683, // int1Type (467x) + 57449: 684, // int2Type (467x) + 57450: 685, // int3Type (467x) + 57451: 686, // int4Type (467x) + 57452: 687, // int8Type (467x) + 57558: 688, // long (467x) + 57470: 689, // longblobType (467x) + 57471: 690, // longtextType (467x) + 57475: 691, // mediumblobType (467x) + 57476: 692, // mediumIntType (467x) + 57477: 693, // mediumtextType (467x) + 57486: 694, // numericType (467x) + 57489: 695, // optimize (467x) + 57524: 696, // smallIntType (467x) + 57539: 697, // tinyblobType (467x) + 57540: 698, // tinyIntType (467x) + 57541: 699, // tinytextType (467x) + 58588: 700, // SubSelect (212x) + 58642: 701, // UserVariable (172x) + 58563: 702, // SimpleIdent (171x) + 58377: 703, // Literal (169x) + 58578: 704, // StringLiteral (169x) + 58398: 705, // NextValueForSequence (168x) + 58302: 706, // FunctionCallGeneric (167x) + 58303: 707, // FunctionCallKeyword (167x) + 58304: 708, // FunctionCallNonKeyword (167x) + 58305: 709, // FunctionNameConflict (167x) + 58306: 710, // FunctionNameDateArith (167x) + 58307: 711, // FunctionNameDateArithMultiForms (167x) + 58308: 712, // FunctionNameDatetimePrecision (167x) + 58309: 713, // FunctionNameOptionalBraces (167x) + 58310: 714, // FunctionNameSequence (167x) + 58562: 715, // SimpleExpr (167x) + 58589: 716, // SumExpr (167x) + 58591: 717, // SystemVariable (167x) + 58653: 718, // Variable (167x) + 58676: 719, // WindowFuncCall (167x) + 58153: 720, // BitExpr (154x) + 58471: 721, // PredicateExpr (131x) + 58156: 722, // BoolPri (128x) + 58269: 723, // Expression (128x) + 58396: 724, // NUM (97x) + 58691: 725, // logAnd (96x) + 58692: 726, // logOr (96x) + 58259: 727, // EqOpt (75x) + 58601: 728, // TableName (75x) + 58579: 729, // StringName (56x) + 57549: 730, // unsigned (47x) + 57495: 731, // over (45x) + 57571: 732, // zerofill (45x) + 57400: 733, // deleteKwd (43x) + 58368: 734, // LengthNum (41x) + 58179: 735, // ColumnName (40x) + 57404: 736, // distinct (36x) + 57405: 737, // distinctRow (36x) + 58681: 738, // WindowingClause (35x) + 57399: 739, // delayed (33x) + 57430: 740, // highPriority (33x) + 57472: 741, // lowPriority (33x) + 58517: 742, // SelectStmt (32x) + 58518: 743, // SelectStmtBasic (32x) + 58520: 744, // SelectStmtFromDualTable (32x) + 58521: 745, // SelectStmtFromTable (32x) + 58538: 746, // SetOprClause (32x) + 58539: 747, // SetOprClauseList (31x) + 58542: 748, // SetOprStmtWithLimitOrderBy (31x) + 58543: 749, // SetOprStmtWoutLimitOrderBy (31x) + 58530: 750, // SelectStmtWithClause (28x) + 58541: 751, // SetOprStmt (28x) + 58682: 752, // WithClause (28x) + 57353: 753, // hintComment (27x) + 58280: 754, // FieldLen (26x) + 58357: 755, // Int64Num (26x) + 58438: 756, // OptWindowingClause (24x) + 58443: 757, // OrderBy (23x) + 58524: 758, // SelectStmtLimit (23x) + 57527: 759, // sqlBigResult (23x) + 57528: 760, // sqlCalcFoundRows (23x) + 57529: 761, // sqlSmallResult (23x) + 58167: 762, // CharsetKw (20x) + 58636: 763, // UpdateStmtNoWith (20x) + 58644: 764, // Username (20x) + 58235: 765, // DeleteWithoutUsingStmt (19x) + 58270: 766, // ExpressionList (18x) + 58354: 767, // InsertIntoStmt (18x) + 58492: 768, // ReplaceIntoStmt (18x) + 58635: 769, // UpdateStmt (18x) + 58466: 770, // PlacementPolicyOption (17x) + 58326: 771, // IfExists (16x) 57537: 772, // terminated (16x) - 58631: 773, // UpdateStmt (16x) - 58234: 774, // DistinctKwd (15x) - 58324: 775, // IfNotExists (15x) - 58419: 776, // OptFieldLen (15x) - 58235: 777, // DistinctOpt (14x) - 57411: 778, // enclosed (14x) - 58450: 779, // PartitionNameList (14x) - 58662: 780, // WhereClause (14x) - 58663: 781, // WhereClauseOptional (14x) - 58227: 782, // DefaultKwdOpt (13x) - 58231: 783, // DeleteWithUsingStmt (13x) - 57412: 784, // escaped (13x) - 57491: 785, // optionally (13x) - 58598: 786, // TableNameList (13x) - 58230: 787, // DeleteFromStmt (12x) - 58265: 788, // ExprOrDefault (12x) - 58359: 789, // JoinTable (12x) - 58413: 790, // OptBinary (12x) - 58505: 791, // RolenameComposed (12x) - 58594: 792, // TableFactor (12x) - 58607: 793, // TableRef (12x) - 58126: 794, // AnalyzeOptionListOpt (11x) - 58294: 795, // FromOrIn (11x) - 58621: 796, // TimestampUnit (11x) - 58165: 797, // CharsetName (10x) - 58177: 798, // ColumnNameList (10x) - 57466: 799, // load (10x) - 58398: 800, // NotSym (10x) - 58440: 801, // OrderByOptional (10x) - 58442: 802, // PartDefOption (10x) - 58557: 803, // SignedNum (10x) - 58157: 804, // BuggyDefaultFalseDistinctOpt (9x) - 58217: 805, // DBName (9x) - 58226: 806, // DefaultFalseDistinctOpt (9x) - 58360: 807, // JoinType (9x) - 57482: 808, // noWriteToBinLog (9x) - 58403: 809, // NumLiteral (9x) - 58504: 810, // Rolename (9x) - 58499: 811, // RoleNameString (9x) - 58122: 812, // AlterTableStmt (8x) - 58216: 813, // CrossOpt (8x) - 58257: 814, // EqOrAssignmentEq (8x) - 58268: 815, // ExpressionListOpt (8x) - 58345: 816, // IndexPartSpecification (8x) - 58361: 817, // KeyOrIndex (8x) - 58522: 818, // SelectStmtLimitOpt (8x) - 58620: 819, // TimeUnit (8x) - 58652: 820, // VariableName (8x) - 58108: 821, // AllOrPartitionNameList (7x) - 58200: 822, // ConstraintKeywordOpt (7x) - 58283: 823, // FieldsOrColumns (7x) - 58292: 824, // ForceOpt (7x) - 58346: 825, // IndexPartSpecificationList (7x) - 58396: 826, // NoWriteToBinLogAliasOpt (7x) - 58472: 827, // Priority (7x) - 58509: 828, // RowFormat (7x) - 58512: 829, // RowValue (7x) - 58532: 830, // SetExpr (7x) - 58543: 831, // ShowDatabaseNameOpt (7x) - 58604: 832, // TableOption (7x) - 57562: 833, // varying (7x) - 58147: 834, // BeginTransactionStmt (6x) + 58237: 773, // DistinctKwd (15x) + 58327: 774, // IfNotExists (15x) + 58423: 775, // OptFieldLen (15x) + 58238: 776, // DistinctOpt (14x) + 57411: 777, // enclosed (14x) + 58454: 778, // PartitionNameList (14x) + 58666: 779, // WhereClause (14x) + 58667: 780, // WhereClauseOptional (14x) + 58230: 781, // DefaultKwdOpt (13x) + 58234: 782, // DeleteWithUsingStmt (13x) + 57412: 783, // escaped (13x) + 57491: 784, // optionally (13x) + 58602: 785, // TableNameList (13x) + 58233: 786, // DeleteFromStmt (12x) + 58268: 787, // ExprOrDefault (12x) + 58362: 788, // JoinTable (12x) + 58417: 789, // OptBinary (12x) + 58508: 790, // RolenameComposed (12x) + 58598: 791, // TableFactor (12x) + 58611: 792, // TableRef (12x) + 58127: 793, // AnalyzeOptionListOpt (11x) + 58297: 794, // FromOrIn (11x) + 58625: 795, // TimestampUnit (11x) + 58168: 796, // CharsetName (10x) + 58180: 797, // ColumnNameList (10x) + 57466: 798, // load (10x) + 58401: 799, // NotSym (10x) + 58444: 800, // OrderByOptional (10x) + 58446: 801, // PartDefOption (10x) + 58561: 802, // SignedNum (10x) + 58159: 803, // BuggyDefaultFalseDistinctOpt (9x) + 58220: 804, // DBName (9x) + 58229: 805, // DefaultFalseDistinctOpt (9x) + 58363: 806, // JoinType (9x) + 57482: 807, // noWriteToBinLog (9x) + 58407: 808, // NumLiteral (9x) + 58507: 809, // Rolename (9x) + 58502: 810, // RoleNameString (9x) + 58123: 811, // AlterTableStmt (8x) + 58219: 812, // CrossOpt (8x) + 58260: 813, // EqOrAssignmentEq (8x) + 58271: 814, // ExpressionListOpt (8x) + 58348: 815, // IndexPartSpecification (8x) + 58364: 816, // KeyOrIndex (8x) + 58525: 817, // SelectStmtLimitOpt (8x) + 58624: 818, // TimeUnit (8x) + 58656: 819, // VariableName (8x) + 58109: 820, // AllOrPartitionNameList (7x) + 58203: 821, // ConstraintKeywordOpt (7x) + 58286: 822, // FieldsOrColumns (7x) + 58295: 823, // ForceOpt (7x) + 58349: 824, // IndexPartSpecificationList (7x) + 58399: 825, // NoWriteToBinLogAliasOpt (7x) + 58475: 826, // Priority (7x) + 58512: 827, // RowFormat (7x) + 58515: 828, // RowValue (7x) + 58536: 829, // SetExpr (7x) + 58547: 830, // ShowDatabaseNameOpt (7x) + 58608: 831, // TableOption (7x) + 57562: 832, // varying (7x) + 58148: 833, // BeginTransactionStmt (6x) + 58150: 834, // BindableStmt (6x) 57380: 835, // column (6x) - 58171: 836, // ColumnDef (6x) - 58190: 837, // CommitStmt (6x) - 58219: 838, // DatabaseOption (6x) - 58222: 839, // DatabaseSym (6x) - 58259: 840, // EscapedTableRef (6x) - 58264: 841, // ExplainableStmt (6x) - 58281: 842, // FieldTerminator (6x) + 58174: 836, // ColumnDef (6x) + 58193: 837, // CommitStmt (6x) + 58222: 838, // DatabaseOption (6x) + 58225: 839, // DatabaseSym (6x) + 58262: 840, // EscapedTableRef (6x) + 58267: 841, // ExplainableStmt (6x) + 58284: 842, // FieldTerminator (6x) 57426: 843, // grant (6x) - 58328: 844, // IgnoreOptional (6x) - 58337: 845, // IndexInvisible (6x) - 58342: 846, // IndexNameList (6x) - 58348: 847, // IndexType (6x) - 58378: 848, // LoadDataStmt (6x) - 58451: 849, // PartitionNameListOpt (6x) + 58331: 844, // IgnoreOptional (6x) + 58340: 845, // IndexInvisible (6x) + 58345: 846, // IndexNameList (6x) + 58351: 847, // IndexType (6x) + 58381: 848, // LoadDataStmt (6x) + 58455: 849, // PartitionNameListOpt (6x) 57508: 850, // release (6x) - 58506: 851, // RolenameList (6x) - 58508: 852, // RollbackStmt (6x) - 58542: 853, // SetStmt (6x) + 58509: 851, // RolenameList (6x) + 58511: 852, // RollbackStmt (6x) + 58546: 853, // SetStmt (6x) 57523: 854, // show (6x) - 58602: 855, // TableOptimizerHints (6x) - 58641: 856, // UsernameList (6x) - 58679: 857, // WithClustered (6x) - 58106: 858, // AlgorithmClause (5x) - 58158: 859, // ByItem (5x) - 58170: 860, // CollationName (5x) - 58174: 861, // ColumnKeywordOpt (5x) - 58279: 862, // FieldOpt (5x) - 58280: 863, // FieldOpts (5x) - 58320: 864, // IdentList (5x) - 58340: 865, // IndexName (5x) - 58343: 866, // IndexOption (5x) - 58344: 867, // IndexOptionList (5x) - 57438: 868, // infile (5x) - 58370: 869, // LimitOption (5x) - 58382: 870, // LockClause (5x) - 58415: 871, // OptCharsetWithOptBinary (5x) - 58426: 872, // OptNullTreatment (5x) - 58466: 873, // PolicyName (5x) - 58473: 874, // PriorityOpt (5x) - 58513: 875, // SelectLockOpt (5x) - 58520: 876, // SelectStmtIntoOption (5x) - 58608: 877, // TableRefs (5x) - 58634: 878, // UserSpec (5x) - 58132: 879, // Assignment (4x) - 58138: 880, // AuthString (4x) - 58149: 881, // BindableStmt (4x) - 58139: 882, // BRIEBooleanOptionName (4x) - 58140: 883, // BRIEIntegerOptionName (4x) - 58141: 884, // BRIEKeywordOptionName (4x) - 58142: 885, // BRIEOption (4x) - 58143: 886, // BRIEOptions (4x) - 58145: 887, // BRIEStringOptionName (4x) - 58159: 888, // ByList (4x) - 58163: 889, // Char (4x) - 58194: 890, // ConfigItemName (4x) - 58198: 891, // Constraint (4x) - 58288: 892, // FloatOpt (4x) - 58349: 893, // IndexTypeName (4x) + 58606: 855, // TableOptimizerHints (6x) + 58645: 856, // UsernameList (6x) + 58683: 857, // WithClustered (6x) + 58107: 858, // AlgorithmClause (5x) + 58161: 859, // ByItem (5x) + 58173: 860, // CollationName (5x) + 58177: 861, // ColumnKeywordOpt (5x) + 58236: 862, // DirectPlacementOption (5x) + 58282: 863, // FieldOpt (5x) + 58283: 864, // FieldOpts (5x) + 58323: 865, // IdentList (5x) + 58343: 866, // IndexName (5x) + 58346: 867, // IndexOption (5x) + 58347: 868, // IndexOptionList (5x) + 57438: 869, // infile (5x) + 58373: 870, // LimitOption (5x) + 58385: 871, // LockClause (5x) + 58419: 872, // OptCharsetWithOptBinary (5x) + 58430: 873, // OptNullTreatment (5x) + 58469: 874, // PolicyName (5x) + 58476: 875, // PriorityOpt (5x) + 58516: 876, // SelectLockOpt (5x) + 58523: 877, // SelectStmtIntoOption (5x) + 58612: 878, // TableRefs (5x) + 58638: 879, // UserSpec (5x) + 58133: 880, // Assignment (4x) + 58139: 881, // AuthString (4x) + 58140: 882, // BRIEBooleanOptionName (4x) + 58141: 883, // BRIEIntegerOptionName (4x) + 58142: 884, // BRIEKeywordOptionName (4x) + 58143: 885, // BRIEOption (4x) + 58144: 886, // BRIEOptions (4x) + 58146: 887, // BRIEStringOptionName (4x) + 58162: 888, // ByList (4x) + 58166: 889, // Char (4x) + 58197: 890, // ConfigItemName (4x) + 58201: 891, // Constraint (4x) + 58291: 892, // FloatOpt (4x) + 58352: 893, // IndexTypeName (4x) 57490: 894, // option (4x) - 58431: 895, // OptWild (4x) + 58435: 895, // OptWild (4x) 57494: 896, // outer (4x) - 58467: 897, // Precision (4x) - 58481: 898, // ReferDef (4x) - 58495: 899, // RestrictOrCascadeOpt (4x) - 58511: 900, // RowStmt (4x) - 58528: 901, // SequenceOption (4x) + 58470: 897, // Precision (4x) + 58484: 898, // ReferDef (4x) + 58498: 899, // RestrictOrCascadeOpt (4x) + 58514: 900, // RowStmt (4x) + 58531: 901, // SequenceOption (4x) 57532: 902, // statsExtended (4x) - 58589: 903, // TableAsName (4x) - 58590: 904, // TableAsNameOpt (4x) - 58601: 905, // TableNameOptWild (4x) - 58603: 906, // TableOptimizerHintsOpt (4x) - 58605: 907, // TableOptionList (4x) - 58623: 908, // TraceableStmt (4x) - 58624: 909, // TransactionChar (4x) - 58635: 910, // UserSpecList (4x) - 58673: 911, // WindowName (4x) - 58129: 912, // AsOfClause (3x) - 58133: 913, // AssignmentList (3x) - 58135: 914, // AttributesOpt (3x) - 58155: 915, // Boolean (3x) - 58183: 916, // ColumnOption (3x) - 58186: 917, // ColumnPosition (3x) - 58191: 918, // CommonTableExpr (3x) - 58212: 919, // CreateTableStmt (3x) - 58220: 920, // DatabaseOptionList (3x) - 58228: 921, // DefaultTrueDistinctOpt (3x) - 58253: 922, // EnforcedOrNot (3x) + 58593: 903, // TableAsName (4x) + 58594: 904, // TableAsNameOpt (4x) + 58605: 905, // TableNameOptWild (4x) + 58607: 906, // TableOptimizerHintsOpt (4x) + 58609: 907, // TableOptionList (4x) + 58627: 908, // TraceableStmt (4x) + 58628: 909, // TransactionChar (4x) + 58639: 910, // UserSpecList (4x) + 58677: 911, // WindowName (4x) + 58130: 912, // AsOfClause (3x) + 58134: 913, // AssignmentList (3x) + 58136: 914, // AttributesOpt (3x) + 58157: 915, // Boolean (3x) + 58186: 916, // ColumnOption (3x) + 58189: 917, // ColumnPosition (3x) + 58194: 918, // CommonTableExpr (3x) + 58215: 919, // CreateTableStmt (3x) + 58223: 920, // DatabaseOptionList (3x) + 58231: 921, // DefaultTrueDistinctOpt (3x) + 58256: 922, // EnforcedOrNot (3x) 57414: 923, // explain (3x) - 58270: 924, // ExtendedPriv (3x) - 58308: 925, // GeneratedAlways (3x) - 58310: 926, // GlobalScope (3x) - 58314: 927, // GroupByClause (3x) - 58332: 928, // IndexHint (3x) - 58336: 929, // IndexHintType (3x) - 58341: 930, // IndexNameAndTypeOpt (3x) + 58273: 924, // ExtendedPriv (3x) + 58311: 925, // GeneratedAlways (3x) + 58313: 926, // GlobalScope (3x) + 58317: 927, // GroupByClause (3x) + 58335: 928, // IndexHint (3x) + 58339: 929, // IndexHintType (3x) + 58344: 930, // IndexNameAndTypeOpt (3x) 57455: 931, // keys (3x) - 58372: 932, // Lines (3x) - 58390: 933, // MaxValueOrExpression (3x) - 58427: 934, // OptOrder (3x) - 58430: 935, // OptTemporary (3x) - 58443: 936, // PartDefOptionList (3x) - 58445: 937, // PartitionDefinition (3x) - 58454: 938, // PasswordExpire (3x) - 58456: 939, // PasswordOrLockOption (3x) - 58465: 940, // PluginNameList (3x) - 58471: 941, // PrimaryOpt (3x) - 58474: 942, // PrivElem (3x) - 58476: 943, // PrivType (3x) - 57500: 944, // procedure (3x) - 58490: 945, // RequireClause (3x) - 58491: 946, // RequireClauseOpt (3x) - 58493: 947, // RequireListElement (3x) - 58507: 948, // RolenameWithoutIdent (3x) - 58500: 949, // RoleOrPrivElem (3x) - 58519: 950, // SelectStmtGroup (3x) - 58536: 951, // SetOprOpt (3x) - 58588: 952, // TableAliasRefList (3x) - 58591: 953, // TableElement (3x) - 58600: 954, // TableNameListOpt2 (3x) - 58616: 955, // TextString (3x) - 58625: 956, // TransactionChars (3x) - 57544: 957, // trigger (3x) - 57548: 958, // unlock (3x) - 57551: 959, // usage (3x) - 58645: 960, // ValuesList (3x) - 58647: 961, // ValuesStmtList (3x) - 58643: 962, // ValueSym (3x) - 58650: 963, // VariableAssignment (3x) - 58670: 964, // WindowFrameStart (3x) - 58105: 965, // AdminStmt (2x) - 58107: 966, // AllColumnsOrPredicateColumnsOpt (2x) - 58109: 967, // AlterDatabaseStmt (2x) - 58110: 968, // AlterImportStmt (2x) - 58111: 969, // AlterInstanceStmt (2x) - 58112: 970, // AlterOrderItem (2x) - 58114: 971, // AlterPolicyStmt (2x) - 58115: 972, // AlterSequenceOption (2x) - 58117: 973, // AlterSequenceStmt (2x) - 58119: 974, // AlterTableSpec (2x) - 58123: 975, // AlterUserStmt (2x) - 58124: 976, // AnalyzeOption (2x) - 58127: 977, // AnalyzeTableStmt (2x) - 58150: 978, // BinlogStmt (2x) - 58144: 979, // BRIEStmt (2x) - 58146: 980, // BRIETables (2x) - 57372: 981, // call (2x) - 58160: 982, // CallStmt (2x) - 58161: 983, // CastType (2x) - 58162: 984, // ChangeStmt (2x) - 58168: 985, // CheckConstraintKeyword (2x) - 58178: 986, // ColumnNameListOpt (2x) - 58181: 987, // ColumnNameOrUserVariable (2x) - 58184: 988, // ColumnOptionList (2x) - 58185: 989, // ColumnOptionListOpt (2x) - 58187: 990, // ColumnSetValue (2x) - 58193: 991, // CompletionTypeWithinTransaction (2x) - 58195: 992, // ConnectionOption (2x) - 58197: 993, // ConnectionOptions (2x) - 58201: 994, // CreateBindingStmt (2x) - 58202: 995, // CreateDatabaseStmt (2x) - 58203: 996, // CreateImportStmt (2x) - 58204: 997, // CreateIndexStmt (2x) - 58205: 998, // CreatePolicyStmt (2x) - 58206: 999, // CreateRoleStmt (2x) - 58208: 1000, // CreateSequenceStmt (2x) - 58209: 1001, // CreateStatisticsStmt (2x) - 58210: 1002, // CreateTableOptionListOpt (2x) - 58213: 1003, // CreateUserStmt (2x) - 58215: 1004, // CreateViewStmt (2x) - 57392: 1005, // databases (2x) - 58224: 1006, // DeallocateStmt (2x) - 58225: 1007, // DeallocateSym (2x) - 57403: 1008, // describe (2x) - 58236: 1009, // DoStmt (2x) - 58237: 1010, // DropBindingStmt (2x) - 58238: 1011, // DropDatabaseStmt (2x) - 58239: 1012, // DropImportStmt (2x) - 58240: 1013, // DropIndexStmt (2x) - 58241: 1014, // DropPolicyStmt (2x) - 58242: 1015, // DropRoleStmt (2x) - 58243: 1016, // DropSequenceStmt (2x) - 58244: 1017, // DropStatisticsStmt (2x) - 58245: 1018, // DropStatsStmt (2x) - 58246: 1019, // DropTableStmt (2x) - 58247: 1020, // DropUserStmt (2x) - 58248: 1021, // DropViewStmt (2x) - 58249: 1022, // DuplicateOpt (2x) - 58251: 1023, // EmptyStmt (2x) - 58252: 1024, // EncryptionOpt (2x) - 58254: 1025, // EnforcedOrNotOpt (2x) - 58258: 1026, // ErrorHandling (2x) - 58260: 1027, // ExecuteStmt (2x) - 58262: 1028, // ExplainStmt (2x) - 58263: 1029, // ExplainSym (2x) - 58272: 1030, // Field (2x) - 58275: 1031, // FieldItem (2x) - 58282: 1032, // Fields (2x) - 58286: 1033, // FlashbackTableStmt (2x) - 58291: 1034, // FlushStmt (2x) - 58297: 1035, // FuncDatetimePrecList (2x) - 58298: 1036, // FuncDatetimePrecListOpt (2x) - 58311: 1037, // GrantProxyStmt (2x) - 58312: 1038, // GrantRoleStmt (2x) - 58313: 1039, // GrantStmt (2x) - 58315: 1040, // HandleRange (2x) - 58317: 1041, // HashString (2x) - 58319: 1042, // HelpStmt (2x) - 58331: 1043, // IndexAdviseStmt (2x) - 58333: 1044, // IndexHintList (2x) - 58334: 1045, // IndexHintListOpt (2x) - 58339: 1046, // IndexLockAndAlgorithmOpt (2x) - 58352: 1047, // InsertValues (2x) - 58356: 1048, // IntoOpt (2x) - 58362: 1049, // KeyOrIndexOpt (2x) - 57456: 1050, // kill (2x) - 58363: 1051, // KillOrKillTiDB (2x) - 58364: 1052, // KillStmt (2x) - 58369: 1053, // LimitClause (2x) - 57465: 1054, // linear (2x) - 58371: 1055, // LinearOpt (2x) - 58375: 1056, // LoadDataSetItem (2x) - 58379: 1057, // LoadStatsStmt (2x) - 58380: 1058, // LocalOpt (2x) - 58383: 1059, // LockTablesStmt (2x) - 58391: 1060, // MaxValueOrExpressionList (2x) - 58399: 1061, // NowSym (2x) - 58400: 1062, // NowSymFunc (2x) - 58401: 1063, // NowSymOptionFraction (2x) - 58402: 1064, // NumList (2x) - 58405: 1065, // ObjectType (2x) - 57487: 1066, // of (2x) - 58406: 1067, // OfTablesOpt (2x) - 58407: 1068, // OnCommitOpt (2x) - 58408: 1069, // OnDelete (2x) - 58411: 1070, // OnUpdate (2x) - 58416: 1071, // OptCollate (2x) - 58421: 1072, // OptFull (2x) - 58423: 1073, // OptInteger (2x) - 58436: 1074, // OptionalBraces (2x) - 58435: 1075, // OptionLevel (2x) - 58425: 1076, // OptLeadLagInfo (2x) - 58424: 1077, // OptLLDefault (2x) - 58441: 1078, // OuterOpt (2x) - 58446: 1079, // PartitionDefinitionList (2x) - 58447: 1080, // PartitionDefinitionListOpt (2x) - 58453: 1081, // PartitionOpt (2x) - 58455: 1082, // PasswordOpt (2x) - 58457: 1083, // PasswordOrLockOptionList (2x) - 58458: 1084, // PasswordOrLockOptions (2x) - 58462: 1085, // PlacementOptionList (2x) - 58464: 1086, // PlanReplayerStmt (2x) - 58470: 1087, // PreparedStmt (2x) - 58475: 1088, // PrivLevel (2x) - 58478: 1089, // PurgeImportStmt (2x) - 58479: 1090, // QuickOptional (2x) - 58480: 1091, // RecoverTableStmt (2x) - 58482: 1092, // ReferOpt (2x) - 58484: 1093, // RegexpSym (2x) - 58485: 1094, // RenameTableStmt (2x) - 58486: 1095, // RenameUserStmt (2x) - 58488: 1096, // RepeatableOpt (2x) - 58494: 1097, // RestartStmt (2x) - 58496: 1098, // ResumeImportStmt (2x) - 57514: 1099, // revoke (2x) - 58497: 1100, // RevokeRoleStmt (2x) - 58498: 1101, // RevokeStmt (2x) - 58501: 1102, // RoleOrPrivElemList (2x) - 58502: 1103, // RoleSpec (2x) - 58523: 1104, // SelectStmtOpt (2x) - 58526: 1105, // SelectStmtSQLCache (2x) - 58530: 1106, // SetDefaultRoleOpt (2x) - 58531: 1107, // SetDefaultRoleStmt (2x) - 58541: 1108, // SetRoleStmt (2x) - 58544: 1109, // ShowImportStmt (2x) - 58549: 1110, // ShowProfileType (2x) - 58552: 1111, // ShowStmt (2x) - 58553: 1112, // ShowTableAliasOpt (2x) - 58555: 1113, // ShutdownStmt (2x) - 58556: 1114, // SignedLiteral (2x) - 58560: 1115, // SplitOption (2x) - 58561: 1116, // SplitRegionStmt (2x) - 58565: 1117, // Statement (2x) - 58568: 1118, // StatsOptionsOpt (2x) - 58569: 1119, // StatsPersistentVal (2x) - 58570: 1120, // StatsType (2x) - 58571: 1121, // StopImportStmt (2x) - 58578: 1122, // SubPartDefinition (2x) - 58581: 1123, // SubPartitionMethod (2x) - 58586: 1124, // Symbol (2x) - 58592: 1125, // TableElementList (2x) - 58595: 1126, // TableLock (2x) - 58599: 1127, // TableNameListOpt (2x) - 58606: 1128, // TableOrTables (2x) - 58615: 1129, // TablesTerminalSym (2x) - 58613: 1130, // TableToTable (2x) - 58617: 1131, // TextStringList (2x) - 58622: 1132, // TraceStmt (2x) - 58627: 1133, // TruncateTableStmt (2x) - 58630: 1134, // UnlockTablesStmt (2x) - 58636: 1135, // UserToUser (2x) - 58633: 1136, // UseStmt (2x) - 58648: 1137, // Varchar (2x) - 58651: 1138, // VariableAssignmentList (2x) - 58660: 1139, // WhenClause (2x) - 58665: 1140, // WindowDefinition (2x) - 58668: 1141, // WindowFrameBound (2x) - 58675: 1142, // WindowSpec (2x) - 58680: 1143, // WithGrantOptionOpt (2x) - 58681: 1144, // WithList (2x) - 58685: 1145, // Writeable (2x) - 58104: 1146, // AdminShowSlow (1x) - 58113: 1147, // AlterOrderList (1x) - 58116: 1148, // AlterSequenceOptionList (1x) - 58118: 1149, // AlterTablePartitionOpt (1x) - 58120: 1150, // AlterTableSpecList (1x) - 58121: 1151, // AlterTableSpecListOpt (1x) - 58125: 1152, // AnalyzeOptionList (1x) - 58128: 1153, // AnyOrAll (1x) - 58130: 1154, // AsOfClauseOpt (1x) - 58131: 1155, // AsOpt (1x) - 58136: 1156, // AuthOption (1x) - 58137: 1157, // AuthPlugin (1x) - 58148: 1158, // BetweenOrNotOp (1x) - 58152: 1159, // BitValueType (1x) - 58153: 1160, // BlobType (1x) - 58156: 1161, // BooleanType (1x) - 57370: 1162, // both (1x) - 58166: 1163, // CharsetNameOrDefault (1x) - 58167: 1164, // CharsetOpt (1x) - 58169: 1165, // ClearPasswordExpireOptions (1x) - 58173: 1166, // ColumnFormat (1x) - 58175: 1167, // ColumnList (1x) - 58182: 1168, // ColumnNameOrUserVariableList (1x) - 58179: 1169, // ColumnNameOrUserVarListOpt (1x) - 58180: 1170, // ColumnNameOrUserVarListOptWithBrackets (1x) - 58188: 1171, // ColumnSetValueList (1x) - 58192: 1172, // CompareOp (1x) - 58196: 1173, // ConnectionOptionList (1x) - 58199: 1174, // ConstraintElem (1x) - 58207: 1175, // CreateSequenceOptionListOpt (1x) - 58211: 1176, // CreateTableSelectOpt (1x) - 58214: 1177, // CreateViewSelectOpt (1x) - 58221: 1178, // DatabaseOptionListOpt (1x) - 58223: 1179, // DateAndTimeType (1x) - 58218: 1180, // DBNameList (1x) - 58229: 1181, // DefaultValueExpr (1x) - 57409: 1182, // dual (1x) - 58250: 1183, // ElseOpt (1x) - 58255: 1184, // EnforcedOrNotOrNotNullOpt (1x) - 58261: 1185, // ExplainFormatType (1x) - 58269: 1186, // ExpressionOpt (1x) - 58271: 1187, // FetchFirstOpt (1x) - 58273: 1188, // FieldAsName (1x) - 58274: 1189, // FieldAsNameOpt (1x) - 58276: 1190, // FieldItemList (1x) - 58278: 1191, // FieldList (1x) - 58284: 1192, // FirstOrNext (1x) - 58285: 1193, // FixedPointType (1x) - 58287: 1194, // FlashbackToNewName (1x) - 58289: 1195, // FloatingPointType (1x) - 58290: 1196, // FlushOption (1x) - 58293: 1197, // FromDual (1x) - 58295: 1198, // FulltextSearchModifierOpt (1x) - 58296: 1199, // FuncDatetimePrec (1x) - 58309: 1200, // GetFormatSelector (1x) - 58316: 1201, // HandleRangeList (1x) - 58318: 1202, // HavingClause (1x) - 58321: 1203, // IdentListWithParenOpt (1x) - 58325: 1204, // IfNotRunning (1x) - 58326: 1205, // IfRunning (1x) - 58327: 1206, // IgnoreLines (1x) - 58329: 1207, // ImportTruncate (1x) - 58335: 1208, // IndexHintScope (1x) - 58338: 1209, // IndexKeyTypeOpt (1x) - 58347: 1210, // IndexPartSpecificationListOpt (1x) - 58350: 1211, // IndexTypeOpt (1x) - 58330: 1212, // InOrNotOp (1x) - 58353: 1213, // InstanceOption (1x) - 58355: 1214, // IntegerType (1x) - 58358: 1215, // IsolationLevel (1x) - 58357: 1216, // IsOrNotOp (1x) - 57460: 1217, // leading (1x) - 58366: 1218, // LikeEscapeOpt (1x) - 58367: 1219, // LikeOrNotOp (1x) - 58368: 1220, // LikeTableWithOrWithoutParen (1x) - 58373: 1221, // LinesTerminated (1x) - 58376: 1222, // LoadDataSetList (1x) - 58377: 1223, // LoadDataSetSpecOpt (1x) - 58381: 1224, // LocationLabelList (1x) - 58384: 1225, // LockType (1x) - 58385: 1226, // LogTypeOpt (1x) - 58386: 1227, // Match (1x) - 58387: 1228, // MatchOpt (1x) - 58388: 1229, // MaxIndexNumOpt (1x) - 58389: 1230, // MaxMinutesOpt (1x) - 58392: 1231, // NChar (1x) - 58404: 1232, // NumericType (1x) - 58394: 1233, // NVarchar (1x) - 58409: 1234, // OnDeleteUpdateOpt (1x) - 58410: 1235, // OnDuplicateKeyUpdate (1x) - 58412: 1236, // OptBinMod (1x) - 58414: 1237, // OptCharset (1x) - 58417: 1238, // OptErrors (1x) - 58418: 1239, // OptExistingWindowName (1x) - 58420: 1240, // OptFromFirstLast (1x) - 58422: 1241, // OptGConcatSeparator (1x) - 58428: 1242, // OptPartitionClause (1x) - 58429: 1243, // OptTable (1x) - 58432: 1244, // OptWindowFrameClause (1x) - 58433: 1245, // OptWindowOrderByClause (1x) - 58438: 1246, // Order (1x) - 58437: 1247, // OrReplace (1x) - 57444: 1248, // outfile (1x) - 58444: 1249, // PartDefValuesOpt (1x) - 58448: 1250, // PartitionKeyAlgorithmOpt (1x) - 58449: 1251, // PartitionMethod (1x) - 58452: 1252, // PartitionNumOpt (1x) - 58459: 1253, // PerDB (1x) - 58460: 1254, // PerTable (1x) - 57498: 1255, // precisionType (1x) - 58469: 1256, // PrepareSQL (1x) - 58477: 1257, // ProcedureCall (1x) - 57505: 1258, // recursive (1x) - 58483: 1259, // RegexpOrNotOp (1x) - 58487: 1260, // ReorganizePartitionRuleOpt (1x) - 58492: 1261, // RequireList (1x) - 58503: 1262, // RoleSpecList (1x) - 58510: 1263, // RowOrRows (1x) - 58516: 1264, // SelectStmtFieldList (1x) - 58524: 1265, // SelectStmtOpts (1x) - 58525: 1266, // SelectStmtOptsList (1x) - 58529: 1267, // SequenceOptionList (1x) - 58533: 1268, // SetOpr (1x) - 58540: 1269, // SetRoleOpt (1x) - 58545: 1270, // ShowIndexKwd (1x) - 58546: 1271, // ShowLikeOrWhereOpt (1x) - 58547: 1272, // ShowPlacementTarget (1x) - 58548: 1273, // ShowProfileArgsOpt (1x) - 58550: 1274, // ShowProfileTypes (1x) - 58551: 1275, // ShowProfileTypesOpt (1x) - 58554: 1276, // ShowTargetFilterable (1x) - 57525: 1277, // spatial (1x) - 58562: 1278, // SplitSyntaxOption (1x) - 57530: 1279, // ssl (1x) - 58563: 1280, // Start (1x) - 58564: 1281, // Starting (1x) - 57531: 1282, // starting (1x) - 58566: 1283, // StatementList (1x) - 58567: 1284, // StatementScope (1x) - 58572: 1285, // StorageMedia (1x) - 57536: 1286, // stored (1x) - 58573: 1287, // StringList (1x) - 58576: 1288, // StringNameOrBRIEOptionKeyword (1x) - 58577: 1289, // StringType (1x) - 58579: 1290, // SubPartDefinitionList (1x) - 58580: 1291, // SubPartDefinitionListOpt (1x) - 58582: 1292, // SubPartitionNumOpt (1x) - 58583: 1293, // SubPartitionOpt (1x) - 58593: 1294, // TableElementListOpt (1x) - 58596: 1295, // TableLockList (1x) - 58609: 1296, // TableRefsClause (1x) - 58610: 1297, // TableSampleMethodOpt (1x) - 58611: 1298, // TableSampleOpt (1x) - 58612: 1299, // TableSampleUnitOpt (1x) - 58614: 1300, // TableToTableList (1x) - 58618: 1301, // TextType (1x) - 57543: 1302, // trailing (1x) - 58626: 1303, // TrimDirection (1x) - 58628: 1304, // Type (1x) - 58637: 1305, // UserToUserList (1x) - 58639: 1306, // UserVariableList (1x) - 58642: 1307, // UsingRoles (1x) - 58644: 1308, // Values (1x) - 58646: 1309, // ValuesOpt (1x) - 58653: 1310, // ViewAlgorithm (1x) - 58654: 1311, // ViewCheckOption (1x) - 58655: 1312, // ViewDefiner (1x) - 58656: 1313, // ViewFieldList (1x) - 58657: 1314, // ViewName (1x) - 58658: 1315, // ViewSQLSecurity (1x) - 57563: 1316, // virtual (1x) - 58659: 1317, // VirtualOrStored (1x) - 58661: 1318, // WhenClauseList (1x) - 58664: 1319, // WindowClauseOptional (1x) - 58666: 1320, // WindowDefinitionList (1x) - 58667: 1321, // WindowFrameBetween (1x) - 58669: 1322, // WindowFrameExtent (1x) - 58671: 1323, // WindowFrameUnits (1x) - 58674: 1324, // WindowNameOrSpec (1x) - 58676: 1325, // WindowSpecDetails (1x) - 58682: 1326, // WithReadLockOpt (1x) - 58683: 1327, // WithValidation (1x) - 58684: 1328, // WithValidationOpt (1x) - 58686: 1329, // Year (1x) - 58103: 1330, // $default (0x) - 58064: 1331, // andnot (0x) - 58134: 1332, // AssignmentListOpt (0x) - 58172: 1333, // ColumnDefList (0x) - 58189: 1334, // CommaOpt (0x) - 58087: 1335, // createTableSelect (0x) - 58078: 1336, // empty (0x) - 57345: 1337, // error (0x) - 58102: 1338, // higherThanComma (0x) - 58096: 1339, // higherThanParenthese (0x) - 58085: 1340, // insertValues (0x) - 57352: 1341, // invalid (0x) - 58088: 1342, // lowerThanCharsetKwd (0x) - 58101: 1343, // lowerThanComma (0x) - 58086: 1344, // lowerThanCreateTableSelect (0x) - 58098: 1345, // lowerThanEq (0x) - 58093: 1346, // lowerThanFunction (0x) - 58084: 1347, // lowerThanInsertValues (0x) - 58089: 1348, // lowerThanKey (0x) - 58090: 1349, // lowerThanLocal (0x) - 58100: 1350, // lowerThanNot (0x) - 58097: 1351, // lowerThanOn (0x) - 58095: 1352, // lowerThanParenthese (0x) - 58091: 1353, // lowerThanRemove (0x) - 58079: 1354, // lowerThanSelectOpt (0x) - 58083: 1355, // lowerThanSelectStmt (0x) - 58082: 1356, // lowerThanSetKeyword (0x) - 58081: 1357, // lowerThanStringLitToken (0x) - 58080: 1358, // lowerThanValueKeyword (0x) - 58092: 1359, // lowerThenOrder (0x) - 58099: 1360, // neg (0x) - 57356: 1361, // odbcDateType (0x) - 57358: 1362, // odbcTimestampType (0x) - 57357: 1363, // odbcTimeType (0x) - 58094: 1364, // tableRefPriority (0x) + 58375: 932, // Lines (3x) + 58393: 933, // MaxValueOrExpression (3x) + 58402: 934, // NowSym (3x) + 58403: 935, // NowSymFunc (3x) + 58404: 936, // NowSymOptionFraction (3x) + 58431: 937, // OptOrder (3x) + 58434: 938, // OptTemporary (3x) + 58447: 939, // PartDefOptionList (3x) + 58449: 940, // PartitionDefinition (3x) + 58458: 941, // PasswordExpire (3x) + 58460: 942, // PasswordOrLockOption (3x) + 58468: 943, // PluginNameList (3x) + 58474: 944, // PrimaryOpt (3x) + 58477: 945, // PrivElem (3x) + 58479: 946, // PrivType (3x) + 57500: 947, // procedure (3x) + 58493: 948, // RequireClause (3x) + 58494: 949, // RequireClauseOpt (3x) + 58496: 950, // RequireListElement (3x) + 58510: 951, // RolenameWithoutIdent (3x) + 58503: 952, // RoleOrPrivElem (3x) + 58522: 953, // SelectStmtGroup (3x) + 58540: 954, // SetOprOpt (3x) + 58592: 955, // TableAliasRefList (3x) + 58595: 956, // TableElement (3x) + 58604: 957, // TableNameListOpt2 (3x) + 58620: 958, // TextString (3x) + 58629: 959, // TransactionChars (3x) + 57544: 960, // trigger (3x) + 57548: 961, // unlock (3x) + 57551: 962, // usage (3x) + 58649: 963, // ValuesList (3x) + 58651: 964, // ValuesStmtList (3x) + 58647: 965, // ValueSym (3x) + 58654: 966, // VariableAssignment (3x) + 58674: 967, // WindowFrameStart (3x) + 58106: 968, // AdminStmt (2x) + 58108: 969, // AllColumnsOrPredicateColumnsOpt (2x) + 58110: 970, // AlterDatabaseStmt (2x) + 58111: 971, // AlterImportStmt (2x) + 58112: 972, // AlterInstanceStmt (2x) + 58113: 973, // AlterOrderItem (2x) + 58115: 974, // AlterPolicyStmt (2x) + 58116: 975, // AlterSequenceOption (2x) + 58118: 976, // AlterSequenceStmt (2x) + 58120: 977, // AlterTableSpec (2x) + 58124: 978, // AlterUserStmt (2x) + 58125: 979, // AnalyzeOption (2x) + 58128: 980, // AnalyzeTableStmt (2x) + 58152: 981, // BinlogStmt (2x) + 58145: 982, // BRIEStmt (2x) + 58147: 983, // BRIETables (2x) + 58160: 984, // BuiltinFunction (2x) + 57372: 985, // call (2x) + 58163: 986, // CallStmt (2x) + 58164: 987, // CastType (2x) + 58165: 988, // ChangeStmt (2x) + 58171: 989, // CheckConstraintKeyword (2x) + 58181: 990, // ColumnNameListOpt (2x) + 58184: 991, // ColumnNameOrUserVariable (2x) + 58187: 992, // ColumnOptionList (2x) + 58188: 993, // ColumnOptionListOpt (2x) + 58190: 994, // ColumnSetValue (2x) + 58196: 995, // CompletionTypeWithinTransaction (2x) + 58198: 996, // ConnectionOption (2x) + 58200: 997, // ConnectionOptions (2x) + 58204: 998, // CreateBindingStmt (2x) + 58205: 999, // CreateDatabaseStmt (2x) + 58206: 1000, // CreateImportStmt (2x) + 58207: 1001, // CreateIndexStmt (2x) + 58208: 1002, // CreatePolicyStmt (2x) + 58209: 1003, // CreateRoleStmt (2x) + 58211: 1004, // CreateSequenceStmt (2x) + 58212: 1005, // CreateStatisticsStmt (2x) + 58213: 1006, // CreateTableOptionListOpt (2x) + 58216: 1007, // CreateUserStmt (2x) + 58218: 1008, // CreateViewStmt (2x) + 57392: 1009, // databases (2x) + 58227: 1010, // DeallocateStmt (2x) + 58228: 1011, // DeallocateSym (2x) + 57403: 1012, // describe (2x) + 58239: 1013, // DoStmt (2x) + 58240: 1014, // DropBindingStmt (2x) + 58241: 1015, // DropDatabaseStmt (2x) + 58242: 1016, // DropImportStmt (2x) + 58243: 1017, // DropIndexStmt (2x) + 58244: 1018, // DropPolicyStmt (2x) + 58245: 1019, // DropRoleStmt (2x) + 58246: 1020, // DropSequenceStmt (2x) + 58247: 1021, // DropStatisticsStmt (2x) + 58248: 1022, // DropStatsStmt (2x) + 58249: 1023, // DropTableStmt (2x) + 58250: 1024, // DropUserStmt (2x) + 58251: 1025, // DropViewStmt (2x) + 58252: 1026, // DuplicateOpt (2x) + 58254: 1027, // EmptyStmt (2x) + 58255: 1028, // EncryptionOpt (2x) + 58257: 1029, // EnforcedOrNotOpt (2x) + 58261: 1030, // ErrorHandling (2x) + 58263: 1031, // ExecuteStmt (2x) + 58265: 1032, // ExplainStmt (2x) + 58266: 1033, // ExplainSym (2x) + 58275: 1034, // Field (2x) + 58278: 1035, // FieldItem (2x) + 58285: 1036, // Fields (2x) + 58289: 1037, // FlashbackTableStmt (2x) + 58294: 1038, // FlushStmt (2x) + 58300: 1039, // FuncDatetimePrecList (2x) + 58301: 1040, // FuncDatetimePrecListOpt (2x) + 58314: 1041, // GrantProxyStmt (2x) + 58315: 1042, // GrantRoleStmt (2x) + 58316: 1043, // GrantStmt (2x) + 58318: 1044, // HandleRange (2x) + 58320: 1045, // HashString (2x) + 58322: 1046, // HelpStmt (2x) + 58334: 1047, // IndexAdviseStmt (2x) + 58336: 1048, // IndexHintList (2x) + 58337: 1049, // IndexHintListOpt (2x) + 58342: 1050, // IndexLockAndAlgorithmOpt (2x) + 58355: 1051, // InsertValues (2x) + 58359: 1052, // IntoOpt (2x) + 58365: 1053, // KeyOrIndexOpt (2x) + 57456: 1054, // kill (2x) + 58366: 1055, // KillOrKillTiDB (2x) + 58367: 1056, // KillStmt (2x) + 58372: 1057, // LimitClause (2x) + 57465: 1058, // linear (2x) + 58374: 1059, // LinearOpt (2x) + 58378: 1060, // LoadDataSetItem (2x) + 58382: 1061, // LoadStatsStmt (2x) + 58383: 1062, // LocalOpt (2x) + 58384: 1063, // LocationLabelList (2x) + 58386: 1064, // LockTablesStmt (2x) + 58394: 1065, // MaxValueOrExpressionList (2x) + 58405: 1066, // NowSymOptionFractionParentheses (2x) + 58406: 1067, // NumList (2x) + 58409: 1068, // ObjectType (2x) + 57487: 1069, // of (2x) + 58410: 1070, // OfTablesOpt (2x) + 58411: 1071, // OnCommitOpt (2x) + 58412: 1072, // OnDelete (2x) + 58415: 1073, // OnUpdate (2x) + 58420: 1074, // OptCollate (2x) + 58425: 1075, // OptFull (2x) + 58427: 1076, // OptInteger (2x) + 58440: 1077, // OptionalBraces (2x) + 58439: 1078, // OptionLevel (2x) + 58429: 1079, // OptLeadLagInfo (2x) + 58428: 1080, // OptLLDefault (2x) + 58445: 1081, // OuterOpt (2x) + 58450: 1082, // PartitionDefinitionList (2x) + 58451: 1083, // PartitionDefinitionListOpt (2x) + 58457: 1084, // PartitionOpt (2x) + 58459: 1085, // PasswordOpt (2x) + 58461: 1086, // PasswordOrLockOptionList (2x) + 58462: 1087, // PasswordOrLockOptions (2x) + 58465: 1088, // PlacementOptionList (2x) + 58467: 1089, // PlanReplayerStmt (2x) + 58473: 1090, // PreparedStmt (2x) + 58478: 1091, // PrivLevel (2x) + 58481: 1092, // PurgeImportStmt (2x) + 58482: 1093, // QuickOptional (2x) + 58483: 1094, // RecoverTableStmt (2x) + 58485: 1095, // ReferOpt (2x) + 58487: 1096, // RegexpSym (2x) + 58488: 1097, // RenameTableStmt (2x) + 58489: 1098, // RenameUserStmt (2x) + 58491: 1099, // RepeatableOpt (2x) + 58497: 1100, // RestartStmt (2x) + 58499: 1101, // ResumeImportStmt (2x) + 57514: 1102, // revoke (2x) + 58500: 1103, // RevokeRoleStmt (2x) + 58501: 1104, // RevokeStmt (2x) + 58504: 1105, // RoleOrPrivElemList (2x) + 58505: 1106, // RoleSpec (2x) + 58526: 1107, // SelectStmtOpt (2x) + 58529: 1108, // SelectStmtSQLCache (2x) + 58533: 1109, // SetBindingStmt (2x) + 58534: 1110, // SetDefaultRoleOpt (2x) + 58535: 1111, // SetDefaultRoleStmt (2x) + 58545: 1112, // SetRoleStmt (2x) + 58548: 1113, // ShowImportStmt (2x) + 58553: 1114, // ShowProfileType (2x) + 58556: 1115, // ShowStmt (2x) + 58557: 1116, // ShowTableAliasOpt (2x) + 58559: 1117, // ShutdownStmt (2x) + 58560: 1118, // SignedLiteral (2x) + 58564: 1119, // SplitOption (2x) + 58565: 1120, // SplitRegionStmt (2x) + 58569: 1121, // Statement (2x) + 58572: 1122, // StatsOptionsOpt (2x) + 58573: 1123, // StatsPersistentVal (2x) + 58574: 1124, // StatsType (2x) + 58575: 1125, // StopImportStmt (2x) + 58582: 1126, // SubPartDefinition (2x) + 58585: 1127, // SubPartitionMethod (2x) + 58590: 1128, // Symbol (2x) + 58596: 1129, // TableElementList (2x) + 58599: 1130, // TableLock (2x) + 58603: 1131, // TableNameListOpt (2x) + 58610: 1132, // TableOrTables (2x) + 58619: 1133, // TablesTerminalSym (2x) + 58617: 1134, // TableToTable (2x) + 58621: 1135, // TextStringList (2x) + 58626: 1136, // TraceStmt (2x) + 58631: 1137, // TruncateTableStmt (2x) + 58634: 1138, // UnlockTablesStmt (2x) + 58640: 1139, // UserToUser (2x) + 58637: 1140, // UseStmt (2x) + 58652: 1141, // Varchar (2x) + 58655: 1142, // VariableAssignmentList (2x) + 58664: 1143, // WhenClause (2x) + 58669: 1144, // WindowDefinition (2x) + 58672: 1145, // WindowFrameBound (2x) + 58679: 1146, // WindowSpec (2x) + 58684: 1147, // WithGrantOptionOpt (2x) + 58685: 1148, // WithList (2x) + 58689: 1149, // Writeable (2x) + 58105: 1150, // AdminShowSlow (1x) + 58114: 1151, // AlterOrderList (1x) + 58117: 1152, // AlterSequenceOptionList (1x) + 58119: 1153, // AlterTablePartitionOpt (1x) + 58121: 1154, // AlterTableSpecList (1x) + 58122: 1155, // AlterTableSpecListOpt (1x) + 58126: 1156, // AnalyzeOptionList (1x) + 58129: 1157, // AnyOrAll (1x) + 58131: 1158, // AsOfClauseOpt (1x) + 58132: 1159, // AsOpt (1x) + 58137: 1160, // AuthOption (1x) + 58138: 1161, // AuthPlugin (1x) + 58149: 1162, // BetweenOrNotOp (1x) + 58151: 1163, // BindingStatusType (1x) + 58154: 1164, // BitValueType (1x) + 58155: 1165, // BlobType (1x) + 58158: 1166, // BooleanType (1x) + 57370: 1167, // both (1x) + 58169: 1168, // CharsetNameOrDefault (1x) + 58170: 1169, // CharsetOpt (1x) + 58172: 1170, // ClearPasswordExpireOptions (1x) + 58176: 1171, // ColumnFormat (1x) + 58178: 1172, // ColumnList (1x) + 58185: 1173, // ColumnNameOrUserVariableList (1x) + 58182: 1174, // ColumnNameOrUserVarListOpt (1x) + 58183: 1175, // ColumnNameOrUserVarListOptWithBrackets (1x) + 58191: 1176, // ColumnSetValueList (1x) + 58195: 1177, // CompareOp (1x) + 58199: 1178, // ConnectionOptionList (1x) + 58202: 1179, // ConstraintElem (1x) + 58210: 1180, // CreateSequenceOptionListOpt (1x) + 58214: 1181, // CreateTableSelectOpt (1x) + 58217: 1182, // CreateViewSelectOpt (1x) + 58224: 1183, // DatabaseOptionListOpt (1x) + 58226: 1184, // DateAndTimeType (1x) + 58221: 1185, // DBNameList (1x) + 58232: 1186, // DefaultValueExpr (1x) + 57409: 1187, // dual (1x) + 58253: 1188, // ElseOpt (1x) + 58258: 1189, // EnforcedOrNotOrNotNullOpt (1x) + 58264: 1190, // ExplainFormatType (1x) + 58272: 1191, // ExpressionOpt (1x) + 58274: 1192, // FetchFirstOpt (1x) + 58276: 1193, // FieldAsName (1x) + 58277: 1194, // FieldAsNameOpt (1x) + 58279: 1195, // FieldItemList (1x) + 58281: 1196, // FieldList (1x) + 58287: 1197, // FirstOrNext (1x) + 58288: 1198, // FixedPointType (1x) + 58290: 1199, // FlashbackToNewName (1x) + 58292: 1200, // FloatingPointType (1x) + 58293: 1201, // FlushOption (1x) + 58296: 1202, // FromDual (1x) + 58298: 1203, // FulltextSearchModifierOpt (1x) + 58299: 1204, // FuncDatetimePrec (1x) + 58312: 1205, // GetFormatSelector (1x) + 58319: 1206, // HandleRangeList (1x) + 58321: 1207, // HavingClause (1x) + 58324: 1208, // IdentListWithParenOpt (1x) + 58328: 1209, // IfNotRunning (1x) + 58329: 1210, // IfRunning (1x) + 58330: 1211, // IgnoreLines (1x) + 58332: 1212, // ImportTruncate (1x) + 58338: 1213, // IndexHintScope (1x) + 58341: 1214, // IndexKeyTypeOpt (1x) + 58350: 1215, // IndexPartSpecificationListOpt (1x) + 58353: 1216, // IndexTypeOpt (1x) + 58333: 1217, // InOrNotOp (1x) + 58356: 1218, // InstanceOption (1x) + 58358: 1219, // IntegerType (1x) + 58361: 1220, // IsolationLevel (1x) + 58360: 1221, // IsOrNotOp (1x) + 57460: 1222, // leading (1x) + 58369: 1223, // LikeEscapeOpt (1x) + 58370: 1224, // LikeOrNotOp (1x) + 58371: 1225, // LikeTableWithOrWithoutParen (1x) + 58376: 1226, // LinesTerminated (1x) + 58379: 1227, // LoadDataSetList (1x) + 58380: 1228, // LoadDataSetSpecOpt (1x) + 58387: 1229, // LockType (1x) + 58388: 1230, // LogTypeOpt (1x) + 58389: 1231, // Match (1x) + 58390: 1232, // MatchOpt (1x) + 58391: 1233, // MaxIndexNumOpt (1x) + 58392: 1234, // MaxMinutesOpt (1x) + 58395: 1235, // NChar (1x) + 58408: 1236, // NumericType (1x) + 58397: 1237, // NVarchar (1x) + 58413: 1238, // OnDeleteUpdateOpt (1x) + 58414: 1239, // OnDuplicateKeyUpdate (1x) + 58416: 1240, // OptBinMod (1x) + 58418: 1241, // OptCharset (1x) + 58421: 1242, // OptErrors (1x) + 58422: 1243, // OptExistingWindowName (1x) + 58424: 1244, // OptFromFirstLast (1x) + 58426: 1245, // OptGConcatSeparator (1x) + 58432: 1246, // OptPartitionClause (1x) + 58433: 1247, // OptTable (1x) + 58436: 1248, // OptWindowFrameClause (1x) + 58437: 1249, // OptWindowOrderByClause (1x) + 58442: 1250, // Order (1x) + 58441: 1251, // OrReplace (1x) + 57444: 1252, // outfile (1x) + 58448: 1253, // PartDefValuesOpt (1x) + 58452: 1254, // PartitionKeyAlgorithmOpt (1x) + 58453: 1255, // PartitionMethod (1x) + 58456: 1256, // PartitionNumOpt (1x) + 58463: 1257, // PerDB (1x) + 58464: 1258, // PerTable (1x) + 57498: 1259, // precisionType (1x) + 58472: 1260, // PrepareSQL (1x) + 58480: 1261, // ProcedureCall (1x) + 57505: 1262, // recursive (1x) + 58486: 1263, // RegexpOrNotOp (1x) + 58490: 1264, // ReorganizePartitionRuleOpt (1x) + 58495: 1265, // RequireList (1x) + 58506: 1266, // RoleSpecList (1x) + 58513: 1267, // RowOrRows (1x) + 58519: 1268, // SelectStmtFieldList (1x) + 58527: 1269, // SelectStmtOpts (1x) + 58528: 1270, // SelectStmtOptsList (1x) + 58532: 1271, // SequenceOptionList (1x) + 58537: 1272, // SetOpr (1x) + 58544: 1273, // SetRoleOpt (1x) + 58549: 1274, // ShowIndexKwd (1x) + 58550: 1275, // ShowLikeOrWhereOpt (1x) + 58551: 1276, // ShowPlacementTarget (1x) + 58552: 1277, // ShowProfileArgsOpt (1x) + 58554: 1278, // ShowProfileTypes (1x) + 58555: 1279, // ShowProfileTypesOpt (1x) + 58558: 1280, // ShowTargetFilterable (1x) + 57525: 1281, // spatial (1x) + 58566: 1282, // SplitSyntaxOption (1x) + 57530: 1283, // ssl (1x) + 58567: 1284, // Start (1x) + 58568: 1285, // Starting (1x) + 57531: 1286, // starting (1x) + 58570: 1287, // StatementList (1x) + 58571: 1288, // StatementScope (1x) + 58576: 1289, // StorageMedia (1x) + 57536: 1290, // stored (1x) + 58577: 1291, // StringList (1x) + 58580: 1292, // StringNameOrBRIEOptionKeyword (1x) + 58581: 1293, // StringType (1x) + 58583: 1294, // SubPartDefinitionList (1x) + 58584: 1295, // SubPartDefinitionListOpt (1x) + 58586: 1296, // SubPartitionNumOpt (1x) + 58587: 1297, // SubPartitionOpt (1x) + 58597: 1298, // TableElementListOpt (1x) + 58600: 1299, // TableLockList (1x) + 58613: 1300, // TableRefsClause (1x) + 58614: 1301, // TableSampleMethodOpt (1x) + 58615: 1302, // TableSampleOpt (1x) + 58616: 1303, // TableSampleUnitOpt (1x) + 58618: 1304, // TableToTableList (1x) + 58622: 1305, // TextType (1x) + 57543: 1306, // trailing (1x) + 58630: 1307, // TrimDirection (1x) + 58632: 1308, // Type (1x) + 58641: 1309, // UserToUserList (1x) + 58643: 1310, // UserVariableList (1x) + 58646: 1311, // UsingRoles (1x) + 58648: 1312, // Values (1x) + 58650: 1313, // ValuesOpt (1x) + 58657: 1314, // ViewAlgorithm (1x) + 58658: 1315, // ViewCheckOption (1x) + 58659: 1316, // ViewDefiner (1x) + 58660: 1317, // ViewFieldList (1x) + 58661: 1318, // ViewName (1x) + 58662: 1319, // ViewSQLSecurity (1x) + 57563: 1320, // virtual (1x) + 58663: 1321, // VirtualOrStored (1x) + 58665: 1322, // WhenClauseList (1x) + 58668: 1323, // WindowClauseOptional (1x) + 58670: 1324, // WindowDefinitionList (1x) + 58671: 1325, // WindowFrameBetween (1x) + 58673: 1326, // WindowFrameExtent (1x) + 58675: 1327, // WindowFrameUnits (1x) + 58678: 1328, // WindowNameOrSpec (1x) + 58680: 1329, // WindowSpecDetails (1x) + 58686: 1330, // WithReadLockOpt (1x) + 58687: 1331, // WithValidation (1x) + 58688: 1332, // WithValidationOpt (1x) + 58690: 1333, // Year (1x) + 58104: 1334, // $default (0x) + 58065: 1335, // andnot (0x) + 58135: 1336, // AssignmentListOpt (0x) + 58175: 1337, // ColumnDefList (0x) + 58192: 1338, // CommaOpt (0x) + 58088: 1339, // createTableSelect (0x) + 58079: 1340, // empty (0x) + 57345: 1341, // error (0x) + 58103: 1342, // higherThanComma (0x) + 58097: 1343, // higherThanParenthese (0x) + 58086: 1344, // insertValues (0x) + 57352: 1345, // invalid (0x) + 58089: 1346, // lowerThanCharsetKwd (0x) + 58102: 1347, // lowerThanComma (0x) + 58087: 1348, // lowerThanCreateTableSelect (0x) + 58099: 1349, // lowerThanEq (0x) + 58094: 1350, // lowerThanFunction (0x) + 58085: 1351, // lowerThanInsertValues (0x) + 58090: 1352, // lowerThanKey (0x) + 58091: 1353, // lowerThanLocal (0x) + 58101: 1354, // lowerThanNot (0x) + 58098: 1355, // lowerThanOn (0x) + 58096: 1356, // lowerThanParenthese (0x) + 58092: 1357, // lowerThanRemove (0x) + 58080: 1358, // lowerThanSelectOpt (0x) + 58084: 1359, // lowerThanSelectStmt (0x) + 58083: 1360, // lowerThanSetKeyword (0x) + 58082: 1361, // lowerThanStringLitToken (0x) + 58081: 1362, // lowerThanValueKeyword (0x) + 58093: 1363, // lowerThenOrder (0x) + 58100: 1364, // neg (0x) + 57356: 1365, // odbcDateType (0x) + 57358: 1366, // odbcTimestampType (0x) + 57357: 1367, // odbcTimeType (0x) + 58095: 1368, // tableRefPriority (0x) } yySymNames = []string{ @@ -2202,24 +2207,13 @@ var ( "serial", "autoRandom", "columnFormat", - "charsetKwd", "password", - "regions", - "placement", - "constraints", - "followerConstraints", - "followers", - "leaderConstraints", - "learnerConstraints", - "learners", - "primaryRegion", - "schedule", - "voterConstraints", - "voters", + "charsetKwd", "checksum", - "encryption", + "placement", "keyBlockSize", "tablespace", + "encryption", "engine", "data", "insertMethod", @@ -2246,8 +2240,8 @@ var ( "statsSamplePages", "statsSampleRate", "tableChecksum", - "')'", "account", + "')'", "resume", "signed", "snapshot", @@ -2286,7 +2280,18 @@ var ( "clustered", "invisible", "nonclustered", + "regions", "visible", + "constraints", + "followerConstraints", + "followers", + "leaderConstraints", + "learnerConstraints", + "learners", + "primaryRegion", + "schedule", + "voterConstraints", + "voters", "columns", "view", "subpartition", @@ -2312,9 +2317,9 @@ var ( "sqlTsiQuarter", "sqlTsiSecond", "sqlTsiWeek", + "status", "week", "separator", - "status", "maxConnectionsPerHour", "maxQueriesPerHour", "maxUpdatesPerHour", @@ -2338,6 +2343,7 @@ var ( "current", "enforced", "following", + "identifier", "nowait", "only", "rollback", @@ -2352,7 +2358,6 @@ var ( "temporary", "unbounded", "user", - "identifier", "offset", "planCache", "prepare", @@ -2365,6 +2370,7 @@ var ( "fixed", "isolation", "jsonType", + "location", "max_idxnum", "memory", "off", @@ -2390,7 +2396,6 @@ var ( "flush", "full", "identSQLErrors", - "location", "mb", "mode", "never", @@ -2456,6 +2461,7 @@ var ( "rebuild", "redundant", "reload", + "replica", "restore", "routine", "s3", @@ -2470,6 +2476,7 @@ var ( "statsOptions", "stop", "swaps", + "tiFlash", "tokudbDefault", "tokudbFast", "tokudbLzma", @@ -2487,6 +2494,7 @@ var ( "always", "backups", "bernoulli", + "bindingCache", "bitType", "boolType", "briefType", @@ -2505,8 +2513,10 @@ var ( "consistent", "ddl", "depth", + "disabled", "dotType", "dump", + "enabled", "engines", "enum", "events", @@ -2555,7 +2565,6 @@ var ( "recent", "region", "replayer", - "replica", "reset", "restores", "security", @@ -2574,7 +2583,6 @@ var ( "temptable", "textType", "than", - "tiFlash", "tls", "top", "traditional", @@ -2653,44 +2661,44 @@ var ( "on", "'('", "with", - "stringLit", "not2", + "stringLit", "not", - "defaultKwd", "as", + "defaultKwd", "union", - "collate", "using", + "collate", "left", "right", "'-'", "'+'", "mod", - "ignore", - "partition", "except", "intersect", + "ignore", + "partition", "null", "forKwd", "limit", "into", - "eq", "lock", - "values", - "force", - "charType", + "eq", "from", "fetch", "where", + "values", "order", - "replace", + "force", + "set", "and", + "charType", + "replace", "intLit", "or", "andand", "pipesAsOr", "xor", - "set", "group", "straightJoin", "window", @@ -2721,8 +2729,8 @@ var ( "secondMicrosecond", "yearMonth", "when", - "binaryType", "in", + "binaryType", "elseKwd", "then", "'<'", @@ -2745,36 +2753,36 @@ var ( "regexpKwd", "rlike", "ifKwd", - "tableKwd", "insert", "singleAtIdentifier", "currentUser", + "tableKwd", "falseKwd", "trueKwd", + "key", "decLit", "floatLit", "row", "hexLit", - "key", "paramMarker", "'{'", "bitLit", "interval", + "check", "pipes", + "primary", "database", "exists", - "check", "convert", - "primary", - "doubleAtIdentifier", "builtinNow", "currentTs", + "doubleAtIdentifier", "localTime", "localTs", "underscoreCS", + "unique", "'!'", "'~'", - "builtinAddDate", "builtinApproxCountDistinct", "builtinApproxPercentile", "builtinBitAnd", @@ -2793,7 +2801,6 @@ var ( "builtinPosition", "builtinStddevPop", "builtinStddevSamp", - "builtinSubDate", "builtinSubstring", "builtinSum", "builtinSysDate", @@ -2803,6 +2810,7 @@ var ( "builtinVarPop", "builtinVarSamp", "caseKwd", + "constraint", "cumeDist", "currentDate", "currentRole", @@ -2821,14 +2829,12 @@ var ( "utcDate", "utcTime", "utcTimestamp", - "unique", - "constraint", - "selectKwd", "references", "generated", + "selectKwd", "character", - "index", "match", + "index", "to", "all", "'.'", @@ -2912,9 +2918,9 @@ var ( "PredicateExpr", "BoolPri", "Expression", + "NUM", "logAnd", "logOr", - "NUM", "EqOpt", "TableName", "StringName", @@ -2922,8 +2928,8 @@ var ( "over", "zerofill", "deleteKwd", - "ColumnName", "LengthNum", + "ColumnName", "distinct", "distinctRow", "WindowingClause", @@ -2938,31 +2944,29 @@ var ( "SetOprClauseList", "SetOprStmtWithLimitOrderBy", "SetOprStmtWoutLimitOrderBy", - "hintComment", - "FieldLen", - "Int64Num", "SelectStmtWithClause", "SetOprStmt", "WithClause", + "hintComment", + "FieldLen", + "Int64Num", "OptWindowingClause", "OrderBy", "SelectStmtLimit", "sqlBigResult", "sqlCalcFoundRows", "sqlSmallResult", - "DirectPlacementOption", "CharsetKw", - "Username", "UpdateStmtNoWith", + "Username", "DeleteWithoutUsingStmt", "ExpressionList", - "PlacementPolicyOption", - "IfExists", "InsertIntoStmt", - "PlacementOption", "ReplaceIntoStmt", - "terminated", "UpdateStmt", + "PlacementPolicyOption", + "IfExists", + "terminated", "DistinctKwd", "IfNotExists", "OptFieldLen", @@ -3024,6 +3028,7 @@ var ( "TableOption", "varying", "BeginTransactionStmt", + "BindableStmt", "column", "ColumnDef", "CommitStmt", @@ -3051,6 +3056,7 @@ var ( "ByItem", "CollationName", "ColumnKeywordOpt", + "DirectPlacementOption", "FieldOpt", "FieldOpts", "IdentList", @@ -3070,7 +3076,6 @@ var ( "UserSpec", "Assignment", "AuthString", - "BindableStmt", "BRIEBooleanOptionName", "BRIEIntegerOptionName", "BRIEKeywordOptionName", @@ -3123,6 +3128,9 @@ var ( "keys", "Lines", "MaxValueOrExpression", + "NowSym", + "NowSymFunc", + "NowSymOptionFraction", "OptOrder", "OptTemporary", "PartDefOptionList", @@ -3170,6 +3178,7 @@ var ( "BinlogStmt", "BRIEStmt", "BRIETables", + "BuiltinFunction", "call", "CallStmt", "CastType", @@ -3248,11 +3257,10 @@ var ( "LoadDataSetItem", "LoadStatsStmt", "LocalOpt", + "LocationLabelList", "LockTablesStmt", "MaxValueOrExpressionList", - "NowSym", - "NowSymFunc", - "NowSymOptionFraction", + "NowSymOptionFractionParentheses", "NumList", "ObjectType", "of", @@ -3295,6 +3303,7 @@ var ( "RoleSpec", "SelectStmtOpt", "SelectStmtSQLCache", + "SetBindingStmt", "SetDefaultRoleOpt", "SetDefaultRoleStmt", "SetRoleStmt", @@ -3348,6 +3357,7 @@ var ( "AuthOption", "AuthPlugin", "BetweenOrNotOp", + "BindingStatusType", "BitValueType", "BlobType", "BooleanType", @@ -3413,7 +3423,6 @@ var ( "LinesTerminated", "LoadDataSetList", "LoadDataSetSpecOpt", - "LocationLabelList", "LockType", "LogTypeOpt", "Match", @@ -3558,104 +3567,102 @@ var ( yyReductions = []struct{ xsym, components int }{ {0, 1}, - {1280, 1}, - {812, 6}, - {812, 8}, - {812, 10}, - {1085, 1}, - {1085, 2}, - {1085, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {761, 3}, - {770, 1}, - {770, 1}, - {767, 4}, - {767, 4}, - {767, 4}, - {767, 4}, + {1284, 1}, + {811, 6}, + {811, 8}, + {811, 10}, + {1088, 1}, + {1088, 2}, + {1088, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {862, 3}, + {770, 4}, + {770, 4}, + {770, 4}, + {770, 4}, {914, 3}, {914, 3}, - {1118, 3}, - {1118, 3}, - {1149, 1}, - {1149, 2}, - {1149, 4}, - {1149, 3}, - {1149, 3}, - {1224, 0}, - {1224, 3}, - {974, 1}, - {974, 5}, - {974, 5}, - {974, 5}, - {974, 5}, - {974, 6}, - {974, 2}, - {974, 5}, - {974, 6}, - {974, 8}, - {974, 1}, - {974, 1}, - {974, 3}, - {974, 4}, - {974, 5}, - {974, 3}, - {974, 4}, - {974, 4}, - {974, 7}, - {974, 3}, - {974, 4}, - {974, 4}, - {974, 4}, - {974, 4}, - {974, 2}, - {974, 2}, - {974, 4}, - {974, 4}, - {974, 5}, - {974, 3}, - {974, 2}, - {974, 2}, - {974, 5}, - {974, 6}, - {974, 6}, - {974, 8}, - {974, 5}, - {974, 5}, - {974, 3}, - {974, 3}, - {974, 3}, - {974, 5}, - {974, 1}, - {974, 1}, - {974, 1}, - {974, 1}, - {974, 2}, - {974, 2}, - {974, 1}, - {974, 1}, - {974, 4}, - {974, 3}, - {974, 4}, - {974, 1}, - {974, 1}, - {1260, 0}, - {1260, 5}, - {821, 1}, - {821, 1}, - {1328, 0}, - {1328, 1}, - {1327, 2}, - {1327, 2}, + {1122, 3}, + {1122, 3}, + {1153, 1}, + {1153, 2}, + {1153, 4}, + {1153, 3}, + {1153, 3}, + {1063, 0}, + {1063, 3}, + {977, 1}, + {977, 5}, + {977, 5}, + {977, 5}, + {977, 5}, + {977, 6}, + {977, 2}, + {977, 5}, + {977, 6}, + {977, 8}, + {977, 1}, + {977, 1}, + {977, 3}, + {977, 4}, + {977, 5}, + {977, 3}, + {977, 4}, + {977, 4}, + {977, 7}, + {977, 3}, + {977, 4}, + {977, 4}, + {977, 4}, + {977, 4}, + {977, 2}, + {977, 2}, + {977, 4}, + {977, 4}, + {977, 5}, + {977, 3}, + {977, 2}, + {977, 2}, + {977, 5}, + {977, 6}, + {977, 6}, + {977, 8}, + {977, 5}, + {977, 5}, + {977, 3}, + {977, 3}, + {977, 3}, + {977, 5}, + {977, 1}, + {977, 1}, + {977, 1}, + {977, 1}, + {977, 2}, + {977, 2}, + {977, 1}, + {977, 1}, + {977, 4}, + {977, 3}, + {977, 4}, + {977, 1}, + {977, 1}, + {1264, 0}, + {1264, 5}, + {820, 1}, + {820, 1}, + {1332, 0}, + {1332, 1}, + {1331, 2}, + {1331, 2}, {857, 1}, {857, 1}, {858, 3}, @@ -3663,124 +3670,124 @@ var ( {858, 3}, {858, 3}, {858, 3}, - {870, 3}, - {870, 3}, - {1145, 2}, - {1145, 2}, - {817, 1}, - {817, 1}, - {1049, 0}, - {1049, 1}, + {871, 3}, + {871, 3}, + {1149, 2}, + {1149, 2}, + {816, 1}, + {816, 1}, + {1053, 0}, + {1053, 1}, {861, 0}, {861, 1}, {917, 0}, {917, 1}, {917, 2}, - {1151, 0}, - {1151, 1}, - {1150, 1}, - {1150, 3}, - {779, 1}, - {779, 3}, - {822, 0}, - {822, 1}, - {822, 2}, - {1124, 1}, + {1155, 0}, + {1155, 1}, + {1154, 1}, + {1154, 3}, + {778, 1}, + {778, 3}, + {821, 0}, + {821, 1}, + {821, 2}, + {1128, 1}, + {1097, 3}, + {1304, 1}, + {1304, 3}, + {1134, 3}, + {1098, 3}, + {1309, 1}, + {1309, 3}, + {1139, 3}, + {1094, 5}, {1094, 3}, - {1300, 1}, - {1300, 3}, - {1130, 3}, - {1095, 3}, - {1305, 1}, - {1305, 3}, - {1135, 3}, - {1091, 5}, - {1091, 3}, - {1091, 4}, - {1033, 4}, - {1194, 0}, - {1194, 2}, - {1116, 6}, - {1116, 8}, - {1115, 6}, - {1115, 2}, - {1278, 0}, - {1278, 2}, - {1278, 1}, - {1278, 3}, - {977, 5}, - {977, 6}, - {977, 7}, - {977, 7}, - {977, 8}, - {977, 9}, - {977, 8}, - {977, 7}, - {977, 6}, - {977, 8}, - {966, 0}, - {966, 2}, - {966, 2}, - {794, 0}, - {794, 2}, - {1152, 1}, - {1152, 3}, - {976, 2}, - {976, 2}, - {976, 3}, - {976, 3}, - {976, 2}, - {976, 2}, - {879, 3}, + {1094, 4}, + {1037, 4}, + {1199, 0}, + {1199, 2}, + {1120, 6}, + {1120, 8}, + {1119, 6}, + {1119, 2}, + {1282, 0}, + {1282, 2}, + {1282, 1}, + {1282, 3}, + {980, 5}, + {980, 6}, + {980, 7}, + {980, 7}, + {980, 8}, + {980, 9}, + {980, 8}, + {980, 7}, + {980, 6}, + {980, 8}, + {969, 0}, + {969, 2}, + {969, 2}, + {793, 0}, + {793, 2}, + {1156, 1}, + {1156, 3}, + {979, 2}, + {979, 2}, + {979, 3}, + {979, 3}, + {979, 2}, + {979, 2}, + {880, 3}, {913, 1}, {913, 3}, - {1332, 0}, - {1332, 1}, - {834, 1}, - {834, 2}, - {834, 2}, - {834, 2}, - {834, 4}, - {834, 5}, - {834, 6}, - {834, 4}, - {834, 5}, - {978, 2}, - {1333, 1}, - {1333, 3}, + {1336, 0}, + {1336, 1}, + {833, 1}, + {833, 2}, + {833, 2}, + {833, 2}, + {833, 4}, + {833, 5}, + {833, 6}, + {833, 4}, + {833, 5}, + {981, 2}, + {1337, 1}, + {1337, 3}, {836, 3}, {836, 3}, - {733, 1}, - {733, 3}, - {733, 5}, - {798, 1}, - {798, 3}, - {986, 0}, - {986, 1}, - {1203, 0}, - {1203, 3}, - {864, 1}, - {864, 3}, - {1169, 0}, - {1169, 1}, - {1168, 1}, - {1168, 3}, - {987, 1}, - {987, 1}, - {1170, 0}, - {1170, 3}, + {735, 1}, + {735, 3}, + {735, 5}, + {797, 1}, + {797, 3}, + {990, 0}, + {990, 1}, + {1208, 0}, + {1208, 3}, + {865, 1}, + {865, 3}, + {1174, 0}, + {1174, 1}, + {1173, 1}, + {1173, 3}, + {991, 1}, + {991, 1}, + {1175, 0}, + {1175, 3}, {837, 1}, {837, 2}, - {941, 0}, - {941, 1}, - {800, 1}, - {800, 1}, + {944, 0}, + {944, 1}, + {799, 1}, + {799, 1}, {922, 1}, {922, 2}, - {1025, 0}, - {1025, 1}, - {1184, 2}, - {1184, 1}, + {1029, 0}, + {1029, 1}, + {1189, 2}, + {1189, 1}, {916, 2}, {916, 1}, {916, 1}, @@ -3799,257 +3806,266 @@ var ( {916, 2}, {916, 2}, {916, 2}, - {1285, 1}, - {1285, 1}, - {1285, 1}, - {1166, 1}, - {1166, 1}, - {1166, 1}, + {1289, 1}, + {1289, 1}, + {1289, 1}, + {1171, 1}, + {1171, 1}, + {1171, 1}, {925, 0}, {925, 2}, - {1317, 0}, - {1317, 1}, - {1317, 1}, - {988, 1}, - {988, 2}, - {989, 0}, - {989, 1}, - {1174, 7}, - {1174, 7}, - {1174, 7}, - {1174, 7}, - {1174, 8}, - {1174, 5}, - {1227, 2}, - {1227, 2}, - {1227, 2}, - {1228, 0}, - {1228, 1}, + {1321, 0}, + {1321, 1}, + {1321, 1}, + {992, 1}, + {992, 2}, + {993, 0}, + {993, 1}, + {1179, 7}, + {1179, 7}, + {1179, 7}, + {1179, 7}, + {1179, 8}, + {1179, 5}, + {1231, 2}, + {1231, 2}, + {1231, 2}, + {1232, 0}, + {1232, 1}, {898, 5}, - {1069, 3}, - {1070, 3}, - {1234, 0}, - {1234, 1}, - {1234, 1}, - {1234, 2}, - {1234, 2}, - {1092, 1}, - {1092, 1}, - {1092, 2}, - {1092, 2}, - {1092, 2}, - {1181, 1}, - {1181, 1}, - {1181, 1}, - {1063, 1}, - {1063, 3}, - {1063, 4}, - {704, 4}, - {704, 4}, - {1062, 1}, - {1062, 1}, - {1062, 1}, - {1062, 1}, - {1061, 1}, - {1061, 1}, - {1061, 1}, - {1114, 1}, - {1114, 2}, - {1114, 2}, - {809, 1}, - {809, 1}, - {809, 1}, - {1120, 1}, - {1120, 1}, - {1120, 1}, - {1001, 12}, - {1017, 3}, - {997, 13}, - {1210, 0}, - {1210, 3}, - {825, 1}, - {825, 3}, - {816, 3}, - {816, 4}, - {1046, 0}, - {1046, 1}, - {1046, 1}, - {1046, 2}, - {1046, 2}, - {1209, 0}, - {1209, 1}, - {1209, 1}, - {1209, 1}, - {967, 4}, - {967, 3}, - {995, 5}, - {805, 1}, - {873, 1}, + {1072, 3}, + {1073, 3}, + {1238, 0}, + {1238, 1}, + {1238, 1}, + {1238, 2}, + {1238, 2}, + {1095, 1}, + {1095, 1}, + {1095, 2}, + {1095, 2}, + {1095, 2}, + {1186, 1}, + {1186, 1}, + {1186, 1}, + {1186, 1}, + {984, 3}, + {984, 3}, + {984, 4}, + {1066, 3}, + {1066, 1}, + {936, 1}, + {936, 3}, + {936, 4}, + {705, 4}, + {705, 4}, + {935, 1}, + {935, 1}, + {935, 1}, + {935, 1}, + {934, 1}, + {934, 1}, + {934, 1}, + {1118, 1}, + {1118, 2}, + {1118, 2}, + {808, 1}, + {808, 1}, + {808, 1}, + {1124, 1}, + {1124, 1}, + {1124, 1}, + {1163, 1}, + {1163, 1}, + {1005, 12}, + {1021, 3}, + {1001, 13}, + {1215, 0}, + {1215, 3}, + {824, 1}, + {824, 3}, + {815, 3}, + {815, 4}, + {1050, 0}, + {1050, 1}, + {1050, 1}, + {1050, 2}, + {1050, 2}, + {1214, 0}, + {1214, 1}, + {1214, 1}, + {1214, 1}, + {970, 4}, + {970, 3}, + {999, 5}, + {804, 1}, + {874, 1}, {838, 4}, {838, 4}, {838, 4}, {838, 2}, {838, 1}, - {1178, 0}, - {1178, 1}, + {838, 5}, + {1183, 0}, + {1183, 1}, {920, 1}, {920, 2}, {919, 12}, {919, 7}, - {1068, 0}, - {1068, 4}, - {1068, 4}, - {782, 0}, - {782, 1}, - {1081, 0}, - {1081, 6}, - {1123, 6}, - {1123, 5}, - {1250, 0}, - {1250, 3}, - {1251, 1}, - {1251, 4}, - {1251, 5}, - {1251, 4}, - {1251, 5}, - {1251, 4}, - {1251, 3}, - {1251, 1}, - {1055, 0}, - {1055, 1}, - {1293, 0}, - {1293, 4}, - {1292, 0}, - {1292, 2}, - {1252, 0}, - {1252, 2}, - {1080, 0}, - {1080, 3}, - {1079, 1}, - {1079, 3}, - {937, 5}, - {1291, 0}, - {1291, 3}, - {1290, 1}, - {1290, 3}, - {1122, 3}, - {936, 0}, - {936, 2}, - {802, 3}, - {802, 3}, - {802, 4}, - {802, 3}, - {802, 4}, - {802, 4}, - {802, 3}, - {802, 3}, - {802, 3}, - {802, 3}, - {802, 1}, - {1249, 0}, - {1249, 4}, - {1249, 6}, - {1249, 1}, - {1249, 5}, - {1249, 1}, - {1249, 1}, - {1022, 0}, - {1022, 1}, - {1022, 1}, - {1155, 0}, - {1155, 1}, - {1176, 0}, - {1176, 1}, - {1176, 1}, - {1176, 1}, - {1176, 1}, - {1177, 1}, - {1177, 1}, - {1177, 1}, - {1177, 1}, - {1220, 2}, - {1220, 4}, - {1004, 11}, - {1247, 0}, - {1247, 2}, - {1310, 0}, - {1310, 3}, - {1310, 3}, - {1310, 3}, - {1312, 0}, - {1312, 3}, + {1071, 0}, + {1071, 4}, + {1071, 4}, + {781, 0}, + {781, 1}, + {1084, 0}, + {1084, 6}, + {1127, 6}, + {1127, 5}, + {1254, 0}, + {1254, 3}, + {1255, 1}, + {1255, 4}, + {1255, 5}, + {1255, 4}, + {1255, 5}, + {1255, 4}, + {1255, 3}, + {1255, 1}, + {1059, 0}, + {1059, 1}, + {1297, 0}, + {1297, 4}, + {1296, 0}, + {1296, 2}, + {1256, 0}, + {1256, 2}, + {1083, 0}, + {1083, 3}, + {1082, 1}, + {1082, 3}, + {940, 5}, + {1295, 0}, + {1295, 3}, + {1294, 1}, + {1294, 3}, + {1126, 3}, + {939, 0}, + {939, 2}, + {801, 3}, + {801, 3}, + {801, 4}, + {801, 3}, + {801, 4}, + {801, 4}, + {801, 3}, + {801, 3}, + {801, 3}, + {801, 3}, + {801, 1}, + {1253, 0}, + {1253, 4}, + {1253, 6}, + {1253, 1}, + {1253, 5}, + {1253, 1}, + {1253, 1}, + {1026, 0}, + {1026, 1}, + {1026, 1}, + {1159, 0}, + {1159, 1}, + {1181, 0}, + {1181, 1}, + {1181, 1}, + {1181, 1}, + {1181, 1}, + {1182, 1}, + {1182, 1}, + {1182, 1}, + {1182, 1}, + {1225, 2}, + {1225, 4}, + {1008, 11}, + {1251, 0}, + {1251, 2}, + {1314, 0}, + {1314, 3}, + {1314, 3}, + {1314, 3}, + {1316, 0}, + {1316, 3}, + {1319, 0}, + {1319, 3}, + {1319, 3}, + {1318, 1}, + {1317, 0}, + {1317, 3}, + {1172, 1}, + {1172, 3}, {1315, 0}, - {1315, 3}, - {1315, 3}, - {1314, 1}, - {1313, 0}, - {1313, 3}, - {1167, 1}, - {1167, 3}, - {1311, 0}, - {1311, 4}, - {1311, 4}, - {1009, 2}, + {1315, 4}, + {1315, 4}, + {1013, 2}, {765, 13}, {765, 9}, - {783, 10}, - {787, 1}, - {787, 1}, - {787, 2}, - {787, 2}, + {782, 10}, + {786, 1}, + {786, 1}, + {786, 2}, + {786, 2}, {839, 1}, - {1011, 4}, - {1013, 7}, - {1019, 6}, - {935, 0}, - {935, 1}, - {935, 2}, - {1021, 4}, - {1021, 6}, - {1020, 3}, - {1020, 5}, - {1015, 3}, - {1015, 5}, - {1018, 3}, - {1018, 5}, - {1018, 4}, + {1015, 4}, + {1017, 7}, + {1023, 6}, + {938, 0}, + {938, 1}, + {938, 2}, + {1025, 4}, + {1025, 6}, + {1024, 3}, + {1024, 5}, + {1019, 3}, + {1019, 5}, + {1022, 3}, + {1022, 5}, + {1022, 4}, {899, 0}, {899, 1}, {899, 1}, - {1128, 1}, - {1128, 1}, - {726, 0}, - {726, 1}, - {1023, 0}, - {1132, 2}, - {1132, 5}, - {1132, 3}, - {1132, 6}, - {1029, 1}, - {1029, 1}, - {1029, 1}, - {1028, 2}, - {1028, 3}, - {1028, 2}, - {1028, 4}, - {1028, 7}, - {1028, 5}, - {1028, 7}, - {1028, 5}, - {1028, 3}, - {1185, 1}, - {1185, 1}, - {1185, 1}, - {1185, 1}, - {1185, 1}, + {1132, 1}, + {1132, 1}, + {727, 0}, + {727, 1}, + {1027, 0}, + {1136, 2}, + {1136, 5}, + {1136, 3}, + {1136, 6}, + {1033, 1}, + {1033, 1}, + {1033, 1}, + {1032, 2}, + {1032, 3}, + {1032, 2}, + {1032, 4}, + {1032, 7}, + {1032, 5}, + {1032, 7}, + {1032, 5}, + {1032, 3}, + {1190, 1}, + {1190, 1}, + {1190, 1}, + {1190, 1}, + {1190, 1}, + {1190, 1}, + {982, 5}, + {982, 5}, + {983, 2}, + {983, 2}, + {983, 2}, {1185, 1}, - {979, 5}, - {979, 5}, - {980, 2}, - {980, 2}, - {980, 2}, - {1180, 1}, - {1180, 3}, + {1185, 3}, {886, 0}, {886, 2}, {883, 1}, @@ -4086,141 +4102,141 @@ var ( {885, 3}, {885, 3}, {734, 1}, - {751, 1}, - {725, 1}, + {755, 1}, + {724, 1}, {915, 1}, {915, 1}, {915, 1}, - {1075, 1}, - {1075, 1}, - {1075, 1}, - {1089, 3}, - {996, 8}, - {1121, 4}, - {1098, 4}, - {968, 6}, - {1012, 4}, - {1109, 5}, - {1205, 0}, - {1205, 2}, - {1204, 0}, - {1204, 3}, - {1238, 0}, - {1238, 1}, - {1026, 0}, - {1026, 1}, - {1026, 2}, - {1026, 2}, - {1026, 2}, - {1026, 2}, - {1207, 0}, - {1207, 3}, - {1207, 3}, - {722, 3}, - {722, 3}, - {722, 3}, - {722, 3}, - {722, 2}, - {722, 9}, - {722, 3}, - {722, 3}, - {722, 3}, - {722, 1}, + {1078, 1}, + {1078, 1}, + {1078, 1}, + {1092, 3}, + {1000, 8}, + {1125, 4}, + {1101, 4}, + {971, 6}, + {1016, 4}, + {1113, 5}, + {1210, 0}, + {1210, 2}, + {1209, 0}, + {1209, 3}, + {1242, 0}, + {1242, 1}, + {1030, 0}, + {1030, 1}, + {1030, 2}, + {1030, 2}, + {1030, 2}, + {1030, 2}, + {1212, 0}, + {1212, 3}, + {1212, 3}, + {723, 3}, + {723, 3}, + {723, 3}, + {723, 3}, + {723, 2}, + {723, 9}, + {723, 3}, + {723, 3}, + {723, 3}, + {723, 1}, {933, 1}, {933, 1}, - {1198, 0}, - {1198, 4}, - {1198, 7}, - {1198, 3}, - {1198, 3}, - {724, 1}, - {724, 1}, - {723, 1}, - {723, 1}, + {1203, 0}, + {1203, 4}, + {1203, 7}, + {1203, 3}, + {1203, 3}, + {726, 1}, + {726, 1}, + {725, 1}, + {725, 1}, {766, 1}, {766, 3}, - {1060, 1}, - {1060, 3}, - {815, 0}, - {815, 1}, - {1036, 0}, - {1036, 1}, - {1035, 1}, - {721, 3}, + {1065, 1}, + {1065, 3}, + {814, 0}, + {814, 1}, + {1040, 0}, + {1040, 1}, + {1039, 1}, + {722, 3}, + {722, 3}, + {722, 4}, + {722, 5}, + {722, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1177, 1}, + {1162, 1}, + {1162, 2}, + {1221, 1}, + {1221, 2}, + {1217, 1}, + {1217, 2}, + {1224, 1}, + {1224, 2}, + {1263, 1}, + {1263, 2}, + {1157, 1}, + {1157, 1}, + {1157, 1}, + {721, 5}, {721, 3}, - {721, 4}, {721, 5}, + {721, 4}, + {721, 3}, {721, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1172, 1}, - {1158, 1}, - {1158, 2}, - {1216, 1}, - {1216, 2}, - {1212, 1}, - {1212, 2}, - {1219, 1}, - {1219, 2}, - {1259, 1}, - {1259, 2}, - {1153, 1}, - {1153, 1}, - {1153, 1}, - {720, 5}, - {720, 3}, - {720, 5}, - {720, 4}, - {720, 3}, - {720, 1}, - {1093, 1}, - {1093, 1}, - {1218, 0}, - {1218, 2}, - {1030, 1}, - {1030, 3}, - {1030, 5}, - {1030, 2}, - {1189, 0}, - {1189, 1}, - {1188, 1}, - {1188, 2}, - {1188, 1}, - {1188, 2}, - {1191, 1}, - {1191, 3}, + {1096, 1}, + {1096, 1}, + {1223, 0}, + {1223, 2}, + {1034, 1}, + {1034, 3}, + {1034, 5}, + {1034, 2}, + {1194, 0}, + {1194, 1}, + {1193, 1}, + {1193, 2}, + {1193, 1}, + {1193, 2}, + {1196, 1}, + {1196, 3}, {927, 3}, - {1202, 0}, - {1202, 2}, - {1154, 0}, - {1154, 1}, + {1207, 0}, + {1207, 2}, + {1158, 0}, + {1158, 1}, {912, 3}, - {768, 0}, - {768, 2}, - {775, 0}, - {775, 3}, + {771, 0}, + {771, 2}, + {774, 0}, + {774, 3}, {844, 0}, {844, 1}, - {865, 0}, - {865, 1}, - {867, 0}, - {867, 2}, - {866, 3}, - {866, 1}, - {866, 3}, - {866, 2}, - {866, 1}, + {866, 0}, {866, 1}, + {868, 0}, + {868, 2}, + {867, 3}, + {867, 1}, + {867, 3}, + {867, 2}, + {867, 1}, + {867, 1}, {930, 1}, {930, 3}, {930, 3}, - {1211, 0}, - {1211, 1}, + {1216, 0}, + {1216, 1}, {847, 2}, {847, 2}, {893, 1}, @@ -4228,305 +4244,347 @@ var ( {893, 1}, {845, 1}, {845, 1}, - {653, 1}, - {653, 1}, - {653, 1}, - {653, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, - {656, 1}, + {654, 1}, + {654, 1}, + {654, 1}, + {654, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, + {657, 1}, {656, 1}, {656, 1}, {656, 1}, @@ -4605,524 +4663,485 @@ var ( {655, 1}, {655, 1}, {655, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {654, 1}, - {982, 2}, - {1257, 1}, - {1257, 3}, - {1257, 4}, - {1257, 6}, - {769, 9}, - {1048, 0}, - {1048, 1}, - {1047, 5}, - {1047, 4}, - {1047, 4}, - {1047, 4}, - {1047, 4}, - {1047, 2}, - {1047, 1}, - {1047, 1}, - {1047, 1}, - {1047, 1}, - {1047, 2}, - {962, 1}, - {962, 1}, - {960, 1}, - {960, 3}, - {829, 3}, - {1309, 0}, - {1309, 1}, - {1308, 3}, - {1308, 1}, - {788, 1}, - {788, 1}, - {990, 3}, - {1171, 0}, - {1171, 1}, - {1171, 3}, - {1235, 0}, - {1235, 5}, - {771, 6}, - {702, 1}, - {702, 1}, - {702, 1}, - {702, 1}, - {702, 1}, - {702, 1}, - {702, 1}, - {702, 2}, - {702, 1}, - {702, 1}, - {702, 2}, - {702, 2}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {655, 1}, + {986, 2}, + {1261, 1}, + {1261, 3}, + {1261, 4}, + {1261, 6}, + {767, 9}, + {1052, 0}, + {1052, 1}, + {1051, 5}, + {1051, 4}, + {1051, 4}, + {1051, 4}, + {1051, 4}, + {1051, 2}, + {1051, 1}, + {1051, 1}, + {1051, 1}, + {1051, 1}, + {1051, 2}, + {965, 1}, + {965, 1}, + {963, 1}, + {963, 3}, + {828, 3}, + {1313, 0}, + {1313, 1}, + {1312, 3}, + {1312, 1}, + {787, 1}, + {787, 1}, + {994, 3}, + {1176, 0}, + {1176, 1}, + {1176, 3}, + {1239, 0}, + {1239, 5}, + {768, 6}, + {703, 1}, + {703, 1}, + {703, 1}, + {703, 1}, + {703, 1}, + {703, 1}, {703, 1}, {703, 2}, - {1147, 1}, - {1147, 3}, - {970, 2}, - {756, 3}, + {703, 1}, + {703, 1}, + {703, 2}, + {703, 2}, + {704, 1}, + {704, 2}, + {1151, 1}, + {1151, 3}, + {973, 2}, + {757, 3}, {888, 1}, {888, 3}, {859, 1}, {859, 2}, - {1246, 1}, - {1246, 1}, - {934, 0}, - {934, 1}, - {934, 1}, - {801, 0}, - {801, 1}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 5}, - {719, 5}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 3}, - {719, 1}, - {701, 1}, - {701, 3}, - {701, 5}, - {714, 1}, - {714, 1}, - {714, 1}, - {714, 1}, - {714, 3}, - {714, 1}, - {714, 1}, - {714, 1}, - {714, 1}, - {714, 1}, - {714, 2}, - {714, 2}, - {714, 2}, - {714, 2}, - {714, 3}, - {714, 2}, - {714, 1}, - {714, 3}, - {714, 5}, - {714, 6}, - {714, 2}, - {714, 4}, - {714, 2}, - {714, 6}, - {714, 5}, - {714, 6}, - {714, 6}, - {714, 4}, - {714, 4}, - {714, 3}, - {714, 3}, - {774, 1}, - {774, 1}, - {777, 1}, - {777, 1}, - {806, 0}, - {806, 1}, - {921, 0}, - {921, 1}, - {804, 1}, - {804, 2}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {708, 1}, - {1074, 0}, - {1074, 2}, - {712, 1}, - {712, 1}, - {712, 1}, - {712, 1}, - {711, 1}, - {711, 1}, - {711, 1}, - {711, 1}, - {711, 1}, - {711, 1}, - {706, 4}, - {706, 4}, - {706, 2}, - {706, 3}, - {706, 2}, - {706, 4}, - {706, 6}, - {706, 2}, - {706, 2}, - {706, 2}, - {706, 4}, - {706, 6}, - {706, 4}, - {707, 4}, - {707, 4}, - {707, 6}, - {707, 8}, - {707, 8}, - {707, 6}, - {707, 6}, - {707, 6}, - {707, 6}, - {707, 6}, - {707, 8}, - {707, 8}, - {707, 8}, - {707, 8}, - {707, 4}, - {707, 6}, - {707, 6}, - {707, 7}, - {707, 4}, - {707, 7}, - {707, 7}, - {707, 1}, - {707, 8}, - {1200, 1}, - {1200, 1}, - {1200, 1}, - {1200, 1}, - {709, 1}, - {709, 1}, - {710, 1}, - {710, 1}, - {1303, 1}, - {1303, 1}, - {1303, 1}, - {713, 4}, - {713, 6}, - {713, 1}, - {715, 6}, - {715, 4}, - {715, 4}, - {715, 5}, - {715, 6}, - {715, 5}, - {715, 6}, + {1250, 1}, + {1250, 1}, + {937, 0}, + {937, 1}, + {937, 1}, + {800, 0}, + {800, 1}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 5}, + {720, 5}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 3}, + {720, 1}, + {702, 1}, + {702, 3}, + {702, 5}, + {715, 1}, + {715, 1}, + {715, 1}, + {715, 1}, + {715, 3}, + {715, 1}, + {715, 1}, + {715, 1}, + {715, 1}, + {715, 1}, + {715, 2}, + {715, 2}, + {715, 2}, + {715, 2}, + {715, 3}, + {715, 2}, + {715, 1}, + {715, 3}, {715, 5}, {715, 6}, - {715, 5}, + {715, 2}, + {715, 4}, + {715, 2}, {715, 6}, {715, 5}, - {715, 5}, - {715, 8}, - {715, 6}, - {715, 6}, {715, 6}, {715, 6}, - {715, 6}, - {715, 6}, - {715, 6}, - {715, 5}, - {715, 6}, - {715, 7}, - {715, 8}, - {715, 8}, - {715, 9}, - {1241, 0}, - {1241, 2}, - {705, 4}, - {705, 6}, - {1199, 0}, - {1199, 2}, - {1199, 3}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {819, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {796, 1}, - {1186, 0}, - {1186, 1}, - {1318, 1}, - {1318, 2}, - {1139, 4}, - {1183, 0}, - {1183, 2}, - {983, 2}, - {983, 3}, - {983, 1}, - {983, 1}, - {983, 2}, - {983, 2}, - {983, 2}, - {983, 2}, - {983, 2}, - {983, 1}, - {983, 1}, - {983, 2}, - {983, 1}, - {827, 1}, - {827, 1}, - {827, 1}, - {874, 0}, - {874, 1}, - {727, 1}, - {727, 3}, - {786, 1}, - {786, 3}, + {715, 4}, + {715, 4}, + {715, 3}, + {715, 3}, + {773, 1}, + {773, 1}, + {776, 1}, + {776, 1}, + {805, 0}, + {805, 1}, + {921, 0}, + {921, 1}, + {803, 1}, + {803, 2}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {709, 1}, + {1077, 0}, + {1077, 2}, + {713, 1}, + {713, 1}, + {713, 1}, + {713, 1}, + {712, 1}, + {712, 1}, + {712, 1}, + {712, 1}, + {712, 1}, + {712, 1}, + {707, 4}, + {707, 4}, + {707, 2}, + {707, 3}, + {707, 2}, + {707, 4}, + {707, 6}, + {707, 2}, + {707, 2}, + {707, 2}, + {707, 4}, + {707, 6}, + {707, 4}, + {708, 4}, + {708, 4}, + {708, 6}, + {708, 8}, + {708, 8}, + {708, 6}, + {708, 6}, + {708, 6}, + {708, 6}, + {708, 6}, + {708, 8}, + {708, 8}, + {708, 8}, + {708, 8}, + {708, 4}, + {708, 6}, + {708, 6}, + {708, 7}, + {708, 4}, + {708, 7}, + {708, 7}, + {708, 1}, + {708, 8}, + {1205, 1}, + {1205, 1}, + {1205, 1}, + {1205, 1}, + {710, 1}, + {710, 1}, + {711, 1}, + {711, 1}, + {1307, 1}, + {1307, 1}, + {1307, 1}, + {714, 4}, + {714, 6}, + {714, 1}, + {716, 6}, + {716, 4}, + {716, 4}, + {716, 5}, + {716, 6}, + {716, 5}, + {716, 6}, + {716, 5}, + {716, 6}, + {716, 5}, + {716, 6}, + {716, 5}, + {716, 5}, + {716, 8}, + {716, 6}, + {716, 6}, + {716, 6}, + {716, 6}, + {716, 6}, + {716, 6}, + {716, 6}, + {716, 5}, + {716, 6}, + {716, 7}, + {716, 8}, + {716, 8}, + {716, 9}, + {1245, 0}, + {1245, 2}, + {706, 4}, + {706, 6}, + {1204, 0}, + {1204, 2}, + {1204, 3}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {795, 1}, + {1191, 0}, + {1191, 1}, + {1322, 1}, + {1322, 2}, + {1143, 4}, + {1188, 0}, + {1188, 2}, + {987, 2}, + {987, 3}, + {987, 1}, + {987, 1}, + {987, 2}, + {987, 2}, + {987, 2}, + {987, 2}, + {987, 2}, + {987, 1}, + {987, 1}, + {987, 2}, + {987, 1}, + {826, 1}, + {826, 1}, + {826, 1}, + {875, 0}, + {875, 1}, + {728, 1}, + {728, 3}, + {785, 1}, + {785, 3}, {905, 2}, {905, 4}, - {952, 1}, - {952, 3}, + {955, 1}, + {955, 3}, {895, 0}, {895, 2}, - {1090, 0}, - {1090, 1}, - {1087, 4}, - {1256, 1}, - {1256, 1}, - {1027, 2}, - {1027, 4}, - {1306, 1}, - {1306, 3}, - {1006, 3}, - {1007, 1}, - {1007, 1}, + {1093, 0}, + {1093, 1}, + {1090, 4}, + {1260, 1}, + {1260, 1}, + {1031, 2}, + {1031, 4}, + {1310, 1}, + {1310, 3}, + {1010, 3}, + {1011, 1}, + {1011, 1}, {852, 1}, {852, 2}, - {991, 4}, - {991, 4}, - {991, 5}, - {991, 2}, - {991, 3}, - {991, 1}, - {991, 2}, - {1113, 1}, - {1097, 1}, - {1042, 2}, - {742, 3}, + {995, 4}, + {995, 4}, + {995, 5}, + {995, 2}, + {995, 3}, + {995, 1}, + {995, 2}, + {1117, 1}, + {1100, 1}, + {1046, 2}, {743, 3}, - {744, 7}, - {1298, 0}, - {1298, 7}, - {1298, 5}, - {1297, 0}, - {1297, 1}, - {1297, 1}, - {1297, 1}, - {1299, 0}, - {1299, 1}, - {1299, 1}, - {1096, 0}, - {1096, 4}, - {741, 7}, - {741, 6}, - {741, 5}, - {741, 6}, - {741, 6}, - {752, 2}, + {744, 3}, + {745, 7}, + {1302, 0}, + {1302, 7}, + {1302, 5}, + {1301, 0}, + {1301, 1}, + {1301, 1}, + {1301, 1}, + {1303, 0}, + {1303, 1}, + {1303, 1}, + {1099, 0}, + {1099, 4}, + {742, 7}, + {742, 6}, + {742, 5}, + {742, 6}, + {742, 6}, + {750, 2}, + {750, 2}, {752, 2}, - {754, 2}, - {754, 3}, - {1144, 3}, - {1144, 1}, + {752, 3}, + {1148, 3}, + {1148, 1}, {918, 4}, - {1197, 2}, - {1319, 0}, - {1319, 2}, - {1320, 1}, - {1320, 3}, - {1140, 3}, + {1202, 2}, + {1323, 0}, + {1323, 2}, + {1324, 1}, + {1324, 3}, + {1144, 3}, {911, 1}, - {1142, 3}, + {1146, 3}, + {1329, 4}, + {1243, 0}, + {1243, 1}, + {1246, 0}, + {1246, 3}, + {1249, 0}, + {1249, 3}, + {1248, 0}, + {1248, 2}, + {1327, 1}, + {1327, 1}, + {1327, 1}, + {1326, 1}, + {1326, 1}, + {967, 2}, + {967, 2}, + {967, 2}, + {967, 4}, + {967, 2}, {1325, 4}, - {1239, 0}, - {1239, 1}, - {1242, 0}, - {1242, 3}, - {1245, 0}, - {1245, 3}, + {1145, 1}, + {1145, 2}, + {1145, 2}, + {1145, 2}, + {1145, 4}, + {756, 0}, + {756, 1}, + {738, 2}, + {1328, 1}, + {1328, 1}, + {719, 4}, + {719, 4}, + {719, 4}, + {719, 4}, + {719, 4}, + {719, 5}, + {719, 7}, + {719, 7}, + {719, 6}, + {719, 6}, + {719, 9}, + {1079, 0}, + {1079, 3}, + {1079, 3}, + {1080, 0}, + {1080, 2}, + {873, 0}, + {873, 2}, + {873, 2}, {1244, 0}, {1244, 2}, - {1323, 1}, - {1323, 1}, - {1323, 1}, - {1322, 1}, - {1322, 1}, - {964, 2}, - {964, 2}, - {964, 2}, - {964, 4}, - {964, 2}, - {1321, 4}, - {1141, 1}, - {1141, 2}, - {1141, 2}, - {1141, 2}, - {1141, 4}, - {755, 0}, - {755, 1}, - {737, 2}, - {1324, 1}, - {1324, 1}, - {718, 4}, - {718, 4}, - {718, 4}, - {718, 4}, - {718, 4}, - {718, 5}, - {718, 7}, - {718, 7}, - {718, 6}, - {718, 6}, - {718, 9}, - {1076, 0}, - {1076, 3}, - {1076, 3}, - {1077, 0}, - {1077, 2}, - {872, 0}, - {872, 2}, - {872, 2}, - {1240, 0}, - {1240, 2}, - {1240, 2}, - {1296, 1}, - {877, 1}, - {877, 3}, + {1244, 2}, + {1300, 1}, + {878, 1}, + {878, 3}, {840, 1}, {840, 4}, - {793, 1}, - {793, 1}, - {792, 6}, - {792, 2}, - {792, 3}, + {792, 1}, + {792, 1}, + {791, 6}, + {791, 2}, + {791, 3}, {849, 0}, {849, 4}, {904, 0}, @@ -5132,112 +5151,112 @@ var ( {929, 2}, {929, 2}, {929, 2}, - {1208, 0}, - {1208, 2}, - {1208, 3}, - {1208, 3}, + {1213, 0}, + {1213, 2}, + {1213, 3}, + {1213, 3}, {928, 5}, {846, 0}, {846, 1}, {846, 3}, {846, 1}, {846, 3}, - {1044, 1}, - {1044, 2}, - {1045, 0}, - {1045, 1}, - {789, 3}, - {789, 5}, - {789, 7}, - {789, 7}, - {789, 9}, - {789, 4}, - {789, 6}, - {789, 3}, - {789, 5}, - {807, 1}, - {807, 1}, - {1078, 0}, - {1078, 1}, - {813, 1}, - {813, 2}, - {813, 2}, - {1053, 0}, - {1053, 2}, - {869, 1}, - {869, 1}, - {1263, 1}, - {1263, 1}, - {1192, 1}, + {1048, 1}, + {1048, 2}, + {1049, 0}, + {1049, 1}, + {788, 3}, + {788, 5}, + {788, 7}, + {788, 7}, + {788, 9}, + {788, 4}, + {788, 6}, + {788, 3}, + {788, 5}, + {806, 1}, + {806, 1}, + {1081, 0}, + {1081, 1}, + {812, 1}, + {812, 2}, + {812, 2}, + {1057, 0}, + {1057, 2}, + {870, 1}, + {870, 1}, + {1267, 1}, + {1267, 1}, + {1197, 1}, + {1197, 1}, + {1192, 0}, {1192, 1}, - {1187, 0}, - {1187, 1}, - {757, 2}, - {757, 4}, - {757, 4}, - {757, 5}, - {818, 0}, - {818, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1104, 1}, - {1265, 0}, - {1265, 1}, - {1266, 2}, - {1266, 1}, + {758, 2}, + {758, 4}, + {758, 4}, + {758, 5}, + {817, 0}, + {817, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1107, 1}, + {1269, 0}, + {1269, 1}, + {1270, 2}, + {1270, 1}, {855, 1}, {906, 0}, {906, 1}, - {1105, 1}, - {1105, 1}, - {1264, 1}, - {950, 0}, - {950, 1}, + {1108, 1}, + {1108, 1}, + {1268, 1}, + {953, 0}, + {953, 1}, + {877, 0}, + {877, 5}, + {700, 3}, + {700, 3}, + {700, 3}, + {700, 3}, {876, 0}, + {876, 3}, + {876, 3}, + {876, 4}, {876, 5}, - {699, 3}, - {699, 3}, - {699, 3}, - {699, 3}, - {875, 0}, - {875, 3}, - {875, 3}, - {875, 4}, - {875, 5}, - {875, 4}, - {875, 5}, - {875, 5}, - {875, 4}, - {1067, 0}, - {1067, 2}, - {753, 1}, - {753, 1}, - {753, 2}, - {753, 2}, - {748, 3}, + {876, 4}, + {876, 5}, + {876, 5}, + {876, 4}, + {1070, 0}, + {1070, 2}, + {751, 1}, + {751, 1}, + {751, 2}, + {751, 2}, + {749, 3}, + {749, 3}, + {748, 4}, + {748, 4}, + {748, 5}, + {748, 2}, + {748, 2}, {748, 3}, - {747, 4}, - {747, 4}, - {747, 5}, - {747, 2}, - {747, 2}, + {747, 1}, {747, 3}, {746, 1}, - {746, 3}, - {745, 1}, - {745, 1}, - {1268, 2}, - {1268, 2}, - {1268, 2}, - {951, 1}, - {984, 9}, - {984, 9}, + {746, 1}, + {1272, 2}, + {1272, 2}, + {1272, 2}, + {954, 1}, + {988, 9}, + {988, 9}, {853, 2}, {853, 4}, {853, 6}, @@ -5246,321 +5265,323 @@ var ( {853, 3}, {853, 6}, {853, 6}, - {1108, 3}, - {1107, 6}, - {1106, 1}, - {1106, 1}, - {1106, 1}, - {1269, 3}, - {1269, 1}, - {1269, 1}, - {956, 1}, - {956, 3}, + {1112, 3}, + {1111, 6}, + {1110, 1}, + {1110, 1}, + {1110, 1}, + {1273, 3}, + {1273, 1}, + {1273, 1}, + {959, 1}, + {959, 3}, {909, 3}, {909, 2}, {909, 2}, {909, 3}, - {1215, 2}, - {1215, 2}, - {1215, 2}, - {1215, 1}, - {830, 1}, - {830, 1}, - {830, 1}, - {814, 1}, - {814, 1}, - {820, 1}, - {820, 3}, + {1220, 2}, + {1220, 2}, + {1220, 2}, + {1220, 1}, + {829, 1}, + {829, 1}, + {829, 1}, + {813, 1}, + {813, 1}, + {819, 1}, + {819, 3}, {890, 1}, {890, 3}, {890, 3}, - {963, 3}, - {963, 4}, - {963, 4}, - {963, 4}, - {963, 3}, - {963, 3}, - {963, 2}, - {963, 4}, - {963, 4}, - {963, 2}, - {963, 2}, - {1163, 1}, - {1163, 1}, - {797, 1}, - {797, 1}, + {966, 3}, + {966, 4}, + {966, 4}, + {966, 4}, + {966, 3}, + {966, 3}, + {966, 2}, + {966, 4}, + {966, 4}, + {966, 2}, + {966, 2}, + {1168, 1}, + {1168, 1}, + {796, 1}, + {796, 1}, {860, 1}, {860, 1}, - {1138, 1}, - {1138, 3}, - {717, 1}, + {1142, 1}, + {1142, 3}, + {718, 1}, + {718, 1}, {717, 1}, - {716, 1}, - {700, 1}, - {763, 1}, - {763, 3}, - {763, 2}, - {763, 2}, + {701, 1}, + {764, 1}, + {764, 3}, + {764, 2}, + {764, 2}, {856, 1}, {856, 3}, - {1082, 1}, - {1082, 4}, - {880, 1}, - {811, 1}, - {811, 1}, - {791, 3}, - {791, 2}, - {948, 1}, - {948, 1}, + {1085, 1}, + {1085, 4}, + {881, 1}, {810, 1}, {810, 1}, + {790, 3}, + {790, 2}, + {951, 1}, + {951, 1}, + {809, 1}, + {809, 1}, {851, 1}, {851, 3}, - {965, 3}, - {965, 5}, - {965, 6}, - {965, 4}, - {965, 4}, - {965, 5}, - {965, 5}, - {965, 5}, - {965, 6}, - {965, 4}, - {965, 5}, - {965, 6}, - {965, 4}, - {965, 3}, - {965, 3}, - {965, 4}, - {965, 4}, - {965, 5}, - {965, 5}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 3}, - {965, 4}, - {1146, 2}, - {1146, 2}, - {1146, 3}, - {1146, 3}, - {1201, 1}, - {1201, 3}, - {1040, 5}, - {1064, 1}, - {1064, 3}, - {1111, 3}, - {1111, 4}, - {1111, 4}, - {1111, 5}, - {1111, 4}, - {1111, 5}, - {1111, 4}, - {1111, 4}, - {1111, 6}, - {1111, 4}, - {1111, 8}, - {1111, 2}, - {1111, 5}, - {1111, 3}, - {1111, 3}, - {1111, 2}, - {1111, 5}, - {1111, 2}, - {1111, 2}, - {1111, 4}, - {1272, 2}, - {1272, 2}, - {1272, 4}, - {1275, 0}, - {1275, 1}, - {1274, 1}, - {1274, 3}, - {1110, 1}, - {1110, 1}, - {1110, 2}, - {1110, 2}, - {1110, 2}, - {1110, 1}, - {1110, 1}, - {1110, 1}, - {1110, 1}, - {1273, 0}, - {1273, 3}, - {1307, 0}, - {1307, 2}, - {1270, 1}, - {1270, 1}, - {1270, 1}, - {795, 1}, - {795, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 3}, - {1276, 3}, - {1276, 3}, - {1276, 3}, - {1276, 5}, - {1276, 4}, - {1276, 5}, - {1276, 1}, - {1276, 1}, - {1276, 2}, - {1276, 2}, - {1276, 2}, - {1276, 1}, - {1276, 2}, - {1276, 2}, - {1276, 2}, - {1276, 2}, - {1276, 2}, - {1276, 2}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, + {968, 3}, + {968, 5}, + {968, 6}, + {968, 4}, + {968, 4}, + {968, 5}, + {968, 5}, + {968, 5}, + {968, 6}, + {968, 4}, + {968, 5}, + {968, 6}, + {968, 4}, + {968, 3}, + {968, 3}, + {968, 4}, + {968, 4}, + {968, 5}, + {968, 5}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 3}, + {968, 4}, + {1150, 2}, + {1150, 2}, + {1150, 3}, + {1150, 3}, + {1206, 1}, + {1206, 3}, + {1044, 5}, + {1067, 1}, + {1067, 3}, + {1115, 3}, + {1115, 4}, + {1115, 4}, + {1115, 5}, + {1115, 4}, + {1115, 5}, + {1115, 4}, + {1115, 4}, + {1115, 6}, + {1115, 4}, + {1115, 8}, + {1115, 2}, + {1115, 5}, + {1115, 3}, + {1115, 3}, + {1115, 2}, + {1115, 5}, + {1115, 2}, + {1115, 2}, + {1115, 4}, {1276, 2}, - {1276, 1}, - {1276, 1}, - {1276, 1}, - {1276, 1}, {1276, 2}, - {1271, 0}, - {1271, 2}, - {1271, 2}, + {1276, 4}, + {1279, 0}, + {1279, 1}, + {1278, 1}, + {1278, 3}, + {1114, 1}, + {1114, 1}, + {1114, 2}, + {1114, 2}, + {1114, 2}, + {1114, 1}, + {1114, 1}, + {1114, 1}, + {1114, 1}, + {1277, 0}, + {1277, 3}, + {1311, 0}, + {1311, 2}, + {1274, 1}, + {1274, 1}, + {1274, 1}, + {794, 1}, + {794, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 3}, + {1280, 3}, + {1280, 3}, + {1280, 3}, + {1280, 5}, + {1280, 4}, + {1280, 5}, + {1280, 1}, + {1280, 1}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 1}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 2}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 2}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 1}, + {1280, 2}, + {1275, 0}, + {1275, 2}, + {1275, 2}, {926, 0}, {926, 1}, {926, 1}, - {1284, 0}, - {1284, 1}, - {1284, 1}, - {1284, 1}, - {1072, 0}, - {1072, 1}, - {831, 0}, - {831, 2}, - {1112, 2}, - {1034, 3}, - {940, 1}, - {940, 3}, - {1196, 1}, - {1196, 1}, - {1196, 3}, - {1196, 1}, - {1196, 2}, - {1196, 3}, - {1196, 1}, - {1226, 0}, - {1226, 1}, - {1226, 1}, - {1226, 1}, - {1226, 1}, - {1226, 1}, - {826, 0}, - {826, 1}, - {826, 1}, - {1127, 0}, - {1127, 1}, - {954, 0}, - {954, 2}, - {1326, 0}, - {1326, 3}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, - {1117, 1}, + {1288, 0}, + {1288, 1}, + {1288, 1}, + {1288, 1}, + {1075, 0}, + {1075, 1}, + {830, 0}, + {830, 2}, + {1116, 2}, + {1038, 3}, + {943, 1}, + {943, 3}, + {1201, 1}, + {1201, 1}, + {1201, 3}, + {1201, 1}, + {1201, 2}, + {1201, 3}, + {1201, 1}, + {1230, 0}, + {1230, 1}, + {1230, 1}, + {1230, 1}, + {1230, 1}, + {1230, 1}, + {825, 0}, + {825, 1}, + {825, 1}, + {1131, 0}, + {1131, 1}, + {957, 0}, + {957, 2}, + {1330, 0}, + {1330, 3}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, + {1121, 1}, {908, 1}, {908, 1}, {908, 1}, @@ -5583,395 +5604,397 @@ var ( {841, 1}, {841, 1}, {841, 1}, - {1283, 1}, - {1283, 3}, + {1287, 1}, + {1287, 3}, {891, 2}, - {985, 1}, - {985, 1}, - {953, 1}, - {953, 1}, - {1125, 1}, - {1125, 3}, - {1294, 0}, - {1294, 3}, - {832, 1}, - {832, 4}, - {832, 4}, - {832, 4}, - {832, 3}, - {832, 4}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 1}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 3}, - {832, 2}, - {832, 2}, - {832, 3}, - {832, 3}, - {832, 5}, - {832, 3}, - {824, 0}, - {824, 1}, - {1119, 1}, - {1119, 1}, - {1002, 0}, - {1002, 1}, - {907, 1}, - {907, 2}, - {907, 3}, - {1243, 0}, - {1243, 1}, - {1133, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {828, 3}, - {1304, 1}, - {1304, 1}, - {1304, 1}, - {1232, 3}, - {1232, 2}, - {1232, 3}, - {1232, 3}, - {1232, 2}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1214, 1}, - {1161, 1}, - {1161, 1}, - {1073, 0}, - {1073, 1}, - {1073, 1}, - {1193, 1}, - {1193, 1}, - {1193, 1}, - {1195, 1}, - {1195, 1}, - {1195, 1}, - {1195, 2}, - {1159, 1}, - {1289, 3}, - {1289, 2}, - {1289, 3}, - {1289, 2}, - {1289, 3}, - {1289, 3}, - {1289, 2}, - {1289, 2}, - {1289, 1}, - {1289, 2}, - {1289, 5}, - {1289, 5}, - {1289, 1}, - {1289, 3}, - {1289, 2}, + {989, 1}, + {989, 1}, + {956, 1}, + {956, 1}, + {1129, 1}, + {1129, 3}, + {1298, 0}, + {1298, 3}, + {831, 1}, + {831, 4}, + {831, 4}, + {831, 4}, + {831, 3}, + {831, 4}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 1}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 3}, + {831, 2}, + {831, 2}, + {831, 3}, + {831, 3}, + {831, 5}, + {831, 3}, + {823, 0}, + {823, 1}, + {1123, 1}, + {1123, 1}, + {1006, 0}, + {1006, 1}, + {907, 1}, + {907, 2}, + {907, 3}, + {1247, 0}, + {1247, 1}, + {1137, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {827, 3}, + {1308, 1}, + {1308, 1}, + {1308, 1}, + {1236, 3}, + {1236, 2}, + {1236, 3}, + {1236, 3}, + {1236, 2}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1219, 1}, + {1166, 1}, + {1166, 1}, + {1076, 0}, + {1076, 1}, + {1076, 1}, + {1198, 1}, + {1198, 1}, + {1198, 1}, + {1200, 1}, + {1200, 1}, + {1200, 1}, + {1200, 2}, + {1164, 1}, + {1293, 3}, + {1293, 2}, + {1293, 3}, + {1293, 2}, + {1293, 3}, + {1293, 3}, + {1293, 2}, + {1293, 2}, + {1293, 1}, + {1293, 2}, + {1293, 5}, + {1293, 5}, + {1293, 1}, + {1293, 3}, + {1293, 2}, {889, 1}, {889, 1}, - {1231, 1}, - {1231, 2}, - {1231, 2}, - {1137, 2}, - {1137, 2}, - {1137, 1}, - {1137, 1}, - {1233, 2}, - {1233, 2}, - {1233, 1}, - {1233, 2}, - {1233, 2}, - {1233, 3}, - {1233, 3}, - {1233, 2}, - {1329, 1}, - {1329, 1}, - {1160, 1}, - {1160, 2}, - {1160, 1}, - {1160, 1}, - {1160, 2}, - {1301, 1}, - {1301, 2}, - {1301, 1}, - {1301, 1}, - {871, 1}, - {871, 1}, - {871, 1}, - {871, 1}, - {1179, 1}, - {1179, 2}, - {1179, 2}, - {1179, 2}, - {1179, 3}, - {750, 3}, - {776, 0}, - {776, 1}, - {862, 1}, - {862, 1}, - {862, 1}, - {863, 0}, - {863, 2}, + {1235, 1}, + {1235, 2}, + {1235, 2}, + {1141, 2}, + {1141, 2}, + {1141, 1}, + {1141, 1}, + {1237, 2}, + {1237, 2}, + {1237, 1}, + {1237, 2}, + {1237, 2}, + {1237, 3}, + {1237, 3}, + {1237, 2}, + {1333, 1}, + {1333, 1}, + {1165, 1}, + {1165, 2}, + {1165, 1}, + {1165, 1}, + {1165, 2}, + {1305, 1}, + {1305, 2}, + {1305, 1}, + {1305, 1}, + {872, 1}, + {872, 1}, + {872, 1}, + {872, 1}, + {1184, 1}, + {1184, 2}, + {1184, 2}, + {1184, 2}, + {1184, 3}, + {754, 3}, + {775, 0}, + {775, 1}, + {863, 1}, + {863, 1}, + {863, 1}, + {864, 0}, + {864, 2}, {892, 0}, {892, 1}, {892, 1}, {897, 5}, - {1236, 0}, - {1236, 1}, - {790, 0}, - {790, 2}, - {790, 3}, - {1237, 0}, - {1237, 2}, + {1240, 0}, + {1240, 1}, + {789, 0}, + {789, 2}, + {789, 3}, + {1241, 0}, + {1241, 2}, {762, 2}, {762, 1}, {762, 2}, - {1071, 0}, - {1071, 2}, - {1287, 1}, - {1287, 3}, - {955, 1}, - {955, 1}, - {955, 1}, - {1131, 1}, - {1131, 3}, - {728, 1}, - {728, 1}, - {1288, 1}, - {1288, 1}, - {1288, 1}, - {773, 1}, - {773, 2}, - {764, 10}, - {764, 8}, - {1136, 2}, - {780, 2}, - {781, 0}, - {781, 1}, - {1334, 0}, - {1334, 1}, - {1003, 7}, - {999, 4}, - {975, 7}, - {975, 9}, - {969, 3}, - {1213, 2}, - {1213, 6}, - {878, 2}, + {1074, 0}, + {1074, 2}, + {1291, 1}, + {1291, 3}, + {958, 1}, + {958, 1}, + {958, 1}, + {1135, 1}, + {1135, 3}, + {729, 1}, + {729, 1}, + {1292, 1}, + {1292, 1}, + {1292, 1}, + {769, 1}, + {769, 2}, + {763, 10}, + {763, 8}, + {1140, 2}, + {779, 2}, + {780, 0}, + {780, 1}, + {1338, 0}, + {1338, 1}, + {1007, 7}, + {1003, 4}, + {978, 7}, + {978, 9}, + {972, 3}, + {1218, 2}, + {1218, 6}, + {879, 2}, {910, 1}, {910, 3}, - {993, 0}, - {993, 2}, - {1173, 1}, - {1173, 2}, - {992, 2}, - {992, 2}, - {992, 2}, - {992, 2}, - {946, 0}, - {946, 1}, - {945, 2}, - {945, 2}, - {945, 2}, - {945, 2}, - {1261, 1}, - {1261, 3}, - {1261, 2}, - {947, 2}, - {947, 2}, - {947, 2}, - {947, 2}, - {1084, 0}, - {1084, 1}, - {1083, 1}, - {1083, 2}, - {939, 2}, - {939, 2}, - {939, 1}, - {939, 4}, - {939, 2}, - {939, 2}, - {938, 3}, - {1165, 0}, - {1156, 0}, - {1156, 3}, - {1156, 3}, - {1156, 5}, - {1156, 5}, - {1156, 4}, - {1157, 1}, - {1041, 1}, - {1041, 1}, - {1103, 1}, - {1262, 1}, - {1262, 3}, - {881, 1}, - {881, 1}, - {881, 1}, - {881, 1}, - {881, 1}, - {881, 1}, - {881, 1}, - {881, 1}, - {994, 7}, - {1010, 5}, - {1010, 7}, - {1039, 9}, - {1037, 7}, - {1038, 4}, - {1143, 0}, - {1143, 3}, - {1143, 3}, - {1143, 3}, - {1143, 3}, - {1143, 3}, - {924, 1}, - {924, 2}, - {949, 1}, - {949, 1}, + {997, 0}, + {997, 2}, + {1178, 1}, + {1178, 2}, + {996, 2}, + {996, 2}, + {996, 2}, + {996, 2}, + {949, 0}, {949, 1}, - {949, 3}, - {949, 3}, - {1102, 1}, - {1102, 3}, + {948, 2}, + {948, 2}, + {948, 2}, + {948, 2}, + {1265, 1}, + {1265, 3}, + {1265, 2}, + {950, 2}, + {950, 2}, + {950, 2}, + {950, 2}, + {1087, 0}, + {1087, 1}, + {1086, 1}, + {1086, 2}, + {942, 2}, + {942, 2}, {942, 1}, {942, 4}, - {943, 1}, - {943, 2}, - {943, 1}, - {943, 1}, - {943, 2}, - {943, 2}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 2}, - {943, 1}, - {943, 2}, - {943, 1}, - {943, 2}, - {943, 2}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 1}, - {943, 3}, - {943, 2}, - {943, 2}, - {943, 2}, - {943, 2}, - {943, 2}, - {943, 2}, - {943, 2}, - {943, 1}, - {943, 1}, - {1065, 0}, - {1065, 1}, - {1065, 1}, - {1065, 1}, - {1088, 1}, - {1088, 3}, - {1088, 3}, - {1088, 3}, - {1088, 1}, - {1101, 7}, - {1100, 4}, + {942, 2}, + {942, 2}, + {941, 3}, + {1170, 0}, + {1160, 0}, + {1160, 3}, + {1160, 3}, + {1160, 5}, + {1160, 5}, + {1160, 4}, + {1161, 1}, + {1045, 1}, + {1045, 1}, + {1106, 1}, + {1266, 1}, + {1266, 3}, + {834, 1}, + {834, 1}, + {834, 1}, + {834, 1}, + {834, 1}, + {834, 1}, + {834, 1}, + {834, 1}, + {998, 7}, + {1014, 5}, + {1014, 7}, + {1109, 5}, + {1109, 7}, + {1043, 9}, + {1041, 7}, + {1042, 4}, + {1147, 0}, + {1147, 3}, + {1147, 3}, + {1147, 3}, + {1147, 3}, + {1147, 3}, + {924, 1}, + {924, 2}, + {952, 1}, + {952, 1}, + {952, 1}, + {952, 3}, + {952, 3}, + {1105, 1}, + {1105, 3}, + {945, 1}, + {945, 4}, + {946, 1}, + {946, 2}, + {946, 1}, + {946, 1}, + {946, 2}, + {946, 2}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 2}, + {946, 1}, + {946, 2}, + {946, 1}, + {946, 2}, + {946, 2}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 1}, + {946, 3}, + {946, 2}, + {946, 2}, + {946, 2}, + {946, 2}, + {946, 2}, + {946, 2}, + {946, 2}, + {946, 1}, + {946, 1}, + {1068, 0}, + {1068, 1}, + {1068, 1}, + {1068, 1}, + {1091, 1}, + {1091, 3}, + {1091, 3}, + {1091, 3}, + {1091, 1}, + {1104, 7}, + {1103, 4}, {848, 15}, - {1206, 0}, - {1206, 3}, - {1164, 0}, - {1164, 3}, - {1058, 0}, - {1058, 1}, - {1032, 0}, - {1032, 2}, - {823, 1}, - {823, 1}, - {1190, 2}, - {1190, 1}, - {1031, 3}, - {1031, 4}, - {1031, 3}, - {1031, 3}, + {1211, 0}, + {1211, 3}, + {1169, 0}, + {1169, 3}, + {1062, 0}, + {1062, 1}, + {1036, 0}, + {1036, 2}, + {822, 1}, + {822, 1}, + {1195, 2}, + {1195, 1}, + {1035, 3}, + {1035, 4}, + {1035, 3}, + {1035, 3}, {842, 1}, {842, 1}, {842, 1}, {932, 0}, {932, 3}, - {1281, 0}, - {1281, 3}, - {1221, 0}, - {1221, 3}, - {1223, 0}, - {1223, 2}, - {1222, 3}, - {1222, 1}, + {1285, 0}, + {1285, 3}, + {1226, 0}, + {1226, 3}, + {1228, 0}, + {1228, 2}, + {1227, 3}, + {1227, 1}, + {1060, 3}, + {1138, 2}, + {1064, 3}, + {1133, 1}, + {1133, 1}, + {1130, 2}, + {1229, 1}, + {1229, 2}, + {1229, 1}, + {1229, 2}, + {1299, 1}, + {1299, 3}, + {1056, 2}, {1056, 3}, - {1134, 2}, - {1059, 3}, - {1129, 1}, - {1129, 1}, - {1126, 2}, - {1225, 1}, - {1225, 2}, - {1225, 1}, - {1225, 2}, - {1295, 1}, - {1295, 3}, - {1052, 2}, - {1052, 3}, - {1052, 3}, - {1051, 1}, - {1051, 2}, - {1057, 3}, - {1014, 5}, - {998, 7}, - {971, 6}, - {1000, 6}, - {1175, 0}, - {1175, 1}, - {1267, 1}, - {1267, 2}, + {1056, 3}, + {1055, 1}, + {1055, 2}, + {1061, 3}, + {1018, 5}, + {1002, 7}, + {974, 6}, + {1004, 6}, + {1180, 0}, + {1180, 1}, + {1271, 1}, + {1271, 2}, {901, 3}, {901, 3}, {901, 3}, @@ -5988,5046 +6011,5067 @@ var ( {901, 1}, {901, 1}, {901, 2}, - {803, 1}, - {803, 2}, - {803, 2}, - {1016, 4}, - {973, 5}, - {1148, 1}, - {1148, 2}, - {972, 1}, - {972, 1}, - {972, 3}, - {972, 3}, - {1043, 8}, - {1230, 0}, - {1230, 2}, - {1229, 0}, - {1229, 3}, - {1254, 0}, - {1254, 2}, - {1253, 0}, - {1253, 2}, - {1024, 1}, - {961, 1}, - {961, 3}, + {802, 1}, + {802, 2}, + {802, 2}, + {1020, 4}, + {976, 5}, + {1152, 1}, + {1152, 2}, + {975, 1}, + {975, 1}, + {975, 3}, + {975, 3}, + {1047, 8}, + {1234, 0}, + {1234, 2}, + {1233, 0}, + {1233, 3}, + {1258, 0}, + {1258, 2}, + {1257, 0}, + {1257, 2}, + {1028, 1}, + {964, 1}, + {964, 3}, {900, 2}, - {1086, 5}, - {1086, 6}, - {1086, 9}, - {1086, 10}, - {1086, 4}, + {1089, 5}, + {1089, 6}, + {1089, 9}, + {1089, 10}, + {1089, 4}, } yyXErrors = map[yyXError]string{} - yyParseTab = [4171][]uint16{ + yyParseTab = [4189][]uint16{ // 0 - {1997, 1997, 59: 2489, 80: 2604, 82: 2470, 91: 2500, 145: 2472, 151: 2498, 153: 2469, 166: 2494, 198: 2519, 205: 2616, 208: 2465, 216: 2518, 2485, 2471, 233: 2497, 238: 2475, 241: 2495, 243: 2466, 245: 2501, 263: 2487, 267: 2486, 274: 2499, 276: 2467, 279: 2488, 290: 2480, 462: 2509, 2508, 486: 2612, 2507, 494: 2493, 501: 2517, 514: 2607, 518: 2483, 556: 2506, 2492, 634: 2502, 638: 2615, 643: 2468, 2606, 652: 2463, 659: 2474, 664: 2473, 669: 2516, 676: 2464, 699: 2513, 732: 2476, 741: 2515, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2586, 2585, 2479, 764: 2605, 2477, 769: 2569, 771: 2580, 773: 2596, 783: 2478, 787: 2535, 799: 2610, 812: 2523, 834: 2530, 837: 2533, 843: 2608, 848: 2572, 852: 2577, 2587, 2490, 919: 2542, 923: 2481, 958: 2611, 965: 2521, 967: 2522, 2525, 2526, 971: 2528, 973: 2527, 975: 2524, 977: 2529, 2531, 2532, 981: 2491, 2568, 984: 2538, 994: 2546, 2539, 2540, 2541, 2547, 2545, 2548, 2549, 1003: 2544, 2543, 1006: 2534, 2496, 2482, 2550, 2562, 2551, 2552, 2553, 2555, 2559, 2556, 2560, 2561, 2554, 2558, 2557, 1023: 2520, 1027: 2536, 2537, 2484, 1033: 2564, 2563, 1037: 2566, 2567, 2565, 1042: 2602, 2570, 1050: 2614, 2613, 2571, 1057: 2573, 1059: 2599, 1086: 2574, 2575, 1089: 2576, 1091: 2581, 1094: 2578, 2579, 1097: 2601, 2582, 2609, 2584, 2583, 1107: 2589, 2588, 2592, 1111: 2593, 1113: 2600, 1116: 2590, 2603, 1121: 2591, 1132: 2594, 2595, 2598, 1136: 2597, 1280: 2461, 1283: 2462}, - {2460}, - {2459, 6629}, - {16: 6570, 132: 6567, 162: 6568, 186: 6571, 249: 6569, 477: 4087, 556: 1813, 572: 5925, 839: 6566, 844: 4086}, - {162: 6551, 556: 6550}, + {2004, 2004, 48: 2503, 69: 2619, 71: 2484, 80: 2514, 145: 2486, 152: 2512, 154: 2483, 166: 2508, 199: 2533, 205: 2631, 208: 2479, 216: 2532, 2499, 2485, 233: 2511, 238: 2489, 241: 2509, 243: 2480, 245: 2515, 263: 2501, 268: 2500, 275: 2513, 277: 2481, 280: 2502, 292: 2494, 465: 2523, 2522, 488: 2627, 493: 2521, 496: 2531, 499: 2507, 517: 2622, 521: 2497, 559: 2506, 562: 2520, 637: 2516, 640: 2630, 644: 2482, 2621, 653: 2477, 660: 2488, 665: 2487, 670: 2530, 677: 2478, 700: 2527, 733: 2490, 742: 2529, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2600, 2599, 2493, 763: 2620, 765: 2491, 767: 2583, 2594, 2611, 782: 2492, 786: 2549, 798: 2625, 811: 2537, 833: 2544, 837: 2547, 843: 2623, 848: 2586, 852: 2591, 2601, 2504, 919: 2556, 923: 2495, 961: 2626, 968: 2535, 970: 2536, 2539, 2540, 974: 2542, 976: 2541, 978: 2538, 980: 2543, 2545, 2546, 985: 2505, 2582, 988: 2552, 998: 2560, 2553, 2554, 2555, 2561, 2559, 2562, 2563, 1007: 2558, 2557, 1010: 2548, 2510, 2496, 2564, 2576, 2565, 2566, 2567, 2569, 2573, 2570, 2574, 2575, 2568, 2572, 2571, 1027: 2534, 1031: 2550, 2551, 2498, 1037: 2578, 2577, 1041: 2580, 2581, 2579, 1046: 2617, 2584, 1054: 2629, 2628, 2585, 1061: 2587, 1064: 2614, 1089: 2588, 2589, 1092: 2590, 1094: 2595, 1097: 2592, 2593, 1100: 2616, 2596, 2624, 2598, 2597, 1109: 2602, 1111: 2604, 2603, 2607, 1115: 2608, 1117: 2615, 1120: 2605, 2618, 1125: 2606, 1136: 2609, 2610, 2613, 1140: 2612, 1284: 2475, 1287: 2476}, + {2474}, + {2473, 6661}, + {16: 6613, 132: 6610, 163: 6611, 187: 6614, 249: 6612, 482: 4105, 562: 1820, 577: 5968, 839: 6609, 844: 4104}, + {163: 6594, 562: 6593}, // 5 - {556: 6544}, - {556: 6539}, - {364: 6520, 478: 6521, 556: 2313, 1278: 6519}, - {332: 6475, 556: 6474}, - {2281, 2281, 351: 6473, 358: 6472}, + {562: 6587}, + {562: 6582}, + {369: 6563, 483: 6564, 562: 2329, 1282: 6562}, + {337: 6518, 562: 6517}, + {2297, 2297, 356: 6516, 363: 6515}, // 10 - {389: 6461}, - {464: 6460}, - {2248, 2248, 81: 5767, 495: 5765, 850: 5766, 991: 6459}, - {16: 2047, 92: 2047, 99: 2047, 132: 6274, 139: 2047, 154: 578, 156: 6196, 160: 5422, 162: 6275, 167: 6276, 186: 6278, 5894, 211: 6266, 497: 6273, 556: 2016, 572: 5925, 632: 6268, 638: 2141, 658: 2047, 666: 6270, 839: 6271, 926: 6277, 935: 5421, 1209: 6267, 1247: 6272, 1277: 6269}, - {16: 6203, 99: 6197, 110: 2016, 132: 6201, 154: 578, 156: 6196, 160: 5422, 162: 6198, 166: 1004, 6199, 186: 6204, 5894, 211: 6192, 277: 6200, 556: 2016, 572: 5925, 638: 6194, 839: 6193, 926: 6202, 935: 6195}, + {392: 6504}, + {468: 6503}, + {2264, 2264, 70: 5808, 497: 5806, 850: 5807, 995: 6502}, + {16: 2054, 81: 2054, 99: 2054, 132: 6279, 139: 2054, 155: 581, 157: 6216, 161: 5417, 163: 6280, 167: 6281, 187: 6283, 5936, 211: 6271, 501: 6278, 562: 2023, 577: 5968, 586: 6273, 640: 2149, 659: 2054, 667: 6275, 839: 6276, 926: 6282, 938: 5416, 1214: 6272, 1251: 6277, 1281: 6274}, + {16: 6223, 99: 6217, 110: 2023, 132: 6221, 155: 581, 157: 6216, 161: 5417, 163: 6218, 166: 1008, 6219, 187: 6224, 5936, 211: 6212, 278: 6220, 562: 2023, 577: 5968, 640: 6214, 839: 6213, 926: 6222, 938: 6215}, // 15 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 6191}, - {2: 825, 825, 825, 825, 825, 8: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 58: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 477: 825, 490: 825, 738: 825, 825, 825, 749: 5229, 855: 5230, 906: 6157}, - {2024, 2024}, - {2023, 2023}, - {462: 2509, 487: 2507, 556: 2506, 634: 2502, 644: 2606, 699: 3787, 732: 2476, 741: 3786, 2503, 2504, 2505, 2514, 2512, 3788, 3789, 764: 6156, 6154, 783: 6155}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 6211}, + {2: 829, 829, 829, 829, 829, 8: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 48: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 482: 829, 490: 829, 739: 829, 829, 829, 753: 5224, 855: 5225, 906: 6199}, + {2031, 2031}, + {2030, 2030}, + {465: 2523, 493: 2521, 562: 2520, 637: 2516, 645: 2621, 700: 3805, 733: 2490, 742: 3804, 2517, 2518, 2519, 2528, 2526, 3806, 3807, 763: 5589, 765: 6197, 782: 6198}, // 20 - {82: 2470, 145: 2472, 151: 2498, 153: 2469, 205: 6130, 326: 6129, 462: 2509, 2508, 487: 2507, 494: 2493, 501: 6133, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6131, 732: 2476, 741: 6132, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6139, 6138, 2479, 764: 2605, 2477, 769: 6136, 771: 6137, 773: 6135, 783: 2478, 787: 6134, 799: 6145, 834: 6141, 837: 6142, 848: 6140, 852: 6143, 6144, 908: 6128}, - {2: 1992, 1992, 1992, 1992, 1992, 8: 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 58: 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 1992, 462: 1992, 1992, 482: 1992, 487: 1992, 494: 1992, 556: 1992, 1992, 634: 1992, 643: 1992, 1992, 652: 1992, 732: 1992}, - {2: 1991, 1991, 1991, 1991, 1991, 8: 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 58: 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 462: 1991, 1991, 482: 1991, 487: 1991, 494: 1991, 556: 1991, 1991, 634: 1991, 643: 1991, 1991, 652: 1991, 732: 1991}, - {2: 1990, 1990, 1990, 1990, 1990, 8: 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 58: 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 462: 1990, 1990, 482: 1990, 487: 1990, 494: 1990, 556: 1990, 1990, 634: 1990, 643: 1990, 1990, 652: 1990, 732: 1990}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 6105, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 2509, 2508, 482: 6104, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 643: 6106, 2606, 652: 2622, 3820, 2676, 2677, 2675, 699: 2623, 727: 6102, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 6103}, + {71: 2484, 145: 2486, 152: 2512, 154: 2483, 205: 6173, 331: 6172, 465: 2523, 2522, 493: 2521, 496: 6176, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 6174, 733: 2490, 742: 6175, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 6182, 6181, 2493, 763: 2620, 765: 2491, 767: 6179, 6180, 6178, 782: 2492, 786: 6177, 798: 6188, 833: 6184, 837: 6185, 848: 6183, 852: 6186, 6187, 908: 6171}, + {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 48: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 465: 1999, 1999, 485: 1999, 493: 1999, 499: 1999, 559: 1999, 562: 1999, 637: 1999, 644: 1999, 1999, 653: 1999, 733: 1999}, + {2: 1998, 1998, 1998, 1998, 1998, 8: 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 48: 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 465: 1998, 1998, 485: 1998, 493: 1998, 499: 1998, 559: 1998, 562: 1998, 637: 1998, 644: 1998, 1998, 653: 1998, 733: 1998}, + {2: 1997, 1997, 1997, 1997, 1997, 8: 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 48: 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 465: 1997, 1997, 485: 1997, 493: 1997, 499: 1997, 559: 1997, 562: 1997, 637: 1997, 644: 1997, 1997, 653: 1997, 733: 1997}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 6148, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 2523, 2522, 485: 6147, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 644: 6149, 2621, 653: 2637, 3838, 2691, 2692, 2690, 700: 2638, 728: 6145, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 6146}, // 25 - {556: 6020, 572: 5925, 839: 6019, 980: 6098}, - {556: 6020, 572: 5925, 839: 6019, 980: 6018}, - {132: 6016}, - {132: 6011}, - {132: 6005}, + {562: 6063, 577: 5968, 839: 6062, 983: 6141}, + {562: 6063, 577: 5968, 839: 6062, 983: 6061}, + {132: 6059}, + {132: 6054}, + {132: 6048}, // 30 - {13: 3735, 16: 5859, 39: 5885, 5884, 98: 571, 107: 571, 110: 571, 125: 578, 132: 5848, 138: 578, 156: 5893, 181: 5857, 187: 5894, 191: 578, 199: 5895, 5871, 206: 5880, 571, 239: 5877, 262: 5876, 296: 5890, 301: 5858, 308: 5873, 5888, 311: 5865, 318: 5863, 320: 5879, 324: 5869, 327: 5878, 5852, 5887, 331: 5892, 333: 5861, 342: 5853, 350: 5867, 360: 5856, 5855, 368: 5891, 373: 5886, 5883, 5882, 390: 5874, 394: 5870, 489: 3736, 556: 5851, 637: 3734, 5860, 643: 5889, 664: 5850, 762: 5866, 902: 5881, 926: 5872, 931: 5862, 944: 5875, 1005: 5864, 1072: 5854, 1270: 5868, 1276: 5849}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5837, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5839, 2676, 2677, 2675, 1257: 5838}, - {2: 825, 825, 825, 825, 825, 8: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 58: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 477: 825, 484: 825, 738: 825, 825, 825, 749: 5229, 855: 5230, 906: 5824}, - {2: 1027, 1027, 1027, 1027, 1027, 8: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 58: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 484: 1027, 738: 5234, 5233, 5232, 827: 5235, 874: 5790}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5785, 2676, 2677, 2675}, + {14: 3753, 16: 5900, 28: 5927, 5926, 98: 574, 107: 574, 110: 574, 123: 581, 132: 5889, 138: 581, 157: 5935, 182: 5898, 188: 5936, 192: 581, 200: 5937, 5912, 206: 5922, 574, 239: 5919, 262: 5918, 298: 5932, 300: 5916, 304: 5899, 311: 5914, 5930, 314: 5906, 323: 5904, 325: 5921, 329: 5910, 332: 5920, 5893, 5929, 336: 5934, 338: 5902, 347: 5894, 355: 5908, 365: 5897, 5896, 372: 5933, 377: 5928, 5925, 5924, 393: 5915, 397: 5911, 498: 3754, 562: 5892, 638: 3752, 640: 5901, 644: 5931, 665: 5891, 762: 5907, 902: 5923, 926: 5913, 931: 5903, 947: 5917, 1009: 5905, 1075: 5895, 1274: 5909, 1280: 5890}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5878, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5880, 2691, 2692, 2690, 1261: 5879}, + {2: 829, 829, 829, 829, 829, 8: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 48: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 482: 829, 487: 829, 739: 829, 829, 829, 753: 5224, 855: 5225, 906: 5865}, + {2: 1031, 1031, 1031, 1031, 1031, 8: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 48: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 487: 1031, 739: 5229, 5228, 5227, 826: 5230, 875: 5831}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5826, 2691, 2692, 2690}, // 35 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5779, 2676, 2677, 2675}, - {166: 5777}, - {166: 1005}, - {1003, 1003, 81: 5767, 495: 5765, 850: 5766, 991: 5764}, - {994, 994}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5820, 2691, 2692, 2690}, + {166: 5818}, + {166: 1009}, + {1007, 1007, 70: 5808, 497: 5806, 850: 5807, 995: 5805}, + {998, 998}, // 40 - {993, 993}, - {464: 5763}, - {2: 830, 830, 830, 830, 830, 8: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 58: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 5734, 5740, 5741, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 462: 830, 464: 830, 830, 830, 830, 472: 830, 830, 830, 830, 830, 481: 830, 487: 830, 489: 830, 494: 830, 496: 830, 503: 5737, 512: 830, 532: 830, 555: 830, 557: 830, 830, 830, 830, 830, 830, 830, 830, 830, 567: 830, 830, 830, 830, 572: 830, 830, 575: 830, 577: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 639: 830, 641: 3447, 735: 3445, 3446, 738: 5234, 5233, 5232, 749: 5229, 758: 5733, 5736, 5732, 774: 5655, 777: 5730, 827: 5731, 855: 5729, 1104: 5739, 5735, 1265: 5728, 5738}, - {237, 237, 57: 237, 461: 237, 463: 237, 469: 237, 471: 237, 479: 237, 237, 482: 237, 237, 237, 486: 237, 490: 5703, 237, 2636, 237, 502: 237, 780: 2637, 5704, 1197: 5702}, - {820, 820, 57: 820, 461: 820, 463: 820, 469: 820, 471: 820, 479: 820, 820, 482: 820, 820, 820, 486: 820, 491: 820, 493: 820, 502: 5693, 927: 5695, 950: 5694}, + {997, 997}, + {468: 5804}, + {2: 834, 834, 834, 834, 834, 8: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 48: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 5775, 5781, 5782, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 465: 834, 467: 834, 834, 834, 471: 834, 475: 834, 834, 834, 834, 834, 484: 834, 493: 834, 498: 834, 834, 834, 506: 5778, 515: 834, 536: 834, 558: 834, 834, 834, 834, 563: 834, 834, 566: 834, 834, 834, 834, 834, 834, 834, 834, 577: 834, 834, 834, 834, 834, 834, 834, 834, 834, 587: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 617: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 639: 834, 642: 3465, 736: 3463, 3464, 739: 5229, 5228, 5227, 753: 5224, 759: 5774, 5777, 5773, 773: 5696, 776: 5771, 826: 5772, 855: 5770, 1107: 5780, 5776, 1269: 5769, 5779}, + {239, 239, 47: 239, 464: 239, 466: 239, 472: 239, 239, 480: 239, 239, 485: 239, 239, 239, 239, 490: 5744, 239, 2651, 494: 239, 505: 239, 779: 2652, 5745, 1202: 5743}, + {824, 824, 47: 824, 464: 824, 466: 824, 472: 824, 824, 480: 824, 824, 485: 824, 824, 824, 824, 491: 824, 494: 824, 505: 5734, 927: 5736, 953: 5735}, // 45 - {1265, 1265, 57: 1265, 461: 1265, 463: 1265, 469: 1265, 471: 1265, 479: 1265, 1265, 482: 1265, 1265, 1265, 486: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 5689}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5684}, - {564: 3795, 900: 3794, 961: 3793}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5671, 2676, 2677, 2675, 918: 5670, 1144: 5668, 1258: 5669}, - {462: 2509, 2508, 487: 2507, 556: 2506, 634: 2502, 699: 5667, 741: 3780, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 3782, 3781, 3779}, + {1269, 1269, 47: 1269, 464: 1269, 466: 1269, 472: 1269, 1269, 480: 1269, 1269, 485: 1269, 1269, 1269, 1269, 491: 1269, 494: 2654, 757: 2655, 800: 5730}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5725}, + {568: 3813, 900: 3812, 964: 3811}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5712, 2691, 2692, 2690, 918: 5711, 1148: 5709, 1262: 5710}, + {465: 2523, 2522, 493: 2521, 562: 2520, 637: 2516, 700: 5708, 742: 3798, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 3800, 3799, 3797}, // 50 - {801, 801, 57: 801, 461: 801, 463: 801, 471: 801}, - {800, 800, 57: 800, 461: 800, 463: 800, 471: 800}, - {469: 5652, 479: 5653, 5654, 1268: 5651}, - {473, 473, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {469: 789, 479: 789, 789}, + {805, 805, 47: 805, 464: 805, 466: 805, 473: 805}, + {804, 804, 47: 804, 464: 804, 466: 804, 473: 804}, + {472: 5693, 480: 5694, 5695, 1272: 5692}, + {476, 476, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {472: 793, 480: 793, 793}, // 55 - {475, 475, 469: 787, 479: 787, 787}, - {239: 5636, 262: 5635}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 5519, 5524, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 5522, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 5521, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 5525, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 5526, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 5520, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 5527, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 5523, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 467: 5529, 489: 3736, 558: 5533, 577: 5532, 637: 3734, 653: 5530, 2676, 2677, 2675, 762: 5534, 820: 5531, 963: 5535, 1138: 5528}, - {27: 5399, 198: 5404, 206: 5402, 208: 5397, 5403, 266: 5401, 302: 5400, 5405, 306: 5398, 321: 5406, 367: 5407, 574: 5396, 854: 5395}, - {31: 550, 110: 550, 125: 550, 136: 4637, 142: 550, 181: 550, 188: 550, 197: 550, 213: 550, 224: 550, 244: 550, 247: 550, 532: 550, 556: 550, 808: 4636, 826: 5368}, + {478, 478, 472: 791, 480: 791, 791}, + {239: 5677, 262: 5676}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 5519, 5514, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 5517, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 5523, 2736, 5516, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 5520, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 5521, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 5515, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 5522, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 5518, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 471: 5525, 498: 3754, 560: 5529, 582: 5528, 638: 3752, 654: 5526, 2691, 2692, 2690, 762: 5530, 819: 5527, 966: 5531, 1142: 5524}, + {15: 5394, 199: 5399, 206: 5397, 208: 5392, 5398, 266: 5396, 305: 5395, 5400, 309: 5393, 326: 5401, 371: 5402, 574: 5391, 854: 5390}, + {20: 553, 110: 553, 123: 553, 136: 4654, 142: 553, 182: 553, 189: 553, 198: 553, 213: 553, 224: 553, 244: 553, 247: 553, 536: 553, 562: 553, 807: 4653, 825: 5363}, // 60 + {544, 544}, + {543, 543}, + {542, 542}, {541, 541}, {540, 540}, + // 65 {539, 539}, {538, 538}, {537, 537}, - // 65 {536, 536}, {535, 535}, + // 70 {534, 534}, {533, 533}, {532, 532}, - // 70 {531, 531}, {530, 530}, + // 75 {529, 529}, {528, 528}, {527, 527}, - // 75 {526, 526}, {525, 525}, + // 80 {524, 524}, {523, 523}, {522, 522}, - // 80 {521, 521}, {520, 520}, + // 85 {519, 519}, {518, 518}, {517, 517}, - // 85 {516, 516}, {515, 515}, + // 90 {514, 514}, {513, 513}, {512, 512}, - // 90 {511, 511}, {510, 510}, + // 95 {509, 509}, {508, 508}, {507, 507}, - // 95 {506, 506}, {505, 505}, + // 100 {504, 504}, {503, 503}, {502, 502}, - // 100 {501, 501}, {500, 500}, + // 105 {499, 499}, {498, 498}, {497, 497}, - // 105 {496, 496}, {495, 495}, + // 110 {494, 494}, {493, 493}, {492, 492}, - // 110 {491, 491}, {490, 490}, + // 115 {489, 489}, {488, 488}, {487, 487}, - // 115 {486, 486}, {485, 485}, + // 120 {484, 484}, {483, 483}, {482, 482}, - // 120 {481, 481}, {480, 480}, + // 125 {479, 479}, - {478, 478}, {477, 477}, - // 125 - {476, 476}, + {475, 475}, {474, 474}, + {473, 473}, + // 130 {472, 472}, {471, 471}, {470, 470}, - // 130 {469, 469}, {468, 468}, + // 135 {467, 467}, {466, 466}, {465, 465}, - // 135 {464, 464}, {463, 463}, + // 140 {462, 462}, {461, 461}, {460, 460}, - // 140 {459, 459}, - {458, 458}, - {457, 457}, - {434, 434}, - {2: 380, 380, 380, 380, 380, 8: 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 58: 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 556: 5365, 1243: 5366}, + {436, 436}, // 145 - {243, 243, 471: 243}, - {2: 825, 825, 825, 825, 825, 8: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 58: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 462: 825, 477: 825, 568: 825, 738: 825, 825, 825, 749: 5229, 855: 5230, 906: 5231}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 5228}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5072, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 5074, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 5080, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 5076, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 5073, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 5081, 3110, 2843, 3063, 5075, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 5078, 5182, 2757, 2993, 5079, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 5077, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5083, 486: 5106, 557: 5100, 634: 5089, 5104, 638: 5099, 641: 5093, 644: 5102, 652: 5094, 3392, 2676, 2677, 2675, 659: 5098, 664: 5095, 728: 5082, 732: 5097, 791: 5084, 799: 5088, 843: 5103, 854: 5101, 924: 5085, 942: 5086, 5092, 948: 5087, 5090, 957: 5096, 959: 5105, 1102: 5183}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5072, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 5074, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 5080, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 5076, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 5073, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 5081, 3110, 2843, 3063, 5075, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 5078, 2756, 2757, 2993, 5079, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 5077, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5083, 486: 5106, 557: 5100, 634: 5089, 5104, 638: 5099, 641: 5093, 644: 5102, 652: 5094, 3392, 2676, 2677, 2675, 659: 5098, 664: 5095, 728: 5082, 732: 5097, 791: 5084, 799: 5088, 843: 5103, 854: 5101, 924: 5085, 942: 5086, 5092, 948: 5087, 5090, 957: 5096, 959: 5105, 1102: 5091}, + {2: 382, 382, 382, 382, 382, 8: 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 48: 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 562: 5360, 1247: 5361}, + {245, 245, 473: 245}, + {2: 829, 829, 829, 829, 829, 8: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 48: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 465: 829, 482: 829, 571: 829, 739: 829, 829, 829, 753: 5224, 855: 5225, 906: 5226}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 5223}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5067, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 5069, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 5075, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 5071, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 5068, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 5076, 3128, 2861, 3081, 5070, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 5073, 5177, 2773, 3011, 5074, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 5072, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5078, 488: 5101, 559: 5095, 635: 5099, 637: 5084, 640: 5094, 642: 5088, 645: 5097, 653: 5089, 3410, 2691, 2692, 2690, 660: 5093, 665: 5090, 729: 5077, 733: 5092, 790: 5079, 798: 5083, 843: 5098, 854: 5096, 924: 5080, 945: 5081, 5087, 951: 5082, 5085, 960: 5091, 962: 5100, 1105: 5178}, // 150 - {32: 5031, 277: 5032}, - {110: 5018, 556: 5019, 1129: 5030}, - {110: 5018, 556: 5019, 1129: 5017}, - {37: 5013, 143: 5014, 496: 2650, 725: 5012}, - {37: 56, 143: 56, 213: 5011, 496: 56}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5067, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 5069, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 5075, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 5071, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 5068, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 5076, 3128, 2861, 3081, 5070, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 5073, 2772, 2773, 3011, 5074, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 5072, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5078, 488: 5101, 559: 5095, 635: 5099, 637: 5084, 640: 5094, 642: 5088, 645: 5097, 653: 5089, 3410, 2691, 2692, 2690, 660: 5093, 665: 5090, 729: 5077, 733: 5092, 790: 5079, 798: 5083, 843: 5098, 854: 5096, 924: 5080, 945: 5081, 5087, 951: 5082, 5085, 960: 5091, 962: 5100, 1105: 5086}, + {21: 5026, 278: 5027}, + {110: 5013, 562: 5014, 1133: 5025}, + {110: 5013, 562: 5014, 1133: 5012}, + {26: 5008, 143: 5009, 500: 2665, 724: 5007}, // 155 - {292: 4994}, - {365: 2617}, - {317: 2618, 799: 2619}, - {923: 2621}, - {464: 2620}, + {26: 56, 143: 56, 213: 5006, 500: 56}, + {294: 4989}, + {370: 2632}, + {321: 2633, 798: 2634}, + {923: 2636}, // 160 + {468: 2635}, {1, 1}, - {188: 2634, 462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 643: 2633, 2606, 652: 2622, 699: 2623, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 2632}, - {477: 4087, 556: 1813, 844: 4086}, - {436, 436, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {438, 438, 469: 787, 479: 787, 787}, + {189: 2649, 465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 644: 2648, 2621, 653: 2637, 700: 2638, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 2647}, + {482: 4105, 562: 1820, 844: 4104}, + {438, 438, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, // 165 + {440, 440, 472: 791, 480: 791, 791}, + {445, 445}, + {444, 444}, {443, 443}, {442, 442}, + // 170 {441, 441}, - {440, 440}, {439, 439}, - // 170 {437, 437}, - {435, 435}, {5, 5}, - {188: 4081, 462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 652: 2622, 699: 2623, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 4080}, - {143: 2635}, + {189: 4099, 465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 653: 2637, 700: 2638, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 4098}, // 175 - {237, 237, 483: 237, 491: 237, 2636, 237, 780: 2637, 2638}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4079}, - {236, 236, 57: 236, 461: 236, 463: 236, 469: 236, 471: 236, 479: 236, 236, 482: 236, 236, 236, 486: 236, 491: 236, 493: 236, 502: 236, 504: 236, 236}, - {1265, 1265, 483: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 2641}, - {649: 2664}, + {143: 2650}, + {239, 239, 486: 239, 491: 239, 2651, 494: 239, 779: 2652, 2653}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4097}, + {238, 238, 47: 238, 464: 238, 466: 238, 472: 238, 238, 480: 238, 238, 485: 238, 238, 238, 238, 491: 238, 494: 238, 505: 238, 507: 238, 238}, + {1269, 1269, 486: 1269, 491: 1269, 494: 2654, 757: 2655, 800: 2656}, // 180 - {1264, 1264, 57: 1264, 124: 1264, 461: 1264, 463: 1264, 469: 1264, 471: 1264, 479: 1264, 1264, 482: 1264, 1264, 1264, 486: 1264, 491: 1264}, - {841, 841, 483: 2642, 491: 2643, 757: 2644, 818: 2645}, - {496: 2650, 567: 2652, 725: 2649, 734: 2651, 869: 2659}, - {8: 2646, 257: 2647, 1192: 2648}, - {840, 840, 57: 840, 461: 840, 463: 840, 469: 840, 471: 840, 479: 840, 840, 482: 840, 484: 840, 486: 840}, + {650: 2679}, + {1268, 1268, 47: 1268, 125: 1268, 464: 1268, 466: 1268, 472: 1268, 1268, 480: 1268, 1268, 485: 1268, 1268, 1268, 1268, 491: 1268}, + {845, 845, 486: 2657, 491: 2658, 758: 2659, 817: 2660}, + {500: 2665, 570: 2667, 724: 2664, 734: 2666, 870: 2674}, + {8: 2661, 257: 2662, 1197: 2663}, // 185 + {844, 844, 47: 844, 464: 844, 466: 844, 472: 844, 844, 480: 844, 844, 485: 844, 487: 844, 844}, {3, 3}, - {496: 849, 513: 849, 564: 849, 567: 849}, - {496: 848, 513: 848, 564: 848, 567: 848}, - {496: 2650, 513: 847, 564: 847, 567: 2652, 725: 2649, 734: 2651, 869: 2653, 1187: 2654}, - {1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 13: 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 59: 1932, 61: 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 92: 1932, 1932, 1932, 1932, 1932, 1932, 100: 1932, 103: 1932, 105: 1932, 1932, 108: 1932, 1932, 111: 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 164: 1932, 201: 1932, 1932, 461: 1932, 1932, 1932, 467: 1932, 1932, 1932, 1932, 1932, 477: 1932, 1932, 1932, 1932, 482: 1932, 484: 1932, 486: 1932, 1932, 1932, 1932, 494: 1932, 513: 1932, 556: 1932, 564: 1932, 634: 1932, 637: 1932, 1932, 643: 1932}, + {500: 853, 516: 853, 568: 853, 570: 853}, + {500: 852, 516: 852, 568: 852, 570: 852}, + {500: 2665, 516: 851, 568: 851, 570: 2667, 724: 2664, 734: 2666, 870: 2668, 1192: 2669}, // 190 - {1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 13: 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 61: 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 100: 1930, 103: 1930, 105: 1930, 1930, 108: 1930, 1930, 111: 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 126: 1930, 1930, 1930, 1930, 164: 1930, 176: 1930, 180: 1930, 201: 1930, 1930, 461: 1930, 1930, 1930, 467: 1930, 1930, 1930, 1930, 1930, 477: 1930, 1930, 1930, 1930, 482: 1930, 1930, 1930, 486: 1930, 1930, 1930, 1930, 491: 1930, 1930, 494: 1930, 513: 1930, 556: 1930, 564: 1930, 634: 1930, 637: 1930, 1930, 643: 1930, 647: 1930, 1930}, - {853, 853, 7: 853, 57: 853, 164: 853, 461: 853, 463: 853, 469: 853, 471: 853, 479: 853, 853, 482: 853, 484: 853, 486: 853, 513: 853, 564: 853}, - {852, 852, 7: 852, 57: 852, 164: 852, 461: 852, 463: 852, 469: 852, 471: 852, 479: 852, 852, 482: 852, 484: 852, 486: 852, 513: 852, 564: 852}, - {513: 846, 564: 846}, - {513: 2656, 564: 2655, 1263: 2657}, + {1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 13: 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 47: 1939, 1939, 50: 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 81: 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 100: 1939, 103: 1939, 105: 1939, 1939, 108: 1939, 1939, 111: 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 124: 1939, 164: 1939, 176: 1939, 202: 1939, 464: 1939, 1939, 1939, 470: 1939, 1939, 1939, 1939, 1939, 480: 1939, 1939, 1939, 1939, 485: 1939, 487: 1939, 1939, 493: 1939, 495: 1939, 1939, 498: 1939, 1939, 516: 1939, 562: 1939, 568: 1939, 637: 1939, 1939, 640: 1939, 644: 1939}, + {1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 13: 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 50: 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 100: 1937, 103: 1937, 105: 1937, 1937, 108: 1937, 1937, 111: 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 124: 1937, 126: 1937, 1937, 1937, 1937, 164: 1937, 176: 1937, 1937, 181: 1937, 202: 1937, 464: 1937, 1937, 1937, 470: 1937, 1937, 1937, 1937, 1937, 480: 1937, 1937, 1937, 1937, 485: 1937, 1937, 1937, 1937, 491: 1937, 1937, 1937, 495: 1937, 1937, 498: 1937, 1937, 516: 1937, 562: 1937, 568: 1937, 637: 1937, 1937, 640: 1937, 644: 1937, 648: 1937, 1937}, + {857, 857, 7: 857, 47: 857, 164: 857, 464: 857, 466: 857, 472: 857, 857, 480: 857, 857, 485: 857, 487: 857, 857, 516: 857, 568: 857}, + {856, 856, 7: 856, 47: 856, 164: 856, 464: 856, 466: 856, 472: 856, 856, 480: 856, 856, 485: 856, 487: 856, 856, 516: 856, 568: 856}, + {516: 850, 568: 850}, // 195 - {150: 851}, - {150: 850}, - {150: 2658}, - {842, 842, 57: 842, 461: 842, 463: 842, 469: 842, 471: 842, 479: 842, 842, 482: 842, 484: 842, 486: 842}, - {845, 845, 7: 2660, 57: 845, 164: 2661, 461: 845, 463: 845, 469: 845, 471: 845, 479: 845, 845, 482: 845, 484: 845, 486: 845}, + {516: 2671, 568: 2670, 1267: 2672}, + {151: 855}, + {151: 854}, + {151: 2673}, + {846, 846, 47: 846, 464: 846, 466: 846, 472: 846, 846, 480: 846, 846, 485: 846, 487: 846, 846}, // 200 - {496: 2650, 567: 2652, 725: 2649, 734: 2651, 869: 2663}, - {496: 2650, 567: 2652, 725: 2649, 734: 2651, 869: 2662}, - {843, 843, 57: 843, 461: 843, 463: 843, 469: 843, 471: 843, 479: 843, 843, 482: 843, 484: 843, 486: 843}, - {844, 844, 57: 844, 461: 844, 463: 844, 469: 844, 471: 844, 479: 844, 844, 482: 844, 484: 844, 486: 844}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 2668, 859: 3144, 888: 3143}, + {849, 849, 7: 2675, 47: 849, 164: 2676, 464: 849, 466: 849, 472: 849, 849, 480: 849, 849, 485: 849, 487: 849, 849}, + {500: 2665, 570: 2667, 724: 2664, 734: 2666, 870: 2678}, + {500: 2665, 570: 2667, 724: 2664, 734: 2666, 870: 2677}, + {847, 847, 47: 847, 464: 847, 466: 847, 472: 847, 847, 480: 847, 847, 485: 847, 487: 847, 847}, + {848, 848, 47: 848, 464: 848, 466: 848, 472: 848, 848, 480: 848, 848, 485: 848, 487: 848, 848}, // 205 - {1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 4076, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 463: 1496, 1496, 1496, 1496, 468: 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 479: 1496, 1496, 482: 1496, 1496, 1496, 1496, 1496, 488: 1496, 490: 1496, 1496, 1496, 1496, 495: 1496, 497: 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 533: 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 571: 1496, 642: 1496, 645: 1496, 1496}, - {1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 4073, 1495, 1495, 1495, 1495, 468: 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 479: 1495, 1495, 482: 1495, 1495, 1495, 1495, 1495, 488: 1495, 490: 1495, 1495, 1495, 1495, 495: 1495, 497: 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 533: 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 571: 1495, 642: 1495, 645: 1495, 1495}, - {721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 463: 721, 721, 721, 721, 468: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 479: 721, 721, 482: 721, 721, 721, 721, 721, 488: 721, 490: 721, 721, 721, 721, 495: 721, 497: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 533: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 571: 721, 650: 4071}, - {1272, 1272, 7: 1272, 57: 1272, 124: 1272, 461: 1272, 463: 1272, 469: 1272, 471: 1272, 479: 1272, 1272, 482: 1272, 1272, 1272, 486: 1272, 491: 1272, 493: 1272, 495: 3249, 497: 3247, 3248, 3246, 3244, 504: 1272, 1272, 513: 1272, 516: 1272, 1272, 4070, 4069, 723: 3245, 3243, 1246: 4068}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4067}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 2683, 859: 3162, 888: 3161}, + {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 4094, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 466: 1500, 1500, 1500, 1500, 1500, 472: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 485: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 494: 1500, 1500, 1500, 1500, 501: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 537: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 575: 1500, 643: 1500, 646: 1500, 1500}, + {1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 4091, 1499, 1499, 1499, 1499, 1499, 472: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 485: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 494: 1499, 1499, 1499, 1499, 501: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 537: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 575: 1499, 643: 1499, 646: 1499, 1499}, + {725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 466: 725, 725, 725, 725, 725, 472: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 485: 725, 725, 725, 725, 725, 725, 725, 725, 494: 725, 725, 725, 725, 501: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 537: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 575: 725, 651: 4089}, + {1276, 1276, 7: 1276, 47: 1276, 125: 1276, 464: 1276, 466: 1276, 472: 1276, 1276, 480: 1276, 1276, 485: 1276, 1276, 1276, 1276, 491: 1276, 494: 1276, 497: 3265, 501: 3263, 3264, 3262, 3260, 507: 1276, 1276, 516: 1276, 519: 1276, 1276, 4088, 4087, 725: 3261, 3259, 1250: 4086}, // 210 - {462: 4039}, - {1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 463: 1892, 1892, 468: 1892, 1892, 471: 1892, 1892, 1892, 477: 1892, 479: 1892, 1892, 482: 1892, 1892, 1892, 4022, 1892, 488: 1892, 490: 1892, 1892, 1892, 1892, 495: 1892, 497: 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 511: 1892, 513: 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 534: 1892, 1892, 4019, 4017, 4016, 4024, 4018, 4020, 4021, 4023, 1172: 4015, 1216: 4014}, - {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 463: 1867, 1867, 468: 1867, 1867, 471: 1867, 1867, 1867, 477: 1867, 479: 1867, 1867, 482: 1867, 1867, 1867, 1867, 1867, 488: 1867, 490: 1867, 1867, 1867, 1867, 495: 1867, 497: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 511: 1867, 513: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 534: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867}, - {1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 463: 1840, 1840, 3986, 3985, 468: 1840, 1840, 471: 1840, 1840, 1840, 3588, 3587, 3593, 1840, 479: 1840, 1840, 482: 1840, 1840, 1840, 1840, 1840, 488: 1840, 490: 1840, 1840, 1840, 1840, 495: 1840, 497: 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 3990, 1840, 3589, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 533: 3989, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 1840, 3987, 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586, 3996, 3997, 800: 3988, 1093: 3991, 1158: 3993, 1212: 3992, 1219: 3994, 1259: 3995}, - {1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 3982, 1789, 1789, 1789, 1789, 468: 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 479: 1789, 1789, 482: 1789, 1789, 1789, 1789, 1789, 488: 1789, 490: 1789, 1789, 1789, 1789, 495: 1789, 497: 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 533: 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 571: 1789, 642: 1789, 645: 1789, 1789}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4085}, + {465: 4057}, + {1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 466: 1899, 468: 1899, 470: 1899, 472: 1899, 1899, 475: 1899, 1899, 480: 1899, 1899, 1899, 485: 1899, 1899, 1899, 1899, 4040, 1899, 1899, 1899, 494: 1899, 1899, 1899, 1899, 501: 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 514: 1899, 516: 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 537: 1899, 1899, 4037, 4035, 4034, 4042, 4036, 4038, 4039, 4041, 1177: 4033, 1221: 4032}, + {1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 466: 1874, 468: 1874, 470: 1874, 472: 1874, 1874, 475: 1874, 1874, 480: 1874, 1874, 1874, 485: 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 494: 1874, 1874, 1874, 1874, 501: 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 514: 1874, 516: 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 537: 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874, 1874}, + {1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 466: 1847, 4004, 1847, 4003, 1847, 472: 1847, 1847, 475: 1847, 1847, 3606, 3605, 3611, 1847, 1847, 1847, 485: 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 494: 1847, 1847, 1847, 1847, 501: 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 4008, 1847, 3607, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 4007, 537: 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 4005, 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604, 4014, 4015, 799: 4006, 1096: 4009, 1162: 4011, 1217: 4010, 1224: 4012, 1263: 4013}, // 215 - {1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 657: 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788}, - {1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 657: 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787}, - {1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 657: 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786}, - {1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 657: 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785}, - {1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 657: 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784}, + {1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 4000, 1796, 1796, 1796, 1796, 1796, 472: 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 485: 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 494: 1796, 1796, 1796, 1796, 501: 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 537: 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 575: 1796, 643: 1796, 646: 1796, 1796}, + {1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 658: 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795}, + {1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 658: 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794}, + {1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 658: 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793}, + {1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 658: 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792}, // 220 - {1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1204, 1783, 1783, 1783, 1783, 468: 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 479: 1783, 1783, 482: 1783, 1783, 1783, 1783, 1783, 488: 1783, 490: 1783, 1783, 1783, 1783, 495: 1783, 497: 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 533: 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 571: 1783, 642: 1783, 645: 1783, 1783}, - {1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 657: 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782}, - {1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 657: 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781}, - {1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 657: 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780}, - {1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 657: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779}, + {1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 658: 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791, 1791}, + {1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1208, 1790, 1790, 1790, 1790, 1790, 472: 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 485: 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 494: 1790, 1790, 1790, 1790, 501: 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 537: 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 575: 1790, 643: 1790, 646: 1790, 1790}, + {1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 658: 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789}, + {1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 658: 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788}, + {1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 658: 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787, 1787}, // 225 - {1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 657: 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778}, - {1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 657: 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777}, - {1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 657: 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776}, - {1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 657: 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775}, - {1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 657: 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774}, + {1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 658: 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786, 1786}, + {1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 658: 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785, 1785}, + {1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 658: 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784}, + {1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 658: 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783}, + {1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 658: 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782, 1782}, // 230 - {1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 3977, 1773, 1773, 1773, 1773, 468: 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 479: 1773, 1773, 482: 1773, 1773, 1773, 1773, 1773, 488: 1773, 490: 1773, 1773, 1773, 1773, 495: 1773, 497: 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 533: 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 571: 1773, 642: 1773, 645: 1773, 1773}, - {1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 657: 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772}, - {1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 657: 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771}, - {1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 657: 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770}, - {1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 657: 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769}, + {1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 658: 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1781}, + {1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 658: 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780}, + {1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 3995, 1779, 1779, 1779, 1779, 1779, 472: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 485: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 494: 1779, 1779, 1779, 1779, 501: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 537: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 575: 1779, 643: 1779, 646: 1779, 1779}, + {1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 658: 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778, 1778}, + {1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 658: 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777, 1777}, // 235 - {1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 657: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768}, - {1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 657: 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767}, - {1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 657: 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766}, - {1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 657: 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765}, - {1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 657: 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764}, + {1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 658: 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776}, + {1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 658: 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775}, + {1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 658: 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774}, + {1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 658: 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773}, + {1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 658: 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772}, // 240 - {1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 657: 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763}, - {1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1203, 1762, 1762, 1762, 1762, 468: 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 479: 1762, 1762, 482: 1762, 1762, 1762, 1762, 1762, 488: 1762, 490: 1762, 1762, 1762, 1762, 495: 1762, 497: 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 533: 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 571: 1762, 642: 1762, 645: 1762, 1762}, - {1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 657: 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761}, - {1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 657: 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760}, - {1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 657: 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759}, + {1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 658: 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771}, + {1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 658: 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770, 1770}, + {1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 658: 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769, 1769}, + {1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1207, 1768, 1768, 1768, 1768, 1768, 472: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 485: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 494: 1768, 1768, 1768, 1768, 501: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 537: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 575: 1768, 643: 1768, 646: 1768, 1768}, + {1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 658: 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767, 1767}, // 245 - {1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 657: 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758}, - {1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 657: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757}, - {1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 657: 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756}, - {1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 657: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755}, - {1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 657: 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754}, + {1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 658: 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766, 1766}, + {1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 658: 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765, 1765}, + {1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 658: 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764, 1764}, + {1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 658: 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763, 1763}, + {1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 658: 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762}, // 250 - {1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 657: 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753}, - {1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 657: 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752}, - {1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1200, 1751, 3976, 1751, 1751, 468: 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 479: 1751, 1751, 482: 1751, 1751, 1751, 1751, 1751, 488: 1751, 490: 1751, 1751, 1751, 1751, 495: 1751, 497: 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 533: 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 571: 1751, 642: 1751, 645: 1751, 1751}, - {1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 657: 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750}, - {1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1198, 1749, 1749, 1749, 1749, 468: 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 479: 1749, 1749, 482: 1749, 1749, 1749, 1749, 1749, 488: 1749, 490: 1749, 1749, 1749, 1749, 495: 1749, 497: 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 533: 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 571: 1749, 642: 1749, 645: 1749, 1749}, + {1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 658: 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761}, + {1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 658: 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760}, + {1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 658: 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759}, + {1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 658: 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758}, + {1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1204, 1757, 1757, 3994, 1757, 1757, 472: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 485: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 494: 1757, 1757, 1757, 1757, 501: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 537: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 575: 1757, 643: 1757, 646: 1757, 1757}, // 255 - {1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 657: 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748}, - {1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 657: 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747}, - {1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 657: 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746}, - {1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 657: 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745}, - {1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 657: 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744}, + {1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 658: 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756}, + {1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1202, 1755, 1755, 1755, 1755, 1755, 472: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 485: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 494: 1755, 1755, 1755, 1755, 501: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 537: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 575: 1755, 643: 1755, 646: 1755, 1755}, + {1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 658: 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754}, + {1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 658: 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753}, + {1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 658: 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752}, // 260 - {1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 657: 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743}, - {1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 657: 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742}, - {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 657: 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741}, - {1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 657: 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740}, - {1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 657: 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739}, + {1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 658: 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751}, + {1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 658: 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750}, + {1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 658: 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749}, + {1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 658: 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748, 1748}, + {1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 658: 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747, 1747}, // 265 - {1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 657: 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738}, - {1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 657: 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737}, - {1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 657: 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736}, - {1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 657: 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735}, - {1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 657: 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734}, + {1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 658: 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746}, + {1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 658: 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745, 1745}, + {1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 658: 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744}, + {1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 658: 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743, 1743}, + {1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 658: 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742}, // 270 - {1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 657: 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733}, - {1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 657: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732}, - {1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 657: 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731}, - {1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 657: 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730}, - {1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 657: 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729}, + {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 658: 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741}, + {1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 658: 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740, 1740}, + {1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 658: 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739, 1739}, + {1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 658: 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738, 1738}, + {1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 658: 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737, 1737}, // 275 - {1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 657: 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728}, - {1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 657: 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727}, - {1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1194, 1726, 1726, 1726, 1726, 468: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 479: 1726, 1726, 482: 1726, 1726, 1726, 1726, 1726, 488: 1726, 490: 1726, 1726, 1726, 1726, 495: 1726, 497: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 533: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 571: 1726, 642: 1726, 645: 1726, 1726}, - {1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 657: 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725}, - {1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 657: 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724}, + {1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 658: 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736}, + {1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 658: 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735}, + {1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 658: 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734}, + {1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 658: 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733}, + {1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1198, 1732, 1732, 1732, 1732, 1732, 472: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 485: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 494: 1732, 1732, 1732, 1732, 501: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 537: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 575: 1732, 643: 1732, 646: 1732, 1732}, // 280 - {1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 657: 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723}, - {1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 657: 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722}, - {1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 657: 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721}, - {1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1197, 1720, 1720, 1720, 1720, 468: 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 479: 1720, 1720, 482: 1720, 1720, 1720, 1720, 1720, 488: 1720, 490: 1720, 1720, 1720, 1720, 495: 1720, 497: 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 533: 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 571: 1720, 642: 1720, 645: 1720, 1720}, - {1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 657: 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719}, + {1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 658: 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731}, + {1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 658: 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730}, + {1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 658: 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729}, + {1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 658: 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728}, + {1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 658: 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727}, // 285 - {1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 657: 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718}, - {1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 657: 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717}, - {1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 657: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716}, - {1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 657: 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715}, - {1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 657: 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714}, + {1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1201, 1726, 1726, 1726, 1726, 1726, 472: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 485: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 494: 1726, 1726, 1726, 1726, 501: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 537: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 575: 1726, 643: 1726, 646: 1726, 1726}, + {1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 658: 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725}, + {1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 658: 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724}, + {1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 658: 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723}, + {1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 658: 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722, 1722}, // 290 - {1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 657: 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713}, - {1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 657: 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712}, - {1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 657: 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711}, - {1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 3973, 1710, 1710, 1710, 1710, 468: 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 479: 1710, 1710, 482: 1710, 1710, 1710, 1710, 1710, 488: 1710, 490: 1710, 1710, 1710, 1710, 495: 1710, 497: 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 533: 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 571: 1710, 642: 1710, 645: 1710, 1710}, - {1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 657: 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709}, + {1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 658: 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721}, + {1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 658: 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720}, + {1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 658: 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719}, + {1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 658: 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718}, + {1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 658: 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717, 1717}, // 295 - {1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 657: 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708}, - {1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 657: 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707}, - {1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 657: 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706}, - {1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 657: 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705}, - {1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 657: 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704}, + {1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 3991, 1716, 1716, 1716, 1716, 1716, 472: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 485: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 494: 1716, 1716, 1716, 1716, 501: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 537: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 575: 1716, 643: 1716, 646: 1716, 1716}, + {1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 658: 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715, 1715}, + {1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 658: 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714, 1714}, + {1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 658: 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713, 1713}, + {1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 658: 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712}, // 300 - {1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 657: 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703}, - {1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 657: 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702}, - {1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 657: 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701}, - {1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 657: 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700}, - {1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 657: 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699}, + {1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 658: 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711, 1711}, + {1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 658: 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710}, + {1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 658: 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709, 1709}, + {1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 658: 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708, 1708}, + {1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 658: 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707}, // 305 - {1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 657: 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698}, - {1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 657: 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697}, - {1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 657: 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696}, - {1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 657: 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695}, - {1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 657: 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694}, + {1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 658: 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706, 1706}, + {1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 658: 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705, 1705}, + {1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 658: 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704}, + {1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 658: 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703, 1703}, + {1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 658: 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702, 1702}, // 310 - {1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 657: 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693}, - {1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 657: 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692}, - {1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 657: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691}, - {1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 657: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690}, - {1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 657: 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689}, + {1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 658: 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701, 1701}, + {1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 658: 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700}, + {1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 658: 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699, 1699}, + {1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 658: 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698}, + {1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 658: 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697, 1697}, // 315 - {1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 657: 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688}, - {1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 657: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687}, - {1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 657: 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686}, - {1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1181, 1685, 3972, 1685, 1685, 468: 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 479: 1685, 1685, 482: 1685, 1685, 1685, 1685, 1685, 488: 1685, 490: 1685, 1685, 1685, 1685, 495: 1685, 497: 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 533: 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 571: 1685, 642: 1685, 645: 1685, 1685}, - {1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1180, 1684, 3971, 1684, 1684, 468: 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 479: 1684, 1684, 482: 1684, 1684, 1684, 1684, 1684, 488: 1684, 490: 1684, 1684, 1684, 1684, 495: 1684, 497: 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 533: 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 571: 1684, 642: 1684, 645: 1684, 1684}, + {1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 658: 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696, 1696}, + {1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 658: 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695, 1695}, + {1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 658: 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694, 1694}, + {1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 658: 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693, 1693}, + {1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 658: 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692}, // 320 - {1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 657: 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683}, - {1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 657: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682}, - {1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1179, 1681, 1681, 1681, 1681, 468: 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 479: 1681, 1681, 482: 1681, 1681, 1681, 1681, 1681, 488: 1681, 490: 1681, 1681, 1681, 1681, 495: 1681, 497: 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 533: 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 571: 1681, 642: 1681, 645: 1681, 1681}, - {1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 657: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680}, - {1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 657: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679}, + {1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1185, 1691, 1691, 3990, 1691, 1691, 472: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 485: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 494: 1691, 1691, 1691, 1691, 501: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 537: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 575: 1691, 643: 1691, 646: 1691, 1691}, + {1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1184, 1690, 1690, 3989, 1690, 1690, 472: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 485: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 494: 1690, 1690, 1690, 1690, 501: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 537: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 575: 1690, 643: 1690, 646: 1690, 1690}, + {1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 658: 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689, 1689}, + {1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 658: 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688, 1688}, + {1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1183, 1687, 1687, 1687, 1687, 1687, 472: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 485: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 494: 1687, 1687, 1687, 1687, 501: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 537: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 575: 1687, 643: 1687, 646: 1687, 1687}, // 325 - {1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 657: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678}, - {1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 657: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677}, - {1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1176, 1676, 1676, 1676, 1676, 468: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 479: 1676, 1676, 482: 1676, 1676, 1676, 1676, 1676, 488: 1676, 490: 1676, 1676, 1676, 1676, 495: 1676, 497: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 533: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 571: 1676, 642: 1676, 645: 1676, 1676}, - {1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 657: 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675}, - {1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1177, 1674, 1674, 1674, 1674, 468: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 479: 1674, 1674, 482: 1674, 1674, 1674, 1674, 1674, 488: 1674, 490: 1674, 1674, 1674, 1674, 495: 1674, 497: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 533: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 571: 1674, 642: 1674, 645: 1674, 1674}, + {1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 658: 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686, 1686}, + {1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 658: 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685}, + {1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 658: 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684}, + {1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 658: 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683}, + {1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1180, 1682, 1682, 1682, 1682, 1682, 472: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 485: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 494: 1682, 1682, 1682, 1682, 501: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 537: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 575: 1682, 643: 1682, 646: 1682, 1682}, // 330 - {1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 3961, 1673, 1673, 1673, 1673, 468: 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 479: 1673, 1673, 482: 1673, 1673, 1673, 1673, 1673, 488: 1673, 490: 1673, 1673, 1673, 1673, 495: 1673, 497: 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 533: 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 571: 1673, 642: 1673, 645: 1673, 1673}, - {1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 657: 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672}, - {1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 657: 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671}, - {1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1178, 1670, 1670, 1670, 1670, 468: 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 479: 1670, 1670, 482: 1670, 1670, 1670, 1670, 1670, 488: 1670, 490: 1670, 1670, 1670, 1670, 495: 1670, 497: 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 533: 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 571: 1670, 642: 1670, 645: 1670, 1670}, - {1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 657: 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669}, + {1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 658: 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681}, + {1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1181, 1680, 1680, 1680, 1680, 1680, 472: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 485: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 494: 1680, 1680, 1680, 1680, 501: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 537: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 575: 1680, 643: 1680, 646: 1680, 1680}, + {1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 3979, 1679, 1679, 1679, 1679, 1679, 472: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 485: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 494: 1679, 1679, 1679, 1679, 501: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 537: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 575: 1679, 643: 1679, 646: 1679, 1679}, + {1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 658: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678}, + {1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 658: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677}, // 335 - {1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1201, 1668, 1668, 1668, 1668, 468: 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 479: 1668, 1668, 482: 1668, 1668, 1668, 1668, 1668, 488: 1668, 490: 1668, 1668, 1668, 1668, 495: 1668, 497: 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 533: 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 571: 1668, 642: 1668, 645: 1668, 1668}, - {1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 657: 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667}, - {1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 657: 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666}, - {1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 657: 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665}, - {1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 657: 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664}, + {1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1182, 1676, 1676, 1676, 1676, 1676, 472: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 485: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 494: 1676, 1676, 1676, 1676, 501: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 537: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 575: 1676, 643: 1676, 646: 1676, 1676}, + {1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 658: 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675}, + {1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1205, 1674, 1674, 1674, 1674, 1674, 472: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 485: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 494: 1674, 1674, 1674, 1674, 501: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 537: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 575: 1674, 643: 1674, 646: 1674, 1674}, + {1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 658: 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673}, + {1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 658: 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672}, // 340 - {1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 657: 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663}, - {1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 657: 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662}, - {1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 657: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661}, - {1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 657: 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660}, - {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 657: 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659}, + {1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 658: 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671}, + {1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 658: 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670}, + {1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 658: 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669}, + {1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 658: 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668}, + {1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 658: 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667, 1667}, // 345 - {1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 657: 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658}, - {1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 657: 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657}, - {1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 657: 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656}, - {1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1188, 1655, 1655, 1655, 1655, 468: 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 479: 1655, 1655, 482: 1655, 1655, 1655, 1655, 1655, 488: 1655, 490: 1655, 1655, 1655, 1655, 495: 1655, 497: 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 533: 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 571: 1655, 642: 1655, 645: 1655, 1655}, - {1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 657: 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654}, + {1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 658: 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666}, + {1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 658: 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665}, + {1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 658: 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664, 1664}, + {1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 658: 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663, 1663}, + {1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 658: 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662}, // 350 - {1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 657: 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653}, - {1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 657: 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652}, - {1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 657: 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651}, - {1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 657: 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650}, - {1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 657: 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649}, + {1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1192, 1661, 1661, 1661, 1661, 1661, 472: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 485: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 494: 1661, 1661, 1661, 1661, 501: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 537: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 575: 1661, 643: 1661, 646: 1661, 1661}, + {1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 658: 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660, 1660}, + {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 658: 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659}, + {1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 658: 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658}, + {1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 658: 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657}, // 355 - {1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 657: 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648}, - {1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 657: 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647}, - {1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 657: 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646}, - {1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 657: 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645}, - {1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 657: 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644}, + {1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 658: 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656, 1656}, + {1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 658: 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655}, + {1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 658: 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654}, + {1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 658: 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653}, + {1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 658: 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652}, // 360 - {1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 657: 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643}, - {1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 657: 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642}, - {1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 657: 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641}, - {1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 657: 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640}, - {1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 657: 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639}, + {1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 658: 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651}, + {1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 658: 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650}, + {1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 658: 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649}, + {1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 658: 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648}, + {1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 658: 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1647}, // 365 - {1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 657: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638}, - {1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 657: 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637}, - {1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 657: 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636}, - {1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 657: 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635}, - {1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1185, 1634, 1634, 1634, 1634, 468: 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 479: 1634, 1634, 482: 1634, 1634, 1634, 1634, 1634, 488: 1634, 490: 1634, 1634, 1634, 1634, 495: 1634, 497: 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 533: 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 571: 1634, 642: 1634, 645: 1634, 1634}, + {1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 658: 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646}, + {1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 658: 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645}, + {1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 658: 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644}, + {1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 658: 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643}, + {1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 658: 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642}, // 370 - {1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 657: 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633}, - {1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 657: 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632}, - {1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 657: 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631}, - {1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 657: 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630}, - {1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 657: 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629}, + {1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 658: 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641}, + {1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 658: 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640, 1640}, + {1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 658: 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639, 1639}, + {1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1189, 1638, 1638, 1638, 1638, 1638, 472: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 485: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 494: 1638, 1638, 1638, 1638, 501: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 537: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 575: 1638, 643: 1638, 646: 1638, 1638}, + {1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 658: 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637}, // 375 - {1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 657: 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628}, - {1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 657: 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627}, - {1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 657: 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626}, - {1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 657: 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625}, - {1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 657: 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624}, + {1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 658: 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636, 1636}, + {1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 658: 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635}, + {1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 658: 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634}, + {1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 658: 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633, 1633}, + {1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 658: 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632}, // 380 - {1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 657: 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623}, - {1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 657: 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622}, - {1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 657: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621}, - {1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 657: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620}, - {1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 657: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619}, + {1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 658: 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631}, + {1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 658: 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630, 1630}, + {1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 658: 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629}, + {1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 658: 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628}, + {1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 658: 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627}, // 385 - {1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 657: 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618}, - {1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1183, 1617, 1617, 1617, 1617, 468: 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 479: 1617, 1617, 482: 1617, 1617, 1617, 1617, 1617, 488: 1617, 490: 1617, 1617, 1617, 1617, 495: 1617, 497: 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 533: 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 571: 1617, 642: 1617, 645: 1617, 1617}, - {1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1202, 1616, 1616, 1616, 1616, 468: 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 479: 1616, 1616, 482: 1616, 1616, 1616, 1616, 1616, 488: 1616, 490: 1616, 1616, 1616, 1616, 495: 1616, 497: 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 533: 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 571: 1616, 642: 1616, 645: 1616, 1616}, - {1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1190, 1615, 1615, 1615, 1615, 468: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 479: 1615, 1615, 482: 1615, 1615, 1615, 1615, 1615, 488: 1615, 490: 1615, 1615, 1615, 1615, 495: 1615, 497: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 533: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 571: 1615, 642: 1615, 645: 1615, 1615}, - {1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 657: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614}, + {1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 658: 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626}, + {1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 658: 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625}, + {1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 658: 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624, 1624}, + {1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 658: 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623}, + {1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 658: 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622}, // 390 - {1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 657: 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613}, - {1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 657: 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612}, - {1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1192, 1611, 1611, 1611, 1611, 468: 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 479: 1611, 1611, 482: 1611, 1611, 1611, 1611, 1611, 488: 1611, 490: 1611, 1611, 1611, 1611, 495: 1611, 497: 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 533: 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 571: 1611, 642: 1611, 645: 1611, 1611}, - {1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1191, 1610, 1610, 1610, 1610, 468: 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 479: 1610, 1610, 482: 1610, 1610, 1610, 1610, 1610, 488: 1610, 490: 1610, 1610, 1610, 1610, 495: 1610, 497: 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 533: 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 571: 1610, 642: 1610, 645: 1610, 1610}, - {1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 657: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609}, + {1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1187, 1621, 1621, 1621, 1621, 1621, 472: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 485: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 494: 1621, 1621, 1621, 1621, 501: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 537: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 575: 1621, 643: 1621, 646: 1621, 1621}, + {1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1206, 1620, 1620, 1620, 1620, 1620, 472: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 485: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 494: 1620, 1620, 1620, 1620, 501: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 537: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 575: 1620, 643: 1620, 646: 1620, 1620}, + {1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1194, 1619, 1619, 1619, 1619, 1619, 472: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 485: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 494: 1619, 1619, 1619, 1619, 501: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 537: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 575: 1619, 643: 1619, 646: 1619, 1619}, + {1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 658: 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618, 1618}, + {1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 658: 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617}, // 395 - {1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 657: 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608}, - {1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 657: 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607}, - {1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 657: 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606}, - {1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1182, 1605, 1605, 1605, 1605, 468: 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 479: 1605, 1605, 482: 1605, 1605, 1605, 1605, 1605, 488: 1605, 490: 1605, 1605, 1605, 1605, 495: 1605, 497: 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 533: 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 571: 1605, 642: 1605, 645: 1605, 1605}, - {1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 657: 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604}, + {1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 658: 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616}, + {1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1196, 1615, 1615, 1615, 1615, 1615, 472: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 485: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 494: 1615, 1615, 1615, 1615, 501: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 537: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 575: 1615, 643: 1615, 646: 1615, 1615}, + {1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1195, 1614, 1614, 1614, 1614, 1614, 472: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 485: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 494: 1614, 1614, 1614, 1614, 501: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 537: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 575: 1614, 643: 1614, 646: 1614, 1614}, + {1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 658: 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613}, + {1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 658: 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612}, // 400 - {1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 657: 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603}, - {1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 657: 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602}, - {1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 657: 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601}, - {1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 657: 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600}, - {1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 657: 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599}, + {1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 658: 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611}, + {1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 658: 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610}, + {1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1186, 1609, 1609, 1609, 1609, 1609, 472: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 485: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 494: 1609, 1609, 1609, 1609, 501: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 537: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 575: 1609, 643: 1609, 646: 1609, 1609}, + {1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 658: 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608}, + {1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 658: 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607, 1607}, // 405 - {1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 657: 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598}, - {1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 657: 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597}, - {1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 657: 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596}, - {1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 657: 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595}, - {1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 657: 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594}, + {1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 658: 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606, 1606}, + {1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 658: 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605}, + {1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 658: 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604, 1604}, + {1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 658: 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603, 1603}, + {1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 658: 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602}, // 410 - {1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 657: 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593}, - {1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 657: 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592}, - {1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 657: 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591}, - {1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 657: 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590}, - {1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 657: 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589}, + {1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 658: 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601, 1601}, + {1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 658: 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600}, + {1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 658: 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599, 1599}, + {1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 658: 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598, 1598}, + {1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 658: 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597, 1597}, // 415 - {1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 657: 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588}, - {1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 657: 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587}, - {1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 657: 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586}, - {1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 657: 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585}, - {1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 657: 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584}, + {1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 658: 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596, 1596}, + {1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 658: 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595, 1595}, + {1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 658: 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594}, + {1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 658: 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593, 1593}, + {1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 658: 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592, 1592}, // 420 - {1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 657: 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583}, - {1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 657: 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582}, - {1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 657: 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581}, - {1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 657: 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580}, - {1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 657: 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579}, + {1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 658: 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591, 1591}, + {1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 658: 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590}, + {1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 658: 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589, 1589}, + {1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 658: 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588, 1588}, + {1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 658: 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587}, // 425 - {1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 657: 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578}, - {1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 657: 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577}, - {1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 657: 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576}, - {1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 657: 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575}, - {1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 657: 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574}, + {1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 658: 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586, 1586}, + {1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 658: 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585, 1585}, + {1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 658: 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584, 1584}, + {1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 658: 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583, 1583}, + {1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 658: 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582, 1582}, // 430 - {1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 657: 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573}, - {1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 657: 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572}, - {1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 657: 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571}, - {1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 657: 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570}, - {1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 657: 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569}, + {1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 658: 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581, 1581}, + {1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 658: 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580, 1580}, + {1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 658: 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579}, + {1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 658: 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578, 1578}, + {1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 658: 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577}, // 435 - {1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 657: 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568}, - {1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 657: 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567}, - {1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 657: 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566}, - {1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 657: 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565}, - {1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 657: 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564}, + {1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 658: 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576, 1576}, + {1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 658: 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575, 1575}, + {1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 658: 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574, 1574}, + {1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 658: 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573}, + {1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 658: 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572, 1572}, // 440 - {1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 657: 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563}, - {1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 657: 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562}, - {1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 657: 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561}, - {1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 657: 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560}, - {1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 657: 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559}, + {1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 658: 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571}, + {1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 658: 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570, 1570}, + {1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 658: 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569, 1569}, + {1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 658: 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568}, + {1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 658: 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567, 1567}, // 445 - {1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 657: 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558}, - {1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 657: 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557}, - {1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 657: 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556}, - {1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 657: 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555}, - {1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 657: 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554}, + {1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 658: 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566}, + {1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 658: 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565, 1565}, + {1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 658: 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564, 1564}, + {1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 658: 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563}, + {1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 658: 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562}, // 450 - {1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 657: 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553}, - {1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 657: 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552}, - {1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 657: 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551}, - {1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 657: 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550}, - {1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 657: 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549}, + {1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 658: 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1561}, + {1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 658: 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560}, + {1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 658: 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559}, + {1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 658: 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558, 1558}, + {1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 658: 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557}, // 455 - {1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 657: 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548}, - {1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 657: 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547}, - {1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 657: 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546}, - {1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 657: 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545}, - {1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 657: 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544}, + {1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 658: 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556}, + {1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 658: 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555, 1555}, + {1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 658: 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554, 1554}, + {1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 658: 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553, 1553}, + {1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 658: 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552, 1552}, // 460 - {1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 657: 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543}, - {1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 657: 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542}, - {1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 657: 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541}, - {1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 657: 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540}, - {1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 657: 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539}, + {1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 658: 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551, 1551}, + {1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 658: 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550}, + {1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 658: 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549, 1549}, + {1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 658: 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548}, + {1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 658: 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547, 1547}, // 465 - {1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 657: 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538}, - {1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 657: 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537}, - {1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 657: 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536}, - {1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 657: 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535}, - {1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 657: 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534}, + {1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 658: 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1546}, + {1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 658: 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545, 1545}, + {1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 658: 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544, 1544}, + {1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 658: 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543, 1543}, + {1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 658: 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542}, // 470 - {1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 657: 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533}, - {1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 657: 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532}, - {1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 657: 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531}, - {1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 657: 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530}, - {1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 657: 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529}, + {1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 658: 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541}, + {1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 658: 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540}, + {1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 658: 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539, 1539}, + {1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 658: 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538, 1538}, + {1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 658: 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537, 1537}, // 475 - {1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 657: 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528}, - {1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 657: 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527}, - {1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 657: 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526}, - {1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 657: 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525}, - {1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 657: 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524}, + {1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 658: 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536}, + {1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 658: 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535, 1535}, + {1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 658: 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1534}, + {1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 658: 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1533}, + {1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 658: 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532, 1532}, // 480 - {1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 657: 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523}, - {1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 657: 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522}, - {1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 657: 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521}, - {1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 657: 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520}, - {1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 657: 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519}, + {1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 658: 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531}, + {1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 658: 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530, 1530}, + {1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 658: 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529, 1529}, + {1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 658: 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528, 1528}, + {1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 658: 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527}, // 485 - {1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 657: 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518}, - {1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 657: 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517}, - {1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 657: 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516}, - {1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 657: 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515}, - {1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 657: 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514}, + {1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 658: 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526}, + {1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 658: 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525, 1525}, + {1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 658: 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524, 1524}, + {1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 658: 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523, 1523}, + {1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 658: 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1522}, // 490 - {1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 657: 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513}, - {1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 657: 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512}, - {1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 657: 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511}, - {1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 657: 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510}, - {1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 657: 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509}, + {1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 658: 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521}, + {1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 658: 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520}, + {1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 658: 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519}, + {1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 658: 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518}, + {1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 658: 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517}, // 495 - {1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 657: 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508}, - {1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 657: 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507}, - {1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 657: 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506}, - {1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 657: 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505}, - {1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 657: 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504}, + {1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 658: 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516, 1516}, + {1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 658: 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515, 1515}, + {1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 658: 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514, 1514}, + {1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 658: 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513}, + {1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 658: 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512, 1512}, // 500 - {1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 657: 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503}, - {1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 657: 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502}, - {1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 657: 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501}, - {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 657: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}, - {1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 657: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499}, + {1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 658: 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511}, + {1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 658: 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510, 1510}, + {1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 658: 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509, 1509}, + {1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 658: 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508, 1508}, + {1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 658: 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507, 1507}, // 505 - {1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 657: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498}, - {1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 657: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497}, - {1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 3958, 1494, 1494, 1494, 1494, 468: 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 479: 1494, 1494, 482: 1494, 1494, 1494, 1494, 1494, 488: 1494, 490: 1494, 1494, 1494, 1494, 495: 1494, 497: 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 533: 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 571: 1494, 642: 1494, 645: 1494, 1494}, - {1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 3947, 1493, 1493, 1493, 1493, 468: 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 479: 1493, 1493, 482: 1493, 1493, 1493, 1493, 1493, 488: 1493, 490: 1493, 1493, 1493, 1493, 495: 1493, 497: 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 533: 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 571: 1493, 642: 1493, 645: 1493, 1493}, - {1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 657: 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492}, + {1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 658: 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506}, + {1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 658: 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505}, + {1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 658: 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504}, + {1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 658: 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503, 1503}, + {1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 658: 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502, 1502}, // 510 - {1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 657: 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491}, - {1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 657: 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490}, - {1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 657: 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489}, - {1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 657: 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488}, - {1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 657: 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487}, + {1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 658: 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501, 1501}, + {1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 3976, 1498, 1498, 1498, 1498, 1498, 472: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 485: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 494: 1498, 1498, 1498, 1498, 501: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 537: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 575: 1498, 643: 1498, 646: 1498, 1498}, + {1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 3965, 1497, 1497, 1497, 1497, 1497, 472: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 485: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 494: 1497, 1497, 1497, 1497, 501: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 537: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 575: 1497, 643: 1497, 646: 1497, 1497}, + {1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 658: 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496}, + {1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 658: 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495}, // 515 - {1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 657: 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486}, - {1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 657: 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485}, - {1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 657: 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484}, - {1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 657: 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483}, - {1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 657: 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482}, + {1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 658: 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494}, + {1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 658: 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493}, + {1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 658: 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492, 1492}, + {1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 658: 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491, 1491}, + {1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 658: 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490}, // 520 - {1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 657: 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481}, - {1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 657: 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480}, - {1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 657: 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479}, - {1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 657: 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478}, - {1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 657: 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477}, + {1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 658: 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489}, + {1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 658: 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488, 1488}, + {1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 658: 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487, 1487}, + {1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 658: 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486, 1486}, + {1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 658: 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485, 1485}, // 525 - {1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 657: 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476}, - {1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 657: 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475}, - {1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 657: 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474}, - {1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 657: 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473}, - {1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 657: 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472}, + {1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 658: 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484, 1484}, + {1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 658: 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483, 1483}, + {1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 658: 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482, 1482}, + {1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 658: 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481}, + {1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 658: 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480}, // 530 - {1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 657: 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471}, - {1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 657: 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470}, - {1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 657: 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469}, - {1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 657: 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468}, - {1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 657: 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467}, + {1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 658: 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479, 1479}, + {1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 658: 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478, 1478}, + {1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 658: 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477}, + {1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 658: 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476, 1476}, + {1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 658: 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475}, // 535 - {1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 657: 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466}, - {1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 657: 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465}, - {1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 657: 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464}, - {1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 657: 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463}, - {1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 657: 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462}, + {1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 658: 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474}, + {1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 658: 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473, 1473}, + {1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 658: 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472}, + {1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 658: 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471, 1471}, + {1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 658: 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470, 1470}, // 540 - {1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 657: 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461}, - {1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 657: 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460}, - {1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 657: 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459}, - {1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 657: 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458}, - {1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 657: 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457}, + {1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 658: 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469, 1469}, + {1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 658: 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468}, + {1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 658: 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467}, + {1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 658: 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466, 1466}, + {1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 658: 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1465}, // 545 - {1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 657: 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456}, - {1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 657: 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455}, - {1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 657: 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454}, - {1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 657: 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453}, - {1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 657: 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452}, + {1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 658: 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464}, + {1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 658: 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463}, + {1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 658: 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462}, + {1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 658: 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461, 1461}, + {1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 658: 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460, 1460}, // 550 - {1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 657: 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451}, - {1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 657: 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450}, - {1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 657: 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449}, - {1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 657: 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448}, - {1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 657: 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447}, + {1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 658: 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459, 1459}, + {1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 658: 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458}, + {1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 658: 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457, 1457}, + {1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 658: 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456, 1456}, + {1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 658: 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455}, // 555 - {1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 657: 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446}, - {1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 657: 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445}, - {1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 657: 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444}, - {1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 657: 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443}, - {1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 657: 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442}, + {1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 658: 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454, 1454}, + {1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 658: 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453}, + {1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 658: 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452, 1452}, + {1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 658: 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451, 1451}, + {1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 658: 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450}, // 560 - {1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 657: 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441}, - {1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 657: 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440}, - {1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 657: 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439}, - {1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 657: 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438}, - {1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 657: 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437}, + {1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 658: 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449}, + {1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 658: 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448}, + {1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 658: 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447, 1447}, + {1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 658: 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446, 1446}, + {1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 658: 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445, 1445}, // 565 - {1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 657: 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436}, - {1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 657: 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435}, - {1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 657: 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434}, - {1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 657: 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433}, - {1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 657: 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432}, + {1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 658: 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444, 1444}, + {1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 658: 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443}, + {1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 658: 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442}, + {1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 658: 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441, 1441}, + {1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 658: 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440}, // 570 - {1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 657: 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431}, - {1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 657: 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430}, - {1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 657: 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429}, - {1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 657: 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428}, - {1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 657: 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427}, + {1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 658: 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439}, + {1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 658: 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438, 1438}, + {1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 658: 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437}, + {1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 658: 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436, 1436}, + {1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 658: 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1435}, // 575 - {1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 657: 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426}, - {1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 657: 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425}, - {1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 657: 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424}, - {1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 657: 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423}, - {1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 657: 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422}, + {1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 658: 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434, 1434}, + {1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 658: 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433, 1433}, + {1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 658: 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432}, + {1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 658: 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431}, + {1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 658: 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430}, // 580 - {1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 657: 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421}, - {1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 657: 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420}, - {1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 657: 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419}, - {1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 657: 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418}, - {1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 657: 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417}, + {1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 658: 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429, 1429}, + {1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 658: 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428}, + {1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 658: 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427}, + {1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 658: 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426}, + {1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 658: 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425}, // 585 - {1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 657: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416}, - {1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 657: 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415}, - {1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 657: 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414}, - {1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 657: 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413}, - {1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 657: 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412}, + {1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 658: 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424, 1424}, + {1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 658: 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423}, + {1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 658: 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422}, + {1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 658: 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421, 1421}, + {1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 658: 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420, 1420}, // 590 - {1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 657: 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411}, - {1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 657: 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410}, - {1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 657: 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409}, - {1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 657: 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408}, - {1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 657: 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407}, + {1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 658: 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419, 1419}, + {1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 658: 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418}, + {1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 658: 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417, 1417}, + {1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1125, 1416, 1416, 1416, 1416, 1416, 472: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 485: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 494: 1416, 1416, 1416, 1416, 501: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 537: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 575: 1416, 643: 1416, 646: 1416, 1416}, + {1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 658: 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415}, // 595 - {1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 657: 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406}, - {1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 657: 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405}, - {1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 657: 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404}, - {1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 657: 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403}, - {1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 657: 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402}, + {1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 658: 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414}, + {1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 658: 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413, 1413}, + {1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 658: 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412}, + {1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 658: 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411, 1411}, + {1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 658: 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410}, // 600 - {1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 657: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401}, - {1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 657: 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400}, - {1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 657: 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399}, - {1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 657: 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398}, - {1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 3938, 1397, 1397, 1397, 1397, 468: 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 479: 1397, 1397, 482: 1397, 1397, 1397, 1397, 1397, 488: 1397, 490: 1397, 1397, 1397, 1397, 495: 1397, 497: 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 533: 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 571: 1397, 642: 1397, 645: 1397, 1397}, + {1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 658: 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409}, + {1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 658: 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408}, + {1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 658: 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407}, + {1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 658: 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406, 1406}, + {1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 658: 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405}, // 605 - {1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 657: 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396}, - {1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 657: 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395}, - {1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 657: 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394}, - {1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 657: 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393}, - {1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 657: 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392}, + {1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 658: 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404, 1404}, + {1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 658: 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403, 1403}, + {1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 658: 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402}, + {1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 3956, 1401, 1401, 1401, 1401, 1401, 472: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 485: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 494: 1401, 1401, 1401, 1401, 501: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 537: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 575: 1401, 643: 1401, 646: 1401, 1401}, + {1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 658: 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400}, // 610 - {1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 657: 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391}, - {1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 657: 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390}, - {1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 657: 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389}, - {1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 657: 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388}, - {1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 657: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387}, + {1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 658: 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399}, + {1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 658: 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398, 1398}, + {1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 658: 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397}, + {1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 658: 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1396}, + {1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 658: 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395, 1395}, // 615 - {1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 657: 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386}, - {1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 657: 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385}, - {1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 657: 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384}, - {1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 657: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383}, - {1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 657: 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382}, + {1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 658: 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394, 1394}, + {1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 658: 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393}, + {1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 658: 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392, 1392}, + {1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 658: 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391}, + {1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 658: 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390}, // 620 - {1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 657: 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381}, - {1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 657: 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380}, - {1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 657: 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379}, - {1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 657: 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378}, - {1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 657: 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377}, + {1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 658: 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389}, + {1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 658: 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388}, + {1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 658: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387}, + {1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 658: 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386}, + {1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 658: 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385}, // 625 - {1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 657: 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376}, - {1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 657: 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375}, - {1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 657: 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374}, - {1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 657: 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373}, - {1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 657: 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372}, + {1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 658: 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384, 1384}, + {1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1124, 1383, 1383, 1383, 1383, 1383, 472: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 485: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 494: 1383, 1383, 1383, 1383, 501: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 537: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 575: 1383, 643: 1383, 646: 1383, 1383}, + {1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 658: 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382}, + {1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 658: 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381, 1381}, + {1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 658: 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380, 1380}, // 630 - {1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 657: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371}, - {1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 657: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370}, - {1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 657: 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369}, - {1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 657: 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368}, - {1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 3931, 1367, 1367, 1367, 1367, 468: 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 479: 1367, 1367, 482: 1367, 1367, 1367, 1367, 1367, 488: 1367, 490: 1367, 1367, 1367, 1367, 495: 1367, 497: 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 533: 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 571: 1367, 642: 1367, 645: 1367, 1367}, + {1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 658: 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379, 1379}, + {1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 658: 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378, 1378}, + {1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 658: 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377}, + {1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 658: 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376}, + {1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 658: 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375}, // 635 - {1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 3924, 1366, 1366, 1366, 1366, 468: 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 479: 1366, 1366, 482: 1366, 1366, 1366, 1366, 1366, 488: 1366, 490: 1366, 1366, 1366, 1366, 495: 1366, 497: 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 533: 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 571: 1366, 642: 1366, 645: 1366, 1366}, - {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 657: 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365}, - {1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 657: 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364}, - {1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 657: 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363}, - {1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 657: 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362}, + {1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 658: 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374, 1374}, + {1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 658: 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373, 1373}, + {1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 658: 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372, 1372}, + {1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 3949, 1371, 1371, 1371, 1371, 1371, 472: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 485: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 494: 1371, 1371, 1371, 1371, 501: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 537: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 575: 1371, 643: 1371, 646: 1371, 1371}, + {1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 3942, 1370, 1370, 1370, 1370, 1370, 472: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 485: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 494: 1370, 1370, 1370, 1370, 501: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 537: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 575: 1370, 643: 1370, 646: 1370, 1370}, // 640 - {1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 657: 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361}, - {1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 657: 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360}, - {1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 657: 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359}, - {1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 657: 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358}, - {1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 657: 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357}, + {1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 658: 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369}, + {1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 658: 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368, 1368}, + {1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 658: 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367}, + {1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 658: 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366}, + {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 658: 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365}, // 645 - {1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 657: 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356}, - {1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 657: 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355}, - {1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 657: 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354}, - {1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 657: 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353}, - {1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 657: 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352}, + {1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 658: 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364}, + {1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 658: 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1363}, + {1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 658: 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362, 1362}, + {1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 658: 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361}, + {1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 658: 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360}, // 650 - {1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 657: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351}, - {1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 657: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350}, - {1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 657: 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349}, - {1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 657: 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348}, - {1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 3904, 1347, 1347, 1347, 1347, 468: 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 479: 1347, 1347, 482: 1347, 1347, 1347, 1347, 1347, 488: 1347, 490: 1347, 1347, 1347, 1347, 495: 1347, 497: 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 533: 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 571: 1347, 642: 1347, 645: 1347, 1347}, + {1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 658: 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359}, + {1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 658: 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358}, + {1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 658: 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357}, + {1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 658: 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356}, + {1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 658: 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355}, // 655 - {1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 3896, 1346, 1346, 1346, 1346, 468: 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 479: 1346, 1346, 482: 1346, 1346, 1346, 1346, 1346, 488: 1346, 490: 1346, 1346, 1346, 1346, 495: 1346, 497: 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 533: 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 571: 1346, 642: 1346, 645: 1346, 1346}, - {1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 657: 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345}, - {1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 657: 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344}, - {1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 657: 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343}, - {1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 657: 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342}, + {1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 658: 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354}, + {1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 658: 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353, 1353}, + {1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 658: 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352}, + {1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 3922, 1351, 1351, 1351, 1351, 1351, 472: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 485: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 494: 1351, 1351, 1351, 1351, 501: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 537: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 575: 1351, 643: 1351, 646: 1351, 1351}, + {1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 3914, 1350, 1350, 1350, 1350, 1350, 472: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 485: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 494: 1350, 1350, 1350, 1350, 501: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 537: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 575: 1350, 643: 1350, 646: 1350, 1350}, // 660 - {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 657: 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341}, - {1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 657: 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340}, - {1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 657: 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339}, - {1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 657: 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338}, - {1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 657: 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337}, + {1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 658: 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349}, + {1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 658: 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348}, + {1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 658: 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347}, + {1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 658: 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346}, + {1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 658: 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1345}, // 665 - {1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 657: 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336}, - {1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 657: 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335}, - {1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 657: 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334}, - {1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 657: 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333}, - {1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 657: 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332}, + {1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 658: 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344}, + {1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 658: 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343}, + {1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 658: 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342}, + {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 658: 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341}, + {1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 658: 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340}, // 670 - {1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 657: 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331}, - {1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 657: 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330}, - {1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 463: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 488: 1292, 490: 1292, 1292, 1292, 1292, 495: 1292, 497: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 533: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 566: 1292, 571: 1292, 574: 1292, 576: 1292, 632: 1292, 1292, 635: 1292, 1292}, - {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 463: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 488: 1291, 490: 1291, 1291, 1291, 1291, 495: 1291, 497: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 533: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 566: 1291, 571: 1291, 574: 1291, 576: 1291, 632: 1291, 1291, 635: 1291, 1291}, - {1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 463: 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 488: 1290, 490: 1290, 1290, 1290, 1290, 495: 1290, 497: 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 533: 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 566: 1290, 571: 1290, 574: 1290, 576: 1290, 632: 1290, 1290, 635: 1290, 1290}, + {1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 658: 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339, 1339}, + {1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 658: 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338}, + {1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 658: 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337}, + {1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 658: 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336}, + {1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 658: 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335}, // 675 - {1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 463: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 488: 1289, 490: 1289, 1289, 1289, 1289, 495: 1289, 497: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 533: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 566: 1289, 571: 1289, 574: 1289, 576: 1289, 632: 1289, 1289, 635: 1289, 1289}, - {1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 463: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 488: 1288, 490: 1288, 1288, 1288, 1288, 495: 1288, 497: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 533: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 566: 1288, 571: 1288, 574: 1288, 576: 1288, 632: 1288, 1288, 635: 1288, 1288}, - {1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 463: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 488: 1287, 490: 1287, 1287, 1287, 1287, 495: 1287, 497: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 533: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 566: 1287, 571: 1287, 574: 1287, 576: 1287, 632: 1287, 1287, 635: 1287, 1287}, - {1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 463: 1286, 3895, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 488: 1286, 490: 1286, 1286, 1286, 1286, 495: 1286, 497: 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 533: 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 566: 1286, 571: 1286, 574: 1286, 576: 1286, 632: 1286, 1286, 635: 1286, 1286}, - {464: 3892, 565: 3893, 569: 3894}, + {1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 658: 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334}, + {1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 466: 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 494: 1296, 1296, 1296, 1296, 501: 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 537: 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 565: 1296, 574: 1296, 1296, 1296, 586: 1296, 616: 1296, 635: 1296, 1296}, + {1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 466: 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 494: 1295, 1295, 1295, 1295, 501: 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 537: 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 565: 1295, 574: 1295, 1295, 1295, 586: 1295, 616: 1295, 635: 1295, 1295}, + {1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 466: 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 494: 1294, 1294, 1294, 1294, 501: 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 537: 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 565: 1294, 574: 1294, 1294, 1294, 586: 1294, 616: 1294, 635: 1294, 1294}, + {1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 466: 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 494: 1293, 1293, 1293, 1293, 501: 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 537: 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 1293, 565: 1293, 574: 1293, 1293, 1293, 586: 1293, 616: 1293, 635: 1293, 1293}, // 680 - {1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 463: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 488: 1284, 490: 1284, 1284, 1284, 1284, 495: 1284, 497: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 533: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 566: 1284, 571: 1284, 574: 1284, 576: 1284, 632: 1284, 1284, 635: 1284, 1284}, - {1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 463: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 488: 1283, 490: 1283, 1283, 1283, 1283, 495: 1283, 497: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 533: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 566: 1283, 571: 1283, 574: 1283, 576: 1283, 632: 1283, 1283, 635: 1283, 1283}, - {1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 463: 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 488: 1280, 490: 1280, 1280, 1280, 1280, 495: 1280, 497: 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 533: 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 566: 1280, 571: 1280, 574: 1280, 576: 1280, 632: 1280, 1280, 635: 1280, 1280}, - {1275, 1275, 7: 3313, 57: 1275, 124: 1275, 461: 1275, 463: 1275, 469: 1275, 471: 1275, 479: 1275, 1275, 482: 1275, 1275, 1275, 486: 1275, 491: 1275}, - {1274, 1274, 7: 1274, 57: 1274, 124: 1274, 461: 1274, 463: 1274, 469: 1274, 471: 1274, 479: 1274, 1274, 482: 1274, 1274, 1274, 486: 1274, 491: 1274, 493: 1274, 504: 1274, 1274, 513: 1274, 516: 1274, 1274}, + {1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 466: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 494: 1292, 1292, 1292, 1292, 501: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 537: 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 1292, 565: 1292, 574: 1292, 1292, 1292, 586: 1292, 616: 1292, 635: 1292, 1292}, + {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 466: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 494: 1291, 1291, 1291, 1291, 501: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 537: 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 565: 1291, 574: 1291, 1291, 1291, 586: 1291, 616: 1291, 635: 1291, 1291}, + {1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 466: 1290, 1290, 3913, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 494: 1290, 1290, 1290, 1290, 501: 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 537: 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 565: 1290, 574: 1290, 1290, 1290, 586: 1290, 616: 1290, 635: 1290, 1290}, + {468: 3910, 569: 3911, 572: 3912}, + {1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 466: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 494: 1288, 1288, 1288, 1288, 501: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 537: 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 565: 1288, 574: 1288, 1288, 1288, 586: 1288, 616: 1288, 635: 1288, 1288}, // 685 - {1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 463: 1249, 1249, 1249, 1249, 468: 1249, 1249, 3253, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 479: 1249, 1249, 482: 1249, 1249, 1249, 1249, 1249, 488: 1249, 490: 1249, 1249, 1249, 1249, 495: 1249, 497: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 533: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 571: 3254}, - {1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 463: 1248, 1248, 1248, 1248, 468: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 479: 1248, 1248, 482: 1248, 1248, 1248, 1248, 1248, 488: 1248, 490: 1248, 1248, 1248, 1248, 495: 1248, 497: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 533: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 571: 1248, 642: 3887, 645: 1248, 1248}, - {1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 463: 1245, 1245, 1245, 1245, 468: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 479: 1245, 1245, 482: 1245, 1245, 1245, 1245, 1245, 488: 1245, 490: 1245, 1245, 1245, 1245, 495: 1245, 497: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 533: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 571: 1245, 645: 3883, 3884}, - {1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 463: 1244, 1244, 1244, 1244, 468: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 479: 1244, 1244, 482: 1244, 1244, 1244, 1244, 1244, 488: 1244, 490: 1244, 1244, 1244, 1244, 495: 1244, 497: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 533: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 571: 1244}, - {1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 463: 1243, 1243, 1243, 1243, 468: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 479: 1243, 1243, 482: 1243, 1243, 1243, 1243, 1243, 488: 1243, 490: 1243, 1243, 1243, 1243, 495: 1243, 497: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 533: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 571: 1243}, + {1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 466: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 494: 1287, 1287, 1287, 1287, 501: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 537: 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 565: 1287, 574: 1287, 1287, 1287, 586: 1287, 616: 1287, 635: 1287, 1287}, + {1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 466: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 494: 1284, 1284, 1284, 1284, 501: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 537: 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 565: 1284, 574: 1284, 1284, 1284, 586: 1284, 616: 1284, 635: 1284, 1284}, + {1279, 1279, 7: 3331, 47: 1279, 125: 1279, 464: 1279, 466: 1279, 472: 1279, 1279, 480: 1279, 1279, 485: 1279, 1279, 1279, 1279, 491: 1279}, + {1278, 1278, 7: 1278, 47: 1278, 125: 1278, 464: 1278, 466: 1278, 472: 1278, 1278, 480: 1278, 1278, 485: 1278, 1278, 1278, 1278, 491: 1278, 494: 1278, 507: 1278, 1278, 516: 1278, 519: 1278, 1278}, + {1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 466: 1253, 1253, 1253, 1253, 1253, 472: 1253, 1253, 3269, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 485: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 494: 1253, 1253, 1253, 1253, 501: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 537: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 575: 3270}, // 690 - {1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 463: 1242, 1242, 1242, 1242, 468: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 479: 1242, 1242, 482: 1242, 1242, 1242, 1242, 1242, 488: 1242, 490: 1242, 1242, 1242, 1242, 495: 1242, 497: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 533: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 571: 1242}, - {1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 463: 1240, 1240, 1240, 1240, 468: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 479: 1240, 1240, 482: 1240, 1240, 1240, 1240, 1240, 488: 1240, 490: 1240, 1240, 1240, 1240, 495: 1240, 497: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 533: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 571: 1240}, - {1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 463: 1239, 1239, 1239, 1239, 468: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 479: 1239, 1239, 482: 1239, 1239, 1239, 1239, 1239, 488: 1239, 490: 1239, 1239, 1239, 1239, 495: 1239, 497: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 533: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 571: 1239}, - {1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 463: 1238, 1238, 1238, 1238, 468: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 479: 1238, 1238, 482: 1238, 1238, 1238, 1238, 1238, 488: 1238, 490: 1238, 1238, 1238, 1238, 495: 1238, 497: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 533: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 571: 1238}, - {1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 463: 1237, 1237, 1237, 1237, 468: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 479: 1237, 1237, 482: 1237, 1237, 1237, 1237, 1237, 488: 1237, 490: 1237, 1237, 1237, 1237, 495: 1237, 497: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 533: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 571: 1237}, + {1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 466: 1252, 1252, 1252, 1252, 1252, 472: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 485: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 494: 1252, 1252, 1252, 1252, 501: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 537: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 575: 1252, 643: 3905, 646: 1252, 1252}, + {1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 466: 1249, 1249, 1249, 1249, 1249, 472: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 485: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 494: 1249, 1249, 1249, 1249, 501: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 537: 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 575: 1249, 646: 3901, 3902}, + {1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 466: 1248, 1248, 1248, 1248, 1248, 472: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 485: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 494: 1248, 1248, 1248, 1248, 501: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 537: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 575: 1248}, + {1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 466: 1247, 1247, 1247, 1247, 1247, 472: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 485: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 494: 1247, 1247, 1247, 1247, 501: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 537: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 575: 1247}, + {1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 466: 1246, 1246, 1246, 1246, 1246, 472: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 485: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 494: 1246, 1246, 1246, 1246, 501: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 537: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 575: 1246}, // 695 - {1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 463: 1236, 1236, 1236, 1236, 468: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 479: 1236, 1236, 482: 1236, 1236, 1236, 1236, 1236, 488: 1236, 490: 1236, 1236, 1236, 1236, 495: 1236, 497: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 533: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 571: 1236}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3882, 3155, 3238, 3154, 3151}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3881, 3155, 3238, 3154, 3151}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3880, 3155, 3238, 3154, 3151}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3879, 3155, 3238, 3154, 3151}, + {1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 466: 1244, 1244, 1244, 1244, 1244, 472: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 485: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 494: 1244, 1244, 1244, 1244, 501: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 537: 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 575: 1244}, + {1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 466: 1243, 1243, 1243, 1243, 1243, 472: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 485: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 494: 1243, 1243, 1243, 1243, 501: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 537: 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 575: 1243}, + {1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 466: 1242, 1242, 1242, 1242, 1242, 472: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 485: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 494: 1242, 1242, 1242, 1242, 501: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 537: 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 575: 1242}, + {1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 466: 1241, 1241, 1241, 1241, 1241, 472: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 485: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 494: 1241, 1241, 1241, 1241, 501: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 537: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 575: 1241}, + {1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 466: 1240, 1240, 1240, 1240, 1240, 472: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 485: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 494: 1240, 1240, 1240, 1240, 501: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 537: 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 575: 1240}, // 700 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3878, 3155, 3238, 3154, 3151}, - {1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 463: 1229, 1229, 1229, 1229, 468: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 479: 1229, 1229, 482: 1229, 1229, 1229, 1229, 1229, 488: 1229, 490: 1229, 1229, 1229, 1229, 495: 1229, 497: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 533: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 571: 1229}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 2508, 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3778, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 2506, 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 634: 2502, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3777, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3775, 741: 3780, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 3782, 3781, 3779, 766: 3776}, - {462: 3770}, - {462: 2509, 699: 3769}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3900, 3173, 3254, 3172, 3169}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3899, 3173, 3254, 3172, 3169}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3898, 3173, 3254, 3172, 3169}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3897, 3173, 3254, 3172, 3169}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3896, 3173, 3254, 3172, 3169}, // 705 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3766, 2676, 2677, 2675}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3765, 3155, 3238, 3154, 3151}, - {462: 3760}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 531: 1050, 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3747, 1186: 3748}, - {462: 3689}, + {1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 466: 1233, 1233, 1233, 1233, 1233, 472: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 485: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 494: 1233, 1233, 1233, 1233, 501: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 537: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 575: 1233}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 2522, 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3796, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 2520, 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 637: 2516, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3795, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3793, 742: 3798, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 3800, 3799, 3797, 766: 3794}, + {465: 3788}, + {465: 2523, 700: 3787}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3784, 2691, 2692, 2690}, // 710 - {462: 3686}, - {462: 3678}, - {462: 1199}, - {462: 1196}, - {462: 1195}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3783, 3173, 3254, 3172, 3169}, + {465: 3778}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 534: 1054, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3765, 1191: 3766}, + {465: 3707}, + {465: 3704}, // 715 - {462: 1193}, - {462: 1189}, - {462: 1187}, - {462: 1186}, - {462: 1184}, + {465: 3696}, + {465: 1203}, + {465: 1200}, + {465: 1199}, + {465: 1197}, // 720 - {1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 468: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 479: 1173, 1173, 482: 1173, 1173, 1173, 1173, 1173, 488: 1173, 490: 1173, 1173, 1173, 1173, 495: 1173, 497: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 533: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 571: 1173}, - {1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 468: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 479: 1172, 1172, 482: 1172, 1172, 1172, 1172, 1172, 488: 1172, 490: 1172, 1172, 1172, 1172, 495: 1172, 497: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 533: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 571: 1172}, - {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 468: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 479: 1171, 1171, 482: 1171, 1171, 1171, 1171, 1171, 488: 1171, 490: 1171, 1171, 1171, 1171, 495: 1171, 497: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 533: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 571: 1171}, - {1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 468: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 479: 1170, 1170, 482: 1170, 1170, 1170, 1170, 1170, 488: 1170, 490: 1170, 1170, 1170, 1170, 495: 1170, 497: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 533: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 571: 1170}, - {1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 468: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 479: 1169, 1169, 482: 1169, 1169, 1169, 1169, 1169, 488: 1169, 490: 1169, 1169, 1169, 1169, 495: 1169, 497: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 533: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 571: 1169}, + {465: 1193}, + {465: 1191}, + {465: 1190}, + {465: 1188}, + {1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 472: 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 485: 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 494: 1177, 1177, 1177, 1177, 501: 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 537: 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 575: 1177}, // 725 - {1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 468: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 479: 1168, 1168, 482: 1168, 1168, 1168, 1168, 1168, 488: 1168, 490: 1168, 1168, 1168, 1168, 495: 1168, 497: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 533: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 571: 1168}, - {1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 468: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 479: 1167, 1167, 482: 1167, 1167, 1167, 1167, 1167, 488: 1167, 490: 1167, 1167, 1167, 1167, 495: 1167, 497: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 533: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 571: 1167}, - {1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 468: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 479: 1166, 1166, 482: 1166, 1166, 1166, 1166, 1166, 488: 1166, 490: 1166, 1166, 1166, 1166, 495: 1166, 497: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 533: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 571: 1166}, - {1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 468: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 479: 1165, 1165, 482: 1165, 1165, 1165, 1165, 1165, 488: 1165, 490: 1165, 1165, 1165, 1165, 495: 1165, 497: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 533: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 571: 1165}, - {1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 468: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 479: 1164, 1164, 482: 1164, 1164, 1164, 1164, 1164, 488: 1164, 490: 1164, 1164, 1164, 1164, 495: 1164, 497: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 533: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 571: 1164}, + {1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 472: 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 485: 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 494: 1176, 1176, 1176, 1176, 501: 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 537: 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 575: 1176}, + {1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 472: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 485: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 494: 1175, 1175, 1175, 1175, 501: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 537: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 575: 1175}, + {1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 472: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 485: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 494: 1174, 1174, 1174, 1174, 501: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 537: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 575: 1174}, + {1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 472: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 485: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 494: 1173, 1173, 1173, 1173, 501: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 537: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 575: 1173}, + {1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 472: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 485: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 494: 1172, 1172, 1172, 1172, 501: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 537: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 575: 1172}, // 730 - {462: 3675}, - {462: 3672}, - {1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 3669, 1175, 1175, 1175, 1175, 468: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 479: 1175, 1175, 482: 1175, 1175, 1175, 1175, 1175, 488: 1175, 490: 1175, 1175, 1175, 1175, 495: 1175, 497: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 533: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 571: 1175, 1074: 3670}, - {462: 3667}, - {1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 3663, 1082, 1082, 1082, 1082, 468: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 479: 1082, 1082, 482: 1082, 1082, 1082, 1082, 1082, 488: 1082, 490: 1082, 1082, 1082, 1082, 495: 1082, 497: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 533: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 571: 1082, 1199: 3662}, + {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 472: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 485: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 494: 1171, 1171, 1171, 1171, 501: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 537: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 575: 1171}, + {1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 472: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 485: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 494: 1170, 1170, 1170, 1170, 501: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 537: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 575: 1170}, + {1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 472: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 485: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 494: 1169, 1169, 1169, 1169, 501: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 537: 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 1169, 575: 1169}, + {1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 472: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 485: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 494: 1168, 1168, 1168, 1168, 501: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 537: 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 575: 1168}, + {465: 3693}, // 735 - {462: 3654}, - {462: 3650}, - {462: 3645}, - {462: 3642}, - {462: 3637}, + {465: 3690}, + {1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 3687, 1179, 1179, 1179, 1179, 1179, 472: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 485: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 494: 1179, 1179, 1179, 1179, 501: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 537: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 575: 1179, 1077: 3688}, + {465: 3685}, + {1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 3681, 1086, 1086, 1086, 1086, 1086, 472: 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 485: 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 494: 1086, 1086, 1086, 1086, 501: 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 537: 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 575: 1086, 1204: 3680}, + {465: 3672}, // 740 - {462: 3628}, - {462: 3621}, - {462: 3616}, - {462: 3581}, - {462: 3567}, + {465: 3668}, + {465: 3663}, + {465: 3660}, + {465: 3655}, + {465: 3646}, // 745 - {462: 3550}, - {1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 463: 1129, 1129, 1129, 1129, 468: 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 479: 1129, 1129, 482: 1129, 1129, 1129, 1129, 1129, 488: 1129, 490: 1129, 1129, 1129, 1129, 495: 1129, 497: 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 533: 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 571: 1129}, - {462: 3543}, - {462: 1123}, - {462: 1122}, + {465: 3639}, + {465: 3634}, + {465: 3599}, + {465: 3585}, + {465: 3568}, // 750 - {462: 1121}, - {462: 1120}, - {1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 463: 1114, 1114, 1114, 1114, 468: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 479: 1114, 1114, 482: 1114, 1114, 1114, 1114, 1114, 488: 1114, 490: 1114, 1114, 1114, 1114, 495: 1114, 497: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 533: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 571: 1114}, - {462: 3540}, - {462: 3537}, + {1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 466: 1133, 1133, 1133, 1133, 1133, 472: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 485: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 494: 1133, 1133, 1133, 1133, 501: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 537: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 575: 1133}, + {465: 3561}, + {465: 1127}, + {465: 1126}, + {1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 466: 1118, 1118, 1118, 1118, 1118, 472: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 485: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 494: 1118, 1118, 1118, 1118, 501: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 537: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 575: 1118}, // 755 - {462: 3529}, - {462: 3521}, - {462: 3513}, - {462: 3499}, - {462: 3487}, + {465: 3558}, + {465: 3555}, + {465: 3547}, + {465: 3539}, + {465: 3531}, // 760 - {462: 3482}, - {462: 3477}, - {462: 3472}, - {462: 3467}, - {462: 3462}, + {465: 3517}, + {465: 3505}, + {465: 3500}, + {465: 3495}, + {465: 3490}, // 765 - {462: 3457}, - {462: 3444}, - {462: 3441}, - {462: 3438}, - {462: 3435}, + {465: 3485}, + {465: 3480}, + {465: 3475}, + {465: 3462}, + {465: 3459}, // 770 - {462: 3432}, - {462: 3429}, - {462: 3425}, - {462: 3419}, - {462: 3406}, + {465: 3456}, + {465: 3453}, + {465: 3450}, + {465: 3447}, + {465: 3443}, // 775 - {462: 3401}, - {462: 3396}, - {462: 3241}, - {724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 463: 724, 724, 724, 724, 468: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 479: 724, 724, 482: 724, 724, 724, 724, 724, 488: 724, 490: 724, 724, 724, 724, 495: 724, 497: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 533: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 571: 724}, - {723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 463: 723, 723, 723, 723, 468: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 479: 723, 723, 482: 723, 723, 723, 723, 723, 488: 723, 490: 723, 723, 723, 723, 495: 723, 497: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 533: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 571: 723}, + {465: 3437}, + {465: 3424}, + {465: 3419}, + {465: 3414}, + {465: 3257}, // 780 - {722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 463: 722, 722, 722, 722, 468: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 479: 722, 722, 482: 722, 722, 722, 722, 722, 488: 722, 490: 722, 722, 722, 722, 495: 722, 497: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 533: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 571: 722}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3242}, - {7: 3250, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3395}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3394}, + {728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 466: 728, 728, 728, 728, 728, 472: 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 485: 728, 728, 728, 728, 728, 728, 728, 728, 494: 728, 728, 728, 728, 501: 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 537: 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 575: 728}, + {727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 466: 727, 727, 727, 727, 727, 472: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 485: 727, 727, 727, 727, 727, 727, 727, 727, 494: 727, 727, 727, 727, 501: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 537: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 575: 727}, + {726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 466: 726, 726, 726, 726, 726, 472: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 485: 726, 726, 726, 726, 726, 726, 726, 726, 494: 726, 726, 726, 726, 501: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 537: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 575: 726}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3258}, + {7: 3266, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 785 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3393}, - {2: 1884, 1884, 1884, 1884, 1884, 8: 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 58: 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 462: 1884, 464: 1884, 1884, 1884, 1884, 472: 1884, 1884, 1884, 1884, 1884, 481: 1884, 487: 1884, 489: 1884, 494: 1884, 496: 1884, 532: 1884, 555: 1884, 557: 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 567: 1884, 1884, 1884, 1884, 572: 1884, 1884, 575: 1884, 577: 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 639: 1884}, - {2: 1883, 1883, 1883, 1883, 1883, 8: 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 58: 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 462: 1883, 464: 1883, 1883, 1883, 1883, 472: 1883, 1883, 1883, 1883, 1883, 481: 1883, 487: 1883, 489: 1883, 494: 1883, 496: 1883, 532: 1883, 555: 1883, 557: 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 567: 1883, 1883, 1883, 1883, 572: 1883, 1883, 575: 1883, 577: 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 639: 1883}, - {2: 1882, 1882, 1882, 1882, 1882, 8: 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 58: 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 462: 1882, 464: 1882, 1882, 1882, 1882, 472: 1882, 1882, 1882, 1882, 1882, 481: 1882, 487: 1882, 489: 1882, 494: 1882, 496: 1882, 532: 1882, 555: 1882, 557: 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 567: 1882, 1882, 1882, 1882, 572: 1882, 1882, 575: 1882, 577: 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 639: 1882}, - {2: 1881, 1881, 1881, 1881, 1881, 8: 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 58: 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 462: 1881, 464: 1881, 1881, 1881, 1881, 472: 1881, 1881, 1881, 1881, 1881, 481: 1881, 487: 1881, 489: 1881, 494: 1881, 496: 1881, 532: 1881, 555: 1881, 557: 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 567: 1881, 1881, 1881, 1881, 572: 1881, 1881, 575: 1881, 577: 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 639: 1881}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3413}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3412}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3411}, + {2: 1891, 1891, 1891, 1891, 1891, 8: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 48: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 465: 1891, 467: 1891, 1891, 1891, 471: 1891, 475: 1891, 1891, 1891, 1891, 1891, 484: 1891, 493: 1891, 498: 1891, 1891, 1891, 536: 1891, 558: 1891, 1891, 1891, 1891, 563: 1891, 1891, 566: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 577: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 587: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 617: 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 639: 1891}, + {2: 1890, 1890, 1890, 1890, 1890, 8: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 48: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 465: 1890, 467: 1890, 1890, 1890, 471: 1890, 475: 1890, 1890, 1890, 1890, 1890, 484: 1890, 493: 1890, 498: 1890, 1890, 1890, 536: 1890, 558: 1890, 1890, 1890, 1890, 563: 1890, 1890, 566: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 577: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 587: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 617: 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 639: 1890}, // 790 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3251, 3155, 3238, 3154, 3151}, - {57: 3255, 470: 3253, 571: 3254}, - {721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 463: 721, 721, 721, 721, 468: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 479: 721, 721, 482: 721, 721, 721, 721, 721, 488: 721, 490: 721, 721, 721, 721, 495: 721, 497: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 533: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 571: 721}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3390, 653: 3392, 2676, 2677, 2675, 728: 3389, 860: 3388}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3387, 3155, 3238, 3154, 3151}, + {2: 1889, 1889, 1889, 1889, 1889, 8: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 48: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 465: 1889, 467: 1889, 1889, 1889, 471: 1889, 475: 1889, 1889, 1889, 1889, 1889, 484: 1889, 493: 1889, 498: 1889, 1889, 1889, 536: 1889, 558: 1889, 1889, 1889, 1889, 563: 1889, 1889, 566: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 577: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 587: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 617: 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 639: 1889}, + {2: 1888, 1888, 1888, 1888, 1888, 8: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 48: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 465: 1888, 467: 1888, 1888, 1888, 471: 1888, 475: 1888, 1888, 1888, 1888, 1888, 484: 1888, 493: 1888, 498: 1888, 1888, 1888, 536: 1888, 558: 1888, 1888, 1888, 1888, 563: 1888, 1888, 566: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 577: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 587: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 617: 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 1888, 639: 1888}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3267, 3173, 3254, 3172, 3169}, + {47: 3271, 474: 3269, 575: 3270}, + {725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 466: 725, 725, 725, 725, 725, 472: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 485: 725, 725, 725, 725, 725, 725, 725, 725, 494: 725, 725, 725, 725, 501: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 537: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 575: 725}, // 795 - {144: 907, 477: 907, 490: 3257, 730: 907, 1240: 3256}, - {144: 3261, 477: 3262, 730: 910, 872: 3260}, - {8: 3258, 338: 3259}, - {144: 906, 477: 906, 730: 906}, - {144: 905, 477: 905, 730: 905}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3408, 654: 3410, 2691, 2692, 2690, 729: 3407, 860: 3406}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3405, 3173, 3254, 3172, 3169}, + {144: 911, 482: 911, 490: 3273, 731: 911, 1244: 3272}, + {144: 3277, 482: 3278, 731: 914, 873: 3276}, + {8: 3274, 343: 3275}, // 800 - {730: 3265, 737: 3266}, - {260: 3264}, - {260: 3263}, - {730: 908}, - {730: 909}, + {144: 910, 482: 910, 731: 910}, + {144: 909, 482: 909, 731: 909}, + {731: 3281, 738: 3282}, + {260: 3280}, + {260: 3279}, // 805 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 3302, 653: 3301, 2676, 2677, 2675, 911: 3304, 1142: 3305, 1324: 3303}, - {916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 463: 916, 916, 916, 916, 468: 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 479: 916, 916, 482: 916, 916, 916, 916, 916, 488: 916, 490: 916, 916, 916, 916, 495: 916, 497: 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 533: 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 571: 916}, - {1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 657: 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789}, - {1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 657: 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783, 1783}, - {1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 657: 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773}, + {731: 912}, + {731: 913}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 3320, 654: 3319, 2691, 2692, 2690, 911: 3322, 1146: 3323, 1328: 3321}, + {920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 466: 920, 920, 920, 920, 920, 472: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 485: 920, 920, 920, 920, 920, 920, 920, 920, 494: 920, 920, 920, 920, 501: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 537: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 575: 920}, + {1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 658: 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796}, // 810 - {1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 657: 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762}, - {1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 657: 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751}, - {1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 657: 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749, 1749}, - {1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 657: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726}, - {1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 657: 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720, 1720}, + {1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 658: 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790, 1790}, + {1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 658: 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779, 1779}, + {1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 658: 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768, 1768}, + {1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 658: 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757, 1757}, + {1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 658: 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755}, // 815 - {1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 657: 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710, 1710}, - {1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 657: 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685, 1685}, - {1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 657: 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684}, - {1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 657: 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681}, - {1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 657: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676}, + {1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 658: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732}, + {1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 658: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726}, + {1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 658: 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716}, + {1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 658: 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691}, + {1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 658: 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690, 1690}, // 820 - {1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 657: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674}, - {1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 657: 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673}, - {1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 657: 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670}, - {1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 657: 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668, 1668}, - {1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 657: 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655, 1655}, + {1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 658: 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687}, + {1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 658: 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682, 1682}, + {1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 658: 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680}, + {1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 658: 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679}, + {1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 658: 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676}, // 825 - {1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 657: 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634}, - {1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 657: 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617}, - {1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 657: 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616, 1616}, - {1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 657: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615}, - {1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 657: 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611, 1611}, + {1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 658: 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1674}, + {1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 658: 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661, 1661}, + {1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 658: 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1638}, + {1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 658: 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621}, + {1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 658: 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620}, // 830 - {1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 657: 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610}, - {1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 657: 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605, 1605}, - {1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 657: 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496, 1496}, - {1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 657: 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495, 1495}, - {1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 657: 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494}, + {1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 658: 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619, 1619}, + {1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 658: 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615}, + {1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 658: 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614}, + {1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 658: 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609, 1609}, + {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 658: 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}, // 835 - {1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 657: 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493}, - {1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 657: 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397, 1397}, - {1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 657: 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367, 1367}, - {1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 657: 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366, 1366}, - {1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 657: 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1347}, + {1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 658: 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499, 1499}, + {1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 658: 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498, 1498}, + {1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 658: 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497, 1497}, + {1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 658: 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416}, + {1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 658: 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401}, // 840 - {1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 657: 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346}, - {958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 463: 958, 958, 958, 958, 468: 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 482: 958, 958, 958, 958, 958, 488: 958, 490: 958, 958, 958, 958, 495: 958, 497: 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 533: 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 571: 958}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 955, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 478: 955, 493: 955, 513: 955, 516: 955, 955, 653: 3301, 2676, 2677, 2675, 911: 3308, 1239: 3307, 1325: 3306}, - {929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 463: 929, 929, 929, 929, 468: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 479: 929, 929, 482: 929, 929, 929, 929, 929, 488: 929, 490: 929, 929, 929, 929, 495: 929, 497: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 533: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 571: 929}, - {928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 463: 928, 928, 928, 928, 468: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 479: 928, 928, 482: 928, 928, 928, 928, 928, 488: 928, 490: 928, 928, 928, 928, 495: 928, 497: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 533: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 571: 928}, + {1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 658: 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383, 1383}, + {1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 658: 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1371}, + {1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 658: 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370}, + {1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 658: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351}, + {1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 658: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350}, // 845 - {927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 463: 927, 927, 927, 927, 468: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 479: 927, 927, 482: 927, 927, 927, 927, 927, 488: 927, 490: 927, 927, 927, 927, 495: 927, 497: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 533: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 571: 927}, - {57: 3386}, - {57: 953, 478: 3310, 493: 953, 513: 953, 516: 953, 953, 1242: 3309}, - {57: 954, 478: 954, 493: 954, 513: 954, 516: 954, 954}, - {57: 951, 493: 3316, 513: 951, 516: 951, 951, 1245: 3315}, + {962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 466: 962, 962, 962, 962, 962, 472: 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 485: 962, 962, 962, 962, 962, 962, 962, 962, 494: 962, 962, 962, 962, 501: 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 537: 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 575: 962}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 959, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 483: 959, 494: 959, 516: 959, 519: 959, 959, 654: 3319, 2691, 2692, 2690, 911: 3326, 1243: 3325, 1329: 3324}, + {933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 466: 933, 933, 933, 933, 933, 472: 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 485: 933, 933, 933, 933, 933, 933, 933, 933, 494: 933, 933, 933, 933, 501: 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 537: 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 575: 933}, + {932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 466: 932, 932, 932, 932, 932, 472: 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 485: 932, 932, 932, 932, 932, 932, 932, 932, 494: 932, 932, 932, 932, 501: 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 537: 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 575: 932}, + {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 466: 931, 931, 931, 931, 931, 472: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 485: 931, 931, 931, 931, 931, 931, 931, 931, 494: 931, 931, 931, 931, 501: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 537: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 575: 931}, // 850 - {649: 3311}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 2668, 859: 3144, 888: 3312}, - {7: 3313, 57: 952, 493: 952, 513: 952, 516: 952, 952}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 2668, 859: 3314}, - {1273, 1273, 7: 1273, 57: 1273, 124: 1273, 461: 1273, 463: 1273, 469: 1273, 471: 1273, 479: 1273, 1273, 482: 1273, 1273, 1273, 486: 1273, 491: 1273, 493: 1273, 504: 1273, 1273, 513: 1273, 516: 1273, 1273}, + {47: 3404}, + {47: 957, 483: 3328, 494: 957, 516: 957, 519: 957, 957, 1246: 3327}, + {47: 958, 483: 958, 494: 958, 516: 958, 519: 958, 958}, + {47: 955, 494: 3334, 516: 955, 519: 955, 955, 1249: 3333}, + {650: 3329}, // 855 - {57: 949, 513: 3321, 516: 3322, 3323, 1244: 3319, 1323: 3320}, - {649: 3317}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 2668, 859: 3144, 888: 3318}, - {7: 3313, 57: 950, 513: 950, 516: 950, 950}, - {57: 956}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 2683, 859: 3162, 888: 3330}, + {7: 3331, 47: 956, 494: 956, 516: 956, 519: 956, 956}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 2683, 859: 3332}, + {1277, 1277, 7: 1277, 47: 1277, 125: 1277, 464: 1277, 466: 1277, 472: 1277, 1277, 480: 1277, 1277, 485: 1277, 1277, 1277, 1277, 491: 1277, 494: 1277, 507: 1277, 1277, 516: 1277, 519: 1277, 1277}, + {47: 953, 516: 3339, 519: 3340, 3341, 1248: 3337, 1327: 3338}, // 860 - {146: 3334, 161: 3330, 496: 3324, 544: 3335, 562: 3326, 3325, 567: 3332, 570: 3333, 809: 3331, 964: 3328, 1321: 3329, 3327}, - {146: 947, 161: 947, 496: 947, 544: 947, 562: 947, 947, 567: 947, 570: 947}, - {146: 946, 161: 946, 496: 946, 544: 946, 562: 946, 946, 567: 946, 570: 946}, - {146: 945, 161: 945, 496: 945, 544: 945, 562: 945, 945, 567: 945, 570: 945}, - {2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 2161, 130: 2161, 148: 2161, 461: 2161, 2161, 2161, 465: 2161, 2161, 2161, 2161, 2161, 2161, 477: 2161, 2161, 481: 2161, 487: 2161, 2161, 2161, 494: 2161, 556: 2161, 566: 2161, 574: 2161, 576: 2161, 632: 2161, 2161, 2161, 2161, 2161, 2161, 2161}, + {650: 3335}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 2683, 859: 3162, 888: 3336}, + {7: 3331, 47: 954, 516: 954, 519: 954, 954}, + {47: 960}, + {146: 3352, 162: 3348, 500: 3342, 547: 3353, 566: 3344, 3343, 570: 3350, 573: 3351, 808: 3349, 967: 3346, 1325: 3347, 3345}, // 865 - {2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 130: 2160, 148: 2160, 185: 2160, 461: 2160, 2160, 2160, 465: 2160, 2160, 2160, 2160, 2160, 2160, 477: 2160, 2160, 481: 2160, 487: 2160, 2160, 2160, 494: 2160, 556: 2160, 566: 2160, 574: 2160, 576: 2160, 632: 2160, 2160, 2160, 2160, 2160, 2160, 2160}, - {2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 130: 2159, 148: 2159, 185: 2159, 461: 2159, 2159, 2159, 465: 2159, 2159, 2159, 2159, 2159, 2159, 477: 2159, 2159, 481: 2159, 487: 2159, 2159, 2159, 494: 2159, 556: 2159, 566: 2159, 574: 2159, 576: 2159, 632: 2159, 2159, 2159, 2159, 2159, 2159, 2159}, - {57: 948}, - {57: 944}, - {57: 943}, + {146: 951, 162: 951, 500: 951, 547: 951, 566: 951, 951, 570: 951, 573: 951}, + {146: 950, 162: 950, 500: 950, 547: 950, 566: 950, 950, 570: 950, 573: 950}, + {146: 949, 162: 949, 500: 949, 547: 949, 566: 949, 949, 570: 949, 573: 949}, + {2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 47: 2171, 130: 2171, 148: 2171, 464: 2171, 2171, 2171, 2171, 469: 2171, 2171, 2171, 2171, 474: 2171, 482: 2171, 2171, 2171, 493: 2171, 495: 2171, 498: 2171, 2171, 562: 2171, 565: 2171, 574: 2171, 576: 2171, 586: 2171, 616: 2171, 635: 2171, 2171, 2171, 2171, 640: 2171}, + {2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 47: 2170, 130: 2170, 148: 2170, 186: 2170, 464: 2170, 2170, 2170, 2170, 469: 2170, 2170, 2170, 2170, 474: 2170, 482: 2170, 2170, 2170, 493: 2170, 495: 2170, 498: 2170, 2170, 562: 2170, 565: 2170, 574: 2170, 576: 2170, 586: 2170, 616: 2170, 635: 2170, 2170, 2170, 2170, 640: 2170}, // 870 - {130: 3381}, - {130: 3379}, - {130: 3377}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3384}, - {564: 3383}, + {2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 47: 2169, 130: 2169, 148: 2169, 186: 2169, 464: 2169, 2169, 2169, 2169, 469: 2169, 2169, 2169, 2169, 474: 2169, 482: 2169, 2169, 2169, 493: 2169, 495: 2169, 498: 2169, 2169, 562: 2169, 565: 2169, 574: 2169, 576: 2169, 586: 2169, 616: 2169, 635: 2169, 2169, 2169, 2169, 640: 2169}, + {47: 952}, + {47: 948}, + {47: 947}, + {130: 3399}, // 875 - {146: 3334, 161: 3336, 496: 3324, 562: 3326, 3325, 567: 3338, 570: 3339, 809: 3337, 964: 3341, 1141: 3340}, - {130: 3381, 148: 3382}, - {130: 3379, 148: 3380}, - {130: 3377, 148: 3378}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3344}, + {130: 3397}, + {130: 3395}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3402}, + {568: 3401}, + {146: 3352, 162: 3354, 500: 3342, 566: 3344, 3343, 570: 3356, 573: 3357, 808: 3355, 967: 3359, 1145: 3358}, // 880 - {495: 3342}, - {57: 936, 495: 936}, - {146: 3334, 161: 3336, 496: 3324, 562: 3326, 3325, 567: 3338, 570: 3339, 809: 3337, 964: 3341, 1141: 3343}, - {57: 937}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3374}, + {130: 3399, 148: 3400}, + {130: 3397, 148: 3398}, + {130: 3395, 148: 3396}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3362}, + {497: 3360}, // 885 - {1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 468: 1079, 1079, 471: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 479: 1079, 1079, 482: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 490: 1079, 1079, 1079, 1079, 1079, 1079, 497: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 533: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 556: 1079, 634: 1079}, - {1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 468: 1078, 1078, 471: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 479: 1078, 1078, 482: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 490: 1078, 1078, 1078, 1078, 1078, 1078, 497: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 533: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 556: 1078, 634: 1078}, - {1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 468: 1077, 1077, 471: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 479: 1077, 1077, 482: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 490: 1077, 1077, 1077, 1077, 1077, 1077, 497: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 533: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 556: 1077, 634: 1077}, - {1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 468: 1076, 1076, 471: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 479: 1076, 1076, 482: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 490: 1076, 1076, 1076, 1076, 1076, 1076, 497: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 533: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 556: 1076, 634: 1076}, - {1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 468: 1075, 1075, 471: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 479: 1075, 1075, 482: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 490: 1075, 1075, 1075, 1075, 1075, 1075, 497: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 533: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 556: 1075, 634: 1075}, + {47: 940, 497: 940}, + {146: 3352, 162: 3354, 500: 3342, 566: 3344, 3343, 570: 3356, 573: 3357, 808: 3355, 967: 3359, 1145: 3361}, + {47: 941}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3392}, + {1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 472: 1083, 1083, 475: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 485: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 499: 1083, 501: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 537: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 562: 1083, 637: 1083}, // 890 - {1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 468: 1074, 1074, 471: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 479: 1074, 1074, 482: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 490: 1074, 1074, 1074, 1074, 1074, 1074, 497: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 533: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 556: 1074, 634: 1074}, - {1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 468: 1073, 1073, 471: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 479: 1073, 1073, 482: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 490: 1073, 1073, 1073, 1073, 1073, 1073, 497: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 533: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 556: 1073, 634: 1073}, - {1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 468: 1072, 1072, 471: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 479: 1072, 1072, 482: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 490: 1072, 1072, 1072, 1072, 1072, 1072, 497: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 533: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 556: 1072, 634: 1072}, - {1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 468: 1071, 1071, 471: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 479: 1071, 1071, 482: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 490: 1071, 1071, 1071, 1071, 1071, 1071, 497: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 533: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 556: 1071, 634: 1071}, - {1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 468: 1070, 1070, 471: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 479: 1070, 1070, 482: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 490: 1070, 1070, 1070, 1070, 1070, 1070, 497: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 533: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 556: 1070, 634: 1070}, + {1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 472: 1082, 1082, 475: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 485: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 499: 1082, 501: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 537: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 562: 1082, 637: 1082}, + {1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 472: 1081, 1081, 475: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 485: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 499: 1081, 501: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 537: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 562: 1081, 637: 1081}, + {1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 472: 1080, 1080, 475: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 485: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 499: 1080, 501: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 537: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 562: 1080, 637: 1080}, + {1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 472: 1079, 1079, 475: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 485: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 499: 1079, 501: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 537: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 562: 1079, 637: 1079}, + {1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 472: 1078, 1078, 475: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 485: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 499: 1078, 501: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 537: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 562: 1078, 637: 1078}, // 895 - {1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 468: 1069, 1069, 471: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 479: 1069, 1069, 482: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 490: 1069, 1069, 1069, 1069, 1069, 1069, 497: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 533: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 556: 1069, 634: 1069}, - {1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 468: 1068, 1068, 471: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 479: 1068, 1068, 482: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 490: 1068, 1068, 1068, 1068, 1068, 1068, 497: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 533: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 556: 1068, 634: 1068}, - {1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 468: 1067, 1067, 471: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 479: 1067, 1067, 482: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 490: 1067, 1067, 1067, 1067, 1067, 1067, 497: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 533: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 556: 1067, 634: 1067}, - {1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 468: 1066, 1066, 471: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 479: 1066, 1066, 482: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 490: 1066, 1066, 1066, 1066, 1066, 1066, 497: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 533: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 556: 1066, 634: 1066}, - {1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 468: 1065, 1065, 471: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 479: 1065, 1065, 482: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 490: 1065, 1065, 1065, 1065, 1065, 1065, 497: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 533: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 556: 1065, 634: 1065}, + {1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 472: 1077, 1077, 475: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 485: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 499: 1077, 501: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 537: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 562: 1077, 637: 1077}, + {1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 472: 1076, 1076, 475: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 485: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 499: 1076, 501: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 537: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 562: 1076, 637: 1076}, + {1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 472: 1075, 1075, 475: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 485: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 499: 1075, 501: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 537: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 562: 1075, 637: 1075}, + {1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 472: 1074, 1074, 475: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 485: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 499: 1074, 501: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 537: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 562: 1074, 637: 1074}, + {1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 472: 1073, 1073, 475: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 485: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 499: 1073, 501: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 537: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 562: 1073, 637: 1073}, // 900 - {1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 468: 1064, 1064, 471: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 479: 1064, 1064, 482: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 490: 1064, 1064, 1064, 1064, 1064, 1064, 497: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 533: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 556: 1064, 634: 1064}, - {1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 468: 1063, 1063, 471: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 479: 1063, 1063, 482: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 490: 1063, 1063, 1063, 1063, 1063, 1063, 497: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 533: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 556: 1063, 634: 1063}, - {1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 468: 1062, 1062, 471: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 479: 1062, 1062, 482: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 490: 1062, 1062, 1062, 1062, 1062, 1062, 497: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 533: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 556: 1062, 634: 1062}, - {1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 468: 1061, 1061, 471: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 479: 1061, 1061, 482: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 490: 1061, 1061, 1061, 1061, 1061, 1061, 497: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 533: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 556: 1061, 634: 1061}, - {1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 468: 1060, 1060, 471: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 479: 1060, 1060, 482: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 490: 1060, 1060, 1060, 1060, 1060, 1060, 497: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 533: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 556: 1060, 634: 1060}, + {1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 472: 1072, 1072, 475: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 485: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 499: 1072, 501: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 537: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 562: 1072, 637: 1072}, + {1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 472: 1071, 1071, 475: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 485: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 499: 1071, 501: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 537: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 562: 1071, 637: 1071}, + {1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 472: 1070, 1070, 475: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 485: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 499: 1070, 501: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 537: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 562: 1070, 637: 1070}, + {1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 472: 1069, 1069, 475: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 485: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 499: 1069, 501: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 537: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 562: 1069, 637: 1069}, + {1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 472: 1068, 1068, 475: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 485: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 499: 1068, 501: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 537: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 562: 1068, 637: 1068}, // 905 - {1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 468: 1059, 1059, 471: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 479: 1059, 1059, 482: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 490: 1059, 1059, 1059, 1059, 1059, 1059, 497: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 533: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 556: 1059, 634: 1059}, - {1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 468: 1058, 1058, 471: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 479: 1058, 1058, 482: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 490: 1058, 1058, 1058, 1058, 1058, 1058, 497: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 533: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 556: 1058, 634: 1058}, - {1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 468: 1057, 1057, 471: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 479: 1057, 1057, 482: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 490: 1057, 1057, 1057, 1057, 1057, 1057, 497: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 533: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 556: 1057, 634: 1057}, - {1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 468: 1056, 1056, 471: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 479: 1056, 1056, 482: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 490: 1056, 1056, 1056, 1056, 1056, 1056, 497: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 533: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 556: 1056, 634: 1056}, - {1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 468: 1055, 1055, 471: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 479: 1055, 1055, 482: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 490: 1055, 1055, 1055, 1055, 1055, 1055, 497: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 533: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 556: 1055, 634: 1055}, + {1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 472: 1067, 1067, 475: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 485: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 499: 1067, 501: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 537: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 562: 1067, 637: 1067}, + {1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 472: 1066, 1066, 475: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 485: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 499: 1066, 501: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 537: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 562: 1066, 637: 1066}, + {1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 472: 1065, 1065, 475: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 485: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 499: 1065, 501: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 537: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 562: 1065, 637: 1065}, + {1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 472: 1064, 1064, 475: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 485: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 499: 1064, 501: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 537: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 562: 1064, 637: 1064}, + {1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 472: 1063, 1063, 475: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 485: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 499: 1063, 501: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 537: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 562: 1063, 637: 1063}, // 910 - {1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 468: 1054, 1054, 471: 1054, 1054, 1054, 1054, 1054, 1054, 1054, 479: 1054, 1054, 482: 1054, 1054, 1054, 1054, 1054, 1054, 1054, 490: 1054, 1054, 1054, 1054, 1054, 1054, 497: 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 533: 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 556: 1054, 634: 1054}, - {1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 468: 1053, 1053, 471: 1053, 1053, 1053, 1053, 1053, 1053, 1053, 479: 1053, 1053, 482: 1053, 1053, 1053, 1053, 1053, 1053, 1053, 490: 1053, 1053, 1053, 1053, 1053, 1053, 497: 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 533: 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 556: 1053, 634: 1053}, - {1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 468: 1052, 1052, 471: 1052, 1052, 1052, 1052, 1052, 1052, 1052, 479: 1052, 1052, 482: 1052, 1052, 1052, 1052, 1052, 1052, 1052, 490: 1052, 1052, 1052, 1052, 1052, 1052, 497: 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 533: 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 556: 1052, 634: 1052}, - {1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 468: 1051, 1051, 471: 1051, 1051, 1051, 1051, 1051, 1051, 1051, 479: 1051, 1051, 482: 1051, 1051, 1051, 1051, 1051, 1051, 1051, 490: 1051, 1051, 1051, 1051, 1051, 1051, 497: 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 533: 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 556: 1051, 634: 1051}, - {130: 3375, 148: 3376}, + {1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 472: 1062, 1062, 475: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 485: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 499: 1062, 501: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 537: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 562: 1062, 637: 1062}, + {1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 472: 1061, 1061, 475: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 485: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 499: 1061, 501: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 537: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 562: 1061, 637: 1061}, + {1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 472: 1060, 1060, 475: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 485: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 499: 1060, 501: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 537: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 562: 1060, 637: 1060}, + {1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 472: 1059, 1059, 475: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 485: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 499: 1059, 501: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 537: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 562: 1059, 637: 1059}, + {1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 472: 1058, 1058, 475: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 485: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 499: 1058, 501: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 537: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 562: 1058, 637: 1058}, // 915 - {57: 939, 495: 939}, - {57: 932, 495: 932}, - {57: 940, 495: 940}, - {57: 933, 495: 933}, - {57: 941, 495: 941}, + {1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 472: 1057, 1057, 475: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 485: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 499: 1057, 501: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 537: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 562: 1057, 637: 1057}, + {1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 472: 1056, 1056, 475: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 485: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 499: 1056, 501: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 537: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 562: 1056, 637: 1056}, + {1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 472: 1055, 1055, 475: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 485: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 499: 1055, 501: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 537: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 562: 1055, 637: 1055}, + {130: 3393, 148: 3394}, + {47: 943, 497: 943}, // 920 - {57: 934, 495: 934}, - {57: 942, 495: 942}, - {57: 935, 495: 935}, - {57: 938, 495: 938}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3385}, + {47: 936, 497: 936}, + {47: 944, 497: 944}, + {47: 937, 497: 937}, + {47: 945, 497: 945}, + {47: 938, 497: 938}, // 925 - {130: 3375}, - {957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 463: 957, 957, 957, 957, 468: 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 479: 957, 957, 482: 957, 957, 957, 957, 957, 488: 957, 490: 957, 957, 957, 957, 495: 957, 497: 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 533: 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 571: 957}, - {1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 463: 1231, 1231, 1231, 1231, 468: 1231, 1231, 3253, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 479: 1231, 1231, 482: 1231, 1231, 1231, 1231, 1231, 488: 1231, 490: 1231, 1231, 1231, 1231, 495: 1231, 497: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 533: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 571: 1231}, - {1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 463: 1241, 1241, 1241, 1241, 468: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 479: 1241, 1241, 482: 1241, 1241, 1241, 1241, 1241, 488: 1241, 490: 1241, 1241, 1241, 1241, 495: 1241, 497: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 533: 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 571: 1241}, - {728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 497: 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 533: 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 556: 728, 566: 728, 571: 728, 574: 728, 576: 728, 632: 728, 728, 728, 728, 728, 728, 728}, + {47: 946, 497: 946}, + {47: 939, 497: 939}, + {47: 942, 497: 942}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3403}, + {130: 3393}, // 930 - {727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 497: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 533: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 556: 727, 566: 727, 571: 727, 574: 727, 576: 727, 632: 727, 727, 727, 727, 727, 727, 727}, - {248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 497: 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 556: 248, 558: 248, 566: 248, 571: 248, 574: 248, 576: 248, 632: 248, 248, 248, 248, 248, 248, 248, 640: 248, 643: 248, 648: 248, 248, 651: 248, 657: 248, 248}, - {247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 497: 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 556: 247, 558: 247, 566: 247, 571: 247, 574: 247, 576: 247, 632: 247, 247, 247, 247, 247, 247, 247, 640: 247, 643: 247, 648: 247, 247, 651: 247, 657: 247, 247}, - {1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 463: 1898, 1898, 468: 1898, 1898, 471: 1898, 1898, 1898, 477: 1898, 479: 1898, 1898, 482: 1898, 1898, 1898, 486: 1898, 488: 1898, 490: 1898, 1898, 1898, 1898, 495: 1898, 497: 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 511: 1898, 513: 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 534: 1898, 1898, 723: 3245, 3243}, - {1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 463: 1899, 1899, 468: 1899, 1899, 471: 1899, 1899, 1899, 477: 1899, 479: 1899, 1899, 482: 1899, 1899, 1899, 486: 1899, 488: 1899, 490: 1899, 1899, 1899, 1899, 495: 3249, 497: 1899, 3248, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 511: 1899, 513: 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 534: 1899, 1899, 723: 3245, 3243}, + {961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 466: 961, 961, 961, 961, 961, 472: 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 485: 961, 961, 961, 961, 961, 961, 961, 961, 494: 961, 961, 961, 961, 501: 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 537: 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 575: 961}, + {1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 466: 1235, 1235, 1235, 1235, 1235, 472: 1235, 1235, 3269, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 485: 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 494: 1235, 1235, 1235, 1235, 501: 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 537: 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 575: 1235}, + {1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 466: 1245, 1245, 1245, 1245, 1245, 472: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 485: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 494: 1245, 1245, 1245, 1245, 501: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 537: 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 575: 1245}, + {732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 501: 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 537: 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 562: 732, 565: 732, 574: 732, 732, 732, 586: 732, 616: 732, 635: 732, 732, 732, 732, 640: 732}, + {731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 501: 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 537: 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, 562: 731, 565: 731, 574: 731, 731, 731, 586: 731, 616: 731, 635: 731, 731, 731, 731, 640: 731}, // 935 - {1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 463: 1900, 1900, 468: 1900, 1900, 471: 1900, 1900, 1900, 477: 1900, 479: 1900, 1900, 482: 1900, 1900, 1900, 486: 1900, 488: 1900, 490: 1900, 1900, 1900, 1900, 495: 3249, 497: 1900, 3248, 1900, 3244, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 511: 1900, 513: 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 534: 1900, 1900, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3397}, - {57: 3398, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {144: 3261, 477: 3262, 730: 910, 872: 3399}, - {730: 3265, 737: 3400}, + {250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 501: 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 560: 250, 562: 250, 565: 250, 574: 250, 250, 250, 586: 250, 616: 250, 635: 250, 250, 250, 250, 640: 250, 250, 644: 250, 649: 250, 250, 652: 250, 658: 250, 250}, + {249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 501: 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 560: 249, 562: 249, 565: 249, 574: 249, 249, 249, 586: 249, 616: 249, 635: 249, 249, 249, 249, 640: 249, 249, 644: 249, 649: 249, 249, 652: 249, 658: 249, 249}, + {1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 466: 1905, 468: 1905, 470: 1905, 472: 1905, 1905, 475: 1905, 1905, 480: 1905, 1905, 1905, 485: 1905, 1905, 1905, 1905, 490: 1905, 1905, 1905, 494: 1905, 1905, 1905, 1905, 501: 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 514: 1905, 516: 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 537: 1905, 1905, 725: 3261, 3259}, + {1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 466: 1906, 468: 1906, 470: 1906, 472: 1906, 1906, 475: 1906, 1906, 480: 1906, 1906, 1906, 485: 1906, 1906, 1906, 1906, 490: 1906, 1906, 1906, 494: 1906, 1906, 1906, 3265, 501: 1906, 3264, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 514: 1906, 516: 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 537: 1906, 1906, 725: 3261, 3259}, + {1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 466: 1907, 468: 1907, 470: 1907, 472: 1907, 1907, 475: 1907, 1907, 480: 1907, 1907, 1907, 485: 1907, 1907, 1907, 1907, 490: 1907, 1907, 1907, 494: 1907, 1907, 1907, 3265, 501: 1907, 3264, 1907, 3260, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 514: 1907, 516: 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 537: 1907, 1907, 725: 3261, 3259}, // 940 - {917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 463: 917, 917, 917, 917, 468: 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 479: 917, 917, 482: 917, 917, 917, 917, 917, 488: 917, 490: 917, 917, 917, 917, 495: 917, 497: 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 533: 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 571: 917}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3402}, - {57: 3403, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {144: 3261, 477: 3262, 730: 910, 872: 3404}, - {730: 3265, 737: 3405}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3415}, + {47: 3416, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {144: 3277, 482: 3278, 731: 914, 873: 3417}, + {731: 3281, 738: 3418}, + {921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 466: 921, 921, 921, 921, 921, 472: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 485: 921, 921, 921, 921, 921, 921, 921, 921, 494: 921, 921, 921, 921, 501: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 537: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 575: 921}, // 945 - {918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 463: 918, 918, 918, 918, 468: 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 479: 918, 918, 482: 918, 918, 918, 918, 918, 488: 918, 490: 918, 918, 918, 918, 495: 918, 497: 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 533: 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 571: 918}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3407}, - {7: 3409, 57: 915, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243, 1076: 3408}, - {57: 3416}, - {496: 3324, 562: 3326, 3325, 567: 3411, 809: 3410}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3420}, + {47: 3421, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {144: 3277, 482: 3278, 731: 914, 873: 3422}, + {731: 3281, 738: 3423}, + {922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 466: 922, 922, 922, 922, 922, 472: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 485: 922, 922, 922, 922, 922, 922, 922, 922, 494: 922, 922, 922, 922, 501: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 537: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 575: 922}, // 950 - {7: 3413, 57: 912, 1077: 3415}, - {7: 3413, 57: 912, 1077: 3412}, - {57: 913}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3414}, - {57: 911, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3425}, + {7: 3427, 47: 919, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259, 1079: 3426}, + {47: 3434}, + {500: 3342, 566: 3344, 3343, 570: 3429, 808: 3428}, + {7: 3431, 47: 916, 1080: 3433}, // 955 - {57: 914}, - {144: 3261, 477: 3262, 730: 910, 872: 3417}, - {730: 3265, 737: 3418}, - {919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 463: 919, 919, 919, 919, 468: 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 479: 919, 919, 482: 919, 919, 919, 919, 919, 488: 919, 490: 919, 919, 919, 919, 495: 919, 497: 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 533: 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 571: 919}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3420}, + {7: 3431, 47: 916, 1080: 3430}, + {47: 917}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3432}, + {47: 915, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {47: 918}, // 960 - {7: 3409, 57: 915, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243, 1076: 3421}, - {57: 3422}, - {144: 3261, 477: 3262, 730: 910, 872: 3423}, - {730: 3265, 737: 3424}, - {920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 463: 920, 920, 920, 920, 468: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 479: 920, 920, 482: 920, 920, 920, 920, 920, 488: 920, 490: 920, 920, 920, 920, 495: 920, 497: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 533: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 571: 920}, + {144: 3277, 482: 3278, 731: 914, 873: 3435}, + {731: 3281, 738: 3436}, + {923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 466: 923, 923, 923, 923, 923, 472: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 485: 923, 923, 923, 923, 923, 923, 923, 923, 494: 923, 923, 923, 923, 501: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 537: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 575: 923}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3438}, + {7: 3427, 47: 919, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259, 1079: 3439}, // 965 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3426, 3155, 3238, 3154, 3151}, - {57: 3427, 470: 3253, 571: 3254}, - {730: 3265, 737: 3428}, - {921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 463: 921, 921, 921, 921, 468: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 479: 921, 921, 482: 921, 921, 921, 921, 921, 488: 921, 490: 921, 921, 921, 921, 495: 921, 497: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 533: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 571: 921}, - {57: 3430}, + {47: 3440}, + {144: 3277, 482: 3278, 731: 914, 873: 3441}, + {731: 3281, 738: 3442}, + {924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 466: 924, 924, 924, 924, 924, 472: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 485: 924, 924, 924, 924, 924, 924, 924, 924, 494: 924, 924, 924, 924, 501: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 537: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 575: 924}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3444, 3173, 3254, 3172, 3169}, // 970 - {730: 3265, 737: 3431}, - {922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 463: 922, 922, 922, 922, 468: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 479: 922, 922, 482: 922, 922, 922, 922, 922, 488: 922, 490: 922, 922, 922, 922, 495: 922, 497: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 533: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 571: 922}, - {57: 3433}, - {730: 3265, 737: 3434}, - {923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 463: 923, 923, 923, 923, 468: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 479: 923, 923, 482: 923, 923, 923, 923, 923, 488: 923, 490: 923, 923, 923, 923, 495: 923, 497: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 533: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 571: 923}, + {47: 3445, 474: 3269, 575: 3270}, + {731: 3281, 738: 3446}, + {925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 466: 925, 925, 925, 925, 925, 472: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 485: 925, 925, 925, 925, 925, 925, 925, 925, 494: 925, 925, 925, 925, 501: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 537: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 575: 925}, + {47: 3448}, + {731: 3281, 738: 3449}, // 975 - {57: 3436}, - {730: 3265, 737: 3437}, - {924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 463: 924, 924, 924, 924, 468: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 479: 924, 924, 482: 924, 924, 924, 924, 924, 488: 924, 490: 924, 924, 924, 924, 495: 924, 497: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 533: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 571: 924}, - {57: 3439}, - {730: 3265, 737: 3440}, + {926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 466: 926, 926, 926, 926, 926, 472: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 485: 926, 926, 926, 926, 926, 926, 926, 926, 494: 926, 926, 926, 926, 501: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 537: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 575: 926}, + {47: 3451}, + {731: 3281, 738: 3452}, + {927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 466: 927, 927, 927, 927, 927, 472: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 485: 927, 927, 927, 927, 927, 927, 927, 927, 494: 927, 927, 927, 927, 501: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 537: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 575: 927}, + {47: 3454}, // 980 - {925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 463: 925, 925, 925, 925, 468: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 479: 925, 925, 482: 925, 925, 925, 925, 925, 488: 925, 490: 925, 925, 925, 925, 495: 925, 497: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 533: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 571: 925}, - {57: 3442}, - {730: 3265, 737: 3443}, - {926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 463: 926, 926, 926, 926, 468: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 479: 926, 926, 482: 926, 926, 926, 926, 926, 488: 926, 490: 926, 926, 926, 926, 495: 926, 497: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 533: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 571: 926}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3451, 806: 3450}, + {731: 3281, 738: 3455}, + {928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 466: 928, 928, 928, 928, 928, 472: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 485: 928, 928, 928, 928, 928, 928, 928, 928, 494: 928, 928, 928, 928, 501: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 537: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 575: 928}, + {47: 3457}, + {731: 3281, 738: 3458}, + {929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 466: 929, 929, 929, 929, 929, 472: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 485: 929, 929, 929, 929, 929, 929, 929, 929, 494: 929, 929, 929, 929, 501: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 537: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 575: 929}, // 985 - {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 58: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 462: 1214, 464: 1214, 1214, 1214, 1214, 472: 1214, 1214, 1214, 1214, 1214, 481: 1214, 487: 1214, 489: 1214, 494: 1214, 496: 1214, 503: 1214, 512: 1214, 532: 1214, 555: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 567: 1214, 1214, 1214, 1214, 572: 1214, 1214, 575: 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 634: 1214, 639: 1214, 641: 1214, 735: 1214, 1214, 738: 1214, 1214, 1214, 749: 1214, 758: 1214, 1214, 1214}, - {2: 1213, 1213, 1213, 1213, 1213, 8: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 58: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 462: 1213, 464: 1213, 1213, 1213, 1213, 472: 1213, 1213, 1213, 1213, 1213, 481: 1213, 487: 1213, 489: 1213, 494: 1213, 496: 1213, 503: 1213, 512: 1213, 532: 1213, 555: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 567: 1213, 1213, 1213, 1213, 572: 1213, 1213, 575: 1213, 577: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 634: 1213, 639: 1213, 641: 1213, 735: 1213, 1213, 738: 1213, 1213, 1213, 749: 1213, 758: 1213, 1213, 1213}, - {2: 1212, 1212, 1212, 1212, 1212, 8: 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 58: 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 462: 1212, 464: 1212, 1212, 1212, 1212, 472: 1212, 1212, 1212, 1212, 1212, 481: 1212, 487: 1212, 489: 1212, 494: 1212, 496: 1212, 503: 1212, 512: 1212, 532: 1212, 555: 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 567: 1212, 1212, 1212, 1212, 572: 1212, 1212, 575: 1212, 577: 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 634: 1212, 639: 1212, 641: 1212, 735: 1212, 1212, 738: 1212, 1212, 1212, 749: 1212, 758: 1212, 1212, 1212}, - {2: 1211, 1211, 1211, 1211, 1211, 8: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 58: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 462: 1211, 464: 1211, 1211, 1211, 1211, 472: 1211, 1211, 1211, 1211, 1211, 481: 1211, 487: 1211, 489: 1211, 494: 1211, 496: 1211, 532: 1211, 555: 1211, 557: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 567: 1211, 1211, 1211, 1211, 572: 1211, 1211, 575: 1211, 577: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 639: 1211, 641: 3456}, - {2: 1209, 1209, 1209, 1209, 1209, 8: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 58: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 462: 1209, 464: 1209, 1209, 1209, 1209, 472: 1209, 1209, 1209, 1209, 1209, 481: 1209, 487: 1209, 489: 1209, 494: 1209, 496: 1209, 532: 1209, 555: 1209, 557: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 567: 1209, 1209, 1209, 1209, 572: 1209, 1209, 575: 1209, 577: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 639: 1209}, + {47: 3460}, + {731: 3281, 738: 3461}, + {930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 466: 930, 930, 930, 930, 930, 472: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 485: 930, 930, 930, 930, 930, 930, 930, 930, 494: 930, 930, 930, 930, 501: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 537: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 575: 930}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3469, 805: 3468}, + {2: 1218, 1218, 1218, 1218, 1218, 8: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 48: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 465: 1218, 467: 1218, 1218, 1218, 471: 1218, 475: 1218, 1218, 1218, 1218, 1218, 484: 1218, 493: 1218, 498: 1218, 1218, 1218, 506: 1218, 515: 1218, 536: 1218, 558: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 566: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 577: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 587: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 617: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 637: 1218, 639: 1218, 642: 1218, 736: 1218, 1218, 739: 1218, 1218, 1218, 753: 1218, 759: 1218, 1218, 1218}, // 990 - {2: 1206, 1206, 1206, 1206, 1206, 8: 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 58: 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 462: 1206, 464: 1206, 1206, 1206, 1206, 472: 1206, 1206, 1206, 1206, 1206, 481: 1206, 487: 1206, 489: 1206, 494: 1206, 496: 1206, 532: 1206, 555: 1206, 557: 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 567: 1206, 1206, 1206, 1206, 572: 1206, 1206, 575: 1206, 577: 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 639: 1206}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3452}, - {57: 3453, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3454}, - {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 463: 1093, 1093, 1093, 1093, 468: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 479: 1093, 1093, 482: 1093, 1093, 1093, 1093, 1093, 488: 1093, 490: 1093, 1093, 1093, 1093, 495: 1093, 497: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 533: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 571: 1093}, + {2: 1217, 1217, 1217, 1217, 1217, 8: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 48: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 465: 1217, 467: 1217, 1217, 1217, 471: 1217, 475: 1217, 1217, 1217, 1217, 1217, 484: 1217, 493: 1217, 498: 1217, 1217, 1217, 506: 1217, 515: 1217, 536: 1217, 558: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 566: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 577: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 587: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 617: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 637: 1217, 639: 1217, 642: 1217, 736: 1217, 1217, 739: 1217, 1217, 1217, 753: 1217, 759: 1217, 1217, 1217}, + {2: 1216, 1216, 1216, 1216, 1216, 8: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 48: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 465: 1216, 467: 1216, 1216, 1216, 471: 1216, 475: 1216, 1216, 1216, 1216, 1216, 484: 1216, 493: 1216, 498: 1216, 1216, 1216, 506: 1216, 515: 1216, 536: 1216, 558: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 566: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 577: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 587: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 617: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 637: 1216, 639: 1216, 642: 1216, 736: 1216, 1216, 739: 1216, 1216, 1216, 753: 1216, 759: 1216, 1216, 1216}, + {2: 1215, 1215, 1215, 1215, 1215, 8: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 48: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 465: 1215, 467: 1215, 1215, 1215, 471: 1215, 475: 1215, 1215, 1215, 1215, 1215, 484: 1215, 493: 1215, 498: 1215, 1215, 1215, 536: 1215, 558: 1215, 1215, 1215, 1215, 563: 1215, 1215, 566: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 577: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 587: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 617: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 639: 1215, 642: 3474}, + {2: 1213, 1213, 1213, 1213, 1213, 8: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 48: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 465: 1213, 467: 1213, 1213, 1213, 471: 1213, 475: 1213, 1213, 1213, 1213, 1213, 484: 1213, 493: 1213, 498: 1213, 1213, 1213, 536: 1213, 558: 1213, 1213, 1213, 1213, 563: 1213, 1213, 566: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 577: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 587: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 617: 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 639: 1213}, + {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 48: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 465: 1210, 467: 1210, 1210, 1210, 471: 1210, 475: 1210, 1210, 1210, 1210, 1210, 484: 1210, 493: 1210, 498: 1210, 1210, 1210, 536: 1210, 558: 1210, 1210, 1210, 1210, 563: 1210, 1210, 566: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 587: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 617: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210}, // 995 - {930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 463: 930, 930, 930, 930, 468: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 479: 930, 930, 482: 930, 930, 930, 930, 930, 488: 930, 490: 930, 930, 930, 930, 495: 930, 497: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 533: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 571: 930}, - {2: 1205, 1205, 1205, 1205, 1205, 8: 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 58: 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 462: 1205, 464: 1205, 1205, 1205, 1205, 472: 1205, 1205, 1205, 1205, 1205, 481: 1205, 487: 1205, 489: 1205, 494: 1205, 496: 1205, 532: 1205, 555: 1205, 557: 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 567: 1205, 1205, 1205, 1205, 572: 1205, 1205, 575: 1205, 577: 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 639: 1205}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3458, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3459}, - {57: 3460, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3470}, + {47: 3471, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3472}, + {1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 466: 1097, 1097, 1097, 1097, 1097, 472: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 485: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 494: 1097, 1097, 1097, 1097, 501: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 537: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 575: 1097}, + {934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 466: 934, 934, 934, 934, 934, 472: 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 485: 934, 934, 934, 934, 934, 934, 934, 934, 494: 934, 934, 934, 934, 501: 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 537: 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 575: 934}, // 1000 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3461}, - {1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 463: 1094, 1094, 1094, 1094, 468: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 479: 1094, 1094, 482: 1094, 1094, 1094, 1094, 1094, 488: 1094, 490: 1094, 1094, 1094, 1094, 495: 1094, 497: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 533: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 571: 1094}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3463, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3464}, - {57: 3465, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {2: 1209, 1209, 1209, 1209, 1209, 8: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 48: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 465: 1209, 467: 1209, 1209, 1209, 471: 1209, 475: 1209, 1209, 1209, 1209, 1209, 484: 1209, 493: 1209, 498: 1209, 1209, 1209, 536: 1209, 558: 1209, 1209, 1209, 1209, 563: 1209, 1209, 566: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 577: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 587: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 617: 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 639: 1209}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3476, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3477}, + {47: 3478, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3479}, // 1005 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3466}, - {1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 463: 1095, 1095, 1095, 1095, 468: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 479: 1095, 1095, 482: 1095, 1095, 1095, 1095, 1095, 488: 1095, 490: 1095, 1095, 1095, 1095, 495: 1095, 497: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 533: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 571: 1095}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3468, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3469}, - {57: 3470, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 466: 1098, 1098, 1098, 1098, 1098, 472: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 485: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 494: 1098, 1098, 1098, 1098, 501: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 537: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 575: 1098}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3481, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3482}, + {47: 3483, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3484}, // 1010 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3471}, - {1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 463: 1096, 1096, 1096, 1096, 468: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 479: 1096, 1096, 482: 1096, 1096, 1096, 1096, 1096, 488: 1096, 490: 1096, 1096, 1096, 1096, 495: 1096, 497: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 533: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 571: 1096}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3473, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3474}, - {57: 3475, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 466: 1099, 1099, 1099, 1099, 1099, 472: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 485: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 494: 1099, 1099, 1099, 1099, 501: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 537: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 575: 1099}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3486, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3487}, + {47: 3488, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3489}, // 1015 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3476}, - {1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 463: 1097, 1097, 1097, 1097, 468: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 479: 1097, 1097, 482: 1097, 1097, 1097, 1097, 1097, 488: 1097, 490: 1097, 1097, 1097, 1097, 495: 1097, 497: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 533: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 571: 1097}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3478, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3479}, - {57: 3480, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 466: 1100, 1100, 1100, 1100, 1100, 472: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 485: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 494: 1100, 1100, 1100, 1100, 501: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 537: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 575: 1100}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3491, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3492}, + {47: 3493, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3494}, // 1020 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3481}, - {1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 463: 1098, 1098, 1098, 1098, 468: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 479: 1098, 1098, 482: 1098, 1098, 1098, 1098, 1098, 488: 1098, 490: 1098, 1098, 1098, 1098, 495: 1098, 497: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 533: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 571: 1098}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3483, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3484}, - {57: 3485, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 466: 1101, 1101, 1101, 1101, 1101, 472: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 485: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 494: 1101, 1101, 1101, 1101, 501: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 537: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 575: 1101}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3496, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3497}, + {47: 3498, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3499}, // 1025 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3486}, - {1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 463: 1099, 1099, 1099, 1099, 468: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 479: 1099, 1099, 482: 1099, 1099, 1099, 1099, 1099, 488: 1099, 490: 1099, 1099, 1099, 1099, 495: 1099, 497: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 533: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 571: 1099}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3488, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3490}, - {1880, 1880, 7: 1880, 57: 1880, 124: 1880, 471: 1880, 493: 1880, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 466: 1102, 1102, 1102, 1102, 1102, 472: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 485: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 494: 1102, 1102, 1102, 1102, 501: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 537: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 575: 1102}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3501, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3502}, + {47: 3503, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3504}, // 1030 - {7: 3491, 57: 1265, 124: 1265, 493: 2639, 756: 2640, 801: 3492}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3498}, - {57: 1086, 124: 3494, 1241: 3493}, - {57: 3496}, - {464: 3495}, + {1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 466: 1103, 1103, 1103, 1103, 1103, 472: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 485: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 494: 1103, 1103, 1103, 1103, 501: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 537: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 575: 1103}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3506, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3508}, + {1887, 1887, 7: 1887, 47: 1887, 125: 1887, 473: 1887, 494: 1887, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {7: 3509, 47: 1269, 125: 1269, 494: 2654, 757: 2655, 800: 3510}, // 1035 - {57: 1085}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3497}, - {1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 463: 1100, 1100, 1100, 1100, 468: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 479: 1100, 1100, 482: 1100, 1100, 1100, 1100, 1100, 488: 1100, 490: 1100, 1100, 1100, 1100, 495: 1100, 497: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 533: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 571: 1100}, - {1879, 1879, 7: 1879, 57: 1879, 124: 1879, 471: 1879, 493: 1879, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 512: 3503, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3502, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3500, 735: 3445, 3446, 774: 3501}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3516}, + {47: 1090, 125: 3512, 1245: 3511}, + {47: 3514}, + {468: 3513}, + {47: 1089}, // 1040 - {57: 3511, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3509}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3506}, - {57: 3504}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3505}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3515}, + {1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 466: 1104, 1104, 1104, 1104, 1104, 472: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 485: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 494: 1104, 1104, 1104, 1104, 501: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 537: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 575: 1104}, + {1886, 1886, 7: 1886, 47: 1886, 125: 1886, 473: 1886, 494: 1886, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 515: 3521, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3520, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3518, 736: 3463, 3464, 773: 3519}, + {47: 3529, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1045 - {1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 463: 1101, 1101, 1101, 1101, 468: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 479: 1101, 1101, 482: 1101, 1101, 1101, 1101, 1101, 488: 1101, 490: 1101, 1101, 1101, 1101, 495: 1101, 497: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 533: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 571: 1101}, - {57: 3507, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3508}, - {1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 463: 1103, 1103, 1103, 1103, 468: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 479: 1103, 1103, 482: 1103, 1103, 1103, 1103, 1103, 488: 1103, 490: 1103, 1103, 1103, 1103, 495: 1103, 497: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 533: 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 571: 1103}, - {7: 3491, 57: 3510}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3527}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3524}, + {47: 3522}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3523}, + {1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 466: 1105, 1105, 1105, 1105, 1105, 472: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 485: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 494: 1105, 1105, 1105, 1105, 501: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 537: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 575: 1105}, // 1050 - {1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 463: 1104, 1104, 1104, 1104, 468: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 479: 1104, 1104, 482: 1104, 1104, 1104, 1104, 1104, 488: 1104, 490: 1104, 1104, 1104, 1104, 495: 1104, 497: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 533: 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 571: 1104}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3512}, - {1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 463: 1102, 1102, 1102, 1102, 468: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 479: 1102, 1102, 482: 1102, 1102, 1102, 1102, 1102, 488: 1102, 490: 1102, 1102, 1102, 1102, 495: 1102, 497: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 533: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 571: 1102}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3515, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3514}, - {57: 3519, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {47: 3525, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3526}, + {1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 466: 1107, 1107, 1107, 1107, 1107, 472: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 485: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 494: 1107, 1107, 1107, 1107, 501: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 537: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 575: 1107}, + {7: 3509, 47: 3528}, + {1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 466: 1108, 1108, 1108, 1108, 1108, 472: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 485: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 494: 1108, 1108, 1108, 1108, 501: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 537: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 575: 1108}, // 1055 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3516}, - {57: 3517, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3518}, - {1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 463: 1105, 1105, 1105, 1105, 468: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 479: 1105, 1105, 482: 1105, 1105, 1105, 1105, 1105, 488: 1105, 490: 1105, 1105, 1105, 1105, 495: 1105, 497: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 533: 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 571: 1105}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3520}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3530}, + {1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 466: 1106, 1106, 1106, 1106, 1106, 472: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 485: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 494: 1106, 1106, 1106, 1106, 501: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 537: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 575: 1106}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3533, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3532}, + {47: 3537, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3534}, // 1060 - {1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 463: 1106, 1106, 1106, 1106, 468: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 479: 1106, 1106, 482: 1106, 1106, 1106, 1106, 1106, 488: 1106, 490: 1106, 1106, 1106, 1106, 495: 1106, 497: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 533: 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 571: 1106}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3523, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3522}, - {57: 3527, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3524}, - {57: 3525, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {47: 3535, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3536}, + {1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 466: 1109, 1109, 1109, 1109, 1109, 472: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 485: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 494: 1109, 1109, 1109, 1109, 501: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 537: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 575: 1109}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3538}, + {1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 466: 1110, 1110, 1110, 1110, 1110, 472: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 485: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 494: 1110, 1110, 1110, 1110, 501: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 537: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 575: 1110}, // 1065 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3526}, - {1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 463: 1107, 1107, 1107, 1107, 468: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 479: 1107, 1107, 482: 1107, 1107, 1107, 1107, 1107, 488: 1107, 490: 1107, 1107, 1107, 1107, 495: 1107, 497: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 533: 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 571: 1107}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3528}, - {1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 463: 1108, 1108, 1108, 1108, 468: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 479: 1108, 1108, 482: 1108, 1108, 1108, 1108, 1108, 488: 1108, 490: 1108, 1108, 1108, 1108, 495: 1108, 497: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 533: 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 571: 1108}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3531, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3530}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3541, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3540}, + {47: 3545, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3542}, + {47: 3543, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3544}, // 1070 - {57: 3535, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3532}, - {57: 3533, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3534}, - {1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 463: 1109, 1109, 1109, 1109, 468: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 479: 1109, 1109, 482: 1109, 1109, 1109, 1109, 1109, 488: 1109, 490: 1109, 1109, 1109, 1109, 495: 1109, 497: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 533: 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 571: 1109}, + {1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 466: 1111, 1111, 1111, 1111, 1111, 472: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 485: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 494: 1111, 1111, 1111, 1111, 501: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 537: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 575: 1111}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3546}, + {1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 466: 1112, 1112, 1112, 1112, 1112, 472: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 485: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 494: 1112, 1112, 1112, 1112, 501: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 537: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 575: 1112}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3549, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3548}, + {47: 3553, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1075 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3536}, - {1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 463: 1110, 1110, 1110, 1110, 468: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 479: 1110, 1110, 482: 1110, 1110, 1110, 1110, 1110, 488: 1110, 490: 1110, 1110, 1110, 1110, 495: 1110, 497: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 533: 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 571: 1110}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3538}, - {7: 3491, 57: 3539}, - {1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 463: 1111, 1111, 1111, 1111, 468: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 479: 1111, 1111, 482: 1111, 1111, 1111, 1111, 1111, 488: 1111, 490: 1111, 1111, 1111, 1111, 495: 1111, 497: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 533: 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 571: 1111}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3550}, + {47: 3551, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3552}, + {1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 466: 1113, 1113, 1113, 1113, 1113, 472: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 485: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 494: 1113, 1113, 1113, 1113, 501: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 537: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 575: 1113}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3554}, // 1080 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3541}, - {7: 3491, 57: 3542}, - {1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 463: 1112, 1112, 1112, 1112, 468: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 479: 1112, 1112, 482: 1112, 1112, 1112, 1112, 1112, 488: 1112, 490: 1112, 1112, 1112, 1112, 495: 1112, 497: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 533: 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 571: 1112}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3544}, - {7: 3545, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 466: 1114, 1114, 1114, 1114, 1114, 472: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 485: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 494: 1114, 1114, 1114, 1114, 501: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 537: 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 575: 1114}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3556}, + {7: 3509, 47: 3557}, + {1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 466: 1115, 1115, 1115, 1115, 1115, 472: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 485: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 494: 1115, 1115, 1115, 1115, 501: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 537: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 575: 1115}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3559}, // 1085 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3546}, - {7: 3547, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3548}, - {57: 3549, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 463: 1128, 1128, 1128, 1128, 468: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 479: 1128, 1128, 482: 1128, 1128, 1128, 1128, 1128, 488: 1128, 490: 1128, 1128, 1128, 1128, 495: 1128, 497: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 533: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 571: 1128}, + {7: 3509, 47: 3560}, + {1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 466: 1116, 1116, 1116, 1116, 1116, 472: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 485: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 494: 1116, 1116, 1116, 1116, 501: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 537: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 575: 1116}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3562}, + {7: 3563, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3564}, // 1090 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3551, 1162: 3553, 1217: 3554, 1302: 3555, 3552}, - {57: 3563, 490: 3564, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 3557, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3556}, - {2: 1119, 1119, 1119, 1119, 1119, 8: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 58: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 462: 1119, 464: 1119, 1119, 1119, 1119, 472: 1119, 1119, 1119, 1119, 1119, 481: 1119, 487: 1119, 489: 1119, 1119, 494: 1119, 496: 1119, 532: 1119, 555: 1119, 557: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 567: 1119, 1119, 1119, 1119, 572: 1119, 1119, 575: 1119, 577: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 639: 1119}, - {2: 1118, 1118, 1118, 1118, 1118, 8: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 58: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 462: 1118, 464: 1118, 1118, 1118, 1118, 472: 1118, 1118, 1118, 1118, 1118, 481: 1118, 487: 1118, 489: 1118, 1118, 494: 1118, 496: 1118, 532: 1118, 555: 1118, 557: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 567: 1118, 1118, 1118, 1118, 572: 1118, 1118, 575: 1118, 577: 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 639: 1118}, + {7: 3565, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3566}, + {47: 3567, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 466: 1132, 1132, 1132, 1132, 1132, 472: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 485: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 494: 1132, 1132, 1132, 1132, 501: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 537: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 575: 1132}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3569, 1167: 3571, 1222: 3572, 1306: 3573, 3570}, // 1095 - {2: 1117, 1117, 1117, 1117, 1117, 8: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 58: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 462: 1117, 464: 1117, 1117, 1117, 1117, 472: 1117, 1117, 1117, 1117, 1117, 481: 1117, 487: 1117, 489: 1117, 1117, 494: 1117, 496: 1117, 532: 1117, 555: 1117, 557: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 567: 1117, 1117, 1117, 1117, 572: 1117, 1117, 575: 1117, 577: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 639: 1117}, - {490: 3560, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3558}, - {57: 3559, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 463: 1134, 1134, 1134, 1134, 468: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 479: 1134, 1134, 482: 1134, 1134, 1134, 1134, 1134, 488: 1134, 490: 1134, 1134, 1134, 1134, 495: 1134, 497: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 533: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 571: 1134}, + {47: 3581, 490: 3582, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 490: 3575, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3574}, + {2: 1123, 1123, 1123, 1123, 1123, 8: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 48: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 465: 1123, 467: 1123, 1123, 1123, 471: 1123, 475: 1123, 1123, 1123, 1123, 1123, 484: 1123, 490: 1123, 493: 1123, 498: 1123, 1123, 1123, 536: 1123, 558: 1123, 1123, 1123, 1123, 563: 1123, 1123, 566: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 577: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 587: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 617: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 639: 1123}, + {2: 1122, 1122, 1122, 1122, 1122, 8: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 48: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 465: 1122, 467: 1122, 1122, 1122, 471: 1122, 475: 1122, 1122, 1122, 1122, 1122, 484: 1122, 490: 1122, 493: 1122, 498: 1122, 1122, 1122, 536: 1122, 558: 1122, 1122, 1122, 1122, 563: 1122, 1122, 566: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 577: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 587: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 617: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 639: 1122}, + {2: 1121, 1121, 1121, 1121, 1121, 8: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 48: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 465: 1121, 467: 1121, 1121, 1121, 471: 1121, 475: 1121, 1121, 1121, 1121, 1121, 484: 1121, 490: 1121, 493: 1121, 498: 1121, 1121, 1121, 536: 1121, 558: 1121, 1121, 1121, 1121, 563: 1121, 1121, 566: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 577: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 587: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 617: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 639: 1121}, // 1100 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3561}, - {57: 3562, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 463: 1133, 1133, 1133, 1133, 468: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 479: 1133, 1133, 482: 1133, 1133, 1133, 1133, 1133, 488: 1133, 490: 1133, 1133, 1133, 1133, 495: 1133, 497: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 533: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 571: 1133}, - {1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 463: 1136, 1136, 1136, 1136, 468: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 479: 1136, 1136, 482: 1136, 1136, 1136, 1136, 1136, 488: 1136, 490: 1136, 1136, 1136, 1136, 495: 1136, 497: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 533: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 571: 1136}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3565}, + {490: 3578, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3576}, + {47: 3577, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 466: 1138, 1138, 1138, 1138, 1138, 472: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 485: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 494: 1138, 1138, 1138, 1138, 501: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 537: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 575: 1138}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3579}, // 1105 - {57: 3566, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 463: 1135, 1135, 1135, 1135, 468: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 479: 1135, 1135, 482: 1135, 1135, 1135, 1135, 1135, 488: 1135, 490: 1135, 1135, 1135, 1135, 495: 1135, 497: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 533: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 571: 1135}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3568}, - {7: 3569, 490: 3570, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3576}, + {47: 3580, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 466: 1137, 1137, 1137, 1137, 1137, 472: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 485: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 494: 1137, 1137, 1137, 1137, 501: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 537: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 575: 1137}, + {1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 466: 1140, 1140, 1140, 1140, 1140, 472: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 485: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 494: 1140, 1140, 1140, 1140, 501: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 537: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 575: 1140}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3583}, + {47: 3584, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1110 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3571}, - {57: 3572, 482: 3573, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 463: 1141, 1141, 1141, 1141, 468: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 479: 1141, 1141, 482: 1141, 1141, 1141, 1141, 1141, 488: 1141, 490: 1141, 1141, 1141, 1141, 495: 1141, 497: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 533: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 571: 1141}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3574}, - {57: 3575, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 466: 1139, 1139, 1139, 1139, 1139, 472: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 485: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 494: 1139, 1139, 1139, 1139, 501: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 537: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 575: 1139}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3586}, + {7: 3587, 490: 3588, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3594}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3589}, // 1115 - {1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 463: 1139, 1139, 1139, 1139, 468: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 479: 1139, 1139, 482: 1139, 1139, 1139, 1139, 1139, 488: 1139, 490: 1139, 1139, 1139, 1139, 495: 1139, 497: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 533: 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 571: 1139}, - {7: 3578, 57: 3577, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 463: 1142, 1142, 1142, 1142, 468: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 479: 1142, 1142, 482: 1142, 1142, 1142, 1142, 1142, 488: 1142, 490: 1142, 1142, 1142, 1142, 495: 1142, 497: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 533: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 571: 1142}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3579}, - {57: 3580, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {47: 3590, 485: 3591, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 466: 1145, 1145, 1145, 1145, 1145, 472: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 485: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 494: 1145, 1145, 1145, 1145, 501: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 537: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 575: 1145}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3592}, + {47: 3593, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 466: 1143, 1143, 1143, 1143, 1143, 472: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 485: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 494: 1143, 1143, 1143, 1143, 501: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 537: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 575: 1143}, // 1120 - {1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 463: 1140, 1140, 1140, 1140, 468: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 479: 1140, 1140, 482: 1140, 1140, 1140, 1140, 1140, 488: 1140, 490: 1140, 1140, 1140, 1140, 495: 1140, 497: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 533: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 571: 1140}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3582}, - {474: 3588, 3587, 3593, 512: 3589, 533: 3595, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3615}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3614}, + {7: 3596, 47: 3595, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 466: 1146, 1146, 1146, 1146, 1146, 472: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 485: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 494: 1146, 1146, 1146, 1146, 501: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 537: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 575: 1146}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3597}, + {47: 3598, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 466: 1144, 1144, 1144, 1144, 1144, 472: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 485: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 494: 1144, 1144, 1144, 1144, 501: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 537: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 575: 1144}, // 1125 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3613}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3612}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3609, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3608}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3605, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3604}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3603}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3600}, + {477: 3606, 3605, 3611, 515: 3607, 535: 3613, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3633}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3632}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3631}, // 1130 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3602}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3601}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3600}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3599}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3598}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3630}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3627, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3626}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3623, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3622}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3621}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3620}, // 1135 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3596}, - {57: 3597, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 463: 1143, 1143, 1143, 1143, 468: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 479: 1143, 1143, 482: 1143, 1143, 1143, 1143, 1143, 488: 1143, 490: 1143, 1143, 1143, 1143, 495: 1143, 497: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 533: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 571: 1143}, - {1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 463: 1250, 1250, 1250, 1250, 468: 1250, 1250, 471: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 479: 1250, 1250, 482: 1250, 1250, 1250, 1250, 1250, 488: 1250, 490: 1250, 1250, 1250, 1250, 495: 1250, 497: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 533: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250}, - {1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 463: 1251, 1251, 1251, 1251, 468: 1251, 1251, 471: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 479: 1251, 1251, 482: 1251, 1251, 1251, 1251, 1251, 488: 1251, 490: 1251, 1251, 1251, 1251, 495: 1251, 497: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 533: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 3594, 1251, 1251, 1251, 1251, 1251, 1251}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3619}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3618}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3617}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3616}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3614}, // 1140 - {1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 463: 1252, 1252, 1252, 1252, 468: 1252, 1252, 471: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 479: 1252, 1252, 482: 1252, 1252, 1252, 1252, 1252, 488: 1252, 490: 1252, 1252, 1252, 1252, 495: 1252, 497: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 533: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 3594, 1252, 1252, 1252, 1252, 1252, 1252}, - {1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 463: 1253, 1253, 1253, 1253, 468: 1253, 1253, 471: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 479: 1253, 1253, 482: 1253, 1253, 1253, 1253, 1253, 488: 1253, 490: 1253, 1253, 1253, 1253, 495: 1253, 497: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 533: 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 3594, 1253, 1253, 1253, 1253, 1253, 1253}, - {1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 463: 1254, 1254, 1254, 1254, 468: 1254, 1254, 471: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 479: 1254, 1254, 482: 1254, 1254, 1254, 1254, 1254, 488: 1254, 490: 1254, 1254, 1254, 1254, 495: 1254, 497: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 533: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 3594, 1254, 1254, 1254, 1254, 1254, 1254}, - {1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 463: 1255, 1255, 1255, 1255, 468: 1255, 1255, 471: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 479: 1255, 1255, 482: 1255, 1255, 1255, 1255, 1255, 488: 1255, 490: 1255, 1255, 1255, 1255, 495: 1255, 497: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 533: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 3594, 1255, 1255, 1255, 1255, 1255, 1255}, - {1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 463: 1258, 1258, 1258, 1258, 468: 1258, 1258, 471: 1258, 1258, 1258, 1258, 1258, 3593, 1258, 479: 1258, 1258, 482: 1258, 1258, 1258, 1258, 1258, 488: 1258, 490: 1258, 1258, 1258, 1258, 495: 1258, 497: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 3589, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 533: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 3590, 3591, 1258, 3594, 1258, 3592, 1258, 1258, 1258, 1258}, + {47: 3615, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 466: 1147, 1147, 1147, 1147, 1147, 472: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 485: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 494: 1147, 1147, 1147, 1147, 501: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 537: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 575: 1147}, + {1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 466: 1254, 1254, 1254, 1254, 1254, 472: 1254, 1254, 475: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 485: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 494: 1254, 1254, 1254, 1254, 501: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 537: 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254}, + {1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 466: 1255, 1255, 1255, 1255, 1255, 472: 1255, 1255, 475: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 485: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 494: 1255, 1255, 1255, 1255, 501: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 537: 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 3612, 1255, 1255, 1255, 1255, 1255, 1255}, + {1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 466: 1256, 1256, 1256, 1256, 1256, 472: 1256, 1256, 475: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 485: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 494: 1256, 1256, 1256, 1256, 501: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 537: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 3612, 1256, 1256, 1256, 1256, 1256, 1256}, // 1145 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 1195, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3606}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3607}, - {1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 463: 1256, 1256, 1256, 1256, 468: 1256, 1256, 471: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 479: 1256, 1256, 482: 1256, 1256, 1256, 1256, 1256, 488: 1256, 490: 1256, 1256, 1256, 1256, 495: 1256, 497: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 533: 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256}, - {1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 463: 1259, 1259, 1259, 1259, 468: 1259, 1259, 471: 1259, 1259, 1259, 1259, 1259, 3593, 1259, 479: 1259, 1259, 482: 1259, 1259, 1259, 1259, 1259, 488: 1259, 490: 1259, 1259, 1259, 1259, 495: 1259, 497: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 3589, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 533: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 3590, 3591, 1259, 3594, 1259, 3592, 1259, 1259, 1259, 1259}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 1195, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3610}, + {1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 466: 1257, 1257, 1257, 1257, 1257, 472: 1257, 1257, 475: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 485: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 494: 1257, 1257, 1257, 1257, 501: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 537: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 3612, 1257, 1257, 1257, 1257, 1257, 1257}, + {1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 466: 1258, 1258, 1258, 1258, 1258, 472: 1258, 1258, 475: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 485: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 494: 1258, 1258, 1258, 1258, 501: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 537: 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 3612, 1258, 1258, 1258, 1258, 1258, 1258}, + {1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 466: 1259, 1259, 1259, 1259, 1259, 472: 1259, 1259, 475: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 485: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 494: 1259, 1259, 1259, 1259, 501: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 537: 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 3612, 1259, 1259, 1259, 1259, 1259, 1259}, + {1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 466: 1262, 1262, 1262, 1262, 1262, 472: 1262, 1262, 475: 1262, 1262, 1262, 1262, 3611, 1262, 1262, 1262, 485: 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 494: 1262, 1262, 1262, 1262, 501: 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 3607, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 537: 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 3608, 3609, 1262, 3612, 1262, 3610, 1262, 1262, 1262, 1262}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 1199, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3624}, // 1150 - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3611}, - {1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 463: 1257, 1257, 1257, 1257, 468: 1257, 1257, 471: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 479: 1257, 1257, 482: 1257, 1257, 1257, 1257, 1257, 488: 1257, 490: 1257, 1257, 1257, 1257, 495: 1257, 497: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 533: 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257}, - {1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 463: 1260, 1260, 1260, 1260, 468: 1260, 1260, 471: 1260, 1260, 1260, 3588, 3587, 3593, 1260, 479: 1260, 1260, 482: 1260, 1260, 1260, 1260, 1260, 488: 1260, 490: 1260, 1260, 1260, 1260, 495: 1260, 497: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 3589, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 533: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 3590, 3591, 1260, 3594, 1260, 3592, 1260, 1260, 1260, 1260}, - {1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 463: 1261, 1261, 1261, 1261, 468: 1261, 1261, 471: 1261, 1261, 1261, 3588, 3587, 3593, 1261, 479: 1261, 1261, 482: 1261, 1261, 1261, 1261, 1261, 488: 1261, 490: 1261, 1261, 1261, 1261, 495: 1261, 497: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 3589, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 533: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 3590, 3591, 1261, 3594, 1261, 3592, 1261, 1261, 1261, 1261}, - {1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 463: 1262, 1262, 1262, 1262, 468: 1262, 1262, 471: 1262, 1262, 1262, 3588, 3587, 3593, 1262, 479: 1262, 1262, 482: 1262, 1262, 1262, 1262, 1262, 488: 1262, 490: 1262, 1262, 1262, 1262, 495: 1262, 497: 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 3589, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 533: 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 3590, 3591, 1262, 3594, 1262, 3592, 3585, 3586, 1262, 1262}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3625}, + {1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 466: 1260, 1260, 1260, 1260, 1260, 472: 1260, 1260, 475: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 485: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 494: 1260, 1260, 1260, 1260, 501: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 537: 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260}, + {1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 466: 1263, 1263, 1263, 1263, 1263, 472: 1263, 1263, 475: 1263, 1263, 1263, 1263, 3611, 1263, 1263, 1263, 485: 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 494: 1263, 1263, 1263, 1263, 501: 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 3607, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 537: 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 3608, 3609, 1263, 3612, 1263, 3610, 1263, 1263, 1263, 1263}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 1199, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3628}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3629}, // 1155 - {1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 463: 1263, 1263, 1263, 1263, 468: 1263, 1263, 471: 1263, 1263, 1263, 3588, 3587, 3593, 1263, 479: 1263, 1263, 482: 1263, 1263, 1263, 1263, 1263, 488: 1263, 490: 1263, 1263, 1263, 1263, 495: 1263, 497: 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 3589, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 533: 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 3590, 3591, 3584, 3594, 1263, 3592, 3585, 3586, 1263, 1263}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 796: 3345, 819: 3617}, - {490: 3618}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3619}, - {57: 3620, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 466: 1261, 1261, 1261, 1261, 1261, 472: 1261, 1261, 475: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 485: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 494: 1261, 1261, 1261, 1261, 501: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 537: 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261}, + {1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 466: 1264, 1264, 1264, 1264, 1264, 472: 1264, 1264, 475: 1264, 1264, 3606, 3605, 3611, 1264, 1264, 1264, 485: 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 494: 1264, 1264, 1264, 1264, 501: 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 3607, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 537: 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 3608, 3609, 1264, 3612, 1264, 3610, 1264, 1264, 1264, 1264}, + {1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 466: 1265, 1265, 1265, 1265, 1265, 472: 1265, 1265, 475: 1265, 1265, 3606, 3605, 3611, 1265, 1265, 1265, 485: 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 494: 1265, 1265, 1265, 1265, 501: 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 3607, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 537: 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 1265, 3608, 3609, 1265, 3612, 1265, 3610, 1265, 1265, 1265, 1265}, + {1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 466: 1266, 1266, 1266, 1266, 1266, 472: 1266, 1266, 475: 1266, 1266, 3606, 3605, 3611, 1266, 1266, 1266, 485: 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 494: 1266, 1266, 1266, 1266, 501: 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 3607, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 537: 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 3608, 3609, 1266, 3612, 1266, 3610, 3603, 3604, 1266, 1266}, + {1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 466: 1267, 1267, 1267, 1267, 1267, 472: 1267, 1267, 475: 1267, 1267, 3606, 3605, 3611, 1267, 1267, 1267, 485: 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 494: 1267, 1267, 1267, 1267, 501: 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 3607, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 537: 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 3608, 3609, 3602, 3612, 1267, 3610, 3603, 3604, 1267, 1267}, // 1160 - {1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 463: 1145, 1145, 1145, 1145, 468: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 479: 1145, 1145, 482: 1145, 1145, 1145, 1145, 1145, 488: 1145, 490: 1145, 1145, 1145, 1145, 495: 1145, 497: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 533: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 571: 1145}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3622}, - {7: 3623, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {570: 3624}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3625}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 795: 3363, 818: 3635}, + {490: 3636}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3637}, + {47: 3638, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 466: 1149, 1149, 1149, 1149, 1149, 472: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 485: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 494: 1149, 1149, 1149, 1149, 501: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 537: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 575: 1149}, // 1165 - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3626}, - {57: 3627}, - {1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 463: 1146, 1146, 1146, 1146, 468: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 479: 1146, 1146, 482: 1146, 1146, 1146, 1146, 1146, 488: 1146, 490: 1146, 1146, 1146, 1146, 495: 1146, 497: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 533: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 571: 1146}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3629}, - {7: 3630, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3640}, + {7: 3641, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {573: 3642}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3643}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3644}, // 1170 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3632, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3631}, - {57: 3636, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 1195, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3633}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 3634}, - {57: 3635}, + {47: 3645}, + {1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 466: 1150, 1150, 1150, 1150, 1150, 472: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 485: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 494: 1150, 1150, 1150, 1150, 501: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 537: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 575: 1150}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3647}, + {7: 3648, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3650, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3649}, // 1175 - {1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 463: 1147, 1147, 1147, 1147, 468: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 479: 1147, 1147, 482: 1147, 1147, 1147, 1147, 1147, 488: 1147, 490: 1147, 1147, 1147, 1147, 495: 1147, 497: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 533: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 571: 1147}, - {1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 463: 1148, 1148, 1148, 1148, 468: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 479: 1148, 1148, 482: 1148, 1148, 1148, 1148, 1148, 488: 1148, 490: 1148, 1148, 1148, 1148, 495: 1148, 497: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 533: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 571: 1148}, - {57: 1874, 496: 3639, 1035: 3638, 3640}, - {57: 1873}, - {57: 1872}, + {47: 3654, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 1199, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3651}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 3652}, + {47: 3653}, + {1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 466: 1151, 1151, 1151, 1151, 1151, 472: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 485: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 494: 1151, 1151, 1151, 1151, 501: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 537: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 575: 1151}, // 1180 - {57: 3641}, - {1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 463: 1149, 1149, 1149, 1149, 468: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 479: 1149, 1149, 482: 1149, 1149, 1149, 1149, 1149, 488: 1149, 490: 1149, 1149, 1149, 1149, 495: 1149, 497: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 533: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 571: 1149}, - {57: 1874, 496: 3639, 1035: 3638, 3643}, - {57: 3644}, - {1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 463: 1150, 1150, 1150, 1150, 468: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 479: 1150, 1150, 482: 1150, 1150, 1150, 1150, 1150, 488: 1150, 490: 1150, 1150, 1150, 1150, 495: 1150, 497: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 533: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 571: 1150}, + {1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 466: 1152, 1152, 1152, 1152, 1152, 472: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 485: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 494: 1152, 1152, 1152, 1152, 501: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 537: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 575: 1152}, + {47: 1881, 500: 3657, 1039: 3656, 3658}, + {47: 1880}, + {47: 1879}, + {47: 3659}, // 1185 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3646}, - {7: 3647, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 3648}, - {57: 3649, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 463: 1152, 1152, 1152, 1152, 468: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 479: 1152, 1152, 482: 1152, 1152, 1152, 1152, 1152, 488: 1152, 490: 1152, 1152, 1152, 1152, 495: 1152, 497: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 533: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 571: 1152}, + {1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 466: 1153, 1153, 1153, 1153, 1153, 472: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 485: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 494: 1153, 1153, 1153, 1153, 501: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 537: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 575: 1153}, + {47: 1881, 500: 3657, 1039: 3656, 3661}, + {47: 3662}, + {1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 466: 1154, 1154, 1154, 1154, 1154, 472: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 485: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 494: 1154, 1154, 1154, 1154, 501: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 537: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 575: 1154}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3664}, // 1190 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3652}, - {7: 3491, 57: 1875}, - {57: 3653}, - {1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 463: 1153, 1153, 1153, 1153, 468: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 479: 1153, 1153, 482: 1153, 1153, 1153, 1153, 1153, 488: 1153, 490: 1153, 1153, 1153, 1153, 495: 1153, 497: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 533: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 571: 1153}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3655}, + {7: 3665, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 3666}, + {47: 3667, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 466: 1156, 1156, 1156, 1156, 1156, 472: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 485: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 494: 1156, 1156, 1156, 1156, 501: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 537: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 575: 1156}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 3670}, // 1195 - {7: 3491, 57: 3656, 471: 3657}, - {1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 463: 1158, 1158, 1158, 1158, 468: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 479: 1158, 1158, 482: 1158, 1158, 1158, 1158, 1158, 488: 1158, 490: 1158, 1158, 1158, 1158, 495: 1158, 497: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 533: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 571: 1158}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 3658}, - {57: 3661}, - {730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 98: 730, 107: 730, 461: 730, 730, 730, 465: 730, 730, 730, 730, 730, 730, 477: 730, 730, 481: 730, 487: 730, 730, 730, 494: 730, 501: 730, 532: 730, 556: 730, 566: 730, 574: 730, 576: 730, 632: 730, 730, 730, 730, 730, 730, 730, 648: 730}, + {7: 3509, 47: 1882}, + {47: 3671}, + {1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 466: 1157, 1157, 1157, 1157, 1157, 472: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 485: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 494: 1157, 1157, 1157, 1157, 501: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 537: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 575: 1157}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3673}, + {7: 3509, 47: 3674, 473: 3675}, // 1200 - {729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 98: 729, 107: 729, 461: 729, 729, 729, 465: 729, 729, 729, 729, 729, 729, 477: 729, 729, 481: 729, 487: 729, 729, 729, 494: 729, 501: 729, 532: 729, 556: 729, 566: 729, 574: 729, 576: 729, 632: 729, 729, 729, 729, 729, 729, 729, 648: 729}, - {1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 463: 1157, 1157, 1157, 1157, 468: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 479: 1157, 1157, 482: 1157, 1157, 1157, 1157, 1157, 488: 1157, 490: 1157, 1157, 1157, 1157, 495: 1157, 497: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 533: 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 571: 1157}, - {1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 463: 1159, 1159, 1159, 1159, 468: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 479: 1159, 1159, 482: 1159, 1159, 1159, 1159, 1159, 488: 1159, 490: 1159, 1159, 1159, 1159, 495: 1159, 497: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 533: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 571: 1159}, - {57: 3664, 496: 3665}, - {1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 463: 1081, 1081, 1081, 1081, 468: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 479: 1081, 1081, 482: 1081, 1081, 1081, 1081, 1081, 488: 1081, 490: 1081, 1081, 1081, 1081, 495: 1081, 497: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 533: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 571: 1081}, + {1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 466: 1162, 1162, 1162, 1162, 1162, 472: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 485: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 494: 1162, 1162, 1162, 1162, 501: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 537: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 575: 1162}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 3676}, + {47: 3679}, + {734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, 47: 734, 98: 734, 107: 734, 464: 734, 734, 734, 734, 469: 734, 734, 734, 734, 474: 734, 482: 734, 734, 734, 493: 734, 495: 734, 734, 498: 734, 734, 536: 734, 562: 734, 565: 734, 574: 734, 576: 734, 586: 734, 616: 734, 635: 734, 734, 734, 734, 640: 734, 649: 734}, + {733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 47: 733, 98: 733, 107: 733, 464: 733, 733, 733, 733, 469: 733, 733, 733, 733, 474: 733, 482: 733, 733, 733, 493: 733, 495: 733, 733, 498: 733, 733, 536: 733, 562: 733, 565: 733, 574: 733, 576: 733, 586: 733, 616: 733, 635: 733, 733, 733, 733, 640: 733, 649: 733}, // 1205 - {57: 3666}, - {1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 463: 1080, 1080, 1080, 1080, 468: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 479: 1080, 1080, 482: 1080, 1080, 1080, 1080, 1080, 488: 1080, 490: 1080, 1080, 1080, 1080, 495: 1080, 497: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 533: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 571: 1080}, - {57: 3668}, - {1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 463: 1160, 1160, 1160, 1160, 468: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 479: 1160, 1160, 482: 1160, 1160, 1160, 1160, 1160, 488: 1160, 490: 1160, 1160, 1160, 1160, 495: 1160, 497: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 533: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 571: 1160}, - {57: 3671}, + {1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 466: 1161, 1161, 1161, 1161, 1161, 472: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 485: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 494: 1161, 1161, 1161, 1161, 501: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 537: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 575: 1161}, + {1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 466: 1163, 1163, 1163, 1163, 1163, 472: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 485: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 494: 1163, 1163, 1163, 1163, 501: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 537: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 575: 1163}, + {47: 3682, 500: 3683}, + {1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 466: 1085, 1085, 1085, 1085, 1085, 472: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 485: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 494: 1085, 1085, 1085, 1085, 501: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 537: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 575: 1085}, + {47: 3684}, // 1210 - {1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 463: 1161, 1161, 1161, 1161, 468: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 479: 1161, 1161, 482: 1161, 1161, 1161, 1161, 1161, 488: 1161, 490: 1161, 1161, 1161, 1161, 495: 1161, 497: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 533: 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 571: 1161}, - {1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 463: 1174, 1174, 1174, 1174, 468: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 479: 1174, 1174, 482: 1174, 1174, 1174, 1174, 1174, 488: 1174, 490: 1174, 1174, 1174, 1174, 495: 1174, 497: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 533: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 571: 1174, 640: 1174, 651: 1174, 658: 1174}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3673}, - {57: 3674}, - {1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 463: 1162, 1162, 1162, 1162, 468: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 479: 1162, 1162, 482: 1162, 1162, 1162, 1162, 1162, 488: 1162, 490: 1162, 1162, 1162, 1162, 495: 1162, 497: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 533: 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 571: 1162}, + {1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 466: 1084, 1084, 1084, 1084, 1084, 472: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 485: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 494: 1084, 1084, 1084, 1084, 501: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 537: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 575: 1084}, + {47: 3686}, + {1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 466: 1164, 1164, 1164, 1164, 1164, 472: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 485: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 494: 1164, 1164, 1164, 1164, 501: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 537: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 575: 1164}, + {47: 3689}, + {1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 466: 1165, 1165, 1165, 1165, 1165, 472: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 485: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 494: 1165, 1165, 1165, 1165, 501: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 537: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 575: 1165}, // 1215 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3676}, - {57: 3677}, - {1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 463: 1163, 1163, 1163, 1163, 468: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 479: 1163, 1163, 482: 1163, 1163, 1163, 1163, 1163, 488: 1163, 490: 1163, 1163, 1163, 1163, 495: 1163, 497: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 533: 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 571: 1163}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3679, 2676, 2677, 2675, 701: 3680}, - {57: 1248, 485: 1248, 642: 3682}, + {1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 466: 1178, 1178, 1178, 1178, 1178, 472: 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 485: 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 494: 1178, 1178, 1178, 1178, 501: 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 537: 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 575: 1178, 641: 1178, 652: 1178, 659: 1178}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 3691}, + {47: 3692}, + {1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 466: 1166, 1166, 1166, 1166, 1166, 472: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 485: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 494: 1166, 1166, 1166, 1166, 501: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 537: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 575: 1166}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 3694}, // 1220 - {57: 3681}, - {1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 463: 1217, 1217, 1217, 1217, 468: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 479: 1217, 1217, 482: 1217, 1217, 1217, 1217, 1217, 488: 1217, 490: 1217, 1217, 1217, 1217, 495: 1217, 497: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 533: 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 571: 1217}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3683, 2676, 2677, 2675}, - {57: 1247, 485: 1247, 642: 3684}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3685, 2676, 2677, 2675}, + {47: 3695}, + {1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 466: 1167, 1167, 1167, 1167, 1167, 472: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 485: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 494: 1167, 1167, 1167, 1167, 501: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 537: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 575: 1167}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3697, 2691, 2692, 2690, 702: 3698}, + {47: 1252, 489: 1252, 643: 3700}, + {47: 3699}, // 1225 - {1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 463: 1246, 1246, 1246, 1246, 468: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 479: 1246, 1246, 482: 1246, 1246, 1246, 1246, 1246, 488: 1246, 490: 1246, 1246, 1246, 1246, 495: 1246, 497: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 533: 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 571: 1246, 645: 1246, 1246}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3679, 2676, 2677, 2675, 701: 3687}, - {57: 3688}, - {1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 463: 1218, 1218, 1218, 1218, 468: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 479: 1218, 1218, 482: 1218, 1218, 1218, 1218, 1218, 488: 1218, 490: 1218, 1218, 1218, 1218, 495: 1218, 497: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 533: 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 571: 1218}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3690}, + {1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 466: 1221, 1221, 1221, 1221, 1221, 472: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 485: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 494: 1221, 1221, 1221, 1221, 501: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 537: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 575: 1221}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3701, 2691, 2692, 2690}, + {47: 1251, 489: 1251, 643: 3702}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3703, 2691, 2692, 2690}, + {1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 466: 1250, 1250, 1250, 1250, 1250, 472: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 485: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 494: 1250, 1250, 1250, 1250, 501: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 537: 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250, 575: 1250, 646: 1250, 1250}, // 1230 - {7: 3691, 471: 3692, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {60: 3703, 105: 3699, 171: 3700, 3698, 175: 3705, 189: 3702, 489: 3710, 532: 3696, 637: 3709, 670: 3701, 3706, 3707, 675: 3708, 729: 3704, 889: 3697, 983: 3695}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 3693}, - {57: 3694}, - {1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 463: 1219, 1219, 1219, 1219, 468: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 479: 1219, 1219, 482: 1219, 1219, 1219, 1219, 1219, 488: 1219, 490: 1219, 1219, 1219, 1219, 495: 1219, 497: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 533: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 571: 1219}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3697, 2691, 2692, 2690, 702: 3705}, + {47: 3706}, + {1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 466: 1222, 1222, 1222, 1222, 1222, 472: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 485: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 494: 1222, 1222, 1222, 1222, 501: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 537: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 575: 1222}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3708}, + {7: 3709, 473: 3710, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1235 - {57: 3746}, - {57: 278, 462: 3725, 750: 3726, 776: 3745}, - {13: 278, 57: 278, 462: 3725, 489: 278, 532: 278, 637: 278, 750: 3726, 776: 3730}, - {57: 1041}, - {57: 1040}, + {49: 3721, 105: 3717, 171: 3718, 3716, 175: 3723, 190: 3720, 498: 3728, 536: 3714, 638: 3727, 671: 3719, 3724, 3725, 676: 3726, 730: 3722, 889: 3715, 987: 3713}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 3711}, + {47: 3712}, + {1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 466: 1223, 1223, 1223, 1223, 1223, 472: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 485: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 494: 1223, 1223, 1223, 1223, 501: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 537: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 575: 1223}, + {47: 3764}, // 1240 - {57: 278, 462: 3725, 750: 3726, 776: 3729}, - {57: 271, 462: 3712, 750: 3713, 892: 3728, 897: 3714}, - {57: 278, 462: 3725, 750: 3726, 776: 3724}, - {57: 342, 673: 3721, 3722, 1073: 3723}, - {57: 342, 673: 3721, 3722, 1073: 3720}, + {47: 280, 465: 3743, 754: 3744, 775: 3763}, + {14: 280, 47: 280, 465: 3743, 498: 280, 536: 280, 638: 280, 754: 3744, 775: 3748}, + {47: 1045}, + {47: 1044}, + {47: 280, 465: 3743, 754: 3744, 775: 3747}, // 1245 - {57: 1034}, - {57: 1033}, - {57: 271, 462: 3712, 750: 3713, 892: 3711, 897: 3714}, - {57: 1031}, - {13: 316, 57: 316, 462: 316, 489: 316, 532: 316, 637: 316}, + {47: 273, 465: 3730, 754: 3731, 892: 3746, 897: 3732}, + {47: 280, 465: 3743, 754: 3744, 775: 3742}, + {47: 344, 674: 3739, 3740, 1076: 3741}, + {47: 344, 674: 3739, 3740, 1076: 3738}, + {47: 1038}, // 1250 - {13: 315, 57: 315, 462: 315, 489: 315, 532: 315, 637: 315}, - {57: 1032}, - {496: 2650, 725: 2649, 734: 3715}, - {270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 57: 270, 60: 270, 461: 270, 465: 270, 270, 270, 270, 470: 270, 478: 270, 481: 270, 566: 270, 574: 270, 576: 270, 632: 270, 270, 635: 270, 270, 729: 270, 731: 270}, - {269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 57: 269, 60: 269, 461: 269, 465: 269, 269, 269, 269, 470: 269, 478: 269, 481: 269, 566: 269, 574: 269, 576: 269, 632: 269, 269, 635: 269, 269, 729: 269, 731: 269}, + {47: 1037}, + {47: 273, 465: 3730, 754: 3731, 892: 3729, 897: 3732}, + {47: 1035}, + {14: 318, 47: 318, 465: 318, 498: 318, 536: 318, 638: 318}, + {14: 317, 47: 317, 465: 317, 498: 317, 536: 317, 638: 317}, // 1255 - {7: 3717, 57: 3716}, - {279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 57: 279, 60: 279, 101: 279, 279, 104: 279, 461: 279, 465: 279, 279, 279, 279, 470: 279, 478: 279, 481: 279, 489: 279, 518: 279, 279, 532: 279, 566: 279, 574: 279, 576: 279, 632: 279, 279, 635: 279, 279, 279, 729: 279, 731: 279}, - {496: 2650, 725: 2649, 734: 3718}, - {57: 3719}, - {268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 57: 268, 60: 268, 461: 268, 465: 268, 268, 268, 268, 470: 268, 478: 268, 481: 268, 566: 268, 574: 268, 576: 268, 632: 268, 268, 635: 268, 268, 729: 268, 731: 268}, + {47: 1036}, + {500: 2665, 724: 2664, 734: 3733}, + {272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 47: 272, 49: 272, 464: 272, 467: 272, 469: 272, 272, 272, 474: 272, 483: 272, 272, 565: 272, 574: 272, 576: 272, 586: 272, 616: 272, 635: 272, 272, 730: 272, 732: 272}, + {271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 47: 271, 49: 271, 464: 271, 467: 271, 469: 271, 271, 271, 474: 271, 483: 271, 271, 565: 271, 574: 271, 576: 271, 586: 271, 616: 271, 635: 271, 271, 730: 271, 732: 271}, + {7: 3735, 47: 3734}, // 1260 - {57: 1035}, - {57: 341}, - {57: 340}, - {57: 1036}, - {57: 1037}, + {281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 14: 281, 47: 281, 49: 281, 101: 281, 281, 104: 281, 464: 281, 467: 281, 469: 281, 281, 281, 474: 281, 483: 281, 281, 498: 281, 521: 281, 281, 536: 281, 565: 281, 574: 281, 576: 281, 586: 281, 616: 281, 635: 281, 281, 638: 281, 730: 281, 732: 281}, + {500: 2665, 724: 2664, 734: 3736}, + {47: 3737}, + {270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 47: 270, 49: 270, 464: 270, 467: 270, 469: 270, 270, 270, 474: 270, 483: 270, 270, 565: 270, 574: 270, 576: 270, 586: 270, 616: 270, 635: 270, 270, 730: 270, 732: 270}, + {47: 1039}, // 1265 - {496: 2650, 725: 2649, 734: 3727}, - {277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 57: 277, 60: 277, 101: 277, 277, 104: 277, 461: 277, 465: 277, 277, 277, 277, 470: 277, 478: 277, 481: 277, 489: 277, 518: 277, 277, 532: 277, 566: 277, 574: 277, 576: 277, 632: 277, 277, 635: 277, 277, 277, 729: 277, 731: 277}, - {57: 3716}, - {57: 1038}, - {57: 1039}, + {47: 343}, + {47: 342}, + {47: 1040}, + {47: 1041}, + {500: 2665, 724: 2664, 734: 3745}, // 1270 - {13: 3735, 57: 265, 489: 3736, 532: 3732, 637: 3734, 762: 3733, 790: 3731}, - {57: 1042}, - {262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 3735, 57: 262, 461: 262, 465: 262, 262, 262, 262, 470: 262, 478: 262, 481: 262, 489: 3736, 566: 262, 574: 262, 576: 262, 632: 262, 262, 635: 262, 262, 3734, 762: 3743, 1237: 3742}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 3739}, - {501: 3738}, + {279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 14: 279, 47: 279, 49: 279, 101: 279, 279, 104: 279, 464: 279, 467: 279, 469: 279, 279, 279, 474: 279, 483: 279, 279, 498: 279, 521: 279, 279, 536: 279, 565: 279, 574: 279, 576: 279, 586: 279, 616: 279, 635: 279, 279, 638: 279, 730: 279, 732: 279}, + {47: 3734}, + {47: 1042}, + {47: 1043}, + {14: 3753, 47: 267, 498: 3754, 536: 3750, 638: 3752, 762: 3751, 789: 3749}, // 1275 - {259, 259, 259, 259, 259, 259, 259, 8: 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 58: 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 464: 259, 467: 259, 485: 259, 492: 259, 510: 259, 532: 259}, - {501: 3737}, - {258, 258, 258, 258, 258, 258, 258, 8: 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 58: 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 464: 258, 467: 258, 485: 258, 492: 258, 510: 258, 532: 258}, - {260, 260, 260, 260, 260, 260, 260, 8: 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 58: 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 464: 260, 467: 260, 485: 260, 492: 260, 510: 260, 532: 260}, - {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 57: 267, 461: 267, 465: 267, 267, 267, 267, 470: 267, 478: 267, 481: 267, 532: 3740, 566: 267, 574: 267, 576: 267, 632: 267, 267, 635: 267, 267, 1236: 3741}, + {47: 1046}, + {264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 14: 3753, 47: 264, 464: 264, 467: 264, 469: 264, 264, 264, 474: 264, 483: 264, 264, 498: 3754, 565: 264, 574: 264, 576: 264, 586: 264, 616: 264, 635: 264, 264, 638: 3752, 762: 3761, 1241: 3760}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 3757}, + {496: 3756}, + {261, 261, 261, 261, 261, 261, 261, 8: 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 48: 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 468: 261, 471: 261, 489: 261, 492: 261, 513: 261, 536: 261}, // 1280 - {266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 57: 266, 461: 266, 465: 266, 266, 266, 266, 470: 266, 478: 266, 481: 266, 566: 266, 574: 266, 576: 266, 632: 266, 266, 635: 266, 266}, - {263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 57: 263, 461: 263, 465: 263, 263, 263, 263, 470: 263, 478: 263, 481: 263, 566: 263, 574: 263, 576: 263, 632: 263, 263, 635: 263, 263}, - {264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 57: 264, 461: 264, 465: 264, 264, 264, 264, 470: 264, 478: 264, 481: 264, 566: 264, 574: 264, 576: 264, 632: 264, 264, 635: 264, 264}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 3744}, - {261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 57: 261, 461: 261, 465: 261, 261, 261, 261, 470: 261, 478: 261, 481: 261, 566: 261, 574: 261, 576: 261, 632: 261, 261, 635: 261, 261}, + {496: 3755}, + {260, 260, 260, 260, 260, 260, 260, 8: 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 48: 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 468: 260, 471: 260, 489: 260, 492: 260, 513: 260, 536: 260}, + {262, 262, 262, 262, 262, 262, 262, 8: 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 48: 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 468: 262, 471: 262, 489: 262, 492: 262, 513: 262, 536: 262}, + {269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 47: 269, 464: 269, 467: 269, 469: 269, 269, 269, 474: 269, 483: 269, 269, 536: 3758, 565: 269, 574: 269, 576: 269, 586: 269, 616: 269, 635: 269, 269, 1240: 3759}, + {268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 47: 268, 464: 268, 467: 268, 469: 268, 268, 268, 474: 268, 483: 268, 268, 565: 268, 574: 268, 576: 268, 586: 268, 616: 268, 635: 268, 268}, // 1285 - {57: 1043}, - {1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 463: 1220, 1220, 1220, 1220, 468: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 479: 1220, 1220, 482: 1220, 1220, 1220, 1220, 1220, 488: 1220, 490: 1220, 1220, 1220, 1220, 495: 1220, 497: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 533: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 571: 1220}, - {495: 3249, 497: 3247, 3248, 3246, 3244, 531: 1049, 723: 3245, 3243}, - {531: 3751, 1139: 3750, 1318: 3749}, - {155: 1045, 531: 3751, 534: 3757, 1139: 3756, 1183: 3755}, + {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 47: 265, 464: 265, 467: 265, 469: 265, 265, 265, 474: 265, 483: 265, 265, 565: 265, 574: 265, 576: 265, 586: 265, 616: 265, 635: 265, 265}, + {266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 47: 266, 464: 266, 467: 266, 469: 266, 266, 266, 474: 266, 483: 266, 266, 565: 266, 574: 266, 576: 266, 586: 266, 616: 266, 635: 266, 266}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 3762}, + {263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 47: 263, 464: 263, 467: 263, 469: 263, 263, 263, 474: 263, 483: 263, 263, 565: 263, 574: 263, 576: 263, 586: 263, 616: 263, 635: 263, 263}, + {47: 1047}, // 1290 - {155: 1048, 531: 1048, 534: 1048}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3752}, - {495: 3249, 497: 3247, 3248, 3246, 3244, 535: 3753, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3754}, - {155: 1046, 495: 3249, 497: 3247, 3248, 3246, 3244, 531: 1046, 534: 1046, 723: 3245, 3243}, + {1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 466: 1224, 1224, 1224, 1224, 1224, 472: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 485: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 494: 1224, 1224, 1224, 1224, 501: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 537: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 575: 1224}, + {497: 3265, 501: 3263, 3264, 3262, 3260, 534: 1053, 725: 3261, 3259}, + {534: 3769, 1143: 3768, 1322: 3767}, + {156: 1049, 534: 3769, 537: 3775, 1143: 3774, 1188: 3773}, + {156: 1052, 534: 1052, 537: 1052}, // 1295 - {155: 3759}, - {155: 1047, 531: 1047, 534: 1047}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3758}, - {155: 1044, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 463: 1221, 1221, 1221, 1221, 468: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 479: 1221, 1221, 482: 1221, 1221, 1221, 1221, 1221, 488: 1221, 490: 1221, 1221, 1221, 1221, 495: 1221, 497: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 533: 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 571: 1221}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3770}, + {497: 3265, 501: 3263, 3264, 3262, 3260, 538: 3771, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3772}, + {156: 1050, 497: 3265, 501: 3263, 3264, 3262, 3260, 534: 1050, 537: 1050, 725: 3261, 3259}, + {156: 3777}, // 1300 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3761}, - {468: 3762, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {60: 3703, 105: 3699, 171: 3700, 3698, 175: 3705, 189: 3702, 489: 3710, 532: 3696, 637: 3709, 670: 3701, 3706, 3707, 675: 3708, 729: 3704, 889: 3697, 983: 3763}, - {57: 3764}, - {1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 463: 1222, 1222, 1222, 1222, 468: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 479: 1222, 1222, 482: 1222, 1222, 1222, 1222, 1222, 488: 1222, 490: 1222, 1222, 1222, 1222, 495: 1222, 497: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 533: 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 571: 1222}, + {156: 1051, 534: 1051, 537: 1051}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3776}, + {156: 1048, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 466: 1225, 1225, 1225, 1225, 1225, 472: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 485: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 494: 1225, 1225, 1225, 1225, 501: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 537: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 575: 1225}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3779}, // 1305 - {1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 463: 1223, 1223, 1223, 1223, 468: 1223, 1223, 3253, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 479: 1223, 1223, 482: 1223, 1223, 1223, 1223, 1223, 488: 1223, 490: 1223, 1223, 1223, 1223, 495: 1223, 497: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 533: 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 571: 1223}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3767}, - {495: 3249, 497: 3247, 3248, 3246, 3244, 511: 3768, 723: 3245, 3243}, - {1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 463: 1224, 1224, 1224, 1224, 468: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 479: 1224, 1224, 482: 1224, 1224, 1224, 1224, 1224, 488: 1224, 490: 1224, 1224, 1224, 1224, 495: 1224, 497: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 533: 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 571: 1224}, - {1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 463: 1225, 1225, 1225, 1225, 468: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 479: 1225, 1225, 482: 1225, 1225, 1225, 1225, 1225, 488: 1225, 490: 1225, 1225, 1225, 1225, 495: 1225, 497: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 533: 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 571: 1225}, + {470: 3780, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {49: 3721, 105: 3717, 171: 3718, 3716, 175: 3723, 190: 3720, 498: 3728, 536: 3714, 638: 3727, 671: 3719, 3724, 3725, 676: 3726, 730: 3722, 889: 3715, 987: 3781}, + {47: 3782}, + {1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 466: 1226, 1226, 1226, 1226, 1226, 472: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 485: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 494: 1226, 1226, 1226, 1226, 501: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 537: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 575: 1226}, + {1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 466: 1227, 1227, 1227, 1227, 1227, 472: 1227, 1227, 3269, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 485: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 494: 1227, 1227, 1227, 1227, 501: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 537: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 575: 1227}, // 1310 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3771}, - {7: 3772}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3773}, - {7: 1879, 57: 3774, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 463: 1226, 1226, 1226, 1226, 468: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 479: 1226, 1226, 482: 1226, 1226, 1226, 1226, 1226, 488: 1226, 490: 1226, 1226, 1226, 1226, 495: 1226, 497: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 533: 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 571: 1226}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3785}, + {497: 3265, 501: 3263, 3264, 3262, 3260, 514: 3786, 725: 3261, 3259}, + {1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 466: 1228, 1228, 1228, 1228, 1228, 472: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 485: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 494: 1228, 1228, 1228, 1228, 501: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 537: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 575: 1228}, + {1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 466: 1229, 1229, 1229, 1229, 1229, 472: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 485: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 494: 1229, 1229, 1229, 1229, 501: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 537: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 575: 1229}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3789}, // 1315 - {7: 1880, 57: 3877, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {7: 3874}, - {7: 1229, 57: 1229, 465: 1229, 1229, 469: 786, 1229, 474: 1229, 1229, 1229, 479: 786, 786, 483: 2642, 485: 1229, 491: 2643, 493: 2639, 495: 1229, 497: 1229, 1229, 1229, 1229, 510: 1229, 512: 1229, 533: 1229, 536: 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 571: 1229, 756: 3790, 3791}, - {462: 3678, 564: 3795, 900: 3794, 961: 3793}, - {462: 2509, 487: 2507, 556: 2506, 634: 2502, 699: 3787, 741: 3786, 2503, 2504, 2505, 2514, 2512, 3788, 3789}, + {7: 3790}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3791}, + {7: 1886, 47: 3792, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 466: 1230, 1230, 1230, 1230, 1230, 472: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 485: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 494: 1230, 1230, 1230, 1230, 501: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 537: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 575: 1230}, + {7: 1887, 47: 3895, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1320 - {57: 3785, 469: 787, 479: 787, 787}, - {57: 3784}, - {57: 3783}, - {814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 468: 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 479: 814, 814, 482: 814, 814, 814, 814, 814, 814, 814, 490: 814, 814, 814, 814, 495: 814, 497: 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 533: 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 556: 814, 571: 814, 634: 814, 644: 814, 732: 814}, - {815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 468: 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 479: 815, 815, 482: 815, 815, 815, 815, 815, 815, 815, 490: 815, 815, 815, 815, 495: 815, 497: 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 533: 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 556: 815, 571: 815, 634: 815, 644: 815, 732: 815}, + {7: 3892}, + {7: 1233, 47: 1233, 467: 1233, 469: 1233, 472: 790, 474: 1233, 477: 1233, 1233, 1233, 790, 790, 486: 2657, 489: 1233, 491: 2658, 494: 2654, 497: 1233, 501: 1233, 1233, 1233, 1233, 513: 1233, 515: 1233, 535: 1233, 539: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 575: 1233, 757: 3808, 3809}, + {465: 3696, 568: 3813, 900: 3812, 964: 3811}, + {465: 2523, 493: 2521, 562: 2520, 637: 2516, 700: 3805, 742: 3804, 2517, 2518, 2519, 2528, 2526, 3806, 3807}, + {47: 3803, 472: 791, 480: 791, 791}, // 1325 - {816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 468: 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 479: 816, 816, 482: 816, 816, 816, 816, 816, 816, 816, 490: 816, 816, 816, 816, 495: 816, 497: 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 533: 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, 556: 816, 571: 816, 634: 816, 644: 816, 732: 816}, - {971, 971, 57: 971, 461: 971, 463: 971, 469: 787, 471: 971, 479: 787, 787}, - {970, 970, 57: 970, 461: 970, 463: 970, 469: 786, 471: 970, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {799, 799, 57: 799, 461: 799, 463: 799, 471: 799}, - {798, 798, 57: 798, 461: 798, 463: 798, 471: 798}, + {47: 3802}, + {47: 3801}, + {818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 472: 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 485: 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 501: 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 537: 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 562: 818, 575: 818, 637: 818, 645: 818, 733: 818}, + {819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 472: 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 485: 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 501: 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 537: 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 562: 819, 575: 819, 637: 819, 645: 819, 733: 819}, + {820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 472: 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 485: 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 501: 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 537: 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 562: 820, 575: 820, 637: 820, 645: 820, 733: 820}, // 1330 - {792, 792, 57: 792, 461: 792, 463: 792, 471: 792, 483: 2642, 491: 2643, 757: 3792}, - {791, 791, 57: 791, 461: 791, 463: 791, 471: 791}, - {790, 790, 57: 790, 461: 790, 463: 790, 471: 790}, - {1265, 1265, 7: 3807, 57: 1265, 461: 1265, 463: 1265, 469: 1265, 471: 1265, 479: 1265, 1265, 482: 1265, 1265, 1265, 486: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 3806}, - {8, 8, 7: 8, 57: 8, 461: 8, 463: 8, 469: 8, 471: 8, 479: 8, 8, 482: 8, 8, 8, 486: 8, 491: 8, 493: 8}, + {975, 975, 47: 975, 464: 975, 466: 975, 472: 791, 975, 480: 791, 791}, + {974, 974, 47: 974, 464: 974, 466: 974, 472: 790, 974, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {803, 803, 47: 803, 464: 803, 466: 803, 473: 803}, + {802, 802, 47: 802, 464: 802, 466: 802, 473: 802}, + {796, 796, 47: 796, 464: 796, 466: 796, 473: 796, 486: 2657, 491: 2658, 758: 3810}, // 1335 - {462: 3796, 829: 3797}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1305, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 3801, 1308: 3800, 3799}, - {6, 6, 7: 6, 57: 6, 461: 6, 463: 6, 469: 6, 471: 6, 479: 6, 6, 482: 6, 6, 6, 486: 6, 491: 6, 493: 6}, - {1301, 1301, 7: 1301, 57: 1301, 461: 1301, 471: 1301, 483: 1301, 492: 1301, 1301, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {57: 3805}, + {795, 795, 47: 795, 464: 795, 466: 795, 473: 795}, + {794, 794, 47: 794, 464: 794, 466: 794, 473: 794}, + {1269, 1269, 7: 3825, 47: 1269, 464: 1269, 466: 1269, 472: 1269, 1269, 480: 1269, 1269, 485: 1269, 1269, 1269, 1269, 491: 1269, 494: 2654, 757: 2655, 800: 3824}, + {8, 8, 7: 8, 47: 8, 464: 8, 466: 8, 472: 8, 8, 480: 8, 8, 485: 8, 8, 8, 8, 491: 8, 494: 8}, + {465: 3814, 828: 3815}, // 1340 - {7: 3803, 57: 1304}, - {7: 1302, 57: 1302}, - {1300, 1300, 7: 1300, 57: 1300, 461: 1300, 3686, 471: 1300, 483: 1300, 492: 1300, 1300}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 3804}, - {7: 1303, 57: 1303}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1309, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 3819, 1312: 3818, 3817}, + {6, 6, 7: 6, 47: 6, 464: 6, 466: 6, 472: 6, 6, 480: 6, 6, 485: 6, 6, 6, 6, 491: 6, 494: 6}, + {1305, 1305, 7: 1305, 47: 1305, 464: 1305, 473: 1305, 486: 1305, 492: 1305, 494: 1305, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {47: 3823}, + {7: 3821, 47: 1308}, // 1345 - {1306, 1306, 7: 1306, 15: 1306, 57: 1306, 461: 1306, 463: 1306, 469: 1306, 471: 1306, 479: 1306, 1306, 482: 1306, 1306, 1306, 486: 1306, 491: 1306, 493: 1306, 495: 1306}, - {841, 841, 57: 841, 461: 841, 463: 841, 469: 841, 471: 841, 479: 841, 841, 482: 841, 2642, 841, 486: 841, 491: 2643, 757: 2644, 818: 3809}, - {564: 3795, 900: 3808}, - {7, 7, 7: 7, 57: 7, 461: 7, 463: 7, 469: 7, 471: 7, 479: 7, 7, 482: 7, 7, 7, 486: 7, 491: 7, 493: 7}, - {812, 812, 57: 812, 461: 812, 463: 812, 469: 812, 471: 812, 479: 812, 812, 482: 3811, 484: 812, 486: 3812, 875: 3810}, + {7: 1306, 47: 1306}, + {1304, 1304, 7: 1304, 47: 1304, 464: 1304, 3704, 473: 1304, 486: 1304, 492: 1304, 494: 1304}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 3822}, + {7: 1307, 47: 1307}, + {1310, 1310, 7: 1310, 47: 1310, 86: 1310, 464: 1310, 466: 1310, 472: 1310, 1310, 480: 1310, 1310, 485: 1310, 1310, 1310, 1310, 491: 1310, 494: 1310, 497: 1310}, // 1350 - {818, 818, 57: 818, 461: 818, 463: 818, 469: 818, 471: 818, 479: 818, 818, 484: 3837, 876: 3836}, - {273: 3817, 644: 3816}, - {533: 3813}, - {273: 3814}, - {203: 3815}, + {845, 845, 47: 845, 464: 845, 466: 845, 472: 845, 845, 480: 845, 845, 485: 845, 2657, 845, 845, 491: 2658, 758: 2659, 817: 3827}, + {568: 3813, 900: 3826}, + {7, 7, 7: 7, 47: 7, 464: 7, 466: 7, 472: 7, 7, 480: 7, 7, 485: 7, 7, 7, 7, 491: 7, 494: 7}, + {816, 816, 47: 816, 464: 816, 466: 816, 472: 816, 816, 480: 816, 816, 485: 3829, 487: 816, 3830, 876: 3828}, + {822, 822, 47: 822, 464: 822, 466: 822, 472: 822, 822, 480: 822, 822, 487: 3855, 877: 3854}, // 1355 - {804, 804, 57: 804, 461: 804, 463: 804, 469: 804, 471: 804, 479: 804, 804, 484: 804}, - {803, 803, 57: 803, 137: 803, 149: 803, 169: 803, 461: 803, 463: 803, 469: 803, 471: 803, 479: 803, 803, 484: 803, 1066: 3819, 3830}, - {803, 803, 57: 803, 137: 803, 149: 803, 461: 803, 463: 803, 469: 803, 471: 803, 479: 803, 803, 484: 803, 1066: 3819, 3818}, - {810, 810, 57: 810, 137: 3828, 149: 3827, 461: 810, 463: 810, 469: 810, 471: 810, 479: 810, 810, 484: 810}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 3822}, + {274: 3835, 645: 3834}, + {535: 3831}, + {274: 3832}, + {203: 3833}, + {808, 808, 47: 808, 464: 808, 466: 808, 472: 808, 808, 480: 808, 808, 487: 808}, // 1360 - {1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 533: 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 556: 1025, 566: 1025, 571: 1025, 574: 1025, 1025, 1025, 632: 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 3825, 1025, 1025, 647: 1025, 1025, 1025, 652: 1025, 659: 1025, 1025, 1025, 1025, 1025, 1025, 669: 1025, 676: 1025, 1025, 679: 1025, 694: 1025}, - {1023, 1023, 7: 1023, 57: 1023, 137: 1023, 149: 1023, 169: 1023, 461: 1023, 463: 1023, 469: 1023, 471: 1023, 479: 1023, 1023, 484: 1023, 490: 1023, 640: 1023, 660: 1023, 662: 1023}, - {802, 802, 7: 3823, 57: 802, 137: 802, 149: 802, 169: 802, 461: 802, 463: 802, 469: 802, 471: 802, 479: 802, 802, 484: 802}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3824}, - {1022, 1022, 7: 1022, 57: 1022, 137: 1022, 149: 1022, 159: 1022, 169: 1022, 461: 1022, 463: 1022, 469: 1022, 471: 1022, 479: 1022, 1022, 484: 1022, 490: 1022, 640: 1022, 1022, 660: 1022, 662: 1022}, + {807, 807, 47: 807, 137: 807, 150: 807, 169: 807, 464: 807, 466: 807, 472: 807, 807, 480: 807, 807, 487: 807, 1069: 3837, 3848}, + {807, 807, 47: 807, 137: 807, 150: 807, 464: 807, 466: 807, 472: 807, 807, 480: 807, 807, 487: 807, 1069: 3837, 3836}, + {814, 814, 47: 814, 137: 3846, 150: 3845, 464: 814, 466: 814, 472: 814, 814, 480: 814, 814, 487: 814}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 3840}, + {1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 537: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 562: 1029, 565: 1029, 574: 1029, 1029, 1029, 579: 1029, 586: 1029, 616: 1029, 635: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 3843, 1029, 1029, 648: 1029, 1029, 1029, 653: 1029, 660: 1029, 1029, 1029, 1029, 1029, 1029, 670: 1029, 677: 1029, 1029, 680: 1029, 695: 1029}, // 1365 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3826, 2676, 2677, 2675}, - {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 533: 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 556: 1024, 566: 1024, 571: 1024, 574: 1024, 1024, 1024, 632: 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 643: 1024, 1024, 647: 1024, 1024, 1024, 652: 1024, 659: 1024, 1024, 1024, 1024, 1024, 1024, 669: 1024, 676: 1024, 1024, 679: 1024, 694: 1024}, - {807, 807, 57: 807, 461: 807, 463: 807, 469: 807, 471: 807, 479: 807, 807, 484: 807}, - {255: 3829}, - {805, 805, 57: 805, 461: 805, 463: 805, 469: 805, 471: 805, 479: 805, 805, 484: 805}, + {1027, 1027, 7: 1027, 47: 1027, 137: 1027, 150: 1027, 169: 1027, 464: 1027, 466: 1027, 472: 1027, 1027, 480: 1027, 1027, 487: 1027, 490: 1027, 641: 1027, 661: 1027, 663: 1027}, + {806, 806, 7: 3841, 47: 806, 137: 806, 150: 806, 169: 806, 464: 806, 466: 806, 472: 806, 806, 480: 806, 806, 487: 806}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3842}, + {1026, 1026, 7: 1026, 47: 1026, 137: 1026, 150: 1026, 160: 1026, 169: 1026, 464: 1026, 466: 1026, 472: 1026, 1026, 480: 1026, 1026, 487: 1026, 490: 1026, 641: 1026, 1026, 661: 1026, 663: 1026}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3844, 2691, 2692, 2690}, // 1370 - {811, 811, 57: 811, 137: 3833, 149: 3831, 169: 3832, 461: 811, 463: 811, 469: 811, 471: 811, 479: 811, 811, 484: 811}, - {809, 809, 57: 809, 461: 809, 463: 809, 469: 809, 471: 809, 479: 809, 809, 484: 809}, - {496: 2650, 725: 3835}, - {255: 3834}, - {806, 806, 57: 806, 461: 806, 463: 806, 469: 806, 471: 806, 479: 806, 806, 484: 806}, + {1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 537: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 562: 1028, 565: 1028, 574: 1028, 1028, 1028, 579: 1028, 586: 1028, 616: 1028, 635: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 644: 1028, 1028, 648: 1028, 1028, 1028, 653: 1028, 660: 1028, 1028, 1028, 1028, 1028, 1028, 670: 1028, 677: 1028, 1028, 680: 1028, 695: 1028}, + {811, 811, 47: 811, 464: 811, 466: 811, 472: 811, 811, 480: 811, 811, 487: 811}, + {255: 3847}, + {809, 809, 47: 809, 464: 809, 466: 809, 472: 809, 809, 480: 809, 809, 487: 809}, + {815, 815, 47: 815, 137: 3851, 150: 3849, 169: 3850, 464: 815, 466: 815, 472: 815, 815, 480: 815, 815, 487: 815}, // 1375 - {808, 808, 57: 808, 461: 808, 463: 808, 469: 808, 471: 808, 479: 808, 808, 484: 808}, - {972, 972, 57: 972, 461: 972, 463: 972, 469: 972, 471: 972, 479: 972, 972}, - {1248: 3838}, - {464: 3839}, - {94, 94, 57: 94, 98: 3843, 107: 3842, 461: 94, 463: 94, 469: 94, 471: 94, 479: 94, 94, 648: 94, 823: 3841, 1032: 3840}, + {813, 813, 47: 813, 464: 813, 466: 813, 472: 813, 813, 480: 813, 813, 487: 813}, + {500: 2665, 724: 3853}, + {255: 3852}, + {810, 810, 47: 810, 464: 810, 466: 810, 472: 810, 810, 480: 810, 810, 487: 810}, + {812, 812, 47: 812, 464: 812, 466: 812, 472: 812, 812, 480: 812, 812, 487: 812}, // 1380 - {81, 81, 57: 81, 461: 81, 463: 81, 469: 81, 471: 81, 479: 81, 81, 648: 3864, 932: 3863}, - {772: 3846, 778: 3848, 784: 3849, 3847, 1031: 3845, 1190: 3844}, - {92, 92, 27: 92, 59: 92, 61: 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 461: 92, 92, 490: 92, 533: 92, 643: 92, 772: 92, 778: 92, 784: 92, 92}, - {91, 91, 27: 91, 59: 91, 61: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 461: 91, 91, 490: 91, 533: 91, 643: 91, 772: 91, 778: 91, 784: 91, 91}, - {93, 93, 57: 93, 461: 93, 93, 93, 469: 93, 471: 93, 477: 93, 479: 93, 93, 501: 93, 648: 93, 772: 3846, 778: 3848, 784: 3849, 3847, 1031: 3862}, + {976, 976, 47: 976, 464: 976, 466: 976, 472: 976, 976, 480: 976, 976}, + {1252: 3856}, + {468: 3857}, + {94, 94, 47: 94, 98: 3861, 107: 3860, 464: 94, 466: 94, 472: 94, 94, 480: 94, 94, 649: 94, 822: 3859, 1036: 3858}, + {81, 81, 47: 81, 464: 81, 466: 81, 472: 81, 81, 480: 81, 81, 649: 3882, 932: 3881}, // 1385 - {89, 89, 57: 89, 461: 89, 89, 89, 469: 89, 471: 89, 477: 89, 479: 89, 89, 501: 89, 648: 89, 772: 89, 778: 89, 784: 89, 89}, - {649: 3860}, - {778: 3857}, - {649: 3855}, - {649: 3850}, + {772: 3864, 777: 3866, 783: 3867, 3865, 1035: 3863, 1195: 3862}, + {92, 92, 15: 92, 48: 92, 50: 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 464: 92, 92, 490: 92, 535: 92, 644: 92, 772: 92, 777: 92, 783: 92, 92}, + {91, 91, 15: 91, 48: 91, 50: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 464: 91, 91, 490: 91, 535: 91, 644: 91, 772: 91, 777: 91, 783: 91, 91}, + {93, 93, 47: 93, 464: 93, 93, 93, 472: 93, 93, 480: 93, 93, 93, 496: 93, 649: 93, 772: 3864, 777: 3866, 783: 3867, 3865, 1035: 3880}, + {89, 89, 47: 89, 464: 89, 89, 89, 472: 89, 89, 480: 89, 89, 89, 496: 89, 649: 89, 772: 89, 777: 89, 783: 89, 89}, // 1390 - {464: 3852, 565: 3853, 569: 3854, 842: 3851}, - {85, 85, 57: 85, 461: 85, 85, 85, 469: 85, 471: 85, 477: 85, 479: 85, 85, 501: 85, 648: 85, 772: 85, 778: 85, 784: 85, 85}, - {84, 84, 57: 84, 461: 84, 84, 84, 469: 84, 471: 84, 477: 84, 479: 84, 84, 501: 84, 648: 84, 772: 84, 778: 84, 784: 84, 84}, - {83, 83, 57: 83, 461: 83, 83, 83, 469: 83, 471: 83, 477: 83, 479: 83, 83, 501: 83, 648: 83, 772: 83, 778: 83, 784: 83, 83}, - {82, 82, 57: 82, 461: 82, 82, 82, 469: 82, 471: 82, 477: 82, 479: 82, 82, 501: 82, 648: 82, 772: 82, 778: 82, 784: 82, 82}, + {650: 3878}, + {777: 3875}, + {650: 3873}, + {650: 3868}, + {468: 3870, 569: 3871, 572: 3872, 842: 3869}, // 1395 - {464: 3852, 565: 3853, 569: 3854, 842: 3856}, - {86, 86, 57: 86, 461: 86, 86, 86, 469: 86, 471: 86, 477: 86, 479: 86, 86, 501: 86, 648: 86, 772: 86, 778: 86, 784: 86, 86}, - {649: 3858}, - {464: 3852, 565: 3853, 569: 3854, 842: 3859}, - {87, 87, 57: 87, 461: 87, 87, 87, 469: 87, 471: 87, 477: 87, 479: 87, 87, 501: 87, 648: 87, 772: 87, 778: 87, 784: 87, 87}, + {85, 85, 47: 85, 464: 85, 85, 85, 472: 85, 85, 480: 85, 85, 85, 496: 85, 649: 85, 772: 85, 777: 85, 783: 85, 85}, + {84, 84, 47: 84, 464: 84, 84, 84, 472: 84, 84, 480: 84, 84, 84, 496: 84, 649: 84, 772: 84, 777: 84, 783: 84, 84}, + {83, 83, 47: 83, 464: 83, 83, 83, 472: 83, 83, 480: 83, 83, 83, 496: 83, 649: 83, 772: 83, 777: 83, 783: 83, 83}, + {82, 82, 47: 82, 464: 82, 82, 82, 472: 82, 82, 480: 82, 82, 82, 496: 82, 649: 82, 772: 82, 777: 82, 783: 82, 82}, + {468: 3870, 569: 3871, 572: 3872, 842: 3874}, // 1400 - {464: 3852, 565: 3853, 569: 3854, 842: 3861}, - {88, 88, 57: 88, 461: 88, 88, 88, 469: 88, 471: 88, 477: 88, 479: 88, 88, 501: 88, 648: 88, 772: 88, 778: 88, 784: 88, 88}, - {90, 90, 57: 90, 461: 90, 90, 90, 469: 90, 471: 90, 477: 90, 479: 90, 90, 501: 90, 648: 90, 772: 90, 778: 90, 784: 90, 90}, - {817, 817, 57: 817, 461: 817, 463: 817, 469: 817, 471: 817, 479: 817, 817}, - {79, 79, 57: 79, 461: 79, 79, 79, 469: 79, 471: 79, 477: 79, 479: 79, 79, 501: 79, 772: 79, 1281: 3865, 3866}, + {86, 86, 47: 86, 464: 86, 86, 86, 472: 86, 86, 480: 86, 86, 86, 496: 86, 649: 86, 772: 86, 777: 86, 783: 86, 86}, + {650: 3876}, + {468: 3870, 569: 3871, 572: 3872, 842: 3877}, + {87, 87, 47: 87, 464: 87, 87, 87, 472: 87, 87, 480: 87, 87, 87, 496: 87, 649: 87, 772: 87, 777: 87, 783: 87, 87}, + {468: 3870, 569: 3871, 572: 3872, 842: 3879}, // 1405 - {77, 77, 57: 77, 461: 77, 77, 77, 469: 77, 471: 77, 477: 77, 479: 77, 77, 501: 77, 772: 3870, 1221: 3869}, - {649: 3867}, - {464: 3852, 565: 3853, 569: 3854, 842: 3868}, - {78, 78, 57: 78, 461: 78, 78, 78, 469: 78, 471: 78, 477: 78, 479: 78, 78, 501: 78, 772: 78}, - {80, 80, 57: 80, 461: 80, 80, 80, 469: 80, 471: 80, 477: 80, 479: 80, 80, 501: 80}, + {88, 88, 47: 88, 464: 88, 88, 88, 472: 88, 88, 480: 88, 88, 88, 496: 88, 649: 88, 772: 88, 777: 88, 783: 88, 88}, + {90, 90, 47: 90, 464: 90, 90, 90, 472: 90, 90, 480: 90, 90, 90, 496: 90, 649: 90, 772: 90, 777: 90, 783: 90, 90}, + {821, 821, 47: 821, 464: 821, 466: 821, 472: 821, 821, 480: 821, 821}, + {79, 79, 47: 79, 464: 79, 79, 79, 472: 79, 79, 480: 79, 79, 79, 496: 79, 772: 79, 1285: 3883, 3884}, + {77, 77, 47: 77, 464: 77, 77, 77, 472: 77, 77, 480: 77, 77, 77, 496: 77, 772: 3888, 1226: 3887}, // 1410 - {649: 3871}, - {464: 3852, 565: 3853, 569: 3854, 842: 3872}, - {76, 76, 57: 76, 461: 76, 76, 76, 469: 76, 471: 76, 477: 76, 479: 76, 76, 501: 76}, - {813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 468: 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 479: 813, 813, 482: 813, 813, 813, 813, 813, 813, 813, 490: 813, 813, 813, 813, 495: 813, 497: 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 533: 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 556: 813, 571: 813, 634: 813, 644: 813, 732: 813}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3875}, + {650: 3885}, + {468: 3870, 569: 3871, 572: 3872, 842: 3886}, + {78, 78, 47: 78, 464: 78, 78, 78, 472: 78, 78, 480: 78, 78, 78, 496: 78, 772: 78}, + {80, 80, 47: 80, 464: 80, 80, 80, 472: 80, 80, 480: 80, 80, 80, 496: 80}, + {650: 3889}, // 1415 - {7: 1879, 57: 3876, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 463: 1227, 1227, 1227, 1227, 468: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 479: 1227, 1227, 482: 1227, 1227, 1227, 1227, 1227, 488: 1227, 490: 1227, 1227, 1227, 1227, 495: 1227, 497: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 533: 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 571: 1227}, - {1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 463: 1228, 1228, 1228, 1228, 468: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 479: 1228, 1228, 482: 1228, 1228, 1228, 1228, 1228, 488: 1228, 490: 1228, 1228, 1228, 1228, 495: 1228, 497: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 533: 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 571: 1228}, - {1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 463: 1230, 1230, 1230, 1230, 468: 1230, 1230, 3253, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 479: 1230, 1230, 482: 1230, 1230, 1230, 1230, 1230, 488: 1230, 490: 1230, 1230, 1230, 1230, 495: 1230, 497: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 533: 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 571: 1230}, - {1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 463: 1232, 1232, 1232, 1232, 468: 1232, 1232, 3253, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 479: 1232, 1232, 482: 1232, 1232, 1232, 1232, 1232, 488: 1232, 490: 1232, 1232, 1232, 1232, 495: 1232, 497: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 533: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 571: 1232}, + {468: 3870, 569: 3871, 572: 3872, 842: 3890}, + {76, 76, 47: 76, 464: 76, 76, 76, 472: 76, 76, 480: 76, 76, 76, 496: 76}, + {817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 472: 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 485: 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 501: 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 537: 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 562: 817, 575: 817, 637: 817, 645: 817, 733: 817}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3893}, + {7: 1886, 47: 3894, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1420 - {1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 463: 1233, 1233, 1233, 1233, 468: 1233, 1233, 3253, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 479: 1233, 1233, 482: 1233, 1233, 1233, 1233, 1233, 488: 1233, 490: 1233, 1233, 1233, 1233, 495: 1233, 497: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 533: 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 571: 1233}, - {1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 463: 1234, 1234, 1234, 1234, 468: 1234, 1234, 3253, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 479: 1234, 1234, 482: 1234, 1234, 1234, 1234, 1234, 488: 1234, 490: 1234, 1234, 1234, 1234, 495: 1234, 497: 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 533: 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 571: 1234}, - {1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 463: 1235, 1235, 1235, 1235, 468: 1235, 1235, 3253, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 479: 1235, 1235, 482: 1235, 1235, 1235, 1235, 1235, 488: 1235, 490: 1235, 1235, 1235, 1235, 495: 1235, 497: 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 533: 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 571: 1235}, - {464: 3886}, - {464: 3885}, + {1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 466: 1231, 1231, 1231, 1231, 1231, 472: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 485: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 494: 1231, 1231, 1231, 1231, 501: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 537: 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 575: 1231}, + {1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 466: 1232, 1232, 1232, 1232, 1232, 472: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 485: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 494: 1232, 1232, 1232, 1232, 501: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 537: 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 575: 1232}, + {1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 466: 1234, 1234, 1234, 1234, 1234, 472: 1234, 1234, 3269, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 485: 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 494: 1234, 1234, 1234, 1234, 501: 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 537: 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 575: 1234}, + {1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 466: 1236, 1236, 1236, 1236, 1236, 472: 1236, 1236, 3269, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 485: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 494: 1236, 1236, 1236, 1236, 501: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 537: 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 575: 1236}, + {1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 466: 1237, 1237, 1237, 1237, 1237, 472: 1237, 1237, 3269, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 485: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 494: 1237, 1237, 1237, 1237, 501: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 537: 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 575: 1237}, // 1425 - {1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 463: 1215, 1215, 1215, 1215, 468: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 479: 1215, 1215, 482: 1215, 1215, 1215, 1215, 1215, 488: 1215, 490: 1215, 1215, 1215, 1215, 495: 1215, 497: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 533: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 571: 1215}, - {1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 463: 1216, 1216, 1216, 1216, 468: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 479: 1216, 1216, 482: 1216, 1216, 1216, 1216, 1216, 488: 1216, 490: 1216, 1216, 1216, 1216, 495: 1216, 497: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 533: 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 571: 1216}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3888, 2676, 2677, 2675}, - {1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 3889, 1247, 1247, 1247, 1247, 468: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 479: 1247, 1247, 482: 1247, 1247, 1247, 1247, 1247, 488: 1247, 490: 1247, 1247, 1247, 1247, 495: 1247, 497: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 533: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 571: 1247, 642: 3684, 645: 1247, 1247}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3890}, + {1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 466: 1238, 1238, 1238, 1238, 1238, 472: 1238, 1238, 3269, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 485: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 494: 1238, 1238, 1238, 1238, 501: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 537: 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 575: 1238}, + {1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 466: 1239, 1239, 1239, 1239, 1239, 472: 1239, 1239, 3269, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 485: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 494: 1239, 1239, 1239, 1239, 501: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 537: 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 575: 1239}, + {468: 3904}, + {468: 3903}, + {1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 466: 1219, 1219, 1219, 1219, 1219, 472: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 485: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 494: 1219, 1219, 1219, 1219, 501: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 537: 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 575: 1219}, // 1430 - {57: 3891}, - {1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 463: 1083, 1083, 1083, 1083, 468: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 479: 1083, 1083, 482: 1083, 1083, 1083, 1083, 1083, 488: 1083, 490: 1083, 1083, 1083, 1083, 495: 1083, 497: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 533: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 571: 1083}, - {1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 463: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 488: 1285, 490: 1285, 1285, 1285, 1285, 495: 1285, 497: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 533: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 566: 1285, 571: 1285, 574: 1285, 576: 1285, 632: 1285, 1285, 635: 1285, 1285}, - {1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 463: 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 488: 1282, 490: 1282, 1282, 1282, 1282, 495: 1282, 497: 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 533: 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 566: 1282, 571: 1282, 574: 1282, 576: 1282, 632: 1282, 1282, 635: 1282, 1282}, - {1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 463: 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 488: 1281, 490: 1281, 1281, 1281, 1281, 495: 1281, 497: 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 533: 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 566: 1281, 571: 1281, 574: 1281, 576: 1281, 632: 1281, 1281, 635: 1281, 1281}, + {1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 466: 1220, 1220, 1220, 1220, 1220, 472: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 485: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 494: 1220, 1220, 1220, 1220, 501: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 537: 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 575: 1220}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3906, 2691, 2692, 2690}, + {1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 3907, 1251, 1251, 1251, 1251, 1251, 472: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 485: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 494: 1251, 1251, 1251, 1251, 501: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 537: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 575: 1251, 643: 3702, 646: 1251, 1251}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 3908}, + {47: 3909}, // 1435 - {1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 463: 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 488: 1279, 490: 1279, 1279, 1279, 1279, 495: 1279, 497: 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 533: 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 566: 1279, 571: 1279, 574: 1279, 576: 1279, 632: 1279, 1279, 635: 1279, 1279}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3898, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3897}, - {57: 3902, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3899}, - {57: 3900, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 466: 1087, 1087, 1087, 1087, 1087, 472: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 485: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 494: 1087, 1087, 1087, 1087, 501: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 537: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 575: 1087}, + {1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 466: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 494: 1289, 1289, 1289, 1289, 501: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 537: 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 565: 1289, 574: 1289, 1289, 1289, 586: 1289, 616: 1289, 635: 1289, 1289}, + {1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 466: 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 494: 1286, 1286, 1286, 1286, 501: 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 537: 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 565: 1286, 574: 1286, 1286, 1286, 586: 1286, 616: 1286, 635: 1286, 1286}, + {1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 466: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 494: 1285, 1285, 1285, 1285, 501: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 537: 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 565: 1285, 574: 1285, 1285, 1285, 586: 1285, 616: 1285, 635: 1285, 1285}, + {1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 466: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 494: 1283, 1283, 1283, 1283, 501: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 537: 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 565: 1283, 574: 1283, 1283, 1283, 586: 1283, 616: 1283, 635: 1283, 1283}, // 1440 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3901}, - {1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 463: 1091, 1091, 1091, 1091, 468: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 479: 1091, 1091, 482: 1091, 1091, 1091, 1091, 1091, 488: 1091, 490: 1091, 1091, 1091, 1091, 495: 1091, 497: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 533: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 571: 1091}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3903}, - {1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 463: 1092, 1092, 1092, 1092, 468: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 479: 1092, 1092, 482: 1092, 1092, 1092, 1092, 1092, 488: 1092, 490: 1092, 1092, 1092, 1092, 495: 1092, 497: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 533: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 571: 1092}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3906, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3905}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3916, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3915}, + {47: 3920, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3917}, + {47: 3918, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3919}, // 1445 - {7: 3916, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3907}, - {7: 3908, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3910, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3909}, - {57: 3914, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 466: 1095, 1095, 1095, 1095, 1095, 472: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 485: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 494: 1095, 1095, 1095, 1095, 501: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 537: 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 575: 1095}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3921}, + {1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 466: 1096, 1096, 1096, 1096, 1096, 472: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 485: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 494: 1096, 1096, 1096, 1096, 501: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 537: 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 575: 1096}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3924, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3923}, + {7: 3934, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1450 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3911}, - {57: 3912, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3913}, - {1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 463: 1087, 1087, 1087, 1087, 468: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 479: 1087, 1087, 482: 1087, 1087, 1087, 1087, 1087, 488: 1087, 490: 1087, 1087, 1087, 1087, 495: 1087, 497: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 533: 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 571: 1087}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3915}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3925}, + {7: 3926, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3928, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3927}, + {47: 3932, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3929}, // 1455 - {1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 463: 1089, 1089, 1089, 1089, 468: 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 479: 1089, 1089, 482: 1089, 1089, 1089, 1089, 1089, 488: 1089, 490: 1089, 1089, 1089, 1089, 495: 1089, 497: 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 533: 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 571: 1089}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 641: 3918, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3917}, - {57: 3922, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3919}, - {57: 3920, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {47: 3930, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3931}, + {1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 466: 1091, 1091, 1091, 1091, 1091, 472: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 485: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 494: 1091, 1091, 1091, 1091, 501: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 537: 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 575: 1091}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3933}, + {1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 466: 1093, 1093, 1093, 1093, 1093, 472: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 485: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 494: 1093, 1093, 1093, 1093, 501: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 537: 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 575: 1093}, // 1460 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3921}, - {1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 463: 1088, 1088, 1088, 1088, 468: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 479: 1088, 1088, 482: 1088, 1088, 1088, 1088, 1088, 488: 1088, 490: 1088, 1088, 1088, 1088, 495: 1088, 497: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 533: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 571: 1088}, - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3923}, - {1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 463: 1090, 1090, 1090, 1090, 468: 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 479: 1090, 1090, 482: 1090, 1090, 1090, 1090, 1090, 488: 1090, 490: 1090, 1090, 1090, 1090, 495: 1090, 497: 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 533: 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 571: 1090}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 796: 3925}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 642: 3936, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3935}, + {47: 3940, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3937}, + {47: 3938, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3939}, // 1465 - {7: 3926}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3927}, - {7: 3928, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3929}, - {57: 3930, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 466: 1092, 1092, 1092, 1092, 1092, 472: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 485: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 494: 1092, 1092, 1092, 1092, 501: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 537: 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 575: 1092}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3941}, + {1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 466: 1094, 1094, 1094, 1094, 1094, 472: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 485: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 494: 1094, 1094, 1094, 1094, 501: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 537: 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 575: 1094}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 795: 3943}, + {7: 3944}, // 1470 - {1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 463: 1137, 1137, 1137, 1137, 468: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 479: 1137, 1137, 482: 1137, 1137, 1137, 1137, 1137, 488: 1137, 490: 1137, 1137, 1137, 1137, 495: 1137, 497: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 533: 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 1137, 571: 1137}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 796: 3932}, - {7: 3933}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3934}, - {7: 3935, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3945}, + {7: 3946, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3947}, + {47: 3948, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 466: 1141, 1141, 1141, 1141, 1141, 472: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 485: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 494: 1141, 1141, 1141, 1141, 501: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 537: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 575: 1141}, // 1475 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3936}, - {57: 3937, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 463: 1138, 1138, 1138, 1138, 468: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 479: 1138, 1138, 482: 1138, 1138, 1138, 1138, 1138, 488: 1138, 490: 1138, 1138, 1138, 1138, 495: 1138, 497: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 533: 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 571: 1138}, - {171: 3941, 3940, 189: 3942, 214: 3943, 1200: 3939}, - {7: 3944}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 795: 3950}, + {7: 3951}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3952}, + {7: 3953, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3954}, // 1480 - {7: 1127}, - {7: 1126}, - {7: 1125}, - {7: 1124}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3945}, + {47: 3955, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 466: 1142, 1142, 1142, 1142, 1142, 472: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 485: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 494: 1142, 1142, 1142, 1142, 501: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 537: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 575: 1142}, + {171: 3959, 3958, 190: 3960, 214: 3961, 1205: 3957}, + {7: 3962}, + {7: 1131}, // 1485 - {57: 3946, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 463: 1144, 1144, 1144, 1144, 468: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 479: 1144, 1144, 482: 1144, 1144, 1144, 1144, 1144, 488: 1144, 490: 1144, 1144, 1144, 1144, 495: 1144, 497: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 533: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 571: 1144}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3948}, - {7: 3949}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 3951}, + {7: 1130}, + {7: 1129}, + {7: 1128}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3963}, + {47: 3964, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1490 - {1931, 1931, 4: 1931, 1931, 1931, 1931, 13: 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 81: 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 106: 1931, 126: 1931, 1931, 1931, 1931, 467: 1931, 469: 1931, 1931, 483: 1931, 488: 1931, 1931, 491: 1931, 1931, 637: 1931, 1931, 647: 1931}, - {57: 3957}, - {29, 29, 4: 29, 29, 29, 13: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 81: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 467: 29, 469: 29, 29, 488: 29, 29, 637: 29, 29, 647: 29}, - {496: 2650, 725: 3950, 751: 3956}, - {496: 2650, 725: 3955}, + {1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 466: 1148, 1148, 1148, 1148, 1148, 472: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 485: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 494: 1148, 1148, 1148, 1148, 501: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 537: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 575: 1148}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3966}, + {7: 3967}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 3969}, + {1938, 1938, 4: 1938, 1938, 1938, 1938, 13: 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 70: 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 106: 1938, 126: 1938, 1938, 1938, 1938, 471: 1938, 1938, 474: 1938, 486: 1938, 491: 1938, 1938, 495: 1938, 498: 1938, 638: 1938, 640: 1938, 648: 1938}, // 1495 - {27, 27, 4: 27, 27, 27, 13: 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 81: 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 467: 27, 469: 27, 27, 488: 27, 27, 637: 27, 27, 647: 27}, - {28, 28, 4: 28, 28, 28, 13: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 81: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 467: 28, 469: 28, 28, 488: 28, 28, 637: 28, 28, 647: 28}, - {1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 463: 1115, 1115, 1115, 1115, 468: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 479: 1115, 1115, 482: 1115, 1115, 1115, 1115, 1115, 488: 1115, 490: 1115, 1115, 1115, 1115, 495: 1115, 497: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 533: 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 571: 1115}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3959}, - {57: 3960}, + {47: 3975}, + {29, 29, 4: 29, 29, 29, 13: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 47: 29, 70: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 471: 29, 29, 474: 29, 495: 29, 498: 29, 638: 29, 640: 29, 648: 29}, + {500: 2665, 724: 3968, 755: 3974}, + {500: 2665, 724: 3973}, + {27, 27, 4: 27, 27, 27, 13: 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 47: 27, 70: 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 471: 27, 27, 474: 27, 495: 27, 498: 27, 638: 27, 640: 27, 648: 27}, // 1500 - {1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 463: 1116, 1116, 1116, 1116, 468: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 479: 1116, 1116, 482: 1116, 1116, 1116, 1116, 1116, 488: 1116, 490: 1116, 1116, 1116, 1116, 495: 1116, 497: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 533: 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 571: 1116}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3962}, - {57: 3963, 468: 3964, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 463: 1132, 1132, 1132, 1132, 468: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 479: 1132, 1132, 482: 1132, 1132, 1132, 1132, 1132, 488: 1132, 490: 1132, 1132, 1132, 1132, 495: 1132, 497: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 533: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 571: 1132}, - {489: 3710, 532: 3966, 637: 3709, 889: 3965}, + {28, 28, 4: 28, 28, 28, 13: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 47: 28, 70: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 471: 28, 28, 474: 28, 495: 28, 498: 28, 638: 28, 640: 28, 648: 28}, + {1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 466: 1119, 1119, 1119, 1119, 1119, 472: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 485: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 494: 1119, 1119, 1119, 1119, 501: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 537: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 575: 1119}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3977}, + {47: 3978}, + {1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 466: 1120, 1120, 1120, 1120, 1120, 472: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 485: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 494: 1120, 1120, 1120, 1120, 501: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 537: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 575: 1120}, // 1505 - {462: 3725, 750: 3969}, - {462: 3725, 750: 3967}, - {57: 3968}, - {1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 463: 1130, 1130, 1130, 1130, 468: 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 479: 1130, 1130, 482: 1130, 1130, 1130, 1130, 1130, 488: 1130, 490: 1130, 1130, 1130, 1130, 495: 1130, 497: 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 533: 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 571: 1130}, - {57: 3970}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3980}, + {47: 3981, 470: 3982, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 466: 1136, 1136, 1136, 1136, 1136, 472: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 485: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 494: 1136, 1136, 1136, 1136, 501: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 537: 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 575: 1136}, + {498: 3728, 536: 3984, 638: 3727, 889: 3983}, + {465: 3743, 754: 3987}, // 1510 - {1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 463: 1131, 1131, 1131, 1131, 468: 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 479: 1131, 1131, 482: 1131, 1131, 1131, 1131, 1131, 488: 1131, 490: 1131, 1131, 1131, 1131, 495: 1131, 497: 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 533: 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 571: 1131}, - {1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 463: 1154, 1154, 1154, 1154, 468: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 479: 1154, 1154, 482: 1154, 1154, 1154, 1154, 1154, 488: 1154, 490: 1154, 1154, 1154, 1154, 495: 1154, 497: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 533: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 571: 1154}, - {1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 463: 1155, 1155, 1155, 1155, 468: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 479: 1155, 1155, 482: 1155, 1155, 1155, 1155, 1155, 488: 1155, 490: 1155, 1155, 1155, 1155, 495: 1155, 497: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 533: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 571: 1155}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3974}, - {57: 3975}, + {465: 3743, 754: 3985}, + {47: 3986}, + {1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 466: 1134, 1134, 1134, 1134, 1134, 472: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 485: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 494: 1134, 1134, 1134, 1134, 501: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 537: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 575: 1134}, + {47: 3988}, + {1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 466: 1135, 1135, 1135, 1135, 1135, 472: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 485: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 494: 1135, 1135, 1135, 1135, 501: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 537: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 575: 1135}, // 1515 - {1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 463: 1151, 1151, 1151, 1151, 468: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 479: 1151, 1151, 482: 1151, 1151, 1151, 1151, 1151, 488: 1151, 490: 1151, 1151, 1151, 1151, 495: 1151, 497: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 533: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 571: 1151}, - {1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 463: 1156, 1156, 1156, 1156, 468: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 479: 1156, 1156, 482: 1156, 1156, 1156, 1156, 1156, 488: 1156, 490: 1156, 1156, 1156, 1156, 495: 1156, 497: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 533: 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 571: 1156}, - {2: 1210, 1210, 1210, 1210, 1210, 8: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 58: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 462: 1210, 464: 1210, 1210, 1210, 1210, 472: 1210, 1210, 1210, 1210, 1210, 481: 1210, 487: 1210, 489: 1210, 494: 1210, 496: 1210, 532: 1210, 555: 1210, 557: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 567: 1210, 1210, 1210, 1210, 572: 1210, 1210, 575: 1210, 577: 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 639: 1210, 641: 3447, 735: 3445, 3446, 774: 3448, 777: 3449, 804: 3978, 806: 3450}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3979}, - {57: 3980, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 466: 1158, 1158, 1158, 1158, 1158, 472: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 485: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 494: 1158, 1158, 1158, 1158, 501: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 537: 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 575: 1158}, + {1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 466: 1159, 1159, 1159, 1159, 1159, 472: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 485: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 494: 1159, 1159, 1159, 1159, 501: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 537: 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 575: 1159}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 3992}, + {47: 3993}, + {1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 466: 1155, 1155, 1155, 1155, 1155, 472: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 485: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 494: 1155, 1155, 1155, 1155, 501: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 537: 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 575: 1155}, // 1520 - {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 463: 931, 931, 931, 931, 468: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 479: 931, 931, 482: 931, 931, 931, 931, 931, 488: 931, 490: 931, 931, 931, 931, 495: 931, 497: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 533: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 571: 931, 730: 3265, 737: 3455, 755: 3981}, - {1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 463: 1113, 1113, 1113, 1113, 468: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 479: 1113, 1113, 482: 1113, 1113, 1113, 1113, 1113, 488: 1113, 490: 1113, 1113, 1113, 1113, 495: 1113, 497: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 533: 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 571: 1113}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 3983}, - {57: 3984}, - {1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 463: 1084, 1084, 1084, 1084, 468: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 479: 1084, 1084, 482: 1084, 1084, 1084, 1084, 1084, 488: 1084, 490: 1084, 1084, 1084, 1084, 495: 1084, 497: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 533: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 571: 1084}, + {1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 466: 1160, 1160, 1160, 1160, 1160, 472: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 485: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 494: 1160, 1160, 1160, 1160, 501: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 537: 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 575: 1160}, + {2: 1214, 1214, 1214, 1214, 1214, 8: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 48: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 465: 1214, 467: 1214, 1214, 1214, 471: 1214, 475: 1214, 1214, 1214, 1214, 1214, 484: 1214, 493: 1214, 498: 1214, 1214, 1214, 536: 1214, 558: 1214, 1214, 1214, 1214, 563: 1214, 1214, 566: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 577: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 587: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 617: 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 1214, 639: 1214, 642: 3465, 736: 3463, 3464, 773: 3466, 776: 3467, 803: 3996, 805: 3468}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3997}, + {47: 3998, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 466: 935, 935, 935, 935, 935, 472: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 485: 935, 935, 935, 935, 935, 935, 935, 935, 494: 935, 935, 935, 935, 501: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 537: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 575: 935, 731: 3281, 738: 3473, 756: 3999}, // 1525 - {147: 2244, 168: 2244, 184: 2244, 481: 2244, 510: 2244, 533: 2244, 544: 2244, 553: 2244, 2244, 560: 2244, 2244, 573: 2244}, - {147: 2243, 168: 2243, 184: 2243, 481: 2243, 510: 2243, 533: 2243, 544: 2243, 553: 2243, 2243, 560: 2243, 2243, 573: 2243}, - {2: 1858, 1858, 1858, 1858, 1858, 8: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 58: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 462: 1858, 464: 1858, 1858, 467: 1858, 472: 1858, 1858, 1858, 1858, 1858, 481: 1858, 487: 1858, 489: 1858, 494: 1858, 496: 1858, 532: 1858, 555: 1858, 557: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 567: 1858, 1858, 1858, 1858, 572: 1858, 1858, 575: 1858, 577: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858}, - {510: 4012, 533: 4011, 544: 4010, 553: 3996, 3997, 1093: 4013}, - {462: 1854}, + {1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 466: 1117, 1117, 1117, 1117, 1117, 472: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 485: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 494: 1117, 1117, 1117, 1117, 501: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 537: 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 575: 1117}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 4001}, + {47: 4002}, + {1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 466: 1088, 1088, 1088, 1088, 1088, 472: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 485: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 494: 1088, 1088, 1088, 1088, 501: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 537: 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 575: 1088}, + {147: 2260, 168: 2260, 185: 2260, 484: 2260, 513: 2260, 535: 2260, 547: 2260, 556: 2260, 2260, 563: 2260, 2260, 578: 2260}, // 1530 - {2: 1852, 1852, 1852, 1852, 1852, 8: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 58: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 462: 1852, 464: 1852, 1852, 467: 1852, 472: 1852, 1852, 1852, 1852, 1852, 481: 1852, 487: 1852, 489: 1852, 494: 1852, 496: 1852, 532: 1852, 555: 1852, 557: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 567: 1852, 1852, 1852, 1852, 572: 1852, 1852, 575: 1852, 577: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852}, - {2: 1850, 1850, 1850, 1850, 1850, 8: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 58: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 462: 1850, 464: 1850, 1850, 467: 1850, 472: 1850, 1850, 1850, 1850, 1850, 481: 1850, 487: 1850, 489: 1850, 494: 1850, 496: 1850, 532: 1850, 555: 1850, 557: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 567: 1850, 1850, 1850, 1850, 572: 1850, 1850, 575: 1850, 577: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850}, - {462: 4006, 699: 4007}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4003}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3999, 3155, 3238, 3154, 3151}, + {147: 2259, 168: 2259, 185: 2259, 484: 2259, 513: 2259, 535: 2259, 547: 2259, 556: 2259, 2259, 563: 2259, 2259, 578: 2259}, + {2: 1865, 1865, 1865, 1865, 1865, 8: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 48: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 465: 1865, 467: 1865, 1865, 471: 1865, 475: 1865, 1865, 1865, 1865, 1865, 484: 1865, 493: 1865, 498: 1865, 1865, 1865, 536: 1865, 558: 1865, 1865, 1865, 1865, 563: 1865, 1865, 566: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 577: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 587: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 617: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865}, + {513: 4030, 535: 4029, 547: 4028, 556: 4014, 4015, 1096: 4031}, + {465: 1861}, + {2: 1859, 1859, 1859, 1859, 1859, 8: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 48: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 465: 1859, 467: 1859, 1859, 471: 1859, 475: 1859, 1859, 1859, 1859, 1859, 484: 1859, 493: 1859, 498: 1859, 1859, 1859, 536: 1859, 558: 1859, 1859, 1859, 1859, 563: 1859, 1859, 566: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 577: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 587: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 617: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859}, // 1535 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3998, 3155, 3238, 3154, 3151}, - {2: 1839, 1839, 1839, 1839, 1839, 8: 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 58: 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 462: 1839, 464: 1839, 1839, 467: 1839, 472: 1839, 1839, 1839, 1839, 1839, 481: 1839, 487: 1839, 489: 1839, 494: 1839, 496: 1839, 532: 1839, 555: 1839, 557: 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 567: 1839, 1839, 1839, 1839, 572: 1839, 1839, 575: 1839, 577: 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839, 1839}, - {2: 1838, 1838, 1838, 1838, 1838, 8: 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 58: 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 462: 1838, 464: 1838, 1838, 467: 1838, 472: 1838, 1838, 1838, 1838, 1838, 481: 1838, 487: 1838, 489: 1838, 494: 1838, 496: 1838, 532: 1838, 555: 1838, 557: 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 567: 1838, 1838, 1838, 1838, 572: 1838, 1838, 575: 1838, 577: 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838, 1838}, - {1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 463: 1841, 1841, 468: 1841, 1841, 3253, 1841, 1841, 1841, 477: 1841, 479: 1841, 1841, 482: 1841, 1841, 1841, 1841, 1841, 488: 1841, 490: 1841, 1841, 1841, 1841, 495: 1841, 497: 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 511: 1841, 513: 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 534: 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 1841, 571: 3254}, - {1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 4001, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 463: 1837, 1837, 468: 1837, 1837, 3253, 1837, 1837, 1837, 477: 1837, 479: 1837, 1837, 482: 1837, 1837, 1837, 1837, 1837, 488: 1837, 490: 1837, 1837, 1837, 1837, 495: 1837, 497: 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 511: 1837, 513: 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 534: 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 571: 3254, 1218: 4000}, + {2: 1857, 1857, 1857, 1857, 1857, 8: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 48: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 465: 1857, 467: 1857, 1857, 471: 1857, 475: 1857, 1857, 1857, 1857, 1857, 484: 1857, 493: 1857, 498: 1857, 1857, 1857, 536: 1857, 558: 1857, 1857, 1857, 1857, 563: 1857, 1857, 566: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 577: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 587: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 617: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857}, + {465: 4024, 700: 4025}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4021}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 4017, 3173, 3254, 3172, 3169}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 4016, 3173, 3254, 3172, 3169}, // 1540 - {1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 463: 1842, 1842, 468: 1842, 1842, 471: 1842, 1842, 1842, 477: 1842, 479: 1842, 1842, 482: 1842, 1842, 1842, 1842, 1842, 488: 1842, 490: 1842, 1842, 1842, 1842, 495: 1842, 497: 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 511: 1842, 513: 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 534: 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842}, - {464: 4002}, - {1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 463: 1836, 1836, 468: 1836, 1836, 471: 1836, 1836, 1836, 477: 1836, 479: 1836, 1836, 482: 1836, 1836, 1836, 1836, 1836, 488: 1836, 490: 1836, 1836, 1836, 1836, 495: 1836, 497: 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 511: 1836, 513: 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 534: 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836, 1836}, - {474: 3588, 3587, 3593, 495: 4004, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 4005}, + {2: 1846, 1846, 1846, 1846, 1846, 8: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 48: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 465: 1846, 467: 1846, 1846, 471: 1846, 475: 1846, 1846, 1846, 1846, 1846, 484: 1846, 493: 1846, 498: 1846, 1846, 1846, 536: 1846, 558: 1846, 1846, 1846, 1846, 563: 1846, 1846, 566: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 577: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 587: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 617: 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846, 1846}, + {2: 1845, 1845, 1845, 1845, 1845, 8: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 48: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 465: 1845, 467: 1845, 1845, 471: 1845, 475: 1845, 1845, 1845, 1845, 1845, 484: 1845, 493: 1845, 498: 1845, 1845, 1845, 536: 1845, 558: 1845, 1845, 1845, 1845, 563: 1845, 1845, 566: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 577: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 587: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 617: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845}, + {1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 466: 1848, 468: 1848, 470: 1848, 472: 1848, 1848, 3269, 1848, 1848, 480: 1848, 1848, 1848, 485: 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 494: 1848, 1848, 1848, 1848, 501: 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 514: 1848, 516: 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 537: 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 1848, 575: 3270}, + {1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 4019, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 466: 1844, 468: 1844, 470: 1844, 472: 1844, 1844, 3269, 1844, 1844, 480: 1844, 1844, 1844, 485: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 494: 1844, 1844, 1844, 1844, 501: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 514: 1844, 516: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 537: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 575: 3270, 1223: 4018}, + {1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 466: 1849, 468: 1849, 470: 1849, 472: 1849, 1849, 475: 1849, 1849, 480: 1849, 1849, 1849, 485: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 494: 1849, 1849, 1849, 1849, 501: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 514: 1849, 516: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 537: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849}, // 1545 - {1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 463: 1843, 1843, 468: 1843, 1843, 471: 1843, 1843, 1843, 477: 1843, 479: 1843, 1843, 482: 1843, 1843, 1843, 1843, 1843, 488: 1843, 490: 1843, 1843, 1843, 1843, 495: 1843, 497: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 511: 1843, 513: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 534: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 2508, 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3778, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 2506, 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 634: 2502, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3777, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 741: 3780, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 3782, 3781, 3779, 766: 4008}, - {1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 463: 1844, 1844, 468: 1844, 1844, 471: 1844, 1844, 1844, 477: 1844, 479: 1844, 1844, 482: 1844, 1844, 1844, 1844, 1844, 488: 1844, 490: 1844, 1844, 1844, 1844, 495: 1844, 497: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 511: 1844, 513: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 534: 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844, 1844}, - {7: 3491, 57: 4009}, - {1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 463: 1845, 1845, 468: 1845, 1845, 471: 1845, 1845, 1845, 477: 1845, 479: 1845, 1845, 482: 1845, 1845, 1845, 1845, 1845, 488: 1845, 490: 1845, 1845, 1845, 1845, 495: 1845, 497: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 511: 1845, 513: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 534: 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845}, + {468: 4020}, + {1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 466: 1843, 468: 1843, 470: 1843, 472: 1843, 1843, 475: 1843, 1843, 480: 1843, 1843, 1843, 485: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 494: 1843, 1843, 1843, 1843, 501: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 514: 1843, 516: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 537: 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843}, + {477: 3606, 3605, 3611, 497: 4022, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 4023}, + {1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 466: 1850, 468: 1850, 470: 1850, 472: 1850, 1850, 475: 1850, 1850, 480: 1850, 1850, 1850, 485: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 494: 1850, 1850, 1850, 1850, 501: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 514: 1850, 516: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 537: 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850}, // 1550 - {2: 1857, 1857, 1857, 1857, 1857, 8: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 58: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 462: 1857, 464: 1857, 1857, 467: 1857, 472: 1857, 1857, 1857, 1857, 1857, 481: 1857, 487: 1857, 489: 1857, 494: 1857, 496: 1857, 532: 1857, 555: 1857, 557: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 567: 1857, 1857, 1857, 1857, 572: 1857, 1857, 575: 1857, 577: 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857}, - {462: 1853}, - {2: 1851, 1851, 1851, 1851, 1851, 8: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 58: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 462: 1851, 464: 1851, 1851, 467: 1851, 472: 1851, 1851, 1851, 1851, 1851, 481: 1851, 487: 1851, 489: 1851, 494: 1851, 496: 1851, 532: 1851, 555: 1851, 557: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 567: 1851, 1851, 1851, 1851, 572: 1851, 1851, 575: 1851, 577: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851}, - {2: 1849, 1849, 1849, 1849, 1849, 8: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 58: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 462: 1849, 464: 1849, 1849, 467: 1849, 472: 1849, 1849, 1849, 1849, 1849, 481: 1849, 487: 1849, 489: 1849, 494: 1849, 496: 1849, 532: 1849, 555: 1849, 557: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 567: 1849, 1849, 1849, 1849, 572: 1849, 1849, 575: 1849, 577: 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849, 1849}, - {168: 4037, 481: 4038, 560: 4036, 4035}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 2522, 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3796, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 2520, 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 637: 2516, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3795, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 742: 3798, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 3800, 3799, 3797, 766: 4026}, + {1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 466: 1851, 468: 1851, 470: 1851, 472: 1851, 1851, 475: 1851, 1851, 480: 1851, 1851, 1851, 485: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 494: 1851, 1851, 1851, 1851, 501: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 514: 1851, 516: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 537: 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851, 1851}, + {7: 3509, 47: 4027}, + {1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 466: 1852, 468: 1852, 470: 1852, 472: 1852, 1852, 475: 1852, 1852, 480: 1852, 1852, 1852, 485: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 494: 1852, 1852, 1852, 1852, 501: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 514: 1852, 516: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 537: 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852}, + {2: 1864, 1864, 1864, 1864, 1864, 8: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 48: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 465: 1864, 467: 1864, 1864, 471: 1864, 475: 1864, 1864, 1864, 1864, 1864, 484: 1864, 493: 1864, 498: 1864, 1864, 1864, 536: 1864, 558: 1864, 1864, 1864, 1864, 563: 1864, 1864, 566: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 577: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 587: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 617: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864}, // 1555 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 4029, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 4030, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 4028, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 641: 4031, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 4026, 1153: 4027}, - {2: 1866, 1866, 1866, 1866, 1866, 8: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 58: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 462: 1866, 464: 1866, 1866, 467: 1866, 472: 1866, 1866, 1866, 1866, 1866, 481: 1866, 487: 1866, 489: 1866, 494: 1866, 496: 1866, 532: 1866, 555: 1866, 557: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 567: 1866, 1866, 1866, 1866, 572: 1866, 1866, 575: 1866, 577: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 641: 1866}, - {2: 1865, 1865, 1865, 1865, 1865, 8: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 58: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 462: 1865, 464: 1865, 1865, 467: 1865, 472: 1865, 1865, 1865, 1865, 1865, 481: 1865, 487: 1865, 489: 1865, 494: 1865, 496: 1865, 532: 1865, 555: 1865, 557: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 567: 1865, 1865, 1865, 1865, 572: 1865, 1865, 575: 1865, 577: 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 641: 1865}, - {2: 1864, 1864, 1864, 1864, 1864, 8: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 58: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 462: 1864, 464: 1864, 1864, 467: 1864, 472: 1864, 1864, 1864, 1864, 1864, 481: 1864, 487: 1864, 489: 1864, 494: 1864, 496: 1864, 532: 1864, 555: 1864, 557: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 567: 1864, 1864, 1864, 1864, 572: 1864, 1864, 575: 1864, 577: 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 641: 1864}, - {2: 1863, 1863, 1863, 1863, 1863, 8: 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 58: 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 462: 1863, 464: 1863, 1863, 467: 1863, 472: 1863, 1863, 1863, 1863, 1863, 481: 1863, 487: 1863, 489: 1863, 494: 1863, 496: 1863, 532: 1863, 555: 1863, 557: 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 567: 1863, 1863, 1863, 1863, 572: 1863, 1863, 575: 1863, 577: 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 641: 1863}, + {465: 1860}, + {2: 1858, 1858, 1858, 1858, 1858, 8: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 48: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 465: 1858, 467: 1858, 1858, 471: 1858, 475: 1858, 1858, 1858, 1858, 1858, 484: 1858, 493: 1858, 498: 1858, 1858, 1858, 536: 1858, 558: 1858, 1858, 1858, 1858, 563: 1858, 1858, 566: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 577: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 587: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 617: 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858}, + {2: 1856, 1856, 1856, 1856, 1856, 8: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 48: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 465: 1856, 467: 1856, 1856, 471: 1856, 475: 1856, 1856, 1856, 1856, 1856, 484: 1856, 493: 1856, 498: 1856, 1856, 1856, 536: 1856, 558: 1856, 1856, 1856, 1856, 563: 1856, 1856, 566: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 577: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 587: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 617: 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856, 1856}, + {168: 4055, 484: 4056, 563: 4054, 4053}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 4047, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 4048, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 4046, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 642: 4049, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 4044, 1157: 4045}, // 1560 - {2: 1862, 1862, 1862, 1862, 1862, 8: 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 58: 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 462: 1862, 464: 1862, 1862, 467: 1862, 472: 1862, 1862, 1862, 1862, 1862, 481: 1862, 487: 1862, 489: 1862, 494: 1862, 496: 1862, 532: 1862, 555: 1862, 557: 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 567: 1862, 1862, 1862, 1862, 572: 1862, 1862, 575: 1862, 577: 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 641: 1862}, - {2: 1861, 1861, 1861, 1861, 1861, 8: 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 58: 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 462: 1861, 464: 1861, 1861, 467: 1861, 472: 1861, 1861, 1861, 1861, 1861, 481: 1861, 487: 1861, 489: 1861, 494: 1861, 496: 1861, 532: 1861, 555: 1861, 557: 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 567: 1861, 1861, 1861, 1861, 572: 1861, 1861, 575: 1861, 577: 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 641: 1861}, - {2: 1860, 1860, 1860, 1860, 1860, 8: 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 58: 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 462: 1860, 464: 1860, 1860, 467: 1860, 472: 1860, 1860, 1860, 1860, 1860, 481: 1860, 487: 1860, 489: 1860, 494: 1860, 496: 1860, 532: 1860, 555: 1860, 557: 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 567: 1860, 1860, 1860, 1860, 572: 1860, 1860, 575: 1860, 577: 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 1860, 641: 1860}, - {2: 1859, 1859, 1859, 1859, 1859, 8: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 58: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 462: 1859, 464: 1859, 1859, 467: 1859, 472: 1859, 1859, 1859, 1859, 1859, 481: 1859, 487: 1859, 489: 1859, 494: 1859, 496: 1859, 532: 1859, 555: 1859, 557: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 567: 1859, 1859, 1859, 1859, 572: 1859, 1859, 575: 1859, 577: 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 1859, 641: 1859}, - {168: 1856, 465: 3986, 3985, 481: 1856, 560: 1856, 1856, 800: 4025}, + {2: 1873, 1873, 1873, 1873, 1873, 8: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 48: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 465: 1873, 467: 1873, 1873, 471: 1873, 475: 1873, 1873, 1873, 1873, 1873, 484: 1873, 493: 1873, 498: 1873, 1873, 1873, 536: 1873, 558: 1873, 1873, 1873, 1873, 563: 1873, 1873, 566: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 577: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 587: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 617: 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 642: 1873}, + {2: 1872, 1872, 1872, 1872, 1872, 8: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 48: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 465: 1872, 467: 1872, 1872, 471: 1872, 475: 1872, 1872, 1872, 1872, 1872, 484: 1872, 493: 1872, 498: 1872, 1872, 1872, 536: 1872, 558: 1872, 1872, 1872, 1872, 563: 1872, 1872, 566: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 577: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 587: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 617: 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 642: 1872}, + {2: 1871, 1871, 1871, 1871, 1871, 8: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 48: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 465: 1871, 467: 1871, 1871, 471: 1871, 475: 1871, 1871, 1871, 1871, 1871, 484: 1871, 493: 1871, 498: 1871, 1871, 1871, 536: 1871, 558: 1871, 1871, 1871, 1871, 563: 1871, 1871, 566: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 577: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 587: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 617: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 642: 1871}, + {2: 1870, 1870, 1870, 1870, 1870, 8: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 48: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 465: 1870, 467: 1870, 1870, 471: 1870, 475: 1870, 1870, 1870, 1870, 1870, 484: 1870, 493: 1870, 498: 1870, 1870, 1870, 536: 1870, 558: 1870, 1870, 1870, 1870, 563: 1870, 1870, 566: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 577: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 587: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 617: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 642: 1870}, + {2: 1869, 1869, 1869, 1869, 1869, 8: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 48: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 465: 1869, 467: 1869, 1869, 471: 1869, 475: 1869, 1869, 1869, 1869, 1869, 484: 1869, 493: 1869, 498: 1869, 1869, 1869, 536: 1869, 558: 1869, 1869, 1869, 1869, 563: 1869, 1869, 566: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 577: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 587: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 617: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 642: 1869}, // 1565 - {168: 1855, 481: 1855, 560: 1855, 1855}, - {1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 463: 1870, 1870, 468: 1870, 1870, 471: 1870, 1870, 1870, 477: 1870, 479: 1870, 1870, 482: 1870, 1870, 1870, 1870, 1870, 488: 1870, 490: 1870, 1870, 1870, 1870, 495: 1870, 497: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 511: 1870, 513: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 534: 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870}, - {462: 2509, 699: 4034}, - {721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 463: 721, 721, 721, 721, 468: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 479: 721, 721, 482: 721, 721, 721, 721, 721, 488: 721, 490: 721, 721, 721, 721, 495: 721, 497: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 533: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 571: 721, 650: 4032}, - {1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1848, 1672, 1672, 1672, 1672, 468: 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 479: 1672, 1672, 482: 1672, 1672, 1672, 1672, 1672, 488: 1672, 490: 1672, 1672, 1672, 1672, 495: 1672, 497: 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 533: 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 571: 1672, 642: 1672, 645: 1672, 1672}, + {2: 1868, 1868, 1868, 1868, 1868, 8: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 48: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 465: 1868, 467: 1868, 1868, 471: 1868, 475: 1868, 1868, 1868, 1868, 1868, 484: 1868, 493: 1868, 498: 1868, 1868, 1868, 536: 1868, 558: 1868, 1868, 1868, 1868, 563: 1868, 1868, 566: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 577: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 587: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 617: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 642: 1868}, + {2: 1867, 1867, 1867, 1867, 1867, 8: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 48: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 465: 1867, 467: 1867, 1867, 471: 1867, 475: 1867, 1867, 1867, 1867, 1867, 484: 1867, 493: 1867, 498: 1867, 1867, 1867, 536: 1867, 558: 1867, 1867, 1867, 1867, 563: 1867, 1867, 566: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 577: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 587: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 617: 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 642: 1867}, + {2: 1866, 1866, 1866, 1866, 1866, 8: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 48: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 465: 1866, 467: 1866, 1866, 471: 1866, 475: 1866, 1866, 1866, 1866, 1866, 484: 1866, 493: 1866, 498: 1866, 1866, 1866, 536: 1866, 558: 1866, 1866, 1866, 1866, 563: 1866, 1866, 566: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 577: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 587: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 617: 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 642: 1866}, + {168: 1863, 467: 4004, 469: 4003, 484: 1863, 563: 1863, 1863, 799: 4043}, + {168: 1862, 484: 1862, 563: 1862, 1862}, // 1570 - {1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1847, 1671, 1671, 1671, 1671, 468: 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 479: 1671, 1671, 482: 1671, 1671, 1671, 1671, 1671, 488: 1671, 490: 1671, 1671, 1671, 1671, 495: 1671, 497: 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 533: 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 571: 1671, 642: 1671, 645: 1671, 1671}, - {462: 1846}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 4033}, - {1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 463: 1868, 1868, 468: 1868, 1868, 471: 1868, 1868, 1868, 477: 1868, 479: 1868, 1868, 482: 1868, 1868, 1868, 1868, 1868, 488: 1868, 490: 1868, 1868, 1868, 1868, 495: 1868, 497: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 511: 1868, 513: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 534: 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868}, - {1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 463: 1869, 1869, 468: 1869, 1869, 471: 1869, 1869, 1869, 477: 1869, 479: 1869, 1869, 482: 1869, 1869, 1869, 1869, 1869, 488: 1869, 490: 1869, 1869, 1869, 1869, 495: 1869, 497: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 511: 1869, 513: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 534: 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869}, + {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 466: 1877, 468: 1877, 470: 1877, 472: 1877, 1877, 475: 1877, 1877, 480: 1877, 1877, 1877, 485: 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 494: 1877, 1877, 1877, 1877, 501: 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 514: 1877, 516: 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 537: 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877}, + {465: 2523, 700: 4052}, + {725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 466: 725, 725, 725, 725, 725, 472: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 485: 725, 725, 725, 725, 725, 725, 725, 725, 494: 725, 725, 725, 725, 501: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 537: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 575: 725, 651: 4050}, + {1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1855, 1678, 1678, 1678, 1678, 1678, 472: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 485: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 494: 1678, 1678, 1678, 1678, 501: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 537: 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 575: 1678, 643: 1678, 646: 1678, 1678}, + {1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1854, 1677, 1677, 1677, 1677, 1677, 472: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 485: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 494: 1677, 1677, 1677, 1677, 501: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 537: 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 575: 1677, 643: 1677, 646: 1677, 1677}, // 1575 - {1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 463: 1895, 1895, 468: 1895, 1895, 471: 1895, 1895, 1895, 477: 1895, 479: 1895, 1895, 482: 1895, 1895, 1895, 486: 1895, 488: 1895, 490: 1895, 1895, 1895, 1895, 495: 1895, 497: 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 511: 1895, 513: 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 534: 1895, 1895}, - {1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 463: 1894, 1894, 468: 1894, 1894, 471: 1894, 1894, 1894, 477: 1894, 479: 1894, 1894, 482: 1894, 1894, 1894, 486: 1894, 488: 1894, 490: 1894, 1894, 1894, 1894, 495: 1894, 497: 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 511: 1894, 513: 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 534: 1894, 1894}, - {1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 463: 1893, 1893, 468: 1893, 1893, 471: 1893, 1893, 1893, 477: 1893, 479: 1893, 1893, 482: 1893, 1893, 1893, 486: 1893, 488: 1893, 490: 1893, 1893, 1893, 1893, 495: 1893, 497: 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 511: 1893, 513: 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 534: 1893, 1893}, - {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 463: 1871, 1871, 468: 1871, 1871, 471: 1871, 1871, 1871, 477: 1871, 479: 1871, 1871, 482: 1871, 1871, 1871, 1871, 1871, 488: 1871, 490: 1871, 1871, 1871, 1871, 495: 1871, 497: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 511: 1871, 513: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 534: 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 4042}, + {465: 1853}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 4051}, + {1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 466: 1875, 468: 1875, 470: 1875, 472: 1875, 1875, 475: 1875, 1875, 480: 1875, 1875, 1875, 485: 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 494: 1875, 1875, 1875, 1875, 501: 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 514: 1875, 516: 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 537: 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875, 1875}, + {1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 466: 1876, 468: 1876, 470: 1876, 472: 1876, 1876, 475: 1876, 1876, 480: 1876, 1876, 1876, 485: 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 494: 1876, 1876, 1876, 1876, 501: 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 514: 1876, 516: 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 537: 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876, 1876}, + {1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 466: 1902, 468: 1902, 470: 1902, 472: 1902, 1902, 475: 1902, 1902, 480: 1902, 1902, 1902, 485: 1902, 1902, 1902, 1902, 490: 1902, 1902, 1902, 494: 1902, 1902, 1902, 1902, 501: 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 514: 1902, 516: 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 537: 1902, 1902}, // 1580 - {2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 462: 2267, 478: 2267, 485: 2267, 489: 2267, 501: 2267, 518: 2267, 2267, 532: 2267, 637: 2267, 642: 4063, 659: 2267, 2267, 662: 2267, 667: 2267, 2267, 670: 2267, 2267, 2267, 2267, 2267, 2267, 678: 2267, 680: 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 695: 2267, 2267, 2267, 2267}, - {7: 2264, 57: 2264}, - {7: 4043, 57: 4044}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4062}, - {293: 4045}, + {1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 466: 1901, 468: 1901, 470: 1901, 472: 1901, 1901, 475: 1901, 1901, 480: 1901, 1901, 1901, 485: 1901, 1901, 1901, 1901, 490: 1901, 1901, 1901, 494: 1901, 1901, 1901, 1901, 501: 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 514: 1901, 516: 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 537: 1901, 1901}, + {1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 466: 1900, 468: 1900, 470: 1900, 472: 1900, 1900, 475: 1900, 1900, 480: 1900, 1900, 1900, 485: 1900, 1900, 1900, 1900, 490: 1900, 1900, 1900, 494: 1900, 1900, 1900, 1900, 501: 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 514: 1900, 516: 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 537: 1900, 1900}, + {1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 466: 1878, 468: 1878, 470: 1878, 472: 1878, 1878, 475: 1878, 1878, 480: 1878, 1878, 1878, 485: 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 494: 1878, 1878, 1878, 1878, 501: 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 514: 1878, 516: 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 537: 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878, 1878}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 4060}, + {2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 465: 2283, 483: 2283, 489: 2283, 496: 2283, 498: 2283, 521: 2283, 2283, 536: 2283, 638: 2283, 643: 4081, 660: 2283, 2283, 663: 2283, 668: 2283, 2283, 671: 2283, 2283, 2283, 2283, 2283, 2283, 679: 2283, 681: 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 696: 2283, 2283, 2283, 2283}, // 1585 - {462: 4046}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4047}, - {57: 1889, 463: 4050, 474: 3588, 3587, 3593, 512: 3589, 533: 4049, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586, 1198: 4048}, - {57: 4061}, - {220: 4054, 507: 4053}, + {7: 2280, 47: 2280}, + {7: 4061, 47: 4062}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4080}, + {295: 4063}, + {465: 4064}, // 1590 - {143: 4051}, - {242: 4052}, - {57: 1885}, - {337: 4056}, - {203: 4055}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4065}, + {47: 1896, 466: 4068, 477: 3606, 3605, 3611, 515: 3607, 535: 4067, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604, 1203: 4066}, + {47: 4079}, + {220: 4072, 510: 4071}, + {143: 4069}, // 1595 - {57: 1886}, - {203: 4057}, - {57: 1888, 463: 4058}, - {143: 4059}, - {242: 4060}, + {242: 4070}, + {47: 1892}, + {342: 4074}, + {203: 4073}, + {47: 1893}, // 1600 - {57: 1887}, - {1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 463: 1896, 1896, 468: 1896, 1896, 471: 1896, 1896, 1896, 477: 1896, 479: 1896, 1896, 482: 1896, 1896, 1896, 486: 1896, 488: 1896, 490: 1896, 1896, 1896, 1896, 495: 1896, 497: 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 511: 1896, 513: 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 534: 1896, 1896}, - {7: 2263, 57: 2263}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4064, 2676, 2677, 2675}, - {2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 462: 2266, 478: 2266, 485: 2266, 489: 2266, 501: 2266, 518: 2266, 2266, 532: 2266, 637: 2266, 642: 4065, 659: 2266, 2266, 662: 2266, 667: 2266, 2266, 670: 2266, 2266, 2266, 2266, 2266, 2266, 678: 2266, 680: 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 695: 2266, 2266, 2266, 2266}, + {203: 4075}, + {47: 1895, 466: 4076}, + {143: 4077}, + {242: 4078}, + {47: 1894}, // 1605 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4066, 2676, 2677, 2675}, - {2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 462: 2265, 478: 2265, 485: 2265, 489: 2265, 501: 2265, 518: 2265, 2265, 532: 2265, 637: 2265, 659: 2265, 2265, 662: 2265, 667: 2265, 2265, 670: 2265, 2265, 2265, 2265, 2265, 2265, 678: 2265, 680: 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 695: 2265, 2265, 2265, 2265}, - {1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 463: 1897, 1897, 468: 1897, 1897, 471: 1897, 1897, 1897, 477: 1897, 479: 1897, 1897, 482: 1897, 1897, 1897, 486: 1897, 488: 1897, 490: 1897, 1897, 1897, 1897, 495: 1897, 497: 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 511: 1897, 513: 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 534: 1897, 1897, 723: 3245, 3243}, - {1271, 1271, 7: 1271, 57: 1271, 124: 1271, 461: 1271, 463: 1271, 469: 1271, 471: 1271, 479: 1271, 1271, 482: 1271, 1271, 1271, 486: 1271, 491: 1271, 493: 1271, 504: 1271, 1271, 513: 1271, 516: 1271, 1271}, - {1270, 1270, 7: 1270, 57: 1270, 124: 1270, 461: 1270, 463: 1270, 469: 1270, 471: 1270, 479: 1270, 1270, 482: 1270, 1270, 1270, 486: 1270, 491: 1270, 493: 1270, 504: 1270, 1270, 513: 1270, 516: 1270, 1270}, + {1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 466: 1903, 468: 1903, 470: 1903, 472: 1903, 1903, 475: 1903, 1903, 480: 1903, 1903, 1903, 485: 1903, 1903, 1903, 1903, 490: 1903, 1903, 1903, 494: 1903, 1903, 1903, 1903, 501: 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 514: 1903, 516: 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 537: 1903, 1903}, + {7: 2279, 47: 2279}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4082, 2691, 2692, 2690}, + {2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 465: 2282, 483: 2282, 489: 2282, 496: 2282, 498: 2282, 521: 2282, 2282, 536: 2282, 638: 2282, 643: 4083, 660: 2282, 2282, 663: 2282, 668: 2282, 2282, 671: 2282, 2282, 2282, 2282, 2282, 2282, 679: 2282, 681: 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 696: 2282, 2282, 2282, 2282}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4084, 2691, 2692, 2690}, // 1610 - {1269, 1269, 7: 1269, 57: 1269, 124: 1269, 461: 1269, 463: 1269, 469: 1269, 471: 1269, 479: 1269, 1269, 482: 1269, 1269, 1269, 486: 1269, 491: 1269, 493: 1269, 504: 1269, 1269, 513: 1269, 516: 1269, 1269}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4072}, - {1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 463: 1901, 1901, 468: 1901, 1901, 471: 1901, 1901, 1901, 477: 1901, 479: 1901, 1901, 482: 1901, 1901, 1901, 486: 1901, 488: 1901, 490: 1901, 1901, 1901, 1901, 495: 3249, 497: 3247, 3248, 3246, 3244, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 511: 1901, 513: 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 534: 1901, 1901, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4074}, - {57: 4075}, + {2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 465: 2281, 483: 2281, 489: 2281, 496: 2281, 498: 2281, 521: 2281, 2281, 536: 2281, 638: 2281, 660: 2281, 2281, 663: 2281, 668: 2281, 2281, 671: 2281, 2281, 2281, 2281, 2281, 2281, 679: 2281, 681: 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 696: 2281, 2281, 2281, 2281}, + {1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 466: 1904, 468: 1904, 470: 1904, 472: 1904, 1904, 475: 1904, 1904, 480: 1904, 1904, 1904, 485: 1904, 1904, 1904, 1904, 490: 1904, 1904, 1904, 494: 1904, 1904, 1904, 1904, 501: 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 514: 1904, 516: 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 537: 1904, 1904, 725: 3261, 3259}, + {1275, 1275, 7: 1275, 47: 1275, 125: 1275, 464: 1275, 466: 1275, 472: 1275, 1275, 480: 1275, 1275, 485: 1275, 1275, 1275, 1275, 491: 1275, 494: 1275, 507: 1275, 1275, 516: 1275, 519: 1275, 1275}, + {1274, 1274, 7: 1274, 47: 1274, 125: 1274, 464: 1274, 466: 1274, 472: 1274, 1274, 480: 1274, 1274, 485: 1274, 1274, 1274, 1274, 491: 1274, 494: 1274, 507: 1274, 1274, 516: 1274, 519: 1274, 1274}, + {1273, 1273, 7: 1273, 47: 1273, 125: 1273, 464: 1273, 466: 1273, 472: 1273, 1273, 480: 1273, 1273, 485: 1273, 1273, 1273, 1273, 491: 1273, 494: 1273, 507: 1273, 1273, 516: 1273, 519: 1273, 1273}, // 1615 - {2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 463: 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 488: 2172, 490: 2172, 2172, 2172, 2172, 495: 2172, 497: 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 533: 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 566: 2172, 571: 2172, 574: 2172, 576: 2172, 632: 2172, 2172, 635: 2172, 2172}, - {482: 4077}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4078}, - {2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 463: 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 488: 2173, 490: 2173, 2173, 2173, 2173, 495: 2173, 497: 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 533: 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 566: 2173, 571: 2173, 574: 2173, 576: 2173, 632: 2173, 2173, 635: 2173, 2173}, - {238, 238, 57: 238, 461: 238, 463: 238, 469: 238, 471: 238, 479: 238, 238, 482: 238, 238, 238, 486: 238, 491: 238, 493: 238, 495: 3249, 497: 3247, 3248, 3246, 3244, 502: 238, 504: 238, 238, 723: 3245, 3243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4090}, + {1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 466: 1908, 468: 1908, 470: 1908, 472: 1908, 1908, 475: 1908, 1908, 480: 1908, 1908, 1908, 485: 1908, 1908, 1908, 1908, 490: 1908, 1908, 1908, 494: 1908, 1908, 1908, 3265, 501: 3263, 3264, 3262, 3260, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 514: 1908, 516: 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 537: 1908, 1908, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4092}, + {47: 4093}, + {2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 466: 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 494: 2182, 2182, 2182, 2182, 501: 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 537: 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 565: 2182, 574: 2182, 2182, 2182, 586: 2182, 616: 2182, 635: 2182, 2182}, // 1620 + {485: 4095}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4096}, + {2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 466: 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 494: 2183, 2183, 2183, 2183, 501: 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 537: 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 565: 2183, 574: 2183, 2183, 2183, 586: 2183, 616: 2183, 635: 2183, 2183}, + {240, 240, 47: 240, 464: 240, 466: 240, 472: 240, 240, 480: 240, 240, 485: 240, 240, 240, 240, 491: 240, 494: 240, 497: 3265, 501: 3263, 3264, 3262, 3260, 240, 507: 240, 240, 725: 3261, 3259}, {4, 4}, - {143: 4082}, - {237, 237, 483: 237, 491: 237, 2636, 237, 780: 2637, 4083}, - {1265, 1265, 483: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 4084}, - {841, 841, 483: 2642, 491: 2643, 757: 2644, 818: 4085}, // 1625 + {143: 4100}, + {239, 239, 486: 239, 491: 239, 2651, 494: 239, 779: 2652, 4101}, + {1269, 1269, 486: 1269, 491: 1269, 494: 2654, 757: 2655, 800: 4102}, + {845, 845, 486: 2657, 491: 2658, 758: 2659, 817: 4103}, {2, 2}, - {556: 4088}, - {2: 1812, 1812, 1812, 1812, 1812, 8: 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 58: 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 462: 1812, 484: 1812, 490: 1812, 556: 1812, 568: 1812}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4089}, - {2341, 2341, 2341, 2341, 4147, 4149, 389, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 80: 4118, 83: 4139, 4140, 92: 4141, 132: 4121, 192: 4106, 4125, 196: 4126, 209: 4120, 215: 4136, 226: 4115, 236: 4122, 240: 4117, 256: 4127, 264: 4123, 271: 4137, 4138, 278: 4107, 463: 4135, 467: 4146, 469: 4183, 2118, 478: 2341, 486: 4142, 488: 4134, 2118, 493: 4124, 501: 4109, 574: 4114, 4110, 637: 2118, 4152, 643: 4091, 652: 4129, 659: 4116, 661: 4143, 669: 4128, 676: 4130, 679: 4111, 694: 4119, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4185, 858: 4133, 870: 4131, 907: 4108, 914: 4112, 974: 4145, 1118: 4113, 1145: 4132, 1150: 4144, 4090}, // 1630 - {2116, 2116, 4928, 4929, 478: 4930, 1081: 4927, 1149: 4926}, - {478: 4900}, - {464: 1999, 485: 4187, 726: 4898}, - {464: 1999, 485: 4187, 726: 4896}, - {485: 4187, 496: 1999, 726: 4894}, + {562: 4106}, + {2: 1819, 1819, 1819, 1819, 1819, 8: 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 48: 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 465: 1819, 487: 1819, 490: 1819, 562: 1819, 571: 1819}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4107}, + {2357, 2357, 2357, 2357, 4152, 4154, 391, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 69: 4123, 72: 4144, 4145, 81: 4146, 132: 4126, 193: 4111, 4130, 197: 4131, 209: 4125, 215: 4141, 226: 4120, 236: 4127, 240: 4122, 256: 4132, 264: 4128, 272: 4142, 4143, 279: 4112, 466: 4140, 471: 4151, 4188, 474: 2125, 483: 2357, 488: 4147, 494: 4129, 4139, 4114, 498: 2125, 574: 4119, 579: 4115, 638: 2125, 640: 4157, 644: 4109, 653: 4134, 660: 4121, 662: 4148, 670: 4133, 677: 4135, 680: 4116, 695: 4124, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4190, 858: 4138, 871: 4136, 907: 4113, 914: 4117, 977: 4150, 1122: 4118, 1149: 4137, 1154: 4149, 4108}, + {2123, 2123, 4923, 4924, 483: 4925, 1084: 4922, 1153: 4921}, // 1635 - {485: 4187, 496: 1999, 726: 4892}, - {485: 4187, 496: 1999, 726: 4890}, - {464: 1999, 485: 4187, 726: 4888}, - {464: 1999, 485: 4187, 726: 4886}, - {464: 1999, 485: 4187, 726: 4884}, + {483: 4895}, + {159: 4887}, + {468: 2006, 471: 2006, 489: 4192, 727: 4884}, + {468: 2006, 471: 2006, 489: 4192, 727: 4881}, + {2440, 2440, 2440, 2440, 4152, 4154, 391, 2440, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 471: 4151, 4188, 474: 2125, 483: 2440, 495: 4877, 498: 2125, 638: 2125, 640: 4157, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4878}, // 1640 - {464: 1999, 485: 4187, 726: 4882}, - {464: 1999, 485: 4187, 726: 4880}, - {464: 1999, 485: 4187, 726: 4878}, - {2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 13: 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 2441, 461: 2441, 2441, 2441, 467: 2441, 2441, 2441, 2441, 477: 2441, 2441, 487: 2441, 2441, 2441, 494: 2441, 556: 2441, 634: 2441, 637: 2441, 2441}, - {2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 13: 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 461: 2440, 2440, 2440, 467: 2440, 2440, 2440, 2440, 477: 2440, 2440, 487: 2440, 2440, 2440, 494: 2440, 556: 2440, 634: 2440, 637: 2440, 2440}, + {282: 4867}, + {641: 4859}, + {2: 2362, 2362, 2362, 2362, 2362, 8: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 48: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 465: 2362, 483: 4718, 558: 2362, 565: 2351, 574: 2351, 576: 2351, 586: 2351, 616: 4499, 640: 2351, 666: 2351, 2351, 821: 4720, 835: 4334, 861: 4716, 891: 4717, 902: 4719}, + {2430, 2430, 2430, 2430, 7: 2430, 483: 2430}, + {2429, 2429, 2429, 2429, 7: 2429, 483: 2429}, // 1645 - {158: 4870}, - {464: 1999, 467: 1999, 485: 4187, 726: 4867}, - {464: 1999, 467: 1999, 485: 4187, 726: 4864}, - {2424, 2424, 2424, 2424, 4147, 4149, 389, 2424, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 467: 4146, 469: 4183, 2118, 478: 2424, 488: 4860, 2118, 637: 2118, 4152, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4861}, - {385: 4850}, + {483: 4714}, + {483: 4711}, + {2: 2362, 2362, 2362, 2362, 2362, 8: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 48: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 483: 4690, 558: 2362, 565: 4320, 574: 4335, 576: 4689, 616: 4336, 640: 4321, 666: 4693, 816: 4692, 835: 4334, 861: 4688, 902: 4691, 989: 4694}, + {483: 4677}, + {483: 4675}, // 1650 - {640: 4842}, - {2: 2346, 2346, 2346, 2346, 2346, 8: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 58: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 462: 2346, 478: 4701, 555: 2346, 566: 2335, 574: 2335, 576: 2335, 632: 2335, 4494, 638: 2335, 665: 2335, 2335, 822: 4703, 835: 4329, 861: 4699, 891: 4700, 902: 4702}, - {2414, 2414, 2414, 2414, 7: 2414, 478: 2414}, - {2413, 2413, 2413, 2413, 7: 2413, 478: 2413}, - {478: 4697}, + {483: 4672}, + {483: 4669}, + {18: 4666, 483: 4665}, + {18: 4662, 483: 4661}, + {483: 4651}, // 1655 - {478: 4694}, - {2: 2346, 2346, 2346, 2346, 2346, 8: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 58: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 478: 4673, 555: 2346, 566: 4315, 574: 4330, 576: 4672, 633: 4331, 638: 4316, 665: 4676, 817: 4675, 835: 4329, 861: 4671, 902: 4674, 985: 4677}, - {478: 4660}, - {478: 4658}, - {478: 4655}, + {650: 4644}, + {931: 4643}, + {931: 4642}, + {2: 2362, 2362, 2362, 2362, 2362, 8: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 48: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 558: 2362, 835: 4334, 861: 4638}, + {2: 2362, 2362, 2362, 2362, 2362, 8: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 48: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 558: 2362, 835: 4334, 861: 4360}, // 1660 - {478: 4652}, - {30: 4649, 478: 4648}, - {30: 4645, 478: 4644}, - {478: 4634}, - {649: 4627}, + {2: 2362, 2362, 2362, 2362, 2362, 8: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 48: 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 2362, 574: 4335, 616: 4336, 640: 4333, 835: 4334, 861: 4331, 989: 4332}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 470: 4318, 489: 4192, 565: 4320, 640: 4321, 4316, 727: 4317, 816: 4319, 835: 4315}, + {2398, 2398, 2398, 2398, 7: 2398, 483: 2398}, + {2397, 2397, 2397, 2397, 7: 2397, 483: 2397}, + {2396, 2396, 2396, 2396, 7: 2396, 483: 2396}, // 1665 - {931: 4626}, - {931: 4625}, - {2: 2346, 2346, 2346, 2346, 2346, 8: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 58: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 555: 2346, 835: 4329, 861: 4621}, - {2: 2346, 2346, 2346, 2346, 2346, 8: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 58: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 555: 2346, 835: 4329, 861: 4355}, - {2: 2346, 2346, 2346, 2346, 2346, 8: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 58: 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 574: 4330, 633: 4331, 638: 4328, 835: 4329, 861: 4326, 985: 4327}, + {2395, 2395, 2395, 2395, 6: 390, 2395, 27: 390, 483: 2395}, + {191: 4314}, + {191: 4313}, + {2392, 2392, 2392, 2392, 7: 2392, 483: 2392}, + {2391, 2391, 2391, 2391, 7: 2391, 483: 2391}, // 1670 - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 468: 4313, 485: 4187, 566: 4315, 638: 4316, 640: 4311, 726: 4312, 817: 4314, 835: 4310}, - {2382, 2382, 2382, 2382, 7: 2382, 478: 2382}, - {2381, 2381, 2381, 2381, 7: 2381, 478: 2381}, - {2380, 2380, 2380, 2380, 7: 2380, 478: 2380}, - {2379, 2379, 2379, 2379, 6: 388, 2379, 38: 388, 478: 2379}, + {2387, 2387, 2387, 2387, 7: 2387, 483: 2387}, + {2386, 2386, 2386, 2386, 7: 2386, 483: 2386}, + {149: 2006, 230: 2006, 248: 2006, 250: 2006, 471: 2006, 489: 4192, 727: 4307}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 471: 2006, 489: 4192, 727: 4304}, + {151: 4303, 678: 4302}, // 1675 - {190: 4309}, - {190: 4308}, - {2376, 2376, 2376, 2376, 7: 2376, 478: 2376}, - {2375, 2375, 2375, 2375, 7: 2375, 478: 2375}, - {2371, 2371, 2371, 2371, 7: 2371, 478: 2371}, + {2356, 2356, 2356, 2356, 7: 4300, 483: 2356}, + {2355, 2355, 2355, 2355, 7: 2355, 483: 2355}, + {14: 2124, 16: 2124, 19: 2124, 474: 2124, 498: 2124, 638: 2124}, + {468: 2006, 489: 4192, 727: 4298}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 727: 4296}, // 1680 - {2370, 2370, 2370, 2370, 7: 2370, 478: 2370}, - {163: 1999, 230: 1999, 248: 1999, 250: 1999, 467: 1999, 485: 4187, 726: 4302}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 467: 1999, 485: 4187, 726: 4299}, - {150: 4298, 677: 4297}, - {2340, 2340, 2340, 2340, 7: 4295, 478: 2340}, + {20: 4291, 178: 4292, 237: 4293}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 727: 4289}, + {235: 4286}, + {235: 4283}, + {489: 4192, 500: 2006, 727: 4281}, // 1685 - {2339, 2339, 2339, 2339, 7: 2339, 478: 2339}, - {13: 2117, 16: 2117, 28: 2117, 470: 2117, 489: 2117, 637: 2117}, - {464: 1999, 485: 4187, 726: 4293}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 726: 4291}, - {31: 4286, 177: 4287, 237: 4288}, + {489: 4192, 500: 2006, 727: 4279}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 489: 4192, 727: 4277}, + {489: 4192, 500: 2006, 727: 4275}, + {2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 13: 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 47: 2079, 464: 2079, 2079, 2079, 470: 2079, 2079, 2079, 474: 2079, 482: 2079, 2079, 493: 2079, 495: 2079, 498: 2079, 2079, 562: 2079, 637: 2079, 2079, 640: 2079}, + {425, 425, 425, 425, 425, 425, 425, 425, 13: 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 464: 425, 425, 425, 470: 425, 425, 425, 474: 425, 482: 425, 425, 493: 425, 495: 425, 498: 425, 425, 562: 425, 637: 425, 425, 640: 425}, // 1690 - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 726: 4284}, - {235: 4281}, - {235: 4278}, - {485: 4187, 496: 1999, 726: 4276}, - {485: 4187, 496: 1999, 726: 4274}, + {14: 3753, 474: 4270, 498: 3754, 638: 3752, 762: 4269}, + {6: 4263, 27: 4264}, + {489: 4192, 500: 2006, 727: 4261}, + {489: 4192, 500: 2006, 727: 4259}, + {468: 2006, 489: 4192, 727: 4257}, // 1695 - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 485: 4187, 726: 4272}, - {485: 4187, 496: 1999, 726: 4270}, - {2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 13: 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 2072, 461: 2072, 2072, 2072, 467: 2072, 2072, 2072, 2072, 477: 2072, 2072, 487: 2072, 2072, 2072, 494: 2072, 556: 2072, 634: 2072, 637: 2072, 2072}, - {423, 423, 423, 423, 423, 423, 423, 423, 13: 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 461: 423, 423, 423, 467: 423, 423, 423, 423, 477: 423, 423, 487: 423, 423, 423, 494: 423, 556: 423, 634: 423, 637: 423, 423}, - {13: 3735, 470: 4265, 489: 3736, 637: 3734, 762: 4264}, + {489: 4192, 500: 2006, 727: 4255}, + {489: 4192, 500: 2006, 727: 4253}, + {468: 2006, 489: 4192, 727: 4251}, + {468: 2006, 489: 4192, 727: 4249}, + {489: 4192, 500: 2006, 727: 4247}, // 1700 - {6: 4258, 38: 4259}, - {485: 4187, 496: 1999, 726: 4256}, - {485: 4187, 496: 1999, 726: 4254}, - {464: 1999, 485: 4187, 726: 4252}, - {485: 4187, 496: 1999, 726: 4250}, + {489: 4192, 500: 2006, 727: 4245}, + {411, 411, 411, 411, 411, 411, 411, 411, 13: 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 464: 411, 411, 411, 470: 411, 411, 411, 474: 411, 482: 411, 411, 493: 411, 495: 411, 498: 411, 411, 562: 411, 637: 411, 411, 640: 411}, + {471: 2006, 489: 4192, 500: 2006, 727: 4243}, + {471: 2006, 489: 4192, 500: 2006, 727: 4240}, + {471: 2006, 489: 4192, 500: 2006, 727: 4237}, // 1705 - {485: 4187, 496: 1999, 726: 4248}, - {464: 1999, 485: 4187, 726: 4246}, - {464: 1999, 485: 4187, 726: 4244}, - {485: 4187, 496: 1999, 726: 4242}, - {485: 4187, 496: 1999, 726: 4240}, + {489: 4192, 500: 2006, 727: 4235}, + {489: 4192, 500: 2006, 727: 4233}, + {489: 4192, 500: 2006, 566: 2006, 2006, 727: 4231}, + {468: 2006, 489: 4192, 727: 4229}, + {468: 2006, 489: 4192, 727: 4227}, // 1710 - {409, 409, 409, 409, 409, 409, 409, 409, 13: 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 461: 409, 409, 409, 467: 409, 409, 409, 409, 477: 409, 409, 487: 409, 409, 409, 494: 409, 556: 409, 634: 409, 637: 409, 409}, - {467: 1999, 485: 4187, 496: 1999, 726: 4238}, - {467: 1999, 485: 4187, 496: 1999, 726: 4235}, - {467: 1999, 485: 4187, 496: 1999, 726: 4232}, - {485: 4187, 496: 1999, 726: 4230}, + {489: 4192, 500: 2006, 727: 4225}, + {489: 4192, 500: 2006, 727: 4223}, + {471: 2006, 489: 4192, 500: 2006, 727: 4219}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 484: 2006, 489: 4192, 727: 4216}, + {465: 2006, 489: 4192, 727: 4211}, // 1715 - {485: 4187, 496: 1999, 726: 4228}, - {485: 4187, 496: 1999, 562: 1999, 1999, 726: 4226}, - {464: 1999, 485: 4187, 726: 4224}, - {464: 1999, 485: 4187, 726: 4222}, - {485: 4187, 496: 1999, 726: 4220}, + {468: 2006, 489: 4192, 727: 4208}, + {385, 385, 385, 385, 385, 385, 385, 385, 13: 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 464: 385, 385, 385, 470: 385, 385, 385, 474: 385, 482: 385, 385, 493: 385, 495: 385, 498: 385, 385, 562: 385, 637: 385, 385, 640: 385}, + {173: 2006, 196: 2006, 227: 2006, 2006, 265: 2006, 283: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 471: 2006, 489: 4192, 727: 4193}, + {2: 2005, 2005, 2005, 2005, 2005, 8: 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 48: 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 465: 2005, 468: 2005, 471: 2005, 477: 2005, 2005, 482: 2005, 484: 2005, 499: 2005, 2005, 536: 2005, 563: 2005, 2005, 566: 2005, 2005}, + {173: 4196, 196: 4195, 227: 4199, 4197, 265: 4198, 283: 4200, 4201, 4205, 4204, 4202, 4206, 4207, 4203, 471: 4194}, // 1720 - {485: 4187, 496: 1999, 726: 4218}, - {467: 1999, 485: 4187, 496: 1999, 726: 4214}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 481: 1999, 485: 4187, 726: 4211}, - {462: 1999, 485: 4187, 726: 4206}, - {464: 1999, 485: 4187, 726: 4203}, + {379, 379, 379, 379, 379, 379, 379, 379, 13: 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 464: 379, 379, 379, 470: 379, 379, 379, 474: 379, 482: 379, 379, 493: 379, 495: 379, 498: 379, 379, 562: 379, 637: 379, 379, 640: 379}, + {378, 378, 378, 378, 378, 378, 378, 378, 13: 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 464: 378, 378, 378, 470: 378, 378, 378, 474: 378, 482: 378, 378, 493: 378, 495: 378, 498: 378, 378, 562: 378, 637: 378, 378, 640: 378}, + {377, 377, 377, 377, 377, 377, 377, 377, 13: 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 464: 377, 377, 377, 470: 377, 377, 377, 474: 377, 482: 377, 377, 493: 377, 495: 377, 498: 377, 377, 562: 377, 637: 377, 377, 640: 377}, + {376, 376, 376, 376, 376, 376, 376, 376, 13: 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 464: 376, 376, 376, 470: 376, 376, 376, 474: 376, 482: 376, 376, 493: 376, 495: 376, 498: 376, 376, 562: 376, 637: 376, 376, 640: 376}, + {375, 375, 375, 375, 375, 375, 375, 375, 13: 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 464: 375, 375, 375, 470: 375, 375, 375, 474: 375, 482: 375, 375, 493: 375, 495: 375, 498: 375, 375, 562: 375, 637: 375, 375, 640: 375}, // 1725 - {383, 383, 383, 383, 383, 383, 383, 383, 13: 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 461: 383, 383, 383, 467: 383, 383, 383, 383, 477: 383, 383, 487: 383, 383, 383, 494: 383, 556: 383, 634: 383, 637: 383, 383}, - {173: 1999, 195: 1999, 227: 1999, 1999, 265: 1999, 281: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 467: 1999, 485: 4187, 726: 4188}, - {2: 1998, 1998, 1998, 1998, 1998, 8: 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 58: 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998, 462: 1998, 464: 1998, 467: 1998, 474: 1998, 1998, 477: 1998, 481: 1998, 494: 1998, 496: 1998, 532: 1998, 560: 1998, 1998, 1998, 1998}, - {173: 4191, 195: 4190, 227: 4194, 4192, 265: 4193, 281: 4195, 4196, 4200, 4199, 4197, 4201, 4202, 4198, 467: 4189}, - {377, 377, 377, 377, 377, 377, 377, 377, 13: 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 461: 377, 377, 377, 467: 377, 377, 377, 377, 477: 377, 377, 487: 377, 377, 377, 494: 377, 556: 377, 634: 377, 637: 377, 377}, + {374, 374, 374, 374, 374, 374, 374, 374, 13: 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 464: 374, 374, 374, 470: 374, 374, 374, 474: 374, 482: 374, 374, 493: 374, 495: 374, 498: 374, 374, 562: 374, 637: 374, 374, 640: 374}, + {373, 373, 373, 373, 373, 373, 373, 373, 13: 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 464: 373, 373, 373, 470: 373, 373, 373, 474: 373, 482: 373, 373, 493: 373, 495: 373, 498: 373, 373, 562: 373, 637: 373, 373, 640: 373}, + {372, 372, 372, 372, 372, 372, 372, 372, 13: 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 464: 372, 372, 372, 470: 372, 372, 372, 474: 372, 482: 372, 372, 493: 372, 495: 372, 498: 372, 372, 562: 372, 637: 372, 372, 640: 372}, + {371, 371, 371, 371, 371, 371, 371, 371, 13: 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 464: 371, 371, 371, 470: 371, 371, 371, 474: 371, 482: 371, 371, 493: 371, 495: 371, 498: 371, 371, 562: 371, 637: 371, 371, 640: 371}, + {370, 370, 370, 370, 370, 370, 370, 370, 13: 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 464: 370, 370, 370, 470: 370, 370, 370, 474: 370, 482: 370, 370, 493: 370, 495: 370, 498: 370, 370, 562: 370, 637: 370, 370, 640: 370}, // 1730 - {376, 376, 376, 376, 376, 376, 376, 376, 13: 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 461: 376, 376, 376, 467: 376, 376, 376, 376, 477: 376, 376, 487: 376, 376, 376, 494: 376, 556: 376, 634: 376, 637: 376, 376}, - {375, 375, 375, 375, 375, 375, 375, 375, 13: 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 461: 375, 375, 375, 467: 375, 375, 375, 375, 477: 375, 375, 487: 375, 375, 375, 494: 375, 556: 375, 634: 375, 637: 375, 375}, - {374, 374, 374, 374, 374, 374, 374, 374, 13: 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 461: 374, 374, 374, 467: 374, 374, 374, 374, 477: 374, 374, 487: 374, 374, 374, 494: 374, 556: 374, 634: 374, 637: 374, 374}, - {373, 373, 373, 373, 373, 373, 373, 373, 13: 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 461: 373, 373, 373, 467: 373, 373, 373, 373, 477: 373, 373, 487: 373, 373, 373, 494: 373, 556: 373, 634: 373, 637: 373, 373}, - {372, 372, 372, 372, 372, 372, 372, 372, 13: 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 461: 372, 372, 372, 467: 372, 372, 372, 372, 477: 372, 372, 487: 372, 372, 372, 494: 372, 556: 372, 634: 372, 637: 372, 372}, + {369, 369, 369, 369, 369, 369, 369, 369, 13: 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 464: 369, 369, 369, 470: 369, 369, 369, 474: 369, 482: 369, 369, 493: 369, 495: 369, 498: 369, 369, 562: 369, 637: 369, 369, 640: 369}, + {368, 368, 368, 368, 368, 368, 368, 368, 13: 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 464: 368, 368, 368, 470: 368, 368, 368, 474: 368, 482: 368, 368, 493: 368, 495: 368, 498: 368, 368, 562: 368, 637: 368, 368, 640: 368}, + {367, 367, 367, 367, 367, 367, 367, 367, 13: 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 464: 367, 367, 367, 470: 367, 367, 367, 474: 367, 482: 367, 367, 493: 367, 495: 367, 498: 367, 367, 562: 367, 637: 367, 367, 640: 367}, + {366, 366, 366, 366, 366, 366, 366, 366, 13: 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 464: 366, 366, 366, 470: 366, 366, 366, 474: 366, 482: 366, 366, 493: 366, 495: 366, 498: 366, 366, 562: 366, 637: 366, 366, 640: 366}, + {468: 4210, 1028: 4209}, // 1735 - {371, 371, 371, 371, 371, 371, 371, 371, 13: 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 461: 371, 371, 371, 467: 371, 371, 371, 371, 477: 371, 371, 487: 371, 371, 371, 494: 371, 556: 371, 634: 371, 637: 371, 371}, - {370, 370, 370, 370, 370, 370, 370, 370, 13: 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 461: 370, 370, 370, 467: 370, 370, 370, 370, 477: 370, 370, 487: 370, 370, 370, 494: 370, 556: 370, 634: 370, 637: 370, 370}, - {369, 369, 369, 369, 369, 369, 369, 369, 13: 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 461: 369, 369, 369, 467: 369, 369, 369, 369, 477: 369, 369, 487: 369, 369, 369, 494: 369, 556: 369, 634: 369, 637: 369, 369}, - {368, 368, 368, 368, 368, 368, 368, 368, 13: 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 461: 368, 368, 368, 467: 368, 368, 368, 368, 477: 368, 368, 487: 368, 368, 368, 494: 368, 556: 368, 634: 368, 637: 368, 368}, - {367, 367, 367, 367, 367, 367, 367, 367, 13: 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 461: 367, 367, 367, 467: 367, 367, 367, 367, 477: 367, 367, 487: 367, 367, 367, 494: 367, 556: 367, 634: 367, 637: 367, 367}, + {392, 392, 392, 392, 392, 392, 392, 392, 13: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 464: 392, 392, 392, 470: 392, 392, 392, 474: 392, 482: 392, 392, 493: 392, 495: 392, 498: 392, 392, 562: 392, 637: 392, 392, 640: 392}, + {9, 9, 9, 9, 9, 9, 9, 9, 13: 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 464: 9, 9, 9, 470: 9, 9, 9, 474: 9, 482: 9, 9, 493: 9, 495: 9, 9, 498: 9, 9, 562: 9, 637: 9, 9, 640: 9}, + {465: 4212}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 550, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 4213, 1131: 4214}, + {549, 549, 7: 3841, 47: 549, 466: 549}, // 1740 - {366, 366, 366, 366, 366, 366, 366, 366, 13: 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 461: 366, 366, 366, 467: 366, 366, 366, 366, 477: 366, 366, 487: 366, 366, 366, 494: 366, 556: 366, 634: 366, 637: 366, 366}, - {365, 365, 365, 365, 365, 365, 365, 365, 13: 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 461: 365, 365, 365, 467: 365, 365, 365, 365, 477: 365, 365, 487: 365, 365, 365, 494: 365, 556: 365, 634: 365, 637: 365, 365}, - {364, 364, 364, 364, 364, 364, 364, 364, 13: 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 461: 364, 364, 364, 467: 364, 364, 364, 364, 477: 364, 364, 487: 364, 364, 364, 494: 364, 556: 364, 634: 364, 637: 364, 364}, - {464: 4205, 1024: 4204}, - {390, 390, 390, 390, 390, 390, 390, 390, 13: 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 461: 390, 390, 390, 467: 390, 390, 390, 390, 477: 390, 390, 487: 390, 390, 390, 494: 390, 556: 390, 634: 390, 637: 390, 390}, + {47: 4215}, + {393, 393, 393, 393, 393, 393, 393, 393, 13: 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 464: 393, 393, 393, 470: 393, 393, 393, 474: 393, 482: 393, 393, 493: 393, 495: 393, 498: 393, 393, 562: 393, 637: 393, 393, 640: 393}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 484: 4217, 654: 3410, 2691, 2692, 2690, 729: 4218}, + {395, 395, 395, 395, 395, 395, 395, 395, 13: 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 464: 395, 395, 395, 470: 395, 395, 395, 474: 395, 482: 395, 395, 493: 395, 495: 395, 498: 395, 395, 562: 395, 637: 395, 395, 640: 395}, + {394, 394, 394, 394, 394, 394, 394, 394, 13: 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 464: 394, 394, 394, 470: 394, 394, 394, 474: 394, 482: 394, 394, 493: 394, 495: 394, 498: 394, 394, 562: 394, 637: 394, 394, 640: 394}, // 1745 - {9, 9, 9, 9, 9, 9, 9, 9, 13: 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 461: 9, 9, 9, 467: 9, 9, 9, 9, 477: 9, 9, 487: 9, 9, 9, 494: 9, 556: 9, 634: 9, 637: 9, 9}, - {462: 4207}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 547, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 4208, 1127: 4209}, - {546, 546, 7: 3823, 57: 546, 463: 546}, - {57: 4210}, + {471: 4221, 500: 2665, 724: 2664, 734: 4222, 1123: 4220}, + {398, 398, 398, 398, 398, 398, 398, 398, 13: 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 464: 398, 398, 398, 470: 398, 398, 398, 474: 398, 482: 398, 398, 493: 398, 495: 398, 498: 398, 398, 562: 398, 637: 398, 398, 640: 398}, + {389, 389, 389, 389, 389, 389, 389, 389, 13: 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 464: 389, 389, 389, 470: 389, 389, 389, 474: 389, 482: 389, 389, 493: 389, 495: 389, 498: 389, 389, 562: 389, 637: 389, 389, 640: 389}, + {388, 388, 388, 388, 388, 388, 388, 388, 13: 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 464: 388, 388, 388, 470: 388, 388, 388, 474: 388, 482: 388, 388, 493: 388, 495: 388, 498: 388, 388, 562: 388, 637: 388, 388, 640: 388}, + {500: 2665, 724: 2664, 734: 4224}, // 1750 - {391, 391, 391, 391, 391, 391, 391, 391, 13: 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 461: 391, 391, 391, 467: 391, 391, 391, 391, 477: 391, 391, 487: 391, 391, 391, 494: 391, 556: 391, 634: 391, 637: 391, 391}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 481: 4212, 653: 3392, 2676, 2677, 2675, 728: 4213}, - {393, 393, 393, 393, 393, 393, 393, 393, 13: 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 461: 393, 393, 393, 467: 393, 393, 393, 393, 477: 393, 393, 487: 393, 393, 393, 494: 393, 556: 393, 634: 393, 637: 393, 393}, - {392, 392, 392, 392, 392, 392, 392, 392, 13: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 461: 392, 392, 392, 467: 392, 392, 392, 392, 477: 392, 392, 487: 392, 392, 392, 494: 392, 556: 392, 634: 392, 637: 392, 392}, - {467: 4216, 496: 2650, 725: 2649, 734: 4217, 1119: 4215}, + {399, 399, 399, 399, 399, 399, 399, 399, 13: 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 464: 399, 399, 399, 470: 399, 399, 399, 474: 399, 482: 399, 399, 493: 399, 495: 399, 498: 399, 399, 562: 399, 637: 399, 399, 640: 399}, + {500: 2665, 724: 2664, 734: 4226}, + {400, 400, 400, 400, 400, 400, 400, 400, 13: 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 464: 400, 400, 400, 470: 400, 400, 400, 474: 400, 482: 400, 400, 493: 400, 495: 400, 498: 400, 400, 562: 400, 637: 400, 400, 640: 400}, + {468: 4228}, + {401, 401, 401, 401, 401, 401, 401, 401, 13: 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 464: 401, 401, 401, 470: 401, 401, 401, 474: 401, 482: 401, 401, 493: 401, 495: 401, 498: 401, 401, 562: 401, 637: 401, 401, 640: 401}, // 1755 - {396, 396, 396, 396, 396, 396, 396, 396, 13: 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 461: 396, 396, 396, 467: 396, 396, 396, 396, 477: 396, 396, 487: 396, 396, 396, 494: 396, 556: 396, 634: 396, 637: 396, 396}, - {387, 387, 387, 387, 387, 387, 387, 387, 13: 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 461: 387, 387, 387, 467: 387, 387, 387, 387, 477: 387, 387, 487: 387, 387, 387, 494: 387, 556: 387, 634: 387, 637: 387, 387}, - {386, 386, 386, 386, 386, 386, 386, 386, 13: 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 461: 386, 386, 386, 467: 386, 386, 386, 386, 477: 386, 386, 487: 386, 386, 386, 494: 386, 556: 386, 634: 386, 637: 386, 386}, - {496: 2650, 725: 2649, 734: 4219}, - {397, 397, 397, 397, 397, 397, 397, 397, 13: 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 461: 397, 397, 397, 467: 397, 397, 397, 397, 477: 397, 397, 487: 397, 397, 397, 494: 397, 556: 397, 634: 397, 637: 397, 397}, + {468: 4230}, + {402, 402, 402, 402, 402, 402, 402, 402, 13: 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 464: 402, 402, 402, 470: 402, 402, 402, 474: 402, 482: 402, 402, 493: 402, 495: 402, 498: 402, 402, 562: 402, 637: 402, 402, 640: 402}, + {500: 3342, 566: 3344, 3343, 808: 4232}, + {403, 403, 403, 403, 403, 403, 403, 403, 13: 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 464: 403, 403, 403, 470: 403, 403, 403, 474: 403, 482: 403, 403, 493: 403, 495: 403, 498: 403, 403, 562: 403, 637: 403, 403, 640: 403}, + {500: 2665, 724: 2664, 734: 4234}, // 1760 - {496: 2650, 725: 2649, 734: 4221}, - {398, 398, 398, 398, 398, 398, 398, 398, 13: 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 461: 398, 398, 398, 467: 398, 398, 398, 398, 477: 398, 398, 487: 398, 398, 398, 494: 398, 556: 398, 634: 398, 637: 398, 398}, - {464: 4223}, - {399, 399, 399, 399, 399, 399, 399, 399, 13: 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 461: 399, 399, 399, 467: 399, 399, 399, 399, 477: 399, 399, 487: 399, 399, 399, 494: 399, 556: 399, 634: 399, 637: 399, 399}, - {464: 4225}, + {404, 404, 404, 404, 404, 404, 404, 404, 13: 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 464: 404, 404, 404, 470: 404, 404, 404, 474: 404, 482: 404, 404, 493: 404, 495: 404, 498: 404, 404, 562: 404, 637: 404, 404, 640: 404}, + {500: 2665, 724: 2664, 734: 4236}, + {405, 405, 405, 405, 405, 405, 405, 405, 13: 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 464: 405, 405, 405, 470: 405, 405, 405, 474: 405, 482: 405, 405, 493: 405, 495: 405, 498: 405, 405, 562: 405, 637: 405, 405, 640: 405}, + {471: 4239, 500: 2665, 724: 2664, 734: 4238}, + {407, 407, 407, 407, 407, 407, 407, 407, 13: 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 464: 407, 407, 407, 470: 407, 407, 407, 474: 407, 482: 407, 407, 493: 407, 495: 407, 498: 407, 407, 562: 407, 637: 407, 407, 640: 407}, // 1765 - {400, 400, 400, 400, 400, 400, 400, 400, 13: 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 461: 400, 400, 400, 467: 400, 400, 400, 400, 477: 400, 400, 487: 400, 400, 400, 494: 400, 556: 400, 634: 400, 637: 400, 400}, - {496: 3324, 562: 3326, 3325, 809: 4227}, - {401, 401, 401, 401, 401, 401, 401, 401, 13: 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 461: 401, 401, 401, 467: 401, 401, 401, 401, 477: 401, 401, 487: 401, 401, 401, 494: 401, 556: 401, 634: 401, 637: 401, 401}, - {496: 2650, 725: 2649, 734: 4229}, - {402, 402, 402, 402, 402, 402, 402, 402, 13: 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 461: 402, 402, 402, 467: 402, 402, 402, 402, 477: 402, 402, 487: 402, 402, 402, 494: 402, 556: 402, 634: 402, 637: 402, 402}, + {406, 406, 406, 406, 406, 406, 406, 406, 13: 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 464: 406, 406, 406, 470: 406, 406, 406, 474: 406, 482: 406, 406, 493: 406, 495: 406, 498: 406, 406, 562: 406, 637: 406, 406, 640: 406}, + {471: 4242, 500: 2665, 724: 2664, 734: 4241}, + {409, 409, 409, 409, 409, 409, 409, 409, 13: 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 464: 409, 409, 409, 470: 409, 409, 409, 474: 409, 482: 409, 409, 493: 409, 495: 409, 498: 409, 409, 562: 409, 637: 409, 409, 640: 409}, + {408, 408, 408, 408, 408, 408, 408, 408, 13: 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 464: 408, 408, 408, 470: 408, 408, 408, 474: 408, 482: 408, 408, 493: 408, 495: 408, 498: 408, 408, 562: 408, 637: 408, 408, 640: 408}, + {471: 4221, 500: 2665, 724: 2664, 734: 4222, 1123: 4244}, // 1770 - {496: 2650, 725: 2649, 734: 4231}, - {403, 403, 403, 403, 403, 403, 403, 403, 13: 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 461: 403, 403, 403, 467: 403, 403, 403, 403, 477: 403, 403, 487: 403, 403, 403, 494: 403, 556: 403, 634: 403, 637: 403, 403}, - {467: 4234, 496: 2650, 725: 2649, 734: 4233}, - {405, 405, 405, 405, 405, 405, 405, 405, 13: 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 461: 405, 405, 405, 467: 405, 405, 405, 405, 477: 405, 405, 487: 405, 405, 405, 494: 405, 556: 405, 634: 405, 637: 405, 405}, - {404, 404, 404, 404, 404, 404, 404, 404, 13: 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 461: 404, 404, 404, 467: 404, 404, 404, 404, 477: 404, 404, 487: 404, 404, 404, 494: 404, 556: 404, 634: 404, 637: 404, 404}, + {410, 410, 410, 410, 410, 410, 410, 410, 13: 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 464: 410, 410, 410, 470: 410, 410, 410, 474: 410, 482: 410, 410, 493: 410, 495: 410, 498: 410, 410, 562: 410, 637: 410, 410, 640: 410}, + {500: 2665, 724: 2664, 734: 4246}, + {412, 412, 412, 412, 412, 412, 412, 412, 13: 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 464: 412, 412, 412, 470: 412, 412, 412, 474: 412, 482: 412, 412, 493: 412, 495: 412, 498: 412, 412, 562: 412, 637: 412, 412, 640: 412}, + {500: 2665, 724: 2664, 734: 4248}, + {413, 413, 413, 413, 413, 413, 413, 413, 13: 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 464: 413, 413, 413, 470: 413, 413, 413, 474: 413, 482: 413, 413, 493: 413, 495: 413, 498: 413, 413, 562: 413, 637: 413, 413, 640: 413}, // 1775 - {467: 4237, 496: 2650, 725: 2649, 734: 4236}, - {407, 407, 407, 407, 407, 407, 407, 407, 13: 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, 461: 407, 407, 407, 467: 407, 407, 407, 407, 477: 407, 407, 487: 407, 407, 407, 494: 407, 556: 407, 634: 407, 637: 407, 407}, - {406, 406, 406, 406, 406, 406, 406, 406, 13: 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, 461: 406, 406, 406, 467: 406, 406, 406, 406, 477: 406, 406, 487: 406, 406, 406, 494: 406, 556: 406, 634: 406, 637: 406, 406}, - {467: 4216, 496: 2650, 725: 2649, 734: 4217, 1119: 4239}, - {408, 408, 408, 408, 408, 408, 408, 408, 13: 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, 461: 408, 408, 408, 467: 408, 408, 408, 408, 477: 408, 408, 487: 408, 408, 408, 494: 408, 556: 408, 634: 408, 637: 408, 408}, + {468: 4250}, + {414, 414, 414, 414, 414, 414, 414, 414, 13: 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 464: 414, 414, 414, 470: 414, 414, 414, 474: 414, 482: 414, 414, 493: 414, 495: 414, 498: 414, 414, 562: 414, 637: 414, 414, 640: 414}, + {468: 4252}, + {415, 415, 415, 415, 415, 415, 415, 415, 13: 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 464: 415, 415, 415, 470: 415, 415, 415, 474: 415, 482: 415, 415, 493: 415, 495: 415, 498: 415, 415, 562: 415, 637: 415, 415, 640: 415}, + {500: 2665, 724: 2664, 734: 4254}, // 1780 - {496: 2650, 725: 2649, 734: 4241}, - {410, 410, 410, 410, 410, 410, 410, 410, 13: 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 461: 410, 410, 410, 467: 410, 410, 410, 410, 477: 410, 410, 487: 410, 410, 410, 494: 410, 556: 410, 634: 410, 637: 410, 410}, - {496: 2650, 725: 2649, 734: 4243}, - {411, 411, 411, 411, 411, 411, 411, 411, 13: 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 461: 411, 411, 411, 467: 411, 411, 411, 411, 477: 411, 411, 487: 411, 411, 411, 494: 411, 556: 411, 634: 411, 637: 411, 411}, - {464: 4245}, + {416, 416, 416, 416, 416, 416, 416, 416, 13: 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 464: 416, 416, 416, 470: 416, 416, 416, 474: 416, 482: 416, 416, 493: 416, 495: 416, 498: 416, 416, 562: 416, 637: 416, 416, 640: 416}, + {500: 2665, 724: 2664, 734: 4256}, + {417, 417, 417, 417, 417, 417, 417, 417, 13: 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 464: 417, 417, 417, 470: 417, 417, 417, 474: 417, 482: 417, 417, 493: 417, 495: 417, 498: 417, 417, 562: 417, 637: 417, 417, 640: 417}, + {468: 4258}, + {418, 418, 418, 418, 418, 418, 418, 418, 13: 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 464: 418, 418, 418, 470: 418, 418, 418, 474: 418, 482: 418, 418, 493: 418, 495: 418, 498: 418, 418, 562: 418, 637: 418, 418, 640: 418}, // 1785 - {412, 412, 412, 412, 412, 412, 412, 412, 13: 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 461: 412, 412, 412, 467: 412, 412, 412, 412, 477: 412, 412, 487: 412, 412, 412, 494: 412, 556: 412, 634: 412, 637: 412, 412}, - {464: 4247}, - {413, 413, 413, 413, 413, 413, 413, 413, 13: 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 461: 413, 413, 413, 467: 413, 413, 413, 413, 477: 413, 413, 487: 413, 413, 413, 494: 413, 556: 413, 634: 413, 637: 413, 413}, - {496: 2650, 725: 2649, 734: 4249}, - {414, 414, 414, 414, 414, 414, 414, 414, 13: 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 461: 414, 414, 414, 467: 414, 414, 414, 414, 477: 414, 414, 487: 414, 414, 414, 494: 414, 556: 414, 634: 414, 637: 414, 414}, + {500: 2665, 724: 2664, 734: 4260}, + {419, 419, 419, 419, 419, 419, 419, 419, 13: 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 464: 419, 419, 419, 470: 419, 419, 419, 474: 419, 482: 419, 419, 493: 419, 495: 419, 498: 419, 419, 562: 419, 637: 419, 419, 640: 419}, + {500: 2665, 724: 2664, 734: 4262}, + {421, 421, 421, 421, 421, 421, 421, 421, 13: 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 464: 421, 421, 421, 470: 421, 421, 421, 474: 421, 482: 421, 421, 493: 421, 495: 421, 498: 421, 421, 562: 421, 637: 421, 421, 640: 421}, + {489: 4192, 500: 2006, 727: 4267}, // 1790 - {496: 2650, 725: 2649, 734: 4251}, - {415, 415, 415, 415, 415, 415, 415, 415, 13: 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 461: 415, 415, 415, 467: 415, 415, 415, 415, 477: 415, 415, 487: 415, 415, 415, 494: 415, 556: 415, 634: 415, 637: 415, 415}, - {464: 4253}, - {416, 416, 416, 416, 416, 416, 416, 416, 13: 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 461: 416, 416, 416, 467: 416, 416, 416, 416, 477: 416, 416, 487: 416, 416, 416, 494: 416, 556: 416, 634: 416, 637: 416, 416}, - {496: 2650, 725: 2649, 734: 4255}, + {489: 4192, 500: 2006, 727: 4265}, + {500: 2665, 724: 2664, 734: 4266}, + {420, 420, 420, 420, 420, 420, 420, 420, 13: 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 464: 420, 420, 420, 470: 420, 420, 420, 474: 420, 482: 420, 420, 493: 420, 495: 420, 498: 420, 420, 562: 420, 637: 420, 420, 640: 420}, + {500: 2665, 724: 2664, 734: 4268}, + {422, 422, 422, 422, 422, 422, 422, 422, 13: 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 464: 422, 422, 422, 470: 422, 422, 422, 474: 422, 482: 422, 422, 493: 422, 495: 422, 498: 422, 422, 562: 422, 637: 422, 422, 640: 422}, // 1795 - {417, 417, 417, 417, 417, 417, 417, 417, 13: 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 461: 417, 417, 417, 467: 417, 417, 417, 417, 477: 417, 417, 487: 417, 417, 417, 494: 417, 556: 417, 634: 417, 637: 417, 417}, - {496: 2650, 725: 2649, 734: 4257}, - {419, 419, 419, 419, 419, 419, 419, 419, 13: 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 461: 419, 419, 419, 467: 419, 419, 419, 419, 477: 419, 419, 487: 419, 419, 419, 494: 419, 556: 419, 634: 419, 637: 419, 419}, - {485: 4187, 496: 1999, 726: 4262}, - {485: 4187, 496: 1999, 726: 4260}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 536: 2006, 727: 4273}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 536: 2006, 727: 4271}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3408, 654: 3410, 2691, 2692, 2690, 729: 3407, 860: 4272}, + {423, 423, 423, 423, 423, 423, 423, 423, 13: 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 464: 423, 423, 423, 470: 423, 423, 423, 474: 423, 482: 423, 423, 493: 423, 495: 423, 498: 423, 423, 562: 423, 637: 423, 423, 640: 423}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 4274}, // 1800 - {496: 2650, 725: 2649, 734: 4261}, - {418, 418, 418, 418, 418, 418, 418, 418, 13: 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 461: 418, 418, 418, 467: 418, 418, 418, 418, 477: 418, 418, 487: 418, 418, 418, 494: 418, 556: 418, 634: 418, 637: 418, 418}, - {496: 2650, 725: 2649, 734: 4263}, - {420, 420, 420, 420, 420, 420, 420, 420, 13: 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 461: 420, 420, 420, 467: 420, 420, 420, 420, 477: 420, 420, 487: 420, 420, 420, 494: 420, 556: 420, 634: 420, 637: 420, 420}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 532: 1999, 726: 4268}, + {424, 424, 424, 424, 424, 424, 424, 424, 13: 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 464: 424, 424, 424, 470: 424, 424, 424, 474: 424, 482: 424, 424, 493: 424, 495: 424, 498: 424, 424, 562: 424, 637: 424, 424, 640: 424}, + {500: 2665, 724: 2664, 734: 4276}, + {2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 13: 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 47: 2080, 464: 2080, 2080, 2080, 470: 2080, 2080, 2080, 474: 2080, 482: 2080, 2080, 493: 2080, 495: 2080, 498: 2080, 2080, 562: 2080, 637: 2080, 2080, 640: 2080}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4278, 2691, 2692, 2690}, + {2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 13: 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 47: 2081, 464: 2081, 2081, 2081, 470: 2081, 2081, 2081, 474: 2081, 482: 2081, 2081, 493: 2081, 495: 2081, 498: 2081, 2081, 562: 2081, 637: 2081, 2081, 640: 2081}, // 1805 - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 532: 1999, 726: 4266}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3390, 653: 3392, 2676, 2677, 2675, 728: 3389, 860: 4267}, - {421, 421, 421, 421, 421, 421, 421, 421, 13: 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 461: 421, 421, 421, 467: 421, 421, 421, 421, 477: 421, 421, 487: 421, 421, 421, 494: 421, 556: 421, 634: 421, 637: 421, 421}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 4269}, - {422, 422, 422, 422, 422, 422, 422, 422, 13: 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 422, 461: 422, 422, 422, 467: 422, 422, 422, 422, 477: 422, 422, 487: 422, 422, 422, 494: 422, 556: 422, 634: 422, 637: 422, 422}, + {500: 2665, 724: 2664, 734: 4280}, + {2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 13: 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 47: 2082, 464: 2082, 2082, 2082, 470: 2082, 2082, 2082, 474: 2082, 482: 2082, 2082, 493: 2082, 495: 2082, 498: 2082, 2082, 562: 2082, 637: 2082, 2082, 640: 2082}, + {500: 2665, 724: 2664, 734: 4282}, + {2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 13: 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 47: 2083, 464: 2083, 2083, 2083, 470: 2083, 2083, 2083, 474: 2083, 482: 2083, 2083, 493: 2083, 495: 2083, 498: 2083, 2083, 562: 2083, 637: 2083, 2083, 640: 2083}, + {468: 2006, 489: 4192, 727: 4284}, // 1810 - {496: 2650, 725: 2649, 734: 4271}, - {2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 13: 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 2073, 461: 2073, 2073, 2073, 467: 2073, 2073, 2073, 2073, 477: 2073, 2073, 487: 2073, 2073, 2073, 494: 2073, 556: 2073, 634: 2073, 637: 2073, 2073}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4273, 2676, 2677, 2675}, - {2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 13: 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 461: 2074, 2074, 2074, 467: 2074, 2074, 2074, 2074, 477: 2074, 2074, 487: 2074, 2074, 2074, 494: 2074, 556: 2074, 634: 2074, 637: 2074, 2074}, - {496: 2650, 725: 2649, 734: 4275}, + {468: 4285}, + {2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 13: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 47: 2084, 464: 2084, 2084, 2084, 470: 2084, 2084, 2084, 474: 2084, 482: 2084, 2084, 493: 2084, 495: 2084, 498: 2084, 2084, 562: 2084, 637: 2084, 2084, 640: 2084}, + {468: 2006, 489: 4192, 727: 4287}, + {468: 4288}, + {2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 13: 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 2085, 47: 2085, 464: 2085, 2085, 2085, 470: 2085, 2085, 2085, 474: 2085, 482: 2085, 2085, 493: 2085, 495: 2085, 498: 2085, 2085, 562: 2085, 637: 2085, 2085, 640: 2085}, // 1815 - {2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 13: 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 461: 2075, 2075, 2075, 467: 2075, 2075, 2075, 2075, 477: 2075, 2075, 487: 2075, 2075, 2075, 494: 2075, 556: 2075, 634: 2075, 637: 2075, 2075}, - {496: 2650, 725: 2649, 734: 4277}, - {2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 13: 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 461: 2076, 2076, 2076, 467: 2076, 2076, 2076, 2076, 477: 2076, 2076, 487: 2076, 2076, 2076, 494: 2076, 556: 2076, 634: 2076, 637: 2076, 2076}, - {464: 1999, 485: 4187, 726: 4279}, - {464: 4280}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 4290}, + {2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 13: 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 2086, 47: 2086, 464: 2086, 2086, 2086, 470: 2086, 2086, 2086, 474: 2086, 482: 2086, 2086, 493: 2086, 495: 2086, 498: 2086, 2086, 562: 2086, 637: 2086, 2086, 640: 2086}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 727: 4294}, + {397, 397, 397, 397, 397, 397, 397, 397, 13: 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 464: 397, 397, 397, 470: 397, 397, 397, 474: 397, 482: 397, 397, 493: 397, 495: 397, 498: 397, 397, 562: 397, 637: 397, 397, 640: 397}, + {396, 396, 396, 396, 396, 396, 396, 396, 13: 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 464: 396, 396, 396, 470: 396, 396, 396, 474: 396, 482: 396, 396, 493: 396, 495: 396, 498: 396, 396, 562: 396, 637: 396, 396, 640: 396}, // 1820 - {2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 13: 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 461: 2077, 2077, 2077, 467: 2077, 2077, 2077, 2077, 477: 2077, 2077, 487: 2077, 2077, 2077, 494: 2077, 556: 2077, 634: 2077, 637: 2077, 2077}, - {464: 1999, 485: 4187, 726: 4282}, - {464: 4283}, - {2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 13: 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 461: 2078, 2078, 2078, 467: 2078, 2078, 2078, 2078, 477: 2078, 2078, 487: 2078, 2078, 2078, 494: 2078, 556: 2078, 634: 2078, 637: 2078, 2078}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 4285}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 4295}, + {2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 13: 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 2087, 47: 2087, 464: 2087, 2087, 2087, 470: 2087, 2087, 2087, 474: 2087, 482: 2087, 2087, 493: 2087, 495: 2087, 498: 2087, 2087, 562: 2087, 637: 2087, 2087, 640: 2087}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 4297}, + {2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 13: 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 2088, 47: 2088, 464: 2088, 2088, 2088, 470: 2088, 2088, 2088, 474: 2088, 482: 2088, 2088, 493: 2088, 495: 2088, 498: 2088, 2088, 562: 2088, 637: 2088, 2088, 640: 2088}, + {468: 4299}, // 1825 - {2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 13: 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 461: 2079, 2079, 2079, 467: 2079, 2079, 2079, 2079, 477: 2079, 2079, 487: 2079, 2079, 2079, 494: 2079, 556: 2079, 634: 2079, 637: 2079, 2079}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 726: 4289}, - {395, 395, 395, 395, 395, 395, 395, 395, 13: 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 461: 395, 395, 395, 467: 395, 395, 395, 395, 477: 395, 395, 487: 395, 395, 395, 494: 395, 556: 395, 634: 395, 637: 395, 395}, - {394, 394, 394, 394, 394, 394, 394, 394, 13: 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 461: 394, 394, 394, 467: 394, 394, 394, 394, 477: 394, 394, 487: 394, 394, 394, 494: 394, 556: 394, 634: 394, 637: 394, 394}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 4290}, + {2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 13: 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 2089, 47: 2089, 464: 2089, 2089, 2089, 470: 2089, 2089, 2089, 474: 2089, 482: 2089, 2089, 493: 2089, 495: 2089, 498: 2089, 2089, 562: 2089, 637: 2089, 2089, 640: 2089}, + {4: 4152, 4154, 391, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 69: 4123, 72: 4144, 4145, 81: 4146, 132: 4126, 193: 4111, 4130, 197: 4131, 209: 4125, 215: 4141, 226: 4120, 236: 4127, 240: 4122, 256: 4132, 264: 4128, 272: 4142, 4143, 279: 4112, 466: 4140, 471: 4151, 4188, 474: 2125, 488: 4147, 494: 4129, 4139, 4114, 498: 2125, 574: 4119, 579: 4115, 638: 2125, 640: 4157, 653: 4134, 660: 4121, 662: 4148, 670: 4133, 677: 4135, 680: 4116, 695: 4124, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4190, 858: 4138, 871: 4136, 907: 4113, 914: 4117, 977: 4301, 1122: 4118, 1149: 4137}, + {2354, 2354, 2354, 2354, 7: 2354, 483: 2354}, + {2368, 2368, 2368, 2368, 7: 2368, 483: 2368}, + {2367, 2367, 2367, 2367, 7: 2367, 483: 2367}, // 1830 - {2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 13: 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 2080, 461: 2080, 2080, 2080, 467: 2080, 2080, 2080, 2080, 477: 2080, 2080, 487: 2080, 2080, 2080, 494: 2080, 556: 2080, 634: 2080, 637: 2080, 2080}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 4292}, - {2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 13: 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 461: 2081, 2081, 2081, 467: 2081, 2081, 2081, 2081, 477: 2081, 2081, 487: 2081, 2081, 2081, 494: 2081, 556: 2081, 634: 2081, 637: 2081, 2081}, - {464: 4294}, - {2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 13: 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 2082, 461: 2082, 2082, 2082, 467: 2082, 2082, 2082, 2082, 477: 2082, 2082, 487: 2082, 2082, 2082, 494: 2082, 556: 2082, 634: 2082, 637: 2082, 2082}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 471: 4305, 654: 4306, 2691, 2692, 2690}, + {2370, 2370, 2370, 2370, 7: 2370, 81: 2370, 483: 2370}, + {2369, 2369, 2369, 2369, 7: 2369, 81: 2369, 483: 2369}, + {149: 4312, 230: 4309, 248: 4310, 250: 4311, 471: 4308}, + {2375, 2375, 2375, 2375, 7: 2375, 483: 2375, 488: 2375}, // 1835 - {4: 4147, 4149, 389, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 80: 4118, 83: 4139, 4140, 92: 4141, 132: 4121, 192: 4106, 4125, 196: 4126, 209: 4120, 215: 4136, 226: 4115, 236: 4122, 240: 4117, 256: 4127, 264: 4123, 271: 4137, 4138, 278: 4107, 463: 4135, 467: 4146, 469: 4183, 2118, 486: 4142, 488: 4134, 2118, 493: 4124, 501: 4109, 574: 4114, 4110, 637: 2118, 4152, 652: 4129, 659: 4116, 661: 4143, 669: 4128, 676: 4130, 679: 4111, 694: 4119, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4185, 858: 4133, 870: 4131, 907: 4108, 914: 4112, 974: 4296, 1118: 4113, 1145: 4132}, - {2338, 2338, 2338, 2338, 7: 2338, 478: 2338}, - {2352, 2352, 2352, 2352, 7: 2352, 478: 2352}, - {2351, 2351, 2351, 2351, 7: 2351, 478: 2351}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 467: 4300, 653: 4301, 2676, 2677, 2675}, + {2374, 2374, 2374, 2374, 7: 2374, 483: 2374, 488: 2374}, + {2373, 2373, 2373, 2373, 7: 2373, 483: 2373, 488: 2373}, + {2372, 2372, 2372, 2372, 7: 2372, 483: 2372, 488: 2372}, + {2371, 2371, 2371, 2371, 7: 2371, 483: 2371, 488: 2371}, + {2393, 2393, 2393, 2393, 7: 2393, 483: 2393}, // 1840 - {2354, 2354, 2354, 2354, 7: 2354, 92: 2354, 478: 2354}, - {2353, 2353, 2353, 2353, 7: 2353, 92: 2353, 478: 2353}, - {163: 4307, 230: 4304, 248: 4305, 250: 4306, 467: 4303}, - {2359, 2359, 2359, 2359, 7: 2359, 478: 2359, 486: 2359}, - {2358, 2358, 2358, 2358, 7: 2358, 478: 2358, 486: 2358}, + {2394, 2394, 2394, 2394, 7: 2394, 483: 2394}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4328, 2691, 2692, 2690}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4327}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4326}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4325}, // 1845 - {2357, 2357, 2357, 2357, 7: 2357, 478: 2357, 486: 2357}, - {2356, 2356, 2356, 2356, 7: 2356, 478: 2356, 486: 2356}, - {2355, 2355, 2355, 2355, 7: 2355, 478: 2355, 486: 2355}, - {2377, 2377, 2377, 2377, 7: 2377, 478: 2377}, - {2378, 2378, 2378, 2378, 7: 2378, 478: 2378}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4322, 2691, 2692, 2690}, + {2: 2366, 2366, 2366, 2366, 2366, 8: 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 48: 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 2366, 465: 2366, 473: 2366, 485: 2366, 558: 2366}, + {2: 2365, 2365, 2365, 2365, 2365, 8: 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 48: 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 2365, 465: 2365, 473: 2365, 485: 2365, 558: 2365}, + {641: 4323}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4324, 2691, 2692, 2690}, // 1850 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4323, 2676, 2677, 2675}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4322}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4321}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4320}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4317, 2676, 2677, 2675}, + {2399, 2399, 2399, 2399, 7: 2399, 483: 2399}, + {2400, 2400, 2400, 2400, 7: 2400, 483: 2400}, + {2401, 2401, 2401, 2401, 7: 2401, 483: 2401}, + {2402, 2402, 2402, 2402, 7: 2402, 483: 2402}, + {641: 4329}, // 1855 - {2: 2350, 2350, 2350, 2350, 2350, 8: 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 58: 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 462: 2350, 471: 2350, 482: 2350, 555: 2350}, - {2: 2349, 2349, 2349, 2349, 2349, 8: 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 58: 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 462: 2349, 471: 2349, 482: 2349, 555: 2349}, - {640: 4318}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4319, 2676, 2677, 2675}, - {2383, 2383, 2383, 2383, 7: 2383, 478: 2383}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4330, 2691, 2692, 2690}, + {2403, 2403, 2403, 2403, 7: 2403, 483: 2403}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4346}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4341, 2691, 2692, 2690}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4337, 2691, 2692, 2690}, // 1860 - {2384, 2384, 2384, 2384, 7: 2384, 478: 2384}, - {2385, 2385, 2385, 2385, 7: 2385, 478: 2385}, - {2386, 2386, 2386, 2386, 7: 2386, 478: 2386}, - {640: 4324}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4325, 2676, 2677, 2675}, + {2: 2361, 2361, 2361, 2361, 2361, 8: 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 48: 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 465: 2361, 558: 2361}, + {2: 433, 433, 433, 433, 433, 8: 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 48: 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433}, + {2: 432, 432, 432, 432, 432, 8: 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 48: 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, 432}, + {84: 4340, 87: 4339, 845: 4338}, + {2388, 2388, 2388, 2388, 7: 2388, 483: 2388}, // 1865 - {2387, 2387, 2387, 2387, 7: 2387, 478: 2387}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4341}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4336, 2676, 2677, 2675}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4332, 2676, 2677, 2675}, - {2: 2345, 2345, 2345, 2345, 2345, 8: 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 58: 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 462: 2345, 555: 2345}, + {1798, 1798, 1798, 1798, 1798, 7: 1798, 17: 1798, 47: 1798, 81: 1798, 1798, 1798, 1798, 1798, 87: 1798, 466: 1798, 473: 1798, 483: 1798, 488: 1798}, + {1797, 1797, 1797, 1797, 1797, 7: 1797, 17: 1797, 47: 1797, 81: 1797, 1797, 1797, 1797, 1797, 87: 1797, 466: 1797, 473: 1797, 483: 1797, 488: 1797}, + {147: 4343, 467: 4004, 469: 4003, 799: 4344, 922: 4342}, + {2390, 2390, 2390, 2390, 7: 2390, 483: 2390}, + {2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 2258, 47: 2258, 464: 2258, 467: 2258, 469: 2258, 2258, 2258, 474: 2258, 483: 2258, 2258, 565: 2258, 574: 2258, 576: 2258, 586: 2258, 616: 2258, 635: 2258, 2258}, // 1870 - {2: 431, 431, 431, 431, 431, 8: 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 58: 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, 431}, - {2: 430, 430, 430, 430, 430, 8: 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 58: 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430}, - {95: 4335, 97: 4334, 845: 4333}, - {2372, 2372, 2372, 2372, 7: 2372, 478: 2372}, - {1791, 1791, 1791, 1791, 1791, 7: 1791, 29: 1791, 57: 1791, 92: 1791, 1791, 1791, 1791, 1791, 1791, 463: 1791, 471: 1791, 478: 1791, 486: 1791}, + {147: 4345}, + {2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 47: 2257, 464: 2257, 467: 2257, 469: 2257, 2257, 2257, 474: 2257, 483: 2257, 2257, 565: 2257, 574: 2257, 576: 2257, 586: 2257, 616: 2257, 635: 2257, 2257}, + {496: 4347, 660: 4348}, + {471: 4350}, + {471: 4349}, // 1875 - {1790, 1790, 1790, 1790, 1790, 7: 1790, 29: 1790, 57: 1790, 92: 1790, 1790, 1790, 1790, 1790, 1790, 463: 1790, 471: 1790, 478: 1790, 486: 1790}, - {147: 4338, 465: 3986, 3985, 800: 4339, 922: 4337}, - {2374, 2374, 2374, 2374, 7: 2374, 478: 2374}, - {2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 57: 2242, 461: 2242, 465: 2242, 2242, 2242, 2242, 470: 2242, 478: 2242, 481: 2242, 566: 2242, 574: 2242, 576: 2242, 632: 2242, 2242, 635: 2242, 2242}, - {147: 4340}, + {2404, 2404, 2404, 2404, 7: 2404, 483: 2404}, + {465: 4352, 468: 3160, 477: 4355, 4354, 484: 3151, 500: 3155, 563: 3150, 3152, 566: 3154, 3153, 569: 3158, 572: 3159, 585: 3157, 703: 4353, 3156, 1118: 4351}, + {2406, 2406, 2406, 2406, 7: 2406, 483: 2406}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4358}, + {2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 47: 2174, 464: 2174, 467: 2174, 469: 2174, 2174, 2174, 474: 2174, 483: 2174, 2174, 565: 2174, 574: 2174, 576: 2174, 586: 2174, 616: 2174, 635: 2174, 2174}, // 1880 - {2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 57: 2241, 461: 2241, 465: 2241, 2241, 2241, 2241, 470: 2241, 478: 2241, 481: 2241, 566: 2241, 574: 2241, 576: 2241, 632: 2241, 2241, 635: 2241, 2241}, - {501: 4342, 659: 4343}, - {467: 4345}, - {467: 4344}, - {2388, 2388, 2388, 2388, 7: 2388, 478: 2388}, + {500: 3342, 566: 3344, 3343, 808: 4357}, + {500: 3342, 566: 3344, 3343, 808: 4356}, + {2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 2172, 47: 2172, 464: 2172, 467: 2172, 469: 2172, 2172, 2172, 474: 2172, 483: 2172, 2172, 565: 2172, 574: 2172, 576: 2172, 586: 2172, 616: 2172, 635: 2172, 2172}, + {2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 47: 2173, 464: 2173, 467: 2173, 469: 2173, 2173, 2173, 474: 2173, 483: 2173, 2173, 565: 2173, 574: 2173, 576: 2173, 586: 2173, 616: 2173, 635: 2173, 2173}, + {47: 4359, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 1885 - {462: 4347, 464: 3142, 474: 4350, 4349, 481: 3133, 496: 3137, 560: 3132, 3134, 3136, 3135, 565: 3140, 569: 3141, 582: 3139, 702: 4348, 3138, 1114: 4346}, - {2390, 2390, 2390, 2390, 7: 2390, 478: 2390}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4353}, - {2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 2164, 57: 2164, 461: 2164, 465: 2164, 2164, 2164, 2164, 470: 2164, 478: 2164, 481: 2164, 566: 2164, 574: 2164, 576: 2164, 632: 2164, 2164, 635: 2164, 2164}, - {496: 3324, 562: 3326, 3325, 809: 4352}, + {2405, 2405, 2405, 2405, 7: 2405, 483: 2405}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4361}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4364}, + {578: 4363}, + {2: 1823, 1823, 1823, 1823, 1823, 8: 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 48: 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 468: 1823, 561: 1823}, // 1890 - {496: 3324, 562: 3326, 3325, 809: 4351}, - {2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 2162, 57: 2162, 461: 2162, 465: 2162, 2162, 2162, 2162, 470: 2162, 478: 2162, 481: 2162, 566: 2162, 574: 2162, 576: 2162, 632: 2162, 2162, 635: 2162, 2162}, - {2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 2163, 57: 2163, 461: 2163, 465: 2163, 2163, 2163, 2163, 470: 2163, 478: 2163, 481: 2163, 566: 2163, 574: 2163, 576: 2163, 632: 2163, 2163, 635: 2163, 2163}, - {57: 4354, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2389, 2389, 2389, 2389, 7: 2389, 478: 2389}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4366, 836: 4365}, + {2360, 2360, 2360, 2360, 7: 2360, 4635, 4636, 483: 2360, 917: 4634}, + {10: 4368, 105: 4416, 109: 4417, 171: 4427, 4426, 4392, 175: 4407, 190: 4429, 214: 4428, 220: 4389, 301: 4396, 4388, 324: 4405, 350: 4412, 4411, 354: 4415, 387: 4423, 496: 4406, 498: 4410, 536: 4401, 638: 4409, 668: 4414, 4413, 671: 4390, 4395, 4393, 4386, 4380, 4394, 679: 4402, 681: 4387, 4419, 4381, 4382, 4383, 4384, 4385, 4408, 4421, 4425, 4420, 4379, 4424, 4391, 696: 4378, 4418, 4377, 4422, 889: 4397, 1141: 4399, 1164: 4376, 4403, 4373, 1184: 4371, 1198: 4374, 1200: 4375, 1219: 4372, 1235: 4398, 4369, 4400, 1293: 4370, 1305: 4404, 1308: 4367, 1333: 4430}, + {2221, 2221, 2221, 2221, 4510, 4516, 4504, 2221, 2221, 2221, 4508, 4517, 4515, 47: 2221, 464: 4509, 467: 4004, 469: 4003, 2228, 4507, 474: 4514, 483: 2221, 4503, 565: 2262, 574: 2351, 576: 4501, 586: 4506, 616: 4499, 635: 4521, 4518, 799: 4502, 821: 4511, 898: 4513, 916: 4519, 925: 4512, 944: 4505, 992: 4520, 4633}, + {2221, 2221, 2221, 2221, 4510, 4516, 4504, 2221, 2221, 2221, 4508, 4517, 4515, 47: 2221, 464: 4509, 467: 4004, 469: 4003, 2228, 4507, 474: 4514, 483: 2221, 4503, 565: 2262, 574: 2351, 576: 4501, 586: 4506, 616: 4499, 635: 4521, 4518, 799: 4502, 821: 4511, 898: 4513, 916: 4519, 925: 4512, 944: 4505, 992: 4520, 4500}, // 1895 - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4356}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4359}, - {573: 4358}, - {2: 1816, 1816, 1816, 1816, 1816, 8: 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 58: 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 1816, 464: 1816, 559: 1816}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4361, 836: 4360}, + {365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 47: 365, 464: 365, 467: 365, 469: 365, 365, 365, 474: 365, 483: 365, 365, 565: 365, 574: 365, 576: 365, 586: 365, 616: 365, 635: 365, 365}, + {364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 47: 364, 464: 364, 467: 364, 469: 364, 364, 364, 474: 364, 483: 364, 364, 565: 364, 574: 364, 576: 364, 586: 364, 616: 364, 635: 364, 364}, + {363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 47: 363, 464: 363, 467: 363, 469: 363, 363, 363, 474: 363, 483: 363, 363, 565: 363, 574: 363, 576: 363, 586: 363, 616: 363, 635: 363, 363}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 49: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 730: 280, 732: 280, 754: 3744, 775: 4497}, + {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 47: 275, 49: 275, 464: 275, 467: 275, 469: 275, 275, 275, 474: 275, 483: 275, 275, 565: 275, 574: 275, 576: 275, 586: 275, 616: 275, 635: 275, 275, 730: 275, 732: 275, 864: 4496}, // 1900 - {2344, 2344, 2344, 2344, 7: 2344, 4618, 4619, 478: 2344, 917: 4617}, - {10: 4363, 105: 4411, 109: 4412, 171: 4422, 4421, 4387, 175: 4402, 189: 4424, 214: 4423, 220: 4384, 298: 4391, 4383, 319: 4400, 345: 4407, 4406, 349: 4410, 383: 4418, 489: 4405, 501: 4401, 532: 4396, 637: 4404, 667: 4409, 4408, 670: 4385, 4390, 4388, 4381, 4375, 4389, 678: 4397, 680: 4382, 4414, 4376, 4377, 4378, 4379, 4380, 4403, 4416, 4420, 4415, 4374, 4419, 4386, 695: 4373, 4413, 4372, 4417, 889: 4392, 1137: 4394, 1159: 4371, 4398, 4368, 1179: 4366, 1193: 4369, 1195: 4370, 1214: 4367, 1231: 4393, 4364, 4395, 1289: 4365, 1301: 4399, 1304: 4362, 1329: 4425}, - {2205, 2205, 2205, 2205, 4505, 4511, 4499, 2205, 2205, 2205, 4503, 4512, 4510, 57: 2205, 461: 4504, 465: 3986, 3985, 4502, 2212, 470: 4509, 478: 2205, 481: 4498, 566: 2246, 574: 2335, 576: 4496, 632: 4501, 4494, 635: 4516, 4513, 800: 4497, 822: 4506, 898: 4508, 916: 4514, 925: 4507, 941: 4500, 988: 4515, 4616}, - {2205, 2205, 2205, 2205, 4505, 4511, 4499, 2205, 2205, 2205, 4503, 4512, 4510, 57: 2205, 461: 4504, 465: 3986, 3985, 4502, 2212, 470: 4509, 478: 2205, 481: 4498, 566: 2246, 574: 2335, 576: 4496, 632: 4501, 4494, 635: 4516, 4513, 800: 4497, 822: 4506, 898: 4508, 916: 4514, 925: 4507, 941: 4500, 988: 4515, 4495}, - {363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 57: 363, 461: 363, 465: 363, 363, 363, 363, 470: 363, 478: 363, 481: 363, 566: 363, 574: 363, 576: 363, 632: 363, 363, 635: 363, 363}, + {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 47: 273, 49: 273, 464: 273, 3730, 467: 273, 469: 273, 273, 273, 474: 273, 483: 273, 273, 565: 273, 574: 273, 576: 273, 586: 273, 616: 273, 635: 273, 273, 730: 273, 732: 273, 754: 3731, 892: 4494, 897: 3732}, + {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 47: 273, 49: 273, 464: 273, 3730, 467: 273, 469: 273, 273, 273, 474: 273, 483: 273, 273, 565: 273, 574: 273, 576: 273, 586: 273, 616: 273, 635: 273, 273, 730: 273, 732: 273, 754: 3731, 892: 4492, 897: 3732}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4491}, + {357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 47: 357, 49: 357, 464: 357, 357, 467: 357, 469: 357, 357, 357, 474: 357, 483: 357, 357, 565: 357, 574: 357, 576: 357, 586: 357, 616: 357, 635: 357, 357, 730: 357, 732: 357}, + {356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 47: 356, 49: 356, 464: 356, 356, 467: 356, 469: 356, 356, 356, 474: 356, 483: 356, 356, 565: 356, 574: 356, 576: 356, 586: 356, 616: 356, 635: 356, 356, 730: 356, 732: 356}, // 1905 - {362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 57: 362, 461: 362, 465: 362, 362, 362, 362, 470: 362, 478: 362, 481: 362, 566: 362, 574: 362, 576: 362, 632: 362, 362, 635: 362, 362}, - {361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 57: 361, 461: 361, 465: 361, 361, 361, 361, 470: 361, 478: 361, 481: 361, 566: 361, 574: 361, 576: 361, 632: 361, 361, 635: 361, 361}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 60: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 729: 278, 731: 278, 750: 3726, 776: 4492}, - {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 57: 273, 60: 273, 461: 273, 465: 273, 273, 273, 273, 470: 273, 478: 273, 481: 273, 566: 273, 574: 273, 576: 273, 632: 273, 273, 635: 273, 273, 729: 273, 731: 273, 863: 4491}, - {271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 57: 271, 60: 271, 461: 271, 3712, 465: 271, 271, 271, 271, 470: 271, 478: 271, 481: 271, 566: 271, 574: 271, 576: 271, 632: 271, 271, 635: 271, 271, 729: 271, 731: 271, 750: 3713, 892: 4489, 897: 3714}, + {355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 47: 355, 49: 355, 464: 355, 355, 467: 355, 469: 355, 355, 355, 474: 355, 483: 355, 355, 565: 355, 574: 355, 576: 355, 586: 355, 616: 355, 635: 355, 355, 730: 355, 732: 355}, + {354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 47: 354, 49: 354, 464: 354, 354, 467: 354, 469: 354, 354, 354, 474: 354, 483: 354, 354, 565: 354, 574: 354, 576: 354, 586: 354, 616: 354, 635: 354, 354, 730: 354, 732: 354}, + {353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 47: 353, 49: 353, 464: 353, 353, 467: 353, 469: 353, 353, 353, 474: 353, 483: 353, 353, 565: 353, 574: 353, 576: 353, 586: 353, 616: 353, 635: 353, 353, 730: 353, 732: 353}, + {352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 47: 352, 49: 352, 464: 352, 352, 467: 352, 469: 352, 352, 352, 474: 352, 483: 352, 352, 565: 352, 574: 352, 576: 352, 586: 352, 616: 352, 635: 352, 352, 730: 352, 732: 352}, + {351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 47: 351, 49: 351, 464: 351, 351, 467: 351, 469: 351, 351, 351, 474: 351, 483: 351, 351, 565: 351, 574: 351, 576: 351, 586: 351, 616: 351, 635: 351, 351, 730: 351, 732: 351}, // 1910 - {271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 57: 271, 60: 271, 461: 271, 3712, 465: 271, 271, 271, 271, 470: 271, 478: 271, 481: 271, 566: 271, 574: 271, 576: 271, 632: 271, 271, 635: 271, 271, 729: 271, 731: 271, 750: 3713, 892: 4487, 897: 3714}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4486}, - {355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 355, 57: 355, 60: 355, 461: 355, 355, 465: 355, 355, 355, 355, 470: 355, 478: 355, 481: 355, 566: 355, 574: 355, 576: 355, 632: 355, 355, 635: 355, 355, 729: 355, 731: 355}, - {354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 57: 354, 60: 354, 461: 354, 354, 465: 354, 354, 354, 354, 470: 354, 478: 354, 481: 354, 566: 354, 574: 354, 576: 354, 632: 354, 354, 635: 354, 354, 729: 354, 731: 354}, - {353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 57: 353, 60: 353, 461: 353, 353, 465: 353, 353, 353, 353, 470: 353, 478: 353, 481: 353, 566: 353, 574: 353, 576: 353, 632: 353, 353, 635: 353, 353, 729: 353, 731: 353}, + {350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 47: 350, 49: 350, 464: 350, 350, 467: 350, 469: 350, 350, 350, 474: 350, 483: 350, 350, 565: 350, 574: 350, 576: 350, 586: 350, 616: 350, 635: 350, 350, 730: 350, 732: 350}, + {349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 47: 349, 49: 349, 464: 349, 349, 467: 349, 469: 349, 349, 349, 474: 349, 483: 349, 349, 565: 349, 574: 349, 576: 349, 586: 349, 616: 349, 635: 349, 349, 730: 349, 732: 349}, + {348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 47: 348, 49: 348, 464: 348, 348, 467: 348, 469: 348, 348, 348, 474: 348, 483: 348, 348, 565: 348, 574: 348, 576: 348, 586: 348, 616: 348, 635: 348, 348, 730: 348, 732: 348}, + {347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 47: 347, 49: 347, 464: 347, 347, 467: 347, 469: 347, 347, 347, 474: 347, 483: 347, 347, 565: 347, 574: 347, 576: 347, 586: 347, 616: 347, 635: 347, 347, 730: 347, 732: 347}, + {346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 47: 346, 49: 346, 464: 346, 467: 346, 469: 346, 346, 346, 474: 346, 483: 346, 346, 565: 346, 574: 346, 576: 346, 586: 346, 616: 346, 635: 346, 346, 730: 346, 732: 346}, // 1915 - {352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 57: 352, 60: 352, 461: 352, 352, 465: 352, 352, 352, 352, 470: 352, 478: 352, 481: 352, 566: 352, 574: 352, 576: 352, 632: 352, 352, 635: 352, 352, 729: 352, 731: 352}, - {351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 57: 351, 60: 351, 461: 351, 351, 465: 351, 351, 351, 351, 470: 351, 478: 351, 481: 351, 566: 351, 574: 351, 576: 351, 632: 351, 351, 635: 351, 351, 729: 351, 731: 351}, - {350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 57: 350, 60: 350, 461: 350, 350, 465: 350, 350, 350, 350, 470: 350, 478: 350, 481: 350, 566: 350, 574: 350, 576: 350, 632: 350, 350, 635: 350, 350, 729: 350, 731: 350}, - {349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 57: 349, 60: 349, 461: 349, 349, 465: 349, 349, 349, 349, 470: 349, 478: 349, 481: 349, 566: 349, 574: 349, 576: 349, 632: 349, 349, 635: 349, 349, 729: 349, 731: 349}, - {348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 57: 348, 60: 348, 461: 348, 348, 465: 348, 348, 348, 348, 470: 348, 478: 348, 481: 348, 566: 348, 574: 348, 576: 348, 632: 348, 348, 635: 348, 348, 729: 348, 731: 348}, + {345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 47: 345, 49: 345, 464: 345, 467: 345, 469: 345, 345, 345, 474: 345, 483: 345, 345, 565: 345, 574: 345, 576: 345, 586: 345, 616: 345, 635: 345, 345, 730: 345, 732: 345}, + {341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 47: 341, 49: 341, 464: 341, 341, 467: 341, 469: 341, 341, 341, 474: 341, 483: 341, 341, 565: 341, 574: 341, 576: 341, 586: 341, 616: 341, 635: 341, 341, 730: 341, 732: 341}, + {340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 47: 340, 49: 340, 464: 340, 340, 467: 340, 469: 340, 340, 340, 474: 340, 483: 340, 340, 565: 340, 574: 340, 576: 340, 586: 340, 616: 340, 635: 340, 340, 730: 340, 732: 340}, + {339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 47: 339, 49: 339, 464: 339, 339, 467: 339, 469: 339, 339, 339, 474: 339, 483: 339, 339, 565: 339, 574: 339, 576: 339, 586: 339, 616: 339, 635: 339, 339, 730: 339, 732: 339}, + {338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 47: 338, 49: 338, 464: 338, 338, 467: 338, 469: 338, 338, 338, 474: 338, 483: 338, 338, 565: 338, 574: 338, 576: 338, 586: 338, 616: 338, 635: 338, 338, 730: 338, 732: 338}, // 1920 - {347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 57: 347, 60: 347, 461: 347, 347, 465: 347, 347, 347, 347, 470: 347, 478: 347, 481: 347, 566: 347, 574: 347, 576: 347, 632: 347, 347, 635: 347, 347, 729: 347, 731: 347}, - {346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 57: 346, 60: 346, 461: 346, 346, 465: 346, 346, 346, 346, 470: 346, 478: 346, 481: 346, 566: 346, 574: 346, 576: 346, 632: 346, 346, 635: 346, 346, 729: 346, 731: 346}, - {345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 57: 345, 60: 345, 461: 345, 345, 465: 345, 345, 345, 345, 470: 345, 478: 345, 481: 345, 566: 345, 574: 345, 576: 345, 632: 345, 345, 635: 345, 345, 729: 345, 731: 345}, - {344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 57: 344, 60: 344, 461: 344, 465: 344, 344, 344, 344, 470: 344, 478: 344, 481: 344, 566: 344, 574: 344, 576: 344, 632: 344, 344, 635: 344, 344, 729: 344, 731: 344}, - {343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 57: 343, 60: 343, 461: 343, 465: 343, 343, 343, 343, 470: 343, 478: 343, 481: 343, 566: 343, 574: 343, 576: 343, 632: 343, 343, 635: 343, 343, 729: 343, 731: 343}, + {337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 47: 337, 49: 337, 464: 337, 337, 467: 337, 469: 337, 337, 337, 474: 337, 483: 337, 337, 565: 337, 574: 337, 576: 337, 586: 337, 616: 337, 635: 337, 337, 730: 337, 732: 337}, + {336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 47: 336, 49: 336, 464: 336, 336, 467: 336, 469: 336, 336, 336, 474: 336, 483: 336, 336, 565: 336, 574: 336, 576: 336, 586: 336, 616: 336, 635: 336, 336, 730: 336, 732: 336, 1259: 4490}, + {334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 47: 334, 464: 334, 334, 467: 334, 469: 334, 334, 334, 474: 334, 483: 334, 334, 565: 334, 574: 334, 576: 334, 586: 334, 616: 334, 635: 334, 334}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 3743, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 754: 4487, 762: 3751, 789: 4488}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 3743, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 754: 4484, 762: 3751, 789: 4485}, // 1925 - {339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 57: 339, 60: 339, 461: 339, 339, 465: 339, 339, 339, 339, 470: 339, 478: 339, 481: 339, 566: 339, 574: 339, 576: 339, 632: 339, 339, 635: 339, 339, 729: 339, 731: 339}, - {338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 57: 338, 60: 338, 461: 338, 338, 465: 338, 338, 338, 338, 470: 338, 478: 338, 481: 338, 566: 338, 574: 338, 576: 338, 632: 338, 338, 635: 338, 338, 729: 338, 731: 338}, - {337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 57: 337, 60: 337, 461: 337, 337, 465: 337, 337, 337, 337, 470: 337, 478: 337, 481: 337, 566: 337, 574: 337, 576: 337, 632: 337, 337, 635: 337, 337, 729: 337, 731: 337}, - {336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 57: 336, 60: 336, 461: 336, 336, 465: 336, 336, 336, 336, 470: 336, 478: 336, 481: 336, 566: 336, 574: 336, 576: 336, 632: 336, 336, 635: 336, 336, 729: 336, 731: 336}, - {335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 57: 335, 60: 335, 461: 335, 335, 465: 335, 335, 335, 335, 470: 335, 478: 335, 481: 335, 566: 335, 574: 335, 576: 335, 632: 335, 335, 635: 335, 335, 729: 335, 731: 335}, + {465: 3743, 754: 4482}, + {465: 3743, 754: 4480}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4479}, + {465: 3743, 754: 4478}, + {325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 47: 325, 464: 325, 467: 325, 469: 325, 325, 325, 474: 325, 483: 325, 325, 565: 325, 574: 325, 576: 325, 586: 325, 616: 325, 635: 325, 325}, // 1930 - {334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 57: 334, 60: 334, 461: 334, 334, 465: 334, 334, 334, 334, 470: 334, 478: 334, 481: 334, 566: 334, 574: 334, 576: 334, 632: 334, 334, 635: 334, 334, 729: 334, 731: 334, 1255: 4485}, - {332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 57: 332, 461: 332, 332, 465: 332, 332, 332, 332, 470: 332, 478: 332, 481: 332, 566: 332, 574: 332, 576: 332, 632: 332, 332, 635: 332, 332}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 3725, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 750: 4482, 762: 3733, 790: 4483}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 3725, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 750: 4479, 762: 3733, 790: 4480}, - {462: 3725, 750: 4477}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 101: 4459, 4461, 104: 4460, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4458, 872: 4477}, + {465: 4473}, + {465: 4463}, + {321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 47: 321, 464: 321, 467: 321, 469: 321, 321, 321, 474: 321, 483: 321, 321, 565: 321, 574: 321, 576: 321, 586: 321, 616: 321, 635: 321, 321}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 101: 4459, 4461, 104: 4460, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 4456, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 4455, 668: 4414, 4413, 679: 4457, 762: 3751, 789: 4458, 872: 4454, 1141: 4453}, // 1935 - {462: 3725, 750: 4475}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4474}, - {462: 3725, 750: 4473}, - {323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 57: 323, 461: 323, 465: 323, 323, 323, 323, 470: 323, 478: 323, 481: 323, 566: 323, 574: 323, 576: 323, 632: 323, 323, 635: 323, 323}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 101: 4454, 4456, 104: 4455, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4453, 871: 4472}, + {318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 14: 318, 47: 318, 464: 318, 318, 467: 318, 469: 318, 318, 318, 474: 318, 483: 318, 318, 498: 318, 536: 318, 565: 318, 574: 318, 576: 318, 586: 318, 616: 318, 635: 318, 318, 638: 318, 832: 4452}, + {317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 14: 317, 47: 317, 464: 317, 317, 467: 317, 469: 317, 317, 317, 474: 317, 483: 317, 317, 498: 317, 536: 317, 565: 317, 574: 317, 576: 317, 586: 317, 616: 317, 635: 317, 317, 638: 317, 832: 4451}, + {316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 14: 316, 47: 316, 464: 316, 316, 467: 316, 469: 316, 316, 316, 474: 316, 483: 316, 316, 498: 316, 536: 316, 565: 316, 574: 316, 576: 316, 586: 316, 616: 316, 635: 316, 316, 638: 316, 668: 4449, 4448, 832: 4450}, + {498: 4443, 638: 4442, 668: 4445, 4444}, + {311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 14: 311, 47: 311, 101: 311, 311, 104: 311, 464: 311, 311, 467: 311, 469: 311, 311, 311, 474: 311, 483: 311, 311, 498: 311, 536: 311, 565: 311, 574: 311, 576: 311, 586: 311, 616: 311, 635: 311, 311, 638: 311}, // 1940 - {462: 4468}, - {462: 4458}, - {319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 57: 319, 461: 319, 465: 319, 319, 319, 319, 470: 319, 478: 319, 481: 319, 566: 319, 574: 319, 576: 319, 632: 319, 319, 635: 319, 319}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 101: 4454, 4456, 104: 4455, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 4451, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 4450, 667: 4409, 4408, 678: 4452, 762: 3733, 790: 4453, 871: 4449, 1137: 4448}, - {316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 57: 316, 461: 316, 316, 465: 316, 316, 316, 316, 470: 316, 478: 316, 481: 316, 489: 316, 532: 316, 566: 316, 574: 316, 576: 316, 632: 316, 316, 635: 316, 316, 316, 833: 4447}, + {310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 14: 310, 47: 310, 101: 310, 310, 104: 310, 464: 310, 310, 467: 310, 469: 310, 310, 310, 474: 310, 483: 310, 310, 498: 310, 536: 310, 565: 310, 574: 310, 576: 310, 586: 310, 616: 310, 635: 310, 310, 638: 310}, + {465: 307}, + {301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 47: 301, 49: 301, 464: 301, 301, 467: 301, 469: 301, 301, 301, 474: 301, 483: 301, 301, 565: 301, 574: 301, 576: 301, 586: 301, 616: 301, 635: 301, 301, 730: 301, 732: 301}, + {300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 47: 300, 49: 300, 464: 300, 300, 467: 300, 469: 300, 300, 300, 474: 300, 483: 300, 300, 565: 300, 574: 300, 576: 300, 586: 300, 616: 300, 635: 300, 300, 730: 300, 732: 300}, + {299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 47: 299, 464: 299, 467: 299, 469: 299, 299, 299, 474: 299, 483: 299, 299, 565: 299, 574: 299, 576: 299, 586: 299, 616: 299, 635: 299, 299}, // 1945 - {315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 57: 315, 461: 315, 315, 465: 315, 315, 315, 315, 470: 315, 478: 315, 481: 315, 489: 315, 532: 315, 566: 315, 574: 315, 576: 315, 632: 315, 315, 635: 315, 315, 315, 833: 4446}, - {314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 57: 314, 461: 314, 314, 465: 314, 314, 314, 314, 470: 314, 478: 314, 481: 314, 489: 314, 532: 314, 566: 314, 574: 314, 576: 314, 632: 314, 314, 635: 314, 314, 314, 667: 4444, 4443, 833: 4445}, - {489: 4438, 637: 4437, 667: 4440, 4439}, - {309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 57: 309, 101: 309, 309, 104: 309, 461: 309, 309, 465: 309, 309, 309, 309, 470: 309, 478: 309, 481: 309, 489: 309, 532: 309, 566: 309, 574: 309, 576: 309, 632: 309, 309, 635: 309, 309, 309}, - {308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 57: 308, 101: 308, 308, 104: 308, 461: 308, 308, 465: 308, 308, 308, 308, 470: 308, 478: 308, 481: 308, 489: 308, 532: 308, 566: 308, 574: 308, 576: 308, 632: 308, 308, 635: 308, 308, 308}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4441}, + {297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 47: 297, 464: 297, 467: 297, 469: 297, 297, 297, 474: 297, 483: 297, 297, 565: 297, 574: 297, 576: 297, 586: 297, 616: 297, 635: 297, 297}, + {296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 47: 296, 464: 296, 467: 296, 469: 296, 296, 296, 474: 296, 483: 296, 296, 565: 296, 574: 296, 576: 296, 586: 296, 616: 296, 635: 296, 296}, + {294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 14: 294, 47: 294, 101: 294, 294, 104: 294, 464: 294, 467: 294, 469: 294, 294, 294, 474: 294, 483: 294, 294, 498: 294, 536: 294, 565: 294, 574: 294, 576: 294, 586: 294, 616: 294, 635: 294, 294, 638: 294}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 14: 280, 47: 280, 101: 280, 280, 104: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 498: 280, 536: 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 638: 280, 754: 3744, 775: 4440}, // 1950 - {462: 305}, - {299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 57: 299, 60: 299, 461: 299, 299, 465: 299, 299, 299, 299, 470: 299, 478: 299, 481: 299, 566: 299, 574: 299, 576: 299, 632: 299, 299, 635: 299, 299, 729: 299, 731: 299}, - {298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 57: 298, 60: 298, 461: 298, 298, 465: 298, 298, 298, 298, 470: 298, 478: 298, 481: 298, 566: 298, 574: 298, 576: 298, 632: 298, 298, 635: 298, 298, 729: 298, 731: 298}, - {297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 57: 297, 461: 297, 465: 297, 297, 297, 297, 470: 297, 478: 297, 481: 297, 566: 297, 574: 297, 576: 297, 632: 297, 297, 635: 297, 297}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4436}, + {292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 14: 292, 47: 292, 101: 292, 292, 104: 292, 464: 292, 467: 292, 469: 292, 292, 292, 474: 292, 483: 292, 292, 498: 292, 536: 292, 565: 292, 574: 292, 576: 292, 586: 292, 616: 292, 635: 292, 292, 638: 292}, + {291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 14: 291, 47: 291, 101: 291, 291, 104: 291, 464: 291, 467: 291, 469: 291, 291, 291, 474: 291, 483: 291, 291, 498: 291, 536: 291, 565: 291, 574: 291, 576: 291, 586: 291, 616: 291, 635: 291, 291, 638: 291}, + {286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 47: 286, 464: 286, 467: 286, 469: 286, 286, 286, 474: 286, 483: 286, 286, 565: 286, 574: 286, 576: 286, 586: 286, 616: 286, 635: 286, 286}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4439}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4438}, // 1955 - {295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 57: 295, 461: 295, 465: 295, 295, 295, 295, 470: 295, 478: 295, 481: 295, 566: 295, 574: 295, 576: 295, 632: 295, 295, 635: 295, 295}, - {294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 57: 294, 461: 294, 465: 294, 294, 294, 294, 470: 294, 478: 294, 481: 294, 566: 294, 574: 294, 576: 294, 632: 294, 294, 635: 294, 294}, - {292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 57: 292, 101: 292, 292, 104: 292, 461: 292, 465: 292, 292, 292, 292, 470: 292, 478: 292, 481: 292, 489: 292, 532: 292, 566: 292, 574: 292, 576: 292, 632: 292, 292, 635: 292, 292, 292}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 101: 278, 278, 104: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 489: 278, 532: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 278, 750: 3726, 776: 4435}, - {290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 57: 290, 101: 290, 290, 104: 290, 461: 290, 465: 290, 290, 290, 290, 470: 290, 478: 290, 481: 290, 489: 290, 532: 290, 566: 290, 574: 290, 576: 290, 632: 290, 290, 635: 290, 290, 290}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4437}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 49: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 730: 280, 732: 280, 754: 3744, 775: 4431}, + {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 47: 275, 49: 275, 464: 275, 467: 275, 469: 275, 275, 275, 474: 275, 483: 275, 275, 565: 275, 574: 275, 576: 275, 586: 275, 616: 275, 635: 275, 275, 730: 275, 732: 275, 864: 4432}, + {282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 47: 282, 49: 4434, 464: 282, 467: 282, 469: 282, 282, 282, 474: 282, 483: 282, 282, 565: 282, 574: 282, 576: 282, 586: 282, 616: 282, 635: 282, 282, 730: 4433, 732: 4435, 863: 4436}, + {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 47: 278, 49: 278, 464: 278, 467: 278, 469: 278, 278, 278, 474: 278, 483: 278, 278, 565: 278, 574: 278, 576: 278, 586: 278, 616: 278, 635: 278, 278, 730: 278, 732: 278}, // 1960 - {289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 57: 289, 101: 289, 289, 104: 289, 461: 289, 465: 289, 289, 289, 289, 470: 289, 478: 289, 481: 289, 489: 289, 532: 289, 566: 289, 574: 289, 576: 289, 632: 289, 289, 635: 289, 289, 289}, - {284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 57: 284, 461: 284, 465: 284, 284, 284, 284, 470: 284, 478: 284, 481: 284, 566: 284, 574: 284, 576: 284, 632: 284, 284, 635: 284, 284}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4434}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4433}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4432}, + {277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 47: 277, 49: 277, 464: 277, 467: 277, 469: 277, 277, 277, 474: 277, 483: 277, 277, 565: 277, 574: 277, 576: 277, 586: 277, 616: 277, 635: 277, 277, 730: 277, 732: 277}, + {276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 47: 276, 49: 276, 464: 276, 467: 276, 469: 276, 276, 276, 474: 276, 483: 276, 276, 565: 276, 574: 276, 576: 276, 586: 276, 616: 276, 635: 276, 276, 730: 276, 732: 276}, + {274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 47: 274, 49: 274, 464: 274, 467: 274, 469: 274, 274, 274, 474: 274, 483: 274, 274, 565: 274, 574: 274, 576: 274, 586: 274, 616: 274, 635: 274, 274, 730: 274, 732: 274}, + {283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 47: 283, 464: 283, 467: 283, 469: 283, 283, 283, 474: 283, 483: 283, 283, 565: 283, 574: 283, 576: 283, 586: 283, 616: 283, 635: 283, 283}, + {284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 47: 284, 464: 284, 467: 284, 469: 284, 284, 284, 474: 284, 483: 284, 284, 565: 284, 574: 284, 576: 284, 586: 284, 616: 284, 635: 284, 284}, // 1965 - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 60: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 729: 278, 731: 278, 750: 3726, 776: 4426}, - {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 57: 273, 60: 273, 461: 273, 465: 273, 273, 273, 273, 470: 273, 478: 273, 481: 273, 566: 273, 574: 273, 576: 273, 632: 273, 273, 635: 273, 273, 729: 273, 731: 273, 863: 4427}, - {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 57: 280, 60: 4429, 461: 280, 465: 280, 280, 280, 280, 470: 280, 478: 280, 481: 280, 566: 280, 574: 280, 576: 280, 632: 280, 280, 635: 280, 280, 729: 4428, 731: 4430, 862: 4431}, - {276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 57: 276, 60: 276, 461: 276, 465: 276, 276, 276, 276, 470: 276, 478: 276, 481: 276, 566: 276, 574: 276, 576: 276, 632: 276, 276, 635: 276, 276, 729: 276, 731: 276}, - {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 57: 275, 60: 275, 461: 275, 465: 275, 275, 275, 275, 470: 275, 478: 275, 481: 275, 566: 275, 574: 275, 576: 275, 632: 275, 275, 635: 275, 275, 729: 275, 731: 275}, + {285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 47: 285, 464: 285, 467: 285, 469: 285, 285, 285, 474: 285, 483: 285, 285, 565: 285, 574: 285, 576: 285, 586: 285, 616: 285, 635: 285, 285}, + {293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 14: 293, 47: 293, 101: 293, 293, 104: 293, 464: 293, 467: 293, 469: 293, 293, 293, 474: 293, 483: 293, 293, 498: 293, 536: 293, 565: 293, 574: 293, 576: 293, 586: 293, 616: 293, 635: 293, 293, 638: 293}, + {298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 47: 298, 464: 298, 467: 298, 469: 298, 298, 298, 474: 298, 483: 298, 298, 565: 298, 574: 298, 576: 298, 586: 298, 616: 298, 635: 298, 298}, + {315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 14: 315, 47: 315, 464: 315, 315, 467: 315, 469: 315, 315, 315, 474: 315, 483: 315, 315, 498: 315, 536: 315, 565: 315, 574: 315, 576: 315, 586: 315, 616: 315, 635: 315, 315, 638: 315, 832: 4447}, + {314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 14: 314, 47: 314, 464: 314, 314, 467: 314, 469: 314, 314, 314, 474: 314, 483: 314, 314, 498: 314, 536: 314, 565: 314, 574: 314, 576: 314, 586: 314, 616: 314, 635: 314, 314, 638: 314, 832: 4446}, // 1970 - {274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 57: 274, 60: 274, 461: 274, 465: 274, 274, 274, 274, 470: 274, 478: 274, 481: 274, 566: 274, 574: 274, 576: 274, 632: 274, 274, 635: 274, 274, 729: 274, 731: 274}, - {272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 57: 272, 60: 272, 461: 272, 465: 272, 272, 272, 272, 470: 272, 478: 272, 481: 272, 566: 272, 574: 272, 576: 272, 632: 272, 272, 635: 272, 272, 729: 272, 731: 272}, - {281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 57: 281, 461: 281, 465: 281, 281, 281, 281, 470: 281, 478: 281, 481: 281, 566: 281, 574: 281, 576: 281, 632: 281, 281, 635: 281, 281}, - {282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 57: 282, 461: 282, 465: 282, 282, 282, 282, 470: 282, 478: 282, 481: 282, 566: 282, 574: 282, 576: 282, 632: 282, 282, 635: 282, 282}, - {283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 57: 283, 461: 283, 465: 283, 283, 283, 283, 470: 283, 478: 283, 481: 283, 566: 283, 574: 283, 576: 283, 632: 283, 283, 635: 283, 283}, + {465: 309}, + {465: 308}, + {465: 303}, + {465: 304}, + {465: 306}, // 1975 - {291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 57: 291, 101: 291, 291, 104: 291, 461: 291, 465: 291, 291, 291, 291, 470: 291, 478: 291, 481: 291, 489: 291, 532: 291, 566: 291, 574: 291, 576: 291, 632: 291, 291, 635: 291, 291, 291}, - {296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 57: 296, 461: 296, 465: 296, 296, 296, 296, 470: 296, 478: 296, 481: 296, 566: 296, 574: 296, 576: 296, 632: 296, 296, 635: 296, 296}, - {313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 57: 313, 461: 313, 313, 465: 313, 313, 313, 313, 470: 313, 478: 313, 481: 313, 489: 313, 532: 313, 566: 313, 574: 313, 576: 313, 632: 313, 313, 635: 313, 313, 313, 833: 4442}, - {312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 57: 312, 461: 312, 312, 465: 312, 312, 312, 312, 470: 312, 478: 312, 481: 312, 489: 312, 532: 312, 566: 312, 574: 312, 576: 312, 632: 312, 312, 635: 312, 312, 312, 833: 4441}, - {462: 307}, + {465: 305}, + {465: 302}, + {312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 14: 312, 47: 312, 101: 312, 312, 104: 312, 464: 312, 312, 467: 312, 469: 312, 312, 312, 474: 312, 483: 312, 312, 498: 312, 536: 312, 565: 312, 574: 312, 576: 312, 586: 312, 616: 312, 635: 312, 312, 638: 312}, + {313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 14: 313, 47: 313, 101: 313, 313, 104: 313, 464: 313, 313, 467: 313, 469: 313, 313, 313, 474: 313, 483: 313, 313, 498: 313, 536: 313, 565: 313, 574: 313, 576: 313, 586: 313, 616: 313, 635: 313, 313, 638: 313}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 101: 4459, 4461, 104: 4460, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4458, 872: 4462}, // 1980 - {462: 306}, - {462: 301}, - {462: 302}, - {462: 304}, - {462: 303}, + {319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 47: 319, 464: 319, 467: 319, 469: 319, 319, 319, 474: 319, 483: 319, 319, 565: 319, 574: 319, 576: 319, 586: 319, 616: 319, 635: 319, 319}, + {496: 3756, 832: 4452}, + {496: 3755, 832: 4451}, + {295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 47: 295, 464: 295, 467: 295, 469: 295, 295, 295, 474: 295, 483: 295, 295, 565: 295, 574: 295, 576: 295, 586: 295, 616: 295, 635: 295, 295}, + {290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 47: 290, 464: 290, 467: 290, 469: 290, 290, 290, 474: 290, 483: 290, 290, 565: 290, 574: 290, 576: 290, 586: 290, 616: 290, 635: 290, 290}, // 1985 - {462: 300}, - {310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 57: 310, 101: 310, 310, 104: 310, 461: 310, 310, 465: 310, 310, 310, 310, 470: 310, 478: 310, 481: 310, 489: 310, 532: 310, 566: 310, 574: 310, 576: 310, 632: 310, 310, 635: 310, 310, 310}, - {311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 57: 311, 101: 311, 311, 104: 311, 461: 311, 311, 465: 311, 311, 311, 311, 470: 311, 478: 311, 481: 311, 489: 311, 532: 311, 566: 311, 574: 311, 576: 311, 632: 311, 311, 635: 311, 311, 311}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 101: 4454, 4456, 104: 4455, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4453, 871: 4457}, - {317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 57: 317, 461: 317, 465: 317, 317, 317, 317, 470: 317, 478: 317, 481: 317, 566: 317, 574: 317, 576: 317, 632: 317, 317, 635: 317, 317}, + {289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 47: 289, 464: 289, 467: 289, 469: 289, 289, 289, 474: 289, 483: 289, 289, 565: 289, 574: 289, 576: 289, 586: 289, 616: 289, 635: 289, 289}, + {288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 47: 288, 464: 288, 467: 288, 469: 288, 288, 288, 474: 288, 483: 288, 288, 565: 288, 574: 288, 576: 288, 586: 288, 616: 288, 635: 288, 288}, + {287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 47: 287, 464: 287, 467: 287, 469: 287, 287, 287, 474: 287, 483: 287, 287, 565: 287, 574: 287, 576: 287, 586: 287, 616: 287, 635: 287, 287}, + {320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 47: 320, 464: 320, 467: 320, 469: 320, 320, 320, 474: 320, 483: 320, 320, 565: 320, 574: 320, 576: 320, 586: 320, 616: 320, 635: 320, 320}, + {468: 4465, 569: 4466, 572: 4467, 958: 4468, 1135: 4464}, // 1990 - {501: 3738, 833: 4447}, - {501: 3737, 833: 4446}, - {293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 57: 293, 461: 293, 465: 293, 293, 293, 293, 470: 293, 478: 293, 481: 293, 566: 293, 574: 293, 576: 293, 632: 293, 293, 635: 293, 293}, - {288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 57: 288, 461: 288, 465: 288, 288, 288, 288, 470: 288, 478: 288, 481: 288, 566: 288, 574: 288, 576: 288, 632: 288, 288, 635: 288, 288}, - {287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 57: 287, 461: 287, 465: 287, 287, 287, 287, 470: 287, 478: 287, 481: 287, 566: 287, 574: 287, 576: 287, 632: 287, 287, 635: 287, 287}, + {7: 4470, 47: 4469}, + {7: 255, 47: 255}, + {7: 254, 47: 254}, + {7: 253, 47: 253}, + {7: 252, 47: 252}, // 1995 - {286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 57: 286, 461: 286, 465: 286, 286, 286, 286, 470: 286, 478: 286, 481: 286, 566: 286, 574: 286, 576: 286, 632: 286, 286, 635: 286, 286}, - {285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 57: 285, 461: 285, 465: 285, 285, 285, 285, 470: 285, 478: 285, 481: 285, 566: 285, 574: 285, 576: 285, 632: 285, 285, 635: 285, 285}, - {318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 57: 318, 461: 318, 465: 318, 318, 318, 318, 470: 318, 478: 318, 481: 318, 566: 318, 574: 318, 576: 318, 632: 318, 318, 635: 318, 318}, - {464: 4460, 565: 4461, 569: 4462, 955: 4463, 1131: 4459}, - {7: 4465, 57: 4464}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 101: 4459, 4461, 104: 4460, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4458, 872: 4472}, + {468: 4465, 569: 4466, 572: 4467, 958: 4471}, + {7: 251, 47: 251}, + {322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 47: 322, 464: 322, 467: 322, 469: 322, 322, 322, 474: 322, 483: 322, 322, 565: 322, 574: 322, 576: 322, 586: 322, 616: 322, 635: 322, 322}, + {468: 4465, 569: 4466, 572: 4467, 958: 4468, 1135: 4474}, // 2000 - {7: 253, 57: 253}, - {7: 252, 57: 252}, - {7: 251, 57: 251}, - {7: 250, 57: 250}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 101: 4454, 4456, 104: 4455, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4453, 871: 4467}, + {7: 4470, 47: 4475}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 101: 4459, 4461, 104: 4460, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4458, 872: 4476}, + {323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 47: 323, 464: 323, 467: 323, 469: 323, 323, 323, 474: 323, 483: 323, 323, 565: 323, 574: 323, 576: 323, 586: 323, 616: 323, 635: 323, 323}, + {324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 47: 324, 464: 324, 467: 324, 469: 324, 324, 324, 474: 324, 483: 324, 324, 565: 324, 574: 324, 576: 324, 586: 324, 616: 324, 635: 324, 324}, + {326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 47: 326, 464: 326, 467: 326, 469: 326, 326, 326, 474: 326, 483: 326, 326, 565: 326, 574: 326, 576: 326, 586: 326, 616: 326, 635: 326, 326}, // 2005 - {464: 4460, 565: 4461, 569: 4462, 955: 4466}, - {7: 249, 57: 249}, - {320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 57: 320, 461: 320, 465: 320, 320, 320, 320, 470: 320, 478: 320, 481: 320, 566: 320, 574: 320, 576: 320, 632: 320, 320, 635: 320, 320}, - {464: 4460, 565: 4461, 569: 4462, 955: 4463, 1131: 4469}, - {7: 4465, 57: 4470}, + {327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 47: 327, 464: 327, 467: 327, 469: 327, 327, 327, 474: 327, 483: 327, 327, 565: 327, 574: 327, 576: 327, 586: 327, 616: 327, 635: 327, 327}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4481}, + {328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 47: 328, 464: 328, 467: 328, 469: 328, 328, 328, 474: 328, 483: 328, 328, 565: 328, 574: 328, 576: 328, 586: 328, 616: 328, 635: 328, 328}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4483}, + {329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 47: 329, 464: 329, 467: 329, 469: 329, 329, 329, 474: 329, 483: 329, 329, 565: 329, 574: 329, 576: 329, 586: 329, 616: 329, 635: 329, 329}, // 2010 - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 101: 4454, 4456, 104: 4455, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4453, 871: 4471}, - {321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 57: 321, 461: 321, 465: 321, 321, 321, 321, 470: 321, 478: 321, 481: 321, 566: 321, 574: 321, 576: 321, 632: 321, 321, 635: 321, 321}, - {322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 57: 322, 461: 322, 465: 322, 322, 322, 322, 470: 322, 478: 322, 481: 322, 566: 322, 574: 322, 576: 322, 632: 322, 322, 635: 322, 322}, - {324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 57: 324, 461: 324, 465: 324, 324, 324, 324, 470: 324, 478: 324, 481: 324, 566: 324, 574: 324, 576: 324, 632: 324, 324, 635: 324, 324}, - {325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 57: 325, 461: 325, 465: 325, 325, 325, 325, 470: 325, 478: 325, 481: 325, 566: 325, 574: 325, 576: 325, 632: 325, 325, 635: 325, 325}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4486}, + {330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 47: 330, 464: 330, 467: 330, 469: 330, 330, 330, 474: 330, 483: 330, 330, 565: 330, 574: 330, 576: 330, 586: 330, 616: 330, 635: 330, 330}, + {331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 47: 331, 464: 331, 467: 331, 469: 331, 331, 331, 474: 331, 483: 331, 331, 565: 331, 574: 331, 576: 331, 586: 331, 616: 331, 635: 331, 331}, + {267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 14: 3753, 47: 267, 464: 267, 467: 267, 469: 267, 267, 267, 474: 267, 483: 267, 267, 498: 3754, 536: 3750, 565: 267, 574: 267, 576: 267, 586: 267, 616: 267, 635: 267, 267, 638: 3752, 762: 3751, 789: 4489}, + {332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 47: 332, 464: 332, 467: 332, 469: 332, 332, 332, 474: 332, 483: 332, 332, 565: 332, 574: 332, 576: 332, 586: 332, 616: 332, 635: 332, 332}, // 2015 - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4476}, - {326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 57: 326, 461: 326, 465: 326, 326, 326, 326, 470: 326, 478: 326, 481: 326, 566: 326, 574: 326, 576: 326, 632: 326, 326, 635: 326, 326}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4478}, - {327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 57: 327, 461: 327, 465: 327, 327, 327, 327, 470: 327, 478: 327, 481: 327, 566: 327, 574: 327, 576: 327, 632: 327, 327, 635: 327, 327}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4481}, + {333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 47: 333, 464: 333, 467: 333, 469: 333, 333, 333, 474: 333, 483: 333, 333, 565: 333, 574: 333, 576: 333, 586: 333, 616: 333, 635: 333, 333}, + {335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 47: 335, 49: 335, 464: 335, 335, 467: 335, 469: 335, 335, 335, 474: 335, 483: 335, 335, 565: 335, 574: 335, 576: 335, 586: 335, 616: 335, 635: 335, 335, 730: 335, 732: 335}, + {358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 47: 358, 464: 358, 467: 358, 469: 358, 358, 358, 474: 358, 483: 358, 358, 565: 358, 574: 358, 576: 358, 586: 358, 616: 358, 635: 358, 358}, + {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 47: 275, 49: 275, 464: 275, 467: 275, 469: 275, 275, 275, 474: 275, 483: 275, 275, 565: 275, 574: 275, 576: 275, 586: 275, 616: 275, 635: 275, 275, 730: 275, 732: 275, 864: 4493}, + {359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 47: 359, 49: 4434, 464: 359, 467: 359, 469: 359, 359, 359, 474: 359, 483: 359, 359, 565: 359, 574: 359, 576: 359, 586: 359, 616: 359, 635: 359, 359, 730: 4433, 732: 4435, 863: 4436}, // 2020 - {328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 57: 328, 461: 328, 465: 328, 328, 328, 328, 470: 328, 478: 328, 481: 328, 566: 328, 574: 328, 576: 328, 632: 328, 328, 635: 328, 328}, - {329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 57: 329, 461: 329, 465: 329, 329, 329, 329, 470: 329, 478: 329, 481: 329, 566: 329, 574: 329, 576: 329, 632: 329, 329, 635: 329, 329}, - {265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 3735, 57: 265, 461: 265, 465: 265, 265, 265, 265, 470: 265, 478: 265, 481: 265, 489: 3736, 532: 3732, 566: 265, 574: 265, 576: 265, 632: 265, 265, 635: 265, 265, 3734, 762: 3733, 790: 4484}, - {330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 57: 330, 461: 330, 465: 330, 330, 330, 330, 470: 330, 478: 330, 481: 330, 566: 330, 574: 330, 576: 330, 632: 330, 330, 635: 330, 330}, - {331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 57: 331, 461: 331, 465: 331, 331, 331, 331, 470: 331, 478: 331, 481: 331, 566: 331, 574: 331, 576: 331, 632: 331, 331, 635: 331, 331}, + {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 47: 275, 49: 275, 464: 275, 467: 275, 469: 275, 275, 275, 474: 275, 483: 275, 275, 565: 275, 574: 275, 576: 275, 586: 275, 616: 275, 635: 275, 275, 730: 275, 732: 275, 864: 4495}, + {360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 47: 360, 49: 4434, 464: 360, 467: 360, 469: 360, 360, 360, 474: 360, 483: 360, 360, 565: 360, 574: 360, 576: 360, 586: 360, 616: 360, 635: 360, 360, 730: 4433, 732: 4435, 863: 4436}, + {361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 47: 361, 49: 4434, 464: 361, 467: 361, 469: 361, 361, 361, 474: 361, 483: 361, 361, 565: 361, 574: 361, 576: 361, 586: 361, 616: 361, 635: 361, 361, 730: 4433, 732: 4435, 863: 4436}, + {275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 47: 275, 49: 275, 464: 275, 467: 275, 469: 275, 275, 275, 474: 275, 483: 275, 275, 565: 275, 574: 275, 576: 275, 586: 275, 616: 275, 635: 275, 275, 730: 275, 732: 275, 864: 4498}, + {362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 47: 362, 49: 4434, 464: 362, 467: 362, 469: 362, 362, 362, 474: 362, 483: 362, 362, 565: 362, 574: 362, 576: 362, 586: 362, 616: 362, 635: 362, 362, 730: 4433, 732: 4435, 863: 4436}, // 2025 - {333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 57: 333, 60: 333, 461: 333, 333, 465: 333, 333, 333, 333, 470: 333, 478: 333, 481: 333, 566: 333, 574: 333, 576: 333, 632: 333, 333, 635: 333, 333, 729: 333, 731: 333}, - {356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 57: 356, 461: 356, 465: 356, 356, 356, 356, 470: 356, 478: 356, 481: 356, 566: 356, 574: 356, 576: 356, 632: 356, 356, 635: 356, 356}, - {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 57: 273, 60: 273, 461: 273, 465: 273, 273, 273, 273, 470: 273, 478: 273, 481: 273, 566: 273, 574: 273, 576: 273, 632: 273, 273, 635: 273, 273, 729: 273, 731: 273, 863: 4488}, - {357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 57: 357, 60: 4429, 461: 357, 465: 357, 357, 357, 357, 470: 357, 478: 357, 481: 357, 566: 357, 574: 357, 576: 357, 632: 357, 357, 635: 357, 357, 729: 4428, 731: 4430, 862: 4431}, - {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 57: 273, 60: 273, 461: 273, 465: 273, 273, 273, 273, 470: 273, 478: 273, 481: 273, 566: 273, 574: 273, 576: 273, 632: 273, 273, 635: 273, 273, 729: 273, 731: 273, 863: 4490}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 565: 2350, 574: 2350, 576: 2350, 586: 2350, 640: 2350, 654: 4632, 2691, 2692, 2690, 666: 2350, 2350, 1128: 4631}, + {2284, 2284, 2284, 2284, 7: 2284, 2284, 2284, 47: 2284, 483: 2284}, + {565: 2261}, + {484: 4630}, + {2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 47: 2251, 464: 2251, 467: 2251, 469: 2251, 2251, 2251, 474: 2251, 483: 2251, 2251, 565: 2251, 574: 2251, 576: 2251, 586: 2251, 616: 2251, 635: 2251, 2251}, // 2030 - {358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 57: 358, 60: 4429, 461: 358, 465: 358, 358, 358, 358, 470: 358, 478: 358, 481: 358, 566: 358, 574: 358, 576: 358, 632: 358, 358, 635: 358, 358, 729: 4428, 731: 4430, 862: 4431}, - {359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, 57: 359, 60: 4429, 461: 359, 465: 359, 359, 359, 359, 470: 359, 478: 359, 481: 359, 566: 359, 574: 359, 576: 359, 632: 359, 359, 635: 359, 359, 729: 4428, 731: 4430, 862: 4431}, - {273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 57: 273, 60: 273, 461: 273, 465: 273, 273, 273, 273, 470: 273, 478: 273, 481: 273, 566: 273, 574: 273, 576: 273, 632: 273, 273, 635: 273, 273, 729: 273, 731: 273, 863: 4493}, - {360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 57: 360, 60: 4429, 461: 360, 465: 360, 360, 360, 360, 470: 360, 478: 360, 481: 360, 566: 360, 574: 360, 576: 360, 632: 360, 360, 635: 360, 360, 729: 4428, 731: 4430, 862: 4431}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 566: 2334, 574: 2334, 576: 2334, 632: 2334, 638: 2334, 653: 4615, 2676, 2677, 2675, 665: 2334, 2334, 1124: 4614}, + {2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 47: 2250, 464: 2250, 467: 2250, 469: 2250, 2250, 2250, 474: 2250, 483: 2250, 2250, 565: 2250, 574: 2250, 576: 2250, 586: 2250, 616: 2250, 635: 2250, 2250}, + {565: 4626}, + {2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 47: 2247, 464: 2247, 467: 2247, 469: 2247, 2247, 2247, 474: 2247, 483: 2247, 2247, 565: 4625, 574: 2247, 576: 2247, 586: 2247, 616: 2247, 635: 2247, 2247}, + {149: 4613, 257: 4615, 352: 4616, 465: 4612, 468: 3160, 477: 4355, 4354, 484: 3151, 500: 3155, 563: 3150, 3152, 566: 3154, 3153, 569: 3158, 572: 3159, 580: 4600, 4597, 583: 4598, 4599, 3157, 703: 4353, 3156, 4610, 934: 4595, 4596, 4614, 984: 4611, 1066: 4608, 1118: 4609, 1186: 4607}, + {471: 4605}, // 2035 - {2268, 2268, 2268, 2268, 7: 2268, 2268, 2268, 57: 2268, 478: 2268}, - {566: 2245}, - {481: 4613}, - {2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 57: 2235, 461: 2235, 465: 2235, 2235, 2235, 2235, 470: 2235, 478: 2235, 481: 2235, 566: 2235, 574: 2235, 576: 2235, 632: 2235, 2235, 635: 2235, 2235}, - {2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 57: 2234, 461: 2234, 465: 2234, 2234, 2234, 2234, 470: 2234, 478: 2234, 481: 2234, 566: 2234, 574: 2234, 576: 2234, 632: 2234, 2234, 635: 2234, 2234}, + {645: 4593}, + {468: 4592}, + {574: 4583}, + {470: 4576}, + {2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 47: 2239, 464: 2239, 467: 2239, 469: 2239, 2239, 2239, 474: 2239, 483: 2239, 2239, 565: 2239, 574: 2239, 576: 2239, 586: 2239, 616: 2239, 635: 2239, 2239}, // 2040 - {566: 4609}, - {2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 57: 2231, 461: 2231, 465: 2231, 2231, 2231, 2231, 470: 2231, 478: 2231, 481: 2231, 566: 4608, 574: 2231, 576: 2231, 632: 2231, 2231, 635: 2231, 2231}, - {257: 4606, 347: 4607, 464: 3142, 474: 4350, 4349, 481: 3133, 496: 3137, 560: 3132, 3134, 3136, 3135, 565: 3140, 569: 3141, 578: 4595, 4592, 4593, 4594, 3139, 702: 4348, 3138, 4605, 1061: 4590, 4591, 4603, 1114: 4604, 1181: 4602}, - {467: 4600}, - {644: 4588}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3408, 654: 3410, 2691, 2692, 2690, 729: 3407, 860: 4575}, + {173: 4573, 196: 4574, 471: 4572, 1171: 4571}, + {178: 4570, 237: 4569, 471: 4568, 1289: 4567}, + {280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 47: 280, 464: 280, 3743, 467: 280, 469: 280, 280, 280, 474: 280, 483: 280, 280, 565: 280, 574: 280, 576: 280, 586: 280, 616: 280, 635: 280, 280, 754: 3744, 775: 4566}, + {297: 4565}, // 2045 - {464: 4587}, - {574: 4578}, - {468: 4571}, - {2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 57: 2223, 461: 2223, 465: 2223, 2223, 2223, 2223, 470: 2223, 478: 2223, 481: 2223, 566: 2223, 574: 2223, 576: 2223, 632: 2223, 2223, 635: 2223, 2223}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3390, 653: 3392, 2676, 2677, 2675, 728: 3389, 860: 4570}, + {2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 47: 2223, 464: 2223, 467: 2223, 469: 2223, 2223, 2223, 474: 2223, 483: 2223, 2223, 565: 2223, 574: 2223, 576: 2223, 586: 2223, 616: 2223, 635: 2223, 2223}, + {2220, 2220, 2220, 2220, 4510, 4516, 4504, 2220, 2220, 2220, 4508, 4517, 4515, 47: 2220, 464: 4509, 467: 4004, 469: 4003, 2228, 4507, 474: 4514, 483: 2220, 4503, 565: 2262, 574: 2351, 576: 4501, 586: 4506, 616: 4499, 635: 4521, 4518, 799: 4502, 821: 4511, 898: 4513, 916: 4564, 925: 4512, 944: 4505}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4522}, + {2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 2160, 47: 2160, 464: 2160, 4524, 467: 2160, 469: 2160, 2160, 2160, 474: 2160, 483: 2160, 2160, 565: 2160, 574: 2160, 576: 2160, 586: 2160, 616: 2160, 635: 2160, 2160, 639: 2160, 1215: 4523}, + {2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 47: 2210, 464: 2210, 467: 2210, 469: 2210, 2210, 2210, 474: 2210, 483: 2210, 2210, 565: 2210, 574: 2210, 576: 2210, 586: 2210, 616: 2210, 635: 2210, 2210, 639: 4539, 1231: 4540, 4541}, // 2050 - {173: 4568, 195: 4569, 467: 4567, 1166: 4566}, - {177: 4565, 237: 4564, 467: 4563, 1285: 4562}, - {278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 57: 278, 461: 278, 3725, 465: 278, 278, 278, 278, 470: 278, 478: 278, 481: 278, 566: 278, 574: 278, 576: 278, 632: 278, 278, 635: 278, 278, 750: 3726, 776: 4561}, - {295: 4560}, - {2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 57: 2207, 461: 2207, 465: 2207, 2207, 2207, 2207, 470: 2207, 478: 2207, 481: 2207, 566: 2207, 574: 2207, 576: 2207, 632: 2207, 2207, 635: 2207, 2207}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4525}, + {7: 4537, 47: 4536}, + {7: 2158, 47: 2158}, + {7: 280, 47: 280, 465: 3743, 521: 280, 280, 754: 3744, 775: 4534}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4529}, // 2055 - {2204, 2204, 2204, 2204, 4505, 4511, 4499, 2204, 2204, 2204, 4503, 4512, 4510, 57: 2204, 461: 4504, 465: 3986, 3985, 4502, 2212, 470: 4509, 478: 2204, 481: 4498, 566: 2246, 574: 2335, 576: 4496, 632: 4501, 4494, 635: 4516, 4513, 800: 4497, 822: 4506, 898: 4508, 916: 4559, 925: 4507, 941: 4500}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4517}, - {2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 2152, 57: 2152, 461: 2152, 4519, 465: 2152, 2152, 2152, 2152, 470: 2152, 478: 2152, 481: 2152, 566: 2152, 574: 2152, 576: 2152, 632: 2152, 2152, 635: 2152, 2152, 639: 2152, 1210: 4518}, - {2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 57: 2194, 461: 2194, 465: 2194, 2194, 2194, 2194, 470: 2194, 478: 2194, 481: 2194, 566: 2194, 574: 2194, 576: 2194, 632: 2194, 2194, 635: 2194, 2194, 639: 4534, 1227: 4535, 4536}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4520}, + {47: 4530, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {7: 1272, 47: 1272, 521: 4533, 4532, 937: 4531}, + {7: 2155, 47: 2155}, + {1271, 1271, 1271, 1271, 7: 1271, 47: 1271, 483: 1271}, + {1270, 1270, 1270, 1270, 7: 1270, 47: 1270, 483: 1270}, // 2060 - {7: 4532, 57: 4531}, - {7: 2150, 57: 2150}, - {7: 278, 57: 278, 462: 3725, 518: 278, 278, 750: 3726, 776: 4529}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4524}, - {57: 4525, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, + {7: 1272, 47: 1272, 521: 4533, 4532, 937: 4535}, + {7: 2156, 47: 2156}, + {2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 2159, 47: 2159, 464: 2159, 467: 2159, 469: 2159, 2159, 2159, 474: 2159, 483: 2159, 2159, 565: 2159, 574: 2159, 576: 2159, 586: 2159, 616: 2159, 635: 2159, 2159, 639: 2159}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4538}, + {7: 2157, 47: 2157}, // 2065 - {7: 1268, 57: 1268, 518: 4528, 4527, 934: 4526}, - {7: 2147, 57: 2147}, - {1267, 1267, 1267, 1267, 7: 1267, 57: 1267, 478: 1267}, - {1266, 1266, 1266, 1266, 7: 1266, 57: 1266, 478: 1266}, - {7: 1268, 57: 1268, 518: 4528, 4527, 934: 4530}, + {200: 4561, 359: 4562, 375: 4563}, + {2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 47: 2209, 464: 2209, 467: 2209, 469: 2209, 2209, 2209, 474: 2209, 483: 2209, 2209, 565: 2209, 574: 2209, 576: 2209, 586: 2209, 616: 2209, 635: 2209, 2209}, + {2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 2205, 47: 2205, 464: 4543, 467: 2205, 469: 2205, 2205, 2205, 474: 2205, 483: 2205, 2205, 565: 2205, 574: 2205, 576: 2205, 586: 2205, 616: 2205, 635: 2205, 2205, 1072: 4544, 4545, 1238: 4542}, + {2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 47: 2208, 464: 2208, 467: 2208, 469: 2208, 2208, 2208, 474: 2208, 483: 2208, 2208, 565: 2208, 574: 2208, 576: 2208, 586: 2208, 616: 2208, 635: 2208, 2208}, + {645: 4559, 733: 4548}, // 2070 - {7: 2148, 57: 2148}, - {2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 2151, 57: 2151, 461: 2151, 465: 2151, 2151, 2151, 2151, 470: 2151, 478: 2151, 481: 2151, 566: 2151, 574: 2151, 576: 2151, 632: 2151, 2151, 635: 2151, 2151, 639: 2151}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4533}, - {7: 2149, 57: 2149}, - {199: 4556, 354: 4557, 371: 4558}, + {2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 47: 2204, 464: 4557, 467: 2204, 469: 2204, 2204, 2204, 474: 2204, 483: 2204, 2204, 565: 2204, 574: 2204, 576: 2204, 586: 2204, 616: 2204, 635: 2204, 2204, 1073: 4558}, + {2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 2203, 47: 2203, 464: 4546, 467: 2203, 469: 2203, 2203, 2203, 474: 2203, 483: 2203, 2203, 565: 2203, 574: 2203, 576: 2203, 586: 2203, 616: 2203, 635: 2203, 2203, 1072: 4547}, + {733: 4548}, + {2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 2201, 47: 2201, 464: 2201, 467: 2201, 469: 2201, 2201, 2201, 474: 2201, 483: 2201, 2201, 565: 2201, 574: 2201, 576: 2201, 586: 2201, 616: 2201, 635: 2201, 2201}, + {70: 4553, 496: 4552, 661: 4551, 663: 4550, 1095: 4549}, // 2075 - {2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 57: 2193, 461: 2193, 465: 2193, 2193, 2193, 2193, 470: 2193, 478: 2193, 481: 2193, 566: 2193, 574: 2193, 576: 2193, 632: 2193, 2193, 635: 2193, 2193}, - {2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 57: 2189, 461: 4538, 465: 2189, 2189, 2189, 2189, 470: 2189, 478: 2189, 481: 2189, 566: 2189, 574: 2189, 576: 2189, 632: 2189, 2189, 635: 2189, 2189, 1069: 4539, 4540, 1234: 4537}, - {2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 57: 2192, 461: 2192, 465: 2192, 2192, 2192, 2192, 470: 2192, 478: 2192, 481: 2192, 566: 2192, 574: 2192, 576: 2192, 632: 2192, 2192, 635: 2192, 2192}, - {644: 4554, 732: 4543}, - {2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 57: 2188, 461: 4552, 465: 2188, 2188, 2188, 2188, 470: 2188, 478: 2188, 481: 2188, 566: 2188, 574: 2188, 576: 2188, 632: 2188, 2188, 635: 2188, 2188, 1070: 4553}, + {2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 47: 2207, 464: 2207, 467: 2207, 469: 2207, 2207, 2207, 474: 2207, 483: 2207, 2207, 565: 2207, 574: 2207, 576: 2207, 586: 2207, 616: 2207, 635: 2207, 2207}, + {2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 47: 2200, 464: 2200, 467: 2200, 469: 2200, 2200, 2200, 474: 2200, 483: 2200, 2200, 565: 2200, 574: 2200, 576: 2200, 586: 2200, 616: 2200, 635: 2200, 2200}, + {2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 2199, 47: 2199, 464: 2199, 467: 2199, 469: 2199, 2199, 2199, 474: 2199, 483: 2199, 2199, 565: 2199, 574: 2199, 576: 2199, 586: 2199, 616: 2199, 635: 2199, 2199}, + {471: 4556, 484: 4555}, + {293: 4554}, // 2080 - {2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 57: 2187, 461: 4541, 465: 2187, 2187, 2187, 2187, 470: 2187, 478: 2187, 481: 2187, 566: 2187, 574: 2187, 576: 2187, 632: 2187, 2187, 635: 2187, 2187, 1069: 4542}, - {732: 4543}, - {2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 57: 2185, 461: 2185, 465: 2185, 2185, 2185, 2185, 470: 2185, 478: 2185, 481: 2185, 566: 2185, 574: 2185, 576: 2185, 632: 2185, 2185, 635: 2185, 2185}, - {81: 4548, 501: 4547, 660: 4546, 662: 4545, 1092: 4544}, - {2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 57: 2191, 461: 2191, 465: 2191, 2191, 2191, 2191, 470: 2191, 478: 2191, 481: 2191, 566: 2191, 574: 2191, 576: 2191, 632: 2191, 2191, 635: 2191, 2191}, + {2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 47: 2197, 464: 2197, 467: 2197, 469: 2197, 2197, 2197, 474: 2197, 483: 2197, 2197, 565: 2197, 574: 2197, 576: 2197, 586: 2197, 616: 2197, 635: 2197, 2197}, + {2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 2198, 47: 2198, 464: 2198, 467: 2198, 469: 2198, 2198, 2198, 474: 2198, 483: 2198, 2198, 565: 2198, 574: 2198, 576: 2198, 586: 2198, 616: 2198, 635: 2198, 2198}, + {2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 47: 2196, 464: 2196, 467: 2196, 469: 2196, 2196, 2196, 474: 2196, 483: 2196, 2196, 565: 2196, 574: 2196, 576: 2196, 586: 2196, 616: 2196, 635: 2196, 2196}, + {645: 4559}, + {2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 2202, 47: 2202, 464: 2202, 467: 2202, 469: 2202, 2202, 2202, 474: 2202, 483: 2202, 2202, 565: 2202, 574: 2202, 576: 2202, 586: 2202, 616: 2202, 635: 2202, 2202}, // 2085 - {2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 57: 2184, 461: 2184, 465: 2184, 2184, 2184, 2184, 470: 2184, 478: 2184, 481: 2184, 566: 2184, 574: 2184, 576: 2184, 632: 2184, 2184, 635: 2184, 2184}, - {2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 2183, 57: 2183, 461: 2183, 465: 2183, 2183, 2183, 2183, 470: 2183, 478: 2183, 481: 2183, 566: 2183, 574: 2183, 576: 2183, 632: 2183, 2183, 635: 2183, 2183}, - {467: 4551, 481: 4550}, - {291: 4549}, - {2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 2181, 57: 2181, 461: 2181, 465: 2181, 2181, 2181, 2181, 470: 2181, 478: 2181, 481: 2181, 566: 2181, 574: 2181, 576: 2181, 632: 2181, 2181, 635: 2181, 2181}, + {70: 4553, 496: 4552, 661: 4551, 663: 4550, 1095: 4560}, + {2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 47: 2206, 464: 2206, 467: 2206, 469: 2206, 2206, 2206, 474: 2206, 483: 2206, 2206, 565: 2206, 574: 2206, 576: 2206, 586: 2206, 616: 2206, 635: 2206, 2206}, + {2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 47: 2213, 464: 2213, 467: 2213, 469: 2213, 2213, 2213, 474: 2213, 483: 2213, 2213, 565: 2213, 574: 2213, 576: 2213, 586: 2213, 616: 2213, 635: 2213, 2213}, + {2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 2212, 47: 2212, 464: 2212, 467: 2212, 469: 2212, 2212, 2212, 474: 2212, 483: 2212, 2212, 565: 2212, 574: 2212, 576: 2212, 586: 2212, 616: 2212, 635: 2212, 2212}, + {2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 47: 2211, 464: 2211, 467: 2211, 469: 2211, 2211, 2211, 474: 2211, 483: 2211, 2211, 565: 2211, 574: 2211, 576: 2211, 586: 2211, 616: 2211, 635: 2211, 2211}, // 2090 - {2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 2182, 57: 2182, 461: 2182, 465: 2182, 2182, 2182, 2182, 470: 2182, 478: 2182, 481: 2182, 566: 2182, 574: 2182, 576: 2182, 632: 2182, 2182, 635: 2182, 2182}, - {2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 2180, 57: 2180, 461: 2180, 465: 2180, 2180, 2180, 2180, 470: 2180, 478: 2180, 481: 2180, 566: 2180, 574: 2180, 576: 2180, 632: 2180, 2180, 635: 2180, 2180}, - {644: 4554}, - {2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 57: 2186, 461: 2186, 465: 2186, 2186, 2186, 2186, 470: 2186, 478: 2186, 481: 2186, 566: 2186, 574: 2186, 576: 2186, 632: 2186, 2186, 635: 2186, 2186}, - {81: 4548, 501: 4547, 660: 4546, 662: 4545, 1092: 4555}, + {2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 47: 2222, 464: 2222, 467: 2222, 469: 2222, 2222, 2222, 474: 2222, 483: 2222, 2222, 565: 2222, 574: 2222, 576: 2222, 586: 2222, 616: 2222, 635: 2222, 2222}, + {470: 2227}, + {2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 47: 2235, 464: 2235, 467: 2235, 469: 2235, 2235, 2235, 474: 2235, 483: 2235, 2235, 565: 2235, 574: 2235, 576: 2235, 586: 2235, 616: 2235, 635: 2235, 2235}, + {2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 47: 2236, 464: 2236, 467: 2236, 469: 2236, 2236, 2236, 474: 2236, 483: 2236, 2236, 565: 2236, 574: 2236, 576: 2236, 586: 2236, 616: 2236, 635: 2236, 2236}, + {2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 47: 2234, 464: 2234, 467: 2234, 469: 2234, 2234, 2234, 474: 2234, 483: 2234, 2234, 565: 2234, 574: 2234, 576: 2234, 586: 2234, 616: 2234, 635: 2234, 2234}, // 2095 - {2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 57: 2190, 461: 2190, 465: 2190, 2190, 2190, 2190, 470: 2190, 478: 2190, 481: 2190, 566: 2190, 574: 2190, 576: 2190, 632: 2190, 2190, 635: 2190, 2190}, - {2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 2197, 57: 2197, 461: 2197, 465: 2197, 2197, 2197, 2197, 470: 2197, 478: 2197, 481: 2197, 566: 2197, 574: 2197, 576: 2197, 632: 2197, 2197, 635: 2197, 2197}, - {2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, 57: 2196, 461: 2196, 465: 2196, 2196, 2196, 2196, 470: 2196, 478: 2196, 481: 2196, 566: 2196, 574: 2196, 576: 2196, 632: 2196, 2196, 635: 2196, 2196}, - {2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 57: 2195, 461: 2195, 465: 2195, 2195, 2195, 2195, 470: 2195, 478: 2195, 481: 2195, 566: 2195, 574: 2195, 576: 2195, 632: 2195, 2195, 635: 2195, 2195}, - {2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 57: 2206, 461: 2206, 465: 2206, 2206, 2206, 2206, 470: 2206, 478: 2206, 481: 2206, 566: 2206, 574: 2206, 576: 2206, 632: 2206, 2206, 635: 2206, 2206}, + {2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 47: 2233, 464: 2233, 467: 2233, 469: 2233, 2233, 2233, 474: 2233, 483: 2233, 2233, 565: 2233, 574: 2233, 576: 2233, 586: 2233, 616: 2233, 635: 2233, 2233}, + {2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 47: 2232, 464: 2232, 467: 2232, 469: 2232, 2232, 2232, 474: 2232, 483: 2232, 2232, 565: 2232, 574: 2232, 576: 2232, 586: 2232, 616: 2232, 635: 2232, 2232}, + {2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 47: 2237, 464: 2237, 467: 2237, 469: 2237, 2237, 2237, 474: 2237, 483: 2237, 2237, 565: 2237, 574: 2237, 576: 2237, 586: 2237, 616: 2237, 635: 2237, 2237}, + {2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 47: 2231, 464: 2231, 467: 2231, 469: 2231, 2231, 2231, 474: 2231, 483: 2231, 2231, 565: 2231, 574: 2231, 576: 2231, 586: 2231, 616: 2231, 635: 2231, 2231}, + {2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 47: 2230, 464: 2230, 467: 2230, 469: 2230, 2230, 2230, 474: 2230, 483: 2230, 2230, 565: 2230, 574: 2230, 576: 2230, 586: 2230, 616: 2230, 635: 2230, 2230}, // 2100 - {468: 2211}, - {2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 57: 2219, 461: 2219, 465: 2219, 2219, 2219, 2219, 470: 2219, 478: 2219, 481: 2219, 566: 2219, 574: 2219, 576: 2219, 632: 2219, 2219, 635: 2219, 2219}, - {2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 57: 2220, 461: 2220, 465: 2220, 2220, 2220, 2220, 470: 2220, 478: 2220, 481: 2220, 566: 2220, 574: 2220, 576: 2220, 632: 2220, 2220, 635: 2220, 2220}, - {2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 57: 2218, 461: 2218, 465: 2218, 2218, 2218, 2218, 470: 2218, 478: 2218, 481: 2218, 566: 2218, 574: 2218, 576: 2218, 632: 2218, 2218, 635: 2218, 2218}, - {2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 57: 2217, 461: 2217, 465: 2217, 2217, 2217, 2217, 470: 2217, 478: 2217, 481: 2217, 566: 2217, 574: 2217, 576: 2217, 632: 2217, 2217, 635: 2217, 2217}, + {2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 47: 2229, 464: 2229, 467: 2229, 469: 2229, 2229, 2229, 474: 2229, 483: 2229, 2229, 565: 2229, 574: 2229, 576: 2229, 586: 2229, 616: 2229, 635: 2229, 2229}, + {2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 47: 2238, 464: 2238, 467: 2238, 469: 2238, 2238, 2238, 474: 2238, 483: 2238, 2238, 565: 2238, 574: 2238, 576: 2238, 586: 2238, 616: 2238, 635: 2238, 2238}, + {465: 4577}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4578}, + {47: 4579, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 2105 - {2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 57: 2216, 461: 2216, 465: 2216, 2216, 2216, 2216, 470: 2216, 478: 2216, 481: 2216, 566: 2216, 574: 2216, 576: 2216, 632: 2216, 2216, 635: 2216, 2216}, - {2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 57: 2221, 461: 2221, 465: 2221, 2221, 2221, 2221, 470: 2221, 478: 2221, 481: 2221, 566: 2221, 574: 2221, 576: 2221, 632: 2221, 2221, 635: 2221, 2221}, - {2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 57: 2215, 461: 2215, 465: 2215, 2215, 2215, 2215, 470: 2215, 478: 2215, 481: 2215, 566: 2215, 574: 2215, 576: 2215, 632: 2215, 2215, 635: 2215, 2215}, - {2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 57: 2214, 461: 2214, 465: 2214, 2214, 2214, 2214, 470: 2214, 478: 2214, 481: 2214, 566: 2214, 574: 2214, 576: 2214, 632: 2214, 2214, 635: 2214, 2214}, - {2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 57: 2213, 461: 2213, 465: 2213, 2213, 2213, 2213, 470: 2213, 478: 2213, 481: 2213, 566: 2213, 574: 2213, 576: 2213, 632: 2213, 2213, 635: 2213, 2213}, + {2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 47: 2226, 464: 2226, 467: 2226, 469: 2226, 2226, 2226, 474: 2226, 483: 2226, 2226, 565: 2226, 574: 2226, 576: 2226, 586: 2226, 616: 2226, 635: 2226, 2226, 1290: 4582, 1320: 4581, 4580}, + {2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 47: 2240, 464: 2240, 467: 2240, 469: 2240, 2240, 2240, 474: 2240, 483: 2240, 2240, 565: 2240, 574: 2240, 576: 2240, 586: 2240, 616: 2240, 635: 2240, 2240}, + {2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 47: 2225, 464: 2225, 467: 2225, 469: 2225, 2225, 2225, 474: 2225, 483: 2225, 2225, 565: 2225, 574: 2225, 576: 2225, 586: 2225, 616: 2225, 635: 2225, 2225}, + {2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 47: 2224, 464: 2224, 467: 2224, 469: 2224, 2224, 2224, 474: 2224, 483: 2224, 2224, 565: 2224, 574: 2224, 576: 2224, 586: 2224, 616: 2224, 635: 2224, 2224}, + {465: 4584}, // 2110 - {2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 57: 2222, 461: 2222, 465: 2222, 2222, 2222, 2222, 470: 2222, 478: 2222, 481: 2222, 566: 2222, 574: 2222, 576: 2222, 632: 2222, 2222, 635: 2222, 2222}, - {462: 4572}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4573}, - {57: 4574, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 57: 2210, 461: 2210, 465: 2210, 2210, 2210, 2210, 470: 2210, 478: 2210, 481: 2210, 566: 2210, 574: 2210, 576: 2210, 632: 2210, 2210, 635: 2210, 2210, 1286: 4577, 1316: 4576, 4575}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4585}, + {47: 4586, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 47: 2256, 147: 4343, 464: 2256, 467: 4004, 469: 4003, 2256, 2256, 474: 2256, 483: 2256, 2256, 565: 2256, 574: 2256, 576: 2256, 586: 2256, 616: 2256, 635: 2256, 2256, 799: 4587, 922: 4588, 1029: 4589, 1189: 4590}, + {147: 4345, 484: 4591}, + {2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 47: 2255, 464: 2255, 467: 2255, 469: 2255, 2255, 2255, 474: 2255, 483: 2255, 2255, 565: 2255, 574: 2255, 576: 2255, 586: 2255, 616: 2255, 635: 2255, 2255}, // 2115 - {2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 57: 2224, 461: 2224, 465: 2224, 2224, 2224, 2224, 470: 2224, 478: 2224, 481: 2224, 566: 2224, 574: 2224, 576: 2224, 632: 2224, 2224, 635: 2224, 2224}, - {2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 57: 2209, 461: 2209, 465: 2209, 2209, 2209, 2209, 470: 2209, 478: 2209, 481: 2209, 566: 2209, 574: 2209, 576: 2209, 632: 2209, 2209, 635: 2209, 2209}, - {2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 57: 2208, 461: 2208, 465: 2208, 2208, 2208, 2208, 470: 2208, 478: 2208, 481: 2208, 566: 2208, 574: 2208, 576: 2208, 632: 2208, 2208, 635: 2208, 2208}, - {462: 4579}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4580}, + {2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 47: 2253, 464: 2253, 467: 2253, 469: 2253, 2253, 2253, 474: 2253, 483: 2253, 2253, 565: 2253, 574: 2253, 576: 2253, 586: 2253, 616: 2253, 635: 2253, 2253}, + {2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 47: 2241, 464: 2241, 467: 2241, 469: 2241, 2241, 2241, 474: 2241, 483: 2241, 2241, 565: 2241, 574: 2241, 576: 2241, 586: 2241, 616: 2241, 635: 2241, 2241}, + {2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 47: 2254, 464: 2254, 467: 2254, 469: 2254, 2254, 2254, 474: 2254, 483: 2254, 2254, 565: 2254, 574: 2254, 576: 2254, 586: 2254, 616: 2254, 635: 2254, 2254}, + {2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 47: 2242, 464: 2242, 467: 2242, 469: 2242, 2242, 2242, 474: 2242, 483: 2242, 2242, 565: 2242, 574: 2242, 576: 2242, 586: 2242, 616: 2242, 635: 2242, 2242}, + {580: 4600, 4597, 583: 4598, 4599, 934: 4595, 4596, 4594}, // 2120 - {57: 4581, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 57: 2240, 147: 4338, 461: 2240, 465: 3986, 3985, 2240, 2240, 470: 2240, 478: 2240, 481: 2240, 566: 2240, 574: 2240, 576: 2240, 632: 2240, 2240, 635: 2240, 2240, 800: 4582, 922: 4583, 1025: 4584, 1184: 4585}, - {147: 4340, 481: 4586}, - {2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 57: 2239, 461: 2239, 465: 2239, 2239, 2239, 2239, 470: 2239, 478: 2239, 481: 2239, 566: 2239, 574: 2239, 576: 2239, 632: 2239, 2239, 635: 2239, 2239}, - {2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 57: 2237, 461: 2237, 465: 2237, 2237, 2237, 2237, 470: 2237, 478: 2237, 481: 2237, 566: 2237, 574: 2237, 576: 2237, 632: 2237, 2237, 635: 2237, 2237}, + {2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 47: 2243, 464: 2243, 467: 2243, 469: 2243, 2243, 2243, 474: 2243, 483: 2243, 2243, 565: 2243, 574: 2243, 576: 2243, 586: 2243, 616: 2243, 635: 2243, 2243}, + {2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 2186, 47: 2186, 464: 2186, 467: 2186, 469: 2186, 2186, 2186, 474: 2186, 483: 2186, 2186, 565: 2186, 574: 2186, 576: 2186, 586: 2186, 616: 2186, 635: 2186, 2186}, + {465: 4601}, + {2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 47: 2177, 464: 2177, 2181, 467: 2177, 469: 2177, 2177, 2177, 474: 2177, 483: 2177, 2177, 565: 2177, 574: 2177, 576: 2177, 586: 2177, 616: 2177, 635: 2177, 2177}, + {2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 47: 2176, 464: 2176, 2180, 467: 2176, 469: 2176, 2176, 2176, 474: 2176, 483: 2176, 2176, 565: 2176, 574: 2176, 576: 2176, 586: 2176, 616: 2176, 635: 2176, 2176}, // 2125 - {2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 57: 2225, 461: 2225, 465: 2225, 2225, 2225, 2225, 470: 2225, 478: 2225, 481: 2225, 566: 2225, 574: 2225, 576: 2225, 632: 2225, 2225, 635: 2225, 2225}, - {2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 57: 2238, 461: 2238, 465: 2238, 2238, 2238, 2238, 470: 2238, 478: 2238, 481: 2238, 566: 2238, 574: 2238, 576: 2238, 632: 2238, 2238, 635: 2238, 2238}, - {2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 57: 2226, 461: 2226, 465: 2226, 2226, 2226, 2226, 470: 2226, 478: 2226, 481: 2226, 566: 2226, 574: 2226, 576: 2226, 632: 2226, 2226, 635: 2226, 2226}, - {578: 4595, 4592, 4593, 4594, 1061: 4590, 4591, 4589}, - {2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 57: 2227, 461: 2227, 465: 2227, 2227, 2227, 2227, 470: 2227, 478: 2227, 481: 2227, 566: 2227, 574: 2227, 576: 2227, 632: 2227, 2227, 635: 2227, 2227}, + {2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 47: 2175, 464: 2175, 2179, 467: 2175, 469: 2175, 2175, 2175, 474: 2175, 483: 2175, 2175, 565: 2175, 574: 2175, 576: 2175, 586: 2175, 616: 2175, 635: 2175, 2175}, + {465: 2178}, + {47: 4602, 500: 2665, 724: 4603}, + {2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 2185, 47: 2185, 464: 2185, 467: 2185, 469: 2185, 2185, 2185, 474: 2185, 483: 2185, 2185, 565: 2185, 574: 2185, 576: 2185, 586: 2185, 616: 2185, 635: 2185, 2185}, + {47: 4604}, // 2130 - {2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 2176, 57: 2176, 461: 2176, 465: 2176, 2176, 2176, 2176, 470: 2176, 478: 2176, 481: 2176, 566: 2176, 574: 2176, 576: 2176, 632: 2176, 2176, 635: 2176, 2176}, - {462: 4596}, - {2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 2167, 57: 2167, 461: 2167, 2171, 465: 2167, 2167, 2167, 2167, 470: 2167, 478: 2167, 481: 2167, 566: 2167, 574: 2167, 576: 2167, 632: 2167, 2167, 635: 2167, 2167}, - {2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 57: 2166, 461: 2166, 2170, 465: 2166, 2166, 2166, 2166, 470: 2166, 478: 2166, 481: 2166, 566: 2166, 574: 2166, 576: 2166, 632: 2166, 2166, 635: 2166, 2166}, - {2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 2165, 57: 2165, 461: 2165, 2169, 465: 2165, 2165, 2165, 2165, 470: 2165, 478: 2165, 481: 2165, 566: 2165, 574: 2165, 576: 2165, 632: 2165, 2165, 635: 2165, 2165}, + {2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 47: 2184, 464: 2184, 467: 2184, 469: 2184, 2184, 2184, 474: 2184, 483: 2184, 2184, 565: 2184, 574: 2184, 576: 2184, 586: 2184, 616: 2184, 635: 2184, 2184}, + {153: 4606}, + {2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 47: 2244, 464: 2244, 467: 2244, 469: 2244, 2244, 2244, 474: 2244, 483: 2244, 2244, 565: 2244, 574: 2244, 576: 2244, 586: 2244, 616: 2244, 635: 2244, 2244}, + {2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 47: 2245, 464: 2245, 467: 2245, 469: 2245, 2245, 2245, 474: 2245, 483: 2245, 2245, 565: 2245, 574: 2245, 576: 2245, 586: 2245, 616: 2245, 635: 2245, 2245}, + {2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 2195, 47: 2195, 464: 2195, 467: 2195, 469: 2195, 2195, 2195, 474: 2195, 483: 2195, 2195, 565: 2195, 574: 2195, 576: 2195, 586: 2195, 616: 2195, 635: 2195, 2195}, // 2135 - {462: 2168}, - {57: 4597, 496: 2650, 725: 4598}, - {2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 2175, 57: 2175, 461: 2175, 465: 2175, 2175, 2175, 2175, 470: 2175, 478: 2175, 481: 2175, 566: 2175, 574: 2175, 576: 2175, 632: 2175, 2175, 635: 2175, 2175}, - {57: 4599}, - {2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 57: 2174, 461: 2174, 465: 2174, 2174, 2174, 2174, 470: 2174, 478: 2174, 481: 2174, 566: 2174, 574: 2174, 576: 2174, 632: 2174, 2174, 635: 2174, 2174}, + {2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 47: 2194, 464: 2194, 467: 2194, 469: 2194, 2194, 2194, 474: 2194, 483: 2194, 2194, 565: 2194, 574: 2194, 576: 2194, 586: 2194, 616: 2194, 635: 2194, 2194}, + {2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 47: 2193, 464: 2193, 467: 2193, 469: 2193, 2193, 2193, 474: 2193, 483: 2193, 2193, 565: 2193, 574: 2193, 576: 2193, 586: 2193, 616: 2193, 635: 2193, 2193}, + {2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 2192, 47: 2192, 464: 2192, 467: 2192, 469: 2192, 2192, 2192, 474: 2192, 483: 2192, 2192, 565: 2192, 574: 2192, 576: 2192, 586: 2192, 616: 2192, 635: 2192, 2192}, + {149: 4613, 465: 4612, 580: 4600, 4597, 583: 4598, 4599, 934: 4595, 4596, 4614, 984: 4621, 1066: 4622}, + {465: 4617}, // 2140 - {152: 4601}, - {2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 57: 2228, 461: 2228, 465: 2228, 2228, 2228, 2228, 470: 2228, 478: 2228, 481: 2228, 566: 2228, 574: 2228, 576: 2228, 632: 2228, 2228, 635: 2228, 2228}, - {2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 57: 2229, 461: 2229, 465: 2229, 2229, 2229, 2229, 470: 2229, 478: 2229, 481: 2229, 566: 2229, 574: 2229, 576: 2229, 632: 2229, 2229, 635: 2229, 2229}, - {2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 2179, 57: 2179, 461: 2179, 465: 2179, 2179, 2179, 2179, 470: 2179, 478: 2179, 481: 2179, 566: 2179, 574: 2179, 576: 2179, 632: 2179, 2179, 635: 2179, 2179}, - {2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 2178, 57: 2178, 461: 2178, 465: 2178, 2178, 2178, 2178, 470: 2178, 478: 2178, 481: 2178, 566: 2178, 574: 2178, 576: 2178, 632: 2178, 2178, 635: 2178, 2178}, + {2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 2187, 47: 2187, 464: 2187, 467: 2187, 469: 2187, 2187, 2187, 474: 2187, 483: 2187, 2187, 565: 2187, 574: 2187, 576: 2187, 586: 2187, 616: 2187, 635: 2187, 2187}, + {153: 4094}, + {465: 4091}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 4618, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 4619}, + {2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 2190, 47: 2190, 464: 2190, 467: 2190, 469: 2190, 2190, 2190, 474: 2190, 483: 2190, 2190, 565: 2190, 574: 2190, 576: 2190, 586: 2190, 616: 2190, 635: 2190, 2190}, // 2145 - {2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 2177, 57: 2177, 461: 2177, 465: 2177, 2177, 2177, 2177, 470: 2177, 478: 2177, 481: 2177, 566: 2177, 574: 2177, 576: 2177, 632: 2177, 2177, 635: 2177, 2177}, - {152: 4076}, - {462: 4073}, - {2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 57: 2230, 461: 2230, 465: 2230, 2230, 2230, 2230, 470: 2230, 478: 2230, 481: 2230, 566: 2230, 574: 2230, 576: 2230, 632: 2230, 2230, 635: 2230, 2230}, - {2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 57: 2233, 94: 4610, 96: 4611, 461: 2233, 465: 2233, 2233, 2233, 2233, 470: 2233, 478: 2233, 481: 2233, 566: 2233, 574: 2233, 576: 2233, 632: 2233, 2233, 635: 2233, 2233, 857: 4612}, + {7: 3509, 47: 4620}, + {2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 2189, 47: 2189, 464: 2189, 467: 2189, 469: 2189, 2189, 2189, 474: 2189, 483: 2189, 2189, 565: 2189, 574: 2189, 576: 2189, 586: 2189, 616: 2189, 635: 2189, 2189}, + {47: 4624}, + {47: 4623}, + {2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 2188, 47: 2188, 464: 2188, 467: 2188, 469: 2188, 2188, 2188, 474: 2188, 483: 2188, 2188, 565: 2188, 574: 2188, 576: 2188, 586: 2188, 616: 2188, 635: 2188, 2188}, // 2150 - {2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 29: 2361, 57: 2361, 92: 2361, 2361, 2361, 2361, 2361, 2361, 461: 2361, 463: 2361, 465: 2361, 2361, 2361, 2361, 470: 2361, 2361, 478: 2361, 481: 2361, 486: 2361, 566: 2361, 574: 2361, 576: 2361, 632: 2361, 2361, 635: 2361, 2361}, - {2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 2360, 29: 2360, 57: 2360, 92: 2360, 2360, 2360, 2360, 2360, 2360, 461: 2360, 463: 2360, 465: 2360, 2360, 2360, 2360, 470: 2360, 2360, 478: 2360, 481: 2360, 486: 2360, 566: 2360, 574: 2360, 576: 2360, 632: 2360, 2360, 635: 2360, 2360}, - {2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 57: 2232, 461: 2232, 465: 2232, 2232, 2232, 2232, 470: 2232, 478: 2232, 481: 2232, 566: 2232, 574: 2232, 576: 2232, 632: 2232, 2232, 635: 2232, 2232}, - {2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 57: 2236, 461: 2236, 465: 2236, 2236, 2236, 2236, 470: 2236, 478: 2236, 481: 2236, 566: 2236, 574: 2236, 576: 2236, 632: 2236, 2236, 635: 2236, 2236}, - {566: 2333, 574: 2333, 576: 2333, 632: 2333, 638: 2333, 665: 2333, 2333}, + {2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 2191, 47: 2191, 464: 2191, 467: 2191, 469: 2191, 2191, 2191, 474: 2191, 483: 2191, 2191, 565: 2191, 574: 2191, 576: 2191, 586: 2191, 616: 2191, 635: 2191, 2191}, + {2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 47: 2246, 464: 2246, 467: 2246, 469: 2246, 2246, 2246, 474: 2246, 483: 2246, 2246, 565: 2246, 574: 2246, 576: 2246, 586: 2246, 616: 2246, 635: 2246, 2246}, + {2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 47: 2249, 83: 4627, 85: 4628, 464: 2249, 467: 2249, 469: 2249, 2249, 2249, 474: 2249, 483: 2249, 2249, 565: 2249, 574: 2249, 576: 2249, 586: 2249, 616: 2249, 635: 2249, 2249, 857: 4629}, + {2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 2377, 17: 2377, 47: 2377, 81: 2377, 2377, 2377, 2377, 2377, 87: 2377, 464: 2377, 466: 2377, 2377, 469: 2377, 2377, 2377, 473: 2377, 2377, 483: 2377, 2377, 488: 2377, 565: 2377, 574: 2377, 576: 2377, 586: 2377, 616: 2377, 635: 2377, 2377}, + {2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376, 17: 2376, 47: 2376, 81: 2376, 2376, 2376, 2376, 2376, 87: 2376, 464: 2376, 466: 2376, 2376, 469: 2376, 2376, 2376, 473: 2376, 2376, 483: 2376, 2376, 488: 2376, 565: 2376, 574: 2376, 576: 2376, 586: 2376, 616: 2376, 635: 2376, 2376}, // 2155 - {2332, 2332, 2332, 2332, 7: 2332, 478: 2332, 566: 2332, 574: 2332, 576: 2332, 632: 2332, 638: 2332, 665: 2332, 2332}, - {2269, 2269, 2269, 2269, 7: 2269, 2269, 2269, 57: 2269, 478: 2269}, - {2391, 2391, 2391, 2391, 7: 2391, 478: 2391}, - {2343, 2343, 2343, 2343, 7: 2343, 478: 2343}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4620}, + {2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 47: 2248, 464: 2248, 467: 2248, 469: 2248, 2248, 2248, 474: 2248, 483: 2248, 2248, 565: 2248, 574: 2248, 576: 2248, 586: 2248, 616: 2248, 635: 2248, 2248}, + {2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 47: 2252, 464: 2252, 467: 2252, 469: 2252, 2252, 2252, 474: 2252, 483: 2252, 2252, 565: 2252, 574: 2252, 576: 2252, 586: 2252, 616: 2252, 635: 2252, 2252}, + {565: 2349, 574: 2349, 576: 2349, 586: 2349, 640: 2349, 666: 2349, 2349}, + {2348, 2348, 2348, 2348, 7: 2348, 483: 2348, 565: 2348, 574: 2348, 576: 2348, 586: 2348, 640: 2348, 666: 2348, 2348}, + {2285, 2285, 2285, 2285, 7: 2285, 2285, 2285, 47: 2285, 483: 2285}, // 2160 - {2342, 2342, 2342, 2342, 7: 2342, 478: 2342}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4622}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4361, 836: 4623}, - {2344, 2344, 2344, 2344, 7: 2344, 4618, 4619, 478: 2344, 917: 4624}, - {2392, 2392, 2392, 2392, 7: 2392, 478: 2392}, + {2407, 2407, 2407, 2407, 7: 2407, 483: 2407}, + {2359, 2359, 2359, 2359, 7: 2359, 483: 2359}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4637}, + {2358, 2358, 2358, 2358, 7: 2358, 483: 2358}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4639}, // 2165 - {2393, 2393, 2393, 2393, 7: 2393, 478: 2393}, - {2394, 2394, 2394, 2394, 7: 2394, 478: 2394}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4630, 970: 4629, 1147: 4628}, - {2395, 2395, 2395, 2395, 7: 4632, 478: 2395}, - {1278, 1278, 1278, 1278, 7: 1278, 478: 1278}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4366, 836: 4640}, + {2360, 2360, 2360, 2360, 7: 2360, 4635, 4636, 483: 2360, 917: 4641}, + {2408, 2408, 2408, 2408, 7: 2408, 483: 2408}, + {2409, 2409, 2409, 2409, 7: 2409, 483: 2409}, + {2410, 2410, 2410, 2410, 7: 2410, 483: 2410}, // 2170 - {1268, 1268, 1268, 1268, 7: 1268, 478: 1268, 518: 4528, 4527, 934: 4631}, - {1276, 1276, 1276, 1276, 7: 1276, 478: 1276}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4630, 970: 4633}, - {1277, 1277, 1277, 1277, 7: 1277, 478: 1277}, - {2: 550, 550, 550, 550, 550, 8: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 58: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 4637, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 641: 550, 808: 4636, 826: 4635}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4647, 973: 4646, 1151: 4645}, + {2411, 2411, 2411, 2411, 7: 4649, 483: 2411}, + {1282, 1282, 1282, 1282, 7: 1282, 483: 1282}, + {1272, 1272, 1272, 1272, 7: 1272, 483: 1272, 521: 4533, 4532, 937: 4648}, + {1280, 1280, 1280, 1280, 7: 1280, 483: 1280}, // 2175 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4638}, - {549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 58: 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, 462: 549, 478: 549, 496: 549, 532: 549, 556: 549, 641: 549}, - {548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 58: 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, 462: 548, 478: 548, 496: 548, 532: 548, 556: 548, 641: 548}, - {2398, 2398, 2398, 2398, 7: 2398, 478: 2398}, - {2367, 2367, 2367, 2367, 7: 2367, 30: 2367, 478: 2367}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4647, 973: 4650}, + {1281, 1281, 1281, 1281, 7: 1281, 483: 1281}, + {2: 553, 553, 553, 553, 553, 8: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 48: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 4654, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 642: 553, 807: 4653, 825: 4652}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4655}, + {552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 48: 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 465: 552, 483: 552, 500: 552, 536: 552, 562: 552, 642: 552}, // 2180 - {2366, 2366, 2366, 2366, 7: 4642, 30: 2366, 478: 2366}, - {2337, 2337, 2337, 2337, 7: 2337, 30: 2337, 57: 2337, 98: 2337, 159: 2337, 463: 2337, 478: 2337, 484: 2337, 638: 2337, 641: 2337}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4643, 2676, 2677, 2675}, - {2336, 2336, 2336, 2336, 7: 2336, 30: 2336, 57: 2336, 98: 2336, 159: 2336, 463: 2336, 478: 2336, 484: 2336, 638: 2336, 641: 2336}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4646}, + {551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 48: 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 551, 465: 551, 483: 551, 500: 551, 536: 551, 562: 551, 642: 551}, + {2414, 2414, 2414, 2414, 7: 2414, 483: 2414}, + {2383, 2383, 2383, 2383, 7: 2383, 18: 2383, 483: 2383}, + {2382, 2382, 2382, 2382, 7: 4659, 18: 2382, 483: 2382}, + {2353, 2353, 2353, 2353, 7: 2353, 18: 2353, 47: 2353, 98: 2353, 160: 2353, 466: 2353, 483: 2353, 487: 2353, 640: 2353, 642: 2353}, // 2185 - {2399, 2399, 2399, 2399, 7: 2399, 478: 2399}, - {30: 4647}, - {2401, 2401, 2401, 2401, 7: 2401, 478: 2401}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4650}, - {2400, 2400, 2400, 2400, 7: 2400, 478: 2400}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4660, 2691, 2692, 2690}, + {2352, 2352, 2352, 2352, 7: 2352, 18: 2352, 47: 2352, 98: 2352, 160: 2352, 466: 2352, 483: 2352, 487: 2352, 640: 2352, 642: 2352}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4663}, + {2415, 2415, 2415, 2415, 7: 2415, 483: 2415}, + {18: 4664}, // 2190 - {30: 4651}, - {2402, 2402, 2402, 2402, 7: 2402, 478: 2402}, - {2: 550, 550, 550, 550, 550, 8: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 58: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 4637, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 641: 550, 808: 4636, 826: 4653}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4654}, - {2403, 2403, 2403, 2403, 7: 2403, 478: 2403}, + {2417, 2417, 2417, 2417, 7: 2417, 483: 2417}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4667}, + {2416, 2416, 2416, 2416, 7: 2416, 483: 2416}, + {18: 4668}, + {2418, 2418, 2418, 2418, 7: 2418, 483: 2418}, // 2195 - {2: 550, 550, 550, 550, 550, 8: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 58: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 4637, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 641: 550, 808: 4636, 826: 4656}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4657}, - {2404, 2404, 2404, 2404, 7: 2404, 478: 2404}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4659}, - {2405, 2405, 2405, 2405, 7: 2405, 478: 2405}, + {2: 553, 553, 553, 553, 553, 8: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 48: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 4654, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 642: 553, 807: 4653, 825: 4670}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4671}, + {2419, 2419, 2419, 2419, 7: 2419, 483: 2419}, + {2: 553, 553, 553, 553, 553, 8: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 48: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 4654, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 642: 553, 807: 4653, 825: 4673}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4674}, // 2200 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4661, 2676, 2677, 2675}, - {463: 4662}, - {556: 4663}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 4664}, - {2365, 2365, 2365, 2365, 7: 2365, 215: 4668, 463: 4667, 478: 2365, 1327: 4666, 4665}, + {2420, 2420, 2420, 2420, 7: 2420, 483: 2420}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4676}, + {2421, 2421, 2421, 2421, 7: 2421, 483: 2421}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4678, 2691, 2692, 2690}, + {466: 4679}, // 2205 - {2406, 2406, 2406, 2406, 7: 2406, 478: 2406}, - {2364, 2364, 2364, 2364, 7: 2364, 478: 2364}, - {190: 4670}, - {190: 4669}, - {2362, 2362, 2362, 2362, 7: 2362, 478: 2362}, + {562: 4680}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 4681}, + {2381, 2381, 2381, 2381, 7: 2381, 215: 4685, 466: 4684, 483: 2381, 1331: 4683, 4682}, + {2422, 2422, 2422, 2422, 7: 2422, 483: 2422}, + {2380, 2380, 2380, 2380, 7: 2380, 483: 2380}, // 2210 - {2363, 2363, 2363, 2363, 7: 2363, 478: 2363}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4689}, - {566: 4688}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4686}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4684}, + {191: 4687}, + {191: 4686}, + {2378, 2378, 2378, 2378, 7: 2378, 483: 2378}, + {2379, 2379, 2379, 2379, 7: 2379, 483: 2379}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4706}, // 2215 - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4682}, - {566: 4679}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4678, 2676, 2677, 2675}, - {2373, 2373, 2373, 2373, 7: 2373, 478: 2373}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 4680}, + {565: 4705}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4703}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4701}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4699}, + {565: 4696}, // 2220 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4615, 2676, 2677, 2675, 1124: 4681}, - {2396, 2396, 2396, 2396, 7: 2396, 478: 2396}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4683, 2676, 2677, 2675}, - {2397, 2397, 2397, 2397, 7: 2397, 478: 2397}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4685, 2676, 2677, 2675}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4695, 2691, 2692, 2690}, + {2389, 2389, 2389, 2389, 7: 2389, 483: 2389}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 4697}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4632, 2691, 2692, 2690, 1128: 4698}, + {2412, 2412, 2412, 2412, 7: 2412, 483: 2412}, // 2225 - {2407, 2407, 2407, 2407, 7: 2407, 478: 2407}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 4687}, - {2408, 2408, 2408, 2408, 7: 4642, 478: 2408}, - {2409, 2409, 2409, 2409, 7: 2409, 478: 2409}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4690}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4700, 2691, 2692, 2690}, + {2413, 2413, 2413, 2413, 7: 2413, 483: 2413}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4702, 2691, 2692, 2690}, + {2423, 2423, 2423, 2423, 7: 2423, 483: 2423}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 4704}, // 2230 - {2004, 2004, 2004, 2004, 7: 2004, 478: 2004, 660: 4693, 662: 4692, 899: 4691}, - {2410, 2410, 2410, 2410, 7: 2410, 478: 2410}, - {2003, 2003, 2003, 2003, 7: 2003, 478: 2003}, - {2002, 2002, 2002, 2002, 7: 2002, 478: 2002}, - {136: 4637, 496: 550, 808: 4636, 826: 4695}, + {2424, 2424, 2424, 2424, 7: 4659, 483: 2424}, + {2425, 2425, 2425, 2425, 7: 2425, 483: 2425}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4707}, + {2011, 2011, 2011, 2011, 7: 2011, 483: 2011, 661: 4710, 663: 4709, 899: 4708}, + {2426, 2426, 2426, 2426, 7: 2426, 483: 2426}, // 2235 - {496: 2650, 725: 4696}, - {2411, 2411, 2411, 2411, 7: 2411, 478: 2411}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 641: 4639, 653: 4641, 2676, 2677, 2675, 779: 4640, 821: 4698}, - {2412, 2412, 2412, 2412, 7: 2412, 478: 2412}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 462: 1815, 555: 4717, 775: 4831}, + {2010, 2010, 2010, 2010, 7: 2010, 483: 2010}, + {2009, 2009, 2009, 2009, 7: 2009, 483: 2009}, + {136: 4654, 500: 553, 807: 4653, 825: 4712}, + {500: 2665, 724: 4713}, + {2427, 2427, 2427, 2427, 7: 2427, 483: 2427}, // 2240 - {2418, 2418, 2418, 2418, 7: 2418, 478: 2418}, - {1815, 1815, 1815, 1815, 7: 1815, 103: 1815, 136: 1815, 462: 1815, 478: 1815, 555: 4717, 775: 4785, 808: 1815}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 4776}, - {566: 4315, 574: 4709, 576: 4704, 632: 4707, 638: 4316, 665: 4708, 4705, 817: 4706, 1174: 4710}, - {566: 4770}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 642: 4656, 654: 4658, 2691, 2692, 2690, 778: 4657, 820: 4715}, + {2428, 2428, 2428, 2428, 7: 2428, 483: 2428}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 465: 1822, 558: 4734, 774: 4848}, + {2434, 2434, 2434, 2434, 7: 2434, 483: 2434}, + {1822, 1822, 1822, 1822, 7: 1822, 103: 1822, 136: 1822, 465: 1822, 483: 1822, 558: 4734, 774: 4802, 807: 1822}, // 2245 - {2: 2348, 2348, 2348, 2348, 2348, 8: 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 58: 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 462: 2348, 566: 4315, 638: 4316, 817: 4726, 1049: 4764}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 462: 1815, 471: 1815, 555: 4717, 775: 4758}, - {2: 2348, 2348, 2348, 2348, 2348, 8: 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 58: 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 462: 2348, 471: 2348, 566: 4315, 638: 4316, 817: 4726, 1049: 4727}, - {566: 4715}, - {462: 4711}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 4793}, + {565: 4320, 574: 4726, 576: 4721, 586: 4724, 640: 4321, 666: 4725, 4722, 816: 4723, 1179: 4727}, + {565: 4787}, + {2: 2364, 2364, 2364, 2364, 2364, 8: 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 48: 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 465: 2364, 565: 4320, 640: 4321, 816: 4743, 1053: 4781}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 465: 1822, 473: 1822, 558: 4734, 774: 4775}, // 2250 - {432, 432, 432, 432, 7: 432, 57: 432, 478: 432}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4712}, - {57: 4713, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2240, 2240, 2240, 2240, 7: 2240, 57: 2240, 147: 4338, 465: 3986, 3985, 478: 2240, 800: 4339, 922: 4583, 1025: 4714}, - {2198, 2198, 2198, 2198, 7: 2198, 57: 2198, 478: 2198}, + {2: 2364, 2364, 2364, 2364, 2364, 8: 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 48: 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 2364, 465: 2364, 473: 2364, 565: 4320, 640: 4321, 816: 4743, 1053: 4744}, + {565: 4732}, + {465: 4728}, + {434, 434, 434, 434, 7: 434, 47: 434, 483: 434}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4729}, // 2255 - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 462: 1815, 555: 4717, 775: 4716}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 1811, 653: 4721, 2676, 2677, 2675, 865: 4720}, - {465: 3986, 3985, 800: 4718}, - {573: 4719}, - {1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 58: 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 1814, 462: 1814, 464: 1814, 471: 1814, 478: 1814, 559: 1814, 808: 1814}, + {47: 4730, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {2256, 2256, 2256, 2256, 7: 2256, 47: 2256, 147: 4343, 467: 4004, 469: 4003, 483: 2256, 799: 4344, 922: 4588, 1029: 4731}, + {2214, 2214, 2214, 2214, 7: 2214, 47: 2214, 483: 2214}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 465: 1822, 558: 4734, 774: 4733}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 1818, 654: 4738, 2691, 2692, 2690, 866: 4737}, // 2260 - {462: 4722}, - {462: 1810}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4723}, - {7: 4532, 57: 4724}, - {635: 4516, 898: 4725}, + {467: 4004, 469: 4003, 799: 4735}, + {578: 4736}, + {1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 48: 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 1821, 465: 1821, 468: 1821, 473: 1821, 483: 1821, 561: 1821, 807: 1821}, + {465: 4739}, + {465: 1817}, // 2265 - {2199, 2199, 2199, 2199, 7: 2199, 57: 2199, 478: 2199}, - {2: 2347, 2347, 2347, 2347, 2347, 8: 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 58: 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 462: 2347, 471: 2347}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 1811, 471: 1811, 653: 4729, 2676, 2677, 2675, 865: 4730, 930: 4728}, - {462: 4738}, - {93: 4736, 462: 1810, 471: 1810}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4740}, + {7: 4537, 47: 4741}, + {635: 4521, 898: 4742}, + {2215, 2215, 2215, 2215, 7: 2215, 47: 2215, 483: 2215}, + {2: 2363, 2363, 2363, 2363, 2363, 8: 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 48: 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 2363, 465: 2363, 473: 2363}, // 2270 - {462: 1801, 471: 4731}, - {140: 4734, 170: 4733, 183: 4735, 893: 4732}, - {462: 1800}, - {1794, 1794, 1794, 1794, 1794, 7: 1794, 29: 1794, 57: 1794, 92: 1794, 1794, 1794, 1794, 1794, 1794, 461: 1794, 1794, 1794, 471: 1794, 478: 1794, 486: 1794}, - {1793, 1793, 1793, 1793, 1793, 7: 1793, 29: 1793, 57: 1793, 92: 1793, 1793, 1793, 1793, 1793, 1793, 461: 1793, 1793, 1793, 471: 1793, 478: 1793, 486: 1793}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 1818, 473: 1818, 654: 4746, 2691, 2692, 2690, 866: 4747, 930: 4745}, + {465: 4755}, + {82: 4753, 465: 1817, 473: 1817}, + {465: 1808, 473: 4748}, + {140: 4751, 170: 4750, 184: 4752, 893: 4749}, // 2275 - {1792, 1792, 1792, 1792, 1792, 7: 1792, 29: 1792, 57: 1792, 92: 1792, 1792, 1792, 1792, 1792, 1792, 461: 1792, 1792, 1792, 471: 1792, 478: 1792, 486: 1792}, - {140: 4734, 170: 4733, 183: 4735, 893: 4737}, - {462: 1799}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4739}, - {7: 4532, 57: 4740}, + {465: 1807}, + {1801, 1801, 1801, 1801, 1801, 7: 1801, 17: 1801, 47: 1801, 81: 1801, 1801, 1801, 1801, 1801, 87: 1801, 464: 1801, 1801, 1801, 473: 1801, 483: 1801, 488: 1801}, + {1800, 1800, 1800, 1800, 1800, 7: 1800, 17: 1800, 47: 1800, 81: 1800, 1800, 1800, 1800, 1800, 87: 1800, 464: 1800, 1800, 1800, 473: 1800, 483: 1800, 488: 1800}, + {1799, 1799, 1799, 1799, 1799, 7: 1799, 17: 1799, 47: 1799, 81: 1799, 1799, 1799, 1799, 1799, 87: 1799, 464: 1799, 1799, 1799, 473: 1799, 483: 1799, 488: 1799}, + {140: 4751, 170: 4750, 184: 4752, 893: 4754}, // 2280 - {1809, 1809, 1809, 1809, 1809, 7: 1809, 29: 1809, 57: 1809, 93: 1809, 1809, 1809, 1809, 1809, 463: 1809, 471: 1809, 478: 1809, 867: 4741}, - {2200, 2200, 2200, 2200, 4746, 7: 2200, 29: 4743, 57: 2200, 93: 4750, 4610, 4335, 4611, 4334, 463: 4745, 471: 4749, 478: 2200, 845: 4747, 847: 4744, 857: 4748, 866: 4742}, - {1808, 1808, 1808, 1808, 1808, 7: 1808, 29: 1808, 57: 1808, 92: 1808, 1808, 1808, 1808, 1808, 1808, 463: 1808, 471: 1808, 478: 1808, 486: 1808}, - {485: 4187, 496: 1999, 726: 4756}, - {1806, 1806, 1806, 1806, 1806, 7: 1806, 29: 1806, 57: 1806, 92: 1806, 1806, 1806, 1806, 1806, 1806, 463: 1806, 471: 1806, 478: 1806, 486: 1806}, + {465: 1806}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4756}, + {7: 4537, 47: 4757}, + {1816, 1816, 1816, 1816, 1816, 7: 1816, 17: 1816, 47: 1816, 82: 1816, 1816, 1816, 1816, 87: 1816, 466: 1816, 473: 1816, 483: 1816, 868: 4758}, + {2216, 2216, 2216, 2216, 4763, 7: 2216, 17: 4760, 47: 2216, 82: 4767, 4627, 4340, 4628, 87: 4339, 466: 4762, 473: 4766, 483: 2216, 845: 4764, 847: 4761, 857: 4765, 867: 4759}, // 2285 - {353: 4754}, - {464: 4753}, - {1803, 1803, 1803, 1803, 1803, 7: 1803, 29: 1803, 57: 1803, 92: 1803, 1803, 1803, 1803, 1803, 1803, 463: 1803, 471: 1803, 478: 1803, 486: 1803}, - {1802, 1802, 1802, 1802, 1802, 7: 1802, 29: 1802, 57: 1802, 92: 1802, 1802, 1802, 1802, 1802, 1802, 463: 1802, 471: 1802, 478: 1802, 486: 1802}, - {140: 4734, 170: 4733, 183: 4735, 893: 4752}, + {1815, 1815, 1815, 1815, 1815, 7: 1815, 17: 1815, 47: 1815, 81: 1815, 1815, 1815, 1815, 1815, 87: 1815, 466: 1815, 473: 1815, 483: 1815, 488: 1815}, + {489: 4192, 500: 2006, 727: 4773}, + {1813, 1813, 1813, 1813, 1813, 7: 1813, 17: 1813, 47: 1813, 81: 1813, 1813, 1813, 1813, 1813, 87: 1813, 466: 1813, 473: 1813, 483: 1813, 488: 1813}, + {358: 4771}, + {468: 4770}, // 2290 - {140: 4734, 170: 4733, 183: 4735, 893: 4751}, - {1795, 1795, 1795, 1795, 1795, 7: 1795, 29: 1795, 57: 1795, 92: 1795, 1795, 1795, 1795, 1795, 1795, 461: 1795, 463: 1795, 471: 1795, 478: 1795, 486: 1795}, - {1796, 1796, 1796, 1796, 1796, 7: 1796, 29: 1796, 57: 1796, 92: 1796, 1796, 1796, 1796, 1796, 1796, 461: 1796, 463: 1796, 471: 1796, 478: 1796, 486: 1796}, - {1804, 1804, 1804, 1804, 1804, 7: 1804, 29: 1804, 57: 1804, 92: 1804, 1804, 1804, 1804, 1804, 1804, 463: 1804, 471: 1804, 478: 1804, 486: 1804}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4755, 2676, 2677, 2675}, + {1810, 1810, 1810, 1810, 1810, 7: 1810, 17: 1810, 47: 1810, 81: 1810, 1810, 1810, 1810, 1810, 87: 1810, 466: 1810, 473: 1810, 483: 1810, 488: 1810}, + {1809, 1809, 1809, 1809, 1809, 7: 1809, 17: 1809, 47: 1809, 81: 1809, 1809, 1809, 1809, 1809, 87: 1809, 466: 1809, 473: 1809, 483: 1809, 488: 1809}, + {140: 4751, 170: 4750, 184: 4752, 893: 4769}, + {140: 4751, 170: 4750, 184: 4752, 893: 4768}, + {1802, 1802, 1802, 1802, 1802, 7: 1802, 17: 1802, 47: 1802, 81: 1802, 1802, 1802, 1802, 1802, 87: 1802, 464: 1802, 466: 1802, 473: 1802, 483: 1802, 488: 1802}, // 2295 - {1805, 1805, 1805, 1805, 1805, 7: 1805, 29: 1805, 57: 1805, 92: 1805, 1805, 1805, 1805, 1805, 1805, 463: 1805, 471: 1805, 478: 1805, 486: 1805}, - {496: 2650, 725: 2649, 734: 4757}, - {1807, 1807, 1807, 1807, 1807, 7: 1807, 29: 1807, 57: 1807, 92: 1807, 1807, 1807, 1807, 1807, 1807, 463: 1807, 471: 1807, 478: 1807, 486: 1807}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 1811, 471: 1811, 653: 4729, 2676, 2677, 2675, 865: 4730, 930: 4759}, - {462: 4760}, + {1803, 1803, 1803, 1803, 1803, 7: 1803, 17: 1803, 47: 1803, 81: 1803, 1803, 1803, 1803, 1803, 87: 1803, 464: 1803, 466: 1803, 473: 1803, 483: 1803, 488: 1803}, + {1811, 1811, 1811, 1811, 1811, 7: 1811, 17: 1811, 47: 1811, 81: 1811, 1811, 1811, 1811, 1811, 87: 1811, 466: 1811, 473: 1811, 483: 1811, 488: 1811}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4772, 2691, 2692, 2690}, + {1812, 1812, 1812, 1812, 1812, 7: 1812, 17: 1812, 47: 1812, 81: 1812, 1812, 1812, 1812, 1812, 87: 1812, 466: 1812, 473: 1812, 483: 1812, 488: 1812}, + {500: 2665, 724: 2664, 734: 4774}, // 2300 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4761}, - {7: 4532, 57: 4762}, - {1809, 1809, 1809, 1809, 1809, 7: 1809, 29: 1809, 57: 1809, 93: 1809, 1809, 1809, 1809, 1809, 463: 1809, 471: 1809, 478: 1809, 867: 4763}, - {2201, 2201, 2201, 2201, 4746, 7: 2201, 29: 4743, 57: 2201, 93: 4750, 4610, 4335, 4611, 4334, 463: 4745, 471: 4749, 478: 2201, 845: 4747, 847: 4744, 857: 4748, 866: 4742}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 1811, 653: 4721, 2676, 2677, 2675, 865: 4765}, + {1814, 1814, 1814, 1814, 1814, 7: 1814, 17: 1814, 47: 1814, 81: 1814, 1814, 1814, 1814, 1814, 87: 1814, 466: 1814, 473: 1814, 483: 1814, 488: 1814}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 1818, 473: 1818, 654: 4746, 2691, 2692, 2690, 866: 4747, 930: 4776}, + {465: 4777}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4778}, + {7: 4537, 47: 4779}, // 2305 - {462: 4766}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4767}, - {7: 4532, 57: 4768}, - {1809, 1809, 1809, 1809, 1809, 7: 1809, 29: 1809, 57: 1809, 93: 1809, 1809, 1809, 1809, 1809, 463: 1809, 471: 1809, 478: 1809, 867: 4769}, - {2202, 2202, 2202, 2202, 4746, 7: 2202, 29: 4743, 57: 2202, 93: 4750, 4610, 4335, 4611, 4334, 463: 4745, 471: 4749, 478: 2202, 845: 4747, 847: 4744, 857: 4748, 866: 4742}, + {1816, 1816, 1816, 1816, 1816, 7: 1816, 17: 1816, 47: 1816, 82: 1816, 1816, 1816, 1816, 87: 1816, 466: 1816, 473: 1816, 483: 1816, 868: 4780}, + {2217, 2217, 2217, 2217, 4763, 7: 2217, 17: 4760, 47: 2217, 82: 4767, 4627, 4340, 4628, 87: 4339, 466: 4762, 473: 4766, 483: 2217, 845: 4764, 847: 4761, 857: 4765, 867: 4759}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 1818, 654: 4738, 2691, 2692, 2690, 866: 4782}, + {465: 4783}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4784}, // 2310 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 1811, 471: 1811, 653: 4729, 2676, 2677, 2675, 865: 4730, 930: 4771}, - {462: 4772}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 4773}, - {7: 4532, 57: 4774}, - {1809, 1809, 1809, 1809, 1809, 7: 1809, 29: 1809, 57: 1809, 93: 1809, 1809, 1809, 1809, 1809, 463: 1809, 471: 1809, 478: 1809, 867: 4775}, + {7: 4537, 47: 4785}, + {1816, 1816, 1816, 1816, 1816, 7: 1816, 17: 1816, 47: 1816, 82: 1816, 1816, 1816, 1816, 87: 1816, 466: 1816, 473: 1816, 483: 1816, 868: 4786}, + {2218, 2218, 2218, 2218, 4763, 7: 2218, 17: 4760, 47: 2218, 82: 4767, 4627, 4340, 4628, 87: 4339, 466: 4762, 473: 4766, 483: 2218, 845: 4764, 847: 4761, 857: 4765, 867: 4759}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 1818, 473: 1818, 654: 4746, 2691, 2692, 2690, 866: 4747, 930: 4788}, + {465: 4789}, // 2315 - {2203, 2203, 2203, 2203, 4746, 7: 2203, 29: 4743, 57: 2203, 93: 4750, 4610, 4335, 4611, 4334, 463: 4745, 471: 4749, 478: 2203, 845: 4747, 847: 4744, 857: 4748, 866: 4742}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4777, 2676, 2677, 2675}, - {222: 4779, 231: 4781, 234: 4780, 1120: 4778}, - {462: 4782}, - {57: 2158, 462: 2158}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 4790}, + {7: 4537, 47: 4791}, + {1816, 1816, 1816, 1816, 1816, 7: 1816, 17: 1816, 47: 1816, 82: 1816, 1816, 1816, 1816, 87: 1816, 466: 1816, 473: 1816, 483: 1816, 868: 4792}, + {2219, 2219, 2219, 2219, 4763, 7: 2219, 17: 4760, 47: 2219, 82: 4767, 4627, 4340, 4628, 87: 4339, 466: 4762, 473: 4766, 483: 2219, 845: 4764, 847: 4761, 857: 4765, 867: 4759}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4794, 2691, 2692, 2690}, // 2320 - {57: 2157, 462: 2157}, - {57: 2156, 462: 2156}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 4783}, - {7: 4043, 57: 4784}, - {2415, 2415, 2415, 2415, 7: 2415, 478: 2415}, + {222: 4796, 231: 4798, 234: 4797, 1124: 4795}, + {465: 4799}, + {47: 2168, 465: 2168}, + {47: 2167, 465: 2167}, + {47: 2166, 465: 2166}, // 2325 - {550, 550, 550, 550, 7: 550, 103: 550, 136: 4637, 462: 550, 478: 550, 808: 4636, 826: 4786}, - {2094, 2094, 2094, 2094, 7: 2094, 103: 4788, 462: 4789, 478: 2094, 1080: 4787}, - {2417, 2417, 2417, 2417, 7: 2417, 478: 2417}, - {496: 2650, 725: 4830}, - {478: 4792, 937: 4791, 1079: 4790}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 4800}, + {7: 4061, 47: 4801}, + {2431, 2431, 2431, 2431, 7: 2431, 483: 2431}, + {553, 553, 553, 553, 7: 553, 103: 553, 136: 4654, 465: 553, 483: 553, 807: 4653, 825: 4803}, + {2101, 2101, 2101, 2101, 7: 2101, 103: 4805, 465: 4806, 483: 2101, 1083: 4804}, // 2330 - {7: 4828, 57: 4827}, - {7: 2092, 57: 2092}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4793, 2676, 2677, 2675}, - {4: 2071, 2071, 7: 2071, 15: 2071, 2071, 2071, 2071, 2071, 2071, 2071, 2071, 2071, 2071, 2071, 2071, 30: 2071, 2071, 2071, 2071, 2071, 2071, 2071, 57: 2071, 146: 4798, 330: 4797, 462: 2071, 467: 4796, 487: 4795, 638: 2071, 1249: 4794}, - {4: 2084, 2084, 7: 2084, 15: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 30: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 57: 2084, 462: 2084, 638: 2084, 936: 4814}, + {2433, 2433, 2433, 2433, 7: 2433, 483: 2433}, + {500: 2665, 724: 4847}, + {483: 4809, 940: 4808, 1082: 4807}, + {7: 4845, 47: 4844}, + {7: 2099, 47: 2099}, // 2335 - {339: 4799, 533: 4800}, - {4: 2068, 2068, 7: 2068, 15: 2068, 2068, 2068, 2068, 2068, 2068, 2068, 2068, 2068, 2068, 2068, 2068, 30: 2068, 2068, 2068, 2068, 2068, 2068, 2068, 57: 2068, 462: 2068, 638: 2068}, - {4: 2066, 2066, 7: 2066, 15: 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066, 2066, 30: 2066, 2066, 2066, 2066, 2066, 2066, 2066, 57: 2066, 462: 2066, 638: 2066}, - {4: 2065, 2065, 7: 2065, 15: 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 30: 2065, 2065, 2065, 2065, 2065, 2065, 2065, 57: 2065, 462: 2065, 638: 2065}, - {384: 4809}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4810, 2691, 2692, 2690}, + {4: 2078, 2078, 7: 2078, 16: 2078, 18: 2078, 20: 2078, 2078, 2078, 2078, 2078, 2078, 47: 2078, 146: 4815, 335: 4814, 465: 2078, 471: 4813, 493: 4812, 640: 2078, 1253: 4811}, + {4: 2091, 2091, 7: 2091, 16: 2091, 18: 2091, 20: 2091, 2091, 2091, 2091, 2091, 2091, 47: 2091, 465: 2091, 640: 2091, 939: 4831}, + {344: 4816, 535: 4817}, + {4: 2075, 2075, 7: 2075, 16: 2075, 18: 2075, 20: 2075, 2075, 2075, 2075, 2075, 2075, 47: 2075, 465: 2075, 640: 2075}, // 2340 - {462: 4801}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 647: 4803, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4804, 933: 4805, 1060: 4802}, - {7: 4807, 57: 4806}, - {7: 1891, 57: 1891}, - {7: 1890, 57: 1890, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, + {4: 2073, 2073, 7: 2073, 16: 2073, 18: 2073, 20: 2073, 2073, 2073, 2073, 2073, 2073, 47: 2073, 465: 2073, 640: 2073}, + {4: 2072, 2072, 7: 2072, 16: 2072, 18: 2072, 20: 2072, 2072, 2072, 2072, 2072, 2072, 47: 2072, 465: 2072, 640: 2072}, + {388: 4826}, + {465: 4818}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 648: 4820, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4821, 933: 4822, 1065: 4819}, // 2345 - {7: 1878, 57: 1878}, - {4: 2067, 2067, 7: 2067, 15: 2067, 2067, 2067, 2067, 2067, 2067, 2067, 2067, 2067, 2067, 2067, 2067, 30: 2067, 2067, 2067, 2067, 2067, 2067, 2067, 57: 2067, 462: 2067, 638: 2067}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 647: 4803, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4804, 933: 4808}, - {7: 1877, 57: 1877}, - {462: 4811, 647: 4810}, + {7: 4824, 47: 4823}, + {7: 1898, 47: 1898}, + {7: 1897, 47: 1897, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {7: 1885, 47: 1885}, + {4: 2074, 2074, 7: 2074, 16: 2074, 18: 2074, 20: 2074, 2074, 2074, 2074, 2074, 2074, 47: 2074, 465: 2074, 640: 2074}, // 2350 - {4: 2070, 2070, 7: 2070, 15: 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 30: 2070, 2070, 2070, 2070, 2070, 2070, 2070, 57: 2070, 462: 2070, 638: 2070}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 647: 4803, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4804, 933: 4805, 1060: 4812}, - {7: 4807, 57: 4813}, - {4: 2069, 2069, 7: 2069, 15: 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 30: 2069, 2069, 2069, 2069, 2069, 2069, 2069, 57: 2069, 462: 2069, 638: 2069}, - {4: 4147, 4818, 7: 2089, 15: 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 30: 4155, 4148, 4151, 4150, 4153, 4154, 4156, 57: 2089, 462: 4816, 638: 4152, 761: 4103, 767: 4104, 770: 4157, 802: 4817, 1291: 4815}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 648: 4820, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4821, 933: 4825}, + {7: 1884, 47: 1884}, + {465: 4828, 648: 4827}, + {4: 2077, 2077, 7: 2077, 16: 2077, 18: 2077, 20: 2077, 2077, 2077, 2077, 2077, 2077, 47: 2077, 465: 2077, 640: 2077}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 648: 4820, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4821, 933: 4822, 1065: 4829}, // 2355 - {7: 2090, 57: 2090}, - {100: 4821, 1122: 4820, 1290: 4819}, - {2083, 2083, 4: 2083, 2083, 7: 2083, 15: 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 30: 2083, 2083, 2083, 2083, 2083, 2083, 2083, 57: 2083, 462: 2083, 638: 2083}, - {31: 4286}, - {7: 4825, 57: 4824}, + {7: 4824, 47: 4830}, + {4: 2076, 2076, 7: 2076, 16: 2076, 18: 2076, 20: 2076, 2076, 2076, 2076, 2076, 2076, 47: 2076, 465: 2076, 640: 2076}, + {4: 4152, 4835, 7: 2096, 16: 4110, 18: 4160, 20: 4153, 4156, 4155, 4158, 4159, 4161, 47: 2096, 465: 4833, 640: 4157, 770: 4162, 801: 4834, 1295: 4832}, + {7: 2097, 47: 2097}, + {100: 4838, 1126: 4837, 1294: 4836}, // 2360 - {7: 2087, 57: 2087}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4822, 2676, 2677, 2675}, - {4: 2084, 2084, 7: 2084, 15: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 30: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 57: 2084, 638: 2084, 936: 4823}, - {4: 4147, 4818, 7: 2085, 15: 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 30: 4155, 4148, 4151, 4150, 4153, 4154, 4156, 57: 2085, 638: 4152, 761: 4103, 767: 4104, 770: 4157, 802: 4817}, - {7: 2088, 57: 2088}, + {2090, 2090, 4: 2090, 2090, 7: 2090, 16: 2090, 18: 2090, 20: 2090, 2090, 2090, 2090, 2090, 2090, 47: 2090, 465: 2090, 640: 2090}, + {20: 4291}, + {7: 4842, 47: 4841}, + {7: 2094, 47: 2094}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4839, 2691, 2692, 2690}, // 2365 - {100: 4821, 1122: 4826}, - {7: 2086, 57: 2086}, - {2093, 2093, 2093, 2093, 7: 2093, 461: 2093, 2093, 2093, 468: 2093, 477: 2093, 2093, 487: 2093, 494: 2093, 556: 2093, 634: 2093}, - {478: 4792, 937: 4829}, - {7: 2091, 57: 2091}, + {4: 2091, 2091, 7: 2091, 16: 2091, 18: 2091, 20: 2091, 2091, 2091, 2091, 2091, 2091, 47: 2091, 640: 2091, 939: 4840}, + {4: 4152, 4835, 7: 2092, 16: 4110, 18: 4160, 20: 4153, 4156, 4155, 4158, 4159, 4161, 47: 2092, 640: 4157, 770: 4162, 801: 4834}, + {7: 2095, 47: 2095}, + {100: 4838, 1126: 4843}, + {7: 2093, 47: 2093}, // 2370 - {2416, 2416, 2416, 2416, 7: 2416, 478: 2416}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4833, 653: 4040, 2676, 2677, 2675, 733: 4361, 836: 4832}, - {2344, 2344, 2344, 2344, 7: 2344, 4618, 4619, 478: 2344, 917: 4841}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 566: 2335, 574: 2335, 576: 2335, 632: 2335, 4494, 638: 2335, 653: 4040, 2676, 2677, 2675, 665: 2335, 2335, 733: 4361, 822: 4703, 836: 4835, 891: 4836, 953: 4837, 1125: 4834}, - {7: 4839, 57: 4838}, + {2100, 2100, 2100, 2100, 7: 2100, 464: 2100, 2100, 2100, 470: 2100, 482: 2100, 2100, 493: 2100, 499: 2100, 562: 2100, 637: 2100}, + {483: 4809, 940: 4846}, + {7: 2098, 47: 2098}, + {2432, 2432, 2432, 2432, 7: 2432, 483: 2432}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4850, 654: 4058, 2691, 2692, 2690, 735: 4366, 836: 4849}, // 2375 - {7: 429, 57: 429}, - {7: 428, 57: 428}, - {7: 427, 57: 427}, - {2419, 2419, 2419, 2419, 7: 2419, 478: 2419}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 566: 2335, 574: 2335, 576: 2335, 632: 2335, 4494, 638: 2335, 653: 4040, 2676, 2677, 2675, 665: 2335, 2335, 733: 4361, 822: 4703, 836: 4835, 891: 4836, 953: 4840}, + {2360, 2360, 2360, 2360, 7: 2360, 4635, 4636, 483: 2360, 917: 4858}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 565: 2351, 574: 2351, 576: 2351, 586: 2351, 616: 4499, 640: 2351, 654: 4058, 2691, 2692, 2690, 666: 2351, 2351, 735: 4366, 821: 4720, 836: 4852, 891: 4853, 956: 4854, 1129: 4851}, + {7: 4856, 47: 4855}, + {7: 431, 47: 431}, + {7: 430, 47: 430}, // 2380 - {7: 426, 57: 426}, - {2420, 2420, 2420, 2420, 7: 2420, 478: 2420}, - {13: 3735, 489: 3736, 637: 3734, 762: 4843}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 467: 4845, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 4844}, - {257, 257, 257, 257, 7: 257, 470: 4847, 478: 257, 1071: 4849}, + {7: 429, 47: 429}, + {2435, 2435, 2435, 2435, 7: 2435, 483: 2435}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 565: 2351, 574: 2351, 576: 2351, 586: 2351, 616: 4499, 640: 2351, 654: 4058, 2691, 2692, 2690, 666: 2351, 2351, 735: 4366, 821: 4720, 836: 4852, 891: 4853, 956: 4857}, + {7: 428, 47: 428}, + {2436, 2436, 2436, 2436, 7: 2436, 483: 2436}, // 2385 - {257, 257, 257, 257, 7: 257, 470: 4847, 478: 257, 1071: 4846}, - {2421, 2421, 2421, 2421, 7: 2421, 478: 2421}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3390, 653: 3392, 2676, 2677, 2675, 728: 3389, 860: 4848}, - {256, 256, 256, 256, 7: 256, 478: 256}, - {2422, 2422, 2422, 2422, 7: 2422, 478: 2422}, + {14: 3753, 498: 3754, 638: 3752, 762: 4860}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 471: 4862, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 4861}, + {259, 259, 259, 259, 7: 259, 474: 4864, 483: 259, 1074: 4866}, + {259, 259, 259, 259, 7: 259, 474: 4864, 483: 259, 1074: 4863}, + {2437, 2437, 2437, 2437, 7: 2437, 483: 2437}, // 2390 - {366: 4851}, - {496: 2650, 725: 2649, 734: 4852}, - {2426, 2426, 2426, 2426, 7: 2426, 201: 4853, 478: 2426, 1224: 4854}, - {254: 4855}, - {2423, 2423, 2423, 2423, 7: 2423, 478: 2423}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3408, 654: 3410, 2691, 2692, 2690, 729: 3407, 860: 4865}, + {258, 258, 258, 258, 7: 258, 483: 258}, + {2438, 2438, 2438, 2438, 7: 2438, 483: 2438}, + {267: 4868}, + {500: 2665, 724: 2664, 734: 4869}, // 2395 - {464: 4857, 1287: 4856}, - {2425, 2425, 2425, 2425, 7: 4858, 478: 2425}, - {255, 255, 255, 255, 7: 255, 478: 255}, - {464: 4859}, - {254, 254, 254, 254, 7: 254, 478: 254}, + {2442, 2442, 2442, 2442, 7: 2442, 176: 4870, 483: 2442, 1063: 4871}, + {254: 4872}, + {2439, 2439, 2439, 2439, 7: 2439, 483: 2439}, + {468: 4874, 1291: 4873}, + {2441, 2441, 2441, 2441, 7: 4875, 14: 2441, 16: 2441, 19: 2441, 471: 2441, 474: 2441, 483: 2441, 496: 2441, 498: 2441, 638: 2441}, // 2400 - {6: 388, 38: 388}, - {382, 382, 382, 382, 382, 382, 382, 382, 13: 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 461: 382, 382, 382, 467: 382, 382, 382, 382, 477: 382, 382, 487: 382, 382, 382, 494: 382, 556: 382, 634: 382, 637: 382, 382}, - {4: 4147, 4149, 389, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 467: 4146, 469: 4183, 2118, 488: 4860, 2118, 637: 2118, 4152, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4863}, - {381, 381, 381, 381, 381, 381, 381, 381, 13: 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 461: 381, 381, 381, 467: 381, 381, 381, 381, 477: 381, 381, 487: 381, 381, 381, 494: 381, 556: 381, 634: 381, 637: 381, 381}, - {464: 4866, 467: 4865}, + {257, 257, 257, 257, 7: 257, 14: 257, 16: 257, 19: 257, 471: 257, 474: 257, 483: 257, 496: 257, 498: 257, 638: 257}, + {468: 4876}, + {256, 256, 256, 256, 7: 256, 14: 256, 16: 256, 19: 256, 471: 256, 474: 256, 483: 256, 496: 256, 498: 256, 638: 256}, + {6: 390, 27: 390}, + {384, 384, 384, 384, 384, 384, 384, 384, 13: 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 464: 384, 384, 384, 470: 384, 384, 384, 474: 384, 482: 384, 384, 493: 384, 495: 384, 498: 384, 384, 562: 384, 637: 384, 384, 640: 384}, // 2405 - {2433, 2433, 2433, 2433, 7: 2433, 478: 2433}, - {2432, 2432, 2432, 2432, 7: 2432, 478: 2432}, - {464: 4869, 467: 4868}, - {2435, 2435, 2435, 2435, 7: 2435, 478: 2435}, - {2434, 2434, 2434, 2434, 7: 2434, 478: 2434}, + {4: 4152, 4154, 391, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 471: 4151, 4188, 474: 2125, 495: 4877, 498: 2125, 638: 2125, 640: 4157, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4880}, + {383, 383, 383, 383, 383, 383, 383, 383, 13: 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 464: 383, 383, 383, 470: 383, 383, 383, 474: 383, 482: 383, 383, 493: 383, 495: 383, 498: 383, 383, 562: 383, 637: 383, 383, 640: 383}, + {468: 4883, 471: 4882}, + {2449, 2449, 2449, 2449, 7: 2449, 483: 2449}, + {2448, 2448, 2448, 2448, 7: 2448, 483: 2448}, // 2410 - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 467: 1999, 485: 4187, 501: 4872, 726: 4871}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 4874, 467: 4876, 653: 4877, 2676, 2677, 2675, 873: 4875}, - {467: 4873}, - {2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 13: 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 2436, 461: 2436, 2436, 2436, 467: 2436, 2436, 2436, 2436, 477: 2436, 2436, 487: 2436, 2436, 2436, 494: 2436, 556: 2436, 634: 2436, 637: 2436, 2436}, - {2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 13: 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 2439, 461: 2439, 2439, 2439, 467: 2439, 2439, 2439, 2439, 477: 2439, 2439, 487: 2439, 2439, 2439, 494: 2439, 556: 2439, 634: 2439, 637: 2439, 2439}, + {468: 4886, 471: 4885}, + {2451, 2451, 2451, 2451, 7: 2451, 483: 2451}, + {2450, 2450, 2450, 2450, 7: 2450, 483: 2450}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 471: 2006, 489: 4192, 496: 4889, 727: 4888}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 4891, 471: 4893, 654: 4894, 2691, 2692, 2690, 874: 4892}, // 2415 - {2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 13: 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 2438, 461: 2438, 2438, 2438, 467: 2438, 2438, 2438, 2438, 477: 2438, 2438, 487: 2438, 2438, 2438, 494: 2438, 556: 2438, 634: 2438, 637: 2438, 2438}, - {2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 13: 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 2437, 461: 2437, 2437, 2437, 467: 2437, 2437, 2437, 2437, 477: 2437, 2437, 487: 2437, 2437, 2437, 494: 2437, 556: 2437, 634: 2437, 637: 2437, 2437}, - {2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 13: 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 461: 2133, 2133, 2133, 467: 2133, 2133, 2133, 2133, 477: 2133, 2133, 487: 2133, 2133, 2133, 494: 2133, 556: 2133, 634: 2133, 637: 2133, 2133}, - {464: 4879}, - {2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 13: 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 2442, 461: 2442, 2442, 2442, 467: 2442, 2442, 2442, 2442, 477: 2442, 2442, 487: 2442, 2442, 2442, 494: 2442, 556: 2442, 634: 2442, 637: 2442, 2442}, + {471: 4890}, + {2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 13: 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 47: 2452, 464: 2452, 2452, 2452, 470: 2452, 2452, 2452, 474: 2452, 482: 2452, 2452, 493: 2452, 495: 2452, 2452, 498: 2452, 2452, 562: 2452, 637: 2452, 2452, 640: 2452}, + {2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 13: 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 47: 2455, 464: 2455, 2455, 2455, 470: 2455, 2455, 2455, 474: 2455, 482: 2455, 2455, 493: 2455, 495: 2455, 2455, 498: 2455, 2455, 562: 2455, 637: 2455, 2455, 640: 2455}, + {2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 13: 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 47: 2454, 464: 2454, 2454, 2454, 470: 2454, 2454, 2454, 474: 2454, 482: 2454, 2454, 493: 2454, 495: 2454, 2454, 498: 2454, 2454, 562: 2454, 637: 2454, 2454, 640: 2454}, + {2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 13: 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 47: 2453, 464: 2453, 2453, 2453, 470: 2453, 2453, 2453, 474: 2453, 482: 2453, 2453, 493: 2453, 495: 2453, 2453, 498: 2453, 2453, 562: 2453, 637: 2453, 2453, 640: 2453}, // 2420 - {464: 4881}, - {2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 13: 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 2443, 461: 2443, 2443, 2443, 467: 2443, 2443, 2443, 2443, 477: 2443, 2443, 487: 2443, 2443, 2443, 494: 2443, 556: 2443, 634: 2443, 637: 2443, 2443}, - {464: 4883}, - {2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 13: 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 2444, 461: 2444, 2444, 2444, 467: 2444, 2444, 2444, 2444, 477: 2444, 2444, 487: 2444, 2444, 2444, 494: 2444, 556: 2444, 634: 2444, 637: 2444, 2444}, - {464: 4885}, + {2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 13: 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 47: 2141, 86: 2141, 88: 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 2141, 464: 2141, 2141, 2141, 470: 2141, 2141, 2141, 474: 2141, 482: 2141, 2141, 493: 2141, 495: 2141, 2141, 498: 2141, 2141, 562: 2141, 637: 2141, 2141, 640: 2141}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 4896}, + {2312, 2312, 7: 4659, 466: 4899, 640: 4898, 793: 4897}, + {2471, 2471}, + {884, 884, 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 884, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 4914}, // 2425 - {2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 13: 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 2445, 461: 2445, 2445, 2445, 467: 2445, 2445, 2445, 2445, 477: 2445, 2445, 487: 2445, 2445, 2445, 494: 2445, 556: 2445, 634: 2445, 637: 2445, 2445}, - {464: 4887}, - {2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 13: 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 2446, 461: 2446, 2446, 2446, 467: 2446, 2446, 2446, 2446, 477: 2446, 2446, 487: 2446, 2446, 2446, 494: 2446, 556: 2446, 634: 2446, 637: 2446, 2446}, - {464: 4889}, - {2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 13: 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 2447, 461: 2447, 2447, 2447, 467: 2447, 2447, 2447, 2447, 477: 2447, 2447, 487: 2447, 2447, 2447, 494: 2447, 556: 2447, 634: 2447, 637: 2447, 2447}, + {500: 4904, 566: 3344, 3343, 724: 4902, 808: 4903, 979: 4901, 1156: 4900}, + {2311, 2311, 7: 4912}, + {2310, 2310, 7: 2310}, + {221: 4906, 225: 4908, 271: 4909, 291: 4907}, + {186: 4905}, // 2430 - {496: 2650, 725: 2649, 734: 4891}, - {2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 13: 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 461: 2448, 2448, 2448, 467: 2448, 2448, 2448, 2448, 477: 2448, 2448, 487: 2448, 2448, 2448, 494: 2448, 556: 2448, 634: 2448, 637: 2448, 2448}, - {496: 2650, 725: 2649, 734: 4893}, - {2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 13: 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 2449, 461: 2449, 2449, 2449, 467: 2449, 2449, 2449, 2449, 477: 2449, 2449, 487: 2449, 2449, 2449, 494: 2449, 556: 2449, 634: 2449, 637: 2449, 2449}, - {496: 2650, 725: 2649, 734: 4895}, + {186: 2171, 221: 1937, 225: 1937, 271: 1937, 291: 1937}, + {2303, 2303, 7: 2303}, + {2308, 2308, 7: 2308}, + {2307, 2307, 7: 2307}, + {318: 4910, 398: 4911}, // 2435 - {2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 13: 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 2450, 461: 2450, 2450, 2450, 467: 2450, 2450, 2450, 2450, 477: 2450, 2450, 487: 2450, 2450, 2450, 494: 2450, 556: 2450, 634: 2450, 637: 2450, 2450}, - {464: 4897}, - {2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 13: 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 2451, 461: 2451, 2451, 2451, 467: 2451, 2451, 2451, 2451, 477: 2451, 2451, 487: 2451, 2451, 2451, 494: 2451, 556: 2451, 634: 2451, 637: 2451, 2451}, - {464: 4899}, - {2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 13: 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 2452, 461: 2452, 2452, 2452, 467: 2452, 2452, 2452, 2452, 477: 2452, 2452, 487: 2452, 2452, 2452, 494: 2452, 556: 2452, 634: 2452, 637: 2452, 2452}, + {2304, 2304, 7: 2304}, + {2306, 2306, 7: 2306}, + {2305, 2305, 7: 2305}, + {500: 4904, 566: 3344, 3343, 724: 4902, 808: 4903, 979: 4913}, + {2309, 2309, 7: 2309}, // 2440 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 4901}, - {2296, 2296, 7: 4642, 463: 4904, 638: 4903, 794: 4902}, - {2457, 2457}, - {880, 880, 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 880, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 4919}, - {496: 4909, 562: 3326, 3325, 725: 4907, 809: 4908, 976: 4906, 1152: 4905}, + {2312, 2312, 7: 4918, 466: 4899, 793: 4917}, + {883, 883, 7: 883, 47: 883, 466: 883}, + {881, 881, 7: 881, 47: 881, 466: 881}, + {2470, 2470}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 576: 4920, 654: 4919, 2691, 2692, 2690}, // 2445 - {2295, 2295, 7: 4917}, - {2294, 2294, 7: 2294}, - {221: 4911, 225: 4913, 270: 4914, 289: 4912}, - {185: 4910}, - {185: 2161, 221: 1930, 225: 1930, 270: 1930, 289: 1930}, + {882, 882, 7: 882, 47: 882, 466: 882}, + {880, 880, 7: 880, 47: 880, 466: 880}, + {2472, 2472}, + {2447, 2447}, + {360: 4988}, // 2450 - {2287, 2287, 7: 2287}, - {2292, 2292, 7: 2292}, - {2291, 2291, 7: 2291}, - {315: 4915, 395: 4916}, - {2288, 2288, 7: 2288}, + {483: 4980}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 650: 4927, 654: 4926, 2691, 2692, 2690}, + {2091, 2091, 4: 2091, 2091, 16: 2091, 18: 2091, 20: 2091, 2091, 2091, 2091, 2091, 2091, 193: 4111, 640: 2091, 914: 4978, 939: 4979}, + {140: 2109, 346: 4932, 383: 4933, 519: 4931, 565: 2109, 1058: 4934, 4929, 1127: 4930, 1255: 4928}, + {2103, 2103, 100: 2103, 103: 4968, 464: 2103, 2103, 2103, 470: 2103, 482: 2103, 493: 2103, 499: 2103, 562: 2103, 637: 2103, 1256: 4967}, // 2455 - {2290, 2290, 7: 2290}, - {2289, 2289, 7: 2289}, - {496: 4909, 562: 3326, 3325, 725: 4907, 809: 4908, 976: 4918}, - {2293, 2293, 7: 2293}, - {2296, 2296, 7: 4923, 463: 4904, 794: 4922}, + {140: 4955, 565: 4954}, + {2117, 2117, 100: 2117, 103: 2117, 464: 2117, 2117, 2117, 470: 2117, 482: 2117, 493: 2117, 499: 2117, 562: 2117, 637: 2117}, + {98: 3861, 107: 3860, 465: 4947, 822: 4948}, + {98: 3861, 107: 3860, 465: 4940, 822: 4941}, + {2110, 2110, 100: 2110, 103: 2110, 464: 2110, 2110, 2110, 470: 2110, 482: 2110, 486: 4936, 493: 2110, 499: 2110, 562: 2110, 573: 4935, 637: 2110}, // 2460 - {879, 879, 7: 879, 57: 879, 463: 879}, - {877, 877, 7: 877, 57: 877, 463: 877}, - {2456, 2456}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 576: 4925, 653: 4924, 2676, 2677, 2675}, - {878, 878, 7: 878, 57: 878, 463: 878}, + {140: 2108, 565: 2108}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 4938}, + {500: 2665, 724: 2664, 734: 4937}, + {2111, 2111, 100: 2111, 103: 2111, 464: 2111, 2111, 2111, 470: 2111, 482: 2111, 493: 2111, 499: 2111, 562: 2111, 637: 2111}, + {105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 497: 3265, 501: 3263, 3264, 3262, 3260, 523: 3373, 3370, 3372, 3371, 3367, 3369, 3368, 3365, 3366, 3364, 3374, 725: 3261, 3259, 795: 3363, 818: 4939}, // 2465 - {876, 876, 7: 876, 57: 876, 463: 876}, - {2458, 2458}, - {2431, 2431}, - {355: 4993}, - {478: 4985}, + {2112, 2112, 100: 2112, 103: 2112, 464: 2112, 2112, 2112, 470: 2112, 482: 2112, 493: 2112, 499: 2112, 562: 2112, 637: 2112}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4945}, + {465: 4942}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 4943}, + {7: 4061, 47: 4944}, // 2470 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 649: 4932, 653: 4931, 2676, 2677, 2675}, - {2084, 2084, 4: 2084, 2084, 15: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 2084, 30: 2084, 2084, 2084, 2084, 2084, 2084, 2084, 192: 4106, 638: 2084, 914: 4983, 936: 4984}, - {140: 2102, 341: 4937, 379: 4938, 516: 4936, 566: 2102, 1054: 4939, 4934, 1123: 4935, 1251: 4933}, - {2096, 2096, 100: 2096, 103: 4973, 461: 2096, 2096, 2096, 468: 2096, 477: 2096, 487: 2096, 494: 2096, 556: 2096, 634: 2096, 1252: 4972}, - {140: 4960, 566: 4959}, + {2113, 2113, 100: 2113, 103: 2113, 464: 2113, 2113, 2113, 470: 2113, 482: 2113, 493: 2113, 499: 2113, 562: 2113, 637: 2113}, + {47: 4946, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2114, 2114, 100: 2114, 103: 2114, 464: 2114, 2114, 2114, 470: 2114, 482: 2114, 493: 2114, 499: 2114, 562: 2114, 637: 2114}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4952}, + {465: 4949}, // 2475 - {2110, 2110, 100: 2110, 103: 2110, 461: 2110, 2110, 2110, 468: 2110, 477: 2110, 487: 2110, 494: 2110, 556: 2110, 634: 2110}, - {98: 3843, 107: 3842, 462: 4952, 823: 4953}, - {98: 3843, 107: 3842, 462: 4945, 823: 4946}, - {2103, 2103, 100: 2103, 103: 2103, 461: 2103, 2103, 2103, 468: 2103, 477: 2103, 483: 4941, 487: 2103, 494: 2103, 556: 2103, 570: 4940, 634: 2103}, - {140: 2101, 566: 2101}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 4950}, + {7: 4061, 47: 4951}, + {2115, 2115, 100: 2115, 103: 2115, 464: 2115, 2115, 2115, 470: 2115, 482: 2115, 493: 2115, 499: 2115, 562: 2115, 637: 2115}, + {47: 4953, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2116, 2116, 100: 2116, 103: 2116, 464: 2116, 2116, 2116, 470: 2116, 482: 2116, 493: 2116, 499: 2116, 562: 2116, 637: 2116}, // 2480 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 4943}, - {496: 2650, 725: 2649, 734: 4942}, - {2104, 2104, 100: 2104, 103: 2104, 461: 2104, 2104, 2104, 468: 2104, 477: 2104, 487: 2104, 494: 2104, 556: 2104, 634: 2104}, - {105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 495: 3249, 497: 3247, 3248, 3246, 3244, 520: 3355, 3352, 3354, 3353, 3349, 3351, 3350, 3347, 3348, 3346, 3356, 723: 3245, 3243, 796: 3345, 819: 4944}, - {2105, 2105, 100: 2105, 103: 2105, 461: 2105, 2105, 2105, 468: 2105, 477: 2105, 487: 2105, 494: 2105, 556: 2105, 634: 2105}, + {81: 4960, 465: 2119, 1254: 4959}, + {465: 4956}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 4957}, + {47: 4958, 477: 3606, 3605, 3611, 515: 3607, 548: 3608, 3609, 3602, 3612, 3601, 3610, 3603, 3604}, + {2120, 2120, 100: 2120, 103: 2120, 212: 2120, 464: 2120, 2120, 2120, 470: 2120, 482: 2120, 493: 2120, 499: 2120, 562: 2120, 637: 2120}, // 2485 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4950}, - {462: 4947}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 4948}, - {7: 4043, 57: 4949}, - {2106, 2106, 100: 2106, 103: 2106, 461: 2106, 2106, 2106, 468: 2106, 477: 2106, 487: 2106, 494: 2106, 556: 2106, 634: 2106}, + {465: 4963}, + {489: 4961}, + {500: 2665, 724: 4962}, + {465: 2118}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 2278, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 4964, 990: 4965}, // 2490 - {57: 4951, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2107, 2107, 100: 2107, 103: 2107, 461: 2107, 2107, 2107, 468: 2107, 477: 2107, 487: 2107, 494: 2107, 556: 2107, 634: 2107}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4957}, - {462: 4954}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 4955}, + {7: 4061, 47: 2277}, + {47: 4966}, + {2121, 2121, 100: 2121, 103: 2121, 212: 2121, 464: 2121, 2121, 2121, 470: 2121, 482: 2121, 493: 2121, 499: 2121, 562: 2121, 637: 2121}, + {2107, 2107, 100: 4971, 464: 2107, 2107, 2107, 470: 2107, 482: 2107, 493: 2107, 499: 2107, 562: 2107, 637: 2107, 1297: 4970}, + {500: 2665, 724: 2664, 734: 4969}, // 2495 - {7: 4043, 57: 4956}, - {2108, 2108, 100: 2108, 103: 2108, 461: 2108, 2108, 2108, 468: 2108, 477: 2108, 487: 2108, 494: 2108, 556: 2108, 634: 2108}, - {57: 4958, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2109, 2109, 100: 2109, 103: 2109, 461: 2109, 2109, 2109, 468: 2109, 477: 2109, 487: 2109, 494: 2109, 556: 2109, 634: 2109}, - {92: 4965, 462: 2112, 1250: 4964}, + {2102, 2102, 100: 2102, 464: 2102, 2102, 2102, 470: 2102, 482: 2102, 493: 2102, 499: 2102, 562: 2102, 637: 2102}, + {2101, 2101, 464: 2101, 4806, 2101, 470: 2101, 482: 2101, 493: 2101, 499: 2101, 562: 2101, 637: 2101, 1083: 4977}, + {650: 4972}, + {140: 2109, 565: 2109, 1058: 4934, 4929, 1127: 4973}, + {2105, 2105, 212: 4975, 464: 2105, 2105, 2105, 470: 2105, 482: 2105, 493: 2105, 499: 2105, 562: 2105, 637: 2105, 1296: 4974}, // 2500 - {462: 4961}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 4962}, - {57: 4963, 474: 3588, 3587, 3593, 512: 3589, 545: 3590, 3591, 3584, 3594, 3583, 3592, 3585, 3586}, - {2113, 2113, 100: 2113, 103: 2113, 212: 2113, 461: 2113, 2113, 2113, 468: 2113, 477: 2113, 487: 2113, 494: 2113, 556: 2113, 634: 2113}, - {462: 4968}, + {2106, 2106, 464: 2106, 2106, 2106, 470: 2106, 482: 2106, 493: 2106, 499: 2106, 562: 2106, 637: 2106}, + {500: 2665, 724: 2664, 734: 4976}, + {2104, 2104, 464: 2104, 2104, 2104, 470: 2104, 482: 2104, 493: 2104, 499: 2104, 562: 2104, 637: 2104}, + {2122, 2122, 464: 2122, 2122, 2122, 470: 2122, 482: 2122, 493: 2122, 499: 2122, 562: 2122, 637: 2122}, + {2444, 2444}, // 2505 - {485: 4966}, - {496: 2650, 725: 4967}, - {462: 2111}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 2262, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 4969, 986: 4970}, - {7: 4043, 57: 2261}, + {2443, 2443, 4: 4152, 4835, 16: 4110, 18: 4160, 20: 4153, 4156, 4155, 4158, 4159, 4161, 640: 4157, 770: 4162, 801: 4834}, + {553, 553, 553, 553, 553, 553, 553, 8: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 48: 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 4654, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 807: 4653, 825: 4981}, + {2385, 2385, 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 4983, 1264: 4982}, + {2445, 2445}, + {7: 4659, 487: 4984}, // 2510 - {57: 4971}, - {2114, 2114, 100: 2114, 103: 2114, 212: 2114, 461: 2114, 2114, 2114, 468: 2114, 477: 2114, 487: 2114, 494: 2114, 556: 2114, 634: 2114}, - {2100, 2100, 100: 4976, 461: 2100, 2100, 2100, 468: 2100, 477: 2100, 487: 2100, 494: 2100, 556: 2100, 634: 2100, 1293: 4975}, - {496: 2650, 725: 2649, 734: 4974}, - {2095, 2095, 100: 2095, 461: 2095, 2095, 2095, 468: 2095, 477: 2095, 487: 2095, 494: 2095, 556: 2095, 634: 2095}, + {465: 4985}, + {483: 4809, 940: 4808, 1082: 4986}, + {7: 4845, 47: 4987}, + {2384, 2384}, + {2446, 2446}, // 2515 - {2094, 2094, 461: 2094, 4789, 2094, 468: 2094, 477: 2094, 487: 2094, 494: 2094, 556: 2094, 634: 2094, 1080: 4982}, - {649: 4977}, - {140: 2102, 566: 2102, 1054: 4939, 4934, 1123: 4978}, - {2098, 2098, 212: 4980, 461: 2098, 2098, 2098, 468: 2098, 477: 2098, 487: 2098, 494: 2098, 556: 2098, 634: 2098, 1292: 4979}, - {2099, 2099, 461: 2099, 2099, 2099, 468: 2099, 477: 2099, 487: 2099, 494: 2099, 556: 2099, 634: 2099}, + {136: 4990, 869: 96, 1062: 4991}, + {869: 95}, + {869: 4992}, + {468: 4993}, + {17, 17, 177: 17, 348: 4995, 649: 17, 1234: 4994}, // 2520 - {496: 2650, 725: 2649, 734: 4981}, - {2097, 2097, 461: 2097, 2097, 2097, 468: 2097, 477: 2097, 487: 2097, 494: 2097, 556: 2097, 634: 2097}, - {2115, 2115, 461: 2115, 2115, 2115, 468: 2115, 477: 2115, 487: 2115, 494: 2115, 556: 2115, 634: 2115}, - {2428, 2428}, - {2427, 2427, 4: 4147, 4818, 15: 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 30: 4155, 4148, 4151, 4150, 4153, 4154, 4156, 638: 4152, 761: 4103, 767: 4104, 770: 4157, 802: 4817}, + {15, 15, 177: 4998, 649: 15, 1233: 4997}, + {500: 2665, 724: 4996}, + {16, 16, 177: 16, 649: 16}, + {81, 81, 649: 3882, 932: 5005}, + {13, 13, 181: 13, 361: 5000, 649: 13, 1258: 4999}, // 2525 - {550, 550, 550, 550, 550, 550, 550, 8: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 58: 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 4637, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 808: 4636, 826: 4986}, - {2369, 2369, 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 4988, 1260: 4987}, - {2429, 2429}, - {7: 4642, 484: 4989}, - {462: 4990}, + {11, 11, 181: 5003, 649: 11, 1257: 5002}, + {500: 2665, 724: 5001}, + {12, 12, 181: 12, 649: 12}, + {14, 14, 649: 14}, + {500: 2665, 724: 5004}, // 2530 - {478: 4792, 937: 4791, 1079: 4991}, - {7: 4828, 57: 4992}, - {2368, 2368}, - {2430, 2430}, - {136: 4995, 868: 96, 1058: 4996}, - // 2535 - {868: 95}, - {868: 4997}, - {464: 4998}, - {17, 17, 176: 17, 343: 5000, 648: 17, 1230: 4999}, - {15, 15, 176: 5003, 648: 15, 1229: 5002}, - // 2540 - {496: 2650, 725: 5001}, - {16, 16, 176: 16, 648: 16}, - {81, 81, 648: 3864, 932: 5010}, - {13, 13, 180: 13, 356: 5005, 648: 13, 1254: 5004}, - {11, 11, 180: 5008, 648: 11, 1253: 5007}, - // 2545 - {496: 2650, 725: 5006}, - {12, 12, 180: 12, 648: 12}, - {14, 14, 648: 14}, - {496: 2650, 725: 5009}, - {10, 10, 648: 10}, - // 2550 + {10, 10, 649: 10}, {18, 18}, - {37: 55, 143: 55, 496: 55}, + {26: 55, 143: 55, 500: 55}, {59, 59}, - {496: 2650, 725: 5016}, - {496: 2650, 725: 5015}, - // 2555 + {500: 2665, 724: 5011}, + // 2535 + {500: 2665, 724: 5010}, {57, 57}, {58, 58}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5021, 1126: 5022, 1295: 5020}, - {68, 68, 68, 68, 68, 68, 68, 8: 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 58: 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68}, - {67, 67, 67, 67, 67, 67, 67, 8: 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 58: 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}, - // 2560 - {69, 69, 7: 5028}, - {661: 5024, 677: 5025, 1225: 5023}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5016, 1130: 5017, 1299: 5015}, + {68, 68, 68, 68, 68, 68, 68, 8: 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 48: 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68}, + // 2540 + {67, 67, 67, 67, 67, 67, 67, 8: 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 48: 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}, + {69, 69, 7: 5023}, + {662: 5019, 678: 5020, 1229: 5018}, {61, 61, 7: 61}, {66, 66, 7: 66}, - {65, 65, 7: 65, 136: 5027}, - // 2565 - {63, 63, 7: 63, 136: 5026}, + // 2545 + {65, 65, 7: 65, 136: 5022}, + {63, 63, 7: 63, 136: 5021}, {62, 62, 7: 62}, {64, 64, 7: 64}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5021, 1126: 5029}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5016, 1130: 5024}, + // 2550 {60, 60, 7: 60}, - // 2570 {70, 70}, - {136: 4995, 868: 96, 1058: 5034}, - {464: 5033}, + {136: 4990, 869: 96, 1062: 5029}, + {468: 5028}, {54, 54}, - {868: 5035}, + // 2555 + {869: 5030}, + {468: 5031}, + {482: 5032, 487: 2071, 499: 5033, 1026: 5034}, + {2070, 2070, 464: 2070, 2070, 2070, 470: 2070, 487: 2070, 493: 2070, 562: 2070, 637: 2070}, + {2069, 2069, 464: 2069, 2069, 2069, 470: 2069, 487: 2069, 493: 2069, 562: 2069, 637: 2069}, + // 2560 + {487: 5035}, + {562: 5036}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5037}, + {98, 98, 98: 98, 107: 98, 465: 98, 482: 98, 496: 98, 638: 5039, 649: 98, 1169: 5038}, + {94, 94, 98: 3861, 107: 3860, 465: 94, 482: 94, 496: 94, 649: 94, 822: 3859, 1036: 5042}, + // 2565 + {496: 5040}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 5041}, + {97, 97, 98: 97, 107: 97, 465: 97, 482: 97, 496: 97, 649: 97}, + {81, 81, 465: 81, 482: 81, 496: 81, 649: 3882, 932: 5043}, + {100, 100, 465: 100, 482: 5045, 496: 100, 1211: 5044}, + // 2570 + {2266, 2266, 465: 5048, 496: 2266, 1175: 5049}, + {500: 2665, 724: 5046}, + {649: 5047}, + {99, 99, 465: 99, 496: 99}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 2272, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 560: 3268, 654: 4058, 2691, 2692, 2690, 701: 5062, 735: 5061, 991: 5060, 1173: 5059, 5063}, // 2575 - {464: 5036}, - {477: 5037, 484: 2064, 494: 5038, 1022: 5039}, - {2063, 2063, 461: 2063, 2063, 2063, 468: 2063, 484: 2063, 487: 2063, 556: 2063, 634: 2063}, - {2062, 2062, 461: 2062, 2062, 2062, 468: 2062, 484: 2062, 487: 2062, 556: 2062, 634: 2062}, - {484: 5040}, + {75, 75, 496: 5051, 1228: 5050}, + {101, 101}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3697, 2691, 2692, 2690, 702: 5054, 1060: 5053, 1227: 5052}, + {74, 74, 7: 5057}, + {72, 72, 7: 72}, // 2580 - {556: 5041}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5042}, - {98, 98, 98: 98, 107: 98, 462: 98, 477: 98, 501: 98, 637: 5044, 648: 98, 1164: 5043}, - {94, 94, 98: 3843, 107: 3842, 462: 94, 477: 94, 501: 94, 648: 94, 823: 3841, 1032: 5047}, - {501: 5045}, + {489: 5055}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5056}, + {71, 71, 7: 71}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3697, 2691, 2692, 2690, 702: 5054, 1060: 5058}, + {73, 73, 7: 73}, // 2585 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 5046}, - {97, 97, 98: 97, 107: 97, 462: 97, 477: 97, 501: 97, 648: 97}, - {81, 81, 462: 81, 477: 81, 501: 81, 648: 3864, 932: 5048}, - {100, 100, 462: 100, 477: 5050, 501: 100, 1206: 5049}, - {2250, 2250, 462: 5053, 501: 2250, 1170: 5054}, + {7: 5065, 47: 2271}, + {7: 2270, 47: 2270}, + {7: 2268, 47: 2268}, + {7: 2267, 47: 2267}, + {47: 5064}, // 2590 - {496: 2650, 725: 5051}, - {648: 5052}, - {99, 99, 462: 99, 501: 99}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 2256, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 558: 3252, 653: 4040, 2676, 2677, 2675, 700: 5067, 733: 5066, 987: 5065, 1168: 5064, 5068}, - {75, 75, 501: 5056, 1223: 5055}, + {2265, 2265, 496: 2265}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 560: 3268, 654: 4058, 2691, 2692, 2690, 701: 5062, 735: 5061, 991: 5066}, + {7: 2269, 47: 2269}, + {7: 158, 149: 158, 464: 158, 490: 158, 560: 1796, 641: 158, 658: 1796}, + {7: 123, 464: 123, 123, 490: 123, 560: 1766, 641: 123, 658: 1766}, // 2595 - {101, 101}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3679, 2676, 2677, 2675, 701: 5059, 1056: 5058, 1222: 5057}, - {74, 74, 7: 5062}, - {72, 72, 7: 72}, - {485: 5060}, + {7: 137, 464: 137, 137, 490: 137, 560: 1740, 641: 137, 658: 1740}, + {7: 124, 464: 124, 124, 490: 124, 560: 1737, 641: 124, 658: 1737}, + {7: 113, 464: 113, 113, 490: 113, 560: 1702, 641: 113, 658: 1702}, + {7: 133, 464: 133, 133, 490: 133, 560: 1625, 641: 133, 658: 1625}, + {7: 138, 464: 138, 138, 490: 138, 560: 1618, 641: 138, 658: 1618}, // 2600 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5061}, - {71, 71, 7: 71}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3679, 2676, 2677, 2675, 701: 5059, 1056: 5063}, - {73, 73, 7: 73}, - {7: 5070, 57: 2255}, + {310: 5176, 376: 5175, 560: 1600, 658: 1600}, + {7: 125, 464: 125, 125, 490: 125, 560: 1597, 641: 125, 658: 1597}, + {7: 114, 464: 114, 114, 490: 114, 560: 1594, 641: 114, 658: 1594}, + {560: 5173, 658: 5172}, + {7: 711, 464: 711, 490: 711, 560: 250, 641: 711, 658: 250}, // 2605 - {7: 2254, 57: 2254}, - {7: 2252, 57: 2252}, - {7: 2251, 57: 2251}, - {57: 5069}, - {2249, 2249, 501: 2249}, + {7: 710, 464: 710, 490: 710, 641: 710}, + {7: 154, 149: 5171, 464: 154, 490: 154, 641: 154}, + {7: 156, 464: 156, 490: 156, 641: 156}, + {7: 155, 464: 155, 490: 155, 641: 155}, + {490: 5169}, // 2610 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 558: 3252, 653: 4040, 2676, 2677, 2675, 700: 5067, 733: 5066, 987: 5071}, - {7: 2253, 57: 2253}, - {7: 158, 163: 158, 461: 158, 490: 158, 558: 1789, 640: 158, 657: 1789}, - {7: 123, 461: 123, 123, 490: 123, 558: 1760, 640: 123, 657: 1760}, - {7: 137, 461: 137, 137, 490: 137, 558: 1734, 640: 137, 657: 1734}, + {7: 134, 464: 134, 134, 487: 5167, 490: 134, 641: 134}, + {7: 151, 464: 151, 490: 151, 641: 151}, + {7: 5119, 464: 5120, 490: 5121}, + {7: 149, 464: 149, 5116, 490: 149, 641: 149}, + {7: 147, 182: 5115, 464: 147, 147, 490: 147, 641: 147}, // 2615 - {7: 124, 461: 124, 124, 490: 124, 558: 1731, 640: 124, 657: 1731}, - {7: 113, 461: 113, 113, 490: 113, 558: 1696, 640: 113, 657: 1696}, - {7: 133, 461: 133, 133, 490: 133, 558: 1621, 640: 133, 657: 1621}, - {7: 138, 461: 138, 138, 490: 138, 558: 1614, 640: 138, 657: 1614}, - {307: 5181, 372: 5180, 558: 1596, 657: 1596}, + {7: 145, 269: 5114, 464: 145, 145, 490: 145, 641: 145}, + {7: 144, 18: 5108, 99: 5110, 161: 5109, 163: 5107, 167: 5111, 269: 5112, 464: 144, 144, 490: 144, 641: 144}, + {7: 141, 464: 141, 141, 490: 141, 641: 141}, + {7: 140, 464: 140, 140, 490: 140, 641: 140}, + {7: 139, 167: 5106, 464: 139, 139, 490: 139, 641: 139}, // 2620 - {7: 125, 461: 125, 125, 490: 125, 558: 1593, 640: 125, 657: 1593}, - {7: 114, 461: 114, 114, 490: 114, 558: 1590, 640: 114, 657: 1590}, - {558: 5178, 657: 5177}, - {7: 707, 461: 707, 490: 707, 558: 248, 640: 707, 657: 248}, - {7: 706, 461: 706, 490: 706, 640: 706}, + {7: 136, 464: 136, 136, 490: 136, 641: 136}, + {7: 135, 464: 135, 135, 490: 135, 641: 135}, + {99: 5105, 1009: 5104}, + {7: 131, 464: 131, 131, 490: 131, 641: 131}, + {894: 5103}, // 2625 - {7: 154, 163: 5176, 461: 154, 490: 154, 640: 154}, - {7: 156, 461: 156, 490: 156, 640: 156}, - {7: 155, 461: 155, 490: 155, 640: 155}, - {490: 5174}, - {7: 134, 461: 134, 134, 484: 5172, 490: 134, 640: 134}, + {7: 129, 464: 129, 129, 490: 129, 641: 129}, + {7: 126, 464: 126, 126, 490: 126, 641: 126}, + {110: 5102}, + {7: 121, 464: 121, 121, 490: 121, 641: 121}, + {7: 130, 464: 130, 130, 490: 130, 641: 130}, // 2630 - {7: 151, 461: 151, 490: 151, 640: 151}, - {7: 5124, 461: 5125, 490: 5126}, - {7: 149, 461: 149, 5121, 490: 149, 640: 149}, - {7: 147, 181: 5120, 461: 147, 147, 490: 147, 640: 147}, - {7: 145, 268: 5119, 461: 145, 145, 490: 145, 640: 145}, + {7: 132, 464: 132, 132, 490: 132, 641: 132}, + {7: 119, 464: 119, 119, 490: 119, 641: 119}, + {7: 117, 464: 117, 117, 490: 117, 641: 117}, + {7: 143, 464: 143, 143, 490: 143, 641: 143}, + {7: 142, 464: 142, 142, 490: 142, 641: 142}, // 2635 - {7: 144, 30: 5113, 99: 5115, 160: 5114, 162: 5112, 167: 5116, 268: 5117, 461: 144, 144, 490: 144, 640: 144}, - {7: 141, 461: 141, 141, 490: 141, 640: 141}, - {7: 140, 461: 140, 140, 490: 140, 640: 140}, - {7: 139, 167: 5111, 461: 139, 139, 490: 139, 640: 139}, - {7: 136, 461: 136, 136, 490: 136, 640: 136}, + {110: 5113}, + {7: 120, 464: 120, 120, 490: 120, 641: 120}, + {7: 118, 464: 118, 118, 490: 118, 641: 118}, + {7: 116, 464: 116, 116, 490: 116, 641: 116}, + {7: 122, 464: 122, 122, 490: 122, 641: 122}, // 2640 - {7: 135, 461: 135, 135, 490: 135, 640: 135}, - {99: 5110, 1005: 5109}, - {7: 131, 461: 131, 131, 490: 131, 640: 131}, - {894: 5108}, - {7: 129, 461: 129, 129, 490: 129, 640: 129}, + {7: 115, 464: 115, 115, 490: 115, 641: 115}, + {7: 146, 464: 146, 146, 490: 146, 641: 146}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 5117}, + {7: 4061, 47: 5118}, + {7: 148, 464: 148, 490: 148, 641: 148}, // 2645 - {7: 126, 461: 126, 126, 490: 126, 640: 126}, - {110: 5107}, - {7: 121, 461: 121, 121, 490: 121, 640: 121}, - {7: 130, 461: 130, 130, 490: 130, 640: 130}, - {7: 132, 461: 132, 132, 490: 132, 640: 132}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5067, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 5069, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 5075, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 5071, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 5068, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 5076, 3128, 2861, 3081, 5070, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 5073, 2772, 2773, 3011, 5074, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 5072, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5078, 488: 5101, 559: 5095, 635: 5099, 637: 5084, 640: 5094, 642: 5088, 645: 5097, 653: 5089, 3410, 2691, 2692, 2690, 660: 5093, 665: 5090, 729: 5077, 733: 5092, 790: 5079, 798: 5083, 843: 5098, 854: 5096, 924: 5080, 945: 5081, 5087, 951: 5082, 5166, 960: 5091, 962: 5100}, + {2: 112, 112, 112, 112, 112, 8: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 48: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 5133, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 515: 112, 562: 5132, 947: 5134, 1068: 5135}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 5125}, + {724, 724, 7: 724, 13: 724, 46: 724, 99: 724, 141: 724, 466: 724, 473: 724, 489: 724, 560: 5130, 641: 724, 652: 724, 658: 5129, 724}, + {1179, 1179, 7: 1179, 13: 1179, 46: 1179, 99: 1179, 141: 1179, 465: 3687, 1179, 473: 1179, 489: 1179, 641: 1179, 652: 1179, 659: 1179, 1077: 5128}, // 2650 - {7: 119, 461: 119, 119, 490: 119, 640: 119}, - {7: 117, 461: 117, 117, 490: 117, 640: 117}, - {7: 143, 461: 143, 143, 490: 143, 640: 143}, - {7: 142, 461: 142, 142, 490: 142, 640: 142}, - {110: 5118}, + {720, 720, 7: 720, 466: 720}, + {102, 102, 7: 5126}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5127}, + {719, 719, 7: 719, 466: 719}, + {721, 721, 7: 721, 13: 721, 46: 721, 99: 721, 141: 721, 466: 721, 473: 721, 489: 721, 641: 721, 652: 721, 659: 721}, // 2655 - {7: 120, 461: 120, 120, 490: 120, 640: 120}, - {7: 118, 461: 118, 118, 490: 118, 640: 118}, - {7: 116, 461: 116, 116, 490: 116, 640: 116}, - {7: 122, 461: 122, 122, 490: 122, 640: 122}, - {7: 115, 461: 115, 115, 490: 115, 640: 115}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 5131}, + {722, 722, 7: 722, 13: 722, 46: 722, 99: 722, 141: 722, 466: 722, 473: 722, 489: 722, 641: 722, 652: 722, 659: 722}, + {723, 723, 7: 723, 13: 723, 46: 723, 99: 723, 141: 723, 466: 723, 473: 723, 489: 723, 641: 723, 652: 723, 659: 723}, + {2: 111, 111, 111, 111, 111, 8: 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 48: 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 515: 111}, + {2: 110, 110, 110, 110, 110, 8: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 48: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 515: 110}, // 2660 - {7: 146, 461: 146, 146, 490: 146, 640: 146}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 5122}, - {7: 4043, 57: 5123}, - {7: 148, 461: 148, 490: 148, 640: 148}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5072, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 5074, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 5080, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 5076, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 5073, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 5081, 3110, 2843, 3063, 5075, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 5078, 2756, 2757, 2993, 5079, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 5077, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5083, 486: 5106, 557: 5100, 634: 5089, 5104, 638: 5099, 641: 5093, 644: 5102, 652: 5094, 3392, 2676, 2677, 2675, 659: 5098, 664: 5095, 728: 5082, 732: 5097, 791: 5084, 799: 5088, 843: 5103, 854: 5101, 924: 5085, 942: 5086, 5092, 948: 5087, 5171, 957: 5096, 959: 5105}, + {2: 109, 109, 109, 109, 109, 8: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 48: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 515: 109}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5136, 654: 5137, 2691, 2692, 2690, 1091: 5138}, + {490: 108, 641: 108, 643: 5164}, + {490: 104, 641: 104, 643: 5161}, + {490: 5139}, // 2665 - {2: 112, 112, 112, 112, 112, 8: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 58: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 5138, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 512: 112, 556: 5137, 944: 5139, 1065: 5140}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 5130}, - {720, 720, 7: 720, 14: 720, 58: 720, 99: 720, 141: 720, 463: 720, 471: 720, 485: 720, 558: 5135, 640: 720, 651: 720, 657: 5134, 720}, - {1175, 1175, 7: 1175, 14: 1175, 58: 1175, 99: 1175, 141: 1175, 462: 3669, 1175, 471: 1175, 485: 1175, 640: 1175, 651: 1175, 658: 1175, 1074: 5133}, - {716, 716, 7: 716, 463: 716}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5140, 879: 5141, 910: 5142}, + {192, 192, 7: 192, 13: 192, 46: 192, 141: 5146, 466: 192, 652: 192, 1160: 5145}, + {227, 227, 7: 227, 13: 227, 46: 227, 466: 227, 652: 227}, + {103, 103, 7: 5143}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5140, 879: 5144}, // 2670 - {102, 102, 7: 5131}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5132}, - {715, 715, 7: 715, 463: 715}, - {717, 717, 7: 717, 14: 717, 58: 717, 99: 717, 141: 717, 463: 717, 471: 717, 485: 717, 640: 717, 651: 717, 658: 717}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 5136}, + {226, 226, 7: 226, 13: 226, 46: 226, 466: 226, 652: 226}, + {228, 228, 7: 228, 13: 228, 46: 228, 466: 228, 652: 228}, + {466: 5148, 650: 5147}, + {13: 5159, 468: 5156, 881: 5158}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 5150, 1161: 5149}, // 2675 - {718, 718, 7: 718, 14: 718, 58: 718, 99: 718, 141: 718, 463: 718, 471: 718, 485: 718, 640: 718, 651: 718, 658: 718}, - {719, 719, 7: 719, 14: 719, 58: 719, 99: 719, 141: 719, 463: 719, 471: 719, 485: 719, 640: 719, 651: 719, 658: 719}, - {2: 111, 111, 111, 111, 111, 8: 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 58: 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 512: 111}, - {2: 110, 110, 110, 110, 110, 8: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 58: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 512: 110}, - {2: 109, 109, 109, 109, 109, 8: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 58: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 512: 109}, + {190, 190, 7: 190, 13: 190, 46: 190, 466: 190, 470: 5152, 650: 5151, 652: 190}, + {186, 186, 7: 186, 13: 186, 46: 186, 466: 186, 470: 186, 650: 186, 652: 186}, + {468: 5156, 881: 5157}, + {468: 5154, 569: 5155, 1045: 5153}, + {188, 188, 7: 188, 13: 188, 46: 188, 466: 188, 652: 188}, // 2680 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 5141, 653: 5142, 2676, 2677, 2675, 1088: 5143}, - {490: 108, 640: 108, 642: 5169}, - {490: 104, 640: 104, 642: 5166}, - {490: 5144}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5145, 878: 5146, 910: 5147}, + {185, 185, 7: 185, 13: 185, 46: 185, 466: 185, 652: 185}, + {184, 184, 7: 184, 13: 184, 46: 184, 466: 184, 652: 184}, + {716, 716, 7: 716, 13: 716, 46: 716, 716, 466: 716, 652: 716}, + {189, 189, 7: 189, 13: 189, 46: 189, 466: 189, 652: 189}, + {191, 191, 7: 191, 13: 191, 46: 191, 466: 191, 652: 191}, // 2685 - {190, 190, 7: 190, 14: 190, 58: 190, 141: 5151, 463: 190, 651: 190, 1156: 5150}, - {225, 225, 7: 225, 14: 225, 58: 225, 463: 225, 651: 225}, - {103, 103, 7: 5148}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5145, 878: 5149}, - {224, 224, 7: 224, 14: 224, 58: 224, 463: 224, 651: 224}, + {468: 5154, 569: 5155, 1045: 5160}, + {187, 187, 7: 187, 13: 187, 46: 187, 466: 187, 652: 187}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5162, 654: 5163, 2691, 2692, 2690}, + {490: 106, 641: 106}, + {490: 105, 641: 105}, // 2690 - {226, 226, 7: 226, 14: 226, 58: 226, 463: 226, 651: 226}, - {463: 5153, 649: 5152}, - {14: 5164, 464: 5161, 880: 5163}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 5155, 1157: 5154}, - {188, 188, 7: 188, 14: 188, 58: 188, 463: 188, 468: 5157, 649: 5156, 651: 188}, + {515: 5165}, + {490: 107, 641: 107}, + {7: 150, 464: 150, 490: 150, 641: 150}, + {270: 5168}, + {7: 152, 464: 152, 490: 152, 641: 152}, // 2695 - {184, 184, 7: 184, 14: 184, 58: 184, 463: 184, 468: 184, 649: 184, 651: 184}, - {464: 5161, 880: 5162}, - {464: 5159, 565: 5160, 1041: 5158}, - {186, 186, 7: 186, 14: 186, 58: 186, 463: 186, 651: 186}, - {183, 183, 7: 183, 14: 183, 58: 183, 463: 183, 651: 183}, + {270: 5170}, + {7: 153, 464: 153, 490: 153, 641: 153}, + {7: 157, 149: 157, 464: 157, 490: 157, 641: 157}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 654: 3410, 2691, 2692, 2690, 729: 5174}, + {712, 712, 7: 712, 464: 712, 490: 712, 641: 712}, // 2700 - {182, 182, 7: 182, 14: 182, 58: 182, 463: 182, 651: 182}, - {712, 712, 7: 712, 14: 712, 57: 712, 712, 463: 712, 651: 712}, - {187, 187, 7: 187, 14: 187, 58: 187, 463: 187, 651: 187}, - {189, 189, 7: 189, 14: 189, 58: 189, 463: 189, 651: 189}, - {464: 5159, 565: 5160, 1041: 5165}, + {713, 713, 7: 713, 464: 713, 490: 713, 641: 713}, + {7: 128, 464: 128, 128, 490: 128, 641: 128}, + {7: 127, 464: 127, 127, 490: 127, 641: 127}, + {464: 5217, 560: 1713, 658: 1713}, + {7: 5119, 464: 5179, 641: 5180}, // 2705 - {185, 185, 7: 185, 14: 185, 58: 185, 463: 185, 651: 185}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 5167, 653: 5168, 2676, 2677, 2675}, - {490: 106, 640: 106}, - {490: 105, 640: 105}, - {512: 5170}, + {2: 112, 112, 112, 112, 112, 8: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 48: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 5133, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 515: 112, 562: 5132, 947: 5134, 1068: 5182}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 5181}, + {165, 165, 7: 5126}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5136, 654: 5137, 2691, 2692, 2690, 1091: 5183}, + {641: 5184}, // 2710 - {490: 107, 640: 107}, - {7: 150, 461: 150, 490: 150, 640: 150}, - {269: 5173}, - {7: 152, 461: 152, 490: 152, 640: 152}, - {269: 5175}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5140, 879: 5141, 910: 5185}, + {217, 217, 7: 5143, 466: 217, 652: 5187, 948: 5186, 5188}, + {216, 216, 13: 216, 46: 216, 466: 216}, + {131: 5208, 133: 5206, 5209, 5207, 353: 5201, 399: 5203, 950: 5205, 1265: 5204, 1283: 5202}, + {164, 164, 466: 5190, 1147: 5189}, // 2715 - {7: 153, 461: 153, 490: 153, 640: 153}, - {7: 157, 163: 157, 461: 157, 490: 157, 640: 157}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 653: 3392, 2676, 2677, 2675, 728: 5179}, - {708, 708, 7: 708, 461: 708, 490: 708, 640: 708}, - {709, 709, 7: 709, 461: 709, 490: 709, 640: 709}, - // 2720 - {7: 128, 461: 128, 128, 490: 128, 640: 128}, - {7: 127, 461: 127, 127, 490: 127, 640: 127}, - {461: 5222, 558: 1707, 657: 1707}, - {7: 5124, 461: 5184, 640: 5185}, - {2: 112, 112, 112, 112, 112, 8: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 58: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 5138, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 512: 112, 556: 5137, 944: 5139, 1065: 5187}, - // 2725 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 5186}, - {165, 165, 7: 5131}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 5141, 653: 5142, 2676, 2677, 2675, 1088: 5188}, - {640: 5189}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5145, 878: 5146, 910: 5190}, - // 2730 - {215, 215, 7: 5148, 463: 215, 651: 5192, 945: 5191, 5193}, - {214, 214, 14: 214, 58: 214, 463: 214}, - {131: 5213, 133: 5211, 5214, 5212, 348: 5206, 396: 5208, 947: 5210, 1261: 5209, 1279: 5207}, - {164, 164, 463: 5195, 1143: 5194}, {167, 167}, - // 2735 - {126: 5199, 5197, 5198, 5200, 843: 5196}, - {894: 5205}, - {496: 2650, 725: 5204}, - {496: 2650, 725: 5203}, - {496: 2650, 725: 5202}, - // 2740 - {496: 2650, 725: 5201}, + {126: 5194, 5192, 5193, 5195, 843: 5191}, + {894: 5200}, + {500: 2665, 724: 5199}, + {500: 2665, 724: 5198}, + // 2720 + {500: 2665, 724: 5197}, + {500: 2665, 724: 5196}, {159, 159}, {160, 160}, {161, 161}, + // 2725 {162, 162}, - // 2745 {163, 163}, - {213, 213, 14: 213, 58: 213, 463: 213}, - {212, 212, 14: 212, 58: 212, 463: 212}, - {211, 211, 14: 211, 58: 211, 463: 211}, - {210, 210, 14: 210, 58: 210, 131: 5213, 133: 5211, 5214, 5212, 463: 210, 495: 5219, 947: 5220}, + {215, 215, 13: 215, 46: 215, 466: 215}, + {214, 214, 13: 214, 46: 214, 466: 214}, + {213, 213, 13: 213, 46: 213, 466: 213}, + // 2730 + {212, 212, 13: 212, 46: 212, 131: 5208, 133: 5206, 5209, 5207, 466: 212, 497: 5214, 950: 5215}, + {211, 211, 13: 211, 46: 211, 131: 211, 133: 211, 211, 211, 466: 211, 497: 211}, + {468: 5213}, + {468: 5212}, + {468: 5211}, + // 2735 + {468: 5210}, + {205, 205, 13: 205, 46: 205, 131: 205, 133: 205, 205, 205, 466: 205, 497: 205}, + {206, 206, 13: 206, 46: 206, 131: 206, 133: 206, 206, 206, 466: 206, 497: 206}, + {207, 207, 13: 207, 46: 207, 131: 207, 133: 207, 207, 207, 466: 207, 497: 207}, + {208, 208, 13: 208, 46: 208, 131: 208, 133: 208, 208, 208, 466: 208, 497: 208}, + // 2740 + {131: 5208, 133: 5206, 5209, 5207, 950: 5216}, + {209, 209, 13: 209, 46: 209, 131: 209, 133: 209, 209, 209, 466: 209, 497: 209}, + {210, 210, 13: 210, 46: 210, 131: 210, 133: 210, 210, 210, 466: 210, 497: 210}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5218}, + {641: 5219}, + // 2745 + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 5220}, + {164, 164, 7: 5126, 466: 5190, 1147: 5221}, + {166, 166}, + {2142, 2142, 7: 2142, 14: 2142, 16: 2142, 19: 2142, 471: 2142, 474: 2142, 490: 2142, 492: 2142, 496: 2142, 498: 2142, 513: 2142, 638: 2142, 641: 2142}, + {241, 241}, // 2750 - {209, 209, 14: 209, 58: 209, 131: 209, 133: 209, 209, 209, 463: 209, 495: 209}, - {464: 5218}, - {464: 5217}, - {464: 5216}, - {464: 5215}, + {2: 830, 830, 830, 830, 830, 8: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 48: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 465: 830, 467: 830, 830, 830, 471: 830, 475: 830, 830, 830, 830, 830, 482: 830, 484: 830, 487: 830, 490: 830, 493: 830, 498: 830, 830, 830, 506: 830, 515: 830, 536: 830, 558: 830, 830, 830, 830, 563: 830, 830, 566: 830, 830, 830, 830, 830, 830, 830, 830, 577: 830, 830, 830, 830, 830, 830, 830, 830, 830, 587: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 617: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 639: 830, 642: 830, 736: 830, 830, 739: 830, 830, 830, 753: 830, 759: 830, 830, 830}, + {2: 828, 828, 828, 828, 828, 8: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 48: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 465: 828, 482: 828, 487: 828, 490: 828, 571: 828, 739: 828, 828, 828}, + {2: 1031, 1031, 1031, 1031, 1031, 8: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 48: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 465: 1031, 482: 1031, 571: 1031, 739: 5229, 5228, 5227, 826: 5230, 875: 5231}, + {2: 1034, 1034, 1034, 1034, 1034, 8: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 48: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 465: 1034, 467: 1034, 1034, 1034, 471: 1034, 475: 1034, 1034, 1034, 1034, 1034, 482: 1034, 484: 1034, 487: 1034, 490: 1034, 493: 1034, 498: 1034, 1034, 1034, 506: 1034, 515: 1034, 536: 1034, 558: 1034, 1034, 1034, 1034, 563: 1034, 1034, 566: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 577: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 587: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 617: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 639: 1034, 642: 1034, 736: 1034, 1034, 739: 1034, 1034, 1034, 753: 1034, 759: 1034, 1034, 1034}, + {2: 1033, 1033, 1033, 1033, 1033, 8: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 48: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 465: 1033, 467: 1033, 1033, 1033, 471: 1033, 475: 1033, 1033, 1033, 1033, 1033, 482: 1033, 484: 1033, 487: 1033, 490: 1033, 493: 1033, 498: 1033, 1033, 1033, 506: 1033, 515: 1033, 536: 1033, 558: 1033, 1033, 1033, 1033, 563: 1033, 1033, 566: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 577: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 587: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 617: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 639: 1033, 642: 1033, 736: 1033, 1033, 739: 1033, 1033, 1033, 753: 1033, 759: 1033, 1033, 1033}, // 2755 - {203, 203, 14: 203, 58: 203, 131: 203, 133: 203, 203, 203, 463: 203, 495: 203}, - {204, 204, 14: 204, 58: 204, 131: 204, 133: 204, 204, 204, 463: 204, 495: 204}, - {205, 205, 14: 205, 58: 205, 131: 205, 133: 205, 205, 205, 463: 205, 495: 205}, - {206, 206, 14: 206, 58: 206, 131: 206, 133: 206, 206, 206, 463: 206, 495: 206}, - {131: 5213, 133: 5211, 5214, 5212, 947: 5221}, + {2: 1032, 1032, 1032, 1032, 1032, 8: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 48: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 465: 1032, 467: 1032, 1032, 1032, 471: 1032, 475: 1032, 1032, 1032, 1032, 1032, 482: 1032, 484: 1032, 487: 1032, 490: 1032, 493: 1032, 498: 1032, 1032, 1032, 506: 1032, 515: 1032, 536: 1032, 558: 1032, 1032, 1032, 1032, 563: 1032, 1032, 566: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 577: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 587: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 617: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 639: 1032, 642: 1032, 736: 1032, 1032, 739: 1032, 1032, 1032, 753: 1032, 759: 1032, 1032, 1032}, + {2: 1030, 1030, 1030, 1030, 1030, 8: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 48: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 465: 1030, 482: 1030, 487: 1030, 490: 1030, 571: 1030}, + {2: 1820, 1820, 1820, 1820, 1820, 8: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 48: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 465: 1820, 482: 4105, 571: 1820, 844: 5232}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 571: 5236, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5235, 840: 5233, 878: 5234}, + {907, 907, 7: 907, 47: 907, 464: 907, 466: 907, 472: 907, 907, 480: 907, 907, 485: 907, 907, 907, 907, 491: 907, 907, 494: 907, 496: 907, 505: 907, 507: 907, 907}, // 2760 - {207, 207, 14: 207, 58: 207, 131: 207, 133: 207, 207, 207, 463: 207, 495: 207}, - {208, 208, 14: 208, 58: 208, 131: 208, 133: 208, 208, 208, 463: 208, 495: 208}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5223}, - {640: 5224}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 5225}, + {7: 5287, 496: 5357}, + {7: 905, 475: 5254, 5255, 496: 5344, 506: 5253, 509: 5256, 5252, 5257, 5258, 806: 5251, 812: 5250}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5341, 2691, 2692, 2690}, + {903, 903, 7: 903, 47: 903, 464: 903, 466: 903, 472: 903, 903, 475: 903, 903, 480: 903, 903, 485: 903, 903, 903, 903, 491: 903, 903, 494: 903, 496: 903, 505: 903, 903, 903, 903, 903, 903, 903, 903, 514: 903}, + {902, 902, 7: 902, 47: 902, 464: 902, 466: 902, 472: 902, 902, 475: 902, 902, 480: 902, 902, 485: 902, 902, 902, 902, 491: 902, 902, 494: 902, 496: 902, 505: 902, 902, 902, 902, 902, 902, 902, 902, 514: 902}, // 2765 - {164, 164, 7: 5131, 463: 5195, 1143: 5226}, - {166, 166}, - {2134, 2134, 7: 2134, 13: 2134, 15: 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 2134, 28: 2134, 467: 2134, 470: 2134, 489: 2134, 2134, 492: 2134, 510: 2134, 637: 2134, 640: 2134}, - {239, 239}, - {2: 826, 826, 826, 826, 826, 8: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 58: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 462: 826, 464: 826, 826, 826, 826, 472: 826, 826, 826, 826, 826, 826, 481: 826, 484: 826, 487: 826, 489: 826, 826, 494: 826, 496: 826, 503: 826, 512: 826, 532: 826, 555: 826, 557: 826, 826, 826, 826, 826, 826, 826, 826, 826, 567: 826, 826, 826, 826, 572: 826, 826, 575: 826, 577: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 639: 826, 641: 826, 735: 826, 826, 738: 826, 826, 826, 749: 826, 758: 826, 826, 826}, + {898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 466: 898, 470: 898, 472: 898, 898, 475: 898, 898, 480: 898, 898, 898, 5291, 485: 898, 898, 898, 898, 491: 898, 898, 494: 898, 898, 898, 505: 898, 898, 898, 898, 898, 898, 898, 898, 514: 898, 517: 898, 898, 664: 898, 849: 5290}, + {896, 896, 2930, 2776, 2812, 2932, 2703, 896, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 896, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 896, 466: 896, 470: 5248, 472: 896, 896, 475: 896, 896, 480: 896, 896, 485: 896, 896, 896, 896, 491: 896, 896, 494: 896, 496: 896, 505: 896, 896, 896, 896, 896, 896, 896, 896, 514: 896, 654: 5247, 2691, 2692, 2690, 903: 5246, 5245}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 2522, 493: 2521, 562: 2520, 571: 5236, 637: 2516, 654: 3838, 2691, 2692, 2690, 700: 5244, 728: 5239, 742: 3798, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 3800, 3799, 3797, 788: 5238, 791: 5237, 5243, 840: 5233, 878: 5242}, + {7: 5287, 47: 5288}, + {905, 905, 7: 905, 47: 905, 464: 905, 466: 905, 472: 905, 905, 475: 5254, 5255, 480: 905, 905, 485: 905, 905, 905, 905, 491: 905, 905, 494: 905, 496: 905, 505: 905, 5253, 905, 905, 5256, 5252, 5257, 5258, 806: 5251, 812: 5250}, // 2770 - {2: 824, 824, 824, 824, 824, 8: 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 58: 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 462: 824, 477: 824, 484: 824, 490: 824, 568: 824, 738: 824, 824, 824}, - {2: 1027, 1027, 1027, 1027, 1027, 8: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 58: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 462: 1027, 477: 1027, 568: 1027, 738: 5234, 5233, 5232, 827: 5235, 874: 5236}, - {2: 1030, 1030, 1030, 1030, 1030, 8: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 58: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 462: 1030, 464: 1030, 1030, 1030, 1030, 472: 1030, 1030, 1030, 1030, 1030, 1030, 481: 1030, 484: 1030, 487: 1030, 489: 1030, 1030, 494: 1030, 496: 1030, 503: 1030, 512: 1030, 532: 1030, 555: 1030, 557: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 567: 1030, 1030, 1030, 1030, 572: 1030, 1030, 575: 1030, 577: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 639: 1030, 641: 1030, 735: 1030, 1030, 738: 1030, 1030, 1030, 749: 1030, 758: 1030, 1030, 1030}, - {2: 1029, 1029, 1029, 1029, 1029, 8: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 58: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 462: 1029, 464: 1029, 1029, 1029, 1029, 472: 1029, 1029, 1029, 1029, 1029, 1029, 481: 1029, 484: 1029, 487: 1029, 489: 1029, 1029, 494: 1029, 496: 1029, 503: 1029, 512: 1029, 532: 1029, 555: 1029, 557: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 567: 1029, 1029, 1029, 1029, 572: 1029, 1029, 575: 1029, 577: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 639: 1029, 641: 1029, 735: 1029, 1029, 738: 1029, 1029, 1029, 749: 1029, 758: 1029, 1029, 1029}, - {2: 1028, 1028, 1028, 1028, 1028, 8: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 58: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 462: 1028, 464: 1028, 1028, 1028, 1028, 472: 1028, 1028, 1028, 1028, 1028, 1028, 481: 1028, 484: 1028, 487: 1028, 489: 1028, 1028, 494: 1028, 496: 1028, 503: 1028, 512: 1028, 532: 1028, 555: 1028, 557: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 567: 1028, 1028, 1028, 1028, 572: 1028, 1028, 575: 1028, 577: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 639: 1028, 641: 1028, 735: 1028, 1028, 738: 1028, 1028, 1028, 749: 1028, 758: 1028, 1028, 1028}, + {2: 2930, 2776, 2812, 2932, 2703, 896, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 3891, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 470: 5248, 472: 790, 475: 896, 896, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 506: 896, 509: 896, 896, 896, 896, 654: 5247, 2691, 2692, 2690, 757: 3808, 3809, 903: 5246, 5245}, + {900, 900, 7: 900, 47: 900, 464: 900, 466: 900, 472: 900, 900, 475: 900, 900, 480: 900, 900, 485: 900, 900, 900, 900, 491: 900, 900, 494: 900, 496: 900, 505: 900, 900, 900, 900, 900, 900, 900, 900, 514: 900}, + {895, 895, 7: 895, 47: 895, 464: 895, 466: 895, 472: 895, 895, 475: 895, 895, 480: 895, 895, 895, 485: 895, 895, 895, 895, 491: 895, 895, 494: 895, 895, 895, 505: 895, 895, 895, 895, 895, 895, 895, 895, 514: 895, 517: 895, 895, 664: 895}, + {894, 894, 7: 894, 47: 894, 464: 894, 466: 894, 472: 894, 894, 475: 894, 894, 480: 894, 894, 894, 485: 894, 894, 894, 894, 491: 894, 894, 494: 894, 894, 894, 505: 894, 894, 894, 894, 894, 894, 894, 894, 514: 894, 517: 894, 894, 664: 894}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5249, 2691, 2692, 2690}, // 2775 - {2: 1026, 1026, 1026, 1026, 1026, 8: 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 58: 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 462: 1026, 477: 1026, 484: 1026, 490: 1026, 568: 1026}, - {2: 1813, 1813, 1813, 1813, 1813, 8: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 58: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 462: 1813, 477: 4087, 568: 1813, 844: 5237}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 568: 5241, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5240, 840: 5238, 877: 5239}, - {903, 903, 7: 903, 57: 903, 461: 903, 463: 903, 469: 903, 471: 903, 479: 903, 903, 482: 903, 903, 903, 486: 903, 491: 903, 903, 903, 501: 903, 903, 504: 903, 903}, - {7: 5292, 501: 5362}, + {893, 893, 7: 893, 47: 893, 464: 893, 466: 893, 472: 893, 893, 475: 893, 893, 480: 893, 893, 893, 485: 893, 893, 893, 893, 491: 893, 893, 494: 893, 893, 893, 505: 893, 893, 893, 893, 893, 893, 893, 893, 514: 893, 517: 893, 893, 664: 893}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5280}, + {509: 864, 896: 5267, 1081: 5271}, + {475: 5254, 5255, 509: 5264, 806: 5265}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5261}, // 2780 - {7: 901, 472: 5259, 5260, 501: 5349, 503: 5258, 506: 5261, 5257, 5262, 5263, 807: 5256, 813: 5255}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5346, 2676, 2677, 2675}, - {899, 899, 7: 899, 57: 899, 461: 899, 463: 899, 469: 899, 471: 899, 899, 899, 479: 899, 899, 482: 899, 899, 899, 486: 899, 491: 899, 899, 899, 501: 899, 899, 899, 899, 899, 899, 899, 899, 899, 511: 899}, - {898, 898, 7: 898, 57: 898, 461: 898, 463: 898, 469: 898, 471: 898, 898, 898, 479: 898, 898, 482: 898, 898, 898, 486: 898, 491: 898, 898, 898, 501: 898, 898, 898, 898, 898, 898, 898, 898, 898, 511: 898}, - {894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 463: 894, 468: 894, 894, 471: 894, 894, 894, 477: 894, 5296, 894, 894, 482: 894, 894, 894, 486: 894, 488: 894, 491: 894, 894, 894, 501: 894, 894, 894, 894, 894, 894, 894, 894, 894, 511: 894, 514: 894, 894, 663: 894, 849: 5295}, + {509: 866, 896: 866}, + {509: 865, 896: 865}, + {2: 862, 862, 862, 862, 862, 8: 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 48: 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 465: 862}, + {509: 5260}, + {509: 5259}, // 2785 - {892, 892, 2912, 2760, 2796, 2914, 2687, 892, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 892, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 892, 463: 892, 468: 5253, 892, 471: 892, 892, 892, 479: 892, 892, 482: 892, 892, 892, 486: 892, 491: 892, 892, 892, 501: 892, 892, 892, 892, 892, 892, 892, 892, 892, 511: 892, 653: 5252, 2676, 2677, 2675, 903: 5251, 5250}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 2508, 487: 2507, 556: 2506, 568: 5241, 634: 2502, 653: 3820, 2676, 2677, 2675, 699: 5249, 727: 5244, 741: 3780, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 3782, 3781, 3779, 789: 5243, 792: 5242, 5248, 840: 5238, 877: 5247}, - {7: 5292, 57: 5293}, - {901, 901, 7: 901, 57: 901, 461: 901, 463: 901, 469: 901, 471: 901, 5259, 5260, 479: 901, 901, 482: 901, 901, 901, 486: 901, 491: 901, 901, 901, 501: 901, 901, 5258, 901, 901, 5261, 5257, 5262, 5263, 807: 5256, 813: 5255}, - {2: 2912, 2760, 2796, 2914, 2687, 892, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 3873, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 468: 5253, 786, 472: 892, 892, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 503: 892, 506: 892, 892, 892, 892, 653: 5252, 2676, 2677, 2675, 756: 3790, 3791, 903: 5251, 5250}, + {2: 860, 860, 860, 860, 860, 8: 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 48: 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, 465: 860}, + {2: 861, 861, 861, 861, 861, 8: 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 48: 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 465: 861}, + {868, 868, 7: 868, 47: 868, 464: 5262, 466: 868, 472: 868, 868, 475: 868, 868, 480: 868, 868, 485: 868, 868, 868, 868, 491: 868, 868, 494: 868, 496: 868, 505: 868, 868, 868, 868, 868, 868, 868, 868, 514: 868, 806: 5251, 812: 5250}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5263}, + {867, 867, 7: 867, 47: 867, 464: 867, 466: 867, 472: 867, 867, 475: 867, 867, 480: 867, 867, 485: 867, 867, 867, 867, 491: 867, 867, 494: 867, 496: 867, 3265, 501: 3263, 3264, 3262, 3260, 867, 867, 867, 867, 867, 867, 867, 867, 514: 867, 725: 3261, 3259}, // 2790 - {896, 896, 7: 896, 57: 896, 461: 896, 463: 896, 469: 896, 471: 896, 896, 896, 479: 896, 896, 482: 896, 896, 896, 486: 896, 491: 896, 896, 896, 501: 896, 896, 896, 896, 896, 896, 896, 896, 896, 511: 896}, - {891, 891, 7: 891, 57: 891, 461: 891, 463: 891, 469: 891, 471: 891, 891, 891, 477: 891, 479: 891, 891, 482: 891, 891, 891, 486: 891, 488: 891, 491: 891, 891, 891, 501: 891, 891, 891, 891, 891, 891, 891, 891, 891, 511: 891, 514: 891, 891, 663: 891}, - {890, 890, 7: 890, 57: 890, 461: 890, 463: 890, 469: 890, 471: 890, 890, 890, 477: 890, 479: 890, 890, 482: 890, 890, 890, 486: 890, 488: 890, 491: 890, 890, 890, 501: 890, 890, 890, 890, 890, 890, 890, 890, 890, 511: 890, 514: 890, 890, 663: 890}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5254, 2676, 2677, 2675}, - {889, 889, 7: 889, 57: 889, 461: 889, 463: 889, 469: 889, 471: 889, 889, 889, 477: 889, 479: 889, 889, 482: 889, 889, 889, 486: 889, 488: 889, 491: 889, 889, 889, 501: 889, 889, 889, 889, 889, 889, 889, 889, 889, 511: 889, 514: 889, 889, 663: 889}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5270}, + {509: 864, 896: 5267, 1081: 5266}, + {509: 5268}, + {509: 863}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5269}, // 2795 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5285}, - {506: 860, 896: 5272, 1078: 5276}, - {472: 5259, 5260, 506: 5269, 807: 5270}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5266}, - {506: 862, 896: 862}, + {869, 869, 7: 869, 47: 869, 464: 869, 466: 869, 472: 869, 869, 475: 869, 869, 480: 869, 869, 485: 869, 869, 869, 869, 491: 869, 869, 494: 869, 496: 869, 505: 869, 869, 869, 869, 869, 869, 869, 869, 514: 869, 806: 5251, 812: 5250}, + {870, 870, 7: 870, 47: 870, 464: 870, 466: 870, 472: 870, 870, 475: 870, 870, 480: 870, 870, 485: 870, 870, 870, 870, 491: 870, 870, 494: 870, 496: 870, 505: 870, 870, 870, 870, 870, 870, 870, 870, 514: 870, 806: 5251, 812: 5250}, + {509: 5272}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5273}, + {464: 5274, 473: 5275, 475: 5254, 5255, 506: 5253, 509: 5256, 5252, 5257, 5258, 806: 5251, 812: 5250}, // 2800 - {506: 861, 896: 861}, - {2: 858, 858, 858, 858, 858, 8: 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 58: 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, 462: 858}, - {506: 5265}, - {506: 5264}, - {2: 856, 856, 856, 856, 856, 8: 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 58: 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 462: 856}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5279}, + {465: 5276}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 5277}, + {7: 4061, 47: 5278}, + {871, 871, 7: 871, 47: 871, 464: 871, 466: 871, 472: 871, 871, 475: 871, 871, 480: 871, 871, 485: 871, 871, 871, 871, 491: 871, 871, 494: 871, 496: 871, 505: 871, 871, 871, 871, 871, 871, 871, 871, 514: 871}, // 2805 - {2: 857, 857, 857, 857, 857, 8: 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 58: 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 857, 462: 857}, - {864, 864, 7: 864, 57: 864, 461: 5267, 463: 864, 469: 864, 471: 864, 864, 864, 479: 864, 864, 482: 864, 864, 864, 486: 864, 491: 864, 864, 864, 501: 864, 864, 864, 864, 864, 864, 864, 864, 864, 511: 864, 807: 5256, 813: 5255}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5268}, - {863, 863, 7: 863, 57: 863, 461: 863, 463: 863, 469: 863, 471: 863, 863, 863, 479: 863, 863, 482: 863, 863, 863, 486: 863, 491: 863, 863, 863, 495: 3249, 497: 3247, 3248, 3246, 3244, 863, 863, 863, 863, 863, 863, 863, 863, 863, 511: 863, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5275}, + {872, 872, 7: 872, 47: 872, 464: 872, 466: 872, 472: 872, 872, 475: 872, 872, 480: 872, 872, 485: 872, 872, 872, 872, 491: 872, 872, 494: 872, 496: 872, 3265, 501: 3263, 3264, 3262, 3260, 872, 872, 872, 872, 872, 872, 872, 872, 514: 872, 725: 3261, 3259}, + {875, 875, 7: 875, 47: 875, 464: 5281, 466: 875, 472: 875, 5282, 475: 5254, 5255, 480: 875, 875, 485: 875, 875, 875, 875, 491: 875, 875, 494: 875, 496: 875, 505: 875, 5253, 875, 875, 5256, 5252, 5257, 5258, 514: 875, 806: 5251, 812: 5250}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5286}, + {465: 5283}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 5284}, // 2810 - {506: 860, 896: 5272, 1078: 5271}, - {506: 5273}, - {506: 859}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5274}, - {865, 865, 7: 865, 57: 865, 461: 865, 463: 865, 469: 865, 471: 865, 865, 865, 479: 865, 865, 482: 865, 865, 865, 486: 865, 491: 865, 865, 865, 501: 865, 865, 865, 865, 865, 865, 865, 865, 865, 511: 865, 807: 5256, 813: 5255}, + {7: 4061, 47: 5285}, + {873, 873, 7: 873, 47: 873, 464: 873, 466: 873, 472: 873, 873, 475: 873, 873, 480: 873, 873, 485: 873, 873, 873, 873, 491: 873, 873, 494: 873, 496: 873, 505: 873, 873, 873, 873, 873, 873, 873, 873, 514: 873}, + {874, 874, 7: 874, 47: 874, 464: 874, 466: 874, 472: 874, 874, 475: 874, 874, 480: 874, 874, 485: 874, 874, 874, 874, 491: 874, 874, 494: 874, 496: 874, 3265, 501: 3263, 3264, 3262, 3260, 874, 874, 874, 874, 874, 874, 874, 874, 514: 874, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 571: 5236, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5243, 840: 5289}, + {899, 899, 7: 899, 47: 899, 464: 899, 466: 899, 472: 899, 899, 475: 899, 899, 480: 899, 899, 485: 899, 899, 899, 899, 491: 899, 899, 494: 899, 496: 899, 505: 899, 899, 899, 899, 899, 899, 899, 899, 514: 899}, // 2815 - {866, 866, 7: 866, 57: 866, 461: 866, 463: 866, 469: 866, 471: 866, 866, 866, 479: 866, 866, 482: 866, 866, 866, 486: 866, 491: 866, 866, 866, 501: 866, 866, 866, 866, 866, 866, 866, 866, 866, 511: 866, 807: 5256, 813: 5255}, - {506: 5277}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5278}, - {461: 5279, 471: 5280, 5259, 5260, 503: 5258, 506: 5261, 5257, 5262, 5263, 807: 5256, 813: 5255}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5284}, + {906, 906, 7: 906, 47: 906, 464: 906, 466: 906, 472: 906, 906, 480: 906, 906, 485: 906, 906, 906, 906, 491: 906, 906, 494: 906, 496: 906, 505: 906, 507: 906, 906}, + {896, 896, 2930, 2776, 2812, 2932, 2703, 896, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 896, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 896, 466: 896, 470: 5248, 472: 896, 896, 475: 896, 896, 480: 896, 896, 896, 485: 896, 896, 896, 896, 491: 896, 896, 494: 896, 896, 896, 505: 896, 896, 896, 896, 896, 896, 896, 896, 514: 896, 517: 896, 896, 654: 5247, 2691, 2692, 2690, 664: 896, 903: 5246, 5295}, + {465: 5292}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 5293}, + {7: 4659, 47: 5294}, // 2820 - {462: 5281}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 5282}, - {7: 4043, 57: 5283}, - {867, 867, 7: 867, 57: 867, 461: 867, 463: 867, 469: 867, 471: 867, 867, 867, 479: 867, 867, 482: 867, 867, 867, 486: 867, 491: 867, 867, 867, 501: 867, 867, 867, 867, 867, 867, 867, 867, 867, 511: 867}, - {868, 868, 7: 868, 57: 868, 461: 868, 463: 868, 469: 868, 471: 868, 868, 868, 479: 868, 868, 482: 868, 868, 868, 486: 868, 491: 868, 868, 868, 495: 3249, 497: 3247, 3248, 3246, 3244, 868, 868, 868, 868, 868, 868, 868, 868, 868, 511: 868, 723: 3245, 3243}, + {897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 470: 897, 472: 897, 897, 475: 897, 897, 480: 897, 897, 897, 485: 897, 897, 897, 897, 491: 897, 897, 897, 897, 897, 897, 505: 897, 897, 897, 897, 897, 897, 897, 897, 514: 897, 517: 897, 897, 547: 897, 562: 897, 637: 897, 640: 897, 650: 897, 664: 897}, + {1827, 1827, 7: 1827, 47: 1827, 464: 1827, 466: 1827, 472: 1827, 1827, 475: 1827, 1827, 480: 1827, 1827, 1827, 485: 1827, 1827, 1827, 1827, 491: 1827, 1827, 494: 1827, 1827, 1827, 505: 1827, 1827, 1827, 1827, 1827, 1827, 1827, 1827, 514: 1827, 517: 1827, 1827, 664: 5297, 912: 5296, 1158: 5298}, + {1826, 1826, 7: 1826, 47: 1826, 464: 1826, 466: 1826, 472: 1826, 1826, 475: 1826, 1826, 480: 1826, 1826, 1826, 485: 1826, 1826, 1826, 1826, 491: 1826, 1826, 494: 1826, 1826, 1826, 505: 1826, 1826, 1826, 1826, 1826, 1826, 1826, 1826, 514: 1826, 517: 1826, 1826}, + {214: 5339}, + {877, 877, 7: 877, 47: 877, 464: 877, 466: 877, 472: 877, 877, 475: 877, 877, 480: 877, 877, 5301, 485: 877, 877, 877, 877, 491: 877, 877, 494: 877, 5302, 877, 505: 877, 877, 877, 877, 877, 877, 877, 877, 514: 877, 517: 5300, 877, 928: 5304, 5303, 1048: 5305, 5299}, // 2825 - {871, 871, 7: 871, 57: 871, 461: 5286, 463: 871, 469: 871, 471: 5287, 5259, 5260, 479: 871, 871, 482: 871, 871, 871, 486: 871, 491: 871, 871, 871, 501: 871, 871, 5258, 871, 871, 5261, 5257, 5262, 5263, 511: 871, 807: 5256, 813: 5255}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5291}, - {462: 5288}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 5289}, - {7: 4043, 57: 5290}, + {992, 992, 7: 992, 47: 992, 464: 992, 466: 992, 472: 992, 992, 475: 992, 992, 480: 992, 992, 485: 992, 992, 992, 992, 491: 992, 992, 494: 992, 496: 992, 505: 992, 992, 992, 992, 992, 992, 992, 992, 514: 992, 518: 5320, 1302: 5321}, + {565: 4320, 640: 4321, 816: 5319}, + {565: 4320, 640: 4321, 816: 5318}, + {565: 4320, 640: 4321, 816: 5317}, + {465: 889, 485: 5307, 1213: 5308}, // 2830 - {869, 869, 7: 869, 57: 869, 461: 869, 463: 869, 469: 869, 471: 869, 869, 869, 479: 869, 869, 482: 869, 869, 869, 486: 869, 491: 869, 869, 869, 501: 869, 869, 869, 869, 869, 869, 869, 869, 869, 511: 869}, - {870, 870, 7: 870, 57: 870, 461: 870, 463: 870, 469: 870, 471: 870, 870, 870, 479: 870, 870, 482: 870, 870, 870, 486: 870, 491: 870, 870, 870, 495: 3249, 497: 3247, 3248, 3246, 3244, 870, 870, 870, 870, 870, 870, 870, 870, 870, 511: 870, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 568: 5241, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5248, 840: 5294}, - {895, 895, 7: 895, 57: 895, 461: 895, 463: 895, 469: 895, 471: 895, 895, 895, 479: 895, 895, 482: 895, 895, 895, 486: 895, 491: 895, 895, 895, 501: 895, 895, 895, 895, 895, 895, 895, 895, 895, 511: 895}, - {902, 902, 7: 902, 57: 902, 461: 902, 463: 902, 469: 902, 471: 902, 479: 902, 902, 482: 902, 902, 902, 486: 902, 491: 902, 902, 902, 501: 902, 902, 504: 902, 902}, + {879, 879, 7: 879, 47: 879, 464: 879, 466: 879, 472: 879, 879, 475: 879, 879, 480: 879, 879, 879, 485: 879, 879, 879, 879, 491: 879, 879, 494: 879, 879, 879, 505: 879, 879, 879, 879, 879, 879, 879, 879, 514: 879, 517: 879, 879}, + {876, 876, 7: 876, 47: 876, 464: 876, 466: 876, 472: 876, 876, 475: 876, 876, 480: 876, 876, 5301, 485: 876, 876, 876, 876, 491: 876, 876, 494: 876, 5302, 876, 505: 876, 876, 876, 876, 876, 876, 876, 876, 514: 876, 517: 5300, 876, 928: 5306, 5303}, + {878, 878, 7: 878, 47: 878, 464: 878, 466: 878, 472: 878, 878, 475: 878, 878, 480: 878, 878, 878, 485: 878, 878, 878, 878, 491: 878, 878, 494: 878, 878, 878, 505: 878, 878, 878, 878, 878, 878, 878, 878, 514: 878, 517: 878, 878}, + {494: 5313, 505: 5314, 509: 5312}, + {465: 5309}, // 2835 - {892, 892, 2912, 2760, 2796, 2914, 2687, 892, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 892, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 892, 463: 892, 468: 5253, 892, 471: 892, 892, 892, 477: 892, 479: 892, 892, 482: 892, 892, 892, 486: 892, 488: 892, 491: 892, 892, 892, 501: 892, 892, 892, 892, 892, 892, 892, 892, 892, 511: 892, 514: 892, 892, 653: 5252, 2676, 2677, 2675, 663: 892, 903: 5251, 5300}, - {462: 5297}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 5298}, - {7: 4642, 57: 5299}, - {893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 468: 893, 893, 471: 893, 893, 893, 477: 893, 479: 893, 893, 482: 893, 893, 893, 486: 893, 893, 893, 491: 893, 893, 893, 501: 893, 893, 893, 893, 893, 893, 893, 893, 893, 511: 893, 514: 893, 893, 544: 893, 556: 893, 634: 893, 638: 893, 649: 893, 663: 893}, + {2: 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 884, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 5310}, + {7: 4918, 47: 5311}, + {885, 885, 7: 885, 47: 885, 464: 885, 466: 885, 472: 885, 885, 475: 885, 885, 480: 885, 885, 885, 485: 885, 885, 885, 885, 491: 885, 885, 494: 885, 885, 885, 505: 885, 885, 885, 885, 885, 885, 885, 885, 514: 885, 517: 885, 885}, + {465: 888}, + {650: 5316}, // 2840 - {1820, 1820, 7: 1820, 57: 1820, 461: 1820, 463: 1820, 469: 1820, 471: 1820, 1820, 1820, 477: 1820, 479: 1820, 1820, 482: 1820, 1820, 1820, 486: 1820, 488: 1820, 491: 1820, 1820, 1820, 501: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 511: 1820, 514: 1820, 1820, 663: 5302, 912: 5301, 1154: 5303}, - {1819, 1819, 7: 1819, 57: 1819, 461: 1819, 463: 1819, 469: 1819, 471: 1819, 1819, 1819, 477: 1819, 479: 1819, 1819, 482: 1819, 1819, 1819, 486: 1819, 488: 1819, 491: 1819, 1819, 1819, 501: 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 511: 1819, 514: 1819, 1819}, - {214: 5344}, - {873, 873, 7: 873, 57: 873, 461: 873, 463: 873, 469: 873, 471: 873, 873, 873, 477: 5306, 479: 873, 873, 482: 873, 873, 873, 486: 873, 488: 5307, 491: 873, 873, 873, 501: 873, 873, 873, 873, 873, 873, 873, 873, 873, 511: 873, 514: 5305, 873, 928: 5309, 5308, 1044: 5310, 5304}, - {988, 988, 7: 988, 57: 988, 461: 988, 463: 988, 469: 988, 471: 988, 988, 988, 479: 988, 988, 482: 988, 988, 988, 486: 988, 491: 988, 988, 988, 501: 988, 988, 988, 988, 988, 988, 988, 988, 988, 511: 988, 515: 5325, 1298: 5326}, + {650: 5315}, + {465: 886}, + {465: 887}, + {465: 890, 485: 890}, + {465: 891, 485: 891}, // 2845 - {566: 4315, 638: 4316, 817: 5324}, - {566: 4315, 638: 4316, 817: 5323}, - {566: 4315, 638: 4316, 817: 5322}, - {462: 885, 482: 5312, 1208: 5313}, - {875, 875, 7: 875, 57: 875, 461: 875, 463: 875, 469: 875, 471: 875, 875, 875, 477: 875, 479: 875, 875, 482: 875, 875, 875, 486: 875, 488: 875, 491: 875, 875, 875, 501: 875, 875, 875, 875, 875, 875, 875, 875, 875, 511: 875, 514: 875, 875}, + {465: 892, 485: 892}, + {86: 5325, 299: 5324, 382: 5323, 465: 989, 1301: 5322}, + {901, 901, 7: 901, 47: 901, 464: 901, 466: 901, 472: 901, 901, 475: 901, 901, 480: 901, 901, 485: 901, 901, 901, 901, 491: 901, 901, 494: 901, 496: 901, 505: 901, 901, 901, 901, 901, 901, 901, 901, 514: 901}, + {465: 5326}, + {465: 988}, // 2850 - {872, 872, 7: 872, 57: 872, 461: 872, 463: 872, 469: 872, 471: 872, 872, 872, 477: 5306, 479: 872, 872, 482: 872, 872, 872, 486: 872, 488: 5307, 491: 872, 872, 872, 501: 872, 872, 872, 872, 872, 872, 872, 872, 872, 511: 872, 514: 5305, 872, 928: 5311, 5308}, - {874, 874, 7: 874, 57: 874, 461: 874, 463: 874, 469: 874, 471: 874, 874, 874, 477: 874, 479: 874, 874, 482: 874, 874, 874, 486: 874, 488: 874, 491: 874, 874, 874, 501: 874, 874, 874, 874, 874, 874, 874, 874, 874, 511: 874, 514: 874, 874}, - {493: 5318, 502: 5319, 506: 5317}, - {462: 5314}, - {2: 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 880, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 5315}, + {465: 987}, + {465: 986}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 5328, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5327}, + {47: 985, 362: 5336, 497: 3265, 501: 3263, 3264, 3262, 3260, 516: 5335, 725: 3261, 3259, 1303: 5334}, + {982, 982, 7: 982, 47: 982, 210: 5330, 464: 982, 466: 982, 472: 982, 982, 475: 982, 982, 480: 982, 982, 485: 982, 982, 982, 982, 491: 982, 982, 494: 982, 496: 982, 505: 982, 982, 982, 982, 982, 982, 982, 982, 514: 982, 1099: 5329}, // 2855 - {7: 4923, 57: 5316}, - {881, 881, 7: 881, 57: 881, 461: 881, 463: 881, 469: 881, 471: 881, 881, 881, 477: 881, 479: 881, 881, 482: 881, 881, 881, 486: 881, 488: 881, 491: 881, 881, 881, 501: 881, 881, 881, 881, 881, 881, 881, 881, 881, 511: 881, 514: 881, 881}, - {462: 884}, - {649: 5321}, - {649: 5320}, + {990, 990, 7: 990, 47: 990, 464: 990, 466: 990, 472: 990, 990, 475: 990, 990, 480: 990, 990, 485: 990, 990, 990, 990, 491: 990, 990, 494: 990, 496: 990, 505: 990, 990, 990, 990, 990, 990, 990, 990, 514: 990}, + {465: 5331}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5332}, + {47: 5333, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {981, 981, 7: 981, 47: 981, 464: 981, 466: 981, 472: 981, 981, 475: 981, 981, 480: 981, 981, 485: 981, 981, 981, 981, 491: 981, 981, 494: 981, 496: 981, 505: 981, 981, 981, 981, 981, 981, 981, 981, 514: 981}, // 2860 - {462: 882}, - {462: 883}, - {462: 886, 482: 886}, - {462: 887, 482: 887}, - {462: 888, 482: 888}, + {47: 5337}, + {47: 984}, + {47: 983}, + {982, 982, 7: 982, 47: 982, 210: 5330, 464: 982, 466: 982, 472: 982, 982, 475: 982, 982, 480: 982, 982, 485: 982, 982, 982, 982, 491: 982, 982, 494: 982, 496: 982, 505: 982, 982, 982, 982, 982, 982, 982, 982, 514: 982, 1099: 5338}, + {991, 991, 7: 991, 47: 991, 464: 991, 466: 991, 472: 991, 991, 475: 991, 991, 480: 991, 991, 485: 991, 991, 991, 991, 491: 991, 991, 494: 991, 496: 991, 505: 991, 991, 991, 991, 991, 991, 991, 991, 514: 991}, // 2865 - {15: 5330, 297: 5329, 378: 5328, 462: 985, 1297: 5327}, - {897, 897, 7: 897, 57: 897, 461: 897, 463: 897, 469: 897, 471: 897, 897, 897, 479: 897, 897, 482: 897, 897, 897, 486: 897, 491: 897, 897, 897, 501: 897, 897, 897, 897, 897, 897, 897, 897, 897, 511: 897}, - {462: 5331}, - {462: 984}, - {462: 983}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5340}, + {1825, 1825, 7: 1825, 47: 1825, 464: 1825, 466: 1825, 472: 1825, 1825, 475: 1825, 1825, 480: 1825, 1825, 1825, 485: 1825, 1825, 1825, 1825, 491: 1825, 1825, 494: 1825, 1825, 1825, 3265, 501: 3263, 3264, 3262, 3260, 1825, 1825, 1825, 1825, 1825, 1825, 1825, 1825, 514: 1825, 517: 1825, 1825, 725: 3261, 3259}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5342}, + {475: 5254, 5255, 506: 5253, 509: 5256, 5252, 5257, 5258, 514: 5343, 806: 5251, 812: 5250}, + {904, 904, 7: 904, 47: 904, 464: 904, 466: 904, 472: 904, 904, 480: 904, 904, 485: 904, 904, 904, 904, 491: 904, 904, 494: 904, 496: 904, 505: 904, 507: 904, 904}, // 2870 - {462: 982}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 5333, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5332}, - {57: 981, 357: 5341, 495: 3249, 497: 3247, 3248, 3246, 3244, 513: 5340, 723: 3245, 3243, 1299: 5339}, - {978, 978, 7: 978, 57: 978, 210: 5335, 461: 978, 463: 978, 469: 978, 471: 978, 978, 978, 479: 978, 978, 482: 978, 978, 978, 486: 978, 491: 978, 978, 978, 501: 978, 978, 978, 978, 978, 978, 978, 978, 978, 511: 978, 1096: 5334}, - {986, 986, 7: 986, 57: 986, 461: 986, 463: 986, 469: 986, 471: 986, 986, 986, 479: 986, 986, 482: 986, 986, 986, 486: 986, 491: 986, 986, 986, 501: 986, 986, 986, 986, 986, 986, 986, 986, 986, 511: 986}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 5345, 880: 5346, 913: 5347}, + {489: 5355}, + {2301, 2301, 7: 2301, 473: 2301, 486: 2301, 492: 2301, 494: 2301}, + {239, 239, 7: 5348, 473: 239, 486: 239, 492: 2651, 494: 239, 779: 2652, 5349}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 5345, 880: 5354}, // 2875 - {462: 5336}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5337}, - {57: 5338, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {977, 977, 7: 977, 57: 977, 461: 977, 463: 977, 469: 977, 471: 977, 977, 977, 479: 977, 977, 482: 977, 977, 977, 486: 977, 491: 977, 977, 977, 501: 977, 977, 977, 977, 977, 977, 977, 977, 977, 511: 977}, - {57: 5342}, + {1269, 1269, 473: 1269, 486: 1269, 494: 2654, 757: 2655, 800: 5350}, + {859, 859, 473: 859, 486: 5351, 1057: 5352}, + {500: 2665, 570: 2667, 724: 2664, 734: 2666, 870: 5353}, + {243, 243, 473: 243}, + {858, 858, 473: 858}, // 2880 - {57: 980}, - {57: 979}, - {978, 978, 7: 978, 57: 978, 210: 5335, 461: 978, 463: 978, 469: 978, 471: 978, 978, 978, 479: 978, 978, 482: 978, 978, 978, 486: 978, 491: 978, 978, 978, 501: 978, 978, 978, 978, 978, 978, 978, 978, 978, 511: 978, 1096: 5343}, - {987, 987, 7: 987, 57: 987, 461: 987, 463: 987, 469: 987, 471: 987, 987, 987, 479: 987, 987, 482: 987, 987, 987, 486: 987, 491: 987, 987, 987, 501: 987, 987, 987, 987, 987, 987, 987, 987, 987, 511: 987}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5345}, + {2300, 2300, 7: 2300, 473: 2300, 486: 2300, 492: 2300, 494: 2300}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5356}, + {2302, 2302, 7: 2302, 473: 2302, 486: 2302, 492: 2302, 494: 2302}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 5345, 880: 5346, 913: 5358}, + {239, 239, 7: 5348, 473: 239, 492: 2651, 779: 2652, 5359}, // 2885 - {1818, 1818, 7: 1818, 57: 1818, 461: 1818, 463: 1818, 469: 1818, 471: 1818, 1818, 1818, 477: 1818, 479: 1818, 1818, 482: 1818, 1818, 1818, 486: 1818, 488: 1818, 491: 1818, 1818, 1818, 495: 3249, 497: 3247, 3248, 3246, 3244, 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818, 1818, 511: 1818, 514: 1818, 1818, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5347}, - {472: 5259, 5260, 503: 5258, 506: 5261, 5257, 5262, 5263, 511: 5348, 807: 5256, 813: 5255}, - {900, 900, 7: 900, 57: 900, 461: 900, 463: 900, 469: 900, 471: 900, 479: 900, 900, 482: 900, 900, 900, 486: 900, 491: 900, 900, 900, 501: 900, 900, 504: 900, 900}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 5350, 879: 5351, 913: 5352}, + {242, 242, 473: 242}, + {2: 381, 381, 381, 381, 381, 8: 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 48: 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5362}, + {380, 380}, + {20: 5375, 110: 5365, 123: 5368, 142: 559, 182: 5367, 189: 5378, 198: 5376, 213: 5369, 224: 5373, 244: 5377, 247: 5370, 536: 5374, 562: 5364, 1132: 5372, 1201: 5366, 1230: 5371}, // 2890 - {485: 5360}, - {2285, 2285, 7: 2285, 471: 2285, 483: 2285, 492: 2285, 2285}, - {237, 237, 7: 5353, 471: 237, 483: 237, 492: 2636, 237, 780: 2637, 5354}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 5350, 879: 5359}, - {1265, 1265, 471: 1265, 483: 1265, 493: 2639, 756: 2640, 801: 5355}, + {2008, 2008, 2008, 2008, 2008, 2008, 2008, 8: 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 48: 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 466: 2008, 558: 2008}, + {2007, 2007, 2007, 2007, 2007, 2007, 2007, 8: 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 48: 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 466: 2007, 558: 2007}, + {569, 569}, + {566, 566}, + {565, 565}, // 2895 - {855, 855, 471: 855, 483: 5356, 1053: 5357}, - {496: 2650, 567: 2652, 725: 2649, 734: 2651, 869: 5358}, - {241, 241, 471: 241}, - {854, 854, 471: 854}, - {2284, 2284, 7: 2284, 471: 2284, 483: 2284, 492: 2284, 2284}, + {206: 5385}, + {563, 563}, + {142: 5384}, + {550, 550, 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 550, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 4213, 1131: 5379}, + {560, 560}, // 2900 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5361}, - {2286, 2286, 7: 2286, 471: 2286, 483: 2286, 492: 2286, 2286}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 5350, 879: 5351, 913: 5363}, - {237, 237, 7: 5353, 471: 237, 492: 2636, 780: 2637, 5364}, - {240, 240, 471: 240}, + {142: 558}, + {142: 557}, + {142: 556}, + {142: 555}, + {142: 554}, // 2905 - {2: 379, 379, 379, 379, 379, 8: 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 58: 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5367}, - {378, 378}, - {31: 5380, 110: 5370, 125: 5373, 142: 556, 181: 5372, 188: 5383, 197: 5381, 213: 5374, 224: 5378, 244: 5382, 247: 5375, 532: 5379, 556: 5369, 1128: 5377, 1196: 5371, 1226: 5376}, - {2001, 2001, 2001, 2001, 2001, 2001, 2001, 8: 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 58: 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 463: 2001, 555: 2001}, + {546, 546, 466: 5381, 1330: 5380}, + {561, 561}, + {662: 5382}, + {488: 5383}, + {545, 545}, // 2910 - {2000, 2000, 2000, 2000, 2000, 2000, 2000, 8: 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 58: 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 463: 2000, 555: 2000}, - {566, 566}, - {563, 563}, {562, 562}, - {206: 5390}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5386, 2691, 2692, 2690, 943: 5387}, + {568, 568, 7: 568}, + {564, 564, 7: 5388}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5389, 2691, 2692, 2690}, // 2915 - {560, 560}, - {142: 5389}, - {547, 547, 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 547, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 4208, 1127: 5384}, - {557, 557}, - {142: 555}, + {567, 567, 7: 567}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 5493, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 5494, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 5495, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5496}, + {562: 5479, 640: 5480}, + {640: 5476}, + {562: 5471, 640: 5470}, // 2920 - {142: 554}, - {142: 553}, - {142: 552}, - {142: 551}, - {543, 543, 463: 5386, 1326: 5385}, + {562: 5468}, + {317: 5462}, + {138: 5459, 211: 5461, 328: 5457, 357: 5458, 902: 5460}, + {194: 5454, 197: 5453}, + {562: 5412}, // 2925 - {558, 558}, - {661: 5387}, - {486: 5388}, - {542, 542}, - {559, 559}, + {138: 5406, 157: 5408, 165: 578, 188: 5410, 249: 5409, 1288: 5407}, + {138: 5405}, + {138: 5404}, + {385: 5403}, + {679, 679}, // 2930 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5391, 2676, 2677, 2675, 940: 5392}, - {565, 565, 7: 565}, - {561, 561, 7: 5393}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5394, 2676, 2677, 2675}, - {564, 564, 7: 564}, + {684, 684}, + {685, 685}, + {686, 686}, + {165: 5411}, + {165: 577}, // 2935 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 5498, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 5499, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 5500, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5501}, - {556: 5484, 638: 5485}, - {638: 5481}, - {556: 5476, 638: 5475}, - {556: 5473}, + {165: 576}, + {165: 575}, + {678, 678}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5413}, + {665: 5414, 919: 5415}, // 2940 - {314: 5467}, - {138: 5464, 211: 5466, 323: 5462, 352: 5463, 902: 5465}, - {193: 5459, 196: 5458}, - {556: 5417}, - {138: 5411, 156: 5413, 165: 575, 187: 5415, 249: 5414, 1284: 5412}, + {157: 5418, 161: 5417, 562: 2023, 938: 5416}, + {687, 687}, + {562: 5420}, + {110: 2022, 562: 2022}, + {161: 5419}, // 2945 - {138: 5410}, - {138: 5409}, - {381: 5408}, - {675, 675}, - {680, 680}, + {110: 2021, 562: 2021}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 5421}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5422}, + {427, 427, 4: 427, 427, 427, 13: 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 464: 427, 5426, 427, 470: 427, 427, 427, 474: 427, 482: 427, 427, 493: 427, 495: 427, 498: 427, 427, 513: 5425, 562: 427, 637: 427, 427, 640: 427, 1225: 5424, 1298: 5423}, + {387, 387, 4: 4152, 4154, 391, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 464: 387, 387, 387, 470: 387, 4151, 4188, 474: 2125, 482: 387, 387, 493: 387, 495: 4877, 498: 2125, 387, 562: 387, 637: 387, 2125, 640: 4157, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4190, 907: 5441, 1006: 5440}, // 2950 - {681, 681}, - {682, 682}, - {165: 5416}, - {165: 574}, - {165: 573}, + {2128, 2128, 464: 5434, 1071: 5433}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5432}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 513: 5427, 565: 2351, 574: 2351, 576: 2351, 586: 2351, 616: 4499, 640: 2351, 654: 4058, 2691, 2692, 2690, 666: 2351, 2351, 735: 4366, 821: 4720, 836: 4852, 891: 4853, 956: 4854, 1129: 5428}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5430}, + {7: 4856, 47: 5429}, // 2955 - {165: 572}, - {674, 674}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5418}, - {664: 5419, 919: 5420}, - {156: 5423, 160: 5422, 556: 2016, 935: 5421}, + {426, 426, 4: 426, 426, 426, 13: 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 464: 426, 426, 426, 470: 426, 426, 426, 474: 426, 482: 426, 426, 493: 426, 495: 426, 498: 426, 426, 562: 426, 637: 426, 426, 640: 426}, + {47: 5431}, + {2056, 2056, 464: 2056}, + {2057, 2057, 464: 2057}, + {2129, 2129}, // 2960 - {683, 683}, - {556: 5425}, - {110: 2015, 556: 2015}, - {160: 5424}, - {110: 2014, 556: 2014}, + {145: 5435}, + {364: 5437, 733: 5436}, + {516: 5439}, + {516: 5438}, + {2126, 2126}, // 2965 - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 5426}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5427}, - {425, 425, 4: 425, 425, 425, 13: 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 425, 461: 425, 5431, 425, 467: 425, 425, 425, 425, 477: 425, 425, 487: 425, 425, 425, 494: 425, 510: 5430, 556: 425, 634: 425, 637: 425, 425, 1220: 5429, 1294: 5428}, - {385, 385, 4: 4147, 4149, 389, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 461: 385, 385, 385, 467: 4146, 385, 4183, 2118, 477: 385, 385, 487: 385, 4860, 2118, 494: 385, 556: 385, 634: 385, 637: 2118, 4152, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4185, 907: 5446, 1002: 5445}, - {2121, 2121, 461: 5439, 1068: 5438}, + {2127, 2127}, + {2123, 2123, 464: 2123, 2123, 2123, 470: 2123, 482: 2123, 5443, 493: 2123, 499: 2123, 562: 2123, 637: 2123, 1084: 5442}, + {386, 386, 4: 4152, 4154, 391, 4879, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 464: 386, 386, 386, 470: 386, 4151, 4188, 474: 2125, 482: 386, 386, 493: 386, 495: 4877, 498: 2125, 386, 562: 386, 637: 386, 2125, 640: 4157, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4878}, + {2071, 2071, 464: 2071, 2071, 2071, 470: 2071, 482: 5032, 493: 2071, 499: 5033, 562: 2071, 637: 2071, 1026: 5444}, + {650: 4927}, // 2970 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5437}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 510: 5432, 566: 2335, 574: 2335, 576: 2335, 632: 2335, 4494, 638: 2335, 653: 4040, 2676, 2677, 2675, 665: 2335, 2335, 733: 4361, 822: 4703, 836: 4835, 891: 4836, 953: 4837, 1125: 5433}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5435}, - {7: 4839, 57: 5434}, - {424, 424, 4: 424, 424, 424, 13: 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, 461: 424, 424, 424, 467: 424, 424, 424, 424, 477: 424, 424, 487: 424, 424, 424, 494: 424, 556: 424, 634: 424, 637: 424, 424}, + {2068, 2068, 464: 2068, 2068, 2068, 470: 5446, 493: 2068, 562: 2068, 637: 2068, 1159: 5445}, + {2066, 2066, 464: 2066, 2523, 2522, 493: 2521, 562: 2520, 637: 2516, 700: 5451, 742: 5449, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5450, 5448, 3797, 1181: 5447}, + {2067, 2067, 464: 2067, 2067, 2067, 493: 2067, 562: 2067, 637: 2067}, + {2128, 2128, 464: 5434, 1071: 5452}, + {2065, 2065, 464: 2065}, // 2975 - {57: 5436}, - {2049, 2049, 461: 2049}, - {2050, 2050, 461: 2050}, - {2122, 2122}, - {145: 5440}, + {2064, 2064, 464: 2064, 472: 791, 480: 791, 791}, + {2063, 2063, 464: 2063}, + {2062, 2062, 464: 2062, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {2130, 2130}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5386, 2691, 2692, 2690, 943: 5456}, // 2980 - {359: 5442, 732: 5441}, - {513: 5444}, - {513: 5443}, - {2119, 2119}, - {2120, 2120}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5386, 2691, 2692, 2690, 943: 5455}, + {689, 689, 7: 5388}, + {690, 690, 7: 5388}, + {692, 692}, + {691, 691}, // 2985 - {2116, 2116, 461: 2116, 2116, 2116, 468: 2116, 477: 2116, 5448, 487: 2116, 494: 2116, 556: 2116, 634: 2116, 1081: 5447}, - {384, 384, 4: 4147, 4149, 389, 4862, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 461: 384, 384, 384, 467: 4146, 384, 4183, 2118, 477: 384, 384, 487: 384, 4860, 2118, 494: 384, 556: 384, 634: 384, 637: 2118, 4152, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4861}, - {2064, 2064, 461: 2064, 2064, 2064, 468: 2064, 477: 5037, 487: 2064, 494: 5038, 556: 2064, 634: 2064, 1022: 5449}, - {649: 4932}, - {2061, 2061, 461: 2061, 2061, 2061, 468: 5451, 487: 2061, 556: 2061, 634: 2061, 1155: 5450}, + {683, 683}, + {682, 682}, + {681, 681}, + {253: 5463}, + {500: 2665, 724: 3968, 755: 5465, 1067: 5464}, // 2990 - {2059, 2059, 461: 2059, 2509, 2508, 487: 2507, 556: 2506, 634: 2502, 699: 5456, 741: 5454, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 5455, 5453, 3779, 1176: 5452}, - {2060, 2060, 461: 2060, 2060, 2060, 487: 2060, 556: 2060, 634: 2060}, - {2121, 2121, 461: 5439, 1068: 5457}, - {2058, 2058, 461: 2058}, - {2057, 2057, 461: 2057, 469: 787, 479: 787, 787}, + {695, 695, 7: 5466}, + {670, 670, 7: 670}, + {500: 2665, 724: 3968, 755: 5467}, + {669, 669, 7: 669}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 5469}, // 2995 - {2056, 2056, 461: 2056}, - {2055, 2055, 461: 2055, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {2123, 2123}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5391, 2676, 2677, 2675, 940: 5461}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5391, 2676, 2677, 2675, 940: 5460}, + {696, 696, 7: 3841}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5474}, + {488: 5472}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 5473}, + {688, 688, 7: 3841}, // 3000 - {685, 685, 7: 5393}, - {686, 686, 7: 5393}, - {688, 688}, - {687, 687}, - {679, 679}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5475, 2691, 2692, 2690}, + {698, 698}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5477}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5478, 2691, 2692, 2690}, + {699, 699}, // 3005 - {678, 678}, - {677, 677}, - {253: 5468}, - {496: 2650, 725: 3950, 751: 5470, 1064: 5469}, - {691, 691, 7: 5471}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 5492}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5481}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5482, 2691, 2692, 2690}, + {700, 700, 465: 5485, 1044: 5484, 1206: 5483}, + {697, 697, 7: 5490}, // 3010 - {666, 666, 7: 666}, - {496: 2650, 725: 3950, 751: 5472}, - {665, 665, 7: 665}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 5474}, - {692, 692, 7: 3823}, + {673, 673, 7: 673}, + {500: 2665, 724: 3968, 755: 5486}, + {7: 5487}, + {500: 2665, 724: 3968, 755: 5488}, + {47: 5489}, // 3015 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5479}, - {486: 5477}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 5478}, - {684, 684, 7: 3823}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5480, 2676, 2677, 2675}, + {671, 671, 7: 671}, + {465: 5485, 1044: 5491}, + {672, 672, 7: 672}, + {701, 701, 7: 3841}, + {158: 1605, 368: 5506, 390: 5507, 643: 1605, 1150: 5505}, // 3020 - {694, 694}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5482}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5483, 2676, 2677, 2675}, - {695, 695}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 5497}, + {705, 705, 158: 1447, 252: 5499, 5498, 643: 1447}, + {680, 680, 158: 1428, 643: 1428}, + {158: 5497}, + {702, 702}, + {239, 239, 492: 2651, 500: 2665, 724: 3968, 755: 5503, 779: 2652, 5502}, // 3025 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5486}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5487, 2676, 2677, 2675}, - {696, 696, 462: 5490, 1040: 5489, 1201: 5488}, - {693, 693, 7: 5495}, - {669, 669, 7: 669}, + {367: 5500}, + {500: 2665, 724: 3968, 755: 5465, 1067: 5501}, + {694, 694, 7: 5466}, + {704, 704}, + {239, 239, 492: 2651, 779: 2652, 5504}, // 3030 - {496: 2650, 725: 3950, 751: 5491}, - {7: 5492}, - {496: 2650, 725: 3950, 751: 5493}, - {57: 5494}, - {667, 667, 7: 667}, + {703, 703}, + {693, 693}, + {500: 2665, 724: 5513}, + {339: 5509, 500: 2665, 642: 5510, 724: 5508}, + {676, 676}, // 3035 - {462: 5490, 1040: 5496}, - {668, 668, 7: 668}, - {697, 697, 7: 3823}, - {157: 1601, 363: 5511, 387: 5512, 642: 1601, 1146: 5510}, - {701, 701, 157: 1443, 252: 5504, 5503, 642: 1443}, + {500: 2665, 724: 5512}, + {500: 2665, 724: 5511}, + {674, 674}, + {675, 675}, + {677, 677}, // 3040 - {676, 676, 157: 1424, 642: 1424}, - {157: 5502}, - {698, 698}, - {237, 237, 492: 2636, 496: 2650, 725: 3950, 751: 5508, 780: 2637, 5507}, - {362: 5505}, + {2: 261, 261, 261, 261, 261, 8: 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 48: 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 468: 261, 471: 261, 489: 1768, 536: 261, 643: 1768, 651: 1768}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5664, 489: 1766, 643: 1766, 651: 1766, 654: 5663, 2691, 2692, 2690}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 5661, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 489: 1729, 643: 1729, 651: 1729, 654: 5526, 2691, 2692, 2690, 819: 5569}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 489: 1723, 643: 1723, 651: 1723, 654: 5526, 2691, 2692, 2690, 819: 5658}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 471: 5654, 489: 1721, 536: 3678, 643: 1721, 651: 1721, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 5653}, // 3045 - {496: 2650, 725: 3950, 751: 5470, 1064: 5506}, - {690, 690, 7: 5471}, - {700, 700}, - {237, 237, 492: 2636, 780: 2637, 5509}, - {699, 699}, + {485: 5643, 489: 5642, 643: 1716, 651: 1716}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 5550, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 471: 5639, 489: 1707, 642: 5637, 1707, 651: 1707, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 5553, 1110: 5638, 1273: 5636}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 5634, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 489: 1705, 643: 1705, 651: 1705, 654: 5526, 2691, 2692, 2690, 819: 5566}, + {174: 5619, 489: 1688, 643: 1688, 651: 1688, 662: 5620, 909: 5618, 959: 5617}, + {319: 5573, 322: 5572, 489: 1632, 643: 1632, 651: 1632, 1163: 5574}, // 3050 - {689, 689}, - {496: 2650, 725: 5518}, - {334: 5514, 496: 2650, 641: 5515, 725: 5513}, - {672, 672}, - {496: 2650, 725: 5517}, + {783, 783, 7: 5562}, + {167: 5548}, + {489: 752, 643: 5546, 651: 752}, + {489: 5535, 651: 5536, 813: 5544}, + {489: 5535, 651: 5536, 813: 5539}, // 3055 - {496: 2650, 725: 5516}, - {670, 670}, - {671, 671}, - {673, 673}, - {2: 259, 259, 259, 259, 259, 8: 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 58: 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 464: 259, 467: 259, 485: 1762, 532: 259, 642: 1762, 650: 1762}, + {489: 5535, 651: 5536, 813: 5537}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 471: 5534, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 5533, 1168: 5532}, + {730, 730, 7: 730}, + {737, 737, 7: 737}, + {736, 736, 7: 736}, // 3060 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5623, 485: 1760, 642: 1760, 650: 1760, 653: 5622, 2676, 2677, 2675}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 5620, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 485: 1723, 642: 1723, 650: 1723, 653: 5530, 2676, 2677, 2675, 820: 5573}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 485: 1717, 642: 1717, 650: 1717, 653: 5530, 2676, 2677, 2675, 820: 5617}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 467: 5613, 485: 1715, 532: 3660, 642: 1715, 650: 1715, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 5612}, - {482: 5602, 485: 5601, 642: 1710, 650: 1710}, + {735, 735, 7: 735}, + {2: 754, 754, 754, 754, 754, 8: 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 48: 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 467: 754, 754, 754, 471: 754, 475: 754, 754, 754, 754, 754, 484: 754, 493: 754, 498: 754, 754, 754, 536: 754, 558: 754, 754, 754, 754, 563: 754, 754, 566: 754, 754, 754, 754, 754, 754, 754, 754, 577: 754, 754, 754, 754, 754, 754, 754, 754, 754, 587: 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 617: 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 639: 754}, + {2: 753, 753, 753, 753, 753, 8: 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 48: 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 467: 753, 753, 753, 471: 753, 475: 753, 753, 753, 753, 753, 484: 753, 493: 753, 498: 753, 753, 753, 536: 753, 558: 753, 753, 753, 753, 563: 753, 753, 566: 753, 753, 753, 753, 753, 753, 753, 753, 577: 753, 753, 753, 753, 753, 753, 753, 753, 753, 587: 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 617: 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 639: 753}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5538}, + {742, 742, 7: 742, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, // 3065 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 5554, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 467: 5598, 485: 1701, 641: 5596, 1701, 650: 1701, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 5557, 1106: 5597, 1269: 5595}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 5593, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 485: 1699, 642: 1699, 650: 1699, 653: 5530, 2676, 2677, 2675, 820: 5570}, - {174: 5578, 485: 1682, 642: 1682, 650: 1682, 661: 5579, 909: 5577, 956: 5576}, - {779, 779, 7: 5566}, - {167: 5552}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5543}, + {756, 756, 2930, 2776, 2812, 2932, 2703, 756, 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3783, 3173, 3254, 3172, 3169}, + {757, 757, 7: 757}, + {755, 755, 7: 755}, + {743, 743, 7: 743}, // 3070 - {485: 748, 642: 5550, 650: 748}, - {485: 5539, 650: 5540, 814: 5548}, - {485: 5539, 650: 5540, 814: 5543}, - {485: 5539, 650: 5540, 814: 5541}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 467: 5538, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 5537, 1163: 5536}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5545}, + {747, 747, 7: 747}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5547, 2691, 2692, 2690}, + {489: 751, 651: 751}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 5550, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 642: 5552, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 5553, 1110: 5551}, // 3075 - {726, 726, 7: 726}, - {733, 733, 7: 733}, - {732, 732, 7: 732}, - {731, 731, 7: 731}, - {2: 750, 750, 750, 750, 750, 8: 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 58: 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 464: 750, 750, 750, 750, 472: 750, 750, 750, 750, 750, 481: 750, 487: 750, 489: 750, 494: 750, 496: 750, 532: 750, 555: 750, 557: 750, 750, 750, 750, 750, 750, 750, 750, 750, 567: 750, 750, 750, 750, 572: 750, 750, 575: 750, 577: 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 639: 750}, + {714, 714, 7: 714, 560: 1796, 641: 714, 658: 1796}, + {773, 773, 560: 1627, 641: 773, 658: 1627}, + {641: 5560}, + {641: 772}, + {771, 771, 7: 5558, 641: 771}, // 3080 - {2: 749, 749, 749, 749, 749, 8: 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 58: 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 464: 749, 749, 749, 749, 472: 749, 749, 749, 749, 749, 481: 749, 487: 749, 489: 749, 494: 749, 496: 749, 532: 749, 555: 749, 557: 749, 749, 749, 749, 749, 749, 749, 749, 749, 567: 749, 749, 749, 749, 572: 749, 749, 575: 749, 577: 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, 639: 749}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5542}, - {738, 738, 7: 738, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5547}, - {752, 752, 2912, 2760, 2796, 2914, 2687, 752, 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3765, 3155, 3238, 3154, 3151}, + {715, 715, 7: 715, 560: 250, 641: 715, 658: 250}, + {709, 709, 7: 709, 641: 709}, + {708, 708, 7: 708, 641: 708}, + {707, 707, 7: 707, 641: 707}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5559, 5555}, // 3085 - {753, 753, 7: 753}, - {751, 751, 7: 751}, - {739, 739, 7: 739}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5549}, - {743, 743, 7: 743}, + {706, 706, 7: 706, 641: 706}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 5561}, + {774, 774, 7: 5126}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 5514, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 5517, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 5563, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 5564, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 5518, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 498: 3754, 560: 5529, 582: 5528, 638: 3752, 654: 5526, 2691, 2692, 2690, 762: 5530, 819: 5527, 966: 5565}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 489: 1729, 643: 1729, 651: 1729, 654: 5526, 2691, 2692, 2690, 819: 5569}, // 3090 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5551, 2676, 2677, 2675}, - {485: 747, 650: 747}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 5554, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 641: 5556, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 5557, 1106: 5555}, - {710, 710, 7: 710, 558: 1789, 640: 710, 657: 1789}, - {769, 769, 558: 1623, 640: 769, 657: 1623}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 489: 1705, 643: 1705, 651: 1705, 654: 5526, 2691, 2692, 2690, 819: 5566}, + {729, 729, 7: 729}, + {489: 5535, 651: 5536, 813: 5567}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5568}, + {745, 745, 7: 745}, // 3095 - {640: 5564}, - {640: 768}, - {767, 767, 7: 5562, 640: 767}, - {711, 711, 7: 711, 558: 248, 640: 711, 657: 248}, - {705, 705, 7: 705, 640: 705}, + {489: 5535, 651: 5536, 813: 5570}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5571}, + {746, 746, 7: 746}, + {485: 2165}, + {485: 2164}, // 3100 - {704, 704, 7: 704, 640: 704}, - {703, 703, 7: 703, 640: 703}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5563, 5559}, - {702, 702, 7: 702, 640: 702}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 5565}, + {485: 5575}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 5586}, + {2: 829, 829, 829, 829, 829, 8: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 48: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 482: 829, 490: 829, 739: 829, 829, 829, 753: 5224, 855: 5225, 906: 5590}, + {465: 2523, 493: 2521, 562: 2520, 637: 2516, 645: 2621, 700: 3805, 742: 3804, 2517, 2518, 2519, 2528, 2526, 3806, 3807, 763: 5589}, + {177, 177, 472: 790, 177, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, // 3105 - {770, 770, 7: 5131}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 5519, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 5522, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 5567, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 5568, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 5523, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 489: 3736, 558: 5533, 577: 5532, 637: 3734, 653: 5530, 2676, 2677, 2675, 762: 5534, 820: 5531, 963: 5569}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 485: 1723, 642: 1723, 650: 1723, 653: 5530, 2676, 2677, 2675, 820: 5573}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 485: 1699, 642: 1699, 650: 1699, 653: 5530, 2676, 2677, 2675, 820: 5570}, - {725, 725, 7: 725}, + {179, 179, 472: 791, 179, 480: 791, 791}, + {180, 180, 473: 180}, + {178, 178, 473: 178}, + {176, 176, 473: 176}, + {175, 175, 473: 175}, // 3110 - {485: 5539, 650: 5540, 814: 5571}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5572}, - {741, 741, 7: 741}, - {485: 5539, 650: 5540, 814: 5574}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5575}, + {174, 174, 473: 174}, + {173, 173, 473: 173}, + {169, 169, 473: 5587}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 5588}, + {168, 168}, // 3115 - {742, 742, 7: 742}, - {774, 774, 7: 5591}, - {763, 763, 7: 763}, - {340: 5583}, - {150: 5581, 677: 5580}, + {244, 244, 473: 244}, + {2: 1031, 1031, 1031, 1031, 1031, 8: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 48: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 482: 1031, 490: 1031, 739: 5229, 5228, 5227, 826: 5230, 875: 5591}, + {2: 1019, 1019, 1019, 1019, 1019, 8: 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 48: 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 5593, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 482: 1019, 490: 1019, 1093: 5592}, + {2: 1820, 1820, 1820, 1820, 1820, 8: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 48: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 482: 4105, 490: 1820, 844: 5594}, + {2: 1018, 1018, 1018, 1018, 1018, 8: 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 48: 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 482: 1018, 490: 1018}, // 3120 - {760, 760, 7: 760}, - {759, 759, 7: 759, 663: 5302, 912: 5582}, - {758, 758, 7: 758}, - {210: 5585, 370: 5587, 661: 5586, 1215: 5584}, - {761, 761, 7: 761}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 490: 5595, 654: 5597, 2691, 2692, 2690, 905: 5598, 955: 5596}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5610}, + {7: 5606, 490: 5605}, + {7: 1021, 473: 1021, 490: 1021, 643: 5600, 895: 5599}, + {7: 1023, 473: 1023, 490: 1023}, // 3125 - {661: 5590}, - {310: 5588, 391: 5589}, - {754, 754, 7: 754}, - {756, 756, 7: 756}, - {755, 755, 7: 755}, + {7: 1025, 473: 1025, 490: 1025}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5602, 654: 5601, 2691, 2692, 2690}, + {7: 1021, 473: 1021, 490: 1021, 643: 5604, 895: 5603}, + {7: 1020, 473: 1020, 490: 1020}, + {7: 1024, 473: 1024, 490: 1024}, // 3130 - {757, 757, 7: 757}, - {174: 5578, 661: 5579, 909: 5592}, - {762, 762, 7: 762}, - {174: 5578, 485: 1682, 642: 1682, 650: 1682, 661: 5579, 909: 5577, 956: 5594}, - {775, 775, 7: 5591}, + {515: 5602}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 571: 5236, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5243, 840: 5233, 878: 5608}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5597, 2691, 2692, 2690, 905: 5607}, + {7: 1022, 473: 1022, 490: 1022}, + {239, 239, 7: 5287, 473: 239, 492: 2651, 779: 2652, 5609}, // 3135 - {771, 771}, - {768, 768, 479: 5599}, - {765, 765}, - {764, 764}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 5600}, + {2033, 2033, 473: 2033}, + {898, 898, 898, 898, 898, 898, 898, 8: 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 48: 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 470: 898, 473: 898, 482: 898, 5291, 486: 898, 492: 898, 494: 898, 898, 517: 898, 849: 5611}, + {896, 896, 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 470: 5248, 473: 896, 482: 896, 486: 896, 492: 896, 494: 896, 896, 517: 896, 654: 5247, 2691, 2692, 2690, 903: 5246, 5612}, + {877, 877, 473: 877, 482: 5301, 486: 877, 492: 877, 494: 877, 5302, 517: 5300, 928: 5304, 5303, 1048: 5305, 5613}, + {239, 239, 473: 239, 486: 239, 492: 2651, 494: 239, 779: 2652, 5614}, // 3140 - {766, 766, 7: 5562}, - {14: 5607, 464: 5606, 1082: 5611}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5603}, - {485: 5604}, - {14: 5607, 464: 5606, 1082: 5605}, + {1269, 1269, 473: 1269, 486: 1269, 494: 2654, 757: 2655, 800: 5615}, + {859, 859, 473: 859, 486: 5351, 1057: 5616}, + {2034, 2034, 473: 2034}, + {778, 778, 7: 5632}, + {767, 767, 7: 767}, // 3145 - {777, 777}, - {714, 714}, - {462: 5608}, - {464: 5161, 880: 5609}, - {57: 5610}, + {345: 5624}, + {151: 5622, 678: 5621}, + {764, 764, 7: 764}, + {763, 763, 7: 763, 664: 5297, 912: 5623}, + {762, 762, 7: 762}, // 3150 - {713, 713}, - {778, 778}, - {737, 737, 7: 737, 470: 5614}, - {734, 734, 7: 734}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 467: 5615, 653: 3392, 2676, 2677, 2675, 728: 5616}, + {210: 5626, 374: 5628, 662: 5627, 1220: 5625}, + {765, 765, 7: 765}, + {662: 5631}, + {313: 5629, 394: 5630}, + {758, 758, 7: 758}, // 3155 - {736, 736, 7: 736}, - {735, 735, 7: 735}, - {485: 5539, 650: 5540, 814: 5618}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5619}, - {740, 740, 7: 740}, + {760, 760, 7: 760}, + {759, 759, 7: 759}, + {761, 761, 7: 761}, + {174: 5619, 662: 5620, 909: 5633}, + {766, 766, 7: 766}, // 3160 - {174: 5578, 485: 1682, 642: 1682, 650: 1682, 661: 5579, 909: 5577, 956: 5621}, - {776, 776, 7: 5591}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5625, 2676, 2677, 2675, 890: 5632}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5625, 2676, 2677, 2675, 890: 5624}, - {485: 5539, 650: 5540, 814: 5630}, + {174: 5619, 489: 1688, 643: 1688, 651: 1688, 662: 5620, 909: 5618, 959: 5635}, + {779, 779, 7: 5632}, + {775, 775}, + {772, 772, 480: 5640}, + {769, 769}, // 3165 - {474: 5627, 485: 746, 642: 5626, 650: 746}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5625, 2676, 2677, 2675, 890: 5629}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5625, 2676, 2677, 2675, 890: 5628}, - {485: 744, 650: 744}, - {485: 745, 650: 745}, + {768, 768}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 5641}, + {770, 770, 7: 5558}, + {13: 5648, 468: 5647, 1085: 5652}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5644}, // 3170 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5631}, - {772, 772}, - {485: 5539, 650: 5540, 814: 5633}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 5545, 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 5544, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5546, 830: 5634}, - {773, 773}, + {489: 5645}, + {13: 5648, 468: 5647, 1085: 5646}, + {781, 781}, + {718, 718}, + {465: 5649}, // 3175 - {640: 5644}, - {640: 5637}, - {259: 5638}, - {485: 5639}, - {464: 5640}, + {468: 5156, 881: 5650}, + {47: 5651}, + {717, 717}, + {782, 782}, + {741, 741, 7: 741, 474: 5655}, // 3180 - {482: 5641}, - {258: 5642}, - {464: 5643}, - {780, 780}, - {259: 5645}, + {738, 738, 7: 738}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 471: 5656, 654: 3410, 2691, 2692, 2690, 729: 5657}, + {740, 740, 7: 740}, + {739, 739, 7: 739}, + {489: 5535, 651: 5536, 813: 5659}, // 3185 - {485: 5646}, - {464: 5647}, - {482: 5648}, - {258: 5649}, - {464: 5650}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5660}, + {744, 744, 7: 744}, + {174: 5619, 489: 1688, 643: 1688, 651: 1688, 662: 5620, 909: 5618, 959: 5662}, + {780, 780, 7: 5632}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5666, 2691, 2692, 2690, 890: 5673}, // 3190 - {781, 781}, - {462: 2509, 487: 2507, 556: 2506, 634: 2502, 699: 5662, 741: 5661, 2503, 2504, 2505, 5663}, - {462: 1208, 487: 1208, 556: 1208, 634: 1208, 641: 3447, 735: 3445, 3446, 774: 5655, 777: 5656, 921: 5658, 951: 5660}, - {462: 1208, 487: 1208, 556: 1208, 634: 1208, 641: 3447, 735: 3445, 3446, 774: 5655, 777: 5656, 921: 5658, 951: 5659}, - {462: 1208, 487: 1208, 556: 1208, 634: 1208, 641: 3447, 735: 3445, 3446, 774: 5655, 777: 5656, 921: 5658, 951: 5657}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5666, 2691, 2692, 2690, 890: 5665}, + {489: 5535, 651: 5536, 813: 5671}, + {477: 5668, 489: 750, 643: 5667, 651: 750}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5666, 2691, 2692, 2690, 890: 5670}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5666, 2691, 2692, 2690, 890: 5669}, // 3195 - {2: 1211, 1211, 1211, 1211, 1211, 8: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 58: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 462: 1211, 464: 1211, 1211, 1211, 1211, 472: 1211, 1211, 1211, 1211, 1211, 481: 1211, 487: 1211, 489: 1211, 494: 1211, 496: 1211, 503: 1211, 512: 1211, 532: 1211, 555: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 567: 1211, 1211, 1211, 1211, 572: 1211, 1211, 575: 1211, 577: 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 634: 1211, 639: 1211, 641: 1211, 735: 1211, 1211, 738: 1211, 1211, 1211, 749: 1211, 758: 1211, 1211, 1211}, - {462: 1207, 487: 1207, 556: 1207, 634: 1207}, - {462: 783, 487: 783, 556: 783, 634: 783}, - {462: 782, 487: 782, 556: 782, 634: 782}, - {462: 784, 487: 784, 556: 784, 634: 784}, + {489: 748, 651: 748}, + {489: 749, 651: 749}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5672}, + {776, 776}, + {489: 5535, 651: 5536, 813: 5674}, // 3200 - {462: 785, 487: 785, 556: 785, 634: 785}, - {797, 797, 57: 797, 461: 797, 463: 797, 469: 787, 471: 797, 479: 787, 787}, - {796, 796, 57: 796, 461: 796, 463: 796, 469: 786, 471: 796, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 5664, 5665}, - {469: 788, 479: 788, 788}, - {795, 795, 57: 795, 461: 795, 463: 795, 471: 795, 483: 2642, 491: 2643, 757: 5666}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 5541, 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 5540, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5542, 829: 5675}, + {777, 777}, + {641: 5685}, + {641: 5678}, + {259: 5679}, // 3205 - {794, 794, 57: 794, 461: 794, 463: 794, 471: 794}, - {793, 793, 57: 793, 461: 793, 463: 793, 471: 793}, - {57: 3873, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {7: 5682, 462: 969, 487: 969, 556: 969, 634: 969, 644: 969, 732: 969}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5671, 2676, 2677, 2675, 918: 5670, 1144: 5681}, + {489: 5680}, + {468: 5681}, + {485: 5682}, + {258: 5683}, + {468: 5684}, // 3210 - {7: 966, 462: 966, 487: 966, 556: 966, 634: 966, 644: 966, 732: 966}, - {462: 5672, 468: 2260, 1203: 5673}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5677, 2676, 2677, 2675, 864: 5676}, - {468: 5674}, - {462: 2509, 699: 5675}, + {784, 784}, + {259: 5686}, + {489: 5687}, + {468: 5688}, + {485: 5689}, // 3215 - {7: 965, 462: 965, 487: 965, 556: 965, 634: 965, 644: 965, 732: 965}, - {7: 5679, 57: 5678}, - {2258, 2258, 7: 2258, 57: 2258, 463: 2258}, - {468: 2259}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5680, 2676, 2677, 2675}, + {258: 5690}, + {468: 5691}, + {785, 785}, + {465: 2523, 493: 2521, 562: 2520, 637: 2516, 700: 5703, 742: 5702, 2517, 2518, 2519, 5704}, + {465: 1212, 493: 1212, 562: 1212, 637: 1212, 642: 3465, 736: 3463, 3464, 773: 5696, 776: 5697, 921: 5699, 954: 5701}, // 3220 - {2257, 2257, 7: 2257, 57: 2257, 463: 2257}, - {7: 5682, 462: 968, 487: 968, 556: 968, 634: 968, 644: 968, 732: 968}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5671, 2676, 2677, 2675, 918: 5683}, - {7: 967, 462: 967, 487: 967, 556: 967, 634: 967, 644: 967, 732: 967}, - {1265, 1265, 57: 1265, 461: 1265, 463: 1265, 469: 1265, 471: 1265, 479: 1265, 1265, 482: 1265, 1265, 1265, 486: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 5685}, + {465: 1212, 493: 1212, 562: 1212, 637: 1212, 642: 3465, 736: 3463, 3464, 773: 5696, 776: 5697, 921: 5699, 954: 5700}, + {465: 1212, 493: 1212, 562: 1212, 637: 1212, 642: 3465, 736: 3463, 3464, 773: 5696, 776: 5697, 921: 5699, 954: 5698}, + {2: 1215, 1215, 1215, 1215, 1215, 8: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 48: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 465: 1215, 467: 1215, 1215, 1215, 471: 1215, 475: 1215, 1215, 1215, 1215, 1215, 484: 1215, 493: 1215, 498: 1215, 1215, 1215, 506: 1215, 515: 1215, 536: 1215, 558: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 566: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 577: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 587: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 617: 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 637: 1215, 639: 1215, 642: 1215, 736: 1215, 1215, 739: 1215, 1215, 1215, 753: 1215, 759: 1215, 1215, 1215}, + {465: 1211, 493: 1211, 562: 1211, 637: 1211}, + {465: 787, 493: 787, 562: 787, 637: 787}, // 3225 - {841, 841, 57: 841, 461: 841, 463: 841, 469: 841, 471: 841, 479: 841, 841, 482: 841, 2642, 841, 486: 841, 491: 2643, 757: 2644, 818: 5686}, - {812, 812, 57: 812, 461: 812, 463: 812, 469: 812, 471: 812, 479: 812, 812, 482: 3811, 484: 812, 486: 3812, 875: 5687}, - {818, 818, 57: 818, 461: 818, 463: 818, 469: 818, 471: 818, 479: 818, 818, 484: 3837, 876: 5688}, - {973, 973, 57: 973, 461: 973, 463: 973, 469: 973, 471: 973, 479: 973, 973}, - {841, 841, 57: 841, 461: 841, 463: 841, 469: 841, 471: 841, 479: 841, 841, 482: 841, 2642, 841, 486: 841, 491: 2643, 757: 2644, 818: 5690}, + {465: 786, 493: 786, 562: 786, 637: 786}, + {465: 788, 493: 788, 562: 788, 637: 788}, + {465: 789, 493: 789, 562: 789, 637: 789}, + {801, 801, 47: 801, 464: 801, 466: 801, 472: 791, 801, 480: 791, 791}, + {800, 800, 47: 800, 464: 800, 466: 800, 472: 790, 800, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 5705, 5706}, // 3230 - {812, 812, 57: 812, 461: 812, 463: 812, 469: 812, 471: 812, 479: 812, 812, 482: 3811, 484: 812, 486: 3812, 875: 5691}, - {818, 818, 57: 818, 461: 818, 463: 818, 469: 818, 471: 818, 479: 818, 818, 484: 3837, 876: 5692}, - {974, 974, 57: 974, 461: 974, 463: 974, 469: 974, 471: 974, 479: 974, 974}, - {649: 5700}, - {1265, 1265, 57: 1265, 461: 1265, 463: 1265, 469: 1265, 471: 1265, 479: 1265, 1265, 482: 1265, 1265, 1265, 486: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 5696}, + {472: 792, 480: 792, 792}, + {799, 799, 47: 799, 464: 799, 466: 799, 473: 799, 486: 2657, 491: 2658, 758: 5707}, + {798, 798, 47: 798, 464: 798, 466: 798, 473: 798}, + {797, 797, 47: 797, 464: 797, 466: 797, 473: 797}, + {47: 3891, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, // 3235 - {819, 819, 57: 819, 461: 819, 463: 819, 469: 819, 471: 819, 479: 819, 819, 482: 819, 819, 819, 486: 819, 491: 819, 493: 819, 504: 819, 819}, - {841, 841, 57: 841, 461: 841, 463: 841, 469: 841, 471: 841, 479: 841, 841, 482: 841, 2642, 841, 486: 841, 491: 2643, 757: 2644, 818: 5697}, - {812, 812, 57: 812, 461: 812, 463: 812, 469: 812, 471: 812, 479: 812, 812, 482: 3811, 484: 812, 486: 3812, 875: 5698}, - {818, 818, 57: 818, 461: 818, 463: 818, 469: 818, 471: 818, 479: 818, 818, 484: 3837, 876: 5699}, - {975, 975, 57: 975, 461: 975, 463: 975, 469: 975, 471: 975, 479: 975, 975}, + {7: 5723, 465: 973, 493: 973, 562: 973, 637: 973, 645: 973, 733: 973}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5712, 2691, 2692, 2690, 918: 5711, 1148: 5722}, + {7: 970, 465: 970, 493: 970, 562: 970, 637: 970, 645: 970, 733: 970}, + {465: 5713, 470: 2276, 1208: 5714}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5718, 2691, 2692, 2690, 865: 5717}, // 3240 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 2668, 859: 3144, 888: 5701}, - {1823, 1823, 7: 3313, 57: 1823, 461: 1823, 463: 1823, 469: 1823, 471: 1823, 479: 1823, 1823, 482: 1823, 1823, 1823, 486: 1823, 491: 1823, 493: 1823, 504: 1823, 1823}, - {237, 237, 57: 237, 461: 237, 463: 237, 469: 237, 471: 237, 479: 237, 237, 482: 237, 237, 237, 486: 237, 491: 237, 2636, 237, 502: 237, 780: 2637, 5727}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 568: 5241, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5248, 840: 5238, 877: 5712, 1182: 5711, 1296: 5710}, - {820, 820, 57: 820, 461: 820, 463: 820, 469: 820, 471: 820, 479: 820, 820, 482: 820, 820, 820, 486: 820, 491: 820, 493: 820, 502: 5693, 927: 5695, 950: 5705}, + {470: 5715}, + {465: 2523, 700: 5716}, + {7: 969, 465: 969, 493: 969, 562: 969, 637: 969, 645: 969, 733: 969}, + {7: 5720, 47: 5719}, + {2274, 2274, 7: 2274, 47: 2274, 466: 2274}, // 3245 - {1265, 1265, 57: 1265, 461: 1265, 463: 1265, 469: 1265, 471: 1265, 479: 1265, 1265, 482: 1265, 1265, 1265, 486: 1265, 491: 1265, 493: 2639, 756: 2640, 801: 5706}, - {841, 841, 57: 841, 461: 841, 463: 841, 469: 841, 471: 841, 479: 841, 841, 482: 841, 2642, 841, 486: 841, 491: 2643, 757: 2644, 818: 5707}, - {812, 812, 57: 812, 461: 812, 463: 812, 469: 812, 471: 812, 479: 812, 812, 482: 3811, 484: 812, 486: 3812, 875: 5708}, - {818, 818, 57: 818, 461: 818, 463: 818, 469: 818, 471: 818, 479: 818, 818, 484: 3837, 876: 5709}, - {976, 976, 57: 976, 461: 976, 463: 976, 469: 976, 471: 976, 479: 976, 976}, + {470: 2275}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5721, 2691, 2692, 2690}, + {2273, 2273, 7: 2273, 47: 2273, 466: 2273}, + {7: 5723, 465: 972, 493: 972, 562: 972, 637: 972, 645: 972, 733: 972}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5712, 2691, 2692, 2690, 918: 5724}, // 3250 - {237, 237, 57: 237, 461: 237, 463: 237, 469: 237, 471: 237, 479: 237, 237, 482: 237, 237, 237, 486: 237, 491: 237, 2636, 237, 502: 237, 504: 237, 237, 780: 2637, 5713}, - {964, 964, 57: 964, 461: 964, 463: 964, 469: 964, 471: 964, 479: 964, 964, 482: 964, 964, 964, 486: 964, 491: 964, 964, 964, 502: 964}, - {904, 904, 7: 5292, 57: 904, 461: 904, 463: 904, 469: 904, 471: 904, 479: 904, 904, 482: 904, 904, 904, 486: 904, 491: 904, 904, 904, 502: 904, 504: 904, 904}, - {820, 820, 57: 820, 461: 820, 463: 820, 469: 820, 471: 820, 479: 820, 820, 482: 820, 820, 820, 486: 820, 491: 820, 493: 820, 502: 5693, 504: 820, 820, 927: 5695, 950: 5714}, - {1822, 1822, 57: 1822, 461: 1822, 463: 1822, 469: 1822, 471: 1822, 479: 1822, 1822, 482: 1822, 1822, 1822, 486: 1822, 491: 1822, 493: 1822, 504: 1822, 5715, 1202: 5716}, + {7: 971, 465: 971, 493: 971, 562: 971, 637: 971, 645: 971, 733: 971}, + {1269, 1269, 47: 1269, 464: 1269, 466: 1269, 472: 1269, 1269, 480: 1269, 1269, 485: 1269, 1269, 1269, 1269, 491: 1269, 494: 2654, 757: 2655, 800: 5726}, + {845, 845, 47: 845, 464: 845, 466: 845, 472: 845, 845, 480: 845, 845, 485: 845, 2657, 845, 845, 491: 2658, 758: 2659, 817: 5727}, + {816, 816, 47: 816, 464: 816, 466: 816, 472: 816, 816, 480: 816, 816, 485: 3829, 487: 816, 3830, 876: 5728}, + {822, 822, 47: 822, 464: 822, 466: 822, 472: 822, 822, 480: 822, 822, 487: 3855, 877: 5729}, // 3255 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5726}, - {963, 963, 57: 963, 461: 963, 463: 963, 469: 963, 471: 963, 479: 963, 963, 482: 963, 963, 963, 486: 963, 491: 963, 493: 963, 504: 5718, 1319: 5717}, - {989, 989, 57: 989, 461: 989, 463: 989, 469: 989, 471: 989, 479: 989, 989, 482: 989, 989, 989, 486: 989, 491: 989, 493: 989}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3301, 2676, 2677, 2675, 911: 5721, 1140: 5720, 1320: 5719}, - {962, 962, 7: 5724, 57: 962, 461: 962, 463: 962, 469: 962, 471: 962, 479: 962, 962, 482: 962, 962, 962, 486: 962, 491: 962, 493: 962}, + {977, 977, 47: 977, 464: 977, 466: 977, 472: 977, 977, 480: 977, 977}, + {845, 845, 47: 845, 464: 845, 466: 845, 472: 845, 845, 480: 845, 845, 485: 845, 2657, 845, 845, 491: 2658, 758: 2659, 817: 5731}, + {816, 816, 47: 816, 464: 816, 466: 816, 472: 816, 816, 480: 816, 816, 485: 3829, 487: 816, 3830, 876: 5732}, + {822, 822, 47: 822, 464: 822, 466: 822, 472: 822, 822, 480: 822, 822, 487: 3855, 877: 5733}, + {978, 978, 47: 978, 464: 978, 466: 978, 472: 978, 978, 480: 978, 978}, // 3260 - {961, 961, 7: 961, 57: 961, 461: 961, 463: 961, 469: 961, 471: 961, 479: 961, 961, 482: 961, 961, 961, 486: 961, 491: 961, 493: 961}, - {468: 5722}, - {462: 3302, 1142: 5723}, - {959, 959, 7: 959, 57: 959, 461: 959, 463: 959, 469: 959, 471: 959, 479: 959, 959, 482: 959, 959, 959, 486: 959, 491: 959, 493: 959}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3301, 2676, 2677, 2675, 911: 5721, 1140: 5725}, + {650: 5741}, + {1269, 1269, 47: 1269, 464: 1269, 466: 1269, 472: 1269, 1269, 480: 1269, 1269, 485: 1269, 1269, 1269, 1269, 491: 1269, 494: 2654, 757: 2655, 800: 5737}, + {823, 823, 47: 823, 464: 823, 466: 823, 472: 823, 823, 480: 823, 823, 485: 823, 823, 823, 823, 491: 823, 494: 823, 507: 823, 823}, + {845, 845, 47: 845, 464: 845, 466: 845, 472: 845, 845, 480: 845, 845, 485: 845, 2657, 845, 845, 491: 2658, 758: 2659, 817: 5738}, + {816, 816, 47: 816, 464: 816, 466: 816, 472: 816, 816, 480: 816, 816, 485: 3829, 487: 816, 3830, 876: 5739}, // 3265 - {960, 960, 7: 960, 57: 960, 461: 960, 463: 960, 469: 960, 471: 960, 479: 960, 960, 482: 960, 960, 960, 486: 960, 491: 960, 493: 960}, - {1821, 1821, 57: 1821, 461: 1821, 463: 1821, 469: 1821, 471: 1821, 479: 1821, 1821, 482: 1821, 1821, 1821, 486: 1821, 491: 1821, 493: 1821, 495: 3249, 497: 3247, 3248, 3246, 3244, 504: 1821, 723: 3245, 3243}, - {990, 990, 57: 990, 461: 990, 463: 990, 469: 990, 471: 990, 479: 990, 990, 482: 990, 990, 990, 486: 990, 491: 990, 493: 990, 502: 990}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 512: 5744, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 5745, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5743, 1030: 5746, 1191: 5747, 1264: 5748}, - {2: 839, 839, 839, 839, 839, 8: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 58: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 462: 839, 464: 839, 839, 839, 839, 472: 839, 839, 839, 839, 839, 481: 839, 487: 839, 489: 839, 494: 839, 496: 839, 503: 839, 512: 839, 532: 839, 555: 839, 557: 839, 839, 839, 839, 839, 839, 839, 839, 839, 567: 839, 839, 839, 839, 572: 839, 839, 575: 839, 577: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 639: 839, 641: 839, 735: 839, 839, 738: 839, 839, 839, 749: 839, 758: 839, 839, 839}, + {822, 822, 47: 822, 464: 822, 466: 822, 472: 822, 822, 480: 822, 822, 487: 3855, 877: 5740}, + {979, 979, 47: 979, 464: 979, 466: 979, 472: 979, 979, 480: 979, 979}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 2683, 859: 3162, 888: 5742}, + {1830, 1830, 7: 3331, 47: 1830, 464: 1830, 466: 1830, 472: 1830, 1830, 480: 1830, 1830, 485: 1830, 1830, 1830, 1830, 491: 1830, 494: 1830, 507: 1830, 1830}, + {239, 239, 47: 239, 464: 239, 466: 239, 472: 239, 239, 480: 239, 239, 485: 239, 239, 239, 239, 491: 239, 2651, 494: 239, 505: 239, 779: 2652, 5768}, // 3270 - {2: 838, 838, 838, 838, 838, 8: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 58: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 462: 838, 464: 838, 838, 838, 838, 472: 838, 838, 838, 838, 838, 481: 838, 487: 838, 489: 838, 494: 838, 496: 838, 503: 838, 512: 838, 532: 838, 555: 838, 557: 838, 838, 838, 838, 838, 838, 838, 838, 838, 567: 838, 838, 838, 838, 572: 838, 838, 575: 838, 577: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 639: 838, 641: 838, 735: 838, 838, 738: 838, 838, 838, 749: 838, 758: 838, 838, 838}, - {2: 837, 837, 837, 837, 837, 8: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 58: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 462: 837, 464: 837, 837, 837, 837, 472: 837, 837, 837, 837, 837, 481: 837, 487: 837, 489: 837, 494: 837, 496: 837, 503: 837, 512: 837, 532: 837, 555: 837, 557: 837, 837, 837, 837, 837, 837, 837, 837, 837, 567: 837, 837, 837, 837, 572: 837, 837, 575: 837, 577: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 639: 837, 641: 837, 735: 837, 837, 738: 837, 837, 837, 749: 837, 758: 837, 837, 837}, - {2: 836, 836, 836, 836, 836, 8: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 58: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 462: 836, 464: 836, 836, 836, 836, 472: 836, 836, 836, 836, 836, 481: 836, 487: 836, 489: 836, 494: 836, 496: 836, 503: 836, 512: 836, 532: 836, 555: 836, 557: 836, 836, 836, 836, 836, 836, 836, 836, 836, 567: 836, 836, 836, 836, 572: 836, 836, 575: 836, 577: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 639: 836, 641: 836, 735: 836, 836, 738: 836, 836, 836, 749: 836, 758: 836, 836, 836}, - {2: 835, 835, 835, 835, 835, 8: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 58: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 462: 835, 464: 835, 835, 835, 835, 472: 835, 835, 835, 835, 835, 481: 835, 487: 835, 489: 835, 494: 835, 496: 835, 503: 835, 512: 835, 532: 835, 555: 835, 557: 835, 835, 835, 835, 835, 835, 835, 835, 835, 567: 835, 835, 835, 835, 572: 835, 835, 575: 835, 577: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 639: 835, 641: 835, 735: 835, 835, 738: 835, 835, 835, 749: 835, 758: 835, 835, 835}, - {2: 834, 834, 834, 834, 834, 8: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 58: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 462: 834, 464: 834, 834, 834, 834, 472: 834, 834, 834, 834, 834, 481: 834, 487: 834, 489: 834, 494: 834, 496: 834, 503: 834, 512: 834, 532: 834, 555: 834, 557: 834, 834, 834, 834, 834, 834, 834, 834, 834, 567: 834, 834, 834, 834, 572: 834, 834, 575: 834, 577: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 639: 834, 641: 834, 735: 834, 834, 738: 834, 834, 834, 749: 834, 758: 834, 834, 834}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 571: 5236, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5243, 840: 5233, 878: 5753, 1187: 5752, 1300: 5751}, + {824, 824, 47: 824, 464: 824, 466: 824, 472: 824, 824, 480: 824, 824, 485: 824, 824, 824, 824, 491: 824, 494: 824, 505: 5734, 927: 5736, 953: 5746}, + {1269, 1269, 47: 1269, 464: 1269, 466: 1269, 472: 1269, 1269, 480: 1269, 1269, 485: 1269, 1269, 1269, 1269, 491: 1269, 494: 2654, 757: 2655, 800: 5747}, + {845, 845, 47: 845, 464: 845, 466: 845, 472: 845, 845, 480: 845, 845, 485: 845, 2657, 845, 845, 491: 2658, 758: 2659, 817: 5748}, + {816, 816, 47: 816, 464: 816, 466: 816, 472: 816, 816, 480: 816, 816, 485: 3829, 487: 816, 3830, 876: 5749}, // 3275 - {2: 833, 833, 833, 833, 833, 8: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 58: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 462: 833, 464: 833, 833, 833, 833, 472: 833, 833, 833, 833, 833, 481: 833, 487: 833, 489: 833, 494: 833, 496: 833, 503: 833, 512: 833, 532: 833, 555: 833, 557: 833, 833, 833, 833, 833, 833, 833, 833, 833, 567: 833, 833, 833, 833, 572: 833, 833, 575: 833, 577: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 639: 833, 641: 833, 735: 833, 833, 738: 833, 833, 833, 749: 833, 758: 833, 833, 833}, - {2: 832, 832, 832, 832, 832, 8: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 58: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 462: 832, 464: 832, 832, 832, 832, 472: 832, 832, 832, 832, 832, 481: 832, 487: 832, 489: 832, 494: 832, 496: 832, 503: 832, 512: 832, 532: 832, 555: 832, 557: 832, 832, 832, 832, 832, 832, 832, 832, 832, 567: 832, 832, 832, 832, 572: 832, 832, 575: 832, 577: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 639: 832, 641: 832, 735: 832, 832, 738: 832, 832, 832, 749: 832, 758: 832, 832, 832}, - {2: 831, 831, 831, 831, 831, 8: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 58: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 462: 831, 464: 831, 831, 831, 831, 472: 831, 831, 831, 831, 831, 481: 831, 487: 831, 489: 831, 494: 831, 496: 831, 503: 831, 512: 831, 532: 831, 555: 831, 557: 831, 831, 831, 831, 831, 831, 831, 831, 831, 567: 831, 831, 831, 831, 572: 831, 831, 575: 831, 577: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 639: 831, 641: 831, 735: 831, 831, 738: 831, 831, 831, 749: 831, 758: 831, 831, 831}, - {2: 829, 829, 829, 829, 829, 8: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 58: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 5734, 5740, 5741, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 462: 829, 464: 829, 829, 829, 829, 472: 829, 829, 829, 829, 829, 481: 829, 487: 829, 489: 829, 494: 829, 496: 829, 503: 5737, 512: 829, 532: 829, 555: 829, 557: 829, 829, 829, 829, 829, 829, 829, 829, 829, 567: 829, 829, 829, 829, 572: 829, 829, 575: 829, 577: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 639: 829, 641: 3447, 735: 3445, 3446, 738: 5234, 5233, 5232, 749: 5229, 758: 5733, 5736, 5732, 774: 5655, 777: 5730, 827: 5731, 855: 5729, 1104: 5742, 5735}, - {2: 827, 827, 827, 827, 827, 8: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 58: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 462: 827, 464: 827, 827, 827, 827, 472: 827, 827, 827, 827, 827, 481: 827, 487: 827, 489: 827, 494: 827, 496: 827, 503: 827, 512: 827, 532: 827, 555: 827, 557: 827, 827, 827, 827, 827, 827, 827, 827, 827, 567: 827, 827, 827, 827, 572: 827, 827, 575: 827, 577: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 639: 827, 641: 827, 735: 827, 827, 738: 827, 827, 827, 749: 827, 758: 827, 827, 827}, + {822, 822, 47: 822, 464: 822, 466: 822, 472: 822, 822, 480: 822, 822, 487: 3855, 877: 5750}, + {980, 980, 47: 980, 464: 980, 466: 980, 472: 980, 980, 480: 980, 980}, + {239, 239, 47: 239, 464: 239, 466: 239, 472: 239, 239, 480: 239, 239, 485: 239, 239, 239, 239, 491: 239, 2651, 494: 239, 505: 239, 507: 239, 239, 779: 2652, 5754}, + {968, 968, 47: 968, 464: 968, 466: 968, 472: 968, 968, 480: 968, 968, 485: 968, 968, 968, 968, 491: 968, 968, 494: 968, 505: 968}, + {908, 908, 7: 5287, 47: 908, 464: 908, 466: 908, 472: 908, 908, 480: 908, 908, 485: 908, 908, 908, 908, 491: 908, 908, 494: 908, 505: 908, 507: 908, 908}, // 3280 - {2: 823, 823, 823, 823, 823, 8: 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 58: 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 462: 823, 464: 823, 823, 823, 823, 472: 823, 823, 823, 823, 823, 481: 823, 487: 823, 489: 823, 494: 823, 496: 823, 503: 823, 512: 823, 532: 823, 555: 823, 557: 823, 823, 823, 823, 823, 823, 823, 823, 823, 567: 823, 823, 823, 823, 572: 823, 823, 575: 823, 577: 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 639: 823, 641: 823, 735: 823, 823, 738: 823, 823, 823, 749: 823, 758: 823, 823, 823}, - {2: 822, 822, 822, 822, 822, 8: 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 58: 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 462: 822, 464: 822, 822, 822, 822, 472: 822, 822, 822, 822, 822, 481: 822, 487: 822, 489: 822, 494: 822, 496: 822, 503: 822, 512: 822, 532: 822, 555: 822, 557: 822, 822, 822, 822, 822, 822, 822, 822, 822, 567: 822, 822, 822, 822, 572: 822, 822, 575: 822, 577: 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, 639: 822, 641: 822, 735: 822, 822, 738: 822, 822, 822, 749: 822, 758: 822, 822, 822}, - {2: 828, 828, 828, 828, 828, 8: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 58: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 462: 828, 464: 828, 828, 828, 828, 472: 828, 828, 828, 828, 828, 481: 828, 487: 828, 489: 828, 494: 828, 496: 828, 503: 828, 512: 828, 532: 828, 555: 828, 557: 828, 828, 828, 828, 828, 828, 828, 828, 828, 567: 828, 828, 828, 828, 572: 828, 828, 575: 828, 577: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 639: 828, 641: 828, 735: 828, 828, 738: 828, 828, 828, 749: 828, 758: 828, 828, 828}, - {1831, 1831, 2912, 2760, 2796, 2914, 2687, 1831, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1831, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 1831, 463: 1831, 5760, 468: 5759, 1831, 471: 1831, 479: 1831, 1831, 482: 1831, 1831, 1831, 486: 1831, 490: 1831, 1831, 1831, 1831, 495: 3249, 497: 3247, 3248, 3246, 3244, 502: 1831, 653: 5758, 2676, 2677, 2675, 723: 3245, 3243, 1188: 5757, 5756}, - {1835, 1835, 7: 1835, 57: 1835, 461: 1835, 463: 1835, 469: 1835, 471: 1835, 479: 1835, 1835, 482: 1835, 1835, 1835, 486: 1835, 490: 1835, 1835, 1835, 1835, 502: 1835}, + {824, 824, 47: 824, 464: 824, 466: 824, 472: 824, 824, 480: 824, 824, 485: 824, 824, 824, 824, 491: 824, 494: 824, 505: 5734, 507: 824, 824, 927: 5736, 953: 5755}, + {1829, 1829, 47: 1829, 464: 1829, 466: 1829, 472: 1829, 1829, 480: 1829, 1829, 485: 1829, 1829, 1829, 1829, 491: 1829, 494: 1829, 507: 1829, 5756, 1207: 5757}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5767}, + {967, 967, 47: 967, 464: 967, 466: 967, 472: 967, 967, 480: 967, 967, 485: 967, 967, 967, 967, 491: 967, 494: 967, 507: 5759, 1323: 5758}, + {993, 993, 47: 993, 464: 993, 466: 993, 472: 993, 993, 480: 993, 993, 485: 993, 993, 993, 993, 491: 993, 494: 993}, // 3285 - {1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 463: 1248, 1248, 1248, 1248, 468: 1248, 1248, 1248, 1248, 474: 1248, 1248, 1248, 479: 1248, 1248, 482: 1248, 1248, 1248, 1248, 1248, 490: 1248, 1248, 1248, 1248, 495: 1248, 497: 1248, 1248, 1248, 1248, 502: 1248, 510: 1248, 512: 1248, 533: 1248, 536: 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 571: 1248, 642: 5751, 645: 1248, 1248}, - {1825, 1825, 7: 1825, 57: 1825, 461: 1825, 463: 1825, 469: 1825, 471: 1825, 479: 1825, 1825, 482: 1825, 1825, 1825, 486: 1825, 490: 1825, 1825, 1825, 1825, 502: 1825}, - {821, 821, 7: 5749, 57: 821, 461: 821, 463: 821, 469: 821, 471: 821, 479: 821, 821, 482: 821, 821, 821, 486: 821, 490: 821, 821, 821, 821, 502: 821}, - {991, 991, 57: 991, 461: 991, 463: 991, 469: 991, 471: 991, 479: 991, 991, 482: 991, 991, 991, 486: 991, 490: 991, 991, 991, 991, 502: 991}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 512: 5744, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 5745, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5743, 1030: 5750}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3319, 2691, 2692, 2690, 911: 5762, 1144: 5761, 1324: 5760}, + {966, 966, 7: 5765, 47: 966, 464: 966, 466: 966, 472: 966, 966, 480: 966, 966, 485: 966, 966, 966, 966, 491: 966, 494: 966}, + {965, 965, 7: 965, 47: 965, 464: 965, 466: 965, 472: 965, 965, 480: 965, 965, 485: 965, 965, 965, 965, 491: 965, 494: 965}, + {470: 5763}, + {465: 3320, 1146: 5764}, // 3290 - {1824, 1824, 7: 1824, 57: 1824, 461: 1824, 463: 1824, 469: 1824, 471: 1824, 479: 1824, 1824, 482: 1824, 1824, 1824, 486: 1824, 490: 1824, 1824, 1824, 1824, 502: 1824}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 5752, 653: 5753, 2676, 2677, 2675}, - {1834, 1834, 7: 1834, 57: 1834, 461: 1834, 463: 1834, 469: 1834, 471: 1834, 479: 1834, 1834, 482: 1834, 1834, 1834, 486: 1834, 490: 1834, 1834, 1834, 1834, 502: 1834}, - {1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 3889, 1247, 1247, 1247, 1247, 468: 1247, 1247, 1247, 1247, 474: 1247, 1247, 1247, 479: 1247, 1247, 482: 1247, 1247, 1247, 1247, 1247, 490: 1247, 1247, 1247, 1247, 495: 1247, 497: 1247, 1247, 1247, 1247, 502: 1247, 510: 1247, 512: 1247, 533: 1247, 536: 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 571: 1247, 642: 5754, 645: 1247, 1247}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 5755, 653: 3685, 2676, 2677, 2675}, + {963, 963, 7: 963, 47: 963, 464: 963, 466: 963, 472: 963, 963, 480: 963, 963, 485: 963, 963, 963, 963, 491: 963, 494: 963}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3319, 2691, 2692, 2690, 911: 5762, 1144: 5766}, + {964, 964, 7: 964, 47: 964, 464: 964, 466: 964, 472: 964, 964, 480: 964, 964, 485: 964, 964, 964, 964, 491: 964, 494: 964}, + {1828, 1828, 47: 1828, 464: 1828, 466: 1828, 472: 1828, 1828, 480: 1828, 1828, 485: 1828, 1828, 1828, 1828, 491: 1828, 494: 1828, 497: 3265, 501: 3263, 3264, 3262, 3260, 507: 1828, 725: 3261, 3259}, + {994, 994, 47: 994, 464: 994, 466: 994, 472: 994, 994, 480: 994, 994, 485: 994, 994, 994, 994, 491: 994, 494: 994, 505: 994}, // 3295 - {1833, 1833, 7: 1833, 57: 1833, 461: 1833, 463: 1833, 469: 1833, 471: 1833, 479: 1833, 1833, 482: 1833, 1833, 1833, 486: 1833, 490: 1833, 1833, 1833, 1833, 502: 1833}, - {1832, 1832, 7: 1832, 57: 1832, 461: 1832, 463: 1832, 469: 1832, 471: 1832, 479: 1832, 1832, 482: 1832, 1832, 1832, 486: 1832, 490: 1832, 1832, 1832, 1832, 502: 1832}, - {1830, 1830, 7: 1830, 57: 1830, 461: 1830, 463: 1830, 469: 1830, 471: 1830, 479: 1830, 1830, 482: 1830, 1830, 1830, 486: 1830, 490: 1830, 1830, 1830, 1830, 502: 1830}, - {1829, 1829, 7: 1829, 57: 1829, 461: 1829, 463: 1829, 469: 1829, 471: 1829, 479: 1829, 1829, 482: 1829, 1829, 1829, 486: 1829, 490: 1829, 1829, 1829, 1829, 502: 1829}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5762, 653: 5761, 2676, 2677, 2675}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 515: 5785, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 5786, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5784, 1034: 5787, 1196: 5788, 1268: 5789}, + {2: 843, 843, 843, 843, 843, 8: 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 48: 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 465: 843, 467: 843, 843, 843, 471: 843, 475: 843, 843, 843, 843, 843, 484: 843, 493: 843, 498: 843, 843, 843, 506: 843, 515: 843, 536: 843, 558: 843, 843, 843, 843, 563: 843, 843, 566: 843, 843, 843, 843, 843, 843, 843, 843, 577: 843, 843, 843, 843, 843, 843, 843, 843, 843, 587: 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 617: 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 843, 639: 843, 642: 843, 736: 843, 843, 739: 843, 843, 843, 753: 843, 759: 843, 843, 843}, + {2: 842, 842, 842, 842, 842, 8: 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 48: 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 465: 842, 467: 842, 842, 842, 471: 842, 475: 842, 842, 842, 842, 842, 484: 842, 493: 842, 498: 842, 842, 842, 506: 842, 515: 842, 536: 842, 558: 842, 842, 842, 842, 563: 842, 842, 566: 842, 842, 842, 842, 842, 842, 842, 842, 577: 842, 842, 842, 842, 842, 842, 842, 842, 842, 587: 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 617: 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 842, 639: 842, 642: 842, 736: 842, 842, 739: 842, 842, 842, 753: 842, 759: 842, 842, 842}, + {2: 841, 841, 841, 841, 841, 8: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 48: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 465: 841, 467: 841, 841, 841, 471: 841, 475: 841, 841, 841, 841, 841, 484: 841, 493: 841, 498: 841, 841, 841, 506: 841, 515: 841, 536: 841, 558: 841, 841, 841, 841, 563: 841, 841, 566: 841, 841, 841, 841, 841, 841, 841, 841, 577: 841, 841, 841, 841, 841, 841, 841, 841, 841, 587: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 617: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 639: 841, 642: 841, 736: 841, 841, 739: 841, 841, 841, 753: 841, 759: 841, 841, 841}, + {2: 840, 840, 840, 840, 840, 8: 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 48: 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 465: 840, 467: 840, 840, 840, 471: 840, 475: 840, 840, 840, 840, 840, 484: 840, 493: 840, 498: 840, 840, 840, 506: 840, 515: 840, 536: 840, 558: 840, 840, 840, 840, 563: 840, 840, 566: 840, 840, 840, 840, 840, 840, 840, 840, 577: 840, 840, 840, 840, 840, 840, 840, 840, 840, 587: 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 617: 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 840, 639: 840, 642: 840, 736: 840, 840, 739: 840, 840, 840, 753: 840, 759: 840, 840, 840}, // 3300 - {1827, 1827, 7: 1827, 57: 1827, 461: 1827, 463: 1827, 469: 1827, 471: 1827, 479: 1827, 1827, 482: 1827, 1827, 1827, 486: 1827, 490: 1827, 1827, 1827, 1827, 502: 1827}, - {1828, 1828, 7: 1828, 57: 1828, 461: 1828, 463: 1828, 469: 1828, 471: 1828, 479: 1828, 1828, 482: 1828, 1828, 1828, 486: 1828, 490: 1828, 1828, 1828, 1828, 502: 1828}, - {1826, 1826, 7: 1826, 57: 1826, 461: 1826, 463: 1826, 469: 1826, 471: 1826, 479: 1826, 1826, 482: 1826, 1826, 1826, 486: 1826, 490: 1826, 1826, 1826, 1826, 502: 1826}, - {992, 992}, - {1002, 1002}, + {2: 839, 839, 839, 839, 839, 8: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 48: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 465: 839, 467: 839, 839, 839, 471: 839, 475: 839, 839, 839, 839, 839, 484: 839, 493: 839, 498: 839, 839, 839, 506: 839, 515: 839, 536: 839, 558: 839, 839, 839, 839, 563: 839, 839, 566: 839, 839, 839, 839, 839, 839, 839, 839, 577: 839, 839, 839, 839, 839, 839, 839, 839, 839, 587: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 617: 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 639: 839, 642: 839, 736: 839, 839, 739: 839, 839, 839, 753: 839, 759: 839, 839, 839}, + {2: 838, 838, 838, 838, 838, 8: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 48: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 465: 838, 467: 838, 838, 838, 471: 838, 475: 838, 838, 838, 838, 838, 484: 838, 493: 838, 498: 838, 838, 838, 506: 838, 515: 838, 536: 838, 558: 838, 838, 838, 838, 563: 838, 838, 566: 838, 838, 838, 838, 838, 838, 838, 838, 577: 838, 838, 838, 838, 838, 838, 838, 838, 838, 587: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 617: 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 838, 639: 838, 642: 838, 736: 838, 838, 739: 838, 838, 838, 753: 838, 759: 838, 838, 838}, + {2: 837, 837, 837, 837, 837, 8: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 48: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 465: 837, 467: 837, 837, 837, 471: 837, 475: 837, 837, 837, 837, 837, 484: 837, 493: 837, 498: 837, 837, 837, 506: 837, 515: 837, 536: 837, 558: 837, 837, 837, 837, 563: 837, 837, 566: 837, 837, 837, 837, 837, 837, 837, 837, 577: 837, 837, 837, 837, 837, 837, 837, 837, 837, 587: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 617: 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 639: 837, 642: 837, 736: 837, 837, 739: 837, 837, 837, 753: 837, 759: 837, 837, 837}, + {2: 836, 836, 836, 836, 836, 8: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 48: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 465: 836, 467: 836, 836, 836, 471: 836, 475: 836, 836, 836, 836, 836, 484: 836, 493: 836, 498: 836, 836, 836, 506: 836, 515: 836, 536: 836, 558: 836, 836, 836, 836, 563: 836, 836, 566: 836, 836, 836, 836, 836, 836, 836, 836, 577: 836, 836, 836, 836, 836, 836, 836, 836, 836, 587: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 617: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 639: 836, 642: 836, 736: 836, 836, 739: 836, 836, 836, 753: 836, 759: 836, 836, 836}, + {2: 835, 835, 835, 835, 835, 8: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 48: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 465: 835, 467: 835, 835, 835, 471: 835, 475: 835, 835, 835, 835, 835, 484: 835, 493: 835, 498: 835, 835, 835, 506: 835, 515: 835, 536: 835, 558: 835, 835, 835, 835, 563: 835, 835, 566: 835, 835, 835, 835, 835, 835, 835, 835, 577: 835, 835, 835, 835, 835, 835, 835, 835, 835, 587: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 617: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 639: 835, 642: 835, 736: 835, 835, 739: 835, 835, 835, 753: 835, 759: 835, 835, 835}, // 3305 - {81: 5770, 223: 5769}, - {996, 996}, - {850: 5768}, - {995, 995}, - {998, 998, 81: 5775}, + {2: 833, 833, 833, 833, 833, 8: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 48: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 5775, 5781, 5782, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 465: 833, 467: 833, 833, 833, 471: 833, 475: 833, 833, 833, 833, 833, 484: 833, 493: 833, 498: 833, 833, 833, 506: 5778, 515: 833, 536: 833, 558: 833, 833, 833, 833, 563: 833, 833, 566: 833, 833, 833, 833, 833, 833, 833, 833, 577: 833, 833, 833, 833, 833, 833, 833, 833, 833, 587: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 617: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 639: 833, 642: 3465, 736: 3463, 3464, 739: 5229, 5228, 5227, 753: 5224, 759: 5774, 5777, 5773, 773: 5696, 776: 5771, 826: 5772, 855: 5770, 1107: 5783, 5776}, + {2: 831, 831, 831, 831, 831, 8: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 48: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 465: 831, 467: 831, 831, 831, 471: 831, 475: 831, 831, 831, 831, 831, 484: 831, 493: 831, 498: 831, 831, 831, 506: 831, 515: 831, 536: 831, 558: 831, 831, 831, 831, 563: 831, 831, 566: 831, 831, 831, 831, 831, 831, 831, 831, 577: 831, 831, 831, 831, 831, 831, 831, 831, 831, 587: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 617: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 639: 831, 642: 831, 736: 831, 831, 739: 831, 831, 831, 753: 831, 759: 831, 831, 831}, + {2: 827, 827, 827, 827, 827, 8: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 48: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 465: 827, 467: 827, 827, 827, 471: 827, 475: 827, 827, 827, 827, 827, 484: 827, 493: 827, 498: 827, 827, 827, 506: 827, 515: 827, 536: 827, 558: 827, 827, 827, 827, 563: 827, 827, 566: 827, 827, 827, 827, 827, 827, 827, 827, 577: 827, 827, 827, 827, 827, 827, 827, 827, 827, 587: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 617: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 639: 827, 642: 827, 736: 827, 827, 739: 827, 827, 827, 753: 827, 759: 827, 827, 827}, + {2: 826, 826, 826, 826, 826, 8: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 48: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 465: 826, 467: 826, 826, 826, 471: 826, 475: 826, 826, 826, 826, 826, 484: 826, 493: 826, 498: 826, 826, 826, 506: 826, 515: 826, 536: 826, 558: 826, 826, 826, 826, 563: 826, 826, 566: 826, 826, 826, 826, 826, 826, 826, 826, 577: 826, 826, 826, 826, 826, 826, 826, 826, 826, 587: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 617: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 639: 826, 642: 826, 736: 826, 826, 739: 826, 826, 826, 753: 826, 759: 826, 826, 826}, + {2: 832, 832, 832, 832, 832, 8: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 48: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 465: 832, 467: 832, 832, 832, 471: 832, 475: 832, 832, 832, 832, 832, 484: 832, 493: 832, 498: 832, 832, 832, 506: 832, 515: 832, 536: 832, 558: 832, 832, 832, 832, 563: 832, 832, 566: 832, 832, 832, 832, 832, 832, 832, 832, 577: 832, 832, 832, 832, 832, 832, 832, 832, 832, 587: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 617: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 639: 832, 642: 832, 736: 832, 832, 739: 832, 832, 832, 753: 832, 759: 832, 832, 832}, // 3310 - {223: 5771}, - {997, 997, 81: 5773, 850: 5772}, - {1000, 1000}, - {850: 5774}, - {999, 999}, + {1838, 1838, 2930, 2776, 2812, 2932, 2703, 1838, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1838, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 1838, 466: 1838, 468: 5801, 470: 5800, 472: 1838, 1838, 480: 1838, 1838, 485: 1838, 1838, 1838, 1838, 490: 1838, 1838, 1838, 494: 1838, 497: 3265, 501: 3263, 3264, 3262, 3260, 1838, 654: 5799, 2691, 2692, 2690, 725: 3261, 3259, 1193: 5798, 5797}, + {1842, 1842, 7: 1842, 47: 1842, 464: 1842, 466: 1842, 472: 1842, 1842, 480: 1842, 1842, 485: 1842, 1842, 1842, 1842, 490: 1842, 1842, 1842, 494: 1842, 505: 1842}, + {1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 466: 1252, 1252, 1252, 1252, 1252, 472: 1252, 1252, 1252, 477: 1252, 1252, 1252, 1252, 1252, 485: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 494: 1252, 497: 1252, 501: 1252, 1252, 1252, 1252, 1252, 513: 1252, 515: 1252, 535: 1252, 539: 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 575: 1252, 643: 5792, 646: 1252, 1252}, + {1832, 1832, 7: 1832, 47: 1832, 464: 1832, 466: 1832, 472: 1832, 1832, 480: 1832, 1832, 485: 1832, 1832, 1832, 1832, 490: 1832, 1832, 1832, 494: 1832, 505: 1832}, + {825, 825, 7: 5790, 47: 825, 464: 825, 466: 825, 472: 825, 825, 480: 825, 825, 485: 825, 825, 825, 825, 490: 825, 825, 825, 494: 825, 505: 825}, // 3315 - {850: 5776}, - {1001, 1001}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5778, 2676, 2677, 2675}, - {1006, 1006}, - {1010, 1010, 471: 5780}, + {995, 995, 47: 995, 464: 995, 466: 995, 472: 995, 995, 480: 995, 995, 485: 995, 995, 995, 995, 490: 995, 995, 995, 494: 995, 505: 995}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 515: 5785, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 5786, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 5784, 1034: 5791}, + {1831, 1831, 7: 1831, 47: 1831, 464: 1831, 466: 1831, 472: 1831, 1831, 480: 1831, 1831, 485: 1831, 1831, 1831, 1831, 490: 1831, 1831, 1831, 494: 1831, 505: 1831}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5793, 654: 5794, 2691, 2692, 2690}, + {1841, 1841, 7: 1841, 47: 1841, 464: 1841, 466: 1841, 472: 1841, 1841, 480: 1841, 1841, 485: 1841, 1841, 1841, 1841, 490: 1841, 1841, 1841, 494: 1841, 505: 1841}, // 3320 - {558: 3252, 700: 5782, 1306: 5781}, - {1009, 1009, 7: 5783}, - {1008, 1008, 7: 1008}, - {558: 3252, 700: 5784}, - {1007, 1007, 7: 1007}, + {1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 3907, 1251, 1251, 1251, 1251, 1251, 472: 1251, 1251, 1251, 477: 1251, 1251, 1251, 1251, 1251, 485: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 494: 1251, 497: 1251, 501: 1251, 1251, 1251, 1251, 1251, 513: 1251, 515: 1251, 535: 1251, 539: 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 575: 1251, 643: 5795, 646: 1251, 1251}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5796, 654: 3703, 2691, 2692, 2690}, + {1840, 1840, 7: 1840, 47: 1840, 464: 1840, 466: 1840, 472: 1840, 1840, 480: 1840, 1840, 485: 1840, 1840, 1840, 1840, 490: 1840, 1840, 1840, 494: 1840, 505: 1840}, + {1839, 1839, 7: 1839, 47: 1839, 464: 1839, 466: 1839, 472: 1839, 1839, 480: 1839, 1839, 485: 1839, 1839, 1839, 1839, 490: 1839, 1839, 1839, 494: 1839, 505: 1839}, + {1837, 1837, 7: 1837, 47: 1837, 464: 1837, 466: 1837, 472: 1837, 1837, 480: 1837, 1837, 485: 1837, 1837, 1837, 1837, 490: 1837, 1837, 1837, 494: 1837, 505: 1837}, // 3325 - {490: 5786}, - {464: 5788, 558: 3252, 700: 5789, 1256: 5787}, - {1013, 1013}, - {1012, 1012}, - {1011, 1011}, + {1836, 1836, 7: 1836, 47: 1836, 464: 1836, 466: 1836, 472: 1836, 1836, 480: 1836, 1836, 485: 1836, 1836, 1836, 1836, 490: 1836, 1836, 1836, 494: 1836, 505: 1836}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5803, 654: 5802, 2691, 2692, 2690}, + {1834, 1834, 7: 1834, 47: 1834, 464: 1834, 466: 1834, 472: 1834, 1834, 480: 1834, 1834, 485: 1834, 1834, 1834, 1834, 490: 1834, 1834, 1834, 494: 1834, 505: 1834}, + {1835, 1835, 7: 1835, 47: 1835, 464: 1835, 466: 1835, 472: 1835, 1835, 480: 1835, 1835, 485: 1835, 1835, 1835, 1835, 490: 1835, 1835, 1835, 494: 1835, 505: 1835}, + {1833, 1833, 7: 1833, 47: 1833, 464: 1833, 466: 1833, 472: 1833, 1833, 480: 1833, 1833, 485: 1833, 1833, 1833, 1833, 490: 1833, 1833, 1833, 494: 1833, 505: 1833}, // 3330 - {2: 1323, 1323, 1323, 1323, 1323, 8: 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 58: 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 484: 5791, 1048: 5792}, - {2: 1322, 1322, 1322, 1322, 1322, 8: 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 58: 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5793}, - {152: 894, 462: 894, 894, 478: 5296, 487: 894, 501: 894, 556: 894, 634: 894, 849: 5794}, - {152: 5802, 462: 5795, 2508, 487: 5803, 501: 5801, 556: 2506, 634: 2502, 699: 5800, 741: 5798, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 5799, 5797, 3779, 962: 5796, 1047: 5804}, + {996, 996}, + {1006, 1006}, + {70: 5811, 223: 5810}, + {1000, 1000}, + {850: 5809}, // 3335 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 2262, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 2509, 2508, 487: 2507, 556: 2506, 634: 2502, 653: 4040, 2676, 2677, 2675, 699: 5667, 733: 4041, 741: 3780, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 3782, 3781, 3779, 798: 4969, 986: 5816}, - {462: 3796, 829: 5813, 960: 5812}, - {1315, 1315, 461: 1315, 471: 1315}, - {1314, 1314, 461: 1314, 469: 787, 471: 1314, 479: 787, 787}, - {1313, 1313, 461: 1313, 471: 1313}, + {999, 999}, + {1002, 1002, 70: 5816}, + {223: 5812}, + {1001, 1001, 70: 5814, 850: 5813}, + {1004, 1004}, // 3340 - {1312, 1312, 461: 1312, 469: 786, 471: 1312, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {1298, 1298, 2912, 2760, 2796, 2914, 2687, 1298, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 1298, 471: 1298, 653: 4040, 2676, 2677, 2675, 733: 5806, 990: 5807, 1171: 5805}, - {462: 1310}, - {462: 1309, 564: 3795, 900: 3794, 961: 3793}, - {1293, 1293, 471: 1293}, + {850: 5815}, + {1003, 1003}, + {850: 5817}, + {1005, 1005}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5819, 2691, 2692, 2690}, // 3345 - {1311, 1311, 7: 5810, 461: 1311, 471: 1311}, - {485: 5808}, - {1297, 1297, 7: 1297, 461: 1297, 471: 1297}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3802, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3798, 788: 5809}, - {1299, 1299, 7: 1299, 461: 1299, 471: 1299}, + {1010, 1010}, + {1014, 1014, 473: 5821}, + {560: 3268, 701: 5823, 1310: 5822}, + {1013, 1013, 7: 5824}, + {1012, 1012, 7: 1012}, // 3350 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 5806, 990: 5811}, - {1296, 1296, 7: 1296, 461: 1296, 471: 1296}, - {1316, 1316, 7: 5814, 461: 1316, 471: 1316}, - {1308, 1308, 7: 1308, 461: 1308, 471: 1308}, - {462: 3796, 829: 5815}, + {560: 3268, 701: 5825}, + {1011, 1011, 7: 1011}, + {490: 5827}, + {468: 5829, 560: 3268, 701: 5830, 1260: 5828}, + {1017, 1017}, // 3355 - {1307, 1307, 7: 1307, 461: 1307, 471: 1307}, - {57: 5817}, - {152: 5802, 462: 2509, 2508, 487: 5803, 556: 2506, 634: 2502, 699: 5822, 741: 5820, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 5821, 5819, 3779, 962: 5818}, - {462: 3796, 829: 5813, 960: 5823}, - {1320, 1320, 461: 1320, 471: 1320}, + {1016, 1016}, + {1015, 1015}, + {2: 1327, 1327, 1327, 1327, 1327, 8: 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 48: 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 487: 5832, 1052: 5833}, + {2: 1326, 1326, 1326, 1326, 1326, 8: 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 48: 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5834}, // 3360 - {1319, 1319, 461: 1319, 469: 787, 471: 1319, 479: 787, 787}, - {1318, 1318, 461: 1318, 471: 1318}, - {1317, 1317, 461: 1317, 469: 786, 471: 1317, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {1321, 1321, 7: 5814, 461: 1321, 471: 1321}, - {2: 1027, 1027, 1027, 1027, 1027, 8: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 58: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 477: 1027, 484: 1027, 738: 5234, 5233, 5232, 827: 5235, 874: 5825}, + {153: 898, 465: 898, 898, 483: 5291, 493: 898, 496: 898, 562: 898, 637: 898, 849: 5835}, + {153: 5843, 465: 5836, 2522, 493: 5844, 496: 5842, 562: 2520, 637: 2516, 700: 5841, 742: 5839, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5840, 5838, 3797, 965: 5837, 1051: 5845}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 2278, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 2523, 2522, 493: 2521, 562: 2520, 637: 2516, 654: 4058, 2691, 2692, 2690, 700: 5708, 735: 4059, 742: 3798, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 3800, 3799, 3797, 797: 4964, 990: 5857}, + {465: 3814, 828: 5854, 963: 5853}, + {1319, 1319, 464: 1319, 473: 1319}, // 3365 - {2: 1813, 1813, 1813, 1813, 1813, 8: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 58: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 477: 4087, 484: 1813, 844: 5826}, - {2: 1323, 1323, 1323, 1323, 1323, 8: 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 58: 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 484: 5791, 1048: 5827}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5828}, - {152: 894, 462: 894, 894, 478: 5296, 487: 894, 501: 894, 556: 894, 634: 894, 849: 5829}, - {152: 5802, 462: 5795, 2508, 487: 5803, 501: 5801, 556: 2506, 634: 2502, 699: 5800, 741: 5798, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 5799, 5797, 3779, 962: 5796, 1047: 5830}, + {1318, 1318, 464: 1318, 472: 791, 1318, 480: 791, 791}, + {1317, 1317, 464: 1317, 473: 1317}, + {1316, 1316, 464: 1316, 472: 790, 1316, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {1302, 1302, 2930, 2776, 2812, 2932, 2703, 1302, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 1302, 473: 1302, 654: 4058, 2691, 2692, 2690, 735: 5847, 994: 5848, 1176: 5846}, + {465: 1314}, // 3370 - {1295, 1295, 461: 5832, 471: 1295, 1235: 5831}, - {1324, 1324, 471: 1324}, - {194: 5833}, - {566: 5834}, - {644: 5835}, + {465: 1313, 568: 3813, 900: 3812, 964: 3811}, + {1297, 1297, 473: 1297}, + {1315, 1315, 7: 5851, 464: 1315, 473: 1315}, + {489: 5849}, + {1301, 1301, 7: 1301, 464: 1301, 473: 1301}, // 3375 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 5350, 879: 5351, 913: 5836}, - {1294, 1294, 7: 5353, 471: 1294}, - {1328, 1328, 462: 5845, 642: 1789}, - {1329, 1329}, - {642: 5840}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3820, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3816, 787: 5850}, + {1303, 1303, 7: 1303, 464: 1303, 473: 1303}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 5847, 994: 5852}, + {1300, 1300, 7: 1300, 464: 1300, 473: 1300}, + {1320, 1320, 7: 5855, 464: 1320, 473: 1320}, // 3380 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5841, 2676, 2677, 2675}, - {1327, 1327, 462: 5842}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 5843}, - {57: 5844}, - {1325, 1325}, + {1312, 1312, 7: 1312, 464: 1312, 473: 1312}, + {465: 3814, 828: 5856}, + {1311, 1311, 7: 1311, 464: 1311, 473: 1311}, + {47: 5858}, + {153: 5843, 465: 2523, 2522, 493: 5844, 562: 2520, 637: 2516, 700: 5863, 742: 5861, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5862, 5860, 3797, 965: 5859}, // 3385 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 1876, 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 3489, 766: 3651, 815: 5846}, - {57: 5847}, - {1326, 1326}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5999, 2676, 2677, 2675}, - {581, 581, 492: 5996, 510: 5995, 1271: 5994}, + {465: 3814, 828: 5854, 963: 5864}, + {1324, 1324, 464: 1324, 473: 1324}, + {1323, 1323, 464: 1323, 472: 791, 1323, 480: 791, 791}, + {1322, 1322, 464: 1322, 473: 1322}, + {1321, 1321, 464: 1321, 472: 790, 1321, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, // 3390 - {16: 5982, 99: 5979, 132: 5984, 162: 5983, 186: 5981, 556: 5978, 572: 5980}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 5967, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5968}, - {653, 653, 482: 5962}, - {125: 5961}, - {98: 3843, 107: 3842, 110: 5956, 207: 5955, 823: 5957}, + {1325, 1325, 7: 5855, 464: 1325, 473: 1325}, + {2: 1031, 1031, 1031, 1031, 1031, 8: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 48: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 482: 1031, 487: 1031, 739: 5229, 5228, 5227, 826: 5230, 875: 5866}, + {2: 1820, 1820, 1820, 1820, 1820, 8: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 48: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 482: 4105, 487: 1820, 844: 5867}, + {2: 1327, 1327, 1327, 1327, 1327, 8: 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 48: 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 487: 5832, 1052: 5868}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5869}, // 3395 - {649, 649}, - {641, 641, 177: 5937, 219: 5938, 229: 5939, 232: 5936, 251: 5941, 261: 5940, 275: 5943, 280: 5942, 482: 641, 641, 491: 641, 641: 5944, 1110: 5935, 1274: 5934, 5933}, - {647, 647}, - {646, 646}, - {583, 583, 254: 5924, 482: 5923, 492: 583, 510: 583}, + {153: 898, 465: 898, 898, 483: 5291, 493: 898, 496: 898, 562: 898, 637: 898, 849: 5870}, + {153: 5843, 465: 5836, 2522, 493: 5844, 496: 5842, 562: 2520, 637: 2516, 700: 5841, 742: 5839, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5840, 5838, 3797, 965: 5837, 1051: 5871}, + {1299, 1299, 464: 5873, 473: 1299, 1239: 5872}, + {1328, 1328, 473: 1328}, + {195: 5874}, // 3400 - {490: 624, 533: 624}, - {490: 623, 533: 623}, - {490: 622, 533: 622}, - {619, 619, 492: 619, 510: 619}, - {618, 618, 492: 618, 510: 618}, + {565: 5875}, + {645: 5876}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 5345, 880: 5346, 913: 5877}, + {1298, 1298, 7: 5348, 473: 1298}, + {1332, 1332, 465: 5886, 643: 1796}, // 3405 - {617, 617, 492: 617, 510: 617}, - {616, 616, 492: 616, 510: 616}, - {110: 5921}, - {490: 5897, 533: 5898, 795: 5916}, - {98: 571, 107: 571, 199: 5895, 1072: 5910}, + {1333, 1333}, + {643: 5881}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5882, 2691, 2692, 2690}, + {1331, 1331, 465: 5883}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 5884}, // 3410 - {608, 608, 492: 608, 510: 608}, - {607, 607, 492: 607, 510: 607}, - {125: 5908, 138: 5909, 191: 5907}, - {603, 603, 492: 603, 510: 603}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5906}, + {47: 5885}, + {1329, 1329}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 1883, 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 3507, 766: 3669, 814: 5887}, + {47: 5888}, + {1330, 1330}, // 3415 - {125: 5905}, - {125: 5904}, - {125: 5903}, - {125: 5902}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5899}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6042, 2691, 2692, 2690}, + {584, 584, 492: 6039, 513: 6038, 1275: 6037}, + {16: 6025, 99: 6022, 132: 6027, 163: 6026, 187: 6024, 562: 6021, 577: 6023}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 6010, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6011}, + {657, 657, 485: 6005}, // 3420 - {596, 596, 492: 596, 510: 596}, - {595, 595, 492: 595, 510: 595}, - {594, 594, 492: 594, 510: 594}, - {593, 593, 492: 593, 510: 593}, - {592, 592, 492: 592, 510: 592}, + {123: 6004}, + {98: 3861, 107: 3860, 110: 5999, 207: 5998, 822: 6000}, + {653, 653}, + {645, 645, 178: 5980, 219: 5981, 229: 5982, 232: 5979, 251: 5984, 261: 5983, 276: 5986, 281: 5985, 485: 645, 645, 491: 645, 642: 5987, 1114: 5978, 1278: 5977, 5976}, + {651, 651}, // 3425 - {591, 591, 492: 591, 510: 591}, - {590, 590, 492: 590, 510: 590}, - {589, 589, 492: 589, 510: 589}, - {588, 588, 492: 588, 510: 588}, - {125: 5896}, + {650, 650}, + {586, 586, 254: 5967, 485: 5966, 492: 586, 513: 586}, + {490: 628, 535: 628}, + {490: 627, 535: 627}, + {490: 626, 535: 626}, // 3430 - {586, 586, 492: 586, 510: 586}, - {585, 585, 492: 585, 510: 585}, - {584, 584, 492: 584, 510: 584}, - {125: 577, 138: 577, 191: 577}, - {125: 576, 138: 576, 154: 576, 191: 576}, + {623, 623, 492: 623, 513: 623}, + {622, 622, 492: 622, 513: 622}, + {621, 621, 492: 621, 513: 621}, + {620, 620, 492: 620, 513: 620}, + {110: 5964}, // 3435 - {98: 570, 107: 570, 110: 570, 207: 570}, - {587, 587, 492: 587, 510: 587}, - {2: 621, 621, 621, 621, 621, 8: 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 58: 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621}, - {2: 620, 620, 620, 620, 620, 8: 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 58: 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620}, - {597, 597, 492: 597, 510: 597}, + {490: 5939, 535: 5940, 794: 5959}, + {98: 574, 107: 574, 200: 5937, 1075: 5953}, + {612, 612, 492: 612, 513: 612}, + {611, 611, 492: 611, 513: 611}, + {123: 5951, 138: 5952, 192: 5950}, // 3440 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 5901}, - {568, 568, 492: 568, 510: 568}, - {598, 598, 492: 598, 510: 598}, - {599, 599, 492: 599, 510: 599}, - {600, 600, 492: 600, 510: 600}, + {607, 607, 492: 607, 513: 607}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 5949}, + {123: 5948}, + {123: 5947}, + {123: 5946}, // 3445 - {601, 601, 492: 601, 510: 601}, - {602, 602, 492: 602, 510: 602}, - {606, 606, 492: 606, 510: 606}, - {605, 605, 492: 605, 510: 605}, - {604, 604, 492: 604, 510: 604}, + {123: 5945}, + {123: 5944}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 5941}, + {599, 599, 492: 599, 513: 599}, + {598, 598, 492: 598, 513: 598}, // 3450 - {98: 3843, 107: 3842, 823: 5911}, - {490: 5897, 533: 5898, 795: 5913, 1112: 5912}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5915}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5914}, - {567, 567, 490: 567, 492: 567, 510: 567, 533: 567}, + {597, 597, 492: 597, 513: 597}, + {596, 596, 492: 596, 513: 596}, + {595, 595, 492: 595, 513: 595}, + {594, 594, 492: 594, 513: 594}, + {593, 593, 492: 593, 513: 593}, // 3455 - {609, 609, 492: 609, 510: 609}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5917, 2676, 2677, 2675, 727: 5918}, - {1025, 1025, 490: 5897, 492: 1025, 510: 1025, 533: 5898, 642: 3825, 795: 5919}, - {612, 612, 492: 612, 510: 612}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5920, 2676, 2677, 2675}, + {592, 592, 492: 592, 513: 592}, + {591, 591, 492: 591, 513: 591}, + {123: 5938}, + {589, 589, 492: 589, 513: 589}, + {588, 588, 492: 588, 513: 588}, // 3460 - {611, 611, 492: 611, 510: 611}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5922}, - {614, 614, 492: 614, 510: 614}, - {556: 5928, 572: 5925, 839: 5927, 1272: 5926}, - {582, 582, 492: 582, 510: 582}, + {587, 587, 492: 587, 513: 587}, + {123: 580, 138: 580, 192: 580}, + {123: 579, 138: 579, 155: 579, 192: 579}, + {98: 573, 107: 573, 110: 573, 207: 573}, + {590, 590, 492: 590, 513: 590}, // 3465 - {2: 2020, 2020, 2020, 2020, 2020, 8: 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 58: 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 467: 2020, 470: 2020, 489: 2020, 512: 2020, 555: 2020, 637: 2020}, - {645, 645}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 5932}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5929}, - {643, 643, 478: 5930}, + {2: 625, 625, 625, 625, 625, 8: 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 48: 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625}, + {2: 624, 624, 624, 624, 624, 8: 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 48: 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624}, + {600, 600, 492: 600, 513: 600}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 5943}, + {571, 571, 492: 571, 513: 571}, // 3470 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5931, 2676, 2677, 2675}, - {642, 642}, - {644, 644}, - {628, 628, 482: 5951, 628, 491: 628, 1273: 5950}, - {640, 640, 7: 5948, 482: 640, 640, 491: 640}, + {601, 601, 492: 601, 513: 601}, + {602, 602, 492: 602, 513: 602}, + {603, 603, 492: 603, 513: 603}, + {604, 604, 492: 604, 513: 604}, + {605, 605, 492: 605, 513: 605}, // 3475 - {639, 639, 7: 639, 482: 639, 639, 491: 639}, - {637, 637, 7: 637, 482: 637, 637, 491: 637}, - {636, 636, 7: 636, 482: 636, 636, 491: 636}, - {336: 5947}, - {377: 5946}, + {606, 606, 492: 606, 513: 606}, + {610, 610, 492: 610, 513: 610}, + {609, 609, 492: 609, 513: 609}, + {608, 608, 492: 608, 513: 608}, + {98: 3861, 107: 3860, 822: 5954}, // 3480 - {325: 5945}, - {632, 632, 7: 632, 482: 632, 632, 491: 632}, - {631, 631, 7: 631, 482: 631, 631, 491: 631}, - {630, 630, 7: 630, 482: 630, 630, 491: 630}, - {629, 629, 7: 629, 482: 629, 629, 491: 629}, + {490: 5939, 535: 5940, 794: 5956, 1116: 5955}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 5958}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5957}, + {570, 570, 490: 570, 492: 570, 513: 570, 535: 570}, + {613, 613, 492: 613, 513: 613}, // 3485 - {633, 633, 7: 633, 482: 633, 633, 491: 633}, - {634, 634, 7: 634, 482: 634, 634, 491: 634}, - {635, 635, 7: 635, 482: 635, 635, 491: 635}, - {177: 5937, 219: 5938, 229: 5939, 232: 5936, 251: 5941, 261: 5940, 275: 5943, 280: 5942, 641: 5944, 1110: 5949}, - {638, 638, 7: 638, 482: 638, 638, 491: 638}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5960, 2691, 2692, 2690, 728: 5961}, + {1029, 1029, 490: 5939, 492: 1029, 513: 1029, 535: 5940, 643: 3843, 794: 5962}, + {616, 616, 492: 616, 513: 616}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5963, 2691, 2692, 2690}, + {615, 615, 492: 615, 513: 615}, // 3490 - {841, 841, 483: 2642, 491: 2643, 757: 2644, 818: 5954}, - {143: 5952}, - {496: 2650, 725: 3950, 751: 5953}, - {627, 627, 483: 627, 491: 627}, - {648, 648}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 5965}, + {618, 618, 492: 618, 513: 618}, + {562: 5971, 577: 5968, 839: 5970, 1276: 5969}, + {585, 585, 492: 585, 513: 585}, + {2: 2027, 2027, 2027, 2027, 2027, 8: 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 48: 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 471: 2027, 474: 2027, 496: 2027, 498: 2027, 515: 2027, 558: 2027, 638: 2027}, // 3495 - {650, 650}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5960}, - {490: 5897, 533: 5898, 795: 5913, 1112: 5958}, - {569, 569, 490: 5897, 492: 569, 510: 569, 533: 5898, 795: 5900, 831: 5959}, - {610, 610, 492: 610, 510: 610}, + {649, 649}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 5975}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 5972}, + {647, 647, 483: 5973}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5974, 2691, 2692, 2690}, // 3500 - {615, 615, 492: 615, 510: 615}, - {651, 651}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5963}, - {626, 626, 471: 5965, 1307: 5964}, - {652, 652}, + {646, 646}, + {648, 648}, + {632, 632, 485: 5994, 632, 491: 632, 1277: 5993}, + {644, 644, 7: 5991, 485: 644, 644, 491: 644}, + {643, 643, 7: 643, 485: 643, 643, 491: 643}, // 3505 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 5966}, - {625, 625, 7: 5562}, - {569, 569, 15: 1693, 157: 1693, 478: 1693, 490: 5897, 492: 569, 510: 569, 533: 5898, 638: 1693, 642: 1693, 795: 5900, 831: 5977}, - {15: 894, 157: 5970, 478: 5296, 638: 894, 849: 5969}, - {15: 5971, 638: 5972}, + {641, 641, 7: 641, 485: 641, 641, 491: 641}, + {640, 640, 7: 640, 485: 640, 640, 491: 640}, + {341: 5990}, + {381: 5989}, + {330: 5988}, // 3510 - {655, 655}, - {237, 237, 492: 2636, 780: 2637, 5976}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5973, 2676, 2677, 2675}, - {15: 5974}, - {237, 237, 492: 2636, 780: 2637, 5975}, + {636, 636, 7: 636, 485: 636, 636, 491: 636}, + {635, 635, 7: 635, 485: 635, 635, 491: 635}, + {634, 634, 7: 634, 485: 634, 634, 491: 634}, + {633, 633, 7: 633, 485: 633, 633, 491: 633}, + {637, 637, 7: 637, 485: 637, 637, 491: 637}, // 3515 - {654, 654}, - {656, 656}, - {613, 613, 492: 613, 510: 613}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5993}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5992}, + {638, 638, 7: 638, 485: 638, 638, 491: 638}, + {639, 639, 7: 639, 485: 639, 639, 491: 639}, + {178: 5980, 219: 5981, 229: 5982, 232: 5979, 251: 5984, 261: 5983, 276: 5986, 281: 5985, 642: 5987, 1114: 5992}, + {642, 642, 7: 642, 485: 642, 642, 491: 642}, + {845, 845, 486: 2657, 491: 2658, 758: 2659, 817: 5997}, // 3520 - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 5990}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 5989}, - {158: 5987}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5986}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5985, 2676, 2677, 2675}, + {143: 5995}, + {500: 2665, 724: 3968, 755: 5996}, + {631, 631, 486: 631, 491: 631}, + {652, 652}, + {654, 654}, // 3525 - {657, 657}, - {658, 658}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4877, 2676, 2677, 2675, 873: 5988}, - {659, 659}, - {660, 660}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 6003}, + {490: 5939, 535: 5940, 794: 5956, 1116: 6001}, + {572, 572, 490: 5939, 492: 572, 513: 572, 535: 5940, 794: 5942, 830: 6002}, + {614, 614, 492: 614, 513: 614}, + {619, 619, 492: 619, 513: 619}, // 3530 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 5991}, - {661, 661}, - {662, 662}, - {663, 663}, - {664, 664}, + {655, 655}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6006}, + {630, 630, 473: 6008, 1311: 6007}, + {656, 656}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 6009}, // 3535 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 467: 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 3252, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 5998, 3155, 3238, 3154, 3151}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 2701, 2753, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 2782, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 2680, 2696, 2839, 2930, 2787, 2714, 2731, 2858, 2941, 2774, 2743, 2852, 2853, 2848, 2808, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 2789, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 2793, 2674, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 2712, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 2778, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 2779, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 2847, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 2665, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 2795, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 2737, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 2666, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 2690, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3064, 3065, 3115, 3114, 2967, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 2829, 2846, 2968, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3094, 3095, 3105, 3090, 3091, 3092, 3123, 2790, 462: 3162, 464: 3142, 3160, 2669, 3170, 472: 3175, 3179, 3158, 3159, 3197, 481: 3133, 487: 3171, 489: 3195, 494: 3178, 496: 3137, 532: 3166, 555: 3173, 557: 3196, 2667, 3180, 3132, 3134, 3136, 3135, 3163, 3140, 567: 3153, 3165, 3141, 3174, 572: 3172, 3164, 575: 3169, 577: 3240, 3176, 3185, 3186, 3187, 3139, 3156, 3157, 3210, 3213, 3214, 3215, 3216, 3217, 3167, 3218, 3193, 3198, 3208, 3209, 3202, 3219, 3220, 3221, 3203, 3223, 3224, 3211, 3204, 3222, 3199, 3207, 3205, 3191, 3225, 3226, 3168, 3230, 3181, 3182, 3184, 3229, 3235, 3234, 3236, 3233, 3237, 3232, 3231, 3228, 3177, 3227, 3183, 3188, 3189, 639: 2670, 653: 3146, 2676, 2677, 2675, 699: 3161, 3239, 3147, 3152, 3138, 3212, 3150, 3148, 3149, 3190, 3201, 3200, 3194, 3192, 3206, 3145, 3155, 3238, 3154, 3151, 2673, 2672, 2671, 5997}, - {579, 579, 495: 3249, 497: 3247, 3248, 3246, 3244, 723: 3245, 3243}, - {580, 580, 470: 3253, 571: 3254}, - {1912, 1912, 200: 6001, 556: 1912, 1238: 6000}, + {629, 629, 7: 5558}, + {572, 572, 86: 1699, 158: 1699, 483: 1699, 490: 5939, 492: 572, 513: 572, 535: 5940, 640: 1699, 643: 1699, 794: 5942, 830: 6020}, + {86: 898, 158: 6013, 483: 5291, 640: 898, 849: 6012}, + {86: 6014, 640: 6015}, + {659, 659}, // 3540 - {545, 545, 556: 6003, 954: 6002}, - {1911, 1911, 556: 1911}, - {1917, 1917}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6004}, - {544, 544, 7: 3823}, + {239, 239, 492: 2651, 779: 2652, 6019}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6016, 2691, 2692, 2690}, + {86: 6017}, + {239, 239, 492: 2651, 779: 2652, 6018}, + {658, 658}, // 3545 - {2: 1914, 1914, 1914, 1914, 1914, 8: 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 58: 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 555: 6007, 1204: 6006}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6010, 2676, 2677, 2675}, - {465: 3986, 3985, 800: 6008}, - {184: 6009}, - {2: 1913, 1913, 1913, 1913, 1913, 8: 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 58: 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913}, + {660, 660}, + {617, 617, 492: 617, 513: 617}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6036}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6035}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6033}, // 3550 - {1920, 1920}, - {2: 1916, 1916, 1916, 1916, 1916, 8: 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 58: 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 555: 6013, 1205: 6012}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6015, 2676, 2677, 2675}, - {184: 6014}, - {2: 1915, 1915, 1915, 1915, 1915, 8: 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 58: 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6032}, + {159: 6030}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6029}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6028, 2691, 2692, 2690}, + {661, 661}, // 3555 - {1921, 1921}, - {496: 2650, 725: 6017}, - {1923, 1923}, - {490: 6027}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 6022, 653: 5227, 2676, 2677, 2675, 805: 6024, 1180: 6023}, + {662, 662}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4894, 2691, 2692, 2690, 874: 6031}, + {663, 663}, + {664, 664}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 6034}, // 3560 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6021}, - {7: 3823, 490: 1970, 640: 1970}, - {490: 1972, 640: 1972}, - {7: 6025, 490: 1971, 640: 1971}, - {7: 1969, 490: 1969, 640: 1969}, + {665, 665}, + {666, 666}, + {667, 667}, + {668, 668}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 3268, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 6041, 3173, 3254, 3172, 3169}, // 3565 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 6026}, - {7: 1968, 490: 1968, 640: 1968}, - {464: 6028}, - {1967, 1967, 27: 1967, 59: 1967, 61: 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 461: 1967, 643: 1967, 886: 6029}, - {1973, 1973, 27: 6056, 59: 6032, 61: 6052, 6045, 6035, 6031, 6039, 6043, 6055, 6038, 6044, 6042, 6040, 6053, 6046, 6034, 6054, 6033, 6036, 6037, 6041, 461: 6047, 643: 6057, 882: 6049, 6048, 6051, 6030, 887: 6050}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 2769, 2717, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 2798, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 2695, 2712, 2857, 2948, 2803, 2730, 2747, 2876, 2959, 2790, 2759, 2870, 2871, 2866, 2824, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 2805, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 2689, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 2809, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 2728, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 2794, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 2795, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 2865, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 2680, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 2811, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 2753, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 2681, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3067, 2807, 3068, 3069, 2706, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3082, 3083, 3133, 3132, 2985, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 2847, 2864, 2986, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3100, 3101, 3102, 2860, 3055, 3112, 3113, 3123, 3108, 3109, 3110, 3141, 2806, 465: 3180, 467: 3178, 3160, 2684, 471: 3188, 475: 3193, 3197, 3176, 3177, 3215, 484: 3151, 493: 3189, 498: 3213, 3196, 3155, 536: 3184, 558: 3191, 3214, 2682, 3198, 563: 3150, 3152, 566: 3154, 3153, 3181, 3158, 3171, 3183, 3159, 3192, 577: 3190, 3182, 3187, 3194, 3203, 3256, 3204, 3205, 3157, 587: 3174, 3175, 3229, 3230, 3231, 3232, 3233, 3185, 3234, 3211, 3216, 3226, 3227, 3220, 3235, 3236, 3237, 3221, 3239, 3240, 3222, 3238, 3217, 3225, 3223, 3209, 3241, 3242, 3186, 617: 3246, 3199, 3200, 3202, 3245, 3251, 3250, 3252, 3249, 3253, 3248, 3247, 3244, 3195, 3243, 3201, 3206, 3207, 639: 2685, 654: 3164, 2691, 2692, 2690, 700: 3179, 3255, 3165, 3170, 3156, 3228, 3168, 3166, 3167, 3208, 3219, 3218, 3212, 3210, 3224, 3163, 3173, 3254, 3172, 3169, 2688, 2687, 2686, 6040}, + {582, 582, 497: 3265, 501: 3263, 3264, 3262, 3260, 725: 3261, 3259}, + {583, 583, 474: 3269, 575: 3270}, + {1919, 1919, 201: 6044, 562: 1919, 1242: 6043}, + {548, 548, 562: 6046, 957: 6045}, // 3570 - {1966, 1966, 27: 1966, 59: 1966, 61: 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 461: 1966, 643: 1966}, - {485: 1965, 496: 1965}, - {485: 1964, 496: 1964}, - {485: 1963, 496: 1963, 560: 1963, 1963}, - {485: 1962, 496: 1962, 560: 1962, 1962}, + {1918, 1918, 562: 1918}, + {1924, 1924}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6047}, + {547, 547, 7: 3841}, + {2: 1921, 1921, 1921, 1921, 1921, 8: 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 48: 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, 558: 6050, 1209: 6049}, // 3575 - {485: 1961, 496: 1961, 560: 1961, 1961}, - {485: 1960, 496: 1960, 560: 1960, 1960}, - {485: 1959, 496: 1959, 560: 1959, 1959}, - {485: 1958, 496: 1958, 560: 1958, 1958}, - {485: 1957, 496: 1957, 560: 1957, 1957}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6053, 2691, 2692, 2690}, + {467: 4004, 469: 4003, 799: 6051}, + {185: 6052}, + {2: 1920, 1920, 1920, 1920, 1920, 8: 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 48: 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920, 1920}, + {1927, 1927}, // 3580 - {485: 1956, 496: 1956, 560: 1956, 1956}, - {464: 1955, 485: 1955}, - {464: 1954, 485: 1954}, - {464: 1953, 485: 1953}, - {464: 1952, 485: 1952}, + {2: 1923, 1923, 1923, 1923, 1923, 8: 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 48: 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 1923, 558: 6056, 1210: 6055}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6058, 2691, 2692, 2690}, + {185: 6057}, + {2: 1922, 1922, 1922, 1922, 1922, 8: 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 48: 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922, 1922}, + {1928, 1928}, // 3585 - {2: 1951, 1951, 1951, 1951, 1951, 8: 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 58: 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 464: 1951, 477: 1951, 485: 1951, 494: 1951}, - {2: 1950, 1950, 1950, 1950, 1950, 8: 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 58: 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 464: 1950, 477: 1950, 485: 1950, 494: 1950}, - {194: 6097}, - {485: 4187, 496: 1999, 726: 6095}, - {485: 4187, 496: 1999, 560: 1999, 1999, 726: 6093}, + {500: 2665, 724: 6060}, + {1930, 1930}, + {490: 6070}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 6065, 654: 5222, 2691, 2692, 2690, 804: 6067, 1185: 6066}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6064}, // 3590 - {464: 1999, 485: 4187, 726: 6091}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 477: 1999, 485: 4187, 494: 1999, 726: 6086}, - {464: 1999, 485: 4187, 496: 1999, 726: 6081}, - {464: 1999, 485: 4187, 496: 1999, 726: 6078}, - {485: 4187, 496: 1999, 726: 6073}, + {7: 3841, 490: 1977, 641: 1977}, + {490: 1979, 641: 1979}, + {7: 6068, 490: 1978, 641: 1978}, + {7: 1976, 490: 1976, 641: 1976}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 6069}, // 3595 - {98: 1999, 107: 1999, 485: 4187, 496: 1999, 726: 6070}, - {178: 1999, 1999, 182: 1999, 485: 4187, 496: 1999, 560: 1999, 1999, 726: 6067}, - {178: 1999, 1999, 182: 1999, 485: 4187, 496: 1999, 560: 1999, 1999, 726: 6058}, - {178: 6064, 6065, 182: 6066, 496: 2650, 560: 6062, 6063, 725: 6061, 915: 6059, 1075: 6060}, - {1934, 1934, 27: 1934, 59: 1934, 61: 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 461: 1934, 643: 1934}, + {7: 1975, 490: 1975, 641: 1975}, + {468: 6071}, + {1974, 1974, 15: 1974, 48: 1974, 50: 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 464: 1974, 644: 1974, 886: 6072}, + {1980, 1980, 15: 6099, 48: 6075, 50: 6095, 6088, 6078, 6074, 6082, 6086, 6098, 6081, 6087, 6085, 6083, 6096, 6089, 6077, 6097, 6076, 6079, 6080, 6084, 464: 6090, 644: 6100, 882: 6092, 6091, 6094, 6073, 887: 6093}, + {1973, 1973, 15: 1973, 48: 1973, 50: 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 464: 1973, 644: 1973}, // 3600 - {1933, 1933, 27: 1933, 59: 1933, 61: 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 461: 1933, 643: 1933}, - {1929, 1929, 27: 1929, 59: 1929, 61: 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 461: 1929, 643: 1929}, - {1928, 1928, 27: 1928, 59: 1928, 61: 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 1928, 461: 1928, 643: 1928}, - {1927, 1927, 27: 1927, 59: 1927, 61: 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 1927, 461: 1927, 643: 1927}, - {1926, 1926, 27: 1926, 59: 1926, 61: 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 1926, 461: 1926, 643: 1926}, + {489: 1972, 500: 1972}, + {489: 1971, 500: 1971}, + {489: 1970, 500: 1970, 563: 1970, 1970}, + {489: 1969, 500: 1969, 563: 1969, 1969}, + {489: 1968, 500: 1968, 563: 1968, 1968}, // 3605 - {1925, 1925, 27: 1925, 59: 1925, 61: 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 461: 1925, 643: 1925}, - {1924, 1924, 27: 1924, 59: 1924, 61: 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 1924, 461: 1924, 643: 1924}, - {178: 6064, 6065, 182: 6066, 496: 2650, 560: 6062, 6063, 725: 6061, 915: 6068, 1075: 6069}, - {1936, 1936, 27: 1936, 59: 1936, 61: 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 461: 1936, 643: 1936}, - {1935, 1935, 27: 1935, 59: 1935, 61: 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 461: 1935, 643: 1935}, + {489: 1967, 500: 1967, 563: 1967, 1967}, + {489: 1966, 500: 1966, 563: 1966, 1966}, + {489: 1965, 500: 1965, 563: 1965, 1965}, + {489: 1964, 500: 1964, 563: 1964, 1964}, + {489: 1963, 500: 1963, 563: 1963, 1963}, // 3610 - {98: 3843, 107: 3842, 496: 2650, 725: 2649, 734: 6072, 823: 6071}, - {1938, 1938, 27: 1938, 59: 1938, 61: 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 1938, 461: 1938, 643: 1938}, - {1937, 1937, 27: 1937, 59: 1937, 61: 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 461: 1937, 643: 1937}, - {496: 2650, 725: 2649, 734: 6074}, - {202: 6075}, + {468: 1962, 489: 1962}, + {468: 1961, 489: 1961}, + {468: 1960, 489: 1960}, + {468: 1959, 489: 1959}, + {2: 1958, 1958, 1958, 1958, 1958, 8: 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 48: 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 468: 1958, 482: 1958, 489: 1958, 499: 1958}, // 3615 - {545: 6076}, - {108: 6077}, - {1939, 1939, 27: 1939, 59: 1939, 61: 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 461: 1939, 643: 1939}, - {464: 6079, 496: 2650, 725: 2649, 734: 6080}, - {1941, 1941, 27: 1941, 59: 1941, 61: 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 461: 1941, 643: 1941}, + {2: 1957, 1957, 1957, 1957, 1957, 8: 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 48: 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 1957, 468: 1957, 482: 1957, 489: 1957, 499: 1957}, + {195: 6140}, + {489: 4192, 500: 2006, 727: 6138}, + {489: 4192, 500: 2006, 563: 2006, 2006, 727: 6136}, + {468: 2006, 489: 4192, 727: 6134}, // 3620 - {1940, 1940, 27: 1940, 59: 1940, 61: 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 461: 1940, 643: 1940}, - {464: 6083, 496: 2650, 725: 2649, 734: 6082}, - {1942, 1942, 27: 1942, 59: 1942, 61: 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 105: 3365, 3361, 108: 3358, 3373, 111: 3360, 3357, 3359, 3363, 3364, 3369, 3368, 3367, 3371, 3372, 3366, 3370, 3362, 461: 1942, 643: 1942, 796: 6084}, - {1943, 1943, 27: 1943, 59: 1943, 61: 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 461: 1943, 643: 1943}, - {294: 6085}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 482: 2006, 489: 4192, 499: 2006, 727: 6129}, + {468: 2006, 489: 4192, 500: 2006, 727: 6124}, + {468: 2006, 489: 4192, 500: 2006, 727: 6121}, + {489: 4192, 500: 2006, 727: 6116}, + {98: 2006, 107: 2006, 489: 4192, 500: 2006, 727: 6113}, // 3625 - {1944, 1944, 27: 1944, 59: 1944, 61: 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 461: 1944, 643: 1944}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 477: 6089, 494: 6090, 653: 3392, 2676, 2677, 2675, 728: 6088, 1288: 6087}, - {1945, 1945, 27: 1945, 59: 1945, 61: 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 461: 1945, 643: 1945}, - {246, 246, 27: 246, 59: 246, 61: 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 461: 246, 643: 246}, - {245, 245, 27: 245, 59: 245, 61: 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 461: 245, 643: 245}, + {179: 2006, 2006, 183: 2006, 489: 4192, 500: 2006, 563: 2006, 2006, 727: 6110}, + {179: 2006, 2006, 183: 2006, 489: 4192, 500: 2006, 563: 2006, 2006, 727: 6101}, + {179: 6107, 6108, 183: 6109, 500: 2665, 563: 6105, 6106, 724: 6104, 915: 6102, 1078: 6103}, + {1941, 1941, 15: 1941, 48: 1941, 50: 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 464: 1941, 644: 1941}, + {1940, 1940, 15: 1940, 48: 1940, 50: 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 464: 1940, 644: 1940}, // 3630 - {244, 244, 27: 244, 59: 244, 61: 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 461: 244, 643: 244}, - {464: 6092}, - {1946, 1946, 27: 1946, 59: 1946, 61: 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 461: 1946, 643: 1946}, - {496: 2650, 560: 6062, 6063, 725: 6061, 915: 6094}, - {1947, 1947, 27: 1947, 59: 1947, 61: 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 461: 1947, 643: 1947}, + {1936, 1936, 15: 1936, 48: 1936, 50: 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 464: 1936, 644: 1936}, + {1935, 1935, 15: 1935, 48: 1935, 50: 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 464: 1935, 644: 1935}, + {1934, 1934, 15: 1934, 48: 1934, 50: 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 464: 1934, 644: 1934}, + {1933, 1933, 15: 1933, 48: 1933, 50: 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 464: 1933, 644: 1933}, + {1932, 1932, 15: 1932, 48: 1932, 50: 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 464: 1932, 644: 1932}, // 3635 - {496: 2650, 725: 2649, 734: 6096}, - {1948, 1948, 27: 1948, 59: 1948, 61: 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 461: 1948, 643: 1948}, - {2: 1949, 1949, 1949, 1949, 1949, 8: 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 58: 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 464: 1949, 477: 1949, 485: 1949, 494: 1949}, - {640: 6099}, - {464: 6100}, + {1931, 1931, 15: 1931, 48: 1931, 50: 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 464: 1931, 644: 1931}, + {179: 6107, 6108, 183: 6109, 500: 2665, 563: 6105, 6106, 724: 6104, 915: 6111, 1078: 6112}, + {1943, 1943, 15: 1943, 48: 1943, 50: 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 1943, 464: 1943, 644: 1943}, + {1942, 1942, 15: 1942, 48: 1942, 50: 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 464: 1942, 644: 1942}, + {98: 3861, 107: 3860, 500: 2665, 724: 2664, 734: 6115, 822: 6114}, // 3640 - {1967, 1967, 27: 1967, 59: 1967, 61: 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 461: 1967, 643: 1967, 886: 6101}, - {1974, 1974, 27: 6056, 59: 6032, 61: 6052, 6045, 6035, 6031, 6039, 6043, 6055, 6038, 6044, 6042, 6040, 6053, 6046, 6034, 6054, 6033, 6036, 6037, 6041, 461: 6047, 643: 6057, 882: 6049, 6048, 6051, 6030, 887: 6050}, - {1989, 1989, 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 6127}, - {1987, 1987}, - {37: 6125}, + {1945, 1945, 15: 1945, 48: 1945, 50: 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 1945, 464: 1945, 644: 1945}, + {1944, 1944, 15: 1944, 48: 1944, 50: 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 464: 1944, 644: 1944}, + {500: 2665, 724: 2664, 734: 6117}, + {202: 6118}, + {548: 6119}, // 3645 - {1726, 1726, 1726, 1726, 1726, 1726, 1726, 8: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 58: 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 1726, 485: 6108, 642: 1726}, - {462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 652: 2622, 699: 2623, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 6107}, - {1981, 1981}, - {175: 6112, 300: 6115, 316: 6114, 388: 6111, 393: 6116, 464: 6109, 564: 6113, 1185: 6110}, - {462: 2509, 2508, 482: 6121, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 652: 2622, 699: 2623, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 6122}, + {108: 6120}, + {1946, 1946, 15: 1946, 48: 1946, 50: 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1946, 464: 1946, 644: 1946}, + {468: 6122, 500: 2665, 724: 2664, 734: 6123}, + {1948, 1948, 15: 1948, 48: 1948, 50: 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 464: 1948, 644: 1948}, + {1947, 1947, 15: 1947, 48: 1947, 50: 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 1947, 464: 1947, 644: 1947}, // 3650 - {462: 2509, 2508, 482: 6117, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 652: 2622, 699: 2623, 732: 2476, 741: 2624, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2630, 2629, 2479, 764: 2605, 2477, 769: 2627, 771: 2628, 773: 2626, 783: 2478, 787: 2625, 812: 2631, 841: 6118}, - {462: 1980, 1980, 482: 1980, 487: 1980, 494: 1980, 556: 1980, 1980, 634: 1980, 644: 1980, 652: 1980, 732: 1980}, - {462: 1979, 1979, 482: 1979, 487: 1979, 494: 1979, 556: 1979, 1979, 634: 1979, 644: 1979, 652: 1979, 732: 1979}, - {462: 1978, 1978, 482: 1978, 487: 1978, 494: 1978, 556: 1978, 1978, 634: 1978, 644: 1978, 652: 1978, 732: 1978}, - {462: 1977, 1977, 482: 1977, 487: 1977, 494: 1977, 556: 1977, 1977, 634: 1977, 644: 1977, 652: 1977, 732: 1977}, + {468: 6126, 500: 2665, 724: 2664, 734: 6125}, + {1949, 1949, 15: 1949, 48: 1949, 50: 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 1949, 105: 3383, 3379, 108: 3376, 3391, 111: 3378, 3375, 3377, 3381, 3382, 3387, 3386, 3385, 3389, 3390, 3384, 3388, 124: 3380, 464: 1949, 644: 1949, 795: 6127}, + {1950, 1950, 15: 1950, 48: 1950, 50: 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 464: 1950, 644: 1950}, + {296: 6128}, + {1951, 1951, 15: 1951, 48: 1951, 50: 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 1951, 464: 1951, 644: 1951}, // 3655 - {462: 1976, 1976, 482: 1976, 487: 1976, 494: 1976, 556: 1976, 1976, 634: 1976, 644: 1976, 652: 1976, 732: 1976}, - {462: 1975, 1975, 482: 1975, 487: 1975, 494: 1975, 556: 1975, 1975, 634: 1975, 644: 1975, 652: 1975, 732: 1975}, - {37: 6119}, - {1982, 1982}, - {496: 2650, 725: 6120}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 482: 6132, 499: 6133, 654: 3410, 2691, 2692, 2690, 729: 6131, 1292: 6130}, + {1952, 1952, 15: 1952, 48: 1952, 50: 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 464: 1952, 644: 1952}, + {248, 248, 15: 248, 48: 248, 50: 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 464: 248, 644: 248}, + {247, 247, 15: 247, 48: 247, 50: 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 464: 247, 644: 247}, + {246, 246, 15: 246, 48: 246, 50: 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 464: 246, 644: 246}, // 3660 - {1983, 1983}, - {37: 6123}, - {1984, 1984}, - {496: 2650, 725: 6124}, - {1985, 1985}, + {468: 6135}, + {1953, 1953, 15: 1953, 48: 1953, 50: 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 1953, 464: 1953, 644: 1953}, + {500: 2665, 563: 6105, 6106, 724: 6104, 915: 6137}, + {1954, 1954, 15: 1954, 48: 1954, 50: 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 464: 1954, 644: 1954}, + {500: 2665, 724: 2664, 734: 6139}, // 3665 - {496: 2650, 725: 6126}, - {1986, 1986}, - {1988, 1988}, - {1996, 1996}, - {485: 6151}, + {1955, 1955, 15: 1955, 48: 1955, 50: 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 1955, 464: 1955, 644: 1955}, + {2: 1956, 1956, 1956, 1956, 1956, 8: 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 48: 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 1956, 468: 1956, 482: 1956, 489: 1956, 499: 1956}, + {641: 6142}, + {468: 6143}, + {1974, 1974, 15: 1974, 48: 1974, 50: 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 464: 1974, 644: 1974, 886: 6144}, // 3670 - {82: 2470, 145: 2472, 151: 2498, 153: 2469, 380: 6147, 462: 2509, 2508, 487: 2507, 494: 2493, 501: 6133, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6131, 732: 2476, 741: 6132, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6139, 6138, 2479, 764: 2605, 2477, 769: 6136, 771: 6137, 773: 6135, 783: 2478, 787: 6134, 799: 6145, 834: 6141, 837: 6142, 848: 6140, 852: 6143, 6144, 908: 6146}, - {449, 449, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, - {451, 451, 469: 787, 479: 787, 787}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 5519, 5524, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 5522, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 5521, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 5526, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 5520, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 5527, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 5523, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 489: 3736, 558: 5533, 577: 5532, 637: 3734, 653: 5530, 2676, 2677, 2675, 762: 5534, 820: 5531, 963: 5535, 1138: 5528}, - {456, 456}, + {1981, 1981, 15: 6099, 48: 6075, 50: 6095, 6088, 6078, 6074, 6082, 6086, 6098, 6081, 6087, 6085, 6083, 6096, 6089, 6077, 6097, 6076, 6079, 6080, 6084, 464: 6090, 644: 6100, 882: 6092, 6091, 6094, 6073, 887: 6093}, + {1996, 1996, 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 6170}, + {1994, 1994}, + {26: 6168}, + {1732, 1732, 1732, 1732, 1732, 1732, 1732, 8: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 48: 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 489: 6151, 643: 1732}, // 3675 - {455, 455}, - {454, 454}, - {453, 453}, - {452, 452}, - {450, 450}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 653: 2637, 700: 2638, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 6150}, + {1988, 1988}, + {175: 6155, 303: 6158, 320: 6157, 391: 6154, 396: 6159, 468: 6152, 568: 6156, 1190: 6153}, + {465: 2523, 2522, 485: 6164, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 653: 2637, 700: 2638, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 6165}, + {465: 2523, 2522, 485: 6160, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 653: 2637, 700: 2638, 733: 2490, 742: 2639, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2645, 2644, 2493, 763: 2620, 765: 2491, 767: 2642, 2643, 2641, 782: 2492, 786: 2640, 811: 2646, 841: 6161}, // 3680 - {448, 448}, - {447, 447}, - {446, 446}, - {445, 445}, - {444, 444}, + {465: 1987, 1987, 485: 1987, 493: 1987, 499: 1987, 559: 1987, 562: 1987, 637: 1987, 645: 1987, 653: 1987, 733: 1987}, + {465: 1986, 1986, 485: 1986, 493: 1986, 499: 1986, 559: 1986, 562: 1986, 637: 1986, 645: 1986, 653: 1986, 733: 1986}, + {465: 1985, 1985, 485: 1985, 493: 1985, 499: 1985, 559: 1985, 562: 1985, 637: 1985, 645: 1985, 653: 1985, 733: 1985}, + {465: 1984, 1984, 485: 1984, 493: 1984, 499: 1984, 559: 1984, 562: 1984, 637: 1984, 645: 1984, 653: 1984, 733: 1984}, + {465: 1983, 1983, 485: 1983, 493: 1983, 499: 1983, 559: 1983, 562: 1983, 637: 1983, 645: 1983, 653: 1983, 733: 1983}, // 3685 - {32: 5031}, - {1994, 1994}, - {485: 6148}, - {464: 6149}, - {82: 2470, 145: 2472, 151: 2498, 153: 2469, 462: 2509, 2508, 487: 2507, 494: 2493, 501: 6133, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6131, 732: 2476, 741: 6132, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6139, 6138, 2479, 764: 2605, 2477, 769: 6136, 771: 6137, 773: 6135, 783: 2478, 787: 6134, 799: 6145, 834: 6141, 837: 6142, 848: 6140, 852: 6143, 6144, 908: 6150}, + {465: 1982, 1982, 485: 1982, 493: 1982, 499: 1982, 559: 1982, 562: 1982, 637: 1982, 645: 1982, 653: 1982, 733: 1982}, + {26: 6162}, + {1989, 1989}, + {500: 2665, 724: 6163}, + {1990, 1990}, // 3690 + {26: 6166}, + {1991, 1991}, + {500: 2665, 724: 6167}, + {1992, 1992}, + {500: 2665, 724: 6169}, + // 3695 {1993, 1993}, - {464: 6152}, - {82: 2470, 145: 2472, 151: 2498, 153: 2469, 462: 2509, 2508, 487: 2507, 494: 2493, 501: 6133, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6131, 732: 2476, 741: 6132, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6139, 6138, 2479, 764: 2605, 2477, 769: 6136, 771: 6137, 773: 6135, 783: 2478, 787: 6134, 799: 6145, 834: 6141, 837: 6142, 848: 6140, 852: 6143, 6144, 908: 6153}, {1995, 1995}, - {2022, 2022}, - // 3695 - {2021, 2021}, - {242, 242, 471: 242}, - {2: 1027, 1027, 1027, 1027, 1027, 8: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 58: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 477: 1027, 490: 1027, 738: 5234, 5233, 5232, 827: 5235, 874: 6158}, - {2: 1015, 1015, 1015, 1015, 1015, 8: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 58: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 6160, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 477: 1015, 490: 1015, 1090: 6159}, - {2: 1813, 1813, 1813, 1813, 1813, 8: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 58: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 477: 4087, 490: 1813, 844: 6161}, + {2003, 2003}, + {489: 6194}, + {71: 2484, 145: 2486, 152: 2512, 154: 2483, 384: 6190, 465: 2523, 2522, 493: 2521, 496: 6176, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 6174, 733: 2490, 742: 6175, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 6182, 6181, 2493, 763: 2620, 765: 2491, 767: 6179, 6180, 6178, 782: 2492, 786: 6177, 798: 6188, 833: 6184, 837: 6185, 848: 6183, 852: 6186, 6187, 908: 6189}, // 3700 - {2: 1014, 1014, 1014, 1014, 1014, 8: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 58: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 477: 1014, 490: 1014}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 490: 6162, 653: 6164, 2676, 2677, 2675, 905: 6165, 952: 6163}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6179, 2676, 2677, 2675, 727: 6177, 905: 6165, 952: 6178}, - {7: 6173, 490: 6172}, - {7: 1017, 471: 1017, 490: 1017, 642: 6167, 895: 6166}, + {451, 451, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {453, 453, 472: 791, 480: 791, 791}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 5519, 5514, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 5517, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 5516, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 5521, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 5515, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 5522, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 5518, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 498: 3754, 560: 5529, 582: 5528, 638: 3752, 654: 5526, 2691, 2692, 2690, 762: 5530, 819: 5527, 966: 5531, 1142: 5524}, + {458, 458}, + {457, 457}, // 3705 - {7: 1019, 471: 1019, 490: 1019}, - {7: 1021, 471: 1021, 490: 1021}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 6169, 653: 6168, 2676, 2677, 2675}, - {7: 1017, 471: 1017, 490: 1017, 642: 6171, 895: 6170}, - {7: 1016, 471: 1016, 490: 1016}, + {456, 456}, + {455, 455}, + {454, 454}, + {452, 452}, + {450, 450}, // 3710 - {7: 1020, 471: 1020, 490: 1020}, - {512: 6169}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 568: 5241, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5248, 840: 5238, 877: 6175}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6164, 2676, 2677, 2675, 905: 6174}, - {7: 1018, 471: 1018, 490: 1018}, + {449, 449}, + {448, 448}, + {447, 447}, + {446, 446}, + {21: 5026}, // 3715 - {237, 237, 7: 5292, 471: 237, 492: 2636, 780: 2637, 6176}, - {2026, 2026, 471: 2026}, - {894, 894, 894, 894, 894, 894, 894, 8: 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 58: 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 468: 894, 471: 894, 477: 894, 5296, 483: 894, 488: 894, 492: 894, 894, 514: 894, 849: 6185}, - {7: 6173, 471: 6182}, - {1025, 1025, 1025, 1025, 1025, 1025, 1025, 1017, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 58: 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 468: 1025, 471: 1017, 477: 1025, 1025, 483: 1025, 488: 1025, 492: 1025, 1025, 514: 1025, 642: 6180, 895: 6166}, + {2001, 2001}, + {489: 6191}, + {468: 6192}, + {71: 2484, 145: 2486, 152: 2512, 154: 2483, 465: 2523, 2522, 493: 2521, 496: 6176, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 6174, 733: 2490, 742: 6175, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 6182, 6181, 2493, 763: 2620, 765: 2491, 767: 6179, 6180, 6178, 782: 2492, 786: 6177, 798: 6188, 833: 6184, 837: 6185, 848: 6183, 852: 6186, 6187, 908: 6193}, + {2000, 2000}, // 3720 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 512: 6169, 653: 6181, 2676, 2677, 2675}, - {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1017, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 58: 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 468: 1024, 471: 1017, 477: 1024, 1024, 483: 1024, 488: 1024, 492: 1024, 1024, 514: 1024, 642: 6171, 895: 6170}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 5246, 568: 5241, 653: 3820, 2676, 2677, 2675, 699: 5245, 727: 5244, 789: 5243, 792: 5242, 5248, 840: 5238, 877: 6183}, - {237, 237, 7: 5292, 492: 2636, 780: 2637, 6184}, - {2025, 2025}, + {468: 6195}, + {71: 2484, 145: 2486, 152: 2512, 154: 2483, 465: 2523, 2522, 493: 2521, 496: 6176, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 6174, 733: 2490, 742: 6175, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 6182, 6181, 2493, 763: 2620, 765: 2491, 767: 6179, 6180, 6178, 782: 2492, 786: 6177, 798: 6188, 833: 6184, 837: 6185, 848: 6183, 852: 6186, 6187, 908: 6196}, + {2002, 2002}, + {2029, 2029}, + {2028, 2028}, // 3725 - {892, 892, 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 468: 5253, 471: 892, 477: 892, 483: 892, 488: 892, 492: 892, 892, 514: 892, 653: 5252, 2676, 2677, 2675, 903: 5251, 6186}, - {873, 873, 471: 873, 477: 5306, 483: 873, 488: 5307, 492: 873, 873, 514: 5305, 928: 5309, 5308, 1044: 5310, 6187}, - {237, 237, 471: 237, 483: 237, 492: 2636, 237, 780: 2637, 6188}, - {1265, 1265, 471: 1265, 483: 1265, 493: 2639, 756: 2640, 801: 6189}, - {855, 855, 471: 855, 483: 5356, 1053: 6190}, + {2: 1031, 1031, 1031, 1031, 1031, 8: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 48: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 482: 1031, 490: 1031, 739: 5229, 5228, 5227, 826: 5230, 875: 6200}, + {2: 1019, 1019, 1019, 1019, 1019, 8: 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 48: 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 5593, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 482: 1019, 490: 1019, 1093: 6201}, + {2: 1820, 1820, 1820, 1820, 1820, 8: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 48: 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 1820, 482: 4105, 490: 1820, 844: 6202}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 490: 6203, 654: 5597, 2691, 2692, 2690, 905: 5598, 955: 5596}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6205, 2691, 2692, 2690, 728: 5610, 905: 5598, 955: 6204}, // 3730 - {2027, 2027, 471: 2027}, - {2028, 2028, 7: 3491}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6265, 2676, 2677, 2675}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6263}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6254}, + {7: 5606, 473: 6208}, + {1029, 1029, 1029, 1029, 1029, 1029, 1029, 1021, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 48: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 470: 1029, 473: 1021, 482: 1029, 1029, 486: 1029, 492: 1029, 494: 1029, 1029, 517: 1029, 643: 6206, 895: 5599}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 515: 5602, 654: 6207, 2691, 2692, 2690}, + {1028, 1028, 1028, 1028, 1028, 1028, 1028, 1021, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 48: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 470: 1028, 473: 1021, 482: 1028, 1028, 486: 1028, 492: 1028, 494: 1028, 1028, 517: 1028, 643: 5604, 895: 5603}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 5241, 571: 5236, 654: 3838, 2691, 2692, 2690, 700: 5240, 728: 5239, 788: 5238, 791: 5237, 5243, 840: 5233, 878: 6209}, // 3735 - {110: 5370, 556: 5369, 1128: 6250}, - {154: 577, 160: 5424}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 555: 6245, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6244}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 555: 6241, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 6240}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 555: 6237, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 6236}, + {239, 239, 7: 5287, 492: 2651, 779: 2652, 6210}, + {2032, 2032}, + {2035, 2035, 7: 3509}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6270, 2691, 2692, 2690}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6268}, // 3740 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6232}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6230}, - {154: 6210}, - {158: 6207}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6205}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6259}, + {110: 5365, 562: 5364, 1132: 6255}, + {155: 580, 161: 5419}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 558: 6250, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6249}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 558: 6246, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 6245}, // 3745 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6206}, - {26, 26, 7: 3823}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6208}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4877, 2676, 2677, 2675, 873: 6209}, - {53, 53}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 558: 6242, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 6241}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6237}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6235}, + {155: 6230}, + {159: 6227}, // 3750 - {482: 6211}, - {462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6214, 732: 6212, 741: 6215, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6217, 6216, 6213, 764: 2605, 6219, 769: 6220, 771: 6221, 773: 6218, 881: 6222}, - {2: 825, 825, 825, 825, 825, 8: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 58: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 477: 825, 490: 825, 738: 825, 825, 825, 749: 5229, 855: 5230, 906: 6225}, - {462: 2509, 487: 2507, 556: 2506, 634: 2502, 644: 2606, 699: 3787, 741: 3786, 2503, 2504, 2505, 2514, 2512, 3788, 3789, 764: 6156}, - {175, 175, 469: 786, 471: 175, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6225}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6226}, + {26, 26, 7: 3841}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6228}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4894, 2691, 2692, 2690, 874: 6229}, // 3755 - {177, 177, 469: 787, 471: 177, 479: 787, 787}, - {178, 178, 471: 178}, - {176, 176, 471: 176}, - {174, 174, 471: 174}, - {173, 173, 471: 173}, + {53, 53}, + {485: 6231}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 6232}, + {171, 171, 473: 6233}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 6234}, // 3760 - {172, 172, 471: 172}, - {171, 171, 471: 171}, - {169, 169, 471: 6223}, - {462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6214, 732: 6212, 741: 6215, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6217, 6216, 6213, 764: 2605, 6219, 769: 6220, 771: 6221, 773: 6218, 881: 6224}, - {168, 168}, + {170, 170}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6236, 2691, 2692, 2690}, + {1925, 1925}, + {2014, 2014, 157: 6239, 483: 6238}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 6240}, // 3765 - {2: 1027, 1027, 1027, 1027, 1027, 8: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 58: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 477: 1027, 490: 1027, 738: 5234, 5233, 5232, 827: 5235, 874: 6226}, - {2: 1015, 1015, 1015, 1015, 1015, 8: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 58: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 6160, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 477: 1015, 490: 1015, 1090: 6227}, - {2: 1813, 1813, 1813, 1813, 1813, 8: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 58: 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 477: 4087, 490: 1813, 844: 6228}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 490: 6229, 653: 6164, 2676, 2677, 2675, 905: 6165, 952: 6163}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6177}, + {2012, 2012}, + {2013, 2013, 7: 4659}, + {2016, 2016, 7: 5558}, + {578: 6243}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 5557, 5555, 851: 6244}, // 3770 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6231, 2676, 2677, 2675}, - {1918, 1918}, - {2007, 2007, 156: 6234, 478: 6233}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 6235}, - {2005, 2005}, + {2015, 2015, 7: 5558}, + {2018, 2018, 7: 5126}, + {578: 6247}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5124, 856: 6248}, + {2017, 2017, 7: 5126}, // 3775 - {2006, 2006, 7: 4642}, - {2009, 2009, 7: 5562}, - {573: 6238}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 5561, 5559, 851: 6239}, - {2008, 2008, 7: 5562}, + {2011, 2011, 7: 3841, 661: 4710, 663: 4709, 899: 6254}, + {578: 6251}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6252}, + {2011, 2011, 7: 3841, 661: 4710, 663: 4709, 899: 6253}, + {2019, 2019}, // 3780 - {2011, 2011, 7: 5131}, - {573: 6242}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5129, 856: 6243}, - {2010, 2010, 7: 5131}, - {2004, 2004, 7: 3823, 660: 4693, 662: 4692, 899: 6249}, + {2020, 2020}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6256}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 3839, 785: 6257}, + {2011, 2011, 7: 3841, 661: 4710, 663: 4709, 899: 6258}, + {2024, 2024}, // 3785 - {573: 6246}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6247}, - {2004, 2004, 7: 3823, 660: 4693, 662: 4692, 899: 6248}, - {2012, 2012}, - {2013, 2013}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6260, 2691, 2692, 2690}, + {464: 6261}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6262}, + {2154, 2154, 81: 4146, 488: 4147, 858: 6264, 871: 6263, 1050: 6265}, + {2153, 2153, 81: 4146, 858: 6267}, // 3790 - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6251}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 3821, 786: 6252}, - {2004, 2004, 7: 3823, 660: 4693, 662: 4692, 899: 6253}, - {2017, 2017}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6255, 2676, 2677, 2675}, + {2152, 2152, 488: 4147, 871: 6266}, + {2025, 2025}, + {2150, 2150}, + {2151, 2151}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 6269}, // 3795 - {461: 6256}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6257}, - {2146, 2146, 92: 4141, 486: 4142, 858: 6259, 870: 6258, 1046: 6260}, - {2145, 2145, 92: 4141, 858: 6262}, - {2144, 2144, 486: 4142, 870: 6261}, + {2026, 2026}, + {2162, 2162}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6492}, + {640: 6480}, + {640: 2148}, // 3800 - {2018, 2018}, - {2142, 2142}, - {2143, 2143}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 6264}, - {2019, 2019}, + {640: 2147}, + {640: 2146}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6457}, + {16: 6378, 81: 6377, 99: 2052, 139: 2052, 659: 2052, 1314: 6376}, + {499: 6375}, // 3805 - {2154, 2154}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6449}, - {638: 6437}, - {638: 2140}, - {638: 2139}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6363}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 468: 1822, 558: 4734, 561: 1822, 774: 6331}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 468: 1822, 558: 4734, 774: 6325}, + {155: 6320}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6284}, // 3810 - {638: 2138}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6419}, - {16: 6373, 92: 6372, 99: 2045, 139: 2045, 658: 2045, 1310: 6371}, - {494: 6370}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6358}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6285}, + {49, 49, 4: 49, 49, 49, 13: 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 70: 6293, 6290, 6296, 6297, 6298, 6291, 6289, 6299, 6295, 6292, 471: 49, 49, 474: 49, 495: 49, 498: 49, 638: 49, 640: 49, 648: 6294, 901: 6288, 1180: 6286, 1271: 6287}, + {387, 387, 4: 4152, 4154, 391, 13: 4171, 2125, 4169, 4110, 4173, 4160, 4189, 4153, 4156, 4155, 4158, 4159, 4161, 4168, 391, 4179, 4180, 4166, 4167, 4172, 4174, 4186, 4185, 4191, 4187, 4184, 4177, 4182, 4183, 4176, 4178, 4181, 4170, 471: 4151, 4188, 474: 2125, 495: 4877, 498: 2125, 638: 2125, 640: 4157, 770: 4162, 781: 4164, 801: 4163, 823: 4165, 827: 4175, 831: 4190, 907: 5441, 1006: 6319}, + {48, 48, 4: 48, 48, 48, 13: 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 70: 6293, 6290, 6296, 6297, 6298, 6291, 6289, 6299, 6295, 6292, 471: 48, 48, 474: 48, 495: 48, 498: 48, 638: 48, 640: 48, 648: 6294, 901: 6318}, + {47, 47, 4: 47, 47, 47, 13: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 70: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 471: 47, 47, 474: 47, 495: 47, 498: 47, 638: 47, 640: 47, 648: 47}, // 3815 - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 464: 1815, 555: 4717, 559: 1815, 775: 6326}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 464: 1815, 555: 4717, 775: 6320}, - {154: 6315}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6279}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6280}, + {477: 2006, 2006, 489: 4192, 500: 2006, 650: 6315, 727: 6314}, + {466: 6311, 477: 2006, 2006, 489: 4192, 500: 2006, 727: 6310}, + {477: 2006, 2006, 489: 4192, 500: 2006, 727: 6308}, + {40, 40, 4: 40, 40, 40, 13: 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 70: 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 471: 40, 40, 474: 40, 495: 40, 498: 40, 638: 40, 640: 40, 648: 40}, + {72: 6306, 74: 6307, 6304, 648: 6305}, // 3820 - {49, 49, 4: 49, 49, 49, 13: 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 81: 6288, 6285, 6291, 6292, 6293, 6286, 6284, 6294, 6290, 6287, 467: 49, 469: 49, 49, 488: 49, 49, 637: 49, 49, 647: 6289, 901: 6283, 1175: 6281, 1267: 6282}, - {385, 385, 4: 4147, 4149, 389, 13: 2118, 4166, 4093, 4105, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 4164, 4184, 4168, 4155, 4148, 4151, 4150, 4153, 4154, 4156, 4163, 389, 4174, 4175, 4161, 4162, 4167, 4169, 4181, 4180, 4186, 4182, 4179, 4172, 4177, 4178, 4171, 4173, 4176, 4165, 467: 4146, 469: 4183, 2118, 488: 4860, 2118, 637: 2118, 4152, 761: 4103, 767: 4104, 770: 4157, 782: 4159, 802: 4158, 824: 4160, 828: 4170, 832: 4185, 907: 5446, 1002: 6314}, - {48, 48, 4: 48, 48, 48, 13: 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 81: 6288, 6285, 6291, 6292, 6293, 6286, 6284, 6294, 6290, 6287, 467: 48, 469: 48, 48, 488: 48, 48, 637: 48, 48, 647: 6289, 901: 6313}, - {47, 47, 4: 47, 47, 47, 13: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 81: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 467: 47, 469: 47, 47, 488: 47, 47, 637: 47, 47, 647: 47}, - {474: 1999, 1999, 485: 4187, 496: 1999, 649: 6310, 726: 6309}, + {477: 2006, 2006, 489: 4192, 500: 2006, 727: 6302}, + {37, 37, 4: 37, 37, 37, 13: 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 70: 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 471: 37, 37, 474: 37, 495: 37, 498: 37, 638: 37, 640: 37, 648: 37}, + {477: 2006, 2006, 489: 4192, 500: 2006, 727: 6300}, + {34, 34, 4: 34, 34, 34, 13: 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 70: 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 471: 34, 34, 474: 34, 495: 34, 498: 34, 638: 34, 640: 34, 648: 34}, + {32, 32, 4: 32, 32, 32, 13: 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 70: 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 471: 32, 32, 474: 32, 495: 32, 498: 32, 638: 32, 640: 32, 648: 32}, // 3825 - {463: 6306, 474: 1999, 1999, 485: 4187, 496: 1999, 726: 6305}, - {474: 1999, 1999, 485: 4187, 496: 1999, 726: 6303}, - {40, 40, 4: 40, 40, 40, 13: 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 81: 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 467: 40, 469: 40, 40, 488: 40, 40, 637: 40, 40, 647: 40}, - {83: 6301, 85: 6302, 6299, 647: 6300}, - {474: 1999, 1999, 485: 4187, 496: 1999, 726: 6297}, + {31, 31, 4: 31, 31, 31, 13: 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 70: 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 471: 31, 31, 474: 31, 495: 31, 498: 31, 638: 31, 640: 31, 648: 31}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6301}, + {35, 35, 4: 35, 35, 35, 13: 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 70: 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 471: 35, 35, 474: 35, 495: 35, 498: 35, 638: 35, 640: 35, 648: 35}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6303}, + {38, 38, 4: 38, 38, 38, 13: 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 70: 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 471: 38, 38, 474: 38, 495: 38, 498: 38, 638: 38, 640: 38, 648: 38}, // 3830 - {37, 37, 4: 37, 37, 37, 13: 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 81: 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 467: 37, 469: 37, 37, 488: 37, 37, 637: 37, 37, 647: 37}, - {474: 1999, 1999, 485: 4187, 496: 1999, 726: 6295}, - {34, 34, 4: 34, 34, 34, 13: 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 81: 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 467: 34, 469: 34, 34, 488: 34, 34, 637: 34, 34, 647: 34}, - {32, 32, 4: 32, 32, 32, 13: 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 81: 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 467: 32, 469: 32, 32, 488: 32, 32, 637: 32, 32, 647: 32}, - {31, 31, 4: 31, 31, 31, 13: 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 81: 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 467: 31, 469: 31, 31, 488: 31, 31, 637: 31, 31, 647: 31}, + {39, 39, 4: 39, 39, 39, 13: 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 70: 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 471: 39, 39, 474: 39, 495: 39, 498: 39, 638: 39, 640: 39, 648: 39}, + {36, 36, 4: 36, 36, 36, 13: 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70: 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 471: 36, 36, 474: 36, 495: 36, 498: 36, 638: 36, 640: 36, 648: 36}, + {33, 33, 4: 33, 33, 33, 13: 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 70: 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 471: 33, 33, 474: 33, 495: 33, 498: 33, 638: 33, 640: 33, 648: 33}, + {30, 30, 4: 30, 30, 30, 13: 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 70: 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 471: 30, 30, 474: 30, 495: 30, 498: 30, 638: 30, 640: 30, 648: 30}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6309}, // 3835 - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6296}, - {35, 35, 4: 35, 35, 35, 13: 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 81: 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 467: 35, 469: 35, 35, 488: 35, 35, 637: 35, 35, 647: 35}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6298}, - {38, 38, 4: 38, 38, 38, 13: 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 81: 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 467: 38, 469: 38, 38, 488: 38, 38, 637: 38, 38, 647: 38}, - {39, 39, 4: 39, 39, 39, 13: 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 81: 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 467: 39, 469: 39, 39, 488: 39, 39, 637: 39, 39, 647: 39}, + {41, 41, 4: 41, 41, 41, 13: 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 70: 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 471: 41, 41, 474: 41, 495: 41, 498: 41, 638: 41, 640: 41, 648: 41}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6313}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6312}, + {42, 42, 4: 42, 42, 42, 13: 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 70: 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 471: 42, 42, 474: 42, 495: 42, 498: 42, 638: 42, 640: 42, 648: 42}, + {43, 43, 4: 43, 43, 43, 13: 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 70: 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 471: 43, 43, 474: 43, 495: 43, 498: 43, 638: 43, 640: 43, 648: 43}, // 3840 - {36, 36, 4: 36, 36, 36, 13: 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 81: 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 467: 36, 469: 36, 36, 488: 36, 36, 637: 36, 36, 647: 36}, - {33, 33, 4: 33, 33, 33, 13: 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 81: 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 467: 33, 469: 33, 33, 488: 33, 33, 637: 33, 33, 647: 33}, - {30, 30, 4: 30, 30, 30, 13: 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 81: 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 467: 30, 469: 30, 30, 488: 30, 30, 637: 30, 30, 647: 30}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6304}, - {41, 41, 4: 41, 41, 41, 13: 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 81: 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 467: 41, 469: 41, 41, 488: 41, 41, 637: 41, 41, 647: 41}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6317}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6316}, + {44, 44, 4: 44, 44, 44, 13: 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 70: 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 471: 44, 44, 474: 44, 495: 44, 498: 44, 638: 44, 640: 44, 648: 44}, + {45, 45, 4: 45, 45, 45, 13: 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 70: 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 471: 45, 45, 474: 45, 495: 45, 498: 45, 638: 45, 640: 45, 648: 45}, + {46, 46, 4: 46, 46, 46, 13: 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 70: 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 471: 46, 46, 474: 46, 495: 46, 498: 46, 638: 46, 640: 46, 648: 46}, // 3845 - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6308}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6307}, - {42, 42, 4: 42, 42, 42, 13: 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 81: 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 467: 42, 469: 42, 42, 488: 42, 42, 637: 42, 42, 647: 42}, - {43, 43, 4: 43, 43, 43, 13: 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 81: 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 467: 43, 469: 43, 43, 488: 43, 43, 637: 43, 43, 647: 43}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6312}, - // 3850 - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6311}, - {44, 44, 4: 44, 44, 44, 13: 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 81: 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 467: 44, 469: 44, 44, 488: 44, 44, 637: 44, 44, 647: 44}, - {45, 45, 4: 45, 45, 45, 13: 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 81: 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 467: 45, 469: 45, 45, 488: 45, 45, 637: 45, 45, 647: 45}, - {46, 46, 4: 46, 46, 46, 13: 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 81: 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 467: 46, 469: 46, 46, 488: 46, 46, 637: 46, 46, 647: 46}, {50, 50}, + {485: 6321}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 6322}, + {473: 6323}, + {465: 2523, 2522, 493: 2521, 499: 2507, 559: 2506, 562: 2520, 637: 2516, 645: 2621, 700: 5578, 733: 5576, 742: 5579, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 5581, 5580, 5577, 763: 2620, 765: 5583, 767: 5584, 5585, 5582, 834: 6324}, + // 3850 + {172, 172}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 6327, 5555, 1106: 6328, 1266: 6326}, + {234, 234, 7: 6329}, + {183, 183, 7: 183}, + {182, 182, 7: 182}, // 3855 - {482: 6316}, - {462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6214, 732: 6212, 741: 6215, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6217, 6216, 6213, 764: 2605, 6219, 769: 6220, 771: 6221, 773: 6218, 881: 6317}, - {471: 6318}, - {462: 2509, 2508, 487: 2507, 494: 2493, 556: 2506, 2492, 634: 2502, 644: 2606, 699: 6214, 732: 6212, 741: 6215, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6217, 6216, 6213, 764: 2605, 6219, 769: 6220, 771: 6221, 773: 6218, 881: 6319}, - {170, 170}, - // 3860 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 6322, 5559, 1103: 6323, 1262: 6321}, - {232, 232, 7: 6324}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 5549, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 5554, 654: 3410, 2691, 2692, 2690, 729: 5077, 790: 5556, 809: 6327, 5555, 1106: 6330}, {181, 181, 7: 181}, - {180, 180, 7: 180}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 5553, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 5558, 653: 3392, 2676, 2677, 2675, 728: 5082, 791: 5560, 810: 6322, 5559, 1103: 6325}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5140, 879: 5141, 910: 6332}, + {217, 217, 7: 5143, 13: 217, 46: 217, 466: 217, 652: 5187, 948: 5186, 6333}, + {225, 225, 13: 225, 46: 225, 466: 6335, 997: 6334}, + // 3860 + {204, 204, 13: 6352, 46: 6350, 941: 6351, 6349, 1086: 6348, 6347}, + {126: 6340, 6338, 6339, 6341, 996: 6337, 1178: 6336}, + {224, 224, 13: 224, 46: 224, 126: 6340, 6338, 6339, 6341, 996: 6346}, + {223, 223, 13: 223, 46: 223, 126: 223, 223, 223, 223}, + {500: 2665, 724: 3968, 755: 6345}, // 3865 - {179, 179, 7: 179}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5145, 878: 5146, 910: 6327}, - {215, 215, 7: 5148, 14: 215, 58: 215, 463: 215, 651: 5192, 945: 5191, 6328}, - {223, 223, 14: 223, 58: 223, 463: 6330, 993: 6329}, - {202, 202, 14: 6347, 58: 6345, 938: 6346, 6344, 1083: 6343, 6342}, + {500: 2665, 724: 3968, 755: 6344}, + {500: 2665, 724: 3968, 755: 6343}, + {500: 2665, 724: 3968, 755: 6342}, + {218, 218, 13: 218, 46: 218, 126: 218, 218, 218, 218}, + {219, 219, 13: 219, 46: 219, 126: 219, 219, 219, 219}, // 3870 - {126: 6335, 6333, 6334, 6336, 992: 6332, 1173: 6331}, - {222, 222, 14: 222, 58: 222, 126: 6335, 6333, 6334, 6336, 992: 6341}, - {221, 221, 14: 221, 58: 221, 126: 221, 221, 221, 221}, - {496: 2650, 725: 3950, 751: 6340}, - {496: 2650, 725: 3950, 751: 6339}, + {220, 220, 13: 220, 46: 220, 126: 220, 220, 220, 220}, + {221, 221, 13: 221, 46: 221, 126: 221, 221, 221, 221}, + {222, 222, 13: 222, 46: 222, 126: 222, 222, 222, 222}, + {235, 235}, + {203, 203, 13: 6352, 46: 6350, 941: 6351, 6362}, // 3875 - {496: 2650, 725: 3950, 751: 6338}, - {496: 2650, 725: 3950, 751: 6337}, - {216, 216, 14: 216, 58: 216, 126: 216, 216, 216, 216}, - {217, 217, 14: 217, 58: 217, 126: 217, 217, 217, 217}, - {218, 218, 14: 218, 58: 218, 126: 218, 218, 218, 218}, + {202, 202, 13: 202, 46: 202}, + {488: 6361, 961: 6360}, + {198, 198, 13: 198, 46: 198, 204: 6356, 471: 6357, 573: 6355}, + {327: 6353}, + {193, 193, 13: 193, 46: 193, 204: 193, 471: 193, 573: 193, 1170: 6354}, // 3880 - {219, 219, 14: 219, 58: 219, 126: 219, 219, 219, 219}, - {220, 220, 14: 220, 58: 220, 126: 220, 220, 220, 220}, - {233, 233}, - {201, 201, 14: 6347, 58: 6345, 938: 6346, 6357}, - {200, 200, 14: 200, 58: 200}, + {194, 194, 13: 194, 46: 194, 204: 194, 471: 194, 573: 194}, + {500: 2665, 724: 3968, 755: 6358}, + {196, 196, 13: 196, 46: 196}, + {195, 195, 13: 195, 46: 195}, + {106: 6359}, // 3885 - {486: 6356, 958: 6355}, - {196, 196, 14: 196, 58: 196, 204: 6351, 467: 6352, 570: 6350}, - {322: 6348}, - {191, 191, 14: 191, 58: 191, 204: 191, 467: 191, 570: 191, 1165: 6349}, - {192, 192, 14: 192, 58: 192, 204: 192, 467: 192, 570: 192}, + {197, 197, 13: 197, 46: 197}, + {200, 200, 13: 200, 46: 200}, + {199, 199, 13: 199, 46: 199}, + {201, 201, 13: 201, 46: 201}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6364, 2691, 2692, 2690}, // 3890 - {496: 2650, 725: 3950, 751: 6353}, - {194, 194, 14: 194, 58: 194}, - {193, 193, 14: 193, 58: 193}, - {106: 6354}, - {195, 195, 14: 195, 58: 195}, + {490: 6365}, + {468: 6366}, + {1917, 1917, 15: 1917, 48: 1917, 50: 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 137: 6369, 464: 1917, 499: 6368, 644: 1917, 1030: 6367}, + {1974, 1974, 15: 1974, 48: 1974, 50: 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 464: 1974, 644: 1974, 886: 6374}, + {1916, 1916, 15: 1916, 48: 1916, 50: 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 1916, 464: 1916, 644: 1916}, // 3895 - {198, 198, 14: 198, 58: 198}, - {197, 197, 14: 197, 58: 197}, - {199, 199, 14: 199, 58: 199}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6359, 2676, 2677, 2675}, - {490: 6360}, + {195: 6372, 380: 6373, 616: 6371, 642: 6370}, + {1915, 1915, 15: 1915, 48: 1915, 50: 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 464: 1915, 644: 1915}, + {1914, 1914, 15: 1914, 48: 1914, 50: 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 464: 1914, 644: 1914}, + {1913, 1913, 15: 1913, 48: 1913, 50: 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 464: 1913, 644: 1913}, + {1912, 1912, 15: 1912, 48: 1912, 50: 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 464: 1912, 644: 1912}, // 3900 - {464: 6361}, - {1910, 1910, 27: 1910, 59: 1910, 61: 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 137: 6364, 461: 1910, 494: 6363, 643: 1910, 1026: 6362}, - {1967, 1967, 27: 1967, 59: 1967, 61: 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 461: 1967, 643: 1967, 886: 6369}, - {1909, 1909, 27: 1909, 59: 1909, 61: 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 461: 1909, 643: 1909}, - {194: 6367, 376: 6368, 633: 6366, 641: 6365}, + {1929, 1929, 15: 6099, 48: 6075, 50: 6095, 6088, 6078, 6074, 6082, 6086, 6098, 6081, 6087, 6085, 6083, 6096, 6089, 6077, 6097, 6076, 6079, 6080, 6084, 464: 6090, 644: 6100, 882: 6092, 6091, 6094, 6073, 887: 6093}, + {16: 2053, 81: 2053, 99: 2053, 139: 2053, 659: 2053}, + {99: 2048, 139: 6425, 659: 2048, 1316: 6424}, + {489: 6420}, + {159: 6379}, // 3905 - {1908, 1908, 27: 1908, 59: 1908, 61: 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 461: 1908, 643: 1908}, - {1907, 1907, 27: 1907, 59: 1907, 61: 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 461: 1907, 643: 1907}, - {1906, 1906, 27: 1906, 59: 1906, 61: 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 461: 1906, 643: 1906}, - {1905, 1905, 27: 1905, 59: 1905, 61: 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 461: 1905, 643: 1905}, - {1922, 1922, 27: 6056, 59: 6032, 61: 6052, 6045, 6035, 6031, 6039, 6043, 6055, 6038, 6044, 6042, 6040, 6053, 6046, 6034, 6054, 6033, 6036, 6037, 6041, 461: 6047, 643: 6057, 882: 6049, 6048, 6051, 6030, 887: 6050}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6380}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4894, 2691, 2692, 2690, 874: 6381}, + {86: 6385, 88: 6390, 6392, 6386, 6391, 6394, 6388, 6384, 6389, 6393, 6387, 862: 6382, 1088: 6383}, + {2469, 2469, 7: 2469, 86: 2469, 88: 2469, 2469, 2469, 2469, 2469, 2469, 2469, 2469, 2469, 2469}, + {52, 52, 7: 6418, 86: 6385, 88: 6390, 6392, 6386, 6391, 6394, 6388, 6384, 6389, 6393, 6387, 862: 6417}, // 3910 - {16: 2046, 92: 2046, 99: 2046, 139: 2046, 658: 2046}, - {99: 2041, 139: 6387, 658: 2041, 1312: 6386}, - {485: 6382}, - {158: 6374}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6375}, + {468: 2006, 489: 4192, 727: 6415}, + {468: 2006, 489: 4192, 727: 6413}, + {489: 4192, 500: 2006, 727: 6411}, + {489: 4192, 500: 2006, 727: 6409}, + {489: 4192, 500: 2006, 727: 6407}, // 3915 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4877, 2676, 2677, 2675, 873: 6376}, - {15: 4093, 17: 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 761: 6377, 1085: 6378}, - {2455, 2455, 7: 2455, 15: 2455, 17: 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455, 2455}, - {52, 52, 7: 6380, 15: 4093, 17: 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 761: 6379}, - {2454, 2454, 7: 2454, 15: 2454, 17: 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454, 2454}, + {468: 2006, 489: 4192, 727: 6405}, + {468: 2006, 489: 4192, 727: 6403}, + {468: 2006, 489: 4192, 727: 6401}, + {468: 2006, 489: 4192, 727: 6399}, + {468: 2006, 489: 4192, 727: 6397}, // 3920 - {15: 4093, 17: 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 761: 6381}, - {2453, 2453, 7: 2453, 15: 2453, 17: 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453, 2453}, - {344: 6384, 382: 6385, 392: 6383}, - {99: 2044, 139: 2044, 658: 2044}, - {99: 2043, 139: 2043, 658: 2043}, + {468: 2006, 489: 4192, 727: 6395}, + {468: 6396}, + {2456, 2456, 7: 2456, 86: 2456, 88: 2456, 2456, 2456, 2456, 2456, 2456, 2456, 2456, 2456, 2456}, + {468: 6398}, + {2457, 2457, 7: 2457, 86: 2457, 88: 2457, 2457, 2457, 2457, 2457, 2457, 2457, 2457, 2457, 2457}, // 3925 - {99: 2042, 139: 2042, 658: 2042}, - {99: 2039, 658: 6391, 1315: 6390}, - {485: 6388}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 6389}, - {99: 2040, 658: 2040}, + {468: 6400}, + {2458, 2458, 7: 2458, 86: 2458, 88: 2458, 2458, 2458, 2458, 2458, 2458, 2458, 2458, 2458, 2458}, + {468: 6402}, + {2459, 2459, 7: 2459, 86: 2459, 88: 2459, 2459, 2459, 2459, 2459, 2459, 2459, 2459, 2459, 2459}, + {468: 6404}, // 3930 - {99: 6395}, - {369: 6392}, - {139: 6393, 335: 6394}, - {99: 2038}, - {99: 2037}, + {2460, 2460, 7: 2460, 86: 2460, 88: 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460}, + {468: 6406}, + {2461, 2461, 7: 2461, 86: 2461, 88: 2461, 2461, 2461, 2461, 2461, 2461, 2461, 2461, 2461, 2461}, + {500: 2665, 724: 2664, 734: 6408}, + {2462, 2462, 7: 2462, 86: 2462, 88: 2462, 2462, 2462, 2462, 2462, 2462, 2462, 2462, 2462, 2462}, // 3935 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6397, 1314: 6396}, - {462: 6399, 468: 2035, 1313: 6398}, - {462: 2036, 468: 2036}, - {468: 6405}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6401, 2676, 2677, 2675, 1167: 6400}, + {500: 2665, 724: 2664, 734: 6410}, + {2463, 2463, 7: 2463, 86: 2463, 88: 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463, 2463}, + {500: 2665, 724: 2664, 734: 6412}, + {2464, 2464, 7: 2464, 86: 2464, 88: 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464}, + {468: 6414}, // 3940 - {7: 6403, 57: 6402}, - {7: 2033, 57: 2033}, - {468: 2034}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6404, 2676, 2677, 2675}, - {7: 2032, 57: 2032}, + {2465, 2465, 7: 2465, 86: 2465, 88: 2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465, 2465}, + {468: 6416}, + {2466, 2466, 7: 2466, 86: 2466, 88: 2466, 2466, 2466, 2466, 2466, 2466, 2466, 2466, 2466, 2466}, + {2468, 2468, 7: 2468, 86: 2468, 88: 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468, 2468}, + {86: 6385, 88: 6390, 6392, 6386, 6391, 6394, 6388, 6384, 6389, 6393, 6387, 862: 6419}, // 3945 - {462: 2509, 2508, 487: 2507, 556: 2506, 634: 2502, 699: 6409, 741: 6407, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 6408, 6406, 3779, 1177: 6410}, - {2054, 2054, 463: 2054}, - {2053, 2053, 463: 2053, 469: 787, 479: 787, 787}, - {2052, 2052, 463: 2052}, - {2051, 2051, 463: 2051, 469: 786, 479: 786, 786, 483: 2642, 491: 2643, 493: 2639, 756: 3790, 3791}, + {2467, 2467, 7: 2467, 86: 2467, 88: 2467, 2467, 2467, 2467, 2467, 2467, 2467, 2467, 2467, 2467}, + {349: 6422, 386: 6423, 395: 6421}, + {99: 2051, 139: 2051, 659: 2051}, + {99: 2050, 139: 2050, 659: 2050}, + {99: 2049, 139: 2049, 659: 2049}, // 3950 - {2031, 2031, 463: 6412, 1311: 6411}, - {2048, 2048}, - {136: 6414, 304: 6413}, - {574: 6417}, - {574: 6415}, + {99: 2046, 659: 6429, 1319: 6428}, + {489: 6426}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6427}, + {99: 2047, 659: 2047}, + {99: 6433}, // 3955 - {894: 6416}, - {2029, 2029}, - {894: 6418}, - {2030, 2030}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5227, 2676, 2677, 2675, 805: 6420}, + {373: 6430}, + {139: 6431, 340: 6432}, + {99: 2045}, + {99: 2044}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6435, 1318: 6434}, // 3960 - {2127, 2127, 13: 2118, 15: 4093, 2118, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 28: 2118, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 838: 6425, 920: 6424, 1178: 6421}, - {2135, 2135}, - {13: 3735, 16: 4105, 28: 6429, 470: 6428, 489: 3736, 637: 3734, 762: 6427, 767: 6430}, - {2128, 2128, 13: 2128, 15: 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128, 2128, 28: 2128, 467: 2128, 470: 2128, 489: 2128, 637: 2128}, - {2126, 2126, 13: 2118, 15: 4093, 2118, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 28: 2118, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 838: 6426}, + {465: 6437, 470: 2042, 1317: 6436}, + {465: 2043, 470: 2043}, + {470: 6443}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6439, 2691, 2692, 2690, 1172: 6438}, + {7: 6441, 47: 6440}, // 3965 - {2125, 2125, 13: 2125, 15: 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 28: 2125, 467: 2125, 470: 2125, 489: 2125, 637: 2125}, - {2124, 2124, 13: 2124, 15: 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 28: 2124, 467: 2124, 470: 2124, 489: 2124, 637: 2124}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 532: 1999, 726: 6435}, - {2: 1999, 1999, 1999, 1999, 1999, 8: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 58: 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 464: 1999, 485: 4187, 532: 1999, 726: 6433}, - {464: 1999, 485: 4187, 726: 6431}, + {7: 2040, 47: 2040}, + {470: 2041}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6442, 2691, 2692, 2690}, + {7: 2039, 47: 2039}, + {465: 2523, 2522, 493: 2521, 562: 2520, 637: 2516, 700: 6447, 742: 6445, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 6446, 6444, 3797, 1182: 6448}, // 3970 - {2129, 2129, 13: 2129, 15: 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, 28: 2129, 467: 2129, 470: 2129, 489: 2129, 637: 2129}, - {464: 4205, 1024: 6432}, - {2130, 2130, 13: 2130, 15: 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130, 2130, 28: 2130, 467: 2130, 470: 2130, 489: 2130, 637: 2130}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3390, 653: 3392, 2676, 2677, 2675, 728: 3389, 860: 6434}, - {2131, 2131, 13: 2131, 15: 2131, 2131, 2131, 2131, 2131, 2131, 2131, 2131, 2131, 2131, 2131, 2131, 28: 2131, 467: 2131, 470: 2131, 489: 2131, 637: 2131}, + {2061, 2061, 466: 2061}, + {2060, 2060, 466: 2060, 472: 791, 480: 791, 791}, + {2059, 2059, 466: 2059}, + {2058, 2058, 466: 2058, 472: 790, 480: 790, 790, 486: 2657, 491: 2658, 494: 2654, 757: 3808, 3809}, + {2038, 2038, 466: 6450, 1315: 6449}, // 3975 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 532: 3660, 653: 3392, 2676, 2677, 2675, 728: 3659, 797: 6436}, - {2132, 2132, 13: 2132, 15: 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 2132, 28: 2132, 467: 2132, 470: 2132, 489: 2132, 637: 2132}, - {2: 1815, 1815, 1815, 1815, 1815, 8: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 58: 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 1815, 555: 4717, 775: 6438}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6439, 2676, 2677, 2675}, - {93: 4750, 461: 1798, 471: 4749, 847: 6441, 1211: 6440}, + {2055, 2055}, + {136: 6452, 307: 6451}, + {574: 6455}, + {574: 6453}, + {894: 6454}, // 3980 - {461: 6442}, - {461: 1797}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6443}, - {462: 6444}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 462: 4523, 653: 4040, 2676, 2677, 2675, 733: 4522, 816: 4521, 825: 6445}, + {2036, 2036}, + {894: 6456}, + {2037, 2037}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5222, 2691, 2692, 2690, 804: 6458}, + {2134, 2134, 14: 2125, 16: 2125, 19: 2125, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 770: 6461, 781: 6460, 838: 6464, 920: 6463, 1183: 6459}, // 3985 - {7: 4532, 57: 6446}, - {1809, 1809, 4: 1809, 29: 1809, 92: 1809, 1809, 1809, 1809, 1809, 1809, 463: 1809, 471: 1809, 486: 1809, 867: 6447}, - {2146, 2146, 4: 4746, 29: 4743, 92: 4141, 4750, 4610, 4335, 4611, 4334, 463: 4745, 471: 4749, 486: 4142, 845: 4747, 847: 4744, 857: 4748, 6259, 866: 4742, 870: 6258, 1046: 6448}, - {2153, 2153}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6450, 2676, 2677, 2675}, + {2143, 2143}, + {14: 3753, 16: 4110, 19: 6472, 474: 6471, 498: 3754, 638: 3752, 762: 6470, 770: 6473}, + {2136, 2136, 14: 2136, 16: 2136, 19: 2136, 471: 2136, 474: 2136, 496: 2136, 498: 2136, 638: 2136}, + {282: 6466}, + {2133, 2133, 14: 2125, 16: 2125, 19: 2125, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 770: 6461, 781: 6460, 838: 6465}, // 3990 - {462: 6451}, - {222: 4779, 231: 4781, 234: 4780, 1120: 6452}, - {57: 6453}, - {461: 6454}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6455}, + {2132, 2132, 14: 2132, 16: 2132, 19: 2132, 471: 2132, 474: 2132, 496: 2132, 498: 2132, 638: 2132}, + {2131, 2131, 14: 2131, 16: 2131, 19: 2131, 471: 2131, 474: 2131, 496: 2131, 498: 2131, 638: 2131}, + {267: 6467}, + {500: 2665, 724: 2664, 734: 6468}, + {2442, 2442, 14: 2442, 16: 2442, 19: 2442, 176: 4870, 471: 2442, 474: 2442, 496: 2442, 498: 2442, 638: 2442, 1063: 6469}, // 3995 - {462: 6456}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4040, 2676, 2677, 2675, 733: 4041, 798: 6457}, - {7: 4043, 57: 6458}, - {2155, 2155}, - {2247, 2247}, + {2135, 2135, 14: 2135, 16: 2135, 19: 2135, 471: 2135, 474: 2135, 496: 2135, 498: 2135, 638: 2135}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 536: 2006, 727: 6478}, + {2: 2006, 2006, 2006, 2006, 2006, 8: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 48: 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 468: 2006, 489: 4192, 536: 2006, 727: 6476}, + {468: 2006, 489: 4192, 727: 6474}, + {2137, 2137, 14: 2137, 16: 2137, 19: 2137, 471: 2137, 474: 2137, 496: 2137, 498: 2137, 638: 2137}, // 4000 - {2272, 2272}, - {2278, 2278, 463: 6463, 661: 6462}, - {150: 6470, 677: 6469}, - {305: 6465, 313: 6464}, - {61: 6468}, + {468: 4210, 1028: 6475}, + {2138, 2138, 14: 2138, 16: 2138, 19: 2138, 471: 2138, 474: 2138, 496: 2138, 498: 2138, 638: 2138}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3408, 654: 3410, 2691, 2692, 2690, 729: 3407, 860: 6477}, + {2139, 2139, 14: 2139, 16: 2139, 19: 2139, 471: 2139, 474: 2139, 496: 2139, 498: 2139, 638: 2139}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 536: 3678, 654: 3410, 2691, 2692, 2690, 729: 3677, 796: 6479}, // 4005 - {312: 6466}, - {150: 6467}, - {2275, 2275}, - {2276, 2276}, - {2277, 2277}, + {2140, 2140, 14: 2140, 16: 2140, 19: 2140, 471: 2140, 474: 2140, 496: 2140, 498: 2140, 638: 2140}, + {2: 1822, 1822, 1822, 1822, 1822, 8: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 48: 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 1822, 558: 4734, 774: 6481}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6482, 2691, 2692, 2690}, + {82: 4767, 464: 1805, 473: 4766, 847: 6484, 1216: 6483}, + {464: 6485}, // 4010 - {2274, 2274, 663: 5302, 912: 6471}, - {2273, 2273}, - {2280, 2280}, - {2279, 2279}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6487, 786: 6486}, + {464: 1804}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6486}, + {465: 6487}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 465: 4528, 654: 4058, 2691, 2692, 2690, 735: 4527, 815: 4526, 824: 6488}, + {7: 4537, 47: 6489}, // 4015 - {556: 6476}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6477}, - {478: 6479, 638: 6478}, - {880, 880, 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 880, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 6484}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 6480}, + {1816, 1816, 4: 1816, 17: 1816, 81: 1816, 1816, 1816, 1816, 1816, 87: 1816, 466: 1816, 473: 1816, 488: 1816, 868: 6490}, + {2154, 2154, 4: 4763, 17: 4760, 81: 4146, 4767, 4627, 4340, 4628, 87: 4339, 466: 4762, 473: 4766, 488: 4147, 845: 4764, 847: 4761, 857: 4765, 6264, 867: 4759, 871: 6263, 1050: 6491}, + {2161, 2161}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6493, 2691, 2692, 2690}, + {465: 6494}, // 4020 - {7: 4642, 638: 6481}, - {880, 880, 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 880, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 6482}, - {2296, 2296, 7: 4923, 463: 4904, 794: 6483}, - {2304, 2304}, - {2296, 2296, 7: 4923, 463: 4904, 794: 6485}, + {222: 4796, 231: 4798, 234: 4797, 1124: 6495}, + {47: 6496}, + {464: 6497}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6498}, + {465: 6499}, // 4025 - {2307, 2307}, - {2299, 2299, 7: 3823, 159: 6507, 463: 2299, 641: 6506, 966: 6517}, - {1023, 1023, 7: 1023, 98: 6492, 159: 1023, 463: 1023, 478: 6489, 638: 6488, 641: 1023, 644: 6490, 659: 6491}, - {880, 880, 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 880, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 6515}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4641, 2676, 2677, 2675, 779: 6502}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4058, 2691, 2692, 2690, 735: 4059, 797: 6500}, + {7: 4061, 47: 6501}, + {2163, 2163}, + {2263, 2263}, + {2288, 2288}, // 4030 - {246: 6498}, - {246: 6495}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5677, 2676, 2677, 2675, 864: 6493}, - {2296, 2296, 7: 5679, 463: 4904, 794: 6494}, - {2301, 2301}, + {2294, 2294, 466: 6506, 662: 6505}, + {151: 6513, 678: 6512}, + {308: 6508, 316: 6507}, + {50: 6511}, + {315: 6509}, // 4035 - {461: 6496}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5677, 2676, 2677, 2675, 864: 6497}, - {2302, 2302, 7: 5679}, - {461: 6499}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5677, 2676, 2677, 2675, 864: 6500}, + {151: 6510}, + {2291, 2291}, + {2292, 2292}, + {2293, 2293}, + {2290, 2290, 664: 5297, 912: 6514}, // 4040 - {2296, 2296, 7: 5679, 463: 4904, 794: 6501}, - {2303, 2303}, - {2299, 2299, 7: 4642, 98: 6505, 159: 6507, 463: 2299, 638: 6504, 641: 6506, 966: 6503}, - {2296, 2296, 463: 4904, 794: 6514}, - {880, 880, 2912, 2760, 2796, 2914, 2687, 880, 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 463: 880, 576: 4921, 653: 4920, 2676, 2677, 2675, 846: 6512}, + {2289, 2289}, + {2296, 2296}, + {2295, 2295}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6530, 785: 6529}, + {562: 6519}, // 4045 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 5677, 2676, 2677, 2675, 864: 6510}, - {98: 6509}, - {98: 6508}, - {2297, 2297, 463: 2297}, - {2298, 2298, 463: 2298}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6520}, + {483: 6522, 640: 6521}, + {884, 884, 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 884, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 6527}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 6523}, + {7: 4659, 640: 6524}, // 4050 - {2296, 2296, 7: 5679, 463: 4904, 794: 6511}, - {2300, 2300}, - {2296, 2296, 7: 4923, 463: 4904, 794: 6513}, - {2305, 2305}, - {2306, 2306}, + {884, 884, 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 884, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 6525}, + {2312, 2312, 7: 4918, 466: 4899, 793: 6526}, + {2320, 2320}, + {2312, 2312, 7: 4918, 466: 4899, 793: 6528}, + {2323, 2323}, // 4055 - {2296, 2296, 7: 4923, 463: 4904, 794: 6516}, - {2308, 2308}, - {2296, 2296, 463: 4904, 794: 6518}, - {2309, 2309}, - {556: 6524}, + {2315, 2315, 7: 3841, 160: 6550, 466: 2315, 642: 6549, 969: 6560}, + {1027, 1027, 7: 1027, 98: 6535, 160: 1027, 466: 1027, 483: 6532, 640: 6531, 642: 1027, 645: 6533, 660: 6534}, + {884, 884, 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 884, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 6558}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4658, 2691, 2692, 2690, 778: 6545}, + {246: 6541}, // 4060 - {482: 6522}, - {556: 2311}, - {478: 6523, 556: 2312}, - {556: 2310}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6525}, - // 4065 - {478: 5296, 544: 894, 638: 894, 649: 894, 849: 6526}, - {544: 6529, 638: 6528, 649: 6530, 1115: 6527}, + {246: 6538}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5718, 2691, 2692, 2690, 865: 6536}, + {2312, 2312, 7: 5720, 466: 4899, 793: 6537}, {2317, 2317}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6537, 2676, 2677, 2675}, - {462: 3796, 829: 6532}, + {464: 6539}, + // 4065 + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5718, 2691, 2692, 2690, 865: 6540}, + {2318, 2318, 7: 5720}, + {464: 6542}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5718, 2691, 2692, 2690, 865: 6543}, + {2312, 2312, 7: 5720, 466: 4899, 793: 6544}, // 4070 - {462: 3796, 829: 5813, 960: 6531}, - {2314, 2314, 7: 5814}, - {495: 6533}, - {462: 3796, 829: 6534}, - {15: 6535}, + {2319, 2319}, + {2315, 2315, 7: 4659, 98: 6548, 160: 6550, 466: 2315, 640: 6547, 642: 6549, 969: 6546}, + {2312, 2312, 466: 4899, 793: 6557}, + {884, 884, 2930, 2776, 2812, 2932, 2703, 884, 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 466: 884, 576: 4916, 654: 4915, 2691, 2692, 2690, 846: 6555}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 5718, 2691, 2692, 2690, 865: 6553}, // 4075 - {496: 2650, 725: 3950, 751: 6536}, - {2315, 2315}, - {544: 6529, 649: 6530, 1115: 6538}, - {2316, 2316}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6540}, + {98: 6552}, + {98: 6551}, + {2313, 2313, 466: 2313}, + {2314, 2314, 466: 2314}, + {2312, 2312, 7: 5720, 466: 4899, 793: 6554}, // 4080 - {2319, 2319, 640: 6542, 1194: 6541}, - {2320, 2320}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6543, 2676, 2677, 2675}, - {2318, 2318}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 649: 6545, 653: 3820, 2676, 2677, 2675, 727: 6546}, - // 4085 - {252: 6548}, - {2322, 2322, 496: 2650, 725: 3950, 751: 6547}, + {2316, 2316}, + {2312, 2312, 7: 4918, 466: 4899, 793: 6556}, {2321, 2321}, - {496: 2650, 725: 3950, 751: 6549}, - {2323, 2323}, + {2322, 2322}, + {2312, 2312, 7: 4918, 466: 4899, 793: 6559}, + // 4085 + {2324, 2324}, + {2312, 2312, 466: 4899, 793: 6561}, + {2325, 2325}, + {562: 6567}, + {485: 6565}, // 4090 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6561, 1130: 6560, 1300: 6559}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 6554, 1135: 6553, 1305: 6552}, - {2327, 2327, 7: 6557}, - {2326, 2326, 7: 2326}, - {640: 6555}, + {562: 2327}, + {483: 6566, 562: 2328}, + {562: 2326}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6568}, + {483: 5291, 547: 898, 640: 898, 650: 898, 849: 6569}, // 4095 - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 6556}, - {2324, 2324, 7: 2324}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 6554, 1135: 6558}, - {2325, 2325, 7: 2325}, - {2331, 2331, 7: 6564}, + {547: 6572, 640: 6571, 650: 6573, 1119: 6570}, + {2333, 2333}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6580, 2691, 2692, 2690}, + {465: 3814, 828: 6575}, + {465: 3814, 828: 5854, 963: 6574}, // 4100 - {2330, 2330, 7: 2330}, - {640: 6562}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6563}, - {2328, 2328, 7: 2328}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6561, 1130: 6565}, + {2330, 2330, 7: 5855}, + {497: 6576}, + {465: 3814, 828: 6577}, + {86: 6578}, + {500: 2665, 724: 3968, 755: 6579}, // 4105 - {2329, 2329, 7: 2329}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 6615, 2118, 6620, 6622, 6616, 6621, 6624, 6618, 6614, 6619, 6623, 6617, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 653: 5227, 2676, 2677, 2675, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 805: 6626, 838: 6425, 920: 6627}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 6605, 2676, 2677, 2675}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 464: 1817, 555: 4357, 559: 1817, 768: 6594}, - {266: 6588, 1213: 6587}, + {2331, 2331}, + {547: 6572, 650: 6573, 1119: 6581}, + {2332, 2332}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6583}, + {2335, 2335, 641: 6585, 1199: 6584}, // 4110 - {158: 6583}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6572}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 3820, 2676, 2677, 2675, 727: 6573}, - {81: 6288, 6285, 6291, 6292, 6293, 6286, 6284, 6294, 6290, 6287, 6577, 647: 6289, 901: 6576, 972: 6575, 1148: 6574}, - {25, 25, 81: 6288, 6285, 6291, 6292, 6293, 6286, 6284, 6294, 6290, 6287, 6577, 647: 6289, 901: 6576, 972: 6582}, + {2336, 2336}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6586, 2691, 2692, 2690}, + {2334, 2334}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 650: 6588, 654: 3838, 2691, 2692, 2690, 728: 6589}, + {252: 6591}, // 4115 - {24, 24, 81: 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 647: 24}, - {22, 22, 81: 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 647: 22}, - {21, 21, 81: 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 463: 6579, 474: 1999, 1999, 485: 4187, 496: 1999, 647: 21, 726: 6578}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6581}, - {474: 3954, 3953, 496: 2650, 725: 3950, 751: 3952, 803: 6580}, + {2338, 2338, 500: 2665, 724: 3968, 755: 6590}, + {2337, 2337}, + {500: 2665, 724: 3968, 755: 6592}, + {2339, 2339}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6604, 1134: 6603, 1304: 6602}, // 4120 - {19, 19, 81: 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 647: 19}, - {20, 20, 81: 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 647: 20}, - {23, 23, 81: 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 647: 23}, - {2: 1817, 1817, 1817, 1817, 1817, 8: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 58: 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 1817, 555: 4357, 768: 6584}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 3282, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 653: 4877, 2676, 2677, 2675, 873: 6585}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6597, 1139: 6596, 1309: 6595}, + {2343, 2343, 7: 6600}, + {2342, 2342, 7: 2342}, + {641: 6598}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6599}, // 4125 - {15: 4093, 17: 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 761: 6377, 1085: 6586}, - {51, 51, 7: 6380, 15: 4093, 17: 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 761: 6379}, - {229, 229}, - {386: 6589}, - {228, 228, 81: 6590}, + {2340, 2340, 7: 2340}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 6597, 1139: 6601}, + {2341, 2341, 7: 2341}, + {2347, 2347, 7: 6607}, + {2346, 2346, 7: 2346}, // 4130 - {151: 6591}, - {461: 6592}, - {197: 6593}, - {227, 227}, - {2: 2912, 2760, 2796, 2914, 2687, 8: 2733, 2688, 2819, 2931, 2924, 3270, 3275, 3046, 3075, 3125, 3129, 3118, 3128, 3130, 3121, 3126, 3127, 3131, 3124, 2799, 2719, 2801, 2775, 2722, 2711, 2744, 2803, 2804, 2908, 2798, 2932, 3034, 3033, 2686, 2797, 2800, 2811, 2751, 2755, 2807, 2917, 2766, 2845, 2684, 2685, 2844, 2916, 2683, 2929, 58: 2889, 3000, 2765, 2768, 2983, 2980, 2972, 2984, 2987, 2988, 2985, 2989, 2990, 2986, 2979, 2991, 2974, 2975, 2978, 2981, 2982, 2992, 3278, 2831, 2769, 2959, 2958, 2960, 2955, 2954, 2961, 2956, 2957, 2761, 2874, 2944, 3007, 2942, 3008, 2943, 2702, 2834, 2773, 3268, 2696, 2839, 2930, 3279, 3272, 2731, 3291, 2941, 2774, 3274, 3289, 3290, 3288, 3284, 2933, 2934, 2935, 2936, 2937, 2938, 2940, 3280, 2859, 2770, 2863, 2864, 2865, 2866, 2855, 2883, 2926, 2885, 2704, 2884, 2746, 3005, 2836, 2875, 2741, 2794, 2950, 2856, 2815, 2705, 2710, 2721, 2736, 2945, 2818, 2763, 2785, 2691, 2835, 2720, 2740, 3106, 2994, 3079, 2871, 2783, 6595, 3267, 2750, 3077, 2754, 2762, 2784, 2995, 2695, 2713, 3271, 2734, 2812, 2813, 2964, 2892, 3001, 3002, 2966, 2830, 3003, 2922, 3074, 3028, 2962, 2764, 2862, 3276, 2920, 2822, 2681, 2827, 2717, 2718, 2828, 2725, 2735, 2738, 2726, 2948, 2973, 2788, 2887, 3076, 2854, 2825, 2882, 2925, 2814, 3029, 2772, 3039, 3277, 2921, 3010, 2970, 2832, 2893, 2694, 3011, 3014, 2700, 2996, 3015, 3287, 2706, 2707, 2895, 3057, 3017, 2891, 2715, 3019, 2904, 2928, 2915, 2716, 3021, 2923, 2729, 2953, 3113, 2739, 2742, 2905, 2951, 3066, 2946, 3067, 2899, 3023, 3022, 2949, 3006, 2837, 3292, 3024, 3025, 2841, 2897, 3026, 3004, 2758, 2759, 2870, 2976, 2872, 3080, 3027, 2918, 2919, 2860, 2767, 2901, 3042, 3030, 2682, 3089, 2900, 3096, 3097, 3098, 3099, 3101, 3100, 3102, 3103, 3041, 2780, 2678, 2679, 2952, 2969, 2689, 2971, 2997, 2692, 2693, 3055, 3012, 3013, 2697, 2881, 2698, 2699, 2868, 3283, 3016, 2816, 2703, 2708, 2709, 3018, 3020, 3061, 3062, 2723, 2724, 2838, 2728, 2888, 3107, 2730, 2898, 3273, 2833, 2809, 3036, 2906, 2927, 2890, 2824, 3068, 2876, 2894, 2939, 2747, 2745, 2821, 2907, 2802, 2963, 2877, 2805, 2806, 3293, 2840, 2749, 2771, 3043, 3108, 2752, 2910, 2913, 2965, 2999, 3044, 3009, 2850, 2851, 2857, 3072, 3047, 3073, 2947, 3048, 2977, 2880, 2820, 2911, 2869, 3035, 3032, 3031, 3081, 2896, 2998, 2909, 3093, 3038, 2878, 2776, 2777, 3040, 3116, 3104, 2902, 2781, 2810, 2817, 2879, 3122, 2786, 3045, 2886, 3049, 2791, 3050, 3051, 3269, 3052, 3053, 3054, 3109, 3056, 3058, 3059, 3060, 2727, 2873, 3110, 2843, 3063, 2732, 3117, 3296, 3065, 3300, 3299, 3294, 3119, 3120, 3070, 3069, 2748, 3071, 3078, 2849, 2756, 2757, 2993, 2867, 3285, 3286, 3295, 2861, 2792, 2903, 2823, 2826, 3111, 3085, 3086, 3087, 3088, 3112, 3082, 3083, 3084, 2842, 3037, 3297, 3298, 3105, 3090, 3091, 3092, 3123, 3281, 464: 3391, 559: 5128, 653: 3392, 2676, 2677, 2675, 728: 5127, 763: 5145, 878: 5146, 910: 6596}, + {641: 6605}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6606}, + {2344, 2344, 7: 2344}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6604, 1134: 6608}, + {2345, 2345, 7: 2345}, // 4135 - {1670, 1670, 7: 1670, 14: 1670, 58: 1670, 141: 1670, 462: 6600, 1670, 558: 1670, 651: 1670, 657: 1670}, - {215, 215, 7: 5148, 14: 215, 58: 215, 463: 215, 651: 5192, 945: 5191, 6597}, - {223, 223, 14: 223, 58: 223, 463: 6330, 993: 6598}, - {202, 202, 14: 6347, 58: 6345, 938: 6346, 6344, 1083: 6343, 6599}, - {231, 231}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 2125, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 654: 5222, 2691, 2692, 2690, 770: 6461, 781: 6460, 804: 6658, 838: 6464, 920: 6659}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 6648, 2691, 2692, 2690}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 468: 1824, 558: 4362, 561: 1824, 771: 6637}, + {266: 6631, 1218: 6630}, + {159: 6626}, // 4140 - {57: 6601}, - {141: 6602}, - {649: 6603}, - {464: 5161, 880: 6604}, - {230, 230}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6615}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 3838, 2691, 2692, 2690, 728: 6616}, + {70: 6293, 6290, 6296, 6297, 6298, 6291, 6289, 6299, 6295, 6292, 6620, 648: 6294, 901: 6619, 975: 6618, 1152: 6617}, + {25, 25, 70: 6293, 6290, 6296, 6297, 6298, 6291, 6289, 6299, 6295, 6292, 6620, 648: 6294, 901: 6619, 975: 6625}, + {24, 24, 70: 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 648: 24}, // 4145 - {1910, 1910, 27: 1910, 59: 1910, 61: 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 137: 6364, 461: 1910, 494: 6363, 643: 1910, 1026: 6606}, - {1967, 1967, 27: 1967, 59: 1967, 61: 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 461: 1967, 643: 1967, 886: 6607}, - {1904, 1904, 27: 6056, 59: 6032, 61: 6052, 6045, 6035, 6031, 6039, 6043, 6055, 6038, 6044, 6042, 6040, 6053, 6046, 6034, 6054, 6033, 6036, 6037, 6041, 6609, 461: 6047, 643: 6057, 882: 6049, 6048, 6051, 6030, 887: 6050, 1207: 6608}, - {1919, 1919}, - {200: 6611, 641: 6610}, + {22, 22, 70: 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 648: 22}, + {21, 21, 70: 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 466: 6622, 477: 2006, 2006, 489: 4192, 500: 2006, 648: 21, 727: 6621}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6624}, + {477: 3972, 3971, 500: 2665, 724: 3968, 755: 3970, 802: 6623}, + {19, 19, 70: 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 648: 19}, // 4150 - {545, 545, 556: 6003, 954: 6613}, - {545, 545, 556: 6003, 954: 6612}, - {1902, 1902}, - {1903, 1903}, - {13: 1335, 15: 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 28: 1335, 464: 1999, 467: 1335, 470: 1335, 485: 4187, 489: 1335, 637: 1335, 726: 4898}, + {20, 20, 70: 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 648: 20}, + {23, 23, 70: 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 648: 23}, + {2: 1824, 1824, 1824, 1824, 1824, 8: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 48: 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 558: 4362, 771: 6627}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 3298, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 654: 4894, 2691, 2692, 2690, 874: 6628}, + {86: 6385, 88: 6390, 6392, 6386, 6391, 6394, 6388, 6384, 6389, 6393, 6387, 862: 6382, 1088: 6629}, // 4155 - {13: 1415, 15: 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 28: 1415, 464: 1999, 467: 1415, 470: 1415, 485: 4187, 489: 1415, 637: 1415, 726: 4896}, - {13: 1343, 15: 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 28: 1343, 467: 1343, 470: 1343, 485: 4187, 489: 1343, 496: 1999, 637: 1343, 726: 4894}, - {13: 1337, 15: 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 28: 1337, 467: 1337, 470: 1337, 485: 4187, 489: 1337, 496: 1999, 637: 1337, 726: 4892}, - {13: 1340, 15: 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340, 28: 1340, 467: 1340, 470: 1340, 485: 4187, 489: 1340, 496: 1999, 637: 1340, 726: 4890}, - {13: 1334, 15: 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 28: 1334, 464: 1999, 467: 1334, 470: 1334, 485: 4187, 489: 1334, 637: 1334, 726: 4888}, + {51, 51, 7: 6418, 86: 6385, 88: 6390, 6392, 6386, 6391, 6394, 6388, 6384, 6389, 6393, 6387, 862: 6417}, + {231, 231}, + {389: 6632}, + {230, 230, 70: 6633}, + {152: 6634}, // 4160 - {13: 1336, 15: 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 28: 1336, 464: 1999, 467: 1336, 470: 1336, 485: 4187, 489: 1336, 637: 1336, 726: 4886}, - {13: 1333, 15: 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 28: 1333, 464: 1999, 467: 1333, 470: 1333, 485: 4187, 489: 1333, 637: 1333, 726: 4884}, - {13: 1332, 15: 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 28: 1332, 464: 1999, 467: 1332, 470: 1332, 485: 4187, 489: 1332, 637: 1332, 726: 4882}, - {13: 1330, 15: 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, 28: 1330, 464: 1999, 467: 1330, 470: 1330, 485: 4187, 489: 1330, 637: 1330, 726: 4880}, - {13: 1331, 15: 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 28: 1331, 464: 1999, 467: 1331, 470: 1331, 485: 4187, 489: 1331, 637: 1331, 726: 4878}, + {464: 6635}, + {198: 6636}, + {229, 229}, + {2: 2930, 2776, 2812, 2932, 2703, 8: 2749, 2704, 2835, 2949, 2942, 3291, 3286, 2815, 3093, 2817, 2791, 2735, 2738, 2727, 2760, 2819, 2820, 2926, 2814, 2950, 3052, 3051, 2702, 2813, 2816, 2827, 2767, 2771, 2823, 2935, 2782, 2863, 2700, 2701, 2862, 2934, 2699, 2947, 2907, 48: 3018, 2781, 2784, 3001, 2998, 2990, 3002, 3005, 3006, 3003, 3007, 3008, 3004, 2997, 3009, 2992, 2993, 2996, 2999, 3000, 3010, 3294, 2849, 2785, 2977, 2976, 2978, 2973, 2972, 2979, 2974, 2975, 2777, 2892, 2962, 3025, 2960, 3026, 3064, 2961, 3143, 3147, 3136, 3146, 3148, 3139, 3144, 3145, 3149, 3142, 2718, 2852, 2789, 3284, 2712, 2857, 2948, 3295, 3288, 2747, 3307, 2959, 2790, 3290, 3305, 3306, 3304, 3300, 2951, 2952, 2953, 2954, 2955, 2956, 2958, 2786, 3296, 2877, 2881, 2882, 2883, 2884, 2873, 2901, 2944, 2903, 2720, 2902, 2762, 3023, 2854, 2893, 2757, 2810, 2968, 2874, 2831, 2721, 2726, 2737, 2752, 3283, 2963, 2834, 2779, 2801, 2707, 2853, 2736, 2756, 3124, 3012, 3097, 2889, 2799, 6638, 2766, 3095, 2770, 2778, 2800, 3013, 2711, 2729, 3287, 2750, 2828, 2829, 2966, 2982, 2910, 3019, 3020, 2984, 2848, 3021, 2940, 3092, 3046, 2980, 2780, 2880, 3292, 2938, 2838, 2696, 2843, 2733, 2734, 2845, 2741, 2751, 2754, 2742, 2991, 2804, 2905, 3094, 2872, 2841, 2900, 2943, 2830, 3047, 2788, 3057, 3293, 2939, 3028, 2988, 2850, 2911, 2710, 3029, 3032, 2716, 3014, 3033, 3303, 2722, 2723, 2913, 3075, 3035, 2909, 2731, 3037, 2922, 2946, 2933, 2732, 3039, 2941, 2745, 2971, 3131, 2755, 2758, 2923, 2969, 3084, 2964, 3085, 2917, 3041, 3040, 2967, 3024, 2855, 3308, 3042, 3043, 2859, 2915, 3044, 3022, 2774, 2775, 2888, 2965, 2994, 2890, 3098, 3045, 2936, 2937, 2878, 2783, 2919, 3060, 3048, 2698, 3107, 2918, 3058, 3114, 3115, 3116, 3117, 3119, 3118, 3120, 3121, 3059, 2796, 2693, 2694, 2970, 2987, 2705, 2989, 3015, 2697, 2708, 2709, 3073, 3030, 3031, 2713, 2899, 2714, 2715, 2886, 3299, 3034, 2832, 2719, 2724, 2725, 3036, 3038, 2844, 3079, 3080, 2846, 2739, 2740, 2856, 2744, 2906, 3125, 2746, 2916, 3289, 2851, 2825, 3054, 2924, 2945, 2908, 2840, 3086, 2894, 2912, 2957, 2763, 2761, 2837, 2925, 2818, 2981, 2895, 2821, 2822, 3309, 2858, 2765, 2787, 3061, 3126, 2768, 2928, 2931, 2983, 3017, 3062, 3027, 2868, 2869, 2875, 3090, 3065, 3091, 3066, 2995, 2898, 2836, 2929, 2887, 3053, 3050, 3049, 3099, 2914, 3016, 2927, 3111, 3056, 2896, 2792, 2793, 3134, 3122, 2920, 2797, 2826, 2833, 2897, 3140, 2802, 3063, 2904, 3312, 2807, 3068, 3069, 3285, 3070, 3071, 3072, 3127, 3074, 3076, 3077, 3078, 2743, 2891, 3128, 2861, 3081, 2748, 3135, 3313, 3083, 3318, 3317, 3310, 3137, 3138, 3088, 3087, 2764, 3089, 3096, 2867, 2772, 2773, 3011, 2885, 3301, 3302, 3311, 2879, 2808, 2921, 2839, 2842, 3129, 3103, 3104, 3105, 3106, 3130, 3314, 3101, 3102, 2860, 3055, 3315, 3316, 3123, 3108, 3109, 3110, 3141, 3297, 468: 3409, 561: 5123, 654: 3410, 2691, 2692, 2690, 729: 5122, 764: 5140, 879: 5141, 910: 6639}, + {1676, 1676, 7: 1676, 13: 1676, 46: 1676, 141: 1676, 465: 6643, 1676, 560: 1676, 652: 1676, 658: 1676}, // 4165 - {13: 1386, 15: 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 28: 1386, 158: 4870, 467: 1386, 470: 1386, 489: 1386, 637: 1386}, - {13: 2118, 15: 4093, 2118, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 28: 2118, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 838: 6425, 920: 6628}, - {2136, 2136, 13: 2118, 15: 4093, 2118, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 28: 2118, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 838: 6426}, - {2137, 2137, 13: 2118, 15: 4093, 2118, 4098, 4100, 4094, 4099, 4102, 4096, 4092, 4097, 4101, 4095, 28: 2118, 467: 4146, 470: 2118, 489: 2118, 637: 2118, 761: 4103, 767: 4104, 770: 6423, 782: 6422, 838: 6426}, - {1997, 1997, 59: 2489, 80: 2604, 82: 2470, 91: 2500, 145: 2472, 151: 2498, 153: 2469, 166: 2494, 198: 2519, 205: 2616, 208: 2465, 216: 2518, 2485, 2471, 233: 2497, 238: 2475, 241: 2495, 243: 2466, 245: 2501, 263: 2487, 267: 2486, 274: 2499, 276: 2467, 279: 2488, 290: 2480, 462: 2509, 2508, 486: 2612, 2507, 494: 2493, 501: 2517, 514: 2607, 518: 2483, 556: 2506, 2492, 634: 2502, 638: 2615, 643: 2468, 2606, 652: 2463, 659: 2474, 664: 2473, 669: 2516, 676: 2464, 699: 2513, 732: 2476, 741: 2515, 2503, 2504, 2505, 2514, 2512, 2511, 2510, 752: 2586, 2585, 2479, 764: 2605, 2477, 769: 2569, 771: 2580, 773: 2596, 783: 2478, 787: 2535, 799: 2610, 812: 2523, 834: 2530, 837: 2533, 843: 2608, 848: 2572, 852: 2577, 2587, 2490, 919: 2542, 923: 2481, 958: 2611, 965: 2521, 967: 2522, 2525, 2526, 971: 2528, 973: 2527, 975: 2524, 977: 2529, 2531, 2532, 981: 2491, 2568, 984: 2538, 994: 2546, 2539, 2540, 2541, 2547, 2545, 2548, 2549, 1003: 2544, 2543, 1006: 2534, 2496, 2482, 2550, 2562, 2551, 2552, 2553, 2555, 2559, 2556, 2560, 2561, 2554, 2558, 2557, 1023: 2520, 1027: 2536, 2537, 2484, 1033: 2564, 2563, 1037: 2566, 2567, 2565, 1042: 2602, 2570, 1050: 2614, 2613, 2571, 1057: 2573, 1059: 2599, 1086: 2574, 2575, 1089: 2576, 1091: 2581, 1094: 2578, 2579, 1097: 2601, 2582, 2609, 2584, 2583, 1107: 2589, 2588, 2592, 1111: 2593, 1113: 2600, 1116: 2590, 6630, 1121: 2591, 1132: 2594, 2595, 2598, 1136: 2597}, + {217, 217, 7: 5143, 13: 217, 46: 217, 466: 217, 652: 5187, 948: 5186, 6640}, + {225, 225, 13: 225, 46: 225, 466: 6335, 997: 6641}, + {204, 204, 13: 6352, 46: 6350, 941: 6351, 6349, 1086: 6348, 6642}, + {233, 233}, + {47: 6644}, // 4170 - {433, 433}, + {141: 6645}, + {650: 6646}, + {468: 5156, 881: 6647}, + {232, 232}, + {1917, 1917, 15: 1917, 48: 1917, 50: 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 1917, 137: 6369, 464: 1917, 499: 6368, 644: 1917, 1030: 6649}, + // 4175 + {1974, 1974, 15: 1974, 48: 1974, 50: 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 464: 1974, 644: 1974, 886: 6650}, + {1911, 1911, 15: 6099, 48: 6075, 50: 6095, 6088, 6078, 6074, 6082, 6086, 6098, 6081, 6087, 6085, 6083, 6096, 6089, 6077, 6097, 6076, 6079, 6080, 6084, 6652, 464: 6090, 644: 6100, 882: 6092, 6091, 6094, 6073, 887: 6093, 1212: 6651}, + {1926, 1926}, + {201: 6654, 642: 6653}, + {548, 548, 562: 6046, 957: 6656}, + // 4180 + {548, 548, 562: 6046, 957: 6655}, + {1909, 1909}, + {1910, 1910}, + {14: 1390, 16: 1390, 19: 1390, 159: 4887, 471: 1390, 474: 1390, 496: 1390, 498: 1390, 638: 1390}, + {14: 2125, 16: 2125, 19: 2125, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 770: 6461, 781: 6460, 838: 6464, 920: 6660}, + // 4185 + {2144, 2144, 14: 2125, 16: 2125, 19: 2125, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 770: 6461, 781: 6460, 838: 6465}, + {2145, 2145, 14: 2125, 16: 2125, 19: 2125, 471: 4151, 474: 2125, 496: 6462, 498: 2125, 638: 2125, 770: 6461, 781: 6460, 838: 6465}, + {2004, 2004, 48: 2503, 69: 2619, 71: 2484, 80: 2514, 145: 2486, 152: 2512, 154: 2483, 166: 2508, 199: 2533, 205: 2631, 208: 2479, 216: 2532, 2499, 2485, 233: 2511, 238: 2489, 241: 2509, 243: 2480, 245: 2515, 263: 2501, 268: 2500, 275: 2513, 277: 2481, 280: 2502, 292: 2494, 465: 2523, 2522, 488: 2627, 493: 2521, 496: 2531, 499: 2507, 517: 2622, 521: 2497, 559: 2506, 562: 2520, 637: 2516, 640: 2630, 644: 2482, 2621, 653: 2477, 660: 2488, 665: 2487, 670: 2530, 677: 2478, 700: 2527, 733: 2490, 742: 2529, 2517, 2518, 2519, 2528, 2526, 2525, 2524, 2600, 2599, 2493, 763: 2620, 765: 2491, 767: 2583, 2594, 2611, 782: 2492, 786: 2549, 798: 2625, 811: 2537, 833: 2544, 837: 2547, 843: 2623, 848: 2586, 852: 2591, 2601, 2504, 919: 2556, 923: 2495, 961: 2626, 968: 2535, 970: 2536, 2539, 2540, 974: 2542, 976: 2541, 978: 2538, 980: 2543, 2545, 2546, 985: 2505, 2582, 988: 2552, 998: 2560, 2553, 2554, 2555, 2561, 2559, 2562, 2563, 1007: 2558, 2557, 1010: 2548, 2510, 2496, 2564, 2576, 2565, 2566, 2567, 2569, 2573, 2570, 2574, 2575, 2568, 2572, 2571, 1027: 2534, 1031: 2550, 2551, 2498, 1037: 2578, 2577, 1041: 2580, 2581, 2579, 1046: 2617, 2584, 1054: 2629, 2628, 2585, 1061: 2587, 1064: 2614, 1089: 2588, 2589, 1092: 2590, 1094: 2595, 1097: 2592, 2593, 1100: 2616, 2596, 2624, 2598, 2597, 1109: 2602, 1111: 2604, 2603, 2607, 1115: 2608, 1117: 2615, 1120: 2605, 6662, 1125: 2606, 1136: 2609, 2610, 2613, 1140: 2612}, + {435, 435}, } ) @@ -11067,7 +11111,7 @@ func yylex1(yylex yyLexer, lval *yySymType) (n int) { } func yyParse(yylex yyLexer, parser *Parser) int { - const yyError = 1337 + const yyError = 1341 yyEx, _ := yylex.(yyLexerEx) var yyn int @@ -11289,7 +11333,12 @@ yynewstate: } case 10: { - parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerCount, UintValue: yyS[yypt-0].item.(uint64)} + cnt := yyS[yypt-0].item.(uint64) + if cnt == 0 { + yylex.AppendError(yylex.Errorf("FOLLOWERS must be positive")) + return 1 + } + parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerCount, UintValue: cnt} } case 11: { @@ -11323,39 +11372,39 @@ yynewstate: { parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionLearnerConstraints, StrValue: yyS[yypt-0].ident} } - case 21: + case 19: { parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: yyS[yypt-0].ident} } - case 22: + case 20: { parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: yyS[yypt-0].ident} } - case 23: + case 21: { parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: yyS[yypt-0].ident} } - case 24: + case 22: { parser.yyVAL.item = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: yyS[yypt-0].ident} } - case 25: + case 23: { parser.yyVAL.item = &ast.AttributesSpec{Default: true} } - case 26: + case 24: { parser.yyVAL.item = &ast.AttributesSpec{Default: false, Attributes: yyS[yypt-0].ident} } - case 27: + case 25: { parser.yyVAL.item = &ast.StatsOptionsSpec{Default: true} } - case 28: + case 26: { parser.yyVAL.item = &ast.StatsOptionsSpec{Default: false, StatsOptions: yyS[yypt-0].ident} } - case 29: + case 27: { if yyS[yypt-0].item != nil { parser.yyVAL.item = &ast.AlterTableSpec{ @@ -11366,19 +11415,19 @@ yynewstate: parser.yyVAL.item = nil } } - case 30: + case 28: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRemovePartitioning, } } - case 31: + case 29: { ret := yyS[yypt-0].item.(*ast.AlterTableSpec) ret.NoWriteToBinlog = yyS[yypt-1].item.(bool) parser.yyVAL.item = ret } - case 32: + case 30: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTablePartitionAttributes, @@ -11386,7 +11435,7 @@ yynewstate: AttributesSpec: yyS[yypt-0].item.(*ast.AttributesSpec), } } - case 33: + case 31: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTablePartitionOptions, @@ -11394,22 +11443,22 @@ yynewstate: Options: yyS[yypt-0].item.([]*ast.TableOption), } } - case 34: + case 32: { parser.yyVAL.item = []string{} } - case 35: + case 33: { parser.yyVAL.item = yyS[yypt-0].item } - case 36: + case 34: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableOption, Options: yyS[yypt-0].item.([]*ast.TableOption), } } - case 37: + case 35: { tiflashReplicaSpec := &ast.TiFlashReplicaSpec{ Count: yyS[yypt-1].item.(uint64), @@ -11420,7 +11469,7 @@ yynewstate: TiFlashReplica: tiflashReplicaSpec, } } - case 38: + case 36: { op := &ast.AlterTableSpec{ Tp: ast.AlterTableOption, @@ -11432,7 +11481,7 @@ yynewstate: } parser.yyVAL.item = op } - case 39: + case 37: { op := &ast.AlterTableSpec{ Tp: ast.AlterTableOption, @@ -11444,7 +11493,7 @@ yynewstate: } parser.yyVAL.item = op } - case 40: + case 38: { parser.yyVAL.item = &ast.AlterTableSpec{ IfNotExists: yyS[yypt-2].item.(bool), @@ -11453,7 +11502,7 @@ yynewstate: Position: yyS[yypt-0].item.(*ast.ColumnPosition), } } - case 41: + case 39: { tes := yyS[yypt-1].item.([]interface{}) var columnDefs []*ast.ColumnDef @@ -11473,7 +11522,7 @@ yynewstate: NewConstraints: constraints, } } - case 42: + case 40: { constraint := yyS[yypt-0].item.(*ast.Constraint) parser.yyVAL.item = &ast.AlterTableSpec{ @@ -11481,7 +11530,7 @@ yynewstate: Constraint: constraint, } } - case 43: + case 41: { var defs []*ast.PartitionDefinition if yyS[yypt-0].item != nil { @@ -11499,7 +11548,7 @@ yynewstate: PartDefinitions: defs, } } - case 44: + case 42: { noWriteToBinlog := yyS[yypt-2].item.(bool) if noWriteToBinlog { @@ -11513,7 +11562,7 @@ yynewstate: Num: getUint64FromNUM(yyS[yypt-0].item), } } - case 45: + case 43: { statsSpec := &ast.StatisticsSpec{ StatsName: yyS[yypt-4].ident, @@ -11526,21 +11575,21 @@ yynewstate: Statistics: statsSpec, } } - case 46: + case 44: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableAttributes, AttributesSpec: yyS[yypt-0].item.(*ast.AttributesSpec), } } - case 47: + case 45: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableStatsOptions, StatsOptionsSpec: yyS[yypt-0].item.(*ast.StatsOptionsSpec), } } - case 48: + case 46: { yylex.AppendError(yylex.Errorf("The CHECK PARTITIONING clause is parsed but not implement yet.")) parser.lastErrorAsWarn() @@ -11554,7 +11603,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 49: + case 47: { noWriteToBinlog := yyS[yypt-1].item.(bool) if noWriteToBinlog { @@ -11567,7 +11616,7 @@ yynewstate: Num: getUint64FromNUM(yyS[yypt-0].item), } } - case 50: + case 48: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-2].item.(bool), @@ -11575,11 +11624,11 @@ yynewstate: OldColumnName: yyS[yypt-1].item.(*ast.ColumnName), } } - case 51: + case 49: { parser.yyVAL.item = &ast.AlterTableSpec{Tp: ast.AlterTableDropPrimaryKey} } - case 52: + case 50: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-1].item.(bool), @@ -11587,7 +11636,7 @@ yynewstate: PartitionNames: yyS[yypt-0].item.([]model.CIStr), } } - case 53: + case 51: { statsSpec := &ast.StatisticsSpec{ StatsName: yyS[yypt-0].ident, @@ -11598,7 +11647,7 @@ yynewstate: Statistics: statsSpec, } } - case 54: + case 52: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableExchangePartition, @@ -11607,7 +11656,7 @@ yynewstate: WithValidation: yyS[yypt-0].item.(bool), } } - case 55: + case 53: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableTruncatePartition, @@ -11619,7 +11668,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 56: + case 54: { ret := &ast.AlterTableSpec{ NoWriteToBinlog: yyS[yypt-1].item.(bool), @@ -11632,7 +11681,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 57: + case 55: { ret := &ast.AlterTableSpec{ NoWriteToBinlog: yyS[yypt-1].item.(bool), @@ -11645,7 +11694,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 58: + case 56: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableImportPartitionTablespace, @@ -11659,7 +11708,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The IMPORT PARTITION TABLESPACE clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 59: + case 57: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableDiscardPartitionTablespace, @@ -11673,7 +11722,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The DISCARD PARTITION TABLESPACE clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 60: + case 58: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableImportTablespace, @@ -11682,7 +11731,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The IMPORT TABLESPACE clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 61: + case 59: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableDiscardTablespace, @@ -11691,7 +11740,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The DISCARD TABLESPACE clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 62: + case 60: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableRebuildPartition, @@ -11704,7 +11753,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 63: + case 61: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-1].item.(bool), @@ -11712,7 +11761,7 @@ yynewstate: Name: yyS[yypt-0].ident, } } - case 64: + case 62: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-1].item.(bool), @@ -11720,26 +11769,26 @@ yynewstate: Name: yyS[yypt-0].ident, } } - case 65: + case 63: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableOrderByColumns, OrderByList: yyS[yypt-0].item.([]*ast.AlterOrderItem), } } - case 66: + case 64: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableDisableKeys, } } - case 67: + case 65: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableEnableKeys, } } - case 68: + case 66: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-2].item.(bool), @@ -11748,7 +11797,7 @@ yynewstate: Position: yyS[yypt-0].item.(*ast.ColumnPosition), } } - case 69: + case 67: { parser.yyVAL.item = &ast.AlterTableSpec{ IfExists: yyS[yypt-3].item.(bool), @@ -11758,7 +11807,7 @@ yynewstate: Position: yyS[yypt-0].item.(*ast.ColumnPosition), } } - case 70: + case 68: { option := &ast.ColumnOption{Expr: yyS[yypt-0].expr} colDef := &ast.ColumnDef{ @@ -11770,7 +11819,7 @@ yynewstate: NewColumns: []*ast.ColumnDef{colDef}, } } - case 71: + case 69: { option := &ast.ColumnOption{Expr: yyS[yypt-1].expr} colDef := &ast.ColumnDef{ @@ -11782,7 +11831,7 @@ yynewstate: NewColumns: []*ast.ColumnDef{colDef}, } } - case 72: + case 70: { colDef := &ast.ColumnDef{ Name: yyS[yypt-2].item.(*ast.ColumnName), @@ -11792,7 +11841,7 @@ yynewstate: NewColumns: []*ast.ColumnDef{colDef}, } } - case 73: + case 71: { oldColName := &ast.ColumnName{Name: model.NewCIStr(yyS[yypt-2].ident)} newColName := &ast.ColumnName{Name: model.NewCIStr(yyS[yypt-0].ident)} @@ -11802,28 +11851,28 @@ yynewstate: NewColumnName: newColName, } } - case 74: + case 72: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRenameTable, NewTable: yyS[yypt-0].item.(*ast.TableName), } } - case 75: + case 73: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRenameTable, NewTable: yyS[yypt-0].item.(*ast.TableName), } } - case 76: + case 74: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRenameTable, NewTable: yyS[yypt-0].item.(*ast.TableName), } } - case 77: + case 75: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRenameIndex, @@ -11831,21 +11880,21 @@ yynewstate: ToKey: model.NewCIStr(yyS[yypt-0].ident), } } - case 78: + case 76: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableLock, LockType: yyS[yypt-0].item.(ast.LockType), } } - case 79: + case 77: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableWriteable, Writeable: yyS[yypt-0].item.(bool), } } - case 80: + case 78: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ @@ -11853,28 +11902,28 @@ yynewstate: Algorithm: yyS[yypt-0].item.(ast.AlgorithmType), } } - case 81: + case 79: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableForce, } } - case 82: + case 80: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableWithValidation, } } - case 83: + case 81: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableWithoutValidation, } } - case 84: + case 82: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ @@ -11883,7 +11932,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The SECONDARY_LOAD clause is parsed but not implement yet.")) parser.lastErrorAsWarn() } - case 85: + case 83: { // Parse it and ignore it. Just for compatibility. parser.yyVAL.item = &ast.AlterTableSpec{ @@ -11892,7 +11941,7 @@ yynewstate: yylex.AppendError(yylex.Errorf("The SECONDARY_UNLOAD VALIDATION clause is parsed but not implement yet.")) parser.lastErrorAsWarn() } - case 86: + case 84: { c := &ast.Constraint{ Name: yyS[yypt-1].ident, @@ -11903,7 +11952,7 @@ yynewstate: Constraint: c, } } - case 87: + case 85: { // Parse it and ignore it. Just for compatibility. c := &ast.Constraint{ @@ -11914,7 +11963,7 @@ yynewstate: Constraint: c, } } - case 88: + case 86: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableIndexInvisible, @@ -11922,19 +11971,19 @@ yynewstate: Visibility: yyS[yypt-0].item.(ast.IndexVisibility), } } - case 89: + case 87: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableCache, } } - case 90: + case 88: { parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableNoCache, } } - case 91: + case 89: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableReorganizePartition, @@ -11942,7 +11991,7 @@ yynewstate: } parser.yyVAL.item = ret } - case 92: + case 90: { ret := &ast.AlterTableSpec{ Tp: ast.AlterTableReorganizePartition, @@ -11951,56 +12000,56 @@ yynewstate: } parser.yyVAL.item = ret } - case 93: + case 91: { parser.yyVAL.item = nil } - case 95: + case 93: { parser.yyVAL.item = true } - case 97: + case 95: { parser.yyVAL.item = true } - case 98: + case 96: { parser.yyVAL.item = false } - case 99: + case 97: { parser.yyVAL.item = model.PrimaryKeyTypeClustered } - case 100: + case 98: { parser.yyVAL.item = model.PrimaryKeyTypeNonClustered } - case 101: + case 99: { parser.yyVAL.item = ast.AlgorithmTypeDefault } - case 102: + case 100: { parser.yyVAL.item = ast.AlgorithmTypeCopy } - case 103: + case 101: { parser.yyVAL.item = ast.AlgorithmTypeInplace } - case 104: + case 102: { parser.yyVAL.item = ast.AlgorithmTypeInstant } - case 105: + case 103: { yylex.AppendError(ErrUnknownAlterAlgorithm.GenWithStackByArgs(yyS[yypt-2].ident)) return 1 } - case 106: + case 104: { parser.yyVAL.item = ast.LockTypeDefault } - case 107: + case 105: { id := strings.ToUpper(yyS[yypt-0].ident) @@ -12015,138 +12064,138 @@ yynewstate: return 1 } } - case 108: + case 106: { parser.yyVAL.item = true } - case 109: + case 107: { parser.yyVAL.item = false } - case 116: + case 114: { parser.yyVAL.item = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} } - case 117: + case 115: { parser.yyVAL.item = &ast.ColumnPosition{Tp: ast.ColumnPositionFirst} } - case 118: + case 116: { parser.yyVAL.item = &ast.ColumnPosition{ Tp: ast.ColumnPositionAfter, RelativeColumn: yyS[yypt-0].item.(*ast.ColumnName), } } - case 119: + case 117: { parser.yyVAL.item = make([]*ast.AlterTableSpec, 0, 1) } - case 121: + case 119: { parser.yyVAL.item = []*ast.AlterTableSpec{yyS[yypt-0].item.(*ast.AlterTableSpec)} } - case 122: + case 120: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.AlterTableSpec), yyS[yypt-0].item.(*ast.AlterTableSpec)) } - case 123: + case 121: { parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 124: + case 122: { parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) } - case 125: + case 123: { parser.yyVAL.item = nil } - case 126: + case 124: { parser.yyVAL.item = nil } - case 127: + case 125: { parser.yyVAL.item = yyS[yypt-0].ident } - case 129: + case 127: { parser.yyVAL.statement = &ast.RenameTableStmt{ TableToTables: yyS[yypt-0].item.([]*ast.TableToTable), } } - case 130: + case 128: { parser.yyVAL.item = []*ast.TableToTable{yyS[yypt-0].item.(*ast.TableToTable)} } - case 131: + case 129: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableToTable), yyS[yypt-0].item.(*ast.TableToTable)) } - case 132: + case 130: { parser.yyVAL.item = &ast.TableToTable{ OldTable: yyS[yypt-2].item.(*ast.TableName), NewTable: yyS[yypt-0].item.(*ast.TableName), } } - case 133: + case 131: { parser.yyVAL.statement = &ast.RenameUserStmt{ UserToUsers: yyS[yypt-0].item.([]*ast.UserToUser), } } - case 134: + case 132: { parser.yyVAL.item = []*ast.UserToUser{yyS[yypt-0].item.(*ast.UserToUser)} } - case 135: + case 133: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.UserToUser), yyS[yypt-0].item.(*ast.UserToUser)) } - case 136: + case 134: { parser.yyVAL.item = &ast.UserToUser{ OldUser: yyS[yypt-2].item.(*auth.UserIdentity), NewUser: yyS[yypt-0].item.(*auth.UserIdentity), } } - case 137: + case 135: { parser.yyVAL.statement = &ast.RecoverTableStmt{ JobID: yyS[yypt-0].item.(int64), } } - case 138: + case 136: { parser.yyVAL.statement = &ast.RecoverTableStmt{ Table: yyS[yypt-0].item.(*ast.TableName), } } - case 139: + case 137: { parser.yyVAL.statement = &ast.RecoverTableStmt{ Table: yyS[yypt-1].item.(*ast.TableName), JobNum: yyS[yypt-0].item.(int64), } } - case 140: + case 138: { parser.yyVAL.statement = &ast.FlashBackTableStmt{ Table: yyS[yypt-1].item.(*ast.TableName), NewName: yyS[yypt-0].ident, } } - case 141: + case 139: { parser.yyVAL.ident = "" } - case 142: + case 140: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 143: + case 141: { parser.yyVAL.statement = &ast.SplitRegionStmt{ SplitSyntaxOpt: yyS[yypt-4].item.(*ast.SplitSyntaxOption), @@ -12155,7 +12204,7 @@ yynewstate: SplitOpt: yyS[yypt-0].item.(*ast.SplitOption), } } - case 144: + case 142: { parser.yyVAL.statement = &ast.SplitRegionStmt{ SplitSyntaxOpt: yyS[yypt-6].item.(*ast.SplitSyntaxOption), @@ -12165,7 +12214,7 @@ yynewstate: SplitOpt: yyS[yypt-0].item.(*ast.SplitOption), } } - case 145: + case 143: { parser.yyVAL.item = &ast.SplitOption{ Lower: yyS[yypt-4].item.([]ast.ExprNode), @@ -12173,52 +12222,52 @@ yynewstate: Num: yyS[yypt-0].item.(int64), } } - case 146: + case 144: { parser.yyVAL.item = &ast.SplitOption{ ValueLists: yyS[yypt-0].item.([][]ast.ExprNode), } } - case 147: + case 145: { parser.yyVAL.item = &ast.SplitSyntaxOption{} } - case 148: + case 146: { parser.yyVAL.item = &ast.SplitSyntaxOption{ HasRegionFor: true, } } - case 149: + case 147: { parser.yyVAL.item = &ast.SplitSyntaxOption{ HasPartition: true, } } - case 150: + case 148: { parser.yyVAL.item = &ast.SplitSyntaxOption{ HasRegionFor: true, HasPartition: true, } } - case 151: + case 149: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: yyS[yypt-2].item.([]*ast.TableName), ColumnChoice: yyS[yypt-1].item.(model.ColumnChoice), AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 152: + case 150: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-3].item.(*ast.TableName)}, IndexNames: yyS[yypt-1].item.([]model.CIStr), IndexFlag: true, AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 153: + case 151: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-3].item.(*ast.TableName)}, IndexNames: yyS[yypt-1].item.([]model.CIStr), IndexFlag: true, Incremental: true, AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 154: + case 152: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-4].item.(*ast.TableName)}, PartitionNames: yyS[yypt-2].item.([]model.CIStr), ColumnChoice: yyS[yypt-1].item.(model.ColumnChoice), AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 155: + case 153: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-5].item.(*ast.TableName)}, @@ -12228,7 +12277,7 @@ yynewstate: AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt), } } - case 156: + case 154: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-5].item.(*ast.TableName)}, @@ -12239,7 +12288,7 @@ yynewstate: AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt), } } - case 157: + case 155: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-5].item.(*ast.TableName)}, @@ -12248,7 +12297,7 @@ yynewstate: HistogramOperation: ast.HistogramOperationUpdate, } } - case 158: + case 156: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-4].item.(*ast.TableName)}, @@ -12256,7 +12305,7 @@ yynewstate: HistogramOperation: ast.HistogramOperationDrop, } } - case 159: + case 157: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-3].item.(*ast.TableName)}, @@ -12264,7 +12313,7 @@ yynewstate: ColumnChoice: model.ColumnList, AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 160: + case 158: { parser.yyVAL.statement = &ast.AnalyzeTableStmt{ TableNames: []*ast.TableName{yyS[yypt-5].item.(*ast.TableName)}, @@ -12273,134 +12322,134 @@ yynewstate: ColumnChoice: model.ColumnList, AnalyzeOpts: yyS[yypt-0].item.([]ast.AnalyzeOpt)} } - case 161: + case 159: { parser.yyVAL.item = model.DefaultChoice } - case 162: + case 160: { parser.yyVAL.item = model.AllColumns } - case 163: + case 161: { parser.yyVAL.item = model.PredicateColumns } - case 164: + case 162: { parser.yyVAL.item = []ast.AnalyzeOpt{} } - case 165: + case 163: { parser.yyVAL.item = yyS[yypt-0].item.([]ast.AnalyzeOpt) } - case 166: + case 164: { parser.yyVAL.item = []ast.AnalyzeOpt{yyS[yypt-0].item.(ast.AnalyzeOpt)} } - case 167: + case 165: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.AnalyzeOpt), yyS[yypt-0].item.(ast.AnalyzeOpt)) } - case 168: + case 166: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumBuckets, Value: ast.NewValueExpr(yyS[yypt-1].item, "", "")} } - case 169: + case 167: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumTopN, Value: ast.NewValueExpr(yyS[yypt-1].item, "", "")} } - case 170: + case 168: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptCMSketchDepth, Value: ast.NewValueExpr(yyS[yypt-2].item, "", "")} } - case 171: + case 169: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptCMSketchWidth, Value: ast.NewValueExpr(yyS[yypt-2].item, "", "")} } - case 172: + case 170: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumSamples, Value: ast.NewValueExpr(yyS[yypt-1].item, "", "")} } - case 173: + case 171: { parser.yyVAL.item = ast.AnalyzeOpt{Type: ast.AnalyzeOptSampleRate, Value: ast.NewValueExpr(yyS[yypt-1].item, "", "")} } - case 174: + case 172: { parser.yyVAL.item = &ast.Assignment{Column: yyS[yypt-2].item.(*ast.ColumnName), Expr: yyS[yypt-0].expr} } - case 175: + case 173: { parser.yyVAL.item = []*ast.Assignment{yyS[yypt-0].item.(*ast.Assignment)} } - case 176: + case 174: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.Assignment), yyS[yypt-0].item.(*ast.Assignment)) } - case 177: + case 175: { parser.yyVAL.item = []*ast.Assignment{} } - case 179: + case 177: { parser.yyVAL.statement = &ast.BeginStmt{} } - case 180: + case 178: { parser.yyVAL.statement = &ast.BeginStmt{ Mode: ast.Pessimistic, } } - case 181: + case 179: { parser.yyVAL.statement = &ast.BeginStmt{ Mode: ast.Optimistic, } } - case 182: + case 180: { parser.yyVAL.statement = &ast.BeginStmt{} } - case 183: + case 181: { parser.yyVAL.statement = &ast.BeginStmt{} } - case 184: + case 182: { parser.yyVAL.statement = &ast.BeginStmt{} } - case 185: + case 183: { parser.yyVAL.statement = &ast.BeginStmt{ CausalConsistencyOnly: true, } } - case 186: + case 184: { parser.yyVAL.statement = &ast.BeginStmt{ ReadOnly: true, } } - case 187: + case 185: { parser.yyVAL.statement = &ast.BeginStmt{ ReadOnly: true, AsOf: yyS[yypt-0].item.(*ast.AsOfClause), } } - case 188: + case 186: { parser.yyVAL.statement = &ast.BinlogStmt{Str: yyS[yypt-0].ident} } - case 189: + case 187: { parser.yyVAL.item = []*ast.ColumnDef{yyS[yypt-0].item.(*ast.ColumnDef)} } - case 190: + case 188: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ColumnDef), yyS[yypt-0].item.(*ast.ColumnDef)) } - case 191: + case 189: { colDef := &ast.ColumnDef{Name: yyS[yypt-2].item.(*ast.ColumnName), Tp: yyS[yypt-1].item.(*types.FieldType), Options: yyS[yypt-0].item.([]*ast.ColumnOption)} if !colDef.Validate() { @@ -12409,7 +12458,7 @@ yynewstate: } parser.yyVAL.item = colDef } - case 192: + case 190: { // TODO: check flen 0 tp := types.NewFieldType(mysql.TypeLonglong) @@ -12423,103 +12472,103 @@ yynewstate: } parser.yyVAL.item = colDef } - case 193: + case 191: { parser.yyVAL.item = &ast.ColumnName{Name: model.NewCIStr(yyS[yypt-0].ident)} } - case 194: + case 192: { parser.yyVAL.item = &ast.ColumnName{Table: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} } - case 195: + case 193: { parser.yyVAL.item = &ast.ColumnName{Schema: model.NewCIStr(yyS[yypt-4].ident), Table: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} } - case 196: + case 194: { parser.yyVAL.item = []*ast.ColumnName{yyS[yypt-0].item.(*ast.ColumnName)} } - case 197: + case 195: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ColumnName), yyS[yypt-0].item.(*ast.ColumnName)) } - case 198: + case 196: { parser.yyVAL.item = []*ast.ColumnName{} } - case 200: + case 198: { parser.yyVAL.item = []model.CIStr{} } - case 201: + case 199: { parser.yyVAL.item = yyS[yypt-1].item } - case 202: + case 200: { parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 203: + case 201: { parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) } - case 204: + case 202: { parser.yyVAL.item = []*ast.ColumnNameOrUserVar{} } - case 206: + case 204: { parser.yyVAL.item = []*ast.ColumnNameOrUserVar{yyS[yypt-0].item.(*ast.ColumnNameOrUserVar)} } - case 207: + case 205: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ColumnNameOrUserVar), yyS[yypt-0].item.(*ast.ColumnNameOrUserVar)) } - case 208: + case 206: { parser.yyVAL.item = &ast.ColumnNameOrUserVar{ColumnName: yyS[yypt-0].item.(*ast.ColumnName)} } - case 209: + case 207: { parser.yyVAL.item = &ast.ColumnNameOrUserVar{UserVar: yyS[yypt-0].expr.(*ast.VariableExpr)} } - case 210: + case 208: { parser.yyVAL.item = []*ast.ColumnNameOrUserVar{} } - case 211: + case 209: { parser.yyVAL.item = yyS[yypt-1].item.([]*ast.ColumnNameOrUserVar) } - case 212: + case 210: { parser.yyVAL.statement = &ast.CommitStmt{} } - case 213: + case 211: { parser.yyVAL.statement = &ast.CommitStmt{CompletionType: yyS[yypt-0].item.(ast.CompletionType)} } - case 217: + case 215: { parser.yyVAL.ident = "NOT" } - case 218: + case 216: { parser.yyVAL.item = true } - case 219: + case 217: { parser.yyVAL.item = false } - case 220: + case 218: { parser.yyVAL.item = true } - case 222: + case 220: { parser.yyVAL.item = 0 } - case 223: + case 221: { if yyS[yypt-0].item.(bool) { parser.yyVAL.item = 1 @@ -12527,57 +12576,57 @@ yynewstate: parser.yyVAL.item = 2 } } - case 224: + case 222: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionNotNull} } - case 225: + case 223: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionNull} } - case 226: + case 224: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionAutoIncrement} } - case 227: + case 225: { // KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY // can also be specified as just KEY when given in a column definition. // See http://dev.mysql.com/doc/refman/5.7/en/create-table.html parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey} } - case 228: + case 226: { // KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY // can also be specified as just KEY when given in a column definition. // See http://dev.mysql.com/doc/refman/5.7/en/create-table.html parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey, PrimaryKeyTp: yyS[yypt-0].item.(model.PrimaryKeyType)} } - case 229: + case 227: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} } - case 230: + case 228: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} } - case 231: + case 229: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: yyS[yypt-0].expr} } - case 232: + case 230: { parser.yyVAL.item = []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}} } - case 233: + case 231: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: yyS[yypt-0].expr} } - case 234: + case 232: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr(yyS[yypt-0].ident, "", "")} } - case 235: + case 233: { // See https://dev.mysql.com/doc/refman/5.7/en/create-table.html // The CHECK clause is parsed but ignored by all storage engines. @@ -12604,12 +12653,12 @@ yynewstate: default: } } - case 236: + case 234: { startOffset := parser.startOffset(&yyS[yypt-2]) endOffset := parser.endOffset(&yyS[yypt-1]) expr := yyS[yypt-2].expr - expr.SetText(parser.src[startOffset:endOffset]) + expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset]) parser.yyVAL.item = &ast.ColumnOption{ Tp: ast.ColumnOptionGenerated, @@ -12617,56 +12666,56 @@ yynewstate: Stored: yyS[yypt-0].item.(bool), } } - case 237: + case 235: { parser.yyVAL.item = &ast.ColumnOption{ Tp: ast.ColumnOptionReference, Refer: yyS[yypt-0].item.(*ast.ReferenceDef), } } - case 238: + case 236: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionCollate, StrValue: yyS[yypt-0].ident} } - case 239: + case 237: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionColumnFormat, StrValue: yyS[yypt-0].ident} } - case 240: + case 238: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionStorage, StrValue: yyS[yypt-0].ident} yylex.AppendError(yylex.Errorf("The STORAGE clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 241: + case 239: { parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionAutoRandom, AutoRandomBitLength: yyS[yypt-0].item.(int)} } - case 245: + case 243: { parser.yyVAL.ident = "DEFAULT" } - case 246: + case 244: { parser.yyVAL.ident = "FIXED" } - case 247: + case 245: { parser.yyVAL.ident = "DYNAMIC" } - case 250: + case 248: { parser.yyVAL.item = false } - case 251: + case 249: { parser.yyVAL.item = false } - case 252: + case 250: { parser.yyVAL.item = true } - case 253: + case 251: { if columnOption, ok := yyS[yypt-0].item.(*ast.ColumnOption); ok { parser.yyVAL.item = []*ast.ColumnOption{columnOption} @@ -12674,7 +12723,7 @@ yynewstate: parser.yyVAL.item = yyS[yypt-0].item } } - case 254: + case 252: { if columnOption, ok := yyS[yypt-0].item.(*ast.ColumnOption); ok { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.ColumnOption), columnOption) @@ -12682,11 +12731,11 @@ yynewstate: parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.ColumnOption), yyS[yypt-0].item.([]*ast.ColumnOption)...) } } - case 255: + case 253: { parser.yyVAL.item = []*ast.ColumnOption{} } - case 257: + case 255: { c := &ast.Constraint{ Tp: ast.ConstraintPrimaryKey, @@ -12705,7 +12754,7 @@ yynewstate: } parser.yyVAL.item = c } - case 258: + case 256: { c := &ast.Constraint{ Tp: ast.ConstraintFulltext, @@ -12718,7 +12767,7 @@ yynewstate: } parser.yyVAL.item = c } - case 259: + case 257: { c := &ast.Constraint{ IfNotExists: yyS[yypt-5].item.(bool), @@ -12738,7 +12787,7 @@ yynewstate: } parser.yyVAL.item = c } - case 260: + case 258: { c := &ast.Constraint{ Tp: ast.ConstraintUniq, @@ -12758,7 +12807,7 @@ yynewstate: } parser.yyVAL.item = c } - case 261: + case 259: { parser.yyVAL.item = &ast.Constraint{ IfNotExists: yyS[yypt-5].item.(bool), @@ -12769,7 +12818,7 @@ yynewstate: IsEmptyIndex: yyS[yypt-4].item.(*ast.NullString).Empty, } } - case 262: + case 260: { parser.yyVAL.item = &ast.Constraint{ Tp: ast.ConstraintCheck, @@ -12777,29 +12826,29 @@ yynewstate: Enforced: yyS[yypt-0].item.(bool), } } - case 263: + case 261: { parser.yyVAL.item = ast.MatchFull } - case 264: + case 262: { parser.yyVAL.item = ast.MatchPartial } - case 265: + case 263: { parser.yyVAL.item = ast.MatchSimple } - case 266: + case 264: { parser.yyVAL.item = ast.MatchNone } - case 267: + case 265: { parser.yyVAL.item = yyS[yypt-0].item yylex.AppendError(yylex.Errorf("The MATCH clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 268: + case 266: { onDeleteUpdate := yyS[yypt-0].item.([2]interface{}) parser.yyVAL.item = &ast.ReferenceDef{ @@ -12810,69 +12859,90 @@ yynewstate: Match: yyS[yypt-1].item.(ast.MatchType), } } - case 269: + case 267: { parser.yyVAL.item = &ast.OnDeleteOpt{ReferOpt: yyS[yypt-0].item.(ast.ReferOptionType)} } - case 270: + case 268: { parser.yyVAL.item = &ast.OnUpdateOpt{ReferOpt: yyS[yypt-0].item.(ast.ReferOptionType)} } - case 271: + case 269: { parser.yyVAL.item = [2]interface{}{&ast.OnDeleteOpt{}, &ast.OnUpdateOpt{}} } - case 272: + case 270: { parser.yyVAL.item = [2]interface{}{yyS[yypt-0].item, &ast.OnUpdateOpt{}} } - case 273: + case 271: { parser.yyVAL.item = [2]interface{}{&ast.OnDeleteOpt{}, yyS[yypt-0].item} } - case 274: + case 272: { parser.yyVAL.item = [2]interface{}{yyS[yypt-1].item, yyS[yypt-0].item} } - case 275: + case 273: { parser.yyVAL.item = [2]interface{}{yyS[yypt-0].item, yyS[yypt-1].item} } - case 276: + case 274: { parser.yyVAL.item = ast.ReferOptionRestrict } - case 277: + case 275: { parser.yyVAL.item = ast.ReferOptionCascade } - case 278: + case 276: { parser.yyVAL.item = ast.ReferOptionSetNull } - case 279: + case 277: { parser.yyVAL.item = ast.ReferOptionNoAction } - case 280: + case 278: { parser.yyVAL.item = ast.ReferOptionSetDefault yylex.AppendError(yylex.Errorf("The SET DEFAULT clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } + case 283: + { + parser.yyVAL.expr = yyS[yypt-1].expr.(*ast.FuncCallExpr) + } case 284: { - parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-2].ident), + } } case 285: { - parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-3].ident), + Args: yyS[yypt-1].item.([]ast.ExprNode), + } } case 286: + { + parser.yyVAL.expr = yyS[yypt-1].expr.(*ast.FuncCallExpr) + } + case 288: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + case 289: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + case 290: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}} } - case 287: + case 291: { objNameExpr := &ast.TableNameExpr{ Name: yyS[yypt-0].item.(*ast.TableName), @@ -12882,7 +12952,7 @@ yynewstate: Args: []ast.ExprNode{objNameExpr}, } } - case 288: + case 292: { objNameExpr := &ast.TableNameExpr{ Name: yyS[yypt-1].item.(*ast.TableName), @@ -12892,31 +12962,39 @@ yynewstate: Args: []ast.ExprNode{objNameExpr}, } } - case 296: + case 300: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].expr, parser.charset, parser.collation) } - case 297: + case 301: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)} } - case 298: + case 302: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)} } - case 302: + case 306: { parser.yyVAL.item = ast.StatsTypeCardinality } - case 303: + case 307: { parser.yyVAL.item = ast.StatsTypeDependency } - case 304: + case 308: { parser.yyVAL.item = ast.StatsTypeCorrelation } - case 305: + case 309: + { + parser.yyVAL.item = ast.BindingStatusTypeEnabled + } + case 310: + { + parser.yyVAL.item = ast.BindingStatusTypeDisabled + } + case 311: { parser.yyVAL.statement = &ast.CreateStatisticsStmt{ IfNotExists: yyS[yypt-9].item.(bool), @@ -12926,11 +13004,11 @@ yynewstate: Columns: yyS[yypt-1].item.([]*ast.ColumnName), } } - case 306: + case 312: { parser.yyVAL.statement = &ast.DropStatisticsStmt{StatsName: yyS[yypt-0].ident} } - case 307: + case 313: { var indexOption *ast.IndexOption if yyS[yypt-1].item != nil { @@ -12963,80 +13041,80 @@ yynewstate: LockAlg: indexLockAndAlgorithm, } } - case 308: + case 314: { parser.yyVAL.item = ([]*ast.IndexPartSpecification)(nil) } - case 309: + case 315: { parser.yyVAL.item = yyS[yypt-1].item } - case 310: + case 316: { parser.yyVAL.item = []*ast.IndexPartSpecification{yyS[yypt-0].item.(*ast.IndexPartSpecification)} } - case 311: + case 317: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.IndexPartSpecification), yyS[yypt-0].item.(*ast.IndexPartSpecification)) } - case 312: + case 318: { // Order is parsed but just ignored as MySQL did. parser.yyVAL.item = &ast.IndexPartSpecification{Column: yyS[yypt-2].item.(*ast.ColumnName), Length: yyS[yypt-1].item.(int)} } - case 313: + case 319: { parser.yyVAL.item = &ast.IndexPartSpecification{Expr: yyS[yypt-2].expr} } - case 314: + case 320: { parser.yyVAL.item = nil } - case 315: + case 321: { parser.yyVAL.item = &ast.IndexLockAndAlgorithm{ LockTp: yyS[yypt-0].item.(ast.LockType), AlgorithmTp: ast.AlgorithmTypeDefault, } } - case 316: + case 322: { parser.yyVAL.item = &ast.IndexLockAndAlgorithm{ LockTp: ast.LockTypeDefault, AlgorithmTp: yyS[yypt-0].item.(ast.AlgorithmType), } } - case 317: + case 323: { parser.yyVAL.item = &ast.IndexLockAndAlgorithm{ LockTp: yyS[yypt-1].item.(ast.LockType), AlgorithmTp: yyS[yypt-0].item.(ast.AlgorithmType), } } - case 318: + case 324: { parser.yyVAL.item = &ast.IndexLockAndAlgorithm{ LockTp: yyS[yypt-0].item.(ast.LockType), AlgorithmTp: yyS[yypt-1].item.(ast.AlgorithmType), } } - case 319: + case 325: { parser.yyVAL.item = ast.IndexKeyTypeNone } - case 320: + case 326: { parser.yyVAL.item = ast.IndexKeyTypeUnique } - case 321: + case 327: { parser.yyVAL.item = ast.IndexKeyTypeSpatial } - case 322: + case 328: { parser.yyVAL.item = ast.IndexKeyTypeFullText } - case 323: + case 329: { parser.yyVAL.statement = &ast.AlterDatabaseStmt{ Name: yyS[yypt-1].ident, @@ -13044,7 +13122,7 @@ yynewstate: Options: yyS[yypt-0].item.([]*ast.DatabaseOption), } } - case 324: + case 330: { parser.yyVAL.statement = &ast.AlterDatabaseStmt{ Name: "", @@ -13052,7 +13130,7 @@ yynewstate: Options: yyS[yypt-0].item.([]*ast.DatabaseOption), } } - case 325: + case 331: { parser.yyVAL.statement = &ast.CreateDatabaseStmt{ IfNotExists: yyS[yypt-2].item.(bool), @@ -13060,19 +13138,19 @@ yynewstate: Options: yyS[yypt-0].item.([]*ast.DatabaseOption), } } - case 328: + case 334: { parser.yyVAL.item = &ast.DatabaseOption{Tp: ast.DatabaseOptionCharset, Value: yyS[yypt-0].ident} } - case 329: + case 335: { parser.yyVAL.item = &ast.DatabaseOption{Tp: ast.DatabaseOptionCollate, Value: yyS[yypt-0].ident} } - case 330: + case 336: { parser.yyVAL.item = &ast.DatabaseOption{Tp: ast.DatabaseOptionEncryption, Value: yyS[yypt-0].ident} } - case 331: + case 337: { placementOptions := yyS[yypt-0].item.(*ast.PlacementOption) parser.yyVAL.item = &ast.DatabaseOption{ @@ -13082,7 +13160,7 @@ yynewstate: UintValue: placementOptions.UintValue, } } - case 332: + case 338: { placementOptions := yyS[yypt-0].item.(*ast.PlacementOption) parser.yyVAL.item = &ast.DatabaseOption{ @@ -13092,19 +13170,30 @@ yynewstate: UintValue: placementOptions.UintValue, } } - case 333: + case 339: + { + tiflashReplicaSpec := &ast.TiFlashReplicaSpec{ + Count: yyS[yypt-1].item.(uint64), + Labels: yyS[yypt-0].item.([]string), + } + parser.yyVAL.item = &ast.DatabaseOption{ + Tp: ast.DatabaseSetTiFlashReplica, + TiFlashReplica: tiflashReplicaSpec, + } + } + case 340: { parser.yyVAL.item = []*ast.DatabaseOption{} } - case 335: + case 342: { parser.yyVAL.item = []*ast.DatabaseOption{yyS[yypt-0].item.(*ast.DatabaseOption)} } - case 336: + case 343: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.DatabaseOption), yyS[yypt-0].item.(*ast.DatabaseOption)) } - case 337: + case 344: { stmt := yyS[yypt-6].item.(*ast.CreateTableStmt) stmt.Table = yyS[yypt-7].item.(*ast.TableName) @@ -13117,7 +13206,7 @@ yynewstate: stmt.OnDuplicate = yyS[yypt-3].item.(ast.OnDuplicateKeyHandlingType) stmt.Select = yyS[yypt-1].item.(*ast.CreateTableStmt).Select if (yyS[yypt-0].item != nil && stmt.TemporaryKeyword != ast.TemporaryGlobal) || (stmt.TemporaryKeyword == ast.TemporaryGlobal && yyS[yypt-0].item == nil) { - yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE|PRESERVE ROWS must appear together")) + yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together")) } else { if stmt.TemporaryKeyword == ast.TemporaryGlobal { stmt.OnCommitDelete = yyS[yypt-0].item.(bool) @@ -13125,7 +13214,7 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 338: + case 345: { tmp := &ast.CreateTableStmt{ Table: yyS[yypt-2].item.(*ast.TableName), @@ -13134,7 +13223,7 @@ yynewstate: TemporaryKeyword: yyS[yypt-5].item.(ast.TemporaryKeyword), } if (yyS[yypt-0].item != nil && tmp.TemporaryKeyword != ast.TemporaryGlobal) || (tmp.TemporaryKeyword == ast.TemporaryGlobal && yyS[yypt-0].item == nil) { - yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE|PRESERVE ROWS must appear together")) + yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together")) } else { if tmp.TemporaryKeyword == ast.TemporaryGlobal { tmp.OnCommitDelete = yyS[yypt-0].item.(bool) @@ -13142,23 +13231,23 @@ yynewstate: } parser.yyVAL.statement = tmp } - case 339: + case 346: { parser.yyVAL.item = nil } - case 340: + case 347: { parser.yyVAL.item = true } - case 341: + case 348: { parser.yyVAL.item = false } - case 344: + case 351: { parser.yyVAL.item = nil } - case 345: + case 352: { method := yyS[yypt-3].item.(*ast.PartitionMethod) method.Num = yyS[yypt-2].item.(uint64) @@ -13175,7 +13264,7 @@ yynewstate: } parser.yyVAL.item = opt } - case 346: + case 353: { keyAlgorithm, _ := yyS[yypt-3].item.(*ast.PartitionKeyAlgorithm) parser.yyVAL.item = &ast.PartitionMethod{ @@ -13185,7 +13274,7 @@ yynewstate: KeyAlgorithm: keyAlgorithm, } } - case 347: + case 354: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeHash, @@ -13193,11 +13282,11 @@ yynewstate: Expr: yyS[yypt-1].expr.(ast.ExprNode), } } - case 348: + case 355: { parser.yyVAL.item = nil } - case 349: + case 356: { tp := getUint64FromNUM(yyS[yypt-0].item) if tp != 1 && tp != 2 { @@ -13208,35 +13297,35 @@ yynewstate: Type: tp, } } - case 351: + case 358: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeRange, Expr: yyS[yypt-1].expr.(ast.ExprNode), } } - case 352: + case 359: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeRange, ColumnNames: yyS[yypt-1].item.([]*ast.ColumnName), } } - case 353: + case 360: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeList, Expr: yyS[yypt-1].expr.(ast.ExprNode), } } - case 354: + case 361: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeList, ColumnNames: yyS[yypt-1].item.([]*ast.ColumnName), } } - case 355: + case 362: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeSystemTime, @@ -13244,38 +13333,38 @@ yynewstate: Unit: yyS[yypt-0].item.(ast.TimeUnitType), } } - case 356: + case 363: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeSystemTime, Limit: yyS[yypt-0].item.(uint64), } } - case 357: + case 364: { parser.yyVAL.item = &ast.PartitionMethod{ Tp: model.PartitionTypeSystemTime, } } - case 358: + case 365: { parser.yyVAL.ident = "" } - case 360: + case 367: { parser.yyVAL.item = nil } - case 361: + case 368: { method := yyS[yypt-1].item.(*ast.PartitionMethod) method.Num = yyS[yypt-0].item.(uint64) parser.yyVAL.item = method } - case 362: + case 369: { parser.yyVAL.item = uint64(0) } - case 363: + case 370: { res := yyS[yypt-0].item.(uint64) if res == 0 { @@ -13284,11 +13373,11 @@ yynewstate: } parser.yyVAL.item = res } - case 364: + case 371: { parser.yyVAL.item = uint64(0) } - case 365: + case 372: { res := yyS[yypt-0].item.(uint64) if res == 0 { @@ -13297,23 +13386,23 @@ yynewstate: } parser.yyVAL.item = res } - case 366: + case 373: { parser.yyVAL.item = nil } - case 367: + case 374: { parser.yyVAL.item = yyS[yypt-1].item.([]*ast.PartitionDefinition) } - case 368: + case 375: { parser.yyVAL.item = []*ast.PartitionDefinition{yyS[yypt-0].item.(*ast.PartitionDefinition)} } - case 369: + case 376: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.PartitionDefinition), yyS[yypt-0].item.(*ast.PartitionDefinition)) } - case 370: + case 377: { parser.yyVAL.item = &ast.PartitionDefinition{ Name: model.NewCIStr(yyS[yypt-3].ident), @@ -13322,80 +13411,80 @@ yynewstate: Sub: yyS[yypt-0].item.([]*ast.SubPartitionDefinition), } } - case 371: + case 378: { parser.yyVAL.item = make([]*ast.SubPartitionDefinition, 0) } - case 372: + case 379: { parser.yyVAL.item = yyS[yypt-1].item } - case 373: + case 380: { parser.yyVAL.item = []*ast.SubPartitionDefinition{yyS[yypt-0].item.(*ast.SubPartitionDefinition)} } - case 374: + case 381: { list := yyS[yypt-2].item.([]*ast.SubPartitionDefinition) parser.yyVAL.item = append(list, yyS[yypt-0].item.(*ast.SubPartitionDefinition)) } - case 375: + case 382: { parser.yyVAL.item = &ast.SubPartitionDefinition{ Name: model.NewCIStr(yyS[yypt-1].ident), Options: yyS[yypt-0].item.([]*ast.TableOption), } } - case 376: + case 383: { parser.yyVAL.item = make([]*ast.TableOption, 0) } - case 377: + case 384: { list := yyS[yypt-1].item.([]*ast.TableOption) parser.yyVAL.item = append(list, yyS[yypt-0].item.(*ast.TableOption)) } - case 378: + case 385: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionComment, StrValue: yyS[yypt-0].ident} } - case 379: + case 386: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: yyS[yypt-0].ident} } - case 380: + case 387: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: yyS[yypt-0].ident} } - case 381: + case 388: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionInsertMethod, StrValue: yyS[yypt-0].ident} } - case 382: + case 389: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionDataDirectory, StrValue: yyS[yypt-0].ident} } - case 383: + case 390: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionIndexDirectory, StrValue: yyS[yypt-0].ident} } - case 384: + case 391: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionMaxRows, UintValue: yyS[yypt-0].item.(uint64)} } - case 385: + case 392: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionMinRows, UintValue: yyS[yypt-0].item.(uint64)} } - case 386: + case 393: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionTablespace, StrValue: yyS[yypt-0].ident} } - case 387: + case 394: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionNodegroup, UintValue: yyS[yypt-0].item.(uint64)} } - case 388: + case 395: { placementOptions := yyS[yypt-0].item.(*ast.PlacementOption) parser.yyVAL.item = &ast.TableOption{ @@ -13405,27 +13494,27 @@ yynewstate: UintValue: placementOptions.UintValue, } } - case 389: + case 396: { parser.yyVAL.item = &ast.PartitionDefinitionClauseNone{} } - case 390: + case 397: { parser.yyVAL.item = &ast.PartitionDefinitionClauseLessThan{ Exprs: []ast.ExprNode{&ast.MaxValueExpr{}}, } } - case 391: + case 398: { parser.yyVAL.item = &ast.PartitionDefinitionClauseLessThan{ Exprs: yyS[yypt-1].item.([]ast.ExprNode), } } - case 392: + case 399: { parser.yyVAL.item = &ast.PartitionDefinitionClauseIn{} } - case 393: + case 400: { exprs := yyS[yypt-1].item.([]ast.ExprNode) values := make([][]ast.ExprNode, 0, len(exprs)) @@ -13438,43 +13527,43 @@ yynewstate: } parser.yyVAL.item = &ast.PartitionDefinitionClauseIn{Values: values} } - case 394: + case 401: { parser.yyVAL.item = &ast.PartitionDefinitionClauseHistory{Current: false} } - case 395: + case 402: { parser.yyVAL.item = &ast.PartitionDefinitionClauseHistory{Current: true} } - case 396: + case 403: { parser.yyVAL.item = ast.OnDuplicateKeyHandlingError } - case 397: + case 404: { parser.yyVAL.item = ast.OnDuplicateKeyHandlingIgnore } - case 398: + case 405: { parser.yyVAL.item = ast.OnDuplicateKeyHandlingReplace } - case 401: + case 408: { parser.yyVAL.item = &ast.CreateTableStmt{} } - case 402: + case 409: { parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 403: + case 410: { parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 404: + case 411: { parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 405: + case 412: { var sel ast.ResultSetNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -13487,7 +13576,7 @@ yynewstate: } parser.yyVAL.item = &ast.CreateTableStmt{Select: sel} } - case 409: + case 416: { var sel ast.StmtNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -13500,19 +13589,19 @@ yynewstate: } parser.yyVAL.statement = sel } - case 410: + case 417: { parser.yyVAL.item = yyS[yypt-0].item } - case 411: + case 418: { parser.yyVAL.item = yyS[yypt-1].item } - case 412: + case 419: { startOffset := parser.startOffset(&yyS[yypt-1]) selStmt := yyS[yypt-1].statement.(ast.StmtNode) - selStmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) x := &ast.CreateViewStmt{ OrReplace: yyS[yypt-9].item.(bool), ViewName: yyS[yypt-4].item.(*ast.TableName), @@ -13527,91 +13616,91 @@ yynewstate: if yyS[yypt-0].item != nil { x.CheckOption = yyS[yypt-0].item.(model.ViewCheckOption) endOffset := parser.startOffset(&yyS[yypt]) - selStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset])) + selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset])) } else { x.CheckOption = model.CheckOptionCascaded } parser.yyVAL.statement = x } - case 413: + case 420: { parser.yyVAL.item = false } - case 414: + case 421: { parser.yyVAL.item = true } - case 415: + case 422: { parser.yyVAL.item = model.AlgorithmUndefined } - case 416: + case 423: { parser.yyVAL.item = model.AlgorithmUndefined } - case 417: + case 424: { parser.yyVAL.item = model.AlgorithmMerge } - case 418: + case 425: { parser.yyVAL.item = model.AlgorithmTemptable } - case 419: + case 426: { parser.yyVAL.item = &auth.UserIdentity{CurrentUser: true} } - case 420: + case 427: { parser.yyVAL.item = yyS[yypt-0].item } - case 421: + case 428: { parser.yyVAL.item = model.SecurityDefiner } - case 422: + case 429: { parser.yyVAL.item = model.SecurityDefiner } - case 423: + case 430: { parser.yyVAL.item = model.SecurityInvoker } - case 425: + case 432: { parser.yyVAL.item = nil } - case 426: + case 433: { parser.yyVAL.item = yyS[yypt-1].item.([]model.CIStr) } - case 427: + case 434: { parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 428: + case 435: { parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) } - case 429: + case 436: { parser.yyVAL.item = nil } - case 430: + case 437: { parser.yyVAL.item = model.CheckOptionCascaded } - case 431: + case 438: { parser.yyVAL.item = model.CheckOptionLocal } - case 432: + case 439: { parser.yyVAL.statement = &ast.DoStmt{ Exprs: yyS[yypt-0].item.([]ast.ExprNode), } } - case 433: + case 440: { // Single Table tn := yyS[yypt-6].item.(*ast.TableName) @@ -13639,7 +13728,7 @@ yynewstate: parser.yyVAL.statement = x } - case 434: + case 441: { // Multiple Table x := &ast.DeleteStmt{ @@ -13659,7 +13748,7 @@ yynewstate: } parser.yyVAL.statement = x } - case 435: + case 442: { // Multiple Table x := &ast.DeleteStmt{ @@ -13678,23 +13767,23 @@ yynewstate: } parser.yyVAL.statement = x } - case 438: + case 445: { d := yyS[yypt-0].statement.(*ast.DeleteStmt) d.With = yyS[yypt-1].item.(*ast.WithClause) parser.yyVAL.statement = d } - case 439: + case 446: { d := yyS[yypt-0].statement.(*ast.DeleteStmt) d.With = yyS[yypt-1].item.(*ast.WithClause) parser.yyVAL.statement = d } - case 441: + case 448: { parser.yyVAL.statement = &ast.DropDatabaseStmt{IfExists: yyS[yypt-1].item.(bool), Name: yyS[yypt-0].ident} } - case 442: + case 449: { var indexLockAndAlgorithm *ast.IndexLockAndAlgorithm if yyS[yypt-0].item != nil { @@ -13705,39 +13794,39 @@ yynewstate: } parser.yyVAL.statement = &ast.DropIndexStmt{IfExists: yyS[yypt-4].item.(bool), IndexName: yyS[yypt-3].ident, Table: yyS[yypt-1].item.(*ast.TableName), LockAlg: indexLockAndAlgorithm} } - case 443: + case 450: { parser.yyVAL.statement = &ast.DropTableStmt{IfExists: yyS[yypt-2].item.(bool), Tables: yyS[yypt-1].item.([]*ast.TableName), IsView: false, TemporaryKeyword: yyS[yypt-4].item.(ast.TemporaryKeyword)} } - case 444: + case 451: { parser.yyVAL.item = ast.TemporaryNone } - case 445: + case 452: { parser.yyVAL.item = ast.TemporaryLocal } - case 446: + case 453: { parser.yyVAL.item = ast.TemporaryGlobal } - case 447: + case 454: { parser.yyVAL.statement = &ast.DropTableStmt{Tables: yyS[yypt-1].item.([]*ast.TableName), IsView: true} } - case 448: + case 455: { parser.yyVAL.statement = &ast.DropTableStmt{IfExists: true, Tables: yyS[yypt-1].item.([]*ast.TableName), IsView: true} } - case 449: + case 456: { parser.yyVAL.statement = &ast.DropUserStmt{IsDropRole: false, IfExists: false, UserList: yyS[yypt-0].item.([]*auth.UserIdentity)} } - case 450: + case 457: { parser.yyVAL.statement = &ast.DropUserStmt{IsDropRole: false, IfExists: true, UserList: yyS[yypt-0].item.([]*auth.UserIdentity)} } - case 451: + case 458: { tmp := make([]*auth.UserIdentity, 0, 10) roleList := yyS[yypt-0].item.([]*auth.RoleIdentity) @@ -13746,7 +13835,7 @@ yynewstate: } parser.yyVAL.statement = &ast.DropUserStmt{IsDropRole: true, IfExists: false, UserList: tmp} } - case 452: + case 459: { tmp := make([]*auth.UserIdentity, 0, 10) roleList := yyS[yypt-0].item.([]*auth.RoleIdentity) @@ -13755,29 +13844,29 @@ yynewstate: } parser.yyVAL.statement = &ast.DropUserStmt{IsDropRole: true, IfExists: true, UserList: tmp} } - case 453: + case 460: { parser.yyVAL.statement = &ast.DropStatsStmt{Table: yyS[yypt-0].item.(*ast.TableName)} } - case 454: + case 461: { parser.yyVAL.statement = &ast.DropStatsStmt{ Table: yyS[yypt-2].item.(*ast.TableName), PartitionNames: yyS[yypt-0].item.([]model.CIStr), } } - case 455: + case 462: { parser.yyVAL.statement = &ast.DropStatsStmt{ Table: yyS[yypt-1].item.(*ast.TableName), IsGlobalStats: true, } } - case 463: + case 470: { parser.yyVAL.statement = nil } - case 464: + case 471: { parser.yyVAL.statement = &ast.TraceStmt{ Stmt: yyS[yypt-0].statement, @@ -13785,9 +13874,9 @@ yynewstate: TracePlan: false, } startOffset := parser.startOffset(&yyS[yypt]) - yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + yyS[yypt-0].statement.SetText(parser.lexer.client, string(parser.src[startOffset:])) } - case 465: + case 472: { parser.yyVAL.statement = &ast.TraceStmt{ Stmt: yyS[yypt-0].statement, @@ -13795,18 +13884,18 @@ yynewstate: TracePlan: false, } startOffset := parser.startOffset(&yyS[yypt]) - yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + yyS[yypt-0].statement.SetText(parser.lexer.client, string(parser.src[startOffset:])) } - case 466: + case 473: { parser.yyVAL.statement = &ast.TraceStmt{ Stmt: yyS[yypt-0].statement, TracePlan: true, } startOffset := parser.startOffset(&yyS[yypt]) - yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + yyS[yypt-0].statement.SetText(parser.lexer.client, string(parser.src[startOffset:])) } - case 467: + case 474: { parser.yyVAL.statement = &ast.TraceStmt{ Stmt: yyS[yypt-0].statement, @@ -13814,9 +13903,9 @@ yynewstate: TracePlanTarget: yyS[yypt-1].ident, } startOffset := parser.startOffset(&yyS[yypt]) - yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + yyS[yypt-0].statement.SetText(parser.lexer.client, string(parser.src[startOffset:])) } - case 471: + case 478: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: &ast.ShowStmt{ @@ -13825,7 +13914,7 @@ yynewstate: }, } } - case 472: + case 479: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: &ast.ShowStmt{ @@ -13835,49 +13924,49 @@ yynewstate: }, } } - case 473: + case 480: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: yyS[yypt-0].statement, Format: "row", } } - case 474: + case 481: { parser.yyVAL.statement = &ast.ExplainForStmt{ Format: "row", ConnectionID: getUint64FromNUM(yyS[yypt-0].item), } } - case 475: + case 482: { parser.yyVAL.statement = &ast.ExplainForStmt{ Format: yyS[yypt-3].ident, ConnectionID: getUint64FromNUM(yyS[yypt-0].item), } } - case 476: + case 483: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: yyS[yypt-0].statement, Format: yyS[yypt-1].ident, } } - case 477: + case 484: { parser.yyVAL.statement = &ast.ExplainForStmt{ Format: yyS[yypt-3].ident, ConnectionID: getUint64FromNUM(yyS[yypt-0].item), } } - case 478: + case 485: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: yyS[yypt-0].statement, Format: yyS[yypt-1].ident, } } - case 479: + case 486: { parser.yyVAL.statement = &ast.ExplainStmt{ Stmt: yyS[yypt-0].statement, @@ -13885,7 +13974,7 @@ yynewstate: Analyze: true, } } - case 486: + case 493: { stmt := yyS[yypt-3].item.(*ast.BRIEStmt) stmt.Kind = ast.BRIEKindBackup @@ -13893,7 +13982,7 @@ yynewstate: stmt.Options = yyS[yypt-0].item.([]*ast.BRIEOption) parser.yyVAL.statement = stmt } - case 487: + case 494: { stmt := yyS[yypt-3].item.(*ast.BRIEStmt) stmt.Kind = ast.BRIEKindRestore @@ -13901,110 +13990,110 @@ yynewstate: stmt.Options = yyS[yypt-0].item.([]*ast.BRIEOption) parser.yyVAL.statement = stmt } - case 488: + case 495: { parser.yyVAL.item = &ast.BRIEStmt{} } - case 489: + case 496: { parser.yyVAL.item = &ast.BRIEStmt{Schemas: yyS[yypt-0].item.([]string)} } - case 490: + case 497: { parser.yyVAL.item = &ast.BRIEStmt{Tables: yyS[yypt-0].item.([]*ast.TableName)} } - case 491: + case 498: { parser.yyVAL.item = []string{yyS[yypt-0].ident} } - case 492: + case 499: { parser.yyVAL.item = append(yyS[yypt-2].item.([]string), yyS[yypt-0].ident) } - case 493: + case 500: { parser.yyVAL.item = []*ast.BRIEOption{} } - case 494: + case 501: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.BRIEOption), yyS[yypt-0].item.(*ast.BRIEOption)) } - case 495: + case 502: { parser.yyVAL.item = ast.BRIEOptionConcurrency } - case 496: + case 503: { parser.yyVAL.item = ast.BRIEOptionResume } - case 497: + case 504: { parser.yyVAL.item = ast.BRIEOptionSendCreds } - case 498: + case 505: { parser.yyVAL.item = ast.BRIEOptionOnline } - case 499: + case 506: { parser.yyVAL.item = ast.BRIEOptionCheckpoint } - case 500: + case 507: { parser.yyVAL.item = ast.BRIEOptionSkipSchemaFiles } - case 501: + case 508: { parser.yyVAL.item = ast.BRIEOptionStrictFormat } - case 502: + case 509: { parser.yyVAL.item = ast.BRIEOptionCSVNotNull } - case 503: + case 510: { parser.yyVAL.item = ast.BRIEOptionCSVBackslashEscape } - case 504: + case 511: { parser.yyVAL.item = ast.BRIEOptionCSVTrimLastSeparators } - case 505: + case 512: { parser.yyVAL.item = ast.BRIEOptionTiKVImporter } - case 506: + case 513: { parser.yyVAL.item = ast.BRIEOptionCSVSeparator } - case 507: + case 514: { parser.yyVAL.item = ast.BRIEOptionCSVDelimiter } - case 508: + case 515: { parser.yyVAL.item = ast.BRIEOptionCSVNull } - case 509: + case 516: { parser.yyVAL.item = ast.BRIEOptionBackend } - case 510: + case 517: { parser.yyVAL.item = ast.BRIEOptionOnDuplicate } - case 511: + case 518: { parser.yyVAL.item = ast.BRIEOptionOnDuplicate } - case 512: + case 519: { parser.yyVAL.item = &ast.BRIEOption{ Tp: yyS[yypt-2].item.(ast.BRIEOptionType), UintValue: yyS[yypt-0].item.(uint64), } } - case 513: + case 520: { value := uint64(0) if yyS[yypt-0].item.(bool) { @@ -14015,21 +14104,21 @@ yynewstate: UintValue: value, } } - case 514: + case 521: { parser.yyVAL.item = &ast.BRIEOption{ Tp: yyS[yypt-2].item.(ast.BRIEOptionType), StrValue: yyS[yypt-0].ident, } } - case 515: + case 522: { parser.yyVAL.item = &ast.BRIEOption{ Tp: yyS[yypt-2].item.(ast.BRIEOptionType), StrValue: strings.ToLower(yyS[yypt-0].ident), } } - case 516: + case 523: { unit, err := yyS[yypt-1].item.(ast.TimeUnitType).Duration() if err != nil { @@ -14042,35 +14131,35 @@ yynewstate: UintValue: yyS[yypt-2].item.(uint64) * uint64(unit), } } - case 517: + case 524: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionBackupTS, StrValue: yyS[yypt-0].ident, } } - case 518: + case 525: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionBackupTSO, UintValue: yyS[yypt-0].item.(uint64), } } - case 519: + case 526: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionLastBackupTS, StrValue: yyS[yypt-0].ident, } } - case 520: + case 527: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionLastBackupTSO, UintValue: yyS[yypt-0].item.(uint64), } } - case 521: + case 528: { // TODO: check overflow? parser.yyVAL.item = &ast.BRIEOption{ @@ -14078,21 +14167,21 @@ yynewstate: UintValue: yyS[yypt-3].item.(uint64) * 1048576, } } - case 522: + case 529: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionCSVHeader, UintValue: ast.BRIECSVHeaderIsColumns, } } - case 523: + case 530: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionCSVHeader, UintValue: yyS[yypt-0].item.(uint64), } } - case 524: + case 531: { value := uint64(0) if yyS[yypt-0].item.(bool) { @@ -14103,14 +14192,14 @@ yynewstate: UintValue: value, } } - case 525: + case 532: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionChecksum, UintValue: uint64(yyS[yypt-0].item.(ast.BRIEOptionLevel)), } } - case 526: + case 533: { value := uint64(0) if yyS[yypt-0].item.(bool) { @@ -14121,18 +14210,18 @@ yynewstate: UintValue: value, } } - case 527: + case 534: { parser.yyVAL.item = &ast.BRIEOption{ Tp: ast.BRIEOptionAnalyze, UintValue: uint64(yyS[yypt-0].item.(ast.BRIEOptionLevel)), } } - case 528: + case 535: { parser.yyVAL.item = getUint64FromNUM(yyS[yypt-0].item) } - case 529: + case 536: { v, rangeErrMsg := getInt64FromNUM(yyS[yypt-0].item) if len(rangeErrMsg) != 0 { @@ -14141,35 +14230,35 @@ yynewstate: } parser.yyVAL.item = v } - case 531: + case 538: { parser.yyVAL.item = yyS[yypt-0].item.(int64) != 0 } - case 532: + case 539: { parser.yyVAL.item = false } - case 533: + case 540: { parser.yyVAL.item = true } - case 534: + case 541: { parser.yyVAL.item = ast.BRIEOptionLevelOff } - case 535: + case 542: { parser.yyVAL.item = ast.BRIEOptionLevelOptional } - case 536: + case 543: { parser.yyVAL.item = ast.BRIEOptionLevelRequired } - case 537: + case 544: { parser.yyVAL.statement = &ast.PurgeImportStmt{TaskID: getUint64FromNUM(yyS[yypt-0].item)} } - case 538: + case 545: { parser.yyVAL.statement = &ast.CreateImportStmt{ IfNotExists: yyS[yypt-5].item.(bool), @@ -14179,21 +14268,21 @@ yynewstate: Options: yyS[yypt-0].item.([]*ast.BRIEOption), } } - case 539: + case 546: { parser.yyVAL.statement = &ast.StopImportStmt{ IfRunning: yyS[yypt-1].item.(bool), Name: yyS[yypt-0].ident, } } - case 540: + case 547: { parser.yyVAL.statement = &ast.ResumeImportStmt{ IfNotRunning: yyS[yypt-1].item.(bool), Name: yyS[yypt-0].ident, } } - case 541: + case 548: { s := &ast.AlterImportStmt{ Name: yyS[yypt-3].ident, @@ -14205,14 +14294,14 @@ yynewstate: } parser.yyVAL.statement = s } - case 542: + case 549: { parser.yyVAL.statement = &ast.DropImportStmt{ IfExists: yyS[yypt-1].item.(bool), Name: yyS[yypt-0].ident, } } - case 543: + case 550: { parser.yyVAL.statement = &ast.ShowImportStmt{ Name: yyS[yypt-2].ident, @@ -14220,73 +14309,73 @@ yynewstate: TableNames: yyS[yypt-0].item.([]*ast.TableName), } } - case 544: + case 551: { parser.yyVAL.item = false } - case 545: + case 552: { parser.yyVAL.item = true } - case 546: + case 553: { parser.yyVAL.item = false } - case 547: + case 554: { parser.yyVAL.item = true } - case 548: + case 555: { parser.yyVAL.item = false } - case 549: + case 556: { parser.yyVAL.item = true } - case 550: + case 557: { parser.yyVAL.item = ast.ErrorHandleError } - case 551: + case 558: { parser.yyVAL.item = ast.ErrorHandleReplace } - case 552: + case 559: { parser.yyVAL.item = ast.ErrorHandleSkipAll } - case 553: + case 560: { parser.yyVAL.item = ast.ErrorHandleSkipConstraint } - case 554: + case 561: { parser.yyVAL.item = ast.ErrorHandleSkipDuplicate } - case 555: + case 562: { parser.yyVAL.item = ast.ErrorHandleSkipStrict } - case 556: + case 563: { parser.yyVAL.item = nil } - case 557: + case 564: { parser.yyVAL.item = &ast.ImportTruncate{ IsErrorsOnly: false, TableNames: yyS[yypt-0].item.([]*ast.TableName), } } - case 558: + case 565: { parser.yyVAL.item = &ast.ImportTruncate{ IsErrorsOnly: true, TableNames: yyS[yypt-0].item.([]*ast.TableName), } } - case 559: + case 566: { v := yyS[yypt-2].ident v = strings.TrimPrefix(v, "@") @@ -14297,19 +14386,19 @@ yynewstate: Value: yyS[yypt-0].expr, } } - case 560: + case 567: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicOr, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 561: + case 568: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicXor, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 562: + case 569: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicAnd, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 563: + case 570: { expr, ok := yyS[yypt-0].expr.(*ast.ExistsSubqueryExpr) if ok { @@ -14319,7 +14408,7 @@ yynewstate: parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not, V: yyS[yypt-0].expr} } } - case 564: + case 571: { parser.yyVAL.expr = &ast.MatchAgainst{ ColumnNames: yyS[yypt-6].item.([]*ast.ColumnName), @@ -14327,87 +14416,87 @@ yynewstate: Modifier: ast.FulltextSearchModifier(yyS[yypt-1].item.(int)), } } - case 565: + case 572: { parser.yyVAL.expr = &ast.IsTruthExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), True: int64(1)} } - case 566: + case 573: { parser.yyVAL.expr = &ast.IsTruthExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), True: int64(0)} } - case 567: + case 574: { /* https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_is */ parser.yyVAL.expr = &ast.IsNullExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool)} } - case 569: + case 576: { parser.yyVAL.expr = &ast.MaxValueExpr{} } - case 571: + case 578: { parser.yyVAL.item = ast.FulltextSearchModifierNaturalLanguageMode } - case 572: + case 579: { parser.yyVAL.item = ast.FulltextSearchModifierNaturalLanguageMode } - case 573: + case 580: { parser.yyVAL.item = ast.FulltextSearchModifierNaturalLanguageMode | ast.FulltextSearchModifierWithQueryExpansion } - case 574: + case 581: { parser.yyVAL.item = ast.FulltextSearchModifierBooleanMode } - case 575: + case 582: { parser.yyVAL.item = ast.FulltextSearchModifierWithQueryExpansion } - case 580: + case 587: { parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} } - case 581: + case 588: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) } - case 582: + case 589: { parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} } - case 583: + case 590: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) } - case 584: + case 591: { parser.yyVAL.item = []ast.ExprNode{} } - case 586: + case 593: { parser.yyVAL.item = []ast.ExprNode{} } - case 588: + case 595: { expr := ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) parser.yyVAL.item = []ast.ExprNode{expr} } - case 589: + case 596: { parser.yyVAL.expr = &ast.IsNullExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool)} } - case 590: + case 597: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: yyS[yypt-1].item.(opcode.Op), L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 591: + case 598: { sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) sq.MultiRows = true parser.yyVAL.expr = &ast.CompareSubqueryExpr{Op: yyS[yypt-2].item.(opcode.Op), L: yyS[yypt-3].expr, R: sq, All: yyS[yypt-1].item.(bool)} } - case 592: + case 599: { v := yyS[yypt-2].ident v = strings.TrimPrefix(v, "@") @@ -14419,101 +14508,101 @@ yynewstate: } parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: yyS[yypt-3].item.(opcode.Op), L: yyS[yypt-4].expr, R: variable} } - case 594: + case 601: { parser.yyVAL.item = opcode.GE } - case 595: + case 602: { parser.yyVAL.item = opcode.GT } - case 596: + case 603: { parser.yyVAL.item = opcode.LE } - case 597: + case 604: { parser.yyVAL.item = opcode.LT } - case 598: + case 605: { parser.yyVAL.item = opcode.NE } - case 599: + case 606: { parser.yyVAL.item = opcode.NE } - case 600: + case 607: { parser.yyVAL.item = opcode.EQ } - case 601: + case 608: { parser.yyVAL.item = opcode.NullEQ } - case 602: + case 609: { parser.yyVAL.item = true } - case 603: + case 610: { parser.yyVAL.item = false } - case 604: + case 611: { parser.yyVAL.item = true } - case 605: + case 612: { parser.yyVAL.item = false } - case 606: + case 613: { parser.yyVAL.item = true } - case 607: + case 614: { parser.yyVAL.item = false } - case 608: + case 615: { parser.yyVAL.item = true } - case 609: + case 616: { parser.yyVAL.item = false } - case 610: + case 617: { parser.yyVAL.item = true } - case 611: + case 618: { parser.yyVAL.item = false } - case 612: + case 619: { parser.yyVAL.item = false } - case 613: + case 620: { parser.yyVAL.item = false } - case 614: + case 621: { parser.yyVAL.item = true } - case 615: + case 622: { parser.yyVAL.expr = &ast.PatternInExpr{Expr: yyS[yypt-4].expr, Not: !yyS[yypt-3].item.(bool), List: yyS[yypt-1].item.([]ast.ExprNode)} } - case 616: + case 623: { sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) sq.MultiRows = true parser.yyVAL.expr = &ast.PatternInExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), Sel: sq} } - case 617: + case 624: { parser.yyVAL.expr = &ast.BetweenExpr{ Expr: yyS[yypt-4].expr, @@ -14522,7 +14611,7 @@ yynewstate: Not: !yyS[yypt-3].item.(bool), } } - case 618: + case 625: { escape := yyS[yypt-0].ident if len(escape) > 1 { @@ -14538,133 +14627,133 @@ yynewstate: Escape: escape[0], } } - case 619: + case 626: { parser.yyVAL.expr = &ast.PatternRegexpExpr{Expr: yyS[yypt-2].expr, Pattern: yyS[yypt-0].expr, Not: !yyS[yypt-1].item.(bool)} } - case 623: + case 630: { parser.yyVAL.ident = "\\" } - case 624: + case 631: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 625: + case 632: { parser.yyVAL.item = &ast.SelectField{WildCard: &ast.WildCardField{}} } - case 626: + case 633: { wildCard := &ast.WildCardField{Table: model.NewCIStr(yyS[yypt-2].ident)} parser.yyVAL.item = &ast.SelectField{WildCard: wildCard} } - case 627: + case 634: { wildCard := &ast.WildCardField{Schema: model.NewCIStr(yyS[yypt-4].ident), Table: model.NewCIStr(yyS[yypt-2].ident)} parser.yyVAL.item = &ast.SelectField{WildCard: wildCard} } - case 628: + case 635: { expr := yyS[yypt-1].expr asName := yyS[yypt-0].ident parser.yyVAL.item = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)} } - case 629: + case 636: { parser.yyVAL.ident = "" } - case 632: + case 639: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 634: + case 641: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 635: + case 642: { field := yyS[yypt-0].item.(*ast.SelectField) field.Offset = parser.startOffset(&yyS[yypt]) parser.yyVAL.item = []*ast.SelectField{field} } - case 636: + case 643: { fl := yyS[yypt-2].item.([]*ast.SelectField) last := fl[len(fl)-1] if last.Expr != nil && last.AsName.O == "" { lastEnd := parser.endOffset(&yyS[yypt-1]) - last.SetText(parser.src[last.Offset:lastEnd]) + last.SetText(parser.lexer.client, parser.src[last.Offset:lastEnd]) } newField := yyS[yypt-0].item.(*ast.SelectField) newField.Offset = parser.startOffset(&yyS[yypt]) parser.yyVAL.item = append(fl, newField) } - case 637: + case 644: { parser.yyVAL.item = &ast.GroupByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} } - case 638: + case 645: { parser.yyVAL.item = nil } - case 639: + case 646: { parser.yyVAL.item = &ast.HavingClause{Expr: yyS[yypt-0].expr} } - case 640: + case 647: { parser.yyVAL.item = nil } - case 642: + case 649: { parser.yyVAL.item = &ast.AsOfClause{ TsExpr: yyS[yypt-0].expr.(ast.ExprNode), } } - case 643: + case 650: { parser.yyVAL.item = false } - case 644: + case 651: { parser.yyVAL.item = true } - case 645: + case 652: { parser.yyVAL.item = false } - case 646: + case 653: { parser.yyVAL.item = true } - case 647: + case 654: { parser.yyVAL.item = false } - case 648: + case 655: { parser.yyVAL.item = true } - case 649: + case 656: { parser.yyVAL.item = &ast.NullString{ String: "", Empty: false, } } - case 650: + case 657: { parser.yyVAL.item = &ast.NullString{ String: yyS[yypt-0].ident, Empty: len(yyS[yypt-0].ident) == 0, } } - case 651: + case 658: { parser.yyVAL.item = nil } - case 652: + case 659: { // Merge the options if yyS[yypt-1].item == nil { @@ -14688,19 +14777,19 @@ yynewstate: parser.yyVAL.item = opt1 } } - case 653: + case 660: { parser.yyVAL.item = &ast.IndexOption{ KeyBlockSize: yyS[yypt-0].item.(uint64), } } - case 654: + case 661: { parser.yyVAL.item = &ast.IndexOption{ Tp: yyS[yypt-0].item.(model.IndexType), } } - case 655: + case 662: { parser.yyVAL.item = &ast.IndexOption{ ParserName: model.NewCIStr(yyS[yypt-0].ident), @@ -14708,75 +14797,75 @@ yynewstate: yylex.AppendError(yylex.Errorf("The WITH PARASER clause is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 656: + case 663: { parser.yyVAL.item = &ast.IndexOption{ Comment: yyS[yypt-0].ident, } } - case 657: + case 664: { parser.yyVAL.item = &ast.IndexOption{ Visibility: yyS[yypt-0].item.(ast.IndexVisibility), } } - case 658: + case 665: { parser.yyVAL.item = &ast.IndexOption{ PrimaryKeyTp: yyS[yypt-0].item.(model.PrimaryKeyType), } } - case 659: + case 666: { parser.yyVAL.item = []interface{}{yyS[yypt-0].item, nil} } - case 660: + case 667: { parser.yyVAL.item = []interface{}{yyS[yypt-2].item, yyS[yypt-0].item} } - case 661: + case 668: { parser.yyVAL.item = []interface{}{&ast.NullString{String: yyS[yypt-2].ident, Empty: len(yyS[yypt-2].ident) == 0}, yyS[yypt-0].item} } - case 662: + case 669: { parser.yyVAL.item = nil } - case 664: + case 671: { parser.yyVAL.item = yyS[yypt-0].item } - case 665: + case 672: { parser.yyVAL.item = yyS[yypt-0].item } - case 666: + case 673: { parser.yyVAL.item = model.IndexTypeBtree } - case 667: + case 674: { parser.yyVAL.item = model.IndexTypeHash } - case 668: + case 675: { parser.yyVAL.item = model.IndexTypeRtree } - case 669: + case 676: { parser.yyVAL.item = ast.IndexVisibilityVisible } - case 670: + case 677: { parser.yyVAL.item = ast.IndexVisibilityInvisible } - case 1131: + case 1141: { parser.yyVAL.statement = &ast.CallStmt{ Procedure: yyS[yypt-0].expr.(*ast.FuncCallExpr), } } - case 1132: + case 1142: { parser.yyVAL.expr = &ast.FuncCallExpr{ Tp: ast.FuncCallExprTypeGeneric, @@ -14784,7 +14873,7 @@ yynewstate: Args: []ast.ExprNode{}, } } - case 1133: + case 1143: { parser.yyVAL.expr = &ast.FuncCallExpr{ Tp: ast.FuncCallExprTypeGeneric, @@ -14793,7 +14882,7 @@ yynewstate: Args: []ast.ExprNode{}, } } - case 1134: + case 1144: { parser.yyVAL.expr = &ast.FuncCallExpr{ Tp: ast.FuncCallExprTypeGeneric, @@ -14801,7 +14890,7 @@ yynewstate: Args: yyS[yypt-1].item.([]ast.ExprNode), } } - case 1135: + case 1145: { parser.yyVAL.expr = &ast.FuncCallExpr{ Tp: ast.FuncCallExprTypeGeneric, @@ -14810,7 +14899,7 @@ yynewstate: Args: yyS[yypt-1].item.([]ast.ExprNode), } } - case 1136: + case 1146: { x := yyS[yypt-1].item.(*ast.InsertStmt) x.Priority = yyS[yypt-6].item.(mysql.PriorityEnum) @@ -14827,26 +14916,26 @@ yynewstate: x.PartitionNames = yyS[yypt-2].item.([]model.CIStr) parser.yyVAL.statement = x } - case 1139: + case 1149: { parser.yyVAL.item = &ast.InsertStmt{ Columns: yyS[yypt-3].item.([]*ast.ColumnName), Lists: yyS[yypt-0].item.([][]ast.ExprNode), } } - case 1140: + case 1150: { parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1141: + case 1151: { parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1142: + case 1152: { parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1143: + case 1153: { var sel ast.ResultSetNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -14859,23 +14948,23 @@ yynewstate: } parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: sel} } - case 1144: + case 1154: { parser.yyVAL.item = &ast.InsertStmt{Lists: yyS[yypt-0].item.([][]ast.ExprNode)} } - case 1145: + case 1155: { parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1146: + case 1156: { parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1147: + case 1157: { parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-0].statement.(ast.ResultSetNode)} } - case 1148: + case 1158: { var sel ast.ResultSetNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -14888,66 +14977,66 @@ yynewstate: } parser.yyVAL.item = &ast.InsertStmt{Select: sel} } - case 1149: + case 1159: { parser.yyVAL.item = &ast.InsertStmt{Setlist: yyS[yypt-0].item.([]*ast.Assignment)} } - case 1152: + case 1162: { parser.yyVAL.item = [][]ast.ExprNode{yyS[yypt-0].item.([]ast.ExprNode)} } - case 1153: + case 1163: { parser.yyVAL.item = append(yyS[yypt-2].item.([][]ast.ExprNode), yyS[yypt-0].item.([]ast.ExprNode)) } - case 1154: + case 1164: { parser.yyVAL.item = yyS[yypt-1].item } - case 1155: + case 1165: { parser.yyVAL.item = []ast.ExprNode{} } - case 1157: + case 1167: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) } - case 1158: + case 1168: { parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} } - case 1160: + case 1170: { parser.yyVAL.expr = &ast.DefaultExpr{} } - case 1161: + case 1171: { parser.yyVAL.item = &ast.Assignment{ Column: yyS[yypt-2].item.(*ast.ColumnName), Expr: yyS[yypt-0].expr, } } - case 1162: + case 1172: { parser.yyVAL.item = []*ast.Assignment{} } - case 1163: + case 1173: { parser.yyVAL.item = []*ast.Assignment{yyS[yypt-0].item.(*ast.Assignment)} } - case 1164: + case 1174: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.Assignment), yyS[yypt-0].item.(*ast.Assignment)) } - case 1165: + case 1175: { parser.yyVAL.item = nil } - case 1166: + case 1176: { parser.yyVAL.item = yyS[yypt-0].item } - case 1167: + case 1177: { x := yyS[yypt-0].item.(*ast.InsertStmt) x.IsReplace = true @@ -14957,31 +15046,31 @@ yynewstate: x.PartitionNames = yyS[yypt-1].item.([]model.CIStr) parser.yyVAL.statement = x } - case 1168: + case 1178: { parser.yyVAL.expr = ast.NewValueExpr(false, parser.charset, parser.collation) } - case 1169: + case 1179: { parser.yyVAL.expr = ast.NewValueExpr(nil, parser.charset, parser.collation) } - case 1170: + case 1180: { parser.yyVAL.expr = ast.NewValueExpr(true, parser.charset, parser.collation) } - case 1171: + case 1181: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1172: + case 1182: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1173: + case 1183: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1175: + case 1185: { // See https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html co, err := charset.GetDefaultCollationLegacy(yyS[yypt-1].ident) @@ -14989,7 +15078,7 @@ yynewstate: yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", yyS[yypt-1].ident)) return 1 } - expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation) + expr := ast.NewValueExpr(yyS[yypt-0].ident, yyS[yypt-1].ident, co) tp := expr.GetType() tp.Charset = yyS[yypt-1].ident tp.Collate = co @@ -14998,22 +15087,22 @@ yynewstate: } parser.yyVAL.expr = expr } - case 1176: + case 1186: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1177: + case 1187: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1178: + case 1188: { co, err := charset.GetDefaultCollationLegacy(yyS[yypt-1].ident) if err != nil { yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", yyS[yypt-1].ident)) return 1 } - expr := ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) + expr := ast.NewValueExpr(yyS[yypt-0].item, yyS[yypt-1].ident, co) tp := expr.GetType() tp.Charset = yyS[yypt-1].ident tp.Collate = co @@ -15022,14 +15111,14 @@ yynewstate: } parser.yyVAL.expr = expr } - case 1179: + case 1189: { co, err := charset.GetDefaultCollationLegacy(yyS[yypt-1].ident) if err != nil { yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", yyS[yypt-1].ident)) return 1 } - expr := ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) + expr := ast.NewValueExpr(yyS[yypt-0].item, yyS[yypt-1].ident, co) tp := expr.GetType() tp.Charset = yyS[yypt-1].ident tp.Collate = co @@ -15038,12 +15127,12 @@ yynewstate: } parser.yyVAL.expr = expr } - case 1180: + case 1190: { expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation) parser.yyVAL.expr = expr } - case 1181: + case 1191: { valExpr := yyS[yypt-1].expr.(ast.ValueExpr) strLit := valExpr.GetString() @@ -15056,31 +15145,31 @@ yynewstate: } parser.yyVAL.expr = expr } - case 1182: + case 1192: { parser.yyVAL.item = []*ast.AlterOrderItem{yyS[yypt-0].item.(*ast.AlterOrderItem)} } - case 1183: + case 1193: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.AlterOrderItem), yyS[yypt-0].item.(*ast.AlterOrderItem)) } - case 1184: + case 1194: { parser.yyVAL.item = &ast.AlterOrderItem{Column: yyS[yypt-1].item.(*ast.ColumnName), Desc: yyS[yypt-0].item.(bool)} } - case 1185: + case 1195: { parser.yyVAL.item = &ast.OrderByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} } - case 1186: + case 1196: { parser.yyVAL.item = []*ast.ByItem{yyS[yypt-0].item.(*ast.ByItem)} } - case 1187: + case 1197: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ByItem), yyS[yypt-0].item.(*ast.ByItem)) } - case 1188: + case 1198: { expr := yyS[yypt-0].expr valueExpr, ok := expr.(ast.ValueExpr) @@ -15092,7 +15181,7 @@ yynewstate: } parser.yyVAL.item = &ast.ByItem{Expr: expr, NullOrder: true} } - case 1189: + case 1199: { expr := yyS[yypt-1].expr valueExpr, ok := expr.(ast.ValueExpr) @@ -15104,55 +15193,55 @@ yynewstate: } parser.yyVAL.item = &ast.ByItem{Expr: expr, Desc: yyS[yypt-0].item.(bool)} } - case 1190: + case 1200: { parser.yyVAL.item = false } - case 1191: + case 1201: { parser.yyVAL.item = true } - case 1192: + case 1202: { parser.yyVAL.item = false // ASC by default } - case 1193: + case 1203: { parser.yyVAL.item = false } - case 1194: + case 1204: { parser.yyVAL.item = true } - case 1195: + case 1205: { parser.yyVAL.item = nil } - case 1197: + case 1207: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Or, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1198: + case 1208: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.And, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1199: + case 1209: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LeftShift, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1200: + case 1210: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.RightShift, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1201: + case 1211: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Plus, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1202: + case 1212: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Minus, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1203: + case 1213: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("DATE_ADD"), @@ -15163,7 +15252,7 @@ yynewstate: }, } } - case 1204: + case 1214: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("DATE_SUB"), @@ -15174,44 +15263,44 @@ yynewstate: }, } } - case 1205: + case 1215: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mul, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1206: + case 1216: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Div, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1207: + case 1217: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1208: + case 1218: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.IntDiv, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1209: + case 1219: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1210: + case 1220: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Xor, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} } - case 1212: + case 1222: { parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ Name: model.NewCIStr(yyS[yypt-0].ident), }} } - case 1213: + case 1223: { parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ Table: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident), }} } - case 1214: + case 1224: { parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ Schema: model.NewCIStr(yyS[yypt-4].ident), @@ -15219,63 +15308,63 @@ yynewstate: Name: model.NewCIStr(yyS[yypt-0].ident), }} } - case 1219: + case 1229: { parser.yyVAL.expr = &ast.SetCollationExpr{Expr: yyS[yypt-2].expr, Collate: yyS[yypt-0].ident} } - case 1222: + case 1232: { parser.yyVAL.expr = ast.NewParamMarkerExpr(yyS[yypt].offset) } - case 1225: + case 1235: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not2, V: yyS[yypt-0].expr} } - case 1226: + case 1236: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.BitNeg, V: yyS[yypt-0].expr} } - case 1227: + case 1237: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: yyS[yypt-0].expr} } - case 1228: + case 1238: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: yyS[yypt-0].expr} } - case 1229: + case 1239: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.Concat), Args: []ast.ExprNode{yyS[yypt-2].expr, yyS[yypt-0].expr}} } - case 1230: + case 1240: { parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not2, V: yyS[yypt-0].expr} } - case 1232: + case 1242: { startOffset := parser.startOffset(&yyS[yypt-1]) endOffset := parser.endOffset(&yyS[yypt]) expr := yyS[yypt-1].expr - expr.SetText(parser.src[startOffset:endOffset]) + expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset]) parser.yyVAL.expr = &ast.ParenthesesExpr{Expr: expr} } - case 1233: + case 1243: { values := append(yyS[yypt-3].item.([]ast.ExprNode), yyS[yypt-1].expr) parser.yyVAL.expr = &ast.RowExpr{Values: values} } - case 1234: + case 1244: { values := append(yyS[yypt-3].item.([]ast.ExprNode), yyS[yypt-1].expr) parser.yyVAL.expr = &ast.RowExpr{Values: values} } - case 1235: + case 1245: { sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) sq.Exists = true parser.yyVAL.expr = &ast.ExistsSubqueryExpr{Sel: sq} } - case 1236: + case 1246: { /* * ODBC escape syntax. @@ -15299,7 +15388,7 @@ yynewstate: parser.yyVAL.expr = yyS[yypt-1].expr } } - case 1237: + case 1247: { // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#operator_binary x := types.NewFieldType(mysql.TypeString) @@ -15312,7 +15401,7 @@ yynewstate: FunctionType: ast.CastBinaryOperator, } } - case 1238: + case 1248: { /* See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast */ tp := yyS[yypt-1].item.(*types.FieldType) @@ -15332,7 +15421,7 @@ yynewstate: ExplicitCharSet: explicitCharset, } } - case 1239: + case 1249: { x := &ast.CaseExpr{WhenClauses: yyS[yypt-2].item.([]*ast.WhenClause)} if yyS[yypt-3].expr != nil { @@ -15343,7 +15432,7 @@ yynewstate: } parser.yyVAL.expr = x } - case 1240: + case 1250: { // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert tp := yyS[yypt-1].item.(*types.FieldType) @@ -15363,7 +15452,7 @@ yynewstate: ExplicitCharSet: explicitCharset, } } - case 1241: + case 1251: { // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert charset1 := ast.NewValueExpr(yyS[yypt-1].ident, "", "") @@ -15372,62 +15461,62 @@ yynewstate: Args: []ast.ExprNode{yyS[yypt-3].expr, charset1}, } } - case 1242: + case 1252: { parser.yyVAL.expr = &ast.DefaultExpr{Name: yyS[yypt-1].expr.(*ast.ColumnNameExpr).Name} } - case 1243: + case 1253: { parser.yyVAL.expr = &ast.ValuesExpr{Column: yyS[yypt-1].expr.(*ast.ColumnNameExpr)} } - case 1244: + case 1254: { expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation) parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}} } - case 1245: + case 1255: { expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation) extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}} parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}} } - case 1248: + case 1258: { parser.yyVAL.item = false } - case 1249: + case 1259: { parser.yyVAL.item = true } - case 1250: + case 1260: { parser.yyVAL.item = false } - case 1252: + case 1262: { parser.yyVAL.item = true } - case 1255: + case 1265: { parser.yyVAL.item = true } - case 1297: + case 1307: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1298: + case 1308: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1299: + case 1309: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-1].ident)} } - case 1300: + case 1310: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-2].ident)} } - case 1301: + case 1311: { args := []ast.ExprNode{} if yyS[yypt-0].item != nil { @@ -15435,7 +15524,7 @@ yynewstate: } parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-1].ident), Args: args} } - case 1302: + case 1312: { nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation) args := yyS[yypt-1].item.([]ast.ExprNode) @@ -15444,7 +15533,7 @@ yynewstate: Args: append(args, nilVal), } } - case 1303: + case 1313: { charset1 := ast.NewValueExpr(yyS[yypt-1].ident, "", "") args := yyS[yypt-3].item.([]ast.ExprNode) @@ -15453,42 +15542,42 @@ yynewstate: Args: append(args, charset1), } } - case 1304: + case 1314: { expr := ast.NewValueExpr(yyS[yypt-0].ident, "", "") parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}} } - case 1305: + case 1315: { expr := ast.NewValueExpr(yyS[yypt-0].ident, "", "") parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}} } - case 1306: + case 1316: { expr := ast.NewValueExpr(yyS[yypt-0].ident, "", "") parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}} } - case 1307: + case 1317: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.InsertFunc), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1308: + case 1318: { parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-3].expr, R: yyS[yypt-1].expr} } - case 1309: + case 1319: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.PasswordFunc), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1310: + case 1320: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1311: + case 1321: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1312: + case 1322: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-5].ident), @@ -15499,7 +15588,7 @@ yynewstate: }, } } - case 1313: + case 1323: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), @@ -15510,7 +15599,7 @@ yynewstate: }, } } - case 1314: + case 1324: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), @@ -15521,7 +15610,7 @@ yynewstate: }, } } - case 1315: + case 1325: { timeUnit := &ast.TimeUnitExpr{Unit: yyS[yypt-3].item.(ast.TimeUnitType)} parser.yyVAL.expr = &ast.FuncCallExpr{ @@ -15529,7 +15618,7 @@ yynewstate: Args: []ast.ExprNode{timeUnit, yyS[yypt-1].expr}, } } - case 1316: + case 1326: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-5].ident), @@ -15539,67 +15628,67 @@ yynewstate: }, } } - case 1317: + case 1327: { parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-5].ident), Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}} } - case 1318: + case 1328: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-5].ident), Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1319: + case 1329: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-5].ident), Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1320: + case 1330: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1321: + case 1331: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1322: + case 1332: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), Args: []ast.ExprNode{&ast.TimeUnitExpr{Unit: yyS[yypt-5].item.(ast.TimeUnitType)}, yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1323: + case 1333: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), Args: []ast.ExprNode{&ast.TimeUnitExpr{Unit: yyS[yypt-5].item.(ast.TimeUnitType)}, yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1324: + case 1334: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-3].ident), Args: []ast.ExprNode{yyS[yypt-1].expr}, } } - case 1325: + case 1335: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-5].ident), Args: []ast.ExprNode{yyS[yypt-1].expr, yyS[yypt-3].expr}, } } - case 1326: + case 1336: { spaceVal := ast.NewValueExpr(" ", parser.charset, parser.collation) direction := &ast.TrimDirectionExpr{Direction: yyS[yypt-3].item.(ast.TrimDirectionType)} @@ -15608,7 +15697,7 @@ yynewstate: Args: []ast.ExprNode{yyS[yypt-1].expr, spaceVal, direction}, } } - case 1327: + case 1337: { direction := &ast.TrimDirectionExpr{Direction: yyS[yypt-4].item.(ast.TrimDirectionType)} parser.yyVAL.expr = &ast.FuncCallExpr{ @@ -15616,63 +15705,63 @@ yynewstate: Args: []ast.ExprNode{yyS[yypt-1].expr, yyS[yypt-3].expr, direction}, } } - case 1328: + case 1338: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-3].ident), Args: []ast.ExprNode{yyS[yypt-1].expr}, } } - case 1329: + case 1339: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-6].ident), Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("CHAR", parser.charset, parser.collation), ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}, } } - case 1330: + case 1340: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-6].ident), Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("BINARY", parser.charset, parser.collation), ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}, } } - case 1332: + case 1342: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-7].ident), Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-3].expr, yyS[yypt-1].expr}, } } - case 1333: + case 1343: { parser.yyVAL.item = ast.GetFormatSelectorDate } - case 1334: + case 1344: { parser.yyVAL.item = ast.GetFormatSelectorDatetime } - case 1335: + case 1345: { parser.yyVAL.item = ast.GetFormatSelectorTime } - case 1336: + case 1346: { parser.yyVAL.item = ast.GetFormatSelectorDatetime } - case 1341: + case 1351: { parser.yyVAL.item = ast.TrimBoth } - case 1342: + case 1352: { parser.yyVAL.item = ast.TrimLeading } - case 1343: + case 1353: { parser.yyVAL.item = ast.TrimTrailing } - case 1344: + case 1354: { objNameExpr := &ast.TableNameExpr{ Name: yyS[yypt-1].item.(*ast.TableName), @@ -15682,7 +15771,7 @@ yynewstate: Args: []ast.ExprNode{objNameExpr}, } } - case 1345: + case 1355: { objNameExpr := &ast.TableNameExpr{ Name: yyS[yypt-3].item.(*ast.TableName), @@ -15693,7 +15782,7 @@ yynewstate: Args: []ast.ExprNode{objNameExpr, valueExpr}, } } - case 1347: + case 1357: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15701,15 +15790,15 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1348: + case 1358: { parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-3].ident, Args: yyS[yypt-1].item.([]ast.ExprNode), Distinct: false} } - case 1349: + case 1359: { parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-3].ident, Args: yyS[yypt-1].item.([]ast.ExprNode)} } - case 1350: + case 1360: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15717,7 +15806,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1351: + case 1361: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15725,7 +15814,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1352: + case 1362: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15733,7 +15822,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1353: + case 1363: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15741,7 +15830,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1354: + case 1364: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15749,7 +15838,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1355: + case 1365: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15757,11 +15846,11 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1356: + case 1366: { parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: yyS[yypt-1].item.([]ast.ExprNode), Distinct: true} } - case 1357: + case 1367: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15769,7 +15858,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1358: + case 1368: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15777,7 +15866,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1359: + case 1369: { args := []ast.ExprNode{ast.NewValueExpr(1, parser.charset, parser.collation)} if yyS[yypt-0].item != nil { @@ -15786,7 +15875,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: args} } } - case 1360: + case 1370: { args := yyS[yypt-4].item.([]ast.ExprNode) args = append(args, yyS[yypt-2].item.(ast.ExprNode)) @@ -15800,7 +15889,7 @@ yynewstate: parser.yyVAL.expr = agg } } - case 1361: + case 1371: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15808,7 +15897,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1362: + case 1372: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15816,7 +15905,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1363: + case 1373: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15824,7 +15913,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1364: + case 1374: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: ast.AggFuncStddevPop, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15832,7 +15921,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: ast.AggFuncStddevPop, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1365: + case 1375: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15840,7 +15929,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1366: + case 1376: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: ast.AggFuncVarPop, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15848,11 +15937,11 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: ast.AggFuncVarPop, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } } - case 1367: + case 1377: { parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} } - case 1368: + case 1378: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15860,7 +15949,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1369: + case 1379: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15868,7 +15957,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} } } - case 1370: + case 1380: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-6].ident, Args: []ast.ExprNode{yyS[yypt-4].expr, yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15876,7 +15965,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-6].ident, Args: []ast.ExprNode{yyS[yypt-4].expr, yyS[yypt-2].expr}} } } - case 1371: + case 1381: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-7].ident, Args: []ast.ExprNode{yyS[yypt-4].expr, yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15884,7 +15973,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-7].ident, Args: []ast.ExprNode{yyS[yypt-4].expr, yyS[yypt-2].expr}} } } - case 1372: + case 1382: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-7].ident, Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15892,7 +15981,7 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-7].ident, Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-2].expr}} } } - case 1373: + case 1383: { if yyS[yypt-0].item != nil { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-8].ident, Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} @@ -15900,22 +15989,22 @@ yynewstate: parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-8].ident, Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-2].expr}} } } - case 1374: + case 1384: { parser.yyVAL.item = ast.NewValueExpr(",", "", "") } - case 1375: + case 1385: { parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].ident, "", "") } - case 1376: + case 1386: { parser.yyVAL.expr = &ast.FuncCallExpr{ FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode), } } - case 1377: + case 1387: { var tp ast.FuncCallExprType if isInTokenMap(yyS[yypt-3].ident) { @@ -15930,159 +16019,159 @@ yynewstate: Args: yyS[yypt-1].item.([]ast.ExprNode), } } - case 1378: + case 1388: { parser.yyVAL.item = nil } - case 1379: + case 1389: { parser.yyVAL.item = nil } - case 1380: + case 1390: { expr := ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation) parser.yyVAL.item = expr } - case 1382: + case 1392: { parser.yyVAL.item = ast.TimeUnitSecondMicrosecond } - case 1383: + case 1393: { parser.yyVAL.item = ast.TimeUnitMinuteMicrosecond } - case 1384: + case 1394: { parser.yyVAL.item = ast.TimeUnitMinuteSecond } - case 1385: + case 1395: { parser.yyVAL.item = ast.TimeUnitHourMicrosecond } - case 1386: + case 1396: { parser.yyVAL.item = ast.TimeUnitHourSecond } - case 1387: + case 1397: { parser.yyVAL.item = ast.TimeUnitHourMinute } - case 1388: + case 1398: { parser.yyVAL.item = ast.TimeUnitDayMicrosecond } - case 1389: + case 1399: { parser.yyVAL.item = ast.TimeUnitDaySecond } - case 1390: + case 1400: { parser.yyVAL.item = ast.TimeUnitDayMinute } - case 1391: + case 1401: { parser.yyVAL.item = ast.TimeUnitDayHour } - case 1392: + case 1402: { parser.yyVAL.item = ast.TimeUnitYearMonth } - case 1393: + case 1403: { parser.yyVAL.item = ast.TimeUnitMicrosecond } - case 1394: + case 1404: { parser.yyVAL.item = ast.TimeUnitSecond } - case 1395: + case 1405: { parser.yyVAL.item = ast.TimeUnitMinute } - case 1396: + case 1406: { parser.yyVAL.item = ast.TimeUnitHour } - case 1397: + case 1407: { parser.yyVAL.item = ast.TimeUnitDay } - case 1398: + case 1408: { parser.yyVAL.item = ast.TimeUnitWeek } - case 1399: + case 1409: { parser.yyVAL.item = ast.TimeUnitMonth } - case 1400: + case 1410: { parser.yyVAL.item = ast.TimeUnitQuarter } - case 1401: + case 1411: { parser.yyVAL.item = ast.TimeUnitYear } - case 1402: + case 1412: { parser.yyVAL.item = ast.TimeUnitSecond } - case 1403: + case 1413: { parser.yyVAL.item = ast.TimeUnitMinute } - case 1404: + case 1414: { parser.yyVAL.item = ast.TimeUnitHour } - case 1405: + case 1415: { parser.yyVAL.item = ast.TimeUnitDay } - case 1406: + case 1416: { parser.yyVAL.item = ast.TimeUnitWeek } - case 1407: + case 1417: { parser.yyVAL.item = ast.TimeUnitMonth } - case 1408: + case 1418: { parser.yyVAL.item = ast.TimeUnitQuarter } - case 1409: + case 1419: { parser.yyVAL.item = ast.TimeUnitYear } - case 1410: + case 1420: { parser.yyVAL.expr = nil } - case 1412: + case 1422: { parser.yyVAL.item = []*ast.WhenClause{yyS[yypt-0].item.(*ast.WhenClause)} } - case 1413: + case 1423: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.WhenClause), yyS[yypt-0].item.(*ast.WhenClause)) } - case 1414: + case 1424: { parser.yyVAL.item = &ast.WhenClause{ Expr: yyS[yypt-2].expr, Result: yyS[yypt-0].expr, } } - case 1415: + case 1425: { parser.yyVAL.item = nil } - case 1416: + case 1426: { parser.yyVAL.item = yyS[yypt-0].expr } - case 1417: + case 1427: { x := types.NewFieldType(mysql.TypeVarString) x.Flen = yyS[yypt-0].item.(int) // TODO: Flen should be the flen of expression @@ -16094,7 +16183,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1418: + case 1428: { x := types.NewFieldType(mysql.TypeVarString) x.Flen = yyS[yypt-1].item.(int) // TODO: Flen should be the flen of expression @@ -16117,7 +16206,7 @@ yynewstate: } parser.yyVAL.item = x } - case 1419: + case 1429: { x := types.NewFieldType(mysql.TypeDate) x.Charset = charset.CharsetBin @@ -16125,7 +16214,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1420: + case 1430: { x := types.NewFieldType(mysql.TypeYear) x.Charset = charset.CharsetBin @@ -16133,7 +16222,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1421: + case 1431: { x := types.NewFieldType(mysql.TypeDatetime) x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDatetime) @@ -16146,7 +16235,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1422: + case 1432: { fopt := yyS[yypt-0].item.(*ast.FloatOpt) x := types.NewFieldType(mysql.TypeNewDecimal) @@ -16157,7 +16246,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1423: + case 1433: { x := types.NewFieldType(mysql.TypeDuration) x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDuration) @@ -16170,7 +16259,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1424: + case 1434: { x := types.NewFieldType(mysql.TypeLonglong) x.Charset = charset.CharsetBin @@ -16178,7 +16267,7 @@ yynewstate: x.Flag |= mysql.BinaryFlag parser.yyVAL.item = x } - case 1425: + case 1435: { x := types.NewFieldType(mysql.TypeLonglong) x.Flag |= mysql.UnsignedFlag | mysql.BinaryFlag @@ -16186,7 +16275,7 @@ yynewstate: x.Collate = charset.CollationBin parser.yyVAL.item = x } - case 1426: + case 1436: { x := types.NewFieldType(mysql.TypeJSON) x.Flag |= mysql.BinaryFlag | (mysql.ParseToJSONFlag) @@ -16194,7 +16283,7 @@ yynewstate: x.Collate = mysql.DefaultCollationName parser.yyVAL.item = x } - case 1427: + case 1437: { x := types.NewFieldType(mysql.TypeDouble) x.Flen, x.Decimal = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDouble) @@ -16203,7 +16292,7 @@ yynewstate: x.Collate = charset.CollationBin parser.yyVAL.item = x } - case 1428: + case 1438: { x := types.NewFieldType(mysql.TypeFloat) fopt := yyS[yypt-0].item.(*ast.FloatOpt) @@ -16218,7 +16307,7 @@ yynewstate: x.Collate = charset.CollationBin parser.yyVAL.item = x } - case 1429: + case 1439: { var x *types.FieldType if parser.lexer.GetSQLMode().HasRealAsFloatMode() { @@ -16232,65 +16321,65 @@ yynewstate: x.Collate = charset.CollationBin parser.yyVAL.item = x } - case 1430: + case 1440: { parser.yyVAL.item = mysql.LowPriority } - case 1431: + case 1441: { parser.yyVAL.item = mysql.HighPriority } - case 1432: + case 1442: { parser.yyVAL.item = mysql.DelayedPriority } - case 1433: + case 1443: { parser.yyVAL.item = mysql.NoPriority } - case 1435: + case 1445: { parser.yyVAL.item = &ast.TableName{Name: model.NewCIStr(yyS[yypt-0].ident)} } - case 1436: + case 1446: { parser.yyVAL.item = &ast.TableName{Schema: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} } - case 1437: + case 1447: { tbl := []*ast.TableName{yyS[yypt-0].item.(*ast.TableName)} parser.yyVAL.item = tbl } - case 1438: + case 1448: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableName), yyS[yypt-0].item.(*ast.TableName)) } - case 1439: + case 1449: { parser.yyVAL.item = &ast.TableName{Name: model.NewCIStr(yyS[yypt-1].ident)} } - case 1440: + case 1450: { parser.yyVAL.item = &ast.TableName{Schema: model.NewCIStr(yyS[yypt-3].ident), Name: model.NewCIStr(yyS[yypt-1].ident)} } - case 1441: + case 1451: { tbl := []*ast.TableName{yyS[yypt-0].item.(*ast.TableName)} parser.yyVAL.item = tbl } - case 1442: + case 1452: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableName), yyS[yypt-0].item.(*ast.TableName)) } - case 1445: + case 1455: { parser.yyVAL.item = false } - case 1446: + case 1456: { parser.yyVAL.item = true } - case 1447: + case 1457: { var sqlText string var sqlVar *ast.VariableExpr @@ -16306,86 +16395,86 @@ yynewstate: SQLVar: sqlVar, } } - case 1448: + case 1458: { parser.yyVAL.item = yyS[yypt-0].ident } - case 1449: + case 1459: { parser.yyVAL.item = yyS[yypt-0].expr } - case 1450: + case 1460: { parser.yyVAL.statement = &ast.ExecuteStmt{Name: yyS[yypt-0].ident} } - case 1451: + case 1461: { parser.yyVAL.statement = &ast.ExecuteStmt{ Name: yyS[yypt-2].ident, UsingVars: yyS[yypt-0].item.([]ast.ExprNode), } } - case 1452: + case 1462: { parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} } - case 1453: + case 1463: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) } - case 1454: + case 1464: { parser.yyVAL.statement = &ast.DeallocateStmt{Name: yyS[yypt-0].ident} } - case 1457: + case 1467: { parser.yyVAL.statement = &ast.RollbackStmt{} } - case 1458: + case 1468: { parser.yyVAL.statement = &ast.RollbackStmt{CompletionType: yyS[yypt-0].item.(ast.CompletionType)} } - case 1459: + case 1469: { parser.yyVAL.item = ast.CompletionTypeChain } - case 1460: + case 1470: { parser.yyVAL.item = ast.CompletionTypeRelease } - case 1461: + case 1471: { parser.yyVAL.item = ast.CompletionTypeDefault } - case 1462: + case 1472: { parser.yyVAL.item = ast.CompletionTypeChain } - case 1463: + case 1473: { parser.yyVAL.item = ast.CompletionTypeDefault } - case 1464: + case 1474: { parser.yyVAL.item = ast.CompletionTypeRelease } - case 1465: + case 1475: { parser.yyVAL.item = ast.CompletionTypeDefault } - case 1466: + case 1476: { parser.yyVAL.statement = &ast.ShutdownStmt{} } - case 1467: + case 1477: { parser.yyVAL.statement = &ast.RestartStmt{} } - case 1468: + case 1478: { parser.yyVAL.statement = &ast.HelpStmt{Topic: yyS[yypt-0].ident} } - case 1469: + case 1479: { st := &ast.SelectStmt{ SelectStmtOpts: yyS[yypt-1].item.(*ast.SelectStmtOpts), @@ -16398,26 +16487,26 @@ yynewstate: } parser.yyVAL.item = st } - case 1470: + case 1480: { st := yyS[yypt-2].item.(*ast.SelectStmt) lastField := st.Fields.Fields[len(st.Fields.Fields)-1] if lastField.Expr != nil && lastField.AsName.O == "" { lastEnd := yyS[yypt-1].offset - 1 - lastField.SetText(parser.src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd]) } if yyS[yypt-0].item != nil { st.Where = yyS[yypt-0].item.(ast.ExprNode) } } - case 1471: + case 1481: { st := yyS[yypt-6].item.(*ast.SelectStmt) st.From = yyS[yypt-4].item.(*ast.TableRefsClause) lastField := st.Fields.Fields[len(st.Fields.Fields)-1] if lastField.Expr != nil && lastField.AsName.O == "" { lastEnd := parser.endOffset(&yyS[yypt-5]) - lastField.SetText(parser.src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd]) } if yyS[yypt-3].item != nil { st.Where = yyS[yypt-3].item.(ast.ExprNode) @@ -16433,11 +16522,11 @@ yynewstate: } parser.yyVAL.item = st } - case 1472: + case 1482: { parser.yyVAL.item = nil } - case 1473: + case 1483: { var repSeed ast.ExprNode if yyS[yypt-0].expr != nil { @@ -16450,7 +16539,7 @@ yynewstate: RepeatableSeed: repSeed, } } - case 1474: + case 1484: { var repSeed ast.ExprNode if yyS[yypt-0].expr != nil { @@ -16461,43 +16550,43 @@ yynewstate: RepeatableSeed: repSeed, } } - case 1475: + case 1485: { parser.yyVAL.item = ast.SampleMethodTypeNone } - case 1476: + case 1486: { parser.yyVAL.item = ast.SampleMethodTypeSystem } - case 1477: + case 1487: { parser.yyVAL.item = ast.SampleMethodTypeBernoulli } - case 1478: + case 1488: { parser.yyVAL.item = ast.SampleMethodTypeTiDBRegion } - case 1479: + case 1489: { parser.yyVAL.item = ast.SampleClauseUnitTypeDefault } - case 1480: + case 1490: { parser.yyVAL.item = ast.SampleClauseUnitTypeRow } - case 1481: + case 1491: { parser.yyVAL.item = ast.SampleClauseUnitTypePercent } - case 1482: + case 1492: { parser.yyVAL.expr = nil } - case 1483: + case 1493: { parser.yyVAL.expr = yyS[yypt-1].expr } - case 1484: + case 1494: { st := yyS[yypt-6].item.(*ast.SelectStmt) if yyS[yypt-1].item != nil { @@ -16525,7 +16614,7 @@ yynewstate: lastEnd-- } } - lastField.SetText(src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, src[lastField.Offset:lastEnd]) } if yyS[yypt-5].item != nil { st.Where = yyS[yypt-5].item.(ast.ExprNode) @@ -16544,7 +16633,7 @@ yynewstate: } parser.yyVAL.statement = st } - case 1485: + case 1495: { st := yyS[yypt-5].item.(*ast.SelectStmt) if yyS[yypt-4].item != nil { @@ -16564,7 +16653,7 @@ yynewstate: } parser.yyVAL.statement = st } - case 1486: + case 1496: { st := yyS[yypt-4].item.(*ast.SelectStmt) if yyS[yypt-1].item != nil { @@ -16581,7 +16670,7 @@ yynewstate: } parser.yyVAL.statement = st } - case 1487: + case 1497: { st := &ast.SelectStmt{ Kind: ast.SelectStmtKindTable, @@ -16603,7 +16692,7 @@ yynewstate: } parser.yyVAL.statement = st } - case 1488: + case 1498: { st := &ast.SelectStmt{ Kind: ast.SelectStmtKindValues, @@ -16624,13 +16713,13 @@ yynewstate: } parser.yyVAL.statement = st } - case 1489: + case 1499: { sel := yyS[yypt-0].statement.(*ast.SelectStmt) sel.With = yyS[yypt-1].item.(*ast.WithClause) parser.yyVAL.statement = sel } - case 1490: + case 1500: { var sel ast.StmtNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -16646,30 +16735,30 @@ yynewstate: } parser.yyVAL.statement = sel } - case 1491: + case 1501: { parser.yyVAL.item = yyS[yypt-0].item } - case 1492: + case 1502: { ws := yyS[yypt-0].item.(*ast.WithClause) ws.IsRecursive = true parser.yyVAL.item = ws } - case 1493: + case 1503: { ws := yyS[yypt-2].item.(*ast.WithClause) ws.CTEs = append(ws.CTEs, yyS[yypt-0].item.(*ast.CommonTableExpression)) parser.yyVAL.item = ws } - case 1494: + case 1504: { ws := &ast.WithClause{} ws.CTEs = make([]*ast.CommonTableExpression, 0, 4) ws.CTEs = append(ws.CTEs, yyS[yypt-0].item.(*ast.CommonTableExpression)) parser.yyVAL.item = ws } - case 1495: + case 1505: { cte := &ast.CommonTableExpression{} cte.Name = model.NewCIStr(yyS[yypt-3].ident) @@ -16677,37 +16766,37 @@ yynewstate: cte.Query = yyS[yypt-0].expr.(*ast.SubqueryExpr) parser.yyVAL.item = cte } - case 1497: + case 1507: { parser.yyVAL.item = nil } - case 1498: + case 1508: { parser.yyVAL.item = yyS[yypt-0].item.([]ast.WindowSpec) } - case 1499: + case 1509: { parser.yyVAL.item = []ast.WindowSpec{yyS[yypt-0].item.(ast.WindowSpec)} } - case 1500: + case 1510: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.WindowSpec), yyS[yypt-0].item.(ast.WindowSpec)) } - case 1501: + case 1511: { var spec = yyS[yypt-0].item.(ast.WindowSpec) spec.Name = yyS[yypt-2].item.(model.CIStr) parser.yyVAL.item = spec } - case 1502: + case 1512: { parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) } - case 1503: + case 1513: { parser.yyVAL.item = yyS[yypt-1].item.(ast.WindowSpec) } - case 1504: + case 1514: { spec := ast.WindowSpec{Ref: yyS[yypt-3].item.(model.CIStr)} if yyS[yypt-2].item != nil { @@ -16721,138 +16810,138 @@ yynewstate: } parser.yyVAL.item = spec } - case 1505: + case 1515: { parser.yyVAL.item = model.CIStr{} } - case 1507: + case 1517: { parser.yyVAL.item = nil } - case 1508: + case 1518: { parser.yyVAL.item = &ast.PartitionByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} } - case 1509: + case 1519: { parser.yyVAL.item = nil } - case 1510: + case 1520: { parser.yyVAL.item = &ast.OrderByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} } - case 1511: + case 1521: { parser.yyVAL.item = nil } - case 1512: + case 1522: { parser.yyVAL.item = &ast.FrameClause{ Type: yyS[yypt-1].item.(ast.FrameType), Extent: yyS[yypt-0].item.(ast.FrameExtent), } } - case 1513: + case 1523: { parser.yyVAL.item = ast.FrameType(ast.Rows) } - case 1514: + case 1524: { parser.yyVAL.item = ast.FrameType(ast.Ranges) } - case 1515: + case 1525: { parser.yyVAL.item = ast.FrameType(ast.Groups) } - case 1516: + case 1526: { parser.yyVAL.item = ast.FrameExtent{ Start: yyS[yypt-0].item.(ast.FrameBound), End: ast.FrameBound{Type: ast.CurrentRow}, } } - case 1518: + case 1528: { parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, UnBounded: true} } - case 1519: + case 1529: { parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)} } - case 1520: + case 1530: { parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewParamMarkerExpr(yyS[yypt].offset)} } - case 1521: + case 1531: { parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: yyS[yypt-2].expr, Unit: yyS[yypt-1].item.(ast.TimeUnitType)} } - case 1522: + case 1532: { parser.yyVAL.item = ast.FrameBound{Type: ast.CurrentRow} } - case 1523: + case 1533: { parser.yyVAL.item = ast.FrameExtent{Start: yyS[yypt-2].item.(ast.FrameBound), End: yyS[yypt-0].item.(ast.FrameBound)} } - case 1525: + case 1535: { parser.yyVAL.item = ast.FrameBound{Type: ast.Following, UnBounded: true} } - case 1526: + case 1536: { parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)} } - case 1527: + case 1537: { parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewParamMarkerExpr(yyS[yypt].offset)} } - case 1528: + case 1538: { parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: yyS[yypt-2].expr, Unit: yyS[yypt-1].item.(ast.TimeUnitType)} } - case 1529: + case 1539: { parser.yyVAL.item = nil } - case 1530: + case 1540: { spec := yyS[yypt-0].item.(ast.WindowSpec) parser.yyVAL.item = &spec } - case 1531: + case 1541: { parser.yyVAL.item = yyS[yypt-0].item.(ast.WindowSpec) } - case 1532: + case 1542: { parser.yyVAL.item = ast.WindowSpec{Name: yyS[yypt-0].item.(model.CIStr), OnlyAlias: true} } - case 1534: + case 1544: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1535: + case 1545: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1536: + case 1546: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1537: + case 1547: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1538: + case 1548: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1539: + case 1549: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1540: + case 1550: { args := []ast.ExprNode{yyS[yypt-4].expr} if yyS[yypt-3].item != nil { @@ -16860,7 +16949,7 @@ yynewstate: } parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-6].ident, Args: args, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1541: + case 1551: { args := []ast.ExprNode{yyS[yypt-4].expr} if yyS[yypt-3].item != nil { @@ -16868,23 +16957,23 @@ yynewstate: } parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-6].ident, Args: args, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1542: + case 1552: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-3].expr}, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1543: + case 1553: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-3].expr}, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1544: + case 1554: { parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-8].ident, Args: []ast.ExprNode{yyS[yypt-6].expr, yyS[yypt-4].expr}, FromLast: yyS[yypt-2].item.(bool), IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} } - case 1545: + case 1555: { parser.yyVAL.item = nil } - case 1546: + case 1556: { args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)} if yyS[yypt-0].item != nil { @@ -16892,7 +16981,7 @@ yynewstate: } parser.yyVAL.item = args } - case 1547: + case 1557: { args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)} if yyS[yypt-0].item != nil { @@ -16900,43 +16989,43 @@ yynewstate: } parser.yyVAL.item = args } - case 1548: + case 1558: { parser.yyVAL.item = nil } - case 1549: + case 1559: { parser.yyVAL.item = yyS[yypt-0].expr } - case 1550: + case 1560: { parser.yyVAL.item = false } - case 1551: + case 1561: { parser.yyVAL.item = false } - case 1552: + case 1562: { parser.yyVAL.item = true } - case 1553: + case 1563: { parser.yyVAL.item = false } - case 1554: + case 1564: { parser.yyVAL.item = false } - case 1555: + case 1565: { parser.yyVAL.item = true } - case 1556: + case 1566: { parser.yyVAL.item = &ast.TableRefsClause{TableRefs: yyS[yypt-0].item.(*ast.Join)} } - case 1557: + case 1567: { if j, ok := yyS[yypt-0].item.(*ast.Join); ok { // if $1 is Join, use it directly @@ -16945,12 +17034,12 @@ yynewstate: parser.yyVAL.item = &ast.Join{Left: yyS[yypt-0].item.(ast.ResultSetNode), Right: nil} } } - case 1558: + case 1568: { /* from a, b is default cross join */ parser.yyVAL.item = &ast.Join{Left: yyS[yypt-2].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), Tp: ast.CrossJoin} } - case 1560: + case 1570: { /* * ODBC escape syntax for outer join is { OJ join_table } @@ -16958,7 +17047,7 @@ yynewstate: */ parser.yyVAL.item = yyS[yypt-1].item } - case 1563: + case 1573: { tn := yyS[yypt-5].item.(*ast.TableName) tn.PartitionNames = yyS[yypt-4].item.([]model.CIStr) @@ -16971,66 +17060,66 @@ yynewstate: } parser.yyVAL.item = &ast.TableSource{Source: tn, AsName: yyS[yypt-3].item.(model.CIStr)} } - case 1564: + case 1574: { resultNode := yyS[yypt-1].expr.(*ast.SubqueryExpr).Query parser.yyVAL.item = &ast.TableSource{Source: resultNode, AsName: yyS[yypt-0].item.(model.CIStr)} } - case 1565: + case 1575: { j := yyS[yypt-1].item.(*ast.Join) j.ExplicitParens = true parser.yyVAL.item = yyS[yypt-1].item } - case 1566: + case 1576: { parser.yyVAL.item = []model.CIStr{} } - case 1567: + case 1577: { parser.yyVAL.item = yyS[yypt-1].item } - case 1568: + case 1578: { parser.yyVAL.item = model.CIStr{} } - case 1570: + case 1580: { parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) } - case 1571: + case 1581: { parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) } - case 1572: + case 1582: { parser.yyVAL.item = ast.HintUse } - case 1573: + case 1583: { parser.yyVAL.item = ast.HintIgnore } - case 1574: + case 1584: { parser.yyVAL.item = ast.HintForce } - case 1575: + case 1585: { parser.yyVAL.item = ast.HintForScan } - case 1576: + case 1586: { parser.yyVAL.item = ast.HintForJoin } - case 1577: + case 1587: { parser.yyVAL.item = ast.HintForOrderBy } - case 1578: + case 1588: { parser.yyVAL.item = ast.HintForGroupBy } - case 1579: + case 1589: { parser.yyVAL.item = &ast.IndexHint{ IndexNames: yyS[yypt-1].item.([]model.CIStr), @@ -17038,134 +17127,134 @@ yynewstate: HintScope: yyS[yypt-3].item.(ast.IndexHintScope), } } - case 1580: + case 1590: { var nameList []model.CIStr parser.yyVAL.item = nameList } - case 1581: + case 1591: { parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 1582: + case 1592: { parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) } - case 1583: + case 1593: { parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 1584: + case 1594: { parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) } - case 1585: + case 1595: { parser.yyVAL.item = []*ast.IndexHint{yyS[yypt-0].item.(*ast.IndexHint)} } - case 1586: + case 1596: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.IndexHint), yyS[yypt-0].item.(*ast.IndexHint)) } - case 1587: + case 1597: { parser.yyVAL.item = []*ast.IndexHint{} } - case 1589: + case 1599: { parser.yyVAL.item = ast.NewCrossJoin(yyS[yypt-2].item.(ast.ResultSetNode), yyS[yypt-0].item.(ast.ResultSetNode)) } - case 1590: + case 1600: { on := &ast.OnCondition{Expr: yyS[yypt-0].expr} parser.yyVAL.item = &ast.Join{Left: yyS[yypt-4].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), Tp: ast.CrossJoin, On: on} } - case 1591: + case 1601: { parser.yyVAL.item = &ast.Join{Left: yyS[yypt-6].item.(ast.ResultSetNode), Right: yyS[yypt-4].item.(ast.ResultSetNode), Tp: ast.CrossJoin, Using: yyS[yypt-1].item.([]*ast.ColumnName)} } - case 1592: + case 1602: { on := &ast.OnCondition{Expr: yyS[yypt-0].expr} parser.yyVAL.item = &ast.Join{Left: yyS[yypt-6].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), Tp: yyS[yypt-5].item.(ast.JoinType), On: on} } - case 1593: + case 1603: { parser.yyVAL.item = &ast.Join{Left: yyS[yypt-8].item.(ast.ResultSetNode), Right: yyS[yypt-4].item.(ast.ResultSetNode), Tp: yyS[yypt-7].item.(ast.JoinType), Using: yyS[yypt-1].item.([]*ast.ColumnName)} } - case 1594: + case 1604: { parser.yyVAL.item = &ast.Join{Left: yyS[yypt-3].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), NaturalJoin: true} } - case 1595: + case 1605: { parser.yyVAL.item = &ast.Join{Left: yyS[yypt-5].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), Tp: yyS[yypt-3].item.(ast.JoinType), NaturalJoin: true} } - case 1596: + case 1606: { parser.yyVAL.item = &ast.Join{Left: yyS[yypt-2].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), StraightJoin: true} } - case 1597: + case 1607: { on := &ast.OnCondition{Expr: yyS[yypt-0].expr} parser.yyVAL.item = &ast.Join{Left: yyS[yypt-4].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), StraightJoin: true, On: on} } - case 1598: + case 1608: { parser.yyVAL.item = ast.LeftJoin } - case 1599: + case 1609: { parser.yyVAL.item = ast.RightJoin } - case 1605: + case 1615: { parser.yyVAL.item = nil } - case 1606: + case 1616: { parser.yyVAL.item = &ast.Limit{Count: yyS[yypt-0].item.(ast.ValueExpr)} } - case 1607: + case 1617: { parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation) } - case 1608: + case 1618: { parser.yyVAL.item = ast.NewParamMarkerExpr(yyS[yypt].offset) } - case 1613: + case 1623: { parser.yyVAL.item = ast.NewValueExpr(uint64(1), parser.charset, parser.collation) } - case 1615: + case 1625: { parser.yyVAL.item = &ast.Limit{Count: yyS[yypt-0].item.(ast.ExprNode)} } - case 1616: + case 1626: { parser.yyVAL.item = &ast.Limit{Offset: yyS[yypt-2].item.(ast.ExprNode), Count: yyS[yypt-0].item.(ast.ExprNode)} } - case 1617: + case 1627: { parser.yyVAL.item = &ast.Limit{Offset: yyS[yypt-0].item.(ast.ExprNode), Count: yyS[yypt-2].item.(ast.ExprNode)} } - case 1618: + case 1628: { parser.yyVAL.item = &ast.Limit{Count: yyS[yypt-2].item.(ast.ExprNode)} } - case 1619: + case 1629: { parser.yyVAL.item = nil } - case 1621: + case 1631: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.TableHints = yyS[yypt-0].item.([]*ast.TableOptimizerHint) parser.yyVAL.item = opt } - case 1622: + case 1632: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true @@ -17177,61 +17266,61 @@ yynewstate: } parser.yyVAL.item = opt } - case 1623: + case 1633: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.Priority = yyS[yypt-0].item.(mysql.PriorityEnum) parser.yyVAL.item = opt } - case 1624: + case 1634: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.SQLSmallResult = true parser.yyVAL.item = opt } - case 1625: + case 1635: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.SQLBigResult = true parser.yyVAL.item = opt } - case 1626: + case 1636: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.SQLBufferResult = true parser.yyVAL.item = opt } - case 1627: + case 1637: { opt := &ast.SelectStmtOpts{} opt.SQLCache = yyS[yypt-0].item.(bool) parser.yyVAL.item = opt } - case 1628: + case 1638: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.CalcFoundRows = true parser.yyVAL.item = opt } - case 1629: + case 1639: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true opt.StraightJoin = true parser.yyVAL.item = opt } - case 1630: + case 1640: { opt := &ast.SelectStmtOpts{} opt.SQLCache = true parser.yyVAL.item = opt } - case 1632: + case 1642: { opts := yyS[yypt-1].item.(*ast.SelectStmtOpts) opt := yyS[yypt-0].item.(*ast.SelectStmtOpts) @@ -17276,7 +17365,7 @@ yynewstate: parser.yyVAL.item = opts } - case 1634: + case 1644: { hints, warns := parser.parseHint(yyS[yypt-0].ident) for _, w := range warns { @@ -17285,31 +17374,31 @@ yynewstate: } parser.yyVAL.item = hints } - case 1635: + case 1645: { parser.yyVAL.item = nil } - case 1637: + case 1647: { parser.yyVAL.item = true } - case 1638: + case 1648: { parser.yyVAL.item = false } - case 1639: + case 1649: { parser.yyVAL.item = &ast.FieldList{Fields: yyS[yypt-0].item.([]*ast.SelectField)} } - case 1640: + case 1650: { parser.yyVAL.item = nil } - case 1642: + case 1652: { parser.yyVAL.item = nil } - case 1643: + case 1653: { x := &ast.SelectIntoOption{ Tp: ast.SelectIntoOutfile, @@ -17324,34 +17413,34 @@ yynewstate: parser.yyVAL.item = x } - case 1644: + case 1654: { rs := yyS[yypt-1].statement.(*ast.SelectStmt) endOffset := parser.endOffset(&yyS[yypt]) parser.setLastSelectFieldText(rs, endOffset) src := parser.src // See the implementation of yyParse function - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) parser.yyVAL.expr = &ast.SubqueryExpr{Query: rs} } - case 1645: + case 1655: { rs := yyS[yypt-1].statement.(*ast.SetOprStmt) src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) parser.yyVAL.expr = &ast.SubqueryExpr{Query: rs} } - case 1646: + case 1656: { rs := yyS[yypt-1].statement.(*ast.SelectStmt) endOffset := parser.endOffset(&yyS[yypt]) parser.setLastSelectFieldText(rs, endOffset) src := parser.src // See the implementation of yyParse function - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) parser.yyVAL.expr = &ast.SubqueryExpr{Query: rs} } - case 1647: + case 1657: { subQuery := yyS[yypt-1].expr.(*ast.SubqueryExpr).Query isRecursive := true @@ -17366,40 +17455,40 @@ yynewstate: endOffset := parser.endOffset(&yyS[yypt]) parser.setLastSelectFieldText(rs, endOffset) src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) parser.yyVAL.expr = &ast.SubqueryExpr{Query: rs} case *ast.SetOprStmt: src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) parser.yyVAL.expr = &ast.SubqueryExpr{Query: rs} } } - case 1648: + case 1658: { parser.yyVAL.item = nil } - case 1649: + case 1659: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForUpdate, Tables: yyS[yypt-0].item.([]*ast.TableName), } } - case 1650: + case 1660: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForShare, Tables: yyS[yypt-0].item.([]*ast.TableName), } } - case 1651: + case 1661: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForUpdateNoWait, Tables: yyS[yypt-1].item.([]*ast.TableName), } } - case 1652: + case 1662: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForUpdateWaitN, @@ -17407,55 +17496,55 @@ yynewstate: Tables: yyS[yypt-2].item.([]*ast.TableName), } } - case 1653: + case 1663: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForShareNoWait, Tables: yyS[yypt-1].item.([]*ast.TableName), } } - case 1654: + case 1664: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForUpdateSkipLocked, Tables: yyS[yypt-2].item.([]*ast.TableName), } } - case 1655: + case 1665: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForShareSkipLocked, Tables: yyS[yypt-2].item.([]*ast.TableName), } } - case 1656: + case 1666: { parser.yyVAL.item = &ast.SelectLockInfo{ LockType: ast.SelectLockForShare, Tables: []*ast.TableName{}, } } - case 1657: + case 1667: { parser.yyVAL.item = []*ast.TableName{} } - case 1658: + case 1668: { parser.yyVAL.item = yyS[yypt-0].item.([]*ast.TableName) } - case 1661: + case 1671: { setOpr := yyS[yypt-0].statement.(*ast.SetOprStmt) setOpr.With = yyS[yypt-1].item.(*ast.WithClause) parser.yyVAL.statement = setOpr } - case 1662: + case 1672: { setOpr := yyS[yypt-0].statement.(*ast.SetOprStmt) setOpr.With = yyS[yypt-1].item.(*ast.WithClause) parser.yyVAL.statement = setOpr } - case 1663: + case 1673: { setOprList1 := yyS[yypt-2].item.([]ast.Node) if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces { @@ -17472,7 +17561,7 @@ yynewstate: setOpr.SelectList.Selects = append(setOpr.SelectList.Selects, st) parser.yyVAL.statement = setOpr } - case 1664: + case 1674: { setOprList1 := yyS[yypt-2].item.([]ast.Node) if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces { @@ -17495,7 +17584,7 @@ yynewstate: setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}} parser.yyVAL.statement = setOpr } - case 1665: + case 1675: { setOprList1 := yyS[yypt-3].item.([]ast.Node) if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces { @@ -17519,7 +17608,7 @@ yynewstate: setOpr.OrderBy = yyS[yypt-0].item.(*ast.OrderByClause) parser.yyVAL.statement = setOpr } - case 1666: + case 1676: { setOprList1 := yyS[yypt-3].item.([]ast.Node) if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces { @@ -17543,7 +17632,7 @@ yynewstate: setOpr.Limit = yyS[yypt-0].item.(*ast.Limit) parser.yyVAL.statement = setOpr } - case 1667: + case 1677: { setOprList1 := yyS[yypt-4].item.([]ast.Node) if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces { @@ -17568,7 +17657,7 @@ yynewstate: setOpr.Limit = yyS[yypt-0].item.(*ast.Limit) parser.yyVAL.statement = setOpr } - case 1668: + case 1678: { var setOprList []ast.Node var with *ast.WithClause @@ -17584,7 +17673,7 @@ yynewstate: setOpr.OrderBy = yyS[yypt-0].item.(*ast.OrderByClause) parser.yyVAL.statement = setOpr } - case 1669: + case 1679: { var setOprList []ast.Node var with *ast.WithClause @@ -17600,7 +17689,7 @@ yynewstate: setOpr.Limit = yyS[yypt-0].item.(*ast.Limit) parser.yyVAL.statement = setOpr } - case 1670: + case 1680: { var setOprList []ast.Node var with *ast.WithClause @@ -17617,7 +17706,7 @@ yynewstate: setOpr.Limit = yyS[yypt-0].item.(*ast.Limit) parser.yyVAL.statement = setOpr } - case 1672: + case 1682: { setOprList1 := yyS[yypt-2].item.([]ast.Node) setOprList2 := yyS[yypt-0].item.([]ast.Node) @@ -17633,11 +17722,11 @@ yynewstate: } parser.yyVAL.item = append(setOprList1, setOprList2...) } - case 1673: + case 1683: { parser.yyVAL.item = []ast.Node{yyS[yypt-0].statement.(*ast.SelectStmt)} } - case 1674: + case 1684: { var setOprList []ast.Node switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -17648,7 +17737,7 @@ yynewstate: } parser.yyVAL.item = setOprList } - case 1675: + case 1685: { var tp ast.SetOprType tp = ast.Union @@ -17657,7 +17746,7 @@ yynewstate: } parser.yyVAL.item = &tp } - case 1676: + case 1686: { var tp ast.SetOprType tp = ast.Except @@ -17666,7 +17755,7 @@ yynewstate: } parser.yyVAL.item = &tp } - case 1677: + case 1687: { var tp ast.SetOprType tp = ast.Intersect @@ -17675,7 +17764,7 @@ yynewstate: } parser.yyVAL.item = &tp } - case 1679: + case 1689: { parser.yyVAL.statement = &ast.ChangeStmt{ NodeType: ast.PumpType, @@ -17683,7 +17772,7 @@ yynewstate: NodeID: yyS[yypt-0].ident, } } - case 1680: + case 1690: { parser.yyVAL.statement = &ast.ChangeStmt{ NodeType: ast.DrainerType, @@ -17691,19 +17780,19 @@ yynewstate: NodeID: yyS[yypt-0].ident, } } - case 1681: + case 1691: { parser.yyVAL.statement = &ast.SetStmt{Variables: yyS[yypt-0].item.([]*ast.VariableAssignment)} } - case 1682: + case 1692: { parser.yyVAL.statement = &ast.SetPwdStmt{Password: yyS[yypt-0].ident} } - case 1683: + case 1693: { parser.yyVAL.statement = &ast.SetPwdStmt{User: yyS[yypt-2].item.(*auth.UserIdentity), Password: yyS[yypt-0].ident} } - case 1684: + case 1694: { vars := yyS[yypt-0].item.([]*ast.VariableAssignment) for _, v := range vars { @@ -17711,11 +17800,11 @@ yynewstate: } parser.yyVAL.statement = &ast.SetStmt{Variables: vars} } - case 1685: + case 1695: { parser.yyVAL.statement = &ast.SetStmt{Variables: yyS[yypt-0].item.([]*ast.VariableAssignment)} } - case 1686: + case 1696: { assigns := yyS[yypt-0].item.([]*ast.VariableAssignment) for i := 0; i < len(assigns); i++ { @@ -17726,19 +17815,19 @@ yynewstate: } parser.yyVAL.statement = &ast.SetStmt{Variables: assigns} } - case 1687: + case 1697: { parser.yyVAL.statement = &ast.SetConfigStmt{Type: strings.ToLower(yyS[yypt-3].ident), Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr} } - case 1688: + case 1698: { parser.yyVAL.statement = &ast.SetConfigStmt{Instance: yyS[yypt-3].ident, Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr} } - case 1689: + case 1699: { parser.yyVAL.statement = yyS[yypt-0].item.(*ast.SetRoleStmt) } - case 1690: + case 1700: { tmp := yyS[yypt-2].item.(*ast.SetRoleStmt) parser.yyVAL.statement = &ast.SetDefaultRoleStmt{ @@ -17747,27 +17836,27 @@ yynewstate: UserList: yyS[yypt-0].item.([]*auth.UserIdentity), } } - case 1691: + case 1701: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleNone, RoleList: nil} } - case 1692: + case 1702: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleAll, RoleList: nil} } - case 1693: + case 1703: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleRegular, RoleList: yyS[yypt-0].item.([]*auth.RoleIdentity)} } - case 1694: + case 1704: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleAllExcept, RoleList: yyS[yypt-0].item.([]*auth.RoleIdentity)} } - case 1696: + case 1706: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleDefault, RoleList: nil} } - case 1697: + case 1707: { if yyS[yypt-0].item != nil { parser.yyVAL.item = yyS[yypt-0].item @@ -17775,7 +17864,7 @@ yynewstate: parser.yyVAL.item = []*ast.VariableAssignment{} } } - case 1698: + case 1708: { if yyS[yypt-0].item != nil { varAssigns := yyS[yypt-0].item.([]*ast.VariableAssignment) @@ -17784,28 +17873,28 @@ yynewstate: parser.yyVAL.item = yyS[yypt-2].item } } - case 1699: + case 1709: { varAssigns := []*ast.VariableAssignment{} expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation) varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true}) parser.yyVAL.item = varAssigns } - case 1700: + case 1710: { varAssigns := []*ast.VariableAssignment{} expr := ast.NewValueExpr("0", parser.charset, parser.collation) varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true}) parser.yyVAL.item = varAssigns } - case 1701: + case 1711: { varAssigns := []*ast.VariableAssignment{} expr := ast.NewValueExpr("1", parser.charset, parser.collation) varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true}) parser.yyVAL.item = varAssigns } - case 1702: + case 1712: { varAssigns := []*ast.VariableAssignment{} asof := yyS[yypt-0].item.(*ast.AsOfClause) @@ -17814,59 +17903,59 @@ yynewstate: } parser.yyVAL.item = varAssigns } - case 1703: + case 1713: { parser.yyVAL.ident = ast.RepeatableRead } - case 1704: + case 1714: { parser.yyVAL.ident = ast.ReadCommitted } - case 1705: + case 1715: { parser.yyVAL.ident = ast.ReadUncommitted } - case 1706: + case 1716: { parser.yyVAL.ident = ast.Serializable } - case 1707: + case 1717: { parser.yyVAL.expr = ast.NewValueExpr("ON", parser.charset, parser.collation) } - case 1708: + case 1718: { parser.yyVAL.expr = ast.NewValueExpr("BINARY", parser.charset, parser.collation) } - case 1713: + case 1723: { parser.yyVAL.ident = yyS[yypt-2].ident + "." + yyS[yypt-0].ident } - case 1715: + case 1725: { parser.yyVAL.ident = yyS[yypt-2].ident + "." + yyS[yypt-0].ident } - case 1716: + case 1726: { parser.yyVAL.ident = yyS[yypt-2].ident + "-" + yyS[yypt-0].ident } - case 1717: + case 1727: { parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} } - case 1718: + case 1728: { parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsGlobal: true, IsSystem: true} } - case 1719: + case 1729: { parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} } - case 1720: + case 1730: { parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} } - case 1721: + case 1731: { v := strings.ToLower(yyS[yypt-2].ident) var isGlobal bool @@ -17882,27 +17971,27 @@ yynewstate: } parser.yyVAL.item = &ast.VariableAssignment{Name: v, Value: yyS[yypt-0].expr, IsGlobal: isGlobal, IsSystem: true} } - case 1722: + case 1732: { v := yyS[yypt-2].ident v = strings.TrimPrefix(v, "@") parser.yyVAL.item = &ast.VariableAssignment{Name: v, Value: yyS[yypt-0].expr} } - case 1723: + case 1733: { parser.yyVAL.item = &ast.VariableAssignment{ Name: ast.SetNames, Value: ast.NewValueExpr(yyS[yypt-0].ident, "", ""), } } - case 1724: + case 1734: { parser.yyVAL.item = &ast.VariableAssignment{ Name: ast.SetNames, Value: ast.NewValueExpr(yyS[yypt-2].ident, "", ""), } } - case 1725: + case 1735: { parser.yyVAL.item = &ast.VariableAssignment{ Name: ast.SetNames, @@ -17910,24 +17999,24 @@ yynewstate: ExtendValue: ast.NewValueExpr(yyS[yypt-0].ident, "", ""), } } - case 1726: + case 1736: { v := &ast.DefaultExpr{} parser.yyVAL.item = &ast.VariableAssignment{Name: ast.SetNames, Value: v} } - case 1727: + case 1737: { parser.yyVAL.item = &ast.VariableAssignment{Name: ast.SetCharset, Value: yyS[yypt-0].expr} } - case 1728: + case 1738: { parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].ident, "", "") } - case 1729: + case 1739: { parser.yyVAL.expr = &ast.DefaultExpr{} } - case 1730: + case 1740: { // Validate input charset name to keep the same behavior as parser of MySQL. cs, err := charset.GetCharsetInfo(yyS[yypt-0].ident) @@ -17939,11 +18028,11 @@ yynewstate: // to keep lower case of input for generated column restore. parser.yyVAL.ident = cs.Name } - case 1731: + case 1741: { parser.yyVAL.ident = charset.CharsetBin } - case 1732: + case 1742: { info, err := charset.GetCollationByName(yyS[yypt-0].ident) if err != nil { @@ -17952,19 +18041,19 @@ yynewstate: } parser.yyVAL.ident = info.Name } - case 1733: + case 1743: { parser.yyVAL.ident = charset.CollationBin } - case 1734: + case 1744: { parser.yyVAL.item = []*ast.VariableAssignment{yyS[yypt-0].item.(*ast.VariableAssignment)} } - case 1735: + case 1745: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.VariableAssignment), yyS[yypt-0].item.(*ast.VariableAssignment)) } - case 1738: + case 1748: { v := strings.ToLower(yyS[yypt-0].ident) var isGlobal bool @@ -17981,77 +18070,77 @@ yynewstate: } parser.yyVAL.expr = &ast.VariableExpr{Name: v, IsGlobal: isGlobal, IsSystem: true, ExplicitScope: explicitScope} } - case 1739: + case 1749: { v := yyS[yypt-0].ident v = strings.TrimPrefix(v, "@") parser.yyVAL.expr = &ast.VariableExpr{Name: v, IsGlobal: false, IsSystem: false} } - case 1740: + case 1750: { parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-0].ident, Hostname: "%"} } - case 1741: + case 1751: { parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-2].ident, Hostname: yyS[yypt-0].ident} } - case 1742: + case 1752: { parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-1].ident, Hostname: strings.TrimPrefix(yyS[yypt-0].ident, "@")} } - case 1743: + case 1753: { parser.yyVAL.item = &auth.UserIdentity{CurrentUser: true} } - case 1744: + case 1754: { parser.yyVAL.item = []*auth.UserIdentity{yyS[yypt-0].item.(*auth.UserIdentity)} } - case 1745: + case 1755: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*auth.UserIdentity), yyS[yypt-0].item.(*auth.UserIdentity)) } - case 1747: + case 1757: { parser.yyVAL.ident = yyS[yypt-1].ident } - case 1751: + case 1761: { parser.yyVAL.item = &auth.RoleIdentity{Username: yyS[yypt-2].ident, Hostname: yyS[yypt-0].ident} } - case 1752: + case 1762: { parser.yyVAL.item = &auth.RoleIdentity{Username: yyS[yypt-1].ident, Hostname: strings.TrimPrefix(yyS[yypt-0].ident, "@")} } - case 1753: + case 1763: { parser.yyVAL.item = &auth.RoleIdentity{Username: yyS[yypt-0].ident, Hostname: "%"} } - case 1754: + case 1764: { parser.yyVAL.item = yyS[yypt-0].item } - case 1755: + case 1765: { parser.yyVAL.item = &auth.RoleIdentity{Username: yyS[yypt-0].ident, Hostname: "%"} } - case 1756: + case 1766: { parser.yyVAL.item = yyS[yypt-0].item } - case 1757: + case 1767: { parser.yyVAL.item = []*auth.RoleIdentity{yyS[yypt-0].item.(*auth.RoleIdentity)} } - case 1758: + case 1768: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*auth.RoleIdentity), yyS[yypt-0].item.(*auth.RoleIdentity)) } - case 1759: + case 1769: { parser.yyVAL.statement = &ast.AdminStmt{Tp: ast.AdminShowDDL} } - case 1760: + case 1770: { stmt := &ast.AdminStmt{Tp: ast.AdminShowDDLJobs} if yyS[yypt-0].item != nil { @@ -18059,7 +18148,7 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 1761: + case 1771: { stmt := &ast.AdminStmt{ Tp: ast.AdminShowDDLJobs, @@ -18070,21 +18159,21 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 1762: + case 1772: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminShowNextRowID, Tables: []*ast.TableName{yyS[yypt-1].item.(*ast.TableName)}, } } - case 1763: + case 1773: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCheckTable, Tables: yyS[yypt-0].item.([]*ast.TableName), } } - case 1764: + case 1774: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCheckIndex, @@ -18092,7 +18181,7 @@ yynewstate: Index: string(yyS[yypt-0].ident), } } - case 1765: + case 1775: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminRecoverIndex, @@ -18100,7 +18189,7 @@ yynewstate: Index: string(yyS[yypt-0].ident), } } - case 1766: + case 1776: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCleanupIndex, @@ -18108,7 +18197,7 @@ yynewstate: Index: string(yyS[yypt-0].ident), } } - case 1767: + case 1777: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCheckIndexRange, @@ -18117,136 +18206,136 @@ yynewstate: HandleRanges: yyS[yypt-0].item.([]ast.HandleRange), } } - case 1768: + case 1778: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminChecksumTable, Tables: yyS[yypt-0].item.([]*ast.TableName), } } - case 1769: + case 1779: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCancelDDLJobs, JobIDs: yyS[yypt-0].item.([]int64), } } - case 1770: + case 1780: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminShowDDLJobQueries, JobIDs: yyS[yypt-0].item.([]int64), } } - case 1771: + case 1781: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminShowSlow, ShowSlow: yyS[yypt-0].item.(*ast.ShowSlow), } } - case 1772: + case 1782: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminReloadExprPushdownBlacklist, } } - case 1773: + case 1783: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminReloadOptRuleBlacklist, } } - case 1774: + case 1784: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminPluginEnable, Plugins: yyS[yypt-0].item.([]string), } } - case 1775: + case 1785: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminPluginDisable, Plugins: yyS[yypt-0].item.([]string), } } - case 1776: + case 1786: { parser.yyVAL.statement = &ast.CleanupTableLockStmt{ Tables: yyS[yypt-0].item.([]*ast.TableName), } } - case 1777: + case 1787: { parser.yyVAL.statement = &ast.RepairTableStmt{ Table: yyS[yypt-1].item.(*ast.TableName), CreateStmt: yyS[yypt-0].statement.(*ast.CreateTableStmt), } } - case 1778: + case 1788: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminFlushBindings, } } - case 1779: + case 1789: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminCaptureBindings, } } - case 1780: + case 1790: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminEvolveBindings, } } - case 1781: + case 1791: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminReloadBindings, } } - case 1782: + case 1792: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminReloadStatistics, } } - case 1783: + case 1793: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminReloadStatistics, } } - case 1784: + case 1794: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminShowTelemetry, } } - case 1785: + case 1795: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminResetTelemetryID, } } - case 1786: + case 1796: { parser.yyVAL.statement = &ast.AdminStmt{ Tp: ast.AdminFlushPlanCache, StatementScope: yyS[yypt-1].item.(ast.StatementScope), } } - case 1787: + case 1797: { parser.yyVAL.item = &ast.ShowSlow{ Tp: ast.ShowSlowRecent, Count: getUint64FromNUM(yyS[yypt-0].item), } } - case 1788: + case 1798: { parser.yyVAL.item = &ast.ShowSlow{ Tp: ast.ShowSlowTop, @@ -18254,7 +18343,7 @@ yynewstate: Count: getUint64FromNUM(yyS[yypt-0].item), } } - case 1789: + case 1799: { parser.yyVAL.item = &ast.ShowSlow{ Tp: ast.ShowSlowTop, @@ -18262,7 +18351,7 @@ yynewstate: Count: getUint64FromNUM(yyS[yypt-0].item), } } - case 1790: + case 1800: { parser.yyVAL.item = &ast.ShowSlow{ Tp: ast.ShowSlowTop, @@ -18270,27 +18359,27 @@ yynewstate: Count: getUint64FromNUM(yyS[yypt-0].item), } } - case 1791: + case 1801: { parser.yyVAL.item = []ast.HandleRange{yyS[yypt-0].item.(ast.HandleRange)} } - case 1792: + case 1802: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.HandleRange), yyS[yypt-0].item.(ast.HandleRange)) } - case 1793: + case 1803: { parser.yyVAL.item = ast.HandleRange{Begin: yyS[yypt-3].item.(int64), End: yyS[yypt-1].item.(int64)} } - case 1794: + case 1804: { parser.yyVAL.item = []int64{yyS[yypt-0].item.(int64)} } - case 1795: + case 1805: { parser.yyVAL.item = append(yyS[yypt-2].item.([]int64), yyS[yypt-0].item.(int64)) } - case 1796: + case 1806: { stmt := yyS[yypt-1].item.(*ast.ShowStmt) if yyS[yypt-0].item != nil { @@ -18302,21 +18391,21 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 1797: + case 1807: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreateTable, Table: yyS[yypt-0].item.(*ast.TableName), } } - case 1798: + case 1808: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreateView, Table: yyS[yypt-0].item.(*ast.TableName), } } - case 1799: + case 1809: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreateDatabase, @@ -18324,21 +18413,21 @@ yynewstate: DBName: yyS[yypt-0].ident, } } - case 1800: + case 1810: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreateSequence, Table: yyS[yypt-0].item.(*ast.TableName), } } - case 1801: + case 1811: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreatePlacementPolicy, DBName: yyS[yypt-0].ident, } } - case 1802: + case 1812: { // See https://dev.mysql.com/doc/refman/5.7/en/show-create-user.html parser.yyVAL.statement = &ast.ShowStmt{ @@ -18346,14 +18435,14 @@ yynewstate: User: yyS[yypt-0].item.(*auth.UserIdentity), } } - case 1803: + case 1813: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowCreateImport, DBName: yyS[yypt-0].ident, // we reuse DBName of ShowStmt } } - case 1804: + case 1814: { stmt := &ast.ShowStmt{ Tp: ast.ShowRegions, @@ -18365,14 +18454,14 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 1805: + case 1815: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowTableNextRowId, Table: yyS[yypt-1].item.(*ast.TableName), } } - case 1806: + case 1816: { stmt := &ast.ShowStmt{ Tp: ast.ShowRegions, @@ -18385,12 +18474,12 @@ yynewstate: } parser.yyVAL.statement = stmt } - case 1807: + case 1817: { // See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html parser.yyVAL.statement = &ast.ShowStmt{Tp: ast.ShowGrants} } - case 1808: + case 1818: { // See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html if yyS[yypt-0].item != nil { @@ -18407,26 +18496,26 @@ yynewstate: } } } - case 1809: + case 1819: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowMasterStatus, } } - case 1810: + case 1820: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowProcessList, Full: yyS[yypt-1].item.(bool), } } - case 1811: + case 1821: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowProfiles, } } - case 1812: + case 1822: { v := &ast.ShowStmt{ Tp: ast.ShowProfile, @@ -18442,37 +18531,37 @@ yynewstate: } parser.yyVAL.statement = v } - case 1813: + case 1823: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowPrivileges, } } - case 1814: + case 1824: { parser.yyVAL.statement = &ast.ShowStmt{ Tp: ast.ShowBuiltins, } } - case 1815: + case 1825: { parser.yyVAL.statement = yyS[yypt-0].item.(*ast.ShowStmt) } - case 1816: + case 1826: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowPlacementForDatabase, DBName: yyS[yypt-0].ident, } } - case 1817: + case 1827: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowPlacementForTable, Table: yyS[yypt-0].item.(*ast.TableName), } } - case 1818: + case 1828: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowPlacementForPartition, @@ -18480,90 +18569,90 @@ yynewstate: Partition: model.NewCIStr(yyS[yypt-0].ident), } } - case 1819: + case 1829: { parser.yyVAL.item = nil } - case 1821: + case 1831: { parser.yyVAL.item = []int{yyS[yypt-0].item.(int)} } - case 1822: + case 1832: { l := yyS[yypt-2].item.([]int) l = append(l, yyS[yypt-0].item.(int)) parser.yyVAL.item = l } - case 1823: + case 1833: { parser.yyVAL.item = ast.ProfileTypeCPU } - case 1824: + case 1834: { parser.yyVAL.item = ast.ProfileTypeMemory } - case 1825: + case 1835: { parser.yyVAL.item = ast.ProfileTypeBlockIo } - case 1826: + case 1836: { parser.yyVAL.item = ast.ProfileTypeContextSwitch } - case 1827: + case 1837: { parser.yyVAL.item = ast.ProfileTypePageFaults } - case 1828: + case 1838: { parser.yyVAL.item = ast.ProfileTypeIpc } - case 1829: + case 1839: { parser.yyVAL.item = ast.ProfileTypeSwaps } - case 1830: + case 1840: { parser.yyVAL.item = ast.ProfileTypeSource } - case 1831: + case 1841: { parser.yyVAL.item = ast.ProfileTypeAll } - case 1832: + case 1842: { parser.yyVAL.item = nil } - case 1833: + case 1843: { v := yyS[yypt-0].item.(int64) parser.yyVAL.item = &v } - case 1834: + case 1844: { parser.yyVAL.item = nil } - case 1835: + case 1845: { parser.yyVAL.item = yyS[yypt-0].item.([]*auth.RoleIdentity) } - case 1841: + case 1851: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowEngines} } - case 1842: + case 1852: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowDatabases} } - case 1843: + case 1853: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowConfig} } - case 1844: + case 1854: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowCharset} } - case 1845: + case 1855: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowTables, @@ -18571,28 +18660,28 @@ yynewstate: Full: yyS[yypt-2].item.(bool), } } - case 1846: + case 1856: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowOpenTables, DBName: yyS[yypt-0].ident, } } - case 1847: + case 1857: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowTableStatus, DBName: yyS[yypt-0].ident, } } - case 1848: + case 1858: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowIndex, Table: yyS[yypt-0].item.(*ast.TableName), } } - case 1849: + case 1859: { show := &ast.ShowStmt{ Tp: ast.ShowIndex, @@ -18600,7 +18689,7 @@ yynewstate: } parser.yyVAL.item = show } - case 1850: + case 1860: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowColumns, @@ -18609,7 +18698,7 @@ yynewstate: Full: yyS[yypt-3].item.(bool), } } - case 1851: + case 1861: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowColumns, @@ -18619,67 +18708,73 @@ yynewstate: Extended: true, } } - case 1852: + case 1862: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowWarnings} } - case 1853: + case 1863: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowErrors} } - case 1854: + case 1864: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowVariables, GlobalScope: yyS[yypt-1].item.(bool), } } - case 1855: + case 1865: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowStatus, GlobalScope: yyS[yypt-1].item.(bool), } } - case 1856: + case 1866: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowBindings, GlobalScope: yyS[yypt-1].item.(bool), } } - case 1857: + case 1867: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowCollation, } } - case 1858: + case 1868: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowTriggers, DBName: yyS[yypt-0].ident, } } - case 1859: + case 1869: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowBindingCacheStatus, + } + } + case 1870: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowProcedureStatus, } } - case 1860: + case 1871: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowPumpStatus, } } - case 1861: + case 1872: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowDrainerStatus, } } - case 1862: + case 1873: { // This statement is similar to SHOW PROCEDURE STATUS but for stored functions. // See http://dev.mysql.com/doc/refman/5.7/en/show-function-status.html @@ -18689,185 +18784,185 @@ yynewstate: Tp: ast.ShowProcedureStatus, } } - case 1863: + case 1874: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowEvents, DBName: yyS[yypt-0].ident, } } - case 1864: + case 1875: { parser.yyVAL.item = &ast.ShowStmt{ Tp: ast.ShowPlugins, } } - case 1865: + case 1876: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsExtended} } - case 1866: + case 1877: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsMeta} } - case 1867: + case 1878: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsHistograms} } - case 1868: + case 1879: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsTopN} } - case 1869: + case 1880: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsBuckets} } - case 1870: + case 1881: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowStatsHealthy} } - case 1871: + case 1882: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowHistogramsInFlight} } - case 1872: + case 1883: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowColumnStatsUsage} } - case 1873: + case 1884: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowAnalyzeStatus} } - case 1874: + case 1885: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowBackups} } - case 1875: + case 1886: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowRestores} } - case 1876: + case 1887: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowImports} } - case 1877: + case 1888: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowPlacement} } - case 1878: + case 1889: { parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowPlacementLabels} } - case 1879: + case 1890: { parser.yyVAL.item = nil } - case 1880: + case 1891: { parser.yyVAL.item = &ast.PatternLikeExpr{ Pattern: yyS[yypt-0].expr, Escape: '\\', } } - case 1881: + case 1892: { parser.yyVAL.item = yyS[yypt-0].expr } - case 1882: + case 1893: { parser.yyVAL.item = false } - case 1883: + case 1894: { parser.yyVAL.item = true } - case 1884: + case 1895: { parser.yyVAL.item = false } - case 1885: + case 1896: { parser.yyVAL.item = ast.StatementScopeSession } - case 1886: + case 1897: { parser.yyVAL.item = ast.StatementScopeGlobal } - case 1887: + case 1898: { parser.yyVAL.item = ast.StatementScopeInstance } - case 1888: + case 1899: { parser.yyVAL.item = ast.StatementScopeSession } - case 1889: + case 1900: { parser.yyVAL.item = false } - case 1890: + case 1901: { parser.yyVAL.item = true } - case 1891: + case 1902: { parser.yyVAL.ident = "" } - case 1892: + case 1903: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 1893: + case 1904: { parser.yyVAL.item = yyS[yypt-0].item.(*ast.TableName) } - case 1894: + case 1905: { tmp := yyS[yypt-0].item.(*ast.FlushStmt) tmp.NoWriteToBinLog = yyS[yypt-1].item.(bool) parser.yyVAL.statement = tmp } - case 1895: + case 1906: { parser.yyVAL.item = []string{yyS[yypt-0].ident} } - case 1896: + case 1907: { parser.yyVAL.item = append(yyS[yypt-2].item.([]string), yyS[yypt-0].ident) } - case 1897: + case 1908: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushPrivileges, } } - case 1898: + case 1909: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushStatus, } } - case 1899: + case 1910: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushTiDBPlugin, Plugins: yyS[yypt-0].item.([]string), } } - case 1900: + case 1911: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushHosts, } } - case 1901: + case 1912: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushLogs, LogType: yyS[yypt-1].item.(ast.LogType), } } - case 1902: + case 1913: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushTables, @@ -18875,69 +18970,69 @@ yynewstate: ReadLock: yyS[yypt-0].item.(bool), } } - case 1903: + case 1914: { parser.yyVAL.item = &ast.FlushStmt{ Tp: ast.FlushClientErrorsSummary, } } - case 1904: + case 1915: { parser.yyVAL.item = ast.LogTypeDefault } - case 1905: + case 1916: { parser.yyVAL.item = ast.LogTypeBinary } - case 1906: + case 1917: { parser.yyVAL.item = ast.LogTypeEngine } - case 1907: + case 1918: { parser.yyVAL.item = ast.LogTypeError } - case 1908: + case 1919: { parser.yyVAL.item = ast.LogTypeGeneral } - case 1909: + case 1920: { parser.yyVAL.item = ast.LogTypeSlow } - case 1910: + case 1921: { parser.yyVAL.item = false } - case 1911: + case 1922: { parser.yyVAL.item = true } - case 1912: + case 1923: { parser.yyVAL.item = true } - case 1913: + case 1924: { parser.yyVAL.item = []*ast.TableName{} } - case 1915: + case 1926: { parser.yyVAL.item = []*ast.TableName{} } - case 1916: + case 1927: { parser.yyVAL.item = yyS[yypt-0].item } - case 1917: + case 1928: { parser.yyVAL.item = false } - case 1918: + case 1929: { parser.yyVAL.item = true } - case 1987: + case 1998: { var sel ast.StmtNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -18950,7 +19045,7 @@ yynewstate: } parser.yyVAL.statement = sel } - case 2011: + case 2023: { var sel ast.StmtNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -18963,7 +19058,7 @@ yynewstate: } parser.yyVAL.statement = sel } - case 2024: + case 2036: { var sel ast.StmtNode switch x := yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(type) { @@ -18976,27 +19071,27 @@ yynewstate: } parser.yyVAL.statement = sel } - case 2026: + case 2038: { if yyS[yypt-0].statement != nil { s := yyS[yypt-0].statement if lexer, ok := yylex.(stmtTexter); ok { - s.SetText(lexer.stmtText()) + s.SetText(parser.lexer.client, lexer.stmtText()) } parser.result = append(parser.result, s) } } - case 2027: + case 2039: { if yyS[yypt-0].statement != nil { s := yyS[yypt-0].statement if lexer, ok := yylex.(stmtTexter); ok { - s.SetText(lexer.stmtText()) + s.SetText(parser.lexer.client, lexer.stmtText()) } parser.result = append(parser.result, s) } } - case 2028: + case 2040: { cst := yyS[yypt-0].item.(*ast.Constraint) if yyS[yypt-1].item != nil { @@ -19004,7 +19099,7 @@ yynewstate: } parser.yyVAL.item = cst } - case 2033: + case 2045: { if yyS[yypt-0].item != nil { parser.yyVAL.item = []interface{}{yyS[yypt-0].item.(interface{})} @@ -19012,7 +19107,7 @@ yynewstate: parser.yyVAL.item = []interface{}{} } } - case 2034: + case 2046: { if yyS[yypt-0].item != nil { parser.yyVAL.item = append(yyS[yypt-2].item.([]interface{}), yyS[yypt-0].item) @@ -19020,7 +19115,7 @@ yynewstate: parser.yyVAL.item = yyS[yypt-2].item } } - case 2035: + case 2047: { var columnDefs []*ast.ColumnDef var constraints []*ast.Constraint @@ -19029,7 +19124,7 @@ yynewstate: Constraints: constraints, } } - case 2036: + case 2048: { tes := yyS[yypt-1].item.([]interface{}) var columnDefs []*ast.ColumnDef @@ -19047,69 +19142,69 @@ yynewstate: Constraints: constraints, } } - case 2038: + case 2050: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCharset, StrValue: yyS[yypt-0].ident, UintValue: ast.TableOptionCharsetWithoutConvertTo} } - case 2039: + case 2051: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: yyS[yypt-0].ident, UintValue: ast.TableOptionCharsetWithoutConvertTo} } - case 2040: + case 2052: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAutoIncrement, UintValue: yyS[yypt-0].item.(uint64), BoolValue: yyS[yypt-3].item.(bool)} } - case 2041: + case 2053: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAutoIdCache, UintValue: yyS[yypt-0].item.(uint64)} } - case 2042: + case 2054: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAutoRandomBase, UintValue: yyS[yypt-0].item.(uint64), BoolValue: yyS[yypt-3].item.(bool)} } - case 2043: + case 2055: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAvgRowLength, UintValue: yyS[yypt-0].item.(uint64)} } - case 2044: + case 2056: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionConnection, StrValue: yyS[yypt-0].ident} } - case 2045: + case 2057: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCheckSum, UintValue: yyS[yypt-0].item.(uint64)} } - case 2046: + case 2058: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionTableCheckSum, UintValue: yyS[yypt-0].item.(uint64)} } - case 2047: + case 2059: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionPassword, StrValue: yyS[yypt-0].ident} } - case 2048: + case 2060: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCompression, StrValue: yyS[yypt-0].ident} } - case 2049: + case 2061: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionKeyBlockSize, UintValue: yyS[yypt-0].item.(uint64)} } - case 2050: + case 2062: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionDelayKeyWrite, UintValue: yyS[yypt-0].item.(uint64)} } - case 2051: + case 2063: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionRowFormat, UintValue: yyS[yypt-0].item.(uint64)} } - case 2052: + case 2064: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionStatsPersistent} } - case 2053: + case 2065: { n := yyS[yypt-0].item.(uint64) if n != 0 && n != 1 { @@ -19120,13 +19215,13 @@ yynewstate: yylex.AppendError(yylex.Errorf("The STATS_AUTO_RECALC is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 2054: + case 2066: { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionStatsAutoRecalc, Default: true} yylex.AppendError(yylex.Errorf("The STATS_AUTO_RECALC is parsed but ignored by all storage engines.")) parser.lastErrorAsWarn() } - case 2055: + case 2067: { // Parse it but will ignore it. // In MySQL, STATS_SAMPLE_PAGES=N(Where 0 1 { @@ -20793,7 +20926,7 @@ yynewstate: OptEnclosed: true, } } - case 2374: + case 2388: { str := yyS[yypt-0].ident if str != "\\" && len(str) > 1 { @@ -20805,7 +20938,7 @@ yynewstate: Value: str, } } - case 2375: + case 2389: { str := yyS[yypt-0].ident if str != "\\" && len(str) > 1 { @@ -20817,118 +20950,118 @@ yynewstate: Value: str, } } - case 2377: + case 2391: { parser.yyVAL.ident = yyS[yypt-0].item.(ast.BinaryLiteral).ToString() } - case 2378: + case 2392: { parser.yyVAL.ident = yyS[yypt-0].item.(ast.BinaryLiteral).ToString() } - case 2379: + case 2393: { parser.yyVAL.item = &ast.LinesClause{Terminated: "\n"} } - case 2380: + case 2394: { parser.yyVAL.item = &ast.LinesClause{Starting: yyS[yypt-1].ident, Terminated: yyS[yypt-0].ident} } - case 2381: + case 2395: { parser.yyVAL.ident = "" } - case 2382: + case 2396: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 2383: + case 2397: { parser.yyVAL.ident = "\n" } - case 2384: + case 2398: { parser.yyVAL.ident = yyS[yypt-0].ident } - case 2385: + case 2399: { parser.yyVAL.item = nil } - case 2386: + case 2400: { parser.yyVAL.item = yyS[yypt-0].item } - case 2387: + case 2401: { l := yyS[yypt-2].item.([]*ast.Assignment) parser.yyVAL.item = append(l, yyS[yypt-0].item.(*ast.Assignment)) } - case 2388: + case 2402: { parser.yyVAL.item = []*ast.Assignment{yyS[yypt-0].item.(*ast.Assignment)} } - case 2389: + case 2403: { parser.yyVAL.item = &ast.Assignment{ Column: yyS[yypt-2].expr.(*ast.ColumnNameExpr).Name, Expr: yyS[yypt-0].expr, } } - case 2390: + case 2404: { parser.yyVAL.statement = &ast.UnlockTablesStmt{} } - case 2391: + case 2405: { parser.yyVAL.statement = &ast.LockTablesStmt{ TableLocks: yyS[yypt-0].item.([]ast.TableLock), } } - case 2394: + case 2408: { parser.yyVAL.item = ast.TableLock{ Table: yyS[yypt-1].item.(*ast.TableName), Type: yyS[yypt-0].item.(model.TableLockType), } } - case 2395: + case 2409: { parser.yyVAL.item = model.TableLockRead } - case 2396: + case 2410: { parser.yyVAL.item = model.TableLockReadLocal } - case 2397: + case 2411: { parser.yyVAL.item = model.TableLockWrite } - case 2398: + case 2412: { parser.yyVAL.item = model.TableLockWriteLocal } - case 2399: + case 2413: { parser.yyVAL.item = []ast.TableLock{yyS[yypt-0].item.(ast.TableLock)} } - case 2400: + case 2414: { parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.TableLock), yyS[yypt-0].item.(ast.TableLock)) } - case 2401: + case 2415: { parser.yyVAL.statement = &ast.KillStmt{ ConnectionID: getUint64FromNUM(yyS[yypt-0].item), TiDBExtension: yyS[yypt-1].item.(bool), } } - case 2402: + case 2416: { parser.yyVAL.statement = &ast.KillStmt{ ConnectionID: getUint64FromNUM(yyS[yypt-0].item), TiDBExtension: yyS[yypt-2].item.(bool), } } - case 2403: + case 2417: { parser.yyVAL.statement = &ast.KillStmt{ ConnectionID: getUint64FromNUM(yyS[yypt-0].item), @@ -20936,28 +21069,28 @@ yynewstate: TiDBExtension: yyS[yypt-2].item.(bool), } } - case 2404: + case 2418: { parser.yyVAL.item = false } - case 2405: + case 2419: { parser.yyVAL.item = true } - case 2406: + case 2420: { parser.yyVAL.statement = &ast.LoadStatsStmt{ Path: yyS[yypt-0].ident, } } - case 2407: + case 2421: { parser.yyVAL.statement = &ast.DropPlacementPolicyStmt{ IfExists: yyS[yypt-1].item.(bool), PolicyName: model.NewCIStr(yyS[yypt-0].ident), } } - case 2408: + case 2422: { parser.yyVAL.statement = &ast.CreatePlacementPolicyStmt{ OrReplace: yyS[yypt-5].item.(bool), @@ -20966,7 +21099,7 @@ yynewstate: PlacementOptions: yyS[yypt-0].item.([]*ast.PlacementOption), } } - case 2409: + case 2423: { parser.yyVAL.statement = &ast.AlterPlacementPolicyStmt{ IfExists: yyS[yypt-2].item.(bool), @@ -20974,7 +21107,7 @@ yynewstate: PlacementOptions: yyS[yypt-0].item.([]*ast.PlacementOption), } } - case 2410: + case 2424: { parser.yyVAL.statement = &ast.CreateSequenceStmt{ IfNotExists: yyS[yypt-3].item.(bool), @@ -20983,87 +21116,87 @@ yynewstate: TblOptions: yyS[yypt-0].item.([]*ast.TableOption), } } - case 2411: + case 2425: { parser.yyVAL.item = []*ast.SequenceOption{} } - case 2413: + case 2427: { parser.yyVAL.item = []*ast.SequenceOption{yyS[yypt-0].item.(*ast.SequenceOption)} } - case 2414: + case 2428: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.SequenceOption), yyS[yypt-0].item.(*ast.SequenceOption)) } - case 2415: + case 2429: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceOptionIncrementBy, IntValue: yyS[yypt-0].item.(int64)} } - case 2416: + case 2430: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceOptionIncrementBy, IntValue: yyS[yypt-0].item.(int64)} } - case 2417: + case 2431: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceStartWith, IntValue: yyS[yypt-0].item.(int64)} } - case 2418: + case 2432: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceStartWith, IntValue: yyS[yypt-0].item.(int64)} } - case 2419: + case 2433: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceMinValue, IntValue: yyS[yypt-0].item.(int64)} } - case 2420: + case 2434: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoMinValue} } - case 2421: + case 2435: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoMinValue} } - case 2422: + case 2436: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceMaxValue, IntValue: yyS[yypt-0].item.(int64)} } - case 2423: + case 2437: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoMaxValue} } - case 2424: + case 2438: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoMaxValue} } - case 2425: + case 2439: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceCache, IntValue: yyS[yypt-0].item.(int64)} } - case 2426: + case 2440: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoCache} } - case 2427: + case 2441: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoCache} } - case 2428: + case 2442: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceCycle} } - case 2429: + case 2443: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoCycle} } - case 2430: + case 2444: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceNoCycle} } - case 2432: + case 2446: { parser.yyVAL.item = yyS[yypt-0].item } - case 2433: + case 2447: { unsigned_num := getUint64FromNUM(yyS[yypt-0].item) if unsigned_num > 9223372036854775808 { @@ -21076,14 +21209,14 @@ yynewstate: parser.yyVAL.item = -int64(unsigned_num) } } - case 2434: + case 2448: { parser.yyVAL.statement = &ast.DropSequenceStmt{ IfExists: yyS[yypt-1].item.(bool), Sequences: yyS[yypt-0].item.([]*ast.TableName), } } - case 2435: + case 2449: { parser.yyVAL.statement = &ast.AlterSequenceStmt{ IfExists: yyS[yypt-2].item.(bool), @@ -21091,27 +21224,27 @@ yynewstate: SeqOptions: yyS[yypt-0].item.([]*ast.SequenceOption), } } - case 2436: + case 2450: { parser.yyVAL.item = []*ast.SequenceOption{yyS[yypt-0].item.(*ast.SequenceOption)} } - case 2437: + case 2451: { parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.SequenceOption), yyS[yypt-0].item.(*ast.SequenceOption)) } - case 2439: + case 2453: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceRestart} } - case 2440: + case 2454: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceRestartWith, IntValue: yyS[yypt-0].item.(int64)} } - case 2441: + case 2455: { parser.yyVAL.item = &ast.SequenceOption{Tp: ast.SequenceRestartWith, IntValue: yyS[yypt-0].item.(int64)} } - case 2442: + case 2456: { x := &ast.IndexAdviseStmt{ Path: yyS[yypt-3].ident, @@ -21128,42 +21261,42 @@ yynewstate: } parser.yyVAL.statement = x } - case 2443: + case 2457: { parser.yyVAL.item = uint64(ast.UnspecifiedSize) } - case 2444: + case 2458: { parser.yyVAL.item = getUint64FromNUM(yyS[yypt-0].item) } - case 2445: + case 2459: { parser.yyVAL.item = nil } - case 2446: + case 2460: { parser.yyVAL.item = &ast.MaxIndexNumClause{ PerTable: yyS[yypt-1].item.(uint64), PerDB: yyS[yypt-0].item.(uint64), } } - case 2447: + case 2461: { parser.yyVAL.item = uint64(ast.UnspecifiedSize) } - case 2448: + case 2462: { parser.yyVAL.item = getUint64FromNUM(yyS[yypt-0].item) } - case 2449: + case 2463: { parser.yyVAL.item = uint64(ast.UnspecifiedSize) } - case 2450: + case 2464: { parser.yyVAL.item = getUint64FromNUM(yyS[yypt-0].item) } - case 2451: + case 2465: { // Parse it but will ignore it switch yyS[yypt-0].ident { @@ -21178,19 +21311,19 @@ yynewstate: } parser.yyVAL.ident = yyS[yypt-0].ident } - case 2452: + case 2466: { parser.yyVAL.item = append([]*ast.RowExpr{}, yyS[yypt-0].item.(*ast.RowExpr)) } - case 2453: + case 2467: { parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.RowExpr), yyS[yypt-0].item.(*ast.RowExpr)) } - case 2454: + case 2468: { parser.yyVAL.item = &ast.RowExpr{Values: yyS[yypt-0].item.([]ast.ExprNode)} } - case 2455: + case 2469: { x := &ast.PlanReplayerStmt{ Stmt: yyS[yypt-0].statement, @@ -21202,11 +21335,11 @@ yynewstate: Limit: nil, } startOffset := parser.startOffset(&yyS[yypt]) - x.Stmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) parser.yyVAL.statement = x } - case 2456: + case 2470: { x := &ast.PlanReplayerStmt{ Stmt: yyS[yypt-0].statement, @@ -21218,11 +21351,11 @@ yynewstate: Limit: nil, } startOffset := parser.startOffset(&yyS[yypt]) - x.Stmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) parser.yyVAL.statement = x } - case 2457: + case 2471: { x := &ast.PlanReplayerStmt{ Stmt: nil, @@ -21242,7 +21375,7 @@ yynewstate: parser.yyVAL.statement = x } - case 2458: + case 2472: { x := &ast.PlanReplayerStmt{ Stmt: nil, @@ -21262,7 +21395,7 @@ yynewstate: parser.yyVAL.statement = x } - case 2459: + case 2473: { x := &ast.PlanReplayerStmt{ Stmt: nil, diff --git a/parser/parser.y b/parser/parser.y index 4c2dc969450bd..75e72bafed171 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -314,6 +314,7 @@ import ( begin "BEGIN" bernoulli "BERNOULLI" binding "BINDING" + bindingCache "BINDING_CACHE" bindings "BINDINGS" binlog "BINLOG" bitType "BIT" @@ -370,12 +371,14 @@ import ( delayKeyWrite "DELAY_KEY_WRITE" directory "DIRECTORY" disable "DISABLE" + disabled "DISABLED" discard "DISCARD" disk "DISK" do "DO" duplicate "DUPLICATE" dynamic "DYNAMIC" enable "ENABLE" + enabled "ENABLED" encryption "ENCRYPTION" end "END" enforced "ENFORCED" @@ -748,7 +751,6 @@ import ( reset "RESET" regions "REGIONS" region "REGION" - builtinAddDate builtinBitAnd builtinBitOr builtinBitXor @@ -766,7 +768,6 @@ import ( builtinMin builtinNow builtinPosition - builtinSubDate builtinSubstring builtinSum builtinSysDate @@ -810,35 +811,37 @@ import ( %token not2 %type - Expression "expression" - MaxValueOrExpression "maxvalue or expression" - BoolPri "boolean primary expression" - ExprOrDefault "expression or default" - PredicateExpr "Predicate expression factor" - SetExpr "Set variable statement value's expression" - BitExpr "bit expression" - SimpleExpr "simple expression" - SimpleIdent "Simple Identifier expression" - SumExpr "aggregate functions" - FunctionCallGeneric "Function call with Identifier" - FunctionCallKeyword "Function call with keyword as function name" - FunctionCallNonKeyword "Function call with nonkeyword as function name" - Literal "literal value" - Variable "User or system variable" - SystemVariable "System defined variable name" - UserVariable "User defined variable name" - SubSelect "Sub Select" - StringLiteral "text literal" - ExpressionOpt "Optional expression" - SignedLiteral "Literal or NumLiteral with sign" - DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)" - NowSymOptionFraction "NowSym with optional fraction part" - CharsetNameOrDefault "Character set name or default" - NextValueForSequence "Default nextval expression" - FunctionNameSequence "Function with sequence function call" - WindowFuncCall "WINDOW function call" - RepeatableOpt "Repeatable optional in sample clause" - ProcedureCall "Procedure call with Identifier or identifier" + Expression "expression" + MaxValueOrExpression "maxvalue or expression" + BoolPri "boolean primary expression" + ExprOrDefault "expression or default" + PredicateExpr "Predicate expression factor" + SetExpr "Set variable statement value's expression" + BitExpr "bit expression" + SimpleExpr "simple expression" + SimpleIdent "Simple Identifier expression" + SumExpr "aggregate functions" + FunctionCallGeneric "Function call with Identifier" + FunctionCallKeyword "Function call with keyword as function name" + FunctionCallNonKeyword "Function call with nonkeyword as function name" + Literal "literal value" + Variable "User or system variable" + SystemVariable "System defined variable name" + UserVariable "User defined variable name" + SubSelect "Sub Select" + StringLiteral "text literal" + ExpressionOpt "Optional expression" + SignedLiteral "Literal or NumLiteral with sign" + DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)" + NowSymOptionFraction "NowSym with optional fraction part" + NowSymOptionFractionParentheses "NowSym with optional fraction part within potential parentheses" + CharsetNameOrDefault "Character set name or default" + NextValueForSequence "Default nextval expression" + BuiltinFunction "Default builtin functions" + FunctionNameSequence "Function with sequence function call" + WindowFuncCall "WINDOW function call" + RepeatableOpt "Repeatable optional in sample clause" + ProcedureCall "Procedure call with Identifier or identifier" %type AdminStmt "Check table statement or show ddl statement" @@ -914,6 +917,7 @@ import ( SplitRegionStmt "Split index region statement" SetStmt "Set variable statement" ChangeStmt "Change statement" + SetBindingStmt "Set binding statement" SetRoleStmt "Set active role statement" SetDefaultRoleStmt "Set default statement for some user" ShowImportStmt "SHOW IMPORT statement" @@ -1165,6 +1169,7 @@ import ( StatementList "statement list" StatsPersistentVal "stats_persistent value" StatsType "stats type value" + BindingStatusType "binding status type value" StringList "string list" SubPartDefinition "SubPartition definition" SubPartDefinitionList "SubPartition definition list" @@ -1195,6 +1200,7 @@ import ( TableSampleUnitOpt "table sample unit optional" TableToTable "rename table to table" TableToTableList "rename table to table by list" + TextString "text string item" TextStringList "text string list" TimeUnit "Time unit for 'DATE_ADD', 'DATE_SUB', 'ADDDATE', 'SUBDATE', 'EXTRACT'" TimestampUnit "Time unit for 'TIMESTAMPADD' and 'TIMESTAMPDIFF'" @@ -1309,7 +1315,6 @@ import ( BRIEBooleanOptionName "Name of a BRIE option which takes a boolean as input" BRIEStringOptionName "Name of a BRIE option which takes a string as input" BRIEKeywordOptionName "Name of a BRIE option which takes a case-insensitive string as input" - PlacementOption "Anonymous or direct placement option" PlacementPolicyOption "Anonymous or placement policy option" DirectPlacementOption "Subset of anonymous or direct placement option" PlacementOptionList "Anomymous or direct placement option list" @@ -1393,7 +1398,6 @@ import ( StringName "string literal or identifier" StringNameOrBRIEOptionKeyword "string literal or identifier or keyword used for BRIE options" Symbol "Constraint Symbol" - TextString "text string item" %precedence empty %precedence as @@ -1526,7 +1530,12 @@ DirectPlacementOption: } | "FOLLOWERS" EqOpt LengthNum { - $$ = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerCount, UintValue: $3.(uint64)} + cnt := $3.(uint64) + if cnt == 0 { + yylex.AppendError(yylex.Errorf("FOLLOWERS must be positive")) + return 1 + } + $$ = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerCount, UintValue: cnt} } | "VOTERS" EqOpt LengthNum { @@ -1561,10 +1570,6 @@ DirectPlacementOption: $$ = &ast.PlacementOption{Tp: ast.PlacementOptionLearnerConstraints, StrValue: $3} } -PlacementOption: - DirectPlacementOption -| PlacementPolicyOption - PlacementPolicyOption: "PLACEMENT" "POLICY" EqOpt stringLit { @@ -3034,7 +3039,7 @@ ColumnOption: startOffset := parser.startOffset(&yyS[yypt-2]) endOffset := parser.endOffset(&yyS[yypt-1]) expr := $4 - expr.SetText(parser.src[startOffset:endOffset]) + expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset]) $$ = &ast.ColumnOption{ Tp: ast.ColumnOptionGenerated, @@ -3319,19 +3324,46 @@ ReferOpt: /* * The DEFAULT clause specifies a default value for a column. - * With one exception, the default value must be a constant; - * it cannot be a function or an expression. This means, for example, - * that you cannot set the default for a date column to be the value of - * a function such as NOW() or CURRENT_DATE. The exception is that you - * can specify CURRENT_TIMESTAMP as the default for a TIMESTAMP or DATETIME column. + * It can be a function or an expression. This means, for example, + * that you can set the default for a date column to be the value of + * a function such as NOW() or CURRENT_DATE. While in MySQL 8.0 + * expression default values are required to be enclosed in parentheses, + * they are NOT required so in TiDB. * - * See http://dev.mysql.com/doc/refman/5.7/en/create-table.html - * https://github.com/mysql/mysql-server/blob/5.7/sql/sql_yacc.yy#L6832 + * See https://dev.mysql.com/doc/refman/8.0/en/create-table.html + * https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html */ DefaultValueExpr: - NowSymOptionFraction + NowSymOptionFractionParentheses | SignedLiteral | NextValueForSequence +| BuiltinFunction + +BuiltinFunction: + '(' BuiltinFunction ')' + { + $$ = $2.(*ast.FuncCallExpr) + } +| identifier '(' ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + } + } +| identifier '(' ExpressionList ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: $3.([]ast.ExprNode), + } + } + +NowSymOptionFractionParentheses: + '(' NowSymOptionFractionParentheses ')' + { + $$ = $2.(*ast.FuncCallExpr) + } +| NowSymOptionFraction NowSymOptionFraction: NowSym @@ -3417,6 +3449,16 @@ StatsType: $$ = ast.StatsTypeCorrelation } +BindingStatusType: + "ENABLED" + { + $$ = ast.BindingStatusTypeEnabled + } +| "DISABLED" + { + $$ = ast.BindingStatusTypeDisabled + } + CreateStatisticsStmt: "CREATE" "STATISTICS" IfNotExists Identifier '(' StatsType ')' "ON" TableName '(' ColumnNameList ')' { @@ -3659,7 +3701,7 @@ DatabaseOption: UintValue: placementOptions.UintValue, } } -| PlacementOption +| PlacementPolicyOption { placementOptions := $1.(*ast.PlacementOption) $$ = &ast.DatabaseOption{ @@ -3669,6 +3711,17 @@ DatabaseOption: UintValue: placementOptions.UintValue, } } +| "SET" "TIFLASH" "REPLICA" LengthNum LocationLabelList + { + tiflashReplicaSpec := &ast.TiFlashReplicaSpec{ + Count: $4.(uint64), + Labels: $5.([]string), + } + $$ = &ast.DatabaseOption{ + Tp: ast.DatabaseSetTiFlashReplica, + TiFlashReplica: tiflashReplicaSpec, + } + } DatabaseOptionListOpt: { @@ -3715,7 +3768,7 @@ CreateTableStmt: stmt.OnDuplicate = $9.(ast.OnDuplicateKeyHandlingType) stmt.Select = $11.(*ast.CreateTableStmt).Select if ($12 != nil && stmt.TemporaryKeyword != ast.TemporaryGlobal) || (stmt.TemporaryKeyword == ast.TemporaryGlobal && $12 == nil) { - yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE|PRESERVE ROWS must appear together")) + yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together")) } else { if stmt.TemporaryKeyword == ast.TemporaryGlobal { stmt.OnCommitDelete = $12.(bool) @@ -3732,7 +3785,7 @@ CreateTableStmt: TemporaryKeyword: $2.(ast.TemporaryKeyword), } if ($7 != nil && tmp.TemporaryKeyword != ast.TemporaryGlobal) || (tmp.TemporaryKeyword == ast.TemporaryGlobal && $7 == nil) { - yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE|PRESERVE ROWS must appear together")) + yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together")) } else { if tmp.TemporaryKeyword == ast.TemporaryGlobal { tmp.OnCommitDelete = $7.(bool) @@ -4028,7 +4081,7 @@ PartDefOption: { $$ = &ast.TableOption{Tp: ast.TableOptionNodegroup, UintValue: $3.(uint64)} } -| PlacementOption +| PlacementPolicyOption { placementOptions := $1.(*ast.PlacementOption) $$ = &ast.TableOption{ @@ -4171,7 +4224,7 @@ CreateViewStmt: { startOffset := parser.startOffset(&yyS[yypt-1]) selStmt := $10.(ast.StmtNode) - selStmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) x := &ast.CreateViewStmt{ OrReplace: $2.(bool), ViewName: $7.(*ast.TableName), @@ -4186,7 +4239,7 @@ CreateViewStmt: if $11 != nil { x.CheckOption = $11.(model.ViewCheckOption) endOffset := parser.startOffset(&yyS[yypt]) - selStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset])) + selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset])) } else { x.CheckOption = model.CheckOptionCascaded } @@ -4529,7 +4582,7 @@ TraceStmt: TracePlan: false, } startOffset := parser.startOffset(&yyS[yypt]) - $2.SetText(string(parser.src[startOffset:])) + $2.SetText(parser.lexer.client, string(parser.src[startOffset:])) } | "TRACE" "FORMAT" "=" stringLit TraceableStmt { @@ -4539,7 +4592,7 @@ TraceStmt: TracePlan: false, } startOffset := parser.startOffset(&yyS[yypt]) - $5.SetText(string(parser.src[startOffset:])) + $5.SetText(parser.lexer.client, string(parser.src[startOffset:])) } | "TRACE" "PLAN" TraceableStmt { @@ -4548,7 +4601,7 @@ TraceStmt: TracePlan: true, } startOffset := parser.startOffset(&yyS[yypt]) - $3.SetText(string(parser.src[startOffset:])) + $3.SetText(parser.lexer.client, string(parser.src[startOffset:])) } | "TRACE" "PLAN" "TARGET" "=" stringLit TraceableStmt { @@ -4558,7 +4611,7 @@ TraceStmt: TracePlanTarget: $5, } startOffset := parser.startOffset(&yyS[yypt]) - $6.SetText(string(parser.src[startOffset:])) + $6.SetText(parser.lexer.client, string(parser.src[startOffset:])) } ExplainSym: @@ -5491,7 +5544,7 @@ FieldList: last := fl[len(fl)-1] if last.Expr != nil && last.AsName.O == "" { lastEnd := parser.endOffset(&yyS[yypt-1]) - last.SetText(parser.src[last.Offset:lastEnd]) + last.SetText(parser.lexer.client, parser.src[last.Offset:lastEnd]) } newField := $3.(*ast.SelectField) newField.Offset = parser.startOffset(&yyS[yypt]) @@ -5724,6 +5777,7 @@ UnReservedKeyword: | "ADVISE" | "ASCII" | "ATTRIBUTES" +| "BINDING_CACHE" | "STATS_OPTIONS" | "STATS_SAMPLE_RATE" | "STATS_COL_CHOICE" @@ -5870,7 +5924,9 @@ UnReservedKeyword: | "PROCESSLIST" | "SQL_NO_CACHE" | "DISABLE" +| "DISABLED" | "ENABLE" +| "ENABLED" | "REVERSE" | "PRIVILEGES" | "NO" @@ -6234,7 +6290,6 @@ ProcedureCall: * * Insert Statements * - * TODO: support PARTITION **********************************************************************************/ InsertIntoStmt: "INSERT" TableOptimizerHintsOpt PriorityOpt IgnoreOptional IntoOpt TableName PartitionNameListOpt InsertValues OnDuplicateKeyUpdate @@ -6408,7 +6463,6 @@ OnDuplicateKeyUpdate: * Replace Statements * See https://dev.mysql.com/doc/refman/5.7/en/replace.html * - * TODO: support PARTITION **********************************************************************************/ ReplaceIntoStmt: "REPLACE" PriorityOpt IntoOpt TableName PartitionNameListOpt InsertValues @@ -6456,7 +6510,7 @@ Literal: yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1)) return 1 } - expr := ast.NewValueExpr($2, parser.charset, parser.collation) + expr := ast.NewValueExpr($2, $1, co) tp := expr.GetType() tp.Charset = $1 tp.Collate = co @@ -6480,7 +6534,7 @@ Literal: yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1)) return 1 } - expr := ast.NewValueExpr($2, parser.charset, parser.collation) + expr := ast.NewValueExpr($2, $1, co) tp := expr.GetType() tp.Charset = $1 tp.Collate = co @@ -6496,7 +6550,7 @@ Literal: yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1)) return 1 } - expr := ast.NewValueExpr($2, parser.charset, parser.collation) + expr := ast.NewValueExpr($2, $1, co) tp := expr.GetType() tp.Charset = $1 tp.Collate = co @@ -6757,7 +6811,7 @@ SimpleExpr: startOffset := parser.startOffset(&yyS[yypt-1]) endOffset := parser.endOffset(&yyS[yypt]) expr := $2 - expr.SetText(parser.src[startOffset:endOffset]) + expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset]) $$ = &ast.ParenthesesExpr{Expr: expr} } | '(' ExpressionList ',' Expression ')' @@ -7237,8 +7291,8 @@ FunctionNameDateArith: | builtinDateSub FunctionNameDateArithMultiForms: - builtinAddDate -| builtinSubDate + addDate +| subDate TrimDirection: "BOTH" @@ -8072,7 +8126,7 @@ SelectStmtFromDualTable: lastField := st.Fields.Fields[len(st.Fields.Fields)-1] if lastField.Expr != nil && lastField.AsName.O == "" { lastEnd := yyS[yypt-1].offset - 1 - lastField.SetText(parser.src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd]) } if $3 != nil { st.Where = $3.(ast.ExprNode) @@ -8087,7 +8141,7 @@ SelectStmtFromTable: lastField := st.Fields.Fields[len(st.Fields.Fields)-1] if lastField.Expr != nil && lastField.AsName.O == "" { lastEnd := parser.endOffset(&yyS[yypt-5]) - lastField.SetText(parser.src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd]) } if $4 != nil { st.Where = $4.(ast.ExprNode) @@ -8205,7 +8259,7 @@ SelectStmt: lastEnd-- } } - lastField.SetText(src[lastField.Offset:lastEnd]) + lastField.SetText(parser.lexer.client, src[lastField.Offset:lastEnd]) } if $2 != nil { st.Where = $2.(ast.ExprNode) @@ -9147,14 +9201,14 @@ SubSelect: parser.setLastSelectFieldText(rs, endOffset) src := parser.src // See the implementation of yyParse function - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) $$ = &ast.SubqueryExpr{Query: rs} } | '(' SetOprStmt ')' { rs := $2.(*ast.SetOprStmt) src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) $$ = &ast.SubqueryExpr{Query: rs} } | '(' SelectStmtWithClause ')' @@ -9164,7 +9218,7 @@ SubSelect: parser.setLastSelectFieldText(rs, endOffset) src := parser.src // See the implementation of yyParse function - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) $$ = &ast.SubqueryExpr{Query: rs} } | '(' SubSelect ')' @@ -9182,11 +9236,11 @@ SubSelect: endOffset := parser.endOffset(&yyS[yypt]) parser.setLastSelectFieldText(rs, endOffset) src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) $$ = &ast.SubqueryExpr{Query: rs} case *ast.SetOprStmt: src := parser.src - rs.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset]) $$ = &ast.SubqueryExpr{Query: rs} } } @@ -10612,6 +10666,12 @@ ShowTargetFilterable: DBName: $2, } } +| "BINDING_CACHE" "STATUS" + { + $$ = &ast.ShowStmt{ + Tp: ast.ShowBindingCacheStatus, + } + } | "PROCEDURE" "STATUS" { $$ = &ast.ShowStmt{ @@ -10995,6 +11055,7 @@ Statement: $$ = sel } | SetStmt +| SetBindingStmt | SetRoleStmt | SetDefaultRoleStmt | SplitRegionStmt @@ -11067,7 +11128,7 @@ StatementList: if $1 != nil { s := $1 if lexer, ok := yylex.(stmtTexter); ok { - s.SetText(lexer.stmtText()) + s.SetText(parser.lexer.client, lexer.stmtText()) } parser.result = append(parser.result, s) } @@ -11077,7 +11138,7 @@ StatementList: if $3 != nil { s := $3 if lexer, ok := yylex.(stmtTexter); ok { - s.SetText(lexer.stmtText()) + s.SetText(parser.lexer.client, lexer.stmtText()) } parser.result = append(parser.result, s) } @@ -11726,7 +11787,9 @@ StringType: | "ENUM" '(' TextStringList ')' OptCharsetWithOptBinary { x := types.NewFieldType(mysql.TypeEnum) - x.Elems = $3.([]string) + elems := $3.([]*ast.TextString) + opt := $5.(*ast.OptBinary) + x.Elems = ast.TransformTextStrings(elems, opt.Charset) fieldLen := -1 // enum_flen = max(ele_flen) for i := range x.Elems { x.Elems[i] = strings.TrimRight(x.Elems[i], " ") @@ -11735,7 +11798,6 @@ StringType: } } x.Flen = fieldLen - opt := $5.(*ast.OptBinary) x.Charset = opt.Charset if opt.IsBinary { x.Flag |= mysql.BinaryFlag @@ -11745,14 +11807,15 @@ StringType: | "SET" '(' TextStringList ')' OptCharsetWithOptBinary { x := types.NewFieldType(mysql.TypeSet) - x.Elems = $3.([]string) + elems := $3.([]*ast.TextString) + opt := $5.(*ast.OptBinary) + x.Elems = ast.TransformTextStrings(elems, opt.Charset) fieldLen := len(x.Elems) - 1 // set_flen = sum(ele_flen) + number_of_ele - 1 for i := range x.Elems { x.Elems[i] = strings.TrimRight(x.Elems[i], " ") fieldLen += len(x.Elems[i]) } x.Flen = fieldLen - opt := $5.(*ast.OptBinary) x.Charset = opt.Charset if opt.IsBinary { x.Flag |= mysql.BinaryFlag @@ -12059,23 +12122,26 @@ StringList: TextString: stringLit + { + $$ = &ast.TextString{Value: $1} + } | hexLit { - $$ = $1.(ast.BinaryLiteral).ToString() + $$ = &ast.TextString{Value: $1.(ast.BinaryLiteral).ToString(), IsBinaryLiteral: true} } | bitLit { - $$ = $1.(ast.BinaryLiteral).ToString() + $$ = &ast.TextString{Value: $1.(ast.BinaryLiteral).ToString(), IsBinaryLiteral: true} } TextStringList: TextString { - $$ = []string{$1} + $$ = []*ast.TextString{$1.(*ast.TextString)} } | TextStringList ',' TextString { - $$ = append($1.([]string), $3) + $$ = append($1.([]*ast.TextString), $3.(*ast.TextString)) } StringName: @@ -12584,11 +12650,11 @@ CreateBindingStmt: startOffset := parser.startOffset(&yyS[yypt-2]) endOffset := parser.startOffset(&yyS[yypt-1]) originStmt := $5 - originStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset])) + originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset])) startOffset = parser.startOffset(&yyS[yypt]) hintedStmt := $7 - hintedStmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) x := &ast.CreateBindingStmt{ OriginNode: originStmt, @@ -12611,7 +12677,7 @@ DropBindingStmt: { startOffset := parser.startOffset(&yyS[yypt]) originStmt := $5 - originStmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) x := &ast.DropBindingStmt{ OriginNode: originStmt, @@ -12625,11 +12691,11 @@ DropBindingStmt: startOffset := parser.startOffset(&yyS[yypt-2]) endOffset := parser.startOffset(&yyS[yypt-1]) originStmt := $5 - originStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset])) + originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset])) startOffset = parser.startOffset(&yyS[yypt]) hintedStmt := $7 - hintedStmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) x := &ast.DropBindingStmt{ OriginNode: originStmt, @@ -12640,6 +12706,40 @@ DropBindingStmt: $$ = x } +SetBindingStmt: + "SET" "BINDING" BindingStatusType "FOR" BindableStmt + { + startOffset := parser.startOffset(&yyS[yypt]) + originStmt := $5 + originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) + + x := &ast.SetBindingStmt{ + BindingStatusType: $3.(ast.BindingStatusType), + OriginNode: originStmt, + } + + $$ = x + } +| "SET" "BINDING" BindingStatusType "FOR" BindableStmt "USING" BindableStmt + { + startOffset := parser.startOffset(&yyS[yypt-2]) + endOffset := parser.startOffset(&yyS[yypt-1]) + originStmt := $5 + originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset])) + + startOffset = parser.startOffset(&yyS[yypt]) + hintedStmt := $7 + hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) + + x := &ast.SetBindingStmt{ + BindingStatusType: $3.(ast.BindingStatusType), + OriginNode: originStmt, + HintedNode: hintedStmt, + } + + $$ = x + } + /************************************************************************************* * Grant statement * See https://dev.mysql.com/doc/refman/5.7/en/grant.html @@ -13716,7 +13816,7 @@ PlanReplayerStmt: Limit: nil, } startOffset := parser.startOffset(&yyS[yypt]) - x.Stmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) $$ = x } @@ -13732,7 +13832,7 @@ PlanReplayerStmt: Limit: nil, } startOffset := parser.startOffset(&yyS[yypt]) - x.Stmt.SetText(strings.TrimSpace(parser.src[startOffset:])) + x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:])) $$ = x } diff --git a/parser/parser_test.go b/parser/parser_test.go index 1c5ed6b4e9987..859afdce83b07 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -1134,6 +1134,8 @@ func TestDBAStmt(t *testing.T) { // for show pump/drainer status. {"show pump status", true, "SHOW PUMP STATUS"}, {"show drainer status", true, "SHOW DRAINER STATUS"}, + // for show binding_cache status + {"show binding_cache status", true, "SHOW BINDING_CACHE STATUS"}, {"show analyze status", true, "SHOW ANALYZE STATUS"}, {"show analyze status where table_name = 't'", true, "SHOW ANALYZE STATUS WHERE `table_name`=_UTF8MB4't'"}, {"show analyze status where table_name like '%'", true, "SHOW ANALYZE STATUS WHERE `table_name` LIKE _UTF8MB4'%'"}, @@ -2190,10 +2192,116 @@ func TestIdentifier(t *testing.T) { {`select .78'123'`, true, "SELECT 0.78 AS `123`"}, {"select .78`123`", true, "SELECT 0.78 AS `123`"}, {`select .78"123"`, true, "SELECT 0.78 AS `123`"}, + {"select 111 as \xd6\xf7", true, "SELECT 111 AS `??`"}, } RunTest(t, table, false) } +func TestBuiltinFuncAsIdentifier(t *testing.T) { + whitespaceFuncs := []struct { + funcName string + args string + }{ + {"BIT_AND", "`c1`"}, + {"BIT_OR", "`c1`"}, + {"BIT_XOR", "`c1`"}, + {"CAST", "1 AS FLOAT"}, + {"COUNT", "1"}, + {"CURDATE", ""}, + {"CURTIME", ""}, + {"DATE_ADD", "_UTF8MB4'2011-11-11 10:10:10', INTERVAL 10 SECOND"}, + {"DATE_SUB", "_UTF8MB4'2011-11-11 10:10:10', INTERVAL 10 SECOND"}, + {"EXTRACT", "SECOND FROM _UTF8MB4'2011-11-11 10:10:10'"}, + {"GROUP_CONCAT", "`c2`, `c1` SEPARATOR ','"}, + {"MAX", "`c1`"}, + {"MID", "_UTF8MB4'Sakila', -5, 3"}, + {"MIN", "`c1`"}, + {"NOW", ""}, + {"POSITION", "_UTF8MB4'bar' IN _UTF8MB4'foobarbar'"}, + {"STDDEV_POP", "`c1`"}, + {"STDDEV_SAMP", "`c1`"}, + {"SUBSTR", "_UTF8MB4'Quadratically', 5"}, + {"SUBSTRING", "_UTF8MB4'Quadratically', 5"}, + {"SUM", "`c1`"}, + {"SYSDATE", ""}, + {"TRIM", "_UTF8MB4' foo '"}, + {"VAR_POP", "`c1`"}, + {"VAR_SAMP", "`c1`"}, + } + + testcases := make([]testCase, 0, 3*len(whitespaceFuncs)) + runTests := func(ignoreSpace bool) { + p := parser.New() + if ignoreSpace { + p.SetSQLMode(mysql.ModeIgnoreSpace) + } + for _, c := range testcases { + _, _, err := p.Parse(c.src, "", "") + if !c.ok { + require.Errorf(t, err, "source %v", c.src) + continue + } + require.NoErrorf(t, err, "source %v", c.src) + if c.ok && !ignoreSpace { + RunRestoreTest(t, c.src, c.restore, false) + } + } + } + + for _, function := range whitespaceFuncs { + // `x` is recognized as a function name for `x()`. + testcases = append(testcases, testCase{fmt.Sprintf("select %s(%s)", function.funcName, function.args), true, fmt.Sprintf("SELECT %s(%s)", function.funcName, function.args)}) + + // In MySQL, `select x ()` is recognized as a stored function. + // In TiDB, most of these functions are recognized as identifiers while some are builtin functions (such as COUNT, CURDATE) + // because the later ones are not added to the token map. We'd better not to modify it since it breaks compatibility. + // For example, `select CURDATE ()` reports an error in MySQL but it works well for TiDB. + + // `x` is recognized as an identifier for `x ()`. + testcases = append(testcases, testCase{fmt.Sprintf("create table %s (a int)", function.funcName), true, fmt.Sprintf("CREATE TABLE `%s` (`a` INT)", function.funcName)}) + + // `x` is recognized as a function name for `x()`. + testcases = append(testcases, testCase{fmt.Sprintf("create table %s(a int)", function.funcName), false, ""}) + } + runTests(false) + + testcases = make([]testCase, 0, 4*len(whitespaceFuncs)) + for _, function := range whitespaceFuncs { + testcases = append(testcases, testCase{fmt.Sprintf("select %s(%s)", function.funcName, function.args), true, fmt.Sprintf("SELECT %s(%s)", function.funcName, function.args)}) + testcases = append(testcases, testCase{fmt.Sprintf("select %s (%s)", function.funcName, function.args), true, fmt.Sprintf("SELECT %s(%s)", function.funcName, function.args)}) + testcases = append(testcases, testCase{fmt.Sprintf("create table %s (a int)", function.funcName), false, ""}) + testcases = append(testcases, testCase{fmt.Sprintf("create table %s(a int)", function.funcName), false, ""}) + } + runTests(true) + + normalFuncs := []struct { + funcName string + args string + }{ + {"ADDDATE", "_UTF8MB4'2011-11-11 10:10:10', INTERVAL 10 SECOND"}, + {"SESSION_USER", ""}, + {"SUBDATE", "_UTF8MB4'2011-11-11 10:10:10', INTERVAL 10 SECOND"}, + {"SYSTEM_USER", ""}, + } + + testcases = make([]testCase, 0, 4*len(normalFuncs)) + for _, function := range normalFuncs { + // `x` is recognized as a function name for `select x()`. + testcases = append(testcases, testCase{fmt.Sprintf("select %s(%s)", function.funcName, function.args), true, fmt.Sprintf("SELECT %s(%s)", function.funcName, function.args)}) + + // `x` is recognized as a function name for `select x ()`. + testcases = append(testcases, testCase{fmt.Sprintf("select %s (%s)", function.funcName, function.args), true, fmt.Sprintf("SELECT %s(%s)", function.funcName, function.args)}) + + // `x` is recognized as an identifier for `create table x ()`. + testcases = append(testcases, testCase{fmt.Sprintf("create table %s (a int)", function.funcName), true, fmt.Sprintf("CREATE TABLE `%s` (`a` INT)", function.funcName)}) + + // `x` is recognized as an identifier for `create table x()`. + testcases = append(testcases, testCase{fmt.Sprintf("create table %s(a int)", function.funcName), true, fmt.Sprintf("CREATE TABLE `%s` (`a` INT)", function.funcName)}) + } + runTests(false) + runTests(true) +} + func TestDDL(t *testing.T) { table := []testCase{ {"CREATE", false, ""}, @@ -2294,6 +2402,7 @@ func TestDDL(t *testing.T) { {`create table testTableCompression (c VARCHAR(15000)) compression="ZLIB";`, true, "CREATE TABLE `testTableCompression` (`c` VARCHAR(15000)) COMPRESSION = 'ZLIB'"}, {`create table t1 (c1 int) compression="zlib";`, true, "CREATE TABLE `t1` (`c1` INT) COMPRESSION = 'zlib'"}, {`create table t1 (c1 int) collate=binary;`, true, "CREATE TABLE `t1` (`c1` INT) DEFAULT COLLATE = BINARY"}, + {`create table t1 (c1 int) collate=utf8mb4_0900_as_cs;`, true, "CREATE TABLE `t1` (`c1` INT) DEFAULT COLLATE = UTF8MB4_0900_AS_CS"}, {`create table t1 (c1 int) default charset=binary collate=binary;`, true, "CREATE TABLE `t1` (`c1` INT) DEFAULT CHARACTER SET = BINARY DEFAULT COLLATE = BINARY"}, // for table option `UNION` @@ -2334,106 +2443,128 @@ func TestDDL(t *testing.T) { // for placement option // 1. create table - {`create table t (c int) primary_region="us";`, true, "CREATE TABLE `t` (`c` INT) PRIMARY_REGION = 'us'"}, - {`create table t (c int) regions="us,3";`, true, "CREATE TABLE `t` (`c` INT) REGIONS = 'us,3'"}, + {`create table t (c int) primary_region="us";`, false, ""}, + {`create table t (c int) regions="us,3";`, false, ""}, {`create table t (c int) followers="us,3";`, false, ""}, - {`create table t (c int) followers=3;`, true, "CREATE TABLE `t` (`c` INT) FOLLOWERS = 3"}, - {`create table t (c int) voters="us,3";`, false, ""}, - {`create table t (c int) voters=3;`, true, "CREATE TABLE `t` (`c` INT) VOTERS = 3"}, + {`create table t (c int) followers=3;`, false, ""}, + {`create table t (c int) followers=0;`, false, ""}, + {`create table t (c int) voters=3;`, false, ""}, {`create table t (c int) learners="us,3";`, false, ""}, - {`create table t (c int) learners=3;`, true, "CREATE TABLE `t` (`c` INT) LEARNERS = 3"}, - {`create table t (c int) schedule="even";`, true, "CREATE TABLE `t` (`c` INT) SCHEDULE = 'even'"}, - {`create table t (c int) constraints="ww";`, true, "CREATE TABLE `t` (`c` INT) CONSTRAINTS = 'ww'"}, - {`create table t (c int) leader_constraints="ww";`, true, "CREATE TABLE `t` (`c` INT) LEADER_CONSTRAINTS = 'ww'"}, - {`create table t (c int) follower_constraints="ww";`, true, "CREATE TABLE `t` (`c` INT) FOLLOWER_CONSTRAINTS = 'ww'"}, - {`create table t (c int) voter_constraints="ww";`, true, "CREATE TABLE `t` (`c` INT) VOTER_CONSTRAINTS = 'ww'"}, - {`create table t (c int) learner_constraints="ww";`, true, "CREATE TABLE `t` (`c` INT) LEARNER_CONSTRAINTS = 'ww'"}, - {`create table t (c int) placement policy="ww";`, true, "CREATE TABLE `t` (`c` INT) PLACEMENT POLICY = `ww`"}, - {`create table t (c int) /*T![placement] primary_region="us" */;`, true, "CREATE TABLE `t` (`c` INT) PRIMARY_REGION = 'us'"}, - {`create table t (c int) /*T![placement] regions="us,3" */;`, true, "CREATE TABLE `t` (`c` INT) REGIONS = 'us,3'"}, + {`create table t (c int) learners=3;`, false, ""}, + {`create table t (c int) schedule="even";`, false, ""}, + {`create table t (c int) constraints="ww";`, false, ""}, + {`create table t (c int) leader_constraints="ww";`, false, ""}, + {`create table t (c int) follower_constraints="ww";`, false, ""}, + {`create table t (c int) voter_constraints="ww";`, false, ""}, + {`create table t (c int) learner_constraints="ww";`, false, ""}, + {`create table t (c int) /*T![placement] primary_region="us" */;`, false, ""}, + {`create table t (c int) /*T![placement] regions="us,3" */;`, false, ""}, {`create table t (c int) /*T![placement] followers="us,3 */";`, false, ""}, - {`create table t (c int) /*T![placement] followers=3 */;`, true, "CREATE TABLE `t` (`c` INT) FOLLOWERS = 3"}, + {`create table t (c int) /*T![placement] followers=3 */;`, false, ""}, + {`create table t (c int) /*T![placement] followers=0 */;`, false, ""}, {`create table t (c int) /*T![placement] voters="us,3" */;`, false, ""}, - {`create table t (c int) /*T![placement] primary_region="us" regions="us,3" */;`, true, "CREATE TABLE `t` (`c` INT) PRIMARY_REGION = 'us' REGIONS = 'us,3'"}, + {`create table t (c int) /*T![placement] primary_region="us" regions="us,3" */;`, false, ""}, + {`create table t (c int) placement policy="ww";`, true, "CREATE TABLE `t` (`c` INT) PLACEMENT POLICY = `ww`"}, {"create table t (c int) /*T![placement] placement policy=`x` */;", true, "CREATE TABLE `t` (`c` INT) PLACEMENT POLICY = `x`"}, {`create table t (c int) /*T![placement] placement policy="y" */;`, true, "CREATE TABLE `t` (`c` INT) PLACEMENT POLICY = `y`"}, // 2. alter table - {`alter table t primary_region="us";`, true, "ALTER TABLE `t` PRIMARY_REGION = 'us'"}, - {`alter table t regions="us,3";`, true, "ALTER TABLE `t` REGIONS = 'us,3'"}, - {`alter table t followers=3;`, true, "ALTER TABLE `t` FOLLOWERS = 3"}, - {`alter table t voters=3;`, true, "ALTER TABLE `t` VOTERS = 3"}, - {`alter table t learners=3;`, true, "ALTER TABLE `t` LEARNERS = 3"}, - {`alter table t schedule="even";`, true, "ALTER TABLE `t` SCHEDULE = 'even'"}, - {`alter table t constraints="ww";`, true, "ALTER TABLE `t` CONSTRAINTS = 'ww'"}, - {`alter table t leader_constraints="ww";`, true, "ALTER TABLE `t` LEADER_CONSTRAINTS = 'ww'"}, - {`alter table t follower_constraints="ww";`, true, "ALTER TABLE `t` FOLLOWER_CONSTRAINTS = 'ww'"}, - {`alter table t voter_constraints="ww";`, true, "ALTER TABLE `t` VOTER_CONSTRAINTS = 'ww'"}, - {`alter table t learner_constraints="ww";`, true, "ALTER TABLE `t` LEARNER_CONSTRAINTS = 'ww'"}, + {`alter table t primary_region="us";`, false, ""}, + {`alter table t regions="us,3";`, false, ""}, + {`alter table t followers=3;`, false, ""}, + {`alter table t followers=0;`, false, ""}, + {`alter table t voters=3;`, false, ""}, + {`alter table t learners=3;`, false, ""}, + {`alter table t schedule="even";`, false, ""}, + {`alter table t constraints="ww";`, false, ""}, + {`alter table t leader_constraints="ww";`, false, ""}, + {`alter table t follower_constraints="ww";`, false, ""}, + {`alter table t voter_constraints="ww";`, false, ""}, + {`alter table t learner_constraints="ww";`, false, ""}, + {`alter table t /*T![placement] primary_region="us" */;`, false, ""}, {`alter table t placement policy="ww";`, true, "ALTER TABLE `t` PLACEMENT POLICY = `ww`"}, - {`alter table t /*T![placement] primary_region="us" */;`, true, "ALTER TABLE `t` PRIMARY_REGION = 'us'"}, + {`alter table t /*T![placement] placement policy="ww" */;`, true, "ALTER TABLE `t` PLACEMENT POLICY = `ww`"}, // 3. create db - {`create database t primary_region="us";`, true, "CREATE DATABASE `t` PRIMARY_REGION = 'us'"}, - {`create database t regions="us,3";`, true, "CREATE DATABASE `t` REGIONS = 'us,3'"}, - {`create database t followers=3;`, true, "CREATE DATABASE `t` FOLLOWERS = 3"}, - {`create database t voters=3;`, true, "CREATE DATABASE `t` VOTERS = 3"}, - {`create database t learners=3;`, true, "CREATE DATABASE `t` LEARNERS = 3"}, - {`create database t schedule="even";`, true, "CREATE DATABASE `t` SCHEDULE = 'even'"}, - {`create database t constraints="ww";`, true, "CREATE DATABASE `t` CONSTRAINTS = 'ww'"}, - {`create database t leader_constraints="ww";`, true, "CREATE DATABASE `t` LEADER_CONSTRAINTS = 'ww'"}, - {`create database t follower_constraints="ww";`, true, "CREATE DATABASE `t` FOLLOWER_CONSTRAINTS = 'ww'"}, - {`create database t voter_constraints="ww";`, true, "CREATE DATABASE `t` VOTER_CONSTRAINTS = 'ww'"}, - {`create database t learner_constraints="ww";`, true, "CREATE DATABASE `t` LEARNER_CONSTRAINTS = 'ww'"}, + {`create database t primary_region="us";`, false, ""}, + {`create database t regions="us,3";`, false, ""}, + {`create database t followers=3;`, false, ""}, + {`create database t followers=0;`, false, ""}, + {`create database t voters=3;`, false, ""}, + {`create database t learners=3;`, false, ""}, + {`create database t schedule="even";`, false, ""}, + {`create database t constraints="ww";`, false, ""}, + {`create database t leader_constraints="ww";`, false, ""}, + {`create database t follower_constraints="ww";`, false, ""}, + {`create database t voter_constraints="ww";`, false, ""}, + {`create database t learner_constraints="ww";`, false, ""}, + {`create database t /*T![placement] primary_region="us" */;`, false, ""}, {`create database t placement policy="ww";`, true, "CREATE DATABASE `t` PLACEMENT POLICY = `ww`"}, {`create database t default placement policy="ww";`, true, "CREATE DATABASE `t` PLACEMENT POLICY = `ww`"}, - {`create database t /*T![placement] primary_region="us" */;`, true, "CREATE DATABASE `t` PRIMARY_REGION = 'us'"}, + {`create database t /*T![placement] placement policy="ww" */;`, true, "CREATE DATABASE `t` PLACEMENT POLICY = `ww`"}, // 4. alter db - {`alter database t primary_region="us";`, true, "ALTER DATABASE `t` PRIMARY_REGION = 'us'"}, - {`alter database t regions="us,3";`, true, "ALTER DATABASE `t` REGIONS = 'us,3'"}, - {`alter database t followers=3;`, true, "ALTER DATABASE `t` FOLLOWERS = 3"}, - {`alter database t voters=3;`, true, "ALTER DATABASE `t` VOTERS = 3"}, - {`alter database t learners=3;`, true, "ALTER DATABASE `t` LEARNERS = 3"}, - {`alter database t schedule="even";`, true, "ALTER DATABASE `t` SCHEDULE = 'even'"}, - {`alter database t constraints="ww";`, true, "ALTER DATABASE `t` CONSTRAINTS = 'ww'"}, - {`alter database t leader_constraints="ww";`, true, "ALTER DATABASE `t` LEADER_CONSTRAINTS = 'ww'"}, - {`alter database t follower_constraints="ww";`, true, "ALTER DATABASE `t` FOLLOWER_CONSTRAINTS = 'ww'"}, - {`alter database t voter_constraints="ww";`, true, "ALTER DATABASE `t` VOTER_CONSTRAINTS = 'ww'"}, - {`alter database t learner_constraints="ww";`, true, "ALTER DATABASE `t` LEARNER_CONSTRAINTS = 'ww'"}, + {`alter database t primary_region="us";`, false, ""}, + {`alter database t regions="us,3";`, false, ""}, + {`alter database t followers=3;`, false, ""}, + {`alter database t followers=0;`, false, ""}, + {`alter database t voters=3;`, false, ""}, + {`alter database t learners=3;`, false, ""}, + {`alter database t schedule="even";`, false, ""}, + {`alter database t constraints="ww";`, false, ""}, + {`alter database t leader_constraints="ww";`, false, ""}, + {`alter database t follower_constraints="ww";`, false, ""}, + {`alter database t voter_constraints="ww";`, false, ""}, + {`alter database t learner_constraints="ww";`, false, ""}, + {`alter database t /*T![placement] primary_region="us" */;`, false, ""}, {`alter database t placement policy="ww";`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `ww`"}, {`alter database t default placement policy="ww";`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `ww`"}, - {`alter database t /*T![placement] primary_region="us" */;`, true, "ALTER DATABASE `t` PRIMARY_REGION = 'us'"}, {`alter database t PLACEMENT POLICY='DEFAULT';`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, {`alter database t PLACEMENT POLICY=DEFAULT;`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, {`alter database t PLACEMENT POLICY = DEFAULT;`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, {`alter database t PLACEMENT POLICY SET DEFAULT`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, {"alter database t PLACEMENT POLICY=`DEFAULT`;", true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, + {`alter database t /*T![placement] PLACEMENT POLICY='DEFAULT' */;`, true, "ALTER DATABASE `t` PLACEMENT POLICY = `DEFAULT`"}, // 5. create partition - {`create table m (c int) partition by range (c) (partition p1 values less than (200) primary_region="us");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) PRIMARY_REGION = 'us')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) regions="us,3");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) REGIONS = 'us,3')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) followers=3);`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) FOLLOWERS = 3)"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) voters=3);`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) VOTERS = 3)"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) learners=3);`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) LEARNERS = 3)"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) schedule="even");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) SCHEDULE = 'even')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) constraints="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) CONSTRAINTS = 'ww')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) leader_constraints="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) LEADER_CONSTRAINTS = 'ww')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) follower_constraints="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) FOLLOWER_CONSTRAINTS = 'ww')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) voter_constraints="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) VOTER_CONSTRAINTS = 'ww')"}, - {`create table m (c int) partition by range (c) (partition p1 values less than (200) learner_constraints="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) LEARNER_CONSTRAINTS = 'ww')"}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) primary_region="us");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) regions="us,3");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) followers=3);`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) voters=3);`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) learners=3);`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) schedule="even");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) constraints="ww");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) leader_constraints="ww");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) follower_constraints="ww");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) voter_constraints="ww");`, false, ""}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) learner_constraints="ww");`, false, ""}, {`create table m (c int) partition by range (c) (partition p1 values less than (200) placement policy="ww");`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) PLACEMENT POLICY = `ww`)"}, + {`create table m (c int) partition by range (c) (partition p1 values less than (200) /*T![placement] placement policy="ww" */);`, true, "CREATE TABLE `m` (`c` INT) PARTITION BY RANGE (`c`) (PARTITION `p1` VALUES LESS THAN (200) PLACEMENT POLICY = `ww`)"}, // 6. alter partition - {`alter table m partition t primary_region="us";`, true, "ALTER TABLE `m` PARTITION `t` PRIMARY_REGION = 'us'"}, - {`alter table m partition t regions="us,3";`, true, "ALTER TABLE `m` PARTITION `t` REGIONS = 'us,3'"}, - {`alter table m partition t followers=3;`, true, "ALTER TABLE `m` PARTITION `t` FOLLOWERS = 3"}, - {`alter table m partition t primary_region="us" followers=3;`, true, "ALTER TABLE `m` PARTITION `t` PRIMARY_REGION = 'us' FOLLOWERS = 3"}, - {`alter table m partition t voters=3;`, true, "ALTER TABLE `m` PARTITION `t` VOTERS = 3"}, - {`alter table m partition t learners=3;`, true, "ALTER TABLE `m` PARTITION `t` LEARNERS = 3"}, - {`alter table m partition t schedule="even";`, true, "ALTER TABLE `m` PARTITION `t` SCHEDULE = 'even'"}, - {`alter table m partition t constraints="ww";`, true, "ALTER TABLE `m` PARTITION `t` CONSTRAINTS = 'ww'"}, - {`alter table m partition t leader_constraints="ww";`, true, "ALTER TABLE `m` PARTITION `t` LEADER_CONSTRAINTS = 'ww'"}, - {`alter table m partition t follower_constraints="ww";`, true, "ALTER TABLE `m` PARTITION `t` FOLLOWER_CONSTRAINTS = 'ww'"}, - {`alter table m partition t voter_constraints="ww";`, true, "ALTER TABLE `m` PARTITION `t` VOTER_CONSTRAINTS = 'ww'"}, - {`alter table m partition t learner_constraints="ww";`, true, "ALTER TABLE `m` PARTITION `t` LEARNER_CONSTRAINTS = 'ww'"}, + {`alter table m partition t primary_region="us";`, false, ""}, + {`alter table m partition t regions="us,3";`, false, ""}, + {`alter table m partition t followers=3;`, false, ""}, + {`alter table m partition t primary_region="us" followers=3;`, false, ""}, + {`alter table m partition t voters=3;`, false, ""}, + {`alter table m partition t learners=3;`, false, ""}, + {`alter table m partition t schedule="even";`, false, ""}, + {`alter table m partition t constraints="ww";`, false, ""}, + {`alter table m partition t leader_constraints="ww";`, false, ""}, + {`alter table m partition t follower_constraints="ww";`, false, ""}, + {`alter table m partition t voter_constraints="ww";`, false, ""}, + {`alter table m partition t learner_constraints="ww";`, false, ""}, {`alter table m partition t placement policy="ww";`, true, "ALTER TABLE `m` PARTITION `t` PLACEMENT POLICY = `ww`"}, - + {`alter table m partition t /*T![placement] placement policy="ww" */;`, true, "ALTER TABLE `m` PARTITION `t` PLACEMENT POLICY = `ww`"}, + // 7. add partition + {`alter table m add partition (partition p1 values less than (200) primary_region="us");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) regions="us,3");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) followers=3);`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) voters=3);`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) learners=3);`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) schedule="even");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) constraints="ww");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) leader_constraints="ww");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) follower_constraints="ww");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) voter_constraints="ww");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) learner_constraints="ww");`, false, ""}, + {`alter table m add partition (partition p1 values less than (200) placement policy="ww");`, true, "ALTER TABLE `m` ADD PARTITION (PARTITION `p1` VALUES LESS THAN (200) PLACEMENT POLICY = `ww`)"}, + {`alter table m add partition (partition p1 values less than (200) /*T![placement] placement policy="ww" */);`, true, "ALTER TABLE `m` ADD PARTITION (PARTITION `p1` VALUES LESS THAN (200) PLACEMENT POLICY = `ww`)"}, // for check clause {"create table t (c1 bool, c2 bool, check (c1 in (0, 1)) not enforced, check (c2 in (0, 1)))", true, "CREATE TABLE `t` (`c1` TINYINT(1),`c2` TINYINT(1),CHECK(`c1` IN (0,1)) NOT ENFORCED,CHECK(`c2` IN (0,1)) ENFORCED)"}, {"CREATE TABLE Customer (SD integer CHECK (SD > 0), First_Name varchar(30));", true, "CREATE TABLE `Customer` (`SD` INT CHECK(`SD`>0) ENFORCED,`First_Name` VARCHAR(30))"}, @@ -2618,8 +2749,10 @@ func TestDDL(t *testing.T) { {"create table t (a timestamp default now)", false, ""}, {"create table t (a timestamp default now())", true, "CREATE TABLE `t` (`a` TIMESTAMP DEFAULT CURRENT_TIMESTAMP())"}, + {"create table t (a timestamp default (((now()))))", true, "CREATE TABLE `t` (`a` TIMESTAMP DEFAULT CURRENT_TIMESTAMP())"}, {"create table t (a timestamp default now() on update now)", false, ""}, {"create table t (a timestamp default now() on update now())", true, "CREATE TABLE `t` (`a` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP())"}, + {"create table t (a timestamp default now() on update (now()))", false, ""}, {"CREATE TABLE t (c TEXT) default CHARACTER SET utf8, default COLLATE utf8_general_ci;", true, "CREATE TABLE `t` (`c` TEXT) DEFAULT CHARACTER SET = UTF8 DEFAULT COLLATE = UTF8_GENERAL_CI"}, {"CREATE TABLE t (c TEXT) shard_row_id_bits = 1;", true, "CREATE TABLE `t` (`c` TEXT) SHARD_ROW_ID_BITS = 1"}, {"CREATE TABLE t (c TEXT) shard_row_id_bits = 1, PRE_SPLIT_REGIONS = 1;", true, "CREATE TABLE `t` (`c` TEXT) SHARD_ROW_ID_BITS = 1 PRE_SPLIT_REGIONS = 1"}, @@ -2628,6 +2761,14 @@ func TestDDL(t *testing.T) { // For reference_definition in column_definition. {"CREATE TABLE followers ( f1 int NOT NULL REFERENCES user_profiles (uid) );", true, "CREATE TABLE `followers` (`f1` INT NOT NULL REFERENCES `user_profiles`(`uid`))"}, + // For column default expression + {"create table t (a int default rand())", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND())"}, + {"create table t (a int default rand(1))", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND(1))"}, + {"create table t (a int default (rand()))", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND())"}, + {"create table t (a int default (rand(1)))", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND(1))"}, + {"create table t (a int default (((rand()))))", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND())"}, + {"create table t (a int default (((rand(1)))))", true, "CREATE TABLE `t` (`a` INT DEFAULT RAND(1))"}, + // For table option `ENCRYPTION` {"create table t (a int) encryption = 'n';", true, "CREATE TABLE `t` (`a` INT) ENCRYPTION = 'n'"}, {"create table t (a int) encryption 'n';", true, "CREATE TABLE `t` (`a` INT) ENCRYPTION = 'n'"}, @@ -3212,6 +3353,12 @@ func TestDDL(t *testing.T) { {"ALTER TABLE t SET TIFLASH REPLICA 2 LOCATION LABELS 'a','b'", true, "ALTER TABLE `t` SET TIFLASH REPLICA 2 LOCATION LABELS 'a', 'b'"}, {"ALTER TABLE t SET TIFLASH REPLICA 0", true, "ALTER TABLE `t` SET TIFLASH REPLICA 0"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 2 LOCATION LABELS 'a','b'", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 2 LOCATION LABELS 'a', 'b'"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 0", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 0"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2 LOCATION LABELS 'a','b'", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2 LOCATION LABELS 'a', 'b'"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 1 SET TIFLASH REPLICA 2"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 1 LOCATION LABELS 'a','b' SET TIFLASH REPLICA 2", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 1 LOCATION LABELS 'a', 'b' SET TIFLASH REPLICA 2"}, + {"ALTER DATABASE t SET TIFLASH REPLICA 1 LOCATION LABELS 'a','b' SET TIFLASH REPLICA 2 LOCATION LABELS 'a', 'b'", true, "ALTER DATABASE `t` SET TIFLASH REPLICA 1 LOCATION LABELS 'a', 'b' SET TIFLASH REPLICA 2 LOCATION LABELS 'a', 'b'"}, // for issue 537 {"CREATE TABLE IF NOT EXISTS table_ident (a SQL_TSI_YEAR(4), b SQL_TSI_YEAR);", true, "CREATE TABLE IF NOT EXISTS `table_ident` (`a` YEAR(4),`b` YEAR)"}, @@ -3382,6 +3529,7 @@ func TestDDL(t *testing.T) { {"create placement policy x primary_region='us'", true, "CREATE PLACEMENT POLICY `x` PRIMARY_REGION = 'us'"}, {"create placement policy x region='us, 3'", false, ""}, {"create placement policy x followers=3", true, "CREATE PLACEMENT POLICY `x` FOLLOWERS = 3"}, + {"create placement policy x followers=0", false, ""}, {"create placement policy x voters=3", true, "CREATE PLACEMENT POLICY `x` VOTERS = 3"}, {"create placement policy x learners=3", true, "CREATE PLACEMENT POLICY `x` LEARNERS = 3"}, {"create placement policy x schedule='even'", true, "CREATE PLACEMENT POLICY `x` SCHEDULE = 'even'"}, @@ -3675,12 +3823,12 @@ func TestOptimizerHints(t *testing.T) { require.Equal(t, "t4", hints[1].Tables[1].TableName.L) // TEST BROADCAST_JOIN - stmt, _, err = p.Parse("select /*+ BROADCAST_JOIN(t1, T2), broadcast_join(t3, t4), BROADCAST_JOIN_LOCAL(t2) */ c1, c2 from t1, t2 where t1.c1 = t2.c1", "", "") + stmt, _, err = p.Parse("select /*+ BROADCAST_JOIN(t1, T2), broadcast_join(t3, t4) */ c1, c2 from t1, t2 where t1.c1 = t2.c1", "", "") require.NoError(t, err) selectStmt = stmt[0].(*ast.SelectStmt) hints = selectStmt.TableHints - require.Len(t, hints, 3) + require.Len(t, hints, 2) require.Equal(t, "broadcast_join", hints[0].HintName.L) require.Len(t, hints[0].Tables, 2) require.Equal(t, "t1", hints[0].Tables[0].TableName.L) @@ -3691,10 +3839,6 @@ func TestOptimizerHints(t *testing.T) { require.Equal(t, "t3", hints[1].Tables[0].TableName.L) require.Equal(t, "t4", hints[1].Tables[1].TableName.L) - require.Equal(t, "broadcast_join_local", hints[2].HintName.L) - require.Len(t, hints[2].Tables, 1) - require.Equal(t, "t2", hints[2].Tables[0].TableName.L) - // Test TIDB_INLJ stmt, _, err = p.Parse("select /*+ TIDB_INLJ(t1, T2), tidb_inlj(t3, t4) */ c1, c2 from t1, t2 where t1.c1 = t2.c1", "", "") require.NoError(t, err) @@ -4738,6 +4882,10 @@ func TestBinding(t *testing.T) { {"drop session binding for select * from t using select * from t use index(a)", true, "DROP SESSION BINDING FOR SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`)"}, {"show global bindings", true, "SHOW GLOBAL BINDINGS"}, {"show session bindings", true, "SHOW SESSION BINDINGS"}, + {"set binding enabled for select * from t", true, "SET BINDING ENABLED FOR SELECT * FROM `t`"}, + {"set binding enabled for select * from t using select * from t use index(a)", true, "SET BINDING ENABLED FOR SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`)"}, + {"set binding disabled for select * from t", true, "SET BINDING DISABLED FOR SELECT * FROM `t`"}, + {"set binding disabled for select * from t using select * from t use index(a)", true, "SET BINDING DISABLED FOR SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`)"}, {"create global binding for select * from t union all select * from t using select * from t use index(a) union all select * from t use index(a)", true, "CREATE GLOBAL BINDING FOR SELECT * FROM `t` UNION ALL SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`) UNION ALL SELECT * FROM `t` USE INDEX (`a`)"}, {"create session binding for select * from t union all select * from t using select * from t use index(a) union all select * from t use index(a)", true, "CREATE SESSION BINDING FOR SELECT * FROM `t` UNION ALL SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`) UNION ALL SELECT * FROM `t` USE INDEX (`a`)"}, {"drop global binding for select * from t union all select * from t using select * from t use index(a) union all select * from t use index(a)", true, "DROP GLOBAL BINDING FOR SELECT * FROM `t` UNION ALL SELECT * FROM `t` USING SELECT * FROM `t` USE INDEX (`a`) UNION ALL SELECT * FROM `t` USE INDEX (`a`)"}, @@ -5086,6 +5234,14 @@ func TestDDLStatements(t *testing.T) { createTableStr = `CREATE TABLE t (c_double double(10, 2))` _, _, err = p.Parse(createTableStr, "", "") require.NoError(t, err) + + createTableStr = `create global temporary table t010(local_01 int, local_03 varchar(20))` + _, _, err = p.Parse(createTableStr, "", "") + require.EqualError(t, err, "line 1 column 70 near \"\"GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together ") + + createTableStr = `create global temporary table t010(local_01 int, local_03 varchar(20)) on commit preserve rows` + _, _, err = p.Parse(createTableStr, "", "") + require.NoError(t, err) } func TestAnalyze(t *testing.T) { @@ -5867,7 +6023,7 @@ type nodeTextCleaner struct { // Enter implements Visitor interface. func (checker *nodeTextCleaner) Enter(in ast.Node) (out ast.Node, skipChildren bool) { - in.SetText("") + in.SetText(nil, "") in.SetOriginTextPosition(0) switch node := in.(type) { case *ast.CreateTableStmt: @@ -6407,18 +6563,30 @@ func TestGBKEncoding(t *testing.T) { require.Equal(t, "测试列", checker.colName) require.Equal(t, "GBK测试用例", checker.expr) - utf8SQL := "select '芢' from `玚`;" - sql, err = encoder.String(utf8SQL) - require.NoError(t, err) - stmt, _, err = p.ParseSQL(sql, gbkOpt) - require.NoError(t, err) - stmt, _, err = p.ParseSQL("select '\xc6\x5c' from `\xab\x60`;", gbkOpt) - require.NoError(t, err) - stmt, _, err = p.ParseSQL(`prepare p1 from "insert into t values ('中文');";`, gbkOpt) - require.NoError(t, err) - - stmt, _, err = p.ParseSQL("select _gbk '\xc6\x5c' from dual;") + _, _, err = p.ParseSQL("select _gbk '\xc6\x5c' from dual;") require.Error(t, err) + + for _, test := range []struct { + sql string + err bool + }{ + {"select '\xc6\x5c' from `\xab\x60`;", false}, + {`prepare p1 from "insert into t values ('中文');";`, false}, + {"select 'å•Š';", false}, + {"create table t1(s set('a一','b二','c三'));", false}, + {"insert into t3 values('一a');", false}, + {"select '\xa5\x5c'", false}, + {"select '''\xa5\x5c'", false}, + {"select ```\xa5\x5c`", false}, + {"select '\x65\x5c'", true}, + } { + _, _, err = p.ParseSQL(test.sql, gbkOpt) + if test.err { + require.Error(t, err, test.sql) + } else { + require.NoError(t, err, test.sql) + } + } } type gbkEncodingChecker struct { @@ -6461,20 +6629,9 @@ func TestInsertStatementMemoryAllocation(t *testing.T) { func TestCharsetIntroducer(t *testing.T) { p := parser.New() - // `_gbk` is treated as an identifier. - _, _, err := p.Parse("select _gbk 'a';", "", "") - require.NoError(t, err) - - charset.AddCharset(&charset.Charset{ - Name: "gbk", - DefaultCollation: "gbk_bin", - Collations: map[string]*charset.Collation{}, - Desc: "gbk", - Maxlen: 2, - }) defer charset.RemoveCharset("gbk") // `_gbk` is treated as a character set. - _, _, err = p.Parse("select _gbk 'a';", "", "") + _, _, err := p.Parse("select _gbk 'a';", "", "") require.EqualError(t, err, "[ddl:1115]Unsupported character introducer: 'gbk'") _, _, err = p.Parse("select _gbk 0x1234;", "", "") require.EqualError(t, err, "[ddl:1115]Unsupported character introducer: 'gbk'") diff --git a/parser/yy_parser.go b/parser/yy_parser.go index df3f416fad2e7..808b4a216ebeb 100644 --- a/parser/yy_parser.go +++ b/parser/yy_parser.go @@ -139,17 +139,16 @@ func (parser *Parser) SetParserConfig(config ParserConfig) { // ParseSQL parses a query string to raw ast.StmtNode. func (parser *Parser) ParseSQL(sql string, params ...ParseParam) (stmt []ast.StmtNode, warns []error, err error) { resetParams(parser) + parser.lexer.reset(sql) for _, p := range params { if err := p.ApplyOn(parser); err != nil { return nil, nil, err } } - sql = parser.lexer.tryDecodeToUTF8String(sql) parser.src = sql parser.result = parser.result[:0] var l yyLexer - parser.lexer.reset(sql) l = &parser.lexer yyParse(l, parser) @@ -218,8 +217,8 @@ func (parser *Parser) setLastSelectFieldText(st *ast.SelectStmt, lastEnd int) { return } lastField := st.Fields.Fields[len(st.Fields.Fields)-1] - if lastField.Offset+len(lastField.Text()) >= len(parser.src)-1 { - lastField.SetText(parser.src[lastField.Offset:lastEnd]) + if lastField.Offset+len(lastField.OriginalText()) >= len(parser.src)-1 { + lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd]) } } @@ -258,7 +257,7 @@ func toInt(l yyLexer, lval *yySymType, str string) int { return toDecimal(l, lval, str) } l.AppendError(l.Errorf("integer literal: %v", err)) - return int(unicode.ReplacementChar) + return invalid } switch { @@ -290,10 +289,10 @@ func toFloat(l yyLexer, lval *yySymType, str string) int { e := err.(*strconv.NumError) if e.Err == strconv.ErrRange { l.AppendError(types.ErrIllegalValueForType.GenWithStackByArgs("double", str)) - return int(unicode.ReplacementChar) + return invalid } l.AppendError(l.Errorf("float literal: %v", err)) - return int(unicode.ReplacementChar) + return invalid } lval.item = n @@ -305,7 +304,7 @@ func toHex(l yyLexer, lval *yySymType, str string) int { h, err := ast.NewHexLiteral(str) if err != nil { l.AppendError(l.Errorf("hex literal: %v", err)) - return int(unicode.ReplacementChar) + return invalid } lval.item = h return hexLit @@ -316,7 +315,7 @@ func toBit(l yyLexer, lval *yySymType, str string) int { b, err := ast.NewBitLiteral(str) if err != nil { l.AppendError(l.Errorf("bit literal: %v", err)) - return int(unicode.ReplacementChar) + return invalid } lval.item = b return bitLit @@ -396,7 +395,6 @@ var ( func resetParams(p *Parser) { p.charset = mysql.DefaultCharset p.collation = mysql.DefaultCollationName - p.lexer.encoding = charset.UTF8Encoding } // ParseParam represents the parameter of parsing. @@ -414,6 +412,7 @@ func (c CharsetConnection) ApplyOn(p *Parser) error { } else { p.charset = string(c) } + p.lexer.connection = charset.FindEncoding(string(c)) return nil } @@ -436,6 +435,6 @@ type CharsetClient string // ApplyOn implements ParseParam interface. func (c CharsetClient) ApplyOn(p *Parser) error { - p.lexer.encoding = charset.NewEncoding(string(c)) + p.lexer.client = charset.FindEncoding(string(c)) return nil } diff --git a/planner/cascades/implementation_rules.go b/planner/cascades/implementation_rules.go index b686d17d72469..7b30b67287202 100644 --- a/planner/cascades/implementation_rules.go +++ b/planner/cascades/implementation_rules.go @@ -242,12 +242,14 @@ func (r *ImplShow) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) func (r *ImplShow) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { logicProp := expr.Group.Prop show := expr.ExprNode.(*plannercore.LogicalShow) - // TODO(zz-jason): unifying LogicalShow and PhysicalShow to a single // struct. So that we don't need to create a new PhysicalShow object, which // can help us to reduce the gc pressure of golang runtime and improve the // overall performance. - showPhys := plannercore.PhysicalShow{ShowContents: show.ShowContents}.Init(show.SCtx()) + showPhys := plannercore.PhysicalShow{ + ShowContents: show.ShowContents, + Extractor: show.Extractor, + }.Init(show.SCtx()) showPhys.SetSchema(logicProp.Schema) return []memo.Implementation{impl.NewShowImpl(showPhys)}, nil } diff --git a/planner/cascades/main_test.go b/planner/cascades/main_test.go index 590e1825b08bd..ba181fa64df76 100644 --- a/planner/cascades/main_test.go +++ b/planner/cascades/main_test.go @@ -30,7 +30,7 @@ var stringerSuiteData testdata.TestData var transformationRulesSuiteData testdata.TestData func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() flag.Parse() @@ -47,7 +47,8 @@ func TestMain(m *testing.M) { testDataMap.GenerateOutputIfNeeded() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/planner/cascades/optimize.go b/planner/cascades/optimize.go index 0d1a0969d7568..c1d73f21f8c89 100644 --- a/planner/cascades/optimize.go +++ b/planner/cascades/optimize.go @@ -116,7 +116,7 @@ func (opt *Optimizer) FindBestPlan(sctx sessionctx.Context, logical plannercore. } func (opt *Optimizer) onPhasePreprocessing(sctx sessionctx.Context, plan plannercore.LogicalPlan) (plannercore.LogicalPlan, error) { - err := plan.PruneColumns(plan.Schema().Columns) + err := plan.PruneColumns(plan.Schema().Columns, nil) if err != nil { return nil, err } diff --git a/planner/cascades/testdata/integration_suite_out.json b/planner/cascades/testdata/integration_suite_out.json index 3b2719c02d293..21b601bfc9198 100644 --- a/planner/cascades/testdata/integration_suite_out.json +++ b/planner/cascades/testdata/integration_suite_out.json @@ -197,7 +197,7 @@ " └─Sort_29 6400.00 root test.t.b", " └─Selection_28 6400.00 root gt(Column#4, 1)", " └─HashAgg_19 8000.00 root group by:test.t.b, funcs:avg(Column#11)->Column#3, funcs:sum(Column#12)->Column#4, funcs:firstrow(test.t.b)->test.t.b", - " └─Projection_20 10000.00 root cast(test.t.a, decimal(15,4) BINARY)->Column#11, cast(test.t.a, decimal(32,0) BINARY)->Column#12, test.t.b, test.t.b", + " └─Projection_20 10000.00 root cast(test.t.a, decimal(15,4) BINARY)->Column#11, cast(test.t.a, decimal(10,0) BINARY)->Column#12, test.t.b, test.t.b", " └─TableReader_21 10000.00 root data:TableFullScan_22", " └─TableFullScan_22 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], @@ -636,7 +636,7 @@ "Plan": [ "Projection_8 8000.00 root Column#5, test.t.c, Column#5, Column#6, Column#7, Column#8, Column#9", "└─HashAgg_9 8000.00 root group by:test.t.c, funcs:avg(Column#10)->Column#5, funcs:count(distinct test.t.a, test.t.b)->Column#6, funcs:count(distinct test.t.a)->Column#7, funcs:count(distinct test.t.c)->Column#8, funcs:sum(Column#11)->Column#9, funcs:firstrow(test.t.c)->test.t.c", - " └─Projection_10 10000.00 root cast(test.t.b, decimal(15,4) BINARY)->Column#10, test.t.a, test.t.b, test.t.a, test.t.c, cast(test.t.b, decimal(32,0) BINARY)->Column#11, test.t.c, test.t.c", + " └─Projection_10 10000.00 root cast(test.t.b, decimal(15,4) BINARY)->Column#10, test.t.a, test.t.b, test.t.a, test.t.c, cast(test.t.b, decimal(10,0) BINARY)->Column#11, test.t.c, test.t.c", " └─TableReader_11 10000.00 root data:TableFullScan_12", " └─TableFullScan_12 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], diff --git a/planner/cascades/testdata/transformation_rules_suite_out.json b/planner/cascades/testdata/transformation_rules_suite_out.json index 185e2441edd11..13a9b993d5da2 100644 --- a/planner/cascades/testdata/transformation_rules_suite_out.json +++ b/planner/cascades/testdata/transformation_rules_suite_out.json @@ -353,10 +353,14 @@ " Projection_3 input:[Group#1], test.t.b, Column#13", "Group#1 Schema:[Column#13,test.t.b]", " Aggregation_2 input:[Group#2], group by:plus(sin(cast(test.t.b, double BINARY)), sin(cast(test.t.c, double BINARY))), test.t.b, funcs:sum(test.t.a), firstrow(test.t.b)", + " Aggregation_7 input:[Group#3], group by:Column#14, test.t.b, funcs:sum(Column#15), firstrow(test.t.b)", "Group#2 Schema:[test.t.a,test.t.b,test.t.c], UniqueKey:[test.t.a]", - " TiKVSingleGather_5 input:[Group#3], table:t", - "Group#3 Schema:[test.t.a,test.t.b,test.t.c], UniqueKey:[test.t.a]", - " TableScan_4 table:t, pk col:test.t.a" + " TiKVSingleGather_5 input:[Group#4], table:t", + "Group#4 Schema:[test.t.a,test.t.b,test.t.c], UniqueKey:[test.t.a]", + " TableScan_4 table:t, pk col:test.t.a", "Group#3 Schema:[Column#15,Column#14,test.t.b]", + " TiKVSingleGather_5 input:[Group#5], table:t", + "Group#5 Schema:[Column#15,Column#14,test.t.b]", + " Aggregation_6 input:[Group#4], group by:plus(sin(cast(test.t.b, double BINARY)), sin(cast(test.t.c, double BINARY))), test.t.b, funcs:sum(test.t.a)" ] } ] diff --git a/planner/cascades/transformation_rules.go b/planner/cascades/transformation_rules.go index 6a0d12eb977c0..18f2e00d73c94 100644 --- a/planner/cascades/transformation_rules.go +++ b/planner/cascades/transformation_rules.go @@ -310,8 +310,8 @@ type PushSelDownTiKVSingleGather struct { // NewRulePushSelDownTiKVSingleGather creates a new Transformation PushSelDownTiKVSingleGather. // The pattern of this rule is `Selection -> TiKVSingleGather -> Any`. func NewRulePushSelDownTiKVSingleGather() Transformation { - any := memo.NewPattern(memo.OperandAny, memo.EngineTiKVOrTiFlash) - tg := memo.BuildPattern(memo.OperandTiKVSingleGather, memo.EngineTiDBOnly, any) + any1 := memo.NewPattern(memo.OperandAny, memo.EngineTiKVOrTiFlash) + tg := memo.BuildPattern(memo.OperandTiKVSingleGather, memo.EngineTiDBOnly, any1) p := memo.BuildPattern(memo.OperandSelection, memo.EngineTiDBOnly, tg) rule := &PushSelDownTiKVSingleGather{} @@ -442,7 +442,7 @@ func (r *PushAggDownGather) OnTransform(old *memo.ExprIter) (newExprs []*memo.Gr gbyItems := make([]expression.Expression, len(agg.GroupByItems)) copy(gbyItems, agg.GroupByItems) - partialPref, finalPref, funcMap := plannercore.BuildFinalModeAggregation(agg.SCtx(), + partialPref, finalPref, firstRowFuncMap := plannercore.BuildFinalModeAggregation(agg.SCtx(), &plannercore.AggInfo{ AggFuncs: aggFuncs, GroupByItems: gbyItems, @@ -453,7 +453,7 @@ func (r *PushAggDownGather) OnTransform(old *memo.ExprIter) (newExprs []*memo.Gr } // Remove unnecessary FirstRow. partialPref.AggFuncs = - plannercore.RemoveUnnecessaryFirstRow(agg.SCtx(), finalPref.AggFuncs, finalPref.GroupByItems, partialPref.AggFuncs, partialPref.GroupByItems, partialPref.Schema, funcMap) + plannercore.RemoveUnnecessaryFirstRow(agg.SCtx(), finalPref.GroupByItems, partialPref.AggFuncs, partialPref.GroupByItems, partialPref.Schema, firstRowFuncMap) partialAgg := plannercore.LogicalAggregation{ AggFuncs: partialPref.AggFuncs, diff --git a/planner/core/cache.go b/planner/core/cache.go index a386c4a5a3649..461258d924d8e 100644 --- a/planner/core/cache.go +++ b/planner/core/cache.go @@ -19,6 +19,7 @@ import ( "sync/atomic" "time" + "github.com/pingcap/errors" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" @@ -65,22 +66,25 @@ func PreparedPlanCacheEnabled() bool { return isEnabled == preparedPlanCacheEnabled } -type pstmtPlanCacheKey struct { +// planCacheKey is used to access Plan Cache. We put some variables that do not affect the plan into planCacheKey, such as the sql text. +// Put the parameters that may affect the plan in planCacheValue, such as bindSQL. +// However, due to some compatibility reasons, we will temporarily keep some system variable-related values in planCacheKey. +// At the same time, because these variables have a small impact on plan, we will move them to PlanCacheValue later if necessary. +type planCacheKey struct { database string connID uint64 - pstmtID uint32 + stmtText string schemaVersion int64 sqlMode mysql.SQLMode timezoneOffset int isolationReadEngines map[kv.StoreType]struct{} selectLimit uint64 - bindSQL string hash []byte } // Hash implements Key interface. -func (key *pstmtPlanCacheKey) Hash() []byte { +func (key *planCacheKey) Hash() []byte { if len(key.hash) == 0 { var ( dbBytes = hack.Slice(key.database) @@ -91,7 +95,7 @@ func (key *pstmtPlanCacheKey) Hash() []byte { } key.hash = append(key.hash, dbBytes...) key.hash = codec.EncodeInt(key.hash, int64(key.connID)) - key.hash = codec.EncodeInt(key.hash, int64(key.pstmtID)) + key.hash = append(key.hash, hack.Slice(key.stmtText)...) key.hash = codec.EncodeInt(key.hash, key.schemaVersion) key.hash = codec.EncodeInt(key.hash, int64(key.sqlMode)) key.hash = codec.EncodeInt(key.hash, int64(key.timezoneOffset)) @@ -105,19 +109,18 @@ func (key *pstmtPlanCacheKey) Hash() []byte { key.hash = append(key.hash, kv.TiFlash.Name()...) } key.hash = codec.EncodeInt(key.hash, int64(key.selectLimit)) - key.hash = append(key.hash, hack.Slice(key.bindSQL)...) } return key.hash } // SetPstmtIDSchemaVersion implements PstmtCacheKeyMutator interface to change pstmtID and schemaVersion of cacheKey. // so we can reuse Key instead of new every time. -func SetPstmtIDSchemaVersion(key kvcache.Key, pstmtID uint32, schemaVersion int64, isolationReadEngines map[kv.StoreType]struct{}) { - psStmtKey, isPsStmtKey := key.(*pstmtPlanCacheKey) +func SetPstmtIDSchemaVersion(key kvcache.Key, stmtText string, schemaVersion int64, isolationReadEngines map[kv.StoreType]struct{}) { + psStmtKey, isPsStmtKey := key.(*planCacheKey) if !isPsStmtKey { return } - psStmtKey.pstmtID = pstmtID + psStmtKey.stmtText = stmtText psStmtKey.schemaVersion = schemaVersion psStmtKey.isolationReadEngines = make(map[kv.StoreType]struct{}) for k, v := range isolationReadEngines { @@ -126,35 +129,41 @@ func SetPstmtIDSchemaVersion(key kvcache.Key, pstmtID uint32, schemaVersion int6 psStmtKey.hash = psStmtKey.hash[:0] } -// NewPSTMTPlanCacheKey creates a new pstmtPlanCacheKey object. -func NewPSTMTPlanCacheKey(sessionVars *variable.SessionVars, pstmtID uint32, schemaVersion int64, bindSQL string) kvcache.Key { +// NewPlanCacheKey creates a new planCacheKey object. +func NewPlanCacheKey(sessionVars *variable.SessionVars, stmtText, stmtDB string, schemaVersion int64) (kvcache.Key, error) { + if stmtText == "" { + return nil, errors.New("no statement text") + } + if stmtDB == "" { + stmtDB = sessionVars.CurrentDB + } timezoneOffset := 0 if sessionVars.TimeZone != nil { _, timezoneOffset = time.Now().In(sessionVars.TimeZone).Zone() } - key := &pstmtPlanCacheKey{ - database: sessionVars.CurrentDB, + key := &planCacheKey{ + database: stmtDB, connID: sessionVars.ConnectionID, - pstmtID: pstmtID, + stmtText: stmtText, schemaVersion: schemaVersion, sqlMode: sessionVars.SQLMode, timezoneOffset: timezoneOffset, isolationReadEngines: make(map[kv.StoreType]struct{}), selectLimit: sessionVars.SelectLimit, - bindSQL: bindSQL, } for k, v := range sessionVars.IsolationReadEngines { key.isolationReadEngines[k] = v } - return key + return key, nil } // FieldSlice is the slice of the types.FieldType type FieldSlice []types.FieldType -// Equal compares FieldSlice with []*types.FieldType -// Currently this is only used in plan cache to invalidate cache when types of variables are different. -func (s FieldSlice) Equal(tps []*types.FieldType) bool { +// CheckTypesCompatibility4PC compares FieldSlice with []*types.FieldType +// Currently this is only used in plan cache to check whether the types of parameters are compatible. +// If the types of parameters are compatible, we can use the cached plan. +func (s FieldSlice) CheckTypesCompatibility4PC(tps []*types.FieldType) bool { if len(s) != len(tps) { return false } @@ -170,20 +179,27 @@ func (s FieldSlice) Equal(tps []*types.FieldType) bool { (s[i].EvalType() == types.ETInt && mysql.HasUnsignedFlag(s[i].Flag) != mysql.HasUnsignedFlag(tps[i].Flag)) { return false } + // When the type is decimal, we should compare the Flen and Decimal. + // We can only use the plan when both Flen and Decimal should less equal than the cached one. + // We assume here that there is no correctness problem when the precision of the parameters is less than the precision of the parameters in the cache. + if tpEqual && s[i].Tp == mysql.TypeNewDecimal && !(s[i].Flen >= tps[i].Flen && s[i].Decimal >= tps[i].Decimal) { + return false + } } return true } -// PSTMTPlanCacheValue stores the cached Statement and StmtNode. -type PSTMTPlanCacheValue struct { +// PlanCacheValue stores the cached Statement and StmtNode. +type PlanCacheValue struct { Plan Plan OutPutNames []*types.FieldName TblInfo2UnionScan map[*model.TableInfo]bool UserVarTypes FieldSlice + BindSQL string } -// NewPSTMTPlanCacheValue creates a SQLCacheValue. -func NewPSTMTPlanCacheValue(plan Plan, names []*types.FieldName, srcMap map[*model.TableInfo]bool, userVarTps []*types.FieldType) *PSTMTPlanCacheValue { +// NewPlanCacheValue creates a SQLCacheValue. +func NewPlanCacheValue(plan Plan, names []*types.FieldName, srcMap map[*model.TableInfo]bool, userVarTps []*types.FieldType, bindSQL string) *PlanCacheValue { dstMap := make(map[*model.TableInfo]bool) for k, v := range srcMap { dstMap[k] = v @@ -192,19 +208,20 @@ func NewPSTMTPlanCacheValue(plan Plan, names []*types.FieldName, srcMap map[*mod for i, tp := range userVarTps { userVarTypes[i] = *tp } - return &PSTMTPlanCacheValue{ + return &PlanCacheValue{ Plan: plan, OutPutNames: names, TblInfo2UnionScan: dstMap, UserVarTypes: userVarTypes, + BindSQL: bindSQL, } } // CachedPrepareStmt store prepared ast from PrepareExec and other related fields type CachedPrepareStmt struct { PreparedAst *ast.Prepared + StmtDB string // which DB the statement will be processed over VisitInfos []visitInfo - ColumnInfos interface{} Executor interface{} NormalizedSQL string NormalizedPlan string @@ -212,4 +229,32 @@ type CachedPrepareStmt struct { PlanDigest *parser.Digest ForUpdateRead bool SnapshotTSEvaluator func(sessionctx.Context) (uint64, error) + NormalizedSQL4PC string + SQLDigest4PC string + + // the different between NormalizedSQL, NormalizedSQL4PC and StmtText: + // for the query `select * from t where a>1 and b ? and `b` < ? --> constants are normalized to '?', + // NormalizedSQL4PC: select * from `test` . `t` where `a` > ? and `b` < ? --> schema name is added, + // StmtText: select * from t where a>1 and b just format the original query; + StmtText string +} + +// GetPreparedStmt extract the prepared statement from the execute statement. +func GetPreparedStmt(stmt *ast.ExecuteStmt, vars *variable.SessionVars) (*CachedPrepareStmt, error) { + var ok bool + execID := stmt.ExecID + if stmt.Name != "" { + if execID, ok = vars.PreparedStmtNameToID[stmt.Name]; !ok { + return nil, ErrStmtNotFound + } + } + if preparedPointer, ok := vars.PreparedStmts[execID]; ok { + preparedObj, ok := preparedPointer.(*CachedPrepareStmt) + if !ok { + return nil, errors.Errorf("invalid CachedPrepareStmt type") + } + return preparedObj, nil + } + return nil, ErrStmtNotFound } diff --git a/planner/core/cache_test.go b/planner/core/cache_test.go index 074d1e4cf2828..8cb4a406dada7 100644 --- a/planner/core/cache_test.go +++ b/planner/core/cache_test.go @@ -28,6 +28,17 @@ func TestCacheKey(t *testing.T) { ctx.GetSessionVars().SQLMode = mysql.ModeNone ctx.GetSessionVars().TimeZone = time.UTC ctx.GetSessionVars().ConnectionID = 0 - key := NewPSTMTPlanCacheKey(ctx.GetSessionVars(), 1, 1, "") - require.Equal(t, []byte{0x74, 0x65, 0x73, 0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x74, 0x69, 0x64, 0x62, 0x74, 0x69, 0x6b, 0x76, 0x74, 0x69, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, key.Hash()) + key, err := NewPlanCacheKey(ctx.GetSessionVars(), "", "test", 1) + if err.Error() != "no statement text" { + t.Fail() // no statement text + } + key, err = NewPlanCacheKey(ctx.GetSessionVars(), "select 1", "", 1) + if err != nil { + t.Fail() // schema can be nil + } + key, err = NewPlanCacheKey(ctx.GetSessionVars(), "select 1", "test", 1) + if err != nil { + t.Fail() + } + require.Equal(t, []byte{0x74, 0x65, 0x73, 0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x74, 0x69, 0x64, 0x62, 0x74, 0x69, 0x6b, 0x76, 0x74, 0x69, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, key.Hash()) } diff --git a/planner/core/cacheable_checker.go b/planner/core/cacheable_checker.go index ace4e45a3e074..3caec678692fb 100644 --- a/planner/core/cacheable_checker.go +++ b/planner/core/cacheable_checker.go @@ -129,9 +129,13 @@ func (checker *cacheableChecker) Enter(in ast.Node) (out ast.Node, skipChildren case *ast.TableName: if checker.schema != nil { if checker.isPartitionTable(node) { - if checker.sctx != nil && checker.sctx.GetSessionVars().UseDynamicPartitionPrune() { - return in, false // dynamic-mode for partition tables can use plan-cache - } + // Temporary disable prepared plan cache until https://github.com/pingcap/tidb/issues/33031 + // is fixed and additional tests with dynamic partition prune mode has been added. + /* + if checker.sctx != nil && checker.sctx.GetSessionVars().UseDynamicPartitionPrune() { + return in, false // dynamic-mode for partition tables can use plan-cache + } + */ checker.cacheable = false return in, true } diff --git a/planner/core/cbo_test.go b/planner/core/cbo_test.go index 603dfd030611a..a0aa419b95b86 100644 --- a/planner/core/cbo_test.go +++ b/planner/core/cbo_test.go @@ -23,43 +23,21 @@ import ( "strings" "testing" - . "github.com/pingcap/check" - "github.com/pingcap/errors" - "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/planner" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/statistics/handle" - "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testAnalyzeSuite{}) - -type testAnalyzeSuite struct { - testData testutil.TestData -} - -func (s *testAnalyzeSuite) SetUpSuite(c *C) { - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "analyze_suite") - c.Assert(err, IsNil) -} - -func (s *testAnalyzeSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testAnalyzeSuite) loadTableStats(fileName string, dom *domain.Domain) error { +func loadTableStats(fileName string, dom *domain.Domain) error { statsPath := filepath.Join("testdata", fileName) bytes, err := os.ReadFile(statsPath) if err != nil { @@ -78,15 +56,10 @@ func (s *testAnalyzeSuite) loadTableStats(fileName string, dom *domain.Domain) e return nil } -func (s *testAnalyzeSuite) TestExplainAnalyze(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestExplainAnalyze(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only full group by tk.MustExec("create table t1(a int, b int, c int, key idx(a, b))") @@ -95,151 +68,134 @@ func (s *testAnalyzeSuite) TestExplainAnalyze(c *C) { tk.MustExec("insert into t2 values (2, 22), (3, 33), (5, 55), (233, 2), (333, 3), (3434, 5)") tk.MustExec("analyze table t1, t2") rs := tk.MustQuery("explain analyze select t1.a, t1.b, sum(t1.c) from t1 join t2 on t1.a = t2.b where t1.a > 1") - c.Assert(len(rs.Rows()), Equals, 10) + require.Len(t, rs.Rows(), 10) for _, row := range rs.Rows() { - c.Assert(len(row), Equals, 9) + require.Len(t, row, 9) execInfo := row[5].(string) - c.Assert(strings.Contains(execInfo, "time"), Equals, true) - c.Assert(strings.Contains(execInfo, "loops"), Equals, true) + require.Contains(t, execInfo, "time") + require.Contains(t, execInfo, "loops") if strings.Contains(row[0].(string), "Reader") || strings.Contains(row[0].(string), "IndexLookUp") { - c.Assert(strings.Contains(execInfo, "cop_task"), Equals, true) + require.Contains(t, execInfo, "cop_task") } } } // TestCBOWithoutAnalyze tests the plan with stats that only have count info. -func (s *testAnalyzeSuite) TestCBOWithoutAnalyze(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestCBOWithoutAnalyze(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t1 (a int)") testKit.MustExec("create table t2 (a int)") h := dom.StatsHandle() - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) testKit.MustExec("insert into t1 values (1), (2), (3), (4), (5), (6)") testKit.MustExec("insert into t2 values (1), (2), (3), (4), (5), (6)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(dom.InfoSchema()), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(dom.InfoSchema())) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, sql := range input { plan := testKit.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestStraightJoin(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestStraightJoin(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") h := dom.StatsHandle() for _, tblName := range []string{"t1", "t2", "t3", "t4"} { testKit.MustExec(fmt.Sprintf("create table %s (a int)", tblName)) - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) } var input []string var output [][]string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { - output[i] = s.testData.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) + testdata.OnRecord(func() { + output[i] = testdata.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) }) testKit.MustQuery(tt).Check(testkit.Rows(output[i]...)) } } -func (s *testAnalyzeSuite) TestTableDual(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() +func TestTableDual(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() - testKit := testkit.NewTestKit(c, store) + testKit := testkit.NewTestKit(t, store) testKit.MustExec(`use test`) h := dom.StatsHandle() testKit.MustExec(`create table t(a int)`) testKit.MustExec("insert into t values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)") - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(dom.InfoSchema()), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(dom.InfoSchema())) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, sql := range input { plan := testKit.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestEstimation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - statistics.RatioOfPseudoEstimate.Store(0.7) - }() +func TestEstimation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) statistics.RatioOfPseudoEstimate.Store(10.0) + defer statistics.RatioOfPseudoEstimate.Store(0.7) testKit.MustExec("use test") testKit.MustExec("create table t (a int)") testKit.MustExec("insert into t values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)") testKit.MustExec("insert into t select * from t") testKit.MustExec("insert into t select * from t") h := dom.StatsHandle() - err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") for i := 1; i <= 8; i++ { testKit.MustExec("delete from t where a = ?", i) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(dom.InfoSchema()), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(dom.InfoSchema())) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, sql := range input { plan := testKit.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) } @@ -256,15 +212,10 @@ func constructInsertSQL(i, n int) string { return sql } -func (s *testAnalyzeSuite) TestIndexRead(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIndexRead(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("set @@session.tidb_executor_concurrency = 4;") testKit.MustExec("set @@session.tidb_hash_join_concurrency = 5;") testKit.MustExec("set @@session.tidb_distsql_scan_concurrency = 15;") @@ -281,78 +232,69 @@ func (s *testAnalyzeSuite) TestIndexRead(c *C) { // This stats is generated by following format: // fill (a, b, c, e) as (i*100+j, i, i+j, i*100+j), i and j is dependent and range of this two are [0, 99]. - err = s.loadTableStats("analyzesSuiteTestIndexReadT.json", dom) - c.Assert(err, IsNil) + require.NoError(t, loadTableStats("analyzesSuiteTestIndexReadT.json", dom)) for i := 1; i < 16; i++ { testKit.MustExec(fmt.Sprintf("insert into t1 values(%v, %v)", i, i)) } testKit.MustExec("analyze table t1") - ctx := testKit.Se.(sessionctx.Context) + ctx := testKit.Session() var input, output []string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { stmts, err := session.Parse(ctx, tt) - c.Assert(err, IsNil) - c.Assert(stmts, HasLen, 1) + require.NoError(t, err) + require.Len(t, stmts, 1) stmt := stmts[0] ret := &core.PreprocessorReturn{} err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) + require.NoError(t, err) planString := core.ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], Commentf("for %s", tt)) + require.Equalf(t, output[i], planString, "case: %v", tt) } } -func (s *testAnalyzeSuite) TestEmptyTable(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestEmptyTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t, t1") testKit.MustExec("create table t (c1 int)") testKit.MustExec("create table t1 (c1 int)") testKit.MustExec("analyze table t, t1") var input, output []string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - ctx := testKit.Se.(sessionctx.Context) + ctx := testKit.Session() stmts, err := session.Parse(ctx, tt) - c.Assert(err, IsNil) - c.Assert(stmts, HasLen, 1) + require.NoError(t, err) + require.Len(t, stmts, 1) stmt := stmts[0] ret := &core.PreprocessorReturn{} err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) + require.NoError(t, err) planString := core.ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], Commentf("for %s", tt)) + require.Equalf(t, output[i], planString, "case: %v", tt) } } -func (s *testAnalyzeSuite) TestAnalyze(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestAnalyze(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t, t1, t2, t3") testKit.MustExec("create table t (a int, b int)") @@ -383,63 +325,58 @@ func (s *testAnalyzeSuite) TestAnalyze(c *C) { testKit.MustExec("analyze table t4") testKit.MustExec("create view v as select * from t") - _, err = testKit.Exec("analyze table v") - c.Assert(err.Error(), Equals, "analyze view v is not supported now.") + _, err := testKit.Exec("analyze table v") + require.EqualError(t, err, "analyze view v is not supported now") testKit.MustExec("drop view v") testKit.MustExec("create sequence seq") _, err = testKit.Exec("analyze table seq") - c.Assert(err.Error(), Equals, "analyze sequence seq is not supported now.") + require.EqualError(t, err, "analyze sequence seq is not supported now") testKit.MustExec("drop sequence seq") var input, output []string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - ctx := testKit.Se.(sessionctx.Context) + ctx := testKit.Session() stmts, err := session.Parse(ctx, tt) - c.Assert(err, IsNil) - c.Assert(stmts, HasLen, 1) + require.NoError(t, err) + require.Len(t, stmts, 1) stmt := stmts[0] err = executor.ResetContextOfStmt(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) ret := &core.PreprocessorReturn{} err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) + require.NoError(t, err) planString := core.ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], Commentf("for %s", tt)) + require.Equalf(t, output[i], planString, "case: %v", tt) } } -func (s *testAnalyzeSuite) TestOutdatedAnalyze(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestOutdatedAnalyze(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int, index idx(a))") for i := 0; i < 10; i++ { testKit.MustExec(fmt.Sprintf("insert into t values (%d,%d)", i, i)) } h := dom.StatsHandle() - err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") testKit.MustExec("insert into t select * from t") testKit.MustExec("insert into t select * from t") testKit.MustExec("insert into t select * from t") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(dom.InfoSchema()), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(dom.InfoSchema())) var input []struct { SQL string EnablePseudoForOutdatedStats bool @@ -451,70 +388,26 @@ func (s *testAnalyzeSuite) TestOutdatedAnalyze(c *C) { RatioOfPseudoEstimate float64 Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - testKit.Se.GetSessionVars().SetEnablePseudoForOutdatedStats(tt.EnablePseudoForOutdatedStats) + testKit.Session().GetSessionVars().SetEnablePseudoForOutdatedStats(tt.EnablePseudoForOutdatedStats) statistics.RatioOfPseudoEstimate.Store(tt.RatioOfPseudoEstimate) plan := testKit.MustQuery(tt.SQL) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt.SQL output[i].EnablePseudoForOutdatedStats = tt.EnablePseudoForOutdatedStats output[i].RatioOfPseudoEstimate = tt.RatioOfPseudoEstimate - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestPreparedNullParam(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - - defer config.RestoreFunc()() - flags := []bool{false, true} - for _, flag := range flags { - config.UpdateGlobal(func(conf *config.Config) { - conf.PreparedPlanCache.Enabled = flag - conf.PreparedPlanCache.Capacity = 100 - }) - testKit := testkit.NewTestKit(c, store) - testKit.MustExec("use test") - testKit.MustExec("drop table if exists t") - testKit.MustExec("create table t (id int not null, KEY id (id))") - testKit.MustExec("insert into t values (1), (2), (3)") - - sql := "select * from t where id = ?" - best := "Dual" - - ctx := testKit.Se.(sessionctx.Context) - stmts, err := session.Parse(ctx, sql) - c.Assert(err, IsNil) - stmt := stmts[0] - - ret := &core.PreprocessorReturn{} - err = core.Preprocess(ctx, stmt, core.InPrepare, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) - - c.Assert(core.ToString(p), Equals, best, Commentf("for %s", sql)) - } -} - -func (s *testAnalyzeSuite) TestNullCount(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestNullCount(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t") testKit.MustExec("create table t (a int, b int, index idx(a))") @@ -522,33 +415,29 @@ func (s *testAnalyzeSuite) TestNullCount(c *C) { testKit.MustExec("analyze table t") var input []string var output [][]string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i := 0; i < 2; i++ { - s.testData.OnRecord(func() { - output[i] = s.testData.ConvertRowsToStrings(testKit.MustQuery(input[i]).Rows()) + testdata.OnRecord(func() { + output[i] = testdata.ConvertRowsToStrings(testKit.MustQuery(input[i]).Rows()) }) testKit.MustQuery(input[i]).Check(testkit.Rows(output[i]...)) } h := dom.StatsHandle() h.Clear() - c.Assert(h.Update(dom.InfoSchema()), IsNil) + require.NoError(t, h.Update(dom.InfoSchema())) for i := 2; i < 4; i++ { - s.testData.OnRecord(func() { - output[i] = s.testData.ConvertRowsToStrings(testKit.MustQuery(input[i]).Rows()) + testdata.OnRecord(func() { + output[i] = testdata.ConvertRowsToStrings(testKit.MustQuery(input[i]).Rows()) }) testKit.MustQuery(input[i]).Check(testkit.Rows(output[i]...)) } } -func (s *testAnalyzeSuite) TestCorrelatedEstimation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestCorrelatedEstimation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only full group by tk.MustExec("create table t(a int, b int, c int, index idx(c,b,a))") @@ -558,25 +447,21 @@ func (s *testAnalyzeSuite) TestCorrelatedEstimation(c *C) { input []string output [][]string ) - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { rs := tk.MustQuery(tt) - s.testData.OnRecord(func() { - output[i] = s.testData.ConvertRowsToStrings(rs.Rows()) + testdata.OnRecord(func() { + output[i] = testdata.ConvertRowsToStrings(rs.Rows()) }) rs.Check(testkit.Rows(output[i]...)) } } -func (s *testAnalyzeSuite) TestInconsistentEstimation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestInconsistentEstimation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int, b int, c int, index ab(a,b), index ac(a,c))") tk.MustExec("insert into t values (1,1,1), (1000,1000,1000)") @@ -588,52 +473,29 @@ func (s *testAnalyzeSuite) TestInconsistentEstimation(c *C) { // Force using the histogram to estimate. tk.MustExec("update mysql.stats_histograms set stats_ver = 0") dom.StatsHandle().Clear() - err = dom.StatsHandle().Update(dom.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, sql := range input { plan := tk.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) } } -func newStoreWithBootstrap() (kv.Storage, *domain.Domain, error) { - store, err := mockstore.NewMockStore() - if err != nil { - return nil, nil, errors.Trace(err) - } - - session.SetSchemaLease(0) - session.DisableStats4Test() - - dom, err := session.BootstrapSession(store) - if err != nil { - return nil, nil, err - } - - dom.SetStatsUpdating(true) - return store, dom, errors.Trace(err) -} - func BenchmarkOptimize(b *testing.B) { - c := &C{} - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() + store, clean := testkit.CreateMockStore(b) + defer clean() - testKit := testkit.NewTestKit(c, store) + testKit := testkit.NewTestKit(b, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t") testKit.MustExec("create table t (a int primary key, b int, c varchar(200), d datetime DEFAULT CURRENT_TIMESTAMP, e int, ts timestamp DEFAULT CURRENT_TIMESTAMP)") @@ -727,35 +589,30 @@ func BenchmarkOptimize(b *testing.B) { }, } for _, tt := range tests { - ctx := testKit.Se.(sessionctx.Context) + ctx := testKit.Session() stmts, err := session.Parse(ctx, tt.sql) - c.Assert(err, IsNil) - c.Assert(stmts, HasLen, 1) + require.NoError(b, err) + require.Len(b, stmts, 1) stmt := stmts[0] ret := &core.PreprocessorReturn{} err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) + require.NoError(b, err) b.Run(tt.sql, func(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) + require.NoError(b, err) } b.ReportAllocs() }) } } -func (s *testAnalyzeSuite) TestIssue9562(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIssue9562(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") var input [][]string @@ -763,16 +620,17 @@ func (s *testAnalyzeSuite) TestIssue9562(c *C) { SQL []string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { for j, tt := range ts { if j != len(ts)-1 { tk.MustExec(tt) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts if j == len(ts)-1 { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) } }) if j == len(ts)-1 { @@ -782,15 +640,10 @@ func (s *testAnalyzeSuite) TestIssue9562(c *C) { } } -func (s *testAnalyzeSuite) TestIssue9805(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIssue9805(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec(` @@ -816,15 +669,10 @@ func (s *testAnalyzeSuite) TestIssue9805(c *C) { tk.MustQuery("explain analyze select /*+ TIDB_INLJ(t2) */ t1.id, t2.a from t1 join t2 on t1.a = t2.d where t1.b = 't2' and t1.d = 4") } -func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestLimitCrossEstimation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_executor_concurrency = 4;") tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;") @@ -837,16 +685,17 @@ func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) { SQL []string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { for j, tt := range ts { if j != len(ts)-1 { tk.MustExec(tt) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts if j == len(ts)-1 { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) } }) if j == len(ts)-1 { @@ -856,21 +705,15 @@ func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) { } } -func (s *testAnalyzeSuite) TestLowSelIndexGreedySearch(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestLowSelIndexGreedySearch(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec(`set tidb_opt_limit_push_down_threshold=0`) testKit.MustExec("drop table if exists t") testKit.MustExec("create table t (a varchar(32) default null, b varchar(10) default null, c varchar(12) default null, d varchar(32) default null, e bigint(10) default null, key idx1 (d,a), key idx2 (a,c), key idx3 (c,b), key idx4 (e))") - err = s.loadTableStats("analyzeSuiteTestLowSelIndexGreedySearchT.json", dom) - c.Assert(err, IsNil) + require.NoError(t, loadTableStats("analyzeSuiteTestLowSelIndexGreedySearchT.json", dom)) var input []string var output []struct { SQL string @@ -879,59 +722,52 @@ func (s *testAnalyzeSuite) TestLowSelIndexGreedySearch(c *C) { // The test purposes are: // - index `idx2` runs much faster than `idx4` experimentally; // - estimated row count of IndexLookUp should be 0; - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) }) testKit.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestUpdateProjEliminate(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestUpdateProjEliminate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustExec("explain update t t1, (select distinct b from t) t2 set t1.b = t2.b") } -func (s *testAnalyzeSuite) TestTiFlashCostModel(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestTiFlashCostModel(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (a int, b int, c int, primary key(a))") tk.MustExec("insert into t values(1,1,1), (2,2,2), (3,3,3)") tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) - c.Assert(err, IsNil) + require.NoError(t, err) // Set the hacked TiFlash replica for explain tests. tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} var input, output [][]string - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { for j, tt := range ts { if j != len(ts)-1 { tk.MustExec(tt) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { if j == len(ts)-1 { - output[i] = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i] = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) } }) if j == len(ts)-1 { @@ -941,45 +777,35 @@ func (s *testAnalyzeSuite) TestTiFlashCostModel(c *C) { } } -func (s *testAnalyzeSuite) TestIndexEqualUnknown(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIndexEqualUnknown(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t, t1") - testKit.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + testKit.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly testKit.MustExec("CREATE TABLE t(a bigint(20) NOT NULL, b bigint(20) NOT NULL, c bigint(20) NOT NULL, PRIMARY KEY (a,c,b), KEY (b))") - err = s.loadTableStats("analyzeSuiteTestIndexEqualUnknownT.json", dom) - c.Assert(err, IsNil) + require.NoError(t, loadTableStats("analyzeSuiteTestIndexEqualUnknownT.json", dom)) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(testKit.MustQuery(tt).Rows()) }) testKit.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestLimitIndexEstimation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestLimitIndexEstimation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -987,31 +813,27 @@ func (s *testAnalyzeSuite) TestLimitIndexEstimation(c *C) { tk.MustExec("set session tidb_enable_extended_stats = on") // Values in column a are from 1 to 1000000, values in column b are from 1000000 to 1, // these 2 columns are strictly correlated in reverse order. - err = s.loadTableStats("analyzeSuiteTestLimitIndexEstimationT.json", dom) - c.Assert(err, IsNil) + require.NoError(t, loadTableStats("analyzeSuiteTestLimitIndexEstimationT.json", dom)) var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + analyzeSuiteData := core.GetAnalyzeSuiteData() + analyzeSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testAnalyzeSuite) TestBatchPointGetTablePartition(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - testKit := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestBatchPointGetTablePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t1,t2,t3,t4,t5,t6") @@ -1092,7 +914,7 @@ func (s *testAnalyzeSuite) TestBatchPointGetTablePartition(c *C) { "1 2", )) - testKit.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + testKit.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn testKit.MustExec("create table t3(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") testKit.MustExec("insert into t3 values(1,1),(1,2),(2,1),(2,2)") @@ -1250,14 +1072,10 @@ func (s *testAnalyzeSuite) TestBatchPointGetTablePartition(c *C) { } // TestAppendIntPkToIndexTailForRangeBuilding tests for issue25219 https://github.com/pingcap/tidb/issues/25219. -func (s *testAnalyzeSuite) TestAppendIntPkToIndexTailForRangeBuilding(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestAppendIntPkToIndexTailForRangeBuilding(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t25219(a int primary key, col3 int, col1 int, index idx(col3))") tk.MustExec("insert into t25219 values(1, 1, 1)") diff --git a/planner/core/collect_column_stats_usage.go b/planner/core/collect_column_stats_usage.go index 6396b1ddad34f..e6f9e7ebed2b6 100644 --- a/planner/core/collect_column_stats_usage.go +++ b/planner/core/collect_column_stats_usage.go @@ -19,27 +19,49 @@ import ( "github.com/pingcap/tidb/parser/model" ) -// predicateColumnCollector collects predicate columns from logical plan. Predicate columns are the columns whose statistics -// are utilized when making query plans, which usually occur in where conditions, join conditions and so on. -type predicateColumnCollector struct { - // colMap maps expression.Column.UniqueID to the table columns whose statistics are utilized to calculate statistics of the column. - colMap map[int64]map[model.TableColumnID]struct{} +const ( + collectPredicateColumns uint64 = 1 << iota + collectHistNeededColumns +) + +// columnStatsUsageCollector collects predicate columns and/or histogram-needed columns from logical plan. +// Predicate columns are the columns whose statistics are utilized when making query plans, which usually occur in where conditions, join conditions and so on. +// Histogram-needed columns are the columns whose histograms are utilized when making query plans, which usually occur in the conditions pushed down to DataSource. +// The set of histogram-needed columns is the subset of that of predicate columns. +type columnStatsUsageCollector struct { + // collectMode indicates whether to collect predicate columns and/or histogram-needed columns + collectMode uint64 // predicateCols records predicate columns. predicateCols map[model.TableColumnID]struct{} + // colMap maps expression.Column.UniqueID to the table columns whose statistics may be utilized to calculate statistics of the column. + // It is used for collecting predicate columns. + // For example, in `select count(distinct a, b) as e from t`, the count of column `e` is calculated as `max(ndv(t.a), ndv(t.b))` if + // we don't know `ndv(t.a, t.b)`(see (*LogicalAggregation).DeriveStats and getColsNDV for details). So when calculating the statistics + // of column `e`, we may use the statistics of column `t.a` and `t.b`. + colMap map[int64]map[model.TableColumnID]struct{} + // histNeededCols records histogram-needed columns + histNeededCols map[model.TableColumnID]struct{} // cols is used to store columns collected from expressions and saves some allocation. cols []*expression.Column } -func newPredicateColumnCollector() *predicateColumnCollector { - return &predicateColumnCollector{ - colMap: make(map[int64]map[model.TableColumnID]struct{}), - predicateCols: make(map[model.TableColumnID]struct{}), +func newColumnStatsUsageCollector(collectMode uint64) *columnStatsUsageCollector { + collector := &columnStatsUsageCollector{ + collectMode: collectMode, // Pre-allocate a slice to reduce allocation, 8 doesn't have special meaning. cols: make([]*expression.Column, 0, 8), } + if collectMode&collectPredicateColumns != 0 { + collector.predicateCols = make(map[model.TableColumnID]struct{}) + collector.colMap = make(map[int64]map[model.TableColumnID]struct{}) + } + if collectMode&collectHistNeededColumns != 0 { + collector.histNeededCols = make(map[model.TableColumnID]struct{}) + } + return collector } -func (c *predicateColumnCollector) addPredicateColumn(col *expression.Column) { +func (c *columnStatsUsageCollector) addPredicateColumn(col *expression.Column) { tblColIDs, ok := c.colMap[col.UniqueID] if !ok { // It may happen if some leaf of logical plan is LogicalMemTable/LogicalShow/LogicalShowDDLJobs. @@ -50,21 +72,14 @@ func (c *predicateColumnCollector) addPredicateColumn(col *expression.Column) { } } -func (c *predicateColumnCollector) addPredicateColumnsFromExpression(expr expression.Expression) { - cols := expression.ExtractColumnsAndCorColumns(c.cols[:0], expr) - for _, col := range cols { - c.addPredicateColumn(col) - } -} - -func (c *predicateColumnCollector) addPredicateColumnsFromExpressions(list []expression.Expression) { +func (c *columnStatsUsageCollector) addPredicateColumnsFromExpressions(list []expression.Expression) { cols := expression.ExtractColumnsAndCorColumnsFromExpressions(c.cols[:0], list) for _, col := range cols { c.addPredicateColumn(col) } } -func (c *predicateColumnCollector) updateColMap(col *expression.Column, relatedCols []*expression.Column) { +func (c *columnStatsUsageCollector) updateColMap(col *expression.Column, relatedCols []*expression.Column) { if _, ok := c.colMap[col.UniqueID]; !ok { c.colMap[col.UniqueID] = map[model.TableColumnID]struct{}{} } @@ -80,15 +95,13 @@ func (c *predicateColumnCollector) updateColMap(col *expression.Column, relatedC } } -func (c *predicateColumnCollector) updateColMapFromExpression(col *expression.Column, expr expression.Expression) { - c.updateColMap(col, expression.ExtractColumnsAndCorColumns(c.cols[:0], expr)) -} - -func (c *predicateColumnCollector) updateColMapFromExpressions(col *expression.Column, list []expression.Expression) { +func (c *columnStatsUsageCollector) updateColMapFromExpressions(col *expression.Column, list []expression.Expression) { c.updateColMap(col, expression.ExtractColumnsAndCorColumnsFromExpressions(c.cols[:0], list)) } -func (ds *DataSource) updateColMapAndAddPredicateColumns(c *predicateColumnCollector) { +func (c *columnStatsUsageCollector) collectPredicateColumnsForDataSource(ds *DataSource) { + // For partition tables, no matter whether it is static or dynamic pruning mode, we use table ID rather than partition ID to + // set TableColumnID.TableID. In this way, we keep the set of predicate columns consistent between different partitions and global table. tblID := ds.TableInfo().ID for _, col := range ds.Schema().Columns { tblColID := model.TableColumnID{TableID: tblID, ColumnID: col.ID} @@ -98,7 +111,7 @@ func (ds *DataSource) updateColMapAndAddPredicateColumns(c *predicateColumnColle c.addPredicateColumnsFromExpressions(ds.pushedDownConds) } -func (p *LogicalJoin) updateColMapAndAddPredicateColumns(c *predicateColumnCollector) { +func (c *columnStatsUsageCollector) collectPredicateColumnsForJoin(p *LogicalJoin) { // The only schema change is merging two schemas so there is no new column. // Assume statistics of all the columns in EqualConditions/LeftConditions/RightConditions/OtherConditions are needed. exprs := make([]expression.Expression, 0, len(p.EqualConditions)+len(p.LeftConditions)+len(p.RightConditions)+len(p.OtherConditions)) @@ -117,7 +130,7 @@ func (p *LogicalJoin) updateColMapAndAddPredicateColumns(c *predicateColumnColle c.addPredicateColumnsFromExpressions(exprs) } -func (p *LogicalUnionAll) updateColMapAndAddPredicateColumns(c *predicateColumnCollector) { +func (c *columnStatsUsageCollector) collectPredicateColumnsForUnionAll(p *LogicalUnionAll) { // statistics of the ith column of UnionAll come from statistics of the ith column of each child. schemas := make([]*expression.Schema, 0, len(p.Children())) relatedCols := make([]*expression.Column, 0, len(p.Children())) @@ -133,120 +146,158 @@ func (p *LogicalUnionAll) updateColMapAndAddPredicateColumns(c *predicateColumnC } } -func (c *predicateColumnCollector) collectFromPlan(lp LogicalPlan) { +func (c *columnStatsUsageCollector) addHistNeededColumns(ds *DataSource) { + columns := expression.ExtractColumnsFromExpressions(c.cols[:0], ds.pushedDownConds, nil) + for _, col := range columns { + tblColID := model.TableColumnID{TableID: ds.physicalTableID, ColumnID: col.ID} + c.histNeededCols[tblColID] = struct{}{} + } +} + +func (c *columnStatsUsageCollector) collectFromPlan(lp LogicalPlan) { for _, child := range lp.Children() { c.collectFromPlan(child) } - switch x := lp.(type) { - case *DataSource: - x.updateColMapAndAddPredicateColumns(c) - case *LogicalIndexScan: - x.Source.updateColMapAndAddPredicateColumns(c) - // TODO: Is it redundant to add predicate columns from LogicalIndexScan.AccessConds? Is LogicalIndexScan.AccessConds a subset of LogicalIndexScan.Source.pushedDownConds. - c.addPredicateColumnsFromExpressions(x.AccessConds) - case *LogicalTableScan: - x.Source.updateColMapAndAddPredicateColumns(c) - // TODO: Is it redundant to add predicate columns from LogicalTableScan.AccessConds? Is LogicalTableScan.AccessConds a subset of LogicalTableScan.Source.pushedDownConds. - c.addPredicateColumnsFromExpressions(x.AccessConds) - case *TiKVSingleGather: - // TODO: Is it redundant? - x.Source.updateColMapAndAddPredicateColumns(c) - case *LogicalProjection: - // Schema change from children to self. - schema := x.Schema() - for i, expr := range x.Exprs { - c.updateColMapFromExpression(schema.Columns[i], expr) - } - case *LogicalSelection: - // Though the conditions in LogicalSelection are complex conditions which cannot be pushed down to DataSource, we still - // regard statistics of the columns in the conditions as needed. - c.addPredicateColumnsFromExpressions(x.Conditions) - case *LogicalAggregation: - // Just assume statistics of all the columns in GroupByItems are needed. - c.addPredicateColumnsFromExpressions(x.GroupByItems) - // Schema change from children to self. - schema := x.Schema() - for i, aggFunc := range x.AggFuncs { - c.updateColMapFromExpressions(schema.Columns[i], aggFunc.Args) - } - case *LogicalWindow: - // Statistics of the columns in LogicalWindow.PartitionBy are used in optimizeByShuffle4Window. - // It seems that we don't use statistics of the columns in LogicalWindow.OrderBy currently? - for _, item := range x.PartitionBy { - c.addPredicateColumn(item.Col) - } - // Schema change from children to self. - windowColumns := x.GetWindowResultColumns() - for i, col := range windowColumns { - c.updateColMapFromExpressions(col, x.WindowFuncDescs[i].Args) - } - case *LogicalJoin: - x.updateColMapAndAddPredicateColumns(c) - case *LogicalApply: - x.updateColMapAndAddPredicateColumns(c) - // Assume statistics of correlated columns are needed. - // Correlated columns can be found in LogicalApply.Children()[0].Schema(). Since we already visit LogicalApply.Children()[0], - // correlated columns must have existed in predicateColumnCollector.colMap. - for _, corCols := range x.CorCols { - c.addPredicateColumn(&corCols.Column) - } - case *LogicalSort: - // Assume statistics of all the columns in ByItems are needed. - for _, item := range x.ByItems { - c.addPredicateColumnsFromExpression(item.Expr) - } - case *LogicalTopN: - // Assume statistics of all the columns in ByItems are needed. - for _, item := range x.ByItems { - c.addPredicateColumnsFromExpression(item.Expr) - } - case *LogicalUnionAll: - x.updateColMapAndAddPredicateColumns(c) - case *LogicalPartitionUnionAll: - x.updateColMapAndAddPredicateColumns(c) - case *LogicalCTE: - // Visit seedPartLogicalPlan and recursivePartLogicalPlan first. - c.collectFromPlan(x.cte.seedPartLogicalPlan) - if x.cte.recursivePartLogicalPlan != nil { - c.collectFromPlan(x.cte.recursivePartLogicalPlan) - } - // Schema change from seedPlan/recursivePlan to self. - columns := x.Schema().Columns - seedColumns := x.cte.seedPartLogicalPlan.Schema().Columns - var recursiveColumns []*expression.Column - if x.cte.recursivePartLogicalPlan != nil { - recursiveColumns = x.cte.recursivePartLogicalPlan.Schema().Columns - } - relatedCols := make([]*expression.Column, 0, 2) - for i, col := range columns { - relatedCols = append(relatedCols[:0], seedColumns[i]) - if recursiveColumns != nil { - relatedCols = append(relatedCols, recursiveColumns[i]) + if c.collectMode&collectPredicateColumns != 0 { + switch x := lp.(type) { + case *DataSource: + c.collectPredicateColumnsForDataSource(x) + case *LogicalIndexScan: + c.collectPredicateColumnsForDataSource(x.Source) + c.addPredicateColumnsFromExpressions(x.AccessConds) + case *LogicalTableScan: + c.collectPredicateColumnsForDataSource(x.Source) + c.addPredicateColumnsFromExpressions(x.AccessConds) + case *LogicalProjection: + // Schema change from children to self. + schema := x.Schema() + for i, expr := range x.Exprs { + c.updateColMapFromExpressions(schema.Columns[i], []expression.Expression{expr}) } - c.updateColMap(col, relatedCols) - } - // If IsDistinct is true, then we use getColsNDV to calculate row count(see (*LogicalCTE).DeriveStat). In this case - // statistics of all the columns are needed. - if x.cte.IsDistinct { - for _, col := range columns { - c.addPredicateColumn(col) + case *LogicalSelection: + // Though the conditions in LogicalSelection are complex conditions which cannot be pushed down to DataSource, we still + // regard statistics of the columns in the conditions as needed. + c.addPredicateColumnsFromExpressions(x.Conditions) + case *LogicalAggregation: + // Just assume statistics of all the columns in GroupByItems are needed. + c.addPredicateColumnsFromExpressions(x.GroupByItems) + // Schema change from children to self. + schema := x.Schema() + for i, aggFunc := range x.AggFuncs { + c.updateColMapFromExpressions(schema.Columns[i], aggFunc.Args) + } + case *LogicalWindow: + // Statistics of the columns in LogicalWindow.PartitionBy are used in optimizeByShuffle4Window. + // We don't use statistics of the columns in LogicalWindow.OrderBy currently. + for _, item := range x.PartitionBy { + c.addPredicateColumn(item.Col) + } + // Schema change from children to self. + windowColumns := x.GetWindowResultColumns() + for i, col := range windowColumns { + c.updateColMapFromExpressions(col, x.WindowFuncDescs[i].Args) + } + case *LogicalJoin: + c.collectPredicateColumnsForJoin(x) + case *LogicalApply: + c.collectPredicateColumnsForJoin(&x.LogicalJoin) + // Assume statistics of correlated columns are needed. + // Correlated columns can be found in LogicalApply.Children()[0].Schema(). Since we already visit LogicalApply.Children()[0], + // correlated columns must have existed in columnStatsUsageCollector.colMap. + for _, corCols := range x.CorCols { + c.addPredicateColumn(&corCols.Column) + } + case *LogicalSort: + // Assume statistics of all the columns in ByItems are needed. + for _, item := range x.ByItems { + c.addPredicateColumnsFromExpressions([]expression.Expression{item.Expr}) + } + case *LogicalTopN: + // Assume statistics of all the columns in ByItems are needed. + for _, item := range x.ByItems { + c.addPredicateColumnsFromExpressions([]expression.Expression{item.Expr}) + } + case *LogicalUnionAll: + c.collectPredicateColumnsForUnionAll(x) + case *LogicalPartitionUnionAll: + c.collectPredicateColumnsForUnionAll(&x.LogicalUnionAll) + case *LogicalCTE: + // Visit seedPartLogicalPlan and recursivePartLogicalPlan first. + c.collectFromPlan(x.cte.seedPartLogicalPlan) + if x.cte.recursivePartLogicalPlan != nil { + c.collectFromPlan(x.cte.recursivePartLogicalPlan) + } + // Schema change from seedPlan/recursivePlan to self. + columns := x.Schema().Columns + seedColumns := x.cte.seedPartLogicalPlan.Schema().Columns + var recursiveColumns []*expression.Column + if x.cte.recursivePartLogicalPlan != nil { + recursiveColumns = x.cte.recursivePartLogicalPlan.Schema().Columns + } + relatedCols := make([]*expression.Column, 0, 2) + for i, col := range columns { + relatedCols = append(relatedCols[:0], seedColumns[i]) + if recursiveColumns != nil { + relatedCols = append(relatedCols, recursiveColumns[i]) + } + c.updateColMap(col, relatedCols) + } + // If IsDistinct is true, then we use getColsNDV to calculate row count(see (*LogicalCTE).DeriveStat). In this case + // statistics of all the columns are needed. + if x.cte.IsDistinct { + for _, col := range columns { + c.addPredicateColumn(col) + } + } + case *LogicalCTETable: + // Schema change from seedPlan to self. + for i, col := range x.Schema().Columns { + c.updateColMap(col, []*expression.Column{x.seedSchema.Columns[i]}) } } - case *LogicalCTETable: - // Schema change from seedPlan to self. - for i, col := range x.Schema().Columns { - c.updateColMap(col, []*expression.Column{x.seedSchema.Columns[i]}) + } + if c.collectMode&collectHistNeededColumns != 0 { + // Histogram-needed columns are the columns which occur in the conditions pushed down to DataSource. + // We don't consider LogicalCTE because seedLogicalPlan and recursiveLogicalPlan haven't got logical optimization + // yet(seedLogicalPlan and recursiveLogicalPlan are optimized in DeriveStats phase). Without logical optimization, + // there is no condition pushed down to DataSource so no histogram-needed column can be collected. + switch x := lp.(type) { + case *DataSource: + c.addHistNeededColumns(x) + case *LogicalIndexScan: + c.addHistNeededColumns(x.Source) + case *LogicalTableScan: + c.addHistNeededColumns(x.Source) } } } -// CollectPredicateColumnsForTest collects predicate columns from logical plan. It is only for test. -func CollectPredicateColumnsForTest(lp LogicalPlan) []model.TableColumnID { - collector := newPredicateColumnCollector() +// CollectColumnStatsUsage collects column stats usage from logical plan. +// predicate indicates whether to collect predicate columns and histNeeded indicates whether to collect histogram-needed columns. +// The first return value is predicate columns(nil if predicate is false) and the second return value is histogram-needed columns(nil if histNeeded is false). +func CollectColumnStatsUsage(lp LogicalPlan, predicate, histNeeded bool) ([]model.TableColumnID, []model.TableColumnID) { + var mode uint64 + if predicate { + mode |= collectPredicateColumns + } + if histNeeded { + mode |= collectHistNeededColumns + } + collector := newColumnStatsUsageCollector(mode) collector.collectFromPlan(lp) - tblColIDs := make([]model.TableColumnID, 0, len(collector.predicateCols)) - for tblColID := range collector.predicateCols { - tblColIDs = append(tblColIDs, tblColID) + set2slice := func(set map[model.TableColumnID]struct{}) []model.TableColumnID { + ret := make([]model.TableColumnID, 0, len(set)) + for tblColID := range set { + ret = append(ret, tblColID) + } + return ret + } + var predicateCols, histNeededCols []model.TableColumnID + if predicate { + predicateCols = set2slice(collector.predicateCols) + } + if histNeeded { + histNeededCols = set2slice(collector.histNeededCols) } - return tblColIDs + return predicateCols, histNeededCols } diff --git a/planner/core/collect_column_stats_usage_test.go b/planner/core/collect_column_stats_usage_test.go index b270b6f7c1bfc..295f29e4d4bc0 100644 --- a/planner/core/collect_column_stats_usage_test.go +++ b/planner/core/collect_column_stats_usage_test.go @@ -12,210 +12,337 @@ // See the License for the specific language governing permissions and // limitations under the License. -package core_test +package core import ( "context" "fmt" + "sort" "testing" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/model" - plannercore "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/logutil" "github.com/stretchr/testify/require" ) -func TestCollectPredicateColumns(t *testing.T) { - store, dom, clean := testkit.CreateMockStoreAndDomain(t) - defer clean() - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2") - tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") - tk.MustExec("create table t1(a int, b int, c int)") - tk.MustExec("create table t2(a int, b int, c int)") - tk.MustExec("create table t3(a int, b int, c int) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than maxvalue)") +func getColumnName(t *testing.T, is infoschema.InfoSchema, tblColID model.TableColumnID, comment string) string { + var tblInfo *model.TableInfo + var prefix string + if tbl, ok := is.TableByID(tblColID.TableID); ok { + tblInfo = tbl.Meta() + prefix = tblInfo.Name.L + "." + } else { + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists, comment) + for _, tbl := range db.Tables { + pi := tbl.GetPartitionInfo() + if pi == nil { + continue + } + for _, def := range pi.Definitions { + if def.ID == tblColID.TableID { + tblInfo = tbl + prefix = tbl.Name.L + "." + def.Name.L + "." + break + } + } + if tblInfo != nil { + break + } + } + require.NotNil(t, tblInfo, comment) + } + + var colName string + for _, col := range tblInfo.Columns { + if tblColID.ColumnID == col.ID { + colName = prefix + col.Name.L + } + } + require.NotEmpty(t, colName, comment) + return colName +} + +func checkColumnStatsUsage(t *testing.T, is infoschema.InfoSchema, lp LogicalPlan, histNeededOnly bool, expected []string, comment string) { + var tblColIDs []model.TableColumnID + if histNeededOnly { + _, tblColIDs = CollectColumnStatsUsage(lp, false, true) + } else { + tblColIDs, _ = CollectColumnStatsUsage(lp, true, false) + } + cols := make([]string, 0, len(tblColIDs)) + for _, tblColID := range tblColIDs { + col := getColumnName(t, is, tblColID, comment) + cols = append(cols, col) + } + sort.Strings(cols) + require.Equal(t, expected, cols, comment) +} + +func TestCollectPredicateColumns(t *testing.T) { tests := []struct { - sql string - res []string + pruneMode string + sql string + res []string }{ { // DataSource - sql: "select * from t1 where a > 2", - res: []string{"t1.a"}, + sql: "select * from t where a > 2", + res: []string{"t.a"}, }, { // DataSource - sql: "select * from t1 where b in (2, 5) or c = 5", - res: []string{"t1.b", "t1.c"}, + sql: "select * from t where b in (2, 5) or c = 5", + res: []string{"t.b", "t.c"}, }, { // LogicalProjection - sql: "select * from (select a + b as ab, c from t1) as tmp where ab > 4", - res: []string{"t1.a", "t1.b"}, + sql: "select * from (select a + b as ab, c from t) as tmp where ab > 4", + res: []string{"t.a", "t.b"}, }, { // LogicalAggregation - sql: "select b, count(*) from t1 group by b", - res: []string{"t1.b"}, + sql: "select b, count(*) from t group by b", + res: []string{"t.b"}, }, { // LogicalAggregation - sql: "select b, sum(a) from t1 group by b having sum(a) > 3", - res: []string{"t1.a", "t1.b"}, + sql: "select b, sum(a) from t group by b having sum(a) > 3", + res: []string{"t.a", "t.b"}, }, { // LogicalAggregation - sql: "select count(*), sum(a), sum(c) from t1", + sql: "select count(*), sum(a), sum(c) from t", res: []string{}, }, { // LogicalAggregation - sql: "(select a, b from t1) union (select a, c from t2)", - res: []string{"t1.a", "t1.b", "t2.a", "t2.c"}, + sql: "(select a, c from t) union (select a, b from t2)", + res: []string{"t.a", "t.c", "t2.a", "t2.b"}, }, { // LogicalWindow - sql: "select avg(b) over(partition by a) from t1", - res: []string{"t1.a"}, + sql: "select avg(b) over(partition by a) from t", + res: []string{"t.a"}, }, { // LogicalWindow - sql: "select * from (select avg(b) over(partition by a) as w from t1) as tmp where w > 4", - res: []string{"t1.a", "t1.b"}, + sql: "select * from (select avg(b) over(partition by a) as w from t) as tmp where w > 4", + res: []string{"t.a", "t.b"}, }, { // LogicalWindow - sql: "select row_number() over(partition by a order by c) from t1", - res: []string{"t1.a"}, + sql: "select row_number() over(partition by a order by c) from t", + res: []string{"t.a"}, }, { // LogicalJoin - sql: "select * from t1, t2 where t1.a = t2.a", - res: []string{"t1.a", "t2.a"}, + sql: "select * from t, t2 where t.a = t2.a", + res: []string{"t.a", "t2.a"}, }, { // LogicalJoin - sql: "select * from t1 as x join t2 as y on x.b + y.c > 2", - res: []string{"t1.b", "t2.c"}, + sql: "select * from t as x join t2 as y on x.c + y.b > 2", + res: []string{"t.c", "t2.b"}, }, { // LogicalJoin - sql: "select * from t1 as x join t2 as y on x.a = y.a and x.b < 3 and y.c > 2", - res: []string{"t1.a", "t1.b", "t2.a", "t2.c"}, + sql: "select * from t as x join t2 as y on x.a = y.a and x.c < 3 and y.b > 2", + res: []string{"t.a", "t.c", "t2.a", "t2.b"}, }, { // LogicalJoin - sql: "select x.b, y.c, sum(x.c), sum(y.b) from t1 as x join t2 as y on x.a = y.a group by x.b, y.c order by x.b", - res: []string{"t1.a", "t1.b", "t2.a", "t2.c"}, + sql: "select x.c, y.b, sum(x.b), sum(y.a) from t as x join t2 as y on x.a < y.a group by x.c, y.b order by x.c", + res: []string{"t.a", "t.c", "t2.a", "t2.b"}, }, { - // LogicalApply - sql: "select * from t1 where t1.b > all(select b from t2 where t2.c > 2)", - res: []string{"t1.b", "t2.b", "t2.c"}, + // LogicalApply, LogicalJoin + sql: "select * from t2 where t2.b > all(select b from t where t.c > 2)", + res: []string{"t.b", "t.c", "t2.b"}, }, { - // LogicalApply - sql: "select * from t1 where t1.b > (select count(b) from t2 where t2.c > t1.a)", - res: []string{"t1.a", "t1.b", "t2.b", "t2.c"}, + // LogicalApply, LogicalJoin + sql: "select * from t2 where t2.b > any(select b from t where t.c > 2)", + res: []string{"t.b", "t.c", "t2.b"}, + }, + { + // LogicalApply, LogicalJoin + sql: "select * from t2 where t2.b > (select sum(b) from t where t.c > t2.a)", + res: []string{"t.b", "t.c", "t2.a", "t2.b"}, }, { // LogicalApply - sql: "select * from t1 where t1.b > (select count(*) from t2 where t2.c > t1.a)", - res: []string{"t1.a", "t1.b", "t2.c"}, + sql: "select * from t2 where t2.b > (select count(*) from t where t.a > t2.a)", + res: []string{"t.a", "t2.a", "t2.b"}, + }, + { + // LogicalApply, LogicalJoin + sql: "select * from t2 where exists (select * from t where t.a > t2.b)", + res: []string{"t.a", "t2.b"}, + }, + { + // LogicalApply, LogicalJoin + sql: "select * from t2 where not exists (select * from t where t.a > t2.b)", + res: []string{"t.a", "t2.b"}, + }, + { + // LogicalJoin + sql: "select * from t2 where t2.a in (select b from t)", + res: []string{"t.b", "t2.a"}, + }, + { + // LogicalApply, LogicalJoin + sql: "select * from t2 where t2.a not in (select b from t)", + res: []string{"t.b", "t2.a"}, }, { // LogicalSort - sql: "select * from t1 order by c", - res: []string{"t1.c"}, + sql: "select * from t order by c", + res: []string{"t.c"}, }, { // LogicalTopN - sql: "select * from t1 order by a + b limit 10", - res: []string{"t1.a", "t1.b"}, + sql: "select * from t order by a + b limit 10", + res: []string{"t.a", "t.b"}, }, { // LogicalUnionAll - sql: "select * from ((select a, b from t1) union all (select a, c from t2)) as tmp where tmp.b > 2", - res: []string{"t1.b", "t2.c"}, - }, - { - // LogicalPartitionUnionAll - sql: "select * from t3 where a < 15 and b > 1", - res: []string{"t3.a", "t3.b"}, + sql: "select * from ((select a, c from t) union all (select a, b from t2)) as tmp where tmp.c > 2", + res: []string{"t.c", "t2.b"}, }, { // LogicalCTE - sql: "with cte(x, y) as (select a + 1, b from t1 where b > 1) select * from cte where x > 3", - res: []string{"t1.a", "t1.b"}, + sql: "with cte(x, y) as (select a + 1, b from t where b > 1) select * from cte where x > 3", + res: []string{"t.a", "t.b"}, }, { // LogicalCTE, LogicalCTETable - sql: "with recursive cte(x, y) as (select c, 1 from t1 union all select x + 1, y from cte where x < 5) select * from cte", - res: []string{"t1.c"}, + sql: "with recursive cte(x, y) as (select c, 1 from t union all select x + 1, y from cte where x < 5) select * from cte", + res: []string{"t.c"}, }, { // LogicalCTE, LogicalCTETable - sql: "with recursive cte(x, y) as (select 1, c from t1 union all select x + 1, y from cte where x < 5) select * from cte where y > 1", - res: []string{"t1.c"}, + sql: "with recursive cte(x, y) as (select 1, c from t union all select x + 1, y from cte where x < 5) select * from cte where y > 1", + res: []string{"t.c"}, }, { // LogicalCTE, LogicalCTETable - sql: "with recursive cte(x, y) as (select a, b from t1 union select x + 1, y from cte where x < 5) select * from cte", - res: []string{"t1.a", "t1.b"}, + sql: "with recursive cte(x, y) as (select a, b from t union select x + 1, y from cte where x < 5) select * from cte", + res: []string{"t.a", "t.b"}, + }, + { + // LogicalPartitionUnionAll, static partition prune mode, use table ID rather than partition ID + pruneMode: "static", + sql: "select * from pt1 where ptn < 20 and b > 1", + res: []string{"pt1.b", "pt1.ptn"}, + }, + { + // dynamic partition prune mode, use table ID rather than partition ID + pruneMode: "dynamic", + sql: "select * from pt1 where ptn < 20 and b > 1", + res: []string{"pt1.b", "pt1.ptn"}, }, } + s := createPlannerSuite() ctx := context.Background() - sctx := tk.Session() - is := dom.InfoSchema() - getColName := func(tblColID model.TableColumnID) (string, bool) { - tbl, ok := is.TableByID(tblColID.TableID) - if !ok { - return "", false - } - tblInfo := tbl.Meta() - for _, col := range tblInfo.Columns { - if tblColID.ColumnID == col.ID { - return tblInfo.Name.L + "." + col.Name.L, true - } + for _, tt := range tests { + comment := fmt.Sprintf("sql: %s", tt.sql) + if len(tt.pruneMode) > 0 { + s.ctx.GetSessionVars().PartitionPruneMode.Store(tt.pruneMode) } - return "", false + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) + require.NoError(t, err, comment) + builder, _ := NewPlanBuilder().Init(s.ctx, s.is, &hint.BlockHintProcessor{}) + p, err := builder.Build(ctx, stmt) + require.NoError(t, err, comment) + lp, ok := p.(LogicalPlan) + require.True(t, ok, comment) + // We check predicate columns twice, before and after logical optimization. Some logical plan patterns may occur before + // logical optimization while others may occur after logical optimization. + checkColumnStatsUsage(t, s.is, lp, false, tt.res, comment) + lp, err = logicalOptimize(ctx, builder.GetOptFlag(), lp) + require.NoError(t, err, comment) + checkColumnStatsUsage(t, s.is, lp, false, tt.res, comment) } - checkPredicateColumns := func(lp plannercore.LogicalPlan, expected []string, comment string) { - tblColIDs := plannercore.CollectPredicateColumnsForTest(lp) - cols := make([]string, 0, len(tblColIDs)) - for _, tblColID := range tblColIDs { - col, ok := getColName(tblColID) - require.True(t, ok, comment) - cols = append(cols, col) - } - require.ElementsMatch(t, expected, cols, comment) +} + +func TestCollectHistNeededColumns(t *testing.T) { + tests := []struct { + pruneMode string + sql string + res []string + }{ + { + sql: "select * from t where a > 2", + res: []string{"t.a"}, + }, + { + sql: "select * from t where b in (2, 5) or c = 5", + res: []string{"t.b", "t.c"}, + }, + { + sql: "select * from t where a + b > 1", + res: []string{"t.a", "t.b"}, + }, + { + sql: "select b, count(a) from t where b > 1 group by b having count(a) > 2", + res: []string{"t.b"}, + }, + { + sql: "select * from t as x join t2 as y on x.b + y.b > 2 and x.c > 1 and y.a < 1", + res: []string{"t.c", "t2.a"}, + }, + { + sql: "select * from t2 where t2.b > all(select b from t where t.c > 2)", + res: []string{"t.c"}, + }, + { + sql: "select * from t2 where t2.b > any(select b from t where t.c > 2)", + res: []string{"t.c"}, + }, + { + sql: "select * from t2 where t2.b in (select b from t where t.c > 2)", + res: []string{"t.c"}, + }, + { + pruneMode: "static", + sql: "select * from pt1 where ptn < 20 and b > 1", + res: []string{"pt1.p1.b", "pt1.p1.ptn", "pt1.p2.b", "pt1.p2.ptn"}, + }, + { + pruneMode: "dynamic", + sql: "select * from pt1 where ptn < 20 and b > 1", + res: []string{"pt1.b", "pt1.ptn"}, + }, } + s := createPlannerSuite() + ctx := context.Background() for _, tt := range tests { - comment := fmt.Sprintf("for %s", tt.sql) - logutil.BgLogger().Info(comment) - stmts, err := tk.Session().Parse(ctx, tt.sql) + comment := fmt.Sprintf("sql: %s", tt.sql) + if len(tt.pruneMode) > 0 { + s.ctx.GetSessionVars().PartitionPruneMode.Store(tt.pruneMode) + } + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") require.NoError(t, err, comment) - stmt := stmts[0] - err = plannercore.Preprocess(sctx, stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) + err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) require.NoError(t, err, comment) - builder, _ := plannercore.NewPlanBuilder().Init(sctx, is, &hint.BlockHintProcessor{}) + builder, _ := NewPlanBuilder().Init(s.ctx, s.is, &hint.BlockHintProcessor{}) p, err := builder.Build(ctx, stmt) require.NoError(t, err, comment) - lp, ok := p.(plannercore.LogicalPlan) + lp, ok := p.(LogicalPlan) require.True(t, ok, comment) - // We check predicate columns twice, before and after logical optimization. Some logical plan patterns may occur before - // logical optimization while others may occur after logical optimization. - // logutil.BgLogger().Info("before logical opt", zap.String("lp", plannercore.ToString(lp))) - checkPredicateColumns(lp, tt.res, comment) - lp, err = plannercore.LogicalOptimize(ctx, builder.GetOptFlag(), lp) + flags := builder.GetOptFlag() + // JoinReOrder may need columns stats so collecting hist-needed columns must happen before JoinReOrder. + // Hence, we disable JoinReOrder and PruneColumnsAgain here. + flags &= ^(flagJoinReOrder | flagPrunColumnsAgain) + lp, err = logicalOptimize(ctx, flags, lp) require.NoError(t, err, comment) - // logutil.BgLogger().Info("after logical opt", zap.String("lp", plannercore.ToString(lp))) - checkPredicateColumns(lp, tt.res, comment) + checkColumnStatsUsage(t, s.is, lp, true, tt.res, comment) } } diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index d3e56600b2c25..d27574b10b590 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -22,6 +22,8 @@ import ( "strings" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" @@ -33,6 +35,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/privilege" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/table" @@ -40,6 +43,7 @@ import ( "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/kvcache" @@ -183,12 +187,15 @@ type Prepare struct { type Execute struct { baseSchemaProducer - Name string - UsingVars []expression.Expression - PrepareParams []types.Datum - ExecID uint32 - SnapshotTS uint64 - IsStaleness bool + Name string + UsingVars []expression.Expression + PrepareParams []types.Datum + ExecID uint32 + // Deprecated: SnapshotTS now is only used for asserting after refactoring stale read, it will be removed later. + SnapshotTS uint64 + // Deprecated: IsStaleness now is only used for asserting after refactoring stale read, it will be removed later. + IsStaleness bool + // Deprecated: ReadReplicaScope now is only used for asserting after refactoring stale read, it will be removed later. ReadReplicaScope string Stmt ast.StmtNode StmtType string @@ -263,17 +270,33 @@ func (e *Execute) OptimizePreparedPlan(ctx context.Context, sctx sessionctx.Cont vars.PreparedParams = append(vars.PreparedParams, val) } } - snapshotTS, readReplicaScope, isStaleness, err := e.handleExecuteBuilderOption(sctx, preparedObj) + + // Just setting `e.SnapshotTS`, `e.ReadReplicaScope` and `e.IsStaleness` with the return value of `handleExecuteBuilderOption` + // for asserting the stale read context after refactoring is exactly the same with the previous logic. + snapshotTS, readReplicaScope, isStaleness, err := handleExecuteBuilderOption(sctx, preparedObj) if err != nil { return err } - if isStaleness { - is, err = domain.GetDomain(sctx).GetSnapshotInfoSchema(snapshotTS) - if err != nil { - return errors.Trace(err) + e.SnapshotTS = snapshotTS + e.ReadReplicaScope = readReplicaScope + e.IsStaleness = isStaleness + + failpoint.Inject("assertStaleReadForOptimizePreparedPlan", func() { + if isStaleness != sctx.GetSessionVars().StmtCtx.IsStaleness { + panic(fmt.Sprintf("%v != %v", isStaleness, sctx.GetSessionVars().StmtCtx.IsStaleness)) } - sctx.GetSessionVars().StmtCtx.IsStaleness = true - } + + if isStaleness { + is2, err := domain.GetDomain(sctx).GetSnapshotInfoSchema(snapshotTS) + if err != nil { + panic(err) + } + + if is.SchemaMetaVersion() != is2.SchemaMetaVersion() { + panic(fmt.Sprintf("%d != %d", is.SchemaMetaVersion(), is2.SchemaMetaVersion())) + } + } + }) if prepared.SchemaVersion != is.SchemaMetaVersion() { // In order to avoid some correctness issues, we have to clear the // cached plan once the schema version is changed. @@ -294,18 +317,26 @@ func (e *Execute) OptimizePreparedPlan(ctx context.Context, sctx sessionctx.Cont } prepared.SchemaVersion = is.SchemaMetaVersion() } + // If the lastUpdateTime less than expiredTimeStamp4PC, + // it means other sessions have executed 'admin flush instance plan_cache'. + // So we need to clear the current session's plan cache. + // And update lastUpdateTime to the newest one. + expiredTimeStamp4PC := domain.GetDomain(sctx).ExpiredTimeStamp4PC() + if prepared.UseCache && expiredTimeStamp4PC.Compare(vars.LastUpdateTime4PC) > 0 { + sctx.PreparedPlanCache().DeleteAll() + prepared.CachedPlan = nil + vars.LastUpdateTime4PC = expiredTimeStamp4PC + } err = e.getPhysicalPlan(ctx, sctx, is, preparedObj) if err != nil { return err } - e.SnapshotTS = snapshotTS - e.ReadReplicaScope = readReplicaScope - e.IsStaleness = isStaleness e.Stmt = prepared.Stmt return nil } -func (e *Execute) handleExecuteBuilderOption(sctx sessionctx.Context, +// Deprecated: it will be removed later. Now it is only used for asserting +func handleExecuteBuilderOption(sctx sessionctx.Context, preparedObj *CachedPrepareStmt) (snapshotTS uint64, readReplicaScope string, isStaleness bool, err error) { snapshotTS = 0 readReplicaScope = oracle.GlobalTxnScope @@ -380,33 +411,53 @@ func (e *Execute) setFoundInPlanCache(sctx sessionctx.Context, opt bool) error { return err } -func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, preparedStmt *CachedPrepareStmt) error { +// GetBindSQL4PlanCache used to get the bindSQL for plan cache to build the plan cache key. +func GetBindSQL4PlanCache(sctx sessionctx.Context, preparedStmt *CachedPrepareStmt) string { + useBinding := sctx.GetSessionVars().UsePlanBaselines + if !useBinding || preparedStmt.PreparedAst.Stmt == nil || preparedStmt.NormalizedSQL4PC == "" || preparedStmt.SQLDigest4PC == "" { + return "" + } + if sctx.Value(bindinfo.SessionBindInfoKeyType) == nil { + return "" + } + sessionHandle := sctx.Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle) + bindRecord := sessionHandle.GetBindRecord(preparedStmt.SQLDigest4PC, preparedStmt.NormalizedSQL4PC, "") + if bindRecord != nil { + enabledBinding := bindRecord.FindEnabledBinding() + if enabledBinding != nil { + return enabledBinding.BindSQL + } + } + globalHandle := domain.GetDomain(sctx).BindHandle() + if globalHandle == nil { + return "" + } + bindRecord = globalHandle.GetBindRecord(preparedStmt.SQLDigest4PC, preparedStmt.NormalizedSQL4PC, "") + if bindRecord != nil { + enabledBinding := bindRecord.FindEnabledBinding() + if enabledBinding != nil { + return enabledBinding.BindSQL + } + } + return "" +} + +func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, preparedStmt *CachedPrepareStmt) (err error) { var cacheKey kvcache.Key sessVars := sctx.GetSessionVars() stmtCtx := sessVars.StmtCtx prepared := preparedStmt.PreparedAst - if prepared.UseCache { - // disable the cache if cache table in prepared statement - for _, vInfo := range preparedStmt.VisitInfos { - tbl, err := is.TableByName(model.NewCIStr(vInfo.db), model.NewCIStr(vInfo.table)) - // if table does not exist, skip it, maybe it is a `create table` statement - if err != nil { - continue - } - if tbl.Meta().TableCacheStatusType == model.TableCacheStatusEnable { - prepared.UseCache = false - break - } - } - } stmtCtx.UseCache = prepared.UseCache var bindSQL string if prepared.UseCache { - bindSQL = GetBindSQL4PlanCache(sctx, prepared.Stmt) - cacheKey = NewPSTMTPlanCacheKey(sctx.GetSessionVars(), e.ExecID, prepared.SchemaVersion, bindSQL) + bindSQL = GetBindSQL4PlanCache(sctx, preparedStmt) + if cacheKey, err = NewPlanCacheKey(sctx.GetSessionVars(), preparedStmt.StmtText, preparedStmt.StmtDB, prepared.SchemaVersion); err != nil { + return err + } } tps := make([]*types.FieldType, len(e.UsingVars)) + varsNum := len(e.UsingVars) for i, param := range e.UsingVars { name := param.(*expression.ScalarFunction).GetArgs()[0].String() tps[i] = sctx.GetSessionVars().UserVarTypes[name] @@ -421,7 +472,7 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, // so you don't need to consider whether prepared.useCache is enabled. plan := prepared.CachedPlan.(Plan) names := prepared.CachedNames.(types.NameSlice) - err := e.rebuildRange(plan) + err := e.RebuildPlan(plan) if err != nil { logutil.BgLogger().Debug("rebuild range failed", zap.Error(err)) goto REBUILD @@ -445,9 +496,16 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, if err := e.checkPreparedPriv(ctx, sctx, preparedStmt, is); err != nil { return err } - cachedVals := cacheValue.([]*PSTMTPlanCacheValue) + cachedVals := cacheValue.([]*PlanCacheValue) for _, cachedVal := range cachedVals { - if !cachedVal.UserVarTypes.Equal(tps) { + if cachedVal.BindSQL != bindSQL { + // When BindSQL does not match, it means that we have added a new binding, + // and the original cached plan will be invalid, + // so the original cached plan can be cleared directly + sctx.PreparedPlanCache().Delete(cacheKey) + break + } + if !cachedVal.UserVarTypes.CheckTypesCompatibility4PC(tps) { continue } planValid := true @@ -461,7 +519,7 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, } } if planValid { - err := e.rebuildRange(cachedVal.Plan) + err := e.RebuildPlan(cachedVal.Plan) if err != nil { logutil.BgLogger().Debug("rebuild range failed", zap.Error(err)) goto REBUILD @@ -505,41 +563,59 @@ REBUILD: } e.names = names e.Plan = p - _, isTableDual := p.(*PhysicalTableDual) - if !isTableDual && prepared.UseCache && !stmtCtx.SkipPlanCache { + // We only cache the tableDual plan when the number of vars are zero. + if containTableDual(p) && varsNum > 0 { + stmtCtx.SkipPlanCache = true + } + if prepared.UseCache && !stmtCtx.SkipPlanCache { // rebuild key to exclude kv.TiFlash when stmt is not read only if _, isolationReadContainTiFlash := sessVars.IsolationReadEngines[kv.TiFlash]; isolationReadContainTiFlash && !IsReadOnly(stmt, sessVars) { delete(sessVars.IsolationReadEngines, kv.TiFlash) - cacheKey = NewPSTMTPlanCacheKey(sessVars, e.ExecID, prepared.SchemaVersion, sessVars.StmtCtx.BindSQL) + if cacheKey, err = NewPlanCacheKey(sessVars, preparedStmt.StmtText, preparedStmt.StmtDB, prepared.SchemaVersion); err != nil { + return err + } sessVars.IsolationReadEngines[kv.TiFlash] = struct{}{} - } else { - // We need to reconstruct the plan cache key based on the bindSQL. - cacheKey = NewPSTMTPlanCacheKey(sessVars, e.ExecID, prepared.SchemaVersion, sessVars.StmtCtx.BindSQL) } - cached := NewPSTMTPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan, tps) + cached := NewPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan, tps, sessVars.StmtCtx.BindSQL) preparedStmt.NormalizedPlan, preparedStmt.PlanDigest = NormalizePlan(p) stmtCtx.SetPlanDigest(preparedStmt.NormalizedPlan, preparedStmt.PlanDigest) if cacheVals, exists := sctx.PreparedPlanCache().Get(cacheKey); exists { hitVal := false - for i, cacheVal := range cacheVals.([]*PSTMTPlanCacheValue) { - if cacheVal.UserVarTypes.Equal(tps) { + for i, cacheVal := range cacheVals.([]*PlanCacheValue) { + if cacheVal.UserVarTypes.CheckTypesCompatibility4PC(tps) { hitVal = true - cacheVals.([]*PSTMTPlanCacheValue)[i] = cached + cacheVals.([]*PlanCacheValue)[i] = cached break } } if !hitVal { - cacheVals = append(cacheVals.([]*PSTMTPlanCacheValue), cached) + cacheVals = append(cacheVals.([]*PlanCacheValue), cached) } sctx.PreparedPlanCache().Put(cacheKey, cacheVals) } else { - sctx.PreparedPlanCache().Put(cacheKey, []*PSTMTPlanCacheValue{cached}) + sctx.PreparedPlanCache().Put(cacheKey, []*PlanCacheValue{cached}) } } err = e.setFoundInPlanCache(sctx, false) return err } +func containTableDual(p Plan) bool { + _, isTableDual := p.(*PhysicalTableDual) + if isTableDual { + return true + } + physicalPlan, ok := p.(PhysicalPlan) + if !ok { + return false + } + childContainTableDual := false + for _, child := range physicalPlan.Children() { + childContainTableDual = childContainTableDual || containTableDual(child) + } + return childContainTableDual +} + // tryCachePointPlan will try to cache point execution plan, there may be some // short paths for these executions, currently "point select" and "point update" func (e *Execute) tryCachePointPlan(ctx context.Context, sctx sessionctx.Context, @@ -571,6 +647,14 @@ func (e *Execute) tryCachePointPlan(ctx context.Context, sctx sessionctx.Context return err } +// RebuildPlan will rebuild this plan under current user parameters. +func (e *Execute) RebuildPlan(p Plan) error { + sc := p.SCtx().GetSessionVars().StmtCtx + sc.InPreparedPlanBuilding = true + defer func() { sc.InPreparedPlanBuilding = false }() + return e.rebuildRange(p) +} + func (e *Execute) rebuildRange(p Plan) error { sctx := p.SCtx() sc := p.SCtx().GetSessionVars().StmtCtx @@ -654,18 +738,25 @@ func (e *Execute) rebuildRange(p Plan) error { // TODO: relocate the partition after rebuilding range to make PlanCache support PointGet return errors.New("point get for partition table can not use plan cache") } - if x.HandleParam != nil { - var iv int64 - iv, err = x.HandleParam.Datum.ToInt64(sc) + if x.HandleConstant != nil { + dVal, err := convertConstant2Datum(sc, x.HandleConstant, x.handleFieldType) + if err != nil { + return err + } + iv, err := dVal.ToInt64(sc) if err != nil { return err } x.Handle = kv.IntHandle(iv) return nil } - for i, param := range x.IndexValueParams { + for i, param := range x.IndexConstants { if param != nil { - x.IndexValues[i] = param.Datum + dVal, err := convertConstant2Datum(sc, param, x.ColsFieldType[i]) + if err != nil { + return err + } + x.IndexValues[i] = *dVal } } return nil @@ -708,8 +799,11 @@ func (e *Execute) rebuildRange(p Plan) error { } for i, param := range x.HandleParams { if param != nil { - var iv int64 - iv, err = param.Datum.ToInt64(sc) + dVal, err := convertConstant2Datum(sc, param, x.HandleType) + if err != nil { + return err + } + iv, err := dVal.ToInt64(sc) if err != nil { return err } @@ -722,7 +816,11 @@ func (e *Execute) rebuildRange(p Plan) error { } for j, param := range params { if param != nil { - x.IndexValues[i][j] = param.Datum + dVal, err := convertConstant2Datum(sc, param, x.IndexColTypes[j]) + if err != nil { + return err + } + x.IndexValues[i][j] = *dVal } } } @@ -759,6 +857,23 @@ func (e *Execute) rebuildRange(p Plan) error { return nil } +func convertConstant2Datum(sc *stmtctx.StatementContext, con *expression.Constant, target *types.FieldType) (*types.Datum, error) { + val, err := con.Eval(chunk.Row{}) + if err != nil { + return nil, err + } + dVal, err := val.ConvertTo(sc, target) + if err != nil { + return nil, err + } + // The converted result must be same as original datum. + cmp, err := dVal.Compare(sc, &val, collate.GetCollator(target.Collate)) + if err != nil || cmp != 0 { + return nil, errors.New("Convert constant to datum is failed, because the constant has changed after the covert") + } + return &dVal, nil +} + func (e *Execute) buildRangeForTableScan(sctx sessionctx.Context, ts *PhysicalTableScan) (err error) { if ts.Table.IsCommonHandle { pk := tables.FindPrimaryIndex(ts.Table) @@ -866,6 +981,8 @@ const ( OpEvolveBindings // OpReloadBindings is used to reload plan binding. OpReloadBindings + // OpSetBindingStatus is used to set binding status. + OpSetBindingStatus ) // SQLBindPlan represents a plan for SQL bind. @@ -880,6 +997,7 @@ type SQLBindPlan struct { Db string Charset string Collation string + NewStatus string } // Simple represents a simple statement plan which doesn't need any optimization. @@ -981,6 +1099,16 @@ type AnalyzeInfo struct { TableID statistics.AnalyzeTableID Incremental bool StatsVersion int + V2Options *V2AnalyzeOptions +} + +// V2AnalyzeOptions is used to hold analyze options information. +type V2AnalyzeOptions struct { + PhyTableID int64 + RawOpts map[ast.AnalyzeOptionType]uint64 + FilledOpts map[ast.AnalyzeOptionType]uint64 + ColChoice model.ColumnChoice + ColumnList []*model.ColumnInfo } // AnalyzeColumnsTask is used for analyze columns. @@ -1004,9 +1132,10 @@ type AnalyzeIndexTask struct { type Analyze struct { baseSchemaProducer - ColTasks []AnalyzeColumnsTask - IdxTasks []AnalyzeIndexTask - Opts map[ast.AnalyzeOptionType]uint64 + ColTasks []AnalyzeColumnsTask + IdxTasks []AnalyzeIndexTask + Opts map[ast.AnalyzeOptionType]uint64 + OptionsMap map[int64]V2AnalyzeOptions } // LoadData represents a loaddata plan. @@ -1276,19 +1405,14 @@ func (e *Explain) explainPlanInRowFormat(p Plan, taskType, driverSide, indent st switch x := p.(type) { case *PhysicalTableReader: - var storeType string switch x.StoreType { case kv.TiKV, kv.TiFlash, kv.TiDB: // expected do nothing default: return errors.Errorf("the store type %v is unknown", x.StoreType) } - storeType = x.StoreType.Name() - taskName := "cop" - if x.BatchCop { - taskName = "batchCop" - } - err = e.explainPlanInRowFormat(x.tablePlan, taskName+"["+storeType+"]", "", childIndent, true) + taskName := x.ReadReqType.Name() + "[" + x.StoreType.Name() + "]" + err = e.explainPlanInRowFormat(x.tablePlan, taskName, "", childIndent, true) case *PhysicalIndexReader: err = e.explainPlanInRowFormat(x.indexPlan, "cop[tikv]", "", childIndent, true) case *PhysicalIndexLookUpReader: @@ -1353,7 +1477,7 @@ func getRuntimeInfo(ctx sessionctx.Context, p Plan, runtimeStatsColl *execdetail } copStats := runtimeStatsColl.GetCopStats(explainID) analyzeInfo += copStats.String() - actRows = fmt.Sprint(copStats.GetActRows()) + actRows = strconv.FormatInt(copStats.GetActRows(), 10) } memoryInfo = "N/A" memTracker := ctx.GetSessionVars().StmtCtx.MemTracker.SearchTrackerWithoutLock(p.ID()) diff --git a/planner/core/enforce_mpp_test.go b/planner/core/enforce_mpp_test.go index f9eb265c1313f..fbefb32e815a1 100644 --- a/planner/core/enforce_mpp_test.go +++ b/planner/core/enforce_mpp_test.go @@ -15,50 +15,25 @@ package core_test import ( + "fmt" + "strconv" "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" + plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testEnforceMPPSuite{}) - -type testEnforceMPPSuite struct { - testData testutil.TestData - store kv.Storage - dom *domain.Domain -} - -func (s *testEnforceMPPSuite) SetUpSuite(c *C) { - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "enforce_mpp_suite") - c.Assert(err, IsNil) -} - -func (s *testEnforceMPPSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testEnforceMPPSuite) SetUpTest(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testEnforceMPPSuite) TearDownTest(c *C) { - s.dom.Close() - err := s.store.Close() - c.Assert(err, IsNil) -} - -func (s *testEnforceMPPSuite) TestSetVariables(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSetVariables(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test value limit of tidb_opt_tiflash_concurrency_factor tk.MustExec("set @@tidb_opt_tiflash_concurrency_factor = 0") @@ -67,18 +42,54 @@ func (s *testEnforceMPPSuite) TestSetVariables(c *C) { // test set tidb_enforce_mpp when tidb_allow_mpp=false; err := tk.ExecToErr("set @@tidb_allow_mpp = 0; set @@tidb_enforce_mpp = 1;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, `[variable:1231]Variable 'tidb_enforce_mpp' can't be set to the value of '1' but tidb_allow_mpp is 0, please activate tidb_allow_mpp at first.'`) - + require.EqualError(t, err, `[variable:1231]Variable 'tidb_enforce_mpp' can't be set to the value of '1' but tidb_allow_mpp is 0, please activate tidb_allow_mpp at first.'`) err = tk.ExecToErr("set @@tidb_allow_mpp = 1; set @@tidb_enforce_mpp = 1;") - c.Assert(err, IsNil) - + require.NoError(t, err) err = tk.ExecToErr("set @@tidb_allow_mpp = 0;") - c.Assert(err, IsNil) + require.NoError(t, err) +} + +func TestRowSizeInMPP(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a varchar(10), b varchar(20), c varchar(256))") + tk.MustExec("insert into t values (space(10), space(20), space(256))") + tk.MustExec("analyze table t") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tblInfo := range db.Tables { + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec(`set @@tidb_opt_tiflash_concurrency_factor=1`) + tk.MustExec(`set @@tidb_allow_mpp=1`) + tk.MustExec(`set @@tidb_enforce_mpp=1`) + var costs [3]float64 + for i, col := range []string{"a", "b", "c"} { + rs := tk.MustQuery(fmt.Sprintf(`explain format='verbose' select %v from t`, col)).Rows() + cost, err := strconv.ParseFloat(rs[0][2].(string), 64) + require.NoError(t, err) + costs[i] = cost + } + require.True(t, costs[0] < costs[1] && costs[1] < costs[2]) // rowSize can affect the final cost } -func (s *testEnforceMPPSuite) TestEnforceMPP(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnforceMPP(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test query tk.MustExec("use test") @@ -87,10 +98,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPP(c *C) { tk.MustExec("create index idx on t(a)") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -106,7 +117,8 @@ func (s *testEnforceMPPSuite) TestEnforceMPP(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + enforceMPPSuiteData := plannercore.GetEnforceMPPSuiteData() + enforceMPPSuiteData.GetTestCases(t, &input, &output) filterWarnings := func(originalWarnings []stmtctx.SQLWarn) []stmtctx.SQLWarn { warnings := make([]stmtctx.SQLWarn, 0, 4) for _, warning := range originalWarnings { @@ -118,27 +130,29 @@ func (s *testEnforceMPPSuite) TestEnforceMPP(c *C) { return warnings } for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") { tk.MustExec(tt) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(filterWarnings(tk.Se.GetSessionVars().StmtCtx.GetWarnings())) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(filterWarnings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(filterWarnings(tk.Se.GetSessionVars().StmtCtx.GetWarnings())), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(filterWarnings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))) } } // general cases. -func (s *testEnforceMPPSuite) TestEnforceMPPWarning1(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnforceMPPWarning1(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test query tk.MustExec("use test") @@ -152,9 +166,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning1(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + enforceMPPSuiteData := plannercore.GetEnforceMPPSuiteData() + enforceMPPSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") { @@ -163,10 +178,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning1(c *C) { } if strings.HasPrefix(tt, "cmd: create-replica") { // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -179,10 +194,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning1(c *C) { } if strings.HasPrefix(tt, "cmd: enable-replica") { // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -193,20 +208,22 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning1(c *C) { } continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } // partition table. -func (s *testEnforceMPPSuite) TestEnforceMPPWarning2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnforceMPPWarning2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test query tk.MustExec("use test") @@ -214,10 +231,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning2(c *C) { tk.MustExec("CREATE TABLE t (a int, b char(20)) PARTITION BY HASH(a)") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -233,29 +250,32 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning2(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + enforceMPPSuiteData := plannercore.GetEnforceMPPSuiteData() + enforceMPPSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") { tk.MustExec(tt) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } // new collation. -func (s *testEnforceMPPSuite) TestEnforceMPPWarning3(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnforceMPPWarning3(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test query tk.MustExec("use test") @@ -263,10 +283,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning3(c *C) { tk.MustExec("CREATE TABLE t (a int, b char(20))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -282,9 +302,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning3(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + enforceMPPSuiteData := plannercore.GetEnforceMPPSuiteData() + enforceMPPSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") || strings.HasPrefix(tt, "UPDATE") { @@ -299,20 +320,23 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning3(c *C) { collate.SetNewCollationEnabledForTest(false) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } + collate.SetNewCollationEnabledForTest(true) } // Test enforce mpp warning for joins -func (s *testEnforceMPPSuite) TestEnforceMPPWarning4(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestEnforceMPPWarning4(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) // test table tk.MustExec("use test") @@ -322,10 +346,10 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning4(c *C) { tk.MustExec("CREATE TABLE s(a int primary key)") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" || tblInfo.Name.L == "s" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -341,22 +365,23 @@ func (s *testEnforceMPPSuite) TestEnforceMPPWarning4(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + enforceMPPSuiteData := plannercore.GetEnforceMPPSuiteData() + enforceMPPSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") || strings.HasPrefix(tt, "UPDATE") { tk.MustExec(tt) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } diff --git a/planner/core/errors.go b/planner/core/errors.go index 6670d64d0b1fd..7182702e9d06a 100644 --- a/planner/core/errors.go +++ b/planner/core/errors.go @@ -108,4 +108,5 @@ var ( ErrPartitionNoTemporary = dbterror.ClassOptimizer.NewStd(mysql.ErrPartitionNoTemporary) ErrViewSelectTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrViewSelectTmptable) ErrSubqueryMoreThan1Row = dbterror.ClassOptimizer.NewStd(mysql.ErrSubqueryNo1Row) + ErrKeyPart0 = dbterror.ClassOptimizer.NewStd(mysql.ErrKeyPart0) ) diff --git a/planner/core/errors_test.go b/planner/core/errors_test.go index b5afcbc616cb5..0eb26d2ed2702 100644 --- a/planner/core/errors_test.go +++ b/planner/core/errors_test.go @@ -15,16 +15,14 @@ package core import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" + "github.com/stretchr/testify/require" ) -type testErrorSuite struct{} - -var _ = Suite(testErrorSuite{}) - -func (s testErrorSuite) TestError(c *C) { +func TestError(t *testing.T) { kvErrs := []*terror.Error{ ErrUnsupportedType, ErrAnalyzeMissIndex, @@ -84,9 +82,10 @@ func (s testErrorSuite) TestError(c *C) { ErrCartesianProductUnsupported, ErrStmtNotFound, ErrAmbiguous, + ErrKeyPart0, } for _, err := range kvErrs { code := terror.ToSQLError(err).Code - c.Assert(code != mysql.ErrUnknown && code == uint16(err.Code()), IsTrue, Commentf("err: %v", err)) + require.Truef(t, code != mysql.ErrUnknown && code == uint16(err.Code()), "err: %v", err) } } diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index db9c16e722d78..a510ae89fccd7 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/planner/util" @@ -51,7 +52,6 @@ func (p *LogicalUnionScan) exhaustPhysicalPlans(prop *property.PhysicalProperty) us := PhysicalUnionScan{ Conditions: p.conditions, HandleCols: p.handleCols, - CacheTable: p.cacheTable, }.Init(p.ctx, p.stats, p.blockOffset, childProp) return []PhysicalPlan{us}, true, nil } @@ -287,14 +287,16 @@ func (p *LogicalJoin) getEnforcedMergeJoin(prop *property.PhysicalProperty, sche return nil } for _, item := range prop.SortItems { - isExist := false + isExist, hasLeftColInProp, hasRightColInProp := false, false, false for joinKeyPos := 0; joinKeyPos < len(leftJoinKeys); joinKeyPos++ { var key *expression.Column if item.Col.Equal(p.ctx, leftJoinKeys[joinKeyPos]) { key = leftJoinKeys[joinKeyPos] + hasLeftColInProp = true } if item.Col.Equal(p.ctx, rightJoinKeys[joinKeyPos]) { key = rightJoinKeys[joinKeyPos] + hasRightColInProp = true } if key == nil { continue @@ -314,6 +316,13 @@ func (p *LogicalJoin) getEnforcedMergeJoin(prop *property.PhysicalProperty, sche if !isExist { return nil } + // If the output wants the order of the inner side. We should reject it since we might add null-extend rows of that side. + if p.JoinType == LeftOuterJoin && hasRightColInProp { + return nil + } + if p.JoinType == RightOuterJoin && hasLeftColInProp { + return nil + } } // Generate the enforced sort merge join leftKeys := getNewJoinKeysByOffsets(leftJoinKeys, offsets) @@ -948,6 +957,8 @@ func (p *LogicalJoin) constructInnerTableScanTask( Desc: desc, physicalTableID: ds.physicalTableID, isPartition: ds.isPartition, + + underInnerIndexJoin: true, }.Init(ds.ctx, ds.blockOffset) ts.SetSchema(ds.schema.Clone()) if rowCount <= 0 { @@ -987,6 +998,7 @@ func (p *LogicalJoin) constructInnerTableScanTask( Columns: ds.TblCols, ColumnNames: ds.names, } + ts.PartitionInfo = copTask.partitionInfo selStats := ts.stats.Scale(selectivity) ts.addPushedDownSelection(copTask, selStats) t := copTask.convertToRootTask(ds.ctx) @@ -1043,6 +1055,8 @@ func (p *LogicalJoin) constructInnerIndexScanTask( Desc: desc, isPartition: ds.isPartition, physicalTableID: ds.physicalTableID, + + underInnerIndexJoin: true, }.Init(ds.ctx, ds.blockOffset) cop := &copTask{ indexPlan: is, @@ -1801,12 +1815,6 @@ func (p *LogicalJoin) exhaustPhysicalPlans(prop *property.PhysicalProperty) ([]P mppJoins := p.tryToGetMppHashJoin(prop, false) joins = append(joins, mppJoins...) } - } else if p.ctx.GetSessionVars().AllowBCJ && canPushToTiFlash { - broadCastJoins := p.tryToGetBroadCastJoin(prop) - if (p.preferJoinType & preferBCJoin) > 0 { - return broadCastJoins, true, nil - } - joins = append(joins, broadCastJoins...) } if prop.IsFlashProp() { return joins, true, nil @@ -1870,7 +1878,12 @@ func (p *LogicalJoin) tryToGetMppHashJoin(prop *property.PhysicalProperty, useBC return nil } - if p.JoinType != InnerJoin && p.JoinType != LeftOuterJoin && p.JoinType != RightOuterJoin && p.JoinType != SemiJoin && p.JoinType != AntiSemiJoin { + if !expression.IsPushDownEnabled(p.JoinType.String(), kv.TiFlash) { + p.SCtx().GetSessionVars().RaiseWarningWhenMPPEnforced("MPP mode may be blocked because join type `" + p.JoinType.String() + "` is blocked by blacklist, check `table mysql.expr_pushdown_blacklist;` for more information.") + return nil + } + + if p.JoinType != InnerJoin && p.JoinType != LeftOuterJoin && p.JoinType != RightOuterJoin && p.JoinType != SemiJoin && p.JoinType != AntiSemiJoin && p.JoinType != LeftOuterSemiJoin && p.JoinType != AntiLeftOuterSemiJoin { p.SCtx().GetSessionVars().RaiseWarningWhenMPPEnforced("MPP mode may be blocked because join type `" + p.JoinType.String() + "` is not supported now.") return nil } @@ -1918,13 +1931,13 @@ func (p *LogicalJoin) tryToGetMppHashJoin(prop *property.PhysicalProperty, useBC if p.children[0].statsInfo().Count() > p.children[1].statsInfo().Count() { preferredBuildIndex = 1 } - } else if p.JoinType == SemiJoin || p.JoinType == AntiSemiJoin { + } else if p.JoinType.IsSemiJoin() { preferredBuildIndex = 1 } if p.JoinType == LeftOuterJoin || p.JoinType == RightOuterJoin { - // TiFlash does not requires that the build side must be the inner table for outer join - // so we can choose the build side based on the row count, except that - // 1. it is a broadcast join(for broadcast join, it make sense to use the broadcast side as the build side) + // TiFlash does not require that the build side must be the inner table for outer join. + // so we can choose the build side based on the row count, except that: + // 1. it is a broadcast join(for broadcast join, it makes sense to use the broadcast side as the build side) // 2. or session variable MPPOuterJoinFixedBuildSide is set to true // 3. or there are otherConditions for this join if useBCJ || p.ctx.GetSessionVars().MPPOuterJoinFixedBuildSide || len(p.OtherConditions) > 0 { @@ -1996,6 +2009,7 @@ func (p *LogicalJoin) tryToGetMppHashJoin(prop *property.PhysicalProperty, useBC mppShuffleJoin: !useBCJ, // Mpp Join has quite heavy cost. Even limit might not suspend it in time, so we dont scale the count. }.Init(p.ctx, p.stats, p.blockOffset, childrenProps...) + join.SetSchema(p.schema) return []PhysicalPlan{join} } @@ -2007,99 +2021,6 @@ func choosePartitionKeys(keys []*property.MPPPartitionColumn, matches []int) []* return newKeys } -func (p *LogicalJoin) tryToGetBroadCastJoin(prop *property.PhysicalProperty) []PhysicalPlan { - if !prop.IsEmpty() { - return nil - } - if prop.TaskTp != property.RootTaskType && !prop.IsFlashProp() { - return nil - } - if !canExprsInJoinPushdown(p, kv.TiFlash) { - return nil - } - - // Disable broadcast join on partition table for TiFlash. - for _, child := range p.children { - if ds, isDataSource := child.(*DataSource); isDataSource { - if ds.tableInfo.GetPartitionInfo() != nil { - return nil - } - } - } - - if (p.JoinType != InnerJoin && p.JoinType != LeftOuterJoin && p.JoinType != RightOuterJoin && p.JoinType != SemiJoin && p.JoinType != AntiSemiJoin) || len(p.EqualConditions) == 0 { - return nil - } - - // for left/semi/anti-semi join the global idx must be 1, and for right join the global idx must be 0 - if hasPrefer, idx := p.getPreferredBCJLocalIndex(); hasPrefer { - if (idx == 0 && p.JoinType == RightOuterJoin) || (idx == 1 && (p.JoinType == LeftOuterJoin || p.JoinType == SemiJoin || p.JoinType == AntiSemiJoin)) { - return nil - } - return p.tryToGetBroadCastJoinByPreferGlobalIdx(prop, 1-idx) - } - if p.JoinType == InnerJoin { - results := p.tryToGetBroadCastJoinByPreferGlobalIdx(prop, 0) - results = append(results, p.tryToGetBroadCastJoinByPreferGlobalIdx(prop, 1)...) - return results - } else if p.JoinType == LeftOuterJoin || p.JoinType == SemiJoin || p.JoinType == AntiSemiJoin { - return p.tryToGetBroadCastJoinByPreferGlobalIdx(prop, 1) - } - return p.tryToGetBroadCastJoinByPreferGlobalIdx(prop, 0) -} - -func (p *LogicalJoin) tryToGetBroadCastJoinByPreferGlobalIdx(prop *property.PhysicalProperty, preferredGlobalIndex int) []PhysicalPlan { - lkeys, rkeys, _, _ := p.GetJoinKeys() - baseJoin := basePhysicalJoin{ - JoinType: p.JoinType, - LeftConditions: p.LeftConditions, - RightConditions: p.RightConditions, - OtherConditions: p.OtherConditions, - DefaultValues: p.DefaultValues, - LeftJoinKeys: lkeys, - RightJoinKeys: rkeys, - } - - preferredBuildIndex := 0 - if p.children[0].statsInfo().Count() > p.children[1].statsInfo().Count() { - preferredBuildIndex = 1 - } - if p.JoinType == SemiJoin || p.JoinType == AntiSemiJoin { - preferredBuildIndex = 1 - } - // TiFlash does not support Right out join with other conditions, if the join - // has other conditions, need to set the build side to make sure it will be - // executed as left join in TiFlash(In TiFlash the build side is always the right side) - if len(p.OtherConditions) != 0 { - if p.JoinType == RightOuterJoin { - preferredBuildIndex = 0 - } else if p.JoinType == LeftOuterJoin { - preferredBuildIndex = 1 - } - } - baseJoin.InnerChildIdx = preferredBuildIndex - childrenReqProps := make([]*property.PhysicalProperty, 2) - childrenReqProps[preferredGlobalIndex] = &property.PhysicalProperty{TaskTp: property.CopTiFlashGlobalReadTaskType, ExpectedCnt: math.MaxFloat64} - if prop.TaskTp == property.CopTiFlashGlobalReadTaskType { - childrenReqProps[1-preferredGlobalIndex] = &property.PhysicalProperty{TaskTp: property.CopTiFlashGlobalReadTaskType, ExpectedCnt: math.MaxFloat64} - } else { - childrenReqProps[1-preferredGlobalIndex] = &property.PhysicalProperty{TaskTp: property.CopTiFlashLocalReadTaskType, ExpectedCnt: math.MaxFloat64} - } - if prop.ExpectedCnt < p.stats.RowCount { - expCntScale := prop.ExpectedCnt / p.stats.RowCount - childrenReqProps[1-baseJoin.InnerChildIdx].ExpectedCnt = p.children[1-baseJoin.InnerChildIdx].statsInfo().RowCount * expCntScale - } - - join := PhysicalHashJoin{ - basePhysicalJoin: baseJoin, - Concurrency: uint(p.ctx.GetSessionVars().CopTiFlashConcurrencyFactor), - EqualConditions: p.EqualConditions, - storeTp: kv.TiFlash, - globalChildIndex: preferredGlobalIndex, - }.Init(p.ctx, p.stats.ScaleByExpectCnt(prop.ExpectedCnt), p.blockOffset, childrenReqProps...) - return []PhysicalPlan{join} -} - // TryToGetChildProp will check if this sort property can be pushed or not. // When a sort column will be replaced by scalar function, we refuse it. // When a sort column will be replaced by a constant, we just remove it. @@ -2349,6 +2270,13 @@ func (p *baseLogicalPlan) canPushToCopImpl(storeTp kv.StoreType, considerDual bo if (isTopN || isLimit) && considerIndexMerge { return false // TopN and Limit cannot be pushed down to IndexMerge } + if c.tableInfo.TableCacheStatusType != model.TableCacheStatusDisable { + // Don't push to cop for cached table, it brings more harm than good: + // 1. Those tables are small enough, push to cop can't utilize several TiKV to accelerate computation. + // 2. Cached table use UnionScan to read the cache data, and push to cop is not supported when an UnionScan exists. + // Once aggregation is pushed to cop, the cache data can't be use any more. + return false + } case *LogicalUnionAll: if storeTp == kv.TiFlash { ret = ret && c.canPushToCopImpl(storeTp, true) @@ -2490,7 +2418,7 @@ func (la *LogicalAggregation) getStreamAggs(prop *property.PhysicalProperty) []P } else if !la.aggHints.preferAggToCop { taskTypes = append(taskTypes, property.RootTaskType) } - if !la.canPushToCop(kv.TiKV) { + if !la.canPushToCop(kv.TiKV) && !la.canPushToCop(kv.TiFlash) { taskTypes = []property.TaskType{property.RootTaskType} } for _, taskTp := range taskTypes { @@ -2611,9 +2539,6 @@ func (la *LogicalAggregation) getHashAggs(prop *property.PhysicalProperty) []Phy } hashAggs := make([]PhysicalPlan, 0, len(prop.GetAllPossibleChildTaskTypes())) taskTypes := []property.TaskType{property.CopSingleReadTaskType, property.CopDoubleReadTaskType} - if la.ctx.GetSessionVars().AllowBCJ { - taskTypes = append(taskTypes, property.CopTiFlashLocalReadTaskType) - } canPushDownToTiFlash := la.canPushToCop(kv.TiFlash) canPushDownToMPP := canPushDownToTiFlash && la.ctx.GetSessionVars().IsMPPAllowed() && la.checkCanPushDownToMPP() if la.HasDistinct() { @@ -2624,11 +2549,8 @@ func (la *LogicalAggregation) getHashAggs(prop *property.PhysicalProperty) []Phy } else if !la.aggHints.preferAggToCop { taskTypes = append(taskTypes, property.RootTaskType) } - if !la.canPushToCop(kv.TiKV) { + if !la.canPushToCop(kv.TiKV) && !canPushDownToTiFlash { taskTypes = []property.TaskType{property.RootTaskType} - if canPushDownToTiFlash { - taskTypes = append(taskTypes, property.CopTiFlashLocalReadTaskType) - } } if canPushDownToMPP { taskTypes = append(taskTypes, property.MppTaskType) @@ -2740,10 +2662,9 @@ func (p *LogicalLock) exhaustPhysicalPlans(prop *property.PhysicalProperty) ([]P } childProp := prop.CloneEssentialFields() lock := PhysicalLock{ - Lock: p.Lock, - TblID2Handle: p.tblID2Handle, - PartitionedTable: p.partitionedTable, - ExtraPIDInfo: p.extraPIDInfo, + Lock: p.Lock, + TblID2Handle: p.tblID2Handle, + TblID2PhysTblIDCol: p.tblID2PhysTblIDCol, }.Init(p.ctx, p.stats.ScaleByExpectCnt(prop.ExpectedCnt), childProp) return []PhysicalPlan{lock}, true, nil } diff --git a/planner/core/explain.go b/planner/core/explain.go index 26bfa775fc417..3f70804c055d5 100644 --- a/planner/core/explain.go +++ b/planner/core/explain.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -289,8 +290,8 @@ func (p *PhysicalTableScan) OperatorInfo(normalized bool) string { if p.stats.StatsVersion == statistics.PseudoVersion && !normalized { buffer.WriteString(", stats:pseudo") } - if p.IsGlobalRead { - buffer.WriteString(", global read") + if p.StoreType == kv.TiFlash && p.Table.GetPartitionInfo() != nil && p.IsMPPOrBatchCop && p.ctx.GetSessionVars().UseDynamicPartitionPrune() { + buffer.WriteString(", PartitionTableScan:true") } return buffer.String() } @@ -431,7 +432,7 @@ func (p *PhysicalIndexReader) ExplainInfo() string { // ExplainNormalizedInfo implements Plan interface. func (p *PhysicalIndexReader) ExplainNormalizedInfo() string { - return p.ExplainInfo() + return "index:" + p.indexPlan.TP() } func (p *PhysicalIndexReader) accessObject(sctx sessionctx.Context) string { @@ -456,17 +457,22 @@ func (p *PhysicalIndexReader) accessObject(sctx sessionctx.Context) string { // ExplainInfo implements Plan interface. func (p *PhysicalIndexLookUpReader) ExplainInfo() string { + var str strings.Builder // The children can be inferred by the relation symbol. if p.PushedLimit != nil { - var str strings.Builder str.WriteString("limit embedded(offset:") str.WriteString(strconv.FormatUint(p.PushedLimit.Offset, 10)) str.WriteString(", count:") str.WriteString(strconv.FormatUint(p.PushedLimit.Count, 10)) str.WriteString(")") - return str.String() } - return "" + if p.Paging { + if p.PushedLimit != nil { + str.WriteString(", ") + } + str.WriteString("paging:true") + } + return str.String() } func (p *PhysicalIndexLookUpReader) accessObject(sctx sessionctx.Context) string { diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go index d6f446de63732..427a0633aa9ba 100644 --- a/planner/core/expression_rewriter.go +++ b/planner/core/expression_rewriter.go @@ -37,7 +37,6 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" - "github.com/pingcap/tidb/telemetry" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" "github.com/pingcap/tidb/util/chunk" @@ -89,6 +88,7 @@ func (b *PlanBuilder) rewriteInsertOnDuplicateUpdate(ctx context.Context, exprNo b.rewriterCounter++ defer func() { b.rewriterCounter-- }() + b.curClause = fieldList rewriter := b.getExpressionRewriter(ctx, mockPlan) // The rewriter maybe is obtained from "b.rewriterPool", "rewriter.err" is // not nil means certain previous procedure has not handled this error. @@ -325,6 +325,10 @@ func (er *expressionRewriter) buildSubquery(ctx context.Context, subq *ast.Subqu er.b.outerNames = er.b.outerNames[0 : len(er.b.outerNames)-1] }() } + outerWindowSpecs := er.b.windowSpecs + defer func() { + er.b.windowSpecs = outerWindowSpecs + }() np, err := er.b.buildResultSetNode(ctx, subq.Query) if err != nil { @@ -509,7 +513,7 @@ func (er *expressionRewriter) handleCompareSubquery(ctx context.Context, v *ast. lexpr := er.ctxStack[len(er.ctxStack)-1] subq, ok := v.R.(*ast.SubqueryExpr) if !ok { - er.err = errors.Errorf("Unknown compare type %T.", v.R) + er.err = errors.Errorf("Unknown compare type %T", v.R) return v, true } np, err := er.buildSubquery(ctx, subq) @@ -792,7 +796,7 @@ func (er *expressionRewriter) handleExistSubquery(ctx context.Context, v *ast.Ex defer resetCTECheckForSubQuery(ci) subq, ok := v.Sel.(*ast.SubqueryExpr) if !ok { - er.err = errors.Errorf("Unknown exists type %T.", v.Sel) + er.err = errors.Errorf("Unknown exists type %T", v.Sel) return v, true } np, err := er.buildSubquery(ctx, subq) @@ -866,7 +870,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte lexpr := er.ctxStack[len(er.ctxStack)-1] subq, ok := v.Sel.(*ast.SubqueryExpr) if !ok { - er.err = errors.Errorf("Unknown compare type %T.", v.Sel) + er.err = errors.Errorf("Unknown compare type %T", v.Sel) return v, true } np, err := er.buildSubquery(ctx, subq) @@ -1070,7 +1074,7 @@ func (er *expressionRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok er.ctxStackAppend(value, types.EmptyName) case *driver.ParamMarkerExpr: var value expression.Expression - value, er.err = expression.ParamMarkerExpression(er.sctx, v) + value, er.err = expression.ParamMarkerExpression(er.sctx, v, false) if er.err != nil { return retNode, false } @@ -1220,13 +1224,13 @@ func (er *expressionRewriter) newFunction(funcName string, retType *types.FieldT return } if scalarFunc, ok := ret.(*expression.ScalarFunction); ok { - telemetry.BuiltinFunctionsUsage(er.b.ctx.GetBuiltinFunctionUsage()).Inc(scalarFunc.Function.PbCode().String()) + er.b.ctx.BuiltinFunctionUsageInc(scalarFunc.Function.PbCode().String()) } return } func (er *expressionRewriter) checkTimePrecision(ft *types.FieldType) error { - if ft.EvalType() == types.ETDuration && ft.Decimal > int(types.MaxFsp) { + if ft.EvalType() == types.ETDuration && ft.Decimal > types.MaxFsp { return errTooBigPrecision.GenWithStackByArgs(ft.Decimal, "CAST", types.MaxFsp) } return nil @@ -1287,7 +1291,7 @@ func (er *expressionRewriter) rewriteVariable(v *ast.VariableExpr) { er.b.visitInfo = appendDynamicVisitInfo(er.b.visitInfo, "RESTRICTED_VARIABLES_ADMIN", false, err) } if v.ExplicitScope && !sysVar.HasNoneScope() { - if v.IsGlobal && !sysVar.HasGlobalScope() { + if v.IsGlobal && !(sysVar.HasGlobalScope() || sysVar.HasInstanceScope()) { er.err = variable.ErrIncorrectScope.GenWithStackByArgs(name, "SESSION") return } @@ -1488,6 +1492,12 @@ func (er *expressionRewriter) inToExpression(lLen int, not bool, tp *types.Field if allSameType && l == 1 && lLen > 1 { function = er.notToExpression(not, ast.In, tp, er.ctxStack[stkLen-lLen-1:]...) } else { + // If we rewrite IN to EQ, we need to decide what's the collation EQ uses. + coll := er.deriveCollationForIn(l, lLen, stkLen, args) + if er.err != nil { + return + } + er.castCollationForIn(l, lLen, stkLen, coll) eqFunctions := make([]expression.Expression, 0, lLen) for i := stkLen - lLen; i < stkLen; i++ { expr, err := er.constructBinaryOpFunction(args[0], er.ctxStack[i], ast.EQ) @@ -1511,6 +1521,53 @@ func (er *expressionRewriter) inToExpression(lLen int, not bool, tp *types.Field er.ctxStackAppend(function, types.EmptyName) } +// deriveCollationForIn derives collation for in expression. +// We don't handle the cases if the element is a tuple, such as (a, b, c) in ((x1, y1, z1), (x2, y2, z2)). +func (er *expressionRewriter) deriveCollationForIn(colLen int, elemCnt int, stkLen int, args []expression.Expression) *expression.ExprCollation { + if colLen == 1 { + // a in (x, y, z) => coll[0] + coll2, err := expression.CheckAndDeriveCollationFromExprs(er.sctx, "IN", types.ETInt, args...) + er.err = err + if er.err != nil { + return nil + } + return coll2 + } + return nil +} + +// castCollationForIn casts collation info for arguments in the `in clause` to make sure the used collation is correct after we +// rewrite it to equal expression. +func (er *expressionRewriter) castCollationForIn(colLen int, elemCnt int, stkLen int, coll *expression.ExprCollation) { + // We don't handle the cases if the element is a tuple, such as (a, b, c) in ((x1, y1, z1), (x2, y2, z2)). + if colLen != 1 { + return + } + for i := stkLen - elemCnt; i < stkLen; i++ { + if er.ctxStack[i].GetType().EvalType() == types.ETString { + rowFunc, ok := er.ctxStack[i].(*expression.ScalarFunction) + if ok && rowFunc.FuncName.String() == ast.RowFunc { + continue + } + // Don't convert it if it's charset is binary. So that we don't convert 0x12 to a string. + if er.ctxStack[i].GetType().Collate == coll.Collation { + continue + } + tp := er.ctxStack[i].GetType().Clone() + if er.ctxStack[i].GetType().Hybrid() { + if expression.GetAccurateCmpType(er.ctxStack[stkLen-elemCnt-1], er.ctxStack[i]) == types.ETString { + tp = types.NewFieldType(mysql.TypeVarString) + } else { + continue + } + } + tp.Charset, tp.Collate = coll.Charset, coll.Collation + er.ctxStack[i] = expression.BuildCastFunction(er.sctx, er.ctxStack[i], tp) + er.ctxStack[i].SetCoercibility(expression.CoercibilityExplicit) + } + } +} + func (er *expressionRewriter) caseToExpression(v *ast.CaseExpr) { stkLen := len(er.ctxStack) argsLen := 2 * len(v.WhenClauses) @@ -1686,9 +1743,14 @@ func (er *expressionRewriter) betweenToExpression(v *ast.BetweenExpr) { return } - expr = expression.BuildCastCollationFunction(er.sctx, expr, coll) - lexp = expression.BuildCastCollationFunction(er.sctx, lexp, coll) - rexp = expression.BuildCastCollationFunction(er.sctx, rexp, coll) + // Handle enum or set. We need to know their real type to decide whether to cast them. + lt := expression.GetAccurateCmpType(expr, lexp) + rt := expression.GetAccurateCmpType(expr, rexp) + enumOrSetRealTypeIsStr := lt != types.ETInt && rt != types.ETInt + + expr = expression.BuildCastCollationFunction(er.sctx, expr, coll, enumOrSetRealTypeIsStr) + lexp = expression.BuildCastCollationFunction(er.sctx, lexp, coll, enumOrSetRealTypeIsStr) + rexp = expression.BuildCastCollationFunction(er.sctx, rexp, coll, enumOrSetRealTypeIsStr) var l, r expression.Expression l, er.err = expression.NewFunction(er.sctx, ast.GE, &v.Type, expr, lexp) @@ -1951,15 +2013,14 @@ func (er *expressionRewriter) evalDefaultExpr(v *ast.DefaultExpr) { isCurrentTimestamp := hasCurrentDatetimeDefault(col) var val *expression.Constant switch { - case isCurrentTimestamp && col.Tp == mysql.TypeDatetime: - // for DATETIME column with current_timestamp, use NULL to be compatible with MySQL 5.7 - val = expression.NewNull() - case isCurrentTimestamp && col.Tp == mysql.TypeTimestamp: - // for TIMESTAMP column with current_timestamp, use 0 to be compatible with MySQL 5.7 - zero := types.NewTime(types.ZeroCoreTime, mysql.TypeTimestamp, int8(col.Decimal)) + case isCurrentTimestamp && (col.Tp == mysql.TypeDatetime || col.Tp == mysql.TypeTimestamp): + t, err := expression.GetTimeValue(er.sctx, ast.CurrentTimestamp, col.Tp, col.Decimal) + if err != nil { + return + } val = &expression.Constant{ - Value: types.NewDatum(zero), - RetType: types.NewFieldType(mysql.TypeTimestamp), + Value: t, + RetType: types.NewFieldType(col.Tp), } default: // for other columns, just use what it is @@ -1981,9 +2042,10 @@ func hasCurrentDatetimeDefault(col *table.Column) bool { } func decodeKeyFromString(ctx sessionctx.Context, s string) string { + sc := ctx.GetSessionVars().StmtCtx key, err := hex.DecodeString(s) if err != nil { - ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("invalid record/index key: %X", key)) + sc.AppendWarning(errors.Errorf("invalid key: %X", key)) return s } // Auto decode byte if needed. @@ -1993,39 +2055,44 @@ func decodeKeyFromString(ctx sessionctx.Context, s string) string { } tableID := tablecodec.DecodeTableID(key) if tableID == 0 { - ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("invalid record/index key: %X", key)) + sc.AppendWarning(errors.Errorf("invalid key: %X", key)) return s } dm := domain.GetDomain(ctx) if dm == nil { - ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("domain not found when decoding record/index key: %X", key)) + sc.AppendWarning(errors.Errorf("domain not found when decoding key: %X", key)) + return s + } + is := dm.InfoSchema() + if is == nil { + sc.AppendWarning(errors.Errorf("infoschema not found when decoding key: %X", key)) return s } - tbl, _ := dm.InfoSchema().TableByID(tableID) + tbl, _ := is.TableByID(tableID) loc := ctx.GetSessionVars().Location() if tablecodec.IsRecordKey(key) { ret, err := decodeRecordKey(key, tableID, tbl, loc) if err != nil { - ctx.GetSessionVars().StmtCtx.AppendWarning(err) + sc.AppendWarning(err) return s } return ret } else if tablecodec.IsIndexKey(key) { ret, err := decodeIndexKey(key, tableID, tbl, loc) if err != nil { - ctx.GetSessionVars().StmtCtx.AppendWarning(err) + sc.AppendWarning(err) return s } return ret } else if tablecodec.IsTableKey(key) { - ret, err := decodeTableKey(key, tableID, tbl, loc) + ret, err := decodeTableKey(key, tableID) if err != nil { - ctx.GetSessionVars().StmtCtx.AppendWarning(err) + sc.AppendWarning(err) return s } return ret } - ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("invalid record/index key: %X", key)) + sc.AppendWarning(errors.Errorf("invalid key: %X", key)) return s } @@ -2038,7 +2105,7 @@ func decodeRecordKey(key []byte, tableID int64, tbl table.Table, loc *time.Locat ret := make(map[string]interface{}) ret["table_id"] = strconv.FormatInt(tableID, 10) // When the clustered index is enabled, we should show the PK name. - if tbl.Meta().HasClusteredIndex() { + if tbl != nil && tbl.Meta().HasClusteredIndex() { ret[tbl.Meta().GetPkName().String()] = handle.IntValue() } else { ret["_tidb_rowid"] = handle.IntValue() @@ -2173,7 +2240,7 @@ func decodeIndexKey(key []byte, tableID int64, tbl table.Table, loc *time.Locati return string(retStr), nil } -func decodeTableKey(key []byte, tableID int64, tbl table.Table, loc *time.Location) (string, error) { +func decodeTableKey(key []byte, tableID int64) (string, error) { ret := map[string]int64{"table_id": tableID} retStr, err := json.Marshal(ret) if err != nil { diff --git a/planner/core/expression_rewriter_test.go b/planner/core/expression_rewriter_test.go index a26c85cbce50d..ee5f20d3f824c 100644 --- a/planner/core/expression_rewriter_test.go +++ b/planner/core/expression_rewriter_test.go @@ -15,53 +15,29 @@ package core_test import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/planner/core" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testExpressionRewriterSuite{}) -var _ = SerialSuites(&testExpressionRewriterSuiteSerial{}) - -type testExpressionRewriterSuite struct { - testData testutil.TestData -} - -func (s *testExpressionRewriterSuite) SetUpSuite(c *C) { - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "expression_rewriter_suite") - c.Assert(err, IsNil) -} - -func (s *testExpressionRewriterSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -type testExpressionRewriterSuiteSerial struct { -} - -func (s *testExpressionRewriterSuite) TestIfNullEliminateColName(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIfNullEliminateColName(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null, b int not null)") rs, err := tk.Exec("select ifnull(a,b) from t") - c.Assert(err, IsNil) + require.NoError(t, err) fields := rs.Fields() - c.Assert(fields[0].Column.Name.L, Equals, "ifnull(a,b)") - c.Assert(rs.Close(), IsNil) + require.Greater(t, len(fields), 0) + require.Equal(t, "ifnull(a,b)", rs.Fields()[0].Column.Name.L) + require.NoError(t, rs.Close()) tk.MustExec("drop table if exists t") tk.MustExec("create table t(e int not null, b int)") @@ -74,15 +50,10 @@ func (s *testExpressionRewriterSuite) TestIfNullEliminateColName(c *C) { rows.Check(testkit.Rows("1")) } -func (s *testExpressionRewriterSuite) TestBinaryOpFunction(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestBinaryOpFunction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE t(a int, b int, c int);") @@ -91,15 +62,10 @@ func (s *testExpressionRewriterSuite) TestBinaryOpFunction(c *C) { tk.MustQuery("SELECT * FROM t WHERE (a,b,c) > (1,2,3) order by b").Check(testkit.Rows("1 3 ")) } -func (s *testExpressionRewriterSuite) TestDefaultFunction(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestDefaultFunction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec(`create table t1( @@ -110,6 +76,10 @@ func (s *testExpressionRewriterSuite) TestDefaultFunction(c *C) { e datetime default '20180101', f datetime default current_timestamp);`) tk.MustExec("insert into t1(a, b, c, d) values ('1', '1', 1, 1)") + tk.MustExec("set @@timestamp = 1321009871") + defer tk.MustExec("set @@timestamp = DEFAULT") + tk.MustExec("set @@time_zone = '+00:00'") + defer tk.MustExec("set @@time_zone = DEFAULT") tk.MustQuery(`select default(a) as defa, default(b) as defb, @@ -117,18 +87,16 @@ func (s *testExpressionRewriterSuite) TestDefaultFunction(c *C) { default(d) as defd, default(e) as defe, default(f) as deff - from t1`).Check(testutil.RowsWithSep("|", "def||10|3.14|2018-01-01 00:00:00|")) - err = tk.ExecToErr("select default(x) from t1") - c.Assert(err.Error(), Equals, "[planner:1054]Unknown column 'x' in 'field list'") + from t1`).Check(testkit.RowsWithSep("|", "def||10|3.14|2018-01-01 00:00:00|2011-11-11 11:11:11")) + require.EqualError(t, tk.ExecToErr("select default(x) from t1"), "[planner:1054]Unknown column 'x' in 'field list'") tk.MustQuery("select default(a0) from (select a as a0 from t1) as t0").Check(testkit.Rows("def")) - err = tk.ExecToErr("select default(a0) from (select a+1 as a0 from t1) as t0") - c.Assert(err.Error(), Equals, "[table:1364]Field 'a0' doesn't have a default value") + require.EqualError(t, tk.ExecToErr("select default(a0) from (select a+1 as a0 from t1) as t0"), "[table:1364]Field 'a0' doesn't have a default value") tk.MustExec("create table t2(a varchar(10), b varchar(10))") tk.MustExec("insert into t2 values ('1', '1')") - err = tk.ExecToErr("select default(a) from t1, t2") - c.Assert(err.Error(), Equals, "[expression:1052]Column 'a' in field list is ambiguous") + require.EqualError(t, tk.ExecToErr("select default(a) from t1, t2"), "[expression:1052]Column 'a' in field list is ambiguous") + tk.MustQuery("select default(t1.a) from t1, t2").Check(testkit.Rows("def")) tk.MustExec(`create table t3( @@ -142,7 +110,7 @@ func (s *testExpressionRewriterSuite) TestDefaultFunction(c *C) { default(b) as defb, default(c) as defc, default(d) as defd - from t3`).Check(testutil.RowsWithSep("|", "|0000-00-00 00:00:00|0000-00-00 00:00:00.000000|current_timestamp")) + from t3`).Check(testkit.RowsWithSep("|", "2011-11-11 11:11:11|2011-11-11 11:11:11|2011-11-11 11:11:11.000000|current_timestamp")) tk.MustExec(`create table t4(a int default 1, b varchar(5))`) tk.MustExec(`insert into t4 values (0, 'B'), (1, 'B'), (2, 'B')`) @@ -176,15 +144,10 @@ func (s *testExpressionRewriterSuite) TestDefaultFunction(c *C) { tk.MustQuery(`select a from t8 order by default(b) * a`).Check(testkit.Rows("1", "0")) } -func (s *testExpressionRewriterSuite) TestCompareSubquery(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestCompareSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists s") @@ -279,32 +242,22 @@ func (s *testExpressionRewriterSuite) TestCompareSubquery(c *C) { tk.MustQuery("select count(1) from table_40_utf8_4 where ( select count(1) from t where table_40_utf8_4.col_bit64_key_signed!=table_40_utf8_4.col_tinyint_key_unsigned)").Check(testkit.Rows("1")) } -func (s *testExpressionRewriterSuite) TestCheckFullGroupBy(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestCheckFullGroupBy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustQuery("select t1.a, (select max(t2.b) from t t2) from t t1").Check(testkit.Rows()) - err = tk.ExecToErr("select t1.a, (select t2.a, max(t2.b) from t t2) from t t1") - c.Assert(terror.ErrorEqual(err, core.ErrMixOfGroupFuncAndFields), IsTrue, Commentf("err %v", err)) + err := tk.ExecToErr("select t1.a, (select t2.a, max(t2.b) from t t2) from t t1") + require.True(t, terror.ErrorEqual(err, plannercore.ErrMixOfGroupFuncAndFields)) } -func (s *testExpressionRewriterSuite) TestPatternLikeToExpression(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestPatternLikeToExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustQuery("select 0 like 'a string';").Check(testkit.Rows("0")) tk.MustQuery("select 0.0 like 'a string';").Check(testkit.Rows("0")) tk.MustQuery("select 0 like '0.00';").Check(testkit.Rows("0")) @@ -314,16 +267,10 @@ func (s *testExpressionRewriterSuite) TestPatternLikeToExpression(c *C) { tk.MustQuery("select 0.00 like '0.00';").Check(testkit.Rows("1")) } -func (s *testExpressionRewriterSuite) TestIssue20007(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestIssue20007(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1, t2;") tk.MustExec("create table t1 (c_int int, c_str varchar(40), c_datetime datetime, primary key(c_int));") @@ -337,16 +284,10 @@ func (s *testExpressionRewriterSuite) TestIssue20007(c *C) { } } -func (s *testExpressionRewriterSuite) TestIssue9869(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestIssue9869(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(a int, b bigint unsigned);") @@ -355,33 +296,21 @@ func (s *testExpressionRewriterSuite) TestIssue9869(c *C) { testkit.Rows("4572794622775114594 4572794622775114594", "18196094287899841997 -250649785809709619", "11120436154190595086 -7326307919518956530")) } -func (s *testExpressionRewriterSuite) TestIssue17652(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestIssue17652(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(x bigint unsigned);") tk.MustExec("insert into t values( 9999999703771440633);") - tk.MustQuery("select ifnull(max(x), 0) from t").Check( - testkit.Rows("9999999703771440633")) + tk.MustQuery("select ifnull(max(x), 0) from t").Check(testkit.Rows("9999999703771440633")) } -func (s *testExpressionRewriterSuite) TestCompareMultiFieldsInSubquery(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestCompareMultiFieldsInSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1, t2, t3, t4;") tk.MustExec("CREATE TABLE t1(c1 int, c2 int);") @@ -404,58 +333,35 @@ func (s *testExpressionRewriterSuite) TestCompareMultiFieldsInSubquery(c *C) { tk.MustExec("INSERT INTO t4 VALUES (1, 2);") tk.MustQuery("SELECT * FROM t3 WHERE (SELECT c1 FROM t3 LIMIT 1) != ALL(SELECT c1 FROM t4);").Check(testkit.Rows()) tk.MustQuery("SELECT * FROM t3 WHERE (SELECT c1, c2 FROM t3 LIMIT 1) != ALL(SELECT c1, c2 FROM t4);").Check(testkit.Rows()) - } -func (s *testExpressionRewriterSuite) TestIssue22818(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestIssue22818(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a time);") tk.MustExec("insert into t values(\"23:22:22\");") - tk.MustQuery("select * from t where a between \"23:22:22\" and \"23:22:22\"").Check( - testkit.Rows("23:22:22")) + tk.MustQuery("select * from t where a between \"23:22:22\" and \"23:22:22\"").Check(testkit.Rows("23:22:22")) } -func (s *testExpressionRewriterSuite) TestIssue24705(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestIssue24705(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1,t2;") tk.MustExec("create table t1 (c_int int, c_str varchar(40) character set utf8 collate utf8_general_ci);") tk.MustExec("create table t2 (c_int int, c_str varchar(40) character set utf8 collate utf8_unicode_ci);") - err = tk.ExecToErr("select * from t1 where c_str < any (select c_str from t2 where c_int between 6 and 9);") - c.Assert(err.Error(), Equals, "[expression:1267]Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '<'") + err := tk.ExecToErr("select * from t1 where c_str < any (select c_str from t2 where c_int between 6 and 9);") + require.EqualError(t, err, "[expression:1267]Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '<'") } -func (s *testExpressionRewriterSuiteSerial) TestBetweenExprCollation(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestBetweenExprCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("create table t1(a char(10) charset latin1 collate latin1_bin, c char(10) collate utf8mb4_general_ci);") @@ -463,20 +369,13 @@ func (s *testExpressionRewriterSuiteSerial) TestBetweenExprCollation(c *C) { tk.MustExec("insert into t1 values ('c', 'D');") tk.MustQuery("select * from t1 where a between 'B' and c;").Check(testkit.Rows("c D")) tk.MustQuery("explain select * from t1 where 'a' between 'g' and 'f';").Check(testkit.Rows("TableDual_6 0.00 root rows:0")) - tk.MustGetErrMsg("select * from t1 where a between 'B' collate utf8mb4_general_ci and c collate utf8mb4_unicode_ci;", "[expression:1270]Illegal mix of collations (latin1_bin,IMPLICIT), (utf8mb4_general_ci,EXPLICIT), (utf8mb4_unicode_ci,EXPLICIT) for operation 'BETWEEN'") } -func (s *testExpressionRewriterSuite) TestInsertOnDuplicateLazyMoreThan1Row(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestInsertOnDuplicateLazyMoreThan1Row(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("DROP TABLE if exists t1, t2, source;") tk.MustExec("CREATE TABLE t1(a INTEGER PRIMARY KEY);") @@ -492,15 +391,10 @@ func (s *testExpressionRewriterSuite) TestInsertOnDuplicateLazyMoreThan1Row(c *C tk.MustExec("DROP TABLE if exists t1, t2, source;") } -func (s *testExpressionRewriterSuite) TestMultiColInExpression(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestMultiColInExpression(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int)") @@ -515,12 +409,13 @@ func (s *testExpressionRewriterSuite) TestMultiColInExpression(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + expressionRewriterSuiteData := plannercore.GetExpressionRewriterSuiteData() + expressionRewriterSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) diff --git a/planner/core/expression_test.go b/planner/core/expression_test.go index 0b207b7141c80..7b9214e2f4d08 100644 --- a/planner/core/expression_test.go +++ b/planner/core/expression_test.go @@ -22,7 +22,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/testkit/trequire" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" ) @@ -124,13 +124,13 @@ func TestCast(t *testing.T) { f.Charset = charset.CharsetBin v, err = evalAstExpr(ctx, expr) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum([]byte("1")), v) + testutil.DatumEqual(t, types.NewDatum([]byte("1")), v) f.Tp = mysql.TypeString f.Charset = charset.CharsetUTF8 v, err = evalAstExpr(ctx, expr) require.NoError(t, err) - trequire.DatumEqual(t, types.NewDatum([]byte("1")), v) + testutil.DatumEqual(t, types.NewDatum([]byte("1")), v) expr.Expr = ast.NewValueExpr(nil, "", "") v, err = evalAstExpr(ctx, expr) diff --git a/planner/core/find_best_task.go b/planner/core/find_best_task.go index 166d3adc298b3..22348e0ee0462 100644 --- a/planner/core/find_best_task.go +++ b/planner/core/find_best_task.go @@ -28,6 +28,7 @@ import ( "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/types" tidbutil "github.com/pingcap/tidb/util" @@ -36,6 +37,7 @@ import ( "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/set" + "github.com/pingcap/tidb/util/tracing" "go.uber.org/zap" ) @@ -135,7 +137,7 @@ func GetPropByOrderByItemsContainScalarFunc(items []*util.ByItems) (*property.Ph return &property.PhysicalProperty{SortItems: propItems}, true, onlyColumn } -func (p *LogicalTableDual) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (task, int64, error) { +func (p *LogicalTableDual) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (task, int64, error) { // If the required property is not empty and the row count > 1, // we cannot ensure this required property. // But if the row count is 0 or 1, we don't need to care about the property. @@ -150,17 +152,17 @@ func (p *LogicalTableDual) findBestTask(prop *property.PhysicalProperty, planCou return &rootTask{p: dual, isEmpty: p.RowCount == 0}, 1, nil } -func (p *LogicalShow) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (task, int64, error) { +func (p *LogicalShow) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (task, int64, error) { if !prop.IsEmpty() || planCounter.Empty() { return invalidTask, 0, nil } - pShow := PhysicalShow{ShowContents: p.ShowContents}.Init(p.ctx) + pShow := PhysicalShow{ShowContents: p.ShowContents, Extractor: p.Extractor}.Init(p.ctx) pShow.SetSchema(p.schema) planCounter.Dec(1) return &rootTask{p: pShow}, 1, nil } -func (p *LogicalShowDDLJobs) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (task, int64, error) { +func (p *LogicalShowDDLJobs) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (task, int64, error) { if !prop.IsEmpty() || planCounter.Empty() { return invalidTask, 0, nil } @@ -171,7 +173,7 @@ func (p *LogicalShowDDLJobs) findBestTask(prop *property.PhysicalProperty, planC } // rebuildChildTasks rebuilds the childTasks to make the clock_th combination. -func (p *baseLogicalPlan) rebuildChildTasks(childTasks *[]task, pp PhysicalPlan, childCnts []int64, planCounter int64, TS uint64) error { +func (p *baseLogicalPlan) rebuildChildTasks(childTasks *[]task, pp PhysicalPlan, childCnts []int64, planCounter int64, TS uint64, opt *physicalOptimizeOp) error { // The taskMap of children nodes should be rolled back first. for _, child := range p.children { child.rollBackTaskMap(TS) @@ -186,7 +188,7 @@ func (p *baseLogicalPlan) rebuildChildTasks(childTasks *[]task, pp PhysicalPlan, for j, child := range p.children { multAll /= childCnts[j] curClock = PlanCounterTp((planCounter-1)/multAll + 1) - childTask, _, err := child.findBestTask(pp.GetChildReqProps(j), &curClock) + childTask, _, err := child.findBestTask(pp.GetChildReqProps(j), &curClock, opt) planCounter = (planCounter-1)%multAll + 1 if err != nil { return err @@ -195,20 +197,21 @@ func (p *baseLogicalPlan) rebuildChildTasks(childTasks *[]task, pp PhysicalPlan, return errors.Errorf("PlanCounterTp planCounter is not handled") } if childTask != nil && childTask.invalid() { - return errors.Errorf("The current plan is invalid, please skip this plan.") + return errors.Errorf("The current plan is invalid, please skip this plan") } *childTasks = append(*childTasks, childTask) } return nil } -func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPlan, prop *property.PhysicalProperty, addEnforcer bool, planCounter *PlanCounterTp) (task, int64, error) { +func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPlan, prop *property.PhysicalProperty, addEnforcer bool, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (task, int64, error) { var bestTask task = invalidTask var curCntPlan, cntPlan int64 childTasks := make([]task, 0, len(p.children)) childCnts := make([]int64, len(p.children)) cntPlan = 0 for _, pp := range physicalPlans { + // Find best child tasks firstly. childTasks = childTasks[:0] // The curCntPlan records the number of possible plans for pp @@ -216,7 +219,8 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl TimeStampNow := p.GetLogicalTS4TaskMap() savedPlanID := p.ctx.GetSessionVars().PlanID for j, child := range p.children { - childTask, cnt, err := child.findBestTask(pp.GetChildReqProps(j), &PlanCounterDisabled) + childProp := pp.GetChildReqProps(j) + childTask, cnt, err := child.findBestTask(childProp, &PlanCounterDisabled, opt) childCnts[j] = cnt if err != nil { return nil, 0, err @@ -237,7 +241,7 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl if planCounter.IsForce() && int64(*planCounter) <= curCntPlan { p.ctx.GetSessionVars().PlanID = savedPlanID curCntPlan = int64(*planCounter) - err := p.rebuildChildTasks(&childTasks, pp, childCnts, int64(*planCounter), TimeStampNow) + err := p.rebuildChildTasks(&childTasks, pp, childCnts, int64(*planCounter), TimeStampNow, opt) if err != nil { return nil, 0, err } @@ -273,6 +277,7 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl bestTask = curTask break } + opt.appendCandidate(p, curTask.plan(), prop) // Get the most efficient one. if curTask.cost() < bestTask.cost() || (bestTask.invalid() && !curTask.invalid()) { bestTask = curTask @@ -281,8 +286,48 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl return bestTask, cntPlan, nil } +type physicalOptimizeOp struct { + // tracer is goring to track optimize steps during physical optimizing + tracer *tracing.PhysicalOptimizeTracer +} + +func defaultPhysicalOptimizeOption() *physicalOptimizeOp { + return &physicalOptimizeOp{} +} + +func (op *physicalOptimizeOp) withEnableOptimizeTracer(tracer *tracing.PhysicalOptimizeTracer) *physicalOptimizeOp { + op.tracer = tracer + return op +} + +func (op *physicalOptimizeOp) buildPhysicalOptimizeTraceInfo(p LogicalPlan) { + if op == nil || op.tracer == nil { + return + } + name := tracing.CodecPlanName(p.TP(), p.ID()) + if _, ok := op.tracer.State[name]; !ok { + op.tracer.State[name] = make(map[string]*tracing.PlanTrace) + } +} + +func (op *physicalOptimizeOp) appendCandidate(lp LogicalPlan, pp PhysicalPlan, prop *property.PhysicalProperty) { + if op == nil || op.tracer == nil || pp == nil { + return + } + PhysicalPlanTrace := &tracing.PlanTrace{TP: pp.TP(), ID: pp.ID(), + ExplainInfo: pp.ExplainInfo(), Cost: pp.Cost(), ProperType: prop.String()} + name := tracing.CodecPlanName(lp.TP(), lp.ID()) + key := tracing.CodecPlanName(pp.TP(), pp.ID()) + pps := op.tracer.State[name] + if pps == nil { + op.buildPhysicalOptimizeTraceInfo(lp) + } + pps[key] = PhysicalPlanTrace + op.tracer.State[name] = pps +} + // findBestTask implements LogicalPlan interface. -func (p *baseLogicalPlan) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (bestTask task, cntPlan int64, err error) { +func (p *baseLogicalPlan) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (bestTask task, cntPlan int64, err error) { // If p is an inner plan in an IndexJoin, the IndexJoin will generate an inner plan by itself, // and set inner child prop nil, so here we do nothing. if prop == nil { @@ -352,7 +397,8 @@ func (p *baseLogicalPlan) findBestTask(prop *property.PhysicalProperty, planCoun var cnt int64 var curTask task - if bestTask, cnt, err = p.enumeratePhysicalPlans4Task(plansFitsProp, newProp, false, planCounter); err != nil { + opt.buildPhysicalOptimizeTraceInfo(p) + if bestTask, cnt, err = p.enumeratePhysicalPlans4Task(plansFitsProp, newProp, false, planCounter, opt); err != nil { return nil, 0, err } cntPlan += cnt @@ -360,7 +406,7 @@ func (p *baseLogicalPlan) findBestTask(prop *property.PhysicalProperty, planCoun goto END } - curTask, cnt, err = p.enumeratePhysicalPlans4Task(plansNeedEnforce, newProp, true, planCounter) + curTask, cnt, err = p.enumeratePhysicalPlans4Task(plansNeedEnforce, newProp, true, planCounter, opt) if err != nil { return nil, 0, err } @@ -369,6 +415,7 @@ func (p *baseLogicalPlan) findBestTask(prop *property.PhysicalProperty, planCoun bestTask = curTask goto END } + opt.appendCandidate(p, curTask.plan(), prop) if curTask.cost() < bestTask.cost() || (bestTask.invalid() && !curTask.invalid()) { bestTask = curTask } @@ -378,7 +425,7 @@ END: return bestTask, cntPlan, nil } -func (p *LogicalMemTable) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (t task, cntPlan int64, err error) { +func (p *LogicalMemTable) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (t task, cntPlan int64, err error) { if !prop.IsEmpty() || planCounter.Empty() { return invalidTask, 0, nil } @@ -449,12 +496,12 @@ func compareIndexBack(lhs, rhs *candidatePath) (int, bool) { // If `x` is not worse than `y` at all factors, // and there exists one factor that `x` is better than `y`, then `x` is better than `y`. func compareCandidates(lhs, rhs *candidatePath) int { - accessResult, comparable := util.CompareCol2Len(lhs.accessCondsColMap, rhs.accessCondsColMap) - if !comparable { + accessResult, comparable1 := util.CompareCol2Len(lhs.accessCondsColMap, rhs.accessCondsColMap) + if !comparable1 { return 0 } - scanResult, comparable := compareIndexBack(lhs, rhs) - if !comparable { + scanResult, comparable2 := compareIndexBack(lhs, rhs) + if !comparable2 { return 0 } matchResult := compareBool(lhs.isMatchProp, rhs.isMatchProp) @@ -558,21 +605,7 @@ func (ds *DataSource) skylinePruning(prop *property.PhysicalProperty) []*candida } var currentCandidate *candidatePath if path.IsTablePath() { - if path.StoreType == kv.TiFlash { - if path.IsTiFlashGlobalRead && prop.TaskTp == property.CopTiFlashGlobalReadTaskType { - currentCandidate = ds.getTableCandidate(path, prop) - } - if !path.IsTiFlashGlobalRead && prop.TaskTp != property.CopTiFlashGlobalReadTaskType { - currentCandidate = ds.getTableCandidate(path, prop) - } - } else { - if !path.IsTiFlashGlobalRead && !prop.IsFlashProp() { - currentCandidate = ds.getTableCandidate(path, prop) - } - } - if currentCandidate == nil { - continue - } + currentCandidate = ds.getTableCandidate(path, prop) } else { if len(path.AccessConds) > 0 || !prop.IsEmpty() || path.Forced || path.IsSingleScan { // We will use index to generate physical plan if any of the following conditions is satisfied: @@ -678,6 +711,10 @@ func (ds *DataSource) getPruningInfo(candidates []*candidatePath, prop *property func (ds *DataSource) isPointGetConvertableSchema() bool { for _, col := range ds.Columns { + if col.Name.L == model.ExtraHandleName.L { + continue + } + // Only handle tables that all columns are public. if col.State != model.StatePublic { return false @@ -688,7 +725,7 @@ func (ds *DataSource) isPointGetConvertableSchema() bool { // findBestTask implements the PhysicalPlan interface. // It will enumerate all the available indices and choose a plan with least cost. -func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (t task, cntPlan int64, err error) { +func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (t task, cntPlan int64, err error) { // If ds is an inner plan in an IndexJoin, the IndexJoin will generate an inner plan by itself, // and set inner child prop nil, so here we do nothing. if prop == nil { @@ -709,7 +746,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter if prop.CanAddEnforcer { // First, get the bestTask without enforced prop prop.CanAddEnforcer = false - t, cnt, err = ds.findBestTask(prop, planCounter) + t, cnt, err = ds.findBestTask(prop, planCounter, opt) if err != nil { return nil, 0, err } @@ -761,11 +798,12 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter } }() + opt.buildPhysicalOptimizeTraceInfo(ds) cntPlan = 0 for _, candidate := range candidates { path := candidate.path if path.PartialIndexPaths != nil { - idxMergeTask, err := ds.convertToIndexMergeScan(prop, candidate) + idxMergeTask, err := ds.convertToIndexMergeScan(prop, candidate, opt) if err != nil { return nil, 0, err } @@ -773,6 +811,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter cntPlan += 1 planCounter.Dec(1) } + appendCandidate(ds, idxMergeTask, prop, opt) if idxMergeTask.cost() < t.cost() || planCounter.Empty() { t = idxMergeTask } @@ -852,10 +891,11 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter if allRangeIsPoint { var pointGetTask task if len(path.Ranges) == 1 { - pointGetTask = ds.convertToPointGet(prop, candidate) + pointGetTask = ds.convertToPointGet(prop, candidate, opt) } else { - pointGetTask = ds.convertToBatchPointGet(prop, candidate, hashPartColName) + pointGetTask = ds.convertToBatchPointGet(prop, candidate, hashPartColName, opt) } + appendCandidate(ds, pointGetTask, prop, opt) if !pointGetTask.invalid() { cntPlan += 1 planCounter.Dec(1) @@ -878,9 +918,9 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter } var tblTask task if ds.SampleInfo != nil { - tblTask, err = ds.convertToSampleTable(prop, candidate) + tblTask, err = ds.convertToSampleTable(prop, candidate, opt) } else { - tblTask, err = ds.convertToTableScan(prop, candidate) + tblTask, err = ds.convertToTableScan(prop, candidate, opt) } if err != nil { return nil, 0, err @@ -889,6 +929,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter cntPlan += 1 planCounter.Dec(1) } + appendCandidate(ds, tblTask, prop, opt) if tblTask.cost() < t.cost() || planCounter.Empty() { t = tblTask } @@ -901,7 +942,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter if ds.preferStoreType&preferTiFlash != 0 { continue } - idxTask, err := ds.convertToIndexScan(prop, candidate) + idxTask, err := ds.convertToIndexScan(prop, candidate, opt) if err != nil { return nil, 0, err } @@ -909,6 +950,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter cntPlan += 1 planCounter.Dec(1) } + appendCandidate(ds, idxTask, prop, opt) if idxTask.cost() < t.cost() || planCounter.Empty() { t = idxTask } @@ -941,7 +983,7 @@ func (ds *DataSource) canConvertToPointGetForPlanCache(path *util.AccessPath) bo return false } -func (ds *DataSource) convertToIndexMergeScan(prop *property.PhysicalProperty, candidate *candidatePath) (task task, err error) { +func (ds *DataSource) convertToIndexMergeScan(prop *property.PhysicalProperty, candidate *candidatePath, opt *physicalOptimizeOp) (task task, err error) { if prop.TaskTp != property.RootTaskType || !prop.IsEmpty() { return invalidTask, nil } @@ -973,7 +1015,7 @@ func (ds *DataSource) convertToIndexMergeScan(prop *property.PhysicalProperty, c if prop.ExpectedCnt < ds.stats.RowCount { totalRowCount *= prop.ExpectedCnt / ds.stats.RowCount } - ts, partialCost, err := ds.buildIndexMergeTableScan(prop, path.TableFilters, totalRowCount) + ts, partialCost, remainingFilters, err := ds.buildIndexMergeTableScan(prop, path.TableFilters, totalRowCount) if err != nil { return nil, err } @@ -981,6 +1023,9 @@ func (ds *DataSource) convertToIndexMergeScan(prop *property.PhysicalProperty, c cop.tablePlan = ts cop.idxMergePartPlans = scans cop.cst = totalCost + if remainingFilters != nil { + cop.rootTaskConds = remainingFilters + } task = cop.convertToRootTask(ds.ctx) ds.addSelection4PlanCache(task.(*rootTask), ds.tableStats.ScaleByExpectCnt(totalRowCount), prop) return task, nil @@ -1092,8 +1137,10 @@ func setIndexMergeTableScanHandleCols(ds *DataSource, ts *PhysicalTableScan) (er return } +// buildIndexMergeTableScan() returns Selection that will be pushed to TiKV. +// Filters that cannot be pushed to TiKV are also returned, and an extra Selection above IndexMergeReader will be constructed later. func (ds *DataSource) buildIndexMergeTableScan(prop *property.PhysicalProperty, tableFilters []expression.Expression, - totalRowCount float64) (PhysicalPlan, float64, error) { + totalRowCount float64) (PhysicalPlan, float64, []expression.Expression, error) { var partialCost float64 sessVars := ds.ctx.GetSessionVars() ts := PhysicalTableScan{ @@ -1108,7 +1155,7 @@ func (ds *DataSource) buildIndexMergeTableScan(prop *property.PhysicalProperty, ts.SetSchema(ds.schema.Clone()) err := setIndexMergeTableScanHandleCols(ds, ts) if err != nil { - return nil, 0, err + return nil, 0, nil, err } if ts.Table.PKIsHandle { if pkColInfo := ts.Table.GetPkColInfo(); pkColInfo != nil { @@ -1124,17 +1171,44 @@ func (ds *DataSource) buildIndexMergeTableScan(prop *property.PhysicalProperty, ts.stats.StatsVersion = statistics.PseudoVersion } if len(tableFilters) > 0 { - partialCost += totalRowCount * sessVars.CopCPUFactor - selectivity, _, err := ds.tableStats.HistColl.Selectivity(ds.ctx, tableFilters, nil) - if err != nil { - logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err)) - selectivity = SelectionFactor + pushedFilters, remainingFilters := extractFiltersForIndexMerge(sessVars.StmtCtx, ds.ctx.GetClient(), tableFilters) + pushedFilters1, remainingFilters1 := SplitSelCondsWithVirtualColumn(pushedFilters) + pushedFilters = pushedFilters1 + remainingFilters = append(remainingFilters, remainingFilters1...) + if len(pushedFilters) != 0 { + partialCost += totalRowCount * sessVars.CopCPUFactor + selectivity, _, err := ds.tableStats.HistColl.Selectivity(ds.ctx, pushedFilters, nil) + if err != nil { + logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err)) + selectivity = SelectionFactor + } + sel := PhysicalSelection{Conditions: pushedFilters}.Init(ts.ctx, ts.stats.ScaleByExpectCnt(selectivity*totalRowCount), ts.blockOffset) + sel.SetChildren(ts) + return sel, partialCost, remainingFilters, nil + } + return ts, partialCost, remainingFilters, nil + } + return ts, partialCost, nil, nil +} + +// extractFiltersForIndexMerge returns: +// `pushed`: exprs that can be pushed to TiKV. +// `remaining`: exprs that can NOT be pushed to TiKV but can be pushed to other storage engines. +// Why do we need this func? +// IndexMerge only works on TiKV, so we need to find all exprs that cannot be pushed to TiKV, and add a new Selection above IndexMergeReader. +// But the new Selection should exclude the exprs that can NOT be pushed to ALL the storage engines. +// Because these exprs have already been put in another Selection(check rule_predicate_push_down). +func extractFiltersForIndexMerge(sc *stmtctx.StatementContext, client kv.Client, filters []expression.Expression) (pushed []expression.Expression, remaining []expression.Expression) { + for _, expr := range filters { + if expression.CanExprsPushDown(sc, []expression.Expression{expr}, client, kv.TiKV) { + pushed = append(pushed, expr) + continue + } + if expression.CanExprsPushDown(sc, []expression.Expression{expr}, client, kv.UnSpecified) { + remaining = append(remaining, expr) } - sel := PhysicalSelection{Conditions: tableFilters}.Init(ts.ctx, ts.stats.ScaleByExpectCnt(selectivity*totalRowCount), ts.blockOffset) - sel.SetChildren(ts) - return sel, partialCost, nil } - return ts, partialCost, nil + return } func indexCoveringCol(col *expression.Column, indexCols []*expression.Column, idxColLens []int) bool { @@ -1197,7 +1271,8 @@ func (ds *DataSource) addSelection4PlanCache(task *rootTask, stats *property.Sta } // convertToIndexScan converts the DataSource to index scan with idx. -func (ds *DataSource) convertToIndexScan(prop *property.PhysicalProperty, candidate *candidatePath) (task task, err error) { +func (ds *DataSource) convertToIndexScan(prop *property.PhysicalProperty, + candidate *candidatePath, opt *physicalOptimizeOp) (task task, err error) { if !candidate.path.IsSingleScan { // If it's parent requires single read task, return max cost. if prop.TaskTp == property.CopSingleReadTaskType { @@ -1216,6 +1291,7 @@ func (ds *DataSource) convertToIndexScan(prop *property.PhysicalProperty, candid indexPlan: is, tblColHists: ds.TblColHists, tblCols: ds.TblCols, + expectCnt: uint64(prop.ExpectedCnt), } cop.partitionInfo = PartitionInfo{ PruningConds: ds.allConds, @@ -1409,15 +1485,15 @@ func (is *PhysicalIndexScan) addPushedDownSelection(copTask *copTask, p *DataSou } // SplitSelCondsWithVirtualColumn filter the select conditions which contain virtual column -func SplitSelCondsWithVirtualColumn(conds []expression.Expression) ([]expression.Expression, []expression.Expression) { - var filterConds []expression.Expression - for i := len(conds) - 1; i >= 0; i-- { +func SplitSelCondsWithVirtualColumn(conds []expression.Expression) (withoutVirt []expression.Expression, withVirt []expression.Expression) { + for i := range conds { if expression.ContainVirtualColumn(conds[i : i+1]) { - filterConds = append(filterConds, conds[i]) - conds = append(conds[:i], conds[i+1:]...) + withVirt = append(withVirt, conds[i]) + } else { + withoutVirt = append(withoutVirt, conds[i]) } } - return conds, filterConds + return withoutVirt, withVirt } func matchIndicesProp(idxCols []*expression.Column, colLens []int, propItems []property.SortItem) bool { @@ -1702,7 +1778,7 @@ func (s *LogicalIndexScan) GetPhysicalIndexScan(schema *expression.Schema, stats } // convertToTableScan converts the DataSource to table scan. -func (ds *DataSource) convertToTableScan(prop *property.PhysicalProperty, candidate *candidatePath) (task task, err error) { +func (ds *DataSource) convertToTableScan(prop *property.PhysicalProperty, candidate *candidatePath, opt *physicalOptimizeOp) (task task, err error) { // It will be handled in convertToIndexScan. if prop.TaskTp == property.CopDoubleReadTaskType { return invalidTask, nil @@ -1779,7 +1855,8 @@ func (ds *DataSource) convertToTableScan(prop *property.PhysicalProperty, candid return task, nil } -func (ds *DataSource) convertToSampleTable(prop *property.PhysicalProperty, candidate *candidatePath) (task task, err error) { +func (ds *DataSource) convertToSampleTable(prop *property.PhysicalProperty, + candidate *candidatePath, opt *physicalOptimizeOp) (task task, err error) { if prop.TaskTp == property.CopDoubleReadTaskType { return invalidTask, nil } @@ -1803,7 +1880,7 @@ func (ds *DataSource) convertToSampleTable(prop *property.PhysicalProperty, cand }, nil } -func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candidate *candidatePath) task { +func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candidate *candidatePath, opt *physicalOptimizeOp) (task task) { if !prop.IsEmpty() && !candidate.isMatchProp { return invalidTask } @@ -1887,7 +1964,8 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida return rTsk } -func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, candidate *candidatePath, hashPartColName *ast.ColumnName) task { +func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, + candidate *candidatePath, hashPartColName *ast.ColumnName, opt *physicalOptimizeOp) (task task) { if !prop.IsEmpty() && !candidate.isMatchProp { return invalidTask } @@ -2018,7 +2096,6 @@ func (ds *DataSource) getOriginalPhysicalTableScan(prop *property.PhysicalProper Ranges: path.Ranges, AccessCondition: path.AccessConds, StoreType: path.StoreType, - IsGlobalRead: path.IsTiFlashGlobalRead, }.Init(ds.ctx, ds.blockOffset) ts.filterCondition = make([]expression.Expression, len(path.TableFilters)) copy(ts.filterCondition, path.TableFilters) @@ -2068,9 +2145,6 @@ func (ds *DataSource) getOriginalPhysicalTableScan(prop *property.PhysicalProper } sessVars := ds.ctx.GetSessionVars() cost := rowCount * rowSize * sessVars.GetScanFactor(ds.tableInfo) - if ts.IsGlobalRead { - cost += rowCount * sessVars.GetNetworkFactor(ds.tableInfo) * rowSize - } if isMatchProp { ts.Desc = prop.SortItems[0].Desc if prop.SortItems[0].Desc && prop.ExpectedCnt >= smallScanThreshold { @@ -2078,12 +2152,6 @@ func (ds *DataSource) getOriginalPhysicalTableScan(prop *property.PhysicalProper } ts.KeepOrder = true } - switch ts.StoreType { - case kv.TiKV: - cost += float64(len(ts.Ranges)) * sessVars.GetSeekFactor(ds.tableInfo) - case kv.TiFlash: - cost += float64(len(ts.Ranges)) * float64(len(ts.Columns)) * sessVars.GetSeekFactor(ds.tableInfo) - } return ts, cost, rowCount } @@ -2130,12 +2198,11 @@ func (ds *DataSource) getOriginalPhysicalIndexScan(prop *property.PhysicalProper } is.KeepOrder = true } - cost += float64(len(is.Ranges)) * sessVars.GetSeekFactor(ds.tableInfo) is.cost = cost return is, cost, rowCount } -func (p *LogicalCTE) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (t task, cntPlan int64, err error) { +func (p *LogicalCTE) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (t task, cntPlan int64, err error) { if !prop.IsEmpty() && !prop.CanAddEnforcer { return invalidTask, 1, nil } @@ -2153,7 +2220,7 @@ func (p *LogicalCTE) findBestTask(prop *property.PhysicalProperty, planCounter * return t, 1, nil } -func (p *LogicalCTETable) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (t task, cntPlan int64, err error) { +func (p *LogicalCTETable) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (t task, cntPlan int64, err error) { if !prop.IsEmpty() { return nil, 1, nil } @@ -2163,3 +2230,10 @@ func (p *LogicalCTETable) findBestTask(prop *property.PhysicalProperty, planCoun t = &rootTask{p: pcteTable} return t, 1, nil } + +func appendCandidate(lp LogicalPlan, task task, prop *property.PhysicalProperty, opt *physicalOptimizeOp) { + if task == nil || task.invalid() { + return + } + opt.appendCandidate(lp, task.plan(), prop) +} diff --git a/planner/core/find_best_task_test.go b/planner/core/find_best_task_test.go index 893f20bc93442..f2cf02abfa133 100644 --- a/planner/core/find_best_task_test.go +++ b/planner/core/find_best_task_test.go @@ -34,7 +34,7 @@ func (ds mockDataSource) Init(ctx sessionctx.Context) *mockDataSource { return &ds } -func (ds *mockDataSource) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (task, int64, error) { +func (ds *mockDataSource) findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, opt *physicalOptimizeOp) (task, int64, error) { // It can satisfy any of the property! // Just use a TableDual for convenience. p := PhysicalTableDual{}.Init(ds.ctx, &property.StatsInfo{RowCount: 1}, 0) @@ -144,7 +144,7 @@ func TestCostOverflow(t *testing.T) { mockPlan.SetChildren(mockDS) // An empty property is enough for this test. prop := property.NewPhysicalProperty(property.RootTaskType, nil, false, 0, false) - task, _, err := mockPlan.findBestTask(prop, &PlanCounterDisabled) + task, _, err := mockPlan.findBestTask(prop, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) // The cost should be overflowed, but the task shouldn't be invalid. require.False(t, task.invalid()) @@ -171,7 +171,7 @@ func TestEnforcedProperty(t *testing.T) { CanAddEnforcer: false, } // should return invalid task because no physical plan can match this property. - task, _, err := mockPlan.findBestTask(prop0, &PlanCounterDisabled) + task, _, err := mockPlan.findBestTask(prop0, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.True(t, task.invalid()) @@ -180,7 +180,7 @@ func TestEnforcedProperty(t *testing.T) { CanAddEnforcer: true, } // should return the valid task when the property is enforced. - task, _, err = mockPlan.findBestTask(prop1, &PlanCounterDisabled) + task, _, err = mockPlan.findBestTask(prop1, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.False(t, task.invalid()) } @@ -203,7 +203,7 @@ func TestHintCannotFitProperty(t *testing.T) { SortItems: items, CanAddEnforcer: true, } - task, _, err := mockPlan0.findBestTask(prop0, &PlanCounterDisabled) + task, _, err := mockPlan0.findBestTask(prop0, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.False(t, task.invalid()) _, enforcedSort := task.plan().(*PhysicalSort) @@ -219,7 +219,7 @@ func TestHintCannotFitProperty(t *testing.T) { SortItems: items, CanAddEnforcer: false, } - task, _, err = mockPlan0.findBestTask(prop1, &PlanCounterDisabled) + task, _, err = mockPlan0.findBestTask(prop1, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.False(t, task.invalid()) _, enforcedSort = task.plan().(*PhysicalSort) @@ -240,7 +240,7 @@ func TestHintCannotFitProperty(t *testing.T) { canGeneratePlan2: false, }.Init(ctx) mockPlan1.SetChildren(mockDS) - task, _, err = mockPlan1.findBestTask(prop2, &PlanCounterDisabled) + task, _, err = mockPlan1.findBestTask(prop2, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.False(t, task.invalid()) require.Equal(t, uint16(1), ctx.GetSessionVars().StmtCtx.WarningCount()) @@ -256,7 +256,7 @@ func TestHintCannotFitProperty(t *testing.T) { SortItems: items, CanAddEnforcer: true, } - task, _, err = mockPlan1.findBestTask(prop3, &PlanCounterDisabled) + task, _, err = mockPlan1.findBestTask(prop3, &PlanCounterDisabled, defaultPhysicalOptimizeOption()) require.NoError(t, err) require.False(t, task.invalid()) require.Equal(t, uint16(1), ctx.GetSessionVars().StmtCtx.WarningCount()) diff --git a/planner/core/fragment.go b/planner/core/fragment.go index c8eae1c63d148..ff013fa241e78 100644 --- a/planner/core/fragment.go +++ b/planner/core/fragment.go @@ -16,6 +16,7 @@ package core import ( "context" + "sort" "time" "github.com/pingcap/errors" @@ -28,6 +29,7 @@ import ( "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tipb/go-tipb" "go.uber.org/zap" ) @@ -126,7 +128,8 @@ func (f *Fragment) init(p PhysicalPlan) error { } f.TableScan = x case *PhysicalExchangeReceiver: - f.singleton = x.children[0].(*PhysicalExchangeSender).ExchangeType == tipb.ExchangeType_PassThrough + // TODO: after we support partial merge, we should check whether all the target exchangeReceiver is same. + f.singleton = f.singleton || x.children[0].(*PhysicalExchangeSender).ExchangeType == tipb.ExchangeType_PassThrough f.ExchangeReceivers = append(f.ExchangeReceivers, x) case *PhysicalUnionAll: return errors.New("unexpected union all detected") @@ -247,12 +250,17 @@ func (e *mppTaskGenerator) generateMPPTasksForFragment(f *Fragment) (tasks []*kv } if f.TableScan != nil { tasks, err = e.constructMPPTasksImpl(context.Background(), f.TableScan) + if err == nil && len(tasks) == 0 { + err = errors.New( + "In mpp mode, the number of tasks for table scan should not be zero. " + + "Please set tidb_allow_mpp = 0, and then rerun sql.") + } } else { childrenTasks := make([]*kv.MPPTask, 0) for _, r := range f.ExchangeReceivers { childrenTasks = append(childrenTasks, r.Tasks...) } - if f.singleton { + if f.singleton && len(childrenTasks) > 0 { childrenTasks = childrenTasks[0:1] } tasks = e.constructMPPTasksByChildrenTasks(childrenTasks) @@ -260,9 +268,6 @@ func (e *mppTaskGenerator) generateMPPTasksForFragment(f *Fragment) (tasks []*kv if err != nil { return nil, errors.Trace(err) } - if len(tasks) == 0 { - return nil, errors.New("cannot find mpp task") - } for _, r := range f.ExchangeReceivers { for _, frag := range r.frags { frag.ExchangeSender.TargetTasks = append(frag.ExchangeSender.TargetTasks, tasks...) @@ -314,42 +319,26 @@ func (e *mppTaskGenerator) constructMPPTasksImpl(ctx context.Context, ts *Physic } } + var req *kv.MPPBuildTasksRequest + var allPartitionsIDs []int64 + var err error splitedRanges, _ := distsql.SplitRangesAcrossInt64Boundary(ts.Ranges, false, false, ts.Table.IsCommonHandle) if ts.Table.GetPartitionInfo() != nil { tmp, _ := e.is.TableByID(ts.Table.ID) tbl := tmp.(table.PartitionedTable) - partitions, err := partitionPruning(e.ctx, tbl, ts.PartitionInfo.PruningConds, ts.PartitionInfo.PartitionNames, ts.PartitionInfo.Columns, ts.PartitionInfo.ColumnNames) + var partitions []table.PhysicalTable + partitions, err = partitionPruning(e.ctx, tbl, ts.PartitionInfo.PruningConds, ts.PartitionInfo.PartitionNames, ts.PartitionInfo.Columns, ts.PartitionInfo.ColumnNames) if err != nil { return nil, errors.Trace(err) } - var ret []*kv.MPPTask - for _, p := range partitions { - pid := p.GetPhysicalID() - meta := p.Meta() - kvRanges, err := distsql.TableHandleRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, []int64{pid}, meta != nil && ts.Table.IsCommonHandle, splitedRanges, nil) - if err != nil { - return nil, errors.Trace(err) - } - tasks, err := e.constructMPPTasksForSinglePartitionTable(ctx, kvRanges, pid) - if err != nil { - return nil, errors.Trace(err) - } - ret = append(ret, tasks...) - } - return ret, nil + req, allPartitionsIDs, err = e.constructMPPBuildTaskReqForPartitionedTable(ts, splitedRanges, partitions) + } else { + req, err = e.constructMPPBuildTaskForNonPartitionTable(ts, splitedRanges) } - - kvRanges, err := distsql.TableHandleRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, []int64{ts.Table.ID}, ts.Table.IsCommonHandle, splitedRanges, nil) if err != nil { return nil, errors.Trace(err) } - return e.constructMPPTasksForSinglePartitionTable(ctx, kvRanges, ts.Table.ID) -} -func (e *mppTaskGenerator) constructMPPTasksForSinglePartitionTable(ctx context.Context, kvRanges []kv.KeyRange, tableID int64) ([]*kv.MPPTask, error) { - req := &kv.MPPBuildTasksRequest{ - KeyRanges: kvRanges, - } ttl, err := time.ParseDuration(e.ctx.GetSessionVars().MPPStoreFailTTL) if err != nil { logutil.BgLogger().Warn("MPP store fail ttl is invalid", zap.Error(err)) @@ -359,9 +348,40 @@ func (e *mppTaskGenerator) constructMPPTasksForSinglePartitionTable(ctx context. if err != nil { return nil, errors.Trace(err) } + tasks := make([]*kv.MPPTask, 0, len(metas)) for _, meta := range metas { - tasks = append(tasks, &kv.MPPTask{Meta: meta, ID: e.ctx.GetSessionVars().AllocMPPTaskID(e.startTS), StartTs: e.startTS, TableID: tableID}) + task := &kv.MPPTask{Meta: meta, ID: e.ctx.GetSessionVars().AllocMPPTaskID(e.startTS), StartTs: e.startTS, TableID: ts.Table.ID, PartitionTableIDs: allPartitionsIDs} + tasks = append(tasks, task) } return tasks, nil } + +func (e *mppTaskGenerator) constructMPPBuildTaskReqForPartitionedTable(ts *PhysicalTableScan, splitedRanges []*ranger.Range, partitions []table.PhysicalTable) (*kv.MPPBuildTasksRequest, []int64, error) { + sort.Slice(partitions, func(i, j int) bool { + return partitions[i].GetPhysicalID() < partitions[j].GetPhysicalID() + }) + partitionIDAndRanges := make([]kv.PartitionIDAndRanges, len(partitions)) + allPartitionsIDs := make([]int64, len(partitions)) + // Get region info for each partition + for i, p := range partitions { + pid := p.GetPhysicalID() + meta := p.Meta() + kvRanges, err := distsql.TableHandleRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, []int64{pid}, meta != nil && ts.Table.IsCommonHandle, splitedRanges, nil) + if err != nil { + return nil, nil, errors.Trace(err) + } + partitionIDAndRanges[i].ID = pid + partitionIDAndRanges[i].KeyRanges = kvRanges + allPartitionsIDs[i] = pid + } + return &kv.MPPBuildTasksRequest{PartitionIDAndRanges: partitionIDAndRanges}, allPartitionsIDs, nil +} + +func (e *mppTaskGenerator) constructMPPBuildTaskForNonPartitionTable(ts *PhysicalTableScan, splitedRanges []*ranger.Range) (*kv.MPPBuildTasksRequest, error) { + kvRanges, err := distsql.TableHandleRangesToKVRanges(e.ctx.GetSessionVars().StmtCtx, []int64{ts.Table.ID}, ts.Table.IsCommonHandle, splitedRanges, nil) + if err != nil { + return nil, errors.Trace(err) + } + return &kv.MPPBuildTasksRequest{KeyRanges: kvRanges}, nil +} diff --git a/planner/core/fragment_test.go b/planner/core/fragment_test.go new file mode 100644 index 0000000000000..fa8ec9e99763c --- /dev/null +++ b/planner/core/fragment_test.go @@ -0,0 +1,53 @@ +// Copyright 2020 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core + +import ( + "github.com/pingcap/tipb/go-tipb" + "github.com/stretchr/testify/require" + + "testing" +) + +func TestFragmentInitSingleton(t *testing.T) { + r1, r2 := &PhysicalExchangeReceiver{}, &PhysicalExchangeReceiver{} + r1.SetChildren(&PhysicalExchangeSender{ExchangeType: tipb.ExchangeType_PassThrough}) + r2.SetChildren(&PhysicalExchangeSender{ExchangeType: tipb.ExchangeType_Broadcast}) + p := &PhysicalHashJoin{} + + f := &Fragment{} + p.SetChildren(r1, r1) + err := f.init(p) + require.NoError(t, err) + require.Equal(t, f.singleton, true) + + f = &Fragment{} + p.SetChildren(r1, r2) + err = f.init(p) + require.NoError(t, err) + require.Equal(t, f.singleton, true) + + f = &Fragment{} + p.SetChildren(r2, r1) + err = f.init(p) + require.NoError(t, err) + require.Equal(t, f.singleton, true) + + f = &Fragment{} + p.SetChildren(r2, r2) + err = f.init(p) + require.NoError(t, err) + require.Equal(t, f.singleton, false) +} diff --git a/planner/core/handle_cols.go b/planner/core/handle_cols.go index 48d6ab2444edd..ad59247a3b69a 100644 --- a/planner/core/handle_cols.go +++ b/planner/core/handle_cols.go @@ -239,15 +239,9 @@ func (ib *IntHandleCols) NumCols() int { // Compare implements the kv.HandleCols interface. func (ib *IntHandleCols) Compare(a, b []types.Datum, ctors []collate.Collator) (int, error) { - aInt := a[ib.col.Index].GetInt64() - bInt := b[ib.col.Index].GetInt64() - if aInt == bInt { - return 0, nil - } - if aInt < bInt { - return -1, nil - } - return 1, nil + aVal := &a[ib.col.Index] + bVal := &b[ib.col.Index] + return aVal.Compare(nil, bVal, ctors[ib.col.Index]) } // GetFieldsTypes implements the kv.HandleCols interface. diff --git a/planner/core/hints.go b/planner/core/hints.go index 04cc356f06af5..b4ad15042ef43 100644 --- a/planner/core/hints.go +++ b/planner/core/hints.go @@ -49,11 +49,6 @@ func getTableName(tblName model.CIStr, asName *model.CIStr) model.CIStr { } func extractTableAsName(p PhysicalPlan) (*model.CIStr, *model.CIStr) { - _, isProj := p.(*PhysicalProjection) - _, isUnionScan := p.(*PhysicalUnionScan) - if isProj || isUnionScan { - return extractTableAsName(p.Children()[0]) - } if len(p.Children()) > 1 { return nil, nil } @@ -76,6 +71,8 @@ func extractTableAsName(p PhysicalPlan) (*model.CIStr, *model.CIStr) { return &is.DBName, is.TableAsName } return &is.DBName, &is.Table.Name + case *PhysicalSort, *PhysicalSelection, *PhysicalUnionScan, *PhysicalProjection: + return extractTableAsName(p.Children()[0]) } return nil, nil } diff --git a/planner/core/initialize.go b/planner/core/initialize.go index 5a32d0294e952..9b1a4bf858c6c 100644 --- a/planner/core/initialize.go +++ b/planner/core/initialize.go @@ -414,13 +414,23 @@ func (p PhysicalIndexMergeReader) Init(ctx sessionctx.Context, offset int) *Phys return &p } -// Init initializes PhysicalTableReader. -func (p PhysicalTableReader) Init(ctx sessionctx.Context, offset int) *PhysicalTableReader { - p.basePhysicalPlan = newBasePhysicalPlan(ctx, plancodec.TypeTableReader, &p, offset) - if p.tablePlan != nil { - p.TablePlans = flattenPushDownPlan(p.tablePlan) - p.schema = p.tablePlan.Schema() - if p.StoreType == kv.TiFlash && p.GetTableScan() != nil && !p.GetTableScan().KeepOrder { +func (p *PhysicalTableReader) adjustReadReqType(ctx sessionctx.Context) { + if p.StoreType == kv.TiFlash { + _, ok := p.tablePlan.(*PhysicalExchangeSender) + if ok { + p.ReadReqType = MPP + return + } + tableScans := p.GetTableScans() + // When PhysicalTableReader's store type is tiflash, has table scan + // and all table scans contained are not keepOrder, try to use batch cop. + if len(tableScans) > 0 { + for _, tableScan := range tableScans { + if tableScan.KeepOrder { + return + } + } + // When allow batch cop is 1, only agg / topN uses batch cop. // When allow batch cop is 2, every query uses batch cop. switch ctx.GetSessionVars().AllowBatchCop { @@ -428,14 +438,30 @@ func (p PhysicalTableReader) Init(ctx sessionctx.Context, offset int) *PhysicalT for _, plan := range p.TablePlans { switch plan.(type) { case *PhysicalHashAgg, *PhysicalStreamAgg, *PhysicalTopN: - p.BatchCop = true + p.ReadReqType = BatchCop + return } } case 2: - p.BatchCop = true + p.ReadReqType = BatchCop } } } +} + +// Init initializes PhysicalTableReader. +func (p PhysicalTableReader) Init(ctx sessionctx.Context, offset int) *PhysicalTableReader { + p.basePhysicalPlan = newBasePhysicalPlan(ctx, plancodec.TypeTableReader, &p, offset) + p.ReadReqType = Cop + if p.tablePlan == nil { + return &p + } + p.TablePlans = flattenPushDownPlan(p.tablePlan) + p.schema = p.tablePlan.Schema() + p.adjustReadReqType(ctx) + if p.ReadReqType == BatchCop || p.ReadReqType == MPP { + setMppOrBatchCopForTableScan(p.tablePlan) + } return &p } diff --git a/planner/core/integration_partition_test.go b/planner/core/integration_partition_test.go index d463d05c45754..e9a82d9f96169 100644 --- a/planner/core/integration_partition_test.go +++ b/planner/core/integration_partition_test.go @@ -26,7 +26,6 @@ import ( "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/testdata" - "github.com/pingcap/tidb/util/israce" "github.com/stretchr/testify/require" ) @@ -182,10 +181,6 @@ func TestListPartitionFunctions(t *testing.T) { } func TestListPartitionOrderLimit(t *testing.T) { - if israce.RaceEnabled { - t.Skip("skip race test") - } - store, clean := testkit.CreateMockStore(t) defer clean() @@ -245,10 +240,6 @@ func TestListPartitionOrderLimit(t *testing.T) { } func TestListPartitionAgg(t *testing.T) { - if israce.RaceEnabled { - t.Skip("skip race test") - } - store, clean := testkit.CreateMockStore(t) defer clean() @@ -893,10 +884,6 @@ func TestListPartitionAlterPK(t *testing.T) { } func TestListPartitionRandomTransaction(t *testing.T) { - if israce.RaceEnabled { - t.Skip("skip race test") - } - store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index c3e09b82c2409..3bd8b527d2e3b 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -17,15 +17,17 @@ package core_test import ( "bytes" "fmt" + "strconv" "strings" + "testing" + "time" - . "github.com/pingcap/check" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -36,72 +38,15 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testIntegrationSuite{}) -var _ = SerialSuites(&testIntegrationSerialSuite{}) - -type testIntegrationSuite struct { - testData testutil.TestData - store kv.Storage - dom *domain.Domain -} - -func (s *testIntegrationSuite) SetUpSuite(c *C) { - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "integration_suite") - c.Assert(err, IsNil) -} - -func (s *testIntegrationSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testIntegrationSuite) SetUpTest(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testIntegrationSuite) TearDownTest(c *C) { - s.dom.Close() - err := s.store.Close() - c.Assert(err, IsNil) -} - -type testIntegrationSerialSuite struct { - testData testutil.TestData - store kv.Storage - dom *domain.Domain -} - -func (s *testIntegrationSerialSuite) SetUpSuite(c *C) { - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "integration_serial_suite") - c.Assert(err, IsNil) -} - -func (s *testIntegrationSerialSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testIntegrationSerialSuite) SetUpTest(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testIntegrationSerialSuite) TearDownTest(c *C) { - s.dom.Close() - err := s.store.Close() - c.Assert(err, IsNil) -} - -func (s *testIntegrationSuite) TestShowSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestShowSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a varchar(10), b int, c int)") @@ -131,8 +76,25 @@ func (s *testIntegrationSuite) TestShowSubquery(c *C) { )) } -func (s *testIntegrationSuite) TestPpdWithSetVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinOperatorRightAssociative(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values(1,10),(2,20)") + // make sure this join won't rewrite as left-associative join like (t0 join t1) join t2 when explicit parent existed. + // mysql will detect the t0.a is out of it's join parent scope and errors like ERROR 1054 (42S22): Unknown column 't0.a' in 'on clause' + err := tk.ExecToErr("select t1.* from t t0 cross join (t t1 join t t2 on 100=t0.a);") + require.Error(t, err) + require.EqualError(t, err, "[planner:1054]Unknown column 't0.a' in 'on clause'") +} + +func TestPpdWithSetVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(c1 int, c2 varchar(255))") @@ -142,8 +104,10 @@ func (s *testIntegrationSuite) TestPpdWithSetVar(c *C) { tk.MustQuery("select t01.c1,t01.c2,t01.c3 from (select t1.*,@c3:=@c3+1 as c3 from (select t.*,@c3:=0 from t order by t.c1)t1)t01 where t01.c3=2 and t01.c2='d'").Check(testkit.Rows("2 d 2")) } -func (s *testIntegrationSuite) TestBitColErrorMessage(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBitColErrorMessage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists bit_col_t") @@ -155,8 +119,10 @@ func (s *testIntegrationSuite) TestBitColErrorMessage(c *C) { tk.MustGetErrCode("create table bit_col_t (a bit(65))", mysql.ErrTooBigDisplaywidth) } -func (s *testIntegrationSuite) TestPushLimitDownIndexLookUpReader(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushLimitDownIndexLookUpReader(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_executor_concurrency = 4;") tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;") @@ -172,18 +138,21 @@ func (s *testIntegrationSuite) TestPushLimitDownIndexLookUpReader(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestAggColumnPrune(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAggColumnPrune(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -195,34 +164,54 @@ func (s *testIntegrationSuite) TestAggColumnPrune(c *C) { SQL string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) } } -func (s *testIntegrationSuite) TestIsFromUnixtimeNullRejective(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIsFromUnixtimeNullRejective(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a bigint, b bigint);`) - s.runTestsWithTestData("TestIsFromUnixtimeNullRejective", tk, c) + var input []string + var output []struct { + SQL string + Plan []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) + } } -func (s *testIntegrationSuite) TestIssue22298(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22298(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a int, b int);`) tk.MustGetErrMsg(`select * from t where 0 and c = 10;`, "[planner:1054]Unknown column 'c' in 'where clause'") } -func (s *testIntegrationSuite) TestIssue24571(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue24571(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create view v as select 1 as b;`) tk.MustExec(`create table t (a int);`) @@ -235,8 +224,10 @@ func (s *testIntegrationSuite) TestIssue24571(c *C) { tk.MustExec("update (select 1 as a) as t, test.t set test.t.a=1;") } -func (s *testIntegrationSuite) TestBuildUpdateListResolver(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBuildUpdateListResolver(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // For issue https://github.com/pingcap/tidb/issues/24567 @@ -257,38 +248,20 @@ func (s *testIntegrationSuite) TestBuildUpdateListResolver(c *C) { tk.MustExec("drop table if exists t") } -func (s *testIntegrationSuite) TestIssue22828(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22828(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t1;`) tk.MustExec(`create table t (c int);`) tk.MustGetErrMsg(`select group_concat((select concat(c,group_concat(c)) FROM t where xxx=xxx)) FROM t;`, "[planner:1054]Unknown column 'xxx' in 'where clause'") } -func (s *testIntegrationSuite) runTestsWithTestData(caseName string, tk *testkit.TestKit, c *C) { - var input []string - var output []struct { - SQL string - Plan []string - } - s.testData.GetTestCasesByName(caseName, c, &input, &output) - for i, tt := range input { - s.testData.OnRecord(func() { - output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - }) - tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) - } -} - -func (s *testIntegrationSuite) TestJoinNotNullFlag(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestJoinNotNullFlag(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(x int not null)") @@ -300,14 +273,10 @@ func (s *testIntegrationSuite) TestJoinNotNullFlag(c *C) { tk.MustQuery("select ifnull(t1.x, 'xxx') from t2 natural left join t1").Check(testkit.Rows("xxx")) } -func (s *testIntegrationSuite) TestAntiJoinConstProp(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestAntiJoinConstProp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int not null, b int not null)") @@ -345,8 +314,10 @@ func (s *testIntegrationSuite) TestAntiJoinConstProp(c *C) { )) } -func (s *testIntegrationSuite) TestSimplifyOuterJoinWithCast(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSimplifyOuterJoinWithCast(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -357,18 +328,21 @@ func (s *testIntegrationSuite) TestSimplifyOuterJoinWithCast(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestNoneAccessPathsFoundByIsolationRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNoneAccessPathsFoundByIsolationRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -384,8 +358,7 @@ func (s *testIntegrationSerialSuite) TestNoneAccessPathsFoundByIsolationRead(c * "└─TableFullScan 10000.00 cop[tikv] table:stats_meta keep order:false, stats:pseudo")) _, err := tk.Exec("select * from t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tikv'. Please check tiflash replica or ensure the query is readonly.") + require.EqualError(t, err, "[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tikv'. Please check tiflash replica or ensure the query is readonly.") tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash, tikv'") tk.MustExec("select * from t") @@ -397,17 +370,19 @@ func (s *testIntegrationSerialSuite) TestNoneAccessPathsFoundByIsolationRead(c * tk.MustExec("select * from t") } -func (s *testIntegrationSerialSuite) TestSelPushDownTiFlash(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelPushDownTiFlash(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(20))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -425,19 +400,22 @@ func (s *testIntegrationSerialSuite) TestSelPushDownTiFlash(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestVerboseExplain(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestVerboseExplain(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`set tidb_opt_limit_push_down_threshold=0`) tk.MustExec("drop table if exists t1, t2, t3") @@ -458,10 +436,10 @@ func (s *testIntegrationSerialSuite) TestVerboseExplain(c *C) { tk.MustExec("analyze table t3") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t1" || tblInfo.Name.L == "t2" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -476,28 +454,31 @@ func (s *testIntegrationSerialSuite) TestVerboseExplain(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestPushDownToTiFlashWithKeepOrder(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushDownToTiFlashWithKeepOrder(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(20))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -514,19 +495,22 @@ func (s *testIntegrationSerialSuite) TestPushDownToTiFlashWithKeepOrder(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists d1_t") tk.MustExec("create table d1_t(d1_k int, value int)") @@ -547,10 +531,10 @@ func (s *testIntegrationSerialSuite) TestMPPJoin(c *C) { tk.MustExec("analyze table fact_t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "fact_t" || tblInfo.Name.L == "d1_t" || tblInfo.Name.L == "d2_t" || tblInfo.Name.L == "d3_t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -567,19 +551,73 @@ func (s *testIntegrationSerialSuite) TestMPPJoin(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForBroadcastJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPLeftSemiJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + // test table + tk.MustExec("use test") + tk.MustExec("create table test.t(a int not null, b int null);") + tk.MustExec("set tidb_allow_mpp=1; set tidb_enforce_mpp=1;") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tblInfo := range db.Tables { + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + }) + if strings.HasPrefix(tt, "set") || strings.HasPrefix(tt, "UPDATE") { + tk.MustExec(tt) + continue + } + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) + }) + res := tk.MustQuery(tt) + res.Check(testkit.Rows(output[i].Plan...)) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) + } +} + +func TestMPPOuterJoinBuildSideForBroadcastJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists a") tk.MustExec("create table a(id int, value int)") @@ -590,10 +628,10 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForBroadcastJoin(c tk.MustExec("insert into b values(1,2),(2,3),(3,4)") tk.MustExec("analyze table b") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -611,19 +649,22 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForBroadcastJoin(c SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists a") tk.MustExec("create table a(id int, value int)") @@ -634,10 +675,10 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoinWith tk.MustExec("insert into b values(1,2),(2,3),(3,4)") tk.MustExec("analyze table b") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -655,19 +696,22 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoinWith SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPOuterJoinBuildSideForShuffleJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists a") tk.MustExec("create table a(id int, value int)") @@ -678,10 +722,10 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoin(c * tk.MustExec("insert into b values(1,2),(2,3),(3,4)") tk.MustExec("analyze table b") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -699,19 +743,22 @@ func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoin(c * SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPShuffledJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPShuffledJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists d1_t") tk.MustExec("create table d1_t(d1_k int, value int)") @@ -737,10 +784,10 @@ func (s *testIntegrationSerialSuite) TestMPPShuffledJoin(c *C) { tk.MustExec("analyze table fact_t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "fact_t" || tblInfo.Name.L == "d1_t" || tblInfo.Name.L == "d2_t" || tblInfo.Name.L == "d3_t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -759,19 +806,22 @@ func (s *testIntegrationSerialSuite) TestMPPShuffledJoin(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(id int, v1 decimal(20,2), v2 decimal(20,2))") @@ -784,10 +834,10 @@ func (s *testIntegrationSerialSuite) TestMPPJoinWithCanNotFoundColumnInSchemaCol tk.MustExec("analyze table t2") tk.MustExec("analyze table t3") - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t1" || tblInfo.Name.L == "t2" || tblInfo.Name.L == "t3" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -808,30 +858,37 @@ func (s *testIntegrationSerialSuite) TestMPPJoinWithCanNotFoundColumnInSchemaCol SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestJoinNotSupportedByTiFlash(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinNotSupportedByTiFlash(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists table_1") tk.MustExec("create table table_1(id int not null, bit_col bit(2) not null, datetime_col datetime not null)") tk.MustExec("insert into table_1 values(1,b'1','2020-01-01 00:00:00'),(2,b'0','2020-01-01 00:00:00')") tk.MustExec("analyze table table_1") + tk.MustExec("insert into mysql.expr_pushdown_blacklist values('dayofmonth', 'tiflash', '');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "table_1" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -848,11 +905,12 @@ func (s *testIntegrationSerialSuite) TestJoinNotSupportedByTiFlash(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) @@ -860,37 +918,21 @@ func (s *testIntegrationSerialSuite) TestJoinNotSupportedByTiFlash(c *C) { tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1") tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1") - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - }) - res := tk.MustQuery(tt) - res.Check(testkit.Rows(output[i].Plan...)) - } - - tk.MustExec("set @@session.tidb_allow_mpp = 0") - tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") - tk.MustExec("set @@session.tidb_allow_batch_cop = 1") - tk.MustExec("set @@session.tidb_opt_broadcast_join = 1") - // make cbo force choose broadcast join since sql hint does not work for semi/anti-semi join - tk.MustExec("set @@session.tidb_opt_cpu_factor=10000000;") - s.testData.GetTestCases(c, &input, &output) - for i, tt := range input { - s.testData.OnRecord(func() { - output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPWithHashExchangeUnderNewCollation(c *C) { - defer collate.SetNewCollationEnabledForTest(false) - collate.SetNewCollationEnabledForTest(true) - tk := testkit.NewTestKit(c, s.store) +func TestMPPWithHashExchangeUnderNewCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists table_1") tk.MustExec("create table table_1(id int not null, value char(10)) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;") @@ -902,10 +944,10 @@ func (s *testIntegrationSerialSuite) TestMPPWithHashExchangeUnderNewCollation(c tk.MustExec("analyze table table_2") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "table_1" || tblInfo.Name.L == "table_2" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -917,7 +959,6 @@ func (s *testIntegrationSerialSuite) TestMPPWithHashExchangeUnderNewCollation(c tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") tk.MustExec("set @@session.tidb_allow_mpp = 1") - tk.MustExec("set @@session.tidb_opt_broadcast_join = 0") tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0") tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0") tk.MustExec("set @@session.tidb_hash_exchange_with_new_collation = 1") @@ -926,20 +967,22 @@ func (s *testIntegrationSerialSuite) TestMPPWithHashExchangeUnderNewCollation(c SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMPPWithBroadcastExchangeUnderNewCollation(c *C) { - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestMPPWithBroadcastExchangeUnderNewCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists table_1") tk.MustExec("create table table_1(id int not null, value char(10))") @@ -947,10 +990,10 @@ func (s *testIntegrationSerialSuite) TestMPPWithBroadcastExchangeUnderNewCollati tk.MustExec("analyze table table_1") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "table_1" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -960,7 +1003,6 @@ func (s *testIntegrationSerialSuite) TestMPPWithBroadcastExchangeUnderNewCollati } } - collate.SetNewCollationEnabledForTest(true) tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") tk.MustExec("set @@session.tidb_allow_mpp = 1") var input []string @@ -968,21 +1010,22 @@ func (s *testIntegrationSerialSuite) TestMPPWithBroadcastExchangeUnderNewCollati SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestPartitionTableDynamicModeUnderNewCollation(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKitWithInit(c, s.store) +func TestPartitionTableDynamicModeUnderNewCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database test_new_collation") tk.MustExec("use test_new_collation") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -1019,9 +1062,10 @@ func (s *testIntegrationSerialSuite) TestPartitionTableDynamicModeUnderNewCollat tk.MustQuery(`select * from strlist where a in ('D', 'e')`).Sort().Check(testkit.Rows("D 1", "d 1", "e 1")) } -func (s *testIntegrationSerialSuite) TestMPPAvgRewrite(c *C) { - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestMPPAvgRewrite(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists table_1") tk.MustExec("create table table_1(id int not null, value decimal(10,2))") @@ -1029,10 +1073,10 @@ func (s *testIntegrationSerialSuite) TestMPPAvgRewrite(c *C) { tk.MustExec("analyze table table_1") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "table_1" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -1042,7 +1086,6 @@ func (s *testIntegrationSerialSuite) TestMPPAvgRewrite(c *C) { } } - collate.SetNewCollationEnabledForTest(true) tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") tk.MustExec("set @@session.tidb_allow_mpp = 1") var input []string @@ -1050,28 +1093,31 @@ func (s *testIntegrationSerialSuite) TestMPPAvgRewrite(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestAggPushDownEngine(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAggPushDownEngine(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(20))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -1083,22 +1129,24 @@ func (s *testIntegrationSerialSuite) TestAggPushDownEngine(c *C) { tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") - tk.MustQuery("desc select approx_count_distinct(a) from t").Check(testkit.Rows( - "HashAgg_11 1.00 root funcs:approx_count_distinct(Column#4)->Column#3", - "└─TableReader_12 1.00 root data:HashAgg_6", - " └─HashAgg_6 1.00 batchCop[tiflash] funcs:approx_count_distinct(test.t.a)->Column#4", - " └─TableFullScan_10 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo")) + tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows( + "StreamAgg 1.00 root funcs:approx_count_distinct(Column#5)->Column#3", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:approx_count_distinct(test.t.a)->Column#5", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo")) tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv'") - tk.MustQuery("desc select approx_count_distinct(a) from t").Check(testkit.Rows( - "HashAgg_5 1.00 root funcs:approx_count_distinct(test.t.a)->Column#3", - "└─TableReader_11 10000.00 root data:TableFullScan_10", - " └─TableFullScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) + tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows( + "HashAgg 1.00 root funcs:approx_count_distinct(test.t.a)->Column#3", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) } -func (s *testIntegrationSerialSuite) TestIssue15110(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15110(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists crm_rd_150m") tk.MustExec(`CREATE TABLE crm_rd_150m ( @@ -1115,10 +1163,10 @@ func (s *testIntegrationSerialSuite) TestIssue15110(c *C) { ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;`) // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "crm_rd_150m" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -1132,8 +1180,10 @@ func (s *testIntegrationSerialSuite) TestIssue15110(c *C) { tk.MustExec("explain format = 'brief' SELECT count(*) FROM crm_rd_150m dataset_48 WHERE (CASE WHEN (month(dataset_48.customer_first_date)) <= 30 THEN '新客' ELSE NULL END) IS NOT NULL;") } -func (s *testIntegrationSerialSuite) TestReadFromStorageHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReadFromStorageHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, tt, ttt") @@ -1143,10 +1193,10 @@ func (s *testIntegrationSerialSuite) TestReadFromStorageHint(c *C) { tk.MustExec("create table ttt(a int, primary key (a desc))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ Count: 1, @@ -1160,21 +1210,24 @@ func (s *testIntegrationSerialSuite) TestReadFromStorageHint(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } -func (s *testIntegrationSerialSuite) TestReadFromStorageHintAndIsolationRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReadFromStorageHintAndIsolationRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, tt, ttt") @@ -1182,10 +1235,10 @@ func (s *testIntegrationSerialSuite) TestReadFromStorageHintAndIsolationRead(c * tk.MustExec("set @@session.tidb_isolation_read_engines=\"tikv\"") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ Count: 1, @@ -1199,32 +1252,35 @@ func (s *testIntegrationSerialSuite) TestReadFromStorageHintAndIsolationRead(c * Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - tk.Se.GetSessionVars().StmtCtx.SetWarnings(nil) - s.testData.OnRecord(func() { + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } -func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashNotChoosePointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIsolationReadTiFlashNotChoosePointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, primary key (a))") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ Count: 1, @@ -1238,28 +1294,31 @@ func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashNotChoosePointGet(c SQL string Result []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) } } -func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashUseIndexHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIsolationReadTiFlashUseIndexHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, index idx(a));") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ Count: 1, @@ -1274,21 +1333,24 @@ func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashUseIndexHint(c *C) Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) } } -func (s *testIntegrationSerialSuite) TestIsolationReadDoNotFilterSystemDB(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIsolationReadDoNotFilterSystemDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_isolation_read_engines = \"tiflash\"") @@ -1297,19 +1359,22 @@ func (s *testIntegrationSerialSuite) TestIsolationReadDoNotFilterSystemDB(c *C) SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestPartitionTableStats(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionTableStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) { tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) tk.MustExec("use test") @@ -1324,19 +1389,22 @@ func (s *testIntegrationSuite) TestPartitionTableStats(c *C) { SQL string Result []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) } } } -func (s *testIntegrationSuite) TestPartitionPruningForInExpr(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionPruningForInExpr(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1348,18 +1416,21 @@ func (s *testIntegrationSuite) TestPartitionPruningForInExpr(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestPartitionPruningWithDateType(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionPruningWithDateType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1369,54 +1440,60 @@ func (s *testIntegrationSerialSuite) TestPartitionPruningWithDateType(c *C) { // cannot get the statistical information immediately // tk.MustQuery(`SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't';`).Check(testkit.Rows("p1 1", "p2 1")) str := tk.MustQuery(`desc select * from t where a < '2000-01-01';`).Rows()[0][3].(string) - c.Assert(strings.Contains(str, "partition:p1"), IsTrue) + require.True(t, strings.Contains(str, "partition:p1")) } -func (s *testIntegrationSuite) TestPartitionPruningForEQ(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionPruningForEQ(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a datetime, b int) partition by range(weekday(a)) (partition p0 values less than(10), partition p1 values less than (100))") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) pt := tbl.(table.PartitionedTable) - query, err := expression.ParseSimpleExprWithTableInfo(tk.Se, "a = '2020-01-01 00:00:00'", tbl.Meta()) - c.Assert(err, IsNil) - dbName := model.NewCIStr(tk.Se.GetSessionVars().CurrentDB) - columns, names, err := expression.ColumnInfos2ColumnsAndNames(tk.Se, dbName, tbl.Meta().Name, tbl.Meta().Cols(), tbl.Meta()) - c.Assert(err, IsNil) + query, err := expression.ParseSimpleExprWithTableInfo(tk.Session(), "a = '2020-01-01 00:00:00'", tbl.Meta()) + require.NoError(t, err) + dbName := model.NewCIStr(tk.Session().GetSessionVars().CurrentDB) + columns, names, err := expression.ColumnInfos2ColumnsAndNames(tk.Session(), dbName, tbl.Meta().Name, tbl.Meta().Cols(), tbl.Meta()) + require.NoError(t, err) // Even the partition is not monotonous, EQ condition should be prune! // select * from t where a = '2020-01-01 00:00:00' - res, err := core.PartitionPruning(tk.Se, pt, []expression.Expression{query}, nil, columns, names) - c.Assert(err, IsNil) - c.Assert(res, HasLen, 1) - c.Assert(res[0], Equals, 0) + res, err := core.PartitionPruning(tk.Session(), pt, []expression.Expression{query}, nil, columns, names) + require.NoError(t, err) + require.Len(t, res, 1) + require.Equal(t, 0, res[0]) } -func (s *testIntegrationSuite) TestErrNoDB(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestErrNoDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create user test") _, err := tk.Exec("grant select on test1111 to test@'%'") - c.Assert(errors.Cause(err), Equals, core.ErrNoDB) + require.Equal(t, core.ErrNoDB, errors.Cause(err)) _, err = tk.Exec("grant select on * to test@'%'") - c.Assert(errors.Cause(err), Equals, core.ErrNoDB) + require.Equal(t, core.ErrNoDB, errors.Cause(err)) _, err = tk.Exec("revoke select on * from test@'%'") - c.Assert(errors.Cause(err), Equals, core.ErrNoDB) + require.Equal(t, core.ErrNoDB, errors.Cause(err)) tk.MustExec("use test") tk.MustExec("create table test1111 (id int)") tk.MustExec("grant select on test1111 to test@'%'") } -func (s *testIntegrationSuite) TestMaxMinEliminate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMaxMinEliminate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key)") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("create table cluster_index_t(a int, b int, c int, primary key (a, b));") var input []string @@ -1424,18 +1501,21 @@ func (s *testIntegrationSuite) TestMaxMinEliminate(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestINLJHintSmallTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestINLJHintSmallTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int not null, b int, key(a))") @@ -1446,12 +1526,14 @@ func (s *testIntegrationSuite) TestINLJHintSmallTable(c *C) { tk.MustExec("explain format = 'brief' select /*+ TIDB_INLJ(t1) */ * from t1 join t2 on t1.a = t2.a") } -func (s *testIntegrationSuite) TestIndexJoinUniqueCompositeIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexJoinUniqueCompositeIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t1(a int not null, c int not null)") tk.MustExec("create table t2(a int not null, b int not null, c int not null, primary key(a,b))") tk.MustExec("insert into t1 values(1,1)") @@ -1463,18 +1545,21 @@ func (s *testIntegrationSuite) TestIndexJoinUniqueCompositeIndex(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIndexMerge(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMerge(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1485,18 +1570,21 @@ func (s *testIntegrationSuite) TestIndexMerge(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIndexMergeHint4CNF(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeHint4CNF(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1507,18 +1595,21 @@ func (s *testIntegrationSuite) TestIndexMergeHint4CNF(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestInvisibleIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInvisibleIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1532,9 +1623,9 @@ func (s *testIntegrationSuite) TestInvisibleIndex(c *C) { // Optimizer cannot use invisible indexes. tk.MustQuery("select a from t order by a").Check(testkit.Rows("1")) - c.Check(tk.MustUseIndex("select a from t order by a", "i_a"), IsFalse) + require.False(t, tk.MustUseIndex("select a from t order by a", "i_a")) tk.MustQuery("select a from t where a > 0").Check(testkit.Rows("1")) - c.Check(tk.MustUseIndex("select a from t where a > 1", "i_a"), IsFalse) + require.False(t, tk.MustUseIndex("select a from t where a > 1", "i_a")) // If use invisible indexes in index hint and sql hint, throw an error. errStr := "[planner:1176]Key 'i_a' doesn't exist in table 't'" @@ -1542,27 +1633,29 @@ func (s *testIntegrationSuite) TestInvisibleIndex(c *C) { tk.MustGetErrMsg("select * from t force index(i_a)", errStr) tk.MustGetErrMsg("select * from t ignore index(i_a)", errStr) tk.MustQuery("select /*+ USE_INDEX(t, i_a) */ * from t") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, errStr) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) + require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr) tk.MustQuery("select /*+ IGNORE_INDEX(t, i_a), USE_INDEX(t, i_b) */ a from t order by a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, errStr) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) + require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr) tk.MustQuery("select /*+ FORCE_INDEX(t, i_a), USE_INDEX(t, i_b) */ a from t order by a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, errStr) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) + require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr) // For issue 15519 inapplicableErrStr := "[planner:1815]force_index(test.aaa) is inapplicable, check whether the table(test.aaa) exists" tk.MustQuery("select /*+ FORCE_INDEX(aaa) */ * from t") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, inapplicableErrStr) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1) + require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, inapplicableErrStr) tk.MustExec("admin check table t") tk.MustExec("admin check index t i_a") } // for issue #14822 -func (s *testIntegrationSuite) TestIndexJoinTableRange(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexJoinTableRange(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") @@ -1574,26 +1667,31 @@ func (s *testIntegrationSuite) TestIndexJoinTableRange(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestTopNByConstFunc(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTopNByConstFunc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustQuery("select max(t.col) from (select 'a' as col union all select '' as col) as t").Check(testkit.Rows( "a", )) } -func (s *testIntegrationSuite) TestSubqueryWithTopN(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSubqueryWithTopN(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1604,18 +1702,21 @@ func (s *testIntegrationSuite) TestSubqueryWithTopN(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIndexHintWarning(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexHintWarning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, c int, key a(a), key b(b))") @@ -1625,29 +1726,59 @@ func (s *testIntegrationSuite) TestIndexHintWarning(c *C) { SQL string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt tk.MustQuery(tt) - warns := tk.Se.GetSessionVars().StmtCtx.GetWarnings() + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() output[i].Warnings = make([]string, len(warns)) for j := range warns { output[i].Warnings[j] = warns[j].Err.Error() } }) tk.MustQuery(tt) - warns := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warns), Equals, len(output[i].Warnings)) + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warns, len(output[i].Warnings)) for j := range warns { - c.Assert(warns[j].Level, Equals, stmtctx.WarnLevelWarning) - c.Assert(warns[j].Err.Error(), Equals, output[i].Warnings[j]) + require.Equal(t, stmtctx.WarnLevelWarning, warns[j].Level) + require.EqualError(t, warns[j].Err, output[i].Warnings[j]) } } + //Test view with index hint should result error + tk.MustExec("drop table if exists t1") + tk.MustExec("drop view if exists v1") + tk.MustExec("CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2))") + tk.MustExec("INSERT INTO t1 VALUES (1,1), (2,2), (3,3)") + tk.MustExec("CREATE VIEW v1 AS SELECT c1, c2 FROM t1") + err := tk.ExecToErr("SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2") + require.True(t, terror.ErrorEqual(err, core.ErrKeyDoesNotExist)) +} + +func TestIssue32672(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + for _, agg := range []string{"stream", "hash"} { + rs := tk.MustQuery(fmt.Sprintf("explain format='verbose' select /*+ %v_agg() */ count(*) from t", agg)).Rows() + // cols: id, estRows, estCost, ... + operator := rs[0][0].(string) + cost, err := strconv.ParseFloat(rs[0][2].(string), 64) + require.NoError(t, err) + require.True(t, strings.Contains(strings.ToLower(operator), agg)) + require.True(t, cost > 0) + } } -func (s *testIntegrationSuite) TestIssue15546(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15546(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, pt, vt") @@ -1660,8 +1791,10 @@ func (s *testIntegrationSuite) TestIssue15546(c *C) { tk.MustQuery("select * from pt, vt where pt.a = vt.a").Check(testkit.Rows("1 1 1 1")) } -func (s *testIntegrationSuite) TestApproxCountDistinctInPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestApproxCountDistinctInPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1681,8 +1814,10 @@ func (s *testIntegrationSuite) TestApproxCountDistinctInPartitionTable(c *C) { tk.MustQuery("select approx_count_distinct(a), b from t group by b order by b desc").Check(testkit.Rows("1 2", "3 1")) } -func (s *testIntegrationSuite) TestApproxPercentile(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestApproxPercentile(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1695,20 +1830,23 @@ func (s *testIntegrationSuite) TestApproxPercentile(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) } } -func (s *testIntegrationSuite) TestIssue17813(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue17813(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists hash_partition_overflow") @@ -1718,8 +1856,10 @@ func (s *testIntegrationSuite) TestIssue17813(c *C) { tk.MustQuery("select * from hash_partition_overflow where c0 in (1, 9223372036854775808)").Check(testkit.Rows("9223372036854775808")) } -func (s *testIntegrationSuite) TestHintWithRequiredProperty(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHintWithRequiredProperty(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_executor_concurrency = 4;") tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;") tk.MustExec("set @@session.tidb_distsql_scan_concurrency = 15;") @@ -1732,28 +1872,31 @@ func (s *testIntegrationSuite) TestHintWithRequiredProperty(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() output[i].Warnings = make([]string, len(warnings)) for j, warning := range warnings { output[i].Warnings[j] = warning.Err.Error() } }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warnings), Equals, len(output[i].Warnings)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warnings, len(output[i].Warnings)) for j, warning := range warnings { - c.Assert(output[i].Warnings[j], Equals, warning.Err.Error()) + require.EqualError(t, warning.Err, output[i].Warnings[j]) } } } -func (s *testIntegrationSuite) TestIssue15813(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15813(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0, t1") @@ -1764,19 +1907,44 @@ func (s *testIntegrationSuite) TestIssue15813(c *C) { tk.MustQuery("select /*+ MERGE_JOIN(t0, t1) */ * from t0, t1 where t0.c0 = t1.c0").Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestFullGroupByOrderBy(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue31261(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists PK_MULTI_COL_5177`) + tk.MustExec(` CREATE TABLE PK_MULTI_COL_5177 ( + COL1 binary(10) NOT NULL, + COL2 varbinary(10) NOT NULL, + COL3 smallint(45) NOT NULL, + PRIMARY KEY (COL1(5),COL2,COL3), + UNIQUE KEY UIDXM (COL1(5),COL2), + UNIQUE KEY UIDX (COL2), + KEY IDX3 (COL3), + KEY IDXM (COL3,COL2))`) + tk.MustExec(`insert into PK_MULTI_COL_5177(col1, col2, col3) values(0x00000000000000000000, 0x002B200DF5BA03E59F82, 1)`) + require.Len(t, tk.MustQuery(`select col1, col2 from PK_MULTI_COL_5177 where col1 = 0x00000000000000000000 and col2 in (0x002B200DF5BA03E59F82, 0x002B200DF5BA03E59F82, 0x002B200DF5BA03E59F82)`).Rows(), 1) + require.Len(t, tk.MustQuery(`select col1, col2 from PK_MULTI_COL_5177 where col1 = 0x00000000000000000000 and col2 = 0x002B200DF5BA03E59F82`).Rows(), 1) +} + +func TestFullGroupByOrderBy(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") tk.MustQuery("select count(a) as b from t group by a order by b").Check(testkit.Rows()) err := tk.ExecToErr("select count(a) as cnt from t group by a order by b") - c.Assert(terror.ErrorEqual(err, core.ErrFieldNotInGroupBy), IsTrue) + require.True(t, terror.ErrorEqual(err, core.ErrFieldNotInGroupBy)) } -func (s *testIntegrationSuite) TestHintWithoutTableWarning(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHintWithoutTableWarning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, c int, key a(a))") @@ -1786,37 +1954,42 @@ func (s *testIntegrationSuite) TestHintWithoutTableWarning(c *C) { SQL string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt tk.MustQuery(tt) - warns := tk.Se.GetSessionVars().StmtCtx.GetWarnings() + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() output[i].Warnings = make([]string, len(warns)) for j := range warns { output[i].Warnings[j] = warns[j].Err.Error() } }) tk.MustQuery(tt) - warns := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(len(warns), Equals, len(output[i].Warnings)) + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warns, len(output[i].Warnings)) for j := range warns { - c.Assert(warns[j].Level, Equals, stmtctx.WarnLevelWarning) - c.Assert(warns[j].Err.Error(), Equals, output[i].Warnings[j]) + require.Equal(t, stmtctx.WarnLevelWarning, warns[j].Level) + require.EqualError(t, warns[j].Err, output[i].Warnings[j]) } } } -func (s *testIntegrationSuite) TestIssue15858(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15858(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key)") tk.MustExec("select * from t t1, (select a from t order by a+1) t2 where t1.a = t2.a") } -func (s *testIntegrationSuite) TestIssue15846(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue15846(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0, t1") tk.MustExec("CREATE TABLE t0(t0 INT UNIQUE);") @@ -1841,8 +2014,10 @@ func (s *testIntegrationSuite) TestIssue15846(c *C) { tk.MustQuery("SELECT t1.c0 FROM t1 LEFT JOIN t0 ON 1;").Check(testkit.Rows("0", "0")) } -func (s *testIntegrationSuite) TestFloorUnixTimestampPruning(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestFloorUnixTimestampPruning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists floor_unix_timestamp") tk.MustExec(`create table floor_unix_timestamp (ts timestamp(3)) @@ -1862,8 +2037,10 @@ partition p2 values less than (unix_timestamp('2020-04-15 00:00:00')))`) tk.MustQuery("select * from floor_unix_timestamp partition(p1, p2) where ts > '2020-04-14 00:00:00'").Check(testkit.Rows("2020-04-14 00:00:42.000")) } -func (s *testIntegrationSuite) TestIssue16290And16292(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16290And16292(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b int, primary key(a));") @@ -1879,8 +2056,10 @@ func (s *testIntegrationSuite) TestIssue16290And16292(c *C) { } } -func (s *testIntegrationSuite) TestTableDualWithRequiredProperty(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTableDualWithRequiredProperty(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2;") tk.MustExec("create table t1 (a int, b int) partition by range(a) " + @@ -1889,8 +2068,10 @@ func (s *testIntegrationSuite) TestTableDualWithRequiredProperty(c *C) { tk.MustExec("select /*+ MERGE_JOIN(t1, t2) */ * from t1 partition (p0), t2 where t1.a > 100 and t1.a = t2.a") } -func (s *testIntegrationSuite) TestIndexJoinInnerIndexNDV(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexJoinInnerIndexNDV(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int not null, b int not null, c int not null)") @@ -1904,18 +2085,21 @@ func (s *testIntegrationSuite) TestIndexJoinInnerIndexNDV(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestIssue16837(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16837(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int,b int,c int,d int,e int,unique key idx_ab(a,b),unique key(c),unique key(d))") @@ -1930,8 +2114,10 @@ func (s *testIntegrationSerialSuite) TestIssue16837(c *C) { tk.MustQuery("select /*+ use_index_merge(t,c,idx_ab) */ * from t where a = 1 or (e = 1 and c = 1)").Check(testkit.Rows()) } -func (s *testIntegrationSerialSuite) TestIndexMerge(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeSerial(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, unique key(a), unique key(b))") @@ -1945,20 +2131,23 @@ func (s *testIntegrationSerialSuite) TestIndexMerge(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warnings = s.testData.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...)) } } -func (s *testIntegrationSerialSuite) TestIndexMergePartialScansClusteredIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergePartialScansClusteredIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -2009,8 +2198,10 @@ func (s *testIntegrationSerialSuite) TestIndexMergePartialScansClusteredIndex(c } } -func (s *testIntegrationSerialSuite) TestIndexMergePartialScansTiDBRowID(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergePartialScansTiDBRowID(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -2061,8 +2252,10 @@ func (s *testIntegrationSerialSuite) TestIndexMergePartialScansTiDBRowID(c *C) { } } -func (s *testIntegrationSerialSuite) TestIndexMergePartialScansPKIsHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergePartialScansPKIsHandle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -2109,8 +2302,10 @@ func (s *testIntegrationSerialSuite) TestIndexMergePartialScansPKIsHandle(c *C) } } -func (s *testIntegrationSerialSuite) TestIssue23919(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23919(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") // Test for the minimal reproducible case. @@ -2148,8 +2343,10 @@ PARTITION BY RANGE ( col_8 ) ( "t.col_8 = 7372 order by col_5,col_8 ) ordered_tbl group by col_6;").Check(testkit.Rows("")) } -func (s *testIntegrationSerialSuite) TestIssue16407(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16407(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int,b char(100),key(a),key(b(10)))") @@ -2164,8 +2361,10 @@ func (s *testIntegrationSerialSuite) TestIssue16407(c *C) { tk.MustQuery("select /*+ use_index_merge(t) */ * from t where a=10 or b='x'").Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestStreamAggProp(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestStreamAggProp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2178,20 +2377,23 @@ func (s *testIntegrationSuite) TestStreamAggProp(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) } } -func (s *testIntegrationSuite) TestOptimizeHintOnPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOptimizeHintOnPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2203,12 +2405,16 @@ func (s *testIntegrationSuite) TestOptimizeHintOnPartitionTable(c *C) { partition p1 values less than(11), partition p2 values less than(16));`) tk.MustExec(`insert into t values (1,1,"1"), (2,2,"2"), (8,8,"8"), (11,11,"11"), (15,15,"15")`) + tk.MustExec("set @@tidb_enable_index_merge = off") + defer func() { + tk.MustExec("set @@tidb_enable_index_merge = on") + }() // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -2226,30 +2432,33 @@ func (s *testIntegrationSuite) TestOptimizeHintOnPartitionTable(c *C) { Plan []string Warn []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Warn = s.testData.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Warn = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warn...)) } } -func (s *testIntegrationSerialSuite) TestNotReadOnlySQLOnTiFlash(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNotReadOnlySQLOnTiFlash(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b varchar(20))") tk.MustExec(`set @@tidb_isolation_read_engines = "tiflash"`) // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -2259,22 +2468,21 @@ func (s *testIntegrationSerialSuite) TestNotReadOnlySQLOnTiFlash(c *C) { } } err := tk.ExecToErr("select * from t for update") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) err = tk.ExecToErr("insert into t select * from t") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) tk.MustExec("prepare stmt_insert from 'insert into t select * from t where t.a = ?'") tk.MustExec("set @a=1") err = tk.ExecToErr("execute stmt_insert using @a") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`) } -func (s *testIntegrationSuite) TestSelectLimit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectLimit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2284,7 +2492,7 @@ func (s *testIntegrationSuite) TestSelectLimit(c *C) { // normal test tk.MustExec("set @@session.sql_select_limit=1") result := tk.MustQuery("select * from t order by a") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 0) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 0) result.Check(testkit.Rows("1")) result = tk.MustQuery("select * from t order by a limit 2") result.Check(testkit.Rows("1", "1")) @@ -2349,31 +2557,36 @@ func (s *testIntegrationSuite) TestSelectLimit(c *C) { result.Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestHintParserWarnings(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHintParserWarnings(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b int, key(a), key(b));") tk.MustExec("select /*+ use_index_merge() */ * from t where a = 1 or b = 1;") rows := tk.MustQuery("show warnings;").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) } -func (s *testIntegrationSuite) TestIssue16935(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue16935(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0;") tk.MustExec("CREATE TABLE t0(c0 INT);") tk.MustExec("INSERT INTO t0(c0) VALUES (1), (1), (1), (1), (1), (1);") tk.MustExec("CREATE definer='root'@'localhost' VIEW v0(c0) AS SELECT NULL FROM t0;") - tk.MustQuery("SELECT * FROM t0 LEFT JOIN v0 ON TRUE WHERE v0.c0 IS NULL;") } -func (s *testIntegrationSuite) TestAccessPathOnClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestAccessPathOnClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int, b varchar(20), c decimal(40,10), d int, primary key(a,b), key(c))") tk.MustExec(`insert into t1 values (1,"111",1.1,11), (2,"222",2.2,12), (3,"333",3.3,13)`) @@ -2385,24 +2598,27 @@ func (s *testIntegrationSuite) TestAccessPathOnClusterIndex(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) }) tk.MustQuery("explain format='brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) } } -func (s *testIntegrationSuite) TestClusterIndexUniqueDoubleRead(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusterIndexUniqueDoubleRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database cluster_idx_unique_double_read;") tk.MustExec("use cluster_idx_unique_double_read;") defer tk.MustExec("drop database cluster_idx_unique_double_read;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t") tk.MustExec("create table t (a varchar(64), b varchar(64), uk int, v int, primary key(a, b), unique key uuk(uk));") @@ -2410,10 +2626,12 @@ func (s *testIntegrationSuite) TestClusterIndexUniqueDoubleRead(c *C) { tk.MustQuery("select * from t use index (uuk);").Check(testkit.Rows("a a1 1 11", "b b1 2 22", "c c1 3 33")) } -func (s *testIntegrationSuite) TestIndexJoinOnClusteredIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexJoinOnClusteredIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t1") tk.MustExec("create table t (a int, b varchar(20), c decimal(40,10), d int, primary key(a,b), key(c))") tk.MustExec(`insert into t values (1,"111",1.1,11), (2,"222",2.2,12), (3,"333",3.3,13)`) @@ -2425,22 +2643,26 @@ func (s *testIntegrationSuite) TestIndexJoinOnClusteredIndex(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery("explain format = 'brief'" + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) } } -func (s *testIntegrationSerialSuite) TestIssue18984(c *C) { - tk := testkit.NewTestKit(c, s.store) + +func TestIssue18984(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t, t2") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("create table t(a int, b int, c int, primary key(a, b))") tk.MustExec("create table t2(a int, b int, c int, d int, primary key(a,b), index idx(c))") tk.MustExec("insert into t values(1,1,1), (2,2,2), (3,3,3)") @@ -2456,8 +2678,413 @@ func (s *testIntegrationSerialSuite) TestIssue18984(c *C) { "3 3 3 2 4 3 5")) } -func (s *testIntegrationSuite) TestDistinctScalarFunctionPushDown(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBitColumnPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1(a bit(8), b int)") + tk.MustExec("create table t2(a bit(8), b int)") + tk.MustExec("insert into t1 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)") + tk.MustExec("insert into t2 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)") + sql := "select b from t1 where t1.b > (select min(t2.b) from t2 where t2.a < t1.a)" + tk.MustQuery(sql).Sort().Check(testkit.Rows("2", "2", "3", "3", "4", "4")) + rows := [][]interface{}{ + {"Projection_15", "root", "test.t1.b"}, + {"└─Apply_17", "root", "CARTESIAN inner join, other cond:gt(test.t1.b, Column#7)"}, + {" ├─TableReader_20(Build)", "root", "data:Selection_19"}, + {" │ └─Selection_19", "cop[tikv]", "not(isnull(test.t1.b))"}, + {" │ └─TableFullScan_18", "cop[tikv]", "keep order:false, stats:pseudo"}, + {" └─Selection_21(Probe)", "root", "not(isnull(Column#7))"}, + {" └─StreamAgg_23", "root", "funcs:min(test.t2.b)->Column#7"}, + {" └─TopN_24", "root", "test.t2.b, offset:0, count:1"}, + {" └─TableReader_32", "root", "data:TopN_31"}, + {" └─TopN_31", "cop[tikv]", "test.t2.b, offset:0, count:1"}, + {" └─Selection_30", "cop[tikv]", "lt(test.t2.a, test.t1.a), not(isnull(test.t2.b))"}, + {" └─TableFullScan_29", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + tk.MustExec("insert t1 values ('A', 1);") + sql = "select a from t1 where ascii(a)=65" + tk.MustQuery(sql).Check(testkit.Rows("A")) + rows = [][]interface{}{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(concat(cast(test.t1.a, var_string(1)), "A"), "AA")` + sql = "select a from t1 where concat(a, 'A')='AA'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(cast(test.t1.a, binary(1)), "A")` + sql = "select a from t1 where binary a='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(cast(test.t1.a, var_string(1)), "A")` + sql = "select a from t1 where cast(a as char)='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + tk.MustExec("insert into mysql.expr_pushdown_blacklist values('bit', 'tikv','');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = [][]interface{}{ + {"Selection_5", "root", `eq(cast(test.t1.a, var_string(1)), "A")`}, + {"└─TableReader_7", "root", "data:TableFullScan_6"}, + {" └─TableFullScan_6", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + sql = "select a from t1 where cast(a as char)='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name='bit'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + sql = "select a from t1 where ascii(a)=65" + tk.MustQuery(sql).Check(testkit.Rows("A")) + rows = [][]interface{}{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + // test collation + tk.MustExec("update mysql.tidb set VARIABLE_VALUE='True' where VARIABLE_NAME='new_collation_enabled'") + tk.MustQuery("SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME='new_collation_enabled';").Check( + testkit.Rows("True")) + tk.MustExec("create table t3 (a bit(8));") + tk.MustExec("insert into t3 values (65)") + tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_bin") + tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows()) + tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_general_ci") + tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows("A")) +} + +func TestSysdatePushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))") + tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, 'abc', '2021-12-12')") + rows := [][]interface{}{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "gt(test.t.d, sysdate())"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + // assert sysdate isn't now after set global tidb_sysdate_is_now in the same session + tk.MustExec("set global tidb_sysdate_is_now='1'") + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + + // assert sysdate is now after set global tidb_sysdate_is_now in the new session + tk = testkit.NewTestKit(t, store) + tk.MustExec("use test") + now := time.Now() + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix()))) + rows[1][2] = fmt.Sprintf("gt(test.t.d, %v)", now.Format("2006-01-02 15:04:05")) + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + failpoint.Disable("github.com/pingcap/tidb/expression/injectNow") + + // assert sysdate isn't now after set session tidb_sysdate_is_now false in the same session + tk.MustExec("set tidb_sysdate_is_now='0'") + rows[1][2] = "gt(test.t.d, sysdate())" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) +} + +func TestTimeScalarFunctionPushDownResult(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(col1 datetime, col2 datetime, y int(8), m int(8), d int(8)) CHARSET=utf8 COLLATE=utf8_general_ci;") + tk.MustExec("insert into t values ('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59', 9999, 12, 31);") + testcases := []struct { + sql string + function string + }{ + { + sql: "select col1, hour(col1) from t where hour(col1)=hour('2022-03-24 01:02:03.040506');", + function: "hour", + }, + { + sql: "select col1, month(col1) from t where month(col1)=month('2022-03-24 01:02:03.040506');", + function: "month", + }, + { + sql: "select col1, minute(col1) from t where minute(col1)=minute('2022-03-24 01:02:03.040506');", + function: "minute", + }, + { + function: "second", + sql: "select col1, second(col1) from t where second(col1)=second('2022-03-24 01:02:03.040506');", + }, + { + function: "microsecond", + sql: "select col1, microsecond(col1) from t where microsecond(col1)=microsecond('2022-03-24 01:02:03.040506');", + }, + { + function: "dayName", + sql: "select col1, dayName(col1) from t where dayName(col1)=dayName('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfMonth", + sql: "select col1, dayOfMonth(col1) from t where dayOfMonth(col1)=dayOfMonth('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfWeek", + sql: "select col1, dayOfWeek(col1) from t where dayOfWeek(col1)=dayOfWeek('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfYear", + sql: "select col1, dayOfYear(col1) from t where dayOfYear(col1)=dayOfYear('2022-03-24 01:02:03.040506');", + }, + { + function: "Date", + sql: "select col1, Date(col1) from t where Date(col1)=Date('2022-03-24 01:02:03.040506');", + }, + { + function: "Week", + sql: "select col1, Week(col1) from t where Week(col1)=Week('2022-03-24 01:02:03.040506');", + }, + { + function: "time_to_sec", + sql: "select col1, time_to_sec (col1) from t where time_to_sec(col1)=time_to_sec('2022-03-24 01:02:03.040506');", + }, + { + function: "DateDiff", + sql: "select col1, DateDiff(col1, col2) from t where DateDiff(col1, col2)=DateDiff('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59');", + }, + { + function: "MonthName", + sql: "select col1, MonthName(col1) from t where MonthName(col1)=MonthName('2022-03-24 01:02:03.040506');", + }, + { + function: "MakeDate", + sql: "select col1, MakeDate(9999, 31) from t where MakeDate(y, d)=MakeDate(9999, 31);", + }, + { + function: "MakeTime", + sql: "select col1, MakeTime(12, 12, 31) from t where MakeTime(m, m, d)=MakeTime(12, 12, 31);", + }, + } + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + for _, testcase := range testcases { + r1 := tk.MustQuery(testcase.sql).Rows() + tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function)) + tk.MustExec("admin reload expr_pushdown_blacklist;") + r2 := tk.MustQuery(testcase.sql).Rows() + require.EqualValues(t, r2, r1, testcase.sql) + } + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") +} + +func TestNumberFunctionPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int signed, b int unsigned,c double)") + tk.MustExec("insert into t values (-1,61,4.4)") + testcases := []struct { + sql string + function string + }{ + { + sql: "select a, mod(a,2) from t where mod(-1,2)=mod(a,2);", + function: "mod", + }, + { + sql: "select b, mod(b,2) from t where mod(61,2)=mod(b,2);", + function: "mod", + }, + { + sql: "select b,unhex(b) from t where unhex(61) = unhex(b)", + function: "unhex", + }, + { + sql: "select b, oct(b) from t where oct(61) = oct(b)", + function: "oct", + }, + { + sql: "select c, sin(c) from t where sin(4.4) = sin(c)", + function: "sin", + }, + { + sql: "select c, asin(c) from t where asin(4.4) = asin(c)", + function: "asin", + }, + { + sql: "select c, cos(c) from t where cos(4.4) = cos(c)", + function: "cos", + }, + { + sql: "select c, acos(c) from t where acos(4.4) = acos(c)", + function: "acos", + }, + { + sql: "select b,atan(b) from t where atan(61)=atan(b)", + function: "atan", + }, + { + sql: "select b, atan2(b, c) from t where atan2(61,4.4)=atan2(b,c)", + function: "atan2", + }, + { + sql: "select b,cot(b) from t where cot(61)=cot(b)", + function: "cot", + }, + { + sql: "select c from t where pi() < c", + function: "pi", + }, + } + for _, testcase := range testcases { + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + r1 := tk.MustQuery(testcase.sql).Rows() + tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function)) + tk.MustExec("admin reload expr_pushdown_blacklist;") + r2 := tk.MustQuery(testcase.sql).Rows() + require.EqualValues(t, r2, r1, testcase.sql) + } +} + +func TestScalarFunctionPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))") + tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, 'abc', '2021-12-12')") + rows := [][]interface{}{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "right(test.t.c, 1)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where right(c,1);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "mod(test.t.id, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id, test.t.id2)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id2);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id2, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id2, test.t.id2)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id2);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "sin(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where sin(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "asin(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where asin(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "cos(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where cos(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "acos(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where acos(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "atan(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "atan2(cast(test.t.id, double BINARY), cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan2(id,id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "hour(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "hour(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "minute(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where minute(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "second(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where second(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "month(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where month(d);"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "dayname(test.t.d)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayname(d);"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "dayofmonth(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayofmonth(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "from_days(test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where from_days(id);"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "last_day(test.t.d)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where last_day(d);"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "gt(4, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where pi() > id;"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "truncate(test.t.id, 0)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where truncate(id,0)"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "round(test.t.b)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where round(b)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "date(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where date(d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "week(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where week(d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "datediff(test.t.d, test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where datediff(d,d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "gt(test.t.d, sysdate())" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "ascii(cast(test.t.e, var_string(2)))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where ascii(e);"). + CheckAt([]int{0, 3, 6}, rows) +} + +func TestDistinctScalarFunctionPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int not null, b int not null, c int not null, primary key (a,c)) partition by range (c) (partition p0 values less than (5), partition p1 values less than (10))") @@ -2467,8 +3094,10 @@ func (s *testIntegrationSuite) TestDistinctScalarFunctionPushDown(c *C) { )) } -func (s *testIntegrationSerialSuite) TestExplainAnalyzePointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainAnalyzePointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(20))") @@ -2478,19 +3107,21 @@ func (s *testIntegrationSerialSuite) TestExplainAnalyzePointGet(c *C) { checkExplain := func(rpc string) { resBuff := bytes.NewBufferString("") for _, row := range res.Rows() { - fmt.Fprintf(resBuff, "%s\n", row) + _, _ = fmt.Fprintf(resBuff, "%s\n", row) } explain := resBuff.String() - c.Assert(strings.Contains(explain, rpc+":{num_rpc:"), IsTrue, Commentf("%s", explain)) - c.Assert(strings.Contains(explain, "total_time:"), IsTrue, Commentf("%s", explain)) + require.Containsf(t, explain, rpc+":{num_rpc:", "%s", explain) + require.Containsf(t, explain, "total_time:", "%s", explain) } checkExplain("Get") res = tk.MustQuery("explain analyze select * from t where a in (1,2,3);") checkExplain("BatchGet") } -func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainAnalyzeDML(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(" create table t (a int, b int, unique index (a));") @@ -2500,19 +3131,21 @@ func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML(c *C) { checkExplain := func(rpc string) { resBuff := bytes.NewBufferString("") for _, row := range res.Rows() { - fmt.Fprintf(resBuff, "%s\n", row) + _, _ = fmt.Fprintf(resBuff, "%s\n", row) } explain := resBuff.String() - c.Assert(strings.Contains(explain, rpc+":{num_rpc:"), IsTrue, Commentf("%s", explain)) - c.Assert(strings.Contains(explain, "total_time:"), IsTrue, Commentf("%s", explain)) + require.Containsf(t, explain, rpc+":{num_rpc:", "%s", explain) + require.Containsf(t, explain, "total_time:", "%s", explain) } checkExplain("Get") res = tk.MustQuery("explain analyze insert ignore into t values (1,1),(2,2),(3,3),(4,4);") checkExplain("BatchGet") } -func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainAnalyzeDML2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") cases := []struct { @@ -2586,10 +3219,10 @@ func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML2(c *C) { res := tk.MustQuery("explain analyze " + ca.sql) resBuff := bytes.NewBufferString("") for _, row := range res.Rows() { - fmt.Fprintf(resBuff, "%s\t", row) + _, _ = fmt.Fprintf(resBuff, "%s\t", row) } explain := resBuff.String() - c.Assert(explain, Matches, ca.planRegexp, Commentf("idx: %v,sql: %v", i, ca.sql)) + require.Regexpf(t, ca.planRegexp, explain, "idx: %v,sql: %v", i, ca.sql) } } @@ -2604,15 +3237,17 @@ func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML2(c *C) { res := tk.MustQuery("explain analyze " + ca.sql) resBuff := bytes.NewBufferString("") for _, row := range res.Rows() { - fmt.Fprintf(resBuff, "%s\t", row) + _, _ = fmt.Fprintf(resBuff, "%s\t", row) } explain := resBuff.String() - c.Assert(strings.Contains(explain, "auto_id_allocator"), IsFalse, Commentf("sql: %v, explain: %v", ca.sql, explain)) + require.NotContainsf(t, explain, "auto_id_allocator", "sql: %v, explain: %v", ca.sql, explain) } } -func (s *testIntegrationSuite) TestPartitionExplain(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionExplain(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table pt (id int, c int, key i_id(id), key i_c(c)) partition by range (c) ( partition p0 values less than (4), @@ -2626,18 +3261,21 @@ partition p2 values less than (10))`) SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) }) tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestPartialBatchPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartialBatchPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c_int int, c_str varchar(40), primary key(c_int, c_str))") @@ -2650,8 +3288,10 @@ func (s *testIntegrationSuite) TestPartialBatchPointGet(c *C) { )) } -func (s *testIntegrationSuite) TestIssue19926(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue19926(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ta;") tk.MustExec("drop table if exists tb;") @@ -2667,8 +3307,10 @@ func (s *testIntegrationSuite) TestIssue19926(c *C) { tk.MustQuery("SELECT tc.status,v.id FROM tc, v WHERE tc.id = v.id AND v.status = '11';").Check(testkit.Rows("1 1")) } -func (s *testIntegrationSuite) TestDeleteUsingJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDeleteUsingJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int primary key, b int)") @@ -2680,13 +3322,12 @@ func (s *testIntegrationSuite) TestDeleteUsingJoin(c *C) { tk.MustQuery("select * from t2").Check(testkit.Rows("2 2")) } -func (s *testIntegrationSerialSuite) Test19942(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - - tk := testkit.NewTestKit(c, s.store) +func Test19942(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("CREATE TABLE test.`t` (" + " `a` int(11) NOT NULL," + " `b` varchar(10) COLLATE utf8_general_ci NOT NULL," + @@ -2708,7 +3349,7 @@ func (s *testIntegrationSerialSuite) Test19942(c *C) { tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (6, ' E', 'é ', ' E');") mkr := func() [][]interface{} { - return testutil.RowsWithSep("|", + return testkit.RowsWithSep("|", "3| 3 | 3 | 3", "2| 2 0| 2", "5| A | A | A", @@ -2725,8 +3366,10 @@ func (s *testIntegrationSerialSuite) Test19942(c *C) { tk.MustExec("admin check table t") } -func (s *testIntegrationSuite) TestPartitionUnionWithPPruningColumn(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPartitionUnionWithPPruningColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("CREATE TABLE `t` (\n `fid` bigint(36) NOT NULL,\n `oty` varchar(30) DEFAULT NULL,\n `oid` int(11) DEFAULT NULL,\n `pid` bigint(20) DEFAULT NULL,\n `bid` int(11) DEFAULT NULL,\n `r5` varchar(240) DEFAULT '',\n PRIMARY KEY (`fid`)\n)PARTITION BY HASH( `fid` ) PARTITIONS 4;") @@ -2781,8 +3424,10 @@ func (s *testIntegrationSuite) TestPartitionUnionWithPPruningColumn(c *C) { "3290 LE1327_r5")) } -func (s *testIntegrationSuite) TestIssue20139(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20139(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2797,19 +3442,24 @@ func (s *testIntegrationSuite) TestIssue20139(c *C) { tk.MustExec("drop table t") } -func (s *testIntegrationSuite) TestIssue14481(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue14481(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int default null, b int default null, c int default null)") plan := tk.MustQuery("explain format = 'brief' select * from t where a = 1 and a = 2") - plan.Check(testkit.Rows("TableDual 8000.00 root rows:0")) + plan.Check(testkit.Rows("TableDual 0.00 root rows:0")) tk.MustExec("drop table t") } -func (s *testIntegrationSerialSuite) TestIssue20710(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestIssue20710(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("drop table if exists s;") tk.MustExec("create table t(a int, b int)") @@ -2822,30 +3472,35 @@ func (s *testIntegrationSerialSuite) TestIssue20710(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestQueryBlockTableAliasInHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestQueryBlockTableAliasInHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - c.Assert(tk.HasPlan("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2", "HashJoin"), IsTrue) + require.True(t, tk.HasPlan("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2", "HashJoin")) tk.MustQuery("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2").Check(testkit.Rows( "1 2", )) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 0) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 0) } -func (s *testIntegrationSuite) TestIssue10448(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue10448(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") @@ -2854,8 +3509,10 @@ func (s *testIntegrationSuite) TestIssue10448(c *C) { tk.MustQuery("select a from (select pk as a from t) t1 where a = 18446744073709551615").Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestMultiUpdateOnPrimaryKey(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiUpdateOnPrimaryKey(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -2900,8 +3557,10 @@ func (s *testIntegrationSuite) TestMultiUpdateOnPrimaryKey(c *C) { tk.MustQuery("select * from t").Check(testkit.Rows("11 12")) } -func (s *testIntegrationSuite) TestOrderByHavingNotInSelect(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderByHavingNotInSelect(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ttest") tk.MustExec("create table ttest (v1 int, v2 int)") @@ -2917,15 +3576,20 @@ func (s *testIntegrationSuite) TestOrderByHavingNotInSelect(c *C) { } -func (s *testIntegrationSuite) TestUpdateSetDefault(c *C) { +func TestUpdateSetDefault(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // #20598 - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table tt (x int, z int as (x+10) stored)") tk.MustExec("insert into tt(x) values (1)") tk.MustExec("update tt set x=2, z = default") + tk.MustExec("update tt set x=2, z = default(z)") tk.MustQuery("select * from tt").Check(testkit.Rows("2 12")) + tk.MustGetErrMsg("update tt set x=2, z = default(x)", + "[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.") tk.MustGetErrMsg("update tt set z = 123", "[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.") tk.MustGetErrMsg("update tt as ss set z = 123", @@ -2936,8 +3600,10 @@ func (s *testIntegrationSuite) TestUpdateSetDefault(c *C) { "[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.") } -func (s *testIntegrationSuite) TestExtendedStatsSwitch(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExtendedStatsSwitch(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null, b int not null, key(a), key(b))") @@ -2989,8 +3655,10 @@ func (s *testIntegrationSuite) TestExtendedStatsSwitch(c *C) { )) } -func (s *testIntegrationSuite) TestOrderByNotInSelectDistinct(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderByNotInSelectDistinct(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // #12442 @@ -3029,9 +3697,11 @@ func (s *testIntegrationSuite) TestOrderByNotInSelectDistinct(c *C) { tk.MustQuery("select distinct v1 as z from ttest order by v1+z").Check(testkit.Rows("1", "4")) } -func (s *testIntegrationSuite) TestInvalidNamedWindowSpec(c *C) { +func TestInvalidNamedWindowSpec(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // #12356 - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("DROP TABLE IF EXISTS temptest") tk.MustExec("create table temptest (val int, val1 int)") @@ -3044,8 +3714,10 @@ func (s *testIntegrationSuite) TestInvalidNamedWindowSpec(c *C) { "[planner:1054]Unknown column 'a' in 'window partition by'") } -func (s *testIntegrationSuite) TestCorrelatedAggregate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCorrelatedAggregate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // #18350 @@ -3124,8 +3796,10 @@ func (s *testIntegrationSuite) TestCorrelatedAggregate(c *C) { Check(testkit.Rows("6 6 6 6")) } -func (s *testIntegrationSuite) TestCorrelatedColumnAggFuncPushDown(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCorrelatedColumnAggFuncPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int, b int);") @@ -3136,8 +3810,10 @@ func (s *testIntegrationSuite) TestCorrelatedColumnAggFuncPushDown(c *C) { } // Test for issue https://github.com/pingcap/tidb/issues/21607. -func (s *testIntegrationSuite) TestConditionColPruneInPhysicalUnionScan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestConditionColPruneInPhysicalUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int, b int);") @@ -3156,8 +3832,10 @@ func (s *testIntegrationSuite) TestConditionColPruneInPhysicalUnionScan(c *C) { Check(testkit.Rows("0")) } -func (s *testIntegrationSuite) TestInvalidHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestInvalidHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tt") @@ -3169,21 +3847,24 @@ func (s *testIntegrationSuite) TestInvalidHint(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) warning := "show warnings;" for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warnings = s.testData.ConvertRowsToStrings(tk.MustQuery(warning).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery(warning).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } // Test for issue https://github.com/pingcap/tidb/issues/18320 -func (s *testIntegrationSuite) TestNonaggregateColumnWithSingleValueInOnlyFullGroupByMode(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNonaggregateColumnWithSingleValueInOnlyFullGroupByMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, c int)") @@ -3195,8 +3876,10 @@ func (s *testIntegrationSuite) TestNonaggregateColumnWithSingleValueInOnlyFullGr tk.MustQuery("select a from t where a = 1 having count(b) > 0").Check(testkit.Rows("1")) } -func (s *testIntegrationSuite) TestConvertRangeToPoint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestConvertRangeToPoint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0") @@ -3223,19 +3906,22 @@ func (s *testIntegrationSuite) TestConvertRangeToPoint(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIssue22040(c *C) { +func TestIssue22040(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // #22040 - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int, b int, primary key(a,b))") @@ -3244,16 +3930,18 @@ func (s *testIntegrationSuite) TestIssue22040(c *C) { // invalid case, column count doesn't match { err := tk.ExecToErr("select * from t where (a,b) in (1,2)") - c.Assert(errors.Cause(err), FitsTypeOf, expression.ErrOperandColumns) + require.IsType(t, expression.ErrOperandColumns, errors.Cause(err)) } { err := tk.ExecToErr("select * from t where (a,b) in ((1,2),1)") - c.Assert(errors.Cause(err), FitsTypeOf, expression.ErrOperandColumns) + require.IsType(t, expression.ErrOperandColumns, errors.Cause(err)) } } -func (s *testIntegrationSuite) TestIssue22105(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22105(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -3279,18 +3967,21 @@ func (s *testIntegrationSuite) TestIssue22105(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIssue22071(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22071(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (a int);") tk.MustExec("insert into t values(1),(2),(5)") @@ -3298,12 +3989,14 @@ func (s *testIntegrationSuite) TestIssue22071(c *C) { tk.MustQuery("select n in (1,n) from (select a in (1,2) as n from t) g;").Check(testkit.Rows("1", "1", "1")) } -func (s *testIntegrationSuite) TestCreateViewIsolationRead(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) - tk := testkit.NewTestKit(c, s.store) - tk.Se = se +func TestCreateViewIsolationRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk := testkit.NewTestKit(t, store) + tk.SetSession(se) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") @@ -3316,8 +4009,10 @@ func (s *testIntegrationSuite) TestCreateViewIsolationRead(c *C) { tk.MustQuery("select * from v0;").Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestIssue22199(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22199(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(i int primary key, j int, index idx_j(j))") @@ -3325,8 +4020,10 @@ func (s *testIntegrationSuite) TestIssue22199(c *C) { tk.MustGetErrMsg("select t1.*, (select t2.* from t1) from t1", "[planner:1051]Unknown table 't2'") } -func (s *testIntegrationSuite) TestIssue22892(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22892(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='static'") tk.MustExec("drop table if exists t1") @@ -3341,8 +4038,10 @@ func (s *testIntegrationSuite) TestIssue22892(c *C) { tk.MustQuery("select * from t2 where a not between 1 and 2;").Check(testkit.Rows("0")) } -func (s *testIntegrationSuite) TestIssue26719(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26719(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table tx (a int) partition by range (a) (partition p0 values less than (10), partition p1 values less than (20))`) tk.MustExec(`insert into tx values (1)`) @@ -3355,8 +4054,34 @@ func (s *testIntegrationSuite) TestIssue26719(c *C) { tk.MustExec(`rollback`) } -func (s *testIntegrationSerialSuite) TestPushDownProjectionForTiFlash(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue32428(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table `t1` (`a` enum('aa') DEFAULT NULL, KEY `k` (`a`))") + tk.MustExec("insert into t1 values('aa')") + tk.MustExec("insert into t1 values(null)") + tk.MustQuery("select a from t1 where a<=>'aa'").Check(testkit.Rows("aa")) + tk.MustQuery("select a from t1 where a<=>null").Check(testkit.Rows("")) + + tk.MustExec(`CREATE TABLE IDT_MULTI15860STROBJSTROBJ ( + COL1 enum('aa') DEFAULT NULL, + COL2 int(41) DEFAULT NULL, + COL3 year(4) DEFAULT NULL, + KEY U_M_COL4 (COL1,COL2), + KEY U_M_COL5 (COL3,COL2))`) + tk.MustExec(`insert into IDT_MULTI15860STROBJSTROBJ values("aa", 1013610488, 1982)`) + tk.MustQuery(`SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = "aa"`).Check(testkit.Rows()) // empty result + tk.MustExec(`prepare stmt from "SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = ?"`) + tk.MustExec(`set @a="aa"`) + tk.MustQuery(`execute stmt using @a`).Check(testkit.Rows()) // empty result +} + +func TestPushDownProjectionForTiFlash(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int, value decimal(6,3), name char(128))") @@ -3364,10 +4089,10 @@ func (s *testIntegrationSerialSuite) TestPushDownProjectionForTiFlash(c *C) { tk.MustExec("set session tidb_allow_mpp=OFF") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3377,36 +4102,37 @@ func (s *testIntegrationSerialSuite) TestPushDownProjectionForTiFlash(c *C) { } } - tk.MustExec("set @@tidb_opt_broadcast_join=1;") - var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestPushDownProjectionForMPP(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushDownProjectionForMPP(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int, value decimal(6,3), name char(128))") tk.MustExec("analyze table t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3416,26 +4142,29 @@ func (s *testIntegrationSerialSuite) TestPushDownProjectionForMPP(c *C) { } } - tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_opt_broadcast_join=0; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestReorderSimplifiedOuterJoins(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestReorderSimplifiedOuterJoins(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2,t3") @@ -3448,19 +4177,22 @@ func (s *testIntegrationSuite) TestReorderSimplifiedOuterJoins(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } // Apply operator may got panic because empty Projection is eliminated. -func (s *testIntegrationSerialSuite) TestIssue23887(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23887(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b int);") @@ -3471,12 +4203,13 @@ func (s *testIntegrationSerialSuite) TestIssue23887(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...)) @@ -3487,8 +4220,10 @@ func (s *testIntegrationSerialSuite) TestIssue23887(c *C) { tk.MustQuery("select count(1) from (select count(1) from (select * from t1 where c3 = 100) k) k2;").Check(testkit.Rows("1")) } -func (s *testIntegrationSerialSuite) TestDeleteStmt(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDeleteStmt(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int)") tk.MustExec("delete t from t;") @@ -3501,8 +4236,10 @@ func (s *testIntegrationSerialSuite) TestDeleteStmt(c *C) { tk.MustGetErrCode("delete test.t from t;", mysql.ErrUnknownTable) } -func (s *testIntegrationSuite) TestIndexMergeConstantTrue(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeConstantTrue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int primary key, b int not null, key(b))") @@ -3517,18 +4254,20 @@ func (s *testIntegrationSuite) TestIndexMergeConstantTrue(c *C) { tk.MustExec("delete /*+ use_index_merge(t) */ FROM t WHERE a=1 OR (a<2 and b<2)") } -func (s *testIntegrationSerialSuite) TestPushDownAggForMPP(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushDownAggForMPP(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int, value decimal(6,3))") tk.MustExec("analyze table t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3538,26 +4277,29 @@ func (s *testIntegrationSerialSuite) TestPushDownAggForMPP(c *C) { } } - tk.MustExec(" set @@tidb_allow_mpp=1; set @@tidb_opt_broadcast_join=0; set @@tidb_broadcast_join_threshold_count = 1; set @@tidb_broadcast_join_threshold_size=1;") + tk.MustExec(" set @@tidb_allow_mpp=1; set @@tidb_broadcast_join_threshold_count = 1; set @@tidb_broadcast_join_threshold_size=1;") var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMppUnionAll(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppUnionAll(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists t1") @@ -3565,10 +4307,10 @@ func (s *testIntegrationSerialSuite) TestMppUnionAll(c *C) { tk.MustExec("create table t1 (a int, b int not null, c double)") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" || tblInfo.Name.L == "t1" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3583,11 +4325,12 @@ func (s *testIntegrationSerialSuite) TestMppUnionAll(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) @@ -3595,8 +4338,10 @@ func (s *testIntegrationSerialSuite) TestMppUnionAll(c *C) { } -func (s *testIntegrationSerialSuite) TestMppJoinDecimal(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppJoinDecimal(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("drop table if exists tt") @@ -3606,10 +4351,10 @@ func (s *testIntegrationSerialSuite) TestMppJoinDecimal(c *C) { tk.MustExec("analyze table tt") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" || tblInfo.Name.L == "tt" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3628,29 +4373,32 @@ func (s *testIntegrationSerialSuite) TestMppJoinDecimal(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestMppAggTopNWithJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMppAggTopNWithJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int, value decimal(6,3))") tk.MustExec("analyze table t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -3667,19 +4415,22 @@ func (s *testIntegrationSerialSuite) TestMppAggTopNWithJoin(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestLimitIndexLookUpKeepOrder(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestLimitIndexLookUpKeepOrder(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b int, c int, d int, index idx(a,b,c));") @@ -3689,18 +4440,21 @@ func (s *testIntegrationSerialSuite) TestLimitIndexLookUpKeepOrder(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestDecorrelateInnerJoinInSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestDecorrelateInnerJoinInSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -3711,18 +4465,21 @@ func (s *testIntegrationSuite) TestDecorrelateInnerJoinInSubquery(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIndexMergeTableFilter(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeTableFilter(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int, b int, c int, d int, key(a), key(b));") @@ -3750,16 +4507,20 @@ func (s *testIntegrationSuite) TestIndexMergeTableFilter(c *C) { )) } -func (s *testIntegrationSuite) TestIssue22850(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22850(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("CREATE TABLE t1 (a int(11))") tk.MustQuery("SELECT @v:=(SELECT 1 FROM t1 t2 LEFT JOIN t1 ON t1.a GROUP BY t1.a) FROM t1").Check(testkit.Rows()) // work fine } -func (s *testIntegrationSuite) TestJoinSchemaChange(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestJoinSchemaChange(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int(11))") @@ -3768,8 +4529,10 @@ func (s *testIntegrationSuite) TestJoinSchemaChange(c *C) { } // #22949: test HexLiteral Used in GetVar expr -func (s *testIntegrationSuite) TestGetVarExprWithHexLiteral(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGetVarExprWithHexLiteral(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1_no_idx;") tk.MustExec("create table t1_no_idx(id int, col_bit bit(16));") @@ -3818,8 +4581,10 @@ func (s *testIntegrationSuite) TestGetVarExprWithHexLiteral(c *C) { } // test BitLiteral used with GetVar -func (s *testIntegrationSuite) TestGetVarExprWithBitLiteral(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGetVarExprWithBitLiteral(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t1_no_idx;") tk.MustExec("create table t1_no_idx(id int, col_bit bit(16));") @@ -3837,8 +4602,10 @@ func (s *testIntegrationSuite) TestGetVarExprWithBitLiteral(c *C) { tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1")) } -func (s *testIntegrationSuite) TestIndexMergeClusterIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIndexMergeClusterIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 float, c2 int, c3 int, primary key (c1) /*T![clustered_index] CLUSTERED */, key idx_1 (c2), key idx_2 (c3))") @@ -3856,8 +4623,10 @@ func (s *testIntegrationSuite) TestIndexMergeClusterIndex(c *C) { )) } -func (s *testIntegrationSuite) TestMultiColMaxOneRow(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMultiColMaxOneRow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2") @@ -3869,18 +4638,21 @@ func (s *testIntegrationSuite) TestMultiColMaxOneRow(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIssue23736(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23736(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t0, t1") tk.MustExec("create table t0(a int, b int, c int as (a + b) virtual, unique index (c) invisible);") @@ -3894,26 +4666,30 @@ func (s *testIntegrationSuite) TestIssue23736(c *C) { tk.MustQuery("select /*+ nth_plan(3) */ count(1) from t0 where c > 10 and b < 2;").Check(testkit.Rows("0")) // Should not use invisible index - c.Assert(tk.MustUseIndex("select /*+ stream_agg() */ count(1) from t0 where c > 10 and b < 2", "c"), IsFalse) + require.False(t, tk.MustUseIndex("select /*+ stream_agg() */ count(1) from t0 where c > 10 and b < 2", "c")) } // https://github.com/pingcap/tidb/issues/23802 -func (s *testIntegrationSuite) TestPanicWhileQueryTableWithIsNull(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPanicWhileQueryTableWithIsNull(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists NT_HP27193") tk.MustExec("CREATE TABLE `NT_HP27193` ( `COL1` int(20) DEFAULT NULL, `COL2` varchar(20) DEFAULT NULL, `COL4` datetime DEFAULT NULL, `COL3` bigint(20) DEFAULT NULL, `COL5` float DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin PARTITION BY HASH ( `COL1`%`COL3` ) PARTITIONS 10;") _, err := tk.Exec("select col1 from NT_HP27193 where col1 is null;") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("INSERT INTO NT_HP27193 (COL2, COL4, COL3, COL5) VALUES ('m', '2020-05-04 13:15:27', 8, 2602)") _, err = tk.Exec("select col1 from NT_HP27193 where col1 is null;") - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("drop table if exists NT_HP27193") } -func (s *testIntegrationSuite) TestIssue23846(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23846(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a varbinary(10),UNIQUE KEY(a))") @@ -3922,8 +4698,10 @@ func (s *testIntegrationSuite) TestIssue23846(c *C) { tk.MustQuery("select * from t where a=0x00A4EEF4FA55D6706ED5").Check(testkit.Rows("\x00\xa4\xee\xf4\xfaU\xd6pn\xd5")) // not empty } -func (s *testIntegrationSuite) TestIssue23839(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23839(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists BB") tk.MustExec("CREATE TABLE `BB` (\n" + @@ -3942,8 +4720,10 @@ func (s *testIntegrationSuite) TestIssue23839(c *C) { } // https://github.com/pingcap/tidb/issues/24095 -func (s *testIntegrationSuite) TestIssue24095(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue24095(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("create table t (id int, value decimal(10,5));") @@ -3954,18 +4734,21 @@ func (s *testIntegrationSuite) TestIssue24095(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIssue24281(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue24281(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists member, agent, deposit, view_member_agents") tk.MustExec("create table member(login varchar(50) NOT NULL, agent_login varchar(100) DEFAULT NULL, PRIMARY KEY(login))") @@ -3981,8 +4764,10 @@ func (s *testIntegrationSuite) TestIssue24281(c *C) { "UNION select 1 as v1, 2 as v2") } -func (s *testIntegrationSuite) TestIssue25799(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue25799(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec(`create table t1 (a float default null, b smallint(6) DEFAULT NULL)`) @@ -3993,8 +4778,10 @@ func (s *testIntegrationSuite) TestIssue25799(c *C) { tk.MustQuery(`select /*+ TIDB_INLJ(t2@sel_2) */ t1.a, t1.b from t1 where t1.a not in (select t2.a from t2 where t1.b=t2.b)`).Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestLimitWindowColPrune(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestLimitWindowColPrune(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") @@ -4002,34 +4789,39 @@ func (s *testIntegrationSuite) TestLimitWindowColPrune(c *C) { tk.MustQuery("select count(a) f1, row_number() over (order by count(a)) as f2 from t limit 1").Check(testkit.Rows("1 1")) } -func (s *testIntegrationSuite) TestIncrementalAnalyzeStatsVer2(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIncrementalAnalyzeStatsVer2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b int, index idx_b(b))") tk.MustExec("insert into t values(1,1),(2,2),(3,3)") tk.MustExec("set @@session.tidb_analyze_version = 2") tk.MustExec("analyze table t") - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblID := tbl.Meta().ID rows := tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d and is_index = 1", tblID)).Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][0], Equals, "3") + require.Len(t, rows, 1) + require.Equal(t, "3", rows[0][0]) tk.MustExec("insert into t values(4,4),(5,5),(6,6)") tk.MustExec("analyze incremental table t index idx_b") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 3) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, "The version 2 would collect all statistics not only the selected indexes") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[1].Err.Error(), Equals, "The version 2 stats would ignore the INCREMENTAL keyword and do full sampling") - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[2].Err.Error(), Equals, "Analyze use auto adjusted sample rate 1.000000 for table test.t.") + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warns, 3) + require.EqualError(t, warns[0].Err, "The version 2 would collect all statistics not only the selected indexes") + require.EqualError(t, warns[1].Err, "The version 2 stats would ignore the INCREMENTAL keyword and do full sampling") + require.EqualError(t, warns[2].Err, "Analyze use auto adjusted sample rate 1.000000 for table test.t") rows = tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d and is_index = 1", tblID)).Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][0], Equals, "6") + require.Len(t, rows, 1) + require.Equal(t, "6", rows[0][0]) } -func (s *testIntegrationSuite) TestConflictReadFromStorage(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestConflictReadFromStorage(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(`create table t ( @@ -4041,10 +4833,10 @@ func (s *testIntegrationSuite) TestConflictReadFromStorage(c *C) { partition p2 values less than(16));`) tk.MustExec(`insert into t values (1,1,"1"), (2,2,"2"), (8,8,"8"), (11,11,"11"), (15,15,"15")`) // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -4060,8 +4852,10 @@ func (s *testIntegrationSuite) TestConflictReadFromStorage(c *C) { } // TestSequenceAsDataSource is used to test https://github.com/pingcap/tidb/issues/24383. -func (s *testIntegrationSuite) TestSequenceAsDataSource(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSequenceAsDataSource(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop sequence if exists s1, s2") @@ -4073,20 +4867,21 @@ func (s *testIntegrationSuite) TestSequenceAsDataSource(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestIssue27167(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestIssue27167(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set names utf8mb4") tk.MustExec("use test") tk.MustExec("drop table if exists all_types") @@ -4120,10 +4915,10 @@ func (s *testIntegrationSerialSuite) TestIssue27167(c *C) { tk.MustQuery("select collation(c) from (select d_timestamp c from all_types union select d_float c from all_types) t").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin")) } -func (s *testIntegrationSerialSuite) TestIssue25300(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tk := testkit.NewTestKit(c, s.store) +func TestIssue25300(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`create table t (a char(65) collate utf8_unicode_ci, b text collate utf8_general_ci not null);`) tk.MustExec(`insert into t values ('a', 'A');`) @@ -4135,17 +4930,19 @@ func (s *testIntegrationSerialSuite) TestIssue25300(c *C) { tk.MustGetErrCode(`(select a from t) union ( select b from t) union select 'a' except select 'd';`, mysql.ErrCantAggregateNcollations) } -func (s *testIntegrationSerialSuite) TestMergeContinuousSelections(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestMergeContinuousSelections(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ts") tk.MustExec("create table ts (col_char_64 char(64), col_varchar_64_not_null varchar(64) not null, col_varchar_key varchar(1), id int primary key, col_varchar_64 varchar(64),col_char_64_not_null char(64) not null);") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "ts" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -4162,22 +4959,25 @@ func (s *testIntegrationSerialSuite) TestMergeContinuousSelections(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestSelectIgnoreTemporaryTableInView(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectIgnoreTemporaryTableInView(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) tk.MustExec("create table t1 (a int, b int)") tk.MustExec("create table t2 (c int, d int)") tk.MustExec("create view v1 as select * from t1 order by a") @@ -4203,8 +5003,10 @@ func (s *testIntegrationSerialSuite) TestSelectIgnoreTemporaryTableInView(c *C) } // TestIsMatchProp is used to test https://github.com/pingcap/tidb/issues/26017. -func (s *testIntegrationSuite) TestIsMatchProp(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIsMatchProp(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") @@ -4216,18 +5018,21 @@ func (s *testIntegrationSuite) TestIsMatchProp(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestIssue26250(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26250(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table tp (id int primary key) partition by range (id) (partition p0 values less than (100));") tk.MustExec("create table tn (id int primary key);") @@ -4236,8 +5041,10 @@ func (s *testIntegrationSerialSuite) TestIssue26250(c *C) { tk.MustQuery("select * from tp,tn where tp.id=tn.id and tn.id=1 for update;").Check(testkit.Rows("1 1")) } -func (s *testIntegrationSuite) TestCorrelationAdjustment4Limit(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCorrelationAdjustment4Limit(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (pk int primary key auto_increment, year int, c varchar(256), index idx_year(year))") @@ -4289,8 +5096,10 @@ func (s *testIntegrationSuite) TestCorrelationAdjustment4Limit(c *C) { " └─TableFullScan 51.00 cop[tikv] table:t keep order:false")) } -func (s *testIntegrationSerialSuite) TestCTESelfJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCTESelfJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2, t3") tk.MustExec("create table t1(t1a int, t1b int, t1c int)") @@ -4312,17 +5121,21 @@ func (s *testIntegrationSerialSuite) TestCTESelfJoin(c *C) { } // https://github.com/pingcap/tidb/issues/26214 -func (s *testIntegrationSerialSuite) TestIssue26214(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26214(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table `t` (`a` int(11) default null, `b` int(11) default null, `c` int(11) default null, key `expression_index` ((case when `a` < 0 then 1 else 2 end)))") _, err := tk.Exec("select * from t where case when a < 0 then 1 else 2 end <= 1 order by 4;") - c.Assert(core.ErrUnknownColumn.Equal(err), IsTrue) + require.True(t, core.ErrUnknownColumn.Equal(err)) } -func (s *testIntegrationSuite) TestCreateViewWithWindowFunc(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCreateViewWithWindowFunc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t6;") tk.MustExec("CREATE TABLE t6(t TIME, ts TIMESTAMP);") @@ -4333,8 +5146,10 @@ func (s *testIntegrationSuite) TestCreateViewWithWindowFunc(c *C) { rows.Check(testkit.Rows("1 1")) } -func (s *testIntegrationSuite) TestIssue29834(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue29834(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists IDT_MC21814;") tk.MustExec("CREATE TABLE `IDT_MC21814` (`COL1` year(4) DEFAULT NULL,`COL2` year(4) DEFAULT NULL,KEY `U_M_COL` (`COL1`,`COL2`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") @@ -4342,11 +5157,13 @@ func (s *testIntegrationSuite) TestIssue29834(c *C) { tk.MustQuery("SELECT/*+ INL_JOIN(t1, t2), nth_plan(1) */ t2.* FROM IDT_MC21814 t1 LEFT JOIN IDT_MC21814 t2 ON t1.col1 = t2.col1 WHERE t2.col2 BETWEEN 2593 AND 1971 AND t1.col1 IN (2155, 1901, 1967);").Check(testkit.Rows()) tk.MustQuery("SELECT/*+ INL_JOIN(t1, t2), nth_plan(2) */ t2.* FROM IDT_MC21814 t1 LEFT JOIN IDT_MC21814 t2 ON t1.col1 = t2.col1 WHERE t2.col2 BETWEEN 2593 AND 1971 AND t1.col1 IN (2155, 1901, 1967);").Check(testkit.Rows()) // Only can generate one index join plan. Because the index join inner child can not be tableDual. - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The parameter of nth_plan() is out of range.")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The parameter of nth_plan() is out of range")) } -func (s *testIntegrationSuite) TestIssue29221(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue29221(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_index_merge=on;") tk.MustExec("drop table if exists t;") @@ -4389,8 +5206,10 @@ func (s *testIntegrationSuite) TestIssue29221(c *C) { " └─TableRowIDScan(Probe) 3.00 cop[tikv] table:t keep order:false, stats:pseudo")) } -func (s *testIntegrationSerialSuite) TestLimitPushDown(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestLimitPushDown(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -4423,16 +5242,20 @@ func (s *testIntegrationSerialSuite) TestLimitPushDown(c *C) { ` └─TableFullScan 1.00 cop[tikv] table:t keep order:false`)) } -func (s *testIntegrationSuite) TestIssue26559(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26559(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a timestamp, b datetime);") tk.MustExec("insert into t values('2020-07-29 09:07:01', '2020-07-27 16:57:36');") tk.MustQuery("select greatest(a, b) from t union select null;").Sort().Check(testkit.Rows("2020-07-29 09:07:01", "")) } -func (s *testIntegrationSuite) TestIssue29503(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue29503(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.Status.RecordQPSbyDB = true @@ -4441,16 +5264,52 @@ func (s *testIntegrationSuite) TestIssue29503(c *C) { tk.MustExec("use test") tk.MustExec("drop table if exists t;") tk.MustExec("create table t(a int);") - err := tk.ExecToErr("create binding for select 1 using select 1;") - c.Assert(err, Equals, nil) - err = tk.ExecToErr("create binding for select a from t using select a from t;") - c.Assert(err, Equals, nil) + require.NoError(t, tk.ExecToErr("create binding for select 1 using select 1;")) + require.NoError(t, tk.ExecToErr("create binding for select a from t using select a from t;")) res := tk.MustQuery("show session bindings;") - c.Assert(len(res.Rows()), Equals, 2) -} - -func (s *testIntegrationSuite) TestHeuristicIndexSelection(c *C) { - tk := testkit.NewTestKit(c, s.store) + require.Len(t, res.Rows(), 2) +} + +func TestIndexJoinCost(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t_outer, t_inner_pk, t_inner_idx`) + tk.MustExec(`create table t_outer (a int)`) + tk.MustExec(`create table t_inner_pk (a int primary key)`) + tk.MustExec(`create table t_inner_idx (a int, b int, key(a))`) + + tk.MustQuery(`explain format=verbose select /*+ TIDB_INLJ(t_outer, t_inner_pk) */ * from t_outer, t_inner_pk where t_outer.a=t_inner_pk.a`).Check(testkit.Rows( // IndexJoin with inner TableScan + `IndexJoin_11 12487.50 193048.09 root inner join, inner:TableReader_8, outer key:test.t_outer.a, inner key:test.t_inner_pk.a, equal cond:eq(test.t_outer.a, test.t_inner_pk.a)`, + `├─TableReader_18(Build) 9990.00 36412.58 root data:Selection_17`, + `│ └─Selection_17 9990.00 465000.00 cop[tikv] not(isnull(test.t_outer.a))`, + `│ └─TableFullScan_16 10000.00 435000.00 cop[tikv] table:t_outer keep order:false, stats:pseudo`, + `└─TableReader_8(Probe) 1.00 2.54 root data:TableRangeScan_7`, + ` └─TableRangeScan_7 1.00 0.00 cop[tikv] table:t_inner_pk range: decided by [test.t_outer.a], keep order:false, stats:pseudo`)) + tk.MustQuery(`explain format=verbose select /*+ TIDB_INLJ(t_outer, t_inner_idx) */ t_inner_idx.a from t_outer, t_inner_idx where t_outer.a=t_inner_idx.a`).Check(testkit.Rows( // IndexJoin with inner IndexScan + `IndexJoin_10 12487.50 221872.19 root inner join, inner:IndexReader_9, outer key:test.t_outer.a, inner key:test.t_inner_idx.a, equal cond:eq(test.t_outer.a, test.t_inner_idx.a)`, + `├─TableReader_20(Build) 9990.00 36412.58 root data:Selection_19`, + `│ └─Selection_19 9990.00 465000.00 cop[tikv] not(isnull(test.t_outer.a))`, + `│ └─TableFullScan_18 10000.00 435000.00 cop[tikv] table:t_outer keep order:false, stats:pseudo`, + `└─IndexReader_9(Probe) 1.25 4.56 root index:Selection_8`, + ` └─Selection_8 1.25 0.00 cop[tikv] not(isnull(test.t_inner_idx.a))`, + ` └─IndexRangeScan_7 1.25 0.00 cop[tikv] table:t_inner_idx, index:a(a) range: decided by [eq(test.t_inner_idx.a, test.t_outer.a)], keep order:false, stats:pseudo`)) + tk.MustQuery(`explain format=verbose select /*+ TIDB_INLJ(t_outer, t_inner_idx) */ * from t_outer, t_inner_idx where t_outer.a=t_inner_idx.a`).Check(testkit.Rows( // IndexJoin with inner IndexLookup + `IndexJoin_11 12487.50 529388.13 root inner join, inner:IndexLookUp_10, outer key:test.t_outer.a, inner key:test.t_inner_idx.a, equal cond:eq(test.t_outer.a, test.t_inner_idx.a)`, + `├─TableReader_23(Build) 9990.00 36412.58 root data:Selection_22`, + `│ └─Selection_22 9990.00 465000.00 cop[tikv] not(isnull(test.t_outer.a))`, + `│ └─TableFullScan_21 10000.00 435000.00 cop[tikv] table:t_outer keep order:false, stats:pseudo`, + `└─IndexLookUp_10(Probe) 1.25 35.34 root `, + ` ├─Selection_9(Build) 1.25 0.00 cop[tikv] not(isnull(test.t_inner_idx.a))`, + ` │ └─IndexRangeScan_7 1.25 0.00 cop[tikv] table:t_inner_idx, index:a(a) range: decided by [eq(test.t_inner_idx.a, test.t_outer.a)], keep order:false, stats:pseudo`, + ` └─TableRowIDScan_8(Probe) 1.25 0.00 cop[tikv] table:t_inner_idx keep order:false, stats:pseudo`)) +} + +func TestHeuristicIndexSelection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, c int, d int, e int, f int, g int, primary key (a), unique key c_d_e (c, d, e), unique key f (f), unique key f_g (f, g), key g (g))") @@ -4464,20 +5323,23 @@ func (s *testIntegrationSuite) TestHeuristicIndexSelection(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows()) - output[i].Warnings = s.testData.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows()) + output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) }) tk.MustQuery("explain format = 'verbose' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...)) } } -func (s *testIntegrationSuite) TestOutputSkylinePruningInfo(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOutputSkylinePruningInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, d int, e int, f int, g int, primary key (a), unique key c_d_e (c, d, e), unique key f (f), unique key f_g (f, g), key g (g))") @@ -4488,26 +5350,29 @@ func (s *testIntegrationSuite) TestOutputSkylinePruningInfo(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows()) - output[i].Warnings = s.testData.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows()) + output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) }) tk.MustQuery("explain format = 'verbose' " + tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...)) } } -func (s *testIntegrationSuite) TestPreferRangeScanForUnsignedIntHandle(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPreferRangeScanForUnsignedIntHandle(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int unsigned primary key, b int, c int, index idx_b(b))") tk.MustExec("insert into t values (1,2,3), (4,5,6), (7,8,9), (10,11,12), (13,14,15)") - do, _ := session.GetDomain(s.store) - c.Assert(do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + do, _ := session.GetDomain(store) + require.Nil(t, do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table t") var input []string @@ -4516,33 +5381,36 @@ func (s *testIntegrationSuite) TestPreferRangeScanForUnsignedIntHandle(c *C) { Plan []string Warnings []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt }) if strings.HasPrefix(tt, "set") { tk.MustExec(tt) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Warnings = s.testData.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...)) } } -func (s *testIntegrationSuite) TestIssue27083(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue27083(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b int, c int, index idx_b(b))") tk.MustExec("insert into t values (1,2,3), (4,5,6), (7,8,9), (10, 11, 12), (13,14,15), (16, 17, 18)") - do, _ := session.GetDomain(s.store) - c.Assert(do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + do, _ := session.GetDomain(store) + require.Nil(t, do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table t") var input []string @@ -4550,18 +5418,21 @@ func (s *testIntegrationSuite) TestIssue27083(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSuite) TestIssues27130(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssues27130(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") @@ -4599,8 +5470,10 @@ func (s *testIntegrationSuite) TestIssues27130(c *C) { )) } -func (s *testIntegrationSuite) TestIssue27242(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue27242(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists UK_MU16407") tk.MustExec("CREATE TABLE UK_MU16407 (COL3 timestamp NULL DEFAULT NULL, UNIQUE KEY U3(COL3));") @@ -4622,8 +5495,10 @@ func verifyTimestampOutOfRange(tk *testkit.TestKit) { tk.MustQuery(`select * from t28424 where t > "1970-1-1 0:0:0"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07")) } -func (s *testIntegrationSuite) TestIssue28424(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue28424(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t28424, dt28242") @@ -4648,8 +5523,10 @@ func (s *testIntegrationSuite) TestIssue28424(c *C) { "[ 2038-03-19 03:14:08")) } -func (s *testIntegrationSerialSuite) TestTemporaryTableForCte(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestTemporaryTableForCte(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create temporary table tmp1(a int, b int, c int);") @@ -4662,8 +5539,10 @@ func (s *testIntegrationSerialSuite) TestTemporaryTableForCte(c *C) { rows.Check(testkit.Rows("1", "2", "3", "4", "5")) } -func (s *testIntegrationSuite) TestGroupBySetVar(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGroupBySetVar(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1(c1 int);") @@ -4679,28 +5558,31 @@ func (s *testIntegrationSuite) TestGroupBySetVar(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { res := tk.MustQuery("explain format = 'brief' " + tt) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(res.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(res.Rows()) }) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestPushDownGroupConcatToTiFlash(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPushDownGroupConcatToTiFlash(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ts") tk.MustExec("create table ts (col_0 char(64), col_1 varchar(64) not null, col_2 varchar(1), id int primary key);") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "ts" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -4718,18 +5600,19 @@ func (s *testIntegrationSerialSuite) TestPushDownGroupConcatToTiFlash(c *C) { Plan []string Warning []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) - comment := Commentf("case:%v sql:%s", i, tt) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + testdata.OnRecord(func() { if len(warnings) > 0 { output[i].Warning = make([]string, len(warnings)) for j, warning := range warnings { @@ -4738,19 +5621,21 @@ func (s *testIntegrationSerialSuite) TestPushDownGroupConcatToTiFlash(c *C) { } }) if len(output[i].Warning) == 0 { - c.Assert(len(warnings), Equals, 0, comment) + require.Len(t, warnings, 0, comment) } else { - c.Assert(len(warnings), Equals, len(output[i].Warning), comment) + require.Len(t, warnings, len(output[i].Warning), comment) for j, warning := range warnings { - c.Assert(warning.Level, Equals, stmtctx.WarnLevelWarning, comment) - c.Assert(warning.Err.Error(), Equals, output[i].Warning[j], comment) + require.Equal(t, stmtctx.WarnLevelWarning, warning.Level, comment) + require.EqualError(t, warning.Err, output[i].Warning[j], comment) } } } } -func (s *testIntegrationSuite) TestIssue27797(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue27797(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) origin := tk.MustQuery("SELECT @@session.tidb_partition_prune_mode") originStr := origin.Rows()[0][0].(string) defer func() { @@ -4785,8 +5670,10 @@ func (s *testIntegrationSuite) TestIssue27797(c *C) { result.Check(testkit.Rows("")) } -func (s *testIntegrationSuite) TestIssue27949(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue27949(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t27949") tk.MustExec("create table t27949 (a int, b int, key(b))") @@ -4814,44 +5701,47 @@ func (s *testIntegrationSuite) TestIssue27949(c *C) { tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1")) } -func (s *testIntegrationSuite) TestIssue28154(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue28154(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") defer func() { - tk.Exec("drop table if exists t") + tk.MustExec("drop table if exists t") }() tk.MustExec("create table t(a TEXT)") tk.MustExec("insert into t values('abc')") result := tk.MustQuery("select * from t where from_base64('')") result.Check(testkit.Rows()) _, err := tk.Exec("update t set a = 'def' where from_base64('')") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[types:1292]Truncated incorrect DOUBLE value: ''") + require.EqualError(t, err, "[types:1292]Truncated incorrect DOUBLE value: ''") result = tk.MustQuery("select * from t where from_base64('invalidbase64')") result.Check(testkit.Rows()) tk.MustExec("update t set a = 'hig' where from_base64('invalidbase64')") result = tk.MustQuery("select * from t where from_base64('test')") result.Check(testkit.Rows()) _, err = tk.Exec("update t set a = 'xyz' where from_base64('test')") - c.Assert(err, NotNil) - c.Assert(err, ErrorMatches, "\\[types:1292\\]Truncated incorrect DOUBLE value.*") + require.Error(t, err) + require.Regexp(t, "\\[types:1292\\]Truncated incorrect DOUBLE value.*", err.Error()) result = tk.MustQuery("select * from t") result.Check(testkit.Rows("abc")) } -func (s *testIntegrationSerialSuite) TestRejectSortForMPP(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRejectSortForMPP(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int, value decimal(6,3), name char(128))") tk.MustExec("analyze table t") // Create virtual tiflash replica info. - dom := domain.GetDomain(tk.Se) + dom := domain.GetDomain(tk.Session()) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -4861,26 +5751,29 @@ func (s *testIntegrationSerialSuite) TestRejectSortForMPP(c *C) { } } - tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_opt_broadcast_join=0; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") var input []string var output []struct { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) res := tk.MustQuery(tt) res.Check(testkit.Rows(output[i].Plan...)) } } -func (s *testIntegrationSerialSuite) TestRegardNULLAsPoint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRegardNULLAsPoint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tpk") @@ -4908,16 +5801,17 @@ func (s *testIntegrationSerialSuite) TestRegardNULLAsPoint(c *C) { PlanDisabled []string Result []string } - s.testData.GetTestCases(c, &input, &output) + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt tk.MustExec(`set @@session.tidb_regard_null_as_point=true`) - output[i].PlanEnabled = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].PlanEnabled = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) tk.MustExec(`set @@session.tidb_regard_null_as_point=false`) - output[i].PlanDisabled = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) + output[i].PlanDisabled = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows()) }) tk.MustExec(`set @@session.tidb_regard_null_as_point=true`) tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].PlanEnabled...)) @@ -4929,8 +5823,10 @@ func (s *testIntegrationSerialSuite) TestRegardNULLAsPoint(c *C) { } } -func (s *testIntegrationSuite) TestIssues29711(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssues29711(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tbl_29711") @@ -4964,8 +5860,10 @@ func (s *testIntegrationSuite) TestIssues29711(c *C) { )) } -func (s *testIntegrationSuite) TestIssue27313(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue27313(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a varchar(100), b int, c int, index idx1(a(2), b), index idx2(a))") @@ -4974,8 +5872,10 @@ func (s *testIntegrationSuite) TestIssue27313(c *C) { tk.MustQuery("show warnings").Check(testkit.Rows()) } -func (s *testIntegrationSuite) TestIssue30094(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue30094(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`drop table if exists t30094;`) @@ -4987,13 +5887,62 @@ func (s *testIntegrationSuite) TestIssue30094(c *C) { )) tk.MustQuery(`explain format = 'brief' select * from t30094 where concat(a,'1') = _binary 0xe59388e59388e59388 collate binary and concat(a,'1') = _binary 0xe598bfe598bfe598bf collate binary;`).Check(testkit.Rows( "TableReader 8000.00 root data:Selection", - "└─Selection 8000.00 cop[tikv] eq(to_binary(concat(test.t30094.a, \"1\")), \"0xe59388e59388e59388\"), eq(to_binary(concat(test.t30094.a, \"1\")), \"0xe598bfe598bfe598bf\")", + "└─Selection 8000.00 cop[tikv] eq(concat(test.t30094.a, \"1\"), \"0xe59388e59388e59388\"), eq(concat(test.t30094.a, \"1\"), \"0xe598bfe598bfe598bf\")", " └─TableFullScan 10000.00 cop[tikv] table:t30094 keep order:false, stats:pseudo", )) } -func (s *testIntegrationSuite) TestIssue29705(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue30200(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 varchar(100), c2 varchar(100), key(c1), key(c2), c3 varchar(100));") + tk.MustExec("insert into t1 values('ab', '10', '10');") + + tk.MustExec("drop table if exists tt1;") + tk.MustExec("create table tt1(c1 varchar(100), c2 varchar(100), c3 varchar(100), c4 varchar(100), key idx_0(c1), key idx_1(c2, c3));") + tk.MustExec("insert into tt1 values('ab', '10', '10', '10');") + + tk.MustExec("drop table if exists tt2;") + tk.MustExec("create table tt2 (c1 int , pk int, primary key( pk ) , unique key( c1));") + tk.MustExec("insert into tt2 values(-3896405, -1), (-2, 1), (-1, -2);") + + tk.MustExec("drop table if exists tt3;") + tk.MustExec("create table tt3(c1 int, c2 int, c3 int as (c1 + c2), key(c1), key(c2), key(c3));") + tk.MustExec("insert into tt3(c1, c2) values(1, 1);") + + oriIndexMergeSwitcher := tk.MustQuery("select @@tidb_enable_index_merge;").Rows()[0][0].(string) + tk.MustExec("set tidb_enable_index_merge = on;") + defer func() { + tk.MustExec(fmt.Sprintf("set tidb_enable_index_merge = %s;", oriIndexMergeSwitcher)) + }() + + var input []string + var output []struct { + SQL string + Plan []string + Res []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format=brief " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery("explain format=brief " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) + } +} + +func TestIssue29705(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) origin := tk.MustQuery("SELECT @@session.tidb_partition_prune_mode") originStr := origin.Rows()[0][0].(string) defer func() { @@ -5008,10 +5957,10 @@ func (s *testIntegrationSuite) TestIssue29705(c *C) { result.Check(testkit.Rows("1")) } -func (s *testIntegrationSerialSuite) TestIssue30271(c *C) { - defer collate.SetNewCollationEnabledForTest(false) - collate.SetNewCollationEnabledForTest(true) - tk := testkit.NewTestKit(c, s.store) +func TestIssue30271(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a char(10), b char(10), c char(10), index (a, b, c)) collate utf8mb4_bin;") @@ -5020,3 +5969,539 @@ func (s *testIntegrationSerialSuite) TestIssue30271(c *C) { tk.MustQuery("select * from t where (a>'a' and b='a') or (b = 'A' and a < 'd') order by a,c;").Check(testkit.Rows("b a 1", "b A 2", "c a 3")) } + +func TestIssue30804(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("create table t2(a int, b int)") + // minimal reproduction of https://github.com/pingcap/tidb/issues/30804 + tk.MustExec("select avg(0) over w from t1 window w as (order by (select 1))") + // named window cannot be used in subquery + err := tk.ExecToErr("select avg(0) over w from t1 where b > (select sum(t2.a) over w from t2) window w as (partition by t1.b)") + require.True(t, core.ErrWindowNoSuchWindow.Equal(err)) + tk.MustExec("select avg(0) over w1 from t1 where b > (select sum(t2.a) over w2 from t2 window w2 as (partition by t2.b)) window w1 as (partition by t1.b)") +} + +func TestIndexMergeWarning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(c1 int, c2 int)") + tk.MustExec("select /*+ use_index_merge(t1) */ * from t1 where c1 < 1 or c2 < 1") + warningMsg := "Warning 1105 IndexMerge is inapplicable or disabled. No available filter or available index." + tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg)) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(c1 int, c2 int, key(c1), key(c2))") + tk.MustExec("select /*+ use_index_merge(t1), no_index_merge() */ * from t1 where c1 < 1 or c2 < 1") + warningMsg = "Warning 1105 IndexMerge is inapplicable or disabled. Got no_index_merge hint or tidb_enable_index_merge is off." + tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg)) + + tk.MustExec("drop table if exists t1") + tk.MustExec("create temporary table t1(c1 int, c2 int, key(c1), key(c2))") + tk.MustExec("select /*+ use_index_merge(t1) */ * from t1 where c1 < 1 or c2 < 1") + warningMsg = "Warning 1105 IndexMerge is inapplicable or disabled. Cannot use IndexMerge on temporary table." + tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg)) +} + +func TestIndexMergeWithCorrelatedColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + + tk.MustExec("drop table if exists t1, t2;") + tk.MustExec("create table t1(c1 int, c2 int, c3 int, primary key(c1), key(c2));") + tk.MustExec("insert into t1 values(1, 1, 1);") + tk.MustExec("insert into t1 values(2, 2, 2);") + tk.MustExec("create table t2(c1 int, c2 int, c3 int);") + tk.MustExec("insert into t2 values(1, 1, 1);") + tk.MustExec("insert into t2 values(2, 2, 2);") + + tk.MustExec("drop table if exists tt1, tt2;") + tk.MustExec("create table tt1 (c_int int, c_str varchar(40), c_datetime datetime, c_decimal decimal(12, 6), primary key(c_int), key(c_int), key(c_str), unique key(c_decimal), key(c_datetime));") + tk.MustExec("create table tt2 like tt1 ;") + tk.MustExec(`insert into tt1 (c_int, c_str, c_datetime, c_decimal) values (6, 'sharp payne', '2020-06-07 10:40:39', 6.117000) , + (7, 'objective kare', '2020-02-05 18:47:26', 1.053000) , + (8, 'thirsty pasteur', '2020-01-02 13:06:56', 2.506000) , + (9, 'blissful wilbur', '2020-06-04 11:34:04', 9.144000) , + (10, 'reverent mclean', '2020-02-12 07:36:26', 7.751000) ;`) + tk.MustExec(`insert into tt2 (c_int, c_str, c_datetime, c_decimal) values (6, 'beautiful joliot', '2020-01-16 01:44:37', 5.627000) , + (7, 'hopeful blackburn', '2020-05-23 21:44:20', 7.890000) , + (8, 'ecstatic davinci', '2020-02-01 12:27:17', 5.648000) , + (9, 'hopeful lewin', '2020-05-05 05:58:25', 7.288000) , + (10, 'sharp jennings', '2020-01-28 04:35:03', 9.758000) ;`) + + var input []string + var output []struct { + SQL string + Plan []string + Res []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format=brief " + tt).Rows()) + output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery("explain format=brief " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...)) + } + +} + +func TestIssue20510(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("CREATE TABLE t1 (a int PRIMARY KEY, b int)") + tk.MustExec("CREATE TABLE t2 (a int PRIMARY KEY, b int)") + tk.MustExec("INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (4,2)") + tk.MustExec("INSERT INTO t2 VALUES (1,2), (2,2)") + + tk.MustQuery("explain format=brief SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a WHERE not(0+(t1.a=30 and t2.b=1));").Check(testkit.Rows( + "Selection 8000.00 root not(plus(0, and(eq(test.t1.a, 30), eq(test.t2.b, 1))))", + "└─MergeJoin 10000.00 root left outer join, left key:test.t1.a, right key:test.t2.a", + " ├─TableReader(Build) 8000.00 root data:Selection", + " │ └─Selection 8000.00 cop[tikv] not(istrue_with_null(plus(0, and(eq(test.t2.a, 30), eq(test.t2.b, 1)))))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo")) + tk.MustQuery("SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a WHERE not(0+(t1.a=30 and t2.b=1));").Check(testkit.Rows( + "1 1 1 2", + "2 1 2 2", + "3 1 ", + "4 2 ", + )) +} + +func TestIssue31035(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 longtext, c2 decimal(37, 4), unique key(c1(10)), unique key(c2));") + tk.MustExec("insert into t1 values('çœ', -962541614831459.7458);") + tk.MustQuery("select * from t1 order by c2 + 10;").Check(testkit.Rows("çœ -962541614831459.7458")) +} + +// TestDNFCondSelectivityWithConst test selectivity calculation with DNF conditions with one is const. +// Close https://github.com/pingcap/tidb/issues/31096 +func TestDNFCondSelectivityWithConst(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + testKit.MustExec("use test") + testKit.MustExec("drop table if exists t1") + testKit.MustExec("create table t1(a int, b int, c int);") + testKit.MustExec("insert into t1 value(10,10,10)") + for i := 0; i < 7; i++ { + testKit.MustExec("insert into t1 select * from t1") + } + testKit.MustExec("insert into t1 value(1,1,1)") + testKit.MustExec("analyze table t1") + + testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1;").Check(testkit.Rows( + "TableReader 1.99 root data:Selection", + "└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), eq(test.t1.b, 1))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where 0=1 or a=1 or b=1;").Check(testkit.Rows( + "TableReader 1.99 root data:Selection", + "└─Selection 1.99 cop[tikv] or(0, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where null or a=1 or b=1;").Check(testkit.Rows( + "TableReader 1.99 root data:Selection", + "└─Selection 1.99 cop[tikv] or(0, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or false or b=1;").Check(testkit.Rows( + "TableReader 1.99 root data:Selection", + "└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), or(0, eq(test.t1.b, 1)))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1 or \"false\";").Check(testkit.Rows( + "TableReader 1.99 root data:Selection", + "└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), or(eq(test.t1.b, 1), 0))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where 1=1 or a=1 or b=1;").Check(testkit.Rows( + "TableReader 129.00 root data:Selection", + "└─Selection 129.00 cop[tikv] or(1, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1 or 1=1;").Check(testkit.Rows( + "TableReader 129.00 root data:Selection", + "└─Selection 129.00 cop[tikv] or(eq(test.t1.a, 1), or(eq(test.t1.b, 1), 1))", + " └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false")) + testKit.MustExec("drop table if exists t1") +} + +func TestIssue31202(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t31202(a int primary key, b int);") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t31202", L: "t31202"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + tk.MustQuery("explain format = 'brief' select * from t31202;").Check(testkit.Rows( + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:t31202 keep order:false, stats:pseudo")) + + tk.MustQuery("explain format = 'brief' select * from t31202 use index (primary);").Check(testkit.Rows( + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t31202 keep order:false, stats:pseudo")) + tk.MustExec("drop table if exists t31202") +} + +func TestNaturalJoinUpdateSameTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("create database natural_join_update") + defer tk.MustExec("drop database natural_join_update") + tk.MustExec("use natural_join_update") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("insert into t1 values (1,1),(2,2)") + tk.MustExec("update t1 as a natural join t1 b SET a.a = 2, b.b = 3") + tk.MustQuery("select * from t1").Sort().Check(testkit.Rows("2 3", "2 3")) + tk.MustExec("drop table t1") + tk.MustExec("create table t1 (a int primary key, b int)") + tk.MustExec("insert into t1 values (1,1),(2,2)") + tk.MustGetErrCode(`update t1 as a natural join t1 b SET a.a = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict) + tk.MustExec("drop table t1") + tk.MustExec("create table t1 (a int, b int) partition by hash (a) partitions 3") + tk.MustExec("insert into t1 values (1,1),(2,2)") + tk.MustGetErrCode(`update t1 as a natural join t1 b SET a.a = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict) + tk.MustExec("drop table t1") + tk.MustExec("create table t1 (A int, b int) partition by hash (b) partitions 3") + tk.MustExec("insert into t1 values (1,1),(2,2)") + tk.MustGetErrCode(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict) + _, err := tk.Exec(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`) + require.Error(t, err) + require.Regexp(t, ".planner:1706.Primary key/partition key update is not allowed since the table is updated both as 'a' and 'B'.", err.Error()) + tk.MustExec("drop table t1") + tk.MustExec("create table t1 (A int, b int) partition by RANGE COLUMNS (b) (partition `pNeg` values less than (0),partition `pPos` values less than MAXVALUE)") + tk.MustExec("insert into t1 values (1,1),(2,2)") + tk.MustGetErrCode(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict) + tk.MustExec("drop table t1") +} + +func TestAggPushToCopForCachedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec(`create table t32157( + process_code varchar(8) NOT NULL, + ctrl_class varchar(2) NOT NULL, + ctrl_type varchar(1) NOT NULL, + oper_no varchar(12) DEFAULT NULL, + modify_date datetime DEFAULT NULL, + d_c_flag varchar(2) NOT NULL, + PRIMARY KEY (process_code,ctrl_class,d_c_flag));`) + tk.MustExec("insert into t32157 values ('GDEP0071', '05', '1', '10000', '2016-06-29 00:00:00', 'C')") + tk.MustExec("insert into t32157 values ('GDEP0071', '05', '0', '0000', '2016-06-01 00:00:00', 'D')") + tk.MustExec("alter table t32157 cache") + + tk.MustQuery("explain format = 'brief' select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows( + "StreamAgg 1.00 root funcs:count(1)->Column#8]\n" + + "[└─UnionScan 10.00 root eq(test.t32157.process_code, \"GDEP0071\")]\n" + + "[ └─TableReader 10.00 root data:Selection]\n" + + "[ └─Selection 10.00 cop[tikv] eq(test.t32157.process_code, \"GDEP0071\")]\n" + + "[ └─TableFullScan 10000.00 cop[tikv] table:t32157 keep order:false, stats:pseudo")) + + var readFromCacheNoPanic bool + for i := 0; i < 10; i++ { + tk.MustQuery("select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows("2")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + readFromCacheNoPanic = true + break + } + } + require.True(t, readFromCacheNoPanic) + + tk.MustExec("drop table if exists t31202") +} + +func TestIssue31240(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t31240(a int, b int);") + tk.MustExec("set @@tidb_allow_mpp = 0") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t31240", L: "t31240"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + var input []string + var output []struct { + SQL string + Plan []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + }) + if strings.HasPrefix(tt, "set") { + tk.MustExec(tt) + continue + } + testdata.OnRecord(func() { + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) + } + tk.MustExec("drop table if exists t31240") +} + +func TestIssue32632(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("CREATE TABLE `partsupp` (" + + " `PS_PARTKEY` bigint(20) NOT NULL," + + "`PS_SUPPKEY` bigint(20) NOT NULL," + + "`PS_AVAILQTY` bigint(20) NOT NULL," + + "`PS_SUPPLYCOST` decimal(15,2) NOT NULL," + + "`PS_COMMENT` varchar(199) NOT NULL," + + "PRIMARY KEY (`PS_PARTKEY`,`PS_SUPPKEY`) /*T![clustered_index] NONCLUSTERED */)") + tk.MustExec("CREATE TABLE `supplier` (" + + "`S_SUPPKEY` bigint(20) NOT NULL," + + "`S_NAME` char(25) NOT NULL," + + "`S_ADDRESS` varchar(40) NOT NULL," + + "`S_NATIONKEY` bigint(20) NOT NULL," + + "`S_PHONE` char(15) NOT NULL," + + "`S_ACCTBAL` decimal(15,2) NOT NULL," + + "`S_COMMENT` varchar(101) NOT NULL," + + "PRIMARY KEY (`S_SUPPKEY`) /*T![clustered_index] CLUSTERED */)") + tk.MustExec("analyze table partsupp;") + tk.MustExec("analyze table supplier;") + tk.MustExec("set @@tidb_enforce_mpp = 1") + + tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "partsupp", L: "partsupp"}) + require.NoError(t, err) + tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "supplier", L: "supplier"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + h := dom.StatsHandle() + statsTbl1 := h.GetTableStats(tbl1.Meta()) + statsTbl1.Count = 800000 + statsTbl2 := h.GetTableStats(tbl2.Meta()) + statsTbl2.Count = 10000 + var input []string + var output []struct { + SQL string + Plan []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) + } + tk.MustExec("drop table if exists partsupp") + tk.MustExec("drop table if exists supplier") +} + +func TestTiFlashPartitionTableScan(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + tk.MustExec("set @@tidb_enforce_mpp = on") + tk.MustExec("set @@tidb_allow_batch_cop = 2") + tk.MustExec("drop table if exists rp_t;") + tk.MustExec("drop table if exists hp_t;") + tk.MustExec("create table rp_t(a int) partition by RANGE (a) (PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16), PARTITION p3 VALUES LESS THAN (21));") + tk.MustExec("create table hp_t(a int) partition by hash(a) partitions 4;") + tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "rp_t", L: "rp_t"}) + require.NoError(t, err) + tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "hp_t", L: "hp_t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + var input []string + var output []struct { + SQL string + Plan []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.GetTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) + } + tk.MustExec("drop table rp_t;") + tk.MustExec("drop table hp_t;") +} + +func TestIssue33175(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table t (id bigint(45) unsigned not null, c varchar(20), primary key(id));") + tk.MustExec("insert into t values (9734095886065816707, 'a'), (10353107668348738101, 'b'), (0, 'c');") + tk.MustExec("begin") + tk.MustExec("insert into t values (33, 'd');") + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + tk.MustExec("rollback") + + tk.MustExec("alter table t cache") + for { + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + // // With subquery, like the original issue case. + for { + tk.MustQuery("select * from t where id > (select max(id) from t where t.id > 0);").Check(testkit.Rows()) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + // Test order by desc / asc. + tk.MustQuery("select id from t order by id desc;").Check(testkit.Rows( + "10353107668348738101", + "9734095886065816707", + "0")) + + tk.MustQuery("select id from t order by id asc;").Check(testkit.Rows( + "0", + "9734095886065816707", + "10353107668348738101")) + + tk.MustExec("alter table t nocache") + tk.MustExec("drop table t") + + // Cover more code that use union scan + // TableReader/IndexReader/IndexLookup + for idx, q := range []string{ + "create temporary table t (id bigint unsigned, c int default null, index(id))", + "create temporary table t (id bigint unsigned primary key)", + } { + tk.MustExec(q) + tk.MustExec("insert into t(id) values (1), (3), (9734095886065816707), (9734095886065816708)") + tk.MustQuery("select min(id) from t").Check(testkit.Rows("1")) + tk.MustQuery("select max(id) from t").Check(testkit.Rows("9734095886065816708")) + tk.MustQuery("select id from t order by id asc").Check(testkit.Rows( + "1", "3", "9734095886065816707", "9734095886065816708")) + tk.MustQuery("select id from t order by id desc").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "3", "1")) + if idx == 0 { + tk.MustQuery("select * from t order by id asc").Check(testkit.Rows( + "1 ", + "3 ", + "9734095886065816707 ", + "9734095886065816708 ")) + tk.MustQuery("select * from t order by id desc").Check(testkit.Rows( + "9734095886065816708 ", + "9734095886065816707 ", + "3 ", + "1 ")) + } + tk.MustExec("drop table t") + } + + // More and more test + tk.MustExec("create global temporary table `tmp1` (id bigint unsigned primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp1 values (0),(1),(2),(65536),(9734095886065816707),(9734095886065816708);") + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id desc;").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "65536", "2", "1", "0")) + + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id asc;").Check(testkit.Rows( + "0", "1", "2", "65536", "9734095886065816707", "9734095886065816708")) + + tk.MustExec("create global temporary table `tmp2` (id bigint primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp2 values(-2),(-1),(0),(1),(2);") + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id desc;").Check(testkit.Rows("2", "1", "-1", "-2")) + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id asc;").Check(testkit.Rows("-2", "-1", "1", "2")) +} + +func TestIssue33042(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t1(id int primary key, col1 int)") + tk.MustExec("create table t2(id int primary key, col1 int)") + tk.MustQuery("explain format='brief' SELECT /*+ merge_join(t1, t2)*/ * FROM (t1 LEFT JOIN t2 ON t1.col1=t2.id) order by t2.id;").Check( + testkit.Rows( + "Sort 12500.00 root test.t2.id", + "└─MergeJoin 12500.00 root left outer join, left key:test.t1.col1, right key:test.t2.id", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─Sort(Probe) 10000.00 root test.t1.col1", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + ), + ) +} + +func TestIssue29663(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1 (a int, b int)") + tk.MustExec("create table t2 (c int, d int)") + tk.MustExec("insert into t1 values(1, 1), (1,2),(2,1),(2,2)") + tk.MustExec("insert into t2 values(1, 3), (1,4),(2,5),(2,6)") + + tk.MustQuery("explain select one.a from t1 one order by (select two.d from t2 two where two.c = one.b)").Check(testkit.Rows( + "Projection_16 10000.00 root test.t1.a", + "└─Sort_17 10000.00 root test.t2.d", + " └─Apply_20 10000.00 root CARTESIAN left outer join", + " ├─TableReader_22(Build) 10000.00 root data:TableFullScan_21", + " │ └─TableFullScan_21 10000.00 cop[tikv] table:one keep order:false, stats:pseudo", + " └─MaxOneRow_23(Probe) 1.00 root ", + " └─TableReader_26 2.00 root data:Selection_25", + " └─Selection_25 2.00 cop[tikv] eq(test.t2.c, test.t1.b)", + " └─TableFullScan_24 2000.00 cop[tikv] table:two keep order:false, stats:pseudo")) +} diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 5df63d975950a..67e8b46969570 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -27,8 +27,6 @@ import ( "github.com/cznic/mathutil" "github.com/pingcap/errors" - "github.com/pingcap/log" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" @@ -42,6 +40,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/opcode" "github.com/pingcap/tidb/parser/terror" + fd "github.com/pingcap/tidb/planner/funcdep" "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/privilege" @@ -56,6 +55,7 @@ import ( util2 "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/plancodec" "github.com/pingcap/tidb/util/set" ) @@ -68,11 +68,8 @@ const ( // TiDBBroadCastJoin indicates applying broadcast join by force. TiDBBroadCastJoin = "tidb_bcj" - // HintBCJ indicates applying broadcast join by force. HintBCJ = "broadcast_join" - // HintBCJPreferLocal specifies the preferred local read table - HintBCJPreferLocal = "broadcast_join_local" // TiDBIndexNestedLoopJoin is hint enforce index nested loop join. TiDBIndexNestedLoopJoin = "tidb_inlj" @@ -277,7 +274,17 @@ func (b *PlanBuilder) buildAggregation(ctx context.Context, p LogicalPlan, aggFu schema4Agg.Append(newCol) names = append(names, p.OutputNames()[i]) } - if join, isJoin := p.(*LogicalJoin); isJoin && join.fullSchema != nil { + var ( + join *LogicalJoin + isJoin bool + isSelectionJoin bool + ) + join, isJoin = p.(*LogicalJoin) + selection, isSelection := p.(*LogicalSelection) + if isSelection { + join, isSelectionJoin = selection.children[0].(*LogicalJoin) + } + if (isJoin && join.fullSchema != nil) || (isSelectionJoin && join.fullSchema != nil) { for i, col := range join.fullSchema.Columns { if p.Schema().Contains(col) { continue @@ -541,19 +548,6 @@ func extractTableAlias(p Plan, parentOffset int) *hintTableInfo { return nil } -func (p *LogicalJoin) getPreferredBCJLocalIndex() (hasPrefer bool, prefer int) { - if p.hintInfo == nil { - return - } - if p.hintInfo.ifPreferAsLocalInBCJoin(p.children[0], p.blockOffset) { - return true, 0 - } - if p.hintInfo.ifPreferAsLocalInBCJoin(p.children[1], p.blockOffset) { - return true, 1 - } - return false, 0 -} - func (p *LogicalJoin) setPreferredJoinType(hintInfo *tableHintInfo) { if hintInfo == nil { return @@ -981,7 +975,7 @@ func (b *PlanBuilder) buildSelection(ctx context.Context, p LogicalPlan, where a conditions := splitWhere(where) expressions := make([]expression.Expression, 0, len(conditions)) - selection := LogicalSelection{buildByHaving: aggMapper != nil}.Init(b.ctx, b.getSelectOffset()) + selection := LogicalSelection{}.Init(b.ctx, b.getSelectOffset()) for _, cond := range conditions { expr, np, err := b.rewrite(ctx, cond, p, aggMapper, false) if err != nil { @@ -1157,9 +1151,22 @@ func (b *PlanBuilder) buildProjectionField(ctx context.Context, p LogicalPlan, f if expr == nil { return nil, name, nil } + // invalid unique id + correlatedColUniqueID := int64(0) + if cc, ok := expr.(*expression.CorrelatedColumn); ok { + correlatedColUniqueID = cc.UniqueID + } + // for expr projection, we should record the map relationship down. newCol := &expression.Column{ - UniqueID: b.ctx.GetSessionVars().AllocPlanColumnID(), - RetType: expr.GetType(), + UniqueID: b.ctx.GetSessionVars().AllocPlanColumnID(), + RetType: expr.GetType(), + CorrelatedColUniqueID: correlatedColUniqueID, + } + if b.ctx.GetSessionVars().OptimizerEnableNewOnlyFullGroupByCheck { + if b.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol == nil { + b.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = make(map[string]int, 1) + } + b.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol[string(expr.HashCode(b.ctx.GetSessionVars().StmtCtx))] = int(newCol.UniqueID) } newCol.SetCoercibility(expr.Coercibility()) return newCol, name, nil @@ -1801,7 +1808,7 @@ func getUintFromNode(ctx sessionctx.Context, n ast.Node) (uVal uint64, isNull bo if !v.InExecute { return 0, false, true } - param, err := expression.ParamMarkerExpression(ctx, v) + param, err := expression.ParamMarkerExpression(ctx, v, false) if err != nil { return 0, false, false } @@ -2037,6 +2044,14 @@ func (a *havingWindowAndOrderbyExprResolver) resolveFromPlan(v *ast.ColumnNameEx Expr: &ast.ColumnNameExpr{Name: newColName}, Auxiliary: true, } + // appended with new select fields. set them with flag. + if a.inAggFunc { + // should skip check in FD for only full group by. + sf.AuxiliaryColInAgg = true + } else if a.curClause == orderByClause { + // should skip check in FD for only full group by only when group by item are empty. + sf.AuxiliaryColInOrderBy = true + } sf.Expr.SetType(col.GetType()) a.selectFields = append(a.selectFields, sf) return len(a.selectFields) - 1, nil @@ -2164,7 +2179,7 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o // resolveHavingAndOrderBy will process aggregate functions and resolve the columns that don't exist in select fields. // If we found some columns that are not in select fields, we will append it to select fields and update the colMapper. // When we rewrite the order by / having expression, we will find column in map at first. -func (b *PlanBuilder) resolveHavingAndOrderBy(sel *ast.SelectStmt, p LogicalPlan) ( +func (b *PlanBuilder) resolveHavingAndOrderBy(ctx context.Context, sel *ast.SelectStmt, p LogicalPlan) ( map[*ast.AggregateFuncExpr]int, map[*ast.AggregateFuncExpr]int, error) { extractor := &havingWindowAndOrderbyExprResolver{ p: p, @@ -2204,9 +2219,67 @@ func (b *PlanBuilder) resolveHavingAndOrderBy(sel *ast.SelectStmt, p LogicalPlan } } sel.Fields.Fields = extractor.selectFields + // this part is used to fetch correlated column from sub-query item in order-by clause, and append the origin + // auxiliary select filed in select list, otherwise, sub-query itself won't get the name resolved in outer schema. + if sel.OrderBy != nil { + for _, byItem := range sel.OrderBy.Items { + if _, ok := byItem.Expr.(*ast.SubqueryExpr); ok { + // correlated agg will be extracted completely latter. + _, np, err := b.rewrite(ctx, byItem.Expr, p, nil, true) + if err != nil { + return nil, nil, errors.Trace(err) + } + correlatedCols := ExtractCorrelatedCols4LogicalPlan(np) + for _, cone := range correlatedCols { + var colName *ast.ColumnName + for idx, pone := range p.Schema().Columns { + if cone.UniqueID == pone.UniqueID { + pname := p.OutputNames()[idx] + colName = &ast.ColumnName{ + Schema: pname.DBName, + Table: pname.TblName, + Name: pname.ColName, + } + break + } + } + if colName != nil { + columnNameExpr := &ast.ColumnNameExpr{Name: colName} + for _, field := range sel.Fields.Fields { + if c, ok := field.Expr.(*ast.ColumnNameExpr); ok && colMatch(c.Name, columnNameExpr.Name) { + // deduplicate select fields: don't append it once it already has one. + columnNameExpr = nil + break + } + } + if columnNameExpr != nil { + sel.Fields.Fields = append(sel.Fields.Fields, &ast.SelectField{ + Auxiliary: true, + Expr: columnNameExpr, + }) + } + } + } + } + } + } return havingAggMapper, extractor.aggMapper, nil } +func (b *PlanBuilder) extractAggFuncsInExprs(exprs []ast.ExprNode) ([]*ast.AggregateFuncExpr, map[*ast.AggregateFuncExpr]int) { + extractor := &AggregateFuncExtractor{skipAggMap: b.correlatedAggMapper} + for _, expr := range exprs { + expr.Accept(extractor) + } + aggList := extractor.AggFuncs + totalAggMapper := make(map[*ast.AggregateFuncExpr]int, len(aggList)) + + for i, agg := range aggList { + totalAggMapper[agg] = i + } + return aggList, totalAggMapper +} + func (b *PlanBuilder) extractAggFuncsInSelectFields(fields []*ast.SelectField) ([]*ast.AggregateFuncExpr, map[*ast.AggregateFuncExpr]int) { extractor := &AggregateFuncExtractor{skipAggMap: b.correlatedAggMapper} for _, f := range fields { @@ -2373,7 +2446,7 @@ func (r *correlatedAggregateResolver) resolveSelect(sel *ast.SelectStmt) (err er } } - _, _, err = r.b.resolveHavingAndOrderBy(sel, p) + _, _, err = r.b.resolveHavingAndOrderBy(r.ctx, sel, p) if err != nil { return err } @@ -2730,6 +2803,7 @@ func checkColFuncDepend( continue } funcDepend := true + // if all columns of some unique/pri indexes are determined, all columns left are check-passed. for _, indexCol := range index.Columns { iColInfo := tblInfo.Columns[indexCol.Offset] if !mysql.HasNotNullFlag(iColInfo.Flag) { @@ -3183,7 +3257,7 @@ func unfoldWildStar(field *ast.SelectField, outputName types.NameSlice, column [ } if (dbName.L == "" || dbName.L == name.DBName.L) && (tblName.L == "" || tblName.L == name.TblName.L) && - col.ID != model.ExtraHandleID { + col.ID != model.ExtraHandleID && col.ID != model.ExtraPidColID && col.ID != model.ExtraPhysTblID { colName := &ast.ColumnNameExpr{ Name: &ast.ColumnName{ Schema: name.DBName, @@ -3192,7 +3266,7 @@ func unfoldWildStar(field *ast.SelectField, outputName types.NameSlice, column [ }} colName.SetType(col.GetType()) field := &ast.SelectField{Expr: colName} - field.SetText(name.ColName.O) + field.SetText(nil, name.ColName.O) resultList = append(resultList, field) } } @@ -3286,12 +3360,12 @@ func (b *PlanBuilder) pushHintWithoutTableWarning(hint *ast.TableOptimizerHint) func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLevel int) { hints = b.hintProcessor.GetCurrentStmtHints(hints, currentLevel) var ( - sortMergeTables, INLJTables, INLHJTables, INLMJTables, hashJoinTables, BCTables, BCJPreferLocalTables []hintTableInfo - indexHintList, indexMergeHintList []indexHintInfo - tiflashTables, tikvTables []hintTableInfo - aggHints aggHintInfo - timeRangeHint ast.HintTimeRange - limitHints limitHintInfo + sortMergeTables, INLJTables, INLHJTables, INLMJTables, hashJoinTables, BCTables []hintTableInfo + indexHintList, indexMergeHintList []indexHintInfo + tiflashTables, tikvTables []hintTableInfo + aggHints aggHintInfo + timeRangeHint ast.HintTimeRange + limitHints limitHintInfo ) for _, hint := range hints { // Set warning for the hint that requires the table name. @@ -3309,8 +3383,6 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev sortMergeTables = append(sortMergeTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...) case TiDBBroadCastJoin, HintBCJ: BCTables = append(BCTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...) - case HintBCJPreferLocal: - BCJPreferLocalTables = append(BCJPreferLocalTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...) case TiDBIndexNestedLoopJoin, HintINLJ: INLJTables = append(INLJTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...) case HintINLHJ: @@ -3401,18 +3473,17 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev } } b.tableHintInfo = append(b.tableHintInfo, tableHintInfo{ - sortMergeJoinTables: sortMergeTables, - broadcastJoinTables: BCTables, - broadcastJoinPreferredLocal: BCJPreferLocalTables, - indexNestedLoopJoinTables: indexNestedLoopJoinTables{INLJTables, INLHJTables, INLMJTables}, - hashJoinTables: hashJoinTables, - indexHintList: indexHintList, - tiflashTables: tiflashTables, - tikvTables: tikvTables, - aggHints: aggHints, - indexMergeHintList: indexMergeHintList, - timeRangeHint: timeRangeHint, - limitHints: limitHints, + sortMergeJoinTables: sortMergeTables, + broadcastJoinTables: BCTables, + indexNestedLoopJoinTables: indexNestedLoopJoinTables{INLJTables, INLHJTables, INLMJTables}, + hashJoinTables: hashJoinTables, + indexHintList: indexHintList, + tiflashTables: tiflashTables, + tikvTables: tikvTables, + aggHints: aggHints, + indexMergeHintList: indexMergeHintList, + timeRangeHint: timeRangeHint, + limitHints: limitHints, }) } @@ -3432,7 +3503,6 @@ func (b *PlanBuilder) popTableHints() { b.appendUnmatchedJoinHintWarning(HintINLMJ, "", hintInfo.indexNestedLoopJoinTables.inlmjTables) b.appendUnmatchedJoinHintWarning(HintSMJ, TiDBMergeJoin, hintInfo.sortMergeJoinTables) b.appendUnmatchedJoinHintWarning(HintBCJ, TiDBBroadCastJoin, hintInfo.broadcastJoinTables) - b.appendUnmatchedJoinHintWarning(HintBCJPreferLocal, "", hintInfo.broadcastJoinPreferredLocal) b.appendUnmatchedJoinHintWarning(HintHJ, TiDBHashJoin, hintInfo.hashJoinTables) b.appendUnmatchedStorageHintWarning(hintInfo.tiflashTables, hintInfo.tikvTables) b.tableHintInfo = b.tableHintInfo[:len(b.tableHintInfo)-1] @@ -3601,7 +3671,7 @@ func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p L // We must resolve having and order by clause before build projection, // because when the query is "select a+1 as b from t having sum(b) < 0", we must replace sum(b) to sum(a+1), // which only can be done before building projection and extracting Agg functions. - havingMap, orderMap, err = b.resolveHavingAndOrderBy(sel, p) + havingMap, orderMap, err = b.resolveHavingAndOrderBy(ctx, sel, p) if err != nil { return nil, err } @@ -3733,13 +3803,19 @@ func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p L } if sel.OrderBy != nil { - if b.ctx.GetSessionVars().SQLMode.HasOnlyFullGroupBy() { - p, err = b.buildSortWithCheck(ctx, p, sel.OrderBy.Items, orderMap, windowMapper, projExprs, oldLen, sel.Distinct) - } else { - p, err = b.buildSort(ctx, p, sel.OrderBy.Items, orderMap, windowMapper) - } - if err != nil { - return nil, err + // We need to keep the ORDER BY clause for the following cases: + // 1. The select is top level query, order should be honored + // 2. The query has LIMIT clause + // 3. The control flag requires keeping ORDER BY explicitly + if len(b.selectOffset) == 1 || sel.Limit != nil || !b.ctx.GetSessionVars().RemoveOrderbyInSubquery { + if b.ctx.GetSessionVars().SQLMode.HasOnlyFullGroupBy() { + p, err = b.buildSortWithCheck(ctx, p, sel.OrderBy.Items, orderMap, windowMapper, projExprs, oldLen, sel.Distinct) + } else { + p, err = b.buildSort(ctx, p, sel.OrderBy.Items, orderMap, windowMapper) + } + if err != nil { + return nil, err + } } } @@ -3782,30 +3858,36 @@ func (ds *DataSource) newExtraHandleSchemaCol() *expression.Column { } } -// addExtraPIDColumn add an extra PID column for partition table. +// AddExtraPhysTblIDColumn for partition table. // 'select ... for update' on a partition table need to know the partition ID // to construct the lock key, so this column is added to the chunk row. -func (ds *DataSource) addExtraPIDColumn(info *extraPIDInfo) { +// Also needed for checking against the sessions transaction buffer +func (ds *DataSource) AddExtraPhysTblIDColumn() *expression.Column { + // Avoid adding multiple times (should never happen!) + cols := ds.TblCols + for i := len(cols) - 1; i >= 0; i-- { + if cols[i].ID == model.ExtraPhysTblID { + return cols[i] + } + } pidCol := &expression.Column{ RetType: types.NewFieldType(mysql.TypeLonglong), UniqueID: ds.ctx.GetSessionVars().AllocPlanColumnID(), - ID: model.ExtraPidColID, - OrigName: fmt.Sprintf("%v.%v.%v", ds.DBName, ds.tableInfo.Name, model.ExtraPartitionIdName), + ID: model.ExtraPhysTblID, + OrigName: fmt.Sprintf("%v.%v.%v", ds.DBName, ds.tableInfo.Name, model.ExtraPhysTblIdName), } - ds.Columns = append(ds.Columns, model.NewExtraPartitionIDColInfo()) + ds.Columns = append(ds.Columns, model.NewExtraPhysTblIDColInfo()) schema := ds.Schema() schema.Append(pidCol) ds.names = append(ds.names, &types.FieldName{ DBName: ds.DBName, TblName: ds.TableInfo().Name, - ColName: model.ExtraPartitionIdName, - OrigColName: model.ExtraPartitionIdName, + ColName: model.ExtraPhysTblIdName, + OrigColName: model.ExtraPhysTblIdName, }) ds.TblCols = append(ds.TblCols, pidCol) - - info.Columns = append(info.Columns, pidCol) - info.TblIDs = append(info.TblIDs, ds.TableInfo().ID) + return pidCol } var ( @@ -3900,11 +3982,15 @@ func (b *PlanBuilder) tryBuildCTE(ctx context.Context, tn *ast.TableName, asName cte.cteClass = &CTEClass{IsDistinct: cte.isDistinct, seedPartLogicalPlan: cte.seedLP, recursivePartLogicalPlan: cte.recurLP, IDForStorage: cte.storageID, optFlag: cte.optFlag, HasLimit: hasLimit, LimitBeg: limitBeg, - LimitEnd: limitEnd} + LimitEnd: limitEnd, pushDownPredicates: make([]expression.Expression, 0), ColumnMap: make(map[string]*expression.Column)} } var p LogicalPlan - lp := LogicalCTE{cteAsName: tn.Name, cte: cte.cteClass, seedStat: cte.seedStat}.Init(b.ctx, b.getSelectOffset()) + lp := LogicalCTE{cteAsName: tn.Name, cte: cte.cteClass, seedStat: cte.seedStat, isOuterMostCTE: !b.buildingCTE}.Init(b.ctx, b.getSelectOffset()) + prevSchema := cte.seedLP.Schema().Clone() lp.SetSchema(getResultCTESchema(cte.seedLP.Schema(), b.ctx.GetSessionVars())) + for i, col := range lp.schema.Columns { + lp.cte.ColumnMap[string(col.HashCode(nil))] = prevSchema.Columns[i] + } p = lp p.SetOutputNames(cte.seedLP.OutputNames()) if len(asName.String()) > 0 { @@ -3968,6 +4054,15 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as return b.buildMemTable(ctx, dbName, tableInfo) } + tblName := *asName + if tblName.L == "" { + tblName = tn.Name + } + possiblePaths, err := getPossibleAccessPaths(b.ctx, b.TableHints(), tn.IndexHints, tbl, dbName, tblName, b.isForUpdateRead, b.is.SchemaMetaVersion()) + if err != nil { + return nil, err + } + if tableInfo.IsView() { if tn.TableSample != nil { return nil, expression.ErrInvalidTableSample.GenWithStackByArgs("Unsupported TABLESAMPLE in views") @@ -4007,14 +4102,6 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as return nil, ErrPartitionClauseOnNonpartitioned } - tblName := *asName - if tblName.L == "" { - tblName = tn.Name - } - possiblePaths, err := getPossibleAccessPaths(b.ctx, b.TableHints(), tn.IndexHints, tbl, dbName, tblName, b.isForUpdateRead, b.is.SchemaMetaVersion()) - if err != nil { - return nil, err - } // Skip storage engine check for CreateView. if b.capFlag&canExpandAST == 0 { possiblePaths, err = filterPathByIsolationRead(b.ctx, possiblePaths, tblName, dbName) @@ -4166,6 +4253,20 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as ds.SampleInfo = NewTableSampleInfo(tn.TableSample, schema.Clone(), b.partitionedTable) b.isSampling = ds.SampleInfo != nil + for i, colExpr := range ds.Schema().Columns { + var expr expression.Expression + if i < len(columns) { + if columns[i].IsGenerated() && !columns[i].GeneratedStored { + var err error + expr, _, err = b.rewrite(ctx, columns[i].GeneratedExpr, ds, nil, true) + if err != nil { + return nil, err + } + colExpr.VirtualExpr = expr.Clone() + } + } + } + // Init commonHandleCols and commonHandleLens for data source. if tableInfo.IsCommonHandle { ds.commonHandleCols, ds.commonHandleLens = expression.IndexInfo2Cols(ds.Columns, ds.schema.Columns, tables.FindPrimaryIndex(tableInfo)) @@ -4174,68 +4275,166 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as for _, path := range ds.possibleAccessPaths { if !path.IsIntHandlePath { path.FullIdxCols, path.FullIdxColLens = expression.IndexInfo2Cols(ds.Columns, ds.schema.Columns, path.Index) + + // check whether the path's index has a tidb_shard() prefix and the index column count + // more than 1. e.g. index(tidb_shard(a), a) + // set UkShardIndexPath only for unique secondary index + if !path.IsCommonHandlePath { + // tidb_shard expression must be first column of index + col := path.FullIdxCols[0] + if col != nil && + expression.GcColumnExprIsTidbShard(col.VirtualExpr) && + len(path.Index.Columns) > 1 && + path.Index.Unique { + path.IsUkShardIndexPath = true + ds.containExprPrefixUk = true + } + } } } var result LogicalPlan = ds dirty := tableHasDirtyContent(b.ctx, tableInfo) - if dirty || tableInfo.TempTableType == model.TempTableLocal { + if dirty || tableInfo.TempTableType == model.TempTableLocal || tableInfo.TableCacheStatusType == model.TableCacheStatusEnable { us := LogicalUnionScan{handleCols: handleCols}.Init(b.ctx, b.getSelectOffset()) us.SetChildren(ds) - result = us - } - // If a table is a cache table, it is judged whether it satisfies the conditions of read cache. - if tableInfo.TableCacheStatusType == model.TableCacheStatusEnable && b.ctx.GetSessionVars().SnapshotTS == 0 && !b.ctx.GetSessionVars().StmtCtx.IsStaleness { - cachedTable := tbl.(table.CachedTable) - txn, err := b.ctx.Txn(true) - if err != nil { - return nil, err - } - // Use the TS of the transaction to determine whether the cache can be used. - cacheData := cachedTable.TryReadFromCache(txn.StartTS()) - if cacheData != nil { - sessionVars.StmtCtx.ReadFromTableCache = true - us := LogicalUnionScan{handleCols: handleCols, cacheTable: cacheData}.Init(b.ctx, b.getSelectOffset()) - us.SetChildren(ds) - result = us - } else { - if !b.inUpdateStmt && !b.inDeleteStmt && !sessionVars.StmtCtx.InExplainStmt { - startTS := txn.StartTS() - store := b.ctx.GetStore() - go func() { - defer func() { - if r := recover(); r != nil { - } - }() - err := cachedTable.UpdateLockForRead(ctx, store, startTS) - if err != nil { - log.Warn("Update Lock Info Error") - } - }() - } + if tableInfo.Partition != nil && b.optFlag&flagPartitionProcessor == 0 { + // Adding ExtraPhysTblIDCol for UnionScan (transaction buffer handling) + // Not using old static prune mode + // Single TableReader for all partitions, needs the PhysTblID from storage + _ = ds.AddExtraPhysTblIDColumn() } + result = us } + // Adding ExtraPhysTblIDCol for SelectLock (SELECT FOR UPDATE) is done when building SelectLock + if sessionVars.StmtCtx.TblInfo2UnionScan == nil { sessionVars.StmtCtx.TblInfo2UnionScan = make(map[*model.TableInfo]bool) } sessionVars.StmtCtx.TblInfo2UnionScan[tableInfo] = dirty - for i, colExpr := range ds.Schema().Columns { - var expr expression.Expression - if i < len(columns) { - if columns[i].IsGenerated() && !columns[i].GeneratedStored { - var err error - expr, _, err = b.rewrite(ctx, columns[i].GeneratedExpr, ds, nil, true) - if err != nil { - return nil, err + return result, nil +} + +// ExtractFD implements the LogicalPlan interface. +func (ds *DataSource) ExtractFD() *fd.FDSet { + // FD in datasource (leaf node) can be cached and reused. + // Once the all conditions are not equal to nil, built it again. + if ds.fdSet == nil || ds.allConds != nil { + fds := &fd.FDSet{HashCodeToUniqueID: make(map[string]int)} + allCols := fd.NewFastIntSet() + // should use the column's unique ID avoiding fdSet conflict. + for _, col := range ds.TblCols { + // todo: change it to int64 + allCols.Insert(int(col.UniqueID)) + } + // int pk doesn't store its index column in indexInfo. + if ds.tableInfo.PKIsHandle { + keyCols := fd.NewFastIntSet() + for _, col := range ds.TblCols { + if mysql.HasPriKeyFlag(col.RetType.Flag) { + keyCols.Insert(int(col.UniqueID)) } - colExpr.VirtualExpr = expr.Clone() + } + fds.AddStrictFunctionalDependency(keyCols, allCols) + fds.MakeNotNull(keyCols) + } + // we should check index valid while forUpdateRead, see detail in https://github.com/pingcap/tidb/pull/22152 + var ( + latestIndexes map[int64]*model.IndexInfo + changed bool + err error + ) + if ds.isForUpdateRead { + latestIndexes, changed, err = getLatestIndexInfo(ds.ctx, ds.table.Meta().ID, 0) + if err != nil { + ds.fdSet = fds + return fds } } + // other indices including common handle. + for _, idx := range ds.tableInfo.Indices { + keyCols := fd.NewFastIntSet() + allColIsNotNull := true + if ds.isForUpdateRead && changed { + latestIndex, ok := latestIndexes[idx.ID] + if !ok || latestIndex.State != model.StatePublic { + continue + } + } + if idx.State != model.StatePublic { + continue + } + for _, idxCol := range idx.Columns { + // Note: even the prefix column can also be the FD. For example: + // unique(char_column(10)), will also guarantee the prefix to be + // the unique which means the while column is unique too. + refCol := ds.tableInfo.Columns[idxCol.Offset] + if !mysql.HasNotNullFlag(refCol.Flag) { + allColIsNotNull = false + } + keyCols.Insert(int(ds.TblCols[idxCol.Offset].UniqueID)) + } + if idx.Primary { + fds.AddStrictFunctionalDependency(keyCols, allCols) + fds.MakeNotNull(keyCols) + } else if idx.Unique { + if allColIsNotNull { + fds.AddStrictFunctionalDependency(keyCols, allCols) + fds.MakeNotNull(keyCols) + } else { + // unique index: + // 1: normal value should be unique + // 2: null value can be multiple + // for this kind of lax to be strict, we need to make the determinant not-null. + fds.AddLaxFunctionalDependency(keyCols, allCols) + } + } + } + // handle the datasource conditions (maybe pushed down from upper layer OP) + if len(ds.allConds) != 0 { + // extract the not null attributes from selection conditions. + notnullColsUniqueIDs := extractNotNullFromConds(ds.allConds, ds) + + // extract the constant cols from selection conditions. + constUniqueIDs := extractConstantCols(ds.allConds, ds.SCtx(), fds) + + // extract equivalence cols. + equivUniqueIDs := extractEquivalenceCols(ds.allConds, ds.SCtx(), fds) + + // apply conditions to FD. + fds.MakeNotNull(notnullColsUniqueIDs) + fds.AddConstants(constUniqueIDs) + for _, equiv := range equivUniqueIDs { + fds.AddEquivalence(equiv[0], equiv[1]) + } + } + // build the dependency for generated columns. + // the generated column is sequentially dependent on the forward column. + // a int, b int as (a+1), c int as (b+1), here we can build the strict FD down: + // {a} -> {b}, {b} -> {c}, put the maintenance of the dependencies between generated columns to the FD graph. + notNullCols := fd.NewFastIntSet() + for _, col := range ds.TblCols { + if col.VirtualExpr != nil { + dependencies := fd.NewFastIntSet() + dependencies.Insert(int(col.UniqueID)) + // dig out just for 1 level. + directBaseCol := expression.ExtractColumns(col.VirtualExpr) + determinant := fd.NewFastIntSet() + for _, col := range directBaseCol { + determinant.Insert(int(col.UniqueID)) + } + fds.AddStrictFunctionalDependency(determinant, dependencies) + } + if mysql.HasNotNullFlag(col.RetType.Flag) { + notNullCols.Insert(int(col.UniqueID)) + } + } + fds.MakeNotNull(notNullCols) + ds.fdSet = fds } - - return result, nil + return ds.fdSet } func (b *PlanBuilder) timeRangeForSummaryTable() QueryTimeRange { @@ -4348,6 +4547,12 @@ func (b *PlanBuilder) buildMemTable(_ context.Context, dbName model.CIStr, table p.Extractor = &TiFlashSystemTableExtractor{} case infoschema.TableStatementsSummary, infoschema.TableStatementsSummaryHistory: p.Extractor = &StatementsSummaryExtractor{} + case infoschema.TableTiKVRegionPeers: + p.Extractor = &TikvRegionPeersExtractor{} + case infoschema.TableColumns: + p.Extractor = &ColumnsTableExtractor{} + case infoschema.TableTiKVRegionStatus: + p.Extractor = &TiKVRegionStatusExtractor{tablesID: make([]int64, 0)} } } return p, nil @@ -4393,7 +4598,9 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. if err != nil { if terror.ErrorNotEqual(err, ErrViewRecursive) && terror.ErrorNotEqual(err, ErrNoSuchTable) && - terror.ErrorNotEqual(err, ErrInternal) { + terror.ErrorNotEqual(err, ErrInternal) && + terror.ErrorNotEqual(err, ErrFieldNotInGroupBy) && + terror.ErrorNotEqual(err, ErrMixOfGroupFuncAndFields) { err = ErrViewInvalid.GenWithStackByArgs(dbName.O, tableInfo.Name.O) } return nil, err @@ -4475,6 +4682,7 @@ func (b *PlanBuilder) buildProjUponView(ctx context.Context, dbName model.CIStr, // every row from outerPlan and the whole innerPlan. func (b *PlanBuilder) buildApplyWithJoinType(outerPlan, innerPlan LogicalPlan, tp JoinType) LogicalPlan { b.optFlag = b.optFlag | flagPredicatePushDown | flagBuildKeyInfo | flagDecorrelate + setIsInApplyForCTE(innerPlan) ap := LogicalApply{LogicalJoin: LogicalJoin{JoinType: tp}}.Init(b.ctx, b.getSelectOffset()) ap.SetChildren(outerPlan, innerPlan) ap.names = make([]*types.FieldName, outerPlan.Schema().Len()+innerPlan.Schema().Len()) @@ -4500,12 +4708,31 @@ func (b *PlanBuilder) buildSemiApply(outerPlan, innerPlan LogicalPlan, condition return nil, err } + setIsInApplyForCTE(innerPlan) ap := &LogicalApply{LogicalJoin: *join} ap.tp = plancodec.TypeApply ap.self = ap return ap, nil } +// setIsInApplyForCTE indicates CTE is the in inner side of Apply, +// the storage of cte needs to be reset for each outer row. +// It's better to handle this in CTEExec.Close(), but cte storage is closed when SQL is finished. +func setIsInApplyForCTE(p LogicalPlan) { + switch x := p.(type) { + case *LogicalCTE: + x.cte.IsInApply = true + setIsInApplyForCTE(x.cte.seedPartLogicalPlan) + if x.cte.recursivePartLogicalPlan != nil { + setIsInApplyForCTE(x.cte.recursivePartLogicalPlan) + } + default: + for _, child := range p.Children() { + setIsInApplyForCTE(child) + } + } +} + func (b *PlanBuilder) buildMaxOneRow(p LogicalPlan) LogicalPlan { maxOneRow := LogicalMaxOneRow{}.Init(b.ctx, b.getSelectOffset()) maxOneRow.SetChildren(p) @@ -4768,8 +4995,9 @@ func (b *PlanBuilder) buildUpdate(ctx context.Context, update *ast.UpdateStmt) ( } type tblUpdateInfo struct { - name string - pkUpdated bool + name string + pkUpdated bool + partitionColUpdated bool } // CheckUpdateList checks all related columns in updatable state. @@ -4778,7 +5006,12 @@ func CheckUpdateList(assignFlags []int, updt *Update, newTblID2Table map[int64]t for _, content := range updt.TblColPosInfos { tbl := newTblID2Table[content.TblID] flags := assignFlags[content.Start:content.End] - var update, updatePK bool + var update, updatePK, updatePartitionCol bool + var partitionColumnNames []model.CIStr + if pt, ok := tbl.(table.PartitionedTable); ok && pt != nil { + partitionColumnNames = pt.GetPartitionColumnNames() + } + for i, col := range tbl.WritableCols() { if flags[i] >= 0 && col.State != model.StatePublic { return ErrUnknownColumn.GenWithStackByArgs(col.Name, clauseMsg[fieldList]) @@ -4788,19 +5021,25 @@ func CheckUpdateList(assignFlags []int, updt *Update, newTblID2Table map[int64]t if mysql.HasPriKeyFlag(col.Flag) { updatePK = true } + for _, partColName := range partitionColumnNames { + if col.Name.L == partColName.L { + updatePartitionCol = true + } + } } } if update { // Check for multi-updates on primary key, // see https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_multi_update_key_conflict if otherTable, ok := updateFromOtherAlias[tbl.Meta().ID]; ok { - if otherTable.pkUpdated || updatePK { + if otherTable.pkUpdated || updatePK || otherTable.partitionColUpdated || updatePartitionCol { return ErrMultiUpdateKeyConflict.GenWithStackByArgs(otherTable.name, updt.names[content.Start].TblName.O) } } else { updateFromOtherAlias[tbl.Meta().ID] = tblUpdateInfo{ - name: updt.names[content.Start].TblName.O, - pkUpdated: updatePK, + name: updt.names[content.Start].TblName.O, + pkUpdated: updatePK, + partitionColUpdated: updatePartitionCol, } } } @@ -4856,11 +5095,7 @@ func (b *PlanBuilder) buildUpdateLists(ctx context.Context, tableList []*ast.Tab columnFullName := fmt.Sprintf("%s.%s.%s", name.DBName.L, name.TblName.L, name.ColName.L) // We save a flag for the column in map `modifyColumns` // This flag indicated if assign keyword `DEFAULT` to the column - if extractDefaultExpr(assign.Expr) != nil { - modifyColumns[columnFullName] = true - } else { - modifyColumns[columnFullName] = false - } + modifyColumns[columnFullName] = IsDefaultExprSameColumn(p.OutputNames()[idx:idx+1], assign.Expr) } // If columns in set list contains generated columns, raise error. @@ -4998,9 +5233,25 @@ func extractDefaultExpr(node ast.ExprNode) *ast.DefaultExpr { return nil } -func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) (Plan, error) { +// IsDefaultExprSameColumn - DEFAULT or col = DEFAULT(col) +func IsDefaultExprSameColumn(names types.NameSlice, node ast.ExprNode) bool { + if expr, ok := node.(*ast.DefaultExpr); ok { + if expr.Name == nil { + // col = DEFAULT + return true + } + refIdx, err := expression.FindFieldName(names, expr.Name) + if refIdx == 0 && err == nil { + // col = DEFAULT(col) + return true + } + } + return false +} + +func (b *PlanBuilder) buildDelete(ctx context.Context, ds *ast.DeleteStmt) (Plan, error) { b.pushSelectOffset(0) - b.pushTableHints(delete.TableHints, 0) + b.pushTableHints(ds.TableHints, 0) defer func() { b.popSelectOffset() // table hints are only visible in the current DELETE statement. @@ -5010,18 +5261,18 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( b.inDeleteStmt = true b.isForUpdateRead = true - if delete.With != nil { + if ds.With != nil { l := len(b.outerCTEs) defer func() { b.outerCTEs = b.outerCTEs[:l] }() - err := b.buildWith(ctx, delete.With) + err := b.buildWith(ctx, ds.With) if err != nil { return nil, err } } - p, err := b.buildResultSetNode(ctx, delete.TableRefs.TableRefs) + p, err := b.buildResultSetNode(ctx, ds.TableRefs.TableRefs) if err != nil { return nil, err } @@ -5029,14 +5280,14 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( oldLen := oldSchema.Len() // For explicit column usage, should use the all-public columns. - if delete.Where != nil { - p, err = b.buildSelection(ctx, p, delete.Where, nil) + if ds.Where != nil { + p, err = b.buildSelection(ctx, p, ds.Where, nil) if err != nil { return nil, err } } if b.ctx.GetSessionVars().TxnCtx.IsPessimistic { - if !delete.IsMultiTable { + if !ds.IsMultiTable { p, err = b.buildSelectLock(p, &ast.SelectLockInfo{ LockType: ast.SelectLockForUpdate, }) @@ -5046,22 +5297,22 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( } } - if delete.Order != nil { - p, err = b.buildSort(ctx, p, delete.Order.Items, nil, nil) + if ds.Order != nil { + p, err = b.buildSort(ctx, p, ds.Order.Items, nil, nil) if err != nil { return nil, err } } - if delete.Limit != nil { - p, err = b.buildLimit(p, delete.Limit) + if ds.Limit != nil { + p, err = b.buildLimit(p, ds.Limit) if err != nil { return nil, err } } // If the delete is non-qualified it does not require Select Priv - if delete.Where == nil && delete.Order == nil { + if ds.Where == nil && ds.Order == nil { b.popVisitInfo() } var authErr error @@ -5089,7 +5340,7 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( } del := Delete{ - IsMultiTable: delete.IsMultiTable, + IsMultiTable: ds.IsMultiTable, }.Init(b.ctx) del.names = p.OutputNames() @@ -5104,12 +5355,12 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( } // Collect visitInfo. - if delete.Tables != nil { + if ds.Tables != nil { // Delete a, b from a, b, c, d... add a and b. updatableList := make(map[string]bool) tbInfoList := make(map[string]*ast.TableName) - collectTableName(delete.TableRefs.TableRefs, &updatableList, &tbInfoList) - for _, tn := range delete.Tables.Tables { + collectTableName(ds.TableRefs.TableRefs, &updatableList, &tbInfoList) + for _, tn := range ds.Tables.Tables { var canUpdate, foundMatch = false, false name := tn.Name.L if tn.Schema.L == "" { @@ -5136,10 +5387,10 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( tn.DBInfo = tb.DBInfo tn.TableInfo = tb.TableInfo if tn.TableInfo.IsView() { - return nil, errors.Errorf("delete view %s is not supported now.", tn.Name.O) + return nil, errors.Errorf("delete view %s is not supported now", tn.Name.O) } if tn.TableInfo.IsSequence() { - return nil, errors.Errorf("delete sequence %s is not supported now.", tn.Name.O) + return nil, errors.Errorf("delete sequence %s is not supported now", tn.Name.O) } if sessionVars.User != nil { authErr = ErrTableaccessDenied.FastGenByArgs("DELETE", sessionVars.User.AuthUsername, sessionVars.User.AuthHostname, tb.Name.L) @@ -5149,16 +5400,16 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( } else { // Delete from a, b, c, d. var tableList []*ast.TableName - tableList = extractTableList(delete.TableRefs.TableRefs, tableList, false) + tableList = extractTableList(ds.TableRefs.TableRefs, tableList, false) for _, v := range tableList { if isCTE(v) { return nil, ErrNonUpdatableTable.GenWithStackByArgs(v.Name.O, "DELETE") } if v.TableInfo.IsView() { - return nil, errors.Errorf("delete view %s is not supported now.", v.Name.O) + return nil, errors.Errorf("delete view %s is not supported now", v.Name.O) } if v.TableInfo.IsSequence() { - return nil, errors.Errorf("delete sequence %s is not supported now.", v.Name.O) + return nil, errors.Errorf("delete sequence %s is not supported now", v.Name.O) } dbName := v.Schema.L if dbName == "" { @@ -5175,8 +5426,8 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) ( // Table ID may not be unique for deleting multiple tables, for statements like // `delete from t as t1, t as t2`, the same table has two alias, we have to identify a table // by its alias instead of ID. - tblID2TableName := make(map[int64][]*ast.TableName, len(delete.Tables.Tables)) - for _, tn := range delete.Tables.Tables { + tblID2TableName := make(map[int64][]*ast.TableName, len(ds.Tables.Tables)) + for _, tn := range ds.Tables.Tables { tblID2TableName[tn.TableInfo.ID] = append(tblID2TableName[tn.TableInfo.ID], tn) } tblID2Handle = del.cleanTblID2HandleMap(tblID2TableName, tblID2Handle, del.names) @@ -6185,6 +6436,12 @@ func containDifferentJoinTypes(preferJoinType uint) bool { } func (b *PlanBuilder) buildCte(ctx context.Context, cte *ast.CommonTableExpression, isRecursive bool) (p LogicalPlan, err error) { + saveBuildingCTE := b.buildingCTE + b.buildingCTE = true + defer func() { + b.buildingCTE = saveBuildingCTE + }() + if isRecursive { // buildingRecursivePartForCTE likes a stack. We save it before building a recursive CTE and restore it after building. // We need a stack because we need to handle the nested recursive CTE. And buildingRecursivePartForCTE indicates the innermost CTE. @@ -6381,7 +6638,7 @@ func (b *PlanBuilder) adjustCTEPlanOutputName(p LogicalPlan, def *ast.CommonTabl } if len(def.ColNameList) > 0 { if len(def.ColNameList) != len(p.OutputNames()) { - return nil, ddl.ErrViewWrongList + return nil, dbterror.ErrViewWrongList } for i, n := range def.ColNameList { outPutNames[i].ColName = n diff --git a/planner/core/logical_plan_test.go b/planner/core/logical_plan_test.go index e381da64fcdb6..1fb0e2a552022 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -21,7 +21,6 @@ import ( "strings" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" @@ -35,86 +34,106 @@ import ( "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPlanSuite{}) - -func TestT(t *testing.T) { - CustomVerboseFlag = true - TestingT(t) -} - -type testPlanSuite struct { - *parser.Parser - +type plannerSuite struct { + p *parser.Parser is infoschema.InfoSchema ctx sessionctx.Context - - testData testutil.TestData - - optimizeVars map[string]string } -func (s *testPlanSuite) SetUpSuite(c *C) { - s.is = infoschema.MockInfoSchema([]*model.TableInfo{MockSignedTable(), MockUnsignedTable(), MockView(), MockNoPKTable(), - MockRangePartitionTable(), MockHashPartitionTable(), MockListPartitionTable()}) +func createPlannerSuite() (s *plannerSuite) { + s = new(plannerSuite) + tblInfos := []*model.TableInfo{ + MockSignedTable(), + MockUnsignedTable(), + MockView(), + MockNoPKTable(), + MockRangePartitionTable(), + MockHashPartitionTable(), + MockListPartitionTable(), + } + id := int64(0) + for _, tblInfo := range tblInfos { + tblInfo.ID = id + id += 1 + pi := tblInfo.GetPartitionInfo() + if pi == nil { + continue + } + for _, def := range pi.Definitions { + def.ID = id + id += 1 + } + } + s.is = infoschema.MockInfoSchema(tblInfos) s.ctx = MockContext() domain.GetDomain(s.ctx).MockInfoCacheAndLoadInfoSchema(s.is) s.ctx.GetSessionVars().EnableWindowFunction = true - s.Parser = parser.New() - s.Parser.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) - - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "plan_suite_unexported") - c.Assert(err, IsNil) + s.p = parser.New() + s.p.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) + return } -func (s *testPlanSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testPlanSuite) TestPredicatePushDown(c *C) { - defer testleak.AfterTest(c)() +func TestPredicatePushDown(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for ith, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[ith] = ToString(p) }) - c.Assert(ToString(p), Equals, output[ith], Commentf("for %s %d", ca, ith)) + require.Equal(t, output[ith], ToString(p), fmt.Sprintf("for %s %d", ca, ith)) } } -func (s *testPlanSuite) TestEliminateProjectionUnderUnion(c *C) { - defer testleak.AfterTest(c)() +// Issue: 31399 +func TestImplicitCastNotNullFlag(t *testing.T) { + ctx := context.Background() + ca := "select count(*) from t3 group by a having bit_and(b) > 1;" + comment := fmt.Sprintf("for %s", ca) + s := createPlannerSuite() + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) + p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) + require.NoError(t, err) + p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagJoinReOrder|flagPrunColumns|flagEliminateProjection, p.(LogicalPlan)) + require.NoError(t, err) + // AggFuncs[0] is count; AggFuncs[1] is bit_and, args[0] is return type of the implicit cast + castNotNullFlag := (p.(*LogicalProjection).children[0].(*LogicalSelection).children[0].(*LogicalAggregation).AggFuncs[1].Args[0].GetType().Flag) & mysql.NotNullFlag + var nullableFlag uint = 0 + require.Equal(t, nullableFlag, castNotNullFlag) +} + +func TestEliminateProjectionUnderUnion(t *testing.T) { ctx := context.Background() ca := "Select a from t3 join ( (select 127 as IDD from t3) union all (select 1 as IDD from t3) ) u on t3.b = u.IDD;" - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + s := createPlannerSuite() + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagJoinReOrder|flagPrunColumns|flagEliminateProjection, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) // after folding constants, the null flag should keep the same with the old one's (i.e., the schema's). schemaNullFlag := p.(*LogicalProjection).children[0].(*LogicalJoin).children[1].Children()[1].(*LogicalProjection).schema.Columns[0].RetType.Flag & mysql.NotNullFlag exprNullFlag := p.(*LogicalProjection).children[0].(*LogicalJoin).children[1].Children()[1].(*LogicalProjection).Exprs[0].GetType().Flag & mysql.NotNullFlag - c.Assert(schemaNullFlag, Equals, exprNullFlag) + require.Equal(t, exprNullFlag, schemaNullFlag) } -func (s *testPlanSuite) TestJoinPredicatePushDown(c *C) { - defer testleak.AfterTest(c)() +func TestJoinPredicatePushDown(t *testing.T) { var ( input []string output []struct { @@ -122,37 +141,37 @@ func (s *testPlanSuite) TestJoinPredicatePushDown(c *C) { Right string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) proj, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) join, ok := proj.children[0].(*LogicalJoin) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftPlan, ok := join.children[0].(*DataSource) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) rightPlan, ok := join.children[1].(*DataSource) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftCond := fmt.Sprintf("%s", leftPlan.pushedDownConds) rightCond := fmt.Sprintf("%s", rightPlan.pushedDownConds) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Left, output[i].Right = leftCond, rightCond }) - c.Assert(leftCond, Equals, output[i].Left, comment) - c.Assert(rightCond, Equals, output[i].Right, comment) + require.Equal(t, output[i].Left, leftCond, comment) + require.Equal(t, output[i].Right, rightCond, comment) } } -func (s *testPlanSuite) TestOuterWherePredicatePushDown(c *C) { - defer testleak.AfterTest(c)() +func TestOuterWherePredicatePushDown(t *testing.T) { var ( input []string output []struct { @@ -161,44 +180,44 @@ func (s *testPlanSuite) TestOuterWherePredicatePushDown(c *C) { Right string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) proj, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) selection, ok := proj.children[0].(*LogicalSelection) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) selCond := fmt.Sprintf("%s", selection.Conditions) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Sel = selCond }) - c.Assert(selCond, Equals, output[i].Sel, comment) + require.Equal(t, output[i].Sel, selCond, comment) join, ok := selection.children[0].(*LogicalJoin) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftPlan, ok := join.children[0].(*DataSource) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) rightPlan, ok := join.children[1].(*DataSource) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftCond := fmt.Sprintf("%s", leftPlan.pushedDownConds) rightCond := fmt.Sprintf("%s", rightPlan.pushedDownConds) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Left, output[i].Right = leftCond, rightCond }) - c.Assert(leftCond, Equals, output[i].Left, comment) - c.Assert(rightCond, Equals, output[i].Right, comment) + require.Equal(t, output[i].Left, leftCond, comment) + require.Equal(t, output[i].Right, rightCond, comment) } } -func (s *testPlanSuite) TestSimplifyOuterJoin(c *C) { - defer testleak.AfterTest(c)() +func TestSimplifyOuterJoin(t *testing.T) { var ( input []string output []struct { @@ -206,36 +225,36 @@ func (s *testPlanSuite) TestSimplifyOuterJoin(c *C) { JoinType string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) planString := ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Best = planString }) - c.Assert(planString, Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, planString, comment) join, ok := p.(LogicalPlan).Children()[0].(*LogicalJoin) if !ok { join, ok = p.(LogicalPlan).Children()[0].Children()[0].(*LogicalJoin) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].JoinType = join.JoinType.String() }) - c.Assert(join.JoinType.String(), Equals, output[i].JoinType, comment) + require.Equal(t, output[i].JoinType, join.JoinType.String(), comment) } } -func (s *testPlanSuite) TestAntiSemiJoinConstFalse(c *C) { - defer testleak.AfterTest(c)() +func TestAntiSemiJoinConstFalse(t *testing.T) { tests := []struct { sql string best string @@ -248,23 +267,23 @@ func (s *testPlanSuite) TestAntiSemiJoinConstFalse(c *C) { }, } + s := createPlannerSuite() ctx := context.Background() for _, ca := range tests { - comment := Commentf("for %s", ca.sql) - stmt, err := s.ParseOneStmt(ca.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca.sql) + stmt, err := s.p.ParseOneStmt(ca.sql, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagDecorrelate|flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) - c.Assert(ToString(p), Equals, ca.best, comment) + require.NoError(t, err, comment) + require.Equal(t, ca.best, ToString(p), comment) join, _ := p.(LogicalPlan).Children()[0].(*LogicalJoin) - c.Assert(join.JoinType.String(), Equals, ca.joinType, comment) + require.Equal(t, ca.joinType, join.JoinType.String(), comment) } } -func (s *testPlanSuite) TestDeriveNotNullConds(c *C) { - defer testleak.AfterTest(c)() +func TestDeriveNotNullConds(t *testing.T) { var ( input []string output []struct { @@ -273,59 +292,60 @@ func (s *testPlanSuite) TestDeriveNotNullConds(c *C) { Right string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain|flagDecorrelate, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].Plan = ToString(p) }) - c.Assert(ToString(p), Equals, output[i].Plan, comment) + require.Equal(t, output[i].Plan, ToString(p), comment) join := p.(LogicalPlan).Children()[0].(*LogicalJoin) left := join.Children()[0].(*DataSource) right := join.Children()[1].(*DataSource) leftConds := fmt.Sprintf("%s", left.pushedDownConds) rightConds := fmt.Sprintf("%s", right.pushedDownConds) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Left, output[i].Right = leftConds, rightConds }) - c.Assert(leftConds, Equals, output[i].Left, comment) - c.Assert(rightConds, Equals, output[i].Right, comment) + require.Equal(t, output[i].Left, leftConds, comment) + require.Equal(t, output[i].Right, rightConds, comment) } } -func (s *testPlanSuite) TestExtraPKNotNullFlag(c *C) { - defer testleak.AfterTest(c)() +func TestExtraPKNotNullFlag(t *testing.T) { sql := "select count(*) from t3" + s := createPlannerSuite() ctx := context.Background() - comment := Commentf("for %s", sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", sql) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) ds := p.(*LogicalProjection).children[0].(*LogicalAggregation).children[0].(*DataSource) - c.Assert(ds.Columns[2].Name.L, Equals, "_tidb_rowid") - c.Assert(ds.Columns[2].Flag, Equals, mysql.PriKeyFlag|mysql.NotNullFlag) - c.Assert(ds.schema.Columns[2].RetType.Flag, Equals, mysql.PriKeyFlag|mysql.NotNullFlag) + require.Equal(t, "_tidb_rowid", ds.Columns[2].Name.L) + require.Equal(t, mysql.PriKeyFlag|mysql.NotNullFlag, ds.Columns[2].Flag) + require.Equal(t, mysql.PriKeyFlag|mysql.NotNullFlag, ds.schema.Columns[2].RetType.Flag) } -func buildLogicPlan4GroupBy(s *testPlanSuite, c *C, sql string) (Plan, error) { +func buildLogicPlan4GroupBy(s *plannerSuite, t *testing.T, sql string) (Plan, error) { sqlMode := s.ctx.GetSessionVars().SQLMode mockedTableInfo := MockSignedTable() // mock the table info here for later use // enable only full group by s.ctx.GetSessionVars().SQLMode = sqlMode | mysql.ModeOnlyFullGroupBy defer func() { s.ctx.GetSessionVars().SQLMode = sqlMode }() // restore it - comment := Commentf("for %s", sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", sql) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) stmt.(*ast.SelectStmt).From.TableRefs.Left.(*ast.TableSource).Source.(*ast.TableName).TableInfo = mockedTableInfo @@ -333,7 +353,7 @@ func buildLogicPlan4GroupBy(s *testPlanSuite, c *C, sql string) (Plan, error) { return p, err } -func (s *testPlanSuite) TestGroupByWhenNotExistCols(c *C) { +func TestGroupByWhenNotExistCols(t *testing.T) { sqlTests := []struct { sql string expectedErrMatch string @@ -373,37 +393,38 @@ func (s *testPlanSuite) TestGroupByWhenNotExistCols(c *C) { expectedErrMatch: ".*contains nonaggregated column 'test\\.t\\.a'.*", }, } + s := createPlannerSuite() for _, test := range sqlTests { sql := test.sql - p, err := buildLogicPlan4GroupBy(s, c, sql) - c.Assert(err, NotNil) - c.Assert(p, IsNil) - c.Assert(err, ErrorMatches, test.expectedErrMatch) + p, err := buildLogicPlan4GroupBy(s, t, sql) + require.Nil(t, p) + require.Error(t, err) + require.Regexp(t, test.expectedErrMatch, err.Error()) } } -func (s *testPlanSuite) TestDupRandJoinCondsPushDown(c *C) { +func TestDupRandJoinCondsPushDown(t *testing.T) { sql := "select * from t as t1 join t t2 on t1.a > rand() and t1.a > rand()" - comment := Commentf("for %s", sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", sql) + s := createPlannerSuite() + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(context.Background(), s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) proj, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) join, ok := proj.children[0].(*LogicalJoin) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftPlan, ok := join.children[0].(*LogicalSelection) - c.Assert(ok, IsTrue, comment) + require.True(t, ok, comment) leftCond := fmt.Sprintf("%s", leftPlan.Conditions) // Condition with mutable function cannot be de-duplicated when push down join conds. - c.Assert(leftCond, Equals, "[gt(cast(test.t.a, double BINARY), rand()) gt(cast(test.t.a, double BINARY), rand())]", comment) + require.Equal(t, "[gt(cast(test.t.a, double BINARY), rand()) gt(cast(test.t.a, double BINARY), rand())]", leftCond, comment) } -func (s *testPlanSuite) TestTablePartition(c *C) { - defer testleak.AfterTest(c)() +func TestTablePartition(t *testing.T) { definitions := []model.PartitionDefinition{ { ID: 41, @@ -445,179 +466,183 @@ func (s *testPlanSuite) TestTablePartition(c *C) { } output []string ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca.SQL) - stmt, err := s.ParseOneStmt(ca.SQL, "", "") - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("for %s", ca.SQL) + stmt, err := s.p.ParseOneStmt(ca.SQL, "", "") + require.NoError(t, err, comment) + testdata.OnRecord(func() { }) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, isChoices[ca.IsIdx]) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain|flagPredicatePushDown|flagPartitionProcessor, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) planString := ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(ToString(p), Equals, output[i], Commentf("for %s", ca)) + require.Equal(t, output[i], ToString(p), fmt.Sprintf("for %v", ca)) } } -func (s *testPlanSuite) TestSubquery(c *C) { - defer testleak.AfterTest(c)() +func TestSubquery(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for ith, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) if lp, ok := p.(LogicalPlan); ok { p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain, lp) - c.Assert(err, IsNil) + require.NoError(t, err) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[ith] = ToString(p) }) - c.Assert(ToString(p), Equals, output[ith], Commentf("for %s %d", ca, ith)) + require.Equal(t, output[ith], ToString(p), fmt.Sprintf("for %s %d", ca, ith)) } } -func (s *testPlanSuite) TestPlanBuilder(c *C) { - defer testleak.AfterTest(c)() +func TestPlanBuilder(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + + s := createPlannerSuite() ctx := context.Background() for i, ca := range input { - comment := Commentf("for %s", ca) - stmt, err := s.ParseOneStmt(ca, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", ca) + stmt, err := s.p.ParseOneStmt(ca, "", "") + require.NoError(t, err, comment) s.ctx.GetSessionVars().SetHashJoinConcurrency(1) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) if lp, ok := p.(LogicalPlan); ok { p, err = logicalOptimize(context.TODO(), flagPrunColumns|flagPrunColumnsAgain, lp) - c.Assert(err, IsNil) + require.NoError(t, err) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = ToString(p) }) - c.Assert(ToString(p), Equals, output[i], Commentf("for %s", ca)) + require.Equal(t, output[i], ToString(p), fmt.Sprintf("for %s", ca)) } } -func (s *testPlanSuite) TestJoinReOrder(c *C) { - defer testleak.AfterTest(c)() +func TestJoinReOrder(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagJoinReOrder, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) planString := ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], Commentf("for %s", tt)) + require.Equal(t, output[i], planString, fmt.Sprintf("for %s", tt)) } } -func (s *testPlanSuite) TestEagerAggregation(c *C) { - defer testleak.AfterTest(c)() +func TestEagerAggregation(t *testing.T) { var input []string var output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + + s := createPlannerSuite() ctx := context.Background() s.ctx.GetSessionVars().AllowAggPushDown = true + defer func() { + s.ctx.GetSessionVars().AllowAggPushDown = false + }() for ith, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain|flagPushDownAgg, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[ith] = ToString(p) }) - c.Assert(ToString(p), Equals, output[ith], Commentf("for %s %d", tt, ith)) + require.Equal(t, output[ith], ToString(p), fmt.Sprintf("for %s %d", tt, ith)) } - s.ctx.GetSessionVars().AllowAggPushDown = false } -func (s *testPlanSuite) TestColumnPruning(c *C) { - defer testleak.AfterTest(c)() +func TestColumnPruning(t *testing.T) { var ( input []string output []map[int][]string ) - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, tt := range input { - comment := Commentf("case:%v sql:\"%s\"", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:\"%s\"", i, tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) lp, err := logicalOptimize(ctx, flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[i] = make(map[int][]string) }) - s.checkDataSourceCols(lp, c, output[i], comment) + checkDataSourceCols(lp, t, output[i], comment) } } -func (s *testPlanSuite) TestSortByItemsPruning(c *C) { - defer testleak.AfterTest(c)() +func TestSortByItemsPruning(t *testing.T) { var ( input []string output [][]string ) - s.testData.GetTestCases(c, &input, &output) - s.testData.OnRecord(func() { + planSuiteUnexportedData.GetTestCases(t, &input, &output) + testdata.OnRecord(func() { output = make([][]string, len(input)) }) + s := createPlannerSuite() ctx := context.Background() for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) lp, err := logicalOptimize(ctx, flagEliminateProjection|flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.checkOrderByItems(lp, c, &output[i], comment) + require.NoError(t, err) + checkOrderByItems(lp, t, &output[i], comment) } } -func (s *testPlanSuite) TestProjectionEliminator(c *C) { - defer testleak.AfterTest(c)() +func TestProjectionEliminator(t *testing.T) { tests := []struct { sql string best string @@ -631,94 +656,93 @@ func (s *testPlanSuite) TestProjectionEliminator(c *C) { }, } + s := createPlannerSuite() ctx := context.Background() for ith, tt := range tests { - comment := Commentf("for %s", tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagPrunColumns|flagPrunColumnsAgain|flagEliminateProjection, p.(LogicalPlan)) - c.Assert(err, IsNil) - c.Assert(ToString(p), Equals, tt.best, Commentf("for %s %d", tt.sql, ith)) + require.NoError(t, err) + require.Equal(t, tt.best, ToString(p), fmt.Sprintf("for %s %d", tt.sql, ith)) } } -func (s *testPlanSuite) TestCS3389(c *C) { - defer testleak.AfterTest(c)() - +func TestCS3389(t *testing.T) { + s := createPlannerSuite() ctx := context.Background() - stmt, err := s.ParseOneStmt("select count(*) from t where a in (select b from t2 where a is null);", "", "") - c.Assert(err, IsNil) + stmt, err := s.p.ParseOneStmt("select count(*) from t where a in (select b from t2 where a is null);", "", "") + require.NoError(t, err) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagPrunColumns|flagPrunColumnsAgain|flagEliminateProjection|flagJoinReOrder, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) // Assert that all Projection is not empty and there is no Projection between Aggregation and Join. proj, isProj := p.(*LogicalProjection) - c.Assert(isProj, IsTrue) - c.Assert(len(proj.Exprs) > 0, IsTrue) + require.True(t, isProj) + require.True(t, len(proj.Exprs) > 0) child := proj.Children()[0] agg, isAgg := child.(*LogicalAggregation) - c.Assert(isAgg, IsTrue) + require.True(t, isAgg) child = agg.Children()[0] _, isJoin := child.(*LogicalJoin) - c.Assert(isJoin, IsTrue) + require.True(t, isJoin) } -func (s *testPlanSuite) TestAllocID(c *C) { +func TestAllocID(t *testing.T) { ctx := MockContext() pA := DataSource{}.Init(ctx, 0) pB := DataSource{}.Init(ctx, 0) - c.Assert(pA.id+1, Equals, pB.id) + require.Equal(t, pB.id, pA.id+1) } -func (s *testPlanSuite) checkDataSourceCols(p LogicalPlan, c *C, ans map[int][]string, comment CommentInterface) { +func checkDataSourceCols(p LogicalPlan, t *testing.T, ans map[int][]string, comment string) { switch v := p.(type) { case *DataSource, *LogicalUnionAll, *LogicalLimit: - s.testData.OnRecord(func() { + testdata.OnRecord(func() { ans[p.ID()] = make([]string, p.Schema().Len()) }) colList, ok := ans[p.ID()] - c.Assert(ok, IsTrue, Commentf("For %s %T ID %d Not found", comment.CheckCommentString(), v, p.ID())) - c.Assert(len(p.Schema().Columns), Equals, len(colList), comment) + require.True(t, ok, fmt.Sprintf("For %s %T ID %d Not found", comment, v, p.ID())) + require.Equal(t, len(colList), len(p.Schema().Columns), comment) for i, col := range p.Schema().Columns { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { colList[i] = col.String() }) - c.Assert(col.String(), Equals, colList[i], comment) + require.Equal(t, colList[i], col.String(), comment) } } for _, child := range p.Children() { - s.checkDataSourceCols(child, c, ans, comment) + checkDataSourceCols(child, t, ans, comment) } } -func (s *testPlanSuite) checkOrderByItems(p LogicalPlan, c *C, colList *[]string, comment CommentInterface) { +func checkOrderByItems(p LogicalPlan, t *testing.T, colList *[]string, comment string) { switch p := p.(type) { case *LogicalSort: - s.testData.OnRecord(func() { + testdata.OnRecord(func() { *colList = make([]string, len(p.ByItems)) }) for i, col := range p.ByItems { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { (*colList)[i] = col.String() }) s := col.String() - c.Assert(s, Equals, (*colList)[i], comment) + require.Equal(t, (*colList)[i], s, comment) } } children := p.Children() - c.Assert(len(children), LessEqual, 1, Commentf("For %v Expected <= 1 Child", comment)) + require.LessOrEqual(t, len(children), 1, fmt.Sprintf("For %v Expected <= 1 Child", comment)) for _, child := range children { - s.checkOrderByItems(child, c, colList, comment) + checkOrderByItems(child, t, colList, comment) } } -func (s *testPlanSuite) TestValidate(c *C) { - defer testleak.AfterTest(c)() +func TestValidate(t *testing.T) { tests := []struct { sql string err *terror.Error @@ -889,102 +913,102 @@ func (s *testPlanSuite) TestValidate(c *C) { }, } + s := createPlannerSuite() ctx := context.Background() for _, tt := range tests { sql := tt.sql - comment := Commentf("for %s", sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", sql) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) _, _, err = BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) if tt.err == nil { - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) } else { - c.Assert(tt.err.Equal(err), IsTrue, comment) + require.True(t, tt.err.Equal(err), comment) } } } -func (s *testPlanSuite) checkUniqueKeys(p LogicalPlan, c *C, ans map[int][][]string, sql string) { - s.testData.OnRecord(func() { +func checkUniqueKeys(p LogicalPlan, t *testing.T, ans map[int][][]string, sql string) { + testdata.OnRecord(func() { ans[p.ID()] = make([][]string, len(p.Schema().Keys)) }) keyList, ok := ans[p.ID()] - c.Assert(ok, IsTrue, Commentf("for %s, %v not found", sql, p.ID())) - c.Assert(len(p.Schema().Keys), Equals, len(keyList), Commentf("for %s, %v, the number of key doesn't match, the schema is %s", sql, p.ID(), p.Schema())) + require.True(t, ok, fmt.Sprintf("for %s, %v not found", sql, p.ID())) + require.Equal(t, len(keyList), len(p.Schema().Keys), fmt.Sprintf("for %s, %v, the number of key doesn't match, the schema is %s", sql, p.ID(), p.Schema())) for i := range keyList { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { keyList[i] = make([]string, len(p.Schema().Keys[i])) }) - c.Assert(len(p.Schema().Keys[i]), Equals, len(keyList[i]), Commentf("for %s, %v %v, the number of column doesn't match", sql, p.ID(), keyList[i])) + require.Equal(t, len(keyList[i]), len(p.Schema().Keys[i]), fmt.Sprintf("for %s, %v %v, the number of column doesn't match", sql, p.ID(), keyList[i])) for j := range keyList[i] { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { keyList[i][j] = p.Schema().Keys[i][j].String() }) - c.Assert(p.Schema().Keys[i][j].String(), Equals, keyList[i][j], Commentf("for %s, %v %v, column dosen't match", sql, p.ID(), keyList[i])) + require.Equal(t, keyList[i][j], p.Schema().Keys[i][j].String(), fmt.Sprintf("for %s, %v %v, column dosen't match", sql, p.ID(), keyList[i])) } } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { ans[p.ID()] = keyList }) for _, child := range p.Children() { - s.checkUniqueKeys(child, c, ans, sql) + checkUniqueKeys(child, t, ans, sql) } } -func (s *testPlanSuite) TestUniqueKeyInfo(c *C) { - defer testleak.AfterTest(c)() +func TestUniqueKeyInfo(t *testing.T) { var input []string var output []map[int][][]string - s.testData.GetTestCases(c, &input, &output) - s.testData.OnRecord(func() { + planSuiteUnexportedData.GetTestCases(t, &input, &output) + testdata.OnRecord(func() { output = make([]map[int][][]string, len(input)) }) + s := createPlannerSuite() ctx := context.Background() for ith, tt := range input { - comment := Commentf("for %s %d", tt, ith) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s %d", tt, ith) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) lp, err := logicalOptimize(context.TODO(), flagPredicatePushDown|flagPrunColumns|flagBuildKeyInfo, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[ith] = make(map[int][][]string) }) - s.checkUniqueKeys(lp, c, output[ith], tt) + checkUniqueKeys(lp, t, output[ith], tt) } } -func (s *testPlanSuite) TestAggPrune(c *C) { - defer testleak.AfterTest(c)() +func TestAggPrune(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.Background() for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) domain.GetDomain(s.ctx).MockInfoCacheAndLoadInfoSchema(s.is) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(context.TODO(), flagPredicatePushDown|flagPrunColumns|flagPrunColumnsAgain|flagBuildKeyInfo|flagEliminateAgg|flagEliminateProjection, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) planString := ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], comment) + require.Equal(t, output[i], planString, comment) } } -func (s *testPlanSuite) TestVisitInfo(c *C) { - defer testleak.AfterTest(c)() +func TestVisitInfo(t *testing.T) { tests := []struct { sql string ans []visitInfo @@ -1127,6 +1151,7 @@ func (s *testPlanSuite) TestVisitInfo(c *C) { {mysql.IndexPriv, "test", "", "", nil, false, "", false}, {mysql.CreateViewPriv, "test", "", "", nil, false, "", false}, {mysql.ShowViewPriv, "test", "", "", nil, false, "", false}, + {mysql.TriggerPriv, "test", "", "", nil, false, "", false}, }, }, { @@ -1201,6 +1226,7 @@ func (s *testPlanSuite) TestVisitInfo(c *C) { {mysql.IndexPriv, "test", "", "", nil, false, "", false}, {mysql.CreateViewPriv, "test", "", "", nil, false, "", false}, {mysql.ShowViewPriv, "test", "", "", nil, false, "", false}, + {mysql.TriggerPriv, "test", "", "", nil, false, "", false}, }, }, { @@ -1381,10 +1407,11 @@ func (s *testPlanSuite) TestVisitInfo(c *C) { }, } + s := createPlannerSuite() for _, tt := range tests { - comment := Commentf("for %s", tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) // TODO: to fix, Table 'test.ttt' doesn't exist _ = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) @@ -1393,9 +1420,9 @@ func (s *testPlanSuite) TestVisitInfo(c *C) { domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) builder.ctx.GetSessionVars().SetHashJoinConcurrency(1) _, err = builder.Build(context.TODO(), stmt) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) - checkVisitInfo(c, builder.visitInfo, tt.ans, comment) + checkVisitInfo(t, builder.visitInfo, tt.ans, comment) } } @@ -1438,90 +1465,85 @@ func unique(v []visitInfo) []visitInfo { return v[:len(v)-repeat] } -func checkVisitInfo(c *C, v1, v2 []visitInfo, comment CommentInterface) { +func checkVisitInfo(t *testing.T, v1, v2 []visitInfo, comment string) { sort.Sort(visitInfoArray(v1)) sort.Sort(visitInfoArray(v2)) v1 = unique(v1) v2 = unique(v2) - c.Assert(len(v1), Equals, len(v2), comment) + require.Equal(t, len(v2), len(v1), comment) for i := 0; i < len(v1); i++ { // loose compare errors for code match - c.Assert(terror.ErrorEqual(v1[i].err, v2[i].err), IsTrue, Commentf("err1 %v, err2 %v for %s", v1[i].err, v2[i].err, comment)) + require.True(t, terror.ErrorEqual(v1[i].err, v2[i].err), fmt.Sprintf("err1 %v, err2 %v for %s", v1[i].err, v2[i].err, comment)) // compare remainder v1[i].err = v2[i].err - c.Assert(v1[i], Equals, v2[i], comment) + require.Equal(t, v2[i], v1[i], comment) } } -func (s *testPlanSuite) TestUnion(c *C) { - defer func() { - testleak.AfterTest(c)() - }() +func TestUnion(t *testing.T) { var input []string var output []struct { Best string Err bool } - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.TODO() for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) plan, err := builder.Build(ctx, stmt) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Err = err != nil }) if output[i].Err { - c.Assert(err, NotNil) + require.Error(t, err) continue } - c.Assert(err, IsNil) + require.NoError(t, err, comment) p := plan.(LogicalPlan) p, err = logicalOptimize(ctx, builder.optFlag, p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Best = ToString(p) }) - c.Assert(err, IsNil) - c.Assert(ToString(p), Equals, output[i].Best, comment) + require.NoError(t, err) + require.Equal(t, output[i].Best, ToString(p), comment) } } -func (s *testPlanSuite) TestTopNPushDown(c *C) { - defer func() { - testleak.AfterTest(c)() - }() +func TestTopNPushDown(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.TODO() for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[i] = ToString(p) }) - c.Assert(ToString(p), Equals, output[i], comment) + require.Equal(t, output[i], ToString(p), comment) } } -func (s *testPlanSuite) TestNameResolver(c *C) { - defer testleak.AfterTest(c)() +func TestNameResolver(t *testing.T) { tests := []struct { sql string err string @@ -1555,53 +1577,51 @@ func (s *testPlanSuite) TestNameResolver(c *C) { {"select sum(a) as x from t group by 1", "[planner:1056]Can't group on 'x'"}, } + s := createPlannerSuite() ctx := context.Background() - for _, t := range tests { - comment := Commentf("for %s", t.sql) - stmt, err := s.ParseOneStmt(t.sql, "", "") - c.Assert(err, IsNil, comment) + for _, test := range tests { + comment := fmt.Sprintf("for %s", test.sql) + stmt, err := s.p.ParseOneStmt(test.sql, "", "") + require.NoError(t, err, comment) s.ctx.GetSessionVars().SetHashJoinConcurrency(1) _, _, err = BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - if t.err == "" { - c.Check(err, IsNil) + if test.err == "" { + require.NoError(t, err) } else { - c.Assert(err.Error(), Equals, t.err) + require.EqualError(t, err, test.err) } } } -func (s *testPlanSuite) TestOuterJoinEliminator(c *C) { - defer testleak.AfterTest(c)() +func TestOuterJoinEliminator(t *testing.T) { var input, output []string - s.testData.GetTestCases(c, &input, &output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s := createPlannerSuite() ctx := context.TODO() for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := s.p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) planString := ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = planString }) - c.Assert(planString, Equals, output[i], comment) + require.Equal(t, output[i], planString, comment) } } -func (s *testPlanSuite) TestSelectView(c *C) { - defer func() { - testleak.AfterTest(c)() - }() +func TestSelectView(t *testing.T) { tests := []struct { sql string best string @@ -1615,80 +1635,90 @@ func (s *testPlanSuite) TestSelectView(c *C) { best: "DataScan(t)->Projection", }, } + s := createPlannerSuite() ctx := context.TODO() for i, tt := range tests { - comment := Commentf("case:%v sql:%s", i, tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) builder, _ := NewPlanBuilder().Init(MockContext(), s.is, &hint.BlockHintProcessor{}) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) - c.Assert(ToString(p), Equals, tt.best, comment) + require.NoError(t, err) + require.Equal(t, tt.best, ToString(p), comment) } } -func (s *testPlanSuite) TestWindowFunction(c *C) { +type plannerSuiteWithOptimizeVars struct { + *plannerSuite + optimizeVars map[string]string +} + +func TestWindowFunction(t *testing.T) { + s := new(plannerSuiteWithOptimizeVars) + s.plannerSuite = createPlannerSuite() + s.optimizeVars = map[string]string{ variable.TiDBWindowConcurrency: "1", } defer func() { s.optimizeVars = nil - testleak.AfterTest(c)() }() var input, output []string - s.testData.GetTestCases(c, &input, &output) - s.doTestWindowFunction(c, input, output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s.doTestWindowFunction(t, input, output) } -func (s *testPlanSuite) TestWindowParallelFunction(c *C) { +func TestWindowParallelFunction(t *testing.T) { + s := new(plannerSuiteWithOptimizeVars) + s.plannerSuite = createPlannerSuite() + s.optimizeVars = map[string]string{ variable.TiDBWindowConcurrency: "4", } defer func() { s.optimizeVars = nil - testleak.AfterTest(c)() }() var input, output []string - s.testData.GetTestCases(c, &input, &output) - s.doTestWindowFunction(c, input, output) + planSuiteUnexportedData.GetTestCases(t, &input, &output) + s.doTestWindowFunction(t, input, output) } -func (s *testPlanSuite) doTestWindowFunction(c *C, input, output []string) { +func (s *plannerSuiteWithOptimizeVars) doTestWindowFunction(t *testing.T, input, output []string) { ctx := context.TODO() for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) p, stmt, err := s.optimize(ctx, tt) if err != nil { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = err.Error() }) - c.Assert(err.Error(), Equals, output[i], comment) + require.EqualError(t, err, output[i], comment) continue } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i] = ToString(p) }) - c.Assert(ToString(p), Equals, output[i], comment) + require.Equal(t, output[i], ToString(p), comment) var sb strings.Builder // After restore, the result should be the same. err = stmt.Restore(format.NewRestoreCtx(format.DefaultRestoreFlags, &sb)) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err = s.optimize(ctx, sb.String()) if err != nil { - c.Assert(err.Error(), Equals, output[i], comment) + require.EqualError(t, err, output[i], comment) continue } - c.Assert(ToString(p), Equals, output[i], comment) + require.Equal(t, output[i], ToString(p), comment) } } -func (s *testPlanSuite) optimize(ctx context.Context, sql string) (PhysicalPlan, ast.Node, error) { - stmt, err := s.ParseOneStmt(sql, "", "") +func (s *plannerSuiteWithOptimizeVars) optimize(ctx context.Context, sql string) (PhysicalPlan, ast.Node, error) { + stmt, err := s.p.ParseOneStmt(sql, "", "") if err != nil { return nil, nil, err } @@ -1737,8 +1767,7 @@ func pathsName(paths []*candidatePath) string { return strings.Join(names, ",") } -func (s *testPlanSuite) TestSkylinePruning(c *C) { - defer testleak.AfterTest(c)() +func TestSkylinePruning(t *testing.T) { tests := []struct { sql string result string @@ -1796,27 +1825,28 @@ func (s *testPlanSuite) TestSkylinePruning(c *C) { result: "PRIMARY_KEY,c_d_e,g,f_g", }, } + s := createPlannerSuite() ctx := context.TODO() for i, tt := range tests { - comment := Commentf("case:%v sql:%s", i, tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) if err != nil { - c.Assert(err.Error(), Equals, tt.result, comment) + require.EqualError(t, err, tt.result, comment) continue } - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) lp := p.(LogicalPlan) _, err = lp.recursiveDeriveStats(nil) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) var ds *DataSource var byItems []*util.ByItems for ds == nil { @@ -1842,12 +1872,11 @@ func (s *testPlanSuite) TestSkylinePruning(c *C) { } } paths := ds.skylinePruning(byItemsToProperty(byItems)) - c.Assert(pathsName(paths), Equals, tt.result, comment) + require.Equal(t, tt.result, pathsName(paths), comment) } } -func (s *testPlanSuite) TestFastPlanContextTables(c *C) { - defer testleak.AfterTest(c)() +func TestFastPlanContextTables(t *testing.T) { tests := []struct { sql string fastPlan bool @@ -1870,28 +1899,28 @@ func (s *testPlanSuite) TestFastPlanContextTables(c *C) { false, }, } + s := createPlannerSuite() s.ctx.GetSessionVars().SnapshotInfoschema = s.is for _, tt := range tests { - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) s.ctx.GetSessionVars().StmtCtx.Tables = nil p := TryFastPlan(s.ctx, stmt) if tt.fastPlan { - c.Assert(p, NotNil) - c.Assert(len(s.ctx.GetSessionVars().StmtCtx.Tables), Equals, 1) - c.Assert(s.ctx.GetSessionVars().StmtCtx.Tables[0].Table, Equals, "t") - c.Assert(s.ctx.GetSessionVars().StmtCtx.Tables[0].DB, Equals, "test") + require.NotNil(t, p) + require.Equal(t, 1, len(s.ctx.GetSessionVars().StmtCtx.Tables)) + require.Equal(t, "t", s.ctx.GetSessionVars().StmtCtx.Tables[0].Table) + require.Equal(t, "test", s.ctx.GetSessionVars().StmtCtx.Tables[0].DB) } else { - c.Assert(p, IsNil) - c.Assert(len(s.ctx.GetSessionVars().StmtCtx.Tables), Equals, 0) + require.Nil(t, p) + require.Equal(t, 0, len(s.ctx.GetSessionVars().StmtCtx.Tables)) } } } -func (s *testPlanSuite) TestUpdateEQCond(c *C) { - defer testleak.AfterTest(c)() +func TestUpdateEQCond(t *testing.T) { tests := []struct { sql string best string @@ -1901,72 +1930,72 @@ func (s *testPlanSuite) TestUpdateEQCond(c *C) { best: "Join{DataScan(t1)->DataScan(t2)->Projection}(test.t.a,Column#25)->Projection->Projection", }, } + s := createPlannerSuite() ctx := context.TODO() for i, tt := range tests { - comment := Commentf("case:%v sql:%s", i, tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) - c.Assert(ToString(p), Equals, tt.best, comment) + require.NoError(t, err) + require.Equal(t, tt.best, ToString(p), comment) } } -func (s *testPlanSuite) TestConflictedJoinTypeHints(c *C) { - defer testleak.AfterTest(c)() +func TestConflictedJoinTypeHints(t *testing.T) { sql := "select /*+ INL_JOIN(t1) HASH_JOIN(t1) */ * from t t1, t t2 where t1.e = t2.e" + s := createPlannerSuite() ctx := context.TODO() - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) proj, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue) + require.True(t, ok) join, ok := proj.Children()[0].(*LogicalJoin) - c.Assert(ok, IsTrue) - c.Assert(join.hintInfo, IsNil) - c.Assert(join.preferJoinType, Equals, uint(0)) + require.True(t, ok) + require.Nil(t, join.hintInfo) + require.Equal(t, uint(0), join.preferJoinType) } -func (s *testPlanSuite) TestSimplyOuterJoinWithOnlyOuterExpr(c *C) { - defer testleak.AfterTest(c)() +func TestSimplyOuterJoinWithOnlyOuterExpr(t *testing.T) { + s := createPlannerSuite() sql := "select * from t t1 right join t t0 ON TRUE where CONCAT_WS(t0.e=t0.e, 0, NULL) IS NULL" ctx := context.TODO() - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) + require.NoError(t, err) sctx := MockContext() builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) p, err = logicalOptimize(ctx, builder.optFlag, p.(LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) proj, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue) + require.True(t, ok) join, ok := proj.Children()[0].(*LogicalJoin) - c.Assert(ok, IsTrue) + require.True(t, ok) // previous wrong JoinType is InnerJoin - c.Assert(join.JoinType, Equals, RightOuterJoin) + require.Equal(t, RightOuterJoin, join.JoinType) } -func (s *testPlanSuite) TestResolvingCorrelatedAggregate(c *C) { - defer testleak.AfterTest(c)() +func TestResolvingCorrelatedAggregate(t *testing.T) { tests := []struct { sql string best string @@ -1997,24 +2026,24 @@ func (s *testPlanSuite) TestResolvingCorrelatedAggregate(c *C) { }, } + s := createPlannerSuite() ctx := context.TODO() for i, tt := range tests { - comment := Commentf("case:%v sql:%s", i, tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagEliminateProjection|flagPrunColumns|flagPrunColumnsAgain, p.(LogicalPlan)) - c.Assert(err, IsNil, comment) - c.Assert(ToString(p), Equals, tt.best, comment) + require.NoError(t, err, comment) + require.Equal(t, tt.best, ToString(p), comment) } } -func (s *testPlanSuite) TestFastPathInvalidBatchPointGet(c *C) { +func TestFastPathInvalidBatchPointGet(t *testing.T) { // #22040 - defer testleak.AfterTest(c)() tt := []struct { sql string fastPlan bool @@ -2040,35 +2069,93 @@ func (s *testPlanSuite) TestFastPathInvalidBatchPointGet(c *C) { fastPlan: false, }, } + s := createPlannerSuite() for i, tc := range tt { - comment := Commentf("case:%v sql:%s", i, tc.sql) - stmt, err := s.ParseOneStmt(tc.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tc.sql) + stmt, err := s.p.ParseOneStmt(tc.sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) plan := TryFastPlan(s.ctx, stmt) if tc.fastPlan { - c.Assert(plan, NotNil) + require.NotNil(t, plan) } else { - c.Assert(plan, IsNil) + require.Nil(t, plan) } } } -func (s *testPlanSuite) TestWindowLogicalPlanAmbiguous(c *C) { +func TestTraceFastPlan(t *testing.T) { + s := createPlannerSuite() + s.ctx.GetSessionVars().StmtCtx.EnableOptimizeTrace = true + defer func() { + s.ctx.GetSessionVars().StmtCtx.EnableOptimizeTrace = false + }() + s.ctx.GetSessionVars().SnapshotInfoschema = s.is + sql := "select * from t where a=1" + comment := fmt.Sprintf("sql:%s", sql) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) + err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) + require.NoError(t, err, comment) + plan := TryFastPlan(s.ctx, stmt) + require.NotNil(t, plan) + require.NotNil(t, s.ctx.GetSessionVars().StmtCtx.OptimizeTracer) + require.NotNil(t, s.ctx.GetSessionVars().StmtCtx.OptimizeTracer.FinalPlan) + require.True(t, s.ctx.GetSessionVars().StmtCtx.OptimizeTracer.IsFastPlan) +} + +func TestWindowLogicalPlanAmbiguous(t *testing.T) { sql := "select a, max(a) over(), sum(a) over() from t" var planString string // The ambiguous logical plan which contains window function can usually be found in 100 iterations. iterations := 100 + s := createPlannerSuite() for i := 0; i < iterations; i++ { - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err) p, _, err := BuildLogicalPlanForTest(context.Background(), s.ctx, stmt, s.is) - c.Assert(err, IsNil) + require.NoError(t, err) if planString == "" { planString = ToString(p) } else { - c.Assert(planString, Equals, ToString(p)) + require.Equal(t, ToString(p), planString) } } } + +func TestRemoveOrderbyInSubquery(t *testing.T) { + tests := []struct { + sql string + best string + }{ + { + sql: "select * from t order by a", + best: "DataScan(t)->Projection->Sort", + }, + { + sql: "select (select 1) from t order by a", + best: "DataScan(t)->Projection->Sort->Projection", + }, + { + sql: "select count(*) from (select b from t order by a) n", + best: "DataScan(t)->Projection->Projection->Aggr(count(1),firstrow(test.t.b))->Projection", + }, + { + sql: "select count(1) from (select b from t order by a limit 1) n", + best: "DataScan(t)->Projection->Sort->Limit->Projection->Aggr(count(1),firstrow(test.t.b))->Projection", + }, + } + + s := createPlannerSuite() + s.ctx.GetSessionVars().RemoveOrderbyInSubquery = true + ctx := context.TODO() + for i, tt := range tests { + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := s.p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) + require.NoError(t, err, comment) + require.Equal(t, tt.best, ToString(p), comment) + } +} diff --git a/planner/core/logical_plan_trace_test.go b/planner/core/logical_plan_trace_test.go index 58348bd7712de..97e4db8ba20d7 100644 --- a/planner/core/logical_plan_trace_test.go +++ b/planner/core/logical_plan_trace_test.go @@ -16,84 +16,182 @@ package core import ( "context" + "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/testleak" + "github.com/stretchr/testify/require" ) -func (s *testPlanSuite) TestLogicalOptimizeWithTraceEnabled(c *C) { - sql := "select * from t where a in (1,2)" - defer testleak.AfterTest(c)() +func TestSingleRuleTraceStep(t *testing.T) { tt := []struct { - flags []uint64 - steps int + sql string + flags []uint64 + assertRuleName string + assertRuleSteps []assertTraceStep }{ { - flags: []uint64{ - flagEliminateAgg, - flagPushDownAgg}, - steps: 2, + sql: "select count(1) from t join (select count(1) from t where false) as tmp;", + flags: []uint64{flagPrunColumns}, + assertRuleName: "column_prune", + assertRuleSteps: []assertTraceStep{ + { + assertAction: "Aggregation_8's columns[Column#25,test.t.i_date,test.t.h,test.t.g,test.t.f,test.t.e_str,test.t.d_str,test.t.c_str,test.t.e,test.t.d,test.t.c,test.t.b,test.t.a] have been pruned", + }, + { + assertAction: "Aggregation_8's aggregation functions[firstrow(Column#25),firstrow(test.t.i_date),firstrow(test.t.h),firstrow(test.t.g),firstrow(test.t.f),firstrow(test.t.e_str),firstrow(test.t.d_str),firstrow(test.t.c_str),firstrow(test.t.e),firstrow(test.t.d),firstrow(test.t.c),firstrow(test.t.b),firstrow(test.t.a)] have been pruned", + }, + { + assertAction: "DataSource_1's columns[test.t.i_date,test.t.h,test.t.g,test.t.f,test.t.e_str,test.t.d_str,test.t.c_str,test.t.e,test.t.d,test.t.c,test.t.b,test.t.a] have been pruned", + }, + { + assertAction: "Projection_6's columns[Column#25] have been pruned", + }, + { + assertAction: "Aggregation_5's columns[test.t.i_date,test.t.h,test.t.g,test.t.f,test.t.e_str,test.t.d_str,test.t.c_str,test.t.e,test.t.d,test.t.c,test.t.b,test.t.a,Column#25] have been pruned", + }, + { + assertAction: "Aggregation_5's aggregation functions[firstrow(test.t.i_date),firstrow(test.t.h),firstrow(test.t.g),firstrow(test.t.f),firstrow(test.t.e_str),firstrow(test.t.d_str),firstrow(test.t.c_str),firstrow(test.t.e),firstrow(test.t.d),firstrow(test.t.c),firstrow(test.t.b),firstrow(test.t.a),count(1)] have been pruned", + }, + { + assertAction: "TableDual_4's columns[test.t.i_date,test.t.h,test.t.g,test.t.f,test.t.e_str,test.t.d_str,test.t.c_str,test.t.e,test.t.d,test.t.c,test.t.b,test.t.a] have been pruned", + }, + { + assertAction: "Join_7's columns[Column#28,test.t.a] have been pruned", + }, + }, }, { - flags: []uint64{ - flagEliminateAgg, - flagPushDownAgg, - flagPrunColumns, - flagBuildKeyInfo, + sql: "select a from t where b > 5;", + flags: []uint64{flagPrunColumns}, + assertRuleName: "column_prune", + assertRuleSteps: []assertTraceStep{ + { + assertReason: "", + assertAction: "DataSource_1's columns[test.t.i_date,test.t.h,test.t.g,test.t.f,test.t.e_str,test.t.d_str,test.t.c_str,test.t.e,test.t.d,test.t.c] have been pruned", + }, }, - steps: 4, }, { - flags: []uint64{}, - steps: 0, + sql: "select * from t as t1 where t1.a < (select sum(t2.a) from t as t2 where t2.b = t1.b);", + flags: []uint64{flagDecorrelate, flagBuildKeyInfo, flagPrunColumns}, + assertRuleName: "decorrelate", + assertRuleSteps: []assertTraceStep{ + { + assertAction: "MaxOneRow_7 removed from plan tree", + assertReason: "", + }, + { + assertAction: "Selection_4 removed from plan tree", + assertReason: "Selection_4's conditions have been pushed into Apply_8", + }, + { + assertAction: "Apply_8 simplified into Join_8", + assertReason: "Join_8 hasn't any corelated column, thus the inner plan is non-correlated", + }, + { + assertAction: "Aggregation_5 pulled up as Join_8's parent, and Join_8's join type becomes left outer join", + assertReason: "Aggregation_5's functions haven't any group by items and Join_8's join type isn't inner join or left outer join, and hasn't any conditions", + }, + { + assertAction: "Projection_6 is moved as Aggregation_5's parent", + assertReason: "Join_8's join type is left outer join, not semi join", + }, + }, + }, + { + sql: "select * from t as t1 join t as t2 on t1.a = t2.a where t1.a < 1;", + flags: []uint64{flagPredicatePushDown, flagBuildKeyInfo, flagPrunColumns}, + assertRuleName: "predicate_push_down", + assertRuleSteps: []assertTraceStep{ + { + assertReason: "", + assertAction: "The conditions[lt(test.t.a, 1)] are pushed down across DataSource_1", + }, + { + assertReason: "", + assertAction: "The conditions[lt(test.t.a, 1)] are pushed down across DataSource_2", + }, + { + assertAction: "Selection_4 is removed", + assertReason: "The conditions[eq(test.t.a, test.t.a)] in Selection_4 are pushed down", + }, + { + assertAction: "Selection_5 is removed", + assertReason: "The conditions[lt(test.t.a, 1)] in Selection_5 are pushed down", + }, + }, + }, + { + sql: "select * from t where a < 1;", + flags: []uint64{flagPredicatePushDown, flagBuildKeyInfo, flagPrunColumns}, + assertRuleName: "predicate_push_down", + assertRuleSteps: []assertTraceStep{ + { + assertReason: "", + assertAction: "The conditions[lt(test.t.a, 1)] are pushed down across DataSource_1", + }, + { + assertReason: "The conditions[lt(test.t.a, 1)] in Selection_2 are pushed down", + assertAction: "Selection_2 is removed", + }, + }, + }, + { + sql: "select * from t as t1 left join t as t2 on t1.a = t2.a order by t1.a limit 10;", + flags: []uint64{flagPrunColumns, flagBuildKeyInfo, flagPushDownTopN}, + assertRuleName: "topn_push_down", + assertRuleSteps: []assertTraceStep{ + { + assertAction: "Limit_6 is converted into TopN_7", + assertReason: "", + }, + { + assertAction: "Sort_5 passes ByItems[test.t.a] to TopN_7", + assertReason: "TopN_7 is Limit originally", + }, + { + assertAction: "TopN_8 is added and pushed into Join_3's left table", + assertReason: "Join_3's joinType is left outer join, and all ByItems[test.t.a] contained in left table", + }, + { + assertAction: "TopN_8 is added as DataSource_1's parent", + assertReason: "TopN is pushed down", + }, + { + assertAction: "TopN_7 is added as Join_3's parent", + assertReason: "TopN is pushed down", + }, + }, + }, + { + sql: "select * from t order by a limit 10", + flags: []uint64{flagPrunColumns, flagBuildKeyInfo, flagPushDownTopN}, + assertRuleName: "topn_push_down", + assertRuleSteps: []assertTraceStep{ + { + assertAction: "Limit_4 is converted into TopN_5", + assertReason: "", + }, + { + assertAction: "Sort_3 passes ByItems[test.t.a] to TopN_5", + assertReason: "TopN_5 is Limit originally", + }, + { + assertAction: "TopN_5 is added as DataSource_1's parent", + assertReason: "TopN is pushed down", + }, + }, }, - } - - for i, tc := range tt { - comment := Commentf("case:%v sql:%s", i, sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) - err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil, comment) - sctx := MockContext() - sctx.GetSessionVars().StmtCtx.EnableOptimizeTrace = true - builder, _ := NewPlanBuilder().Init(sctx, s.is, &hint.BlockHintProcessor{}) - domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) - ctx := context.TODO() - p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) - flag := uint64(0) - for _, f := range tc.flags { - flag = flag | f - } - p, err = logicalOptimize(ctx, flag, p.(LogicalPlan)) - c.Assert(err, IsNil) - _, ok := p.(*LogicalProjection) - c.Assert(ok, IsTrue) - otrace := sctx.GetSessionVars().StmtCtx.LogicalOptimizeTrace - c.Assert(otrace, NotNil) - c.Assert(len(otrace.Steps), Equals, tc.steps) - } -} - -func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { - defer testleak.AfterTest(c)() - tt := []struct { - sql string - flags []uint64 - assertRuleName string - assertRuleSteps []assertTraceStep - }{ { sql: "select * from pt3 where ptn > 3;", flags: []uint64{flagPartitionProcessor, flagPredicatePushDown, flagBuildKeyInfo, flagPrunColumns}, assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has multiple needed partitions[p1,p2] after pruning", - assertAction: "Datasource[1] becomes PartitionUnion[6] with children[TableScan[1],TableScan[1]]", + assertReason: "DataSource_1 has multiple needed partitions[p1,p2] after pruning", + assertAction: "DataSource_1 becomes PartitionUnion_6 with children[TableScan_1,TableScan_1]", }, }, }, @@ -103,8 +201,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has one needed partition[p1] after pruning", - assertAction: "Datasource[1] becomes TableScan[1]", + assertReason: "DataSource_1 has one needed partition[p1] after pruning", + assertAction: "DataSource_1 becomes TableScan_1", }, }, }, @@ -114,8 +212,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has multiple needed partitions[p1,p2] after pruning", - assertAction: "Datasource[1] becomes PartitionUnion[7] with children[TableScan[1],TableScan[1]]", + assertReason: "DataSource_1 has multiple needed partitions[p1,p2] after pruning", + assertAction: "DataSource_1 becomes PartitionUnion_7 with children[TableScan_1,TableScan_1]", }, }, }, @@ -125,8 +223,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has one needed partition[p2] after pruning", - assertAction: "Datasource[1] becomes TableScan[1]", + assertReason: "DataSource_1 has one needed partition[p2] after pruning", + assertAction: "DataSource_1 becomes TableScan_1", }, }, }, @@ -136,8 +234,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] doesn't have needed partition table after pruning", - assertAction: "Datasource[1] becomes TableDual[5]", + assertReason: "DataSource_1 doesn't have needed partition table after pruning", + assertAction: "DataSource_1 becomes TableDual_5", }, }, }, @@ -147,8 +245,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has multiple needed partitions[p1,p2] after pruning", - assertAction: "Datasource[1] becomes PartitionUnion[7] with children[TableScan[1],TableScan[1]]", + assertReason: "DataSource_1 has multiple needed partitions[p1,p2] after pruning", + assertAction: "DataSource_1 becomes PartitionUnion_7 with children[TableScan_1,TableScan_1]", }, }, }, @@ -158,8 +256,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "Datasource[1] has one needed partition[p1] after pruning", - assertAction: "Datasource[1] becomes TableScan[1]", + assertReason: "DataSource_1 has one needed partition[p1] after pruning", + assertAction: "DataSource_1 becomes TableScan_1", }, }, }, @@ -196,7 +294,7 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { }, { assertReason: "[test.t.a] is a unique key", - assertAction: "aggregation is simplified to a projection", + assertAction: "Aggregation_2 is simplified to a Projection_4", }, }, }, @@ -206,8 +304,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "projection_eliminate", assertRuleSteps: []assertTraceStep{ { - assertAction: "Proj[2] is eliminated, Proj[3]'s expressions changed into[plus(1, plus(1, test.t.a))]", - assertReason: "Proj[3]'s child proj[2] is redundant", + assertAction: "Projection_2 is eliminated, Projection_3's expressions changed into[plus(1, plus(1, test.t.a))]", + assertReason: "Projection_3's child Projection_2 is redundant", }, }, }, @@ -217,8 +315,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "aggregation_push_down", assertRuleSteps: []assertTraceStep{ { - assertAction: "agg[6] pushed down across join[5], and join right path becomes agg[8]", - assertReason: "agg[6]'s functions[count(Column#38)] are decomposable with join", + assertAction: "Aggregation_6 pushed down across Join_5, and Join_5 right path becomes Aggregation_8", + assertReason: "Aggregation_6's functions[count(Column#38)] are decomposable with join", }, }, }, @@ -228,16 +326,16 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "aggregation_push_down", assertRuleSteps: []assertTraceStep{ { - assertAction: "agg[8] pushed down, and union[5]'s children changed into[[id:11,tp:Aggregation],[id:12,tp:Aggregation]]", - assertReason: "agg[8] functions[sum(Column#28)] are decomposable with union", + assertAction: "Aggregation_8 pushed down, and Union_5's children changed into[Aggregation_11,Aggregation_12]", + assertReason: "Aggregation_8 functions[sum(Column#28)] are decomposable with Union_5", }, { - assertAction: "proj[6] is eliminated, and agg[11]'s functions changed into[sum(test.t.c),firstrow(test.t.d)]", - assertReason: "Proj[6] is directly below an agg[11] and has no side effects", + assertAction: "Projection_6 is eliminated, and Aggregation_11's functions changed into[sum(test.t.c),firstrow(test.t.d)]", + assertReason: "Projection_6 is directly below an Aggregation_11 and has no side effects", }, { - assertAction: "proj[7] is eliminated, and agg[12]'s functions changed into[sum(test.t.a),firstrow(test.t.b)]", - assertReason: "Proj[7] is directly below an agg[12] and has no side effects", + assertAction: "Projection_7 is eliminated, and Aggregation_12's functions changed into[sum(test.t.a),firstrow(test.t.b)]", + assertReason: "Projection_7 is directly below an Aggregation_12 and has no side effects", }, }, }, @@ -247,16 +345,16 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "max_min_eliminate", assertRuleSteps: []assertTraceStep{ { - assertAction: "add sort[8],add limit[9] during eliminating agg[4] max function", - assertReason: "agg[4] has only one function[max] without group by, the columns in agg[4] should be sorted", + assertAction: "add Sort_8,add Limit_9 during eliminating Aggregation_4 max function", + assertReason: "Aggregation_4 has only one function[max] without group by, the columns in Aggregation_4 should be sorted", }, { - assertAction: "add sort[10],add limit[11] during eliminating agg[6] min function", - assertReason: "agg[6] has only one function[min] without group by, the columns in agg[6] should be sorted", + assertAction: "add Sort_10,add Limit_11 during eliminating Aggregation_6 min function", + assertReason: "Aggregation_6 has only one function[min] without group by, the columns in Aggregation_6 should be sorted", }, { - assertAction: "agg[2] splited into aggs[4,6], and add joins[12] to connect them during eliminating agg[2] multi min/max functions", - assertReason: "each column is sorted and can benefit from index/primary key in agg[4,6] and none of them has group by clause", + assertAction: "Aggregation_2 splited into [Aggregation_4,Aggregation_6], and add [Join_12] to connect them during eliminating Aggregation_2 multi min/max functions", + assertReason: "each column is sorted and can benefit from index/primary key in [Aggregation_4,Aggregation_6] and none of them has group by clause", }, }, }, @@ -266,8 +364,8 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "max_min_eliminate", assertRuleSteps: []assertTraceStep{ { - assertAction: "add selection[4],add sort[5],add limit[6] during eliminating agg[2] max function", - assertReason: "agg[2] has only one function[max] without group by, the columns in agg[2] shouldn't be NULL and needs NULL to be filtered out, the columns in agg[2] should be sorted", + assertAction: "add Selection_4,add Sort_5,add Limit_6 during eliminating Aggregation_2 max function", + assertReason: "Aggregation_2 has only one function[max] without group by, the columns in Aggregation_2 shouldn't be NULL and needs NULL to be filtered out, the columns in Aggregation_2 should be sorted", }, }, }, @@ -277,7 +375,7 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "outer_join_eliminate", assertRuleSteps: []assertTraceStep{ { - assertAction: "Outer join[3] is eliminated and become DataSource[1]", + assertAction: "Outer Join_3 is eliminated and become DataSource_1", assertReason: "The columns[test.t.b,test.t.c] are from outer table, and the inner join keys[test.t.a] are unique", }, }, @@ -288,20 +386,21 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { assertRuleName: "outer_join_eliminate", assertRuleSteps: []assertTraceStep{ { - assertAction: "Outer join[3] is eliminated and become DataSource[1]", + assertAction: "Outer Join_3 is eliminated and become DataSource_1", assertReason: "The columns[test.t.a,test.t.b] in agg are from outer table, and the agg functions are duplicate agnostic", }, }, }, } + s := createPlannerSuite() for i, tc := range tt { sql := tc.sql - comment := Commentf("case:%v sql:%s", i, sql) - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, sql) + stmt, err := s.p.ParseOneStmt(sql, "", "") + require.NoError(t, err, comment) err = Preprocess(s.ctx, stmt, WithPreprocessorReturn(&PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) sctx := MockContext() sctx.GetSessionVars().StmtCtx.EnableOptimizeTrace = true sctx.GetSessionVars().AllowAggPushDown = true @@ -309,26 +408,26 @@ func (s *testPlanSuite) TestSingleRuleTraceStep(c *C) { domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(s.is) ctx := context.TODO() p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err, comment) flag := uint64(0) for _, f := range tc.flags { flag = flag | f } _, err = logicalOptimize(ctx, flag, p.(LogicalPlan)) - c.Assert(err, IsNil) - otrace := sctx.GetSessionVars().StmtCtx.LogicalOptimizeTrace - c.Assert(otrace, NotNil) + require.NoError(t, err, comment) + trace := sctx.GetSessionVars().StmtCtx.OptimizeTracer.Logical + require.NotNil(t, trace, comment) assert := false - for _, step := range otrace.Steps { + for _, step := range trace.Steps { if step.RuleName == tc.assertRuleName { assert = true for i, ruleStep := range step.Steps { - c.Assert(ruleStep.Action, Equals, tc.assertRuleSteps[i].assertAction) - c.Assert(ruleStep.Reason, Equals, tc.assertRuleSteps[i].assertReason) + require.Equal(t, tc.assertRuleSteps[i].assertAction, ruleStep.Action) + require.Equal(t, tc.assertRuleSteps[i].assertReason, ruleStep.Reason) } } } - c.Assert(assert, IsTrue) + require.True(t, assert) } } diff --git a/planner/core/logical_plans.go b/planner/core/logical_plans.go index 5fe0426b5c15b..38502297ba400 100644 --- a/planner/core/logical_plans.go +++ b/planner/core/logical_plans.go @@ -20,17 +20,18 @@ import ( "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/infoschema" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + fd "github.com/pingcap/tidb/planner/funcdep" "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/ranger" "go.uber.org/zap" @@ -75,12 +76,18 @@ const ( AntiLeftOuterSemiJoin ) -// IsOuterJoin returns if this joiner is a outer joiner +// IsOuterJoin returns if this joiner is an outer joiner func (tp JoinType) IsOuterJoin() bool { return tp == LeftOuterJoin || tp == RightOuterJoin || tp == LeftOuterSemiJoin || tp == AntiLeftOuterSemiJoin } +// IsSemiJoin returns if this joiner is a semi/anti-semi joiner +func (tp JoinType) IsSemiJoin() bool { + return tp == SemiJoin || tp == AntiSemiJoin || + tp == LeftOuterSemiJoin || tp == AntiLeftOuterSemiJoin +} + func (tp JoinType) String() string { switch tp { case InnerJoin: @@ -174,6 +181,78 @@ func (p *LogicalJoin) Shallow() *LogicalJoin { return join.Init(p.ctx, p.blockOffset) } +// ExtractFD implements the interface LogicalPlan. +func (p *LogicalJoin) ExtractFD() *fd.FDSet { + switch p.JoinType { + case InnerJoin: + return p.extractFDForInnerJoin(nil) + case SemiJoin: + return p.extractFDForSemiJoin(nil) + default: + return &fd.FDSet{HashCodeToUniqueID: make(map[string]int)} + } +} + +func (p *LogicalJoin) extractFDForSemiJoin(filtersFromApply []expression.Expression) *fd.FDSet { + // 1: since semi join will keep the part or all rows of the outer table, it's outer FD can be saved. + // 2: the un-projected column will be left for the upper layer projection or already be pruned from bottom up. + outerFD, _ := p.children[0].ExtractFD(), p.children[1].ExtractFD() + fds := outerFD + + eqCondSlice := expression.ScalarFuncs2Exprs(p.EqualConditions) + allConds := append(eqCondSlice, p.OtherConditions...) + allConds = append(allConds, filtersFromApply...) + notNullColsFromFilters := extractNotNullFromConds(allConds, p) + + constUniqueIDs := extractConstantCols(p.LeftConditions, p.SCtx(), fds) + + fds.MakeNotNull(notNullColsFromFilters) + fds.AddConstants(constUniqueIDs) + p.fdSet = fds + return fds +} + +func (p *LogicalJoin) extractFDForInnerJoin(filtersFromApply []expression.Expression) *fd.FDSet { + leftFD, rightFD := p.children[0].ExtractFD(), p.children[1].ExtractFD() + fds := leftFD + fds.MakeCartesianProduct(rightFD) + + eqCondSlice := expression.ScalarFuncs2Exprs(p.EqualConditions) + // some join eq conditions are stored in the OtherConditions. + allConds := append(eqCondSlice, p.OtherConditions...) + allConds = append(allConds, filtersFromApply...) + notNullColsFromFilters := extractNotNullFromConds(allConds, p) + + constUniqueIDs := extractConstantCols(allConds, p.SCtx(), fds) + + equivUniqueIDs := extractEquivalenceCols(allConds, p.SCtx(), fds) + + fds.MakeNotNull(notNullColsFromFilters) + fds.AddConstants(constUniqueIDs) + for _, equiv := range equivUniqueIDs { + fds.AddEquivalence(equiv[0], equiv[1]) + } + // merge the not-null-cols/registered-map from both side together. + fds.NotNullCols.UnionWith(rightFD.NotNullCols) + if fds.HashCodeToUniqueID == nil { + fds.HashCodeToUniqueID = rightFD.HashCodeToUniqueID + } else { + for k, v := range rightFD.HashCodeToUniqueID { + if _, ok := fds.HashCodeToUniqueID[k]; ok { + logutil.BgLogger().Warn("Error occurred while maintaining functional dependency") + continue + } + fds.HashCodeToUniqueID[k] = v + } + } + for i, ok := rightFD.GroupByCols.Next(0); ok; i, ok = rightFD.GroupByCols.Next(i + 1) { + fds.GroupByCols.Insert(i) + } + fds.HasAggBuilt = fds.HasAggBuilt || rightFD.HasAggBuilt + p.fdSet = fds + return fds +} + // GetJoinKeys extracts join keys(columns) from EqualConditions. It returns left join keys, right // join keys and an `isNullEQ` array which means the `joinKey[i]` is a `NullEQ` function. The `hasNullEQ` // means whether there is a `NullEQ` of a join key. @@ -308,6 +387,118 @@ type LogicalProjection struct { AvoidColumnEvaluator bool } +// ExtractFD implements the logical plan interface, extracting the FD from bottom up. +func (p *LogicalProjection) ExtractFD() *fd.FDSet { + // basically extract the children's fdSet. + fds := p.logicalSchemaProducer.ExtractFD() + // collect the output columns' unique ID. + outputColsUniqueIDs := fd.NewFastIntSet() + notnullColsUniqueIDs := fd.NewFastIntSet() + outputColsUniqueIDsArray := make([]int, 0, len(p.Schema().Columns)) + // here schema extended columns may contain expr, const and column allocated with uniqueID. + for _, one := range p.Schema().Columns { + outputColsUniqueIDs.Insert(int(one.UniqueID)) + outputColsUniqueIDsArray = append(outputColsUniqueIDsArray, int(one.UniqueID)) + } + // map the expr hashCode with its unique ID. + for idx, expr := range p.Exprs { + switch x := expr.(type) { + case *expression.Column: + continue + case *expression.CorrelatedColumn: + // t1(a,b,c), t2(m,n) + // select a, (select c from t2 where m=b) from t1; + // take c as constant column here. + continue + case *expression.Constant: + hashCode := string(x.HashCode(p.ctx.GetSessionVars().StmtCtx)) + var ( + ok bool + constantUniqueID int + ) + if constantUniqueID, ok = fds.IsHashCodeRegistered(hashCode); !ok { + constantUniqueID = outputColsUniqueIDsArray[idx] + fds.RegisterUniqueID(string(x.HashCode(p.ctx.GetSessionVars().StmtCtx)), constantUniqueID) + } + fds.AddConstants(fd.NewFastIntSet(constantUniqueID)) + case *expression.ScalarFunction: + // t1(a,b,c), t2(m,n) + // select a, (select c+n from t2 where m=b) from t1; + // expr(c+n) contains correlated column , but we can treat it as constant here. + hashCode := string(x.HashCode(p.ctx.GetSessionVars().StmtCtx)) + var ( + ok bool + scalarUniqueID int + ) + // If this function is not deterministic, we skip it since it not a stable value. + if expression.CheckNonDeterministic(x) { + if scalarUniqueID, ok = fds.IsHashCodeRegistered(hashCode); !ok { + fds.RegisterUniqueID(hashCode, scalarUniqueID) + } + continue + } + if scalarUniqueID, ok = fds.IsHashCodeRegistered(hashCode); !ok { + scalarUniqueID = outputColsUniqueIDsArray[idx] + fds.RegisterUniqueID(hashCode, scalarUniqueID) + } else { + // since the scalar's hash code has been registered before, the equivalence exists between the unique ID + // allocated by phase of building-projection-for-scalar and that of previous registered unique ID. + fds.AddEquivalence(fd.NewFastIntSet(scalarUniqueID), fd.NewFastIntSet(outputColsUniqueIDsArray[idx])) + } + determinants := fd.NewFastIntSet() + extractedColumns := expression.ExtractColumns(x) + extractedCorColumns := expression.ExtractCorColumns(x) + for _, one := range extractedColumns { + determinants.Insert(int(one.UniqueID)) + // the dependent columns in scalar function should be also considered as output columns as well. + outputColsUniqueIDs.Insert(int(one.UniqueID)) + } + for _, one := range extractedCorColumns { + determinants.Insert(int(one.UniqueID)) + // the dependent columns in scalar function should be also considered as output columns as well. + outputColsUniqueIDs.Insert(int(one.UniqueID)) + } + notnull := isNullRejected(p.ctx, p.schema, x) + if notnull || determinants.SubsetOf(fds.NotNullCols) { + notnullColsUniqueIDs.Insert(scalarUniqueID) + } + fds.AddStrictFunctionalDependency(determinants, fd.NewFastIntSet(scalarUniqueID)) + } + } + + // apply operator's characteristic's FD setting. + // since the distinct attribute is built as firstRow agg func, we don't need to think about it here. + // let the fds itself to trace the not null, because after the outer join, some not null column can be nullable. + fds.MakeNotNull(notnullColsUniqueIDs) + // select max(a) from t group by b, we should project both `a` & `b` to maintain the FD down here, even if select-fields only contain `a`. + fds.ProjectCols(outputColsUniqueIDs.Union(fds.GroupByCols)) + + if fds.GroupByCols.Only1Zero() { + // maxOneRow is delayed from agg's ExtractFD logic since some details listed in it. + projectionUniqueIDs := fd.NewFastIntSet() + for _, expr := range p.Exprs { + switch x := expr.(type) { + case *expression.Column: + projectionUniqueIDs.Insert(int(x.UniqueID)) + case *expression.ScalarFunction: + scalarUniqueID, ok := fds.IsHashCodeRegistered(string(hack.String(x.HashCode(p.SCtx().GetSessionVars().StmtCtx)))) + if !ok { + logutil.BgLogger().Warn("Error occurred while maintaining the functional dependency") + continue + } + projectionUniqueIDs.Insert(scalarUniqueID) + } + } + fds.MaxOneRow(projectionUniqueIDs) + } + // for select * from view (include agg), outer projection don't have to check select list with the inner group-by flag. + fds.HasAggBuilt = false + + // just trace it down in every operator for test checking. + p.fdSet = fds + return fds +} + // ExtractCorrelatedCols implements LogicalPlan interface. func (p *LogicalProjection) ExtractCorrelatedCols() []*expression.CorrelatedColumn { corCols := make([]*expression.CorrelatedColumn, 0, len(p.Exprs)) @@ -363,6 +554,129 @@ func (la *LogicalAggregation) HasOrderBy() bool { return false } +// ExtractFD implements the logical plan interface, extracting the FD from bottom up. +// 1: +// In most of the cases, using FDs to check the only_full_group_by problem should be done in the buildAggregation phase +// by extracting the bottom-up FDs graph from the `p` --- the sub plan tree that has already been built. +// +// 2: +// and this requires that some conditions push-down into the `p` like selection should be done before building aggregation, +// otherwise, 'a=1 and a can occur in the select lists of a group by' will be miss-checked because it doesn't be implied in the known FDs graph. +// +// 3: +// when a logical agg is built, it's schema columns indicates what the permitted-non-agg columns is. Therefore, we shouldn't +// depend on logicalAgg.ExtractFD() to finish the only_full_group_by checking problem rather than by 1 & 2. +func (la *LogicalAggregation) ExtractFD() *fd.FDSet { + // basically extract the children's fdSet. + fds := la.logicalSchemaProducer.ExtractFD() + // collect the output columns' unique ID. + outputColsUniqueIDs := fd.NewFastIntSet() + notnullColsUniqueIDs := fd.NewFastIntSet() + groupByColsUniqueIDs := fd.NewFastIntSet() + groupByColsOutputCols := fd.NewFastIntSet() + // Since the aggregation is build ahead of projection, the latter one will reuse the column with UniqueID allocated in aggregation + // via aggMapper, so we don't need unnecessarily maintain the mapping in the FDSet like expr did, just treating + // it as normal column. + for _, one := range la.Schema().Columns { + outputColsUniqueIDs.Insert(int(one.UniqueID)) + } + // For one like sum(a), we don't need to build functional dependency from a --> sum(a), cause it's only determined by the + // group-by-item (group-by-item --> sum(a)). + for _, expr := range la.GroupByItems { + switch x := expr.(type) { + case *expression.Column: + groupByColsUniqueIDs.Insert(int(x.UniqueID)) + case *expression.CorrelatedColumn: + // shouldn't be here, intercepted by plan builder as unknown column. + continue + case *expression.Constant: + // shouldn't be here, interpreted as pos param by plan builder. + continue + case *expression.ScalarFunction: + hashCode := string(x.HashCode(la.ctx.GetSessionVars().StmtCtx)) + var ( + ok bool + scalarUniqueID int + ) + if scalarUniqueID, ok = fds.IsHashCodeRegistered(hashCode); ok { + groupByColsUniqueIDs.Insert(scalarUniqueID) + } else { + // retrieve unique plan column id. 1: completely new one, allocating new unique id. 2: registered by projection earlier, using it. + if scalarUniqueID, ok = la.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol[hashCode]; !ok { + scalarUniqueID = int(la.ctx.GetSessionVars().AllocPlanColumnID()) + } + fds.RegisterUniqueID(hashCode, scalarUniqueID) + groupByColsUniqueIDs.Insert(scalarUniqueID) + } + determinants := fd.NewFastIntSet() + extractedColumns := expression.ExtractColumns(x) + extractedCorColumns := expression.ExtractCorColumns(x) + for _, one := range extractedColumns { + determinants.Insert(int(one.UniqueID)) + groupByColsOutputCols.Insert(int(one.UniqueID)) + } + for _, one := range extractedCorColumns { + determinants.Insert(int(one.UniqueID)) + groupByColsOutputCols.Insert(int(one.UniqueID)) + } + notnull := isNullRejected(la.ctx, la.schema, x) + if notnull || determinants.SubsetOf(fds.NotNullCols) { + notnullColsUniqueIDs.Insert(scalarUniqueID) + } + fds.AddStrictFunctionalDependency(determinants, fd.NewFastIntSet(scalarUniqueID)) + } + } + + // Some details: + // For now, select max(a) from t group by c, tidb will see `max(a)` as Max aggDes and `a,b,c` as firstRow aggDes, + // and keep them all in the schema columns before projection does the pruning. If we build the fake FD eg: {c} ~~> {b} + // here since we have seen b as firstRow aggDes, for the upper layer projection of `select max(a), b from t group by c`, + // it will take b as valid projection field of group by statement since it has existed in the FD with {c} ~~> {b}. + // + // and since any_value will NOT be pushed down to agg schema, which means every firstRow aggDes in the agg logical operator + // is meaningless to build the FD with. Let's only store the non-firstRow FD down: {group by items} ~~> {real aggDes} + realAggFuncUniqueID := fd.NewFastIntSet() + for i, aggDes := range la.AggFuncs { + if aggDes.Name != "firstrow" { + realAggFuncUniqueID.Insert(int(la.schema.Columns[i].UniqueID)) + } + } + + // apply operator's characteristic's FD setting. + if len(la.GroupByItems) == 0 { + // 1: as the details shown above, output cols (normal column seen as firstrow) of group by are not validated. + // we couldn't merge them as constant FD with origin constant FD together before projection done. + // fds.MaxOneRow(outputColsUniqueIDs.Union(groupByColsOutputCols)) + // + // 2: for the convenience of later judgement, when there is no group by items, we will store a FD: {0} -> {real aggDes} + // 0 unique id is only used for here. + groupByColsUniqueIDs.Insert(0) + for i, ok := realAggFuncUniqueID.Next(0); ok; i, ok = realAggFuncUniqueID.Next(i + 1) { + fds.AddStrictFunctionalDependency(groupByColsUniqueIDs, fd.NewFastIntSet(i)) + } + } else { + // eliminating input columns that are un-projected. + fds.ProjectCols(outputColsUniqueIDs.Union(groupByColsOutputCols).Union(groupByColsUniqueIDs)) + + // note: {a} --> {b,c} is not same with {a} --> {b} and {a} --> {c} + for i, ok := realAggFuncUniqueID.Next(0); ok; i, ok = realAggFuncUniqueID.Next(i + 1) { + // group by phrase always produce strict FD. + // 1: it can always distinguish and group the all-null/part-null group column rows. + // 2: the rows with all/part null group column are unique row after group operation. + // 3: there won't be two same group key with different agg values, so strict FD secured. + fds.AddStrictFunctionalDependency(groupByColsUniqueIDs, fd.NewFastIntSet(i)) + } + + // agg funcDes has been tag not null flag when building aggregation. + fds.MakeNotNull(notnullColsUniqueIDs) + } + fds.GroupByCols = groupByColsUniqueIDs + fds.HasAggBuilt = true + // just trace it down in every operator for test checking. + la.fdSet = fds + return fds +} + // CopyAggHints copies the aggHints from another LogicalAggregation. func (la *LogicalAggregation) CopyAggHints(agg *LogicalAggregation) { // TODO: Copy the hint may make the un-applicable hint throw the @@ -452,9 +766,155 @@ type LogicalSelection struct { // but after we converted to CNF(Conjunctive normal form), it can be // split into a list of AND conditions. Conditions []expression.Expression +} + +func extractNotNullFromConds(Conditions []expression.Expression, p LogicalPlan) fd.FastIntSet { + // extract the column NOT NULL rejection characteristic from selection condition. + // CNF considered only, DNF doesn't have its meanings (cause that condition's eval may don't take effect) + // + // Take this case: select * from t where (a = 1) and (b is null): + // + // If we wanna where phrase eval to true, two pre-condition: {a=1} and {b is null} both need to be true. + // Hence, we assert that: + // + // 1: `a` must not be null since `NULL = 1` is evaluated as NULL. + // 2: `b` must be null since only `NULL is NULL` is evaluated as true. + // + // As a result, `a` will be extracted as not-null column to abound the FDSet. + notnullColsUniqueIDs := fd.NewFastIntSet() + for _, condition := range Conditions { + var cols []*expression.Column + cols = expression.ExtractColumnsFromExpressions(cols, []expression.Expression{condition}, nil) + if isNullRejected(p.SCtx(), p.Schema(), condition) { + for _, col := range cols { + notnullColsUniqueIDs.Insert(int(col.UniqueID)) + } + } + } + return notnullColsUniqueIDs +} + +func extractConstantCols(Conditions []expression.Expression, sctx sessionctx.Context, fds *fd.FDSet) fd.FastIntSet { + // extract constant cols + // eg: where a=1 and b is null and (1+c)=5. + // TODO: Some columns can only be determined to be constant from multiple constraints (e.g. x <= 1 AND x >= 1) + var ( + constObjs []expression.Expression + constUniqueIDs = fd.NewFastIntSet() + ) + constObjs = expression.ExtractConstantEqColumnsOrScalar(sctx, constObjs, Conditions) + for _, constObj := range constObjs { + switch x := constObj.(type) { + case *expression.Column: + constUniqueIDs.Insert(int(x.UniqueID)) + case *expression.ScalarFunction: + hashCode := string(x.HashCode(sctx.GetSessionVars().StmtCtx)) + if uniqueID, ok := fds.IsHashCodeRegistered(hashCode); ok { + constUniqueIDs.Insert(uniqueID) + } else { + scalarUniqueID := int(sctx.GetSessionVars().AllocPlanColumnID()) + fds.RegisterUniqueID(string(x.HashCode(sctx.GetSessionVars().StmtCtx)), scalarUniqueID) + constUniqueIDs.Insert(scalarUniqueID) + } + } + } + return constUniqueIDs +} + +func extractEquivalenceCols(Conditions []expression.Expression, sctx sessionctx.Context, fds *fd.FDSet) [][]fd.FastIntSet { + var equivObjsPair [][]expression.Expression + equivObjsPair = expression.ExtractEquivalenceColumns(equivObjsPair, Conditions) + equivUniqueIDs := make([][]fd.FastIntSet, 0, len(equivObjsPair)) + for _, equivObjPair := range equivObjsPair { + // lhs of equivalence. + var ( + lhsUniqueID int + rhsUniqueID int + ) + switch x := equivObjPair[0].(type) { + case *expression.Column: + lhsUniqueID = int(x.UniqueID) + case *expression.ScalarFunction: + hashCode := string(x.HashCode(sctx.GetSessionVars().StmtCtx)) + if uniqueID, ok := fds.IsHashCodeRegistered(hashCode); ok { + lhsUniqueID = uniqueID + } else { + scalarUniqueID := int(sctx.GetSessionVars().AllocPlanColumnID()) + fds.RegisterUniqueID(string(x.HashCode(sctx.GetSessionVars().StmtCtx)), scalarUniqueID) + lhsUniqueID = scalarUniqueID + } + } + // rhs of equivalence. + switch x := equivObjPair[1].(type) { + case *expression.Column: + rhsUniqueID = int(x.UniqueID) + case *expression.ScalarFunction: + hashCode := string(x.HashCode(sctx.GetSessionVars().StmtCtx)) + if uniqueID, ok := fds.IsHashCodeRegistered(hashCode); ok { + rhsUniqueID = uniqueID + } else { + scalarUniqueID := int(sctx.GetSessionVars().AllocPlanColumnID()) + fds.RegisterUniqueID(string(x.HashCode(sctx.GetSessionVars().StmtCtx)), scalarUniqueID) + rhsUniqueID = scalarUniqueID + } + } + equivUniqueIDs = append(equivUniqueIDs, []fd.FastIntSet{fd.NewFastIntSet(lhsUniqueID), fd.NewFastIntSet(rhsUniqueID)}) + } + return equivUniqueIDs +} + +// ExtractFD implements the LogicalPlan interface. +func (p *LogicalSelection) ExtractFD() *fd.FDSet { + // basically extract the children's fdSet. + fds := p.baseLogicalPlan.ExtractFD() + // collect the output columns' unique ID. + outputColsUniqueIDs := fd.NewFastIntSet() + notnullColsUniqueIDs := fd.NewFastIntSet() + // eg: select t2.a, count(t2.b) from t1 join t2 using (a) where t1.a = 1 + // join's schema will miss t2.a while join.full schema has. since selection + // itself doesn't contain schema, extracting schema should tell them apart. + var columns []*expression.Column + if join, ok := p.children[0].(*LogicalJoin); ok { + columns = join.fullSchema.Columns + } else { + columns = p.Schema().Columns + } + for _, one := range columns { + outputColsUniqueIDs.Insert(int(one.UniqueID)) + } + + // extract the not null attributes from selection conditions. + notnullColsUniqueIDs.UnionWith(extractNotNullFromConds(p.Conditions, p)) + + // extract the constant cols from selection conditions. + constUniqueIDs := extractConstantCols(p.Conditions, p.SCtx(), fds) - // having selection can't be pushed down, because it must above the aggregation. - buildByHaving bool + // extract equivalence cols. + equivUniqueIDs := extractEquivalenceCols(p.Conditions, p.SCtx(), fds) + + // after left join, according to rule 3.3.3, it may create a lax FD from inner equivalence + // cols pointing to outer equivalence cols. eg: t left join t1 on t.a = t1.b, leading a + // lax FD from t1.b ~> t.a, this lax attribute is coming from supplied null value to all + // left rows, once there is a null-refusing predicate on the inner side on upper layer, this + // can be equivalence again. (the outer rows left are all coming from equal matching) + // + // why not just makeNotNull of them, because even a non-equiv-related inner col can also + // refuse supplied null values. + if fds.Rule333Equiv.InnerCols.Len() != 0 && notnullColsUniqueIDs.Intersects(fds.Rule333Equiv.InnerCols) { + // restore/re-strength FDs from rule 333 + fds.MakeRestoreRule333() + } + + // apply operator's characteristic's FD setting. + fds.MakeNotNull(notnullColsUniqueIDs) + fds.AddConstants(constUniqueIDs) + for _, equiv := range equivUniqueIDs { + fds.AddEquivalence(equiv[0], equiv[1]) + } + fds.ProjectCols(outputColsUniqueIDs) + // just trace it down in every operator for test checking. + p.fdSet = fds + return fds } // ExtractCorrelatedCols implements LogicalPlan interface. @@ -484,6 +944,40 @@ func (la *LogicalApply) ExtractCorrelatedCols() []*expression.CorrelatedColumn { return corCols } +// ExtractFD implements the LogicalPlan interface. +func (la *LogicalApply) ExtractFD() *fd.FDSet { + innerPlan := la.children[1] + // build the join correlated equal condition for apply join, this equal condition is used for deriving the transitive FD between outer and inner side. + correlatedCols := ExtractCorrelatedCols4LogicalPlan(innerPlan) + deduplicateCorrelatedCols := make(map[int64]*expression.CorrelatedColumn) + for _, cc := range correlatedCols { + if _, ok := deduplicateCorrelatedCols[cc.UniqueID]; !ok { + deduplicateCorrelatedCols[cc.UniqueID] = cc + } + } + eqCond := make([]expression.Expression, 0, 4) + // for case like select (select t1.a from t2) from t1. will be assigned with new UniqueID after sub query projection is built. + // we should distinguish them out, building the equivalence relationship from inner == outer in the apply-join for FD derivation. + for _, cc := range deduplicateCorrelatedCols { + // for every correlated column, find the connection with the inner newly built column. + for _, col := range innerPlan.Schema().Columns { + if cc.UniqueID == col.CorrelatedColUniqueID { + ccc := &cc.Column + cond := expression.NewFunctionInternal(la.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), ccc, col) + eqCond = append(eqCond, cond.(*expression.ScalarFunction)) + } + } + } + switch la.JoinType { + case InnerJoin: + return la.extractFDForInnerJoin(eqCond) + case SemiJoin: + return la.extractFDForSemiJoin(eqCond) + default: + return &fd.FDSet{HashCodeToUniqueID: make(map[string]int)} + } +} + // LogicalMaxOneRow checks if a query returns no more than one row. type LogicalMaxOneRow struct { baseLogicalPlan @@ -527,9 +1021,6 @@ type LogicalUnionScan struct { conditions []expression.Expression handleCols HandleCols - - // cacheTable not nil means it's reading from cached table. - cacheTable kv.MemBuffer } // DataSource represents a tableScan without condition push down. @@ -549,7 +1040,7 @@ type DataSource struct { // pushedDownConds are the conditions that will be pushed down to coprocessor. pushedDownConds []expression.Expression // allConds contains all the filters on this table. For now it's maintained - // in predicate push down and used only in partition pruning. + // in predicate push down and used in partition pruning/index merge. allConds []expression.Expression statisticTable *statistics.Table @@ -586,6 +1077,10 @@ type DataSource struct { // 1. use `inside insert`, `update`, `delete` or `select for update` statement // 2. isolation level is RC isForUpdateRead bool + + // contain unique index and the first field is tidb_shard(), + // such as (tidb_shard(a), a ...), the fields are more than 2 + containExprPrefixUk bool } // ExtractCorrelatedCols implements LogicalPlan interface. @@ -1045,26 +1540,17 @@ type LogicalLimit struct { limitHints limitHintInfo } -// extraPIDInfo is used by SelectLock on partitioned table, the TableReader need -// to return the partition id column. -// Because SelectLock has to used that partition id to encode the lock key. -// the child of SelectLock may be Join, so that table can be multiple extra PID columns. -// fields are for each of the table, and TblIDs are the corresponding table IDs. -type extraPIDInfo struct { - Columns []*expression.Column - TblIDs []int64 -} - // LogicalLock represents a select lock plan. type LogicalLock struct { baseLogicalPlan - Lock *ast.SelectLockInfo - tblID2Handle map[int64][]HandleCols - partitionedTable []table.PartitionedTable - // extraPIDInfo is used when it works on partition table, the child executor - // need to return an extra partition ID column in the chunk row. - extraPIDInfo + Lock *ast.SelectLockInfo + tblID2Handle map[int64][]HandleCols + + // tblID2phyTblIDCol is used for partitioned tables, + // the child executor need to return an extra column containing + // the Physical Table ID (i.e. from which partition the row came from) + tblID2PhysTblIDCol map[int64]*expression.Column } // WindowFrame represents a window function frame. @@ -1261,6 +1747,8 @@ type ShowContents struct { type LogicalShow struct { logicalSchemaProducer ShowContents + + Extractor ShowPredicateExtractor } // LogicalShowDDLJobs is for showing DDL job list. @@ -1284,19 +1772,24 @@ type CTEClass struct { // storageID for this CTE. IDForStorage int // optFlag is the optFlag for the whole CTE. - optFlag uint64 - HasLimit bool - LimitBeg uint64 - LimitEnd uint64 + optFlag uint64 + HasLimit bool + LimitBeg uint64 + LimitEnd uint64 + IsInApply bool + // pushDownPredicates may be push-downed by different references. + pushDownPredicates []expression.Expression + ColumnMap map[string]*expression.Column } // LogicalCTE is for CTE. type LogicalCTE struct { logicalSchemaProducer - cte *CTEClass - cteAsName model.CIStr - seedStat *property.StatsInfo + cte *CTEClass + cteAsName model.CIStr + seedStat *property.StatsInfo + isOuterMostCTE bool } // LogicalCTETable is for CTE table @@ -1307,7 +1800,7 @@ type LogicalCTETable struct { name string idForStorage int - // seedSchema is only used in predicateColumnCollector to get column mapping + // seedSchema is only used in columnStatsUsageCollector to get column mapping seedSchema *expression.Schema } diff --git a/planner/core/logical_plans_test.go b/planner/core/logical_plans_test.go index 69db1e9f8a839..16b5e05be28d1 100644 --- a/planner/core/logical_plans_test.go +++ b/planner/core/logical_plans_test.go @@ -16,42 +16,30 @@ package core import ( "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/util" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/testleak" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testUnitTestSuit{}) - -type testUnitTestSuit struct { - ctx sessionctx.Context -} - -func (s *testUnitTestSuit) SetUpSuite(c *C) { - s.ctx = MockContext() -} - -func (s *testUnitTestSuit) newTypeWithFlen(typeByte byte, flen int) *types.FieldType { +func newTypeWithFlen(typeByte byte, flen int) *types.FieldType { tp := types.NewFieldType(typeByte) tp.Flen = flen return tp } -func (s *testUnitTestSuit) SubstituteCol2CorCol(expr expression.Expression, colIDs map[int64]struct{}) (expression.Expression, error) { +func SubstituteCol2CorCol(expr expression.Expression, colIDs map[int64]struct{}) (expression.Expression, error) { switch x := expr.(type) { case *expression.ScalarFunction: newArgs := make([]expression.Expression, 0, len(x.GetArgs())) for _, arg := range x.GetArgs() { - newArg, err := s.SubstituteCol2CorCol(arg, colIDs) + newArg, err := SubstituteCol2CorCol(arg, colIDs) if err != nil { return nil, errors.Trace(err) } @@ -67,8 +55,8 @@ func (s *testUnitTestSuit) SubstituteCol2CorCol(expr expression.Expression, colI return expr, nil } -func (s *testUnitTestSuit) TestIndexPathSplitCorColCond(c *C) { - defer testleak.AfterTest(c)() +func TestIndexPathSplitCorColCond(t *testing.T) { + ctx := MockContext() totalSchema := expression.NewSchema() totalSchema.Append(&expression.Column{ UniqueID: 1, @@ -80,11 +68,11 @@ func (s *testUnitTestSuit) TestIndexPathSplitCorColCond(c *C) { }) totalSchema.Append(&expression.Column{ UniqueID: 3, - RetType: s.newTypeWithFlen(mysql.TypeVarchar, 10), + RetType: newTypeWithFlen(mysql.TypeVarchar, 10), }) totalSchema.Append(&expression.Column{ UniqueID: 4, - RetType: s.newTypeWithFlen(mysql.TypeVarchar, 10), + RetType: newTypeWithFlen(mysql.TypeVarchar, 10), }) totalSchema.Append(&expression.Column{ UniqueID: 5, @@ -177,11 +165,10 @@ func (s *testUnitTestSuit) TestIndexPathSplitCorColCond(c *C) { remained: "[]", }, } - collate.SetNewCollationEnabledForTest(true) for _, tt := range testCases { - comment := Commentf("failed at case:\nexpr: %v\ncorColIDs: %v\nidxColIDs: %v\nidxColLens: %v\naccess: %v\nremained: %v\n", tt.expr, tt.corColIDs, tt.idxColIDs, tt.idxColLens, tt.access, tt.remained) - filters, err := expression.ParseSimpleExprsWithNames(s.ctx, tt.expr, totalSchema, names) - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("failed at case:\nexpr: %v\ncorColIDs: %v\nidxColIDs: %v\nidxColLens: %v\naccess: %v\nremained: %v\n", tt.expr, tt.corColIDs, tt.idxColIDs, tt.idxColLens, tt.access, tt.remained) + filters, err := expression.ParseSimpleExprsWithNames(ctx, tt.expr, totalSchema, names) + require.NoError(t, err, comment) if sf, ok := filters[0].(*expression.ScalarFunction); ok && sf.FuncName.L == ast.LogicAnd { filters = expression.FlattenCNFConditions(sf) } @@ -191,8 +178,8 @@ func (s *testUnitTestSuit) TestIndexPathSplitCorColCond(c *C) { idMap[id] = struct{}{} } for _, filter := range filters { - trueFilter, err := s.SubstituteCol2CorCol(filter, idMap) - c.Assert(err, IsNil, comment) + trueFilter, err := SubstituteCol2CorCol(filter, idMap) + require.NoError(t, err, comment) trueFilters = append(trueFilters, trueFilter) } path := util.AccessPath{ @@ -202,9 +189,8 @@ func (s *testUnitTestSuit) TestIndexPathSplitCorColCond(c *C) { IdxColLens: tt.idxColLens, } - access, remained := path.SplitCorColAccessCondFromFilters(s.ctx, path.EqCondCount) - c.Assert(fmt.Sprintf("%s", access), Equals, tt.access, comment) - c.Assert(fmt.Sprintf("%s", remained), Equals, tt.remained, comment) + access, remained := path.SplitCorColAccessCondFromFilters(ctx, path.EqCondCount) + require.Equal(t, tt.access, fmt.Sprintf("%s", access), comment) + require.Equal(t, tt.remained, fmt.Sprintf("%s", remained), comment) } - collate.SetNewCollationEnabledForTest(false) } diff --git a/planner/core/main_test.go b/planner/core/main_test.go index 236d154ff8934..669de70e669e9 100644 --- a/planner/core/main_test.go +++ b/planner/core/main_test.go @@ -24,20 +24,35 @@ import ( "go.uber.org/goleak" ) -var testDataMap = make(testdata.BookKeeper, 2) +var testDataMap = make(testdata.BookKeeper) var indexMergeSuiteData testdata.TestData +var planSuiteUnexportedData testdata.TestData func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() flag.Parse() testDataMap.LoadTestSuiteData("testdata", "integration_partition_suite") testDataMap.LoadTestSuiteData("testdata", "index_merge_suite") + testDataMap.LoadTestSuiteData("testdata", "plan_normalized_suite") + testDataMap.LoadTestSuiteData("testdata", "stats_suite") + testDataMap.LoadTestSuiteData("testdata", "ordered_result_mode_suite") + testDataMap.LoadTestSuiteData("testdata", "point_get_plan") + testDataMap.LoadTestSuiteData("testdata", "enforce_mpp_suite") + testDataMap.LoadTestSuiteData("testdata", "expression_rewriter_suite") + testDataMap.LoadTestSuiteData("testdata", "partition_pruner") + testDataMap.LoadTestSuiteData("testdata", "plan_suite") + testDataMap.LoadTestSuiteData("testdata", "integration_suite") + testDataMap.LoadTestSuiteData("testdata", "analyze_suite") + testDataMap.LoadTestSuiteData("testdata", "plan_suite_unexported") + indexMergeSuiteData = testDataMap["index_merge_suite"] + planSuiteUnexportedData = testDataMap["plan_suite_unexported"] opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } @@ -52,3 +67,43 @@ func TestMain(m *testing.M) { func GetIntegrationPartitionSuiteData() testdata.TestData { return testDataMap["integration_partition_suite"] } + +func GetPlanNormalizedSuiteData() testdata.TestData { + return testDataMap["plan_normalized_suite"] +} + +func GetStatsSuiteData() testdata.TestData { + return testDataMap["stats_suite"] +} + +func GetOrderedResultModeSuiteData() testdata.TestData { + return testDataMap["ordered_result_mode_suite"] +} + +func GetPointGetPlanData() testdata.TestData { + return testDataMap["point_get_plan"] +} + +func GetEnforceMPPSuiteData() testdata.TestData { + return testDataMap["enforce_mpp_suite"] +} + +func GetExpressionRewriterSuiteData() testdata.TestData { + return testDataMap["expression_rewriter_suite"] +} + +func GetPartitionPrunerData() testdata.TestData { + return testDataMap["partition_pruner"] +} + +func GetPlanSuiteData() testdata.TestData { + return testDataMap["plan_suite"] +} + +func GetIntegrationSuiteData() testdata.TestData { + return testDataMap["integration_suite"] +} + +func GetAnalyzeSuiteData() testdata.TestData { + return testDataMap["analyze_suite"] +} diff --git a/planner/core/memtable_predicate_extractor.go b/planner/core/memtable_predicate_extractor.go index 923d025ac7d13..02359c8fa3fe6 100644 --- a/planner/core/memtable_predicate_extractor.go +++ b/planner/core/memtable_predicate_extractor.go @@ -36,10 +36,12 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/rowcodec" "github.com/pingcap/tidb/util/set" "github.com/pingcap/tidb/util/stringutil" "github.com/pingcap/tipb/go-tipb" + "go.uber.org/zap" ) // MemTablePredicateExtractor is used to extract some predicates from `WHERE` clause @@ -78,7 +80,7 @@ func (helper extractHelper) extractColInConsExpr(extractCols map[int64]*types.Fi } // All expressions in IN must be a constant // SELECT * FROM t1 WHERE c IN ('1', '2') - var results []types.Datum + results := make([]types.Datum, 0, len(args[1:])) for _, arg := range args[1:] { constant, ok := arg.(*expression.Constant) if !ok || constant.DeferredExpr != nil || constant.ParamMarker != nil { @@ -236,6 +238,8 @@ func (helper extractHelper) extractLikePatternCol( names []*types.FieldName, predicates []expression.Expression, extractColName string, + toLower bool, + needLike2Regexp bool, ) ( remained []expression.Expression, patterns []string, @@ -262,10 +266,13 @@ func (helper extractHelper) extractLikePatternCol( // We use '|' to combine DNF regular expression: .*a.*|.*b.* // e.g: // SELECT * FROM t WHERE c LIKE '%a%' OR c LIKE '%b%' - if fn.FuncName.L == ast.LogicOr { - canBuildPattern, pattern = helper.extractOrLikePattern(fn, extractColName, extractCols) + if fn.FuncName.L == ast.LogicOr && !toLower { + canBuildPattern, pattern = helper.extractOrLikePattern(fn, extractColName, extractCols, needLike2Regexp) } else { - canBuildPattern, pattern = helper.extractLikePattern(fn, extractColName, extractCols) + canBuildPattern, pattern = helper.extractLikePattern(fn, extractColName, extractCols, needLike2Regexp) + } + if canBuildPattern && toLower { + pattern = strings.ToLower(pattern) } if canBuildPattern { patterns = append(patterns, pattern) @@ -280,6 +287,7 @@ func (helper extractHelper) extractOrLikePattern( orFunc *expression.ScalarFunction, extractColName string, extractCols map[int64]*types.FieldName, + needLike2Regexp bool, ) ( ok bool, pattern string, @@ -296,7 +304,7 @@ func (helper extractHelper) extractOrLikePattern( return false, "" } - ok, partPattern := helper.extractLikePattern(fn, extractColName, extractCols) + ok, partPattern := helper.extractLikePattern(fn, extractColName, extractCols, needLike2Regexp) if !ok { return false, "" } @@ -309,6 +317,7 @@ func (helper extractHelper) extractLikePattern( fn *expression.ScalarFunction, extractColName string, extractCols map[int64]*types.FieldName, + needLike2Regexp bool, ) ( ok bool, pattern string, @@ -324,7 +333,10 @@ func (helper extractHelper) extractLikePattern( case ast.EQ: return true, "^" + regexp.QuoteMeta(datums[0].GetString()) + "$" case ast.Like: - return true, stringutil.CompileLike2Regexp(datums[0].GetString()) + if needLike2Regexp { + return true, stringutil.CompileLike2Regexp(datums[0].GetString()) + } + return true, datums[0].GetString() case ast.Regexp: return true, datums[0].GetString() default: @@ -678,7 +690,7 @@ func (e *ClusterLogTableExtractor) Extract( return nil } - remained, patterns := e.extractLikePatternCol(schema, names, remained, "message") + remained, patterns := e.extractLikePatternCol(schema, names, remained, "message", false, true) e.Patterns = patterns return remained } @@ -1415,3 +1427,183 @@ func (e *StatementsSummaryExtractor) explainInfo(p *PhysicalMemTable) string { } return fmt.Sprintf("digests: [%s]", extractStringFromStringSet(e.Digests)) } + +// TikvRegionPeersExtractor is used to extract some predicates of cluster table. +type TikvRegionPeersExtractor struct { + extractHelper + + // SkipRequest means the where clause always false, we don't need to request any component + SkipRequest bool + + // RegionIDs/StoreIDs represents all region/store ids we should filter in PD to reduce network IO. + // e.g: + // 1. SELECT * FROM tikv_region_peers WHERE region_id=1 + // 2. SELECT * FROM tikv_region_peers WHERE table_id in (11, 22) + RegionIDs []uint64 + StoreIDs []uint64 +} + +// Extract implements the MemTablePredicateExtractor Extract interface +func (e *TikvRegionPeersExtractor) Extract(_ sessionctx.Context, + schema *expression.Schema, + names []*types.FieldName, + predicates []expression.Expression, +) []expression.Expression { + // Extract the `region_id/store_id` columns. + remained, regionIDSkipRequest, regionIDs := e.extractCol(schema, names, predicates, "region_id", false) + remained, storeIDSkipRequest, storeIDs := e.extractCol(schema, names, remained, "store_id", false) + e.RegionIDs, e.StoreIDs = e.parseUint64(regionIDs), e.parseUint64(storeIDs) + + e.SkipRequest = regionIDSkipRequest || storeIDSkipRequest + if e.SkipRequest { + return nil + } + + return remained +} + +func (e *TikvRegionPeersExtractor) explainInfo(p *PhysicalMemTable) string { + if e.SkipRequest { + return "skip_request:true" + } + r := new(bytes.Buffer) + if len(e.RegionIDs) > 0 { + r.WriteString(fmt.Sprintf("region_ids:[%s], ", extractStringFromUint64Slice(e.RegionIDs))) + } + if len(e.StoreIDs) > 0 { + r.WriteString(fmt.Sprintf("store_ids:[%s], ", extractStringFromUint64Slice(e.StoreIDs))) + } + // remove the last ", " in the message info + s := r.String() + if len(s) > 2 { + return s[:len(s)-2] + } + return s +} + +// ColumnsTableExtractor is used to extract some predicates of columns table. +type ColumnsTableExtractor struct { + extractHelper + + // SkipRequest means the where clause always false, we don't need to request any component + SkipRequest bool + + TableSchema set.StringSet + + TableName set.StringSet + // ColumnName represents all column name we should filter in memtable. + ColumnName set.StringSet + + TableSchemaPatterns []string + + TableNamePatterns []string + + ColumnNamePatterns []string +} + +// Extract implements the MemTablePredicateExtractor Extract interface +func (e *ColumnsTableExtractor) Extract(_ sessionctx.Context, + schema *expression.Schema, + names []*types.FieldName, + predicates []expression.Expression, +) (remained []expression.Expression) { + remained, tableSchemaSkipRequest, tableSchema := e.extractCol(schema, names, predicates, "table_schema", true) + remained, tableNameSkipRequest, tableName := e.extractCol(schema, names, remained, "table_name", true) + remained, columnNameSkipRequest, columnName := e.extractCol(schema, names, remained, "column_name", true) + e.SkipRequest = columnNameSkipRequest || tableSchemaSkipRequest || tableNameSkipRequest + if e.SkipRequest { + return + } + remained, tableSchemaPatterns := e.extractLikePatternCol(schema, names, remained, "table_schema", true, false) + remained, tableNamePatterns := e.extractLikePatternCol(schema, names, remained, "table_name", true, false) + remained, columnNamePatterns := e.extractLikePatternCol(schema, names, remained, "column_name", true, false) + + e.ColumnName = columnName + e.TableName = tableName + e.TableSchema = tableSchema + e.TableSchemaPatterns = tableSchemaPatterns + e.TableNamePatterns = tableNamePatterns + e.ColumnNamePatterns = columnNamePatterns + return remained +} + +func (e *ColumnsTableExtractor) explainInfo(p *PhysicalMemTable) string { + if e.SkipRequest { + return "skip_request:true" + } + r := new(bytes.Buffer) + if len(e.TableSchema) > 0 { + r.WriteString(fmt.Sprintf("table_schema:[%s], ", extractStringFromStringSet(e.TableSchema))) + } + if len(e.TableName) > 0 { + r.WriteString(fmt.Sprintf("table_name:[%s], ", extractStringFromStringSet(e.TableName))) + } + if len(e.ColumnName) > 0 { + r.WriteString(fmt.Sprintf("column_name:[%s], ", extractStringFromStringSet(e.ColumnName))) + } + if len(e.TableSchemaPatterns) > 0 { + r.WriteString(fmt.Sprintf("table_schema_pattern:[%s], ", extractStringFromStringSlice(e.TableSchemaPatterns))) + } + if len(e.TableNamePatterns) > 0 { + r.WriteString(fmt.Sprintf("table_name_pattern:[%s], ", extractStringFromStringSlice(e.TableNamePatterns))) + } + if len(e.ColumnNamePatterns) > 0 { + r.WriteString(fmt.Sprintf("column_name_pattern:[%s], ", extractStringFromStringSlice(e.ColumnNamePatterns))) + } + // remove the last ", " in the message info + s := r.String() + if len(s) > 2 { + return s[:len(s)-2] + } + return s +} + +// TiKVRegionStatusExtractor is used to extract single table region scan region from predictions +type TiKVRegionStatusExtractor struct { + extractHelper + tablesID []int64 +} + +// Extract implements the MemTablePredicateExtractor Extract interface +func (e *TiKVRegionStatusExtractor) Extract(_ sessionctx.Context, + schema *expression.Schema, + names []*types.FieldName, + predicates []expression.Expression, +) (remained []expression.Expression) { + remained, _, tableIDSet := e.extractCol(schema, names, predicates, "table_id", true) + if tableIDSet.Count() < 1 { + return predicates + } + var tableID int64 + var err error + for key := range tableIDSet { + tableID, err = strconv.ParseInt(key, 10, 64) + if err != nil { + logutil.BgLogger().Error("extract table_id failed", zap.Error(err), zap.String("tableID", key)) + e.tablesID = nil + return predicates + } + e.tablesID = append(e.tablesID, tableID) + } + return remained +} + +func (e *TiKVRegionStatusExtractor) explainInfo(p *PhysicalMemTable) string { + r := new(bytes.Buffer) + if len(e.tablesID) > 0 { + r.WriteString("table_id in {") + for i, tableID := range e.tablesID { + if i > 0 { + r.WriteString(",") + } + r.WriteString(fmt.Sprintf("%v", tableID)) + } + r.WriteString("}") + } + return r.String() +} + +// GetTablesID returns TablesID +func (e *TiKVRegionStatusExtractor) GetTablesID() []int64 { + return e.tablesID +} diff --git a/planner/core/memtable_predicate_extractor_test.go b/planner/core/memtable_predicate_extractor_test.go index 311b9ae4a8838..97898259e1113 100644 --- a/planner/core/memtable_predicate_extractor_test.go +++ b/planner/core/memtable_predicate_extractor_test.go @@ -18,57 +18,31 @@ import ( "context" "regexp" "sort" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/set" + "github.com/stretchr/testify/require" ) -var _ = Suite(&extractorSuite{}) - -type extractorSuite struct { - store kv.Storage - dom *domain.Domain -} - -func (s *extractorSuite) SetUpSuite(c *C) { - store, err := mockstore.NewMockStore() - c.Assert(err, IsNil) - c.Assert(store, NotNil) - - session.SetSchemaLease(0) - session.DisableStats4Test() - dom, err := session.BootstrapSession(store) - c.Assert(err, IsNil) - c.Assert(dom, NotNil) - - s.store = store - s.dom = dom -} - -func (s *extractorSuite) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() -} - -func (s *extractorSuite) getLogicalMemTable(c *C, se session.Session, parser *parser.Parser, sql string) *plannercore.LogicalMemTable { +func getLogicalMemTable(t *testing.T, dom *domain.Domain, se session.Session, parser *parser.Parser, sql string) *plannercore.LogicalMemTable { stmt, err := parser.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) + require.NoError(t, err) ctx := context.Background() - builder, _ := plannercore.NewPlanBuilder().Init(se, s.dom.InfoSchema(), &hint.BlockHintProcessor{}) + builder, _ := plannercore.NewPlanBuilder().Init(se, dom.InfoSchema(), &hint.BlockHintProcessor{}) plan, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil) + require.NoError(t, err) logicalPlan, err := plannercore.LogicalOptimize(ctx, builder.GetOptFlag(), plan.(plannercore.LogicalPlan)) - c.Assert(err, IsNil) + require.NoError(t, err) // Obtain the leaf plan leafPlan := logicalPlan @@ -80,9 +54,12 @@ func (s *extractorSuite) getLogicalMemTable(c *C, se session.Session, parser *pa return logicalMemTable } -func (s *extractorSuite) TestClusterConfigTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestClusterConfigTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) parser := parser.New() var cases = []struct { @@ -236,25 +213,28 @@ func (s *extractorSuite) TestClusterConfigTableExtractor(c *C) { }, } for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) clusterConfigExtractor := logicalMemTable.Extractor.(*plannercore.ClusterTableExtractor) - c.Assert(clusterConfigExtractor.NodeTypes, DeepEquals, ca.nodeTypes, Commentf("SQL: %v", ca.sql)) - c.Assert(clusterConfigExtractor.Instances, DeepEquals, ca.instances, Commentf("SQL: %v", ca.sql)) - c.Assert(clusterConfigExtractor.SkipRequest, DeepEquals, ca.skipRequest, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.nodeTypes, clusterConfigExtractor.NodeTypes, "SQL: %v", ca.sql) + require.EqualValues(t, ca.instances, clusterConfigExtractor.Instances, "SQL: %v", ca.sql) + require.EqualValues(t, ca.skipRequest, clusterConfigExtractor.SkipRequest, "SQL: %v", ca.sql) } } -func timestamp(c *C, s string) int64 { - t, err := time.ParseInLocation("2006-01-02 15:04:05.999", s, time.Local) - c.Assert(err, IsNil) - return t.UnixNano() / int64(time.Millisecond) +func timestamp(t *testing.T, s string) int64 { + tt, err := time.ParseInLocation("2006-01-02 15:04:05.999", s, time.Local) + require.NoError(t, err) + return tt.UnixNano() / int64(time.Millisecond) } -func (s *extractorSuite) TestClusterLogTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestClusterLogTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) parser := parser.New() var cases = []struct { @@ -414,77 +394,77 @@ func (s *extractorSuite) TestClusterLogTableExtractor(c *C) { sql: "select * from information_schema.cluster_log where time='2019-10-10 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10' and time<='2019-10-11 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time>'2019-10-10 10:10:10' and time<'2019-10-11 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10") + 1, - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-10 10:10:10") + 1, + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10' and time<'2019-10-11 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, }, { sql: "select * from information_schema.cluster_log where time>='2019-10-12 10:10:10' and time<'2019-10-11 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-12 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-12 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, skipRequest: true, }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10' and time>='2019-10-11 10:10:10' and time>='2019-10-12 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-12 10:10:10"), + startTime: timestamp(t, "2019-10-12 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10' and time>='2019-10-11 10:10:10' and time>='2019-10-12 10:10:10' and time='2019-10-13 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-13 10:10:10"), - endTime: timestamp(c, "2019-10-13 10:10:10"), + startTime: timestamp(t, "2019-10-13 10:10:10"), + endTime: timestamp(t, "2019-10-13 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time<='2019-10-10 10:10:10' and time='2019-10-13 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-13 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-13 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), skipRequest: true, }, { sql: "select * from information_schema.cluster_log where time='2019-10-10 10:10:10' and time<='2019-10-13 10:10:10'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), }, { sql: "select * from information_schema.cluster_log where time>='2019-10-10 10:10:10' and message like '%a%'", nodeTypes: set.NewStringSet(), instances: set.NewStringSet(), - startTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), patterns: []string{".*a.*"}, }, { @@ -531,34 +511,37 @@ func (s *extractorSuite) TestClusterLogTableExtractor(c *C) { }, } for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) clusterConfigExtractor := logicalMemTable.Extractor.(*plannercore.ClusterLogTableExtractor) - c.Assert(clusterConfigExtractor.NodeTypes, DeepEquals, ca.nodeTypes, Commentf("SQL: %v", ca.sql)) - c.Assert(clusterConfigExtractor.Instances, DeepEquals, ca.instances, Commentf("SQL: %v", ca.sql)) - c.Assert(clusterConfigExtractor.SkipRequest, DeepEquals, ca.skipRequest, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.nodeTypes, clusterConfigExtractor.NodeTypes, "SQL: %v", ca.sql) + require.EqualValues(t, ca.instances, clusterConfigExtractor.Instances, "SQL: %v", ca.sql) + require.EqualValues(t, ca.skipRequest, clusterConfigExtractor.SkipRequest, "SQL: %v", ca.sql) if ca.startTime > 0 { - c.Assert(clusterConfigExtractor.StartTime, Equals, ca.startTime, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.startTime, clusterConfigExtractor.StartTime, "SQL: %v", ca.sql) } if ca.endTime > 0 { - c.Assert(clusterConfigExtractor.EndTime, Equals, ca.endTime, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.endTime, clusterConfigExtractor.EndTime, "SQL: %v", ca.sql) } - c.Assert(clusterConfigExtractor.Patterns, DeepEquals, ca.patterns, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.patterns, clusterConfigExtractor.Patterns, "SQL: %v", ca.sql) if len(ca.level) > 0 { - c.Assert(clusterConfigExtractor.LogLevels, DeepEquals, ca.level, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.level, clusterConfigExtractor.LogLevels, "SQL: %v", ca.sql) } } } -func (s *extractorSuite) TestMetricTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestMetricTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) - parseTime := func(c *C, s string) time.Time { - t, err := time.ParseInLocation(plannercore.MetricTableTimeFormat, s, time.Local) - c.Assert(err, IsNil) - return t + parseTime := func(t *testing.T, s string) time.Time { + tt, err := time.ParseInLocation(plannercore.MetricTableTimeFormat, s, time.Local) + require.NoError(t, err) + return tt } parser := parser.New() @@ -607,33 +590,33 @@ func (s *extractorSuite) TestMetricTableExtractor(c *C) { "instance": set.NewStringSet("127.0.0.1:10080"), "sql_type": set.NewStringSet("Update"), }, - startTime: parseTime(c, "2019-10-10 10:10:10"), - endTime: parseTime(c, "2019-10-10 10:10:10"), + startTime: parseTime(t, "2019-10-10 10:10:10"), + endTime: parseTime(t, "2019-10-10 10:10:10"), }, { sql: "select * from metrics_schema.tidb_query_duration where time>'2019-10-10 10:10:10' and time<'2019-10-11 10:10:10'", promQL: `histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance))`, - startTime: parseTime(c, "2019-10-10 10:10:10.001"), - endTime: parseTime(c, "2019-10-11 10:10:09.999"), + startTime: parseTime(t, "2019-10-10 10:10:10.001"), + endTime: parseTime(t, "2019-10-11 10:10:09.999"), }, { sql: "select * from metrics_schema.tidb_query_duration where time>='2019-10-10 10:10:10'", promQL: `histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance))`, - startTime: parseTime(c, "2019-10-10 10:10:10"), - endTime: parseTime(c, "2019-10-10 10:20:10"), + startTime: parseTime(t, "2019-10-10 10:10:10"), + endTime: parseTime(t, "2019-10-10 10:20:10"), }, { sql: "select * from metrics_schema.tidb_query_duration where time>='2019-10-10 10:10:10' and time<='2019-10-09 10:10:10'", promQL: "", - startTime: parseTime(c, "2019-10-10 10:10:10"), - endTime: parseTime(c, "2019-10-09 10:10:10"), + startTime: parseTime(t, "2019-10-10 10:10:10"), + endTime: parseTime(t, "2019-10-09 10:10:10"), skipRequest: true, }, { sql: "select * from metrics_schema.tidb_query_duration where time<='2019-10-09 10:10:10'", promQL: "histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance))", - startTime: parseTime(c, "2019-10-09 10:00:10"), - endTime: parseTime(c, "2019-10-09 10:10:10"), + startTime: parseTime(t, "2019-10-09 10:00:10"), + endTime: parseTime(t, "2019-10-09 10:10:10"), }, { sql: "select * from metrics_schema.tidb_query_duration where quantile=0.9 or quantile=0.8", @@ -649,34 +632,37 @@ func (s *extractorSuite) TestMetricTableExtractor(c *C) { } se.GetSessionVars().StmtCtx.TimeZone = time.Local for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) metricTableExtractor := logicalMemTable.Extractor.(*plannercore.MetricTableExtractor) if len(ca.labelConditions) > 0 { - c.Assert(metricTableExtractor.LabelConditions, DeepEquals, ca.labelConditions, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.labelConditions, metricTableExtractor.LabelConditions, "SQL: %v", ca.sql) } - c.Assert(metricTableExtractor.SkipRequest, DeepEquals, ca.skipRequest, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.skipRequest, metricTableExtractor.SkipRequest, "SQL: %v", ca.sql) if len(metricTableExtractor.Quantiles) > 0 { - c.Assert(metricTableExtractor.Quantiles, DeepEquals, ca.quantiles) + require.EqualValues(t, ca.quantiles, metricTableExtractor.Quantiles) } if !ca.skipRequest { promQL := metricTableExtractor.GetMetricTablePromQL(se, "tidb_query_duration") - c.Assert(promQL, DeepEquals, ca.promQL, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, promQL, ca.promQL, "SQL: %v", ca.sql) start, end := metricTableExtractor.StartTime, metricTableExtractor.EndTime - c.Assert(start.UnixNano() <= end.UnixNano(), IsTrue) + require.GreaterOrEqual(t, end.UnixNano(), start.UnixNano()) if ca.startTime.Unix() > 0 { - c.Assert(metricTableExtractor.StartTime, DeepEquals, ca.startTime, Commentf("SQL: %v, start_time: %v", ca.sql, metricTableExtractor.StartTime)) + require.EqualValues(t, ca.startTime, metricTableExtractor.StartTime, "SQL: %v, start_time: %v", ca.sql, metricTableExtractor.StartTime) } if ca.endTime.Unix() > 0 { - c.Assert(metricTableExtractor.EndTime, DeepEquals, ca.endTime, Commentf("SQL: %v, end_time: %v", ca.sql, metricTableExtractor.EndTime)) + require.EqualValues(t, ca.endTime, metricTableExtractor.EndTime, "SQL: %v, end_time: %v", ca.sql, metricTableExtractor.EndTime) } } } } -func (s *extractorSuite) TestMetricsSummaryTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestMetricsSummaryTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) var cases = []struct { sql string @@ -758,23 +744,26 @@ func (s *extractorSuite) TestMetricsSummaryTableExtractor(c *C) { for _, ca := range cases { sort.Float64s(ca.quantiles) - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) extractor := logicalMemTable.Extractor.(*plannercore.MetricSummaryTableExtractor) if len(ca.quantiles) > 0 { - c.Assert(extractor.Quantiles, DeepEquals, ca.quantiles, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.quantiles, extractor.Quantiles, "SQL: %v", ca.sql) } if len(ca.names) > 0 { - c.Assert(extractor.MetricsNames, DeepEquals, ca.names, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.names, extractor.MetricsNames, "SQL: %v", ca.sql) } - c.Assert(extractor.SkipRequest, Equals, ca.skipRequest, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.skipRequest, extractor.SkipRequest, "SQL: %v", ca.sql) } } -func (s *extractorSuite) TestInspectionResultTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestInspectionResultTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) var cases = []struct { sql string @@ -897,23 +886,26 @@ func (s *extractorSuite) TestInspectionResultTableExtractor(c *C) { } parser := parser.New() for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) clusterConfigExtractor := logicalMemTable.Extractor.(*plannercore.InspectionResultTableExtractor) if len(ca.rules) > 0 { - c.Assert(clusterConfigExtractor.Rules, DeepEquals, ca.rules, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.rules, clusterConfigExtractor.Rules, "SQL: %v", ca.sql) } if len(ca.items) > 0 { - c.Assert(clusterConfigExtractor.Items, DeepEquals, ca.items, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.items, clusterConfigExtractor.Items, "SQL: %v", ca.sql) } - c.Assert(clusterConfigExtractor.SkipInspection, Equals, ca.skipInspection, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.skipInspection, clusterConfigExtractor.SkipInspection, "SQL: %v", ca.sql) } } -func (s *extractorSuite) TestInspectionSummaryTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestInspectionSummaryTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) var cases = []struct { sql string @@ -996,23 +988,26 @@ func (s *extractorSuite) TestInspectionSummaryTableExtractor(c *C) { } parser := parser.New() for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) clusterConfigExtractor := logicalMemTable.Extractor.(*plannercore.InspectionSummaryTableExtractor) if len(ca.rules) > 0 { - c.Assert(clusterConfigExtractor.Rules, DeepEquals, ca.rules, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.rules, clusterConfigExtractor.Rules, "SQL: %v", ca.sql) } if len(ca.names) > 0 { - c.Assert(clusterConfigExtractor.MetricNames, DeepEquals, ca.names, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.names, clusterConfigExtractor.MetricNames, "SQL: %v", ca.sql) } - c.Assert(clusterConfigExtractor.SkipInspection, Equals, ca.skipInspection, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.skipInspection, clusterConfigExtractor.SkipInspection, "SQL: %v", ca.sql) } } -func (s *extractorSuite) TestInspectionRuleTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestInspectionRuleTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) var cases = []struct { sql string @@ -1037,20 +1032,23 @@ func (s *extractorSuite) TestInspectionRuleTableExtractor(c *C) { } parser := parser.New() for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) clusterConfigExtractor := logicalMemTable.Extractor.(*plannercore.InspectionRuleTableExtractor) if len(ca.tps) > 0 { - c.Assert(clusterConfigExtractor.Types, DeepEquals, ca.tps, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.tps, clusterConfigExtractor.Types, "SQL: %v", ca.sql) } - c.Assert(clusterConfigExtractor.SkipRequest, Equals, ca.skip, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.skip, clusterConfigExtractor.SkipRequest, "SQL: %v", ca.sql) } } -func (s *extractorSuite) TestTiDBHotRegionsHistoryTableExtractor(c *C) { - se, err := session.CreateSession4Test(s.store) - c.Assert(err, IsNil) +func TestTiDBHotRegionsHistoryTableExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) se.GetSessionVars().StmtCtx.TimeZone = time.Local var cases = []struct { @@ -1072,40 +1070,40 @@ func (s *extractorSuite) TestTiDBHotRegionsHistoryTableExtractor(c *C) { }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time='2019-10-10 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-10 10:10:10' and update_time<='2019-10-11 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>'2019-10-10 10:10:10' and update_time<'2019-10-11 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10") + 1, - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-10 10:10:10") + 1, + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-10 10:10:10' and update_time<'2019-10-11 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-12 10:10:10' and update_time<'2019-10-11 10:10:10'", - startTime: timestamp(c, "2019-10-12 10:10:10"), - endTime: timestamp(c, "2019-10-11 10:10:10") - 1, + startTime: timestamp(t, "2019-10-12 10:10:10"), + endTime: timestamp(t, "2019-10-11 10:10:10") - 1, isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), @@ -1113,30 +1111,30 @@ func (s *extractorSuite) TestTiDBHotRegionsHistoryTableExtractor(c *C) { }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-10 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-10 10:10:10' and update_time>='2019-10-11 10:10:10' and update_time>='2019-10-12 10:10:10'", - startTime: timestamp(c, "2019-10-12 10:10:10"), + startTime: timestamp(t, "2019-10-12 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time>='2019-10-10 10:10:10' and update_time>='2019-10-11 10:10:10' and update_time>='2019-10-12 10:10:10' and update_time='2019-10-13 10:10:10'", - startTime: timestamp(c, "2019-10-13 10:10:10"), - endTime: timestamp(c, "2019-10-13 10:10:10"), + startTime: timestamp(t, "2019-10-13 10:10:10"), + endTime: timestamp(t, "2019-10-13 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time<='2019-10-10 10:10:10' and update_time='2019-10-13 10:10:10'", - startTime: timestamp(c, "2019-10-13 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-13 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), @@ -1144,8 +1142,8 @@ func (s *extractorSuite) TestTiDBHotRegionsHistoryTableExtractor(c *C) { }, { sql: "select * from information_schema.tidb_hot_regions_history where update_time='2019-10-10 10:10:10' and update_time<='2019-10-13 10:10:10'", - startTime: timestamp(c, "2019-10-10 10:10:10"), - endTime: timestamp(c, "2019-10-10 10:10:10"), + startTime: timestamp(t, "2019-10-10 10:10:10"), + endTime: timestamp(t, "2019-10-10 10:10:10"), isLearners: []bool{false, true}, isLeaders: []bool{false, true}, hotRegionTypes: set.NewStringSet(plannercore.HotRegionTypeRead, plannercore.HotRegionTypeWrite), @@ -1389,34 +1387,358 @@ func (s *extractorSuite) TestTiDBHotRegionsHistoryTableExtractor(c *C) { parser := parser.New() for _, ca := range cases { - logicalMemTable := s.getLogicalMemTable(c, se, parser, ca.sql) - c.Assert(logicalMemTable.Extractor, NotNil, Commentf("SQL: %v", ca.sql)) + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor, "SQL: %v", ca.sql) hotRegionsHistoryExtractor := logicalMemTable.Extractor.(*plannercore.HotRegionsHistoryTableExtractor) if ca.startTime > 0 { - c.Assert(hotRegionsHistoryExtractor.StartTime, Equals, ca.startTime, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.startTime, hotRegionsHistoryExtractor.StartTime, "SQL: %v", ca.sql) } if ca.endTime > 0 { - c.Assert(hotRegionsHistoryExtractor.EndTime, Equals, ca.endTime, Commentf("SQL: %v", ca.sql)) + require.Equal(t, ca.endTime, hotRegionsHistoryExtractor.EndTime, "SQL: %v", ca.sql) } - c.Assert(hotRegionsHistoryExtractor.SkipRequest, DeepEquals, ca.skipRequest, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.skipRequest, hotRegionsHistoryExtractor.SkipRequest, "SQL: %v", ca.sql) if len(ca.isLearners) > 0 { - c.Assert(hotRegionsHistoryExtractor.IsLearners, DeepEquals, ca.isLearners, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.isLearners, hotRegionsHistoryExtractor.IsLearners, "SQL: %v", ca.sql) } if len(ca.isLeaders) > 0 { - c.Assert(hotRegionsHistoryExtractor.IsLeaders, DeepEquals, ca.isLeaders, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.isLeaders, hotRegionsHistoryExtractor.IsLeaders, "SQL: %v", ca.sql) } if ca.hotRegionTypes.Count() > 0 { - c.Assert(hotRegionsHistoryExtractor.HotRegionTypes, DeepEquals, ca.hotRegionTypes, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.hotRegionTypes, hotRegionsHistoryExtractor.HotRegionTypes, "SQL: %v", ca.sql) } if len(ca.regionIDs) > 0 { - c.Assert(hotRegionsHistoryExtractor.RegionIDs, DeepEquals, ca.regionIDs, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.regionIDs, hotRegionsHistoryExtractor.RegionIDs, "SQL: %v", ca.sql) } if len(ca.storeIDs) > 0 { - c.Assert(hotRegionsHistoryExtractor.StoreIDs, DeepEquals, ca.storeIDs, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.storeIDs, hotRegionsHistoryExtractor.StoreIDs, "SQL: %v", ca.sql) } if len(ca.peerIDs) > 0 { - c.Assert(hotRegionsHistoryExtractor.PeerIDs, DeepEquals, ca.peerIDs, Commentf("SQL: %v", ca.sql)) + require.EqualValues(t, ca.peerIDs, hotRegionsHistoryExtractor.PeerIDs, "SQL: %v", ca.sql) } } } + +func TestTikvRegionPeersExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + + var cases = []struct { + sql string + regionIDs, storeIDs []uint64 + skipRequest bool + }{ + // Test `region_id`, `store_id` columns. + { + sql: "select * from information_schema.tikv_region_peers where region_id=100", + regionIDs: []uint64{100}, + }, + { + sql: "select * from information_schema.tikv_region_peers where 100=region_id", + regionIDs: []uint64{100}, + }, + { + sql: "select * from information_schema.tikv_region_peers where 100=region_id or region_id=101", + regionIDs: []uint64{100, 101}, + }, + { + sql: "select * from information_schema.tikv_region_peers where 100=region_id or region_id=101 or region_id=102 or 103 = region_id", + regionIDs: []uint64{100, 101, 102, 103}, + }, + { + sql: "select * from information_schema.tikv_region_peers where (region_id=100 or region_id=101) and (store_id=200 or store_id=201)", + regionIDs: []uint64{100, 101}, + storeIDs: []uint64{200, 201}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id in (100, 101)", + regionIDs: []uint64{100, 101}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id in (100, 101) and store_id=200", + regionIDs: []uint64{100, 101}, + storeIDs: []uint64{200}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id in (100, 101) and store_id in (200, 201)", + regionIDs: []uint64{100, 101}, + storeIDs: []uint64{200, 201}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and store_id in (200, 201)", + regionIDs: []uint64{100}, + storeIDs: []uint64{200, 201}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and store_id=200", + regionIDs: []uint64{100}, + storeIDs: []uint64{200}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id=101", + skipRequest: true, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id in (100,101)", + regionIDs: []uint64{100}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id in (100,101) and store_id=200 and store_id in (200,201)", + regionIDs: []uint64{100}, + storeIDs: []uint64{200}, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id in (101,102)", + skipRequest: true, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id in (101,102) and store_id=200 and store_id in (200,201)", + skipRequest: true, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id=100 and region_id in (100,101) and store_id=200 and store_id in (201,202)", + skipRequest: true, + }, + { + sql: `select * from information_schema.tikv_region_peers + where region_id=100 and region_id in (100,101) + and store_id=200 and store_id in (201,202)`, + skipRequest: true, + }, + { + sql: "select * from information_schema.tikv_region_peers where region_id in (100,101) and region_id in (101,102)", + regionIDs: []uint64{101}, + }, + { + sql: `select * from information_schema.tikv_region_peers + where region_id in (100,101) + and region_id in (101,102) + and store_id in (200,201) + and store_id in (201,202)`, + regionIDs: []uint64{101}, + storeIDs: []uint64{201}, + }, + { + sql: `select * from information_schema.tikv_region_peers + where region_id in (100,101) + and region_id in (100,102) + and region_id in (102,103) + and region_id in (103,104)`, + skipRequest: true, + }, + // Test columns that is not extracted by TikvRegionPeersExtractor + { + sql: `select * from information_schema.tikv_region_peers + where peer_id=100 + and is_learner=0 + and is_leader=1 + and status='NORMAL' + and down_seconds=1000`, + }, + } + parser := parser.New() + for _, ca := range cases { + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) + + tikvRegionPeersExtractor := logicalMemTable.Extractor.(*plannercore.TikvRegionPeersExtractor) + if len(ca.regionIDs) > 0 { + require.EqualValues(t, ca.regionIDs, tikvRegionPeersExtractor.RegionIDs, "SQL: %v", ca.sql) + } + if len(ca.storeIDs) > 0 { + require.EqualValues(t, ca.storeIDs, tikvRegionPeersExtractor.StoreIDs, "SQL: %v", ca.sql) + } + } +} + +func TestColumns(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + + var cases = []struct { + sql string + columnName set.StringSet + tableSchema set.StringSet + tableName set.StringSet + columnNamePattern []string + tableSchemaPattern []string + tableNamePattern []string + skipRequest bool + }{ + { + sql: `select * from INFORMATION_SCHEMA.COLUMNS where column_name='T';`, + columnName: set.NewStringSet("t"), + }, + { + sql: `select * from INFORMATION_SCHEMA.COLUMNS where table_schema='TEST';`, + tableSchema: set.NewStringSet("test"), + }, + { + sql: `select * from INFORMATION_SCHEMA.COLUMNS where table_name='TEST';`, + tableName: set.NewStringSet("test"), + }, + { + sql: "select * from information_schema.COLUMNS where table_name in ('TEST','t') and column_name in ('A','b')", + columnName: set.NewStringSet("a", "b"), + tableName: set.NewStringSet("test", "t"), + }, + { + sql: `select * from information_schema.COLUMNS where table_name='a' and table_name in ('a', 'B');`, + tableName: set.NewStringSet("a"), + }, + { + sql: `select * from information_schema.COLUMNS where table_name='a' and table_name='B';`, + skipRequest: true, + }, + { + sql: `select * from information_schema.COLUMNS where table_name like 'T%';`, + tableNamePattern: []string{"t%"}, + }, + { + sql: `select * from information_schema.COLUMNS where column_name like 'T%';`, + columnNamePattern: []string{"t%"}, + }, + { + sql: `select * from information_schema.COLUMNS where column_name like 'i%';`, + columnNamePattern: []string{"i%"}, + }, + { + sql: `select * from information_schema.COLUMNS where column_name like 'abc%' or column_name like "def%";`, + columnNamePattern: []string{}, + }, + { + sql: `select * from information_schema.COLUMNS where column_name like 'abc%' and column_name like "%def";`, + columnNamePattern: []string{"abc%", "%def"}, + }, + } + parser := parser.New() + for _, ca := range cases { + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) + + columnsTableExtractor := logicalMemTable.Extractor.(*plannercore.ColumnsTableExtractor) + require.Equal(t, ca.skipRequest, columnsTableExtractor.SkipRequest, "SQL: %v", ca.sql) + + require.Equal(t, ca.columnName.Count(), columnsTableExtractor.ColumnName.Count()) + if ca.columnName.Count() > 0 && columnsTableExtractor.ColumnName.Count() > 0 { + require.EqualValues(t, ca.columnName, columnsTableExtractor.ColumnName, "SQL: %v", ca.sql) + } + + require.Equal(t, ca.tableSchema.Count(), columnsTableExtractor.TableSchema.Count()) + if ca.tableSchema.Count() > 0 && columnsTableExtractor.TableSchema.Count() > 0 { + require.EqualValues(t, ca.tableSchema, columnsTableExtractor.TableSchema, "SQL: %v", ca.sql) + } + require.Equal(t, ca.tableName.Count(), columnsTableExtractor.TableName.Count()) + if ca.tableName.Count() > 0 && columnsTableExtractor.TableName.Count() > 0 { + require.EqualValues(t, ca.tableName, columnsTableExtractor.TableName, "SQL: %v", ca.sql) + } + require.Equal(t, len(ca.tableNamePattern), len(columnsTableExtractor.TableNamePatterns)) + if len(ca.tableNamePattern) > 0 && len(columnsTableExtractor.TableNamePatterns) > 0 { + require.EqualValues(t, ca.tableNamePattern, columnsTableExtractor.TableNamePatterns, "SQL: %v", ca.sql) + } + require.Equal(t, len(ca.columnNamePattern), len(columnsTableExtractor.ColumnNamePatterns)) + if len(ca.columnNamePattern) > 0 && len(columnsTableExtractor.ColumnNamePatterns) > 0 { + require.EqualValues(t, ca.columnNamePattern, columnsTableExtractor.ColumnNamePatterns, "SQL: %v", ca.sql) + } + require.Equal(t, len(ca.tableSchemaPattern), len(columnsTableExtractor.TableSchemaPatterns)) + if len(ca.tableSchemaPattern) > 0 && len(columnsTableExtractor.TableSchemaPatterns) > 0 { + require.EqualValues(t, ca.tableSchemaPattern, columnsTableExtractor.TableSchemaPatterns, "SQL: %v", ca.sql) + } + } +} + +func TestPredicateQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int, abctime int,DATETIME_PRECISION int);") + tk.MustExec("create table abclmn(a int);") + tk.MustQuery("select TABLE_NAME from information_schema.columns where table_schema = 'test' and column_name like 'i%'").Check(testkit.Rows("t")) + tk.MustQuery("select TABLE_NAME from information_schema.columns where table_schema = 'TEST' and column_name like 'I%'").Check(testkit.Rows("t")) + tk.MustQuery("select TABLE_NAME from information_schema.columns where table_schema = 'TEST' and column_name like 'ID'").Check(testkit.Rows("t")) + tk.MustQuery("select TABLE_NAME from information_schema.columns where table_schema = 'TEST' and column_name like 'id'").Check(testkit.Rows("t")) + tk.MustQuery("select column_name from information_schema.columns where table_schema = 'TEST' and (column_name like 'i%' or column_name like '%d')").Check(testkit.Rows("id")) + tk.MustQuery("select column_name from information_schema.columns where table_schema = 'TEST' and (column_name like 'abc%' and column_name like '%time')").Check(testkit.Rows("abctime")) + result := tk.MustQuery("select TABLE_NAME, column_name from information_schema.columns where table_schema = 'TEST' and column_name like '%time';") + require.Len(t, result.Rows(), 1) + tk.MustQuery("describe t").Check(testkit.Rows("id int(11) YES ", "abctime int(11) YES ", "DATETIME_PRECISION int(11) YES ")) + tk.MustQuery("describe t id").Check(testkit.Rows("id int(11) YES ")) + tk.MustQuery("describe t ID").Check(testkit.Rows("id int(11) YES ")) + tk.MustGetErrCode("describe t 'I%'", errno.ErrParse) + tk.MustGetErrCode("describe t I%", errno.ErrParse) + + tk.MustQuery("show columns from t like 'abctime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t like 'ABCTIME'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t like 'abc%'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t like 'ABC%'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t like '%ime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t like '%IME'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns in t like '%ime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns in t like '%IME'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show fields in t like '%ime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show fields in t like '%IME'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + + tk.MustQuery("show columns from t where field like '%time'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns from t where field = 'abctime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show columns in t where field = 'abctime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show fields from t where field = 'abctime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("show fields in t where field = 'abctime'").Check(testkit.RowsWithSep(",", "abctime,int(11),YES,,,")) + tk.MustQuery("explain t").Check(testkit.Rows("id int(11) YES ", "abctime int(11) YES ", "DATETIME_PRECISION int(11) YES ")) + + tk.MustGetErrCode("show columns from t like id", errno.ErrBadField) + tk.MustGetErrCode("show columns from t like `id`", errno.ErrBadField) + + tk.MustQuery("show tables like 't'").Check(testkit.Rows("t")) + tk.MustQuery("show tables like 'T'").Check(testkit.Rows("t")) + tk.MustQuery("show tables like 'ABCLMN'").Check(testkit.Rows("abclmn")) + tk.MustQuery("show tables like 'ABC%'").Check(testkit.Rows("abclmn")) + tk.MustQuery("show tables like '%lmn'").Check(testkit.Rows("abclmn")) + tk.MustQuery("show full tables like '%lmn'").Check(testkit.Rows("abclmn BASE TABLE")) + tk.MustGetErrCode("show tables like T", errno.ErrBadField) + tk.MustGetErrCode("show tables like `T`", errno.ErrBadField) +} + +func TestTikvRegionStatusExtractor(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + + var cases = []struct { + sql string + tableIDs []int64 + }{ + { + sql: "select * from information_schema.TIKV_REGION_STATUS where table_id = 1", + tableIDs: []int64{1}, + }, + { + sql: "select * from information_schema.TIKV_REGION_STATUS where table_id = 1 or table_id = 2", + tableIDs: []int64{1, 2}, + }, + { + sql: "select * from information_schema.TIKV_REGION_STATUS where table_id in (1,2,3)", + tableIDs: []int64{1, 2, 3}, + }, + } + parser := parser.New() + for _, ca := range cases { + logicalMemTable := getLogicalMemTable(t, dom, se, parser, ca.sql) + require.NotNil(t, logicalMemTable.Extractor) + rse := logicalMemTable.Extractor.(*plannercore.TiKVRegionStatusExtractor) + tableids := rse.GetTablesID() + sort.Slice(tableids, func(i, j int) bool { + return tableids[i] < tableids[j] + }) + require.Equal(t, ca.tableIDs, tableids) + } +} diff --git a/planner/core/optimizer.go b/planner/core/optimizer.go index 89b156e632cea..2bec5a5c1298c 100644 --- a/planner/core/optimizer.go +++ b/planner/core/optimizer.go @@ -17,6 +17,7 @@ package core import ( "context" "math" + "sort" "github.com/pingcap/errors" "github.com/pingcap/tidb/config" @@ -44,9 +45,6 @@ import ( // OptimizeAstNode optimizes the query to a physical plan directly. var OptimizeAstNode func(ctx context.Context, sctx sessionctx.Context, node ast.Node, is infoschema.InfoSchema) (Plan, types.NameSlice, error) -// GetBindSQL4PlanCache get the bindSQL for the ast.StmtNode -var GetBindSQL4PlanCache func(sctx sessionctx.Context, stmtNode ast.StmtNode) (bindSQL string) - // AllowCartesianProduct means whether tidb allows cartesian join without equal conditions. var AllowCartesianProduct = atomic.NewBool(true) @@ -65,8 +63,10 @@ const ( flagPredicatePushDown flagEliminateOuterJoin flagPartitionProcessor + flagCollectPredicateColumnsPoint flagPushDownAgg flagPushDownTopN + flagSyncWaitStatsLoadPoint flagJoinReOrder flagPrunColumnsAgain ) @@ -83,8 +83,10 @@ var optRuleList = []logicalOptRule{ &ppdSolver{}, &outerJoinEliminator{}, &partitionProcessor{}, + &collectPredicateColumnsPoint{}, &aggregationPushDownSolver{}, &pushDownTopNOptimizer{}, + &syncWaitStatsLoadPoint{}, &joinReOrderSolver{}, &columnPruner{}, // column pruning again at last, note it will mess up the results of buildKeySolver } @@ -104,24 +106,24 @@ func (op *logicalOptimizeOp) withEnableOptimizeTracer(tracer *tracing.LogicalOpt } func (op *logicalOptimizeOp) appendBeforeRuleOptimize(index int, name string, before LogicalPlan) { - if op.tracer == nil { + if op == nil || op.tracer == nil { return } - op.tracer.AppendRuleTracerBeforeRuleOptimize(index, name, before.buildLogicalPlanTrace(before)) + op.tracer.AppendRuleTracerBeforeRuleOptimize(index, name, before.buildPlanTrace()) } -func (op *logicalOptimizeOp) appendStepToCurrent(id int, tp, reason, action string) { - if op.tracer == nil { +func (op *logicalOptimizeOp) appendStepToCurrent(id int, tp string, reason, action func() string) { + if op == nil || op.tracer == nil { return } - op.tracer.AppendRuleTracerStepToCurrent(id, tp, reason, action) + op.tracer.AppendRuleTracerStepToCurrent(id, tp, reason(), action()) } func (op *logicalOptimizeOp) recordFinalLogicalPlan(final LogicalPlan) { - if op.tracer == nil { + if op == nil || op.tracer == nil { return } - op.tracer.RecordFinalLogicalPlan(final.buildLogicalPlanTrace(final)) + op.tracer.RecordFinalLogicalPlan(final.buildPlanTrace()) } // logicalOptRule means a logical optimizing rule, which contains decorrelate, ppd, column pruning, etc. @@ -267,6 +269,8 @@ func DoOptimize(ctx context.Context, sctx sessionctx.Context, flag uint64, logic if checkStableResultMode(sctx) { flag |= flagStabilizeResults } + flag |= flagCollectPredicateColumnsPoint + flag |= flagSyncWaitStatsLoadPoint logic, err := logicalOptimize(ctx, flag, logic) if err != nil { return nil, 0, err @@ -287,15 +291,36 @@ func DoOptimize(ctx context.Context, sctx sessionctx.Context, flag uint64, logic if sctx.GetSessionVars().StmtCtx.EnableOptimizerCETrace { refineCETrace(sctx) } - + if sctx.GetSessionVars().StmtCtx.EnableOptimizeTrace { + sctx.GetSessionVars().StmtCtx.OptimizeTracer.RecordFinalPlan(finalPlan.buildPlanTrace()) + } return finalPlan, cost, nil } // refineCETrace will adjust the content of CETrace. -// Currently, it will (1) deduplicate trace records and (2) fill in the table name. +// Currently, it will (1) deduplicate trace records, (2) sort the trace records (to make it easier in the tests) and (3) fill in the table name. func refineCETrace(sctx sessionctx.Context) { stmtCtx := sctx.GetSessionVars().StmtCtx stmtCtx.OptimizerCETrace = tracing.DedupCETrace(stmtCtx.OptimizerCETrace) + sort.Slice(stmtCtx.OptimizerCETrace, func(i, j int) bool { + if stmtCtx.OptimizerCETrace[i] == nil && stmtCtx.OptimizerCETrace[j] != nil { + return true + } + if stmtCtx.OptimizerCETrace[i] == nil || stmtCtx.OptimizerCETrace[j] == nil { + return false + } + + if stmtCtx.OptimizerCETrace[i].TableID != stmtCtx.OptimizerCETrace[j].TableID { + return stmtCtx.OptimizerCETrace[i].TableID < stmtCtx.OptimizerCETrace[j].TableID + } + if stmtCtx.OptimizerCETrace[i].Type != stmtCtx.OptimizerCETrace[j].Type { + return stmtCtx.OptimizerCETrace[i].Type < stmtCtx.OptimizerCETrace[j].Type + } + if stmtCtx.OptimizerCETrace[i].Expr != stmtCtx.OptimizerCETrace[j].Expr { + return stmtCtx.OptimizerCETrace[i].Expr < stmtCtx.OptimizerCETrace[j].Expr + } + return stmtCtx.OptimizerCETrace[i].RowCount < stmtCtx.OptimizerCETrace[j].RowCount + }) traceRecords := stmtCtx.OptimizerCETrace is := sctx.GetInfoSchema().(infoschema.InfoSchema) for _, rec := range traceRecords { @@ -402,16 +427,22 @@ func enableParallelApply(sctx sessionctx.Context, plan PhysicalPlan) PhysicalPla return plan } +// LogicalOptimizeTest is just exported for test. +func LogicalOptimizeTest(ctx context.Context, flag uint64, logic LogicalPlan) (LogicalPlan, error) { + return logicalOptimize(ctx, flag, logic) +} + func logicalOptimize(ctx context.Context, flag uint64, logic LogicalPlan) (LogicalPlan, error) { opt := defaultLogicalOptimizeOption() vars := logic.SCtx().GetSessionVars() if vars.StmtCtx.EnableOptimizeTrace { + vars.StmtCtx.OptimizeTracer = &tracing.OptimizeTracer{} tracer := &tracing.LogicalOptimizeTracer{ Steps: make([]*tracing.LogicalRuleOptimizeTracer, 0), } opt = opt.withEnableOptimizeTracer(tracer) defer func() { - vars.StmtCtx.LogicalOptimizeTrace = tracer + vars.StmtCtx.OptimizeTracer.Logical = tracer }() } var err error @@ -437,7 +468,7 @@ func isLogicalRuleDisabled(r logicalOptRule) bool { return disabled } -func physicalOptimize(logic LogicalPlan, planCounter *PlanCounterTp) (PhysicalPlan, float64, error) { +func physicalOptimize(logic LogicalPlan, planCounter *PlanCounterTp) (plan PhysicalPlan, cost float64, err error) { if _, err := logic.recursiveDeriveStats(nil); err != nil { return nil, 0, err } @@ -449,13 +480,26 @@ func physicalOptimize(logic LogicalPlan, planCounter *PlanCounterTp) (PhysicalPl ExpectedCnt: math.MaxFloat64, } + opt := defaultPhysicalOptimizeOption() + stmtCtx := logic.SCtx().GetSessionVars().StmtCtx + if stmtCtx.EnableOptimizeTrace { + tracer := &tracing.PhysicalOptimizeTracer{State: make(map[string]map[string]*tracing.PlanTrace)} + opt = opt.withEnableOptimizeTracer(tracer) + defer func() { + if err == nil { + tracer.RecordFinalPlanTrace(plan.buildPlanTrace()) + stmtCtx.OptimizeTracer.Physical = tracer + } + }() + } + logic.SCtx().GetSessionVars().StmtCtx.TaskMapBakTS = 0 - t, _, err := logic.findBestTask(prop, planCounter) + t, _, err := logic.findBestTask(prop, planCounter, opt) if err != nil { return nil, 0, err } if *planCounter > 0 { - logic.SCtx().GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("The parameter of nth_plan() is out of range.")) + logic.SCtx().GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("The parameter of nth_plan() is out of range")) } if t.invalid() { return nil, 0, ErrInternal.GenWithStackByArgs("Can't find a proper physical plan for this query") diff --git a/planner/core/optimizer_test.go b/planner/core/optimizer_test.go index bbcf0055eb4ea..0339498b75a55 100644 --- a/planner/core/optimizer_test.go +++ b/planner/core/optimizer_test.go @@ -15,21 +15,18 @@ package core import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) // LogicalOptimize exports the `logicalOptimize` function for test packages and // doesn't affect the normal package and access control of Golang (tricky ^_^) var LogicalOptimize = logicalOptimize -var _ = Suite(&testPlannerFunctionSuite{}) - -type testPlannerFunctionSuite struct { -} - -func testDecimalConvert(lDec, lLen, rDec, rLen int, lConvert, rConvert bool, cDec, cLen int, c *C) { +func testDecimalConvert(t *testing.T, lDec, lLen, rDec, rLen int, lConvert, rConvert bool, cDec, cLen int) { lType := types.NewFieldType(mysql.TypeNewDecimal) lType.Decimal = lDec lType.Flen = lLen @@ -39,39 +36,40 @@ func testDecimalConvert(lDec, lLen, rDec, rLen int, lConvert, rConvert bool, cDe rType.Flen = rLen cType, lCon, rCon := negotiateCommonType(lType, rType) - c.Assert(cType.Tp, Equals, mysql.TypeNewDecimal) - c.Assert(cType.Decimal, Equals, cDec) - c.Assert(cType.Flen, Equals, cLen) - c.Assert(lConvert, Equals, lCon) - c.Assert(rConvert, Equals, rCon) + require.Equal(t, mysql.TypeNewDecimal, cType.Tp) + require.Equal(t, cDec, cType.Decimal) + require.Equal(t, cLen, cType.Flen) + require.Equal(t, lConvert, lCon) + require.Equal(t, rConvert, rCon) } -func (t *testPlannerFunctionSuite) TestMPPDecimalConvert(c *C) { - testDecimalConvert(5, 9, 5, 8, false, false, 5, 9, c) - testDecimalConvert(5, 8, 5, 9, false, false, 5, 9, c) - testDecimalConvert(0, 8, 0, 11, true, false, 0, 11, c) - testDecimalConvert(0, 16, 0, 11, false, false, 0, 16, c) - testDecimalConvert(5, 9, 4, 9, true, true, 5, 10, c) - testDecimalConvert(5, 8, 4, 9, true, true, 5, 10, c) - testDecimalConvert(5, 9, 4, 8, false, true, 5, 9, c) - testDecimalConvert(10, 16, 0, 11, true, true, 10, 21, c) - testDecimalConvert(5, 19, 0, 20, false, true, 5, 25, c) - testDecimalConvert(20, 20, 0, 60, true, true, 20, 65, c) - testDecimalConvert(20, 40, 0, 60, false, true, 20, 65, c) - testDecimalConvert(0, 40, 0, 60, false, false, 0, 60, c) +func TestMPPDecimalConvert(t *testing.T) { + testDecimalConvert(t, 5, 9, 5, 8, false, false, 5, 9) + testDecimalConvert(t, 5, 8, 5, 9, false, false, 5, 9) + testDecimalConvert(t, 0, 8, 0, 11, true, false, 0, 11) + testDecimalConvert(t, 0, 16, 0, 11, false, false, 0, 16) + testDecimalConvert(t, 5, 9, 4, 9, true, true, 5, 10) + testDecimalConvert(t, 5, 8, 4, 9, true, true, 5, 10) + testDecimalConvert(t, 5, 9, 4, 8, false, true, 5, 9) + testDecimalConvert(t, 10, 16, 0, 11, true, true, 10, 21) + testDecimalConvert(t, 5, 19, 0, 20, false, true, 5, 25) + testDecimalConvert(t, 20, 20, 0, 60, true, true, 20, 65) + testDecimalConvert(t, 20, 40, 0, 60, false, true, 20, 65) + testDecimalConvert(t, 0, 40, 0, 60, false, false, 0, 60) } -func testJoinKeyTypeConvert(leftType, rightType, retType *types.FieldType, lConvert, rConvert bool, c *C) { +func testJoinKeyTypeConvert(t *testing.T, leftType, rightType, retType *types.FieldType, lConvert, rConvert bool) { cType, lCon, rCon := negotiateCommonType(leftType, rightType) - c.Assert(cType.Tp, Equals, retType.Tp) - c.Assert(cType.Flen, Equals, retType.Flen) - c.Assert(cType.Decimal, Equals, retType.Decimal) - c.Assert(cType.Flag, Equals, retType.Flag) - c.Assert(lConvert, Equals, lCon) - c.Assert(rConvert, Equals, rCon) + require.Equal(t, retType.Tp, cType.Tp) + require.Equal(t, retType.Flen, cType.Flen) + require.Equal(t, retType.Decimal, cType.Decimal) + require.Equal(t, retType.Flag, cType.Flag) + require.Equal(t, lConvert, lCon) + require.Equal(t, rConvert, rCon) + } -func (t *testPlannerFunctionSuite) TestMPPJoinKeyTypeConvert(c *C) { +func TestMPPJoinKeyTypeConvert(t *testing.T) { tinyIntType := &types.FieldType{ Tp: mysql.TypeTiny, } @@ -100,13 +98,13 @@ func (t *testPlannerFunctionSuite) TestMPPJoinKeyTypeConvert(c *C) { Decimal: 0, } - testJoinKeyTypeConvert(tinyIntType, tinyIntType, tinyIntType, false, false, c) - testJoinKeyTypeConvert(tinyIntType, unsignedTinyIntType, bigIntType, true, true, c) - testJoinKeyTypeConvert(tinyIntType, bigIntType, bigIntType, true, false, c) - testJoinKeyTypeConvert(bigIntType, tinyIntType, bigIntType, false, true, c) - testJoinKeyTypeConvert(unsignedBigIntType, tinyIntType, decimalType, true, true, c) - testJoinKeyTypeConvert(tinyIntType, unsignedBigIntType, decimalType, true, true, c) - testJoinKeyTypeConvert(bigIntType, bigIntType, bigIntType, false, false, c) - testJoinKeyTypeConvert(unsignedBigIntType, bigIntType, decimalType, true, true, c) - testJoinKeyTypeConvert(bigIntType, unsignedBigIntType, decimalType, true, true, c) + testJoinKeyTypeConvert(t, tinyIntType, tinyIntType, tinyIntType, false, false) + testJoinKeyTypeConvert(t, tinyIntType, unsignedTinyIntType, bigIntType, true, true) + testJoinKeyTypeConvert(t, tinyIntType, bigIntType, bigIntType, true, false) + testJoinKeyTypeConvert(t, bigIntType, tinyIntType, bigIntType, false, true) + testJoinKeyTypeConvert(t, unsignedBigIntType, tinyIntType, decimalType, true, true) + testJoinKeyTypeConvert(t, tinyIntType, unsignedBigIntType, decimalType, true, true) + testJoinKeyTypeConvert(t, bigIntType, bigIntType, bigIntType, false, false) + testJoinKeyTypeConvert(t, unsignedBigIntType, bigIntType, decimalType, true, true) + testJoinKeyTypeConvert(t, bigIntType, unsignedBigIntType, decimalType, true, true) } diff --git a/planner/core/partition_pruner_test.go b/planner/core/partition_pruner_test.go index ec8e9e92a9556..5853438545d08 100644 --- a/planner/core/partition_pruner_test.go +++ b/planner/core/partition_pruner_test.go @@ -19,47 +19,23 @@ import ( "fmt" "sort" "strings" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/sessionctx" + plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPartitionPruneSuit{}) - -type testPartitionPruneSuit struct { - store kv.Storage - dom *domain.Domain - ctx sessionctx.Context - testData testutil.TestData -} - -func (s *testPartitionPruneSuit) SetUpSuite(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) - s.ctx = mock.NewContext() - s.testData, err = testutil.LoadTestSuiteData("testdata", "partition_pruner") - c.Assert(err, IsNil) -} - -func (s *testPartitionPruneSuit) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) - s.dom.Close() - s.store.Close() -} - -func (s *testPartitionPruneSuit) TestHashPartitionPruner(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHashPartitionPruner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("create database test_partition") tk.MustExec("use test_partition") tk.MustExec("drop table if exists t1, t2;") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t2(id int, a int, b int, primary key(id, a)) partition by hash(id + a) partitions 10;") tk.MustExec("create table t1(id int primary key, a int, b int) partition by hash(id) partitions 10;") tk.MustExec("create table t3(id int, a int, b int, primary key(id, a)) partition by hash(id) partitions 10;") @@ -76,22 +52,210 @@ func (s *testPartitionPruneSuit) TestHashPartitionPruner(c *C) { SQL string Result []string } - s.testData.GetTestCases(c, &input, &output) + partitionPrunerData := plannercore.GetPartitionPrunerData() + partitionPrunerData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) } } -func (s *testPartitionPruneSuit) TestListPartitionPruner(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangeColumnPartitionPruningForIn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists test_range_col_in") + tk.MustExec("create database test_range_col_in") + tk.MustExec("use test_range_col_in") + tk.MustExec(`set @@session.tidb_enable_list_partition = 1`) + tk.MustExec("set @@session.tidb_partition_prune_mode='static'") + + // case in issue-26739 + tk.MustExec(`CREATE TABLE t1 ( + id bigint(20) NOT NULL AUTO_INCREMENT, + dt date, + PRIMARY KEY (id,dt)) + PARTITION BY RANGE COLUMNS(dt) ( + PARTITION p20201125 VALUES LESS THAN ("20201126"), + PARTITION p20201126 VALUES LESS THAN ("20201127"), + PARTITION p20201127 VALUES LESS THAN ("20201128"), + PARTITION p20201128 VALUES LESS THAN ("20201129"), + PARTITION p20201129 VALUES LESS THAN ("20201130"))`) + tk.MustQuery(`explain format='brief' select /*+ HASH_AGG() */ count(1) from t1 where dt in ('2020-11-27','2020-11-28')`).Check( + testkit.Rows("HashAgg 1.00 root funcs:count(Column#5)->Column#4", + "└─PartitionUnion 2.00 root ", + " ├─HashAgg 1.00 root funcs:count(Column#7)->Column#5", + " │ └─IndexReader 1.00 root index:HashAgg", + " │ └─HashAgg 1.00 cop[tikv] funcs:count(1)->Column#7", + " │ └─Selection 20.00 cop[tikv] in(test_range_col_in.t1.dt, 2020-11-27 00:00:00.000000, 2020-11-28 00:00:00.000000)", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t1, partition:p20201127, index:PRIMARY(id, dt) keep order:false, stats:pseudo", + " └─HashAgg 1.00 root funcs:count(Column#10)->Column#5", + " └─IndexReader 1.00 root index:HashAgg", + " └─HashAgg 1.00 cop[tikv] funcs:count(1)->Column#10", + " └─Selection 20.00 cop[tikv] in(test_range_col_in.t1.dt, 2020-11-27 00:00:00.000000, 2020-11-28 00:00:00.000000)", + " └─IndexFullScan 10000.00 cop[tikv] table:t1, partition:p20201128, index:PRIMARY(id, dt) keep order:false, stats:pseudo")) + + tk.MustExec(`insert into t1 values (1, "2020-11-25")`) + tk.MustExec(`insert into t1 values (2, "2020-11-26")`) + tk.MustExec(`insert into t1 values (3, "2020-11-27")`) + tk.MustExec(`insert into t1 values (4, "2020-11-28")`) + tk.MustQuery(`select id from t1 where dt in ('2020-11-27','2020-11-28') order by id`).Check(testkit.Rows("3", "4")) + tk.MustQuery(`select id from t1 where dt in (20201127,'2020-11-28') order by id`).Check(testkit.Rows("3", "4")) + tk.MustQuery(`select id from t1 where dt in (20201127,20201128) order by id`).Check(testkit.Rows("3", "4")) + tk.MustQuery(`select id from t1 where dt in (20201127,20201128,null) order by id`).Check(testkit.Rows("3", "4")) + tk.MustQuery(`select id from t1 where dt in ('2020-11-26','2020-11-25','2020-11-28') order by id`).Check(testkit.Rows("1", "2", "4")) + tk.MustQuery(`select id from t1 where dt in ('2020-11-26','wrong','2020-11-28') order by id`).Check(testkit.Rows("2", "4")) + + // int + tk.MustExec(`create table t2 (a int) partition by range columns(a) ( + partition p0 values less than (0), + partition p1 values less than (10), + partition p2 values less than (20))`) + tk.MustExec(`insert into t2 values (-1), (1), (11), (null)`) + tk.MustQuery(`select a from t2 where a in (-1, 1) order by a`).Check(testkit.Rows("-1", "1")) + tk.MustQuery(`select a from t2 where a in (1, 11, null) order by a`).Check(testkit.Rows("1", "11")) + tk.MustQuery(`explain format='brief' select a from t2 where a in (-1, 1)`).Check(testkit.Rows("PartitionUnion 40.00 root ", + "├─TableReader 20.00 root data:Selection", + "│ └─Selection 20.00 cop[tikv] in(test_range_col_in.t2.a, -1, 1)", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo", + "└─TableReader 20.00 root data:Selection", + " └─Selection 20.00 cop[tikv] in(test_range_col_in.t2.a, -1, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo")) + + tk.MustExec(`create table t3 (a varchar(10)) partition by range columns(a) ( + partition p0 values less than ("aaa"), + partition p1 values less than ("bbb"), + partition p2 values less than ("ccc"))`) + tk.MustQuery(`explain format='brief' select a from t3 where a in ('aaa', 'aab')`).Check(testkit.Rows( + `TableReader 20.00 root data:Selection`, + `└─Selection 20.00 cop[tikv] in(test_range_col_in.t3.a, "aaa", "aab")`, + ` └─TableFullScan 10000.00 cop[tikv] table:t3, partition:p1 keep order:false, stats:pseudo`)) + tk.MustQuery(`explain format='brief' select a from t3 where a in ('aaa', 'bu')`).Check(testkit.Rows( + `PartitionUnion 40.00 root `, + `├─TableReader 20.00 root data:Selection`, + `│ └─Selection 20.00 cop[tikv] in(test_range_col_in.t3.a, "aaa", "bu")`, + `│ └─TableFullScan 10000.00 cop[tikv] table:t3, partition:p1 keep order:false, stats:pseudo`, + `└─TableReader 20.00 root data:Selection`, + ` └─Selection 20.00 cop[tikv] in(test_range_col_in.t3.a, "aaa", "bu")`, + ` └─TableFullScan 10000.00 cop[tikv] table:t3, partition:p2 keep order:false, stats:pseudo`)) +} + +func TestRangeColumnPartitionPruningForInString(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop database if exists test_range_col_in_string") + tk.MustExec("create database test_range_col_in_string") + + tk.MustExec("use test_range_col_in_string") + tk.MustExec("set names utf8mb4 collate utf8mb4_bin") + tk.MustExec("set @@session.tidb_partition_prune_mode='static'") + + type testStruct struct { + sql string + partitions string + rows []string + } + + extractPartitions := func(res *testkit.Result) string { + planStrings := testdata.ConvertRowsToStrings(res.Rows()) + partitions := []string{} + for _, s := range planStrings { + parts := getFieldValue("partition:", s) + if parts != "" { + partitions = append(partitions, strings.Split(parts, ",")...) + } + } + return strings.Join(partitions, ",") + } + checkColumnStringPruningTests := func(tests []testStruct) { + modes := []string{"dynamic", "static"} + for _, mode := range modes { + tk.MustExec(`set @@tidb_partition_prune_mode = '` + mode + `'`) + for _, test := range tests { + explainResult := tk.MustQuery("explain format = 'brief' " + test.sql) + partitions := strings.ToLower(extractPartitions(explainResult)) + require.Equal(t, test.partitions, partitions, "Mode: %s sql: %s", mode, test.sql) + tk.MustQuery(test.sql).Sort().Check(testkit.Rows(test.rows...)) + } + } + } + tk.MustExec("create table t (a varchar(255) charset utf8mb4 collate utf8mb4_bin) partition by range columns(a)" + + `( partition pNull values less than (""),` + + `partition pAAAA values less than ("AAAA"),` + + `partition pCCC values less than ("CCC"),` + + `partition pShrimpsandwich values less than ("RäksmörgÃ¥s"),` + + `partition paaa values less than ("aaa"),` + + `partition pSushi values less than ("ðŸ£ðŸ£ðŸ£"),` + + `partition pMax values less than (MAXVALUE))`) + tk.MustExec(`insert into t values (NULL), ("a"), ("Räkmacka"), ("🣠is life"), ("🺠after work?"), ("ðŸºðŸºðŸºðŸºðŸº for oktoberfest"),("AA"),("aa"),("AAA"),("aaa")`) + tests := []testStruct{ + // Lower case partition names due to issue#32719 + {sql: `select * from t where a IS NULL`, partitions: "pnull", rows: []string{""}}, + {sql: `select * from t where a = 'AA'`, partitions: "paaaa", rows: []string{"AA"}}, + {sql: `select * from t where a = 'AA' collate utf8mb4_general_ci`, partitions: "paaaa", rows: []string{"AA"}}, // Notice that the it not uses _bin collation for partition => 'aa' not found! #32749 + {sql: `select * from t where a = 'aa'`, partitions: "paaa", rows: []string{"aa"}}, + {sql: `select * from t where a = 'aa' collate utf8mb4_general_ci`, partitions: "paaaa", rows: []string{"AA"}}, // Notice that the it not uses _bin collation for partition => 'aa' not found! #32749 + {sql: `select * from t where a = 'AAA'`, partitions: "paaaa", rows: []string{"AAA"}}, + {sql: `select * from t where a = 'AB'`, partitions: "pccc", rows: []string{}}, + {sql: `select * from t where a = 'aB'`, partitions: "paaa", rows: []string{}}, + {sql: `select * from t where a = 'ðŸ£'`, partitions: "psushi", rows: []string{}}, + {sql: `select * from t where a in ('🣠is life', "Räkmacka", "ðŸºðŸºðŸºðŸº after work?")`, partitions: "pshrimpsandwich,psushi,pmax", rows: []string{"Räkmacka", "🣠is life"}}, + {sql: `select * from t where a in ('AAA', 'aa')`, partitions: "paaaa,paaa", rows: []string{"AAA", "aa"}}, + {sql: `select * from t where a in ('AAA' collate utf8mb4_general_ci, 'aa')`, partitions: "paaaa,paaa", rows: []string{"AA", "AAA", "aa"}}, // aaa missing due to #32749 + {sql: `select * from t where a in ('AAA', 'aa' collate utf8mb4_general_ci)`, partitions: "paaaa", rows: []string{"AA", "AAA"}}, // aa, aaa missing due to #32749 + } + checkColumnStringPruningTests(tests) + tk.MustExec(`set names utf8mb4 collate utf8mb4_general_ci`) + checkColumnStringPruningTests(tests) + tk.MustExec(`set names utf8mb4 collate utf8mb4_unicode_ci`) + checkColumnStringPruningTests(tests) + tk.MustExec("drop table t") + tk.MustExec("create table t (a varchar(255) charset utf8mb4 collate utf8mb4_general_ci) partition by range columns(a)" + + `( partition pNull values less than (""),` + + `partition paaa values less than ("aaa"),` + + `partition pAAAA values less than ("AAAA"),` + + `partition pCCC values less than ("CCC"),` + + `partition pShrimpsandwich values less than ("RäksmörgÃ¥s"),` + + `partition pSushi values less than ("ðŸ£ðŸ£ðŸ£"),` + + `partition pMax values less than (MAXVALUE))`) + tk.MustExec(`insert into t values (NULL), ("a"), ("Räkmacka"), ("🣠is life"), ("🺠after work?"), ("ðŸºðŸºðŸºðŸºðŸº for oktoberfest"),("AA"),("aa"),("AAA"),("aaa")`) + + tests = []testStruct{ + // Lower case partition names due to issue#32719 + {sql: `select * from t where a IS NULL`, partitions: "pnull", rows: []string{""}}, + {sql: `select * from t where a = 'AA'`, partitions: "paaa", rows: []string{"AA", "aa"}}, + {sql: `select * from t where a = 'AA' collate utf8mb4_bin`, partitions: "paaa", rows: []string{"AA"}}, + {sql: `select * from t where a = 'AAA'`, partitions: "paaaa", rows: []string{"AAA", "aaa"}}, + {sql: `select * from t where a = 'AAA' collate utf8mb4_bin`, partitions: "paaa", rows: []string{}}, // Notice that the it uses _bin collation for partition => not found! #32749 + {sql: `select * from t where a = 'AB'`, partitions: "pccc", rows: []string{}}, + {sql: `select * from t where a = 'aB'`, partitions: "pccc", rows: []string{}}, + {sql: `select * from t where a = 'ðŸ£'`, partitions: "psushi", rows: []string{}}, + {sql: `select * from t where a in ('🣠is life', "Räkmacka", "ðŸºðŸºðŸºðŸº after work?")`, partitions: "pshrimpsandwich,psushi,pmax", rows: []string{"Räkmacka", "🣠is life"}}, + {sql: `select * from t where a in ('AA', 'aaa')`, partitions: "paaa,paaaa", rows: []string{"AA", "AAA", "aa", "aaa"}}, + {sql: `select * from t where a in ('AAA' collate utf8mb4_bin, 'aa')`, partitions: "paaa", rows: []string{"aa"}}, // AAA missing due to #32749, why is AA missing? + {sql: `select * from t where a in ('AAA', 'aa' collate utf8mb4_bin)`, partitions: "paaaa,psushi", rows: []string{"AAA"}}, // aa, aaa missing due to #32749 also all missing paaa + } + + tk.MustExec(`set names utf8mb4 collate utf8mb4_bin`) + checkColumnStringPruningTests(tests) + tk.MustExec(`set names utf8mb4 collate utf8mb4_general_ci`) + checkColumnStringPruningTests(tests) + tk.MustExec(`set names utf8mb4 collate utf8mb4_unicode_ci`) + checkColumnStringPruningTests(tests) +} + +func TestListPartitionPruner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("drop database if exists test_partition;") tk.MustExec("create database test_partition") tk.MustExec("use test_partition") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec(`set @@session.tidb_regard_null_as_point=false`) tk.MustExec("create table t1 (id int, a int, b int ) partition by list ( a ) (partition p0 values in (1,2,3,4,5), partition p1 values in (6,7,8,9,10,null));") @@ -110,7 +274,7 @@ func (s *testPartitionPruneSuit) TestListPartitionPruner(c *C) { tk.MustExec("insert into t7 values (null),(0),(1),(2);") // tk2 use to compare the result with normal table. - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("drop database if exists test_partition_2;") tk2.MustExec("create database test_partition_2") tk2.MustExec("use test_partition_2") @@ -135,13 +299,14 @@ func (s *testPartitionPruneSuit) TestListPartitionPruner(c *C) { Result []string Plan []string } - s.testData.GetTestCases(c, &input, &output) + partitionPrunerData := plannercore.GetPartitionPrunerData() + partitionPrunerData.GetTestCases(t, &input, &output) valid := false for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) result := tk.MustQuery(tt) @@ -151,12 +316,14 @@ func (s *testPartitionPruneSuit) TestListPartitionPruner(c *C) { result.Check(tk2.MustQuery(tt).Rows()) valid = true } - c.Assert(valid, IsTrue) + require.True(t, valid) } } -func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestListColumnsPartitionPruner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("drop database if exists test_partition;") tk.MustExec("create database test_partition") @@ -168,7 +335,7 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { tk.MustExec("insert into t2 (id,a,b) values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),(null,null,null)") // tk1 use to test partition table with index. - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("drop database if exists test_partition_1;") tk1.MustExec(`set @@session.tidb_regard_null_as_point=false`) tk1.MustExec("create database test_partition_1") @@ -180,7 +347,7 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { tk1.MustExec("insert into t2 (id,a,b) values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),(null,null,null)") // tk2 use to compare the result with normal table. - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("drop database if exists test_partition_2;") tk2.MustExec(`set @@session.tidb_regard_null_as_point=false`) tk2.MustExec("create database test_partition_2") @@ -200,18 +367,19 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { Plan []string IndexPlan []string } - s.testData.GetTestCases(c, &input, &output) + partitionPrunerData := plannercore.GetPartitionPrunerData() + partitionPrunerData.GetTestCases(t, &input, &output) valid := false for i, tt := range input { // Test for table without index. plan := tk.MustQuery("explain format = 'brief' " + tt.SQL) - planTree := s.testData.ConvertRowsToStrings(plan.Rows()) + planTree := testdata.ConvertRowsToStrings(plan.Rows()) // Test for table with index. indexPlan := tk1.MustQuery("explain format = 'brief' " + tt.SQL) - indexPlanTree := s.testData.ConvertRowsToStrings(indexPlan.Rows()) - s.testData.OnRecord(func() { + indexPlanTree := testdata.ConvertRowsToStrings(indexPlan.Rows()) + testdata.OnRecord(func() { output[i].SQL = tt.SQL - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt.SQL).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt.SQL).Rows()) // Test for table without index. output[i].Plan = planTree // Test for table with index. @@ -222,8 +390,8 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { indexPlan.Check(testkit.Rows(output[i].IndexPlan...)) // compare the pruner information. - s.checkPrunePartitionInfo(c, tt.SQL, tt.Pruner, planTree) - s.checkPrunePartitionInfo(c, tt.SQL, tt.Pruner, indexPlanTree) + checkPrunePartitionInfo(t, tt.SQL, tt.Pruner, planTree) + checkPrunePartitionInfo(t, tt.SQL, tt.Pruner, indexPlanTree) // compare the result. result := tk.MustQuery(tt.SQL) @@ -237,12 +405,13 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPruner(c *C) { valid = true } } - c.Assert(valid, IsTrue) + require.True(t, valid) } -func (s *testPartitionPruneSuit) checkPrunePartitionInfo(c *C, query string, infos1 string, plan []string) { - infos2 := s.getPartitionInfoFromPlan(plan) - c.Assert(infos1, Equals, infos2, Commentf("the query is: %v, the plan is:\n%v", query, strings.Join(plan, "\n"))) +func checkPrunePartitionInfo(c *testing.T, query string, infos1 string, plan []string) { + infos2 := getPartitionInfoFromPlan(plan) + comment := fmt.Sprintf("the query is: %v, the plan is:\n%v", query, strings.Join(plan, "\n")) + require.Equal(c, infos1, infos2, comment) } type testTablePartitionInfo struct { @@ -261,16 +430,16 @@ type testTablePartitionInfo struct { // " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" // // The return table partition info is: t1: p0; t2: p1 -func (s *testPartitionPruneSuit) getPartitionInfoFromPlan(plan []string) string { +func getPartitionInfoFromPlan(plan []string) string { infos := make([]testTablePartitionInfo, 0, 2) info := testTablePartitionInfo{} for _, row := range plan { - partitions := s.getFieldValue("partition:", row) + partitions := getFieldValue("partition:", row) if partitions != "" { info.Partitions = partitions continue } - tbl := s.getFieldValue("table:", row) + tbl := getFieldValue("table:", row) if tbl != "" { info.Table = tbl infos = append(infos, info) @@ -292,7 +461,7 @@ func (s *testPartitionPruneSuit) getPartitionInfoFromPlan(plan []string) string return buf.String() } -func (s *testPartitionPruneSuit) getFieldValue(prefix, row string) string { +func getFieldValue(prefix, row string) string { if idx := strings.Index(row, prefix); idx > 0 { start := idx + len(prefix) end := strings.Index(row[start:], " ") @@ -305,8 +474,10 @@ func (s *testPartitionPruneSuit) getFieldValue(prefix, row string) string { return "" } -func (s *testPartitionPruneSuit) TestListColumnsPartitionPrunerRandom(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestListColumnsPartitionPrunerRandom(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) valueNum := 10 // Create table. tk.MustExec("drop database if exists test_partition;") @@ -315,7 +486,7 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPrunerRandom(c *C) { tk.MustExec("set @@session.tidb_enable_list_partition = ON") tk.MustExec("create table t1 (id int, a int, b int ) partition by list columns (b, id, a) (partition p0 values in ((1,0,2),(2,0,2),(0,1,0),(1,1,0),(2,1,0),(0,1,1),(0,1,2),(0,2,0),(1,2,0)),partition p1 values in ((1,0,1),(0,0,2),(2,1,1),(2,1,2),(2,2,1),(1,2,2),(2,2,2)),partition p2 values in ((0,0,0),(1,0,0),(2,0,0),(0,0,1),(2,0,1),(1,1,1),(1,1,2),(2,2,0),(0,2,1),(1,2,1),(0,2,2)))") - tk1 := testkit.NewTestKit(c, s.store) + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("drop database if exists test_partition_1;") tk1.MustExec("create database test_partition_1") tk1.MustExec("use test_partition_1") @@ -358,8 +529,10 @@ func (s *testPartitionPruneSuit) TestListColumnsPartitionPrunerRandom(c *C) { } } -func (s *testPartitionPruneSuit) TestIssue22635(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22635(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") tk.MustExec("DROP TABLE IF EXISTS t1") tk.MustExec(` @@ -384,19 +557,23 @@ PARTITIONS 4`) tk.MustQuery("SELECT (SELECT tt.a FROM t1 tt LIMIT 1) aa, COUNT(DISTINCT b) FROM t1 GROUP BY aa").Check(testkit.Rows("4 4")) } -func (s *testPartitionPruneSuit) TestIssue22898(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue22898(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") tk.MustExec("DROP TABLE IF EXISTS test;") tk.MustExec("CREATE TABLE NT_RP3763 (COL1 TINYINT(8) SIGNED COMMENT \"NUMERIC NO INDEX\" DEFAULT 41,COL2 VARCHAR(20),COL3 DATETIME,COL4 BIGINT,COL5 FLOAT) PARTITION BY RANGE (COL1 * COL3) (PARTITION P0 VALUES LESS THAN (0),PARTITION P1 VALUES LESS THAN (10),PARTITION P2 VALUES LESS THAN (20),PARTITION P3 VALUES LESS THAN (30),PARTITION P4 VALUES LESS THAN (40),PARTITION P5 VALUES LESS THAN (50),PARTITION PMX VALUES LESS THAN MAXVALUE);") tk.MustExec("insert into NT_RP3763 (COL1,COL2,COL3,COL4,COL5) values(-82,\"å¤é½é†•çš†ç£¹æ¼‹ç”“崘潮嵙燷æ¸è‰‚朼洛炷鉢å„鱈肇\",\"5748\\-06\\-26\\ 20:48:49\",-3133527360541070260,-2.624880003397658e+38);") tk.MustExec("insert into NT_RP3763 (COL1,COL2,COL3,COL4,COL5) values(48,\"簖鹩筈匹眜赖泽騈爷詵赺玡婙Ɇéƒé®™å»›è³™ç–¼èˆ¢\",\"7228\\-12\\-13\\ 02:59:54\",-6181009269190017937,2.7731105531290494e+38);") - tk.MustQuery("select * from `NT_RP3763` where `COL1` in (10, 48, -82);").Check(testkit.Rows("-82 å¤é½é†•çš†ç£¹æ¼‹ç”“崘潮嵙燷æ¸è‰‚朼洛炷鉢å„鱈肇 5748-06-26 20:48:49 -3133527360541070260 -262488000000000000000000000000000000000", "48 簖鹩筈匹眜赖泽騈爷詵赺玡婙Ɇéƒé®™å»›è³™ç–¼èˆ¢ 7228-12-13 02:59:54 -6181009269190017937 277311060000000000000000000000000000000")) + tk.MustQuery("select * from `NT_RP3763` where `COL1` in (10, 48, -82);").Sort().Check(testkit.Rows("-82 å¤é½é†•çš†ç£¹æ¼‹ç”“崘潮嵙燷æ¸è‰‚朼洛炷鉢å„鱈肇 5748-06-26 20:48:49 -3133527360541070260 -262488000000000000000000000000000000000", "48 簖鹩筈匹眜赖泽騈爷詵赺玡婙Ɇéƒé®™å»›è³™ç–¼èˆ¢ 7228-12-13 02:59:54 -6181009269190017937 277311060000000000000000000000000000000")) tk.MustQuery("select * from `NT_RP3763` where `COL1` in (48);").Check(testkit.Rows("48 簖鹩筈匹眜赖泽騈爷詵赺玡婙Ɇéƒé®™å»›è³™ç–¼èˆ¢ 7228-12-13 02:59:54 -6181009269190017937 277311060000000000000000000000000000000")) } -func (s *testPartitionPruneSuit) TestIssue23622(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23622(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") tk.MustExec("drop table if exists t2;") tk.MustExec("create table t2 (a int, b int) partition by range (a) (partition p0 values less than (0), partition p1 values less than (5));") @@ -404,8 +581,10 @@ func (s *testPartitionPruneSuit) TestIssue23622(c *C) { tk.MustQuery("select * from t2 where a > 10 or b is NULL order by a;").Check(testkit.Rows("-1 ", "1 ")) } -func (s *testPartitionPruneSuit) Test22396(c *C) { - tk := testkit.NewTestKit(c, s.store) +func Test22396(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("USE test;") tk.MustExec("DROP TABLE IF EXISTS test;") tk.MustExec("CREATE TABLE test(a INT, b INT, PRIMARY KEY(a, b)) PARTITION BY RANGE (a + b) (PARTITION p0 VALUES LESS THAN (20),PARTITION p1 VALUES LESS THAN MAXVALUE);") @@ -416,8 +595,10 @@ func (s *testPartitionPruneSuit) Test22396(c *C) { tk.MustQuery("SELECT * FROM test WHERE a + b = 2;") } -func (s *testPartitionPruneSuit) TestIssue23608(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23608(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='static'") tk.MustExec("drop table if exists t1") @@ -462,14 +643,16 @@ partition by range (a) ( } //issue 22079 -func (s *testPartitionPruneSuit) TestRangePartitionPredicatePruner(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestRangePartitionPredicatePruner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Static) + "'") tk.MustExec("drop database if exists test_partition;") tk.MustExec("create database test_partition") tk.MustExec("use test_partition") tk.MustExec("drop table if exists t") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec(`create table t (a int(11) default null) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin partition by range(a) ( partition p0 values less than (1), @@ -482,18 +665,21 @@ func (s *testPartitionPruneSuit) TestRangePartitionPredicatePruner(c *C) { SQL string Result []string } - s.testData.GetTestCases(c, &input, &output) + partitionPrunerData := plannercore.GetPartitionPrunerData() + partitionPrunerData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) }) tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) } } -func (s *testPartitionPruneSuit) TestHashPartitionPruning(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestHashPartitionPruning(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode='static'") tk.MustExec("USE test;") tk.MustExec("DROP TABLE IF EXISTS t;") @@ -510,3 +696,44 @@ func (s *testPartitionPruneSuit) TestHashPartitionPruning(c *C) { tk.MustExec("insert into t(col1, col3) values(0, 3522101843073676459);") tk.MustQuery("SELECT col1, COL3 FROM t WHERE COL1 IN (0,14158354938390,0) AND COL3 IN (3522101843073676459,-2846203247576845955,838395691793635638);").Check(testkit.Rows("0 3522101843073676459")) } + +func TestIssue32007(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database Issue32007") + tk.MustExec("USE Issue32007") + tk.MustExec("create table t1 (a int, b tinyint, primary key (a)) partition by range (a) (" + + "partition p0 values less than (5)," + + "partition p1 values less than (20)," + + "partition p2 values less than (30)," + + "partition p3 values less than (40)," + + "partition p4 values less than MAXVALUE)") + tk.MustExec("insert into t1 values (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (20, 20), (21, 21), (22, 22), (23, 23), (24, 24), (25, 25), (30, 30), (31, 31), (32, 32), (33, 33), (34, 34), (35, 35), (36, 36), (40, 40), (50, 50), (80, 80), (90, 90), (100, 100)") + tk.MustExec("create table t3 (a int, b mediumint, primary key (a))") + tk.MustExec("insert into t3 values (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19), (20, 20), (21, 21), (22, 22), (23, 23)") + + tk.MustExec("set @@tidb_partition_prune_mode='static'") + tk.MustQuery("select * from t3 where t3.a <> ALL (select t1.a from t1 partition (p0)) order by t3.a").Sort().Check(testkit.Rows("10 10", "11 11", "12 12", "13 13", "14 14", "15 15", "16 16", "17 17", "18 18", "19 19", "20 20", "21 21", "22 22", "23 23", "5 5", "6 6", "7 7", "8 8", "9 9")) + tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") + tk.MustQuery("select * from t3 where t3.a <> ALL (select t1.a from t1 partition (p0)) order by t3.a").Sort().Check(testkit.Rows("10 10", "11 11", "12 12", "13 13", "14 14", "15 15", "16 16", "17 17", "18 18", "19 19", "20 20", "21 21", "22 22", "23 23", "5 5", "6 6", "7 7", "8 8", "9 9")) +} + +func TestIssue33231(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database issue33231") + tk.MustExec("use issue33231") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'dynamic';") + tk.MustExec("create table t1 (c_int int, c_str varchar(40), primary key (c_int, c_str) clustered, key(c_int) ) partition by hash (c_int) partitions 4;") + tk.MustExec("create table t2 like t1;") + tk.MustExec("insert into t1 values(6, 'beautiful curran');") + tk.MustExec("insert into t1 values(7, 'epic kalam');") + tk.MustExec("insert into t1 values(7, 'affectionate curie');") + tk.MustExec("insert into t2 values(6, 'vigorous rhodes');") + tk.MustExec("insert into t2 values(7, 'sweet aryabhata');") + tk.MustQuery("select /*+ INL_JOIN(t2) */ * from t1, t2 where t1.c_int = t2.c_int and t1.c_str <= t2.c_str and t2.c_int in (6, 7, 6);"). + Sort(). + Check(testkit.Rows("6 beautiful curran 6 vigorous rhodes", "7 affectionate curie 7 sweet aryabhata", "7 epic kalam 7 sweet aryabhata")) +} diff --git a/planner/core/partition_pruning_test.go b/planner/core/partition_pruning_test.go index 4ba103b01ea96..2b7e8625b15f5 100644 --- a/planner/core/partition_pruning_test.go +++ b/planner/core/partition_pruning_test.go @@ -15,7 +15,8 @@ package core import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser" @@ -23,17 +24,11 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testPartitionPruningSuite{}) - -type testPartitionPruningSuite struct { - partitionProcessor -} - -func (s *testPartitionPruningSuite) TestCanBePrune(c *C) { +func TestCanBePrune(t *testing.T) { // For the following case: // CREATE TABLE t1 ( recdate DATETIME NOT NULL ) // PARTITION BY RANGE( TO_DAYS(recdate) ) ( @@ -43,20 +38,17 @@ func (s *testPartitionPruningSuite) TestCanBePrune(c *C) { // SELECT * FROM t1 WHERE recdate < '2007-03-08 00:00:00'; // SELECT * FROM t1 WHERE recdate > '2018-03-08 00:00:00'; - tc := prepareTestCtx(c, - "create table t (d datetime not null)", - "to_days(d)", - ) + tc := prepareTestCtx(t, "create table t (d datetime not null)", "to_days(d)") lessThan := lessThanDataInt{data: []int64{733108, 733132}, maxvalue: false} - prunner := &rangePruner{lessThan, tc.col, tc.fn, monotoneModeNonStrict} + pruner := &rangePruner{lessThan, tc.col, tc.fn, monotoneModeNonStrict} queryExpr := tc.expr("d < '2000-03-08 00:00:00'") - result := partitionRangeForCNFExpr(tc.sctx, queryExpr, prunner, fullRange(len(lessThan.data))) - c.Assert(equalPartitionRangeOR(result, partitionRangeOR{{0, 1}}), IsTrue) + result := partitionRangeForCNFExpr(tc.sctx, queryExpr, pruner, fullRange(len(lessThan.data))) + require.True(t, equalPartitionRangeOR(result, partitionRangeOR{{0, 1}})) queryExpr = tc.expr("d > '2018-03-08 00:00:00'") - result = partitionRangeForCNFExpr(tc.sctx, queryExpr, prunner, fullRange(len(lessThan.data))) - c.Assert(equalPartitionRangeOR(result, partitionRangeOR{}), IsTrue) + result = partitionRangeForCNFExpr(tc.sctx, queryExpr, pruner, fullRange(len(lessThan.data))) + require.True(t, equalPartitionRangeOR(result, partitionRangeOR{})) // For the following case: // CREATE TABLE quarterly_report_status ( @@ -69,27 +61,24 @@ func (s *testPartitionPruningSuite) TestCanBePrune(c *C) { // PARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2010-01-01 00:00:00')), // PARTITION p3 VALUES LESS THAN (MAXVALUE) // ); - tc = prepareTestCtx(c, - "create table t (report_updated timestamp)", - "unix_timestamp(report_updated)", - ) + tc = prepareTestCtx(t, "create table t (report_updated timestamp)", "unix_timestamp(report_updated)") lessThan = lessThanDataInt{data: []int64{1199145600, 1207008000, 1262304000, 0}, maxvalue: true} - prunner = &rangePruner{lessThan, tc.col, tc.fn, monotoneModeStrict} + pruner = &rangePruner{lessThan, tc.col, tc.fn, monotoneModeStrict} queryExpr = tc.expr("report_updated > '2008-05-01 00:00:00'") - result = partitionRangeForCNFExpr(tc.sctx, queryExpr, prunner, fullRange(len(lessThan.data))) - c.Assert(equalPartitionRangeOR(result, partitionRangeOR{{2, 4}}), IsTrue) + result = partitionRangeForCNFExpr(tc.sctx, queryExpr, pruner, fullRange(len(lessThan.data))) + require.True(t, equalPartitionRangeOR(result, partitionRangeOR{{2, 4}})) queryExpr = tc.expr("report_updated > unix_timestamp('2008-05-01 00:00:00')") - partitionRangeForCNFExpr(tc.sctx, queryExpr, prunner, fullRange(len(lessThan.data))) + partitionRangeForCNFExpr(tc.sctx, queryExpr, pruner, fullRange(len(lessThan.data))) // TODO: Uncomment the check after fixing issue https://github.com/pingcap/tidb/issues/12028 - // c.Assert(equalPartitionRangeOR(result, partitionRangeOR{{2, 4}}), IsTrue) + // require.True(t, equalPartitionRangeOR(result, partitionRangeOR{{2, 4}})) // report_updated > unix_timestamp('2008-05-01 00:00:00') is converted to gt(t.t.report_updated, ) // Because unix_timestamp('2008-05-01 00:00:00') is fold to constant int 1564761600, and compare it with timestamp (report_updated) // need to convert 1564761600 to a timestamp, during that step, an error happen and the result is set to } -func (s *testPartitionPruningSuite) TestPruneUseBinarySearch(c *C) { +func TestPruneUseBinarySearch(t *testing.T) { lessThan := lessThanDataInt{data: []int64{4, 7, 11, 14, 17, 0}, maxvalue: true} cases := []struct { input dataForPrune @@ -122,13 +111,13 @@ func (s *testPartitionPruningSuite) TestPruneUseBinarySearch(c *C) { for i, ca := range cases { start, end := pruneUseBinarySearch(lessThan, ca.input, false) - c.Assert(ca.result.start, Equals, start, Commentf("fail = %d", i)) - c.Assert(ca.result.end, Equals, end, Commentf("fail = %d", i)) + require.Equalf(t, ca.result.start, start, "fail = %d", i) + require.Equalf(t, ca.result.end, end, "fail = %d", i) } } type testCtx struct { - c *C + require *require.Assertions sctx sessionctx.Context schema *expression.Schema columns []*expression.Column @@ -137,21 +126,21 @@ type testCtx struct { fn *expression.ScalarFunction } -func prepareTestCtx(c *C, createTable string, partitionExpr string) *testCtx { +func prepareTestCtx(t *testing.T, createTable string, partitionExpr string) *testCtx { p := parser.New() stmt, err := p.ParseOneStmt(createTable, "", "") - c.Assert(err, IsNil) + require.NoError(t, err) sctx := mock.NewContext() tblInfo, err := ddl.BuildTableInfoFromAST(stmt.(*ast.CreateTableStmt)) - c.Assert(err, IsNil) + require.NoError(t, err) columns, names, err := expression.ColumnInfos2ColumnsAndNames(sctx, model.NewCIStr("t"), tblInfo.Name, tblInfo.Cols(), tblInfo) - c.Assert(err, IsNil) + require.NoError(t, err) schema := expression.NewSchema(columns...) col, fn, _, err := makePartitionByFnCol(sctx, columns, names, partitionExpr) - c.Assert(err, IsNil) + require.NoError(t, err) return &testCtx{ - c: c, + require: require.New(t), sctx: sctx, schema: schema, columns: columns, @@ -163,15 +152,12 @@ func prepareTestCtx(c *C, createTable string, partitionExpr string) *testCtx { func (tc *testCtx) expr(expr string) []expression.Expression { res, err := expression.ParseSimpleExprsWithNames(tc.sctx, expr, tc.schema, tc.names) - tc.c.Assert(err, IsNil) + tc.require.NoError(err) return res } -func (s *testPartitionPruningSuite) TestPartitionRangeForExpr(c *C) { - tc := prepareTestCtx(c, - "create table t (a int)", - "a", - ) +func TestPartitionRangeForExpr(t *testing.T) { + tc := prepareTestCtx(t, "create table t (a int)", "a") lessThan := lessThanDataInt{data: []int64{4, 7, 11, 14, 17, 0}, maxvalue: true} prunner := &rangePruner{lessThan, tc.columns[0], nil, monotoneModeInvalid} cases := []struct { @@ -194,10 +180,10 @@ func (s *testPartitionPruningSuite) TestPartitionRangeForExpr(c *C) { for _, ca := range cases { expr, err := expression.ParseSimpleExprsWithNames(tc.sctx, ca.input, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) result := fullRange(lessThan.length()) result = partitionRangeForExpr(tc.sctx, expr[0], prunner, result) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("unexpected:", ca.input)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "unexpected: %v", ca.input) } } @@ -213,7 +199,7 @@ func equalPartitionRangeOR(x, y partitionRangeOR) bool { return true } -func (s *testPartitionPruningSuite) TestPartitionRangeOperation(c *C) { +func TestPartitionRangeOperation(t *testing.T) { testIntersectionRange := []struct { input1 partitionRangeOR input2 partitionRange @@ -231,7 +217,7 @@ func (s *testPartitionPruningSuite) TestPartitionRangeOperation(c *C) { } for i, ca := range testIntersectionRange { result := ca.input1.intersectionRange(ca.input2.start, ca.input2.end) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("failed %d", i)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "fail = %d", i) } testIntersection := []struct { @@ -251,7 +237,7 @@ func (s *testPartitionPruningSuite) TestPartitionRangeOperation(c *C) { } for i, ca := range testIntersection { result := ca.input1.intersection(ca.input2) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("failed %d", i)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "fail = %d", i) } testUnion := []struct { @@ -271,24 +257,21 @@ func (s *testPartitionPruningSuite) TestPartitionRangeOperation(c *C) { } for i, ca := range testUnion { result := ca.input1.union(ca.input2) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("failed %d", i)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "fail = %d", i) } } -func (s *testPartitionPruningSuite) TestPartitionRangePrunner2VarChar(c *C) { - tc := prepareTestCtx(c, - "create table t (a varchar(32))", - "a", - ) +func TestPartitionRangePrunner2VarChar(t *testing.T) { + tc := prepareTestCtx(t, "create table t (a varchar(32))", "a") lessThanDataInt := []string{"'c'", "'f'", "'h'", "'l'", "'t'"} lessThan := make([]expression.Expression, len(lessThanDataInt)+1) // +1 for maxvalue for i, str := range lessThanDataInt { tmp, err := expression.ParseSimpleExprsWithNames(tc.sctx, str, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) lessThan[i] = tmp[0] } - prunner := &rangeColumnsPruner{lessThan, tc.columns[0], true} + pruner := &rangeColumnsPruner{lessThan, tc.columns[0], true} cases := []struct { input string result partitionRangeOR @@ -310,17 +293,15 @@ func (s *testPartitionPruningSuite) TestPartitionRangePrunner2VarChar(c *C) { for _, ca := range cases { expr, err := expression.ParseSimpleExprsWithNames(tc.sctx, ca.input, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) result := fullRange(len(lessThan)) - result = partitionRangeForExpr(tc.sctx, expr[0], prunner, result) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("unexpected:", ca.input)) + result = partitionRangeForExpr(tc.sctx, expr[0], pruner, result) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "unexpected: %v", ca.input) } } -func (s *testPartitionPruningSuite) TestPartitionRangePrunner2CharWithCollation(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tc := prepareTestCtx(c, +func TestPartitionRangePrunner2CharWithCollation(t *testing.T) { + tc := prepareTestCtx(t, "create table t (a char(32) collate utf8mb4_unicode_ci)", "a", ) @@ -328,7 +309,7 @@ func (s *testPartitionPruningSuite) TestPartitionRangePrunner2CharWithCollation( lessThan := make([]expression.Expression, len(lessThanDataInt)+1) // +1 for maxvalue for i, str := range lessThanDataInt { tmp, err := expression.ParseSimpleExprsWithNames(tc.sctx, str, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) lessThan[i] = tmp[0] } @@ -356,15 +337,15 @@ func (s *testPartitionPruningSuite) TestPartitionRangePrunner2CharWithCollation( for _, ca := range cases { expr, err := expression.ParseSimpleExprsWithNames(tc.sctx, ca.input, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) result := fullRange(len(lessThan)) result = partitionRangeForExpr(tc.sctx, expr[0], prunner, result) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("unexpected:", ca.input)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "unexpected: %v", ca.input) } } -func (s *testPartitionPruningSuite) TestPartitionRangePrunner2Date(c *C) { - tc := prepareTestCtx(c, +func TestPartitionRangePrunner2Date(t *testing.T) { + tc := prepareTestCtx(t, "create table t (a date)", "a", ) @@ -378,7 +359,7 @@ func (s *testPartitionPruningSuite) TestPartitionRangePrunner2Date(c *C) { lessThan := make([]expression.Expression, len(lessThanDataInt)) for i, str := range lessThanDataInt { tmp, err := expression.ParseSimpleExprsWithNames(tc.sctx, str, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) lessThan[i] = tmp[0] } @@ -403,9 +384,9 @@ func (s *testPartitionPruningSuite) TestPartitionRangePrunner2Date(c *C) { for _, ca := range cases { expr, err := expression.ParseSimpleExprsWithNames(tc.sctx, ca.input, tc.schema, tc.names) - c.Assert(err, IsNil) + require.NoError(t, err) result := fullRange(len(lessThan)) result = partitionRangeForExpr(tc.sctx, expr[0], prunner, result) - c.Assert(equalPartitionRangeOR(ca.result, result), IsTrue, Commentf("unexpected:", ca.input)) + require.Truef(t, equalPartitionRangeOR(ca.result, result), "unexpected: %v", ca.input) } } diff --git a/planner/core/pb_to_plan.go b/planner/core/pb_to_plan.go index 661ea3fb16f62..f59cbb1c2b8c2 100644 --- a/planner/core/pb_to_plan.go +++ b/planner/core/pb_to_plan.go @@ -79,7 +79,7 @@ func (b *PBPlanBuilder) pbToPhysicalPlan(e *tipb.Executor) (p PhysicalPlan, err p, err = b.pbToKill(e) default: // TODO: Support other types. - err = errors.Errorf("this exec type %v doesn't support yet.", e.GetTp()) + err = errors.Errorf("this exec type %v doesn't support yet", e.GetTp()) } return p, err } diff --git a/planner/core/physical_plan_test.go b/planner/core/physical_plan_test.go index 1b3d13c02cc03..21e810f7c1ccc 100644 --- a/planner/core/physical_plan_test.go +++ b/planner/core/physical_plan_test.go @@ -18,8 +18,9 @@ import ( "context" "fmt" "math" + "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" @@ -31,103 +32,51 @@ import ( "github.com/pingcap/tidb/planner" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPlanSuite{}) -var _ = SerialSuites(&testPlanSerialSuite{}) +func TestDAGPlanBuilderSimpleCase(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -type testPlanSuiteBase struct { - *parser.Parser - is infoschema.InfoSchema -} - -func (s *testPlanSuiteBase) SetUpSuite(c *C) { - s.is = infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) - s.Parser = parser.New() - s.Parser.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) -} - -type testPlanSerialSuite struct { - testPlanSuiteBase -} - -type testPlanSuite struct { - testPlanSuiteBase - - testData testutil.TestData -} - -func (s *testPlanSuite) SetUpSuite(c *C) { - s.testPlanSuiteBase.SetUpSuite(c) - - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "plan_suite") - c.Assert(err, IsNil) -} - -func (s *testPlanSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testPlanSuite) TestDAGPlanBuilderSimpleCase(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set tidb_opt_limit_push_down_threshold=0") - c.Assert(err, IsNil) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_opt_limit_push_down_threshold=0") var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - - err = se.NewTxn(context.Background()) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case: %v, sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + require.NoError(t, tk.Session().NewTxn(context.Background())) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestAnalyzeBuildSucc(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - sctx := se.(sessionctx.Context) - _, err = se.Execute(context.Background(), "create table t(a int)") - c.Assert(err, IsNil) +func TestAnalyzeBuildSucc(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int)") tests := []struct { sql string succ bool @@ -159,43 +108,37 @@ func (s *testPlanSuite) TestAnalyzeBuildSucc(c *C) { statsVer: 1, }, } + + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range tests { - comment := Commentf("The %v-th test failed", i) - _, err := se.Execute(context.Background(), fmt.Sprintf("set @@tidb_analyze_version=%v", tt.statsVer)) - c.Assert(err, IsNil) + comment := fmt.Sprintf("The %v-th test failed", i) + tk.MustExec(fmt.Sprintf("set @@tidb_analyze_version=%v", tt.statsVer)) - stmt, err := s.ParseOneStmt(tt.sql, "", "") + stmt, err := p.ParseOneStmt(tt.sql, "", "") if tt.succ { - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) } else if err != nil { continue } - err = core.Preprocess(se, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) - _, _, err = planner.Optimize(context.Background(), sctx, stmt, s.is) + err = core.Preprocess(tk.Session(), stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err) + _, _, err = planner.Optimize(context.Background(), tk.Session(), stmt, is) if tt.succ { - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) } else { - c.Assert(err, NotNil, comment) + require.Error(t, err, comment) } } } -func (s *testPlanSuite) TestAnalyzeSetRate(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - sctx := se.(sessionctx.Context) - _, err = se.Execute(context.Background(), "create table t(a int)") - c.Assert(err, IsNil) +func TestAnalyzeSetRate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int)") tests := []struct { sql string rate float64 @@ -213,35 +156,30 @@ func (s *testPlanSuite) TestAnalyzeSetRate(c *C) { rate: -1, }, } + + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range tests { - comment := Commentf("The %v-th test failed", i) - c.Assert(err, IsNil) - - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) - err = core.Preprocess(se, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.Background(), sctx, stmt, s.is) - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("The %v-th test failed", i) + stmt, err := p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + + err = core.Preprocess(tk.Session(), stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err, comment) + p, _, err := planner.Optimize(context.Background(), tk.Session(), stmt, is) + require.NoError(t, err, comment) ana := p.(*core.Analyze) - c.Assert(math.Float64frombits(ana.Opts[ast.AnalyzeOptSampleRate]), Equals, tt.rate) + require.Equal(t, tt.rate, math.Float64frombits(ana.Opts[ast.AnalyzeOptSampleRate])) } } -func (s *testPlanSuite) TestDAGPlanBuilderJoin(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - ctx := se.(sessionctx.Context) - sessionVars := ctx.GetSessionVars() +func TestDAGPlanBuilderJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + sessionVars := tk.Session().GetSessionVars() sessionVars.ExecutorConcurrency = 4 sessionVars.SetDistSQLScanConcurrency(15) sessionVars.SetHashJoinConcurrency(5) @@ -251,38 +189,34 @@ func (s *testPlanSuite) TestDAGPlanBuilderJoin(c *C) { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestDAGPlanBuilderSubquery(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set sql_mode='STRICT_TRANS_TABLES'") - c.Assert(err, IsNil) // disable only full group by - ctx := se.(sessionctx.Context) - sessionVars := ctx.GetSessionVars() +func TestDAGPlanBuilderSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only full group by + sessionVars := tk.Session().GetSessionVars() sessionVars.SetHashAggFinalConcurrency(1) sessionVars.SetHashAggPartialConcurrency(1) sessionVars.SetHashJoinConcurrency(5) @@ -293,69 +227,64 @@ func (s *testPlanSuite) TestDAGPlanBuilderSubquery(c *C) { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, Commentf("for %s", tt)) + require.Equal(t, output[i].Best, core.ToString(p), fmt.Sprintf("input: %s", tt)) } } -func (s *testPlanSuite) TestDAGPlanTopN(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestDAGPlanTopN(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestDAGPlanBuilderBasePhysicalPlan(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) +func TestDAGPlanBuilderBasePhysicalPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + se, err := session.CreateSession4Test(store) + require.NoError(t, err) _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) + require.NoError(t, err) var input []string var output []struct { @@ -363,117 +292,103 @@ func (s *testPlanSuite) TestDAGPlanBuilderBasePhysicalPlan(c *C) { Best string Hints string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - - err = core.Preprocess(se, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + + err = core.Preprocess(se, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), se, stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Best, Commentf("for %s", tt)) - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, Commentf("for %s", tt)) + require.Equal(t, output[i].Best, core.ToString(p), fmt.Sprintf("input: %s", tt)) + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), fmt.Sprintf("input: %s", tt)) } } -func (s *testPlanSuite) TestDAGPlanBuilderUnion(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestDAGPlanBuilderUnion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestDAGPlanBuilderUnionScan(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestDAGPlanBuilderUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Best string } + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + require.NoError(t, tk.Session().NewTxn(context.Background())) - err = se.NewTxn(context.Background()) - c.Assert(err, IsNil) // Make txn not read only. - txn, err := se.Txn(true) - c.Assert(err, IsNil) + txn, err := tk.Session().Txn(true) + require.NoError(t, err) err = txn.Set(kv.Key("AAA"), []byte("BBB")) - c.Assert(err, IsNil) - se.StmtCommit() - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + tk.Session().StmtCommit() + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, Commentf("for %s", tt)) + require.Equal(t, output[i].Best, core.ToString(p), fmt.Sprintf("input: %s", tt)) } } -func (s *testPlanSuite) TestDAGPlanBuilderAgg(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set sql_mode='STRICT_TRANS_TABLES'") - c.Assert(err, IsNil) // disable only full group by - ctx := se.(sessionctx.Context) - sessionVars := ctx.GetSessionVars() +func TestDAGPlanBuilderAgg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only full group by + sessionVars := tk.Session().GetSessionVars() sessionVars.SetHashAggFinalConcurrency(1) sessionVars.SetHashAggPartialConcurrency(1) sessionVars.SetDistSQLScanConcurrency(15) @@ -484,96 +399,91 @@ func (s *testPlanSuite) TestDAGPlanBuilderAgg(c *C) { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, Commentf("for %s", tt)) + require.Equal(t, output[i].Best, core.ToString(p), fmt.Sprintf("input: %s", tt)) } } -func (s *testPlanSuite) TestRefine(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestRefine(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - sc := se.(sessionctx.Context).GetSessionVars().StmtCtx + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + sc := tk.Session().GetSessionVars().StmtCtx sc.IgnoreTruncate = false - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestAggEliminator(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set tidb_opt_limit_push_down_threshold=0") - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "set sql_mode='STRICT_TRANS_TABLES'") - c.Assert(err, IsNil) // disable only full group by +func TestAggEliminator(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_opt_limit_push_down_threshold=0") + tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'") // disable only full group by var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - comment := Commentf("for %s", tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - sc := se.(sessionctx.Context).GetSessionVars().StmtCtx + comment := fmt.Sprintf("input: %s", tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + sc := tk.Session().GetSessionVars().StmtCtx sc.IgnoreTruncate = false - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, Commentf("for %s", tt)) + require.Equal(t, output[i].Best, core.ToString(p), fmt.Sprintf("input: %s", tt)) } } -func (s *testPlanSuite) TestINMJHint(c *C) { +func TestINMJHint(t *testing.T) { var ( input []string output []struct { @@ -582,14 +492,11 @@ func (s *testPlanSuite) TestINMJHint(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int primary key, b int not null)") @@ -598,17 +505,17 @@ func (s *testPlanSuite) TestINMJHint(c *C) { tk.MustExec("insert into t2 values(1,1),(2,1)") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Sort().Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestEliminateMaxOneRow(c *C) { +func TestEliminateMaxOneRow(t *testing.T) { var ( input []string output []struct { @@ -617,14 +524,11 @@ func (s *testPlanSuite) TestEliminateMaxOneRow(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1;") tk.MustExec("drop table if exists t2;") @@ -634,10 +538,10 @@ func (s *testPlanSuite) TestEliminateMaxOneRow(c *C) { tk.MustExec("create table t3(a int(11) DEFAULT NULL, b int(11) DEFAULT NULL, c int(11) DEFAULT NULL, UNIQUE KEY idx_abc (a, b, c))") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Check(testkit.Rows(output[i].Result...)) @@ -653,65 +557,57 @@ func (store overrideStore) GetClient() kv.Client { type overrideClient struct{ kv.Client } -func (cli overrideClient) IsRequestTypeSupported(reqType, subType int64) bool { +func (cli overrideClient) IsRequestTypeSupported(_, _ int64) bool { return false } -func (s *testPlanSuite) TestRequestTypeSupportedOff(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() +func TestRequestTypeSupportedOff(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() se, err := session.CreateSession4Test(overrideStore{store}) - c.Assert(err, IsNil) + require.NoError(t, err) _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) + require.NoError(t, err) sql := "select * from t where a in (1, 10, 20)" expect := "TableReader(Table(t))->Sel([in(test.t.a, 1, 10, 20)])" - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - c.Assert(core.ToString(p), Equals, expect, Commentf("for %s", sql)) + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + stmt, err := parser.New().ParseOneStmt(sql, "", "") + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), se, stmt, is) + require.NoError(t, err) + require.Equal(t, expect, core.ToString(p), fmt.Sprintf("sql: %s", sql)) } -func (s *testPlanSuite) TestIndexJoinUnionScan(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIndexJoinUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("create table t (a int primary key, b int, index idx(a))") + tk.MustExec("create table tt (a int primary key) partition by range (a) (partition p0 values less than (100), partition p1 values less than (200))") + tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) + var input [][]string var output []struct { SQL []string Plan []string } - tk.MustExec("create table t (a int primary key, b int, index idx(a))") - tk.MustExec("create table tt (a int primary key) partition by range (a) (partition p0 values less than (100), partition p1 values less than (200))") - - tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) - s.testData.GetTestCases(c, &input, &output) for i, ts := range input { tk.MustExec("begin") for j, tt := range ts { if j != len(ts)-1 { tk.MustExec(tt) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts if j == len(ts)-1 { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) } }) if j == len(ts)-1 { @@ -722,38 +618,34 @@ func (s *testPlanSuite) TestIndexJoinUnionScan(c *C) { } } -func (s *testPlanSuite) TestMergeJoinUnionScan(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - +func TestMergeJoinUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("create table t1 (c_int int, c_str varchar(40), primary key (c_int))") + tk.MustExec("create table t2 (c_int int, c_str varchar(40), primary key (c_int))") + tk.MustExec("insert into t1 (`c_int`, `c_str`) values (11, 'keen williamson'), (10, 'gracious hermann')") + tk.MustExec("insert into t2 (`c_int`, `c_str`) values (10, 'gracious hermann')") + var input [][]string var output []struct { SQL []string Plan []string } - tk.MustExec("create table t1 (c_int int, c_str varchar(40), primary key (c_int))") - tk.MustExec("create table t2 (c_int int, c_str varchar(40), primary key (c_int))") - tk.MustExec("insert into t1 (`c_int`, `c_str`) values (11, 'keen williamson'), (10, 'gracious hermann')") - tk.MustExec("insert into t2 (`c_int`, `c_str`) values (10, 'gracious hermann')") + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) - s.testData.GetTestCases(c, &input, &output) for i, ts := range input { tk.MustExec("begin") for j, tt := range ts { if j != len(ts)-1 { tk.MustExec(tt) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts if j == len(ts)-1 { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) } }) if j == len(ts)-1 { @@ -764,18 +656,13 @@ func (s *testPlanSuite) TestMergeJoinUnionScan(c *C) { } } -func (s *testPlanSuite) TestDoSubquery(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestDoSubQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tests := []struct { sql string best string @@ -785,161 +672,145 @@ func (s *testPlanSuite) TestDoSubquery(c *C) { best: "LeftHashJoin{Dual->PointGet(Handle(t.a)1)}->Projection", }, } + + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for _, tt := range tests { - comment := Commentf("for %s", tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - c.Assert(core.ToString(p), Equals, tt.best, comment) + comment := fmt.Sprintf("for %s", tt.sql) + stmt, err := p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + require.Equal(t, tt.best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestIndexLookupCartesianJoin(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) - sql := "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2" - stmt, err := s.ParseOneStmt(sql, "", "") - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - c.Assert(core.ToString(p), Equals, "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}") - warnings := se.GetSessionVars().StmtCtx.GetWarnings() +func TestIndexLookupCartesianJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + stmt, err := parser.New().ParseOneStmt("select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2", "", "") + require.NoError(t, err) + + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + require.Equal(t, "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}", core.ToString(p)) + + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() lastWarn := warnings[len(warnings)-1] err = core.ErrInternal.GenWithStack("TIDB_INLJ hint is inapplicable without column equal ON condition") - c.Assert(terror.ErrorEqual(err, lastWarn.Err), IsTrue) + require.True(t, terror.ErrorEqual(err, lastWarn.Err)) } -func (s *testPlanSuite) TestSemiJoinToInner(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestSemiJoinToInner(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, tt := range input { - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best) + require.Equal(t, output[i].Best, core.ToString(p)) } } -func (s *testPlanSuite) TestUnmatchedTableInHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestUnmatchedTableInHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Warning string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, test := range input { - se.GetSessionVars().StmtCtx.SetWarnings(nil) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil) - _, _, err = planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - warnings := se.GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err) + _, _, err = planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + testdata.OnRecord(func() { output[i].SQL = test if len(warnings) > 0 { output[i].Warning = warnings[0].Err.Error() } }) if output[i].Warning == "" { - c.Assert(len(warnings), Equals, 0) + require.Len(t, warnings, 0) } else { - c.Assert(len(warnings), Equals, 1) - c.Assert(warnings[0].Level, Equals, stmtctx.WarnLevelWarning) - c.Assert(warnings[0].Err.Error(), Equals, output[i].Warning) + require.Len(t, warnings, 1) + require.Equal(t, stmtctx.WarnLevelWarning, warnings[0].Level) + require.Equal(t, output[i].Warning, warnings[0].Err.Error()) } } } -func (s *testPlanSuite) TestHintScope(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestHintScope(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, test) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(context.Background(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(context.Background(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = test output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best) - - warnings := se.GetSessionVars().StmtCtx.GetWarnings() - c.Assert(warnings, HasLen, 0, comment) + require.Equal(t, output[i].Best, core.ToString(p)) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + require.Len(t, warnings, 0, comment) } } -func (s *testPlanSuite) TestJoinHints(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestJoinHints(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { @@ -948,19 +819,23 @@ func (s *testPlanSuite) TestJoinHints(c *C) { Warning string Hints string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.Background() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql:%s", i, test) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) - se.GetSessionVars().StmtCtx.SetWarnings(nil) - p, _, err := planner.Optimize(ctx, se, stmt, s.is) - c.Assert(err, IsNil) - warnings := se.GetSessionVars().StmtCtx.GetWarnings() + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = test output[i].Best = core.ToString(p) if len(warnings) > 0 { @@ -968,32 +843,26 @@ func (s *testPlanSuite) TestJoinHints(c *C) { } output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Best) + require.Equal(t, output[i].Best, core.ToString(p)) if output[i].Warning == "" { - c.Assert(len(warnings), Equals, 0) + require.Len(t, warnings, 0) } else { - c.Assert(len(warnings), Equals, 1, Commentf("%v", warnings)) - c.Assert(warnings[0].Level, Equals, stmtctx.WarnLevelWarning) - c.Assert(warnings[0].Err.Error(), Equals, output[i].Warning) + require.Len(t, warnings, 1, fmt.Sprintf("%v", warnings)) + require.Equal(t, stmtctx.WarnLevelWarning, warnings[0].Level) + require.Equal(t, output[i].Warning, warnings[0].Err.Error()) } - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, comment) + + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), comment) } } -func (s *testPlanSuite) TestAggregationHints(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestAggregationHints(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") - sessionVars := se.(sessionctx.Context).GetSessionVars() + sessionVars := tk.Session().GetSessionVars() sessionVars.SetHashAggFinalConcurrency(1) sessionVars.SetHashAggPartialConcurrency(1) @@ -1006,47 +875,45 @@ func (s *testPlanSuite) TestAggregationHints(c *C) { Best string Warning string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.Background() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - se.GetSessionVars().StmtCtx.SetWarnings(nil) - se.GetSessionVars().AllowAggPushDown = test.AggPushDown + comment := fmt.Sprintf("case: %v sql: %v", i, test) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + tk.Session().GetSessionVars().AllowAggPushDown = test.AggPushDown - stmt, err := s.ParseOneStmt(test.SQL, "", "") - c.Assert(err, IsNil, comment) + stmt, err := p.ParseOneStmt(test.SQL, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(ctx, se, stmt, s.is) - c.Assert(err, IsNil) - warnings := se.GetSessionVars().StmtCtx.GetWarnings() + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = test.SQL output[i].Best = core.ToString(p) if len(warnings) > 0 { output[i].Warning = warnings[0].Err.Error() } }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) if output[i].Warning == "" { - c.Assert(len(warnings), Equals, 0, comment) + require.Len(t, warnings, 0) } else { - c.Assert(len(warnings), Equals, 1, comment) - c.Assert(warnings[0].Level, Equals, stmtctx.WarnLevelWarning, comment) - c.Assert(warnings[0].Err.Error(), Equals, output[i].Warning, comment) + require.Len(t, warnings, 1, fmt.Sprintf("%v", warnings)) + require.Equal(t, stmtctx.WarnLevelWarning, warnings[0].Level) + require.Equal(t, output[i].Warning, warnings[0].Err.Error()) } } } -func (s *testPlanSuite) TestExplainJoinHints(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestExplainJoinHints(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, key(b), key(c))") @@ -1058,15 +925,10 @@ func (s *testPlanSuite) TestExplainJoinHints(c *C) { )) } -func (s *testPlanSuite) TestAggToCopHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestAggToCopHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists ta") tk.MustExec("create table ta(a int, b int, index(a))") @@ -1079,55 +941,52 @@ func (s *testPlanSuite) TestAggToCopHint(c *C) { Warning string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.Background() - is := domain.GetDomain(tk.Se).InfoSchema() + is := domain.GetDomain(tk.Session()).InfoSchema() + p := parser.New() for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql:%s", i, test) + testdata.OnRecord(func() { output[i].SQL = test }) - c.Assert(test, Equals, output[i].SQL, comment) + require.Equal(t, output[i].SQL, test, comment) - tk.Se.GetSessionVars().StmtCtx.SetWarnings(nil) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil, comment) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(ctx, tk.Se, stmt, is) - c.Assert(err, IsNil, comment) + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err, comment) planString := core.ToString(p) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].Best = planString }) - c.Assert(planString, Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, planString, comment) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + testdata.OnRecord(func() { if len(warnings) > 0 { output[i].Warning = warnings[0].Err.Error() } }) if output[i].Warning == "" { - c.Assert(len(warnings), Equals, 0, comment) + require.Len(t, warnings, 0) } else { - c.Assert(len(warnings), Equals, 1, comment) - c.Assert(warnings[0].Level, Equals, stmtctx.WarnLevelWarning, comment) - c.Assert(warnings[0].Err.Error(), Equals, output[i].Warning, comment) + require.Len(t, warnings, 1, fmt.Sprintf("%v", warnings)) + require.Equal(t, stmtctx.WarnLevelWarning, warnings[0].Level) + require.Equal(t, output[i].Warning, warnings[0].Err.Error()) } } } -func (s *testPlanSuite) TestLimitToCopHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestLimitToCopHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tn") tk.MustExec("create table tn(a int, b int, c int, d int, key (a, b, c, d))") @@ -1142,18 +1001,19 @@ func (s *testPlanSuite) TestLimitToCopHint(c *C) { } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) - comment := Commentf("case:%v sql:%s", i, ts) - warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql:%s", i, ts) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + testdata.OnRecord(func() { if len(warnings) > 0 { output[i].Warning = make([]string, len(warnings)) for j, warning := range warnings { @@ -1162,19 +1022,18 @@ func (s *testPlanSuite) TestLimitToCopHint(c *C) { } }) if len(output[i].Warning) == 0 { - c.Assert(len(warnings), Equals, 0, comment) + require.Len(t, warnings, 0) } else { - c.Assert(len(warnings), Equals, len(output[i].Warning), comment) + require.Len(t, warnings, len(output[i].Warning), comment) for j, warning := range warnings { - c.Assert(warning.Level, Equals, stmtctx.WarnLevelWarning, comment) - c.Assert(warning.Err.Error(), Equals, output[i].Warning[j], comment) + require.Equal(t, stmtctx.WarnLevelWarning, warning.Level, comment) + require.Equal(t, output[i].Warning[j], warning.Err.Error(), comment) } } } } -func (s *testPlanSuite) TestPushdownDistinctEnable(c *C) { - defer testleak.AfterTest(c)() +func TestPushdownDistinctEnable(t *testing.T) { var ( input []string output []struct { @@ -1183,16 +1042,16 @@ func (s *testPlanSuite) TestPushdownDistinctEnable(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) vars := []string{ fmt.Sprintf("set @@session.%s = 1", variable.TiDBOptDistinctAggPushDown), "set session tidb_opt_agg_push_down = 1", } - s.doTestPushdownDistinct(c, vars, input, output) + doTestPushdownDistinct(t, vars, input, output) } -func (s *testPlanSuite) TestPushdownDistinctDisable(c *C) { - defer testleak.AfterTest(c)() +func TestPushdownDistinctDisable(t *testing.T) { var ( input []string output []struct { @@ -1202,15 +1061,16 @@ func (s *testPlanSuite) TestPushdownDistinctDisable(c *C) { } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) vars := []string{ fmt.Sprintf("set @@session.%s = 0", variable.TiDBOptDistinctAggPushDown), "set session tidb_opt_agg_push_down = 1", } - s.doTestPushdownDistinct(c, vars, input, output) + doTestPushdownDistinct(t, vars, input, output) } -func (s *testPlanSuite) TestPushdownDistinctEnableAggPushDownDisable(c *C) { +func TestPushdownDistinctEnableAggPushDownDisable(t *testing.T) { var ( input []string output []struct { @@ -1219,26 +1079,23 @@ func (s *testPlanSuite) TestPushdownDistinctEnableAggPushDownDisable(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) vars := []string{ fmt.Sprintf("set @@session.%s = 1", variable.TiDBOptDistinctAggPushDown), "set session tidb_opt_agg_push_down = 0", } - s.doTestPushdownDistinct(c, vars, input, output) + doTestPushdownDistinct(t, vars, input, output) } -func (s *testPlanSuite) doTestPushdownDistinct(c *C, vars, input []string, output []struct { +func doTestPushdownDistinct(t *testing.T, vars, input []string, output []struct { SQL string Plan []string Result []string }) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1272,17 +1129,17 @@ func (s *testPlanSuite) doTestPushdownDistinct(c *C, vars, input []string, outpu } for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Sort().Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestGroupConcatOrderby(c *C) { +func TestGroupConcatOrderby(t *testing.T) { var ( input []string output []struct { @@ -1291,14 +1148,11 @@ func (s *testPlanSuite) TestGroupConcatOrderby(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test;") tk.MustExec("create table test(id int, name int)") @@ -1317,28 +1171,22 @@ func (s *testPlanSuite) TestGroupConcatOrderby(c *C) { tk.MustExec(fmt.Sprintf("set session tidb_opt_agg_push_down = %v", 1)) for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestHintAlias(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestHintAlias(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tests := []struct { sql1 string @@ -1358,34 +1206,31 @@ func (s *testPlanSuite) TestHintAlias(c *C) { }, } ctx := context.TODO() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, tt := range tests { - comment := Commentf("case:%v sql1:%s sql2:%s", i, tt.sql1, tt.sql2) - stmt1, err := s.ParseOneStmt(tt.sql1, "", "") - c.Assert(err, IsNil, comment) - stmt2, err := s.ParseOneStmt(tt.sql2, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql1:%s sql2:%s", i, tt.sql1, tt.sql2) + stmt1, err := p.ParseOneStmt(tt.sql1, "", "") + require.NoError(t, err, comment) + stmt2, err := p.ParseOneStmt(tt.sql2, "", "") + require.NoError(t, err, comment) - p1, _, err := planner.Optimize(ctx, se, stmt1, s.is) - c.Assert(err, IsNil) - p2, _, err := planner.Optimize(ctx, se, stmt2, s.is) - c.Assert(err, IsNil) + p1, _, err := planner.Optimize(ctx, tk.Session(), stmt1, is) + require.NoError(t, err) + p2, _, err := planner.Optimize(ctx, tk.Session(), stmt2, is) + require.NoError(t, err) - c.Assert(core.ToString(p1), Equals, core.ToString(p2)) + require.Equal(t, core.ToString(p2), core.ToString(p1)) } } -func (s *testPlanSuite) TestIndexHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestIndexHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { @@ -1394,46 +1239,44 @@ func (s *testPlanSuite) TestIndexHint(c *C) { HasWarn bool Hints string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.Background() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - se.GetSessionVars().StmtCtx.SetWarnings(nil) + comment := fmt.Sprintf("case:%v sql:%s", i, test) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil, comment) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(ctx, se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = test output[i].Best = core.ToString(p) - output[i].HasWarn = len(se.GetSessionVars().StmtCtx.GetWarnings()) > 0 + output[i].HasWarn = len(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) > 0 output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) - warnings := se.GetSessionVars().StmtCtx.GetWarnings() + require.Equal(t, output[i].Best, core.ToString(p), comment) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() if output[i].HasWarn { - c.Assert(warnings, HasLen, 1, comment) + require.Len(t, warnings, 1, comment) } else { - c.Assert(warnings, HasLen, 0, comment) + require.Len(t, warnings, 0, comment) } - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, comment) + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), comment) } } -func (s *testPlanSuite) TestIndexMergeHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestIndexMergeHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { @@ -1442,47 +1285,45 @@ func (s *testPlanSuite) TestIndexMergeHint(c *C) { HasWarn bool Hints string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.Background() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, test := range input { - comment := Commentf("case:%v sql:%s", i, test) - se.GetSessionVars().StmtCtx.SetWarnings(nil) - stmt, err := s.ParseOneStmt(test, "", "") - c.Assert(err, IsNil, comment) - sctx := se.(sessionctx.Context) + comment := fmt.Sprintf("case:%v sql:%s", i, test) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) + sctx := tk.Session() err = executor.ResetContextOfStmt(sctx, stmt) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(ctx, se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = test output[i].Best = core.ToString(p) - output[i].HasWarn = len(se.GetSessionVars().StmtCtx.GetWarnings()) > 0 + output[i].HasWarn = len(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) > 0 output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) - warnings := se.GetSessionVars().StmtCtx.GetWarnings() + require.Equal(t, output[i].Best, core.ToString(p), comment) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() if output[i].HasWarn { - c.Assert(warnings, HasLen, 1, comment) + require.Len(t, warnings, 1, comment) } else { - c.Assert(warnings, HasLen, 0, comment) + require.Len(t, warnings, 0, comment) } - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, comment) + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), comment) } } -func (s *testPlanSuite) TestQueryBlockHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestQueryBlockHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") var input []string var output []struct { @@ -1490,44 +1331,38 @@ func (s *testPlanSuite) TestQueryBlockHint(c *C) { Plan string Hints string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) ctx := context.TODO() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, tt := range input { - comment := Commentf("case:%v sql: %s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(ctx, se, stmt, s.is) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = core.ToString(p) output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Plan, comment) - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, comment) + require.Equal(t, output[i].Plan, core.ToString(p), comment) + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), comment) } } -func (s *testPlanSuite) TestInlineProjection(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - ctx := context.Background() - _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `drop table if exists test.t1, test.t2;`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t1(a bigint, b bigint, index idx_a(a), index idx_b(b));`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t2(a bigint, b bigint, index idx_a(a), index idx_b(b));`) - c.Assert(err, IsNil) +func TestInlineProjection(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists test.t1, test.t2;`) + tk.MustExec(`create table test.t1(a bigint, b bigint, index idx_a(a), index idx_b(b));`) + tk.MustExec(`create table test.t2(a bigint, b bigint, index idx_a(a), index idx_b(b));`) var input []string var output []struct { @@ -1535,37 +1370,36 @@ func (s *testPlanSuite) TestInlineProjection(c *C) { Plan string Hints string } - is := domain.GetDomain(se).InfoSchema() - s.testData.GetTestCases(c, &input, &output) + is := domain.GetDomain(tk.Session()).InfoSchema() + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + + ctx := context.Background() + p := parser.New() + for i, tt := range input { - comment := Commentf("case:%v sql: %s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) - p, _, err := planner.Optimize(ctx, se, stmt, is) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = core.ToString(p) output[i].Hints = hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)) }) - c.Assert(core.ToString(p), Equals, output[i].Plan, comment) - c.Assert(hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), Equals, output[i].Hints, comment) + require.Equal(t, output[i].Plan, core.ToString(p), comment) + require.Equal(t, output[i].Hints, hint.RestoreOptimizerHints(core.GenHintsFromPhysicalPlan(p)), comment) } } -func (s *testPlanSuite) TestDAGPlanBuilderSplitAvg(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - _, err = se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestDAGPlanBuilderSplitAvg(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") tests := []struct { sql string plan string @@ -1580,37 +1414,40 @@ func (s *testPlanSuite) TestDAGPlanBuilderSplitAvg(c *C) { }, } + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for _, tt := range tests { - comment := Commentf("for %s", tt.sql) - stmt, err := s.ParseOneStmt(tt.sql, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("for %s", tt.sql) + stmt, err := p.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) - err = core.Preprocess(se, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: s.is})) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil, comment) + err = core.Preprocess(tk.Session(), stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err, comment) - c.Assert(core.ToString(p), Equals, tt.plan, comment) + require.Equal(t, tt.plan, core.ToString(p), comment) root, ok := p.(core.PhysicalPlan) if !ok { continue } - testDAGPlanBuilderSplitAvg(c, root) + testDAGPlanBuilderSplitAvg(t, root) } } -func testDAGPlanBuilderSplitAvg(c *C, root core.PhysicalPlan) { +func testDAGPlanBuilderSplitAvg(t *testing.T, root core.PhysicalPlan) { if p, ok := root.(*core.PhysicalTableReader); ok { if p.TablePlans != nil { baseAgg := p.TablePlans[len(p.TablePlans)-1] if agg, ok := baseAgg.(*core.PhysicalHashAgg); ok { for i, aggfunc := range agg.AggFuncs { - c.Assert(agg.Schema().Columns[i].RetType, Equals, aggfunc.RetTp) + require.Equal(t, aggfunc.RetTp, agg.Schema().Columns[i].RetType) } } if agg, ok := baseAgg.(*core.PhysicalStreamAgg); ok { for i, aggfunc := range agg.AggFuncs { - c.Assert(agg.Schema().Columns[i].RetType, Equals, aggfunc.RetTp) + require.Equal(t, aggfunc.RetTp, agg.Schema().Columns[i].RetType) } } } @@ -1621,141 +1458,122 @@ func testDAGPlanBuilderSplitAvg(c *C, root core.PhysicalPlan) { return } for _, son := range childs { - testDAGPlanBuilderSplitAvg(c, son) + testDAGPlanBuilderSplitAvg(t, son) } } -func (s *testPlanSuite) TestIndexJoinHint(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - ctx := context.Background() - _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `drop table if exists test.t1, test.t2, test.t;`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t1(a bigint, b bigint, index idx_a(a), index idx_b(b));`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t2(a bigint, b bigint, index idx_a(a), index idx_b(b));`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, "CREATE TABLE `t` ( `a` bigint(20) NOT NULL, `b` tinyint(1) DEFAULT NULL, `c` datetime DEFAULT NULL, `d` int(10) unsigned DEFAULT NULL, `e` varchar(20) DEFAULT NULL, `f` double DEFAULT NULL, `g` decimal(30,5) DEFAULT NULL, `h` float DEFAULT NULL, `i` date DEFAULT NULL, `j` timestamp NULL DEFAULT NULL, PRIMARY KEY (`a`), UNIQUE KEY `b` (`b`), KEY `c` (`c`,`d`,`e`), KEY `f` (`f`), KEY `g` (`g`,`h`), KEY `g_2` (`g`), UNIQUE KEY `g_3` (`g`), KEY `i` (`i`) );") - c.Assert(err, IsNil) +func TestIndexJoinHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists test.t1, test.t2, test.t;`) + tk.MustExec(`create table test.t1(a bigint, b bigint, index idx_a(a), index idx_b(b));`) + tk.MustExec(`create table test.t2(a bigint, b bigint, index idx_a(a), index idx_b(b));`) + tk.MustExec("CREATE TABLE `t` ( `a` bigint(20) NOT NULL, `b` tinyint(1) DEFAULT NULL, `c` datetime DEFAULT NULL, `d` int(10) unsigned DEFAULT NULL, `e` varchar(20) DEFAULT NULL, `f` double DEFAULT NULL, `g` decimal(30,5) DEFAULT NULL, `h` float DEFAULT NULL, `i` date DEFAULT NULL, `j` timestamp NULL DEFAULT NULL, PRIMARY KEY (`a`), UNIQUE KEY `b` (`b`), KEY `c` (`c`,`d`,`e`), KEY `f` (`f`), KEY `g` (`g`,`h`), KEY `g_2` (`g`), UNIQUE KEY `g_3` (`g`), KEY `i` (`i`) );") + var input []string var output []struct { SQL string Plan string } - is := domain.GetDomain(se).InfoSchema() - s.testData.GetTestCases(c, &input, &output) + + is := domain.GetDomain(tk.Session()).InfoSchema() + p := parser.New() + ctx := context.Background() + + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - comment := Commentf("case:%v sql: %s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - p, _, err := planner.Optimize(ctx, se, stmt, is) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Plan, comment) + require.Equal(t, output[i].Plan, core.ToString(p), comment) } } -func (s *testPlanSuite) TestDAGPlanBuilderWindow(c *C) { - defer testleak.AfterTest(c)() +func TestDAGPlanBuilderWindow(t *testing.T) { var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) vars := []string{ "set @@session.tidb_window_concurrency = 1", } - s.doTestDAGPlanBuilderWindow(c, vars, input, output) + doTestDAGPlanBuilderWindow(t, vars, input, output) } -func (s *testPlanSuite) TestDAGPlanBuilderWindowParallel(c *C) { - defer testleak.AfterTest(c)() +func TestDAGPlanBuilderWindowParallel(t *testing.T) { var input []string var output []struct { SQL string Best string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) vars := []string{ "set @@session.tidb_window_concurrency = 4", } - s.doTestDAGPlanBuilderWindow(c, vars, input, output) + doTestDAGPlanBuilderWindow(t, vars, input, output) } -func (s *testPlanSuite) TestTopNPushDownEmpty(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestTopNPushDownEmpty(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, index idx_a(a))") tk.MustQuery("select extract(day_hour from 'ziy') as res from t order by res limit 1").Check(testkit.Rows()) } -func (s *testPlanSuite) doTestDAGPlanBuilderWindow(c *C, vars, input []string, output []struct { +func doTestDAGPlanBuilderWindow(t *testing.T, vars, input []string, output []struct { SQL string Best string }) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - ctx := context.Background() - _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") for _, v := range vars { - _, err = se.Execute(ctx, v) - c.Assert(err, IsNil) + tk.MustExec(v) } + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, tt := range input { - comment := Commentf("case:%v sql:%s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - - err = se.NewTxn(context.Background()) - c.Assert(err, IsNil) - p, _, err := planner.Optimize(context.TODO(), se, stmt, s.is) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql:%s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + + err = tk.Session().NewTxn(context.Background()) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), tk.Session(), stmt, is) + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Best = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Best, comment) + require.Equal(t, output[i].Best, core.ToString(p), comment) } } -func (s *testPlanSuite) TestNominalSort(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestNominalSort(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") var input []string var output []struct { @@ -1768,88 +1586,65 @@ func (s *testPlanSuite) TestNominalSort(c *C) { tk.MustExec("insert into t values(1, 2)") tk.MustExec("insert into t values(2, 4)") tk.MustExec("insert into t values(3, 5)") - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestHintFromDiffDatabase(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - ctx := context.Background() - _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `drop table if exists test.t1`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t1(a bigint, index idx_a(a));`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.t2(a bigint, index idx_a(a));`) - c.Assert(err, IsNil) - - _, err = se.Execute(ctx, "drop database if exists test2") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, "create database test2") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, "use test2") - c.Assert(err, IsNil) +func TestHintFromDiffDatabase(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists test.t1`) + tk.MustExec(`create table test.t1(a bigint, index idx_a(a));`) + tk.MustExec(`create table test.t2(a bigint, index idx_a(a));`) + tk.MustExec("drop database if exists test2") + tk.MustExec("create database test2") + tk.MustExec("use test2") var input []string var output []struct { SQL string Plan string } - is := domain.GetDomain(se).InfoSchema() - s.testData.GetTestCases(c, &input, &output) + is := domain.GetDomain(tk.Session()).InfoSchema() + p := parser.New() + ctx := context.Background() + + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - comment := Commentf("case:%v sql: %s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) - p, _, err := planner.Optimize(ctx, se, stmt, is) - c.Assert(err, IsNil, comment) - s.testData.OnRecord(func() { + comment := fmt.Sprintf("case:%v sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) + p, _, err := planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err, comment) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = core.ToString(p) }) - c.Assert(core.ToString(p), Equals, output[i].Plan, comment) + require.Equal(t, output[i].Plan, core.ToString(p), comment) } } -func (s *testPlanSuite) TestNthPlanHintWithExplain(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() - se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - ctx := context.Background() - _, err = se.Execute(ctx, "use test") - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `drop table if exists test.tt`) - c.Assert(err, IsNil) - _, err = se.Execute(ctx, `create table test.tt (a int,b int, index(a), index(b));`) - c.Assert(err, IsNil) - - _, err = se.Execute(ctx, "insert into tt values (1, 1), (2, 2), (3, 4)") - c.Assert(err, IsNil) - +func TestNthPlanHintWithExplain(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists test.tt`) + tk.MustExec(`create table test.tt (a int,b int, index(a), index(b));`) + tk.MustExec("insert into tt values (1, 1), (2, 2), (3, 4)") tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) var input []string @@ -1857,23 +1652,24 @@ func (s *testPlanSuite) TestNthPlanHintWithExplain(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) }) tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) } - // This assert makes sure a query with or without nth_plan() hint output exactly the same plan(including plan ID). + // This assertion makes sure a query with or without nth_plan() hint output exactly the same plan(including plan ID). // The query below is the same as queries in the testdata except for nth_plan() hint. - // Currently its output is the same as the second test case in the testdata, which is `output[1]`. If this doesn't + // Currently, its output is the same as the second test case in the testdata, which is `output[1]`. If this doesn't // hold in the future, you may need to modify this. tk.MustQuery("explain format = 'brief' select * from test.tt where a=1 and b=1").Check(testkit.Rows(output[1].Plan...)) } -func (s *testPlanSuite) TestEnumIndex(c *C) { +func TestEnumIndex(t *testing.T) { var ( input []string output []struct { @@ -1882,31 +1678,28 @@ func (s *testPlanSuite) TestEnumIndex(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(e enum('c','b','a',''), index idx(e))") tk.MustExec("insert ignore into t values(0),(1),(2),(3),(4);") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format='brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Sort().Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestIssue27233(c *C) { +func TestIssue27233(t *testing.T) { var ( input []string output []struct { @@ -1915,38 +1708,31 @@ func (s *testPlanSuite) TestIssue27233(c *C) { Result []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE `PK_S_MULTI_31` (\n `COL1` tinyint(45) NOT NULL,\n `COL2` tinyint(45) NOT NULL,\n PRIMARY KEY (`COL1`,`COL2`) /*T![clustered_index] NONCLUSTERED */\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") tk.MustExec("insert into PK_S_MULTI_31 values(122,100),(124,-22),(124,34),(127,103);") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) - output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) + output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(ts).Sort().Rows()) }) tk.MustQuery("explain format='brief' " + ts).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(ts).Sort().Check(testkit.Rows(output[i].Result...)) } } -func (s *testPlanSuite) TestPossibleProperties(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestPossibleProperties(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists student, sc") tk.MustExec("create table student(id int primary key auto_increment, name varchar(4) not null)") @@ -1958,7 +1744,7 @@ func (s *testPlanSuite) TestPossibleProperties(c *C) { )) } -func (s *testPlanSuite) TestSelectionPartialPushDown(c *C) { +func TestSelectionPartialPushDown(t *testing.T) { var ( input []string output []struct { @@ -1966,29 +1752,26 @@ func (s *testPlanSuite) TestSelectionPartialPushDown(c *C) { Plan []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int as (a+1) virtual)") tk.MustExec("create table t2(a int, b int as (a+1) virtual, c int, key idx_a(a))") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) }) tk.MustQuery("explain format='brief' " + ts).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testPlanSuite) TestIssue28316(c *C) { +func TestIssue28316(t *testing.T) { var ( input []string output []struct { @@ -1996,22 +1779,84 @@ func (s *testPlanSuite) TestIssue28316(c *C) { Plan []string } ) - s.testData.GetTestCases(c, &input, &output) - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") for i, ts := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { + output[i].SQL = ts + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) + }) + tk.MustQuery("explain format='brief' " + ts).Check(testkit.Rows(output[i].Plan...)) + } +} + +func TestIssue30965(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t30965") + tk.MustExec("CREATE TABLE `t30965` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) GENERATED ALWAYS AS (`a` + 1) VIRTUAL, KEY `ib` (`b`));") + tk.MustExec("insert into t30965 (a,b,c) value(3,4,5);") + tk.MustQuery("select count(*) from t30965 where d = 2 and b = 4 and a = 3 and c = 5;").Check(testkit.Rows("0")) + tk.MustQuery("explain format = 'brief' select count(*) from t30965 where d = 2 and b = 4 and a = 3 and c = 5;").Check( + testkit.Rows( + "StreamAgg 1.00 root funcs:count(1)->Column#6", + "└─Selection 0.00 root eq(test.t30965.d, 2)", + " └─IndexLookUp 0.00 root ", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t30965, index:ib(b) range:[4,4], keep order:false, stats:pseudo", + " └─Selection(Probe) 0.00 cop[tikv] eq(test.t30965.a, 3), eq(test.t30965.c, 5)", + " └─TableRowIDScan 10.00 cop[tikv] table:t30965 keep order:false, stats:pseudo")) +} + +func TestMPPSinglePartitionType(t *testing.T) { + var ( + input []string + output []struct { + SQL string + Plan []string + } + ) + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists employee") + tk.MustExec("create table employee(empid int, deptid int, salary decimal(10,2))") + tk.MustExec("set tidb_enforce_mpp=1") + + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tblInfo := range db.Tables { + if tblInfo.Name.L == "employee" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + for i, ts := range input { + testdata.OnRecord(func() { + output[i].SQL = ts + }) + if strings.HasPrefix(ts, "set") { + tk.MustExec(ts) + continue + } + testdata.OnRecord(func() { output[i].SQL = ts - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief'" + ts).Rows()) }) tk.MustQuery("explain format='brief' " + ts).Check(testkit.Rows(output[i].Plan...)) } diff --git a/planner/core/physical_plan_trace_test.go b/planner/core/physical_plan_trace_test.go new file mode 100644 index 0000000000000..9988fb6cacfa9 --- /dev/null +++ b/planner/core/physical_plan_trace_test.go @@ -0,0 +1,120 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core_test + +import ( + "context" + "sort" + "strings" + "testing" + + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/hint" + "github.com/pingcap/tidb/util/tracing" + "github.com/stretchr/testify/require" +) + +func TestPhysicalOptimizeWithTraceEnabled(t *testing.T) { + p := parser.New() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + ctx := tk.Session().(sessionctx.Context) + tk.MustExec("use test") + tk.MustExec("create table t(a int, primary key (a))") + testcases := []struct { + sql string + logicalList []string + physicalList []string + bests []string + }{ + { + sql: "select * from t", + logicalList: []string{ + "DataSource_1", "Projection_2", + }, + physicalList: []string{ + "Projection_3", "TableReader_5", + }, + bests: []string{ + "Projection_3", "TableReader_5", + }, + }, + { + sql: "select * from t where a = 1", + logicalList: []string{ + "DataSource_1", "Projection_3", + }, + physicalList: []string{ + "Point_Get_5", "Projection_4", + }, + bests: []string{ + "Point_Get_5", "Projection_4", + }, + }, + } + + for _, testcase := range testcases { + sql := testcase.sql + stmt, err := p.ParseOneStmt(sql, "", "") + require.NoError(t, err) + err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: dom.InfoSchema()})) + require.NoError(t, err) + sctx := core.MockContext() + sctx.GetSessionVars().StmtCtx.EnableOptimizeTrace = true + builder, _ := core.NewPlanBuilder().Init(sctx, dom.InfoSchema(), &hint.BlockHintProcessor{}) + domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(dom.InfoSchema()) + plan, err := builder.Build(context.TODO(), stmt) + require.NoError(t, err) + flag := uint64(0) + flag = flag | 1<<3 | 1<<8 + _, _, err = core.DoOptimize(context.TODO(), sctx, flag, plan.(core.LogicalPlan)) + require.NoError(t, err) + otrace := sctx.GetSessionVars().StmtCtx.OptimizeTracer.Physical + require.NotNil(t, otrace) + logicalList, physicalList := getList(otrace) + require.True(t, checkList(logicalList, testcase.logicalList)) + require.True(t, checkList(physicalList, testcase.physicalList)) + } +} + +func checkList(d []string, s []string) bool { + if len(d) != len(s) { + return false + } + for i := 0; i < len(d); i++ { + if strings.Compare(d[i], s[i]) != 0 { + return false + } + } + return true +} + +func getList(otrace *tracing.PhysicalOptimizeTracer) (ll []string, pl []string) { + for logicalPlan, v := range otrace.State { + ll = append(ll, logicalPlan) + for physicalPlanKey := range v { + pl = append(pl, physicalPlanKey) + } + } + sort.Strings(ll) + sort.Strings(pl) + return ll, pl +} diff --git a/planner/core/physical_plans.go b/planner/core/physical_plans.go index 17e84b6efcf47..e533ecb7b717c 100644 --- a/planner/core/physical_plans.go +++ b/planner/core/physical_plans.go @@ -73,6 +73,30 @@ type tableScanAndPartitionInfo struct { partitionInfo PartitionInfo } +type readReqType uint8 + +const ( + // Cop means read from storage by cop request. + Cop readReqType = iota + // BatchCop means read from storage by BatchCop request, only used for TiFlash + BatchCop + // MPP means read from storage by MPP request, only used for TiFlash + MPP +) + +// Name returns the name of read request type. +func (r readReqType) Name() string { + switch r { + case BatchCop: + return "batchCop" + case MPP: + return "mpp" + default: + // return cop by default + return "cop" + } +} + // PhysicalTableReader is the table reader in tidb. type PhysicalTableReader struct { physicalSchemaProducer @@ -84,8 +108,9 @@ type PhysicalTableReader struct { // StoreType indicates table read from which type of store. StoreType kv.StoreType - // BatchCop = true means the cop task in the physical table reader will be executed in batch mode(use in TiFlash only) - BatchCop bool + // ReadReqType is the read request type for current physical table reader, there are 3 kinds of read request: Cop, + // BatchCop and MPP, currently, the latter two are only used in TiFlash + ReadReqType readReqType IsCommonHandle bool @@ -108,23 +133,36 @@ func (p *PhysicalTableReader) GetTablePlan() PhysicalPlan { return p.tablePlan } -// GetTableScan exports the tableScan that contained in tablePlan. -func (p *PhysicalTableReader) GetTableScan() *PhysicalTableScan { - curPlan := p.tablePlan - for { - chCnt := len(curPlan.Children()) - if chCnt == 0 { - return curPlan.(*PhysicalTableScan) - } else if chCnt == 1 { - curPlan = curPlan.Children()[0] - } else { - join, ok := curPlan.(*PhysicalHashJoin) - if !ok { - return nil - } - curPlan = join.children[1-join.globalChildIndex] +// GetTableScans exports the tableScan that contained in tablePlans. +func (p *PhysicalTableReader) GetTableScans() []*PhysicalTableScan { + tableScans := make([]*PhysicalTableScan, 0, 1) + for _, tablePlan := range p.TablePlans { + tableScan, ok := tablePlan.(*PhysicalTableScan) + if ok { + tableScans = append(tableScans, tableScan) } } + return tableScans +} + +// GetTableScan exports the tableScan that contained in tablePlans and return error when the count of table scan != 1. +func (p *PhysicalTableReader) GetTableScan() (*PhysicalTableScan, error) { + tableScans := p.GetTableScans() + if len(tableScans) != 1 { + return nil, errors.New("the count of table scan != 1") + } + return tableScans[0], nil +} + +// setMppOrBatchCopForTableScan set IsMPPOrBatchCop for all TableScan. +func setMppOrBatchCopForTableScan(curPlan PhysicalPlan) { + if ts, ok := curPlan.(*PhysicalTableScan); ok { + ts.IsMPPOrBatchCop = true + } + children := curPlan.Children() + for _, child := range children { + setMppOrBatchCopForTableScan(child) + } } // GetPhysicalTableReader returns PhysicalTableReader for logical TiKVSingleGather. @@ -160,7 +198,7 @@ func (p *PhysicalTableReader) Clone() (PhysicalPlan, error) { } cloned.physicalSchemaProducer = *base cloned.StoreType = p.StoreType - cloned.BatchCop = p.BatchCop + cloned.ReadReqType = p.ReadReqType cloned.IsCommonHandle = p.IsCommonHandle if cloned.tablePlan, err = p.tablePlan.Clone(); err != nil { return nil, err @@ -270,6 +308,7 @@ type PhysicalIndexLookUpReader struct { TablePlans []PhysicalPlan indexPlan PhysicalPlan tablePlan PhysicalPlan + Paging bool ExtraHandleCol *expression.Column // PushedLimit is used to avoid unnecessary table scan tasks of IndexLookUpReader. @@ -279,6 +318,10 @@ type PhysicalIndexLookUpReader struct { // Used by partition table. PartitionInfo PartitionInfo + + // required by cost calculation + expectedCnt uint64 + keepOrder bool } // Clone implements PhysicalPlan interface. @@ -394,6 +437,10 @@ type PhysicalIndexScan struct { DoubleRead bool NeedCommonHandle bool + + // required by cost model + // IndexScan operators under inner side of IndexJoin no need to consider net seek cost + underInnerIndexJoin bool } // Clone implements PhysicalPlan interface. @@ -475,7 +522,7 @@ type PhysicalTableScan struct { StoreType kv.StoreType - IsGlobalRead bool + IsMPPOrBatchCop bool // Used for tiflash PartitionTableScan. // The table scan may be a partition, rather than a real table. // TODO: clean up this field. After we support dynamic partitioning, table scan @@ -490,6 +537,10 @@ type PhysicalTableScan struct { PartitionInfo PartitionInfo SampleInfo *TableSampleInfo + + // required by cost model + // TableScan operators under inner side of IndexJoin no need to consider net seek cost + underInnerIndexJoin bool } // Clone implements PhysicalPlan interface. @@ -769,9 +820,8 @@ type PhysicalHashJoin struct { UseOuterToBuild bool // on which store the join executes. - storeTp kv.StoreType - globalChildIndex int - mppShuffleJoin bool + storeTp kv.StoreType + mppShuffleJoin bool } // Clone implements PhysicalPlan interface. @@ -958,9 +1008,8 @@ type PhysicalLock struct { Lock *ast.SelectLockInfo - TblID2Handle map[int64][]HandleCols - PartitionedTable []table.PartitionedTable - ExtraPIDInfo extraPIDInfo + TblID2Handle map[int64][]HandleCols + TblID2PhysTblIDCol map[int64]*expression.Column } // PhysicalLimit is the physical operator of Limit. @@ -1185,8 +1234,6 @@ type PhysicalUnionScan struct { Conditions []expression.Expression HandleCols HandleCols - - CacheTable kv.MemBuffer } // ExtractCorrelatedCols implements PhysicalPlan interface. @@ -1366,6 +1413,8 @@ type PhysicalShow struct { physicalSchemaProducer ShowContents + + Extractor ShowPredicateExtractor } // PhysicalShowDDLJobs is for showing DDL job list. diff --git a/planner/core/plan.go b/planner/core/plan.go index 3515f44e91750..44cb793862800 100644 --- a/planner/core/plan.go +++ b/planner/core/plan.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" + fd "github.com/pingcap/tidb/planner/funcdep" "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" @@ -66,6 +67,8 @@ type Plan interface { SetOutputNames(names types.NameSlice) SelectBlockOffset() int + + buildPlanTrace() *tracing.PlanTrace } func enforceProperty(p *property.PhysicalProperty, tsk task, ctx sessionctx.Context) task { @@ -237,10 +240,10 @@ type LogicalPlan interface { // PredicatePushDown pushes down the predicates in the where/on/having clauses as deeply as possible. // It will accept a predicate that is an expression slice, and return the expressions that can't be pushed. // Because it might change the root if the having clause exists, we need to return a plan that represents a new root. - PredicatePushDown([]expression.Expression) ([]expression.Expression, LogicalPlan) + PredicatePushDown([]expression.Expression, *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) // PruneColumns prunes the unused columns. - PruneColumns([]*expression.Column) error + PruneColumns([]*expression.Column, *logicalOptimizeOp) error // findBestTask converts the logical plan to the physical plan. It's a new interface. // It is called recursively from the parent to the children to create the result physical plan. @@ -250,7 +253,7 @@ type LogicalPlan interface { // If planCounter > 0, the clock_th plan generated in this function will be returned. // If planCounter = 0, the plan generated in this function will not be considered. // If planCounter = -1, then we will not force plan. - findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp) (task, int64, error) + findBestTask(prop *property.PhysicalProperty, planCounter *PlanCounterTp, op *physicalOptimizeOp) (task, int64, error) // BuildKeyInfo will collect the information of unique keys into schema. // Because this method is also used in cascades planner, we cannot use @@ -259,7 +262,7 @@ type LogicalPlan interface { BuildKeyInfo(selfSchema *expression.Schema, childSchema []*expression.Schema) // pushDownTopN will push down the topN or limit operator during logical optimization. - pushDownTopN(topN *LogicalTopN) LogicalPlan + pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan // recursiveDeriveStats derives statistic info between plans. recursiveDeriveStats(colGroups [][]*expression.Column) (*property.StatsInfo, error) @@ -307,8 +310,8 @@ type LogicalPlan interface { // canPushToCop check if we might push this plan to a specific store. canPushToCop(store kv.StoreType) bool - // buildLogicalPlanTrace clone necessary information from LogicalPlan - buildLogicalPlanTrace(p Plan) *tracing.LogicalPlanTrace + // ExtractFD derive the FDSet from the tree bottom up. + ExtractFD() *fd.FDSet } // PhysicalPlan is a tree of the physical operators. @@ -370,6 +373,23 @@ type baseLogicalPlan struct { self LogicalPlan maxOneRow bool children []LogicalPlan + // fdSet is a set of functional dependencies(FDs) which powers many optimizations, + // including eliminating unnecessary DISTINCT operators, simplifying ORDER BY columns, + // removing Max1Row operators, and mapping semi-joins to inner-joins. + // for now, it's hard to maintain in individual operator, build it from bottom up when using. + fdSet *fd.FDSet +} + +// ExtractFD return the children[0]'s fdSet if there are no adding/removing fd in this logic plan. +func (p *baseLogicalPlan) ExtractFD() *fd.FDSet { + if p.fdSet != nil { + return p.fdSet + } + fds := &fd.FDSet{HashCodeToUniqueID: make(map[string]int)} + for _, ch := range p.children { + fds.AddFrom(ch.ExtractFD()) + } + return fds } func (p *baseLogicalPlan) MaxOneRow() bool { @@ -381,15 +401,6 @@ func (p *baseLogicalPlan) ExplainInfo() string { return "" } -// buildLogicalPlanTrace implements LogicalPlan -func (p *baseLogicalPlan) buildLogicalPlanTrace(plan Plan) *tracing.LogicalPlanTrace { - planTrace := &tracing.LogicalPlanTrace{ID: p.ID(), TP: p.TP(), ExplainInfo: plan.ExplainInfo()} - for _, child := range p.Children() { - planTrace.Children = append(planTrace.Children, child.buildLogicalPlanTrace(child)) - } - return planTrace -} - type basePhysicalPlan struct { basePlan @@ -593,11 +604,11 @@ func (p *baseLogicalPlan) ExtractCorrelatedCols() []*expression.CorrelatedColumn } // PruneColumns implements LogicalPlan interface. -func (p *baseLogicalPlan) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *baseLogicalPlan) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { if len(p.children) == 0 { return nil } - return p.children[0].PruneColumns(parentUsedCols) + return p.children[0].PruneColumns(parentUsedCols, opt) } // basePlan implements base Plan interface. @@ -711,3 +722,27 @@ func (p *basePhysicalPlan) SetChild(i int, child PhysicalPlan) { func (p *basePlan) SCtx() sessionctx.Context { return p.ctx } + +// buildPlanTrace implements Plan +func (p *basePhysicalPlan) buildPlanTrace() *tracing.PlanTrace { + planTrace := &tracing.PlanTrace{ID: p.ID(), TP: p.TP(), ExplainInfo: p.self.ExplainInfo(), Cost: p.Cost()} + for _, child := range p.Children() { + planTrace.Children = append(planTrace.Children, child.buildPlanTrace()) + } + return planTrace +} + +// buildPlanTrace implements Plan +func (p *baseLogicalPlan) buildPlanTrace() *tracing.PlanTrace { + planTrace := &tracing.PlanTrace{ID: p.ID(), TP: p.TP(), ExplainInfo: p.self.ExplainInfo()} + for _, child := range p.Children() { + planTrace.Children = append(planTrace.Children, child.buildPlanTrace()) + } + return planTrace +} + +// buildPlanTrace implements Plan +func (p *basePlan) buildPlanTrace() *tracing.PlanTrace { + planTrace := &tracing.PlanTrace{ID: p.ID(), TP: p.TP()} + return planTrace +} diff --git a/planner/core/plan_stats.go b/planner/core/plan_stats.go new file mode 100644 index 0000000000000..f1100061b9f3b --- /dev/null +++ b/planner/core/plan_stats.go @@ -0,0 +1,112 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core + +import ( + "context" + "time" + + "github.com/cznic/mathutil" + "github.com/pingcap/errors" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/sessionctx/variable" +) + +type collectPredicateColumnsPoint struct{} + +func (c collectPredicateColumnsPoint) optimize(ctx context.Context, plan LogicalPlan, op *logicalOptimizeOp) (LogicalPlan, error) { + if plan.SCtx().GetSessionVars().InRestrictedSQL { + return plan, nil + } + predicateNeeded := variable.EnableColumnTracking.Load() + syncWait := plan.SCtx().GetSessionVars().StatsLoadSyncWait * time.Millisecond.Nanoseconds() + histNeeded := syncWait > 0 + predicateColumns, histNeededColumns := CollectColumnStatsUsage(plan, predicateNeeded, histNeeded) + if len(predicateColumns) > 0 { + plan.SCtx().UpdateColStatsUsage(predicateColumns) + } + if histNeeded && len(histNeededColumns) > 0 { + err := RequestLoadColumnStats(plan.SCtx(), histNeededColumns, syncWait) + return plan, err + } + return plan, nil +} + +func (c collectPredicateColumnsPoint) name() string { + return "collect_predicate_columns_point" +} + +type syncWaitStatsLoadPoint struct{} + +func (s syncWaitStatsLoadPoint) optimize(ctx context.Context, plan LogicalPlan, op *logicalOptimizeOp) (LogicalPlan, error) { + if plan.SCtx().GetSessionVars().InRestrictedSQL { + return plan, nil + } + _, err := SyncWaitStatsLoad(plan) + return plan, err +} + +func (s syncWaitStatsLoadPoint) name() string { + return "sync_wait_stats_load_point" +} + +const maxDuration = 1<<63 - 1 + +// RequestLoadColumnStats send requests to stats handle +func RequestLoadColumnStats(ctx sessionctx.Context, neededColumns []model.TableColumnID, syncWait int64) error { + stmtCtx := ctx.GetSessionVars().StmtCtx + hintMaxExecutionTime := int64(stmtCtx.MaxExecutionTime) + if hintMaxExecutionTime <= 0 { + hintMaxExecutionTime = maxDuration + } + sessMaxExecutionTime := int64(ctx.GetSessionVars().MaxExecutionTime) + if sessMaxExecutionTime <= 0 { + sessMaxExecutionTime = maxDuration + } + waitTime := mathutil.MinInt64(syncWait, mathutil.MinInt64(hintMaxExecutionTime, sessMaxExecutionTime)) + var timeout = time.Duration(waitTime) + err := domain.GetDomain(ctx).StatsHandle().SendLoadRequests(stmtCtx, neededColumns, timeout) + if err != nil { + return handleTimeout(stmtCtx) + } + return nil +} + +// SyncWaitStatsLoad sync-wait for stats load until timeout +func SyncWaitStatsLoad(plan LogicalPlan) (bool, error) { + stmtCtx := plan.SCtx().GetSessionVars().StmtCtx + if stmtCtx.StatsLoad.Fallback { + return false, nil + } + success := domain.GetDomain(plan.SCtx()).StatsHandle().SyncWaitStatsLoad(stmtCtx) + if success { + return true, nil + } + err := handleTimeout(stmtCtx) + return false, err +} + +func handleTimeout(stmtCtx *stmtctx.StatementContext) error { + err := errors.New("Timeout when sync-load full stats for needed columns") + if variable.StatsLoadPseudoTimeout.Load() { + stmtCtx.AppendWarning(err) + stmtCtx.StatsLoad.Fallback = true + return nil + } + return err +} diff --git a/planner/core/plan_stats_test.go b/planner/core/plan_stats_test.go new file mode 100644 index 0000000000000..51a303922fe32 --- /dev/null +++ b/planner/core/plan_stats_test.go @@ -0,0 +1,273 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/planner" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/statistics" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestPlanStatsLoad(t *testing.T) { + p := parser.New() + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + ctx := tk.Session().(sessionctx.Context) + tk.MustExec("drop table if exists t") + tk.MustExec("set @@session.tidb_analyze_version=2") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") + tk.MustExec("set @@session.tidb_stats_load_sync_wait = 60000") + tk.MustExec("create table t(a int, b int, c int, d int, primary key(a), key idx(b))") + tk.MustExec("insert into t values (1,1,1,1),(2,2,2,2),(3,3,3,3)") + tk.MustExec("create table pt(a int, b int, c int) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than maxvalue)") + tk.MustExec("insert into pt values (1,1,1),(2,2,2),(13,13,13),(14,14,14),(25,25,25),(36,36,36)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + tk.MustExec("analyze table t") + tk.MustExec("analyze table pt") + + testCases := []struct { + sql string + skip bool + check func(p plannercore.Plan, tableInfo *model.TableInfo) + }{ + { // DataSource + sql: "select * from t where c>1", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + switch pp := p.(type) { + case *plannercore.PhysicalTableReader: + stats := pp.Stats().HistColl + require.Equal(t, 0, countFullStats(stats, tableInfo.Columns[1].ID)) + require.Greater(t, countFullStats(stats, tableInfo.Columns[2].ID), 0) + default: + t.Error("unexpected plan:", pp) + } + }, + }, + { // PartitionTable + sql: "select * from pt where a < 15 and c > 1", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + pua, ok := p.(*plannercore.PhysicalUnionAll) + require.True(t, ok) + for _, child := range pua.Children() { + require.Greater(t, countFullStats(child.Stats().HistColl, tableInfo.Columns[2].ID), 0) + } + }, + }, + { // Join + sql: "select * from t t1 inner join t t2 on t1.b=t2.b where t1.d=3", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + pp, ok := p.(plannercore.PhysicalPlan) + require.True(t, ok) + require.Greater(t, countFullStats(pp.Children()[0].Stats().HistColl, tableInfo.Columns[3].ID), 0) + require.Greater(t, countFullStats(pp.Children()[1].Stats().HistColl, tableInfo.Columns[3].ID), 0) + }, + }, + { // Apply + sql: "select * from t t1 where t1.b > (select count(*) from t t2 where t2.c > t1.a and t2.d>1) and t1.c>2", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + pp, ok := p.(*plannercore.PhysicalProjection) + require.True(t, ok) + pa, ok := pp.Children()[0].(*plannercore.PhysicalApply) + require.True(t, ok) + left := pa.PhysicalHashJoin.Children()[0] + right := pa.PhysicalHashJoin.Children()[0] + require.Greater(t, countFullStats(left.Stats().HistColl, tableInfo.Columns[2].ID), 0) + require.Greater(t, countFullStats(right.Stats().HistColl, tableInfo.Columns[3].ID), 0) + }, + }, + { // > Any + sql: "select * from t where t.b > any(select d from t where t.c > 2)", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ph, ok := p.(*plannercore.PhysicalHashJoin) + require.True(t, ok) + ptr, ok := ph.Children()[0].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(ptr.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // in + sql: "select * from t where t.b in (select d from t where t.c > 2)", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ph, ok := p.(*plannercore.PhysicalHashJoin) + require.True(t, ok) + ptr, ok := ph.Children()[1].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(ptr.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // not in + sql: "select * from t where t.b not in (select d from t where t.c > 2)", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ph, ok := p.(*plannercore.PhysicalHashJoin) + require.True(t, ok) + ptr, ok := ph.Children()[1].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(ptr.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // exists + sql: "select * from t t1 where exists (select * from t t2 where t1.b > t2.d and t2.c>1)", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ph, ok := p.(*plannercore.PhysicalHashJoin) + require.True(t, ok) + ptr, ok := ph.Children()[1].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(ptr.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // not exists + sql: "select * from t t1 where not exists (select * from t t2 where t1.b > t2.d and t2.c>1)", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ph, ok := p.(*plannercore.PhysicalHashJoin) + require.True(t, ok) + ptr, ok := ph.Children()[1].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(ptr.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // CTE + sql: "with cte(x, y) as (select d + 1, b from t where c > 1) select * from cte where x < 3", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + ps, ok := p.(*plannercore.PhysicalSelection) + require.True(t, ok) + pc, ok := ps.Children()[0].(*plannercore.PhysicalCTE) + require.True(t, ok) + pp, ok := pc.SeedPlan.(*plannercore.PhysicalProjection) + require.True(t, ok) + reader, ok := pp.Children()[0].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(reader.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + { // recursive CTE + sql: "with recursive cte(x, y) as (select a, b from t where c > 1 union select x + 1, y from cte where x < 5) select * from cte", + check: func(p plannercore.Plan, tableInfo *model.TableInfo) { + pc, ok := p.(*plannercore.PhysicalCTE) + require.True(t, ok) + pp, ok := pc.SeedPlan.(*plannercore.PhysicalProjection) + require.True(t, ok) + reader, ok := pp.Children()[0].(*plannercore.PhysicalTableReader) + require.True(t, ok) + require.Greater(t, countFullStats(reader.Stats().HistColl, tableInfo.Columns[2].ID), 0) + }, + }, + } + for _, testCase := range testCases { + if testCase.skip { + continue + } + is := dom.InfoSchema() + dom.StatsHandle().Clear() // clear statsCache + require.NoError(t, dom.StatsHandle().Update(is)) + stmt, err := p.ParseOneStmt(testCase.sql, "", "") + require.NoError(t, err) + err = executor.ResetContextOfStmt(ctx, stmt) + require.NoError(t, err) + p, _, err := planner.Optimize(context.TODO(), ctx, stmt, is) + require.NoError(t, err) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + testCase.check(p, tableInfo) + } +} + +func countFullStats(stats *statistics.HistColl, colID int64) int { + for _, col := range stats.Columns { + if col.Info.ID == colID { + return col.Histogram.Len() + col.TopN.Num() + } + } + return -1 +} + +func TestPlanStatsLoadTimeout(t *testing.T) { + p := parser.New() + originConfig := config.GetGlobalConfig() + newConfig := config.NewConfig() + newConfig.Performance.StatsLoadConcurrency = 0 // no worker to consume channel + newConfig.Performance.StatsLoadQueueSize = 1 + config.StoreGlobalConfig(newConfig) + defer config.StoreGlobalConfig(originConfig) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + originalVal1 := tk.MustQuery("select @@tidb_stats_load_pseudo_timeout").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_stats_load_pseudo_timeout = %v", originalVal1)) + }() + + ctx := tk.Session().(sessionctx.Context) + tk.MustExec("drop table if exists t") + tk.MustExec("set @@session.tidb_analyze_version=2") + // since queue full, make sync-wait return as timeout as soon as possible + tk.MustExec("set @@session.tidb_stats_load_sync_wait = 1") + tk.MustExec("create table t(a int, b int, c int, primary key(a))") + tk.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + tk.MustExec("analyze table t") + is := dom.InfoSchema() + require.NoError(t, dom.StatsHandle().Update(is)) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + neededColumn := model.TableColumnID{TableID: tableInfo.ID, ColumnID: tableInfo.Columns[0].ID} + resultCh := make(chan model.TableColumnID, 1) + timeout := time.Duration(1<<63 - 1) + dom.StatsHandle().AppendNeededColumn(neededColumn, resultCh, timeout) // make channel queue full + stmt, err := p.ParseOneStmt("select * from t where c>1", "", "") + require.NoError(t, err) + tk.MustExec("set global tidb_stats_load_pseudo_timeout=false") + _, _, err = planner.Optimize(context.TODO(), ctx, stmt, is) + require.Error(t, err) // fail sql for timeout when pseudo=false + tk.MustExec("set global tidb_stats_load_pseudo_timeout=true") + plan, _, err := planner.Optimize(context.TODO(), ctx, stmt, is) + require.NoError(t, err) // not fail sql for timeout when pseudo=true + switch pp := plan.(type) { + case *plannercore.PhysicalTableReader: + stats := pp.Stats().HistColl + require.Greater(t, countFullStats(stats, tableInfo.Columns[0].ID), 0) + require.Equal(t, 0, countFullStats(stats, tableInfo.Columns[2].ID)) // pseudo stats + default: + t.Error("unexpected plan:", pp) + } +} diff --git a/planner/core/plan_test.go b/planner/core/plan_test.go index 4437a354b1757..f3cdd2840622a 100644 --- a/planner/core/plan_test.go +++ b/planner/core/plan_test.go @@ -18,50 +18,30 @@ import ( "bytes" "fmt" "strings" + "testing" - . "github.com/pingcap/check" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/expression/aggregation" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/planner/util" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/israce" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/plancodec" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPlanNormalize{}) - -type testPlanNormalize struct { - store kv.Storage - dom *domain.Domain - - testData testutil.TestData -} - -func (s *testPlanNormalize) SetUpSuite(c *C) { - testleak.BeforeTest() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - s.store = store - s.dom = dom - - s.testData, err = testutil.LoadTestSuiteData("testdata", "plan_normalized_suite") - c.Assert(err, IsNil) -} - -func (s *testPlanNormalize) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) - s.dom.Close() - s.store.Close() - testleak.AfterTest(c)() -} - -func (s *testPlanNormalize) TestPreferRangeScan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPreferRangeScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists test;") tk.MustExec("create table test(`id` int(10) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL DEFAULT 'tidb',`age` int(11) NOT NULL,`addr` varchar(50) DEFAULT 'The ocean of stars',PRIMARY KEY (`id`),KEY `idx_age` (`age`))") @@ -83,33 +63,36 @@ func (s *testPlanNormalize) TestPreferRangeScan(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + planNormalizedSuiteData := core.GetPlanNormalizedSuiteData() + planNormalizedSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { if i == 0 { tk.MustExec("set session tidb_opt_prefer_range_scan=0") } else if i == 1 { tk.MustExec("set session tidb_opt_prefer_range_scan=1") } - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 tk.MustExec(tt) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(t, info) p, ok := info.Plan.(core.Plan) - c.Assert(ok, IsTrue) + require.True(t, ok) normalized, _ := core.NormalizePlan(p) normalizedPlan, err := plancodec.DecodeNormalizedPlan(normalized) normalizedPlanRows := getPlanRows(normalizedPlan) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = normalizedPlanRows }) - compareStringSlice(c, normalizedPlanRows, output[i].Plan) + compareStringSlice(t, normalizedPlanRows, output[i].Plan) } } -func (s *testPlanNormalize) TestNormalizedPlan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNormalizedPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='static';") tk.MustExec("drop table if exists t1,t2,t3,t4") @@ -122,35 +105,37 @@ func (s *testPlanNormalize) TestNormalizedPlan(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + planNormalizedSuiteData := core.GetPlanNormalizedSuiteData() + planNormalizedSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 tk.MustExec(tt) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(t, info) p, ok := info.Plan.(core.Plan) - c.Assert(ok, IsTrue) + require.True(t, ok) normalized, _ := core.NormalizePlan(p) normalizedPlan, err := plancodec.DecodeNormalizedPlan(normalized) normalizedPlanRows := getPlanRows(normalizedPlan) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[i].SQL = tt output[i].Plan = normalizedPlanRows }) - compareStringSlice(c, normalizedPlanRows, output[i].Plan) + compareStringSlice(t, normalizedPlanRows, output[i].Plan) } } -func (s *testPlanNormalize) TestNormalizedPlanForDiffStore(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNormalizedPlanForDiffStore(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int, b int, c int, primary key(a))") tk.MustExec("insert into t1 values(1,1,1), (2,2,2), (3,3,3)") - - tbl, err := s.dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"}) - c.Assert(err, IsNil) + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"}) + require.NoError(t, err) // Set the hacked TiFlash replica for explain tests. tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} @@ -159,78 +144,80 @@ func (s *testPlanNormalize) TestNormalizedPlanForDiffStore(c *C) { Digest string Plan []string } - s.testData.GetTestCases(c, &input, &output) + planNormalizedSuiteData := core.GetPlanNormalizedSuiteData() + planNormalizedSuiteData.GetTestCases(t, &input, &output) lastDigest := "" for i, tt := range input { - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 tk.MustExec(tt) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(t, info) ep, ok := info.Plan.(*core.Explain) - c.Assert(ok, IsTrue) + require.True(t, ok) normalized, digest := core.NormalizePlan(ep.TargetPlan) normalizedPlan, err := plancodec.DecodeNormalizedPlan(normalized) normalizedPlanRows := getPlanRows(normalizedPlan) - c.Assert(err, IsNil) - s.testData.OnRecord(func() { + require.NoError(t, err) + testdata.OnRecord(func() { output[i].Digest = digest.String() output[i].Plan = normalizedPlanRows }) - compareStringSlice(c, normalizedPlanRows, output[i].Plan) - c.Assert(digest.String() != lastDigest, IsTrue) + compareStringSlice(t, normalizedPlanRows, output[i].Plan) + require.NotEqual(t, digest.String(), lastDigest) lastDigest = digest.String() } } -func (s *testPlanNormalize) TestEncodeDecodePlan(c *C) { - if israce.RaceEnabled { - c.Skip("skip race test") - } - tk := testkit.NewTestKit(c, s.store) +func TestEncodeDecodePlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2") tk.MustExec("create table t1 (a int key,b int,c int, index (b));") tk.MustExec("set tidb_enable_collect_execution_info=1;") - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 getPlanTree := func() string { - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(t, info) p, ok := info.Plan.(core.Plan) - c.Assert(ok, IsTrue) + require.True(t, ok) encodeStr := core.EncodePlan(p) planTree, err := plancodec.DecodePlan(encodeStr) - c.Assert(err, IsNil) + require.NoError(t, err) return planTree } tk.MustExec("select max(a) from t1 where a>0;") planTree := getPlanTree() - c.Assert(strings.Contains(planTree, "time"), IsTrue) - c.Assert(strings.Contains(planTree, "loops"), IsTrue) + require.True(t, strings.Contains(planTree, "time")) + require.True(t, strings.Contains(planTree, "loops")) tk.MustExec("insert into t1 values (1,1,1);") planTree = getPlanTree() - c.Assert(strings.Contains(planTree, "Insert"), IsTrue) - c.Assert(strings.Contains(planTree, "time"), IsTrue) - c.Assert(strings.Contains(planTree, "loops"), IsTrue) + require.True(t, strings.Contains(planTree, "Insert")) + require.True(t, strings.Contains(planTree, "time")) + require.True(t, strings.Contains(planTree, "loops")) tk.MustExec("with cte(a) as (select 1) select * from cte") planTree = getPlanTree() - c.Assert(strings.Contains(planTree, "CTE"), IsTrue) - c.Assert(strings.Contains(planTree, "1->Column#1"), IsTrue) - c.Assert(strings.Contains(planTree, "time"), IsTrue) - c.Assert(strings.Contains(planTree, "loops"), IsTrue) + require.True(t, strings.Contains(planTree, "CTE")) + require.True(t, strings.Contains(planTree, "1->Column#1")) + require.True(t, strings.Contains(planTree, "time")) + require.True(t, strings.Contains(planTree, "loops")) tk.MustExec("with cte(a) as (select 2) select * from cte") planTree = getPlanTree() - c.Assert(strings.Contains(planTree, "CTE"), IsTrue) - c.Assert(strings.Contains(planTree, "2->Column#1"), IsTrue) - c.Assert(strings.Contains(planTree, "time"), IsTrue) - c.Assert(strings.Contains(planTree, "loops"), IsTrue) + require.True(t, strings.Contains(planTree, "CTE")) + require.True(t, strings.Contains(planTree, "2->Column#1")) + require.True(t, strings.Contains(planTree, "time")) + require.True(t, strings.Contains(planTree, "loops")) } -func (s *testPlanNormalize) TestNormalizedDigest(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNormalizedDigest(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1,t2,t3,t4, bmsql_order_line, bmsql_district,bmsql_stock") tk.MustExec("create table t1 (a int key,b int,c int, index (b));") @@ -284,6 +271,14 @@ func (s *testPlanNormalize) TestNormalizedDigest(c *C) { s_dist_10 char(24) DEFAULT NULL, PRIMARY KEY ( s_w_id , s_i_id ) );`) + + err := failpoint.Enable("github.com/pingcap/tidb/planner/mockRandomPlanID", "return(true)") + require.NoError(t, err) + defer func() { + err = failpoint.Disable("github.com/pingcap/tidb/planner/mockRandomPlanID") + require.NoError(t, err) + }() + normalizedDigestCases := []struct { sql1 string sql2 string @@ -397,33 +392,31 @@ func (s *testPlanNormalize) TestNormalizedDigest(c *C) { }, } for _, testCase := range normalizedDigestCases { - testNormalizeDigest(tk, c, testCase.sql1, testCase.sql2, testCase.isSame) + testNormalizeDigest(tk, t, testCase.sql1, testCase.sql2, testCase.isSame) } } -func testNormalizeDigest(tk *testkit.TestKit, c *C, sql1, sql2 string, isSame bool) { - tk.Se.GetSessionVars().PlanID = 0 +func testNormalizeDigest(tk *testkit.TestKit, t *testing.T, sql1, sql2 string, isSame bool) { tk.MustQuery(sql1) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(t, info) physicalPlan, ok := info.Plan.(core.PhysicalPlan) - c.Assert(ok, IsTrue) + require.True(t, ok) normalized1, digest1 := core.NormalizePlan(physicalPlan) - tk.Se.GetSessionVars().PlanID = 0 tk.MustQuery(sql2) - info = tk.Se.ShowProcess() - c.Assert(info, NotNil) + info = tk.Session().ShowProcess() + require.NotNil(t, info) physicalPlan, ok = info.Plan.(core.PhysicalPlan) - c.Assert(ok, IsTrue) + require.True(t, ok) normalized2, digest2 := core.NormalizePlan(physicalPlan) - comment := Commentf("sql1: %v, sql2: %v\n%v !=\n%v\n", sql1, sql2, normalized1, normalized2) + comment := fmt.Sprintf("sql1: %v, sql2: %v\n%v !=\n%v\n", sql1, sql2, normalized1, normalized2) if isSame { - c.Assert(normalized1, Equals, normalized2, comment) - c.Assert(digest1.String(), Equals, digest2.String(), comment) + require.Equal(t, normalized1, normalized2, comment) + require.Equal(t, digest1.String(), digest2.String(), comment) } else { - c.Assert(normalized1 != normalized2, IsTrue, comment) - c.Assert(digest1.String() != digest2.String(), IsTrue, comment) + require.NotEqual(t, normalized1, normalized2, comment) + require.NotEqual(t, digest1.String(), digest2.String(), comment) } } @@ -432,15 +425,17 @@ func getPlanRows(planStr string) []string { return strings.Split(planStr, "\n") } -func compareStringSlice(c *C, ss1, ss2 []string) { - c.Assert(len(ss1), Equals, len(ss2)) +func compareStringSlice(t *testing.T, ss1, ss2 []string) { + require.Equal(t, len(ss1), len(ss2)) for i, s := range ss1 { - c.Assert(s, Equals, ss2[i]) + require.Equal(t, len(s), len(ss2[i])) } } -func (s *testPlanNormalize) TestExplainFormatHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainFormatHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 int not null, c2 int not null, key idx_c2(c2)) partition by range (c2) (partition p0 values less than (10), partition p1 values less than (20))") @@ -449,16 +444,17 @@ func (s *testPlanNormalize) TestExplainFormatHint(c *C) { "use_index(@`sel_2` `test`.`t2` `idx_c2`), hash_agg(@`sel_2`), use_index(@`sel_1` `test`.`t1` `idx_c2`), hash_agg(@`sel_1`)")) } -func (s *testPlanNormalize) TestExplainFormatHintRecoverableForTiFlashReplica(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestExplainFormatHintRecoverableForTiFlashReplica(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") // Create virtual `tiflash` replica info. - dom := domain.GetDomain(tk.Se) is := dom.InfoSchema() db, exists := is.SchemaByName(model.NewCIStr("test")) - c.Assert(exists, IsTrue) + require.True(t, exists) for _, tblInfo := range db.Tables { if tblInfo.Name.L == "t" { tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ @@ -469,18 +465,20 @@ func (s *testPlanNormalize) TestExplainFormatHintRecoverableForTiFlashReplica(c } rows := tk.MustQuery("explain select * from t").Rows() - c.Assert(rows[len(rows)-1][2], Equals, "cop[tiflash]") + require.Equal(t, rows[len(rows)-1][2], "cop[tiflash]") rows = tk.MustQuery("explain format='hint' select * from t").Rows() - c.Assert(rows[0][0], Equals, "read_from_storage(@`sel_1` tiflash[`test`.`t`])") + require.Equal(t, rows[0][0], "read_from_storage(@`sel_1` tiflash[`test`.`t`])") hints := tk.MustQuery("explain format='hint' select * from t;").Rows()[0][0] rows = tk.MustQuery(fmt.Sprintf("explain select /*+ %s */ * from t", hints)).Rows() - c.Assert(rows[len(rows)-1][2], Equals, "cop[tiflash]") + require.Equal(t, rows[len(rows)-1][2], "cop[tiflash]") } -func (s *testPlanNormalize) TestNthPlanHint(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestNthPlanHint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tt") tk.MustExec("create table tt (a int,b int, index(a), index(b));") @@ -488,7 +486,7 @@ func (s *testPlanNormalize) TestNthPlanHint(c *C) { tk.MustExec("explain select /*+nth_plan(4)*/ * from tt where a=1 and b=1;") tk.MustQuery("show warnings").Check(testkit.Rows( - "Warning 1105 The parameter of nth_plan() is out of range.")) + "Warning 1105 The parameter of nth_plan() is out of range")) // Test hints for nth_plan(x). tk.MustExec("drop table if exists t") @@ -502,11 +500,11 @@ func (s *testPlanNormalize) TestNthPlanHint(c *C) { tk.MustExec("explain format='hint' select /*+ nth_plan(3) */ * from t where a=1 and b=1") tk.MustQuery("show warnings").Check(testkit.Rows( - "Warning 1105 The parameter of nth_plan() is out of range.")) + "Warning 1105 The parameter of nth_plan() is out of range")) tk.MustExec("explain format='hint' select /*+ nth_plan(500) */ * from t where a=1 and b=1") tk.MustQuery("show warnings").Check(testkit.Rows( - "Warning 1105 The parameter of nth_plan() is out of range.")) + "Warning 1105 The parameter of nth_plan() is out of range")) // Test warning for multiply hints. tk.MustQuery("explain format='hint' select /*+ nth_plan(1) nth_plan(2) */ * from t where a=1 and b=1").Check(testkit.Rows( @@ -531,14 +529,16 @@ func (s *testPlanNormalize) TestNthPlanHint(c *C) { // Make sure nth_plan() doesn't affect separately executed subqueries by asserting there's only one warning. tk.MustExec("select /*+ nth_plan(1000) */ count(1) from t where (select count(1) from t, tt) > 1;") tk.MustQuery("show warnings").Check(testkit.Rows( - "Warning 1105 The parameter of nth_plan() is out of range.")) + "Warning 1105 The parameter of nth_plan() is out of range")) tk.MustExec("select /*+ nth_plan(1000) */ count(1) from t where exists (select count(1) from t, tt);") tk.MustQuery("show warnings").Check(testkit.Rows( - "Warning 1105 The parameter of nth_plan() is out of range.")) + "Warning 1105 The parameter of nth_plan() is out of range")) } -func (s *testPlanNormalize) BenchmarkDecodePlan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func BenchmarkDecodePlan(b *testing.B) { + store, clean := testkit.CreateMockStore(b) + defer clean() + tk := testkit.NewTestKit(b, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a varchar(10) key,b int);") @@ -553,24 +553,26 @@ func (s *testPlanNormalize) BenchmarkDecodePlan(c *C) { buf.WriteString(fmt.Sprintf("select count(1) as num,a from t where a='%v' group by a", i)) } query := buf.String() - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 tk.MustExec(query) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(b, info) p, ok := info.Plan.(core.PhysicalPlan) - c.Assert(ok, IsTrue) + require.True(b, ok) // TODO: optimize the encode plan performance when encode plan with runtimeStats - tk.Se.GetSessionVars().StmtCtx.RuntimeStatsColl = nil + tk.Session().GetSessionVars().StmtCtx.RuntimeStatsColl = nil encodedPlanStr := core.EncodePlan(p) - c.ResetTimer() - for i := 0; i < c.N; i++ { + b.ResetTimer() + for i := 0; i < b.N; i++ { _, err := plancodec.DecodePlan(encodedPlanStr) - c.Assert(err, IsNil) + require.NoError(b, err) } } -func (s *testPlanNormalize) BenchmarkEncodePlan(c *C) { - tk := testkit.NewTestKit(c, s.store) +func BenchmarkEncodePlan(b *testing.B) { + store, clean := testkit.CreateMockStore(b) + defer clean() + tk := testkit.NewTestKit(b, store) tk.MustExec("use test") tk.MustExec("drop table if exists th") tk.MustExec("set @@session.tidb_enable_table_partition = 1") @@ -579,25 +581,27 @@ func (s *testPlanNormalize) BenchmarkEncodePlan(c *C) { tk.MustExec("set @@tidb_slow_log_threshold=200000") query := "select count(*) from th t1 join th t2 join th t3 join th t4 join th t5 join th t6 where t1.i=t2.a and t1.i=t3.i and t3.i=t4.i and t4.i=t5.i and t5.i=t6.i" - tk.Se.GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID = 0 tk.MustExec(query) - info := tk.Se.ShowProcess() - c.Assert(info, NotNil) + info := tk.Session().ShowProcess() + require.NotNil(b, info) p, ok := info.Plan.(core.PhysicalPlan) - c.Assert(ok, IsTrue) - tk.Se.GetSessionVars().StmtCtx.RuntimeStatsColl = nil - c.ResetTimer() - for i := 0; i < c.N; i++ { + require.True(b, ok) + tk.Session().GetSessionVars().StmtCtx.RuntimeStatsColl = nil + b.ResetTimer() + for i := 0; i < b.N; i++ { core.EncodePlan(p) } } // Close issue 25729 -func (s *testPlanNormalize) TestIssue25729(c *C) { +func TestIssue25729(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { conf.Experimental.AllowsExpressionIndex = true }) - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists tt") // Case1 @@ -639,3 +643,209 @@ func (s *testPlanNormalize) TestIssue25729(c *C) { tk.MustExec("insert into t1 values(\"a\", \"adwa\");") tk.MustQuery("select * from t1 where concat(a, b) like \"aadwa\" and a = \"a\";").Check(testkit.Rows("a adwa")) } + +func TestCopPaging(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set session tidb_enable_paging = 1") + tk.MustExec("create table t(id int, c1 int, c2 int, primary key (id), key i(c1))") + defer tk.MustExec("drop table t") + for i := 0; i < 1024; i++ { + tk.MustExec("insert into t values(?, ?, ?)", i, i, i) + } + tk.MustExec("analyze table t") + + // limit 960 should go paging + for i := 0; i < 10; i++ { + tk.MustQuery("explain format='brief' select * from t force index(i) where id <= 1024 and c1 >= 0 and c1 <= 1024 and c2 in (2, 4, 6, 8) order by c1 limit 960").Check(testkit.Rows( + "Limit 4.00 root offset:0, count:960", + "└─IndexLookUp 4.00 root paging:true", + " ├─Selection(Build) 1024.00 cop[tikv] le(test.t.id, 1024)", + " │ └─IndexRangeScan 1024.00 cop[tikv] table:t, index:i(c1) range:[0,1024], keep order:true", + " └─Selection(Probe) 4.00 cop[tikv] in(test.t.c2, 2, 4, 6, 8)", + " └─TableRowIDScan 1024.00 cop[tikv] table:t keep order:false")) + } + + // selection between limit and indexlookup, limit 960 should also go paging + for i := 0; i < 10; i++ { + tk.MustQuery("explain format='brief' select * from t force index(i) where mod(id, 2) > 0 and id <= 1024 and c1 >= 0 and c1 <= 1024 and c2 in (2, 4, 6, 8) order by c1 limit 960").Check(testkit.Rows( + "Limit 3.20 root offset:0, count:960", + "└─IndexLookUp 3.20 root paging:true", + " ├─Selection(Build) 819.20 cop[tikv] gt(mod(test.t.id, 2), 0), le(test.t.id, 1024)", + " │ └─IndexRangeScan 1024.00 cop[tikv] table:t, index:i(c1) range:[0,1024], keep order:true", + " └─Selection(Probe) 3.20 cop[tikv] in(test.t.c2, 2, 4, 6, 8)", + " └─TableRowIDScan 819.20 cop[tikv] table:t keep order:false")) + } + + // limit 961 exceeds the threshold, it should not go paging + for i := 0; i < 10; i++ { + tk.MustQuery("explain format='brief' select * from t force index(i) where id <= 1024 and c1 >= 0 and c1 <= 1024 and c2 in (2, 4, 6, 8) order by c1 limit 961").Check(testkit.Rows( + "Limit 4.00 root offset:0, count:961", + "└─IndexLookUp 4.00 root ", + " ├─Selection(Build) 1024.00 cop[tikv] le(test.t.id, 1024)", + " │ └─IndexRangeScan 1024.00 cop[tikv] table:t, index:i(c1) range:[0,1024], keep order:true", + " └─Selection(Probe) 4.00 cop[tikv] in(test.t.c2, 2, 4, 6, 8)", + " └─TableRowIDScan 1024.00 cop[tikv] table:t keep order:false")) + } + + // selection between limit and indexlookup, limit 961 should not go paging too + for i := 0; i < 10; i++ { + tk.MustQuery("explain format='brief' select * from t force index(i) where mod(id, 2) > 0 and id <= 1024 and c1 >= 0 and c1 <= 1024 and c2 in (2, 4, 6, 8) order by c1 limit 961").Check(testkit.Rows( + "Limit 3.20 root offset:0, count:961", + "└─IndexLookUp 3.20 root ", + " ├─Selection(Build) 819.20 cop[tikv] gt(mod(test.t.id, 2), 0), le(test.t.id, 1024)", + " │ └─IndexRangeScan 1024.00 cop[tikv] table:t, index:i(c1) range:[0,1024], keep order:true", + " └─Selection(Probe) 3.20 cop[tikv] in(test.t.c2, 2, 4, 6, 8)", + " └─TableRowIDScan 819.20 cop[tikv] table:t keep order:false")) + } +} + +func TestBuildFinalModeAggregation(t *testing.T) { + aggSchemaBuilder := func(sctx sessionctx.Context, aggFuncs []*aggregation.AggFuncDesc) *expression.Schema { + schema := expression.NewSchema(make([]*expression.Column, 0, len(aggFuncs))...) + for _, agg := range aggFuncs { + newCol := &expression.Column{ + UniqueID: sctx.GetSessionVars().AllocPlanColumnID(), + RetType: agg.RetTp, + } + schema.Append(newCol) + } + return schema + } + isFinalAggMode := func(mode aggregation.AggFunctionMode) bool { + return mode == aggregation.FinalMode || mode == aggregation.CompleteMode + } + checkResult := func(sctx sessionctx.Context, aggFuncs []*aggregation.AggFuncDesc, groubyItems []expression.Expression) { + for partialIsCop := 0; partialIsCop < 2; partialIsCop++ { + for isMPPTask := 0; isMPPTask < 2; isMPPTask++ { + partial, final, _ := core.BuildFinalModeAggregation(sctx, &core.AggInfo{ + AggFuncs: aggFuncs, + GroupByItems: groubyItems, + Schema: aggSchemaBuilder(sctx, aggFuncs), + }, partialIsCop == 0, isMPPTask == 0) + if partial != nil { + for _, aggFunc := range partial.AggFuncs { + if partialIsCop == 0 { + require.True(t, !isFinalAggMode(aggFunc.Mode)) + } else { + require.True(t, isFinalAggMode(aggFunc.Mode)) + } + } + } + if final != nil { + for _, aggFunc := range final.AggFuncs { + require.True(t, isFinalAggMode(aggFunc.Mode)) + } + } + } + } + } + + ctx := core.MockContext() + + aggCol := &expression.Column{ + Index: 0, + RetType: types.NewFieldType(mysql.TypeLonglong), + } + gbyCol := &expression.Column{ + Index: 1, + RetType: types.NewFieldType(mysql.TypeLonglong), + } + orderCol := &expression.Column{ + Index: 2, + RetType: types.NewFieldType(mysql.TypeLonglong), + } + + emptyGroupByItems := make([]expression.Expression, 0, 1) + groupByItems := make([]expression.Expression, 0, 1) + groupByItems = append(groupByItems, gbyCol) + + orderByItems := make([]*util.ByItems, 0, 1) + orderByItems = append(orderByItems, &util.ByItems{ + Expr: orderCol, + Desc: true, + }) + + aggFuncs := make([]*aggregation.AggFuncDesc, 0, 5) + desc, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncMax, []expression.Expression{aggCol}, false) + require.NoError(t, err) + aggFuncs = append(aggFuncs, desc) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncFirstRow, []expression.Expression{aggCol}, false) + require.NoError(t, err) + aggFuncs = append(aggFuncs, desc) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncCount, []expression.Expression{aggCol}, false) + require.NoError(t, err) + aggFuncs = append(aggFuncs, desc) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncSum, []expression.Expression{aggCol}, false) + require.NoError(t, err) + aggFuncs = append(aggFuncs, desc) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncAvg, []expression.Expression{aggCol}, false) + require.NoError(t, err) + aggFuncs = append(aggFuncs, desc) + + aggFuncsWithDistinct := make([]*aggregation.AggFuncDesc, 0, 2) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncAvg, []expression.Expression{aggCol}, true) + require.NoError(t, err) + aggFuncsWithDistinct = append(aggFuncsWithDistinct, desc) + desc, err = aggregation.NewAggFuncDesc(ctx, ast.AggFuncCount, []expression.Expression{aggCol}, true) + require.NoError(t, err) + aggFuncsWithDistinct = append(aggFuncsWithDistinct, desc) + + groupConcatAggFuncs := make([]*aggregation.AggFuncDesc, 0, 4) + groupConcatWithoutDistinctWithoutOrderBy, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncGroupConcat, []expression.Expression{aggCol, aggCol}, false) + require.NoError(t, err) + groupConcatAggFuncs = append(groupConcatAggFuncs, groupConcatWithoutDistinctWithoutOrderBy) + groupConcatWithoutDistinctWithOrderBy, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncGroupConcat, []expression.Expression{aggCol, aggCol}, false) + require.NoError(t, err) + groupConcatWithoutDistinctWithOrderBy.OrderByItems = orderByItems + groupConcatAggFuncs = append(groupConcatAggFuncs, groupConcatWithoutDistinctWithOrderBy) + groupConcatWithDistinctWithoutOrderBy, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncGroupConcat, []expression.Expression{aggCol, aggCol}, true) + require.NoError(t, err) + groupConcatAggFuncs = append(groupConcatAggFuncs, groupConcatWithDistinctWithoutOrderBy) + groupConcatWithDistinctWithOrderBy, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncGroupConcat, []expression.Expression{aggCol, aggCol}, true) + require.NoError(t, err) + groupConcatWithDistinctWithOrderBy.OrderByItems = orderByItems + groupConcatAggFuncs = append(groupConcatAggFuncs, groupConcatWithDistinctWithOrderBy) + + // case 1 agg without distinct + checkResult(ctx, aggFuncs, emptyGroupByItems) + checkResult(ctx, aggFuncs, groupByItems) + + // case 2 agg with distinct + checkResult(ctx, aggFuncsWithDistinct, emptyGroupByItems) + checkResult(ctx, aggFuncsWithDistinct, groupByItems) + + // case 3 mixed with distinct and without distinct + mixedAggFuncs := make([]*aggregation.AggFuncDesc, 0, 10) + mixedAggFuncs = append(mixedAggFuncs, aggFuncs...) + mixedAggFuncs = append(mixedAggFuncs, aggFuncsWithDistinct...) + checkResult(ctx, mixedAggFuncs, emptyGroupByItems) + checkResult(ctx, mixedAggFuncs, groupByItems) + + // case 4 group concat + for _, groupConcatAggFunc := range groupConcatAggFuncs { + checkResult(ctx, []*aggregation.AggFuncDesc{groupConcatAggFunc}, emptyGroupByItems) + checkResult(ctx, []*aggregation.AggFuncDesc{groupConcatAggFunc}, groupByItems) + } + checkResult(ctx, groupConcatAggFuncs, emptyGroupByItems) + checkResult(ctx, groupConcatAggFuncs, groupByItems) + + // case 5 mixed group concat and other agg funcs + for _, groupConcatAggFunc := range groupConcatAggFuncs { + funcs := make([]*aggregation.AggFuncDesc, 0, 10) + funcs = append(funcs, groupConcatAggFunc) + funcs = append(funcs, aggFuncs...) + checkResult(ctx, funcs, emptyGroupByItems) + checkResult(ctx, funcs, groupByItems) + funcs = append(funcs, aggFuncsWithDistinct...) + checkResult(ctx, funcs, emptyGroupByItems) + checkResult(ctx, funcs, groupByItems) + } + mixedAggFuncs = append(mixedAggFuncs, groupConcatAggFuncs...) + checkResult(ctx, mixedAggFuncs, emptyGroupByItems) + checkResult(ctx, mixedAggFuncs, groupByItems) +} diff --git a/planner/core/plan_to_pb.go b/planner/core/plan_to_pb.go index 27056a8937c20..d4a5441045e69 100644 --- a/planner/core/plan_to_pb.go +++ b/planner/core/plan_to_pb.go @@ -16,7 +16,6 @@ package core import ( "github.com/pingcap/errors" - "github.com/pingcap/tidb/distsql" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/kv" @@ -131,7 +130,7 @@ func (p *PhysicalProjection) ToPB(ctx sessionctx.Context, storeType kv.StoreType } executorID = p.ExplainID().String() } else { - return nil, errors.Errorf("The projection can only be pushed down to TiFlash now, not %s.", storeType.Name()) + return nil, errors.Errorf("The projection can only be pushed down to TiFlash now, not %s", storeType.Name()) } return &tipb.Executor{Tp: tipb.ExecType_TypeProjection, Projection: projExec, ExecutorId: &executorID}, nil } @@ -177,23 +176,15 @@ func (p *PhysicalLimit) ToPB(ctx sessionctx.Context, storeType kv.StoreType) (*t // ToPB implements PhysicalPlan ToPB interface. func (p *PhysicalTableScan) ToPB(ctx sessionctx.Context, storeType kv.StoreType) (*tipb.Executor, error) { + if storeType == kv.TiFlash && p.Table.GetPartitionInfo() != nil && p.IsMPPOrBatchCop && p.ctx.GetSessionVars().UseDynamicPartitionPrune() { + return p.partitionTableScanToPBForFlash(ctx) + } tsExec := tables.BuildTableScanFromInfos(p.Table, p.Columns) tsExec.Desc = p.Desc if p.isPartition { tsExec.TableId = p.physicalTableID } executorID := "" - if storeType == kv.TiFlash && p.IsGlobalRead { - tsExec.NextReadEngine = tipb.EngineType_TiFlash - splitedRanges, _ := distsql.SplitRangesAcrossInt64Boundary(p.Ranges, false, false, p.Table.IsCommonHandle) - ranges, err := distsql.TableHandleRangesToKVRanges(ctx.GetSessionVars().StmtCtx, []int64{tsExec.TableId}, p.Table.IsCommonHandle, splitedRanges, nil) - if err != nil { - return nil, err - } - for _, keyRange := range ranges { - tsExec.Ranges = append(tsExec.Ranges, tipb.KeyRange{Low: keyRange.StartKey, High: keyRange.EndKey}) - } - } if storeType == kv.TiFlash { executorID = p.ExplainID().String() } @@ -201,6 +192,14 @@ func (p *PhysicalTableScan) ToPB(ctx sessionctx.Context, storeType kv.StoreType) return &tipb.Executor{Tp: tipb.ExecType_TypeTableScan, TblScan: tsExec, ExecutorId: &executorID}, err } +func (p *PhysicalTableScan) partitionTableScanToPBForFlash(ctx sessionctx.Context) (*tipb.Executor, error) { + ptsExec := tables.BuildPartitionTableScanFromInfos(p.Table, p.Columns) + ptsExec.Desc = p.Desc + executorID := p.ExplainID().String() + err := SetPBColumnsDefaultValue(ctx, ptsExec.Columns, p.Columns) + return &tipb.Executor{Tp: tipb.ExecType_TypePartitionTableScan, PartitionTableScan: ptsExec, ExecutorId: &executorID}, err +} + // checkCoverIndex checks whether we can pass unique info to TiKV. We should push it if and only if the length of // range and index are equal. func checkCoverIndex(idx *model.IndexInfo, ranges []*ranger.Range) bool { @@ -324,6 +323,8 @@ func (p *PhysicalIndexScan) ToPB(ctx sessionctx.Context, _ kv.StoreType) (*tipb. for _, col := range p.schema.Columns { if col.ID == model.ExtraHandleID { columns = append(columns, model.NewExtraHandleColInfo()) + } else if col.ID == model.ExtraPhysTblID { + columns = append(columns, model.NewExtraPhysTblIDColInfo()) } else if col.ID == model.ExtraPidColID { columns = append(columns, model.NewExtraPartitionIDColInfo()) } else { @@ -390,7 +391,9 @@ func (p *PhysicalHashJoin) ToPB(ctx sessionctx.Context, storeType kv.StoreType) var otherConditionsInJoin expression.CNFExprs var otherEqConditionsFromIn expression.CNFExprs - if p.JoinType == AntiSemiJoin { + /// For anti join, equal conditions from `in` clause requires additional processing, + /// for example, treat `null` as true. + if p.JoinType == AntiSemiJoin || p.JoinType == AntiLeftOuterSemiJoin || p.JoinType == LeftOuterSemiJoin { for _, condition := range p.OtherConditions { if expression.IsEQCondFromIn(condition) { otherEqConditionsFromIn = append(otherEqConditionsFromIn, condition) diff --git a/planner/core/plan_to_pb_serial_test.go b/planner/core/plan_to_pb_test.go similarity index 98% rename from planner/core/plan_to_pb_serial_test.go rename to planner/core/plan_to_pb_test.go index 866f104887fef..e4267024c884f 100644 --- a/planner/core/plan_to_pb_serial_test.go +++ b/planner/core/plan_to_pb_test.go @@ -28,6 +28,7 @@ import ( func TestColumnToProto(t *testing.T) { // Make sure the Flag is set in tipb.ColumnInfo + collate.SetNewCollationEnabledForTest(false) tp := types.NewFieldType(mysql.TypeLong) tp.Flag = 10 tp.Collate = "utf8_bin" @@ -59,7 +60,6 @@ func TestColumnToProto(t *testing.T) { require.Equal(t, int32(8), pc.Collation) collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) pc = util.ColumnToProto(col) expect = &tipb.ColumnInfo{ColumnId: 0, Tp: 3, Collation: -83, ColumnLen: -1, Decimal: -1, Flag: 10, Elems: []string(nil), DefaultVal: []uint8(nil), PkHandle: false, XXX_unrecognized: []uint8(nil)} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index b830d26da025d..9d965aedb9310 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -20,12 +20,14 @@ import ( "encoding/binary" "fmt" "math" + "strconv" "strings" "time" + "github.com/cznic/mathutil" "github.com/pingcap/errors" + "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" @@ -44,13 +46,16 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/table/temptable" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" util2 "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/logutil" @@ -58,11 +63,8 @@ import ( "github.com/pingcap/tidb/util/ranger" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/set" - "github.com/tikv/client-go/v2/oracle" + "github.com/pingcap/tidb/util/sqlexec" "github.com/tikv/client-go/v2/tikv" - - "github.com/cznic/mathutil" - "github.com/pingcap/tidb/table/tables" "go.uber.org/zap" ) @@ -85,17 +87,16 @@ type indexNestedLoopJoinTables struct { type tableHintInfo struct { indexNestedLoopJoinTables - sortMergeJoinTables []hintTableInfo - broadcastJoinTables []hintTableInfo - broadcastJoinPreferredLocal []hintTableInfo - hashJoinTables []hintTableInfo - indexHintList []indexHintInfo - tiflashTables []hintTableInfo - tikvTables []hintTableInfo - aggHints aggHintInfo - indexMergeHintList []indexHintInfo - timeRangeHint ast.HintTimeRange - limitHints limitHintInfo + sortMergeJoinTables []hintTableInfo + broadcastJoinTables []hintTableInfo + hashJoinTables []hintTableInfo + indexHintList []indexHintInfo + tiflashTables []hintTableInfo + tikvTables []hintTableInfo + aggHints aggHintInfo + indexMergeHintList []indexHintInfo + timeRangeHint ast.HintTimeRange + limitHints limitHintInfo } type limitHintInfo struct { @@ -197,22 +198,6 @@ func tableNames2HintTableInfo(ctx sessionctx.Context, hintName string, hintTable return hintTableInfos } -// ifPreferAsLocalInBCJoin checks if there is a data source specified as local read by hint -func (info *tableHintInfo) ifPreferAsLocalInBCJoin(p LogicalPlan, blockOffset int) bool { - alias := extractTableAlias(p, blockOffset) - if alias != nil { - tableNames := make([]*hintTableInfo, 1) - tableNames[0] = alias - return info.matchTableName(tableNames, info.broadcastJoinPreferredLocal) - } - for _, c := range p.Children() { - if info.ifPreferAsLocalInBCJoin(c, blockOffset) { - return true - } - } - return false -} - func (info *tableHintInfo) ifPreferMergeJoin(tableNames ...*hintTableInfo) bool { return info.matchTableName(tableNames, info.sortMergeJoinTables) } @@ -514,6 +499,7 @@ type PlanBuilder struct { isForUpdateRead bool allocIDForCTEStorage int buildingRecursivePartForCTE bool + buildingCTE bool } type handleColHelper struct { @@ -738,6 +724,8 @@ func (b *PlanBuilder) Build(ctx context.Context, node ast.Node) (Plan, error) { return b.buildCreateBindPlan(x) case *ast.DropBindingStmt: return b.buildDropBindPlan(x) + case *ast.SetBindingStmt: + return b.buildSetBindingStatusPlan(x) case *ast.ChangeStmt: return b.buildChange(x) case *ast.SplitRegionStmt: @@ -785,8 +773,39 @@ func (b *PlanBuilder) buildDo(ctx context.Context, v *ast.DoStmt) (Plan, error) proj := LogicalProjection{Exprs: make([]expression.Expression, 0, len(v.Exprs))}.Init(b.ctx, b.getSelectOffset()) proj.names = make([]*types.FieldName, len(v.Exprs)) schema := expression.NewSchema(make([]*expression.Column, 0, len(v.Exprs))...) + + // Since do statement only contain expression list, and it may contain aggFunc, detecting to build the aggMapper firstly. + var ( + err error + aggFuncs []*ast.AggregateFuncExpr + totalMap map[*ast.AggregateFuncExpr]int + ) + hasAgg := b.detectAggInExprNode(v.Exprs) + needBuildAgg := hasAgg + if hasAgg { + if b.buildingRecursivePartForCTE { + return nil, ErrCTERecursiveForbidsAggregation.GenWithStackByArgs(b.genCTETableNameForError()) + } + + aggFuncs, totalMap = b.extractAggFuncsInExprs(v.Exprs) + + if len(aggFuncs) == 0 { + needBuildAgg = false + } + } + if needBuildAgg { + var aggIndexMap map[int]int + p, aggIndexMap, err = b.buildAggregation(ctx, p, aggFuncs, nil, nil) + if err != nil { + return nil, err + } + for agg, idx := range totalMap { + totalMap[agg] = aggIndexMap[idx] + } + } + for _, astExpr := range v.Exprs { - expr, np, err := b.rewrite(ctx, astExpr, p, nil, true) + expr, np, err := b.rewrite(ctx, astExpr, p, totalMap, true) if err != nil { return nil, err } @@ -860,6 +879,25 @@ func (b *PlanBuilder) buildDropBindPlan(v *ast.DropBindingStmt) (Plan, error) { return p, nil } +func (b *PlanBuilder) buildSetBindingStatusPlan(v *ast.SetBindingStmt) (Plan, error) { + p := &SQLBindPlan{ + SQLBindOp: OpSetBindingStatus, + NormdOrigSQL: parser.Normalize(utilparser.RestoreWithDefaultDB(v.OriginNode, b.ctx.GetSessionVars().CurrentDB, v.OriginNode.Text())), + Db: utilparser.GetDefaultDB(v.OriginNode, b.ctx.GetSessionVars().CurrentDB), + } + switch v.BindingStatusType { + case ast.BindingStatusTypeEnabled: + p.NewStatus = bindinfo.Enabled + case ast.BindingStatusTypeDisabled: + p.NewStatus = bindinfo.Disabled + } + if v.HintedNode != nil { + p.BindSQL = utilparser.RestoreWithDefaultDB(v.HintedNode, b.ctx.GetSessionVars().CurrentDB, v.HintedNode.Text()) + } + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", nil) + return p, nil +} + func checkHintedSQL(sql, charset, collation, db string) error { p := parser.New() hintsSet, _, warns, err := hint.ParseHintsSet(p, sql, charset, collation, db) @@ -905,6 +943,16 @@ func (b *PlanBuilder) buildCreateBindPlan(v *ast.CreateBindingStmt) (Plan, error return p, nil } +// detectAggInExprNode detects an aggregate function in its exprs. +func (b *PlanBuilder) detectAggInExprNode(exprs []ast.ExprNode) bool { + for _, expr := range exprs { + if ast.HasAggFlag(expr) { + return true + } + } + return false +} + // detectSelectAgg detects an aggregate function or GROUP BY clause. func (b *PlanBuilder) detectSelectAgg(sel *ast.SelectStmt) bool { if sel.GroupBy != nil { @@ -950,10 +998,13 @@ func (b *PlanBuilder) detectSelectWindow(sel *ast.SelectStmt) bool { } func getPathByIndexName(paths []*util.AccessPath, idxName model.CIStr, tblInfo *model.TableInfo) *util.AccessPath { - var tablePath *util.AccessPath + var primaryIdxPath *util.AccessPath for _, path := range paths { + if path.StoreType == kv.TiFlash { + continue + } if path.IsTablePath() { - tablePath = path + primaryIdxPath = path continue } if path.Index.Name.L == idxName.L { @@ -961,7 +1012,7 @@ func getPathByIndexName(paths []*util.AccessPath, idxName model.CIStr, tblInfo * } } if isPrimaryIndex(idxName) && tblInfo.HasClusteredIndex() { - return tablePath + return primaryIdxPath } return nil } @@ -970,8 +1021,8 @@ func isPrimaryIndex(indexName model.CIStr) bool { return indexName.L == "primary" } -func genTiFlashPath(tblInfo *model.TableInfo, isGlobalRead bool) *util.AccessPath { - tiFlashPath := &util.AccessPath{StoreType: kv.TiFlash, IsTiFlashGlobalRead: isGlobalRead} +func genTiFlashPath(tblInfo *model.TableInfo) *util.AccessPath { + tiFlashPath := &util.AccessPath{StoreType: kv.TiFlash} fillContentForTablePath(tiFlashPath, tblInfo) return tiFlashPath } @@ -1039,8 +1090,7 @@ func getPossibleAccessPaths(ctx sessionctx.Context, tableHints *tableHintInfo, i } else if !tblInfo.TiFlashReplica.Available { ctx.GetSessionVars().RaiseWarningWhenMPPEnforced("MPP mode may be blocked because tiflash replicas of table `" + tblInfo.Name.O + "` not ready.") } else { - publicPaths = append(publicPaths, genTiFlashPath(tblInfo, false)) - publicPaths = append(publicPaths, genTiFlashPath(tblInfo, true)) + publicPaths = append(publicPaths, genTiFlashPath(tblInfo)) } optimizerUseInvisibleIndexes := ctx.GetSessionVars().OptimizerUseInvisibleIndexes @@ -1221,50 +1271,40 @@ func removeTiflashDuringStaleRead(paths []*util.AccessPath) []*util.AccessPath { } func (b *PlanBuilder) buildSelectLock(src LogicalPlan, lock *ast.SelectLockInfo) (*LogicalLock, error) { - selectLock := LogicalLock{ - Lock: lock, - tblID2Handle: b.handleHelper.tailMap(), - partitionedTable: b.partitionedTable, - }.Init(b.ctx) - selectLock.SetChildren(src) - + var tblID2PhysTblIDCol map[int64]*expression.Column if len(b.partitionedTable) > 0 { + tblID2PhysTblIDCol = make(map[int64]*expression.Column) // If a chunk row is read from a partitioned table, which partition the row // comes from is unknown. With the existence of Join, the situation could be // even worse: SelectLock have to know the `pid` to construct the lock key. - // To solve the problem, an extra `pid` column is add to the schema, and the + // To solve the problem, an extra `pid` column is added to the schema, and the // DataSource need to return the `pid` information in the chunk row. - err := addExtraPIDColumnToDataSource(src, &selectLock.extraPIDInfo) - if err != nil { - return nil, err - } - // TODO: Dynamic partition mode does not support adding extra pid column to the data source. - // (Because one table reader can read from multiple partitions, which partition a chunk row comes from is unknown) - // So we have to use the old "rewrite to union" way here, set `flagPartitionProcessor` flag for that. - b.optFlag = b.optFlag | flagPartitionProcessor + // For dynamic prune mode, it is filled in from the tableID in the key by storage. + // For static prune mode it is also filled in from the tableID in the key by storage. + // since it would otherwise be lost in the PartitionUnion executor. + setExtraPhysTblIDColsOnDataSource(src, tblID2PhysTblIDCol) } + selectLock := LogicalLock{ + Lock: lock, + tblID2Handle: b.handleHelper.tailMap(), + tblID2PhysTblIDCol: tblID2PhysTblIDCol, + }.Init(b.ctx) + selectLock.SetChildren(src) return selectLock, nil } -func addExtraPIDColumnToDataSource(p LogicalPlan, info *extraPIDInfo) error { - switch raw := p.(type) { +func setExtraPhysTblIDColsOnDataSource(p LogicalPlan, tblID2PhysTblIDCol map[int64]*expression.Column) { + switch ds := p.(type) { case *DataSource: - // Fix issue 26250, do not add extra pid column to normal table. - if raw.tableInfo.GetPartitionInfo() == nil { - return nil + if ds.tableInfo.GetPartitionInfo() == nil { + return } - raw.addExtraPIDColumn(info) - return nil + tblID2PhysTblIDCol[ds.tableInfo.ID] = ds.AddExtraPhysTblIDColumn() default: - var err error for _, child := range p.Children() { - err = addExtraPIDColumnToDataSource(child, info) - if err != nil { - return err - } + setExtraPhysTblIDColsOnDataSource(child, tblID2PhysTblIDCol) } } - return nil } func (b *PlanBuilder) buildPrepare(x *ast.PrepareStmt) Plan { @@ -1380,6 +1420,8 @@ func (b *PlanBuilder) buildAdmin(ctx context.Context, as *ast.AdminStmt) (Plan, return &AdminResetTelemetryID{}, nil case ast.AdminReloadStatistics: return &Simple{Statement: as}, nil + case ast.AdminFlushPlanCache: + return &Simple{Statement: as}, nil default: return nil, ErrUnsupportedType.GenWithStack("Unsupported ast.AdminStmt(%T) for buildAdmin", as) } @@ -1780,7 +1822,7 @@ func GetPhysicalIDsAndPartitionNames(tblInfo *model.TableInfo, partitionNames [] pi := tblInfo.GetPartitionInfo() if pi == nil { if len(partitionNames) != 0 { - return nil, nil, errors.Trace(ddl.ErrPartitionMgmtOnNonpartitioned) + return nil, nil, errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned) } return []int64{tblInfo.ID}, []string{""}, nil } @@ -1812,26 +1854,20 @@ func GetPhysicalIDsAndPartitionNames(tblInfo *model.TableInfo, partitionNames [] return ids, names, nil } -// getAnalyzeColumnsInfo returns the columns whose stats need to be collected. -// 1. For `ANALYZE TABLE t PREDICATE COLUMNS`, it returns union of the predicate columns and the columns in index/primary key/extended stats. -// 2. For `ANALYZE TABLE t COLUMNS c1, c2, ..., cn`, it returns union of the specified columns(c1, c2, ..., cn) and the columns in index/primary key/extended stats. -// 3. Otherwise it returns all the columns. -func (b *PlanBuilder) getAnalyzeColumnsInfo(as *ast.AnalyzeTableStmt, tbl *ast.TableName) ([]*model.ColumnInfo, error) { - tblInfo := tbl.TableInfo - if len(as.ColumnNames) == 0 { - return tblInfo.Columns, nil - } - columnIDs := make(map[int64]struct{}, len(tblInfo.Columns)) - for _, colName := range as.ColumnNames { - colInfo := model.FindColumnInfo(tblInfo.Columns, colName.L) - if colInfo == nil { - return nil, ErrAnalyzeMissColumn.GenWithStackByArgs(colName.O, tblInfo.Name.O) - } - columnIDs[colInfo.ID] = struct{}{} +type calcOnceMap struct { + data map[int64]struct{} + calculated bool +} + +// getMustAnalyzedColumns puts the columns whose statistics must be collected into `cols` if `cols` has not been calculated. +func (b *PlanBuilder) getMustAnalyzedColumns(tbl *ast.TableName, cols *calcOnceMap) (map[int64]struct{}, error) { + if cols.calculated { + return cols.data, nil } - missingCols := make(map[int64]struct{}, len(tblInfo.Columns)-len(columnIDs)) + tblInfo := tbl.TableInfo + cols.data = make(map[int64]struct{}, len(tblInfo.Columns)) if len(tblInfo.Indices) > 0 { - // add indexed columns + // Add indexed columns. // Some indexed columns are generated columns so we also need to add the columns that make up those generated columns. columns, _, err := expression.ColumnInfos2ColumnsAndNames(b.ctx, tbl.Schema, tbl.Name, tblInfo.Columns, tblInfo) if err != nil { @@ -1844,10 +1880,7 @@ func (b *PlanBuilder) getAnalyzeColumnsInfo(as *ast.AnalyzeTableStmt, tbl *ast.T } for _, idxCol := range idx.Columns { colInfo := tblInfo.Columns[idxCol.Offset] - if _, ok := columnIDs[colInfo.ID]; !ok { - columnIDs[colInfo.ID] = struct{}{} - missingCols[colInfo.ID] = struct{}{} - } + cols.data[colInfo.ID] = struct{}{} if expr := columns[idxCol.Offset].VirtualExpr; expr != nil { virtualExprs = append(virtualExprs, expr) } @@ -1858,10 +1891,7 @@ func (b *PlanBuilder) getAnalyzeColumnsInfo(as *ast.AnalyzeTableStmt, tbl *ast.T relatedCols = expression.ExtractColumnsFromExpressions(relatedCols, virtualExprs, nil) virtualExprs = virtualExprs[:0] for _, col := range relatedCols { - if _, ok := columnIDs[col.ID]; !ok { - columnIDs[col.ID] = struct{}{} - missingCols[col.ID] = struct{}{} - } + cols.data[col.ID] = struct{}{} if col.VirtualExpr != nil { virtualExprs = append(virtualExprs, col.VirtualExpr) } @@ -1871,13 +1901,10 @@ func (b *PlanBuilder) getAnalyzeColumnsInfo(as *ast.AnalyzeTableStmt, tbl *ast.T } if tblInfo.PKIsHandle { pkCol := tblInfo.GetPkColInfo() - if _, ok := columnIDs[pkCol.ID]; !ok { - columnIDs[pkCol.ID] = struct{}{} - missingCols[pkCol.ID] = struct{}{} - } + cols.data[pkCol.ID] = struct{}{} } if b.ctx.GetSessionVars().EnableExtendedStats { - // add the columns related to extended stats + // Add the columns related to extended stats. // TODO: column_ids read from mysql.stats_extended in optimization phase may be different from that in execution phase((*Handle).BuildExtendedStats) // if someone inserts data into mysql.stats_extended between the two time points, the new added extended stats may not be computed. statsHandle := domain.GetDomain(b.ctx).StatsHandle() @@ -1886,28 +1913,133 @@ func (b *PlanBuilder) getAnalyzeColumnsInfo(as *ast.AnalyzeTableStmt, tbl *ast.T return nil, err } for _, colID := range extendedStatsColIDs { - if _, ok := columnIDs[colID]; !ok { - columnIDs[colID] = struct{}{} - missingCols[colID] = struct{}{} - } + cols.data[colID] = struct{}{} } } - if len(missingCols) > 0 { - missingNames := make([]string, 0, len(missingCols)) - for _, col := range tblInfo.Columns { - if _, ok := missingCols[col.ID]; ok { - missingNames = append(missingNames, col.Name.O) + cols.calculated = true + return cols.data, nil +} + +func (b *PlanBuilder) getPredicateColumns(tbl *ast.TableName, cols *calcOnceMap) (map[int64]struct{}, error) { + if cols.calculated { + return cols.data, nil + } + tblInfo := tbl.TableInfo + cols.data = make(map[int64]struct{}, len(tblInfo.Columns)) + do := domain.GetDomain(b.ctx) + h := do.StatsHandle() + colList, err := h.GetPredicateColumns(tblInfo.ID) + if err != nil { + return nil, err + } + if len(colList) == 0 { + b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("No predicate column has been collected yet for table %s.%s so all columns are analyzed", tbl.Schema.L, tbl.Name.L)) + for _, colInfo := range tblInfo.Columns { + cols.data[colInfo.ID] = struct{}{} + } + } else { + for _, id := range colList { + cols.data[id] = struct{}{} + } + } + cols.calculated = true + return cols.data, nil +} + +func getAnalyzeColumnList(specifiedColumns []model.CIStr, tbl *ast.TableName) ([]*model.ColumnInfo, error) { + colList := make([]*model.ColumnInfo, 0, len(specifiedColumns)) + for _, colName := range specifiedColumns { + colInfo := model.FindColumnInfo(tbl.TableInfo.Columns, colName.L) + if colInfo == nil { + return nil, ErrAnalyzeMissColumn.GenWithStackByArgs(colName.O, tbl.TableInfo.Name.O) + } + colList = append(colList, colInfo) + } + return colList, nil +} + +// getFullAnalyzeColumnsInfo decides which columns need to be analyzed. +// The first return value is the columns which need to be analyzed and the second return value is the columns which need to +// be record in mysql.analyze_options(only for the case of analyze table t columns c1, .., cn). +func (b *PlanBuilder) getFullAnalyzeColumnsInfo( + tbl *ast.TableName, + columnChoice model.ColumnChoice, + specifiedCols []*model.ColumnInfo, + predicateCols, mustAnalyzedCols *calcOnceMap, + mustAllColumns bool, + warning bool, +) ([]*model.ColumnInfo, []*model.ColumnInfo, error) { + if mustAllColumns && warning && (columnChoice == model.PredicateColumns || columnChoice == model.ColumnList) { + b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("Table %s.%s has version 1 statistics so all the columns must be analyzed to overwrite the current statistics", tbl.Schema.L, tbl.Name.L)) + } + colSet2colList := func(colSet map[int64]struct{}) []*model.ColumnInfo { + colList := make([]*model.ColumnInfo, 0, len(colSet)) + for _, colInfo := range tbl.TableInfo.Columns { + if _, ok := colSet[colInfo.ID]; ok { + colList = append(colList, colInfo) } } - b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("Columns %s are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", strings.Join(missingNames, ","))) + return colList } - columnsInfo := make([]*model.ColumnInfo, 0, len(columnIDs)) - for _, col := range tblInfo.Columns { - if _, ok := columnIDs[col.ID]; ok { - columnsInfo = append(columnsInfo, col) + switch columnChoice { + case model.DefaultChoice, model.AllColumns: + return tbl.TableInfo.Columns, nil, nil + case model.PredicateColumns: + if mustAllColumns { + return tbl.TableInfo.Columns, nil, nil + } + predicate, err := b.getPredicateColumns(tbl, predicateCols) + if err != nil { + return nil, nil, err + } + mustAnalyzed, err := b.getMustAnalyzedColumns(tbl, mustAnalyzedCols) + if err != nil { + return nil, nil, err + } + colSet := make(map[int64]struct{}, len(predicate)+len(mustAnalyzed)) + for colID := range predicate { + colSet[colID] = struct{}{} + } + for colID := range mustAnalyzed { + colSet[colID] = struct{}{} } + return colSet2colList(colSet), nil, nil + case model.ColumnList: + colSet := make(map[int64]struct{}, len(specifiedCols)) + for _, colInfo := range specifiedCols { + colSet[colInfo.ID] = struct{}{} + } + mustAnalyzed, err := b.getMustAnalyzedColumns(tbl, mustAnalyzedCols) + if err != nil { + return nil, nil, err + } + if warning { + missing := make(map[int64]struct{}, len(mustAnalyzed)) + for colID := range mustAnalyzed { + if _, ok := colSet[colID]; !ok { + missing[colID] = struct{}{} + } + } + if len(missing) > 0 { + missingNames := make([]string, 0, len(missing)) + for _, col := range tbl.TableInfo.Columns { + if _, ok := missing[col.ID]; ok { + missingNames = append(missingNames, col.Name.O) + } + } + b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("Columns %s are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats", strings.Join(missingNames, ","))) + } + } + for colID := range mustAnalyzed { + colSet[colID] = struct{}{} + } + colList := colSet2colList(colSet) + if mustAllColumns { + return tbl.TableInfo.Columns, colList, nil + } + return colList, colList, nil } - return columnsInfo, nil + return nil, nil, nil } func getColOffsetForAnalyze(colsInfo []*model.ColumnInfo, colID int64) int { @@ -1954,18 +2086,39 @@ func (b *PlanBuilder) buildAnalyzeFullSamplingTask( names []string, tbl *ast.TableName, version int, + persistOpts bool, + rsOptionsMap map[int64]V2AnalyzeOptions, ) ([]AnalyzeColumnsTask, error) { if as.Incremental { b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("The version 2 stats would ignore the INCREMENTAL keyword and do full sampling")) } - colsInfo, err := b.getAnalyzeColumnsInfo(as, tbl) + astOpts, err := parseAnalyzeOptionsV2(as.AnalyzeOpts) + if err != nil { + return nil, err + } + astColList, err := getAnalyzeColumnList(as.ColumnNames, tbl) + if err != nil { + return nil, err + } + var predicateCols, mustAnalyzedCols calcOnceMap + ver := version + statsHandle := domain.GetDomain(b.ctx).StatsHandle() + // If the statistics of the table is version 1, we must analyze all columns to overwrites all of old statistics. + mustAllColumns := !statsHandle.CheckAnalyzeVersion(tbl.TableInfo, physicalIDs, &ver) + astColsInfo, _, err := b.getFullAnalyzeColumnsInfo(tbl, as.ColumnChoice, astColList, &predicateCols, &mustAnalyzedCols, mustAllColumns, true) if err != nil { return nil, err } - allColumns := len(tbl.TableInfo.Columns) == len(colsInfo) - indexes := getModifiedIndexesInfoForAnalyze(tbl.TableInfo, allColumns, colsInfo) - handleCols := BuildHandleColsForAnalyze(b.ctx, tbl.TableInfo, allColumns, colsInfo) + isAnalyzeTable := len(as.PartitionNames) == 0 + optionsMap, colsInfoMap, err := b.genV2AnalyzeOptions(persistOpts, tbl, isAnalyzeTable, physicalIDs, astOpts, as.ColumnChoice, astColList, &predicateCols, &mustAnalyzedCols, mustAllColumns) + if err != nil { + return nil, err + } + for physicalID, opts := range optionsMap { + rsOptionsMap[physicalID] = opts + } for i, id := range physicalIDs { + physicalID := id if id == tbl.TableInfo.ID { id = -1 } @@ -1977,9 +2130,19 @@ func (b *PlanBuilder) buildAnalyzeFullSamplingTask( Incremental: false, StatsVersion: version, } + if optsV2, ok := optionsMap[physicalID]; ok { + info.V2Options = &optsV2 + } + execColsInfo := astColsInfo + if colsInfo, ok := colsInfoMap[physicalID]; ok { + execColsInfo = colsInfo + } + allColumns := len(tbl.TableInfo.Columns) == len(execColsInfo) + indexes := getModifiedIndexesInfoForAnalyze(tbl.TableInfo, allColumns, execColsInfo) + handleCols := BuildHandleColsForAnalyze(b.ctx, tbl.TableInfo, allColumns, execColsInfo) newTask := AnalyzeColumnsTask{ HandleCols: handleCols, - ColsInfo: colsInfo, + ColsInfo: execColsInfo, AnalyzeInfo: info, TblInfo: tbl.TableInfo, Indexes: indexes, @@ -1995,14 +2158,156 @@ func (b *PlanBuilder) buildAnalyzeFullSamplingTask( return taskSlice, nil } +func (b *PlanBuilder) genV2AnalyzeOptions( + persist bool, + tbl *ast.TableName, + isAnalyzeTable bool, + physicalIDs []int64, + astOpts map[ast.AnalyzeOptionType]uint64, + astColChoice model.ColumnChoice, + astColList []*model.ColumnInfo, + predicateCols, mustAnalyzedCols *calcOnceMap, + mustAllColumns bool, +) (map[int64]V2AnalyzeOptions, map[int64][]*model.ColumnInfo, error) { + optionsMap := make(map[int64]V2AnalyzeOptions, len(physicalIDs)) + colsInfoMap := make(map[int64][]*model.ColumnInfo, len(physicalIDs)) + if !persist { + return optionsMap, colsInfoMap, nil + } + tblSavedOpts, tblSavedColChoice, tblSavedColList, err := b.getSavedAnalyzeOpts(tbl.TableInfo.ID, tbl.TableInfo) + if err != nil { + return nil, nil, err + } + tblOpts := tblSavedOpts + tblColChoice := tblSavedColChoice + tblColList := tblSavedColList + if isAnalyzeTable { + tblOpts = mergeAnalyzeOptions(astOpts, tblSavedOpts) + tblColChoice, tblColList = mergeColumnList(astColChoice, astColList, tblSavedColChoice, tblSavedColList) + } + tblFilledOpts := fillAnalyzeOptionsV2(tblOpts) + tblColsInfo, tblColList, err := b.getFullAnalyzeColumnsInfo(tbl, tblColChoice, tblColList, predicateCols, mustAnalyzedCols, mustAllColumns, false) + if err != nil { + return nil, nil, err + } + tblAnalyzeOptions := V2AnalyzeOptions{ + PhyTableID: tbl.TableInfo.ID, + RawOpts: tblOpts, + FilledOpts: tblFilledOpts, + ColChoice: tblColChoice, + ColumnList: tblColList, + } + optionsMap[tbl.TableInfo.ID] = tblAnalyzeOptions + colsInfoMap[tbl.TableInfo.ID] = tblColsInfo + for _, id := range physicalIDs { + if id != tbl.TableInfo.ID { + parSavedOpts, parSavedColChoice, parSavedColList, err := b.getSavedAnalyzeOpts(id, tbl.TableInfo) + if err != nil { + return nil, nil, err + } + // merge partition level options with table level options firstly + savedOpts := mergeAnalyzeOptions(parSavedOpts, tblSavedOpts) + savedColChoice, savedColList := mergeColumnList(parSavedColChoice, parSavedColList, tblSavedColChoice, tblSavedColList) + // then merge statement level options + mergedOpts := mergeAnalyzeOptions(astOpts, savedOpts) + filledMergedOpts := fillAnalyzeOptionsV2(mergedOpts) + finalColChoice, mergedColList := mergeColumnList(astColChoice, astColList, savedColChoice, savedColList) + finalColsInfo, finalColList, err := b.getFullAnalyzeColumnsInfo(tbl, finalColChoice, mergedColList, predicateCols, mustAnalyzedCols, mustAllColumns, false) + if err != nil { + return nil, nil, err + } + parV2Options := V2AnalyzeOptions{ + PhyTableID: id, + RawOpts: mergedOpts, + FilledOpts: filledMergedOpts, + ColChoice: finalColChoice, + ColumnList: finalColList, + } + optionsMap[id] = parV2Options + colsInfoMap[id] = finalColsInfo + } + } + return optionsMap, colsInfoMap, nil +} + +func (b *PlanBuilder) getSavedAnalyzeOpts(physicalID int64, tblInfo *model.TableInfo) (map[ast.AnalyzeOptionType]uint64, model.ColumnChoice, []*model.ColumnInfo, error) { + analyzeOptions := map[ast.AnalyzeOptionType]uint64{} + exec := b.ctx.(sqlexec.RestrictedSQLExecutor) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, "select sample_num,sample_rate,buckets,topn,column_choice,column_ids from mysql.analyze_options where table_id = %?", physicalID) + if err != nil { + return nil, model.DefaultChoice, nil, err + } + if len(rows) <= 0 { + return analyzeOptions, model.DefaultChoice, nil, nil + } + row := rows[0] + sampleNum := row.GetInt64(0) + if sampleNum > 0 { + analyzeOptions[ast.AnalyzeOptNumSamples] = uint64(sampleNum) + } + sampleRate := row.GetFloat64(1) + if sampleRate > 0 { + analyzeOptions[ast.AnalyzeOptSampleRate] = math.Float64bits(sampleRate) + } + buckets := row.GetInt64(2) + if buckets > 0 { + analyzeOptions[ast.AnalyzeOptNumBuckets] = uint64(buckets) + } + topn := row.GetInt64(3) + if topn >= 0 { + analyzeOptions[ast.AnalyzeOptNumTopN] = uint64(topn) + } + colType := row.GetEnum(4) + switch colType.Name { + case "ALL": + return analyzeOptions, model.AllColumns, tblInfo.Columns, nil + case "LIST": + colIDStrs := strings.Split(row.GetString(5), ",") + colList := make([]*model.ColumnInfo, 0, len(colIDStrs)) + for _, colIDStr := range colIDStrs { + colID, _ := strconv.ParseInt(colIDStr, 10, 64) + colInfo := model.FindColumnInfoByID(tblInfo.Columns, colID) + if colInfo != nil { + colList = append(colList, colInfo) + } + } + return analyzeOptions, model.ColumnList, colList, nil + case "PREDICATE": + return analyzeOptions, model.PredicateColumns, nil, nil + default: + return analyzeOptions, model.DefaultChoice, nil, nil + } +} + +func mergeAnalyzeOptions(stmtOpts map[ast.AnalyzeOptionType]uint64, savedOpts map[ast.AnalyzeOptionType]uint64) map[ast.AnalyzeOptionType]uint64 { + merged := map[ast.AnalyzeOptionType]uint64{} + for optType := range ast.AnalyzeOptionString { + if stmtOpt, ok := stmtOpts[optType]; ok { + merged[optType] = stmtOpt + } else if savedOpt, ok := savedOpts[optType]; ok { + merged[optType] = savedOpt + } + } + return merged +} + +func mergeColumnList(choice1 model.ColumnChoice, list1 []*model.ColumnInfo, choice2 model.ColumnChoice, list2 []*model.ColumnInfo) (model.ColumnChoice, []*model.ColumnInfo) { + if choice1 != model.DefaultChoice { + return choice1, list1 + } + return choice2, list2 +} + func (b *PlanBuilder) buildAnalyzeTable(as *ast.AnalyzeTableStmt, opts map[ast.AnalyzeOptionType]uint64, version int) (Plan, error) { p := &Analyze{Opts: opts} + p.OptionsMap = make(map[int64]V2AnalyzeOptions) + usePersistedOptions := variable.PersistAnalyzeOptions.Load() for _, tbl := range as.TableNames { if tbl.TableInfo.IsView() { - return nil, errors.Errorf("analyze view %s is not supported now.", tbl.Name.O) + return nil, errors.Errorf("analyze view %s is not supported now", tbl.Name.O) } if tbl.TableInfo.IsSequence() { - return nil, errors.Errorf("analyze sequence %s is not supported now.", tbl.Name.O) + return nil, errors.Errorf("analyze sequence %s is not supported now", tbl.Name.O) } idxInfo, colInfo := getColsInfo(tbl) physicalIDs, names, err := GetPhysicalIDsAndPartitionNames(tbl.TableInfo, as.PartitionNames) @@ -2022,13 +2327,16 @@ func (b *PlanBuilder) buildAnalyzeTable(as *ast.AnalyzeTableStmt, opts map[ast.A } } if version == statistics.Version2 { - p.ColTasks, err = b.buildAnalyzeFullSamplingTask(as, p.ColTasks, physicalIDs, names, tbl, version) + p.ColTasks, err = b.buildAnalyzeFullSamplingTask(as, p.ColTasks, physicalIDs, names, tbl, version, usePersistedOptions, p.OptionsMap) if err != nil { return nil, err } continue } - if len(as.ColumnNames) > 0 { + if as.ColumnChoice == model.PredicateColumns { + return nil, errors.Errorf("Only the analyze version 2 supports analyzing predicate columns") + } + if as.ColumnChoice == model.ColumnList { return nil, errors.Errorf("Only the analyze version 2 supports analyzing the specified columns") } for _, idx := range idxInfo { @@ -2098,7 +2406,7 @@ func (b *PlanBuilder) buildAnalyzeIndex(as *ast.AnalyzeTableStmt, opts map[ast.A versionIsSame := statsHandle.CheckAnalyzeVersion(tblInfo, physicalIDs, &version) if !versionIsSame { if b.ctx.GetSessionVars().EnableFastAnalyze { - return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1.") + return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1") } b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead")) } @@ -2163,7 +2471,7 @@ func (b *PlanBuilder) buildAnalyzeAllIndex(as *ast.AnalyzeTableStmt, opts map[as versionIsSame := statsHandle.CheckAnalyzeVersion(tblInfo, physicalIDs, &version) if !versionIsSame { if b.ctx.GetSessionVars().EnableFastAnalyze { - return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1.") + return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1") } b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead")) } @@ -2239,6 +2547,59 @@ var analyzeOptionDefaultV2 = map[ast.AnalyzeOptionType]uint64{ ast.AnalyzeOptSampleRate: math.Float64bits(-1), } +func parseAnalyzeOptionsV2(opts []ast.AnalyzeOpt) (map[ast.AnalyzeOptionType]uint64, error) { + optMap := make(map[ast.AnalyzeOptionType]uint64, len(analyzeOptionDefault)) + sampleNum, sampleRate := uint64(0), 0.0 + for _, opt := range opts { + datumValue := opt.Value.(*driver.ValueExpr).Datum + switch opt.Type { + case ast.AnalyzeOptNumTopN: + v := datumValue.GetUint64() + if v > analyzeOptionLimit[opt.Type] { + return nil, errors.Errorf("Value of analyze option %s should not be larger than %d", ast.AnalyzeOptionString[opt.Type], analyzeOptionLimit[opt.Type]) + } + optMap[opt.Type] = v + case ast.AnalyzeOptSampleRate: + // Only Int/Float/Decimal is accepted, so pass nil here is safe. + fVal, err := datumValue.ToFloat64(nil) + if err != nil { + return nil, err + } + limit := math.Float64frombits(analyzeOptionLimit[opt.Type]) + if fVal <= 0 || fVal > limit { + return nil, errors.Errorf("Value of analyze option %s should not larger than %f, and should be greater than 0", ast.AnalyzeOptionString[opt.Type], limit) + } + sampleRate = fVal + optMap[opt.Type] = math.Float64bits(fVal) + default: + v := datumValue.GetUint64() + if opt.Type == ast.AnalyzeOptNumSamples { + sampleNum = v + } + if v == 0 || v > analyzeOptionLimit[opt.Type] { + return nil, errors.Errorf("Value of analyze option %s should be positive and not larger than %d", ast.AnalyzeOptionString[opt.Type], analyzeOptionLimit[opt.Type]) + } + optMap[opt.Type] = v + } + } + if sampleNum > 0 && sampleRate > 0 { + return nil, errors.Errorf("You can only either set the value of the sample num or set the value of the sample rate. Don't set both of them") + } + return optMap, nil +} + +func fillAnalyzeOptionsV2(optMap map[ast.AnalyzeOptionType]uint64) map[ast.AnalyzeOptionType]uint64 { + filledMap := make(map[ast.AnalyzeOptionType]uint64, len(analyzeOptionDefault)) + for key, defaultVal := range analyzeOptionDefaultV2 { + if val, ok := optMap[key]; ok { + filledMap[key] = val + } else { + filledMap[key] = defaultVal + } + } + return filledMap +} + func handleAnalyzeOptions(opts []ast.AnalyzeOpt, statsVer int) (map[ast.AnalyzeOptionType]uint64, error) { optMap := make(map[ast.AnalyzeOptionType]uint64, len(analyzeOptionDefault)) if statsVer == statistics.Version1 { @@ -2287,7 +2648,7 @@ func handleAnalyzeOptions(opts []ast.AnalyzeOpt, statsVer int) (map[ast.AnalyzeO } } if sampleNum > 0 && sampleRate > 0 { - return nil, errors.Errorf("You can only either set the value of the sample num or set the value of the sample rate. Don't set both of them.") + return nil, errors.Errorf("You can only either set the value of the sample num or set the value of the sample rate. Don't set both of them") } if optMap[ast.AnalyzeOptCMSketchWidth]*optMap[ast.AnalyzeOptCMSketchDepth] > CMSketchSizeLimit { return nil, errors.Errorf("cm sketch size(depth * width) should not larger than %d", CMSketchSizeLimit) @@ -2298,11 +2659,11 @@ func handleAnalyzeOptions(opts []ast.AnalyzeOpt, statsVer int) (map[ast.AnalyzeO func (b *PlanBuilder) buildAnalyze(as *ast.AnalyzeTableStmt) (Plan, error) { // If enable fast analyze, the storage must be tikv.Storage. if _, isTikvStorage := b.ctx.GetStore().(tikv.Storage); !isTikvStorage && b.ctx.GetSessionVars().EnableFastAnalyze { - return nil, errors.Errorf("Only support fast analyze in tikv storage.") + return nil, errors.Errorf("Only support fast analyze in tikv storage") } statsVersion := b.ctx.GetSessionVars().AnalyzeVersion if b.ctx.GetSessionVars().EnableFastAnalyze && statsVersion >= statistics.Version2 { - return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently.") + return nil, errors.Errorf("Fast analyze hasn't reached General Availability and only support analyze version 1 currently") } for _, tbl := range as.TableNames { user := b.ctx.GetSessionVars().User @@ -2363,7 +2724,7 @@ func buildCleanupIndexFields() (*expression.Schema, types.NameSlice) { } func buildShowDDLJobsFields() (*expression.Schema, types.NameSlice) { - schema := newColumnsWithNames(11) + schema := newColumnsWithNames(12) schema.Append(buildColumnWithName("", "JOB_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumnWithName("", "DB_NAME", mysql.TypeVarchar, 64)) schema.Append(buildColumnWithName("", "TABLE_NAME", mysql.TypeVarchar, 64)) @@ -2372,6 +2733,7 @@ func buildShowDDLJobsFields() (*expression.Schema, types.NameSlice) { schema.Append(buildColumnWithName("", "SCHEMA_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumnWithName("", "TABLE_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumnWithName("", "ROW_COUNT", mysql.TypeLonglong, 4)) + schema.Append(buildColumnWithName("", "CREATE_TIME", mysql.TypeDatetime, 19)) schema.Append(buildColumnWithName("", "START_TIME", mysql.TypeDatetime, 19)) schema.Append(buildColumnWithName("", "END_TIME", mysql.TypeDatetime, 19)) schema.Append(buildColumnWithName("", "STATE", mysql.TypeVarchar, 64)) @@ -2485,7 +2847,7 @@ type columnsWithNames struct { names types.NameSlice } -func newColumnsWithNames(cap int) *columnsWithNames { +func newColumnsWithNames(c int) *columnsWithNames { return &columnsWithNames{ cols: make([]*expression.Column, 0, 2), names: make(types.NameSlice, 0, 2), @@ -2541,8 +2903,26 @@ func (b *PlanBuilder) buildShow(ctx context.Context, show *ast.ShowStmt) (Plan, }.Init(b.ctx) isView := false isSequence := false + switch show.Tp { - case ast.ShowTables, ast.ShowTableStatus: + case ast.ShowColumns: + var extractor ShowColumnsTableExtractor + if extractor.Extract(show) { + p.Extractor = &extractor + // avoid to build Selection. + show.Pattern = nil + } + case ast.ShowTables: + if p.DBName == "" { + return nil, ErrNoDB + } + var extractor ShowTablesTableExtractor + if extractor.Extract(show) { + p.Extractor = &extractor + // Avoid building Selection. + show.Pattern = nil + } + case ast.ShowTableStatus: if p.DBName == "" { return nil, ErrNoDB } @@ -2605,6 +2985,14 @@ func (b *PlanBuilder) buildShow(ctx context.Context, show *ast.ShowStmt) (Plan, return nil, ErrOptOnTemporaryTable.GenWithStackByArgs("show table regions") } } + if show.Tp == ast.ShowVariables { + var extractor ShowVariablesExtractor + if extractor.Extract(show) { + p.Extractor = &extractor + // Avoid building Selection. + show.Pattern = nil + } + } schema, names := buildShowSchema(show, isView, isSequence) p.SetSchema(schema) p.names = names @@ -2714,6 +3102,10 @@ func (b *PlanBuilder) buildSimple(ctx context.Context, node ast.StmtNode) (Plan, b.visitInfo = appendDynamicVisitInfo(b.visitInfo, "CONNECTION_ADMIN", false, err) b.visitInfo = appendVisitInfoIsRestrictedUser(b.visitInfo, b.ctx, &auth.UserIdentity{Username: pi.User, Hostname: pi.Host}, "RESTRICTED_CONNECTION_ADMIN") } + } else if raw.ConnectionID == util2.GetAutoAnalyzeProcID() { + // Only the users with SUPER or CONNECTION_ADMIN privilege can kill auto analyze. + err := ErrSpecificAccessDenied.GenWithStackByArgs("SUPER or CONNECTION_ADMIN") + b.visitInfo = appendDynamicVisitInfo(b.visitInfo, "CONNECTION_ADMIN", false, err) } } case *ast.UseStmt: @@ -2735,7 +3127,7 @@ func (b *PlanBuilder) buildSimple(ctx context.Context, node ast.StmtNode) (Plan, case *ast.BeginStmt: readTS := b.ctx.GetSessionVars().TxnReadTS.PeakTxnReadTS() if raw.AsOf != nil { - startTS, err := calculateTsExpr(b.ctx, raw.AsOf) + startTS, err := staleread.CalculateAsOfTsExpr(b.ctx, raw.AsOf) if err != nil { return nil, err } @@ -2752,36 +3144,6 @@ func (b *PlanBuilder) buildSimple(ctx context.Context, node ast.StmtNode) (Plan, return p, nil } -// calculateTsExpr calculates the TsExpr of AsOfClause to get a StartTS. -func calculateTsExpr(sctx sessionctx.Context, asOfClause *ast.AsOfClause) (uint64, error) { - tsVal, err := evalAstExpr(sctx, asOfClause.TsExpr) - if err != nil { - return 0, err - } - toTypeTimestamp := types.NewFieldType(mysql.TypeTimestamp) - // We need at least the millionsecond here, so set fsp to 3. - toTypeTimestamp.Decimal = 3 - tsTimestamp, err := tsVal.ConvertTo(sctx.GetSessionVars().StmtCtx, toTypeTimestamp) - if err != nil { - return 0, err - } - tsTime, err := tsTimestamp.GetMysqlTime().GoTime(sctx.GetSessionVars().Location()) - if err != nil { - return 0, err - } - return oracle.GoTimeToTS(tsTime), nil -} - -func calculateTsWithReadStaleness(sctx sessionctx.Context, readStaleness time.Duration) (uint64, error) { - nowVal, err := expression.GetStmtTimestamp(sctx) - if err != nil { - return 0, err - } - tsVal := nowVal.Add(readStaleness) - minTsVal := expression.GetMinSafeTime(sctx) - return oracle.GoTimeToTS(expression.CalAppropriateTime(tsVal, nowVal, minTsVal)), nil -} - func collectVisitInfoFromRevokeStmt(sctx sessionctx.Context, vi []visitInfo, stmt *ast.RevokeStmt) ([]visitInfo, error) { // To use REVOKE, you must have the GRANT OPTION privilege, // and you must have the privileges that you are granting. @@ -2920,15 +3282,6 @@ func (b *PlanBuilder) getDefaultValue(col *table.Column) (*expression.Constant, return &expression.Constant{Value: value, RetType: &col.FieldType}, nil } -func (b *PlanBuilder) findDefaultValue(cols []*table.Column, name *ast.ColumnName) (*expression.Constant, error) { - for _, col := range cols { - if col.Name.L == name.Name.L { - return b.getDefaultValue(col) - } - } - return nil, ErrUnknownColumn.GenWithStackByArgs(name.Name.O, "field_list") -} - // resolveGeneratedColumns resolves generated columns with their generation // expressions respectively. onDups indicates which columns are in on-duplicate list. func (b *PlanBuilder) resolveGeneratedColumns(ctx context.Context, columns []*table.Column, onDups map[string]struct{}, mockPlan LogicalPlan) (igc InsertGeneratedColumns, err error) { @@ -2937,7 +3290,7 @@ func (b *PlanBuilder) resolveGeneratedColumns(ctx context.Context, columns []*ta continue } columnName := &ast.ColumnName{Name: column.Name} - columnName.SetText(column.Name.O) + columnName.SetText(nil, column.Name.O) idx, err := expression.FindFieldName(mockPlan.OutputNames(), columnName) if err != nil { @@ -2977,16 +3330,16 @@ func (b *PlanBuilder) buildInsert(ctx context.Context, insert *ast.InsertStmt) ( } tableInfo := tn.TableInfo if tableInfo.IsView() { - err := errors.Errorf("insert into view %s is not supported now.", tableInfo.Name.O) + err := errors.Errorf("insert into view %s is not supported now", tableInfo.Name.O) if insert.IsReplace { - err = errors.Errorf("replace into view %s is not supported now.", tableInfo.Name.O) + err = errors.Errorf("replace into view %s is not supported now", tableInfo.Name.O) } return nil, err } if tableInfo.IsSequence() { - err := errors.Errorf("insert into sequence %s is not supported now.", tableInfo.Name.O) + err := errors.Errorf("insert into sequence %s is not supported now", tableInfo.Name.O) if insert.IsReplace { - err = errors.Errorf("replace into sequence %s is not supported now.", tableInfo.Name.O) + err = errors.Errorf("replace into sequence %s is not supported now", tableInfo.Name.O) } return nil, err } @@ -2997,7 +3350,7 @@ func (b *PlanBuilder) buildInsert(ctx context.Context, insert *ast.InsertStmt) ( } tableInPlan, ok := b.is.TableByID(tableInfo.ID) if !ok { - return nil, errors.Errorf("Can't get table %s.", tableInfo.Name.O) + return nil, errors.Errorf("Can't get table %s", tableInfo.Name.O) } insertPlan := Insert{ @@ -3118,7 +3471,7 @@ func (p *Insert) resolveOnDuplicate(onDup []*ast.Assignment, tblInfo *model.Tabl if err != nil { return nil, err } else if idx < 0 { - return nil, ErrUnknownColumn.GenWithStackByArgs(assign.Column.OrigColName(), "field list") + return nil, ErrUnknownColumn.GenWithStackByArgs(assign.Column.OrigColName(), clauseMsg[fieldList]) } column := colMap[assign.Column.Name.L] @@ -3126,18 +3479,18 @@ func (p *Insert) resolveOnDuplicate(onDup []*ast.Assignment, tblInfo *model.Tabl return nil, ErrUnknownColumn.GenWithStackByArgs(column.Name, clauseMsg[fieldList]) } // Check whether the column to be updated is the generated column. - defaultExpr := extractDefaultExpr(assign.Expr) - if defaultExpr != nil { - defaultExpr.Name = assign.Column - } // Note: For INSERT, REPLACE, and UPDATE, if a generated column is inserted into, replaced, or updated explicitly, the only permitted value is DEFAULT. // see https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html if column.IsGenerated() { - if defaultExpr != nil { + if IsDefaultExprSameColumn(p.tableColNames[idx:idx+1], assign.Expr) { continue } return nil, ErrBadGeneratedColumn.GenWithStackByArgs(assign.Column.Name.O, tblInfo.Name.O) } + defaultExpr := extractDefaultExpr(assign.Expr) + if defaultExpr != nil { + defaultExpr.Name = assign.Column + } onDupColSet[column.Name.L] = struct{}{} @@ -3184,6 +3537,68 @@ func (b *PlanBuilder) getAffectCols(insertStmt *ast.InsertStmt, insertPlan *Inse return affectedValuesCols, nil } +func (b PlanBuilder) getInsertColExpr(ctx context.Context, insertPlan *Insert, mockTablePlan *LogicalTableDual, col *table.Column, expr ast.ExprNode, checkRefColumn func(n ast.Node) ast.Node) (outExpr expression.Expression, err error) { + if col.Hidden { + return nil, ErrUnknownColumn.GenWithStackByArgs(col.Name, clauseMsg[fieldList]) + } + switch x := expr.(type) { + case *ast.DefaultExpr: + refCol := col + if x.Name != nil { + refCol = table.FindColLowerCase(insertPlan.Table.Cols(), x.Name.Name.L) + if refCol == nil { + return nil, ErrUnknownColumn.GenWithStackByArgs(x.Name.OrigColName(), clauseMsg[fieldList]) + } + // Cannot use DEFAULT(generated column) except for the same column + if col != refCol && (col.IsGenerated() || refCol.IsGenerated()) { + return nil, ErrBadGeneratedColumn.GenWithStackByArgs(col.Name.O, insertPlan.Table.Meta().Name.O) + } else if col == refCol && col.IsGenerated() { + return nil, nil + } + } else if col.IsGenerated() { + // See note in the end of the function. Only default for generated columns are OK. + return nil, nil + } + outExpr, err = b.getDefaultValue(refCol) + case *driver.ValueExpr: + outExpr = &expression.Constant{ + Value: x.Datum, + RetType: &x.Type, + } + case *driver.ParamMarkerExpr: + outExpr, err = expression.ParamMarkerExpression(b.ctx, x, false) + default: + b.curClause = fieldList + // subquery in insert values should not reference upper scope + usingPlan := mockTablePlan + if _, ok := expr.(*ast.SubqueryExpr); ok { + usingPlan = LogicalTableDual{}.Init(b.ctx, b.getSelectOffset()) + } + var np LogicalPlan + outExpr, np, err = b.rewriteWithPreprocess(ctx, expr, usingPlan, nil, nil, true, checkRefColumn) + if np != nil { + if _, ok := np.(*LogicalTableDual); !ok { + // See issue#30626 and the related tests in function TestInsertValuesWithSubQuery for more details. + // This is a TODO and we will support it later. + return nil, errors.New("Insert's SET operation or VALUES_LIST doesn't support complex subqueries now") + } + } + } + if err != nil { + return nil, err + } + if insertPlan.AllAssignmentsAreConstant { + _, isConstant := outExpr.(*expression.Constant) + insertPlan.AllAssignmentsAreConstant = isConstant + } + // Note: For INSERT, REPLACE, and UPDATE, if a generated column is inserted into, replaced, or updated explicitly, the only permitted value is DEFAULT. + // see https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html + if col.IsGenerated() { + return nil, ErrBadGeneratedColumn.GenWithStackByArgs(col.Name.O, insertPlan.Table.Meta().Name.O) + } + return outExpr, nil +} + func (b *PlanBuilder) buildSetValuesOfInsert(ctx context.Context, insert *ast.InsertStmt, insertPlan *Insert, mockTablePlan *LogicalTableDual, checkRefColumn func(n ast.Node) ast.Node) error { tableInfo := insertPlan.Table.Meta() colNames := make([]string, 0, len(insert.Setlist)) @@ -3205,40 +3620,15 @@ func (b *PlanBuilder) buildSetValuesOfInsert(ctx context.Context, insert *ast.In if missingColIdx >= 0 { return ErrUnknownColumn.GenWithStackByArgs(insert.Setlist[missingColIdx].Column.Name.O, clauseMsg[fieldList]) } - generatedColumns := make(map[string]struct{}, len(tCols)) - for _, tCol := range tCols { - if tCol.IsGenerated() { - generatedColumns[tCol.Name.L] = struct{}{} - } - } insertPlan.AllAssignmentsAreConstant = true for i, assign := range insert.Setlist { - defaultExpr := extractDefaultExpr(assign.Expr) - if defaultExpr != nil { - defaultExpr.Name = assign.Column - } - // Note: For INSERT, REPLACE, and UPDATE, if a generated column is inserted into, replaced, or updated explicitly, the only permitted value is DEFAULT. - // see https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html - if _, ok := generatedColumns[assign.Column.Name.L]; ok { - if defaultExpr != nil { - continue - } - return ErrBadGeneratedColumn.GenWithStackByArgs(assign.Column.Name.O, tableInfo.Name.O) - } - b.curClause = fieldList - // subquery in insert values should not reference upper scope - usingPlan := mockTablePlan - if _, ok := assign.Expr.(*ast.SubqueryExpr); ok { - usingPlan = LogicalTableDual{}.Init(b.ctx, b.getSelectOffset()) - } - expr, _, err := b.rewriteWithPreprocess(ctx, assign.Expr, usingPlan, nil, nil, true, checkRefColumn) + expr, err := b.getInsertColExpr(ctx, insertPlan, mockTablePlan, tCols[i], assign.Expr, checkRefColumn) if err != nil { return err } - if insertPlan.AllAssignmentsAreConstant { - _, isConstant := expr.(*expression.Constant) - insertPlan.AllAssignmentsAreConstant = isConstant + if expr == nil { + continue } insertPlan.SetList = append(insertPlan.SetList, &expression.Assignment{ @@ -3268,7 +3658,6 @@ func (b *PlanBuilder) buildValuesListOfInsert(ctx context.Context, insert *ast.I } insertPlan.AllAssignmentsAreConstant = true - totalTableCols := insertPlan.Table.Cols() for i, valuesItem := range insert.Lists { // The length of all the value_list should be the same. // "insert into t values (), ()" is valid. @@ -3280,54 +3669,12 @@ func (b *PlanBuilder) buildValuesListOfInsert(ctx context.Context, insert *ast.I } exprList := make([]expression.Expression, 0, len(valuesItem)) for j, valueItem := range valuesItem { - var expr expression.Expression - var err error - var generatedColumnWithDefaultExpr bool - col := affectedValuesCols[j] - switch x := valueItem.(type) { - case *ast.DefaultExpr: - if col.IsGenerated() { - if x.Name != nil { - return ErrBadGeneratedColumn.GenWithStackByArgs(col.Name.O, insertPlan.Table.Meta().Name.O) - } - generatedColumnWithDefaultExpr = true - break - } - if x.Name != nil { - expr, err = b.findDefaultValue(totalTableCols, x.Name) - } else { - expr, err = b.getDefaultValue(affectedValuesCols[j]) - } - case *driver.ValueExpr: - expr = &expression.Constant{ - Value: x.Datum, - RetType: &x.Type, - } - case *driver.ParamMarkerExpr: - expr, err = expression.ParamMarkerExpression(b.ctx, x) - default: - b.curClause = fieldList - // subquery in insert values should not reference upper scope - usingPlan := mockTablePlan - if _, ok := valueItem.(*ast.SubqueryExpr); ok { - usingPlan = LogicalTableDual{}.Init(b.ctx, b.getSelectOffset()) - } - expr, _, err = b.rewriteWithPreprocess(ctx, valueItem, usingPlan, nil, nil, true, checkRefColumn) - } + expr, err := b.getInsertColExpr(ctx, insertPlan, mockTablePlan, affectedValuesCols[j], valueItem, checkRefColumn) if err != nil { return err } - if insertPlan.AllAssignmentsAreConstant { - _, isConstant := expr.(*expression.Constant) - insertPlan.AllAssignmentsAreConstant = isConstant - } - // Note: For INSERT, REPLACE, and UPDATE, if a generated column is inserted into, replaced, or updated explicitly, the only permitted value is DEFAULT. - // see https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html - if col.IsGenerated() { - if generatedColumnWithDefaultExpr { - continue - } - return ErrBadGeneratedColumn.GenWithStackByArgs(col.Name.O, insertPlan.Table.Meta().Name.O) + if expr == nil { + continue } exprList = append(exprList, expr) } @@ -3494,11 +3841,15 @@ func (b *PlanBuilder) buildLoadData(ctx context.Context, ld *ast.LoadDataStmt) ( ColumnsAndUserVars: ld.ColumnsAndUserVars, }.Init(b.ctx) user := b.ctx.GetSessionVars().User - var insertErr error + var insertErr, deleteErr error if user != nil { insertErr = ErrTableaccessDenied.GenWithStackByArgs("INSERT", user.AuthUsername, user.AuthHostname, p.Table.Name.O) + deleteErr = ErrTableaccessDenied.GenWithStackByArgs("DELETE", user.AuthUsername, user.AuthHostname, p.Table.Name.O) } b.visitInfo = appendVisitInfo(b.visitInfo, mysql.InsertPriv, p.Table.Schema.O, p.Table.Name.O, "", insertErr) + if p.OnDuplicate == ast.OnDuplicateKeyHandlingReplace { + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.DeletePriv, p.Table.Schema.O, p.Table.Name.O, "", deleteErr) + } tableInfo := p.Table.TableInfo tableInPlan, ok := b.is.TableByID(tableInfo.ID) if !ok { @@ -3926,7 +4277,7 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err } } if len(v.Cols) != schema.Len() { - return nil, ddl.ErrViewWrongList + return nil, dbterror.ErrViewWrongList } if b.ctx.GetSessionVars().User != nil { authErr = ErrTableaccessDenied.GenWithStackByArgs("CREATE VIEW", b.ctx.GetSessionVars().User.AuthUsername, @@ -4370,9 +4721,12 @@ func buildShowSchema(s *ast.ShowStmt, isView bool, isSequence bool) (schema *exp case ast.ShowBindings: names = []string{"Original_sql", "Bind_sql", "Default_db", "Status", "Create_time", "Update_time", "Charset", "Collation", "Source"} ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar} + case ast.ShowBindingCacheStatus: + names = []string{"bindings_in_cache", "bindings_in_table", "memory_usage", "memory_quota"} + ftypes = []byte{mysql.TypeLonglong, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeVarchar} case ast.ShowAnalyzeStatus: - names = []string{"Table_schema", "Table_name", "Partition_name", "Job_info", "Processed_rows", "Start_time", "End_time", "State"} - ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar} + names = []string{"Table_schema", "Table_name", "Partition_name", "Job_info", "Processed_rows", "Start_time", "End_time", "State", "Fail_reason", "Instance", "Process_ID"} + ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong} case ast.ShowBuiltins: names = []string{"Supported_builtin_functions"} ftypes = []byte{mysql.TypeVarchar} diff --git a/planner/core/planbuilder_test.go b/planner/core/planbuilder_test.go index b820da05ed9b0..5ff2084947170 100644 --- a/planner/core/planbuilder_test.go +++ b/planner/core/planbuilder_test.go @@ -19,10 +19,10 @@ import ( "fmt" "reflect" "strings" + "testing" "unsafe" _ "unsafe" // required by go:linkname - . "github.com/pingcap/check" "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" @@ -38,17 +38,10 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPlanBuilderSuite{}) - -func (s *testPlanBuilderSuite) SetUpSuite(c *C) { -} - -type testPlanBuilderSuite struct { -} - -func (s *testPlanBuilderSuite) TestShow(c *C) { +func TestShow(t *testing.T) { node := &ast.ShowStmt{} tps := []ast.ShowStmtType{ ast.ShowEngines, @@ -78,12 +71,12 @@ func (s *testPlanBuilderSuite) TestShow(c *C) { node.Tp = tp schema, _ := buildShowSchema(node, false, false) for _, col := range schema.Columns { - c.Assert(col.RetType.Flen, Greater, 0) + require.Greater(t, col.RetType.Flen, 0) } } } -func (s *testPlanBuilderSuite) TestGetPathByIndexName(c *C) { +func TestGetPathByIndexName(t *testing.T) { tblInfo := &model.TableInfo{ Indices: make([]*model.IndexInfo, 0), PKIsHandle: true, @@ -92,18 +85,19 @@ func (s *testPlanBuilderSuite) TestGetPathByIndexName(c *C) { accessPath := []*util.AccessPath{ {IsIntHandlePath: true}, {Index: &model.IndexInfo{Name: model.NewCIStr("idx")}}, + genTiFlashPath(tblInfo), } path := getPathByIndexName(accessPath, model.NewCIStr("idx"), tblInfo) - c.Assert(path, NotNil) - c.Assert(path, Equals, accessPath[1]) + require.NotNil(t, path) + require.Equal(t, accessPath[1], path) path = getPathByIndexName(accessPath, model.NewCIStr("primary"), tblInfo) - c.Assert(path, NotNil) - c.Assert(path, Equals, accessPath[0]) + require.NotNil(t, path) + require.Equal(t, accessPath[0], path) path = getPathByIndexName(accessPath, model.NewCIStr("not exists"), tblInfo) - c.Assert(path, IsNil) + require.Nil(t, path) tblInfo = &model.TableInfo{ Indices: make([]*model.IndexInfo, 0), @@ -111,10 +105,10 @@ func (s *testPlanBuilderSuite) TestGetPathByIndexName(c *C) { } path = getPathByIndexName(accessPath, model.NewCIStr("primary"), tblInfo) - c.Assert(path, IsNil) + require.Nil(t, path) } -func (s *testPlanBuilderSuite) TestRewriterPool(c *C) { +func TestRewriterPool(t *testing.T) { builder, _ := NewPlanBuilder().Init(MockContext(), nil, &hint.BlockHintProcessor{}) // Make sure PlanBuilder.getExpressionRewriter() provides clean rewriter from pool. @@ -132,17 +126,17 @@ func (s *testPlanBuilderSuite) TestRewriterPool(c *C) { // Then, pick again and check if it's cleaned up. builder.rewriterCounter++ cleanRewriter := builder.getExpressionRewriter(context.TODO(), nil) - c.Assert(cleanRewriter, Equals, dirtyRewriter) // Rewriter should be reused. - c.Assert(cleanRewriter.asScalar, Equals, false) - c.Assert(cleanRewriter.aggrMap, IsNil) - c.Assert(cleanRewriter.preprocess, IsNil) - c.Assert(cleanRewriter.insertPlan, IsNil) - c.Assert(cleanRewriter.disableFoldCounter, Equals, 0) - c.Assert(len(cleanRewriter.ctxStack), Equals, 0) + require.Equal(t, dirtyRewriter, cleanRewriter) + require.Equal(t, false, cleanRewriter.asScalar) + require.Nil(t, cleanRewriter.aggrMap) + require.Nil(t, cleanRewriter.preprocess) + require.Nil(t, cleanRewriter.insertPlan) + require.Zero(t, cleanRewriter.disableFoldCounter) + require.Len(t, cleanRewriter.ctxStack, 0) builder.rewriterCounter-- } -func (s *testPlanBuilderSuite) TestDisableFold(c *C) { +func TestDisableFold(t *testing.T) { // Functions like BENCHMARK() shall not be folded into result 0, // but normal outer function with constant args should be folded. // Types of expression and first layer of args will be validated. @@ -163,31 +157,31 @@ func (s *testPlanBuilderSuite) TestDisableFold(c *C) { } ctx := MockContext() - for _, t := range cases { - st, err := parser.New().ParseOneStmt(t.SQL, "", "") - c.Assert(err, IsNil) + for _, c := range cases { + st, err := parser.New().ParseOneStmt(c.SQL, "", "") + require.NoError(t, err) stmt := st.(*ast.SelectStmt) expr := stmt.Fields.Fields[0].Expr builder, _ := NewPlanBuilder().Init(ctx, nil, &hint.BlockHintProcessor{}) builder.rewriterCounter++ rewriter := builder.getExpressionRewriter(context.TODO(), nil) - c.Assert(rewriter, NotNil) - c.Assert(rewriter.disableFoldCounter, Equals, 0) - rewritenExpression, _, err := builder.rewriteExprNode(rewriter, expr, true) - c.Assert(err, IsNil) - c.Assert(rewriter.disableFoldCounter, Equals, 0) // Make sure the counter is reduced to 0 in the end. + require.NotNil(t, rewriter) + require.Equal(t, 0, rewriter.disableFoldCounter) + rewrittenExpression, _, err := builder.rewriteExprNode(rewriter, expr, true) + require.NoError(t, err) + require.Equal(t, 0, rewriter.disableFoldCounter) builder.rewriterCounter-- - c.Assert(rewritenExpression, FitsTypeOf, t.Expected) - for i, expectedArg := range t.Args { - rewritenArg := expression.GetFuncArg(rewritenExpression, i) - c.Assert(rewritenArg, FitsTypeOf, expectedArg) + require.IsType(t, c.Expected, rewrittenExpression) + for i, expectedArg := range c.Args { + rewrittenArg := expression.GetFuncArg(rewrittenExpression, i) + require.IsType(t, expectedArg, rewrittenArg) } } } -func (s *testPlanBuilderSuite) TestDeepClone(c *C) { +func TestDeepClone(t *testing.T) { tp := types.NewFieldType(mysql.TypeLonglong) expr := &expression.Column{RetType: tp} byItems := []*util.ByItems{{Expr: expr}} @@ -197,24 +191,32 @@ func (s *testPlanBuilderSuite) TestDeepClone(c *C) { whiteList := []string{"*property.StatsInfo", "*sessionctx.Context", "*mock.Context"} return checkDeepClonedCore(reflect.ValueOf(p1), reflect.ValueOf(p2), typeName(reflect.TypeOf(p1)), whiteList, nil) } - c.Assert(checkDeepClone(sort1, sort2), ErrorMatches, "invalid slice pointers, path PhysicalSort.ByItems") + err := checkDeepClone(sort1, sort2) + require.Error(t, err) + require.Regexp(t, "invalid slice pointers, path PhysicalSort.ByItems", err.Error()) byItems2 := []*util.ByItems{{Expr: expr}} sort2.ByItems = byItems2 - c.Assert(checkDeepClone(sort1, sort2), ErrorMatches, "same pointer, path PhysicalSort.ByItems.*Expression") + err = checkDeepClone(sort1, sort2) + require.Error(t, err) + require.Regexp(t, "same pointer, path PhysicalSort.ByItems.*Expression", err.Error()) expr2 := &expression.Column{RetType: tp} byItems2[0].Expr = expr2 - c.Assert(checkDeepClone(sort1, sort2), ErrorMatches, "same pointer, path PhysicalSort.ByItems.*Expression.FieldType") + err = checkDeepClone(sort1, sort2) + require.Error(t, err) + require.Regexp(t, "same pointer, path PhysicalSort.ByItems.*Expression.FieldType", err.Error()) expr2.RetType = types.NewFieldType(mysql.TypeString) - c.Assert(checkDeepClone(sort1, sort2), ErrorMatches, "different values, path PhysicalSort.ByItems.*Expression.FieldType.uint8") + err = checkDeepClone(sort1, sort2) + require.Error(t, err) + require.Regexp(t, "different values, path PhysicalSort.ByItems.*Expression.FieldType.uint8", err.Error()) expr2.RetType = types.NewFieldType(mysql.TypeLonglong) - c.Assert(checkDeepClone(sort1, sort2), IsNil) + require.NoError(t, checkDeepClone(sort1, sort2)) } -func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { +func TestPhysicalPlanClone(t *testing.T) { ctx := mock.NewContext() col, cst := &expression.Column{RetType: types.NewFieldType(mysql.TypeString)}, &expression.Constant{RetType: types.NewFieldType(mysql.TypeLonglong)} stats := &property.StatsInfo{RowCount: 1000} @@ -223,9 +225,9 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { idxInfo := &model.IndexInfo{} hist := &statistics.Histogram{Bounds: chunk.New(nil, 0, 0)} aggDesc1, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncAvg, []expression.Expression{col}, false) - c.Assert(err, IsNil) + require.NoError(t, err) aggDesc2, err := aggregation.NewAggFuncDesc(ctx, ast.AggFuncCount, []expression.Expression{cst}, true) - c.Assert(err, IsNil) + require.NoError(t, err) aggDescs := []*aggregation.AggFuncDesc{aggDesc1, aggDesc2} // table scan @@ -236,7 +238,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { } tableScan = tableScan.Init(ctx, 0) tableScan.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(tableScan), IsNil) + require.NoError(t, checkPhysicalPlanClone(tableScan)) // table reader tableReader := &PhysicalTableReader{ @@ -245,7 +247,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { StoreType: kv.TiFlash, } tableReader = tableReader.Init(ctx, 0) - c.Assert(checkPhysicalPlanClone(tableReader), IsNil) + require.NoError(t, checkPhysicalPlanClone(tableReader)) // index scan indexScan := &PhysicalIndexScan{ @@ -257,7 +259,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { } indexScan = indexScan.Init(ctx, 0) indexScan.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(indexScan), IsNil) + require.NoError(t, checkPhysicalPlanClone(indexScan)) // index reader indexReader := &PhysicalIndexReader{ @@ -266,7 +268,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { OutputColumns: []*expression.Column{col, col}, } indexReader = indexReader.Init(ctx, 0) - c.Assert(checkPhysicalPlanClone(indexReader), IsNil) + require.NoError(t, checkPhysicalPlanClone(indexReader)) // index lookup indexLookup := &PhysicalIndexLookUpReader{ @@ -278,33 +280,33 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { PushedLimit: &PushedDownLimit{1, 2}, } indexLookup = indexLookup.Init(ctx, 0) - c.Assert(checkPhysicalPlanClone(indexLookup), IsNil) + require.NoError(t, checkPhysicalPlanClone(indexLookup)) // selection sel := &PhysicalSelection{Conditions: []expression.Expression{col, cst}} sel = sel.Init(ctx, stats, 0) - c.Assert(checkPhysicalPlanClone(sel), IsNil) + require.NoError(t, checkPhysicalPlanClone(sel)) // projection proj := &PhysicalProjection{Exprs: []expression.Expression{col, cst}} proj = proj.Init(ctx, stats, 0) - c.Assert(checkPhysicalPlanClone(proj), IsNil) + require.NoError(t, checkPhysicalPlanClone(proj)) // limit lim := &PhysicalLimit{Count: 1, Offset: 2} lim = lim.Init(ctx, stats, 0) - c.Assert(checkPhysicalPlanClone(lim), IsNil) + require.NoError(t, checkPhysicalPlanClone(lim)) // sort byItems := []*util.ByItems{{Expr: col}, {Expr: cst}} sort := &PhysicalSort{ByItems: byItems} sort = sort.Init(ctx, stats, 0) - c.Assert(checkPhysicalPlanClone(sort), IsNil) + require.NoError(t, checkPhysicalPlanClone(sort)) // topN topN := &PhysicalTopN{ByItems: byItems, Offset: 2333, Count: 2333} topN = topN.Init(ctx, stats, 0) - c.Assert(checkPhysicalPlanClone(topN), IsNil) + require.NoError(t, checkPhysicalPlanClone(topN)) // stream agg streamAgg := &PhysicalStreamAgg{basePhysicalAgg{ @@ -313,7 +315,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { }} streamAgg = streamAgg.initForStream(ctx, stats, 0) streamAgg.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(streamAgg), IsNil) + require.NoError(t, checkPhysicalPlanClone(streamAgg)) // hash agg hashAgg := &PhysicalHashAgg{basePhysicalAgg{ @@ -322,7 +324,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { }} hashAgg = hashAgg.initForHash(ctx, stats, 0) hashAgg.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(hashAgg), IsNil) + require.NoError(t, checkPhysicalPlanClone(hashAgg)) // hash join hashJoin := &PhysicalHashJoin{ @@ -331,7 +333,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { } hashJoin = hashJoin.Init(ctx, stats, 0) hashJoin.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(hashJoin), IsNil) + require.NoError(t, checkPhysicalPlanClone(hashJoin)) // merge join mergeJoin := &PhysicalMergeJoin{ @@ -340,7 +342,7 @@ func (s *testPlanBuilderSuite) TestPhysicalPlanClone(c *C) { } mergeJoin = mergeJoin.Init(ctx, stats, 0) mergeJoin.SetSchema(schema) - c.Assert(checkPhysicalPlanClone(mergeJoin), IsNil) + require.NoError(t, checkPhysicalPlanClone(mergeJoin)) } //go:linkname valueInterface reflect.valueInterface diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index 05ecb5c18eb41..bc0dec4ce0aa1 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -40,11 +40,13 @@ import ( "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" tidbutil "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/math" "github.com/pingcap/tidb/util/plancodec" "github.com/pingcap/tidb/util/stringutil" + "github.com/pingcap/tidb/util/tracing" "github.com/pingcap/tipb/go-tipb" tikvstore "github.com/tikv/client-go/v2/kv" "go.uber.org/zap" @@ -61,9 +63,11 @@ type PointGetPlan struct { IndexInfo *model.IndexInfo PartitionInfo *model.PartitionDefinition Handle kv.Handle - HandleParam *driver.ParamMarkerExpr + HandleConstant *expression.Constant + handleFieldType *types.FieldType IndexValues []types.Datum - IndexValueParams []*driver.ParamMarkerExpr + IndexConstants []*expression.Constant + ColsFieldType []*types.FieldType IdxCols []*expression.Column IdxColLens []int AccessConditions []expression.Expression @@ -79,9 +83,10 @@ type PointGetPlan struct { } type nameValuePair struct { - colName string - value types.Datum - param *driver.ParamMarkerExpr + colName string + colFieldType *types.FieldType + value types.Datum + con *expression.Constant } // Schema implements the Plan interface. @@ -112,7 +117,7 @@ func (p *PointGetPlan) ToPB(ctx sessionctx.Context, _ kv.StoreType) (*tipb.Execu // Clone implements PhysicalPlan interface. func (p *PointGetPlan) Clone() (PhysicalPlan, error) { - return nil, errors.Errorf("%T doesn't support cloning.", p) + return nil, errors.Errorf("%T doesn't support cloning", p) } // ExplainInfo implements Plan interface. @@ -144,7 +149,7 @@ func (p *PointGetPlan) AccessObject(normalized bool) string { buffer.WriteString(", partition:?") } else { buffer.WriteString(", partition:") - buffer.WriteString(p.PartitionInfo.Name.L) + buffer.WriteString(p.PartitionInfo.Name.O) } } if p.IndexInfo != nil { @@ -276,9 +281,11 @@ type BatchPointGetPlan struct { TblInfo *model.TableInfo IndexInfo *model.IndexInfo Handles []kv.Handle - HandleParams []*driver.ParamMarkerExpr + HandleType *types.FieldType + HandleParams []*expression.Constant // record all Parameters for Plan-Cache IndexValues [][]types.Datum - IndexValueParams [][]*driver.ParamMarkerExpr + IndexValueParams [][]*expression.Constant // record all Parameters for Plan-Cache + IndexColTypes []*types.FieldType AccessConditions []expression.Expression IdxCols []*expression.Column IdxColLens []int @@ -475,10 +482,17 @@ func TryFastPlan(ctx sessionctx.Context, node ast.Node) (p Plan) { switch x := node.(type) { case *ast.SelectStmt: defer func() { - if ctx.GetSessionVars().SelectLimit != math2.MaxUint64 && p != nil { + vars := ctx.GetSessionVars() + if vars.SelectLimit != math2.MaxUint64 && p != nil { ctx.GetSessionVars().StmtCtx.AppendWarning(errors.New("sql_select_limit is set, so point get plan is not activated")) p = nil } + if vars.StmtCtx.EnableOptimizeTrace && p != nil { + if vars.StmtCtx.OptimizeTracer == nil { + vars.StmtCtx.OptimizeTracer = &tracing.OptimizeTracer{} + } + vars.StmtCtx.OptimizeTracer.SetFastPlan(p.buildPlanTrace()) + } }() // Try to convert the `SELECT a, b, c FROM t WHERE (a, b, c) in ((1, 2, 4), (1, 3, 5))` to // `PhysicalUnionAll` which children are `PointGet` if exists an unique key (a, b, c) in table `t` @@ -575,20 +589,27 @@ func newBatchPointGetPlan( } if handleCol != nil { var handles = make([]kv.Handle, len(patternInExpr.List)) - var handleParams = make([]*driver.ParamMarkerExpr, len(patternInExpr.List)) + var handleParams = make([]*expression.Constant, len(patternInExpr.List)) for i, item := range patternInExpr.List { // SELECT * FROM t WHERE (key) in ((1), (2)) if p, ok := item.(*ast.ParenthesesExpr); ok { item = p.Expr } var d types.Datum - var param *driver.ParamMarkerExpr + var con *expression.Constant switch x := item.(type) { case *driver.ValueExpr: d = x.Datum case *driver.ParamMarkerExpr: - d = x.Datum - param = x + var err error + con, err = expression.ParamMarkerExpression(ctx, x, true) + if err != nil { + return nil + } + d, err = con.Eval(chunk.Row{}) + if err != nil { + return nil + } default: return nil } @@ -600,12 +621,13 @@ func newBatchPointGetPlan( return nil } handles[i] = kv.IntHandle(intDatum.GetInt64()) - handleParams[i] = param + handleParams[i] = con } return BatchPointGetPlan{ TblInfo: tbl, Handles: handles, HandleParams: handleParams, + HandleType: &handleCol.FieldType, PartitionExpr: partitionExpr, }.Init(ctx, statsInfo, schema, names, 0) } @@ -660,14 +682,15 @@ func newBatchPointGetPlan( } indexValues := make([][]types.Datum, len(patternInExpr.List)) - indexValueParams := make([][]*driver.ParamMarkerExpr, len(patternInExpr.List)) + indexValueParams := make([][]*expression.Constant, len(patternInExpr.List)) + var indexTypes []*types.FieldType for i, item := range patternInExpr.List { // SELECT * FROM t WHERE (key) in ((1), (2)) if p, ok := item.(*ast.ParenthesesExpr); ok { item = p.Expr } var values []types.Datum - var valuesParams []*driver.ParamMarkerExpr + var valuesParams []*expression.Constant switch x := item.(type) { case *ast.RowExpr: // The `len(values) == len(valuesParams)` should be satisfied in this mode @@ -675,7 +698,12 @@ func newBatchPointGetPlan( return nil } values = make([]types.Datum, len(x.Values)) - valuesParams = make([]*driver.ParamMarkerExpr, len(x.Values)) + valuesParams = make([]*expression.Constant, len(x.Values)) + initTypes := false + if indexTypes == nil { // only init once + indexTypes = make([]*types.FieldType, len(x.Values)) + initTypes = true + } for index, inner := range x.Values { permIndex := permutations[index] switch innerX := inner.(type) { @@ -686,12 +714,23 @@ func newBatchPointGetPlan( } values[permIndex] = innerX.Datum case *driver.ParamMarkerExpr: - dval := getPointGetValue(stmtCtx, colInfos[index], &innerX.Datum) + con, err := expression.ParamMarkerExpression(ctx, innerX, true) + if err != nil { + return nil + } + d, err := con.Eval(chunk.Row{}) + if err != nil { + return nil + } + dval := getPointGetValue(stmtCtx, colInfos[index], &d) if dval == nil { return nil } values[permIndex] = innerX.Datum - valuesParams[permIndex] = innerX + valuesParams[permIndex] = con + if initTypes { + indexTypes[permIndex] = &colInfos[index].FieldType + } default: return nil } @@ -711,12 +750,23 @@ func newBatchPointGetPlan( if len(whereColNames) != 1 { return nil } - dval := getPointGetValue(stmtCtx, colInfos[0], &x.Datum) + con, err := expression.ParamMarkerExpression(ctx, x, true) + if err != nil { + return nil + } + d, err := con.Eval(chunk.Row{}) + if err != nil { + return nil + } + dval := getPointGetValue(stmtCtx, colInfos[0], &d) if dval == nil { return nil } values = []types.Datum{*dval} - valuesParams = []*driver.ParamMarkerExpr{x} + valuesParams = []*expression.Constant{con} + if indexTypes == nil { // only init once + indexTypes = []*types.FieldType{&colInfos[0].FieldType} + } default: return nil } @@ -728,6 +778,7 @@ func newBatchPointGetPlan( IndexInfo: matchIdxInfo, IndexValues: indexValues, IndexValueParams: indexValueParams, + IndexColTypes: indexTypes, PartitionColPos: pos, PartitionExpr: partitionExpr, }.Init(ctx, statsInfo, schema, names, 0) @@ -870,7 +921,7 @@ func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt, check bool } pairs := make([]nameValuePair, 0, 4) - pairs, isTableDual := getNameValuePairs(ctx.GetSessionVars().StmtCtx, tbl, tblAlias, pairs, selStmt.Where) + pairs, isTableDual := getNameValuePairs(ctx, tbl, tblAlias, pairs, selStmt.Where) if pairs == nil && !isTableDual { return nil } @@ -908,7 +959,8 @@ func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt, check bool p := newPointGetPlan(ctx, dbName, schema, tbl, names) p.Handle = kv.IntHandle(handlePair.value.GetInt64()) p.UnsignedHandle = mysql.HasUnsignedFlag(fieldType.Flag) - p.HandleParam = handlePair.param + p.handleFieldType = fieldType + p.HandleConstant = handlePair.con p.PartitionInfo = partitionInfo return p } else if handlePair.value.Kind() != types.KindNull { @@ -941,7 +993,7 @@ func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt, check bool p.IsTableDual = true return p } - idxValues, idxValueParams := getIndexValues(idxInfo, pairs) + idxValues, idxConstant, colsFieldType := getIndexValues(idxInfo, pairs) if idxValues == nil { continue } @@ -960,7 +1012,8 @@ func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt, check bool p := newPointGetPlan(ctx, dbName, schema, tbl, names) p.IndexInfo = idxInfo p.IndexValues = idxValues - p.IndexValueParams = idxValueParams + p.IndexConstants = idxConstant + p.ColsFieldType = colsFieldType p.PartitionInfo = partitionInfo if p.PartitionInfo != nil { p.partitionColumnPos = findPartitionIdx(idxInfo, pos, pairs) @@ -1033,7 +1086,7 @@ func newPointGetPlan(ctx sessionctx.Context, dbName string, schema *expression.S func checkFastPlanPrivilege(ctx sessionctx.Context, dbName, tableName string, checkTypes ...mysql.PrivilegeType) error { pm := privilege.GetPrivilegeManager(ctx) - var visitInfos []visitInfo + visitInfos := make([]visitInfo, 0, len(checkTypes)) for _, checkType := range checkTypes { if pm != nil && !pm.RequestVerification(ctx.GetSessionVars().ActiveRoles, dbName, tableName, "", checkType) { return ErrPrivilegeCheckFail.GenWithStackByArgs(checkType.String()) @@ -1145,42 +1198,58 @@ func getSingleTableNameAndAlias(tableRefs *ast.TableRefsClause) (tblName *ast.Ta } // getNameValuePairs extracts `column = constant/paramMarker` conditions from expr as name value pairs. -func getNameValuePairs(stmtCtx *stmtctx.StatementContext, tbl *model.TableInfo, tblName model.CIStr, nvPairs []nameValuePair, expr ast.ExprNode) ( +func getNameValuePairs(ctx sessionctx.Context, tbl *model.TableInfo, tblName model.CIStr, nvPairs []nameValuePair, expr ast.ExprNode) ( pairs []nameValuePair, isTableDual bool) { + stmtCtx := ctx.GetSessionVars().StmtCtx binOp, ok := expr.(*ast.BinaryOperationExpr) if !ok { return nil, false } if binOp.Op == opcode.LogicAnd { - nvPairs, isTableDual = getNameValuePairs(stmtCtx, tbl, tblName, nvPairs, binOp.L) + nvPairs, isTableDual = getNameValuePairs(ctx, tbl, tblName, nvPairs, binOp.L) if nvPairs == nil || isTableDual { return nil, isTableDual } - nvPairs, isTableDual = getNameValuePairs(stmtCtx, tbl, tblName, nvPairs, binOp.R) + nvPairs, isTableDual = getNameValuePairs(ctx, tbl, tblName, nvPairs, binOp.R) if nvPairs == nil || isTableDual { return nil, isTableDual } return nvPairs, isTableDual } else if binOp.Op == opcode.EQ { - var d types.Datum - var colName *ast.ColumnNameExpr - var param *driver.ParamMarkerExpr - var ok bool + var ( + d types.Datum + colName *ast.ColumnNameExpr + ok bool + con *expression.Constant + err error + ) if colName, ok = binOp.L.(*ast.ColumnNameExpr); ok { switch x := binOp.R.(type) { case *driver.ValueExpr: d = x.Datum case *driver.ParamMarkerExpr: - d = x.Datum - param = x + con, err = expression.ParamMarkerExpression(ctx, x, true) + if err != nil { + return nil, false + } + d, err = con.Eval(chunk.Row{}) + if err != nil { + return nil, false + } } } else if colName, ok = binOp.R.(*ast.ColumnNameExpr); ok { switch x := binOp.L.(type) { case *driver.ValueExpr: d = x.Datum case *driver.ParamMarkerExpr: - d = x.Datum - param = x + con, err = expression.ParamMarkerExpression(ctx, x, true) + if err != nil { + return nil, false + } + d, err = con.Eval(chunk.Row{}) + if err != nil { + return nil, false + } } } else { return nil, false @@ -1196,9 +1265,10 @@ func getNameValuePairs(stmtCtx *stmtctx.StatementContext, tbl *model.TableInfo, return nil, false } col := model.FindColumnInfo(tbl.Cols(), colName.Name.Name.L) - if col == nil || // Handling the case when the column is _tidb_rowid. - (col.Tp == mysql.TypeString && col.Collate == charset.CollationBin) { // This type we needn't to pad `\0` in here. - return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, value: d, param: param}), false + if col == nil { // Handling the case when the column is _tidb_rowid. + return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: types.NewFieldType(mysql.TypeLonglong), value: d, con: con}), false + } else if col.Tp == mysql.TypeString && col.Collate == charset.CollationBin { // This type we needn't to pad `\0` in here. + return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: &col.FieldType, value: d, con: con}), false } if !checkCanConvertInPointGet(col, d) { return nil, false @@ -1206,7 +1276,7 @@ func getNameValuePairs(stmtCtx *stmtctx.StatementContext, tbl *model.TableInfo, dVal, err := d.ConvertTo(stmtCtx, &col.FieldType) if err != nil { if terror.ErrorEqual(types.ErrOverflow, err) { - return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, value: d, param: param}), true + return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: &col.FieldType, value: d, con: con}), true } // Some scenarios cast to int with error, but we may use this value in point get. if !terror.ErrorEqual(types.ErrTruncatedWrongVal, err) { @@ -1215,13 +1285,10 @@ func getNameValuePairs(stmtCtx *stmtctx.StatementContext, tbl *model.TableInfo, } // The converted result must be same as original datum. cmp, err := dVal.Compare(stmtCtx, &d, collate.GetCollator(col.Collate)) - if err != nil { + if err != nil || cmp != 0 { return nil, false - } else if cmp != 0 { - return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, value: dVal, param: param}), true } - - return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, value: dVal, param: param}), false + return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: &col.FieldType, value: dVal, con: con}), false } return nil, false } @@ -1284,27 +1351,29 @@ func findPKHandle(tblInfo *model.TableInfo, pairs []nameValuePair) (handlePair n return handlePair, nil } -func getIndexValues(idxInfo *model.IndexInfo, pairs []nameValuePair) ([]types.Datum, []*driver.ParamMarkerExpr) { +func getIndexValues(idxInfo *model.IndexInfo, pairs []nameValuePair) ([]types.Datum, []*expression.Constant, []*types.FieldType) { idxValues := make([]types.Datum, 0, 4) - idxValueParams := make([]*driver.ParamMarkerExpr, 0, 4) + idxConstants := make([]*expression.Constant, 0, 4) + colsFieldType := make([]*types.FieldType, 0, 4) if len(idxInfo.Columns) != len(pairs) { - return nil, nil + return nil, nil, nil } if idxInfo.HasPrefixIndex() { - return nil, nil + return nil, nil, nil } for _, idxCol := range idxInfo.Columns { i := findInPairs(idxCol.Name.L, pairs) if i == -1 { - return nil, nil + return nil, nil, nil } idxValues = append(idxValues, pairs[i].value) - idxValueParams = append(idxValueParams, pairs[i].param) + idxConstants = append(idxConstants, pairs[i].con) + colsFieldType = append(colsFieldType, pairs[i].colFieldType) } if len(idxValues) > 0 { - return idxValues, idxValueParams + return idxValues, idxConstants, colsFieldType } - return nil, nil + return nil, nil, nil } func findInPairs(colName string, pairs []nameValuePair) int { @@ -1418,6 +1487,10 @@ func buildOrderedList(ctx sessionctx.Context, plan Plan, list []*ast.Assignment, Col: col, ColName: plan.OutputNames()[idx].ColName, } + defaultExpr := extractDefaultExpr(assign.Expr) + if defaultExpr != nil { + defaultExpr.Name = assign.Column + } expr, err := expression.RewriteSimpleExprWithNames(ctx, assign.Expr, plan.Schema(), plan.OutputNames()) if err != nil { return nil, true @@ -1488,6 +1561,11 @@ func buildPointDeletePlan(ctx sessionctx.Context, pointPlan PhysicalPlan, dbName } func findCol(tbl *model.TableInfo, colName *ast.ColumnName) *model.ColumnInfo { + if colName.Name.L == model.ExtraHandleName.L && !tbl.PKIsHandle { + colInfo := model.NewExtraHandleColInfo() + colInfo.Offset = len(tbl.Columns) - 1 + return colInfo + } for _, col := range tbl.Columns { if col.Name.L == colName.Name.L { return col diff --git a/planner/core/point_get_plan_test.go b/planner/core/point_get_plan_test.go index 300370b60dee6..d39e95b767ab8 100644 --- a/planner/core/point_get_plan_test.go +++ b/planner/core/point_get_plan_test.go @@ -19,62 +19,37 @@ import ( "fmt" "math" "strings" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/planner" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" ) -var _ = SerialSuites(&testPointGetSuite{}) - -type testPointGetSuite struct { - store kv.Storage - dom *domain.Domain - testData testutil.TestData -} - -func (s *testPointGetSuite) SetUpSuite(c *C) { - testleak.BeforeTest() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - s.store = store - s.dom = dom - s.testData, err = testutil.LoadTestSuiteData("testdata", "point_get_plan") - c.Assert(err, IsNil) -} - -func (s *testPointGetSuite) TearDownSuite(c *C) { - s.dom.Close() - s.store.Close() - testleak.AfterTest(c)() - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + sess, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(sess) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -111,26 +86,26 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { tk.MustExec("set @param=1") tk.MustQuery("execute stmt1 using @param").Check(testkit.Rows("1 1 1")) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(0)) + require.Equal(t, float64(0), hit) tk.MustExec("set @param=2") tk.MustQuery("execute stmt1 using @param").Check(testkit.Rows("2 2 2")) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(1)) + require.Equal(t, float64(1), hit) tk.MustQuery("execute stmt2 using @param, @param").Check(testkit.Rows("2 2 2")) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(1)) + require.Equal(t, float64(1), hit) tk.MustExec("set @param=1") tk.MustQuery("execute stmt2 using @param, @param").Check(testkit.Rows("1 1 1")) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) // PointGetPlan for Update. tk.MustExec(`prepare stmt3 from "update t set b=b+1, c=c+1 where a = ?"`) tk.MustExec(`prepare stmt4 from "update t set a=a+1 where b = ? and c = ?"`) @@ -142,9 +117,9 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { "3 4 4", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) tk.MustExec("set @param=4") tk.MustExec("execute stmt4 using @param, @param") tk.MustQuery("select * from t").Check(testkit.Rows( @@ -153,9 +128,9 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { "4 4 4", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) // PointGetPlan for Delete. tk.MustExec(`prepare stmt5 from "delete from t where a = ?"`) tk.MustExec(`prepare stmt6 from "delete from t where b = ? and c = ?"`) @@ -165,18 +140,18 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { "2 2 2", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) tk.MustExec("set @param=2") tk.MustExec("execute stmt6 using @param, @param") tk.MustQuery("select * from t").Check(testkit.Rows( "1 1 1", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) tk.MustExec("insert into t (a, b, c) values (18446744073709551615, 4, 4)") tk.MustExec("set @p1=-1") tk.MustExec("set @p2=1") @@ -184,31 +159,66 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { tk.MustQuery("execute stmt7 using @p1").Check(testkit.Rows()) tk.MustQuery("execute stmt7 using @p2").Check(testkit.Rows("1")) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(2)) + require.Equal(t, float64(2), hit) } -func (s *testPointGetSuite) TestPointGetForUpdate(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetForUpdate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table fu (id int primary key, val int)") tk.MustExec("insert into fu values (6, 6)") // In autocommit mode, outside a transaction, "for update" doesn't take effect. - checkUseForUpdate(tk, c, false) + checkUseForUpdate(tk, t, false) tk.MustExec("begin") - checkUseForUpdate(tk, c, true) + checkUseForUpdate(tk, t, true) tk.MustExec("rollback") tk.MustExec("set @@session.autocommit = 0") - checkUseForUpdate(tk, c, true) + checkUseForUpdate(tk, t, true) tk.MustExec("rollback") } -func (s *testPointGetSuite) TestPointGetForUpdateWithSubquery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestGetExtraColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t ( + a int(11) DEFAULT NULL, + b int(11) DEFAULT NULL, + UNIQUE KEY idx (a))`) + tk.MustQuery(`explain format='brief' select t.*, _tidb_rowid from t where a = 1`).Check(testkit.Rows("Point_Get 1.00 root table:t, index:idx(a) ")) + tk.MustQuery(`explain format='brief' select t.*, _tidb_rowid, date_format(a, "") from t where a = 1`).Check(testkit.Rows( + `Projection 1.00 root test.t.a, test.t.b, test.t._tidb_rowid, date_format(cast(test.t.a, datetime BINARY), )->Column#4`, + `└─Point_Get 1.00 root table:t, index:idx(a) `)) + tk.MustExec(`begin`) // in transaction + tk.MustExec(`insert into t values (1, 1)`) + tk.MustQuery(`explain format='brief' select t.*, _tidb_rowid from t where a = 1`).Check(testkit.Rows(`Point_Get 1.00 root table:t, index:idx(a) `)) + tk.MustExec(`commit`) + tk.MustQuery(`explain format='brief' select count(_tidb_rowid) from t where a=1`).Check(testkit.Rows( + `StreamAgg 1.00 root funcs:count(test.t._tidb_rowid)->Column#4`, + `└─Point_Get 1.00 root table:t, index:idx(a) `)) + tk.MustQuery(`explain format='brief' select *, date_format(b, "") from t where a =1 for update`).Check(testkit.Rows( + `Projection 1.00 root test.t.a, test.t.b, date_format(cast(test.t.b, datetime BINARY), )->Column#4`, + `└─SelectLock 1.00 root for update 0`, + ` └─Point_Get 1.00 root table:t, index:idx(a) `)) + + // if the PK is handled + tk.MustExec(`create table t1 (pk int, a int, b int, primary key(pk), unique key(a))`) + err := tk.ExecToErr(`explain format='brief' select t1.*, _tidb_rowid from t1 where a = 1`) + require.EqualError(t, err, `[planner:1054]Unknown column '_tidb_rowid' in 'field list'`) +} + +func TestPointGetForUpdateWithSubquery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("CREATE TABLE users (id bigint(20) unsigned NOT NULL primary key, name longtext DEFAULT NULL, company_id bigint(20) DEFAULT NULL)") tk.MustExec("create table companies(id bigint primary key, name longtext default null)") @@ -220,18 +230,20 @@ func (s *testPointGetSuite) TestPointGetForUpdateWithSubquery(c *C) { tk.MustQuery("select * from users").Check(testkit.Rows("239 Company15 15")) } -func checkUseForUpdate(tk *testkit.TestKit, c *C, expectLock bool) { +func checkUseForUpdate(tk *testkit.TestKit, t *testing.T, expectLock bool) { res := tk.MustQuery("explain format = 'brief' select * from fu where id = 6 for update") // Point_Get_1 1.00 root table:fu, handle:6 opInfo := res.Rows()[0][4] selectLock := strings.Contains(fmt.Sprintf("%s", opInfo), "lock") - c.Assert(selectLock, Equals, expectLock) + require.Equal(t, expectLock, selectLock) tk.MustQuery("select * from fu where id = 6 for update").Check(testkit.Rows("6 6")) } -func (s *testPointGetSuite) TestWhereIn2BatchPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestWhereIn2BatchPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key auto_increment not null, b int, c int, unique key idx_abc(a, b, c))") @@ -317,34 +329,38 @@ func (s *testPointGetSuite) TestWhereIn2BatchPointGet(c *C) { } // Test that the plan id will be reset before optimization every time. -func (s *testPointGetSuite) TestPointGetId(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetId(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 int primary key, c2 int)") defer tk.MustExec("drop table if exists t") pointGetQuery := "select c2 from t where c1 = 1" for i := 0; i < 2; i++ { - ctx := tk.Se.(sessionctx.Context) + ctx := tk.Session().(sessionctx.Context) stmts, err := session.Parse(ctx, pointGetQuery) - c.Assert(err, IsNil) - c.Assert(stmts, HasLen, 1) + require.NoError(t, err) + require.Len(t, stmts, 1) stmt := stmts[0] ret := &core.PreprocessorReturn{} err = core.Preprocess(ctx, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) + require.NoError(t, err) p, _, err := planner.Optimize(context.TODO(), ctx, stmt, ret.InfoSchema) - c.Assert(err, IsNil) + require.NoError(t, err) // Test explain format = 'brief' result is useless, plan id will be reset when running `explain`. - c.Assert(p.ID(), Equals, 1) + require.Equal(t, 1, p.ID()) } } -func (s *testPointGetSuite) TestCBOPointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCBOPointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly tk.MustExec("create table t (a varchar(20), b int, c int, d int, primary key(a), unique key(b, c))") tk.MustExec("insert into t values('1',4,4,1), ('2',3,3,2), ('3',2,2,3), ('4',1,1,4)") @@ -354,251 +370,256 @@ func (s *testPointGetSuite) TestCBOPointGet(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + pointGetPlanData := core.GetPointGetPlanData() + pointGetPlanData.GetTestCases(t, &input, &output) + require.Equal(t, len(input), len(output)) for i, sql := range input { plan := tk.MustQuery("explain format = 'brief' " + sql) res := tk.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(res.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) + output[i].Res = testdata.ConvertRowsToStrings(res.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) res.Check(testkit.Rows(output[i].Res...)) } } -func (s *testPointGetSuite) TestPartitionBatchPointGetPlanCache(c *C) { - testKit := testkit.NewTestKit(c, s.store) +func TestPartitionBatchPointGetPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - - var err error - testKit.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + sess, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) - - testKit.MustExec("use test") - testKit.MustExec("drop table if exists t") - testKit.MustExec("create table t(a int, b int, unique key(a))") - testKit.MustExec("insert into t values(1,1),(2,2),(3,3)") - testKit.MustExec("prepare stmt from 'select * from t use index(a) where (a >= ? and a <= ?) or a = 3'") - testKit.MustExec("set @p=1,@q=2,@u=3") - testKit.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows( + require.NoError(t, err) + tk.SetSession(sess) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, unique key(a))") + tk.MustExec("insert into t values(1,1),(2,2),(3,3)") + tk.MustExec("prepare stmt from 'select * from t use index(a) where (a >= ? and a <= ?) or a = 3'") + tk.MustExec("set @p=1,@q=2,@u=3") + tk.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows( "1 1", "3 3", )) - testKit.MustQuery("execute stmt using @u,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @u,@q").Sort().Check(testkit.Rows( "3 3", )) - testKit.MustExec("drop table t") - testKit.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") - testKit.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)") - testKit.MustExec("set @@tidb_partition_prune_mode = 'static'") - testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'") - testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( + tk.MustExec("drop table t") + tk.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") + tk.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)") + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'") + tk.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( "2 2", )) - testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( "1 1", "2 1", "3 1", )) - testKit.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'") - testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'") + tk.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", "2 2", )) - testKit.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'") - testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'") + tk.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( "2 2", )) - testKit.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows( "1 1", "1 2", "1 3", )) - testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'") - testKit.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'") + tk.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows( "2 1", "2 2", )) - testKit.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - testKit.MustExec("drop table t") - testKit.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") - testKit.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)") - testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'") - testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("drop table t") + tk.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") + tk.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)") + tk.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'") + tk.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( "2 2", )) - testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( "1 1", "2 1", "3 1", )) - testKit.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'") - testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'") + tk.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows( "1 1", "2 1", )) - testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows( "2 1", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", "2 2", )) - testKit.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'") - testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'") + tk.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows( "2 2", )) - testKit.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows( "1 1", "1 2", "1 3", )) - testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'") - testKit.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'") + tk.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows( "1 1", "1 2", )) - testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows( "1 2", )) - testKit.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows( "2 1", "2 2", )) - testKit.MustExec("drop table t") - testKit.MustExec("create table t(a int, b int, primary key(a)) partition by hash(a) partitions 2") - testKit.MustExec("insert into t values(1,0),(2,0),(3,0),(4,0)") - testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and 1 = 1'") - testKit.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows( + tk.MustExec("drop table t") + tk.MustExec("create table t(a int, b int, primary key(a)) partition by hash(a) partitions 2") + tk.MustExec("insert into t values(1,0),(2,0),(3,0),(4,0)") + tk.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and 1 = 1'") + tk.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows( "1 0", "2 0", )) - testKit.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows( "2 0", )) - testKit.MustQuery("execute stmt using @p,@u").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @p,@u").Sort().Check(testkit.Rows( "1 0", "2 0", "3 0", )) - testKit.MustQuery("execute stmt using @u,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @u,@p").Sort().Check(testkit.Rows( "2 0", )) - testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and 1 = 1'") - testKit.MustQuery("execute stmt using @p,@q").Sort().Check(testkit.Rows( + tk.MustExec("prepare stmt from 'select * from t where a in (?,?) and 1 = 1'") + tk.MustQuery("execute stmt using @p,@q").Sort().Check(testkit.Rows( "1 0", "2 0", )) - testKit.MustQuery("execute stmt using @q,@p").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@p").Sort().Check(testkit.Rows( "1 0", "2 0", )) - testKit.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows( + tk.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows( "2 0", )) } -func (s *testPointGetSuite) TestBatchPointGetPlanCache(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBatchPointGetPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + sess, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(sess) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -620,22 +641,23 @@ func (s *testPointGetSuite) TestBatchPointGetPlanCache(c *C) { )) } -func (s *testPointGetSuite) TestBatchPointGetPartition(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBatchPointGetPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) orgEnable := core.PreparedPlanCacheEnabled() defer func() { core.SetPreparedPlanCache(orgEnable) }() core.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + sess, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) - + require.NoError(t, err) + tk.SetSession(sess) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b int) PARTITION BY HASH(a) PARTITIONS 4") tk.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (4, 4)") @@ -679,9 +701,11 @@ func (s *testPointGetSuite) TestBatchPointGetPartition(c *C) { tk.MustQuery("select * from t where (a, b) in ((1, 1), (2, 2), (3, 3), (4, 4))").Check(testkit.Rows()) } -func (s *testPointGetSuite) TestIssue19141(c *C) { +func TestIssue19141(t *testing.T) { // For issue 19141, fix partition selection on batch point get. - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t19141 (c_int int, primary key (c_int)) partition by hash ( c_int ) partitions 4") tk.MustExec("insert into t19141 values (1), (2), (3), (4)") @@ -698,8 +722,10 @@ func (s *testPointGetSuite) TestIssue19141(c *C) { tk.MustQuery("select * from t19141 order by c_int").Check(testkit.Rows("1", "2", "3", "4")) } -func (s *testPointGetSuite) TestSelectInMultiColumns(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSelectInMultiColumns(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t2") tk.MustExec("create table t2(a int, b int, c int, primary key(a, b, c));") @@ -707,48 +733,46 @@ func (s *testPointGetSuite) TestSelectInMultiColumns(c *C) { tk.MustQuery("select * from t2 where (a, b, c) in ((1, 1, 1));").Check(testkit.Rows("1 1 1")) _, err := tk.Exec("select * from t2 where (a, b, c) in ((1, 1, 1, 1));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1241]Operand should contain 3 column(s)") + require.Error(t, err) + require.Equal(t, "[expression:1241]Operand should contain 3 column(s)", err.Error()) _, err = tk.Exec("select * from t2 where (a, b, c) in ((1, 1, 1), (2, 2, 2, 2));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1241]Operand should contain 3 column(s)") + require.Error(t, err) + require.Equal(t, "[expression:1241]Operand should contain 3 column(s)", err.Error()) _, err = tk.Exec("select * from t2 where (a, b, c) in ((1, 1), (2, 2, 2));") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[expression:1241]Operand should contain 3 column(s)") + require.Error(t, err) + require.Equal(t, "[expression:1241]Operand should contain 3 column(s)", err.Error()) } -func (s *testPointGetSuite) TestUpdateWithTableReadLockWillFail(c *C) { +func TestUpdateWithTableReadLockWillFail(t *testing.T) { defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.EnableTableLock = true }) - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table tbllock(id int, c int);") tk.MustExec("insert into tbllock values(1, 2), (2, 2);") tk.MustExec("lock table tbllock read;") _, err := tk.Exec("update tbllock set c = 3 where id = 2;") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "[schema:1099]Table 'tbllock' was locked with a READ lock and can't be updated") + require.Error(t, err) + require.Equal(t, "[schema:1099]Table 'tbllock' was locked with a READ lock and can't be updated", err.Error()) } -func (s *testPointGetSuite) TestIssue20692(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue20692(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (id int primary key, v int, vv int, vvv int, unique key u0(id, v, vv));") tk.MustExec("insert into t values(1, 1, 1, 1);") - se1, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - tk1 := testkit.NewTestKitWithSession(c, s.store, se1) - se2, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - tk2 := testkit.NewTestKitWithSession(c, s.store, se2) - se3, err := session.CreateSession(s.store) - c.Assert(err, IsNil) - tk3 := testkit.NewTestKitWithSession(c, s.store, se3) + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk3 := testkit.NewTestKit(t, store) tk1.MustExec("begin pessimistic;") tk1.MustExec("use test") tk2.MustExec("begin pessimistic;") @@ -769,7 +793,7 @@ func (s *testPointGetSuite) TestIssue20692(c *C) { // wait 50ms to ensure tk3 is blocked by tk2 select { case <-stop2: - c.Fail() + t.Fail() case <-time.After(50 * time.Millisecond): } @@ -779,8 +803,10 @@ func (s *testPointGetSuite) TestIssue20692(c *C) { tk3.MustQuery("select * from t;").Check(testkit.Rows("10 20 30 40")) } -func (s *testPointGetSuite) TestPointGetWithInvisibleIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetWithInvisibleIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 int, unique(c1))") @@ -792,8 +818,10 @@ func (s *testPointGetSuite) TestPointGetWithInvisibleIndex(c *C) { )) } -func (s *testPointGetSuite) TestBatchPointGetWithInvisibleIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestBatchPointGetWithInvisibleIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t (c1 int, unique(c1))") @@ -805,10 +833,12 @@ func (s *testPointGetSuite) TestBatchPointGetWithInvisibleIndex(c *C) { )) } -func (s *testPointGetSuite) TestCBOShouldNotUsePointGet(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestCBOShouldNotUsePointGet(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop tables if exists t1, t2, t3, t4, t5") tk.MustExec("create table t1(id varchar(20) primary key)") tk.MustExec("create table t2(id varchar(20), unique(id))") @@ -827,22 +857,27 @@ func (s *testPointGetSuite) TestCBOShouldNotUsePointGet(c *C) { Plan []string Res []string } - s.testData.GetTestCases(c, &input, &output) + + pointGetPlanData := core.GetPointGetPlanData() + pointGetPlanData.GetTestCases(t, &input, &output) + require.Equal(t, len(input), len(output)) for i, sql := range input { plan := tk.MustQuery("explain format = 'brief' " + sql) res := tk.MustQuery(sql) - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = sql - output[i].Plan = s.testData.ConvertRowsToStrings(plan.Rows()) - output[i].Res = s.testData.ConvertRowsToStrings(res.Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(plan.Rows()) + output[i].Res = testdata.ConvertRowsToStrings(res.Rows()) }) plan.Check(testkit.Rows(output[i].Plan...)) res.Check(testkit.Rows(output[i].Res...)) } } -func (s *testPointGetSuite) TestPointGetWithIndexHints(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestPointGetWithIndexHints(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") // point get @@ -887,20 +922,24 @@ func (s *testPointGetSuite) TestPointGetWithIndexHints(c *C) { " └─TableRowIDScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo")) } -func (s *testPointGetSuite) TestIssue18042(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue18042(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, primary key(a), index ab(a, b));") tk.MustExec("insert into t values (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)") tk.MustExec("SELECT /*+ MAX_EXECUTION_TIME(100), MEMORY_QUOTA(1 MB) */ * FROM t where a = 1;") - c.Assert(tk.Se.GetSessionVars().StmtCtx.MemQuotaQuery, Equals, int64(1<<20)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.MaxExecutionTime, Equals, uint64(100)) + require.Equal(t, int64(1<<20), tk.Session().GetSessionVars().StmtCtx.MemQuotaQuery) + require.Equal(t, uint64(100), tk.Session().GetSessionVars().StmtCtx.MaxExecutionTime) tk.MustExec("drop table t") } -func (s *testPointGetSuite) TestIssue26638(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue26638(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a float, unique index uidx(a));") @@ -929,8 +968,10 @@ func (s *testPointGetSuite) TestIssue26638(c *C) { tk.MustQuery("execute stmt4 using @i,@e,@d,@a,@b,@c,@e,@g,@h;").Check(testkit.Rows("0 1 2")) } -func (s *testPointGetSuite) TestIssue23511(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestIssue23511(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2;") tk.MustExec("CREATE TABLE `t1` (`COL1` bit(11) NOT NULL,PRIMARY KEY (`COL1`));") diff --git a/planner/core/prepare_test.go b/planner/core/prepare_test.go index d633896e7b718..e88ce13c3827d 100644 --- a/planner/core/prepare_test.go +++ b/planner/core/prepare_test.go @@ -21,53 +21,392 @@ import ( "math/rand" "strconv" "strings" + "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/israce" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testPrepareSuite{}) -var _ = SerialSuites(&testPrepareSerialSuite{}) +func TestPreparePointGetWithDML(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) -type testPrepareSuite struct { + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int, unique key(a))`) + tk.MustExec(`insert into t values(1), (2)`) + + // txn1 left a cached plan + tk.MustExec(`begin`) + tk.MustExec(`prepare stmt from 'update t set a = ? where a = ?'`) + tk.MustExec(`set @a=1`) + tk.MustExec(`execute stmt using @a, @a`) + tk.MustExec(`commit`) + + // txn2 can reuse the cached plan generated by txn1 directly + tk.MustExec(`begin`) + tk.MustExec(`prepare stmt from 'update t set a = ? where a = ?'`) + tk.MustExec(`set @a=2`) + tk.MustExec(`execute stmt using @a, @a`) // can reuse the cached plan directly + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustExec(`rollback`) +} + +func TestPrepareIgnoreCloseStmtCmd(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int, unique key(a))`) + + // disable the ignore-stmt-cmd + tk.MustExec(`set @@tidb_ignore_prepared_cache_close_stmt=0`) + tk.MustQuery(`select @@tidb_ignore_prepared_cache_close_stmt`).Check(testkit.Rows("0")) + tk.MustExec(`prepare stmt from 'select * from t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustExec(`deallocate prepare stmt`) // close/deallocate this stmt + tk.MustExec(`prepare stmt from 'select * from t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) // cannot reuse last plan since it is closed + + // enable the ignore-stmt-cmd + tk.MustExec(`set tidb_ignore_prepared_cache_close_stmt=1`) + tk.MustQuery(`select @@tidb_ignore_prepared_cache_close_stmt`).Check(testkit.Rows("1")) + tk.MustExec(`prepare stmt from 'select * from t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustExec(`deallocate prepare stmt`) // close/deallocate this stmt + tk.MustExec(`prepare stmt from 'select * from t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows()) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) // can reuse last plan since last close-cmd was ignored } -type testPrepareSerialSuite struct { +func TestRandomFlushPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(id int, a int, b int, key(a))") + tk.MustExec("create table t2(id int, a int, b int, key(a))") + tk.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk.MustExec("prepare stmt4 from 'SELECT * from t2';") + tk.MustExec("prepare stmt5 from 'SELECT * from t2 where id = 1';") + + tk2.MustExec("use test") + tk2.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk2.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk2.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk2.MustExec("prepare stmt4 from 'SELECT * from t2';") + tk2.MustExec("prepare stmt5 from 'SELECT * from t2 where id = 1';") + + prepareNum := 5 + execStmts := make([]string, 0, prepareNum) + for i := 1; i <= prepareNum; i++ { + execStmt := fmt.Sprintf("execute stmt%d", i) + execStmts = append(execStmts, execStmt) + } + + rand.Seed(time.Now().Unix()) + for i := 0; i < 10; i++ { + // Warm up to make sure all the plans are in the cache. + for _, execStmt := range execStmts { + tk.MustExec(execStmt) + tk.MustExec(execStmt) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk2.MustExec(execStmt) + tk2.MustExec(execStmt) + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + } + + for j := 0; j < 10; j++ { + session1PC, session2PC := "1", "1" + // random to flush the plan cache + randNum := rand.Intn(10) + if randNum == 0 { + session1PC, session2PC = "0", "0" + if j%2 == 0 { + err = tk.ExecToErr("admin flush instance plan_cache;") + } else { + err = tk2.ExecToErr("admin flush instance plan_cache;") + } + require.NoError(t, err) + } else if randNum == 1 { + session1PC = "0" + err = tk.ExecToErr("admin flush session plan_cache;") + require.NoError(t, err) + } else if randNum == 2 { + session2PC = "0" + err = tk2.ExecToErr("admin flush session plan_cache;") + require.NoError(t, err) + } + + for _, execStmt := range execStmts { + tk.MustExec(execStmt) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows(session1PC)) + + tk2.MustExec(execStmt) + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows(session2PC)) + } + } + + err = tk.ExecToErr("admin flush instance plan_cache;") + require.NoError(t, err) + } + + err = tk.ExecToErr("admin flush global plan_cache;") + require.EqualError(t, err, "Do not support the 'admin flush global scope.'") } -func (s *testPrepareSerialSuite) TestPrepareCache(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestFlushPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(id int, a int, b int, key(a))") + tk.MustExec("create table t2(id int, a int, b int, key(a))") + tk.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk.MustExec("execute stmt1;") + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk.MustExec("execute stmt2;") + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk.MustExec("execute stmt3;") + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk2.MustExec("use test") + tk2.MustExec("drop table if exists t1") + tk2.MustExec("drop table if exists t2") + tk2.MustExec("create table t1(id int, a int, b int, key(a))") + tk2.MustExec("create table t2(id int, a int, b int, key(a))") + tk2.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk2.MustExec("execute stmt1;") + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk2.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk2.MustExec("execute stmt2;") + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk2.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk2.MustExec("execute stmt3;") + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec("admin flush session plan_cache;") + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk2.MustExec("admin flush instance plan_cache;") + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + err = tk.ExecToErr("admin flush global plan_cache;") + require.EqualError(t, err, "Do not support the 'admin flush global scope.'") +} + +func TestFlushPlanCacheWithoutPCEnable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(false) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + tk2 := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(id int, a int, b int, key(a))") + tk.MustExec("create table t2(id int, a int, b int, key(a))") + tk.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk.MustExec("execute stmt1;") + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk.MustExec("execute stmt2;") + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk.MustExec("execute stmt3;") + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("use test") + tk2.MustExec("drop table if exists t1") + tk2.MustExec("drop table if exists t2") + tk2.MustExec("create table t1(id int, a int, b int, key(a))") + tk2.MustExec("create table t2(id int, a int, b int, key(a))") + tk2.MustExec("prepare stmt1 from 'SELECT * from t1,t2 where t1.id = t2.id';") + tk2.MustExec("execute stmt1;") + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("prepare stmt2 from 'SELECT * from t1';") + tk2.MustExec("execute stmt2;") + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("prepare stmt3 from 'SELECT * from t1 where id = 1';") + tk2.MustExec("execute stmt3;") + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("admin flush session plan_cache;") + tk.MustQuery("show warnings;").Check(testkit.Rows("Warning 1105 The plan cache is disable. So there no need to flush the plan cache")) + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk2.MustExec("admin flush instance plan_cache;") + tk2.MustQuery("show warnings;").Check(testkit.Rows("Warning 1105 The plan cache is disable. So there no need to flush the plan cache")) + tk2.MustExec("execute stmt1;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt2;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk2.MustExec("execute stmt3;") + tk2.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustExec("execute stmt1;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt2;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustExec("execute stmt3;") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + err = tk.ExecToErr("admin flush global plan_cache;") + require.EqualError(t, err, "Do not support the 'admin flush global scope.'") +} + +func TestPrepareCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -96,7 +435,7 @@ func (s *testPrepareSerialSuite) TestPrepareCache(c *C) { tk.MustQuery("execute stmt6").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) // test privilege change - rootSe := tk.Se + rootSe := tk.Session() tk.MustExec("drop table if exists tp") tk.MustExec(`create table tp(c1 int, c2 int, primary key (c1))`) tk.MustExec(`insert into tp values(1, 1), (2, 2), (3, 3)`) @@ -105,56 +444,50 @@ func (s *testPrepareSerialSuite) TestPrepareCache(c *C) { tk.MustExec(`grant select on test.tp to u_tp@'localhost';`) // user u_tp - userSess := newSession(c, store, "test") - c.Assert(userSess.Auth(&auth.UserIdentity{Username: "u_tp", Hostname: "localhost"}, nil, nil), IsTrue) - mustExec(c, userSess, `prepare ps_stp_r from 'select * from tp where c1 > ?'`) - mustExec(c, userSess, `set @p2 = 2`) - tk.Se = userSess + userSess := newSession(t, store, "test") + require.True(t, userSess.Auth(&auth.UserIdentity{Username: "u_tp", Hostname: "localhost"}, nil, nil)) + mustExec(t, userSess, `prepare ps_stp_r from 'select * from tp where c1 > ?'`) + mustExec(t, userSess, `set @p2 = 2`) + tk.SetSession(userSess) tk.MustQuery(`execute ps_stp_r using @p2`).Check(testkit.Rows("3 3")) tk.MustQuery(`execute ps_stp_r using @p2`).Check(testkit.Rows("3 3")) tk.MustQuery(`execute ps_stp_r using @p2`).Check(testkit.Rows("3 3")) // root revoke - tk.Se = rootSe + tk.SetSession(rootSe) tk.MustExec(`revoke all on test.tp from 'u_tp'@'localhost';`) // user u_tp - tk.Se = userSess + tk.SetSession(userSess) _, err = tk.Exec(`execute ps_stp_r using @p2`) - c.Assert(err, NotNil) + require.Error(t, err) // grant again - tk.Se = rootSe + tk.SetSession(rootSe) tk.MustExec(`grant select on test.tp to u_tp@'localhost';`) // user u_tp - tk.Se = userSess + tk.SetSession(userSess) tk.MustQuery(`execute ps_stp_r using @p2`).Check(testkit.Rows("3 3")) tk.MustQuery(`execute ps_stp_r using @p2`).Check(testkit.Rows("3 3")) // restore - tk.Se = rootSe + tk.SetSession(rootSe) tk.MustExec("drop table if exists tp") tk.MustExec(`DROP USER 'u_tp'@'localhost';`) } -func (s *testPrepareSerialSuite) TestPrepareCacheIndexScan(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheIndexScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -249,23 +582,17 @@ func randValue(tk *testkit.TestKit, tbl, col, dtype, rtype string) string { return "'invalid-type-" + dtype + "'" } -func (s *testPrepareSerialSuite) TestPrepareCacheChangingParamType(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheChangingParamType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t_tinyint, t_unsigned, t_float, t_decimal, t_year`) @@ -301,11 +628,10 @@ func (s *testPrepareSerialSuite) TestPrepareCacheChangingParamType(c *C) { compareResult := func(sql1, sql2 string) { raw, err := tk.Exec(sql1) if err != nil { - err := tk.ExecToErr(sql2) - c.Assert(err, NotNil) + require.Error(t, tk.ExecToErr(sql2)) return } - rs := tk.ResultSetToResult(raw, Commentf("sql1:%s, sql2:%v", sql1, sql2)) + rs := tk.ResultSetToResult(raw, fmt.Sprintf("sql1:%s, sql2:%v", sql1, sql2)) rs.Sort().Check(tk.MustQuery(sql2).Sort().Rows()) } @@ -321,23 +647,17 @@ func (s *testPrepareSerialSuite) TestPrepareCacheChangingParamType(c *C) { } } -func (s *testPrepareSerialSuite) TestPrepareCacheChangeCharsetCollation(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheChangeCharsetCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists t`) @@ -368,23 +688,17 @@ func (s *testPrepareSerialSuite) TestPrepareCacheChangeCharsetCollation(c *C) { tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestPrepareCacheDeferredFunction(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheDeferredFunction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t1") @@ -400,81 +714,71 @@ func (s *testPlanSerialSuite) TestPrepareCacheDeferredFunction(c *C) { metrics.PlanCacheCounter.Reset() counter := metrics.PlanCacheCounter.WithLabelValues("prepare") ctx := context.TODO() + p := parser.New() + p.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) for i := 0; i < 2; i++ { - stmt, err := s.ParseOneStmt(sql1, "", "") - c.Check(err, IsNil) - is := tk.Se.GetInfoSchema().(infoschema.InfoSchema) - builder, _ := core.NewPlanBuilder().Init(tk.Se, is, &hint.BlockHintProcessor{}) + stmt, err := p.ParseOneStmt(sql1, "", "") + require.NoError(t, err) + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) + builder, _ := core.NewPlanBuilder().Init(tk.Session(), is, &hint.BlockHintProcessor{}) p, err := builder.Build(ctx, stmt) - c.Check(err, IsNil) + require.NoError(t, err) execPlan, ok := p.(*core.Execute) - c.Check(ok, IsTrue) - err = executor.ResetContextOfStmt(tk.Se, stmt) - c.Assert(err, IsNil) - err = execPlan.OptimizePreparedPlan(ctx, tk.Se, is) - c.Check(err, IsNil) + require.True(t, ok) + err = executor.ResetContextOfStmt(tk.Session(), stmt) + require.NoError(t, err) + err = execPlan.OptimizePreparedPlan(ctx, tk.Session(), is) + require.NoError(t, err) planStr[i] = core.ToString(execPlan.Plan) - c.Check(planStr[i], Matches, expectedPattern, Commentf("for %dth %s", i, sql1)) + require.Regexpf(t, expectedPattern, planStr[i], "for %dth %s", i, sql1) pb := &dto.Metric{} err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt[i] = pb.GetCounter().GetValue() - c.Check(cnt[i], Equals, float64(i)) + require.Equal(t, float64(i), cnt[i]) time.Sleep(time.Millisecond * 10) } - c.Assert(planStr[0] < planStr[1], IsTrue, Commentf("plan 1: %v, plan 2: %v", planStr[0], planStr[1])) + require.Lessf(t, planStr[0], planStr[1], "plan 1: %v, plan 2: %v", planStr[0], planStr[1]) } -func (s *testPrepareSerialSuite) TestPrepareCacheNow(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheNow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec(`prepare stmt1 from "select now(), current_timestamp(), utc_timestamp(), unix_timestamp(), sleep(0.1), now(), current_timestamp(), utc_timestamp(), unix_timestamp()"`) // When executing one statement at the first time, we don't usTestPrepareCacheDeferredFunctione cache, so we need to execute it at least twice to test the cache. _ = tk.MustQuery("execute stmt1").Rows() rs := tk.MustQuery("execute stmt1").Rows() - c.Assert(rs[0][0].(string), Equals, rs[0][5].(string)) - c.Assert(rs[0][1].(string), Equals, rs[0][6].(string)) - c.Assert(rs[0][2].(string), Equals, rs[0][7].(string)) - c.Assert(rs[0][3].(string), Equals, rs[0][8].(string)) + require.Equal(t, rs[0][5].(string), rs[0][0].(string)) + require.Equal(t, rs[0][6].(string), rs[0][1].(string)) + require.Equal(t, rs[0][7].(string), rs[0][2].(string)) + require.Equal(t, rs[0][8].(string), rs[0][3].(string)) } -func (s *testPrepareSerialSuite) TestPrepareOverMaxPreparedStmtCount(c *C) { - c.Skip("unstable, skip it and fix it before 20210705") - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() +func TestPrepareOverMaxPreparedStmtCount(t *testing.T) { + t.Skip("unstable, skip it and fix it before 20210705") + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") // test prepare and deallocate. prePrepared := readGaugeInt(metrics.PreparedStmtGauge) tk.MustExec(`prepare stmt1 from "select 1"`) onePrepared := readGaugeInt(metrics.PreparedStmtGauge) - c.Assert(prePrepared+1, Equals, onePrepared) + require.Equal(t, onePrepared, prePrepared+1) tk.MustExec(`deallocate prepare stmt1`) deallocPrepared := readGaugeInt(metrics.PreparedStmtGauge) - c.Assert(prePrepared, Equals, deallocPrepared) + require.Equal(t, deallocPrepared, prePrepared) // test change global limit and make it affected in test session. tk.MustQuery("select @@max_prepared_stmt_count").Check(testkit.Rows("-1")) @@ -484,45 +788,38 @@ func (s *testPrepareSerialSuite) TestPrepareOverMaxPreparedStmtCount(c *C) { // test close session to give up all prepared stmt tk.MustExec(`prepare stmt2 from "select 1"`) prePrepared = readGaugeInt(metrics.PreparedStmtGauge) - tk.Se.Close() + tk.Session().Close() drawPrepared := readGaugeInt(metrics.PreparedStmtGauge) - c.Assert(prePrepared-1, Equals, drawPrepared) + require.Equal(t, drawPrepared, prePrepared-1) // test meet max limit. - tk.Se = nil + tk.RefreshSession() tk.MustQuery("select @@max_prepared_stmt_count").Check(testkit.Rows("2")) for i := 1; ; i++ { prePrepared = readGaugeInt(metrics.PreparedStmtGauge) if prePrepared >= 2 { - _, err = tk.Exec(`prepare stmt` + strconv.Itoa(i) + ` from "select 1"`) - c.Assert(terror.ErrorEqual(err, variable.ErrMaxPreparedStmtCountReached), IsTrue) + _, err := tk.Exec(`prepare stmt` + strconv.Itoa(i) + ` from "select 1"`) + require.True(t, terror.ErrorEqual(err, variable.ErrMaxPreparedStmtCountReached)) break } - _, err = tk.Exec(`prepare stmt` + strconv.Itoa(i) + ` from "select 1"`) - c.Assert(err, IsNil) + _, err := tk.Exec(`prepare stmt` + strconv.Itoa(i) + ` from "select 1"`) + require.NoError(t, err) } } // unit test for issue https://github.com/pingcap/tidb/issues/8518 -func (s *testPrepareSerialSuite) TestPrepareTableAsNameOnGroupByWithCache(c *C) { - c.Skip("unstable, skip it and fix it before 20210702") - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareTableAsNameOnGroupByWithCache(t *testing.T) { + t.Skip("unstable, skip it and fix it before 20210702") + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t1") @@ -546,23 +843,17 @@ func (s *testPrepareSerialSuite) TestPrepareTableAsNameOnGroupByWithCache(c *C) tk.MustQuery("execute stmt").Sort().Check(testkit.Rows("partner1", "partner2", "partner3", "partner4")) } -func (s *testPrepareSerialSuite) TestPrepareCachePointGetInsert(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCachePointGetInsert(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -588,6 +879,84 @@ func (s *testPrepareSerialSuite) TestPrepareCachePointGetInsert(c *C) { tk.MustQuery("select * from t2 order by a").Check(testkit.Rows("1 1", "2 2", "3 3")) } +func TestIssue31280(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("drop table if exists UK_MU15569;") + tk.MustExec("CREATE TABLE `UK_MU15569` (" + + "`COL1` varbinary(20) DEFAULT NULL," + + "`COL2` bit(16) DEFAULT NULL," + + "`COL3` time DEFAULT NULL," + + "`COL4` int(11) DEFAULT NULL," + + "UNIQUE KEY `U_M_COL4` (`COL1`(10),`COL2`)," + + "UNIQUE KEY `U_M_COL5` (`COL3`,`COL2`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into UK_MU15569 values(0x1C4FDBA09B42D999AC3019B6A9C0C787FBA08446, 0xCA74, '-836:46:08', 735655453);") + + tk.MustExec(`prepare stmt from 'select * from UK_MU15569 where col2 >= ? and col1 is not null and col3 = ?;';`) + + tk.MustExec("set @a=-32373, @b='545:50:46.85487';") + // The tableDual plan can not be cached. + res := tk.MustQuery("execute stmt using @a,@b;") + require.Len(t, res.Rows(), 0) + + tk.MustExec("set @a=-27225, @b='-836:46:08';") + res = tk.MustQuery("execute stmt using @a,@b;") + require.Len(t, res.Rows(), 1) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @a,@b;") + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + + res1 := tk.MustQuery("select * from UK_MU15569 where col2 >= -27225 and col1 is not null and col3 = '-836:46:08';") + require.Equal(t, res1.Rows(), res.Rows()) +} + +func TestIssue31375(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("drop table if exists IDT_MULTI15844STROBJSTROBJ;") + tk.MustExec("CREATE TABLE `IDT_MULTI15844STROBJSTROBJ` (" + + "`COL1` enum('bb','aa') DEFAULT NULL," + + "`COL2` smallint(41) DEFAULT NULL," + + "`COL3` year(4) DEFAULT NULL," + + "KEY `U_M_COL4` (`COL1`,`COL2`)," + + "KEY `U_M_COL5` (`COL3`,`COL2`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("insert into IDT_MULTI15844STROBJSTROBJ values('bb', -16994, 1987);") + + tk.MustExec(`prepare stmt from 'SELECT/*+ HASH_JOIN(t1, t2) */ t2.* FROM IDT_MULTI15844STROBJSTROBJ t1 LEFT JOIN IDT_MULTI15844STROBJSTROBJ t2 ON t1.col1 = t2.col1 WHERE t1.col2 BETWEEN ? AND ? AND t1.col1 >= ?;';`) + + tk.MustExec("set @a=752400293960, @b=258241896853, @c='none';") + // The tableDual plan can not be cached. + tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows()) + + tk.MustExec("set @a=-170756280585, @b=3756, @c='aa';") + tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("bb -16994 1987")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @a,@b,@c;") + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) +} + // nolint:unused func readGaugeInt(g prometheus.Gauge) int { ch := make(chan prometheus.Metric, 1) @@ -603,20 +972,12 @@ func readGaugeInt(g prometheus.Gauge) int { } // unit test for issue https://github.com/pingcap/tidb/issues/9478 -func (s *testPrepareSuite) TestPrepareWithWindowFunction(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() +func TestPrepareWithWindowFunction(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_enable_window_function = 1") - defer func() { - tk.MustExec("set @@tidb_enable_window_function = 0") - }() + defer tk.MustExec("set @@tidb_enable_window_function = 0") tk.MustExec("use test") tk.MustExec("create table window_prepare(a int, b double)") tk.MustExec("insert into window_prepare values(1, 1.1), (2, 1.9)") @@ -629,17 +990,10 @@ func (s *testPrepareSuite) TestPrepareWithWindowFunction(c *C) { tk.MustQuery("execute stmt2 using @a, @b").Check(testkit.Rows("0", "0")) } -func (s *testPrepareSuite) TestPrepareWithSnapshot(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() - +func TestPrepareWithSnapshot(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) safePointName := "tikv_gc_safe_point" safePointValue := "20060102-15:04:05 -0700" safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" @@ -663,16 +1017,10 @@ func (s *testPrepareSuite) TestPrepareWithSnapshot(c *C) { tk.MustQuery("execute s2").Check(testkit.Rows("1 2")) } -func (s *testPrepareSuite) TestPrepareForGroupByItems(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() +func TestPrepareForGroupByItems(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(id int, v int)") @@ -683,21 +1031,16 @@ func (s *testPrepareSuite) TestPrepareForGroupByItems(c *C) { tk.MustExec("prepare s1 from 'select max(v) from t group by ?';") tk.MustExec("set @a=2;") - err = tk.ExecToErr("execute s1 using @a;") - c.Assert(err.Error(), Equals, "Unknown column '2' in 'group statement'") + err := tk.ExecToErr("execute s1 using @a;") + require.EqualError(t, err, "Unknown column '2' in 'group statement'") tk.MustExec("set @a=2.0;") tk.MustQuery("execute s1 using @a;").Check(testkit.Rows("3")) } -func (s *testPrepareSuite) TestPrepareCacheForClusteredIndex(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - }() +func TestPrepareCacheForClusteredIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t1(k varchar(100) primary key clustered, v1 int, v2 int)") tk.MustExec("insert into t1 (k, v1, v2) values('a', 1, 2), ('b', 1, 1)") @@ -708,28 +1051,21 @@ func (s *testPrepareSuite) TestPrepareCacheForClusteredIndex(c *C) { tk.MustQuery("execute prepare_1").Check(testkit.Rows("2 100", "1 ")) } -func (s *testPrepareSerialSuite) TestPrepareCacheForPartition(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheForPartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") - for _, val := range []string{string(variable.Static), string(variable.Dynamic)} { - tk.MustExec("set @@tidb_partition_prune_mode = '" + val + "'") + for _, pruneMode := range []string{string(variable.Static), string(variable.Dynamic)} { + tk.MustExec("set @@tidb_partition_prune_mode = '" + pruneMode + "'") // Test for PointGet and IndexRead. tk.MustExec("drop table if exists t_index_read") tk.MustExec("create table t_index_read (id int, k int, c varchar(10), primary key (id, k)) partition by hash(id+k) partitions 10") @@ -830,40 +1166,49 @@ func (s *testPrepareSerialSuite) TestPrepareCacheForPartition(c *C) { tk.MustQuery("execute stmt8 using @id").Check(testkit.Rows("hij")) tk.MustExec("set @id=100") tk.MustQuery("execute stmt8 using @id").Check(testkit.Rows()) + + // https://github.com/pingcap/tidb/issues/33031 + tk.MustExec(`drop table if exists Issue33031`) + tk.MustExec(`CREATE TABLE Issue33031 (COL1 int(16) DEFAULT '29' COMMENT 'NUMERIC UNIQUE INDEX', COL2 bigint(20) DEFAULT NULL, UNIQUE KEY UK_COL1 (COL1)) PARTITION BY RANGE (COL1) (PARTITION P0 VALUES LESS THAN (0))`) + tk.MustExec(`insert into Issue33031 values(-5, 7)`) + tk.MustExec(`prepare stmt from 'select *,? from Issue33031 where col2 < ? and col1 in (?, ?)'`) + tk.MustExec(`set @a=111, @b=1, @c=2, @d=22`) + tk.MustQuery(`execute stmt using @d,@a,@b,@c`).Check(testkit.Rows()) + tk.MustExec(`set @a=112, @b=-2, @c=-5, @d=33`) + tk.MustQuery(`execute stmt using @d,@a,@b,@c`).Check(testkit.Rows("-5 7 33")) + if pruneMode == string(variable.Dynamic) { + // When the temporary disabling of prepared plan cache for dynamic partition prune mode is disabled, change this to 1! + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + } else { + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + } } } -func newSession(c *C, store kv.Storage, dbName string) session.Session { +func newSession(t *testing.T, store kv.Storage, dbName string) session.Session { se, err := session.CreateSession4Test(store) - c.Assert(err, IsNil) - mustExec(c, se, "create database if not exists "+dbName) - mustExec(c, se, "use "+dbName) + require.NoError(t, err) + mustExec(t, se, "create database if not exists "+dbName) + mustExec(t, se, "use "+dbName) return se } -func mustExec(c *C, se session.Session, sql string) { +func mustExec(t *testing.T, se session.Session, sql string) { _, err := se.Execute(context.Background(), sql) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testPrepareSerialSuite) TestConstPropAndPPDWithCache(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestConstPropAndPPDWithCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -953,22 +1298,17 @@ func (s *testPrepareSerialSuite) TestConstPropAndPPDWithCache(c *C) { tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestPlanCacheUnionScan(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPlanCacheUnionScan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) pb := &dto.Metric{} metrics.ResettablePlanCacheCounterFortTest = true metrics.PlanCacheCounter.Reset() @@ -985,97 +1325,144 @@ func (s *testPlanSerialSuite) TestPlanCacheUnionScan(c *C) { tk.MustExec("begin") tk.MustQuery("execute stmt1 using @p0").Check(testkit.Rows()) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt := pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(1)) + require.Equal(t, float64(1), cnt) tk.MustExec("insert into t1 values(1)") // Cached plan is invalid now, it is not chosen and removed. tk.MustQuery("execute stmt1 using @p0").Check(testkit.Rows( "1", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(1)) + require.Equal(t, float64(1), cnt) tk.MustExec("insert into t2 values(1)") // Cached plan is chosen, modification on t2 does not impact plan of t1. tk.MustQuery("execute stmt1 using @p0").Check(testkit.Rows( "1", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(2)) + require.Equal(t, float64(2), cnt) tk.MustExec("rollback") // Though cached plan contains UnionScan, it does not impact correctness, so it is reused. tk.MustQuery("execute stmt1 using @p0").Check(testkit.Rows()) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(3)) + require.Equal(t, float64(3), cnt) tk.MustExec("prepare stmt2 from 'select * from t1 left join t2 on true where t1.a > ?'") tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows()) tk.MustExec("begin") tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows()) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(4)) + require.Equal(t, float64(4), cnt) tk.MustExec("insert into t1 values(1)") // Cached plan is invalid now, it is not chosen and removed. tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows( "1 ", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(4)) + require.Equal(t, float64(4), cnt) tk.MustExec("insert into t2 values(1)") // Cached plan is invalid now, it is not chosen and removed. tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows( "1 1", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(4)) + require.Equal(t, float64(4), cnt) // Cached plan is reused. tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows( "1 1", )) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(5)) + require.Equal(t, float64(5), cnt) tk.MustExec("rollback") // Though cached plan contains UnionScan, it does not impact correctness, so it is reused. tk.MustQuery("execute stmt2 using @p0").Check(testkit.Rows()) err = counter.Write(pb) - c.Assert(err, IsNil) + require.NoError(t, err) cnt = pb.GetCounter().GetValue() - c.Check(cnt, Equals, float64(6)) + require.Equal(t, float64(6), cnt) } -func (s *testPlanSerialSuite) TestPlanCacheHitInfo(c *C) { - c.Skip("unstable, skip it and fix it before 20210705") - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPlanCacheSwitchDB(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + // create a table in test + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists t`) + tk.MustExec(`create table t(a int)`) + tk.MustExec(`insert into t values (-1)`) + tk.MustExec(`prepare stmt from 'select * from t'`) + + // DB is not specified + se2, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk2 := testkit.NewTestKitWithSession(t, store, se2) + require.Equal(t, tk2.ExecToErr(`prepare stmt from 'select * from t'`).Error(), "[planner:1046]No database selected") + require.Equal(t, tk2.ExecToErr(`prepare stmt from 'select * from test.t'`), nil) + + // switch to a new DB + tk.MustExec(`drop database if exists plan_cache`) + tk.MustExec(`create database plan_cache`) + tk.MustExec(`use plan_cache`) + tk.MustExec(`create table t(a int)`) + tk.MustExec(`insert into t values (1)`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("-1")) // read test.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("-1")) // read test.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + + // prepare again + tk.MustExec(`prepare stmt from 'select * from t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("1")) // read plan_cache.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("1")) // read plan_cache.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + + // specify DB in the query + tk.MustExec(`prepare stmt from 'select * from test.t'`) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("-1")) // read test.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery(`execute stmt`).Check(testkit.Rows("-1")) // read test.t + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) +} + +func TestPlanCacheHitInfo(t *testing.T) { + t.Skip("unstable, skip it and fix it before 20210705") + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1101,23 +1488,17 @@ func (s *testPlanSerialSuite) TestPlanCacheHitInfo(c *C) { tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) } -func (s *testPlanSerialSuite) TestIssue29303(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue29303(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`set tidb_enable_clustered_index=on`) tk.MustExec(`use test`) @@ -1135,23 +1516,17 @@ func (s *testPlanSerialSuite) TestIssue29303(c *C) { tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) } -func (s *testPlanSerialSuite) TestIssue28942(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue28942(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists IDT_MULTI15853STROBJSTROBJ`) @@ -1169,24 +1544,17 @@ func (s *testPlanSerialSuite) TestIssue28942(c *C) { tk.MustQuery(`execute stmt using @a,@b`).Check(testkit.Rows()) // empty result } -func (s *testPlanSerialSuite) TestPlanCacheUnsignedHandleOverflow(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPlanCacheUnsignedHandleOverflow(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1203,23 +1571,17 @@ func (s *testPlanSerialSuite) TestPlanCacheUnsignedHandleOverflow(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) } -func (s *testPlanSerialSuite) TestIssue28254(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue28254(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists PK_GCOL_STORED9816") @@ -1236,23 +1598,41 @@ func (s *testPlanSerialSuite) TestIssue28254(c *C) { tk.MustQuery("execute stmt using @a").Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestIssue29486(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue33067(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + tk.MustExec("use test") + tk.MustExec("DROP TABLE IF EXISTS `t`") + tk.MustExec("CREATE TABLE `t` (`COL1` char(20) DEFAULT NULL, `COL2` bit(16),`COL3` date, KEY `U_M_COL5` (`COL3`,`COL2`))") + tk.MustExec("insert into t values ('','>d','9901-06-17')") + tk.MustExec("prepare stmt from 'select * from t where col1 is not null and col2 not in (?, ?, ?) and col3 in (?, ?, ?)'") + tk.MustExec(`set @a=-21188, @b=26824, @c=31855, @d="5597-1-4", @e="5755-12-6", @f="1253-7-12"`) + tk.MustQuery(`execute stmt using @a,@b,@c,@d,@e,@f`).Check(testkit.Rows()) + tk.MustExec(`set @a=-5360, @b=-11715, @c=9399, @d="9213-09-13", @e="4705-12-24", @f="9901-06-17"`) + tk.MustQuery(`execute stmt using @a,@b,@c,@d,@e,@f`).Check(testkit.Rows(" >d 9901-06-17")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +} + +func TestIssue29486(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists UK_MULTI_COL_11691`) @@ -1273,23 +1653,17 @@ func (s *testPlanSerialSuite) TestIssue29486(c *C) { tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows("126", "126")) } -func (s *testPlanSerialSuite) TestIssue28867(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue28867(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") @@ -1322,19 +1696,125 @@ func (s *testPlanSerialSuite) TestIssue28867(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestIssue29565(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestParamMarker4FastPlan(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + // test handle for point get + tk.MustExec(`use test`) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int primary key)") + tk.MustExec("insert into t values(1)") + tk.MustExec(`prepare stmt from 'select * from t where pk = ?'`) + tk.MustExec(`set @a0=1.1, @a1='1.1', @a2=1, @a3=1.0, @a4='1.0'`) + + tk.MustQuery(`execute stmt using @a2`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a2`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustQuery(`execute stmt using @a3`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a3`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a0`).Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustQuery(`execute stmt using @a4`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a4`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a1`).Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + // test indexValues for point get + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int, unique index idx(pk))") + tk.MustExec("insert into t values(1)") + tk.MustExec(`prepare stmt from 'select * from t where pk = ?'`) + tk.MustExec(`set @a0=1.1, @a1='1.1', @a2=1, @a3=1.0, @a4='1.0'`) + + tk.MustQuery(`execute stmt using @a2`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a2`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + tk.MustQuery(`execute stmt using @a3`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a3`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a0`).Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + tk.MustQuery(`execute stmt using @a4`).Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a4`).Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a1`).Check(testkit.Rows()) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + // test _tidb_rowid for point get + tk.MustExec(`use test`) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int);") + tk.MustExec("insert t values (1, 7), (1, 8), (1, 9);") + tk.MustExec(`prepare stmt from 'select * from t where _tidb_rowid = ?'`) + tk.MustExec(`set @a=2`) + tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1 8")) + tk.MustExec(`set @a=1`) + tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1 7")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + // test handle for batch point get + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int primary key)") + tk.MustExec("insert into t values (1), (2), (3), (4), (5)") + tk.MustExec(`prepare stmt from 'select * from t where pk in (1, ?, ?)'`) + tk.MustExec(`set @a0=0, @a1=1, @a2=2, @a3=3, @a1_1=1.1, @a4=4, @a5=5`) + tk.MustQuery(`execute stmt using @a2, @a3`).Sort().Check(testkit.Rows("1", "2", "3")) + tk.MustQuery(`execute stmt using @a2, @a3`).Sort().Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a0, @a4`).Sort().Check(testkit.Rows("1", "4")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a1_1, @a5`).Sort().Check(testkit.Rows("1", "5")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + // test indexValues for batch point get + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int, unique index idx(pk))") + tk.MustExec("insert into t values (1), (2), (3), (4), (5)") + tk.MustExec(`prepare stmt from 'select * from t where pk in (1, ?, ?)'`) + tk.MustExec(`set @a0=0, @a1=1, @a2=2, @a3=3, @a1_1=1.1, @a4=4, @a5=5`) + tk.MustQuery(`execute stmt using @a2, @a3`).Sort().Check(testkit.Rows("1", "2", "3")) + tk.MustQuery(`execute stmt using @a2, @a3`).Sort().Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a0, @a4`).Sort().Check(testkit.Rows("1", "4")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery(`execute stmt using @a1_1, @a5`).Sort().Check(testkit.Rows("1", "5")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + + // test _tidb_rowid for batch point get + tk.MustExec(`use test`) + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int);") + tk.MustExec("insert t values (1, 7), (1, 8), (1, 9), (1, 10);") + tk.MustExec(`prepare stmt from 'select * from t where _tidb_rowid in (1, ?, ?)'`) + tk.MustExec(`set @a2=2, @a3=3`) + tk.MustQuery("execute stmt using @a2, @a3;").Sort().Check(testkit.Rows("1 7", "1 8", "1 9")) + tk.MustExec(`set @a2=4, @a3=2`) + tk.MustQuery("execute stmt using @a2, @a3;").Sort().Check(testkit.Rows("1 10", "1 7", "1 8")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) +} + +func TestIssue29565(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) + tk := testkit.NewTestKit(t, store) tk.MustExec(`use test`) tk.MustExec(`drop table if exists PK_SIGNED_10094`) @@ -1345,22 +1825,36 @@ func (s *testPlanSerialSuite) TestIssue29565(c *C) { tk.MustQuery(`execute stmt using @a,@b`).Check(testkit.Rows()) tk.MustExec(`set @a=5408499810319315618, @b=-9999999999999999999999999999999999999999999999999999999`) tk.MustQuery(`execute stmt using @a,@b`).Check(testkit.Rows("-9999999999999999999999999999999999999999999999999999999")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustExec(`set @a=7309027171262036496, @b=-9798213896406520625`) + tk.MustQuery(`execute stmt using @a,@b`).Check(testkit.Rows()) tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestIssue28828(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - store.Close() - }() +func TestIssue31730(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + tk := testkit.NewTestKit(t, store) + + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists PK_S_MULTI_37;`) + tk.MustExec(`CREATE TABLE PK_S_MULTI_37 (COL1 decimal(55,0) NOT NULL, COL2 decimal(55,0) NOT NULL,PRIMARY KEY (COL1, COL2) /*T![clustered_index] NONCLUSTERED */) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;`) + tk.MustExec(`insert into PK_S_MULTI_37 values(-9999999999999999999999999999999999999999999999, 1);`) + tk.MustExec(`prepare stmt from 'SELECT SUM(COL1+?), col2 FROM PK_S_MULTI_37 GROUP BY col2';`) + tk.MustExec(`set @a=1;`) + tk.MustQuery(`execute stmt using @a`).Check(testkit.Rows("-9999999999999999999999999999999999999999999998 1")) +} + +func TestIssue28828(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_enable_collect_execution_info=0;") tk.MustExec("CREATE TABLE t (" + @@ -1394,22 +1888,17 @@ func (s *testPlanSerialSuite) TestIssue28828(c *C) { tk.MustQuery("select @@last_plan_from_cache;").Check(testkit.Rows("0")) } -func (s *testPlanSerialSuite) TestIssue28920(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue28920(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists UK_GCOL_VIRTUAL_18928`) @@ -1429,26 +1918,19 @@ func (s *testPlanSerialSuite) TestIssue28920(c *C) { tk.MustQuery(`execute stmt using @a, @b`).Check(testkit.Rows("-5175976006730879891 8 屘厒镇览錻碛斵大擔è§è­¨é ™ç¡ºç®„é­¨æç„鋧扭趖 ")) } -func (s *testPlanSerialSuite) TestIssue18066(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue18066(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) - tk.GetConnectionID() - c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + tk.RefreshConnectionID() + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1462,21 +1944,15 @@ func (s *testPlanSerialSuite) TestIssue18066(c *C) { testkit.Rows("2 1 1")) tk.MustExec("prepare stmt from 'select * from t'") tk.MustQuery("execute stmt").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) - tk.MustQuery("select EXEC_COUNT,plan_cache_hits, plan_in_cache from information_schema.statements_summary where digest_text='select * from `t`'").Check( - testkit.Rows("3 1 0")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select EXEC_COUNT, plan_cache_hits, plan_in_cache from information_schema.statements_summary where digest_text='select * from `t`'").Check( + testkit.Rows("3 2 1")) } -func (s *testPrepareSuite) TestPrepareForGroupByMultiItems(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() +func TestPrepareForGroupByMultiItems(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1490,8 +1966,7 @@ func (s *testPrepareSuite) TestPrepareForGroupByMultiItems(c *C) { tk.MustQuery(`execute stmt using @a, @b, @a, @b`).Check(testkit.Rows("1 4 -1", "1 2 1", "4 4 3")) tk.MustExec("set @c=10") - err = tk.ExecToErr("execute stmt using @a, @c, @a, @c") - c.Assert(err.Error(), Equals, "Unknown column '10' in 'group statement'") + require.EqualError(t, tk.ExecToErr("execute stmt using @a, @c, @a, @c"), "Unknown column '10' in 'group statement'") tk.MustExec("set @v1=1.0") tk.MustExec("set @v2=3.0") @@ -1499,16 +1974,10 @@ func (s *testPrepareSuite) TestPrepareForGroupByMultiItems(c *C) { tk.MustQuery(`execute stmt2 using @v1, @v2`).Check(testkit.Rows("10")) } -func (s *testPrepareSuite) TestInvisibleIndex(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - }() +func TestInvisibleIndexPrepare(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1518,39 +1987,33 @@ func (s *testPrepareSuite) TestInvisibleIndex(c *C) { tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) - c.Assert(len(tk.Se.GetSessionVars().StmtCtx.IndexNames), Equals, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx_a") + require.Len(t, tk.Session().GetSessionVars().StmtCtx.IndexNames, 1) + require.Equal(t, "t:idx_a", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) tk.MustExec("alter table t alter index idx_a invisible") tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) - c.Assert(len(tk.Se.GetSessionVars().StmtCtx.IndexNames), Equals, 0) + require.Len(t, tk.Session().GetSessionVars().StmtCtx.IndexNames, 0) tk.MustExec("alter table t alter index idx_a visible") tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) tk.MustQuery("execute stmt1").Check(testkit.Rows("1")) - c.Assert(len(tk.Se.GetSessionVars().StmtCtx.IndexNames), Equals, 1) - c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx_a") + require.Len(t, tk.Session().GetSessionVars().StmtCtx.IndexNames, 1) + require.Equal(t, "t:idx_a", tk.Session().GetSessionVars().StmtCtx.IndexNames[0]) } // Test for issue https://github.com/pingcap/tidb/issues/22167 -func (s *testPrepareSerialSuite) TestPrepareCacheWithJoinTable(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPrepareCacheWithJoinTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists ta, tb") @@ -1563,23 +2026,17 @@ func (s *testPrepareSerialSuite) TestPrepareCacheWithJoinTable(c *C) { tk.MustQuery("execute stmt using @b").Check(testkit.Rows("a ")) } -func (s *testPlanSerialSuite) TestPlanCacheSnapshot(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPlanCacheSnapshot(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1603,9 +2060,9 @@ func (s *testPlanSerialSuite) TestPlanCacheSnapshot(c *C) { // Record the current tso. tk.MustExec("begin") - tso := tk.Se.GetSessionVars().TxnCtx.StartTS + tso := tk.Session().GetSessionVars().TxnCtx.StartTS tk.MustExec("rollback") - c.Assert(tso > 0, IsTrue) + require.True(t, tso > 0) // Insert one more row with id = 1. tk.MustExec("insert into t values (1)") @@ -1615,22 +2072,17 @@ func (s *testPlanSerialSuite) TestPlanCacheSnapshot(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPlanCachePointGetAndTableDual(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t0, t1, t2, t3, t4") @@ -1679,7 +2131,7 @@ func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { tk.MustExec("set @a3=1,@b3=3") // TableReader plan would be built, we should cache it. tk.MustQuery("execute s3 using @b3,@a3").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute s3 using @a3,@b3").Check(testkit.Rows("2 1 1")) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) @@ -1695,27 +2147,22 @@ func (s *testPlanSerialSuite) TestPlanCachePointGetAndTableDual(c *C) { tk.MustExec("prepare s4 from 'select /*+ use_index_merge(t4) */ * from t4 where (c1 >= ? and c1 <= ?) or c2 > 1'") tk.MustExec("set @a4=1,@b4=3") tk.MustQuery("execute s4 using @b4,@a4").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute s4 using @a4,@b4").Check(testkit.Rows("2 1 1")) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPrepareSuite) TestIssue26873(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue26873(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1729,22 +2176,17 @@ func (s *testPrepareSuite) TestIssue26873(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPrepareSuite) TestIssue29511(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue29511(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1756,22 +2198,17 @@ func (s *testPrepareSuite) TestIssue29511(c *C) { tk.MustQuery("execute stmt using @a,@b;").Check(testkit.Rows("-3865356285544170443")) } -func (s *testPlanSerialSuite) TestIssue23671(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue23671(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - c.Assert(store.Close(), IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1786,23 +2223,17 @@ func (s *testPlanSerialSuite) TestIssue23671(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPrepareSerialSuite) TestIssue29296(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue29296(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec(`use test`) tk.MustExec(`drop table if exists UK_MU14722`) @@ -1825,23 +2256,17 @@ func (s *testPrepareSerialSuite) TestIssue29296(c *C) { tk.MustQuery(`execute stmt using @a,@b,@c,@d`).Check(testkit.Rows(`å§å­‡é±“鼂瘠钻ç¯é†—時鷷è½ç®Œç£‡ç €çŽ¸çœžæ‰¦é¸‡ç¥ˆç‡ 127 7902-03-05 08:54:04 -1094128660`)) } -func (s *testPrepareSerialSuite) TestIssue28246(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue28246(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists PK_AUTO_RANDOM9111;") @@ -1859,23 +2284,17 @@ func (s *testPrepareSerialSuite) TestIssue28246(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPrepareSerialSuite) TestIssue29805(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue29805(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("set tidb_enable_clustered_index=on;") @@ -1894,23 +2313,17 @@ func (s *testPrepareSerialSuite) TestIssue29805(c *C) { tk.MustQuery("select/*+ hash_agg() */ count(distinct col1) from PK_TCOLLATION10197 where col1 > '龺';").Check(testkit.Rows("0")) } -func (s *testPrepareSerialSuite) TestIssue29993(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue29993(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") @@ -1939,7 +2352,7 @@ func (s *testPrepareSerialSuite) TestIssue29993(c *C) { tk.MustQuery("execute stmt using @b").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // invalid since 'z' is not in enum('a', 'b') tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) // test PointGet + non cluster index @@ -1967,27 +2380,21 @@ func (s *testPrepareSerialSuite) TestIssue29993(c *C) { tk.MustQuery("execute stmt using @b").Check(testkit.Rows()) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) // invalid since 'z' is not in enum('a', 'b') tk.MustQuery("execute stmt using @z").Check(testkit.Rows()) } -func (s *testPrepareSerialSuite) TestIssue30100(c *C) { - defer testleak.AfterTest(c)() - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestIssue30100(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) tk.MustExec("use test") tk.MustExec("drop table if exists t;") @@ -2005,32 +2412,23 @@ func (s *testPrepareSerialSuite) TestIssue30100(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } -func (s *testPlanSerialSuite) TestPartitionTable(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - - // enable plan cache - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) // enable partition table dynamic mode tk.MustExec("create database test_plan_cache") tk.MustExec("use test_plan_cache") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + tk.MustExec("set @@tidb_enable_list_partition = 1") type testcase struct { t1Create string @@ -2140,34 +2538,25 @@ func (s *testPlanSerialSuite) TestPartitionTable(c *C) { for i := 0; i < 100; i++ { tk.MustExec(fmt.Sprintf("set @a=%v", tc.varGener())) result1 := tk.MustQuery("execute stmt1 using @a").Sort().Rows() - tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + // When https://github.com/pingcap/tidb/pull/33098 is reverted this should be 1 again + tk.MustQuery("select @@last_plan_from_cache /* i=" + strconv.Itoa(i) + " prepared statement: (t1) " + tc.query + "\n-- create table: " + tc.t1Create + "*/").Check(testkit.Rows("0")) tk.MustQuery("execute stmt2 using @a").Sort().Check(result1) tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) } } } -func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { - if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") - } - - // enable plan cache - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - tk := testkit.NewTestKit(c, store) +func TestPartitionWithVariedDataSources(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() orgEnable := core.PreparedPlanCacheEnabled() - defer func() { - dom.Close() - err = store.Close() - c.Assert(err, IsNil) - core.SetPreparedPlanCache(orgEnable) - }() + defer core.SetPreparedPlanCache(orgEnable) core.SetPreparedPlanCache(true) - tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) // enable partition table dynamic mode tk.MustExec("create database test_plan_cache2") @@ -2261,10 +2650,16 @@ func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { tk.MustExec(fmt.Sprintf(`set @a0=%v, @a1=%v, @a2=%v`, rand.Intn(40000), rand.Intn(40000), rand.Intn(40000))) var rscan, rlookup, rpoint, rbatch [][]interface{} + var expectedFromPlanCache string for id, tbl := range []string{"trangeIdx", "thashIdx", "tnormalIdx"} { scan := tk.MustQuery(fmt.Sprintf(`execute stmt%v_indexscan using @mina, @maxa`, tbl)).Sort() + if id == 2 { + expectedFromPlanCache = "1" + } else { + expectedFromPlanCache = "0" + } if i > 0 { - tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustQuery(`select @@last_plan_from_cache /* table: ` + tbl + " */").Check(testkit.Rows(expectedFromPlanCache)) } if id == 0 { rscan = scan.Rows() @@ -2274,7 +2669,7 @@ func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { lookup := tk.MustQuery(fmt.Sprintf(`execute stmt%v_indexlookup using @mina, @maxa`, tbl)).Sort() if i > 0 { - tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows(expectedFromPlanCache)) } if id == 0 { rlookup = lookup.Rows() @@ -2286,7 +2681,7 @@ func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { if tbl == `tnormalPK` && i > 0 { // PlanCache cannot support PointGet now since we haven't relocated partition after rebuilding range. // Please see Execute.rebuildRange for more details. - tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows(expectedFromPlanCache)) } if id == 0 { rpoint = point.Rows() @@ -2296,7 +2691,7 @@ func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { batch := tk.MustQuery(fmt.Sprintf(`execute stmt%v_batchget_idx using @a0, @a1, @a2`, tbl)).Sort() if i > 0 { - tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) + tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows(expectedFromPlanCache)) } if id == 0 { rbatch = batch.Rows() @@ -2306,3 +2701,69 @@ func (s *testPlanSerialSuite) TestPartitionWithVariedDatasources(c *C) { } } } + +func TestCachedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + orgEnable := core.PreparedPlanCacheEnabled() + defer core.SetPreparedPlanCache(orgEnable) + core.SetPreparedPlanCache(true) + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + require.NoError(t, err) + tk := testkit.NewTestKitWithSession(t, store, se) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + + tk.MustExec("create table t (a int, b int, index i_b(b))") + tk.MustExec("insert into t values (1, 1), (2, 2)") + tk.MustExec("alter table t cache") + + tk.MustExec("prepare tableScan from 'select * from t where a>=?'") + tk.MustExec("prepare indexScan from 'select b from t use index(i_b) where b>?'") + tk.MustExec("prepare indexLookup from 'select a from t use index(i_b) where b>? and b 0 && sql[len(sql)-1] == ';' { - stmt.SetText(sql[:len(sql)-1]) + stmt.SetText(nil, sql[:len(sql)-1]) } } @@ -361,6 +383,8 @@ const ( TypeRepair // TypeShow for ShowStmt TypeShow + // TypeExecute for ExecuteStmt + TypeExecute ) func bindableStmtType(node ast.StmtNode) byte { @@ -450,7 +474,7 @@ func (p *preprocessor) checkBindGrammar(originNode, hintedNode ast.StmtNode, def return } if tbl.Meta().TempTableType != model.TempTableNone { - p.err = ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("create binding") + p.err = dbterror.ErrOptOnTemporaryTable.GenWithStackByArgs("create binding") return } tableInfo := tbl.Meta() @@ -687,20 +711,20 @@ func (p *preprocessor) checkSetOprSelectList(stmt *ast.SetOprSelectList) { func (p *preprocessor) checkCreateDatabaseGrammar(stmt *ast.CreateDatabaseStmt) { if isIncorrectName(stmt.Name) { - p.err = ddl.ErrWrongDBName.GenWithStackByArgs(stmt.Name) + p.err = dbterror.ErrWrongDBName.GenWithStackByArgs(stmt.Name) } } func (p *preprocessor) checkAlterDatabaseGrammar(stmt *ast.AlterDatabaseStmt) { // for 'ALTER DATABASE' statement, database name can be empty to alter default database. if isIncorrectName(stmt.Name) && !stmt.AlterDefaultDatabase { - p.err = ddl.ErrWrongDBName.GenWithStackByArgs(stmt.Name) + p.err = dbterror.ErrWrongDBName.GenWithStackByArgs(stmt.Name) } } func (p *preprocessor) checkDropDatabaseGrammar(stmt *ast.DropDatabaseStmt) { if isIncorrectName(stmt.Name) { - p.err = ddl.ErrWrongDBName.GenWithStackByArgs(stmt.Name) + p.err = dbterror.ErrWrongDBName.GenWithStackByArgs(stmt.Name) } } @@ -757,18 +781,7 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { case ast.TableOptionShardRowID: p.err = ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits") return - case ast.TableOptionPlacementPrimaryRegion, - ast.TableOptionPlacementRegions, - ast.TableOptionPlacementFollowerCount, - ast.TableOptionPlacementVoterCount, - ast.TableOptionPlacementLearnerCount, - ast.TableOptionPlacementSchedule, - ast.TableOptionPlacementConstraints, - ast.TableOptionPlacementLeaderConstraints, - ast.TableOptionPlacementLearnerConstraints, - ast.TableOptionPlacementFollowerConstraints, - ast.TableOptionPlacementVoterConstraints, - ast.TableOptionPlacementPolicy: + case ast.TableOptionPlacementPolicy: p.err = ErrOptOnTemporaryTable.GenWithStackByArgs("PLACEMENT") return } @@ -776,14 +789,17 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { } tName := stmt.Table.Name.String() if isIncorrectName(tName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(tName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(tName) return } countPrimaryKey := 0 for _, colDef := range stmt.Cols { if err := checkColumn(colDef); err != nil { - p.err = err - return + // Try to convert to BLOB or TEXT, see issue #30328 + if !terror.ErrorEqual(err, types.ErrTooBigFieldLength) || !p.hasAutoConvertWarning(colDef) { + p.err = err + return + } } isPrimary, err := checkColumnOptions(stmt.TemporaryKeyword != ast.TemporaryNone, colDef.Options) if err != nil { @@ -805,7 +821,7 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { return } if constraint.IsEmptyIndex { - p.err = ddl.ErrWrongNameForIndex.GenWithStackByArgs(constraint.Name) + p.err = dbterror.ErrWrongNameForIndex.GenWithStackByArgs(constraint.Name) return } case ast.ConstraintPrimaryKey: @@ -829,30 +845,48 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { p.err = errors.New("'CREATE TABLE ... SELECT' is not implemented yet") return } else if len(stmt.Cols) == 0 && stmt.ReferTable == nil { - p.err = ddl.ErrTableMustHaveColumns + p.err = dbterror.ErrTableMustHaveColumns return } + + if stmt.Partition != nil { + for _, def := range stmt.Partition.Definitions { + pName := def.Name.String() + if isIncorrectName(pName) { + p.err = dbterror.ErrWrongPartitionName.GenWithStackByArgs(pName) + return + } + } + } } func (p *preprocessor) checkCreateViewGrammar(stmt *ast.CreateViewStmt) { vName := stmt.ViewName.Name.String() if isIncorrectName(vName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(vName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(vName) return } for _, col := range stmt.Cols { if isIncorrectName(col.String()) { - p.err = ddl.ErrWrongColumnName.GenWithStackByArgs(col) + p.err = dbterror.ErrWrongColumnName.GenWithStackByArgs(col) return } } + if len(stmt.Definer.Username) > auth.UserNameMaxLength { + p.err = dbterror.ErrWrongStringLength.GenWithStackByArgs(stmt.Definer.Username, "user name", auth.UserNameMaxLength) + return + } + if len(stmt.Definer.Hostname) > auth.HostNameMaxLength { + p.err = dbterror.ErrWrongStringLength.GenWithStackByArgs(stmt.Definer.Hostname, "host name", auth.HostNameMaxLength) + return + } } func (p *preprocessor) checkCreateViewWithSelect(stmt ast.Node) { switch s := stmt.(type) { case *ast.SelectStmt: if s.SelectIntoOpt != nil { - p.err = ddl.ErrViewSelectClause.GenWithStackByArgs("INFO") + p.err = dbterror.ErrViewSelectClause.GenWithStackByArgs("INFO") return } if s.LockInfo != nil && s.LockInfo.LockType != ast.SelectLockNone { @@ -895,7 +929,7 @@ func (p *preprocessor) checkDropTemporaryTableGrammar(stmt *ast.DropTableStmt) { currentDB := model.NewCIStr(p.ctx.GetSessionVars().CurrentDB) for _, t := range stmt.Tables { if isIncorrectName(t.Name.String()) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(t.Name.String()) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(t.Name.String()) return } @@ -926,7 +960,7 @@ func (p *preprocessor) checkDropTemporaryTableGrammar(stmt *ast.DropTableStmt) { func (p *preprocessor) checkDropTableNames(tables []*ast.TableName) { for _, t := range tables { if isIncorrectName(t.Name.String()) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(t.Name.String()) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(t.Name.String()) return } } @@ -999,11 +1033,11 @@ func checkColumnOptions(isTempTable bool, ops []*ast.ColumnOption) (int, error) func (p *preprocessor) checkCreateIndexGrammar(stmt *ast.CreateIndexStmt) { tName := stmt.Table.Name.String() if isIncorrectName(tName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(tName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(tName) return } if stmt.IndexName == "" { - p.err = ddl.ErrWrongNameForIndex.GenWithStackByArgs(stmt.IndexName) + p.err = dbterror.ErrWrongNameForIndex.GenWithStackByArgs(stmt.IndexName) return } p.err = checkIndexInfo(stmt.IndexName, stmt.IndexPartSpecifications) @@ -1033,12 +1067,12 @@ func (p *preprocessor) checkRenameTableGrammar(stmt *ast.RenameTableStmt) { func (p *preprocessor) checkRenameTable(oldTable, newTable string) { if isIncorrectName(oldTable) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(oldTable) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(oldTable) return } if isIncorrectName(newTable) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(newTable) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(newTable) return } } @@ -1046,11 +1080,11 @@ func (p *preprocessor) checkRenameTable(oldTable, newTable string) { func (p *preprocessor) checkRepairTableGrammar(stmt *ast.RepairTableStmt) { // Check create table stmt whether it's is in REPAIR MODE. if !domainutil.RepairInfo.InRepairMode() { - p.err = ddl.ErrRepairTableFail.GenWithStackByArgs("TiDB is not in REPAIR MODE") + p.err = dbterror.ErrRepairTableFail.GenWithStackByArgs("TiDB is not in REPAIR MODE") return } if len(domainutil.RepairInfo.GetRepairTableList()) == 0 { - p.err = ddl.ErrRepairTableFail.GenWithStackByArgs("repair list is empty") + p.err = dbterror.ErrRepairTableFail.GenWithStackByArgs("repair list is empty") return } @@ -1063,7 +1097,7 @@ func (p *preprocessor) checkRepairTableGrammar(stmt *ast.RepairTableStmt) { func (p *preprocessor) checkAlterTableGrammar(stmt *ast.AlterTableStmt) { tName := stmt.Table.Name.String() if isIncorrectName(tName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(tName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(tName) return } specs := stmt.Specs @@ -1071,7 +1105,7 @@ func (p *preprocessor) checkAlterTableGrammar(stmt *ast.AlterTableStmt) { if spec.NewTable != nil { ntName := spec.NewTable.Name.String() if isIncorrectName(ntName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(ntName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(ntName) return } } @@ -1102,6 +1136,14 @@ func (p *preprocessor) checkAlterTableGrammar(stmt *ast.AlterTableStmt) { p.err = ErrInternal.GenWithStack(msg) return } + case ast.AlterTableAddPartitions: + for _, def := range spec.PartDefinitions { + pName := def.Name.String() + if isIncorrectName(pName) { + p.err = dbterror.ErrWrongPartitionName.GenWithStackByArgs(pName) + return + } + } default: // Nothing to do now. } @@ -1123,14 +1165,20 @@ func checkDuplicateColumnName(IndexPartSpecifications []*ast.IndexPartSpecificat return nil } -// checkIndexInfo checks index name and index column names. +// checkIndexInfo checks index name, index column names and prefix lengths. func checkIndexInfo(indexName string, IndexPartSpecifications []*ast.IndexPartSpecification) error { if strings.EqualFold(indexName, mysql.PrimaryKeyName) { - return ddl.ErrWrongNameForIndex.GenWithStackByArgs(indexName) + return dbterror.ErrWrongNameForIndex.GenWithStackByArgs(indexName) } if len(IndexPartSpecifications) > mysql.MaxKeyParts { return infoschema.ErrTooManyKeyParts.GenWithStackByArgs(mysql.MaxKeyParts) } + for _, idxSpec := range IndexPartSpecifications { + // -1 => unspecified/full, > 0 OK, 0 => error + if idxSpec.Expr == nil && idxSpec.Length == 0 { + return ErrKeyPart0.GenWithStackByArgs(idxSpec.Column.Name.O) + } + } return checkDuplicateColumnName(IndexPartSpecifications) } @@ -1140,9 +1188,9 @@ func checkUnsupportedTableOptions(options []*ast.TableOption) error { for _, option := range options { switch option.Tp { case ast.TableOptionUnion: - err = ddl.ErrTableOptionUnionUnsupported + err = dbterror.ErrTableOptionUnionUnsupported case ast.TableOptionInsertMethod: - err = ddl.ErrTableOptionInsertMethodUnsupported + err = dbterror.ErrTableOptionInsertMethodUnsupported case ast.TableOptionEngine: err = checkTableEngine(option.StrValue) } @@ -1170,7 +1218,7 @@ var mysqlValidTableEngineNames = map[string]struct{}{ func checkTableEngine(engineName string) error { if _, have := mysqlValidTableEngineNames[strings.ToLower(engineName)]; !have { - return ddl.ErrUnknownEngine.GenWithStackByArgs(engineName) + return dbterror.ErrUnknownEngine.GenWithStackByArgs(engineName) } return nil } @@ -1188,7 +1236,7 @@ func checkReferInfoForTemporaryTable(tableMetaInfo *model.TableInfo) error { if tableMetaInfo.ShardRowIDBits != 0 { return ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits") } - if tableMetaInfo.DirectPlacementOpts != nil || tableMetaInfo.PlacementPolicyRef != nil { + if tableMetaInfo.PlacementPolicyRef != nil { return ErrOptOnTemporaryTable.GenWithStackByArgs("placement") } @@ -1201,7 +1249,7 @@ func checkColumn(colDef *ast.ColumnDef) error { // Check column name. cName := colDef.Name.Name.String() if isIncorrectName(cName) { - return ddl.ErrWrongColumnName.GenWithStackByArgs(cName) + return dbterror.ErrWrongColumnName.GenWithStackByArgs(cName) } if isInvalidDefaultValue(colDef) { @@ -1344,11 +1392,11 @@ func (p *preprocessor) checkContainDotColumn(stmt *ast.CreateTableStmt) { for _, colDef := range stmt.Cols { // check schema and table names. if colDef.Name.Schema.O != sName && len(colDef.Name.Schema.O) != 0 { - p.err = ddl.ErrWrongDBName.GenWithStackByArgs(colDef.Name.Schema.O) + p.err = dbterror.ErrWrongDBName.GenWithStackByArgs(colDef.Name.Schema.O) return } if colDef.Name.Table.O != tName && len(colDef.Name.Table.O) != 0 { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(colDef.Name.Table.O) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(colDef.Name.Table.O) return } } @@ -1413,9 +1461,11 @@ func (p *preprocessor) handleTableName(tn *ast.TableName) { return } - p.handleAsOfAndReadTS(tn.AsOf) - if p.err != nil { - return + if p.stmtTp == TypeSelect { + if p.err = p.staleReadProcessor.OnSelectTable(tn); p.err != nil { + return + } + p.updateStateFromStaleReadProcessor() } table, err := p.tableByName(tn) @@ -1443,24 +1493,24 @@ func (p *preprocessor) checkNotInRepair(tn *ast.TableName) { return } if tableInfo != nil { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(tn.Name.L, "this table is in repair") + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(tn.Name.L, "this table is in repair") } } func (p *preprocessor) handleRepairName(tn *ast.TableName) { // Check the whether the repaired table is system table. if util.IsMemOrSysDB(tn.Schema.L) { - p.err = ddl.ErrRepairTableFail.GenWithStackByArgs("memory or system database is not for repair") + p.err = dbterror.ErrRepairTableFail.GenWithStackByArgs("memory or system database is not for repair") return } tableInfo, dbInfo := domainutil.RepairInfo.GetRepairedTableInfoByTableName(tn.Schema.L, tn.Name.L) // tableName here only has the schema rather than DBInfo. if dbInfo == nil { - p.err = ddl.ErrRepairTableFail.GenWithStackByArgs("database " + tn.Schema.L + " is not in repair") + p.err = dbterror.ErrRepairTableFail.GenWithStackByArgs("database " + tn.Schema.L + " is not in repair") return } if tableInfo == nil { - p.err = ddl.ErrRepairTableFail.GenWithStackByArgs("table " + tn.Name.L + " is not in repair") + p.err = dbterror.ErrRepairTableFail.GenWithStackByArgs("table " + tn.Name.L + " is not in repair") return } p.ctx.SetValue(domainutil.RepairedTable, tableInfo) @@ -1489,6 +1539,18 @@ func (p *preprocessor) resolveShowStmt(node *ast.ShowStmt) { } } +func (p *preprocessor) resolveExecuteStmt(node *ast.ExecuteStmt) { + prepared, err := GetPreparedStmt(node, p.ctx.GetSessionVars()) + if err != nil { + p.err = err + return + } + + if p.err = p.staleReadProcessor.OnExecutePreparedStmt(prepared.SnapshotTSEvaluator); p.err == nil { + p.updateStateFromStaleReadProcessor() + } +} + func (p *preprocessor) resolveCreateTableStmt(node *ast.CreateTableStmt) { for _, val := range node.Constraints { if val.Refer != nil && val.Refer.Table.Schema.String() == "" { @@ -1515,7 +1577,7 @@ func (p *preprocessor) resolveAlterTableStmt(node *ast.AlterTableStmt) { func (p *preprocessor) resolveCreateSequenceStmt(stmt *ast.CreateSequenceStmt) { sName := stmt.Name.Name.String() if isIncorrectName(sName) { - p.err = ddl.ErrWrongTableName.GenWithStackByArgs(sName) + p.err = dbterror.ErrWrongTableName.GenWithStackByArgs(sName) return } } @@ -1548,125 +1610,34 @@ func (p *preprocessor) checkFuncCastExpr(node *ast.FuncCastExpr) { } } -// handleAsOfAndReadTS tries to handle as of closure, or possibly read_ts. -func (p *preprocessor) handleAsOfAndReadTS(node *ast.AsOfClause) { - if p.stmtTp != TypeSelect { +func (p *preprocessor) updateStateFromStaleReadProcessor() { + if p.initedLastSnapshotTS { return } - defer func() { + + if p.IsStaleness = p.staleReadProcessor.IsStaleness(); p.IsStaleness { + p.LastSnapshotTS = p.staleReadProcessor.GetStalenessReadTS() + p.SnapshotTSEvaluator = p.staleReadProcessor.GetStalenessTSEvaluatorForPrepare() + p.InfoSchema = p.staleReadProcessor.GetStalenessInfoSchema() // If the select statement was like 'select * from t as of timestamp ...' or in a stale read transaction // or is affected by the tidb_read_staleness session variable, then the statement will be makred as isStaleness // in stmtCtx - if p.flag&inPrepare == 0 && p.IsStaleness { + if p.flag&inPrepare == 0 { p.ctx.GetSessionVars().StmtCtx.IsStaleness = true } - }() - // When statement is during the Txn, we check whether there exists AsOfClause. If exists, we will return error, - // otherwise we should directly set the return param from TxnCtx. - p.ReadReplicaScope = kv.GlobalReplicaScope - if p.ctx.GetSessionVars().InTxn() { - if node != nil { - p.err = ErrAsOf.FastGenWithCause("as of timestamp can't be set in transaction.") - return - } - txnCtx := p.ctx.GetSessionVars().TxnCtx - p.ReadReplicaScope = txnCtx.TxnScope - // It means we meet following case: - // 1. start transaction read only as of timestamp ts - // 2. select statement - if txnCtx.IsStaleness { - p.LastSnapshotTS = txnCtx.StartTS - p.IsStaleness = txnCtx.IsStaleness - p.initedLastSnapshotTS = true - return - } - } - scope := config.GetTxnScopeFromConfig() - if p.ctx.GetSessionVars().GetReplicaRead().IsClosestRead() && scope != kv.GlobalReplicaScope { - p.ReadReplicaScope = scope } - // If the statement is in auto-commit mode, we will check whether there exists read_ts, if exists, - // we will directly use it. The txnScope will be defined by the zone label, if it is not set, we will use - // global txnScope directly. - readTS := p.ctx.GetSessionVars().TxnReadTS.UseTxnReadTS() - readStaleness := p.ctx.GetSessionVars().ReadStaleness - var ts uint64 - switch { - case readTS > 0: - ts = readTS - if node != nil { - p.err = ErrAsOf.FastGenWithCause("can't use select as of while already set transaction as of") - return - } - if !p.initedLastSnapshotTS { - p.SnapshotTSEvaluator = func(sessionctx.Context) (uint64, error) { - return ts, nil - } - p.LastSnapshotTS = ts - p.IsStaleness = true - } - case readTS == 0 && node != nil: - // If we didn't use read_ts, and node isn't nil, it means we use 'select table as of timestamp ... ' - // for stale read - // It means we meet following case: - // select statement with as of timestamp - ts, p.err = calculateTsExpr(p.ctx, node) - if p.err != nil { - return - } - if err := sessionctx.ValidateStaleReadTS(context.Background(), p.ctx, ts); err != nil { - p.err = errors.Trace(err) - return - } - if !p.initedLastSnapshotTS { - p.SnapshotTSEvaluator = func(ctx sessionctx.Context) (uint64, error) { - return calculateTsExpr(ctx, node) - } - p.LastSnapshotTS = ts - p.IsStaleness = true - } - case readTS == 0 && node == nil && readStaleness != 0: - // If both readTS and node is empty while the readStaleness isn't, it means we meet following situation: - // set @@tidb_read_staleness='-5'; - // select * from t; - // Then the following select statement should be affected by the tidb_read_staleness in session. - ts, p.err = calculateTsWithReadStaleness(p.ctx, readStaleness) - if p.err != nil { - return - } - if err := sessionctx.ValidateStaleReadTS(context.Background(), p.ctx, ts); err != nil { - p.err = errors.Trace(err) - return - } - if !p.initedLastSnapshotTS { - p.SnapshotTSEvaluator = func(ctx sessionctx.Context) (uint64, error) { - return calculateTsWithReadStaleness(p.ctx, readStaleness) - } - p.LastSnapshotTS = ts - p.IsStaleness = true - } + // It is a little hacking for the below codes. `ReadReplicaScope` is used both by stale read's closest read and local txn. + // They are different features and the value for `ReadReplicaScope` will be conflicted in some scenes. + // But because local txn is still an experimental feature, we should make stale read work first. + if p.IsStaleness || p.ctx.GetSessionVars().GetReplicaRead().IsClosestRead() { + // When stale read or closet read is set, we read the tidb's locality as the read replica scope + p.ReadReplicaScope = config.GetTxnScopeFromConfig() + } else { + // Otherwise, use the scope from TxnCtx for local txn validation + p.ReadReplicaScope = p.ctx.GetSessionVars().TxnCtx.TxnScope } - // If the select statement is related to multi tables, we should grantee that all tables use the same timestamp - if p.LastSnapshotTS != ts { - p.err = ErrAsOf.GenWithStack("can not set different time in the as of") - return - } - if p.LastSnapshotTS != 0 { - dom := domain.GetDomain(p.ctx) - is, err := dom.GetSnapshotInfoSchema(p.LastSnapshotTS) - // if infoschema is empty, LastSnapshotTS init failed - if err != nil { - p.err = err - return - } - if is == nil { - p.err = fmt.Errorf("can not get any information schema based on snapshotTS: %d", p.LastSnapshotTS) - return - } - p.InfoSchema = temptable.AttachLocalTemporaryTableInfoSchema(p.ctx, is) - } p.initedLastSnapshotTS = true } @@ -1689,3 +1660,27 @@ func (p *preprocessor) ensureInfoSchema() infoschema.InfoSchema { p.InfoSchema = p.ctx.GetInfoSchema().(infoschema.InfoSchema) return p.InfoSchema } + +func (p *preprocessor) initTxnContextProviderIfNecessary(node ast.Node) { + if p.err != nil || p.flag&initTxnContextProvider == 0 { + return + } + + p.err = sessiontxn.GetTxnManager(p.ctx).SetContextProvider(&sessiontxn.SimpleTxnContextProvider{ + InfoSchema: p.ensureInfoSchema(), + }) +} + +func (p *preprocessor) hasAutoConvertWarning(colDef *ast.ColumnDef) bool { + sessVars := p.ctx.GetSessionVars() + if !sessVars.SQLMode.HasStrictMode() && colDef.Tp.Tp == mysql.TypeVarchar { + colDef.Tp.Tp = mysql.TypeBlob + if colDef.Tp.Charset == charset.CharsetBin { + sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colDef.Name.Name.O, "VARBINARY", "BLOB")) + } else { + sessVars.StmtCtx.AppendWarning(dbterror.ErrAutoConvert.GenWithStackByArgs(colDef.Name.Name.O, "VARCHAR", "TEXT")) + } + return true + } + return false +} diff --git a/planner/core/preprocess_test.go b/planner/core/preprocess_test.go index ff25091b4eeb8..0a22f349bd9ed 100644 --- a/planner/core/preprocess_test.go +++ b/planner/core/preprocess_test.go @@ -15,15 +15,11 @@ package core_test import ( - "context" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/errors" - "github.com/pingcap/tidb/ddl" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/model" @@ -32,54 +28,26 @@ import ( "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/testleak" + "github.com/pingcap/tidb/util/dbterror" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testValidatorSuite{}) - -type testValidatorSuite struct { - store kv.Storage - dom *domain.Domain - se session.Session - ctx sessionctx.Context - is infoschema.InfoSchema -} - -func (s *testValidatorSuite) SetUpTest(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) - - s.se, err = session.CreateSession4Test(s.store) - c.Assert(err, IsNil) - - s.ctx = s.se.(sessionctx.Context) - - s.is = infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable()}) -} - -func (s *testValidatorSuite) TearDownTest(c *C) { - s.dom.Close() - err := s.store.Close() - c.Assert(err, IsNil) - testleak.AfterTest(c)() -} - -func (s *testValidatorSuite) runSQL(c *C, sql string, inPrepare bool, terr error) { - stmts, err1 := session.Parse(s.ctx, sql) - c.Assert(err1, IsNil, Commentf("sql: %s", sql)) - c.Assert(stmts, HasLen, 1) +func runSQL(t *testing.T, ctx sessionctx.Context, is infoschema.InfoSchema, sql string, inPrepare bool, terr error) { + stmts, err := session.Parse(ctx, sql) + require.NoErrorf(t, err, "sql: %s", sql) + require.Len(t, stmts, 1) stmt := stmts[0] var opts []core.PreprocessOpt if inPrepare { opts = append(opts, core.InPrepare) } - err := core.Preprocess(s.ctx, stmt, append(opts, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: s.is}))...) - c.Assert(terror.ErrorEqual(err, terr), IsTrue, Commentf("sql: %s, err:%v", sql, err)) + err = core.Preprocess(ctx, stmt, append(opts, core.WithPreprocessorReturn(&core.PreprocessorReturn{InfoSchema: is}))...) + require.Truef(t, terror.ErrorEqual(err, terr), "sql: %s, err:%v", sql, err) } -func (s *testValidatorSuite) TestValidator(c *C) { +func TestValidator(t *testing.T) { tests := []struct { sql string inPrepare bool @@ -158,8 +126,8 @@ func (s *testValidatorSuite) TestValidator(c *C) { errors.New("[types:1074]Column length too big for column 'c' (max = 16383); use BLOB or TEXT instead")}, {"alter table t add column c varchar(4294967295) CHARACTER SET ascii", true, errors.New("[types:1074]Column length too big for column 'c' (max = 65535); use BLOB or TEXT instead")}, - {"create table t", false, ddl.ErrTableMustHaveColumns}, - {"create table t (unique(c))", false, ddl.ErrTableMustHaveColumns}, + {"create table t", false, dbterror.ErrTableMustHaveColumns}, + {"create table t (unique(c))", false, dbterror.ErrTableMustHaveColumns}, {"create table `t ` (a int)", true, errors.New("[ddl:1103]Incorrect table name 't '")}, {"create table `` (a int)", true, errors.New("[ddl:1103]Incorrect table name ''")}, @@ -255,7 +223,7 @@ func (s *testValidatorSuite) TestValidator(c *C) { {"select * from (select 1 ) a , (select 2) b, (select * from (select 3) a join (select 4) b) c;", false, nil}, {"CREATE VIEW V (a,b,c) AS SELECT 1,1,3;", false, nil}, - {"CREATE VIEW V AS SELECT 5 INTO OUTFILE 'ttt'", true, ddl.ErrViewSelectClause.GenWithStackByArgs("INFO")}, + {"CREATE VIEW V AS SELECT 5 INTO OUTFILE 'ttt'", true, dbterror.ErrViewSelectClause.GenWithStackByArgs("INFO")}, {"CREATE VIEW V AS SELECT 5 FOR UPDATE", false, nil}, {"CREATE VIEW V AS SELECT 5 LOCK IN SHARE MODE", false, nil}, @@ -282,11 +250,11 @@ func (s *testValidatorSuite) TestValidator(c *C) { {"CREATE INDEX `` on t ((lower(a)));", true, errors.New("[ddl:1280]Incorrect index name ''")}, // issue 21082 - {"CREATE TABLE t (a int) ENGINE=Unknown;", false, ddl.ErrUnknownEngine}, + {"CREATE TABLE t (a int) ENGINE=Unknown;", false, dbterror.ErrUnknownEngine}, {"CREATE TABLE t (a int) ENGINE=InnoDB;", false, nil}, {"CREATE TABLE t (a int);", false, nil}, {"ALTER TABLE t ENGINE=InnoDB;", false, nil}, - {"ALTER TABLE t ENGINE=Unknown;", false, ddl.ErrUnknownEngine}, + {"ALTER TABLE t ENGINE=Unknown;", false, dbterror.ErrUnknownEngine}, // issue 20295 // issue 11193 @@ -304,63 +272,95 @@ func (s *testValidatorSuite) TestValidator(c *C) { {"select * from t tablesample system() repeatable (10);", false, expression.ErrInvalidTableSample}, } - _, err := s.se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable()}) for _, tt := range tests { - s.runSQL(c, tt.sql, tt.inPrepare, tt.err) + runSQL(t, tk.Session(), is, tt.sql, tt.inPrepare, tt.err) } } -func (s *testValidatorSuite) TestForeignKey(c *C) { - _, err := s.se.Execute(context.Background(), "create table test.t1(a int, b int, c int)") - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "create table test.t2(d int)") - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "create database test2") - c.Assert(err, IsNil) - - _, err = s.se.Execute(context.Background(), "create table test2.t(e int)") - c.Assert(err, IsNil) - - s.is = s.dom.InfoSchema() - - s.runSQL(c, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (a) REFERENCES t2 (d)", false, nil) - - _, err = s.se.Execute(context.Background(), "use test") - c.Assert(err, IsNil) +func TestForeignKey(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create table test.t1(a int, b int, c int)") + tk.MustExec("create table test.t2(d int)") + tk.MustExec("create database test2") + tk.MustExec("create table test2.t(e int)") + + is := dom.InfoSchema() + runSQL(t, tk.Session(), is, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (a) REFERENCES t2 (d)", false, nil) + + tk.MustExec("use test") + runSQL(t, tk.Session(), is, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (b) REFERENCES t2 (d)", false, nil) + runSQL(t, tk.Session(), is, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (c) REFERENCES test2.t (e)", false, nil) +} - s.runSQL(c, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (b) REFERENCES t2 (d)", false, nil) +func TestDropGlobalTempTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table tb(id int);") + tk.MustExec("create global temporary table temp(id int) on commit delete rows;") + tk.MustExec("create global temporary table temp1(id int) on commit delete rows;") + tk.MustExec("create temporary table ltemp1(id int);") + tk.MustExec("create database test2") + tk.MustExec("create global temporary table test2.temp2(id int) on commit delete rows;") + + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) + runSQL(t, tk.Session(), is, "drop global temporary table tb;", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table temp", false, nil) + runSQL(t, tk.Session(), is, "drop global temporary table test.tb;", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table test.temp1", false, nil) + runSQL(t, tk.Session(), is, "drop global temporary table ltemp1", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table test.ltemp1", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table temp, temp1", false, nil) + runSQL(t, tk.Session(), is, "drop global temporary table temp, tb", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table temp, ltemp1", false, core.ErrDropTableOnTemporaryTable) + runSQL(t, tk.Session(), is, "drop global temporary table test2.temp2, temp1", false, nil) +} - s.runSQL(c, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (c) REFERENCES test2.t (e)", false, nil) +func TestErrKeyPart0(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database TestErrKeyPart") + tk.MustExec("use TestErrKeyPart") + err := tk.ExecToErr("CREATE TABLE `tbl11`(`a` INT(11) NOT NULL, `b` INT(11), PRIMARY KEY (`a`(0))) CHARSET UTF8MB4 COLLATE UTF8MB4_BIN") + require.EqualError(t, err, "[planner:1391]Key part 'a' length cannot be 0") + err = tk.ExecToErr("create table t (a int, b varchar(255), key (b(0)))") + require.EqualError(t, err, "[planner:1391]Key part 'b' length cannot be 0") + err = tk.ExecToErr("create table t (a int, b varchar(255))") + require.NoError(t, err) + err = tk.ExecToErr("alter table t add index (b(0))") + require.EqualError(t, err, "[planner:1391]Key part 'b' length cannot be 0") } -func (s *testValidatorSuite) TestDropGlobalTempTable(c *C) { - ctx := context.Background() - execSQLList := []string{ - "use test", - "create table tb(id int);", - "create global temporary table temp(id int) on commit delete rows;", - "create global temporary table temp1(id int) on commit delete rows;", - "create temporary table ltemp1(id int);", - "create database test2", - "create global temporary table test2.temp2(id int) on commit delete rows;", - } - for _, execSQL := range execSQLList { - _, err := s.se.Execute(ctx, execSQL) - c.Assert(err, IsNil) +// For issue #30328 +func TestLargeVarcharAutoConv(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable()}) + runSQL(t, tk.Session(), is, "CREATE TABLE t1(a varbinary(70000), b varchar(70000000))", false, + errors.New("[types:1074]Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead")) + + tk.MustExec("SET sql_mode = 'NO_ENGINE_SUBSTITUTION'") + runSQL(t, tk.Session(), is, "CREATE TABLE t1(a varbinary(70000), b varchar(70000000));", false, nil) + runSQL(t, tk.Session(), is, "CREATE TABLE t1(a varbinary(70000), b varchar(70000000) charset utf8mb4);", false, nil) + warnCnt := tk.Session().GetSessionVars().StmtCtx.WarningCount() + // It is only 3. For the first stmt, charset of column b is not resolved, so ddl will append a warning for it + require.Equal(t, uint16(3), warnCnt) + warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + for i := range warns { + require.True(t, terror.ErrorEqual(warns[i].Err, dbterror.ErrAutoConvert)) } - s.is = s.se.GetInfoSchema().(infoschema.InfoSchema) - s.runSQL(c, "drop global temporary table tb;", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table temp", false, nil) - s.runSQL(c, "drop global temporary table test.tb;", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table test.temp1", false, nil) - s.runSQL(c, "drop global temporary table ltemp1", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table test.ltemp1", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table temp, temp1", false, nil) - s.runSQL(c, "drop global temporary table temp, tb", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table temp, ltemp1", false, core.ErrDropTableOnTemporaryTable) - s.runSQL(c, "drop global temporary table test2.temp2, temp1", false, nil) } diff --git a/planner/core/resolve_indices.go b/planner/core/resolve_indices.go index fa8708c960759..7b5b4261a281c 100644 --- a/planner/core/resolve_indices.go +++ b/planner/core/resolve_indices.go @@ -15,7 +15,9 @@ package core import ( + "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/util/disjointset" ) @@ -410,14 +412,23 @@ func (p *basePhysicalAgg) ResolveIndices() (err error) { return } -// ResolveIndices implements Plan interface. -func (p *PhysicalSort) ResolveIndices() (err error) { - err = p.basePhysicalPlan.ResolveIndices() +func resolveIndicesForSort(p basePhysicalPlan) (err error) { + err = p.ResolveIndices() if err != nil { return err } - for _, item := range p.ByItems { - item.Expr, err = item.Expr.ResolveIndices(p.children[0].Schema()) + + var byItems []*util.ByItems + switch x := p.self.(type) { + case *PhysicalSort: + byItems = x.ByItems + case *NominalSort: + byItems = x.ByItems + default: + return errors.Errorf("expect PhysicalSort or NominalSort, but got %s", p.TP()) + } + for _, item := range byItems { + item.Expr, err = item.Expr.ResolveIndices(p.Children()[0].Schema()) if err != nil { return err } @@ -425,6 +436,16 @@ func (p *PhysicalSort) ResolveIndices() (err error) { return err } +// ResolveIndices implements Plan interface. +func (p *PhysicalSort) ResolveIndices() (err error) { + return resolveIndicesForSort(p.basePhysicalPlan) +} + +// ResolveIndices implements Plan interface. +func (p *NominalSort) ResolveIndices() (err error) { + return resolveIndicesForSort(p.basePhysicalPlan) +} + // ResolveIndices implements Plan interface. func (p *PhysicalWindow) ResolveIndices() (err error) { err = p.physicalSchemaProducer.ResolveIndices() diff --git a/planner/core/rule_aggregation_elimination.go b/planner/core/rule_aggregation_elimination.go index 61d9e0f117e0d..9adca6936099d 100644 --- a/planner/core/rule_aggregation_elimination.go +++ b/planner/core/rule_aggregation_elimination.go @@ -67,7 +67,7 @@ func (a *aggregationEliminateChecker) tryToEliminateAggregation(agg *LogicalAggr // GroupByCols has unique key, so this aggregation can be removed. if ok, proj := ConvertAggToProj(agg, agg.schema); ok { proj.SetChildren(agg.children[0]) - appendAggregationEliminateTraceStep(agg, uniqueKey, opt) + appendAggregationEliminateTraceStep(agg, proj, uniqueKey, opt) return proj } } @@ -116,17 +116,26 @@ func (a *aggregationEliminateChecker) tryToEliminateDistinct(agg *LogicalAggrega } } -func appendAggregationEliminateTraceStep(agg *LogicalAggregation, uniqueKey expression.KeyInfo, opt *logicalOptimizeOp) { - opt.appendStepToCurrent(agg.ID(), agg.TP(), - fmt.Sprintf("%s is a unique key", uniqueKey.String()), - "aggregation is simplified to a projection") +func appendAggregationEliminateTraceStep(agg *LogicalAggregation, proj *LogicalProjection, uniqueKey expression.KeyInfo, opt *logicalOptimizeOp) { + reason := func() string { + return fmt.Sprintf("%s is a unique key", uniqueKey.String()) + } + action := func() string { + return fmt.Sprintf("%v_%v is simplified to a %v_%v", agg.TP(), agg.ID(), proj.TP(), proj.ID()) + } + + opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) } func appendDistinctEliminateTraceStep(agg *LogicalAggregation, uniqueKey expression.KeyInfo, af *aggregation.AggFuncDesc, opt *logicalOptimizeOp) { - opt.appendStepToCurrent(agg.ID(), agg.TP(), - fmt.Sprintf("%s is a unique key", uniqueKey.String()), - fmt.Sprintf("%s(distinct ...) is simplified to %s(...)", af.Name, af.Name)) + reason := func() string { + return fmt.Sprintf("%s is a unique key", uniqueKey.String()) + } + action := func() string { + return fmt.Sprintf("%s(distinct ...) is simplified to %s(...)", af.Name, af.Name) + } + opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) } // ConvertAggToProj convert aggregation to projection. diff --git a/planner/core/rule_aggregation_push_down.go b/planner/core/rule_aggregation_push_down.go index 7cc0548a7f57d..5f927befb8ee3 100644 --- a/planner/core/rule_aggregation_push_down.go +++ b/planner/core/rule_aggregation_push_down.go @@ -517,7 +517,7 @@ func (*aggregationPushDownSolver) name() string { func appendAggPushDownAcrossJoinTraceStep(oldAgg, newAgg *LogicalAggregation, aggFuncs []*aggregation.AggFuncDesc, join *LogicalJoin, childIdx int, opt *logicalOptimizeOp) { reason := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v]'s functions[", oldAgg.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v's functions[", oldAgg.TP(), oldAgg.ID())) for i, aggFunc := range aggFuncs { if i > 0 { buffer.WriteString(",") @@ -526,23 +526,23 @@ func appendAggPushDownAcrossJoinTraceStep(oldAgg, newAgg *LogicalAggregation, ag } buffer.WriteString("] are decomposable with join") return buffer.String() - }() + } action := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v] pushed down across join[%v], ", oldAgg.ID(), join.ID())) - buffer.WriteString(fmt.Sprintf("and join %v path becomes agg[%v]", func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v pushed down across %v_%v, ", oldAgg.TP(), oldAgg.ID(), join.TP(), join.ID())) + buffer.WriteString(fmt.Sprintf("and %v_%v %v path becomes %v_%v", join.TP(), join.ID(), func() string { if childIdx == 0 { return "left" } return "right" - }(), newAgg.ID())) + }(), newAgg.TP(), newAgg.ID())) return buffer.String() - }() + } opt.appendStepToCurrent(join.ID(), join.TP(), reason, action) } func appendAggPushDownAcrossProjTraceStep(agg *LogicalAggregation, proj *LogicalProjection, opt *logicalOptimizeOp) { action := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("proj[%v] is eliminated, and agg[%v]'s functions changed into[", proj.ID(), agg.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v is eliminated, and %v_%v's functions changed into[", proj.TP(), proj.ID(), agg.TP(), agg.ID())) for i, aggFunc := range agg.AggFuncs { if i > 0 { buffer.WriteString(",") @@ -551,33 +551,35 @@ func appendAggPushDownAcrossProjTraceStep(agg *LogicalAggregation, proj *Logical } buffer.WriteString("]") return buffer.String() - }() - reason := fmt.Sprintf("Proj[%v] is directly below an agg[%v] and has no side effects", proj.ID(), agg.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v is directly below an %v_%v and has no side effects", proj.TP(), proj.ID(), agg.TP(), agg.ID()) + } opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) } func appendAggPushDownAcrossUnionTraceStep(union *LogicalUnionAll, agg *LogicalAggregation, opt *logicalOptimizeOp) { reason := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v] functions[", agg.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v functions[", agg.TP(), agg.ID())) for i, aggFunc := range agg.AggFuncs { if i > 0 { buffer.WriteString(",") } buffer.WriteString(aggFunc.String()) } - buffer.WriteString("] are decomposable with union") + buffer.WriteString(fmt.Sprintf("] are decomposable with %v_%v", union.TP(), union.ID())) return buffer.String() - }() + } action := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v] pushed down, and union[%v]'s children changed into[", agg.ID(), union.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v pushed down, and %v_%v's children changed into[", agg.TP(), agg.ID(), union.TP(), union.ID())) for i, child := range union.Children() { if i > 0 { buffer.WriteString(",") } - buffer.WriteString(fmt.Sprintf("[id:%v,tp:%s]", child.ID(), child.TP())) + buffer.WriteString(fmt.Sprintf("%v_%v", child.TP(), child.ID())) } buffer.WriteString("]") return buffer.String() - }() + } opt.appendStepToCurrent(union.ID(), union.TP(), reason, action) } diff --git a/planner/core/rule_column_pruning.go b/planner/core/rule_column_pruning.go index 1d144c72807f9..98ca1e20190da 100644 --- a/planner/core/rule_column_pruning.go +++ b/planner/core/rule_column_pruning.go @@ -15,7 +15,9 @@ package core import ( + "bytes" "context" + "fmt" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" @@ -30,7 +32,7 @@ type columnPruner struct { } func (s *columnPruner) optimize(ctx context.Context, lp LogicalPlan, opt *logicalOptimizeOp) (LogicalPlan, error) { - err := lp.PruneColumns(lp.Schema().Columns) + err := lp.PruneColumns(lp.Schema().Columns, opt) return lp, err } @@ -63,32 +65,38 @@ func exprHasSetVarOrSleep(expr expression.Expression) bool { // PruneColumns implements LogicalPlan interface. // If any expression has SetVar function or Sleep function, we do not prune it. -func (p *LogicalProjection) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalProjection) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { child := p.children[0] used := expression.GetUsedList(parentUsedCols, p.schema) + prunedColumns := make([]*expression.Column, 0) for i := len(used) - 1; i >= 0; i-- { if !used[i] && !exprHasSetVarOrSleep(p.Exprs[i]) { + prunedColumns = append(prunedColumns, p.schema.Columns[i]) p.schema.Columns = append(p.schema.Columns[:i], p.schema.Columns[i+1:]...) p.Exprs = append(p.Exprs[:i], p.Exprs[i+1:]...) } } + appendColumnPruneTraceStep(p, prunedColumns, opt) selfUsedCols := make([]*expression.Column, 0, len(p.Exprs)) selfUsedCols = expression.ExtractColumnsFromExpressions(selfUsedCols, p.Exprs, nil) - return child.PruneColumns(selfUsedCols) + return child.PruneColumns(selfUsedCols, opt) } // PruneColumns implements LogicalPlan interface. -func (p *LogicalSelection) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalSelection) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { child := p.children[0] parentUsedCols = expression.ExtractColumnsFromExpressions(parentUsedCols, p.Conditions, nil) - return child.PruneColumns(parentUsedCols) + return child.PruneColumns(parentUsedCols, opt) } // PruneColumns implements LogicalPlan interface. -func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column) error { +func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { child := la.children[0] used := expression.GetUsedList(parentUsedCols, la.Schema()) + prunedColumns := make([]*expression.Column, 0) + prunedFunctions := make([]*aggregation.AggFuncDesc, 0) + prunedGroupByItems := make([]expression.Expression, 0) allFirstRow := true allRemainFirstRow := true @@ -97,18 +105,22 @@ func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column) allFirstRow = false } if !used[i] && !ExprsHasSideEffects(la.AggFuncs[i].Args) { + prunedColumns = append(prunedColumns, la.schema.Columns[i]) + prunedFunctions = append(prunedFunctions, la.AggFuncs[i]) la.schema.Columns = append(la.schema.Columns[:i], la.schema.Columns[i+1:]...) la.AggFuncs = append(la.AggFuncs[:i], la.AggFuncs[i+1:]...) } else if la.AggFuncs[i].Name != ast.AggFuncFirstRow { allRemainFirstRow = false } } + appendColumnPruneTraceStep(la, prunedColumns, opt) + appendFunctionPruneTraceStep(la, prunedFunctions, opt) var selfUsedCols []*expression.Column for _, aggrFunc := range la.AggFuncs { selfUsedCols = expression.ExtractColumnsFromExpressions(selfUsedCols, aggrFunc.Args, nil) var cols []*expression.Column - aggrFunc.OrderByItems, cols = pruneByItems(aggrFunc.OrderByItems) + aggrFunc.OrderByItems, cols = pruneByItems(la, aggrFunc.OrderByItems, opt) selfUsedCols = append(selfUsedCols, cols...) } if len(la.AggFuncs) == 0 || (!allFirstRow && allRemainFirstRow) { @@ -138,6 +150,7 @@ func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column) for i := len(la.GroupByItems) - 1; i >= 0; i-- { cols := expression.ExtractColumns(la.GroupByItems[i]) if len(cols) == 0 && !exprHasSetVarOrSleep(la.GroupByItems[i]) { + prunedGroupByItems = append(prunedGroupByItems, la.GroupByItems[i]) la.GroupByItems = append(la.GroupByItems[:i], la.GroupByItems[i+1:]...) } else { selfUsedCols = append(selfUsedCols, cols...) @@ -149,7 +162,8 @@ func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column) la.GroupByItems = []expression.Expression{expression.NewOne()} } } - err := child.PruneColumns(selfUsedCols) + appendGroupByItemsPruneTraceStep(la, prunedGroupByItems, opt) + err := child.PruneColumns(selfUsedCols, opt) if err != nil { return err } @@ -166,10 +180,13 @@ func (la *LogicalAggregation) PruneColumns(parentUsedCols []*expression.Column) return nil } -func pruneByItems(old []*util.ByItems) (new []*util.ByItems, parentUsedCols []*expression.Column) { - new = make([]*util.ByItems, 0, len(old)) +func pruneByItems(p LogicalPlan, old []*util.ByItems, opt *logicalOptimizeOp) (byItems []*util.ByItems, + parentUsedCols []*expression.Column) { + prunedByItems := make([]*util.ByItems, 0) + byItems = make([]*util.ByItems, 0, len(old)) seen := make(map[string]struct{}, len(old)) for _, byItem := range old { + pruned := true hash := string(byItem.Expr.HashCode(nil)) _, hashMatch := seen[hash] seen[hash] = struct{}{} @@ -178,42 +195,48 @@ func pruneByItems(old []*util.ByItems) (new []*util.ByItems, parentUsedCols []*e // do nothing, should be filtered } else if len(cols) == 0 { if !expression.IsRuntimeConstExpr(byItem.Expr) { - new = append(new, byItem) + pruned = false + byItems = append(byItems, byItem) } } else if byItem.Expr.GetType().Tp == mysql.TypeNull { // do nothing, should be filtered } else { + pruned = false parentUsedCols = append(parentUsedCols, cols...) - new = append(new, byItem) + byItems = append(byItems, byItem) + } + if pruned { + prunedByItems = append(prunedByItems, byItem) } } + appendByItemsPruneTraceStep(p, prunedByItems, opt) return } // PruneColumns implements LogicalPlan interface. // If any expression can view as a constant in execution stage, such as correlated column, constant, // we do prune them. Note that we can't prune the expressions contain non-deterministic functions, such as rand(). -func (ls *LogicalSort) PruneColumns(parentUsedCols []*expression.Column) error { +func (ls *LogicalSort) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { child := ls.children[0] var cols []*expression.Column - ls.ByItems, cols = pruneByItems(ls.ByItems) + ls.ByItems, cols = pruneByItems(ls, ls.ByItems, opt) parentUsedCols = append(parentUsedCols, cols...) - return child.PruneColumns(parentUsedCols) + return child.PruneColumns(parentUsedCols, opt) } // PruneColumns implements LogicalPlan interface. // If any expression can view as a constant in execution stage, such as correlated column, constant, // we do prune them. Note that we can't prune the expressions contain non-deterministic functions, such as rand(). -func (lt *LogicalTopN) PruneColumns(parentUsedCols []*expression.Column) error { +func (lt *LogicalTopN) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { child := lt.children[0] var cols []*expression.Column - lt.ByItems, cols = pruneByItems(lt.ByItems) + lt.ByItems, cols = pruneByItems(lt, lt.ByItems, opt) parentUsedCols = append(parentUsedCols, cols...) - return child.PruneColumns(parentUsedCols) + return child.PruneColumns(parentUsedCols, opt) } // PruneColumns implements LogicalPlan interface. -func (p *LogicalUnionAll) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalUnionAll) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { used := expression.GetUsedList(parentUsedCols, p.schema) hasBeenUsed := false for i := range used { @@ -227,20 +250,23 @@ func (p *LogicalUnionAll) PruneColumns(parentUsedCols []*expression.Column) erro copy(parentUsedCols, p.schema.Columns) } for _, child := range p.Children() { - err := child.PruneColumns(parentUsedCols) + err := child.PruneColumns(parentUsedCols, opt) if err != nil { return err } } + prunedColumns := make([]*expression.Column, 0) if hasBeenUsed { // keep the schema of LogicalUnionAll same as its children's used := expression.GetUsedList(p.children[0].Schema().Columns, p.schema) for i := len(used) - 1; i >= 0; i-- { if !used[i] { + prunedColumns = append(prunedColumns, p.schema.Columns[i]) p.schema.Columns = append(p.schema.Columns[:i], p.schema.Columns[i+1:]...) } } + appendColumnPruneTraceStep(p, prunedColumns, opt) // It's possible that the child operator adds extra columns to the schema. // Currently, (*LogicalAggregation).PruneColumns() might do this. // But we don't need such columns, so we add an extra Projection to prune this column when this happened. @@ -263,30 +289,44 @@ func (p *LogicalUnionAll) PruneColumns(parentUsedCols []*expression.Column) erro } // PruneColumns implements LogicalPlan interface. -func (p *LogicalUnionScan) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalUnionScan) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { for i := 0; i < p.handleCols.NumCols(); i++ { parentUsedCols = append(parentUsedCols, p.handleCols.GetCol(i)) } + for _, col := range p.Schema().Columns { + if col.ID == model.ExtraPidColID || col.ID == model.ExtraPhysTblID { + parentUsedCols = append(parentUsedCols, col) + } + } condCols := expression.ExtractColumnsFromExpressions(nil, p.conditions, nil) parentUsedCols = append(parentUsedCols, condCols...) - return p.children[0].PruneColumns(parentUsedCols) + return p.children[0].PruneColumns(parentUsedCols, opt) } // PruneColumns implements LogicalPlan interface. -func (ds *DataSource) PruneColumns(parentUsedCols []*expression.Column) error { +func (ds *DataSource) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { used := expression.GetUsedList(parentUsedCols, ds.schema) exprCols := expression.ExtractColumnsFromExpressions(nil, ds.allConds, nil) exprUsed := expression.GetUsedList(exprCols, ds.schema) + prunedColumns := make([]*expression.Column, 0) originSchemaColumns := ds.schema.Columns originColumns := ds.Columns for i := len(used) - 1; i >= 0; i-- { if !used[i] && !exprUsed[i] { + // If ds has a shard index, and the column is generated column by `tidb_shard()` + // it can't prune the generated column of shard index + if ds.containExprPrefixUk && + expression.GcColumnExprIsTidbShard(ds.schema.Columns[i].VirtualExpr) { + continue + } + prunedColumns = append(prunedColumns, ds.schema.Columns[i]) ds.schema.Columns = append(ds.schema.Columns[:i], ds.schema.Columns[i+1:]...) ds.Columns = append(ds.Columns[:i], ds.Columns[i+1:]...) } } + appendColumnPruneTraceStep(ds, prunedColumns, opt) // For SQL like `select 1 from t`, tikv's response will be empty if no column is in schema. // So we'll force to push one if schema doesn't have any column. if ds.schema.Len() == 0 { @@ -315,7 +355,7 @@ func (ds *DataSource) PruneColumns(parentUsedCols []*expression.Column) error { } // PruneColumns implements LogicalPlan interface. -func (p *LogicalMemTable) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalMemTable) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { switch p.TableInfo.Name.O { case infoschema.TableStatementsSummary, infoschema.TableStatementsSummaryHistory, @@ -331,26 +371,31 @@ func (p *LogicalMemTable) PruneColumns(parentUsedCols []*expression.Column) erro default: return nil } + prunedColumns := make([]*expression.Column, 0) used := expression.GetUsedList(parentUsedCols, p.schema) for i := len(used) - 1; i >= 0; i-- { if !used[i] && p.schema.Len() > 1 { + prunedColumns = append(prunedColumns, p.schema.Columns[i]) p.schema.Columns = append(p.schema.Columns[:i], p.schema.Columns[i+1:]...) p.names = append(p.names[:i], p.names[i+1:]...) p.Columns = append(p.Columns[:i], p.Columns[i+1:]...) } } + appendColumnPruneTraceStep(p, prunedColumns, opt) return nil } // PruneColumns implements LogicalPlan interface. -func (p *LogicalTableDual) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalTableDual) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { used := expression.GetUsedList(parentUsedCols, p.Schema()) - + prunedColumns := make([]*expression.Column, 0) for i := len(used) - 1; i >= 0; i-- { if !used[i] { + prunedColumns = append(prunedColumns, p.schema.Columns[i]) p.schema.Columns = append(p.schema.Columns[:i], p.schema.Columns[i+1:]...) } } + appendColumnPruneTraceStep(p, prunedColumns, opt) return nil } @@ -384,16 +429,16 @@ func (p *LogicalJoin) mergeSchema() { } // PruneColumns implements LogicalPlan interface. -func (p *LogicalJoin) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalJoin) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { leftCols, rightCols := p.extractUsedCols(parentUsedCols) - err := p.children[0].PruneColumns(leftCols) + err := p.children[0].PruneColumns(leftCols, opt) if err != nil { return err } addConstOneForEmptyProjection(p.children[0]) - err = p.children[1].PruneColumns(rightCols) + err = p.children[1].PruneColumns(rightCols, opt) if err != nil { return err } @@ -404,15 +449,15 @@ func (p *LogicalJoin) PruneColumns(parentUsedCols []*expression.Column) error { joinCol := p.schema.Columns[len(p.schema.Columns)-1] parentUsedCols = append(parentUsedCols, joinCol) } - p.inlineProjection(parentUsedCols) + p.inlineProjection(parentUsedCols, opt) return nil } // PruneColumns implements LogicalPlan interface. -func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column) error { +func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { leftCols, rightCols := la.extractUsedCols(parentUsedCols) - err := la.children[1].PruneColumns(rightCols) + err := la.children[1].PruneColumns(rightCols, opt) if err != nil { return err } @@ -423,7 +468,7 @@ func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column) error leftCols = append(leftCols, &col.Column) } - err = la.children[0].PruneColumns(leftCols) + err = la.children[0].PruneColumns(leftCols, opt) if err != nil { return err } @@ -434,28 +479,27 @@ func (la *LogicalApply) PruneColumns(parentUsedCols []*expression.Column) error } // PruneColumns implements LogicalPlan interface. -func (p *LogicalLock) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalLock) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { if !IsSelectForUpdateLockType(p.Lock.LockType) { - return p.baseLogicalPlan.PruneColumns(parentUsedCols) + return p.baseLogicalPlan.PruneColumns(parentUsedCols, opt) } - if len(p.partitionedTable) > 0 { - // If the children include partitioned tables, there is an extra partition ID column. - parentUsedCols = append(parentUsedCols, p.extraPIDInfo.Columns...) - } - - for _, cols := range p.tblID2Handle { + for tblID, cols := range p.tblID2Handle { for _, col := range cols { for i := 0; i < col.NumCols(); i++ { parentUsedCols = append(parentUsedCols, col.GetCol(i)) } } + if physTblIDCol, ok := p.tblID2PhysTblIDCol[tblID]; ok { + // If the children include partitioned tables, there is an extra partition ID column. + parentUsedCols = append(parentUsedCols, physTblIDCol) + } } - return p.children[0].PruneColumns(parentUsedCols) + return p.children[0].PruneColumns(parentUsedCols, opt) } // PruneColumns implements LogicalPlan interface. -func (p *LogicalWindow) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalWindow) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { windowColumns := p.GetWindowResultColumns() cnt := 0 for _, col := range parentUsedCols { @@ -473,7 +517,7 @@ func (p *LogicalWindow) PruneColumns(parentUsedCols []*expression.Column) error } parentUsedCols = parentUsedCols[:cnt] parentUsedCols = p.extractUsedCols(parentUsedCols) - err := p.children[0].PruneColumns(parentUsedCols) + err := p.children[0].PruneColumns(parentUsedCols, opt) if err != nil { return err } @@ -499,18 +543,18 @@ func (p *LogicalWindow) extractUsedCols(parentUsedCols []*expression.Column) []* } // PruneColumns implements LogicalPlan interface. -func (p *LogicalLimit) PruneColumns(parentUsedCols []*expression.Column) error { +func (p *LogicalLimit) PruneColumns(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) error { if len(parentUsedCols) == 0 { // happens when LIMIT appears in UPDATE. return nil } savedUsedCols := make([]*expression.Column, len(parentUsedCols)) copy(savedUsedCols, parentUsedCols) - if err := p.children[0].PruneColumns(parentUsedCols); err != nil { + if err := p.children[0].PruneColumns(parentUsedCols, opt); err != nil { return err } p.schema = nil - p.inlineProjection(savedUsedCols) + p.inlineProjection(savedUsedCols, opt) return nil } @@ -539,3 +583,68 @@ func addConstOneForEmptyProjection(p LogicalPlan) { RetType: constOne.GetType(), }) } + +func appendColumnPruneTraceStep(p LogicalPlan, prunedColumns []*expression.Column, opt *logicalOptimizeOp) { + if len(prunedColumns) < 1 { + return + } + s := make([]fmt.Stringer, 0, len(prunedColumns)) + for _, item := range prunedColumns { + s = append(s, item) + } + appendItemPruneTraceStep(p, "columns", s, opt) +} + +func appendFunctionPruneTraceStep(p LogicalPlan, prunedFunctions []*aggregation.AggFuncDesc, opt *logicalOptimizeOp) { + if len(prunedFunctions) < 1 { + return + } + s := make([]fmt.Stringer, 0, len(prunedFunctions)) + for _, item := range prunedFunctions { + s = append(s, item) + } + appendItemPruneTraceStep(p, "aggregation functions", s, opt) +} + +func appendByItemsPruneTraceStep(p LogicalPlan, prunedByItems []*util.ByItems, opt *logicalOptimizeOp) { + if len(prunedByItems) < 1 { + return + } + s := make([]fmt.Stringer, 0, len(prunedByItems)) + for _, item := range prunedByItems { + s = append(s, item) + } + appendItemPruneTraceStep(p, "byItems", s, opt) +} + +func appendGroupByItemsPruneTraceStep(p LogicalPlan, prunedGroupByItems []expression.Expression, opt *logicalOptimizeOp) { + if len(prunedGroupByItems) < 1 { + return + } + s := make([]fmt.Stringer, 0, len(prunedGroupByItems)) + for _, item := range prunedGroupByItems { + s = append(s, item) + } + appendItemPruneTraceStep(p, "groupByItems", s, opt) +} + +func appendItemPruneTraceStep(p LogicalPlan, itemType string, prunedObjects []fmt.Stringer, opt *logicalOptimizeOp) { + if len(prunedObjects) < 1 { + return + } + action := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v's %v[", p.TP(), p.ID(), itemType)) + for i, item := range prunedObjects { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(item.String()) + } + buffer.WriteString("] have been pruned") + return buffer.String() + } + reason := func() string { + return "" + } + opt.appendStepToCurrent(p.ID(), p.TP(), reason, action) +} diff --git a/planner/core/rule_decorrelate.go b/planner/core/rule_decorrelate.go index a8835d57448b9..e8a80f722f055 100644 --- a/planner/core/rule_decorrelate.go +++ b/planner/core/rule_decorrelate.go @@ -15,7 +15,9 @@ package core import ( + "bytes" "context" + "fmt" "math" "github.com/pingcap/tidb/expression" @@ -23,6 +25,7 @@ import ( "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/plancodec" ) // canPullUpAgg checks if an apply can pull an aggregation up. @@ -128,7 +131,9 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo // If the inner plan is non-correlated, the apply will be simplified to join. join := &apply.LogicalJoin join.self = join + join.tp = plancodec.TypeJoin p = join + appendApplySimplifiedTraceStep(apply, join, opt) } else if sel, ok := innerPlan.(*LogicalSelection); ok { // If the inner plan is a selection, we add this condition to join predicates. // Notice that no matter what kind of join is, it's always right. @@ -139,14 +144,31 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo apply.AttachOnConds(newConds) innerPlan = sel.children[0] apply.SetChildren(outerPlan, innerPlan) + appendRemoveSelectionTraceStep(apply, sel, opt) return s.optimize(ctx, p, opt) } else if m, ok := innerPlan.(*LogicalMaxOneRow); ok { if m.children[0].MaxOneRow() { innerPlan = m.children[0] apply.SetChildren(outerPlan, innerPlan) + appendRemoveMaxOneRowTraceStep(m, opt) return s.optimize(ctx, p, opt) } } else if proj, ok := innerPlan.(*LogicalProjection); ok { + allConst := true + for _, expr := range proj.Exprs { + if len(expression.ExtractCorColumns(expr)) > 0 || !expression.ExtractColumnSet(expr).IsEmpty() { + allConst = false + break + } + } + if allConst && apply.JoinType == LeftOuterJoin { + // If the projection just references some constant. We cannot directly pull it up when the APPLY is an outer join. + // e.g. select (select 1 from t1 where t1.a=t2.a) from t2; When the t1.a=t2.a is false the join's output is NULL. + // But if we pull the projection upon the APPLY. It will return 1 since the projection is evaluated after the join. + // We disable the decorrelation directly for now. + // TODO: Actually, it can be optimized. We need to first push the projection down to the selection. And then the APPLY can be decorrelated. + goto NoOptimize + } for i, expr := range proj.Exprs { proj.Exprs[i] = expr.Decorrelate(outerPlan.Schema()) } @@ -162,8 +184,10 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo return nil, err } proj.SetChildren(np) + appendMoveProjTraceStep(apply, np, proj, opt) return proj, nil } + appendRemoveProjTraceStep(apply, proj, opt) return s.optimize(ctx, p, opt) } else if agg, ok := innerPlan.(*LogicalAggregation); ok { if apply.canPullUpAgg() && agg.canPullUp() { @@ -188,7 +212,6 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo } apply.SetSchema(expression.MergeSchema(expression.NewSchema(outerColsInSchema...), innerPlan.Schema())) resetNotNullFlag(apply.schema, outerPlan.Schema().Len(), apply.schema.Len()) - for i, aggFunc := range agg.AggFuncs { aggArgs := make([]expression.Expression, 0, len(aggFunc.Args)) for _, arg := range aggFunc.Args { @@ -219,6 +242,7 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo return nil, err } agg.SetChildren(np) + appendPullUpAggTraceStep(apply, np, agg, opt) // TODO: Add a Projection if any argument of aggregate funcs or group by items are scalar functions. // agg.buildProjectionIfNecessary() return agg, nil @@ -245,6 +269,9 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo // There's no other correlated column. groupByCols := expression.NewSchema(agg.GetGroupByCols()...) if len(apply.CorCols) == 0 { + appendedGroupByCols := expression.NewSchema() + var appendedAggFuncs []*aggregation.AggFuncDesc + join := &apply.LogicalJoin join.EqualConditions = append(join.EqualConditions, eqCondWithCorCol...) for _, eqCond := range eqCondWithCorCol { @@ -258,16 +285,19 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo agg.AggFuncs = append(agg.AggFuncs, newFunc) agg.schema.Append(clonedCol) agg.schema.Columns[agg.schema.Len()-1].RetType = newFunc.RetTp + appendedAggFuncs = append(appendedAggFuncs, newFunc) } // If group by cols don't contain the join key, add it into this. if !groupByCols.Contains(clonedCol) { agg.GroupByItems = append(agg.GroupByItems, clonedCol) groupByCols.Append(clonedCol) + appendedGroupByCols.Append(clonedCol) } } // The selection may be useless, check and remove it. if len(sel.Conditions) == 0 { agg.SetChildren(sel.children[0]) + appendRemoveSelectionTraceStep(agg, sel, opt) } defaultValueMap := s.aggDefaultValueMap(agg) // We should use it directly, rather than building a projection. @@ -282,7 +312,9 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo } proj.SetChildren(apply) p = proj + appendAddProjTraceStep(apply, proj, opt) } + appendModifyAggTraceStep(outerPlan, apply, agg, sel, appendedGroupByCols, appendedAggFuncs, eqCondWithCorCol, opt) return s.optimize(ctx, p, opt) } sel.Conditions = originalExpr @@ -294,9 +326,11 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo // the top level Sort has no effect on the subquery's result. innerPlan = sort.children[0] apply.SetChildren(outerPlan, innerPlan) + appendRemoveSortTraceStep(sort, opt) return s.optimize(ctx, p, opt) } } +NoOptimize: newChildren := make([]LogicalPlan, 0, len(p.Children())) for _, child := range p.Children() { np, err := s.optimize(ctx, child, opt) @@ -312,3 +346,128 @@ func (s *decorrelateSolver) optimize(ctx context.Context, p LogicalPlan, opt *lo func (*decorrelateSolver) name() string { return "decorrelate" } + +func appendApplySimplifiedTraceStep(p *LogicalApply, j *LogicalJoin, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v simplified into %v_%v", plancodec.TypeApply, p.ID(), plancodec.TypeJoin, j.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v hasn't any corelated column, thus the inner plan is non-correlated", p.TP(), p.ID()) + } + opt.appendStepToCurrent(p.ID(), p.TP(), reason, action) +} + +func appendRemoveSelectionTraceStep(p LogicalPlan, s *LogicalSelection, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v removed from plan tree", s.TP(), s.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v's conditions have been pushed into %v_%v", s.TP(), s.ID(), p.TP(), p.ID()) + } + opt.appendStepToCurrent(s.ID(), s.TP(), reason, action) +} + +func appendRemoveMaxOneRowTraceStep(m *LogicalMaxOneRow, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v removed from plan tree", m.TP(), m.ID()) + } + reason := func() string { + return "" + } + opt.appendStepToCurrent(m.ID(), m.TP(), reason, action) +} + +func appendRemoveProjTraceStep(p *LogicalApply, proj *LogicalProjection, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v removed from plan tree", proj.TP(), proj.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v's columns all substituted into %v_%v", proj.TP(), proj.ID(), p.TP(), p.ID()) + } + opt.appendStepToCurrent(proj.ID(), proj.TP(), reason, action) +} + +func appendMoveProjTraceStep(p *LogicalApply, np LogicalPlan, proj *LogicalProjection, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v is moved as %v_%v's parent", proj.TP(), proj.ID(), np.TP(), np.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v's join type is %v, not semi join", p.TP(), p.ID(), p.JoinType.String()) + } + opt.appendStepToCurrent(proj.ID(), proj.TP(), reason, action) +} + +func appendRemoveSortTraceStep(sort *LogicalSort, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v removed from plan tree", sort.TP(), sort.ID()) + } + reason := func() string { + return "" + } + opt.appendStepToCurrent(sort.ID(), sort.TP(), reason, action) +} + +func appendPullUpAggTraceStep(p *LogicalApply, np LogicalPlan, agg *LogicalAggregation, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v pulled up as %v_%v's parent, and %v_%v's join type becomes %v", + agg.TP(), agg.ID(), np.TP(), np.ID(), p.TP(), p.ID(), p.JoinType.String()) + } + reason := func() string { + return fmt.Sprintf("%v_%v's functions haven't any group by items and %v_%v's join type isn't %v or %v, and hasn't any conditions", + agg.TP(), agg.ID(), p.TP(), p.ID(), InnerJoin.String(), LeftOuterJoin.String()) + } + opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) +} + +func appendAddProjTraceStep(p *LogicalApply, proj *LogicalProjection, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v is added as %v_%v's parent", proj.TP(), proj.ID(), p.TP(), p.ID()) + } + reason := func() string { + return "" + } + opt.appendStepToCurrent(proj.ID(), proj.TP(), reason, action) +} + +func appendModifyAggTraceStep(outerPlan LogicalPlan, p *LogicalApply, agg *LogicalAggregation, sel *LogicalSelection, + appendedGroupByCols *expression.Schema, appendedAggFuncs []*aggregation.AggFuncDesc, + eqCondWithCorCol []*expression.ScalarFunction, opt *logicalOptimizeOp) { + action := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v's groupby items added [", agg.TP(), agg.ID())) + for i, col := range appendedGroupByCols.Columns { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(col.String()) + } + buffer.WriteString("], and functions added [") + for i, f := range appendedAggFuncs { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(f.String()) + } + buffer.WriteString(fmt.Sprintf("], and %v_%v's conditions added [", p.TP(), p.ID())) + for i, cond := range eqCondWithCorCol { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(cond.String()) + } + buffer.WriteString("]") + return buffer.String() + } + reason := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v's equal conditions [", sel.TP(), sel.ID())) + for i, cond := range eqCondWithCorCol { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(cond.String()) + } + buffer.WriteString(fmt.Sprintf("] are correlated to %v_%v and pulled up as %v_%v's join key", + outerPlan.TP(), outerPlan.ID(), p.TP(), p.ID())) + return buffer.String() + } + opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) +} diff --git a/planner/core/rule_eliminate_projection.go b/planner/core/rule_eliminate_projection.go index 0c377bd974703..0daaf4616185a 100644 --- a/planner/core/rule_eliminate_projection.go +++ b/planner/core/rule_eliminate_projection.go @@ -300,7 +300,7 @@ func (*projectionEliminator) name() string { func appendDupProjEliminateTraceStep(parent, child *LogicalProjection, opt *logicalOptimizeOp) { action := func() string { buffer := bytes.NewBufferString( - fmt.Sprintf("Proj[%v] is eliminated, Proj[%v]'s expressions changed into[", child.ID(), parent.ID())) + fmt.Sprintf("%v_%v is eliminated, %v_%v's expressions changed into[", child.TP(), child.ID(), parent.TP(), parent.ID())) for i, expr := range parent.Exprs { if i > 0 { buffer.WriteString(",") @@ -309,13 +309,19 @@ func appendDupProjEliminateTraceStep(parent, child *LogicalProjection, opt *logi } buffer.WriteString("]") return buffer.String() - }() - reason := fmt.Sprintf("Proj[%v]'s child proj[%v] is redundant", parent.ID(), child.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v's child %v_%v is redundant", parent.TP(), parent.ID(), child.TP(), child.ID()) + } opt.appendStepToCurrent(child.ID(), child.TP(), reason, action) } func appendProjEliminateTraceStep(proj *LogicalProjection, opt *logicalOptimizeOp) { - reason := fmt.Sprintf("Proj[%v]'s Exprs are all Columns", proj.ID()) - action := fmt.Sprintf("Proj[%v] is eliminated", proj.ID()) + reason := func() string { + return fmt.Sprintf("%v_%v's Exprs are all Columns", proj.TP(), proj.ID()) + } + action := func() string { + return fmt.Sprintf("%v_%v is eliminated", proj.TP(), proj.ID()) + } opt.appendStepToCurrent(proj.ID(), proj.TP(), reason, action) } diff --git a/planner/core/rule_inject_extra_projection_test.go b/planner/core/rule_inject_extra_projection_test.go index 6bbfc544638ff..58b00f0113848 100644 --- a/planner/core/rule_inject_extra_projection_test.go +++ b/planner/core/rule_inject_extra_projection_test.go @@ -15,21 +15,18 @@ package core import ( - . "github.com/pingcap/check" + "testing" + "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testInjectProjSuite{}) - -type testInjectProjSuite struct { -} - -func (s *testInjectProjSuite) TestWrapCastForAggFuncs(c *C) { +func TestWrapCastForAggFuncs(t *testing.T) { aggNames := []string{ast.AggFuncSum} modes := []aggregation.AggFunctionMode{aggregation.CompleteMode, aggregation.FinalMode, aggregation.Partial1Mode, aggregation.Partial1Mode} @@ -45,7 +42,7 @@ func (s *testInjectProjSuite) TestWrapCastForAggFuncs(c *C) { aggFunc, err := aggregation.NewAggFuncDesc(sctx, name, []expression.Expression{&expression.Constant{Value: types.Datum{}, RetType: types.NewFieldType(retType)}}, hasDistinct) - c.Assert(err, IsNil) + require.NoError(t, err) aggFunc.Mode = mode aggFuncs = append(aggFuncs, aggFunc) } @@ -61,9 +58,9 @@ func (s *testInjectProjSuite) TestWrapCastForAggFuncs(c *C) { wrapCastForAggFuncs(mock.NewContext(), aggFuncs) for i := range aggFuncs { if aggFuncs[i].Mode != aggregation.FinalMode && aggFuncs[i].Mode != aggregation.Partial2Mode { - c.Assert(aggFuncs[i].RetTp.Tp, Equals, aggFuncs[i].Args[0].GetType().Tp) + require.Equal(t, aggFuncs[i].Args[0].GetType().Tp, aggFuncs[i].RetTp.Tp) } else { - c.Assert(aggFuncs[i].Args[0].GetType().Tp, Equals, orgAggFuncs[i].Args[0].GetType().Tp) + require.Equal(t, orgAggFuncs[i].Args[0].GetType().Tp, aggFuncs[i].Args[0].GetType().Tp) } } } diff --git a/planner/core/rule_join_elimination.go b/planner/core/rule_join_elimination.go index 6d4a750ea4356..c7ed935b8dc99 100644 --- a/planner/core/rule_join_elimination.go +++ b/planner/core/rule_join_elimination.go @@ -258,8 +258,10 @@ func appendOuterJoinEliminateTraceStep(join *LogicalJoin, outerPlan LogicalPlan, } buffer.WriteString("] are unique") return buffer.String() - }() - action := fmt.Sprintf("Outer join[%v] is eliminated and become %v[%v]", join.ID(), outerPlan.TP(), outerPlan.ID()) + } + action := func() string { + return fmt.Sprintf("Outer %v_%v is eliminated and become %v_%v", join.TP(), join.ID(), outerPlan.TP(), outerPlan.ID()) + } opt.appendStepToCurrent(join.ID(), join.TP(), reason, action) } @@ -274,7 +276,9 @@ func appendOuterJoinEliminateAggregationTraceStep(join *LogicalJoin, outerPlan L } buffer.WriteString("] in agg are from outer table, and the agg functions are duplicate agnostic") return buffer.String() - }() - action := fmt.Sprintf("Outer join[%v] is eliminated and become %v[%v]", join.ID(), outerPlan.TP(), outerPlan.ID()) + } + action := func() string { + return fmt.Sprintf("Outer %v_%v is eliminated and become %v_%v", join.TP(), join.ID(), outerPlan.TP(), outerPlan.ID()) + } opt.appendStepToCurrent(join.ID(), join.TP(), reason, action) } diff --git a/planner/core/rule_join_reorder.go b/planner/core/rule_join_reorder.go index dd29f7d3f1f30..3f2065650ff33 100644 --- a/planner/core/rule_join_reorder.go +++ b/planner/core/rule_join_reorder.go @@ -209,7 +209,9 @@ func appendJoinReorderTraceStep(tracer *joinReorderTrace, plan LogicalPlan, opt if len(tracer.initial) < 1 || len(tracer.final) < 1 { return } - action := fmt.Sprintf("join order becomes %v from original %v", tracer.final, tracer.initial) + action := func() string { + return fmt.Sprintf("join order becomes %v from original %v", tracer.final, tracer.initial) + } reason := func() string { buffer := bytes.NewBufferString("join cost during reorder: [") var joins []string @@ -225,11 +227,11 @@ func appendJoinReorderTraceStep(tracer *joinReorderTrace, plan LogicalPlan, opt } buffer.WriteString("]") return buffer.String() - }() + } opt.appendStepToCurrent(plan.ID(), plan.TP(), reason, action) } -func allJoinOrderToString(tt []*tracing.LogicalPlanTrace) string { +func allJoinOrderToString(tt []*tracing.PlanTrace) string { if len(tt) == 1 { return joinOrderToString(tt[0]) } @@ -245,7 +247,7 @@ func allJoinOrderToString(tt []*tracing.LogicalPlanTrace) string { } // joinOrderToString let Join(DataSource, DataSource) become '(t1*t2)' -func joinOrderToString(t *tracing.LogicalPlanTrace) string { +func joinOrderToString(t *tracing.PlanTrace) string { if t.TP == plancodec.TypeJoin { buffer := bytes.NewBufferString("(") for i, child := range t.Children { @@ -264,12 +266,12 @@ func joinOrderToString(t *tracing.LogicalPlanTrace) string { // extractJoinAndDataSource will only keep join and dataSource operator and remove other operators. // For example: Proj->Join->(Proj->DataSource, DataSource) will become Join->(DataSource, DataSource) -func extractJoinAndDataSource(t *tracing.LogicalPlanTrace) []*tracing.LogicalPlanTrace { +func extractJoinAndDataSource(t *tracing.PlanTrace) []*tracing.PlanTrace { roots := findRoots(t) if len(roots) < 1 { return nil } - var rr []*tracing.LogicalPlanTrace + rr := make([]*tracing.PlanTrace, 0, len(roots)) for _, root := range roots { simplify(root) rr = append(rr, root) @@ -278,13 +280,13 @@ func extractJoinAndDataSource(t *tracing.LogicalPlanTrace) []*tracing.LogicalPla } // simplify only keeps Join and DataSource operators, and discard other operators. -func simplify(node *tracing.LogicalPlanTrace) { +func simplify(node *tracing.PlanTrace) { if len(node.Children) < 1 { return } for valid := false; !valid; { valid = true - newChildren := make([]*tracing.LogicalPlanTrace, 0) + newChildren := make([]*tracing.PlanTrace, 0) for _, child := range node.Children { if child.TP != plancodec.TypeDataSource && child.TP != plancodec.TypeJoin { newChildren = append(newChildren, child.Children...) @@ -300,11 +302,11 @@ func simplify(node *tracing.LogicalPlanTrace) { } } -func findRoots(t *tracing.LogicalPlanTrace) []*tracing.LogicalPlanTrace { +func findRoots(t *tracing.PlanTrace) []*tracing.PlanTrace { if t.TP == plancodec.TypeJoin || t.TP == plancodec.TypeDataSource { - return []*tracing.LogicalPlanTrace{t} + return []*tracing.PlanTrace{t} } - var r []*tracing.LogicalPlanTrace + var r []*tracing.PlanTrace for _, child := range t.Children { r = append(r, findRoots(child)...) } @@ -323,16 +325,16 @@ func (t *joinReorderTrace) traceJoinReorder(p LogicalPlan) { return } if len(t.initial) > 0 { - t.final = allJoinOrderToString(extractJoinAndDataSource(p.buildLogicalPlanTrace(p))) + t.final = allJoinOrderToString(extractJoinAndDataSource(p.buildPlanTrace())) return } - t.initial = allJoinOrderToString(extractJoinAndDataSource(p.buildLogicalPlanTrace(p))) + t.initial = allJoinOrderToString(extractJoinAndDataSource(p.buildPlanTrace())) } func (t *joinReorderTrace) appendLogicalJoinCost(join LogicalPlan, cost float64) { if t == nil || t.opt == nil || t.opt.tracer == nil { return } - joinMapKey := allJoinOrderToString(extractJoinAndDataSource(join.buildLogicalPlanTrace(join))) + joinMapKey := allJoinOrderToString(extractJoinAndDataSource(join.buildPlanTrace())) t.cost[joinMapKey] = cost } diff --git a/planner/core/rule_join_reorder_dp.go b/planner/core/rule_join_reorder_dp.go index d5db965667258..459755de2e2ec 100644 --- a/planner/core/rule_join_reorder_dp.go +++ b/planner/core/rule_join_reorder_dp.go @@ -211,7 +211,7 @@ func (s *joinReorderDPSolver) dpGraph(visitID2NodeID, nodeID2VisitID []int, join func (s *joinReorderDPSolver) nodesAreConnected(leftMask, rightMask uint, oldPos2NewPos []int, totalEqEdges []joinGroupEqEdge, totalNonEqEdges []joinGroupNonEqEdge) ([]joinGroupEqEdge, []expression.Expression) { - var ( + var ( // nolint: prealloc usedEqEdges []joinGroupEqEdge otherConds []expression.Expression ) diff --git a/planner/core/rule_join_reorder_dp_test.go b/planner/core/rule_join_reorder_dp_test.go index 5d674dca9e66a..ed41d55c43520 100644 --- a/planner/core/rule_join_reorder_dp_test.go +++ b/planner/core/rule_join_reorder_dp_test.go @@ -16,8 +16,8 @@ package core import ( "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" @@ -25,20 +25,9 @@ import ( "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testJoinReorderDPSuite{}) - -type testJoinReorderDPSuite struct { - ctx sessionctx.Context - statsMap map[int]*property.StatsInfo -} - -func (s *testJoinReorderDPSuite) SetUpTest(c *C) { - s.ctx = MockContext() - s.ctx.GetSessionVars().PlanID = -1 -} - type mockLogicalJoin struct { logicalSchemaProducer involvedNodeSet int @@ -57,31 +46,27 @@ func (mj *mockLogicalJoin) recursiveDeriveStats(_ [][]*expression.Column) (*prop return mj.statsMap[mj.involvedNodeSet], nil } -func (s *testJoinReorderDPSuite) newMockJoin(lChild, rChild LogicalPlan, eqConds []*expression.ScalarFunction, _ []expression.Expression) LogicalPlan { - retJoin := mockLogicalJoin{}.init(s.ctx) - retJoin.schema = expression.MergeSchema(lChild.Schema(), rChild.Schema()) - retJoin.statsMap = s.statsMap - if mj, ok := lChild.(*mockLogicalJoin); ok { - retJoin.involvedNodeSet = mj.involvedNodeSet - } else { - retJoin.involvedNodeSet = 1 << uint(lChild.ID()) - } - if mj, ok := rChild.(*mockLogicalJoin); ok { - retJoin.involvedNodeSet |= mj.involvedNodeSet - } else { - retJoin.involvedNodeSet |= 1 << uint(rChild.ID()) - } - retJoin.SetChildren(lChild, rChild) - return retJoin -} - -func (s *testJoinReorderDPSuite) mockStatsInfo(state int, count float64) { - s.statsMap[state] = &property.StatsInfo{ - RowCount: count, +func newMockJoin(ctx sessionctx.Context, statsMap map[int]*property.StatsInfo) func(lChild, rChild LogicalPlan, _ []*expression.ScalarFunction, _ []expression.Expression) LogicalPlan { + return func(lChild, rChild LogicalPlan, _ []*expression.ScalarFunction, _ []expression.Expression) LogicalPlan { + retJoin := mockLogicalJoin{}.init(ctx) + retJoin.schema = expression.MergeSchema(lChild.Schema(), rChild.Schema()) + retJoin.statsMap = statsMap + if mj, ok := lChild.(*mockLogicalJoin); ok { + retJoin.involvedNodeSet = mj.involvedNodeSet + } else { + retJoin.involvedNodeSet = 1 << uint(lChild.ID()) + } + if mj, ok := rChild.(*mockLogicalJoin); ok { + retJoin.involvedNodeSet |= mj.involvedNodeSet + } else { + retJoin.involvedNodeSet |= 1 << uint(rChild.ID()) + } + retJoin.SetChildren(lChild, rChild) + return retJoin } } -func (s *testJoinReorderDPSuite) makeStatsMapForTPCHQ5() { +func makeStatsMapForTPCHQ5() map[int]*property.StatsInfo { // Labeled as lineitem -> 0, orders -> 1, customer -> 2, supplier 3, nation 4, region 5 // This graph can be shown as following: // +---------------+ +---------------+ @@ -112,48 +97,48 @@ func (s *testJoinReorderDPSuite) makeStatsMapForTPCHQ5() { // | region | // | | // +---------------+ - s.statsMap = make(map[int]*property.StatsInfo) - s.mockStatsInfo(3, 9103367) - s.mockStatsInfo(6, 2275919) - s.mockStatsInfo(7, 9103367) - s.mockStatsInfo(9, 59986052) - s.mockStatsInfo(11, 9103367) - s.mockStatsInfo(12, 5999974575) - s.mockStatsInfo(13, 59999974575) - s.mockStatsInfo(14, 9103543072) - s.mockStatsInfo(15, 99103543072) - s.mockStatsInfo(20, 1500000) - s.mockStatsInfo(22, 2275919) - s.mockStatsInfo(23, 7982159) - s.mockStatsInfo(24, 100000) - s.mockStatsInfo(25, 59986052) - s.mockStatsInfo(27, 9103367) - s.mockStatsInfo(28, 5999974575) - s.mockStatsInfo(29, 59999974575) - s.mockStatsInfo(30, 59999974575) - s.mockStatsInfo(31, 59999974575) - s.mockStatsInfo(48, 5) - s.mockStatsInfo(52, 299838) - s.mockStatsInfo(54, 454183) - s.mockStatsInfo(55, 1815222) - s.mockStatsInfo(56, 20042) - s.mockStatsInfo(57, 12022687) - s.mockStatsInfo(59, 1823514) - s.mockStatsInfo(60, 1201884359) - s.mockStatsInfo(61, 12001884359) - s.mockStatsInfo(62, 12001884359) - s.mockStatsInfo(63, 72985) - + statsMap := make(map[int]*property.StatsInfo) + statsMap[3] = &property.StatsInfo{RowCount: 9103367} + statsMap[6] = &property.StatsInfo{RowCount: 2275919} + statsMap[7] = &property.StatsInfo{RowCount: 9103367} + statsMap[9] = &property.StatsInfo{RowCount: 59986052} + statsMap[11] = &property.StatsInfo{RowCount: 9103367} + statsMap[12] = &property.StatsInfo{RowCount: 5999974575} + statsMap[13] = &property.StatsInfo{RowCount: 59999974575} + statsMap[14] = &property.StatsInfo{RowCount: 9103543072} + statsMap[15] = &property.StatsInfo{RowCount: 99103543072} + statsMap[20] = &property.StatsInfo{RowCount: 1500000} + statsMap[22] = &property.StatsInfo{RowCount: 2275919} + statsMap[23] = &property.StatsInfo{RowCount: 7982159} + statsMap[24] = &property.StatsInfo{RowCount: 100000} + statsMap[25] = &property.StatsInfo{RowCount: 59986052} + statsMap[27] = &property.StatsInfo{RowCount: 9103367} + statsMap[28] = &property.StatsInfo{RowCount: 5999974575} + statsMap[29] = &property.StatsInfo{RowCount: 59999974575} + statsMap[30] = &property.StatsInfo{RowCount: 59999974575} + statsMap[31] = &property.StatsInfo{RowCount: 59999974575} + statsMap[48] = &property.StatsInfo{RowCount: 5} + statsMap[52] = &property.StatsInfo{RowCount: 299838} + statsMap[54] = &property.StatsInfo{RowCount: 454183} + statsMap[55] = &property.StatsInfo{RowCount: 1815222} + statsMap[56] = &property.StatsInfo{RowCount: 20042} + statsMap[57] = &property.StatsInfo{RowCount: 12022687} + statsMap[59] = &property.StatsInfo{RowCount: 1823514} + statsMap[60] = &property.StatsInfo{RowCount: 1201884359} + statsMap[61] = &property.StatsInfo{RowCount: 12001884359} + statsMap[62] = &property.StatsInfo{RowCount: 12001884359} + statsMap[63] = &property.StatsInfo{RowCount: 72985} + return statsMap } -func (s *testJoinReorderDPSuite) newDataSource(name string, count int) LogicalPlan { - ds := DataSource{}.Init(s.ctx, 0) +func newDataSource(ctx sessionctx.Context, name string, count int) LogicalPlan { + ds := DataSource{}.Init(ctx, 0) tan := model.NewCIStr(name) ds.TableAsName = &tan ds.schema = expression.NewSchema() - s.ctx.GetSessionVars().PlanColumnID++ + ctx.GetSessionVars().PlanColumnID++ ds.schema.Append(&expression.Column{ - UniqueID: s.ctx.GetSessionVars().PlanColumnID, + UniqueID: ctx.GetSessionVars().PlanColumnID, RetType: types.NewFieldType(mysql.TypeLonglong), }) ds.stats = &property.StatsInfo{ @@ -162,57 +147,70 @@ func (s *testJoinReorderDPSuite) newDataSource(name string, count int) LogicalPl return ds } -func (s *testJoinReorderDPSuite) planToString(plan LogicalPlan) string { +func planToString(plan LogicalPlan) string { switch x := plan.(type) { case *mockLogicalJoin: - return fmt.Sprintf("MockJoin{%v, %v}", s.planToString(x.children[0]), s.planToString(x.children[1])) + return fmt.Sprintf("MockJoin{%v, %v}", planToString(x.children[0]), planToString(x.children[1])) case *DataSource: return x.TableAsName.L } return "" } -func (s *testJoinReorderDPSuite) TestDPReorderTPCHQ5(c *C) { - s.makeStatsMapForTPCHQ5() +func TestDPReorderTPCHQ5(t *testing.T) { + statsMap := makeStatsMapForTPCHQ5() + + ctx := MockContext() + ctx.GetSessionVars().PlanID = -1 joinGroups := make([]LogicalPlan, 0, 6) - joinGroups = append(joinGroups, s.newDataSource("lineitem", 59986052)) - joinGroups = append(joinGroups, s.newDataSource("orders", 15000000)) - joinGroups = append(joinGroups, s.newDataSource("customer", 1500000)) - joinGroups = append(joinGroups, s.newDataSource("supplier", 100000)) - joinGroups = append(joinGroups, s.newDataSource("nation", 25)) - joinGroups = append(joinGroups, s.newDataSource("region", 5)) + joinGroups = append(joinGroups, newDataSource(ctx, "lineitem", 59986052)) + joinGroups = append(joinGroups, newDataSource(ctx, "orders", 15000000)) + joinGroups = append(joinGroups, newDataSource(ctx, "customer", 1500000)) + joinGroups = append(joinGroups, newDataSource(ctx, "supplier", 100000)) + joinGroups = append(joinGroups, newDataSource(ctx, "nation", 25)) + joinGroups = append(joinGroups, newDataSource(ctx, "region", 5)) + var eqConds []expression.Expression - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[0].Schema().Columns[0], joinGroups[1].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[1].Schema().Columns[0], joinGroups[2].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[2].Schema().Columns[0], joinGroups[3].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[0].Schema().Columns[0], joinGroups[3].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[2].Schema().Columns[0], joinGroups[4].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[3].Schema().Columns[0], joinGroups[4].Schema().Columns[0])) - eqConds = append(eqConds, expression.NewFunctionInternal(s.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[4].Schema().Columns[0], joinGroups[5].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[0].Schema().Columns[0], joinGroups[1].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[1].Schema().Columns[0], joinGroups[2].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[2].Schema().Columns[0], joinGroups[3].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[0].Schema().Columns[0], joinGroups[3].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[2].Schema().Columns[0], joinGroups[4].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[3].Schema().Columns[0], joinGroups[4].Schema().Columns[0])) + eqConds = append(eqConds, expression.NewFunctionInternal(ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), joinGroups[4].Schema().Columns[0], joinGroups[5].Schema().Columns[0])) solver := &joinReorderDPSolver{ baseSingleGroupJoinOrderSolver: &baseSingleGroupJoinOrderSolver{ - ctx: s.ctx, + ctx: ctx, }, - newJoin: s.newMockJoin, + newJoin: newMockJoin(ctx, statsMap), } result, err := solver.solve(joinGroups, eqConds, nil) - c.Assert(err, IsNil) - c.Assert(s.planToString(result), Equals, "MockJoin{supplier, MockJoin{lineitem, MockJoin{orders, MockJoin{customer, MockJoin{nation, region}}}}}") + require.NoError(t, err) + + expected := "MockJoin{supplier, MockJoin{lineitem, MockJoin{orders, MockJoin{customer, MockJoin{nation, region}}}}}" + require.Equal(t, expected, planToString(result)) } -func (s *testJoinReorderDPSuite) TestDPReorderAllCartesian(c *C) { +func TestDPReorderAllCartesian(t *testing.T) { + statsMap := makeStatsMapForTPCHQ5() + + ctx := MockContext() + ctx.GetSessionVars().PlanID = -1 + joinGroup := make([]LogicalPlan, 0, 4) - joinGroup = append(joinGroup, s.newDataSource("a", 100)) - joinGroup = append(joinGroup, s.newDataSource("b", 100)) - joinGroup = append(joinGroup, s.newDataSource("c", 100)) - joinGroup = append(joinGroup, s.newDataSource("d", 100)) + joinGroup = append(joinGroup, newDataSource(ctx, "a", 100)) + joinGroup = append(joinGroup, newDataSource(ctx, "b", 100)) + joinGroup = append(joinGroup, newDataSource(ctx, "c", 100)) + joinGroup = append(joinGroup, newDataSource(ctx, "d", 100)) solver := &joinReorderDPSolver{ baseSingleGroupJoinOrderSolver: &baseSingleGroupJoinOrderSolver{ - ctx: s.ctx, + ctx: ctx, }, - newJoin: s.newMockJoin, + newJoin: newMockJoin(ctx, statsMap), } result, err := solver.solve(joinGroup, nil, nil) - c.Assert(err, IsNil) - c.Assert(s.planToString(result), Equals, "MockJoin{MockJoin{a, b}, MockJoin{c, d}}") + require.NoError(t, err) + + expected := "MockJoin{MockJoin{a, b}, MockJoin{c, d}}" + require.Equal(t, expected, planToString(result)) } diff --git a/planner/core/rule_max_min_eliminate.go b/planner/core/rule_max_min_eliminate.go index 858f9005c2273..a2af6c0c21a4d 100644 --- a/planner/core/rule_max_min_eliminate.go +++ b/planner/core/rule_max_min_eliminate.go @@ -154,7 +154,7 @@ func (a *maxMinEliminator) splitAggFuncAndCheckIndices(agg *LogicalAggregation, newAgg := LogicalAggregation{AggFuncs: []*aggregation.AggFuncDesc{f}}.Init(agg.ctx, agg.blockOffset) newAgg.SetChildren(a.cloneSubPlans(agg.children[0])) newAgg.schema = expression.NewSchema(agg.schema.Columns[i]) - if err := newAgg.PruneColumns([]*expression.Column{newAgg.schema.Columns[0]}); err != nil { + if err := newAgg.PruneColumns([]*expression.Column{newAgg.schema.Columns[0]}, opt); err != nil { return nil, false } aggs = append(aggs, newAgg) @@ -254,56 +254,56 @@ func appendEliminateSingleMaxMinTrace(agg *LogicalAggregation, sel *LogicalSelec action := func() string { buffer := bytes.NewBufferString("") if sel != nil { - buffer.WriteString(fmt.Sprintf("add selection[%v],", sel.ID())) + buffer.WriteString(fmt.Sprintf("add %v_%v,", sel.TP(), sel.ID())) } if sort != nil { - buffer.WriteString(fmt.Sprintf("add sort[%v],", sort.ID())) + buffer.WriteString(fmt.Sprintf("add %v_%v,", sort.TP(), sort.ID())) } - buffer.WriteString(fmt.Sprintf("add limit[%v] during eliminating agg[%v] %s function", limit.ID(), agg.ID(), agg.AggFuncs[0].Name)) + buffer.WriteString(fmt.Sprintf("add %v_%v during eliminating %v_%v %s function", limit.TP(), limit.ID(), agg.TP(), agg.ID(), agg.AggFuncs[0].Name)) return buffer.String() - }() + } reason := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v] has only one function[%s] without group by", agg.ID(), agg.AggFuncs[0].Name)) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v has only one function[%s] without group by", agg.TP(), agg.ID(), agg.AggFuncs[0].Name)) if sel != nil { - buffer.WriteString(fmt.Sprintf(", the columns in agg[%v] shouldn't be NULL and needs NULL to be filtered out", agg.ID())) + buffer.WriteString(fmt.Sprintf(", the columns in %v_%v shouldn't be NULL and needs NULL to be filtered out", agg.TP(), agg.ID())) } if sort != nil { - buffer.WriteString(fmt.Sprintf(", the columns in agg[%v] should be sorted", agg.ID())) + buffer.WriteString(fmt.Sprintf(", the columns in %v_%v should be sorted", agg.TP(), agg.ID())) } return buffer.String() - }() + } opt.appendStepToCurrent(agg.ID(), agg.TP(), reason, action) } func appendEliminateMultiMinMaxTraceStep(originAgg *LogicalAggregation, aggs []*LogicalAggregation, joins []*LogicalJoin, opt *logicalOptimizeOp) { action := func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("agg[%v] splited into aggs[", originAgg.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v splited into [", originAgg.TP(), originAgg.ID())) for i, agg := range aggs { if i > 0 { buffer.WriteString(",") } - buffer.WriteString(fmt.Sprintf("%v", agg.ID())) + buffer.WriteString(fmt.Sprintf("%v_%v", agg.TP(), agg.ID())) } - buffer.WriteString("], and add joins[") + buffer.WriteString("], and add [") for i, join := range joins { if i > 0 { buffer.WriteString(",") } - buffer.WriteString(fmt.Sprintf("%v", join.ID())) + buffer.WriteString(fmt.Sprintf("%v_%v", join.TP(), join.ID())) } - buffer.WriteString(fmt.Sprintf("] to connect them during eliminating agg[%v] multi min/max functions", originAgg.ID())) + buffer.WriteString(fmt.Sprintf("] to connect them during eliminating %v_%v multi min/max functions", originAgg.TP(), originAgg.ID())) return buffer.String() - }() + } reason := func() string { - buffer := bytes.NewBufferString("each column is sorted and can benefit from index/primary key in agg[") + buffer := bytes.NewBufferString("each column is sorted and can benefit from index/primary key in [") for i, agg := range aggs { if i > 0 { buffer.WriteString(",") } - buffer.WriteString(fmt.Sprintf("%v", agg.ID())) + buffer.WriteString(fmt.Sprintf("%v_%v", agg.TP(), agg.ID())) } buffer.WriteString("] and none of them has group by clause") return buffer.String() - }() + } opt.appendStepToCurrent(originAgg.ID(), originAgg.TP(), reason, action) } diff --git a/planner/core/rule_partition_processor.go b/planner/core/rule_partition_processor.go index 04f572200232b..991c42ec4c1b6 100644 --- a/planner/core/rule_partition_processor.go +++ b/planner/core/rule_partition_processor.go @@ -43,6 +43,7 @@ import ( const FullRange = -1 // partitionProcessor rewrites the ast for table partition. +// Used by static partition prune mode. // // create table t (id int) partition by range (id) // (partition p1 values less than (10), @@ -310,6 +311,15 @@ func (s *partitionProcessor) reconstructTableColNames(ds *DataSource) ([]*types. }) continue } + if colExpr.ID == model.ExtraPhysTblID { + names = append(names, &types.FieldName{ + DBName: ds.DBName, + TblName: ds.tableInfo.Name, + ColName: model.ExtraPhysTblIdName, + OrigColName: model.ExtraPhysTblIdName, + }) + continue + } if colInfo, found := colsInfoMap[colExpr.ID]; found { names = append(names, &types.FieldName{ DBName: ds.DBName, @@ -640,7 +650,7 @@ func (s *partitionProcessor) prune(ds *DataSource, opt *logicalOptimizeOp) (Logi return s.processListPartition(ds, pi, opt) } - // We haven't implement partition by list and so on. + // We haven't implement partition by key and so on. return s.makeUnionAllChildren(ds, pi, fullRange(len(pi.Definitions)), opt) } @@ -930,7 +940,7 @@ func makePartitionByFnCol(sctx sessionctx.Context, columns []*expression.Column, monotonous = getMonotoneMode(raw.FuncName.L) // Check the partitionExpr is in the form: fn(col, ...) // There should be only one column argument, and it should be the first parameter. - if expression.ExtractColumnSet(args).Len() == 1 { + if expression.ExtractColumnSet(args...).Len() == 1 { if col1, ok := args[0].(*expression.Column); ok { col = col1 } @@ -964,6 +974,9 @@ func partitionRangeForExpr(sctx sessionctx.Context, expr expression.Expression, if p, ok := pruner.(*rangePruner); ok { newRange := partitionRangeForInExpr(sctx, op.GetArgs(), p) return result.intersection(newRange) + } else if p, ok := pruner.(*rangeColumnsPruner); ok { + newRange := partitionRangeColumnForInExpr(sctx, op.GetArgs(), p) + return result.intersection(newRange) } return result } @@ -1024,6 +1037,43 @@ func partitionRangeForOrExpr(sctx sessionctx.Context, expr1, expr2 expression.Ex return tmp1.union(tmp2) } +func partitionRangeColumnForInExpr(sctx sessionctx.Context, args []expression.Expression, + pruner *rangeColumnsPruner) partitionRangeOR { + col, ok := args[0].(*expression.Column) + if !ok || col.ID != pruner.partCol.ID { + return pruner.fullRange() + } + + var result partitionRangeOR + for i := 1; i < len(args); i++ { + constExpr, ok := args[i].(*expression.Constant) + if !ok { + return pruner.fullRange() + } + switch constExpr.Value.Kind() { + case types.KindInt64, types.KindUint64, types.KindMysqlTime, types.KindString: // for safety, only support string,int and datetime now + case types.KindNull: + result = append(result, partitionRange{0, 1}) + continue + default: + return pruner.fullRange() + } + + // convert all elements to EQ-exprs and prune them one by one + sf, err := expression.NewFunction(sctx, ast.EQ, types.NewFieldType(types.KindInt64), []expression.Expression{col, args[i]}...) + if err != nil { + return pruner.fullRange() + } + start, end, ok := pruner.partitionRangeForExpr(sctx, sf) + if !ok { + return pruner.fullRange() + } + result = append(result, partitionRange{start, end}) + } + + return result.simplify() +} + func partitionRangeForInExpr(sctx sessionctx.Context, args []expression.Expression, pruner *rangePruner) partitionRangeOR { col, ok := args[0].(*expression.Column) @@ -1580,9 +1630,8 @@ func appendMakeUnionAllChildrenTranceStep(ds *DataSource, usedMap map[int64]mode appendNoPartitionChildTraceStep(ds, plan, opt) return } - action := "" - reason := "" - var used []model.PartitionDefinition + var action, reason func() string + used := make([]model.PartitionDefinition, 0, len(usedMap)) for _, def := range usedMap { used = append(used, def) } @@ -1590,22 +1639,26 @@ func appendMakeUnionAllChildrenTranceStep(ds *DataSource, usedMap map[int64]mode return used[i].ID < used[j].ID }) if len(children) == 1 { - action = fmt.Sprintf("Datasource[%v] becomes %s[%v]", ds.ID(), plan.TP(), plan.ID()) - reason = fmt.Sprintf("Datasource[%v] has one needed partition[%s] after pruning", ds.ID(), used[0].Name) + action = func() string { + return fmt.Sprintf("%v_%v becomes %s_%v", ds.TP(), ds.ID(), plan.TP(), plan.ID()) + } + reason = func() string { + return fmt.Sprintf("%v_%v has one needed partition[%s] after pruning", ds.TP(), ds.ID(), used[0].Name) + } } else { action = func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("Datasource[%v] becomes %s[%v] with children[", ds.ID(), plan.TP(), plan.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v becomes %s_%v with children[", ds.TP(), ds.ID(), plan.TP(), plan.ID())) for i, child := range children { if i > 0 { buffer.WriteString(",") } - buffer.WriteString(fmt.Sprintf("%s[%v]", child.TP(), child.ID())) + buffer.WriteString(fmt.Sprintf("%s_%v", child.TP(), child.ID())) } buffer.WriteString("]") return buffer.String() - }() + } reason = func() string { - buffer := bytes.NewBufferString(fmt.Sprintf("Datasource[%v] has multiple needed partitions[", ds.ID())) + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v has multiple needed partitions[", ds.TP(), ds.ID())) for i, u := range used { if i > 0 { buffer.WriteString(",") @@ -1614,13 +1667,17 @@ func appendMakeUnionAllChildrenTranceStep(ds *DataSource, usedMap map[int64]mode } buffer.WriteString("] after pruning") return buffer.String() - }() + } } opt.appendStepToCurrent(ds.ID(), ds.TP(), reason, action) } func appendNoPartitionChildTraceStep(ds *DataSource, dual LogicalPlan, opt *logicalOptimizeOp) { - action := fmt.Sprintf("Datasource[%v] becomes %v[%v]", ds.ID(), dual.TP(), dual.ID()) - reason := fmt.Sprintf("Datasource[%v] doesn't have needed partition table after pruning", ds.ID()) + action := func() string { + return fmt.Sprintf("%v_%v becomes %v_%v", ds.TP(), ds.ID(), dual.TP(), dual.ID()) + } + reason := func() string { + return fmt.Sprintf("%v_%v doesn't have needed partition table after pruning", ds.TP(), ds.ID()) + } opt.appendStepToCurrent(dual.ID(), dual.TP(), reason, action) } diff --git a/planner/core/rule_predicate_push_down.go b/planner/core/rule_predicate_push_down.go index f59fedc25ba28..9d060ce2bb166 100644 --- a/planner/core/rule_predicate_push_down.go +++ b/planner/core/rule_predicate_push_down.go @@ -15,24 +15,39 @@ package core import ( + "bytes" "context" + "fmt" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/planner/util" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/ranger" + "go.uber.org/zap" ) type ppdSolver struct{} +// exprPrefixAdder is the wrapper struct to add tidb_shard(x) = val for `OrigConds` +// `cols` is the index columns for a unique shard index +type exprPrefixAdder struct { + sctx sessionctx.Context + OrigConds []expression.Expression + cols []*expression.Column + lengths []int +} + func (s *ppdSolver) optimize(ctx context.Context, lp LogicalPlan, opt *logicalOptimizeOp) (LogicalPlan, error) { - _, p := lp.PredicatePushDown(nil) + _, p := lp.PredicatePushDown(nil, opt) return p, nil } -func addSelection(p LogicalPlan, child LogicalPlan, conditions []expression.Expression, chIdx int) { +func addSelection(p LogicalPlan, child LogicalPlan, conditions []expression.Expression, chIdx int, opt *logicalOptimizeOp) { if len(conditions) == 0 { p.Children()[chIdx] = child return @@ -42,6 +57,7 @@ func addSelection(p LogicalPlan, child LogicalPlan, conditions []expression.Expr dual := Conds2TableDual(child, conditions) if dual != nil { p.Children()[chIdx] = dual + appendTableDualTraceStep(child, dual, conditions, opt) return } @@ -53,16 +69,17 @@ func addSelection(p LogicalPlan, child LogicalPlan, conditions []expression.Expr selection := LogicalSelection{Conditions: conditions}.Init(p.SCtx(), p.SelectBlockOffset()) selection.SetChildren(child) p.Children()[chIdx] = selection + appendAddSelectionTraceStep(p, child, selection, opt) } // PredicatePushDown implements LogicalPlan interface. -func (p *baseLogicalPlan) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *baseLogicalPlan) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { if len(p.children) == 0 { return predicates, p.self } child := p.children[0] - rest, newChild := child.PredicatePushDown(predicates) - addSelection(p.self, newChild, rest, 0) + rest, newChild := child.PredicatePushDown(predicates, opt) + addSelection(p.self, newChild, rest, 0, opt) return nil, p.self } @@ -80,34 +97,33 @@ func splitSetGetVarFunc(filters []expression.Expression) ([]expression.Expressio } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalSelection) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalSelection) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { predicates = DeleteTrueExprs(p, predicates) p.Conditions = DeleteTrueExprs(p, p.Conditions) var child LogicalPlan var retConditions []expression.Expression - if p.buildByHaving { - retConditions, child = p.children[0].PredicatePushDown(predicates) - retConditions = append(retConditions, p.Conditions...) - } else { - canBePushDown, canNotBePushDown := splitSetGetVarFunc(p.Conditions) - retConditions, child = p.children[0].PredicatePushDown(append(canBePushDown, predicates...)) - retConditions = append(retConditions, canNotBePushDown...) - } + var originConditions []expression.Expression + canBePushDown, canNotBePushDown := splitSetGetVarFunc(p.Conditions) + originConditions = canBePushDown + retConditions, child = p.children[0].PredicatePushDown(append(canBePushDown, predicates...), opt) + retConditions = append(retConditions, canNotBePushDown...) if len(retConditions) > 0 { p.Conditions = expression.PropagateConstant(p.ctx, retConditions) // Return table dual when filter is constant false or null. dual := Conds2TableDual(p, p.Conditions) if dual != nil { + appendTableDualTraceStep(p, dual, p.Conditions, opt) return nil, dual } return nil, p } + appendSelectionPredicatePushDownTraceStep(p, originConditions, opt) return nil, child } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalUnionScan) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { - retainedPredicates, _ := p.children[0].PredicatePushDown(predicates) +func (p *LogicalUnionScan) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { + retainedPredicates, _ := p.children[0].PredicatePushDown(predicates, opt) p.conditions = make([]expression.Expression, 0, len(predicates)) p.conditions = append(p.conditions, predicates...) // The conditions in UnionScan is only used for added rows, so parent Selection should not be removed. @@ -115,21 +131,25 @@ func (p *LogicalUnionScan) PredicatePushDown(predicates []expression.Expression) } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (ds *DataSource) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (ds *DataSource) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { predicates = expression.PropagateConstant(ds.ctx, predicates) predicates = DeleteTrueExprs(ds, predicates) + // Add tidb_shard() prefix to the condtion for shard index in some scenarios + // TODO: remove it to the place building logical plan + predicates = ds.AddPrefix4ShardIndexes(ds.ctx, predicates) ds.allConds = predicates ds.pushedDownConds, predicates = expression.PushDownExprs(ds.ctx.GetSessionVars().StmtCtx, predicates, ds.ctx.GetClient(), kv.UnSpecified) + appendDataSourcePredicatePushDownTraceStep(ds, opt) return predicates, ds } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalTableDual) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalTableDual) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { return predicates, p } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret []expression.Expression, retPlan LogicalPlan) { +func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) (ret []expression.Expression, retPlan LogicalPlan) { simplifyOuterJoin(p, predicates) var equalCond []*expression.ScalarFunction var leftPushCond, rightPushCond, otherCond, leftCond, rightCond []expression.Expression @@ -138,6 +158,7 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret predicates = p.outerJoinPropConst(predicates) dual := Conds2TableDual(p, predicates) if dual != nil { + appendTableDualTraceStep(p, dual, predicates, opt) return ret, dual } // Handle where conditions @@ -156,6 +177,7 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret predicates = p.outerJoinPropConst(predicates) dual := Conds2TableDual(p, predicates) if dual != nil { + appendTableDualTraceStep(p, dual, predicates, opt) return ret, dual } // Handle where conditions @@ -182,6 +204,7 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret // Return table dual when filter is constant false or null. dual := Conds2TableDual(p, tempCond) if dual != nil { + appendTableDualTraceStep(p, dual, tempCond, opt) return ret, dual } equalCond, leftPushCond, rightPushCond, otherCond = p.extractOnCondition(tempCond, true, true) @@ -196,6 +219,7 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret // Return table dual when filter is constant false or null. dual := Conds2TableDual(p, predicates) if dual != nil { + appendTableDualTraceStep(p, dual, predicates, opt) return ret, dual } // `predicates` should only contain left conditions or constant filters. @@ -212,10 +236,10 @@ func (p *LogicalJoin) PredicatePushDown(predicates []expression.Expression) (ret } leftCond = expression.RemoveDupExprs(p.ctx, leftCond) rightCond = expression.RemoveDupExprs(p.ctx, rightCond) - leftRet, lCh := p.children[0].PredicatePushDown(leftCond) - rightRet, rCh := p.children[1].PredicatePushDown(rightCond) - addSelection(p, lCh, leftRet, 0) - addSelection(p, rCh, rightRet, 1) + leftRet, lCh := p.children[0].PredicatePushDown(leftCond, opt) + rightRet, rCh := p.children[1].PredicatePushDown(rightCond, opt) + addSelection(p, lCh, leftRet, 0, opt) + addSelection(p, rCh, rightRet, 1, opt) p.updateEQCond() buildKeyInfo(p) return ret, p.self @@ -363,6 +387,9 @@ func simplifyOuterJoin(p *LogicalJoin, predicates []expression.Expression) { // If it is a disjunction of null-rejected conditions. func isNullRejected(ctx sessionctx.Context, schema *expression.Schema, expr expression.Expression) bool { expr = expression.PushDownNot(ctx, expr) + if expression.ContainOuterNot(expr) { + return false + } sc := ctx.GetSessionVars().StmtCtx sc.InNullRejectCheck = true result := expression.EvaluateExprWithNull(ctx, schema, expr) @@ -380,12 +407,12 @@ func isNullRejected(ctx sessionctx.Context, schema *expression.Schema, expr expr } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression) (ret []expression.Expression, retPlan LogicalPlan) { +func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) (ret []expression.Expression, retPlan LogicalPlan) { canBePushed := make([]expression.Expression, 0, len(predicates)) canNotBePushed := make([]expression.Expression, 0, len(predicates)) for _, expr := range p.Exprs { if expression.HasAssignSetVarFunc(expr) { - _, child := p.baseLogicalPlan.PredicatePushDown(nil) + _, child := p.baseLogicalPlan.PredicatePushDown(nil, opt) return predicates, child } } @@ -397,71 +424,142 @@ func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression canNotBePushed = append(canNotBePushed, cond) } } - remained, child := p.baseLogicalPlan.PredicatePushDown(canBePushed) + remained, child := p.baseLogicalPlan.PredicatePushDown(canBePushed, opt) return append(remained, canNotBePushed...), child } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalUnionAll) PredicatePushDown(predicates []expression.Expression) (ret []expression.Expression, retPlan LogicalPlan) { +func (p *LogicalUnionAll) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) (ret []expression.Expression, retPlan LogicalPlan) { for i, proj := range p.children { newExprs := make([]expression.Expression, 0, len(predicates)) newExprs = append(newExprs, predicates...) - retCond, newChild := proj.PredicatePushDown(newExprs) - addSelection(p, newChild, retCond, i) + retCond, newChild := proj.PredicatePushDown(newExprs, opt) + addSelection(p, newChild, retCond, i, opt) } return nil, p } +// pushDownPredicatesForAggregation split a condition to two parts, can be pushed-down or can not be pushed-down below aggregation. +func (la *LogicalAggregation) pushDownPredicatesForAggregation(cond expression.Expression, groupByColumns *expression.Schema, exprsOriginal []expression.Expression) ([]expression.Expression, []expression.Expression) { + var condsToPush []expression.Expression + var ret []expression.Expression + switch cond.(type) { + case *expression.Constant: + condsToPush = append(condsToPush, cond) + // Consider SQL list "select sum(b) from t group by a having 1=0". "1=0" is a constant predicate which should be + // retained and pushed down at the same time. Because we will get a wrong query result that contains one column + // with value 0 rather than an empty query result. + ret = append(ret, cond) + case *expression.ScalarFunction: + extractedCols := expression.ExtractColumns(cond) + ok := true + for _, col := range extractedCols { + if !groupByColumns.Contains(col) { + ok = false + break + } + } + if ok { + newFunc := expression.ColumnSubstitute(cond, la.Schema(), exprsOriginal) + condsToPush = append(condsToPush, newFunc) + } else { + ret = append(ret, cond) + } + default: + ret = append(ret, cond) + } + return condsToPush, ret +} + +// pushDownPredicatesForAggregation split a CNF condition to two parts, can be pushed-down or can not be pushed-down below aggregation. +// It would consider the CNF. +// For example, +// (a > 1 or avg(b) > 1) and (a < 3), and `avg(b) > 1` can't be pushed-down. +// Then condsToPush: a < 3, ret: a > 1 or avg(b) > 1 +func (la *LogicalAggregation) pushDownCNFPredicatesForAggregation(cond expression.Expression, groupByColumns *expression.Schema, exprsOriginal []expression.Expression) ([]expression.Expression, []expression.Expression) { + var condsToPush []expression.Expression + var ret []expression.Expression + subCNFItem := expression.SplitCNFItems(cond) + if len(subCNFItem) == 1 { + return la.pushDownPredicatesForAggregation(subCNFItem[0], groupByColumns, exprsOriginal) + } + for _, item := range subCNFItem { + condsToPushForItem, retForItem := la.pushDownDNFPredicatesForAggregation(item, groupByColumns, exprsOriginal) + if len(condsToPushForItem) > 0 { + condsToPush = append(condsToPush, expression.ComposeDNFCondition(la.ctx, condsToPushForItem...)) + } + if len(retForItem) > 0 { + ret = append(ret, expression.ComposeDNFCondition(la.ctx, retForItem...)) + } + } + return condsToPush, ret +} + +// pushDownDNFPredicatesForAggregation split a DNF condition to two parts, can be pushed-down or can not be pushed-down below aggregation. +// It would consider the DNF. +// For example, +// (a > 1 and avg(b) > 1) or (a < 3), and `avg(b) > 1` can't be pushed-down. +// Then condsToPush: (a < 3) and (a > 1), ret: (a > 1 and avg(b) > 1) or (a < 3) +func (la *LogicalAggregation) pushDownDNFPredicatesForAggregation(cond expression.Expression, groupByColumns *expression.Schema, exprsOriginal []expression.Expression) ([]expression.Expression, []expression.Expression) { + var condsToPush []expression.Expression + var ret []expression.Expression + subDNFItem := expression.SplitDNFItems(cond) + if len(subDNFItem) == 1 { + return la.pushDownPredicatesForAggregation(subDNFItem[0], groupByColumns, exprsOriginal) + } + for _, item := range subDNFItem { + condsToPushForItem, retForItem := la.pushDownCNFPredicatesForAggregation(item, groupByColumns, exprsOriginal) + if len(condsToPushForItem) > 0 { + condsToPush = append(condsToPush, expression.ComposeCNFCondition(la.ctx, condsToPushForItem...)) + } else { + return nil, []expression.Expression{cond} + } + if len(retForItem) > 0 { + ret = append(ret, expression.ComposeCNFCondition(la.ctx, retForItem...)) + } + } + if len(ret) == 0 { + // All the condition can be pushed down. + return []expression.Expression{cond}, nil + } + dnfPushDownCond := expression.ComposeDNFCondition(la.ctx, condsToPush...) + // Some condition can't be pushed down, we need to keep all the condition. + return []expression.Expression{dnfPushDownCond}, []expression.Expression{cond} +} + // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (la *LogicalAggregation) PredicatePushDown(predicates []expression.Expression) (ret []expression.Expression, retPlan LogicalPlan) { +func (la *LogicalAggregation) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) (ret []expression.Expression, retPlan LogicalPlan) { var condsToPush []expression.Expression exprsOriginal := make([]expression.Expression, 0, len(la.AggFuncs)) for _, fun := range la.AggFuncs { exprsOriginal = append(exprsOriginal, fun.Args[0]) } groupByColumns := expression.NewSchema(la.GetGroupByCols()...) + // It's almost the same as pushDownCNFPredicatesForAggregation, except that the condition is a slice. for _, cond := range predicates { - switch cond.(type) { - case *expression.Constant: - condsToPush = append(condsToPush, cond) - // Consider SQL list "select sum(b) from t group by a having 1=0". "1=0" is a constant predicate which should be - // retained and pushed down at the same time. Because we will get a wrong query result that contains one column - // with value 0 rather than an empty query result. - ret = append(ret, cond) - case *expression.ScalarFunction: - extractedCols := expression.ExtractColumns(cond) - ok := true - for _, col := range extractedCols { - if !groupByColumns.Contains(col) { - ok = false - break - } - } - if ok { - newFunc := expression.ColumnSubstitute(cond, la.Schema(), exprsOriginal) - condsToPush = append(condsToPush, newFunc) - } else { - ret = append(ret, cond) - } - default: - ret = append(ret, cond) + subCondsToPush, subRet := la.pushDownDNFPredicatesForAggregation(cond, groupByColumns, exprsOriginal) + if len(subCondsToPush) > 0 { + condsToPush = append(condsToPush, subCondsToPush...) + } + if len(subRet) > 0 { + ret = append(ret, subRet...) } } - la.baseLogicalPlan.PredicatePushDown(condsToPush) + la.baseLogicalPlan.PredicatePushDown(condsToPush, opt) return ret, la } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalLimit) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalLimit) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { // Limit forbids any condition to push down. - p.baseLogicalPlan.PredicatePushDown(nil) + p.baseLogicalPlan.PredicatePushDown(nil, opt) return predicates, p } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalMaxOneRow) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalMaxOneRow) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { // MaxOneRow forbids any condition to push down. - p.baseLogicalPlan.PredicatePushDown(nil) + p.baseLogicalPlan.PredicatePushDown(nil, opt) return predicates, p } @@ -610,7 +708,7 @@ func (p *LogicalWindow) GetPartitionByCols() []*expression.Column { } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalWindow) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalWindow) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { canBePushed := make([]expression.Expression, 0, len(predicates)) canNotBePushed := make([]expression.Expression, 0, len(predicates)) partitionCols := expression.NewSchema(p.GetPartitionByCols()...) @@ -623,12 +721,12 @@ func (p *LogicalWindow) PredicatePushDown(predicates []expression.Expression) ([ canNotBePushed = append(canNotBePushed, cond) } } - p.baseLogicalPlan.PredicatePushDown(canBePushed) + p.baseLogicalPlan.PredicatePushDown(canBePushed, opt) return canNotBePushed, p } // PredicatePushDown implements LogicalPlan PredicatePushDown interface. -func (p *LogicalMemTable) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) { +func (p *LogicalMemTable) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { if p.Extractor != nil { predicates = p.Extractor.Extract(p.ctx, p.schema, p.names, predicates) } @@ -638,3 +736,215 @@ func (p *LogicalMemTable) PredicatePushDown(predicates []expression.Expression) func (*ppdSolver) name() string { return "predicate_push_down" } + +func appendTableDualTraceStep(replaced LogicalPlan, dual LogicalPlan, conditions []expression.Expression, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v is replaced by %v_%v", replaced.TP(), replaced.ID(), dual.TP(), dual.ID()) + } + reason := func() string { + buffer := bytes.NewBufferString("The conditions[") + for i, cond := range conditions { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(cond.String()) + } + buffer.WriteString("] are constant false or null") + return buffer.String() + } + opt.appendStepToCurrent(dual.ID(), dual.TP(), reason, action) +} + +func appendSelectionPredicatePushDownTraceStep(p *LogicalSelection, conditions []expression.Expression, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v is removed", p.TP(), p.ID()) + } + reason := func() string { + return "" + } + if len(conditions) > 0 { + reason = func() string { + buffer := bytes.NewBufferString("The conditions[") + for i, cond := range conditions { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(cond.String()) + } + buffer.WriteString(fmt.Sprintf("] in %v_%v are pushed down", p.TP(), p.ID())) + return buffer.String() + } + } + opt.appendStepToCurrent(p.ID(), p.TP(), reason, action) +} + +func appendDataSourcePredicatePushDownTraceStep(ds *DataSource, opt *logicalOptimizeOp) { + if len(ds.pushedDownConds) < 1 { + return + } + reason := func() string { + return "" + } + action := func() string { + buffer := bytes.NewBufferString("The conditions[") + for i, cond := range ds.pushedDownConds { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(cond.String()) + } + buffer.WriteString(fmt.Sprintf("] are pushed down across %v_%v", ds.TP(), ds.ID())) + return buffer.String() + } + opt.appendStepToCurrent(ds.ID(), ds.TP(), reason, action) +} + +func appendAddSelectionTraceStep(p LogicalPlan, child LogicalPlan, sel *LogicalSelection, opt *logicalOptimizeOp) { + reason := func() string { + return "" + } + action := func() string { + return fmt.Sprintf("add %v_%v to connect %v_%v and %v_%v", sel.TP(), sel.ID(), p.TP(), p.ID(), child.TP(), child.ID()) + } + opt.appendStepToCurrent(sel.ID(), sel.TP(), reason, action) +} + +// AddPrefix4ShardIndexes add expression prefix for shard index. e.g. an index is test.uk(tidb_shard(a), a). +// It transforms the sql "SELECT * FROM test WHERE a = 10" to +// "SELECT * FROM test WHERE tidb_shard(a) = val AND a = 10", val is the value of tidb_shard(10). +// It also transforms the sql "SELECT * FROM test WHERE a IN (10, 20, 30)" to +// "SELECT * FROM test WHERE tidb_shard(a) = val1 AND a = 10 OR tidb_shard(a) = val2 AND a = 20" +// @param[in] conds the original condtion of this datasource +// @retval - the new condition after adding expression prefix +func (ds *DataSource) AddPrefix4ShardIndexes(sc sessionctx.Context, conds []expression.Expression) []expression.Expression { + if !ds.containExprPrefixUk { + return conds + } + + var err error + newConds := conds + + for _, path := range ds.possibleAccessPaths { + if !path.IsUkShardIndexPath { + continue + } + newConds, err = ds.addExprPrefixCond(sc, path, newConds) + if err != nil { + logutil.BgLogger().Error("Add tidb_shard expression failed", + zap.Error(err), + zap.Uint64("connection id", sc.GetSessionVars().ConnectionID), + zap.String("database name", ds.DBName.L), + zap.String("table name", ds.tableInfo.Name.L), + zap.String("index name", path.Index.Name.L)) + return conds + } + } + + return newConds +} + +func (ds *DataSource) addExprPrefixCond(sc sessionctx.Context, path *util.AccessPath, + conds []expression.Expression) ([]expression.Expression, error) { + IdxCols, IdxColLens := + expression.IndexInfo2PrefixCols(ds.Columns, ds.schema.Columns, path.Index) + if len(IdxCols) == 0 { + return conds, nil + } + + adder := &exprPrefixAdder{ + sctx: sc, + OrigConds: conds, + cols: IdxCols, + lengths: IdxColLens, + } + + return adder.addExprPrefix4ShardIndex() +} + +// AddExprPrefix4ShardIndex +// if original condition is a LogicOr expression, such as `WHERE a = 1 OR a = 10`, +// call the function AddExprPrefix4DNFCond to add prefix expression tidb_shard(a) = xxx for shard index. +// Otherwise, if the condition is `WHERE a = 1`, `WHERE a = 1 AND b = 10`, `WHERE a IN (1, 2, 3)`......, +// call the function AddExprPrefix4CNFCond to add prefix expression for shard index. +func (adder *exprPrefixAdder) addExprPrefix4ShardIndex() ([]expression.Expression, error) { + if len(adder.OrigConds) == 1 { + if sf, ok := adder.OrigConds[0].(*expression.ScalarFunction); ok && sf.FuncName.L == ast.LogicOr { + return adder.addExprPrefix4DNFCond(sf) + } + } + return adder.addExprPrefix4CNFCond(adder.OrigConds) +} + +// AddExprPrefix4CNFCond +// add the prefix expression for CNF condition, e.g. `WHERE a = 1`, `WHERE a = 1 AND b = 10`, ...... +// @param[in] conds the original condtion of the datasoure. e.g. `WHERE t1.a = 1 AND t1.b = 10 AND t2.a = 20`. +// if current datasource is `t1`, conds is {t1.a = 1, t1.b = 10}. if current datasource is +// `t2`, conds is {t2.a = 20} +// @return - the new condition after adding expression prefix +func (adder *exprPrefixAdder) addExprPrefix4CNFCond(conds []expression.Expression) ([]expression.Expression, error) { + newCondtionds, err := ranger.AddExpr4EqAndInCondition(adder.sctx, + conds, adder.cols) + + return newCondtionds, err +} + +// AddExprPrefix4DNFCond +// add the prefix expression for DNF condition, e.g. `WHERE a = 1 OR a = 10`, ...... +// The condition returned is `WHERE (tidb_shard(a) = 214 AND a = 1) OR (tidb_shard(a) = 142 AND a = 10)` +// @param[in] condition the original condtion of the datasoure. e.g. `WHERE a = 1 OR a = 10`. +// condtion is `a = 1 OR a = 10` +// @return - the new condition after adding expression prefix. It's still a LogicOr expression. +func (adder *exprPrefixAdder) addExprPrefix4DNFCond(condition *expression.ScalarFunction) ([]expression.Expression, error) { + var err error + dnfItems := expression.FlattenDNFConditions(condition) + newAccessItems := make([]expression.Expression, 0, len(dnfItems)) + + for _, item := range dnfItems { + if sf, ok := item.(*expression.ScalarFunction); ok { + var accesses []expression.Expression + if sf.FuncName.L == ast.LogicAnd { + cnfItems := expression.FlattenCNFConditions(sf) + accesses, err = adder.addExprPrefix4CNFCond(cnfItems) + if err != nil { + return []expression.Expression{condition}, err + } + newAccessItems = append(newAccessItems, expression.ComposeCNFCondition(adder.sctx, accesses...)) + } else if sf.FuncName.L == ast.EQ || sf.FuncName.L == ast.In { + // only add prefix expression for EQ or IN function + accesses, err = adder.addExprPrefix4CNFCond([]expression.Expression{sf}) + if err != nil { + return []expression.Expression{condition}, err + } + newAccessItems = append(newAccessItems, expression.ComposeCNFCondition(adder.sctx, accesses...)) + } else { + newAccessItems = append(newAccessItems, item) + } + } else { + newAccessItems = append(newAccessItems, item) + } + } + + return []expression.Expression{expression.ComposeDNFCondition(adder.sctx, newAccessItems...)}, nil +} + +// PredicatePushDown implements LogicalPlan PredicatePushDown interface. +func (p *LogicalCTE) PredicatePushDown(predicates []expression.Expression, opt *logicalOptimizeOp) ([]expression.Expression, LogicalPlan) { + if p.cte.recursivePartLogicalPlan != nil { + // Doesn't support recursive CTE yet. + return predicates, p.self + } + if !p.isOuterMostCTE { + return predicates, p.self + } + if len(predicates) == 0 { + p.cte.pushDownPredicates = append(p.cte.pushDownPredicates, expression.NewOne()) + return predicates, p.self + } + newPred := make([]expression.Expression, 0, len(predicates)) + for i := range predicates { + newPred = append(newPred, predicates[i].Clone()) + ResolveExprAndReplace(newPred[i], p.cte.ColumnMap) + } + p.cte.pushDownPredicates = append(p.cte.pushDownPredicates, expression.ComposeCNFCondition(p.ctx, newPred...)) + return predicates, p.self +} diff --git a/planner/core/rule_result_reorder_test.go b/planner/core/rule_result_reorder_test.go index 7c12e1fff934d..567c1488508d9 100644 --- a/planner/core/rule_result_reorder_test.go +++ b/planner/core/rule_result_reorder_test.go @@ -17,49 +17,32 @@ package core_test import ( "fmt" "math" + "testing" - . "github.com/pingcap/check" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/kvcache" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testRuleReorderResults{}) -var _ = SerialSuites(&testRuleReorderResultsSerial{}) +func TestPlanCache(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() -type testRuleReorderResultsSerial struct { - store kv.Storage - dom *domain.Domain -} - -func (s *testRuleReorderResultsSerial) SetUpTest(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testRuleReorderResultsSerial) TearDownTest(c *C) { - s.dom.Close() - c.Assert(s.store.Close(), IsNil) -} - -func (s *testRuleReorderResultsSerial) TestPlanCache(c *C) { - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) orgEnable := plannercore.PreparedPlanCacheEnabled() defer func() { plannercore.SetPreparedPlanCache(orgEnable) }() plannercore.SetPreparedPlanCache(true) - var err error - tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{ + se, err := session.CreateSession4TestWithOpt(store, &session.Opt{ PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), }) - c.Assert(err, IsNil) + require.NoError(t, err) + tk.SetSession(se) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") @@ -73,8 +56,11 @@ func (s *testRuleReorderResultsSerial) TestPlanCache(c *C) { tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) // plan cache is still working } -func (s *testRuleReorderResultsSerial) TestSQLBinding(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestSQLBinding(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("set tidb_opt_limit_push_down_threshold=0") @@ -96,11 +82,14 @@ func (s *testRuleReorderResultsSerial) TestSQLBinding(c *C) { " └─TableRowIDScan_16(Probe) 1.00 cop[tikv] table:t keep order:false, stats:pseudo")) } -func (s *testRuleReorderResultsSerial) TestClusteredIndex(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestClusteredIndex(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn tk.MustExec("drop table if exists t") tk.MustExec("CREATE TABLE t (a int,b int,c int, PRIMARY KEY (a,b))") tk.MustQuery("explain format=brief select * from t limit 10").Check(testkit.Rows( @@ -108,100 +97,97 @@ func (s *testRuleReorderResultsSerial) TestClusteredIndex(c *C) { "└─TableReader 10.00 root data:TopN", " └─TopN 10.00 cop[tikv] test.t.a, test.t.b, test.t.c, offset:0, count:10", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) - tk.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOff -} - -type testRuleReorderResults struct { - store kv.Storage - dom *domain.Domain - - testData testutil.TestData + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOff } -func (s *testRuleReorderResults) SetUpSuite(c *C) { - var err error - s.store, s.dom, err = newStoreWithBootstrap() - c.Assert(err, IsNil) - - s.testData, err = testutil.LoadTestSuiteData("testdata", "ordered_result_mode_suite") - c.Assert(err, IsNil) -} - -func (s *testRuleReorderResults) TearDownSuite(c *C) { - s.dom.Close() - c.Assert(s.store.Close(), IsNil) - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testRuleReorderResults) runTestData(c *C, tk *testkit.TestKit, name string) { +func runTestData(t *testing.T, tk *testkit.TestKit, name string) { var input []string var output []struct { Plan []string } - s.testData.GetTestCasesByName(name, c, &input, &output) - c.Assert(len(input), Equals, len(output)) + statsSuiteData := plannercore.GetOrderedResultModeSuiteData() + statsSuiteData.GetTestCasesByName(name, t, &input, &output) + require.Equal(t, len(input), len(output)) for i := range input { - s.testData.OnRecord(func() { - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + input[i]).Rows()) + testdata.OnRecord(func() { + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + input[i]).Rows()) }) tk.MustQuery("explain " + input[i]).Check(testkit.Rows(output[i].Plan...)) } } -func (s *testRuleReorderResults) TestOrderedResultMode(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(`set tidb_opt_limit_push_down_threshold=0`) tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int primary key, b int, c int, d int, key(b))") - s.runTestData(c, tk, "TestOrderedResultMode") + runTestData(t, tk, "TestOrderedResultMode") } -func (s *testRuleReorderResults) TestOrderedResultModeOnDML(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultModeOnDML(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int primary key, b int, c int, key(b))") - s.runTestData(c, tk, "TestOrderedResultModeOnDML") + runTestData(t, tk, "TestOrderedResultModeOnDML") } -func (s *testRuleReorderResults) TestOrderedResultModeOnSubQuery(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultModeOnSubQuery(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") tk.MustExec("create table t1 (a int primary key, b int, c int, d int, key(b))") tk.MustExec("create table t2 (a int primary key, b int, c int, d int, key(b))") - s.runTestData(c, tk, "TestOrderedResultModeOnSubQuery") + runTestData(t, tk, "TestOrderedResultModeOnSubQuery") } -func (s *testRuleReorderResults) TestOrderedResultModeOnJoin(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultModeOnJoin(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") tk.MustExec("create table t1 (a int primary key, b int, c int, d int, key(b))") tk.MustExec("create table t2 (a int primary key, b int, c int, d int, key(b))") - s.runTestData(c, tk, "TestOrderedResultModeOnJoin") + runTestData(t, tk, "TestOrderedResultModeOnJoin") } -func (s *testRuleReorderResults) TestOrderedResultModeOnOtherOperators(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultModeOnOtherOperators(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set tidb_enable_ordered_result_mode=1") tk.MustExec("drop table if exists t1") tk.MustExec("drop table if exists t2") tk.MustExec("create table t1 (a int primary key, b int, c int, d int, unique key(b))") tk.MustExec("create table t2 (a int primary key, b int, c int, d int, unique key(b))") - s.runTestData(c, tk, "TestOrderedResultModeOnOtherOperators") + runTestData(t, tk, "TestOrderedResultModeOnOtherOperators") } -func (s *testRuleReorderResults) TestOrderedResultModeOnPartitionTable(c *C) { - tk := testkit.NewTestKit(c, s.store) +func TestOrderedResultModeOnPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec(fmt.Sprintf(`set tidb_partition_prune_mode='%v'`, variable.DefTiDBPartitionPruneMode)) tk.MustExec("set tidb_enable_ordered_result_mode=1") @@ -214,10 +200,14 @@ func (s *testRuleReorderResults) TestOrderedResultModeOnPartitionTable(c *C) { partition p2 values less than (300), partition p3 values less than (400))`) tk.MustQuery("select @@tidb_partition_prune_mode").Check(testkit.Rows("static")) - s.runTestData(c, tk, "TestOrderedResultModeOnPartitionTable") + runTestData(t, tk, "TestOrderedResultModeOnPartitionTable") } -func (s *testRuleReorderResults) TestStableResultSwitch(c *C) { - tk := testkit.NewTestKit(c, s.store) - c.Assert(len(tk.MustQuery("show variables where variable_name like 'tidb_enable_ordered_result_mode'").Rows()), Equals, 1) +func TestStableResultSwitch(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + rows := tk.MustQuery("show variables where variable_name like 'tidb_enable_ordered_result_mode'").Rows() + require.Len(t, rows, 1) } diff --git a/planner/core/rule_topn_push_down.go b/planner/core/rule_topn_push_down.go index e6234bbc3f3dc..ecbb30a9cb17b 100644 --- a/planner/core/rule_topn_push_down.go +++ b/planner/core/rule_topn_push_down.go @@ -15,7 +15,9 @@ package core import ( + "bytes" "context" + "fmt" "github.com/cznic/mathutil" "github.com/pingcap/tidb/expression" @@ -27,22 +29,22 @@ type pushDownTopNOptimizer struct { } func (s *pushDownTopNOptimizer) optimize(ctx context.Context, p LogicalPlan, opt *logicalOptimizeOp) (LogicalPlan, error) { - return p.pushDownTopN(nil), nil + return p.pushDownTopN(nil, opt), nil } -func (s *baseLogicalPlan) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (s *baseLogicalPlan) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { p := s.self for i, child := range p.Children() { - p.Children()[i] = child.pushDownTopN(nil) + p.Children()[i] = child.pushDownTopN(nil, opt) } if topN != nil { - return topN.setChild(p) + return topN.setChild(p, opt) } return p } // setChild set p as topn's child. -func (lt *LogicalTopN) setChild(p LogicalPlan) LogicalPlan { +func (lt *LogicalTopN) setChild(p LogicalPlan, opt *logicalOptimizeOp) LogicalPlan { // Remove this TopN if its child is a TableDual. dual, isDual := p.(*LogicalTableDual) if isDual { @@ -62,37 +64,42 @@ func (lt *LogicalTopN) setChild(p LogicalPlan) LogicalPlan { limitHints: lt.limitHints, }.Init(lt.ctx, lt.blockOffset) limit.SetChildren(p) + appendTopNPushDownTraceStep(limit, p, opt) return limit } // Then lt must be topN. lt.SetChildren(p) + appendTopNPushDownTraceStep(lt, p, opt) return lt } -func (ls *LogicalSort) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (ls *LogicalSort) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { if topN == nil { - return ls.baseLogicalPlan.pushDownTopN(nil) + return ls.baseLogicalPlan.pushDownTopN(nil, opt) } else if topN.isLimit() { topN.ByItems = ls.ByItems - return ls.children[0].pushDownTopN(topN) + appendSortPassByItemsTraceStep(ls, topN, opt) + return ls.children[0].pushDownTopN(topN, opt) } // If a TopN is pushed down, this sort is useless. - return ls.children[0].pushDownTopN(topN) + return ls.children[0].pushDownTopN(topN, opt) } -func (p *LogicalLimit) convertToTopN() *LogicalTopN { - return LogicalTopN{Offset: p.Offset, Count: p.Count, limitHints: p.limitHints}.Init(p.ctx, p.blockOffset) +func (p *LogicalLimit) convertToTopN(opt *logicalOptimizeOp) *LogicalTopN { + topn := LogicalTopN{Offset: p.Offset, Count: p.Count, limitHints: p.limitHints}.Init(p.ctx, p.blockOffset) + appendConvertTopNTraceStep(p, topn, opt) + return topn } -func (p *LogicalLimit) pushDownTopN(topN *LogicalTopN) LogicalPlan { - child := p.children[0].pushDownTopN(p.convertToTopN()) +func (p *LogicalLimit) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { + child := p.children[0].pushDownTopN(p.convertToTopN(opt), opt) if topN != nil { - return topN.setChild(child) + return topN.setChild(child, opt) } return child } -func (p *LogicalUnionAll) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (p *LogicalUnionAll) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { for i, child := range p.children { var newTopN *LogicalTopN if topN != nil { @@ -100,19 +107,21 @@ func (p *LogicalUnionAll) pushDownTopN(topN *LogicalTopN) LogicalPlan { for _, by := range topN.ByItems { newTopN.ByItems = append(newTopN.ByItems, &util.ByItems{Expr: by.Expr, Desc: by.Desc}) } + // newTopN to push down Union's child + appendNewTopNTraceStep(topN, p, opt) } - p.children[i] = child.pushDownTopN(newTopN) + p.children[i] = child.pushDownTopN(newTopN, opt) } if topN != nil { - return topN.setChild(p) + return topN.setChild(p, opt) } return p } -func (p *LogicalProjection) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (p *LogicalProjection) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { for _, expr := range p.Exprs { if expression.HasAssignSetVarFunc(expr) { - return p.baseLogicalPlan.pushDownTopN(topN) + return p.baseLogicalPlan.pushDownTopN(topN, opt) } } if topN != nil { @@ -128,28 +137,28 @@ func (p *LogicalProjection) pushDownTopN(topN *LogicalTopN) LogicalPlan { } } } - p.children[0] = p.children[0].pushDownTopN(topN) + p.children[0] = p.children[0].pushDownTopN(topN, opt) return p } -func (p *LogicalLock) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (p *LogicalLock) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { if topN != nil { - p.children[0] = p.children[0].pushDownTopN(topN) + p.children[0] = p.children[0].pushDownTopN(topN, opt) } return p.self } // pushDownTopNToChild will push a topN to one child of join. The idx stands for join child index. 0 is for left child. -func (p *LogicalJoin) pushDownTopNToChild(topN *LogicalTopN, idx int) LogicalPlan { +func (p *LogicalJoin) pushDownTopNToChild(topN *LogicalTopN, idx int, opt *logicalOptimizeOp) LogicalPlan { if topN == nil { - return p.children[idx].pushDownTopN(nil) + return p.children[idx].pushDownTopN(nil, opt) } for _, by := range topN.ByItems { cols := expression.ExtractColumns(by.Expr) for _, col := range cols { if !p.children[idx].Schema().Contains(col) { - return p.children[idx].pushDownTopN(nil) + return p.children[idx].pushDownTopN(nil, opt) } } } @@ -162,24 +171,25 @@ func (p *LogicalJoin) pushDownTopNToChild(topN *LogicalTopN, idx int) LogicalPla for i := range topN.ByItems { newTopN.ByItems[i] = topN.ByItems[i].Clone() } - return p.children[idx].pushDownTopN(newTopN) + appendTopNPushDownJoinTraceStep(p, newTopN, idx, opt) + return p.children[idx].pushDownTopN(newTopN, opt) } -func (p *LogicalJoin) pushDownTopN(topN *LogicalTopN) LogicalPlan { +func (p *LogicalJoin) pushDownTopN(topN *LogicalTopN, opt *logicalOptimizeOp) LogicalPlan { switch p.JoinType { case LeftOuterJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin: - p.children[0] = p.pushDownTopNToChild(topN, 0) - p.children[1] = p.children[1].pushDownTopN(nil) + p.children[0] = p.pushDownTopNToChild(topN, 0, opt) + p.children[1] = p.children[1].pushDownTopN(nil, opt) case RightOuterJoin: - p.children[1] = p.pushDownTopNToChild(topN, 1) - p.children[0] = p.children[0].pushDownTopN(nil) + p.children[1] = p.pushDownTopNToChild(topN, 1, opt) + p.children[0] = p.children[0].pushDownTopN(nil, opt) default: - return p.baseLogicalPlan.pushDownTopN(topN) + return p.baseLogicalPlan.pushDownTopN(topN, opt) } // The LogicalJoin may be also a LogicalApply. So we must use self to set parents. if topN != nil { - return topN.setChild(p.self) + return topN.setChild(p.self, opt) } return p.self } @@ -187,3 +197,83 @@ func (p *LogicalJoin) pushDownTopN(topN *LogicalTopN) LogicalPlan { func (*pushDownTopNOptimizer) name() string { return "topn_push_down" } + +func appendTopNPushDownTraceStep(parent LogicalPlan, child LogicalPlan, opt *logicalOptimizeOp) { + action := func() string { + return fmt.Sprintf("%v_%v is added as %v_%v's parent", parent.TP(), parent.ID(), child.TP(), child.ID()) + } + reason := func() string { + return fmt.Sprintf("%v is pushed down", parent.TP()) + } + opt.appendStepToCurrent(parent.ID(), parent.TP(), reason, action) +} + +func appendTopNPushDownJoinTraceStep(p *LogicalJoin, topN *LogicalTopN, idx int, opt *logicalOptimizeOp) { + action := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v is added and pushed into %v_%v's ", + topN.TP(), topN.ID(), p.TP(), p.ID())) + if idx == 0 { + buffer.WriteString("left ") + } else { + buffer.WriteString("right ") + } + buffer.WriteString("table") + return buffer.String() + } + reason := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v's joinType is %v, and all ByItems[", p.TP(), p.ID(), p.JoinType.String())) + for i, item := range topN.ByItems { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(item.String()) + } + buffer.WriteString("] contained in ") + if idx == 0 { + buffer.WriteString("left ") + } else { + buffer.WriteString("right ") + } + buffer.WriteString("table") + return buffer.String() + } + opt.appendStepToCurrent(p.ID(), p.TP(), reason, action) +} + +func appendSortPassByItemsTraceStep(sort *LogicalSort, topN *LogicalTopN, opt *logicalOptimizeOp) { + action := func() string { + buffer := bytes.NewBufferString(fmt.Sprintf("%v_%v passes ByItems[", sort.TP(), sort.ID())) + for i, item := range sort.ByItems { + if i > 0 { + buffer.WriteString(",") + } + buffer.WriteString(item.String()) + } + buffer.WriteString(fmt.Sprintf("] to %v_%v", topN.TP(), topN.ID())) + return buffer.String() + } + reason := func() string { + return fmt.Sprintf("%v_%v is Limit originally", topN.TP(), topN.ID()) + } + opt.appendStepToCurrent(sort.ID(), sort.TP(), reason, action) +} + +func appendNewTopNTraceStep(topN *LogicalTopN, union *LogicalUnionAll, opt *logicalOptimizeOp) { + reason := func() string { + return "" + } + action := func() string { + return fmt.Sprintf("%v_%v is added and pushed down across %v_%v", topN.TP(), topN.ID(), union.TP(), union.ID()) + } + opt.appendStepToCurrent(topN.ID(), topN.TP(), reason, action) +} + +func appendConvertTopNTraceStep(p LogicalPlan, topN *LogicalTopN, opt *logicalOptimizeOp) { + reason := func() string { + return "" + } + action := func() string { + return fmt.Sprintf("%v_%v is converted into %v_%v", p.TP(), p.ID(), topN.TP(), topN.ID()) + } + opt.appendStepToCurrent(topN.ID(), topN.TP(), reason, action) +} diff --git a/planner/core/show_predicate_extractor.go b/planner/core/show_predicate_extractor.go new file mode 100644 index 0000000000000..352b38b4f8b8c --- /dev/null +++ b/planner/core/show_predicate_extractor.go @@ -0,0 +1,169 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core + +import ( + "bytes" + "fmt" + "strings" + + "github.com/pingcap/tidb/parser/ast" + driver "github.com/pingcap/tidb/types/parser_driver" + "github.com/pingcap/tidb/util/stringutil" +) + +var ( + _ ShowPredicateExtractor = &ShowColumnsTableExtractor{} + _ ShowPredicateExtractor = &ShowTablesTableExtractor{} + _ ShowPredicateExtractor = &ShowVariablesExtractor{} +) + +// ShowPredicateExtractor is used to extract some predicates from `PatternLikeExpr` clause +// and push the predicates down to the data retrieving on reading memory table stage when use ShowStmt. +// +// e.g: +// SHOW COLUMNS FROM t LIKE '%abc%' +// We must request all components from the memory table, and filter the result by the PatternLikeExpr predicate. +// +// it is a way to fix https://github.com/pingcap/tidb/issues/29910. +type ShowPredicateExtractor interface { + // Extract predicates which can be pushed down and returns whether the extractor can extract predicates. + Extract(show *ast.ShowStmt) bool + explainInfo() string +} + +// ShowBaseExtractor is the definition of base extractor for derived predicates. +type ShowBaseExtractor struct { + Field string + + FieldPatterns string +} + +// Extract implements the ShowPredicateExtractor interface. +func (e *ShowBaseExtractor) Extract(show *ast.ShowStmt) bool { + if show.Pattern != nil && show.Pattern.Pattern != nil { + pattern := show.Pattern + switch pattern.Pattern.(type) { + case *driver.ValueExpr: + // It is used in `SHOW XXXX in t LIKE `abc``. + ptn := pattern.Pattern.(*driver.ValueExpr).GetString() + patValue, patTypes := stringutil.CompilePattern(ptn, pattern.Escape) + if stringutil.IsExactMatch(patTypes) { + e.Field = strings.ToLower(string(patValue)) + return true + } + e.FieldPatterns = strings.ToLower(string(patValue)) + return true + } + } + return false +} + +// ShowColumnsTableExtractor is used to extract some predicates of tables table. +type ShowColumnsTableExtractor struct { + ShowBaseExtractor +} + +// Extract implements the MemTablePredicateExtractor Extract interface +func (e *ShowColumnsTableExtractor) Extract(show *ast.ShowStmt) bool { + if show.Pattern != nil && show.Pattern.Pattern != nil { + pattern := show.Pattern + switch pattern.Pattern.(type) { + case *driver.ValueExpr: + // It is used in `SHOW COLUMNS FROM t LIKE `abc``. + ptn := pattern.Pattern.(*driver.ValueExpr).GetString() + patValue, patTypes := stringutil.CompilePattern(ptn, pattern.Escape) + if stringutil.IsExactMatch(patTypes) { + e.Field = strings.ToLower(string(patValue)) + return true + } + e.FieldPatterns = strings.ToLower(string(patValue)) + return true + case *ast.ColumnNameExpr: + // It is used in `SHOW COLUMNS FROM t LIKE abc`. + // MySQL do not support this syntax and return the error. + return false + } + } else if show.Column != nil && show.Column.Name.L != "" { + // it is used in `DESCRIBE t COLUMN`. + e.Field = show.Column.Name.L + return true + } + return false +} + +func (e *ShowColumnsTableExtractor) explainInfo() string { + r := new(bytes.Buffer) + if len(e.Field) > 0 { + r.WriteString(fmt.Sprintf("field:[%s], ", e.Field)) + } + + if len(e.FieldPatterns) > 0 { + r.WriteString(fmt.Sprintf("field_pattern:[%s], ", e.FieldPatterns)) + } + + // remove the last ", " in the message info + s := r.String() + if len(s) > 2 { + return s[:len(s)-2] + } + return s +} + +// ShowTablesTableExtractor is used to extract some predicates of tables. +type ShowTablesTableExtractor struct { + ShowBaseExtractor +} + +func (e *ShowTablesTableExtractor) explainInfo() string { + r := new(bytes.Buffer) + if len(e.Field) > 0 { + r.WriteString(fmt.Sprintf("table:[%s], ", e.Field)) + } + + if len(e.FieldPatterns) > 0 { + r.WriteString(fmt.Sprintf("table_pattern:[%s], ", e.FieldPatterns)) + } + + // remove the last ", " in the message info + s := r.String() + if len(s) > 2 { + return s[:len(s)-2] + } + return s +} + +// ShowVariablesExtractor is used to extract some predicates of variables. +type ShowVariablesExtractor struct { + ShowBaseExtractor +} + +func (e *ShowVariablesExtractor) explainInfo() string { + r := new(bytes.Buffer) + if len(e.Field) > 0 { + r.WriteString(fmt.Sprintf("variable:[%s], ", e.Field)) + } + + if len(e.FieldPatterns) > 0 { + r.WriteString(fmt.Sprintf("variable_pattern:[%s], ", e.FieldPatterns)) + } + + // remove the last ", " in the message info + s := r.String() + if len(s) > 2 { + return s[:len(s)-2] + } + return s +} diff --git a/planner/core/stats.go b/planner/core/stats.go index d3f23427b2f40..7613ffdb6837c 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -315,8 +316,8 @@ func (ds *DataSource) derivePathStatsAndTryHeuristics() error { for _, singleScanIdx := range singleScanIdxs { col2Len := singleScanIdx.GetCol2LenFromAccessConds() for _, uniqueIdxCol2Len := range uniqueIdxAccessCols { - accessResult, comparable := util.CompareCol2Len(col2Len, uniqueIdxCol2Len) - if comparable && accessResult == 1 { + accessResult, comparable1 := util.CompareCol2Len(col2Len, uniqueIdxCol2Len) + if comparable1 && accessResult == 1 { if refinedBest == nil || len(singleScanIdx.Ranges) < len(refinedBest.Ranges) { refinedBest = singleScanIdx } @@ -409,9 +410,20 @@ func (ds *DataSource) DeriveStats(childStats []*property.StatsInfo, selfSchema * } // Consider the IndexMergePath. Now, we just generate `IndexMergePath` in DNF case. - isPossibleIdxMerge := len(ds.pushedDownConds) > 0 && len(ds.possibleAccessPaths) > 1 - sessionAndStmtPermission := (ds.ctx.GetSessionVars().GetEnableIndexMerge() || len(ds.indexMergeHints) > 0) && !ds.ctx.GetSessionVars().StmtCtx.NoIndexMergeHint - // If there is an index path, we current do not consider `IndexMergePath`. + // Use allConds instread of pushedDownConds, + // because we want to use IndexMerge even if some expr cannot be pushed to TiKV. + // We will create new Selection for exprs that cannot be pushed in convertToIndexMergeScan. + indexMergeConds := make([]expression.Expression, 0, len(ds.allConds)) + for _, expr := range ds.allConds { + indexMergeConds = append(indexMergeConds, expression.PushDownNot(ds.ctx, expr)) + } + + stmtCtx := ds.ctx.GetSessionVars().StmtCtx + isPossibleIdxMerge := len(indexMergeConds) > 0 && len(ds.possibleAccessPaths) > 1 + sessionAndStmtPermission := (ds.ctx.GetSessionVars().GetEnableIndexMerge() || len(ds.indexMergeHints) > 0) && !stmtCtx.NoIndexMergeHint + // We current do not consider `IndexMergePath`: + // 1. If there is an index path. + // 2. TODO: If there exists exprs that cannot be pushed down. This is to avoid wrongly estRow of Selection added by rule_predicate_push_down. needConsiderIndexMerge := true if len(ds.indexMergeHints) == 0 { for i := 1; i < len(ds.possibleAccessPaths); i++ { @@ -420,24 +432,42 @@ func (ds *DataSource) DeriveStats(childStats []*property.StatsInfo, selfSchema * break } } + if needConsiderIndexMerge { + // PushDownExprs() will append extra warnings, which is annoying. So we reset warnings here. + warnings := stmtCtx.GetWarnings() + _, remaining := expression.PushDownExprs(stmtCtx, indexMergeConds, ds.ctx.GetClient(), kv.UnSpecified) + stmtCtx.SetWarnings(warnings) + if len(remaining) != 0 { + needConsiderIndexMerge = false + } + } } - readFromTableCache := ds.ctx.GetSessionVars().StmtCtx.ReadFromTableCache - if isPossibleIdxMerge && sessionAndStmtPermission && needConsiderIndexMerge && ds.tableInfo.TempTableType != model.TempTableLocal && !readFromTableCache { - err := ds.generateAndPruneIndexMergePath(ds.indexMergeHints != nil) + if isPossibleIdxMerge && sessionAndStmtPermission && needConsiderIndexMerge && ds.tableInfo.TempTableType != model.TempTableLocal { + err := ds.generateAndPruneIndexMergePath(indexMergeConds, ds.indexMergeHints != nil) if err != nil { return nil, err } } else if len(ds.indexMergeHints) > 0 { ds.indexMergeHints = nil - ds.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("IndexMerge is inapplicable or disabled")) + var msg string + if !isPossibleIdxMerge { + msg = "No available filter or available index." + } else if !sessionAndStmtPermission { + msg = "Got no_index_merge hint or tidb_enable_index_merge is off." + } else if ds.tableInfo.TempTableType == model.TempTableLocal { + msg = "Cannot use IndexMerge on temporary table." + } + msg = fmt.Sprintf("IndexMerge is inapplicable or disabled. %s", msg) + stmtCtx.AppendWarning(errors.Errorf(msg)) + logutil.BgLogger().Debug(msg) } return ds.stats, nil } -func (ds *DataSource) generateAndPruneIndexMergePath(needPrune bool) error { +func (ds *DataSource) generateAndPruneIndexMergePath(indexMergeConds []expression.Expression, needPrune bool) error { regularPathCount := len(ds.possibleAccessPaths) - err := ds.generateIndexMergeOrPaths() + err := ds.generateIndexMergeOrPaths(indexMergeConds) if err != nil { return err } @@ -448,12 +478,22 @@ func (ds *DataSource) generateAndPruneIndexMergePath(needPrune bool) error { // With hints and without generated IndexMerge paths if regularPathCount == len(ds.possibleAccessPaths) { ds.indexMergeHints = nil - ds.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("IndexMerge is inapplicable or disabled")) + ds.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("IndexMerge is inapplicable")) return nil } // Do not need to consider the regular paths in find_best_task(). + // So we can use index merge's row count as DataSource's row count. if needPrune { ds.possibleAccessPaths = ds.possibleAccessPaths[regularPathCount:] + minRowCount := ds.possibleAccessPaths[0].CountAfterAccess + for _, path := range ds.possibleAccessPaths { + if minRowCount < path.CountAfterAccess { + minRowCount = path.CountAfterAccess + } + } + if ds.stats.RowCount > minRowCount { + ds.stats = ds.tableStats.ScaleByExpectCnt(minRowCount) + } } return nil } @@ -510,9 +550,9 @@ func (is *LogicalIndexScan) DeriveStats(childStats []*property.StatsInfo, selfSc } // getIndexMergeOrPath generates all possible IndexMergeOrPaths. -func (ds *DataSource) generateIndexMergeOrPaths() error { +func (ds *DataSource) generateIndexMergeOrPaths(filters []expression.Expression) error { usedIndexCount := len(ds.possibleAccessPaths) - for i, cond := range ds.pushedDownConds { + for i, cond := range filters { sf, ok := cond.(*expression.ScalarFunction) if !ok || sf.FuncName.L != ast.LogicOr { continue @@ -548,7 +588,7 @@ func (ds *DataSource) generateIndexMergeOrPaths() error { continue } if len(partialPaths) > 1 { - possiblePath := ds.buildIndexMergeOrPath(partialPaths, i) + possiblePath := ds.buildIndexMergeOrPath(filters, partialPaths, i) if possiblePath == nil { return nil } @@ -686,16 +726,29 @@ func (ds *DataSource) buildIndexMergePartialPath(indexAccessPaths []*util.Access } // buildIndexMergeOrPath generates one possible IndexMergePath. -func (ds *DataSource) buildIndexMergeOrPath(partialPaths []*util.AccessPath, current int) *util.AccessPath { +func (ds *DataSource) buildIndexMergeOrPath(filters []expression.Expression, partialPaths []*util.AccessPath, current int) *util.AccessPath { indexMergePath := &util.AccessPath{PartialIndexPaths: partialPaths} - indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[:current]...) - indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[current+1:]...) + indexMergePath.TableFilters = append(indexMergePath.TableFilters, filters[:current]...) + indexMergePath.TableFilters = append(indexMergePath.TableFilters, filters[current+1:]...) + var addCurrentFilter bool for _, path := range partialPaths { // If any partial path contains table filters, we need to keep the whole DNF filter in the Selection. if len(path.TableFilters) > 0 { - indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[current]) - break + addCurrentFilter = true + } + // If any partial path's index filter cannot be pushed to TiKV, we should keep the whole DNF filter. + if len(path.IndexFilters) != 0 && !expression.CanExprsPushDown(ds.ctx.GetSessionVars().StmtCtx, path.IndexFilters, ds.ctx.GetClient(), kv.TiKV) { + addCurrentFilter = true + // Clear IndexFilter, the whole filter will be put in indexMergePath.TableFilters. + path.IndexFilters = nil } + if len(path.TableFilters) != 0 && !expression.CanExprsPushDown(ds.ctx.GetSessionVars().StmtCtx, path.TableFilters, ds.ctx.GetClient(), kv.TiKV) { + addCurrentFilter = true + path.TableFilters = nil + } + } + if addCurrentFilter { + indexMergePath.TableFilters = append(indexMergePath.TableFilters, filters[current]) } return indexMergePath } @@ -1205,6 +1258,13 @@ func (p *LogicalCTE) DeriveStats(childStats []*property.StatsInfo, selfSchema *e var err error if p.cte.seedPartPhysicalPlan == nil { + // Build push-downed predicates. + if len(p.cte.pushDownPredicates) > 0 { + newCond := expression.ComposeDNFCondition(p.ctx, p.cte.pushDownPredicates...) + newSel := LogicalSelection{Conditions: []expression.Expression{newCond}}.Init(p.SCtx(), p.cte.seedPartLogicalPlan.SelectBlockOffset()) + newSel.SetChildren(p.cte.seedPartLogicalPlan) + p.cte.seedPartLogicalPlan = newSel + } p.cte.seedPartPhysicalPlan, _, err = DoOptimize(context.TODO(), p.ctx, p.cte.optFlag, p.cte.seedPartLogicalPlan) if err != nil { return nil, err diff --git a/planner/core/stats_test.go b/planner/core/stats_test.go index 0485083f99d3b..2959aae593e08 100644 --- a/planner/core/stats_test.go +++ b/planner/core/stats_test.go @@ -16,44 +16,22 @@ package core_test import ( "context" + "fmt" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/planner/property" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testdata" "github.com/pingcap/tidb/util/hint" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" + "github.com/stretchr/testify/require" ) -var _ = Suite(&testStatsSuite{}) - -type testStatsSuite struct { - *parser.Parser - testData testutil.TestData -} - -func (s *testStatsSuite) SetUpSuite(c *C) { - s.Parser = parser.New() - s.Parser.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) - - var err error - s.testData, err = testutil.LoadTestSuiteData("testdata", "stats_suite") - c.Assert(err, IsNil) -} - -func (s *testStatsSuite) TearDownSuite(c *C) { - c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil) -} - -func (s *testStatsSuite) TestGroupNDVs(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestGroupNDVs(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int not null, b int not null, key(a,b))") @@ -64,29 +42,31 @@ func (s *testStatsSuite) TestGroupNDVs(c *C) { tk.MustExec("analyze table t2") ctx := context.Background() + p := parser.New() var input []string var output []struct { SQL string AggInput string JoinInput string } - s.testData.GetTestCases(c, &input, &output) + statsSuiteData := core.GetStatsSuiteData() + statsSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - comment := Commentf("case:%v sql: %s", i, tt) - stmt, err := s.ParseOneStmt(tt, "", "") - c.Assert(err, IsNil, comment) + comment := fmt.Sprintf("case:%v sql: %s", i, tt) + stmt, err := p.ParseOneStmt(tt, "", "") + require.NoError(t, err, comment) ret := &core.PreprocessorReturn{} - err = core.Preprocess(tk.Se, stmt, core.WithPreprocessorReturn(ret)) - c.Assert(err, IsNil) - tk.Se.GetSessionVars().PlanColumnID = 0 - builder, _ := core.NewPlanBuilder().Init(tk.Se, ret.InfoSchema, &hint.BlockHintProcessor{}) + err = core.Preprocess(tk.Session(), stmt, core.WithPreprocessorReturn(ret)) + require.NoError(t, err) + tk.Session().GetSessionVars().PlanColumnID = 0 + builder, _ := core.NewPlanBuilder().Init(tk.Session(), ret.InfoSchema, &hint.BlockHintProcessor{}) p, err := builder.Build(ctx, stmt) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) p, err = core.LogicalOptimize(ctx, builder.GetOptFlag(), p.(core.LogicalPlan)) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) lp := p.(core.LogicalPlan) _, err = core.RecursiveDeriveStats4Test(lp) - c.Assert(err, IsNil, comment) + require.NoError(t, err, comment) var agg *core.LogicalAggregation var join *core.LogicalJoin stack := make([]core.LogicalPlan, 0, 2) @@ -130,24 +110,20 @@ func (s *testStatsSuite) TestGroupNDVs(c *C) { r := core.GetStats4Test(join.Children()[1]) joinInput = property.ToString(l.GroupNDVs) + ";" + property.ToString(r.GroupNDVs) } - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt output[i].AggInput = aggInput output[i].JoinInput = joinInput }) - c.Assert(aggInput, Equals, output[i].AggInput, comment) - c.Assert(joinInput, Equals, output[i].JoinInput, comment) + require.Equal(t, output[i].AggInput, aggInput, comment) + require.Equal(t, output[i].JoinInput, joinInput, comment) } } -func (s *testStatsSuite) TestNDVGroupCols(c *C) { - store, dom, err := newStoreWithBootstrap() - c.Assert(err, IsNil) - defer func() { - dom.Close() - store.Close() - }() - tk := testkit.NewTestKit(c, store) +func TestNDVGroupCols(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int not null, b int not null, key(a,b))") @@ -162,11 +138,12 @@ func (s *testStatsSuite) TestNDVGroupCols(c *C) { SQL string Plan []string } - s.testData.GetTestCases(c, &input, &output) + statsSuiteData := core.GetStatsSuiteData() + statsSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { - s.testData.OnRecord(func() { + testdata.OnRecord(func() { output[i].SQL = tt - output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) }) // The test point is the row count estimation for aggregations and joins. tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) diff --git a/planner/core/stringer.go b/planner/core/stringer.go index ce41a53bf66c8..3679b92ce777c 100644 --- a/planner/core/stringer.go +++ b/planner/core/stringer.go @@ -28,6 +28,15 @@ func ToString(p Plan) string { return strings.Join(strs, "->") } +// FDToString explains fd transfer over a Plan, returns description string. +func FDToString(p LogicalPlan) string { + strs, _ := fdToString(p, []string{}, []int{}) + for i, j := 0, len(strs)-1; i < j; i, j = i+1, j-1 { + strs[i], strs[j] = strs[j], strs[i] + } + return strings.Join(strs, " >>> ") +} + func needIncludeChildrenString(plan Plan) bool { switch x := plan.(type) { case *LogicalUnionAll, *PhysicalUnionAll, *LogicalPartitionUnionAll: @@ -43,6 +52,29 @@ func needIncludeChildrenString(plan Plan) bool { } } +func fdToString(in LogicalPlan, strs []string, idxs []int) ([]string, []int) { + switch x := in.(type) { + case *LogicalProjection: + strs = append(strs, "{"+x.fdSet.String()+"}") + for _, child := range x.Children() { + strs, idxs = fdToString(child, strs, idxs) + } + case *LogicalAggregation: + strs = append(strs, "{"+x.fdSet.String()+"}") + for _, child := range x.Children() { + strs, idxs = fdToString(child, strs, idxs) + } + case *DataSource: + strs = append(strs, "{"+x.fdSet.String()+"}") + case *LogicalApply: + strs = append(strs, "{"+x.fdSet.String()+"}") + case *LogicalJoin: + strs = append(strs, "{"+x.fdSet.String()+"}") + default: + } + return strs, idxs +} + func toString(in Plan, strs []string, idxs []int) ([]string, []int) { switch x := in.(type) { case LogicalPlan: @@ -132,8 +164,16 @@ func toString(in Plan, strs []string, idxs []int) ([]string, []int) { str = "Lock" case *ShowDDL: str = "ShowDDL" - case *LogicalShow, *PhysicalShow: + case *LogicalShow: + str = "Show" + if pl := in.(*LogicalShow); pl.Extractor != nil { + str = str + "(" + pl.Extractor.explainInfo() + ")" + } + case *PhysicalShow: str = "Show" + if pl := in.(*PhysicalShow); pl.Extractor != nil { + str = str + "(" + pl.Extractor.explainInfo() + ")" + } case *LogicalShowDDLJobs, *PhysicalShowDDLJobs: str = "ShowDDLJobs" case *LogicalSort, *PhysicalSort: diff --git a/planner/core/stringer_test.go b/planner/core/stringer_test.go new file mode 100644 index 0000000000000..6433ad59b158c --- /dev/null +++ b/planner/core/stringer_test.go @@ -0,0 +1,88 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core_test + +import ( + "context" + "testing" + + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/hint" + "github.com/stretchr/testify/require" +) + +func TestPlanStringer(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, c int, index idx(a))") + tests := []struct { + sql string + plan string + }{ + { + sql: "show columns from t like 'a'", + plan: "Show(field:[a])", + }, + { + sql: "show columns from t like 'a%'", + plan: "Show(field_pattern:[a%])", + }, + { + sql: "show columns from t where field = 'a'", + plan: "Show->Sel([eq(Column#13, a)])->Projection", + }, + { + sql: "desc t", + plan: "Show", + }, + { + sql: "desc t a", + plan: "Show(field:[a])", + }, + { + sql: "show tables in test like 't'", + plan: "Show(table:[t])", + }, + { + sql: "show tables in test like 'T'", + plan: "Show(table:[t])", + }, + { + sql: "show tables in test like 't%'", + plan: "Show(table_pattern:[t%])", + }, + { + sql: "show tables in test like '%T%'", + plan: "Show(table_pattern:[%t%])", + }, + } + parser := parser.New() + for _, tt := range tests { + stmt, err := parser.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, "for %s", tt.sql) + ret := &core.PreprocessorReturn{} + builder, _ := core.NewPlanBuilder().Init(tk.Session(), ret.InfoSchema, &hint.BlockHintProcessor{}) + p, err := builder.Build(context.TODO(), stmt) + require.NoError(t, err, "for %s", tt.sql) + p, err = core.LogicalOptimize(context.TODO(), builder.GetOptFlag(), p.(core.LogicalPlan)) + require.NoError(t, err, "for %s", tt.sql) + require.Equal(t, tt.plan, core.ToString(p)) + } +} diff --git a/planner/core/task.go b/planner/core/task.go index 187140c613aa5..d8ab2369214e3 100644 --- a/planner/core/task.go +++ b/planner/core/task.go @@ -35,6 +35,7 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/paging" "github.com/pingcap/tidb/util/plancodec" "github.com/pingcap/tipb/go-tipb" "go.uber.org/zap" @@ -89,6 +90,10 @@ type copTask struct { // For table partition. partitionInfo PartitionInfo + + // expectCnt is the expected row count of upper task, 0 for unlimited. + // It's used for deciding whether using paging distsql. + expectCnt uint64 } func (t *copTask) invalid() bool { @@ -167,15 +172,22 @@ func (t *copTask) finishIndexPlan() { } // Network cost of transferring rows of index scan to TiDB. t.cst += cnt * sessVars.GetNetworkFactor(tableInfo) * t.tblColHists.GetAvgRowSize(t.indexPlan.SCtx(), t.indexPlan.Schema().Columns, true, false) + + // net seek cost + var p PhysicalPlan + for p = t.indexPlan; len(p.Children()) > 0; p = p.Children()[0] { + } + is := p.(*PhysicalIndexScan) + if !is.underInnerIndexJoin { // no need to accumulate seek cost for IndexJoin + t.cst += float64(len(is.Ranges)) * sessVars.GetSeekFactor(is.Table) // net seek cost + } + if t.tablePlan == nil { return } // Calculate the IO cost of table scan here because we cannot know its stats until we finish index plan. - var p PhysicalPlan - for p = t.indexPlan; len(p.Children()) > 0; p = p.Children()[0] { - } - rowSize := t.tblColHists.GetIndexAvgRowSize(t.indexPlan.SCtx(), t.tblCols, p.(*PhysicalIndexScan).Index.Unique) + rowSize := t.tblColHists.GetIndexAvgRowSize(t.indexPlan.SCtx(), t.tblCols, is.Index.Unique) t.cst += cnt * rowSize * sessVars.GetScanFactor(tableInfo) } @@ -204,6 +216,20 @@ func (p *basePhysicalPlan) attach2Task(tasks ...task) task { func (p *PhysicalUnionScan) attach2Task(tasks ...task) task { p.cost = tasks[0].cost() + // We need to pull the projection under unionScan upon unionScan. + // Since the projection only prunes columns, it's ok the put it upon unionScan. + if sel, ok := tasks[0].plan().(*PhysicalSelection); ok { + if pj, ok := sel.children[0].(*PhysicalProjection); ok { + // Convert unionScan->selection->projection to projection->unionScan->selection. + sel.SetChildren(pj.children...) + p.SetChildren(sel) + p.stats = tasks[0].plan().statsInfo() + rt, _ := tasks[0].(*rootTask) + rt.p = p + pj.SetChildren(p) + return pj.attach2Task(tasks...) + } + } if pj, ok := tasks[0].plan().(*PhysicalProjection); ok { // Convert unionScan->projection to projection->unionScan, because unionScan can't handle projection as its children. p.SetChildren(pj.children...) @@ -423,16 +449,15 @@ func (p *PhysicalIndexJoin) attach2Task(tasks ...task) task { } t := &rootTask{ p: p, - cst: p.GetCost(outerTask, innerTask), + cst: p.GetCost(outerTask.count(), innerTask.count(), outerTask.cost(), innerTask.cost()), } p.cost = t.cost() return t } // GetCost computes the cost of index join operator and its children. -func (p *PhysicalIndexJoin) GetCost(outerTask, innerTask task) float64 { +func (p *PhysicalIndexJoin) GetCost(outerCnt, innerCnt float64, outerCost, innerCost float64) float64 { var cpuCost float64 - outerCnt, innerCnt := outerTask.count(), innerTask.count() sessVars := p.ctx.GetSessionVars() // Add the cost of evaluating outer filter, since inner filter of index join // is always empty, we can simply tell whether outer filter is empty using the @@ -475,8 +500,8 @@ func (p *PhysicalIndexJoin) GetCost(outerTask, innerTask task) float64 { // since the executor is pipelined and not all workers are always in full load. memoryCost := innerConcurrency * (batchSize * distinctFactor) * innerCnt * sessVars.MemoryFactor // Cost of inner child plan, i.e, mainly I/O and network cost. - innerPlanCost := outerCnt * innerTask.cost() - return outerTask.cost() + innerPlanCost + cpuCost + memoryCost + innerPlanCost := outerCnt * innerCost + return outerCost + innerPlanCost + cpuCost + memoryCost } func getAvgRowSize(stats *property.StatsInfo, schema *expression.Schema) (size float64) { @@ -740,7 +765,7 @@ func (p *PhysicalHashJoin) convertPartitionKeysIfNeed(lTask, rTask *mppTask) (*m if lChanged { nlTask := lTask.copy().(*mppTask) nlTask.p = lProj - nlTask = nlTask.enforceExchangerImpl(&property.PhysicalProperty{ + nlTask = nlTask.enforceExchanger(&property.PhysicalProperty{ TaskTp: property.MppTaskType, MPPPartitionTp: property.HashType, MPPPartitionCols: lPartKeys, @@ -752,7 +777,7 @@ func (p *PhysicalHashJoin) convertPartitionKeysIfNeed(lTask, rTask *mppTask) (*m if rChanged { nrTask := rTask.copy().(*mppTask) nrTask.p = rProj - nrTask = nrTask.enforceExchangerImpl(&property.PhysicalProperty{ + nrTask = nrTask.enforceExchanger(&property.PhysicalProperty{ TaskTp: property.MppTaskType, MPPPartitionTp: property.HashType, MPPPartitionCols: rPartKeys, @@ -897,27 +922,30 @@ func (p *PhysicalMergeJoin) attach2Task(tasks ...task) task { return t } -func buildIndexLookUpTask(ctx sessionctx.Context, t *copTask) *rootTask { - newTask := &rootTask{cst: t.cst} +// GetCost computes cost of index lookup operator itself. +func (p *PhysicalIndexLookUpReader) GetCost() (cost float64) { + indexPlan, tablePlan := p.indexPlan, p.tablePlan + ctx := p.ctx sessVars := ctx.GetSessionVars() - p := PhysicalIndexLookUpReader{ - tablePlan: t.tablePlan, - indexPlan: t.indexPlan, - ExtraHandleCol: t.extraHandleCol, - CommonHandleCols: t.commonHandleCols, - }.Init(ctx, t.tablePlan.SelectBlockOffset()) - p.PartitionInfo = t.partitionInfo - setTableScanToTableRowIDScan(p.tablePlan) - p.stats = t.tablePlan.statsInfo() // Add cost of building table reader executors. Handles are extracted in batch style, // each handle is a range, the CPU cost of building copTasks should be: // (indexRows / batchSize) * batchSize * CPUFactor // Since we don't know the number of copTasks built, ignore these network cost now. - indexRows := t.indexPlan.statsInfo().RowCount - newTask.cst += indexRows * sessVars.CPUFactor + indexRows := indexPlan.statsInfo().RowCount + idxCst := indexRows * sessVars.CPUFactor + // if the expectCnt is below the paging threshold, using paging API, recalculate idxCst. + // paging API reduces the count of index and table rows, however introduces more seek cost. + if ctx.GetSessionVars().EnablePaging && p.expectedCnt > 0 && p.expectedCnt <= paging.Threshold { + p.Paging = true + pagingCst := calcPagingCost(ctx, p.indexPlan, p.expectedCnt) + // prevent enlarging the cost because we take paging as a better plan, + // if the cost is enlarged, it'll be easier to go another plan. + idxCst = math.Min(idxCst, pagingCst) + } + cost += idxCst // Add cost of worker goroutines in index lookup. numTblWorkers := float64(sessVars.IndexLookupConcurrency()) - newTask.cst += (numTblWorkers + 1) * sessVars.ConcurrencyFactor + cost += (numTblWorkers + 1) * sessVars.ConcurrencyFactor // When building table reader executor for each batch, we would sort the handles. CPU // cost of sort is: // CPUFactor * batchSize * Log2(batchSize) * (indexRows / batchSize) @@ -925,20 +953,48 @@ func buildIndexLookUpTask(ctx sessionctx.Context, t *copTask) *rootTask { batchSize := math.Min(indexLookupSize, indexRows) if batchSize > 2 { sortCPUCost := (indexRows * math.Log2(batchSize) * sessVars.CPUFactor) / numTblWorkers - newTask.cst += sortCPUCost + cost += sortCPUCost } // Also, we need to sort the retrieved rows if index lookup reader is expected to return // ordered results. Note that row count of these two sorts can be different, if there are // operators above table scan. - tableRows := t.tablePlan.statsInfo().RowCount + tableRows := tablePlan.statsInfo().RowCount selectivity := tableRows / indexRows batchSize = math.Min(indexLookupSize*selectivity, tableRows) - if t.keepOrder && batchSize > 2 { + if p.keepOrder && batchSize > 2 { sortCPUCost := (tableRows * math.Log2(batchSize) * sessVars.CPUFactor) / numTblWorkers - newTask.cst += sortCPUCost + cost += sortCPUCost } + return +} + +func buildIndexLookUpTask(ctx sessionctx.Context, t *copTask) *rootTask { + newTask := &rootTask{cst: t.cst} + p := PhysicalIndexLookUpReader{ + tablePlan: t.tablePlan, + indexPlan: t.indexPlan, + ExtraHandleCol: t.extraHandleCol, + CommonHandleCols: t.commonHandleCols, + expectedCnt: t.expectCnt, + keepOrder: t.keepOrder, + }.Init(ctx, t.tablePlan.SelectBlockOffset()) + p.PartitionInfo = t.partitionInfo + setTableScanToTableRowIDScan(p.tablePlan) + p.stats = t.tablePlan.statsInfo() + newTask.cst += p.GetCost() p.cost = newTask.cst - if t.needExtraProj { + + // Do not inject the extra Projection even if t.needExtraProj is set, or the schema between the phase-1 agg and + // the final agg would be broken. Please reference comments for the similar logic in + // (*copTask).convertToRootTaskImpl() for the PhysicalTableReader case. + // We need to refactor these logics. + aggPushedDown := false + switch p.tablePlan.(type) { + case *PhysicalHashAgg, *PhysicalStreamAgg: + aggPushedDown = true + } + + if t.needExtraProj && !aggPushedDown { schema := t.originSchema proj := PhysicalProjection{Exprs: expression.Column2Exprs(schema.Columns)}.Init(ctx, p.stats, t.tablePlan.SelectBlockOffset(), nil) proj.SetSchema(schema) @@ -951,6 +1007,40 @@ func buildIndexLookUpTask(ctx sessionctx.Context, t *copTask) *rootTask { return newTask } +func extractRows(p PhysicalPlan) float64 { + f := float64(0) + for _, c := range p.Children() { + if len(c.Children()) != 0 { + f += extractRows(c) + } else { + f += c.statsInfo().RowCount + } + } + return f +} + +// calcPagingCost calculates the cost for paging processing which may increase the seekCnt and reduce scanned rows. +func calcPagingCost(ctx sessionctx.Context, indexPlan PhysicalPlan, expectCnt uint64) float64 { + sessVars := ctx.GetSessionVars() + indexRows := indexPlan.StatsCount() + sourceRows := extractRows(indexPlan) + // with paging, the scanned rows is always less than or equal to source rows. + if uint64(sourceRows) < expectCnt { + expectCnt = uint64(sourceRows) + } + seekCnt := paging.CalculateSeekCnt(expectCnt) + indexSelectivity := float64(1) + if sourceRows > indexRows { + indexSelectivity = indexRows / sourceRows + } + pagingCst := seekCnt*sessVars.GetSeekFactor(nil) + float64(expectCnt)*sessVars.CPUFactor + pagingCst *= indexSelectivity + + // we want the diff between idxCst and pagingCst here, + // however, the idxCst does not contain seekFactor, so a seekFactor needs to be removed + return pagingCst - sessVars.GetSeekFactor(nil) +} + func (t *rootTask) convertToRootTask(_ sessionctx.Context) *rootTask { return t.copy().(*rootTask) } @@ -968,10 +1058,9 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { // the number of regions involved, we simply use DistSQLScanConcurrency. copIterWorkers := float64(t.plan().SCtx().GetSessionVars().DistSQLScanConcurrency()) t.finishIndexPlan() - needExtraProj := false - var prevSchema *expression.Schema // Network cost of transferring rows of table scan to TiDB. if t.tablePlan != nil { + // net I/O cost t.cst += t.count() * sessVars.GetNetworkFactor(nil) * t.tblColHists.GetAvgRowSize(ctx, t.tablePlan.Schema().Columns, false, false) tp := t.tablePlan @@ -984,12 +1073,24 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { } } ts := tp.(*PhysicalTableScan) + + // net seek cost + if !ts.underInnerIndexJoin { // no need to accumulate net seek cost for IndexJoin + switch ts.StoreType { + case kv.TiKV: + t.cst += float64(len(ts.Ranges)) * sessVars.GetSeekFactor(ts.Table) + case kv.TiFlash: + t.cst += float64(len(ts.Ranges)) * float64(len(ts.Columns)) * sessVars.GetSeekFactor(ts.Table) + } + } + prevColumnLen := len(ts.Columns) - prevSchema = ts.schema.Clone() + prevSchema := ts.schema.Clone() ts.Columns = ExpandVirtualColumn(ts.Columns, ts.schema, ts.Table.Columns) - if len(ts.Columns) > prevColumnLen { + if !t.needExtraProj && len(ts.Columns) > prevColumnLen { // Add an projection to make sure not to output extract columns. - needExtraProj = true + t.needExtraProj = true + t.originSchema = prevSchema } } t.cst /= copIterWorkers @@ -1005,6 +1106,7 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { setTableScanToTableRowIDScan(p.tablePlan) newTask.p = p p.cost = newTask.cost() + t.handleRootTaskConds(ctx, newTask) if t.needExtraProj { schema := t.originSchema proj := PhysicalProjection{Exprs: expression.Column2Exprs(schema.Columns)}.Init(ctx, p.stats, t.idxMergePartPlans[0].SelectBlockOffset(), nil) @@ -1055,9 +1157,9 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { aggPushedDown = true } - if needExtraProj && !aggPushedDown { - proj := PhysicalProjection{Exprs: expression.Column2Exprs(prevSchema.Columns)}.Init(ts.ctx, ts.stats, ts.SelectBlockOffset(), nil) - proj.SetSchema(prevSchema) + if t.needExtraProj && !aggPushedDown { + proj := PhysicalProjection{Exprs: expression.Column2Exprs(t.originSchema.Columns)}.Init(ts.ctx, ts.stats, ts.SelectBlockOffset(), nil) + proj.SetSchema(t.originSchema) proj.SetChildren(p) proj.cost = t.cost() newTask.p = proj @@ -1066,6 +1168,11 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { } } + t.handleRootTaskConds(ctx, newTask) + return newTask +} + +func (t *copTask) handleRootTaskConds(ctx sessionctx.Context, newTask *rootTask) { if len(t.rootTaskConds) > 0 { selectivity, _, err := t.tblColHists.Selectivity(ctx, t.rootTaskConds, nil) if err != nil { @@ -1077,8 +1184,6 @@ func (t *copTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { newTask.p = sel sel.cost = newTask.cost() } - - return newTask } // setTableScanToTableRowIDScan is to update the isChildOfIndexLookUp attribute of PhysicalTableScan child @@ -1522,11 +1627,13 @@ type AggInfo struct { // BuildFinalModeAggregation splits either LogicalAggregation or PhysicalAggregation to finalAgg and partial1Agg, // returns the information of partial and final agg. -// partialIsCop means whether partial agg is a cop task. +// partialIsCop means whether partial agg is a cop task. When partialIsCop is false, +// we do not set the AggMode for partialAgg cause it may be split further when +// building the aggregate executor(e.g. buildHashAgg will split the AggDesc further for parallel executing). +// firstRowFuncMap is a map between partial first_row to final first_row, will be used in RemoveUnnecessaryFirstRow func BuildFinalModeAggregation( - sctx sessionctx.Context, original *AggInfo, partialIsCop bool, isMPPTask bool) (partial, final *AggInfo, funcMap map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc) { - - funcMap = make(map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc, len(original.AggFuncs)) + sctx sessionctx.Context, original *AggInfo, partialIsCop bool, isMPPTask bool) (partial, final *AggInfo, firstRowFuncMap map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc) { + firstRowFuncMap = make(map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc, len(original.AggFuncs)) partial = &AggInfo{ AggFuncs: make([]*aggregation.AggFuncDesc, 0, len(original.AggFuncs)), GroupByItems: original.GroupByItems, @@ -1556,7 +1663,7 @@ func BuildFinalModeAggregation( } // TODO: Refactor the way of constructing aggregation functions. - // This fop loop is ugly, but I do not find a proper way to reconstruct + // This for loop is ugly, but I do not find a proper way to reconstruct // it right away. // group_concat is special when pushing down, it cannot take the two phase execution if no distinct but with orderBy, and other cases are also different: @@ -1718,20 +1825,23 @@ func BuildFinalModeAggregation( partial.Schema.Columns[partialCursor-1].RetType = sumAgg.RetTp partial.AggFuncs = append(partial.AggFuncs, cntAgg, sumAgg) } else if aggFunc.Name == ast.AggFuncApproxCountDistinct || aggFunc.Name == ast.AggFuncGroupConcat { - newAggFunc := *aggFunc + newAggFunc := aggFunc.Clone() newAggFunc.Name = aggFunc.Name newAggFunc.RetTp = partial.Schema.Columns[partialCursor-1].GetType() - partial.AggFuncs = append(partial.AggFuncs, &newAggFunc) + partial.AggFuncs = append(partial.AggFuncs, newAggFunc) if aggFunc.Name == ast.AggFuncGroupConcat { // append the last separator arg args = append(args, aggFunc.Args[len(aggFunc.Args)-1]) } } else { - partial.AggFuncs = append(partial.AggFuncs, aggFunc) + partialFuncDesc := aggFunc.Clone() + partial.AggFuncs = append(partial.AggFuncs, partialFuncDesc) + if aggFunc.Name == ast.AggFuncFirstRow { + firstRowFuncMap[partialFuncDesc] = finalAggFunc + } } finalAggFunc.Mode = aggregation.FinalMode - funcMap[aggFunc] = finalAggFunc } finalAggFunc.Args = args @@ -1739,6 +1849,11 @@ func BuildFinalModeAggregation( final.AggFuncs[i] = finalAggFunc } partial.Schema.Append(partialGbySchema.Columns...) + if partialIsCop { + for _, f := range partial.AggFuncs { + f.Mode = aggregation.Partial1Mode + } + } return } @@ -1817,7 +1932,7 @@ func (p *basePhysicalAgg) newPartialAggregate(copTaskType kv.StoreType, isMPPTas if !CheckAggCanPushCop(p.ctx, p.AggFuncs, p.GroupByItems, copTaskType) { return nil, p.self } - partialPref, finalPref, funcMap := BuildFinalModeAggregation(p.ctx, &AggInfo{ + partialPref, finalPref, firstRowFuncMap := BuildFinalModeAggregation(p.ctx, &AggInfo{ AggFuncs: p.AggFuncs, GroupByItems: p.GroupByItems, Schema: p.Schema().Clone(), @@ -1830,8 +1945,7 @@ func (p *basePhysicalAgg) newPartialAggregate(copTaskType kv.StoreType, isMPPTas } // Remove unnecessary FirstRow. partialPref.AggFuncs = RemoveUnnecessaryFirstRow(p.ctx, - finalPref.AggFuncs, finalPref.GroupByItems, - partialPref.AggFuncs, partialPref.GroupByItems, partialPref.Schema, funcMap) + finalPref.GroupByItems, partialPref.AggFuncs, partialPref.GroupByItems, partialPref.Schema, firstRowFuncMap) if copTaskType == kv.TiDB { // For partial agg of TiDB cop task, since TiDB coprocessor reuse the TiDB executor, // and TiDB aggregation executor won't output the group by value, @@ -1888,12 +2002,11 @@ func genFirstRowAggForGroupBy(ctx sessionctx.Context, groupByItems []expression. // Can optimize the schema to [count(b), a] , and change the index to get value. func RemoveUnnecessaryFirstRow( sctx sessionctx.Context, - finalAggFuncs []*aggregation.AggFuncDesc, finalGbyItems []expression.Expression, partialAggFuncs []*aggregation.AggFuncDesc, partialGbyItems []expression.Expression, partialSchema *expression.Schema, - funcMap map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc) []*aggregation.AggFuncDesc { + firstRowFuncMap map[*aggregation.AggFuncDesc]*aggregation.AggFuncDesc) []*aggregation.AggFuncDesc { partialCursor := 0 newAggFuncs := make([]*aggregation.AggFuncDesc, 0, len(partialAggFuncs)) @@ -1913,7 +2026,7 @@ func RemoveUnnecessaryFirstRow( } if gbyExpr.Equal(sctx, aggFunc.Args[0]) { canOptimize = true - funcMap[aggFunc].Args[0] = finalGbyItems[j] + firstRowFuncMap[aggFunc].Args[0] = finalGbyItems[j] break } } @@ -1978,13 +2091,15 @@ func (p *PhysicalStreamAgg) attach2Task(tasks ...task) task { t = cop.convertToRootTask(p.ctx) inputRows = t.count() attachPlan2Task(finalAgg, t) - finalAgg.SetCost(cop.cost()) } + } else if mpp, ok := t.(*mppTask); ok { + t = mpp.convertToRootTask(p.ctx) + attachPlan2Task(p, t) } else { attachPlan2Task(p, t) } t.addCost(p.GetCost(inputRows, true)) - p.SetCost(t.cost()) + t.plan().SetCost(t.cost()) return t } @@ -2021,6 +2136,20 @@ func (p *PhysicalHashAgg) cpuCostDivisor(hasDistinct bool) (float64, float64) { return math.Min(float64(finalCon), float64(partialCon)), float64(finalCon + partialCon) } +func (p *PhysicalHashAgg) attach2TaskForMpp1Phase(mpp *mppTask) task { + inputRows := mpp.count() + // 1-phase agg: when the partition columns can be satisfied, where the plan does not need to enforce Exchange + // only push down the original agg + proj := p.convertAvgForMPP() + attachPlan2Task(p.self, mpp) + if proj != nil { + attachPlan2Task(proj, mpp) + } + mpp.addCost(p.GetCost(inputRows, false, true)) + p.cost = mpp.cost() + return mpp +} + func (p *PhysicalHashAgg) attach2TaskForMpp(tasks ...task) task { t := tasks[0].copy() mpp, ok := t.(*mppTask) @@ -2041,6 +2170,7 @@ func (p *PhysicalHashAgg) attach2TaskForMpp(tasks ...task) task { p.cost = mpp.cost() return mpp case Mpp2Phase: + // TODO: when partition property is matched by sub-plan, we actually needn't do extra an exchange and final agg. proj := p.convertAvgForMPP() partialAgg, finalAgg := p.newPartialAggregate(kv.TiFlash, true) if partialAgg == nil { @@ -2095,6 +2225,10 @@ func (p *PhysicalHashAgg) attach2TaskForMpp(tasks ...task) task { finalAgg.SetCost(t.cost()) return t case MppScalar: + prop := &property.PhysicalProperty{TaskTp: property.MppTaskType, ExpectedCnt: math.MaxFloat64, MPPPartitionTp: property.SinglePartitionType} + if !mpp.needEnforceExchanger(prop) { + return p.attach2TaskForMpp1Phase(mpp) + } proj := p.convertAvgForMPP() partialAgg, finalAgg := p.newPartialAggregate(kv.TiFlash, true) if finalAgg == nil { @@ -2104,8 +2238,7 @@ func (p *PhysicalHashAgg) attach2TaskForMpp(tasks ...task) task { if partialAgg != nil { attachPlan2Task(partialAgg, mpp) } - prop := &property.PhysicalProperty{TaskTp: property.MppTaskType, ExpectedCnt: math.MaxFloat64, MPPPartitionTp: property.AnyType} - newMpp := mpp.enforceExchangerImpl(prop) + newMpp := mpp.enforceExchanger(prop) attachPlan2Task(finalAgg, newMpp) if proj == nil { proj = PhysicalProjection{ @@ -2183,7 +2316,7 @@ func (p *PhysicalHashAgg) attach2Task(tasks ...task) task { // To make it simple, we also treat 2-phase parallel hash aggregation in TiDB layer as // 1-phase when computing cost. t.addCost(p.GetCost(inputRows, true, false)) - p.cost = t.cost() + t.plan().SetCost(t.cost()) return t } @@ -2265,6 +2398,23 @@ func collectPartitionInfosFromMPPPlan(p *PhysicalTableReader, mppPlan PhysicalPl } } +func collectRowSizeFromMPPPlan(mppPlan PhysicalPlan) (rowSize float64) { + if mppPlan != nil && mppPlan.Stats() != nil && mppPlan.Stats().HistColl != nil { + return mppPlan.Stats().HistColl.GetAvgRowSize(mppPlan.SCtx(), mppPlan.Schema().Columns, false, false) + } + return 1 // use 1 as lower-bound for safety +} + +func accumulateNetSeekCost4MPP(p PhysicalPlan) (cost float64) { + if ts, ok := p.(*PhysicalTableScan); ok { + return float64(len(ts.Ranges)) * float64(len(ts.Columns)) * ts.SCtx().GetSessionVars().GetSeekFactor(ts.Table) + } + for _, c := range p.Children() { + cost += accumulateNetSeekCost4MPP(c) + } + return +} + func (t *mppTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { sender := PhysicalExchangeSender{ ExchangeType: tipb.ExchangeType_PassThrough, @@ -2278,30 +2428,38 @@ func (t *mppTask) convertToRootTaskImpl(ctx sessionctx.Context) *rootTask { }.Init(ctx, t.p.SelectBlockOffset()) p.stats = t.p.statsInfo() collectPartitionInfosFromMPPPlan(p, t.p) + rowSize := collectRowSizeFromMPPPlan(sender) - cst := t.cst + t.count()*ctx.GetSessionVars().GetNetworkFactor(nil) - p.cost = cst / p.ctx.GetSessionVars().CopTiFlashConcurrencyFactor + cst := t.cst + t.count()*rowSize*ctx.GetSessionVars().GetNetworkFactor(nil) // net I/O cost + // net seek cost, unlike copTask, a mppTask may have multiple underlying TableScan, so use a recursive function to accumulate this + cst += accumulateNetSeekCost4MPP(sender) + cst /= p.ctx.GetSessionVars().CopTiFlashConcurrencyFactor + p.cost = cst if p.ctx.GetSessionVars().IsMPPEnforced() { - p.cost = cst / 1000000000 + cst /= 1000000000 } rt := &rootTask{ p: p, - cst: p.cost, + cst: cst, } return rt } -func (t *mppTask) needEnforce(prop *property.PhysicalProperty) bool { +func (t *mppTask) needEnforceExchanger(prop *property.PhysicalProperty) bool { switch prop.MPPPartitionTp { case property.AnyType: return false case property.BroadcastType: return true + case property.SinglePartitionType: + return t.partTp != property.SinglePartitionType default: if t.partTp != property.HashType { return true } // TODO: consider equalivant class + // TODO: `prop.IsSubsetOf` is enough, instead of equal. + // for example, if already partitioned by hash(B,C), then same (A,B,C) must distribute on a same node. if len(prop.MPPPartitionCols) != len(t.hashCols) { return true } @@ -2319,7 +2477,7 @@ func (t *mppTask) enforceExchanger(prop *property.PhysicalProperty) *mppTask { t.p.SCtx().GetSessionVars().RaiseWarningWhenMPPEnforced("MPP mode may be blocked because operator `Sort` is not supported now.") return &mppTask{} } - if !t.needEnforce(prop) { + if !t.needEnforceExchanger(prop) { return t } return t.copy().(*mppTask).enforceExchangerImpl(prop) @@ -2336,7 +2494,7 @@ func (t *mppTask) enforceExchangerImpl(prop *property.PhysicalProperty) *mppTask } ctx := t.p.SCtx() sender := PhysicalExchangeSender{ - ExchangeType: tipb.ExchangeType(prop.MPPPartitionTp), + ExchangeType: prop.MPPPartitionTp.ToExchangeType(), HashCols: prop.MPPPartitionCols, }.Init(ctx, t.p.statsInfo()) sender.SetChildren(t.p) diff --git a/planner/core/testdata/enforce_mpp_suite_in.json b/planner/core/testdata/enforce_mpp_suite_in.json index 70f519b80192f..41b3aac9920a6 100644 --- a/planner/core/testdata/enforce_mpp_suite_in.json +++ b/planner/core/testdata/enforce_mpp_suite_in.json @@ -28,21 +28,21 @@ "name": "TestEnforceMPPWarning1", "cases": [ "set @@tidb_allow_mpp=1;set @@tidb_enforce_mpp=1;", - "explain select count(*) from t where a=1 -- 1. no replica", + "explain format = 'brief' select count(*) from t where a=1 -- 1. no replica", "cmd: create-replica", "explain select count(*) from t where a=1 -- 2. replica not ready", "cmd: enable-replica", "set @@session.tidb_isolation_read_engines = 'tikv';", "explain select count(*) from t where a=1 -- 3. isolation_engine not match", "set @@session.tidb_isolation_read_engines = 'tikv, tiflash';", - "explain select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1 -- 4. hint use tikv", - "explain SELECT a, ROW_NUMBER() OVER (ORDER BY a) FROM t; -- 5. window unsupported", - "EXPLAIN SELECT t1.b FROM t t1 join t t2 where t1.a=t2.a; -- 6. virtual column", - "EXPLAIN SELECT count(b) from t where a=1; -- 7. agg func has virtual column", - "EXPLAIN SELECT count(*) from t group by b; -- 8. group by virtual column", - "EXPLAIN SELECT count(a) from t group by md5(a); -- 10. scalar func not supported", - "EXPLAIN SELECT count(a) from t where c=1; -- 11. type not supported", - "EXPLAIN SELECT count(a) from t where d=1; -- 11.1. type not supported" + "explain format = 'brief' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1 -- 4. hint use tikv", + "explain format = 'brief' SELECT a, ROW_NUMBER() OVER (ORDER BY a) FROM t; -- 5. window unsupported", + "EXPLAIN format = 'brief' SELECT t1.b FROM t t1 join t t2 where t1.a=t2.a; -- 6. virtual column", + "EXPLAIN format = 'brief' SELECT count(b) from t where a=1; -- 7. agg func has virtual column", + "EXPLAIN format = 'brief' SELECT count(*) from t group by b; -- 8. group by virtual column", + "EXPLAIN format = 'brief' SELECT count(a) from t group by md5(a); -- 10. scalar func not supported", + "EXPLAIN format = 'brief' SELECT count(a) from t where c=1; -- 11. type not supported", + "EXPLAIN format = 'brief' SELECT count(a) from t where d=1; -- 11.1. type not supported" ] }, { @@ -82,7 +82,7 @@ "EXPLAIN SELECT * from t join s; -- can use mpp", "set @@tidb_broadcast_join_threshold_size = 104857600; set @@tidb_opt_broadcast_cartesian_join = 1;", "explain select a from t where t.a>1 or t.a in (select a from t); -- 7. left outer semi join", - "explain select a from t where t.a>1 or t.a not in (select a from t); -- 8. anti left outer semi join", + "explain select a from t where t.a>1 or t.a not in (select a from t); -- now it's supported -- 8. anti left outer semi join", "explain select a from t where t.a not in (select a from s where t.a<1); -- 9. non left join has left conditions" ] } diff --git a/planner/core/testdata/enforce_mpp_suite_out.json b/planner/core/testdata/enforce_mpp_suite_out.json index d93fd15e63968..4fc4915ad80d0 100644 --- a/planner/core/testdata/enforce_mpp_suite_out.json +++ b/planner/core/testdata/enforce_mpp_suite_out.json @@ -31,31 +31,31 @@ { "SQL": "explain format='verbose' select count(*) from t where a=1", "Plan": [ - "StreamAgg_24 1.00 485.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_24 1.00 35.88 root funcs:count(Column#6)->Column#4", "└─IndexReader_25 1.00 32.88 root index:StreamAgg_9", - " └─StreamAgg_9 1.00 35.88 cop[tikv] funcs:count(1)->Column#6", - " └─IndexRangeScan_23 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_9 1.00 465.00 cop[tikv] funcs:count(1)->Column#6", + " └─IndexRangeScan_23 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": null }, { "SQL": "explain format='verbose' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_17 1.00 485.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_17 1.00 35.88 root funcs:count(Column#6)->Column#4", "└─IndexReader_18 1.00 32.88 root index:StreamAgg_9", - " └─StreamAgg_9 1.00 35.88 cop[tikv] funcs:count(1)->Column#6", - " └─IndexRangeScan_16 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_9 1.00 465.00 cop[tikv] funcs:count(1)->Column#6", + " └─IndexRangeScan_16 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": null }, { "SQL": "explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_20 1.00 285050.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_20 1.00 19006.88 root funcs:count(Column#6)->Column#4", "└─TableReader_21 1.00 19003.88 root data:StreamAgg_9", - " └─StreamAgg_9 1.00 19006.88 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_19 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_18 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + " └─StreamAgg_9 1.00 285030.00 batchCop[tiflash] funcs:count(1)->Column#6", + " └─Selection_19 10.00 285000.00 batchCop[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_18 10000.00 255000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -72,20 +72,20 @@ { "SQL": "explain format='verbose' select count(*) from t where a=1", "Plan": [ - "StreamAgg_30 1.00 485.00 root funcs:count(Column#7)->Column#4", + "StreamAgg_30 1.00 35.88 root funcs:count(Column#7)->Column#4", "└─IndexReader_31 1.00 32.88 root index:StreamAgg_10", - " └─StreamAgg_10 1.00 35.88 cop[tikv] funcs:count(1)->Column#7", - " └─IndexRangeScan_29 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_10 1.00 465.00 cop[tikv] funcs:count(1)->Column#7", + " └─IndexRangeScan_29 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": null }, { "SQL": "explain format='verbose' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_18 1.00 485.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_18 1.00 35.88 root funcs:count(Column#6)->Column#4", "└─IndexReader_19 1.00 32.88 root index:StreamAgg_10", - " └─StreamAgg_10 1.00 35.88 cop[tikv] funcs:count(1)->Column#6", - " └─IndexRangeScan_17 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_10 1.00 465.00 cop[tikv] funcs:count(1)->Column#6", + " └─IndexRangeScan_17 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": null }, @@ -94,10 +94,10 @@ "Plan": [ "HashAgg_21 1.00 11910.73 root funcs:count(Column#6)->Column#4", "└─TableReader_23 1.00 11877.13 root data:ExchangeSender_22", - " └─ExchangeSender_22 1.00 285050.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_9 1.00 285050.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_20 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_19 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + " └─ExchangeSender_22 1.00 285030.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_9 1.00 285030.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─Selection_20 10.00 285000.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_19 10000.00 255000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -111,20 +111,20 @@ "Plan": [ "HashAgg_24 1.00 33.89 root funcs:count(Column#6)->Column#4", "└─TableReader_26 1.00 0.29 root data:ExchangeSender_25", - " └─ExchangeSender_25 1.00 285050.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_9 1.00 285050.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_23 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_22 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + " └─ExchangeSender_25 1.00 285030.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_9 1.00 285030.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─Selection_23 10.00 285000.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_22 10000.00 255000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, { "SQL": "explain format='verbose' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_18 1.00 485.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_18 1.00 35.88 root funcs:count(Column#6)->Column#4", "└─IndexReader_19 1.00 32.88 root index:StreamAgg_10", - " └─StreamAgg_10 1.00 35.88 cop[tikv] funcs:count(1)->Column#6", - " └─IndexRangeScan_17 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_10 1.00 465.00 cop[tikv] funcs:count(1)->Column#6", + " └─IndexRangeScan_17 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": null }, @@ -133,10 +133,10 @@ "Plan": [ "HashAgg_21 1.00 33.89 root funcs:count(Column#6)->Column#4", "└─TableReader_23 1.00 0.29 root data:ExchangeSender_22", - " └─ExchangeSender_22 1.00 285050.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_9 1.00 285050.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_20 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_19 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + " └─ExchangeSender_22 1.00 285030.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_9 1.00 285030.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─Selection_20 10.00 285000.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_19 10000.00 255000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -149,21 +149,21 @@ "SQL": "explain format='verbose' select count(*) from t where a=1", "Plan": [ "HashAgg_25 1.00 33.60 root funcs:count(Column#6)->Column#4", - "└─TableReader_27 1.00 0.00 root data:ExchangeSender_26", - " └─ExchangeSender_26 1.00 285050.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_10 1.00 285050.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_24 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_23 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + "└─TableReader_27 1.00 0.29 root data:ExchangeSender_26", + " └─ExchangeSender_26 1.00 285030.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_10 1.00 285030.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─Selection_24 10.00 285000.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_23 10000.00 255000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, { "SQL": "explain format='verbose' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_19 1.00 485.00 root funcs:count(Column#6)->Column#4", + "StreamAgg_19 1.00 35.88 root funcs:count(Column#6)->Column#4", "└─IndexReader_20 1.00 32.88 root index:StreamAgg_11", - " └─StreamAgg_11 1.00 35.88 cop[tikv] funcs:count(1)->Column#6", - " └─IndexRangeScan_18 10.00 455.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + " └─StreamAgg_11 1.00 465.00 cop[tikv] funcs:count(1)->Column#6", + " └─IndexRangeScan_18 10.00 435.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have set a hint to read table `t` from TiKV." @@ -173,11 +173,11 @@ "SQL": "explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1", "Plan": [ "HashAgg_22 1.00 33.60 root funcs:count(Column#6)->Column#4", - "└─TableReader_24 1.00 0.00 root data:ExchangeSender_23", - " └─ExchangeSender_23 1.00 285050.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_10 1.00 285050.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─Selection_21 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_20 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + "└─TableReader_24 1.00 0.29 root data:ExchangeSender_23", + " └─ExchangeSender_23 1.00 285030.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_10 1.00 285030.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─Selection_21 10.00 285000.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_20 10000.00 255000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null } @@ -192,12 +192,12 @@ "Warn": null }, { - "SQL": "explain select count(*) from t where a=1 -- 1. no replica", + "SQL": "explain format = 'brief' select count(*) from t where a=1 -- 1. no replica", "Plan": [ - "StreamAgg_17 1.00 root funcs:count(Column#8)->Column#6", - "└─IndexReader_18 1.00 root index:StreamAgg_9", - " └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#8", - " └─IndexRangeScan_16 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + "StreamAgg 1.00 root funcs:count(Column#8)->Column#6", + "└─IndexReader 1.00 root index:StreamAgg", + " └─StreamAgg 1.00 cop[tikv] funcs:count(1)->Column#8", + " └─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because there aren't tiflash replicas of table `t`." @@ -248,23 +248,23 @@ "Warn": null }, { - "SQL": "explain select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1 -- 4. hint use tikv", + "SQL": "explain format = 'brief' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1 -- 4. hint use tikv", "Plan": [ - "StreamAgg_19 1.00 root funcs:count(Column#8)->Column#6", - "└─IndexReader_20 1.00 root index:StreamAgg_11", - " └─StreamAgg_11 1.00 cop[tikv] funcs:count(1)->Column#8", - " └─IndexRangeScan_18 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" + "StreamAgg 1.00 root funcs:count(Column#8)->Column#6", + "└─IndexReader 1.00 root index:StreamAgg", + " └─StreamAgg 1.00 cop[tikv] funcs:count(1)->Column#8", + " └─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have set a hint to read table `t` from TiKV." ] }, { - "SQL": "explain SELECT a, ROW_NUMBER() OVER (ORDER BY a) FROM t; -- 5. window unsupported", + "SQL": "explain format = 'brief' SELECT a, ROW_NUMBER() OVER (ORDER BY a) FROM t; -- 5. window unsupported", "Plan": [ - "Window_7 10000.00 root row_number()->Column#7 over(order by test.t.a rows between current row and current row)", - "└─IndexReader_9 10000.00 root index:IndexFullScan_8", - " └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:idx(a) keep order:true, stats:pseudo" + "Window 10000.00 root row_number()->Column#7 over(order by test.t.a rows between current row and current row)", + "└─IndexReader 10000.00 root index:IndexFullScan", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx(a) keep order:true, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because operator `Window` is not supported now.", @@ -272,27 +272,27 @@ ] }, { - "SQL": "EXPLAIN SELECT t1.b FROM t t1 join t t2 where t1.a=t2.a; -- 6. virtual column", + "SQL": "EXPLAIN format = 'brief' SELECT t1.b FROM t t1 join t t2 where t1.a=t2.a; -- 6. virtual column", "Plan": [ - "HashJoin_36 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", - "├─TableReader_56(Build) 9990.00 root data:Selection_55", - "│ └─Selection_55 9990.00 cop[tiflash] not(isnull(test.t.a))", - "│ └─TableFullScan_54 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", - "└─TableReader_50(Probe) 9990.00 root data:Selection_49", - " └─Selection_49 9990.00 cop[tiflash] not(isnull(test.t.a))", - " └─TableFullScan_48 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" + "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because column `test.t.b` is a virtual column which is not supported now." ] }, { - "SQL": "EXPLAIN SELECT count(b) from t where a=1; -- 7. agg func has virtual column", + "SQL": "EXPLAIN format = 'brief' SELECT count(b) from t where a=1; -- 7. agg func has virtual column", "Plan": [ - "StreamAgg_11 1.00 root funcs:count(test.t.b)->Column#6", - "└─IndexLookUp_42 10.00 root ", - " ├─IndexRangeScan_40(Build) 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo", - " └─TableRowIDScan_41(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo" + "StreamAgg 1.00 root funcs:count(test.t.b)->Column#6", + "└─IndexLookUp 10.00 root ", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx(a) range:[1,1], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warn": [ "Aggregation can not be pushed to tiflash because expressions of AggFunc `count` contain virtual column or correlated column, which is not supported now", @@ -303,12 +303,12 @@ ] }, { - "SQL": "EXPLAIN SELECT count(*) from t group by b; -- 8. group by virtual column", + "SQL": "EXPLAIN format = 'brief' SELECT count(*) from t group by b; -- 8. group by virtual column", "Plan": [ - "HashAgg_6 8000.00 root group by:test.t.b, funcs:count(1)->Column#6", - "└─Projection_12 10000.00 root test.t.b", - " └─TableReader_11 10000.00 root data:TableFullScan_10", - " └─TableFullScan_10 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "HashAgg 8000.00 root group by:test.t.b, funcs:count(1)->Column#6", + "└─Projection 10000.00 root test.t.b", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ "Aggregation can not be pushed to tiflash because groupByItems contain virtual columns, which is not supported now", @@ -317,12 +317,12 @@ ] }, { - "SQL": "EXPLAIN SELECT count(a) from t group by md5(a); -- 10. scalar func not supported", + "SQL": "EXPLAIN format = 'brief' SELECT count(a) from t group by md5(a); -- 10. scalar func not supported", "Plan": [ - "HashAgg_6 8000.00 root group by:Column#8, funcs:count(Column#7)->Column#6", - "└─Projection_19 10000.00 root test.t.a, md5(cast(test.t.a, var_string(20)))->Column#8", - " └─TableReader_12 10000.00 root data:TableFullScan_10", - " └─TableFullScan_10 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "HashAgg 8000.00 root group by:Column#8, funcs:count(Column#7)->Column#6", + "└─Projection 10000.00 root test.t.a, md5(cast(test.t.a, var_string(20)))->Column#8", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ "Scalar function 'md5'(signature: MD5, return type: var_string(32)) is not supported to push down to tiflash now.", @@ -334,12 +334,12 @@ ] }, { - "SQL": "EXPLAIN SELECT count(a) from t where c=1; -- 11. type not supported", + "SQL": "EXPLAIN format = 'brief' SELECT count(a) from t where c=1; -- 11. type not supported", "Plan": [ - "StreamAgg_11 1.00 root funcs:count(test.t.a)->Column#6", - "└─Selection_29 10.00 root eq(test.t.c, 1)", - " └─TableReader_28 10000.00 root data:TableFullScan_27", - " └─TableFullScan_27 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "StreamAgg 1.00 root funcs:count(test.t.a)->Column#6", + "└─Selection 10.00 root eq(test.t.c, 1)", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ "Expression about 'test.t.c' can not be pushed to TiFlash because it contains unsupported calculation of type 'enum'.", @@ -350,15 +350,18 @@ ] }, { - "SQL": "EXPLAIN SELECT count(a) from t where d=1; -- 11.1. type not supported", + "SQL": "EXPLAIN format = 'brief' SELECT count(a) from t where d=1; -- 11.1. type not supported", "Plan": [ - "HashAgg_9 1.00 root funcs:count(test.t.a)->Column#6", - "└─Selection_19 8000.00 root eq(test.t.d, 1)", - " └─TableReader_22 10000.00 root data:ExchangeSender_21", - " └─ExchangeSender_21 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan_20 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "StreamAgg 1.00 root funcs:count(test.t.a)->Column#6", + "└─Selection 10.00 root eq(test.t.d, 1)", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ + "Expression about 'test.t.d' can not be pushed to TiFlash because it contains unsupported calculation of type 'bit'.", + "Expression about 'test.t.d' can not be pushed to TiFlash because it contains unsupported calculation of type 'bit'.", + "Expression about 'test.t.d' can not be pushed to TiFlash because it contains unsupported calculation of type 'bit'.", + "Expression about 'test.t.d' can not be pushed to TiFlash because it contains unsupported calculation of type 'bit'.", "Expression about 'test.t.d' can not be pushed to TiFlash because it contains unsupported calculation of type 'bit'." ] } @@ -415,9 +418,9 @@ "Plan": [ "HashAgg_24 8000.00 root group by:test.t.b, funcs:count(Column#7)->Column#4", "└─TableReader_26 8000.00 root data:ExchangeSender_25", - " └─ExchangeSender_25 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg_11 8000.00 batchCop[tiflash] group by:test.t.b, funcs:count(1)->Column#7", - " └─TableFullScan_21 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + " └─ExchangeSender_25 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg_11 8000.00 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#7", + " └─TableFullScan_21 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because when `new_collation_enabled` is true, HashJoin or HashAgg with string key is not supported now.", @@ -429,14 +432,14 @@ "SQL": "EXPLAIN SELECT * from t t1 join t t2 on t1.b=t2.b; -- 2. new collation FIXME", "Plan": [ "TableReader_34 12487.50 root data:ExchangeSender_33", - "└─ExchangeSender_33 12487.50 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin_32 12487.50 cop[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", - " ├─ExchangeReceiver_15(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender_14 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection_13 9990.00 cop[tiflash] not(isnull(test.t.b))", - " │ └─TableFullScan_12 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo", - " └─Selection_17(Probe) 9990.00 cop[tiflash] not(isnull(test.t.b))", - " └─TableFullScan_16 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo" + "└─ExchangeSender_33 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_32 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver_15(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_14 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection_13 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan_12 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─Selection_17(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan_16 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" ], "Warn": null } @@ -454,10 +457,10 @@ "SQL": "EXPLAIN SELECT /*+ MERGE_JOIN(t,s) */ * from t join s using(a); -- 1. hint use MERGE_JOIN", "Plan": [ "MergeJoin_8 12500.00 root inner join, left key:test.t.a, right key:test.s.a", - "├─TableReader_19(Build) 10000.00 root data:TableFullScan_18", - "│ └─TableFullScan_18 10000.00 cop[tiflash] table:s keep order:true, stats:pseudo", - "└─TableReader_15(Probe) 10000.00 root data:TableFullScan_14", - " └─TableFullScan_14 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" + "├─TableReader_18(Build) 10000.00 root data:TableFullScan_17", + "│ └─TableFullScan_17 10000.00 cop[tiflash] table:s keep order:true, stats:pseudo", + "└─TableReader_14(Probe) 10000.00 root data:TableFullScan_13", + " └─TableFullScan_13 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.", @@ -467,11 +470,11 @@ { "SQL": "EXPLAIN SELECT /*+ INL_JOIN(t,s) */ * from t, s where t.a=s.a; -- 2. hint use INL_JOIN", "Plan": [ - "IndexJoin_16 12500.00 root inner join, inner:TableReader_13, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a)", - "├─TableReader_33(Build) 10000.00 root data:TableFullScan_32", - "│ └─TableFullScan_32 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - "└─TableReader_13(Probe) 1.00 root data:TableRangeScan_12", - " └─TableRangeScan_12 1.00 cop[tikv] table:s range: decided by [test.t.a], keep order:false, stats:pseudo" + "IndexJoin_15 12500.00 root inner join, inner:TableReader_12, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a)", + "├─TableReader_32(Build) 10000.00 root data:TableFullScan_31", + "│ └─TableFullScan_31 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader_12(Probe) 1.00 root data:TableRangeScan_11", + " └─TableRangeScan_11 1.00 cop[tikv] table:s range: decided by [test.t.a], keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.", @@ -481,11 +484,11 @@ { "SQL": "EXPLAIN SELECT /*+ INL_HASH_JOIN(t,s) */ * from t join s using(a); -- 3. hint use INL_HASH_JOIN", "Plan": [ - "IndexHashJoin_17 12500.00 root inner join, inner:TableReader_12, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a)", - "├─TableReader_32(Build) 10000.00 root data:TableFullScan_31", - "│ └─TableFullScan_31 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - "└─TableReader_12(Probe) 1.00 root data:TableRangeScan_11", - " └─TableRangeScan_11 1.00 cop[tikv] table:s range: decided by [test.t.a], keep order:false, stats:pseudo" + "IndexHashJoin_16 12500.00 root inner join, inner:TableReader_11, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a)", + "├─TableReader_31(Build) 10000.00 root data:TableFullScan_30", + "│ └─TableFullScan_30 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader_11(Probe) 1.00 root data:TableRangeScan_10", + " └─TableRangeScan_10 1.00 cop[tikv] table:s range: decided by [test.t.a], keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.", @@ -495,11 +498,11 @@ { "SQL": "EXPLAIN SELECT /*+ HASH_JOIN(t,s) */ * from t join s using(a); -- 4. hint use INL_JOIN", "Plan": [ - "HashJoin_29 12500.00 root inner join, equal:[eq(test.t.a, test.s.a)]", - "├─TableReader_38(Build) 10000.00 root data:TableFullScan_37", - "│ └─TableFullScan_37 10000.00 cop[tiflash] table:s keep order:false, stats:pseudo", - "└─TableReader_34(Probe) 10000.00 root data:TableFullScan_33", - " └─TableFullScan_33 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "HashJoin_28 12500.00 root inner join, equal:[eq(test.t.a, test.s.a)]", + "├─TableReader_37(Build) 10000.00 root data:TableFullScan_36", + "│ └─TableFullScan_36 10000.00 cop[tiflash] table:s keep order:false, stats:pseudo", + "└─TableReader_33(Probe) 10000.00 root data:TableFullScan_32", + " └─TableFullScan_32 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.", @@ -553,12 +556,12 @@ "SQL": "EXPLAIN SELECT * from t join s; -- can use mpp", "Plan": [ "TableReader_27 100000000.00 root data:ExchangeSender_26", - "└─ExchangeSender_26 100000000.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin_25 100000000.00 cop[tiflash] CARTESIAN inner join", - " ├─ExchangeReceiver_13(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender_12 10000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan_11 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─TableFullScan_14(Probe) 10000.00 cop[tiflash] table:s keep order:false, stats:pseudo" + "└─ExchangeSender_26 100000000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_25 100000000.00 mpp[tiflash] CARTESIAN inner join", + " ├─ExchangeReceiver_13(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender_12 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan_11 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan_14(Probe) 10000.00 mpp[tiflash] table:s keep order:false, stats:pseudo" ], "Warn": null }, @@ -571,12 +574,12 @@ "SQL": "EXPLAIN SELECT * from t join s; -- can use mpp", "Plan": [ "TableReader_27 100000000.00 root data:ExchangeSender_26", - "└─ExchangeSender_26 100000000.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin_25 100000000.00 cop[tiflash] CARTESIAN inner join", - " ├─ExchangeReceiver_13(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender_12 10000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan_11 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─TableFullScan_14(Probe) 10000.00 cop[tiflash] table:s keep order:false, stats:pseudo" + "└─ExchangeSender_26 100000000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_25 100000000.00 mpp[tiflash] CARTESIAN inner join", + " ├─ExchangeReceiver_13(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender_12 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan_11 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan_14(Probe) 10000.00 mpp[tiflash] table:s keep order:false, stats:pseudo" ], "Warn": null }, @@ -588,43 +591,41 @@ { "SQL": "explain select a from t where t.a>1 or t.a in (select a from t); -- 7. left outer semi join", "Plan": [ - "Projection_7 8000.00 root test.t.a", - "└─Selection_9 8000.00 root or(gt(test.t.a, 1), Column#3)", - " └─MergeJoin_10 10000.00 root left outer semi join, left key:test.t.a, right key:test.t.a", - " ├─TableReader_30(Build) 10000.00 root data:TableFullScan_29", - " │ └─TableFullScan_29 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo", - " └─TableReader_26(Probe) 10000.00 root data:TableFullScan_25", - " └─TableFullScan_25 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" + "TableReader_48 8000.00 root data:ExchangeSender_47", + "└─ExchangeSender_47 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection_8 8000.00 mpp[tiflash] test.t.a", + " └─Selection_45 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#3)", + " └─HashJoin_46 10000.00 mpp[tiflash] left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_26(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender_25 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan_24 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan_23(Probe) 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "MPP mode may be blocked because join type `left outer semi join` is not supported now.", - "MPP mode may be blocked because join type `left outer semi join` is not supported now." - ] + "Warn": null }, { - "SQL": "explain select a from t where t.a>1 or t.a not in (select a from t); -- 8. anti left outer semi join", + "SQL": "explain select a from t where t.a>1 or t.a not in (select a from t); -- now it's supported -- 8. anti left outer semi join", "Plan": [ - "Projection_7 8000.00 root test.t.a", - "└─Selection_9 8000.00 root or(gt(test.t.a, 1), Column#3)", - " └─MergeJoin_10 10000.00 root anti left outer semi join, left key:test.t.a, right key:test.t.a", - " ├─TableReader_30(Build) 10000.00 root data:TableFullScan_29", - " │ └─TableFullScan_29 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo", - " └─TableReader_26(Probe) 10000.00 root data:TableFullScan_25", - " └─TableFullScan_25 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" + "TableReader_48 8000.00 root data:ExchangeSender_47", + "└─ExchangeSender_47 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection_8 8000.00 mpp[tiflash] test.t.a", + " └─Selection_45 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#3)", + " └─HashJoin_46 10000.00 mpp[tiflash] anti left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_26(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender_25 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan_24 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan_23(Probe) 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "MPP mode may be blocked because join type `anti left outer semi join` is not supported now.", - "MPP mode may be blocked because join type `anti left outer semi join` is not supported now." - ] + "Warn": null }, { "SQL": "explain select a from t where t.a not in (select a from s where t.a<1); -- 9. non left join has left conditions", "Plan": [ "MergeJoin_10 8000.00 root anti semi join, left key:test.t.a, right key:test.s.a, left cond:[lt(test.t.a, 1)]", - "├─TableReader_30(Build) 10000.00 root data:TableFullScan_29", - "│ └─TableFullScan_29 10000.00 cop[tiflash] table:s keep order:true, stats:pseudo", - "└─TableReader_26(Probe) 10000.00 root data:TableFullScan_25", - " └─TableFullScan_25 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" + "├─TableReader_29(Build) 10000.00 root data:TableFullScan_28", + "│ └─TableFullScan_28 10000.00 cop[tiflash] table:s keep order:true, stats:pseudo", + "└─TableReader_25(Probe) 10000.00 root data:TableFullScan_24", + " └─TableFullScan_24 10000.00 cop[tiflash] table:t keep order:true, stats:pseudo" ], "Warn": [ "MPP mode may be blocked because there is a join that is not `left join` but has left conditions, which is not supported by mpp now, see github.com/pingcap/tidb/issues/26090 for more information.", diff --git a/planner/core/testdata/integration_partition_suite_out.json b/planner/core/testdata/integration_partition_suite_out.json index de53ff095d7e9..726b0f6598d6d 100644 --- a/planner/core/testdata/integration_partition_suite_out.json +++ b/planner/core/testdata/integration_partition_suite_out.json @@ -378,16 +378,14 @@ { "SQL": "explain format = 'brief' select * from tlist where a in (0, 1, 2) and mod(a, 2)=0", "DynamicPlan": [ - "Selection 24.00 root eq(mod(list_partition_pruning.tlist.a, 2), 0)", - "└─TableReader 30.00 root partition:p0 data:Selection", - " └─Selection 30.00 cop[tikv] in(list_partition_pruning.tlist.a, 0, 1, 2)", - " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" + "TableReader 24.00 root partition:p0 data:Selection", + "└─Selection 24.00 cop[tikv] eq(mod(list_partition_pruning.tlist.a, 2), 0), in(list_partition_pruning.tlist.a, 0, 1, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" ], "StaticPlan": [ - "Selection 24.00 root eq(mod(list_partition_pruning.tlist.a, 2), 0)", - "└─TableReader 30.00 root data:Selection", - " └─Selection 30.00 cop[tikv] in(list_partition_pruning.tlist.a, 0, 1, 2)", - " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo" + "TableReader 24.00 root data:Selection", + "└─Selection 24.00 cop[tikv] eq(mod(list_partition_pruning.tlist.a, 2), 0), in(list_partition_pruning.tlist.a, 0, 1, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo" ] }, { @@ -413,16 +411,14 @@ { "SQL": "explain format = 'brief' select * from tcollist where a in (0, 1, 2) and mod(a, 2)=0", "DynamicPlan": [ - "Selection 24.00 root eq(mod(list_partition_pruning.tcollist.a, 2), 0)", - "└─TableReader 30.00 root partition:p0 data:Selection", - " └─Selection 30.00 cop[tikv] in(list_partition_pruning.tcollist.a, 0, 1, 2)", - " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" + "TableReader 24.00 root partition:p0 data:Selection", + "└─Selection 24.00 cop[tikv] eq(mod(list_partition_pruning.tcollist.a, 2), 0), in(list_partition_pruning.tcollist.a, 0, 1, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" ], "StaticPlan": [ - "Selection 24.00 root eq(mod(list_partition_pruning.tcollist.a, 2), 0)", - "└─TableReader 30.00 root data:Selection", - " └─Selection 30.00 cop[tikv] in(list_partition_pruning.tcollist.a, 0, 1, 2)", - " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p0 keep order:false, stats:pseudo" + "TableReader 24.00 root data:Selection", + "└─Selection 24.00 cop[tikv] eq(mod(list_partition_pruning.tcollist.a, 2), 0), in(list_partition_pruning.tcollist.a, 0, 1, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p0 keep order:false, stats:pseudo" ] }, { diff --git a/planner/core/testdata/integration_serial_suite_in.json b/planner/core/testdata/integration_serial_suite_in.json deleted file mode 100644 index aece551a5b991..0000000000000 --- a/planner/core/testdata/integration_serial_suite_in.json +++ /dev/null @@ -1,424 +0,0 @@ -[ - { - "name": "TestSelPushDownTiFlash", - "cases": [ - "explain format = 'brief' select * from t where t.a > 1 and t.b = \"flash\" or t.a + 3 * t.a = 5", - "explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1", - "explain format = 'brief' select * from t where b > 'a' order by convert(b, unsigned) limit 2", - "explain format = 'brief' select * from t where b > 'a' order by b limit 2" - ] - }, - { - "name": "TestVerboseExplain", - "cases": [ - "explain format = 'verbose' select count(*) from t3", - "explain format = 'verbose' select count(*) from t2", - "explain format = 'verbose' select * from t3 order by a", - "explain format = 'verbose' select * from t3 order by b", - "explain format = 'verbose' select * from t3 order by a limit 1", - "explain format = 'verbose' select * from t3 order by b limit 1", - "explain format = 'verbose' select count(*) from t2 group by a", - "explain format = 'verbose' select count(*) from t3 where b = 0", - "explain format = 'verbose' select /*+ use_index(t3, c) */ count(a) from t3 where b = 0", - "explain format = 'verbose' select count(*) from t2 where a = 0", - "explain format = 'verbose' select count(*) from t3 t join t3 on t.a = t3.b", - "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a", - "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a join t3 on t1.b = t3.b", - "explain format = 'verbose' select (2) in (select count(*) from t1) from (select t.b < (select t.b from t2 limit 1 ) from t3 t) t", - "explain format = 'verbose' select /*+ merge_join(t1) */ count(*) from t1 join t2 on t1.a = t2.a" - ] - - }, - { - "name": "TestRegardNULLAsPoint", - "cases": [ - "select * from tuk where a<=>null and b=1", - "select * from tik where a<=>null and b=1", - "select * from tuk where a<=>null and b>0 and b<2", - "select * from tik where a<=>null and b>0 and b<2", - "select * from tuk where a<=>null and b>=1 and b<2", - "select * from tik where a<=>null and b>=1 and b<2", - "select * from tuk where a<=>null and b=1 and c=1", - "select * from tik where a<=>null and b=1 and c=1", - "select * from tuk where a=1 and b<=>null and c=1", - "select * from tik where a=1 and b<=>null and c=1", - "select * from tuk where a<=>null and b<=>null and c=1", - "select * from tik where a<=>null and b<=>null and c=1", - "select * from tuk where a<=>null and b<=>null and c<=>null", - "select * from tik where a<=>null and b<=>null and c<=>null" - ] - }, - { - "name": "TestPushDownToTiFlashWithKeepOrder", - "cases": [ - "explain format = 'brief' select max(a) from t", - "explain format = 'brief' select min(a) from t" - ] - }, - { - "name": "TestMPPJoin", - "cases": [ - "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", - "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k > d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k > d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k > d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t where d1_k not in (select d1_k from d1_t)" - ] - }, - { - "name": "TestMPPOuterJoinBuildSideForBroadcastJoin", - "cases": [ - "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "explain format = 'brief' select count(*) from b right join a on a.id = b.id" - ] - }, - { - "name": "TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide", - "cases": [ - "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "explain format = 'brief' select count(*) from b right join a on a.id = b.id" - ] - }, - { - "name": "TestMPPOuterJoinBuildSideForShuffleJoin", - "cases": [ - "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "explain format = 'brief' select count(*) from b right join a on a.id = b.id" - ] - }, - { - "name": "TestMPPShuffledJoin", - "cases": [ - "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", - "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d1_k = d2_t.value and fact_t.d1_k = d3_t.value", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", - "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", - "explain format = 'brief' select count(*) from (select case when t1.col1 is null then t2.col1 + 5 else 10 end as col1, t2.d1_k as d1_k from fact_t t1 right join fact_t t2 on t1.d1_k = t2.d1_k) fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 5", - "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", - "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", - "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)" - ] - }, - { - "name": "TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError", - "cases": [ - "explain format = 'brief' select v from t3 as a left join (select t1.v1, t1.v2, t1.v1 + t1.v2 as v from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2) b on a.v1 = b.v1 and a.v2 = b.v2", - "explain format = 'brief' select count(*), t2.v1, t2.v2 from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2 group by t2.v1, t2.v2", - "explain format = 'brief' select count(*), t2.v1, t2.v2 from t3 left join t2 on t3.v1 = t2.v1 and t3.v2 = t2.v2 group by t2.v1, t2.v2" - ] - }, - { - "name": "TestJoinNotSupportedByTiFlash", - "cases": [ - "explain format = 'brief' select * from table_1 a, table_1 b where a.bit_col = b.bit_col", - "explain format = 'brief' select * from table_1 a left join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > 100", - "explain format = 'brief' select * from table_1 a right join table_1 b on a.id = b.id and dayofmonth(b.datetime_col) > 100", - "explain format = 'brief' select * from table_1 a join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > dayofmonth(b.datetime_col)" - ] - }, - { - "name": "TestMPPWithHashExchangeUnderNewCollation", - "cases": [ - "explain format = 'brief' select * from table_1 a, table_1 b where a.value = b.value", - "explain format = 'brief' select * from table_1 a, table_2 b where a.value = b.value", - "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and b.value = c.value", - "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and a.value = c.value", - "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_1 group by value", - "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_2 group by value" - ] - }, - { - "name": "TestMPPWithBroadcastExchangeUnderNewCollation", - "cases": [ - "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.id = b.id", - "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.value = b.value" - ] - }, - { - "name": "TestMPPAvgRewrite", - "cases": [ - "explain format = 'brief' select /*+ avg_to_cop() */ id, avg(value+1),avg(value) from table_1 group by id" - ] - }, - { - "name": "TestReadFromStorageHint", - "cases": [ - "desc format = 'brief' select avg(a) from t", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a) from t", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a+1) from t", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(isnull(a)) from t", - "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIKV[t2]) */ * from t t1, t t2 where t1.a = t2.a", - "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIFLASH[t2]) */ * from t t1, t t2 where t1.a = t2.a", - "desc format = 'brief' select * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", - "desc format = 'brief' select /*+ read_from_storage(tiflash[tt]) */ * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", - "desc format = 'brief' select * from ttt order by ttt.a desc", - "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a desc", - "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a", - "desc format = 'brief' select /*+ read_from_storage(tikv[t, ttt]) */ * from ttt", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt" - ] - }, - { - "name": "TestReadFromStorageHintAndIsolationRead", - "cases": [ - "desc format = 'brief' select /*+ read_from_storage(tikv[t], tiflash[t]) */ avg(a) from t", - "desc format = 'brief' select /*+ read_from_storage(tikv[t]) */ avg(a) from t", - "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t" - ] - }, - { - "name": "TestIsolationReadDoNotFilterSystemDB", - "cases": [ - "desc format = 'brief' select * from metrics_schema.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'", - "desc format = 'brief' select * from information_schema.tables", - "desc format = 'brief' select * from mysql.stats_meta" - ] - }, - { - "name": "TestIsolationReadTiFlashNotChoosePointGet", - "cases": [ - "explain format = 'brief' select * from t where t.a = 1", - "explain format = 'brief' select * from t where t.a in (1, 2)" - ] - }, - { - "name": "TestIsolationReadTiFlashUseIndexHint", - "cases": [ - "explain format = 'brief' select * from t", - "explain format = 'brief' select * from t use index();", - "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", - "explain format = 'brief' select /*+ use_index(t)*/ * from t" - ] - }, - { - "name": "TestIssue20710", - "cases": [ - "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.b", - "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.a", - "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.a = s.b", - "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.b", - "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.a", - "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.a = s.b" - ] - }, - { - "name": "TestPushDownProjectionForTiFlash", - "cases": [ - "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select * from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "desc format = 'brief' select A.id from t as A where exists (select 1 from t where t.id=A.id)", - "desc format = 'brief' select A.id from t as A where not exists (select 1 from t where t.id=A.id)", - "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;" - ] - }, - { - "name": "TestPushDownProjectionForMPP", - "cases": [ - "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select B.b+A.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", - "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "desc format = 'brief' select id from t as A where exists (select 1 from t where t.id=A.id)", - "desc format = 'brief' select id from t as A where not exists (select 1 from t where t.id=A.id)", - "desc format = 'brief' select b*2, id from (select avg(value+2) as b, id from t group by id) C order by id", - "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;" - ] - }, - { - "name": "TestMppUnionAll", - "cases": [ - "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1) tt", - "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1 union all select a, b from t where false) tt", - "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1) tt", - "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1 where false) tt", - "explain format = 'brief' select count(*) from (select a , b from t where false union all select a , c from t1 where false) tt" - ] - }, - { - "name": "TestMppJoinDecimal", - "cases": [ - "desc format = 'brief' select t1.c1, t1.c2, t2.c1, t2.c2, t2.c3 from t t1 join t t2 on t1.c1 + 1 = t2.c2 - 10 and t1.c1 * 3 = t2.c3 / 2", - "desc format = 'brief' select * from (select c1, c2, c5, count(*) c from t group by c1, c2, c5) t1 join (select c1, c2, c3, count(*) c from t group by c1, c2, c3) t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c5 = t2.c1", - "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c2 and t1.c3 = t2.c3 and t1.c4 = t2.c4 and t1.c5 = t2.c5", - "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5", - "desc format = 'brief' select * from t t1 join t t2 on t1.c1 + t1.c2 = t2.c2 / t2.c3", - "desc format = 'brief' select * from t t1 where exists (select * from t t2 where t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5)", - "desc format = 'brief' select * from t t1 left join t t2 on t1.c1 = t2.c2 join t t3 on t2.c5 = t3.c3 right join t t4 on t3.c3 = t4.c4 ", - "desc format = 'brief' SELECT STRAIGHT_JOIN t1 . col_varchar_64 , t1 . col_char_64_not_null FROM tt AS t1 INNER JOIN( tt AS t2 JOIN tt AS t3 ON(t3 . col_decimal_30_10_key = t2 . col_tinyint)) ON(t3 . col_varchar_64 = t2 . col_varchar_key) WHERE t3 . col_varchar_64 = t1 . col_char_64_not_null GROUP BY 1 , 2" - ] - }, - { - "name": "TestPushDownAggForMPP", - "cases": [ - "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id+1 from t)A", - "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "desc format = 'brief' select count(*) from t", - "desc format = 'brief' select count(*), id from t group by id", - "desc format = 'brief' select count(*), id + 1 from t group by id + 1", - "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", - "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", - "desc format = 'brief' select avg(value) as b,id from t group by id", - "desc format = 'brief' select /*+hash_agg()*/ sum(b) from (select avg(value) as b, id from t group by id)A", - "desc format = 'brief' select id from t group by id having avg(value)>0", - "desc format = 'brief' select avg(value),id from t group by id having avg(value)>0", - "desc format = 'brief' select avg(value) +1,id from t group by id", - "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", - "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", - "desc format = 'brief' select count(distinct value),id from t group by id", - "desc format = 'brief' select count(distinct value),sum(distinct value),id from t group by id", - "desc format = 'brief' select * from t join ( select count(distinct value), id from t group by id) as A on A.id = t.id", - "desc format = 'brief' select * from t join ( select count(1/value), id from t group by id) as A on A.id = t.id", - "desc format = 'brief' select /*+hash_agg()*/ sum(id) from (select value, id from t where id > value group by id, value)A group by value /*the exchange should have only one partition column: test.t.value*/", - "desc format = 'brief' select /*+hash_agg()*/ sum(B.value) from t as B where B.id+1 > (select count(*) from t where t.id= B.id and t.value=B.value) group by B.id /*the exchange should have only one partition column: test.t.id*/", - "desc format = 'brief' select count(distinct value) from t", - "desc format = 'brief' select count(distinct x ) from (select count(distinct value) x from t) t", - "desc format = 'brief' select count(distinct value), count(value), avg(value) from t" - ] - }, - { - "name": "TestMppAggTopNWithJoin", - "cases": [ - "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", - "desc format = 'brief' select * from t join ( select count(*)+id as v from t group by id) as A on A.v = t.id", - "desc format = 'brief' select * from t join ( select count(*) as v, id from t group by value,id having value+v <10) as A on A.id = t.id", - "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", - "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", - "desc format = 'brief' select * from (select id from t group by id) C join (select sum(value),id from t group by id)B on C.id=B.id", - "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", - "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value limit 1", - "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value % 100 limit 1", - "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id order by t.value limit 20) v group by v.v1", - "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", - "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", - "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id limit 20) v group by v.v1" - ] - }, - { - "name": "TestIndexMerge", - "cases": [ - "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and b+2>1)", - "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and length(b)=1)", - "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(a)=1) or (b=1 and length(b)=1)", - "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(b)=1) or (b=1 and length(a)=1)" - ] - }, - { - "name": "TestLimitIndexLookUpKeepOrder", - "cases": [ - "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b,c limit 10", - "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b desc, c desc limit 10" - ] - }, - { - "name": "TestIssue23887", - "cases": [ - "select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t" - ] - }, - { - "name": "TestMergeContinuousSelections", - "cases": [ - "desc format = 'brief' SELECT table2 . `col_char_64` AS field1 FROM `ts` AS table2 INNER JOIN (SELECT DISTINCT SUBQUERY3_t1 . * FROM `ts` AS SUBQUERY3_t1 LEFT OUTER JOIN `ts` AS SUBQUERY3_t2 ON SUBQUERY3_t2 . `col_varchar_64_not_null` = SUBQUERY3_t1 . `col_varchar_key`) AS table3 ON (table3 . `col_varchar_key` = table2 . `col_varchar_64`) WHERE table3 . `col_char_64_not_null` >= SOME (SELECT SUBQUERY4_t1 . `col_varchar_64` AS SUBQUERY4_field1 FROM `ts` AS SUBQUERY4_t1) GROUP BY field1 ;" - ] - }, - { - "name": "TestPushDownGroupConcatToTiFlash", - "cases": [ - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_1) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_0) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_1, id order by col_0) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_1, id order by col_0) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_0),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_1),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(distinct id),min(col_0),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(distinct id),max(col_1),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),group_concat(col_0 order by 1),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0),count(distinct id),group_concat(col_1, id order by 1,2),avg(id) from ts group by col_2", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, id),count(distinct id),group_concat(col_1, id order by 1,2),min(col_0),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),group_concat(col_1, id order by 1,2),max(col_1),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts group by col_0", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'01') from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,1) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,10) from ts group by '010'", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts group by '011'", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts group by 'GG'", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG','GG') from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'Gg','GG') from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG-10','GG') from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct '1200-01-01 00:00:00.023',1200) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0) from ts group by id", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0,id) from ts group by id", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts group by col_1", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0>10 order by id<10) from ts group by col_1", - "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by col_0<=>null) from ts" - ] - }, - { - "name": "TestRejectSortForMPP", - "cases": [ - "desc format = 'brief' select count(*) from (select * from t order by id)a group by name,id order by id", - "desc format = 'brief' select count(*) from (select * from t order by id)a group by name order by 1", - "desc format = 'brief' select count(*) from (select id,name from t group by id,name order by id,name)a group by name order by 1", - "desc format = 'brief' select * from (select id from t group by id order by id)a join t on a.id=t.id order by 1", - "desc format = 'brief' select * from (select * from t order by id)a join t on a.id=t.id order by 1", - "desc format = 'brief' select * from ((select id from t order by 1) union all (select id+1 from t order by 1))c", - "desc format = 'brief' select * from ((select count(*) from (select id,name from t order by id)a group by name,id order by id) union all (select id+1 from t order by 1))c", - "desc format = 'brief' select * from (select * from t order by id)a order by name" - ] - } -] diff --git a/planner/core/testdata/integration_serial_suite_out.json b/planner/core/testdata/integration_serial_suite_out.json deleted file mode 100644 index fa07e7323f022..0000000000000 --- a/planner/core/testdata/integration_serial_suite_out.json +++ /dev/null @@ -1,4040 +0,0 @@ -[ - { - "Name": "TestSelPushDownTiFlash", - "Cases": [ - { - "SQL": "explain format = 'brief' select * from t where t.a > 1 and t.b = \"flash\" or t.a + 3 * t.a = 5", - "Plan": [ - "TableReader 8000.67 root data:Selection", - "└─Selection 8000.67 cop[tiflash] or(and(gt(test.t.a, 1), eq(test.t.b, \"flash\")), eq(plus(test.t.a, mul(3, test.t.a)), 5))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1", - "Plan": [ - "TableReader 8000.00 root data:Selection", - "└─Selection 8000.00 cop[tiflash] eq(plus(cast(test.t.a, double BINARY), 3), 5.1)", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select * from t where b > 'a' order by convert(b, unsigned) limit 2", - "Plan": [ - "Projection 2.00 root test.t.a, test.t.b", - "└─TopN 2.00 root Column#4, offset:0, count:2", - " └─Projection 2.00 root test.t.a, test.t.b, cast(test.t.b, bigint(22) UNSIGNED BINARY)->Column#4", - " └─TableReader 2.00 root data:Projection", - " └─Projection 2.00 batchCop[tiflash] test.t.a, test.t.b", - " └─TopN 2.00 batchCop[tiflash] Column#3, offset:0, count:2", - " └─Projection 3333.33 batchCop[tiflash] test.t.a, test.t.b, cast(test.t.b, bigint(22) UNSIGNED BINARY)->Column#3", - " └─Selection 3333.33 batchCop[tiflash] gt(test.t.b, \"a\")", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select * from t where b > 'a' order by b limit 2", - "Plan": [ - "TopN 2.00 root test.t.b, offset:0, count:2", - "└─TableReader 2.00 root data:TopN", - " └─TopN 2.00 batchCop[tiflash] test.t.b, offset:0, count:2", - " └─Selection 3333.33 batchCop[tiflash] gt(test.t.b, \"a\")", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestVerboseExplain", - "Cases": [ - { - "SQL": "explain format = 'verbose' select count(*) from t3", - "Plan": [ - "StreamAgg_20 1.00 137.00 root funcs:count(Column#9)->Column#4", - "└─TableReader_21 1.00 9.68 root data:StreamAgg_8", - " └─StreamAgg_8 1.00 12.68 cop[tikv] funcs:count(1)->Column#9", - " └─TableFullScan_18 3.00 128.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t2", - "Plan": [ - "StreamAgg_25 1.00 69.50 root funcs:count(Column#7)->Column#4", - "└─TableReader_26 1.00 5.17 root data:StreamAgg_9", - " └─StreamAgg_9 1.00 8.18 batchCop[tiflash] funcs:count(1)->Column#7", - " └─TableFullScan_24 3.00 60.50 batchCop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select * from t3 order by a", - "Plan": [ - "Sort_4 3.00 45.85 root test.t3.a", - "└─TableReader_8 3.00 11.78 root data:TableFullScan_7", - " └─TableFullScan_7 3.00 128.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select * from t3 order by b", - "Plan": [ - "Sort_4 3.00 45.85 root test.t3.b", - "└─TableReader_8 3.00 11.78 root data:TableFullScan_7", - " └─TableFullScan_7 3.00 128.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select * from t3 order by a limit 1", - "Plan": [ - "TopN_7 1.00 13.22 root test.t3.a, offset:0, count:1", - "└─TableReader_16 1.00 10.22 root data:TopN_15", - " └─TopN_15 1.00 0.00 cop[tikv] test.t3.a, offset:0, count:1", - " └─TableFullScan_14 3.00 128.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select * from t3 order by b limit 1", - "Plan": [ - "TopN_7 1.00 13.22 root test.t3.b, offset:0, count:1", - "└─TableReader_16 1.00 10.22 root data:TopN_15", - " └─TopN_15 1.00 0.00 cop[tikv] test.t3.b, offset:0, count:1", - " └─TableFullScan_14 3.00 128.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t2 group by a", - "Plan": [ - "TableReader_24 3.00 3.33 root data:ExchangeSender_23", - "└─ExchangeSender_23 3.00 77.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection_22 3.00 0.00 batchCop[tiflash] Column#4", - " └─HashAgg_8 3.00 77.00 batchCop[tiflash] group by:test.t2.a, funcs:count(1)->Column#4", - " └─ExchangeReceiver_21 3.00 68.00 batchCop[tiflash] ", - " └─ExchangeSender_20 3.00 68.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.a, collate: N/A]", - " └─TableFullScan_19 3.00 65.00 batchCop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t3 where b = 0", - "Plan": [ - "StreamAgg_10 1.00 1.33 root funcs:count(1)->Column#4", - "└─IndexReader_15 0.00 1.33 root index:IndexRangeScan_14", - " └─IndexRangeScan_14 0.00 20.00 cop[tikv] table:t3, index:c(b) range:[0,0], keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select /*+ use_index(t3, c) */ count(a) from t3 where b = 0", - "Plan": [ - "StreamAgg_10 1.00 19.33 root funcs:count(test.t3.a)->Column#4", - "└─IndexLookUp_17 0.00 19.33 root ", - " ├─IndexRangeScan_15(Build) 0.00 20.00 cop[tikv] table:t3, index:c(b) range:[0,0], keep order:false", - " └─TableRowIDScan_16(Probe) 0.00 20.00 cop[tikv] table:t3 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t2 where a = 0", - "Plan": [ - "StreamAgg_11 1.00 4.93 root funcs:count(1)->Column#4", - "└─TableReader_23 0.00 4.93 root data:Selection_22", - " └─Selection_22 0.00 74.00 cop[tiflash] eq(test.t2.a, 0)", - " └─TableFullScan_21 3.00 65.00 cop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t3 t join t3 on t.a = t3.b", - "Plan": [ - "StreamAgg_10 1.00 60.22 root funcs:count(1)->Column#7", - "└─HashJoin_40 3.00 51.22 root inner join, equal:[eq(test.t3.a, test.t3.b)]", - " ├─IndexReader_28(Build) 3.00 11.66 root index:IndexFullScan_27", - " │ └─IndexFullScan_27 3.00 150.50 cop[tikv] table:t3, index:c(b) keep order:false", - " └─TableReader_26(Probe) 3.00 10.76 root data:Selection_25", - " └─Selection_25 3.00 137.00 cop[tikv] not(isnull(test.t3.a))", - " └─TableFullScan_24 3.00 128.00 cop[tikv] table:t keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a", - "Plan": [ - "StreamAgg_12 1.00 18.93 root funcs:count(1)->Column#7", - "└─TableReader_44 3.00 9.93 root data:ExchangeSender_43", - " └─ExchangeSender_43 3.00 235.38 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin_40 3.00 235.38 cop[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a)]", - " ├─ExchangeReceiver_19(Build) 3.00 77.00 cop[tiflash] ", - " │ └─ExchangeSender_18 3.00 77.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection_17 3.00 74.00 cop[tiflash] not(isnull(test.t1.a))", - " │ └─TableFullScan_16 3.00 65.00 cop[tiflash] table:t1 keep order:false", - " └─Selection_21(Probe) 3.00 74.00 cop[tiflash] not(isnull(test.t2.a))", - " └─TableFullScan_20 3.00 65.00 cop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a join t3 on t1.b = t3.b", - "Plan": [ - "StreamAgg_15 1.00 60.60 root funcs:count(1)->Column#10", - "└─HashJoin_65 3.00 51.60 root inner join, equal:[eq(test.t1.b, test.t3.b)]", - " ├─IndexReader_53(Build) 3.00 11.66 root index:IndexFullScan_52", - " │ └─IndexFullScan_52 3.00 150.50 cop[tikv] table:t3, index:c(b) keep order:false", - " └─TableReader_39(Probe) 3.00 11.14 root data:ExchangeSender_38", - " └─ExchangeSender_38 3.00 264.38 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin_29 3.00 264.38 cop[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a)]", - " ├─ExchangeReceiver_35(Build) 3.00 106.00 cop[tiflash] ", - " │ └─ExchangeSender_34 3.00 106.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection_33 3.00 103.00 cop[tiflash] not(isnull(test.t1.a)), not(isnull(test.t1.b))", - " │ └─TableFullScan_32 3.00 94.00 cop[tiflash] table:t1 keep order:false", - " └─Selection_37(Probe) 3.00 74.00 cop[tiflash] not(isnull(test.t2.a))", - " └─TableFullScan_36 3.00 65.00 cop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select (2) in (select count(*) from t1) from (select t.b < (select t.b from t2 limit 1 ) from t3 t) t", - "Plan": [ - "HashJoin_19 3.00 127.40 root CARTESIAN left outer semi join", - "├─Selection_39(Build) 0.80 11.18 root eq(2, Column#18)", - "│ └─StreamAgg_60 1.00 69.50 root funcs:count(Column#32)->Column#18", - "│ └─TableReader_61 1.00 5.17 root data:StreamAgg_44", - "│ └─StreamAgg_44 1.00 8.18 batchCop[tiflash] funcs:count(1)->Column#32", - "│ └─TableFullScan_59 3.00 60.50 batchCop[tiflash] table:t1 keep order:false", - "└─Projection_20(Probe) 3.00 95.82 root 1->Column#28", - " └─Apply_22 3.00 76.02 root CARTESIAN left outer join", - " ├─TableReader_24(Build) 3.00 10.16 root data:TableFullScan_23", - " │ └─TableFullScan_23 3.00 128.00 cop[tikv] table:t keep order:false", - " └─Projection_27(Probe) 1.00 21.95 root 1->Column#26", - " └─Limit_30 1.00 3.35 root offset:0, count:1", - " └─TableReader_38 1.00 3.35 root data:ExchangeSender_37", - " └─ExchangeSender_37 1.00 79.50 cop[tiflash] ExchangeType: PassThrough", - " └─Limit_36 1.00 79.50 cop[tiflash] offset:0, count:1", - " └─TableFullScan_35 1.00 79.50 cop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'verbose' select /*+ merge_join(t1) */ count(*) from t1 join t2 on t1.a = t2.a", - "Plan": [ - "StreamAgg_11 1.00 59.65 root funcs:count(1)->Column#7", - "└─MergeJoin_29 3.00 50.65 root inner join, left key:test.t1.a, right key:test.t2.a", - " ├─Sort_27(Build) 3.00 20.83 root test.t2.a", - " │ └─TableReader_26 3.00 6.56 root data:Selection_25", - " │ └─Selection_25 3.00 74.00 cop[tiflash] not(isnull(test.t2.a))", - " │ └─TableFullScan_24 3.00 65.00 cop[tiflash] table:t2 keep order:false", - " └─Sort_20(Probe) 3.00 20.83 root test.t1.a", - " └─TableReader_19 3.00 6.56 root data:Selection_18", - " └─Selection_18 3.00 74.00 cop[tiflash] not(isnull(test.t1.a))", - " └─TableFullScan_17 3.00 65.00 cop[tiflash] table:t1 keep order:false" - ] - } - ] - }, - { - "Name": "TestRegardNULLAsPoint", - "Cases": [ - { - "SQL": "select * from tuk where a<=>null and b=1", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.01 root index:Selection_6", - "└─Selection_6 0.01 cop[tikv] eq(test.tuk.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tik where a<=>null and b=1", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.01 root index:Selection_6", - "└─Selection_6 0.01 cop[tikv] eq(test.tik.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tuk where a<=>null and b>0 and b<2", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.25 root index:Selection_6", - "└─Selection_6 0.25 cop[tikv] eq(test.tuk.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tik where a<=>null and b>0 and b<2", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.25 root index:Selection_6", - "└─Selection_6 0.25 cop[tikv] eq(test.tik.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tuk where a<=>null and b>=1 and b<2", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.25 root index:Selection_6", - "└─Selection_6 0.25 cop[tikv] eq(test.tuk.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tik where a<=>null and b>=1 and b<2", - "PlanEnabled": [ - "IndexReader_6 0.10 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.25 root index:Selection_6", - "└─Selection_6 0.25 cop[tikv] eq(test.tik.b, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 ", - " 1 ", - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tuk where a<=>null and b=1 and c=1", - "PlanEnabled": [ - "IndexReader_6 1.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1 1,NULL 1 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tuk.b, 1), eq(test.tuk.c, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tik where a<=>null and b=1 and c=1", - "PlanEnabled": [ - "IndexReader_6 0.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1 1,NULL 1 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tik.b, 1), eq(test.tik.c, 1)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1 1", - " 1 1" - ] - }, - { - "SQL": "select * from tuk where a=1 and b<=>null and c=1", - "PlanEnabled": [ - "IndexReader_6 1.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[1 NULL 1,1 NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tuk.c, 1)", - " └─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[1 NULL,1 NULL], keep order:false, stats:pseudo" - ], - "Result": [ - "1 1", - "1 1" - ] - }, - { - "SQL": "select * from tik where a=1 and b<=>null and c=1", - "PlanEnabled": [ - "IndexReader_6 0.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[1 NULL 1,1 NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tik.c, 1)", - " └─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[1 NULL,1 NULL], keep order:false, stats:pseudo" - ], - "Result": [ - "1 1", - "1 1" - ] - }, - { - "SQL": "select * from tuk where a<=>null and b<=>null and c=1", - "PlanEnabled": [ - "IndexReader_6 1.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL NULL 1,NULL NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tuk.c, 1), nulleq(test.tuk.b, NULL)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1", - " 1" - ] - }, - { - "SQL": "select * from tik where a<=>null and b<=>null and c=1", - "PlanEnabled": [ - "IndexReader_6 0.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL NULL 1,NULL NULL 1], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] eq(test.tik.c, 1), nulleq(test.tik.b, NULL)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " 1", - " 1" - ] - }, - { - "SQL": "select * from tuk where a<=>null and b<=>null and c<=>null", - "PlanEnabled": [ - "IndexReader_6 1.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL NULL NULL,NULL NULL NULL], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] nulleq(test.tuk.b, NULL), nulleq(test.tuk.c, NULL)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " ", - " " - ] - }, - { - "SQL": "select * from tik where a<=>null and b<=>null and c<=>null", - "PlanEnabled": [ - "IndexReader_6 0.00 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL NULL NULL,NULL NULL NULL], keep order:false, stats:pseudo" - ], - "PlanDisabled": [ - "IndexReader_7 0.00 root index:Selection_6", - "└─Selection_6 0.00 cop[tikv] nulleq(test.tik.b, NULL), nulleq(test.tik.c, NULL)", - " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" - ], - "Result": [ - " ", - " " - ] - } - ] - }, - { - "Name": "TestPushDownToTiFlashWithKeepOrder", - "Cases": [ - { - "SQL": "explain format = 'brief' select max(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:max(test.t.a)->Column#3", - "└─TopN 1.00 root test.t.a:desc, offset:0, count:1", - " └─TableReader 1.00 root data:TopN", - " └─TopN 1.00 batchCop[tiflash] test.t.a:desc, offset:0, count:1", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select min(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:min(test.t.a)->Column#3", - "└─Limit 1.00 root offset:0, count:1", - " └─TableReader 1.00 root data:Limit", - " └─Limit 1.00 cop[tiflash] offset:0, count:1", - " └─TableFullScan 1.00 cop[tiflash] table:t keep order:true, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestMPPJoin", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#17", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] inner join, equal:[eq(test.fact_t.d3_k, test.d3_t.d3_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d3_t.d3_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d3_t keep order:false", - " └─HashJoin(Probe) 8.00 cop[tiflash] inner join, equal:[eq(test.fact_t.d2_k, test.d2_t.d2_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d2_t.d2_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d2_t keep order:false", - " └─HashJoin(Probe) 8.00 cop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k)), not(isnull(test.fact_t.d2_k)), not(isnull(test.fact_t.d3_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 8.00 cop[tiflash] ", - " │ └─ExchangeSender 8.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:d1_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)], other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col1, 10)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col2, 10)], other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10)", - " ├─ExchangeReceiver(Build) 8.00 cop[tiflash] ", - " │ └─ExchangeSender 8.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:d1_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 8.00 root data:ExchangeSender", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8.00 cop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10), other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 8.00 cop[tiflash] ", - " │ └─ExchangeSender 8.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 8.00 cop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:d1_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#12", - "└─TableReader 6.40 root data:ExchangeSender", - " └─ExchangeSender 6.40 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 6.40 cop[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#12", - "└─TableReader 6.40 root data:ExchangeSender", - " └─ExchangeSender 6.40 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 6.40 cop[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 cop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#12", - "└─TableReader 6.40 root data:ExchangeSender", - " └─ExchangeSender 6.40 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 6.40 cop[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#12", - "└─TableReader 6.40 root data:ExchangeSender", - " └─ExchangeSender 6.40 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 6.40 cop[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k > d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 16.00 batchCop[tiflash] CARTESIAN inner join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", - " ├─ExchangeReceiver(Build) 2.00 batchCop[tiflash] ", - " │ └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 batchCop[tiflash] table:d1_t keep order:false", - " └─Selection(Probe) 8.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 8.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k > d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 16.00 batchCop[tiflash] CARTESIAN left outer join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", - " ├─ExchangeReceiver(Build) 2.00 batchCop[tiflash] ", - " │ └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 2.00 batchCop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k > d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 16.00 batchCop[tiflash] CARTESIAN right outer join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", - " ├─ExchangeReceiver(Build) 8.00 batchCop[tiflash] ", - " │ └─ExchangeSender 8.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 8.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 8.00 batchCop[tiflash] table:fact_t keep order:false", - " └─TableFullScan(Probe) 2.00 batchCop[tiflash] table:d1_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where d1_k not in (select d1_k from d1_t)", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─TableReader 6.40 root data:ExchangeSender", - " └─ExchangeSender 6.40 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 6.40 cop[tiflash] CARTESIAN anti semi join, other cond:eq(test.fact_t.d1_k, test.d1_t.d1_k)", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan 2.00 cop[tiflash] table:d1_t keep order:false", - " └─TableFullScan(Probe) 8.00 cop[tiflash] table:fact_t keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPOuterJoinBuildSideForBroadcastJoin", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", - " ├─ExchangeReceiver(Build) 3.00 cop[tiflash] ", - " │ └─ExchangeSender 3.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " │ └─TableFullScan 3.00 cop[tiflash] table:b keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:a keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", - " ├─ExchangeReceiver(Build) 3.00 cop[tiflash] ", - " │ └─ExchangeSender 3.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " │ └─TableFullScan 3.00 cop[tiflash] table:b keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:a keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", - " ├─ExchangeReceiver(Build) 3.00 cop[tiflash] ", - " │ └─ExchangeSender 3.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: N/A]", - " │ └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " │ └─TableFullScan 3.00 cop[tiflash] table:b keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: N/A]", - " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", - " ├─ExchangeReceiver(Build) 3.00 cop[tiflash] ", - " │ └─ExchangeSender 3.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: N/A]", - " │ └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " │ └─TableFullScan 3.00 cop[tiflash] table:b keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: N/A]", - " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPOuterJoinBuildSideForShuffleJoin", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from a left join b on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: N/A]", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─ExchangeReceiver(Probe) 3.00 cop[tiflash] ", - " └─ExchangeSender 3.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: N/A]", - " └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " └─TableFullScan 3.00 cop[tiflash] table:b keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: N/A]", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─ExchangeReceiver(Probe) 3.00 cop[tiflash] ", - " └─ExchangeSender 3.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: N/A]", - " └─Selection 3.00 cop[tiflash] not(isnull(test.b.id))", - " └─TableFullScan 3.00 cop[tiflash] table:b keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPShuffledJoin", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#18)->Column#17", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#18", - " └─HashJoin 128.00 batchCop[tiflash] inner join, equal:[eq(test.fact_t.d3_k, test.d3_t.d3_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d3_t.d3_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d3_t.d3_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d3_t keep order:false", - " └─ExchangeReceiver(Probe) 64.00 batchCop[tiflash] ", - " └─ExchangeSender 64.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d3_k, collate: N/A]", - " └─HashJoin 64.00 batchCop[tiflash] inner join, equal:[eq(test.fact_t.d2_k, test.d2_t.d2_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d2_t.d2_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d2_t.d2_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d2_t keep order:false", - " └─ExchangeReceiver(Probe) 32.00 batchCop[tiflash] ", - " └─ExchangeSender 32.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d2_k, collate: N/A]", - " └─HashJoin 32.00 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k)), not(isnull(test.fact_t.d2_k)), not(isnull(test.fact_t.d3_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d1_k = d2_t.value and fact_t.d1_k = d3_t.value", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#18)->Column#17", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#18", - " └─HashJoin 128.00 batchCop[tiflash] inner join, equal:[eq(test.fact_t.d1_k, test.d3_t.value)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d3_t.value, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d3_t.value))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d3_t keep order:false", - " └─HashJoin(Probe) 64.00 batchCop[tiflash] inner join, equal:[eq(test.fact_t.d1_k, test.d2_t.value)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d2_t.value, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d2_t.value))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d2_t keep order:false", - " └─HashJoin(Probe) 32.00 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)], other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col1, 10)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from (select case when t1.col1 is null then t2.col1 + 5 else 10 end as col1, t2.d1_k as d1_k from fact_t t1 right join fact_t t2 on t1.d1_k = t2.d1_k) fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 5", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#22)->Column#19", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#22", - " └─HashJoin 204.80 batchCop[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─Projection(Probe) 102.40 batchCop[tiflash] test.fact_t.d1_k", - " └─Selection 102.40 batchCop[tiflash] gt(case(isnull(test.fact_t.col1), plus(test.fact_t.col1, 5), 10), 5)", - " └─HashJoin 128.00 batchCop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.fact_t.d1_k)]", - " ├─ExchangeReceiver(Build) 16.00 batchCop[tiflash] ", - " │ └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " │ └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 16.00 batchCop[tiflash] table:t1 keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col2, 10)], other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10)", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#12", - " └─HashJoin 32.00 batchCop[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10), other cond:gt(test.fact_t.col1, test.d1_t.value)", - " ├─ExchangeReceiver(Build) 16.00 batchCop[tiflash] ", - " │ └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " │ └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " │ └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false", - " └─ExchangeReceiver(Probe) 4.00 batchCop[tiflash] ", - " └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#13)->Column#12", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#13", - " └─HashJoin 12.80 batchCop[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#13)->Column#12", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#13", - " └─HashJoin 12.80 batchCop[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─Selection 4.00 batchCop[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─Selection 16.00 batchCop[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#13)->Column#12", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#13", - " └─HashJoin 12.80 batchCop[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#13)->Column#12", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#13", - " └─HashJoin 12.80 batchCop[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", - " ├─ExchangeReceiver(Build) 4.00 batchCop[tiflash] ", - " │ └─ExchangeSender 4.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: N/A]", - " │ └─TableFullScan 4.00 batchCop[tiflash] table:d1_t keep order:false", - " └─ExchangeReceiver(Probe) 16.00 batchCop[tiflash] ", - " └─ExchangeSender 16.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: N/A]", - " └─TableFullScan 16.00 batchCop[tiflash] table:fact_t keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError", - "Cases": [ - { - "SQL": "explain format = 'brief' select v from t3 as a left join (select t1.v1, t1.v2, t1.v1 + t1.v2 as v from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2) b on a.v1 = b.v1 and a.v2 = b.v2", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 cop[tiflash] Column#13", - " └─HashJoin 1.00 cop[tiflash] left outer join, equal:[eq(test.t3.v1, test.t1.v1) eq(test.t3.v2, test.t1.v2)]", - " ├─ExchangeReceiver(Build) 1.00 cop[tiflash] ", - " │ └─ExchangeSender 1.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#23, collate: N/A], [name: Column#24, collate: N/A]", - " │ └─Projection 1.00 cop[tiflash] test.t3.v1, test.t3.v2, cast(test.t3.v1, decimal(20,2))->Column#23, cast(test.t3.v2, decimal(20,2))->Column#24", - " │ └─TableFullScan 1.00 cop[tiflash] table:a keep order:false", - " └─Projection(Probe) 2.00 cop[tiflash] test.t1.v1, test.t1.v2, plus(test.t1.v1, test.t1.v2)->Column#13", - " └─HashJoin 2.00 cop[tiflash] left outer join, equal:[eq(test.t1.v1, test.t2.v1) eq(test.t1.v2, test.t2.v2)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t1.v1, collate: N/A], [name: test.t1.v2, collate: N/A]", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.t1.v1)), not(isnull(test.t1.v2))", - " │ └─TableFullScan 2.00 cop[tiflash] table:t1 keep order:false", - " └─ExchangeReceiver(Probe) 8.00 cop[tiflash] ", - " └─ExchangeSender 8.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#15, collate: N/A], [name: Column#16, collate: N/A]", - " └─Projection 8.00 cop[tiflash] test.t2.v1, test.t2.v2, cast(test.t2.v1, decimal(20,2))->Column#15, cast(test.t2.v2, decimal(20,2))->Column#16", - " └─Selection 8.00 cop[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", - " └─TableFullScan 8.00 cop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*), t2.v1, t2.v2 from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2 group by t2.v1, t2.v2", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 2.00 batchCop[tiflash] Column#9, test.t2.v1, test.t2.v2", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.t2.v1, test.t2.v2, funcs:sum(Column#22)->Column#9, funcs:firstrow(test.t2.v1)->test.t2.v1, funcs:firstrow(test.t2.v2)->test.t2.v2", - " └─ExchangeReceiver 2.00 batchCop[tiflash] ", - " └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: N/A], [name: test.t2.v2, collate: N/A]", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.t2.v1, test.t2.v2, funcs:count(1)->Column#22", - " └─HashJoin 2.00 batchCop[tiflash] left outer join, equal:[eq(test.t1.v1, test.t2.v1) eq(test.t1.v2, test.t2.v2)]", - " ├─ExchangeReceiver(Build) 2.00 batchCop[tiflash] ", - " │ └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t1.v1, collate: N/A], [name: test.t1.v2, collate: N/A]", - " │ └─TableFullScan 2.00 batchCop[tiflash] table:t1 keep order:false", - " └─ExchangeReceiver(Probe) 8.00 batchCop[tiflash] ", - " └─ExchangeSender 8.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#14, collate: N/A], [name: Column#15, collate: N/A]", - " └─Projection 8.00 batchCop[tiflash] test.t2.v1, test.t2.v2, cast(test.t2.v1, decimal(20,2))->Column#14, cast(test.t2.v2, decimal(20,2))->Column#15", - " └─Selection 8.00 batchCop[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", - " └─TableFullScan 8.00 batchCop[tiflash] table:t2 keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select count(*), t2.v1, t2.v2 from t3 left join t2 on t3.v1 = t2.v1 and t3.v2 = t2.v2 group by t2.v1, t2.v2", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#9, test.t2.v1, test.t2.v2", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.t2.v1, test.t2.v2, funcs:sum(Column#16)->Column#9, funcs:firstrow(test.t2.v1)->test.t2.v1, funcs:firstrow(test.t2.v2)->test.t2.v2", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: N/A], [name: test.t2.v2, collate: N/A]", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.t2.v1, test.t2.v2, funcs:count(1)->Column#16", - " └─HashJoin 1.00 batchCop[tiflash] left outer join, equal:[eq(test.t3.v1, test.t2.v1) eq(test.t3.v2, test.t2.v2)]", - " ├─ExchangeReceiver(Build) 1.00 batchCop[tiflash] ", - " │ └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t3.v1, collate: N/A], [name: test.t3.v2, collate: N/A]", - " │ └─TableFullScan 1.00 batchCop[tiflash] table:t3 keep order:false", - " └─ExchangeReceiver(Probe) 8.00 batchCop[tiflash] ", - " └─ExchangeSender 8.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: N/A], [name: test.t2.v2, collate: N/A]", - " └─Selection 8.00 batchCop[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", - " └─TableFullScan 8.00 batchCop[tiflash] table:t2 keep order:false" - ] - } - ] - }, - { - "Name": "TestJoinNotSupportedByTiFlash", - "Cases": [ - { - "SQL": "explain format = 'brief' select * from table_1 a, table_1 b where a.bit_col = b.bit_col", - "Plan": [ - "HashJoin 2.00 root inner join, equal:[eq(test.table_1.bit_col, test.table_1.bit_col)]", - "├─TableReader(Build) 2.00 root data:TableFullScan", - "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", - "└─TableReader(Probe) 2.00 root data:TableFullScan", - " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a left join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > 100", - "Plan": [ - "HashJoin 2.00 root left outer join, equal:[eq(test.table_1.id, test.table_1.id)], left cond:[gt(dayofmonth(test.table_1.datetime_col), 100)]", - "├─TableReader(Build) 2.00 root data:TableFullScan", - "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", - "└─TableReader(Probe) 2.00 root data:TableFullScan", - " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a right join table_1 b on a.id = b.id and dayofmonth(b.datetime_col) > 100", - "Plan": [ - "HashJoin 2.00 root right outer join, equal:[eq(test.table_1.id, test.table_1.id)], right cond:gt(dayofmonth(test.table_1.datetime_col), 100)", - "├─TableReader(Build) 2.00 root data:TableFullScan", - "│ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - "└─TableReader(Probe) 2.00 root data:TableFullScan", - " └─TableFullScan 2.00 cop[tiflash] table:b keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > dayofmonth(b.datetime_col)", - "Plan": [ - "HashJoin 2.00 root inner join, equal:[eq(test.table_1.id, test.table_1.id)], other cond:gt(dayofmonth(test.table_1.datetime_col), dayofmonth(test.table_1.datetime_col))", - "├─TableReader(Build) 2.00 root data:TableFullScan", - "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", - "└─TableReader(Probe) 2.00 root data:TableFullScan", - " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPWithHashExchangeUnderNewCollation", - "Cases": [ - { - "SQL": "explain format = 'brief' select * from table_1 a, table_1 b where a.value = b.value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", - " └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " └─TableFullScan 2.00 cop[tiflash] table:b keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a, table_2 b where a.value = b.value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", - " └─Selection 2.00 cop[tiflash] not(isnull(test.table_2.value))", - " └─TableFullScan 2.00 cop[tiflash] table:b keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and b.value = c.value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_2.value, test.table_1.value)]", - " ├─HashJoin(Build) 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", - " │ ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", - " │ │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " │ │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " │ └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_2.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", - " └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " └─TableFullScan 2.00 cop[tiflash] table:c keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and a.value = c.value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", - " │ └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", - " │ ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", - " │ │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " │ │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " │ └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_2.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", - " └─ExchangeReceiver(Probe) 2.00 cop[tiflash] ", - " └─ExchangeSender 2.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", - " └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " └─TableFullScan 2.00 cop[tiflash] table:c keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_1 group by value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 2.00 batchCop[tiflash] Column#4, test.table_1.value", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.table_1.value, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.table_1.value)->test.table_1.value", - " └─ExchangeReceiver 2.00 batchCop[tiflash] ", - " └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.table_1.value, funcs:count(1)->Column#7", - " └─TableFullScan 2.00 batchCop[tiflash] table:table_1 keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_2 group by value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 2.00 batchCop[tiflash] Column#4, test.table_2.value", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.table_2.value, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.table_2.value)->test.table_2.value", - " └─ExchangeReceiver 2.00 batchCop[tiflash] ", - " └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.table_2.value, funcs:count(1)->Column#7", - " └─TableFullScan 2.00 batchCop[tiflash] table:table_2 keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPWithBroadcastExchangeUnderNewCollation", - "Cases": [ - { - "SQL": "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.id = b.id", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.id, test.table_1.id)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─TableFullScan(Probe) 2.00 cop[tiflash] table:b keep order:false" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.value = b.value", - "Plan": [ - "TableReader 2.00 root data:ExchangeSender", - "└─ExchangeSender 2.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 2.00 cop[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", - " ├─ExchangeReceiver(Build) 2.00 cop[tiflash] ", - " │ └─ExchangeSender 2.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " │ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", - " └─Selection(Probe) 2.00 cop[tiflash] not(isnull(test.table_1.value))", - " └─TableFullScan 2.00 cop[tiflash] table:b keep order:false" - ] - } - ] - }, - { - "Name": "TestMPPAvgRewrite", - "Cases": [ - { - "SQL": "explain format = 'brief' select /*+ avg_to_cop() */ id, avg(value+1),avg(value) from table_1 group by id", - "Plan": [ - "Projection 2.00 root test.table_1.id, Column#4, Column#5", - "└─TableReader 2.00 root data:ExchangeSender", - " └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 2.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#13, 0), 1, Column#13), decimal(20,0) BINARY))->Column#4, div(Column#5, cast(case(eq(Column#14, 0), 1, Column#14), decimal(20,0) BINARY))->Column#5, test.table_1.id", - " └─HashAgg 2.00 batchCop[tiflash] group by:test.table_1.id, funcs:sum(Column#15)->Column#13, funcs:sum(Column#16)->Column#4, funcs:sum(Column#17)->Column#14, funcs:sum(Column#18)->Column#5, funcs:firstrow(test.table_1.id)->test.table_1.id", - " └─ExchangeReceiver 2.00 batchCop[tiflash] ", - " └─ExchangeSender 2.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.id, collate: binary]", - " └─HashAgg 2.00 batchCop[tiflash] group by:Column#29, funcs:count(Column#25)->Column#15, funcs:sum(Column#26)->Column#16, funcs:count(Column#27)->Column#17, funcs:sum(Column#28)->Column#18", - " └─Projection 2.00 batchCop[tiflash] plus(test.table_1.value, 1)->Column#25, plus(test.table_1.value, 1)->Column#26, test.table_1.value, test.table_1.value, test.table_1.id", - " └─TableFullScan 2.00 batchCop[tiflash] table:table_1 keep order:false" - ] - } - ] - }, - { - "Name": "TestReadFromStorageHint", - "Cases": [ - { - "SQL": "desc format = 'brief' select avg(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#7, funcs:sum(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.t.a, cast(test.t.a, decimal(37,4) BINARY)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#7, funcs:sum(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.t.a, cast(test.t.a, decimal(37,4) BINARY)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", - " └─Projection 10000.00 batchCop[tiflash] cast(test.t.a, decimal(32,0) BINARY)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a+1) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.a, 1), decimal(41,0) BINARY)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(isnull(a)) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", - " └─Projection 10000.00 batchCop[tiflash] cast(isnull(test.t.a), decimal(22,0) BINARY)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIKV[t2]) */ * from t t1, t t2 where t1.a = t2.a", - "Plan": [ - "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", - "├─TableReader(Build) 9990.00 root data:Selection", - "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - "└─TableReader(Probe) 9990.00 root data:Selection", - " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", - " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIFLASH[t2]) */ * from t t1, t t2 where t1.a = t2.a", - "Plan": [ - "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", - "├─TableReader(Build) 9990.00 root data:Selection", - "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.a))", - "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", - "└─TableReader(Probe) 9990.00 root data:Selection", - " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", - " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", - "Plan": [ - "TableReader 44.00 root data:TableRangeScan", - "└─TableRangeScan 44.00 cop[tiflash] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[tt]) */ * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", - "Plan": [ - "TableReader 44.00 root data:TableRangeScan", - "└─TableRangeScan 44.00 cop[tiflash] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select * from ttt order by ttt.a desc", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:true, desc, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a desc", - "Plan": [ - "Sort 10000.00 root test.ttt.a:desc", - "└─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:true, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t, ttt]) */ * from ttt", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:false, stats:pseudo" - ], - "Warn": [ - "[planner:1815]There are no matching table names for (t) in optimizer hint /*+ READ_FROM_STORAGE(tikv[t, ttt]) */. Maybe you can use the table alias name" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" - ], - "Warn": [ - "[planner:1815]There are no matching table names for (t, tt) in optimizer hint /*+ READ_FROM_STORAGE(tiflash[t, ttt], tikv[tt]) */. Maybe you can use the table alias name" - ] - } - ] - }, - { - "Name": "TestReadFromStorageHintAndIsolationRead", - "Cases": [ - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t], tiflash[t]) */ avg(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", - "└─IndexReader 1.00 root index:StreamAgg", - " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", - " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" - ], - "Warn": [ - "[planner:1815]Storage hints are conflict, you can only specify one storage type of table test.t" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t]) */ avg(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", - "└─IndexReader 1.00 root index:StreamAgg", - " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", - " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", - "Plan": [ - "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", - "└─IndexReader 1.00 root index:StreamAgg", - " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", - " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" - ], - "Warn": [ - "[planner:1815]No available path for table test.t with the store type tiflash of the hint /*+ read_from_storage */, please check the status of the table replica and variable value of tidb_isolation_read_engines(map[0:{}])" - ] - } - ] - }, - { - "Name": "TestIsolationReadDoNotFilterSystemDB", - "Cases": [ - { - "SQL": "desc format = 'brief' select * from metrics_schema.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'", - "Plan": [ - "MemTableScan 10000.00 root table:tidb_query_duration PromQL:histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance)), start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s" - ] - }, - { - "SQL": "desc format = 'brief' select * from information_schema.tables", - "Plan": [ - "MemTableScan 10000.00 root table:TABLES " - ] - }, - { - "SQL": "desc format = 'brief' select * from mysql.stats_meta", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tikv] table:stats_meta keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestIsolationReadTiFlashNotChoosePointGet", - "Cases": [ - { - "SQL": "explain format = 'brief' select * from t where t.a = 1", - "Result": [ - "TableReader 1.00 root data:TableRangeScan", - "└─TableRangeScan 1.00 cop[tiflash] table:t range:[1,1], keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select * from t where t.a in (1, 2)", - "Result": [ - "TableReader 2.00 root data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tiflash] table:t range:[1,1], [2,2], keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestIsolationReadTiFlashUseIndexHint", - "Cases": [ - { - "SQL": "explain format = 'brief' select * from t", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "explain format = 'brief' select * from t use index();", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - }, - { - "SQL": "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": [ - "TiDB doesn't support index in the isolation read engines(value: 'tiflash')" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ use_index(t)*/ * from t", - "Plan": [ - "TableReader 10000.00 root data:TableFullScan", - "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ], - "Warn": null - } - ] - }, - { - "Name": "TestIssue20710", - "Cases": [ - { - "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.b", - "Plan": [ - "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.b)", - "├─TableReader(Build) 9980.01 root data:Selection", - "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", - " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.a", - "Plan": [ - "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.a)", - "├─TableReader(Build) 9980.01 root data:Selection", - "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.a = s.b", - "Plan": [ - "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.a, test.s.b)", - "├─TableReader(Build) 9990.00 root data:Selection", - "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", - " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.b", - "Plan": [ - "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.b)", - "├─TableReader(Build) 9980.01 root data:Selection", - "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", - " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.a", - "Plan": [ - "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.a)", - "├─TableReader(Build) 9980.01 root data:Selection", - "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.a = s.b", - "Plan": [ - "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.a, test.s.b)", - "├─TableReader(Build) 9990.00 root data:Selection", - "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 1.25 root ", - " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", - " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", - " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", - " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestPushDownProjectionForTiFlash", - "Cases": [ - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#8)->Column#6", - "└─TableReader 1.00 root data:HashAgg", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#7)->Column#6", - "└─TableReader 1.00 root data:HashAgg", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:sum(Column#8)->Column#6", - "└─TableReader 1.00 root data:HashAgg", - " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(41,0) BINARY)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", - "Plan": [ - "StreamAgg 1.00 root funcs:count(Column#8)->Column#6", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", - "Plan": [ - "StreamAgg 1.00 root funcs:count(Column#7)->Column#6", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", - "Plan": [ - "StreamAgg 1.00 root funcs:sum(Column#8)->Column#6", - "└─TableReader 1.00 root data:StreamAgg", - " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#10)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(41,0) BINARY)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "Plan": [ - "TableReader 10000.00 root data:HashJoin", - "└─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(Column#5, Column#10)]", - " ├─Projection(Build) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#5", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─Projection(Probe) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#10", - " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 10000.00 root data:HashJoin", - "└─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(test.t.id, Column#9)]", - " ├─Projection(Build) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 10000.00 root data:HashJoin", - "└─HashJoin 10000.00 cop[tiflash] left outer join, equal:[eq(test.t.id, Column#9)]", - " ├─Projection(Build) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─TableFullScan(Probe) 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 12487.50 root data:HashJoin", - "└─HashJoin 12487.50 cop[tiflash] right outer join, equal:[eq(test.t.id, Column#9)]", - " ├─Selection(Build) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─Projection(Probe) 10000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "Plan": [ - "Projection 10000.00 root Column#10, Column#5", - "└─TableReader 10000.00 root data:HashJoin", - " └─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(Column#5, Column#10)]", - " ├─Projection(Build) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#5", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─Projection(Probe) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#10", - " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select A.id from t as A where exists (select 1 from t where t.id=A.id)", - "Plan": [ - "TableReader 7992.00 root data:HashJoin", - "└─HashJoin 7992.00 cop[tiflash] semi join, equal:[eq(test.t.id, test.t.id)]", - " ├─Selection(Build) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select A.id from t as A where not exists (select 1 from t where t.id=A.id)", - "Plan": [ - "TableReader 8000.00 root data:HashJoin", - "└─HashJoin 8000.00 cop[tiflash] anti semi join, equal:[eq(test.t.id, test.t.id)]", - " ├─TableFullScan(Build) 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo, global read", - " └─TableFullScan(Probe) 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;", - "Plan": [ - "Projection 10000.00 root from_unixtime(cast(test.t.name, decimal(65,0) BINARY), %Y-%m-%d)->Column#5", - "└─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestPushDownProjectionForMPP", - "Cases": [ - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#9)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#11)->Column#9", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#8)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#8", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:sum(Column#9)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#11)->Column#9", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(41,0) BINARY)->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#10)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#11)->Column#10", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#9)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#9", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:sum(Column#10)->Column#6", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#11)->Column#10", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(41,0) BINARY)->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select B.b+A.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "Plan": [ - "TableReader 10000.00 root data:ExchangeSender", - "└─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─Projection 10000.00 cop[tiflash] plus(Column#5, Column#10)->Column#11", - " └─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(Column#5, Column#10)]", - " ├─ExchangeReceiver(Build) 8000.00 cop[tiflash] ", - " │ └─ExchangeSender 8000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#5", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#10", - " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 10000.00 root data:ExchangeSender", - "└─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(test.t.id, Column#9)]", - " ├─ExchangeReceiver(Build) 8000.00 cop[tiflash] ", - " │ └─ExchangeSender 8000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 10000.00 root data:ExchangeSender", - "└─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 10000.00 cop[tiflash] left outer join, equal:[eq(test.t.id, Column#9)]", - " ├─ExchangeReceiver(Build) 8000.00 cop[tiflash] ", - " │ └─ExchangeSender 8000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─TableFullScan(Probe) 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", - "Plan": [ - "TableReader 12487.50 root data:ExchangeSender", - "└─ExchangeSender 12487.50 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12487.50 cop[tiflash] right outer join, equal:[eq(test.t.id, Column#9)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 10000.00 cop[tiflash] minus(test.t.id, 2)->Column#9", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", - "Plan": [ - "TableReader 10000.00 root data:ExchangeSender", - "└─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─Projection 10000.00 cop[tiflash] Column#10, Column#5", - " └─HashJoin 10000.00 cop[tiflash] inner join, equal:[eq(Column#5, Column#10)]", - " ├─ExchangeReceiver(Build) 8000.00 cop[tiflash] ", - " │ └─ExchangeSender 8000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#5", - " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 8000.00 cop[tiflash] minus(test.t.id, 2)->Column#10", - " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select id from t as A where exists (select 1 from t where t.id=A.id)", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 cop[tiflash] semi join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select id from t as A where not exists (select 1 from t where t.id=A.id)", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8000.00 cop[tiflash] anti semi join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─TableFullScan(Probe) 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select b*2, id from (select avg(value+2) as b, id from t group by id) C order by id", - "Plan": [ - "Sort 8000.00 root test.t.id", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] mul(Column#5, 2)->Column#6, test.t.id", - " └─Projection 8000.00 batchCop[tiflash] div(Column#5, cast(case(eq(Column#20, 0), 1, Column#20), decimal(20,0) BINARY))->Column#5, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#21)->Column#20, funcs:sum(Column#22)->Column#5, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#26, funcs:count(Column#24)->Column#21, funcs:sum(Column#25)->Column#22", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.value, 2)->Column#24, plus(test.t.value, 2)->Column#25, test.t.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;", - "Plan": [ - "TableReader 10000.00 root data:ExchangeSender", - "└─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─Projection 10000.00 cop[tiflash] from_unixtime(cast(test.t.name, decimal(65,0) BINARY), %Y-%m-%d)->Column#5", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestMppUnionAll", - "Cases": [ - { - "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1) tt", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#12)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 cop[tiflash] funcs:count(1)->Column#12", - " └─Union 20000.00 cop[tiflash] ", - " ├─Projection 10000.00 cop[tiflash] cast(test.t.a, int(11) BINARY)->Column#9, test.t.b", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection 10000.00 cop[tiflash] test.t1.a, cast(test.t1.b, int(11) BINARY)->Column#10", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1 union all select a, b from t where false) tt", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#16)->Column#15", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 cop[tiflash] funcs:count(1)->Column#16", - " └─Union 20000.00 cop[tiflash] ", - " ├─Projection 10000.00 cop[tiflash] cast(test.t.a, int(11) BINARY)->Column#13, test.t.b", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection 10000.00 cop[tiflash] test.t1.a, cast(test.t1.b, int(11) BINARY)->Column#14", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1) tt", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#14)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 cop[tiflash] funcs:count(1)->Column#14", - " └─Union 20000.00 cop[tiflash] ", - " ├─Projection 10000.00 cop[tiflash] cast(Column#9, int(11) BINARY)->Column#9, Column#10", - " │ └─Projection 10000.00 cop[tiflash] test.t.a, cast(test.t.b, double BINARY)->Column#10", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection 10000.00 cop[tiflash] test.t1.a, cast(test.t1.c, double BINARY)->Column#10", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1 where false) tt", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#14)->Column#11", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#14", - " └─Union 10000.00 batchCop[tiflash] ", - " └─Projection 10000.00 batchCop[tiflash] cast(Column#9, int(11) BINARY)->Column#9, Column#10", - " └─Projection 10000.00 batchCop[tiflash] test.t.a, cast(test.t.b, double BINARY)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "explain format = 'brief' select count(*) from (select a , b from t where false union all select a , c from t1 where false) tt", - "Plan": [ - "StreamAgg 1.00 root funcs:count(1)->Column#11", - "└─Union 0.00 root ", - " ├─Projection 0.00 root test.t.a, cast(test.t.b, double BINARY)->Column#10", - " │ └─TableDual 0.00 root rows:0", - " └─Projection 0.00 root test.t1.a, cast(test.t1.c, double BINARY)->Column#10", - " └─TableDual 0.00 root rows:0" - ] - } - ] - }, - { - "Name": "TestMppJoinDecimal", - "Cases": [ - { - "SQL": "desc format = 'brief' select t1.c1, t1.c2, t2.c1, t2.c2, t2.c3 from t t1 join t t2 on t1.c1 + 1 = t2.c2 - 10 and t1.c1 * 3 = t2.c3 / 2", - "Plan": [ - "Projection 12500.00 root test.t.c1, test.t.c2, test.t.c1, test.t.c2, test.t.c3", - "└─TableReader 12500.00 root data:ExchangeSender", - " └─ExchangeSender 12500.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12500.00 cop[tiflash] inner join, equal:[eq(Column#13, Column#14) eq(Column#15, Column#16)]", - " ├─ExchangeReceiver(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#21, collate: N/A], [name: Column#15, collate: N/A]", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, Column#13, Column#15, cast(Column#13, decimal(34,8) BINARY)->Column#21", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, mul(test.t.c1, 3)->Column#13, plus(test.t.c1, 1)->Column#15", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 10000.00 cop[tiflash] ", - " └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#22, collate: N/A], [name: Column#16, collate: N/A]", - " └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, Column#14, Column#16, cast(Column#14, decimal(34,8) BINARY)->Column#22", - " └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, div(test.t.c3, 2)->Column#14, minus(test.t.c2, 10)->Column#16", - " └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select c1, c2, c5, count(*) c from t group by c1, c2, c5) t1 join (select c1, c2, c3, count(*) c from t group by c1, c2, c3) t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c5 = t2.c1", - "Plan": [ - "Projection 7976.02 root test.t.c1, test.t.c2, test.t.c5, Column#7, test.t.c1, test.t.c2, test.t.c3, Column#14", - "└─TableReader 7976.02 root data:ExchangeSender", - " └─ExchangeSender 7976.02 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7976.02 batchCop[tiflash] inner join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c3) eq(test.t.c5, test.t.c1)]", - " ├─ExchangeReceiver(Build) 7976.02 batchCop[tiflash] ", - " │ └─ExchangeSender 7976.02 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A], [name: Column#31, collate: N/A], [name: test.t.c5, collate: N/A]", - " │ └─Projection 7976.02 batchCop[tiflash] Column#7, test.t.c1, test.t.c2, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#31", - " │ └─Projection 7976.02 batchCop[tiflash] Column#7, test.t.c1, test.t.c2, test.t.c5", - " │ └─HashAgg 7976.02 batchCop[tiflash] group by:test.t.c1, test.t.c2, test.t.c5, funcs:sum(Column#15)->Column#7, funcs:firstrow(test.t.c1)->test.t.c1, funcs:firstrow(test.t.c2)->test.t.c2, funcs:firstrow(test.t.c5)->test.t.c5", - " │ └─ExchangeReceiver 7976.02 batchCop[tiflash] ", - " │ └─ExchangeSender 7976.02 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A], [name: test.t.c2, collate: N/A], [name: test.t.c5, collate: N/A]", - " │ └─HashAgg 7976.02 batchCop[tiflash] group by:test.t.c1, test.t.c2, test.t.c5, funcs:count(1)->Column#15", - " │ └─Selection 9970.03 batchCop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 7984.01 batchCop[tiflash] ", - " └─ExchangeSender 7984.01 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A], [name: Column#32, collate: N/A], [name: Column#33, collate: N/A]", - " └─Projection 7984.01 batchCop[tiflash] Column#14, test.t.c1, test.t.c2, test.t.c3, cast(test.t.c3, decimal(10,5))->Column#32, cast(test.t.c1, decimal(40,20))->Column#33", - " └─Projection 7984.01 batchCop[tiflash] Column#14, test.t.c1, test.t.c2, test.t.c3", - " └─HashAgg 7984.01 batchCop[tiflash] group by:test.t.c1, test.t.c2, test.t.c3, funcs:sum(Column#23)->Column#14, funcs:firstrow(test.t.c1)->test.t.c1, funcs:firstrow(test.t.c2)->test.t.c2, funcs:firstrow(test.t.c3)->test.t.c3", - " └─ExchangeReceiver 7984.01 batchCop[tiflash] ", - " └─ExchangeSender 7984.01 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A], [name: test.t.c3, collate: N/A], [name: test.t.c1, collate: N/A]", - " └─HashAgg 7984.01 batchCop[tiflash] group by:test.t.c1, test.t.c2, test.t.c3, funcs:count(1)->Column#23", - " └─Selection 9980.01 batchCop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c2 and t1.c3 = t2.c3 and t1.c4 = t2.c4 and t1.c5 = t2.c5", - "Plan": [ - "TableReader 12462.54 root data:ExchangeSender", - "└─ExchangeSender 12462.54 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12462.54 cop[tiflash] inner join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c2) eq(test.t.c3, test.t.c3) eq(test.t.c4, test.t.c4) eq(test.t.c5, test.t.c5)]", - " ├─ExchangeReceiver(Build) 9970.03 cop[tiflash] ", - " │ └─ExchangeSender 9970.03 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A], [name: test.t.c2, collate: N/A], [name: test.t.c3, collate: N/A], [name: test.t.c4, collate: N/A], [name: test.t.c5, collate: N/A]", - " │ └─Selection 9970.03 cop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9980.01 cop[tiflash] ", - " └─ExchangeSender 9980.01 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A], [name: test.t.c2, collate: N/A], [name: test.t.c3, collate: N/A], [name: test.t.c4, collate: N/A], [name: test.t.c5, collate: N/A]", - " └─Selection 9980.01 cop[tiflash] not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5", - "Plan": [ - "Projection 12462.54 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", - "└─TableReader 12462.54 root data:ExchangeSender", - " └─ExchangeSender 12462.54 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12462.54 cop[tiflash] inner join, equal:[eq(test.t.c2, test.t.c1) eq(test.t.c3, test.t.c2) eq(test.t.c1, test.t.c3) eq(test.t.c3, test.t.c4) eq(test.t.c5, test.t.c1)]", - " ├─ExchangeReceiver(Build) 9970.03 cop[tiflash] ", - " │ └─ExchangeSender 9970.03 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A], [name: Column#13, collate: N/A], [name: Column#15, collate: N/A], [name: test.t.c3, collate: N/A], [name: test.t.c5, collate: N/A]", - " │ └─Projection 9970.03 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c3, decimal(10,5))->Column#13, cast(test.t.c1, decimal(10,5))->Column#15", - " │ └─Selection 9970.03 cop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9980.01 cop[tiflash] ", - " └─ExchangeSender 9980.01 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A], [name: Column#14, collate: N/A], [name: Column#16, collate: N/A], [name: test.t.c4, collate: N/A], [name: Column#17, collate: N/A]", - " └─Projection 9980.01 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#14, cast(test.t.c3, decimal(10,5))->Column#16, cast(test.t.c1, decimal(40,20))->Column#17", - " └─Selection 9980.01 cop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 + t1.c2 = t2.c2 / t2.c3", - "Plan": [ - "Projection 12500.00 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", - "└─TableReader 12500.00 root data:ExchangeSender", - " └─ExchangeSender 12500.00 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12500.00 cop[tiflash] inner join, equal:[eq(Column#13, Column#14)]", - " ├─ExchangeReceiver(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: N/A]", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, Column#13, cast(Column#13, decimal(17,9) BINARY)->Column#17", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, plus(test.t.c1, test.t.c2)->Column#13", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 10000.00 cop[tiflash] ", - " └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#14, collate: N/A]", - " └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, div(test.t.c2, test.t.c3)->Column#14", - " └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t t1 where exists (select * from t t2 where t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5)", - "Plan": [ - "Projection 7984.01 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", - "└─TableReader 7984.01 root data:ExchangeSender", - " └─ExchangeSender 7984.01 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7984.01 cop[tiflash] semi join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c3) eq(test.t.c3, test.t.c1) eq(test.t.c4, test.t.c3) eq(test.t.c1, test.t.c5)]", - " ├─ExchangeReceiver(Build) 9970.03 cop[tiflash] ", - " │ └─ExchangeSender 9970.03 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A], [name: Column#14, collate: N/A], [name: Column#16, collate: N/A], [name: test.t.c3, collate: N/A], [name: test.t.c5, collate: N/A]", - " │ └─Projection 9970.03 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c5, cast(test.t.c3, decimal(10,5))->Column#14, cast(test.t.c1, decimal(10,5))->Column#16", - " │ └─Selection 9970.03 cop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9980.01 cop[tiflash] ", - " └─ExchangeSender 9980.01 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A], [name: Column#13, collate: N/A], [name: Column#15, collate: N/A], [name: test.t.c4, collate: N/A], [name: Column#17, collate: N/A]", - " └─Projection 9980.01 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#13, cast(test.t.c3, decimal(10,5))->Column#15, cast(test.t.c1, decimal(40,20))->Column#17", - " └─Selection 9980.01 cop[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t t1 left join t t2 on t1.c1 = t2.c2 join t t3 on t2.c5 = t3.c3 right join t t4 on t3.c3 = t4.c4 ", - "Plan": [ - "Projection 19492.21 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", - "└─TableReader 19492.21 root data:ExchangeSender", - " └─ExchangeSender 19492.21 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 19492.21 cop[tiflash] right outer join, equal:[eq(test.t.c3, test.t.c4)]", - " ├─ExchangeReceiver(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#27, collate: N/A]", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c4, decimal(40,20))->Column#27", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t4 keep order:false, stats:pseudo", - " └─Projection(Probe) 15593.77 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", - " └─HashJoin 15593.77 cop[tiflash] inner join, equal:[eq(test.t.c5, test.t.c3)]", - " ├─ExchangeReceiver(Build) 10000.00 cop[tiflash] ", - " │ └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#25, collate: N/A]", - " │ └─Projection 10000.00 cop[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c3, decimal(40,20))->Column#25", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t3 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 12475.01 cop[tiflash] ", - " └─ExchangeSender 12475.01 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c5, collate: N/A]", - " └─HashJoin 12475.01 cop[tiflash] inner join, equal:[eq(test.t.c2, test.t.c1)]", - " ├─ExchangeReceiver(Build) 9980.01 cop[tiflash] ", - " │ └─ExchangeSender 9980.01 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: N/A]", - " │ └─Selection 9980.01 cop[tiflash] not(isnull(test.t.c2)), not(isnull(test.t.c5))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 cop[tiflash] ", - " └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: N/A]", - " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.c1))", - " └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' SELECT STRAIGHT_JOIN t1 . col_varchar_64 , t1 . col_char_64_not_null FROM tt AS t1 INNER JOIN( tt AS t2 JOIN tt AS t3 ON(t3 . col_decimal_30_10_key = t2 . col_tinyint)) ON(t3 . col_varchar_64 = t2 . col_varchar_key) WHERE t3 . col_varchar_64 = t1 . col_char_64_not_null GROUP BY 1 , 2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] test.tt.col_varchar_64, test.tt.col_char_64_not_null", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.tt.col_char_64_not_null, test.tt.col_varchar_64, funcs:firstrow(test.tt.col_varchar_64)->test.tt.col_varchar_64, funcs:firstrow(test.tt.col_char_64_not_null)->test.tt.col_char_64_not_null", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_64, collate: N/A], [name: test.tt.col_char_64_not_null, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.tt.col_char_64_not_null, test.tt.col_varchar_64, ", - " └─HashJoin 15609.38 batchCop[tiflash] inner join, equal:[eq(test.tt.col_char_64_not_null, test.tt.col_varchar_64)]", - " ├─ExchangeReceiver(Build) 10000.00 batchCop[tiflash] ", - " │ └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_char_64_not_null, collate: N/A]", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo", - " └─HashJoin(Probe) 12487.50 batchCop[tiflash] inner join, equal:[eq(test.tt.col_varchar_key, test.tt.col_varchar_64) eq(Column#19, test.tt.col_decimal_30_10_key)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_key, collate: N/A]", - " │ └─Projection 9990.00 batchCop[tiflash] test.tt.col_varchar_key, cast(test.tt.col_tinyint, decimal(20,0) BINARY)->Column#19", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.tt.col_varchar_key))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t2 keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_64, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.tt.col_varchar_64))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t3 keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestPushDownAggForMPP", - "Cases": [ - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#8)->Column#5", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#9", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id+1 from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#7)->Column#5", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", - "Plan": [ - "HashAgg 1.00 root funcs:sum(Column#8)->Column#5", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#9)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(41,0) BINARY)->Column#9", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*) from t", - "Plan": [ - "HashAgg 1.00 root funcs:count(Column#6)->Column#4", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#6", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*), id from t group by id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*), id + 1 from t group by id + 1", - "Plan": [ - "Projection 8000.00 root Column#4, plus(test.t.id, 1)->Column#5", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#10, funcs:sum(Column#11)->Column#4, funcs:firstrow(Column#12)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#10, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#17, funcs:count(1)->Column#11, funcs:firstrow(Column#16)->Column#12", - " └─Projection 10000.00 batchCop[tiflash] test.t.id, plus(test.t.id, 1)->Column#17", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", - "Plan": [ - "TableReader 9990.00 root data:ExchangeSender", - "└─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─Projection(Build) 7992.00 batchCop[tiflash] Column#7, test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#8", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", - "Plan": [ - "HashJoin 1.25 root inner join, equal:[eq(test.t.id, Column#7)]", - "├─HashAgg(Build) 1.00 root funcs:count(Column#11)->Column#7", - "│ └─TableReader 1.00 root data:ExchangeSender", - "│ └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - "│ └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#11", - "│ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - "└─TableReader(Probe) 9990.00 root data:Selection", - " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select avg(value) as b,id from t group by id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#9, 0), 1, Column#9), decimal(20,0) BINARY))->Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#10)->Column#9, funcs:sum(Column#11)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#10, funcs:sum(test.t.value)->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(b) from (select avg(value) as b, id from t group by id)A", - "Plan": [ - "HashAgg 1.00 root funcs:sum(Column#20)->Column#5", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#4)->Column#20", - " └─Projection 8000.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#17, 0), 1, Column#17), decimal(20,0) BINARY))->Column#4", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#18)->Column#17, funcs:sum(Column#19)->Column#4", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#18, funcs:sum(test.t.value)->Column#19", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select id from t group by id having avg(value)>0", - "Plan": [ - "Projection 6400.00 root test.t.id", - "└─Selection 6400.00 root gt(Column#4, 0)", - " └─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#10, 0), 1, Column#10), decimal(20,0) BINARY))->Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#11)->Column#10, funcs:sum(Column#12)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#11, funcs:sum(test.t.value)->Column#12", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select avg(value),id from t group by id having avg(value)>0", - "Plan": [ - "Selection 6400.00 root gt(Column#4, 0)", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#12)->Column#11, funcs:sum(Column#13)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#12, funcs:sum(test.t.value)->Column#13", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select avg(value) +1,id from t group by id", - "Plan": [ - "Projection 8000.00 root plus(Column#4, 1)->Column#5, test.t.id", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] div(Column#4, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#12)->Column#11, funcs:sum(Column#13)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#12, funcs:sum(test.t.value)->Column#13", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 7992.00 batchCop[tiflash] Column#7", - " └─HashAgg 7992.00 batchCop[tiflash] group by:Column#11, funcs:sum(Column#10)->Column#7", - " └─Projection 12487.50 batchCop[tiflash] cast(test.t.id, decimal(32,0) BINARY)->Column#10, test.t.id", - " └─HashJoin 12487.50 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─Projection(Build) 7992.00 batchCop[tiflash] test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, ", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 7992.00 batchCop[tiflash] Column#11, test.t.id", - " └─HashAgg 7992.00 batchCop[tiflash] group by:Column#39, funcs:sum(Column#37)->Column#11, funcs:firstrow(Column#38)->test.t.id", - " └─Projection 9990.00 batchCop[tiflash] cast(test.t.id, decimal(32,0) BINARY)->Column#37, test.t.id, test.t.id", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─Projection(Build) 7992.00 batchCop[tiflash] test.t.id, Column#13", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id, funcs:sum(Column#17)->Column#13", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#17", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(distinct value),id from t group by id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#4, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(distinct test.t.value)->Column#4, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, test.t.value, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(distinct value),sum(distinct value),id from t group by id", - "Plan": [ - "HashAgg 8000.00 root group by:test.t.id, funcs:count(distinct test.t.value)->Column#4, funcs:sum(distinct test.t.value)->Column#5, funcs:firstrow(test.t.id)->test.t.id", - "└─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select count(distinct value), id from t group by id) as A on A.id = t.id", - "Plan": [ - "TableReader 9990.00 root data:ExchangeSender", - "└─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─Projection(Build) 7992.00 batchCop[tiflash] Column#7, test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:count(distinct test.t.value)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, test.t.value, ", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select count(1/value), id from t group by id) as A on A.id = t.id", - "Plan": [ - "TableReader 9990.00 root data:ExchangeSender", - "└─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─Projection(Build) 7992.00 batchCop[tiflash] Column#7, test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:Column#19, funcs:count(Column#18)->Column#8", - " │ └─Projection 9990.00 batchCop[tiflash] div(1, test.t.value)->Column#18, test.t.id", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 9990.00 batchCop[tiflash] ", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(id) from (select value, id from t where id > value group by id, value)A group by value /*the exchange should have only one partition column: test.t.value*/", - "Plan": [ - "TableReader 6400.00 root data:ExchangeSender", - "└─ExchangeSender 6400.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 6400.00 batchCop[tiflash] Column#4", - " └─HashAgg 6400.00 batchCop[tiflash] group by:Column#22, funcs:sum(Column#21)->Column#4", - " └─Projection 6400.00 batchCop[tiflash] cast(test.t.id, decimal(32,0) BINARY)->Column#21, test.t.value", - " └─Projection 6400.00 batchCop[tiflash] test.t.id, test.t.value", - " └─HashAgg 6400.00 batchCop[tiflash] group by:test.t.id, test.t.value, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", - " └─ExchangeReceiver 6400.00 batchCop[tiflash] ", - " └─ExchangeSender 6400.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.value, collate: N/A]", - " └─HashAgg 6400.00 batchCop[tiflash] group by:test.t.id, test.t.value, ", - " └─Selection 8000.00 batchCop[tiflash] gt(cast(test.t.id, decimal(20,0) BINARY), test.t.value)", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(B.value) from t as B where B.id+1 > (select count(*) from t where t.id= B.id and t.value=B.value) group by B.id /*the exchange should have only one partition column: test.t.id*/", - "Plan": [ - "TableReader 6400.00 root data:ExchangeSender", - "└─ExchangeSender 6400.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 6400.00 batchCop[tiflash] Column#8", - " └─HashAgg 6400.00 batchCop[tiflash] group by:test.t.id, funcs:sum(test.t.value)->Column#8", - " └─Selection 8000.00 batchCop[tiflash] gt(plus(test.t.id, 1), ifnull(Column#7, 0))", - " └─HashJoin 10000.00 batchCop[tiflash] left outer join, equal:[eq(test.t.id, test.t.id) eq(test.t.value, test.t.value)]", - " ├─Projection(Build) 7984.01 batchCop[tiflash] Column#7, test.t.id, test.t.value", - " │ └─HashAgg 7984.01 batchCop[tiflash] group by:test.t.id, test.t.value, funcs:sum(Column#24)->Column#7, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", - " │ └─ExchangeReceiver 7984.01 batchCop[tiflash] ", - " │ └─ExchangeSender 7984.01 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7984.01 batchCop[tiflash] group by:test.t.id, test.t.value, funcs:count(1)->Column#24", - " │ └─Selection 9980.01 batchCop[tiflash] not(isnull(test.t.id)), not(isnull(test.t.value))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─ExchangeReceiver(Probe) 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:B keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(distinct value) from t", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#4", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(distinct test.t.value)->Column#4", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.t.value, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(distinct x ) from (select count(distinct value) x from t) t", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(distinct Column#4)->Column#5", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#4, ", - " └─Projection 1.00 batchCop[tiflash] Column#4", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(distinct test.t.value)->Column#4", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.t.value, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(distinct value), count(value), avg(value) from t", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#4, Column#5, div(Column#6, cast(case(eq(Column#7, 0), 1, Column#7), decimal(20,0) BINARY))->Column#6", - " └─HashAgg 1.00 batchCop[tiflash] funcs:count(distinct test.t.value)->Column#4, funcs:sum(Column#8)->Column#5, funcs:sum(Column#9)->Column#7, funcs:sum(Column#10)->Column#6", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.t.value, funcs:count(test.t.value)->Column#8, funcs:count(test.t.value)->Column#9, funcs:sum(test.t.value)->Column#10", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestMppAggTopNWithJoin", - "Cases": [ - { - "SQL": "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", - "Plan": [ - "TableReader 9990.00 root data:ExchangeSender", - "└─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 7992.00 batchCop[tiflash] Column#7, test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#8", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select count(*)+id as v from t group by id) as A on A.v = t.id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 8000.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, Column#8)]", - " ├─ExchangeReceiver(Build) 6400.00 batchCop[tiflash] ", - " │ └─ExchangeSender 6400.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 6400.00 batchCop[tiflash] plus(Column#7, test.t.id)->Column#8", - " │ └─Selection 6400.00 batchCop[tiflash] not(isnull(plus(Column#7, test.t.id)))", - " │ └─Projection 8000.00 batchCop[tiflash] Column#7, test.t.id", - " │ └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#11)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " │ └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#11", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select count(*) as v, id from t group by value,id having value+v <10) as A on A.id = t.id", - "Plan": [ - "Projection 7992.00 root test.t.id, test.t.value, Column#7, test.t.id", - "└─TableReader 7992.00 root data:ExchangeSender", - " └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 6393.60 batchCop[tiflash] ", - " │ └─ExchangeSender 6393.60 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 6393.60 batchCop[tiflash] lt(plus(test.t.value, cast(Column#7, decimal(20,0) BINARY)), 10)", - " │ └─Projection 7992.00 batchCop[tiflash] Column#7, test.t.id, test.t.value", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, test.t.value, funcs:sum(Column#10)->Column#7, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.value, collate: N/A], [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, test.t.value, funcs:count(1)->Column#10", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", - "Plan": [ - "HashJoin 1.25 root inner join, equal:[eq(test.t.id, Column#7)]", - "├─HashAgg(Build) 1.00 root funcs:count(Column#10)->Column#7", - "│ └─TableReader 1.00 root data:ExchangeSender", - "│ └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - "│ └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#10", - "│ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - "└─TableReader(Probe) 9990.00 root data:Selection", - " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 7992.00 batchCop[tiflash] Column#7", - " └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7", - " └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 7992.00 batchCop[tiflash] group by:Column#11, funcs:sum(Column#10)->Column#8", - " └─Projection 12487.50 batchCop[tiflash] cast(test.t.id, decimal(32,0) BINARY)->Column#10, test.t.id", - " └─HashJoin 12487.50 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(value),id from t group by id)B on C.id=B.id", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 7992.00 batchCop[tiflash] test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, ", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 7992.00 batchCop[tiflash] Column#7, test.t.id", - " └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#9)->Column#7, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(test.t.value)->Column#9", - " └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", - "Plan": [ - "TableReader 7992.00 root data:ExchangeSender", - "└─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 7992.00 batchCop[tiflash] test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, ", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 7992.00 batchCop[tiflash] Column#11, test.t.id", - " └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:sum(Column#17)->Column#11, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " └─HashAgg 7992.00 batchCop[tiflash] group by:Column#33, funcs:sum(Column#32)->Column#17", - " └─Projection 9990.00 batchCop[tiflash] cast(test.t.id, decimal(32,0) BINARY)->Column#32, test.t.id", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 7992.00 batchCop[tiflash] test.t.id, Column#13", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id, funcs:sum(Column#16)->Column#13", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:count(1)->Column#16", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value limit 1", - "Plan": [ - "TopN 1.00 root test.t.value, offset:0, count:1", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TopN 1.00 batchCop[tiflash] test.t.value, offset:0, count:1", - " └─HashJoin 12487.50 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value % 100 limit 1", - "Plan": [ - "Projection 1.00 root test.t.id, test.t.value, test.t.id, test.t.value", - "└─TopN 1.00 root Column#8, offset:0, count:1", - " └─Projection 1.00 root test.t.id, test.t.value, test.t.id, test.t.value, mod(test.t.value, 100)->Column#8", - " └─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] test.t.id, test.t.value, test.t.id, test.t.value", - " └─TopN 1.00 batchCop[tiflash] Column#7, offset:0, count:1", - " └─Projection 12487.50 batchCop[tiflash] test.t.id, test.t.value, test.t.id, test.t.value, mod(test.t.value, 100)->Column#7", - " └─HashJoin 12487.50 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id order by t.value limit 20) v group by v.v1", - "Plan": [ - "HashAgg 20.00 root group by:test.t.value, funcs:count(1)->Column#7", - "└─TopN 20.00 root test.t.value, offset:0, count:20", - " └─TableReader 20.00 root data:ExchangeSender", - " └─ExchangeSender 20.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TopN 20.00 batchCop[tiflash] test.t.value, offset:0, count:20", - " └─HashJoin 12487.50 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 batchCop[tiflash] ", - " │ └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", - "Plan": [ - "Limit 1.00 root offset:0, count:1", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─Limit 1.00 cop[tiflash] offset:0, count:1", - " └─HashJoin 12487.50 cop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 0.80 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", - "Plan": [ - "Limit 1.00 root offset:0, count:1", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 cop[tiflash] ExchangeType: PassThrough", - " └─Limit 1.00 cop[tiflash] offset:0, count:1", - " └─HashJoin 12487.50 cop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 0.80 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id limit 20) v group by v.v1", - "Plan": [ - "HashAgg 20.00 root group by:test.t.value, funcs:count(1)->Column#7", - "└─Limit 20.00 root offset:0, count:20", - " └─TableReader 20.00 root data:ExchangeSender", - " └─ExchangeSender 20.00 cop[tiflash] ExchangeType: PassThrough", - " └─Limit 20.00 cop[tiflash] offset:0, count:20", - " └─HashJoin 12487.50 cop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 16.02 cop[tiflash] table:t1 keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestIndexMerge", - "Cases": [ - { - "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and b+2>1)", - "Plan": [ - "IndexMerge 8.00 root ", - "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", - "├─Selection(Build) 0.80 cop[tikv] 1", - "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", - "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" - ], - "Warnings": null - }, - { - "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and length(b)=1)", - "Plan": [ - "IndexMerge 8.00 root ", - "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", - "├─Selection(Build) 0.80 cop[tikv] 1", - "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", - "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" - ], - "Warnings": null - }, - { - "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(a)=1) or (b=1 and length(b)=1)", - "Plan": [ - "IndexMerge 8.00 root ", - "├─Selection(Build) 0.80 cop[tikv] 1", - "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", - "├─Selection(Build) 0.80 cop[tikv] 1", - "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", - "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" - ], - "Warnings": null - }, - { - "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(b)=1) or (b=1 and length(a)=1)", - "Plan": [ - "IndexMerge 0.29 root ", - "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", - "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", - "└─Selection(Probe) 0.29 cop[tikv] or(and(eq(test.t.a, 1), eq(length(cast(test.t.b, var_string(20))), 1)), and(eq(test.t.b, 1), eq(length(cast(test.t.a, var_string(20))), 1)))", - " └─TableRowIDScan 1.90 cop[tikv] table:t keep order:false" - ], - "Warnings": null - } - ] - }, - { - "Name": "TestLimitIndexLookUpKeepOrder", - "Cases": [ - { - "SQL": "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b,c limit 10", - "Plan": [ - "Limit 0.00 root offset:0, count:10", - "└─Projection 0.00 root test.t.a, test.t.b, test.t.c, test.t.d", - " └─IndexLookUp 0.00 root ", - " ├─IndexRangeScan(Build) 2.50 cop[tikv] table:t, index:idx(a, b, c) range:(1 2,1 10), keep order:true, stats:pseudo", - " └─Selection(Probe) 0.00 cop[tikv] eq(test.t.d, 10)", - " └─TableRowIDScan 2.50 cop[tikv] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b desc, c desc limit 10", - "Plan": [ - "Limit 0.00 root offset:0, count:10", - "└─Projection 0.00 root test.t.a, test.t.b, test.t.c, test.t.d", - " └─IndexLookUp 0.00 root ", - " ├─IndexRangeScan(Build) 2.50 cop[tikv] table:t, index:idx(a, b, c) range:(1 2,1 10), keep order:true, desc, stats:pseudo", - " └─Selection(Probe) 0.00 cop[tikv] eq(test.t.d, 10)", - " └─TableRowIDScan 2.50 cop[tikv] table:t keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestIssue23887", - "Cases": [ - { - "SQL": "select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t", - "Plan": [ - "HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(2, test.t.b)", - "├─TableReader(Build) 10000.00 root data:TableFullScan", - "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - "└─Projection(Probe) 10000.00 root 1->Column#27", - " └─Apply 10000.00 root CARTESIAN left outer join", - " ├─TableReader(Build) 10000.00 root data:TableFullScan", - " │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", - " └─Projection(Probe) 1.00 root 1->Column#25", - " └─Limit 1.00 root offset:0, count:1", - " └─TableReader 1.00 root data:Limit", - " └─Limit 1.00 cop[tikv] offset:0, count:1", - " └─TableFullScan 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" - ], - "Res": [ - "1", - "1" - ] - } - ] - }, - { - "Name": "TestMergeContinuousSelections", - "Cases": [ - { - "SQL": "desc format = 'brief' SELECT table2 . `col_char_64` AS field1 FROM `ts` AS table2 INNER JOIN (SELECT DISTINCT SUBQUERY3_t1 . * FROM `ts` AS SUBQUERY3_t1 LEFT OUTER JOIN `ts` AS SUBQUERY3_t2 ON SUBQUERY3_t2 . `col_varchar_64_not_null` = SUBQUERY3_t1 . `col_varchar_key`) AS table3 ON (table3 . `col_varchar_key` = table2 . `col_varchar_64`) WHERE table3 . `col_char_64_not_null` >= SOME (SELECT SUBQUERY4_t1 . `col_varchar_64` AS SUBQUERY4_field1 FROM `ts` AS SUBQUERY4_t1) GROUP BY field1 ;", - "Plan": [ - "HashAgg 7992.00 root group by:test.ts.col_char_64, funcs:firstrow(test.ts.col_char_64)->test.ts.col_char_64", - "└─HashJoin 9990.00 root CARTESIAN inner join, other cond:or(ge(test.ts.col_char_64_not_null, Column#25), if(ne(Column#26, 0), NULL, 0))", - " ├─Selection(Build) 0.80 root ne(Column#27, 0)", - " │ └─HashAgg 1.00 root funcs:min(Column#36)->Column#25, funcs:sum(Column#37)->Column#26, funcs:count(Column#38)->Column#27", - " │ └─TableReader 1.00 root data:ExchangeSender", - " │ └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " │ └─HashAgg 1.00 batchCop[tiflash] funcs:min(Column#42)->Column#36, funcs:sum(Column#43)->Column#37, funcs:count(1)->Column#38", - " │ └─Projection 10000.00 batchCop[tiflash] test.ts.col_varchar_64, cast(isnull(test.ts.col_varchar_64), decimal(22,0) BINARY)->Column#43", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:SUBQUERY4_t1 keep order:false, stats:pseudo", - " └─TableReader(Probe) 12487.50 root data:ExchangeSender", - " └─ExchangeSender 12487.50 cop[tiflash] ExchangeType: PassThrough", - " └─HashJoin 12487.50 cop[tiflash] inner join, equal:[eq(test.ts.col_varchar_64, test.ts.col_varchar_key)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.ts.col_varchar_64))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:table2 keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.ts.col_varchar_key))", - " └─TableFullScan 10000.00 cop[tiflash] table:SUBQUERY3_t1 keep order:false, stats:pseudo" - ] - } - ] - }, - { - "Name": "TestPushDownGroupConcatToTiFlash", - "Cases": [ - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts", - "Plan": [ - "HashAgg 1.00 root funcs:group_concat(Column#7 separator \",\")->Column#5", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#9, Column#10, Column#11 separator \",\")->Column#7", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#11", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#6, Column#7, Column#8 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_1) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#8, Column#9, Column#10 order by Column#11 separator \",\")->Column#5, funcs:count(1)->Column#6, funcs:min(Column#12)->Column#7", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#10, test.ts.col_0, test.ts.col_1", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_0) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#14, Column#15, Column#16 order by Column#17 separator \",\")->Column#5, funcs:sum(Column#18)->Column#6, funcs:max(Column#19)->Column#7", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#16, test.ts.col_0, Column#12, Column#13", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, funcs:count(1)->Column#12, funcs:max(test.ts.col_0)->Column#13", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_2, funcs:group_concat(Column#9 separator \",\")->Column#5", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#13, funcs:group_concat(Column#10, Column#11, Column#12 separator \",\")->Column#9", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#12, test.ts.col_2", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#9, funcs:group_concat(distinct Column#6, Column#7, Column#8 separator \",\")->Column#5", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_2", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.col_2, test.ts.id, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#10, funcs:group_concat(Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0, test.ts.col_2", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#10, funcs:group_concat(distinct Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0, test.ts.col_2", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.col_2, test.ts.id, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_1, id order by col_0) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#9, funcs:group_concat(Column#6, Column#7 order by Column#8 separator \",\")->Column#5", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#7, test.ts.col_0, test.ts.col_2", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_1, id order by col_0) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#9, funcs:group_concat(distinct Column#6, Column#7 order by Column#8 separator \",\")->Column#5", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#7, test.ts.col_0, test.ts.col_2", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_1, test.ts.col_2, test.ts.id, funcs:firstrow(test.ts.col_0)->test.ts.col_0", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_0),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#20, funcs:group_concat(Column#13, Column#14, Column#15 order by Column#16 separator \",\")->Column#5, funcs:count(1)->Column#6, funcs:min(Column#17)->Column#7, funcs:count(Column#18)->Column#11, funcs:sum(Column#19)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#15, test.ts.col_0, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#19, test.ts.col_2", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_1),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#24, 0), 1, Column#24), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#44, funcs:group_concat(distinct Column#36, Column#37, Column#38 order by Column#39 separator \",\")->Column#5, funcs:sum(Column#40)->Column#6, funcs:max(Column#41)->Column#7, funcs:sum(Column#42)->Column#24, funcs:sum(Column#43)->Column#8", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#38, test.ts.col_0, Column#25, Column#26, Column#27, Column#28, test.ts.col_2", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#32, Column#33, Column#34, Column#35, funcs:count(1)->Column#25, funcs:max(Column#29)->Column#26, funcs:count(Column#30)->Column#27, funcs:sum(Column#31)->Column#28", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#31, test.ts.col_2, test.ts.col_0, test.ts.col_1, test.ts.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(distinct id),min(col_0),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#10, 0), 1, Column#10), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#11, Column#12, Column#13 order by Column#14 separator \",\")->Column#5, funcs:count(Column#15)->Column#6, funcs:min(Column#16)->Column#7, funcs:count(Column#17)->Column#10, funcs:sum(Column#18)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#13, test.ts.col_0, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#18", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(distinct id),max(col_1),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#18, 0), 1, Column#18), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#30, Column#31, Column#32 order by Column#33 separator \",\")->Column#5, funcs:sum(Column#34)->Column#6, funcs:max(Column#35)->Column#7, funcs:sum(Column#36)->Column#18, funcs:sum(Column#37)->Column#8", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#32, test.ts.col_0, Column#19, Column#20, Column#21, Column#22", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#27, Column#28, Column#29, funcs:count(Column#23)->Column#19, funcs:max(Column#24)->Column#20, funcs:count(Column#25)->Column#21, funcs:sum(Column#26)->Column#22", - " └─Projection 10000.00 batchCop[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#26, test.ts.col_0, test.ts.col_1, test.ts.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#27, 0), 1, Column#27), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_2, funcs:group_concat(Column#28 separator \",\")->Column#5, funcs:sum(Column#29)->Column#6, funcs:min(Column#30)->Column#7, funcs:sum(Column#31)->Column#27, funcs:sum(Column#32)->Column#8", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#40, funcs:group_concat(Column#33, Column#34, Column#35 separator \",\")->Column#28, funcs:count(Column#36)->Column#29, funcs:min(Column#37)->Column#30, funcs:count(Column#38)->Column#31, funcs:sum(Column#39)->Column#32", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#35, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#39, test.ts.col_2", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#24, 0), 1, Column#24), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#44, funcs:group_concat(distinct Column#37, Column#38, Column#39 separator \",\")->Column#5, funcs:sum(Column#40)->Column#6, funcs:max(Column#41)->Column#7, funcs:sum(Column#42)->Column#24, funcs:sum(Column#43)->Column#8", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#39, Column#25, Column#26, Column#27, Column#28, test.ts.col_2", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#33, Column#34, Column#35, Column#36, funcs:count(Column#29)->Column#25, funcs:max(Column#30)->Column#26, funcs:count(Column#31)->Column#27, funcs:sum(Column#32)->Column#28", - " └─Projection 10000.00 batchCop[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#32, test.ts.col_2, test.ts.col_0, test.ts.col_1, test.ts.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts", - "Plan": [ - "HashAgg 1.00 root funcs:group_concat(Column#14 separator \",\")->Column#5, funcs:count(Column#15)->Column#6, funcs:min(Column#16)->Column#7, funcs:avg(Column#17, Column#18)->Column#8", - "└─TableReader 1.00 root data:ExchangeSender", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#24, Column#25, Column#26 separator \",\")->Column#14, funcs:count(Column#27)->Column#15, funcs:min(Column#28)->Column#16, funcs:count(Column#29)->Column#17, funcs:sum(Column#30)->Column#18", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#26, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#30", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#18, 0), 1, Column#18), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#30, Column#31, Column#32 separator \",\")->Column#5, funcs:sum(Column#33)->Column#6, funcs:max(Column#34)->Column#7, funcs:sum(Column#35)->Column#18, funcs:sum(Column#36)->Column#8", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#32, Column#19, Column#20, Column#21, Column#22", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#27, Column#28, Column#29, funcs:count(Column#23)->Column#19, funcs:max(Column#24)->Column#20, funcs:count(Column#25)->Column#21, funcs:sum(Column#26)->Column#22", - " └─Projection 10000.00 batchCop[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#26, test.ts.col_0, test.ts.col_1, test.ts.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),group_concat(col_0 order by 1),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#17, 0), 1, Column#17), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#29, funcs:group_concat(Column#21, Column#22, Column#23 separator \",\")->Column#5, funcs:count(Column#24)->Column#6, funcs:group_concat(Column#25 order by Column#26 separator \",\")->Column#7, funcs:count(Column#27)->Column#17, funcs:sum(Column#28)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#23, test.ts.id, test.ts.col_0, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#28, test.ts.col_2", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0),count(distinct id),group_concat(col_1, id order by 1,2),avg(id) from ts group by col_2", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#14, 0), 1, Column#14), decimal(20,0) BINARY))->Column#8", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#25, funcs:group_concat(distinct Column#17 separator \",\")->Column#5, funcs:count(Column#18)->Column#6, funcs:group_concat(Column#19, Column#20 order by Column#21, Column#22 separator \",\")->Column#7, funcs:count(Column#23)->Column#14, funcs:sum(Column#24)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#20, test.ts.col_1, test.ts.id, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#24, test.ts.col_2", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: N/A]", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, id),count(distinct id),group_concat(col_1, id order by 1,2),min(col_0),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#15, 0), 1, Column#15), decimal(20,0) BINARY))->Column#9", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(Column#18, Column#19 separator \",\")->Column#5, funcs:count(Column#20)->Column#6, funcs:group_concat(Column#21, Column#22 order by Column#23, Column#24 separator \",\")->Column#7, funcs:min(Column#25)->Column#8, funcs:count(Column#26)->Column#15, funcs:sum(Column#27)->Column#9", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, cast(test.ts.id, var_string(20))->Column#19, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#22, test.ts.col_1, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#27", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),group_concat(col_1, id order by 1,2),max(col_1),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#13, 0), 1, Column#13), decimal(20,0) BINARY))->Column#9", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#15, Column#16, Column#17 separator \",\")->Column#5, funcs:count(Column#18)->Column#6, funcs:group_concat(Column#19, Column#20 order by Column#21, Column#22 separator \",\")->Column#7, funcs:max(Column#23)->Column#8, funcs:count(Column#24)->Column#13, funcs:sum(Column#25)->Column#9", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#17, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#20, test.ts.col_1, test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#25", - " └─ExchangeReceiver 10000.00 batchCop[tiflash] ", - " └─ExchangeSender 10000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#19, 0), 1, Column#19), decimal(20,0) BINARY))->Column#9", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#33, Column#34, Column#35 separator \",\")->Column#5, funcs:count(distinct Column#36)->Column#6, funcs:group_concat(Column#37 separator \",\")->Column#7, funcs:max(Column#38)->Column#8, funcs:sum(Column#39)->Column#19, funcs:sum(Column#40)->Column#9", - " └─Projection 1.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#35, test.ts.col_2, Column#20, Column#21, Column#22, Column#23", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#29, Column#30, Column#31, Column#32, funcs:group_concat(Column#24, Column#25 separator \",\")->Column#20, funcs:max(Column#26)->Column#21, funcs:count(Column#27)->Column#22, funcs:sum(Column#28)->Column#23", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#25, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#28, test.ts.col_0, test.ts.col_1, test.ts.id, test.ts.col_2", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts group by col_0", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#25, 0), 1, Column#25), decimal(20,0) BINARY))->Column#9", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#47, funcs:group_concat(distinct Column#39, Column#40, Column#41 separator \",\")->Column#5, funcs:count(distinct Column#42)->Column#6, funcs:group_concat(Column#43 separator \",\")->Column#7, funcs:max(Column#44)->Column#8, funcs:sum(Column#45)->Column#25, funcs:sum(Column#46)->Column#9", - " └─Projection 8000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#41, test.ts.col_2, Column#26, Column#27, Column#28, Column#29, test.ts.col_0", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_0, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#35, Column#36, Column#37, Column#38, funcs:group_concat(Column#30, Column#31 separator \",\")->Column#26, funcs:max(Column#32)->Column#27, funcs:count(Column#33)->Column#28, funcs:sum(Column#34)->Column#29", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#31, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(37,4) BINARY)->Column#34, test.ts.col_0, test.ts.col_1, test.ts.id, test.ts.col_2", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#12, Column#13 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#10, var_string(20))->Column#12, Column#11", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"GG\", 0, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'01') from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#12, Column#13 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#10, var_string(20))->Column#12, Column#11", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"01\", 0, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,1) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#12, Column#13 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#10, var_string(20))->Column#12, cast(Column#11, var_string(20))->Column#13", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:0, 1, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#9, Column#10 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#8, var_string(20))->Column#9, cast(Column#8, var_string(20))->Column#10", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:0, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,10) from ts group by '010'", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#20, funcs:group_concat(distinct Column#18, Column#19 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#16, var_string(20))->Column#18, cast(Column#17, var_string(20))->Column#19, Column#15", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#15, collate: N/A]", - " └─HashAgg 1.00 batchCop[tiflash] group by:0, 1, 10, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts group by '011'", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#16, funcs:group_concat(distinct Column#14, Column#15 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#13, var_string(20))->Column#14, cast(Column#13, var_string(20))->Column#15, Column#12", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: N/A]", - " └─HashAgg 1.00 batchCop[tiflash] group by:0, 1, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts group by 'GG'", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#20, funcs:group_concat(distinct Column#18, Column#19 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] cast(Column#16, var_string(20))->Column#18, Column#17, Column#15", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#15, collate: N/A]", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"GG\", 0, 1, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'", - "[types:1292]Truncated incorrect DOUBLE value: 'GG'" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG','GG') from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#8, Column#8 separator \",\")->Column#5", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"GG\", ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'Gg','GG') from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"GG\", \"Gg\", ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG-10','GG') from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"GG\", \"GG-10\", ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct '1200-01-01 00:00:00.023',1200) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct Column#12, Column#13 separator \",\")->Column#5", - " └─Projection 1.00 batchCop[tiflash] Column#10, cast(Column#11, var_string(20))->Column#13", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:\"1200-01-01 00:00:00.023\", 1200, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", - "[types:1292]Truncated incorrect DOUBLE value: '1200-01-01 00:00:00.023'", - "[types:1292]Truncated incorrect DOUBLE value: '1200-01-01 00:00:00.023'", - "[types:1292]Truncated incorrect DOUBLE value: '1200-01-01 00:00:00.023'" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0) from ts group by id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.id, funcs:group_concat(Column#9 separator \",\")->Column#5", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.id, funcs:group_concat(test.ts.col_0, test.ts.col_0 separator \",\")->Column#9", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0,id) from ts group by id", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.id, funcs:group_concat(Column#9 separator \",\")->Column#5", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#13, funcs:group_concat(Column#10, Column#11, Column#12 separator \",\")->Column#9", - " └─Projection 10000.00 batchCop[tiflash] test.ts.col_0, test.ts.col_0, cast(test.ts.id, var_string(20))->Column#12, test.ts.id", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts", - "Plan": [ - "TableReader 1.00 root data:ExchangeSender", - "└─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 1.00 batchCop[tiflash] Column#5", - " └─HashAgg 1.00 batchCop[tiflash] funcs:group_concat(distinct test.ts.col_0 order by Column#8 separator \",\")->Column#5", - " └─ExchangeReceiver 1.00 batchCop[tiflash] ", - " └─ExchangeSender 1.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─HashAgg 1.00 batchCop[tiflash] group by:Column#10, funcs:firstrow(Column#9)->Column#8", - " └─Projection 10000.00 batchCop[tiflash] lt(test.ts.id, 10)->Column#9, test.ts.col_0", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts group by col_1", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.ts.col_1, funcs:group_concat(distinct test.ts.col_0 order by Column#9 separator \",\")->Column#5", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_1, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#11, Column#12, funcs:firstrow(Column#10)->Column#9", - " └─Projection 10000.00 batchCop[tiflash] lt(test.ts.id, 10)->Column#10, test.ts.col_1, test.ts.col_0", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0>10 order by id<10) from ts group by col_1", - "Plan": [ - "TableReader 8000.00 root data:ExchangeSender", - "└─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#19, funcs:group_concat(distinct Column#17 order by Column#18 separator \",\")->Column#5", - " └─Projection 8000.00 batchCop[tiflash] cast(Column#12, var_string(20))->Column#17, Column#13, test.ts.col_1", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_1, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:Column#15, Column#16, funcs:firstrow(Column#14)->Column#13", - " └─Projection 10000.00 batchCop[tiflash] lt(test.ts.id, 10)->Column#14, test.ts.col_1, gt(cast(test.ts.col_0, double BINARY), 10)->Column#16", - " └─TableFullScan 10000.00 batchCop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" - ] - }, - { - "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by col_0<=>null) from ts", - "Plan": [ - "HashAgg 1.00 root funcs:group_concat(distinct Column#6 order by Column#7 separator \",\")->Column#5", - "└─Projection 10000.00 root test.ts.col_0, nulleq(test.ts.col_0, )->Column#7", - " └─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tiflash] table:ts keep order:false, stats:pseudo" - ], - "Warning": [ - "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", - "Scalar function 'nulleq'(signature: NullEQString, return type: bigint(1)) is not supported to push down to tiflash now.", - "Aggregation can not be pushed to tiflash because arguments of AggFunc `group_concat` contains unsupported exprs in order-by clause", - "Scalar function 'nulleq'(signature: NullEQString, return type: bigint(1)) is not supported to push down to tiflash now.", - "Aggregation can not be pushed to tiflash because arguments of AggFunc `group_concat` contains unsupported exprs in order-by clause", - "Scalar function 'nulleq'(signature: NullEQString, return type: bigint(1)) is not supported to push down to tiflash now.", - "Aggregation can not be pushed to tiflash because arguments of AggFunc `group_concat` contains unsupported exprs in order-by clause" - ] - } - ] - }, - { - "Name": "TestRejectSortForMPP", - "Cases": [ - { - "SQL": "desc format = 'brief' select count(*) from (select * from t order by id)a group by name,id order by id", - "Plan": [ - "Projection 8000.00 root Column#5", - "└─Sort 8000.00 root test.t.id", - " └─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5, test.t.id", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, test.t.name, funcs:sum(Column#7)->Column#5, funcs:firstrow(test.t.id)->test.t.id", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: N/A], [name: test.t.id, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, test.t.name, funcs:count(1)->Column#7", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*) from (select * from t order by id)a group by name order by 1", - "Plan": [ - "Sort 8000.00 root Column#5", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.name, funcs:sum(Column#8)->Column#5", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.name, funcs:count(1)->Column#8", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select count(*) from (select id,name from t group by id,name order by id,name)a group by name order by 1", - "Plan": [ - "Sort 8000.00 root Column#5", - "└─TableReader 8000.00 root data:ExchangeSender", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 8000.00 batchCop[tiflash] Column#5", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.name, funcs:count(1)->Column#5", - " └─Projection 8000.00 batchCop[tiflash] test.t.id, test.t.name", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, test.t.name, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.name)->test.t.name", - " └─ExchangeReceiver 8000.00 batchCop[tiflash] ", - " └─ExchangeSender 8000.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: N/A]", - " └─HashAgg 8000.00 batchCop[tiflash] group by:test.t.id, test.t.name, ", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select id from t group by id order by id)a join t on a.id=t.id order by 1", - "Plan": [ - "Sort 9990.00 root test.t.id", - "└─TableReader 9990.00 root data:ExchangeSender", - " └─ExchangeSender 9990.00 batchCop[tiflash] ExchangeType: PassThrough", - " └─Projection 9990.00 batchCop[tiflash] test.t.id, test.t.id, test.t.value, test.t.name", - " └─HashJoin 9990.00 batchCop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: Broadcast", - " │ └─Projection 7992.00 batchCop[tiflash] test.t.id", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 7992.00 batchCop[tiflash] ", - " │ └─ExchangeSender 7992.00 batchCop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: N/A]", - " │ └─HashAgg 7992.00 batchCop[tiflash] group by:test.t.id, ", - " │ └─Selection 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 batchCop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select * from t order by id)a join t on a.id=t.id order by 1", - "Plan": [ - "Sort 12487.50 root test.t.id", - "└─TableReader 12487.50 root data:ExchangeSender", - " └─ExchangeSender 12487.50 cop[tiflash] ExchangeType: PassThrough", - " └─Projection 12487.50 cop[tiflash] test.t.id, test.t.value, test.t.name, test.t.id, test.t.value, test.t.name", - " └─HashJoin 12487.50 cop[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", - " ├─ExchangeReceiver(Build) 9990.00 cop[tiflash] ", - " │ └─ExchangeSender 9990.00 cop[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 cop[tiflash] not(isnull(test.t.id))", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from ((select id from t order by 1) union all (select id+1 from t order by 1))c", - "Plan": [ - "TableReader 20000.00 root data:ExchangeSender", - "└─ExchangeSender 20000.00 cop[tiflash] ExchangeType: PassThrough", - " └─Union 20000.00 cop[tiflash] ", - " ├─Projection 10000.00 cop[tiflash] cast(test.t.id, bigint(20) BINARY)->Column#10", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection 10000.00 cop[tiflash] plus(test.t.id, 1)->Column#10", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from ((select count(*) from (select id,name from t order by id)a group by name,id order by id) union all (select id+1 from t order by 1))c", - "Plan": [ - "TableReader 18000.00 root data:ExchangeSender", - "└─ExchangeSender 18000.00 cop[tiflash] ExchangeType: PassThrough", - " └─Union 18000.00 cop[tiflash] ", - " ├─Projection 8000.00 cop[tiflash] cast(Column#12, bigint(21) BINARY)->Column#12", - " │ └─Projection 8000.00 cop[tiflash] Column#5", - " │ └─Projection 8000.00 cop[tiflash] Column#5, test.t.id", - " │ └─HashAgg 8000.00 cop[tiflash] group by:test.t.id, test.t.name, funcs:sum(Column#19)->Column#5, funcs:firstrow(test.t.id)->test.t.id", - " │ └─ExchangeReceiver 8000.00 cop[tiflash] ", - " │ └─ExchangeSender 8000.00 cop[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: N/A], [name: test.t.id, collate: N/A]", - " │ └─HashAgg 8000.00 cop[tiflash] group by:test.t.id, test.t.name, funcs:count(1)->Column#19", - " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", - " └─Projection 10000.00 cop[tiflash] cast(Column#11, bigint(21) BINARY)->Column#12", - " └─Projection 10000.00 cop[tiflash] plus(test.t.id, 1)->Column#11", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - }, - { - "SQL": "desc format = 'brief' select * from (select * from t order by id)a order by name", - "Plan": [ - "Sort 10000.00 root test.t.name", - "└─TableReader 10000.00 root data:ExchangeSender", - " └─ExchangeSender 10000.00 cop[tiflash] ExchangeType: PassThrough", - " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" - ] - } - ] - } -] diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index b67cc1ffbf4e6..a93847591c21a 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -381,5 +381,506 @@ "select a from ta group by @n:=@n+1", "select a from ta group by @n:=@n+a" ] + }, + { + "name": "TestIssue30200", + "cases": [ + // to_base64 and from_base64 has not been pushed to TiKV or TiFlash. + // We expect a Selection will be added above IndexMerge. + "select /*+ use_index_merge(t1) */ 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';", + + // `left` has not been pushed to TiKV, but it has been pushed to TiFlash. + // We expect a Selection will be added above IndexMerge. + "select /*+ use_index_merge(t1) */ 1 from t1 where c1 = 'ab' or c2 = '10' and char_length(left(c1, 10)) = 10;", + + // c3 is part of idx_1, so it will be put in partial_path's IndexFilters instead of TableFilters. + // But it still cannot be pushed to TiKV. This case cover code in DataSource.buildIndexMergeOrPath. + "select /*+ use_index_merge(tt1) */ 1 from tt1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c3)) = '10';", + + // to_base64(left(pk, 5)) is in partial_path's TableFilters. But it cannot be pushed to TiKV. + // So it should be executed in TiDB. This case cover code in DataSource.buildIndexMergeOrPath. + "select /*+ use_index_merge( tt2 ) */ 1 from tt2 where tt2.c1 in (-3896405) or tt2.pk in (1, 53330) and to_base64(left(pk, 5));", + + // This case covert expression index. + "select /*+ use_index_merge(tt3) */ 1 from tt3 where c1 < -10 or c2 < 10 and reverse(c3) = '2';", + + // If no hint, we cannot use index merge if filter cannot be pushed to any storage. + "select 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';" + ] + }, + { + "name": "TestIndexMergeWithCorrelatedColumns", + "cases": [ + "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 = 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and substring(c3, 10)) order by c1;", + "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 = 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and reverse(c3)) order by c1;", + "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 >= 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and substring(c3, 10)) order by c1;", + // Test correlated column in IndexPath.TableFilters. + "select c_int from tt1 where c_decimal < all (select /*+ use_index_merge(tt2) */ c_decimal from tt2 where tt1.c_int = tt2.c_int and tt1.c_datetime > tt2.c_datetime and tt2.c_decimal = 9.060 or tt2.c_str <= 'interesting shtern' and tt1.c_int = tt2.c_int) order by 1;", + // Test correlated column in TablePath.TableFilters. + "select c_int from tt1 where c_decimal > all (select /*+ use_index_merge(tt2) */ c_decimal from tt2 where tt2.c_int = 7 and tt2.c_int < tt1.c_decimal or tt2.c_str >= 'zzzzzzzzzzzzzzzzzzz' and tt1.c_int = tt2.c_int) order by 1;" + ] + }, + { + "name": "TestIssue31240", + "cases": [ + "explain format = 'brief' select count(*) from t31240;", + "set @@tidb_isolation_read_engines=\"tiflash,tidb\";", + "explain format = 'brief' select count(*) from t31240;" + ] + }, + { + "name": "TestSelPushDownTiFlash", + "cases": [ + "explain format = 'brief' select * from t where t.a > 1 and t.b = \"flash\" or t.a + 3 * t.a = 5", + "explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1", + "explain format = 'brief' select * from t where b > 'a' order by convert(b, unsigned) limit 2", + "explain format = 'brief' select * from t where b > 'a' order by b limit 2" + ] + }, + { + "name": "TestVerboseExplain", + "cases": [ + "explain format = 'verbose' select count(*) from t3", + "explain format = 'verbose' select count(*) from t2", + "explain format = 'verbose' select * from t3 order by a", + "explain format = 'verbose' select * from t3 order by b", + "explain format = 'verbose' select * from t3 order by a limit 1", + "explain format = 'verbose' select * from t3 order by b limit 1", + "explain format = 'verbose' select count(*) from t2 group by a", + "explain format = 'verbose' select count(*) from t3 where b = 0", + "explain format = 'verbose' select /*+ use_index(t3, c) */ count(a) from t3 where b = 0", + "explain format = 'verbose' select count(*) from t2 where a = 0", + "explain format = 'verbose' select count(*) from t3 t join t3 on t.a = t3.b", + "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a", + "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a join t3 on t1.b = t3.b", + "explain format = 'verbose' select (2) in (select count(*) from t1) from (select t.b < (select t.b from t2 limit 1 ) from t3 t) t", + "explain format = 'verbose' select /*+ merge_join(t1) */ count(*) from t1 join t2 on t1.a = t2.a" + ] + + }, + { + "name": "TestRegardNULLAsPoint", + "cases": [ + "select * from tuk where a<=>null and b=1", + "select * from tik where a<=>null and b=1", + "select * from tuk where a<=>null and b>0 and b<2", + "select * from tik where a<=>null and b>0 and b<2", + "select * from tuk where a<=>null and b>=1 and b<2", + "select * from tik where a<=>null and b>=1 and b<2", + "select * from tuk where a<=>null and b=1 and c=1", + "select * from tik where a<=>null and b=1 and c=1", + "select * from tuk where a=1 and b<=>null and c=1", + "select * from tik where a=1 and b<=>null and c=1", + "select * from tuk where a<=>null and b<=>null and c=1", + "select * from tik where a<=>null and b<=>null and c=1", + "select * from tuk where a<=>null and b<=>null and c<=>null", + "select * from tik where a<=>null and b<=>null and c<=>null" + ] + }, + { + "name": "TestPushDownToTiFlashWithKeepOrder", + "cases": [ + "explain format = 'brief' select max(a) from t", + "explain format = 'brief' select min(a) from t" + ] + }, + { + "name": "TestMPPJoin", + "cases": [ + "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", + "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", + "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k > d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k > d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k > d1_t.d1_k", + "explain format = 'brief' select count(*) from fact_t where d1_k not in (select d1_k from d1_t)" + ] + }, + { + "name": "TestMPPLeftSemiJoin", + "cases": [ + "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select a from test.t); -- left semi", + "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select a from test.t where b1 or t1.a not in (select a from test.t); -- left anti", + "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a not in (select a from test.t where b1 or t1.b in (select a from test.t); -- cartesian left semi", + "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select b from test.t where b1 or t1.b not in (select a from test.t); -- cartesian left anti", + "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.b not in (select a from test.t where b d1_t.value", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", + "explain format = 'brief' select count(*) from (select case when t1.col1 is null then t2.col1 + 5 else 10 end as col1, t2.d1_k as d1_k from fact_t t1 right join fact_t t2 on t1.d1_k = t2.d1_k) fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 5", + "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", + "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", + "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)" + ] + }, + { + "name": "TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError", + "cases": [ + "explain format = 'brief' select v from t3 as a left join (select t1.v1, t1.v2, t1.v1 + t1.v2 as v from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2) b on a.v1 = b.v1 and a.v2 = b.v2", + "explain format = 'brief' select count(*), t2.v1, t2.v2 from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2 group by t2.v1, t2.v2", + "explain format = 'brief' select count(*), t2.v1, t2.v2 from t3 left join t2 on t3.v1 = t2.v1 and t3.v2 = t2.v2 group by t2.v1, t2.v2" + ] + }, + { + "name": "TestJoinNotSupportedByTiFlash", + "cases": [ + "explain format = 'brief' select * from table_1 a, table_1 b where a.bit_col = b.bit_col", + "explain format = 'brief' select * from table_1 a left join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > 100", + "explain format = 'brief' select * from table_1 a right join table_1 b on a.id = b.id and dayofmonth(b.datetime_col) > 100", + "explain format = 'brief' select * from table_1 a join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > dayofmonth(b.datetime_col)" + ] + }, + { + "name": "TestMPPWithHashExchangeUnderNewCollation", + "cases": [ + "explain format = 'brief' select * from table_1 a, table_1 b where a.value = b.value", + "explain format = 'brief' select * from table_1 a, table_2 b where a.value = b.value", + "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and b.value = c.value", + "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and a.value = c.value", + "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_1 group by value", + "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_2 group by value" + ] + }, + { + "name": "TestMPPWithBroadcastExchangeUnderNewCollation", + "cases": [ + "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.id = b.id", + "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.value = b.value" + ] + }, + { + "name": "TestMPPAvgRewrite", + "cases": [ + "explain format = 'brief' select /*+ avg_to_cop() */ id, avg(value+1),avg(value) from table_1 group by id" + ] + }, + { + "name": "TestReadFromStorageHint", + "cases": [ + "desc format = 'brief' select avg(a) from t", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a) from t", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a+1) from t", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(isnull(a)) from t", + "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIKV[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIFLASH[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "desc format = 'brief' select * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "desc format = 'brief' select /*+ read_from_storage(tiflash[tt]) */ * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "desc format = 'brief' select * from ttt order by ttt.a desc", + "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a desc", + "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a", + "desc format = 'brief' select /*+ read_from_storage(tikv[t, ttt]) */ * from ttt", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt" + ] + }, + { + "name": "TestReadFromStorageHintAndIsolationRead", + "cases": [ + "desc format = 'brief' select /*+ read_from_storage(tikv[t], tiflash[t]) */ avg(a) from t", + "desc format = 'brief' select /*+ read_from_storage(tikv[t]) */ avg(a) from t", + "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t" + ] + }, + { + "name": "TestIsolationReadDoNotFilterSystemDB", + "cases": [ + "desc format = 'brief' select * from metrics_schema.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'", + "desc format = 'brief' select * from information_schema.tables", + "desc format = 'brief' select * from mysql.stats_meta" + ] + }, + { + "name": "TestIsolationReadTiFlashNotChoosePointGet", + "cases": [ + "explain format = 'brief' select * from t where t.a = 1", + "explain format = 'brief' select * from t where t.a in (1, 2)" + ] + }, + { + "name": "TestIsolationReadTiFlashUseIndexHint", + "cases": [ + "explain format = 'brief' select * from t", + "explain format = 'brief' select * from t use index();", + "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", + "explain format = 'brief' select /*+ use_index(t)*/ * from t" + ] + }, + { + "name": "TestIssue20710", + "cases": [ + "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.b", + "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.a", + "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.a = s.b", + "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.b", + "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.a", + "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.a = s.b" + ] + }, + { + "name": "TestPushDownProjectionForTiFlash", + "cases": [ + "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select * from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "desc format = 'brief' select A.id from t as A where exists (select 1 from t where t.id=A.id)", + "desc format = 'brief' select A.id from t as A where not exists (select 1 from t where t.id=A.id)", + "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;" + ] + }, + { + "name": "TestPushDownProjectionForMPP", + "cases": [ + "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select B.b+A.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", + "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "desc format = 'brief' select id from t as A where exists (select 1 from t where t.id=A.id)", + "desc format = 'brief' select id from t as A where not exists (select 1 from t where t.id=A.id)", + "desc format = 'brief' select b*2, id from (select avg(value+2) as b, id from t group by id) C order by id", + "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;" + ] + }, + { + "name": "TestMppUnionAll", + "cases": [ + "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1) tt", + "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1 union all select a, b from t where false) tt", + "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1) tt", + "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1 where false) tt", + "explain format = 'brief' select count(*) from (select a , b from t where false union all select a , c from t1 where false) tt" + ] + }, + { + "name": "TestMppJoinDecimal", + "cases": [ + "desc format = 'brief' select t1.c1, t1.c2, t2.c1, t2.c2, t2.c3 from t t1 join t t2 on t1.c1 + 1 = t2.c2 - 10 and t1.c1 * 3 = t2.c3 / 2", + "desc format = 'brief' select * from (select c1, c2, c5, count(*) c from t group by c1, c2, c5) t1 join (select c1, c2, c3, count(*) c from t group by c1, c2, c3) t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c5 = t2.c1", + "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c2 and t1.c3 = t2.c3 and t1.c4 = t2.c4 and t1.c5 = t2.c5", + "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5", + "desc format = 'brief' select * from t t1 join t t2 on t1.c1 + t1.c2 = t2.c2 / t2.c3", + "desc format = 'brief' select * from t t1 where exists (select * from t t2 where t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5)", + "desc format = 'brief' select * from t t1 left join t t2 on t1.c1 = t2.c2 join t t3 on t2.c5 = t3.c3 right join t t4 on t3.c3 = t4.c4 ", + "desc format = 'brief' SELECT STRAIGHT_JOIN t1 . col_varchar_64 , t1 . col_char_64_not_null FROM tt AS t1 INNER JOIN( tt AS t2 JOIN tt AS t3 ON(t3 . col_decimal_30_10_key = t2 . col_tinyint)) ON(t3 . col_varchar_64 = t2 . col_varchar_key) WHERE t3 . col_varchar_64 = t1 . col_char_64_not_null GROUP BY 1 , 2" + ] + }, + { + "name": "TestPushDownAggForMPP", + "cases": [ + "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id+1 from t)A", + "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "desc format = 'brief' select count(*) from t", + "desc format = 'brief' select count(*), id from t group by id", + "desc format = 'brief' select count(*), id + 1 from t group by id + 1", + "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", + "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", + "desc format = 'brief' select avg(value) as b,id from t group by id", + "desc format = 'brief' select /*+hash_agg()*/ sum(b) from (select avg(value) as b, id from t group by id)A", + "desc format = 'brief' select id from t group by id having avg(value)>0", + "desc format = 'brief' select avg(value),id from t group by id having avg(value)>0", + "desc format = 'brief' select avg(value) +1,id from t group by id", + "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", + "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", + "desc format = 'brief' select count(distinct value),id from t group by id", + "desc format = 'brief' select count(distinct value),sum(distinct value),id from t group by id", + "desc format = 'brief' select * from t join ( select count(distinct value), id from t group by id) as A on A.id = t.id", + "desc format = 'brief' select * from t join ( select count(1/value), id from t group by id) as A on A.id = t.id", + "desc format = 'brief' select /*+hash_agg()*/ sum(id) from (select value, id from t where id > value group by id, value)A group by value /*the exchange should have only one partition column: test.t.value*/", + "desc format = 'brief' select /*+hash_agg()*/ sum(B.value) from t as B where B.id+1 > (select count(*) from t where t.id= B.id and t.value=B.value) group by B.id /*the exchange should have only one partition column: test.t.id*/", + "desc format = 'brief' select count(distinct value) from t", + "desc format = 'brief' select count(distinct x ) from (select count(distinct value) x from t) t", + "desc format = 'brief' select count(distinct value), count(value), avg(value) from t" + ] + }, + { + "name": "TestMppAggTopNWithJoin", + "cases": [ + "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", + "desc format = 'brief' select * from t join ( select count(*)+id as v from t group by id) as A on A.v = t.id", + "desc format = 'brief' select * from t join ( select count(*) as v, id from t group by value,id having value+v <10) as A on A.id = t.id", + "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", + "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", + "desc format = 'brief' select * from (select id from t group by id) C join (select sum(value),id from t group by id)B on C.id=B.id", + "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", + "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value limit 1", + "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value % 100 limit 1", + "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id order by t.value limit 20) v group by v.v1", + "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", + "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", + "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id limit 20) v group by v.v1" + ] + }, + { + "name": "TestIndexMergeSerial", + "cases": [ + "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and b+2>1)", + "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and length(b)=1)", + "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(a)=1) or (b=1 and length(b)=1)", + "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(b)=1) or (b=1 and length(a)=1)" + ] + }, + { + "name": "TestLimitIndexLookUpKeepOrder", + "cases": [ + "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b,c limit 10", + "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b desc, c desc limit 10" + ] + }, + { + "name": "TestIssue23887", + "cases": [ + "select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t" + ] + }, + { + "name": "TestMergeContinuousSelections", + "cases": [ + "desc format = 'brief' SELECT table2 . `col_char_64` AS field1 FROM `ts` AS table2 INNER JOIN (SELECT DISTINCT SUBQUERY3_t1 . * FROM `ts` AS SUBQUERY3_t1 LEFT OUTER JOIN `ts` AS SUBQUERY3_t2 ON SUBQUERY3_t2 . `col_varchar_64_not_null` = SUBQUERY3_t1 . `col_varchar_key`) AS table3 ON (table3 . `col_varchar_key` = table2 . `col_varchar_64`) WHERE table3 . `col_char_64_not_null` >= SOME (SELECT SUBQUERY4_t1 . `col_varchar_64` AS SUBQUERY4_field1 FROM `ts` AS SUBQUERY4_t1) GROUP BY field1 ;" + ] + }, + { + "name": "TestPushDownGroupConcatToTiFlash", + "cases": [ + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_1) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_0) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_1, id order by col_0) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_1, id order by col_0) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_0),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_1),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(distinct id),min(col_0),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(distinct id),max(col_1),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),group_concat(col_0 order by 1),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0),count(distinct id),group_concat(col_1, id order by 1,2),avg(id) from ts group by col_2", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, id),count(distinct id),group_concat(col_1, id order by 1,2),min(col_0),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),group_concat(col_1, id order by 1,2),max(col_1),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts group by col_0", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'01') from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,1) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,10) from ts group by '010'", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts group by '011'", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts group by 'GG'", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG','GG') from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'Gg','GG') from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG-10','GG') from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct '1200-01-01 00:00:00.023',1200) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0) from ts group by id", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0,id) from ts group by id", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts group by col_1", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0>10 order by id<10) from ts group by col_1", + "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by col_0<=>null) from ts" + ] + }, + { + "name": "TestRejectSortForMPP", + "cases": [ + "desc format = 'brief' select count(*) from (select * from t order by id)a group by name,id order by id", + "desc format = 'brief' select count(*) from (select * from t order by id)a group by name order by 1", + "desc format = 'brief' select count(*) from (select id,name from t group by id,name order by id,name)a group by name order by 1", + "desc format = 'brief' select * from (select id from t group by id order by id)a join t on a.id=t.id order by 1", + "desc format = 'brief' select * from (select * from t order by id)a join t on a.id=t.id order by 1", + "desc format = 'brief' select * from ((select id from t order by 1) union all (select id+1 from t order by 1))c", + "desc format = 'brief' select * from ((select count(*) from (select id,name from t order by id)a group by name,id order by id) union all (select id+1 from t order by 1))c", + "desc format = 'brief' select * from (select * from t order by id)a order by name" + ] + }, + { + "name": "TestIssue32632", + "cases": [ + "explain format = 'brief' select sum(ps_supplycost) from partsupp, supplier where ps_suppkey = s_suppkey;" + ] + }, + { + "name": "TestTiFlashPartitionTableScan", + "cases": [ + "explain format = 'brief' select * from rp_t where a = 1 or a = 20", + "explain format = 'brief' select * from hp_t where a = 1 or a = 20", + "explain format = 'brief' select count(*) from rp_t where a = 1 or a = 20", + "explain format = 'brief' select count(*) from hp_t where a = 1 or a = 20" + ] } ] diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 6c946cdac4d2d..db5f789ede11c 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -355,8 +355,8 @@ { "SQL": "explain format = 'brief' select /*+ USE_INDEX_MERGE(t, a, b, c) */ * from t where 1 or t.a = 1 or t.b = 2", "Plan": [ - "TableReader 8000.40 root data:Selection", - "└─Selection 8000.40 cop[tikv] or(1, or(eq(test.t.a, 1), eq(test.t.b, 2)))", + "TableReader 10000.00 root data:Selection", + "└─Selection 10000.00 cop[tikv] or(1, or(eq(test.t.a, 1), eq(test.t.b, 2)))", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] } @@ -1332,7 +1332,7 @@ "└─IndexRangeScan 20.00 cop[tikv] table:tt, index:a(a) range:[10,10], [20,20], keep order:false, stats:pseudo" ], "Warnings": [ - "Warning 1105 IndexMerge is inapplicable or disabled" + "Warning 1105 IndexMerge is inapplicable" ] }, { @@ -1342,7 +1342,7 @@ "└─IndexRangeScan 6666.67 cop[tikv] table:tt, index:a(a) range:[-inf,10), [15,15], (20,+inf], keep order:false, stats:pseudo" ], "Warnings": [ - "Warning 1105 IndexMerge is inapplicable or disabled" + "Warning 1105 IndexMerge is inapplicable" ] } ] @@ -1714,7 +1714,7 @@ "SQL": "select f, g from t1 where f = 2 and g > 3", "Plan": [ "IndexReader_6 33.33 160.78 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 33.33 1870.00 cop[tikv] table:t1, index:f_g(f, g) range:(2 3,2 +inf], keep order:false, stats:pseudo" + "└─IndexRangeScan_5 33.33 1850.00 cop[tikv] table:t1, index:f_g(f, g) range:(2 3,2 +inf], keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 unique index f_g of t1 is selected since the path only fetches limited number of rows with single scan" @@ -1818,8 +1818,8 @@ "Plan": [ "IndexLookUp_14 3333.33 139413.67 root ", "├─Selection_13(Build) 3333.33 0.00 cop[tikv] gt(test.t.a, 1)", - "│ └─IndexFullScan_11 10000.00 555020.00 cop[tikv] table:t, index:f(f) keep order:true, stats:pseudo", - "└─TableRowIDScan_12(Probe) 3333.33 555020.00 cop[tikv] table:t keep order:false, stats:pseudo" + "│ └─IndexFullScan_11 10000.00 555000.00 cop[tikv] table:t, index:f(f) keep order:true, stats:pseudo", + "└─TableRowIDScan_12(Probe) 3333.33 555000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [t,f,f_g] remain after pruning paths for t given Prop{SortItems: [{test.t.f asc}], TaskTp: rootTask}" @@ -1829,8 +1829,8 @@ "SQL": "select * from t where f > 1", "Plan": [ "TableReader_7 3333.33 88640.22 root data:Selection_6", - "└─Selection_6 3333.33 1140020.00 cop[tikv] gt(test.t.f, 1)", - " └─TableFullScan_5 10000.00 1110020.00 cop[tikv] table:t keep order:false, stats:pseudo" + "└─Selection_6 3333.33 1140000.00 cop[tikv] gt(test.t.f, 1)", + " └─TableFullScan_5 10000.00 1110000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [t,f,f_g] remain after pruning paths for t given Prop{SortItems: [], TaskTp: rootTask}" @@ -1840,7 +1840,7 @@ "SQL": "select f from t where f > 1", "Plan": [ "IndexReader_6 3333.33 11140.22 root index:IndexRangeScan_5", - "└─IndexRangeScan_5 3333.33 140020.00 cop[tikv] table:t, index:f(f) range:(1,+inf], keep order:false, stats:pseudo" + "└─IndexRangeScan_5 3333.33 140000.00 cop[tikv] table:t, index:f(f) range:(1,+inf], keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [f,f_g] remain after pruning paths for t given Prop{SortItems: [], TaskTp: rootTask}" @@ -1850,9 +1850,9 @@ "SQL": "select * from t where f > 3 and g = 5", "Plan": [ "IndexLookUp_15 3.33 215.74 root ", - "├─IndexRangeScan_12(Build) 10.00 590.00 cop[tikv] table:t, index:g(g) range:[5,5], keep order:false, stats:pseudo", + "├─IndexRangeScan_12(Build) 10.00 570.00 cop[tikv] table:t, index:g(g) range:[5,5], keep order:false, stats:pseudo", "└─Selection_14(Probe) 3.33 0.00 cop[tikv] gt(test.t.f, 3)", - " └─TableRowIDScan_13 10.00 590.00 cop[tikv] table:t keep order:false, stats:pseudo" + " └─TableRowIDScan_13 10.00 570.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [t,f_g,g] remain after pruning paths for t given Prop{SortItems: [], TaskTp: rootTask}" @@ -1863,8 +1863,8 @@ "Plan": [ "Sort_5 10.00 362.68 root test.t.f", "└─IndexLookUp_13 10.00 239.01 root ", - " ├─IndexRangeScan_11(Build) 10.00 590.00 cop[tikv] table:t, index:g(g) range:[5,5], keep order:false, stats:pseudo", - " └─TableRowIDScan_12(Probe) 10.00 590.00 cop[tikv] table:t keep order:false, stats:pseudo" + " ├─IndexRangeScan_11(Build) 10.00 570.00 cop[tikv] table:t, index:g(g) range:[5,5], keep order:false, stats:pseudo", + " └─TableRowIDScan_12(Probe) 10.00 570.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [t,g] remain after pruning paths for t given Prop{SortItems: [], TaskTp: rootTask}" @@ -1875,8 +1875,8 @@ "Plan": [ "IndexLookUp_15 10.00 57230.78 root ", "├─Selection_14(Build) 10.00 0.00 cop[tikv] eq(test.t.d, 3)", - "│ └─IndexFullScan_12 10000.00 825020.00 cop[tikv] table:t, index:c_d_e(c, d, e) keep order:true, stats:pseudo", - "└─TableRowIDScan_13(Probe) 10.00 825020.00 cop[tikv] table:t keep order:false, stats:pseudo" + "│ └─IndexFullScan_12 10000.00 825000.00 cop[tikv] table:t, index:c_d_e(c, d, e) keep order:true, stats:pseudo", + "└─TableRowIDScan_13(Probe) 10.00 825000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warnings": [ "Note 1105 [t,c_d_e] remain after pruning paths for t given Prop{SortItems: [{test.t.c asc} {test.t.e asc}], TaskTp: rootTask}" @@ -1896,8 +1896,8 @@ "SQL": "explain format = 'verbose' select * from t where b > 5", "Plan": [ "TableReader_7 3.00 19.21 root data:Selection_6", - "└─Selection_6 3.00 215.00 cop[tikv] gt(test.t.b, 5)", - " └─TableFullScan_5 5.00 200.00 cop[tikv] table:t keep order:false" + "└─Selection_6 3.00 195.00 cop[tikv] gt(test.t.b, 5)", + " └─TableFullScan_5 5.00 180.00 cop[tikv] table:t keep order:false" ], "Warnings": null }, @@ -1906,9 +1906,9 @@ "Plan": [ "Limit_11 0.00 14.33 root offset:0, count:1", "└─TableReader_24 0.00 14.33 root data:Limit_23", - " └─Limit_23 0.00 215.00 cop[tikv] offset:0, count:1", - " └─Selection_22 0.00 215.00 cop[tikv] eq(test.t.b, 6)", - " └─TableFullScan_21 5.00 200.00 cop[tikv] table:t keep order:true" + " └─Limit_23 0.00 195.00 cop[tikv] offset:0, count:1", + " └─Selection_22 0.00 195.00 cop[tikv] eq(test.t.b, 6)", + " └─TableFullScan_21 5.00 180.00 cop[tikv] table:t keep order:true" ], "Warnings": null }, @@ -1917,9 +1917,9 @@ "Plan": [ "Limit_8 0.00 14.33 root offset:0, count:1", "└─TableReader_13 0.00 14.33 root data:Limit_12", - " └─Limit_12 0.00 215.00 cop[tikv] offset:0, count:1", - " └─Selection_11 0.00 215.00 cop[tikv] eq(test.t.b, 6)", - " └─TableFullScan_10 5.00 200.00 cop[tikv] table:t keep order:false" + " └─Limit_12 0.00 195.00 cop[tikv] offset:0, count:1", + " └─Selection_11 0.00 195.00 cop[tikv] eq(test.t.b, 6)", + " └─TableFullScan_10 5.00 180.00 cop[tikv] table:t keep order:false" ], "Warnings": null }, @@ -1932,8 +1932,8 @@ "SQL": "explain format = 'verbose' select * from t where b > 5", "Plan": [ "IndexLookUp_7 3.00 64.81 root ", - "├─IndexRangeScan_5(Build) 3.00 191.00 cop[tikv] table:t, index:idx_b(b) range:(5,+inf], keep order:false", - "└─TableRowIDScan_6(Probe) 3.00 191.00 cop[tikv] table:t keep order:false" + "├─IndexRangeScan_5(Build) 3.00 171.00 cop[tikv] table:t, index:idx_b(b) range:(5,+inf], keep order:false", + "└─TableRowIDScan_6(Probe) 3.00 171.00 cop[tikv] table:t keep order:false" ], "Warnings": [ "Note 1105 [idx_b] remain after pruning paths for t given Prop{SortItems: [], TaskTp: rootTask}" @@ -1945,8 +1945,8 @@ "TopN_9 0.00 19.34 root test.t.a, offset:0, count:1", "└─IndexLookUp_16 0.00 19.33 root ", " ├─TopN_15(Build) 0.00 0.00 cop[tikv] test.t.a, offset:0, count:1", - " │ └─IndexRangeScan_13 0.00 20.00 cop[tikv] table:t, index:idx_b(b) range:[6,6], keep order:false", - " └─TableRowIDScan_14(Probe) 0.00 20.00 cop[tikv] table:t keep order:false" + " │ └─IndexRangeScan_13 0.00 0.00 cop[tikv] table:t, index:idx_b(b) range:[6,6], keep order:false", + " └─TableRowIDScan_14(Probe) 0.00 0.00 cop[tikv] table:t keep order:false" ], "Warnings": [ "Note 1105 [idx_b] remain after pruning paths for t given Prop{SortItems: [], TaskTp: copDoubleReadTask}" @@ -1956,9 +1956,9 @@ "SQL": "explain format = 'verbose' select * from t where b = 6 limit 1", "Plan": [ "IndexLookUp_13 0.00 19.33 root limit embedded(offset:0, count:1)", - "├─Limit_12(Build) 0.00 20.00 cop[tikv] offset:0, count:1", - "│ └─IndexRangeScan_10 0.00 20.00 cop[tikv] table:t, index:idx_b(b) range:[6,6], keep order:false", - "└─TableRowIDScan_11(Probe) 0.00 20.00 cop[tikv] table:t keep order:false" + "├─Limit_12(Build) 0.00 0.00 cop[tikv] offset:0, count:1", + "│ └─IndexRangeScan_10 0.00 0.00 cop[tikv] table:t, index:idx_b(b) range:[6,6], keep order:false", + "└─TableRowIDScan_11(Probe) 0.00 0.00 cop[tikv] table:t keep order:false" ], "Warnings": [ "Note 1105 [idx_b] remain after pruning paths for t given Prop{SortItems: [], TaskTp: copDoubleReadTask}" @@ -2055,5 +2055,4574 @@ ] } ] + }, + { + "Name": "TestIssue30200", + "Cases": [ + { + "SQL": "select /*+ use_index_merge(t1) */ 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';", + "Plan": [ + "Projection 15.99 root 1->Column#5", + "└─Selection 15.99 root or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))", + " └─IndexMerge 19.99 root ", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c1(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c2(c2) range:[\"10\",\"10\"], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 19.99 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + }, + { + "SQL": "select /*+ use_index_merge(t1) */ 1 from t1 where c1 = 'ab' or c2 = '10' and char_length(left(c1, 10)) = 10;", + "Plan": [ + "Projection 17.99 root 1->Column#5", + "└─Selection 0.04 root or(eq(test.t1.c1, \"ab\"), and(eq(test.t1.c2, \"10\"), eq(char_length(left(test.t1.c1, 10)), 10)))", + " └─IndexMerge 19.99 root ", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c1(c1) range:[\"ab\",\"ab\"], keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c2(c2) range:[\"10\",\"10\"], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 19.99 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + }, + { + "SQL": "select /*+ use_index_merge(tt1) */ 1 from tt1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c3)) = '10';", + "Plan": [ + "Projection 15.99 root 1->Column#6", + "└─Selection 15.99 root or(eq(test.tt1.c1, \"de\"), and(eq(test.tt1.c2, \"10\"), eq(from_base64(to_base64(test.tt1.c3)), \"10\")))", + " └─IndexMerge 19.99 root ", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt1, index:idx_0(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt1, index:idx_1(c2, c3) range:[\"10\",\"10\"], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 19.99 cop[tikv] table:tt1 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + }, + { + "SQL": "select /*+ use_index_merge( tt2 ) */ 1 from tt2 where tt2.c1 in (-3896405) or tt2.pk in (1, 53330) and to_base64(left(pk, 5));", + "Plan": [ + "Projection 2.40 root 1->Column#3", + "└─Selection 2.40 root or(eq(test.tt2.c1, -3896405), and(in(test.tt2.pk, 1, 53330), istrue_with_null(cast(to_base64(left(cast(test.tt2.pk, var_string(20)), 5)), double BINARY))))", + " └─IndexMerge 3.00 root ", + " ├─IndexRangeScan(Build) 1.00 cop[tikv] table:tt2, index:c1(c1) range:[-3896405,-3896405], keep order:false, stats:pseudo", + " ├─TableRangeScan(Build) 2.00 cop[tikv] table:tt2 range:[1,1], [53330,53330], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 3.00 cop[tikv] table:tt2 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + }, + { + "SQL": "select /*+ use_index_merge(tt3) */ 1 from tt3 where c1 < -10 or c2 < 10 and reverse(c3) = '2';", + "Plan": [ + "Projection 5098.44 root 1->Column#5", + "└─Selection 2825.66 root or(lt(test.tt3.c1, -10), and(lt(test.tt3.c2, 10), eq(reverse(cast(test.tt3.c3, var_string(20))), \"2\")))", + " └─IndexMerge 5542.21 root ", + " ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:tt3, index:c1(c1) range:[-inf,-10), keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:tt3, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 5542.21 cop[tikv] table:tt3 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + }, + { + "SQL": "select 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';", + "Plan": [ + "Projection 8000.00 root 1->Column#5", + "└─Selection 8000.00 root or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1" + ] + } + ] + }, + { + "Name": "TestIndexMergeWithCorrelatedColumns", + "Cases": [ + { + "SQL": "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 = 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and substring(c3, 10)) order by c1;", + "Plan": [ + "Sort 10000.00 root test.t2.c1", + "└─Projection 10000.00 root test.t2.c1, test.t2.c2, test.t2.c3", + " └─Apply 10000.00 root CARTESIAN inner join, other cond:or(and(lt(test.t2.c1, Column#8), if(ne(Column#9, 0), NULL, 1)), or(eq(Column#10, 0), if(isnull(test.t2.c1), NULL, 0)))", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─StreamAgg(Probe) 1.00 root funcs:min(test.t1.c1)->Column#8, funcs:sum(0)->Column#9, funcs:count(1)->Column#10", + " └─IndexMerge 0.01 root ", + " ├─Selection(Build) 1.00 cop[tikv] eq(10, test.t2.c3)", + " │ └─TableRangeScan 1.00 cop[tikv] table:t1 range:[10,10], keep order:false, stats:pseudo", + " ├─Selection(Build) 8.00 cop[tikv] eq(1, test.t2.c3)", + " │ └─IndexRangeScan 10.00 cop[tikv] table:t1, index:c2(c2) range:[1,1], keep order:false, stats:pseudo", + " └─Selection(Probe) 0.01 cop[tikv] or(and(eq(test.t1.c1, 10), eq(10, test.t2.c3)), and(eq(test.t1.c2, 1), eq(1, test.t2.c3))), substring(cast(test.t1.c3, var_string(20)), 10)", + " └─TableRowIDScan 9.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1 1 1", + "2 2 2" + ] + }, + { + "SQL": "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 = 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and reverse(c3)) order by c1;", + "Plan": [ + "Sort 10000.00 root test.t2.c1", + "└─Projection 10000.00 root test.t2.c1, test.t2.c2, test.t2.c3", + " └─Apply 10000.00 root CARTESIAN inner join, other cond:or(and(lt(test.t2.c1, Column#8), if(ne(Column#9, 0), NULL, 1)), or(eq(Column#10, 0), if(isnull(test.t2.c1), NULL, 0)))", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─StreamAgg(Probe) 1.00 root funcs:min(test.t1.c1)->Column#8, funcs:sum(0)->Column#9, funcs:count(1)->Column#10", + " └─IndexMerge 0.01 root ", + " ├─Selection(Build) 1.00 cop[tikv] eq(10, test.t2.c3)", + " │ └─TableRangeScan 1.00 cop[tikv] table:t1 range:[10,10], keep order:false, stats:pseudo", + " ├─Selection(Build) 8.00 cop[tikv] eq(1, test.t2.c3)", + " │ └─IndexRangeScan 10.00 cop[tikv] table:t1, index:c2(c2) range:[1,1], keep order:false, stats:pseudo", + " └─Selection(Probe) 0.01 cop[tikv] or(and(eq(test.t1.c1, 10), eq(10, test.t2.c3)), and(eq(test.t1.c2, 1), eq(1, test.t2.c3))), reverse(cast(test.t1.c3, var_string(20)))", + " └─TableRowIDScan 9.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "2 2 2" + ] + }, + { + "SQL": "select * from t2 where c1 < all(select /*+ use_index_merge(t1) */ c1 from t1 where (c1 >= 10 and c1 = t2.c3 or c2 = 1 and c2 = t2.c3) and substring(c3, 10)) order by c1;", + "Plan": [ + "Sort 10000.00 root test.t2.c1", + "└─Projection 10000.00 root test.t2.c1, test.t2.c2, test.t2.c3", + " └─Apply 10000.00 root CARTESIAN inner join, other cond:or(and(lt(test.t2.c1, Column#8), if(ne(Column#9, 0), NULL, 1)), or(eq(Column#10, 0), if(isnull(test.t2.c1), NULL, 0)))", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─StreamAgg(Probe) 1.00 root funcs:min(test.t1.c1)->Column#8, funcs:sum(0)->Column#9, funcs:count(1)->Column#10", + " └─IndexMerge 3.03 root ", + " ├─Selection(Build) 3.33 cop[tikv] eq(test.t1.c1, test.t2.c3)", + " │ └─TableRangeScan 3333.33 cop[tikv] table:t1 range:[10,+inf], keep order:false, stats:pseudo", + " ├─Selection(Build) 8.00 cop[tikv] eq(1, test.t2.c3)", + " │ └─IndexRangeScan 10.00 cop[tikv] table:t1, index:c2(c2) range:[1,1], keep order:false, stats:pseudo", + " └─Selection(Probe) 3.03 cop[tikv] or(and(ge(test.t1.c1, 10), eq(test.t1.c1, test.t2.c3)), and(eq(test.t1.c2, 1), eq(1, test.t2.c3))), substring(cast(test.t1.c3, var_string(20)), 10)", + " └─TableRowIDScan 3338.67 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1 1 1", + "2 2 2" + ] + }, + { + "SQL": "select c_int from tt1 where c_decimal < all (select /*+ use_index_merge(tt2) */ c_decimal from tt2 where tt1.c_int = tt2.c_int and tt1.c_datetime > tt2.c_datetime and tt2.c_decimal = 9.060 or tt2.c_str <= 'interesting shtern' and tt1.c_int = tt2.c_int) order by 1;", + "Plan": [ + "Projection 10000.00 root test.tt1.c_int", + "└─Apply 10000.00 root CARTESIAN inner join, other cond:or(and(lt(test.tt1.c_decimal, Column#9), if(ne(Column#10, 0), NULL, 1)), or(eq(Column#11, 0), if(isnull(test.tt1.c_decimal), NULL, 0)))", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:tt1 keep order:true, stats:pseudo", + " └─StreamAgg(Probe) 1.00 root funcs:min(Column#14)->Column#9, funcs:sum(Column#15)->Column#10, funcs:count(1)->Column#11", + " └─Projection 0.00 root test.tt2.c_decimal, cast(isnull(test.tt2.c_decimal), decimal(20,0) BINARY)->Column#15", + " └─IndexMerge 0.00 root ", + " ├─Selection(Build) 0.00 cop[tikv] eq(test.tt1.c_int, test.tt2.c_int)", + " │ └─IndexRangeScan 1.00 cop[tikv] table:tt2, index:c_decimal(c_decimal) range:[9.060000,9.060000], keep order:false, stats:pseudo", + " ├─Selection(Build) 3.32 cop[tikv] eq(test.tt1.c_int, test.tt2.c_int)", + " │ └─IndexRangeScan 3323.33 cop[tikv] table:tt2, index:c_str(c_str) range:[-inf,\"interesting shtern\"], keep order:false, stats:pseudo", + " └─Selection(Probe) 0.00 cop[tikv] or(and(eq(test.tt1.c_int, test.tt2.c_int), and(gt(test.tt1.c_datetime, test.tt2.c_datetime), eq(test.tt2.c_decimal, 9.060))), and(le(test.tt2.c_str, \"interesting shtern\"), eq(test.tt1.c_int, test.tt2.c_int)))", + " └─TableRowIDScan 3.32 cop[tikv] table:tt2 keep order:false, stats:pseudo" + ], + "Res": [ + "7", + "8", + "10" + ] + }, + { + "SQL": "select c_int from tt1 where c_decimal > all (select /*+ use_index_merge(tt2) */ c_decimal from tt2 where tt2.c_int = 7 and tt2.c_int < tt1.c_decimal or tt2.c_str >= 'zzzzzzzzzzzzzzzzzzz' and tt1.c_int = tt2.c_int) order by 1;", + "Plan": [ + "Projection 10000.00 root test.tt1.c_int", + "└─Apply 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.tt1.c_decimal, Column#9), if(ne(Column#10, 0), NULL, 1)), or(eq(Column#11, 0), if(isnull(test.tt1.c_decimal), NULL, 0)))", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:tt1 keep order:true, stats:pseudo", + " └─StreamAgg(Probe) 1.00 root funcs:max(Column#14)->Column#9, funcs:sum(Column#15)->Column#10, funcs:count(1)->Column#11", + " └─Projection 0.00 root test.tt2.c_decimal, cast(isnull(test.tt2.c_decimal), decimal(20,0) BINARY)->Column#15", + " └─IndexMerge 0.00 root ", + " ├─Selection(Build) 1.00 cop[tikv] lt(7, test.tt1.c_decimal)", + " │ └─TableRangeScan 1.00 cop[tikv] table:tt2 range:[7,7], keep order:false, stats:pseudo", + " ├─Selection(Build) 3.33 cop[tikv] eq(test.tt1.c_int, test.tt2.c_int)", + " │ └─IndexRangeScan 3333.33 cop[tikv] table:tt2, index:c_str(c_str) range:[\"zzzzzzzzzzzzzzzzzzz\",+inf], keep order:false, stats:pseudo", + " └─Selection(Probe) 0.00 cop[tikv] or(and(eq(test.tt2.c_int, 7), lt(7, test.tt1.c_decimal)), and(ge(test.tt2.c_str, \"zzzzzzzzzzzzzzzzzzz\"), eq(test.tt1.c_int, test.tt2.c_int)))", + " └─TableRowIDScan 4.33 cop[tikv] table:tt2 keep order:false, stats:pseudo" + ], + "Res": [ + "6", + "7", + "8", + "9" + ] + } + ] + }, + { + "Name": "TestIssue31240", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from t31240;", + "Plan": [ + "StreamAgg 1.00 root funcs:count(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#6", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t31240 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "set @@tidb_isolation_read_engines=\"tiflash,tidb\";", + "Plan": null + }, + { + "SQL": "explain format = 'brief' select count(*) from t31240;", + "Plan": [ + "StreamAgg 1.00 root funcs:count(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#6", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t31240 keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestSelPushDownTiFlash", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from t where t.a > 1 and t.b = \"flash\" or t.a + 3 * t.a = 5", + "Plan": [ + "TableReader 8000.67 root data:Selection", + "└─Selection 8000.67 cop[tiflash] or(and(gt(test.t.a, 1), eq(test.t.b, \"flash\")), eq(plus(test.t.a, mul(3, test.t.a)), 5))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1", + "Plan": [ + "TableReader 8000.00 root data:Selection", + "└─Selection 8000.00 cop[tiflash] eq(plus(cast(test.t.a, double BINARY), 3), 5.1)", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from t where b > 'a' order by convert(b, unsigned) limit 2", + "Plan": [ + "Projection 2.00 root test.t.a, test.t.b", + "└─TopN 2.00 root Column#4, offset:0, count:2", + " └─Projection 2.00 root test.t.a, test.t.b, cast(test.t.b, bigint(22) UNSIGNED BINARY)->Column#4", + " └─TableReader 2.00 root data:Projection", + " └─Projection 2.00 batchCop[tiflash] test.t.a, test.t.b", + " └─TopN 2.00 batchCop[tiflash] Column#3, offset:0, count:2", + " └─Projection 3333.33 batchCop[tiflash] test.t.a, test.t.b, cast(test.t.b, bigint(22) UNSIGNED BINARY)->Column#3", + " └─Selection 3333.33 batchCop[tiflash] gt(test.t.b, \"a\")", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from t where b > 'a' order by b limit 2", + "Plan": [ + "TopN 2.00 root test.t.b, offset:0, count:2", + "└─TableReader 2.00 root data:TopN", + " └─TopN 2.00 batchCop[tiflash] test.t.b, offset:0, count:2", + " └─Selection 3333.33 batchCop[tiflash] gt(test.t.b, \"a\")", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestVerboseExplain", + "Cases": [ + { + "SQL": "explain format = 'verbose' select count(*) from t3", + "Plan": [ + "StreamAgg_20 1.00 12.68 root funcs:count(Column#9)->Column#4", + "└─TableReader_21 1.00 9.68 root data:StreamAgg_8", + " └─StreamAgg_8 1.00 117.00 cop[tikv] funcs:count(1)->Column#9", + " └─TableFullScan_18 3.00 108.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t2", + "Plan": [ + "StreamAgg_25 1.00 8.18 root funcs:count(Column#7)->Column#4", + "└─TableReader_26 1.00 5.17 root data:StreamAgg_9", + " └─StreamAgg_9 1.00 49.50 batchCop[tiflash] funcs:count(1)->Column#7", + " └─TableFullScan_24 3.00 40.50 batchCop[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select * from t3 order by a", + "Plan": [ + "Sort_4 3.00 45.85 root test.t3.a", + "└─TableReader_8 3.00 11.78 root data:TableFullScan_7", + " └─TableFullScan_7 3.00 108.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select * from t3 order by b", + "Plan": [ + "Sort_4 3.00 45.85 root test.t3.b", + "└─TableReader_8 3.00 11.78 root data:TableFullScan_7", + " └─TableFullScan_7 3.00 108.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select * from t3 order by a limit 1", + "Plan": [ + "TopN_7 1.00 13.22 root test.t3.a, offset:0, count:1", + "└─TableReader_16 1.00 10.22 root data:TopN_15", + " └─TopN_15 1.00 0.00 cop[tikv] test.t3.a, offset:0, count:1", + " └─TableFullScan_14 3.00 108.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select * from t3 order by b limit 1", + "Plan": [ + "TopN_7 1.00 13.22 root test.t3.b, offset:0, count:1", + "└─TableReader_16 1.00 10.22 root data:TopN_15", + " └─TopN_15 1.00 0.00 cop[tikv] test.t3.b, offset:0, count:1", + " └─TableFullScan_14 3.00 108.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t2 group by a", + "Plan": [ + "TableReader_24 3.00 3.33 root data:ExchangeSender_23", + "└─ExchangeSender_23 3.00 57.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection_22 3.00 0.00 mpp[tiflash] Column#4", + " └─HashAgg_8 3.00 57.00 mpp[tiflash] group by:test.t2.a, funcs:count(1)->Column#4", + " └─ExchangeReceiver_21 3.00 48.00 mpp[tiflash] ", + " └─ExchangeSender_20 3.00 48.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.a, collate: binary]", + " └─TableFullScan_19 3.00 45.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t3 where b = 0", + "Plan": [ + "StreamAgg_10 1.00 1.33 root funcs:count(1)->Column#4", + "└─IndexReader_15 0.00 1.33 root index:IndexRangeScan_14", + " └─IndexRangeScan_14 0.00 0.00 cop[tikv] table:t3, index:c(b) range:[0,0], keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select /*+ use_index(t3, c) */ count(a) from t3 where b = 0", + "Plan": [ + "StreamAgg_10 1.00 19.33 root funcs:count(test.t3.a)->Column#4", + "└─IndexLookUp_17 0.00 19.33 root ", + " ├─IndexRangeScan_15(Build) 0.00 0.00 cop[tikv] table:t3, index:c(b) range:[0,0], keep order:false", + " └─TableRowIDScan_16(Probe) 0.00 0.00 cop[tikv] table:t3 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t2 where a = 0", + "Plan": [ + "StreamAgg_11 1.00 4.93 root funcs:count(1)->Column#4", + "└─TableReader_23 0.00 4.93 root data:Selection_22", + " └─Selection_22 0.00 54.00 cop[tiflash] eq(test.t2.a, 0)", + " └─TableFullScan_21 3.00 45.00 cop[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t3 t join t3 on t.a = t3.b", + "Plan": [ + "StreamAgg_10 1.00 60.22 root funcs:count(1)->Column#7", + "└─HashJoin_40 3.00 51.22 root inner join, equal:[eq(test.t3.a, test.t3.b)]", + " ├─IndexReader_28(Build) 3.00 11.66 root index:IndexFullScan_27", + " │ └─IndexFullScan_27 3.00 130.50 cop[tikv] table:t3, index:c(b) keep order:false", + " └─TableReader_26(Probe) 3.00 10.76 root data:Selection_25", + " └─Selection_25 3.00 117.00 cop[tikv] not(isnull(test.t3.a))", + " └─TableFullScan_24 3.00 108.00 cop[tikv] table:t keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a", + "Plan": [ + "StreamAgg_14 1.00 18.93 root funcs:count(1)->Column#7", + "└─TableReader_46 3.00 9.93 root data:ExchangeSender_45", + " └─ExchangeSender_45 3.00 195.38 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_42 3.00 195.38 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a)]", + " ├─ExchangeReceiver_21(Build) 3.00 57.00 mpp[tiflash] ", + " │ └─ExchangeSender_20 3.00 57.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection_19 3.00 54.00 mpp[tiflash] not(isnull(test.t1.a))", + " │ └─TableFullScan_18 3.00 45.00 mpp[tiflash] table:t1 keep order:false", + " └─Selection_23(Probe) 3.00 54.00 mpp[tiflash] not(isnull(test.t2.a))", + " └─TableFullScan_22 3.00 45.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select count(*) from t1 join t2 on t1.a = t2.a join t3 on t1.b = t3.b", + "Plan": [ + "StreamAgg_15 1.00 60.60 root funcs:count(1)->Column#10", + "└─HashJoin_65 3.00 51.60 root inner join, equal:[eq(test.t1.b, test.t3.b)]", + " ├─IndexReader_53(Build) 3.00 11.66 root index:IndexFullScan_52", + " │ └─IndexFullScan_52 3.00 130.50 cop[tikv] table:t3, index:c(b) keep order:false", + " └─TableReader_39(Probe) 3.00 11.14 root data:ExchangeSender_38", + " └─ExchangeSender_38 3.00 204.38 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_29 3.00 204.38 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a)]", + " ├─ExchangeReceiver_35(Build) 3.00 66.00 mpp[tiflash] ", + " │ └─ExchangeSender_34 3.00 66.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection_33 3.00 63.00 mpp[tiflash] not(isnull(test.t1.a)), not(isnull(test.t1.b))", + " │ └─TableFullScan_32 3.00 54.00 mpp[tiflash] table:t1 keep order:false", + " └─Selection_37(Probe) 3.00 54.00 mpp[tiflash] not(isnull(test.t2.a))", + " └─TableFullScan_36 3.00 45.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select (2) in (select count(*) from t1) from (select t.b < (select t.b from t2 limit 1 ) from t3 t) t", + "Plan": [ + "HashJoin_19 3.00 127.40 root CARTESIAN left outer semi join", + "├─Selection_39(Build) 0.80 11.18 root eq(2, Column#18)", + "│ └─StreamAgg_60 1.00 8.18 root funcs:count(Column#32)->Column#18", + "│ └─TableReader_61 1.00 5.17 root data:StreamAgg_44", + "│ └─StreamAgg_44 1.00 49.50 batchCop[tiflash] funcs:count(1)->Column#32", + "│ └─TableFullScan_59 3.00 40.50 batchCop[tiflash] table:t1 keep order:false", + "└─Projection_20(Probe) 3.00 95.82 root 1->Column#28", + " └─Apply_22 3.00 76.02 root CARTESIAN left outer join", + " ├─TableReader_24(Build) 3.00 10.16 root data:TableFullScan_23", + " │ └─TableFullScan_23 3.00 108.00 cop[tikv] table:t keep order:false", + " └─Projection_27(Probe) 1.00 21.95 root 1->Column#26", + " └─Limit_30 1.00 3.35 root offset:0, count:1", + " └─TableReader_38 1.00 3.35 root data:ExchangeSender_37", + " └─ExchangeSender_37 1.00 19.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Limit_36 1.00 19.50 mpp[tiflash] offset:0, count:1", + " └─TableFullScan_35 1.00 19.50 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'verbose' select /*+ merge_join(t1) */ count(*) from t1 join t2 on t1.a = t2.a", + "Plan": [ + "StreamAgg_13 1.00 59.65 root funcs:count(1)->Column#7", + "└─MergeJoin_31 3.00 50.65 root inner join, left key:test.t1.a, right key:test.t2.a", + " ├─Sort_29(Build) 3.00 20.83 root test.t2.a", + " │ └─TableReader_28 3.00 6.56 root data:Selection_27", + " │ └─Selection_27 3.00 54.00 cop[tiflash] not(isnull(test.t2.a))", + " │ └─TableFullScan_26 3.00 45.00 cop[tiflash] table:t2 keep order:false", + " └─Sort_22(Probe) 3.00 20.83 root test.t1.a", + " └─TableReader_21 3.00 6.56 root data:Selection_20", + " └─Selection_20 3.00 54.00 cop[tiflash] not(isnull(test.t1.a))", + " └─TableFullScan_19 3.00 45.00 cop[tiflash] table:t1 keep order:false" + ] + } + ] + }, + { + "Name": "TestRegardNULLAsPoint", + "Cases": [ + { + "SQL": "select * from tuk where a<=>null and b=1", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.01 root index:Selection_6", + "└─Selection_6 0.01 cop[tikv] eq(test.tuk.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tik where a<=>null and b=1", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.01 root index:Selection_6", + "└─Selection_6 0.01 cop[tikv] eq(test.tik.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tuk where a<=>null and b>0 and b<2", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.25 root index:Selection_6", + "└─Selection_6 0.25 cop[tikv] eq(test.tuk.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tik where a<=>null and b>0 and b<2", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.25 root index:Selection_6", + "└─Selection_6 0.25 cop[tikv] eq(test.tik.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tuk where a<=>null and b>=1 and b<2", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.25 root index:Selection_6", + "└─Selection_6 0.25 cop[tikv] eq(test.tuk.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tik where a<=>null and b>=1 and b<2", + "PlanEnabled": [ + "IndexReader_6 0.10 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1,NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.25 root index:Selection_6", + "└─Selection_6 0.25 cop[tikv] eq(test.tik.b, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 ", + " 1 ", + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tuk where a<=>null and b=1 and c=1", + "PlanEnabled": [ + "IndexReader_6 1.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL 1 1,NULL 1 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tuk.b, 1), eq(test.tuk.c, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tik where a<=>null and b=1 and c=1", + "PlanEnabled": [ + "IndexReader_6 0.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL 1 1,NULL 1 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tik.b, 1), eq(test.tik.c, 1)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1 1", + " 1 1" + ] + }, + { + "SQL": "select * from tuk where a=1 and b<=>null and c=1", + "PlanEnabled": [ + "IndexReader_6 1.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[1 NULL 1,1 NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tuk.c, 1)", + " └─IndexRangeScan_5 0.10 cop[tikv] table:tuk, index:a(a, b, c) range:[1 NULL,1 NULL], keep order:false, stats:pseudo" + ], + "Result": [ + "1 1", + "1 1" + ] + }, + { + "SQL": "select * from tik where a=1 and b<=>null and c=1", + "PlanEnabled": [ + "IndexReader_6 0.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[1 NULL 1,1 NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tik.c, 1)", + " └─IndexRangeScan_5 0.10 cop[tikv] table:tik, index:a(a, b, c) range:[1 NULL,1 NULL], keep order:false, stats:pseudo" + ], + "Result": [ + "1 1", + "1 1" + ] + }, + { + "SQL": "select * from tuk where a<=>null and b<=>null and c=1", + "PlanEnabled": [ + "IndexReader_6 1.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL NULL 1,NULL NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tuk.c, 1), nulleq(test.tuk.b, NULL)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1", + " 1" + ] + }, + { + "SQL": "select * from tik where a<=>null and b<=>null and c=1", + "PlanEnabled": [ + "IndexReader_6 0.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL NULL 1,NULL NULL 1], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] eq(test.tik.c, 1), nulleq(test.tik.b, NULL)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " 1", + " 1" + ] + }, + { + "SQL": "select * from tuk where a<=>null and b<=>null and c<=>null", + "PlanEnabled": [ + "IndexReader_6 1.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 1.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL NULL NULL,NULL NULL NULL], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] nulleq(test.tuk.b, NULL), nulleq(test.tuk.c, NULL)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tuk, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " ", + " " + ] + }, + { + "SQL": "select * from tik where a<=>null and b<=>null and c<=>null", + "PlanEnabled": [ + "IndexReader_6 0.00 root index:IndexRangeScan_5", + "└─IndexRangeScan_5 0.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL NULL NULL,NULL NULL NULL], keep order:false, stats:pseudo" + ], + "PlanDisabled": [ + "IndexReader_7 0.00 root index:Selection_6", + "└─Selection_6 0.00 cop[tikv] nulleq(test.tik.b, NULL), nulleq(test.tik.c, NULL)", + " └─IndexRangeScan_5 10.00 cop[tikv] table:tik, index:a(a, b, c) range:[NULL,NULL], keep order:false, stats:pseudo" + ], + "Result": [ + " ", + " " + ] + } + ] + }, + { + "Name": "TestPushDownToTiFlashWithKeepOrder", + "Cases": [ + { + "SQL": "explain format = 'brief' select max(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:max(test.t.a)->Column#3", + "└─TopN 1.00 root test.t.a:desc, offset:0, count:1", + " └─TableReader 1.00 root data:TopN", + " └─TopN 1.00 batchCop[tiflash] test.t.a:desc, offset:0, count:1", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select min(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:min(test.t.a)->Column#3", + "└─Limit 1.00 root offset:0, count:1", + " └─TableReader 1.00 root data:Limit", + " └─Limit 1.00 cop[tiflash] offset:0, count:1", + " └─TableFullScan 1.00 cop[tiflash] table:t keep order:true, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestMPPJoin", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#17", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d3_k, test.d3_t.d3_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d3_t.d3_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d3_t keep order:false", + " └─HashJoin(Probe) 8.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d2_k, test.d2_t.d2_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d2_t.d2_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d2_t keep order:false", + " └─HashJoin(Probe) 8.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k)), not(isnull(test.fact_t.d2_k)), not(isnull(test.fact_t.d3_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 8.00 mpp[tiflash] ", + " │ └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:d1_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)], other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col1, 10)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col2, 10)], other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10)", + " ├─ExchangeReceiver(Build) 8.00 mpp[tiflash] ", + " │ └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:d1_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10), other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 8.00 mpp[tiflash] ", + " │ └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 8.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:d1_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k > d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 16.00 mpp[tiflash] CARTESIAN inner join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k > d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 16.00 mpp[tiflash] CARTESIAN left outer join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k > d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 16.00 mpp[tiflash] CARTESIAN right outer join, other cond:gt(test.fact_t.d1_k, test.d1_t.d1_k)", + " ├─ExchangeReceiver(Build) 8.00 mpp[tiflash] ", + " │ └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:d1_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where d1_k not in (select d1_k from d1_t)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] CARTESIAN anti semi join, other cond:eq(test.fact_t.d1_k, test.d1_t.d1_k)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─TableFullScan(Probe) 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPLeftSemiJoin", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select a from test.t); -- left semi", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, test.t.b", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#7)", + " └─HashJoin 10000.00 mpp[tiflash] left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select a from test.t where b1 or t1.a not in (select a from test.t); -- left anti", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, test.t.b", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#7)", + " └─HashJoin 10000.00 mpp[tiflash] anti left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a not in (select a from test.t where b1 or t1.b in (select a from test.t); -- cartesian left semi", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, test.t.b", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#7)", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN left outer semi join, other cond:eq(test.t.b, test.t.a)", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.a in (select b from test.t where b1 or t1.b not in (select a from test.t); -- cartesian left anti", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, test.t.b", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#7)", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN anti left outer semi join, other cond:eq(test.t.b, test.t.a)", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from test.t t1 where t1.a>1 or t1.b not in (select a from test.t where bColumn#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", + " ├─ExchangeReceiver(Build) 3.00 mpp[tiflash] ", + " │ └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " │ └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:a keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", + " ├─ExchangeReceiver(Build) 3.00 mpp[tiflash] ", + " │ └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " │ └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:a keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from a left join b on a.id = b.id", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", + " ├─ExchangeReceiver(Build) 3.00 mpp[tiflash] ", + " │ └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: binary]", + " │ └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " │ └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: binary]", + " └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", + " ├─ExchangeReceiver(Build) 3.00 mpp[tiflash] ", + " │ └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: binary]", + " │ └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " │ └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: binary]", + " └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPOuterJoinBuildSideForShuffleJoin", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from a left join b on a.id = b.id", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] left outer join, equal:[eq(test.a.id, test.b.id)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: binary]", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─ExchangeReceiver(Probe) 3.00 mpp[tiflash] ", + " └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: binary]", + " └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from b right join a on a.id = b.id", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] right outer join, equal:[eq(test.b.id, test.a.id)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.a.id, collate: binary]", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─ExchangeReceiver(Probe) 3.00 mpp[tiflash] ", + " └─ExchangeSender 3.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.b.id, collate: binary]", + " └─Selection 3.00 mpp[tiflash] not(isnull(test.b.id))", + " └─TableFullScan 3.00 mpp[tiflash] table:b keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPShuffledJoin", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d2_k = d2_t.d2_k and fact_t.d3_k = d3_t.d3_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#18)->Column#17", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#18", + " └─HashJoin 128.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d3_k, test.d3_t.d3_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d3_t.d3_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d3_t.d3_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d3_t keep order:false", + " └─ExchangeReceiver(Probe) 64.00 mpp[tiflash] ", + " └─ExchangeSender 64.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d3_k, collate: binary]", + " └─HashJoin 64.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d2_k, test.d2_t.d2_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d2_t.d2_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d2_t.d2_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d2_t keep order:false", + " └─ExchangeReceiver(Probe) 32.00 mpp[tiflash] ", + " └─ExchangeSender 32.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d2_k, collate: binary]", + " └─HashJoin 32.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k)), not(isnull(test.fact_t.d2_k)), not(isnull(test.fact_t.d3_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t where fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t, d1_t, d2_t, d3_t where fact_t.d1_k = d1_t.d1_k and fact_t.d1_k = d2_t.value and fact_t.d1_k = d3_t.value", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#18)->Column#17", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#18", + " └─HashJoin 128.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d1_k, test.d3_t.value)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d3_t.value, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d3_t.value))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d3_t keep order:false", + " └─HashJoin(Probe) 64.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d1_k, test.d2_t.value)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d2_t.value, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d2_t.value))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d2_t keep order:false", + " └─HashJoin(Probe) 32.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > d1_t.value", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)], other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 10", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col1, 10)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from (select case when t1.col1 is null then t2.col1 + 5 else 10 end as col1, t2.d1_k as d1_k from fact_t t1 right join fact_t t2 on t1.d1_k = t2.d1_k) fact_t join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col1 > 5", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#22)->Column#19", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#22", + " └─HashJoin 204.80 mpp[tiflash] inner join, equal:[eq(test.d1_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─Projection(Probe) 102.40 mpp[tiflash] test.fact_t.d1_k", + " └─Selection 102.40 mpp[tiflash] gt(case(isnull(test.fact_t.col1), plus(test.fact_t.col1, 5), 10), 5)", + " └─HashJoin 128.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.fact_t.d1_k)]", + " ├─ExchangeReceiver(Build) 16.00 mpp[tiflash] ", + " │ └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " │ └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 16.00 mpp[tiflash] table:t1 keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t left join d1_t on fact_t.d1_k = d1_t.d1_k and fact_t.col2 > 10 and fact_t.col1 > d1_t.value", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] left outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], left cond:[gt(test.fact_t.col2, 10)], other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10)", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─HashJoin 32.00 mpp[tiflash] right outer join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], right cond:gt(test.d1_t.value, 10), other cond:gt(test.fact_t.col1, test.d1_t.value)", + " ├─ExchangeReceiver(Build) 16.00 mpp[tiflash] ", + " │ └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " │ └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " │ └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false", + " └─ExchangeReceiver(Probe) 4.00 mpp[tiflash] ", + " └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#13)->Column#12", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#13", + " └─HashJoin 12.80 mpp[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#13)->Column#12", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#13", + " └─HashJoin 12.80 mpp[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 4.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─Selection 16.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#13)->Column#12", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#13", + " └─HashJoin 12.80 mpp[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#13)->Column#12", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#13", + " └─HashJoin 12.80 mpp[tiflash] anti semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", + " ├─ExchangeReceiver(Build) 4.00 mpp[tiflash] ", + " │ └─ExchangeSender 4.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─TableFullScan 4.00 mpp[tiflash] table:d1_t keep order:false", + " └─ExchangeReceiver(Probe) 16.00 mpp[tiflash] ", + " └─ExchangeSender 16.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.fact_t.d1_k, collate: binary]", + " └─TableFullScan 16.00 mpp[tiflash] table:fact_t keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError", + "Cases": [ + { + "SQL": "explain format = 'brief' select v from t3 as a left join (select t1.v1, t1.v2, t1.v1 + t1.v2 as v from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2) b on a.v1 = b.v1 and a.v2 = b.v2", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#13", + " └─HashJoin 1.00 mpp[tiflash] left outer join, equal:[eq(test.t3.v1, test.t1.v1) eq(test.t3.v2, test.t1.v2)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#23, collate: binary], [name: Column#24, collate: binary]", + " │ └─Projection 1.00 mpp[tiflash] test.t3.v1, test.t3.v2, cast(test.t3.v1, decimal(20,2))->Column#23, cast(test.t3.v2, decimal(20,2))->Column#24", + " │ └─TableFullScan 1.00 mpp[tiflash] table:a keep order:false", + " └─Projection(Probe) 2.00 mpp[tiflash] test.t1.v1, test.t1.v2, plus(test.t1.v1, test.t1.v2)->Column#13", + " └─HashJoin 2.00 mpp[tiflash] left outer join, equal:[eq(test.t1.v1, test.t2.v1) eq(test.t1.v2, test.t2.v2)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t1.v1, collate: binary], [name: test.t1.v2, collate: binary]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.t1.v1)), not(isnull(test.t1.v2))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:t1 keep order:false", + " └─ExchangeReceiver(Probe) 8.00 mpp[tiflash] ", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#15, collate: binary], [name: Column#16, collate: binary]", + " └─Projection 8.00 mpp[tiflash] test.t2.v1, test.t2.v2, cast(test.t2.v1, decimal(20,2))->Column#15, cast(test.t2.v2, decimal(20,2))->Column#16", + " └─Selection 8.00 mpp[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", + " └─TableFullScan 8.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*), t2.v1, t2.v2 from t1 left join t2 on t1.v1 = t2.v1 and t1.v2 = t2.v2 group by t2.v1, t2.v2", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 2.00 mpp[tiflash] Column#9, test.t2.v1, test.t2.v2", + " └─HashAgg 2.00 mpp[tiflash] group by:test.t2.v1, test.t2.v2, funcs:sum(Column#22)->Column#9, funcs:firstrow(test.t2.v1)->test.t2.v1, funcs:firstrow(test.t2.v2)->test.t2.v2", + " └─ExchangeReceiver 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: binary], [name: test.t2.v2, collate: binary]", + " └─HashAgg 2.00 mpp[tiflash] group by:test.t2.v1, test.t2.v2, funcs:count(1)->Column#22", + " └─HashJoin 2.00 mpp[tiflash] left outer join, equal:[eq(test.t1.v1, test.t2.v1) eq(test.t1.v2, test.t2.v2)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t1.v1, collate: binary], [name: test.t1.v2, collate: binary]", + " │ └─TableFullScan 2.00 mpp[tiflash] table:t1 keep order:false", + " └─ExchangeReceiver(Probe) 8.00 mpp[tiflash] ", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#14, collate: binary], [name: Column#15, collate: binary]", + " └─Projection 8.00 mpp[tiflash] test.t2.v1, test.t2.v2, cast(test.t2.v1, decimal(20,2))->Column#14, cast(test.t2.v2, decimal(20,2))->Column#15", + " └─Selection 8.00 mpp[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", + " └─TableFullScan 8.00 mpp[tiflash] table:t2 keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*), t2.v1, t2.v2 from t3 left join t2 on t3.v1 = t2.v1 and t3.v2 = t2.v2 group by t2.v1, t2.v2", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#9, test.t2.v1, test.t2.v2", + " └─HashAgg 1.00 mpp[tiflash] group by:test.t2.v1, test.t2.v2, funcs:sum(Column#16)->Column#9, funcs:firstrow(test.t2.v1)->test.t2.v1, funcs:firstrow(test.t2.v2)->test.t2.v2", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: binary], [name: test.t2.v2, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:test.t2.v1, test.t2.v2, funcs:count(1)->Column#16", + " └─HashJoin 1.00 mpp[tiflash] left outer join, equal:[eq(test.t3.v1, test.t2.v1) eq(test.t3.v2, test.t2.v2)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t3.v1, collate: binary], [name: test.t3.v2, collate: binary]", + " │ └─TableFullScan 1.00 mpp[tiflash] table:t3 keep order:false", + " └─ExchangeReceiver(Probe) 8.00 mpp[tiflash] ", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t2.v1, collate: binary], [name: test.t2.v2, collate: binary]", + " └─Selection 8.00 mpp[tiflash] not(isnull(test.t2.v1)), not(isnull(test.t2.v2))", + " └─TableFullScan 8.00 mpp[tiflash] table:t2 keep order:false" + ] + } + ] + }, + { + "Name": "TestJoinNotSupportedByTiFlash", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from table_1 a, table_1 b where a.bit_col = b.bit_col", + "Plan": [ + "HashJoin 2.00 root inner join, equal:[eq(test.table_1.bit_col, test.table_1.bit_col)]", + "├─TableReader(Build) 2.00 root data:TableFullScan", + "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", + "└─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a left join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > 100", + "Plan": [ + "HashJoin 2.00 root left outer join, equal:[eq(test.table_1.id, test.table_1.id)], left cond:[gt(dayofmonth(test.table_1.datetime_col), 100)]", + "├─TableReader(Build) 2.00 root data:TableFullScan", + "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", + "└─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a right join table_1 b on a.id = b.id and dayofmonth(b.datetime_col) > 100", + "Plan": [ + "HashJoin 2.00 root right outer join, equal:[eq(test.table_1.id, test.table_1.id)], right cond:gt(dayofmonth(test.table_1.datetime_col), 100)", + "├─TableReader(Build) 2.00 root data:TableFullScan", + "│ └─TableFullScan 2.00 cop[tiflash] table:a keep order:false", + "└─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tiflash] table:b keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a join table_1 b on a.id = b.id and dayofmonth(a.datetime_col) > dayofmonth(b.datetime_col)", + "Plan": [ + "HashJoin 2.00 root inner join, equal:[eq(test.table_1.id, test.table_1.id)], other cond:gt(dayofmonth(test.table_1.datetime_col), dayofmonth(test.table_1.datetime_col))", + "├─TableReader(Build) 2.00 root data:TableFullScan", + "│ └─TableFullScan 2.00 cop[tiflash] table:b keep order:false", + "└─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tiflash] table:a keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPWithHashExchangeUnderNewCollation", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from table_1 a, table_1 b where a.value = b.value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", + " └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " └─TableFullScan 2.00 mpp[tiflash] table:b keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a, table_2 b where a.value = b.value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", + " └─Selection 2.00 mpp[tiflash] not(isnull(test.table_2.value))", + " └─TableFullScan 2.00 mpp[tiflash] table:b keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and b.value = c.value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_2.value, test.table_1.value)]", + " ├─HashJoin(Build) 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", + " │ ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", + " │ │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " │ │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " │ └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_2.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:b keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", + " └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " └─TableFullScan 2.00 mpp[tiflash] table:c keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select * from table_1 a, table_2 b, table_1 c where a.value = b.value and a.value = c.value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", + " │ └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_2.value)]", + " │ ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_bin]", + " │ │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " │ │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " │ └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_2.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:b keep order:false", + " └─ExchangeReceiver(Probe) 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", + " └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " └─TableFullScan 2.00 mpp[tiflash] table:c keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_1 group by value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 2.00 mpp[tiflash] Column#4, test.table_1.value", + " └─HashAgg 2.00 mpp[tiflash] group by:test.table_1.value, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.table_1.value)->test.table_1.value", + " └─ExchangeReceiver 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.value, collate: utf8mb4_general_ci]", + " └─HashAgg 2.00 mpp[tiflash] group by:test.table_1.value, funcs:count(1)->Column#7", + " └─TableFullScan 2.00 mpp[tiflash] table:table_1 keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ agg_to_cop() */ count(*), value from table_2 group by value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 2.00 mpp[tiflash] Column#4, test.table_2.value", + " └─HashAgg 2.00 mpp[tiflash] group by:test.table_2.value, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.table_2.value)->test.table_2.value", + " └─ExchangeReceiver 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_2.value, collate: utf8mb4_bin]", + " └─HashAgg 2.00 mpp[tiflash] group by:test.table_2.value, funcs:count(1)->Column#7", + " └─TableFullScan 2.00 mpp[tiflash] table:table_2 keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPWithBroadcastExchangeUnderNewCollation", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.id = b.id", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.id, test.table_1.id)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─TableFullScan(Probe) 2.00 mpp[tiflash] table:b keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ broadcast_join(a,b) */ * from table_1 a, table_1 b where a.value = b.value", + "Plan": [ + "TableReader 2.00 root data:ExchangeSender", + "└─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 2.00 mpp[tiflash] inner join, equal:[eq(test.table_1.value, test.table_1.value)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:a keep order:false", + " └─Selection(Probe) 2.00 mpp[tiflash] not(isnull(test.table_1.value))", + " └─TableFullScan 2.00 mpp[tiflash] table:b keep order:false" + ] + } + ] + }, + { + "Name": "TestMPPAvgRewrite", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ avg_to_cop() */ id, avg(value+1),avg(value) from table_1 group by id", + "Plan": [ + "Projection 2.00 root test.table_1.id, Column#4, Column#5", + "└─TableReader 2.00 root data:ExchangeSender", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 2.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#13, 0), 1, Column#13), decimal(20,0) BINARY))->Column#4, div(Column#5, cast(case(eq(Column#14, 0), 1, Column#14), decimal(20,0) BINARY))->Column#5, test.table_1.id", + " └─HashAgg 2.00 mpp[tiflash] group by:test.table_1.id, funcs:sum(Column#15)->Column#13, funcs:sum(Column#16)->Column#4, funcs:sum(Column#17)->Column#14, funcs:sum(Column#18)->Column#5, funcs:firstrow(test.table_1.id)->test.table_1.id", + " └─ExchangeReceiver 2.00 mpp[tiflash] ", + " └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.table_1.id, collate: binary]", + " └─HashAgg 2.00 mpp[tiflash] group by:Column#29, funcs:count(Column#25)->Column#15, funcs:sum(Column#26)->Column#16, funcs:count(Column#27)->Column#17, funcs:sum(Column#28)->Column#18", + " └─Projection 2.00 mpp[tiflash] plus(test.table_1.value, 1)->Column#25, plus(test.table_1.value, 1)->Column#26, test.table_1.value, test.table_1.value, test.table_1.id", + " └─TableFullScan 2.00 mpp[tiflash] table:table_1 keep order:false" + ] + } + ] + }, + { + "Name": "TestReadFromStorageHint", + "Cases": [ + { + "SQL": "desc format = 'brief' select avg(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#7, funcs:sum(Column#10)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] test.t.a, cast(test.t.a, decimal(14,4) BINARY)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#7, funcs:sum(Column#10)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] test.t.a, cast(test.t.a, decimal(14,4) BINARY)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a+1) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.a, 1), decimal(20,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(isnull(a)) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(isnull(test.t.a), decimal(20,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIKV[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "Plan": [ + "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIFLASH[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "Plan": [ + "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "Plan": [ + "TableReader 44.00 root data:TableRangeScan", + "└─TableRangeScan 44.00 cop[tiflash] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[tt]) */ * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "Plan": [ + "TableReader 44.00 root data:TableRangeScan", + "└─TableRangeScan 44.00 cop[tiflash] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select * from ttt order by ttt.a desc", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:true, desc, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a desc", + "Plan": [ + "Sort 10000.00 root test.ttt.a:desc", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t, ttt]) */ * from ttt", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t) in optimizer hint /*+ READ_FROM_STORAGE(tikv[t, ttt]) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t, tt) in optimizer hint /*+ READ_FROM_STORAGE(tiflash[t, ttt], tikv[tt]) */. Maybe you can use the table alias name" + ] + } + ] + }, + { + "Name": "TestReadFromStorageHintAndIsolationRead", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t], tiflash[t]) */ avg(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", + "└─IndexReader 1.00 root index:StreamAgg", + " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Storage hints are conflict, you can only specify one storage type of table test.t" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t]) */ avg(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", + "└─IndexReader 1.00 root index:StreamAgg", + " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:avg(Column#7, Column#8)->Column#4", + "└─IndexReader 1.00 root index:StreamAgg", + " └─StreamAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#7, funcs:sum(test.t.a)->Column#8", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]No available path for table test.t with the store type tiflash of the hint /*+ read_from_storage */, please check the status of the table replica and variable value of tidb_isolation_read_engines(map[0:{}])" + ] + } + ] + }, + { + "Name": "TestIsolationReadDoNotFilterSystemDB", + "Cases": [ + { + "SQL": "desc format = 'brief' select * from metrics_schema.tidb_query_duration where time >= '2019-12-23 16:10:13' and time <= '2019-12-23 16:30:13'", + "Plan": [ + "MemTableScan 10000.00 root table:tidb_query_duration PromQL:histogram_quantile(0.9, sum(rate(tidb_server_handle_query_duration_seconds_bucket{}[60s])) by (le,sql_type,instance)), start_time:2019-12-23 16:10:13, end_time:2019-12-23 16:30:13, step:1m0s" + ] + }, + { + "SQL": "desc format = 'brief' select * from information_schema.tables", + "Plan": [ + "MemTableScan 10000.00 root table:TABLES " + ] + }, + { + "SQL": "desc format = 'brief' select * from mysql.stats_meta", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:stats_meta keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestIsolationReadTiFlashNotChoosePointGet", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from t where t.a = 1", + "Result": [ + "TableReader 1.00 root data:TableRangeScan", + "└─TableRangeScan 1.00 cop[tiflash] table:t range:[1,1], keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from t where t.a in (1, 2)", + "Result": [ + "TableReader 2.00 root data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tiflash] table:t range:[1,1], [2,2], keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestIsolationReadTiFlashUseIndexHint", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from t", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from t use index();", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "TiDB doesn't support index in the isolation read engines(value: 'tiflash')" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ use_index(t)*/ * from t", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestIssue20710", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.b", + "Plan": [ + "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.b)", + "├─TableReader(Build) 9980.01 root data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", + " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.b = s.a", + "Plan": [ + "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.a)", + "├─TableReader(Build) 9980.01 root data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ inl_join(s) */ * from t join s on t.a=s.a and t.a = s.b", + "Plan": [ + "IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.a, test.s.b)", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", + " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.b", + "Plan": [ + "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.b)", + "├─TableReader(Build) 9980.01 root data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", + " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.b = s.a", + "Plan": [ + "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.b, test.s.a)", + "├─TableReader(Build) 9980.01 root data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ inl_hash_join(s) */ * from t join s on t.a=s.a and t.a = s.b", + "Plan": [ + "IndexHashJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.s.a, equal cond:eq(test.t.a, test.s.a), eq(test.t.a, test.s.b)", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─Selection(Build) 1.25 cop[tikv] not(isnull(test.s.a))", + " │ └─IndexRangeScan 1.25 cop[tikv] table:s, index:a(a) range: decided by [eq(test.s.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 1.25 cop[tikv] not(isnull(test.s.b))", + " └─TableRowIDScan 1.25 cop[tikv] table:s keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestPushDownProjectionForTiFlash", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#8)->Column#6", + "└─TableReader 1.00 root data:HashAgg", + " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#9", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#7)->Column#6", + "└─TableReader 1.00 root data:HashAgg", + " └─HashAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#8)->Column#6", + "└─TableReader 1.00 root data:HashAgg", + " └─HashAgg 1.00 batchCop[tiflash] funcs:sum(Column#9)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(20,0) BINARY)->Column#9", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", + "Plan": [ + "StreamAgg 1.00 root funcs:count(Column#8)->Column#6", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(Column#10)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] plus(test.t.id, 1)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", + "Plan": [ + "StreamAgg 1.00 root funcs:count(Column#7)->Column#6", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:count(1)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#8)->Column#6", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#10)->Column#8", + " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.id, 1), decimal(20,0) BINARY)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "Plan": [ + "HashJoin 10000.00 root inner join, equal:[eq(Column#5, Column#10)]", + "├─Projection(Build) 8000.00 root minus(test.t.id, 2)->Column#10", + "│ └─TableReader 8000.00 root data:Selection", + "│ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─Projection(Probe) 8000.00 root minus(test.t.id, 2)->Column#5", + " └─TableReader 8000.00 root data:Selection", + " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "HashJoin 10000.00 root inner join, equal:[eq(test.t.id, Column#9)]", + "├─Projection(Build) 8000.00 root minus(test.t.id, 2)->Column#9", + "│ └─TableReader 8000.00 root data:Selection", + "│ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "HashJoin 10000.00 root left outer join, equal:[eq(test.t.id, Column#9)]", + "├─Projection(Build) 8000.00 root minus(test.t.id, 2)->Column#9", + "│ └─TableReader 8000.00 root data:Selection", + "│ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "HashJoin 12487.50 root right outer join, equal:[eq(test.t.id, Column#9)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─Projection(Probe) 10000.00 root minus(test.t.id, 2)->Column#9", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "Plan": [ + "Projection 10000.00 root Column#10, Column#5", + "└─HashJoin 10000.00 root inner join, equal:[eq(Column#5, Column#10)]", + " ├─Projection(Build) 8000.00 root minus(test.t.id, 2)->Column#10", + " │ └─TableReader 8000.00 root data:Selection", + " │ └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 8000.00 root minus(test.t.id, 2)->Column#5", + " └─TableReader 8000.00 root data:Selection", + " └─Selection 8000.00 cop[tiflash] not(isnull(minus(test.t.id, 2)))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select A.id from t as A where exists (select 1 from t where t.id=A.id)", + "Plan": [ + "HashJoin 7992.00 root semi join, equal:[eq(test.t.id, test.t.id)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select A.id from t as A where not exists (select 1 from t where t.id=A.id)", + "Plan": [ + "HashJoin 8000.00 root anti semi join, equal:[eq(test.t.id, test.t.id)]", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:A keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;", + "Plan": [ + "Projection 10000.00 root from_unixtime(cast(test.t.name, decimal(65,0) BINARY), %Y-%m-%d)->Column#5", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestPushDownProjectionForMPP", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#9)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(Column#11)->Column#9", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.id, 1)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#8)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#8", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#9)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#11)->Column#9", + " └─Projection 10000.00 mpp[tiflash] cast(plus(test.t.id, 1), decimal(20,0) BINARY)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#10)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(Column#11)->Column#10", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.id, 1)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ count(*) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#9)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ stream_agg()*/ sum(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#10)->Column#6", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#11)->Column#10", + " └─Projection 10000.00 mpp[tiflash] cast(plus(test.t.id, 1), decimal(20,0) BINARY)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select B.b+A.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 10000.00 mpp[tiflash] plus(Column#5, Column#10)->Column#11", + " └─HashJoin 10000.00 mpp[tiflash] inner join, equal:[eq(Column#5, Column#10)]", + " ├─ExchangeReceiver(Build) 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#5", + " │ └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#10", + " └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 10000.00 mpp[tiflash] inner join, equal:[eq(test.t.id, Column#9)]", + " ├─ExchangeReceiver(Build) 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#9", + " │ └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t left join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 10000.00 mpp[tiflash] left outer join, equal:[eq(test.t.id, Column#9)]", + " ├─ExchangeReceiver(Build) 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#9", + " │ └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t right join (select id-2 as b from t) A on A.b=t.id", + "Plan": [ + "TableReader 12487.50 root data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.id, Column#9)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 10000.00 mpp[tiflash] minus(test.t.id, 2)->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select A.b, B.b from (select id-2 as b from t) B join (select id-2 as b from t) A on A.b=B.b", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 10000.00 mpp[tiflash] Column#10, Column#5", + " └─HashJoin 10000.00 mpp[tiflash] inner join, equal:[eq(Column#5, Column#10)]", + " ├─ExchangeReceiver(Build) 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#5", + " │ └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 8000.00 mpp[tiflash] minus(test.t.id, 2)->Column#10", + " └─Selection 8000.00 mpp[tiflash] not(isnull(minus(test.t.id, 2)))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select id from t as A where exists (select 1 from t where t.id=A.id)", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7992.00 mpp[tiflash] semi join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:A keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select id from t as A where not exists (select 1 from t where t.id=A.id)", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8000.00 mpp[tiflash] anti semi join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:A keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select b*2, id from (select avg(value+2) as b, id from t group by id) C order by id", + "Plan": [ + "Sort 8000.00 root test.t.id", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] mul(Column#5, 2)->Column#6, test.t.id", + " └─Projection 8000.00 mpp[tiflash] div(Column#5, cast(case(eq(Column#20, 0), 1, Column#20), decimal(20,0) BINARY))->Column#5, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#21)->Column#20, funcs:sum(Column#22)->Column#5, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#26, funcs:count(Column#24)->Column#21, funcs:sum(Column#25)->Column#22", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.value, 2)->Column#24, plus(test.t.value, 2)->Column#25, test.t.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' SELECT FROM_UNIXTIME(name,'%Y-%m-%d') FROM t;", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 10000.00 mpp[tiflash] from_unixtime(cast(test.t.name, decimal(65,0) BINARY), %Y-%m-%d)->Column#5", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestMppUnionAll", + "Cases": [ + { + "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1) tt", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#12", + " └─Union 20000.00 mpp[tiflash] ", + " ├─Projection 10000.00 mpp[tiflash] cast(test.t.a, int(11) BINARY)->Column#9, test.t.b", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection 10000.00 mpp[tiflash] test.t1.a, cast(test.t1.b, int(11) BINARY)->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , b from t1 union all select a, b from t where false) tt", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#16)->Column#15", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#16", + " └─Union 20000.00 mpp[tiflash] ", + " ├─Projection 10000.00 mpp[tiflash] cast(test.t.a, int(11) BINARY)->Column#13, test.t.b", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection 10000.00 mpp[tiflash] test.t1.a, cast(test.t1.b, int(11) BINARY)->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1) tt", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#14)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#14", + " └─Union 20000.00 mpp[tiflash] ", + " ├─Projection 10000.00 mpp[tiflash] cast(Column#9, int(11) BINARY)->Column#9, Column#10", + " │ └─Projection 10000.00 mpp[tiflash] test.t.a, cast(test.t.b, double BINARY)->Column#10", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection 10000.00 mpp[tiflash] test.t1.a, cast(test.t1.c, double BINARY)->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from (select a , b from t union all select a , c from t1 where false) tt", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#14)->Column#11", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#14", + " └─Union 10000.00 mpp[tiflash] ", + " └─Projection 10000.00 mpp[tiflash] cast(Column#9, int(11) BINARY)->Column#9, Column#10", + " └─Projection 10000.00 mpp[tiflash] test.t.a, cast(test.t.b, double BINARY)->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from (select a , b from t where false union all select a , c from t1 where false) tt", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#11", + "└─Union 0.00 root ", + " ├─Projection 0.00 root test.t.a, cast(test.t.b, double BINARY)->Column#10", + " │ └─TableDual 0.00 root rows:0", + " └─Projection 0.00 root test.t1.a, cast(test.t1.c, double BINARY)->Column#10", + " └─TableDual 0.00 root rows:0" + ] + } + ] + }, + { + "Name": "TestMppJoinDecimal", + "Cases": [ + { + "SQL": "desc format = 'brief' select t1.c1, t1.c2, t2.c1, t2.c2, t2.c3 from t t1 join t t2 on t1.c1 + 1 = t2.c2 - 10 and t1.c1 * 3 = t2.c3 / 2", + "Plan": [ + "Projection 12500.00 root test.t.c1, test.t.c2, test.t.c1, test.t.c2, test.t.c3", + "└─TableReader 12500.00 root data:ExchangeSender", + " └─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(Column#13, Column#14) eq(Column#15, Column#16)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#21, collate: binary], [name: Column#22, collate: binary]", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, Column#13, Column#15, cast(Column#13, decimal(13,8) BINARY)->Column#21, cast(Column#15, decimal(10,5) BINARY)->Column#22", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, mul(test.t.c1, 3)->Column#13, plus(test.t.c1, 1)->Column#15", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#14, collate: binary], [name: Column#16, collate: binary]", + " └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, div(test.t.c3, 2)->Column#14, minus(test.t.c2, 10)->Column#16", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select c1, c2, c5, count(*) c from t group by c1, c2, c5) t1 join (select c1, c2, c3, count(*) c from t group by c1, c2, c3) t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c5 = t2.c1", + "Plan": [ + "Projection 7976.02 root test.t.c1, test.t.c2, test.t.c5, Column#7, test.t.c1, test.t.c2, test.t.c3, Column#14", + "└─TableReader 7976.02 root data:ExchangeSender", + " └─ExchangeSender 7976.02 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7976.02 mpp[tiflash] inner join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c3) eq(test.t.c5, test.t.c1)]", + " ├─ExchangeReceiver(Build) 7976.02 mpp[tiflash] ", + " │ └─ExchangeSender 7976.02 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary], [name: Column#31, collate: binary], [name: test.t.c5, collate: binary]", + " │ └─Projection 7976.02 mpp[tiflash] Column#7, test.t.c1, test.t.c2, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#31", + " │ └─Projection 7976.02 mpp[tiflash] Column#7, test.t.c1, test.t.c2, test.t.c5", + " │ └─HashAgg 7976.02 mpp[tiflash] group by:test.t.c1, test.t.c2, test.t.c5, funcs:sum(Column#15)->Column#7, funcs:firstrow(test.t.c1)->test.t.c1, funcs:firstrow(test.t.c2)->test.t.c2, funcs:firstrow(test.t.c5)->test.t.c5", + " │ └─ExchangeReceiver 7976.02 mpp[tiflash] ", + " │ └─ExchangeSender 7976.02 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary], [name: test.t.c2, collate: binary], [name: test.t.c5, collate: binary]", + " │ └─HashAgg 7976.02 mpp[tiflash] group by:test.t.c1, test.t.c2, test.t.c5, funcs:count(1)->Column#15", + " │ └─Selection 9970.03 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 7984.01 mpp[tiflash] ", + " └─ExchangeSender 7984.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary], [name: Column#32, collate: binary], [name: Column#33, collate: binary]", + " └─Projection 7984.01 mpp[tiflash] Column#14, test.t.c1, test.t.c2, test.t.c3, cast(test.t.c3, decimal(10,5))->Column#32, cast(test.t.c1, decimal(40,20))->Column#33", + " └─Projection 7984.01 mpp[tiflash] Column#14, test.t.c1, test.t.c2, test.t.c3", + " └─HashAgg 7984.01 mpp[tiflash] group by:test.t.c1, test.t.c2, test.t.c3, funcs:sum(Column#23)->Column#14, funcs:firstrow(test.t.c1)->test.t.c1, funcs:firstrow(test.t.c2)->test.t.c2, funcs:firstrow(test.t.c3)->test.t.c3", + " └─ExchangeReceiver 7984.01 mpp[tiflash] ", + " └─ExchangeSender 7984.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary], [name: test.t.c3, collate: binary], [name: test.t.c1, collate: binary]", + " └─HashAgg 7984.01 mpp[tiflash] group by:test.t.c1, test.t.c2, test.t.c3, funcs:count(1)->Column#23", + " └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c2 and t1.c3 = t2.c3 and t1.c4 = t2.c4 and t1.c5 = t2.c5", + "Plan": [ + "TableReader 12462.54 root data:ExchangeSender", + "└─ExchangeSender 12462.54 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12462.54 mpp[tiflash] inner join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c2) eq(test.t.c3, test.t.c3) eq(test.t.c4, test.t.c4) eq(test.t.c5, test.t.c5)]", + " ├─ExchangeReceiver(Build) 9970.03 mpp[tiflash] ", + " │ └─ExchangeSender 9970.03 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary], [name: test.t.c2, collate: binary], [name: test.t.c3, collate: binary], [name: test.t.c4, collate: binary], [name: test.t.c5, collate: binary]", + " │ └─Selection 9970.03 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9980.01 mpp[tiflash] ", + " └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary], [name: test.t.c2, collate: binary], [name: test.t.c3, collate: binary], [name: test.t.c4, collate: binary], [name: test.t.c5, collate: binary]", + " └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5", + "Plan": [ + "Projection 12462.54 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", + "└─TableReader 12462.54 root data:ExchangeSender", + " └─ExchangeSender 12462.54 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12462.54 mpp[tiflash] inner join, equal:[eq(test.t.c2, test.t.c1) eq(test.t.c3, test.t.c2) eq(test.t.c1, test.t.c3) eq(test.t.c3, test.t.c4) eq(test.t.c5, test.t.c1)]", + " ├─ExchangeReceiver(Build) 9970.03 mpp[tiflash] ", + " │ └─ExchangeSender 9970.03 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary], [name: Column#13, collate: binary], [name: Column#15, collate: binary], [name: test.t.c3, collate: binary], [name: test.t.c5, collate: binary]", + " │ └─Projection 9970.03 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c3, decimal(10,5))->Column#13, cast(test.t.c1, decimal(10,5))->Column#15", + " │ └─Selection 9970.03 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9980.01 mpp[tiflash] ", + " └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary], [name: Column#14, collate: binary], [name: Column#16, collate: binary], [name: test.t.c4, collate: binary], [name: Column#17, collate: binary]", + " └─Projection 9980.01 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#14, cast(test.t.c3, decimal(10,5))->Column#16, cast(test.t.c1, decimal(40,20))->Column#17", + " └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t t1 join t t2 on t1.c1 + t1.c2 = t2.c2 / t2.c3", + "Plan": [ + "Projection 12500.00 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", + "└─TableReader 12500.00 root data:ExchangeSender", + " └─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(Column#13, Column#14)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: binary]", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, Column#13, cast(Column#13, decimal(17,9) BINARY)->Column#17", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, plus(test.t.c1, test.t.c2)->Column#13", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#14, collate: binary]", + " └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, div(test.t.c2, test.t.c3)->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t t1 where exists (select * from t t2 where t1.c1 = t2.c2 and t1.c2 = t2.c3 and t1.c3 = t2.c1 and t1.c4 = t2.c3 and t1.c1 = t2.c5)", + "Plan": [ + "Projection 7984.01 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", + "└─TableReader 7984.01 root data:ExchangeSender", + " └─ExchangeSender 7984.01 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7984.01 mpp[tiflash] semi join, equal:[eq(test.t.c1, test.t.c2) eq(test.t.c2, test.t.c3) eq(test.t.c3, test.t.c1) eq(test.t.c4, test.t.c3) eq(test.t.c1, test.t.c5)]", + " ├─ExchangeReceiver(Build) 9970.03 mpp[tiflash] ", + " │ └─ExchangeSender 9970.03 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary], [name: Column#14, collate: binary], [name: Column#16, collate: binary], [name: test.t.c3, collate: binary], [name: test.t.c5, collate: binary]", + " │ └─Projection 9970.03 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c5, cast(test.t.c3, decimal(10,5))->Column#14, cast(test.t.c1, decimal(10,5))->Column#16", + " │ └─Selection 9970.03 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9980.01 mpp[tiflash] ", + " └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary], [name: Column#13, collate: binary], [name: Column#15, collate: binary], [name: test.t.c4, collate: binary], [name: Column#17, collate: binary]", + " └─Projection 9980.01 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c2, decimal(10,5))->Column#13, cast(test.t.c3, decimal(10,5))->Column#15, cast(test.t.c1, decimal(40,20))->Column#17", + " └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.c1)), not(isnull(test.t.c2))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t t1 left join t t2 on t1.c1 = t2.c2 join t t3 on t2.c5 = t3.c3 right join t t4 on t3.c3 = t4.c4 ", + "Plan": [ + "Projection 19492.21 root test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", + "└─TableReader 19492.21 root data:ExchangeSender", + " └─ExchangeSender 19492.21 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 19492.21 mpp[tiflash] right outer join, equal:[eq(test.t.c3, test.t.c4)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#27, collate: binary]", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c4, decimal(40,20))->Column#27", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 keep order:false, stats:pseudo", + " └─Projection(Probe) 15593.77 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t.c5, test.t.c3)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#25, collate: binary]", + " │ └─Projection 10000.00 mpp[tiflash] test.t.c1, test.t.c2, test.t.c3, test.t.c4, test.t.c5, cast(test.t.c3, decimal(40,20))->Column#25", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t3 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 12475.01 mpp[tiflash] ", + " └─ExchangeSender 12475.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c5, collate: binary]", + " └─HashJoin 12475.01 mpp[tiflash] inner join, equal:[eq(test.t.c2, test.t.c1)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c2, collate: binary]", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.c2)), not(isnull(test.t.c5))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.c1, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.c1))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' SELECT STRAIGHT_JOIN t1 . col_varchar_64 , t1 . col_char_64_not_null FROM tt AS t1 INNER JOIN( tt AS t2 JOIN tt AS t3 ON(t3 . col_decimal_30_10_key = t2 . col_tinyint)) ON(t3 . col_varchar_64 = t2 . col_varchar_key) WHERE t3 . col_varchar_64 = t1 . col_char_64_not_null GROUP BY 1 , 2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.tt.col_varchar_64, test.tt.col_char_64_not_null", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.tt.col_char_64_not_null, test.tt.col_varchar_64, funcs:firstrow(test.tt.col_varchar_64)->test.tt.col_varchar_64, funcs:firstrow(test.tt.col_char_64_not_null)->test.tt.col_char_64_not_null", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_64, collate: utf8mb4_bin], [name: test.tt.col_char_64_not_null, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.tt.col_char_64_not_null, test.tt.col_varchar_64, ", + " └─HashJoin 15609.38 mpp[tiflash] inner join, equal:[eq(test.tt.col_char_64_not_null, test.tt.col_varchar_64)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_char_64_not_null, collate: utf8mb4_bin]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12487.50 mpp[tiflash] inner join, equal:[eq(test.tt.col_varchar_key, test.tt.col_varchar_64) eq(Column#19, test.tt.col_decimal_30_10_key)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_key, collate: utf8mb4_bin]", + " │ └─Projection 9990.00 mpp[tiflash] test.tt.col_varchar_key, cast(test.tt.col_tinyint, decimal(20,0) BINARY)->Column#19", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.tt.col_varchar_key))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.tt.col_varchar_64, collate: utf8mb4_bin]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.tt.col_varchar_64))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t3 keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestPushDownAggForMPP", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#8)->Column#5", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(Column#9)->Column#8", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.id, 1)->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ count(*) from (select id+1 from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#7)->Column#5", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#7", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg()*/ sum(b) from (select id + 1 as b from t)A", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#8)->Column#5", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#9)->Column#8", + " └─Projection 10000.00 mpp[tiflash] cast(plus(test.t.id, 1), decimal(20,0) BINARY)->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*) from t", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#6)->Column#4", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#6", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*), id from t group by id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#7", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*), id + 1 from t group by id + 1", + "Plan": [ + "Projection 8000.00 root Column#4, plus(test.t.id, 1)->Column#5", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, funcs:sum(Column#11)->Column#4, funcs:firstrow(Column#12)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#10, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:count(1)->Column#11, funcs:firstrow(Column#16)->Column#12", + " └─Projection 10000.00 mpp[tiflash] test.t.id, plus(test.t.id, 1)->Column#17", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", + "Plan": [ + "TableReader 9990.00 root data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] Column#7, test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#8", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", + "Plan": [ + "HashJoin 1.25 root inner join, equal:[eq(test.t.id, Column#7)]", + "├─HashAgg(Build) 1.00 root funcs:count(Column#11)->Column#7", + "│ └─TableReader 1.00 root data:ExchangeSender", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#11", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select avg(value) as b,id from t group by id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#9, 0), 1, Column#9), decimal(20,0) BINARY))->Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#10)->Column#9, funcs:sum(Column#11)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#10, funcs:sum(test.t.value)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(b) from (select avg(value) as b, id from t group by id)A", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#18)->Column#5", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#4)->Column#18", + " └─Projection 8000.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#15, 0), 1, Column#15), decimal(20,0) BINARY))->Column#4", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#16)->Column#15, funcs:sum(Column#17)->Column#4", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#16, funcs:sum(test.t.value)->Column#17", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select id from t group by id having avg(value)>0", + "Plan": [ + "Projection 6400.00 root test.t.id", + "└─Selection 6400.00 root gt(Column#4, 0)", + " └─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#10, 0), 1, Column#10), decimal(20,0) BINARY))->Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#11)->Column#10, funcs:sum(Column#12)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#11, funcs:sum(test.t.value)->Column#12", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select avg(value),id from t group by id having avg(value)>0", + "Plan": [ + "Selection 6400.00 root gt(Column#4, 0)", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#12)->Column#11, funcs:sum(Column#13)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#12, funcs:sum(test.t.value)->Column#13", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select avg(value) +1,id from t group by id", + "Plan": [ + "Projection 8000.00 root plus(Column#4, 1)->Column#5, test.t.id", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] div(Column#4, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#12)->Column#11, funcs:sum(Column#13)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(test.t.value)->Column#12, funcs:sum(test.t.value)->Column#13", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 7992.00 mpp[tiflash] Column#7", + " └─HashAgg 7992.00 mpp[tiflash] group by:Column#11, funcs:sum(Column#10)->Column#7", + " └─Projection 12487.50 mpp[tiflash] cast(test.t.id, decimal(10,0) BINARY)->Column#10, test.t.id", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7992.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 7992.00 mpp[tiflash] Column#11, test.t.id", + " └─HashAgg 7992.00 mpp[tiflash] group by:Column#39, funcs:sum(Column#37)->Column#11, funcs:firstrow(Column#38)->test.t.id", + " └─Projection 9990.00 mpp[tiflash] cast(test.t.id, decimal(10,0) BINARY)->Column#37, test.t.id, test.t.id", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] test.t.id, Column#13", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id, funcs:sum(Column#17)->Column#13", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#17", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(distinct value),id from t group by id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#4, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(distinct test.t.value)->Column#4, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.value, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(distinct value),sum(distinct value),id from t group by id", + "Plan": [ + "HashAgg 8000.00 root group by:test.t.id, funcs:count(distinct test.t.value)->Column#4, funcs:sum(distinct test.t.value)->Column#5, funcs:firstrow(test.t.id)->test.t.id", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select count(distinct value), id from t group by id) as A on A.id = t.id", + "Plan": [ + "TableReader 9990.00 root data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] Column#7, test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:count(distinct test.t.value)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, test.t.value, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select count(1/value), id from t group by id) as A on A.id = t.id", + "Plan": [ + "TableReader 9990.00 root data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] Column#7, test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:Column#19, funcs:count(Column#18)->Column#8", + " │ └─Projection 9990.00 mpp[tiflash] div(1, test.t.value)->Column#18, test.t.id", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(id) from (select value, id from t where id > value group by id, value)A group by value /*the exchange should have only one partition column: test.t.value*/", + "Plan": [ + "TableReader 6400.00 root data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 6400.00 mpp[tiflash] Column#4", + " └─HashAgg 6400.00 mpp[tiflash] group by:Column#20, funcs:sum(Column#19)->Column#4", + " └─Projection 6400.00 mpp[tiflash] cast(test.t.id, decimal(10,0) BINARY)->Column#19, test.t.value", + " └─Projection 6400.00 mpp[tiflash] test.t.id, test.t.value", + " └─HashAgg 6400.00 mpp[tiflash] group by:test.t.id, test.t.value, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", + " └─ExchangeReceiver 6400.00 mpp[tiflash] ", + " └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.value, collate: binary]", + " └─HashAgg 6400.00 mpp[tiflash] group by:test.t.id, test.t.value, ", + " └─Selection 8000.00 mpp[tiflash] gt(cast(test.t.id, decimal(20,0) BINARY), test.t.value)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select /*+hash_agg()*/ sum(B.value) from t as B where B.id+1 > (select count(*) from t where t.id= B.id and t.value=B.value) group by B.id /*the exchange should have only one partition column: test.t.id*/", + "Plan": [ + "TableReader 6400.00 root data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 6400.00 mpp[tiflash] Column#8", + " └─HashAgg 6400.00 mpp[tiflash] group by:test.t.id, funcs:sum(test.t.value)->Column#8", + " └─Selection 8000.00 mpp[tiflash] gt(plus(test.t.id, 1), ifnull(Column#7, 0))", + " └─HashJoin 10000.00 mpp[tiflash] left outer join, equal:[eq(test.t.id, test.t.id) eq(test.t.value, test.t.value)]", + " ├─Projection(Build) 7984.01 mpp[tiflash] Column#7, test.t.id, test.t.value", + " │ └─HashAgg 7984.01 mpp[tiflash] group by:test.t.id, test.t.value, funcs:sum(Column#24)->Column#7, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", + " │ └─ExchangeReceiver 7984.01 mpp[tiflash] ", + " │ └─ExchangeSender 7984.01 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7984.01 mpp[tiflash] group by:test.t.id, test.t.value, funcs:count(1)->Column#24", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.id)), not(isnull(test.t.value))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:B keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(distinct value) from t", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#4", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.t.value)->Column#4", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.t.value, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(distinct x ) from (select count(distinct value) x from t) t", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct Column#4)->Column#5", + " └─Projection 1.00 mpp[tiflash] Column#4", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.t.value)->Column#4", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.t.value, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(distinct value), count(value), avg(value) from t", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#4, Column#5, div(Column#6, cast(case(eq(Column#7, 0), 1, Column#7), decimal(20,0) BINARY))->Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.t.value)->Column#4, funcs:sum(Column#8)->Column#5, funcs:sum(Column#9)->Column#7, funcs:sum(Column#10)->Column#6", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.t.value, funcs:count(test.t.value)->Column#8, funcs:count(test.t.value)->Column#9, funcs:sum(test.t.value)->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestMppAggTopNWithJoin", + "Cases": [ + { + "SQL": "desc format = 'brief' select * from t join ( select count(*), id from t group by id) as A on A.id = t.id", + "Plan": [ + "TableReader 9990.00 root data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] Column#7, test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#8", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select count(*)+id as v from t group by id) as A on A.v = t.id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.t.id, Column#8)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 6400.00 mpp[tiflash] plus(Column#7, test.t.id)->Column#8", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(Column#7, test.t.id)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#7, test.t.id", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#11)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#11", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select count(*) as v, id from t group by value,id having value+v <10) as A on A.id = t.id", + "Plan": [ + "Projection 7992.00 root test.t.id, test.t.value, Column#7, test.t.id", + "└─TableReader 7992.00 root data:ExchangeSender", + " └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7992.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 6393.60 mpp[tiflash] ", + " │ └─ExchangeSender 6393.60 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 6393.60 mpp[tiflash] lt(plus(test.t.value, cast(Column#7, decimal(20,0) BINARY)), 10)", + " │ └─Projection 7992.00 mpp[tiflash] Column#7, test.t.id, test.t.value", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, test.t.value, funcs:sum(Column#10)->Column#7, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.value)->test.t.value", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.value, collate: binary], [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, test.t.value, funcs:count(1)->Column#10", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join ( select /*+ hash_agg()*/ count(*) as a from t) as A on A.a = t.id", + "Plan": [ + "HashJoin 1.25 root inner join, equal:[eq(test.t.id, Column#7)]", + "├─HashAgg(Build) 1.00 root funcs:count(Column#10)->Column#7", + "│ └─TableReader 1.00 root data:ExchangeSender", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#10", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select sum(b) from (select t.id, t1.id as b from t join t t1 on t.id=t1.id)A group by id", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 7992.00 mpp[tiflash] Column#7", + " └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#8)->Column#7", + " └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 7992.00 mpp[tiflash] group by:Column#11, funcs:sum(Column#10)->Column#8", + " └─Projection 12487.50 mpp[tiflash] cast(test.t.id, decimal(10,0) BINARY)->Column#10, test.t.id", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(value),id from t group by id)B on C.id=B.id", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7992.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 7992.00 mpp[tiflash] Column#7, test.t.id", + " └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#9)->Column#7, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(test.t.value)->Column#9", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select id from t group by id) C join (select sum(b),id from (select t.id, t1.id as b from t join (select id, count(*) as c from t group by id) t1 on t.id=t1.id)A group by id)B on C.id=b.id", + "Plan": [ + "TableReader 7992.00 root data:ExchangeSender", + "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 7992.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 7992.00 mpp[tiflash] Column#11, test.t.id", + " └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:sum(Column#17)->Column#11, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " └─HashAgg 7992.00 mpp[tiflash] group by:Column#33, funcs:sum(Column#32)->Column#17", + " └─Projection 9990.00 mpp[tiflash] cast(test.t.id, decimal(10,0) BINARY)->Column#32, test.t.id", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] test.t.id, Column#13", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id, funcs:sum(Column#16)->Column#13", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:count(1)->Column#16", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value limit 1", + "Plan": [ + "TopN 1.00 root test.t.value, offset:0, count:1", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TopN 1.00 mpp[tiflash] test.t.value, offset:0, count:1", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id order by t.value % 100 limit 1", + "Plan": [ + "Projection 1.00 root test.t.id, test.t.value, test.t.id, test.t.value", + "└─TopN 1.00 root Column#8, offset:0, count:1", + " └─Projection 1.00 root test.t.id, test.t.value, test.t.id, test.t.value, mod(test.t.value, 100)->Column#8", + " └─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] test.t.id, test.t.value, test.t.id, test.t.value", + " └─TopN 1.00 mpp[tiflash] Column#7, offset:0, count:1", + " └─Projection 12487.50 mpp[tiflash] test.t.id, test.t.value, test.t.id, test.t.value, mod(test.t.value, 100)->Column#7", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id order by t.value limit 20) v group by v.v1", + "Plan": [ + "HashAgg 20.00 root group by:test.t.value, funcs:count(1)->Column#7", + "└─TopN 20.00 root test.t.value, offset:0, count:20", + " └─TableReader 20.00 root data:ExchangeSender", + " └─ExchangeSender 20.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TopN 20.00 mpp[tiflash] test.t.value, offset:0, count:20", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", + "Plan": [ + "Limit 1.00 root offset:0, count:1", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Limit 1.00 mpp[tiflash] offset:0, count:1", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 0.80 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t join t t1 on t.id = t1.id limit 1", + "Plan": [ + "Limit 1.00 root offset:0, count:1", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Limit 1.00 mpp[tiflash] offset:0, count:1", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 0.80 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*) from (select t.id, t.value v1 from t join t t1 on t.id = t1.id limit 20) v group by v.v1", + "Plan": [ + "HashAgg 20.00 root group by:test.t.value, funcs:count(1)->Column#7", + "└─Limit 20.00 root offset:0, count:20", + " └─TableReader 20.00 root data:ExchangeSender", + " └─ExchangeSender 20.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Limit 20.00 mpp[tiflash] offset:0, count:20", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 16.02 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestIndexMergeSerial", + "Cases": [ + { + "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and b+2>1)", + "Plan": [ + "IndexMerge 8.00 root ", + "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", + "├─Selection(Build) 1.00 cop[tikv] 1", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", + "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" + ], + "Warnings": null + }, + { + "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where a =1 or (b=1 and length(b)=1)", + "Plan": [ + "IndexMerge 8.00 root ", + "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", + "├─Selection(Build) 1.00 cop[tikv] 1", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", + "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" + ], + "Warnings": null + }, + { + "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(a)=1) or (b=1 and length(b)=1)", + "Plan": [ + "IndexMerge 8.00 root ", + "├─Selection(Build) 1.00 cop[tikv] 1", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", + "├─Selection(Build) 1.00 cop[tikv] 1", + "│ └─IndexRangeScan 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", + "└─TableRowIDScan(Probe) 8.00 cop[tikv] table:t keep order:false" + ], + "Warnings": null + }, + { + "SQL": "desc format='brief' select /*+ use_index_merge(t) */ * from t where (a=1 and length(b)=1) or (b=1 and length(a)=1)", + "Plan": [ + "IndexMerge 0.29 root ", + "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false", + "├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false", + "└─Selection(Probe) 0.29 cop[tikv] or(and(eq(test.t.a, 1), eq(length(cast(test.t.b, var_string(20))), 1)), and(eq(test.t.b, 1), eq(length(cast(test.t.a, var_string(20))), 1)))", + " └─TableRowIDScan 1.90 cop[tikv] table:t keep order:false" + ], + "Warnings": null + } + ] + }, + { + "Name": "TestLimitIndexLookUpKeepOrder", + "Cases": [ + { + "SQL": "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b,c limit 10", + "Plan": [ + "Limit 0.00 root offset:0, count:10", + "└─Projection 0.00 root test.t.a, test.t.b, test.t.c, test.t.d", + " └─IndexLookUp 0.00 root ", + " ├─IndexRangeScan(Build) 2.50 cop[tikv] table:t, index:idx(a, b, c) range:(1 2,1 10), keep order:true, stats:pseudo", + " └─Selection(Probe) 0.00 cop[tikv] eq(test.t.d, 10)", + " └─TableRowIDScan 2.50 cop[tikv] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from t where a = 1 and b > 2 and b < 10 and d = 10 order by b desc, c desc limit 10", + "Plan": [ + "Limit 0.00 root offset:0, count:10", + "└─Projection 0.00 root test.t.a, test.t.b, test.t.c, test.t.d", + " └─IndexLookUp 0.00 root ", + " ├─IndexRangeScan(Build) 2.50 cop[tikv] table:t, index:idx(a, b, c) range:(1 2,1 10), keep order:true, desc, stats:pseudo", + " └─Selection(Probe) 0.00 cop[tikv] eq(test.t.d, 10)", + " └─TableRowIDScan 2.50 cop[tikv] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestIssue23887", + "Cases": [ + { + "SQL": "select (2) in (select b from t) from (select t.a < (select t.a from t t1 limit 1) from t) t", + "Plan": [ + "HashJoin 10000.00 root CARTESIAN left outer semi join, other cond:eq(2, test.t.b)", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "└─Projection(Probe) 10000.00 root 1->Column#27", + " └─Apply 10000.00 root CARTESIAN left outer join", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 1.00 root 1->Column#25", + " └─Limit 1.00 root offset:0, count:1", + " └─TableReader 1.00 root data:Limit", + " └─Limit 1.00 cop[tikv] offset:0, count:1", + " └─TableFullScan 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Res": [ + "1", + "1" + ] + } + ] + }, + { + "Name": "TestMergeContinuousSelections", + "Cases": [ + { + "SQL": "desc format = 'brief' SELECT table2 . `col_char_64` AS field1 FROM `ts` AS table2 INNER JOIN (SELECT DISTINCT SUBQUERY3_t1 . * FROM `ts` AS SUBQUERY3_t1 LEFT OUTER JOIN `ts` AS SUBQUERY3_t2 ON SUBQUERY3_t2 . `col_varchar_64_not_null` = SUBQUERY3_t1 . `col_varchar_key`) AS table3 ON (table3 . `col_varchar_key` = table2 . `col_varchar_64`) WHERE table3 . `col_char_64_not_null` >= SOME (SELECT SUBQUERY4_t1 . `col_varchar_64` AS SUBQUERY4_field1 FROM `ts` AS SUBQUERY4_t1) GROUP BY field1 ;", + "Plan": [ + "HashAgg 7992.00 root group by:test.ts.col_char_64, funcs:firstrow(test.ts.col_char_64)->test.ts.col_char_64", + "└─HashJoin 9990.00 root CARTESIAN inner join, other cond:or(ge(test.ts.col_char_64_not_null, Column#25), if(ne(Column#26, 0), NULL, 0))", + " ├─Selection(Build) 0.80 root ne(Column#27, 0)", + " │ └─HashAgg 1.00 root funcs:min(Column#36)->Column#25, funcs:sum(Column#37)->Column#26, funcs:count(Column#38)->Column#27", + " │ └─TableReader 1.00 root data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:min(Column#42)->Column#36, funcs:sum(Column#43)->Column#37, funcs:count(1)->Column#38", + " │ └─Projection 10000.00 mpp[tiflash] test.ts.col_varchar_64, cast(isnull(test.ts.col_varchar_64), decimal(20,0) BINARY)->Column#43", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:SUBQUERY4_t1 keep order:false, stats:pseudo", + " └─TableReader(Probe) 12487.50 root data:ExchangeSender", + " └─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.ts.col_varchar_64, test.ts.col_varchar_key)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.ts.col_varchar_64))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:table2 keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.ts.col_varchar_key))", + " └─TableFullScan 10000.00 mpp[tiflash] table:SUBQUERY3_t1 keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestPushDownGroupConcatToTiFlash", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(Column#7 separator \",\")->Column#5", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#9, Column#10, Column#11 separator \",\")->Column#7", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#6, Column#7, Column#8 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_1) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#8, Column#9, Column#10 order by Column#11 separator \",\")->Column#5, funcs:count(1)->Column#6, funcs:min(Column#12)->Column#7", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#10, test.ts.col_0, test.ts.col_1", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_0) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#12, Column#13, Column#14 order by Column#15 separator \",\")->Column#5, funcs:sum(Column#16)->Column#6, funcs:max(Column#17)->Column#7", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#14, test.ts.col_0, Column#10, Column#11", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.id, funcs:count(1)->Column#10, funcs:max(test.ts.col_0)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_2, funcs:group_concat(Column#9 separator \",\")->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:group_concat(Column#10, Column#11, Column#12 separator \",\")->Column#9", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#12, test.ts.col_2", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#9, funcs:group_concat(distinct Column#6, Column#7, Column#8 separator \",\")->Column#5", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_2", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.col_2, test.ts.id, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, funcs:group_concat(Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0, test.ts.col_2", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, funcs:group_concat(distinct Column#6, Column#7, Column#8 order by Column#9 separator \",\")->Column#5", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#8, test.ts.col_0, test.ts.col_2", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_0, test.ts.col_1, test.ts.col_2, test.ts.id, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_1, id order by col_0) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#9, funcs:group_concat(Column#6, Column#7 order by Column#8 separator \",\")->Column#5", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#7, test.ts.col_0, test.ts.col_2", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_1, id order by col_0) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#9, funcs:group_concat(distinct Column#6, Column#7 order by Column#8 separator \",\")->Column#5", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#7, test.ts.col_0, test.ts.col_2", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_1, test.ts.col_2, test.ts.id, funcs:firstrow(test.ts.col_0)->test.ts.col_0", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(*),min(col_0),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#11, 0), 1, Column#11), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#20, funcs:group_concat(Column#13, Column#14, Column#15 order by Column#16 separator \",\")->Column#5, funcs:count(1)->Column#6, funcs:min(Column#17)->Column#7, funcs:count(Column#18)->Column#11, funcs:sum(Column#19)->Column#8", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#15, test.ts.col_0, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#19, test.ts.col_2", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(*),max(col_1),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#20, 0), 1, Column#20), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#40, funcs:group_concat(distinct Column#32, Column#33, Column#34 order by Column#35 separator \",\")->Column#5, funcs:sum(Column#36)->Column#6, funcs:max(Column#37)->Column#7, funcs:sum(Column#38)->Column#20, funcs:sum(Column#39)->Column#8", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#34, test.ts.col_0, Column#21, Column#22, Column#23, Column#24, test.ts.col_2", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#28, Column#29, Column#30, Column#31, funcs:count(1)->Column#21, funcs:max(Column#25)->Column#22, funcs:count(Column#26)->Column#23, funcs:sum(Column#27)->Column#24", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#27, test.ts.col_2, test.ts.col_0, test.ts.col_1, test.ts.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id order by col_0),count(distinct id),min(col_0),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#10, 0), 1, Column#10), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#11, Column#12, Column#13 order by Column#14 separator \",\")->Column#5, funcs:count(Column#15)->Column#6, funcs:min(Column#16)->Column#7, funcs:count(Column#17)->Column#10, funcs:sum(Column#18)->Column#8", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#13, test.ts.col_0, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#18", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id order by col_0),count(distinct id),max(col_1),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#14, 0), 1, Column#14), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#26, Column#27, Column#28 order by Column#29 separator \",\")->Column#5, funcs:sum(Column#30)->Column#6, funcs:max(Column#31)->Column#7, funcs:sum(Column#32)->Column#14, funcs:sum(Column#33)->Column#8", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#28, test.ts.col_0, Column#15, Column#16, Column#17, Column#18", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#23, Column#24, Column#25, funcs:count(Column#19)->Column#15, funcs:max(Column#20)->Column#16, funcs:count(Column#21)->Column#17, funcs:sum(Column#22)->Column#18", + " └─Projection 10000.00 mpp[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#22, test.ts.col_0, test.ts.col_1, test.ts.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#27, 0), 1, Column#27), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_2, funcs:group_concat(Column#28 separator \",\")->Column#5, funcs:sum(Column#29)->Column#6, funcs:min(Column#30)->Column#7, funcs:sum(Column#31)->Column#27, funcs:sum(Column#32)->Column#8", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#40, funcs:group_concat(Column#33, Column#34, Column#35 separator \",\")->Column#28, funcs:count(Column#36)->Column#29, funcs:min(Column#37)->Column#30, funcs:count(Column#38)->Column#31, funcs:sum(Column#39)->Column#32", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#35, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#39, test.ts.col_2", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#20, 0), 1, Column#20), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#40, funcs:group_concat(distinct Column#33, Column#34, Column#35 separator \",\")->Column#5, funcs:sum(Column#36)->Column#6, funcs:max(Column#37)->Column#7, funcs:sum(Column#38)->Column#20, funcs:sum(Column#39)->Column#8", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#35, Column#21, Column#22, Column#23, Column#24, test.ts.col_2", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, Column#30, Column#31, Column#32, funcs:count(Column#25)->Column#21, funcs:max(Column#26)->Column#22, funcs:count(Column#27)->Column#23, funcs:sum(Column#28)->Column#24", + " └─Projection 10000.00 mpp[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#28, test.ts.col_2, test.ts.col_0, test.ts.col_1, test.ts.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),min(col_0),avg(id) from ts", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(Column#14 separator \",\")->Column#5, funcs:count(Column#15)->Column#6, funcs:min(Column#16)->Column#7, funcs:avg(Column#17, Column#18)->Column#8", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#24, Column#25, Column#26 separator \",\")->Column#14, funcs:count(Column#27)->Column#15, funcs:min(Column#28)->Column#16, funcs:count(Column#29)->Column#17, funcs:sum(Column#30)->Column#18", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#26, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#30", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),max(col_1),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#14, 0), 1, Column#14), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#26, Column#27, Column#28 separator \",\")->Column#5, funcs:sum(Column#29)->Column#6, funcs:max(Column#30)->Column#7, funcs:sum(Column#31)->Column#14, funcs:sum(Column#32)->Column#8", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#28, Column#15, Column#16, Column#17, Column#18", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#23, Column#24, Column#25, funcs:count(Column#19)->Column#15, funcs:max(Column#20)->Column#16, funcs:count(Column#21)->Column#17, funcs:sum(Column#22)->Column#18", + " └─Projection 10000.00 mpp[tiflash] test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#22, test.ts.col_0, test.ts.col_1, test.ts.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_1, id),count(distinct id),group_concat(col_0 order by 1),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#17, 0), 1, Column#17), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, funcs:group_concat(Column#21, Column#22, Column#23 separator \",\")->Column#5, funcs:count(Column#24)->Column#6, funcs:group_concat(Column#25 order by Column#26 separator \",\")->Column#7, funcs:count(Column#27)->Column#17, funcs:sum(Column#28)->Column#8", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#23, test.ts.id, test.ts.col_0, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#28, test.ts.col_2", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0),count(distinct id),group_concat(col_1, id order by 1,2),avg(id) from ts group by col_2", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, div(Column#8, cast(case(eq(Column#13, 0), 1, Column#13), decimal(20,0) BINARY))->Column#8", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#24, funcs:group_concat(distinct Column#16 separator \",\")->Column#5, funcs:count(Column#17)->Column#6, funcs:group_concat(Column#18, Column#19 order by Column#20, Column#21 separator \",\")->Column#7, funcs:count(Column#22)->Column#13, funcs:sum(Column#23)->Column#8", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#19, test.ts.col_1, test.ts.id, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#23, test.ts.col_2", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_2, collate: utf8mb4_bin]", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, id),count(distinct id),group_concat(col_1, id order by 1,2),min(col_0),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#15, 0), 1, Column#15), decimal(20,0) BINARY))->Column#9", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(Column#18, Column#19 separator \",\")->Column#5, funcs:count(Column#20)->Column#6, funcs:group_concat(Column#21, Column#22 order by Column#23, Column#24 separator \",\")->Column#7, funcs:min(Column#25)->Column#8, funcs:count(Column#26)->Column#15, funcs:sum(Column#27)->Column#9", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, cast(test.ts.id, var_string(20))->Column#19, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#22, test.ts.col_1, test.ts.id, test.ts.col_0, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#27", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct id),group_concat(col_1, id order by 1,2),max(col_1),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#12, 0), 1, Column#12), decimal(20,0) BINARY))->Column#9", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#14, Column#15, Column#16 separator \",\")->Column#5, funcs:count(Column#17)->Column#6, funcs:group_concat(Column#18, Column#19 order by Column#20, Column#21 separator \",\")->Column#7, funcs:max(Column#22)->Column#8, funcs:count(Column#23)->Column#12, funcs:sum(Column#24)->Column#9", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#16, test.ts.id, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#19, test.ts.col_1, test.ts.id, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#24", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#15, 0), 1, Column#15), decimal(20,0) BINARY))->Column#9", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#29, Column#30, Column#31 separator \",\")->Column#5, funcs:count(distinct Column#32)->Column#6, funcs:group_concat(Column#33 separator \",\")->Column#7, funcs:max(Column#34)->Column#8, funcs:sum(Column#35)->Column#15, funcs:sum(Column#36)->Column#9", + " └─Projection 1.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#31, test.ts.col_2, Column#16, Column#17, Column#18, Column#19", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#25, Column#26, Column#27, Column#28, funcs:group_concat(Column#20, Column#21 separator \",\")->Column#16, funcs:max(Column#22)->Column#17, funcs:count(Column#23)->Column#18, funcs:sum(Column#24)->Column#19", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#21, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#24, test.ts.col_0, test.ts.col_1, test.ts.id, test.ts.col_2", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0, col_1, id),count(distinct col_2),group_concat(col_1, id),max(col_1),avg(id) from ts group by col_0", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, Column#6, Column#7, Column#8, div(Column#9, cast(case(eq(Column#21, 0), 1, Column#21), decimal(20,0) BINARY))->Column#9", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#43, funcs:group_concat(distinct Column#35, Column#36, Column#37 separator \",\")->Column#5, funcs:count(distinct Column#38)->Column#6, funcs:group_concat(Column#39 separator \",\")->Column#7, funcs:max(Column#40)->Column#8, funcs:sum(Column#41)->Column#21, funcs:sum(Column#42)->Column#9", + " └─Projection 8000.00 mpp[tiflash] test.ts.col_0, test.ts.col_1, cast(test.ts.id, var_string(20))->Column#37, test.ts.col_2, Column#22, Column#23, Column#24, Column#25, test.ts.col_0", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_0, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#31, Column#32, Column#33, Column#34, funcs:group_concat(Column#26, Column#27 separator \",\")->Column#22, funcs:max(Column#28)->Column#23, funcs:count(Column#29)->Column#24, funcs:sum(Column#30)->Column#25", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_1, cast(test.ts.id, var_string(20))->Column#27, test.ts.col_1, test.ts.id, cast(test.ts.id, decimal(14,4) BINARY)->Column#30, test.ts.col_0, test.ts.col_1, test.ts.id, test.ts.col_2", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#8, var_string(20))->Column#10, Column#9", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"GG\", 0, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'01') from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#8, var_string(20))->Column#10, Column#9", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"01\", 0, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,1) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#8, var_string(20))->Column#10, cast(Column#9, var_string(20))->Column#11", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:0, 1, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#8, Column#9 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#7, var_string(20))->Column#8, cast(Column#7, var_string(20))->Column#9", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:0, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,10) from ts group by '010'", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#17, funcs:group_concat(distinct Column#15, Column#16 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#13, var_string(20))->Column#15, cast(Column#14, var_string(20))->Column#16, Column#12", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:0, 1, 10, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,0) from ts group by '011'", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#14, funcs:group_concat(distinct Column#12, Column#13 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#11, var_string(20))->Column#12, cast(Column#11, var_string(20))->Column#13, Column#10", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#10, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:0, 1, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 0,'GG') from ts group by 'GG'", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#17, funcs:group_concat(distinct Column#15, Column#16 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] cast(Column#13, var_string(20))->Column#15, Column#14, Column#12", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:\"GG\", 0, 1, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'", + "[types:1292]Truncated incorrect DOUBLE value: 'GG'" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG','GG') from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#7, Column#7 separator \",\")->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"GG\", ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'Gg','GG') from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#8, Column#9 separator \",\")->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"GG\", \"Gg\", ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct 'GG-10','GG') from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#8, Column#9 separator \",\")->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"GG\", \"GG-10\", ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct '1200-01-01 00:00:00.023',1200) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct Column#10, Column#11 separator \",\")->Column#5", + " └─Projection 1.00 mpp[tiflash] Column#8, cast(Column#9, var_string(20))->Column#11", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:\"1200-01-01 00:00:00.023\", 1200, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", + "[types:1292]Truncated incorrect DOUBLE value: '1200-01-01 00:00:00.023'", + "[types:1292]Truncated incorrect DOUBLE value: '1200-01-01 00:00:00.023'" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0) from ts group by id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.id, funcs:group_concat(Column#9 separator \",\")->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.id, funcs:group_concat(test.ts.col_0, test.ts.col_0 separator \",\")->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(col_0, col_0,id) from ts group by id", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.id, funcs:group_concat(Column#9 separator \",\")->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:group_concat(Column#10, Column#11, Column#12 separator \",\")->Column#9", + " └─Projection 10000.00 mpp[tiflash] test.ts.col_0, test.ts.col_0, cast(test.ts.id, var_string(20))->Column#12, test.ts.id", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:group_concat(distinct test.ts.col_0 order by Column#7 separator \",\")->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#9, funcs:firstrow(Column#8)->Column#7", + " └─Projection 10000.00 mpp[tiflash] lt(test.ts.id, 10)->Column#8, test.ts.col_0", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by id<10) from ts group by col_1", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.ts.col_1, funcs:group_concat(distinct test.ts.col_0 order by Column#8 separator \",\")->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_1, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, Column#11, funcs:firstrow(Column#9)->Column#8", + " └─Projection 10000.00 mpp[tiflash] lt(test.ts.id, 10)->Column#9, test.ts.col_1, test.ts.col_0", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0>10 order by id<10) from ts group by col_1", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:group_concat(distinct Column#15 order by Column#16 separator \",\")->Column#5", + " └─Projection 8000.00 mpp[tiflash] cast(Column#10, var_string(20))->Column#15, Column#11, test.ts.col_1", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.ts.col_1, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, Column#14, funcs:firstrow(Column#12)->Column#11", + " └─Projection 10000.00 mpp[tiflash] lt(test.ts.id, 10)->Column#12, test.ts.col_1, gt(cast(test.ts.col_0, double BINARY), 10)->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ hash_agg(),agg_to_cop() */ group_concat(distinct col_0 order by col_0<=>null) from ts", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(distinct Column#6 order by Column#7 separator \",\")->Column#5", + "└─Projection 10000.00 root test.ts.col_0, nulleq(test.ts.col_0, )->Column#7", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:ts keep order:false, stats:pseudo" + ], + "Warning": [ + "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable", + "Scalar function 'nulleq'(signature: NullEQString, return type: bigint(1)) is not supported to push down to tiflash now.", + "Aggregation can not be pushed to tiflash because arguments of AggFunc `group_concat` contains unsupported exprs in order-by clause", + "Scalar function 'nulleq'(signature: NullEQString, return type: bigint(1)) is not supported to push down to tiflash now.", + "Aggregation can not be pushed to tiflash because arguments of AggFunc `group_concat` contains unsupported exprs in order-by clause" + ] + } + ] + }, + { + "Name": "TestRejectSortForMPP", + "Cases": [ + { + "SQL": "desc format = 'brief' select count(*) from (select * from t order by id)a group by name,id order by id", + "Plan": [ + "Projection 8000.00 root Column#5", + "└─Sort 8000.00 root test.t.id", + " └─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.id", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, funcs:sum(Column#7)->Column#5, funcs:firstrow(test.t.id)->test.t.id", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: utf8mb4_bin], [name: test.t.id, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, funcs:count(1)->Column#7", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*) from (select * from t order by id)a group by name order by 1", + "Plan": [ + "Sort 8000.00 root Column#5", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.name, funcs:sum(Column#8)->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.name, funcs:count(1)->Column#8", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select count(*) from (select id,name from t group by id,name order by id,name)a group by name order by 1", + "Plan": [ + "Sort 8000.00 root Column#5", + "└─TableReader 8000.00 root data:ExchangeSender", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.name, funcs:count(1)->Column#5", + " └─Projection 8000.00 mpp[tiflash] test.t.id, test.t.name", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, funcs:firstrow(test.t.id)->test.t.id, funcs:firstrow(test.t.name)->test.t.name", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: utf8mb4_bin]", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select id from t group by id order by id)a join t on a.id=t.id order by 1", + "Plan": [ + "Sort 9990.00 root test.t.id", + "└─TableReader 9990.00 root data:ExchangeSender", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.id, test.t.id, test.t.value, test.t.name", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] test.t.id", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.id, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.id, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select * from t order by id)a join t on a.id=t.id order by 1", + "Plan": [ + "Sort 12487.50 root test.t.id", + "└─TableReader 12487.50 root data:ExchangeSender", + " └─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12487.50 mpp[tiflash] test.t.id, test.t.value, test.t.name, test.t.id, test.t.value, test.t.name", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.id, test.t.id)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.id))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from ((select id from t order by 1) union all (select id+1 from t order by 1))c", + "Plan": [ + "TableReader 20000.00 root data:ExchangeSender", + "└─ExchangeSender 20000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Union 20000.00 mpp[tiflash] ", + " ├─Projection 10000.00 mpp[tiflash] cast(test.t.id, bigint(20) BINARY)->Column#10", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.id, 1)->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from ((select count(*) from (select id,name from t order by id)a group by name,id order by id) union all (select id+1 from t order by 1))c", + "Plan": [ + "TableReader 18000.00 root data:ExchangeSender", + "└─ExchangeSender 18000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Union 18000.00 mpp[tiflash] ", + " ├─Projection 8000.00 mpp[tiflash] cast(Column#12, bigint(21) BINARY)->Column#12", + " │ └─Projection 8000.00 mpp[tiflash] Column#5", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.t.id", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, funcs:sum(Column#19)->Column#5, funcs:firstrow(test.t.id)->test.t.id", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.t.name, collate: utf8mb4_bin], [name: test.t.id, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:test.t.id, test.t.name, funcs:count(1)->Column#19", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─Projection 10000.00 mpp[tiflash] cast(Column#11, bigint(21) BINARY)->Column#12", + " └─Projection 10000.00 mpp[tiflash] plus(test.t.id, 1)->Column#11", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "desc format = 'brief' select * from (select * from t order by id)a order by name", + "Plan": [ + "Sort 10000.00 root test.t.name", + "└─TableReader 10000.00 root data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestIssue32632", + "Cases": [ + { + "SQL": "explain format = 'brief' select sum(ps_supplycost) from partsupp, supplier where ps_suppkey = s_suppkey;", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#15)->Column#14", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(test.partsupp.ps_supplycost)->Column#15", + " └─Projection 12500.00 mpp[tiflash] test.partsupp.ps_supplycost", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.supplier.s_suppkey, test.partsupp.ps_suppkey)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:supplier keep order:false", + " └─TableFullScan(Probe) 800000.00 mpp[tiflash] table:partsupp keep order:false" + ] + } + ] + }, + { + "Name": "TestTiFlashPartitionTableScan", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from rp_t where a = 1 or a = 20", + "Plan": [ + "TableReader 20.00 root partition:p0,p3 data:ExchangeSender", + "└─ExchangeSender 20.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 20.00 mpp[tiflash] or(eq(test.rp_t.a, 1), eq(test.rp_t.a, 20))", + " └─TableFullScan 10000.00 mpp[tiflash] table:rp_t keep order:false, stats:pseudo, PartitionTableScan:true" + ] + }, + { + "SQL": "explain format = 'brief' select * from hp_t where a = 1 or a = 20", + "Plan": [ + "TableReader 20.00 root partition:p0,p1 data:ExchangeSender", + "└─ExchangeSender 20.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 20.00 mpp[tiflash] or(eq(test.hp_t.a, 1), eq(test.hp_t.a, 20))", + " └─TableFullScan 10000.00 mpp[tiflash] table:hp_t keep order:false, stats:pseudo, PartitionTableScan:true" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from rp_t where a = 1 or a = 20", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#5)->Column#3", + "└─TableReader 1.00 root partition:p0,p3 data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#5", + " └─Selection 20.00 mpp[tiflash] or(eq(test.rp_t.a, 1), eq(test.rp_t.a, 20))", + " └─TableFullScan 10000.00 mpp[tiflash] table:rp_t keep order:false, stats:pseudo, PartitionTableScan:true" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from hp_t where a = 1 or a = 20", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#5)->Column#3", + "└─TableReader 1.00 root partition:p0,p1 data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#5", + " └─Selection 20.00 mpp[tiflash] or(eq(test.hp_t.a, 1), eq(test.hp_t.a, 20))", + " └─TableFullScan 10000.00 mpp[tiflash] table:hp_t keep order:false, stats:pseudo, PartitionTableScan:true" + ] + } + ] } ] diff --git a/planner/core/testdata/ordered_result_mode_suite_out.json b/planner/core/testdata/ordered_result_mode_suite_out.json index 80d8b06a86fd6..2047c8542e776 100644 --- a/planner/core/testdata/ordered_result_mode_suite_out.json +++ b/planner/core/testdata/ordered_result_mode_suite_out.json @@ -401,7 +401,7 @@ "Plan": [ "Projection_8 10000.00 root Column#6", "└─Sort_9 10000.00 root test.t1.b, test.t1.a, Column#6", - " └─Window_11 10000.00 root sum(cast(test.t1.b, decimal(32,0) BINARY))->Column#6 over(partition by test.t1.a)", + " └─Window_11 10000.00 root sum(cast(test.t1.b, decimal(10,0) BINARY))->Column#6 over(partition by test.t1.a)", " └─TableReader_13 10000.00 root data:TableFullScan_12", " └─TableFullScan_12 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] @@ -417,12 +417,12 @@ }, { "Plan": [ - "Selection_8 6400.00 root lt(Column#6, 20)", - "└─Sort_9 8000.00 root Column#5, Column#6, Column#7", - " └─HashAgg_15 8000.00 root group by:test.t1.d, funcs:min(Column#11)->Column#5, funcs:max(Column#12)->Column#6, funcs:sum(Column#13)->Column#7", - " └─TableReader_16 8000.00 root data:HashAgg_11", - " └─HashAgg_11 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#11, funcs:max(test.t1.b)->Column#12, funcs:sum(test.t1.c)->Column#13", - " └─TableFullScan_14 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort_9 6400.00 root Column#5, Column#6, Column#7", + "└─Selection_11 6400.00 root lt(Column#6, 20)", + " └─HashAgg_16 8000.00 root group by:test.t1.d, funcs:min(Column#11)->Column#5, funcs:max(Column#12)->Column#6, funcs:sum(Column#13)->Column#7", + " └─TableReader_17 8000.00 root data:HashAgg_12", + " └─HashAgg_12 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#11, funcs:max(test.t1.b)->Column#12, funcs:sum(test.t1.c)->Column#13", + " └─TableFullScan_15 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { diff --git a/planner/core/testdata/partition_pruner_out.json b/planner/core/testdata/partition_pruner_out.json index 7977fc780453d..db74202a1459b 100644 --- a/planner/core/testdata/partition_pruner_out.json +++ b/planner/core/testdata/partition_pruner_out.json @@ -1485,10 +1485,10 @@ "SQL": "select * from t1 where a in (1,6) and (a=3 and b =3)", "Result": null, "Plan": [ - "TableDual 8000.00 root rows:0" + "TableDual 0.00 root rows:0" ], "IndexPlan": [ - "TableDual 8000.00 root rows:0" + "TableDual 0.00 root rows:0" ] }, { @@ -2488,10 +2488,10 @@ "SQL": "select * from t1 where a in (1,6) and (a=3 and b =3)", "Result": null, "Plan": [ - "TableDual 8000.00 root rows:0" + "TableDual 0.00 root rows:0" ], "IndexPlan": [ - "TableDual 8000.00 root rows:0" + "TableDual 0.00 root rows:0" ] }, { diff --git a/planner/core/testdata/plan_normalized_suite_out.json b/planner/core/testdata/plan_normalized_suite_out.json index 8c656d9b60b40..ec97aea6b15b6 100644 --- a/planner/core/testdata/plan_normalized_suite_out.json +++ b/planner/core/testdata/plan_normalized_suite_out.json @@ -47,7 +47,7 @@ "SQL": "select a+1,b+2 from t1 use index(b) where b=3", "Plan": [ " Projection root plus(test.t1.a, ?), plus(test.t1.b, ?)", - " └─IndexReader root index:IndexRangeScan_5", + " └─IndexReader root index:IndexRangeScan", " └─IndexRangeScan cop table:t1, index:b(b), range:[?,?], keep order:false" ] }, diff --git a/planner/core/testdata/plan_suite_in.json b/planner/core/testdata/plan_suite_in.json index 09233f05dd121..ce4c38cbc695d 100644 --- a/planner/core/testdata/plan_suite_in.json +++ b/planner/core/testdata/plan_suite_in.json @@ -746,5 +746,42 @@ "cases": [ "select * from t where t.a < 3 and t.a < 3" ] + }, + { + "name": "TestMPPSinglePartitionType", + "cases": [ + // test normal aggregation, MPP2Phase. + "select count(*) from employee group by deptid+1", + // test normal aggregation, MPPScalar. + "select count(distinct deptid) a from employee", + // test normal join, Broadcast. + "select * from employee join employee e1 using(deptid)", + // test redundant collect exchange can be eliminated. + "select count(distinct a) from (select count(distinct deptid) a from employee) x", + // test mppScalar agg below mpp2Phase agg. + "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b+1", + // test mppScalar agg below mpp1Phase agg, TODO: add hint to enforce + // test mppScalar agg below mppTiDB agg, TODO: add hint to enforce + "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b", + // test mppScalar agg below join + "select * from employee join (select count(distinct deptid) a, count(distinct empid) b from employee) e1", + "select * from employee e1 join (select count(distinct deptid) a from employee) e2 on e1.deptid = e2.a", + "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + // test mpp2Phase agg below join + "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d", + // non-broadcast join + "set tidb_broadcast_join_threshold_count=1", + "set tidb_broadcast_join_threshold_size=1", + "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d" + ] } ] diff --git a/planner/core/testdata/plan_suite_out.json b/planner/core/testdata/plan_suite_out.json index 75db6cb736e99..95fc30592645e 100644 --- a/planner/core/testdata/plan_suite_out.json +++ b/planner/core/testdata/plan_suite_out.json @@ -286,9 +286,9 @@ }, { "SQL": "select /*+ USE_INDEX_MERGE(t1, c_d_e, f_g) */ * from t where c < 1 or f > 2", - "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f)[(2,+inf]]], TablePlan->Table(t))", "HasWarn": true, - "Hints": "use_index(@`sel_1` `test`.`t` )" + "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f`)" }, { "SQL": "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2", @@ -304,15 +304,15 @@ }, { "SQL": "select /*+ USE_INDEX_MERGE(db2.t) */ * from t where c < 1 or f > 2", - "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f)[(2,+inf]]], TablePlan->Table(t))", "HasWarn": true, - "Hints": "use_index(@`sel_1` `test`.`t` )" + "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f`)" }, { "SQL": "select /*+ USE_INDEX_MERGE(db2.t, c_d_e, f_g) */ * from t where c < 1 or f > 2", - "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f)[(2,+inf]]], TablePlan->Table(t))", "HasWarn": true, - "Hints": "use_index(@`sel_1` `test`.`t` )" + "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f`)" } ] }, @@ -566,7 +566,7 @@ }, { "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t2.a = t3.a", - "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)" + "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Sort->TableReader(Table(t))}(test.t.a,test.t.a)" }, { "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t1.a = t3.a", @@ -1075,11 +1075,11 @@ }, { "SQL": "select a from t where c_str not like 'abc'", - "Best": "IndexReader(Index(t.c_d_e_str)[[-inf,\"abc\") (\"abc\",+inf]])->Projection" + "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([not(like(test.t.c_str, abc, 92))]))->Projection" }, { "SQL": "select a from t where not (c_str like 'abc' or c_str like 'abd')", - "Best": "IndexReader(Index(t.c_d_e_str)[[-inf,\"abc\") (\"abc\",\"abd\") (\"abd\",+inf]])->Projection" + "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([and(not(like(test.t.c_str, abc, 92)), not(like(test.t.c_str, abd, 92)))]))->Projection" }, { "SQL": "select a from t where c_str like '_abc'", @@ -1705,7 +1705,7 @@ "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;", "Plan": [ "HashAgg 1.00 root funcs:sum(distinct Column#9)->Column#4", - "└─Projection 16000.00 root cast(test.pt.b, decimal(32,0) BINARY)->Column#9", + "└─Projection 16000.00 root cast(test.pt.b, decimal(10,0) BINARY)->Column#9", " └─PartitionUnion 16000.00 root ", " ├─HashAgg 8000.00 root group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b", " │ └─TableReader 8000.00 root data:HashAgg", @@ -1788,7 +1788,7 @@ "Plan": [ "Projection 8000.00 root Column#5, test.t.c, Column#5, Column#6, Column#7, Column#8, Column#9", "└─HashAgg 8000.00 root group by:Column#17, funcs:avg(Column#10)->Column#5, funcs:count(distinct Column#11, Column#12)->Column#6, funcs:count(distinct Column#13)->Column#7, funcs:count(distinct Column#14)->Column#8, funcs:sum(Column#15)->Column#9, funcs:firstrow(Column#16)->test.t.c", - " └─Projection 10000.00 root cast(test.t.b, decimal(15,4) BINARY)->Column#10, test.t.a, test.t.b, test.t.a, test.t.c, cast(test.t.b, decimal(32,0) BINARY)->Column#15, test.t.c, test.t.c", + " └─Projection 10000.00 root cast(test.t.b, decimal(15,4) BINARY)->Column#10, test.t.a, test.t.b, test.t.a, test.t.c, cast(test.t.b, decimal(10,0) BINARY)->Column#15, test.t.c, test.t.c", " └─TableReader 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], @@ -1850,7 +1850,7 @@ "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;", "Plan": [ "HashAgg 1.00 root funcs:sum(distinct Column#9)->Column#4", - "└─Projection 16000.00 root cast(test.pt.b, decimal(32,0) BINARY)->Column#9", + "└─Projection 16000.00 root cast(test.pt.b, decimal(10,0) BINARY)->Column#9", " └─PartitionUnion 16000.00 root ", " ├─HashAgg 8000.00 root group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b", " │ └─TableReader 8000.00 root data:HashAgg", @@ -1892,7 +1892,7 @@ "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;", "Plan": [ "HashAgg 1.00 root funcs:sum(distinct Column#9)->Column#4", - "└─Projection 16000.00 root cast(test.pt.b, decimal(32,0) BINARY)->Column#9", + "└─Projection 16000.00 root cast(test.pt.b, decimal(10,0) BINARY)->Column#9", " └─PartitionUnion 16000.00 root ", " ├─HashAgg 8000.00 root group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b", " │ └─TableReader 8000.00 root data:HashAgg", @@ -2677,5 +2677,406 @@ ] } ] + }, + { + "Name": "TestMPPSinglePartitionType", + "Cases": [ + { + "SQL": "select count(*) from employee group by deptid+1", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#12, funcs:sum(Column#13)->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#14, funcs:count(1)->Column#13", + " └─Projection 10000.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(distinct deptid) a from employee", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee join employee e1 using(deptid)", + "Plan": [ + "TableReader 12487.50 root data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12487.50 mpp[tiflash] test.employee.deptid, test.employee.empid, test.employee.salary, test.employee.empid, test.employee.salary", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(distinct a) from (select count(distinct deptid) a from employee) x", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct Column#5)->Column#6", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b+1", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#7", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#12, funcs:sum(Column#13)->Column#7", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#15, funcs:count(Column#14)->Column#13", + " └─Projection 1.00 mpp[tiflash] Column#5, plus(Column#6, 1)->Column#15", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#7", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#6, funcs:count(Column#5)->Column#7", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee join (select count(distinct deptid) a, count(distinct empid) b from employee) e1", + "Plan": [ + "TableReader 10000.00 root data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN inner join", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 1.00 mpp[tiflash] Column#9, Column#10", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#9, funcs:count(distinct test.employee.empid)->Column#10", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select count(distinct deptid) a from employee) e2 on e1.deptid = e2.a", + "Plan": [ + "TableReader 1.25 root data:ExchangeSender", + "└─ExchangeSender 1.25 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 1.25 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#9)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 1.00 mpp[tiflash] Column#9", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#9", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "Plan": [ + "TableReader 1.25 root data:ExchangeSender", + "└─ExchangeSender 1.25 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.25 mpp[tiflash] Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─HashJoin 1.25 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#5)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + "Plan": [ + "TableReader 1.00 root data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 1.00 mpp[tiflash] inner join, equal:[eq(Column#5, Column#10)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Projection(Probe) 1.00 mpp[tiflash] Column#10", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#10", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "Plan": [ + "TableReader 12487.50 root data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#6)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#27", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#10)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#10, Column#9", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#9, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#27", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d", + "Plan": [ + "TableReader 6400.00 root data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6400.00 mpp[tiflash] inner join, equal:[eq(Column#6, Column#12)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#43", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Projection(Probe) 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#12, Column#11", + " └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " └─Projection 8000.00 mpp[tiflash] Column#11, test.employee.deptid", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#20, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22", + " └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#46", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "set tidb_broadcast_join_threshold_count=1", + "Plan": null + }, + { + "SQL": "set tidb_broadcast_join_threshold_size=1", + "Plan": null + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "Plan": [ + "Projection 1.25 root Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + "└─HashJoin 1.25 root inner join, equal:[eq(test.employee.deptid, Column#5)]", + " ├─TableReader(Build) 1.00 root data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 cop[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + "Plan": [ + "HashJoin 1.00 root inner join, equal:[eq(Column#5, Column#10)]", + "├─TableReader(Build) 1.00 root data:ExchangeSender", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─Projection 1.00 mpp[tiflash] Column#10", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#10", + "│ └─ExchangeReceiver 1.00 mpp[tiflash] ", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + "└─TableReader(Probe) 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "Plan": [ + "TableReader 12487.50 root data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#6)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#6, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#29", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#26, collate: binary]", + " └─Projection 9990.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "Plan": [ + "TableReader 8000.00 root data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, Column#10, Column#9", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#10)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#10, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#10, Column#9", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#9, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#29", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#26, collate: binary]", + " └─Projection 9990.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d", + "Plan": [ + "TableReader 6400.00 root data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6400.00 mpp[tiflash] inner join, equal:[eq(Column#6, Column#12)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#6, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#43", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 6400.00 mpp[tiflash] ", + " └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]", + " └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#12, Column#11", + " └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " └─Projection 8000.00 mpp[tiflash] Column#11, test.employee.deptid", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: Column#20, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22", + " └─Projection 10000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#46", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + } + ] } ] diff --git a/planner/core/testdata/plan_suite_unexported_in.json b/planner/core/testdata/plan_suite_unexported_in.json index f32d4d4ab8123..98c7b9b9b5985 100644 --- a/planner/core/testdata/plan_suite_unexported_in.json +++ b/planner/core/testdata/plan_suite_unexported_in.json @@ -131,7 +131,8 @@ "select t1.b from t t1 where t1.b in (select t2.b from t t2 where t2.a = t1.a order by t2.a)", "select t1.b from t t1 where exists(select t2.b from t t2 where t2.a = t1.a order by t2.a)", // `Sort` will not be eliminated, if it is not the top level operator. - "select t1.b from t t1 where t1.b = (select t2.b from t t2 where t2.a = t1.a order by t2.a limit 1)" + "select t1.b from t t1 where t1.b = (select t2.b from t t2 where t2.a = t1.a order by t2.a limit 1)", + "select (select 1 from t t1 where t1.a = t2.a) from t t2" ] }, { @@ -556,7 +557,9 @@ "select * from t t1 left join t t2 on t1.b = t2.b where not (t1.c > 1 or t2.c > 1);", "select * from t t1 left join t t2 on t1.b = t2.b where not (t1.c > 1 and t2.c > 1);", "select * from t t1 left join t t2 on t1.b > 1 where t1.c = t2.c;", - "select * from t t1 left join t t2 on true where t1.b <=> t2.b;" + "select * from t t1 left join t t2 on true where t1.b <=> t2.b;", + "select * from t t1 left join t t2 on t1.b = t2.b where not(0+(t1.c=1 and t2.c=2));", + "select * from t t1 left join t t2 on t1.b = t2.b where not(t1.c) and not(t2.c)" ] }, { diff --git a/planner/core/testdata/plan_suite_unexported_out.json b/planner/core/testdata/plan_suite_unexported_out.json index 6401df6aa9264..218880d0aa713 100644 --- a/planner/core/testdata/plan_suite_unexported_out.json +++ b/planner/core/testdata/plan_suite_unexported_out.json @@ -3,7 +3,7 @@ "Name": "TestEagerAggregation", "Cases": [ "DataScan(t)->Aggr(sum(test.t.a),sum(plus(test.t.a, 1)),count(test.t.a))->Projection", - "DataScan(t)->Aggr(sum(plus(test.t.a, test.t.b)),sum(plus(test.t.a, test.t.c)),count(test.t.a))->Projection->Sel([gt(Column#13, 0)])->Sort->Projection", + "DataScan(t)->Aggr(sum(plus(test.t.a, test.t.b)),sum(plus(test.t.a, test.t.c)),count(test.t.a))->Sel([gt(Column#13, 0)])->Projection->Sort->Projection", "Join{DataScan(a)->Aggr(sum(test.t.a),firstrow(test.t.c))->DataScan(b)}(test.t.c,test.t.c)->Aggr(sum(Column#26))->Projection", "Join{DataScan(a)->DataScan(b)->Aggr(sum(test.t.a),firstrow(test.t.c))}(test.t.c,test.t.c)->Aggr(sum(Column#26))->Projection", "Join{DataScan(a)->DataScan(b)->Aggr(sum(test.t.a),firstrow(test.t.c))}(test.t.c,test.t.c)->Aggr(sum(Column#26),firstrow(test.t.a))->Projection", @@ -89,11 +89,11 @@ "DataScan(t)->Aggr(sum(test.t.b),firstrow(test.t.a))->Sel([gt(cast(test.t.a, decimal(20,0) BINARY), Column#13)])->Projection->Projection", "DataScan(t)->Aggr(sum(test.t.b),firstrow(test.t.a))->Sel([gt(test.t.a, 1)])->Projection->Projection", "Dual->Sel([gt(test.t.a, 1)])->Projection", - "DataScan(t)->Aggr(count(test.t.a),firstrow(test.t.a))->Projection->Sel([lt(Column#13, 1)])", + "DataScan(t)->Aggr(count(test.t.a),firstrow(test.t.a))->Sel([lt(Column#13, 1)])->Projection", "Join{DataScan(t1)->DataScan(t2)}(test.t.a,test.t.a)->Projection", "Dual->Projection", "DataScan(t)->Projection->Projection->Window(min(test.t.a)->Column#14)->Sel([lt(test.t.a, 10) eq(test.t.b, Column#14)])->Projection->Projection", - "DataScan(t)->Projection->Projection->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14)->Sel([gt(Column#14, cast(test.t.b, decimal(20,0) BINARY))])->Projection->Projection" + "DataScan(t)->Projection->Projection->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14)->Sel([gt(Column#14, cast(test.t.b, decimal(20,0) BINARY))])->Projection->Projection" ] }, { @@ -117,7 +117,8 @@ "Join{DataScan(t1)->DataScan(t2)->Aggr(max(test.t.a),firstrow(test.t.b))}(test.t.b,test.t.b)->Projection->Sel([eq(test.t.b, Column#25)])->Projection", "Join{DataScan(t1)->DataScan(t2)}(test.t.a,test.t.a)(test.t.b,test.t.b)->Projection", "Join{DataScan(t1)->DataScan(t2)}(test.t.a,test.t.a)->Projection", - "Apply{DataScan(t1)->DataScan(t2)->Sel([eq(test.t.a, test.t.a)])->Projection->Sort->Limit}->Projection->Sel([eq(test.t.b, test.t.b)])->Projection" + "Apply{DataScan(t1)->DataScan(t2)->Sel([eq(test.t.a, test.t.a)])->Projection->Sort->Limit}->Projection->Sel([eq(test.t.b, test.t.b)])->Projection", + "Apply{DataScan(t2)->DataScan(t1)->Sel([eq(test.t.a, test.t.a)])->Projection}->Projection" ] }, { @@ -189,12 +190,12 @@ "TableReader(Table(t))->Sort->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(order by test.t.a, test.t.b desc range between unbounded preceding and current row))->Projection", "TableReader(Table(t))->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.a))->Projection", "[planner:1054]Unknown column 'z' in 'field list'", - "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#14 over())->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#14 over())->Sort->Projection", "IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg->Window(sum(Column#13)->Column#15 over())->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over())->Sort->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over())->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", "TableReader(Table(t)->StreamAgg)->StreamAgg->Window(sum(Column#13)->Column#15 over())->Sort->Projection", - "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)]))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#38 over())->MaxOneRow}->Sel([Column#38])->Projection", + "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)]))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#38 over())->MaxOneRow->Sel([Column#38])}->Projection", "[planner:3594]You cannot use the alias 'w' of an expression containing a window function in this context.'", "[planner:1247]Reference 'sum_a' not supported (reference to window function)", "[planner:3579]Window name 'w2' is not defined.", @@ -203,11 +204,11 @@ "[planner:3581]A window which depends on another cannot define partitioning.", "[planner:3581]A window which depends on another cannot define partitioning.", "[planner:3582]Window 'w' has a frame definition, so cannot be referenced by another window.", - "IndexReader(Index(t.f)[[NULL,+inf]])->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(rows between 1 preceding and 1 following))->Projection", + "IndexReader(Index(t.f)[[NULL,+inf]])->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(rows between 1 preceding and 1 following))->Projection", "[planner:3583]Window '' cannot inherit 'w' since both contain an ORDER BY clause.", "[planner:3591]Window 'w1' is defined twice.", "TableReader(Table(t))->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.a))->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", "[planner:1235]This version of TiDB doesn't yet support 'GROUPS'", "[planner:3584]Window '': frame start cannot be UNBOUNDED FOLLOWING.", "[planner:3585]Window '': frame end cannot be UNBOUNDED PRECEDING.", @@ -219,7 +220,7 @@ "[planner:3590]Window '' has a non-constant frame bound.", "[planner:3586]Window '': frame start or end is negative, NULL or of non-integral type", "[planner:3588]Window '' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(order by test.t.a range between 1.0 preceding and 1 following))->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(order by test.t.a range between 1.0 preceding and 1 following))->Projection", "IndexReader(Index(t.f)[[NULL,+inf]])->Window(row_number()->Column#14 over())->Projection", "TableReader(Table(t))->HashAgg->Window(max(Column#13)->Column#15 over(rows between 1 preceding and 1 following))->Projection", "[planner:1210]Incorrect arguments to nth_value", @@ -229,11 +230,11 @@ "IndexReader(Index(t.f)[[NULL,+inf]])->Window(ntile()->Column#14 over())->Projection", "TableReader(Table(t))->Sort->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.b))->Projection", "TableReader(Table(t))->Window(nth_value(test.t.i_date, 1)->Column#14 over())->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#15, sum(cast(test.t.c, decimal(65,0) BINARY))->Column#16 over(order by test.t.a range between unbounded preceding and current row))->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#15, sum(cast(test.t.c, decimal(10,0) BINARY))->Column#16 over(order by test.t.a range between unbounded preceding and current row))->Projection", "[planner:3593]You cannot use the window function 'sum' in this context.'", "[planner:3593]You cannot use the window function 'sum' in this context.'", "[planner:3593]You cannot use the window function 'row_number' in this context.'", - "TableReader(Table(t))->Sort->Window(sum(cast(test.t.c, decimal(65,0) BINARY))->Column#17 over(partition by test.t.a order by test.t.c range between unbounded preceding and current row))->Sort->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#18 over(order by test.t.a, test.t.b, test.t.c range between unbounded preceding and current row))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#19 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row))->Window(sum(cast(test.t.d, decimal(65,0) BINARY))->Column#20 over())->Projection", + "TableReader(Table(t))->Sort->Window(sum(cast(test.t.c, decimal(10,0) BINARY))->Column#17 over(partition by test.t.a order by test.t.c range between unbounded preceding and current row))->Sort->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#18 over(order by test.t.a, test.t.b, test.t.c range between unbounded preceding and current row))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#19 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row))->Window(sum(cast(test.t.d, decimal(10,0) BINARY))->Column#20 over())->Projection", "[planner:3587]Window 'w1' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type", "TableReader(Table(t))->Sort->Window(dense_rank()->Column#14 over(partition by test.t.b order by test.t.a desc, test.t.b desc))->Projection", "[planner:3587]Window 'w1' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type", @@ -262,12 +263,12 @@ "TableReader(Table(t))->Sort->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(order by test.t.a, test.t.b desc range between unbounded preceding and current row))->Projection", "TableReader(Table(t))->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.a))->Projection", "[planner:1054]Unknown column 'z' in 'field list'", - "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#14 over())->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#14 over())->Sort->Projection", "IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg->Window(sum(Column#13)->Column#15 over())->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over())->Sort->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over())->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", "TableReader(Table(t)->StreamAgg)->StreamAgg->Window(sum(Column#13)->Column#15 over())->Sort->Projection", - "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)]))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#38 over())->MaxOneRow}->Sel([Column#38])->Projection", + "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)]))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#38 over())->MaxOneRow->Sel([Column#38])}->Projection", "[planner:3594]You cannot use the alias 'w' of an expression containing a window function in this context.'", "[planner:1247]Reference 'sum_a' not supported (reference to window function)", "[planner:3579]Window name 'w2' is not defined.", @@ -276,11 +277,11 @@ "[planner:3581]A window which depends on another cannot define partitioning.", "[planner:3581]A window which depends on another cannot define partitioning.", "[planner:3582]Window 'w' has a frame definition, so cannot be referenced by another window.", - "IndexReader(Index(t.f)[[NULL,+inf]])->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(rows between 1 preceding and 1 following))->Projection", + "IndexReader(Index(t.f)[[NULL,+inf]])->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(rows between 1 preceding and 1 following))->Projection", "[planner:3583]Window '' cannot inherit 'w' since both contain an ORDER BY clause.", "[planner:3591]Window 'w1' is defined twice.", "TableReader(Table(t))->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.a))->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(partition by test.t.a))->Sort->Projection", "[planner:1235]This version of TiDB doesn't yet support 'GROUPS'", "[planner:3584]Window '': frame start cannot be UNBOUNDED FOLLOWING.", "[planner:3585]Window '': frame end cannot be UNBOUNDED PRECEDING.", @@ -292,7 +293,7 @@ "[planner:3590]Window '' has a non-constant frame bound.", "[planner:3586]Window '': frame start or end is negative, NULL or of non-integral type", "[planner:3588]Window '' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.", - "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#14 over(order by test.t.a range between 1.0 preceding and 1 following))->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#14 over(order by test.t.a range between 1.0 preceding and 1 following))->Projection", "IndexReader(Index(t.f)[[NULL,+inf]])->Window(row_number()->Column#14 over())->Projection", "TableReader(Table(t))->HashAgg->Window(max(Column#13)->Column#15 over(rows between 1 preceding and 1 following))->Projection", "[planner:1210]Incorrect arguments to nth_value", @@ -302,11 +303,11 @@ "IndexReader(Index(t.f)[[NULL,+inf]])->Window(ntile()->Column#14 over())->Projection", "TableReader(Table(t))->Sort->Window(avg(cast(test.t.a, decimal(15,4) BINARY))->Column#14 over(partition by test.t.b))->Partition(execution info: concurrency:4, data sources:[TableReader_10])->Projection", "TableReader(Table(t))->Window(nth_value(test.t.i_date, 1)->Column#14 over())->Projection", - "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#15, sum(cast(test.t.c, decimal(65,0) BINARY))->Column#16 over(order by test.t.a range between unbounded preceding and current row))->Projection", + "TableReader(Table(t))->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#15, sum(cast(test.t.c, decimal(10,0) BINARY))->Column#16 over(order by test.t.a range between unbounded preceding and current row))->Projection", "[planner:3593]You cannot use the window function 'sum' in this context.'", "[planner:3593]You cannot use the window function 'sum' in this context.'", "[planner:3593]You cannot use the window function 'row_number' in this context.'", - "TableReader(Table(t))->Sort->Window(sum(cast(test.t.c, decimal(65,0) BINARY))->Column#17 over(partition by test.t.a order by test.t.c range between unbounded preceding and current row))->Sort->Window(sum(cast(test.t.b, decimal(65,0) BINARY))->Column#18 over(order by test.t.a, test.t.b, test.t.c range between unbounded preceding and current row))->Window(sum(cast(test.t.a, decimal(65,0) BINARY))->Column#19 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row))->Window(sum(cast(test.t.d, decimal(65,0) BINARY))->Column#20 over())->Projection", + "TableReader(Table(t))->Sort->Window(sum(cast(test.t.c, decimal(10,0) BINARY))->Column#17 over(partition by test.t.a order by test.t.c range between unbounded preceding and current row))->Sort->Window(sum(cast(test.t.b, decimal(10,0) BINARY))->Column#18 over(order by test.t.a, test.t.b, test.t.c range between unbounded preceding and current row))->Window(sum(cast(test.t.a, decimal(10,0) BINARY))->Column#19 over(partition by test.t.a order by test.t.b range between unbounded preceding and current row))->Window(sum(cast(test.t.d, decimal(10,0) BINARY))->Column#20 over())->Projection", "[planner:3587]Window 'w1' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type", "TableReader(Table(t))->Sort->Window(dense_rank()->Column#14 over(partition by test.t.b order by test.t.a desc, test.t.b desc))->Partition(execution info: concurrency:4, data sources:[TableReader_9])->Projection", "[planner:3587]Window 'w1' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type", @@ -482,12 +483,12 @@ "test.t.f" ] ], - "4": [ + "5": [ [ "test.t.f" ] ], - "5": [ + "6": [ [ "test.t.f" ] @@ -991,6 +992,14 @@ { "Best": "Join{DataScan(t1)->DataScan(t2)}->Sel([nulleq(test.t.b, test.t.b)])->Projection", "JoinType": "left outer join" + }, + { + "Best": "Join{DataScan(t1)->DataScan(t2)}(test.t.b,test.t.b)->Sel([not(plus(0, and(eq(test.t.c, 1), eq(test.t.c, 2))))])->Projection", + "JoinType": "left outer join" + }, + { + "Best": "Join{DataScan(t1)->DataScan(t2)}(test.t.b,test.t.b)->Projection", + "JoinType": "inner join" } ] }, diff --git a/planner/core/testdata/point_get_plan_out.json b/planner/core/testdata/point_get_plan_out.json index 9f9ac9e27deb9..f90f5bed3d6a0 100644 --- a/planner/core/testdata/point_get_plan_out.json +++ b/planner/core/testdata/point_get_plan_out.json @@ -191,9 +191,7 @@ { "SQL": "select * from t5 where id in ('0')", "Plan": [ - "Selection 8000.00 root eq(test.t5.id, 0)", - "└─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + "Point_Get 1.00 root table:t5, clustered index:PRIMARY(id) " ], "Res": null } diff --git a/planner/core/testdata/stats_suite_out.json b/planner/core/testdata/stats_suite_out.json index f7e40ddcc0e61..26f0f2fe5a193 100644 --- a/planner/core/testdata/stats_suite_out.json +++ b/planner/core/testdata/stats_suite_out.json @@ -24,7 +24,7 @@ }, { "SQL": "select count(1) from t1 where cos(a) > 0 group by a, b", - "AggInput": "[]", + "AggInput": "[{[1 2] 3.2}]", "JoinInput": "" }, { @@ -275,7 +275,7 @@ "SQL": "select count(tmp.a_sum) from (select t1.a as a, t1.b as b, sum(a) over() as a_sum from t1) tmp group by tmp.a, tmp.b", "Plan": [ "HashAgg 4.00 root group by:test.t1.a, test.t1.b, funcs:count(Column#5)->Column#6", - "└─Window 4.00 root sum(cast(test.t1.a, decimal(32,0) BINARY))->Column#5 over()", + "└─Window 4.00 root sum(cast(test.t1.a, decimal(10,0) BINARY))->Column#5 over()", " └─TableReader 4.00 root data:TableFullScan", " └─TableFullScan 4.00 cop[tikv] table:t1 keep order:false" ] diff --git a/planner/core/util.go b/planner/core/util.go index 480c4bdfabd0c..d37c190129a23 100644 --- a/planner/core/util.go +++ b/planner/core/util.go @@ -128,13 +128,16 @@ func (s *logicalSchemaProducer) setSchemaAndNames(schema *expression.Schema, nam } // inlineProjection prunes unneeded columns inline a executor. -func (s *logicalSchemaProducer) inlineProjection(parentUsedCols []*expression.Column) { +func (s *logicalSchemaProducer) inlineProjection(parentUsedCols []*expression.Column, opt *logicalOptimizeOp) { + prunedColumns := make([]*expression.Column, 0) used := expression.GetUsedList(parentUsedCols, s.Schema()) for i := len(used) - 1; i >= 0; i-- { if !used[i] { + prunedColumns = append(prunedColumns, s.Schema().Columns[i]) s.schema.Columns = append(s.Schema().Columns[:i], s.Schema().Columns[i+1:]...) } } + appendColumnPruneTraceStep(s.self, prunedColumns, opt) } // physicalSchemaProducer stores the schema for the physical plans who can produce schema directly. @@ -295,6 +298,15 @@ func extractStringFromStringSet(set set.StringSet) string { return strings.Join(l, ",") } +// extractStringFromStringSlice helps extract string info from []string. +func extractStringFromStringSlice(ss []string) string { + if len(ss) < 1 { + return "" + } + sort.Strings(ss) + return strings.Join(ss, ",") +} + // extractStringFromUint64Slice helps extract string info from uint64 slice. func extractStringFromUint64Slice(slice []uint64) string { if len(slice) < 1 { diff --git a/planner/funcdep/extract_fd_test.go b/planner/funcdep/extract_fd_test.go new file mode 100644 index 0000000000000..eefabff9bd6a2 --- /dev/null +++ b/planner/funcdep/extract_fd_test.go @@ -0,0 +1,332 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep_test + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/parser" + plannercore "github.com/pingcap/tidb/planner/core" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/hint" +) + +func testGetIS(t *testing.T, ctx sessionctx.Context) infoschema.InfoSchema { + dom := domain.GetDomain(ctx) + // Make sure the table schema is the new schema. + err := dom.Reload() + require.NoError(t, err) + return dom.InfoSchema() +} + +func TestFDSet_ExtractFD(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + par := parser.New() + par.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set sql_mode = ''") + tk.MustExec("set @@session.tidb_enable_new_only_full_group_by_check = 'on';") + tk.MustExec("create table t1(a int key, b int, c int, unique(b,c))") + tk.MustExec("create table t2(m int key, n int, p int, unique(m,n))") + tk.MustExec("create table x1(a int not null primary key, b int not null, c int default null, d int not null, unique key I_b_c (b,c), unique key I_b_d (b,d))") + tk.MustExec("create table x2(a int not null primary key, b int not null, c int default null, d int not null, unique key I_b_c (b,c), unique key I_b_d (b,d))") + + tests := []struct { + sql string + best string + fd string + }{ + { + sql: "select a from t1", + best: "DataScan(t1)->Projection", + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {}", + }, + { + sql: "select a,b from t1", + best: "DataScan(t1)->Projection", + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(1)-->(2)}", + }, + { + sql: "select a,c,b+1 from t1", + best: "DataScan(t1)->Projection", + // 4 is the extended column from (b+1) determined by b, also determined by a. + // since b is also projected in the b+1, so 2 is kept. + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(1)-->(2,3), (2,3)~~>(1), (2)-->(4)}", + }, + { + sql: "select a,b+1,c+b from t1", + best: "DataScan(t1)->Projection", + // 4, 5 is the extended column from (b+1),(c+b) determined by b,c, also determined by a. + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(1)-->(2,3), (2,3)~~>(1), (2)-->(4), (2,3)-->(5)}", + }, + { + sql: "select a,a+b,1 from t1", + best: "DataScan(t1)->Projection", + // 4 is the extended column from (b+1) determined by b, also determined by a. + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(1)-->(2,4), ()-->(5)}", + }, + { + sql: "select b+1, sum(a) from t1 group by(b)", + // The final ones are b -> (b+1), b -> sum(a) + best: "DataScan(t1)->Aggr(sum(test.t1.a),firstrow(test.t1.b))->Projection", + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(2)-->(4)} >>> {(2)-->(4,5)}", + }, + { + sql: "select b+1, b, sum(a) from t1 group by(b)", + // The final ones are b -> (b+1), b -> sum(a) + best: "DataScan(t1)->Aggr(sum(test.t1.a),firstrow(test.t1.b))->Projection", + fd: "{(1)-->(2,3), (2,3)~~>(1)} >>> {(2)-->(4)} >>> {(2)-->(4,5)}", + }, + // test for table x1 and x2 + { + sql: "select a from x1 group by a,b,c", + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {}", + }, + { + sql: "select b from x1 group by b", + best: "DataScan(x1)->Aggr(firstrow(test.x1.b))->Projection", + // b --> b is natural existed, so it won't exist in fd. + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {}", + }, + { + sql: "select b as e from x1 group by b", + best: "DataScan(x1)->Aggr(firstrow(test.x1.b))->Projection", + // b --> b is naturally existed, so it won't exist in fd. + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {}", + }, + { + sql: "select b+c from x1 group by b+c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.b),firstrow(test.x1.c))->Projection", + // avoid allocating unique ID 7 from fd temporarily, and substituted by unique ID 5 + // attention: + // b+c is an expr assigned with new plan ID when building upper-layer projection. + // when extracting FD after build phase is done, we should be able to recognize a+b in lower-layer group by item with the same unique ID. + // that's why we introduce session variable MapHashCode2UniqueID4ExtendedCol in. + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)-->(5)} >>> {(2,3)-->(5)}", + }, + { + sql: "select b+c, min(a) from x1 group by b+c, b-c", + best: "DataScan(x1)->Aggr(min(test.x1.a),firstrow(test.x1.b),firstrow(test.x1.c))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)-->(6,8), (6,8)-->(5)} >>> {(2,3)-->(6,8), (6,8)-->(5)}", + }, + { + sql: "select b+c, min(a) from x1 group by b, c", + best: "DataScan(x1)->Aggr(min(test.x1.a),firstrow(test.x1.b),firstrow(test.x1.c))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)-->(5)} >>> {(2,3)-->(5,6)}", + }, + { + sql: "select b+c from x1 group by b,c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.b),firstrow(test.x1.c))->Projection", + // b --> b is naturally existed, so it won't exist in fd. + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {(2,3)-->(5)}", + }, + { + sql: "select case b when 1 then c when 2 then d else d end from x1 group by b,c,d", + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)~~>(4), (2,4)-->(3,5)}", + }, + { + // scalar sub query will be substituted with constant datum. + sql: "select c > (select b from x1) from x1 group by c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.c))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {(3)-->(15)}", + }, + { + sql: "select exists (select * from x1) from x1 group by d", + best: "DataScan(x1)->Aggr(firstrow(1))->Projection", + // 14 is added in the logicAgg pruning process cause all the columns of agg has been pruned. + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {()-->(13)}", + }, + { + sql: "select c is null from x1 group by c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.c))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {(3)-->(5)}", + }, + { + sql: "select c is true from x1 group by c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.c))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {(3)-->(5)}", + }, + { + sql: "select (c+b)*d from x1 group by c,b,d", + // agg elimination. + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)~~>(4), (2,4)-->(3,5)}", + }, + { + sql: "select b in (c,d) from x1 group by b,c,d", + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(2,3)~~>(4), (2,4)-->(3,5)}", + }, + { + sql: "select b like '%a' from x1 group by b", + best: "DataScan(x1)->Aggr(firstrow(test.x1.b))->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {} >>> {(2)-->(5)}", + }, + // test functional dependency on primary key + { + sql: "select * from x1 group by a", + // agg eliminated by primary key. + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)}", + }, + // test functional dependency on unique key with not null + { + sql: "select * from x1 group by b,d", + best: "DataScan(x1)->Projection", + fd: "{(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)} >>> {(1)-->(2-4), (2,3)~~>(1,4), (2,4)-->(1,3)}", + }, + // test functional dependency derived from keys in where condition + { + sql: "select * from x1 where c = d group by b, c", + best: "DataScan(x1)->Aggr(firstrow(test.x1.a),firstrow(test.x1.b),firstrow(test.x1.c),firstrow(test.x1.d))->Projection", + // c = d derives: + // 1: c and d are not null, make lax FD (2,3)~~>(1,4) to be strict one. + // 2: c and d are equivalent. + fd: "{(1)-->(2-4), (2,3)-->(1,4), (2,4)-->(1,3), (3,4)==(3,4)} >>> {(1)-->(2-4), (2,3)-->(1,4), (2,4)-->(1,3), (3,4)==(3,4)} >>> {(1)-->(2-4), (2,3)-->(1,4), (2,4)-->(1,3), (3,4)==(3,4)}", + }, + } + + ctx := context.TODO() + is := testGetIS(t, tk.Session()) + for i, tt := range tests { + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := par.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanColumnID = 0 + err = plannercore.Preprocess(tk.Session(), stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err) + tk.Session().PrepareTSFuture(ctx) + builder, _ := plannercore.NewPlanBuilder().Init(tk.Session(), is, &hint.BlockHintProcessor{}) + // extract FD to every OP + p, err := builder.Build(ctx, stmt) + require.NoError(t, err) + p, err = plannercore.LogicalOptimizeTest(ctx, builder.GetOptFlag(), p.(plannercore.LogicalPlan)) + require.NoError(t, err) + require.Equal(t, tt.best, plannercore.ToString(p), comment) + // extract FD to every OP + p.(plannercore.LogicalPlan).ExtractFD() + require.Equal(t, tt.fd, plannercore.FDToString(p.(plannercore.LogicalPlan)), comment) + } +} + +func TestFDSet_ExtractFDForApply(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + par := parser.New() + par.SetParserConfig(parser.ParserConfig{EnableWindowFunction: true, EnableStrictDoubleTypeCheck: true}) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_enable_new_only_full_group_by_check = 'on';") + tk.MustExec("CREATE TABLE X (a INT PRIMARY KEY, b INT, c INT, d INT, e INT)") + tk.MustExec("CREATE UNIQUE INDEX uni ON X (b, c)") + tk.MustExec("CREATE TABLE Y (m INT, n INT, p INT, q INT, PRIMARY KEY (m, n))") + + tests := []struct { + sql string + best string + fd string + }{ + { + sql: "select * from X where exists (select * from Y where m=a limit 1)", + // For this Apply, it's essentially a semi join, for every `a` in X, do the inner loop once. + // +- datasource(x) + // +- limit + // +- datasource(Y) + best: "Apply{DataScan(X)->DataScan(Y)->Limit}->Projection", + // Since semi join will keep the **all** rows of the outer table, it's FD can be derived. + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(1)-->(2-5), (2,3)~~>(1,4,5)}", + }, + { + sql: "select a, b from X where exists (select * from Y where m=a limit 1)", + // For this Apply, it's essentially a semi join, for every `a` in X, do the inner loop once. + // +- datasource(x) + // +- limit + // +- datasource(Y) + best: "Apply{DataScan(X)->DataScan(Y)->Limit}->Projection", // semi join + // Since semi join will keep the **part** rows of the outer table, it's FD can be derived. + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(1)-->(2)}", + }, + { + // Limit will refuse to de-correlate apply to join while this won't. + sql: "select * from X where exists (select * from Y where m=a and p=1)", + best: "Join{DataScan(X)->DataScan(Y)}(test.x.a,test.y.m)->Projection", // semi join + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(1)-->(2-5), (2,3)~~>(1,4,5)}", + }, + { + sql: "select * from X where exists (select * from Y where m=a and p=q)", + best: "Join{DataScan(X)->DataScan(Y)}(test.x.a,test.y.m)->Projection", // semi join + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(1)-->(2-5), (2,3)~~>(1,4,5)}", + }, + { + sql: "select * from X where exists (select * from Y where m=a and b=1)", + best: "Join{DataScan(X)->DataScan(Y)}(test.x.a,test.y.m)->Projection", // semi join + // b=1 is semi join's left condition which should be conserved. + fd: "{(1)-->(3-5), (2,3)~~>(1,4,5), ()-->(2)} >>> {(1)-->(3-5), (2,3)~~>(1,4,5), ()-->(2)}", + }, + { + sql: "select * from (select b,c,d,e from X) X1 where exists (select * from Y where p=q and n=1) ", + best: "Dual->Projection", + fd: "{}", + }, + { + sql: "select * from (select b,c,d,e from X) X1 where exists (select * from Y where p=b and n=1) ", + best: "Join{DataScan(X)->DataScan(Y)}(test.x.b,test.y.p)->Projection", // semi join + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(2,3)~~>(4,5)}", + }, + { + sql: "select * from X where exists (select m, p, q from Y where n=a and p=1)", + best: "Join{DataScan(X)->DataScan(Y)}(test.x.a,test.y.n)->Projection", + // p=1 is semi join's right condition which should **NOT** be conserved. + fd: "{(1)-->(2-5), (2,3)~~>(1,4,5)} >>> {(1)-->(2-5), (2,3)~~>(1,4,5)}", + }, + } + + ctx := context.TODO() + is := testGetIS(t, tk.Session()) + for i, tt := range tests { + comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) + stmt, err := par.ParseOneStmt(tt.sql, "", "") + require.NoError(t, err, comment) + tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanColumnID = 0 + err = plannercore.Preprocess(tk.Session(), stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) + require.NoError(t, err, comment) + tk.Session().PrepareTSFuture(ctx) + builder, _ := plannercore.NewPlanBuilder().Init(tk.Session(), is, &hint.BlockHintProcessor{}) + // extract FD to every OP + p, err := builder.Build(ctx, stmt) + require.NoError(t, err, comment) + p, err = plannercore.LogicalOptimizeTest(ctx, builder.GetOptFlag(), p.(plannercore.LogicalPlan)) + require.NoError(t, err, comment) + require.Equal(t, tt.best, plannercore.ToString(p), comment) + // extract FD to every OP + p.(plannercore.LogicalPlan).ExtractFD() + require.Equal(t, tt.fd, plannercore.FDToString(p.(plannercore.LogicalPlan)), comment) + } +} diff --git a/planner/funcdep/fast_int_set.go b/planner/funcdep/fast_int_set.go new file mode 100644 index 0000000000000..b089f102fcd83 --- /dev/null +++ b/planner/funcdep/fast_int_set.go @@ -0,0 +1,390 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "bytes" + "fmt" + "math/bits" + + "golang.org/x/tools/container/intsets" +) + +const smallCutOff = 64 + +// FastIntSet is wrapper of sparse with an optimization that number [0 ~ 64) can be cached for quick access. +// From the benchmark in fd_graph_test.go, we choose to use sparse to accelerate int set. And when the set +// size is quite small we can just skip the block allocation in the sparse chain list. +type FastIntSet struct { + // an uint64 used like quick-small bitmap of 0~63. + small uint64 + // when some is bigger than 64, then all that previous inserted will be dumped into sparse. + large *intsets.Sparse +} + +// NewFastIntSet is used to make the instance of FastIntSet with initial values. +func NewFastIntSet(values ...int) FastIntSet { + var res FastIntSet + for _, v := range values { + res.Insert(v) + } + return res +} + +// Len return the size of the int set. +func (s FastIntSet) Len() int { + if s.large == nil { + return bits.OnesCount64(s.small) + } + return s.large.Len() +} + +// Only1Zero is a usage function for convenience judgement. +func (s FastIntSet) Only1Zero() bool { + return s.Len() == 1 && s.Has(0) +} + +// Insert is used to insert a value into int-set. +func (s *FastIntSet) Insert(i int) { + isSmall := i >= 0 && i < smallCutOff + if isSmall { + s.small |= 1 << uint64(i) + } + if !isSmall && s.large == nil { + // first encounter a larger/smaller number, dump all that in `small` into `large`. + s.large = s.toLarge() + } + if s.large != nil { + s.large.Insert(i) + } +} + +func (s FastIntSet) toLarge() *intsets.Sparse { + if s.large != nil { + return s.large + } + large := new(intsets.Sparse) + for i, ok := s.Next(0); ok; i, ok = s.Next(i + 1) { + large.Insert(i) + } + return large +} + +// Next returns the next existing number in the Set. If there's no larger one than the given start val, return (MaxInt, false). +func (s FastIntSet) Next(startVal int) (int, bool) { + if startVal < smallCutOff { + if startVal < 0 { + startVal = 0 + } + // x=0, gap=64, which means there is no `1` after right shift. + if gap := bits.TrailingZeros64(s.small >> uint64(startVal)); gap < 64 { + return gap + startVal, true + } + } + if s.large != nil { + res := s.large.LowerBound(startVal) + return res, res != intsets.MaxInt + } + return intsets.MaxInt, false +} + +// Remove is used to remove a value from the set. Nothing done if the value is not in the set. +func (s *FastIntSet) Remove(i int) { + if i >= 0 && i < smallCutOff { + s.small &^= 1 << uint64(i) + } + if s.large != nil { + s.large.Remove(i) + } +} + +// Clear is used to clear a fastIntSet and reuse it as an empty one. +func (s *FastIntSet) Clear() { + s.small = 0 + if s.large != nil { + s.large.Clear() + } +} + +// Has is used ot judge whether a value is in the set. +func (s FastIntSet) Has(i int) bool { + if i >= 0 && i < smallCutOff { + return (s.small & (1 << uint64(i))) != 0 + } + if s.large != nil { + return s.large.Has(i) + } + return false +} + +// IsEmpty is used to judge whether the int-set is empty. +func (s FastIntSet) IsEmpty() bool { + return s.small == 0 && (s.large == nil || s.large.IsEmpty()) +} + +// SortedArray is used to return the in array of the set. +func (s FastIntSet) SortedArray() []int { + if s.IsEmpty() { + return nil + } + if s.large != nil { + return s.large.AppendTo([]int(nil)) + } + res := make([]int, 0, s.Len()) + s.ForEach(func(i int) { + res = append(res, i) + }) + return res +} + +// ForEach call a function for each value in the int-set. (Ascend) +func (s FastIntSet) ForEach(f func(i int)) { + if s.large != nil { + for x := s.large.Min(); x != intsets.MaxInt; x = s.large.LowerBound(x + 1) { + f(x) + } + return + } + for v := s.small; v != 0; { + // from the left to right. + i := bits.TrailingZeros64(v) + f(i) + v &^= 1 << uint(i) + } +} + +// Copy returns a copy of s. +func (s FastIntSet) Copy() FastIntSet { + c := FastIntSet{} + c.small = s.small + if s.large != nil { + c.large = new(intsets.Sparse) + c.large.Copy(s.large) + } + return c +} + +// CopyFrom clear the receiver to be a copy of the param. +func (s *FastIntSet) CopyFrom(target FastIntSet) { + s.small = target.small + if target.large != nil { + if s.large == nil { + s.large = new(intsets.Sparse) + } + s.large.Copy(target.large) + } else { + if s.large != nil { + s.large.Clear() + } + } +} + +// Equals returns whether two int-set are identical. +func (s FastIntSet) Equals(rhs FastIntSet) bool { + if s.large == nil && rhs.large == nil { + return s.small == rhs.small + } + if s.large != nil && rhs.large != nil { + return s.large.Equals(rhs.large) + } + // how come to this? eg: a set operates like: {insert:1, insert:65, remove:65}, resulting a large int-set with only small numbers. + // so we need calculate the exact numbers. + var excess bool + s1 := s.small + s2 := rhs.small + if s.large != nil { + s1, excess = s.largeToSmall() + } else { + s2, excess = rhs.largeToSmall() + } + return !excess && s1 == s2 +} + +func (s FastIntSet) largeToSmall() (small uint64, otherValues bool) { + if s.large == nil { + panic("set contains no large") + } + return s.small, s.large.Min() < 0 || s.large.Max() >= smallCutOff +} + +// ************************************************************************* +// * Logic Operators * +// ************************************************************************* + +// Difference is used to return the s without elements in rhs. +func (s FastIntSet) Difference(rhs FastIntSet) FastIntSet { + r := s.Copy() + r.DifferenceWith(rhs) + return r +} + +// DifferenceWith removes any elements in rhs from source. +func (s *FastIntSet) DifferenceWith(rhs FastIntSet) { + s.small &^= rhs.small + if s.large == nil { + return + } + s.large.DifferenceWith(rhs.toLarge()) +} + +// Union is used to return a union of s and rhs as new set. +func (s FastIntSet) Union(rhs FastIntSet) FastIntSet { + cps := s.Copy() + cps.UnionWith(rhs) + return cps +} + +// UnionWith is used to copy all the elements of rhs to source. +func (s *FastIntSet) UnionWith(rhs FastIntSet) { + s.small |= rhs.small + if s.large == nil && rhs.large == nil { + return + } + if s.large == nil { + s.large = s.toLarge() + } + if rhs.large == nil { + for i, ok := rhs.Next(0); ok; i, ok = rhs.Next(i + 1) { + s.large.Insert(i) + } + } else { + s.large.UnionWith(rhs.large) + } +} + +// Intersection is used to return the intersection of s and rhs. +func (s FastIntSet) Intersection(rhs FastIntSet) FastIntSet { + r := s.Copy() + r.IntersectionWith(rhs) + return r +} + +// IntersectionWith removes any elements not in rhs from source. +func (s *FastIntSet) IntersectionWith(rhs FastIntSet) { + s.small &= rhs.small + if rhs.large == nil { + s.large = nil + } + if s.large == nil { + return + } + s.large.IntersectionWith(rhs.toLarge()) +} + +// Intersects is used to judge whether two set has something in common. +func (s FastIntSet) Intersects(rhs FastIntSet) bool { + if (s.small & rhs.small) != 0 { + return true + } + if s.large == nil || rhs.large == nil { + return false + } + return s.large.Intersects(rhs.toLarge()) +} + +// SubsetOf is used to judge whether rhs contains source set. +func (s FastIntSet) SubsetOf(rhs FastIntSet) bool { + if s.large == nil { + return (s.small & rhs.small) == s.small + } + if s.large != nil && rhs.large != nil { + return s.large.SubsetOf(rhs.large) + } + // s is large and rhs is small. + if _, excess := s.largeToSmall(); excess { + // couldn't map s to small. + return false + } + // how come to this? eg: a set operates like: {insert:1, insert:65, remove:65}, resulting a large + // int-set with only small numbers. + return (s.small & rhs.small) == s.small +} + +// Shift generates a new set which contains elements i+delta for elements i in +// the original set. +func (s *FastIntSet) Shift(delta int) FastIntSet { + if s.large == nil { + // Fast path. + if delta > 0 { + if bits.LeadingZeros64(s.small)-(64-smallCutOff) >= delta { + return FastIntSet{small: s.small << uint32(delta)} + } + } else { + if bits.TrailingZeros64(s.small) >= -delta { + return FastIntSet{small: s.small >> uint32(-delta)} + } + } + } + // Do the slow thing. + var result FastIntSet + s.ForEach(func(i int) { + result.Insert(i + delta) + }) + return result +} + +// AddRange adds the interval [from, to] to the Set. +func (s *FastIntSet) AddRange(from, to int) { + if to < from { + panic("invalid range when adding range to FastIntSet") + } + + withinSmallBounds := from >= 0 && to < smallCutOff + if withinSmallBounds && s.large == nil { + nValues := to - from + 1 + s.small |= (1< 1 { + buf.WriteByte(',') + } + if start == end { + fmt.Fprintf(&buf, "%d", start) + } else if start+1 == end { + fmt.Fprintf(&buf, "%d,%d", start, end) + } else { + fmt.Fprintf(&buf, "%d-%d", start, end) + } + } + rangeStart, rangeEnd := -1, -1 + s.ForEach(func(i int) { + if i < 0 { + appendRange(i, i) + return + } + if rangeStart != -1 && rangeEnd == i-1 { + rangeEnd = i + } else { + if rangeStart != -1 { + appendRange(rangeStart, rangeEnd) + } + rangeStart, rangeEnd = i, i + } + }) + if rangeStart != -1 { + appendRange(rangeStart, rangeEnd) + } + buf.WriteByte(')') + return buf.String() +} diff --git a/planner/funcdep/fast_int_set_bench_test.go b/planner/funcdep/fast_int_set_bench_test.go new file mode 100644 index 0000000000000..a81c607a4c9af --- /dev/null +++ b/planner/funcdep/fast_int_set_bench_test.go @@ -0,0 +1,158 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "testing" + + "golang.org/x/tools/container/intsets" +) + +func BenchmarkMapIntSet_Difference(b *testing.B) { + intSetA := NewIntSet() + for i := 0; i < 200000; i++ { + intSetA[i] = struct{}{} + } + intSetB := NewIntSet() + for i := 100000; i < 300000; i++ { + intSetB[i] = struct{}{} + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + tmp := NewIntSet() + tmp.Difference2(intSetA, intSetB) + //intSetA.SubsetOf(intSetB) + } +} + +func BenchmarkIntSet_Difference(b *testing.B) { + intSetA := &intsets.Sparse{} + for i := 0; i < 200000; i++ { + intSetA.Insert(i) + } + intSetB := &intsets.Sparse{} + for i := 100000; i < 300000; i++ { + intSetA.Insert(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + tmp := &intsets.Sparse{} + tmp.Difference(intSetA, intSetB) + //intSetA.SubsetOf(intSetB) + } +} + +func BenchmarkFastIntSet_Difference(b *testing.B) { + intSetA := NewFastIntSet() + for i := 0; i < 200000; i++ { + intSetA.Insert(i) + } + intSetB := NewFastIntSet() + for i := 100000; i < 300000; i++ { + intSetA.Insert(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + intSetA.Difference(intSetB) + //intSetA.SubsetOf(intSetB) + } +} + +func BenchmarkIntSet_Insert(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + intSet := NewIntSet() + for j := 0; j < 64; j++ { + intSet.Insert(j) + } + } +} + +func BenchmarkSparse_Insert(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + intSet := &intsets.Sparse{} + for j := 0; j < 64; j++ { + intSet.Insert(j) + } + } +} + +func BenchmarkFastIntSet_Insert(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + intSet := NewFastIntSet() + for j := 0; j < 64; j++ { + intSet.Insert(j) + } + } +} + +// BenchMarkResult +// +// Test with Difference (traverse and allocation) (size means the intersection size) +// +--------------------------------------------------------------------------------+ +// | size | map int set | basic sparse int set | fast sparse int set | +// +------------+-----------------+------------------------+------------------------+ +// | 64 | 3203 ns/op | 64 ns/op | 5.750 ns/op | +// | 1000 | 244284 ns/op | 822 ns/op | 919.8 ns/op | +// | 10000 | 2940130 ns/op | 8071 ns/op | 8686 ns/op | +// | 100000 | 41283606 ns/op | 83320 ns/op | 85563 ns/op | +// +------------+-----------------+------------------------+------------------------+ +// +// This test is under same operation with same data with following analysis: +// MapInt and Sparse are all temporarily allocated for intermediate result. Since +// MapInt need to reallocate the capacity with unit as int(64) which is expensive +// than a bit of occupation in Sparse reallocation. +// +// From the space utilization and allocation times, here in favour of sparse. +// +// Test with Insert (allocation) +// +----------------------------------------------------------------------------+ +// | size | map int set | basic sparse int set | fast sparse int set | +// +--------+-----------------+------------------------+------------------------+ +// | 64 | 5705 ns/op | 580 ns/op | 234 ns/op | +// | 1000 | 122906 ns/op | 7991 ns/op | 10606 ns/op | +// | 10000 | 845961 ns/op | 281134 ns/op | 303006 ns/op | +// | 100000 | 15529859 ns/op | 31273573 ns/op | 30752177 ns/op | +// +--------------------------+------------------------+------------------------+ +// +// From insert, map insert take much time than sparse does when insert size is under +// 100 thousand. While when the size grows bigger, map insert take less time to do that +// (maybe cost more memory usage), that because sparse need to traverse the chain to +// find the suitable block to insert. +// +// From insert, if set size is larger than 100 thousand, map-set is preferred, otherwise, sparse is good. +// +// Test with Subset (traverse) (sizes means the size A / B) +// +---------------------------------------------------------------------------------+ +// | size | map int set | basic sparse int set | fast sparse int set | +// +--------+-----------------+------------------------+------------------------+ +// | 64 | 59.47 ns/op | 3.775 ns/op | 2.727 ns/op | +// | 1000 | 68.9 ns/op | 3.561 ns/op | 22.64 ns/op | +// | 20000 | 104.7 ns/op | 3.502 ns/op | 23.92 ns/op | +// | 200000 | 249.8 ns/op | 3.504 ns/op | 22.11 ns/op | +// +--------------------------+------------------------+------------------------+ +// +// This is the most amazing part we have been tested. Map set need to compute the equality +// about the every key int in the map with others. While sparse only need to do is just to +// fetch every bitmap (every bit implies a number) and to the bit operation together. +// +// FastIntSet's performance is quite like Sparse IntSet, because they have the same implementation +// inside. While FastIntSet have some optimizations with small range (0-63), so we add an +// extra test for size with 64, from the number above, they did have some effects, especially +// in computing the difference (bit | technically). +// +// From all above, we are in favour of sparse. sparse to store fast-int-set instead of using map. diff --git a/planner/funcdep/fast_int_set_test.go b/planner/funcdep/fast_int_set_test.go new file mode 100644 index 0000000000000..8fef7ffa36a49 --- /dev/null +++ b/planner/funcdep/fast_int_set_test.go @@ -0,0 +1,516 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "fmt" + "math/rand" + "reflect" + "runtime" + "sort" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/tools/container/intsets" +) + +// IntSet is used to hold set of vertexes of one side of an edge. +type IntSet map[int]struct{} + +// SubsetOf is used to judge whether IntSet itself is a subset of others. +func (is IntSet) SubsetOf(target IntSet) bool { + for i := range is { + if _, ok := target[i]; ok { + continue + } + return false + } + return true +} + +// Intersects is used to judge whether IntSet itself intersects with others. +func (is IntSet) Intersects(target IntSet) bool { + for i := range is { + if _, ok := target[i]; ok { + return true + } + } + return false +} + +// Difference is used to exclude the intersection sector away from itself. +func (is IntSet) Difference(target IntSet) { + for i := range target { + delete(is, i) + } +} + +func (is IntSet) Difference2(target1, target2 IntSet) { + for i := range target1 { + if _, ok := target2[i]; ok { + delete(is, i) + } else { + is[i] = struct{}{} + } + } +} + +// Union is used to union the IntSet itself with others +func (is IntSet) Union(target IntSet) { + // deduplicate + for i := range target { + if _, ok := is[i]; ok { + continue + } + is[i] = struct{}{} + } +} + +// Equals is used to judge whether two IntSet are semantically equal. +func (is IntSet) Equals(target IntSet) bool { + if len(is) != len(target) { + return false + } + for i := range target { + if _, ok := is[i]; !ok { + return false + } + } + return true +} + +func (is *IntSet) CopyFrom(target IntSet) { + *is = NewIntSetWithCap(len(target)) + for k, v := range target { + (*is)[k] = v + } +} + +func (is IntSet) SortedArray() []int { + arr := make([]int, 0, len(is)) + for k := range is { + arr = append(arr, k) + } + sort.Slice(arr, func(i, j int) bool { return arr[i] < arr[j] }) + return arr +} + +func (is IntSet) Insert(k int) { + is[k] = struct{}{} +} + +func NewIntSet() IntSet { + return make(map[int]struct{}) +} + +func NewIntSetWithCap(c int) IntSet { + return make(map[int]struct{}, c) +} + +func TestFastIntSetBasic(t *testing.T) { + // Test Insert, Remove, Len, Has. + fis := FastIntSet{} + fis.Insert(1) + fis.Insert(2) + fis.Insert(3) + require.Equal(t, fis.Len(), 3) + require.True(t, fis.Has(1)) + require.True(t, fis.Has(2)) + require.True(t, fis.Has(3)) + fis.Remove(2) + require.Equal(t, fis.Len(), 2) + require.True(t, fis.Has(1)) + require.True(t, fis.Has(3)) + fis.Remove(3) + require.Equal(t, fis.Len(), 1) + require.True(t, fis.Has(1)) + fis.Remove(1) + require.Equal(t, fis.Len(), 0) + + // Test Next (only seek non-neg) + fis.Insert(6) + fis.Insert(3) + fis.Insert(0) + fis.Insert(-1) + fis.Insert(77) + n, ok := fis.Next(intsets.MinInt) + require.True(t, ok) + require.Equal(t, n, 0) + n, ok = fis.Next(n + 1) + require.True(t, ok) + require.Equal(t, n, 3) + n, ok = fis.Next(n + 1) + require.True(t, ok) + require.Equal(t, n, 6) + n, ok = fis.Next(n + 1) + require.True(t, ok) + require.Equal(t, n, 77) + n, ok = fis.Next(n + 1) + require.False(t, ok) + require.Equal(t, n, intsets.MaxInt) + + // Test Clear and IsEmpty. + fis.Clear() + require.Equal(t, fis.Len(), 0) + require.True(t, fis.IsEmpty()) + + // Test ForEach (seek all) and SortedArray. + fis.Insert(1) + fis.Insert(-1) + fis.Insert(77) + var res []int + fis.ForEach(func(i int) { + res = append(res, i) + }) + res1 := fis.SortedArray() + require.Equal(t, len(res), 3) + require.Equal(t, len(res1), 3) + require.Equal(t, res, res1) + + // Test Copy, CopyFrom and Equal + cp := fis.Copy() + require.Equal(t, fis.Len(), cp.Len()) + require.Equal(t, fis.SortedArray(), cp.SortedArray()) + require.True(t, fis.Equals(cp)) + + cpf := FastIntSet{} + intervene := 100 + cpf.Insert(intervene) + cpf.CopyFrom(fis) + require.Equal(t, cpf.Len(), cp.Len()) + require.Equal(t, cpf.SortedArray(), cp.SortedArray()) + require.True(t, cpf.Equals(cp)) +} + +func getTestName() string { + pcs := make([]uintptr, 10) + n := runtime.Callers(2, pcs) + frames := runtime.CallersFrames(pcs[:n]) + for { + frame, more := frames.Next() + fxn := frame.Function + if strings.Contains(fxn, ".Test") { + return fxn + } + if !more { + break + } + } + return "" +} + +var lastTestName string +var rng *rand.Rand + +func NewTestRand() (*rand.Rand, int64) { + fxn := getTestName() + if fxn != "" && lastTestName != fxn { + // Re-seed rng (the source of seeds for test random number generators) with + // the global seed so that individual tests are reproducible using the + // random seed. + lastTestName = fxn + rng = rand.New(rand.NewSource(time.Now().Unix())) + } + seed := rng.Int63() + return rand.New(rand.NewSource(seed)), seed +} + +func TestFastIntSet(t *testing.T) { + for _, mVal := range []int{1, 8, 30, smallCutOff, 2 * smallCutOff, 4 * smallCutOff} { + m := mVal + t.Run(fmt.Sprintf("%d", m), func(t *testing.T) { + rng, _ := NewTestRand() + in := make([]bool, m) + forEachRes := make([]bool, m) + + var s FastIntSet + for i := 0; i < 1000; i++ { + v := rng.Intn(m) + if rng.Intn(2) == 0 { + in[v] = true + s.Insert(v) + } else { + in[v] = false + s.Remove(v) + } + empty := true + for j := 0; j < m; j++ { + empty = empty && !in[j] + if in[j] != s.Has(j) { + t.Fatalf("incorrect result for Contains(%d), expected %t", j, in[j]) + } + } + if empty != s.IsEmpty() { + t.Fatalf("incorrect result for Empty(), expected %t", empty) + } + // Test ForEach + for j := range forEachRes { + forEachRes[j] = false + } + s.ForEach(func(j int) { + forEachRes[j] = true + }) + for j := 0; j < m; j++ { + if in[j] != forEachRes[j] { + t.Fatalf("incorrect ForEachResult for %d (%t, expected %t)", j, forEachRes[j], in[j]) + } + } + // Cross-check Ordered and Next(). + var vals []int + for i, ok := s.Next(0); ok; i, ok = s.Next(i + 1) { + vals = append(vals, i) + } + if o := s.SortedArray(); !reflect.DeepEqual(vals, o) { + t.Fatalf("set built with Next doesn't match Ordered: %v vs %v", vals, o) + } + assertSame := func(orig, copied FastIntSet) { + t.Helper() + if !orig.Equals(copied) || !copied.Equals(orig) { + t.Fatalf("expected equality: %v, %v", orig, copied) + } + if col, ok := copied.Next(0); ok { + copied.Remove(col) + if orig.Equals(copied) || copied.Equals(orig) { + t.Fatalf("unexpected equality: %v, %v", orig, copied) + } + copied.Insert(col) + if !orig.Equals(copied) || !copied.Equals(orig) { + t.Fatalf("expected equality: %v, %v", orig, copied) + } + } + } + // Test Copy. + s2 := s.Copy() + assertSame(s, s2) + // Test CopyFrom. + var s3 FastIntSet + s3.CopyFrom(s) + assertSame(s, s3) + // Make sure CopyFrom into a non-empty set still works. + s.Shift(100) + s.CopyFrom(s3) + assertSame(s, s3) + } + }) + } +} + +func TestFastIntSetTwoSetOps(t *testing.T) { + rng, _ := NewTestRand() + // genSet creates a set of numElem values in [minVal, minVal + valRange) + // It also adds and then removes numRemoved elements. + genSet := func(numElem, numRemoved, minVal, valRange int) (FastIntSet, map[int]bool) { + var s FastIntSet + vals := rng.Perm(valRange)[:numElem+numRemoved] + used := make(map[int]bool, len(vals)) + for _, i := range vals { + used[i] = true + } + for k := range used { + s.Insert(k) + } + p := rng.Perm(len(vals)) + for i := 0; i < numRemoved; i++ { + k := vals[p[i]] + s.Remove(k) + delete(used, k) + } + return s, used + } + + // returns true if a is a subset of b + subset := func(a, b map[int]bool) bool { + for k := range a { + if !b[k] { + return false + } + } + return true + } + + for _, minVal := range []int{-10, -1, 0, smallCutOff, 2 * smallCutOff} { + for _, valRange := range []int{0, 20, 200} { + for _, num1 := range []int{0, 1, 5, 10, 20} { + for _, removed1 := range []int{0, 1, 3, 8} { + s1, m1 := genSet(num1, removed1, minVal, num1+removed1+valRange) + for _, shift := range []int{-100, -10, -1, 1, 2, 10, 100} { + shifted := s1.Shift(shift) + failed := false + s1.ForEach(func(i int) { + failed = failed || !shifted.Has(i+shift) + }) + shifted.ForEach(func(i int) { + failed = failed || !s1.Has(i-shift) + }) + if failed { + t.Errorf("invalid shifted result: %s shifted by %d: %s", &s1, shift, &shifted) + } + } + for _, num2 := range []int{0, 1, 5, 10, 20} { + for _, removed2 := range []int{0, 1, 4, 10} { + s2, m2 := genSet(num2, removed2, minVal, num2+removed2+valRange) + + subset1 := subset(m1, m2) + if subset1 != s1.SubsetOf(s2) { + t.Errorf("SubsetOf result incorrect: %s, %s", &s1, &s2) + } + subset2 := subset(m2, m1) + if subset2 != s2.SubsetOf(s1) { + t.Errorf("SubsetOf result incorrect: %s, %s", &s2, &s1) + } + eq := subset1 && subset2 + if eq != s1.Equals(s2) || eq != s2.Equals(s1) { + t.Errorf("Equals result incorrect: %s, %s", &s1, &s2) + } + + // Test union. + + u := s1.Copy() + u.UnionWith(s2) + + if !u.Equals(s1.Union(s2)) { + t.Errorf("inconsistency between UnionWith and Union on %s %s\n", s1, s2) + } + // Verify all elements from m1 and m2 are in u. + for _, m := range []map[int]bool{m1, m2} { + for x := range m { + if !u.Has(x) { + t.Errorf("incorrect union result %s union %s = %s", &s1, &s2, &u) + break + } + } + } + // Verify all elements from u are in m2 or m1. + for x, ok := u.Next(minVal); ok; x, ok = u.Next(x + 1) { + if !(m1[x] || m2[x]) { + t.Errorf("incorrect union result %s union %s = %s", &s1, &s2, &u) + break + } + } + + // Test intersection. + u = s1.Copy() + u.IntersectionWith(s2) + if s1.Intersects(s2) != !u.IsEmpty() || + s2.Intersects(s1) != !u.IsEmpty() { + t.Errorf("inconsistency between IntersectionWith and Intersect on %s %s\n", s1, s2) + } + if !u.Equals(s1.Intersection(s2)) { + t.Errorf("inconsistency between IntersectionWith and Intersection on %s %s\n", s1, s2) + } + // Verify all elements from m1 and m2 are in u. + for x := range m1 { + if m2[x] && !u.Has(x) { + t.Errorf("incorrect intersection result %s union %s = %s x=%d", &s1, &s2, &u, x) + break + } + } + // Verify all elements from u are in m2 and m1. + for x, ok := u.Next(minVal); ok; x, ok = u.Next(x + 1) { + if !(m1[x] && m2[x]) { + t.Errorf("incorrect intersection result %s intersect %s = %s", &s1, &s2, &u) + break + } + } + + // Test difference. + u = s1.Copy() + u.DifferenceWith(s2) + + if !u.Equals(s1.Difference(s2)) { + t.Errorf("inconsistency between DifferenceWith and Difference on %s %s\n", s1, s2) + } + + // Verify all elements in m1 but not in m2 are in u. + for x := range m1 { + if !m2[x] && !u.Has(x) { + t.Errorf("incorrect difference result %s \\ %s = %s x=%d", &s1, &s2, &u, x) + break + } + } + // Verify all elements from u are in m1. + for x, ok := u.Next(minVal); ok; x, ok = u.Next(x + 1) { + if !m1[x] { + t.Errorf("incorrect difference result %s \\ %s = %s", &s1, &s2, &u) + break + } + } + } + } + } + } + } + } +} + +func TestFastIntSetAddRange(t *testing.T) { + assertSet := func(set *FastIntSet, from, to int) { + t.Helper() + // Iterate through the set and ensure that the values + // it contain are the values from 'from' to 'to' (inclusively). + expected := from + set.ForEach(func(actual int) { + t.Helper() + if actual > to { + t.Fatalf("expected last value in FastIntSet to be %d, got %d", to, actual) + } + if expected != actual { + t.Fatalf("expected next value in FastIntSet to be %d, got %d", expected, actual) + } + expected++ + }) + } + + max := smallCutOff + 20 + // Test all O(n^2) sub-intervals of [from,to] in the interval + // [-5, smallCutoff + 20]. + for from := -5; from <= max; from++ { + for to := from; to <= max; to++ { + var set FastIntSet + set.AddRange(from, to) + assertSet(&set, from, to) + } + } +} + +func TestFastIntSetString(t *testing.T) { + testCases := []struct { + vals []int + exp string + }{ + { + vals: []int{}, + exp: "()", + }, + { + vals: []int{-5, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + exp: "(-5,-3,-2,-1,0-5)", + }, + { + vals: []int{0, 1, 3, 4, 5}, + exp: "(0,1,3-5)", + }, + } + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + s := NewFastIntSet(tc.vals...) + if str := s.String(); str != tc.exp { + t.Errorf("expected %s, got %s", tc.exp, str) + } + }) + } +} diff --git a/planner/funcdep/fd_graph.go b/planner/funcdep/fd_graph.go new file mode 100644 index 0000000000000..f103429ca4728 --- /dev/null +++ b/planner/funcdep/fd_graph.go @@ -0,0 +1,909 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "fmt" + "strings" + + "github.com/pingcap/tidb/util/logutil" +) + +type fdEdge struct { + // functional dependency = determinants -> dependencies + // determinants = from + // dependencies = to + from FastIntSet + to FastIntSet + // The value of the strict and eq bool forms the four kind of edges: + // functional dependency, lax functional dependency, strict equivalence constraint, lax equivalence constraint. + // And if there's a functional dependency `const` -> `column` exists. We would let the from side be empty. + strict bool + equiv bool +} + +// FDSet is the main portal of functional dependency, it stores the relationship between (extended table / physical table)'s +// columns. For more theory about this design, ref the head comments in the funcdep/doc.go. +type FDSet struct { + fdEdges []*fdEdge + // NotNullCols is used to record the columns with not-null attributes applied. + // eg: {1} ~~> {2,3}, when {2,3} not null is applied, it actually does nothing. + // but we should record {2,3} as not-null down for the convenience of transferring + // Lax FD: {1} ~~> {2,3} to strict FD: {1} --> {2,3} with {1} as not-null next time. + NotNullCols FastIntSet + // HashCodeToUniqueID map the expression's hashcode to a statement allocated unique + // ID quite like the unique ID bounded with column. It's mainly used to add the expr + // to the fdSet as an extended column. + HashCodeToUniqueID map[string]int + // GroupByCols is used to record columns / expressions that under the group by phrase. + GroupByCols FastIntSet + HasAggBuilt bool + // after left join, according to rule 3.3.3, it may create a lax FD from inner equivalence + // cols pointing to outer equivalence cols. eg: t left join t1 on t.a = t1.b, leading a + // lax FD from t1.b ~> t.a, this lax attribute is coming from supplied null value to all + // left rows, once there is a null-refusing predicate on the inner side on upper layer, this + // can be equivalence again. (the outer rows left are all coming from equal matching) + // + // why not just makeNotNull of them, because even a non-equiv-related inner col can also + // refuse supplied null values. + Rule333Equiv struct { + Edges []*fdEdge + InnerCols FastIntSet + } +} + +// ClosureOfStrict is exported for outer usage. +func (s *FDSet) ClosureOfStrict(colSet FastIntSet) FastIntSet { + return s.closureOfStrict(colSet) +} + +// closureOfStrict is to find strict fd closure of X with respect to F. +// A -> B = colSet -> { resultIntSet } +// eg: considering closure F: {A-> CD, B -> E}, and input is {AB} +// res: AB -> {CDE} (AB is included in trivial FD) +// The time complexity is O(n^2). +func (s *FDSet) closureOfStrict(colSet FastIntSet) FastIntSet { + resultSet := NewFastIntSet() + // self included. + resultSet.UnionWith(colSet) + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + if fd.strict && fd.from.SubsetOf(resultSet) && !fd.to.SubsetOf(resultSet) { + resultSet.UnionWith(fd.to) + // If the closure is updated, we redo from the beginning. + i = -1 + } + // why this? it is caused by our definition of equivalence as {superset} == {superset}, + // which is also seen as {superset} --> {superset}. but when we compute the transitive + // closure, `fd.from.SubsetOf(resultSet)` is not transitive here. Actually, we can also + // see the equivalence as {single element} == {superset} / {single element} --> {superset}. + if fd.equiv && fd.from.Intersects(resultSet) && !fd.to.SubsetOf(resultSet) { + resultSet.UnionWith(fd.to) + i = -1 + } + } + return resultSet +} + +// ClosureOfLax is exported for outer usage. +func (s *FDSet) ClosureOfLax(colSet FastIntSet) FastIntSet { + return s.closureOfLax(colSet) +} + +// ClosureOfLax is used to find lax fd closure of X with respect to F. +func (s *FDSet) closureOfLax(colSet FastIntSet) FastIntSet { + // Lax dependencies are not transitive (see figure 2.1 in the paper for + // properties that hold for lax dependencies), so only include them if they + // are reachable in a single lax dependency step from the input set. + laxOneStepReached := NewFastIntSet() + // self included. + laxOneStepReached.UnionWith(colSet) + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + // A ~~> B && A == C && C ~~> D: given A, BD can be included via Lax FDs (plus self A and equiv C). + // A ~~> B && B == C: given A, BC can be included via Lax FDs (plus self A). + // which means both dependency and determinant can extend Lax exploration via equivalence. + // + // Besides, strict is a kind of strong lax FDs, result computed above should be unionised with strict FDs closure. + if fd.equiv && fd.from.Intersects(laxOneStepReached) && !fd.to.SubsetOf(laxOneStepReached) { + // equiv can extend the lax-set's access paths. + laxOneStepReached.UnionWith(fd.to) + i = -1 + } + if !fd.strict && !fd.equiv && fd.from.SubsetOf(laxOneStepReached) && !fd.to.SubsetOf(laxOneStepReached) { + // lax FDs. + laxOneStepReached.UnionWith(fd.to) + } + } + // Unionised strict FDs + laxOneStepReached.UnionWith(s.closureOfStrict(colSet)) + return laxOneStepReached +} + +// closureOfEquivalence is to find strict equivalence closure of X with respect to F. +func (s *FDSet) closureOfEquivalence(colSet FastIntSet) FastIntSet { + resultSet := NewFastIntSet() + // self included. + resultSet.UnionWith(colSet) + for i := 0; i < len(s.fdEdges); i++ { + // equivalence is maintained as {superset} == {superset}, we don't need to do transitive computation. + // but they may multi equivalence closure, eg: {a,b}=={a,b}, {c,d} =={c,d}, when adding b=c, we need traverse them all. + fd := s.fdEdges[i] + if fd.equiv { + if fd.from.Intersects(resultSet) && !fd.to.SubsetOf(resultSet) { + resultSet.UnionWith(fd.to) + } + } + } + return resultSet +} + +// InClosure is used to judge whether fd: setA -> setB can be inferred from closure s. +// It's a short-circuit version of the `closureOf`. +func (s *FDSet) InClosure(setA, setB FastIntSet) bool { + if setB.SubsetOf(setA) { + return true + } + currentClosure := NewFastIntSet() + // self included. + currentClosure.UnionWith(setA) + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + if fd.strict && fd.from.SubsetOf(currentClosure) && !fd.to.SubsetOf(currentClosure) { + // once fd.from is subset of setA, which means fd is part of our closure; + // when fd.to is not subset of setA itself, it means inference result is necessary to add; (closure extending) + currentClosure.UnionWith(fd.to) + if setB.SubsetOf(currentClosure) { + return true + } + // If the closure is updated, we redo from the beginning. + i = -1 + } + // why this? it is caused by our definition of equivalence as {superset} == {superset}, + // which is also seen as {superset} --> {superset}. but when we compute the transitive + // closure, `fd.from.SubsetOf(resultSet)` is not transitive here. Actually, we can also + // see the equivalence as {single element} == {superset} / {single element} --> {superset}. + if fd.equiv && fd.from.Intersects(currentClosure) && !fd.to.SubsetOf(currentClosure) { + currentClosure.UnionWith(fd.to) + if setB.SubsetOf(currentClosure) { + return true + } + i = -1 + } + } + return false +} + +// ReduceCols is used to minimize the determinants in one fd input. +// function dependency = determinants -> dependencies +// given: AB -> XY, once B can be inferred from current closure when inserting, take A -> XY instead. +func (s *FDSet) ReduceCols(colSet FastIntSet) FastIntSet { + // Suppose the colSet is A and B, we have A --> B. Then we only need A since B' value is always determined by A. + var removed, result = NewFastIntSet(), NewFastIntSet() + result.CopyFrom(colSet) + for k, ok := colSet.Next(0); ok; k, ok = colSet.Next(k + 1) { + removed.Insert(k) + result.Remove(k) + // If the removed one is not dependent with the result. We add the bit back. + if !s.InClosure(result, removed) { + removed.Remove(k) + result.Insert(k) + } + } + return result +} + +// AddStrictFunctionalDependency is to add `STRICT` functional dependency to the fdGraph. +func (s *FDSet) AddStrictFunctionalDependency(from, to FastIntSet) { + s.addFunctionalDependency(from, to, true, false) +} + +// AddLaxFunctionalDependency is to add `LAX` functional dependency to the fdGraph. +func (s *FDSet) AddLaxFunctionalDependency(from, to FastIntSet) { + s.addFunctionalDependency(from, to, false, false) +} + +// addFunctionalDependency will add strict/lax functional dependency to the fdGraph. +// eg: +// CREATE TABLE t (a int key, b int, c int, d int, e int, UNIQUE (b,c)) +// strict FD: {a} --> {a,b,c,d,e} && lax FD: {b,c} ~~> {a,b,c,d,e} will be added. +// stored FD: {a} --> {b,c,d,e} && lax FD: {b,c} ~~> {a,d,e} is determinant eliminated. +// +// To reduce the edge number, we limit the functional dependency when we insert into the +// set. The key code of insert is like the following codes. +func (s *FDSet) addFunctionalDependency(from, to FastIntSet, strict, equiv bool) { + // trivial FD, refused. + if to.SubsetOf(from) { + return + } + + // exclude the intersection part. + if to.Intersects(from) { + to.DifferenceWith(from) + } + + // reduce the determinants. + from = s.ReduceCols(from) + + newFD := &fdEdge{ + from: from, + to: to, + strict: strict, + equiv: equiv, + } + + swapPointer := 0 + added := false + // the newFD couldn't be superSet of existed one A and be subset of the other existed one B at same time. + // Because the subset relationship between A and B will be replaced previously. + for i := range s.fdEdges { + fd := s.fdEdges[i] + // If the new one is stronger than the old one. Just replace it. + if newFD.implies(fd) { + if added { + continue + } + fd.from = from + fd.to = to + fd.strict = strict + fd.equiv = equiv + added = true + } else if !added { + // There's a strong one. No need to add. + if fd.implies(newFD) { + added = true + } else if fd.strict && !fd.equiv && fd.from.Equals(from) { + // We can use the new FD to extend the current one. + // eg: A -> BC, A -> CE, they couldn't be the subset of each other, union them. + // res: A -> BCE + fd.to.UnionWith(to) + added = true + } + } + // If the current one is not eliminated, add it to the result. + s.fdEdges[swapPointer] = s.fdEdges[i] + swapPointer++ + } + s.fdEdges = s.fdEdges[:swapPointer] + + // If it's still not added. + if !added { + s.fdEdges = append(s.fdEdges, newFD) + } +} + +// implies is used to shrink the edge size, keeping the minimum of the functional dependency set size. +func (e *fdEdge) implies(otherEdge *fdEdge) bool { + // The given one's from should be larger than the current one and the current one's to should be larger than the given one. + // STRICT FD: + // A --> C is stronger than AB --> C. --- YES + // A --> BC is stronger than A --> C. --- YES + // + // LAX FD: + // 1: A ~~> C is stronger than AB ~~> C. --- YES + // 2: A ~~> BC is stronger than A ~~> C. --- NO + // The precondition for 2 to be strict FD is much easier to satisfied than 1, only to + // need {a,c} is not null. So we couldn't merge this two to be one lax FD. + // but for strict/equiv FD implies lax FD, 1 & 2 is implied both reasonably. + lhsIsLax := !e.equiv && !e.strict + rhsIsLax := !otherEdge.equiv && !otherEdge.strict + if lhsIsLax && rhsIsLax { + if e.from.SubsetOf(otherEdge.from) && e.to.Equals(otherEdge.to) { + return true + } + return false + } + if e.from.SubsetOf(otherEdge.from) && otherEdge.to.SubsetOf(e.to) { + // The given one should be weaker than the current one. + // So the given one should not be more strict than the current one. + // The given one should not be equivalence constraint if the given one is not equivalence constraint. + if (e.strict || !otherEdge.strict) && (e.equiv || !otherEdge.equiv) { + return true + } + // 1: e.strict + e.equiv => e > o + // 2: e.strict + !o.equiv => e >= o + // 3: !o.strict + e.equiv => e > o + // 4: !o.strict + !o.equiv => o.lax + } + return false +} + +// addEquivalence add an equivalence set to fdSet. +// when adding an equivalence between column a and b: +// 1: they may be integrated into the origin equivalence superset if this two enclosure have some id in common. +// 2: they can be used to extend the existed constant closure, consequently leading some reduce work: see addConstant. +// 3: they self can be used to eliminate existed strict/lax FDs, see comments below. +func (s *FDSet) addEquivalence(eqs FastIntSet) { + var addConst bool + // get equivalence closure. + eqClosure := s.closureOfEquivalence(eqs) + s.fdEdges = append(s.fdEdges, &fdEdge{from: eqClosure.Copy(), to: eqClosure.Copy(), strict: true, equiv: true}) + + for i := 0; i < len(s.fdEdges)-1; i++ { + fd := s.fdEdges[i] + + if fd.isConstant() { + // If any equivalent column is a constant, then all are constants. + if fd.to.Intersects(eqClosure) && !eqClosure.SubsetOf(fd.to) { + // new non-constant-subset columns need to be merged to the constant closure. + // Since adding constant wil induce extra FD reshapes, we call addConstant directly. + addConst = true + } + } else if fd.from.SubsetOf(eqClosure) { + if fd.equiv { + // this equivalence is enclosed in the super closure appended above, remove it. + s.fdEdges = append(s.fdEdges[:i], s.fdEdges[i+1:]...) + i-- + } else { + // Since from side are all in equivalence closure, we can eliminate some + // columns of dependencies in equivalence closure. because equivalence is + // a stronger relationship than a strict or lax dependency. + // eg: {A,B} --> {C,D}, {A,B,D} in equivalence, FD can be shortly as {A,B} --> {C} + if fd.removeColumnsToSide(eqClosure) { + // Once the to side is empty, remove the FD. + s.fdEdges = append(s.fdEdges[:i], s.fdEdges[i+1:]...) + i-- + } + } + } + } + // addConstant logic won't induce recomputing of the logic above recursively, so do it here. + if addConst { + // {} --> {a} + {a,b,c} --> {a,b,c} leading to extension {} --> {a,b,c} + s.AddConstants(eqClosure) + } +} + +// AddEquivalence take two column id as parameters, establish a strict equivalence between +// this two column which may be enclosed a superset of equivalence closure in the fdSet. +// +// For the equivalence storage, for simplicity, we only keep the superset relationship of +// equivalence since equivalence has the reflexivity. +// +// eg: a==b, b==c, a==e +// +// in our fdSet, the equivalence will be stored like: {a, b, c, e} == {a, b, c,e} +// According and characteristic and reflexivity, each element in the equivalence enclosure +// can derive whatever in the same enclosure. +func (s *FDSet) AddEquivalence(from, to FastIntSet) { + // trivial equivalence, refused. + if to.SubsetOf(from) { + return + } + s.addEquivalence(from.Union(to)) +} + +// AddConstants adds a strict FD to the source which indicates that each of the given column +// have the same constant value for all rows, or same null value for all rows if it's nullable. +// +// {} --> {a} +// +// there are several usage for this kind of FD, for example, constant FD column can exist in the +// select fields not matter whatever the group by column is; distinct predicate can be eliminated +// for these columns as well. +// +// when adding columns, be cautious that +// 1: constant can be propagated in the equivalence/strict closure, turning strict FD as a constant one. +// 2: constant can simplify the strict FD both in determinants side and dependencies side. +// 3: constant can simplify the lax FD in the dependencies side. +func (s *FDSet) AddConstants(cons FastIntSet) { + if cons.IsEmpty() { + return + } + // 1: {} --> {a}, {} --> {b}, when counting the closure, it will collect all constant FD if it has. + // 2: {m,n} --> {x, y}, once the m,n is subset of constant closure, x,y must be constant as well. + // 3: {a,b,c} == {a,b,c}, equiv dependency is also strict FD included int the closure computation here. + cols := s.closureOfStrict(cons) + s.fdEdges = append(s.fdEdges, &fdEdge{to: cols.Copy(), strict: true}) + + // skip the last, newly append one. + for i := 0; i < len(s.fdEdges)-1; i++ { + shouldRemoved := false + fd := s.fdEdges[i] + + if !fd.equiv { + if fd.strict { + // Constant columns can be removed from the determinant of a strict + // FD. If all determinant columns are constant, then the entire FD + // can be removed, since this means that the dependant columns must + // also be constant (and were part of constant closure added to the + // constant FD above). + if fd.removeColumnsFromSide(cols) { + // transfer to constant FD which is enclosed in cols above. + shouldRemoved = true + } + } + // for strict or lax FDs, both can reduce the dependencies side columns with constant closure. + if fd.removeColumnsToSide(cols) { + shouldRemoved = true + } + } + if shouldRemoved { + s.fdEdges = append(s.fdEdges[:i], s.fdEdges[i+1:]...) + i-- + } + } +} + +// removeColumnsFromSide remove the columns from determinant side of FDs in source. +// +// eg: {A B} --> {C} +// +// once B is a constant, whether values of c in difference rows have the same values or are all +// null is only determined by A, which can be used to simplify the strict FDs. +// +// Attention: why this reduction can not be applied to lax FDs? +// +// According to the lax definition, once determinant side have the null value, whatever dependencies +// would be. So let B be null value, once two row like: <1, null> and <1, null> (false interpreted), +// their dependencies may would be <3>, <4>, once we eliminate B here, FDs looks like: <1>,<1> lax +// determinate <3>,<4>. +func (e *fdEdge) removeColumnsFromSide(cons FastIntSet) bool { + if e.from.Intersects(cons) { + e.from = e.from.Difference(cons) + } + return e.isConstant() +} + +// isConstant returns whether this FD indicates a constant FD which means {} --> {...} +func (e *fdEdge) isConstant() bool { + return e.from.IsEmpty() +} + +// isEquivalence returns whether this FD indicates an equivalence FD which means {xyz...} == {xyz...} +func (e *fdEdge) isEquivalence() bool { + return e.equiv && e.from.Equals(e.to) +} + +// removeColumnsToSide remove the columns from dependencies side of FDs in source. +// +// eg: {A} --> {B, C} +// +// once B is a constant, only the C's value can be determined by A, this kind of irrelevant coefficient +// can be removed in the to side both for strict and lax FDs. +func (e *fdEdge) removeColumnsToSide(cons FastIntSet) bool { + if e.to.Intersects(cons) { + e.to = e.to.Difference(cons) + } + return e.to.IsEmpty() +} + +// ConstantCols returns the set of columns that will always have the same value for all rows in table. +func (s *FDSet) ConstantCols() FastIntSet { + for i := 0; i < len(s.fdEdges); i++ { + if s.fdEdges[i].isConstant() { + return s.fdEdges[i].to + } + } + return FastIntSet{} +} + +// EquivalenceCols returns the set of columns that are constrained to equal to each other. +func (s *FDSet) EquivalenceCols() (eqs []*FastIntSet) { + for i := 0; i < len(s.fdEdges); i++ { + if s.fdEdges[i].isEquivalence() { + // return either side is the same. + eqs = append(eqs, &s.fdEdges[i].from) + } + } + return eqs +} + +// MakeNotNull modify the FD set based the listed column with NOT NULL flags. +// Most of the case is used in the derived process after predicate evaluation, +// which can upgrade lax FDs to strict ones. +func (s *FDSet) MakeNotNull(notNullCols FastIntSet) { + notNullCols.UnionWith(s.NotNullCols) + notNullColsSet := s.closureOfEquivalence(notNullCols) + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + if fd.strict { + continue + } + // unique lax can be made strict only if determinant are not null. + if fd.from.SubsetOf(notNullColsSet) { + // we don't need to clean the old lax FD because when adding the corresponding strict one, the lax + // one will be implied by that and itself is removed. + s.AddStrictFunctionalDependency(fd.from, fd.to) + // add strict FDs will cause reconstruction of FDSet, re-traverse it. + i = -1 + } + } + s.NotNullCols = notNullColsSet +} + +// MakeNullable make the fd's NotNullCols to be cleaned, after the both side fds are handled it can be nullable. +func (s *FDSet) MakeNullable(nullableCols FastIntSet) { + s.NotNullCols.DifferenceWith(nullableCols) +} + +// MakeCartesianProduct records fdSet after the impact of Cartesian Product of (T1 x T2) is made. +// 1: left FD is reserved. +// 2: right FD is reserved. +// Actually, for two independent table, FDs won't affect (implies or something) each other, appending +// them together is adequate. But for constant FDs, according to our definition, we should merge them +// as a larger superset pointing themselves. +func (s *FDSet) MakeCartesianProduct(rhs *FDSet) { + for i := 0; i < len(rhs.fdEdges); i++ { + fd := rhs.fdEdges[i] + if fd.isConstant() { + // both from or to side is ok since {superset} --> {superset}. + s.AddConstants(fd.to) + } else { + s.fdEdges = append(s.fdEdges, fd) + } + } + // todo: add strict FD: (left key + right key) -> all cols. + // maintain a key? +} + +// MakeRestoreRule333 reset the status of how we deal with this rule. +func (s *FDSet) MakeRestoreRule333() { + for _, eg := range s.Rule333Equiv.Edges { + if eg.isConstant() { + s.AddConstants(eg.to) + } else { + s.AddEquivalence(eg.from, eg.to) + } + } + s.Rule333Equiv.Edges = nil + s.Rule333Equiv.InnerCols.Clear() +} + +// ArgOpts contains some arg used for FD maintenance. +type ArgOpts struct { + SkipFDRule331 bool + TypeFDRule331 TypeFilterFD331 + OnlyInnerFilter bool + InnerIsFalse bool +} + +// TypeFilterFD331 describes the type of the filter used in this rule. +type TypeFilterFD331 byte + +// Here's the two specific type. +const ( + SingleFD TypeFilterFD331 = 0 + CombinedFD TypeFilterFD331 = 1 +) + +// FindPrimaryKey checks whether there's a key in the current set which implies key -> all cols. +func (s FDSet) FindPrimaryKey() (*FastIntSet, bool) { + allCols := s.AllCols() + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + // Since we haven't maintained the key column, let's traverse every strict FD to judge with. + if fd.strict && !fd.equiv { + closure := s.closureOfStrict(fd.from) + if allCols.SubsetOf(closure) { + pk := NewFastIntSet() + pk.CopyFrom(fd.from) + return &pk, true + } + } + } + return nil, false +} + +// AllCols returns all columns in the current set. +func (s FDSet) AllCols() FastIntSet { + allCols := NewFastIntSet() + for i := 0; i < len(s.fdEdges); i++ { + allCols.UnionWith(s.fdEdges[i].from) + if !s.fdEdges[i].equiv { + allCols.UnionWith(s.fdEdges[i].to) + } + } + return allCols +} + +// AddFrom merges two FD sets by adding each FD from the given set to this set. +// Since two different tables may have some column ID overlap, we better use +// column unique ID to build the FDSet instead. +func (s *FDSet) AddFrom(fds *FDSet) { + for i := range fds.fdEdges { + fd := fds.fdEdges[i] + if fd.equiv { + s.addEquivalence(fd.from) + } else if fd.isConstant() { + s.AddConstants(fd.to) + } else if fd.strict { + s.AddStrictFunctionalDependency(fd.from, fd.to) + } else { + s.AddLaxFunctionalDependency(fd.from, fd.to) + } + } + s.NotNullCols.UnionWith(fds.NotNullCols) + if s.HashCodeToUniqueID == nil { + s.HashCodeToUniqueID = fds.HashCodeToUniqueID + } else { + for k, v := range fds.HashCodeToUniqueID { + if _, ok := s.HashCodeToUniqueID[k]; ok { + logutil.BgLogger().Warn("Error occurred when building the functional dependency") + continue + } + s.HashCodeToUniqueID[k] = v + } + } + for i, ok := fds.GroupByCols.Next(0); ok; i, ok = fds.GroupByCols.Next(i + 1) { + s.GroupByCols.Insert(i) + } + s.HasAggBuilt = fds.HasAggBuilt + s.Rule333Equiv = fds.Rule333Equiv +} + +// MaxOneRow will regard every column in the fdSet as a constant. Since constant is stronger that strict FD, it will +// take over all existed strict/lax FD, only keeping the equivalence. Because equivalence is stronger than constant. +// +// f: {a}--> {b,c}, {abc} == {abc} +// cols: {a,c} +// result: {} --> {a,c}, {a,c} == {a,c} +func (s *FDSet) MaxOneRow(cols FastIntSet) { + cnt := 0 + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + // non-equivalence FD, skip it. + if !fd.equiv { + continue + } + // equivalence: {superset} --> {superset} + if cols.Intersects(fd.from) { + s.fdEdges[cnt] = &fdEdge{ + from: fd.from.Intersection(cols), + to: fd.to.Intersection(cols), + strict: true, + equiv: true, + } + cnt++ + } + } + s.fdEdges = s.fdEdges[:cnt] + // At last, add the constant FD, {} --> {cols} + if !cols.IsEmpty() { + s.fdEdges = append(s.fdEdges, &fdEdge{ + to: cols, + strict: true, + }) + } +} + +// ProjectCols projects FDSet to the target columns +// Formula: +// Strict decomposition FD4A: If X −→ Y Z then X −→ Y and X −→ Z. +// Lax decomposition FD4B: If X ~→ Y Z and I(R) is Y-definite then X ~→ Z. +func (s *FDSet) ProjectCols(cols FastIntSet) { + // **************************************** START LOOP 1 ******************************************** + // Ensure the transitive relationship between remaining columns won't be lost. + // 1: record all the constant columns + // 2: if an FD's to side contain un-projected column, substitute it with its closure. + // fd1: {a} --> {b,c} + // fd2: {b} --> {d} + // when b is un-projected, the fd1 should be {a} --> {b,c's closure} which is {a} --> {b,c,d} + // 3: track all columns that have equivalent alternates that are part of the projection. + // fd1: {a} --> {c} + // fd2: {a,b} == {a,b} + // if only a is un-projected, the fd1 can actually be kept as {b} --> {c}. + var constCols, detCols, equivCols FastIntSet + for i := 0; i < len(s.fdEdges); i++ { + fd := s.fdEdges[i] + + if fd.isConstant() { + constCols = fd.to + } + + if !fd.to.SubsetOf(cols) { + // equivalence FD has been the closure as {superset} == {superset}. + if !fd.equiv && fd.strict { + // extended the `to` as it's complete closure, in case of missing some transitive FDs. + fd.to = s.closureOfStrict(fd.to.Union(fd.from)) + fd.to.DifferenceWith(fd.from) + } + } + + // {a,b} --> {c}, when b is un-projected, this FD should be handled latter, recording `b` here. + if !fd.equiv && !fd.from.SubsetOf(cols) { + detCols.UnionWith(fd.from.Difference(cols)) + } + + // equivalence {superset} == {superset} + if fd.equiv && fd.from.Intersects(cols) { + equivCols.UnionWith(fd.from) + } + } + // ****************************************** END LOOP 1 ******************************************** + + // find deleted columns with equivalence. + detCols.IntersectionWith(equivCols) + equivMap := s.makeEquivMap(detCols, cols) + + // it's actually maintained already. + if !constCols.IsEmpty() { + s.AddConstants(constCols) + } + + // **************************************** START LOOP 2 ******************************************** + // leverage the information collected in the loop1 above and try to do some FD substitution. + var ( + cnt int + newFDs []*fdEdge + ) + for i := range s.fdEdges { + fd := s.fdEdges[i] + + // step1: clear the `to` side + // subtract out un-projected columns from dependants. + // subtract out strict constant columns from dependants. + if !fd.to.SubsetOf(cols) { + // since loop 1 has computed the complete transitive closure for strict FD, now as: + // 1: equivalence FD: {superset} == {superset} + // 2: strict FD: {xxx} --> {complete closure} + // 3: lax FD: {xxx} ~~> {yyy} + if fd.equiv { + // As formula FD4A above, delete from un-projected column from `to` side directly. + fd.to = fd.to.Intersection(cols) + // Since from are the same, delete it too here. + fd.from = fd.from.Intersection(cols) + } else if fd.strict { + // As formula FD4A above, delete from un-projected column from `to` side directly. + fd.to = fd.to.Intersection(cols) + } else { + // As formula FD4B above, only if the deleted columns are definite, then we can keep it. + deletedCols := fd.to.Difference(cols) + if deletedCols.SubsetOf(constCols) { + fd.to = fd.to.Intersection(cols) + } else if deletedCols.SubsetOf(s.NotNullCols) { + fd.to = fd.to.Intersection(cols) + } else { + continue + } + } + + if !fd.isConstant() { + // clear the constant columns in the dependency of FD. + if fd.removeColumnsToSide(constCols) { + continue + } + } + if fd.removeColumnsToSide(fd.from) { + // fd.to side is empty, remove this FD. + continue + } + } + + // step2: clear the `from` side + // substitute the equivalence columns for removed determinant columns. + if !fd.from.SubsetOf(cols) { + // equivalence and constant FD couldn't be here. + deletedCols := fd.from.Difference(cols) + substitutedCols := NewFastIntSet() + foundAll := true + for c, ok := deletedCols.Next(0); ok; c, ok = deletedCols.Next(c + 1) { + // For every un-projected column, try to found their substituted column in projection list. + var id int + if id, foundAll = equivMap[c]; !foundAll { + break + } + substitutedCols.Insert(id) + } + if foundAll { + // deleted columns can be remapped using equivalencies. + from := fd.from.Union(substitutedCols) + from.DifferenceWith(deletedCols) + newFDs = append(newFDs, &fdEdge{ + from: from, + to: fd.to, + strict: fd.strict, + equiv: fd.equiv, + }) + } + continue + } + + if cnt != i { + s.fdEdges[cnt] = s.fdEdges[i] + } + cnt++ + } + s.fdEdges = s.fdEdges[:cnt] + // ****************************************** END LOOP 2 ******************************************** + + for i := range newFDs { + fd := newFDs[i] + if fd.equiv { + s.addEquivalence(fd.from) + } else if fd.isConstant() { + s.AddConstants(fd.to) + } else if fd.strict { + s.AddStrictFunctionalDependency(fd.from, fd.to) + } else { + s.AddLaxFunctionalDependency(fd.from, fd.to) + } + } +} + +// makeEquivMap try to find the equivalence column of every deleted column in the project list. +func (s *FDSet) makeEquivMap(detCols, projectedCols FastIntSet) map[int]int { + var equivMap map[int]int + for i, ok := detCols.Next(0); ok; i, ok = detCols.Next(i + 1) { + var oneCol FastIntSet + oneCol.Insert(i) + closure := s.closureOfEquivalence(oneCol) + closure.IntersectionWith(projectedCols) + // the column to be deleted has an equivalence column exactly in the project list. + if !closure.IsEmpty() { + if equivMap == nil { + equivMap = make(map[int]int) + } + id, _ := closure.Next(0) // We can record more equiv columns. + equivMap[i] = id + } + } + return equivMap +} + +// String returns format string of this FDSet. +func (s *FDSet) String() string { + var builder strings.Builder + + for i := range s.fdEdges { + if i != 0 { + builder.WriteString(", ") + } + builder.WriteString(s.fdEdges[i].String()) + } + return builder.String() +} + +// String returns format string of this FD. +func (e *fdEdge) String() string { + var b strings.Builder + if e.equiv { + if !e.strict { + logutil.BgLogger().Warn("Error occurred when building the functional dependency. We don't support lax equivalent columns") + return "Wrong functional dependency" + } + _, _ = fmt.Fprintf(&b, "%s==%s", e.from, e.to) + } else { + if e.strict { + _, _ = fmt.Fprintf(&b, "%s-->%s", e.from, e.to) + } else { + _, _ = fmt.Fprintf(&b, "%s~~>%s", e.from, e.to) + } + } + return b.String() +} + +// RegisterUniqueID is used to record the map relationship between expr and allocated uniqueID. +func (s *FDSet) RegisterUniqueID(hashCode string, uniqueID int) { + if len(hashCode) == 0 { + // shouldn't be here. + logutil.BgLogger().Warn("Error occurred when building the functional dependency") + return + } + if _, ok := s.HashCodeToUniqueID[hashCode]; ok { + // shouldn't be here. + logutil.BgLogger().Warn("Error occurred when building the functional dependency") + return + } + s.HashCodeToUniqueID[hashCode] = uniqueID +} + +// IsHashCodeRegistered checks whether the given hashcode has been registered in the current set. +func (s *FDSet) IsHashCodeRegistered(hashCode string) (int, bool) { + if uniqueID, ok := s.HashCodeToUniqueID[hashCode]; ok { + return uniqueID, true + } + return -1, false +} diff --git a/planner/funcdep/fd_graph_test.go b/planner/funcdep/fd_graph_test.go new file mode 100644 index 0000000000000..dbe49fb2d7103 --- /dev/null +++ b/planner/funcdep/fd_graph_test.go @@ -0,0 +1,333 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAddStrictFunctionalDependency(t *testing.T) { + fd := FDSet{ + fdEdges: []*fdEdge{}, + } + fe1 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> CDEFG + to: NewFastIntSet(3, 4, 5, 6, 7), + strict: true, + equiv: false, + } + fe2 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> CD + to: NewFastIntSet(3, 4), + strict: true, + equiv: false, + } + fe3 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> EF + to: NewFastIntSet(5, 6), + strict: true, + equiv: false, + } + // fd: AB -> CDEFG implies all of others. + assertF := func() { + require.Equal(t, len(fd.fdEdges), 1) + from := fd.fdEdges[0].from.SortedArray() + require.Equal(t, len(from), 2) + require.Equal(t, from[0], 1) + require.Equal(t, from[1], 2) + to := fd.fdEdges[0].to.SortedArray() + require.Equal(t, len(to), 5) + require.Equal(t, to[0], 3) + require.Equal(t, to[1], 4) + require.Equal(t, to[2], 5) + require.Equal(t, to[3], 6) + require.Equal(t, to[4], 7) + } + fd.AddStrictFunctionalDependency(fe1.from, fe1.to) + fd.AddStrictFunctionalDependency(fe2.from, fe2.to) + fd.AddStrictFunctionalDependency(fe3.from, fe3.to) + assertF() + + fd.fdEdges = fd.fdEdges[:0] + fd.AddStrictFunctionalDependency(fe2.from, fe2.to) + fd.AddStrictFunctionalDependency(fe1.from, fe1.to) + fd.AddStrictFunctionalDependency(fe3.from, fe3.to) + assertF() + + // TODO: + // test reduce col + // test more edges +} + +// Preface Notice: +// For test convenience, we add fdEdge to fdSet directly which is not valid in the procedure. +// Because two difference fdEdge in the fdSet may imply each other which is strictly not permitted in the procedure. +// Use `AddStrictFunctionalDependency` to add the fdEdge to the fdSet in the formal way . +func TestFDSet_ClosureOf(t *testing.T) { + fd := FDSet{ + fdEdges: []*fdEdge{}, + } + fe1 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> CD + to: NewFastIntSet(3, 4), + strict: true, + equiv: false, + } + fe2 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> EF + to: NewFastIntSet(5, 6), + strict: true, + equiv: false, + } + fe3 := &fdEdge{ + from: NewFastIntSet(2), // B -> FG + to: NewFastIntSet(6, 7), + strict: true, + equiv: false, + } + fe4 := &fdEdge{ + from: NewFastIntSet(1), // A -> DEH + to: NewFastIntSet(4, 5, 8), + strict: true, + equiv: false, + } + fd.fdEdges = append(fd.fdEdges, fe1, fe2, fe3, fe4) + // A -> ADEH + closure := fd.closureOfStrict(NewFastIntSet(1)).SortedArray() + require.Equal(t, len(closure), 4) + require.Equal(t, closure[0], 1) + require.Equal(t, closure[1], 4) + require.Equal(t, closure[2], 5) + require.Equal(t, closure[3], 8) + // AB -> ABCDEFGH + fd.fdEdges = append(fd.fdEdges, fe1, fe2, fe3, fe4) + closure = fd.closureOfStrict(NewFastIntSet(1, 2)).SortedArray() + require.Equal(t, len(closure), 8) + require.Equal(t, closure[0], 1) + require.Equal(t, closure[1], 2) + require.Equal(t, closure[2], 3) + require.Equal(t, closure[3], 4) + require.Equal(t, closure[4], 5) + require.Equal(t, closure[5], 6) + require.Equal(t, closure[6], 7) + require.Equal(t, closure[7], 8) +} + +func TestFDSet_ReduceCols(t *testing.T) { + fd := FDSet{ + fdEdges: []*fdEdge{}, + } + fe1 := &fdEdge{ + from: NewFastIntSet(1), // A -> CD + to: NewFastIntSet(3, 4), + strict: true, + equiv: false, + } + fe2 := &fdEdge{ + from: NewFastIntSet(3), // C -> DE + to: NewFastIntSet(4, 5), + strict: true, + equiv: false, + } + fe3 := &fdEdge{ + from: NewFastIntSet(3, 5), // CE -> B + to: NewFastIntSet(2), + strict: true, + equiv: false, + } + fd.fdEdges = append(fd.fdEdges, fe1, fe2, fe3) + res := fd.ReduceCols(NewFastIntSet(1, 2)).SortedArray() + require.Equal(t, len(res), 1) + require.Equal(t, res[0], 1) +} + +func TestFDSet_InClosure(t *testing.T) { + fd := FDSet{ + fdEdges: []*fdEdge{}, + } + fe1 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> CD + to: NewFastIntSet(3, 4), + strict: true, + equiv: false, + } + fe2 := &fdEdge{ + from: NewFastIntSet(1, 2), // AB -> EF + to: NewFastIntSet(5, 6), + strict: true, + equiv: false, + } + fe3 := &fdEdge{ + from: NewFastIntSet(2), // B -> FG + to: NewFastIntSet(6, 7), + strict: true, + equiv: false, + } + fd.fdEdges = append(fd.fdEdges, fe1, fe2, fe3) + // A -> F : false (determinants should not be torn apart) + require.False(t, fd.InClosure(NewFastIntSet(1), NewFastIntSet(6))) + // B -> G : true (dependency can be torn apart) + require.True(t, fd.InClosure(NewFastIntSet(2), NewFastIntSet(7))) + // AB -> E : true (dependency can be torn apart) + require.True(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(5))) + // AB -> FG: true (in closure node set) + require.True(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(6, 7))) + // AB -> DF: true (in closure node set) + require.True(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(4, 6))) + // AB -> EG: true (in closure node set) + require.True(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(5, 7))) + // AB -> EGH: false (H is not in closure node set) + require.False(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(5, 7, 8))) + + fe4 := &fdEdge{ + from: NewFastIntSet(2), // B -> CH + to: NewFastIntSet(3, 8), + strict: true, + equiv: false, + } + fd.fdEdges = append(fd.fdEdges, fe4) + // AB -> EGH: true (in closure node set) + require.True(t, fd.InClosure(NewFastIntSet(1, 2), NewFastIntSet(5, 7, 8))) +} + +func TestFDSet_AddConstant(t *testing.T) { + fd := FDSet{} + require.Equal(t, "()", fd.ConstantCols().String()) + + fd.AddConstants(NewFastIntSet(1, 2)) // {} --> {a,b} + require.Equal(t, len(fd.fdEdges), 1) + require.True(t, fd.fdEdges[0].strict) + require.False(t, fd.fdEdges[0].equiv) + require.Equal(t, "()", fd.fdEdges[0].from.String()) + require.Equal(t, "(1,2)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1,2)", fd.ConstantCols().String()) + + fd.AddConstants(NewFastIntSet(3)) // c, {} --> {a,b,c} + require.Equal(t, len(fd.fdEdges), 1) + require.True(t, fd.fdEdges[0].strict) + require.False(t, fd.fdEdges[0].equiv) + require.Equal(t, "()", fd.fdEdges[0].from.String()) + require.Equal(t, "(1-3)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1-3)", fd.ConstantCols().String()) + + fd.AddStrictFunctionalDependency(NewFastIntSet(3, 4), NewFastIntSet(5, 6)) // {c,d} --> {e,f} + require.Equal(t, len(fd.fdEdges), 2) + require.True(t, fd.fdEdges[0].strict) + require.False(t, fd.fdEdges[0].equiv) + require.Equal(t, "()", fd.fdEdges[0].from.String()) + require.Equal(t, "(1-3)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1-3)", fd.ConstantCols().String()) + require.True(t, fd.fdEdges[1].strict) + require.False(t, fd.fdEdges[1].equiv) + require.Equal(t, "(4)", fd.fdEdges[1].from.String()) // determinant 3 reduced as constant, leaving FD {d} --> {f,g}. + require.Equal(t, "(5,6)", fd.fdEdges[1].to.String()) + + fd.AddLaxFunctionalDependency(NewFastIntSet(7), NewFastIntSet(5, 6)) // {g} ~~> {e,f} + require.Equal(t, len(fd.fdEdges), 3) + require.False(t, fd.fdEdges[2].strict) + require.False(t, fd.fdEdges[2].equiv) + require.Equal(t, "(7)", fd.fdEdges[2].from.String()) + require.Equal(t, "(5,6)", fd.fdEdges[2].to.String()) + + fd.AddConstants(NewFastIntSet(4)) // add d, {} --> {a,b,c,d}, and FD {d} --> {f,g} is transferred to constant closure. + require.Equal(t, 1, len(fd.fdEdges)) // => {} --> {a,b,c,d,e,f}, for lax FD {g} ~~> {e,f}, dependencies are constants, removed. + require.True(t, fd.fdEdges[0].strict) + require.False(t, fd.fdEdges[0].equiv) + require.Equal(t, "()", fd.fdEdges[0].from.String()) + require.Equal(t, "(1-6)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1-6)", fd.ConstantCols().String()) +} + +func TestFDSet_LaxImplies(t *testing.T) { + fd := FDSet{} + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(2, 3)) + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(2)) + // lax FD won't imply each other once they have the different to side. + require.Equal(t, "(1)~~>(2,3), (1)~~>(2)", fd.String()) + + fd = FDSet{} + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(2)) + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(2, 3)) + require.Equal(t, "(1)~~>(2), (1)~~>(2,3)", fd.String()) + + fd = FDSet{} + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(3)) + fd.AddLaxFunctionalDependency(NewFastIntSet(1, 2), NewFastIntSet(3)) + // lax FD can imply each other once they have the same to side. {1,2} ~~> {3} implies {1} ~~> {3} + require.Equal(t, "(1)~~>(3)", fd.String()) + + fd = FDSet{} + fd.AddLaxFunctionalDependency(NewFastIntSet(1), NewFastIntSet(3, 4)) + fd.AddLaxFunctionalDependency(NewFastIntSet(1, 2), NewFastIntSet(3)) + // lax FD won't imply each other once they have the different to side. {1,2} ~~> {3} implies {1} ~~> {3} + require.Equal(t, "(1)~~>(3,4), (1,2)~~>(3)", fd.String()) +} + +func TestFDSet_AddEquivalence(t *testing.T) { + fd := FDSet{} + require.Equal(t, 0, len(fd.EquivalenceCols())) + + fd.AddEquivalence(NewFastIntSet(1), NewFastIntSet(2)) // {a} == {b} + require.Equal(t, 1, len(fd.fdEdges)) // res: {a} == {b} + require.Equal(t, 1, len(fd.EquivalenceCols())) + require.True(t, fd.fdEdges[0].strict) + require.True(t, fd.fdEdges[0].equiv) + require.Equal(t, "(1,2)", fd.fdEdges[0].from.String()) + require.Equal(t, "(1,2)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1,2)", fd.EquivalenceCols()[0].String()) + + fd.AddEquivalence(NewFastIntSet(3), NewFastIntSet(4)) // {c} == {d} + require.Equal(t, 2, len(fd.fdEdges)) // res: {a,b} == {a,b}, {c,d} == {c,d} + require.Equal(t, 2, len(fd.EquivalenceCols())) + require.True(t, fd.fdEdges[0].strict) + require.True(t, fd.fdEdges[0].equiv) + require.Equal(t, "(1,2)", fd.fdEdges[0].from.String()) + require.Equal(t, "(1,2)", fd.fdEdges[0].to.String()) + require.Equal(t, "(1,2)", fd.EquivalenceCols()[0].String()) + require.True(t, fd.fdEdges[1].strict) + require.True(t, fd.fdEdges[1].equiv) + require.Equal(t, "(3,4)", fd.fdEdges[1].from.String()) + require.Equal(t, "(3,4)", fd.fdEdges[1].to.String()) + require.Equal(t, "(3,4)", fd.EquivalenceCols()[1].String()) + + fd.AddConstants(NewFastIntSet(4, 5)) // {} --> {d,e} + require.Equal(t, 3, len(fd.fdEdges)) // res: {a,b} == {a,b}, {c,d} == {c,d},{} --> {c,d,e} + require.True(t, fd.fdEdges[2].strict) // explain: constant closure is extended by equivalence {c,d} == {c,d} + require.False(t, fd.fdEdges[2].equiv) + require.Equal(t, "()", fd.fdEdges[2].from.String()) + require.Equal(t, "(3-5)", fd.fdEdges[2].to.String()) + require.Equal(t, "(3-5)", fd.ConstantCols().String()) + + fd.AddStrictFunctionalDependency(NewFastIntSet(2, 3), NewFastIntSet(5, 6)) // {b,c} --> {e,f} + require.Equal(t, 4, len(fd.fdEdges)) // res: {a,b} == {a,b}, {c,d} == {c,d},{} --> {c,d,e}, {b} --> {e,f} + require.True(t, fd.fdEdges[3].strict) // explain: strict FD's from side c is eliminated by constant closure. + require.False(t, fd.fdEdges[3].equiv) + require.Equal(t, "(2)", fd.fdEdges[3].from.String()) + require.Equal(t, "(5,6)", fd.fdEdges[3].to.String()) + + fd.AddEquivalence(NewFastIntSet(2), NewFastIntSet(3)) // {b} == {d} + // res: {a,b,c,d} == {a,b,c,d}, {} --> {a,b,c,d,e,f} + // explain: + // b = d build the connection between {a,b} == {a,b}, {c,d} == {c,d}, make the superset of equivalence closure. + // the superset equivalence closure extend the existed constant closure in turn, resulting {} --> {a,b,c,d,e} + // the superset constant closure eliminate existed strict FD, since determinants is constant, so the dependencies must be constant as well. + // so extending the current constant closure as to {} --> {a,b,c,d,e,f} + require.Equal(t, 2, len(fd.fdEdges)) + require.Equal(t, 1, len(fd.EquivalenceCols())) + require.Equal(t, "(1-4)", fd.EquivalenceCols()[0].String()) + require.Equal(t, "(1-6)", fd.ConstantCols().String()) +} diff --git a/planner/funcdep/main_test.go b/planner/funcdep/main_test.go new file mode 100644 index 0000000000000..0a3b3828fda20 --- /dev/null +++ b/planner/funcdep/main_test.go @@ -0,0 +1,32 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package funcdep + +import ( + "testing" + + "github.com/pingcap/tidb/util/testbridge" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) +} diff --git a/planner/implementation/main_test.go b/planner/implementation/main_test.go index b7a2088709314..167a9c51880ac 100644 --- a/planner/implementation/main_test.go +++ b/planner/implementation/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/planner/memo/main_test.go b/planner/memo/main_test.go index 784f011a9ddee..404c80d45df11 100644 --- a/planner/memo/main_test.go +++ b/planner/memo/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/planner/optimize.go b/planner/optimize.go index b16fc09a238f0..fcf58000a2976 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -18,6 +18,7 @@ import ( "context" "fmt" "math" + "math/rand" "runtime/trace" "strings" "sync" @@ -45,32 +46,14 @@ import ( "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/logutil" utilparser "github.com/pingcap/tidb/util/parser" + "github.com/pingcap/tidb/util/topsql" "go.uber.org/zap" ) -// GetPreparedStmt extract the prepared statement from the execute statement. -func GetPreparedStmt(stmt *ast.ExecuteStmt, vars *variable.SessionVars) (*plannercore.CachedPrepareStmt, error) { - var ok bool - execID := stmt.ExecID - if stmt.Name != "" { - if execID, ok = vars.PreparedStmtNameToID[stmt.Name]; !ok { - return nil, plannercore.ErrStmtNotFound - } - } - if preparedPointer, ok := vars.PreparedStmts[execID]; ok { - preparedObj, ok := preparedPointer.(*plannercore.CachedPrepareStmt) - if !ok { - return nil, errors.Errorf("invalid CachedPrepareStmt type") - } - return preparedObj, nil - } - return nil, plannercore.ErrStmtNotFound -} - // IsReadOnly check whether the ast.Node is a read only statement. func IsReadOnly(node ast.Node, vars *variable.SessionVars) bool { if execStmt, isExecStmt := node.(*ast.ExecuteStmt); isExecStmt { - prepareStmt, err := GetPreparedStmt(execStmt, vars) + prepareStmt, err := plannercore.GetPreparedStmt(execStmt, vars) if err != nil { logutil.BgLogger().Warn("GetPreparedStmt failed", zap.Error(err)) return false @@ -99,15 +82,6 @@ func GetExecuteForUpdateReadIS(node ast.Node, sctx sessionctx.Context) infoschem return nil } -// GetBindSQL4PlanCache used to get the bindSQL for plan cache to build the plan cache key. -func GetBindSQL4PlanCache(sctx sessionctx.Context, stmtNode ast.StmtNode) (bindSQL string) { - bindRecord, _, match := matchSQLBinding(sctx, stmtNode) - if match { - bindSQL = bindRecord.Bindings[0].BindSQL - } - return bindSQL -} - func matchSQLBinding(sctx sessionctx.Context, stmtNode ast.StmtNode) (bindRecord *bindinfo.BindRecord, scope string, matched bool) { useBinding := sctx.GetSessionVars().UsePlanBaselines if !useBinding || stmtNode == nil { @@ -126,6 +100,16 @@ func matchSQLBinding(sctx sessionctx.Context, stmtNode ast.StmtNode) (bindRecord func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is infoschema.InfoSchema) (plannercore.Plan, types.NameSlice, error) { sessVars := sctx.GetSessionVars() + if !sctx.GetSessionVars().InRestrictedSQL && variable.RestrictedReadOnly.Load() || variable.VarTiDBSuperReadOnly.Load() { + allowed, err := allowInReadOnlyMode(sctx, node) + if err != nil { + return nil, nil, err + } + if !allowed { + return nil, nil, errors.Trace(core.ErrSQLInReadOnlyMode) + } + } + // Because for write stmt, TiFlash has a different results when lock the data in point get plan. We ban the TiFlash // engine in not read only stmt. if _, isolationReadContainTiFlash := sessVars.IsolationReadEngines[kv.TiFlash]; isolationReadContainTiFlash && !IsReadOnly(node, sessVars) { @@ -193,7 +177,7 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in originHints := hint.CollectHint(stmtNode) // bindRecord must be not nil when coming here, try to find the best binding. for _, binding := range bindRecord.Bindings { - if binding.Status != bindinfo.Using { + if !binding.IsBindingEnabled() { continue } metrics.BindUsageCounter.WithLabelValues(scope).Inc() @@ -338,12 +322,22 @@ func optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in failpoint.Return(nil, nil, 0, errors.New("gofail wrong optimizerCnt error")) } }) + failpoint.Inject("mockHighLoadForOptimize", func() { + sqlPrefixes := []string{"select"} + topsql.MockHighCPULoad(sctx.GetSessionVars().StmtCtx.OriginalSQL, sqlPrefixes, 10) + }) + // build logical plan sctx.GetSessionVars().PlanID = 0 sctx.GetSessionVars().PlanColumnID = 0 + sctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = nil hintProcessor := &hint.BlockHintProcessor{Ctx: sctx} node.Accept(hintProcessor) + failpoint.Inject("mockRandomPlanID", func() { + sctx.GetSessionVars().PlanID = rand.Intn(1000) // nolint:gosec + }) + builder := planBuilderPool.Get().(*plannercore.PlanBuilder) defer planBuilderPool.Put(builder.ResetForReuse()) @@ -374,16 +368,6 @@ func optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in return nil, nil, 0, err } - if !sctx.GetSessionVars().InRestrictedSQL && variable.RestrictedReadOnly.Load() { - allowed, err := allowInReadOnlyMode(sctx, node) - if err != nil { - return nil, nil, 0, err - } - if !allowed { - return nil, nil, 0, errors.Trace(core.ErrSQLInReadOnlyMode) - } - } - // Handle the execute statement. if execPlan, ok := p.(*plannercore.Execute); ok { err := execPlan.OptimizePreparedPlan(ctx, sctx, is) @@ -410,7 +394,8 @@ func optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in return finalPlan, names, cost, err } -func extractSelectAndNormalizeDigest(stmtNode ast.StmtNode, specifiledDB string) (ast.StmtNode, string, string, error) { +// ExtractSelectAndNormalizeDigest extract the select statement and normalize it. +func ExtractSelectAndNormalizeDigest(stmtNode ast.StmtNode, specifiledDB string) (ast.StmtNode, string, string, error) { switch x := stmtNode.(type) { case *ast.ExplainStmt: // This function is only used to find bind record. @@ -465,14 +450,14 @@ func getBindRecord(ctx sessionctx.Context, stmt ast.StmtNode) (*bindinfo.BindRec if ctx.Value(bindinfo.SessionBindInfoKeyType) == nil { return nil, "", nil } - stmtNode, normalizedSQL, hash, err := extractSelectAndNormalizeDigest(stmt, ctx.GetSessionVars().CurrentDB) + stmtNode, normalizedSQL, hash, err := ExtractSelectAndNormalizeDigest(stmt, ctx.GetSessionVars().CurrentDB) if err != nil || stmtNode == nil { return nil, "", err } sessionHandle := ctx.Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle) - bindRecord := sessionHandle.GetBindRecord(normalizedSQL, "") + bindRecord := sessionHandle.GetBindRecord(hash, normalizedSQL, "") if bindRecord != nil { - if bindRecord.HasUsingBinding() { + if bindRecord.HasEnabledBinding() { return bindRecord, metrics.ScopeSession, nil } return nil, "", nil @@ -618,6 +603,7 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin setVarsOffs = append(setVarsOffs, i) } } + stmtHints.OriginalTableHints = hints stmtHints.SetVars = setVars // Handle MEMORY_QUOTA @@ -697,7 +683,7 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin stmtHints.ForceNthPlan = forceNthPlan.HintData.(int64) if stmtHints.ForceNthPlan < 1 { stmtHints.ForceNthPlan = -1 - warn := errors.Errorf("the hintdata for NTH_PLAN() is too small, hint ignored.") + warn := errors.Errorf("the hintdata for NTH_PLAN() is too small, hint ignored") warns = append(warns, warn) } } else { @@ -719,6 +705,5 @@ func setFoundInBinding(sctx sessionctx.Context, opt bool, bindSQL string) error func init() { plannercore.OptimizeAstNode = Optimize - plannercore.GetBindSQL4PlanCache = GetBindSQL4PlanCache plannercore.IsReadOnly = IsReadOnly } diff --git a/planner/property/physical_property.go b/planner/property/physical_property.go index 1e6e3aaeefae1..04c91fe664bbd 100644 --- a/planner/property/physical_property.go +++ b/planner/property/physical_property.go @@ -18,10 +18,12 @@ import ( "bytes" "fmt" + "github.com/pingcap/log" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tipb/go-tipb" ) // wholeTaskTypes records all possible kinds of task that a plan can return. For Agg, TopN and Limit, we will try to get @@ -51,8 +53,25 @@ const ( BroadcastType // HashType requires current task to shuffle its data according to some columns. HashType + // SinglePartitionType requires all the task pass the data to one node (tidb/tiflash). + SinglePartitionType ) +// ToExchangeType generates ExchangeType from MPPPartitionType +func (t MPPPartitionType) ToExchangeType() tipb.ExchangeType { + switch t { + case BroadcastType: + return tipb.ExchangeType_Broadcast + case HashType: + return tipb.ExchangeType_Hash + case SinglePartitionType: + return tipb.ExchangeType_PassThrough + default: + log.Warn("generate an exchange with any partition type, which is illegal.") + return tipb.ExchangeType_PassThrough + } +} + // MPPPartitionColumn is the column that will be used in MPP Hash Exchange type MPPPartitionColumn struct { Col *expression.Column @@ -205,7 +224,7 @@ func (p *PhysicalProperty) AllColsFromSchema(schema *expression.Schema) bool { // IsFlashProp return true if this physical property is only allowed to generate flash related task func (p *PhysicalProperty) IsFlashProp() bool { - return p.TaskTp == CopTiFlashLocalReadTaskType || p.TaskTp == CopTiFlashGlobalReadTaskType || p.TaskTp == MppTaskType + return p.TaskTp == MppTaskType } // GetAllPossibleChildTaskTypes enumrates the possible types of tasks for children. diff --git a/planner/property/task_type.go b/planner/property/task_type.go index 1bc825795ed5f..a4c16d4a51d2e 100644 --- a/planner/property/task_type.go +++ b/planner/property/task_type.go @@ -29,17 +29,6 @@ const ( // coprocessor layer. CopDoubleReadTaskType - // CopTiFlashLocalReadTaskType stands for flash coprocessor that read data locally, - // and only a part of the data is read in one cop task, if the current task type is - // CopTiFlashLocalReadTaskType, all its children prop's task type is CopTiFlashLocalReadTaskType - CopTiFlashLocalReadTaskType - - // CopTiFlashGlobalReadTaskType stands for flash coprocessor that read data globally - // and all the data of given table will be read in one cop task, if the current task - // type is CopTiFlashGlobalReadTaskType, all its children prop's task type is - // CopTiFlashGlobalReadTaskType - CopTiFlashGlobalReadTaskType - // MppTaskType stands for task that would run on Mpp nodes, currently meaning the tiflash node. MppTaskType ) @@ -53,10 +42,6 @@ func (t TaskType) String() string { return "copSingleReadTask" case CopDoubleReadTaskType: return "copDoubleReadTask" - case CopTiFlashLocalReadTaskType: - return "copTiFlashLocalReadTask" - case CopTiFlashGlobalReadTaskType: - return "copTiFlashGlobalReadTask" case MppTaskType: return "mppTask" } diff --git a/planner/util/main_test.go b/planner/util/main_test.go index 1b930670688d0..d78129a7fa1b3 100644 --- a/planner/util/main_test.go +++ b/planner/util/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/planner/util/path.go b/planner/util/path.go index 9a0b4207d1314..0c0783926ff28 100644 --- a/planner/util/path.go +++ b/planner/util/path.go @@ -54,9 +54,6 @@ type AccessPath struct { IsDNFCond bool - // IsTiFlashGlobalRead indicates whether this path is a remote read path for tiflash - IsTiFlashGlobalRead bool - // IsIntHandlePath indicates whether this path is table path. IsIntHandlePath bool IsCommonHandlePath bool @@ -64,6 +61,9 @@ type AccessPath struct { Forced bool // IsSingleScan indicates whether the path is a single index/table scan or table access after index scan. IsSingleScan bool + + // Maybe added in model.IndexInfo better, but the cache of model.IndexInfo may lead side effect + IsUkShardIndexPath bool } // IsTablePath returns true if it's IntHandlePath or CommonHandlePath. diff --git a/planner/util/path_test.go b/planner/util/path_test.go index 9268ad81f6a23..d3603845aa737 100644 --- a/planner/util/path_test.go +++ b/planner/util/path_test.go @@ -71,9 +71,9 @@ func TestCompareCol2Len(t *testing.T) { }, } for _, tt := range tests { - res, comparable := util.CompareCol2Len(tt.c1, tt.c2) + res, comparable1 := util.CompareCol2Len(tt.c1, tt.c2) require.Equal(t, tt.res, res) - require.Equal(t, tt.comparable, comparable) + require.Equal(t, tt.comparable, comparable1) } } diff --git a/plugin/conn_ip_example/conn_ip_example.go b/plugin/conn_ip_example/conn_ip_example.go index a5b806aa67ae2..f6d09ffc5c612 100644 --- a/plugin/conn_ip_example/conn_ip_example.go +++ b/plugin/conn_ip_example/conn_ip_example.go @@ -30,6 +30,7 @@ var connection int32 // Validate implements TiDB plugin's Validate SPI. // It is called before OnInit +// nolint: unused, deadcode func Validate(ctx context.Context, m *plugin.Manifest) error { fmt.Println("## conn_ip_example Validate called ##") fmt.Printf("---- context: %s\n", ctx) @@ -37,6 +38,7 @@ func Validate(ctx context.Context, m *plugin.Manifest) error { } // OnInit implements TiDB plugin's OnInit SPI. +// nolint: unused, deadcode func OnInit(ctx context.Context, manifest *plugin.Manifest) error { fmt.Println("## conn_ip_example OnInit called ##") fmt.Printf("---- context: %s\n", ctx) @@ -78,6 +80,7 @@ func OnInit(ctx context.Context, manifest *plugin.Manifest) error { } // OnShutdown implements TiDB plugin's OnShutdown SPI. +// nolint: unused, deadcode func OnShutdown(ctx context.Context, manifest *plugin.Manifest) error { fmt.Println("## conn_ip_example OnShutdown called ##") fmt.Printf("---- context: %s\n", ctx) @@ -87,6 +90,7 @@ func OnShutdown(ctx context.Context, manifest *plugin.Manifest) error { } // OnGeneralEvent implements TiDB Audit plugin's OnGeneralEvent SPI. +// nolint: unused, deadcode func OnGeneralEvent(ctx context.Context, sctx *variable.SessionVars, event plugin.GeneralEvent, cmd string) { fmt.Println("## conn_ip_example OnGeneralEvent called ##") if sctx != nil { @@ -112,6 +116,7 @@ func OnGeneralEvent(ctx context.Context, sctx *variable.SessionVars, event plugi } // OnConnectionEvent implements TiDB Audit plugin's OnConnectionEvent SPI. +// nolint: unused, deadcode func OnConnectionEvent(ctx context.Context, event plugin.ConnectionEvent, info *variable.ConnectionInfo) error { var reason string if r := ctx.Value(plugin.RejectReasonCtxValue{}); r != nil { diff --git a/plugin/conn_ip_example/main_test.go b/plugin/conn_ip_example/main_test.go index 640b8d3aa5108..fb7995913f593 100644 --- a/plugin/conn_ip_example/main_test.go +++ b/plugin/conn_ip_example/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/plugin/integration_test.go b/plugin/integration_test.go index eac32e58707df..bf6eafc99a40d 100644 --- a/plugin/integration_test.go +++ b/plugin/integration_test.go @@ -50,6 +50,7 @@ func TestAuditLogNormal(t *testing.T) { tables string cmd string event plugin.GeneralEvent + resCnt int } tests := []normalTest{ @@ -189,14 +190,14 @@ func TestAuditLogNormal(t *testing.T) { sql: "DROP SESSION BINDING FOR SELECT * FROM t1 WHERE a = 123", stmtType: "DropBinding", }, - //{ + // { // sql: "LOAD STATS '/tmp/stats.json'", // stmtType: "other", - //}, - //{ + // }, + // { // sql: "DROP STATS t", // stmtType: "other", - //}, + // }, { sql: "RENAME TABLE t2 TO t5", stmtType: "other", @@ -209,18 +210,18 @@ func TestAuditLogNormal(t *testing.T) { dbs: "test", tables: "t1", }, - //{ + // { // sql: "FLASHBACK TABLE t TO t1", // stmtType: "other", // dbs: "test", // tables: "t1", - //}, - //{ + // }, + // { // sql: "RECOVER TABLE t1", // stmtType: "other", // dbs: "test", // tables: "t1,t2", - //}, + // }, { sql: "ALTER DATABASE test DEFAULT CHARACTER SET = utf8mb4", stmtType: "other", @@ -230,20 +231,20 @@ func TestAuditLogNormal(t *testing.T) { sql: "ADMIN RELOAD opt_rule_blacklist", stmtType: "other", }, - //{ + // { // sql: "ADMIN PLUGINS ENABLE audit_test", // stmtType: "other", - //}, + // }, { sql: "ADMIN FLUSH bindings", stmtType: "other", }, - //{ + // { // sql: "ADMIN REPAIR TABLE t1 CREATE TABLE (id int)", // stmtType: "other", // dbs: "test", // tables: "t1", - //}, + // }, { sql: "ADMIN SHOW SLOW RECENT 10", stmtType: "other", @@ -252,27 +253,27 @@ func TestAuditLogNormal(t *testing.T) { sql: "ADMIN SHOW DDL JOBS", stmtType: "other", }, - //{ + // { // sql: "ADMIN CANCEL DDL JOBS 1", // stmtType: "other", - //}, + // }, { sql: "ADMIN CHECKSUM TABLE t1", stmtType: "other", - //dbs: "test", - //tables: "t1", + // dbs: "test", + // tables: "t1", }, { sql: "ADMIN CHECK TABLE t1", stmtType: "other", - //dbs: "test", - //tables: "t1", + // dbs: "test", + // tables: "t1", }, { sql: "ADMIN CHECK INDEX t1 a", stmtType: "other", - //dbs: "test", - //tables: "t1", + // dbs: "test", + // tables: "t1", }, { sql: "CREATE USER 'newuser' IDENTIFIED BY 'newuserpassword'", @@ -316,10 +317,10 @@ func TestAuditLogNormal(t *testing.T) { sql: "SET PASSWORD FOR 'newuser' = 'test'", stmtType: "Set", }, - //{ + // { // sql: "SET ROLE ALL", // stmtType: "other", - //}, + // }, { sql: "DROP USER 'newuser'", stmtType: "other", @@ -333,26 +334,26 @@ func TestAuditLogNormal(t *testing.T) { { sql: "SPLIT TABLE t1 BETWEEN (0) AND (1000000000) REGIONS 16", stmtType: "other", - //dbs: "test", - //tables: "t1", + // dbs: "test", + // tables: "t1", }, - //{ + // { // sql: "BACKUP DATABASE `test` TO '.'", // stmtType: "other", // dbs: "test", - //}, - //{ + // }, + // { // sql: "RESTORE DATABASE * FROM '.'", // stmtType: "other", - //}, - //{ + // }, + // { // sql: "CHANGE DRAINER TO NODE_STATE ='paused' FOR NODE_ID 'drainer1'", // stmtType: "other", - //}, - //{ + // }, + // { // sql: "CHANGE PUMP TO NODE_STATE ='paused' FOR NODE_ID 'pump1'", // stmtType: "other", - //}, + // }, { sql: "BEGIN", stmtType: "Begin", @@ -369,30 +370,30 @@ func TestAuditLogNormal(t *testing.T) { sql: "COMMIT", stmtType: "Commit", }, - //{ + // { // sql: "SHOW DRAINER STATUS", // stmtType: "Show", - //}, - //{ + // }, + // { // sql: "SHOW PUMP STATUS", // stmtType: "Show", - //}, - //{ + // }, + // { // sql: "SHOW GRANTS", // stmtType: "Show", - //}, + // }, { sql: "SHOW PROCESSLIST", stmtType: "Show", }, - //{ + // { // sql: "SHOW BACKUPS", // stmtType: "Show", - //}, - //{ + // }, + // { // sql: "SHOW RESTORES", // stmtType: "Show", - //}, + // }, { sql: "show analyze status", stmtType: "Show", @@ -421,10 +422,10 @@ func TestAuditLogNormal(t *testing.T) { sql: "show fields from t1", stmtType: "Show", }, - //{ + // { // sql: "SHOW CONFIG", // stmtType: "Show", - //}, + // }, { sql: "SHOW CREATE TABLE t1", stmtType: "Show", @@ -467,10 +468,10 @@ func TestAuditLogNormal(t *testing.T) { sql: "SHOW PROFILES", stmtType: "Show", }, - //{ + // { // sql: "SHOW PUMP STATUS", // stmtType: "Show", - //}, + // }, { sql: "SHOW SCHEMAS", stmtType: "Show", @@ -507,6 +508,7 @@ func TestAuditLogNormal(t *testing.T) { { sql: "SHOW TABLE STATUS LIKE 't1'", stmtType: "Show", + resCnt: 3, // Start + SHOW TABLE + Internal SELECT .. FROM IS.TABLES in current session }, { sql: "SHOW TABLES", @@ -585,12 +587,12 @@ func TestAuditLogNormal(t *testing.T) { sql: "DO 1", stmtType: "other", }, - //{ + // { // sql: "LOAD DATA LOCAL INFILE 'data.csv' INTO TABLE t1 FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES (id)", // stmtType: "LoadData", // dbs: "test", // tables: "t1", - //}, + // }, { sql: "SELECT * FROM t1", stmtType: "Select", @@ -609,39 +611,39 @@ func TestAuditLogNormal(t *testing.T) { }, { sql: "EXPLAIN ANALYZE SELECT * FROM t1 WHERE a = 1", - stmtType: "Explain", - //dbs: "test", - //tables: "t1", + stmtType: "ExplainAnalyzeSQL", + // dbs: "test", + // tables: "t1", }, { sql: "EXPLAIN SELECT * FROM t1", - stmtType: "Explain", - //dbs: "test", - //tables: "t1", + stmtType: "ExplainSQL", + // dbs: "test", + // tables: "t1", }, { sql: "EXPLAIN SELECT * FROM t1 WHERE a = 1", - stmtType: "Explain", - //dbs: "test", - //tables: "t1", + stmtType: "ExplainSQL", + // dbs: "test", + // tables: "t1", }, { sql: "DESC SELECT * FROM t1 WHERE a = 1", - stmtType: "Explain", - //dbs: "test", - //tables: "t1", + stmtType: "ExplainSQL", + // dbs: "test", + // tables: "t1", }, { sql: "DESCRIBE SELECT * FROM t1 WHERE a = 1", - stmtType: "Explain", - //dbs: "test", - //tables: "t1", + stmtType: "ExplainSQL", + // dbs: "test", + // tables: "t1", }, { sql: "trace format='row' select * from t1", stmtType: "Trace", - //dbs: "test", - //tables: "t1", + // dbs: "test", + // tables: "t1", }, { sql: "flush status", @@ -651,18 +653,18 @@ func TestAuditLogNormal(t *testing.T) { sql: "FLUSH TABLES", stmtType: "other", }, - //{ + // { // sql: "KILL TIDB 2", // stmtType: "other", - //}, - //{ + // }, + // { // sql: "SHUTDOWN", // stmtType: "Shutdow", - //}, - //{ + // }, + // { // sql: "ALTER INSTANCE RELOAD TLS", // stmtType: "other", - //}, + // }, } testResults := make([]normalTest, 0) @@ -696,12 +698,18 @@ func TestAuditLogNormal(t *testing.T) { query := append([]byte{mysql.ComQuery}, []byte(test.sql)...) err := conn.Dispatch(context.Background(), query) require.NoError(t, err, errMsg) - require.Equal(t, 2, len(testResults), errMsg) + resultCount := test.resCnt + if resultCount == 0 { + resultCount = 2 + } + require.Equal(t, resultCount, len(testResults), errMsg) + result := testResults[0] - // TODO: currently, result.text is wrong. require.Equal(t, "Query", result.cmd, errMsg) require.Equal(t, plugin.Starting, result.event, errMsg) - result = testResults[1] + + result = testResults[resultCount-1] + require.Equal(t, "Query", result.cmd, errMsg) if test.text == "" { require.Equal(t, test.sql, result.text, errMsg) } else { @@ -713,6 +721,11 @@ func TestAuditLogNormal(t *testing.T) { require.Equal(t, test.tables, result.tables, errMsg) require.Equal(t, "Query", result.cmd, errMsg) require.Equal(t, plugin.Completed, result.event, errMsg) + for i := 1; i < resultCount-1; i++ { + result = testResults[i] + require.Equal(t, "Query", result.cmd, errMsg) + require.Equal(t, plugin.Completed, result.event, errMsg) + } } } diff --git a/plugin/main_test.go b/plugin/main_test.go index 48633eff506ae..b6091ff667b40 100644 --- a/plugin/main_test.go +++ b/plugin/main_test.go @@ -22,10 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), goleak.IgnoreTopFunction("time.Sleep"), } diff --git a/plugin/plugin.go b/plugin/plugin.go index 572b676aa3450..b3aac9694193f 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -26,7 +26,7 @@ import ( "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" ) @@ -46,6 +46,7 @@ type plugins struct { } // clone deep copies plugins info. +// nolint: unused func (p *plugins) clone() *plugins { np := &plugins{ plugins: make(map[Kind][]Plugin, len(p.plugins)), diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index 26e06ec85769b..4e6d4633d0832 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -54,7 +54,7 @@ const globalDBVisible = mysql.CreatePriv | mysql.SelectPriv | mysql.InsertPriv | const ( sqlLoadRoleGraph = "SELECT HIGH_PRIORITY FROM_USER, FROM_HOST, TO_USER, TO_HOST FROM mysql.role_edges" sqlLoadGlobalPrivTable = "SELECT HIGH_PRIORITY Host,User,Priv FROM mysql.global_priv" - sqlLoadDBTable = "SELECT HIGH_PRIORITY Host,DB,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,Index_priv,References_priv,Lock_tables_priv,Create_tmp_table_priv,Event_priv,Create_routine_priv,Alter_routine_priv,Alter_priv,Execute_priv,Create_view_priv,Show_view_priv FROM mysql.db ORDER BY host, db, user" + sqlLoadDBTable = "SELECT HIGH_PRIORITY Host,DB,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,Index_priv,References_priv,Lock_tables_priv,Create_tmp_table_priv,Event_priv,Create_routine_priv,Alter_routine_priv,Alter_priv,Execute_priv,Create_view_priv,Show_view_priv,Trigger_priv FROM mysql.db ORDER BY host, db, user" sqlLoadTablePrivTable = "SELECT HIGH_PRIORITY Host,DB,User,Table_name,Grantor,Timestamp,Table_priv,Column_priv FROM mysql.tables_priv" sqlLoadColumnsPrivTable = "SELECT HIGH_PRIORITY Host,DB,User,Table_name,Column_name,Timestamp,Column_priv FROM mysql.columns_priv" sqlLoadDefaultRoles = "SELECT HIGH_PRIORITY HOST, USER, DEFAULT_ROLE_HOST, DEFAULT_ROLE_USER FROM mysql.default_roles" @@ -1168,7 +1168,7 @@ func (p *MySQLPrivilege) DBIsVisible(user, host, db string) bool { } func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentity) []string { - var gs []string + var gs []string // nolint: prealloc var sortFromIdx int var hasGlobalGrant = false // Some privileges may granted from role inheritance. @@ -1231,19 +1231,11 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit dbPrivTable := make(map[string]mysql.PrivilegeType) for _, record := range p.DB { if record.fullyMatch(user, host) { - if _, ok := dbPrivTable[record.DB]; ok { - dbPrivTable[record.DB] |= record.Privileges - } else { - dbPrivTable[record.DB] = record.Privileges - } + dbPrivTable[record.DB] |= record.Privileges } else { for _, r := range allRoles { if record.baseRecord.match(r.Username, r.Hostname) { - if _, ok := dbPrivTable[record.DB]; ok { - dbPrivTable[record.DB] |= record.Privileges - } else { - dbPrivTable[record.DB] = record.Privileges - } + dbPrivTable[record.DB] |= record.Privileges } } } @@ -1273,19 +1265,11 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit for _, record := range p.TablesPriv { recordKey := record.DB + "." + record.TableName if user == record.User && host == record.Host { - if _, ok := dbPrivTable[record.DB]; ok { - tablePrivTable[recordKey] |= record.TablePriv - } else { - tablePrivTable[recordKey] = record.TablePriv - } + tablePrivTable[recordKey] |= record.TablePriv } else { for _, r := range allRoles { if record.baseRecord.match(r.Username, r.Hostname) { - if _, ok := dbPrivTable[record.DB]; ok { - tablePrivTable[recordKey] |= record.TablePriv - } else { - tablePrivTable[recordKey] = record.TablePriv - } + tablePrivTable[recordKey] |= record.TablePriv } } } diff --git a/privilege/privileges/cache_test.go b/privilege/privileges/cache_test.go index 4d796333664e5..9fe596e29de65 100644 --- a/privilege/privileges/cache_test.go +++ b/privilege/privileges/cache_test.go @@ -18,39 +18,34 @@ import ( "fmt" "testing" - . "github.com/pingcap/check" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/privilege/privileges" - "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) func TestLoadUserTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table user;") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table user;") var p privileges.MySQLPrivilege - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.Len(t, p.User, 0) // Host | User | authentication_string | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Process_priv | Grant_priv | References_priv | Alter_priv | Show_db_priv | Super_priv | Execute_priv | Index_priv | Create_user_priv | Trigger_priv - mustExec(t, se, `INSERT INTO mysql.user (Host, User, authentication_string, Select_priv) VALUES ("%", "root", "", "Y")`) - mustExec(t, se, `INSERT INTO mysql.user (Host, User, authentication_string, Insert_priv) VALUES ("%", "root1", "admin", "Y")`) - mustExec(t, se, `INSERT INTO mysql.user (Host, User, authentication_string, Update_priv, Show_db_priv, References_priv) VALUES ("%", "root11", "", "Y", "Y", "Y")`) - mustExec(t, se, `INSERT INTO mysql.user (Host, User, authentication_string, Create_user_priv, Index_priv, Execute_priv, Create_view_priv, Show_view_priv, Show_db_priv, Super_priv, Trigger_priv) VALUES ("%", "root111", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`) + tk.MustExec(`INSERT INTO mysql.user (Host, User, authentication_string, Select_priv) VALUES ("%", "root", "", "Y")`) + tk.MustExec(`INSERT INTO mysql.user (Host, User, authentication_string, Insert_priv) VALUES ("%", "root1", "admin", "Y")`) + tk.MustExec(`INSERT INTO mysql.user (Host, User, authentication_string, Update_priv, Show_db_priv, References_priv) VALUES ("%", "root11", "", "Y", "Y", "Y")`) + tk.MustExec(`INSERT INTO mysql.user (Host, User, authentication_string, Create_user_priv, Index_priv, Execute_priv, Create_view_priv, Show_view_priv, Show_db_priv, Super_priv, Trigger_priv) VALUES ("%", "root111", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`) p = privileges.MySQLPrivilege{} - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.Len(t, p.User, len(p.UserMap)) user := p.User @@ -62,21 +57,18 @@ func TestLoadUserTable(t *testing.T) { } func TestLoadGlobalPrivTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table global_priv") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table global_priv") - mustExec(t, se, `INSERT INTO mysql.global_priv VALUES ("%", "tu", "{\"access\":0,\"plugin\":\"mysql_native_password\",\"ssl_type\":3, + tk.MustExec(`INSERT INTO mysql.global_priv VALUES ("%", "tu", "{\"access\":0,\"plugin\":\"mysql_native_password\",\"ssl_type\":3, \"ssl_cipher\":\"cipher\",\"x509_subject\":\"\C=ZH1\", \"x509_issuer\":\"\C=ZH2\", \"san\":\"\IP:127.0.0.1, IP:1.1.1.1, DNS:pingcap.com, URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me1\", \"password_last_changed\":1}")`) var p privileges.MySQLPrivilege - err = p.LoadGlobalPrivTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadGlobalPrivTable(tk.Session())) require.Equal(t, `%`, p.Global["tu"][0].Host) require.Equal(t, `tu`, p.Global["tu"][0].User) require.Equal(t, privileges.SslTypeSpecified, p.Global["tu"][0].Priv.SSLType) @@ -89,21 +81,18 @@ func TestLoadGlobalPrivTable(t *testing.T) { } func TestLoadDBTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table db;") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table db;") - mustExec(t, se, `INSERT INTO mysql.db (Host, DB, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv) VALUES ("%", "information_schema", "root", "Y", "Y", "Y", "Y", "Y")`) - mustExec(t, se, `INSERT INTO mysql.db (Host, DB, User, Drop_priv, Grant_priv, Index_priv, Alter_priv, Create_view_priv, Show_view_priv, Execute_priv) VALUES ("%", "mysql", "root1", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`) + tk.MustExec(`INSERT INTO mysql.db (Host, DB, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv) VALUES ("%", "information_schema", "root", "Y", "Y", "Y", "Y", "Y")`) + tk.MustExec(`INSERT INTO mysql.db (Host, DB, User, Drop_priv, Grant_priv, Index_priv, Alter_priv, Create_view_priv, Show_view_priv, Execute_priv) VALUES ("%", "mysql", "root1", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`) var p privileges.MySQLPrivilege - err = p.LoadDBTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadDBTable(tk.Session())) require.Len(t, p.DB, len(p.DBMap)) require.Equal(t, mysql.SelectPriv|mysql.InsertPriv|mysql.UpdatePriv|mysql.DeletePriv|mysql.CreatePriv, p.DB[0].Privileges) @@ -111,20 +100,17 @@ func TestLoadDBTable(t *testing.T) { } func TestLoadTablesPrivTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table tables_priv") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table tables_priv") - mustExec(t, se, `INSERT INTO mysql.tables_priv VALUES ("%", "db", "user", "table", "grantor", "2017-01-04 16:33:42.235831", "Grant,Index,Alter", "Insert,Update")`) + tk.MustExec(`INSERT INTO mysql.tables_priv VALUES ("%", "db", "user", "table", "grantor", "2017-01-04 16:33:42.235831", "Grant,Index,Alter", "Insert,Update")`) var p privileges.MySQLPrivilege - err = p.LoadTablesPrivTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadTablesPrivTable(tk.Session())) require.Len(t, p.TablesPriv, len(p.TablesPrivMap)) require.Equal(t, `%`, p.TablesPriv[0].Host) @@ -136,21 +122,18 @@ func TestLoadTablesPrivTable(t *testing.T) { } func TestLoadColumnsPrivTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table columns_priv") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table columns_priv") - mustExec(t, se, `INSERT INTO mysql.columns_priv VALUES ("%", "db", "user", "table", "column", "2017-01-04 16:33:42.235831", "Insert,Update")`) - mustExec(t, se, `INSERT INTO mysql.columns_priv VALUES ("127.0.0.1", "db", "user", "table", "column", "2017-01-04 16:33:42.235831", "Select")`) + tk.MustExec(`INSERT INTO mysql.columns_priv VALUES ("%", "db", "user", "table", "column", "2017-01-04 16:33:42.235831", "Insert,Update")`) + tk.MustExec(`INSERT INTO mysql.columns_priv VALUES ("127.0.0.1", "db", "user", "table", "column", "2017-01-04 16:33:42.235831", "Select")`) var p privileges.MySQLPrivilege - err = p.LoadColumnsPrivTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadColumnsPrivTable(tk.Session())) require.Equal(t, `%`, p.ColumnsPriv[0].Host) require.Equal(t, "db", p.ColumnsPriv[0].DB) require.Equal(t, "user", p.ColumnsPriv[0].User) @@ -161,20 +144,17 @@ func TestLoadColumnsPrivTable(t *testing.T) { } func TestLoadDefaultRoleTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table default_roles") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table default_roles") - mustExec(t, se, `INSERT INTO mysql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_1")`) - mustExec(t, se, `INSERT INTO mysql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_2")`) + tk.MustExec(`INSERT INTO mysql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_1")`) + tk.MustExec(`INSERT INTO mysql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_2")`) var p privileges.MySQLPrivilege - err = p.LoadDefaultRoles(se) - require.NoError(t, err) + require.NoError(t, p.LoadDefaultRoles(tk.Session())) require.Equal(t, `%`, p.DefaultRoles[0].Host) require.Equal(t, "test_default_roles", p.DefaultRoles[0].User) require.Equal(t, "localhost", p.DefaultRoles[0].DefaultRoleHost) @@ -183,19 +163,17 @@ func TestLoadDefaultRoleTable(t *testing.T) { } func TestPatternMatch(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "USE MYSQL;") - mustExec(t, se, "TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("10.0.%", "root", "Y", "Y")`) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("USE MYSQL;") + tk.MustExec("TRUNCATE TABLE mysql.user") + tk.MustExec(`INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("10.0.%", "root", "Y", "Y")`) var p privileges.MySQLPrivilege - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.True(t, p.RequestVerification(activeRoles, "root", "10.0.1", "test", "", "", mysql.SelectPriv)) require.True(t, p.RequestVerification(activeRoles, "root", "10.0.1.118", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.SelectPriv)) @@ -204,40 +182,35 @@ func TestPatternMatch(t *testing.T) { require.True(t, p.RequestVerification(activeRoles, "root", "114.114.114.114", "test", "", "", mysql.PrivilegeType(0))) require.True(t, p.RequestVerification(activeRoles, "root", "10.0.1.118", "test", "", "", mysql.ShutdownPriv)) - mustExec(t, se, "TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("", "root", "Y", "N")`) + tk.MustExec("TRUNCATE TABLE mysql.user") + tk.MustExec(`INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("", "root", "Y", "N")`) p = privileges.MySQLPrivilege{} - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.True(t, p.RequestVerification(activeRoles, "root", "", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "notnull", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "", "test", "", "", mysql.ShutdownPriv)) // Pattern match for DB. - mustExec(t, se, "TRUNCATE TABLE mysql.user") - mustExec(t, se, "TRUNCATE TABLE mysql.db") - mustExec(t, se, `INSERT INTO mysql.db (user,host,db,select_priv) values ('genius', '%', 'te%', 'Y')`) - err = p.LoadDBTable(se) - require.NoError(t, err) + tk.MustExec("TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.db") + tk.MustExec(`INSERT INTO mysql.db (user,host,db,select_priv) values ('genius', '%', 'te%', 'Y')`) + require.NoError(t, p.LoadDBTable(tk.Session())) require.True(t, p.RequestVerification(activeRoles, "genius", "127.0.0.1", "test", "", "", mysql.SelectPriv)) } func TestHostMatch(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, err) - defer se.Close() + tk := testkit.NewTestKit(t, store) // Host name can be IPv4 address + netmask. - mustExec(t, se, "USE MYSQL;") - mustExec(t, se, "TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (HOST, USER, authentication_string, Select_priv, Shutdown_priv) VALUES ("172.0.0.0/255.0.0.0", "root", "", "Y", "Y")`) + tk.MustExec("USE MYSQL;") + tk.MustExec("TRUNCATE TABLE mysql.user") + tk.MustExec(`INSERT INTO mysql.user (HOST, USER, authentication_string, Select_priv, Shutdown_priv) VALUES ("172.0.0.0/255.0.0.0", "root", "", "Y", "Y")`) var p privileges.MySQLPrivilege - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.True(t, p.RequestVerification(activeRoles, "root", "172.0.0.1", "test", "", "", mysql.SelectPriv)) require.True(t, p.RequestVerification(activeRoles, "root", "172.1.1.1", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.SelectPriv)) @@ -245,7 +218,7 @@ func TestHostMatch(t *testing.T) { require.False(t, p.RequestVerification(activeRoles, "root", "198.0.0.1", "test", "", "", mysql.SelectPriv)) require.True(t, p.RequestVerification(activeRoles, "root", "198.0.0.1", "test", "", "", mysql.PrivilegeType(0))) require.True(t, p.RequestVerification(activeRoles, "root", "172.0.0.1", "test", "", "", mysql.ShutdownPriv)) - mustExec(t, se, `TRUNCATE TABLE mysql.user`) + tk.MustExec(`TRUNCATE TABLE mysql.user`) // Invalid host name, the user can be created, but cannot login. cases := []string{ @@ -260,69 +233,60 @@ func TestHostMatch(t *testing.T) { } for _, IPMask := range cases { sql := fmt.Sprintf(`INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("%s", "root", "Y", "Y")`, IPMask) - mustExec(t, se, sql) + tk.MustExec(sql) p = privileges.MySQLPrivilege{} - err = p.LoadUserTable(se) - require.NoError(t, err) - require.False(t, p.RequestVerification(activeRoles, "root", "127.0.0.1", "test", "", "", mysql.SelectPriv), IsFalse, Commentf("test case: %s", IPMask)) - require.False(t, p.RequestVerification(activeRoles, "root", "127.0.0.0", "test", "", "", mysql.SelectPriv), IsFalse, Commentf("test case: %s", IPMask)) - require.False(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.ShutdownPriv), IsFalse, Commentf("test case: %s", IPMask)) + require.NoError(t, p.LoadUserTable(tk.Session())) + require.False(t, p.RequestVerification(activeRoles, "root", "127.0.0.1", "test", "", "", mysql.SelectPriv), fmt.Sprintf("test case: %s", IPMask)) + require.False(t, p.RequestVerification(activeRoles, "root", "127.0.0.0", "test", "", "", mysql.SelectPriv), fmt.Sprintf("test case: %s", IPMask)) + require.False(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.ShutdownPriv), fmt.Sprintf("test case: %s", IPMask)) } // Netmask notation cannot be used for IPv6 addresses. - mustExec(t, se, `INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("2001:db8::/ffff:ffff::", "root", "Y", "Y")`) + tk.MustExec(`INSERT INTO mysql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("2001:db8::/ffff:ffff::", "root", "Y", "Y")`) p = privileges.MySQLPrivilege{} - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) require.False(t, p.RequestVerification(activeRoles, "root", "2001:db8::1234", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "2001:db8::", "test", "", "", mysql.SelectPriv)) require.False(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.ShutdownPriv)) } func TestCaseInsensitive(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "CREATE DATABASE TCTrain;") - mustExec(t, se, "CREATE TABLE TCTrain.TCTrainOrder (id int);") - mustExec(t, se, "TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.db VALUES ("127.0.0.1", "TCTrain", "genius", "Y", "Y", "Y", "Y", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N")`) + tk := testkit.NewTestKit(t, store) + tk.MustExec("CREATE DATABASE TCTrain;") + tk.MustExec("CREATE TABLE TCTrain.TCTrainOrder (id int);") + tk.MustExec("TRUNCATE TABLE mysql.user") + tk.MustExec(`INSERT INTO mysql.db VALUES ("127.0.0.1", "TCTrain", "genius", "Y", "Y", "Y", "Y", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N")`) var p privileges.MySQLPrivilege - err = p.LoadDBTable(se) - require.NoError(t, err) - // DB and Table names are case insensitive in MySQL. + require.NoError(t, p.LoadDBTable(tk.Session())) + // DB and Table names are case-insensitive in MySQL. require.True(t, p.RequestVerification(activeRoles, "genius", "127.0.0.1", "TCTrain", "TCTrainOrder", "", mysql.SelectPriv)) require.True(t, p.RequestVerification(activeRoles, "genius", "127.0.0.1", "TCTRAIN", "TCTRAINORDER", "", mysql.SelectPriv)) require.True(t, p.RequestVerification(activeRoles, "genius", "127.0.0.1", "tctrain", "tctrainorder", "", mysql.SelectPriv)) } func TestLoadRoleGraph(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "use mysql;") - mustExec(t, se, "truncate table user;") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use mysql;") + tk.MustExec("truncate table user;") var p privileges.MySQLPrivilege - err = p.LoadRoleGraph(se) - require.NoError(t, err) + require.NoError(t, p.LoadDBTable(tk.Session())) require.Len(t, p.User, 0) - mustExec(t, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_1", "%", "user2")`) - mustExec(t, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_2", "%", "root")`) - mustExec(t, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_3", "%", "user1")`) - mustExec(t, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_4", "%", "root")`) + tk.MustExec(`INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_1", "%", "user2")`) + tk.MustExec(`INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_2", "%", "root")`) + tk.MustExec(`INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_3", "%", "user1")`) + tk.MustExec(`INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_4", "%", "root")`) p = privileges.MySQLPrivilege{} - err = p.LoadRoleGraph(se) - require.NoError(t, err) + require.NoError(t, p.LoadRoleGraph(tk.Session())) graph := p.RoleGraph require.True(t, graph["root@%"].Find("r_2", "%")) require.True(t, graph["root@%"].Find("r_4", "%")) @@ -334,22 +298,19 @@ func TestLoadRoleGraph(t *testing.T) { } func TestRoleGraphBFS(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, `CREATE ROLE r_1, r_2, r_3, r_4, r_5, r_6;`) - mustExec(t, se, `GRANT r_2 TO r_1;`) - mustExec(t, se, `GRANT r_3 TO r_2;`) - mustExec(t, se, `GRANT r_4 TO r_3;`) - mustExec(t, se, `GRANT r_1 TO r_4;`) - mustExec(t, se, `GRANT r_5 TO r_3, r_6;`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE ROLE r_1, r_2, r_3, r_4, r_5, r_6;`) + tk.MustExec(`GRANT r_2 TO r_1;`) + tk.MustExec(`GRANT r_3 TO r_2;`) + tk.MustExec(`GRANT r_4 TO r_3;`) + tk.MustExec(`GRANT r_1 TO r_4;`) + tk.MustExec(`GRANT r_5 TO r_3, r_6;`) var p privileges.MySQLPrivilege - err = p.LoadRoleGraph(se) - require.NoError(t, err) + require.NoError(t, p.LoadRoleGraph(tk.Session())) activeRoles := make([]*auth.RoleIdentity, 0) ret := p.FindAllRole(activeRoles) @@ -371,22 +332,19 @@ func TestRoleGraphBFS(t *testing.T) { } func TestFindAllUserEffectiveRoles(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, `CREATE USER u1`) - mustExec(t, se, `CREATE ROLE r_1, r_2, r_3, r_4;`) - mustExec(t, se, `GRANT r_3 to r_1`) - mustExec(t, se, `GRANT r_4 to r_2`) - mustExec(t, se, `GRANT r_1 to u1`) - mustExec(t, se, `GRANT r_2 to u1`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER u1`) + tk.MustExec(`CREATE ROLE r_1, r_2, r_3, r_4;`) + tk.MustExec(`GRANT r_3 to r_1`) + tk.MustExec(`GRANT r_4 to r_2`) + tk.MustExec(`GRANT r_1 to u1`) + tk.MustExec(`GRANT r_2 to u1`) var p privileges.MySQLPrivilege - err = p.LoadAll(se) - require.NoError(t, err) + require.NoError(t, p.LoadAll(tk.Session())) ret := p.FindAllUserEffectiveRoles("u1", "%", []*auth.RoleIdentity{ {Username: "r_1", Hostname: "%"}, {Username: "r_2", Hostname: "%"}, @@ -397,9 +355,8 @@ func TestFindAllUserEffectiveRoles(t *testing.T) { require.Equal(t, "r_3", ret[2].Username) require.Equal(t, "r_4", ret[3].Username) - mustExec(t, se, `REVOKE r_2 from u1`) - err = p.LoadAll(se) - require.NoError(t, err) + tk.MustExec(`REVOKE r_2 from u1`) + require.NoError(t, p.LoadAll(tk.Session())) ret = p.FindAllUserEffectiveRoles("u1", "%", []*auth.RoleIdentity{ {Username: "r_1", Hostname: "%"}, {Username: "r_2", Hostname: "%"}, @@ -410,17 +367,15 @@ func TestFindAllUserEffectiveRoles(t *testing.T) { } func TestAbnormalMySQLTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() + tk := testkit.NewTestKit(t, store) // Simulate the case mysql.user is synchronized from MySQL. - mustExec(t, se, "DROP TABLE mysql.user;") - mustExec(t, se, "USE mysql;") - mustExec(t, se, `CREATE TABLE user ( + tk.MustExec("DROP TABLE mysql.user;") + tk.MustExec("USE mysql;") + tk.MustExec(`CREATE TABLE user ( Host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', User char(16) COLLATE utf8_bin NOT NULL DEFAULT '', Password char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', @@ -470,21 +425,19 @@ func TestAbnormalMySQLTable(t *testing.T) { password_expired enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (Host,User) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges';`) - mustExec(t, se, `INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); + tk.MustExec(`INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); `) var p privileges.MySQLPrivilege - err = p.LoadUserTable(se) - require.NoError(t, err) + require.NoError(t, p.LoadUserTable(tk.Session())) activeRoles := make([]*auth.RoleIdentity, 0) // MySQL mysql.user table schema is not identical to TiDB, check it doesn't break privilege. require.True(t, p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", mysql.SelectPriv)) // Absent of those tables doesn't cause error. - mustExec(t, se, "DROP TABLE mysql.db;") - mustExec(t, se, "DROP TABLE mysql.tables_priv;") - mustExec(t, se, "DROP TABLE mysql.columns_priv;") - err = p.LoadAll(se) - require.NoError(t, err) + tk.MustExec("DROP TABLE mysql.db;") + tk.MustExec("DROP TABLE mysql.tables_priv;") + tk.MustExec("DROP TABLE mysql.columns_priv;") + require.NoError(t, p.LoadAll(tk.Session())) } func TestSortUserTable(t *testing.T) { @@ -555,77 +508,65 @@ func checkUserRecord(t *testing.T, x, y []privileges.UserRecord) { } func TestDBIsVisible(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - mustExec(t, se, "create database visdb") + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database visdb") p := privileges.MySQLPrivilege{} - err = p.LoadAll(se) - require.NoError(t, err) + require.NoError(t, p.LoadAll(tk.Session())) - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Create_role_priv, Super_priv) VALUES ("%", "testvisdb", "Y", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Create_role_priv, Super_priv) VALUES ("%", "testvisdb", "Y", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible := p.DBIsVisible("testvisdb", "%", "visdb") require.False(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Select_priv) VALUES ("%", "testvisdb2", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Select_priv) VALUES ("%", "testvisdb2", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb2", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Create_priv) VALUES ("%", "testvisdb3", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Create_priv) VALUES ("%", "testvisdb3", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb3", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Insert_priv) VALUES ("%", "testvisdb4", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Insert_priv) VALUES ("%", "testvisdb4", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb4", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Update_priv) VALUES ("%", "testvisdb5", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Update_priv) VALUES ("%", "testvisdb5", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb5", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Create_view_priv) VALUES ("%", "testvisdb6", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Create_view_priv) VALUES ("%", "testvisdb6", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb6", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Trigger_priv) VALUES ("%", "testvisdb7", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Trigger_priv) VALUES ("%", "testvisdb7", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb7", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, References_priv) VALUES ("%", "testvisdb8", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, References_priv) VALUES ("%", "testvisdb8", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb8", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") - mustExec(t, se, `INSERT INTO mysql.user (Host, User, Execute_priv) VALUES ("%", "testvisdb9", "Y")`) - err = p.LoadUserTable(se) - require.NoError(t, err) + tk.MustExec(`INSERT INTO mysql.user (Host, User, Execute_priv) VALUES ("%", "testvisdb9", "Y")`) + require.NoError(t, p.LoadUserTable(tk.Session())) isVisible = p.DBIsVisible("testvisdb9", "%", "visdb") require.True(t, isVisible) - mustExec(t, se, "TRUNCATE TABLE mysql.user") + tk.MustExec("TRUNCATE TABLE mysql.user") } diff --git a/privilege/privileges/main_test.go b/privilege/privileges/main_test.go index 0d43ce5c21a4a..d530daf09bd56 100644 --- a/privilege/privileges/main_test.go +++ b/privilege/privileges/main_test.go @@ -24,10 +24,13 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("net/http.(*persistConn).writeLoop"), + goleak.IgnoreTopFunction("internal/poll.runtime_pollWait"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() session.SetSchemaLease(0) session.DisableStats4Test() diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index d9b7d94b64b33..a59c4c79f3c0e 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -38,276 +38,303 @@ import ( "github.com/pingcap/tidb/privilege/privileges" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" - "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/testutil" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/sem" "github.com/pingcap/tidb/util/sqlexec" - "github.com/pingcap/tidb/util/testutil" "github.com/stretchr/testify/require" ) -const dbName = "test" - func TestCheckDBPrivilege(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'testcheck'@'localhost';`) - mustExec(t, rootSe, `CREATE USER 'testcheck_tmp'@'localhost';`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'testcheck'@'localhost';`) + rootTk.MustExec(`CREATE USER 'testcheck_tmp'@'localhost';`) - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.True(t, se.Auth(&auth.UserIdentity{Username: "testcheck", Hostname: "localhost"}, nil, nil)) - pc := privilege.GetPrivilegeManager(se) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "testcheck", Hostname: "localhost"}, nil, nil)) + pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) - mustExec(t, rootSe, `GRANT SELECT ON *.* TO 'testcheck'@'localhost';`) + rootTk.MustExec(`GRANT SELECT ON *.* TO 'testcheck'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) require.False(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) - mustExec(t, rootSe, `GRANT Update ON test.* TO 'testcheck'@'localhost';`) + rootTk.MustExec(`GRANT Update ON test.* TO 'testcheck'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "testcheck", Hostname: "localhost"}) - mustExec(t, rootSe, `GRANT 'testcheck'@'localhost' TO 'testcheck_tmp'@'localhost';`) - se2 := newSession(t, store, dbName) - require.True(t, se2.Auth(&auth.UserIdentity{Username: "testcheck_tmp", Hostname: "localhost"}, nil, nil)) - pc = privilege.GetPrivilegeManager(se2) + rootTk.MustExec(`GRANT 'testcheck'@'localhost' TO 'testcheck_tmp'@'localhost';`) + tk2 := testkit.NewTestKit(t, store) + require.True(t, tk2.Session().Auth(&auth.UserIdentity{Username: "testcheck_tmp", Hostname: "localhost"}, nil, nil)) + pc = privilege.GetPrivilegeManager(tk2.Session()) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) } func TestCheckPointGetDBPrivilege(t *testing.T) { - store, clean := newStore(t) - defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'tester'@'localhost';`) - mustExec(t, rootSe, `GRANT SELECT,UPDATE ON test.* TO 'tester'@'localhost';`) - mustExec(t, rootSe, `create database test2`) - mustExec(t, rootSe, `create table test2.t(id int, v int, primary key(id))`) - mustExec(t, rootSe, `insert into test2.t(id, v) values(1, 1)`) - - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `use test;`) - _, err := se.ExecuteInternal(context.Background(), `select * from test2.t where id = 1`) + store, clean := createStoreAndPrepareDB(t) + defer clean() + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'tester'@'localhost';`) + rootTk.MustExec(`GRANT SELECT,UPDATE ON test.* TO 'tester'@'localhost';`) + rootTk.MustExec(`create database test2`) + rootTk.MustExec(`create table test2.t(id int, v int, primary key(id))`) + rootTk.MustExec(`insert into test2.t(id, v) values(1, 1)`) + + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`use test;`) + err := tk.ExecToErr(`select * from test2.t where id = 1`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - _, err = se.ExecuteInternal(context.Background(), "update test2.t set v = 2 where id = 1") + err = tk.ExecToErr("update test2.t set v = 2 where id = 1") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) } func TestIssue22946(t *testing.T) { - store, clean := newStore(t) - defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, "create database db1;") - mustExec(t, rootSe, "create database db2;") - mustExec(t, rootSe, "use test;") - mustExec(t, rootSe, "create table a(id int);") - mustExec(t, rootSe, "use db1;") - mustExec(t, rootSe, "create table a(id int primary key,name varchar(20));") - mustExec(t, rootSe, "use db2;") - mustExec(t, rootSe, "create table b(id int primary key,address varchar(50));") - mustExec(t, rootSe, "CREATE USER 'delTest'@'localhost';") - mustExec(t, rootSe, "grant all on db1.* to delTest@'localhost';") - mustExec(t, rootSe, "grant all on db2.* to delTest@'localhost';") - mustExec(t, rootSe, "grant select on test.* to delTest@'localhost';") - - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "delTest", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `delete from db1.a as A where exists(select 1 from db2.b as B where A.id = B.id);`) - require.NoError(t, err) - mustExec(t, rootSe, "use db1;") - _, err = se.ExecuteInternal(context.Background(), "delete from test.a as A;") + store, clean := createStoreAndPrepareDB(t) + defer clean() + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec("create database db1;") + rootTk.MustExec("create database db2;") + rootTk.MustExec("use test;") + rootTk.MustExec("create table a(id int);") + rootTk.MustExec("use db1;") + rootTk.MustExec("create table a(id int primary key,name varchar(20));") + rootTk.MustExec("use db2;") + rootTk.MustExec("create table b(id int primary key,address varchar(50));") + rootTk.MustExec("CREATE USER 'delTest'@'localhost';") + rootTk.MustExec("grant all on db1.* to delTest@'localhost';") + rootTk.MustExec("grant all on db2.* to delTest@'localhost';") + rootTk.MustExec("grant select on test.* to delTest@'localhost';") + + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "delTest", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`delete from db1.a as A where exists(select 1 from db2.b as B where A.id = B.id);`) + rootTk.MustExec("use db1;") + err := tk.ExecToErr("delete from test.a as A;") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) } func TestCheckTablePrivilege(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'test1'@'localhost';`) - mustExec(t, rootSe, `CREATE USER 'test1_tmp'@'localhost';`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'test1'@'localhost';`) + rootTk.MustExec(`CREATE USER 'test1_tmp'@'localhost';`) - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test1", Hostname: "localhost"}, nil, nil)) - pc := privilege.GetPrivilegeManager(se) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "localhost"}, nil, nil)) + pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.SelectPriv)) - mustExec(t, rootSe, `GRANT SELECT ON *.* TO 'test1'@'localhost';`) + rootTk.MustExec(`GRANT SELECT ON *.* TO 'test1'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.SelectPriv)) require.False(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.UpdatePriv)) - mustExec(t, rootSe, `GRANT Update ON test.* TO 'test1'@'localhost';`) + rootTk.MustExec(`GRANT Update ON test.* TO 'test1'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.UpdatePriv)) require.False(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.IndexPriv)) activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "test1", Hostname: "localhost"}) - se2 := newSession(t, store, dbName) - mustExec(t, rootSe, `GRANT 'test1'@'localhost' TO 'test1_tmp'@'localhost';`) - require.True(t, se2.Auth(&auth.UserIdentity{Username: "test1_tmp", Hostname: "localhost"}, nil, nil)) - pc2 := privilege.GetPrivilegeManager(se2) + tk2 := testkit.NewTestKit(t, store) + rootTk.MustExec(`GRANT 'test1'@'localhost' TO 'test1_tmp'@'localhost';`) + require.True(t, tk2.Session().Auth(&auth.UserIdentity{Username: "test1_tmp", Hostname: "localhost"}, nil, nil)) + pc2 := privilege.GetPrivilegeManager(tk2.Session()) require.True(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.SelectPriv)) require.True(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.UpdatePriv)) require.False(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.IndexPriv)) - mustExec(t, rootSe, `GRANT Index ON test.test TO 'test1'@'localhost';`) + rootTk.MustExec(`GRANT Index ON test.test TO 'test1'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.IndexPriv)) require.True(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.IndexPriv)) } func TestCheckViewPrivilege(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'vuser'@'localhost';`) - mustExec(t, rootSe, `CREATE VIEW v AS SELECT * FROM test;`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec("use test") + rootTk.MustExec(`CREATE USER 'vuser'@'localhost';`) + rootTk.MustExec(`CREATE VIEW v AS SELECT * FROM test;`) - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.True(t, se.Auth(&auth.UserIdentity{Username: "vuser", Hostname: "localhost"}, nil, nil)) - pc := privilege.GetPrivilegeManager(se) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "vuser", Hostname: "localhost"}, nil, nil)) + pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.SelectPriv)) - mustExec(t, rootSe, `GRANT SELECT ON test.v TO 'vuser'@'localhost';`) + rootTk.MustExec(`GRANT SELECT ON test.v TO 'vuser'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.SelectPriv)) require.False(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.ShowViewPriv)) - mustExec(t, rootSe, `GRANT SHOW VIEW ON test.v TO 'vuser'@'localhost';`) + rootTk.MustExec(`GRANT SHOW VIEW ON test.v TO 'vuser'@'localhost';`) require.True(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.SelectPriv)) require.True(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.ShowViewPriv)) } func TestCheckPrivilegeWithRoles(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'test_role'@'localhost';`) - mustExec(t, rootSe, `CREATE ROLE r_1, r_2, r_3;`) - mustExec(t, rootSe, `GRANT r_1, r_2, r_3 TO 'test_role'@'localhost';`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'test_role'@'localhost';`) + rootTk.MustExec(`CREATE ROLE r_1, r_2, r_3;`) + rootTk.MustExec(`GRANT r_1, r_2, r_3 TO 'test_role'@'localhost';`) - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_role", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `SET ROLE r_1, r_2;`) - mustExec(t, rootSe, `SET DEFAULT ROLE r_1 TO 'test_role'@'localhost';`) + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_role", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`SET ROLE r_1, r_2;`) + rootTk.MustExec(`SET DEFAULT ROLE r_1 TO 'test_role'@'localhost';`) // test bogus role for current user. - _, err := se.ExecuteInternal(context.Background(), `SET DEFAULT ROLE roledoesnotexist TO 'test_role'@'localhost';`) + err := tk.ExecToErr(`SET DEFAULT ROLE roledoesnotexist TO 'test_role'@'localhost';`) require.True(t, terror.ErrorEqual(err, executor.ErrRoleNotGranted)) - mustExec(t, rootSe, `GRANT SELECT ON test.* TO r_1;`) - pc := privilege.GetPrivilegeManager(se) - activeRoles := se.GetSessionVars().ActiveRoles + rootTk.MustExec(`GRANT SELECT ON test.* TO r_1;`) + pc := privilege.GetPrivilegeManager(tk.Session()) + activeRoles := tk.Session().GetSessionVars().ActiveRoles require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) require.False(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) - mustExec(t, rootSe, `GRANT UPDATE ON test.* TO r_2;`) + rootTk.MustExec(`GRANT UPDATE ON test.* TO r_2;`) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) - mustExec(t, se, `SET ROLE NONE;`) - require.Equal(t, 0, len(se.GetSessionVars().ActiveRoles)) - mustExec(t, se, `SET ROLE DEFAULT;`) - require.Equal(t, 1, len(se.GetSessionVars().ActiveRoles)) - mustExec(t, se, `SET ROLE ALL;`) - require.Equal(t, 3, len(se.GetSessionVars().ActiveRoles)) - mustExec(t, se, `SET ROLE ALL EXCEPT r_1, r_2;`) - require.Equal(t, 1, len(se.GetSessionVars().ActiveRoles)) + tk.MustExec(`SET ROLE NONE;`) + require.Equal(t, 0, len(tk.Session().GetSessionVars().ActiveRoles)) + tk.MustExec(`SET ROLE DEFAULT;`) + require.Equal(t, 1, len(tk.Session().GetSessionVars().ActiveRoles)) + tk.MustExec(`SET ROLE ALL;`) + require.Equal(t, 3, len(tk.Session().GetSessionVars().ActiveRoles)) + tk.MustExec(`SET ROLE ALL EXCEPT r_1, r_2;`) + require.Equal(t, 1, len(tk.Session().GetSessionVars().ActiveRoles)) } func TestShowGrants(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - ctx, _ := se.(sessionctx.Context) - mustExec(t, se, `CREATE USER 'show'@'localhost' identified by '123';`) - mustExec(t, se, `GRANT Index ON *.* TO 'show'@'localhost';`) - pc := privilege.GetPrivilegeManager(se) + tk := testkit.NewTestKit(t, store) + ctx, _ := tk.Session().(sessionctx.Context) + tk.MustExec(`CREATE USER 'show'@'localhost' identified by '123';`) + tk.MustExec(`GRANT Index ON *.* TO 'show'@'localhost';`) + pc := privilege.GetPrivilegeManager(tk.Session()) - gs, err := pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + gs, err := pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT INDEX ON *.* TO 'show'@'localhost'`, gs[0]) - mustExec(t, se, `GRANT Select ON *.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT Select ON *.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT SELECT,INDEX ON *.* TO 'show'@'localhost'`, gs[0]) // The order of privs is the same with AllGlobalPrivs - mustExec(t, se, `GRANT Update ON *.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT Update ON *.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT SELECT,UPDATE,INDEX ON *.* TO 'show'@'localhost'`, gs[0]) // All privileges - mustExec(t, se, `GRANT ALL ON *.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT ALL ON *.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, gs[0]) // All privileges with grant option - mustExec(t, se, `GRANT ALL ON *.* TO 'show'@'localhost' WITH GRANT OPTION;`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT ALL ON *.* TO 'show'@'localhost' WITH GRANT OPTION;`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost' WITH GRANT OPTION`, gs[0]) // Revoke grant option - mustExec(t, se, `REVOKE GRANT OPTION ON *.* FROM 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`REVOKE GRANT OPTION ON *.* FROM 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, gs[0]) // Add db scope privileges - mustExec(t, se, `GRANT Select ON test.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT Select ON test.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 2) expected := []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, `GRANT SELECT ON test.* TO 'show'@'localhost'`} - require.True(t, testutil.CompareUnorderedStringSlice(gs, expected)) + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) - mustExec(t, se, `GRANT Index ON test1.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT Index ON test1.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 3) expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, `GRANT SELECT ON test.* TO 'show'@'localhost'`, `GRANT INDEX ON test1.* TO 'show'@'localhost'`} - require.True(t, testutil.CompareUnorderedStringSlice(gs, expected)) + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) + + // Add another db privilege to the same db and test again. + tk.MustExec(`GRANT Delete ON test1.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + require.NoError(t, err) + require.Len(t, gs, 3) + expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, + `GRANT SELECT ON test.* TO 'show'@'localhost'`, + `GRANT DELETE,INDEX ON test1.* TO 'show'@'localhost'`} + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) - mustExec(t, se, `GRANT ALL ON test1.* TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT ALL ON test1.* TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 3) expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, `GRANT SELECT ON test.* TO 'show'@'localhost'`, `GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`} - require.True(t, testutil.CompareUnorderedStringSlice(gs, expected)) + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) // Add table scope privileges - mustExec(t, se, `GRANT Update ON test.test TO 'show'@'localhost';`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`GRANT Update ON test.test TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 4) expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, `GRANT SELECT ON test.* TO 'show'@'localhost'`, `GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`, `GRANT UPDATE ON test.test TO 'show'@'localhost'`} - require.True(t, testutil.CompareUnorderedStringSlice(gs, expected)) + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) + + // Revoke the db privilege of `test` and test again. See issue #30855. + tk.MustExec(`REVOKE SELECT ON test.* FROM 'show'@'localhost'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + require.NoError(t, err) + require.Len(t, gs, 3) + expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, + `GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`, + `GRANT UPDATE ON test.test TO 'show'@'localhost'`} + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) + + // Add another table privilege and test again. + tk.MustExec(`GRANT Select ON test.test TO 'show'@'localhost';`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + require.NoError(t, err) + require.Len(t, gs, 3) + expected = []string{`GRANT ALL PRIVILEGES ON *.* TO 'show'@'localhost'`, + `GRANT ALL PRIVILEGES ON test1.* TO 'show'@'localhost'`, + `GRANT SELECT,UPDATE ON test.test TO 'show'@'localhost'`} + require.True(t, testutil.CompareUnorderedStringSlice(gs, expected), fmt.Sprintf("gs: %v, expected: %v", gs, expected)) // Expected behavior: Usage still exists after revoking all privileges - mustExec(t, se, `REVOKE ALL PRIVILEGES ON *.* FROM 'show'@'localhost'`) - mustExec(t, se, `REVOKE Select on test.* FROM 'show'@'localhost'`) - mustExec(t, se, `REVOKE ALL ON test1.* FROM 'show'@'localhost'`) - mustExec(t, se, `REVOKE UPDATE on test.test FROM 'show'@'localhost'`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + tk.MustExec(`REVOKE ALL PRIVILEGES ON *.* FROM 'show'@'localhost'`) + tk.MustExec(`REVOKE ALL ON test1.* FROM 'show'@'localhost'`) + tk.MustExec(`REVOKE UPDATE, SELECT on test.test FROM 'show'@'localhost'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 1) require.Equal(t, `GRANT USAGE ON *.* TO 'show'@'localhost'`, gs[0]) @@ -315,52 +342,52 @@ func TestShowGrants(t *testing.T) { // Usage should not exist after dropping the user // Which we need privileges to do so! ctx.GetSessionVars().User = &auth.UserIdentity{Username: "root", Hostname: "localhost"} - mustExec(t, se, `DROP USER 'show'@'localhost'`) + tk.MustExec(`DROP USER 'show'@'localhost'`) // This should now return an error - _, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) + _, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "show", Hostname: "localhost"}, nil) require.Error(t, err) // cant show grants for non-existent require.True(t, terror.ErrorEqual(err, privileges.ErrNonexistingGrant)) // Test SHOW GRANTS with USING roles. - mustExec(t, se, `CREATE ROLE 'r1', 'r2'`) - mustExec(t, se, `GRANT SELECT ON test.* TO 'r1'`) - mustExec(t, se, `GRANT INSERT, UPDATE ON test.* TO 'r2'`) - mustExec(t, se, `CREATE USER 'testrole'@'localhost' IDENTIFIED BY 'u1pass'`) - mustExec(t, se, `GRANT 'r1', 'r2' TO 'testrole'@'localhost'`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, nil) + tk.MustExec(`CREATE ROLE 'r1', 'r2'`) + tk.MustExec(`GRANT SELECT ON test.* TO 'r1'`) + tk.MustExec(`GRANT INSERT, UPDATE ON test.* TO 'r2'`) + tk.MustExec(`CREATE USER 'testrole'@'localhost' IDENTIFIED BY 'u1pass'`) + tk.MustExec(`GRANT 'r1', 'r2' TO 'testrole'@'localhost'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 2) roles := make([]*auth.RoleIdentity, 0) roles = append(roles, &auth.RoleIdentity{Username: "r2", Hostname: "%"}) - mustExec(t, se, `GRANT DELETE ON test.* TO 'testrole'@'localhost'`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) + tk.MustExec(`GRANT DELETE ON test.* TO 'testrole'@'localhost'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) require.NoError(t, err) require.Len(t, gs, 3) roles = append(roles, &auth.RoleIdentity{Username: "r1", Hostname: "%"}) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) require.NoError(t, err) require.Len(t, gs, 3) - mustExec(t, se, `GRANT INSERT, DELETE ON test.test TO 'r2'`) - mustExec(t, se, `create table test.b (id int)`) - mustExec(t, se, `GRANT UPDATE ON test.b TO 'testrole'@'localhost'`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) + tk.MustExec(`GRANT INSERT, DELETE ON test.test TO 'r2'`) + tk.MustExec(`create table test.b (id int)`) + tk.MustExec(`GRANT UPDATE ON test.b TO 'testrole'@'localhost'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) require.NoError(t, err) require.Len(t, gs, 5) - mustExec(t, se, `DROP ROLE 'r1', 'r2'`) - mustExec(t, se, `DROP USER 'testrole'@'localhost'`) - mustExec(t, se, `CREATE ROLE 'r1', 'r2'`) - mustExec(t, se, `GRANT SELECT ON test.* TO 'r2'`) - mustExec(t, se, `CREATE USER 'testrole'@'localhost' IDENTIFIED BY 'u1pass'`) - mustExec(t, se, `GRANT 'r1' TO 'testrole'@'localhost'`) - mustExec(t, se, `GRANT 'r2' TO 'r1'`) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, nil) + tk.MustExec(`DROP ROLE 'r1', 'r2'`) + tk.MustExec(`DROP USER 'testrole'@'localhost'`) + tk.MustExec(`CREATE ROLE 'r1', 'r2'`) + tk.MustExec(`GRANT SELECT ON test.* TO 'r2'`) + tk.MustExec(`CREATE USER 'testrole'@'localhost' IDENTIFIED BY 'u1pass'`) + tk.MustExec(`GRANT 'r1' TO 'testrole'@'localhost'`) + tk.MustExec(`GRANT 'r2' TO 'r1'`) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, nil) require.NoError(t, err) require.Len(t, gs, 2) roles = make([]*auth.RoleIdentity, 0) roles = append(roles, &auth.RoleIdentity{Username: "r1", Hostname: "%"}) - gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) + gs, err = pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles) require.NoError(t, err) require.Len(t, gs, 3) } @@ -370,146 +397,145 @@ func TestShowGrants(t *testing.T) { // identity from mysql.user. In TiDB we now use the identity from mysql.user in error messages // for consistency. func TestErrorMessage(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER wildcard`) - mustExec(t, rootSe, `CREATE USER specifichost@192.168.1.1`) - mustExec(t, rootSe, `GRANT SELECT on test.* TO wildcard`) - mustExec(t, rootSe, `GRANT SELECT on test.* TO specifichost@192.168.1.1`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER wildcard`) + rootTk.MustExec(`CREATE USER specifichost@192.168.1.1`) + rootTk.MustExec(`GRANT SELECT on test.* TO wildcard`) + rootTk.MustExec(`GRANT SELECT on test.* TO specifichost@192.168.1.1`) - wildSe := newSession(t, store, dbName) + wildTk := testkit.NewTestKit(t, store) // The session.Auth() func will populate the AuthUsername and AuthHostname fields. // We don't have to explicitly specify them. - require.True(t, wildSe.Auth(&auth.UserIdentity{Username: "wildcard", Hostname: "192.168.1.1"}, nil, nil)) - _, err := wildSe.ExecuteInternal(context.Background(), "use mysql;") - require.Equal(t, "[executor:1044]Access denied for user 'wildcard'@'%' to database 'mysql'", err.Error()) + require.True(t, wildTk.Session().Auth(&auth.UserIdentity{Username: "wildcard", Hostname: "192.168.1.1"}, nil, nil)) + require.EqualError(t, wildTk.ExecToErr("use mysql;"), "[executor:1044]Access denied for user 'wildcard'@'%' to database 'mysql'") - specificSe := newSession(t, store, dbName) - require.True(t, specificSe.Auth(&auth.UserIdentity{Username: "specifichost", Hostname: "192.168.1.1"}, nil, nil)) - _, err = specificSe.ExecuteInternal(context.Background(), "use mysql;") - require.Equal(t, "[executor:1044]Access denied for user 'specifichost'@'192.168.1.1' to database 'mysql'", err.Error()) + specificTk := testkit.NewTestKit(t, store) + require.True(t, specificTk.Session().Auth(&auth.UserIdentity{Username: "specifichost", Hostname: "192.168.1.1"}, nil, nil)) + require.EqualError(t, specificTk.ExecToErr("use mysql;"), "[executor:1044]Access denied for user 'specifichost'@'192.168.1.1' to database 'mysql'") } func TestShowColumnGrants(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `USE test`) - mustExec(t, se, `CREATE USER 'column'@'%'`) - mustExec(t, se, `CREATE TABLE column_table (a int, b int, c int)`) - mustExec(t, se, `GRANT Select(a),Update(a,b),Insert(c) ON test.column_table TO 'column'@'%'`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`USE test`) + tk.MustExec(`CREATE USER 'column'@'%'`) + tk.MustExec(`CREATE TABLE column_table (a int, b int, c int)`) + tk.MustExec(`GRANT Select(a),Update(a,b),Insert(c) ON test.column_table TO 'column'@'%'`) - pc := privilege.GetPrivilegeManager(se) - gs, err := pc.ShowGrants(se, &auth.UserIdentity{Username: "column", Hostname: "%"}, nil) + pc := privilege.GetPrivilegeManager(tk.Session()) + gs, err := pc.ShowGrants(tk.Session(), &auth.UserIdentity{Username: "column", Hostname: "%"}, nil) require.NoError(t, err) require.Equal(t, "GRANT USAGE ON *.* TO 'column'@'%' GRANT SELECT(a), INSERT(c), UPDATE(a, b) ON test.column_table TO 'column'@'%'", strings.Join(gs, " ")) } func TestDropTablePrivileges(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - ctx, _ := se.(sessionctx.Context) - mustExec(t, se, `CREATE TABLE todrop(c int);`) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + ctx, _ := tk.Session().(sessionctx.Context) + tk.MustExec(`CREATE TABLE todrop(c int);`) // ctx.GetSessionVars().User = "root@localhost" - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `CREATE USER 'drop'@'localhost';`) - mustExec(t, se, `GRANT Select ON test.todrop TO 'drop'@'localhost';`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`CREATE USER 'drop'@'localhost';`) + tk.MustExec(`GRANT Select ON test.todrop TO 'drop'@'localhost';`) // ctx.GetSessionVars().User = "drop@localhost" - require.True(t, se.Auth(&auth.UserIdentity{Username: "drop", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `SELECT * FROM todrop;`) - _, err := se.ExecuteInternal(context.Background(), "DROP TABLE todrop;") - require.Error(t, err) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "drop", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`SELECT * FROM todrop;`) + require.Error(t, tk.ExecToErr("DROP TABLE todrop;")) - se = newSession(t, store, dbName) + tk = testkit.NewTestKit(t, store) ctx.GetSessionVars().User = &auth.UserIdentity{Username: "root", Hostname: "localhost"} - mustExec(t, se, `GRANT Drop ON test.todrop TO 'drop'@'localhost';`) + tk.MustExec(`GRANT Drop ON test.todrop TO 'drop'@'localhost';`) - se = newSession(t, store, dbName) + tk = testkit.NewTestKit(t, store) + tk.MustExec("use test") ctx.GetSessionVars().User = &auth.UserIdentity{Username: "drop", Hostname: "localhost"} - mustExec(t, se, `DROP TABLE todrop;`) + tk.MustExec(`DROP TABLE todrop;`) } func TestSetPasswdStmt(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) // high privileged user setting password for other user (passes) - mustExec(t, se, "CREATE USER 'superuser'") - mustExec(t, se, "CREATE USER 'nobodyuser'") - mustExec(t, se, "GRANT ALL ON *.* TO 'superuser'") + tk.MustExec("CREATE USER 'superuser'") + tk.MustExec("CREATE USER 'nobodyuser'") + tk.MustExec("GRANT ALL ON *.* TO 'superuser'") - require.True(t, se.Auth(&auth.UserIdentity{Username: "superuser", Hostname: "localhost", AuthUsername: "superuser", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "SET PASSWORD for 'nobodyuser' = 'newpassword'") - mustExec(t, se, "SET PASSWORD for 'nobodyuser' = ''") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser", Hostname: "localhost", AuthUsername: "superuser", AuthHostname: "%"}, nil, nil)) + tk.MustExec("SET PASSWORD for 'nobodyuser' = 'newpassword'") + tk.MustExec("SET PASSWORD for 'nobodyuser' = ''") // low privileged user trying to set password for other user (fails) - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser", Hostname: "localhost", AuthUsername: "nobodyuser", AuthHostname: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "SET PASSWORD for 'superuser' = 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser", Hostname: "localhost", AuthUsername: "nobodyuser", AuthHostname: "%"}, nil, nil)) + err := tk.ExecToErr("SET PASSWORD for 'superuser' = 'newpassword'") require.Error(t, err) } func TestAlterUserStmt(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) // high privileged user setting password for other user (passes) - mustExec(t, se, "CREATE USER superuser2, nobodyuser2, nobodyuser3, nobodyuser4, nobodyuser5, semuser1, semuser2, semuser3, semuser4") - mustExec(t, se, "GRANT ALL ON *.* TO superuser2") - mustExec(t, se, "GRANT CREATE USER ON *.* TO nobodyuser2") - mustExec(t, se, "GRANT SYSTEM_USER ON *.* TO nobodyuser4") - mustExec(t, se, "GRANT UPDATE ON mysql.user TO nobodyuser5, semuser1") - mustExec(t, se, "GRANT RESTRICTED_TABLES_ADMIN ON *.* TO semuser1") - mustExec(t, se, "GRANT RESTRICTED_USER_ADMIN ON *.* TO semuser1, semuser2, semuser3") - mustExec(t, se, "GRANT SYSTEM_USER ON *.* to semuser3") // user is both restricted + has SYSTEM_USER (or super) - - require.True(t, se.Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + tk.MustExec("CREATE USER superuser2, nobodyuser2, nobodyuser3, nobodyuser4, nobodyuser5, semuser1, semuser2, semuser3, semuser4") + tk.MustExec("GRANT ALL ON *.* TO superuser2") + tk.MustExec("GRANT CREATE USER ON *.* TO nobodyuser2") + tk.MustExec("GRANT SYSTEM_USER ON *.* TO nobodyuser4") + tk.MustExec("GRANT UPDATE ON mysql.user TO nobodyuser5, semuser1") + tk.MustExec("GRANT RESTRICTED_TABLES_ADMIN ON *.* TO semuser1") + tk.MustExec("GRANT RESTRICTED_USER_ADMIN ON *.* TO semuser1, semuser2, semuser3") + tk.MustExec("GRANT SYSTEM_USER ON *.* to semuser3") // user is both restricted + has SYSTEM_USER (or super) + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") // low privileged user trying to set password for others // nobodyuser3 = SUCCESS (not a SYSTEM_USER) // nobodyuser4 = FAIL (has SYSTEM_USER) // superuser2 = FAIL (has SYSTEM_USER privilege implied by SUPER) - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'nobodyuser3' IDENTIFIED BY ''") - _, err := se.ExecuteInternal(context.Background(), "ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") + err := tk.ExecToErr("ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SYSTEM_USER or SUPER privilege(s) for this operation") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'superuser2' IDENTIFIED BY 'newpassword'") + err = tk.ExecToErr("ALTER USER 'superuser2' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SYSTEM_USER or SUPER privilege(s) for this operation") // Nobody3 has no privileges at all, but they can still alter their own password. // Any other user fails. - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser3", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser3' IDENTIFIED BY ''") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser3", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") + err = tk.ExecToErr("ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'superuser2' IDENTIFIED BY 'newpassword'") // it checks create user before SYSTEM_USER + err = tk.ExecToErr("ALTER USER 'superuser2' IDENTIFIED BY 'newpassword'") // it checks create user before SYSTEM_USER require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") // Nobody5 doesn't explicitly have CREATE USER, but mysql also accepts UDPATE on mysql.user // as a substitute so it can modify nobody2 and nobody3 but not nobody4 - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'nobodyuser3' IDENTIFIED BY ''") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") + err = tk.ExecToErr("ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SYSTEM_USER or SUPER privilege(s) for this operation") - require.True(t, se.Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'semuser1' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'semuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'semuser3' IDENTIFIED BY ''") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'semuser1' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'semuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'semuser3' IDENTIFIED BY ''") sem.Enable() defer sem.Disable() @@ -521,68 +547,69 @@ func TestAlterUserStmt(t *testing.T) { // any request for UpdatePriv on mysql.user even if the privilege exists in the internal mysql.user table. // UpdatePriv on mysql.user - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) + err = tk.ExecToErr("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") // actual CreateUserPriv - require.True(t, se.Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'nobodyuser3' IDENTIFIED BY ''") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") // UpdatePriv on mysql.user but also has RESTRICTED_TABLES_ADMIN - require.True(t, se.Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, "ALTER USER 'nobodyuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'nobodyuser3' IDENTIFIED BY ''") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") // As it has (RESTRICTED_TABLES_ADMIN + UpdatePriv on mysql.user) + RESTRICTED_USER_ADMIN it can modify other restricted_user_admins like semuser2 // and it can modify semuser3 because RESTRICTED_USER_ADMIN does not also need SYSTEM_USER - mustExec(t, se, "ALTER USER 'semuser1' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'semuser2' IDENTIFIED BY ''") - mustExec(t, se, "ALTER USER 'semuser3' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'semuser1' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'semuser2' IDENTIFIED BY ''") + tk.MustExec("ALTER USER 'semuser3' IDENTIFIED BY ''") - require.True(t, se.Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'semuser1' IDENTIFIED BY 'newpassword'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) + err = tk.ExecToErr("ALTER USER 'semuser1' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_USER_ADMIN privilege(s) for this operation") - require.True(t, se.Auth(&auth.UserIdentity{Username: "semuser4", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser4", Hostname: "localhost"}, nil, nil)) // has restricted_user_admin but not CREATE USER or (update on mysql.user + RESTRICTED_TABLES_ADMIN) - mustExec(t, se, "ALTER USER 'semuser4' IDENTIFIED BY ''") // can modify self - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'nobodyuser3' IDENTIFIED BY 'newpassword'") + tk.MustExec("ALTER USER 'semuser4' IDENTIFIED BY ''") // can modify self + err = tk.ExecToErr("ALTER USER 'nobodyuser3' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'semuser1' IDENTIFIED BY 'newpassword'") + err = tk.ExecToErr("ALTER USER 'semuser1' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") - _, err = se.ExecuteInternal(context.Background(), "ALTER USER 'semuser3' IDENTIFIED BY 'newpassword'") + err = tk.ExecToErr("ALTER USER 'semuser3' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") } func TestSelectViewSecurity(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - ctx, _ := se.(sessionctx.Context) - mustExec(t, se, `CREATE TABLE viewsecurity(c int);`) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + ctx, _ := tk.Session().(sessionctx.Context) + tk.MustExec(`CREATE TABLE viewsecurity(c int);`) // ctx.GetSessionVars().User = "root@localhost" - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `CREATE USER 'selectusr'@'localhost';`) - mustExec(t, se, `GRANT CREATE VIEW ON test.* TO 'selectusr'@'localhost';`) - mustExec(t, se, `GRANT SELECT ON test.viewsecurity TO 'selectusr'@'localhost';`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`CREATE USER 'selectusr'@'localhost';`) + tk.MustExec(`GRANT CREATE VIEW ON test.* TO 'selectusr'@'localhost';`) + tk.MustExec(`GRANT SELECT ON test.viewsecurity TO 'selectusr'@'localhost';`) // ctx.GetSessionVars().User = "selectusr@localhost" - require.True(t, se.Auth(&auth.UserIdentity{Username: "selectusr", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `SELECT * FROM test.viewsecurity;`) - mustExec(t, se, `CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW test.selectviewsecurity as select * FROM test.viewsecurity;`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "selectusr", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`SELECT * FROM test.viewsecurity;`) + tk.MustExec(`CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW test.selectviewsecurity as select * FROM test.viewsecurity;`) - se = newSession(t, store, dbName) + tk = testkit.NewTestKit(t, store) ctx.GetSessionVars().User = &auth.UserIdentity{Username: "root", Hostname: "localhost"} - mustExec(t, se, "SELECT * FROM test.selectviewsecurity") - mustExec(t, se, `REVOKE Select ON test.viewsecurity FROM 'selectusr'@'localhost';`) - _, err := se.ExecuteInternal(context.Background(), "select * from test.selectviewsecurity") + tk.MustExec("SELECT * FROM test.selectviewsecurity") + tk.MustExec(`REVOKE Select ON test.viewsecurity FROM 'selectusr'@'localhost';`) + err := tk.ExecToErr("select * from test.selectviewsecurity") require.EqualError(t, err, core.ErrViewInvalid.GenWithStackByArgs("test", "selectviewsecurity").Error()) } func TestShowViewPriv(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -678,97 +705,97 @@ func TestShowViewPriv(t *testing.T) { } func TestRoleAdminSecurity(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'ar1'@'localhost';`) - mustExec(t, se, `CREATE USER 'ar2'@'localhost';`) - mustExec(t, se, `GRANT ALL ON *.* to ar1@localhost`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'ar1'@'localhost';`) + tk.MustExec(`CREATE USER 'ar2'@'localhost';`) + tk.MustExec(`GRANT ALL ON *.* to ar1@localhost`) defer func() { - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - mustExec(t, se, "drop user 'ar1'@'localhost'") - mustExec(t, se, "drop user 'ar2'@'localhost'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("drop user 'ar1'@'localhost'") + tk.MustExec("drop user 'ar2'@'localhost'") }() - require.True(t, se.Auth(&auth.UserIdentity{Username: "ar1", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `create role r_test1@localhost`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar1", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`create role r_test1@localhost`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "ar2", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `create role r_test2@localhost`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar2", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr(`create role r_test2@localhost`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) } func TestCheckCertBasedAuth(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'r1'@'localhost';`) - mustExec(t, se, `CREATE USER 'r2'@'localhost' require none;`) - mustExec(t, se, `CREATE USER 'r3'@'localhost' require ssl;`) - mustExec(t, se, `CREATE USER 'r4'@'localhost' require x509;`) - mustExec(t, se, `CREATE USER 'r5'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'r1'@'localhost';`) + tk.MustExec(`CREATE USER 'r2'@'localhost' require none;`) + tk.MustExec(`CREATE USER 'r3'@'localhost' require ssl;`) + tk.MustExec(`CREATE USER 'r4'@'localhost' require x509;`) + tk.MustExec(`CREATE USER 'r5'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' subject '/C=ZH/ST=Beijing/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1' cipher 'TLS_AES_128_GCM_SHA256'`) - mustExec(t, se, `CREATE USER 'r6'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' + tk.MustExec(`CREATE USER 'r6'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' subject '/C=ZH/ST=Beijing/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) - mustExec(t, se, `CREATE USER 'r7_issuer_only'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin'`) - mustExec(t, se, `CREATE USER 'r8_subject_only'@'localhost' require subject '/C=ZH/ST=Beijing/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) - mustExec(t, se, `CREATE USER 'r9_subject_disorder'@'localhost' require subject '/ST=Beijing/C=ZH/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) - mustExec(t, se, `CREATE USER 'r10_issuer_disorder'@'localhost' require issuer '/ST=California/C=US/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin'`) - mustExec(t, se, `CREATE USER 'r11_cipher_only'@'localhost' require cipher 'TLS_AES_256_GCM_SHA384'`) - mustExec(t, se, `CREATE USER 'r12_old_tidb_user'@'localhost'`) - mustExec(t, se, "DELETE FROM mysql.global_priv WHERE `user` = 'r12_old_tidb_user' and `host` = 'localhost'") - mustExec(t, se, `CREATE USER 'r13_broken_user'@'localhost'require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' + tk.MustExec(`CREATE USER 'r7_issuer_only'@'localhost' require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin'`) + tk.MustExec(`CREATE USER 'r8_subject_only'@'localhost' require subject '/C=ZH/ST=Beijing/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) + tk.MustExec(`CREATE USER 'r9_subject_disorder'@'localhost' require subject '/ST=Beijing/C=ZH/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) + tk.MustExec(`CREATE USER 'r10_issuer_disorder'@'localhost' require issuer '/ST=California/C=US/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin'`) + tk.MustExec(`CREATE USER 'r11_cipher_only'@'localhost' require cipher 'TLS_AES_256_GCM_SHA384'`) + tk.MustExec(`CREATE USER 'r12_old_tidb_user'@'localhost'`) + tk.MustExec("DELETE FROM mysql.global_priv WHERE `user` = 'r12_old_tidb_user' and `host` = 'localhost'") + tk.MustExec(`CREATE USER 'r13_broken_user'@'localhost'require issuer '/C=US/ST=California/L=San Francisco/O=PingCAP/OU=TiDB/CN=TiDB admin' subject '/C=ZH/ST=Beijing/L=Haidian/O=PingCAP.Inc/OU=TiDB/CN=tester1'`) - mustExec(t, se, "UPDATE mysql.global_priv set priv = 'abc' where `user` = 'r13_broken_user' and `host` = 'localhost'") - mustExec(t, se, `CREATE USER 'r14_san_only_pass'@'localhost' require san 'URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me1'`) - mustExec(t, se, `CREATE USER 'r15_san_only_fail'@'localhost' require san 'URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me2'`) + tk.MustExec("UPDATE mysql.global_priv set priv = 'abc' where `user` = 'r13_broken_user' and `host` = 'localhost'") + tk.MustExec(`CREATE USER 'r14_san_only_pass'@'localhost' require san 'URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me1'`) + tk.MustExec(`CREATE USER 'r15_san_only_fail'@'localhost' require san 'URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me2'`) defer func() { - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - mustExec(t, se, "drop user 'r1'@'localhost'") - mustExec(t, se, "drop user 'r2'@'localhost'") - mustExec(t, se, "drop user 'r3'@'localhost'") - mustExec(t, se, "drop user 'r4'@'localhost'") - mustExec(t, se, "drop user 'r5'@'localhost'") - mustExec(t, se, "drop user 'r6'@'localhost'") - mustExec(t, se, "drop user 'r7_issuer_only'@'localhost'") - mustExec(t, se, "drop user 'r8_subject_only'@'localhost'") - mustExec(t, se, "drop user 'r9_subject_disorder'@'localhost'") - mustExec(t, se, "drop user 'r10_issuer_disorder'@'localhost'") - mustExec(t, se, "drop user 'r11_cipher_only'@'localhost'") - mustExec(t, se, "drop user 'r12_old_tidb_user'@'localhost'") - mustExec(t, se, "drop user 'r13_broken_user'@'localhost'") - mustExec(t, se, "drop user 'r14_san_only_pass'@'localhost'") - mustExec(t, se, "drop user 'r15_san_only_fail'@'localhost'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("drop user 'r1'@'localhost'") + tk.MustExec("drop user 'r2'@'localhost'") + tk.MustExec("drop user 'r3'@'localhost'") + tk.MustExec("drop user 'r4'@'localhost'") + tk.MustExec("drop user 'r5'@'localhost'") + tk.MustExec("drop user 'r6'@'localhost'") + tk.MustExec("drop user 'r7_issuer_only'@'localhost'") + tk.MustExec("drop user 'r8_subject_only'@'localhost'") + tk.MustExec("drop user 'r9_subject_disorder'@'localhost'") + tk.MustExec("drop user 'r10_issuer_disorder'@'localhost'") + tk.MustExec("drop user 'r11_cipher_only'@'localhost'") + tk.MustExec("drop user 'r12_old_tidb_user'@'localhost'") + tk.MustExec("drop user 'r13_broken_user'@'localhost'") + tk.MustExec("drop user 'r14_san_only_pass'@'localhost'") + tk.MustExec("drop user 'r15_san_only_fail'@'localhost'") }() // test without ssl or ca - require.True(t, se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) // test use ssl without ca - se.GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: nil} - require.True(t, se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + tk.Session().GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: nil} + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) // test use ssl with signed but info wrong ca. - se.GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: [][]*x509.Certificate{{{}}}} - require.True(t, se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + tk.Session().GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: [][]*x509.Certificate{{{}}}} + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) // test a all pass case - se.GetSessionVars().TLSConnectionState = connectionState( + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ util.MockPkixAttribute(util.Country, "US"), @@ -795,19 +822,19 @@ func TestCheckCertBasedAuth(t *testing.T) { require.NoError(t, err) cert.URIs = append(cert.URIs, &url) }) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r14_san_only_pass", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r14_san_only_pass", Hostname: "localhost"}, nil, nil)) // test require but give nothing - se.GetSessionVars().TLSConnectionState = nil - require.False(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + tk.Session().GetSessionVars().TLSConnectionState = nil + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) // test mismatch cipher - se.GetSessionVars().TLSConnectionState = connectionState( + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ util.MockPkixAttribute(util.Country, "US"), @@ -829,12 +856,12 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_256_GCM_SHA384) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r6", Hostname: "localhost"}, nil, nil)) // not require cipher - require.True(t, se.Auth(&auth.UserIdentity{Username: "r11_cipher_only", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r6", Hostname: "localhost"}, nil, nil)) // not require cipher + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r11_cipher_only", Hostname: "localhost"}, nil, nil)) // test only subject or only issuer - se.GetSessionVars().TLSConnectionState = connectionState( + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ util.MockPkixAttribute(util.Country, "US"), @@ -856,8 +883,8 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r7_issuer_only", Hostname: "localhost"}, nil, nil)) - se.GetSessionVars().TLSConnectionState = connectionState( + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r7_issuer_only", Hostname: "localhost"}, nil, nil)) + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ util.MockPkixAttribute(util.Country, "AU"), @@ -879,10 +906,10 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.True(t, se.Auth(&auth.UserIdentity{Username: "r8_subject_only", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r8_subject_only", Hostname: "localhost"}, nil, nil)) // test disorder issuer or subject - se.GetSessionVars().TLSConnectionState = connectionState( + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{}, }, @@ -897,8 +924,8 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r9_subject_disorder", Hostname: "localhost"}, nil, nil)) - se.GetSessionVars().TLSConnectionState = connectionState( + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r9_subject_disorder", Hostname: "localhost"}, nil, nil)) + tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ util.MockPkixAttribute(util.Country, "US"), @@ -913,14 +940,14 @@ func TestCheckCertBasedAuth(t *testing.T) { Names: []pkix.AttributeTypeAndValue{}, }, tls.TLS_AES_128_GCM_SHA256) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r10_issuer_disorder", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r10_issuer_disorder", Hostname: "localhost"}, nil, nil)) // test mismatch san - require.False(t, se.Auth(&auth.UserIdentity{Username: "r15_san_only_fail", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r15_san_only_fail", Hostname: "localhost"}, nil, nil)) // test old data and broken data - require.True(t, se.Auth(&auth.UserIdentity{Username: "r12_old_tidb_user", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r13_broken_user", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "r12_old_tidb_user", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r13_broken_user", Hostname: "localhost"}, nil, nil)) } @@ -936,363 +963,357 @@ func connectionState(issuer, subject pkix.Name, cipher uint16, opt ...func(c *x5 } func TestCheckAuthenticate(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'u1'@'localhost';`) - mustExec(t, se, `CREATE USER 'u2'@'localhost' identified by 'abc';`) - mustExec(t, se, `CREATE USER 'u3@example.com'@'localhost';`) - mustExec(t, se, `CREATE USER u4@localhost;`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'u1'@'localhost';`) + tk.MustExec(`CREATE USER 'u2'@'localhost' identified by 'abc';`) + tk.MustExec(`CREATE USER 'u3@example.com'@'localhost';`) + tk.MustExec(`CREATE USER u4@localhost;`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) salt := []byte{85, 92, 45, 22, 58, 79, 107, 6, 122, 125, 58, 80, 12, 90, 103, 32, 90, 10, 74, 82} authentication := []byte{24, 180, 183, 225, 166, 6, 81, 102, 70, 248, 199, 143, 91, 204, 169, 9, 161, 171, 203, 33} - require.True(t, se.Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, authentication, salt)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) - - se1 := newSession(t, store, dbName) - mustExec(t, se1, "drop user 'u1'@'localhost'") - mustExec(t, se1, "drop user 'u2'@'localhost'") - mustExec(t, se1, "drop user 'u3@example.com'@'localhost'") - mustExec(t, se1, "drop user u4@localhost") - - require.False(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) - - se2 := newSession(t, store, dbName) - mustExec(t, se2, "create role 'r1'@'localhost'") - mustExec(t, se2, "create role 'r2'@'localhost'") - mustExec(t, se2, "create role 'r3@example.com'@'localhost'") - require.False(t, se.Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.False(t, se.Auth(&auth.UserIdentity{Username: "r3@example.com", Hostname: "localhost"}, nil, nil)) - - mustExec(t, se1, "drop user 'r1'@'localhost'") - mustExec(t, se1, "drop user 'r2'@'localhost'") - mustExec(t, se1, "drop user 'r3@example.com'@'localhost'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, authentication, salt)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("drop user 'u1'@'localhost'") + tk1.MustExec("drop user 'u2'@'localhost'") + tk1.MustExec("drop user 'u3@example.com'@'localhost'") + tk1.MustExec("drop user u4@localhost") + + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("create role 'r1'@'localhost'") + tk2.MustExec("create role 'r2'@'localhost'") + tk2.MustExec("create role 'r3@example.com'@'localhost'") + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) + require.False(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3@example.com", Hostname: "localhost"}, nil, nil)) + + tk1.MustExec("drop user 'r1'@'localhost'") + tk1.MustExec("drop user 'r2'@'localhost'") + tk1.MustExec("drop user 'r3@example.com'@'localhost'") } func TestUseDB(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) // high privileged user - mustExec(t, se, "CREATE USER 'usesuper'") - mustExec(t, se, "CREATE USER 'usenobody'") - mustExec(t, se, "GRANT ALL ON *.* TO 'usesuper'") + tk.MustExec("CREATE USER 'usesuper'") + tk.MustExec("CREATE USER 'usenobody'") + tk.MustExec("GRANT ALL ON *.* TO 'usesuper'") // without grant option - require.True(t, se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) - _, e := se.ExecuteInternal(context.Background(), "GRANT SELECT ON mysql.* TO 'usenobody'") - require.Error(t, e) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + require.Error(t, tk.ExecToErr("GRANT SELECT ON mysql.* TO 'usenobody'")) // with grant option - se = newSession(t, store, dbName) + tk = testkit.NewTestKit(t, store) // high privileged user - mustExec(t, se, "GRANT ALL ON *.* TO 'usesuper' WITH GRANT OPTION") - require.True(t, se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "use mysql") + tk.MustExec("GRANT ALL ON *.* TO 'usesuper' WITH GRANT OPTION") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec("use mysql") // low privileged user - require.True(t, se.Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "use mysql") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) + err := tk.ExecToErr("use mysql") require.Error(t, err) // try again after privilege granted - require.True(t, se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "GRANT SELECT ON mysql.* TO 'usenobody'") - require.True(t, se.Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "use mysql") - require.NoError(t, err) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec("GRANT SELECT ON mysql.* TO 'usenobody'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) + tk.MustExec("use mysql") // test `use db` for role. - require.True(t, se.Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, `CREATE DATABASE app_db`) - mustExec(t, se, `CREATE ROLE 'app_developer'`) - mustExec(t, se, `GRANT ALL ON app_db.* TO 'app_developer'`) - mustExec(t, se, `CREATE USER 'dev'@'localhost'`) - mustExec(t, se, `GRANT 'app_developer' TO 'dev'@'localhost'`) - mustExec(t, se, `SET DEFAULT ROLE 'app_developer' TO 'dev'@'localhost'`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "dev", Hostname: "localhost", AuthUsername: "dev", AuthHostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "use app_db") - require.NoError(t, err) - _, err = se.ExecuteInternal(context.Background(), "use mysql") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec(`CREATE DATABASE app_db`) + tk.MustExec(`CREATE ROLE 'app_developer'`) + tk.MustExec(`GRANT ALL ON app_db.* TO 'app_developer'`) + tk.MustExec(`CREATE USER 'dev'@'localhost'`) + tk.MustExec(`GRANT 'app_developer' TO 'dev'@'localhost'`) + tk.MustExec(`SET DEFAULT ROLE 'app_developer' TO 'dev'@'localhost'`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "localhost", AuthUsername: "dev", AuthHostname: "localhost"}, nil, nil)) + tk.MustExec("use app_db") + err = tk.ExecToErr("use mysql") require.Error(t, err) } func TestRevokePrivileges(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, "CREATE USER 'hasgrant'") - mustExec(t, se, "CREATE USER 'withoutgrant'") - mustExec(t, se, "GRANT ALL ON *.* TO 'hasgrant'") - mustExec(t, se, "GRANT ALL ON mysql.* TO 'withoutgrant'") + tk := testkit.NewTestKit(t, store) + tk.MustExec("CREATE USER 'hasgrant'") + tk.MustExec("CREATE USER 'withoutgrant'") + tk.MustExec("GRANT ALL ON *.* TO 'hasgrant'") + tk.MustExec("GRANT ALL ON mysql.* TO 'withoutgrant'") // Without grant option - require.True(t, se.Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) - _, e := se.ExecuteInternal(context.Background(), "REVOKE SELECT ON mysql.* FROM 'withoutgrant'") - require.Error(t, e) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) + require.Error(t, tk.ExecToErr("REVOKE SELECT ON mysql.* FROM 'withoutgrant'")) // With grant option - se = newSession(t, store, dbName) - mustExec(t, se, "GRANT ALL ON *.* TO 'hasgrant' WITH GRANT OPTION") - require.True(t, se.Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "REVOKE SELECT ON mysql.* FROM 'withoutgrant'") - mustExec(t, se, "REVOKE ALL ON mysql.* FROM withoutgrant") + tk = testkit.NewTestKit(t, store) + tk.MustExec("GRANT ALL ON *.* TO 'hasgrant' WITH GRANT OPTION") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) + tk.MustExec("REVOKE SELECT ON mysql.* FROM 'withoutgrant'") + tk.MustExec("REVOKE ALL ON mysql.* FROM withoutgrant") // For issue https://github.com/pingcap/tidb/issues/23850 - mustExec(t, se, "CREATE USER u4") - mustExec(t, se, "GRANT ALL ON *.* TO u4 WITH GRANT OPTION") - require.True(t, se.Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost", AuthUsername: "u4", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "REVOKE ALL ON *.* FROM CURRENT_USER()") + tk.MustExec("CREATE USER u4") + tk.MustExec("GRANT ALL ON *.* TO u4 WITH GRANT OPTION") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost", AuthUsername: "u4", AuthHostname: "%"}, nil, nil)) + tk.MustExec("REVOKE ALL ON *.* FROM CURRENT_USER()") } func TestSetGlobal(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER setglobal_a@localhost`) - mustExec(t, se, `CREATE USER setglobal_b@localhost`) - mustExec(t, se, `GRANT SUPER ON *.* to setglobal_a@localhost`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER setglobal_a@localhost`) + tk.MustExec(`CREATE USER setglobal_b@localhost`) + tk.MustExec(`GRANT SUPER ON *.* to setglobal_a@localhost`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "setglobal_a", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `set global innodb_commit_concurrency=16`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_a", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`set global innodb_commit_concurrency=16`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "setglobal_b", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `set global innodb_commit_concurrency=16`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_b", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr(`set global innodb_commit_concurrency=16`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) } func TestCreateDropUser(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER tcd1, tcd2`) - mustExec(t, se, `GRANT ALL ON *.* to tcd2 WITH GRANT OPTION`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER tcd1, tcd2`) + tk.MustExec(`GRANT ALL ON *.* to tcd2 WITH GRANT OPTION`) // should fail - require.True(t, se.Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `CREATE USER acdc`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) + err := tk.ExecToErr(`CREATE USER acdc`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) - _, err = se.ExecuteInternal(context.Background(), `DROP USER tcd2`) + err = tk.ExecToErr(`DROP USER tcd2`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) // should pass - require.True(t, se.Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthUsername: "tcd2", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, `DROP USER tcd1`) - mustExec(t, se, `CREATE USER tcd1`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthUsername: "tcd2", AuthHostname: "%"}, nil, nil)) + tk.MustExec(`DROP USER tcd1`) + tk.MustExec(`CREATE USER tcd1`) // should pass - mustExec(t, se, `GRANT tcd2 TO tcd1`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, `SET ROLE tcd2;`) - mustExec(t, se, `CREATE USER tcd3`) - mustExec(t, se, `DROP USER tcd3`) + tk.MustExec(`GRANT tcd2 TO tcd1`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) + tk.MustExec(`SET ROLE tcd2;`) + tk.MustExec(`CREATE USER tcd3`) + tk.MustExec(`DROP USER tcd3`) } func TestConfigPrivilege(t *testing.T) { - store, clean := newStore(t) - defer clean() - - se := newSession(t, store, dbName) - mustExec(t, se, `DROP USER IF EXISTS tcd1`) - mustExec(t, se, `CREATE USER tcd1`) - mustExec(t, se, `GRANT ALL ON *.* to tcd1`) - mustExec(t, se, `DROP USER IF EXISTS tcd2`) - mustExec(t, se, `CREATE USER tcd2`) - mustExec(t, se, `GRANT ALL ON *.* to tcd2`) - mustExec(t, se, `REVOKE CONFIG ON *.* FROM tcd2`) - - require.True(t, se.Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthHostname: "tcd1", AuthUsername: "%"}, nil, nil)) - mustExec(t, se, `SHOW CONFIG`) - mustExec(t, se, `SET CONFIG TIKV testkey="testval"`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthHostname: "tcd2", AuthUsername: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `SHOW CONFIG`) + store, clean := createStoreAndPrepareDB(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec(`DROP USER IF EXISTS tcd1`) + tk.MustExec(`CREATE USER tcd1`) + tk.MustExec(`GRANT ALL ON *.* to tcd1`) + tk.MustExec(`DROP USER IF EXISTS tcd2`) + tk.MustExec(`CREATE USER tcd2`) + tk.MustExec(`GRANT ALL ON *.* to tcd2`) + tk.MustExec(`REVOKE CONFIG ON *.* FROM tcd2`) + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthHostname: "tcd1", AuthUsername: "%"}, nil, nil)) + tk.MustExec(`SHOW CONFIG`) + tk.MustExec(`SET CONFIG TIKV testkey="testval"`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthHostname: "tcd2", AuthUsername: "%"}, nil, nil)) + err := tk.ExecToErr(`SHOW CONFIG`) require.Error(t, err) require.Regexp(t, "you need \\(at least one of\\) the CONFIG privilege\\(s\\) for this operation$", err.Error()) - _, err = se.ExecuteInternal(context.Background(), `SET CONFIG TIKV testkey="testval"`) + err = tk.ExecToErr(`SET CONFIG TIKV testkey="testval"`) require.Error(t, err) require.Regexp(t, "you need \\(at least one of\\) the CONFIG privilege\\(s\\) for this operation$", err.Error()) - mustExec(t, se, `DROP USER tcd1, tcd2`) + tk.MustExec(`DROP USER tcd1, tcd2`) } func TestShowCreateTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER tsct1, tsct2`) - mustExec(t, se, `GRANT select ON mysql.* to tsct2`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER tsct1, tsct2`) + tk.MustExec(`GRANT select ON mysql.* to tsct2`) // should fail - require.True(t, se.Auth(&auth.UserIdentity{Username: "tsct1", Hostname: "localhost", AuthUsername: "tsct1", AuthHostname: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `SHOW CREATE TABLE mysql.user`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct1", Hostname: "localhost", AuthUsername: "tsct1", AuthHostname: "%"}, nil, nil)) + err := tk.ExecToErr(`SHOW CREATE TABLE mysql.user`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) // should pass - require.True(t, se.Auth(&auth.UserIdentity{Username: "tsct2", Hostname: "localhost", AuthUsername: "tsct2", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, `SHOW CREATE TABLE mysql.user`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct2", Hostname: "localhost", AuthUsername: "tsct2", AuthHostname: "%"}, nil, nil)) + tk.MustExec(`SHOW CREATE TABLE mysql.user`) } func TestReplaceAndInsertOnDuplicate(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER tr_insert`) - mustExec(t, se, `CREATE USER tr_update`) - mustExec(t, se, `CREATE USER tr_delete`) - mustExec(t, se, `CREATE TABLE t1 (a int primary key, b int)`) - mustExec(t, se, `GRANT INSERT ON t1 TO tr_insert`) - mustExec(t, se, `GRANT UPDATE ON t1 TO tr_update`) - mustExec(t, se, `GRANT DELETE ON t1 TO tr_delete`) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`CREATE USER tr_insert`) + tk.MustExec(`CREATE USER tr_update`) + tk.MustExec(`CREATE USER tr_delete`) + tk.MustExec(`CREATE TABLE t1 (a int primary key, b int)`) + tk.MustExec(`GRANT INSERT ON t1 TO tr_insert`) + tk.MustExec(`GRANT UPDATE ON t1 TO tr_update`) + tk.MustExec(`GRANT DELETE ON t1 TO tr_delete`) // Restrict the permission to INSERT only. - require.True(t, se.Auth(&auth.UserIdentity{Username: "tr_insert", Hostname: "localhost", AuthUsername: "tr_insert", AuthHostname: "%"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_insert", Hostname: "localhost", AuthUsername: "tr_insert", AuthHostname: "%"}, nil, nil)) // REPLACE requires INSERT + DELETE privileges, having INSERT alone is insufficient. - _, err := se.ExecuteInternal(context.Background(), `REPLACE INTO t1 VALUES (1, 2)`) + err := tk.ExecToErr(`REPLACE INTO t1 VALUES (1, 2)`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]DELETE command denied to user 'tr_insert'@'%' for table 't1'") // INSERT ON DUPLICATE requires INSERT + UPDATE privileges, having INSERT alone is insufficient. - _, err = se.ExecuteInternal(context.Background(), `INSERT INTO t1 VALUES (3, 4) ON DUPLICATE KEY UPDATE b = 5`) + err = tk.ExecToErr(`INSERT INTO t1 VALUES (3, 4) ON DUPLICATE KEY UPDATE b = 5`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]UPDATE command denied to user 'tr_insert'@'%' for table 't1'") // Plain INSERT should work. - mustExec(t, se, `INSERT INTO t1 VALUES (6, 7)`) + tk.MustExec(`INSERT INTO t1 VALUES (6, 7)`) // Also check that having DELETE alone is insufficient for REPLACE. - require.True(t, se.Auth(&auth.UserIdentity{Username: "tr_delete", Hostname: "localhost", AuthUsername: "tr_delete", AuthHostname: "%"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), `REPLACE INTO t1 VALUES (8, 9)`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_delete", Hostname: "localhost", AuthUsername: "tr_delete", AuthHostname: "%"}, nil, nil)) + err = tk.ExecToErr(`REPLACE INTO t1 VALUES (8, 9)`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'tr_delete'@'%' for table 't1'") // Also check that having UPDATE alone is insufficient for INSERT ON DUPLICATE. - require.True(t, se.Auth(&auth.UserIdentity{Username: "tr_update", Hostname: "localhost", AuthUsername: "tr_update", AuthHostname: "%"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), `INSERT INTO t1 VALUES (10, 11) ON DUPLICATE KEY UPDATE b = 12`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_update", Hostname: "localhost", AuthUsername: "tr_update", AuthHostname: "%"}, nil, nil)) + err = tk.ExecToErr(`INSERT INTO t1 VALUES (10, 11) ON DUPLICATE KEY UPDATE b = 12`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'tr_update'@'%' for table 't1'") } func TestAnalyzeTable(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) + tk := testkit.NewTestKit(t, store) // high privileged user - mustExec(t, se, "CREATE USER 'asuper'") - mustExec(t, se, "CREATE USER 'anobody'") - mustExec(t, se, "GRANT ALL ON *.* TO 'asuper' WITH GRANT OPTION") - mustExec(t, se, "CREATE DATABASE atest") - mustExec(t, se, "use atest") - mustExec(t, se, "CREATE TABLE t1 (a int)") - - require.True(t, se.Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "analyze table mysql.user") + tk.MustExec("CREATE USER 'asuper'") + tk.MustExec("CREATE USER 'anobody'") + tk.MustExec("GRANT ALL ON *.* TO 'asuper' WITH GRANT OPTION") + tk.MustExec("CREATE DATABASE atest") + tk.MustExec("use atest") + tk.MustExec("CREATE TABLE t1 (a int)") + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec("analyze table mysql.user") // low privileged user - require.True(t, se.Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "analyze table t1") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + err := tk.ExecToErr("analyze table t1") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'anobody'@'%' for table 't1'") - _, err = se.ExecuteInternal(context.Background(), "select * from t1") + err = tk.ExecToErr("select * from t1") require.EqualError(t, err, "[planner:1142]SELECT command denied to user 'anobody'@'%' for table 't1'") // try again after SELECT privilege granted - require.True(t, se.Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "GRANT SELECT ON atest.* TO 'anobody'") - require.True(t, se.Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "analyze table t1") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec("GRANT SELECT ON atest.* TO 'anobody'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + err = tk.ExecToErr("analyze table t1") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'anobody'@'%' for table 't1'") // Add INSERT privilege and it should work. - require.True(t, se.Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) - mustExec(t, se, "GRANT INSERT ON atest.* TO 'anobody'") - require.True(t, se.Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "analyze table t1") - require.NoError(t, err) - + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + tk.MustExec("GRANT INSERT ON atest.* TO 'anobody'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + tk.MustExec("analyze table t1") } func TestSystemSchema(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() // This test tests no privilege check for INFORMATION_SCHEMA database. - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'u1'@'localhost';`) - mustExec(t, se, `GRANT SELECT ON *.* TO 'u1'@'localhost';`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `select * from information_schema.tables`) - mustExec(t, se, `select * from information_schema.key_column_usage`) - _, err := se.ExecuteInternal(context.Background(), "create table information_schema.t(a int)") + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'u1'@'localhost';`) + tk.MustExec(`GRANT SELECT ON *.* TO 'u1'@'localhost';`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`select * from information_schema.tables`) + tk.MustExec(`select * from information_schema.key_column_usage`) + err := tk.ExecToErr("create table information_schema.t(a int)") require.Error(t, err) require.True(t, strings.Contains(err.Error(), "denied to user")) - _, err = se.ExecuteInternal(context.Background(), "drop table information_schema.tables") + err = tk.ExecToErr("drop table information_schema.tables") require.Error(t, err) require.True(t, strings.Contains(err.Error(), "denied to user")) - _, err = se.ExecuteInternal(context.Background(), "update information_schema.tables set table_name = 'tst' where table_name = 'mysql'") + err = tk.ExecToErr("update information_schema.tables set table_name = 'tst' where table_name = 'mysql'") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) // Test metric_schema. - mustExec(t, se, `select * from metrics_schema.tidb_query_duration`) - _, err = se.ExecuteInternal(context.Background(), "drop table metrics_schema.tidb_query_duration") + tk.MustExec(`select * from metrics_schema.tidb_query_duration`) + err = tk.ExecToErr("drop table metrics_schema.tidb_query_duration") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - _, err = se.ExecuteInternal(context.Background(), "update metrics_schema.tidb_query_duration set instance = 'tst'") + err = tk.ExecToErr("update metrics_schema.tidb_query_duration set instance = 'tst'") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) - _, err = se.ExecuteInternal(context.Background(), "delete from metrics_schema.tidb_query_duration") + err = tk.ExecToErr("delete from metrics_schema.tidb_query_duration") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - _, err = se.ExecuteInternal(context.Background(), "create table metric_schema.t(a int)") + err = tk.ExecToErr("create table metric_schema.t(a int)") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) } func TestPerformanceSchema(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() // This test tests no privilege check for INFORMATION_SCHEMA database. - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'u1'@'localhost';`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'u1'@'localhost';`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr("select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `GRANT SELECT ON *.* TO 'u1'@'localhost';`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`GRANT SELECT ON *.* TO 'u1'@'localhost';`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") - require.NoError(t, err) - mustExec(t, se, `select * from performance_schema.events_statements_summary_by_digest`) - _, err = se.ExecuteInternal(context.Background(), "drop table performance_schema.events_statements_summary_by_digest") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + tk.MustExec("select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") + tk.MustExec(`select * from performance_schema.events_statements_summary_by_digest`) + err = tk.ExecToErr("drop table performance_schema.events_statements_summary_by_digest") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - _, err = se.ExecuteInternal(context.Background(), "update performance_schema.events_statements_summary_by_digest set schema_name = 'tst'") + err = tk.ExecToErr("update performance_schema.events_statements_summary_by_digest set schema_name = 'tst'") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) - _, err = se.ExecuteInternal(context.Background(), "delete from performance_schema.events_statements_summary_by_digest") + err = tk.ExecToErr("delete from performance_schema.events_statements_summary_by_digest") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - _, err = se.ExecuteInternal(context.Background(), "create table performance_schema.t(a int)") + err = tk.ExecToErr("create table performance_schema.t(a int)") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) } func TestMetricsSchema(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -1403,38 +1424,38 @@ func TestMetricsSchema(t *testing.T) { } func TestAdminCommand(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `CREATE USER 'test_admin'@'localhost';`) - mustExec(t, se, `CREATE TABLE t(a int)`) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`CREATE USER 'test_admin'@'localhost';`) + tk.MustExec(`CREATE TABLE t(a int)`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_admin", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "ADMIN SHOW DDL JOBS") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_admin", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr("ADMIN SHOW DDL JOBS") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) - _, err = se.ExecuteInternal(context.Background(), "ADMIN CHECK TABLE t") + err = tk.ExecToErr("ADMIN CHECK TABLE t") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "ADMIN SHOW DDL JOBS") - require.NoError(t, err) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec("ADMIN SHOW DDL JOBS") } func TestTableNotExistNoPermissions(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `CREATE USER 'testnotexist'@'localhost';`) - mustExec(t, se, `CREATE DATABASE dbexists`) - mustExec(t, se, `CREATE TABLE dbexists.t1 (a int)`) + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`CREATE USER 'testnotexist'@'localhost';`) + tk.MustExec(`CREATE DATABASE dbexists`) + tk.MustExec(`CREATE TABLE dbexists.t1 (a int)`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "testnotexist", Hostname: "localhost"}, nil, nil)) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "testnotexist", Hostname: "localhost"}, nil, nil)) tests := []struct { stmt string @@ -1459,9 +1480,8 @@ func TestTableNotExistNoPermissions(t *testing.T) { } for _, tt := range tests { - - _, err1 := se.ExecuteInternal(context.Background(), fmt.Sprintf(tt.stmt, "dbexists", "t1")) - _, err2 := se.ExecuteInternal(context.Background(), fmt.Sprintf(tt.stmt, "dbnotexists", "t1")) + err1 := tk.ExecToErr(fmt.Sprintf(tt.stmt, "dbexists", "t1")) + err2 := tk.ExecToErr(fmt.Sprintf(tt.stmt, "dbnotexists", "t1")) // Check the error is the same whether table exists or not. require.True(t, terror.ErrorEqual(err1, err2)) @@ -1479,96 +1499,103 @@ func TestLoadDataPrivilege(t *testing.T) { require.NoError(t, err) require.NotNil(t, fp) defer func() { - err = fp.Close() - require.NoError(t, err) - err = os.Remove(path) - require.NoError(t, err) + require.NoError(t, fp.Close()) + require.NoError(t, os.Remove(path)) }() _, err = fp.WriteString("1\n") require.NoError(t, err) - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `CREATE USER 'test_load'@'localhost';`) - mustExec(t, se, `CREATE TABLE t_load(a int)`) - mustExec(t, se, `GRANT SELECT on *.* to 'test_load'@'localhost'`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`CREATE USER 'test_load'@'localhost';`) + tk.MustExec(`CREATE TABLE t_load(a int)`) + + tk.MustExec(`GRANT SELECT on *.* to 'test_load'@'localhost'`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + err = tk.ExecToErr("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") + require.Error(t, err) + require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`GRANT INSERT on *.* to 'test_load'@'localhost'`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + tk.MustExec("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") + + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec(`GRANT INSERT on *.* to 'test_load'@'localhost'`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + err = tk.ExecToErr("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' REPLACE INTO TABLE t_load") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, `GRANT INSERT on *.* to 'test_load'@'localhost'`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) - _, err = se.ExecuteInternal(context.Background(), "LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") - require.NoError(t, err) } func TestSelectIntoNoPermissions(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'nofile'@'localhost';`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "nofile", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), `select 1 into outfile '/tmp/doesntmatter-no-permissions'`) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'nofile'@'localhost';`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "nofile", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr(`select 1 into outfile '/tmp/doesntmatter-no-permissions'`) require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) } func TestGetEncodedPassword(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'test_encode_u'@'localhost' identified by 'root';`) - pc := privilege.GetPrivilegeManager(se) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER 'test_encode_u'@'localhost' identified by 'root';`) + pc := privilege.GetPrivilegeManager(tk.Session()) require.Equal(t, pc.GetEncodedPassword("test_encode_u", "localhost"), "*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B") } func TestAuthHost(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - se := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'test_auth_host'@'%';`) - mustExec(t, rootSe, `GRANT ALL ON *.* TO 'test_auth_host'@'%' WITH GRANT OPTION;`) + rootTk := testkit.NewTestKit(t, store) + tk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'test_auth_host'@'%';`) + rootTk.MustExec(`GRANT ALL ON *.* TO 'test_auth_host'@'%' WITH GRANT OPTION;`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) - mustExec(t, se, "CREATE USER 'test_auth_host'@'192.168.%';") - mustExec(t, se, "GRANT SELECT ON *.* TO 'test_auth_host'@'192.168.%';") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) + tk.MustExec("CREATE USER 'test_auth_host'@'192.168.%';") + tk.MustExec("GRANT SELECT ON *.* TO 'test_auth_host'@'192.168.%';") - require.True(t, se.Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), "create user test_auth_host_a") + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) + err := tk.ExecToErr("create user test_auth_host_a") require.Error(t, err) - mustExec(t, rootSe, "DROP USER 'test_auth_host'@'192.168.%';") - mustExec(t, rootSe, "DROP USER 'test_auth_host'@'%';") + rootTk.MustExec("DROP USER 'test_auth_host'@'192.168.%';") + rootTk.MustExec("DROP USER 'test_auth_host'@'%';") } func TestDefaultRoles(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, `CREATE USER 'testdefault'@'localhost';`) - mustExec(t, rootSe, `CREATE ROLE 'testdefault_r1'@'localhost', 'testdefault_r2'@'localhost';`) - mustExec(t, rootSe, `GRANT 'testdefault_r1'@'localhost', 'testdefault_r2'@'localhost' TO 'testdefault'@'localhost';`) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec(`CREATE USER 'testdefault'@'localhost';`) + rootTk.MustExec(`CREATE ROLE 'testdefault_r1'@'localhost', 'testdefault_r2'@'localhost';`) + rootTk.MustExec(`GRANT 'testdefault_r1'@'localhost', 'testdefault_r2'@'localhost' TO 'testdefault'@'localhost';`) - se := newSession(t, store, dbName) - pc := privilege.GetPrivilegeManager(se) + tk := testkit.NewTestKit(t, store) + pc := privilege.GetPrivilegeManager(tk.Session()) ret := pc.GetDefaultRoles("testdefault", "localhost") require.Len(t, ret, 0) - mustExec(t, rootSe, `SET DEFAULT ROLE ALL TO 'testdefault'@'localhost';`) + rootTk.MustExec(`SET DEFAULT ROLE ALL TO 'testdefault'@'localhost';`) ret = pc.GetDefaultRoles("testdefault", "localhost") require.Len(t, ret, 2) - mustExec(t, rootSe, `SET DEFAULT ROLE NONE TO 'testdefault'@'localhost';`) + rootTk.MustExec(`SET DEFAULT ROLE NONE TO 'testdefault'@'localhost';`) ret = pc.GetDefaultRoles("testdefault", "localhost") require.Len(t, ret, 0) } @@ -1578,7 +1605,7 @@ func TestUserTableConsistency(t *testing.T) { defer clean() tk := testkit.NewAsyncTestKit(t, store) - ctx := tk.OpenSession(context.Background(), dbName) + ctx := tk.OpenSession(context.Background(), "test") tk.MustExec(ctx, "create user superadmin") tk.MustExec(ctx, "grant all privileges on *.* to 'superadmin'") @@ -1606,144 +1633,114 @@ func TestFieldList(t *testing.T) { // Issue #14237 List fields RPC store, clean := testkit.CreateMockStore(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, `CREATE USER 'tableaccess'@'localhost'`) - mustExec(t, se, `CREATE TABLE fieldlistt1 (a int)`) - require.True(t, se.Auth(&auth.UserIdentity{Username: "tableaccess", Hostname: "localhost"}, nil, nil)) - _, err := se.FieldList("fieldlistt1") + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`CREATE USER 'tableaccess'@'localhost'`) + tk.MustExec(`CREATE TABLE fieldlistt1 (a int)`) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "tableaccess", Hostname: "localhost"}, nil, nil)) + _, err := tk.Session().FieldList("fieldlistt1") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) } -func mustExec(t *testing.T, se session.Session, sql string) { - _, err := se.ExecuteInternal(context.Background(), sql) - require.NoError(t, err) -} - -func newStore(t *testing.T) (kv.Storage, func()) { - store, err := mockstore.NewMockStore() - require.NoError(t, err) - dom, err := session.BootstrapSession(store) - require.NoError(t, err) - setUpTest(t, store, dbName) - - clean := func() { - tearDownTest(t, store, dbName) - dom.Close() - err = store.Close() - require.NoError(t, err) - } - return store, clean -} - -func newSession(t *testing.T, store kv.Storage, dbName string) session.Session { - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - mustExec(t, se, "create database if not exists "+dbName) - mustExec(t, se, "use "+dbName) - return se -} - func TestDynamicPrivs(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, "CREATE USER notsuper") - mustExec(t, rootSe, "CREATE USER otheruser") - mustExec(t, rootSe, "CREATE ROLE anyrolename") + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec("CREATE USER notsuper") + rootTk.MustExec("CREATE USER otheruser") + rootTk.MustExec("CREATE ROLE anyrolename") - se := newSession(t, store, dbName) - require.True(t, se.Auth(&auth.UserIdentity{Username: "notsuper", Hostname: "%"}, nil, nil)) + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "notsuper", Hostname: "%"}, nil, nil)) // test SYSTEM_VARIABLES_ADMIN - _, err := se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86400") + err := tk.ExecToErr("SET GLOBAL wait_timeout = 86400") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") - mustExec(t, rootSe, "GRANT SYSTEM_VARIABLES_admin ON *.* TO notsuper") - mustExec(t, se, "SET GLOBAL wait_timeout = 86400") + rootTk.MustExec("GRANT SYSTEM_VARIABLES_admin ON *.* TO notsuper") + tk.MustExec("SET GLOBAL wait_timeout = 86400") // test ROLE_ADMIN - _, err = se.ExecuteInternal(context.Background(), "GRANT anyrolename TO otheruser") + err = tk.ExecToErr("GRANT anyrolename TO otheruser") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or ROLE_ADMIN privilege(s) for this operation") - mustExec(t, rootSe, "GRANT ROLE_ADMIN ON *.* TO notsuper") - mustExec(t, se, "GRANT anyrolename TO otheruser") + rootTk.MustExec("GRANT ROLE_ADMIN ON *.* TO notsuper") + tk.MustExec("GRANT anyrolename TO otheruser") // revoke SYSTEM_VARIABLES_ADMIN, confirm it is dropped - mustExec(t, rootSe, "REVOKE SYSTEM_VARIABLES_AdmIn ON *.* FROM notsuper") - _, err = se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86000") + rootTk.MustExec("REVOKE SYSTEM_VARIABLES_AdmIn ON *.* FROM notsuper") + err = tk.ExecToErr("SET GLOBAL wait_timeout = 86000") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") // grant super, confirm that it is also a substitute for SYSTEM_VARIABLES_ADMIN - mustExec(t, rootSe, "GRANT SUPER ON *.* TO notsuper") - mustExec(t, se, "SET GLOBAL wait_timeout = 86400") + rootTk.MustExec("GRANT SUPER ON *.* TO notsuper") + tk.MustExec("SET GLOBAL wait_timeout = 86400") // revoke SUPER, assign SYSTEM_VARIABLES_ADMIN to anyrolename. // confirm that a dynamic privilege can be inherited from a role. - mustExec(t, rootSe, "REVOKE SUPER ON *.* FROM notsuper") - mustExec(t, rootSe, "GRANT SYSTEM_VARIABLES_AdmIn ON *.* TO anyrolename") - mustExec(t, rootSe, "GRANT anyrolename TO notsuper") + rootTk.MustExec("REVOKE SUPER ON *.* FROM notsuper") + rootTk.MustExec("GRANT SYSTEM_VARIABLES_AdmIn ON *.* TO anyrolename") + rootTk.MustExec("GRANT anyrolename TO notsuper") // It's not a default role, this should initially fail: - _, err = se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86400") + err = tk.ExecToErr("SET GLOBAL wait_timeout = 86400") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") - mustExec(t, se, "SET ROLE anyrolename") - mustExec(t, se, "SET GLOBAL wait_timeout = 87000") + tk.MustExec("SET ROLE anyrolename") + tk.MustExec("SET GLOBAL wait_timeout = 87000") } func TestDynamicGrantOption(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, "CREATE USER varuser1") - mustExec(t, rootSe, "CREATE USER varuser2") - mustExec(t, rootSe, "CREATE USER varuser3") - - mustExec(t, rootSe, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser1") - mustExec(t, rootSe, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser2 WITH GRANT OPTION") + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec("CREATE USER varuser1") + rootTk.MustExec("CREATE USER varuser2") + rootTk.MustExec("CREATE USER varuser3") - se1 := newSession(t, store, dbName) + rootTk.MustExec("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser1") + rootTk.MustExec("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser2 WITH GRANT OPTION") - require.True(t, se1.Auth(&auth.UserIdentity{Username: "varuser1", Hostname: "%"}, nil, nil)) - _, err := se1.ExecuteInternal(context.Background(), "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") + tk1 := testkit.NewTestKit(t, store) + require.True(t, tk1.Session().Auth(&auth.UserIdentity{Username: "varuser1", Hostname: "%"}, nil, nil)) + err := tk1.ExecToErr("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation") - se2 := newSession(t, store, dbName) - - require.True(t, se2.Auth(&auth.UserIdentity{Username: "varuser2", Hostname: "%"}, nil, nil)) - mustExec(t, se2, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") + tk2 := testkit.NewTestKit(t, store) + require.True(t, tk2.Session().Auth(&auth.UserIdentity{Username: "varuser2", Hostname: "%"}, nil, nil)) + tk2.MustExec("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") } func TestSecurityEnhancedModeRestrictedTables(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() // This provides an integration test of the tests in util/security/security_test.go - cloudAdminSe := newSession(t, store, dbName) - mustExec(t, cloudAdminSe, "CREATE USER cloudadmin") - mustExec(t, cloudAdminSe, "GRANT RESTRICTED_TABLES_ADMIN, SELECT ON *.* to cloudadmin") - mustExec(t, cloudAdminSe, "GRANT CREATE ON mysql.* to cloudadmin") - mustExec(t, cloudAdminSe, "CREATE USER uroot") - mustExec(t, cloudAdminSe, "GRANT ALL ON *.* to uroot WITH GRANT OPTION") // A "MySQL" all powerful user. - require.True(t, cloudAdminSe.Auth(&auth.UserIdentity{Username: "cloudadmin", Hostname: "%"}, nil, nil)) - urootSe := newSession(t, store, dbName) - require.True(t, urootSe.Auth(&auth.UserIdentity{Username: "uroot", Hostname: "%"}, nil, nil)) + cloudAdminTK := testkit.NewTestKit(t, store) + cloudAdminTK.MustExec("CREATE USER cloudadmin") + cloudAdminTK.MustExec("GRANT RESTRICTED_TABLES_ADMIN, SELECT ON *.* to cloudadmin") + cloudAdminTK.MustExec("GRANT CREATE ON mysql.* to cloudadmin") + cloudAdminTK.MustExec("CREATE USER uroot") + cloudAdminTK.MustExec("GRANT ALL ON *.* to uroot WITH GRANT OPTION") // A "MySQL" all powerful user. + require.True(t, cloudAdminTK.Session().Auth(&auth.UserIdentity{Username: "cloudadmin", Hostname: "%"}, nil, nil)) + urootTk := testkit.NewTestKit(t, store) + require.True(t, urootTk.Session().Auth(&auth.UserIdentity{Username: "uroot", Hostname: "%"}, nil, nil)) sem.Enable() defer sem.Disable() - _, err := urootSe.ExecuteInternal(context.Background(), "use metrics_schema") + err := urootTk.ExecToErr("use metrics_schema") require.EqualError(t, err, "[executor:1044]Access denied for user 'uroot'@'%' to database 'metrics_schema'") - _, err = urootSe.ExecuteInternal(context.Background(), "SELECT * FROM metrics_schema.uptime") + err = urootTk.ExecToErr("SELECT * FROM metrics_schema.uptime") require.EqualError(t, err, "[planner:1142]SELECT command denied to user 'uroot'@'%' for table 'uptime'") - _, err = urootSe.ExecuteInternal(context.Background(), "CREATE TABLE mysql.abcd (a int)") + err = urootTk.ExecToErr("CREATE TABLE mysql.abcd (a int)") require.EqualError(t, err, "[planner:1142]CREATE command denied to user 'uroot'@'%' for table 'abcd'") - mustExec(t, cloudAdminSe, "USE metrics_schema") - mustExec(t, cloudAdminSe, "SELECT * FROM metrics_schema.uptime") - mustExec(t, cloudAdminSe, "CREATE TABLE mysql.abcd (a int)") + cloudAdminTK.MustExec("USE metrics_schema") + cloudAdminTK.MustExec("SELECT * FROM metrics_schema.uptime") + cloudAdminTK.MustExec("CREATE TABLE mysql.abcd (a int)") } func TestSecurityEnhancedModeInfoschema(t *testing.T) { @@ -1780,7 +1777,7 @@ func TestSecurityEnhancedModeInfoschema(t *testing.T) { } func TestClusterConfigInfoschema(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -1867,7 +1864,7 @@ func TestSecurityEnhancedModeStatusVars(t *testing.T) { // So we can only test that the dynamic privilege is grantable. // We will have to use an integration test to run SHOW STATUS LIKE 'tidb_gc_leader_desc' // and verify if it appears. - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER unostatus, ustatus") @@ -1880,7 +1877,7 @@ func TestSecurityEnhancedModeStatusVars(t *testing.T) { } func TestSecurityEnhancedLocalBackupRestore(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -1923,65 +1920,67 @@ func TestSecurityEnhancedLocalBackupRestore(t *testing.T) { } func TestRenameUser(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - rootSe := newSession(t, store, dbName) - mustExec(t, rootSe, "DROP USER IF EXISTS 'ru1'@'localhost'") - mustExec(t, rootSe, "DROP USER IF EXISTS ru3") - mustExec(t, rootSe, "DROP USER IF EXISTS ru6@localhost") - mustExec(t, rootSe, "CREATE USER 'ru1'@'localhost'") - mustExec(t, rootSe, "CREATE USER ru3") - mustExec(t, rootSe, "CREATE USER ru6@localhost") - se1 := newSession(t, store, dbName) - require.True(t, se1.Auth(&auth.UserIdentity{Username: "ru1", Hostname: "localhost"}, nil, nil)) + rootTk := testkit.NewTestKit(t, store) + rootTk.MustExec("DROP USER IF EXISTS 'ru1'@'localhost'") + rootTk.MustExec("DROP USER IF EXISTS ru3") + rootTk.MustExec("DROP USER IF EXISTS ru6@localhost") + rootTk.MustExec("CREATE USER 'ru1'@'localhost'") + rootTk.MustExec("CREATE USER ru3") + rootTk.MustExec("CREATE USER ru6@localhost") + tk := testkit.NewTestKit(t, store) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "ru1", Hostname: "localhost"}, nil, nil)) // Check privileges (need CREATE USER) - _, err := se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru4") + err := tk.ExecToErr("RENAME USER ru3 TO ru4") require.Error(t, err) require.Regexp(t, "Access denied; you need .at least one of. the CREATE USER privilege.s. for this operation$", err.Error()) - mustExec(t, rootSe, "GRANT UPDATE ON mysql.user TO 'ru1'@'localhost'") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru4") + rootTk.MustExec("GRANT UPDATE ON mysql.user TO 'ru1'@'localhost'") + err = tk.ExecToErr("RENAME USER ru3 TO ru4") require.Error(t, err) require.Regexp(t, "Access denied; you need .at least one of. the CREATE USER privilege.s. for this operation$", err.Error()) - mustExec(t, rootSe, "GRANT CREATE USER ON *.* TO 'ru1'@'localhost'") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru4") - require.NoError(t, err) + rootTk.MustExec("GRANT CREATE USER ON *.* TO 'ru1'@'localhost'") + tk.MustExec("RENAME USER ru3 TO ru4") // Test a few single rename (both Username and Hostname) - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER 'ru4'@'%' TO 'ru3'@'localhost'") - require.NoError(t, err) - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER 'ru3'@'localhost' TO 'ru3'@'%'") - require.NoError(t, err) - // Including negative tests, i.e. non existing from user and existing to user - _, err = rootSe.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru1@localhost") + tk.MustExec("RENAME USER 'ru4'@'%' TO 'ru3'@'localhost'") + tk.MustExec("RENAME USER 'ru3'@'localhost' TO 'ru3'@'%'") + // Including negative tests, i.e. non-existing from user and existing to user + err = rootTk.ExecToErr("RENAME USER ru3 TO ru1@localhost") require.Error(t, err) require.Contains(t, err.Error(), "Operation RENAME USER failed for ru3@%") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru4 TO ru5@localhost") + err = tk.ExecToErr("RENAME USER ru4 TO ru5@localhost") require.Error(t, err) require.Contains(t, err.Error(), "Operation RENAME USER failed for ru4@%") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru3") + err = tk.ExecToErr("RENAME USER ru3 TO ru3") require.Error(t, err) require.Contains(t, err.Error(), "Operation RENAME USER failed for ru3@%") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru5@localhost, ru4 TO ru7") + err = tk.ExecToErr("RENAME USER ru3 TO ru5@localhost, ru4 TO ru7") require.Error(t, err) require.Contains(t, err.Error(), "Operation RENAME USER failed for ru4@%") - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER ru3 TO ru5@localhost, ru6@localhost TO ru1@localhost") + err = tk.ExecToErr("RENAME USER ru3 TO ru5@localhost, ru6@localhost TO ru1@localhost") require.Error(t, err) require.Contains(t, err.Error(), "Operation RENAME USER failed for ru6@localhost") // Test multi rename, this is a full swap of ru3 and ru6, i.e. need to read its previous state in the same transaction. - _, err = se1.ExecuteInternal(context.Background(), "RENAME USER 'ru3' TO 'ru3_tmp', ru6@localhost TO ru3, 'ru3_tmp' to ru6@localhost") - require.NoError(t, err) + tk.MustExec("RENAME USER 'ru3' TO 'ru3_tmp', ru6@localhost TO ru3, 'ru3_tmp' to ru6@localhost") + + // Test rename to a too long name + err = tk.ExecToErr("RENAME USER 'ru6@localhost' TO '1234567890abcdefGHIKL1234567890abcdefGHIKL@localhost'") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String '1234567890abcdefGHIKL1234567890abcdefGHIKL' is too long for user name (should be no longer than 32)") + err = tk.ExecToErr("RENAME USER 'ru6@localhost' TO 'some_user_name@host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890X'") + require.Truef(t, terror.ErrorEqual(err, executor.ErrWrongStringLength), "ERROR 1470 (HY000): String 'host_1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij12345' is too long for host name (should be no longer than 255)") // Cleanup - mustExec(t, rootSe, "DROP USER ru6@localhost") - mustExec(t, rootSe, "DROP USER ru3") - mustExec(t, rootSe, "DROP USER 'ru1'@'localhost'") + rootTk.MustExec("DROP USER ru6@localhost") + rootTk.MustExec("DROP USER ru3") + rootTk.MustExec("DROP USER 'ru1'@'localhost'") } func TestSecurityEnhancedModeSysVars(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2002,16 +2001,22 @@ func TestSecurityEnhancedModeSysVars(t *testing.T) { tk.MustQuery(`SHOW VARIABLES LIKE 'tidb_force_priority'`).Check(testkit.Rows()) tk.MustQuery(`SHOW GLOBAL VARIABLES LIKE 'tidb_enable_telemetry'`).Check(testkit.Rows()) + tk.MustQuery(`SHOW GLOBAL VARIABLES LIKE 'tidb_top_sql_max_time_series_count'`).Check(testkit.Rows()) + tk.MustQuery(`SHOW GLOBAL VARIABLES LIKE 'tidb_top_sql_max_meta_count'`).Check(testkit.Rows()) _, err := tk.Exec("SET tidb_force_priority = 'NO_PRIORITY'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") _, err = tk.Exec("SET GLOBAL tidb_enable_telemetry = OFF") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") + _, err = tk.Exec("SET GLOBAL tidb_top_sql_max_time_series_count = 100") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") _, err = tk.Exec("SELECT @@session.tidb_force_priority") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") _, err = tk.Exec("SELECT @@global.tidb_enable_telemetry") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") + _, err = tk.Exec("SELECT @@global.tidb_top_sql_max_time_series_count") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_VARIABLES_ADMIN privilege(s) for this operation") tk.Session().Auth(&auth.UserIdentity{ Username: "svroot2", @@ -2029,12 +2034,18 @@ func TestSecurityEnhancedModeSysVars(t *testing.T) { tk.MustQuery(`SELECT @@session.tidb_force_priority`).Check(testkit.Rows("NO_PRIORITY")) tk.MustQuery(`SELECT @@global.tidb_enable_telemetry`).Check(testkit.Rows("1")) + + tk.MustQuery(`SELECT @@hostname`).Check(testkit.Rows(variable.DefHostname)) + sem.Disable() + if hostname, err := os.Hostname(); err == nil { + tk.MustQuery(`SELECT @@hostname`).Check(testkit.Rows(hostname)) + } } // TestViewDefiner tests that default roles are correctly applied in the algorithm definer // See: https://github.com/pingcap/tidb/issues/24414 func TestViewDefiner(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2063,7 +2074,7 @@ func TestViewDefiner(t *testing.T) { } func TestSecurityEnhancedModeRestrictedUsers(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2111,11 +2122,11 @@ func TestSecurityEnhancedModeRestrictedUsers(t *testing.T) { } func TestDynamicPrivsRegistration(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - pm := privilege.GetPrivilegeManager(se) + tk := testkit.NewTestKit(t, store) + pm := privilege.GetPrivilegeManager(tk.Session()) count := len(privileges.GetDynamicPrivileges()) @@ -2132,7 +2143,7 @@ func TestDynamicPrivsRegistration(t *testing.T) { require.Equal(t, "privilege name is longer than 32 characters", privileges.RegisterDynamicPrivilege("THIS_PRIVILEGE_NAME_IS_TOO_LONG_THE_MAX_IS_32_CHARS").Error()) require.False(t, pm.IsDynamicPrivilege("THIS_PRIVILEGE_NAME_IS_TOO_LONG_THE_MAX_IS_32_CHARS")) - tk := testkit.NewTestKit(t, store) + tk = testkit.NewTestKit(t, store) tk.MustExec("CREATE USER privassigntest") // Check that all privileges registered are assignable to users, @@ -2153,7 +2164,7 @@ func TestDynamicPrivsRegistration(t *testing.T) { func TestInfoSchemaUserPrivileges(t *testing.T) { // Being able to read all privileges from information_schema.user_privileges requires a very specific set of permissions. // SUPER user is not sufficient. It was observed in MySQL to require SELECT on mysql.* - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2211,7 +2222,7 @@ func TestInfoSchemaUserPrivileges(t *testing.T) { // Issues https://github.com/pingcap/tidb/issues/25972 and https://github.com/pingcap/tidb/issues/26451 func TestGrantOptionAndRevoke(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2259,36 +2270,24 @@ func TestGrantOptionAndRevoke(t *testing.T) { "GRANT USAGE ON test.testgrant TO 'u3'@'%' WITH GRANT OPTION", )) } -func setUpTest(t *testing.T, store kv.Storage, dbName string) { - se := newSession(t, store, dbName) - createDBSQL := fmt.Sprintf("create database if not exists %s;", dbName) - createDB1SQL := fmt.Sprintf("create database if not exists %s1;", dbName) - useDBSQL := fmt.Sprintf("use %s;", dbName) - createTableSQL := `CREATE TABLE test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));` - - mustExec(t, se, createDBSQL) - mustExec(t, se, createDB1SQL) // create database test1 - mustExec(t, se, useDBSQL) - mustExec(t, se, createTableSQL) - - createSystemDBSQL := fmt.Sprintf("create database if not exists %s;", mysql.SystemDB) - - mustExec(t, se, createSystemDBSQL) - mustExec(t, se, session.CreateUserTable) - mustExec(t, se, session.CreateDBPrivTable) - mustExec(t, se, session.CreateTablePrivTable) - mustExec(t, se, session.CreateColumnPrivTable) -} -func tearDownTest(t *testing.T, store kv.Storage, dbName string) { - // drop db - se := newSession(t, store, dbName) - dropDBSQL := fmt.Sprintf("drop database if exists %s;", dbName) - mustExec(t, se, dropDBSQL) +func createStoreAndPrepareDB(t *testing.T) (kv.Storage, func()) { + store, clean := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database if not exists test") + tk.MustExec("create database if not exists test1") + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));`) + tk.MustExec(fmt.Sprintf("create database if not exists %s;", mysql.SystemDB)) + tk.MustExec(session.CreateUserTable) + tk.MustExec(session.CreateDBPrivTable) + tk.MustExec(session.CreateTablePrivTable) + tk.MustExec(session.CreateColumnPrivTable) + return store, clean } func TestGrantReferences(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2313,7 +2312,7 @@ func TestGrantReferences(t *testing.T) { } func TestDashboardClientDynamicPriv(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2357,7 +2356,7 @@ func TestDashboardClientDynamicPriv(t *testing.T) { // https://github.com/pingcap/tidb/issues/27213 func TestShowGrantsWithRolesAndDynamicPrivs(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2445,7 +2444,7 @@ func TestShowGrantsWithRolesAndDynamicPrivs(t *testing.T) { } func TestGrantLockTables(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2469,7 +2468,7 @@ func TestGrantLockTables(t *testing.T) { // https://github.com/pingcap/tidb/issues/27560 func TestShowGrantsForCurrentUserUsingRole(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2506,21 +2505,20 @@ func TestShowGrantsForCurrentUserUsingRole(t *testing.T) { "GRANT USAGE ON *.* TO 'joe'@'%'", "GRANT SELECT ON test.* TO 'joe'@'%'", "GRANT UPDATE ON role.* TO 'joe'@'%'", - "GRANT DELETE ON mysql.user TO 'joe'@'%'", + "GRANT SELECT,DELETE ON mysql.user TO 'joe'@'%'", "GRANT 'admins'@'%', 'engineering'@'%', 'otherrole'@'%' TO 'joe'@'%'", )) tk.MustQuery("SHOW GRANTS FOR joe USING otherrole;").Check(testkit.Rows( "GRANT USAGE ON *.* TO 'joe'@'%'", "GRANT SELECT ON test.* TO 'joe'@'%'", "GRANT UPDATE ON role.* TO 'joe'@'%'", - "GRANT DELETE ON mysql.user TO 'joe'@'%'", + "GRANT SELECT,DELETE ON mysql.user TO 'joe'@'%'", "GRANT 'admins'@'%', 'engineering'@'%', 'otherrole'@'%' TO 'joe'@'%'", )) - } func TestGrantPlacementAdminDynamicPriv(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2542,97 +2540,44 @@ func TestGrantPlacementAdminDynamicPriv(t *testing.T) { } func TestPlacementPolicyStmt(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, "drop placement policy if exists x") + tk := testkit.NewTestKit(t, store) + tk.MustExec("drop placement policy if exists x") createStmt := "create placement policy x PRIMARY_REGION=\"cn-east-1\" REGIONS=\"cn-east-1\"" dropStmt := "drop placement policy if exists x" // high privileged user setting password for other user (passes) - mustExec(t, se, "CREATE USER super_user, placement_user, empty_user") - mustExec(t, se, "GRANT ALL ON *.* TO super_user") - mustExec(t, se, "GRANT PLACEMENT_ADMIN ON *.* TO placement_user") + tk.MustExec("CREATE USER super_user, placement_user, empty_user") + tk.MustExec("GRANT ALL ON *.* TO super_user") + tk.MustExec("GRANT PLACEMENT_ADMIN ON *.* TO placement_user") - require.True(t, se.Auth(&auth.UserIdentity{Username: "empty_user", Hostname: "localhost"}, nil, nil)) - _, err := se.ExecuteInternal(context.Background(), createStmt) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "empty_user", Hostname: "localhost"}, nil, nil)) + err := tk.ExecToErr(createStmt) require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or PLACEMENT_ADMIN privilege(s) for this operation") - _, err = se.ExecuteInternal(context.Background(), dropStmt) + err = tk.ExecToErr(dropStmt) require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or PLACEMENT_ADMIN privilege(s) for this operation") - require.True(t, se.Auth(&auth.UserIdentity{Username: "super_user", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, createStmt) - mustExec(t, se, dropStmt) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "super_user", Hostname: "localhost"}, nil, nil)) + tk.MustExec(createStmt) + tk.MustExec(dropStmt) - require.True(t, se.Auth(&auth.UserIdentity{Username: "placement_user", Hostname: "localhost"}, nil, nil)) - mustExec(t, se, createStmt) - mustExec(t, se, dropStmt) + require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "placement_user", Hostname: "localhost"}, nil, nil)) + tk.MustExec(createStmt) + tk.MustExec(dropStmt) } func TestDBNameCaseSensitivityInTableLevel(t *testing.T) { - store, clean := newStore(t) - defer clean() - se := newSession(t, store, dbName) - mustExec(t, se, "CREATE USER test_user") - mustExec(t, se, "grant select on metrics_schema.up to test_user;") -} - -func TestInformationSchemaPlacmentRulesPrivileges(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() - tk := testkit.NewTestKit(t, store) - - defer func() { - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "root", - Hostname: "localhost", - }, nil, nil)) - tk.MustExec(`DROP SCHEMA IF EXISTS placment_rule_db`) - tk.MustExec(`DROP USER IF EXISTS placement_rule_user_scheam`) - tk.MustExec(`DROP USER IF EXISTS placement_rule_user_table`) - }() - tk.MustExec("CREATE DATABASE placement_rule_db") - tk.MustExec("USE placement_rule_db") - tk.Session().GetSessionVars().EnableAlterPlacement = true - tk.MustExec(`CREATE TABLE placement_rule_table_se (a int) PRIMARY_REGION="se" REGIONS="se,nl"`) - tk.MustExec(`CREATE TABLE placement_rule_table_nl (a int) PRIMARY_REGION="nl" REGIONS="se,nl"`) - tk.MustQuery(`SELECT * FROM information_schema.placement_rules WHERE SCHEMA_NAME = "placement_rule_db"`).Sort().Check(testkit.Rows( - " def placement_rule_db placement_rule_table_nl nl se,nl 0 0", - " def placement_rule_db placement_rule_table_se se se,nl 0 0")) - tk.MustExec("CREATE USER placement_rule_user_schema") - tk.MustExec("CREATE USER placement_rule_user_table") - tk.MustExec("GRANT SELECT ON placement_rule_db.placement_rule_table_se TO placement_rule_user_table") - - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "placement_rule_user_schema", - Hostname: "somehost", - }, nil, nil)) - tk.MustQuery(`SELECT * FROM information_schema.placement_rules WHERE SCHEMA_NAME = "placement_rule_db"`).Check(testkit.Rows()) - - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "placement_rule_user_table", - Hostname: "somehost", - }, nil, nil)) - tk.MustQuery(`SELECT * FROM information_schema.placement_rules WHERE SCHEMA_NAME = "placement_rule_db"`).Check(testkit.Rows(" def placement_rule_db placement_rule_table_se se se,nl 0 0")) - - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "root", - Hostname: "localhost", - }, nil, nil)) - tk.MustExec("GRANT SELECT ON placement_rule_db.* TO placement_rule_user_schema") - require.True(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "placement_rule_user_schema", - Hostname: "somehost", - }, nil, nil)) - tk.MustQuery(`SELECT * FROM information_schema.placement_rules WHERE SCHEMA_NAME = "placement_rule_db"`).Sort().Check(testkit.Rows( - " def placement_rule_db placement_rule_table_nl nl se,nl 0 0", - " def placement_rule_db placement_rule_table_se se se,nl 0 0")) + tk.MustExec("CREATE USER test_user") + tk.MustExec("grant select on metrics_schema.up to test_user;") } func TestGrantCreateTmpTables(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2656,7 +2601,7 @@ func TestGrantCreateTmpTables(t *testing.T) { } func TestCreateTmpTablesPriv(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() createStmt := "CREATE TEMPORARY TABLE test.tmp(id int)" @@ -2813,7 +2758,7 @@ func TestCreateTmpTablesPriv(t *testing.T) { } func TestRevokeSecondSyntax(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2829,7 +2774,7 @@ func TestRevokeSecondSyntax(t *testing.T) { } func TestGrantEvent(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2852,7 +2797,7 @@ func TestGrantEvent(t *testing.T) { } func TestGrantRoutine(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2877,7 +2822,7 @@ func TestGrantRoutine(t *testing.T) { } func TestIssue28675(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) @@ -2895,7 +2840,9 @@ func TestIssue28675(t *testing.T) { tk.MustExec("grant select on test.v to test_user") require.True(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_user", Hostname: "localhost"}, nil, nil)) tk.MustQuery("select count(*) from information_schema.columns where table_schema='test' and table_name='v'").Check(testkit.Rows("1")) + tk.MustQuery("select count(*) from information_schema.columns where table_schema='Test' and table_name='V'").Check(testkit.Rows("1")) tk.MustQuery("select privileges from information_schema.columns where table_schema='test' and table_name='v'").Check(testkit.Rows("select,update")) + tk.MustQuery("select privileges from information_schema.columns where table_schema='Test' and table_name='V'").Check(testkit.Rows("select,update")) require.Equal(t, 1, len(tk.MustQuery("desc test.v").Rows())) require.Equal(t, 1, len(tk.MustQuery("explain test.v").Rows())) } @@ -2905,7 +2852,7 @@ func TestSkipGrantTable(t *testing.T) { config.UpdateGlobal(func(c *config.Config) { c.Security.SkipGrantTable = true }) defer config.StoreGlobalConfig(save) - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() // Issue 29317 @@ -2941,8 +2888,24 @@ func TestSkipGrantTable(t *testing.T) { tk.MustExec(`GRANT RESTRICTED_USER_ADMIN ON *.* TO 'test2'@'%';`) } +// https://github.com/pingcap/tidb/issues/32891 +func TestIncorrectUsageDBGrant(t *testing.T) { + store, clean := createStoreAndPrepareDB(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec(`CREATE USER ucorrect1, ucorrect2;`) + tk.MustExec(`CREATE TABLE test.trigger_table (a int)`) + tk.MustExec(`GRANT CREATE TEMPORARY TABLES,DELETE,EXECUTE,INSERT,SELECT,SHOW VIEW,TRIGGER,UPDATE ON test.* TO ucorrect1;`) + tk.MustExec(`GRANT TRIGGER ON test.trigger_table TO ucorrect2;`) + tk.MustExec(`DROP TABLE test.trigger_table`) + + err := tk.ExecToErr(`GRANT CREATE TEMPORARY TABLES,DELETE,EXECUTE,INSERT,SELECT,SHOW VIEW,TRIGGER,UPDATE ON test.* TO uincorrect;`) + require.EqualError(t, err, "[executor:1410]You are not allowed to create a user with GRANT") +} + func TestIssue29823(t *testing.T) { - store, clean := newStore(t) + store, clean := createStoreAndPrepareDB(t) defer clean() tk := testkit.NewTestKit(t, store) diff --git a/server/conn.go b/server/conn.go index e9325a6dd97d6..bd6147e2514ae 100644 --- a/server/conn.go +++ b/server/conn.go @@ -59,6 +59,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" @@ -85,6 +86,7 @@ import ( "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/prometheus/client_golang/prometheus" "github.com/tikv/client-go/v2/util" "go.uber.org/zap" @@ -1063,12 +1065,16 @@ func (cc *clientConn) Run(ctx context.Context) { if err != nil { if terror.ErrorNotEqual(err, io.EOF) { if netErr, isNetErr := errors.Cause(err).(net.Error); isNetErr && netErr.Timeout() { - idleTime := time.Since(start) - logutil.Logger(ctx).Info("read packet timeout, close this connection", - zap.Duration("idle", idleTime), - zap.Uint64("waitTimeout", waitTimeout), - zap.Error(err), - ) + if atomic.LoadInt32(&cc.status) == connStatusWaitShutdown { + logutil.Logger(ctx).Info("read packet timeout because of killed connection") + } else { + idleTime := time.Since(start) + logutil.Logger(ctx).Info("read packet timeout, close this connection", + zap.Duration("idle", idleTime), + zap.Uint64("waitTimeout", waitTimeout), + zap.Error(err), + ) + } } else { errStack := errors.ErrorStack(err) if !strings.Contains(errStack, "use of closed network connection") { @@ -1110,12 +1116,17 @@ func (cc *clientConn) Run(ctx context.Context) { if storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err) { logutil.Logger(ctx).Debug("Expected error for FOR UPDATE NOWAIT", zap.Error(err)) } else { + var startTS uint64 + if cc.ctx != nil && cc.ctx.GetSessionVars() != nil && cc.ctx.GetSessionVars().TxnCtx != nil { + startTS = cc.ctx.GetSessionVars().TxnCtx.StartTS + } logutil.Logger(ctx).Info("command dispatched failed", zap.String("connInfo", cc.String()), zap.String("command", mysql.Command2Str[data[0]]), zap.String("status", cc.SessionStatusToString()), zap.Stringer("sql", getLastStmtInConn{cc}), zap.String("txn_mode", txnMode), + zap.Uint64("timestamp", startTS), zap.String("err", errStrForLog(err, cc.ctx.GetSessionVars().EnableRedactLog)), ) } @@ -1254,7 +1265,7 @@ func (cc *clientConn) dispatch(ctx context.Context, data []byte) error { cc.lastPacket = data cmd := data[0] data = data[1:] - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { defer pprof.SetGoroutineLabels(ctx) } if variable.EnablePProfSQLCPU.Load() { @@ -1374,11 +1385,21 @@ func (cc *clientConn) dispatch(ctx context.Context, data []byte) error { } func (cc *clientConn) writeStats(ctx context.Context) error { - msg := []byte("Uptime: 0 Threads: 0 Questions: 0 Slow queries: 0 Opens: 0 Flush tables: 0 Open tables: 0 Queries per second avg: 0.000") + var err error + var uptime int64 = 0 + info := serverInfo{} + info.ServerInfo, err = infosync.GetServerInfo() + if err != nil { + logutil.BgLogger().Error("Failed to get ServerInfo for uptime status", zap.Error(err)) + } else { + uptime = int64(time.Since(time.Unix(info.ServerInfo.StartTimestamp, 0)).Seconds()) + } + msg := []byte(fmt.Sprintf("Uptime: %d Threads: 0 Questions: 0 Slow queries: 0 Opens: 0 Flush tables: 0 Open tables: 0 Queries per second avg: 0.000", + uptime)) data := cc.alloc.AllocWithLen(4, len(msg)) data = append(data, msg...) - err := cc.writePacket(data) + err = cc.writePacket(data) if err != nil { return err } @@ -1828,6 +1849,17 @@ func (cc *clientConn) handleQuery(ctx context.Context, sql string) (err error) { } retryable, err = cc.handleStmt(ctx, stmt, parserWarns, i == len(stmts)-1) if err != nil { + if retryable && cc.ctx.GetSessionVars().IsRcCheckTsRetryable(err) { + cc.ctx.GetSessionVars().RetryInfo.Retrying = true + logutil.Logger(ctx).Info("RC read with ts checking has failed, retry RC read", + zap.String("sql", cc.ctx.GetSessionVars().StmtCtx.OriginalSQL)) + _, err = cc.handleStmt(ctx, stmt, parserWarns, i == len(stmts)-1) + cc.ctx.GetSessionVars().RetryInfo.Retrying = false + if err != nil { + break + } + continue + } if !retryable || !errors.ErrorEqual(err, storeerr.ErrTiFlashServerTimeout) { break } @@ -1874,8 +1906,8 @@ func (cc *clientConn) prefetchPointPlanKeys(ctx context.Context, stmts []ast.Stm } } pointPlans := make([]plannercore.Plan, len(stmts)) - var idxKeys []kv.Key - var rowKeys []kv.Key + var idxKeys []kv.Key // nolint: prealloc + var rowKeys []kv.Key // nolint: prealloc sc := vars.StmtCtx for i, stmt := range stmts { switch stmt.(type) { @@ -2201,14 +2233,13 @@ func (cc *clientConn) writeChunks(ctx context.Context, rs ResultSet, binary bool func (cc *clientConn) writeChunksWithFetchSize(ctx context.Context, rs ResultSet, serverStatus uint16, fetchSize int) error { fetchedRows := rs.GetFetchedRows() // if fetchedRows is not enough, getting data from recordSet. + // NOTE: chunk should not be allocated from the allocator + // the allocator will reset every statement + // but it maybe stored in the result set among statements + // ref https://github.com/pingcap/tidb/blob/7fc6ebbda4ddf84c0ba801ca7ebb636b934168cf/server/conn_stmt.go#L233-L239 + // Here server.tidbResultSet implements Next method. req := rs.NewChunk(nil) for len(fetchedRows) < fetchSize { - // NOTE: chunk should not be allocated from the allocator - // the allocator will reset every statement - // but it maybe stored in the result set among statements - // ref https://github.com/pingcap/tidb/blob/7fc6ebbda4ddf84c0ba801ca7ebb636b934168cf/server/conn_stmt.go#L233-L239 - // Here server.tidbResultSet implements Next method. - req.Reset() if err := rs.Next(ctx, req); err != nil { return err } @@ -2220,6 +2251,7 @@ func (cc *clientConn) writeChunksWithFetchSize(ctx context.Context, rs ResultSet for i := 0; i < rowCount; i++ { fetchedRows = append(fetchedRows, req.GetRow(i)) } + req = chunk.Renew(req, cc.ctx.GetSessionVars().MaxChunkSize) } // tell the client COM_STMT_FETCH has finished by setting proper serverStatus, @@ -2309,6 +2341,7 @@ func (cc *clientConn) handleChangeUser(ctx context.Context, data []byte) error { if err := cc.ctx.Close(); err != nil { logutil.Logger(ctx).Debug("close old context failed", zap.Error(err)) } + cc.ctx = nil if err := cc.openSessionAndDoAuth(pass, ""); err != nil { return err } diff --git a/server/conn_stmt.go b/server/conn_stmt.go index 07e4699d52738..f1e519eecbe55 100644 --- a/server/conn_stmt.go +++ b/server/conn_stmt.go @@ -51,13 +51,15 @@ import ( "github.com/pingcap/tidb/parser/terror" plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx/stmtctx" - "github.com/pingcap/tidb/sessionctx/variable" storeerr "github.com/pingcap/tidb/store/driver/error" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hack" + "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/topsql" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/tikv/client-go/v2/util" + "go.uber.org/zap" ) func (cc *clientConn) handleStmtPrepare(ctx context.Context, sql string) error { @@ -128,13 +130,6 @@ func (cc *clientConn) handleStmtExecute(ctx context.Context, data []byte) (err e stmtID := binary.LittleEndian.Uint32(data[0:4]) pos += 4 - if variable.TopSQLEnabled() { - preparedStmt, _ := cc.preparedStmtID2CachePreparedStmt(stmtID) - if preparedStmt != nil && preparedStmt.SQLDigest != nil { - ctx = topsql.AttachSQLInfo(ctx, preparedStmt.NormalizedSQL, preparedStmt.SQLDigest, "", nil, false) - } - } - stmt := cc.ctx.GetStatement(int(stmtID)) if stmt == nil { return mysql.NewErr(mysql.ErrUnknownStmtHandler, @@ -169,7 +164,6 @@ func (cc *clientConn) handleStmtExecute(ctx context.Context, data []byte) (err e paramValues []byte ) cc.initInputEncoder(ctx) - defer cc.inputDecoder.clean() numParams := stmt.NumParams() args := make([]types.Datum, numParams) if numParams > 0 { @@ -206,6 +200,14 @@ func (cc *clientConn) handleStmtExecute(ctx context.Context, data []byte) (err e ctx = context.WithValue(ctx, execdetails.StmtExecDetailKey, &execdetails.StmtExecDetails{}) ctx = context.WithValue(ctx, util.ExecDetailsKey, &util.ExecDetails{}) retryable, err := cc.executePreparedStmtAndWriteResult(ctx, stmt, args, useCursor) + if retryable && err != nil && cc.ctx.GetSessionVars().IsRcCheckTsRetryable(err) { + logutil.Logger(ctx).Info("RC read using start_ts has failed, retry RC read", + zap.String("sql", cc.ctx.GetSessionVars().StmtCtx.OriginalSQL)) + cc.ctx.GetSessionVars().RetryInfo.Retrying = true + _, err = cc.executePreparedStmtAndWriteResult(ctx, stmt, args, useCursor) + cc.ctx.GetSessionVars().RetryInfo.Retrying = false + return err + } _, allowTiFlashFallback := cc.ctx.GetSessionVars().AllowFallbackToTiKV[kv.TiFlash] if allowTiFlashFallback && err != nil && errors.ErrorEqual(err, storeerr.ErrTiFlashServerTimeout) && retryable { // When the TiFlash server seems down, we append a warning to remind the user to check the status of the TiFlash @@ -276,7 +278,7 @@ func (cc *clientConn) handleStmtFetch(ctx context.Context, data []byte) (err err return errors.Annotate(mysql.NewErr(mysql.ErrUnknownStmtHandler, strconv.FormatUint(uint64(stmtID), 10), "stmt_fetch"), cc.preparedStmt2String(stmtID)) } - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { prepareObj, _ := cc.preparedStmtID2CachePreparedStmt(stmtID) if prepareObj != nil && prepareObj.SQLDigest != nil { ctx = topsql.AttachSQLInfo(ctx, prepareObj.NormalizedSQL, prepareObj.SQLDigest, "", nil, false) @@ -331,7 +333,7 @@ func parseExecArgs(sc *stmtctx.StatementContext, args []types.Datum, boundParams // ref https://dev.mysql.com/doc/internals/en/com-stmt-send-long-data.html // see clientConn#handleStmtSendLongData if boundParams[i] != nil { - args[i] = types.NewBytesDatum(boundParams[i]) + args[i] = types.NewBytesDatum(enc.decodeInput(boundParams[i])) continue } diff --git a/server/conn_stmt_test.go b/server/conn_stmt_test.go index cd63aea7e66bf..a4ff4c2ee7070 100644 --- a/server/conn_stmt_test.go +++ b/server/conn_stmt_test.go @@ -214,6 +214,16 @@ func TestParseExecArgsAndEncode(t *testing.T) { newInputDecoder("gbk")) require.NoError(t, err) require.Equal(t, "测试", dt[0].GetValue()) + + err = parseExecArgs(&stmtctx.StatementContext{}, + dt, + [][]byte{{178, 226, 202, 212}}, + []byte{0x0}, + []byte{mysql.TypeString, 0}, + []byte{}, + newInputDecoder("gbk")) + require.NoError(t, err) + require.Equal(t, "测试", dt[0].GetString()) } func TestParseStmtFetchCmd(t *testing.T) { diff --git a/server/conn_test.go b/server/conn_test.go index a599ccee48702..f6fbcb5e53c8e 100644 --- a/server/conn_test.go +++ b/server/conn_test.go @@ -27,15 +27,13 @@ import ( "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/unistore" - "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util/arena" "github.com/pingcap/tidb/util/chunk" "github.com/stretchr/testify/require" @@ -43,6 +41,125 @@ import ( "github.com/tikv/client-go/v2/testutils" ) +type Issue33699CheckType struct { + name string + defVal string + setVal string + isSessionVariable bool +} + +func (c *Issue33699CheckType) toSetSessionVar() string { + if c.isSessionVariable { + return fmt.Sprintf("set session %s=%s", c.name, c.setVal) + } + return fmt.Sprintf("set @%s=%s", c.name, c.setVal) +} + +func (c *Issue33699CheckType) toGetSessionVar() string { + if c.isSessionVariable { + return fmt.Sprintf("select @@session.%s", c.name) + } + return fmt.Sprintf("select @%s", c.name) +} + +func TestIssue33699(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + var outBuffer bytes.Buffer + tidbdrv := NewTiDBDriver(store) + cfg := newTestConfig() + cfg.Port, cfg.Status.StatusPort = 0, 0 + cfg.Status.ReportStatus = false + server, err := NewServer(cfg, tidbdrv) + require.NoError(t, err) + defer server.Close() + + cc := &clientConn{ + connectionID: 1, + salt: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}, + server: server, + pkt: &packetIO{ + bufWriter: bufio.NewWriter(&outBuffer), + }, + collation: mysql.DefaultCollationID, + peerHost: "localhost", + alloc: arena.NewAllocator(512), + chunkAlloc: chunk.NewAllocator(), + capability: mysql.ClientProtocol41, + } + + tk := testkit.NewTestKit(t, store) + ctx := &TiDBContext{Session: tk.Session()} + cc.ctx = ctx + + // change user. + doChangeUser := func() { + userData := append([]byte("root"), 0x0, 0x0) + userData = append(userData, []byte("test")...) + userData = append(userData, 0x0) + changeUserReq := dispatchInput{ + com: mysql.ComChangeUser, + in: userData, + err: nil, + out: []byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, + } + inBytes := append([]byte{changeUserReq.com}, changeUserReq.in...) + err = cc.dispatch(context.Background(), inBytes) + require.Equal(t, changeUserReq.err, err) + if err == nil { + err = cc.flush(context.TODO()) + require.NoError(t, err) + require.Equal(t, changeUserReq.out, outBuffer.Bytes()) + } else { + _ = cc.flush(context.TODO()) + } + outBuffer.Reset() + } + // check variable. + checks := []Issue33699CheckType{ + { // self define. + "a", + "", + "1", + false, + }, + { // session variable + "net_read_timeout", + "30", + "1234", + true, + }, + { + "net_write_timeout", + "60", + "1234", + true, + }, + } + + // default; + for _, ck := range checks { + tk.MustQuery(ck.toGetSessionVar()).Check(testkit.Rows(ck.defVal)) + } + // set; + for _, ck := range checks { + tk.MustExec(ck.toSetSessionVar()) + } + // check after set. + for _, ck := range checks { + tk.MustQuery(ck.toGetSessionVar()).Check(testkit.Rows(ck.setVal)) + } + doChangeUser() + require.NotEqual(t, ctx, cc.ctx) + require.NotEqual(t, ctx.Session, cc.ctx.Session) + // new session,so values is defaults; + tk.SetSession(cc.ctx.Session) // set new session. + for _, ck := range checks { + tk.MustQuery(ck.toGetSessionVar()).Check(testkit.Rows(ck.defVal)) + } +} + func TestMalformHandshakeHeader(t *testing.T) { data := []byte{0x00} var p handshakeResponse41 @@ -718,16 +835,6 @@ func TestPrefetchPointKeys(t *testing.T) { tk.MustQuery("select * from prefetch").Check(testkit.Rows("1 1 3", "2 2 6", "3 3 5")) } -func testGetTableByName(t *testing.T, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - require.NoError(t, err) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - require.NoError(t, err) - return tbl -} - func TestTiFlashFallback(t *testing.T) { store, clean := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) { @@ -757,7 +864,7 @@ func TestTiFlashFallback(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int not null primary key, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(t, tk.Session(), "test", "t") + tb := external.GetTableByName(t, tk, "test", "t") err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) require.NoError(t, err) diff --git a/server/driver_tidb.go b/server/driver_tidb.go index 9a13eea632962..2594f9a140b46 100644 --- a/server/driver_tidb.go +++ b/server/driver_tidb.go @@ -25,13 +25,13 @@ import ( "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/planner" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/sqlexec" + "github.com/pingcap/tidb/util/topsql/stmtstats" ) // TiDBDriver implements IDriver. @@ -80,8 +80,7 @@ func (ts *TiDBStatement) Execute(ctx context.Context, args []types.Datum) (rs Re return } rs = &tidbResultSet{ - recordSet: tidbRecordset, - preparedStmt: ts.ctx.GetSessionVars().PreparedStmts[ts.id].(*core.CachedPrepareStmt), + recordSet: tidbRecordset, } return } @@ -165,10 +164,13 @@ func (ts *TiDBStatement) Close() error { if !ok { return errors.Errorf("invalid CachedPrepareStmt type") } - preparedAst := preparedObj.PreparedAst - bindSQL := planner.GetBindSQL4PlanCache(ts.ctx, preparedAst.Stmt) - ts.ctx.PreparedPlanCache().Delete(core.NewPSTMTPlanCacheKey( - ts.ctx.GetSessionVars(), ts.id, preparedObj.PreparedAst.SchemaVersion, bindSQL)) + cacheKey, err := core.NewPlanCacheKey(ts.ctx.GetSessionVars(), preparedObj.StmtText, preparedObj.StmtDB, preparedObj.PreparedAst.SchemaVersion) + if err != nil { + return err + } + if !ts.ctx.GetSessionVars().IgnorePreparedCacheCloseStmt { // keep the plan in cache + ts.ctx.PreparedPlanCache().Delete(cacheKey) + } } ts.ctx.GetSessionVars().RemovePreparedStmt(ts.id) } @@ -293,12 +295,16 @@ func (tc *TiDBContext) Prepare(sql string) (statement PreparedStatement, columns return } +// GetStmtStats implements the sessionctx.Context interface. +func (tc *TiDBContext) GetStmtStats() *stmtstats.StatementStats { + return tc.Session.GetStmtStats() +} + type tidbResultSet struct { - recordSet sqlexec.RecordSet - columns []*ColumnInfo - rows []chunk.Row - closed int32 - preparedStmt *core.CachedPrepareStmt + recordSet sqlexec.RecordSet + columns []*ColumnInfo + rows []chunk.Row + closed int32 } func (trs *tidbResultSet) NewChunk(alloc chunk.Allocator) *chunk.Chunk { @@ -340,23 +346,12 @@ func (trs *tidbResultSet) Columns() []*ColumnInfo { if trs.columns != nil { return trs.columns } - // for prepare statement, try to get cached columnInfo array - if trs.preparedStmt != nil { - ps := trs.preparedStmt - if colInfos, ok := ps.ColumnInfos.([]*ColumnInfo); ok { - trs.columns = colInfos - } - } + if trs.columns == nil { fields := trs.recordSet.Fields() for _, v := range fields { trs.columns = append(trs.columns, convertColumnInfo(v)) } - if trs.preparedStmt != nil { - // if ColumnInfo struct has allocated object, - // here maybe we need deep copy ColumnInfo to do caching - trs.preparedStmt.ColumnInfos = trs.columns - } } return trs.columns } @@ -375,15 +370,13 @@ func convertColumnInfo(fld *ast.ResultField) (ci *ColumnInfo) { if fld.Table != nil { ci.OrgTable = fld.Table.Name.O } - if fld.Column.Flen == types.UnspecifiedLength { - ci.ColumnLength = 0 - } else { + if fld.Column.Flen != types.UnspecifiedLength { ci.ColumnLength = uint32(fld.Column.Flen) } if fld.Column.Tp == mysql.TypeNewDecimal { // Consider the negative sign. ci.ColumnLength++ - if fld.Column.Decimal > int(types.DefaultFsp) { + if fld.Column.Decimal > types.DefaultFsp { // Consider the decimal point. ci.ColumnLength++ } diff --git a/server/driver_tidb_test.go b/server/driver_tidb_test.go index b7126b31e00b4..a16168cd5017d 100644 --- a/server/driver_tidb_test.go +++ b/server/driver_tidb_test.go @@ -25,14 +25,14 @@ import ( "github.com/stretchr/testify/require" ) -func createColumnByTypeAndLen(tp byte, len uint32) *ColumnInfo { +func createColumnByTypeAndLen(tp byte, cl uint32) *ColumnInfo { return &ColumnInfo{ Schema: "test", Table: "dual", OrgTable: "", Name: "a", OrgName: "a", - ColumnLength: len, + ColumnLength: cl, Charset: uint16(mysql.CharsetNameToID(charset.CharsetUTF8)), Flag: uint16(mysql.UnsignedFlag), Decimal: uint8(0), diff --git a/server/http_handler.go b/server/http_handler.go index 3fe4ac8587cd7..9e9d6e204bc33 100644 --- a/server/http_handler.go +++ b/server/http_handler.go @@ -63,6 +63,7 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/deadlockhistory" "github.com/pingcap/tidb/util/gcutil" + "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/sqlexec" @@ -706,9 +707,9 @@ func (h settingsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if checkMb4ValueInUtf8 := req.Form.Get("check_mb4_value_in_utf8"); checkMb4ValueInUtf8 != "" { switch checkMb4ValueInUtf8 { case "0": - config.GetGlobalConfig().CheckMb4ValueInUTF8 = false + config.GetGlobalConfig().CheckMb4ValueInUTF8.Store(false) case "1": - config.GetGlobalConfig().CheckMb4ValueInUTF8 = true + config.GetGlobalConfig().CheckMb4ValueInUTF8.Store(true) default: writeError(w, errors.New("illegal argument")) return @@ -738,6 +739,28 @@ func (h settingsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { cfg.PessimisticTxn.DeadlockHistoryCollectRetryable = collectRetryable config.StoreGlobalConfig(cfg) } + if mutationChecker := req.Form.Get("tidb_enable_mutation_checker"); mutationChecker != "" { + s, err := session.CreateSession(h.Store) + if err != nil { + writeError(w, err) + return + } + defer s.Close() + + switch mutationChecker { + case "0": + err = s.GetSessionVars().GlobalVarsAccessor.SetGlobalSysVar(variable.TiDBEnableMutationChecker, variable.Off) + case "1": + err = s.GetSessionVars().GlobalVarsAccessor.SetGlobalSysVar(variable.TiDBEnableMutationChecker, variable.On) + default: + writeError(w, errors.New("illegal argument")) + return + } + if err != nil { + writeError(w, err) + return + } + } } else { writeData(w, config.GetGlobalConfig()) } @@ -1056,6 +1079,51 @@ func (h schemaStorageHandler) ServeHTTP(w http.ResponseWriter, req *http.Request } } +// writeDBTablesData writes all the table data in a database. The format is the marshal result of []*model.TableInfo, you can +// unmarshal it to []*model.TableInfo. In this function, we manually construct the marshal result so that the memory +// can be deallocated quickly. +// For every table in the input, we marshal them. The result such as {tb1} {tb2} {tb3}. +// Then we add some bytes to make it become [{tb1}, {tb2}, {tb3}], so we can unmarshal it to []*model.TableInfo. +// Note: It would return StatusOK even if errors occur. But if errors occur, there must be some bugs. +func writeDBTablesData(w http.ResponseWriter, tbs []table.Table) { + if len(tbs) == 0 { + writeData(w, []*model.TableInfo{}) + return + } + w.Header().Set(headerContentType, contentTypeJSON) + // We assume that marshal is always OK. + w.WriteHeader(http.StatusOK) + _, err := w.Write(hack.Slice("[\n")) + if err != nil { + terror.Log(errors.Trace(err)) + return + } + init := false + for _, tb := range tbs { + if init { + _, err = w.Write(hack.Slice(",\n")) + if err != nil { + terror.Log(errors.Trace(err)) + return + } + } else { + init = true + } + js, err := json.MarshalIndent(tb.Meta(), "", " ") + if err != nil { + terror.Log(errors.Trace(err)) + return + } + _, err = w.Write(js) + if err != nil { + terror.Log(errors.Trace(err)) + return + } + } + _, err = w.Write(hack.Slice("\n]")) + terror.Log(errors.Trace(err)) +} + // ServeHTTP handles request of list a database or table's schemas. func (h schemaHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { schema, err := h.schema() @@ -1083,11 +1151,7 @@ func (h schemaHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // all table schemas in a specified database if schema.SchemaExists(cDBName) { tbs := schema.SchemaTables(cDBName) - tbsInfo := make([]*model.TableInfo, len(tbs)) - for i := range tbsInfo { - tbsInfo[i] = tbs[i].Meta() - } - writeData(w, tbsInfo) + writeDBTablesData(w, tbs) return } writeError(w, infoschema.ErrDatabaseNotExists.GenWithStackByArgs(dbName)) @@ -1231,7 +1295,7 @@ func (h ddlResignOwnerHandler) resignDDLOwner() error { // ServeHTTP handles request of resigning ddl owner. func (h ddlResignOwnerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Method != http.MethodPost { - writeError(w, errors.Errorf("This api only support POST method.")) + writeError(w, errors.Errorf("This api only support POST method")) return } @@ -1479,7 +1543,7 @@ func (h tableHandler) getRegionsByID(tbl table.Table, id int64, name string) (*T func (h tableHandler) handleDiskUsageRequest(tbl table.Table, w http.ResponseWriter) { tableID := tbl.Meta().ID var stats helper.PDRegionStats - err := h.GetPDRegionStats(tableID, &stats) + err := h.GetPDRegionStats(tableID, &stats, false) if err != nil { writeError(w, err) return @@ -1740,7 +1804,7 @@ func (h mvccTxnHandler) handleMvccGetByKey(params map[string]string, values url. respValue := resp.Value var result interface{} = resp if respValue.Info != nil { - datas := make(map[string][]map[string]string) + datas := make(map[string]map[string]string) for _, w := range respValue.Info.Writes { if len(w.ShortValue) > 0 { datas[strconv.FormatUint(w.StartTs, 10)], err = h.decodeMvccData(w.ShortValue, colMap, tb.Meta()) @@ -1769,16 +1833,16 @@ func (h mvccTxnHandler) handleMvccGetByKey(params map[string]string, values url. return result, nil } -func (h mvccTxnHandler) decodeMvccData(bs []byte, colMap map[int64]*types.FieldType, tb *model.TableInfo) ([]map[string]string, error) { +func (h mvccTxnHandler) decodeMvccData(bs []byte, colMap map[int64]*types.FieldType, tb *model.TableInfo) (map[string]string, error) { rs, err := tablecodec.DecodeRowToDatumMap(bs, colMap, time.UTC) - var record []map[string]string + record := make(map[string]string, len(tb.Columns)) for _, col := range tb.Columns { if c, ok := rs[col.ID]; ok { data := "nil" if !c.IsNull() { data, err = c.ToString() } - record = append(record, map[string]string{col.Name.O: data}) + record[col.Name.O] = data } } return record, err @@ -2046,7 +2110,7 @@ func (h *testHandler) handleGCResolveLocks(w http.ResponseWriter, req *http.Requ // ServeHTTP handles request of resigning ddl owner. func (h ddlHookHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Method != http.MethodPost { - writeError(w, errors.Errorf("This api only support POST method.")) + writeError(w, errors.Errorf("This api only support POST method")) return } diff --git a/server/http_handler_serial_test.go b/server/http_handler_serial_test.go index 2cbd9bb7c3fb3..befbdcbfa1109 100644 --- a/server/http_handler_serial_test.go +++ b/server/http_handler_serial_test.go @@ -32,7 +32,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/log" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" + ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -119,7 +119,7 @@ func TestPostSettings(t *testing.T) { require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) require.NoError(t, resp.Body.Close()) - require.Equal(t, true, config.GetGlobalConfig().CheckMb4ValueInUTF8) + require.Equal(t, true, config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()) txn1, err := dbt.GetDB().Begin() require.NoError(t, err) _, err = txn1.Exec("insert t2 values (unhex('F0A48BAE'));") @@ -134,7 +134,7 @@ func TestPostSettings(t *testing.T) { require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) require.NoError(t, resp.Body.Close()) - require.Equal(t, false, config.GetGlobalConfig().CheckMb4ValueInUTF8) + require.Equal(t, false, config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()) dbt.MustExec("insert t2 values (unhex('f09f8c80'));") // test deadlock_history_capacity @@ -185,7 +185,7 @@ func TestPostSettings(t *testing.T) { require.NoError(t, resp.Body.Close()) // restore original value. - config.GetGlobalConfig().CheckMb4ValueInUTF8 = true + config.GetGlobalConfig().CheckMb4ValueInUTF8.Store(true) } func TestAllServerInfo(t *testing.T) { @@ -264,15 +264,15 @@ func TestTiFlashReplica(t *testing.T) { defer func(originGC bool) { if originGC { - ddl.EmulatorGCEnable() + ddlutil.EmulatorGCEnable() } else { - ddl.EmulatorGCDisable() + ddlutil.EmulatorGCDisable() } - }(ddl.IsEmulatorGCEnable()) + }(ddlutil.IsEmulatorGCEnable()) // Disable emulator GC. // Otherwise emulator GC will delete table record as soon as possible after execute drop table DDL. - ddl.EmulatorGCDisable() + ddlutil.EmulatorGCDisable() gcTimeFormat := "20060102-15:04:05 -0700 MST" timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', ''),('tikv_gc_enable','true','') @@ -281,7 +281,7 @@ func TestTiFlashReplica(t *testing.T) { // Set GC safe point and enable GC. dbt.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) - resp, err := ts.fetchStatus("/tiflash/replica") + resp, err := ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder := json.NewDecoder(resp.Body) var data []tableFlashReplicaInfo @@ -298,7 +298,7 @@ func TestTiFlashReplica(t *testing.T) { dbt.MustExec("use tidb") dbt.MustExec("alter table test set tiflash replica 2 location labels 'a','b';") - resp, err = ts.fetchStatus("/tiflash/replica") + resp, err = ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) @@ -309,7 +309,7 @@ func TestTiFlashReplica(t *testing.T) { require.Equal(t, "a,b", strings.Join(data[0].LocationLabels, ",")) require.Equal(t, false, data[0].Available) - resp, err = ts.postStatus("/tiflash/replica", "application/json", bytes.NewBuffer([]byte(`{"id":84,"region_count":3,"flash_region_count":3}`))) + resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(`{"id":84,"region_count":3,"flash_region_count":3}`))) require.NoError(t, err) require.NotNil(t, resp) body, err := io.ReadAll(resp.Body) @@ -320,7 +320,7 @@ func TestTiFlashReplica(t *testing.T) { tbl, err := ts.domain.InfoSchema().TableByName(model.NewCIStr("tidb"), model.NewCIStr("test")) require.NoError(t, err) req := fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, tbl.Meta().ID) - resp, err = ts.postStatus("/tiflash/replica", "application/json", bytes.NewBuffer([]byte(req))) + resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req))) require.NoError(t, err) require.NotNil(t, resp) body, err = io.ReadAll(resp.Body) @@ -328,7 +328,7 @@ func TestTiFlashReplica(t *testing.T) { require.NoError(t, resp.Body.Close()) require.Equal(t, "", string(body)) - resp, err = ts.fetchStatus("/tiflash/replica") + resp, err = ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) @@ -342,7 +342,7 @@ func TestTiFlashReplica(t *testing.T) { // Should not take effect. dbt.MustExec("alter table test set tiflash replica 2 location labels 'a','b';") checkFunc := func() { - resp, err := ts.fetchStatus("/tiflash/replica") + resp, err := ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) @@ -369,7 +369,7 @@ func TestTiFlashReplica(t *testing.T) { // Test for partition table. dbt.MustExec("alter table pt set tiflash replica 2 location labels 'a','b';") dbt.MustExec("alter table test set tiflash replica 0;") - resp, err = ts.fetchStatus("/tiflash/replica") + resp, err = ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) @@ -387,10 +387,10 @@ func TestTiFlashReplica(t *testing.T) { // Mock for partition 1 replica was available. req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid1) - resp, err = ts.postStatus("/tiflash/replica", "application/json", bytes.NewBuffer([]byte(req))) + resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req))) require.NoError(t, err) require.NoError(t, resp.Body.Close()) - resp, err = ts.fetchStatus("/tiflash/replica") + resp, err = ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) @@ -403,16 +403,16 @@ func TestTiFlashReplica(t *testing.T) { // Mock for partition 0,2 replica was available. req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid0) - resp, err = ts.postStatus("/tiflash/replica", "application/json", bytes.NewBuffer([]byte(req))) + resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req))) require.NoError(t, err) err = resp.Body.Close() require.NoError(t, err) req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid2) - resp, err = ts.postStatus("/tiflash/replica", "application/json", bytes.NewBuffer([]byte(req))) + resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req))) require.NoError(t, err) require.NoError(t, resp.Body.Close()) checkFunc = func() { - resp, err := ts.fetchStatus("/tiflash/replica") + resp, err := ts.fetchStatus("/tiflash/replica-deprecated") require.NoError(t, err) decoder = json.NewDecoder(resp.Body) err = decoder.Decode(&data) diff --git a/server/http_handler_test.go b/server/http_handler_test.go index 48205c192c11e..37dfdfd280562 100644 --- a/server/http_handler_test.go +++ b/server/http_handler_test.go @@ -26,6 +26,7 @@ import ( "io" "net" "net/http" + "net/http/httptest" "net/http/httputil" "sort" "testing" @@ -35,10 +36,12 @@ import ( "github.com/pingcap/log" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/binloginfo" @@ -47,6 +50,7 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/deadlockhistory" @@ -844,8 +848,12 @@ func TestGetSchema(t *testing.T) { } sort.Strings(names) require.Equal(t, expects, names) + store, clean := testkit.CreateMockStore(t) + defer clean() - resp, err = ts.fetchStatus("/schema?table_id=5") + tk := testkit.NewTestKit(t, store) + userTbl := external.GetTableByName(t, tk, "mysql", "user") + resp, err = ts.fetchStatus(fmt.Sprintf("/schema?table_id=%d", userTbl.Meta().ID)) require.NoError(t, err) var ti *model.TableInfo decoder = json.NewDecoder(resp.Body) @@ -873,7 +881,7 @@ func TestGetSchema(t *testing.T) { err = decoder.Decode(<) require.NoError(t, err) require.NoError(t, resp.Body.Close()) - require.Greater(t, len(lt), 0) + require.Greater(t, len(lt), 2) resp, err = ts.fetchStatus("/schema/abc") require.NoError(t, err) @@ -891,7 +899,7 @@ func TestGetSchema(t *testing.T) { require.NoError(t, err) require.NoError(t, resp.Body.Close()) - resp, err = ts.fetchStatus("/db-table/5") + resp, err = ts.fetchStatus(fmt.Sprintf("/db-table/%d", userTbl.Meta().ID)) require.NoError(t, err) var dbtbl *dbTableInfo decoder = json.NewDecoder(resp.Body) @@ -1059,3 +1067,45 @@ func TestDDLHookHandler(t *testing.T) { require.Equal(t, "\"success!\"", string(body)) require.Equal(t, http.StatusOK, resp.StatusCode) } + +func TestWriteDBTablesData(t *testing.T) { + // No table in a schema. + info := infoschema.MockInfoSchema([]*model.TableInfo{}) + rc := httptest.NewRecorder() + tbs := info.SchemaTables(model.NewCIStr("test")) + require.Equal(t, 0, len(tbs)) + writeDBTablesData(rc, tbs) + var ti []*model.TableInfo + decoder := json.NewDecoder(rc.Body) + err := decoder.Decode(&ti) + require.NoError(t, err) + require.Equal(t, 0, len(ti)) + + // One table in a schema. + info = infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable()}) + rc = httptest.NewRecorder() + tbs = info.SchemaTables(model.NewCIStr("test")) + require.Equal(t, 1, len(tbs)) + writeDBTablesData(rc, tbs) + decoder = json.NewDecoder(rc.Body) + err = decoder.Decode(&ti) + require.NoError(t, err) + require.Equal(t, 1, len(ti)) + require.Equal(t, ti[0].ID, tbs[0].Meta().ID) + require.Equal(t, ti[0].Name.String(), tbs[0].Meta().Name.String()) + + // Two tables in a schema. + info = infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + rc = httptest.NewRecorder() + tbs = info.SchemaTables(model.NewCIStr("test")) + require.Equal(t, 2, len(tbs)) + writeDBTablesData(rc, tbs) + decoder = json.NewDecoder(rc.Body) + err = decoder.Decode(&ti) + require.NoError(t, err) + require.Equal(t, 2, len(ti)) + require.Equal(t, ti[0].ID, tbs[0].Meta().ID) + require.Equal(t, ti[1].ID, tbs[1].Meta().ID) + require.Equal(t, ti[0].Name.String(), tbs[0].Meta().Name.String()) + require.Equal(t, ti[1].Name.String(), tbs[1].Meta().Name.String()) +} diff --git a/server/http_status.go b/server/http_status.go index 8248e7c54e3de..0ed6dd07543a8 100644 --- a/server/http_status.go +++ b/server/http_status.go @@ -43,10 +43,10 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/cpuprofile" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/printer" - "github.com/pingcap/tidb/util/topsql/tracecpu" "github.com/pingcap/tidb/util/versioninfo" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/soheilhy/cmux" @@ -80,7 +80,7 @@ func sleepWithCtx(ctx context.Context, d time.Duration) { func (s *Server) listenStatusHTTPServer() error { s.statusAddr = fmt.Sprintf("%s:%d", s.cfg.Status.StatusHost, s.cfg.Status.StatusPort) - if s.cfg.Status.StatusPort == 0 && !runInGoTest { + if s.cfg.Status.StatusPort == 0 && !RunInGoTest { s.statusAddr = fmt.Sprintf("%s:%d", s.cfg.Status.StatusHost, defaultStatusPort) } @@ -102,7 +102,7 @@ func (s *Server) listenStatusHTTPServer() error { if err != nil { logutil.BgLogger().Info("listen failed", zap.Error(err)) return errors.Trace(err) - } else if runInGoTest && s.cfg.Status.StatusPort == 0 { + } else if RunInGoTest && s.cfg.Status.StatusPort == 0 { s.statusAddr = s.statusListener.Addr().String() s.cfg.Status.StatusPort = uint(s.statusListener.Addr().(*net.TCPAddr).Port) } @@ -232,7 +232,7 @@ func (s *Server) startHTTPServer() { // HTTP path for get db and table info that is related to the tableID. router.Handle("/db-table/{tableID}", dbTableHandler{tikvHandlerTool}) // HTTP path for get table tiflash replica info. - router.Handle("/tiflash/replica", flashReplicaHandler{tikvHandlerTool}) + router.Handle("/tiflash/replica-deprecated", flashReplicaHandler{tikvHandlerTool}) if s.cfg.Store == "tikv" { // HTTP path for tikv. @@ -278,7 +278,7 @@ func (s *Server) startHTTPServer() { serverMux.HandleFunc("/debug/pprof/", pprof.Index) serverMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) - serverMux.HandleFunc("/debug/pprof/profile", tracecpu.ProfileHTTPHandler) + serverMux.HandleFunc("/debug/pprof/profile", cpuprofile.ProfileHTTPHandler) serverMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) serverMux.HandleFunc("/debug/pprof/trace", pprof.Trace) @@ -355,7 +355,8 @@ func (s *Server) startHTTPServer() { serveError(w, http.StatusInternalServerError, fmt.Sprintf("Create zipped %s fail: %v", "profile", err)) return } - if err := tracecpu.StartCPUProfile(fw); err != nil { + pc := cpuprofile.NewCollector() + if err := pc.StartCPUProfile(fw); err != nil { serveError(w, http.StatusInternalServerError, fmt.Sprintf("Could not enable CPU profiling: %s", err)) return @@ -365,9 +366,10 @@ func (s *Server) startHTTPServer() { sec = 10 } sleepWithCtx(r.Context(), time.Duration(sec)*time.Second) - err = tracecpu.StopCPUProfile() + err = pc.StopCPUProfile() if err != nil { - serveError(w, http.StatusInternalServerError, fmt.Sprintf("Create zipped %s fail: %v", "config", err)) + serveError(w, http.StatusInternalServerError, + fmt.Sprintf("Could not enable CPU profiling: %s", err)) return } @@ -451,17 +453,20 @@ func (s *Server) startStatusServerAndRPCServer(serverMux *http.ServeMux) { httpL := m.Match(cmux.HTTP1Fast()) grpcL := m.Match(cmux.Any()) - s.statusServer = &http.Server{Addr: s.statusAddr, Handler: CorsHandler{handler: serverMux, cfg: s.cfg}} - s.grpcServer = NewRPCServer(s.cfg, s.dom, s) - service.RegisterChannelzServiceToServer(s.grpcServer) + statusServer := &http.Server{Addr: s.statusAddr, Handler: CorsHandler{handler: serverMux, cfg: s.cfg}} + grpcServer := NewRPCServer(s.cfg, s.dom, s) + service.RegisterChannelzServiceToServer(grpcServer) + + s.statusServer = statusServer + s.grpcServer = grpcServer go util.WithRecovery(func() { - err := s.grpcServer.Serve(grpcL) + err := grpcServer.Serve(grpcL) logutil.BgLogger().Error("grpc server error", zap.Error(err)) }, nil) go util.WithRecovery(func() { - err := s.statusServer.Serve(httpL) + err := statusServer.Serve(httpL) logutil.BgLogger().Error("http server error", zap.Error(err)) }, nil) diff --git a/server/main_test.go b/server/main_test.go index 155d9f9b7294e..1d79b3caf2070 100644 --- a/server/main_test.go +++ b/server/main_test.go @@ -23,15 +23,21 @@ import ( "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/store/mockstore/unistore" "github.com/pingcap/tidb/util/testbridge" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/tikv/client-go/v2/tikv" "go.uber.org/goleak" ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() - runInGoTest = true // flag for NewServer to known it is running in test environment + RunInGoTest = true // flag for NewServer to known it is running in test environment + // Enable TopSQL for all test, and check the resource tag for each RPC request. + // This is used to detect which codes are not tracked by TopSQL. + topsqlstate.EnableTopSQL() + unistore.CheckResourceTagForTopSQLInGoTest = true // AsyncCommit will make DDL wait 2.5s before changing to the next state. // Set schema lease to avoid it from making CI slow. @@ -51,6 +57,7 @@ func TestMain(m *testing.M) { } opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("time.Sleep"), goleak.IgnoreTopFunction("database/sql.(*Tx).awaitDone"), goleak.IgnoreTopFunction("internal/poll.runtime_pollWait"), @@ -59,9 +66,8 @@ func TestMain(m *testing.M) { goleak.IgnoreTopFunction("github.com/pingcap/tidb/server.NewServer.func1"), goleak.IgnoreTopFunction("gopkg.in/natefinch/lumberjack%2ev2.(*Logger).millRun"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1"), - goleak.IgnoreTopFunction("github.com/pingcap/tidb/util/topsql/tracecpu.(*sqlCPUProfiler).startAnalyzeProfileWorker"), } goleak.VerifyTestMain(m, opts...) diff --git a/server/mock_conn.go b/server/mock_conn.go index 14e4daacf059e..1af3c35d59dd2 100644 --- a/server/mock_conn.go +++ b/server/mock_conn.go @@ -69,9 +69,9 @@ func (mc *mockConn) Close() { // CreateMockServer creates a mock server. func CreateMockServer(t *testing.T, store kv.Storage) *Server { - if !runInGoTest { - // If CreateMockServer is called in another package, runInGoTest is not initialized. - runInGoTest = flag.Lookup("test.v") != nil || flag.Lookup("check.v") != nil + if !RunInGoTest { + // If CreateMockServer is called in another package, RunInGoTest is not initialized. + RunInGoTest = flag.Lookup("test.v") != nil || flag.Lookup("check.v") != nil } tidbdrv := NewTiDBDriver(store) cfg := config.NewConfig() diff --git a/server/optimize_trace.go b/server/optimize_trace.go index dcd0184fd87e9..9363ad6c7f2b3 100644 --- a/server/optimize_trace.go +++ b/server/optimize_trace.go @@ -30,6 +30,7 @@ type OptimizeTraceHandler struct { infoGetter *infosync.InfoSyncer address string statusPort uint + scheme string } func (s *Server) newOptimizeTraceHandler() *OptimizeTraceHandler { @@ -37,10 +38,14 @@ func (s *Server) newOptimizeTraceHandler() *OptimizeTraceHandler { oth := &OptimizeTraceHandler{ address: cfg.AdvertiseAddress, statusPort: cfg.Status.StatusPort, + scheme: "http", } if s.dom != nil && s.dom.InfoSyncer() != nil { oth.infoGetter = s.dom.InfoSyncer() } + if len(cfg.Security.ClusterSSLCA) > 0 { + oth.scheme = "https" + } return oth } @@ -55,6 +60,7 @@ func (oth OptimizeTraceHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque statusPort: oth.statusPort, urlPath: fmt.Sprintf("optimize_trace/dump/%s", name), downloadedFilename: "optimize_trace", + scheme: oth.scheme, } handleDownloadFile(handler, w, req) } diff --git a/server/packetio.go b/server/packetio.go index 8ab9e40042fd0..250ae024cd362 100644 --- a/server/packetio.go +++ b/server/packetio.go @@ -49,8 +49,8 @@ import ( const defaultWriterSize = 16 * 1024 var ( - readPacketBytes = metrics.PacketIOHistogram.WithLabelValues("read") - writePacketBytes = metrics.PacketIOHistogram.WithLabelValues("write") + readPacketBytes = metrics.PacketIOCounter.WithLabelValues("read") + writePacketBytes = metrics.PacketIOCounter.WithLabelValues("write") ) // packetIO is a helper to read and write data in packet format. @@ -120,7 +120,7 @@ func (p *packetIO) readPacket() ([]byte, error) { } if len(data) < mysql.MaxPayloadLen { - readPacketBytes.Observe(float64(len(data))) + readPacketBytes.Add(float64(len(data))) return data, nil } @@ -138,14 +138,14 @@ func (p *packetIO) readPacket() ([]byte, error) { } } - readPacketBytes.Observe(float64(len(data))) + readPacketBytes.Add(float64(len(data))) return data, nil } // writePacket writes data that already have header func (p *packetIO) writePacket(data []byte) error { length := len(data) - 4 - writePacketBytes.Observe(float64(len(data))) + writePacketBytes.Add(float64(len(data))) for length >= mysql.MaxPayloadLen { data[0] = 0xff diff --git a/server/plan_replayer.go b/server/plan_replayer.go index 1d9a6a957f06e..b783fad87f66f 100644 --- a/server/plan_replayer.go +++ b/server/plan_replayer.go @@ -22,11 +22,9 @@ import ( "path/filepath" "github.com/gorilla/mux" - "github.com/pingcap/errors" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" - "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/util/logutil" "go.uber.org/zap" ) @@ -36,6 +34,7 @@ type PlanReplayerHandler struct { infoGetter *infosync.InfoSyncer address string statusPort uint + scheme string } func (s *Server) newPlanReplayerHandler() *PlanReplayerHandler { @@ -43,10 +42,14 @@ func (s *Server) newPlanReplayerHandler() *PlanReplayerHandler { prh := &PlanReplayerHandler{ address: cfg.AdvertiseAddress, statusPort: cfg.Status.StatusPort, + scheme: "http", } if s.dom != nil && s.dom.InfoSyncer() != nil { prh.infoGetter = s.dom.InfoSyncer() } + if len(cfg.Security.ClusterSSLCA) > 0 { + prh.scheme = "https" + } return prh } @@ -61,6 +64,7 @@ func (prh PlanReplayerHandler) ServeHTTP(w http.ResponseWriter, req *http.Reques statusPort: prh.statusPort, urlPath: fmt.Sprintf("plan_replyaer/dump/%s", name), downloadedFilename: "plan_replayer", + scheme: prh.scheme, } handleDownloadFile(handler, w, req) } @@ -69,6 +73,8 @@ func handleDownloadFile(handler downloadFileHandler, w http.ResponseWriter, req params := mux.Vars(req) name := params[pFileName] path := handler.filePath + isForwarded := len(req.URL.Query().Get("forward")) > 0 + localAddr := fmt.Sprintf("%s:%v", handler.address, handler.statusPort) exist, err := isExists(path) if err != nil { writeError(w, err) @@ -90,11 +96,6 @@ func handleDownloadFile(handler downloadFileHandler, w http.ResponseWriter, req writeError(w, err) return } - err = os.Remove(path) - if err != nil { - writeError(w, err) - return - } _, err = w.Write(content) if err != nil { writeError(w, err) @@ -102,15 +103,15 @@ func handleDownloadFile(handler downloadFileHandler, w http.ResponseWriter, req } w.Header().Set("Content-Type", "application/zip") w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.zip\"", handler.downloadedFilename)) + logutil.BgLogger().Info("return dump file successfully", zap.String("filename", name), + zap.String("address", localAddr), zap.Bool("forwarded", isForwarded)) return } - if handler.infoGetter == nil { - w.WriteHeader(http.StatusNotFound) - return - } - // we didn't find file for forward request, return 404 - forwarded := req.URL.Query().Get("forward") - if len(forwarded) > 0 { + // handler.infoGetter will be nil only in unit test + // or we couldn't find file for forward request, return 404 + if handler.infoGetter == nil || isForwarded { + logutil.BgLogger().Info("failed to find dump file", zap.String("filename", name), + zap.String("address", localAddr), zap.Bool("forwarded", isForwarded)) w.WriteHeader(http.StatusNotFound) return } @@ -125,14 +126,17 @@ func handleDownloadFile(handler downloadFileHandler, w http.ResponseWriter, req if topo.IP == handler.address && topo.StatusPort == handler.statusPort { continue } - url := fmt.Sprintf("http://%s:%v/%s?forward=true", topo.IP, topo.StatusPort, handler.urlPath) + remoteAddr := fmt.Sprintf("%s/%v", topo.IP, topo.StatusPort) + url := fmt.Sprintf("%s://%s/%s?forward=true", handler.scheme, remoteAddr, handler.urlPath) resp, err := http.Get(url) // #nosec G107 if err != nil { - terror.Log(errors.Trace(err)) - logutil.BgLogger().Error("forward request failed", zap.String("addr", topo.IP), zap.Uint("port", topo.StatusPort), zap.Error(err)) + logutil.BgLogger().Error("forward request failed", + zap.String("remote-addr", remoteAddr), zap.Error(err)) continue } if resp.StatusCode != http.StatusOK { + logutil.BgLogger().Info("can't find file in remote server", zap.String("filename", name), + zap.String("remote-addr", remoteAddr), zap.Int("status-code", resp.StatusCode)) continue } content, err := ioutil.ReadAll(resp.Body) @@ -153,14 +157,19 @@ func handleDownloadFile(handler downloadFileHandler, w http.ResponseWriter, req // find dump file in one remote tidb-server, return file directly w.Header().Set("Content-Type", "application/zip") w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.zip\"", handler.downloadedFilename)) + logutil.BgLogger().Info("return dump file successfully in remote server", + zap.String("filename", name), zap.String("remote-addr", remoteAddr)) return } // we can't find dump file in any tidb-server, return 404 directly - logutil.BgLogger().Error("can't find dump file in any remote server", zap.String("filename", name)) + logutil.BgLogger().Info("can't find dump file in any remote server", zap.String("filename", name)) w.WriteHeader(http.StatusNotFound) + _, err = w.Write([]byte(fmt.Sprintf("can't find dump file %s in any remote server", name))) + writeError(w, err) } type downloadFileHandler struct { + scheme string filePath string fileName string infoGetter *infosync.InfoSyncer diff --git a/server/rpc_server.go b/server/rpc_server.go index 674047781a6bd..3b23539c0bac1 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" + "github.com/pingcap/tidb/util/topsql" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/keepalive" @@ -64,6 +65,7 @@ func NewRPCServer(config *config.Config, dom *domain.Domain, sm util.SessionMana } diagnosticspb.RegisterDiagnosticsServer(s, rpcSrv) tikvpb.RegisterTikvServer(s, rpcSrv) + topsql.RegisterPubSubServer(s) return s } diff --git a/server/server.go b/server/server.go index ce4ef41a2151d..8c6a0731f943b 100644 --- a/server/server.go +++ b/server/server.go @@ -33,6 +33,7 @@ import ( "context" "crypto/tls" "fmt" + "io" "math/rand" "net" "net/http" @@ -56,6 +57,7 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/plugin" + "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/session/txninfo" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util" @@ -69,10 +71,11 @@ import ( ) var ( - serverPID int - osUser string - osVersion string - runInGoTest bool + serverPID int + osUser string + osVersion string + // RunInGoTest represents whether we are run code in test. + RunInGoTest bool ) func init() { @@ -130,6 +133,9 @@ type Server struct { statusServer *http.Server grpcServer *grpc.Server inShutdownMode bool + + sessionMapMutex sync.Mutex + internalSessions map[interface{}]struct{} } // ConnectionCount gets current connection count. @@ -161,10 +167,7 @@ func (s *Server) SetDomain(dom *domain.Domain) { // InitGlobalConnID initialize global connection id. func (s *Server) InitGlobalConnID(serverIDGetter func() uint64) { - s.globalConnID = util.GlobalConnID{ - ServerIDGetter: serverIDGetter, - Is64bits: true, - } + s.globalConnID = util.NewGlobalConnIDWithGetter(serverIDGetter, true) } // newConn creates a new *clientConn from a net.Conn. @@ -191,7 +194,8 @@ func NewServer(cfg *config.Config, driver IDriver) (*Server, error) { driver: driver, concurrentLimiter: NewTokenLimiter(cfg.TokenLimit), clients: make(map[uint64]*clientConn), - globalConnID: util.GlobalConnID{ServerID: 0, Is64bits: true}, + globalConnID: util.NewGlobalConnID(0, true), + internalSessions: make(map[interface{}]struct{}, 100), } s.capability = defaultCapability setTxnScope() @@ -234,7 +238,7 @@ func NewServer(cfg *config.Config, driver IDriver) (*Server, error) { s.capability |= mysql.ClientSSL } - if s.cfg.Host != "" && (s.cfg.Port != 0 || runInGoTest) { + if s.cfg.Host != "" && (s.cfg.Port != 0 || RunInGoTest) { addr := fmt.Sprintf("%s:%d", s.cfg.Host, s.cfg.Port) tcpProto := "tcp" if s.cfg.EnableTCP4Only { @@ -244,7 +248,7 @@ func NewServer(cfg *config.Config, driver IDriver) (*Server, error) { return nil, errors.Trace(err) } logutil.BgLogger().Info("server is running MySQL protocol", zap.String("addr", addr)) - if runInGoTest && s.cfg.Port == 0 { + if RunInGoTest && s.cfg.Port == 0 { s.cfg.Port = uint(s.listener.Addr().(*net.TCPAddr).Port) } } @@ -315,10 +319,8 @@ func cleanupStaleSocket(socket string) error { return fmt.Errorf("unix socket %s exists and is functional, not removing it", socket) } - logutil.BgLogger().Warn("Unix socket exists and is nonfunctional, removing it", - zap.String("socket", socket), zap.Error(err)) - if err = os.Remove(socket); err != nil { - return fmt.Errorf("failed to remove socket file %s", socket) + if err2 := os.Remove(socket); err2 != nil { + return fmt.Errorf("failed to cleanup stale Unix socket file %s: %w", socket, err) } return nil @@ -510,11 +512,17 @@ func (s *Server) onConn(conn *clientConn) { }) terror.Log(err) } - // Some keep alive services will send request to TiDB and disconnect immediately. - // So we only record metrics. - metrics.HandShakeErrorCounter.Inc() - terror.Log(errors.Trace(err)) - terror.Log(errors.Trace(conn.Close())) + if errors.Cause(err) == io.EOF { + // `EOF` means the connection is closed normally, we do not treat it as a noticeable error and log it in 'DEBUG' level. + logutil.BgLogger().With(zap.Uint64("conn", conn.connectionID)). + Debug("EOF", zap.String("remote addr", conn.bufReadConn.RemoteAddr().String())) + } else { + metrics.HandShakeErrorCounter.Inc() + logutil.BgLogger().With(zap.Uint64("conn", conn.connectionID)). + Warn("Server.onConn handshake", zap.Error(err), + zap.String("remote addr", conn.bufReadConn.RemoteAddr().String())) + } + terror.Log(conn.Close()) return } @@ -613,13 +621,23 @@ func (s *Server) checkConnectionCount() error { // ShowProcessList implements the SessionManager interface. func (s *Server) ShowProcessList() map[uint64]*util.ProcessInfo { + rs := make(map[uint64]*util.ProcessInfo) + for connID, pi := range s.getUserProcessList() { + rs[connID] = pi + } + if s.dom != nil { + for connID, pi := range s.dom.SysProcTracker().GetSysProcessList() { + rs[connID] = pi + } + } + return rs +} + +func (s *Server) getUserProcessList() map[uint64]*util.ProcessInfo { s.rwlock.RLock() defer s.rwlock.RUnlock() - rs := make(map[uint64]*util.ProcessInfo, len(s.clients)) + rs := make(map[uint64]*util.ProcessInfo) for _, client := range s.clients { - if atomic.LoadInt32(&client.status) == connStatusWaitShutdown { - continue - } if pi := client.ctx.ShowProcess(); pi != nil { rs[pi.ID] = pi } @@ -662,7 +680,8 @@ func (s *Server) Kill(connectionID uint64, query bool) { s.rwlock.RLock() defer s.rwlock.RUnlock() conn, ok := s.clients[connectionID] - if !ok { + if !ok && s.dom != nil { + s.dom.SysProcTracker().KillSysProcess(connectionID) return } @@ -692,6 +711,11 @@ func killConn(conn *clientConn) { if cancelFunc != nil { cancelFunc() } + if conn.bufReadConn != nil { + if err := conn.bufReadConn.SetReadDeadline(time.Now()); err != nil { + logutil.BgLogger().Warn("error setting read deadline for kill.", zap.Error(err)) + } + } } // KillAllConnections kills all connections when server is not gracefully shutdown. @@ -778,6 +802,35 @@ func (s *Server) ServerID() uint64 { return s.dom.ServerID() } +// StoreInternalSession implements SessionManager interface. +// @param addr The address of a session.session struct variable +func (s *Server) StoreInternalSession(se interface{}) { + s.sessionMapMutex.Lock() + s.internalSessions[se] = struct{}{} + s.sessionMapMutex.Unlock() +} + +// DeleteInternalSession implements SessionManager interface. +// @param addr The address of a session.session struct variable +func (s *Server) DeleteInternalSession(se interface{}) { + s.sessionMapMutex.Lock() + delete(s.internalSessions, se) + s.sessionMapMutex.Unlock() +} + +// GetInternalSessionStartTSList implements SessionManager interface. +func (s *Server) GetInternalSessionStartTSList() []uint64 { + s.sessionMapMutex.Lock() + defer s.sessionMapMutex.Unlock() + tsList := make([]uint64, 0, len(s.internalSessions)) + for se := range s.internalSessions { + if ts := session.GetStartTSFromSession(se); ts != 0 { + tsList = append(tsList, ts) + } + } + return tsList +} + // setSysTimeZoneOnce is used for parallel run tests. When several servers are running, // only the first will actually do setSystemTimeZoneVariable, thus we can avoid data race. var setSysTimeZoneOnce = &sync.Once{} diff --git a/server/server_test.go b/server/server_test.go index 034587d7be1f7..c09bfbd7a9c20 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -400,10 +400,11 @@ func (cli *testServerClient) runTestLoadDataWithSelectIntoOutfile(t *testing.T, } func (cli *testServerClient) runTestLoadDataForSlowLog(t *testing.T, server *Server) { - path := "/tmp/load_data_test.csv" - fp, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + t.Skip("unstable test") + fp, err := os.CreateTemp("", "load_data_test.csv") require.NoError(t, err) require.NotNil(t, fp) + path := fp.Name() defer func() { err = fp.Close() require.NoError(t, err) @@ -460,29 +461,29 @@ func (cli *testServerClient) runTestLoadDataForSlowLog(t *testing.T, server *Ser }) } -func (cli *testServerClient) prepareLoadDataFile(t *testing.T, path string, rows ...string) { - fp, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) +func (cli *testServerClient) prepareLoadDataFile(t *testing.T, fp *os.File, rows ...string) { + err := fp.Truncate(0) require.NoError(t, err) - require.NotNil(t, fp) - defer func() { - err = fp.Close() - require.NoError(t, err) - }() + _, err = fp.Seek(0, 0) + require.NoError(t, err) + for _, row := range rows { fields := strings.Split(row, " ") _, err = fp.WriteString(strings.Join(fields, "\t")) + require.NoError(t, err) _, err = fp.WriteString("\n") + require.NoError(t, err) } - require.NoError(t, err) + require.NoError(t, fp.Sync()) } func (cli *testServerClient) runTestLoadDataAutoRandom(t *testing.T) { - path := "/tmp/load_data_txn_error.csv" - - fp, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + fp, err := os.CreateTemp("", "load_data_txn_error.csv") require.NoError(t, err) require.NotNil(t, fp) + path := fp.Name() + defer func() { _ = os.Remove(path) }() @@ -534,11 +535,10 @@ func (cli *testServerClient) runTestLoadDataAutoRandom(t *testing.T) { } func (cli *testServerClient) runTestLoadDataAutoRandomWithSpecialTerm(t *testing.T) { - path := "/tmp/load_data_txn_error_term.csv" - - fp, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + fp, err := os.CreateTemp("", "load_data_txn_error_term.csv") require.NoError(t, err) require.NotNil(t, fp) + path := fp.Name() defer func() { _ = os.Remove(path) @@ -591,10 +591,10 @@ func (cli *testServerClient) runTestLoadDataAutoRandomWithSpecialTerm(t *testing } func (cli *testServerClient) runTestLoadDataForListPartition(t *testing.T) { - path := "/tmp/load_data_list_partition.csv" - defer func() { - _ = os.Remove(path) - }() + f, err := os.CreateTemp("", "load_data_list_partition.csv") + require.NoError(t, err) + defer os.Remove(f.Name()) + path := f.Name() cli.runTestsOnNewDB(t, func(config *mysql.Config) { config.AllowAllFiles = true @@ -609,20 +609,20 @@ func (cli *testServerClient) runTestLoadDataForListPartition(t *testing.T) { partition p3 values in (7,8,15,16,null) );`) // Test load data into 1 partition. - cli.prepareLoadDataFile(t, path, "1 a", "2 b") + cli.prepareLoadDataFile(t, f, "1 a", "2 b") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) rows := dbt.MustQuery("select * from t partition(p1) order by id") cli.checkRows(t, rows, "1 a", "2 b") // Test load data into multi-partitions. dbt.MustExec("delete from t") - cli.prepareLoadDataFile(t, path, "1 a", "3 c", "4 e") + cli.prepareLoadDataFile(t, f, "1 a", "3 c", "4 e") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, rows.Close()) rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "1 a", "3 c", "4 e") require.NoError(t, rows.Close()) // Test load data meet duplicate error. - cli.prepareLoadDataFile(t, path, "1 x", "2 b", "2 x", "7 a") + cli.prepareLoadDataFile(t, f, "1 x", "2 b", "2 x", "7 a") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) rows = dbt.MustQuery("show warnings") cli.checkRows(t, rows, @@ -632,7 +632,7 @@ func (cli *testServerClient) runTestLoadDataForListPartition(t *testing.T) { rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "1 a", "2 b", "3 c", "4 e", "7 a") // Test load data meet no partition warning. - cli.prepareLoadDataFile(t, path, "5 a", "100 x") + cli.prepareLoadDataFile(t, f, "5 a", "100 x") _, err := dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, err) rows = dbt.MustQuery("show warnings") @@ -645,10 +645,10 @@ func (cli *testServerClient) runTestLoadDataForListPartition(t *testing.T) { } func (cli *testServerClient) runTestLoadDataForListPartition2(t *testing.T) { - path := "/tmp/load_data_list_partition.csv" - defer func() { - _ = os.Remove(path) - }() + f, err := os.CreateTemp("", "load_data_list_partition.csv") + require.NoError(t, err) + defer os.Remove(f.Name()) + path := f.Name() cli.runTestsOnNewDB(t, func(config *mysql.Config) { config.AllowAllFiles = true @@ -663,19 +663,19 @@ func (cli *testServerClient) runTestLoadDataForListPartition2(t *testing.T) { partition p3 values in (7,8,15,16,null) );`) // Test load data into 1 partition. - cli.prepareLoadDataFile(t, path, "1 a", "2 b") + cli.prepareLoadDataFile(t, f, "1 a", "2 b") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t (id,name)", path)) rows := dbt.MustQuery("select id,name from t partition(p1) order by id") cli.checkRows(t, rows, "1 a", "2 b") // Test load data into multi-partitions. dbt.MustExec("delete from t") - cli.prepareLoadDataFile(t, path, "1 a", "3 c", "4 e") + cli.prepareLoadDataFile(t, f, "1 a", "3 c", "4 e") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t (id,name)", path)) require.NoError(t, rows.Close()) rows = dbt.MustQuery("select id,name from t order by id") cli.checkRows(t, rows, "1 a", "3 c", "4 e") // Test load data meet duplicate error. - cli.prepareLoadDataFile(t, path, "1 x", "2 b", "2 x", "7 a") + cli.prepareLoadDataFile(t, f, "1 x", "2 b", "2 x", "7 a") require.NoError(t, rows.Close()) dbt.MustExec(fmt.Sprintf("load data local infile %q into table t (id,name)", path)) rows = dbt.MustQuery("show warnings") @@ -687,7 +687,7 @@ func (cli *testServerClient) runTestLoadDataForListPartition2(t *testing.T) { cli.checkRows(t, rows, "1 a", "2 b", "3 c", "4 e", "7 a") require.NoError(t, rows.Close()) // Test load data meet no partition warning. - cli.prepareLoadDataFile(t, path, "5 a", "100 x") + cli.prepareLoadDataFile(t, f, "5 a", "100 x") _, err := dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t (id,name)", path)) require.NoError(t, err) rows = dbt.MustQuery("show warnings") @@ -700,10 +700,10 @@ func (cli *testServerClient) runTestLoadDataForListPartition2(t *testing.T) { } func (cli *testServerClient) runTestLoadDataForListColumnPartition(t *testing.T) { - path := "/tmp/load_data_list_partition.csv" - defer func() { - _ = os.Remove(path) - }() + f, err := os.CreateTemp("", "load_data_list_partition.csv") + require.NoError(t, err) + defer os.Remove(f.Name()) + path := f.Name() cli.runTestsOnNewDB(t, func(config *mysql.Config) { config.AllowAllFiles = true @@ -718,20 +718,20 @@ func (cli *testServerClient) runTestLoadDataForListColumnPartition(t *testing.T) partition p3 values in (7,8,15,16,null) );`) // Test load data into 1 partition. - cli.prepareLoadDataFile(t, path, "1 a", "2 b") + cli.prepareLoadDataFile(t, f, "1 a", "2 b") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) rows := dbt.MustQuery("select * from t partition(p1) order by id") cli.checkRows(t, rows, "1 a", "2 b") // Test load data into multi-partitions. dbt.MustExec("delete from t") - cli.prepareLoadDataFile(t, path, "1 a", "3 c", "4 e") + cli.prepareLoadDataFile(t, f, "1 a", "3 c", "4 e") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, rows.Close()) rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "1 a", "3 c", "4 e") require.NoError(t, rows.Close()) // Test load data meet duplicate error. - cli.prepareLoadDataFile(t, path, "1 x", "2 b", "2 x", "7 a") + cli.prepareLoadDataFile(t, f, "1 x", "2 b", "2 x", "7 a") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) rows = dbt.MustQuery("show warnings") cli.checkRows(t, rows, @@ -741,7 +741,7 @@ func (cli *testServerClient) runTestLoadDataForListColumnPartition(t *testing.T) rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "1 a", "2 b", "3 c", "4 e", "7 a") // Test load data meet no partition warning. - cli.prepareLoadDataFile(t, path, "5 a", "100 x") + cli.prepareLoadDataFile(t, f, "5 a", "100 x") _, err := dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, err) require.NoError(t, rows.Close()) @@ -755,10 +755,10 @@ func (cli *testServerClient) runTestLoadDataForListColumnPartition(t *testing.T) } func (cli *testServerClient) runTestLoadDataForListColumnPartition2(t *testing.T) { - path := "/tmp/load_data_list_partition.csv" - defer func() { - _ = os.Remove(path) - }() + f, err := os.CreateTemp("", "load_data_list_partition.csv") + require.NoError(t, err) + defer os.Remove(f.Name()) + path := f.Name() cli.runTestsOnNewDB(t, func(config *mysql.Config) { config.AllowAllFiles = true @@ -772,19 +772,19 @@ func (cli *testServerClient) runTestLoadDataForListColumnPartition2(t *testing.T partition p_south values in (('s',13),('s',14),('s',15),('s',16)) );`) // Test load data into 1 partition. - cli.prepareLoadDataFile(t, path, "w 1 1", "w 2 2") + cli.prepareLoadDataFile(t, f, "w 1 1", "w 2 2") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) rows := dbt.MustQuery("select * from t partition(p_west) order by id") cli.checkRows(t, rows, "w 1 1", "w 2 2") // Test load data into multi-partitions. dbt.MustExec("delete from t") - cli.prepareLoadDataFile(t, path, "w 1 1", "e 5 5", "n 9 9") + cli.prepareLoadDataFile(t, f, "w 1 1", "e 5 5", "n 9 9") dbt.MustExec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, rows.Close()) rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "w 1 1", "e 5 5", "n 9 9") // Test load data meet duplicate error. - cli.prepareLoadDataFile(t, path, "w 1 2", "w 2 2") + cli.prepareLoadDataFile(t, f, "w 1 2", "w 2 2") _, err := dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, err) require.NoError(t, rows.Close()) @@ -794,13 +794,13 @@ func (cli *testServerClient) runTestLoadDataForListColumnPartition2(t *testing.T rows = dbt.MustQuery("select * from t order by id") cli.checkRows(t, rows, "w 1 1", "w 2 2", "e 5 5", "n 9 9") // Test load data meet no partition warning. - cli.prepareLoadDataFile(t, path, "w 3 3", "w 5 5", "e 8 8") + cli.prepareLoadDataFile(t, f, "w 3 3", "w 5 5", "e 8 8") _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, err) require.NoError(t, rows.Close()) rows = dbt.MustQuery("show warnings") cli.checkRows(t, rows, "Warning 1526 Table has no partition for value from column_list") - cli.prepareLoadDataFile(t, path, "x 1 1", "w 1 1") + cli.prepareLoadDataFile(t, f, "x 1 1", "w 1 1") _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table t", path)) require.NoError(t, err) require.NoError(t, rows.Close()) @@ -851,10 +851,9 @@ func (cli *testServerClient) checkRows(t *testing.T, rows *sql.Rows, expectedRow } func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { - // create a file and write data. - path := "/tmp/load_data_test.csv" - fp, err := os.Create(path) + fp, err := os.CreateTemp("", "load_data_test.csv") require.NoError(t, err) + path := fp.Name() require.NotNil(t, fp) defer func() { err = fp.Close() @@ -886,14 +885,14 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { dbt.MustExec("create sequence s1") // can't insert into views (in TiDB) or sequences. issue #20880 - _, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table v1") + _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table v1", path)) require.Error(t, err) require.Equal(t, "Error 1105: can only load data into base tables", err.Error()) - _, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table s1") + _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table s1", path)) require.Error(t, err) require.Equal(t, "Error 1105: can only load data into base tables", err.Error()) - rs, err1 := dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table test") + rs, err1 := dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table test", path)) require.NoError(t, err1) lastID, err1 := rs.LastInsertId() require.NoError(t, err1) @@ -944,7 +943,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { // specify faileds and lines dbt.MustExec("delete from test") dbt.MustExec("set @@tidb_dml_batch_size = 3") - rs, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table test fields terminated by '\t- ' lines starting by 'xxx ' terminated by '\n'") + rs, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table test fields terminated by '\t- ' lines starting by 'xxx ' terminated by '\n'", path)) require.NoError(t, err) lastID, err = rs.LastInsertId() require.NoError(t, err) @@ -988,7 +987,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { require.NoError(t, err) } dbt.MustExec("set @@tidb_dml_batch_size = 3") - rs, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table test fields terminated by '\t- ' lines starting by 'xxx ' terminated by '\n'") + rs, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table test fields terminated by '\t- ' lines starting by 'xxx ' terminated by '\n'", path)) require.NoError(t, err) lastID, err = rs.LastInsertId() require.NoError(t, err) @@ -1001,7 +1000,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { require.NoError(t, rows.Close()) // don't support lines terminated is "" dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table test lines terminated by ''") + _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table test lines terminated by ''", path)) require.NotNil(t, err) // infile doesn't exist @@ -1032,7 +1031,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { }, "LoadData", func(dbt *testkit.DBTestKit) { dbt.MustExec("create table test (str varchar(10) default null, i int default null)") dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table test FIELDS TERMINATED BY ',' enclosed by '"'`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table test FIELDS TERMINATED BY ',' enclosed by '"'`, path)) require.NoError(t, err1) var ( str string @@ -1081,7 +1080,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { }, "LoadData", func(dbt *testkit.DBTestKit) { dbt.MustExec("create table test (a date, b date, c date not null, d date)") dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table test FIELDS TERMINATED BY ','`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table test FIELDS TERMINATED BY ','`, path)) require.NoError(t, err1) var ( a sql.NullString @@ -1138,7 +1137,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { }, "LoadData", func(dbt *testkit.DBTestKit) { dbt.MustExec("create table test (a varchar(20), b varchar(20))") dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table test FIELDS TERMINATED BY ',' enclosed by '"'`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table test FIELDS TERMINATED BY ',' enclosed by '"'`, path)) require.NoError(t, err1) var ( a sql.NullString @@ -1185,7 +1184,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { }, "LoadData", func(dbt *testkit.DBTestKit) { dbt.MustExec("create table test (id INT NOT NULL PRIMARY KEY, b INT, c varchar(10))") dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table test FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' IGNORE 1 LINES`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table test FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' IGNORE 1 LINES`, path)) require.NoError(t, err1) var ( a int @@ -1211,7 +1210,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { }, "LoadData", func(dbt *testkit.DBTestKit) { dbt.MustExec("create table test (a varchar(255), b varchar(255) default 'default value', c int not null auto_increment, primary key(c))") dbt.MustExec("set @@tidb_dml_batch_size = 3") - _, err = dbt.GetDB().Exec("load data local infile '/tmp/load_data_test.csv' into table test") + _, err = dbt.GetDB().Exec(fmt.Sprintf("load data local infile %q into table test", path)) require.Error(t, err) checkErrorCode(t, err, errno.ErrNotAllowedCommand) }) @@ -1239,7 +1238,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { dbt.MustExec("drop table if exists pn") dbt.MustExec("create table pn (c1 int, c2 int)") dbt.MustExec("set @@tidb_dml_batch_size = 1") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table pn FIELDS TERMINATED BY ','`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table pn FIELDS TERMINATED BY ','`, path)) require.NoError(t, err1) var ( a int @@ -1260,7 +1259,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { require.NoError(t, rows.Close()) // fail error processing test require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/commitOneTaskErr", "return")) - _, err1 = dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table pn FIELDS TERMINATED BY ','`) + _, err1 = dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table pn FIELDS TERMINATED BY ','`, path)) mysqlErr, ok := err1.(*mysql.MySQLError) require.True(t, ok) require.Equal(t, "mock commit one task error", mysqlErr.Message) @@ -1291,7 +1290,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { dbt.MustExec("drop table if exists pn") dbt.MustExec("create table pn (c1 int, c2 int)") dbt.MustExec("set @@tidb_dml_batch_size = 1") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table pn FIELDS TERMINATED BY ',' (c1, c2)`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table pn FIELDS TERMINATED BY ',' (c1, c2)`, path)) require.NoError(t, err1) var ( a int @@ -1335,7 +1334,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { dbt.MustExec("drop table if exists pn") dbt.MustExec("create table pn (c1 int, c2 int, c3 int)") dbt.MustExec("set @@tidb_dml_batch_size = 1") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table pn FIELDS TERMINATED BY ',' (c1, @dummy)`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table pn FIELDS TERMINATED BY ',' (c1, @dummy)`, path)) require.NoError(t, err1) var ( a int @@ -1382,7 +1381,7 @@ func (cli *testServerClient) runTestLoadData(t *testing.T, server *Server) { dbt.MustExec("drop table if exists pn") dbt.MustExec("create table pn (c1 int, c2 int, c3 int)") dbt.MustExec("set @@tidb_dml_batch_size = 1") - _, err1 := dbt.GetDB().Exec(`load data local infile '/tmp/load_data_test.csv' into table pn FIELDS TERMINATED BY ',' (c1, @val1, @val2) SET c3 = @val2 * 100, c2 = CAST(@val1 AS UNSIGNED)`) + _, err1 := dbt.GetDB().Exec(fmt.Sprintf(`load data local infile %q into table pn FIELDS TERMINATED BY ',' (c1, @val1, @val2) SET c3 = @val2 * 100, c2 = CAST(@val1 AS UNSIGNED)`, path)) require.NoError(t, err1) var ( a int diff --git a/server/stat.go b/server/stat.go index 9725a7ec5e480..382a68e701ce0 100644 --- a/server/stat.go +++ b/server/stat.go @@ -16,7 +16,9 @@ package server import ( "crypto/x509" + "time" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util/logutil" "go.uber.org/zap" @@ -25,11 +27,13 @@ import ( var ( serverNotAfter = "Ssl_server_not_after" serverNotBefore = "Ssl_server_not_before" + upTime = "Uptime" ) var defaultStatus = map[string]*variable.StatusVal{ serverNotAfter: {Scope: variable.ScopeGlobal | variable.ScopeSession, Value: ""}, serverNotBefore: {Scope: variable.ScopeGlobal | variable.ScopeSession, Value: ""}, + upTime: {Scope: variable.ScopeGlobal, Value: 0}, } // GetScope gets the status variables scope. @@ -57,5 +61,15 @@ func (s *Server) Stats(vars *variable.SessionVars) (map[string]interface{}, erro } } } + + var err error + info := serverInfo{} + info.ServerInfo, err = infosync.GetServerInfo() + if err != nil { + logutil.BgLogger().Error("Failed to get ServerInfo for uptime status", zap.Error(err)) + } else { + m[upTime] = int64(time.Since(time.Unix(info.ServerInfo.StartTimestamp, 0)).Seconds()) + } + return m, nil } diff --git a/server/stat_test.go b/server/stat_test.go new file mode 100644 index 0000000000000..66c974a3deeea --- /dev/null +++ b/server/stat_test.go @@ -0,0 +1,63 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "context" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/domain/infosync" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/store/mockstore" + "github.com/stretchr/testify/require" +) + +func TestUptime(t *testing.T) { + var err error + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/infosync/mockServerInfo", "return(true)")) + defer func() { + err := failpoint.Disable("github.com/pingcap/tidb/domain/infosync/mockServerInfo") + require.NoError(t, err) + }() + + store, err := mockstore.NewMockStore() + require.NoError(t, err) + + dom, err := session.BootstrapSession(store) + defer func() { + dom.Close() + err := store.Close() + require.NoError(t, err) + }() + require.NoError(t, err) + + _, err = infosync.GlobalInfoSyncerInit(context.Background(), dom.DDL().GetID(), dom.ServerID, dom.GetEtcdClient(), true) + require.NoError(t, err) + + tidbdrv := NewTiDBDriver(store) + cfg := newTestConfig() + cfg.Socket = "" + cfg.Port = 0 + cfg.Status.StatusPort = 0 + server, err := NewServer(cfg, tidbdrv) + require.NoError(t, err) + + stats, err := server.Stats(nil) + require.NoError(t, err) + require.GreaterOrEqual(t, stats[upTime].(int64), int64(time.Since(time.Unix(1282967700, 0)).Seconds())) +} diff --git a/server/statistics_handler_serial_test.go b/server/statistics_handler_test.go similarity index 100% rename from server/statistics_handler_serial_test.go rename to server/statistics_handler_test.go diff --git a/server/tidb_serial_test.go b/server/tidb_serial_test.go index 5bbf88ad0e392..468f840c888ee 100644 --- a/server/tidb_serial_test.go +++ b/server/tidb_serial_test.go @@ -20,6 +20,7 @@ import ( "context" "crypto/x509" "os" + "path/filepath" "sync/atomic" "testing" "time" @@ -31,13 +32,12 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/collate" "github.com/stretchr/testify/require" ) // this test will change `kv.TxnTotalSizeLimit` which may affect other test suites, // so we must make it running in serial. -func TestLoadData(t *testing.T) { +func TestLoadData1(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() @@ -130,31 +130,22 @@ func TestTLSBasic(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() + dir := t.TempDir() + + fileName := func(file string) string { + return filepath.Join(dir, file) + } + // Generate valid TLS certificates. - caCert, caKey, err := generateCert(0, "TiDB CA", nil, nil, "/tmp/ca-key.pem", "/tmp/ca-cert.pem") + caCert, caKey, err := generateCert(0, "TiDB CA", nil, nil, fileName("ca-key.pem"), fileName("ca-cert.pem")) require.NoError(t, err) - serverCert, _, err := generateCert(1, "tidb-server", caCert, caKey, "/tmp/server-key.pem", "/tmp/server-cert.pem") + serverCert, _, err := generateCert(1, "tidb-server", caCert, caKey, fileName("server-key.pem"), fileName("server-cert.pem")) require.NoError(t, err) - _, _, err = generateCert(2, "SQL Client Certificate", caCert, caKey, "/tmp/client-key.pem", "/tmp/client-cert.pem") + _, _, err = generateCert(2, "SQL Client Certificate", caCert, caKey, fileName("client-key.pem"), fileName("client-cert.pem")) require.NoError(t, err) - err = registerTLSConfig("client-certificate", "/tmp/ca-cert.pem", "/tmp/client-cert.pem", "/tmp/client-key.pem", "tidb-server", true) + err = registerTLSConfig("client-certificate", fileName("ca-cert.pem"), fileName("client-cert.pem"), fileName("client-key.pem"), "tidb-server", true) require.NoError(t, err) - defer func() { - err := os.Remove("/tmp/ca-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/ca-cert.pem") - require.NoError(t, err) - err = os.Remove("/tmp/server-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/server-cert.pem") - require.NoError(t, err) - err = os.Remove("/tmp/client-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/client-cert.pem") - require.NoError(t, err) - }() - // Start the server with TLS but without CA, in this case the server will not verify client's certificate. connOverrider := func(config *mysql.Config) { config.TLSConfig = "skip-verify" @@ -164,8 +155,8 @@ func TestTLSBasic(t *testing.T) { cfg.Port = cli.port cfg.Status.ReportStatus = false cfg.Security = config.Security{ - SSLCert: "/tmp/server-cert.pem", - SSLKey: "/tmp/server-key.pem", + SSLCert: fileName("server-cert.pem"), + SSLKey: fileName("server-key.pem"), } server, err := NewServer(cfg, ts.tidbdrv) require.NoError(t, err) @@ -204,40 +195,31 @@ func TestTLSVerify(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() + dir := t.TempDir() + + fileName := func(file string) string { + return filepath.Join(dir, file) + } + // Generate valid TLS certificates. - caCert, caKey, err := generateCert(0, "TiDB CA", nil, nil, "/tmp/ca-key.pem", "/tmp/ca-cert.pem") + caCert, caKey, err := generateCert(0, "TiDB CA", nil, nil, fileName("ca-key.pem"), fileName("ca-cert.pem")) require.NoError(t, err) - _, _, err = generateCert(1, "tidb-server", caCert, caKey, "/tmp/server-key.pem", "/tmp/server-cert.pem") + _, _, err = generateCert(1, "tidb-server", caCert, caKey, fileName("server-key.pem"), fileName("server-cert.pem")) require.NoError(t, err) - _, _, err = generateCert(2, "SQL Client Certificate", caCert, caKey, "/tmp/client-key.pem", "/tmp/client-cert.pem") + _, _, err = generateCert(2, "SQL Client Certificate", caCert, caKey, fileName("client-key.pem"), fileName("client-cert.pem")) require.NoError(t, err) - err = registerTLSConfig("client-certificate", "/tmp/ca-cert.pem", "/tmp/client-cert.pem", "/tmp/client-key.pem", "tidb-server", true) + err = registerTLSConfig("client-certificate", fileName("ca-cert.pem"), fileName("client-cert.pem"), fileName("client-key.pem"), "tidb-server", true) require.NoError(t, err) - defer func() { - err := os.Remove("/tmp/ca-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/ca-cert.pem") - require.NoError(t, err) - err = os.Remove("/tmp/server-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/server-cert.pem") - require.NoError(t, err) - err = os.Remove("/tmp/client-key.pem") - require.NoError(t, err) - err = os.Remove("/tmp/client-cert.pem") - require.NoError(t, err) - }() - // Start the server with TLS & CA, if the client presents its certificate, the certificate will be verified. cli := newTestServerClient() cfg := newTestConfig() cfg.Port = cli.port cfg.Status.ReportStatus = false cfg.Security = config.Security{ - SSLCA: "/tmp/ca-cert.pem", - SSLCert: "/tmp/server-cert.pem", - SSLKey: "/tmp/server-key.pem", + SSLCA: fileName("ca-cert.pem"), + SSLCert: fileName("server-cert.pem"), + SSLKey: fileName("server-key.pem"), } server, err := NewServer(cfg, ts.tidbdrv) require.NoError(t, err) @@ -269,7 +251,7 @@ func TestTLSVerify(t *testing.T) { _, _, err = util.LoadTLSCertificates("", "wrong key", "wrong cert", true, 528) require.Error(t, err) - _, _, err = util.LoadTLSCertificates("wrong ca", "/tmp/server-key.pem", "/tmp/server-cert.pem", true, 528) + _, _, err = util.LoadTLSCertificates("wrong ca", fileName("server-key.pem"), fileName("server-cert.pem"), true, 528) require.Error(t, err) } @@ -366,13 +348,52 @@ func TestPrepareCount(t *testing.T) { require.NoError(t, qctx.Close()) } +func TestPrepareExecute(t *testing.T) { + ts, cleanup := createTidbTestSuite(t) + defer cleanup() + + qctx, err := ts.tidbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultCollationID), "test", nil) + require.NoError(t, err) + + ctx := context.Background() + _, err = qctx.Execute(ctx, "use test") + require.NoError(t, err) + _, err = qctx.Execute(ctx, "create table t1(id int primary key, v int)") + require.NoError(t, err) + _, err = qctx.Execute(ctx, "insert into t1 values(1, 100)") + require.NoError(t, err) + + stmt, _, _, err := qctx.Prepare("select * from t1 where id=1") + require.NoError(t, err) + rs, err := stmt.Execute(ctx, nil) + require.NoError(t, err) + req := rs.NewChunk(nil) + require.NoError(t, rs.Next(ctx, req)) + require.Equal(t, 2, req.NumCols()) + require.Equal(t, req.NumCols(), len(rs.Columns())) + require.Equal(t, 1, req.NumRows()) + require.Equal(t, int64(1), req.GetRow(0).GetInt64(0)) + require.Equal(t, int64(100), req.GetRow(0).GetInt64(1)) + + // issue #33509 + _, err = qctx.Execute(ctx, "alter table t1 drop column v") + require.NoError(t, err) + + rs, err = stmt.Execute(ctx, nil) + require.NoError(t, err) + req = rs.NewChunk(nil) + require.NoError(t, rs.Next(ctx, req)) + require.Equal(t, 1, req.NumCols()) + require.Equal(t, req.NumCols(), len(rs.Columns())) + require.Equal(t, 1, req.NumRows()) + require.Equal(t, int64(1), req.GetRow(0).GetInt64(0)) +} + func TestDefaultCharacterAndCollation(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() // issue #21194 - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) // 255 is the collation id of mysql client 8 default collation_connection qctx, err := ts.tidbdrv.OpenCtx(uint64(0), 0, uint8(255), "test", nil) require.NoError(t, err) diff --git a/server/tidb_test.go b/server/tidb_test.go index 08647d19ba1f8..2a4f8859f318c 100644 --- a/server/tidb_test.go +++ b/server/tidb_test.go @@ -17,7 +17,6 @@ package server import ( - "bytes" "context" "crypto/rand" "crypto/rsa" @@ -32,6 +31,7 @@ import ( "os" "path/filepath" "strings" + "sync" "testing" "time" @@ -39,21 +39,27 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" + ddlutil "github.com/pingcap/tidb/ddl/util" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" tmysql "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/store/mockstore/unistore" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/cpuprofile" "github.com/pingcap/tidb/util/plancodec" - "github.com/pingcap/tidb/util/topsql/reporter" - mockTopSQLReporter "github.com/pingcap/tidb/util/topsql/reporter/mock" - "github.com/pingcap/tidb/util/topsql/tracecpu" - mockTopSQLTraceCPU "github.com/pingcap/tidb/util/topsql/tracecpu/mock" + "github.com/pingcap/tidb/util/resourcegrouptag" + "github.com/pingcap/tidb/util/topsql" + "github.com/pingcap/tidb/util/topsql/collector" + mockTopSQLTraceCPU "github.com/pingcap/tidb/util/topsql/collector/mock" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/pingcap/tidb/util/topsql/stmtstats" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/tikvrpc" ) type tidbTestSuite struct { @@ -80,14 +86,15 @@ func createTidbTestSuite(t *testing.T) (*tidbTestSuite, func()) { cfg.Status.ReportStatus = true cfg.Status.StatusPort = ts.statusPort cfg.Performance.TCPKeepAlive = true - err = logutil.InitLogger(cfg.Log.ToLogConfig()) - require.NoError(t, err) server, err := NewServer(cfg, ts.tidbdrv) require.NoError(t, err) ts.port = getPortFromTCPAddr(server.listener.Addr()) ts.statusPort = getPortFromTCPAddr(server.statusListener.Addr()) ts.server = server + ts.server.SetDomain(ts.domain) + ts.server.InitGlobalConnID(ts.domain.ServerID) + ts.domain.InfoSyncer().SetSessionManager(ts.server) go func() { err := ts.server.Run() require.NoError(t, err) @@ -127,13 +134,18 @@ func createTidbTestTopSQLSuite(t *testing.T) (*tidbTestTopSQLSuite, func()) { }() dbt := testkit.NewDBTestKit(t, db) - dbt.MustExec("set @@global.tidb_top_sql_precision_seconds=1;") - dbt.MustExec("set @@global.tidb_top_sql_report_interval_seconds=2;") - dbt.MustExec("set @@global.tidb_top_sql_max_statement_count=5;") - - tracecpu.GlobalSQLCPUProfiler.Run() - - return ts, cleanup + topsqlstate.GlobalState.PrecisionSeconds.Store(1) + topsqlstate.GlobalState.ReportIntervalSeconds.Store(2) + dbt.MustExec("set @@global.tidb_top_sql_max_time_series_count=5;") + + require.NoError(t, cpuprofile.StartCPUProfiler()) + cleanFn := func() { + cleanup() + cpuprofile.StopCPUProfiler() + topsqlstate.GlobalState.PrecisionSeconds.Store(topsqlstate.DefTiDBTopSQLPrecisionSeconds) + topsqlstate.GlobalState.ReportIntervalSeconds.Store(topsqlstate.DefTiDBTopSQLReportIntervalSeconds) + } + return ts, cleanFn } func TestRegression(t *testing.T) { @@ -242,26 +254,25 @@ func TestStatusAPIWithTLS(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() - caCert, caKey, err := generateCert(0, "TiDB CA 2", nil, nil, "/tmp/ca-key-2.pem", "/tmp/ca-cert-2.pem") + dir := t.TempDir() + + fileName := func(file string) string { + return filepath.Join(dir, file) + } + + caCert, caKey, err := generateCert(0, "TiDB CA 2", nil, nil, fileName("ca-key-2.pem"), fileName("ca-cert-2.pem")) require.NoError(t, err) - _, _, err = generateCert(1, "tidb-server-2", caCert, caKey, "/tmp/server-key-2.pem", "/tmp/server-cert-2.pem") + _, _, err = generateCert(1, "tidb-server-2", caCert, caKey, fileName("server-key-2.pem"), fileName("server-cert-2.pem")) require.NoError(t, err) - defer func() { - os.Remove("/tmp/ca-key-2.pem") - os.Remove("/tmp/ca-cert-2.pem") - os.Remove("/tmp/server-key-2.pem") - os.Remove("/tmp/server-cert-2.pem") - }() - cli := newTestServerClient() cli.statusScheme = "https" cfg := newTestConfig() cfg.Port = cli.port cfg.Status.StatusPort = cli.statusPort - cfg.Security.ClusterSSLCA = "/tmp/ca-cert-2.pem" - cfg.Security.ClusterSSLCert = "/tmp/server-cert-2.pem" - cfg.Security.ClusterSSLKey = "/tmp/server-key-2.pem" + cfg.Security.ClusterSSLCA = fileName("ca-cert-2.pem") + cfg.Security.ClusterSSLCert = fileName("server-cert-2.pem") + cfg.Security.ClusterSSLKey = fileName("server-key-2.pem") server, err := NewServer(cfg, ts.tidbdrv) require.NoError(t, err) cli.port = getPortFromTCPAddr(server.listener.Addr()) @@ -287,15 +298,17 @@ func TestStatusAPIWithTLSCNCheck(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() - caPath := filepath.Join(os.TempDir(), "ca-cert-cn.pem") - serverKeyPath := filepath.Join(os.TempDir(), "server-key-cn.pem") - serverCertPath := filepath.Join(os.TempDir(), "server-cert-cn.pem") - client1KeyPath := filepath.Join(os.TempDir(), "client-key-cn-check-a.pem") - client1CertPath := filepath.Join(os.TempDir(), "client-cert-cn-check-a.pem") - client2KeyPath := filepath.Join(os.TempDir(), "client-key-cn-check-b.pem") - client2CertPath := filepath.Join(os.TempDir(), "client-cert-cn-check-b.pem") + dir := t.TempDir() + + caPath := filepath.Join(dir, "ca-cert-cn.pem") + serverKeyPath := filepath.Join(dir, "server-key-cn.pem") + serverCertPath := filepath.Join(dir, "server-cert-cn.pem") + client1KeyPath := filepath.Join(dir, "client-key-cn-check-a.pem") + client1CertPath := filepath.Join(dir, "client-cert-cn-check-a.pem") + client2KeyPath := filepath.Join(dir, "client-key-cn-check-b.pem") + client2CertPath := filepath.Join(dir, "client-cert-cn-check-b.pem") - caCert, caKey, err := generateCert(0, "TiDB CA CN CHECK", nil, nil, filepath.Join(os.TempDir(), "ca-key-cn.pem"), caPath) + caCert, caKey, err := generateCert(0, "TiDB CA CN CHECK", nil, nil, filepath.Join(dir, "ca-key-cn.pem"), caPath) require.NoError(t, err) _, _, err = generateCert(1, "tidb-server-cn-check", caCert, caKey, serverKeyPath, serverCertPath) require.NoError(t, err) @@ -370,11 +383,8 @@ func TestMultiStatements(t *testing.T) { } func TestSocketForwarding(t *testing.T) { - osTempDir := os.TempDir() - tempDir, err := os.MkdirTemp(osTempDir, "tidb-test.*.socket") - require.NoError(t, err) + tempDir := t.TempDir() socketFile := tempDir + "/tidbtest.sock" // Unix Socket does not work on Windows, so '/' should be OK - defer os.RemoveAll(tempDir) ts, cleanup := createTidbTestSuite(t) defer cleanup() @@ -406,11 +416,8 @@ func TestSocketForwarding(t *testing.T) { } func TestSocket(t *testing.T) { - osTempDir := os.TempDir() - tempDir, err := os.MkdirTemp(osTempDir, "tidb-test.*.socket") - require.NoError(t, err) + tempDir := t.TempDir() socketFile := tempDir + "/tidbtest.sock" // Unix Socket does not work on Windows, so '/' should be OK - defer os.RemoveAll(tempDir) cfg := newTestConfig() cfg.Socket = socketFile @@ -445,11 +452,8 @@ func TestSocket(t *testing.T) { } func TestSocketAndIp(t *testing.T) { - osTempDir := os.TempDir() - tempDir, err := os.MkdirTemp(osTempDir, "tidb-test.*.socket") - require.NoError(t, err) + tempDir := t.TempDir() socketFile := tempDir + "/tidbtest.sock" // Unix Socket does not work on Windows, so '/' should be OK - defer os.RemoveAll(tempDir) cli := newTestServerClient() cfg := newTestConfig() @@ -614,11 +618,8 @@ func TestSocketAndIp(t *testing.T) { // TestOnlySocket for server configuration without network interface for mysql clients func TestOnlySocket(t *testing.T) { - osTempDir := os.TempDir() - tempDir, err := os.MkdirTemp(osTempDir, "tidb-test.*.socket") - require.NoError(t, err) + tempDir := t.TempDir() socketFile := tempDir + "/tidbtest.sock" // Unix Socket does not work on Windows, so '/' should be OK - defer os.RemoveAll(tempDir) cli := newTestServerClient() cfg := newTestConfig() @@ -890,6 +891,40 @@ func TestSystemTimeZone(t *testing.T) { tk.MustQuery("select @@system_time_zone").Check(tz1) } +func TestInternalSessionTxnStartTS(t *testing.T) { + ts, cleanup := createTidbTestSuite(t) + defer cleanup() + + se, err := session.CreateSession4Test(ts.store) + require.NoError(t, err) + + count := 10 + stmts := make([]ast.StmtNode, count) + for i := 0; i < count; i++ { + stmt, err := session.ParseWithParams4Test(context.Background(), se, "select * from mysql.user limit 1") + require.NoError(t, err) + stmts[i] = stmt + } + // Test an issue that sysSessionPool doesn't call session's Close, cause + // asyncGetTSWorker goroutine leak. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/mockDelayInnerSessionExecute", "return")) + var wg util.WaitGroupWrapper + for i := 0; i < count; i++ { + s := stmts[i] + wg.Run(func() { + _, _, err := session.ExecRestrictedStmt4Test(context.Background(), se, s) + require.NoError(t, err) + }) + } + time.Sleep(100 * time.Millisecond) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/mockDelayInnerSessionExecute")) + + lst := ts.domain.InfoSyncer().GetSessionManager().GetInternalSessionStartTSList() + require.Equal(t, len(lst), 10) + + wg.Wait() +} + func TestClientWithCollation(t *testing.T) { ts, cleanup := createTidbTestSuite(t) defer cleanup() @@ -1258,10 +1293,6 @@ func TestPessimisticInsertSelectForUpdate(t *testing.T) { require.Nil(t, rs) // should be no delay } -type collectorWrapper struct { - reporter.TopSQLReporter -} - func TestTopSQLCPUProfile(t *testing.T) { ts, cleanup := createTidbTestTopSQLSuite(t) defer cleanup() @@ -1269,21 +1300,24 @@ func TestTopSQLCPUProfile(t *testing.T) { db, err := sql.Open("mysql", ts.getDSN()) require.NoError(t, err) defer func() { - err := db.Close() - require.NoError(t, err) + require.NoError(t, db.Close()) }() - require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop", `return(true)`)) require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/util/topsql/mockHighLoadForEachSQL", `return(true)`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop", `return(true)`)) defer func() { - err = failpoint.Disable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop") - require.NoError(t, err) - err = failpoint.Disable("github.com/pingcap/tidb/util/topsql/mockHighLoadForEachSQL") - require.NoError(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/util/topsql/mockHighLoadForEachSQL")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop")) }() - collector := mockTopSQLTraceCPU.NewTopSQLCollector() - tracecpu.GlobalSQLCPUProfiler.SetCollector(&collectorWrapper{collector}) + topsqlstate.EnableTopSQL() + defer topsqlstate.DisableTopSQL() + + mc := mockTopSQLTraceCPU.NewTopSQLCollector() + topsql.SetupTopSQLForTest(mc) + sqlCPUCollector := collector.NewSQLCPUCollector(mc) + sqlCPUCollector.Start() + defer sqlCPUCollector.Stop() dbt := testkit.NewDBTestKit(t, db) dbt.MustExec("drop database if exists topsql") @@ -1292,18 +1326,36 @@ func TestTopSQLCPUProfile(t *testing.T) { dbt.MustExec("create table t (a int auto_increment, b int, unique index idx(a));") dbt.MustExec("create table t1 (a int auto_increment, b int, unique index idx(a));") dbt.MustExec("create table t2 (a int auto_increment, b int, unique index idx(a));") - dbt.MustExec("set @@global.tidb_enable_top_sql='On';") - config.UpdateGlobal(func(conf *config.Config) { - conf.TopSQL.ReceiverAddress = "127.0.0.1:4001" - }) - dbt.MustExec("set @@global.tidb_top_sql_precision_seconds=1;") dbt.MustExec("set @@global.tidb_txn_mode = 'pessimistic'") + timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + checkFn := func(sql, planRegexp string) { + require.NoError(t, timeoutCtx.Err()) + stats := mc.GetSQLStatsBySQLWithRetry(sql, len(planRegexp) > 0) + // since 1 sql may has many plan, check `len(stats) > 0` instead of `len(stats) == 1`. + require.Greaterf(t, len(stats), 0, "sql: "+sql) + + for _, s := range stats { + sqlStr := mc.GetSQL(s.SQLDigest) + encodedPlan := mc.GetPlan(s.PlanDigest) + // Normalize the user SQL before check. + normalizedSQL := parser.Normalize(sql) + require.Equalf(t, normalizedSQL, sqlStr, "sql: %v", sql) + // decode plan before check. + normalizedPlan, err := plancodec.DecodeNormalizedPlan(encodedPlan) + require.NoError(t, err) + // remove '\n' '\t' before do regexp match. + normalizedPlan = strings.Replace(normalizedPlan, "\n", " ", -1) + normalizedPlan = strings.Replace(normalizedPlan, "\t", " ", -1) + require.Regexpf(t, planRegexp, normalizedPlan, "sql: %v", sql) + } + } + // Test case 1: DML query: insert/update/replace/delete/select cases1 := []struct { sql string planRegexp string - cancel func() }{ {sql: "insert into t () values (),(),(),(),(),(),();", planRegexp: ""}, {sql: "insert into t (b) values (1),(1),(1),(1),(1),(1),(1),(1);", planRegexp: ""}, @@ -1317,59 +1369,29 @@ func TestTopSQLCPUProfile(t *testing.T) { {sql: "select * from t where a=1;", planRegexp: ".*Point_Get.*"}, {sql: "select * from t where a in (1,2,3,4)", planRegexp: ".*Batch_Point_Get.*"}, } - for i, ca := range cases1 { - ctx, cancel := context.WithCancel(context.Background()) - cases1[i].cancel = cancel - sqlStr := ca.sql - go ts.loopExec(ctx, t, func(db *sql.DB) { - dbt := testkit.NewDBTestKit(t, db) + execFn := func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases1 { + sqlStr := ca.sql if strings.HasPrefix(sqlStr, "select") { - rows := dbt.MustQuery(sqlStr) - require.NoError(t, rows.Close()) + mustQuery(t, dbt, sqlStr) } else { - // Ignore error here since the error may be write conflict. - db.Exec(sqlStr) + dbt.MustExec(sqlStr) } - }) - } - - timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*20) - defer cancel() - checkFn := func(sql, planRegexp string) { - require.NoError(t, timeoutCtx.Err()) - stats := collector.GetSQLStatsBySQLWithRetry(sql, len(planRegexp) > 0) - // since 1 sql may has many plan, check `len(stats) > 0` instead of `len(stats) == 1`. - require.Greaterf(t, len(stats), 0, "sql: %v", sql) - - for _, s := range stats { - sqlStr := collector.GetSQL(s.SQLDigest) - encodedPlan := collector.GetPlan(s.PlanDigest) - // Normalize the user SQL before check. - normalizedSQL := parser.Normalize(sql) - require.Equalf(t, normalizedSQL, sqlStr, "sql: %v", sql) - // decode plan before check. - normalizedPlan, err := plancodec.DecodeNormalizedPlan(encodedPlan) - require.NoError(t, err) - // remove '\n' '\t' before do regexp match. - normalizedPlan = strings.Replace(normalizedPlan, "\n", " ", -1) - normalizedPlan = strings.Replace(normalizedPlan, "\t", " ", -1) - require.Regexpf(t, planRegexp, normalizedPlan, "sql: %v", sql) } } - // Wait the top sql collector to collect profile data. - collector.WaitCollectCnt(1) - // Check result of test case 1. - for _, ca := range cases1 { - checkFn(ca.sql, ca.planRegexp) - ca.cancel() + check := func() { + for _, ca := range cases1 { + checkFn(ca.sql, ca.planRegexp) + } } + ts.testCase(t, mc, execFn, check) // Test case 2: prepare/execute sql cases2 := []struct { prepare string args []interface{} planRegexp string - cancel func() }{ {prepare: "insert into t1 (b) values (?);", args: []interface{}{1}, planRegexp: ""}, {prepare: "replace into t1 (b) values (?);", args: []interface{}{1}, planRegexp: ""}, @@ -1383,41 +1405,35 @@ func TestTopSQLCPUProfile(t *testing.T) { {prepare: "select * from t1 where a=?;", args: []interface{}{1}, planRegexp: ".*Point_Get.*"}, {prepare: "select * from t1 where a in (?,?,?,?)", args: []interface{}{1, 2, 3, 4}, planRegexp: ".*Batch_Point_Get.*"}, } - for i, ca := range cases2 { - ctx, cancel := context.WithCancel(context.Background()) - cases2[i].cancel = cancel - prepare, args := ca.prepare, ca.args - var stmt *sql.Stmt - go ts.loopExec(ctx, t, func(db *sql.DB) { - if stmt == nil { - stmt, err = db.Prepare(prepare) - require.NoError(t, err) - } + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases2 { + prepare, args := ca.prepare, ca.args + stmt := dbt.MustPrepare(prepare) if strings.HasPrefix(prepare, "select") { rows, err := stmt.Query(args...) require.NoError(t, err) + for rows.Next() { + } require.NoError(t, rows.Close()) } else { - // Ignore error here since the error may be write conflict. _, err = stmt.Exec(args...) require.NoError(t, err) } - }) + } } - // Wait the top sql collector to collect profile data. - collector.WaitCollectCnt(1) - // Check result of test case 2. - for _, ca := range cases2 { - checkFn(ca.prepare, ca.planRegexp) - ca.cancel() + check = func() { + for _, ca := range cases2 { + checkFn(ca.prepare, ca.planRegexp) + } } + ts.testCase(t, mc, execFn, check) // Test case 3: prepare, execute stmt using @val... cases3 := []struct { prepare string args []interface{} planRegexp string - cancel func() }{ {prepare: "insert into t2 (b) values (?);", args: []interface{}{1}, planRegexp: ""}, {prepare: "update t2 set b=a where b is null limit ?;", args: []interface{}{1}, planRegexp: ".*Limit.*TableReader.*"}, @@ -1430,220 +1446,972 @@ func TestTopSQLCPUProfile(t *testing.T) { {prepare: "select * from t2 where a=?;", args: []interface{}{1}, planRegexp: ".*Point_Get.*"}, {prepare: "select * from t2 where a in (?,?,?,?)", args: []interface{}{1, 2, 3, 4}, planRegexp: ".*Batch_Point_Get.*"}, } - for i, ca := range cases3 { - ctx, cancel := context.WithCancel(context.Background()) - cases3[i].cancel = cancel - prepare, args := ca.prepare, ca.args - doPrepare := true - go ts.loopExec(ctx, t, func(db *sql.DB) { - if doPrepare { - doPrepare = false - _, err := db.Exec(fmt.Sprintf("prepare stmt from '%v'", prepare)) - require.NoError(t, err) - } - sqlBuf := bytes.NewBuffer(nil) - sqlBuf.WriteString("execute stmt ") + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases3 { + prepare, args := ca.prepare, ca.args + dbt.MustExec(fmt.Sprintf("prepare stmt from '%v'", prepare)) + + var params []string for i := range args { - _, err = db.Exec(fmt.Sprintf("set @%c=%v", 'a'+i, args[i])) - require.NoError(t, err) - if i == 0 { - sqlBuf.WriteString("using ") - } else { - sqlBuf.WriteByte(',') - } - sqlBuf.WriteByte('@') - sqlBuf.WriteByte('a' + byte(i)) + param := 'a' + i + dbt.MustExec(fmt.Sprintf("set @%c=%v", param, args[i])) + params = append(params, fmt.Sprintf("@%c", param)) + } + + sqlStr := "execute stmt" + if len(params) > 0 { + sqlStr += " using " + sqlStr += strings.Join(params, ",") } if strings.HasPrefix(prepare, "select") { - rows, err := db.Query(sqlBuf.String()) - require.NoErrorf(t, err, "%v", sqlBuf.String()) - require.NoError(t, rows.Close()) + mustQuery(t, dbt, sqlStr) } else { - // Ignore error here since the error may be write conflict. - _, err = db.Exec(sqlBuf.String()) - require.NoError(t, err) + dbt.MustExec(sqlStr) } - }) + } + } + check = func() { + for _, ca := range cases3 { + checkFn(ca.prepare, ca.planRegexp) + } + } + ts.testCase(t, mc, execFn, check) + + // Test case for other statements + cases4 := []struct { + sql string + plan string + isQuery bool + }{ + {"begin", "", false}, + {"insert into t () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()", "", false}, + {"commit", "", false}, + {"analyze table t", "", false}, + {"explain analyze select sum(a+b) from t", ".*TableReader.*", true}, + {"trace select sum(b*a), sum(a+b) from t", "", true}, + {"set global tidb_stmt_summary_history_size=5;", "", false}, + } + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases4 { + if ca.isQuery { + mustQuery(t, dbt, ca.sql) + } else { + dbt.MustExec(ca.sql) + } + } + } + check = func() { + for _, ca := range cases4 { + checkFn(ca.sql, ca.plan) + } + // check for internal SQL. + checkFn("replace into mysql.global_variables (variable_name,variable_value) values ('tidb_stmt_summary_history_size', '5')", "") + } + ts.testCase(t, mc, execFn, check) + + // Test case for multi-statement. + cases5 := []string{ + "delete from t limit 1;", + "update t set b=1 where b is null limit 1;", + "select sum(a+b*2) from t;", + } + multiStatement5 := strings.Join(cases5, "") + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("SET tidb_multi_statement_mode='ON'") + dbt.MustExec(multiStatement5) + } + check = func() { + for _, sqlStr := range cases5 { + checkFn(sqlStr, ".*TableReader.*") + } + } + ts.testCase(t, mc, execFn, check) + + // Test case for multi-statement, but first statements execute failed + cases6 := []string{ + "delete from t_not_exist;", + "update t set a=1 where a is null limit 1;", + } + multiStatement6 := strings.Join(cases6, "") + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("SET tidb_multi_statement_mode='ON'") + _, err := db.Exec(multiStatement6) + require.NotNil(t, err) + require.Equal(t, "Error 1146: Table 'topsql.t_not_exist' doesn't exist", err.Error()) + } + check = func() { + for i := 1; i < len(cases6); i++ { + sqlStr := cases6[i] + stats := mc.GetSQLStatsBySQL(sqlStr, false) + require.Equal(t, 0, len(stats), sqlStr) + } + } + ts.testCase(t, mc, execFn, check) + + // Test case for multi-statement, the first statements execute success but the second statement execute failed. + cases7 := []string{ + "update t set a=1 where a <0 limit 1;", + "delete from t_not_exist;", + } + multiStatement7 := strings.Join(cases7, "") + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("SET tidb_multi_statement_mode='ON'") + _, err = db.Exec(multiStatement7) + require.NotNil(t, err) + require.Equal(t, "Error 1146: Table 'topsql.t_not_exist' doesn't exist", err.Error()) + } + check = func() { + checkFn(cases7[0], "") // the first statement execute success, should have topsql data. + } + ts.testCase(t, mc, execFn, check) + + // Test case for statement with wrong syntax. + wrongSyntaxSQL := "select * froms t" + execFn = func(db *sql.DB) { + _, err = db.Exec(wrongSyntaxSQL) + require.NotNil(t, err) + require.Regexp(t, "Error 1064: You have an error in your SQL syntax...", err.Error()) + } + check = func() { + stats := mc.GetSQLStatsBySQL(wrongSyntaxSQL, false) + require.Equal(t, 0, len(stats), wrongSyntaxSQL) } + ts.testCase(t, mc, execFn, check) + + // Test case for high cost of plan optimize. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/mockHighLoadForOptimize", "return")) + selectSQL := "select sum(a+b), count(distinct b) from t where a+b >0" + updateSQL := "update t set a=a+100 where a > 10000000" + selectInPlanSQL := "select * from t where exists (select 1 from t1 where t1.a = 1);" + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + mustQuery(t, dbt, selectSQL) + dbt.MustExec(updateSQL) + mustQuery(t, dbt, selectInPlanSQL) + } + check = func() { + checkFn(selectSQL, "") + checkFn(updateSQL, "") + selectCPUTime := mc.GetSQLCPUTimeBySQL(selectSQL) + updateCPUTime := mc.GetSQLCPUTimeBySQL(updateSQL) + require.Less(t, updateCPUTime, selectCPUTime) + checkFn(selectInPlanSQL, "") + } + ts.testCase(t, mc, execFn, check) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/mockHighLoadForOptimize")) + + // Test case for DDL execute failed but should still have CPU data. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/ddl/mockHighLoadForAddIndex", "return")) + dbt.MustExec(fmt.Sprintf("insert into t values (%v,%v), (%v, %v);", 2000, 1, 2001, 1)) + addIndexStr := "alter table t add unique index idx_b (b)" + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("alter table t drop index if exists idx_b") + _, err := db.Exec(addIndexStr) + require.NotNil(t, err) + require.Equal(t, "Error 1062: Duplicate entry '1' for key 'idx_b'", err.Error()) + } + check = func() { + checkFn(addIndexStr, "") + } + ts.testCase(t, mc, execFn, check) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/ddl/mockHighLoadForAddIndex")) + + // Test case for execute failed cause by storage error. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/copr/handleTaskOnceError", `return(true)`)) + execFailedQuery := "select * from t where a*b < 1000" + execFn = func(db *sql.DB) { + _, err = db.Query(execFailedQuery) + require.NotNil(t, err) + require.Equal(t, "Error 1105: mock handleTaskOnce error", err.Error()) + } + check = func() { + checkFn(execFailedQuery, "") + } + ts.testCase(t, mc, execFn, check) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/copr/handleTaskOnceError")) +} + +func (ts *tidbTestTopSQLSuite) testCase(t *testing.T, mc *mockTopSQLTraceCPU.TopSQLCollector, execFn func(db *sql.DB), checkFn func()) { + var wg sync.WaitGroup + ctx, cancel := context.WithCancel(context.Background()) + wg.Add(1) + go func() { + defer wg.Done() + ts.loopExec(ctx, t, execFn) + }() + + checkFn() + cancel() + wg.Wait() + mc.Reset() +} - // Wait the top sql collector to collect profile data. - collector.WaitCollectCnt(1) - // Check result of test case 3. +func mustQuery(t *testing.T, dbt *testkit.DBTestKit, query string) { + rows := dbt.MustQuery(query) + for rows.Next() { + } + err := rows.Close() + require.NoError(t, err) +} + +type mockCollector struct { + f func(data stmtstats.StatementStatsMap) +} + +func newMockCollector(f func(data stmtstats.StatementStatsMap)) stmtstats.Collector { + return &mockCollector{f: f} +} + +func (c *mockCollector) CollectStmtStatsMap(data stmtstats.StatementStatsMap) { + c.f(data) +} + +func waitCollected(ch chan struct{}) { + select { + case <-ch: + case <-time.After(time.Second * 3): + } +} + +func TestTopSQLStatementStats(t *testing.T) { + ts, total, tagChecker, collectedNotifyCh, cleanFn := setupForTestTopSQLStatementStats(t) + defer cleanFn() + + const ExecCountPerSQL = 2 + // Test for CRUD. + cases1 := []string{ + "insert into t values (%d, sleep(0.1))", + "update t set a = %[1]d + 1000 where a = %[1]d and sleep(0.1);", + "select a from t where b = %d and sleep(0.1);", + "select a from t where a = %d and sleep(0.1);", // test for point-get + "delete from t where a = %d and sleep(0.1);", + "insert into t values (%d, sleep(0.1)) on duplicate key update b = b+1", + } + var wg sync.WaitGroup + sqlDigests := map[stmtstats.BinaryDigest]string{} + for i, ca := range cases1 { + sqlStr := fmt.Sprintf(ca, i) + _, digest := parser.NormalizeDigest(sqlStr) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = sqlStr + } + wg.Add(1) + go func() { + defer wg.Done() + for _, ca := range cases1 { + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("use stmtstats;") + for n := 0; n < ExecCountPerSQL; n++ { + sqlStr := fmt.Sprintf(ca, n) + if strings.HasPrefix(strings.ToLower(sqlStr), "select") { + mustQuery(t, dbt, sqlStr) + } else { + dbt.MustExec(sqlStr) + } + } + err = db.Close() + require.NoError(t, err) + } + }() + + // Test for prepare stmt/execute stmt + cases2 := []struct { + prepare string + execStmt string + setSQLsGen func(idx int) []string + execSQL string + }{ + { + prepare: "prepare stmt from 'insert into t2 values (?, sleep(?))';", + execStmt: "insert into t2 values (1, sleep(0.1))", + setSQLsGen: func(idx int) []string { + return []string{fmt.Sprintf("set @a=%v", idx), "set @b=0.1"} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + prepare: "prepare stmt from 'update t2 set a = a + 1000 where a = ? and sleep(?);';", + execStmt: "update t2 set a = a + 1000 where a = 1 and sleep(0.1);", + setSQLsGen: func(idx int) []string { + return []string{fmt.Sprintf("set @a=%v", idx), "set @b=0.1"} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + // test for point-get + prepare: "prepare stmt from 'select a, sleep(?) from t2 where a = ?';", + execStmt: "select a, sleep(?) from t2 where a = ?", + setSQLsGen: func(idx int) []string { + return []string{"set @a=0.1", fmt.Sprintf("set @b=%v", idx)} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + prepare: "prepare stmt from 'select a, sleep(?) from t2 where b = ?';", + execStmt: "select a, sleep(?) from t2 where b = ?", + setSQLsGen: func(idx int) []string { + return []string{"set @a=0.1", fmt.Sprintf("set @b=%v", idx)} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + prepare: "prepare stmt from 'delete from t2 where sleep(?) and a = ?';", + execStmt: "delete from t2 where sleep(0.1) and a = 1", + setSQLsGen: func(idx int) []string { + return []string{"set @a=0.1", fmt.Sprintf("set @b=%v", idx)} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + prepare: "prepare stmt from 'insert into t2 values (?, sleep(?)) on duplicate key update b = b+1';", + execStmt: "insert into t2 values (1, sleep(0.1)) on duplicate key update b = b+1", + setSQLsGen: func(idx int) []string { + return []string{fmt.Sprintf("set @a=%v", idx), "set @b=0.1"} + }, + execSQL: "execute stmt using @a, @b;", + }, + { + prepare: "prepare stmt from 'set global tidb_enable_top_sql = (? = sleep(?))';", + execStmt: "set global tidb_enable_top_sql = (0 = sleep(0.1))", + setSQLsGen: func(idx int) []string { + return []string{"set @a=0", "set @b=0.1"} + }, + execSQL: "execute stmt using @a, @b;", + }, + } + for _, ca := range cases2 { + _, digest := parser.NormalizeDigest(ca.execStmt) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = ca.execStmt + } + wg.Add(1) + go func() { + defer wg.Done() + for _, ca := range cases2 { + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("use stmtstats;") + // prepare stmt + dbt.MustExec(ca.prepare) + for n := 0; n < ExecCountPerSQL; n++ { + setSQLs := ca.setSQLsGen(n) + for _, setSQL := range setSQLs { + dbt.MustExec(setSQL) + } + if strings.HasPrefix(strings.ToLower(ca.execStmt), "select") { + mustQuery(t, dbt, ca.execSQL) + } else { + dbt.MustExec(ca.execSQL) + } + } + err = db.Close() + require.NoError(t, err) + } + }() + + // Test for prepare by db client prepare/exec interface. + cases3 := []struct { + prepare string + execStmt string + argsGen func(idx int) []interface{} + }{ + { + prepare: "insert into t3 values (?, sleep(?))", + argsGen: func(idx int) []interface{} { + return []interface{}{idx, 0.1} + }, + }, + { + prepare: "update t3 set a = a + 1000 where a = ? and sleep(?)", + argsGen: func(idx int) []interface{} { + return []interface{}{idx, 0.1} + }, + }, + { + // test for point-get + prepare: "select a, sleep(?) from t3 where a = ?", + argsGen: func(idx int) []interface{} { + return []interface{}{0.1, idx} + }, + }, + { + prepare: "select a, sleep(?) from t3 where b = ?", + argsGen: func(idx int) []interface{} { + return []interface{}{0.1, idx} + }, + }, + { + prepare: "delete from t3 where sleep(?) and a = ?", + argsGen: func(idx int) []interface{} { + return []interface{}{0.1, idx} + }, + }, + { + prepare: "insert into t3 values (?, sleep(?)) on duplicate key update b = b+1", + argsGen: func(idx int) []interface{} { + return []interface{}{idx, 0.1} + }, + }, + { + prepare: "set global tidb_enable_1pc = (? = sleep(?))", + argsGen: func(idx int) []interface{} { + return []interface{}{0, 0.1} + }, + }, + } for _, ca := range cases3 { - checkFn(ca.prepare, ca.planRegexp) - ca.cancel() + _, digest := parser.NormalizeDigest(ca.prepare) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = ca.prepare } + wg.Add(1) + go func() { + defer wg.Done() + for _, ca := range cases3 { + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("use stmtstats;") + // prepare stmt + stmt, err := db.Prepare(ca.prepare) + require.NoError(t, err) + for n := 0; n < ExecCountPerSQL; n++ { + args := ca.argsGen(n) + if strings.HasPrefix(strings.ToLower(ca.prepare), "select") { + row, err := stmt.Query(args...) + require.NoError(t, err) + err = row.Close() + require.NoError(t, err) + } else { + _, err := stmt.Exec(args...) + require.NoError(t, err) + } + } + err = db.Close() + require.NoError(t, err) + } + }() - // Test case 4: transaction commit - ctx4, cancel4 := context.WithCancel(context.Background()) - defer cancel4() - go ts.loopExec(ctx4, t, func(db *sql.DB) { - db.Exec("begin") - db.Exec("insert into t () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()") - db.Exec("commit") - }) - // Check result of test case 4. - checkFn("commit", "") + wg.Wait() + // Wait for collect. + waitCollected(collectedNotifyCh) + + found := 0 + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + found++ + require.Equal(t, uint64(ExecCountPerSQL), item.ExecCount, sqlStr) + require.Equal(t, uint64(ExecCountPerSQL), item.DurationCount, sqlStr) + require.True(t, item.SumDurationNs > uint64(time.Millisecond*100*ExecCountPerSQL), sqlStr) + require.True(t, item.SumDurationNs < uint64(time.Millisecond*300*ExecCountPerSQL), sqlStr) + if strings.HasPrefix(sqlStr, "set global") { + // set global statement use internal SQL to change global variable, so itself doesn't have KV request. + continue + } + var kvSum uint64 + for _, kvCount := range item.KvStatsItem.KvExecCount { + kvSum += kvCount + } + require.Equal(t, uint64(ExecCountPerSQL), kvSum) + tagChecker.checkExist(t, digest.SQLDigest, sqlStr) + } + } + require.Equal(t, len(sqlDigests), found) + require.Equal(t, 20, found) +} + +type resourceTagChecker struct { + sync.Mutex + sqlDigest2Reqs map[stmtstats.BinaryDigest]map[tikvrpc.CmdType]struct{} } -func TestTopSQLAgent(t *testing.T) { - t.Skip("unstable, skip it and fix it before 20210702") +func (c *resourceTagChecker) checkExist(t *testing.T, digest stmtstats.BinaryDigest, sqlStr string) { + if strings.HasPrefix(sqlStr, "set global") { + // `set global` statement will use another internal sql to execute, so `set global` statement won't + // send RPC request. + return + } + if strings.HasPrefix(sqlStr, "trace") { + // `trace` statement will use another internal sql to execute, so remove the `trace` prefix before check. + _, sqlDigest := parser.NormalizeDigest(strings.TrimPrefix(sqlStr, "trace")) + digest = stmtstats.BinaryDigest(sqlDigest.Bytes()) + } + + c.Lock() + defer c.Unlock() + _, ok := c.sqlDigest2Reqs[digest] + require.True(t, ok, sqlStr) +} + +func (c *resourceTagChecker) checkReqExist(t *testing.T, digest stmtstats.BinaryDigest, sqlStr string, reqs ...tikvrpc.CmdType) { + if len(reqs) == 0 { + return + } + c.Lock() + defer c.Unlock() + reqMap, ok := c.sqlDigest2Reqs[digest] + require.True(t, ok, sqlStr) + for _, req := range reqs { + _, ok := reqMap[req] + require.True(t, ok, sqlStr+"--"+req.String()) + } +} + +func setupForTestTopSQLStatementStats(t *testing.T) (*tidbTestSuite, stmtstats.StatementStatsMap, *resourceTagChecker, chan struct{}, func()) { + // Prepare stmt stats. + stmtstats.SetupAggregator() + + // Register stmt stats collector. + var mu sync.Mutex + collectedNotifyCh := make(chan struct{}) + total := stmtstats.StatementStatsMap{} + mockCollector := newMockCollector(func(data stmtstats.StatementStatsMap) { + mu.Lock() + defer mu.Unlock() + total.Merge(data) + select { + case collectedNotifyCh <- struct{}{}: + default: + } + }) + stmtstats.RegisterCollector(mockCollector) + + ts, cleanup := createTidbTestSuite(t) - ts, cleanup := createTidbTestTopSQLSuite(t) - defer cleanup() db, err := sql.Open("mysql", ts.getDSN()) - require.NoError(t, err, "Error connecting") + require.NoError(t, err) defer func() { err := db.Close() require.NoError(t, err) }() - agentServer, err := mockTopSQLReporter.StartMockAgentServer() - require.NoError(t, err) - defer func() { - agentServer.Stop() - }() - require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/util/topsql/reporter/resetTimeoutForTest", `return(true)`)) require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop", `return(true)`)) - require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/util/topsql/mockHighLoadForEachSQL", `return(true)`)) - defer func() { - err := failpoint.Disable("github.com/pingcap/tidb/util/topsql/reporter/resetTimeoutForTest") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook", `return(true)`)) + + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("drop database if exists stmtstats") + dbt.MustExec("create database stmtstats") + dbt.MustExec("use stmtstats;") + dbt.MustExec("create table t (a int, b int, unique index idx(a));") + dbt.MustExec("create table t2 (a int, b int, unique index idx(a));") + dbt.MustExec("create table t3 (a int, b int, unique index idx(a));") + + // Enable TopSQL + topsqlstate.EnableTopSQL() + config.UpdateGlobal(func(conf *config.Config) { + conf.TopSQL.ReceiverAddress = "mock-agent" + }) + + tagChecker := &resourceTagChecker{ + sqlDigest2Reqs: make(map[stmtstats.BinaryDigest]map[tikvrpc.CmdType]struct{}), + } + unistore.UnistoreRPCClientSendHook = func(req *tikvrpc.Request) { + tag := req.GetResourceGroupTag() + if len(tag) == 0 || ddlutil.IsInternalResourceGroupTaggerForTopSQL(tag) { + // Ignore for internal background request. + return + } + sqlDigest, err := resourcegrouptag.DecodeResourceGroupTag(tag) require.NoError(t, err) + tagChecker.Lock() + defer tagChecker.Unlock() + + reqMap, ok := tagChecker.sqlDigest2Reqs[stmtstats.BinaryDigest(sqlDigest)] + if !ok { + reqMap = make(map[tikvrpc.CmdType]struct{}) + } + reqMap[req.Type] = struct{}{} + tagChecker.sqlDigest2Reqs[stmtstats.BinaryDigest(sqlDigest)] = reqMap + } + + cleanFn := func() { + stmtstats.UnregisterCollector(mockCollector) + cleanup() err = failpoint.Disable("github.com/pingcap/tidb/domain/skipLoadSysVarCacheLoop") require.NoError(t, err) - err = failpoint.Disable("github.com/pingcap/tidb/util/topsql/mockHighLoadForEachSQL") + err = failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/unistoreRPCClientSendHook") require.NoError(t, err) + stmtstats.CloseAggregator() + + } + return ts, total, tagChecker, collectedNotifyCh, cleanFn +} + +func TestTopSQLStatementStats2(t *testing.T) { + ts, total, tagChecker, collectedNotifyCh, cleanFn := setupForTestTopSQLStatementStats(t) + defer cleanFn() + + const ExecCountPerSQL = 3 + sqlDigests := map[stmtstats.BinaryDigest]string{} + + // Test case for other statements + cases4 := []struct { + sql string + plan string + isQuery bool + }{ + {"insert into t () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()", "", false}, + {"analyze table t", "", false}, + {"explain analyze select sum(a+b) from t", ".*TableReader.*", true}, + {"trace select sum(b*a), sum(a+b) from t", "", true}, + {"set global tidb_stmt_summary_history_size=5;", "", false}, + {"select * from stmtstats.t where exists (select 1 from stmtstats.t2 where t2.a = 1);", ".*TableReader.*", true}, + } + executeCaseFn := func(execFn func(db *sql.DB)) { + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("use stmtstats;") + require.NoError(t, err) + + for n := 0; n < ExecCountPerSQL; n++ { + execFn(db) + } + err = db.Close() + require.NoError(t, err) + } + execFn := func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases4 { + if ca.isQuery { + mustQuery(t, dbt, ca.sql) + } else { + dbt.MustExec(ca.sql) + } + } + } + for _, ca := range cases4 { + _, digest := parser.NormalizeDigest(ca.sql) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = ca.sql + } + executeCaseFn(execFn) + + // Test case for multi-statement. + cases5 := []string{ + "delete from t limit 1;", + "update t set b=1 where b is null limit 1;", + "select sum(a+b*2) from t;", + } + multiStatement5 := strings.Join(cases5, "") + // Test case for multi-statement, but first statements execute failed + cases6 := []string{ + "delete from t6_not_exist;", + "update t set a=1 where a is null limit 1;", + } + multiStatement6 := strings.Join(cases6, "") + // Test case for multi-statement, the first statements execute success but the second statement execute failed. + cases7 := []string{ + "update t set a=1 where a <0 limit 1;", + "delete from t7_not_exist;", + } + // Test case for DDL. + cases8 := []string{ + "create table if not exists t10 (a int, b int)", + "alter table t drop index if exists idx_b", + "alter table t add index idx_b (b)", + } + multiStatement7 := strings.Join(cases7, "") + execFn = func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("SET tidb_multi_statement_mode='ON'") + dbt.MustExec(multiStatement5) + + _, err := db.Exec(multiStatement6) + require.NotNil(t, err) + require.Equal(t, "Error 1146: Table 'stmtstats.t6_not_exist' doesn't exist", err.Error()) + + _, err = db.Exec(multiStatement7) + require.NotNil(t, err) + require.Equal(t, "Error 1146: Table 'stmtstats.t7_not_exist' doesn't exist", err.Error()) + + for _, ca := range cases8 { + dbt.MustExec(ca) + } + } + executeCaseFn(execFn) + sqlStrs := append([]string{}, cases5...) + sqlStrs = append(sqlStrs, cases7[0]) + sqlStrs = append(sqlStrs, cases8...) + for _, sqlStr := range sqlStrs { + _, digest := parser.NormalizeDigest(sqlStr) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = sqlStr + } + + // Wait for collect. + waitCollected(collectedNotifyCh) + + foundMap := map[stmtstats.BinaryDigest]string{} + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + require.Equal(t, uint64(ExecCountPerSQL), item.ExecCount, sqlStr) + require.True(t, item.SumDurationNs > 1, sqlStr) + foundMap[digest.SQLDigest] = sqlStr + tagChecker.checkExist(t, digest.SQLDigest, sqlStr) + // The special check uses to test the issue #33202. + if strings.Contains(strings.ToLower(sqlStr), "add index") { + tagChecker.checkReqExist(t, digest.SQLDigest, sqlStr, tikvrpc.CmdScan) + } + } + } + require.Equal(t, len(sqlDigests), len(foundMap), fmt.Sprintf("%v !=\n %v", sqlDigests, foundMap)) +} + +func TestTopSQLStatementStats3(t *testing.T) { + ts, total, tagChecker, collectedNotifyCh, cleanFn := setupForTestTopSQLStatementStats(t) + defer cleanFn() + + err := failpoint.Enable("github.com/pingcap/tidb/executor/mockSleepInTableReaderNext", "return(2000)") + require.NoError(t, err) + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/executor/mockSleepInTableReaderNext") }() - dbt := testkit.NewDBTestKit(t, db) - dbt.MustExec("drop database if exists topsql") - dbt.MustExec("create database topsql") - dbt.MustExec("use topsql;") - for i := 0; i < 20; i++ { - dbt.MustExec(fmt.Sprintf("create table t%v (a int auto_increment, b int, unique index idx(a));", i)) - for j := 0; j < 100; j++ { - dbt.MustExec(fmt.Sprintf("insert into t%v (b) values (%v);", i, j)) + cases := []string{ + "select count(a+b) from stmtstats.t", + "select * from stmtstats.t where b is null", + "update stmtstats.t set b = 1 limit 10", + "delete from stmtstats.t limit 1", + } + var wg sync.WaitGroup + sqlDigests := map[stmtstats.BinaryDigest]string{} + for _, ca := range cases { + wg.Add(1) + go func(sqlStr string) { + defer wg.Done() + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + require.NoError(t, err) + if strings.HasPrefix(sqlStr, "select") { + mustQuery(t, dbt, sqlStr) + } else { + dbt.MustExec(sqlStr) + } + err = db.Close() + require.NoError(t, err) + }(ca) + _, digest := parser.NormalizeDigest(ca) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = ca + } + // Wait for collect. + waitCollected(collectedNotifyCh) + + foundMap := map[stmtstats.BinaryDigest]string{} + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + // since the SQL doesn't execute finish, the ExecCount should be recorded, + // but the DurationCount and SumDurationNs should be 0. + require.Equal(t, uint64(1), item.ExecCount, sqlStr) + require.Equal(t, uint64(0), item.DurationCount, sqlStr) + require.Equal(t, uint64(0), item.SumDurationNs, sqlStr) + foundMap[digest.SQLDigest] = sqlStr } } - setTopSQLReceiverAddress := func(addr string) { - config.UpdateGlobal(func(conf *config.Config) { - conf.TopSQL.ReceiverAddress = addr - }) + + // wait sql execute finish. + wg.Wait() + // Wait for collect. + waitCollected(collectedNotifyCh) + + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + require.Equal(t, uint64(1), item.ExecCount, sqlStr) + require.Equal(t, uint64(1), item.DurationCount, sqlStr) + require.Less(t, uint64(0), item.SumDurationNs, sqlStr) + foundMap[digest.SQLDigest] = sqlStr + tagChecker.checkExist(t, digest.SQLDigest, sqlStr) + } } - dbt.MustExec("set @@global.tidb_enable_top_sql='On';") - setTopSQLReceiverAddress("") - dbt.MustExec("set @@global.tidb_top_sql_precision_seconds=1;") - dbt.MustExec("set @@global.tidb_top_sql_report_interval_seconds=2;") - dbt.MustExec("set @@global.tidb_top_sql_max_statement_count=5;") +} + +func TestTopSQLStatementStats4(t *testing.T) { + ts, total, tagChecker, collectedNotifyCh, cleanFn := setupForTestTopSQLStatementStats(t) + defer cleanFn() - r := reporter.NewRemoteTopSQLReporter(plancodec.DecodeNormalizedPlan) - s := reporter.NewSingleTargetDataSink(r) + err := failpoint.Enable("github.com/pingcap/tidb/executor/mockSleepInTableReaderNext", "return(2000)") + require.NoError(t, err) defer func() { - r.Close() - s.Close() + _ = failpoint.Disable("github.com/pingcap/tidb/executor/mockSleepInTableReaderNext") }() - tracecpu.GlobalSQLCPUProfiler.SetCollector(&collectorWrapper{r}) - - // TODO: change to ensure that the right sql statements are reported, not just counts - checkFn := func(n int) { - records := agentServer.GetLatestRecords() - require.Len(t, records, n) - for _, r := range records { - sqlMeta, exist := agentServer.GetSQLMetaByDigestBlocking(r.SqlDigest, time.Second) - require.True(t, exist) - require.Regexp(t, "^select.*from.*join", sqlMeta.NormalizedSql) - if len(r.PlanDigest) == 0 { - continue + cases := []struct { + prepare string + sql string + args []interface{} + }{ + {prepare: "select count(a+b) from stmtstats.t", sql: "select count(a+b) from stmtstats.t"}, + {prepare: "select * from stmtstats.t where b is null", sql: "select * from stmtstats.t where b is null"}, + {prepare: "update stmtstats.t set b = ? limit ?", sql: "update stmtstats.t set b = 1 limit 10", args: []interface{}{1, 10}}, + {prepare: "delete from stmtstats.t limit ?", sql: "delete from stmtstats.t limit 1", args: []interface{}{1}}, + } + var wg sync.WaitGroup + sqlDigests := map[stmtstats.BinaryDigest]string{} + for _, ca := range cases { + wg.Add(1) + go func(prepare string, args []interface{}) { + defer wg.Done() + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + stmt, err := db.Prepare(prepare) + require.NoError(t, err) + if strings.HasPrefix(prepare, "select") { + rows, err := stmt.Query(args...) + require.NoError(t, err) + for rows.Next() { + } + err = rows.Close() + require.NoError(t, err) + } else { + _, err := stmt.Exec(args...) + require.NoError(t, err) } - plan, exist := agentServer.GetPlanMetaByDigestBlocking(r.PlanDigest, time.Second) - require.True(t, exist) - plan = strings.Replace(plan, "\n", " ", -1) - plan = strings.Replace(plan, "\t", " ", -1) - require.Regexp(t, "Join.*Select", plan) + err = db.Close() + require.NoError(t, err) + }(ca.prepare, ca.args) + _, digest := parser.NormalizeDigest(ca.sql) + sqlDigests[stmtstats.BinaryDigest(digest.Bytes())] = ca.sql + } + // Wait for collect. + waitCollected(collectedNotifyCh) + + foundMap := map[stmtstats.BinaryDigest]string{} + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + // since the SQL doesn't execute finish, the ExecCount should be recorded, + // but the DurationCount and SumDurationNs should be 0. + require.Equal(t, uint64(1), item.ExecCount, sqlStr) + require.Equal(t, uint64(0), item.DurationCount, sqlStr) + require.Equal(t, uint64(0), item.SumDurationNs, sqlStr) + foundMap[digest.SQLDigest] = sqlStr } } - runWorkload := func(start, end int) context.CancelFunc { - ctx, cancel := context.WithCancel(context.Background()) - for i := start; i < end; i++ { - query := fmt.Sprintf("select /*+ HASH_JOIN(ta, tb) */ * from t%[1]v ta join t%[1]v tb on ta.a=tb.a where ta.b is not null;", i) - go ts.loopExec(ctx, t, func(db *sql.DB) { - dbt := testkit.NewDBTestKit(t, db) - rows := dbt.MustQuery(query) - require.NoError(t, rows.Close()) - }) + + // wait sql execute finish. + wg.Wait() + // Wait for collect. + waitCollected(collectedNotifyCh) + + for digest, item := range total { + if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok { + require.Equal(t, uint64(1), item.ExecCount, sqlStr) + require.Equal(t, uint64(1), item.DurationCount, sqlStr) + require.Less(t, uint64(0), item.SumDurationNs, sqlStr) + foundMap[digest.SQLDigest] = sqlStr + tagChecker.checkExist(t, digest.SQLDigest, sqlStr) } - return cancel - } - - // case 1: dynamically change agent endpoint - cancel := runWorkload(0, 10) - // Test with null agent address, the agent server can't receive any record. - setTopSQLReceiverAddress("") - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(0) - // Test after set agent address and the evict take effect. - dbt.MustExec("set @@global.tidb_top_sql_max_statement_count=5;") - setTopSQLReceiverAddress(agentServer.Address()) - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(5) - // Test with wrong agent address, the agent server can't receive any record. - dbt.MustExec("set @@global.tidb_top_sql_max_statement_count=8;") - setTopSQLReceiverAddress("127.0.0.1:65530") - - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(0) - // Test after set agent address and the evict take effect. - setTopSQLReceiverAddress(agentServer.Address()) - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(8) - cancel() // cancel case 1 - - // case 2: agent hangs for a while - cancel2 := runWorkload(0, 10) - // empty agent address, should not collect records - dbt.MustExec("set @@global.tidb_top_sql_max_statement_count=5;") - setTopSQLReceiverAddress("") - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(0) - // set correct address, should collect records - setTopSQLReceiverAddress(agentServer.Address()) - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(5) - // agent server hangs for a while - agentServer.HangFromNow(time.Second * 6) - // run another set of SQL queries - cancel2() - - cancel3 := runWorkload(11, 20) - agentServer.WaitCollectCnt(1, time.Second*8) - checkFn(5) - cancel3() - - // case 3: agent restart - cancel4 := runWorkload(0, 10) - // empty agent address, should not collect records - setTopSQLReceiverAddress("") - agentServer.WaitCollectCnt(1, time.Second*4) - checkFn(0) - // set correct address, should collect records - setTopSQLReceiverAddress(agentServer.Address()) - agentServer.WaitCollectCnt(1, time.Second*8) - checkFn(5) - // run another set of SQL queries - cancel4() - - cancel5 := runWorkload(11, 20) - // agent server shutdown - agentServer.Stop() - // agent server restart - agentServer, err = mockTopSQLReporter.StartMockAgentServer() - require.NoError(t, err) - setTopSQLReceiverAddress(agentServer.Address()) - // check result - agentServer.WaitCollectCnt(2, time.Second*8) - checkFn(5) - cancel5() + } +} + +func TestTopSQLResourceTag(t *testing.T) { + ts, _, tagChecker, _, cleanFn := setupForTestTopSQLStatementStats(t) + defer func() { + topsqlstate.DisableTopSQL() + cleanFn() + }() + + loadDataFile, err := os.CreateTemp("", "load_data_test0.csv") + require.NoError(t, err) + defer func() { + path := loadDataFile.Name() + err = loadDataFile.Close() + require.NoError(t, err) + err = os.Remove(path) + require.NoError(t, err) + }() + _, err = loadDataFile.WriteString( + "31 31\n" + + "32 32\n" + + "33 33\n") + require.NoError(t, err) + + // Test case for other statements + cases := []struct { + sql string + isQuery bool + reqs []tikvrpc.CmdType + }{ + // Test for curd. + {"insert into t values (1,1), (3,3)", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"insert into t values (1,2) on duplicate key update a = 2", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdBatchGet}}, + {"update t set b=b+1 where a=3", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdGet}}, + {"update t set b=b+1 where a>1", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdCop}}, + {"delete from t where a=3", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdGet}}, + {"delete from t where a>1", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdCop}}, + {"insert ignore into t values (2,2), (3,3)", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdBatchGet}}, + {"select * from t where a in (1,2,3,4)", true, []tikvrpc.CmdType{tikvrpc.CmdBatchGet}}, + {"select * from t where a = 1", true, []tikvrpc.CmdType{tikvrpc.CmdGet}}, + {"select * from t where b > 0", true, []tikvrpc.CmdType{tikvrpc.CmdCop}}, + {"replace into t values (2,2), (4,4)", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdBatchGet}}, + + // Test for DDL + {"create database test_db0", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"create table test_db0.test_t0 (a int, b int, index idx(a))", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"create table test_db0.test_t1 (a int, b int, index idx(a))", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"alter table test_db0.test_t0 add column c int", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"drop table test_db0.test_t0", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"drop database test_db0", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + {"alter table t modify column b double", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdScan, tikvrpc.CmdCop}}, + {"alter table t add index idx2 (b,a)", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdScan, tikvrpc.CmdCop}}, + {"alter table t drop index idx2", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + + // Test for transaction + {"begin", false, nil}, + {"insert into t2 values (10,10), (11,11)", false, nil}, + {"insert ignore into t2 values (20,20), (21,21)", false, []tikvrpc.CmdType{tikvrpc.CmdBatchGet}}, + {"commit", false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit}}, + + // Test for other statements. + {"set @@global.tidb_enable_1pc = 1", false, nil}, + {fmt.Sprintf("load data local infile %q into table t2", loadDataFile.Name()), false, []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdBatchGet}}, + } + + internalCases := []struct { + sql string + reqs []tikvrpc.CmdType + }{ + {"replace into mysql.global_variables (variable_name,variable_value) values ('tidb_enable_1pc', '1')", []tikvrpc.CmdType{tikvrpc.CmdPrewrite, tikvrpc.CmdCommit, tikvrpc.CmdBatchGet}}, + } + executeCaseFn := func(execFn func(db *sql.DB)) { + dsn := ts.getDSN(func(config *mysql.Config) { + config.AllowAllFiles = true + config.Params["sql_mode"] = "''" + }) + db, err := sql.Open("mysql", dsn) + require.NoError(t, err) + dbt := testkit.NewDBTestKit(t, db) + dbt.MustExec("use stmtstats;") + require.NoError(t, err) + + execFn(db) + err = db.Close() + require.NoError(t, err) + } + execFn := func(db *sql.DB) { + dbt := testkit.NewDBTestKit(t, db) + for _, ca := range cases { + if ca.isQuery { + mustQuery(t, dbt, ca.sql) + } else { + dbt.MustExec(ca.sql) + } + } + } + executeCaseFn(execFn) + + for _, ca := range cases { + _, digest := parser.NormalizeDigest(ca.sql) + tagChecker.checkReqExist(t, stmtstats.BinaryDigest(digest.Bytes()), ca.sql, ca.reqs...) + } + for _, ca := range internalCases { + _, digest := parser.NormalizeDigest(ca.sql) + tagChecker.checkReqExist(t, stmtstats.BinaryDigest(digest.Bytes()), ca.sql, ca.reqs...) + } } func (ts *tidbTestTopSQLSuite) loopExec(ctx context.Context, t *testing.T, fn func(db *sql.DB)) { @@ -1666,11 +2434,8 @@ func (ts *tidbTestTopSQLSuite) loopExec(ctx context.Context, t *testing.T, fn fu } func TestLocalhostClientMapping(t *testing.T) { - osTempDir := os.TempDir() - tempDir, err := os.MkdirTemp(osTempDir, "tidb-test.*.socket") - require.NoError(t, err) + tempDir := t.TempDir() socketFile := tempDir + "/tidbtest.sock" // Unix Socket does not work on Windows, so '/' should be OK - defer os.RemoveAll(tempDir) cli := newTestServerClient() cfg := newTestConfig() @@ -1769,3 +2534,64 @@ func TestLocalhostClientMapping(t *testing.T) { err = dbSocket.Ping() require.Errorf(t, err, "Connection successful without matching host for unix domain socket!") } + +func TestRcReadCheckTS(t *testing.T) { + ts, cleanup := createTidbTestSuite(t) + defer cleanup() + + db, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + defer func() { + err := db.Close() + require.NoError(t, err) + }() + + db2, err := sql.Open("mysql", ts.getDSN()) + require.NoError(t, err) + defer func() { + err := db2.Close() + require.NoError(t, err) + }() + tk2 := testkit.NewDBTestKit(t, db2) + tk2.MustExec("set @@tidb_enable_async_commit = 0") + tk2.MustExec("set @@tidb_enable_1pc = 0") + + cli := newTestServerClient() + + tk := testkit.NewDBTestKit(t, db) + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(c1 int key, c2 int)") + tk.MustExec("insert into t1 values(1, 10), (2, 20), (3, 30)") + + tk.MustExec(`set tidb_rc_read_check_ts = 'on';`) + tk.MustExec(`set tx_isolation = 'READ-COMMITTED';`) + tk.MustExec("begin pessimistic") + // Test point get retry. + rows := tk.MustQuery("select * from t1 where c1 = 1") + cli.checkRows(t, rows, "1 10") + tk2.MustExec("update t1 set c2 = c2 + 1") + rows = tk.MustQuery("select * from t1 where c1 = 1") + cli.checkRows(t, rows, "1 11") + // Test batch point get retry. + rows = tk.MustQuery("select * from t1 where c1 in (1, 3)") + cli.checkRows(t, rows, "1 11", "3 31") + tk2.MustExec("update t1 set c2 = c2 + 1") + rows = tk.MustQuery("select * from t1 where c1 in (1, 3)") + cli.checkRows(t, rows, "1 12", "3 32") + // Test scan retry. + rows = tk.MustQuery("select * from t1") + cli.checkRows(t, rows, "1 12", "2 22", "3 32") + tk2.MustExec("update t1 set c2 = c2 + 1") + rows = tk.MustQuery("select * from t1") + cli.checkRows(t, rows, "1 13", "2 23", "3 33") + // Test reverse scan retry. + rows = tk.MustQuery("select * from t1 order by c1 desc") + cli.checkRows(t, rows, "3 33", "2 23", "1 13") + tk2.MustExec("update t1 set c2 = c2 + 1") + rows = tk.MustQuery("select * from t1 order by c1 desc") + cli.checkRows(t, rows, "3 34", "2 24", "1 14") + + // Test retry caused by ongoing prewrite lock. + // As the `defaultLockTTL` is 3s and it's difficult to change it here, the lock + // test is implemented in the uft test cases. +} diff --git a/server/util.go b/server/util.go index d84b4cd566519..43144e6376f34 100644 --- a/server/util.go +++ b/server/util.go @@ -281,7 +281,9 @@ func dumpBinaryRow(buffer []byte, columns []*ColumnInfo, row chunk.Row, d *resul d.updateDataEncoding(columns[i].Charset) buffer = dumpLengthEncodedString(buffer, d.encodeData(hack.Slice(row.GetSet(i).String()))) case mysql.TypeJSON: - d.updateDataEncoding(columns[i].Charset) + // The collation of JSON type is always binary. + // To compatible with MySQL, here we treat it as utf-8. + d.updateDataEncoding(mysql.DefaultCollationID) buffer = dumpLengthEncodedString(buffer, d.encodeData(hack.Slice(row.GetJSON(i).String()))) default: return nil, errInvalidType.GenWithStack("invalid type %v", columns[i].Type) @@ -291,25 +293,17 @@ func dumpBinaryRow(buffer []byte, columns []*ColumnInfo, row chunk.Row, d *resul } type inputDecoder struct { - encoding *charset.Encoding - - buffer []byte + encoding charset.Encoding } func newInputDecoder(chs string) *inputDecoder { return &inputDecoder{ - encoding: charset.NewEncoding(chs), - buffer: nil, + encoding: charset.FindEncodingTakeUTF8AsNoop(chs), } } -// clean prevents the inputDecoder from holding too much memory. -func (i *inputDecoder) clean() { - i.buffer = nil -} - func (i *inputDecoder) decodeInput(src []byte) []byte { - result, err := i.encoding.Decode(i.buffer, src) + result, err := i.encoding.Transform(nil, src, charset.OpDecode) if err != nil { return src } @@ -320,23 +314,24 @@ type resultEncoder struct { // chsName and encoding are unchanged after the initialization from // session variable @@character_set_results. chsName string - encoding *charset.Encoding + encoding charset.Encoding // dataEncoding can be updated to match the column data charset. - dataEncoding *charset.Encoding + dataEncoding charset.Encoding - buffer []byte + buffer *bytes.Buffer - isBinary bool - isNull bool + isBinary bool + isNull bool + dataIsBinary bool } // newResultEncoder creates a new resultEncoder. func newResultEncoder(chs string) *resultEncoder { return &resultEncoder{ chsName: chs, - encoding: charset.NewEncoding(chs), - buffer: nil, + encoding: charset.FindEncodingTakeUTF8AsNoop(chs), + buffer: &bytes.Buffer{}, isBinary: chs == charset.CharsetBinary, isNull: len(chs) == 0, } @@ -352,7 +347,8 @@ func (d *resultEncoder) updateDataEncoding(chsID uint16) { if err != nil { logutil.BgLogger().Warn("unknown charset ID", zap.Error(err)) } - d.dataEncoding = charset.NewEncoding(chs) + d.dataEncoding = charset.FindEncodingTakeUTF8AsNoop(chs) + d.dataIsBinary = chsID == mysql.BinaryDefaultCollationID } func (d *resultEncoder) columnTypeInfoCharsetID(info *ColumnInfo) uint16 { @@ -367,24 +363,33 @@ func (d *resultEncoder) columnTypeInfoCharsetID(info *ColumnInfo) uint16 { return uint16(mysql.CharsetNameToID(d.chsName)) } +// encodeMeta encodes bytes for meta info like column names. +// Note that the result should be consumed immediately. func (d *resultEncoder) encodeMeta(src []byte) []byte { return d.encodeWith(src, d.encoding) } +// encodeData encodes bytes for row data. +// Note that the result should be consumed immediately. func (d *resultEncoder) encodeData(src []byte) []byte { - if d.isNull || d.isBinary { + // For the following cases, TiDB encodes the results with column charset + // instead of @@character_set_results: + // - @@character_set_result = null. + // - @@character_set_result = binary. + // - The column is binary type like blob, binary char/varchar. + if d.isNull || d.isBinary || d.dataIsBinary { // Use the column charset to encode. return d.encodeWith(src, d.dataEncoding) } return d.encodeWith(src, d.encoding) } -func (d *resultEncoder) encodeWith(src []byte, enc *charset.Encoding) []byte { - result, err := enc.Encode(d.buffer, src) +func (d *resultEncoder) encodeWith(src []byte, enc charset.Encoding) []byte { + data, err := enc.Transform(d.buffer, src, charset.OpEncode) if err != nil { logutil.BgLogger().Debug("encode error", zap.Error(err)) } - return result + return data } func dumpTextRow(buffer []byte, columns []*ColumnInfo, row chunk.Row, d *resultEncoder) ([]byte, error) { @@ -449,7 +454,9 @@ func dumpTextRow(buffer []byte, columns []*ColumnInfo, row chunk.Row, d *resultE d.updateDataEncoding(col.Charset) buffer = dumpLengthEncodedString(buffer, d.encodeData(hack.Slice(row.GetSet(i).String()))) case mysql.TypeJSON: - d.updateDataEncoding(col.Charset) + // The collation of JSON type is always binary. + // To compatible with MySQL, here we treat it as utf-8. + d.updateDataEncoding(mysql.DefaultCollationID) buffer = dumpLengthEncodedString(buffer, d.encodeData(hack.Slice(row.GetJSON(i).String()))) default: return nil, errInvalidType.GenWithStack("invalid type %v", columns[i].Type) diff --git a/session/bench_test.go b/session/bench_test.go index d34bb94501071..8d1bcb49d3b0a 100644 --- a/session/bench_test.go +++ b/session/bench_test.go @@ -445,6 +445,7 @@ func BenchmarkInsertWithIndex(b *testing.B) { do.Close() st.Close() }() + mustExecute(se, `set @@tidb_enable_mutation_checker = 0`) mustExecute(se, "drop table if exists t") mustExecute(se, "create table t (pk int primary key, col int, index idx (col))") b.ResetTimer() @@ -1692,7 +1693,7 @@ func BenchmarkInsertIntoSelect(b *testing.B) { do.Close() st.Close() }() - + mustExecute(se, `set @@tidb_enable_mutation_checker = 0`) mustExecute(se, `set @@tmp_table_size = 1000000000`) mustExecute(se, `create global temporary table tmp (id int, dt varchar(512)) on commit delete rows`) mustExecute(se, `create table src (id int, dt varchar(512))`) @@ -1812,7 +1813,7 @@ func BenchmarkCompileExecutePreparedStmt(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - _, _, _, err := executor.CompileExecutePreparedStmt(context.Background(), se, stmtID, is.(infoschema.InfoSchema), 0, args) + _, _, _, err := executor.CompileExecutePreparedStmt(context.Background(), se, stmtID, is.(infoschema.InfoSchema), 0, kv.GlobalTxnScope, args) if err != nil { b.Fatal(err) } diff --git a/session/bootstrap.go b/session/bootstrap.go index e5c588ec5af01..61c0cd073799f 100644 --- a/session/bootstrap.go +++ b/session/bootstrap.go @@ -32,7 +32,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" @@ -44,6 +43,7 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/logutil" utilparser "github.com/pingcap/tidb/util/parser" "github.com/pingcap/tidb/util/sqlexec" @@ -365,6 +365,55 @@ const ( oldReadLease bigint(20) NOT NULL DEFAULT 0, PRIMARY KEY (tid) );` + // CreateAnalyzeOptionsTable stores the analyze options used by analyze and auto analyze. + CreateAnalyzeOptionsTable = `CREATE TABLE IF NOT EXISTS mysql.analyze_options ( + table_id BIGINT(64) NOT NULL, + sample_num BIGINT(64) NOT NULL DEFAULT 0, + sample_rate DOUBLE NOT NULL DEFAULT -1, + buckets BIGINT(64) NOT NULL DEFAULT 0, + topn BIGINT(64) NOT NULL DEFAULT -1, + column_choice enum('DEFAULT','ALL','PREDICATE','LIST') NOT NULL DEFAULT 'DEFAULT', + column_ids TEXT(19372), + PRIMARY KEY (table_id) CLUSTERED + );` + // CreateStatsHistory stores the historical stats. + CreateStatsHistory = `CREATE TABLE IF NOT EXISTS mysql.stats_history ( + table_id bigint(64) NOT NULL, + stats_data longblob NOT NULL, + seq_no bigint(64) NOT NULL comment 'sequence number of the gzipped data slice', + version bigint(64) NOT NULL comment 'stats version which corresponding to stats:version in EXPLAIN', + create_time datetime(6) NOT NULL, + UNIQUE KEY table_version_seq (table_id, version, seq_no), + KEY table_create_time (table_id, create_time, seq_no) + );` + // CreateStatsMetaHistory stores the historical meta stats. + CreateStatsMetaHistory = `CREATE TABLE IF NOT EXISTS mysql.stats_meta_history ( + table_id bigint(64) NOT NULL, + modify_count bigint(64) NOT NULL, + count bigint(64) NOT NULL, + version bigint(64) NOT NULL comment 'stats version which corresponding to stats:version in EXPLAIN', + create_time datetime(6) NOT NULL, + UNIQUE KEY table_version (table_id, version), + KEY table_create_time (table_id, create_time) + );` + // CreateAnalyzeJobs stores the analyze jobs. + CreateAnalyzeJobs = `CREATE TABLE IF NOT EXISTS mysql.analyze_jobs ( + id BIGINT(64) UNSIGNED NOT NULL AUTO_INCREMENT, + update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + table_schema CHAR(64) NOT NULL DEFAULT '', + table_name CHAR(64) NOT NULL DEFAULT '', + partition_name CHAR(64) NOT NULL DEFAULT '', + job_info TEXT NOT NULL, + processed_rows BIGINT(64) UNSIGNED NOT NULL DEFAULT 0, + start_time TIMESTAMP, + end_time TIMESTAMP, + state ENUM('pending', 'running', 'finished', 'failed') NOT NULL, + fail_reason TEXT, + instance CHAR(64) NOT NULL comment 'address of the TiDB instance executing the analyze job', + process_id BIGINT(64) UNSIGNED comment 'ID of the process executing the analyze job', + PRIMARY KEY (id), + KEY (update_time) + );` ) // bootstrap initiates system DB for a store. @@ -541,11 +590,26 @@ const ( // version80 fixes the issue https://github.com/pingcap/tidb/issues/25422. // If the TiDB upgrading from the 4.x to a newer version, we keep the tidb_analyze_version to 1. version80 = 80 + // version81 insert "tidb_enable_index_merge|off" to mysql.GLOBAL_VARIABLES if there is no tidb_enable_index_merge. + // This will only happens when we upgrade a cluster before 4.0.0 to 4.0.0+. + version81 = 81 + // version82 adds the mysql.analyze_options table + version82 = 82 + // version83 adds the tables mysql.stats_history + version83 = 83 + // version84 adds the tables mysql.stats_meta_history + version84 = 84 + // version85 updates bindings with status 'using' in mysql.bind_info table to 'enabled' status + version85 = 85 + // version86 update mysql.tables_priv from SET('Select','Insert','Update') to SET('Select','Insert','Update','References'). + version86 = 86 + // version87 adds the mysql.analyze_jobs table + version87 = 87 ) // currentBootstrapVersion is defined as a variable, so we can modify its value for testing. // please make sure this is the largest version -var currentBootstrapVersion int64 = version80 +var currentBootstrapVersion int64 = version87 var ( bootstrapVersion = []func(Session, int64){ @@ -629,6 +693,13 @@ var ( upgradeToVer78, upgradeToVer79, upgradeToVer80, + upgradeToVer81, + upgradeToVer82, + upgradeToVer83, + upgradeToVer84, + upgradeToVer85, + upgradeToVer86, + upgradeToVer87, } ) @@ -823,8 +894,8 @@ func upgradeToVer10(s Session, ver int64) { doReentrantDDL(s, "ALTER TABLE mysql.stats_buckets CHANGE COLUMN `value` `upper_bound` BLOB NOT NULL", infoschema.ErrColumnNotExists, infoschema.ErrColumnExists) doReentrantDDL(s, "ALTER TABLE mysql.stats_buckets ADD COLUMN `lower_bound` BLOB", infoschema.ErrColumnExists) doReentrantDDL(s, "ALTER TABLE mysql.stats_histograms ADD COLUMN `null_count` BIGINT(64) NOT NULL DEFAULT 0", infoschema.ErrColumnExists) - doReentrantDDL(s, "ALTER TABLE mysql.stats_histograms DROP COLUMN distinct_ratio", ddl.ErrCantDropFieldOrKey) - doReentrantDDL(s, "ALTER TABLE mysql.stats_histograms DROP COLUMN use_count_to_estimate", ddl.ErrCantDropFieldOrKey) + doReentrantDDL(s, "ALTER TABLE mysql.stats_histograms DROP COLUMN distinct_ratio", dbterror.ErrCantDropFieldOrKey) + doReentrantDDL(s, "ALTER TABLE mysql.stats_histograms DROP COLUMN use_count_to_estimate", dbterror.ErrCantDropFieldOrKey) } func upgradeToVer11(s Session, ver int64) { @@ -994,9 +1065,9 @@ func upgradeToVer21(s Session, ver int64) { } mustExecute(s, CreateGCDeleteRangeDoneTable) - doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range DROP INDEX job_id", ddl.ErrCantDropFieldOrKey) - doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range ADD UNIQUE INDEX delete_range_index (job_id, element_id)", ddl.ErrDupKeyName) - doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range DROP INDEX element_id", ddl.ErrCantDropFieldOrKey) + doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range DROP INDEX job_id", dbterror.ErrCantDropFieldOrKey) + doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range ADD UNIQUE INDEX delete_range_index (job_id, element_id)", dbterror.ErrDupKeyName) + doReentrantDDL(s, "ALTER TABLE mysql.gc_delete_range DROP INDEX element_id", dbterror.ErrCantDropFieldOrKey) } func upgradeToVer22(s Session, ver int64) { @@ -1078,7 +1149,7 @@ func upgradeToVer29(s Session, ver int64) { } doReentrantDDL(s, "ALTER TABLE mysql.bind_info CHANGE create_time create_time TIMESTAMP(3)") doReentrantDDL(s, "ALTER TABLE mysql.bind_info CHANGE update_time update_time TIMESTAMP(3)") - doReentrantDDL(s, "ALTER TABLE mysql.bind_info ADD INDEX sql_index (original_sql(1024),default_db(1024))", ddl.ErrDupKeyName) + doReentrantDDL(s, "ALTER TABLE mysql.bind_info ADD INDEX sql_index (original_sql(1024),default_db(1024))", dbterror.ErrDupKeyName) } func upgradeToVer30(s Session, ver int64) { @@ -1201,13 +1272,12 @@ func upgradeToVer42(s Session, ver int64) { // Convert statement summary global variables to non-empty values. func writeStmtSummaryVars(s Session) { sql := "UPDATE %n.%n SET variable_value= %? WHERE variable_name= %? AND variable_value=''" - stmtSummaryConfig := config.GetGlobalConfig().StmtSummary - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, variable.BoolToOnOff(stmtSummaryConfig.Enable), variable.TiDBEnableStmtSummary) - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, variable.BoolToOnOff(stmtSummaryConfig.EnableInternalQuery), variable.TiDBStmtSummaryInternalQuery) - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.Itoa(stmtSummaryConfig.RefreshInterval), variable.TiDBStmtSummaryRefreshInterval) - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.Itoa(stmtSummaryConfig.HistorySize), variable.TiDBStmtSummaryHistorySize) - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.FormatUint(uint64(stmtSummaryConfig.MaxStmtCount), 10), variable.TiDBStmtSummaryMaxStmtCount) - mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.FormatUint(uint64(stmtSummaryConfig.MaxSQLLength), 10), variable.TiDBStmtSummaryMaxSQLLength) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, variable.BoolToOnOff(variable.DefTiDBEnableStmtSummary), variable.TiDBEnableStmtSummary) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, variable.BoolToOnOff(variable.DefTiDBStmtSummaryInternalQuery), variable.TiDBStmtSummaryInternalQuery) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.Itoa(variable.DefTiDBStmtSummaryRefreshInterval), variable.TiDBStmtSummaryRefreshInterval) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.Itoa(variable.DefTiDBStmtSummaryHistorySize), variable.TiDBStmtSummaryHistorySize) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.FormatUint(uint64(variable.DefTiDBStmtSummaryMaxStmtCount), 10), variable.TiDBStmtSummaryMaxStmtCount) + mustExecute(s, sql, mysql.SystemDB, mysql.GlobalVariablesTable, strconv.FormatUint(uint64(variable.DefTiDBStmtSummaryMaxSQLLength), 10), variable.TiDBStmtSummaryMaxSQLLength) } func upgradeToVer43(s Session, ver int64) { @@ -1466,7 +1536,7 @@ func updateBindInfo(iter *chunk.Iterator4Chunk, p *parser.Parser, bindMap map[st db := row.GetString(1) status := row.GetString(2) - if status != "using" && status != "builtin" { + if status != bindinfo.Enabled && status != bindinfo.Using && status != bindinfo.Builtin { continue } @@ -1590,7 +1660,7 @@ func upgradeToVer74(s Session, ver int64) { return } // The old default value of `tidb_stmt_summary_max_stmt_count` is 200, we want to enlarge this to the new default value when TiDB upgrade. - mustExecute(s, fmt.Sprintf("UPDATE mysql.global_variables SET VARIABLE_VALUE='%[1]v' WHERE VARIABLE_NAME = 'tidb_stmt_summary_max_stmt_count' AND CAST(VARIABLE_VALUE AS SIGNED) = 200", config.GetGlobalConfig().StmtSummary.MaxStmtCount)) + mustExecute(s, fmt.Sprintf("UPDATE mysql.global_variables SET VARIABLE_VALUE='%[1]v' WHERE VARIABLE_NAME = 'tidb_stmt_summary_max_stmt_count' AND CAST(VARIABLE_VALUE AS SIGNED) = 200", variable.DefTiDBStmtSummaryMaxStmtCount)) } func upgradeToVer75(s Session, ver int64) { @@ -1655,6 +1725,71 @@ func upgradeToVer80(s Session, ver int64) { mysql.SystemDB, mysql.GlobalVariablesTable, variable.TiDBAnalyzeVersion, 1) } +// For users that upgrade TiDB from a pre-4.0 version, we want to disable index merge by default. +// This helps minimize query plan regressions. +func upgradeToVer81(s Session, ver int64) { + if ver >= version81 { + return + } + // Check if tidb_enable_index_merge exists in mysql.GLOBAL_VARIABLES. + // If not, insert "tidb_enable_index_merge | off". + ctx := context.Background() + rs, err := s.ExecuteInternal(ctx, "SELECT VARIABLE_VALUE FROM %n.%n WHERE VARIABLE_NAME=%?;", + mysql.SystemDB, mysql.GlobalVariablesTable, variable.TiDBEnableIndexMerge) + terror.MustNil(err) + req := rs.NewChunk(nil) + err = rs.Next(ctx, req) + terror.MustNil(err) + if req.NumRows() != 0 { + return + } + + mustExecute(s, "INSERT HIGH_PRIORITY IGNORE INTO %n.%n VALUES (%?, %?);", + mysql.SystemDB, mysql.GlobalVariablesTable, variable.TiDBEnableIndexMerge, variable.Off) +} + +func upgradeToVer82(s Session, ver int64) { + if ver >= version82 { + return + } + doReentrantDDL(s, CreateAnalyzeOptionsTable) +} + +func upgradeToVer83(s Session, ver int64) { + if ver >= version83 { + return + } + doReentrantDDL(s, CreateStatsHistory) +} + +func upgradeToVer84(s Session, ver int64) { + if ver >= version84 { + return + } + doReentrantDDL(s, CreateStatsMetaHistory) +} + +func upgradeToVer85(s Session, ver int64) { + if ver >= version85 { + return + } + mustExecute(s, fmt.Sprintf("UPDATE HIGH_PRIORITY mysql.bind_info SET status= '%s' WHERE status = '%s'", bindinfo.Enabled, bindinfo.Using)) +} + +func upgradeToVer86(s Session, ver int64) { + if ver >= version86 { + return + } + doReentrantDDL(s, "ALTER TABLE mysql.tables_priv MODIFY COLUMN Column_priv SET('Select','Insert','Update','References')") +} + +func upgradeToVer87(s Session, ver int64) { + if ver >= version87 { + return + } + doReentrantDDL(s, CreateAnalyzeJobs) +} + func writeOOMAction(s Session) { comment := "oom-action is `log` by default in v3.0.x, `cancel` by default in v4.0.11+" mustExecute(s, `INSERT HIGH_PRIORITY INTO %n.%n VALUES (%?, %?, %?) ON DUPLICATE KEY UPDATE VARIABLE_VALUE= %?`, @@ -1739,6 +1874,14 @@ func doDDLWorks(s Session) { mustExecute(s, CreateColumnStatsUsageTable) // Create table_cache_meta table. mustExecute(s, CreateTableCacheMetaTable) + // Create analyze_options table. + mustExecute(s, CreateAnalyzeOptionsTable) + // Create stats_history table. + mustExecute(s, CreateStatsHistory) + // Create stats_meta_history table. + mustExecute(s, CreateStatsMetaHistory) + // Create analyze_jobs table. + mustExecute(s, CreateAnalyzeJobs) } // doDMLWorks executes DML statements in bootstrap stage. @@ -1793,6 +1936,12 @@ func doDMLWorks(s Session) { if v.Name == variable.TiDBEnable1PC && config.GetGlobalConfig().Store == "tikv" { vVal = variable.On } + if v.Name == variable.TiDBEnableMutationChecker { + vVal = variable.On + } + if v.Name == variable.TiDBTxnAssertionLevel { + vVal = variable.AssertionFastStr + } value := fmt.Sprintf(`("%s", "%s")`, strings.ToLower(k), vVal) values = append(values, value) } diff --git a/session/bootstrap_serial_test.go b/session/bootstrap_test.go similarity index 78% rename from session/bootstrap_serial_test.go rename to session/bootstrap_test.go index 6caf7e702c10b..581068a9f56bd 100644 --- a/session/bootstrap_serial_test.go +++ b/session/bootstrap_test.go @@ -21,6 +21,7 @@ import ( "strings" "testing" + "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/meta" @@ -32,6 +33,11 @@ import ( "github.com/stretchr/testify/require" ) +// This test file have many problem. +// 1. Please use testkit to create dom, session and store. +// 2. Don't use createStoreAndBootstrap and BootstrapSession together. It will cause data race. +// Please do not add any test here. You can add test case at the bootstrap_update_test.go. After All problem fixed, +// We will overwrite this file by update_test.go. func TestBootstrap(t *testing.T) { store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() @@ -213,7 +219,7 @@ func TestUpgrade(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() se := createSessionAndSetID(t, store) @@ -259,11 +265,10 @@ func TestUpgrade(t *testing.T) { ver, err = getBootstrapVersion(se1) require.NoError(t, err) require.Equal(t, int64(0), ver) - + dom.Close() // Create a new session then upgrade() will run automatically. - dom, err := BootstrapSession(store) + dom, err = BootstrapSession(store) require.NoError(t, err) - defer dom.Close() se2 := createSessionAndSetID(t, store) r = mustExec(t, se2, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="tidb_server_version"`) @@ -288,6 +293,7 @@ func TestUpgrade(t *testing.T) { require.Equal(t, 1, req.NumRows()) require.Equal(t, "False", req.GetRow(0).GetString(0)) require.NoError(t, r.Close()) + dom.Close() } func TestIssue17979_1(t *testing.T) { @@ -299,9 +305,8 @@ func TestIssue17979_1(t *testing.T) { }() ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() - // test issue 20900, upgrade from v3.0 to v4.0.11+ seV3 := createSessionAndSetID(t, store) txn, err := store.Begin() @@ -318,10 +323,9 @@ func TestIssue17979_1(t *testing.T) { ver, err := getBootstrapVersion(seV3) require.NoError(t, err) require.Equal(t, int64(58), ver) - + dom.Close() domV4, err := BootstrapSession(store) require.NoError(t, err) - defer domV4.Close() seV4 := createSessionAndSetID(t, store) ver, err = getBootstrapVersion(seV4) require.NoError(t, err) @@ -331,6 +335,7 @@ func TestIssue17979_1(t *testing.T) { require.NoError(t, r.Next(ctx, req)) require.Equal(t, "log", req.GetRow(0).GetString(0)) require.Equal(t, config.OOMActionLog, config.GetGlobalConfig().OOMAction) + domV4.Close() } func TestIssue17979_2(t *testing.T) { @@ -342,7 +347,7 @@ func TestIssue17979_2(t *testing.T) { }() ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() // test issue 20900, upgrade from v4.0.11 to v4.0.11 @@ -361,7 +366,7 @@ func TestIssue17979_2(t *testing.T) { ver, err := getBootstrapVersion(seV3) require.NoError(t, err) require.Equal(t, int64(59), ver) - + dom.Close() domV4, err := BootstrapSession(store) require.NoError(t, err) defer domV4.Close() @@ -386,9 +391,8 @@ func TestIssue20900_1(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() - // test issue 20900, upgrade from v3.0 to v4.0.9+ seV3 := createSessionAndSetID(t, store) txn, err := store.Begin() @@ -405,7 +409,7 @@ func TestIssue20900_1(t *testing.T) { ver, err := getBootstrapVersion(seV3) require.NoError(t, err) require.Equal(t, int64(38), ver) - + dom.Close() domV4, err := BootstrapSession(store) require.NoError(t, err) defer domV4.Close() @@ -434,7 +438,7 @@ func TestIssue20900_2(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() // test issue 20900, upgrade from v4.0.8 to v4.0.9+ @@ -453,10 +457,9 @@ func TestIssue20900_2(t *testing.T) { ver, err := getBootstrapVersion(seV3) require.NoError(t, err) require.Equal(t, int64(52), ver) - + dom.Close() domV4, err := BootstrapSession(store) require.NoError(t, err) - defer domV4.Close() seV4 := createSessionAndSetID(t, store) ver, err = getBootstrapVersion(seV4) require.NoError(t, err) @@ -470,6 +473,7 @@ func TestIssue20900_2(t *testing.T) { req = r.NewChunk(nil) require.NoError(t, r.Next(ctx, req)) require.Equal(t, 0, req.NumRows()) + domV4.Close() } func TestANSISQLMode(t *testing.T) { @@ -527,8 +531,6 @@ func TestStmtSummary(t *testing.T) { defer func() { require.NoError(t, store.Close()) }() defer dom.Close() se := createSessionAndSetID(t, store) - mustExec(t, se, `update mysql.global_variables set variable_value='' where variable_name='tidb_enable_stmt_summary'`) - writeStmtSummaryVars(se) r := mustExec(t, se, "select variable_value from mysql.global_variables where variable_name='tidb_enable_stmt_summary'") req := r.NewChunk(nil) @@ -581,7 +583,7 @@ func TestUpdateBindInfo(t *testing.T) { defer dom.Close() se := createSessionAndSetID(t, store) for _, bindCase := range bindCases { - sql := fmt.Sprintf("insert into mysql.bind_info values('%s', '%s', '%s', 'using', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')", + sql := fmt.Sprintf("insert into mysql.bind_info values('%s', '%s', '%s', 'enabled', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')", bindCase.originText, bindCase.bindText, bindCase.db, @@ -596,7 +598,7 @@ func TestUpdateBindInfo(t *testing.T) { require.Equal(t, bindCase.originWithDB, row.GetString(0)) require.Equal(t, bindCase.bindWithDB, row.GetString(1)) require.Equal(t, "", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.NoError(t, r.Close()) sql = fmt.Sprintf("drop global binding for %s", bindCase.deleteText) mustExec(t, se, sql) @@ -618,14 +620,14 @@ func TestUpdateDuplicateBindInfo(t *testing.T) { defer func() { require.NoError(t, store.Close()) }() defer dom.Close() se := createSessionAndSetID(t, store) - mustExec(t, se, `insert into mysql.bind_info values('select * from t', 'select /*+ use_index(t, idx_a)*/ * from t', 'test', 'using', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t', 'select /*+ use_index(t, idx_a)*/ * from t', 'test', 'enabled', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) // The latest one. - mustExec(t, se, `insert into mysql.bind_info values('select * from test . t', 'select /*+ use_index(t, idx_b)*/ * from test.t', 'test', 'using', '2021-01-04 14:50:58.257', '2021-01-09 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from test . t', 'select /*+ use_index(t, idx_b)*/ * from test.t', 'test', 'enabled', '2021-01-04 14:50:58.257', '2021-01-09 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) mustExec(t, se, `insert into mysql.bind_info values('select * from t where a < ?', 'select * from t use index(idx) where a < 1', 'test', 'deleted', '2021-06-04 17:04:43.333', '2021-06-04 17:04:43.335', 'utf8', 'utf8_general_ci', 'manual')`) - mustExec(t, se, `insert into mysql.bind_info values('select * from t where a < ?', 'select * from t ignore index(idx) where a < 1', 'test', 'using', '2021-06-04 17:04:43.335', '2021-06-04 17:04:43.335', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t where a < ?', 'select * from t ignore index(idx) where a < 1', 'test', 'enabled', '2021-06-04 17:04:43.335', '2021-06-04 17:04:43.335', 'utf8', 'utf8_general_ci', 'manual')`) mustExec(t, se, `insert into mysql.bind_info values('select * from test . t where a <= ?', 'select * from test.t use index(idx) where a <= 1', '', 'deleted', '2021-06-04 17:04:43.345', '2021-06-04 17:04:45.334', 'utf8', 'utf8_general_ci', 'manual')`) - mustExec(t, se, `insert into mysql.bind_info values('select * from test . t where a <= ?', 'select * from test.t ignore index(idx) where a <= 1', '', 'using', '2021-06-04 17:04:45.334', '2021-06-04 17:04:45.334', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from test . t where a <= ?', 'select * from test.t ignore index(idx) where a <= 1', '', 'enabled', '2021-06-04 17:04:45.334', '2021-06-04 17:04:45.334', 'utf8', 'utf8_general_ci', 'manual')`) upgradeToVer67(se, version66) @@ -637,19 +639,19 @@ func TestUpdateDuplicateBindInfo(t *testing.T) { require.Equal(t, "select * from `test` . `t`", row.GetString(0)) require.Equal(t, "SELECT /*+ use_index(`t` `idx_b`)*/ * FROM `test`.`t`", row.GetString(1)) require.Equal(t, "", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.Equal(t, "2021-01-04 14:50:58.257", row.GetTime(4).String()) row = req.GetRow(1) require.Equal(t, "select * from `test` . `t` where `a` < ?", row.GetString(0)) require.Equal(t, "SELECT * FROM `test`.`t` IGNORE INDEX (`idx`) WHERE `a` < 1", row.GetString(1)) require.Equal(t, "", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.Equal(t, "2021-06-04 17:04:43.335", row.GetTime(4).String()) row = req.GetRow(2) require.Equal(t, "select * from `test` . `t` where `a` <= ?", row.GetString(0)) require.Equal(t, "SELECT * FROM `test`.`t` IGNORE INDEX (`idx`) WHERE `a` <= 1", row.GetString(1)) require.Equal(t, "", row.GetString(2)) - require.Equal(t, "using", row.GetString(3)) + require.Equal(t, bindinfo.Enabled, row.GetString(3)) require.Equal(t, "2021-06-04 17:04:45.334", row.GetTime(4).String()) require.NoError(t, r.Close()) @@ -657,7 +659,7 @@ func TestUpdateDuplicateBindInfo(t *testing.T) { } func TestUpgradeClusteredIndexDefaultValue(t *testing.T) { - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() seV67 := createSessionAndSetID(t, store) @@ -676,10 +678,10 @@ func TestUpgradeClusteredIndexDefaultValue(t *testing.T) { ver, err := getBootstrapVersion(seV67) require.NoError(t, err) require.Equal(t, int64(67), ver) + dom.Close() domV68, err := BootstrapSession(store) require.NoError(t, err) - defer domV68.Close() seV68 := createSessionAndSetID(t, store) ver, err = getBootstrapVersion(seV68) require.NoError(t, err) @@ -692,13 +694,13 @@ func TestUpgradeClusteredIndexDefaultValue(t *testing.T) { row := req.GetRow(0) require.Equal(t, "INT_ONLY", row.GetString(0)) require.Equal(t, "INT_ONLY", row.GetString(1)) + domV68.Close() } func TestUpgradeVersion66(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() - seV65 := createSessionAndSetID(t, store) txn, err := store.Begin() require.NoError(t, err) @@ -714,10 +716,10 @@ func TestUpgradeVersion66(t *testing.T) { ver, err := getBootstrapVersion(seV65) require.NoError(t, err) require.Equal(t, int64(65), ver) - + dom.Close() domV66, err := BootstrapSession(store) require.NoError(t, err) - defer domV66.Close() + seV66 := createSessionAndSetID(t, store) ver, err = getBootstrapVersion(seV66) require.NoError(t, err) @@ -729,6 +731,7 @@ func TestUpgradeVersion66(t *testing.T) { row := req.GetRow(0) require.Equal(t, int64(1), row.GetInt64(0)) require.Equal(t, int64(1), row.GetInt64(1)) + domV66.Close() } func TestUpgradeVersion74(t *testing.T) { @@ -745,7 +748,7 @@ func TestUpgradeVersion74(t *testing.T) { for _, ca := range cases { func() { - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() seV73 := createSessionAndSetID(t, store) @@ -763,7 +766,7 @@ func TestUpgradeVersion74(t *testing.T) { ver, err := getBootstrapVersion(seV73) require.NoError(t, err) require.Equal(t, int64(72), ver) - + dom.Close() domV74, err := BootstrapSession(store) require.NoError(t, err) defer domV74.Close() @@ -771,13 +774,12 @@ func TestUpgradeVersion74(t *testing.T) { ver, err = getBootstrapVersion(seV74) require.NoError(t, err) require.Equal(t, currentBootstrapVersion, ver) - r := mustExec(t, seV74, `select @@global.tidb_stmt_summary_max_stmt_count, @@session.tidb_stmt_summary_max_stmt_count`) + r := mustExec(t, seV74, `SELECT @@global.tidb_stmt_summary_max_stmt_count`) req := r.NewChunk(nil) require.NoError(t, r.Next(ctx, req)) require.Equal(t, 1, req.NumRows()) row := req.GetRow(0) require.Equal(t, strconv.Itoa(ca.newValue), row.GetString(0)) - require.Equal(t, strconv.Itoa(ca.newValue), row.GetString(1)) }() } } @@ -785,7 +787,7 @@ func TestUpgradeVersion74(t *testing.T) { func TestUpgradeVersion75(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() seV74 := createSessionAndSetID(t, store) @@ -811,7 +813,7 @@ func TestUpgradeVersion75(t *testing.T) { require.NoError(t, r.Next(ctx, req)) require.Equal(t, "host", strings.ToLower(row.GetString(0))) require.Equal(t, "char(64)", strings.ToLower(row.GetString(1))) - + dom.Close() domV75, err := BootstrapSession(store) require.NoError(t, err) defer domV75.Close() @@ -836,19 +838,16 @@ func TestForIssue23387(t *testing.T) { store, err := mockstore.NewMockStore() require.NoError(t, err) defer func() { require.NoError(t, store.Close()) }() - _, err = BootstrapSession(store) - // domain leaked here, Close() is not called. For testing, it's OK. - // If we close it and BootstrapSession again, we'll get an error "session pool is closed". - // The problem is caused by some the global level variable, domain map is not intended for multiple instances. + dom, err := BootstrapSession(store) require.NoError(t, err) se := createSessionAndSetID(t, store) se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890")) mustExec(t, se, "create user quatest") - + dom.Close() // Upgrade to a newer version, check the user's privilege. currentBootstrapVersion = saveCurrentBootstrapVersion - dom, err := BootstrapSession(store) + dom, err = BootstrapSession(store) require.NoError(t, err) defer dom.Close() @@ -882,7 +881,7 @@ func TestReferencesPrivilegeOnColumn(t *testing.T) { func TestAnalyzeVersionUpgradeFrom300To500(t *testing.T) { ctx := context.Background() - store, _ := createStoreAndBootstrap(t) + store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() // Upgrade from 3.0.0 to 5.1+ or above. @@ -909,7 +908,7 @@ func TestAnalyzeVersionUpgradeFrom300To500(t *testing.T) { err = res.Next(ctx, chk) require.NoError(t, err) require.Equal(t, 0, chk.NumRows()) - + dom.Close() domCurVer, err := BootstrapSession(store) require.NoError(t, err) defer domCurVer.Close() @@ -928,3 +927,170 @@ func TestAnalyzeVersionUpgradeFrom300To500(t *testing.T) { require.Equal(t, 1, row.Len()) require.Equal(t, "1", row.GetString(0)) } + +func TestIndexMergeInNewCluster(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + // Indicates we are in a new cluster. + require.Equal(t, int64(notBootstrapped), getStoreBootstrapVersion(store)) + dom, err := BootstrapSession(store) + require.NoError(t, err) + defer func() { require.NoError(t, store.Close()) }() + defer dom.Close() + se := createSessionAndSetID(t, store) + + // In a new created cluster(above 5.4+), tidb_enable_index_merge is 1 by default. + mustExec(t, se, "use test;") + r := mustExec(t, se, "select @@tidb_enable_index_merge;") + require.NotNil(t, r) + + ctx := context.Background() + chk := r.NewChunk(nil) + err = r.Next(ctx, chk) + require.NoError(t, err) + require.Equal(t, 1, chk.NumRows()) + row := chk.GetRow(0) + require.Equal(t, 1, row.Len()) + require.Equal(t, int64(1), row.GetInt64(0)) +} + +func TestIndexMergeUpgradeFrom300To540(t *testing.T) { + ctx := context.Background() + store, dom := createStoreAndBootstrap(t) + defer func() { require.NoError(t, store.Close()) }() + + // Upgrade from 3.0.0 to 5.4+. + ver300 := 33 + seV3 := createSessionAndSetID(t, store) + txn, err := store.Begin() + require.NoError(t, err) + m := meta.NewMeta(txn) + err = m.FinishBootstrap(int64(ver300)) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + mustExec(t, seV3, fmt.Sprintf("update mysql.tidb set variable_value=%d where variable_name='tidb_server_version'", ver300)) + mustExec(t, seV3, fmt.Sprintf("delete from mysql.GLOBAL_VARIABLES where variable_name='%s'", variable.TiDBEnableIndexMerge)) + mustExec(t, seV3, "commit") + unsetStoreBootstrapped(store.UUID()) + ver, err := getBootstrapVersion(seV3) + require.NoError(t, err) + require.Equal(t, int64(ver300), ver) + + // We are now in 3.0.0, check tidb_enable_index_merge shoudle not exist. + res := mustExec(t, seV3, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", variable.TiDBEnableIndexMerge)) + chk := res.NewChunk(nil) + err = res.Next(ctx, chk) + require.NoError(t, err) + require.Equal(t, 0, chk.NumRows()) + dom.Close() + domCurVer, err := BootstrapSession(store) + require.NoError(t, err) + defer domCurVer.Close() + seCurVer := createSessionAndSetID(t, store) + ver, err = getBootstrapVersion(seCurVer) + require.NoError(t, err) + require.Equal(t, currentBootstrapVersion, ver) + + // We are now in 5.x, tidb_enable_index_merge should be off. + res = mustExec(t, seCurVer, "select @@tidb_enable_index_merge") + chk = res.NewChunk(nil) + err = res.Next(ctx, chk) + require.NoError(t, err) + require.Equal(t, 1, chk.NumRows()) + row := chk.GetRow(0) + require.Equal(t, 1, row.Len()) + require.Equal(t, int64(0), row.GetInt64(0)) +} + +func TestIndexMergeUpgradeFrom400To540(t *testing.T) { + for i := 0; i < 2; i++ { + func() { + ctx := context.Background() + store, dom := createStoreAndBootstrap(t) + defer func() { require.NoError(t, store.Close()) }() + + // upgrade from 4.0.0 to 5.4+. + ver400 := 46 + seV4 := createSessionAndSetID(t, store) + txn, err := store.Begin() + require.NoError(t, err) + m := meta.NewMeta(txn) + err = m.FinishBootstrap(int64(ver400)) + require.NoError(t, err) + err = txn.Commit(context.Background()) + require.NoError(t, err) + mustExec(t, seV4, fmt.Sprintf("update mysql.tidb set variable_value=%d where variable_name='tidb_server_version'", ver400)) + mustExec(t, seV4, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", variable.Off, variable.TiDBEnableIndexMerge)) + mustExec(t, seV4, "commit") + unsetStoreBootstrapped(store.UUID()) + ver, err := getBootstrapVersion(seV4) + require.NoError(t, err) + require.Equal(t, int64(ver400), ver) + + // We are now in 4.0.0, tidb_enable_index_merge is off. + res := mustExec(t, seV4, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", variable.TiDBEnableIndexMerge)) + chk := res.NewChunk(nil) + err = res.Next(ctx, chk) + require.NoError(t, err) + require.Equal(t, 1, chk.NumRows()) + row := chk.GetRow(0) + require.Equal(t, 2, row.Len()) + require.Equal(t, variable.Off, row.GetString(1)) + + if i == 0 { + // For the first time, We set tidb_enable_index_merge as on. + // And after upgrade to 5.x, tidb_enable_index_merge should remains to be on. + // For the second it should be off. + mustExec(t, seV4, "set global tidb_enable_index_merge = on") + } + dom.Close() + // Upgrade to 5.x. + domCurVer, err := BootstrapSession(store) + require.NoError(t, err) + defer domCurVer.Close() + seCurVer := createSessionAndSetID(t, store) + ver, err = getBootstrapVersion(seCurVer) + require.NoError(t, err) + require.Equal(t, currentBootstrapVersion, ver) + + // We are now in 5.x, tidb_enable_index_merge should be on because we enable it in 4.0.0. + res = mustExec(t, seCurVer, "select @@tidb_enable_index_merge") + chk = res.NewChunk(nil) + err = res.Next(ctx, chk) + require.NoError(t, err) + require.Equal(t, 1, chk.NumRows()) + row = chk.GetRow(0) + require.Equal(t, 1, row.Len()) + if i == 0 { + require.Equal(t, int64(1), row.GetInt64(0)) + } else { + require.Equal(t, int64(0), row.GetInt64(0)) + } + }() + } +} + +func TestUpgradeToVer85(t *testing.T) { + ctx := context.Background() + store, dom := createStoreAndBootstrap(t) + defer func() { require.NoError(t, store.Close()) }() + defer dom.Close() + se := createSessionAndSetID(t, store) + mustExec(t, se, `insert into mysql.bind_info values('select * from t', 'select /*+ use_index(t, idx_a)*/ * from t', 'test', 'using', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t1', 'select /*+ use_index(t1, idx_a)*/ * from t1', 'test', 'enabled', '2021-01-05 14:50:58.257', '2021-01-05 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t2', 'select /*+ use_index(t2, idx_a)*/ * from t2', 'test', 'disabled', '2021-01-06 14:50:58.257', '2021-01-06 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t3', 'select /*+ use_index(t3, idx_a)*/ * from t3', 'test', 'deleted', '2021-01-07 14:50:58.257', '2021-01-07 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + mustExec(t, se, `insert into mysql.bind_info values('select * from t4', 'select /*+ use_index(t4, idx_a)*/ * from t4', 'test', 'invalid', '2021-01-08 14:50:58.257', '2021-01-08 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`) + upgradeToVer85(se, version84) + + r := mustExec(t, se, `select count(*) from mysql.bind_info where status = 'enabled'`) + req := r.NewChunk(nil) + require.NoError(t, r.Next(ctx, req)) + require.Equal(t, 1, req.NumRows()) + row := req.GetRow(0) + require.Equal(t, int64(2), row.GetInt64(0)) + + require.NoError(t, r.Close()) + mustExec(t, se, "delete from mysql.bind_info where default_db = 'test'") +} diff --git a/session/bootstrap_upgrade_test.go b/session/bootstrap_upgrade_test.go new file mode 100644 index 0000000000000..15981329b4e98 --- /dev/null +++ b/session/bootstrap_upgrade_test.go @@ -0,0 +1,89 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package session_test + +import ( + "context" + "strings" + "testing" + + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestUpgradeVersion83(t *testing.T) { + ctx := context.Background() + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + ver, err := session.GetBootstrapVersion(tk.Session()) + require.NoError(t, err) + require.Equal(t, session.CurrentBootstrapVersion, ver) + + statsHistoryTblFields := []struct { + field string + tp string + }{ + {"table_id", "bigint(64)"}, + {"stats_data", "longblob"}, + {"seq_no", "bigint(64)"}, + {"version", "bigint(64)"}, + {"create_time", "datetime(6)"}, + } + rStatsHistoryTbl, err := tk.Exec(`desc mysql.stats_history`) + require.NoError(t, err) + req := rStatsHistoryTbl.NewChunk(nil) + require.NoError(t, rStatsHistoryTbl.Next(ctx, req)) + require.Equal(t, 5, req.NumRows()) + for i := 0; i < 5; i++ { + row := req.GetRow(i) + require.Equal(t, statsHistoryTblFields[i].field, strings.ToLower(row.GetString(0))) + require.Equal(t, statsHistoryTblFields[i].tp, strings.ToLower(row.GetString(1))) + } +} + +func TestUpgradeVersion84(t *testing.T) { + ctx := context.Background() + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + ver, err := session.GetBootstrapVersion(tk.Session()) + require.NoError(t, err) + require.Equal(t, session.CurrentBootstrapVersion, ver) + + statsHistoryTblFields := []struct { + field string + tp string + }{ + {"table_id", "bigint(64)"}, + {"modify_count", "bigint(64)"}, + {"count", "bigint(64)"}, + {"version", "bigint(64)"}, + {"create_time", "datetime(6)"}, + } + rStatsHistoryTbl, err := tk.Exec(`desc mysql.stats_meta_history`) + require.NoError(t, err) + req := rStatsHistoryTbl.NewChunk(nil) + require.NoError(t, rStatsHistoryTbl.Next(ctx, req)) + require.Equal(t, 5, req.NumRows()) + for i := 0; i < 5; i++ { + row := req.GetRow(i) + require.Equal(t, statsHistoryTblFields[i].field, strings.ToLower(row.GetString(0))) + require.Equal(t, statsHistoryTblFields[i].tp, strings.ToLower(row.GetString(1))) + } +} diff --git a/session/clustered_index_serial_test.go b/session/clustered_index_serial_test.go deleted file mode 100644 index 056c525944ac0..0000000000000 --- a/session/clustered_index_serial_test.go +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session_test - -import ( - "fmt" - "math/rand" - "strings" - "testing" - - "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/errno" - "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/israce" -) - -func TestCreateClusteredTable(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := createTestKit(t, store) - tk.MustExec("set @@tidb_enable_clustered_index = 'int_only';") - tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") - tk.MustExec("create table t1(id int primary key, v int)") - tk.MustExec("create table t2(id varchar(10) primary key, v int)") - tk.MustExec("create table t3(id int primary key clustered, v int)") - tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") - tk.MustExec("create table t5(id int primary key nonclustered, v int)") - tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") - tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") - tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") - tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) - - tk.MustExec("set @@tidb_enable_clustered_index = 'off';") - tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") - tk.MustExec("create table t1(id int primary key, v int)") - tk.MustExec("create table t2(id varchar(10) primary key, v int)") - tk.MustExec("create table t3(id int primary key clustered, v int)") - tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") - tk.MustExec("create table t5(id int primary key nonclustered, v int)") - tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") - tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") - tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") - tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) - - tk.MustExec("set @@tidb_enable_clustered_index = 'on';") - tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") - tk.MustExec("create table t1(id int primary key, v int)") - tk.MustExec("create table t2(id varchar(10) primary key, v int)") - tk.MustExec("create table t3(id int primary key clustered, v int)") - tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") - tk.MustExec("create table t5(id int primary key nonclustered, v int)") - tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") - tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") - tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") - tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) - - tk.MustExec("set @@tidb_enable_clustered_index = 'int_only';") - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.AlterPrimaryKey = true - }) - tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") - tk.MustExec("create table t1(id int primary key, v int)") - tk.MustExec("create table t2(id varchar(10) primary key, v int)") - tk.MustExec("create table t3(id int primary key clustered, v int)") - tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") - tk.MustExec("create table t5(id int primary key nonclustered, v int)") - tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") - tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") - tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") - tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) - tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) - tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) -} - -// Test for union scan in prefixed clustered index table. -// See https://github.com/pingcap/tidb/issues/22069. -func TestClusteredUnionScanOnPrefixingPrimaryKey(t *testing.T) { - originCollate := collate.NewCollationEnabled() - collate.SetNewCollationEnabledForTest(false) - defer collate.SetNewCollationEnabledForTest(originCollate) - store, clean := testkit.CreateMockStore(t) - defer clean() - tk := createTestKit(t, store) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (col_1 varchar(255), col_2 tinyint, primary key idx_1 (col_1(1)));") - tk.MustExec("insert into t values ('aaaaa', -38);") - tk.MustExec("insert into t values ('bbbbb', -48);") - - tk.MustExec("begin PESSIMISTIC;") - tk.MustExec("update t set col_2 = 47 where col_1 in ('aaaaa') order by col_1,col_2;") - tk.MustQuery("select * from t;").Check(testkit.Rows("aaaaa 47", "bbbbb -48")) - tk.MustGetErrCode("insert into t values ('bb', 0);", errno.ErrDupEntry) - tk.MustGetErrCode("insert into t values ('aa', 0);", errno.ErrDupEntry) - tk.MustExec("commit;") - tk.MustQuery("select * from t;").Check(testkit.Rows("aaaaa 47", "bbbbb -48")) - tk.MustExec("admin check table t;") -} - -// https://github.com/pingcap/tidb/issues/22453 -func TestClusteredIndexSplitAndAddIndex2(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := createTestKit(t, store) - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a int, b enum('Alice'), c int, primary key (c, b));") - tk.MustExec("insert into t values (-1,'Alice',100);") - tk.MustExec("insert into t values (-1,'Alice',7000);") - tk.MustQuery("split table t between (0,'Alice') and (10000,'Alice') regions 2;").Check(testkit.Rows("1 1")) - tk.MustExec("set @@global.tidb_ddl_error_count_limit = 3;") - tk.MustExec("alter table t add index idx (c);") - tk.MustExec("admin check table t;") -} - -func TestClusteredIndexSyntax(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - const showPKType = `select tidb_pk_type from information_schema.tables where table_schema = 'test' and table_name = 't';` - const nonClustered, clustered = `NONCLUSTERED`, `CLUSTERED` - assertPkType := func(sql string, pkType string) { - tk.MustExec("drop table if exists t;") - tk.MustExec(sql) - tk.MustQuery(showPKType).Check(testkit.Rows(pkType)) - } - - // Test single integer column as the primary key. - clusteredDefault := clustered - assertPkType("create table t (a int primary key, b int);", clusteredDefault) - assertPkType("create table t (a int, b int, primary key(a) clustered);", clustered) - assertPkType("create table t (a int, b int, primary key(a) /*T![clustered_index] clustered */);", clustered) - assertPkType("create table t (a int, b int, primary key(a) nonclustered);", nonClustered) - assertPkType("create table t (a int, b int, primary key(a) /*T![clustered_index] nonclustered */);", nonClustered) - - // Test for clustered index. - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly - assertPkType("create table t (a int, b varchar(255), primary key(b, a));", nonClustered) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) nonclustered);", nonClustered) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) clustered);", clustered) - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - assertPkType("create table t (a int, b varchar(255), primary key(b, a));", clusteredDefault) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) nonclustered);", nonClustered) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) /*T![clustered_index] nonclustered */);", nonClustered) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) clustered);", clustered) - assertPkType("create table t (a int, b varchar(255), primary key(b, a) /*T![clustered_index] clustered */);", clustered) - - tk.MustGetErrCode("create table t (a varchar(255) unique key clustered);", errno.ErrParse) - tk.MustGetErrCode("create table t (a varchar(255), foreign key (a) reference t1(a) clustered);", errno.ErrParse) - tk.MustGetErrCode("create table t (a varchar(255), foreign key (a) clustered reference t1(a));", errno.ErrParse) - tk.MustGetErrCode("create table t (a varchar(255) clustered);", errno.ErrParse) - - errMsg := "[ddl:8200]CLUSTERED/NONCLUSTERED keyword is only supported for primary key" - tk.MustGetErrMsg("create table t (a varchar(255), unique key(a) clustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), unique key(a) nonclustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), unique index(a) clustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), unique index(a) nonclustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), key(a) clustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), key(a) nonclustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), index(a) clustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), index(a) nonclustered);", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), b decimal(5, 4), primary key (a, b) clustered, key (b) clustered)", errMsg) - tk.MustGetErrMsg("create table t (a varchar(255), b decimal(5, 4), primary key (a, b) clustered, key (b) nonclustered)", errMsg) -} - -func TestPrefixClusteredIndexAddIndexAndRecover(t *testing.T) { - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk1 := testkit.NewTestKit(t, store) - tk1.MustExec("use test;") - tk1.MustExec("drop table if exists t;") - defer func() { - tk1.MustExec("drop table if exists t;") - }() - - tk1.MustExec("create table t(a char(3), b char(3), primary key(a(1)) clustered)") - tk1.MustExec("insert into t values ('aaa', 'bbb')") - tk1.MustExec("alter table t add index idx(b)") - tk1.MustQuery("select * from t use index(idx)").Check(testkit.Rows("aaa bbb")) - tk1.MustExec("admin check table t") - tk1.MustExec("admin recover index t idx") - tk1.MustQuery("select * from t use index(idx)").Check(testkit.Rows("aaa bbb")) - tk1.MustExec("admin check table t") -} - -func TestPartitionTable(t *testing.T) { - if israce.RaceEnabled { - t.Skip("exhaustive types test, skip race test") - } - - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("create database test_view") - tk.MustExec("use test_view") - tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") - - tk.MustExec(`create table thash (a int, b int, c varchar(32), primary key(a, b) clustered) partition by hash(a) partitions 4`) - tk.MustExec(`create table trange (a int, b int, c varchar(32), primary key(a, b) clustered) partition by range columns(a) ( - partition p0 values less than (3000), - partition p1 values less than (6000), - partition p2 values less than (9000), - partition p3 values less than (10000))`) - tk.MustExec(`create table tnormal (a int, b int, c varchar(32), primary key(a, b))`) - - vals := make([]string, 0, 4000) - existedPK := make(map[string]struct{}, 4000) - for i := 0; i < 4000; { - a := rand.Intn(10000) - b := rand.Intn(10000) - pk := fmt.Sprintf("%v, %v", a, b) - if _, ok := existedPK[pk]; ok { - continue - } - existedPK[pk] = struct{}{} - i++ - vals = append(vals, fmt.Sprintf(`(%v, %v, '%v')`, a, b, rand.Intn(10000))) - } - - tk.MustExec("insert into thash values " + strings.Join(vals, ", ")) - tk.MustExec("insert into trange values " + strings.Join(vals, ", ")) - tk.MustExec("insert into tnormal values " + strings.Join(vals, ", ")) - - for i := 0; i < 200; i++ { - cond := fmt.Sprintf("where a in (%v, %v, %v) and b < %v", rand.Intn(10000), rand.Intn(10000), rand.Intn(10000), rand.Intn(10000)) - result := tk.MustQuery("select * from tnormal " + cond).Sort().Rows() - tk.MustQuery("select * from thash use index(primary) " + cond).Sort().Check(result) - tk.MustQuery("select * from trange use index(primary) " + cond).Sort().Check(result) - } -} - -// https://github.com/pingcap/tidb/issues/23106 -func TestClusteredIndexDecodeRestoredDataV5(t *testing.T) { - defer collate.SetNewCollationEnabledForTest(false) - collate.SetNewCollationEnabledForTest(true) - - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (id1 int, id2 varchar(10), a1 int, primary key(id1, id2) clustered) collate utf8mb4_general_ci;") - tk.MustExec("insert into t values (1, 'asd', 1), (1, 'dsa', 1);") - tk.MustGetErrCode("alter table t add unique index t_idx(id1, a1);", errno.ErrDupEntry) - - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (id1 int, id2 varchar(10), a1 int, primary key(id1, id2) clustered, unique key t_idx(id1, a1)) collate utf8mb4_general_ci;") - tk.MustExec("begin;") - tk.MustExec("insert into t values (1, 'asd', 1);") - tk.MustQuery("select * from t use index (t_idx);").Check(testkit.Rows("1 asd 1")) - tk.MustExec("commit;") - tk.MustExec("admin check table t;") - tk.MustExec("drop table t;") -} - -// https://github.com/pingcap/tidb/issues/23178 -func TestPrefixedClusteredIndexUniqueKeyWithNewCollation(t *testing.T) { - defer collate.SetNewCollationEnabledForTest(false) - collate.SetNewCollationEnabledForTest(true) - - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("create table t (a text collate utf8mb4_general_ci not null, b int(11) not null, " + - "primary key (a(10), b) clustered, key idx(a(2)) ) default charset=utf8mb4 collate=utf8mb4_bin;") - tk.MustExec("insert into t values ('aaa', 2);") - // Key-value content: sk = sortKey, p = prefixed - // row record: sk(aaa), 2 -> aaa - // index record: sk(p(aa)), {sk(aaa), 2} -> restore data(aaa) - tk.MustExec("admin check table t;") - tk.MustExec("drop table t;") -} - -func TestClusteredIndexNewCollationWithOldRowFormat(t *testing.T) { - // This case maybe not useful, because newCollation isn't convenience to run on TiKV(it's required serialSuit) - // but unistore doesn't support old row format. - defer collate.SetNewCollationEnabledForTest(false) - collate.SetNewCollationEnabledForTest(true) - - store, clean := testkit.CreateMockStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test;") - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.Session().GetSessionVars().RowEncoder.Enable = false - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t2(col_1 varchar(132) CHARACTER SET utf8 COLLATE utf8_unicode_ci, primary key(col_1) clustered)") - tk.MustExec("insert into t2 select 'aBc'") - tk.MustQuery("select col_1 from t2 where col_1 = 'aBc'").Check(testkit.Rows("aBc")) -} diff --git a/session/clustered_index_test.go b/session/clustered_index_test.go index b993bd3405a6d..e04052c1b6c79 100644 --- a/session/clustered_index_test.go +++ b/session/clustered_index_test.go @@ -15,14 +15,19 @@ package session_test import ( + "fmt" + "math/rand" + "strings" "testing" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/testkit/testdata" + "github.com/pingcap/tidb/util/collate" "github.com/stretchr/testify/require" ) @@ -421,3 +426,302 @@ func TestClusteredIndexSelectWhereInNull(t *testing.T) { tk.MustExec("create table t (a datetime, b bigint, primary key (a));") tk.MustQuery("select * from t where a in (null);").Check(testkit.Rows( /* empty result */ )) } + +func TestCreateClusteredTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := createTestKit(t, store) + tk.MustExec("set @@tidb_enable_clustered_index = 'int_only';") + tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") + tk.MustExec("create table t1(id int primary key, v int)") + tk.MustExec("create table t2(id varchar(10) primary key, v int)") + tk.MustExec("create table t3(id int primary key clustered, v int)") + tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") + tk.MustExec("create table t5(id int primary key nonclustered, v int)") + tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") + tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") + tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") + tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) + + tk.MustExec("set @@tidb_enable_clustered_index = 'off';") + tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") + tk.MustExec("create table t1(id int primary key, v int)") + tk.MustExec("create table t2(id varchar(10) primary key, v int)") + tk.MustExec("create table t3(id int primary key clustered, v int)") + tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") + tk.MustExec("create table t5(id int primary key nonclustered, v int)") + tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") + tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") + tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") + tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) + + tk.MustExec("set @@tidb_enable_clustered_index = 'on';") + tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") + tk.MustExec("create table t1(id int primary key, v int)") + tk.MustExec("create table t2(id varchar(10) primary key, v int)") + tk.MustExec("create table t3(id int primary key clustered, v int)") + tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") + tk.MustExec("create table t5(id int primary key nonclustered, v int)") + tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") + tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") + tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") + tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) + + tk.MustExec("set @@tidb_enable_clustered_index = 'int_only';") + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.AlterPrimaryKey = true + }) + tk.MustExec("drop table if exists t1, t2, t3, t4, t5, t6, t7, t8") + tk.MustExec("create table t1(id int primary key, v int)") + tk.MustExec("create table t2(id varchar(10) primary key, v int)") + tk.MustExec("create table t3(id int primary key clustered, v int)") + tk.MustExec("create table t4(id varchar(10) primary key clustered, v int)") + tk.MustExec("create table t5(id int primary key nonclustered, v int)") + tk.MustExec("create table t6(id varchar(10) primary key nonclustered, v int)") + tk.MustExec("create table t7(id varchar(10), v int, primary key (id) /*T![clustered_index] CLUSTERED */)") + tk.MustExec("create table t8(id varchar(10), v int, primary key (id) /*T![clustered_index] NONCLUSTERED */)") + tk.MustQuery("show index from t1").Check(testkit.Rows("t1 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t2").Check(testkit.Rows("t2 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t3").Check(testkit.Rows("t3 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t4").Check(testkit.Rows("t4 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t5").Check(testkit.Rows("t5 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t6").Check(testkit.Rows("t6 0 PRIMARY 1 id A 0 BTREE YES NO")) + tk.MustQuery("show index from t7").Check(testkit.Rows("t7 0 PRIMARY 1 id A 0 BTREE YES YES")) + tk.MustQuery("show index from t8").Check(testkit.Rows("t8 0 PRIMARY 1 id A 0 BTREE YES NO")) +} + +// Test for union scan in prefixed clustered index table. +// See https://github.com/pingcap/tidb/issues/22069. +func TestClusteredUnionScanOnPrefixingPrimaryKey(t *testing.T) { + originCollate := collate.NewCollationEnabled() + collate.SetNewCollationEnabledForTest(false) + defer collate.SetNewCollationEnabledForTest(originCollate) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := createTestKit(t, store) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (col_1 varchar(255), col_2 tinyint, primary key idx_1 (col_1(1)));") + tk.MustExec("insert into t values ('aaaaa', -38);") + tk.MustExec("insert into t values ('bbbbb', -48);") + + tk.MustExec("begin PESSIMISTIC;") + tk.MustExec("update t set col_2 = 47 where col_1 in ('aaaaa') order by col_1,col_2;") + tk.MustQuery("select * from t;").Check(testkit.Rows("aaaaa 47", "bbbbb -48")) + tk.MustGetErrCode("insert into t values ('bb', 0);", errno.ErrDupEntry) + tk.MustGetErrCode("insert into t values ('aa', 0);", errno.ErrDupEntry) + tk.MustExec("commit;") + tk.MustQuery("select * from t;").Check(testkit.Rows("aaaaa 47", "bbbbb -48")) + tk.MustExec("admin check table t;") +} + +// https://github.com/pingcap/tidb/issues/22453 +func TestClusteredIndexSplitAndAddIndex2(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := createTestKit(t, store) + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a int, b enum('Alice'), c int, primary key (c, b));") + tk.MustExec("insert into t values (-1,'Alice',100);") + tk.MustExec("insert into t values (-1,'Alice',7000);") + tk.MustQuery("split table t between (0,'Alice') and (10000,'Alice') regions 2;").Check(testkit.Rows("1 1")) + tk.MustExec("set @@global.tidb_ddl_error_count_limit = 3;") + tk.MustExec("alter table t add index idx (c);") + tk.MustExec("admin check table t;") +} + +func TestClusteredIndexSyntax(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + const showPKType = `select tidb_pk_type from information_schema.tables where table_schema = 'test' and table_name = 't';` + const nonClustered, clustered = `NONCLUSTERED`, `CLUSTERED` + assertPkType := func(sql string, pkType string) { + tk.MustExec("drop table if exists t;") + tk.MustExec(sql) + tk.MustQuery(showPKType).Check(testkit.Rows(pkType)) + } + + // Test single integer column as the primary key. + clusteredDefault := clustered + assertPkType("create table t (a int primary key, b int);", clusteredDefault) + assertPkType("create table t (a int, b int, primary key(a) clustered);", clustered) + assertPkType("create table t (a int, b int, primary key(a) /*T![clustered_index] clustered */);", clustered) + assertPkType("create table t (a int, b int, primary key(a) nonclustered);", nonClustered) + assertPkType("create table t (a int, b int, primary key(a) /*T![clustered_index] nonclustered */);", nonClustered) + + // Test for clustered index. + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly + assertPkType("create table t (a int, b varchar(255), primary key(b, a));", nonClustered) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) nonclustered);", nonClustered) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) clustered);", clustered) + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + assertPkType("create table t (a int, b varchar(255), primary key(b, a));", clusteredDefault) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) nonclustered);", nonClustered) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) /*T![clustered_index] nonclustered */);", nonClustered) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) clustered);", clustered) + assertPkType("create table t (a int, b varchar(255), primary key(b, a) /*T![clustered_index] clustered */);", clustered) + + tk.MustGetErrCode("create table t (a varchar(255) unique key clustered);", errno.ErrParse) + tk.MustGetErrCode("create table t (a varchar(255), foreign key (a) reference t1(a) clustered);", errno.ErrParse) + tk.MustGetErrCode("create table t (a varchar(255), foreign key (a) clustered reference t1(a));", errno.ErrParse) + tk.MustGetErrCode("create table t (a varchar(255) clustered);", errno.ErrParse) + + errMsg := "[ddl:8200]CLUSTERED/NONCLUSTERED keyword is only supported for primary key" + tk.MustGetErrMsg("create table t (a varchar(255), unique key(a) clustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), unique key(a) nonclustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), unique index(a) clustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), unique index(a) nonclustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), key(a) clustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), key(a) nonclustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), index(a) clustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), index(a) nonclustered);", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), b decimal(5, 4), primary key (a, b) clustered, key (b) clustered)", errMsg) + tk.MustGetErrMsg("create table t (a varchar(255), b decimal(5, 4), primary key (a, b) clustered, key (b) nonclustered)", errMsg) +} + +func TestPrefixClusteredIndexAddIndexAndRecover(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test;") + tk1.MustExec("drop table if exists t;") + defer func() { + tk1.MustExec("drop table if exists t;") + }() + + tk1.MustExec("create table t(a char(3), b char(3), primary key(a(1)) clustered)") + tk1.MustExec("insert into t values ('aaa', 'bbb')") + tk1.MustExec("alter table t add index idx(b)") + tk1.MustQuery("select * from t use index(idx)").Check(testkit.Rows("aaa bbb")) + tk1.MustExec("admin check table t") + tk1.MustExec("admin recover index t idx") + tk1.MustQuery("select * from t use index(idx)").Check(testkit.Rows("aaa bbb")) + tk1.MustExec("admin check table t") +} + +func TestPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("create database test_view") + tk.MustExec("use test_view") + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + + tk.MustExec(`create table thash (a int, b int, c varchar(32), primary key(a, b) clustered) partition by hash(a) partitions 4`) + tk.MustExec(`create table trange (a int, b int, c varchar(32), primary key(a, b) clustered) partition by range columns(a) ( + partition p0 values less than (3000), + partition p1 values less than (6000), + partition p2 values less than (9000), + partition p3 values less than (10000))`) + tk.MustExec(`create table tnormal (a int, b int, c varchar(32), primary key(a, b))`) + + vals := make([]string, 0, 4000) + existedPK := make(map[string]struct{}, 4000) + for i := 0; i < 4000; { + a := rand.Intn(10000) + b := rand.Intn(10000) + pk := fmt.Sprintf("%v, %v", a, b) + if _, ok := existedPK[pk]; ok { + continue + } + existedPK[pk] = struct{}{} + i++ + vals = append(vals, fmt.Sprintf(`(%v, %v, '%v')`, a, b, rand.Intn(10000))) + } + + tk.MustExec("insert into thash values " + strings.Join(vals, ", ")) + tk.MustExec("insert into trange values " + strings.Join(vals, ", ")) + tk.MustExec("insert into tnormal values " + strings.Join(vals, ", ")) + + for i := 0; i < 200; i++ { + cond := fmt.Sprintf("where a in (%v, %v, %v) and b < %v", rand.Intn(10000), rand.Intn(10000), rand.Intn(10000), rand.Intn(10000)) + result := tk.MustQuery("select * from tnormal " + cond).Sort().Rows() + tk.MustQuery("select * from thash use index(primary) " + cond).Sort().Check(result) + tk.MustQuery("select * from trange use index(primary) " + cond).Sort().Check(result) + } +} + +// https://github.com/pingcap/tidb/issues/23106 +func TestClusteredIndexDecodeRestoredDataV5(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (id1 int, id2 varchar(10), a1 int, primary key(id1, id2) clustered) collate utf8mb4_general_ci;") + tk.MustExec("insert into t values (1, 'asd', 1), (1, 'dsa', 1);") + tk.MustGetErrCode("alter table t add unique index t_idx(id1, a1);", errno.ErrDupEntry) + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (id1 int, id2 varchar(10), a1 int, primary key(id1, id2) clustered, unique key t_idx(id1, a1)) collate utf8mb4_general_ci;") + tk.MustExec("begin;") + tk.MustExec("insert into t values (1, 'asd', 1);") + tk.MustQuery("select * from t use index (t_idx);").Check(testkit.Rows("1 asd 1")) + tk.MustExec("commit;") + tk.MustExec("admin check table t;") + tk.MustExec("drop table t;") +} + +// https://github.com/pingcap/tidb/issues/23178 +func TestPrefixedClusteredIndexUniqueKeyWithNewCollation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.MustExec("create table t (a text collate utf8mb4_general_ci not null, b int(11) not null, " + + "primary key (a(10), b) clustered, key idx(a(2)) ) default charset=utf8mb4 collate=utf8mb4_bin;") + tk.MustExec("insert into t values ('aaa', 2);") + // Key-value content: sk = sortKey, p = prefixed + // row record: sk(aaa), 2 -> aaa + // index record: sk(p(aa)), {sk(aaa), 2} -> restore data(aaa) + tk.MustExec("admin check table t;") + tk.MustExec("drop table t;") +} + +func TestClusteredIndexNewCollationWithOldRowFormat(t *testing.T) { + // This case maybe not useful, because newCollation isn't convenience to run on TiKV(it's required serialSuit) + // but unistore doesn't support old row format. + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn + tk.Session().GetSessionVars().RowEncoder.Enable = false + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2(col_1 varchar(132) CHARACTER SET utf8 COLLATE utf8_unicode_ci, primary key(col_1) clustered)") + tk.MustExec("insert into t2 select 'aBc'") + tk.MustQuery("select col_1 from t2 where col_1 = 'aBc'").Check(testkit.Rows("aBc")) +} diff --git a/session/index_usage_sync_lease_serial_test.go b/session/index_usage_sync_lease_test.go similarity index 92% rename from session/index_usage_sync_lease_serial_test.go rename to session/index_usage_sync_lease_test.go index 53327f45cf308..ede3aca8d01e6 100644 --- a/session/index_usage_sync_lease_serial_test.go +++ b/session/index_usage_sync_lease_test.go @@ -20,6 +20,9 @@ import ( "github.com/stretchr/testify/require" ) +var GetBootstrapVersion = getBootstrapVersion +var CurrentBootstrapVersion = currentBootstrapVersion + func TestIndexUsageSyncLease(t *testing.T) { store, dom := createStoreAndBootstrap(t) defer func() { require.NoError(t, store.Close()) }() diff --git a/session/isolation_test.go b/session/isolation_test.go index ec8aa6a7fa9ae..eafeee4ca0f97 100644 --- a/session/isolation_test.go +++ b/session/isolation_test.go @@ -15,22 +15,26 @@ package session_test import ( - . "github.com/pingcap/check" + "testing" + + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" ) -type testIsolationSuite struct { - testSessionSuiteBase -} - /* These test cases come from the paper . The sign 'P0', 'P1'.... can be found in the paper. These cases will run under snapshot isolation. */ -func (s *testIsolationSuite) TestP0DirtyWrite(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP0DirtyWrite(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") @@ -42,7 +46,7 @@ func (s *testIsolationSuite) TestP0DirtyWrite(c *C) { session2.MustExec("update x set c = c+1 where id = 1;") session1.MustExec("commit;") _, err := session2.Exec("commit;") - c.Assert(err, NotNil) + require.Error(t, err) session1.MustExec("set tidb_txn_mode = 'pessimistic'") session2.MustExec("set tidb_txn_mode = 'pessimistic'") @@ -81,9 +85,15 @@ func (s *testIsolationSuite) TestP0DirtyWrite(c *C) { session2.MustQuery("select * from x").Check(testkit.Rows("1 3")) } -func (s *testIsolationSuite) TestP1DirtyRead(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP1DirtyRead(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") @@ -125,9 +135,15 @@ func (s *testIsolationSuite) TestP1DirtyRead(c *C) { session2.MustExec("commit;") } -func (s *testIsolationSuite) TestP2NonRepeatableRead(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP2NonRepeatableRead(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("drop table if exists y;") @@ -190,9 +206,15 @@ func (s *testIsolationSuite) TestP2NonRepeatableRead(c *C) { session1.MustExec("commit;") } -func (s *testIsolationSuite) TestP3Phantom(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP3Phantom(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("drop table if exists z;") @@ -252,9 +274,15 @@ func (s *testIsolationSuite) TestP3Phantom(c *C) { session1.MustExec("commit;") } -func (s *testIsolationSuite) TestP4LostUpdate(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP4LostUpdate(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") @@ -268,7 +296,7 @@ func (s *testIsolationSuite) TestP4LostUpdate(c *C) { session2.MustExec("commit;") session1.MustExec("update x set c = c+1 where id = 1;") _, err := session1.Exec("commit;") - c.Assert(err, NotNil) + require.Error(t, err) session1.MustExec("set tidb_txn_mode = 'pessimistic'") session2.MustExec("set tidb_txn_mode = 'pessimistic'") @@ -305,11 +333,17 @@ func (s *testIsolationSuite) TestP4LostUpdate(c *C) { } // cursor is not supported -func (s *testIsolationSuite) TestP4CLostUpdate(c *C) {} - -func (s *testIsolationSuite) TestA3Phantom(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestP4CLostUpdate(t *testing.T) {} + +func TestA3Phantom(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") @@ -354,9 +388,15 @@ func (s *testIsolationSuite) TestA3Phantom(c *C) { session2.MustExec("commit;") } -func (s *testIsolationSuite) TestA5AReadSkew(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestA5AReadSkew(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("drop table if exists y;") @@ -413,9 +453,15 @@ func (s *testIsolationSuite) TestA5AReadSkew(c *C) { session1.MustExec("commit;") } -func (s *testIsolationSuite) TestA5BWriteSkew(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestA5BWriteSkew(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("drop table if exists y;") @@ -504,9 +550,15 @@ func (s *testIsolationSuite) TestA5BWriteSkew(c *C) { These test cases come from the paper for tidb, we support read-after-write on cluster level. */ -func (s *testIsolationSuite) TestReadAfterWrite(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestReadAfterWrite(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") @@ -551,9 +603,15 @@ func (s *testIsolationSuite) TestReadAfterWrite(c *C) { /* This case will do harm in Innodb, even if in snapshot isolation, but harmless in tidb. */ -func (s *testIsolationSuite) TestPhantomReadInInnodb(c *C) { - session1 := testkit.NewTestKitWithInit(c, s.store) - session2 := testkit.NewTestKitWithInit(c, s.store) +func TestPhantomReadInInnodb(t *testing.T) { + store, clean := createStorage(t) + defer clean() + session1 := testkit.NewTestKit(t, store) + session2 := testkit.NewTestKit(t, store) + session1.MustExec("use test;") + session2.MustExec("use test;") + session1.MustExec("set tidb_txn_mode = 'optimistic'") + session2.MustExec("set tidb_txn_mode = 'optimistic'") session1.MustExec("drop table if exists x;") session1.MustExec("create table x (id int primary key, c int);") diff --git a/session/main_test.go b/session/main_test.go index ee79b1b30e967..5acc2d4bf2de0 100644 --- a/session/main_test.go +++ b/session/main_test.go @@ -42,7 +42,7 @@ var testDataMap = make(testdata.BookKeeper, 1) func TestMain(m *testing.M) { testmain.ShortCircuitForBench(m) - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() flag.Parse() testDataMap.LoadTestSuiteData("testdata", "clustered_index_suite") @@ -55,8 +55,10 @@ func TestMain(m *testing.M) { tikv.EnableFailpoints() opts := []goleak.Option{ // TODO: figure the reason and shorten this list + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("github.com/tikv/client-go/v2/internal/retry.newBackoffFn.func1"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/v3.waitRetryBackoff"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), goleak.IgnoreTopFunction("google.golang.org/grpc.(*addrConn).resetTransport"), goleak.IgnoreTopFunction("google.golang.org/grpc.(*ccBalancerWrapper).watcher"), diff --git a/session/pessimistic_test.go b/session/pessimistic_test.go index 563433769b6a5..bda96b4878031 100644 --- a/session/pessimistic_test.go +++ b/session/pessimistic_test.go @@ -44,7 +44,6 @@ import ( "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/deadlockhistory" "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testutil" ) var _ = SerialSuites(&testPessimisticSuite{}) @@ -61,14 +60,20 @@ func (s *testPessimisticSuite) new1PCTestKitWithInit(c *C) *testkit.TestKit { return tk } +type lockTTL uint64 + +func setLockTTL(v uint64) lockTTL { return lockTTL(atomic.SwapUint64(&transaction.ManagedLockTTL, v)) } + +func (v lockTTL) restore() { atomic.StoreUint64(&transaction.ManagedLockTTL, uint64(v)) } + type testPessimisticSuite struct { testSessionSuiteBase } func (s *testPessimisticSuite) SetUpSuite(c *C) { s.testSessionSuiteBase.SetUpSuite(c) - // Set it to 300ms for testing lock resolve. - atomic.StoreUint64(&transaction.ManagedLockTTL, 300) + // Set it to 5s for testing lock resolve. + atomic.StoreUint64(&transaction.ManagedLockTTL, 5000) transaction.PrewriteMaxBackoff = 500 } @@ -205,6 +210,8 @@ func (s *testPessimisticSuite) TestDeadlock(c *C) { syncCh <- nil _, err := tk2.Exec("update deadlock set v = v + 1 where k = 1") syncCh <- err + + tk2.MustExec("rollback") }() <-syncCh _, err1 := tk1.Exec("update deadlock set v = v + 1 where k = 2") @@ -232,7 +239,7 @@ func (s *testPessimisticSuite) TestDeadlock(c *C) { expectedDeadlockInfo[0], expectedDeadlockInfo[1] = expectedDeadlockInfo[1], expectedDeadlockInfo[0] } res := tk1.MustQuery("select deadlock_id, try_lock_trx_id, trx_holding_lock, current_sql_digest, current_sql_digest_text from information_schema.deadlocks") - res.CheckAt([]int{1, 2, 3, 4}, testutil.RowsWithSep("/", expectedDeadlockInfo...)) + res.CheckAt([]int{1, 2, 3, 4}, testkit.RowsWithSep("/", expectedDeadlockInfo...)) c.Assert(res.Rows()[0][0], Equals, res.Rows()[1][0]) } @@ -250,10 +257,10 @@ func (s *testPessimisticSuite) TestSingleStatementRollback(c *C) { tableStart := tablecodec.GenTableRecordPrefix(tblID) s.cluster.SplitKeys(tableStart, tableStart.PrefixNext(), 2) region1Key := codec.EncodeBytes(nil, tablecodec.EncodeRowKeyWithHandle(tblID, kv.IntHandle(1))) - region1, _ := s.cluster.GetRegionByKey(region1Key) + region1, _, _ := s.cluster.GetRegionByKey(region1Key) region1ID := region1.Id region2Key := codec.EncodeBytes(nil, tablecodec.EncodeRowKeyWithHandle(tblID, kv.IntHandle(3))) - region2, _ := s.cluster.GetRegionByKey(region2Key) + region2, _, _ := s.cluster.GetRegionByKey(region2Key) region2ID := region2.Id syncCh := make(chan bool) @@ -435,11 +442,6 @@ func (s *testPessimisticSuite) TestLockUnchangedRowKey(c *C) { } func (s *testPessimisticSuite) TestOptimisticConflicts(c *C) { - // To avoid the resolve lock request arrives earlier before heartbeat request while lock expires. - atomic.StoreUint64(&transaction.ManagedLockTTL, 1000) - defer func() { - atomic.StoreUint64(&transaction.ManagedLockTTL, 300) - }() tk := testkit.NewTestKitWithInit(c, s.store) tk2 := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("drop table if exists conflict") @@ -601,10 +603,17 @@ func (s *testPessimisticSuite) TestAsyncRollBackNoWait(c *C) { tk.MustExec("commit") // This statement success for now, but its lock will be rollbacked later by the // lingering rollback request, as forUpdateTS doesn't change. - tk2.MustQuery("select * from tk where c1 > 0 for update nowait") + tk2.MustQuery("select * from tk where c1 > 0 for update nowait").Check(testkit.Rows("1 1", "2 2", "3 3", "4 4", "5 17")) tk2.MustQuery("select * from tk where c1 = 5 for update nowait").Check(testkit.Rows("5 17")) tk3.MustExec("begin pessimistic") + // TODO: @coocood skip the following test in https://github.com/pingcap/tidb/pull/13553/ + // Remove this code block and figure out why it's skipped. + // ---------------------- + tk2.MustExec("rollback") + tk3.MustExec("rollback") + // ---------------------- + c.Skip("tk3 is blocking because tk2 didn't rollback itself") // tk3 succ because tk2 rollback itself. tk3.MustExec("update tk set c2 = 1 where c1 = 5") @@ -650,6 +659,7 @@ func (s *testPessimisticSuite) TestWaitLockKill(c *C) { func (s *testPessimisticSuite) TestKillStopTTLManager(c *C) { // Test killing an idle pessimistic session stop its ttlManager. + defer setLockTTL(300).restore() tk := testkit.NewTestKitWithInit(c, s.store) tk2 := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("drop table if exists test_kill") @@ -664,6 +674,10 @@ func (s *testPessimisticSuite) TestKillStopTTLManager(c *C) { // This query should success rather than returning a ResolveLock error. tk2.MustExec("update test_kill set c = c + 1 where id = 1") + succ = atomic.CompareAndSwapUint32(&sessVars.Killed, 1, 0) + c.Assert(succ, IsTrue) + tk.MustExec("rollback") + tk2.MustExec("rollback") } func (s *testPessimisticSuite) TestConcurrentInsert(c *C) { @@ -706,11 +720,6 @@ func (s *testPessimisticSuite) TestConcurrentInsert(c *C) { } func (s *testPessimisticSuite) TestInnodbLockWaitTimeout(c *C) { - // Increasing the ManagedLockTTL so that the lock may not be resolved testing with TiKV. - atomic.StoreUint64(&transaction.ManagedLockTTL, 5000) - defer func() { - atomic.StoreUint64(&transaction.ManagedLockTTL, 300) - }() tk := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("drop table if exists tk") tk.MustExec("create table tk (c1 int primary key, c2 int)") @@ -723,6 +732,10 @@ func (s *testPessimisticSuite) TestInnodbLockWaitTimeout(c *C) { tk2.MustQuery(`show variables like "innodb_lock_wait_timeout"`).Check(testkit.Rows("innodb_lock_wait_timeout 3")) tk2.MustExec("set innodb_lock_wait_timeout = 2") tk2.MustQuery(`show variables like "innodb_lock_wait_timeout"`).Check(testkit.Rows("innodb_lock_wait_timeout 2")) + // to check whether it will set to innodb_lock_wait_timeout to max value + tk2.MustExec("set innodb_lock_wait_timeout = 3602") + tk2.MustQuery(`show variables like "innodb_lock_wait_timeout"`).Check(testkit.Rows("innodb_lock_wait_timeout 3600")) + tk2.MustExec("set innodb_lock_wait_timeout = 2") tk3 := testkit.NewTestKitWithInit(c, s.store) tk3.MustQuery(`show variables like "innodb_lock_wait_timeout"`).Check(testkit.Rows("innodb_lock_wait_timeout 3")) @@ -835,11 +848,6 @@ func (s *testPessimisticSuite) TestPushConditionCheckForPessimisticTxn(c *C) { } func (s *testPessimisticSuite) TestInnodbLockWaitTimeoutWaitStart(c *C) { - // Increasing the ManagedLockTTL so that the lock may not be resolved testing with TiKV. - atomic.StoreUint64(&transaction.ManagedLockTTL, 5000) - defer func() { - atomic.StoreUint64(&transaction.ManagedLockTTL, 300) - }() // prepare work tk := testkit.NewTestKitWithInit(c, s.store) defer tk.MustExec("drop table if exists tk") @@ -1164,11 +1172,11 @@ func (s *testPessimisticSuite) TestPessimisticLockNonExistsKey(c *C) { tk1.MustExec("begin pessimistic") err := tk1.ExecToErr("select * from t where k = 2 for update nowait") - c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue) + c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue, Commentf("got %v", err)) err = tk1.ExecToErr("select * from t where k = 4 for update nowait") - c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue) + c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue, Commentf("got %v", err)) err = tk1.ExecToErr("select * from t where k = 7 for update nowait") - c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue) + c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue, Commentf("got %v", err)) tk.MustExec("rollback") tk1.MustExec("rollback") @@ -1180,17 +1188,15 @@ func (s *testPessimisticSuite) TestPessimisticLockNonExistsKey(c *C) { tk1.MustExec("begin pessimistic") err = tk1.ExecToErr("select * from t where k = 2 for update nowait") - c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue) + c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue, Commentf("got %v", err)) err = tk1.ExecToErr("select * from t where k = 6 for update nowait") - c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue) + c.Check(storeerr.ErrLockAcquireFailAndNoWaitSet.Equal(err), IsTrue, Commentf("got %v", err)) tk.MustExec("rollback") tk1.MustExec("rollback") } func (s *testPessimisticSuite) TestPessimisticCommitReadLock(c *C) { - // set lock ttl to 3s, tk1 lock wait timeout is 2s - atomic.StoreUint64(&transaction.ManagedLockTTL, 3000) - defer atomic.StoreUint64(&transaction.ManagedLockTTL, 300) + // tk1 lock wait timeout is 2s tk := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("use test") tk1 := testkit.NewTestKitWithInit(c, s.store) @@ -1294,8 +1300,6 @@ func (s *testPessimisticSuite) TestNonAutoCommitWithPessimisticMode(c *C) { } func (s *testPessimisticSuite) TestBatchPointGetLockIndex(c *C) { - atomic.StoreUint64(&transaction.ManagedLockTTL, 3000) - defer atomic.StoreUint64(&transaction.ManagedLockTTL, 300) tk := testkit.NewTestKitWithInit(c, s.store) tk2 := testkit.NewTestKitWithInit(c, s.store) tk2.MustExec("use test") @@ -1442,8 +1446,6 @@ func (s *testPessimisticSuite) TestRCIndexMerge(c *C) { } func (s *testPessimisticSuite) TestGenerateColPointGet(c *C) { - atomic.StoreUint64(&transaction.ManagedLockTTL, 3000) - defer atomic.StoreUint64(&transaction.ManagedLockTTL, 300) tk := testkit.NewTestKitWithInit(c, s.store) defer func() { tk.MustExec(fmt.Sprintf("set global tidb_row_format_version = %d", variable.DefTiDBRowFormatV2)) @@ -1516,6 +1518,7 @@ func (s *testPessimisticSuite) TestTxnWithExpiredPessimisticLocks(c *C) { func (s *testPessimisticSuite) TestKillWaitLockTxn(c *C) { // Test kill command works on waiting pessimistic lock. + defer setLockTTL(300).restore() tk := testkit.NewTestKitWithInit(c, s.store) tk2 := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("drop table if exists test_kill") @@ -2360,7 +2363,7 @@ func (s *testPessimisticSuite) TestIssue21498(c *C) { tk.MustExec("set tidb_enable_amend_pessimistic_txn = 1") for _, partition := range []bool{false, true} { - //RC test + // RC test tk.MustExec("drop table if exists t, t1") createTable := "create table t (id int primary key, v int, index iv (v))" if partition { @@ -2465,6 +2468,7 @@ func (s *testPessimisticSuite) TestIssue21498(c *C) { tk.MustQuery("select * from t s, t t1 where s.v = 23 and s.id = t1.id").Check(testkit.Rows("2 23 200 2 23 200")) tk.MustQuery("select * from t s, t t1 where s.v = 24 and s.id = t1.id").Check(testkit.Rows()) tk.MustQuery("select * from t s, t t1 where s.v = 23 and s.id = t1.id for update").Check(testkit.Rows()) + // TODO: Do the same with Partitioned Table!!! Since this query leads to two columns in SelectLocExec.tblID2Handle!!! tk.MustQuery("select * from t s, t t1 where s.v = 24 and s.id = t1.id for update").Check(testkit.Rows("2 24 200 2 24 200")) tk.MustExec("delete from t where v = 24") tk.CheckExecResult(1, 0) @@ -2529,7 +2533,7 @@ func (s *testPessimisticSuite) TestPlanCacheSchemaChange(c *C) { tk.MustExec("set tidb_enable_amend_pessimistic_txn = 1") tk2.MustExec("set tidb_enable_amend_pessimistic_txn = 1") - //generate plan cache + // generate plan cache tk.MustExec("prepare update_stmt from 'update t set vv = vv + 1 where v = ?'") tk.MustExec("set @v = 1") tk.MustExec("execute update_stmt using @v") @@ -2571,10 +2575,6 @@ func (s *testPessimisticSuite) TestPlanCacheSchemaChange(c *C) { } func (s *testPessimisticSuite) TestAsyncCommitCalTSFail(c *C) { - atomic.StoreUint64(&transaction.ManagedLockTTL, 5000) - defer func() { - atomic.StoreUint64(&transaction.ManagedLockTTL, 300) - }() defer config.RestoreFunc()() config.UpdateGlobal(func(conf *config.Config) { conf.TiKVClient.AsyncCommit.SafeWindow = time.Second @@ -2840,3 +2840,29 @@ func (s *testPessimisticSuite) TestAmendForColumnChange(c *C) { tk2.MustExec("drop database test_db") } + +func (s *testPessimisticSuite) TestPessimisticAutoCommitTxn(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + tk.MustExec("set tidb_txn_mode = 'pessimistic'") + tk.MustExec("drop database if exists test_db") + tk.MustExec("create database test_db") + tk.MustExec("use test_db") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (i int)") + tk.MustExec("insert into t values (1)") + tk.MustExec("set autocommit = on") + + rows := tk.MustQuery("explain update t set i = -i").Rows() + explain := fmt.Sprintf("%v", rows[1]) + c.Assert(explain, Not(Matches), ".*SelectLock.*") + + originCfg := config.GetGlobalConfig() + defer config.StoreGlobalConfig(originCfg) + newCfg := *originCfg + newCfg.PessimisticTxn.PessimisticAutoCommit.Store(true) + config.StoreGlobalConfig(&newCfg) + + rows = tk.MustQuery("explain update t set i = -i").Rows() + explain = fmt.Sprintf("%v", rows[1]) + c.Assert(explain, Matches, ".*SelectLock.*") +} diff --git a/session/schema_amender.go b/session/schema_amender.go index 8993190d2fef5..2cfc0db358aae 100644 --- a/session/schema_amender.go +++ b/session/schema_amender.go @@ -23,7 +23,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" @@ -172,7 +171,7 @@ func colChangeAmendable(colAtStart *model.ColumnInfo, colAtCommit *model.ColumnI if colAtStart.Charset != colAtCommit.Charset || colAtStart.Collate != colAtCommit.Collate { return errors.Trace(errors.Errorf("charset or collate is not matched for column=%v", colAtCommit.Name.String())) } - _, err := ddl.CheckModifyTypeCompatible(&colAtStart.FieldType, &colAtCommit.FieldType) + _, err := types.CheckModifyTypeCompatible(&colAtStart.FieldType, &colAtCommit.FieldType) if err != nil { return errors.Trace(err) } @@ -393,7 +392,8 @@ func (a *amendOperationAddIndex) genMutations(ctx context.Context, sctx sessionc for i := 0; i < len(deletedMutations.GetKeys()); i++ { key := deletedMutations.GetKeys()[i] if _, ok := a.insertedNewIndexKeys[string(key)]; !ok { - resAddMutations.Push(deletedMutations.GetOps()[i], key, deletedMutations.GetValues()[i], deletedMutations.GetPessimisticFlags()[i]) + resAddMutations.Push(deletedMutations.GetOps()[i], key, deletedMutations.GetValues()[i], deletedMutations.IsPessimisticLock(i), + deletedMutations.IsAssertExists(i), deletedMutations.IsAssertNotExist(i)) } } for i := 0; i < len(insertedMutations.GetKeys()); i++ { @@ -402,7 +402,8 @@ func (a *amendOperationAddIndex) genMutations(ctx context.Context, sctx sessionc if _, ok := a.deletedOldIndexKeys[string(key)]; ok { destKeyOp = kvrpcpb.Op_Put } - resAddMutations.Push(destKeyOp, key, insertedMutations.GetValues()[i], insertedMutations.GetPessimisticFlags()[i]) + resAddMutations.Push(destKeyOp, key, insertedMutations.GetValues()[i], insertedMutations.IsPessimisticLock(i), + insertedMutations.IsAssertExists(i), insertedMutations.IsAssertNotExist(i)) } } else { resAddMutations.MergeMutations(deletedMutations) @@ -492,7 +493,11 @@ func (a *amendOperationAddIndex) genNewIdxKey(ctx context.Context, sctx sessionc isPessimisticLock = true } a.insertedNewIndexKeys[string(newIdxKey)] = struct{}{} - newMutation := &transaction.PlainMutation{KeyOp: newIndexOp, Key: newIdxKey, Value: newIdxValue, IsPessimisticLock: isPessimisticLock} + var flags transaction.CommitterMutationFlags + if isPessimisticLock { + flags |= transaction.MutationFlagIsPessimisticLock + } + newMutation := &transaction.PlainMutation{KeyOp: newIndexOp, Key: newIdxKey, Value: newIdxValue, Flags: flags} return newMutation, nil } @@ -519,7 +524,11 @@ func (a *amendOperationAddIndex) genOldIdxKey(ctx context.Context, sctx sessionc isPessimisticLock = true } a.deletedOldIndexKeys[string(newIdxKey)] = struct{}{} - return &transaction.PlainMutation{KeyOp: kvrpcpb.Op_Del, Key: newIdxKey, Value: emptyVal, IsPessimisticLock: isPessimisticLock}, nil + var flags transaction.CommitterMutationFlags + if isPessimisticLock { + flags |= transaction.MutationFlagIsPessimisticLock + } + return &transaction.PlainMutation{KeyOp: kvrpcpb.Op_Del, Key: newIdxKey, Value: emptyVal, Flags: flags}, nil } return nil, nil } diff --git a/session/schema_amender_serial_test.go b/session/schema_amender_test.go similarity index 96% rename from session/schema_amender_serial_test.go rename to session/schema_amender_test.go index a22f21ad6e225..514c82bd411f1 100644 --- a/session/schema_amender_serial_test.go +++ b/session/schema_amender_test.go @@ -66,7 +66,7 @@ func mutationsEqual(res *transaction.PlainMutations, expected *transaction.Plain } require.GreaterOrEqual(t, foundIdx, 0) require.Equal(t, expected.GetOps()[foundIdx], res.GetOps()[i]) - require.Equal(t, expected.GetPessimisticFlags()[foundIdx], res.GetPessimisticFlags()[i]) + require.Equal(t, expected.IsPessimisticLock(foundIdx), res.IsPessimisticLock(i)) require.Equal(t, expected.GetKeys()[foundIdx], res.GetKeys()[i]) require.Equal(t, expected.GetValues()[foundIdx], res.GetValues()[i]) } @@ -140,7 +140,7 @@ func prepareTestData( oldData.ops = append(oldData.ops, keyOp) oldData.rowValue = append(oldData.rowValue, thisRowValue) if keyOp == kvrpcpb.Op_Del { - mutations.Push(keyOp, rowKey, []byte{}, true) + mutations.Push(keyOp, rowKey, []byte{}, true, false, false) } } oldRowValues[i] = thisRowValue @@ -168,9 +168,9 @@ func prepareTestData( } require.NoError(t, err) if keyOp == kvrpcpb.Op_Put || keyOp == kvrpcpb.Op_Insert { - mutations.Push(keyOp, rowKey, rowValue, true) + mutations.Push(keyOp, rowKey, rowValue, true, false, false) } else if keyOp == kvrpcpb.Op_Lock { - mutations.Push(keyOp, rowKey, []byte{}, true) + mutations.Push(keyOp, rowKey, []byte{}, true, false, false) } newRowValues[i] = thisRowValue newRowKvMap[string(rowKey)] = thisRowValue @@ -209,7 +209,7 @@ func prepareTestData( if info.indexInfoAtCommit.Meta().Unique { isPessimisticLock = true } - oldIdxKeyMutation.Push(kvrpcpb.Op_Del, idxKey, []byte{}, isPessimisticLock) + oldIdxKeyMutation.Push(kvrpcpb.Op_Del, idxKey, []byte{}, isPessimisticLock, false, false) } } if addIndexNeedAddOp(info.AmendOpType) && mayGenPutIndexRowKeyOp(keyOp) { @@ -221,7 +221,7 @@ func prepareTestData( mutOp = kvrpcpb.Op_Insert isPessimisticLock = true } - newIdxKeyMutation.Push(mutOp, idxKey, idxVal, isPessimisticLock) + newIdxKeyMutation.Push(mutOp, idxKey, idxVal, isPessimisticLock, false, false) } skipMerge := false if info.AmendOpType == AmendNeedAddDeleteAndInsert { @@ -436,7 +436,7 @@ func TestAmendCollectAndGenMutations(t *testing.T) { idxKey := tablecodec.EncodeIndexSeekKey(oldTbInfo.Meta().ID, oldTbInfo.Indices()[i].Meta().ID, idxValue) err = txn.Set(idxKey, idxValue) require.NoError(t, err) - mutations.Push(kvrpcpb.Op_Put, idxKey, idxValue, false) + mutations.Push(kvrpcpb.Op_Put, idxKey, idxValue, false, false, false) } res, err := schemaAmender.genAllAmendMutations(ctx, &mutations, collector) @@ -446,13 +446,13 @@ func TestAmendCollectAndGenMutations(t *testing.T) { // Validate generated results. require.Equal(t, len(res.GetOps()), len(res.GetKeys())) require.Equal(t, len(res.GetOps()), len(res.GetValues())) - require.Equal(t, len(res.GetOps()), len(res.GetPessimisticFlags())) + require.Equal(t, len(res.GetOps()), len(res.GetFlags())) for i := 0; i < len(expectedMutations.GetKeys()); i++ { logutil.BgLogger().Info("[TEST] expected mutations", zap.Stringer("key", kv.Key(expectedMutations.GetKeys()[i])), zap.Stringer("val", kv.Key(expectedMutations.GetKeys()[i])), zap.Stringer("op_type", expectedMutations.GetOps()[i]), - zap.Bool("is_pessimistic", expectedMutations.GetPessimisticFlags()[i]), + zap.Bool("is_pessimistic", expectedMutations.IsPessimisticLock(i)), ) } for i := 0; i < len(res.GetKeys()); i++ { @@ -460,7 +460,7 @@ func TestAmendCollectAndGenMutations(t *testing.T) { zap.Stringer("key", kv.Key(res.GetKeys()[i])), zap.Stringer("val", kv.Key(res.GetKeys()[i])), zap.Stringer("op_type", res.GetOps()[i]), - zap.Bool("is_pessimistic", res.GetPessimisticFlags()[i]), + zap.Bool("is_pessimistic", res.IsPessimisticLock(i)), ) } mutationsEqual(res, &expectedMutations, t) diff --git a/session/session.go b/session/session.go index c57628d090f44..61dcad4720985 100644 --- a/session/session.go +++ b/session/session.go @@ -22,7 +22,9 @@ import ( "bytes" "context" "crypto/tls" + "encoding/hex" "encoding/json" + stderrs "errors" "fmt" "runtime/pprof" "runtime/trace" @@ -37,6 +39,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/auth" @@ -44,15 +47,22 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/sessiontxn/staleread" + "github.com/pingcap/tidb/store/driver/txn" + "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/temptable" + "github.com/pingcap/tidb/util/logutil/consistency" "github.com/pingcap/tidb/util/topsql" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/pingcap/tidb/util/topsql/stmtstats" "github.com/pingcap/tipb/go-binlog" + tikverr "github.com/tikv/client-go/v2/error" "go.uber.org/zap" "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/ddl/placement" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/errno" @@ -148,11 +158,10 @@ type Session interface { AuthWithoutVerification(user *auth.UserIdentity) bool AuthPluginForUser(user *auth.UserIdentity) (string, error) MatchIdentity(username, remoteHost string) (*auth.UserIdentity, error) - ShowProcess() *util.ProcessInfo // Return the information of the txn current running TxnInfo() *txninfo.TxnInfo // PrepareTxnCtx is exported for test. - PrepareTxnCtx(context.Context) + PrepareTxnCtx(context.Context) error // FieldList returns fields list of a table. FieldList(tableName string) (fields []*ast.ResultField, err error) SetPort(port string) @@ -225,9 +234,19 @@ type session struct { cache [1]ast.StmtNode - builtinFunctionUsage telemetry.BuiltinFunctionsUsage + functionUsageMu struct { + sync.RWMutex + builtinFunctionUsage telemetry.BuiltinFunctionsUsage + } // allowed when tikv disk full happened. diskFullOpt kvrpcpb.DiskFullOpt + + // StmtStats is used to count various indicators of each SQL in this session + // at each point in time. These data will be periodically taken away by the + // background goroutine. The background goroutine will continue to aggregate + // all the local data in each session, and finally report them to the remote + // regularly. + stmtStats *stmtstats.StatementStats } var parserPool = &sync.Pool{New: func() interface{} { return parser.New() }} @@ -304,24 +323,32 @@ func (s *session) cleanRetryInfo() { planCacheEnabled := plannercore.PreparedPlanCacheEnabled() var cacheKey kvcache.Key + var err error var preparedAst *ast.Prepared + var stmtText, stmtDB string if planCacheEnabled { firstStmtID := retryInfo.DroppedPreparedStmtIDs[0] if preparedPointer, ok := s.sessionVars.PreparedStmts[firstStmtID]; ok { preparedObj, ok := preparedPointer.(*plannercore.CachedPrepareStmt) if ok { preparedAst = preparedObj.PreparedAst - bindSQL := planner.GetBindSQL4PlanCache(s, preparedAst.Stmt) - cacheKey = plannercore.NewPSTMTPlanCacheKey(s.sessionVars, firstStmtID, preparedAst.SchemaVersion, bindSQL) + stmtText, stmtDB = preparedObj.StmtText, preparedObj.StmtDB + cacheKey, err = plannercore.NewPlanCacheKey(s.sessionVars, stmtText, stmtDB, preparedAst.SchemaVersion) + if err != nil { + logutil.Logger(s.currentCtx).Warn("clean cached plan failed", zap.Error(err)) + return + } } } } for i, stmtID := range retryInfo.DroppedPreparedStmtIDs { if planCacheEnabled { if i > 0 && preparedAst != nil { - plannercore.SetPstmtIDSchemaVersion(cacheKey, stmtID, preparedAst.SchemaVersion, s.sessionVars.IsolationReadEngines) + plannercore.SetPstmtIDSchemaVersion(cacheKey, stmtText, preparedAst.SchemaVersion, s.sessionVars.IsolationReadEngines) + } + if !s.sessionVars.IgnorePreparedCacheCloseStmt { // keep the plan in cache + s.PreparedPlanCache().Delete(cacheKey) } - s.PreparedPlanCache().Delete(cacheKey) } s.sessionVars.RemovePreparedStmt(stmtID) } @@ -412,6 +439,18 @@ func (s *session) StoreQueryFeedback(feedback interface{}) { } } +func (s *session) UpdateColStatsUsage(predicateColumns []model.TableColumnID) { + if s.statsCollector == nil { + return + } + t := time.Now() + colMap := make(map[model.TableColumnID]time.Time, len(predicateColumns)) + for _, col := range predicateColumns { + colMap[col] = t + } + s.statsCollector.UpdateColStatsUsage(colMap) +} + // StoreIndexUsage stores index usage information in idxUsageCollector. func (s *session) StoreIndexUsage(tblID int64, idxID int64, rowsSelected int64) { if s.idxUsageCollector == nil { @@ -548,6 +587,10 @@ func (s *session) doCommit(ctx context.Context) error { s.txn.SetOption(kv.EnableAsyncCommit, sessVars.EnableAsyncCommit) s.txn.SetOption(kv.Enable1PC, sessVars.Enable1PC) s.txn.SetOption(kv.ResourceGroupTagger, sessVars.StmtCtx.GetResourceGroupTagger()) + if sessVars.StmtCtx.KvExecCounter != nil { + // Bind an interceptor for client-go to count the number of SQL executions of each TiKV. + s.txn.SetOption(kv.RPCInterceptor, sessVars.StmtCtx.KvExecCounter.RPCInterceptor()) + } // priority of the sysvar is lower than `start transaction with causal consistency only` if val := s.txn.GetOption(kv.GuaranteeLinearizability); val == nil || val.(bool) { // We needn't ask the TiKV client to guarantee linearizability for auto-commit transactions @@ -573,7 +616,11 @@ func (s *session) doCommit(ctx context.Context) error { s.txn.SetOption(kv.CommitTSUpperBoundCheck, c.commitTSCheck) } - return s.commitTxnWithTemporaryData(tikvutil.SetSessionID(ctx, sessVars.ConnectionID), &s.txn) + err = s.commitTxnWithTemporaryData(tikvutil.SetSessionID(ctx, sessVars.ConnectionID), &s.txn) + if err != nil { + err = s.handleAssertionFailure(ctx, err) + } + return err } type cachedTableRenewLease struct { @@ -585,10 +632,11 @@ type cachedTableRenewLease struct { func (c *cachedTableRenewLease) start(ctx context.Context) error { c.exit = make(chan struct{}) c.lease = make([]uint64, len(c.tables)) - wg := make(chan error) + wg := make(chan error, len(c.tables)) ith := 0 - for tid, raw := range c.tables { - go c.keepAlive(ctx, wg, raw.(tables.StateRemote), tid, &c.lease[ith]) + for _, raw := range c.tables { + tbl := raw.(table.CachedTable) + go tbl.WriteLockAndKeepAlive(ctx, c.exit, &c.lease[ith], wg) ith++ } @@ -603,47 +651,6 @@ func (c *cachedTableRenewLease) start(ctx context.Context) error { return err } -const cacheTableWriteLease = 5 * time.Second - -func (c *cachedTableRenewLease) keepAlive(ctx context.Context, wg chan error, handle tables.StateRemote, tid int64, leasePtr *uint64) { - writeLockLease, err := handle.LockForWrite(ctx, tid) - atomic.StoreUint64(leasePtr, writeLockLease) - wg <- err - if err != nil { - logutil.Logger(ctx).Warn("[cached table] lock for write lock fail", zap.Error(err)) - return - } - - t := time.NewTicker(cacheTableWriteLease) - defer t.Stop() - for { - select { - case <-t.C: - if err := c.renew(ctx, handle, tid, leasePtr); err != nil { - logutil.Logger(ctx).Warn("[cached table] renew write lock lease fail", zap.Error(err)) - return - } - case <-c.exit: - return - } - } -} - -func (c *cachedTableRenewLease) renew(ctx context.Context, handle tables.StateRemote, tid int64, leasePtr *uint64) error { - oldLease := atomic.LoadUint64(leasePtr) - physicalTime := oracle.GetTimeFromTS(oldLease) - newLease := oracle.GoTimeToTS(physicalTime.Add(cacheTableWriteLease)) - - succ, err := handle.RenewLease(ctx, tid, newLease, tables.RenewWriteLease) - if err != nil { - return errors.Trace(err) - } - if succ { - atomic.StoreUint64(leasePtr, newLease) - } - return nil -} - func (c *cachedTableRenewLease) stop(ctx context.Context) { close(c.exit) } @@ -659,6 +666,62 @@ func (c *cachedTableRenewLease) commitTSCheck(commitTS uint64) bool { return true } +// handleAssertionFailure extracts the possible underlying assertionFailed error, +// gets the corresponding MVCC history and logs it. +// If it's not an assertion failure, returns the original error. +func (s *session) handleAssertionFailure(ctx context.Context, err error) error { + var assertionFailure *tikverr.ErrAssertionFailed + if !stderrs.As(err, &assertionFailure) { + return err + } + key := assertionFailure.Key + newErr := kv.ErrAssertionFailed.GenWithStackByArgs( + hex.EncodeToString(key), assertionFailure.Assertion.String(), assertionFailure.StartTs, + assertionFailure.ExistingStartTs, assertionFailure.ExistingCommitTs, + ) + + if s.GetSessionVars().EnableRedactLog { + return newErr + } + + var decodeFunc func(kv.Key, *kvrpcpb.MvccGetByKeyResponse, map[string]interface{}) + // if it's a record key or an index key, decode it + if infoSchema, ok := s.sessionVars.TxnCtx.InfoSchema.(infoschema.InfoSchema); ok && + infoSchema != nil && (tablecodec.IsRecordKey(key) || tablecodec.IsIndexKey(key)) { + tableID := tablecodec.DecodeTableID(key) + if table, ok := infoSchema.TableByID(tableID); ok { + if tablecodec.IsRecordKey(key) { + decodeFunc = consistency.DecodeRowMvccData(table.Meta()) + } else { + tableInfo := table.Meta() + _, indexID, _, e := tablecodec.DecodeIndexKey(key) + if e != nil { + logutil.Logger(ctx).Error("assertion failed but cannot decode index key", zap.Error(e)) + return err + } + var indexInfo *model.IndexInfo + for _, idx := range tableInfo.Indices { + if idx.ID == indexID { + indexInfo = idx + break + } + } + if indexInfo == nil { + return err + } + decodeFunc = consistency.DecodeIndexMvccData(indexInfo) + } + } else { + logutil.Logger(ctx).Warn("assertion failed but table not found in infoschema", zap.Int64("tableID", tableID)) + } + } + if store, ok := s.store.(helper.Storage); ok { + content := consistency.GetMvccByKey(store, key, decodeFunc) + logutil.Logger(ctx).Error("assertion failed", zap.String("message", newErr.Error()), zap.String("mvcc history", content)) + } + return newErr +} + func (s *session) commitTxnWithTemporaryData(ctx context.Context, txn kv.Transaction) error { sessVars := s.sessionVars txnTempTables := sessVars.TxnCtx.TemporaryTables @@ -749,14 +812,15 @@ func (s *session) commitTxnWithTemporaryData(ctx context.Context, txn kv.Transac type temporaryTableKVFilter map[int64]tableutil.TempTable -func (m temporaryTableKVFilter) IsUnnecessaryKeyValue(key, value []byte, flags tikvstore.KeyFlags) bool { +func (m temporaryTableKVFilter) IsUnnecessaryKeyValue(key, value []byte, flags tikvstore.KeyFlags) (bool, error) { tid := tablecodec.DecodeTableID(key) if _, ok := m[tid]; ok { - return true + return true, nil } // This is the default filter for all tables. - return tablecodec.IsUntouchedIndexKValue(key, value) + defaultFilter := txn.TiDBKVFilter{} + return defaultFilter.IsUnnecessaryKeyValue(key, value, flags) } // errIsNoisy is used to filter DUPLCATE KEY errors. @@ -835,6 +899,11 @@ func (s *session) doCommitWithRetry(ctx context.Context) error { } return err } + s.updateStatsDeltaToCollector() + return nil +} + +func (s *session) updateStatsDeltaToCollector() { mapper := s.GetSessionVars().TxnCtx.TableDeltaMap if s.statsCollector != nil && mapper != nil { for _, item := range mapper { @@ -843,7 +912,6 @@ func (s *session) doCommitWithRetry(ctx context.Context) error { } } } - return nil } func (s *session) CommitTxn(ctx context.Context) error { @@ -991,7 +1059,9 @@ func (s *session) retry(ctx context.Context, maxCnt uint) (err error) { orgStartTS := sessVars.TxnCtx.StartTS label := s.GetSQLLabel() for { - s.PrepareTxnCtx(ctx) + if err = s.PrepareTxnCtx(ctx); err != nil { + return err + } s.sessionVars.RetryInfo.ResetOffset() for i, sr := range nh.history { st := sr.st @@ -1109,6 +1179,8 @@ func createSessionFunc(store kv.Storage) pools.Factory { } se.sessionVars.CommonGlobalLoaded = true se.sessionVars.InRestrictedSQL = true + // Internal session uses default format to prevent memory leak problem. + se.sessionVars.EnableChunkRPC = false return se, nil } } @@ -1129,6 +1201,8 @@ func createSessionWithDomainFunc(store kv.Storage) func(*domain.Domain) (pools.R } se.sessionVars.CommonGlobalLoaded = true se.sessionVars.InRestrictedSQL = true + // Internal session uses default format to prevent memory leak problem. + se.sessionVars.EnableChunkRPC = false return se, nil } } @@ -1153,11 +1227,7 @@ func drainRecordSet(ctx context.Context, se *session, rs sqlexec.RecordSet, allo // getTableValue executes restricted sql and the result is one column. // It returns a string value. func (s *session) getTableValue(ctx context.Context, tblName string, varName string) (string, error) { - stmt, err := s.ParseWithParams(ctx, "SELECT VARIABLE_VALUE FROM %n.%n WHERE VARIABLE_NAME=%?", mysql.SystemDB, tblName, varName) - if err != nil { - return "", err - } - rows, fields, err := s.ExecRestrictedStmt(ctx, stmt) + rows, fields, err := s.ExecRestrictedSQL(ctx, nil, "SELECT VARIABLE_VALUE FROM %n.%n WHERE VARIABLE_NAME=%?", mysql.SystemDB, tblName, varName) if err != nil { return "", err } @@ -1175,11 +1245,10 @@ func (s *session) getTableValue(ctx context.Context, tblName string, varName str // replaceGlobalVariablesTableValue executes restricted sql updates the variable value // It will then notify the etcd channel that the value has changed. func (s *session) replaceGlobalVariablesTableValue(ctx context.Context, varName, val string) error { - stmt, err := s.ParseWithParams(ctx, `REPLACE INTO %n.%n (variable_name, variable_value) VALUES (%?, %?)`, mysql.SystemDB, mysql.GlobalVariablesTable, varName, val) + _, _, err := s.ExecRestrictedSQL(ctx, nil, `REPLACE INTO %n.%n (variable_name, variable_value) VALUES (%?, %?)`, mysql.SystemDB, mysql.GlobalVariablesTable, varName, val) if err != nil { return err } - _, _, err = s.ExecRestrictedStmt(ctx, stmt) domain.GetDomain(s).NotifyUpdateSysVarCache() return err } @@ -1214,10 +1283,17 @@ func (s *session) GetGlobalSysVar(name string) (string, error) { } // It might have been written from an earlier TiDB version, so we should do type validation // See https://github.com/pingcap/tidb/issues/30255 for why we don't do full validation. - return sv.ValidateFromType(s.GetSessionVars(), sysVar, variable.ScopeGlobal) + // If validation fails, we should return the default value: + // See: https://github.com/pingcap/tidb/pull/31566 + sysVar, err = sv.ValidateFromType(s.GetSessionVars(), sysVar, variable.ScopeGlobal) + if err != nil { + return sv.Value, nil + } + return sysVar, nil } // SetGlobalSysVar implements GlobalVarAccessor.SetGlobalSysVar interface. +// it is called (but skipped) when setting instance scope func (s *session) SetGlobalSysVar(name, value string) (err error) { sv := variable.GetSysVar(name) if sv == nil { @@ -1229,6 +1305,9 @@ func (s *session) SetGlobalSysVar(name, value string) (err error) { if err = sv.SetGlobalFromHook(s.sessionVars, value, false); err != nil { return err } + if sv.HasInstanceScope() { // skip for INSTANCE scope + return nil + } if sv.GlobalConfigName != "" { domain.GetDomain(s).NotifyGlobalConfigChange(sv.GlobalConfigName, variable.OnOffToTrueFalse(value)) } @@ -1245,16 +1324,15 @@ func (s *session) SetGlobalSysVarOnly(name, value string) (err error) { if err = sv.SetGlobalFromHook(s.sessionVars, value, true); err != nil { return err } + if sv.HasInstanceScope() { // skip for INSTANCE scope + return nil + } return s.replaceGlobalVariablesTableValue(context.TODO(), sv.Name, value) } // SetTiDBTableValue implements GlobalVarAccessor.SetTiDBTableValue interface. func (s *session) SetTiDBTableValue(name, value, comment string) error { - stmt, err := s.ParseWithParams(context.TODO(), `REPLACE INTO mysql.tidb (variable_name, variable_value, comment) VALUES (%?, %?, %?)`, name, value, comment) - if err != nil { - return err - } - _, _, err = s.ExecRestrictedStmt(context.TODO(), stmt) + _, _, err := s.ExecRestrictedSQL(context.TODO(), nil, `REPLACE INTO mysql.tidb (variable_name, variable_value, comment) VALUES (%?, %?, %?)`, name, value, comment) return err } @@ -1369,7 +1447,7 @@ func (s *session) ExecuteInternal(ctx context.Context, sql string, args ...inter s.sessionVars.InRestrictedSQL = true defer func() { s.sessionVars.InRestrictedSQL = origin - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { // Restore the goroutine label by using the original ctx after execution is finished. pprof.SetGoroutineLabels(ctx) } @@ -1473,15 +1551,13 @@ func (s *session) ParseWithParams(ctx context.Context, sql string, args ...inter var stmts []ast.StmtNode var warns []error - var parseStartTime time.Time + parseStartTime := time.Now() if internal { // Do no respect the settings from clients, if it is for internal usage. // Charsets from clients may give chance injections. // Refer to https://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string/12118602. - parseStartTime = time.Now() stmts, warns, err = s.ParseSQL(ctx, sql) } else { - parseStartTime = time.Now() stmts, warns, err = s.ParseSQL(ctx, sql, s.sessionVars.GetParseParams()...) } if len(stmts) != 1 { @@ -1501,7 +1577,7 @@ func (s *session) ParseWithParams(ctx context.Context, sql string, args ...inter return nil, util.SyntaxError(err) } durParse := time.Since(parseStartTime) - if s.isInternal() { + if internal { sessionExecuteParseDurationInternal.Observe(durParse.Seconds()) } else { sessionExecuteParseDurationGeneral.Observe(durParse.Seconds()) @@ -1509,7 +1585,7 @@ func (s *session) ParseWithParams(ctx context.Context, sql string, args ...inter for _, warn := range warns { s.sessionVars.StmtCtx.AppendWarning(util.SyntaxWarn(warn)) } - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { normalized, digest := parser.NormalizeDigest(sql) if digest != nil { // Reset the goroutine label when internal sql execute finish. @@ -1520,45 +1596,111 @@ func (s *session) ParseWithParams(ctx context.Context, sql string, args ...inter return stmts[0], nil } +// ParseWithParams4Test wrapper (s *session) ParseWithParams for test +func ParseWithParams4Test(ctx context.Context, s Session, + sql string, args ...interface{}) (ast.StmtNode, error) { + return s.(*session).ParseWithParams(ctx, sql, args) +} + // ExecRestrictedStmt implements RestrictedSQLExecutor interface. func (s *session) ExecRestrictedStmt(ctx context.Context, stmtNode ast.StmtNode, opts ...sqlexec.OptionFuncAlias) ( []chunk.Row, []*ast.ResultField, error) { - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { defer pprof.SetGoroutineLabels(ctx) } - var execOption sqlexec.ExecOption - for _, opt := range opts { - opt(&execOption) + execOption := sqlexec.GetExecOption(opts) + var se *session + var clean func() + var err error + if execOption.UseCurSession { + se, clean, err = s.useCurrentSession(execOption) + } else { + se, clean, err = s.getInternalSession(execOption) } - // Use special session to execute the sql. - tmp, err := s.sysSessionPool().Get() if err != nil { return nil, nil, err } - defer s.sysSessionPool().Put(tmp) - se := tmp.(*session) + defer clean() startTime := time.Now() + metrics.SessionRestrictedSQLCounter.Inc() + ctx = context.WithValue(ctx, execdetails.StmtExecDetailKey, &execdetails.StmtExecDetails{}) + ctx = context.WithValue(ctx, tikvutil.ExecDetailsKey, &tikvutil.ExecDetails{}) + rs, err := se.ExecuteStmt(ctx, stmtNode) + if err != nil { + se.sessionVars.StmtCtx.AppendError(err) + } + if rs == nil { + return nil, nil, err + } + defer func() { + if closeErr := rs.Close(); closeErr != nil { + err = closeErr + } + }() + var rows []chunk.Row + rows, err = drainRecordSet(ctx, se, rs, nil) + if err != nil { + return nil, nil, err + } + metrics.QueryDurationHistogram.WithLabelValues(metrics.LblInternal).Observe(time.Since(startTime).Seconds()) + return rows, rs.Fields(), err +} + +// ExecRestrictedStmt4Test wrapper `(s *session) ExecRestrictedStmt` for test. +func ExecRestrictedStmt4Test(ctx context.Context, s Session, + stmtNode ast.StmtNode, opts ...sqlexec.OptionFuncAlias) ( + []chunk.Row, []*ast.ResultField, error) { + return s.(*session).ExecRestrictedStmt(ctx, stmtNode, opts...) +} + +// only set and clean session with execOption +func (s *session) useCurrentSession(execOption sqlexec.ExecOption) (*session, func(), error) { + var err error + if execOption.SnapshotTS != 0 { + s.sessionVars.SnapshotInfoschema, err = getSnapshotInfoSchema(s, execOption.SnapshotTS) + if err != nil { + return nil, nil, err + } + if err := s.sessionVars.SetSystemVar(variable.TiDBSnapshot, strconv.FormatUint(execOption.SnapshotTS, 10)); err != nil { + return nil, nil, err + } + } + prevStatsVer := s.sessionVars.AnalyzeVersion + if execOption.AnalyzeVer != 0 { + s.sessionVars.AnalyzeVersion = execOption.AnalyzeVer + } + prevSQL := s.sessionVars.StmtCtx.OriginalSQL + prevStmtType := s.sessionVars.StmtCtx.StmtType + prevTables := s.sessionVars.StmtCtx.Tables + return s, func() { + s.sessionVars.AnalyzeVersion = prevStatsVer + if err := s.sessionVars.SetSystemVar(variable.TiDBSnapshot, ""); err != nil { + logutil.BgLogger().Error("set tidbSnapshot error", zap.Error(err)) + } + s.sessionVars.SnapshotInfoschema = nil + s.sessionVars.StmtCtx.OriginalSQL = prevSQL + s.sessionVars.StmtCtx.StmtType = prevStmtType + s.sessionVars.StmtCtx.Tables = prevTables + }, nil +} + +func (s *session) getInternalSession(execOption sqlexec.ExecOption) (*session, func(), error) { + tmp, err := s.sysSessionPool().Get() + if err != nil { + return nil, nil, errors.Trace(err) + } + se := tmp.(*session) + // The special session will share the `InspectionTableCache` with current session // if the current session in inspection mode. if cache := s.sessionVars.InspectionTableCache; cache != nil { se.sessionVars.InspectionTableCache = cache - defer func() { se.sessionVars.InspectionTableCache = nil }() } if ok := s.sessionVars.OptimizerUseInvisibleIndexes; ok { se.sessionVars.OptimizerUseInvisibleIndexes = true - defer func() { se.sessionVars.OptimizerUseInvisibleIndexes = false }() } prePruneMode := se.sessionVars.PartitionPruneMode.Load() - defer func() { - if !execOption.IgnoreWarning { - if se != nil && se.GetSessionVars().StmtCtx.WarningCount() > 0 { - warnings := se.GetSessionVars().StmtCtx.GetWarnings() - s.GetSessionVars().StmtCtx.AppendWarnings(warnings) - } - } - se.sessionVars.PartitionPruneMode.Store(prePruneMode) - }() if execOption.SnapshotTS != 0 { se.sessionVars.SnapshotInfoschema, err = getSnapshotInfoSchema(s, execOption.SnapshotTS) @@ -1568,47 +1710,98 @@ func (s *session) ExecRestrictedStmt(ctx context.Context, stmtNode ast.StmtNode, if err := se.sessionVars.SetSystemVar(variable.TiDBSnapshot, strconv.FormatUint(execOption.SnapshotTS, 10)); err != nil { return nil, nil, err } - defer func() { - if err := se.sessionVars.SetSystemVar(variable.TiDBSnapshot, ""); err != nil { - logutil.BgLogger().Error("set tidbSnapshot error", zap.Error(err)) - } - se.sessionVars.SnapshotInfoschema = nil - }() } + prevStatsVer := se.sessionVars.AnalyzeVersion if execOption.AnalyzeVer != 0 { - prevStatsVer := se.sessionVars.AnalyzeVersion se.sessionVars.AnalyzeVersion = execOption.AnalyzeVer - defer func() { - se.sessionVars.AnalyzeVersion = prevStatsVer - }() } // for analyze stmt we need let worker session follow user session that executing stmt. se.sessionVars.PartitionPruneMode.Store(s.sessionVars.PartitionPruneMode.Load()) - metrics.SessionRestrictedSQLCounter.Inc() - ctx = context.WithValue(ctx, execdetails.StmtExecDetailKey, &execdetails.StmtExecDetails{}) - ctx = context.WithValue(ctx, tikvutil.ExecDetailsKey, &tikvutil.ExecDetails{}) - rs, err := se.ExecuteStmt(ctx, stmtNode) - if err != nil { - se.sessionVars.StmtCtx.AppendError(err) + // Put the internal session to the map of SessionManager + infosync.StoreInternalSession(se) + + return se, func() { + se.sessionVars.AnalyzeVersion = prevStatsVer + if err := se.sessionVars.SetSystemVar(variable.TiDBSnapshot, ""); err != nil { + logutil.BgLogger().Error("set tidbSnapshot error", zap.Error(err)) + } + se.sessionVars.SnapshotInfoschema = nil + if !execOption.IgnoreWarning { + if se != nil && se.GetSessionVars().StmtCtx.WarningCount() > 0 { + warnings := se.GetSessionVars().StmtCtx.GetWarnings() + s.GetSessionVars().StmtCtx.AppendWarnings(warnings) + } + } + se.sessionVars.PartitionPruneMode.Store(prePruneMode) + se.sessionVars.OptimizerUseInvisibleIndexes = false + se.sessionVars.InspectionTableCache = nil + // Delete the internal session to the map of SessionManager + infosync.DeleteInternalSession(se) + s.sysSessionPool().Put(tmp) + }, nil +} + +func (s *session) withRestrictedSQLExecutor(ctx context.Context, opts []sqlexec.OptionFuncAlias, fn func(context.Context, *session) ([]chunk.Row, []*ast.ResultField, error)) ([]chunk.Row, []*ast.ResultField, error) { + execOption := sqlexec.GetExecOption(opts) + var se *session + var clean func() + var err error + if execOption.UseCurSession { + se, clean, err = s.useCurrentSession(execOption) + } else { + se, clean, err = s.getInternalSession(execOption) } - if rs == nil { - return nil, nil, err + if err != nil { + return nil, nil, errors.Trace(err) } - defer func() { - if closeErr := rs.Close(); closeErr != nil { - err = closeErr + defer clean() + if execOption.TrackSysProcID > 0 { + err = execOption.TrackSysProc(execOption.TrackSysProcID, se) + if err != nil { + return nil, nil, errors.Trace(err) } - }() - var rows []chunk.Row - rows, err = drainRecordSet(ctx, se, rs, nil) - if err != nil { - return nil, nil, err + // unTrack should be called before clean (return sys session) + defer execOption.UnTrackSysProc(execOption.TrackSysProcID) } - metrics.QueryDurationHistogram.WithLabelValues(metrics.LblInternal).Observe(time.Since(startTime).Seconds()) - return rows, rs.Fields(), err + return fn(ctx, se) +} + +func (s *session) ExecRestrictedSQL(ctx context.Context, opts []sqlexec.OptionFuncAlias, sql string, params ...interface{}) ([]chunk.Row, []*ast.ResultField, error) { + return s.withRestrictedSQLExecutor(ctx, opts, func(ctx context.Context, se *session) ([]chunk.Row, []*ast.ResultField, error) { + stmt, err := se.ParseWithParams(ctx, sql, params...) + if err != nil { + return nil, nil, errors.Trace(err) + } + if topsqlstate.TopSQLEnabled() { + defer pprof.SetGoroutineLabels(ctx) + } + startTime := time.Now() + metrics.SessionRestrictedSQLCounter.Inc() + ctx = context.WithValue(ctx, execdetails.StmtExecDetailKey, &execdetails.StmtExecDetails{}) + ctx = context.WithValue(ctx, tikvutil.ExecDetailsKey, &tikvutil.ExecDetails{}) + rs, err := se.ExecuteStmt(ctx, stmt) + if err != nil { + se.sessionVars.StmtCtx.AppendError(err) + } + if rs == nil { + return nil, nil, err + } + defer func() { + if closeErr := rs.Close(); closeErr != nil { + err = closeErr + } + }() + var rows []chunk.Row + rows, err = drainRecordSet(ctx, se, rs, nil) + if err != nil { + return nil, nil, err + } + metrics.QueryDurationHistogram.WithLabelValues(metrics.LblInternal).Observe(time.Since(startTime).Seconds()) + return rows, rs.Fields(), err + }) } func (s *session) ExecuteStmt(ctx context.Context, stmtNode ast.StmtNode) (sqlexec.RecordSet, error) { @@ -1618,7 +1811,10 @@ func (s *session) ExecuteStmt(ctx context.Context, stmtNode ast.StmtNode) (sqlex ctx = opentracing.ContextWithSpan(ctx, span1) } - s.PrepareTxnCtx(ctx) + if err := s.PrepareTxnCtx(ctx); err != nil { + return nil, err + } + if err := s.loadCommonGlobalVariablesIfNeeded(); err != nil { return nil, err } @@ -1630,7 +1826,7 @@ func (s *session) ExecuteStmt(ctx context.Context, stmtNode ast.StmtNode) (sqlex return nil, err } normalizedSQL, digest := s.sessionVars.StmtCtx.SQLDigest() - if variable.TopSQLEnabled() { + if topsqlstate.TopSQLEnabled() { ctx = topsql.AttachSQLInfo(ctx, normalizedSQL, digest, "", nil, s.sessionVars.InRestrictedSQL) } @@ -1756,6 +1952,13 @@ func (s *session) hasQuerySpecial() bool { // runStmt executes the sqlexec.Statement and commit or rollback the current transaction. func runStmt(ctx context.Context, se *session, s sqlexec.Statement) (rs sqlexec.RecordSet, err error) { + failpoint.Inject("assertTxnManagerInRunStmt", func() { + sessiontxn.RecordAssert(se, "assertTxnManagerInRunStmt", true) + if stmt, ok := s.(*executor.ExecStmt); ok { + sessiontxn.AssertTxnManagerInfoSchema(se, stmt.InfoSchema) + } + }) + if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil { span1 := span.Tracer().StartSpan("session.runStmt", opentracing.ChildOf(span.Context())) span1.LogKV("sql", s.OriginText()) @@ -1896,7 +2099,9 @@ func (s *session) PrepareStmt(sql string) (stmtID uint32, paramCount int, fields inTxn := s.GetSessionVars().InTxn() // NewPrepareExec may need startTS to build the executor, for example prepare statement has subquery in int. // So we have to call PrepareTxnCtx here. - s.PrepareTxnCtx(ctx) + if err = s.PrepareTxnCtx(ctx); err != nil { + return + } s.PrepareTSFuture(ctx) prepareExec := executor.NewPrepareExec(s, sql) err = prepareExec.Next(ctx, nil) @@ -1912,8 +2117,14 @@ func (s *session) PrepareStmt(sql string) (stmtID uint32, paramCount int, fields func (s *session) preparedStmtExec(ctx context.Context, is infoschema.InfoSchema, snapshotTS uint64, - stmtID uint32, prepareStmt *plannercore.CachedPrepareStmt, args []types.Datum) (sqlexec.RecordSet, error) { - st, tiFlashPushDown, tiFlashExchangePushDown, err := executor.CompileExecutePreparedStmt(ctx, s, stmtID, is, snapshotTS, args) + stmtID uint32, prepareStmt *plannercore.CachedPrepareStmt, replicaReadScope string, args []types.Datum) (sqlexec.RecordSet, error) { + + failpoint.Inject("assertTxnManagerInPreparedStmtExec", func() { + sessiontxn.RecordAssert(s, "assertTxnManagerInPreparedStmtExec", true) + sessiontxn.AssertTxnManagerInfoSchema(s, is) + }) + + st, tiFlashPushDown, tiFlashExchangePushDown, err := executor.CompileExecutePreparedStmt(ctx, s, stmtID, is, snapshotTS, replicaReadScope, args) if err != nil { return nil, err } @@ -1934,13 +2145,21 @@ func (s *session) preparedStmtExec(ctx context.Context, // cachedPlanExec short path currently ONLY for cached "point select plan" execution func (s *session) cachedPlanExec(ctx context.Context, is infoschema.InfoSchema, snapshotTS uint64, - stmtID uint32, prepareStmt *plannercore.CachedPrepareStmt, args []types.Datum) (sqlexec.RecordSet, error) { + stmtID uint32, prepareStmt *plannercore.CachedPrepareStmt, replicaReadScope string, args []types.Datum) (sqlexec.RecordSet, error) { + + failpoint.Inject("assertTxnManagerInCachedPlanExec", func() { + sessiontxn.RecordAssert(s, "assertTxnManagerInCachedPlanExec", true) + sessiontxn.AssertTxnManagerInfoSchema(s, is) + }) + prepared := prepareStmt.PreparedAst // compile ExecStmt execAst := &ast.ExecuteStmt{ExecID: stmtID} if err := executor.ResetContextOfStmt(s, execAst); err != nil { return nil, err } + isStaleness := snapshotTS != 0 + s.sessionVars.StmtCtx.IsStaleness = isStaleness execAst.BinaryArgs = args execPlan, err := planner.OptimizeExecStmt(ctx, s, execAst, is) if err != nil { @@ -1949,15 +2168,17 @@ func (s *session) cachedPlanExec(ctx context.Context, stmtCtx := s.GetSessionVars().StmtCtx stmt := &executor.ExecStmt{ - GoCtx: ctx, - InfoSchema: is, - Plan: execPlan, - StmtNode: execAst, - Ctx: s, - OutputNames: execPlan.OutputNames(), - PsStmt: prepareStmt, - Ti: &executor.TelemetryInfo{}, - SnapshotTS: snapshotTS, + GoCtx: ctx, + InfoSchema: is, + Plan: execPlan, + StmtNode: execAst, + Ctx: s, + OutputNames: execPlan.OutputNames(), + PsStmt: prepareStmt, + Ti: &executor.TelemetryInfo{}, + IsStaleness: isStaleness, + SnapshotTS: snapshotTS, + ReplicaReadScope: replicaReadScope, } compileDuration := time.Since(s.sessionVars.StartTime) sessionExecuteCompileDurationGeneral.Observe(compileDuration.Seconds()) @@ -2007,25 +2228,19 @@ func (s *session) cachedPlanExec(ctx context.Context, // IsCachedExecOk check if we can execute using plan cached in prepared structure // Be careful for the short path, current precondition is ths cached plan satisfying // IsPointGetWithPKOrUniqueKeyByAutoCommit -func (s *session) IsCachedExecOk(ctx context.Context, preparedStmt *plannercore.CachedPrepareStmt) (bool, error) { +func (s *session) IsCachedExecOk(ctx context.Context, preparedStmt *plannercore.CachedPrepareStmt, isStaleness bool) (bool, error) { prepared := preparedStmt.PreparedAst - if prepared.CachedPlan == nil { + if prepared.CachedPlan == nil || isStaleness { return false, nil } // check auto commit if !plannercore.IsAutoCommitTxn(s) { return false, nil } - // SnapshotTSEvaluator != nil, it is stale read - // stale read expect a stale infoschema - // so skip infoschema check - if preparedStmt.SnapshotTSEvaluator == nil { - // check schema version - is := s.GetInfoSchema().(infoschema.InfoSchema) - if prepared.SchemaVersion != is.SchemaMetaVersion() { - prepared.CachedPlan = nil - return false, nil - } + is := s.GetInfoSchema().(infoschema.InfoSchema) + if prepared.SchemaVersion != is.SchemaMetaVersion() { + prepared.CachedPlan = nil + return false, nil } // maybe we'd better check cached plan type here, current // only point select/update will be cached, see "getPhysicalPlan" func @@ -2050,8 +2265,11 @@ func (s *session) IsCachedExecOk(ctx context.Context, preparedStmt *plannercore. // ExecutePreparedStmt executes a prepared statement. func (s *session) ExecutePreparedStmt(ctx context.Context, stmtID uint32, args []types.Datum) (sqlexec.RecordSet, error) { - s.PrepareTxnCtx(ctx) var err error + if err = s.PrepareTxnCtx(ctx); err != nil { + return nil, err + } + s.sessionVars.StartTime = time.Now() preparedPointer, ok := s.sessionVars.PreparedStmts[stmtID] if !ok { @@ -2063,33 +2281,47 @@ func (s *session) ExecutePreparedStmt(ctx context.Context, stmtID uint32, args [ if !ok { return nil, errors.Errorf("invalid CachedPrepareStmt type") } - executor.CountStmtNode(preparedStmt.PreparedAst.Stmt, s.sessionVars.InRestrictedSQL) - ok, err = s.IsCachedExecOk(ctx, preparedStmt) - if err != nil { - return nil, err - } - s.txn.onStmtStart(preparedStmt.SQLDigest.String()) - defer s.txn.onStmtEnd() + var is infoschema.InfoSchema var snapshotTS uint64 - if preparedStmt.ForUpdateRead { + replicaReadScope := oracle.GlobalTxnScope + + staleReadProcessor := staleread.NewStaleReadProcessor(s) + if err = staleReadProcessor.OnExecutePreparedStmt(preparedStmt.SnapshotTSEvaluator); err != nil { + return nil, err + } + + if staleReadProcessor.IsStaleness() { + snapshotTS = staleReadProcessor.GetStalenessReadTS() + is = staleReadProcessor.GetStalenessInfoSchema() + replicaReadScope = config.GetTxnScopeFromConfig() + } else if preparedStmt.ForUpdateRead { is = domain.GetDomain(s).InfoSchema() - } else if preparedStmt.SnapshotTSEvaluator != nil { - snapshotTS, err = preparedStmt.SnapshotTSEvaluator(s) - if err != nil { - return nil, errors.Trace(err) - } - is, err = getSnapshotInfoSchema(s, snapshotTS) - if err != nil { - return nil, errors.Trace(err) - } } else { is = s.GetInfoSchema().(infoschema.InfoSchema) } + + txnCtxProvider := &sessiontxn.SimpleTxnContextProvider{ + InfoSchema: is, + } + + txnManager := sessiontxn.GetTxnManager(s) + if err = txnManager.SetContextProvider(txnCtxProvider); err != nil { + return nil, err + } + + executor.CountStmtNode(preparedStmt.PreparedAst.Stmt, s.sessionVars.InRestrictedSQL) + ok, err = s.IsCachedExecOk(ctx, preparedStmt, snapshotTS != 0) + if err != nil { + return nil, err + } + s.txn.onStmtStart(preparedStmt.SQLDigest.String()) + defer s.txn.onStmtEnd() + if ok { - return s.cachedPlanExec(ctx, is, snapshotTS, stmtID, preparedStmt, args) + return s.cachedPlanExec(ctx, txnManager.GetTxnInfoSchema(), snapshotTS, stmtID, preparedStmt, replicaReadScope, args) } - return s.preparedStmtExec(ctx, is, snapshotTS, stmtID, preparedStmt, args) + return s.preparedStmtExec(ctx, txnManager.GetTxnInfoSchema(), snapshotTS, stmtID, preparedStmt, replicaReadScope, args) } func (s *session) DropPreparedStmt(stmtID uint32) error { @@ -2101,6 +2333,19 @@ func (s *session) DropPreparedStmt(stmtID uint32) error { return nil } +// setTxnAssertionLevel sets assertion level of a transactin. Note that assertion level should be set only once just +// after creating a new transaction. +func setTxnAssertionLevel(txn kv.Transaction, assertionLevel variable.AssertionLevel) { + switch assertionLevel { + case variable.AssertionLevelOff: + txn.SetOption(kv.AssertionLevel, kvrpcpb.AssertionLevel_Off) + case variable.AssertionLevelFast: + txn.SetOption(kv.AssertionLevel, kvrpcpb.AssertionLevel_Fast) + case variable.AssertionLevelStrict: + txn.SetOption(kv.AssertionLevel, kvrpcpb.AssertionLevel_Strict) + } +} + func (s *session) Txn(active bool) (kv.Transaction, error) { if !active { return &s.txn, nil @@ -2136,6 +2381,10 @@ func (s *session) Txn(active bool) (kv.Transaction, error) { s.txn.SetOption(kv.ReplicaRead, readReplicaType) } s.txn.SetOption(kv.SnapInterceptor, s.getSnapshotInterceptor()) + if s.GetSessionVars().StmtCtx.WeakConsistency { + s.txn.SetOption(kv.IsolationLevel, kv.RC) + } + setTxnAssertionLevel(&s.txn, s.sessionVars.AssertionLevel) } return &s.txn, nil } @@ -2190,6 +2439,7 @@ func (s *session) NewTxn(ctx context.Context) error { if replicaReadType.IsFollowerRead() { txn.SetOption(kv.ReplicaRead, replicaReadType) } + setTxnAssertionLevel(txn, s.sessionVars.AssertionLevel) s.txn.changeInvalidToValid(txn) is := domain.GetDomain(s).InfoSchema() s.sessionVars.TxnCtx = &variable.TransactionContext{ @@ -2233,6 +2483,7 @@ func (s *session) NewStaleTxnWithStartTS(ctx context.Context, startTS uint64) er txn.SetVars(s.sessionVars.KVVars) txn.SetOption(kv.IsStalenessReadOnly, true) txn.SetOption(kv.TxnScope, txnScope) + setTxnAssertionLevel(txn, s.sessionVars.AssertionLevel) s.txn.changeInvalidToValid(txn) is, err := getSnapshotInfoSchema(s, txn.StartTS()) if err != nil { @@ -2302,6 +2553,9 @@ func (s *session) Close() { if s.sessionVars != nil { s.sessionVars.WithdrawAllPreparedStmt() } + if s.stmtStats != nil { + s.stmtStats.SetFinished() + } s.ClearDiskFullOpt() } @@ -2460,6 +2714,30 @@ func loadCollationParameter(se *session) (bool, error) { return false, nil } +func updateMemoryConfigAndSysVar(se *session) error { + if !config.IsMemoryQuotaQuerySetByUser { + newMemoryQuotaQuery, err := loadDefMemQuotaQuery(se) + if err != nil { + return err + } + config.UpdateGlobal(func(conf *config.Config) { + conf.MemQuotaQuery = newMemoryQuotaQuery + }) + variable.SetSysVar(variable.TiDBMemQuotaQuery, strconv.FormatInt(config.GetGlobalConfig().MemQuotaQuery, 10)) + } + if !config.IsOOMActionSetByUser { + newOOMAction, err := loadDefOOMAction(se) + if err != nil { + return err + } + config.UpdateGlobal(func(conf *config.Config) { + conf.OOMAction = newOOMAction + }) + } + + return nil +} + // loadDefMemQuotaQuery loads the default value of mem-quota-query. // We'll read a tuple if the cluster is upgraded from v3.0.x to v4.0.9+. // An empty result will be returned if it's a newly deployed cluster whose @@ -2506,7 +2784,6 @@ func BootstrapSession(store kv.Storage) (*domain.Domain, error) { return nil, err } } - ver := getStoreBootstrapVersion(store) if ver == notBootstrapped { runInBootstrapSession(store, bootstrap) @@ -2514,87 +2791,50 @@ func BootstrapSession(store kv.Storage) (*domain.Domain, error) { runInBootstrapSession(store, upgrade) } - se, err := createSession(store) + concurrency := int(config.GetGlobalConfig().Performance.StatsLoadConcurrency) + ses, err := createSessions(store, 7+concurrency) if err != nil { return nil, err } - se.GetSessionVars().InRestrictedSQL = true + ses[0].GetSessionVars().InRestrictedSQL = true // get system tz from mysql.tidb - tz, err := se.getTableValue(context.TODO(), mysql.TiDBTable, "system_tz") + tz, err := ses[0].getTableValue(context.TODO(), mysql.TiDBTable, tidbSystemTZ) if err != nil { return nil, err } timeutil.SetSystemTZ(tz) // get the flag from `mysql`.`tidb` which indicating if new collations are enabled. - newCollationEnabled, err := loadCollationParameter(se) + newCollationEnabled, err := loadCollationParameter(ses[0]) if err != nil { return nil, err } + collate.SetNewCollationEnabledForTest(newCollationEnabled) - if newCollationEnabled { - collate.EnableNewCollations() - } - if cfg.Experimental.EnableNewCharset { - collate.EnableNewCharset() - } - - newMemoryQuotaQuery, err := loadDefMemQuotaQuery(se) + err = updateMemoryConfigAndSysVar(ses[0]) if err != nil { return nil, err } - if !config.IsMemoryQuotaQuerySetByUser { - newCfg := *(config.GetGlobalConfig()) - newCfg.MemQuotaQuery = newMemoryQuotaQuery - config.StoreGlobalConfig(&newCfg) - variable.SetSysVar(variable.TiDBMemQuotaQuery, strconv.FormatInt(newCfg.MemQuotaQuery, 10)) - } - newOOMAction, err := loadDefOOMAction(se) - if err != nil { - return nil, err - } - if !config.IsOOMActionSetByUser { - config.UpdateGlobal(func(conf *config.Config) { - conf.OOMAction = newOOMAction - }) - } - - dom := domain.GetDomain(se) - se2, err := createSession(store) - if err != nil { - return nil, err - } - se3, err := createSession(store) - if err != nil { - return nil, err - } + dom := domain.GetDomain(ses[0]) // We should make the load bind-info loop before other loops which has internal SQL. // Because the internal SQL may access the global bind-info handler. As the result, the data race occurs here as the // LoadBindInfoLoop inits global bind-info handler. - err = dom.LoadBindInfoLoop(se2, se3) + err = dom.LoadBindInfoLoop(ses[1], ses[2]) if err != nil { return nil, err } if !config.GetGlobalConfig().Security.SkipGrantTable { - se4, err := createSession(store) - if err != nil { - return nil, err - } - err = dom.LoadPrivilegeLoop(se4) + err = dom.LoadPrivilegeLoop(ses[3]) if err != nil { return nil, err } } // Rebuild sysvar cache in a loop - se5, err := createSession(store) - if err != nil { - return nil, err - } - err = dom.LoadSysVarCacheLoop(se5) + err = dom.LoadSysVarCacheLoop(ses[4]) if err != nil { return nil, err } @@ -2605,33 +2845,30 @@ func BootstrapSession(store kv.Storage) (*domain.Domain, error) { return nil, err } } - se6, err := createSession(store) - if err != nil { - return nil, err - } - err = executor.LoadExprPushdownBlacklist(se6) + + err = executor.LoadExprPushdownBlacklist(ses[5]) if err != nil { return nil, err } - - err = executor.LoadOptRuleBlacklist(se6) + err = executor.LoadOptRuleBlacklist(ses[5]) if err != nil { return nil, err } - dom.TelemetryReportLoop(se6) - dom.TelemetryRotateSubWindowLoop(se6) + dom.TelemetryReportLoop(ses[5]) + dom.TelemetryRotateSubWindowLoop(ses[5]) - se7, err := createSession(store) - if err != nil { - return nil, err + // A sub context for update table stats, and other contexts for concurrent stats loading. + cnt := 1 + concurrency + subCtxs := make([]sessionctx.Context, cnt) + for i := 0; i < cnt; i++ { + subCtxs[i] = sessionctx.Context(ses[6+i]) } - err = dom.UpdateTableStatsLoop(se7) - if err != nil { + if err = dom.LoadAndUpdateStatsLoop(subCtxs); err != nil { return nil, err } - dom.PlanReplayerLoop() + dom.DumpFileGcCheckerLoop() if raw, ok := store.(kv.EtcdBackend); ok { err = raw.StartGCWorker() @@ -2669,6 +2906,19 @@ func runInBootstrapSession(store kv.Storage, bootstrap func(Session)) { domap.Delete(store) } +func createSessions(store kv.Storage, cnt int) ([]*session, error) { + ses := make([]*session, cnt) + for i := 0; i < cnt; i++ { + se, err := createSession(store) + if err != nil { + return nil, err + } + ses[i] = se + } + + return ses, nil +} + func createSession(store kv.Storage) (*session, error) { return createSessionWithOpt(store, nil) } @@ -2679,13 +2929,14 @@ func createSessionWithOpt(store kv.Storage, opt *Opt) (*session, error) { return nil, err } s := &session{ - store: store, - sessionVars: variable.NewSessionVars(), - ddlOwnerChecker: dom.DDL().OwnerManager(), - client: store.GetClient(), - mppClient: store.GetMPPClient(), - builtinFunctionUsage: make(telemetry.BuiltinFunctionsUsage), - } + store: store, + sessionVars: variable.NewSessionVars(), + ddlOwnerChecker: dom.DDL().OwnerManager(), + client: store.GetClient(), + mppClient: store.GetMPPClient(), + stmtStats: stmtstats.CreateStatementStats(), + } + s.functionUsageMu.builtinFunctionUsage = make(telemetry.BuiltinFunctionsUsage) if plannercore.PreparedPlanCacheEnabled() { if opt != nil && opt.PreparedPlanCache != nil { s.preparedPlanCache = opt.PreparedPlanCache @@ -2713,12 +2964,13 @@ func createSessionWithOpt(store kv.Storage, opt *Opt) (*session, error) { // a lock context, which cause we can't call createSession directly. func CreateSessionWithDomain(store kv.Storage, dom *domain.Domain) (*session, error) { s := &session{ - store: store, - sessionVars: variable.NewSessionVars(), - client: store.GetClient(), - mppClient: store.GetMPPClient(), - builtinFunctionUsage: make(telemetry.BuiltinFunctionsUsage), + store: store, + sessionVars: variable.NewSessionVars(), + client: store.GetClient(), + mppClient: store.GetMPPClient(), + stmtStats: stmtstats.CreateStatementStats(), } + s.functionUsageMu.builtinFunctionUsage = make(telemetry.BuiltinFunctionsUsage) if plannercore.PreparedPlanCacheEnabled() { s.preparedPlanCache = kvcache.NewSimpleLRUCache(plannercore.PreparedPlanCacheCapacity, plannercore.PreparedPlanCacheMemoryGuardRatio, plannercore.PreparedPlanCacheMaxMemory.Load()) @@ -2822,12 +3074,12 @@ func (s *session) loadCommonGlobalVariablesIfNeeded() error { return nil } -// PrepareTxnCtx starts a goroutine to begin a transaction if needed, and creates a new transaction context. +// PrepareTxnCtx begins a transaction, and creates a new transaction context. // It is called before we execute a sql query. -func (s *session) PrepareTxnCtx(ctx context.Context) { +func (s *session) PrepareTxnCtx(ctx context.Context) error { s.currentCtx = ctx if s.txn.validOrPending() { - return + return nil } is := s.GetInfoSchema() @@ -2837,11 +3089,17 @@ func (s *session) PrepareTxnCtx(ctx context.Context) { ShardStep: int(s.sessionVars.ShardAllocateStep), TxnScope: s.GetSessionVars().CheckAndGetTxnScope(), } - if !s.sessionVars.IsAutocommit() || s.sessionVars.RetryInfo.Retrying { + if !s.sessionVars.IsAutocommit() || s.sessionVars.RetryInfo.Retrying || + config.GetGlobalConfig().PessimisticTxn.PessimisticAutoCommit.Load() { if s.sessionVars.TxnMode == ast.Pessimistic { s.sessionVars.TxnCtx.IsPessimistic = true } } + + txnCtxProvider := &sessiontxn.SimpleTxnContextProvider{ + InfoSchema: is.(infoschema.InfoSchema), + } + return sessiontxn.GetTxnManager(s).SetContextProvider(txnCtxProvider) } // PrepareTSFuture uses to try to get ts future. @@ -2865,7 +3123,12 @@ func (s *session) PrepareTSFuture(ctx context.Context) { s.txn.changeInvalidToPending(txnFuture) } else if s.txn.Valid() && s.GetSessionVars().IsPessimisticReadConsistency() { // Prepare the statement future if the transaction is valid in RC transactions. - s.GetSessionVars().TxnCtx.SetStmtFutureForRC(s.getTxnFuture(ctx).future) + // If the `RCCheckTS` is used, try to use the last valid ts to read. + if s.GetSessionVars().StmtCtx.RCCheckTS { + s.GetSessionVars().TxnCtx.SetStmtFutureForRC(nil) + } else { + s.GetSessionVars().TxnCtx.SetStmtFutureForRC(s.getTxnFuture(ctx).future) + } } } @@ -2881,6 +3144,8 @@ func (s *session) RefreshTxnCtx(ctx context.Context) error { return err } + s.updateStatsDeltaToCollector() + return s.NewTxn(ctx) } @@ -2896,6 +3161,7 @@ func (s *session) InitTxnWithStartTS(startTS uint64) error { return err } txn.SetVars(s.sessionVars.KVVars) + setTxnAssertionLevel(txn, s.sessionVars.AssertionLevel) s.txn.changeInvalidToValid(txn) err = s.loadCommonGlobalVariablesIfNeeded() if err != nil { @@ -2926,6 +3192,21 @@ func (s *session) ShowProcess() *util.ProcessInfo { return pi } +// GetStartTSFromSession returns the startTS in the session `se` +func GetStartTSFromSession(se interface{}) uint64 { + var startTS uint64 + tmp, ok := se.(*session) + if !ok { + logutil.BgLogger().Error("GetStartTSFromSession failed, can't transform to session struct") + return 0 + } + txnInfo := tmp.TxnInfo() + if txnInfo != nil { + startTS = txnInfo.StartTS + } + return startTS +} + // logStmt logs some crucial SQL including: CREATE USER/GRANT PRIVILEGE/CHANGE PASSWORD/DDL etc and normal SQL // if variable.ProcessGeneralLog is set. func logStmt(execStmt *executor.ExecStmt, s *session) { @@ -3032,7 +3313,7 @@ func (s *session) checkPlacementPolicyBeforeCommit() error { errMsg = fmt.Sprintf("table %v's partition %v doesn't have placement policies with txn_scope %v", tableName, partitionName, txnScope) } - err = ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) + err = dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) break } dcLocation, ok := bundle.GetLeaderDC(placement.DCLabelKey) @@ -3041,7 +3322,7 @@ func (s *session) checkPlacementPolicyBeforeCommit() error { if len(partitionName) > 0 { errMsg = fmt.Sprintf("table %v's partition %v's leader placement policy is not defined", tableName, partitionName) } - err = ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) + err = dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) break } if dcLocation != txnScope { @@ -3050,7 +3331,7 @@ func (s *session) checkPlacementPolicyBeforeCommit() error { errMsg = fmt.Sprintf("table %v's partition %v's leader location %v is out of txn_scope %v", tableName, partitionName, dcLocation, txnScope) } - err = ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) + err = dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs(errMsg) break } // FIXME: currently we assume the physicalTableID is the partition ID. In future, we should consider the situation @@ -3061,7 +3342,7 @@ func (s *session) checkPlacementPolicyBeforeCommit() error { tblInfo := tbl.Meta() state := tblInfo.Partition.GetStateByID(partitionID) if state == model.StateGlobalTxnOnly { - err = ddl.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( + err = dbterror.ErrInvalidPlacementPolicyCheck.GenWithStackByArgs( fmt.Sprintf("partition %s of table %s can not be written by local transactions when its placement policy is being altered", tblInfo.Name, partitionDefInfo.Name)) break @@ -3081,34 +3362,6 @@ func (s *session) GetTxnWriteThroughputSLI() *sli.TxnWriteThroughputSLI { return &s.txn.writeSLI } -var _ telemetry.TemporaryOrCacheTableFeatureChecker = &session{} - -// TemporaryTableExists is used by the telemetry package to avoid circle dependency. -func (s *session) TemporaryTableExists() bool { - is := domain.GetDomain(s).InfoSchema() - for _, dbInfo := range is.AllSchemas() { - for _, tbInfo := range is.SchemaTables(dbInfo.Name) { - if tbInfo.Meta().TempTableType != model.TempTableNone { - return true - } - } - } - return false -} - -// CachedTableExists is used by the telemetry package to avoid circle dependency. -func (s *session) CachedTableExists() bool { - is := domain.GetDomain(s).InfoSchema() - for _, dbInfo := range is.AllSchemas() { - for _, tbInfo := range is.SchemaTables(dbInfo.Name) { - if tbInfo.Meta().TableCacheStatusType != model.TableCacheStatusDisable { - return true - } - } - } - return false -} - // GetInfoSchema returns snapshotInfoSchema if snapshot schema is set. // Transaction infoschema is returned if inside an explicit txn. // Otherwise the latest infoschema is returned. @@ -3160,10 +3413,28 @@ func (s *session) updateTelemetryMetric(es *executor.ExecStmt) { } } +// GetBuiltinFunctionUsage returns the replica of counting of builtin function usage func (s *session) GetBuiltinFunctionUsage() map[string]uint32 { - return s.builtinFunctionUsage + replica := make(map[string]uint32) + s.functionUsageMu.RLock() + defer s.functionUsageMu.RUnlock() + for key, value := range s.functionUsageMu.builtinFunctionUsage { + replica[key] = value + } + return replica +} + +// BuiltinFunctionUsageInc increase the counting of the builtin function usage +func (s *session) BuiltinFunctionUsageInc(scalarFuncSigName string) { + s.functionUsageMu.Lock() + defer s.functionUsageMu.Unlock() + s.functionUsageMu.builtinFunctionUsage.Inc(scalarFuncSigName) } func (s *session) getSnapshotInterceptor() kv.SnapshotInterceptor { return temptable.SessionSnapshotInterceptor(s) } + +func (s *session) GetStmtStats() *stmtstats.StatementStats { + return s.stmtStats +} diff --git a/session/session_fail_test.go b/session/session_fail_test.go index 2e293f106ff6d..2e0b770c348ea 100644 --- a/session/session_fail_test.go +++ b/session/session_fail_test.go @@ -16,16 +16,20 @@ package session_test import ( "context" - "strings" + "testing" - . "github.com/pingcap/check" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/util/testkit" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" ) -func (s *testSessionSerialSuite) TestFailStatementCommitInRetry(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestFailStatementCommitInRetry(t *testing.T) { + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) tk.MustExec("create table t (id int)") tk.MustExec("begin") @@ -33,90 +37,109 @@ func (s *testSessionSerialSuite) TestFailStatementCommitInRetry(c *C) { tk.MustExec("insert into t values (2),(3),(4),(5)") tk.MustExec("insert into t values (6)") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockCommitError8942", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/mockCommitError8942", `return(true)`)) _, err := tk.Exec("commit") - c.Assert(err, NotNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockCommitError8942"), IsNil) + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/mockCommitError8942")) tk.MustExec("insert into t values (6)") tk.MustQuery(`select * from t`).Check(testkit.Rows("6")) } -func (s *testSessionSerialSuite) TestGetTSFailDirtyState(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestGetTSFailDirtyState(t *testing.T) { + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) tk.MustExec("create table t (id int)") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockGetTSFail", "return"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/mockGetTSFail", "return")) ctx := failpoint.WithHook(context.Background(), func(ctx context.Context, fpname string) bool { return fpname == "github.com/pingcap/tidb/session/mockGetTSFail" }) - _, err := tk.Se.Execute(ctx, "select * from t") - c.Assert(err, NotNil) + _, err := tk.Session().Execute(ctx, "select * from t") + if config.GetGlobalConfig().Store == "unistore" { + require.Error(t, err) + } else { + require.NoError(t, err) + } // Fix a bug that active txn fail set TxnState.fail to error, and then the following write // affected by this fail flag. tk.MustExec("insert into t values (1)") tk.MustQuery(`select * from t`).Check(testkit.Rows("1")) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockGetTSFail"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/mockGetTSFail")) } -func (s *testSessionSerialSuite) TestGetTSFailDirtyStateInretry(c *C) { +func TestGetTSFailDirtyStateInretry(t *testing.T) { defer func() { - c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockCommitError"), IsNil) - c.Assert(failpoint.Disable("tikvclient/mockGetTSErrorInRetry"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/mockCommitError")) + require.NoError(t, failpoint.Disable("tikvclient/mockGetTSErrorInRetry")) }() - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) tk.MustExec("create table t (id int)") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockCommitError", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/mockCommitError", `return(true)`)) // This test will mock a PD timeout error, and recover then. // Just make mockGetTSErrorInRetry return true once, and then return false. - c.Assert(failpoint.Enable("tikvclient/mockGetTSErrorInRetry", - `1*return(true)->return(false)`), IsNil) + require.NoError(t, failpoint.Enable("tikvclient/mockGetTSErrorInRetry", + `1*return(true)->return(false)`)) tk.MustExec("insert into t values (2)") tk.MustQuery(`select * from t`).Check(testkit.Rows("2")) } -func (s *testSessionSerialSuite) TestKillFlagInBackoff(c *C) { +func TestKillFlagInBackoff(t *testing.T) { // This test checks the `killed` flag is passed down to the backoffer through // session.KVVars. - tk := testkit.NewTestKitWithInit(c, s.store) + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) tk.MustExec("create table kill_backoff (id int)") // Inject 1 time timeout. If `Killed` is not successfully passed, it will retry and complete query. - c.Assert(failpoint.Enable("tikvclient/tikvStoreSendReqResult", `return("timeout")->return("")`), IsNil) + require.NoError(t, failpoint.Enable("tikvclient/tikvStoreSendReqResult", `return("timeout")->return("")`)) defer failpoint.Disable("tikvclient/tikvStoreSendReqResult") // Set kill flag and check its passed to backoffer. - tk.Se.GetSessionVars().Killed = 1 + tk.Session().GetSessionVars().Killed = 1 rs, err := tk.Exec("select * from kill_backoff") - c.Assert(err, IsNil) - _, err = session.ResultSetToStringSlice(context.TODO(), tk.Se, rs) + require.NoError(t, err) + _, err = session.ResultSetToStringSlice(context.TODO(), tk.Session(), rs) // `interrupted` is returned when `Killed` is set. - c.Assert(strings.Contains(err.Error(), "Query execution was interrupted"), IsTrue) + require.Regexp(t, ".*Query execution was interrupted.*", err.Error()) } -func (s *testSessionSerialSuite) TestClusterTableSendError(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - c.Assert(failpoint.Enable("tikvclient/tikvStoreSendReqResult", `return("requestTiDBStoreError")`), IsNil) +func TestClusterTableSendError(t *testing.T) { + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) + require.NoError(t, failpoint.Enable("tikvclient/tikvStoreSendReqResult", `return("requestTiDBStoreError")`)) defer failpoint.Disable("tikvclient/tikvStoreSendReqResult") tk.MustQuery("select * from information_schema.cluster_slow_query") - c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) - c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err, ErrorMatches, ".*TiDB server timeout, address is.*") + require.Equal(t, tk.Session().GetSessionVars().StmtCtx.WarningCount(), uint16(1)) + require.Regexp(t, ".*TiDB server timeout, address is.*", tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error()) } -func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) +func TestAutoCommitNeedNotLinearizability(t *testing.T) { + store, clean := createStorage(t) + defer clean() + + tk := createTestKit(t, store) tk.MustExec("drop table if exists t1;") defer tk.MustExec("drop table if exists t1") tk.MustExec(`create table t1 (c int)`) - c.Assert(failpoint.Enable("tikvclient/getMinCommitTSFromTSO", `panic`), IsNil) + require.NoError(t, failpoint.Enable("tikvclient/getMinCommitTSFromTSO", `panic`)) defer func() { - c.Assert(failpoint.Disable("tikvclient/getMinCommitTSFromTSO"), IsNil) + require.NoError(t, failpoint.Disable("tikvclient/getMinCommitTSFromTSO")) }() - c.Assert(tk.Se.GetSessionVars().SetSystemVar("tidb_enable_async_commit", "1"), IsNil) - c.Assert(tk.Se.GetSessionVars().SetSystemVar("tidb_guarantee_linearizability", "1"), IsNil) + require.NoError(t, tk.Session().GetSessionVars().SetSystemVar("tidb_enable_async_commit", "1")) + require.NoError(t, tk.Session().GetSessionVars().SetSystemVar("tidb_guarantee_linearizability", "1")) // Auto-commit transactions don't need to get minCommitTS from TSO tk.MustExec("INSERT INTO t1 VALUES (1)") @@ -127,7 +150,7 @@ func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { func() { defer func() { err := recover() - c.Assert(err, NotNil) + require.NotNil(t, err) }() tk.MustExec("COMMIT") }() @@ -137,14 +160,14 @@ func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { func() { defer func() { err := recover() - c.Assert(err, NotNil) + require.NotNil(t, err) }() tk.MustExec("COMMIT") }() // Same for 1PC tk.MustExec("set autocommit = 1") - c.Assert(tk.Se.GetSessionVars().SetSystemVar("tidb_enable_1pc", "1"), IsNil) + require.NoError(t, tk.Session().GetSessionVars().SetSystemVar("tidb_enable_1pc", "1")) tk.MustExec("INSERT INTO t1 VALUES (4)") tk.MustExec("BEGIN") @@ -152,7 +175,7 @@ func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { func() { defer func() { err := recover() - c.Assert(err, NotNil) + require.NotNil(t, err) }() tk.MustExec("COMMIT") }() @@ -162,7 +185,7 @@ func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { func() { defer func() { err := recover() - c.Assert(err, NotNil) + require.NotNil(t, err) }() tk.MustExec("COMMIT") }() diff --git a/session/session_test.go b/session/session_test.go index 7b5febe0d18e0..78baad9013878 100644 --- a/session/session_test.go +++ b/session/session_test.go @@ -27,6 +27,7 @@ import ( "strings" "sync" "sync/atomic" + "testing" "time" "github.com/docker/go-units" @@ -61,18 +62,19 @@ import ( "github.com/pingcap/tidb/store/mockstore/mockcopr" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" + newTestkit "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tidb/util/testkit" "github.com/pingcap/tidb/util/testleak" - "github.com/pingcap/tidb/util/testutil" "github.com/pingcap/tipb/go-binlog" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/txnkv/transaction" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc" ) @@ -87,7 +89,6 @@ var _ = Suite(&testSessionSuite{}) var _ = Suite(&testSessionSuite2{}) var _ = Suite(&testSessionSuite3{}) var _ = Suite(&testSchemaSuite{}) -var _ = Suite(&testIsolationSuite{}) var _ = SerialSuites(&testSchemaSerialSuite{}) var _ = SerialSuites(&testSessionSerialSuite{}) var _ = SerialSuites(&testBackupRestoreSuite{}) @@ -259,6 +260,31 @@ func (s *testSessionSuiteBase) TearDownTest(c *C) { } } +func createStorage(t *testing.T) (kv.Storage, func()) { + if *withTiKV { + initPdAddrs() + pdAddr := <-pdAddrChan + var d driver.TiKVDriver + config.UpdateGlobal(func(conf *config.Config) { + conf.TxnLocalLatches.Enabled = false + }) + store, err := d.Open(fmt.Sprintf("tikv://%s?disableGC=true", pdAddr)) + require.NoError(t, err) + require.NoError(t, clearStorage(store)) + require.NoError(t, clearETCD(store.(kv.EtcdBackend))) + session.ResetStoreForWithTiKVTest(store) + dom, err := session.BootstrapSession(store) + require.NoError(t, err) + + return store, func() { + dom.Close() + require.NoError(t, store.Close()) + pdAddrChan <- pdAddr + } + } + return newTestkit.CreateMockStore(t) +} + type mockBinlogPump struct { } @@ -691,15 +717,87 @@ func (s *testSessionSuite) TestGlobalVarAccessor(c *C) { _, err = tk.Exec("set global time_zone = 'timezone'") c.Assert(err, NotNil) c.Assert(terror.ErrorEqual(err, variable.ErrUnknownTimeZone), IsTrue) +} + +func (s *testSessionSuite) TestUpgradeSysvars(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + se := tk.Se.(variable.GlobalVarAccessor) // Set the global var to a non canonical form of the value // i.e. implying that it was set from an earlier version of TiDB. tk.MustExec(`REPLACE INTO mysql.global_variables (variable_name, variable_value) VALUES ('tidb_enable_noop_functions', '0')`) domain.GetDomain(tk.Se).NotifyUpdateSysVarCache() // update cache - v, err = se.GetGlobalSysVar("tidb_enable_noop_functions") + v, err := se.GetGlobalSysVar("tidb_enable_noop_functions") c.Assert(err, IsNil) c.Assert(v, Equals, "OFF") + + // Set the global var to "" which is the invalid version of this from TiDB 4.0.16 + // the err is quashed by the GetGlobalSysVar, and the default value is restored. + // This helps callers of GetGlobalSysVar(), which can't individually be expected + // to handle upgrade/downgrade issues correctly. + + tk.MustExec(`REPLACE INTO mysql.global_variables (variable_name, variable_value) VALUES ('rpl_semi_sync_slave_enabled', '')`) + domain.GetDomain(tk.Se).NotifyUpdateSysVarCache() // update cache + v, err = se.GetGlobalSysVar("rpl_semi_sync_slave_enabled") + c.Assert(err, IsNil) + c.Assert(v, Equals, "OFF") // the default value is restored. + result := tk.MustQuery("SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'") + result.Check(testkit.Rows("rpl_semi_sync_slave_enabled OFF")) + + // Ensure variable out of range is converted to in range after upgrade. + // This further helps for https://github.com/pingcap/tidb/pull/28842 + + tk.MustExec(`REPLACE INTO mysql.global_variables (variable_name, variable_value) VALUES ('tidb_executor_concurrency', '999')`) + domain.GetDomain(tk.Se).NotifyUpdateSysVarCache() // update cache + v, err = se.GetGlobalSysVar("tidb_executor_concurrency") + c.Assert(err, IsNil) + c.Assert(v, Equals, "256") // the max value is restored. + + // Handle the case of a completely bogus value from an earlier version of TiDB. + // This could be the case if an ENUM sysvar removes a value. + + tk.MustExec(`REPLACE INTO mysql.global_variables (variable_name, variable_value) VALUES ('tidb_enable_noop_functions', 'SOMEVAL')`) + domain.GetDomain(tk.Se).NotifyUpdateSysVarCache() // update cache + v, err = se.GetGlobalSysVar("tidb_enable_noop_functions") + c.Assert(err, IsNil) + c.Assert(v, Equals, "OFF") // the default value is restored. +} + +func (s *testSessionSuite) TestSetInstanceSysvarBySetGlobalSysVar(c *C) { + varName := "tidb_general_log" + defaultValue := "OFF" // This is the default value for tidb_general_log + + tk := testkit.NewTestKitWithInit(c, s.store) + se := tk.Se.(variable.GlobalVarAccessor) + + // Get globalSysVar twice and get the same default value + v, err := se.GetGlobalSysVar(varName) + c.Assert(err, IsNil) + c.Assert(v, Equals, defaultValue) + v, err = se.GetGlobalSysVar(varName) + c.Assert(err, IsNil) + c.Assert(v, Equals, defaultValue) + + // session.GetGlobalSysVar would not get the value which session.SetGlobalSysVar writes, + // because SetGlobalSysVar calls SetGlobalFromHook, which uses TiDBGeneralLog's SetGlobal, + // but GetGlobalSysVar could not access TiDBGeneralLog's GetGlobal. + + // set to "1" + err = se.SetGlobalSysVar(varName, "ON") + c.Assert(err, IsNil) + v, err = se.GetGlobalSysVar(varName) + tk.MustQuery("select @@global.tidb_general_log").Check(testkit.Rows("1")) + c.Assert(err, IsNil) + c.Assert(v, Equals, defaultValue) + + // set back to "0" + err = se.SetGlobalSysVar(varName, defaultValue) + c.Assert(err, IsNil) + v, err = se.GetGlobalSysVar(varName) + tk.MustQuery("select @@global.tidb_general_log").Check(testkit.Rows("0")) + c.Assert(err, IsNil) + c.Assert(v, Equals, defaultValue) } func (s *testSessionSuite) TestMatchIdentity(c *C) { @@ -2103,17 +2201,30 @@ func (s *testSessionSuite2) TestDeletePanic(c *C) { func (s *testSessionSuite2) TestInformationSchemaCreateTime(c *C) { tk := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("create table t (c int)") + tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) ret := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") // Make sure t1 is greater than t. time.Sleep(time.Second) tk.MustExec("alter table t modify c int default 11") ret1 := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") + ret2 := tk.MustQuery("show table status like 't'") + c.Assert(ret1.Rows()[0][0].(string), Equals, ret2.Rows()[0][11].(string)) t, err := types.ParseDatetime(nil, ret.Rows()[0][0].(string)) c.Assert(err, IsNil) t1, err := types.ParseDatetime(nil, ret1.Rows()[0][0].(string)) c.Assert(err, IsNil) r := t1.Compare(t) c.Assert(r, Equals, 1) + // Check that time_zone changes makes the create_time different + tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) + ret = tk.MustQuery(`select create_time from information_schema.tables where table_name='t'`) + ret2 = tk.MustQuery(`show table status like 't'`) + c.Assert(ret.Rows()[0][0].(string), Equals, ret2.Rows()[0][11].(string)) + t, err = types.ParseDatetime(nil, ret.Rows()[0][0].(string)) + c.Assert(err, IsNil) + // Asia/Shanghai 2022-02-17 17:40:05 > Europe/Amsterdam 2022-02-17 10:40:05 + r = t1.Compare(t) + c.Assert(r, Equals, 1) } type testSchemaSuiteBase struct { @@ -2162,11 +2273,13 @@ func (s *testSchemaSuiteBase) TearDownSuite(c *C) { } func (s *testSchemaSerialSuite) TestLoadSchemaFailed(c *C) { - atomic.StoreInt32(&domain.SchemaOutOfDateRetryTimes, int32(3)) - atomic.StoreInt64(&domain.SchemaOutOfDateRetryInterval, int64(20*time.Millisecond)) + originalRetryTime := domain.SchemaOutOfDateRetryTimes.Load() + originalRetryInterval := domain.SchemaOutOfDateRetryInterval.Load() + domain.SchemaOutOfDateRetryTimes.Store(3) + domain.SchemaOutOfDateRetryInterval.Store(20 * time.Millisecond) defer func() { - atomic.StoreInt32(&domain.SchemaOutOfDateRetryTimes, 10) - atomic.StoreInt64(&domain.SchemaOutOfDateRetryInterval, int64(500*time.Millisecond)) + domain.SchemaOutOfDateRetryTimes.Store(originalRetryTime) + domain.SchemaOutOfDateRetryInterval.Store(originalRetryInterval) }() tk := testkit.NewTestKitWithInit(c, s.store) @@ -2268,6 +2381,36 @@ func (s *testSchemaSerialSuite) TestSchemaCheckerSQL(c *C) { tk.MustQuery(`select * from t for update`) _, err = tk.Exec(`commit;`) c.Assert(err, NotNil) + + // Repeated tests for partitioned table + tk.MustExec(`create table pt (id int, c int) partition by hash (id) partitions 3`) + tk.MustExec(`insert into pt values(1, 1);`) + // The schema version is out of date in the first transaction, and the SQL can't be retried. + tk.MustExec(`begin;`) + tk1.MustExec(`alter table pt modify column c bigint;`) + tk.MustExec(`insert into pt values(3, 3);`) + _, err = tk.Exec(`commit;`) + c.Assert(terror.ErrorEqual(err, domain.ErrInfoSchemaChanged), IsTrue, Commentf("err %v", err)) + + // But the transaction related table IDs aren't in the updated table IDs. + tk.MustExec(`begin;`) + tk1.MustExec(`alter table pt add index idx2(c);`) + tk.MustExec(`insert into t1 values(4, 4);`) + tk.MustExec(`commit;`) + + // Test for "select for update". + tk.MustExec(`begin;`) + tk1.MustExec(`alter table pt add index idx3(c);`) + tk.MustQuery(`select * from pt for update`) + _, err = tk.Exec(`commit;`) + c.Assert(err, NotNil) + + // Test for "select for update". + tk.MustExec(`begin;`) + tk1.MustExec(`alter table pt add index idx4(c);`) + tk.MustQuery(`select * from pt partition (p1) for update`) + _, err = tk.Exec(`commit;`) + c.Assert(err, NotNil) } func (s *testSchemaSerialSuite) TestSchemaCheckerTempTable(c *C) { @@ -2932,7 +3075,7 @@ func (s *testSessionSuite2) TestHostLengthMax(c *C) { tk.MustExec(fmt.Sprintf(`CREATE USER 'abcddfjakldfjaldddds'@'%s'`, host1)) err := tk.ExecToErr(fmt.Sprintf(`CREATE USER 'abcddfjakldfjaldddds'@'%s'`, host2)) - c.Assert(err.Error(), Equals, "[types:1406]Data too long for column 'Host' at row 1") + c.Assert(err.Error(), Equals, "[ddl:1470]String 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long for host name (should be no longer than 255)") } func (s *testSessionSerialSuite) TestKVVars(c *C) { @@ -3058,7 +3201,8 @@ func (s *testSchemaSuite) TestDisableTxnAutoRetry(c *C) { // session 1 starts a transaction early. // execute a select statement to clear retry history. tk1.MustExec("select 1") - tk1.Se.PrepareTxnCtx(context.Background()) + err = tk1.Se.PrepareTxnCtx(context.Background()) + c.Assert(err, IsNil) // session 2 update the value. tk2.MustExec("update no_retry set id = 4") // AutoCommit update will retry, so it would not fail. @@ -3159,7 +3303,7 @@ func (s *testSessionSuite2) TestSetGroupConcatMaxLen(c *C) { // Test value out of range tk.MustExec("set @@group_concat_max_len=1") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect group_concat_max_len value: '1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect group_concat_max_len value: '1'")) result = tk.MustQuery("select @@group_concat_max_len;") result.Check(testkit.Rows("4")) @@ -3725,6 +3869,7 @@ PARTITION BY RANGE (c) ( result = tk.MustQuery("select * from t1") c.Assert(len(result.Rows()), Equals, 2) + timeBeforeWriting := time.Now() tk.MustExec("insert into t1 (c) values (101)") // write dc-2 with global scope result = tk.MustQuery("select * from t1") // read dc-1 and dc-2 with global scope c.Assert(len(result.Rows()), Equals, 3) @@ -3737,7 +3882,9 @@ PARTITION BY RANGE (c) ( result.Check(testkit.Rows("local")) // test local txn auto commit - tk.MustExec("insert into t1 (c) values (1)") // write dc-1 with dc-1 scope + tk.MustExec("insert into t1 (c) values (1)") // write dc-1 with dc-1 scope + result = tk.MustQuery("select * from t1 where c = 1") // point get dc-1 with dc-1 scope + c.Assert(len(result.Rows()), Equals, 3) result = tk.MustQuery("select * from t1 where c < 100") // read dc-1 with dc-1 scope c.Assert(len(result.Rows()), Equals, 3) @@ -3773,7 +3920,16 @@ PARTITION BY RANGE (c) ( _, err = tk.Exec("insert into t1 (c) values (101)") // write dc-2 with dc-1 scope c.Assert(err, NotNil) c.Assert(err.Error(), Matches, ".*out of txn_scope.*") + err = tk.ExecToErr("select * from t1 where c = 101") // point get dc-2 with dc-1 scope + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, ".*can not be read by.*") + err = tk.ExecToErr("select * from t1 where c > 100") // read dc-2 with dc-1 scope + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, ".*can not be read by.*") tk.MustExec("begin") + err = tk.ExecToErr("select * from t1 where c = 101") // point get dc-2 with dc-1 scope + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, ".*can not be read by.*") err = tk.ExecToErr("select * from t1 where c > 100") // read dc-2 with dc-1 scope c.Assert(err, NotNil) c.Assert(err.Error(), Matches, ".*can not be read by.*") @@ -3799,6 +3955,30 @@ PARTITION BY RANGE (c) ( // Won't read the value 99 because the previous commit failed result = tk.MustQuery("select * from t1 where c < 100") // read dc-1 with dc-1 scope c.Assert(len(result.Rows()), Equals, 4) + + // Stale Read will ignore the cross-dc txn scope. + c.Assert(tk.Se.GetSessionVars().CheckAndGetTxnScope(), Equals, "dc-1") + result = tk.MustQuery("select @@txn_scope;") + result.Check(testkit.Rows("local")) + err = tk.ExecToErr("select * from t1 where c > 100") // read dc-2 with dc-1 scope + c.Assert(err, NotNil) + c.Assert(err.Error(), Matches, ".*can not be read by.*") + // Read dc-2 with Stale Read (in dc-1 scope) + timestamp := timeBeforeWriting.Format(time.RFC3339Nano) + // TODO: check the result of Stale Read when we figure out how to make the time precision more accurate. + tk.MustExec(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%s' where c = 101", timestamp)) + tk.MustExec(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%s' where c > 100", timestamp)) + tk.MustExec(fmt.Sprintf("START TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", timestamp)) + tk.MustExec("select * from t1 where c = 101") + tk.MustExec("select * from t1 where c > 100") + tk.MustExec("commit") + tk.MustExec("set @@tidb_replica_read='closest-replicas'") + tk.MustExec(fmt.Sprintf("select * from t1 AS OF TIMESTAMP '%s' where c > 100", timestamp)) + tk.MustExec(fmt.Sprintf("START TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", timestamp)) + tk.MustExec("select * from t1 where c = 101") + tk.MustExec("select * from t1 where c > 100") + tk.MustExec("commit") + tk.MustExec("set global tidb_enable_local_txn = off;") } @@ -3807,6 +3987,18 @@ func (s *testSessionSuite2) TestSetEnableRateLimitAction(c *C) { // assert default value result := tk.MustQuery("select @@tidb_enable_rate_limit_action;") result.Check(testkit.Rows("1")) + tk.MustExec("use test") + tk.MustExec("create table tmp123(id int)") + tk.MustQuery("select * from tmp123;") + haveRateLimitAction := false + action := tk.Se.GetSessionVars().StmtCtx.MemTracker.GetFallbackForTest() + for ; action != nil; action = action.GetFallback() { + if action.GetPriority() == memory.DefRateLimitPriority { + haveRateLimitAction = true + break + } + } + c.Assert(haveRateLimitAction, IsTrue) // assert set sys variable tk.MustExec("set global tidb_enable_rate_limit_action= '0';") @@ -3817,6 +4009,16 @@ func (s *testSessionSuite2) TestSetEnableRateLimitAction(c *C) { tk.Se = se result = tk.MustQuery("select @@tidb_enable_rate_limit_action;") result.Check(testkit.Rows("0")) + + haveRateLimitAction = false + action = tk.Se.GetSessionVars().StmtCtx.MemTracker.GetFallbackForTest() + for ; action != nil; action = action.GetFallback() { + if action.GetPriority() == memory.DefRateLimitPriority { + haveRateLimitAction = true + break + } + } + c.Assert(haveRateLimitAction, IsFalse) } func (s *testSessionSuite3) TestSetVarHint(c *C) { @@ -4017,7 +4219,7 @@ func (s *testSessionSerialSuite) TestDoDDLJobQuit(c *C) { defer failpoint.Disable("github.com/pingcap/tidb/ddl/storeCloseInLoop") // this DDL call will enter deadloop before this fix - err = dom.DDL().CreateSchema(se, model.NewCIStr("testschema"), nil, nil, nil) + err = dom.DDL().CreateSchema(se, model.NewCIStr("testschema"), nil, nil) c.Assert(err.Error(), Equals, "context canceled") } @@ -4363,12 +4565,10 @@ func (s *testSessionSerialSuite) TestProcessInfoIssue22068(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") tk.MustExec("create table t(a int)") - wg := sync.WaitGroup{} - wg.Add(1) - go func() { + var wg util.WaitGroupWrapper + wg.Run(func() { tk.MustQuery("select 1 from t where a = (select sleep(5));").Check(testkit.Rows()) - wg.Done() - }() + }) time.Sleep(2 * time.Second) pi := tk.Se.ShowProcess() c.Assert(pi, NotNil) @@ -4383,11 +4583,6 @@ func (s *testSessionSerialSuite) TestParseWithParams(c *C) { exec := se.(sqlexec.RestrictedSQLExecutor) // test compatibility with ExcuteInternal - origin := se.GetSessionVars().InRestrictedSQL - se.GetSessionVars().InRestrictedSQL = true - defer func() { - se.GetSessionVars().InRestrictedSQL = origin - }() _, err := exec.ParseWithParams(context.TODO(), "SELECT 4") c.Assert(err, IsNil) @@ -4873,8 +5068,6 @@ func (s *testStatisticsSuite) cleanEnv(c *C, store kv.Storage, do *domain.Domain } func (s *testStatisticsSuite) TestNewCollationStatsWithPrefixIndex(c *C) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) defer s.cleanEnv(c, s.store, s.dom) tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") @@ -5424,7 +5617,7 @@ func (s *testSessionSuite) TestLocalTemporaryTableScan(c *C) { "12 112 1012", "3 113 1003", "14 114 1014", "16 116 1016", "7 117 1007", "18 118 1018", )) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled. Cannot use IndexMerge on temporary table.")) } doModify := func() { @@ -5463,7 +5656,7 @@ func (s *testSessionSuite) TestLocalTemporaryTableScan(c *C) { "3 113 1003", "14 114 1014", "7 117 9999", "18 118 1018", "12 132 1012", )) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled. Cannot use IndexMerge on temporary table.")) } assertSelectAsUnModified() @@ -5752,6 +5945,7 @@ func (s *testTiDBAsLibrary) TestMemoryLeak(c *C) { func (s *testSessionSuite) TestTiDBReadStaleness(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("set @@tidb_read_staleness='-5'") + tk.MustExec("set @@tidb_read_staleness='-100'") err := tk.ExecToErr("set @@tidb_read_staleness='-5s'") c.Assert(err, NotNil) err = tk.ExecToErr("set @@tidb_read_staleness='foo'") @@ -5799,16 +5993,16 @@ func (s *testSessionSuite) TestSetPDClientDynmaicOption(c *C) { err = tk.ExecToErr("set tidb_tso_client_batch_max_wait_time = 0;") c.Assert(err, NotNil) tk.MustExec("set global tidb_tso_client_batch_max_wait_time = -1;") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '-1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '-1'")) tk.MustQuery("select @@tidb_tso_client_batch_max_wait_time;").Check(testkit.Rows("0")) tk.MustExec("set global tidb_tso_client_batch_max_wait_time = -0.1;") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '-0.1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '-0.1'")) tk.MustQuery("select @@tidb_tso_client_batch_max_wait_time;").Check(testkit.Rows("0")) tk.MustExec("set global tidb_tso_client_batch_max_wait_time = 10.1;") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '10.1'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '10.1'")) tk.MustQuery("select @@tidb_tso_client_batch_max_wait_time;").Check(testkit.Rows("10")) tk.MustExec("set global tidb_tso_client_batch_max_wait_time = 11;") - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '11'")) + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1292|Truncated incorrect tidb_tso_client_batch_max_wait_time value: '11'")) tk.MustQuery("select @@tidb_tso_client_batch_max_wait_time;").Check(testkit.Rows("10")) tk.MustQuery("select @@tidb_enable_tso_follower_proxy;").Check(testkit.Rows("0")) @@ -5895,13 +6089,16 @@ func (s *testSessionSuite) TestWriteOnMultipleCachedTable(c *C) { tk.MustQuery("select * from ct1").Check(testkit.Rows()) tk.MustQuery("select * from ct2").Check(testkit.Rows()) + lastReadFromCache := func(tk *testkit.TestKit) bool { + return tk.Se.GetSessionVars().StmtCtx.ReadFromTableCache + } + cached := false for i := 0; i < 50; i++ { - if tk.HasPlan("select * from ct1", "Union") { - if tk.HasPlan("select * from ct2", "Union") { - cached = true - break - } + tk.MustQuery("select * from ct1") + if lastReadFromCache(tk) { + cached = true + break } time.Sleep(100 * time.Millisecond) } @@ -5914,4 +6111,61 @@ func (s *testSessionSuite) TestWriteOnMultipleCachedTable(c *C) { tk.MustQuery("select * from ct1").Check(testkit.Rows("3 4")) tk.MustQuery("select * from ct2").Check(testkit.Rows("5 6")) + + // cleanup + tk.MustExec("alter table ct1 nocache") + tk.MustExec("alter table ct2 nocache") +} + +func (s *testSessionSuite) TestForbidSettingBothTSVariable(c *C) { + tk := testkit.NewTestKit(c, s.store) + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20060102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + + // Set tidb_snapshot and assert tidb_read_staleness + tk.MustExec("set @@tidb_snapshot = '2007-01-01 15:04:05.999999'") + _, err := tk.Exec("set @@tidb_read_staleness='-5'") + c.Assert(err, NotNil) + c.Assert(err.Error(), Equals, "tidb_snapshot should be clear before setting tidb_read_staleness") + tk.MustExec("set @@tidb_snapshot = ''") + tk.MustExec("set @@tidb_read_staleness='-5'") + + // Set tidb_read_staleness and assert tidb_snapshot + tk.MustExec("set @@tidb_read_staleness='-5'") + _, err = tk.Exec("set @@tidb_snapshot = '2007-01-01 15:04:05.999999'") + c.Assert(err, NotNil) + c.Assert(err.Error(), Equals, "tidb_read_staleness should be clear before setting tidb_snapshot") + tk.MustExec("set @@tidb_read_staleness = ''") + tk.MustExec("set @@tidb_snapshot = '2007-01-01 15:04:05.999999'") +} + +func (s *testSessionSuite) TestSysdateIsNow(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustQuery("show variables like '%tidb_sysdate_is_now%'").Check(testkit.Rows("tidb_sysdate_is_now OFF")) + c.Assert(tk.Se.GetSessionVars().SysdateIsNow, IsFalse) + tk.MustExec("set @@tidb_sysdate_is_now=true") + tk.MustQuery("show variables like '%tidb_sysdate_is_now%'").Check(testkit.Rows("tidb_sysdate_is_now ON")) + c.Assert(tk.Se.GetSessionVars().SysdateIsNow, IsTrue) +} + +func (s *testSessionSuite) TestEnableLegacyInstanceScope(c *C) { + tk := testkit.NewTestKit(c, s.store) + + // enable 'switching' to SESSION variables + tk.MustExec("set tidb_enable_legacy_instance_scope = 1") + tk.MustExec("set tidb_general_log = 1") + tk.MustQuery(`show warnings`).Check(testkit.Rows(fmt.Sprintf("Warning %d modifying tidb_general_log will require SET GLOBAL in a future version of TiDB", errno.ErrInstanceScope))) + c.Assert(tk.Se.GetSessionVars().EnableLegacyInstanceScope, IsTrue) + + // disable 'switching' to SESSION variables + tk.MustExec("set tidb_enable_legacy_instance_scope = 0") + tk.MustGetErrCode("set tidb_general_log = 1", errno.ErrGlobalVariable) + c.Assert(tk.Se.GetSessionVars().EnableLegacyInstanceScope, IsFalse) } diff --git a/session/tidb.go b/session/tidb.go index 911e64f3727f2..99ab58644d275 100644 --- a/session/tidb.go +++ b/session/tidb.go @@ -44,12 +44,11 @@ import ( type domainMap struct { domains map[string]*domain.Domain - mu sync.Mutex + mu sync.RWMutex } func (dm *domainMap) Get(store kv.Storage) (d *domain.Domain, err error) { - dm.mu.Lock() - defer dm.mu.Unlock() + dm.mu.RLock() // If this is the only domain instance, and the caller doesn't provide store. if len(dm.domains) == 1 && store == nil { @@ -60,6 +59,7 @@ func (dm *domainMap) Get(store kv.Storage) (d *domain.Domain, err error) { key := store.UUID() d = dm.domains[key] + dm.mu.RUnlock() if d != nil { return } @@ -92,7 +92,7 @@ func (dm *domainMap) Get(store kv.Storage) (d *domain.Domain, err error) { if err != nil { return nil, err } - dm.domains[key] = d + dm.Set(store, d) return } @@ -103,6 +103,12 @@ func (dm *domainMap) Delete(store kv.Storage) { dm.mu.Unlock() } +func (dm *domainMap) Set(store kv.Storage, domain *domain.Domain) { + dm.mu.Lock() + dm.domains[store.UUID()] = domain + dm.mu.Unlock() +} + var ( domap = &domainMap{ domains: map[string]*domain.Domain{}, diff --git a/session/tidb_test.go b/session/tidb_test.go index 661a8f19d5f47..70831a8f64d89 100644 --- a/session/tidb_test.go +++ b/session/tidb_test.go @@ -16,13 +16,13 @@ package session import ( "context" - "sync" "testing" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/util" "github.com/stretchr/testify/require" ) @@ -43,14 +43,13 @@ func TestSysSessionPoolGoroutineLeak(t *testing.T) { } // Test an issue that sysSessionPool doesn't call session's Close, cause // asyncGetTSWorker goroutine leak. - var wg sync.WaitGroup - wg.Add(count) + var wg util.WaitGroupWrapper for i := 0; i < count; i++ { - go func(se *session, stmt ast.StmtNode) { - _, _, err := se.ExecRestrictedStmt(context.Background(), stmt) + s := stmts[i] + wg.Run(func() { + _, _, err := se.ExecRestrictedStmt(context.Background(), s) require.NoError(t, err) - wg.Done() - }(se, stmts[i]) + }) } wg.Wait() } diff --git a/session/txn.go b/session/txn.go index 2ed83e89c2fde..ce36621ba8afe 100644 --- a/session/txn.go +++ b/session/txn.go @@ -488,6 +488,7 @@ type txnFuture struct { func (tf *txnFuture) wait() (kv.Transaction, error) { startTS, err := tf.future.Wait() + failpoint.Inject("txnFutureWait", func() {}) if err == nil { return tf.store.Begin(tikv.WithTxnScope(tf.txnScope), tikv.WithStartTS(startTS)) } else if config.GetGlobalConfig().Store == "unistore" { diff --git a/session/txnmanager.go b/session/txnmanager.go new file mode 100644 index 0000000000000..0e47a8cf7406a --- /dev/null +++ b/session/txnmanager.go @@ -0,0 +1,62 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package session + +import ( + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessiontxn" +) + +func init() { + sessiontxn.GetTxnManager = getTxnManager +} + +func getTxnManager(sctx sessionctx.Context) sessiontxn.TxnManager { + if manager, ok := sctx.GetSessionVars().TxnManager.(sessiontxn.TxnManager); ok { + return manager + } + + manager := newTxnManager(sctx) + sctx.GetSessionVars().TxnManager = manager + return manager +} + +// txnManager implements sessiontxn.TxnManager +type txnManager struct { + sctx sessionctx.Context + + ctxProvider sessiontxn.TxnContextProvider +} + +func newTxnManager(sctx sessionctx.Context) *txnManager { + return &txnManager{sctx: sctx} +} + +func (m *txnManager) GetTxnInfoSchema() infoschema.InfoSchema { + if m.ctxProvider == nil { + return nil + } + return m.ctxProvider.GetTxnInfoSchema() +} + +func (m *txnManager) GetContextProvider() sessiontxn.TxnContextProvider { + return m.ctxProvider +} + +func (m *txnManager) SetContextProvider(provider sessiontxn.TxnContextProvider) error { + m.ctxProvider = provider + return nil +} diff --git a/sessionctx/binloginfo/binloginfo.go b/sessionctx/binloginfo/binloginfo.go index 78c1b124de72b..5b29dd91c5b6b 100644 --- a/sessionctx/binloginfo/binloginfo.go +++ b/sessionctx/binloginfo/binloginfo.go @@ -15,22 +15,21 @@ package binloginfo import ( - "math" - "regexp" "strings" "sync" "sync/atomic" "time" "github.com/pingcap/errors" - "github.com/pingcap/tidb-tools/tidb-binlog/node" - pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/format" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" - driver "github.com/pingcap/tidb/types/parser_driver" + "github.com/pingcap/tidb/tidb-binlog/node" + pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tipb/go-binlog" "go.uber.org/zap" @@ -45,8 +44,6 @@ func init() { // shared by all sessions. var pumpsClient *pumpcli.PumpsClient var pumpsClientLock sync.RWMutex -var shardPat = regexp.MustCompile(`(?PSHARD_ROW_ID_BITS\s*=\s*\d+\s*)`) -var preSplitPat = regexp.MustCompile(`(?PPRE_SPLIT_REGIONS\s*=\s*\d+\s*)`) // BinlogInfo contains binlog data and binlog client. type BinlogInfo struct { @@ -283,7 +280,11 @@ func SetDDLBinlog(client *pumpcli.PumpsClient, txn kv.Transaction, jobID int64, return } - ddlQuery = AddSpecialComment(ddlQuery) + if commented, err := FormatAndAddTiDBSpecificComment(ddlQuery); err == nil { + ddlQuery = commented + } else { + logutil.BgLogger().Warn("Unable to add TiDB-specified comment for DDL query.", zap.String("DDL Query", ddlQuery), zap.Error(err)) + } info := &BinlogInfo{ Data: &binlog.Binlog{ Tp: binlog.BinlogType_Prewrite, @@ -296,71 +297,6 @@ func SetDDLBinlog(client *pumpcli.PumpsClient, txn kv.Transaction, jobID int64, txn.SetOption(kv.BinlogInfo, info) } -const specialPrefix = `/*T! ` - -// AddSpecialComment uses to add comment for table option in DDL query. -// Used by pingcap/ticdc. -func AddSpecialComment(ddlQuery string) string { - if strings.Contains(ddlQuery, specialPrefix) || strings.Contains(ddlQuery, driver.SpecialCommentVersionPrefix) { - return ddlQuery - } - ddlQuery = addSpecialCommentByRegexps(ddlQuery, specialPrefix, shardPat, preSplitPat) - for featureID, pattern := range driver.FeatureIDPatterns { - ddlQuery = addSpecialCommentByRegexps(ddlQuery, driver.BuildSpecialCommentPrefix(featureID), pattern) - } - return ddlQuery -} - -// addSpecialCommentByRegexps uses to add special comment for the worlds in the ddlQuery with match the regexps. -// addSpecialCommentByRegexps will merge multi pattern regs to one special comment. -func addSpecialCommentByRegexps(ddlQuery string, prefix string, regs ...*regexp.Regexp) string { - upperQuery := strings.ToUpper(ddlQuery) - var specialComments []string - minIdx := math.MaxInt64 - for i := 0; i < len(regs); { - reg := regs[i] - locs := reg.FindStringSubmatchIndex(upperQuery) - ns := reg.SubexpNames() - var loc []int - if len(locs) > 0 { - for i, n := range ns { - if n == "REPLACE" { - loc = locs[i*2 : (i+1)*2] - break - } - } - } - if len(loc) < 2 { - i++ - continue - } - specialComments = append(specialComments, ddlQuery[loc[0]:loc[1]]) - if loc[0] < minIdx { - minIdx = loc[0] - } - ddlQuery = ddlQuery[:loc[0]] + ddlQuery[loc[1]:] - upperQuery = upperQuery[:loc[0]] + upperQuery[loc[1]:] - } - if minIdx != math.MaxInt64 { - query := ddlQuery[:minIdx] + prefix - for _, comment := range specialComments { - if query[len(query)-1] != ' ' { - query += " " - } - query += comment - } - if query[len(query)-1] != ' ' { - query += " " - } - query += "*/" - if len(ddlQuery[minIdx:]) > 0 { - return query + " " + ddlQuery[minIdx:] - } - return query - } - return ddlQuery -} - // MockPumpsClient creates a PumpsClient, used for test. func MockPumpsClient(client binlog.PumpClient) *pumpcli.PumpsClient { nodeID := "pump-1" @@ -390,3 +326,28 @@ func MockPumpsClient(client binlog.PumpClient) *pumpcli.PumpsClient { return pCli } + +// FormatAndAddTiDBSpecificComment translate tidb feature syntax to tidb-specified comment. +// ddlQuery can be multiple-statements separated by ';' and the statement can be empty. +func FormatAndAddTiDBSpecificComment(ddlQuery string) (string, error) { + stmts, _, err := parser.New().ParseSQL(ddlQuery) + if err != nil { + return "", errors.Trace(err) + } + var sb strings.Builder + // translate TiDB feature to special comment + restoreFlags := format.RestoreTiDBSpecialComment + // escape the keyword + restoreFlags |= format.RestoreNameBackQuotes + // upper case keyword + restoreFlags |= format.RestoreKeyWordUppercase + // wrap string with single quote + restoreFlags |= format.RestoreStringSingleQuotes + for _, stmt := range stmts { + if err = stmt.Restore(format.NewRestoreCtx(restoreFlags, &sb)); err != nil { + return "", errors.Trace(err) + } + sb.WriteString(";") + } + return sb.String(), nil +} diff --git a/sessionctx/binloginfo/binloginfo_test.go b/sessionctx/binloginfo/binloginfo_test.go index 511db81cd81ad..59f0157fa499d 100644 --- a/sessionctx/binloginfo/binloginfo_test.go +++ b/sessionctx/binloginfo/binloginfo_test.go @@ -26,23 +26,22 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" - pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/binloginfo" "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" + pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" - binlog "github.com/pingcap/tipb/go-binlog" + "github.com/pingcap/tipb/go-binlog" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) @@ -112,6 +111,7 @@ func createBinlogSuite(t *testing.T) (s *binlogSuite, clean func()) { s.ddl.SetBinlogClient(s.client) clean = func() { + clientCon.Close() err = s.ddl.Stop() require.NoError(t, err) s.serv.Stop() @@ -328,7 +328,9 @@ func getLatestDDLBinlog(t *testing.T, pump *mockBinlogPump, ddlQuery string) (pr require.Greater(t, preDDL.DdlJobId, int64(0)) require.Greater(t, preDDL.StartTs, int64(0)) require.Equal(t, int64(0), preDDL.CommitTs) - require.Equal(t, ddlQuery, string(preDDL.DdlQuery)) + formatted, err := binloginfo.FormatAndAddTiDBSpecificComment(ddlQuery) + require.NoError(t, err, "ddlQuery: %s", ddlQuery) + require.Equal(t, formatted, string(preDDL.DdlQuery)) return } @@ -402,7 +404,7 @@ func TestBinlogForSequence(t *testing.T) { tk.MustExec("create sequence seq cache 3") // trigger the sequence cache allocation. tk.MustQuery("select nextval(seq)").Check(testkit.Rows("1")) - sequenceTable := testGetTableByName(t, tk.Session(), "test", "seq") + sequenceTable := external.GetTableByName(t, tk, "test", "seq") tc, ok := sequenceTable.(*tables.TableCommon) require.Equal(t, true, ok) _, end, round := tc.GetSequenceCommon().GetSequenceBaseEndRound() @@ -430,7 +432,7 @@ func TestBinlogForSequence(t *testing.T) { tk.MustExec("create sequence seq2 start 1 increment -2 cache 3 minvalue -10 maxvalue 10 cycle") // trigger the sequence cache allocation. tk.MustQuery("select nextval(seq2)").Check(testkit.Rows("1")) - sequenceTable = testGetTableByName(t, tk.Session(), "test2", "seq2") + sequenceTable = external.GetTableByName(t, tk, "test2", "seq2") tc, ok = sequenceTable.(*tables.TableCommon) require.Equal(t, true, ok) _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() @@ -549,136 +551,161 @@ func TestDeleteSchema(t *testing.T) { tk.MustExec("delete b1 from b2 right join b1 on b1.job_id = b2.job_id and batch_class = 'TEST';") } -func TestAddSpecialComment(t *testing.T) { +func TestFormatAndAddTiDBSpecificComment(t *testing.T) { testCase := []struct { input string result string }{ { "create table t1 (id int ) shard_row_id_bits=2;", - "create table t1 (id int ) /*T! shard_row_id_bits=2 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T! SHARD_ROW_ID_BITS = 2 */;", }, { "create table t1 (id int ) shard_row_id_bits=2 pre_split_regions=2;", - "create table t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T! SHARD_ROW_ID_BITS = 2 */ /*T! PRE_SPLIT_REGIONS = 2 */;", }, { "create table t1 (id int ) shard_row_id_bits=2 pre_split_regions=2;", - "create table t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T! SHARD_ROW_ID_BITS = 2 */ /*T! PRE_SPLIT_REGIONS = 2 */;", }, - { "create table t1 (id int ) shard_row_id_bits=2 engine=innodb pre_split_regions=2;", - "create table t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ engine=innodb ;", + "CREATE TABLE `t1` (`id` INT) /*T! SHARD_ROW_ID_BITS = 2 */ ENGINE = innodb /*T! PRE_SPLIT_REGIONS = 2 */;", }, { "create table t1 (id int ) pre_split_regions=2 shard_row_id_bits=2;", - "create table t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T! PRE_SPLIT_REGIONS = 2 */ /*T! SHARD_ROW_ID_BITS = 2 */;", }, { "create table t6 (id int ) shard_row_id_bits=2 shard_row_id_bits=3 pre_split_regions=2;", - "create table t6 (id int ) /*T! shard_row_id_bits=2 shard_row_id_bits=3 pre_split_regions=2 */ ;", + "CREATE TABLE `t6` (`id` INT) /*T! SHARD_ROW_ID_BITS = 2 */ /*T! SHARD_ROW_ID_BITS = 3 */ /*T! PRE_SPLIT_REGIONS = 2 */;", }, { "create table t1 (id int primary key auto_random(2));", - "create table t1 (id int primary key /*T![auto_rand] auto_random(2) */ );", + "CREATE TABLE `t1` (`id` INT PRIMARY KEY /*T![auto_rand] AUTO_RANDOM(2) */);", }, { "create table t1 (id int primary key auto_random);", - "create table t1 (id int primary key /*T![auto_rand] auto_random */ );", + "CREATE TABLE `t1` (`id` INT PRIMARY KEY /*T![auto_rand] AUTO_RANDOM */);", }, { "create table t1 (id int auto_random ( 4 ) primary key);", - "create table t1 (id int /*T![auto_rand] auto_random ( 4 ) */ primary key);", + "CREATE TABLE `t1` (`id` INT /*T![auto_rand] AUTO_RANDOM(4) */ PRIMARY KEY);", }, { "create table t1 (id int auto_random ( 4 ) primary key);", - "create table t1 (id int /*T![auto_rand] auto_random ( 4 ) */ primary key);", + "CREATE TABLE `t1` (`id` INT /*T![auto_rand] AUTO_RANDOM(4) */ PRIMARY KEY);", }, { "create table t1 (id int auto_random ( 3 ) primary key) auto_random_base = 100;", - "create table t1 (id int /*T![auto_rand] auto_random ( 3 ) */ primary key) /*T![auto_rand_base] auto_random_base = 100 */ ;", + "CREATE TABLE `t1` (`id` INT /*T![auto_rand] AUTO_RANDOM(3) */ PRIMARY KEY) /*T![auto_rand_base] AUTO_RANDOM_BASE = 100 */;", }, { "create table t1 (id int auto_random primary key) auto_random_base = 50;", - "create table t1 (id int /*T![auto_rand] auto_random */ primary key) /*T![auto_rand_base] auto_random_base = 50 */ ;", + "CREATE TABLE `t1` (`id` INT /*T![auto_rand] AUTO_RANDOM */ PRIMARY KEY) /*T![auto_rand_base] AUTO_RANDOM_BASE = 50 */;", }, { "create table t1 (id int auto_increment key) auto_id_cache 100;", - "create table t1 (id int auto_increment key) /*T![auto_id_cache] auto_id_cache 100 */ ;", + "CREATE TABLE `t1` (`id` INT AUTO_INCREMENT PRIMARY KEY) /*T![auto_id_cache] AUTO_ID_CACHE = 100 */;", }, { "create table t1 (id int auto_increment unique) auto_id_cache 10;", - "create table t1 (id int auto_increment unique) /*T![auto_id_cache] auto_id_cache 10 */ ;", + "CREATE TABLE `t1` (`id` INT AUTO_INCREMENT UNIQUE KEY) /*T![auto_id_cache] AUTO_ID_CACHE = 10 */;", }, { "create table t1 (id int) auto_id_cache = 5;", - "create table t1 (id int) /*T![auto_id_cache] auto_id_cache = 5 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T![auto_id_cache] AUTO_ID_CACHE = 5 */;", }, { "create table t1 (id int) auto_id_cache=5;", - "create table t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T![auto_id_cache] AUTO_ID_CACHE = 5 */;", }, { "create table t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", - "create table t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", + "CREATE TABLE `t1` (`id` INT) /*T![auto_id_cache] AUTO_ID_CACHE = 5 */;", }, { "create table t1 (id int, a varchar(255), primary key (a, b) clustered);", - "create table t1 (id int, a varchar(255), primary key (a, b) /*T![clustered_index] clustered */ );", + "CREATE TABLE `t1` (`id` INT,`a` VARCHAR(255),PRIMARY KEY(`a`, `b`) /*T![clustered_index] CLUSTERED */);", }, { "create table t1(id int, v int, primary key(a) clustered);", - "create table t1(id int, v int, primary key(a) /*T![clustered_index] clustered */ );", + "CREATE TABLE `t1` (`id` INT,`v` INT,PRIMARY KEY(`a`) /*T![clustered_index] CLUSTERED */);", }, { "create table t1(id int primary key clustered, v int);", - "create table t1(id int primary key /*T![clustered_index] clustered */ , v int);", + "CREATE TABLE `t1` (`id` INT PRIMARY KEY /*T![clustered_index] CLUSTERED */,`v` INT);", }, { "alter table t add primary key(a) clustered;", - "alter table t add primary key(a) /*T![clustered_index] clustered */ ;", + "ALTER TABLE `t` ADD PRIMARY KEY(`a`) /*T![clustered_index] CLUSTERED */;", }, { "create table t1 (id int, a varchar(255), primary key (a, b) nonclustered);", - "create table t1 (id int, a varchar(255), primary key (a, b) /*T![clustered_index] nonclustered */ );", + "CREATE TABLE `t1` (`id` INT,`a` VARCHAR(255),PRIMARY KEY(`a`, `b`) /*T![clustered_index] NONCLUSTERED */);", }, { "create table t1 (id int, a varchar(255), primary key (a, b) /*T![clustered_index] nonclustered */);", - "create table t1 (id int, a varchar(255), primary key (a, b) /*T![clustered_index] nonclustered */);", + "CREATE TABLE `t1` (`id` INT,`a` VARCHAR(255),PRIMARY KEY(`a`, `b`) /*T![clustered_index] NONCLUSTERED */);", }, { "create table clustered_test(id int)", - "create table clustered_test(id int)", + "CREATE TABLE `clustered_test` (`id` INT);", }, { "create database clustered_test", - "create database clustered_test", + "CREATE DATABASE `clustered_test`;", }, { "create database clustered", - "create database clustered", + "CREATE DATABASE `clustered`;", }, { "create table clustered (id int)", - "create table clustered (id int)", + "CREATE TABLE `clustered` (`id` INT);", }, { "create table t1 (id int, a varchar(255) key clustered);", - "create table t1 (id int, a varchar(255) key /*T![clustered_index] clustered */ );", + "CREATE TABLE `t1` (`id` INT,`a` VARCHAR(255) PRIMARY KEY /*T![clustered_index] CLUSTERED */);", }, { "alter table t force auto_increment = 12;", - "alter table t /*T![force_inc] force */ auto_increment = 12;", + "ALTER TABLE `t` /*T![force_inc] FORCE */ AUTO_INCREMENT = 12;", }, { "alter table t force, auto_increment = 12;", - "alter table t force, auto_increment = 12;", + "ALTER TABLE `t` FORCE /* AlterTableForce is not supported */ , AUTO_INCREMENT = 12;", + }, + { + // https://github.com/pingcap/tiflow/issues/3755 + "create table cdc_test (id varchar(10) primary key ,c1 varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin/*!90000 SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=3 */", + "CREATE TABLE `cdc_test` (`id` VARCHAR(10) PRIMARY KEY,`c1` VARCHAR(10)) ENGINE = InnoDB DEFAULT CHARACTER SET = UTF8MB4 DEFAULT COLLATE = UTF8MB4_BIN /*T! SHARD_ROW_ID_BITS = 4 */ /*T! PRE_SPLIT_REGIONS = 3 */;", + }, + { + "create table clustered (id int); create table t1 (id int, a varchar(255) key clustered); ", + "CREATE TABLE `clustered` (`id` INT);CREATE TABLE `t1` (`id` INT,`a` VARCHAR(255) PRIMARY KEY /*T![clustered_index] CLUSTERED */);", + }, + { + "", + "", + }, + { + ";;", + "", + }, + { + "alter table t cache", + "ALTER TABLE `t` CACHE;", + }, + { + "alter table t nocache", + "ALTER TABLE `t` NOCACHE;", }, } for _, ca := range testCase { - re := binloginfo.AddSpecialComment(ca.input) + re, err := binloginfo.FormatAndAddTiDBSpecificComment(ca.input) require.Equal(t, ca.result, re) + require.NoError(t, err, "Unexpected error for AddTiDBSpecificComment, test input: %s", ca.input) } } @@ -698,16 +725,6 @@ func mustGetDDLBinlog(s *binlogSuite, ddlQuery string, t *testing.T) (matched bo return } -func testGetTableByName(t *testing.T, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - require.NoError(t, err) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - require.NoError(t, err) - return tbl -} - func TestTempTableBinlog(t *testing.T) { s, clean := createBinlogSuite(t) defer clean() @@ -785,6 +802,32 @@ func TestTempTableBinlog(t *testing.T) { require.True(t, ok) } +func TestAlterTableCache(t *testing.T) { + s, clean := createBinlogSuite(t) + defer clean() + + // Don't write binlog for 'ALTER TABLE t CACHE|NOCACHE'. + // Cached table is regarded as normal table. + + tk := testkit.NewTestKit(t, s.store) + tk.MustExec("use test") + tk.Session().GetSessionVars().BinlogClient = s.client + tk.MustExec("drop table if exists t") + ddlQuery := "create table t (id int)" + tk.MustExec(ddlQuery) + + tk.MustExec(`alter table t cache`) + // The latest DDL is still the previous one. + getLatestDDLBinlog(t, s.pump, ddlQuery) + + tk.MustExec("insert into t values (?)", 666) + prewriteVal := getLatestBinlogPrewriteValue(t, s.pump) + require.Equal(t, 1, len(prewriteVal.Mutations)) + + tk.MustExec(`alter table t nocache`) + getLatestDDLBinlog(t, s.pump, ddlQuery) +} + func TestIssue28292(t *testing.T) { s, clean := createBinlogSuite(t) defer clean() diff --git a/sessionctx/binloginfo/main_test.go b/sessionctx/binloginfo/main_test.go index 27abcdef3e02f..51a97bee98a96 100644 --- a/sessionctx/binloginfo/main_test.go +++ b/sessionctx/binloginfo/main_test.go @@ -22,12 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("google.golang.org/grpc.(*addrConn).resetTransport"), - goleak.IgnoreTopFunction("google.golang.org/grpc.(*ccBalancerWrapper).watcher"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), } goleak.VerifyTestMain(m, opts...) } diff --git a/sessionctx/context.go b/sessionctx/context.go index 2f9a50aa211f6..f7394a5e85e7e 100644 --- a/sessionctx/context.go +++ b/sessionctx/context.go @@ -28,6 +28,7 @@ import ( "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/kvcache" "github.com/pingcap/tidb/util/sli" + "github.com/pingcap/tidb/util/topsql/stmtstats" "github.com/pingcap/tipb/go-binlog" "github.com/tikv/client-go/v2/oracle" ) @@ -70,6 +71,7 @@ type Context interface { // ClearValue clears the value associated with this context for key. ClearValue(key fmt.Stringer) + // Deprecated: Use TxnManager.GetTxnInfoSchema to get the current schema in session GetInfoSchema() InfoschemaMetaVersion GetSessionVars() *variable.SessionVars @@ -101,6 +103,10 @@ type Context interface { // StoreQueryFeedback stores the query feedback. StoreQueryFeedback(feedback interface{}) + // UpdateColStatsUsage updates the column stats usage. + // TODO: maybe we can use a method called GetSessionStatsCollector to replace both StoreQueryFeedback and UpdateColStatsUsage but we need to deal with import circle if we do so. + UpdateColStatsUsage(predicateColumns []model.TableColumnID) + // HasDirtyContent checks whether there's dirty update on the given table. HasDirtyContent(tid int64) bool @@ -135,6 +141,13 @@ type Context interface { // GetBuiltinFunctionUsage returns the BuiltinFunctionUsage of current Context, which is not thread safe. // Use primitive map type to prevent circular import. Should convert it to telemetry.BuiltinFunctionUsage before using. GetBuiltinFunctionUsage() map[string]uint32 + // BuiltinFunctionUsageInc increase the counting of each builtin function usage + // Notice that this is a thread safe function + BuiltinFunctionUsageInc(scalarFuncSigName string) + // GetStmtStats returns stmtstats.StatementStats owned by implementation. + GetStmtStats() *stmtstats.StatementStats + // ShowProcess returns ProcessInfo running in current Context + ShowProcess() *util.ProcessInfo } type basicCtxType int @@ -198,3 +211,11 @@ func ValidateStaleReadTS(ctx context.Context, sctx Context, readTS uint64) error } return nil } + +// SysProcTracker is used to track background sys processes +type SysProcTracker interface { + Track(id uint64, proc Context) error + UnTrack(id uint64) + GetSysProcessList() map[uint64]*util.ProcessInfo + KillSysProcess(id uint64) +} diff --git a/sessionctx/main_test.go b/sessionctx/main_test.go index 89eeb11becb85..91943d5726ca9 100644 --- a/sessionctx/main_test.go +++ b/sessionctx/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/sessionctx/stmtctx/main_test.go b/sessionctx/stmtctx/main_test.go index 5ccfada0cec6c..444f2610ba5a8 100644 --- a/sessionctx/stmtctx/main_test.go +++ b/sessionctx/stmtctx/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/sessionctx/stmtctx/stmtctx.go b/sessionctx/stmtctx/stmtctx.go index e41eb4766b47b..a7eb8b0c69dd3 100644 --- a/sessionctx/stmtctx/stmtctx.go +++ b/sessionctx/stmtctx/stmtctx.go @@ -23,12 +23,14 @@ import ( "time" "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/util/disk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/resourcegrouptag" + "github.com/pingcap/tidb/util/topsql/stmtstats" "github.com/pingcap/tidb/util/tracing" "github.com/tikv/client-go/v2/tikvrpc" "github.com/tikv/client-go/v2/util" @@ -74,8 +76,10 @@ type StatementContext struct { InLoadDataStmt bool InExplainStmt bool InCreateOrAlterStmt bool + InPreparedPlanBuilding bool IgnoreTruncate bool IgnoreZeroInDate bool + NoZeroDate bool DupKeyAsWarning bool BadNullAsWarning bool DividedByZeroAsWarning bool @@ -89,6 +93,10 @@ type StatementContext struct { IgnoreNoPartition bool SkipPlanCache bool IgnoreExplainIDSuffix bool + SkipUTF8Check bool + SkipASCIICheck bool + SkipUTF8MB4Check bool + MultiSchemaInfo *model.MultiSchemaInfo // If the select statement was like 'select * from t as of timestamp ...' or in a stale read transaction // or is affected by the tidb_read_staleness session variable, then the statement will be makred as isStaleness // in stmtCtx @@ -114,6 +122,7 @@ type StatementContext struct { see https://github.com/mysql/mysql-server/blob/d2029238d6d9f648077664e4cdd611e231a6dc14/sql/sql_data_change.h#L60 for more details */ records uint64 + deleted uint64 updated uint64 copied uint64 touched uint64 @@ -198,8 +207,8 @@ type StatementContext struct { // EnableOptimizeTrace indicates whether enable optimizer trace by 'trace plan statement' EnableOptimizeTrace bool - // LogicalOptimizeTrace indicates the trace for optimize - LogicalOptimizeTrace *tracing.LogicalOptimizeTracer + // OptimizeTracer indicates the tracer for optimize + OptimizeTracer *tracing.OptimizeTracer // EnableOptimizerCETrace indicate if cardinality estimation internal process needs to be traced. // CE Trace is currently a submodule of the optimizer trace and is controlled by a separated option. EnableOptimizerCETrace bool @@ -207,6 +216,34 @@ type StatementContext struct { // WaitLockLeaseTime is the duration of cached table read lease expiration time. WaitLockLeaseTime time.Duration + + // KvExecCounter is created from SessionVars.StmtStats to count the number of SQL + // executions of the kv layer during the current execution of the statement. + // Its life cycle is limited to this execution, and a new KvExecCounter is + // always created during each statement execution. + KvExecCounter *stmtstats.KvExecCounter + + // WeakConsistency is true when read consistency is weak and in a read statement and not in a transaction. + WeakConsistency bool + + StatsLoad struct { + // Timeout to wait for sync-load + Timeout time.Duration + // NeededColumns stores the columns whose stats are needed for planner. + NeededColumns []model.TableColumnID + // ResultCh to receive stats loading results + ResultCh chan model.TableColumnID + // Fallback indicates if the planner uses full-loaded stats or fallback all to pseudo/simple. + Fallback bool + // LoadStartTime is to record the load start time to calculate latency + LoadStartTime time.Time + } + + // SysdateIsNow indicates whether sysdate() is an alias of now() in this statement + SysdateIsNow bool + + // RCCheckTS indicates the current read-consistency read select statement will use `RCCheckTS` path. + RCCheckTS bool } // StmtHints are SessionVars related sql hints. @@ -231,6 +268,9 @@ type StmtHints struct { HasMaxExecutionTime bool HasEnableCascadesPlannerHint bool SetVars map[string]string + + // the original table hints + OriginalTableHints []*ast.TableOptimizerHint } // TaskMapNeedBackUp indicates that whether we need to back up taskMap during physical optimizing. @@ -394,6 +434,20 @@ func (sc *StatementContext) AddRecordRows(rows uint64) { sc.mu.records += rows } +// DeletedRows is used to generate info message +func (sc *StatementContext) DeletedRows() uint64 { + sc.mu.Lock() + defer sc.mu.Unlock() + return sc.mu.deleted +} + +// AddDeletedRows adds record rows. +func (sc *StatementContext) AddDeletedRows(rows uint64) { + sc.mu.Lock() + defer sc.mu.Unlock() + sc.mu.deleted += rows +} + // UpdatedRows is used to generate info message func (sc *StatementContext) UpdatedRows() uint64 { sc.mu.Lock() @@ -578,6 +632,7 @@ func (sc *StatementContext) resetMuForRetry() { sc.mu.affectedRows = 0 sc.mu.foundRows = 0 sc.mu.records = 0 + sc.mu.deleted = 0 sc.mu.updated = 0 sc.mu.copied = 0 sc.mu.touched = 0 diff --git a/sessionctx/stmtctx/stmtctx_test.go b/sessionctx/stmtctx/stmtctx_test.go index f5bf2cca866be..7a4ec77a90660 100644 --- a/sessionctx/stmtctx/stmtctx_test.go +++ b/sessionctx/stmtctx/stmtctx_test.go @@ -15,11 +15,14 @@ package stmtctx_test import ( + "context" "fmt" "testing" "time" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/execdetails" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/util" @@ -90,3 +93,53 @@ func TestStatementContextPushDownFLags(t *testing.T) { require.Equal(t, tt.out, got) } } + +func TestWeakConsistencyRead(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key, c int, c1 int, unique index i(c))") + + execAndCheck := func(sql string, rows [][]interface{}, isolationLevel kv.IsoLevel) { + ctx := context.WithValue(context.Background(), "CheckSelectRequestHook", func(req *kv.Request) { + require.Equal(t, req.IsolationLevel, isolationLevel) + }) + rss, err := tk.Session().Execute(ctx, sql) + require.Nil(t, err) + for _, rs := range rss { + rs.Close() + } + if rows != nil { + tk.MustQuery(sql).Check(rows) + } + lastWeakConsistency := tk.Session().GetSessionVars().StmtCtx.WeakConsistency + require.Equal(t, lastWeakConsistency, isolationLevel == kv.RC) + } + + // strict + execAndCheck("insert into t values(1, 1, 1)", nil, kv.SI) + execAndCheck("select * from t", testkit.Rows("1 1 1"), kv.SI) + tk.MustExec("prepare s from 'select * from t'") + tk.MustExec("prepare u from 'update t set c1 = id + 1'") + execAndCheck("execute s", testkit.Rows("1 1 1"), kv.SI) + execAndCheck("execute u", nil, kv.SI) + execAndCheck("admin check table t", nil, kv.SI) + // weak + tk.MustExec("set tidb_read_consistency = weak") + execAndCheck("insert into t values(2, 2, 2)", nil, kv.SI) + execAndCheck("select * from t", testkit.Rows("1 1 2", "2 2 2"), kv.RC) + execAndCheck("execute s", testkit.Rows("1 1 2", "2 2 2"), kv.RC) + execAndCheck("execute u", nil, kv.SI) + // non-read-only queries should be strict + execAndCheck("admin check table t", nil, kv.SI) + execAndCheck("update t set c = c + 1 where id = 2", nil, kv.SI) + execAndCheck("delete from t where id = 2", nil, kv.SI) + // in-transaction queries should be strict + tk.MustExec("begin") + execAndCheck("select * from t", testkit.Rows("1 1 2"), kv.SI) + execAndCheck("execute s", testkit.Rows("1 1 2"), kv.SI) + tk.MustExec("rollback") +} diff --git a/sessionctx/variable/main_test.go b/sessionctx/variable/main_test.go index af5506566eac2..3d1f5cabbee70 100644 --- a/sessionctx/variable/main_test.go +++ b/sessionctx/variable/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/sessionctx/variable/mock_globalaccessor.go b/sessionctx/variable/mock_globalaccessor.go index ab9024f986b4f..969892dc6f736 100644 --- a/sessionctx/variable/mock_globalaccessor.go +++ b/sessionctx/variable/mock_globalaccessor.go @@ -96,6 +96,14 @@ func (m *MockGlobalAccessor) SetGlobalSysVarOnly(name string, value string) erro // GetTiDBTableValue implements GlobalVarAccessor.GetTiDBTableValue interface. func (m *MockGlobalAccessor) GetTiDBTableValue(name string) (string, error) { + // add for test tidb_gc_max_wait_time validation + if name == "tikv_gc_life_time" { + sv := GetSysVar(TiDBGCLifetime) + if sv == nil { + panic("Get SysVar Failed") + } + return sv.Value, nil + } panic("not supported") } diff --git a/sessionctx/variable/noop.go b/sessionctx/variable/noop.go index 79c7a63fe3abb..449a9aef63f39 100644 --- a/sessionctx/variable/noop.go +++ b/sessionctx/variable/noop.go @@ -447,7 +447,7 @@ var noopSysVars = []*SysVar{ {Scope: ScopeGlobal | ScopeSession, Name: InnodbTableLocks, Value: On, Type: TypeBool, AutoConvertNegativeBool: true}, {Scope: ScopeNone, Name: PerformanceSchema, Value: Off, Type: TypeBool}, {Scope: ScopeNone, Name: "myisam_recover_options", Value: Off}, - {Scope: ScopeGlobal | ScopeSession, Name: NetBufferLength, Value: "16384"}, + {Scope: ScopeGlobal | ScopeSession, Name: NetBufferLength, Value: "16384", Type: TypeUnsigned, MinValue: 1024, MaxValue: 1048576}, {Scope: ScopeGlobal | ScopeSession, Name: "binlog_row_image", Value: "FULL"}, {Scope: ScopeNone, Name: "innodb_locks_unsafe_for_binlog", Value: "0"}, {Scope: ScopeSession, Name: "rbr_exec_mode", Value: ""}, @@ -494,6 +494,8 @@ var noopSysVars = []*SysVar{ {Scope: ScopeGlobal | ScopeSession, Name: "information_schema_stats_expiry", Value: "86400"}, {Scope: ScopeGlobal, Name: ThreadPoolSize, Value: "16", Type: TypeUnsigned, MinValue: 1, MaxValue: 64}, {Scope: ScopeNone, Name: "lower_case_file_system", Value: "1"}, + {Scope: ScopeNone, Name: LowerCaseTableNames, Value: "2"}, + // for compatibility purpose, we should leave them alone. // TODO: Follow the Terminology Updates of MySQL after their changes arrived. // https://mysqlhighavailability.com/mysql-terminology-updates/ diff --git a/sessionctx/variable/removed.go b/sessionctx/variable/removed.go index 45c2e1704a02f..fbaae51b04a40 100644 --- a/sessionctx/variable/removed.go +++ b/sessionctx/variable/removed.go @@ -21,9 +21,34 @@ package variable // This helps ensure some compatibility for applications while being // careful not to return dummy data. +const ( + tiDBEnableAlterPlacement = "tidb_enable_alter_placement" + tiDBMemQuotaHashJoin = "tidb_mem_quota_hashjoin" + tiDBMemQuotaMergeJoin = "tidb_mem_quota_mergejoin" + tiDBMemQuotaSort = "tidb_mem_quota_sort" + tiDBMemQuotaTopn = "tidb_mem_quota_topn" + tiDBMemQuotaIndexLookupReader = "tidb_mem_quota_indexlookupreader" + tiDBMemQuotaIndexLookupJoin = "tidb_mem_quota_indexlookupjoin" + tiDBEnableGlobalTemporaryTable = "tidb_enable_global_temporary_table" + tiDBSlowLogMasking = "tidb_slow_log_masking" + placementChecks = "placement_checks" + tiDBEnableStreaming = "tidb_enable_streaming" + tiDBOptBCJ = "tidb_opt_broadcast_join" +) + var removedSysVars = map[string]string{ - TiDBEnableGlobalTemporaryTable: "temporary table support is now always enabled", - TiDBSlowLogMasking: "use tidb_redact_log instead", + tiDBEnableAlterPlacement: "alter placement is now always enabled", + tiDBEnableGlobalTemporaryTable: "temporary table support is now always enabled", + tiDBSlowLogMasking: "use tidb_redact_log instead", + placementChecks: "placement_checks is removed and use tidb_placement_mode instead", + tiDBMemQuotaHashJoin: "use tidb_mem_quota_query instead", + tiDBMemQuotaMergeJoin: "use tidb_mem_quota_query instead", + tiDBMemQuotaSort: "use tidb_mem_quota_query instead", + tiDBMemQuotaTopn: "use tidb_mem_quota_query instead", + tiDBMemQuotaIndexLookupReader: "use tidb_mem_quota_query instead", + tiDBMemQuotaIndexLookupJoin: "use tidb_mem_quota_query instead", + tiDBEnableStreaming: "streaming is no longer supported", + tiDBOptBCJ: "tidb_opt_broadcast_join is removed and use tidb_allow_mpp instead", } // IsRemovedSysVar returns true if the sysvar has been removed diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 8169eaa5c2d66..98c6e8dede550 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -29,10 +29,7 @@ import ( "sync/atomic" "time" - utilMath "github.com/pingcap/tidb/util/math" - "github.com/pingcap/errors" - pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" @@ -45,9 +42,11 @@ import ( "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx/stmtctx" + pumpcli "github.com/pingcap/tidb/tidb-binlog/pump_client" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" + utilMath "github.com/pingcap/tidb/util/math" "github.com/pingcap/tidb/util/rowcodec" "github.com/pingcap/tidb/util/stringutil" "github.com/pingcap/tidb/util/tableutil" @@ -67,6 +66,7 @@ type RetryInfo struct { DroppedPreparedStmtIDs []uint32 autoIncrementIDs retryInfoAutoIDs autoRandomIDs retryInfoAutoIDs + LastRcReadTS uint64 } // Clean does some clean work. @@ -183,6 +183,9 @@ type TransactionContext struct { // CachedTables is not nil if the transaction write on cached table. CachedTables map[int64]interface{} + + // Last ts used by read-consistency read. + LastRcReadTs uint64 } // GetShard returns the shard prefix for the next `count` rowids. @@ -433,6 +436,30 @@ const ( oneShotUse ) +// ReadConsistencyLevel is the level of read consistency. +type ReadConsistencyLevel string + +const ( + // ReadConsistencyStrict means read by strict consistency, default value. + ReadConsistencyStrict ReadConsistencyLevel = "strict" + // ReadConsistencyWeak means read can be weak consistency. + ReadConsistencyWeak ReadConsistencyLevel = "weak" +) + +// IsWeak returns true only if it's a weak-consistency read. +func (r ReadConsistencyLevel) IsWeak() bool { + return r == ReadConsistencyWeak +} + +func validateReadConsistencyLevel(val string) error { + switch v := ReadConsistencyLevel(strings.ToLower(val)); v { + case ReadConsistencyStrict, ReadConsistencyWeak: + return nil + default: + return ErrWrongTypeForVar.GenWithStackByArgs(TiDBReadConsistency) + } +} + // SessionVars is to handle user-defined or global variables in the current session. type SessionVars struct { Concurrency @@ -465,7 +492,8 @@ type SessionVars struct { // preparedStmtID is id of prepared statement. preparedStmtID uint32 // PreparedParams params for prepared statements - PreparedParams PreparedParams + PreparedParams PreparedParams + LastUpdateTime4PC types.Time // ActiveRoles stores active roles for current user ActiveRoles []*auth.RoleIdentity @@ -474,6 +502,9 @@ type SessionVars struct { // TxnCtx Should be reset on transaction finished. TxnCtx *TransactionContext + // TxnManager is used to manage txn context in session + TxnManager interface{} + // KVVars is the variables for KV storage. KVVars *tikvstore.Variables @@ -508,6 +539,9 @@ type SessionVars struct { // PlanColumnID is the unique id for column when building plan. PlanColumnID int64 + // MapHashCode2UniqueID4ExtendedCol map the expr's hash code to specified unique ID. + MapHashCode2UniqueID4ExtendedCol map[string]int + // User is the user identity with which the session login. User *auth.UserIdentity @@ -555,9 +589,6 @@ type SessionVars struct { // AllowAggPushDown can be set to false to forbid aggregation push down. AllowAggPushDown bool - // AllowBCJ means allow broadcast join. - AllowBCJ bool - // AllowCartesianBCJ means allow broadcast CARTESIAN join, 0 means not allow, 1 means allow broadcast CARTESIAN join // but the table size should under the broadcast threshold, 2 means allow broadcast CARTESIAN join even if the table // size exceeds the broadcast threshold @@ -682,6 +713,9 @@ type SessionVars struct { // OptimizerSelectivityLevel defines the level of the selectivity estimation in plan. OptimizerSelectivityLevel int + // OptimizerEnableNewOnlyFullGroupByCheck enables the new only_full_group_by check which is implemented by maintaining functional dependency. + OptimizerEnableNewOnlyFullGroupByCheck bool + // EnableTablePartition enables table partition feature. EnableTablePartition string @@ -715,11 +749,10 @@ type SessionVars struct { // EnablePointGetCache is used to cache value for point get for read only scenario. EnablePointGetCache bool - // EnableAlterPlacement indicates whether a user can alter table partition placement rules. - EnableAlterPlacement bool - - // EnablePlacementChecks indicates whether a user can check validation of placement. - EnablePlacementChecks bool + // PlacementMode the placement mode we use + // strict: Check placement settings strictly in ddl operations + // ignore: Ignore all placement settings in ddl operations + PlacementMode string // WaitSplitRegionFinish defines the split region behaviour is sync or async. WaitSplitRegionFinish bool @@ -727,10 +760,6 @@ type SessionVars struct { // WaitSplitRegionTimeout defines the split region timeout. WaitSplitRegionTimeout uint64 - // EnableStreaming indicates whether the coprocessor request can use streaming API. - // TODO: remove this after tidb-server configuration "enable-streaming' removed. - EnableStreaming bool - // EnableChunkRPC indicates whether the coprocessor request can use chunk API. EnableChunkRPC bool @@ -892,6 +921,9 @@ type SessionVars struct { // LastQueryInfo keeps track the info of last query. LastQueryInfo QueryInfo + // LastDDLInfo keeps track the info of last DDL. + LastDDLInfo LastDDLInfo + // PartitionPruneMode indicates how and when to prune partitions. PartitionPruneMode atomic2.String @@ -969,6 +1001,31 @@ type SessionVars struct { // EnablePaging indicates whether enable paging in coprocessor requests. EnablePaging bool + + // EnableLegacyInstanceScope says if SET SESSION can be used to set an instance + // scope variable. The default is TRUE. + EnableLegacyInstanceScope bool + + // ReadConsistency indicates the read consistency requirement. + ReadConsistency ReadConsistencyLevel + + // StatsLoadSyncWait indicates how long to wait for stats load before timeout. + StatsLoadSyncWait int64 + + // SysdateIsNow indicates whether Sysdate is an alias of Now function + SysdateIsNow bool + // EnableMutationChecker indicates whether to check data consistency for mutations + EnableMutationChecker bool + // AssertionLevel controls how strict the assertions on data mutations should be. + AssertionLevel AssertionLevel + // IgnorePreparedCacheCloseStmt controls if ignore the close-stmt command for prepared statement. + IgnorePreparedCacheCloseStmt bool + // BatchPendingTiFlashCount shows the threshold of pending TiFlash tables when batch adding. + BatchPendingTiFlashCount int + // RcReadCheckTS indicates if ts check optimization is enabled for current session. + RcReadCheckTS bool + // RemoveOrderbyInSubquery indicates whether to remove ORDER BY in subquery. + RemoveOrderbyInSubquery bool } // InitStatementContext initializes a StatementContext, the object is reused to reduce allocation. @@ -1024,11 +1081,6 @@ func (s *SessionVars) CheckAndGetTxnScope() string { // UseDynamicPartitionPrune indicates whether use new dynamic partition prune. func (s *SessionVars) UseDynamicPartitionPrune() bool { - if s.InTxn() || !s.GetStatusFlag(mysql.ServerStatusAutocommit) { - // UnionScan cannot get partition table IDs in dynamic-mode, this is a quick-fix for issues/26719, - // please see it for more details. - return false - } return PartitionPruneMode(s.PartitionPruneMode.Load()) == Dynamic } @@ -1041,6 +1093,13 @@ func (s *SessionVars) BuildParserConfig() parser.ParserConfig { } } +const ( + // PlacementModeStrict indicates all placement operations should be checked strictly in ddl + PlacementModeStrict string = "STRICT" + // PlacementModeIgnore indicates ignore all placement operations in ddl + PlacementModeIgnore string = "IGNORE" +) + // PartitionPruneMode presents the prune mode used. type PartitionPruneMode string @@ -1131,7 +1190,6 @@ func NewSessionVars() *SessionVars { Status: mysql.ServerStatusAutocommit, StmtCtx: new(stmtctx.StatementContext), AllowAggPushDown: false, - AllowBCJ: false, AllowCartesianBCJ: DefOptCartesianBCJ, MPPOuterJoinFixedBuildSide: DefOptMPPOuterJoinFixedBuildSide, BroadcastJoinThresholdSize: DefBroadcastJoinThresholdSize, @@ -1162,7 +1220,7 @@ func NewSessionVars() *SessionVars { SlowQueryFile: config.GetGlobalConfig().Log.SlowQueryFile, WaitSplitRegionFinish: DefTiDBWaitSplitRegionFinish, WaitSplitRegionTimeout: DefWaitSplitRegionTimeout, - enableIndexMerge: false, + enableIndexMerge: DefTiDBEnableIndexMerge, NoopFuncsMode: TiDBOptOnOffWarn(DefTiDBEnableNoopFuncs), replicaRead: kv.ReplicaReadLeader, AllowRemoveAutoInc: DefTiDBAllowRemoveAutoInc, @@ -1186,7 +1244,6 @@ func NewSessionVars() *SessionVars { ShardAllocateStep: DefTiDBShardAllocateStep, EnableChangeMultiSchema: DefTiDBChangeMultiSchema, EnablePointGetCache: DefTiDBPointGetCache, - EnableAlterPlacement: DefTiDBEnableAlterPlacement, EnableAmendPessimisticTxn: DefTiDBEnableAmendPessimisticTxn, PartitionPruneMode: *atomic2.NewString(DefTiDBPartitionPruneMode), TxnScope: kv.NewDefaultTxnScopeVar(), @@ -1201,8 +1258,10 @@ func NewSessionVars() *SessionVars { TMPTableSize: DefTiDBTmpTableMaxSize, MPPStoreLastFailTime: make(map[string]time.Time), MPPStoreFailTTL: DefTiDBMPPStoreFailTTL, - EnablePlacementChecks: DefEnablePlacementCheck, Rng: utilMath.NewWithTime(), + StatsLoadSyncWait: StatsLoadSyncWait.Load(), + EnableLegacyInstanceScope: DefEnableLegacyInstanceScope, + RemoveOrderbyInSubquery: DefTiDBRemoveOrderbyInSubquery, } vars.KVVars = tikvstore.NewVariables(&vars.Killed) vars.Concurrency = Concurrency{ @@ -1222,16 +1281,6 @@ func NewSessionVars() *SessionVars { vars.MemQuota = MemQuota{ MemQuotaQuery: config.GetGlobalConfig().MemQuotaQuery, MemQuotaApplyCache: DefTiDBMemQuotaApplyCache, - - // The variables below do not take any effect anymore, it's remaining for compatibility. - // TODO: remove them in v4.1 - MemQuotaHashJoin: DefTiDBMemQuotaHashJoin, - MemQuotaMergeJoin: DefTiDBMemQuotaMergeJoin, - MemQuotaSort: DefTiDBMemQuotaSort, - MemQuotaTopn: DefTiDBMemQuotaTopn, - MemQuotaIndexLookupReader: DefTiDBMemQuotaIndexLookupReader, - MemQuotaIndexLookupJoin: DefTiDBMemQuotaIndexLookupJoin, - MemQuotaDistSQL: DefTiDBMemQuotaDistSQL, } vars.BatchSize = BatchSize{ IndexJoinBatchSize: DefIndexJoinBatchSize, @@ -1240,25 +1289,15 @@ func NewSessionVars() *SessionVars { MaxChunkSize: DefMaxChunkSize, } vars.DMLBatchSize = DefDMLBatchSize - var enableStreaming string - if config.GetGlobalConfig().EnableStreaming { - enableStreaming = "1" - } else { - enableStreaming = "0" - } - terror.Log(vars.SetSystemVar(TiDBEnableStreaming, enableStreaming)) - vars.AllowBatchCop = DefTiDBAllowBatchCop vars.allowMPPExecution = DefTiDBAllowMPPExecution vars.HashExchangeWithNewCollation = DefTiDBHashExchangeWithNewCollation vars.enforceMPPExecution = DefTiDBEnforceMPPExecution vars.MPPStoreFailTTL = DefTiDBMPPStoreFailTTL - var enableChunkRPC string + enableChunkRPC := "0" if config.GetGlobalConfig().TiKVClient.EnableChunkRPC { enableChunkRPC = "1" - } else { - enableChunkRPC = "0" } terror.Log(vars.SetSystemVar(TiDBEnableChunkRPC, enableChunkRPC)) for _, engine := range config.GetGlobalConfig().IsolationRead.Engines { @@ -1507,9 +1546,6 @@ func (s *SessionVars) GetSystemVar(name string) (string, bool) { } else if name == ErrorCount { return strconv.Itoa(int(s.SysErrorCount)), true } - if name == TiDBSlowLogMasking { - name = TiDBRedactLog - } if val, ok := s.stmtVars[name]; ok { return val, ok } @@ -1612,20 +1648,6 @@ func (s *SessionVars) GetReadableTxnMode() string { return txnMode } -func (s *SessionVars) setTxnMode(val string) error { - switch strings.ToUpper(val) { - case ast.Pessimistic: - s.TxnMode = ast.Pessimistic - case ast.Optimistic: - s.TxnMode = ast.Optimistic - case "": - s.TxnMode = "" - default: - return ErrWrongValueForVar.FastGenByArgs(TiDBTxnMode, val) - } - return nil -} - // SetPrevStmtDigest sets the digest of the previous statement. func (s *SessionVars) SetPrevStmtDigest(prevStmtDigest string) { s.prevStmtDigest = prevStmtDigest @@ -1640,7 +1662,7 @@ func (s *SessionVars) GetPrevStmtDigest() string { // LazyCheckKeyNotExists returns if we can lazy check key not exists. func (s *SessionVars) LazyCheckKeyNotExists() bool { - return s.PresumeKeyNotExists || (s.TxnCtx.IsPessimistic && !s.StmtCtx.DupKeyAsWarning) + return s.PresumeKeyNotExists || (s.TxnCtx != nil && s.TxnCtx.IsPessimistic && !s.StmtCtx.DupKeyAsWarning) } // GetTemporaryTable returns a TempTable by tableInfo. @@ -1873,23 +1895,6 @@ type MemQuota struct { MemQuotaQuery int64 // MemQuotaApplyCache defines the memory capacity for apply cache. MemQuotaApplyCache int64 - - // The variables below do not take any effect anymore, it's remaining for compatibility. - // TODO: remove them in v4.1 - // MemQuotaHashJoin defines the memory quota for a hash join executor. - MemQuotaHashJoin int64 - // MemQuotaMergeJoin defines the memory quota for a merge join executor. - MemQuotaMergeJoin int64 - // MemQuotaSort defines the memory quota for a sort executor. - MemQuotaSort int64 - // MemQuotaTopn defines the memory quota for a top n executor. - MemQuotaTopn int64 - // MemQuotaIndexLookupReader defines the memory quota for a index lookup reader executor. - MemQuotaIndexLookupReader int64 - // MemQuotaIndexLookupJoin defines the memory quota for a index lookup join executor. - MemQuotaIndexLookupJoin int64 - // MemQuotaDistSQL defines the memory quota for all operators in DistSQL layer like co-processor and selectResult. - MemQuotaDistSQL int64 } // BatchSize defines batch size values. @@ -1967,13 +1972,13 @@ const ( // SlowLogCopProcAddr is the address of TiKV where the cop-task which cost max process time run. SlowLogCopProcAddr = "Cop_proc_addr" // SlowLogCopWaitAvg is the average wait time of all cop-tasks. - SlowLogCopWaitAvg = "Cop_wait_avg" + SlowLogCopWaitAvg = "Cop_wait_avg" // #nosec G101 // SlowLogCopWaitP90 is the p90 wait time of all cop-tasks. - SlowLogCopWaitP90 = "Cop_wait_p90" + SlowLogCopWaitP90 = "Cop_wait_p90" // #nosec G101 // SlowLogCopWaitMax is the max wait time of all cop-tasks. SlowLogCopWaitMax = "Cop_wait_max" // SlowLogCopWaitAddr is the address of TiKV where the cop-task which cost wait process time run. - SlowLogCopWaitAddr = "Cop_wait_addr" + SlowLogCopWaitAddr = "Cop_wait_addr" // #nosec G101 // SlowLogCopBackoffPrefix contains backoff information. SlowLogCopBackoffPrefix = "Cop_backoff_" // SlowLogMemMax is the max number bytes of memory used in this statement. @@ -2127,7 +2132,7 @@ func (s *SessionVars) SlowLogFormat(logItems *SlowQueryLogItems) string { } if len(s.CurrentDB) > 0 { - writeSlowLogItem(&buf, SlowLogDBStr, s.CurrentDB) + writeSlowLogItem(&buf, SlowLogDBStr, strings.ToLower(s.CurrentDB)) } if len(logItems.IndexNames) > 0 { writeSlowLogItem(&buf, SlowLogIndexNamesStr, logItems.IndexNames) @@ -2146,7 +2151,6 @@ func (s *SessionVars) SlowLogFormat(logItems *SlowQueryLogItems) string { vStr = "pseudo" } else { vStr = strconv.FormatUint(v, 10) - } if firstComma { buf.WriteString("," + k + ":" + vStr) @@ -2239,7 +2243,7 @@ func (s *SessionVars) SlowLogFormat(logItems *SlowQueryLogItems) string { } if s.CurrentDBChanged { - buf.WriteString(fmt.Sprintf("use %s;\n", s.CurrentDB)) + buf.WriteString(fmt.Sprintf("use %s;\n", strings.ToLower(s.CurrentDB))) s.CurrentDBChanged = false } @@ -2263,6 +2267,12 @@ type QueryInfo struct { ErrMsg string `json:"error,omitempty"` } +// LastDDLInfo represents the information of last DDL. It's used to expose information for test purpose. +type LastDDLInfo struct { + Query string `json:"query"` + SeqNum uint64 `json:"seq_num"` +} + // TxnReadTS indicates the value and used situation for tx_read_ts type TxnReadTS struct { readTS uint64 @@ -2357,3 +2367,12 @@ func (s *SessionVars) GetSeekFactor(tbl *model.TableInfo) float64 { } return s.seekFactor } + +// IsRcCheckTsRetryable checks if the current error is retryable for `RcReadCheckTS` path. +func (s *SessionVars) IsRcCheckTsRetryable(err error) bool { + if err == nil { + return false + } + // The `RCCheckTS` flag of `stmtCtx` is set. + return s.RcReadCheckTS && s.StmtCtx.RCCheckTS && errors.ErrorEqual(err, kv.ErrWriteConflict) +} diff --git a/sessionctx/variable/session_test.go b/sessionctx/variable/session_test.go index abcf79ca49158..52c8fd5c818f6 100644 --- a/sessionctx/variable/session_test.go +++ b/sessionctx/variable/session_test.go @@ -47,14 +47,8 @@ func TestSetSystemVariable(t *testing.T) { {variable.TiDBOptAggPushDown, "1", false}, {variable.TiDBOptDistinctAggPushDown, "1", false}, {variable.TiDBMemQuotaQuery, "1024", false}, - {variable.TiDBMemQuotaHashJoin, "1024", false}, - {variable.TiDBMemQuotaMergeJoin, "1024", false}, - {variable.TiDBMemQuotaSort, "1024", false}, - {variable.TiDBMemQuotaTopn, "1024", false}, - {variable.TiDBMemQuotaIndexLookupReader, "1024", false}, - {variable.TiDBMemQuotaIndexLookupJoin, "1024", false}, {variable.TiDBMemQuotaApplyCache, "1024", false}, - {variable.TiDBEnableStmtSummary, "1", false}, + {variable.TiDBEnableStmtSummary, "1", true}, // now global only } for _, tc := range testCases { @@ -152,7 +146,8 @@ func TestSlowLogFormat(t *testing.T) { seVar.User = &auth.UserIdentity{Username: "root", Hostname: "192.168.0.1"} seVar.ConnectionInfo = &variable.ConnectionInfo{ClientIP: "192.168.0.1"} seVar.ConnectionID = 1 - seVar.CurrentDB = "test" + // the out put of the loged CurrentDB should be 'test', should be to lower cased. + seVar.CurrentDB = "TeST" seVar.InRestrictedSQL = true seVar.StmtCtx.WaitLockLeaseTime = 1 txnTS := uint64(406649736972468225) diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 3491f28bc73dc..1dae2a52a93bf 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -35,12 +35,658 @@ import ( "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/stmtsummary" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" "github.com/pingcap/tidb/util/versioninfo" tikvstore "github.com/tikv/client-go/v2/kv" atomic2 "go.uber.org/atomic" ) +// All system variables declared here are ordered by their scopes, which follow the order of scopes below: +// [NONE, SESSION, INSTANCE, GLOBAL, GLOBAL & SESSION] +// If you are adding a new system variable, please put it in the corresponding area. var defaultSysVars = []*SysVar{ + /* The system variables below have NONE scope */ + {Scope: ScopeNone, Name: SystemTimeZone, Value: "CST"}, + {Scope: ScopeNone, Name: Hostname, Value: DefHostname}, + {Scope: ScopeNone, Name: Port, Value: "4000", Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxUint16}, + {Scope: ScopeNone, Name: LogBin, Value: Off, Type: TypeBool}, + {Scope: ScopeNone, Name: VersionComment, Value: "TiDB Server (Apache License 2.0) " + versioninfo.TiDBEdition + " Edition, MySQL 5.7 compatible"}, + {Scope: ScopeNone, Name: Version, Value: mysql.ServerVersion}, + {Scope: ScopeNone, Name: DataDir, Value: "/usr/local/mysql/data/"}, + {Scope: ScopeNone, Name: Socket, Value: ""}, + {Scope: ScopeNone, Name: "license", Value: "Apache License 2.0"}, + {Scope: ScopeNone, Name: "have_ssl", Value: "DISABLED"}, + {Scope: ScopeNone, Name: "have_openssl", Value: "DISABLED"}, + {Scope: ScopeNone, Name: "ssl_ca", Value: ""}, + {Scope: ScopeNone, Name: "ssl_cert", Value: ""}, + {Scope: ScopeNone, Name: "ssl_key", Value: ""}, + {Scope: ScopeNone, Name: "version_compile_os", Value: runtime.GOOS}, + {Scope: ScopeNone, Name: "version_compile_machine", Value: runtime.GOARCH}, + /* TiDB specific variables */ + {Scope: ScopeNone, Name: TiDBEnableEnhancedSecurity, Value: Off, Type: TypeBool}, + {Scope: ScopeNone, Name: TiDBAllowFunctionForExpressionIndex, ReadOnly: true, Value: collectAllowFuncName4ExpressionIndex()}, + + /* The system variables below have SESSION scope */ + {Scope: ScopeSession, Name: Timestamp, Value: DefTimestamp, skipInit: true, MinValue: 0, MaxValue: 2147483647, Type: TypeFloat, GetSession: func(s *SessionVars) (string, error) { + if timestamp, ok := s.systems[Timestamp]; ok && timestamp != DefTimestamp { + return timestamp, nil + } + timestamp := s.StmtCtx.GetOrStoreStmtCache(stmtctx.StmtNowTsCacheKey, time.Now()).(time.Time) + return types.ToString(float64(timestamp.UnixNano()) / float64(time.Second)) + }}, + {Scope: ScopeSession, Name: WarningCount, Value: "0", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return strconv.Itoa(s.SysWarningCount), nil + }}, + {Scope: ScopeSession, Name: ErrorCount, Value: "0", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return strconv.Itoa(int(s.SysErrorCount)), nil + }}, + {Scope: ScopeSession, Name: LastInsertID, Value: "", skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(s.StmtCtx.PrevLastInsertID, 10), nil + }}, + {Scope: ScopeSession, Name: Identity, Value: "", skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(s.StmtCtx.PrevLastInsertID, 10), nil + }}, + /* TiDB specific variables */ + // TODO: TiDBTxnScope is hidden because local txn feature is not done. + {Scope: ScopeSession, Name: TiDBTxnScope, skipInit: true, Hidden: true, Value: kv.GlobalTxnScope, SetSession: func(s *SessionVars, val string) error { + switch val { + case kv.GlobalTxnScope: + s.TxnScope = kv.NewGlobalTxnScopeVar() + case kv.LocalTxnScope: + if !EnableLocalTxn.Load() { + return ErrWrongValueForVar.GenWithStack("@@txn_scope can not be set to local when tidb_enable_local_txn is off") + } + txnScope := config.GetTxnScopeFromConfig() + if txnScope == kv.GlobalTxnScope { + return ErrWrongValueForVar.GenWithStack("@@txn_scope can not be set to local when zone label is empty or \"global\"") + } + s.TxnScope = kv.NewLocalTxnScopeVar(txnScope) + default: + return ErrWrongValueForVar.GenWithStack("@@txn_scope value should be global or local") + } + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return s.TxnScope.GetVarValue(), nil + }}, + {Scope: ScopeSession, Name: TiDBTxnReadTS, Value: "", Hidden: true, SetSession: func(s *SessionVars, val string) error { + return setTxnReadTS(s, val) + }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + return normalizedValue, nil + }}, + {Scope: ScopeSession, Name: TiDBReadStaleness, Value: strconv.Itoa(DefTiDBReadStaleness), Type: TypeInt, MinValue: math.MinInt32, MaxValue: 0, AllowEmpty: true, Hidden: false, SetSession: func(s *SessionVars, val string) error { + return setReadStaleness(s, val) + }}, + {Scope: ScopeSession, Name: TiDBEnforceMPPExecution, Type: TypeBool, Value: BoolToOnOff(config.GetGlobalConfig().Performance.EnforceMPP), Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + if TiDBOptOn(normalizedValue) && !vars.allowMPPExecution { + return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs("tidb_enforce_mpp", "1' but tidb_allow_mpp is 0, please activate tidb_allow_mpp at first.") + } + return normalizedValue, nil + }, SetSession: func(s *SessionVars, val string) error { + s.enforceMPPExecution = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBSnapshot, Value: "", skipInit: true, SetSession: func(s *SessionVars, val string) error { + err := setSnapshotTS(s, val) + if err != nil { + return err + } + return nil + }}, + {Scope: ScopeSession, Name: TiDBOptAggPushDown, Value: BoolToOnOff(DefOptAggPushDown), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.AllowAggPushDown = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBOptDistinctAggPushDown, Value: BoolToOnOff(config.GetGlobalConfig().Performance.DistinctAggPushDown), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.AllowDistinctAggPushDown = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBOptWriteRowID, Value: BoolToOnOff(DefOptWriteRowID), skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.AllowWriteRowID = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBChecksumTableConcurrency, skipInit: true, Value: strconv.Itoa(DefChecksumTableConcurrency)}, + {Scope: ScopeSession, Name: TiDBBatchInsert, Value: BoolToOnOff(DefBatchInsert), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.BatchInsert = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBBatchDelete, Value: BoolToOnOff(DefBatchDelete), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.BatchDelete = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBBatchCommit, Value: BoolToOnOff(DefBatchCommit), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.BatchCommit = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBCurrentTS, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(s.TxnCtx.StartTS, 10), nil + }}, + {Scope: ScopeSession, Name: TiDBLastTxnInfo, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + return s.LastTxnInfo, nil + }}, + {Scope: ScopeSession, Name: TiDBLastQueryInfo, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + info, err := json.Marshal(s.LastQueryInfo) + if err != nil { + return "", err + } + return string(info), nil + }}, + {Scope: ScopeSession, Name: TiDBMemQuotaQuery, Value: strconv.FormatInt(config.GetGlobalConfig().MemQuotaQuery, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { + s.MemQuotaQuery = TidbOptInt64(val, config.GetGlobalConfig().MemQuotaQuery) + return nil + }}, + {Scope: ScopeSession, Name: TiDBEnableChunkRPC, Value: On, Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.EnableChunkRPC = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TxnIsolationOneShot, Value: "", skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + return checkIsolationLevel(vars, normalizedValue, originalValue, scope) + }, SetSession: func(s *SessionVars, val string) error { + s.txnIsolationLevelOneShot.state = oneShotSet + s.txnIsolationLevelOneShot.value = val + return nil + }}, + {Scope: ScopeSession, Name: TiDBOptimizerSelectivityLevel, Value: strconv.Itoa(DefTiDBOptimizerSelectivityLevel), skipInit: true, Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.OptimizerSelectivityLevel = tidbOptPositiveInt32(val, DefTiDBOptimizerSelectivityLevel) + return nil + }}, + {Scope: ScopeSession, Name: TiDBLogFileMaxDays, Value: strconv.Itoa(config.GetGlobalConfig().Log.File.MaxDays), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt32, skipInit: true, SetSession: func(s *SessionVars, val string) error { + maxAge, err := strconv.ParseInt(val, 10, 32) + if err != nil { + return err + } + + GlobalLogMaxDays.Store(int32(maxAge)) + + cfg := config.GetGlobalConfig().Log.ToLogConfig() + cfg.Config.File.MaxDays = int(maxAge) + + err = logutil.ReplaceLogger(cfg) + if err != nil { + return err + } + + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatInt(int64(GlobalLogMaxDays.Load()), 10), nil + }}, + {Scope: ScopeSession, Name: TiDBPProfSQLCPU, Value: strconv.Itoa(DefTiDBPProfSQLCPU), Type: TypeInt, skipInit: true, MinValue: 0, MaxValue: 1, SetSession: func(s *SessionVars, val string) error { + EnablePProfSQLCPU.Store(uint32(tidbOptPositiveInt32(val, DefTiDBPProfSQLCPU)) > 0) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + val := "0" + if EnablePProfSQLCPU.Load() { + val = "1" + } + return val, nil + }}, + {Scope: ScopeSession, Name: TiDBDDLSlowOprThreshold, Value: strconv.Itoa(DefTiDBDDLSlowOprThreshold), skipInit: true, SetSession: func(s *SessionVars, val string) error { + atomic.StoreUint32(&DDLSlowOprThreshold, uint32(tidbOptPositiveInt32(val, DefTiDBDDLSlowOprThreshold))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(uint64(atomic.LoadUint32(&DDLSlowOprThreshold)), 10), nil + }}, + {Scope: ScopeSession, Name: TiDBConfig, Value: "", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + conf := config.GetGlobalConfig() + j, err := json.MarshalIndent(conf, "", "\t") + if err != nil { + return "", err + } + return config.HideConfig(string(j)), nil + }}, + {Scope: ScopeSession, Name: TiDBDDLReorgPriority, Value: "PRIORITY_LOW", skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.setDDLReorgPriority(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBForcePriority, skipInit: true, Value: mysql.Priority2Str[DefTiDBForcePriority], SetSession: func(s *SessionVars, val string) error { + atomic.StoreInt32(&ForcePriority, int32(mysql.Str2Priority(val))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return mysql.Priority2Str[mysql.PriorityEnum(atomic.LoadInt32(&ForcePriority))], nil + }}, + {Scope: ScopeSession, Name: TiDBSlowQueryFile, Value: "", skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.SlowQueryFile = val + return nil + }}, + {Scope: ScopeSession, Name: TiDBWaitSplitRegionFinish, Value: BoolToOnOff(DefTiDBWaitSplitRegionFinish), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.WaitSplitRegionFinish = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBWaitSplitRegionTimeout, Value: strconv.Itoa(DefWaitSplitRegionTimeout), skipInit: true, Type: TypeUnsigned, MinValue: 1, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.WaitSplitRegionTimeout = uint64(tidbOptPositiveInt32(val, DefWaitSplitRegionTimeout)) + return nil + }}, + {Scope: ScopeSession, Name: TiDBLowResolutionTSO, Value: Off, Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.LowResolutionTSO = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBExpensiveQueryTimeThreshold, Value: strconv.Itoa(DefTiDBExpensiveQueryTimeThreshold), Type: TypeUnsigned, MinValue: int64(MinExpensiveQueryTimeThreshold), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + atomic.StoreUint64(&ExpensiveQueryTimeThreshold, uint64(tidbOptPositiveInt32(val, DefTiDBExpensiveQueryTimeThreshold))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(atomic.LoadUint64(&ExpensiveQueryTimeThreshold), 10), nil + }}, + {Scope: ScopeSession, Name: TiDBMemoryUsageAlarmRatio, Value: strconv.FormatFloat(config.GetGlobalConfig().Performance.MemoryUsageAlarmRatio, 'f', -1, 64), Type: TypeFloat, MinValue: 0.0, MaxValue: 1.0, skipInit: true, SetSession: func(s *SessionVars, val string) error { + MemoryUsageAlarmRatio.Store(tidbOptFloat64(val, 0.8)) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return fmt.Sprintf("%g", MemoryUsageAlarmRatio.Load()), nil + }}, + {Scope: ScopeSession, Name: TiDBAllowRemoveAutoInc, Value: BoolToOnOff(DefTiDBAllowRemoveAutoInc), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.AllowRemoveAutoInc = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeSession, Name: TiDBIsolationReadEngines, Value: strings.Join(config.GetGlobalConfig().IsolationRead.Engines, ","), Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + engines := strings.Split(normalizedValue, ",") + var formatVal string + for i, engine := range engines { + engine = strings.TrimSpace(engine) + if i != 0 { + formatVal += "," + } + switch { + case strings.EqualFold(engine, kv.TiKV.Name()): + formatVal += kv.TiKV.Name() + case strings.EqualFold(engine, kv.TiFlash.Name()): + formatVal += kv.TiFlash.Name() + case strings.EqualFold(engine, kv.TiDB.Name()): + formatVal += kv.TiDB.Name() + default: + return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(TiDBIsolationReadEngines, normalizedValue) + } + } + return formatVal, nil + }, SetSession: func(s *SessionVars, val string) error { + s.IsolationReadEngines = make(map[kv.StoreType]struct{}) + for _, engine := range strings.Split(val, ",") { + switch engine { + case kv.TiKV.Name(): + s.IsolationReadEngines[kv.TiKV] = struct{}{} + case kv.TiFlash.Name(): + s.IsolationReadEngines[kv.TiFlash] = struct{}{} + case kv.TiDB.Name(): + s.IsolationReadEngines[kv.TiDB] = struct{}{} + } + } + return nil + }}, + {Scope: ScopeSession, Name: TiDBMetricSchemaStep, Value: strconv.Itoa(DefTiDBMetricSchemaStep), Type: TypeUnsigned, skipInit: true, MinValue: 10, MaxValue: 60 * 60 * 60, SetSession: func(s *SessionVars, val string) error { + s.MetricSchemaStep = TidbOptInt64(val, DefTiDBMetricSchemaStep) + return nil + }}, + {Scope: ScopeSession, Name: TiDBMetricSchemaRangeDuration, Value: strconv.Itoa(DefTiDBMetricSchemaRangeDuration), skipInit: true, Type: TypeUnsigned, MinValue: 10, MaxValue: 60 * 60 * 60, SetSession: func(s *SessionVars, val string) error { + s.MetricSchemaRangeDuration = TidbOptInt64(val, DefTiDBMetricSchemaRangeDuration) + return nil + }}, + {Scope: ScopeSession, Name: TiDBSlowLogThreshold, Value: strconv.Itoa(logutil.DefaultSlowThreshold), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { + atomic.StoreUint64(&config.GetGlobalConfig().Log.SlowThreshold, uint64(TidbOptInt64(val, logutil.DefaultSlowThreshold))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.SlowThreshold), 10), nil + }}, + {Scope: ScopeSession, Name: TiDBRecordPlanInSlowLog, Value: int32ToBoolStr(logutil.DefaultRecordPlanInSlowLog), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + atomic.StoreUint32(&config.GetGlobalConfig().Log.RecordPlanInSlowLog, uint32(TidbOptInt64(val, logutil.DefaultRecordPlanInSlowLog))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + enabled := atomic.LoadUint32(&config.GetGlobalConfig().Log.RecordPlanInSlowLog) == 1 + return BoolToOnOff(enabled), nil + }}, + {Scope: ScopeSession, Name: TiDBEnableSlowLog, Value: BoolToOnOff(logutil.DefaultTiDBEnableSlowLog), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { + config.GetGlobalConfig().Log.EnableSlowLog.Store(TiDBOptOn(val)) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return BoolToOnOff(config.GetGlobalConfig().Log.EnableSlowLog.Load()), nil + }}, + {Scope: ScopeSession, Name: TiDBQueryLogMaxLen, Value: strconv.Itoa(logutil.DefaultQueryLogMaxLen), Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, skipInit: true, SetSession: func(s *SessionVars, val string) error { + atomic.StoreUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen, uint64(TidbOptInt64(val, logutil.DefaultQueryLogMaxLen))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen), 10), nil + }}, + {Scope: ScopeSession, Name: TiDBCheckMb4ValueInUTF8, Value: BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + config.GetGlobalConfig().CheckMb4ValueInUTF8.Store(TiDBOptOn(val)) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()), nil + }}, + {Scope: ScopeSession, Name: TiDBFoundInPlanCache, Value: BoolToOnOff(DefTiDBFoundInPlanCache), Type: TypeBool, ReadOnly: true, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.FoundInPlanCache = TiDBOptOn(val) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return BoolToOnOff(s.PrevFoundInPlanCache), nil + }}, + {Scope: ScopeSession, Name: TiDBFoundInBinding, Value: BoolToOnOff(DefTiDBFoundInBinding), Type: TypeBool, ReadOnly: true, skipInit: true, SetSession: func(s *SessionVars, val string) error { + s.FoundInBinding = TiDBOptOn(val) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return BoolToOnOff(s.PrevFoundInBinding), nil + }}, + {Scope: ScopeSession, Name: TiDBEnableCollectExecutionInfo, Value: BoolToOnOff(DefTiDBEnableCollectExecutionInfo), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + oldConfig := config.GetGlobalConfig() + newValue := TiDBOptOn(val) + if oldConfig.EnableCollectExecutionInfo != newValue { + newConfig := *oldConfig + newConfig.EnableCollectExecutionInfo = newValue + config.StoreGlobalConfig(&newConfig) + } + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return BoolToOnOff(config.GetGlobalConfig().EnableCollectExecutionInfo), nil + }}, + {Scope: ScopeSession, Name: PluginLoad, Value: "", GetSession: func(s *SessionVars) (string, error) { + return config.GetGlobalConfig().Plugin.Load, nil + }}, + {Scope: ScopeSession, Name: PluginDir, Value: "/data/deploy/plugin", GetSession: func(s *SessionVars) (string, error) { + return config.GetGlobalConfig().Plugin.Dir, nil + }}, + {Scope: ScopeSession, Name: RandSeed1, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.Rng.SetSeed1(uint32(tidbOptPositiveInt32(val, 0))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return "0", nil + }}, + {Scope: ScopeSession, Name: RandSeed2, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.Rng.SetSeed2(uint32(tidbOptPositiveInt32(val, 0))) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return "0", nil + }}, + {Scope: ScopeSession, Name: TiDBReadConsistency, Value: string(ReadConsistencyStrict), Type: TypeStr, Hidden: true, + Validation: func(_ *SessionVars, normalized string, _ string, _ ScopeFlag) (string, error) { + return normalized, validateReadConsistencyLevel(normalized) + }, + SetSession: func(s *SessionVars, val string) error { + s.ReadConsistency = ReadConsistencyLevel(val) + return nil + }, + }, + {Scope: ScopeSession, Name: TiDBLastDDLInfo, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { + info, err := json.Marshal(s.LastDDLInfo) + if err != nil { + return "", err + } + return string(info), nil + }}, + + /* The system variables below have INSTANCE scope */ + {Scope: ScopeInstance, Name: TiDBGeneralLog, Value: BoolToOnOff(DefTiDBGeneralLog), Type: TypeBool, skipInit: true, SetGlobal: func(s *SessionVars, val string) error { + ProcessGeneralLog.Store(TiDBOptOn(val)) + return nil + }, GetGlobal: func(s *SessionVars) (string, error) { + return BoolToOnOff(ProcessGeneralLog.Load()), nil + }}, + + /* The system variables below have GLOBAL scope */ + {Scope: ScopeGlobal, Name: MaxPreparedStmtCount, Value: strconv.FormatInt(DefMaxPreparedStmtCount, 10), Type: TypeInt, MinValue: -1, MaxValue: 1048576}, + {Scope: ScopeGlobal, Name: InitConnect, Value: ""}, + /* TiDB specific variables */ + {Scope: ScopeGlobal, Name: TiDBTSOClientBatchMaxWaitTime, Value: strconv.FormatFloat(DefTiDBTSOClientBatchMaxWaitTime, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: 10, + GetGlobal: func(sv *SessionVars) (string, error) { + return strconv.FormatFloat(MaxTSOBatchWaitInterval.Load(), 'f', -1, 64), nil + }, + SetGlobal: func(s *SessionVars, val string) error { + MaxTSOBatchWaitInterval.Store(tidbOptFloat64(val, DefTiDBTSOClientBatchMaxWaitTime)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBEnableTSOFollowerProxy, Value: BoolToOnOff(DefTiDBEnableTSOFollowerProxy), Type: TypeBool, GetGlobal: func(sv *SessionVars) (string, error) { + return BoolToOnOff(EnableTSOFollowerProxy.Load()), nil + }, SetGlobal: func(s *SessionVars, val string) error { + EnableTSOFollowerProxy.Store(TiDBOptOn(val)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBEnableLocalTxn, Value: BoolToOnOff(DefTiDBEnableLocalTxn), Hidden: true, Type: TypeBool, GetGlobal: func(sv *SessionVars) (string, error) { + return BoolToOnOff(EnableLocalTxn.Load()), nil + }, SetGlobal: func(s *SessionVars, val string) error { + oldVal := EnableLocalTxn.Load() + newVal := TiDBOptOn(val) + // Make sure the TxnScope is always Global when disable the Local Txn. + // ON -> OFF + if oldVal && !newVal { + s.TxnScope = kv.NewGlobalTxnScopeVar() + } + EnableLocalTxn.Store(newVal) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeRatio, Value: strconv.FormatFloat(DefAutoAnalyzeRatio, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: math.MaxUint64}, + {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeStartTime, Value: DefAutoAnalyzeStartTime, Type: TypeTime}, + {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeEndTime, Value: DefAutoAnalyzeEndTime, Type: TypeTime}, + {Scope: ScopeGlobal, Name: TiDBMemQuotaBindingCache, Value: strconv.FormatInt(DefTiDBMemQuotaBindingCache, 10), Type: TypeUnsigned, MaxValue: math.MaxInt32, GetGlobal: func(sv *SessionVars) (string, error) { + return strconv.FormatInt(MemQuotaBindingCache.Load(), 10), nil + }, SetGlobal: func(s *SessionVars, val string) error { + MemQuotaBindingCache.Store(TidbOptInt64(val, DefTiDBMemQuotaBindingCache)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBRowFormatVersion, Value: strconv.Itoa(DefTiDBRowFormatV1), Type: TypeUnsigned, MinValue: 1, MaxValue: 2, SetSession: func(s *SessionVars, val string) error { + formatVersion := int(TidbOptInt64(val, DefTiDBRowFormatV1)) + if formatVersion == DefTiDBRowFormatV1 { + s.RowEncoder.Enable = false + } else if formatVersion == DefTiDBRowFormatV2 { + s.RowEncoder.Enable = true + } + SetDDLReorgRowFormat(TidbOptInt64(val, DefTiDBRowFormatV2)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBDDLReorgWorkerCount, Value: strconv.Itoa(DefTiDBDDLReorgWorkerCount), Type: TypeUnsigned, MinValue: 1, MaxValue: MaxConfigurableConcurrency, SetSession: func(s *SessionVars, val string) error { + SetDDLReorgWorkerCounter(int32(tidbOptPositiveInt32(val, DefTiDBDDLReorgWorkerCount))) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBDDLReorgBatchSize, Value: strconv.Itoa(DefTiDBDDLReorgBatchSize), Type: TypeUnsigned, MinValue: int64(MinDDLReorgBatchSize), MaxValue: uint64(MaxDDLReorgBatchSize), SetSession: func(s *SessionVars, val string) error { + SetDDLReorgBatchSize(int32(tidbOptPositiveInt32(val, DefTiDBDDLReorgBatchSize))) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBDDLErrorCountLimit, Value: strconv.Itoa(DefTiDBDDLErrorCountLimit), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { + SetDDLErrorCountLimit(TidbOptInt64(val, DefTiDBDDLErrorCountLimit)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBMaxDeltaSchemaCount, Value: strconv.Itoa(DefTiDBMaxDeltaSchemaCount), Type: TypeUnsigned, MinValue: 100, MaxValue: 16384, SetSession: func(s *SessionVars, val string) error { + // It's a global variable, but it also wants to be cached in server. + SetMaxDeltaSchemaCount(TidbOptInt64(val, DefTiDBMaxDeltaSchemaCount)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBEnableChangeMultiSchema, Value: BoolToOnOff(DefTiDBChangeMultiSchema), Hidden: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.EnableChangeMultiSchema = TiDBOptOn(val) + return nil + }, SetGlobal: func(s *SessionVars, val string) error { + s.EnableChangeMultiSchema = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBEnablePointGetCache, Value: BoolToOnOff(DefTiDBPointGetCache), Hidden: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.EnablePointGetCache = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBScatterRegion, Value: BoolToOnOff(DefTiDBScatterRegion), Type: TypeBool}, + {Scope: ScopeGlobal, Name: TiDBEnableStmtSummary, Value: BoolToOnOff(DefTiDBEnableStmtSummary), Type: TypeBool, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + return stmtsummary.StmtSummaryByDigestMap.SetEnabled(TiDBOptOn(val)) + }}, + {Scope: ScopeGlobal, Name: TiDBStmtSummaryInternalQuery, Value: BoolToOnOff(DefTiDBStmtSummaryInternalQuery), Type: TypeBool, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + return stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(TiDBOptOn(val)) + }}, + {Scope: ScopeGlobal, Name: TiDBStmtSummaryRefreshInterval, Value: strconv.Itoa(DefTiDBStmtSummaryRefreshInterval), Type: TypeInt, MinValue: 1, MaxValue: math.MaxInt32, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + // convert val to int64 + return stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(TidbOptInt64(val, DefTiDBStmtSummaryRefreshInterval)) + }}, + {Scope: ScopeGlobal, Name: TiDBStmtSummaryHistorySize, Value: strconv.Itoa(DefTiDBStmtSummaryHistorySize), Type: TypeInt, MinValue: 0, MaxValue: math.MaxUint8, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + return stmtsummary.StmtSummaryByDigestMap.SetHistorySize(TidbOptInt(val, DefTiDBStmtSummaryHistorySize)) + }}, + {Scope: ScopeGlobal, Name: TiDBStmtSummaryMaxStmtCount, Value: strconv.Itoa(DefTiDBStmtSummaryMaxStmtCount), Type: TypeInt, MinValue: 1, MaxValue: math.MaxInt16, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + return stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(uint(TidbOptInt(val, DefTiDBStmtSummaryMaxStmtCount))) + }}, + {Scope: ScopeGlobal, Name: TiDBStmtSummaryMaxSQLLength, Value: strconv.Itoa(DefTiDBStmtSummaryMaxSQLLength), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt32, AllowEmpty: true, + SetGlobal: func(s *SessionVars, val string) error { + return stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(TidbOptInt(val, DefTiDBStmtSummaryMaxSQLLength)) + }}, + {Scope: ScopeGlobal, Name: TiDBCapturePlanBaseline, Value: DefTiDBCapturePlanBaseline, Type: TypeBool, AllowEmptyAll: true}, + {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskMaxTime, Value: strconv.Itoa(DefTiDBEvolvePlanTaskMaxTime), Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64}, + {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskStartTime, Value: DefTiDBEvolvePlanTaskStartTime, Type: TypeTime}, + {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskEndTime, Value: DefTiDBEvolvePlanTaskEndTime, Type: TypeTime}, + {Scope: ScopeGlobal, Name: TiDBStoreLimit, Value: strconv.FormatInt(atomic.LoadInt64(&config.GetGlobalConfig().TiKVClient.StoreLimit), 10), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt64, GetGlobal: func(s *SessionVars) (string, error) { + return strconv.FormatInt(tikvstore.StoreLimit.Load(), 10), nil + }, SetGlobal: func(s *SessionVars, val string) error { + tikvstore.StoreLimit.Store(TidbOptInt64(val, DefTiDBStoreLimit)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBTxnCommitBatchSize, Value: strconv.FormatUint(tikvstore.DefTxnCommitBatchSize, 10), Type: TypeUnsigned, MinValue: 1, MaxValue: 1 << 30, + GetGlobal: func(sv *SessionVars) (string, error) { + return strconv.FormatUint(tikvstore.TxnCommitBatchSize.Load(), 10), nil + }, + SetGlobal: func(s *SessionVars, val string) error { + tikvstore.TxnCommitBatchSize.Store(uint64(TidbOptInt64(val, int64(tikvstore.DefTxnCommitBatchSize)))) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBRestrictedReadOnly, Value: BoolToOnOff(DefTiDBRestrictedReadOnly), Type: TypeBool, SetGlobal: func(s *SessionVars, val string) error { + on := TiDBOptOn(val) + if on { + err := s.GlobalVarsAccessor.SetGlobalSysVar(TiDBSuperReadOnly, "ON") + if err != nil { + return err + } + } + RestrictedReadOnly.Store(on) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBSuperReadOnly, Value: BoolToOnOff(DefTiDBSuperReadOnly), Type: TypeBool, Validation: func(vars *SessionVars, normalizedValue string, _ string, _ ScopeFlag) (string, error) { + on := TiDBOptOn(normalizedValue) + if !on { + result, err := vars.GlobalVarsAccessor.GetGlobalSysVar(TiDBRestrictedReadOnly) + if err != nil { + return normalizedValue, err + } + if TiDBOptOn(result) { + return normalizedValue, fmt.Errorf("can't turn off %s when %s is on", TiDBSuperReadOnly, TiDBRestrictedReadOnly) + } + } + return normalizedValue, nil + }, SetGlobal: func(s *SessionVars, val string) error { + VarTiDBSuperReadOnly.Store(TiDBOptOn(val)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBEnableTelemetry, Value: BoolToOnOff(DefTiDBEnableTelemetry), Type: TypeBool}, + {Scope: ScopeGlobal, Name: TiDBEnableHistoricalStats, Value: Off, Type: TypeBool, GetGlobal: func(s *SessionVars) (string, error) { + return getTiDBTableValue(s, "tidb_enable_historical_stats", Off) + }, SetGlobal: func(s *SessionVars, val string) error { + return setTiDBTableValue(s, "tidb_enable_historical_stats", val, "Current historical statistics enable status") + }}, + /* tikv gc metrics */ + {Scope: ScopeGlobal, Name: TiDBGCEnable, Value: On, Type: TypeBool, GetGlobal: func(s *SessionVars) (string, error) { + return getTiDBTableValue(s, "tikv_gc_enable", On) + }, SetGlobal: func(s *SessionVars, val string) error { + return setTiDBTableValue(s, "tikv_gc_enable", val, "Current GC enable status") + }}, + {Scope: ScopeGlobal, Name: TiDBGCRunInterval, Value: "10m0s", Type: TypeDuration, MinValue: int64(time.Minute * 10), MaxValue: uint64(time.Hour * 24 * 365), GetGlobal: func(s *SessionVars) (string, error) { + return getTiDBTableValue(s, "tikv_gc_run_interval", "10m0s") + }, SetGlobal: func(s *SessionVars, val string) error { + return setTiDBTableValue(s, "tikv_gc_run_interval", val, "GC run interval, at least 10m, in Go format.") + }}, + {Scope: ScopeGlobal, Name: TiDBGCLifetime, Value: "10m0s", Type: TypeDuration, MinValue: int64(time.Minute * 10), MaxValue: uint64(time.Hour * 24 * 365), Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + return checkTiKVGCLifeTime(vars, normalizedValue, originalValue, scope) + }, GetGlobal: func(s *SessionVars) (string, error) { + return getTiDBTableValue(s, "tikv_gc_life_time", "10m0s") + }, SetGlobal: func(s *SessionVars, val string) error { + return setTiDBTableValue(s, "tikv_gc_life_time", val, "All versions within life time will not be collected by GC, at least 10m, in Go format.") + }}, + {Scope: ScopeGlobal, Name: TiDBGCConcurrency, Value: "-1", Type: TypeInt, MinValue: 1, MaxValue: MaxConfigurableConcurrency, AllowAutoValue: true, GetGlobal: func(s *SessionVars) (string, error) { + autoConcurrencyVal, err := getTiDBTableValue(s, "tikv_gc_auto_concurrency", On) + if err == nil && autoConcurrencyVal == On { + return "-1", nil // convention for "AUTO" + } + return getTiDBTableValue(s, "tikv_gc_concurrency", "-1") + }, SetGlobal: func(s *SessionVars, val string) error { + autoConcurrency := Off + if val == "-1" { + autoConcurrency = On + } + // Update both autoconcurrency and concurrency. + if err := setTiDBTableValue(s, "tikv_gc_auto_concurrency", autoConcurrency, "Let TiDB pick the concurrency automatically. If set false, tikv_gc_concurrency will be used"); err != nil { + return err + } + return setTiDBTableValue(s, "tikv_gc_concurrency", val, "How many goroutines used to do GC parallel, [1, 256], default 2") + }}, + {Scope: ScopeGlobal, Name: TiDBGCScanLockMode, Value: "LEGACY", Type: TypeEnum, PossibleValues: []string{"PHYSICAL", "LEGACY"}, GetGlobal: func(s *SessionVars) (string, error) { + return getTiDBTableValue(s, "tikv_gc_scan_lock_mode", "LEGACY") + }, SetGlobal: func(s *SessionVars, val string) error { + return setTiDBTableValue(s, "tikv_gc_scan_lock_mode", val, "Mode of scanning locks, \"physical\" or \"legacy\"") + }}, + {Scope: ScopeGlobal, Name: TiDBGCMaxWaitTime, Value: strconv.Itoa(DefTiDBGCMaxWaitTime), Type: TypeInt, MinValue: 600, MaxValue: 31536000, + Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { + return checkGCTxnMaxWaitTime(vars, normalizedValue, originalValue, scope) + }, SetGlobal: func(s *SessionVars, val string) error { + ival, _ := strconv.Atoi(val) + GCMaxWaitTime.Store((int64)(ival)) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBTableCacheLease, Value: strconv.Itoa(DefTiDBTableCacheLease), Type: TypeUnsigned, MinValue: 1, MaxValue: 10, SetGlobal: func(s *SessionVars, sVal string) error { + var val int64 + val, err := strconv.ParseInt(sVal, 10, 64) + if err != nil { + return errors.Trace(err) + } + TableCacheLease.Store(val) + return nil + }}, + // variable for top SQL feature. + // TopSQL enable only be controlled by TopSQL pub/sub sinker. + // This global variable only uses to update the global config which store in PD(ETCD). + {Scope: ScopeGlobal, Name: TiDBEnableTopSQL, Value: BoolToOnOff(topsqlstate.DefTiDBTopSQLEnable), Type: TypeBool, AllowEmpty: true, GlobalConfigName: GlobalConfigEnableTopSQL}, + {Scope: ScopeGlobal, Name: TiDBTopSQLMaxTimeSeriesCount, Value: strconv.Itoa(topsqlstate.DefTiDBTopSQLMaxTimeSeriesCount), Type: TypeInt, MinValue: 1, MaxValue: 5000, GetGlobal: func(s *SessionVars) (string, error) { + return strconv.FormatInt(topsqlstate.GlobalState.MaxStatementCount.Load(), 10), nil + }, SetGlobal: func(vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + topsqlstate.GlobalState.MaxStatementCount.Store(val) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBTopSQLMaxMetaCount, Value: strconv.Itoa(topsqlstate.DefTiDBTopSQLMaxMetaCount), Type: TypeInt, MinValue: 1, MaxValue: 10000, GetGlobal: func(s *SessionVars) (string, error) { + return strconv.FormatInt(topsqlstate.GlobalState.MaxCollect.Load(), 10), nil + }, SetGlobal: func(vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + topsqlstate.GlobalState.MaxCollect.Store(val) + return nil + }}, + {Scope: ScopeGlobal, Name: SkipNameResolve, Value: Off, Type: TypeBool}, + {Scope: ScopeGlobal, Name: DefaultAuthPlugin, Value: mysql.AuthNativePassword, Type: TypeEnum, PossibleValues: []string{mysql.AuthNativePassword, mysql.AuthCachingSha2Password}}, + {Scope: ScopeGlobal, Name: TiDBPersistAnalyzeOptions, Value: BoolToOnOff(DefTiDBPersistAnalyzeOptions), skipInit: true, Type: TypeBool, + GetGlobal: func(s *SessionVars) (string, error) { + return BoolToOnOff(PersistAnalyzeOptions.Load()), nil + }, + SetGlobal: func(s *SessionVars, val string) error { + PersistAnalyzeOptions.Store(TiDBOptOn(val)) + return nil + }, + }, + {Scope: ScopeGlobal, Name: TiDBEnableColumnTracking, Value: BoolToOnOff(DefTiDBEnableColumnTracking), skipInit: true, Type: TypeBool, GetGlobal: func(s *SessionVars) (string, error) { + return BoolToOnOff(EnableColumnTracking.Load()), nil + }, SetGlobal: func(s *SessionVars, val string) error { + v := TiDBOptOn(val) + if !v { + // Set the location to UTC to avoid time zone interference. + disableTime := time.Now().UTC().Format(types.UTCTimeFormat) + if err := setTiDBTableValue(s, TiDBDisableColumnTrackingTime, disableTime, "Record the last time tidb_enable_column_tracking is set off"); err != nil { + return err + } + } + EnableColumnTracking.Store(v) + return nil + }}, + {Scope: ScopeGlobal, Name: TiDBStatsLoadPseudoTimeout, Value: BoolToOnOff(DefTiDBStatsLoadPseudoTimeout), skipInit: true, Type: TypeBool, + GetGlobal: func(s *SessionVars) (string, error) { + return strconv.FormatBool(StatsLoadPseudoTimeout.Load()), nil + }, + SetGlobal: func(s *SessionVars, val string) error { + StatsLoadPseudoTimeout.Store(TiDBOptOn(val)) + return nil + }, + }, + + /* The system variables below have GLOBAL and SESSION scope */ {Scope: ScopeGlobal | ScopeSession, Name: SQLSelectLimit, Value: "18446744073709551615", Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxUint64, SetSession: func(s *SessionVars, val string) error { result, err := strconv.ParseUint(val, 10, 64) if err != nil { @@ -97,7 +743,6 @@ var defaultSysVars = []*SysVar{ s.TimeZone = tz return nil }}, - {Scope: ScopeNone, Name: SystemTimeZone, Value: "CST"}, {Scope: ScopeGlobal | ScopeSession, Name: ForeignKeyChecks, Value: Off, Type: TypeBool, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { if TiDBOptOn(normalizedValue) { // TiDB does not yet support foreign keys. @@ -109,18 +754,6 @@ var defaultSysVars = []*SysVar{ } return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(ForeignKeyChecks, originalValue) }}, - {Scope: ScopeGlobal | ScopeSession, Name: PlacementChecks, Value: On, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.EnablePlacementChecks = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeNone, Name: Hostname, Value: DefHostname}, - {Scope: ScopeSession, Name: Timestamp, Value: DefTimestamp, skipInit: true, MinValue: 0, MaxValue: 2147483647, Type: TypeFloat, GetSession: func(s *SessionVars) (string, error) { - if timestamp, ok := s.systems[Timestamp]; ok && timestamp != DefTimestamp { - return timestamp, nil - } - timestamp := s.StmtCtx.GetOrStoreStmtCache(stmtctx.StmtNowTsCacheKey, time.Now()).(time.Time) - return types.ToString(float64(timestamp.UnixNano()) / float64(time.Second)) - }}, {Scope: ScopeGlobal | ScopeSession, Name: CollationDatabase, Value: mysql.DefaultCollationName, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { return checkCollation(vars, normalizedValue, originalValue, scope) }, SetSession: func(s *SessionVars, val string) error { @@ -142,16 +775,12 @@ var defaultSysVars = []*SysVar{ {Scope: ScopeGlobal | ScopeSession, Name: CharacterSetClient, Value: mysql.DefaultCharset, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { return checkCharacterSet(normalizedValue, CharacterSetClient) }}, - {Scope: ScopeNone, Name: Port, Value: "4000", Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxUint16}, - {Scope: ScopeNone, Name: LowerCaseTableNames, Value: "2"}, - {Scope: ScopeNone, Name: LogBin, Value: Off, Type: TypeBool}, {Scope: ScopeGlobal | ScopeSession, Name: CharacterSetResults, Value: mysql.DefaultCharset, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { if normalizedValue == "" { return normalizedValue, nil } return checkCharacterSet(normalizedValue, "") }}, - {Scope: ScopeNone, Name: VersionComment, Value: "TiDB Server (Apache License 2.0) " + versioninfo.TiDBEdition + " Edition, MySQL 5.7 compatible"}, {Scope: ScopeGlobal | ScopeSession, Name: TxnIsolation, Value: "REPEATABLE-READ", Type: TypeEnum, Aliases: []string{TransactionIsolation}, PossibleValues: []string{"READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE"}, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { // MySQL appends a warning here for tx_isolation is deprecated // TiDB doesn't currently, but may in future. It is still commonly used by applications @@ -169,7 +798,6 @@ var defaultSysVars = []*SysVar{ } return nil }}, - {Scope: ScopeNone, Name: Version, Value: mysql.ServerVersion}, {Scope: ScopeGlobal | ScopeSession, Name: AutoCommit, Value: On, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { isAutocommit := TiDBOptOn(val) s.SetStatusFlag(mysql.ServerStatusAutocommit, isAutocommit) @@ -186,12 +814,10 @@ var defaultSysVars = []*SysVar{ } return nil }}, - {Scope: ScopeGlobal, Name: MaxPreparedStmtCount, Value: strconv.FormatInt(DefMaxPreparedStmtCount, 10), Type: TypeInt, MinValue: -1, MaxValue: 1048576}, - {Scope: ScopeNone, Name: DataDir, Value: "/usr/local/mysql/data/"}, {Scope: ScopeGlobal | ScopeSession, Name: WaitTimeout, Value: strconv.FormatInt(DefWaitTimeout, 10), Type: TypeUnsigned, MinValue: 0, MaxValue: secondsPerYear}, {Scope: ScopeGlobal | ScopeSession, Name: InteractiveTimeout, Value: "28800", Type: TypeUnsigned, MinValue: 1, MaxValue: secondsPerYear}, - {Scope: ScopeGlobal | ScopeSession, Name: InnodbLockWaitTimeout, Value: strconv.FormatInt(DefInnodbLockWaitTimeout, 10), Type: TypeUnsigned, MinValue: 1, MaxValue: 1073741824, SetSession: func(s *SessionVars, val string) error { - lockWaitSec := tidbOptInt64(val, DefInnodbLockWaitTimeout) + {Scope: ScopeGlobal | ScopeSession, Name: InnodbLockWaitTimeout, Value: strconv.FormatInt(DefInnodbLockWaitTimeout, 10), Type: TypeUnsigned, MinValue: 1, MaxValue: 3600, SetSession: func(s *SessionVars, val string) error { + lockWaitSec := TidbOptInt64(val, DefInnodbLockWaitTimeout) s.LockWaitTimeout = lockWaitSec * 1000 return nil }}, @@ -204,13 +830,12 @@ var defaultSysVars = []*SysVar{ if val, err := strconv.ParseUint(normalizedValue, 10, 64); err == nil { if val > uint64(math.MaxUint32) { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(GroupConcatMaxLen, originalValue)) - return fmt.Sprintf("%d", math.MaxUint32), nil + return strconv.FormatInt(int64(math.MaxUint32), 10), nil } } } return normalizedValue, nil }}, - {Scope: ScopeNone, Name: Socket, Value: ""}, {Scope: ScopeGlobal | ScopeSession, Name: CharacterSetConnection, Value: mysql.DefaultCharset, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { return checkCharacterSet(normalizedValue, CharacterSetConnection) }, SetSession: func(s *SessionVars, val string) error { @@ -222,94 +847,18 @@ var defaultSysVars = []*SysVar{ {Scope: ScopeGlobal | ScopeSession, Name: CharacterSetServer, Value: mysql.DefaultCharset, skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { return checkCharacterSet(normalizedValue, CharacterSetServer) }, SetSession: func(s *SessionVars, val string) error { - if cs, err := charset.GetCharsetInfo(val); err == nil { - s.systems[CollationServer] = cs.DefaultCollation - } - return nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: MaxAllowedPacket, Value: "67108864", Type: TypeUnsigned, MinValue: 1024, MaxValue: MaxOfMaxAllowedPacket}, - {Scope: ScopeSession, Name: WarningCount, Value: "0", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return strconv.Itoa(s.SysWarningCount), nil - }}, - {Scope: ScopeSession, Name: ErrorCount, Value: "0", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return strconv.Itoa(int(s.SysErrorCount)), nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: WindowingUseHighPrecision, Value: On, Type: TypeBool, IsHintUpdatable: true, SetSession: func(s *SessionVars, val string) error { - s.WindowingUseHighPrecision = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeNone, Name: "license", Value: "Apache License 2.0"}, - {Scope: ScopeGlobal | ScopeSession, Name: BlockEncryptionMode, Value: "aes-128-ecb"}, - {Scope: ScopeSession, Name: LastInsertID, Value: "", skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatUint(s.StmtCtx.PrevLastInsertID, 10), nil - }}, - {Scope: ScopeSession, Name: Identity, Value: "", skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatUint(s.StmtCtx.PrevLastInsertID, 10), nil - }}, - {Scope: ScopeNone, Name: "have_ssl", Value: "DISABLED"}, - {Scope: ScopeNone, Name: "have_openssl", Value: "DISABLED"}, - {Scope: ScopeNone, Name: "ssl_ca", Value: ""}, - {Scope: ScopeNone, Name: "ssl_cert", Value: ""}, - {Scope: ScopeNone, Name: "ssl_key", Value: ""}, - {Scope: ScopeGlobal, Name: InitConnect, Value: ""}, - - /* TiDB specific variables */ - {Scope: ScopeGlobal, Name: TiDBTSOClientBatchMaxWaitTime, Value: strconv.FormatFloat(DefTiDBTSOClientBatchMaxWaitTime, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: 10, - GetGlobal: func(sv *SessionVars) (string, error) { - return strconv.FormatFloat(MaxTSOBatchWaitInterval.Load(), 'f', -1, 64), nil - }, - SetGlobal: func(s *SessionVars, val string) error { - MaxTSOBatchWaitInterval.Store(tidbOptFloat64(val, DefTiDBTSOClientBatchMaxWaitTime)) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnableTSOFollowerProxy, Value: BoolToOnOff(DefTiDBEnableTSOFollowerProxy), Type: TypeBool, GetGlobal: func(sv *SessionVars) (string, error) { - return BoolToOnOff(EnableTSOFollowerProxy.Load()), nil - }, SetGlobal: func(s *SessionVars, val string) error { - EnableTSOFollowerProxy.Store(TiDBOptOn(val)) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnableLocalTxn, Value: BoolToOnOff(DefTiDBEnableLocalTxn), Hidden: true, Type: TypeBool, GetGlobal: func(sv *SessionVars) (string, error) { - return BoolToOnOff(EnableLocalTxn.Load()), nil - }, SetGlobal: func(s *SessionVars, val string) error { - oldVal := EnableLocalTxn.Load() - newVal := TiDBOptOn(val) - // Make sure the TxnScope is always Global when disable the Local Txn. - // ON -> OFF - if oldVal && !newVal { - s.TxnScope = kv.NewGlobalTxnScopeVar() - } - EnableLocalTxn.Store(newVal) - return nil - }}, - // TODO: TiDBTxnScope is hidden because local txn feature is not done. - {Scope: ScopeSession, Name: TiDBTxnScope, skipInit: true, Hidden: true, Value: kv.GlobalTxnScope, SetSession: func(s *SessionVars, val string) error { - switch val { - case kv.GlobalTxnScope: - s.TxnScope = kv.NewGlobalTxnScopeVar() - case kv.LocalTxnScope: - if !EnableLocalTxn.Load() { - return ErrWrongValueForVar.GenWithStack("@@txn_scope can not be set to local when tidb_enable_local_txn is off") - } - txnScope := config.GetTxnScopeFromConfig() - if txnScope == kv.GlobalTxnScope { - return ErrWrongValueForVar.GenWithStack("@@txn_scope can not be set to local when zone label is empty or \"global\"") - } - s.TxnScope = kv.NewLocalTxnScopeVar(txnScope) - default: - return ErrWrongValueForVar.GenWithStack("@@txn_scope value should be global or local") + if cs, err := charset.GetCharsetInfo(val); err == nil { + s.systems[CollationServer] = cs.DefaultCollation } return nil - }, GetSession: func(s *SessionVars) (string, error) { - return s.TxnScope.GetVarValue(), nil - }}, - {Scope: ScopeSession, Name: TiDBTxnReadTS, Value: "", Hidden: true, SetSession: func(s *SessionVars, val string) error { - return setTxnReadTS(s, val) - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - return normalizedValue, nil }}, - {Scope: ScopeSession, Name: TiDBReadStaleness, Value: "", Hidden: false, SetSession: func(s *SessionVars, val string) error { - return setReadStaleness(s, val) + {Scope: ScopeGlobal | ScopeSession, Name: MaxAllowedPacket, Value: "67108864", Type: TypeUnsigned, MinValue: 1024, MaxValue: MaxOfMaxAllowedPacket}, + {Scope: ScopeGlobal | ScopeSession, Name: WindowingUseHighPrecision, Value: On, Type: TypeBool, IsHintUpdatable: true, SetSession: func(s *SessionVars, val string) error { + s.WindowingUseHighPrecision = TiDBOptOn(val) + return nil }}, + {Scope: ScopeGlobal | ScopeSession, Name: BlockEncryptionMode, Value: "aes-128-ecb"}, + /* TiDB specific variables */ {Scope: ScopeGlobal | ScopeSession, Name: TiDBAllowMPPExecution, Type: TypeBool, Value: BoolToOnOff(DefTiDBAllowMPPExecution), SetSession: func(s *SessionVars, val string) error { s.allowMPPExecution = TiDBOptOn(val) return nil @@ -322,64 +871,23 @@ var defaultSysVars = []*SysVar{ s.HashExchangeWithNewCollation = TiDBOptOn(val) return nil }}, - {Scope: ScopeSession, Name: TiDBEnforceMPPExecution, Type: TypeBool, Value: BoolToOnOff(config.GetGlobalConfig().Performance.EnforceMPP), Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - if TiDBOptOn(normalizedValue) && !vars.allowMPPExecution { - return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs("tidb_enforce_mpp", "1' but tidb_allow_mpp is 0, please activate tidb_allow_mpp at first.") - } - return normalizedValue, nil - }, SetSession: func(s *SessionVars, val string) error { - s.enforceMPPExecution = TiDBOptOn(val) - return nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBBCJThresholdCount, Value: strconv.Itoa(DefBroadcastJoinThresholdCount), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.BroadcastJoinThresholdCount = tidbOptInt64(val, DefBroadcastJoinThresholdCount) + s.BroadcastJoinThresholdCount = TidbOptInt64(val, DefBroadcastJoinThresholdCount) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBBCJThresholdSize, Value: strconv.Itoa(DefBroadcastJoinThresholdSize), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.BroadcastJoinThresholdSize = tidbOptInt64(val, DefBroadcastJoinThresholdSize) - return nil - }}, - {Scope: ScopeSession, Name: TiDBSnapshot, Value: "", skipInit: true, SetSession: func(s *SessionVars, val string) error { - err := setSnapshotTS(s, val) - if err != nil { - return err - } - return nil - }}, - {Scope: ScopeSession, Name: TiDBOptAggPushDown, Value: BoolToOnOff(DefOptAggPushDown), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.AllowAggPushDown = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptBCJ, Value: BoolToOnOff(DefOptBCJ), Type: TypeBool, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - if TiDBOptOn(normalizedValue) && vars.AllowBatchCop == 0 { - return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(TiDBOptBCJ, "'true' while tidb_allow_batch_cop is 0, please active batch cop at first.") - } - return normalizedValue, nil - }, SetSession: func(s *SessionVars, val string) error { - s.AllowBCJ = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBOptDistinctAggPushDown, Value: BoolToOnOff(config.GetGlobalConfig().Performance.DistinctAggPushDown), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.AllowDistinctAggPushDown = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBOptWriteRowID, Value: BoolToOnOff(DefOptWriteRowID), skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.AllowWriteRowID = TiDBOptOn(val) + s.BroadcastJoinThresholdSize = TidbOptInt64(val, DefBroadcastJoinThresholdSize) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBBuildStatsConcurrency, skipInit: true, Value: strconv.Itoa(DefBuildStatsConcurrency)}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptCartesianBCJ, Value: strconv.Itoa(DefOptCartesianBCJ), Type: TypeInt, MinValue: 0, MaxValue: 2, SetSession: func(s *SessionVars, val string) error { - s.AllowCartesianBCJ = tidbOptInt(val, DefOptCartesianBCJ) + s.AllowCartesianBCJ = TidbOptInt(val, DefOptCartesianBCJ) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptMPPOuterJoinFixedBuildSide, Value: BoolToOnOff(DefOptMPPOuterJoinFixedBuildSide), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.MPPOuterJoinFixedBuildSide = TiDBOptOn(val) return nil }}, - {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeRatio, Value: strconv.FormatFloat(DefAutoAnalyzeRatio, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: math.MaxUint64}, - {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeStartTime, Value: DefAutoAnalyzeStartTime, Type: TypeTime}, - {Scope: ScopeGlobal, Name: TiDBAutoAnalyzeEndTime, Value: DefAutoAnalyzeEndTime, Type: TypeTime}, - {Scope: ScopeSession, Name: TiDBChecksumTableConcurrency, skipInit: true, Value: strconv.Itoa(DefChecksumTableConcurrency)}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBExecutorConcurrency, Value: strconv.Itoa(DefExecutorConcurrency), Type: TypeUnsigned, MinValue: 1, MaxValue: MaxConfigurableConcurrency, SetSession: func(s *SessionVars, val string) error { s.ExecutorConcurrency = tidbOptPositiveInt32(val, DefExecutorConcurrency) return nil @@ -396,11 +904,10 @@ var defaultSysVars = []*SysVar{ s.SetAllowPreferRangeScan(TiDBOptOn(val)) return nil }}, - { - Scope: ScopeGlobal | ScopeSession, Name: TiDBOptLimitPushDownThreshold, Value: strconv.Itoa(DefOptLimitPushDownThreshold), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.LimitPushDownThreshold = tidbOptInt64(val, DefOptLimitPushDownThreshold) - return nil - }}, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptLimitPushDownThreshold, Value: strconv.Itoa(DefOptLimitPushDownThreshold), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.LimitPushDownThreshold = TidbOptInt64(val, DefOptLimitPushDownThreshold) + return nil + }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptCorrelationThreshold, Value: strconv.FormatFloat(DefOptCorrelationThreshold, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: 1, SetSession: func(s *SessionVars, val string) error { s.CorrelationThreshold = tidbOptFloat64(val, DefOptCorrelationThreshold) return nil @@ -410,7 +917,7 @@ var defaultSysVars = []*SysVar{ return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptCorrelationExpFactor, Value: strconv.Itoa(DefOptCorrelationExpFactor), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.CorrelationExpFactor = int(tidbOptInt64(val, DefOptCorrelationExpFactor)) + s.CorrelationExpFactor = int(TidbOptInt64(val, DefOptCorrelationExpFactor)) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptCPUFactor, Value: strconv.FormatFloat(DefOptCPUFactor, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: math.MaxUint64, SetSession: func(s *SessionVars, val string) error { @@ -449,6 +956,10 @@ var defaultSysVars = []*SysVar{ s.DiskFactor = tidbOptFloat64(val, DefOptDiskFactor) return nil }}, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptimizerEnableNewOnlyFullGroupByCheck, Value: BoolToOnOff(DefTiDBOptimizerEnableNewOFGB), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.OptimizerEnableNewOnlyFullGroupByCheck = TiDBOptOn(val) + return nil + }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptConcurrencyFactor, Value: strconv.FormatFloat(DefOptConcurrencyFactor, 'f', -1, 64), Type: TypeFloat, MinValue: 0, MaxValue: math.MaxUint64, SetSession: func(s *SessionVars, val string) error { s.ConcurrencyFactor = tidbOptFloat64(val, DefOptConcurrencyFactor) return nil @@ -487,46 +998,16 @@ var defaultSysVars = []*SysVar{ s.SkipASCIICheck = TiDBOptOn(val) return nil }}, - {Scope: ScopeSession, Name: TiDBBatchInsert, Value: BoolToOnOff(DefBatchInsert), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.BatchInsert = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBBatchDelete, Value: BoolToOnOff(DefBatchDelete), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.BatchDelete = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBBatchCommit, Value: BoolToOnOff(DefBatchCommit), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.BatchCommit = TiDBOptOn(val) - return nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBDMLBatchSize, Value: strconv.Itoa(DefDMLBatchSize), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.DMLBatchSize = int(tidbOptInt64(val, DefDMLBatchSize)) + s.DMLBatchSize = int(TidbOptInt64(val, DefDMLBatchSize)) return nil }}, - {Scope: ScopeSession, Name: TiDBCurrentTS, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return fmt.Sprintf("%d", s.TxnCtx.StartTS), nil - }}, - {Scope: ScopeSession, Name: TiDBLastTxnInfo, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return s.LastTxnInfo, nil - }}, - {Scope: ScopeSession, Name: TiDBLastQueryInfo, Value: strconv.Itoa(DefCurretTS), ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - info, err := json.Marshal(s.LastQueryInfo) - if err != nil { - return "", err - } - return string(info), nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBMaxChunkSize, Value: strconv.Itoa(DefMaxChunkSize), Type: TypeUnsigned, MinValue: maxChunkSizeLowerBound, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { s.MaxChunkSize = tidbOptPositiveInt32(val, DefMaxChunkSize) return nil }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBAllowBatchCop, Value: strconv.Itoa(DefTiDBAllowBatchCop), Type: TypeInt, MinValue: 0, MaxValue: 2, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - if normalizedValue == "0" && vars.AllowBCJ { - return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(TiDBAllowBatchCop, "'0' while tidb_opt_broadcast_join is true, please set tidb_opt_broadcast_join false at first") - } - return normalizedValue, nil - }, SetSession: func(s *SessionVars, val string) error { - s.AllowBatchCop = int(tidbOptInt64(val, DefTiDBAllowBatchCop)) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBAllowBatchCop, Value: strconv.Itoa(DefTiDBAllowBatchCop), Type: TypeInt, MinValue: 0, MaxValue: 2, SetSession: func(s *SessionVars, val string) error { + s.AllowBatchCop = int(TidbOptInt64(val, DefTiDBAllowBatchCop)) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBInitChunkSize, Value: strconv.Itoa(DefInitChunkSize), Type: TypeUnsigned, MinValue: 1, MaxValue: initChunkSizeUpperBound, SetSession: func(s *SessionVars, val string) error { @@ -537,72 +1018,10 @@ var defaultSysVars = []*SysVar{ s.SetEnableCascadesPlanner(TiDBOptOn(val)) return nil }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableIndexMerge, Value: Off, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableIndexMerge, Value: BoolToOnOff(DefTiDBEnableIndexMerge), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.SetEnableIndexMerge(TiDBOptOn(val)) return nil }}, - {Scope: ScopeSession, Name: TiDBMemQuotaQuery, Value: strconv.FormatInt(config.GetGlobalConfig().MemQuotaQuery, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaQuery = tidbOptInt64(val, config.GetGlobalConfig().MemQuotaQuery) - return nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaHashJoin, Value: strconv.FormatInt(DefTiDBMemQuotaHashJoin, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaHashJoin = tidbOptInt64(val, DefTiDBMemQuotaHashJoin) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaHashJoin, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaMergeJoin, Value: strconv.FormatInt(DefTiDBMemQuotaMergeJoin, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaMergeJoin = tidbOptInt64(val, DefTiDBMemQuotaMergeJoin) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaMergeJoin, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaSort, Value: strconv.FormatInt(DefTiDBMemQuotaSort, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaSort = tidbOptInt64(val, DefTiDBMemQuotaSort) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaSort, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaTopn, Value: strconv.FormatInt(DefTiDBMemQuotaTopn, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaTopn = tidbOptInt64(val, DefTiDBMemQuotaTopn) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaTopn, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaIndexLookupReader, Value: strconv.FormatInt(DefTiDBMemQuotaIndexLookupReader, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaIndexLookupReader = tidbOptInt64(val, DefTiDBMemQuotaIndexLookupReader) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaIndexLookupReader, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - {Scope: ScopeSession, Name: TiDBMemQuotaIndexLookupJoin, Value: strconv.FormatInt(DefTiDBMemQuotaIndexLookupJoin, 10), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaIndexLookupJoin = tidbOptInt64(val, DefTiDBMemQuotaIndexLookupJoin) - return nil - }, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - appendDeprecationWarning(vars, TiDBMemQuotaIndexLookupJoin, TiDBMemQuotaQuery) - return normalizedValue, nil - }}, - // Deprecated: tidb_enable_streaming - {Scope: ScopeSession, Name: TiDBEnableStreaming, Value: Off, Type: TypeBool, skipInit: true, Hidden: true, SetSession: func(s *SessionVars, val string) error { - s.EnableStreaming = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBEnableChunkRPC, Value: On, Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.EnableChunkRPC = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TxnIsolationOneShot, Value: "", skipInit: true, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - return checkIsolationLevel(vars, normalizedValue, originalValue, scope) - }, SetSession: func(s *SessionVars, val string) error { - s.txnIsolationLevelOneShot.state = oneShotSet - s.txnIsolationLevelOneShot.value = val - return nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableTablePartition, Value: On, Type: TypeEnum, PossibleValues: []string{Off, On, "AUTO"}, SetSession: func(s *SessionVars, val string) error { s.EnableTablePartition = val return nil @@ -653,7 +1072,6 @@ var defaultSysVars = []*SysVar{ appendDeprecationWarning(vars, TiDBMergeJoinConcurrency, TiDBExecutorConcurrency) return normalizedValue, nil }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStreamAggConcurrency, Value: strconv.Itoa(DefTiDBStreamAggConcurrency), Type: TypeInt, MinValue: 1, MaxValue: MaxConfigurableConcurrency, AllowAutoValue: true, SetSession: func(s *SessionVars, val string) error { s.streamAggConcurrency = tidbOptPositiveInt32(val, ConcurrencyUnset) return nil @@ -666,19 +1084,19 @@ var defaultSysVars = []*SysVar{ return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBMemQuotaApplyCache, Value: strconv.Itoa(DefTiDBMemQuotaApplyCache), Type: TypeUnsigned, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.MemQuotaApplyCache = tidbOptInt64(val, DefTiDBMemQuotaApplyCache) + s.MemQuotaApplyCache = TidbOptInt64(val, DefTiDBMemQuotaApplyCache) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBBackoffLockFast, Value: strconv.Itoa(tikvstore.DefBackoffLockFast), Type: TypeUnsigned, MinValue: 1, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { s.KVVars.BackoffLockFast = tidbOptPositiveInt32(val, tikvstore.DefBackoffLockFast) return nil }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBBackOffWeight, Value: strconv.Itoa(tikvstore.DefBackOffWeight), Type: TypeUnsigned, MinValue: 1, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + {Scope: ScopeGlobal | ScopeSession, Name: TiDBBackOffWeight, Value: strconv.Itoa(tikvstore.DefBackOffWeight), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { s.KVVars.BackOffWeight = tidbOptPositiveInt32(val, tikvstore.DefBackOffWeight) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBRetryLimit, Value: strconv.Itoa(DefTiDBRetryLimit), Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - s.RetryLimit = tidbOptInt64(val, DefTiDBRetryLimit) + s.RetryLimit = TidbOptInt64(val, DefTiDBRetryLimit) return nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBDisableTxnAutoRetry, Value: BoolToOnOff(DefTiDBDisableTxnAutoRetry), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { @@ -693,20 +1111,6 @@ var defaultSysVars = []*SysVar{ s.TxnMode = strings.ToUpper(val) return nil }}, - {Scope: ScopeGlobal, Name: TiDBRowFormatVersion, Value: strconv.Itoa(DefTiDBRowFormatV1), Type: TypeUnsigned, MinValue: 1, MaxValue: 2, SetSession: func(s *SessionVars, val string) error { - formatVersion := int(tidbOptInt64(val, DefTiDBRowFormatV1)) - if formatVersion == DefTiDBRowFormatV1 { - s.RowEncoder.Enable = false - } else if formatVersion == DefTiDBRowFormatV2 { - s.RowEncoder.Enable = true - } - SetDDLReorgRowFormat(tidbOptInt64(val, DefTiDBRowFormatV2)) - return nil - }}, - {Scope: ScopeSession, Name: TiDBOptimizerSelectivityLevel, Value: strconv.Itoa(DefTiDBOptimizerSelectivityLevel), skipInit: true, Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.OptimizerSelectivityLevel = tidbOptPositiveInt32(val, DefTiDBOptimizerSelectivityLevel) - return nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableWindowFunction, Value: BoolToOnOff(DefEnableWindowFunction), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.EnableWindowFunction = TiDBOptOn(val) return nil @@ -754,146 +1158,28 @@ var defaultSysVars = []*SysVar{ return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(TiDBAllowFallbackToTiKV, normalizedValue) } } - return formatVal, nil - }, SetSession: func(s *SessionVars, val string) error { - s.AllowFallbackToTiKV = make(map[kv.StoreType]struct{}) - for _, engine := range strings.Split(val, ",") { - switch engine { - case kv.TiFlash.Name(): - s.AllowFallbackToTiKV[kv.TiFlash] = struct{}{} - } - } - return nil - }}, - /* The following variable is defined as session scope but is actually server scope. */ - {Scope: ScopeSession, Name: TiDBGeneralLog, Value: BoolToOnOff(DefTiDBGeneralLog), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - ProcessGeneralLog.Store(TiDBOptOn(val)) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(ProcessGeneralLog.Load()), nil - }}, - {Scope: ScopeSession, Name: TiDBLogFileMaxDays, Value: strconv.Itoa(config.GetGlobalConfig().Log.File.MaxDays), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt32, skipInit: true, SetSession: func(s *SessionVars, val string) error { - maxAge, err := strconv.ParseInt(val, 10, 32) - if err != nil { - return err - } - - GlobalLogMaxDays.Store(int32(maxAge)) - - cfg := config.GetGlobalConfig().Log.ToLogConfig() - cfg.Config.File.MaxDays = int(maxAge) - - err = logutil.ReplaceLogger(cfg) - if err != nil { - return err - } - - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatInt(int64(GlobalLogMaxDays.Load()), 10), nil - }}, - {Scope: ScopeSession, Name: TiDBPProfSQLCPU, Value: strconv.Itoa(DefTiDBPProfSQLCPU), Type: TypeInt, skipInit: true, MinValue: 0, MaxValue: 1, SetSession: func(s *SessionVars, val string) error { - EnablePProfSQLCPU.Store(uint32(tidbOptPositiveInt32(val, DefTiDBPProfSQLCPU)) > 0) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - val := "0" - if EnablePProfSQLCPU.Load() { - val = "1" - } - return val, nil - }}, - {Scope: ScopeSession, Name: TiDBDDLSlowOprThreshold, Value: strconv.Itoa(DefTiDBDDLSlowOprThreshold), skipInit: true, SetSession: func(s *SessionVars, val string) error { - atomic.StoreUint32(&DDLSlowOprThreshold, uint32(tidbOptPositiveInt32(val, DefTiDBDDLSlowOprThreshold))) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatUint(uint64(atomic.LoadUint32(&DDLSlowOprThreshold)), 10), nil - }}, - {Scope: ScopeSession, Name: TiDBConfig, Value: "", ReadOnly: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - conf := config.GetGlobalConfig() - j, err := json.MarshalIndent(conf, "", "\t") - if err != nil { - return "", err - } - return config.HideConfig(string(j)), nil - }}, - {Scope: ScopeGlobal, Name: TiDBDDLReorgWorkerCount, Value: strconv.Itoa(DefTiDBDDLReorgWorkerCount), Type: TypeUnsigned, MinValue: 1, MaxValue: MaxConfigurableConcurrency, SetSession: func(s *SessionVars, val string) error { - SetDDLReorgWorkerCounter(int32(tidbOptPositiveInt32(val, DefTiDBDDLReorgWorkerCount))) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBDDLReorgBatchSize, Value: strconv.Itoa(DefTiDBDDLReorgBatchSize), Type: TypeUnsigned, MinValue: int64(MinDDLReorgBatchSize), MaxValue: uint64(MaxDDLReorgBatchSize), SetSession: func(s *SessionVars, val string) error { - SetDDLReorgBatchSize(int32(tidbOptPositiveInt32(val, DefTiDBDDLReorgBatchSize))) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBDDLErrorCountLimit, Value: strconv.Itoa(DefTiDBDDLErrorCountLimit), Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - SetDDLErrorCountLimit(tidbOptInt64(val, DefTiDBDDLErrorCountLimit)) - return nil - }}, - {Scope: ScopeSession, Name: TiDBDDLReorgPriority, Value: "PRIORITY_LOW", skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.setDDLReorgPriority(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBMaxDeltaSchemaCount, Value: strconv.Itoa(DefTiDBMaxDeltaSchemaCount), Type: TypeUnsigned, MinValue: 100, MaxValue: 16384, SetSession: func(s *SessionVars, val string) error { - // It's a global variable, but it also wants to be cached in server. - SetMaxDeltaSchemaCount(tidbOptInt64(val, DefTiDBMaxDeltaSchemaCount)) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnableChangeMultiSchema, Value: BoolToOnOff(DefTiDBChangeMultiSchema), Hidden: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.EnableChangeMultiSchema = TiDBOptOn(val) - return nil - }, SetGlobal: func(s *SessionVars, val string) error { - s.EnableChangeMultiSchema = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableAutoIncrementInGenerated, Value: BoolToOnOff(DefTiDBEnableAutoIncrementInGenerated), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.EnableAutoIncrementInGenerated = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnablePointGetCache, Value: BoolToOnOff(DefTiDBPointGetCache), Hidden: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.EnablePointGetCache = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnableAlterPlacement, Value: BoolToOnOff(DefTiDBEnableAlterPlacement), Hidden: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.EnableAlterPlacement = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBForcePriority, skipInit: true, Value: mysql.Priority2Str[DefTiDBForcePriority], SetSession: func(s *SessionVars, val string) error { - atomic.StoreInt32(&ForcePriority, int32(mysql.Str2Priority(val))) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return mysql.Priority2Str[mysql.PriorityEnum(atomic.LoadInt32(&ForcePriority))], nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptJoinReorderThreshold, Value: strconv.Itoa(DefTiDBOptJoinReorderThreshold), skipInit: true, Type: TypeUnsigned, MinValue: 0, MaxValue: 63, SetSession: func(s *SessionVars, val string) error { - s.TiDBOptJoinReorderThreshold = tidbOptPositiveInt32(val, DefTiDBOptJoinReorderThreshold) - return nil - }}, - {Scope: ScopeSession, Name: TiDBSlowQueryFile, Value: "", skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.SlowQueryFile = val - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBScatterRegion, Value: BoolToOnOff(DefTiDBScatterRegion), Type: TypeBool}, - {Scope: ScopeSession, Name: TiDBWaitSplitRegionFinish, Value: BoolToOnOff(DefTiDBWaitSplitRegionFinish), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.WaitSplitRegionFinish = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeSession, Name: TiDBWaitSplitRegionTimeout, Value: strconv.Itoa(DefWaitSplitRegionTimeout), skipInit: true, Type: TypeUnsigned, MinValue: 1, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.WaitSplitRegionTimeout = uint64(tidbOptPositiveInt32(val, DefWaitSplitRegionTimeout)) + return formatVal, nil + }, SetSession: func(s *SessionVars, val string) error { + s.AllowFallbackToTiKV = make(map[kv.StoreType]struct{}) + for _, engine := range strings.Split(val, ",") { + switch engine { + case kv.TiFlash.Name(): + s.AllowFallbackToTiKV[kv.TiFlash] = struct{}{} + } + } return nil }}, - {Scope: ScopeSession, Name: TiDBLowResolutionTSO, Value: Off, Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.LowResolutionTSO = TiDBOptOn(val) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableAutoIncrementInGenerated, Value: BoolToOnOff(DefTiDBEnableAutoIncrementInGenerated), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.EnableAutoIncrementInGenerated = TiDBOptOn(val) return nil }}, - {Scope: ScopeSession, Name: TiDBExpensiveQueryTimeThreshold, Value: strconv.Itoa(DefTiDBExpensiveQueryTimeThreshold), Type: TypeUnsigned, MinValue: int64(MinExpensiveQueryTimeThreshold), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - atomic.StoreUint64(&ExpensiveQueryTimeThreshold, uint64(tidbOptPositiveInt32(val, DefTiDBExpensiveQueryTimeThreshold))) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBPlacementMode, Value: DefTiDBPlacementMode, Type: TypeEnum, PossibleValues: []string{PlacementModeStrict, PlacementModeIgnore}, SetSession: func(s *SessionVars, val string) error { + s.PlacementMode = val return nil - }, GetSession: func(s *SessionVars) (string, error) { - return fmt.Sprintf("%d", atomic.LoadUint64(&ExpensiveQueryTimeThreshold)), nil }}, - {Scope: ScopeSession, Name: TiDBMemoryUsageAlarmRatio, Value: strconv.FormatFloat(config.GetGlobalConfig().Performance.MemoryUsageAlarmRatio, 'f', -1, 64), Type: TypeFloat, MinValue: 0.0, MaxValue: 1.0, skipInit: true, SetSession: func(s *SessionVars, val string) error { - MemoryUsageAlarmRatio.Store(tidbOptFloat64(val, 0.8)) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBOptJoinReorderThreshold, Value: strconv.Itoa(DefTiDBOptJoinReorderThreshold), skipInit: true, Type: TypeUnsigned, MinValue: 0, MaxValue: 63, SetSession: func(s *SessionVars, val string) error { + s.TiDBOptJoinReorderThreshold = tidbOptPositiveInt32(val, DefTiDBOptJoinReorderThreshold) return nil - }, GetSession: func(s *SessionVars) (string, error) { - return fmt.Sprintf("%g", MemoryUsageAlarmRatio.Load()), nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableNoopFuncs, Value: DefTiDBEnableNoopFuncs, Type: TypeEnum, PossibleValues: []string{Off, On, Warn}, Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { @@ -933,49 +1219,6 @@ var defaultSysVars = []*SysVar{ } return nil }}, - {Scope: ScopeSession, Name: TiDBAllowRemoveAutoInc, Value: BoolToOnOff(DefTiDBAllowRemoveAutoInc), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - s.AllowRemoveAutoInc = TiDBOptOn(val) - return nil - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableStmtSummary, Value: BoolToOnOff(config.GetGlobalConfig().StmtSummary.Enable), skipInit: true, Type: TypeBool, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetEnabled(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetEnabled(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStmtSummaryInternalQuery, Value: BoolToOnOff(config.GetGlobalConfig().StmtSummary.EnableInternalQuery), skipInit: true, Type: TypeBool, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetEnabledInternalQuery(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStmtSummaryRefreshInterval, Value: strconv.Itoa(config.GetGlobalConfig().StmtSummary.RefreshInterval), skipInit: true, Type: TypeInt, MinValue: 1, MaxValue: math.MaxInt32, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetRefreshInterval(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStmtSummaryHistorySize, Value: strconv.Itoa(config.GetGlobalConfig().StmtSummary.HistorySize), skipInit: true, Type: TypeInt, MinValue: 0, MaxValue: math.MaxUint8, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetHistorySize(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetHistorySize(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStmtSummaryMaxStmtCount, Value: strconv.FormatUint(uint64(config.GetGlobalConfig().StmtSummary.MaxStmtCount), 10), skipInit: true, Type: TypeInt, MinValue: 1, MaxValue: math.MaxInt16, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetMaxStmtCount(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBStmtSummaryMaxSQLLength, Value: strconv.FormatUint(uint64(config.GetGlobalConfig().StmtSummary.MaxSQLLength), 10), skipInit: true, Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt32, AllowEmpty: true, SetSession: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(val, true) - }, SetGlobal: func(s *SessionVars, val string) error { - return stmtsummary.StmtSummaryByDigestMap.SetMaxSQLLength(val, false) - }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBCapturePlanBaseline, Value: Off, Type: TypeBool, AllowEmptyAll: true, skipInit: true, GetSession: func(s *SessionVars) (string, error) { - return CapturePlanBaseline.GetVal(), nil - }, SetSession: func(s *SessionVars, val string) error { - CapturePlanBaseline.Set(val, true) - return nil - }, SetGlobal: func(s *SessionVars, val string) error { - CapturePlanBaseline.Set(val, false) - return nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBUsePlanBaselines, Value: BoolToOnOff(DefTiDBUsePlanBaselines), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.UsePlanBaselines = TiDBOptOn(val) return nil @@ -993,115 +1236,9 @@ var defaultSysVars = []*SysVar{ s.EnableExtendedStats = TiDBOptOn(val) return nil }}, - {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskMaxTime, Value: strconv.Itoa(DefTiDBEvolvePlanTaskMaxTime), Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64}, - {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskStartTime, Value: DefTiDBEvolvePlanTaskStartTime, Type: TypeTime}, - {Scope: ScopeGlobal, Name: TiDBEvolvePlanTaskEndTime, Value: DefTiDBEvolvePlanTaskEndTime, Type: TypeTime}, - {Scope: ScopeSession, Name: TiDBIsolationReadEngines, Value: strings.Join(config.GetGlobalConfig().IsolationRead.Engines, ","), Validation: func(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) { - engines := strings.Split(normalizedValue, ",") - var formatVal string - for i, engine := range engines { - engine = strings.TrimSpace(engine) - if i != 0 { - formatVal += "," - } - switch { - case strings.EqualFold(engine, kv.TiKV.Name()): - formatVal += kv.TiKV.Name() - case strings.EqualFold(engine, kv.TiFlash.Name()): - formatVal += kv.TiFlash.Name() - case strings.EqualFold(engine, kv.TiDB.Name()): - formatVal += kv.TiDB.Name() - default: - return normalizedValue, ErrWrongValueForVar.GenWithStackByArgs(TiDBIsolationReadEngines, normalizedValue) - } - } - return formatVal, nil - }, SetSession: func(s *SessionVars, val string) error { - s.IsolationReadEngines = make(map[kv.StoreType]struct{}) - for _, engine := range strings.Split(val, ",") { - switch engine { - case kv.TiKV.Name(): - s.IsolationReadEngines[kv.TiKV] = struct{}{} - case kv.TiFlash.Name(): - s.IsolationReadEngines[kv.TiFlash] = struct{}{} - case kv.TiDB.Name(): - s.IsolationReadEngines[kv.TiDB] = struct{}{} - } - } - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBStoreLimit, Value: strconv.FormatInt(atomic.LoadInt64(&config.GetGlobalConfig().TiKVClient.StoreLimit), 10), Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt64, GetGlobal: func(s *SessionVars) (string, error) { - return strconv.FormatInt(tikvstore.StoreLimit.Load(), 10), nil - }, SetGlobal: func(s *SessionVars, val string) error { - tikvstore.StoreLimit.Store(tidbOptInt64(val, DefTiDBStoreLimit)) - return nil - }}, - {Scope: ScopeSession, Name: TiDBMetricSchemaStep, Value: strconv.Itoa(DefTiDBMetricSchemaStep), Type: TypeUnsigned, skipInit: true, MinValue: 10, MaxValue: 60 * 60 * 60, SetSession: func(s *SessionVars, val string) error { - s.MetricSchemaStep = tidbOptInt64(val, DefTiDBMetricSchemaStep) - return nil - }}, - {Scope: ScopeSession, Name: TiDBMetricSchemaRangeDuration, Value: strconv.Itoa(DefTiDBMetricSchemaRangeDuration), skipInit: true, Type: TypeUnsigned, MinValue: 10, MaxValue: 60 * 60 * 60, SetSession: func(s *SessionVars, val string) error { - s.MetricSchemaRangeDuration = tidbOptInt64(val, DefTiDBMetricSchemaRangeDuration) - return nil - }}, - {Scope: ScopeSession, Name: TiDBSlowLogThreshold, Value: strconv.Itoa(logutil.DefaultSlowThreshold), skipInit: true, Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error { - atomic.StoreUint64(&config.GetGlobalConfig().Log.SlowThreshold, uint64(tidbOptInt64(val, logutil.DefaultSlowThreshold))) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.SlowThreshold), 10), nil - }}, - {Scope: ScopeSession, Name: TiDBRecordPlanInSlowLog, Value: int32ToBoolStr(logutil.DefaultRecordPlanInSlowLog), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - atomic.StoreUint32(&config.GetGlobalConfig().Log.RecordPlanInSlowLog, uint32(tidbOptInt64(val, logutil.DefaultRecordPlanInSlowLog))) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - enabled := atomic.LoadUint32(&config.GetGlobalConfig().Log.RecordPlanInSlowLog) == 1 - return BoolToOnOff(enabled), nil - }}, - {Scope: ScopeSession, Name: TiDBEnableSlowLog, Value: BoolToOnOff(logutil.DefaultTiDBEnableSlowLog), Type: TypeBool, skipInit: true, SetSession: func(s *SessionVars, val string) error { - config.GetGlobalConfig().Log.EnableSlowLog.Store(TiDBOptOn(val)) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(config.GetGlobalConfig().Log.EnableSlowLog.Load()), nil - }}, - {Scope: ScopeSession, Name: TiDBQueryLogMaxLen, Value: strconv.Itoa(logutil.DefaultQueryLogMaxLen), Type: TypeInt, MinValue: -1, MaxValue: math.MaxInt64, skipInit: true, SetSession: func(s *SessionVars, val string) error { - atomic.StoreUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen, uint64(tidbOptInt64(val, logutil.DefaultQueryLogMaxLen))) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return strconv.FormatUint(atomic.LoadUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen), 10), nil - }}, {Scope: ScopeGlobal | ScopeSession, Name: CTEMaxRecursionDepth, Value: strconv.Itoa(DefCTEMaxRecursionDepth), Type: TypeInt, MinValue: 0, MaxValue: 4294967295, SetSession: func(s *SessionVars, val string) error { - s.CTEMaxRecursionDepth = tidbOptInt(val, DefCTEMaxRecursionDepth) - return nil - }}, - {Scope: ScopeSession, Name: TiDBCheckMb4ValueInUTF8, Value: BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - config.GetGlobalConfig().CheckMb4ValueInUTF8 = TiDBOptOn(val) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8), nil - }}, - {Scope: ScopeSession, Name: TiDBFoundInPlanCache, Value: BoolToOnOff(DefTiDBFoundInPlanCache), Type: TypeBool, ReadOnly: true, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.FoundInPlanCache = TiDBOptOn(val) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(s.PrevFoundInPlanCache), nil - }}, - {Scope: ScopeSession, Name: TiDBFoundInBinding, Value: BoolToOnOff(DefTiDBFoundInBinding), Type: TypeBool, ReadOnly: true, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.FoundInBinding = TiDBOptOn(val) - return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(s.PrevFoundInBinding), nil - }}, - {Scope: ScopeSession, Name: TiDBEnableCollectExecutionInfo, Value: BoolToOnOff(DefTiDBEnableCollectExecutionInfo), skipInit: true, Type: TypeBool, SetSession: func(s *SessionVars, val string) error { - oldConfig := config.GetGlobalConfig() - newValue := TiDBOptOn(val) - if oldConfig.EnableCollectExecutionInfo != newValue { - newConfig := *oldConfig - newConfig.EnableCollectExecutionInfo = newValue - config.StoreGlobalConfig(&newConfig) - } + s.CTEMaxRecursionDepth = TidbOptInt(val, DefCTEMaxRecursionDepth) return nil - }, GetSession: func(s *SessionVars) (string, error) { - return BoolToOnOff(config.GetGlobalConfig().EnableCollectExecutionInfo), nil }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBAllowAutoRandExplicitInsert, Value: BoolToOnOff(DefTiDBAllowAutoRandExplicitInsert), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.AllowAutoRandExplicitInsert = TiDBOptOn(val) @@ -1131,12 +1268,10 @@ var defaultSysVars = []*SysVar{ errors.RedactLogEnabled.Store(s.EnableRedactLog) return nil }}, - {Scope: ScopeGlobal, Name: TiDBRestrictedReadOnly, Value: BoolToOnOff(DefTiDBRestrictedReadOnly), Type: TypeBool}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBShardAllocateStep, Value: strconv.Itoa(DefTiDBShardAllocateStep), Type: TypeInt, MinValue: 1, MaxValue: uint64(math.MaxInt64), SetSession: func(s *SessionVars, val string) error { - s.ShardAllocateStep = tidbOptInt64(val, DefTiDBShardAllocateStep) + s.ShardAllocateStep = TidbOptInt64(val, DefTiDBShardAllocateStep) return nil }}, - {Scope: ScopeGlobal, Name: TiDBEnableTelemetry, Value: BoolToOnOff(DefTiDBEnableTelemetry), Type: TypeBool}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableAmendPessimisticTxn, Value: BoolToOnOff(DefTiDBEnableAmendPessimisticTxn), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.EnableAmendPessimisticTxn = TiDBOptOn(val) return nil @@ -1189,110 +1324,11 @@ var defaultSysVars = []*SysVar{ s.TiDBEnableExchangePartition = TiDBOptOn(val) return nil }}, - {Scope: ScopeNone, Name: TiDBEnableEnhancedSecurity, Value: Off, Type: TypeBool}, - {Scope: ScopeSession, Name: PluginLoad, Value: "", GetSession: func(s *SessionVars) (string, error) { - return config.GetGlobalConfig().Plugin.Load, nil - }}, - {Scope: ScopeSession, Name: PluginDir, Value: "/data/deploy/plugin", GetSession: func(s *SessionVars) (string, error) { - return config.GetGlobalConfig().Plugin.Dir, nil - }}, - {Scope: ScopeGlobal, Name: TiDBEnableHistoricalStats, Value: Off, Type: TypeBool, GetGlobal: func(s *SessionVars) (string, error) { - return getTiDBTableValue(s, "tidb_enable_historical_stats", Off) - }, SetGlobal: func(s *SessionVars, val string) error { - return setTiDBTableValue(s, "tidb_enable_historical_stats", val, "Current historical statistics enable status") - }}, - /* tikv gc metrics */ - {Scope: ScopeGlobal, Name: TiDBGCEnable, Value: On, Type: TypeBool, GetGlobal: func(s *SessionVars) (string, error) { - return getTiDBTableValue(s, "tikv_gc_enable", On) - }, SetGlobal: func(s *SessionVars, val string) error { - return setTiDBTableValue(s, "tikv_gc_enable", val, "Current GC enable status") - }}, - {Scope: ScopeGlobal, Name: TiDBGCRunInterval, Value: "10m0s", Type: TypeDuration, MinValue: int64(time.Minute * 10), MaxValue: uint64(time.Hour * 24 * 365), GetGlobal: func(s *SessionVars) (string, error) { - return getTiDBTableValue(s, "tikv_gc_run_interval", "10m0s") - }, SetGlobal: func(s *SessionVars, val string) error { - return setTiDBTableValue(s, "tikv_gc_run_interval", val, "GC run interval, at least 10m, in Go format.") - }}, - {Scope: ScopeGlobal, Name: TiDBGCLifetime, Value: "10m0s", Type: TypeDuration, MinValue: int64(time.Minute * 10), MaxValue: uint64(time.Hour * 24 * 365), GetGlobal: func(s *SessionVars) (string, error) { - return getTiDBTableValue(s, "tikv_gc_life_time", "10m0s") - }, SetGlobal: func(s *SessionVars, val string) error { - return setTiDBTableValue(s, "tikv_gc_life_time", val, "All versions within life time will not be collected by GC, at least 10m, in Go format.") - }}, - {Scope: ScopeGlobal, Name: TiDBGCConcurrency, Value: "-1", Type: TypeInt, MinValue: 1, MaxValue: MaxConfigurableConcurrency, AllowAutoValue: true, GetGlobal: func(s *SessionVars) (string, error) { - autoConcurrencyVal, err := getTiDBTableValue(s, "tikv_gc_auto_concurrency", On) - if err == nil && autoConcurrencyVal == On { - return "-1", nil // convention for "AUTO" - } - return getTiDBTableValue(s, "tikv_gc_concurrency", "-1") - }, SetGlobal: func(s *SessionVars, val string) error { - autoConcurrency := Off - if val == "-1" { - autoConcurrency = On - } - // Update both autoconcurrency and concurrency. - if err := setTiDBTableValue(s, "tikv_gc_auto_concurrency", autoConcurrency, "Let TiDB pick the concurrency automatically. If set false, tikv_gc_concurrency will be used"); err != nil { - return err - } - return setTiDBTableValue(s, "tikv_gc_concurrency", val, "How many goroutines used to do GC parallel, [1, 256], default 2") - }}, - {Scope: ScopeGlobal, Name: TiDBGCScanLockMode, Value: "LEGACY", Type: TypeEnum, PossibleValues: []string{"PHYSICAL", "LEGACY"}, GetGlobal: func(s *SessionVars) (string, error) { - return getTiDBTableValue(s, "tikv_gc_scan_lock_mode", "LEGACY") - }, SetGlobal: func(s *SessionVars, val string) error { - return setTiDBTableValue(s, "tikv_gc_scan_lock_mode", val, "Mode of scanning locks, \"physical\" or \"legacy\"") - }}, // It's different from tmp_table_size or max_heap_table_size. See https://github.com/pingcap/tidb/issues/28691. {Scope: ScopeGlobal | ScopeSession, Name: TiDBTmpTableMaxSize, Value: strconv.Itoa(DefTiDBTmpTableMaxSize), Type: TypeUnsigned, MinValue: 1 << 20, MaxValue: 1 << 37, SetSession: func(s *SessionVars, val string) error { - s.TMPTableSize = tidbOptInt64(val, DefTiDBTmpTableMaxSize) - return nil - }}, - // variable for top SQL feature. - {Scope: ScopeGlobal, Name: TiDBEnableTopSQL, Value: BoolToOnOff(DefTiDBTopSQLEnable), Type: TypeBool, Hidden: true, AllowEmpty: true, GetGlobal: func(s *SessionVars) (string, error) { - return BoolToOnOff(TopSQLVariable.Enable.Load()), nil - }, SetGlobal: func(vars *SessionVars, s string) error { - TopSQLVariable.Enable.Store(TiDBOptOn(s)) - return nil - }, GlobalConfigName: GlobalConfigEnableTopSQL}, - {Scope: ScopeGlobal, Name: TiDBTopSQLPrecisionSeconds, Value: strconv.Itoa(DefTiDBTopSQLPrecisionSeconds), Type: TypeInt, Hidden: true, MinValue: 1, MaxValue: math.MaxInt64, GetGlobal: func(s *SessionVars) (string, error) { - return strconv.FormatInt(TopSQLVariable.PrecisionSeconds.Load(), 10), nil - }, SetGlobal: func(vars *SessionVars, s string) error { - val, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return err - } - TopSQLVariable.PrecisionSeconds.Store(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBTopSQLMaxStatementCount, Value: strconv.Itoa(DefTiDBTopSQLMaxStatementCount), Type: TypeInt, Hidden: true, MinValue: 0, MaxValue: 5000, GetGlobal: func(s *SessionVars) (string, error) { - return strconv.FormatInt(TopSQLVariable.MaxStatementCount.Load(), 10), nil - }, SetGlobal: func(vars *SessionVars, s string) error { - val, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return err - } - TopSQLVariable.MaxStatementCount.Store(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBTopSQLMaxCollect, Value: strconv.Itoa(DefTiDBTopSQLMaxCollect), Type: TypeInt, Hidden: true, MinValue: 1, MaxValue: 10000, GetGlobal: func(s *SessionVars) (string, error) { - return strconv.FormatInt(TopSQLVariable.MaxCollect.Load(), 10), nil - }, SetGlobal: func(vars *SessionVars, s string) error { - val, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return err - } - TopSQLVariable.MaxCollect.Store(val) - return nil - }}, - {Scope: ScopeGlobal, Name: TiDBTopSQLReportIntervalSeconds, Value: strconv.Itoa(DefTiDBTopSQLReportIntervalSeconds), Type: TypeInt, Hidden: true, MinValue: 1, MaxValue: 1 * 60 * 60, GetGlobal: func(s *SessionVars) (string, error) { - return strconv.FormatInt(TopSQLVariable.ReportIntervalSeconds.Load(), 10), nil - }, SetGlobal: func(vars *SessionVars, s string) error { - val, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return err - } - TopSQLVariable.ReportIntervalSeconds.Store(val) + s.TMPTableSize = TidbOptInt64(val, DefTiDBTmpTableMaxSize) return nil }}, - {Scope: ScopeGlobal, Name: SkipNameResolve, Value: Off, Type: TypeBool}, - {Scope: ScopeGlobal, Name: DefaultAuthPlugin, Value: mysql.AuthNativePassword, Type: TypeEnum, PossibleValues: []string{mysql.AuthNativePassword, mysql.AuthCachingSha2Password}}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableOrderedResultMode, Value: BoolToOnOff(DefTiDBEnableOrderedResultMode), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { s.EnableStableResultMode = TiDBOptOn(val) return nil @@ -1305,24 +1341,64 @@ var defaultSysVars = []*SysVar{ s.RegardNULLAsPoint = TiDBOptOn(val) return nil }}, - - {Scope: ScopeNone, Name: "version_compile_os", Value: runtime.GOOS}, - {Scope: ScopeNone, Name: "version_compile_machine", Value: runtime.GOARCH}, - {Scope: ScopeNone, Name: TiDBAllowFunctionForExpressionIndex, ReadOnly: true, Value: collectAllowFuncName4ExpressionIndex()}, - {Scope: ScopeSession, Name: RandSeed1, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.Rng.SetSeed1(uint32(tidbOptPositiveInt32(val, 0))) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnablePaging, Value: Off, Type: TypeBool, Hidden: true, SetSession: func(s *SessionVars, val string) error { + s.EnablePaging = TiDBOptOn(val) return nil - }, GetSession: func(s *SessionVars) (string, error) { - return "0", nil }}, - {Scope: ScopeSession, Name: RandSeed2, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.Rng.SetSeed2(uint32(tidbOptPositiveInt32(val, 0))) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableLegacyInstanceScope, Value: BoolToOnOff(DefEnableLegacyInstanceScope), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.EnableLegacyInstanceScope = TiDBOptOn(val) return nil - }, GetSession: func(s *SessionVars) (string, error) { - return "0", nil }}, - {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnablePaging, Value: Off, Type: TypeBool, Hidden: true, skipInit: true, SetSession: func(s *SessionVars, val string) error { - s.EnablePaging = TiDBOptOn(val) + {Scope: ScopeGlobal | ScopeSession, Name: TiDBStatsLoadSyncWait, Value: strconv.Itoa(DefTiDBStatsLoadSyncWait), skipInit: true, Type: TypeInt, MinValue: 0, MaxValue: math.MaxInt32, + SetSession: func(s *SessionVars, val string) error { + s.StatsLoadSyncWait = TidbOptInt64(val, DefTiDBStatsLoadSyncWait) + return nil + }, + GetGlobal: func(s *SessionVars) (string, error) { + return strconv.FormatInt(StatsLoadSyncWait.Load(), 10), nil + }, + SetGlobal: func(s *SessionVars, val string) error { + StatsLoadSyncWait.Store(TidbOptInt64(val, DefTiDBStatsLoadSyncWait)) + return nil + }, + }, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBSysdateIsNow, Value: BoolToOnOff(DefSysdateIsNow), Type: TypeBool, + SetSession: func(vars *SessionVars, s string) error { + vars.SysdateIsNow = TiDBOptOn(s) + return nil + }, + }, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBEnableMutationChecker, Hidden: true, + Value: BoolToOnOff(DefTiDBEnableMutationChecker), Type: TypeBool, + SetSession: func(s *SessionVars, val string) error { + s.EnableMutationChecker = TiDBOptOn(val) + return nil + }, + }, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBTxnAssertionLevel, Value: DefTiDBTxnAssertionLevel, PossibleValues: []string{AssertionOffStr, AssertionFastStr, AssertionStrictStr}, Hidden: true, Type: TypeEnum, SetSession: func(s *SessionVars, val string) error { + s.AssertionLevel = tidbOptAssertionLevel(val) + return nil + }}, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBBatchPendingTiFlashCount, Value: strconv.Itoa(DefTiDBBatchPendingTiFlashCount), MinValue: 0, MaxValue: math.MaxUint32, Hidden: false, Type: TypeUnsigned, SetSession: func(s *SessionVars, val string) error { + b, e := strconv.Atoi(val) + if e != nil { + b = DefTiDBBatchPendingTiFlashCount + } + s.BatchPendingTiFlashCount = b + return nil + }}, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBIgnorePreparedCacheCloseStmt, Value: BoolToOnOff(DefTiDBIgnorePreparedCacheCloseStmt), Type: TypeBool, + SetSession: func(vars *SessionVars, s string) error { + vars.IgnorePreparedCacheCloseStmt = TiDBOptOn(s) + return nil + }, + }, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBRCReadCheckTS, Type: TypeBool, Value: BoolToOnOff(DefRCReadCheckTS), SetSession: func(s *SessionVars, val string) error { + s.RcReadCheckTS = TiDBOptOn(val) + return nil + }}, + {Scope: ScopeGlobal | ScopeSession, Name: TiDBRemoveOrderbyInSubquery, Value: BoolToOnOff(DefTiDBRemoveOrderbyInSubquery), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.RemoveOrderbyInSubquery = TiDBOptOn(val) return nil }}, } @@ -1419,8 +1495,6 @@ const ( SkipNameResolve = "skip_name_resolve" // ForeignKeyChecks is the name for 'foreign_key_checks' system variable. ForeignKeyChecks = "foreign_key_checks" - // PlacementChecks is the name for 'placement_checks' system variable. - PlacementChecks = "placement_checks" // SQLSafeUpdates is the name for 'sql_safe_updates' system variable. SQLSafeUpdates = "sql_safe_updates" // WarningCount is the name for 'warning_count' system variable. @@ -1544,7 +1618,7 @@ const ( // InnodbAdaptiveHashIndex is the name for 'innodb_adaptive_hash_index' system variable. InnodbAdaptiveHashIndex = "innodb_adaptive_hash_index" // InnodbFtEnableStopword is the name for 'innodb_ft_enable_stopword' system variable. - InnodbFtEnableStopword = "innodb_ft_enable_stopword" + InnodbFtEnableStopword = "innodb_ft_enable_stopword" // #nosec G101 // InnodbSupportXA is the name for 'innodb_support_xa' system variable. InnodbSupportXA = "innodb_support_xa" // InnodbOptimizeFullTextOnly is the name for 'innodb_optimize_fulltext_only' system variable. diff --git a/sessionctx/variable/sysvar_test.go b/sessionctx/variable/sysvar_test.go index e15c9f92b92b8..0d694d8b9af88 100644 --- a/sessionctx/variable/sysvar_test.go +++ b/sessionctx/variable/sysvar_test.go @@ -60,20 +60,6 @@ func TestSysVar(t *testing.T) { require.Equal(t, runtime.GOARCH, f.Value) } -func TestTxnMode(t *testing.T) { - seVar := NewSessionVars() - require.NotNil(t, seVar) - require.Equal(t, "", seVar.TxnMode) - err := seVar.setTxnMode("pessimistic") - require.NoError(t, err) - err = seVar.setTxnMode("optimistic") - require.NoError(t, err) - err = seVar.setTxnMode("") - require.NoError(t, err) - err = seVar.setTxnMode("something else") - require.Error(t, err) -} - func TestError(t *testing.T) { kvErrs := []*terror.Error{ ErrUnsupportedValueForVar, @@ -99,7 +85,7 @@ func TestRegistrationOfNewSysVar(t *testing.T) { }} RegisterSysVar(&sv) - require.Equal(t, len(GetSysVars()), count+1) + require.Len(t, GetSysVars(), count+1) sysVar := GetSysVar("mynewsysvar") require.NotNil(t, sysVar) @@ -260,22 +246,32 @@ func TestScope(t *testing.T) { sv := SysVar{Scope: ScopeGlobal | ScopeSession, Name: "mynewsysvar", Value: On, Type: TypeEnum, PossibleValues: []string{"OFF", "ON", "AUTO"}} require.True(t, sv.HasSessionScope()) require.True(t, sv.HasGlobalScope()) + require.False(t, sv.HasInstanceScope()) require.False(t, sv.HasNoneScope()) sv = SysVar{Scope: ScopeGlobal, Name: "mynewsysvar", Value: On, Type: TypeEnum, PossibleValues: []string{"OFF", "ON", "AUTO"}} require.False(t, sv.HasSessionScope()) require.True(t, sv.HasGlobalScope()) + require.False(t, sv.HasInstanceScope()) require.False(t, sv.HasNoneScope()) sv = SysVar{Scope: ScopeSession, Name: "mynewsysvar", Value: On, Type: TypeEnum, PossibleValues: []string{"OFF", "ON", "AUTO"}} require.True(t, sv.HasSessionScope()) require.False(t, sv.HasGlobalScope()) + require.False(t, sv.HasInstanceScope()) require.False(t, sv.HasNoneScope()) sv = SysVar{Scope: ScopeNone, Name: "mynewsysvar", Value: On, Type: TypeEnum, PossibleValues: []string{"OFF", "ON", "AUTO"}} require.False(t, sv.HasSessionScope()) require.False(t, sv.HasGlobalScope()) + require.False(t, sv.HasInstanceScope()) require.True(t, sv.HasNoneScope()) + + sv = SysVar{Scope: ScopeInstance, Name: "mynewsysvar", Value: On, Type: TypeEnum, PossibleValues: []string{"OFF", "ON", "AUTO"}} + require.False(t, sv.HasSessionScope()) + require.False(t, sv.HasGlobalScope()) + require.True(t, sv.HasInstanceScope()) + require.False(t, sv.HasNoneScope()) } func TestBuiltInCase(t *testing.T) { @@ -540,6 +536,43 @@ func TestIsNoop(t *testing.T) { require.True(t, sv.IsNoop) } +func TestTiDBReadOnly(t *testing.T) { + rro := GetSysVar(TiDBRestrictedReadOnly) + sro := GetSysVar(TiDBSuperReadOnly) + + vars := NewSessionVars() + mock := NewMockGlobalAccessor4Tests() + mock.SessionVars = vars + vars.GlobalVarsAccessor = mock + + // turn on tidb_restricted_read_only should turn on tidb_super_read_only + require.NoError(t, mock.SetGlobalSysVar(rro.Name, "ON")) + result, err := mock.GetGlobalSysVar(sro.Name) + require.NoError(t, err) + require.Equal(t, "ON", result) + + // can't turn off tidb_super_read_only if tidb_restricted_read_only is on + err = mock.SetGlobalSysVar(sro.Name, "OFF") + require.Error(t, err) + require.Equal(t, "can't turn off tidb_super_read_only when tidb_restricted_read_only is on", err.Error()) + + // turn off tidb_restricted_read_only won't affect tidb_super_read_only + require.NoError(t, mock.SetGlobalSysVar(rro.Name, "OFF")) + result, err = mock.GetGlobalSysVar(rro.Name) + require.NoError(t, err) + require.Equal(t, "OFF", result) + + result, err = mock.GetGlobalSysVar(sro.Name) + require.NoError(t, err) + require.Equal(t, "ON", result) + + // it is ok to turn off tidb_super_read_only now + require.NoError(t, mock.SetGlobalSysVar(sro.Name, "OFF")) + result, err = mock.GetGlobalSysVar(sro.Name) + require.NoError(t, err) + require.Equal(t, "OFF", result) +} + func TestInstanceScopedVars(t *testing.T) { // This tests instance scoped variables through GetSessionOrGlobalSystemVar(). // Eventually these should be changed to use getters so that the switch @@ -616,11 +649,7 @@ func TestInstanceScopedVars(t *testing.T) { val, err = GetSessionOrGlobalSystemVar(vars, TiDBCheckMb4ValueInUTF8) require.NoError(t, err) - require.Equal(t, BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8), val) - - val, err = GetSessionOrGlobalSystemVar(vars, TiDBCapturePlanBaseline) - require.NoError(t, err) - require.Equal(t, CapturePlanBaseline.GetVal(), val) + require.Equal(t, BoolToOnOff(config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()), val) val, err = GetSessionOrGlobalSystemVar(vars, TiDBFoundInPlanCache) require.NoError(t, err) @@ -668,7 +697,7 @@ func TestSettersandGetters(t *testing.T) { // There are some historial exceptions where global variables are loaded into the session. // Please don't add to this list, the behavior is not MySQL compatible. switch sv.Name { - case TiDBEnableChangeMultiSchema, TiDBDDLReorgBatchSize, TiDBEnableAlterPlacement, + case TiDBEnableChangeMultiSchema, TiDBDDLReorgBatchSize, TiDBMaxDeltaSchemaCount, InitConnect, MaxPreparedStmtCount, TiDBDDLReorgWorkerCount, TiDBDDLErrorCountLimit, TiDBRowFormatVersion, TiDBEnableTelemetry, TiDBEnablePointGetCache: @@ -677,7 +706,7 @@ func TestSettersandGetters(t *testing.T) { require.Nil(t, sv.SetSession) require.Nil(t, sv.GetSession) } - if !sv.HasGlobalScope() { + if !sv.HasGlobalScope() && !sv.HasInstanceScope() { require.Nil(t, sv.SetGlobal) if sv.Name == Timestamp { // The Timestamp sysvar will have GetGlobal func even though it does not have global scope. @@ -825,3 +854,96 @@ func TestDefaultCharsetAndCollation(t *testing.T) { require.NoError(t, err) require.Equal(t, val, mysql.DefaultCollationName) } + +func TestInstanceScope(t *testing.T) { + // Instance scope used to be settable via "SET SESSION", which is weird to any MySQL user. + // It is now settable via SET GLOBAL, but to work correctly a sysvar can only ever + // be INSTANCE scoped or GLOBAL scoped, never *both* at the same time (at least for now). + // Otherwise the semantics are confusing to users for how precedence applies. + + for _, sv := range GetSysVars() { + require.False(t, sv.HasGlobalScope() && sv.HasInstanceScope(), "sysvar %s has both instance and global scope", sv.Name) + if sv.HasInstanceScope() { + require.NotNil(t, sv.GetGlobal) + require.NotNil(t, sv.SetGlobal) + } + } + + count := len(GetSysVars()) + sv := SysVar{Scope: ScopeInstance, Name: "newinstancesysvar", Value: On, Type: TypeBool, + SetGlobal: func(s *SessionVars, val string) error { + return fmt.Errorf("set should fail") + }, + GetGlobal: func(s *SessionVars) (string, error) { + return "", fmt.Errorf("get should fail") + }, + } + + RegisterSysVar(&sv) + require.Len(t, GetSysVars(), count+1) + + sysVar := GetSysVar("newinstancesysvar") + require.NotNil(t, sysVar) + + vars := NewSessionVars() + + // It is a boolean, try to set it to a bogus value + _, err := sysVar.Validate(vars, "ABCD", ScopeInstance) + require.Error(t, err) + + // Boolean oN or 1 converts to canonical ON or OFF + normalizedVal, err := sysVar.Validate(vars, "oN", ScopeInstance) + require.Equal(t, "ON", normalizedVal) + require.NoError(t, err) + normalizedVal, err = sysVar.Validate(vars, "0", ScopeInstance) + require.Equal(t, "OFF", normalizedVal) + require.NoError(t, err) + + err = sysVar.SetGlobalFromHook(vars, "OFF", true) // default is on + require.Equal(t, "set should fail", err.Error()) + + // Test unregistration restores previous count + UnregisterSysVar("newinstancesysvar") + require.Equal(t, len(GetSysVars()), count) +} + +func TestIndexMergeSwitcher(t *testing.T) { + vars := NewSessionVars() + vars.GlobalVarsAccessor = NewMockGlobalAccessor4Tests() + val, err := GetSessionOrGlobalSystemVar(vars, TiDBEnableIndexMerge) + require.NoError(t, err) + require.Equal(t, DefTiDBEnableIndexMerge, true) + require.Equal(t, BoolToOnOff(DefTiDBEnableIndexMerge), val) +} + +func TestNetBufferLength(t *testing.T) { + netBufferLength := GetSysVar(NetBufferLength) + vars := NewSessionVars() + vars.GlobalVarsAccessor = NewMockGlobalAccessor4Tests() + + val, err := netBufferLength.Validate(vars, "1", ScopeGlobal) + require.NoError(t, err) + require.Equal(t, "1024", val) // converts it to min value + val, err = netBufferLength.Validate(vars, "10485760", ScopeGlobal) + require.NoError(t, err) + require.Equal(t, "1048576", val) // converts it to max value + val, err = netBufferLength.Validate(vars, "524288", ScopeGlobal) + require.NoError(t, err) + require.Equal(t, "524288", val) // unchanged +} + +func TestTiDBBatchPendingTiFlashCount(t *testing.T) { + sv := GetSysVar(TiDBBatchPendingTiFlashCount) + vars := NewSessionVars() + val, err := sv.Validate(vars, "-10", ScopeSession) + require.NoError(t, err) // it has autoconvert out of range. + require.Equal(t, "0", val) + + val, err = sv.Validate(vars, "9999", ScopeSession) + require.NoError(t, err) + require.Equal(t, "9999", val) + + _, err = sv.Validate(vars, "1.5", ScopeSession) + require.Error(t, err) + require.EqualError(t, err, "[variable:1232]Incorrect argument type to variable 'tidb_batch_pending_tiflash_count'") +} diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index ee01348a76441..af92acbeab6c2 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -34,43 +34,40 @@ import ( const ( TiDBDDLSlowOprThreshold = "ddl_slow_threshold" - // tidb_snapshot is used for reading history data, the default value is empty string. + // TiDBSnapshot is used for reading history data, the default value is empty string. // The value can be a datetime string like '2017-11-11 20:20:20' or a tso string. When this variable is set, the session reads history data of that time. TiDBSnapshot = "tidb_snapshot" - // tidb_opt_agg_push_down is used to enable/disable the optimizer rule of aggregation push down. + // TiDBOptAggPushDown is used to enable/disable the optimizer rule of aggregation push down. TiDBOptAggPushDown = "tidb_opt_agg_push_down" - // TiDBOptBCJ is used to enable/disable broadcast join in MPP mode - TiDBOptBCJ = "tidb_opt_broadcast_join" - // TiDBOptCartesianBCJ is used to disable/enable broadcast cartesian join in MPP mode TiDBOptCartesianBCJ = "tidb_opt_broadcast_cartesian_join" TiDBOptMPPOuterJoinFixedBuildSide = "tidb_opt_mpp_outer_join_fixed_build_side" - // tidb_opt_distinct_agg_push_down is used to decide whether agg with distinct should be pushed to tikv/tiflash. + // TiDBOptDistinctAggPushDown is used to decide whether agg with distinct should be pushed to tikv/tiflash. TiDBOptDistinctAggPushDown = "tidb_opt_distinct_agg_push_down" - // tidb_broadcast_join_threshold_size is used to limit the size of small table for mpp broadcast join. - // It's unit is bytes, if the size of small table is larger than it, we will not use bcj. + // TiDBBCJThresholdSize is used to limit the size of small table for mpp broadcast join. + // Its unit is bytes, if the size of small table is larger than it, we will not use bcj. TiDBBCJThresholdSize = "tidb_broadcast_join_threshold_size" - // tidb_broadcast_join_threshold_count is used to limit the count of small table for mpp broadcast join. + // TiDBBCJThresholdCount is used to limit the count of small table for mpp broadcast join. // If we can't estimate the size of one side of join child, we will check if its row number exceeds this limitation. TiDBBCJThresholdCount = "tidb_broadcast_join_threshold_count" - // tidb_opt_write_row_id is used to enable/disable the operations of insertã€replace and update to _tidb_rowid. + // TiDBOptWriteRowID is used to enable/disable the operations of insertã€replace and update to _tidb_rowid. TiDBOptWriteRowID = "tidb_opt_write_row_id" - // Auto analyze will run if (table modify count)/(table row count) is greater than this value. + // TiDBAutoAnalyzeRatio will run if (table modify count)/(table row count) is greater than this value. TiDBAutoAnalyzeRatio = "tidb_auto_analyze_ratio" - // Auto analyze will run if current time is within start time and end time. + // TiDBAutoAnalyzeStartTime will run if current time is within start time and end time. TiDBAutoAnalyzeStartTime = "tidb_auto_analyze_start_time" TiDBAutoAnalyzeEndTime = "tidb_auto_analyze_end_time" - // tidb_checksum_table_concurrency is used to speed up the ADMIN CHECKSUM TABLE + // TiDBChecksumTableConcurrency is used to speed up the ADMIN CHECKSUM TABLE // statement, when a table has multiple indices, those indices can be // scanned concurrently, with the cost of higher system performance impact. TiDBChecksumTableConcurrency = "tidb_checksum_table_concurrency" @@ -82,82 +79,79 @@ const ( // TiDBLastTxnInfo is used to get the last transaction info within the current session. TiDBLastTxnInfo = "tidb_last_txn_info" - // TiDBLastTxnInfo is used to get the last query info within the current session. + // TiDBLastQueryInfo is used to get the last query info within the current session. TiDBLastQueryInfo = "tidb_last_query_info" - // tidb_config is a read-only variable that shows the config of the current server. + // TiDBLastDDLInfo is used to get the last ddl info within the current session. + TiDBLastDDLInfo = "tidb_last_ddl_info" + + // TiDBConfig is a read-only variable that shows the config of the current server. TiDBConfig = "tidb_config" - // tidb_batch_insert is used to enable/disable auto-split insert data. If set this option on, insert executor will automatically + // TiDBBatchInsert is used to enable/disable auto-split insert data. If set this option on, insert executor will automatically // insert data into multiple batches and use a single txn for each batch. This will be helpful when inserting large data. TiDBBatchInsert = "tidb_batch_insert" - // tidb_batch_delete is used to enable/disable auto-split delete data. If set this option on, delete executor will automatically + // TiDBBatchDelete is used to enable/disable auto-split delete data. If set this option on, delete executor will automatically // split data into multiple batches and use a single txn for each batch. This will be helpful when deleting large data. TiDBBatchDelete = "tidb_batch_delete" - // tidb_batch_commit is used to enable/disable auto-split the transaction. + // TiDBBatchCommit is used to enable/disable auto-split the transaction. // If set this option on, the transaction will be committed when it reaches stmt-count-limit and starts a new transaction. TiDBBatchCommit = "tidb_batch_commit" - // tidb_dml_batch_size is used to split the insert/delete data into small batches. + // TiDBDMLBatchSize is used to split the insert/delete data into small batches. // It only takes effort when tidb_batch_insert/tidb_batch_delete is on. // Its default value is 20000. When the row size is large, 20k rows could be larger than 100MB. // User could change it to a smaller one to avoid breaking the transaction size limitation. TiDBDMLBatchSize = "tidb_dml_batch_size" // The following session variables controls the memory quota during query execution. - // "tidb_mem_quota_query": control the memory quota of a query. + + // TiDBMemQuotaQuery controls the memory quota of a query. TiDBMemQuotaQuery = "tidb_mem_quota_query" // Bytes. TiDBMemQuotaApplyCache = "tidb_mem_quota_apply_cache" - // TODO: remove them below sometime, it should have only one Quota(TiDBMemQuotaQuery). - TiDBMemQuotaHashJoin = "tidb_mem_quota_hashjoin" // Bytes. - TiDBMemQuotaMergeJoin = "tidb_mem_quota_mergejoin" // Bytes. - TiDBMemQuotaSort = "tidb_mem_quota_sort" // Bytes. - TiDBMemQuotaTopn = "tidb_mem_quota_topn" // Bytes. - TiDBMemQuotaIndexLookupReader = "tidb_mem_quota_indexlookupreader" // Bytes. - TiDBMemQuotaIndexLookupJoin = "tidb_mem_quota_indexlookupjoin" // Bytes. - - // tidb_general_log is used to log every query in the server in info level. + + // TiDBGeneralLog is used to log every query in the server in info level. TiDBGeneralLog = "tidb_general_log" - // tidb_general_log is used to log every query in the server in info level. + // TiDBLogFileMaxDays is used to log every query in the server in info level. TiDBLogFileMaxDays = "tidb_log_file_max_days" - // tidb_pprof_sql_cpu is used to add label sql label to pprof result. + // TiDBPProfSQLCPU is used to add label sql label to pprof result. TiDBPProfSQLCPU = "tidb_pprof_sql_cpu" - // tidb_retry_limit is the maximum number of retries when committing a transaction. + // TiDBRetryLimit is the maximum number of retries when committing a transaction. TiDBRetryLimit = "tidb_retry_limit" - // tidb_disable_txn_auto_retry disables transaction auto retry. + // TiDBDisableTxnAutoRetry disables transaction auto retry. TiDBDisableTxnAutoRetry = "tidb_disable_txn_auto_retry" - // Deprecated: tidb_enable_streaming enables TiDB to use streaming API for coprocessor requests. - TiDBEnableStreaming = "tidb_enable_streaming" - - // tidb_enable_chunk_rpc enables TiDB to use Chunk format for coprocessor requests. + // TiDBEnableChunkRPC enables TiDB to use Chunk format for coprocessor requests. TiDBEnableChunkRPC = "tidb_enable_chunk_rpc" - // tidb_optimizer_selectivity_level is used to control the selectivity estimation level. + // TiDBOptimizerSelectivityLevel is used to control the selectivity estimation level. TiDBOptimizerSelectivityLevel = "tidb_optimizer_selectivity_level" - // tidb_txn_mode is used to control the transaction behavior. + // TiDBOptimizerEnableNewOnlyFullGroupByCheck is used to open the newly only_full_group_by check by maintaining functional dependency. + TiDBOptimizerEnableNewOnlyFullGroupByCheck = "tidb_enable_new_only_full_group_by_check" + + // TiDBTxnMode is used to control the transaction behavior. TiDBTxnMode = "tidb_txn_mode" - // tidb_row_format_version is used to control tidb row format version current. + // TiDBRowFormatVersion is used to control tidb row format version current. TiDBRowFormatVersion = "tidb_row_format_version" - // tidb_enable_table_partition is used to control table partition feature. + // TiDBEnableTablePartition is used to control table partition feature. // The valid value include auto/on/off: // on or auto: enable table partition if the partition type is implemented. // off: always disable table partition. TiDBEnableTablePartition = "tidb_enable_table_partition" - // tidb_enable_list_partition is used to control list table partition feature. + // TiDBEnableListTablePartition is used to control list table partition feature. TiDBEnableListTablePartition = "tidb_enable_list_partition" - // tidb_skip_isolation_level_check is used to control whether to return error when set unsupported transaction + // TiDBSkipIsolationLevelCheck is used to control whether to return error when set unsupported transaction // isolation level. TiDBSkipIsolationLevelCheck = "tidb_skip_isolation_level_check" @@ -182,16 +176,16 @@ const ( // TiDBEvolvePlanTaskEndTime is the end time of evolution task. TiDBEvolvePlanTaskEndTime = "tidb_evolve_plan_task_end_time" - // tidb_slow_log_threshold is used to set the slow log threshold in the server. + // TiDBSlowLogThreshold is used to set the slow log threshold in the server. TiDBSlowLogThreshold = "tidb_slow_log_threshold" - // tidb_record_plan_in_slow_log is used to log the plan of the slow query. + // TiDBRecordPlanInSlowLog is used to log the plan of the slow query. TiDBRecordPlanInSlowLog = "tidb_record_plan_in_slow_log" - // tidb_enable_slow_log enables TiDB to log slow queries. + // TiDBEnableSlowLog enables TiDB to log slow queries. TiDBEnableSlowLog = "tidb_enable_slow_log" - // tidb_query_log_max_len is used to set the max length of the query in the log. + // TiDBQueryLogMaxLen is used to set the max length of the query in the log. TiDBQueryLogMaxLen = "tidb_query_log_max_len" // TiDBCheckMb4ValueInUTF8 is used to control whether to enable the check wrong utf8 value. @@ -217,87 +211,93 @@ const ( // TiDBEnablePaging indicates whether paging is enabled in coprocessor requests. TiDBEnablePaging = "tidb_enable_paging" + + // TiDBReadConsistency indicates whether the autocommit read statement goes through TiKV RC. + TiDBReadConsistency = "tidb_read_consistency" + + // TiDBSysdateIsNow is the name of the `tidb_sysdate_is_now` system variable + TiDBSysdateIsNow = "tidb_sysdate_is_now" ) // TiDB system variable names that both in session and global scope. const ( - // tidb_build_stats_concurrency is used to speed up the ANALYZE statement, when a table has multiple indices, + // TiDBBuildStatsConcurrency is used to speed up the ANALYZE statement, when a table has multiple indices, // those indices can be scanned concurrently, with the cost of higher system performance impact. TiDBBuildStatsConcurrency = "tidb_build_stats_concurrency" - // tidb_distsql_scan_concurrency is used to set the concurrency of a distsql scan task. + // TiDBDistSQLScanConcurrency is used to set the concurrency of a distsql scan task. // A distsql scan task can be a table scan or a index scan, which may be distributed to many TiKV nodes. // Higher concurrency may reduce latency, but with the cost of higher memory usage and system performance impact. // If the query has a LIMIT clause, high concurrency makes the system do much more work than needed. TiDBDistSQLScanConcurrency = "tidb_distsql_scan_concurrency" - // tidb_opt_insubquery_to_join_and_agg is used to enable/disable the optimizer rule of rewriting IN subquery. + // TiDBOptInSubqToJoinAndAgg is used to enable/disable the optimizer rule of rewriting IN subquery. TiDBOptInSubqToJoinAndAgg = "tidb_opt_insubq_to_join_and_agg" - // tidb_opt_prefer_range_scan is used to enable/disable the optimizer to always prefer range scan over table scan, ignoring their costs. + // TiDBOptPreferRangeScan is used to enable/disable the optimizer to always prefer range scan over table scan, ignoring their costs. TiDBOptPreferRangeScan = "tidb_opt_prefer_range_scan" - // tidb_opt_enable_correlation_adjustment is used to indicates if enable correlation adjustment. + // TiDBOptEnableCorrelationAdjustment is used to indicates if enable correlation adjustment. TiDBOptEnableCorrelationAdjustment = "tidb_opt_enable_correlation_adjustment" - // tidb_opt_limit_push_down_threshold determines if push Limit or TopN down to TiKV forcibly. + // TiDBOptLimitPushDownThreshold determines if push Limit or TopN down to TiKV forcibly. TiDBOptLimitPushDownThreshold = "tidb_opt_limit_push_down_threshold" - // tidb_opt_correlation_threshold is a guard to enable row count estimation using column order correlation. + // TiDBOptCorrelationThreshold is a guard to enable row count estimation using column order correlation. TiDBOptCorrelationThreshold = "tidb_opt_correlation_threshold" - // tidb_opt_correlation_exp_factor is an exponential factor to control heuristic approach when tidb_opt_correlation_threshold is not satisfied. + // TiDBOptCorrelationExpFactor is an exponential factor to control heuristic approach when tidb_opt_correlation_threshold is not satisfied. TiDBOptCorrelationExpFactor = "tidb_opt_correlation_exp_factor" - // tidb_opt_cpu_factor is the CPU cost of processing one expression for one row. + // TiDBOptCPUFactor is the CPU cost of processing one expression for one row. TiDBOptCPUFactor = "tidb_opt_cpu_factor" - // tidb_opt_copcpu_factor is the CPU cost of processing one expression for one row in coprocessor. + // TiDBOptCopCPUFactor is the CPU cost of processing one expression for one row in coprocessor. TiDBOptCopCPUFactor = "tidb_opt_copcpu_factor" - // tidb_opt_tiflash_concurrency_factor is concurrency number of tiflash computation. + // TiDBOptTiFlashConcurrencyFactor is concurrency number of tiflash computation. TiDBOptTiFlashConcurrencyFactor = "tidb_opt_tiflash_concurrency_factor" - // tidb_opt_network_factor is the network cost of transferring 1 byte data. + // TiDBOptNetworkFactor is the network cost of transferring 1 byte data. TiDBOptNetworkFactor = "tidb_opt_network_factor" - // tidb_opt_scan_factor is the IO cost of scanning 1 byte data on TiKV. + // TiDBOptScanFactor is the IO cost of scanning 1 byte data on TiKV. TiDBOptScanFactor = "tidb_opt_scan_factor" - // tidb_opt_desc_factor is the IO cost of scanning 1 byte data on TiKV in desc order. + // TiDBOptDescScanFactor is the IO cost of scanning 1 byte data on TiKV in desc order. TiDBOptDescScanFactor = "tidb_opt_desc_factor" - // tidb_opt_seek_factor is the IO cost of seeking the start value in a range on TiKV or TiFlash. + // TiDBOptSeekFactor is the IO cost of seeking the start value in a range on TiKV or TiFlash. TiDBOptSeekFactor = "tidb_opt_seek_factor" - // tidb_opt_memory_factor is the memory cost of storing one tuple. + // TiDBOptMemoryFactor is the memory cost of storing one tuple. TiDBOptMemoryFactor = "tidb_opt_memory_factor" - // tidb_opt_disk_factor is the IO cost of reading/writing one byte to temporary disk. + // TiDBOptDiskFactor is the IO cost of reading/writing one byte to temporary disk. TiDBOptDiskFactor = "tidb_opt_disk_factor" - // tidb_opt_concurrency_factor is the CPU cost of additional one goroutine. + // TiDBOptConcurrencyFactor is the CPU cost of additional one goroutine. TiDBOptConcurrencyFactor = "tidb_opt_concurrency_factor" - // tidb_index_join_batch_size is used to set the batch size of a index lookup join. + // TiDBIndexJoinBatchSize is used to set the batch size of an index lookup join. // The index lookup join fetches batches of data from outer executor and constructs ranges for inner executor. // This value controls how much of data in a batch to do the index join. // Large value may reduce the latency but consumes more system resource. TiDBIndexJoinBatchSize = "tidb_index_join_batch_size" - // tidb_index_lookup_size is used for index lookup executor. + // TiDBIndexLookupSize is used for index lookup executor. // The index lookup executor first scan a batch of handles from a index, then use those handles to lookup the table // rows, this value controls how much of handles in a batch to do a lookup task. // Small value sends more RPCs to TiKV, consume more system resource. // Large value may do more work than needed if the query has a limit. TiDBIndexLookupSize = "tidb_index_lookup_size" - // tidb_index_lookup_concurrency is used for index lookup executor. - // A lookup task may have 'tidb_index_lookup_size' of handles at maximun, the handles may be distributed - // in many TiKV nodes, we executes multiple concurrent index lookup tasks concurrently to reduce the time + // TiDBIndexLookupConcurrency is used for index lookup executor. + // A lookup task may have 'tidb_index_lookup_size' of handles at maximum, the handles may be distributed + // in many TiKV nodes, we execute multiple concurrent index lookup tasks concurrently to reduce the time // waiting for a task to finish. // Set this value higher may reduce the latency but consumes more system resource. // tidb_index_lookup_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBIndexLookupConcurrency = "tidb_index_lookup_concurrency" - // tidb_index_lookup_join_concurrency is used for index lookup join executor. + // TiDBIndexLookupJoinConcurrency is used for index lookup join executor. // IndexLookUpJoin starts "tidb_index_lookup_join_concurrency" inner workers // to fetch inner rows and join the matched (outer, inner) row pairs. // tidb_index_lookup_join_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBIndexLookupJoinConcurrency = "tidb_index_lookup_join_concurrency" - // tidb_index_serial_scan_concurrency is used for controlling the concurrency of index scan operation + // TiDBIndexSerialScanConcurrency is used for controlling the concurrency of index scan operation // when we need to keep the data output order the same as the order of index data. TiDBIndexSerialScanConcurrency = "tidb_index_serial_scan_concurrency" @@ -305,7 +305,7 @@ const ( TiDBMaxChunkSize = "tidb_max_chunk_size" // TiDBAllowBatchCop means if we should send batch coprocessor to TiFlash. It can be set to 0, 1 and 2. - // 0 means never use batch cop, 1 means use batch cop in case of aggregation and join, 2, means to force to send batch cop for any query. + // 0 means never use batch cop, 1 means use batch cop in case of aggregation and join, 2, means to force sending batch cop for any query. // The default value is 0 TiDBAllowBatchCop = "tidb_allow_batch_cop" @@ -332,71 +332,71 @@ const ( // TiDBInitChunkSize is used to control the init chunk size during query execution. TiDBInitChunkSize = "tidb_init_chunk_size" - // tidb_enable_cascades_planner is used to control whether to enable the cascades planner. + // TiDBEnableCascadesPlanner is used to control whether to enable the cascades planner. TiDBEnableCascadesPlanner = "tidb_enable_cascades_planner" - // tidb_skip_utf8_check skips the UTF8 validate process, validate UTF8 has performance cost, if we can make sure + // TiDBSkipUTF8Check skips the UTF8 validate process, validate UTF8 has performance cost, if we can make sure // the input string values are valid, we can skip the check. TiDBSkipUTF8Check = "tidb_skip_utf8_check" - // tidb_skip_ascii_check skips the ASCII validate process + // TiDBSkipASCIICheck skips the ASCII validate process // old tidb may already have fields with invalid ASCII bytes // disable ASCII validate can guarantee a safe replication TiDBSkipASCIICheck = "tidb_skip_ascii_check" - // tidb_hash_join_concurrency is used for hash join executor. + // TiDBHashJoinConcurrency is used for hash join executor. // The hash join outer executor starts multiple concurrent join workers to probe the hash table. // tidb_hash_join_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBHashJoinConcurrency = "tidb_hash_join_concurrency" - // tidb_projection_concurrency is used for projection operator. + // TiDBProjectionConcurrency is used for projection operator. // This variable controls the worker number of projection operator. // tidb_projection_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBProjectionConcurrency = "tidb_projection_concurrency" - // tidb_hashagg_partial_concurrency is used for hash agg executor. + // TiDBHashAggPartialConcurrency is used for hash agg executor. // The hash agg executor starts multiple concurrent partial workers to do partial aggregate works. // tidb_hashagg_partial_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBHashAggPartialConcurrency = "tidb_hashagg_partial_concurrency" - // tidb_hashagg_final_concurrency is used for hash agg executor. + // TiDBHashAggFinalConcurrency is used for hash agg executor. // The hash agg executor starts multiple concurrent final workers to do final aggregate works. // tidb_hashagg_final_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBHashAggFinalConcurrency = "tidb_hashagg_final_concurrency" - // tidb_window_concurrency is used for window parallel executor. + // TiDBWindowConcurrency is used for window parallel executor. // tidb_window_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBWindowConcurrency = "tidb_window_concurrency" - // tidb_merge_join_concurrency is used for merge join parallel executor + // TiDBMergeJoinConcurrency is used for merge join parallel executor TiDBMergeJoinConcurrency = "tidb_merge_join_concurrency" - // tidb_stream_agg_concurrency is used for stream aggregation parallel executor. + // TiDBStreamAggConcurrency is used for stream aggregation parallel executor. // tidb_stream_agg_concurrency is deprecated, use tidb_executor_concurrency instead. TiDBStreamAggConcurrency = "tidb_streamagg_concurrency" - // tidb_enable_parallel_apply is used for parallel apply. + // TiDBEnableParallelApply is used for parallel apply. TiDBEnableParallelApply = "tidb_enable_parallel_apply" - // tidb_backoff_lock_fast is used for tikv backoff base time in milliseconds. + // TiDBBackoffLockFast is used for tikv backoff base time in milliseconds. TiDBBackoffLockFast = "tidb_backoff_lock_fast" - // tidb_backoff_weight is used to control the max back off time in TiDB. + // TiDBBackOffWeight is used to control the max back off time in TiDB. // The default maximum back off time is a small value. // BackOffWeight could multiply it to let the user adjust the maximum time for retrying. // Only positive integers can be accepted, which means that the maximum back off time can only grow. TiDBBackOffWeight = "tidb_backoff_weight" - // tidb_ddl_reorg_worker_cnt defines the count of ddl reorg workers. + // TiDBDDLReorgWorkerCount defines the count of ddl reorg workers. TiDBDDLReorgWorkerCount = "tidb_ddl_reorg_worker_cnt" - // tidb_ddl_reorg_batch_size defines the transaction batch size of ddl reorg workers. + // TiDBDDLReorgBatchSize defines the transaction batch size of ddl reorg workers. TiDBDDLReorgBatchSize = "tidb_ddl_reorg_batch_size" - // tidb_ddl_error_count_limit defines the count of ddl error limit. + // TiDBDDLErrorCountLimit defines the count of ddl error limit. TiDBDDLErrorCountLimit = "tidb_ddl_error_count_limit" - // tidb_ddl_reorg_priority defines the operations priority of adding indices. + // TiDBDDLReorgPriority defines the operations' priority of adding indices. // It can be: PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH TiDBDDLReorgPriority = "tidb_ddl_reorg_priority" @@ -410,14 +410,14 @@ const ( // TiDBEnablePointGetCache is used to control whether to enable the point get cache for special scenario. TiDBEnablePointGetCache = "tidb_enable_point_get_cache" - // TiDBEnableAlterPlacement is used to control whether to enable alter table partition. - TiDBEnableAlterPlacement = "tidb_enable_alter_placement" + // TiDBPlacementMode is used to control the mode for placement + TiDBPlacementMode = "tidb_placement_mode" - // tidb_max_delta_schema_count defines the max length of deltaSchemaInfos. + // TiDBMaxDeltaSchemaCount defines the max length of deltaSchemaInfos. // deltaSchemaInfos is a queue that maintains the history of schema changes. TiDBMaxDeltaSchemaCount = "tidb_max_delta_schema_count" - // tidb_scatter_region will scatter the regions for DDLs when it is ON. + // TiDBScatterRegion will scatter the regions for DDLs when it is ON. TiDBScatterRegion = "tidb_scatter_region" // TiDBWaitSplitRegionFinish defines the split region behaviour is sync or async. @@ -426,31 +426,31 @@ const ( // TiDBWaitSplitRegionTimeout uses to set the split and scatter region back off time. TiDBWaitSplitRegionTimeout = "tidb_wait_split_region_timeout" - // tidb_force_priority defines the operations priority of all statements. + // TiDBForcePriority defines the operations' priority of all statements. // It can be "NO_PRIORITY", "LOW_PRIORITY", "HIGH_PRIORITY", "DELAYED" TiDBForcePriority = "tidb_force_priority" - // tidb_constraint_check_in_place indicates to check the constraint when the SQL executing. + // TiDBConstraintCheckInPlace indicates to check the constraint when the SQL executing. // It could hurt the performance of bulking insert when it is ON. TiDBConstraintCheckInPlace = "tidb_constraint_check_in_place" - // tidb_enable_window_function is used to control whether to enable the window function. + // TiDBEnableWindowFunction is used to control whether to enable the window function. TiDBEnableWindowFunction = "tidb_enable_window_function" - // tidb_enable_pipelined_window_function is used to control whether to use pipelined window function, it only works when tidb_enable_window_function = true. + // TiDBEnablePipelinedWindowFunction is used to control whether to use pipelined window function, it only works when tidb_enable_window_function = true. TiDBEnablePipelinedWindowFunction = "tidb_enable_pipelined_window_function" - // tidb_enable_strict_double_type_check is used to control table field double type syntax check. + // TiDBEnableStrictDoubleTypeCheck is used to control table field double type syntax check. TiDBEnableStrictDoubleTypeCheck = "tidb_enable_strict_double_type_check" - // tidb_enable_vectorized_expression is used to control whether to enable the vectorized expression evaluation. + // TiDBEnableVectorizedExpression is used to control whether to enable the vectorized expression evaluation. TiDBEnableVectorizedExpression = "tidb_enable_vectorized_expression" // TiDBOptJoinReorderThreshold defines the threshold less than which - // we'll choose a rather time consuming algorithm to calculate the join order. + // we'll choose a rather time-consuming algorithm to calculate the join order. TiDBOptJoinReorderThreshold = "tidb_opt_join_reorder_threshold" - // SlowQueryFile indicates which slow query log file for SLOW_QUERY table to parse. + // TiDBSlowQueryFile indicates which slow query log file for SLOW_QUERY table to parse. TiDBSlowQueryFile = "tidb_slow_query_file" // TiDBEnableFastAnalyze indicates to use fast analyze. @@ -511,7 +511,7 @@ const ( // TiDBEnableCollectExecutionInfo indicates that whether execution info is collected. TiDBEnableCollectExecutionInfo = "tidb_enable_collect_execution_info" - // DefExecutorConcurrency is used for controlling the concurrency of all types of executors. + // TiDBExecutorConcurrency is used for controlling the concurrency of all types of executors. TiDBExecutorConcurrency = "tidb_executor_concurrency" // TiDBEnableClusteredIndex indicates if clustered index feature is enabled. @@ -520,16 +520,15 @@ const ( // TiDBPartitionPruneMode indicates the partition prune mode used. TiDBPartitionPruneMode = "tidb_partition_prune_mode" - // TiDBSlowLogMasking is deprecated and a alias of TiDBRedactLog. - // Deprecated: use TiDBRedactLog instead. - TiDBSlowLogMasking = "tidb_slow_log_masking" - // TiDBRedactLog indicates that whether redact log. TiDBRedactLog = "tidb_redact_log" // TiDBRestrictedReadOnly is meant for the cloud admin to toggle the cluster read only TiDBRestrictedReadOnly = "tidb_restricted_read_only" + // TiDBSuperReadOnly is tidb's variant of mysql's super_read_only, which has some differences from mysql's super_read_only. + TiDBSuperReadOnly = "tidb_super_read_only" + // TiDBShardAllocateStep indicates the max size of continuous rowid shard in one transaction. TiDBShardAllocateStep = "tidb_shard_allocate_step" // TiDBEnableTelemetry indicates that whether usage data report to PingCAP is enabled. @@ -553,7 +552,7 @@ const ( // TiDBGuaranteeLinearizability indicates whether to guarantee linearizability. TiDBGuaranteeLinearizability = "tidb_guarantee_linearizability" - // TiDBAnalyzeVersion indicates the how tidb collects the analyzed statistics and how use to it. + // TiDBAnalyzeVersion indicates how tidb collects the analyzed statistics and how use to it. TiDBAnalyzeVersion = "tidb_analyze_version" // TiDBEnableIndexMergeJoin indicates whether to enable index merge join. @@ -572,29 +571,32 @@ const ( // TiDBEnableTopSQL indicates whether the top SQL is enabled. TiDBEnableTopSQL = "tidb_enable_top_sql" - // TiDBTopSQLPrecisionSeconds indicates the top SQL precision seconds. - TiDBTopSQLPrecisionSeconds = "tidb_top_sql_precision_seconds" - - // TiDBTopSQLMaxStatementCount indicates the max number of statements been collected. - TiDBTopSQLMaxStatementCount = "tidb_top_sql_max_statement_count" + // TiDBTopSQLMaxTimeSeriesCount indicates the max number of statements been collected in each time series. + TiDBTopSQLMaxTimeSeriesCount = "tidb_top_sql_max_time_series_count" - // TiDBTopSQLMaxCollect indicates the max capacity of the collect map. - TiDBTopSQLMaxCollect = "tidb_top_sql_max_collect" + // TiDBTopSQLMaxMetaCount indicates the max capacity of the collect meta per second. + TiDBTopSQLMaxMetaCount = "tidb_top_sql_max_meta_count" - // TiDBTopSQLReportIntervalSeconds indicates the top SQL report interval seconds. - TiDBTopSQLReportIntervalSeconds = "tidb_top_sql_report_interval_seconds" - // TiDBEnableGlobalTemporaryTable indicates whether to enable global temporary table - TiDBEnableGlobalTemporaryTable = "tidb_enable_global_temporary_table" // TiDBEnableLocalTxn indicates whether to enable Local Txn. TiDBEnableLocalTxn = "tidb_enable_local_txn" + // TiDBTSOClientBatchMaxWaitTime indicates the max value of the TSO Batch Wait interval time of PD client. TiDBTSOClientBatchMaxWaitTime = "tidb_tso_client_batch_max_wait_time" + + // TiDBTxnCommitBatchSize is used to control the batch size of transaction commit related requests sent by TiDB to TiKV. + // If a single transaction has a large amount of writes, you can increase the batch size to improve the batch effect, + // setting too large will exceed TiKV's raft-entry-max-size limit and cause commit failure. + TiDBTxnCommitBatchSize = "tidb_txn_commit_batch_size" + // TiDBEnableTSOFollowerProxy indicates whether to enable the TSO Follower Proxy feature of PD client. TiDBEnableTSOFollowerProxy = "tidb_enable_tso_follower_proxy" // TiDBEnableOrderedResultMode indicates if stabilize query results. TiDBEnableOrderedResultMode = "tidb_enable_ordered_result_mode" + // TiDBRemoveOrderbyInSubquery indicates whether to remove ORDER BY in subquery. + TiDBRemoveOrderbyInSubquery = "tidb_remove_orderby_in_subquery" + // TiDBEnablePseudoForOutdatedStats indicates whether use pseudo for outdated stats TiDBEnablePseudoForOutdatedStats = "tidb_enable_pseudo_for_outdated_stats" @@ -603,6 +605,27 @@ const ( // TiDBTmpTableMaxSize indicates the max memory size of temporary tables. TiDBTmpTableMaxSize = "tidb_tmp_table_max_size" + + // TiDBEnableLegacyInstanceScope indicates if instance scope can be set with SET SESSION. + TiDBEnableLegacyInstanceScope = "tidb_enable_legacy_instance_scope" + + // TiDBTableCacheLease indicates the read lock lease of a cached table. + TiDBTableCacheLease = "tidb_table_cache_lease" + + // TiDBStatsLoadSyncWait indicates the time sql execution will sync-wait for stats load. + TiDBStatsLoadSyncWait = "tidb_stats_load_sync_wait" + + // TiDBEnableMutationChecker indicates whether to check data consistency for mutations + TiDBEnableMutationChecker = "tidb_enable_mutation_checker" + // TiDBTxnAssertionLevel indicates how strict the assertion will be, which helps to detect and preventing data & + // index inconsistency problems. + TiDBTxnAssertionLevel = "tidb_txn_assertion_level" + + // TiDBIgnorePreparedCacheCloseStmt indicates whether to ignore close-stmt commands for prepared statements. + TiDBIgnorePreparedCacheCloseStmt = "tidb_ignore_prepared_cache_close_stmt" + + // TiDBBatchPendingTiFlashCount indicates the maximum count of non-available TiFlash tables. + TiDBBatchPendingTiFlashCount = "tidb_batch_pending_tiflash_count" ) // TiDB vars that have only global scope @@ -618,14 +641,30 @@ const ( TiDBGCConcurrency = "tidb_gc_concurrency" // TiDBGCScanLockMode enables the green GC feature (default) TiDBGCScanLockMode = "tidb_gc_scan_lock_mode" + // TiDBGCMaxWaitTime sets max time for gc advances the safepoint delayed by active transactions + TiDBGCMaxWaitTime = "tidb_gc_max_wait_time" // TiDBEnableEnhancedSecurity restricts SUPER users from certain operations. TiDBEnableEnhancedSecurity = "tidb_enable_enhanced_security" // TiDBEnableHistoricalStats enables the historical statistics feature (default off) TiDBEnableHistoricalStats = "tidb_enable_historical_stats" + // TiDBPersistAnalyzeOptions persists analyze options for later analyze and auto-analyze + TiDBPersistAnalyzeOptions = "tidb_persist_analyze_options" + // TiDBEnableColumnTracking enables collecting predicate columns. + TiDBEnableColumnTracking = "tidb_enable_column_tracking" + // TiDBDisableColumnTrackingTime records the last time TiDBEnableColumnTracking is set off. + // It is used to invalidate the collected predicate columns after turning off TiDBEnableColumnTracking, which avoids physical deletion. + // It doesn't have cache in memory, and we directly get/set the variable value from/to mysql.tidb. + TiDBDisableColumnTrackingTime = "tidb_disable_column_tracking_time" + // TiDBStatsLoadPseudoTimeout indicates whether to fallback to pseudo stats after load timeout. + TiDBStatsLoadPseudoTimeout = "tidb_stats_load_pseudo_timeout" + // TiDBMemQuotaBindingCache indicates the memory quota for the bind cache. + TiDBMemQuotaBindingCache = "tidb_mem_quota_binding_cache" + // TiDBRCReadCheckTS indicates the tso optimization for read-consistency read is enabled. + TiDBRCReadCheckTS = "tidb_rc_read_check_ts" ) // TiDB intentional limits -// Can be raised in future. +// Can be raised in the future. const ( // MaxConfigurableConcurrency is the maximum number of "threads" (goroutines) that can be specified @@ -652,7 +691,6 @@ const ( DefSkipUTF8Check = false DefSkipASCIICheck = false DefOptAggPushDown = false - DefOptBCJ = false DefOptCartesianBCJ = 1 DefOptMPPOuterJoinFixedBuildSide = false DefOptWriteRowID = false @@ -682,13 +720,7 @@ const ( DefMaxPreparedStmtCount = -1 DefWaitTimeout = 28800 DefTiDBMemQuotaApplyCache = 32 << 20 // 32MB. - DefTiDBMemQuotaHashJoin = 32 << 30 // 32GB. - DefTiDBMemQuotaMergeJoin = 32 << 30 // 32GB. - DefTiDBMemQuotaSort = 32 << 30 // 32GB. - DefTiDBMemQuotaTopn = 32 << 30 // 32GB. - DefTiDBMemQuotaIndexLookupReader = 32 << 30 // 32GB. - DefTiDBMemQuotaIndexLookupJoin = 32 << 30 // 32GB. - DefTiDBMemQuotaDistSQL = 32 << 30 // 32GB. + DefTiDBMemQuotaBindingCache = 64 << 20 // 64MB. DefTiDBGeneralLog = false DefTiDBPProfSQLCPU = 0 DefTiDBRetryLimit = 10 @@ -699,6 +731,7 @@ const ( DefBroadcastJoinThresholdSize = 100 * 1024 * 1024 DefBroadcastJoinThresholdCount = 10 * 1024 DefTiDBOptimizerSelectivityLevel = 0 + DefTiDBOptimizerEnableNewOFGB = false DefTiDBAllowBatchCop = 1 DefTiDBAllowMPPExecution = true DefTiDBHashExchangeWithNewCollation = true @@ -713,7 +746,7 @@ const ( DefTiDBMaxDeltaSchemaCount = 1024 DefTiDBChangeMultiSchema = false DefTiDBPointGetCache = false - DefTiDBEnableAlterPlacement = false + DefTiDBPlacementMode = PlacementModeStrict DefTiDBEnableAutoIncrementInGenerated = false DefTiDBHashAggPartialConcurrency = ConcurrencyUnset DefTiDBHashAggFinalConcurrency = ConcurrencyUnset @@ -751,6 +784,7 @@ const ( DefTiDBEnableClusteredIndex = ClusteredIndexDefModeIntOnly DefTiDBRedactLog = false DefTiDBRestrictedReadOnly = false + DefTiDBSuperReadOnly = false DefTiDBShardAllocateStep = math.MaxInt64 DefTiDBEnableTelemetry = true DefTiDBEnableParallelApply = false @@ -765,11 +799,6 @@ const ( DefTiDBTrackAggregateMemoryUsage = true DefTiDBEnableExchangePartition = false DefCTEMaxRecursionDepth = 1000 - DefTiDBTopSQLEnable = false - DefTiDBTopSQLPrecisionSeconds = 1 - DefTiDBTopSQLMaxStatementCount = 200 - DefTiDBTopSQLMaxCollect = 5000 - DefTiDBTopSQLReportIntervalSeconds = 60 DefTiDBTmpTableMaxSize = 64 << 20 // 64MB. DefTiDBEnableLocalTxn = false DefTiDBTSOClientBatchMaxWaitTime = 0.0 // 0ms @@ -779,6 +808,29 @@ const ( DefTiDBRegardNULLAsPoint = true DefEnablePlacementCheck = true DefTimestamp = "0" + DefTiDBEnableStmtSummary = true + DefTiDBStmtSummaryInternalQuery = false + DefTiDBStmtSummaryRefreshInterval = 1800 + DefTiDBStmtSummaryHistorySize = 24 + DefTiDBStmtSummaryMaxStmtCount = 3000 + DefTiDBStmtSummaryMaxSQLLength = 4096 + DefTiDBCapturePlanBaseline = Off + DefTiDBEnableIndexMerge = true + DefEnableLegacyInstanceScope = true + DefTiDBTableCacheLease = 3 // 3s + DefTiDBPersistAnalyzeOptions = true + DefTiDBEnableColumnTracking = false + DefTiDBStatsLoadSyncWait = 0 + DefTiDBStatsLoadPseudoTimeout = false + DefSysdateIsNow = false + DefTiDBEnableMutationChecker = false + DefTiDBTxnAssertionLevel = AssertionOffStr + DefTiDBIgnorePreparedCacheCloseStmt = false + DefTiDBBatchPendingTiFlashCount = 4000 + DefRCReadCheckTS = false + DefTiDBRemoveOrderbyInSubquery = false + DefTiDBReadStaleness = 0 + DefTiDBGCMaxWaitTime = 24 * 60 * 60 ) // Process global variables. @@ -791,7 +843,7 @@ var ( ddlErrorCountlimit int64 = DefTiDBDDLErrorCountLimit ddlReorgRowFormat int64 = DefTiDBRowFormatV2 maxDeltaSchemaCount int64 = DefTiDBMaxDeltaSchemaCount - // Export for testing. + // MaxDDLReorgBatchSize is exported for testing. MaxDDLReorgBatchSize int32 = 10240 MinDDLReorgBatchSize int32 = 32 // DDLSlowOprThreshold is the threshold for ddl slow operations, uint is millisecond. @@ -800,37 +852,18 @@ var ( MaxOfMaxAllowedPacket uint64 = 1073741824 ExpensiveQueryTimeThreshold uint64 = DefTiDBExpensiveQueryTimeThreshold MinExpensiveQueryTimeThreshold uint64 = 10 // 10s - CapturePlanBaseline = serverGlobalVariable{globalVal: Off} DefExecutorConcurrency = 5 MemoryUsageAlarmRatio = atomic.NewFloat64(config.GetGlobalConfig().Performance.MemoryUsageAlarmRatio) - TopSQLVariable = TopSQL{ - Enable: atomic.NewBool(DefTiDBTopSQLEnable), - PrecisionSeconds: atomic.NewInt64(DefTiDBTopSQLPrecisionSeconds), - MaxStatementCount: atomic.NewInt64(DefTiDBTopSQLMaxStatementCount), - MaxCollect: atomic.NewInt64(DefTiDBTopSQLMaxCollect), - ReportIntervalSeconds: atomic.NewInt64(DefTiDBTopSQLReportIntervalSeconds), - } - EnableLocalTxn = atomic.NewBool(DefTiDBEnableLocalTxn) - MaxTSOBatchWaitInterval = atomic.NewFloat64(DefTiDBTSOClientBatchMaxWaitTime) - EnableTSOFollowerProxy = atomic.NewBool(DefTiDBEnableTSOFollowerProxy) - RestrictedReadOnly = atomic.NewBool(DefTiDBRestrictedReadOnly) + EnableLocalTxn = atomic.NewBool(DefTiDBEnableLocalTxn) + MaxTSOBatchWaitInterval = atomic.NewFloat64(DefTiDBTSOClientBatchMaxWaitTime) + EnableTSOFollowerProxy = atomic.NewBool(DefTiDBEnableTSOFollowerProxy) + RestrictedReadOnly = atomic.NewBool(DefTiDBRestrictedReadOnly) + VarTiDBSuperReadOnly = atomic.NewBool(DefTiDBSuperReadOnly) + PersistAnalyzeOptions = atomic.NewBool(DefTiDBPersistAnalyzeOptions) + TableCacheLease = atomic.NewInt64(DefTiDBTableCacheLease) + EnableColumnTracking = atomic.NewBool(DefTiDBEnableColumnTracking) + StatsLoadSyncWait = atomic.NewInt64(DefTiDBStatsLoadSyncWait) + StatsLoadPseudoTimeout = atomic.NewBool(DefTiDBStatsLoadPseudoTimeout) + MemQuotaBindingCache = atomic.NewInt64(DefTiDBMemQuotaBindingCache) + GCMaxWaitTime = atomic.NewInt64(DefTiDBGCMaxWaitTime) ) - -// TopSQL is the variable for control top sql feature. -type TopSQL struct { - // Enable top-sql or not. - Enable *atomic.Bool - // The refresh interval of top-sql. - PrecisionSeconds *atomic.Int64 - // The maximum number of statements kept in memory. - MaxStatementCount *atomic.Int64 - // The maximum capacity of the collect map. - MaxCollect *atomic.Int64 - // The report data interval of top-sql. - ReportIntervalSeconds *atomic.Int64 -} - -// TopSQLEnabled uses to check whether enabled the top SQL feature. -func TopSQLEnabled() bool { - return TopSQLVariable.Enable.Load() && config.GetGlobalConfig().TopSQL.ReceiverAddress != "" -} diff --git a/sessionctx/variable/variable.go b/sessionctx/variable/variable.go index aeb65a8257d9f..7989f50fe2e8e 100644 --- a/sessionctx/variable/variable.go +++ b/sessionctx/variable/variable.go @@ -15,7 +15,6 @@ package variable import ( - "fmt" "strconv" "strings" "sync" @@ -39,6 +38,8 @@ const ( ScopeGlobal ScopeFlag = 1 << 0 // ScopeSession means the system variable can only be changed in current session. ScopeSession ScopeFlag = 1 << 1 + // ScopeInstance means it is similar to global but doesn't propagate to other TiDB servers. + ScopeInstance ScopeFlag = 1 << 2 // TypeStr is the default TypeStr TypeFlag = 0 @@ -65,6 +66,15 @@ const ( Warn = "WARN" // IntOnly means enable for int type IntOnly = "INT_ONLY" + + // AssertionStrictStr is a choice of variable TiDBTxnAssertionLevel that means full assertions should be performed, + // even if the performance might be slowed down. + AssertionStrictStr = "STRICT" + // AssertionFastStr is a choice of variable TiDBTxnAssertionLevel that means assertions that doesn't affect + // performance should be performed. + AssertionFastStr = "FAST" + // AssertionOffStr is a choice of variable TiDBTxnAssertionLevel that means no assertion should be performed. + AssertionOffStr = "OFF" ) // Global config name list. @@ -240,6 +250,11 @@ func (sv *SysVar) HasGlobalScope() bool { return sv.Scope&ScopeGlobal != 0 } +// HasInstanceScope returns true if the scope for the sysVar includes instance +func (sv *SysVar) HasInstanceScope() bool { + return sv.Scope&ScopeInstance != 0 +} + // Validate checks if system variable satisfies specific restriction. func (sv *SysVar) Validate(vars *SessionVars, value string, scope ScopeFlag) (string, error) { // Check that the scope is correct first. @@ -291,7 +306,7 @@ func (sv *SysVar) validateScope(scope ScopeFlag) error { if sv.ReadOnly || sv.Scope == ScopeNone { return ErrIncorrectScope.FastGenByArgs(sv.Name, "read only") } - if scope == ScopeGlobal && !sv.HasGlobalScope() { + if scope == ScopeGlobal && !(sv.HasGlobalScope() || sv.HasInstanceScope()) { return errLocalVariable.FastGenByArgs(sv.Name) } if scope == ScopeSession && !sv.HasSessionScope() { @@ -373,7 +388,7 @@ func (sv *SysVar) checkUInt64SystemVar(value string, vars *SessionVars) (string, return value, ErrWrongTypeForVar.GenWithStackByArgs(sv.Name) } vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MinValue), nil + return strconv.FormatInt(sv.MinValue, 10), nil } val, err := strconv.ParseUint(value, 10, 64) if err != nil { @@ -381,11 +396,12 @@ func (sv *SysVar) checkUInt64SystemVar(value string, vars *SessionVars) (string, } if val < uint64(sv.MinValue) { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MinValue), nil + return strconv.FormatInt(sv.MinValue, 10), nil } if val > sv.MaxValue { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MaxValue), nil + return strconv.FormatUint(sv.MaxValue, 10), nil + } return value, nil } @@ -400,11 +416,11 @@ func (sv *SysVar) checkInt64SystemVar(value string, vars *SessionVars) (string, } if val < sv.MinValue { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MinValue), nil + return strconv.FormatInt(sv.MinValue, 10), nil } if val > int64(sv.MaxValue) { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MaxValue), nil + return strconv.FormatUint(sv.MaxValue, 10), nil } return value, nil } @@ -414,7 +430,7 @@ func (sv *SysVar) checkEnumSystemVar(value string, vars *SessionVars) (string, e // This allows for the behavior 0 = OFF, 1 = ON, 2 = DEMAND etc. var iStr string for i, v := range sv.PossibleValues { - iStr = fmt.Sprintf("%d", i) + iStr = strconv.Itoa(i) if strings.EqualFold(value, v) || strings.EqualFold(value, iStr) { return v, nil } @@ -432,11 +448,11 @@ func (sv *SysVar) checkFloatSystemVar(value string, vars *SessionVars) (string, } if val < float64(sv.MinValue) { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MinValue), nil + return strconv.FormatInt(sv.MinValue, 10), nil } if val > float64(sv.MaxValue) { vars.StmtCtx.AppendWarning(ErrTruncatedWrongValue.GenWithStackByArgs(sv.Name, value)) - return fmt.Sprintf("%d", sv.MaxValue), nil + return strconv.FormatUint(sv.MaxValue, 10), nil } return value, nil } @@ -497,7 +513,7 @@ func (sv *SysVar) SkipInit() bool { // These a special "Global-only" sysvars that for backward compatibility // are currently cached in the session. Please don't add to this list. switch sv.Name { - case TiDBEnableChangeMultiSchema, TiDBDDLReorgBatchSize, TiDBEnableAlterPlacement, + case TiDBEnableChangeMultiSchema, TiDBDDLReorgBatchSize, TiDBMaxDeltaSchemaCount, InitConnect, MaxPreparedStmtCount, TiDBDDLReorgWorkerCount, TiDBDDLErrorCountLimit, TiDBRowFormatVersion, TiDBEnableTelemetry, TiDBEnablePointGetCache: @@ -550,12 +566,12 @@ func SetSysVar(name string, value string) { func GetSysVars() map[string]*SysVar { sysVarsLock.RLock() defer sysVarsLock.RUnlock() - copy := make(map[string]*SysVar, len(sysVars)) + m := make(map[string]*SysVar, len(sysVars)) for name, sv := range sysVars { tmp := *sv - copy[name] = &tmp + m[name] = &tmp } - return copy + return m } func init() { diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 15f13a53521f5..977ee42a69da6 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -19,7 +19,6 @@ import ( "sort" "strconv" "strings" - "sync" "sync/atomic" "time" @@ -328,6 +327,31 @@ func TiDBOptEnableClustered(opt string) ClusteredIndexDefMode { } } +// AssertionLevel controls the assertion that will be performed during transactions. +type AssertionLevel int + +const ( + // AssertionLevelOff indicates no assertion should be performed. + AssertionLevelOff AssertionLevel = iota + // AssertionLevelFast indicates assertions that doesn't affect performance should be performed. + AssertionLevelFast + // AssertionLevelStrict indicates full assertions should be performed, even if the performance might be slowed down. + AssertionLevelStrict +) + +func tidbOptAssertionLevel(opt string) AssertionLevel { + switch opt { + case AssertionStrictStr: + return AssertionLevelStrict + case AssertionFastStr: + return AssertionLevelFast + case AssertionOffStr: + return AssertionLevelOff + default: + return AssertionLevelOff + } +} + func tidbOptPositiveInt32(opt string, defaultVal int) int { val, err := strconv.Atoi(opt) if err != nil || val <= 0 { @@ -336,7 +360,8 @@ func tidbOptPositiveInt32(opt string, defaultVal int) int { return val } -func tidbOptInt(opt string, defaultVal int) int { +// TidbOptInt converts a string to an int +func TidbOptInt(opt string, defaultVal int) int { val, err := strconv.Atoi(opt) if err != nil { return defaultVal @@ -344,7 +369,8 @@ func tidbOptInt(opt string, defaultVal int) int { return val } -func tidbOptInt64(opt string, defaultVal int64) int64 { +// TidbOptInt64 converts a string to an int64 +func TidbOptInt64(opt string, defaultVal int64) int64 { val, err := strconv.ParseInt(opt, 10, 64) if err != nil { return defaultVal @@ -402,6 +428,9 @@ func setSnapshotTS(s *SessionVars, sVal string) error { s.SnapshotInfoschema = nil return nil } + if s.ReadStaleness != 0 { + return fmt.Errorf("tidb_read_staleness should be clear before setting tidb_snapshot") + } if tso, err := strconv.ParseUint(sVal, 10, 64); err == nil { s.SnapshotTS = tso @@ -446,47 +475,19 @@ func setReadStaleness(s *SessionVars, sVal string) error { s.ReadStaleness = 0 return nil } + if s.SnapshotTS != 0 { + return fmt.Errorf("tidb_snapshot should be clear before setting tidb_read_staleness") + } sValue, err := strconv.ParseInt(sVal, 10, 32) if err != nil { return err } - if sValue > 0 { - return fmt.Errorf("%s's value should be less than 0", TiDBReadStaleness) - } s.ReadStaleness = time.Duration(sValue) * time.Second return nil } -// serverGlobalVariable is used to handle variables that acts in server and global scope. -type serverGlobalVariable struct { - sync.Mutex - serverVal string - globalVal string -} - -// Set sets the value according to variable scope. -func (v *serverGlobalVariable) Set(val string, isServer bool) { - v.Lock() - if isServer { - v.serverVal = val - } else { - v.globalVal = val - } - v.Unlock() -} - -// GetVal gets the value. -func (v *serverGlobalVariable) GetVal() string { - v.Lock() - defer v.Unlock() - if v.serverVal != "" { - return v.serverVal - } - return v.globalVal -} - func collectAllowFuncName4ExpressionIndex() string { - var str []string + str := make([]string, 0, len(GAFunction4ExpressionIndex)) for funcName := range GAFunction4ExpressionIndex { str = append(str, funcName) } @@ -501,4 +502,38 @@ var GAFunction4ExpressionIndex = map[string]struct{}{ ast.MD5: {}, ast.Reverse: {}, ast.VitessHash: {}, + ast.TiDBShard: {}, +} + +func checkGCTxnMaxWaitTime(vars *SessionVars, + normalizedValue string, + originalValue string, + scope ScopeFlag) (string, error) { + ival, err := strconv.Atoi(normalizedValue) + if err != nil { + return originalValue, errors.Trace(err) + } + GcLifeTimeStr, _ := getTiDBTableValue(vars, "tikv_gc_life_time", "10m0s") + GcLifeTimeDuration, err := time.ParseDuration(GcLifeTimeStr) + if err != nil { + return originalValue, errors.Trace(err) + } + if GcLifeTimeDuration.Seconds() > (float64)(ival) { + return originalValue, errors.Trace(ErrWrongValueForVar.GenWithStackByArgs(TiDBGCMaxWaitTime, normalizedValue)) + } + return normalizedValue, nil +} + +func checkTiKVGCLifeTime(vars *SessionVars, + normalizedValue string, + originalValue string, + scope ScopeFlag) (string, error) { + gcLifetimeDuration, err := time.ParseDuration(normalizedValue) + if err != nil { + return originalValue, errors.Trace(err) + } + if gcLifetimeDuration.Seconds() > float64(GCMaxWaitTime.Load()) { + return originalValue, errors.Trace(ErrWrongValueForVar.GenWithStackByArgs(TiDBGCLifetime, normalizedValue)) + } + return normalizedValue, nil } diff --git a/sessionctx/variable/varsutil_test.go b/sessionctx/variable/varsutil_test.go index b50399cf851a8..fbe84adf756c4 100644 --- a/sessionctx/variable/varsutil_test.go +++ b/sessionctx/variable/varsutil_test.go @@ -63,7 +63,6 @@ func TestNewSessionVars(t *testing.T) { require.Equal(t, DefExecutorConcurrency, vars.IndexLookupJoinConcurrency()) require.Equal(t, DefExecutorConcurrency, vars.HashJoinConcurrency()) require.Equal(t, DefTiDBAllowBatchCop, vars.AllowBatchCop) - require.Equal(t, DefOptBCJ, vars.AllowBCJ) require.Equal(t, ConcurrencyUnset, vars.projectionConcurrency) require.Equal(t, ConcurrencyUnset, vars.hashAggPartialConcurrency) require.Equal(t, ConcurrencyUnset, vars.hashAggFinalConcurrency) @@ -82,12 +81,6 @@ func TestNewSessionVars(t *testing.T) { require.Equal(t, DefMaxChunkSize, vars.MaxChunkSize) require.Equal(t, DefDMLBatchSize, vars.DMLBatchSize) require.Equal(t, config.GetGlobalConfig().MemQuotaQuery, vars.MemQuotaQuery) - require.Equal(t, int64(DefTiDBMemQuotaHashJoin), vars.MemQuotaHashJoin) - require.Equal(t, int64(DefTiDBMemQuotaMergeJoin), vars.MemQuotaMergeJoin) - require.Equal(t, int64(DefTiDBMemQuotaSort), vars.MemQuotaSort) - require.Equal(t, int64(DefTiDBMemQuotaTopn), vars.MemQuotaTopn) - require.Equal(t, int64(DefTiDBMemQuotaIndexLookupReader), vars.MemQuotaIndexLookupReader) - require.Equal(t, int64(DefTiDBMemQuotaIndexLookupJoin), vars.MemQuotaIndexLookupJoin) require.Equal(t, int64(DefTiDBMemQuotaApplyCache), vars.MemQuotaApplyCache) require.Equal(t, DefOptWriteRowID, vars.AllowWriteRowID) require.Equal(t, DefTiDBOptJoinReorderThreshold, vars.TiDBOptJoinReorderThreshold) @@ -208,17 +201,6 @@ func TestVarsutil(t *testing.T) { require.Equal(t, mode, v.SQLMode) } - err = SetSessionSystemVar(v, "tidb_opt_broadcast_join", "1") - require.NoError(t, err) - err = SetSessionSystemVar(v, "tidb_allow_batch_cop", "0") - require.True(t, terror.ErrorEqual(err, ErrWrongValueForVar)) - err = SetSessionSystemVar(v, "tidb_opt_broadcast_join", "0") - require.NoError(t, err) - err = SetSessionSystemVar(v, "tidb_allow_batch_cop", "0") - require.NoError(t, err) - err = SetSessionSystemVar(v, "tidb_opt_broadcast_join", "1") - require.True(t, terror.ErrorEqual(err, ErrWrongValueForVar)) - // Combined sql_mode err = SetSessionSystemVar(v, "sql_mode", "REAL_AS_FLOAT,ANSI_QUOTES") require.NoError(t, err) @@ -252,24 +234,16 @@ func TestVarsutil(t *testing.T) { require.NoError(t, err) require.Equal(t, config.HideConfig(string(bVal)), val) - err = SetSessionSystemVar(v, TiDBEnableStreaming, "1") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBEnableStreaming) - require.NoError(t, err) - require.Equal(t, "ON", val) - require.True(t, v.EnableStreaming) - err = SetSessionSystemVar(v, TiDBEnableStreaming, "0") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBEnableStreaming) - require.NoError(t, err) - require.Equal(t, "OFF", val) - require.False(t, v.EnableStreaming) - require.Equal(t, DefTiDBOptimizerSelectivityLevel, v.OptimizerSelectivityLevel) err = SetSessionSystemVar(v, TiDBOptimizerSelectivityLevel, "1") require.NoError(t, err) require.Equal(t, 1, v.OptimizerSelectivityLevel) + require.Equal(t, DefTiDBOptimizerEnableNewOFGB, v.OptimizerEnableNewOnlyFullGroupByCheck) + err = SetSessionSystemVar(v, TiDBOptimizerEnableNewOnlyFullGroupByCheck, "off") + require.NoError(t, err) + require.Equal(t, false, v.OptimizerEnableNewOnlyFullGroupByCheck) + err = SetSessionSystemVar(v, TiDBDDLReorgWorkerCount, "4") // wrong scope global only require.True(t, terror.ErrorEqual(err, errGlobalVariable)) @@ -309,13 +283,13 @@ func TestVarsutil(t *testing.T) { val, err = GetSessionOrGlobalSystemVar(v, TiDBCheckMb4ValueInUTF8) require.NoError(t, err) require.Equal(t, "ON", val) - require.True(t, config.GetGlobalConfig().CheckMb4ValueInUTF8) + require.True(t, config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()) err = SetSessionSystemVar(v, TiDBCheckMb4ValueInUTF8, "0") require.NoError(t, err) val, err = GetSessionOrGlobalSystemVar(v, TiDBCheckMb4ValueInUTF8) require.NoError(t, err) require.Equal(t, "OFF", val) - require.False(t, config.GetGlobalConfig().CheckMb4ValueInUTF8) + require.False(t, config.GetGlobalConfig().CheckMb4ValueInUTF8.Load()) err = SetSessionSystemVar(v, TiDBLowResolutionTSO, "1") require.NoError(t, err) @@ -437,48 +411,12 @@ func TestVarsutil(t *testing.T) { require.Equal(t, "leader-and-follower", val) require.Equal(t, kv.ReplicaReadMixed, v.GetReplicaRead()) - err = SetSessionSystemVar(v, TiDBEnableStmtSummary, "ON") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBEnableStmtSummary) - require.NoError(t, err) - require.Equal(t, "ON", val) - err = SetSessionSystemVar(v, TiDBRedactLog, "ON") require.NoError(t, err) val, err = GetSessionOrGlobalSystemVar(v, TiDBRedactLog) require.NoError(t, err) require.Equal(t, "ON", val) - err = SetSessionSystemVar(v, TiDBStmtSummaryRefreshInterval, "10") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBStmtSummaryRefreshInterval) - require.NoError(t, err) - require.Equal(t, "10", val) - - err = SetSessionSystemVar(v, TiDBStmtSummaryHistorySize, "10") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBStmtSummaryHistorySize) - require.NoError(t, err) - require.Equal(t, "10", val) - - err = SetSessionSystemVar(v, TiDBStmtSummaryMaxStmtCount, "10") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBStmtSummaryMaxStmtCount) - require.NoError(t, err) - require.Equal(t, "10", val) - err = SetSessionSystemVar(v, TiDBStmtSummaryMaxStmtCount, "a") - require.Error(t, err) - require.Regexp(t, "Incorrect argument type to variable 'tidb_stmt_summary_max_stmt_count'$", err) - - err = SetSessionSystemVar(v, TiDBStmtSummaryMaxSQLLength, "10") - require.NoError(t, err) - val, err = GetSessionOrGlobalSystemVar(v, TiDBStmtSummaryMaxSQLLength) - require.NoError(t, err) - require.Equal(t, "10", val) - err = SetSessionSystemVar(v, TiDBStmtSummaryMaxSQLLength, "a") - require.Error(t, err) - require.Regexp(t, "Incorrect argument type to variable 'tidb_stmt_summary_max_sql_length'$", err.Error()) - err = SetSessionSystemVar(v, TiDBFoundInPlanCache, "1") require.Error(t, err) require.Regexp(t, "]Variable 'last_plan_from_cache' is a read only variable$", err.Error()) @@ -500,6 +438,10 @@ func TestVarsutil(t *testing.T) { warn := v.StmtCtx.GetWarnings()[0] require.Error(t, warn.Err) require.Contains(t, warn.Err.Error(), "Truncated incorrect tidb_analyze_version value") + + err = SetSessionSystemVar(v, TiDBTableCacheLease, "123") + require.Error(t, err) + require.Regexp(t, "'tidb_table_cache_lease' is a GLOBAL variable and should be set with SET GLOBAL", err.Error()) } func TestValidate(t *testing.T) { @@ -641,45 +583,30 @@ func TestValidateStmtSummary(t *testing.T) { key string value string error bool - scope ScopeFlag }{ - {TiDBEnableStmtSummary, "a", true, ScopeSession}, - {TiDBEnableStmtSummary, "-1", true, ScopeSession}, - {TiDBEnableStmtSummary, "", false, ScopeSession}, - {TiDBEnableStmtSummary, "", true, ScopeGlobal}, - {TiDBStmtSummaryInternalQuery, "a", true, ScopeSession}, - {TiDBStmtSummaryInternalQuery, "-1", true, ScopeSession}, - {TiDBStmtSummaryInternalQuery, "", false, ScopeSession}, - {TiDBStmtSummaryInternalQuery, "", true, ScopeGlobal}, - {TiDBStmtSummaryRefreshInterval, "a", true, ScopeSession}, - {TiDBStmtSummaryRefreshInterval, "", false, ScopeSession}, - {TiDBStmtSummaryRefreshInterval, "", true, ScopeGlobal}, - {TiDBStmtSummaryRefreshInterval, "0", false, ScopeGlobal}, - {TiDBStmtSummaryRefreshInterval, "99999999999", false, ScopeGlobal}, - {TiDBStmtSummaryHistorySize, "a", true, ScopeSession}, - {TiDBStmtSummaryHistorySize, "", false, ScopeSession}, - {TiDBStmtSummaryHistorySize, "", true, ScopeGlobal}, - {TiDBStmtSummaryHistorySize, "0", false, ScopeGlobal}, - {TiDBStmtSummaryHistorySize, "-1", false, ScopeGlobal}, - {TiDBStmtSummaryHistorySize, "99999999", false, ScopeGlobal}, - {TiDBStmtSummaryMaxStmtCount, "a", true, ScopeSession}, - {TiDBStmtSummaryMaxStmtCount, "", false, ScopeSession}, - {TiDBStmtSummaryMaxStmtCount, "", true, ScopeGlobal}, - {TiDBStmtSummaryMaxStmtCount, "0", false, ScopeGlobal}, - {TiDBStmtSummaryMaxStmtCount, "99999999", false, ScopeGlobal}, - {TiDBStmtSummaryMaxSQLLength, "a", true, ScopeSession}, - {TiDBStmtSummaryMaxSQLLength, "", false, ScopeSession}, - {TiDBStmtSummaryMaxSQLLength, "", true, ScopeGlobal}, - {TiDBStmtSummaryMaxSQLLength, "0", false, ScopeGlobal}, - {TiDBStmtSummaryMaxSQLLength, "-1", false, ScopeGlobal}, - {TiDBStmtSummaryMaxSQLLength, "99999999999", false, ScopeGlobal}, + {TiDBEnableStmtSummary, "", true}, + {TiDBStmtSummaryInternalQuery, "", true}, + {TiDBStmtSummaryRefreshInterval, "", true}, + {TiDBStmtSummaryRefreshInterval, "0", false}, + {TiDBStmtSummaryRefreshInterval, "99999999999", false}, + {TiDBStmtSummaryHistorySize, "", true}, + {TiDBStmtSummaryHistorySize, "0", false}, + {TiDBStmtSummaryHistorySize, "-1", false}, + {TiDBStmtSummaryHistorySize, "99999999", false}, + {TiDBStmtSummaryMaxStmtCount, "", true}, + {TiDBStmtSummaryMaxStmtCount, "0", false}, + {TiDBStmtSummaryMaxStmtCount, "99999999", false}, + {TiDBStmtSummaryMaxSQLLength, "", true}, + {TiDBStmtSummaryMaxSQLLength, "0", false}, + {TiDBStmtSummaryMaxSQLLength, "-1", false}, + {TiDBStmtSummaryMaxSQLLength, "99999999999", false}, } for _, tc := range testCases { // copy iterator variable into a new variable, see issue #27779 tc := tc t.Run(tc.key, func(t *testing.T) { - _, err := GetSysVar(tc.key).Validate(v, tc.value, tc.scope) + _, err := GetSysVar(tc.key).Validate(v, tc.value, ScopeGlobal) if tc.error { require.Errorf(t, err, "%v got err=%v", tc, err) } else { @@ -742,9 +669,9 @@ func TestHelperFuncs(t *testing.T) { require.Equal(t, 5, tidbOptPositiveInt32("-1234", 5)) require.Equal(t, 5, tidbOptPositiveInt32("bogus", 5)) - require.Equal(t, 1234, tidbOptInt("1234", 5)) - require.Equal(t, -1234, tidbOptInt("-1234", 5)) - require.Equal(t, 5, tidbOptInt("bogus", 5)) + require.Equal(t, 1234, TidbOptInt("1234", 5)) + require.Equal(t, -1234, TidbOptInt("-1234", 5)) + require.Equal(t, 5, TidbOptInt("bogus", 5)) } func TestStmtVars(t *testing.T) { diff --git a/sessiontxn/failpoint.go b/sessiontxn/failpoint.go new file mode 100644 index 0000000000000..1d0a832de1083 --- /dev/null +++ b/sessiontxn/failpoint.go @@ -0,0 +1,74 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sessiontxn + +import ( + "fmt" + + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/util/stringutil" +) + +// AssertRecordsKey is used to save failPoint invoke records +// Only for test +var AssertRecordsKey stringutil.StringerStr = "assertTxnManagerRecords" + +// AssertTxnInfoSchemaKey is used to set the expected infoschema that should be check in failPoint +// Only for test +var AssertTxnInfoSchemaKey stringutil.StringerStr = "assertTxnInfoSchemaKey" + +// AssertTxnInfoSchemaAfterRetryKey is used to set the expected infoschema that should be check in failPoint after retry +// Only for test +var AssertTxnInfoSchemaAfterRetryKey stringutil.StringerStr = "assertTxnInfoSchemaAfterRetryKey" + +// RecordAssert is used only for test +func RecordAssert(sctx sessionctx.Context, name string, value interface{}) { + records, ok := sctx.Value(AssertRecordsKey).(map[string]interface{}) + if !ok { + records = make(map[string]interface{}) + sctx.SetValue(AssertRecordsKey, records) + } + records[name] = value +} + +// AssertTxnManagerInfoSchema is used only for test +func AssertTxnManagerInfoSchema(sctx sessionctx.Context, is interface{}) { + assertVersion := func(expected interface{}) { + if expected == nil { + return + } + + expectVer := expected.(infoschema.InfoSchema).SchemaMetaVersion() + gotVer := GetTxnManager(sctx).GetTxnInfoSchema().SchemaMetaVersion() + if gotVer != expectVer { + panic(fmt.Sprintf("Txn schema version not match, expect:%d, got:%d", expectVer, gotVer)) + } + } + + if localTables := sctx.GetSessionVars().LocalTemporaryTables; localTables != nil { + got, ok := GetTxnManager(sctx).GetTxnInfoSchema().(*infoschema.TemporaryTableAttachedInfoSchema) + if !ok { + panic("Expected to be a TemporaryTableAttachedInfoSchema") + } + + if got.LocalTemporaryTables != localTables { + panic("Local tables should be the same with the one in session") + } + } + + assertVersion(is) + assertVersion(sctx.Value(AssertTxnInfoSchemaKey)) +} diff --git a/sessiontxn/interface.go b/sessiontxn/interface.go new file mode 100644 index 0000000000000..fc7357ad10d55 --- /dev/null +++ b/sessiontxn/interface.go @@ -0,0 +1,59 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sessiontxn + +import ( + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/sessionctx" +) + +// TxnContextProvider provides txn context +type TxnContextProvider interface { + // Initialize the provider with session context + Initialize(sctx sessionctx.Context) error + // GetTxnInfoSchema returns the information schema used by txn + GetTxnInfoSchema() infoschema.InfoSchema +} + +// SimpleTxnContextProvider implements TxnContextProvider +// It is only used in refactor stage +// TODO: remove it after refactor finished +type SimpleTxnContextProvider struct { + InfoSchema infoschema.InfoSchema +} + +// Initialize the provider with session context +func (p *SimpleTxnContextProvider) Initialize(_ sessionctx.Context) error { + return nil +} + +// GetTxnInfoSchema returns the information schema used by txn +func (p *SimpleTxnContextProvider) GetTxnInfoSchema() infoschema.InfoSchema { + return p.InfoSchema +} + +// TxnManager is an interface providing txn context management in session +type TxnManager interface { + // GetTxnInfoSchema returns the information schema used by txn + GetTxnInfoSchema() infoschema.InfoSchema + + // GetContextProvider returns the current TxnContextProvider + GetContextProvider() TxnContextProvider + // SetContextProvider sets the context provider + SetContextProvider(provider TxnContextProvider) error +} + +// GetTxnManager returns the TxnManager object from session context +var GetTxnManager func(sctx sessionctx.Context) TxnManager diff --git a/sessiontxn/staleread/errors.go b/sessiontxn/staleread/errors.go new file mode 100644 index 0000000000000..1d89fa632ccd6 --- /dev/null +++ b/sessiontxn/staleread/errors.go @@ -0,0 +1,24 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package staleread + +import ( + mysql "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/util/dbterror" +) + +var ( + errAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrAsOf) +) diff --git a/sessiontxn/staleread/processor.go b/sessiontxn/staleread/processor.go new file mode 100644 index 0000000000000..17fe266364b67 --- /dev/null +++ b/sessiontxn/staleread/processor.go @@ -0,0 +1,268 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package staleread + +import ( + "context" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/table/temptable" +) + +// enforce implement Processor interface +var _ Processor = &staleReadProcessor{} + +// StalenessTSEvaluator is a function to get staleness ts +type StalenessTSEvaluator func(sctx sessionctx.Context) (uint64, error) + +// Processor is an interface used to process stale read +type Processor interface { + // IsStaleness indicates that whether we should use the staleness + IsStaleness() bool + // GetStalenessInfoSchema returns the information schema if it is stale read, otherwise returns nil + GetStalenessInfoSchema() infoschema.InfoSchema + // GetStalenessReadTS returns the ts if it is stale read, otherwise returns 0 + GetStalenessReadTS() uint64 + // GetStalenessTSEvaluatorForPrepare returns a function that will be used by prepare to evaluate ts + GetStalenessTSEvaluatorForPrepare() StalenessTSEvaluator + + // OnSelectTable will be called when process table in select statement + OnSelectTable(tn *ast.TableName) error + // OnExecutePreparedStmt when process execute + OnExecutePreparedStmt(preparedTSEvaluator StalenessTSEvaluator) error +} + +type baseProcessor struct { + sctx sessionctx.Context + txnManager sessiontxn.TxnManager + + evaluated bool + ts uint64 + tsEvaluator StalenessTSEvaluator + is infoschema.InfoSchema +} + +func (p *baseProcessor) init(sctx sessionctx.Context) { + p.sctx = sctx + p.txnManager = sessiontxn.GetTxnManager(sctx) +} + +func (p *baseProcessor) IsStaleness() bool { + return p.ts != 0 +} + +func (p *baseProcessor) GetStalenessInfoSchema() infoschema.InfoSchema { + return p.is +} + +func (p *baseProcessor) GetStalenessReadTS() uint64 { + return p.ts +} + +func (p *baseProcessor) GetStalenessTSEvaluatorForPrepare() StalenessTSEvaluator { + return p.tsEvaluator +} + +func (p *baseProcessor) OnSelectTable(_ *ast.TableName) error { + return errors.New("not supported") +} + +func (p *baseProcessor) OnExecutePrepared(_ StalenessTSEvaluator) error { + return errors.New("not supported") +} + +func (p *baseProcessor) setAsNonStaleRead() error { + return p.setEvaluatedValues(0, nil, nil) +} + +func (p *baseProcessor) setEvaluatedTS(ts uint64) (err error) { + is, err := domain.GetDomain(p.sctx).GetSnapshotInfoSchema(ts) + if err != nil { + return err + } + is = temptable.AttachLocalTemporaryTableInfoSchema(p.sctx, is) + return p.setEvaluatedValues(ts, is, func(sctx sessionctx.Context) (uint64, error) { + return ts, nil + }) +} + +func (p *baseProcessor) setEvaluatedEvaluator(evaluator StalenessTSEvaluator) error { + ts, err := evaluator(p.sctx) + if err != nil { + return err + } + + is, err := domain.GetDomain(p.sctx).GetSnapshotInfoSchema(ts) + is = temptable.AttachLocalTemporaryTableInfoSchema(p.sctx, is) + if err != nil { + return err + } + + return p.setEvaluatedValues(ts, is, evaluator) +} + +func (p *baseProcessor) setEvaluatedValues(ts uint64, is infoschema.InfoSchema, tsEvaluator StalenessTSEvaluator) error { + if p.evaluated { + return errors.New("already evaluated") + } + + p.ts = ts + p.is = is + p.evaluated = true + p.tsEvaluator = tsEvaluator + return nil +} + +type staleReadProcessor struct { + baseProcessor + stmtTS uint64 +} + +// NewStaleReadProcessor creates a new stale read processor +func NewStaleReadProcessor(sctx sessionctx.Context) Processor { + p := &staleReadProcessor{} + p.init(sctx) + return p +} + +// OnSelectTable will be called when process table in select statement +func (p *staleReadProcessor) OnSelectTable(tn *ast.TableName) error { + if p.sctx.GetSessionVars().InTxn() { + if tn.AsOf != nil { + return errAsOf.FastGenWithCause("as of timestamp can't be set in transaction.") + } + + if !p.evaluated { + return p.evaluateFromTxn() + } + return nil + } + + // If `stmtAsOfTS` is not 0, it means we use 'select ... from xxx as of timestamp ...' + stmtAsOfTS, err := parseAndValidateAsOf(p.sctx, tn.AsOf) + if err != nil { + return err + } + + if p.evaluated { + // If the select statement is related to multi tables, we should guarantee that all tables use the same timestamp + if p.stmtTS != stmtAsOfTS { + return errAsOf.GenWithStack("can not set different time in the as of") + } + return nil + } + return p.evaluateFromStmtTSOrSysVariable(stmtAsOfTS) +} + +func (p *staleReadProcessor) OnExecutePreparedStmt(preparedTSEvaluator StalenessTSEvaluator) (err error) { + if p.evaluated { + return errors.New("already evaluated") + } + + if p.sctx.GetSessionVars().InTxn() { + if preparedTSEvaluator != nil { + return errAsOf.FastGenWithCause("as of timestamp can't be set in transaction.") + } + return p.evaluateFromTxn() + } + + var stmtTS uint64 + if preparedTSEvaluator != nil { + // If the `preparedTSEvaluator` is not nil, it means the prepared statement is stale read + if stmtTS, err = preparedTSEvaluator(p.sctx); err != nil { + return err + } + } + return p.evaluateFromStmtTSOrSysVariable(stmtTS) +} + +func (p *staleReadProcessor) evaluateFromTxn() error { + // sys variables should be ignored when in an explicit transaction + if txnCtx := p.sctx.GetSessionVars().TxnCtx; txnCtx.IsStaleness { + // It means we meet following case: + // 1. `start transaction read only as of timestamp ts + // 2. select or execute statement + return p.setEvaluatedValues( + txnCtx.StartTS, + temptable.AttachLocalTemporaryTableInfoSchema(p.sctx, txnCtx.InfoSchema.(infoschema.InfoSchema)), + nil, + ) + } + return p.setAsNonStaleRead() +} + +func (p *staleReadProcessor) evaluateFromStmtTSOrSysVariable(stmtTS uint64) error { + // If `txnReadTS` is not 0, it means we meet following situation: + // set transaction read only as of timestamp ... + // select from table or execute prepared statement + txnReadTS := p.sctx.GetSessionVars().TxnReadTS.UseTxnReadTS() + if txnReadTS > 0 && stmtTS > 0 { + // `as of` and `@@tx_read_ts` cannot be set in the same time + return errAsOf.FastGenWithCause("can't use select as of while already set transaction as of") + } + + if stmtTS > 0 { + p.stmtTS = stmtTS + return p.setEvaluatedTS(stmtTS) + } + + if txnReadTS > 0 { + return p.setEvaluatedTS(txnReadTS) + } + + if evaluator := getTsEvaluatorFromReadStaleness(p.sctx); evaluator != nil { + // If both txnReadTS and stmtAsOfTS is empty while the return of getTsEvaluatorFromReadStaleness is not nil, it means we meet following situation: + // set @@tidb_read_staleness='-5'; + // select from table + // Then the following select statement should be affected by the tidb_read_staleness in session. + return p.setEvaluatedEvaluator(evaluator) + } + + // Otherwise, it means we should not use stale read. + return p.setAsNonStaleRead() +} + +func parseAndValidateAsOf(sctx sessionctx.Context, asOf *ast.AsOfClause) (uint64, error) { + if asOf == nil { + return 0, nil + } + + ts, err := CalculateAsOfTsExpr(sctx, asOf) + if err != nil { + return 0, err + } + + if err = sessionctx.ValidateStaleReadTS(context.TODO(), sctx, ts); err != nil { + return 0, err + } + + return ts, nil +} + +func getTsEvaluatorFromReadStaleness(sctx sessionctx.Context) StalenessTSEvaluator { + readStaleness := sctx.GetSessionVars().ReadStaleness + if readStaleness == 0 { + return nil + } + + return func(sctx sessionctx.Context) (uint64, error) { + return CalculateTsWithReadStaleness(sctx, readStaleness) + } +} diff --git a/sessiontxn/staleread/processor_test.go b/sessiontxn/staleread/processor_test.go new file mode 100644 index 0000000000000..44fca02cd70a8 --- /dev/null +++ b/sessiontxn/staleread/processor_test.go @@ -0,0 +1,354 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package staleread_test + +import ( + "fmt" + "testing" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/parser" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessiontxn/staleread" + "github.com/pingcap/tidb/table/temptable" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/testbridge" + "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + testbridge.SetupForCommonTest() + goleak.VerifyTestMain(m, opts...) +} + +type staleReadPoint struct { + tk *testkit.TestKit + ts uint64 + dt string + tm time.Time + is infoschema.InfoSchema + tn *ast.TableName +} + +func (p *staleReadPoint) checkMatchProcessor(t *testing.T, processor staleread.Processor, hasEvaluator bool) { + require.True(t, processor.IsStaleness()) + require.Equal(t, p.ts, processor.GetStalenessReadTS()) + require.Equal(t, p.is.SchemaMetaVersion(), processor.GetStalenessInfoSchema().SchemaMetaVersion()) + require.IsTypef(t, processor.GetStalenessInfoSchema(), temptable.AttachLocalTemporaryTableInfoSchema(p.tk.Session(), p.is), "") + evaluator := processor.GetStalenessTSEvaluatorForPrepare() + if hasEvaluator { + require.NotNil(t, evaluator) + ts, err := evaluator(p.tk.Session()) + require.NoError(t, err) + require.Equal(t, processor.GetStalenessReadTS(), ts) + } else { + require.Nil(t, evaluator) + } +} + +func genStaleReadPoint(t *testing.T, tk *testkit.TestKit) *staleReadPoint { + tk.MustExec("create table if not exists test.t(a bigint)") + tk.MustExec(fmt.Sprintf("alter table test.t alter column a set default %d", time.Now().UnixNano())) + time.Sleep(time.Millisecond * 20) + is := domain.GetDomain(tk.Session()).InfoSchema() + dt := tk.MustQuery("select now(3)").Rows()[0][0].(string) + tm, err := time.ParseInLocation("2006-01-02 15:04:05.999999", dt, tk.Session().GetSessionVars().Location()) + require.NoError(t, err) + ts := oracle.GoTimeToTS(tm) + tn := astTableWithAsOf(t, dt) + return &staleReadPoint{ + tk: tk, + ts: ts, + dt: dt, + tm: tm, + is: is, + tn: tn, + } +} + +func astTableWithAsOf(t *testing.T, dt string) *ast.TableName { + p := parser.New() + var sql string + if dt == "" { + sql = "select * from test.t" + } else { + sql = fmt.Sprintf("select * from test.t as of timestamp '%s'", dt) + } + + stmt, err := p.ParseOneStmt(sql, "", "") + require.NoError(t, err) + sel := stmt.(*ast.SelectStmt) + return sel.From.TableRefs.Left.(*ast.TableSource).Source.(*ast.TableName) +} + +func TestStaleReadProcessorWithSelectTable(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tn := astTableWithAsOf(t, "") + p1 := genStaleReadPoint(t, tk) + p2 := genStaleReadPoint(t, tk) + + // create local temporary table to check processor's infoschema will consider temporary table + tk.MustExec("create temporary table test.t2(a int)") + + // no sys variable just select ... as of ... + processor := createProcessor(t, tk.Session()) + err := processor.OnSelectTable(p1.tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + err = processor.OnSelectTable(p1.tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + err = processor.OnSelectTable(p2.tn) + require.Error(t, err) + require.Equal(t, "[planner:8135]can not set different time in the as of", err.Error()) + p1.checkMatchProcessor(t, processor, true) + + // the first select has not 'as of' + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + require.False(t, processor.IsStaleness()) + err = processor.OnSelectTable(p1.tn) + require.Equal(t, "[planner:8135]can not set different time in the as of", err.Error()) + require.False(t, processor.IsStaleness()) + + // 'as of' is not allowed when @@txn_read_ts is set + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(p1.tn) + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: can't use select as of while already set transaction as of", err.Error()) + tk.MustExec("set @@tx_read_ts=''") + + // no 'as of' will consume @txn_read_ts + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + p1.checkMatchProcessor(t, processor, true) + tk.Session().GetSessionVars().CleanupTxnReadTSIfUsed() + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) + tk.MustExec("set @@tx_read_ts=''") + + // `@@tidb_read_staleness` + tk.MustExec("set @@tidb_read_staleness=-5") + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + require.True(t, processor.IsStaleness()) + require.Equal(t, int64(0), processor.GetStalenessInfoSchema().SchemaMetaVersion()) + expectedTS, err := staleread.CalculateTsWithReadStaleness(tk.Session(), -5*time.Second) + require.NoError(t, err) + require.Equal(t, expectedTS, processor.GetStalenessReadTS()) + evaluator := processor.GetStalenessTSEvaluatorForPrepare() + evaluatorTS, err := evaluator(tk.Session()) + require.NoError(t, err) + require.Equal(t, expectedTS, evaluatorTS) + tk.MustExec("set @@tidb_read_staleness=''") + + tk.MustExec("do sleep(0.01)") + evaluatorTS, err = evaluator(tk.Session()) + require.NoError(t, err) + expectedTS2, err := staleread.CalculateTsWithReadStaleness(tk.Session(), -5*time.Second) + require.NoError(t, err) + require.Equal(t, expectedTS2, evaluatorTS) + + // `@@tidb_read_staleness` will be ignored when `as of` or `@@tx_read_ts` + tk.MustExec("set @@tidb_read_staleness=-5") + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(p1.tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + tk.MustExec("set @@tidb_read_staleness=''") +} + +func TestStaleReadProcessorWithExecutePreparedStmt(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + p1 := genStaleReadPoint(t, tk) + //p2 := genStaleReadPoint(t, tk) + + // create local temporary table to check processor's infoschema will consider temporary table + tk.MustExec("create temporary table test.t2(a int)") + + // execute prepared stmt with ts evaluator + processor := createProcessor(t, tk.Session()) + err := processor.OnExecutePreparedStmt(func(sctx sessionctx.Context) (uint64, error) { + return p1.ts, nil + }) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + + // will get an error when ts evaluator fails + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(func(sctx sessionctx.Context) (uint64, error) { + return 0, errors.New("mock error") + }) + require.Error(t, err) + require.Equal(t, "mock error", err.Error()) + require.False(t, processor.IsStaleness()) + + // execute prepared stmt without stale read + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.NoError(t, err) + require.False(t, processor.IsStaleness()) + + // execute prepared stmt without ts evaluator will consume tx_read_ts + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + p1.checkMatchProcessor(t, processor, true) + tk.Session().GetSessionVars().CleanupTxnReadTSIfUsed() + require.Equal(t, uint64(0), tk.Session().GetSessionVars().TxnReadTS.PeakTxnReadTS()) + tk.MustExec("set @@tx_read_ts=''") + + // prepared ts is not allowed when @@txn_read_ts is set + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(func(sctx sessionctx.Context) (uint64, error) { + return p1.ts, nil + }) + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: can't use select as of while already set transaction as of", err.Error()) + tk.MustExec("set @@tx_read_ts=''") + + // `@@tidb_read_staleness` + tk.MustExec("set @@tidb_read_staleness=-5") + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.True(t, processor.IsStaleness()) + require.Equal(t, int64(0), processor.GetStalenessInfoSchema().SchemaMetaVersion()) + expectedTS, err := staleread.CalculateTsWithReadStaleness(tk.Session(), -5*time.Second) + require.NoError(t, err) + require.Equal(t, expectedTS, processor.GetStalenessReadTS()) + tk.MustExec("set @@tidb_read_staleness=''") + + // `@@tidb_read_staleness` will be ignored when `as of` or `@@tx_read_ts` + tk.MustExec("set @@tidb_read_staleness=-5") + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(func(sctx sessionctx.Context) (uint64, error) { + return p1.ts, nil + }) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + + tk.MustExec(fmt.Sprintf("SET TRANSACTION READ ONLY AS OF TIMESTAMP '%s'", p1.dt)) + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, true) + tk.MustExec("set @@tidb_read_staleness=''") +} + +func TestStaleReadProcessorInTxn(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tn := astTableWithAsOf(t, "") + p1 := genStaleReadPoint(t, tk) + _ = genStaleReadPoint(t, tk) + + tk.MustExec("begin") + + // no error when there is no 'as of' + processor := createProcessor(t, tk.Session()) + err := processor.OnSelectTable(tn) + require.NoError(t, err) + require.False(t, processor.IsStaleness()) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + require.False(t, processor.IsStaleness()) + + // no error when execute prepared stmt without ts evaluator + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.NoError(t, err) + require.False(t, processor.IsStaleness()) + + // return an error when 'as of' is set + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(p1.tn) + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: as of timestamp can't be set in transaction.", err.Error()) + + // return an error when execute prepared stmt with ts evaluator + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(func(sctx sessionctx.Context) (uint64, error) { + return p1.ts, nil + }) + require.Error(t, err) + require.Equal(t, "[planner:8135]invalid as of timestamp: as of timestamp can't be set in transaction.", err.Error()) + + tk.MustExec("rollback") + + tk.MustExec(fmt.Sprintf("start transaction read only as of timestamp '%s'", p1.dt)) + + // processor will use the transaction's stale read context + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + + // sys variables will be ignored in txn + tk.MustExec("set @@tidb_read_staleness=-5") + processor = createProcessor(t, tk.Session()) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + err = processor.OnSelectTable(tn) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + + processor = createProcessor(t, tk.Session()) + err = processor.OnExecutePreparedStmt(nil) + require.NoError(t, err) + p1.checkMatchProcessor(t, processor, false) + tk.MustExec("set @@tidb_read_staleness=''") +} + +func createProcessor(t *testing.T, se sessionctx.Context) staleread.Processor { + processor := staleread.NewStaleReadProcessor(se) + require.False(t, processor.IsStaleness()) + require.Equal(t, uint64(0), processor.GetStalenessReadTS()) + require.Nil(t, processor.GetStalenessTSEvaluatorForPrepare()) + require.Nil(t, processor.GetStalenessInfoSchema()) + return processor +} diff --git a/sessiontxn/staleread/util.go b/sessiontxn/staleread/util.go new file mode 100644 index 0000000000000..896b378c0ebd2 --- /dev/null +++ b/sessiontxn/staleread/util.go @@ -0,0 +1,62 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package staleread + +import ( + "time" + + "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/parser/ast" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/types" + "github.com/tikv/client-go/v2/oracle" +) + +// CalculateAsOfTsExpr calculates the TsExpr of AsOfClause to get a StartTS. +func CalculateAsOfTsExpr(sctx sessionctx.Context, asOfClause *ast.AsOfClause) (uint64, error) { + tsVal, err := expression.EvalAstExpr(sctx, asOfClause.TsExpr) + if err != nil { + return 0, err + } + + if tsVal.IsNull() { + return 0, errAsOf.FastGenWithCause("as of timestamp cannot be NULL") + } + + toTypeTimestamp := types.NewFieldType(mysql.TypeTimestamp) + // We need at least the millionsecond here, so set fsp to 3. + toTypeTimestamp.Decimal = 3 + tsTimestamp, err := tsVal.ConvertTo(sctx.GetSessionVars().StmtCtx, toTypeTimestamp) + if err != nil { + return 0, err + } + tsTime, err := tsTimestamp.GetMysqlTime().GoTime(sctx.GetSessionVars().Location()) + if err != nil { + return 0, err + } + return oracle.GoTimeToTS(tsTime), nil +} + +// CalculateTsWithReadStaleness calculates the TsExpr for readStaleness duration +func CalculateTsWithReadStaleness(sctx sessionctx.Context, readStaleness time.Duration) (uint64, error) { + nowVal, err := expression.GetStmtTimestamp(sctx) + if err != nil { + return 0, err + } + tsVal := nowVal.Add(readStaleness) + minTsVal := expression.GetMinSafeTime(sctx) + return oracle.GoTimeToTS(expression.CalAppropriateTime(tsVal, nowVal, minTsVal)), nil +} diff --git a/sessiontxn/txn_context_test.go b/sessiontxn/txn_context_test.go new file mode 100644 index 0000000000000..085166dd3db03 --- /dev/null +++ b/sessiontxn/txn_context_test.go @@ -0,0 +1,697 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sessiontxn_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessiontxn" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/testbridge" + "github.com/stretchr/testify/require" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) +} + +func setupTxnContextTest(t *testing.T) (kv.Storage, *domain.Domain, func()) { + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertTxnManagerInCompile", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertTxnManagerInRebuildPlan", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertTxnManagerAfterBuildExecutor", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertTxnManagerAfterPessimisticLockErrorRetry", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertTxnManagerInShortPointGetPlan", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTxnManagerInRunStmt", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTxnManagerInPreparedStmtExec", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/session/assertTxnManagerInCachedPlanExec", "return")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan", "return")) + + store, do, clean := testkit.CreateMockStoreAndDomain(t) + + tk := testkit.NewTestKit(t, store) + tk.Session().SetValue(sessiontxn.AssertRecordsKey, nil) + tk.Session().SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1,t2") + + tk.MustExec("create table t1 (id int primary key, v int)") + tk.MustExec("insert into t1 values(1, 10)") + + tk.MustExec("create table t2 (id int)") + + tk.MustExec("create temporary table tmp (id int)") + tk.MustExec("insert into tmp values(10)") + + return store, do, func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertTxnManagerInCompile")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertTxnManagerInRebuildPlan")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertTxnManagerAfterBuildExecutor")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertTxnManagerAfterPessimisticLockErrorRetry")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertTxnManagerInShortPointGetPlan")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/assertStaleReadValuesSameWithExecuteAndBuilder")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTxnManagerInRunStmt")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTxnManagerInPreparedStmtExec")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/session/assertTxnManagerInCachedPlanExec")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/core/assertStaleReadForOptimizePreparedPlan")) + + tk.Session().SetValue(sessiontxn.AssertRecordsKey, nil) + tk.Session().SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.Session().SetValue(sessiontxn.AssertTxnInfoSchemaAfterRetryKey, nil) + clean() + } +} + +func checkAssertRecordExits(t *testing.T, se sessionctx.Context, name string) { + records, ok := se.Value(sessiontxn.AssertRecordsKey).(map[string]interface{}) + require.True(t, ok, fmt.Sprintf("'%s' not in record, maybe failpoint not enabled?", name)) + _, ok = records[name] + require.True(t, ok, fmt.Sprintf("'%s' not in record", name)) +} + +func doWithCheckPath(t *testing.T, se sessionctx.Context, names []string, do func()) { + se.SetValue(sessiontxn.AssertRecordsKey, nil) + do() + for _, name := range names { + checkAssertRecordExits(t, se, name) + } +} + +var normalPathRecords = []string{ + "assertTxnManagerInCompile", + "assertTxnManagerInRunStmt", + "assertTxnManagerAfterBuildExecutor", +} + +func TestTxnContextForSimpleCases(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + is1 := do.InfoSchema() + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(3)") + }) + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) + + tk2.MustExec("alter table t2 add column(c1 int)") + is2 := do.InfoSchema() + require.True(t, is2.SchemaMetaVersion() > is1.SchemaMetaVersion()) + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is2) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) +} + +func TestTxnContextInExplicitTxn(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + is1 := do.InfoSchema() + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + + tk.MustExec("begin") + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(2)") + }) + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) + + // info schema changed when txn not finish, the info schema in old txn should not change + tk2.MustExec("alter table t2 add column(c1 int)") + is2 := do.InfoSchema() + require.True(t, is2.SchemaMetaVersion() > is1.SchemaMetaVersion()) + + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(2)") + }) + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("commit") + }) + + // the info schema in new txn should use the newest one + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is2) + tk.MustExec("begin") + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(2)") + }) + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) +} + +func TestTxnContextBeginInUnfinishedTxn(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + is1 := do.InfoSchema() + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + tk.MustExec("begin") + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + tk2.MustExec("alter table t2 add column(c1 int)") + is2 := do.InfoSchema() + require.True(t, is2.SchemaMetaVersion() > is1.SchemaMetaVersion()) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + tk.MustExec("begin") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is2) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + tk.MustExec("rollback") +} + +func TestTxnContextWithAutocommitFalse(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + is1 := do.InfoSchema() + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + tk.MustExec("begin") + + tk.MustExec("set autocommit=0") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(2)") + }) + + // schema change should not affect because it is in txn + tk2.MustExec("alter table t2 add column(c1 int)") + + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) + tk.MustExec("rollback") +} + +func TestTxnContextInRC(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + is1 := do.InfoSchema() + tk.MustExec("set tx_isolation = 'READ-COMMITTED'") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + tk.MustExec("begin pessimistic") + + // schema change should not affect even in rc isolation + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk2.MustExec("alter table t2 add column(c1 int)") + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + // test for write + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("insert into t2 (id) values(2)") + }) + + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + tk2.MustExec("update t1 set v=11 where id=1") + + // test for select + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 11")) + }) + + // test for select for update + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 11")) + }) + + tk.MustExec("rollback") +} + +func TestTxnContextInPessimisticKeyConflict(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + is1 := do.InfoSchema() + + tk.MustExec("begin pessimistic") + + // trigger retry + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("update t1 set v=11 where id=1") + tk2.MustExec("alter table t2 add column(c1 int)") + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + path := append([]string{"assertTxnManagerAfterPessimisticLockErrorRetry"}, normalPathRecords...) + doWithCheckPath(t, se, path, func() { + tk.MustExec("update t1 set v=12 where id=1") + }) + + tk.MustExec("rollback") +} + +func TestTxnContextInOptimisticRetry(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_disable_txn_auto_retry=0") + se := tk.Session() + is1 := do.InfoSchema() + + tk.MustExec("begin optimistic") + + // trigger retry + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("update t1 set v=11 where id=1") + tk2.MustExec("alter table t2 add column(c1 int)") + + tk.MustExec("update t1 set v=12 where id=1") + + // check retry context + path := append([]string{"assertTxnManagerInRebuildPlan"}, normalPathRecords...) + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + se.SetValue(sessiontxn.AssertTxnInfoSchemaAfterRetryKey, do.InfoSchema()) + doWithCheckPath(t, se, path, func() { + tk.MustExec("commit") + }) + + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 12")) +} + +func TestTxnContextForHistoricalRead(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + safePoint := "20160102-15:04:05 -0700" + tk.MustExec(fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%s', '') ON DUPLICATE KEY UPDATE variable_value = '%s', comment=''`, safePoint, safePoint)) + + is1 := do.InfoSchema() + tk.MustExec("set @a=now(6)") + // change schema + tk.MustExec("alter table t2 add column(c1 int)") + tk.MustExec("update t1 set v=11 where id=1") + + tk.MustExec("set @@tidb_snapshot=@a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 10")) + }) + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tidb_snapshot=''") + tk.MustExec("begin") + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 11")) + }) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 11")) + }) + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tidb_snapshot=@a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 11")) + }) + + tk.MustExec("rollback") +} + +func TestTxnContextForStaleRead(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + safePoint := "20160102-15:04:05 -0700" + tk.MustExec(fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%s', '') ON DUPLICATE KEY UPDATE variable_value = '%s', comment=''`, safePoint, safePoint)) + + is1 := do.InfoSchema() + tk.MustExec("set @a=now(6)") + time.Sleep(time.Millisecond * 1200) + + // change schema + tk.MustExec("alter table t2 add column(c1 int)") + tk.MustExec("update t1 set v=11 where id=1") + + // @@tidb_read_staleness + tk.MustExec("set @@tidb_read_staleness=-1") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 as of timestamp @a").Check(testkit.Rows("1 10")) + }) + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tidb_read_staleness=''") + + // select ... as of ... + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 as of timestamp @a").Check(testkit.Rows("1 10")) + }) + + // @@tx_read_ts + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tx_read_ts=@a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 11")) + }) + + // txn begin with @tx_read_ts + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tx_read_ts=@a") + tk.MustExec("begin") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + tk.MustExec("rollback") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 11")) + }) + + // txn begin ... as of ... + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("start transaction read only as of timestamp @a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 10")) + }) + tk.MustExec("rollback") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1").Check(testkit.Rows("1 11")) + }) +} + +func TestTxnContextForPrepareExecute(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + stmtID, _, _, err := se.PrepareStmt("select * from t1 where id=1") + require.NoError(t, err) + + is1 := do.InfoSchema() + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + + // Test prepare/execute in SQL + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("prepare s from 'select * from t1 where id=1'") + }) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("execute s").Check(testkit.Rows("1 10")) + }) + + // Test ExecutePreparedStmt + path := append([]string{"assertTxnManagerInPreparedStmtExec"}, normalPathRecords...) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + + // Test PlanCache + path = []string{"assertTxnManagerInCachedPlanExec", "assertTxnManagerInShortPointGetPlan"} + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + + // In txn + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("begin") + + //change schema + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("alter table t2 add column(c1 int)") + tk2.MustExec("update t1 set v=11 where id=1") + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("prepare s from 'select * from t1 where id=1'") + }) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("execute s").Check(testkit.Rows("1 10")) + }) + path = append([]string{"assertTxnManagerInPreparedStmtExec"}, normalPathRecords...) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + + tk.MustExec("rollback") +} + +func TestTxnContextForStaleReadInPrepare(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + is1 := do.InfoSchema() + tk.MustExec("set @a=now(6)") + tk.MustExec("prepare s1 from 'select * from t1 where id=1'") + tk.MustExec("prepare s2 from 'select * from t1 as of timestamp @a where id=1 '") + + stmtID1, _, _, err := se.PrepareStmt("select * from t1 where id=1") + require.NoError(t, err) + + stmtID2, _, _, err := se.PrepareStmt("select * from t1 as of timestamp @a where id=1 ") + require.NoError(t, err) + + //change schema + tk.MustExec("use test") + tk.MustExec("alter table t2 add column(c1 int)") + tk.MustExec("update t1 set v=11 where id=1") + + tk.MustExec("set @@tx_read_ts=@a") + stmtID3, _, _, err := se.PrepareStmt("select * from t1 where id=1 ") + require.NoError(t, err) + tk.MustExec("set @@tx_read_ts=''") + + tk.MustExec("set @@tx_read_ts=@a") + tk.MustExec("prepare s3 from 'select * from t1 where id=1 '") + tk.MustExec("set @@tx_read_ts=''") + + // tx_read_ts + tk.MustExec("set @@tx_read_ts=@a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + path := append([]string{"assertTxnManagerInPreparedStmtExec"}, normalPathRecords...) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID1, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tx_read_ts=''") + + tk.MustExec("set @@tx_read_ts=@a") + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("execute s1") + }) + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("set @@tx_read_ts=''") + + // select ... as of ... + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID2, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("execute s2") + }) + + // tx_read_ts in prepare + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID3, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 10")) + }) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustExec("execute s3") + }) +} + +func TestTxnContextPreparedStmtWithForUpdate(t *testing.T) { + store, do, deferFunc := setupTxnContextTest(t) + defer deferFunc() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + se := tk.Session() + + is1 := do.InfoSchema() + + stmtID1, _, _, err := se.PrepareStmt("select * from t1 where id=1 for update") + require.NoError(t, err) + tk.MustExec("prepare s from 'select * from t1 where id=1 for update'") + tk.MustExec("begin pessimistic") + + //change schema + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.MustExec("alter table t1 add column(c int default 100)") + tk2.MustExec("update t1 set v=11 where id=1") + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, is1) + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("select * from t1 where id=1 for update").Check(testkit.Rows("1 11")) + }) + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, do.InfoSchema()) + path := append([]string{"assertTxnManagerInPreparedStmtExec"}, normalPathRecords...) + doWithCheckPath(t, se, path, func() { + rs, err := se.ExecutePreparedStmt(context.TODO(), stmtID1, nil) + require.NoError(t, err) + tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 11 100")) + }) + + doWithCheckPath(t, se, normalPathRecords, func() { + tk.MustQuery("execute s").Check(testkit.Rows("1 11 100")) + }) + + se.SetValue(sessiontxn.AssertTxnInfoSchemaKey, nil) + tk.MustExec("rollback") +} diff --git a/statistics/analyze_jobs.go b/statistics/analyze_jobs.go index 07b9bd8769fce..34ae95be58a3c 100644 --- a/statistics/analyze_jobs.go +++ b/statistics/analyze_jobs.go @@ -15,128 +15,77 @@ package statistics import ( - "sort" "sync" "time" ) -type analyzeJobs struct { - sync.Mutex - jobs map[*AnalyzeJob]struct{} - history []*AnalyzeJob -} - -var analyzeStatus = analyzeJobs{jobs: make(map[*AnalyzeJob]struct{}), history: make([]*AnalyzeJob, 0, numMaxHistoryJobs)} - // AnalyzeJob is used to represent the status of one analyze job. type AnalyzeJob struct { - sync.Mutex + ID *uint64 DBName string TableName string PartitionName string JobInfo string - RowCount int64 StartTime time.Time EndTime time.Time - State string - updateTime time.Time -} - -const ( - pending = "pending" - running = "running" - finished = "finished" - failed = "failed" -) - -// AddNewAnalyzeJob adds new analyze job. -func AddNewAnalyzeJob(job *AnalyzeJob) { - analyzeStatus.Lock() - job.updateTime = time.Now() - job.State = pending - analyzeStatus.jobs[job] = struct{}{} - analyzeStatus.Unlock() -} - -const numMaxHistoryJobs = 20 - -// MoveToHistory moves the analyze job to history. -func MoveToHistory(job *AnalyzeJob) { - analyzeStatus.Lock() - delete(analyzeStatus.jobs, job) - analyzeStatus.history = append(analyzeStatus.history, job) - numJobs := len(analyzeStatus.history) - if numJobs > numMaxHistoryJobs { - analyzeStatus.history = analyzeStatus.history[numJobs-numMaxHistoryJobs:] - } - analyzeStatus.Unlock() + Progress AnalyzeProgress } -// ClearHistoryJobs clears all history jobs. -func ClearHistoryJobs() { - analyzeStatus.Lock() - analyzeStatus.history = analyzeStatus.history[:0] - analyzeStatus.Unlock() -} - -// GetAllAnalyzeJobs gets all analyze jobs. -func GetAllAnalyzeJobs() []*AnalyzeJob { - analyzeStatus.Lock() - jobs := make([]*AnalyzeJob, 0, len(analyzeStatus.jobs)+len(analyzeStatus.history)) - for job := range analyzeStatus.jobs { - jobs = append(jobs, job) - } - jobs = append(jobs, analyzeStatus.history...) - analyzeStatus.Unlock() - sort.Slice(jobs, func(i int, j int) bool { return jobs[i].getUpdateTime().Before(jobs[j].getUpdateTime()) }) - return jobs +// AnalyzeProgress represents the process of one analyze job. +type AnalyzeProgress struct { + sync.Mutex + // deltaCount is the newly processed rows after the last time mysql.analyze_jobs.processed_rows is updated. + deltaCount int64 + // lastDumpTime is the last time mysql.analyze_jobs.processed_rows is updated. + lastDumpTime time.Time } -// Start marks status of the analyze job as running and update the start time. -func (job *AnalyzeJob) Start() { - if job == nil { +// Update adds rowCount to the delta count. If the updated delta count reaches threshold, it returns the delta count for +// dumping it into mysql.analyze_jobs and resets the delta count to 0. Otherwise it returns 0. +func (p *AnalyzeProgress) Update(rowCount int64) (dumpCount int64) { + p.Lock() + defer p.Unlock() + p.deltaCount += rowCount + t := time.Now() + const maxDelta int64 = 10000000 + const dumpTimeInterval = 5 * time.Second + if p.deltaCount > maxDelta && t.Sub(p.lastDumpTime) > dumpTimeInterval { + dumpCount = p.deltaCount + p.deltaCount = 0 + p.lastDumpTime = t return } - job.Mutex.Lock() - job.State = running - now := time.Now() - job.StartTime = now - job.updateTime = now - job.Mutex.Unlock() + return } -// Update updates the row count of analyze job. -func (job *AnalyzeJob) Update(rowCount int64) { - if job == nil { - return - } - job.Mutex.Lock() - job.RowCount += rowCount - job.updateTime = time.Now() - job.Mutex.Unlock() +// GetDeltaCount returns the delta count which hasn't been dumped into mysql.analyze_jobs. +func (p *AnalyzeProgress) GetDeltaCount() int64 { + p.Lock() + defer p.Unlock() + return p.deltaCount } -// Finish update the status of analyze job to finished or failed according to `meetError`. -func (job *AnalyzeJob) Finish(meetError bool) { - if job == nil { - return - } - job.Mutex.Lock() - if meetError { - job.State = failed - } else { - job.State = finished - } - job.updateTime = time.Now() - job.EndTime = job.updateTime - job.Mutex.Unlock() +// SetLastDumpTime sets the last dump time. +func (p *AnalyzeProgress) SetLastDumpTime(t time.Time) { + p.Lock() + defer p.Unlock() + p.lastDumpTime = t } -func (job *AnalyzeJob) getUpdateTime() time.Time { - if job == nil { - return time.Time{} - } - job.Mutex.Lock() - defer job.Mutex.Unlock() - return job.updateTime +// GetLastDumpTime returns the last dump time. +func (p *AnalyzeProgress) GetLastDumpTime() time.Time { + p.Lock() + defer p.Unlock() + return p.lastDumpTime } + +const ( + // AnalyzePending means the analyze job is pending + AnalyzePending = "pending" + // AnalyzeRunning means the analyze job is running + AnalyzeRunning = "running" + // AnalyzeFinished means the analyze job has finished + AnalyzeFinished = "finished" + // AnalyzeFailed means the analyze job has failed + AnalyzeFailed = "failed" +) diff --git a/statistics/fmsketch.go b/statistics/fmsketch.go index a0e81c354ffe8..055956d03d01a 100644 --- a/statistics/fmsketch.go +++ b/statistics/fmsketch.go @@ -116,17 +116,6 @@ func (s *FMSketch) InsertRowValue(sc *stmtctx.StatementContext, values []types.D return nil } -func buildFMSketch(sc *stmtctx.StatementContext, values []types.Datum, maxSize int) (*FMSketch, int64, error) { - s := NewFMSketch(maxSize) - for _, value := range values { - err := s.InsertValue(sc, value) - if err != nil { - return nil, 0, errors.Trace(err) - } - } - return s, s.NDV(), nil -} - // MergeFMSketch merges two FM Sketch. func (s *FMSketch) MergeFMSketch(rs *FMSketch) { if s == nil || rs == nil { diff --git a/statistics/fmsketch_test.go b/statistics/fmsketch_test.go index 768db16fb913d..3b04b4dad8233 100644 --- a/statistics/fmsketch_test.go +++ b/statistics/fmsketch_test.go @@ -18,6 +18,7 @@ import ( "testing" "time" + "github.com/pingcap/errors" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/stretchr/testify/require" @@ -33,6 +34,17 @@ func extractSampleItemsDatums(items []*SampleItem) []types.Datum { return datums } +func buildFMSketch(sc *stmtctx.StatementContext, values []types.Datum, maxSize int) (*FMSketch, int64, error) { + s := NewFMSketch(maxSize) + for _, value := range values { + err := s.InsertValue(sc, value) + if err != nil { + return nil, 0, errors.Trace(err) + } + } + return s, s.NDV(), nil +} + func SubTestSketch() func(*testing.T) { return func(t *testing.T) { s := createTestStatisticsSamples(t) diff --git a/statistics/handle/bootstrap.go b/statistics/handle/bootstrap.go index bc5cff9a9084f..5449806774f28 100644 --- a/statistics/handle/bootstrap.go +++ b/statistics/handle/bootstrap.go @@ -16,7 +16,7 @@ package handle import ( "context" - "fmt" + "strconv" "github.com/cznic/mathutil" "github.com/pingcap/errors" @@ -428,5 +428,5 @@ func getFullTableName(is infoschema.InfoSchema, tblInfo *model.TableInfo) string } } } - return fmt.Sprintf("%d", tblInfo.ID) + return strconv.FormatInt(tblInfo.ID, 10) } diff --git a/statistics/handle/ddl.go b/statistics/handle/ddl.go index 6fdf102548ee1..653bc00da52a9 100644 --- a/statistics/handle/ddl.go +++ b/statistics/handle/ddl.go @@ -39,7 +39,7 @@ func (h *Handle) HandleDDLEvent(t *util.Event) error { return err } } - case model.ActionAddColumn, model.ActionAddColumns, model.ActionModifyColumn: + case model.ActionAddColumn, model.ActionModifyColumn: ids := h.getInitStateTableIDs(t.TableInfo) for _, id := range ids { if err := h.insertColStats2KV(id, t.ColumnInfos); err != nil { @@ -176,6 +176,12 @@ func (h *Handle) DDLEventCh() chan *util.Event { // insertTableStats2KV inserts a record standing for a new table to stats_meta and inserts some records standing for the // new columns and indices which belong to this table. func (h *Handle) insertTableStats2KV(info *model.TableInfo, physicalID int64) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(physicalID, statsVer) + } + }() h.mu.Lock() defer h.mu.Unlock() ctx := context.Background() @@ -195,6 +201,7 @@ func (h *Handle) insertTableStats2KV(info *model.TableInfo, physicalID int64) (e if _, err := exec.ExecuteInternal(ctx, "insert into mysql.stats_meta (version, table_id) values(%?, %?)", startTS, physicalID); err != nil { return err } + statsVer = startTS for _, col := range info.Columns { if _, err := exec.ExecuteInternal(ctx, "insert into mysql.stats_histograms (table_id, is_index, hist_id, distinct_count, version) values(%?, 0, %?, 0, %?)", physicalID, col.ID, startTS); err != nil { return err @@ -211,6 +218,12 @@ func (h *Handle) insertTableStats2KV(info *model.TableInfo, physicalID int64) (e // insertColStats2KV insert a record to stats_histograms with distinct_count 1 and insert a bucket to stats_buckets with default value. // This operation also updates version. func (h *Handle) insertColStats2KV(physicalID int64, colInfos []*model.ColumnInfo) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(physicalID, statsVer) + } + }() h.mu.Lock() defer h.mu.Unlock() @@ -233,6 +246,7 @@ func (h *Handle) insertColStats2KV(physicalID int64, colInfos []*model.ColumnInf if err != nil { return } + statsVer = startTS // If we didn't update anything by last SQL, it means the stats of this table does not exist. if h.mu.ctx.GetSessionVars().StmtCtx.AffectedRows() > 0 { // By this step we can get the count of this table, then we can sure the count and repeats of bucket. diff --git a/statistics/handle/ddl_test.go b/statistics/handle/ddl_test.go index 91a3a244cb17d..dfad7cbfbf5e8 100644 --- a/statistics/handle/ddl_test.go +++ b/statistics/handle/ddl_test.go @@ -26,8 +26,9 @@ import ( ) func TestDDLAfterLoad(t *testing.T) { - testKit, do, clean := createTestKitAndDom(t) + store, do, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") testKit.MustExec("analyze table t") @@ -59,8 +60,9 @@ func TestDDLAfterLoad(t *testing.T) { } func TestDDLTable(t *testing.T) { - testKit, do, clean := createTestKitAndDom(t) + store, do, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") is := do.InfoSchema() @@ -98,8 +100,9 @@ func TestDDLTable(t *testing.T) { } func TestDDLHistogram(t *testing.T) { - testKit, do, clean := createTestKitAndDom(t) + store, do, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) h := do.StatsHandle() testKit.MustExec("use test") @@ -185,8 +188,9 @@ func TestDDLHistogram(t *testing.T) { } func TestDDLPartition(t *testing.T) { - testKit, do, clean := createTestKitAndDom(t) + store, do, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testkit.WithPruneMode(testKit, variable.Static, func() { testKit.MustExec("use test") testKit.MustExec("drop table if exists t") diff --git a/statistics/handle/dump.go b/statistics/handle/dump.go index 4628c18ac1c3a..5e2ae4fcddd2d 100644 --- a/statistics/handle/dump.go +++ b/statistics/handle/dump.go @@ -15,6 +15,10 @@ package handle import ( + "bytes" + "compress/gzip" + "encoding/json" + "io/ioutil" "time" "github.com/pingcap/errors" @@ -296,10 +300,18 @@ func TableStatsFromJSON(tableInfo *model.TableInfo, physicalID int64, jsonTbl *J } hist := statistics.HistogramFromProto(jsonCol.Histogram) sc := &stmtctx.StatementContext{TimeZone: time.UTC} + // Deal with sortKey, the length of sortKey maybe longer than the column's length. + orgLen := colInfo.FieldType.Flen + if types.IsString(colInfo.FieldType.Tp) { + colInfo.Flen = types.UnspecifiedLength + } hist, err := hist.ConvertTo(sc, &colInfo.FieldType) if err != nil { return nil, errors.Trace(err) } + if types.IsString(colInfo.FieldType.Tp) { + colInfo.Flen = orgLen + } cm, topN := statistics.CMSketchAndTopNFromProto(jsonCol.CMSketch) fms := statistics.FMSketchFromProto(jsonCol.FMSketch) hist.ID, hist.NullCount, hist.LastUpdateVersion, hist.TotColSize, hist.Correlation = colInfo.ID, jsonCol.NullCount, jsonCol.LastUpdateVersion, jsonCol.TotColSize, jsonCol.Correlation @@ -318,6 +330,7 @@ func TableStatsFromJSON(tableInfo *model.TableInfo, physicalID int64, jsonTbl *J Info: colInfo, IsHandle: tableInfo.PKIsHandle && mysql.HasPriKeyFlag(colInfo.Flag), StatsVer: statsVer, + Loaded: true, } col.Count = int64(col.TotalRowCount()) tbl.Columns[col.ID] = col @@ -326,3 +339,58 @@ func TableStatsFromJSON(tableInfo *model.TableInfo, physicalID int64, jsonTbl *J tbl.ExtendedStats = extendedStatsFromJSON(jsonTbl.ExtStats) return tbl, nil } + +// JSONTableToBlocks convert JSONTable to json, then compresses it to blocks by gzip. +func JSONTableToBlocks(jsTable *JSONTable, blockSize int) ([][]byte, error) { + data, err := json.Marshal(jsTable) + if err != nil { + return nil, errors.Trace(err) + } + var gzippedData bytes.Buffer + gzipWriter := gzip.NewWriter(&gzippedData) + if _, err := gzipWriter.Write(data); err != nil { + return nil, errors.Trace(err) + } + if err := gzipWriter.Close(); err != nil { + return nil, errors.Trace(err) + } + blocksNum := gzippedData.Len() / blockSize + if gzippedData.Len()%blockSize != 0 { + blocksNum = blocksNum + 1 + } + blocks := make([][]byte, blocksNum) + for i := 0; i < blocksNum-1; i++ { + blocks[i] = gzippedData.Bytes()[blockSize*i : blockSize*(i+1)] + } + blocks[blocksNum-1] = gzippedData.Bytes()[blockSize*(blocksNum-1):] + return blocks, nil +} + +// BlocksToJSONTable convert gzip-compressed blocks to JSONTable +func BlocksToJSONTable(blocks [][]byte) (*JSONTable, error) { + if len(blocks) == 0 { + return nil, errors.New("Block empty error") + } + data := blocks[0] + for i := 1; i < len(blocks); i++ { + data = append(data, blocks[i]...) + } + gzippedData := bytes.NewReader(data) + gzipReader, err := gzip.NewReader(gzippedData) + if err != nil { + return nil, err + } + if err := gzipReader.Close(); err != nil { + return nil, err + } + jsonStr, err := ioutil.ReadAll(gzipReader) + if err != nil { + return nil, errors.Trace(err) + } + jsonTbl := JSONTable{} + err = json.Unmarshal(jsonStr, &jsonTbl) + if err != nil { + return nil, errors.Trace(err) + } + return &jsonTbl, nil +} diff --git a/statistics/handle/dump_test.go b/statistics/handle/dump_test.go index 01474870b2e4a..d2c67d49dcdbe 100644 --- a/statistics/handle/dump_test.go +++ b/statistics/handle/dump_test.go @@ -17,7 +17,6 @@ package handle_test import ( "encoding/json" "fmt" - "sync" "testing" "github.com/pingcap/tidb/domain" @@ -75,8 +74,9 @@ func cleanStats(tk *testkit.TestKit, do *domain.Domain) { } func TestConversion(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (a int, b int)") @@ -100,12 +100,10 @@ func TestConversion(t *testing.T) { requireTableEqual(t, loadTbl, tbl) cleanStats(tk, dom) - wg := sync.WaitGroup{} - wg.Add(1) - go func() { + var wg util.WaitGroupWrapper + wg.Run(func() { require.Nil(t, h.Update(is)) - wg.Done() - }() + }) err = h.LoadStatsFromJSON(is, jsonTbl) wg.Wait() require.NoError(t, err) @@ -126,8 +124,9 @@ func getStatsJSON(t *testing.T, dom *domain.Domain, db, tableName string) *handl } func TestDumpGlobalStats(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("set @@tidb_partition_prune_mode = 'static'") @@ -152,8 +151,9 @@ func TestDumpGlobalStats(t *testing.T) { } func TestLoadGlobalStats(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") @@ -178,8 +178,9 @@ func TestLoadGlobalStats(t *testing.T) { } func TestDumpPartitions(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") createTable := `CREATE TABLE t (a int, b int, primary key(a), index idx(b)) @@ -223,8 +224,9 @@ PARTITION BY RANGE ( a ) ( } func TestDumpAlteredTable(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") h := dom.StatsHandle() @@ -242,8 +244,9 @@ func TestDumpAlteredTable(t *testing.T) { func TestDumpCMSketchWithTopN(t *testing.T) { // Just test if we can store and recover the Top N elements stored in database. - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t(a int)") testKit.MustExec("insert into t values (1),(3),(4),(2),(5)") @@ -283,8 +286,9 @@ func TestDumpCMSketchWithTopN(t *testing.T) { } func TestDumpPseudoColumns(t *testing.T) { - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t(a int, b int, index idx(a))") // Force adding an pseudo tables in stats cache. @@ -300,8 +304,9 @@ func TestDumpPseudoColumns(t *testing.T) { } func TestDumpExtendedStats(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -335,8 +340,9 @@ func TestDumpExtendedStats(t *testing.T) { } func TestDumpVer2Stats(t *testing.T) { - tk, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -384,3 +390,92 @@ func TestDumpVer2Stats(t *testing.T) { // the statistics.Table in the stats cache is the same as the unmarshalled statistics.Table requireTableEqual(t, statsCacheTbl, loadTbl) } + +func TestLoadStatsForNewCollation(t *testing.T) { + // This test is almost the same as TestDumpVer2Stats, except that: b varchar(10) => b varchar(3) collate utf8mb4_unicode_ci + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(3) collate utf8mb4_unicode_ci)") + tk.MustExec("insert into t value(1, 'aaa'), (3, 'aab'), (5, 'bba'), (2, 'bbb'), (4, 'cca'), (6, 'ccc')") + // mark column stats as needed + tk.MustExec("select * from t where a = 3") + tk.MustExec("select * from t where b = 'bbb'") + tk.MustExec("alter table t add index single(a)") + tk.MustExec("alter table t add index multi(a, b)") + tk.MustExec("analyze table t with 2 topn") + h := dom.StatsHandle() + is := dom.InfoSchema() + tableInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + storageTbl, err := h.TableStatsFromStorage(tableInfo.Meta(), tableInfo.Meta().ID, false, 0) + require.NoError(t, err) + + dumpJSONTable, err := h.DumpStatsToJSON("test", tableInfo.Meta(), nil) + require.NoError(t, err) + + jsonBytes, err := json.MarshalIndent(dumpJSONTable, "", " ") + require.NoError(t, err) + + loadJSONTable := &handle.JSONTable{} + err = json.Unmarshal(jsonBytes, loadJSONTable) + require.NoError(t, err) + + loadTbl, err := handle.TableStatsFromJSON(tableInfo.Meta(), tableInfo.Meta().ID, loadJSONTable) + require.NoError(t, err) + + // assert that a statistics.Table from storage dumped into JSON text and then unmarshalled into a statistics.Table keeps unchanged + requireTableEqual(t, loadTbl, storageTbl) + + // assert that this statistics.Table is the same as the one in stats cache + statsCacheTbl := h.GetTableStats(tableInfo.Meta()) + requireTableEqual(t, loadTbl, statsCacheTbl) + + err = h.LoadStatsFromJSON(is, loadJSONTable) + require.NoError(t, err) + require.Nil(t, h.Update(is)) + statsCacheTbl = h.GetTableStats(tableInfo.Meta()) + // assert that after the JSONTable above loaded into storage then updated into the stats cache, + // the statistics.Table in the stats cache is the same as the unmarshalled statistics.Table + requireTableEqual(t, statsCacheTbl, loadTbl) +} + +func TestJSONTableToBlocks(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10))") + tk.MustExec("insert into t value(1, 'aaa'), (3, 'aab'), (5, 'bba'), (2, 'bbb'), (4, 'cca'), (6, 'ccc')") + // mark column stats as needed + tk.MustExec("select * from t where a = 3") + tk.MustExec("select * from t where b = 'bbb'") + tk.MustExec("alter table t add index single(a)") + tk.MustExec("alter table t add index multi(a, b)") + tk.MustExec("analyze table t with 2 topn") + h := dom.StatsHandle() + is := dom.InfoSchema() + tableInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + + dumpJSONTable, err := h.DumpStatsToJSON("test", tableInfo.Meta(), nil) + require.NoError(t, err) + jsOrigin, _ := json.Marshal(dumpJSONTable) + + blockSize := 30 + js, err := h.DumpStatsToJSON("test", tableInfo.Meta(), nil) + require.NoError(t, err) + dumpJSONBlocks, err := handle.JSONTableToBlocks(js, blockSize) + require.NoError(t, err) + jsConverted, err := handle.BlocksToJSONTable(dumpJSONBlocks) + require.NoError(t, err) + jsonStr, err := json.Marshal(jsConverted) + require.NoError(t, err) + require.JSONEq(t, string(jsOrigin), string(jsonStr)) +} diff --git a/statistics/handle/gc.go b/statistics/handle/gc.go index ff95558a0cf4e..73646339026eb 100644 --- a/statistics/handle/gc.go +++ b/statistics/handle/gc.go @@ -230,6 +230,9 @@ func (h *Handle) DeleteTableStatsFromKV(statsIDs []int64) (err error) { if _, err = exec.ExecuteInternal(ctx, "delete from mysql.column_stats_usage where table_id = %?", statsID); err != nil { return err } + if _, err = exec.ExecuteInternal(ctx, "delete from mysql.analyze_options where table_id = %?", statsID); err != nil { + return err + } } return nil } diff --git a/statistics/handle/gc_test.go b/statistics/handle/gc_test.go index b426613952c4d..ae1a726d2ee38 100644 --- a/statistics/handle/gc_test.go +++ b/statistics/handle/gc_test.go @@ -18,27 +18,15 @@ import ( "testing" "time" - "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" ) -func createTestKitAndDom(t *testing.T) (*testkit.TestKit, *domain.Domain, func()) { - store, dom, err := newStoreWithBootstrap() - require.NoError(t, err) - clean := func() { - dom.Close() - err := store.Close() - require.NoError(t, err) - } - tk := testkit.NewTestKit(t, store) - return tk, dom, clean -} - func TestGCStats(t *testing.T) { - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("set @@tidb_analyze_version = 1") testKit.MustExec("use test") testKit.MustExec("create table t(a int, b int, index idx(a, b), index idx_a(a))") @@ -70,8 +58,9 @@ func TestGCStats(t *testing.T) { } func TestGCPartition(t *testing.T) { - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("set @@tidb_analyze_version = 1") testkit.WithPruneMode(testKit, variable.Static, func() { testKit.MustExec("use test") @@ -108,8 +97,9 @@ func TestGCPartition(t *testing.T) { } func TestGCExtendedStats(t *testing.T) { - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("set session tidb_enable_extended_stats = on") testKit.MustExec("use test") testKit.MustExec("create table t(a int, b int, c int)") @@ -152,8 +142,9 @@ func TestGCExtendedStats(t *testing.T) { } func TestGCColumnStatsUsage(t *testing.T) { - testKit, dom, clean := createTestKitAndDom(t) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t(a int, b int, c int)") testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") @@ -170,3 +161,18 @@ func TestGCColumnStatsUsage(t *testing.T) { require.Nil(t, h.GCStats(dom.InfoSchema(), ddlLease)) testKit.MustQuery("select count(*) from mysql.column_stats_usage").Check(testkit.Rows("0")) } + +func TestDeleteAnalyzeJobs(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + testKit.MustExec("use test") + testKit.MustExec("create table t(a int, b int)") + testKit.MustExec("insert into t values (1,2),(3,4)") + testKit.MustExec("analyze table t") + rows := testKit.MustQuery("show analyze status").Rows() + require.Equal(t, 1, len(rows)) + require.NoError(t, dom.StatsHandle().DeleteAnalyzeJobs(time.Now().Add(time.Second))) + rows = testKit.MustQuery("show analyze status").Rows() + require.Equal(t, 0, len(rows)) +} diff --git a/statistics/handle/handle.go b/statistics/handle/handle.go index 0889d00e431e5..2d4d186936d8c 100644 --- a/statistics/handle/handle.go +++ b/statistics/handle/handle.go @@ -28,7 +28,9 @@ import ( "github.com/ngaut/pools" "github.com/pingcap/errors" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/util" + "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" @@ -73,7 +75,7 @@ type statsCache struct { // Handle can update stats info periodically. type Handle struct { mu struct { - sync.Mutex + sync.RWMutex ctx sessionctx.Context // rateMap contains the error rate delta from feedback. rateMap errorRateDeltaMap @@ -91,6 +93,7 @@ type Handle struct { memTracker *memory.Tracker } + // Deprecated: only used by feedback now pool sessionPool // ddlEventCh is a channel to notify a ddl operation has happened. @@ -108,59 +111,43 @@ type Handle struct { sync.Mutex data *statistics.QueryFeedbackMap } + // colMap contains all the column stats usage information from collectors when we dump them to KV. + colMap struct { + sync.Mutex + data colStatsUsageMap + } lease atomic2.Duration // idxUsageListHead contains all the index usage collectors required by session. idxUsageListHead *SessionIndexUsageCollector -} -func (h *Handle) withRestrictedSQLExecutor(ctx context.Context, fn func(context.Context, sqlexec.RestrictedSQLExecutor) ([]chunk.Row, []*ast.ResultField, error)) ([]chunk.Row, []*ast.ResultField, error) { - se, err := h.pool.Get() - if err != nil { - return nil, nil, errors.Trace(err) - } - defer h.pool.Put(se) + // StatsLoad is used to load stats concurrently + StatsLoad StatsLoad - exec := se.(sqlexec.RestrictedSQLExecutor) - return fn(ctx, exec) + // sysProcTracker is used to track sys process like analyze + sysProcTracker sessionctx.SysProcTracker } func (h *Handle) execRestrictedSQL(ctx context.Context, sql string, params ...interface{}) ([]chunk.Row, []*ast.ResultField, error) { - return h.withRestrictedSQLExecutor(ctx, func(ctx context.Context, exec sqlexec.RestrictedSQLExecutor) ([]chunk.Row, []*ast.ResultField, error) { - stmt, err := exec.ParseWithParams(ctx, sql, params...) - if err != nil { - return nil, nil, errors.Trace(err) - } - return exec.ExecRestrictedStmt(ctx, stmt) - }) + return h.mu.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseSessionPool}, sql, params...) } -func (h *Handle) execRestrictedSQLWithStatsVer(ctx context.Context, statsVer int, sql string, params ...interface{}) ([]chunk.Row, []*ast.ResultField, error) { - return h.withRestrictedSQLExecutor(ctx, func(ctx context.Context, exec sqlexec.RestrictedSQLExecutor) ([]chunk.Row, []*ast.ResultField, error) { - stmt, err := exec.ParseWithParams(ctx, sql, params...) - // TODO: An ugly way to set @@tidb_partition_prune_mode. Need to be improved. - if _, ok := stmt.(*ast.AnalyzeTableStmt); ok { - pruneMode := h.CurrentPruneMode() - if session, ok := exec.(sessionctx.Context); ok { - session.GetSessionVars().PartitionPruneMode.Store(string(pruneMode)) - } - } - if err != nil { - return nil, nil, errors.Trace(err) - } - return exec.ExecRestrictedStmt(ctx, stmt, execOptionForAnalyze[statsVer]) - }) +func (h *Handle) execRestrictedSQLWithStatsVer(ctx context.Context, statsVer int, procTrackID uint64, sql string, params ...interface{}) ([]chunk.Row, []*ast.ResultField, error) { + optFuncs := []sqlexec.OptionFuncAlias{ + sqlexec.ExecOptionUseSessionPool, + execOptionForAnalyze[statsVer], + sqlexec.ExecOptionWithSysProcTrack(procTrackID, h.sysProcTracker.Track, h.sysProcTracker.UnTrack), + } + return h.mu.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, optFuncs, sql, params...) } func (h *Handle) execRestrictedSQLWithSnapshot(ctx context.Context, sql string, snapshot uint64, params ...interface{}) ([]chunk.Row, []*ast.ResultField, error) { - return h.withRestrictedSQLExecutor(ctx, func(ctx context.Context, exec sqlexec.RestrictedSQLExecutor) ([]chunk.Row, []*ast.ResultField, error) { - stmt, err := exec.ParseWithParams(ctx, sql, params...) - if err != nil { - return nil, nil, errors.Trace(err) - } - return exec.ExecRestrictedStmt(ctx, stmt, sqlexec.ExecOptionWithSnapshot(snapshot)) - }) + optFuncs := []sqlexec.OptionFuncAlias{ + sqlexec.ExecOptionUseSessionPool, + sqlexec.ExecOptionWithSnapshot(snapshot), + } + return h.mu.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, optFuncs, sql, params...) } // Clear the statsCache, only for test. @@ -185,6 +172,9 @@ func (h *Handle) Clear() { h.globalMap.Lock() h.globalMap.data = make(tableDeltaMap) h.globalMap.Unlock() + h.colMap.Lock() + h.colMap.data = make(colStatsUsageMap) + h.colMap.Unlock() h.mu.rateMap = make(errorRateDeltaMap) h.mu.Unlock() } @@ -195,12 +185,14 @@ type sessionPool interface { } // NewHandle creates a Handle for update stats. -func NewHandle(ctx sessionctx.Context, lease time.Duration, pool sessionPool) (*Handle, error) { +func NewHandle(ctx sessionctx.Context, lease time.Duration, pool sessionPool, tracker sessionctx.SysProcTracker) (*Handle, error) { + cfg := config.GetGlobalConfig() handle := &Handle{ ddlEventCh: make(chan *util.Event, 100), listHead: &SessionStatsCollector{mapper: make(tableDeltaMap), rateMap: make(errorRateDeltaMap)}, idxUsageListHead: &SessionIndexUsageCollector{mapper: make(indexUsageMap)}, pool: pool, + sysProcTracker: tracker, } handle.lease.Store(lease) handle.statsCache.memTracker = memory.NewTracker(memory.LabelForStatsCache, -1) @@ -209,6 +201,11 @@ func NewHandle(ctx sessionctx.Context, lease time.Duration, pool sessionPool) (* handle.statsCache.Store(statsCache{tables: make(map[int64]*statistics.Table)}) handle.globalMap.data = make(tableDeltaMap) handle.feedback.data = statistics.NewQueryFeedbackMap() + handle.colMap.data = make(colStatsUsageMap) + handle.StatsLoad.SubCtxs = make([]sessionctx.Context, cfg.Performance.StatsLoadConcurrency) + handle.StatsLoad.NeededColumnsCh = make(chan *NeededColumnTask, cfg.Performance.StatsLoadQueueSize) + handle.StatsLoad.TimeoutColumnsCh = make(chan *NeededColumnTask, cfg.Performance.StatsLoadQueueSize) + handle.StatsLoad.WorkingColMap = map[model.TableColumnID][]chan model.TableColumnID{} err := handle.RefreshVars() if err != nil { return nil, err @@ -598,13 +595,13 @@ func (sc statsCache) update(tables []*statistics.Table, deletedIDs []int64, newV // LoadNeededHistograms will load histograms for those needed columns. func (h *Handle) LoadNeededHistograms() (err error) { cols := statistics.HistogramNeededColumns.AllCols() - reader, err := h.getStatsReader(0) + reader, err := h.getGlobalStatsReader(0) if err != nil { return err } defer func() { - err1 := h.releaseStatsReader(reader) + err1 := h.releaseGlobalStatsReader(reader) if err1 != nil && err == nil { err = err1 } @@ -617,7 +614,7 @@ func (h *Handle) LoadNeededHistograms() (err error) { continue } c, ok := tbl.Columns[col.ColumnID] - if !ok || c.Len() > 0 { + if !ok || c.IsLoaded() { statistics.HistogramNeededColumns.Delete(col) continue } @@ -649,6 +646,7 @@ func (h *Handle) LoadNeededHistograms() (err error) { FMSketch: fms, IsHandle: c.IsHandle, StatsVer: rows[0].GetInt64(0), + Loaded: true, } // Column.Count is calculated by Column.TotalRowCount(). Hence we don't set Column.Count when initializing colHist. colHist.Count = int64(colHist.TotalRowCount()) @@ -795,7 +793,7 @@ func (h *Handle) columnStatsFromStorage(reader *statsReader, row chunk.Row, tabl // 4. loadAll is false. notNeedLoad := h.Lease() > 0 && !isHandle && - (col == nil || col.Len() == 0 && col.LastUpdateVersion < histVer) && + (col == nil || !col.IsLoaded() && col.LastUpdateVersion < histVer) && !loadAll if notNeedLoad { count, err := h.columnCountFromStorage(reader, table.PhysicalID, histID, statsVer) @@ -837,6 +835,7 @@ func (h *Handle) columnStatsFromStorage(reader *statsReader, row chunk.Row, tabl IsHandle: tableInfo.PKIsHandle && mysql.HasPriKeyFlag(colInfo.Flag), Flag: flag, StatsVer: statsVer, + Loaded: true, } // Column.Count is calculated by Column.TotalRowCount(). Hence we don't set Column.Count when initializing col. col.Count = int64(col.TotalRowCount()) @@ -863,12 +862,12 @@ func (h *Handle) columnStatsFromStorage(reader *statsReader, row chunk.Row, tabl // TableStatsFromStorage loads table stats info from storage. func (h *Handle) TableStatsFromStorage(tableInfo *model.TableInfo, physicalID int64, loadAll bool, snapshot uint64) (_ *statistics.Table, err error) { - reader, err := h.getStatsReader(snapshot) + reader, err := h.getGlobalStatsReader(snapshot) if err != nil { return nil, err } defer func() { - err1 := h.releaseStatsReader(reader) + err1 := h.releaseGlobalStatsReader(reader) if err == nil && err1 != nil { err = err1 } @@ -968,12 +967,12 @@ func (h *Handle) extendedStatsFromStorage(reader *statsReader, table *statistics // StatsMetaCountAndModifyCount reads count and modify_count for the given table from mysql.stats_meta. func (h *Handle) StatsMetaCountAndModifyCount(tableID int64) (int64, int64, error) { - reader, err := h.getStatsReader(0) + reader, err := h.getGlobalStatsReader(0) if err != nil { return 0, 0, err } defer func() { - err1 := h.releaseStatsReader(reader) + err1 := h.releaseGlobalStatsReader(reader) if err1 != nil && err == nil { err = err1 } @@ -993,6 +992,12 @@ func (h *Handle) StatsMetaCountAndModifyCount(tableID int64) (int64, int64, erro // SaveTableStatsToStorage saves the stats of a table to storage. func (h *Handle) SaveTableStatsToStorage(results *statistics.AnalyzeResults, needDumpFMS bool) (err error) { tableID := results.TableID.GetStatisticsID() + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() h.mu.Lock() defer h.mu.Unlock() ctx := context.TODO() @@ -1035,6 +1040,7 @@ func (h *Handle) SaveTableStatsToStorage(results *statistics.AnalyzeResults, nee if _, err = exec.ExecuteInternal(ctx, "replace into mysql.stats_meta (version, table_id, count, snapshot) values (%?, %?, %?, %?)", version, tableID, results.Count, results.Snapshot); err != nil { return err } + statsVer = version } else { modifyCnt := curModifyCnt - results.BaseModifyCnt if modifyCnt < 0 { @@ -1047,6 +1053,7 @@ func (h *Handle) SaveTableStatsToStorage(results *statistics.AnalyzeResults, nee if _, err = exec.ExecuteInternal(ctx, "update mysql.stats_meta set version=%?, modify_count=%?, count=%?, snapshot=%? where table_id=%?", version, modifyCnt, cnt, results.Snapshot, tableID); err != nil { return err } + statsVer = version } // 2. Save histograms. for _, result := range results.Ars { @@ -1123,7 +1130,7 @@ func (h *Handle) SaveTableStatsToStorage(results *statistics.AnalyzeResults, nee } } if result.IsIndex == 0 { - if _, err = exec.ExecuteInternal(ctx, "insert into mysql.column_stats_usage (table_id, column_id, last_analyzed_at) values(%?, %?, current_timestamp()) on duplicate key update last_analyzed_at = current_timestamp()", tableID, hg.ID); err != nil { + if _, err = exec.ExecuteInternal(ctx, "insert into mysql.column_stats_usage (table_id, column_id, last_analyzed_at) values(%?, %?, current_timestamp()) on duplicate key update last_analyzed_at = values(last_analyzed_at)", tableID, hg.ID); err != nil { return err } } @@ -1158,6 +1165,12 @@ func (h *Handle) SaveTableStatsToStorage(results *statistics.AnalyzeResults, nee // SaveStatsToStorage saves the stats to storage. // TODO: refactor to reduce the number of parameters func (h *Handle) SaveStatsToStorage(tableID int64, count int64, isIndex int, hg *statistics.Histogram, cms *statistics.CMSketch, topN *statistics.TopN, fms *statistics.FMSketch, statsVersion int, isAnalyzed int64, needDumpFMS bool, updateAnalyzeTime bool) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() h.mu.Lock() defer h.mu.Unlock() ctx := context.TODO() @@ -1184,6 +1197,7 @@ func (h *Handle) SaveStatsToStorage(tableID int64, count int64, isIndex int, hg if err != nil { return err } + statsVer = version cmSketch, err := statistics.EncodeCMSketchWithoutTopN(cms) if err != nil { return err @@ -1261,6 +1275,12 @@ func (h *Handle) SaveStatsToStorage(tableID int64, count int64, isIndex int, hg // SaveMetaToStorage will save stats_meta to storage. func (h *Handle) SaveMetaToStorage(tableID, count, modifyCount int64) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() h.mu.Lock() defer h.mu.Unlock() ctx := context.TODO() @@ -1278,6 +1298,7 @@ func (h *Handle) SaveMetaToStorage(tableID, count, modifyCount int64) (err error } version := txn.StartTS() _, err = exec.ExecuteInternal(ctx, "replace into mysql.stats_meta (version, table_id, count, modify_count) values (%?, %?, %?, %?)", version, tableID, count, modifyCount) + statsVer = version return err } @@ -1385,52 +1406,61 @@ type statsReader struct { func (sr *statsReader) read(sql string, args ...interface{}) (rows []chunk.Row, fields []*ast.ResultField, err error) { ctx := context.TODO() - stmt, err := sr.ctx.ParseWithParams(ctx, sql, args...) - if err != nil { - return nil, nil, errors.Trace(err) - } if sr.snapshot > 0 { - return sr.ctx.ExecRestrictedStmt(ctx, stmt, sqlexec.ExecOptionWithSnapshot(sr.snapshot)) + return sr.ctx.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseSessionPool, sqlexec.ExecOptionWithSnapshot(sr.snapshot)}, sql, args...) } - return sr.ctx.ExecRestrictedStmt(ctx, stmt) + return sr.ctx.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseCurSession}, sql, args...) } func (sr *statsReader) isHistory() bool { return sr.snapshot > 0 } -func (h *Handle) getStatsReader(snapshot uint64) (reader *statsReader, err error) { +func (h *Handle) getGlobalStatsReader(snapshot uint64) (reader *statsReader, err error) { + h.mu.Lock() + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("getGlobalStatsReader panic %v", r) + } + if err != nil { + h.mu.Unlock() + } + }() + return h.getStatsReader(snapshot, h.mu.ctx.(sqlexec.RestrictedSQLExecutor)) +} + +func (h *Handle) releaseGlobalStatsReader(reader *statsReader) error { + defer h.mu.Unlock() + return h.releaseStatsReader(reader, h.mu.ctx.(sqlexec.RestrictedSQLExecutor)) +} + +func (h *Handle) getStatsReader(snapshot uint64, ctx sqlexec.RestrictedSQLExecutor) (reader *statsReader, err error) { failpoint.Inject("mockGetStatsReaderFail", func(val failpoint.Value) { if val.(bool) { failpoint.Return(nil, errors.New("gofail genStatsReader error")) } }) if snapshot > 0 { - return &statsReader{ctx: h.mu.ctx.(sqlexec.RestrictedSQLExecutor), snapshot: snapshot}, nil + return &statsReader{ctx: ctx, snapshot: snapshot}, nil } - h.mu.Lock() defer func() { if r := recover(); r != nil { err = fmt.Errorf("getStatsReader panic %v", r) } - if err != nil { - h.mu.Unlock() - } }() failpoint.Inject("mockGetStatsReaderPanic", nil) - _, err = h.mu.ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "begin") + _, err = ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "begin") if err != nil { return nil, err } - return &statsReader{ctx: h.mu.ctx.(sqlexec.RestrictedSQLExecutor)}, nil + return &statsReader{ctx: ctx}, nil } -func (h *Handle) releaseStatsReader(reader *statsReader) error { +func (h *Handle) releaseStatsReader(reader *statsReader, ctx sqlexec.RestrictedSQLExecutor) error { if reader.snapshot > 0 { return nil } - _, err := h.mu.ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "commit") - h.mu.Unlock() + _, err := ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), "commit") return err } @@ -1445,6 +1475,12 @@ const ( // InsertExtendedStats inserts a record into mysql.stats_extended and update version in mysql.stats_meta. func (h *Handle) InsertExtendedStats(statsName string, colIDs []int64, tp int, tableID int64, ifNotExists bool) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() sort.Slice(colIDs, func(i, j int) bool { return colIDs[i] < colIDs[j] }) bytes, err := json.Marshal(colIDs) if err != nil { @@ -1490,6 +1526,7 @@ func (h *Handle) InsertExtendedStats(statsName string, colIDs []int64, tp int, t if _, err = exec.ExecuteInternal(ctx, "UPDATE mysql.stats_meta SET version = %? WHERE table_id = %?", version, tableID); err != nil { return err } + statsVer = version // Remove the existing 'deleted' records. if _, err = exec.ExecuteInternal(ctx, "DELETE FROM mysql.stats_extended WHERE name = %? and table_id = %?", statsName, tableID); err != nil { return err @@ -1509,6 +1546,12 @@ func (h *Handle) InsertExtendedStats(statsName string, colIDs []int64, tp int, t // MarkExtendedStatsDeleted update the status of mysql.stats_extended to be `deleted` and the version of mysql.stats_meta. func (h *Handle) MarkExtendedStatsDeleted(statsName string, tableID int64, ifExists bool) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() ctx := context.Background() rows, _, err := h.execRestrictedSQL(ctx, "SELECT name FROM mysql.stats_extended WHERE name = %? and table_id = %? and status in (%?, %?)", statsName, tableID, StatsStatusInited, StatsStatusAnalyzed) if err != nil { @@ -1546,6 +1589,7 @@ func (h *Handle) MarkExtendedStatsDeleted(statsName string, tableID int64, ifExi if _, err = exec.ExecuteInternal(ctx, "UPDATE mysql.stats_meta SET version = %? WHERE table_id = %?", version, tableID); err != nil { return err } + statsVer = version if _, err = exec.ExecuteInternal(ctx, "UPDATE mysql.stats_extended SET version = %?, status = %? WHERE name = %? and table_id = %?", version, StatsStatusDeleted, statsName, tableID); err != nil { return err } @@ -1576,12 +1620,12 @@ func (h *Handle) removeExtendedStatsItem(tableID int64, statsName string) { // ReloadExtendedStatistics drops the cache for extended statistics and reload data from mysql.stats_extended. func (h *Handle) ReloadExtendedStatistics() error { - reader, err := h.getStatsReader(0) + reader, err := h.getGlobalStatsReader(0) if err != nil { return err } defer func() { - err1 := h.releaseStatsReader(reader) + err1 := h.releaseGlobalStatsReader(reader) if err1 != nil && err == nil { err = err1 } @@ -1715,6 +1759,12 @@ func (h *Handle) fillExtStatsCorrVals(item *statistics.ExtendedStatsItem, cols [ // SaveExtendedStatsToStorage writes extended stats of a table into mysql.stats_extended. func (h *Handle) SaveExtendedStatsToStorage(tableID int64, extStats *statistics.ExtendedStatsColl, isLoad bool) (err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(tableID, statsVer) + } + }() if extStats == nil || len(extStats.Stats) == 0 { return nil } @@ -1756,14 +1806,13 @@ func (h *Handle) SaveExtendedStatsToStorage(tableID int64, extStats *statistics. if _, err := exec.ExecuteInternal(ctx, "UPDATE mysql.stats_meta SET version = %? WHERE table_id = %?", version, tableID); err != nil { return err } + statsVer = version } return nil } // CurrentPruneMode indicates whether tbl support runtime prune for table and first partition id. func (h *Handle) CurrentPruneMode() variable.PartitionPruneMode { - h.mu.Lock() - defer h.mu.Unlock() return variable.PartitionPruneMode(h.mu.ctx.GetSessionVars().PartitionPruneMode.Load()) } @@ -1790,30 +1839,69 @@ func (h *Handle) CheckAnalyzeVersion(tblInfo *model.TableInfo, physicalIDs []int return statistics.CheckAnalyzeVerOnTable(tbl, version) } -type colStatsUsage struct { +type colStatsTimeInfo struct { LastUsedAt *types.Time LastAnalyzedAt *types.Time } +// getDisableColumnTrackingTime reads the value of tidb_disable_column_tracking_time from mysql.tidb if it exists. +func (h *Handle) getDisableColumnTrackingTime() (*time.Time, error) { + rows, fields, err := h.execRestrictedSQL(context.Background(), "SELECT variable_value FROM %n.%n WHERE variable_name = %?", mysql.SystemDB, mysql.TiDBTable, variable.TiDBDisableColumnTrackingTime) + if err != nil { + return nil, err + } + if len(rows) == 0 { + return nil, nil + } + d := rows[0].GetDatum(0, &fields[0].Column.FieldType) + // The string represents the UTC time when tidb_enable_column_tracking is set to 0. + value, err := d.ToString() + if err != nil { + return nil, err + } + t, err := time.Parse(types.UTCTimeFormat, value) + if err != nil { + return nil, err + } + return &t, nil +} + // LoadColumnStatsUsage loads column stats usage information from disk. -func (h *Handle) LoadColumnStatsUsage() (map[model.TableColumnID]colStatsUsage, error) { - rows, _, err := h.execRestrictedSQL(context.Background(), "SELECT table_id, column_id, last_used_at, last_analyzed_at FROM mysql.column_stats_usage") +func (h *Handle) LoadColumnStatsUsage(loc *time.Location) (map[model.TableColumnID]colStatsTimeInfo, error) { + disableTime, err := h.getDisableColumnTrackingTime() if err != nil { return nil, errors.Trace(err) } - colStatsMap := make(map[model.TableColumnID]colStatsUsage, len(rows)) + // Since we use another session from session pool to read mysql.column_stats_usage, which may have different @@time_zone, so we do time zone conversion here. + rows, _, err := h.execRestrictedSQL(context.Background(), "SELECT table_id, column_id, CONVERT_TZ(last_used_at, @@TIME_ZONE, '+00:00'), CONVERT_TZ(last_analyzed_at, @@TIME_ZONE, '+00:00') FROM mysql.column_stats_usage") + if err != nil { + return nil, errors.Trace(err) + } + colStatsMap := make(map[model.TableColumnID]colStatsTimeInfo, len(rows)) for _, row := range rows { if row.IsNull(0) || row.IsNull(1) { continue } tblColID := model.TableColumnID{TableID: row.GetInt64(0), ColumnID: row.GetInt64(1)} - var statsUsage colStatsUsage + var statsUsage colStatsTimeInfo if !row.IsNull(2) { - t := row.GetTime(2) - statsUsage.LastUsedAt = &t + gt, err := row.GetTime(2).GoTime(time.UTC) + if err != nil { + return nil, errors.Trace(err) + } + // If `last_used_at` is before the time when `set global enable_column_tracking = 0`, we should ignore it because + // `set global enable_column_tracking = 0` indicates all the predicate columns collected before. + if disableTime == nil || gt.After(*disableTime) { + t := types.NewTime(types.FromGoTime(gt.In(loc)), mysql.TypeTimestamp, types.DefaultFsp) + statsUsage.LastUsedAt = &t + } } if !row.IsNull(3) { - t := row.GetTime(3) + gt, err := row.GetTime(3).GoTime(time.UTC) + if err != nil { + return nil, errors.Trace(err) + } + t := types.NewTime(types.FromGoTime(gt.In(loc)), mysql.TypeTimestamp, types.DefaultFsp) statsUsage.LastAnalyzedAt = &t } colStatsMap[tblColID] = statsUsage @@ -1845,3 +1933,157 @@ func (h *Handle) CollectColumnsInExtendedStats(tableID int64) ([]int64, error) { } return columnIDs, nil } + +// GetPredicateColumns returns IDs of predicate columns, which are the columns whose stats are used(needed) when generating query plans. +func (h *Handle) GetPredicateColumns(tableID int64) ([]int64, error) { + disableTime, err := h.getDisableColumnTrackingTime() + if err != nil { + return nil, errors.Trace(err) + } + rows, _, err := h.execRestrictedSQL(context.Background(), "SELECT column_id, CONVERT_TZ(last_used_at, @@TIME_ZONE, '+00:00') FROM mysql.column_stats_usage WHERE table_id = %? AND last_used_at IS NOT NULL", tableID) + if err != nil { + return nil, errors.Trace(err) + } + columnIDs := make([]int64, 0, len(rows)) + for _, row := range rows { + if row.IsNull(0) || row.IsNull(1) { + continue + } + colID := row.GetInt64(0) + gt, err := row.GetTime(1).GoTime(time.UTC) + if err != nil { + return nil, errors.Trace(err) + } + // If `last_used_at` is before the time when `set global enable_column_tracking = 0`, we don't regard the column as predicate column because + // `set global enable_column_tracking = 0` indicates all the predicate columns collected before. + if disableTime == nil || gt.After(*disableTime) { + columnIDs = append(columnIDs, colID) + } + } + return columnIDs, nil +} + +// Max column size is 6MB. Refer https://docs.pingcap.com/tidb/dev/tidb-limitations/#limitation-on-a-single-column +const maxColumnSize = 6 << 20 + +// RecordHistoricalStatsToStorage records the given table's stats data to mysql.stats_history +func (h *Handle) RecordHistoricalStatsToStorage(dbName string, tableInfo *model.TableInfo) (uint64, error) { + ctx := context.Background() + js, err := h.DumpStatsToJSON(dbName, tableInfo, nil) + if err != nil { + return 0, errors.Trace(err) + } + version := uint64(0) + for _, value := range js.Columns { + version = uint64(*value.StatsVer) + if version != 0 { + break + } + } + blocks, err := JSONTableToBlocks(js, maxColumnSize) + if err != nil { + return version, errors.Trace(err) + } + h.mu.Lock() + defer h.mu.Unlock() + exec := h.mu.ctx.(sqlexec.SQLExecutor) + _, err = exec.ExecuteInternal(ctx, "begin pessimistic") + if err != nil { + return version, errors.Trace(err) + } + defer func() { + err = finishTransaction(ctx, exec, err) + }() + ts := time.Now().Format("2006-01-02 15:04:05.999999") + + const sql = "INSERT INTO mysql.stats_history(table_id, stats_data, seq_no, version, create_time) VALUES (%?, %?, %?, %?, %?)" + for i := 0; i < len(blocks); i++ { + if _, err := exec.ExecuteInternal(ctx, sql, tableInfo.ID, blocks[i], i, version, ts); err != nil { + return version, errors.Trace(err) + } + } + return version, nil +} + +// CheckHistoricalStatsEnable is used to check whether TiDBEnableHistoricalStats is enabled. +func (h *Handle) CheckHistoricalStatsEnable() (enable bool, err error) { + h.mu.Lock() + defer h.mu.Unlock() + val, err := h.mu.ctx.GetSessionVars().GlobalVarsAccessor.GetGlobalSysVar(variable.TiDBEnableHistoricalStats) + if err != nil { + return false, errors.Trace(err) + } + return variable.TiDBOptOn(val), nil +} + +func (h *Handle) recordHistoricalStatsMeta(tableID int64, version uint64) error { + if tableID == 0 || version == 0 { + return errors.Errorf("tableID %d, version %d are invalid", tableID, version) + } + historicalStatsEnabled, err := h.CheckHistoricalStatsEnable() + if err != nil { + return errors.Errorf("check tidb_enable_historical_stats failed: %v", err) + } + if !historicalStatsEnabled { + return nil + } + + ctx := context.Background() + h.mu.Lock() + defer h.mu.Unlock() + rows, _, err := h.execRestrictedSQL(ctx, "select modify_count, count from mysql.stats_meta where table_id = %? and version = %?", tableID, version) + if err != nil { + return errors.Trace(err) + } + if len(rows) == 0 { + return errors.New("no historical meta stats can be recorded") + } + modifyCount, count := rows[0].GetInt64(0), rows[0].GetInt64(1) + + exec := h.mu.ctx.(sqlexec.SQLExecutor) + _, err = exec.ExecuteInternal(ctx, "begin pessimistic") + if err != nil { + return errors.Trace(err) + } + defer func() { + err = finishTransaction(ctx, exec, err) + }() + + const sql = "REPLACE INTO mysql.stats_meta_history(table_id, modify_count, count, version, create_time) VALUES (%?, %?, %?, %?, NOW())" + if _, err := exec.ExecuteInternal(ctx, sql, tableID, modifyCount, count, version); err != nil { + return errors.Trace(err) + } + return nil +} + +// InsertAnalyzeJob inserts analyze job into mysql.analyze_jobs and gets job ID for further updating job. +func (h *Handle) InsertAnalyzeJob(job *statistics.AnalyzeJob, procID uint64) error { + serverInfo, err := infosync.GetServerInfo() + if err != nil { + return err + } + address := fmt.Sprintf("%s:%d", serverInfo.IP, serverInfo.Port) + h.mu.Lock() + defer h.mu.Unlock() + exec := h.mu.ctx.(sqlexec.RestrictedSQLExecutor) + ctx := context.TODO() + const insertJob = "INSERT INTO mysql.analyze_jobs (table_schema, table_name, partition_name, job_info, state, instance, process_id) VALUES (%?, %?, %?, %?, %?, %?, %?)" + _, _, err = exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseCurSession}, insertJob, job.DBName, job.TableName, job.PartitionName, job.JobInfo, statistics.AnalyzePending, address, procID) + if err != nil { + return err + } + const getJobID = "SELECT LAST_INSERT_ID()" + rows, _, err := exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseCurSession}, getJobID) + if err != nil { + return err + } + job.ID = new(uint64) + *job.ID = rows[0].GetUint64(0) + return nil +} + +// DeleteAnalyzeJobs deletes the analyze jobs whose update time is earlier than updateTime. +func (h *Handle) DeleteAnalyzeJobs(updateTime time.Time) error { + _, _, err := h.execRestrictedSQL(context.TODO(), "DELETE FROM mysql.analyze_jobs WHERE update_time < CONVERT_TZ(%?, '+00:00', @@TIME_ZONE)", updateTime.UTC().Format(types.TimeFormat)) + return err +} diff --git a/statistics/handle/handle_hist.go b/statistics/handle/handle_hist.go new file mode 100644 index 0000000000000..53ae365f8ce8b --- /dev/null +++ b/statistics/handle/handle_hist.go @@ -0,0 +1,415 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handle + +import ( + "runtime" + "sync" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/metrics" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/statistics" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/sqlexec" + "go.uber.org/zap" +) + +// StatsLoad is used to load stats concurrently +type StatsLoad struct { + sync.Mutex + SubCtxs []sessionctx.Context + NeededColumnsCh chan *NeededColumnTask + TimeoutColumnsCh chan *NeededColumnTask + WorkingColMap map[model.TableColumnID][]chan model.TableColumnID +} + +// NeededColumnTask represents one needed column with expire time. +type NeededColumnTask struct { + TableColumnID model.TableColumnID + ToTimeout time.Time + ResultCh chan model.TableColumnID +} + +// SendLoadRequests send neededColumns requests +func (h *Handle) SendLoadRequests(sc *stmtctx.StatementContext, neededColumns []model.TableColumnID, timeout time.Duration) error { + missingColumns := h.genHistMissingColumns(neededColumns) + if len(missingColumns) <= 0 { + return nil + } + sc.StatsLoad.Timeout = timeout + sc.StatsLoad.NeededColumns = missingColumns + sc.StatsLoad.ResultCh = make(chan model.TableColumnID, len(missingColumns)) + for _, col := range missingColumns { + err := h.AppendNeededColumn(col, sc.StatsLoad.ResultCh, timeout) + if err != nil { + return err + } + } + sc.StatsLoad.LoadStartTime = time.Now() + return nil +} + +// SyncWaitStatsLoad sync waits loading of neededColumns and return false if timeout +func (h *Handle) SyncWaitStatsLoad(sc *stmtctx.StatementContext) bool { + if len(sc.StatsLoad.NeededColumns) <= 0 { + return true + } + defer func() { + sc.StatsLoad.NeededColumns = nil + }() + resultCheckMap := map[model.TableColumnID]struct{}{} + for _, col := range sc.StatsLoad.NeededColumns { + resultCheckMap[col] = struct{}{} + } + metrics.SyncLoadCounter.Inc() + timer := time.NewTimer(sc.StatsLoad.Timeout) + defer timer.Stop() + for { + select { + case result, ok := <-sc.StatsLoad.ResultCh: + if ok { + delete(resultCheckMap, result) + if len(resultCheckMap) == 0 { + metrics.SyncLoadHistogram.Observe(float64(time.Since(sc.StatsLoad.LoadStartTime).Milliseconds())) + return true + } + } else { + return false + } + case <-timer.C: + metrics.SyncLoadTimeoutCounter.Inc() + return false + } + } +} + +// genHistMissingColumns generates hist-missing columns based on neededColumns and statsCache. +func (h *Handle) genHistMissingColumns(neededColumns []model.TableColumnID) []model.TableColumnID { + statsCache := h.statsCache.Load().(statsCache) + missingColumns := make([]model.TableColumnID, 0, len(neededColumns)) + for _, col := range neededColumns { + tbl, ok := statsCache.tables[col.TableID] + if !ok { + continue + } + colHist, ok := tbl.Columns[col.ColumnID] + if !ok { + continue + } + if colHist.IsHistNeeded(tbl.Pseudo) { + missingColumns = append(missingColumns, col) + } + } + return missingColumns +} + +// AppendNeededColumn appends needed column to ch, if exists, do not append the duplicated one. +func (h *Handle) AppendNeededColumn(c model.TableColumnID, resultCh chan model.TableColumnID, timeout time.Duration) error { + toTimout := time.Now().Local().Add(timeout) + colTask := &NeededColumnTask{TableColumnID: c, ToTimeout: toTimout, ResultCh: resultCh} + return h.writeToChanWithTimeout(h.StatsLoad.NeededColumnsCh, colTask, timeout) +} + +var errExit = errors.New("Stop loading since domain is closed") + +// StatsReaderContext exported for testing +type StatsReaderContext struct { + reader *statsReader + createdTime time.Time +} + +// SubLoadWorker loads hist data for each column +func (h *Handle) SubLoadWorker(ctx sessionctx.Context, exit chan struct{}, exitWg *util.WaitGroupWrapper) { + readerCtx := &StatsReaderContext{} + defer func() { + exitWg.Done() + logutil.BgLogger().Info("SubLoadWorker exited.") + if readerCtx.reader != nil { + err := h.releaseStatsReader(readerCtx.reader, ctx.(sqlexec.RestrictedSQLExecutor)) + if err != nil { + logutil.BgLogger().Error("Fail to release stats loader: ", zap.Error(err)) + } + } + }() + // if the last task is not successfully handled in last round for error or panic, pass it to this round to retry + var lastTask *NeededColumnTask + for { + task, err := h.HandleOneTask(lastTask, readerCtx, ctx.(sqlexec.RestrictedSQLExecutor), exit) + lastTask = task + if err != nil { + switch err { + case errExit: + return + default: + time.Sleep(h.Lease() / 10) + continue + } + } + } +} + +// HandleOneTask handles last task if not nil, else handle a new task from chan, and return current task if fail somewhere. +func (h *Handle) HandleOneTask(lastTask *NeededColumnTask, readerCtx *StatsReaderContext, ctx sqlexec.RestrictedSQLExecutor, exit chan struct{}) (task *NeededColumnTask, err error) { + defer func() { + // recover for each task, worker keeps working + if r := recover(); r != nil { + buf := make([]byte, 4096) + stackSize := runtime.Stack(buf, false) + buf = buf[:stackSize] + logutil.BgLogger().Error("stats loading panicked", zap.Any("error", r), zap.String("stack", string(buf))) + err = errors.Errorf("stats loading panicked: %v", r) + } + }() + if lastTask == nil { + task, err = h.drainColTask(exit) + if err != nil { + if err != errExit { + logutil.BgLogger().Error("Fail to drain task for stats loading.", zap.Error(err)) + } + return task, err + } + } else { + task = lastTask + } + col := task.TableColumnID + oldCache := h.statsCache.Load().(statsCache) + tbl, ok := oldCache.tables[col.TableID] + if !ok { + h.writeToResultChan(task.ResultCh, col) + return nil, nil + } + c, ok := tbl.Columns[col.ColumnID] + if !ok || c.Len() > 0 { + h.writeToResultChan(task.ResultCh, col) + return nil, nil + } + // to avoid duplicated handling in concurrent scenario + working := h.setWorking(task.TableColumnID, task.ResultCh) + if !working { + return nil, nil + } + // refresh statsReader to get latest stats + h.getFreshStatsReader(readerCtx, ctx) + t := time.Now() + hist, err := h.readStatsForOne(col, c, readerCtx.reader) + if err != nil { + return task, err + } + metrics.ReadStatsHistogram.Observe(float64(time.Since(t).Milliseconds())) + if hist != nil && h.updateCachedColumn(col, hist) { + h.writeToResultChan(task.ResultCh, col) + } + h.finishWorking(col) + return nil, nil +} + +func (h *Handle) getFreshStatsReader(readerCtx *StatsReaderContext, ctx sqlexec.RestrictedSQLExecutor) { + if readerCtx.reader == nil || readerCtx.createdTime.Add(h.Lease()).Before(time.Now()) { + if readerCtx.reader != nil { + err := h.releaseStatsReader(readerCtx.reader, ctx) + if err != nil { + logutil.BgLogger().Warn("Fail to release stats loader: ", zap.Error(err)) + } + } + for { + newReader, err := h.getStatsReader(0, ctx) + if err != nil { + logutil.BgLogger().Error("Fail to new stats loader, retry after a while.", zap.Error(err)) + time.Sleep(h.Lease() / 10) + } else { + readerCtx.reader = newReader + readerCtx.createdTime = time.Now() + return + } + } + } else { + return + } +} + +// readStatsForOne reads hist for one column, TODO load data via kv-get asynchronously +func (h *Handle) readStatsForOne(col model.TableColumnID, c *statistics.Column, reader *statsReader) (*statistics.Column, error) { + failpoint.Inject("mockReadStatsForOnePanic", nil) + failpoint.Inject("mockReadStatsForOneFail", func(val failpoint.Value) { + if val.(bool) { + failpoint.Return(nil, errors.New("gofail ReadStatsForOne error")) + } + }) + hg, err := h.histogramFromStorage(reader, col.TableID, c.ID, &c.Info.FieldType, c.Histogram.NDV, 0, c.LastUpdateVersion, c.NullCount, c.TotColSize, c.Correlation) + if err != nil { + return nil, errors.Trace(err) + } + cms, topN, err := h.cmSketchAndTopNFromStorage(reader, col.TableID, 0, col.ColumnID) + if err != nil { + return nil, errors.Trace(err) + } + fms, err := h.fmSketchFromStorage(reader, col.TableID, 0, col.ColumnID) + if err != nil { + return nil, errors.Trace(err) + } + rows, _, err := reader.read("select stats_ver from mysql.stats_histograms where is_index = 0 and table_id = %? and hist_id = %?", col.TableID, col.ColumnID) + if err != nil { + return nil, errors.Trace(err) + } + if len(rows) == 0 { + logutil.BgLogger().Error("fail to get stats version for this histogram", zap.Int64("table_id", col.TableID), zap.Int64("hist_id", col.ColumnID)) + } + colHist := &statistics.Column{ + PhysicalID: col.TableID, + Histogram: *hg, + Info: c.Info, + CMSketch: cms, + TopN: topN, + FMSketch: fms, + IsHandle: c.IsHandle, + StatsVer: rows[0].GetInt64(0), + Loaded: true, + } + // Column.Count is calculated by Column.TotalRowCount(). Hence, we don't set Column.Count when initializing colHist. + colHist.Count = int64(colHist.TotalRowCount()) + return colHist, nil +} + +// drainColTask will hang until a column task can return, and either task or error will be returned. +func (h *Handle) drainColTask(exit chan struct{}) (*NeededColumnTask, error) { + // select NeededColumnsCh firstly, if no task, then select TimeoutColumnsCh + for { + select { + case <-exit: + return nil, errExit + case task, ok := <-h.StatsLoad.NeededColumnsCh: + if !ok { + return nil, errors.New("drainColTask: cannot read from NeededColumnsCh, maybe the chan is closed") + } + // if the task has already timeout, no sql is sync-waiting for it, + // so do not handle it just now, put it to another channel with lower priority + if time.Now().After(task.ToTimeout) { + h.writeToTimeoutChan(h.StatsLoad.TimeoutColumnsCh, task) + continue + } + return task, nil + case task, ok := <-h.StatsLoad.TimeoutColumnsCh: + select { + case <-exit: + return nil, errExit + case task0, ok0 := <-h.StatsLoad.NeededColumnsCh: + if !ok0 { + return nil, errors.New("drainColTask: cannot read from NeededColumnsCh, maybe the chan is closed") + } + // send task back to TimeoutColumnsCh and return the task drained from NeededColumnsCh + h.writeToTimeoutChan(h.StatsLoad.TimeoutColumnsCh, task) + return task0, nil + default: + if !ok { + return nil, errors.New("drainColTask: cannot read from TimeoutColumnsCh, maybe the chan is closed") + } + // NeededColumnsCh is empty now, handle task from TimeoutColumnsCh + return task, nil + } + } + } +} + +// writeToTimeoutChan writes in a nonblocking way, and if the channel queue is full, it's ok to drop the task. +func (h *Handle) writeToTimeoutChan(taskCh chan *NeededColumnTask, task *NeededColumnTask) { + select { + case taskCh <- task: + default: + } +} + +// writeToChanWithTimeout writes a task to a channel and blocks until timeout. +func (h *Handle) writeToChanWithTimeout(taskCh chan *NeededColumnTask, task *NeededColumnTask, timeout time.Duration) error { + timer := time.NewTimer(timeout) + defer timer.Stop() + select { + case taskCh <- task: + case <-timer.C: + return errors.New("Channel is full and timeout writing to channel") + } + return nil +} + +// writeToResultChan safe-writes with panic-recover so one write-fail will not have big impact. +func (h *Handle) writeToResultChan(resultCh chan model.TableColumnID, rs model.TableColumnID) { + defer func() { + if r := recover(); r != nil { + buf := make([]byte, 4096) + stackSize := runtime.Stack(buf, false) + buf = buf[:stackSize] + logutil.BgLogger().Error("writeToResultChan panicked", zap.Any("error", r), zap.String("stack", string(buf))) + } + }() + select { + case resultCh <- rs: + default: + } +} + +// updateCachedColumn updates the column hist to global statsCache. +func (h *Handle) updateCachedColumn(col model.TableColumnID, colHist *statistics.Column) (updated bool) { + h.StatsLoad.Lock() + defer h.StatsLoad.Unlock() + // Reload the latest stats cache, otherwise the `updateStatsCache` may fail with high probability, because functions + // like `GetPartitionStats` called in `fmSketchFromStorage` would have modified the stats cache already. + oldCache := h.statsCache.Load().(statsCache) + tbl, ok := oldCache.tables[col.TableID] + if !ok { + return true + } + c, ok := tbl.Columns[col.ColumnID] + if !ok || c.Len() > 0 { + return true + } + tbl = tbl.Copy() + tbl.Columns[c.ID] = colHist + return h.updateStatsCache(oldCache.update([]*statistics.Table{tbl}, nil, oldCache.version)) +} + +func (h *Handle) setWorking(col model.TableColumnID, resultCh chan model.TableColumnID) bool { + h.StatsLoad.Lock() + defer h.StatsLoad.Unlock() + chList, ok := h.StatsLoad.WorkingColMap[col] + if ok { + if chList[0] == resultCh { + return true // just return for duplicate setWorking + } + h.StatsLoad.WorkingColMap[col] = append(chList, resultCh) + return false + } + chList = []chan model.TableColumnID{} + chList = append(chList, resultCh) + h.StatsLoad.WorkingColMap[col] = chList + return true +} + +func (h *Handle) finishWorking(col model.TableColumnID) { + h.StatsLoad.Lock() + defer h.StatsLoad.Unlock() + failpoint.Inject("mockFinishWorkingPanic", nil) + if chList, ok := h.StatsLoad.WorkingColMap[col]; ok { + list := chList[1:] + for _, ch := range list { + h.writeToResultChan(ch, col) + } + } + delete(h.StatsLoad.WorkingColMap, col) +} diff --git a/statistics/handle/handle_hist_test.go b/statistics/handle/handle_hist_test.go new file mode 100644 index 0000000000000..1c460981556ca --- /dev/null +++ b/statistics/handle/handle_hist_test.go @@ -0,0 +1,241 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handle_test + +import ( + "testing" + "time" + + "github.com/cznic/mathutil" + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/statistics/handle" + "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/sqlexec" + "github.com/stretchr/testify/require" +) + +func TestConcurrentLoadHist(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + testKit := testkit.NewTestKit(t, store) + testKit.MustExec("use test") + testKit.MustExec("drop table if exists t") + testKit.MustExec("set @@session.tidb_analyze_version=2") + testKit.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") + testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + testKit.MustExec("analyze table t") + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + h := dom.StatsHandle() + stat := h.GetTableStats(tableInfo) + hg := stat.Columns[tableInfo.Columns[0].ID].Histogram + topn := stat.Columns[tableInfo.Columns[0].ID].TopN + require.Greater(t, hg.Len()+topn.Num(), 0) + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Equal(t, 0, hg.Len()+topn.Num()) + stmtCtx := &stmtctx.StatementContext{} + neededColumns := make([]model.TableColumnID, 0, len(tableInfo.Columns)) + for _, col := range tableInfo.Columns { + neededColumns = append(neededColumns, model.TableColumnID{TableID: tableInfo.ID, ColumnID: col.ID}) + } + timeout := time.Nanosecond * mathutil.MaxInt + h.SendLoadRequests(stmtCtx, neededColumns, timeout) + rs := h.SyncWaitStatsLoad(stmtCtx) + require.True(t, rs) + stat = h.GetTableStats(tableInfo) + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Greater(t, hg.Len()+topn.Num(), 0) +} + +func TestConcurrentLoadHistTimeout(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + testKit := testkit.NewTestKit(t, store) + testKit.MustExec("use test") + testKit.MustExec("drop table if exists t") + testKit.MustExec("set @@session.tidb_analyze_version=2") + testKit.MustExec("set @@session.tidb_stats_load_sync_wait =60000") + testKit.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") + testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + testKit.MustExec("analyze table t") + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + h := dom.StatsHandle() + stat := h.GetTableStats(tableInfo) + hg := stat.Columns[tableInfo.Columns[0].ID].Histogram + topn := stat.Columns[tableInfo.Columns[0].ID].TopN + require.Greater(t, hg.Len()+topn.Num(), 0) + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Equal(t, 0, hg.Len()+topn.Num()) + stmtCtx := &stmtctx.StatementContext{} + neededColumns := make([]model.TableColumnID, 0, len(tableInfo.Columns)) + for _, col := range tableInfo.Columns { + neededColumns = append(neededColumns, model.TableColumnID{TableID: tableInfo.ID, ColumnID: col.ID}) + } + h.SendLoadRequests(stmtCtx, neededColumns, 0) // set timeout to 0 so task will go to timeout channel + rs := h.SyncWaitStatsLoad(stmtCtx) + require.False(t, rs) + stat = h.GetTableStats(tableInfo) + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Equal(t, 0, hg.Len()+topn.Num()) + // wait for timeout task to be handled + oldStat := stat + for { + time.Sleep(time.Millisecond * 100) + stat = h.GetTableStats(tableInfo) + if stat != oldStat { + break + } + } + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Greater(t, hg.Len()+topn.Num(), 0) +} + +func TestConcurrentLoadHistWithPanicAndFail(t *testing.T) { + originConfig := config.GetGlobalConfig() + newConfig := config.NewConfig() + newConfig.Performance.StatsLoadConcurrency = 0 // no worker to consume channel + config.StoreGlobalConfig(newConfig) + defer config.StoreGlobalConfig(originConfig) + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + testKit := testkit.NewTestKit(t, store) + testKit.MustExec("use test") + testKit.MustExec("drop table if exists t") + testKit.MustExec("set @@session.tidb_analyze_version=2") + testKit.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") + testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + testKit.MustExec("analyze table t") + + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + h := dom.StatsHandle() + + neededColumns := make([]model.TableColumnID, 1) + neededColumns[0] = model.TableColumnID{TableID: tableInfo.ID, ColumnID: tableInfo.Columns[2].ID} + timeout := time.Nanosecond * mathutil.MaxInt + + failpoints := []struct { + failPath string + inTerms string + }{ + { + failPath: "github.com/pingcap/tidb/statistics/handle/mockFinishWorkingPanic", + inTerms: "panic", + }, + { + failPath: "github.com/pingcap/tidb/statistics/handle/mockReadStatsForOnePanic", + inTerms: "panic", + }, + { + failPath: "github.com/pingcap/tidb/statistics/handle/mockReadStatsForOneFail", + inTerms: "return(true)", + }, + } + + for _, fp := range failpoints { + // clear statsCache + h.Clear() + require.NoError(t, dom.StatsHandle().Update(is)) + + // no stats at beginning + stat := h.GetTableStats(tableInfo) + hg := stat.Columns[tableInfo.Columns[2].ID].Histogram + topn := stat.Columns[tableInfo.Columns[2].ID].TopN + require.Equal(t, 0, hg.Len()+topn.Num()) + + stmtCtx1 := &stmtctx.StatementContext{} + h.SendLoadRequests(stmtCtx1, neededColumns, timeout) + stmtCtx2 := &stmtctx.StatementContext{} + h.SendLoadRequests(stmtCtx2, neededColumns, timeout) + + readerCtx := &handle.StatsReaderContext{} + exitCh := make(chan struct{}) + require.NoError(t, failpoint.Enable(fp.failPath, fp.inTerms)) + + task1, err1 := h.HandleOneTask(nil, readerCtx, testKit.Session().(sqlexec.RestrictedSQLExecutor), exitCh) + require.Error(t, err1) + require.NotNil(t, task1) + list, ok := h.StatsLoad.WorkingColMap[neededColumns[0]] + require.True(t, ok) + require.Len(t, list, 1) + require.Equal(t, stmtCtx1.StatsLoad.ResultCh, list[0]) + + task2, err2 := h.HandleOneTask(nil, readerCtx, testKit.Session().(sqlexec.RestrictedSQLExecutor), exitCh) + require.Nil(t, err2) + require.Nil(t, task2) + list, ok = h.StatsLoad.WorkingColMap[neededColumns[0]] + require.True(t, ok) + require.Len(t, list, 2) + require.Equal(t, stmtCtx2.StatsLoad.ResultCh, list[1]) + + require.NoError(t, failpoint.Disable(fp.failPath)) + task3, err3 := h.HandleOneTask(task1, readerCtx, testKit.Session().(sqlexec.RestrictedSQLExecutor), exitCh) + require.NoError(t, err3) + require.Nil(t, task3) + + require.Len(t, stmtCtx1.StatsLoad.ResultCh, 1) + require.Len(t, stmtCtx2.StatsLoad.ResultCh, 1) + + rs1, ok1 := <-stmtCtx1.StatsLoad.ResultCh + require.True(t, ok1) + require.Equal(t, neededColumns[0], rs1) + rs2, ok2 := <-stmtCtx2.StatsLoad.ResultCh + require.True(t, ok2) + require.Equal(t, neededColumns[0], rs2) + + stat = h.GetTableStats(tableInfo) + hg = stat.Columns[tableInfo.Columns[2].ID].Histogram + topn = stat.Columns[tableInfo.Columns[2].ID].TopN + require.Greater(t, hg.Len()+topn.Num(), 0) + } +} diff --git a/statistics/handle/handle_test.go b/statistics/handle/handle_test.go index 924ff178aee73..2d474e232d192 100644 --- a/statistics/handle/handle_test.go +++ b/statistics/handle/handle_test.go @@ -18,91 +18,65 @@ import ( "bytes" "fmt" "math" + "strconv" "strings" "testing" "time" "unsafe" - . "github.com/pingcap/check" - "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/errno" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/statistics/handle" - "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/israce" "github.com/pingcap/tidb/util/mock" "github.com/pingcap/tidb/util/ranger" - "github.com/pingcap/tidb/util/testkit" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" ) -func TestT(t *testing.T) { - TestingT(t) -} - -// TODO replace cleanEnv with createTestKitAndDom in gc_series_test.go when migrate this file -func cleanEnv(c *C, store kv.Storage, do *domain.Domain) { - tk := testkit.NewTestKit(c, store) - tk.MustExec("use test") - r := tk.MustQuery("show tables") - for _, tb := range r.Rows() { - tableName := tb[0] - tk.MustExec(fmt.Sprintf("drop table %v", tableName)) - } - tk.MustExec("delete from mysql.stats_meta") - tk.MustExec("delete from mysql.stats_histograms") - tk.MustExec("delete from mysql.stats_buckets") - tk.MustExec("delete from mysql.stats_extended") - tk.MustExec("delete from mysql.stats_fm_sketch") - tk.MustExec("delete from mysql.schema_index_usage") - tk.MustExec("delete from mysql.column_stats_usage") - do.StatsHandle().Clear() -} - -func (s *testStatsSuite) TestStatsCache(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestStatsCache(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") testKit.MustExec("insert into t values(1, 2)") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsTrue) + require.True(t, statsTbl.Pseudo) testKit.MustExec("analyze table t") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) testKit.MustExec("create index idx_t on t(c1)") do.InfoSchema() statsTbl = do.StatsHandle().GetTableStats(tableInfo) // If index is build, but stats is not updated. statsTbl can also work. - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) // But the added index will not work. - c.Assert(statsTbl.Indices[int64(1)], IsNil) + require.Nil(t, statsTbl.Indices[int64(1)]) testKit.MustExec("analyze table t") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) // If the new schema drop a column, the table stats can still work. testKit.MustExec("alter table t drop column c2") is = do.InfoSchema() do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) // If the new schema add a column, the table stats can still work. testKit.MustExec("alter table t add column c10 int") @@ -110,54 +84,55 @@ func (s *testStatsSuite) TestStatsCache(c *C) { do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) } -func (s *testStatsSuite) TestStatsCacheMemTracker(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestStatsCacheMemTracker(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int,c3 int)") testKit.MustExec("insert into t values(1, 2, 3)") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.MemoryUsage() > 0, IsTrue) - c.Assert(statsTbl.Pseudo, IsTrue) + require.True(t, statsTbl.MemoryUsage() > 0) + require.True(t, statsTbl.Pseudo) testKit.MustExec("analyze table t") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) testKit.MustExec("create index idx_t on t(c1)") do.InfoSchema() statsTbl = do.StatsHandle().GetTableStats(tableInfo) // If index is build, but stats is not updated. statsTbl can also work. - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) // But the added index will not work. - c.Assert(statsTbl.Indices[int64(1)], IsNil) + require.Nil(t, statsTbl.Indices[int64(1)]) testKit.MustExec("analyze table t") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) // If the new schema drop a column, the table stats can still work. testKit.MustExec("alter table t drop column c2") is = do.InfoSchema() do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.MemoryUsage() > 0, IsTrue) - c.Assert(statsTbl.Pseudo, IsFalse) + require.True(t, statsTbl.MemoryUsage() > 0) + require.False(t, statsTbl.Pseudo) // If the new schema add a column, the table stats can still work. testKit.MustExec("alter table t add column c10 int") @@ -165,37 +140,37 @@ func (s *testStatsSuite) TestStatsCacheMemTracker(c *C) { do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Pseudo, IsFalse) + require.False(t, statsTbl.Pseudo) } -func assertTableEqual(c *C, a *statistics.Table, b *statistics.Table) { - c.Assert(a.Count, Equals, b.Count) - c.Assert(a.ModifyCount, Equals, b.ModifyCount) - c.Assert(len(a.Columns), Equals, len(b.Columns)) +func assertTableEqual(t *testing.T, a *statistics.Table, b *statistics.Table) { + require.Equal(t, b.Count, a.Count) + require.Equal(t, b.ModifyCount, a.ModifyCount) + require.Len(t, a.Columns, len(b.Columns)) for i := range a.Columns { - c.Assert(a.Columns[i].Count, Equals, b.Columns[i].Count) - c.Assert(statistics.HistogramEqual(&a.Columns[i].Histogram, &b.Columns[i].Histogram, false), IsTrue) + require.Equal(t, b.Columns[i].Count, a.Columns[i].Count) + require.True(t, statistics.HistogramEqual(&a.Columns[i].Histogram, &b.Columns[i].Histogram, false)) if a.Columns[i].CMSketch == nil { - c.Assert(b.Columns[i].CMSketch, IsNil) + require.Nil(t, b.Columns[i].CMSketch) } else { - c.Assert(a.Columns[i].CMSketch.Equal(b.Columns[i].CMSketch), IsTrue) + require.True(t, a.Columns[i].CMSketch.Equal(b.Columns[i].CMSketch)) } // The nil case has been considered in (*TopN).Equal() so we don't need to consider it here. - c.Assert(a.Columns[i].TopN.Equal(b.Columns[i].TopN), IsTrue, Commentf("%v, %v", a.Columns[i].TopN, b.Columns[i].TopN)) + require.Truef(t, a.Columns[i].TopN.Equal(b.Columns[i].TopN), "%v, %v", a.Columns[i].TopN, b.Columns[i].TopN) } - c.Assert(len(a.Indices), Equals, len(b.Indices)) + require.Len(t, a.Indices, len(b.Indices)) for i := range a.Indices { - c.Assert(statistics.HistogramEqual(&a.Indices[i].Histogram, &b.Indices[i].Histogram, false), IsTrue) + require.True(t, statistics.HistogramEqual(&a.Indices[i].Histogram, &b.Indices[i].Histogram, false)) if a.Indices[i].CMSketch == nil { - c.Assert(b.Indices[i].CMSketch, IsNil) + require.Nil(t, b.Indices[i].CMSketch) } else { - c.Assert(a.Indices[i].CMSketch.Equal(b.Indices[i].CMSketch), IsTrue) + require.True(t, a.Indices[i].CMSketch.Equal(b.Indices[i].CMSketch)) } - c.Assert(a.Indices[i].TopN.Equal(b.Indices[i].TopN), IsTrue) + require.True(t, a.Indices[i].TopN.Equal(b.Indices[i].TopN)) } - c.Assert(isSameExtendedStats(a.ExtendedStats, b.ExtendedStats), IsTrue) + require.True(t, isSameExtendedStats(a.ExtendedStats, b.ExtendedStats)) } func isSameExtendedStats(a, b *statistics.ExtendedStatsColl) bool { @@ -227,9 +202,10 @@ func isSameExtendedStats(a, b *statistics.ExtendedStatsColl) bool { return true } -func (s *testStatsSuite) TestStatsStoreAndLoad(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestStatsStoreAndLoad(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") recordCount := 1000 @@ -237,10 +213,10 @@ func (s *testStatsSuite) TestStatsStoreAndLoad(c *C) { testKit.MustExec("insert into t values (?, ?)", i, i+1) } testKit.MustExec("create index idx_t on t(c2)") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() testKit.MustExec("analyze table t") @@ -248,40 +224,42 @@ func (s *testStatsSuite) TestStatsStoreAndLoad(c *C) { do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl2 := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl2.Pseudo, IsFalse) - c.Assert(statsTbl2.Count, Equals, int64(recordCount)) - assertTableEqual(c, statsTbl1, statsTbl2) + require.False(t, statsTbl2.Pseudo) + require.Equal(t, int64(recordCount), statsTbl2.Count) + assertTableEqual(t, statsTbl1, statsTbl2) } -func (s *testStatsSuite) TestEmptyTable(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestEmptyTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int, key cc1(c1), key cc2(c2))") testKit.MustExec("analyze table t") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) count := statsTbl.ColumnGreaterRowCount(mock.NewContext(), types.NewDatum(1), tableInfo.Columns[0].ID) - c.Assert(count, Equals, 0.0) + require.Equal(t, 0.0, count) } -func (s *testStatsSuite) TestColumnIDs(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestColumnIDs(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") testKit.MustExec("insert into t values(1, 2)") testKit.MustExec("analyze table t") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) sctx := mock.NewContext() @@ -293,168 +271,171 @@ func (s *testStatsSuite) TestColumnIDs(c *C) { Collators: collate.GetBinaryCollatorSlice(1), } count, err := statsTbl.GetRowCountByColumnRanges(sctx, tableInfo.Columns[0].ID, []*ranger.Range{ran}) - c.Assert(err, IsNil) - c.Assert(count, Equals, float64(1)) + require.NoError(t, err) + require.Equal(t, float64(1), count) // Drop a column and the offset changed, testKit.MustExec("alter table t drop column c1") is = do.InfoSchema() do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo = tbl.Meta() statsTbl = do.StatsHandle().GetTableStats(tableInfo) // At that time, we should get c2's stats instead of c1's. count, err = statsTbl.GetRowCountByColumnRanges(sctx, tableInfo.Columns[0].ID, []*ranger.Range{ran}) - c.Assert(err, IsNil) - c.Assert(count, Equals, 0.0) + require.NoError(t, err) + require.Equal(t, 0.0, count) } -func (s *testStatsSuite) TestAvgColLen(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestAvgColLen(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 varchar(100), c3 float, c4 datetime, c5 varchar(100))") testKit.MustExec("insert into t values(1, '1234567', 12.3, '2018-03-07 19:00:57', NULL)") testKit.MustExec("analyze table t") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSize(statsTbl.Count, false), Equals, 1.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, 8.0) + require.Equal(t, 1.0, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeChunkFormat(statsTbl.Count)) // The size of varchar type is LEN + BYTE, here is 1 + 7 = 8 - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSize(statsTbl.Count, false), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSize(statsTbl.Count, false), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSize(statsTbl.Count, false), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, 8.0-3) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3)))) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime))) - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, 8.0-3+8) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3)))) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime))) - c.Assert(statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, 0.0) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0-3, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(float32(12.3))), statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(types.ZeroTime)), statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, 8.0-3+8, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(float32(12.3))), statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(types.ZeroTime)), statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, 0.0, statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeListInDisk(statsTbl.Count)) testKit.MustExec("insert into t values(132, '123456789112', 1232.3, '2018-03-07 19:17:29', NULL)") testKit.MustExec("analyze table t") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSize(statsTbl.Count, false), Equals, 1.5) - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSize(statsTbl.Count, false), Equals, 10.5) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSize(statsTbl.Count, false), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSize(statsTbl.Count, false), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, math.Round((10.5-math.Log2(10.5))*100)/100) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3)))) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime))) - c.Assert(statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, math.Round((10.5-math.Log2(10.5))*100)/100+8) - c.Assert(statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3)))) - c.Assert(statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime))) - c.Assert(statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeChunkFormat(statsTbl.Count), Equals, 8.0) - c.Assert(statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeListInDisk(statsTbl.Count), Equals, 0.0) -} - -func (s *testStatsSuite) TestDurationToTS(c *C) { + require.Equal(t, 1.5, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 10.5, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSize(statsTbl.Count, false)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, math.Round((10.5-math.Log2(10.5))*100)/100, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(float32(12.3))), statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(types.ZeroTime)), statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeListInDisk(statsTbl.Count)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[0].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, math.Round((10.5-math.Log2(10.5))*100)/100+8, statsTbl.Columns[tableInfo.Columns[1].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(float32(12.3))), statsTbl.Columns[tableInfo.Columns[2].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, float64(unsafe.Sizeof(types.ZeroTime)), statsTbl.Columns[tableInfo.Columns[3].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, 8.0, statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeChunkFormat(statsTbl.Count)) + require.Equal(t, 0.0, statsTbl.Columns[tableInfo.Columns[4].ID].AvgColSizeListInDisk(statsTbl.Count)) +} + +func TestDurationToTS(t *testing.T) { tests := []time.Duration{time.Millisecond, time.Second, time.Minute, time.Hour} - for _, t := range tests { - ts := handle.DurationToTS(t) - c.Assert(oracle.ExtractPhysical(ts)*int64(time.Millisecond), Equals, int64(t)) + for _, test := range tests { + ts := handle.DurationToTS(test) + require.Equal(t, int64(test), oracle.ExtractPhysical(ts)*int64(time.Millisecond)) } } -func (s *testStatsSuite) TestVersion(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestVersion(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t1 (c1 int, c2 int)") testKit.MustExec("analyze table t1") - do := s.do + do := dom is := do.InfoSchema() tbl1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo1 := tbl1.Meta() - h, err := handle.NewHandle(testKit.Se, time.Millisecond, do.SysSessionPool()) - c.Assert(err, IsNil) + h, err := handle.NewHandle(testKit.Session(), time.Millisecond, do.SysSessionPool(), do.SysProcTracker()) + require.NoError(t, err) unit := oracle.ComposeTS(1, 0) testKit.MustExec("update mysql.stats_meta set version = ? where table_id = ?", 2*unit, tableInfo1.ID) - c.Assert(h.Update(is), IsNil) - c.Assert(h.LastUpdateVersion(), Equals, 2*unit) + require.NoError(t, h.Update(is)) + require.Equal(t, 2*unit, h.LastUpdateVersion()) statsTbl1 := h.GetTableStats(tableInfo1) - c.Assert(statsTbl1.Pseudo, IsFalse) + require.False(t, statsTbl1.Pseudo) testKit.MustExec("create table t2 (c1 int, c2 int)") testKit.MustExec("analyze table t2") is = do.InfoSchema() tbl2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo2 := tbl2.Meta() // A smaller version write, and we can still read it. testKit.MustExec("update mysql.stats_meta set version = ? where table_id = ?", unit, tableInfo2.ID) - c.Assert(h.Update(is), IsNil) - c.Assert(h.LastUpdateVersion(), Equals, 2*unit) + require.NoError(t, h.Update(is)) + require.Equal(t, 2*unit, h.LastUpdateVersion()) statsTbl2 := h.GetTableStats(tableInfo2) - c.Assert(statsTbl2.Pseudo, IsFalse) + require.False(t, statsTbl2.Pseudo) testKit.MustExec("insert t1 values(1,2)") testKit.MustExec("analyze table t1") offset := 3 * unit testKit.MustExec("update mysql.stats_meta set version = ? where table_id = ?", offset+4, tableInfo1.ID) - c.Assert(h.Update(is), IsNil) - c.Assert(h.LastUpdateVersion(), Equals, offset+uint64(4)) + require.NoError(t, h.Update(is)) + require.Equal(t, offset+uint64(4), h.LastUpdateVersion()) statsTbl1 = h.GetTableStats(tableInfo1) - c.Assert(statsTbl1.Count, Equals, int64(1)) + require.Equal(t, int64(1), statsTbl1.Count) testKit.MustExec("insert t2 values(1,2)") testKit.MustExec("analyze table t2") // A smaller version write, and we can still read it. testKit.MustExec("update mysql.stats_meta set version = ? where table_id = ?", offset+3, tableInfo2.ID) - c.Assert(h.Update(is), IsNil) - c.Assert(h.LastUpdateVersion(), Equals, offset+uint64(4)) + require.NoError(t, h.Update(is)) + require.Equal(t, offset+uint64(4), h.LastUpdateVersion()) statsTbl2 = h.GetTableStats(tableInfo2) - c.Assert(statsTbl2.Count, Equals, int64(1)) + require.Equal(t, int64(1), statsTbl2.Count) testKit.MustExec("insert t2 values(1,2)") testKit.MustExec("analyze table t2") // A smaller version write, and we cannot read it. Because at this time, lastThree Version is 4. testKit.MustExec("update mysql.stats_meta set version = 1 where table_id = ?", tableInfo2.ID) - c.Assert(h.Update(is), IsNil) - c.Assert(h.LastUpdateVersion(), Equals, offset+uint64(4)) + require.NoError(t, h.Update(is)) + require.Equal(t, offset+uint64(4), h.LastUpdateVersion()) statsTbl2 = h.GetTableStats(tableInfo2) - c.Assert(statsTbl2.Count, Equals, int64(1)) + require.Equal(t, int64(1), statsTbl2.Count) // We add an index and analyze it, but DDL doesn't load. testKit.MustExec("alter table t2 add column c3 int") testKit.MustExec("analyze table t2") // load it with old schema. - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl2 = h.GetTableStats(tableInfo2) - c.Assert(statsTbl2.Pseudo, IsFalse) - c.Assert(statsTbl2.Columns[int64(3)], IsNil) + require.False(t, statsTbl2.Pseudo) + require.Nil(t, statsTbl2.Columns[int64(3)]) // Next time DDL updated. is = do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl2 = h.GetTableStats(tableInfo2) - c.Assert(statsTbl2.Pseudo, IsFalse) + require.False(t, statsTbl2.Pseudo) // We can read it without analyze again! Thanks for PrevLastVersion. - c.Assert(statsTbl2.Columns[int64(3)], NotNil) + require.NotNil(t, statsTbl2.Columns[int64(3)]) } -func (s *testStatsSuite) TestLoadHist(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestLoadHist(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 varchar(12), c2 char(12))") - do := s.do + do := dom h := do.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) rowCount := 10 for i := 0; i < rowCount; i++ { testKit.MustExec("insert into t values('a','ddd')") @@ -462,194 +443,190 @@ func (s *testStatsSuite) TestLoadHist(c *C) { testKit.MustExec("analyze table t") is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() oldStatsTbl := h.GetTableStats(tableInfo) for i := 0; i < rowCount; i++ { testKit.MustExec("insert into t values('bb','sdfga')") } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) err = h.Update(do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, err) newStatsTbl := h.GetTableStats(tableInfo) // The stats table is updated. - c.Assert(oldStatsTbl == newStatsTbl, IsFalse) + require.False(t, oldStatsTbl == newStatsTbl) // Only the TotColSize of histograms is updated. for id, hist := range oldStatsTbl.Columns { - c.Assert(hist.TotColSize, Less, newStatsTbl.Columns[id].TotColSize) + require.Less(t, hist.TotColSize, newStatsTbl.Columns[id].TotColSize) temp := hist.TotColSize hist.TotColSize = newStatsTbl.Columns[id].TotColSize - c.Assert(statistics.HistogramEqual(&hist.Histogram, &newStatsTbl.Columns[id].Histogram, false), IsTrue) + require.True(t, statistics.HistogramEqual(&hist.Histogram, &newStatsTbl.Columns[id].Histogram, false)) hist.TotColSize = temp - c.Assert(hist.CMSketch.Equal(newStatsTbl.Columns[id].CMSketch), IsTrue) - c.Assert(hist.Count, Equals, newStatsTbl.Columns[id].Count) - c.Assert(hist.Info, Equals, newStatsTbl.Columns[id].Info) + require.True(t, hist.CMSketch.Equal(newStatsTbl.Columns[id].CMSketch)) + require.Equal(t, newStatsTbl.Columns[id].Count, hist.Count) + require.Equal(t, newStatsTbl.Columns[id].Info, hist.Info) } // Add column c3, we only update c3. testKit.MustExec("alter table t add column c3 int") err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) is = do.InfoSchema() tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo = tbl.Meta() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) newStatsTbl2 := h.GetTableStats(tableInfo) - c.Assert(newStatsTbl2 == newStatsTbl, IsFalse) + require.False(t, newStatsTbl2 == newStatsTbl) // The histograms is not updated. for id, hist := range newStatsTbl.Columns { - c.Assert(hist, Equals, newStatsTbl2.Columns[id]) + require.Equal(t, newStatsTbl2.Columns[id], hist) } - c.Assert(newStatsTbl2.Columns[int64(3)].LastUpdateVersion, Greater, newStatsTbl2.Columns[int64(1)].LastUpdateVersion) + require.Greater(t, newStatsTbl2.Columns[int64(3)].LastUpdateVersion, newStatsTbl2.Columns[int64(1)].LastUpdateVersion) } -func (s *testStatsSuite) TestInitStats(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestInitStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 1") testKit.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,7,8)") testKit.MustExec("analyze table t") - h := s.do.StatsHandle() - is := s.do.InfoSchema() + h := dom.StatsHandle() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) // `Update` will not use load by need strategy when `Lease` is 0, and `InitStats` is only called when // `Lease` is not 0, so here we just change it. h.SetLease(time.Millisecond) h.Clear() - c.Assert(h.InitStats(is), IsNil) + require.NoError(t, h.InitStats(is)) table0 := h.GetTableStats(tbl.Meta()) cols := table0.Columns - c.Assert(cols[1].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x36)) - c.Assert(cols[2].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x37)) - c.Assert(cols[3].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x38)) + require.Equal(t, uint8(0x36), cols[1].LastAnalyzePos.GetBytes()[0]) + require.Equal(t, uint8(0x37), cols[2].LastAnalyzePos.GetBytes()[0]) + require.Equal(t, uint8(0x38), cols[3].LastAnalyzePos.GetBytes()[0]) h.Clear() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) table1 := h.GetTableStats(tbl.Meta()) - assertTableEqual(c, table0, table1) + assertTableEqual(t, table0, table1) h.SetLease(0) } -func (s *testStatsSuite) TestInitStatsVer2(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestInitStatsVer2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@session.tidb_analyze_version=2") tk.MustExec("create table t(a int, b int, c int, index idx(a), index idxab(a, b))") tk.MustExec("insert into t values(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (4, 4, 4), (4, 4, 4)") tk.MustExec("analyze table t with 2 topn, 3 buckets") - h := s.do.StatsHandle() - is := s.do.InfoSchema() + h := dom.StatsHandle() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) // `Update` will not use load by need strategy when `Lease` is 0, and `InitStats` is only called when // `Lease` is not 0, so here we just change it. h.SetLease(time.Millisecond) h.Clear() - c.Assert(h.InitStats(is), IsNil) + require.NoError(t, h.InitStats(is)) table0 := h.GetTableStats(tbl.Meta()) cols := table0.Columns - c.Assert(cols[1].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x33)) - c.Assert(cols[2].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x33)) - c.Assert(cols[3].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x33)) + require.Equal(t, uint8(0x33), cols[1].LastAnalyzePos.GetBytes()[0]) + require.Equal(t, uint8(0x33), cols[2].LastAnalyzePos.GetBytes()[0]) + require.Equal(t, uint8(0x33), cols[3].LastAnalyzePos.GetBytes()[0]) h.Clear() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) table1 := h.GetTableStats(tbl.Meta()) - assertTableEqual(c, table0, table1) + assertTableEqual(t, table0, table1) h.SetLease(0) } -func (s *testStatsSuite) TestReloadExtStatsLockRelease(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestReloadExtStatsLockRelease(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values(1,1),(2,2),(3,3)") tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustExec("analyze table t") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/statistics/handle/injectExtStatsLoadErr", `return("")`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/statistics/handle/injectExtStatsLoadErr", `return("")`)) err := tk.ExecToErr("admin reload stats_extended") - c.Assert(err.Error(), Equals, "gofail extendedStatsFromStorage error") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/statistics/handle/injectExtStatsLoadErr"), IsNil) + require.Equal(t, "gofail extendedStatsFromStorage error", err.Error()) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/statistics/handle/injectExtStatsLoadErr")) // Check the lock is released by `admin reload stats_extended` if error happens. tk.MustExec("analyze table t") } -func (s *testStatsSuite) TestLoadStats(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestLoadStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("drop table if exists t") + testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b))") testKit.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") - oriLease := s.do.StatsHandle().Lease() - s.do.StatsHandle().SetLease(1) + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) defer func() { - s.do.StatsHandle().SetLease(oriLease) + dom.StatsHandle().SetLease(oriLease) }() testKit.MustExec("analyze table t") - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() stat := h.GetTableStats(tableInfo) hg := stat.Columns[tableInfo.Columns[0].ID].Histogram - c.Assert(hg.Len(), Greater, 0) + require.Greater(t, hg.Len(), 0) cms := stat.Columns[tableInfo.Columns[0].ID].CMSketch - c.Assert(cms, IsNil) + require.Nil(t, cms) hg = stat.Indices[tableInfo.Indices[0].ID].Histogram - c.Assert(hg.Len(), Greater, 0) + require.Greater(t, hg.Len(), 0) cms = stat.Indices[tableInfo.Indices[0].ID].CMSketch topN := stat.Indices[tableInfo.Indices[0].ID].TopN - c.Assert(cms.TotalCount()+topN.TotalCount(), Greater, uint64(0)) + require.Greater(t, cms.TotalCount()+topN.TotalCount(), uint64(0)) hg = stat.Columns[tableInfo.Columns[2].ID].Histogram - c.Assert(hg.Len(), Equals, 0) + require.Equal(t, 0, hg.Len()) cms = stat.Columns[tableInfo.Columns[2].ID].CMSketch - c.Assert(cms, IsNil) - _, err = stat.ColumnEqualRowCount(testKit.Se, types.NewIntDatum(1), tableInfo.Columns[2].ID) - c.Assert(err, IsNil) - c.Assert(h.LoadNeededHistograms(), IsNil) + require.Nil(t, cms) + _, err = stat.ColumnEqualRowCount(testKit.Session(), types.NewIntDatum(1), tableInfo.Columns[2].ID) + require.NoError(t, err) + require.NoError(t, h.LoadNeededHistograms()) stat = h.GetTableStats(tableInfo) hg = stat.Columns[tableInfo.Columns[2].ID].Histogram - c.Assert(hg.Len(), Greater, 0) + require.Greater(t, hg.Len(), 0) // Following test tests whether the LoadNeededHistograms would panic. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderFail", `return(true)`), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderFail", `return(true)`)) err = h.LoadNeededHistograms() - c.Assert(err, NotNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderFail"), IsNil) + require.Error(t, err) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderFail")) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderPanic", "panic"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderPanic", "panic")) err = h.LoadNeededHistograms() - c.Assert(err, ErrorMatches, ".*getStatsReader panic.*") - c.Assert(failpoint.Disable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderPanic"), IsNil) + require.Error(t, err) + require.Regexp(t, ".*getStatsReader panic.*", err.Error()) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/statistics/handle/mockGetStatsReaderPanic")) err = h.LoadNeededHistograms() - c.Assert(err, IsNil) -} - -func newStoreWithBootstrap() (kv.Storage, *domain.Domain, error) { - store, err := mockstore.NewMockStore() - if err != nil { - return nil, nil, errors.Trace(err) - } - session.SetSchemaLease(0) - session.DisableStats4Test() - domain.RunAutoAnalyze = false - do, err := session.BootstrapSession(store) - do.SetStatsUpdating(true) - return store, do, errors.Trace(err) + require.NoError(t, err) } -func (s *testStatsSuite) TestCorrelation(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestCorrelation(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t(c1 int primary key, c2 int)") testKit.MustExec("select * from t where c1 > 10 and c2 > 10") @@ -657,73 +634,73 @@ func (s *testStatsSuite) TestCorrelation(c *C) { testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result := testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("insert into t values(8,18)") testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "0.8285714285714286") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "0.8285714285714286", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "0.8285714285714286") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "0.8285714285714286", result.Rows()[1][9]) testKit.MustExec("truncate table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) testKit.MustExec("insert into t values(1,21),(3,12),(4,7),(2,20),(5,1)") testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "-1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "-1", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "-1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "-1", result.Rows()[1][9]) testKit.MustExec("insert into t values(8,4)") testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "-0.9428571428571428") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "-0.9428571428571428", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "-0.9428571428571428") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "-0.9428571428571428", result.Rows()[1][9]) testKit.MustExec("truncate table t") testKit.MustExec("insert into t values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,2),(21,2),(22,2),(23,2),(24,2),(25,2)") testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("drop table t") testKit.MustExec("create table t(c1 int, c2 int)") @@ -731,30 +708,30 @@ func (s *testStatsSuite) TestCorrelation(c *C) { testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "0.8285714285714286") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "0.8285714285714286", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "0.8285714285714286") + require.Len(t, result.Rows(), 2) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "0.8285714285714286", result.Rows()[1][9]) testKit.MustExec("truncate table t") testKit.MustExec("insert into t values(1,1),(2,7),(3,12),(8,18),(4,20),(5,21)") testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0.8285714285714286") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0.8285714285714286", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("set @@session.tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 2) - c.Assert(result.Rows()[0][9], Equals, "0.8285714285714286") - c.Assert(result.Rows()[1][9], Equals, "1") + require.Len(t, result.Rows(), 2) + require.Equal(t, "0.8285714285714286", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) testKit.MustExec("drop table t") testKit.MustExec("create table t(c1 int primary key, c2 int, c3 int, key idx_c2(c2))") @@ -762,71 +739,75 @@ func (s *testStatsSuite) TestCorrelation(c *C) { testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 0").Sort() - c.Assert(len(result.Rows()), Equals, 3) - c.Assert(result.Rows()[0][9], Equals, "0") - c.Assert(result.Rows()[1][9], Equals, "1") - c.Assert(result.Rows()[2][9], Equals, "1") + require.Len(t, result.Rows(), 3) + require.Equal(t, "0", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) + require.Equal(t, "1", result.Rows()[2][9]) result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 1").Sort() - c.Assert(len(result.Rows()), Equals, 1) - c.Assert(result.Rows()[0][9], Equals, "0") + require.Len(t, result.Rows(), 1) + require.Equal(t, "0", result.Rows()[0][9]) testKit.MustExec("set @@tidb_analyze_version=2") testKit.MustExec("analyze table t") result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 0").Sort() - c.Assert(len(result.Rows()), Equals, 3) - c.Assert(result.Rows()[0][9], Equals, "1") - c.Assert(result.Rows()[1][9], Equals, "1") - c.Assert(result.Rows()[2][9], Equals, "1") + require.Len(t, result.Rows(), 3) + require.Equal(t, "1", result.Rows()[0][9]) + require.Equal(t, "1", result.Rows()[1][9]) + require.Equal(t, "1", result.Rows()[2][9]) result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 1").Sort() - c.Assert(len(result.Rows()), Equals, 1) - c.Assert(result.Rows()[0][9], Equals, "0") + require.Len(t, result.Rows(), 1) + require.Equal(t, "0", result.Rows()[0][9]) } -func (s *testStatsSuite) TestAnalyzeVirtualCol(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAnalyzeVirtualCol(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int generated always as (-a) virtual, c int generated always as (-a) stored, index (c))") tk.MustExec("insert into t(a) values(2),(1),(1),(3),(NULL)") tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("analyze table t") - c.Assert(len(tk.MustQuery("show stats_histograms where table_name ='t'").Rows()), Equals, 3) + require.Len(t, tk.MustQuery("show stats_histograms where table_name ='t'").Rows(), 3) } -func (s *testStatsSuite) TestShowGlobalStats(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestShowGlobalStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 0") tk.MustExec("drop table if exists t") tk.MustExec("set @@tidb_partition_prune_mode = 'static'") tk.MustExec("create table t (a int, key(a)) partition by hash(a) partitions 2") tk.MustExec("insert into t values (1), (2), (3), (4)") tk.MustExec("analyze table t with 1 buckets") - c.Assert(len(tk.MustQuery("show stats_meta").Rows()), Equals, 2) - c.Assert(len(tk.MustQuery("show stats_meta where partition_name='global'").Rows()), Equals, 0) - c.Assert(len(tk.MustQuery("show stats_buckets").Rows()), Equals, 4) // 2 partitions * (1 for the column_a and 1 for the index_a) - c.Assert(len(tk.MustQuery("show stats_buckets where partition_name='global'").Rows()), Equals, 0) - c.Assert(len(tk.MustQuery("show stats_histograms").Rows()), Equals, 4) - c.Assert(len(tk.MustQuery("show stats_histograms where partition_name='global'").Rows()), Equals, 0) - c.Assert(len(tk.MustQuery("show stats_healthy").Rows()), Equals, 2) - c.Assert(len(tk.MustQuery("show stats_healthy where partition_name='global'").Rows()), Equals, 0) + require.Len(t, tk.MustQuery("show stats_meta").Rows(), 2) + require.Len(t, tk.MustQuery("show stats_meta where partition_name='global'").Rows(), 0) + require.Len(t, tk.MustQuery("show stats_buckets").Rows(), 4) // 2 partitions * (1 for the column_a and 1 for the index_a) + require.Len(t, tk.MustQuery("show stats_buckets where partition_name='global'").Rows(), 0) + require.Len(t, tk.MustQuery("show stats_histograms").Rows(), 4) + require.Len(t, tk.MustQuery("show stats_histograms where partition_name='global'").Rows(), 0) + require.Len(t, tk.MustQuery("show stats_healthy").Rows(), 2) + require.Len(t, tk.MustQuery("show stats_healthy where partition_name='global'").Rows(), 0) tk.MustExec("set @@tidb_analyze_version = 2") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec("analyze table t with 0 topn, 1 buckets") - c.Assert(len(tk.MustQuery("show stats_meta").Rows()), Equals, 3) - c.Assert(len(tk.MustQuery("show stats_meta where partition_name='global'").Rows()), Equals, 1) - c.Assert(len(tk.MustQuery("show stats_buckets").Rows()), Equals, 6) - c.Assert(len(tk.MustQuery("show stats_buckets where partition_name='global'").Rows()), Equals, 2) - c.Assert(len(tk.MustQuery("show stats_histograms").Rows()), Equals, 6) - c.Assert(len(tk.MustQuery("show stats_histograms where partition_name='global'").Rows()), Equals, 2) - c.Assert(len(tk.MustQuery("show stats_healthy").Rows()), Equals, 3) - c.Assert(len(tk.MustQuery("show stats_healthy where partition_name='global'").Rows()), Equals, 1) -} - -func (s *testStatsSuite) TestBuildGlobalLevelStats(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) + require.Len(t, tk.MustQuery("show stats_meta").Rows(), 3) + require.Len(t, tk.MustQuery("show stats_meta where partition_name='global'").Rows(), 1) + require.Len(t, tk.MustQuery("show stats_buckets").Rows(), 6) + require.Len(t, tk.MustQuery("show stats_buckets where partition_name='global'").Rows(), 2) + require.Len(t, tk.MustQuery("show stats_histograms").Rows(), 6) + require.Len(t, tk.MustQuery("show stats_histograms where partition_name='global'").Rows(), 2) + require.Len(t, tk.MustQuery("show stats_healthy").Rows(), 3) + require.Len(t, tk.MustQuery("show stats_healthy where partition_name='global'").Rows(), 1) +} + +func TestBuildGlobalLevelStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t, t1;") testKit.MustExec("set @@tidb_analyze_version = 2") @@ -839,50 +820,50 @@ func (s *testStatsSuite) TestBuildGlobalLevelStats(c *C) { testKit.MustExec("create index idx_t_b on t(b);") testKit.MustExec("analyze table t, t1;") result := testKit.MustQuery("show stats_meta where table_name = 't';").Sort() - c.Assert(len(result.Rows()), Equals, 3) - c.Assert(result.Rows()[0][5], Equals, "1") - c.Assert(result.Rows()[1][5], Equals, "2") - c.Assert(result.Rows()[2][5], Equals, "2") + require.Len(t, result.Rows(), 3) + require.Equal(t, "1", result.Rows()[0][5]) + require.Equal(t, "2", result.Rows()[1][5]) + require.Equal(t, "2", result.Rows()[2][5]) result = testKit.MustQuery("show stats_histograms where table_name = 't';").Sort() - c.Assert(len(result.Rows()), Equals, 15) + require.Len(t, result.Rows(), 15) result = testKit.MustQuery("show stats_meta where table_name = 't1';").Sort() - c.Assert(len(result.Rows()), Equals, 1) - c.Assert(result.Rows()[0][5], Equals, "5") + require.Len(t, result.Rows(), 1) + require.Equal(t, "5", result.Rows()[0][5]) result = testKit.MustQuery("show stats_histograms where table_name = 't1';").Sort() - c.Assert(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) // Test the 'dynamic' mode testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic';") testKit.MustExec("analyze table t, t1;") result = testKit.MustQuery("show stats_meta where table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 4) - c.Assert(result.Rows()[0][5], Equals, "5") - c.Assert(result.Rows()[1][5], Equals, "1") - c.Assert(result.Rows()[2][5], Equals, "2") - c.Assert(result.Rows()[3][5], Equals, "2") + require.Len(t, result.Rows(), 4) + require.Equal(t, "5", result.Rows()[0][5]) + require.Equal(t, "1", result.Rows()[1][5]) + require.Equal(t, "2", result.Rows()[2][5]) + require.Equal(t, "2", result.Rows()[3][5]) result = testKit.MustQuery("show stats_histograms where table_name = 't';").Sort() - c.Assert(len(result.Rows()), Equals, 20) + require.Len(t, result.Rows(), 20) result = testKit.MustQuery("show stats_meta where table_name = 't1';").Sort() - c.Assert(len(result.Rows()), Equals, 1) - c.Assert(result.Rows()[0][5], Equals, "5") + require.Len(t, result.Rows(), 1) + require.Equal(t, "5", result.Rows()[0][5]) result = testKit.MustQuery("show stats_histograms where table_name = 't1';").Sort() - c.Assert(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) testKit.MustExec("analyze table t index idx_t_ab, idx_t_b;") result = testKit.MustQuery("show stats_meta where table_name = 't'").Sort() - c.Assert(len(result.Rows()), Equals, 4) - c.Assert(result.Rows()[0][5], Equals, "5") - c.Assert(result.Rows()[1][5], Equals, "1") - c.Assert(result.Rows()[2][5], Equals, "2") - c.Assert(result.Rows()[3][5], Equals, "2") + require.Len(t, result.Rows(), 4) + require.Equal(t, "5", result.Rows()[0][5]) + require.Equal(t, "1", result.Rows()[1][5]) + require.Equal(t, "2", result.Rows()[2][5]) + require.Equal(t, "2", result.Rows()[3][5]) result = testKit.MustQuery("show stats_histograms where table_name = 't';").Sort() - c.Assert(len(result.Rows()), Equals, 20) + require.Len(t, result.Rows(), 20) } // nolint:unused -func (s *testSerialStatsSuite) prepareForGlobalStatsWithOpts(c *C, tk *testkit.TestKit, tblName, dbName string) { +func prepareForGlobalStatsWithOpts(t *testing.T, dom *domain.Domain, tk *testkit.TestKit, tblName, dbName string) { tk.MustExec("create database if not exists " + dbName) tk.MustExec("use " + dbName) tk.MustExec("drop table if exists " + tblName) @@ -902,25 +883,25 @@ func (s *testSerialStatsSuite) prepareForGlobalStatsWithOpts(c *C, tk *testkit.T tk.MustExec(buf2.String()) tk.MustExec("set @@tidb_analyze_version=2") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) } // nolint:unused -func (s *testSerialStatsSuite) checkForGlobalStatsWithOpts(c *C, tk *testkit.TestKit, db, t, p string, topn, buckets int) { - tbl, err := s.do.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(t)) - c.Assert(err, IsNil) +func checkForGlobalStatsWithOpts(t *testing.T, dom *domain.Domain, db, tt, pp string, topn, buckets int) { + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(tt)) + require.NoError(t, err) tblInfo := tbl.Meta() physicalID := tblInfo.ID - if p != "global" { + if pp != "global" { for _, def := range tbl.Meta().GetPartitionInfo().Definitions { - if def.Name.L == p { + if def.Name.L == pp { physicalID = def.ID } } } - tblStats, err := s.do.StatsHandle().TableStatsFromStorage(tblInfo, physicalID, true, 0) - c.Assert(err, IsNil) + tblStats, err := dom.StatsHandle().TableStatsFromStorage(tblInfo, physicalID, true, 0) + require.NoError(t, err) delta := buckets/2 + 10 for _, idxStats := range tblStats.Indices { @@ -928,9 +909,9 @@ func (s *testSerialStatsSuite) checkForGlobalStatsWithOpts(c *C, tk *testkit.Tes numBuckets := len(idxStats.Buckets) // since the hist-building algorithm doesn't stipulate the final bucket number to be equal to the expected number exactly, // we have to check the results by a range here. - c.Assert(numTopN, Equals, topn) - c.Assert(numBuckets, GreaterEqual, buckets-delta) - c.Assert(numBuckets, LessEqual, buckets+delta) + require.Equal(t, topn, numTopN) + require.GreaterOrEqual(t, numBuckets, buckets-delta) + require.LessOrEqual(t, numBuckets, buckets+delta) } for _, colStats := range tblStats.Columns { if len(colStats.Buckets) == 0 { @@ -938,19 +919,21 @@ func (s *testSerialStatsSuite) checkForGlobalStatsWithOpts(c *C, tk *testkit.Tes } numTopN := colStats.TopN.Num() numBuckets := len(colStats.Buckets) - c.Assert(numTopN, Equals, topn) - c.Assert(numBuckets, GreaterEqual, buckets-delta) - c.Assert(numBuckets, LessEqual, buckets+delta) + require.Equal(t, topn, numTopN) + require.GreaterOrEqual(t, numBuckets, buckets-delta) + require.LessOrEqual(t, numBuckets, buckets+delta) } } -func (s *testSerialStatsSuite) TestAnalyzeGlobalStatsWithOpts(c *C) { +func TestAnalyzeGlobalStatsWithOpts1(t *testing.T) { + t.Skip("unstable test") if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") + t.Skip("exhaustive types test, skip race test") } - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - s.prepareForGlobalStatsWithOpts(c, tk, "test_gstats_opt", "test_gstats_opt") + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + prepareForGlobalStatsWithOpts(t, dom, tk, "test_gstats_opt", "test_gstats_opt") // nolint:unused type opt struct { @@ -973,49 +956,57 @@ func (s *testSerialStatsSuite) TestAnalyzeGlobalStatsWithOpts(c *C) { sql := fmt.Sprintf("analyze table test_gstats_opt with %v topn, %v buckets", ca.topn, ca.buckets) if !ca.err { tk.MustExec(sql) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt", "test_gstats_opt", "global", ca.topn, ca.buckets) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt", "test_gstats_opt", "p0", ca.topn, ca.buckets) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt", "test_gstats_opt", "p1", ca.topn, ca.buckets) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt", "test_gstats_opt", "global", ca.topn, ca.buckets) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt", "test_gstats_opt", "p0", ca.topn, ca.buckets) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt", "test_gstats_opt", "p1", ca.topn, ca.buckets) } else { err := tk.ExecToErr(sql) - c.Assert(err, NotNil) + require.Error(t, err) } } } -func (s *testSerialStatsSuite) TestAnalyzeGlobalStatsWithOpts2(c *C) { +func TestAnalyzeGlobalStatsWithOpts2(t *testing.T) { + t.Skip("unstable test") if israce.RaceEnabled { - c.Skip("exhaustive types test, skip race test") + t.Skip("exhaustive types test, skip race test") } - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - s.prepareForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2") + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + }() + tk.MustExec("set global tidb_persist_analyze_options=false") + prepareForGlobalStatsWithOpts(t, dom, tk, "test_gstats_opt2", "test_gstats_opt2") tk.MustExec("analyze table test_gstats_opt2 with 20 topn, 50 buckets, 1000 samples") - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "global", 2, 50) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p0", 1, 50) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p1", 1, 50) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "global", 2, 50) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p0", 1, 50) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p1", 1, 50) // analyze a partition to let its options be different with others' tk.MustExec("analyze table test_gstats_opt2 partition p0 with 10 topn, 20 buckets") - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "global", 10, 20) // use new options - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p0", 10, 20) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p1", 1, 50) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "global", 10, 20) // use new options + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p0", 10, 20) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p1", 1, 50) tk.MustExec("analyze table test_gstats_opt2 partition p1 with 100 topn, 200 buckets") - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "global", 100, 200) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p0", 10, 20) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p1", 100, 200) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "global", 100, 200) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p0", 10, 20) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p1", 100, 200) tk.MustExec("analyze table test_gstats_opt2 partition p0 with 20 topn") // change back to 20 topn - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "global", 20, 256) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p0", 20, 256) - s.checkForGlobalStatsWithOpts(c, tk, "test_gstats_opt2", "test_gstats_opt2", "p1", 100, 200) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "global", 20, 256) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p0", 20, 256) + checkForGlobalStatsWithOpts(t, dom, "test_gstats_opt2", "test_gstats_opt2", "p1", 100, 200) } -func (s *testStatsSuite) TestGlobalStatsHealthy(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsHealthy(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(` @@ -1030,12 +1021,12 @@ partition by range (a) ( checkModifyAndCount := func(gModify, gCount, p0Modify, p0Count, p1Modify, p1Count int) { rs := tk.MustQuery("show stats_meta").Rows() - c.Assert(rs[0][4].(string), Equals, fmt.Sprintf("%v", gModify)) // global.modify_count - c.Assert(rs[0][5].(string), Equals, fmt.Sprintf("%v", gCount)) // global.row_count - c.Assert(rs[1][4].(string), Equals, fmt.Sprintf("%v", p0Modify)) // p0.modify_count - c.Assert(rs[1][5].(string), Equals, fmt.Sprintf("%v", p0Count)) // p0.row_count - c.Assert(rs[2][4].(string), Equals, fmt.Sprintf("%v", p1Modify)) // p1.modify_count - c.Assert(rs[2][5].(string), Equals, fmt.Sprintf("%v", p1Count)) // p1.row_count + require.Equal(t, fmt.Sprintf("%v", gModify), rs[0][4].(string)) // global.modify_count + require.Equal(t, fmt.Sprintf("%v", gCount), rs[0][5].(string)) // global.row_count + require.Equal(t, fmt.Sprintf("%v", p0Modify), rs[1][4].(string)) // p0.modify_count + require.Equal(t, fmt.Sprintf("%v", p0Count), rs[1][5].(string)) // p0.row_count + require.Equal(t, fmt.Sprintf("%v", p1Modify), rs[2][4].(string)) // p1.modify_count + require.Equal(t, fmt.Sprintf("%v", p1Count), rs[2][5].(string)) // p1.row_count } checkHealthy := func(gH, p0H, p1H int) { tk.MustQuery("show stats_healthy").Check(testkit.Rows( @@ -1051,14 +1042,14 @@ partition by range (a) ( checkHealthy(100, 100, 100) tk.MustExec("insert into t values (1), (2)") // update p0 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) checkModifyAndCount(2, 2, 2, 2, 0, 0) checkHealthy(0, 0, 100) tk.MustExec("insert into t values (11), (12), (13), (14)") // update p1 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) checkModifyAndCount(6, 6, 2, 2, 4, 4) checkHealthy(0, 0, 0) @@ -1067,26 +1058,28 @@ partition by range (a) ( checkHealthy(100, 100, 100) tk.MustExec("insert into t values (4), (5), (15), (16)") // update p0 and p1 together - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) checkModifyAndCount(4, 10, 2, 4, 2, 6) checkHealthy(60, 50, 66) } -func (s *testStatsSuite) TestHideGlobalStatsSwitch(c *C) { +func TestHideGlobalStatsSwitch(t *testing.T) { // NOTICE: remove this test when this global-stats is GA. - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) rs := tk.MustQuery("show variables").Rows() for _, r := range rs { - c.Assert(strings.ToLower(r[0].(string)), Not(Equals), "tidb_partition_prune_mode") + require.NotEqual(t, "tidb_partition_prune_mode", strings.ToLower(r[0].(string))) } - c.Assert(len(tk.MustQuery("show variables where variable_name like '%tidb_partition_prune_mode%'").Rows()), Equals, 0) + require.Len(t, tk.MustQuery("show variables where variable_name like '%tidb_partition_prune_mode%'").Rows(), 0) } -func (s *testStatsSuite) TestGlobalStatsData(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsData(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(` @@ -1101,7 +1094,7 @@ partition by range (a) ( tk.MustExec("set @@tidb_analyze_version=2") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("insert into t values (1), (2), (3), (4), (5), (6), (6), (null), (11), (12), (13), (14), (15), (16), (17), (18), (19), (19)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table t with 0 topn, 2 buckets") tk.MustQuery("select modify_count, count from mysql.stats_meta order by table_id asc").Check( @@ -1130,9 +1123,10 @@ partition by range (a) ( "test t p1 a 1 1 10 2 17 19 0")) } -func (s *testStatsSuite) TestGlobalStatsData2(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsData2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("set @@tidb_analyze_version=2") @@ -1141,7 +1135,7 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { tk.MustExec("drop table if exists tint") tk.MustExec("create table tint (c int, key(c)) partition by range (c) (partition p0 values less than (10), partition p1 values less than (20))") tk.MustExec("insert into tint values (1), (2), (3), (4), (4), (5), (5), (5), (null), (11), (12), (13), (14), (15), (16), (16), (16), (16), (17), (17)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table tint with 2 topn, 2 buckets") tk.MustQuery("select modify_count, count from mysql.stats_meta order by table_id asc").Check(testkit.Rows( @@ -1200,13 +1194,13 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { tk.MustExec(`insert into tdouble values ` + `(1, 1), (2, 2), (3, 3), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (null, null), ` + // values in p0 `(11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (16, 16), (16, 16), (16, 16), (17, 17), (17, 17)`) // values in p1 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table tdouble with 2 topn, 2 buckets") rs := tk.MustQuery("show stats_meta where table_name='tdouble'").Rows() - c.Assert(rs[0][5].(string), Equals, "20") // g.count = p0.count + p1.count - c.Assert(rs[1][5].(string), Equals, "9") // p0.count - c.Assert(rs[2][5].(string), Equals, "11") // p1.count + require.Equal(t, "20", rs[0][5].(string)) // g.count = p0.count + p1.count + require.Equal(t, "9", rs[1][5].(string)) // p0.count + require.Equal(t, "11", rs[2][5].(string)) // p1.count tk.MustQuery("show stats_topn where table_name='tdouble' and is_index=0 and column_name='c'").Check(testkit.Rows( `test tdouble global c 0 5 3`, @@ -1234,12 +1228,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdouble p1 c 0 1 5 1 14 15 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdouble' and column_name='c' and is_index=0").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) tk.MustQuery("show stats_buckets where table_name='tdouble' and is_index=1 and column_name='c'").Check(testkit.Rows( // db, tbl, part, col, isIdx, bucketID, count, repeat, lower, upper, ndv @@ -1251,12 +1245,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdouble p1 c 1 1 5 1 14 15 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdouble' and column_name='c' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) // decimal + (column + index with 1 column) tk.MustExec("drop table if exists tdecimal") @@ -1265,13 +1259,13 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { tk.MustExec(`insert into tdecimal values ` + `(1, 1), (2, 2), (3, 3), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (null, null), ` + // values in p0 `(11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (16, 16), (16, 16), (16, 16), (17, 17), (17, 17)`) // values in p1 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table tdecimal with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tdecimal'").Rows() - c.Assert(rs[0][5].(string), Equals, "20") // g.count = p0.count + p1.count - c.Assert(rs[1][5].(string), Equals, "9") // p0.count - c.Assert(rs[2][5].(string), Equals, "11") // p1.count + require.Equal(t, "20", rs[0][5].(string)) // g.count = p0.count + p1.count + require.Equal(t, "9", rs[1][5].(string)) // p0.count + require.Equal(t, "11", rs[2][5].(string)) // p1.count tk.MustQuery("show stats_topn where table_name='tdecimal' and is_index=0 and column_name='c'").Check(testkit.Rows( `test tdecimal global c 0 5.00 3`, @@ -1299,12 +1293,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdecimal p1 c 0 1 5 1 14.00 15.00 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdecimal' and column_name='c' and is_index=0").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) tk.MustQuery("show stats_buckets where table_name='tdecimal' and is_index=1 and column_name='c'").Check(testkit.Rows( // db, tbl, part, col, isIdx, bucketID, count, repeat, lower, upper, ndv @@ -1316,12 +1310,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdecimal p1 c 1 1 5 1 14.00 15.00 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdecimal' and column_name='c' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) // datetime + (column + index with 1 column) tk.MustExec("drop table if exists tdatetime") @@ -1330,13 +1324,13 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { tk.MustExec(`insert into tdatetime values ` + `(1, '2000-01-01'), (2, '2000-01-02'), (3, '2000-01-03'), (4, '2000-01-04'), (4, '2000-01-04'), (5, '2000-01-05'), (5, '2000-01-05'), (5, '2000-01-05'), (null, null), ` + // values in p0 `(11, '2000-01-11'), (12, '2000-01-12'), (13, '2000-01-13'), (14, '2000-01-14'), (15, '2000-01-15'), (16, '2000-01-16'), (16, '2000-01-16'), (16, '2000-01-16'), (16, '2000-01-16'), (17, '2000-01-17'), (17, '2000-01-17')`) // values in p1 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table tdatetime with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tdatetime'").Rows() - c.Assert(rs[0][5].(string), Equals, "20") // g.count = p0.count + p1.count - c.Assert(rs[1][5].(string), Equals, "9") // p0.count - c.Assert(rs[2][5].(string), Equals, "11") // p1.count + require.Equal(t, "20", rs[0][5].(string)) // g.count = p0.count + p1.count + require.Equal(t, "9", rs[1][5].(string)) // p0.count + require.Equal(t, "11", rs[2][5].(string)) // p1.count tk.MustQuery("show stats_topn where table_name='tdatetime' and is_index=0 and column_name='c'").Check(testkit.Rows( `test tdatetime global c 0 2000-01-05 00:00:00 3`, @@ -1364,12 +1358,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdatetime p1 c 0 1 5 1 2000-01-14 00:00:00 2000-01-15 00:00:00 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdatetime' and column_name='c' and is_index=0").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) tk.MustQuery("show stats_buckets where table_name='tdatetime' and is_index=1 and column_name='c'").Check(testkit.Rows( // db, tbl, part, col, isIdx, bucketID, count, repeat, lower, upper, ndv @@ -1381,12 +1375,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tdatetime p1 c 1 1 5 1 2000-01-14 00:00:00 2000-01-15 00:00:00 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdatetime' and column_name='c' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) // string + (column + index with 1 column) tk.MustExec("drop table if exists tstring") @@ -1395,13 +1389,13 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { tk.MustExec(`insert into tstring values ` + `(1, 'a1'), (2, 'a2'), (3, 'a3'), (4, 'a4'), (4, 'a4'), (5, 'a5'), (5, 'a5'), (5, 'a5'), (null, null), ` + // values in p0 `(11, 'b11'), (12, 'b12'), (13, 'b13'), (14, 'b14'), (15, 'b15'), (16, 'b16'), (16, 'b16'), (16, 'b16'), (16, 'b16'), (17, 'b17'), (17, 'b17')`) // values in p1 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table tstring with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tstring'").Rows() - c.Assert(rs[0][5].(string), Equals, "20") // g.count = p0.count + p1.count - c.Assert(rs[1][5].(string), Equals, "9") // p0.count - c.Assert(rs[2][5].(string), Equals, "11") // p1.count + require.Equal(t, "20", rs[0][5].(string)) // g.count = p0.count + p1.count + require.Equal(t, "9", rs[1][5].(string)) // p0.count + require.Equal(t, "11", rs[2][5].(string)) // p1.count tk.MustQuery("show stats_topn where table_name='tstring' and is_index=0 and column_name='c'").Check(testkit.Rows( `test tstring global c 0 a5 3`, @@ -1429,12 +1423,12 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tstring p1 c 0 1 5 1 b14 b15 0")) rs = tk.MustQuery("show stats_histograms where table_name='tstring' and column_name='c' and is_index=0").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) tk.MustQuery("show stats_buckets where table_name='tstring' and is_index=1 and column_name='c'").Check(testkit.Rows( // db, tbl, part, col, isIdx, bucketID, count, repeat, lower, upper, ndv @@ -1446,17 +1440,18 @@ func (s *testStatsSuite) TestGlobalStatsData2(c *C) { "test tstring p1 c 1 1 5 1 b14 b15 0")) rs = tk.MustQuery("show stats_histograms where table_name='tstring' and column_name='c' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "12") // g.ndv = p0 + p1 - c.Assert(rs[1][6].(string), Equals, "5") - c.Assert(rs[2][6].(string), Equals, "7") - c.Assert(rs[0][7].(string), Equals, "1") // g.null_count = p0 + p1 - c.Assert(rs[1][7].(string), Equals, "1") - c.Assert(rs[2][7].(string), Equals, "0") -} - -func (s *testStatsSuite) TestGlobalStatsData3(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) + require.Equal(t, "12", rs[0][6].(string)) // g.ndv = p0 + p1 + require.Equal(t, "5", rs[1][6].(string)) + require.Equal(t, "7", rs[2][6].(string)) + require.Equal(t, "1", rs[0][7].(string)) // g.null_count = p0 + p1 + require.Equal(t, "1", rs[1][7].(string)) + require.Equal(t, "0", rs[2][7].(string)) +} + +func TestGlobalStatsData3(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("set @@tidb_analyze_version=2") @@ -1470,9 +1465,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { tk.MustExec("analyze table tintint with 2 topn, 2 buckets") rs := tk.MustQuery("show stats_meta where table_name='tintint'").Rows() - c.Assert(rs[0][5].(string), Equals, "17") // g.total = p0.total + p1.total - c.Assert(rs[1][5].(string), Equals, "9") - c.Assert(rs[2][5].(string), Equals, "8") + require.Equal(t, "17", rs[0][5].(string)) // g.total = p0.total + p1.total + require.Equal(t, "9", rs[1][5].(string)) + require.Equal(t, "8", rs[2][5].(string)) tk.MustQuery("show stats_topn where table_name='tintint' and is_index=1").Check(testkit.Rows( "test tintint global a 1 (3, 1) 3", @@ -1491,9 +1486,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { "test tintint p1 a 1 1 3 1 (12, 2) (12, 2) 0")) rs = tk.MustQuery("show stats_histograms where table_name='tintint' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "11") // g.ndv = p0.ndv + p1.ndv - c.Assert(rs[1][6].(string), Equals, "6") - c.Assert(rs[2][6].(string), Equals, "5") + require.Equal(t, "11", rs[0][6].(string)) // g.ndv = p0.ndv + p1.ndv + require.Equal(t, "6", rs[1][6].(string)) + require.Equal(t, "5", rs[2][6].(string)) // index(int, string) tk.MustExec("drop table if exists tintstr") @@ -1504,9 +1499,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { tk.MustExec("analyze table tintstr with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tintstr'").Rows() - c.Assert(rs[0][5].(string), Equals, "17") // g.total = p0.total + p1.total - c.Assert(rs[1][5].(string), Equals, "9") - c.Assert(rs[2][5].(string), Equals, "8") + require.Equal(t, "17", rs[0][5].(string)) // g.total = p0.total + p1.total + require.Equal(t, "9", rs[1][5].(string)) + require.Equal(t, "8", rs[2][5].(string)) tk.MustQuery("show stats_topn where table_name='tintstr' and is_index=1").Check(testkit.Rows( "test tintstr global a 1 (3, 1) 3", @@ -1525,9 +1520,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { "test tintstr p1 a 1 1 3 1 (12, 2) (12, 2) 0")) rs = tk.MustQuery("show stats_histograms where table_name='tintstr' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "11") // g.ndv = p0.ndv + p1.ndv - c.Assert(rs[1][6].(string), Equals, "6") - c.Assert(rs[2][6].(string), Equals, "5") + require.Equal(t, "11", rs[0][6].(string)) // g.ndv = p0.ndv + p1.ndv + require.Equal(t, "6", rs[1][6].(string)) + require.Equal(t, "5", rs[2][6].(string)) // index(int, double) tk.MustExec("drop table if exists tintdouble") @@ -1538,9 +1533,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { tk.MustExec("analyze table tintdouble with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tintdouble'").Rows() - c.Assert(rs[0][5].(string), Equals, "17") // g.total = p0.total + p1.total - c.Assert(rs[1][5].(string), Equals, "9") - c.Assert(rs[2][5].(string), Equals, "8") + require.Equal(t, "17", rs[0][5].(string)) // g.total = p0.total + p1.total + require.Equal(t, "9", rs[1][5].(string)) + require.Equal(t, "8", rs[2][5].(string)) tk.MustQuery("show stats_topn where table_name='tintdouble' and is_index=1").Check(testkit.Rows( "test tintdouble global a 1 (3, 1) 3", @@ -1559,9 +1554,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { "test tintdouble p1 a 1 1 3 1 (12, 2) (12, 2) 0")) rs = tk.MustQuery("show stats_histograms where table_name='tintdouble' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "11") // g.ndv = p0.ndv + p1.ndv - c.Assert(rs[1][6].(string), Equals, "6") - c.Assert(rs[2][6].(string), Equals, "5") + require.Equal(t, "11", rs[0][6].(string)) // g.ndv = p0.ndv + p1.ndv + require.Equal(t, "6", rs[1][6].(string)) + require.Equal(t, "5", rs[2][6].(string)) // index(double, decimal) tk.MustExec("drop table if exists tdoubledecimal") @@ -1572,9 +1567,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { tk.MustExec("analyze table tdoubledecimal with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tdoubledecimal'").Rows() - c.Assert(rs[0][5].(string), Equals, "17") // g.total = p0.total + p1.total - c.Assert(rs[1][5].(string), Equals, "9") - c.Assert(rs[2][5].(string), Equals, "8") + require.Equal(t, "17", rs[0][5].(string)) // g.total = p0.total + p1.total + require.Equal(t, "9", rs[1][5].(string)) + require.Equal(t, "8", rs[2][5].(string)) tk.MustQuery("show stats_topn where table_name='tdoubledecimal' and is_index=1").Check(testkit.Rows( "test tdoubledecimal global a 1 (3, 1.00) 3", @@ -1593,9 +1588,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { "test tdoubledecimal p1 a 1 1 3 1 (12, 2.00) (12, 2.00) 0")) rs = tk.MustQuery("show stats_histograms where table_name='tdoubledecimal' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "11") // g.ndv = p0.ndv + p1.ndv - c.Assert(rs[1][6].(string), Equals, "6") - c.Assert(rs[2][6].(string), Equals, "5") + require.Equal(t, "11", rs[0][6].(string)) // g.ndv = p0.ndv + p1.ndv + require.Equal(t, "6", rs[1][6].(string)) + require.Equal(t, "5", rs[2][6].(string)) // index(string, datetime) tk.MustExec("drop table if exists tstrdt") @@ -1606,9 +1601,9 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { tk.MustExec("analyze table tstrdt with 2 topn, 2 buckets") rs = tk.MustQuery("show stats_meta where table_name='tstrdt'").Rows() - c.Assert(rs[0][5].(string), Equals, "17") // g.total = p0.total + p1.total - c.Assert(rs[1][5].(string), Equals, "9") - c.Assert(rs[2][5].(string), Equals, "8") + require.Equal(t, "17", rs[0][5].(string)) // g.total = p0.total + p1.total + require.Equal(t, "9", rs[1][5].(string)) + require.Equal(t, "8", rs[2][5].(string)) tk.MustQuery("show stats_topn where table_name='tstrdt' and is_index=1").Check(testkit.Rows( "test tstrdt global a 1 (3, 2000-01-01 00:00:00) 3", @@ -1627,14 +1622,15 @@ func (s *testStatsSuite) TestGlobalStatsData3(c *C) { "test tstrdt p1 a 1 1 3 1 (12, 2000-01-02 00:00:00) (12, 2000-01-02 00:00:00) 0")) rs = tk.MustQuery("show stats_histograms where table_name='tstrdt' and is_index=1").Rows() - c.Assert(rs[0][6].(string), Equals, "11") // g.ndv = p0.ndv + p1.ndv - c.Assert(rs[1][6].(string), Equals, "6") - c.Assert(rs[2][6].(string), Equals, "5") + require.Equal(t, "11", rs[0][6].(string)) // g.ndv = p0.ndv + p1.ndv + require.Equal(t, "6", rs[1][6].(string)) + require.Equal(t, "5", rs[2][6].(string)) } -func (s *testStatsSuite) TestGlobalStatsVersion(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsVersion(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec(` @@ -1646,62 +1642,63 @@ partition by range (a) ( partition p1 values less than (20) )`) tk.MustExec("insert into t values (1), (5), (null), (11), (15)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("set @@tidb_partition_prune_mode='static'") tk.MustExec("set @@session.tidb_analyze_version=1") tk.MustExec("analyze table t") // both p0 and p1 are in ver1 - c.Assert(len(tk.MustQuery("show stats_meta").Rows()), Equals, 2) + require.Len(t, tk.MustQuery("show stats_meta").Rows(), 2) tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("set @@session.tidb_analyze_version=1") err := tk.ExecToErr("analyze table t") // try to build global-stats on ver1 - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") tk.MustExec("set @@session.tidb_analyze_version=2") err = tk.ExecToErr("analyze table t partition p1") // only analyze p1 to let it in ver2 while p0 is in ver1 - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("analyze table t") // both p0 and p1 are in ver2 - c.Assert(len(tk.MustQuery("show stats_meta").Rows()), Equals, 3) + require.Len(t, tk.MustQuery("show stats_meta").Rows(), 3) // If we already have global-stats, we can get the latest global-stats by analyzing the newly added partition. tk.MustExec("alter table t add partition (partition p2 values less than (30))") tk.MustExec("insert t values (13), (14), (22), (23)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table t partition p2") // it will success since p0 and p1 are both in ver2 - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - do := s.do + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + do := dom is := do.InfoSchema() h := do.StatsHandle() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() globalStats := h.GetTableStats(tableInfo) // global.count = p0.count(3) + p1.count(2) + p2.count(2) // We did not analyze partition p1, so the value here has not changed - c.Assert(globalStats.Count, Equals, int64(7)) + require.Equal(t, int64(7), globalStats.Count) tk.MustExec("analyze table t partition p1;") globalStats = h.GetTableStats(tableInfo) // global.count = p0.count(3) + p1.count(4) + p2.count(4) // The value of p1.Count is correct now. - c.Assert(globalStats.Count, Equals, int64(9)) - c.Assert(globalStats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(9), globalStats.Count) + require.Equal(t, int64(0), globalStats.ModifyCount) tk.MustExec("alter table t drop partition p2;") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) tk.MustExec("analyze table t;") globalStats = h.GetTableStats(tableInfo) // global.count = p0.count(3) + p1.count(4) - c.Assert(globalStats.Count, Equals, int64(7)) + require.Equal(t, int64(7), globalStats.Count) } -func (s *testSerialStatsSuite) TestDDLPartition4GlobalStats(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestDDLPartition4GlobalStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("set @@session.tidb_analyze_version=2") @@ -1714,57 +1711,58 @@ func (s *testSerialStatsSuite) TestDDLPartition4GlobalStats(c *C) { partition p4 values less than (50), partition p5 values less than (60) )`) - do := s.do + do := dom is := do.InfoSchema() h := do.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) tk.MustExec("insert into t values (1), (2), (3), (4), (5), " + "(11), (21), (31), (41), (51)," + "(12), (22), (32), (42), (52);") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tk.MustExec("analyze table t") result := tk.MustQuery("show stats_meta where table_name = 't';").Rows() - c.Assert(len(result), Equals, 7) + require.Len(t, result, 7) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() globalStats := h.GetTableStats(tableInfo) - c.Assert(globalStats.Count, Equals, int64(15)) + require.Equal(t, int64(15), globalStats.Count) tk.MustExec("alter table t drop partition p3, p5;") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + require.NoError(t, h.Update(is)) result = tk.MustQuery("show stats_meta where table_name = 't';").Rows() - c.Assert(len(result), Equals, 5) + require.Len(t, result, 5) // The value of global.count will be updated automatically after we drop the table partition. globalStats = h.GetTableStats(tableInfo) - c.Assert(globalStats.Count, Equals, int64(11)) + require.Equal(t, int64(11), globalStats.Count) tk.MustExec("alter table t truncate partition p2, p4;") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + require.NoError(t, h.Update(is)) // The value of global.count will not be updated automatically when we truncate the table partition. // Because the partition-stats in the partition table which have been truncated has not been updated. globalStats = h.GetTableStats(tableInfo) - c.Assert(globalStats.Count, Equals, int64(11)) + require.Equal(t, int64(11), globalStats.Count) tk.MustExec("analyze table t;") result = tk.MustQuery("show stats_meta where table_name = 't';").Rows() // The truncate operation only delete the data from the partition p2 and p4. It will not delete the partition-stats. - c.Assert(len(result), Equals, 5) + require.Len(t, result, 5) // The result for the globalStats.count will be right now globalStats = h.GetTableStats(tableInfo) - c.Assert(globalStats.Count, Equals, int64(7)) + require.Equal(t, int64(7), globalStats.Count) } -func (s *testStatsSuite) TestMergeGlobalTopN(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestMergeGlobalTopN(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") tk.MustExec("drop table if exists t;") tk.MustExec("set @@session.tidb_analyze_version=2;") @@ -1798,81 +1796,84 @@ func (s *testStatsSuite) TestMergeGlobalTopN(c *C) { ("test t global b 1 3 5"))) } -func (s *testStatsSuite) TestExtendedStatsDefaultSwitch(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtendedStatsDefaultSwitch(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int primary key, b int, c int, d int)") err := tk.ExecToErr("alter table t add stats_extended s1 correlation(b,c)") - c.Assert(err.Error(), Equals, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF") + require.Equal(t, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF", err.Error()) err = tk.ExecToErr("alter table t drop stats_extended s1") - c.Assert(err.Error(), Equals, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF") + require.Equal(t, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF", err.Error()) err = tk.ExecToErr("admin reload stats_extended") - c.Assert(err.Error(), Equals, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF") + require.Equal(t, "Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF", err.Error()) } -func (s *testStatsSuite) TestExtendedStatsOps(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtendedStatsOps(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int primary key, b int, c int, d int)") tk.MustExec("insert into t values(1,1,5,1),(2,2,4,2),(3,3,3,3),(4,4,2,4),(5,5,1,5)") tk.MustExec("analyze table t") err := tk.ExecToErr("alter table not_exist_db.t add stats_extended s1 correlation(b,c)") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'not_exist_db.t' doesn't exist") + require.Equal(t, "[schema:1146]Table 'not_exist_db.t' doesn't exist", err.Error()) err = tk.ExecToErr("alter table not_exist_tbl add stats_extended s1 correlation(b,c)") - c.Assert(err.Error(), Equals, "[schema:1146]Table 'test.not_exist_tbl' doesn't exist") + require.Equal(t, "[schema:1146]Table 'test.not_exist_tbl' doesn't exist", err.Error()) err = tk.ExecToErr("alter table t add stats_extended s1 correlation(b,e)") - c.Assert(err.Error(), Equals, "[schema:1054]Unknown column 'e' in 't'") + require.Equal(t, "[schema:1054]Unknown column 'e' in 't'", err.Error()) tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustQuery("show warnings").Check(testkit.Rows( "Warning 1105 No need to create correlation statistics on the integer primary key column", )) tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows()) err = tk.ExecToErr("alter table t add stats_extended s1 correlation(b,c,d)") - c.Assert(err.Error(), Equals, "Only support Correlation and Dependency statistics types on 2 columns") + require.Equal(t, "Only support Correlation and Dependency statistics types on 2 columns", err.Error()) tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows()) tk.MustExec("alter table t add stats_extended s1 correlation(b,c)") tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows( "2 [2,3] 0", )) - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) tk.MustExec("update mysql.stats_extended set status = 1 where name = 's1'") do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 1) tk.MustExec("alter table t drop stats_extended s1") tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows( "2 [2,3] 2", )) err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) } -func (s *testStatsSuite) TestAdminReloadStatistics1(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAdminReloadStatistics1(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int primary key, b int, c int, d int)") @@ -1882,43 +1883,44 @@ func (s *testStatsSuite) TestAdminReloadStatistics1(c *C) { tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows( "2 [2,3] 0", )) - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) tk.MustExec("update mysql.stats_extended set status = 1 where name = 's1'") do.StatsHandle().Clear() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 1) tk.MustExec("delete from mysql.stats_extended where name = 's1'") err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 1) tk.MustExec("admin reload stats_extended") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) } -func (s *testStatsSuite) TestAdminReloadStatistics2(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAdminReloadStatistics2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -1929,24 +1931,25 @@ func (s *testStatsSuite) TestAdminReloadStatistics2(c *C) { "1.000000 1", )) rows := tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) tk.MustExec("delete from mysql.stats_extended where name = 's1'") - is := s.do.InfoSchema() - s.do.StatsHandle().Update(is) + is := dom.InfoSchema() + dom.StatsHandle().Update(is) tk.MustQuery("select stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows()) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) tk.MustExec("admin reload stats_extended") tk.MustQuery("select stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows()) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testStatsSuite) TestCorrelationStatsCompute(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestCorrelationStatsCompute(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int, c int)") @@ -1959,17 +1962,17 @@ func (s *testStatsSuite) TestCorrelationStatsCompute(c *C) { "2 [1,2] 0", "2 [1,3] 0", )) - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) tk.MustExec("analyze table t") tk.MustQuery("select type, column_ids, stats, status from mysql.stats_extended").Sort().Check(testkit.Rows( @@ -1983,25 +1986,25 @@ func (s *testStatsSuite) TestCorrelationStatsCompute(c *C) { "2 [1,3] -1.000000 1", )) err = do.StatsHandle().Update(is) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 2) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 2) foundS1, foundS2 := false, false for name, item := range statsTbl.ExtendedStats.Stats { switch name { case "s1": foundS1 = true - c.Assert(item.ScalarVals, Equals, float64(1)) + require.Equal(t, float64(1), item.ScalarVals) case "s2": foundS2 = true - c.Assert(item.ScalarVals, Equals, float64(-1)) + require.Equal(t, float64(-1), item.ScalarVals) default: - c.Assert("Unexpected extended stats in cache", IsNil) + require.FailNow(t, "Unexpected extended stats in cache") } } - c.Assert(foundS1 && foundS2, IsTrue) + require.True(t, foundS1 && foundS2) // Check that table with NULLs won't cause panic tk.MustExec("delete from t") @@ -2033,41 +2036,43 @@ func (s *testStatsSuite) TestCorrelationStatsCompute(c *C) { )) } -func (s *testStatsSuite) TestSyncStatsExtendedRemoval(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestSyncStatsExtendedRemoval(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values(1,1),(2,2),(3,3)") tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustExec("analyze table t") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl := do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 1) item := statsTbl.ExtendedStats.Stats["s1"] - c.Assert(item, NotNil) + require.NotNil(t, item) result := tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) tk.MustExec("alter table t drop stats_extended s1") statsTbl = do.StatsHandle().GetTableStats(tableInfo) - c.Assert(statsTbl, NotNil) - c.Assert(statsTbl.ExtendedStats, NotNil) - c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0) + require.NotNil(t, statsTbl) + require.NotNil(t, statsTbl.ExtendedStats) + require.Len(t, statsTbl.ExtendedStats.Stats, 0) result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) } -func (s *testStatsSuite) TestStaticPartitionPruneMode(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestStaticPartitionPruneMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Static) + "'") tk.MustExec("use test") tk.MustExec(`create table t (a int, key(a)) partition by range(a) @@ -2075,22 +2080,23 @@ func (s *testStatsSuite) TestStaticPartitionPruneMode(c *C) { partition p1 values less than (22))`) tk.MustExec(`insert into t values (1), (2), (3), (10), (11)`) tk.MustExec(`analyze table t`) - c.Assert(tk.MustNoGlobalStats("t"), IsTrue) + require.True(t, tk.MustNoGlobalStats("t")) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Dynamic) + "'") - c.Assert(tk.MustNoGlobalStats("t"), IsTrue) + require.True(t, tk.MustNoGlobalStats("t")) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Static) + "'") tk.MustExec(`insert into t values (4), (5), (6)`) tk.MustExec(`analyze table t partition p0`) - c.Assert(tk.MustNoGlobalStats("t"), IsTrue) + require.True(t, tk.MustNoGlobalStats("t")) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Dynamic) + "'") - c.Assert(tk.MustNoGlobalStats("t"), IsTrue) + require.True(t, tk.MustNoGlobalStats("t")) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Static) + "'") } -func (s *testStatsSuite) TestMergeIdxHist(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestMergeIdxHist(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Dynamic) + "'") defer tk.MustExec("set @@tidb_partition_prune_mode='" + string(variable.Static) + "'") tk.MustExec("use test") @@ -2105,12 +2111,13 @@ func (s *testStatsSuite) TestMergeIdxHist(c *C) { tk.MustExec("analyze table t with 2 topn, 2 buckets") rows := tk.MustQuery("show stats_buckets where partition_name like 'global'") - c.Assert(len(rows.Rows()), Equals, 4) + require.Len(t, rows.Rows(), 4) } -func (s *testStatsSuite) TestAnalyzeWithDynamicPartitionPruneMode(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAnalyzeWithDynamicPartitionPruneMode(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode = '" + string(variable.Dynamic) + "'") tk.MustExec("set @@tidb_analyze_version = 2") @@ -2120,28 +2127,29 @@ func (s *testStatsSuite) TestAnalyzeWithDynamicPartitionPruneMode(c *C) { tk.MustExec(`insert into t values (1), (2), (3), (10), (11)`) tk.MustExec(`analyze table t with 1 topn, 2 buckets`) rows := tk.MustQuery("show stats_buckets where partition_name = 'global' and is_index=1").Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(rows[1][6], Equals, "4") + require.Len(t, rows, 2) + require.Equal(t, "4", rows[1][6]) tk.MustExec("insert into t values (1), (2), (2)") tk.MustExec("analyze table t partition p0 with 1 topn, 2 buckets") rows = tk.MustQuery("show stats_buckets where partition_name = 'global' and is_index=1").Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(rows[1][6], Equals, "5") + require.Len(t, rows, 2) + require.Equal(t, "5", rows[1][6]) tk.MustExec("insert into t values (3)") tk.MustExec("analyze table t partition p0 index a with 1 topn, 2 buckets") rows = tk.MustQuery("show stats_buckets where partition_name = 'global' and is_index=1").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][6], Equals, "6") + require.Len(t, rows, 1) + require.Equal(t, "6", rows[0][6]) } -func (s *testStatsSuite) TestPartitionPruneModeSessionVariable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk1 := testkit.NewTestKit(c, s.store) +func TestPartitionPruneModeSessionVariable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") tk1.MustExec("set @@tidb_partition_prune_mode = '" + string(variable.Dynamic) + "'") tk1.MustExec(`set @@tidb_analyze_version=2`) - tk2 := testkit.NewTestKit(c, s.store) + tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") tk2.MustExec("set @@tidb_partition_prune_mode = '" + string(variable.Static) + "'") tk2.MustExec(`set @@tidb_analyze_version=2`) @@ -2191,9 +2199,10 @@ func (s *testStatsSuite) TestPartitionPruneModeSessionVariable(c *C) { )) } -func (s *testStatsSuite) TestFMSWithAnalyzePartition(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestFMSWithAnalyzePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode = '" + string(variable.Dynamic) + "'") tk.MustExec("set @@tidb_analyze_version = 2") @@ -2204,24 +2213,19 @@ func (s *testStatsSuite) TestFMSWithAnalyzePartition(c *C) { tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("0")) tk.MustExec("analyze table t partition p0 with 1 topn, 2 buckets") tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0.", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0", "Warning 8131 Build table: `t` global-level stats failed due to missing partition-level stats", "Warning 8131 Build table: `t` index: `a` global-level stats failed due to missing partition-level stats", )) tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("2")) } -var _ = SerialSuites(&statsSerialSuite{}) - -type statsSerialSuite struct { - testSuiteBase -} - -func (s *statsSerialSuite) TestIndexUsageInformation(c *C) { - defer cleanEnv(c, s.store, s.do) +func TestIndexUsageInformation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() session.SetIndexUsageSyncLease(1) defer session.SetIndexUsageSyncLease(0) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_idx(a int, b int)") tk.MustExec("create unique index idx_a on t_idx(a)") @@ -2234,9 +2238,9 @@ func (s *statsSerialSuite) TestIndexUsageInformation(c *C) { AND tables.tidb_table_id = stats.table_id AND idx.index_id = stats.index_id AND idx.table_name = "t_idx"` - do := s.do + do := dom err := do.StatsHandle().DumpIndexUsageToKV() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery(querySQL).Check(testkit.Rows( "test t_idx idx_a 1 0", )) @@ -2244,32 +2248,33 @@ func (s *statsSerialSuite) TestIndexUsageInformation(c *C) { tk.MustQuery("select a from t_idx where a=1") tk.MustQuery("select a from t_idx where a=1") err = do.StatsHandle().DumpIndexUsageToKV() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery(querySQL).Check(testkit.Rows( "test t_idx idx_a 3 2", )) tk.MustQuery("select b from t_idx where b=0") tk.MustQuery("select b from t_idx where b=0") err = do.StatsHandle().DumpIndexUsageToKV() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery(querySQL).Check(testkit.Rows( "test t_idx idx_a 3 2", "test t_idx idx_b 2 2", )) } -func (s *statsSerialSuite) TestGCIndexUsageInformation(c *C) { - defer cleanEnv(c, s.store, s.do) +func TestGCIndexUsageInformation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() session.SetIndexUsageSyncLease(1) defer session.SetIndexUsageSyncLease(0) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t_idx(a int, b int)") tk.MustExec("create unique index idx_a on t_idx(a)") tk.MustQuery("select a from t_idx where a=1") - do := s.do + do := dom err := do.StatsHandle().DumpIndexUsageToKV() - c.Assert(err, IsNil) + require.NoError(t, err) querySQL := `select count(distinct idx.table_schema, idx.table_name, idx.key_name, stats.query_count, stats.rows_selected) from mysql.schema_index_usage as stats, information_schema.tidb_indexes as idx, information_schema.tables as tables where tables.table_schema = idx.table_schema @@ -2280,13 +2285,14 @@ func (s *statsSerialSuite) TestGCIndexUsageInformation(c *C) { tk.MustQuery(querySQL).Check(testkit.Rows("1")) tk.MustExec("drop index `idx_a` on t_idx") err = do.StatsHandle().GCIndexUsage() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustQuery(querySQL).Check(testkit.Rows("0")) } -func (s *statsSerialSuite) TestFeedbackWithGlobalStats(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestFeedbackWithGlobalStats(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("set @@tidb_analyze_version = 1") @@ -2308,19 +2314,19 @@ func (s *statsSerialSuite) TestFeedbackWithGlobalStats(c *C) { testKit.MustQuery("show warnings").Check(testkit.Rows(`Error 1105 variable tidb_analyze_version not updated because analyze version 2 is incompatible with query feedback. Please consider setting feedback-probability to 0.0 in config file to disable query feedback`)) testKit.MustQuery("select @@tidb_analyze_version").Check(testkit.Rows("1")) - h := s.do.StatsHandle() + h := dom.StatsHandle() var err error // checkFeedbackOnPartitionTable is used to check whether the statistics are the same as before. checkFeedbackOnPartitionTable := func(statsBefore *statistics.Table, tblInfo *model.TableInfo) { - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) err = h.DumpStatsFeedbackToKV() - c.Assert(err, IsNil) - err = h.HandleUpdateStats(s.do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, err) + err = h.HandleUpdateStats(dom.InfoSchema()) + require.NoError(t, err) statsTblAfter := h.GetTableStats(tblInfo) // assert that statistics not changed // the feedback can not work for the partition table in both static and dynamic mode - assertTableEqual(c, statsBefore, statsTblAfter) + assertTableEqual(t, statsBefore, statsTblAfter) } // Case 2: Feedback wouldn't be applied on version 2 and global-level statistics. @@ -2333,13 +2339,13 @@ func (s *statsSerialSuite) TestFeedbackWithGlobalStats(c *C) { testKit.MustExec("insert into t values (1,2),(2,2),(4,5),(2,3),(3,4)") } testKit.MustExec("analyze table t with 0 topn") - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() testKit.MustExec("analyze table t") - err = h.Update(s.do.InfoSchema()) - c.Assert(err, IsNil) + err = h.Update(dom.InfoSchema()) + require.NoError(t, err) statsTblBefore := h.GetTableStats(tblInfo) statistics.FeedbackProbability.Store(1) // make the statistics inaccurate. @@ -2365,9 +2371,9 @@ func (s *statsSerialSuite) TestFeedbackWithGlobalStats(c *C) { for i := 0; i < 200; i++ { testKit.MustExec("insert into t1 values (3,4), (3,4), (3,4), (3,4), (3,4)") } - is = s.do.InfoSchema() + is = dom.InfoSchema() table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo = table.Meta() statsTblBefore = h.GetTableStats(tblInfo) // trigger feedback @@ -2378,44 +2384,48 @@ func (s *statsSerialSuite) TestFeedbackWithGlobalStats(c *C) { checkFeedbackOnPartitionTable(statsTblBefore, tblInfo) } -func (s *testStatsSuite) TestExtendedStatsPartitionTable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtendedStatsPartitionTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2") tk.MustExec("create table t1(a int, b int, c int) partition by range(a) (partition p0 values less than (5), partition p1 values less than (10))") tk.MustExec("create table t2(a int, b int, c int) partition by hash(a) partitions 4") err := tk.ExecToErr("alter table t1 add stats_extended s1 correlation(b,c)") - c.Assert(err.Error(), Equals, "Extended statistics on partitioned tables are not supported now") + require.Equal(t, "Extended statistics on partitioned tables are not supported now", err.Error()) err = tk.ExecToErr("alter table t2 add stats_extended s1 correlation(b,c)") - c.Assert(err.Error(), Equals, "Extended statistics on partitioned tables are not supported now") + require.Equal(t, "Extended statistics on partitioned tables are not supported now", err.Error()) } -func (s *testStatsSuite) TestHideIndexUsageSyncLease(c *C) { +func TestHideIndexUsageSyncLease(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // NOTICE: remove this test when index usage is GA. - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) rs := tk.MustQuery("select @@tidb_config").Rows() for _, r := range rs { - c.Assert(strings.Contains(strings.ToLower(r[0].(string)), "index-usage-sync-lease"), IsFalse) + require.False(t, strings.Contains(strings.ToLower(r[0].(string)), "index-usage-sync-lease")) } } -func (s *testStatsSuite) TestHideExtendedStatsSwitch(c *C) { +func TestHideExtendedStatsSwitch(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() // NOTICE: remove this test when this extended-stats reaches GA state. - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) + tk := testkit.NewTestKit(t, store) rs := tk.MustQuery("show variables").Rows() for _, r := range rs { - c.Assert(strings.ToLower(r[0].(string)), Not(Equals), "tidb_enable_extended_stats") + require.NotEqual(t, "tidb_enable_extended_stats", strings.ToLower(r[0].(string))) } tk.MustQuery("show variables like 'tidb_enable_extended_stats'").Check(testkit.Rows()) } -func (s *testStatsSuite) TestRepetitiveAddDropExtendedStats(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestRepetitiveAddDropExtendedStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -2425,58 +2435,60 @@ func (s *testStatsSuite) TestRepetitiveAddDropExtendedStats(c *C) { "s1 0", )) result := tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) tk.MustExec("analyze table t") tk.MustQuery("select name, status from mysql.stats_extended where name = 's1'").Sort().Check(testkit.Rows( "s1 1", )) result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) tk.MustExec("alter table t drop stats_extended s1") tk.MustQuery("select name, status from mysql.stats_extended where name = 's1'").Sort().Check(testkit.Rows( "s1 2", )) result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustQuery("select name, status from mysql.stats_extended where name = 's1'").Sort().Check(testkit.Rows( "s1 0", )) result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) tk.MustExec("analyze table t") tk.MustQuery("select name, status from mysql.stats_extended where name = 's1'").Sort().Check(testkit.Rows( "s1 1", )) result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'") - c.Assert(len(result.Rows()), Equals, 1) + require.Len(t, result.Rows(), 1) } -func (s *testStatsSuite) TestDuplicateExtendedStats(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestDuplicateExtendedStats(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int, c int)") err := tk.ExecToErr("alter table t add stats_extended s1 correlation(a,a)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "Cannot create extended statistics on duplicate column names 'a'") + require.Error(t, err) + require.Equal(t, "Cannot create extended statistics on duplicate column names 'a'", err.Error()) tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") err = tk.ExecToErr("alter table t add stats_extended s1 correlation(a,c)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "extended statistics 's1' for the specified table already exists") + require.Error(t, err) + require.Equal(t, "extended statistics 's1' for the specified table already exists", err.Error()) err = tk.ExecToErr("alter table t add stats_extended s2 correlation(a,b)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "extended statistics 's2' with same type on same columns already exists") + require.Error(t, err) + require.Equal(t, "extended statistics 's2' with same type on same columns already exists", err.Error()) err = tk.ExecToErr("alter table t add stats_extended s2 correlation(b,a)") - c.Assert(err, NotNil) - c.Assert(err.Error(), Equals, "extended statistics 's2' with same type on same columns already exists") + require.Error(t, err) + require.Equal(t, "extended statistics 's2' with same type on same columns already exists", err.Error()) tk.MustExec("alter table t add stats_extended s2 correlation(a,c)") } -func (s *testStatsSuite) TestDuplicateFMSketch(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestDuplicateFMSketch(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode='dynamic'") defer tk.MustExec("set @@tidb_partition_prune_mode='static'") @@ -2488,14 +2500,16 @@ func (s *testStatsSuite) TestDuplicateFMSketch(c *C) { tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("9")) tk.MustExec("alter table t drop column b") - c.Assert(s.do.StatsHandle().GCStats(s.do.InfoSchema(), time.Duration(0)), IsNil) + require.NoError(t, dom.StatsHandle().GCStats(dom.InfoSchema(), time.Duration(0))) tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("6")) } -func (s *testStatsSuite) TestIndexFMSketch(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestIndexFMSketch(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 1") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, index ia(a), index ibc(b, c)) partition by hash(a) partitions 3") tk.MustExec("insert into t values (1, 1, 1)") @@ -2508,7 +2522,7 @@ func (s *testStatsSuite) TestIndexFMSketch(c *C) { tk.MustExec("analyze table t") tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("15")) tk.MustExec("drop table if exists t") - c.Assert(s.do.StatsHandle().GCStats(s.do.InfoSchema(), 0), IsNil) + require.NoError(t, dom.StatsHandle().GCStats(dom.InfoSchema(), 0)) // clustered index tk.MustExec("drop table if exists t") @@ -2518,17 +2532,17 @@ func (s *testStatsSuite) TestIndexFMSketch(c *C) { tk.MustExec("analyze table t") tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("6")) tk.MustExec("drop table if exists t") - c.Assert(s.do.StatsHandle().GCStats(s.do.InfoSchema(), 0), IsNil) + require.NoError(t, dom.StatsHandle().GCStats(dom.InfoSchema(), 0)) // test NDV checkNDV := func(rows, ndv int) { tk.MustExec("analyze table t") rs := tk.MustQuery("select value from mysql.stats_fm_sketch").Rows() - c.Assert(len(rs), Equals, rows) + require.Len(t, rs, rows) for i := range rs { fm, err := statistics.DecodeFMSketch([]byte(rs[i][0].(string))) - c.Assert(err, IsNil) - c.Assert(fm.NDV(), Equals, int64(ndv)) + require.NoError(t, err) + require.Equal(t, int64(ndv), fm.NDV()) } } @@ -2541,7 +2555,7 @@ func (s *testStatsSuite) TestIndexFMSketch(c *C) { tk.MustExec("insert into t values (2), (5)") checkNDV(6, 2) tk.MustExec("drop table if exists t") - c.Assert(s.do.StatsHandle().GCStats(s.do.InfoSchema(), 0), IsNil) + require.NoError(t, dom.StatsHandle().GCStats(dom.InfoSchema(), 0)) // clustered index tk.MustExec("set @@tidb_enable_clustered_index=ON") @@ -2552,9 +2566,10 @@ func (s *testStatsSuite) TestIndexFMSketch(c *C) { checkNDV(6, 2) } -func (s *testStatsSuite) TestShowExtendedStats4DropColumn(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestShowExtendedStats4DropColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int, c int)") @@ -2563,25 +2578,26 @@ func (s *testStatsSuite) TestShowExtendedStats4DropColumn(c *C) { tk.MustExec("alter table t add stats_extended s2 correlation(b,c)") tk.MustExec("analyze table t") rows := tk.MustQuery("show stats_extended").Sort().Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(rows[0][2], Equals, "s1") - c.Assert(rows[0][3], Equals, "[a,b]") - c.Assert(rows[1][2], Equals, "s2") - c.Assert(rows[1][3], Equals, "[b,c]") + require.Len(t, rows, 2) + require.Equal(t, "s1", rows[0][2]) + require.Equal(t, "[a,b]", rows[0][3]) + require.Equal(t, "s2", rows[1][2]) + require.Equal(t, "[b,c]", rows[1][3]) tk.MustExec("alter table t drop column b") rows = tk.MustQuery("show stats_extended").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) // Previously registered extended stats should be invalid for re-created columns. tk.MustExec("alter table t add column b int") rows = tk.MustQuery("show stats_extended").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testStatsSuite) TestGlobalStatsNDV(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsNDV(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustExec(`CREATE TABLE t ( a int, key(a) ) @@ -2594,9 +2610,9 @@ func (s *testStatsSuite) TestGlobalStatsNDV(c *C) { checkNDV := func(ndvs ...int) { // g, p0, ..., p3 tk.MustExec("analyze table t") rs := tk.MustQuery(`show stats_histograms where is_index=1`).Rows() - c.Assert(len(rs), Equals, 5) + require.Len(t, rs, 5) for i, ndv := range ndvs { - c.Assert(rs[i][6].(string), Equals, fmt.Sprintf("%v", ndv)) + require.Equal(t, fmt.Sprintf("%v", ndv), rs[i][6].(string)) } } @@ -2621,19 +2637,20 @@ func (s *testStatsSuite) TestGlobalStatsNDV(c *C) { checkNDV(13, 3, 3, 3, 4) } -func (s *testStatsSuite) TestGlobalStatsIndexNDV(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestGlobalStatsIndexNDV(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") checkNDV := func(tbl string, g int, ps ...int) { // g, p0, ..., p3 tk.MustExec("analyze table " + tbl) rs := tk.MustQuery(fmt.Sprintf(`show stats_histograms where is_index=1 and table_name='%v'`, tbl)).Rows() - c.Assert(len(rs), Equals, 1+len(ps)) // 1(global) + number of partitions - c.Assert(rs[0][6].(string), Equals, fmt.Sprintf("%v", g)) // global + require.Len(t, rs, 1+len(ps)) // 1(global) + number of partitions + require.Equal(t, fmt.Sprintf("%v", g), rs[0][6].(string)) // global for i, ndv := range ps { - c.Assert(rs[i+1][6].(string), Equals, fmt.Sprintf("%v", ndv)) + require.Equal(t, fmt.Sprintf("%v", ndv), rs[i+1][6].(string)) } } @@ -2713,9 +2730,10 @@ func (s *testStatsSuite) TestGlobalStatsIndexNDV(c *C) { checkNDV("tdatetime", 8, 8, 6) } -func (s *testStatsSuite) TestExtStatsOnReCreatedTable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtStatsOnReCreatedTable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -2723,36 +2741,37 @@ func (s *testStatsSuite) TestExtStatsOnReCreatedTable(c *C) { tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustExec("analyze table t") rows := tk.MustQuery("select table_id, stats from mysql.stats_extended where name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) + require.Len(t, rows, 1) tableID1 := rows[0][0] - c.Assert(rows[0][1], Equals, "1.000000") + require.Equal(t, "1.000000", rows[0][1]) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][5], Equals, "1.000000") + require.Len(t, rows, 1) + require.Equal(t, "1.000000", rows[0][5]) tk.MustExec("drop table t") rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) tk.MustExec("create table t(a int, b int)") tk.MustExec("insert into t values(1,3),(2,2),(3,1)") tk.MustExec("alter table t add stats_extended s1 correlation(a,b)") tk.MustExec("analyze table t") rows = tk.MustQuery("select table_id, stats from mysql.stats_extended where name = 's1' order by stats").Rows() - c.Assert(len(rows), Equals, 2) + require.Len(t, rows, 2) tableID2 := rows[0][0] - c.Assert(tableID2, Not(Equals), tableID1) - c.Assert(rows[1][0], Equals, tableID1) - c.Assert(rows[0][1], Equals, "-1.000000") - c.Assert(rows[1][1], Equals, "1.000000") + require.NotEqual(t, tableID1, tableID2) + require.Equal(t, tableID1, rows[1][0]) + require.Equal(t, "-1.000000", rows[0][1]) + require.Equal(t, "1.000000", rows[1][1]) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][5], Equals, "-1.000000") + require.Len(t, rows, 1) + require.Equal(t, "-1.000000", rows[0][5]) } -func (s *testStatsSuite) TestExtStatsOnReCreatedColumn(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtStatsOnReCreatedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -2763,9 +2782,9 @@ func (s *testStatsSuite) TestExtStatsOnReCreatedColumn(c *C) { "[1,2] 1.000000", )) rows := tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[a,b]") - c.Assert(rows[0][5], Equals, "1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[a,b]", rows[0][3]) + require.Equal(t, "1.000000", rows[0][5]) tk.MustExec("alter table t drop column b") tk.MustExec("alter table t add column b int") @@ -2788,12 +2807,13 @@ func (s *testStatsSuite) TestExtStatsOnReCreatedColumn(c *C) { "[1,2] 1.000000", )) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 0) + require.Len(t, rows, 0) } -func (s *testStatsSuite) TestExtStatsOnRenamedColumn(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtStatsOnRenamedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -2804,9 +2824,9 @@ func (s *testStatsSuite) TestExtStatsOnRenamedColumn(c *C) { "[1,2] 1.000000", )) rows := tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[a,b]") - c.Assert(rows[0][5], Equals, "1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[a,b]", rows[0][3]) + require.Equal(t, "1.000000", rows[0][5]) tk.MustExec("alter table t rename column b to c") tk.MustExec("update t set c = 3 where a = 1") @@ -2823,14 +2843,15 @@ func (s *testStatsSuite) TestExtStatsOnRenamedColumn(c *C) { "[1,2] -1.000000", )) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[a,c]") - c.Assert(rows[0][5], Equals, "-1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[a,c]", rows[0][3]) + require.Equal(t, "-1.000000", rows[0][5]) } -func (s *testStatsSuite) TestExtStatsOnModifiedColumn(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestExtStatsOnModifiedColumn(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set session tidb_enable_extended_stats = on") tk.MustExec("use test") tk.MustExec("create table t(a int, b int)") @@ -2841,9 +2862,9 @@ func (s *testStatsSuite) TestExtStatsOnModifiedColumn(c *C) { "[1,2] 1.000000", )) rows := tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[a,b]") - c.Assert(rows[0][5], Equals, "1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[a,b]", rows[0][3]) + require.Equal(t, "1.000000", rows[0][5]) tk.MustExec("alter table t modify column b bigint") tk.MustExec("update t set b = 3 where a = 1") @@ -2860,16 +2881,15 @@ func (s *testStatsSuite) TestExtStatsOnModifiedColumn(c *C) { "[1,2] -1.000000", )) rows = tk.MustQuery("show stats_extended where stats_name = 's1'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[a,b]") - c.Assert(rows[0][5], Equals, "-1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[a,b]", rows[0][3]) + require.Equal(t, "-1.000000", rows[0][5]) } -func (s *testSerialStatsSuite) TestCorrelationWithDefinedCollate(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) +func TestCorrelationWithDefinedCollate(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t") testKit.MustExec("create table t(a int primary key, b varchar(8) character set utf8mb4 collate utf8mb4_general_ci, c varchar(8) character set utf8mb4 collate utf8mb4_bin)") @@ -2886,46 +2906,47 @@ func (s *testSerialStatsSuite) TestCorrelationWithDefinedCollate(c *C) { "1", )) rows := testKit.MustQuery("show stats_histograms where table_name = 't'").Sort().Rows() - c.Assert(len(rows), Equals, 3) - c.Assert(rows[1][9], Equals, "1") - c.Assert(rows[2][9], Equals, "-1") + require.Len(t, rows, 3) + require.Equal(t, "1", rows[1][9]) + require.Equal(t, "-1", rows[2][9]) testKit.MustExec("set session tidb_enable_extended_stats = on") testKit.MustExec("alter table t add stats_extended s1 correlation(b,c)") testKit.MustExec("analyze table t") rows = testKit.MustQuery("show stats_extended where stats_name = 's1'").Sort().Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "[b,c]") - c.Assert(rows[0][5], Equals, "-1.000000") + require.Len(t, rows, 1) + require.Equal(t, "[b,c]", rows[0][3]) + require.Equal(t, "-1.000000", rows[0][5]) } -func (s *testSerialStatsSuite) TestLoadHistogramWithCollate(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) +func TestLoadHistogramWithCollate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t") testKit.MustExec("create table t(a varchar(10) collate utf8mb4_unicode_ci);") testKit.MustExec("insert into t values('abcdefghij');") testKit.MustExec("insert into t values('abcdufghij');") testKit.MustExec("analyze table t with 0 topn;") - do := s.do + do := dom h := do.StatsHandle() is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := tbl.Meta() _, err = h.TableStatsFromStorage(tblInfo, tblInfo.ID, true, 0) - c.Assert(err, IsNil) + require.NoError(t, err) } -func (s *testSerialStatsSuite) TestFastAnalyzeColumnHistWithNullValue(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestFastAnalyzeColumnHistWithNullValue(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("drop table if exists t") testKit.MustExec("create table t (a int)") testKit.MustExec("insert into t values (1), (2), (3), (4), (NULL)") + testKit.MustExec("set @@session.tidb_analyze_version = 1") testKit.MustExec("set @@tidb_enable_fast_analyze=1") defer testKit.MustExec("set @@tidb_enable_fast_analyze=0") testKit.MustExec("analyze table t with 0 topn, 2 buckets") @@ -2933,30 +2954,32 @@ func (s *testSerialStatsSuite) TestFastAnalyzeColumnHistWithNullValue(c *C) { testKit.MustQuery("select min(lower_bound) from mysql.stats_buckets").Check(testkit.Rows("1")) } -func (s *testStatsSuite) TestStatsCacheUpdateSkip(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - do := s.do +func TestStatsCacheUpdateSkip(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + do := dom h := do.StatsHandle() testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") testKit.MustExec("insert into t values(1, 2)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() statsTbl1 := h.GetTableStats(tableInfo) - c.Assert(statsTbl1.Pseudo, IsFalse) + require.False(t, statsTbl1.Pseudo) h.Update(is) statsTbl2 := h.GetTableStats(tableInfo) - c.Assert(statsTbl1, Equals, statsTbl2) + require.Equal(t, statsTbl2, statsTbl1) } -func (s *testSerialStatsSuite) TestIssues24349(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestIssues24349(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("set @@tidb_partition_prune_mode='dynamic'") testKit.MustExec("set @@tidb_analyze_version=2") @@ -2972,9 +2995,10 @@ func (s *testSerialStatsSuite) TestIssues24349(c *C) { )) } -func (s *testStatsSuite) TestIssues24401(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestIssues24401(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") // normal table with static prune mode @@ -3000,18 +3024,19 @@ func (s *testStatsSuite) TestIssues24401(c *C) { testKit.MustExec("analyze table tp") rows := testKit.MustQuery("select * from mysql.stats_fm_sketch").Rows() lenRows := len(rows) - c.Assert(lenRows, Equals, 6) + require.Equal(t, 6, lenRows) // check fm-sketch won't increase infinitely testKit.MustExec("insert into t values (10), (20), (30), (12), (23), (23), (4344)") testKit.MustExec("analyze table tp") rows = testKit.MustQuery("select * from mysql.stats_fm_sketch").Rows() - c.Assert(len(rows), Equals, lenRows) + require.Len(t, rows, lenRows) } -func (s *testStatsSuite) TestIssues27147(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestIssues27147(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("set @@tidb_partition_prune_mode='dynamic'") @@ -3019,19 +3044,20 @@ func (s *testStatsSuite) TestIssues27147(c *C) { testKit.MustExec("create table t (a int, b int) partition by range (a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than maxvalue);") testKit.MustExec("alter table t add index idx((a+5));") err := testKit.ExecToErr("analyze table t;") - c.Assert(err, Equals, nil) + require.Equal(t, nil, err) testKit.MustExec("drop table if exists t1") testKit.MustExec("create table t1 (a int, b int as (a+1) virtual, c int) partition by range (a) (partition p0 values less than (10), partition p1 values less than (20), partition p2 values less than maxvalue);") testKit.MustExec("alter table t1 add index idx((a+5));") err = testKit.ExecToErr("analyze table t1;") - c.Assert(err, Equals, nil) + require.Equal(t, nil, err) } -func (s *testStatsSuite) TestColumnCountFromStorage(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - do := s.do +func TestColumnCountFromStorage(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + do := dom h := do.StatsHandle() originLease := h.Lease() defer h.SetLease(originLease) @@ -3046,51 +3072,52 @@ func (s *testStatsSuite) TestColumnCountFromStorage(c *C) { is := do.InfoSchema() h = do.StatsHandle() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("tt")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := tbl.Meta() h.TableStatsFromStorage(tblInfo, tblInfo.ID, false, 0) statsTbl := h.GetTableStats(tblInfo) - c.Assert(statsTbl.Columns[tblInfo.Columns[0].ID].Count, Equals, int64(2)) + require.Equal(t, int64(2), statsTbl.Columns[tblInfo.Columns[0].ID].Count) } -func (s *testStatsSuite) TestIncrementalModifyCountUpdate(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestIncrementalModifyCountUpdate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int)") tk.MustExec("set @@session.tidb_analyze_version = 2") - h := s.do.StatsHandle() + h := dom.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - tbl, err := s.do.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) tblInfo := tbl.Meta() tid := tblInfo.ID tk.MustExec("insert into t values(1),(2),(3)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - err = h.Update(s.do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + err = h.Update(dom.InfoSchema()) + require.NoError(t, err) tk.MustExec("analyze table t") tk.MustQuery(fmt.Sprintf("select count, modify_count from mysql.stats_meta where table_id = %d", tid)).Check(testkit.Rows( "3 0", )) tk.MustExec("begin") - txn, err := tk.Se.Txn(false) - c.Assert(err, IsNil) + txn, err := tk.Session().Txn(false) + require.NoError(t, err) startTS := txn.StartTS() tk.MustExec("commit") tk.MustExec("insert into t values(4),(5),(6)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - err = h.Update(s.do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + err = h.Update(dom.InfoSchema()) + require.NoError(t, err) // Simulate that the analyze would start before and finish after the second insert. - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/injectAnalyzeSnapshot", fmt.Sprintf("return(%d)", startTS)), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/injectBaseCount", "return(3)"), IsNil) - c.Assert(failpoint.Enable("github.com/pingcap/tidb/executor/injectBaseModifyCount", "return(0)"), IsNil) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/injectAnalyzeSnapshot", fmt.Sprintf("return(%d)", startTS))) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/injectBaseCount", "return(3)")) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/executor/injectBaseModifyCount", "return(0)")) tk.MustExec("analyze table t") // Check the count / modify_count changes during the analyze are not lost. tk.MustQuery(fmt.Sprintf("select count, modify_count from mysql.stats_meta where table_id = %d", tid)).Check(testkit.Rows( @@ -3100,522 +3127,33 @@ func (s *testStatsSuite) TestIncrementalModifyCountUpdate(c *C) { tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d", tid)).Check(testkit.Rows( "3", )) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/injectAnalyzeSnapshot"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/injectBaseCount"), IsNil) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/executor/injectBaseModifyCount"), IsNil) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/injectAnalyzeSnapshot")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/injectBaseCount")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/executor/injectBaseModifyCount")) } -func (s *testStatsSuite) TestAnalyzeColumnsWithPrimaryKey(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") +func TestRecordHistoricalStatsToStorage(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("create table t (a int, b int, c int primary key)") - tk.MustExec("insert into t values (1,1,1), (1,1,2), (2,2,3), (2,2,4), (3,3,5), (4,3,6), (5,4,7), (6,4,8), (null,null,9)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.", - "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(rows[0][3], Equals, "a") - c.Assert(rows[1][3], Equals, "c") - - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 9")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t a 0 1 2", - "test t a 0 2 2", - "test t c 0 1 1", - "test t c 0 2 1")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 6 1 8 2 1", - "0 2 0 0 8 0 0", // column b is not analyzed - "0 3 9 0 9 2 1", - )) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t a 0 0 3 1 3 5 0", - "test t a 0 1 4 1 6 6 0", - "test t c 0 0 4 1 3 6 0", - "test t c 0 1 7 1 7 9 0")) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithIndex(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("create table t (a int, b int, c int, d int, index idx_b_d(b, d))") - tk.MustExec("insert into t values (1,1,null,1), (2,1,9,1), (1,1,8,1), (2,2,7,2), (1,3,7,3), (2,4,6,4), (1,4,6,5), (2,4,6,5), (1,5,6,5)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t columns c with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.", - "Warning 1105 Columns b,d are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 3) - c.Assert(rows[0][3], Equals, "b") - c.Assert(rows[1][3], Equals, "c") - c.Assert(rows[2][3], Equals, "d") - - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 9")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t b 0 1 3", - "test t b 0 4 3", - "test t c 0 6 4", - "test t c 0 7 2", - "test t d 0 1 3", - "test t d 0 5 3", - "test t idx_b_d 1 (1, 1) 3", - "test t idx_b_d 1 (4, 5) 2")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 0 0 9 0 0", // column a is not analyzed - "0 2 5 0 9 2 1", - "0 3 4 1 8 2 -0.07", - "0 4 5 0 9 2 1", - "1 1 6 0 18 2 0")) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t b 0 0 2 1 2 3 0", - "test t b 0 1 3 1 5 5 0", - "test t c 0 0 2 1 8 9 0", - "test t d 0 0 2 1 2 3 0", - "test t d 0 1 3 1 4 4 0", - "test t idx_b_d 1 0 3 1 (2, 2) (4, 4) 0", - "test t idx_b_d 1 1 4 1 (5, 5) (5, 5) 0")) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithClusteredIndex(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("create table t (a int, b int, c int, d int, primary key(b, d) clustered)") - tk.MustExec("insert into t values (1,1,null,1), (2,2,9,2), (1,3,8,3), (2,4,7,4), (1,5,7,5), (2,6,6,6), (1,7,6,7), (2,8,6,8), (1,9,6,9)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t columns c with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.", - "Warning 1105 Columns b,d are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 3) - c.Assert(rows[0][3], Equals, "b") - c.Assert(rows[1][3], Equals, "c") - c.Assert(rows[2][3], Equals, "d") - - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 9")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t PRIMARY 1 (1, 1) 1", - "test t PRIMARY 1 (2, 2) 1", - "test t b 0 1 1", - "test t b 0 2 1", - "test t c 0 6 4", - "test t c 0 7 2", - "test t d 0 1 1", - "test t d 0 2 1")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 0 0 9 0 0", // column a is not analyzed - "0 2 9 0 9 2 1", - "0 3 4 1 8 2 -0.07", - "0 4 9 0 9 2 1", - "1 1 9 0 18 2 0")) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t PRIMARY 1 0 4 1 (3, 3) (6, 6) 0", - "test t PRIMARY 1 1 7 1 (7, 7) (9, 9) 0", - "test t b 0 0 4 1 3 6 0", - "test t b 0 1 7 1 7 9 0", - "test t c 0 0 2 1 8 9 0", - "test t d 0 0 4 1 3 6 0", - "test t d 0 1 7 1 7 9 0")) -} - -func (s *testStatsSuite) TestAnalyzeColumnsError(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (a int, b int)") - - // analyze version 1 doesn't support `ANALYZE COLUMNS c1, ..., cn` currently - tk.MustExec("set @@tidb_analyze_version = 1") - err := tk.ExecToErr("analyze table t columns a") - c.Assert(err.Error(), Equals, "Only the analyze version 2 supports analyzing the specified columns") - - // invalid column - tk.MustExec("set @@tidb_analyze_version = 2") - err = tk.ExecToErr("analyze table t columns c") - terr := errors.Cause(err).(*terror.Error) - c.Assert(terr.Code(), Equals, errors.ErrCode(errno.ErrAnalyzeMissColumn)) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithDynamicPartitionTable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") - tk.MustExec("create table t (a int, b int, c int, index idx(c)) partition by range (a) (partition p0 values less than (10), partition p1 values less than maxvalue)") - tk.MustExec("insert into t values (1,2,1), (2,4,1), (3,6,1), (4,8,2), (4,8,2), (5,10,3), (5,10,4), (5,10,5), (null,null,6), (11,22,7), (12,24,8), (13,26,9), (14,28,10), (15,30,11), (16,32,12), (16,32,13), (16,32,13), (16,32,14), (17,34,14), (17,34,14)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - defs := tbl.Meta().Partition.Definitions - p0ID := defs[0].ID - p1ID := defs[1].ID - - tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0.", - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1.", - "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 6) - c.Assert(rows[0][:4], DeepEquals, []interface{}{"test", "t", "global", "a"}) - c.Assert(rows[1][:4], DeepEquals, []interface{}{"test", "t", "global", "c"}) - c.Assert(rows[2][:4], DeepEquals, []interface{}{"test", "t", "p0", "a"}) - c.Assert(rows[3][:4], DeepEquals, []interface{}{"test", "t", "p0", "c"}) - c.Assert(rows[4][:4], DeepEquals, []interface{}{"test", "t", "p1", "a"}) - c.Assert(rows[5][:4], DeepEquals, []interface{}{"test", "t", "p1", "c"}) - - rows = tk.MustQuery("show stats_meta where db_name = 'test' and table_name = 't'").Sort().Rows() - c.Assert(len(rows), Equals, 3) - c.Assert(append(rows[0][:3], rows[0][4:]...), DeepEquals, []interface{}{"test", "t", "global", "0", "20"}) - c.Assert(append(rows[1][:3], rows[1][4:]...), DeepEquals, []interface{}{"test", "t", "p0", "0", "9"}) - c.Assert(append(rows[2][:3], rows[2][4:]...), DeepEquals, []interface{}{"test", "t", "p1", "0", "11"}) - - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t global a 0 16 4", - "test t global a 0 5 3", - "test t global c 0 1 3", - "test t global c 0 14 3", - "test t p0 a 0 4 2", - "test t p0 a 0 5 3", - "test t p0 c 0 1 3", - "test t p0 c 0 2 2", - "test t p1 a 0 16 4", - "test t p1 a 0 17 2", - "test t p1 c 0 13 2", - "test t p1 c 0 14 3")) - - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t global idx 1 1 3", - "test t global idx 1 14 3", - "test t p0 idx 1 1 3", - "test t p0 idx 1 2 2", - "test t p1 idx 1 13 2", - "test t p1 idx 1 14 3")) - - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t global a 0 0 5 2 1 4 0", - "test t global a 0 1 12 2 17 17 0", - "test t global c 0 0 6 1 2 6 0", - "test t global c 0 1 14 2 13 13 0", - "test t p0 a 0 0 2 1 1 2 0", - "test t p0 a 0 1 3 1 3 3 0", - "test t p0 c 0 0 3 1 3 5 0", - "test t p0 c 0 1 4 1 6 6 0", - "test t p1 a 0 0 3 1 11 13 0", - "test t p1 a 0 1 5 1 14 15 0", - "test t p1 c 0 0 4 1 7 10 0", - "test t p1 c 0 1 6 1 11 12 0")) - - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t global idx 1 0 6 1 2 6 0", - "test t global idx 1 1 14 2 13 13 0", - "test t p0 idx 1 0 3 1 3 5 0", - "test t p0 idx 1 1 4 1 6 6 0", - "test t p1 idx 1 0 4 1 7 10 0", - "test t p1 idx 1 1 6 1 11 12 0")) - - tk.MustQuery("select table_id, is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms order by table_id, is_index, hist_id asc").Check( - testkit.Rows(fmt.Sprintf("%d 0 1 12 1 19 2 0", tblID), // global, a - fmt.Sprintf("%d 0 3 14 0 20 2 0", tblID), // global, c - fmt.Sprintf("%d 1 1 14 0 0 2 0", tblID), // global, idx - fmt.Sprintf("%d 0 1 5 1 8 2 1", p0ID), // p0, a - fmt.Sprintf("%d 0 2 0 0 8 0 0", p0ID), // p0, b, not analyzed - fmt.Sprintf("%d 0 3 6 0 9 2 1", p0ID), // p0, c - fmt.Sprintf("%d 1 1 6 0 9 2 0", p0ID), // p0, idx - fmt.Sprintf("%d 0 1 7 0 11 2 1", p1ID), // p1, a - fmt.Sprintf("%d 0 2 0 0 11 0 0", p1ID), // p1, b, not analyzed - fmt.Sprintf("%d 0 3 8 0 11 2 1", p1ID), // p1, c - fmt.Sprintf("%d 1 1 8 0 11 2 0", p1ID), // p1, idx - )) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithStaticPartitionTable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("set @@tidb_partition_prune_mode = 'static'") - tk.MustExec("create table t (a int, b int, c int, index idx(c)) partition by range (a) (partition p0 values less than (10), partition p1 values less than maxvalue)") - tk.MustExec("insert into t values (1,2,1), (2,4,1), (3,6,1), (4,8,2), (4,8,2), (5,10,3), (5,10,4), (5,10,5), (null,null,6), (11,22,7), (12,24,8), (13,26,9), (14,28,10), (15,30,11), (16,32,12), (16,32,13), (16,32,13), (16,32,14), (17,34,14), (17,34,14)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - defs := tbl.Meta().Partition.Definitions - p0ID := defs[0].ID - p1ID := defs[1].ID - - tk.MustExec("analyze table t columns a with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0.", - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1.", - "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 4) - c.Assert(rows[0][:4], DeepEquals, []interface{}{"test", "t", "p0", "a"}) - c.Assert(rows[1][:4], DeepEquals, []interface{}{"test", "t", "p0", "c"}) - c.Assert(rows[2][:4], DeepEquals, []interface{}{"test", "t", "p1", "a"}) - c.Assert(rows[3][:4], DeepEquals, []interface{}{"test", "t", "p1", "c"}) - - rows = tk.MustQuery("show stats_meta where db_name = 'test' and table_name = 't'").Sort().Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(append(rows[0][:3], rows[0][4:]...), DeepEquals, []interface{}{"test", "t", "p0", "0", "9"}) - c.Assert(append(rows[1][:3], rows[1][4:]...), DeepEquals, []interface{}{"test", "t", "p1", "0", "11"}) - - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t p0 a 0 4 2", - "test t p0 a 0 5 3", - "test t p0 c 0 1 3", - "test t p0 c 0 2 2", - "test t p1 a 0 16 4", - "test t p1 a 0 17 2", - "test t p1 c 0 13 2", - "test t p1 c 0 14 3")) - - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t p0 idx 1 1 3", - "test t p0 idx 1 2 2", - "test t p1 idx 1 13 2", - "test t p1 idx 1 14 3")) - - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 0").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t p0 a 0 0 2 1 1 2 0", - "test t p0 a 0 1 3 1 3 3 0", - "test t p0 c 0 0 3 1 3 5 0", - "test t p0 c 0 1 4 1 6 6 0", - "test t p1 a 0 0 3 1 11 13 0", - "test t p1 a 0 1 5 1 14 15 0", - "test t p1 c 0 0 4 1 7 10 0", - "test t p1 c 0 1 6 1 11 12 0")) - - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't' and is_index = 1").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t p0 idx 1 0 3 1 3 5 0", - "test t p0 idx 1 1 4 1 6 6 0", - "test t p1 idx 1 0 4 1 7 10 0", - "test t p1 idx 1 1 6 1 11 12 0")) - - tk.MustQuery("select table_id, is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms order by table_id, is_index, hist_id asc").Check( - testkit.Rows(fmt.Sprintf("%d 0 1 5 1 8 2 1", p0ID), // p0, a - fmt.Sprintf("%d 0 2 0 0 8 0 0", p0ID), // p0, b, not analyzed - fmt.Sprintf("%d 0 3 6 0 9 2 1", p0ID), // p0, c - fmt.Sprintf("%d 1 1 6 0 9 2 0", p0ID), // p0, idx - fmt.Sprintf("%d 0 1 7 0 11 2 1", p1ID), // p1, a - fmt.Sprintf("%d 0 2 0 0 11 0 0", p1ID), // p1, b, not analyzed - fmt.Sprintf("%d 0 3 8 0 11 2 1", p1ID), // p1, c - fmt.Sprintf("%d 1 1 8 0 11 2 0", p1ID), // p1, idx - )) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithExtendedStats(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("set @@tidb_enable_extended_stats = on") - tk.MustExec("create table t (a int, b int, c int)") - tk.MustExec("alter table t add stats_extended s1 correlation(b,c)") - tk.MustExec("insert into t values (5,1,1), (4,2,2), (3,3,3), (2,4,4), (1,5,5)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.", - "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Sort().Rows() - c.Assert(len(rows), Equals, 2) - c.Assert(rows[0][3], Equals, "b") - c.Assert(rows[1][3], Equals, "c") - - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 5")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t b 0 1 1", - "test t b 0 2 1", - "test t c 0 1 1", - "test t c 0 2 1")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 0 0 5 0 0", // column a is not analyzed - "0 2 5 0 5 2 1", - "0 3 5 0 5 2 1", - )) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t b 0 0 2 1 3 4 0", - "test t b 0 1 3 1 5 5 0", - "test t c 0 0 2 1 3 4 0", - "test t c 0 1 3 1 5 5 0")) - rows = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][:len(rows[0])-1], DeepEquals, []interface{}{"test", "t", "s1", "[b,c]", "correlation", "1.000000"}) -} - -func (s *testStatsSuite) TestAnalyzeColumnsWithVirtualColumnIndex(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("create table t (a int, b int, c int as (b+1), index idx(c))") - tk.MustExec("insert into t (a,b) values (1,1), (2,2), (3,3), (4,4), (5,4), (6,5), (7,5), (8,5), (null,null)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") - tk.MustQuery("show warnings").Sort().Check(testkit.Rows( - "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t.", - "Warning 1105 Columns c are missing in ANALYZE but their stats are needed for calculating stats for indexes/primary key/extended stats.", - )) - // virtual column c is skipped when dumping stats into disk, so only the stats of column b are updated - rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_analyzed_at is not null").Rows() - c.Assert(len(rows), Equals, 1) - c.Assert(rows[0][3], Equals, "b") - - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 9")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t b 0 4 2", - "test t b 0 5 3", - "test t idx 1 5 2", - "test t idx 1 6 3")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 0 0 0 0", // column a is not analyzed - "0 2 5 1 2 1", - "0 3 0 0 0 0", // column c is not analyzed - "1 1 5 1 2 0")) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t b 0 0 2 1 1 2 0", - "test t b 0 1 3 1 3 3 0", - "test t idx 1 0 2 1 2 3 0", - "test t idx 1 1 3 1 4 4 0")) -} - -func (s *testStatsSuite) TestAnalyzeColumnsAfterAnalyzeAll(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("set @@tidb_analyze_version = 2") - tk.MustExec("create table t (a int, b int)") - tk.MustExec("insert into t (a,b) values (1,1), (1,1), (2,2), (2,2), (3,3), (4,4)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - is := s.do.InfoSchema() - tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) - tblID := tbl.Meta().ID - - tk.MustExec("analyze table t with 2 topn, 2 buckets") - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 6")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t a 0 1 2", - "test t a 0 2 2", - "test t b 0 1 2", - "test t b 0 2 2")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 4 0 6 2 1", - "0 2 4 0 6 2 1")) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t a 0 0 2 1 3 4 0", - "test t b 0 0 2 1 3 4 0")) - - tk.MustExec("insert into t (a,b) values (1,1), (6,6)") - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - - tk.MustExec("analyze table t columns b with 2 topn, 2 buckets") - // Column a is not analyzed in second ANALYZE. We keep the outdated stats of column a rather than delete them. - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 8")) - tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_idx, value, count - testkit.Rows("test t a 0 1 2", - "test t a 0 2 2", - "test t b 0 1 3", - "test t b 0 2 2")) - tk.MustQuery(fmt.Sprintf("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, truncate(correlation,2) from mysql.stats_histograms where table_id = %d", tblID)).Sort().Check( - testkit.Rows("0 1 4 0 8 2 1", // tot_col_size of column a is updated to 8 by DumpStatsDeltaToKV - "0 2 5 0 8 2 0.76")) - tk.MustQuery("show stats_buckets where db_name = 'test' and table_name = 't'").Sort().Check( - // db, tbl, part, col, is_index, bucket_id, count, repeats, lower, upper, ndv - testkit.Rows("test t a 0 0 2 1 3 4 0", - "test t b 0 0 2 1 3 4 0", - "test t b 0 1 3 1 6 6 0")) - tk.MustQuery(fmt.Sprintf("select hist_id from mysql.stats_histograms where version = (select version from mysql.stats_meta where table_id = %d)", tblID)).Check(testkit.Rows("2")) + tk.MustExec("create table t(a int, b varchar(10))") + tk.MustExec("insert into t value(1, 'aaa'), (3, 'aab'), (5, 'bba'), (2, 'bbb'), (4, 'cca'), (6, 'ccc')") + // mark column stats as needed + tk.MustExec("select * from t where a = 3") + tk.MustExec("select * from t where b = 'bbb'") + tk.MustExec("alter table t add index single(a)") + tk.MustExec("alter table t add index multi(a, b)") + tk.MustExec("analyze table t with 2 topn") + + tableInfo, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + version, err := dom.StatsHandle().RecordHistoricalStatsToStorage("t", tableInfo.Meta()) + require.NoError(t, err) + + rows := tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_history where version = '%d'", version)).Rows() + num, _ := strconv.Atoi(rows[0][0].(string)) + require.GreaterOrEqual(t, num, 1) } diff --git a/statistics/handle/main_test.go b/statistics/handle/main_test.go index 5b8ea0ed4c0dc..1822c3b52eb27 100644 --- a/statistics/handle/main_test.go +++ b/statistics/handle/main_test.go @@ -23,9 +23,10 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() goleak.VerifyTestMain(m, opts...) } diff --git a/statistics/handle/update.go b/statistics/handle/update.go index 73fb91c4d8979..018d49173bcd4 100644 --- a/statistics/handle/update.go +++ b/statistics/handle/update.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "math" + "sort" "strconv" "strings" "sync" @@ -31,12 +32,12 @@ import ( "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" @@ -133,13 +134,26 @@ func (m errorRateDeltaMap) clear(tableID int64, histID int64, isIndex bool) { m[tableID] = item } -func merge(s *SessionStatsCollector, deltaMap tableDeltaMap, rateMap errorRateDeltaMap, feedback *statistics.QueryFeedbackMap) { +// colStatsUsageMap maps (tableID, columnID) to the last time when the column stats are used(needed). +type colStatsUsageMap map[model.TableColumnID]time.Time + +func (m colStatsUsageMap) merge(other colStatsUsageMap) { + for id, t := range other { + if mt, ok := m[id]; !ok || mt.Before(t) { + m[id] = t + } + } +} + +func merge(s *SessionStatsCollector, deltaMap tableDeltaMap, rateMap errorRateDeltaMap, feedback *statistics.QueryFeedbackMap, colMap colStatsUsageMap) { deltaMap.merge(s.mapper) s.mapper = make(tableDeltaMap) rateMap.merge(s.rateMap) s.rateMap = make(errorRateDeltaMap) feedback.Merge(s.feedback) s.feedback = statistics.NewQueryFeedbackMap() + colMap.merge(s.colMap) + s.colMap = make(colStatsUsageMap) } // SessionStatsCollector is a list item that holds the delta mapper. If you want to write or read mapper, you must lock it. @@ -149,6 +163,7 @@ type SessionStatsCollector struct { mapper tableDeltaMap feedback *statistics.QueryFeedbackMap rateMap errorRateDeltaMap + colMap colStatsUsageMap next *SessionStatsCollector // deleted is set to true when a session is closed. Every time we sweep the list, we will remove the useless collector. deleted bool @@ -175,7 +190,7 @@ var ( MinLogErrorRate = atomic.NewFloat64(0.5) ) -// StoreQueryFeedback merges the feedback into stats collector. +// StoreQueryFeedback merges the feedback into stats collector. Deprecated. func (s *SessionStatsCollector) StoreQueryFeedback(feedback interface{}, h *Handle) error { q := feedback.(*statistics.QueryFeedback) if !q.Valid || q.Hist == nil { @@ -204,6 +219,13 @@ func (s *SessionStatsCollector) StoreQueryFeedback(feedback interface{}, h *Hand return nil } +// UpdateColStatsUsage updates the last time when the column stats are used(needed). +func (s *SessionStatsCollector) UpdateColStatsUsage(colMap colStatsUsageMap) { + s.Lock() + defer s.Unlock() + s.colMap.merge(colMap) +} + // NewSessionStatsCollector allocates a stats collector for a session. func (h *Handle) NewSessionStatsCollector() *SessionStatsCollector { h.listHead.Lock() @@ -213,6 +235,7 @@ func (h *Handle) NewSessionStatsCollector() *SessionStatsCollector { rateMap: make(errorRateDeltaMap), next: h.listHead.next, feedback: statistics.NewQueryFeedbackMap(), + colMap: make(colStatsUsageMap), } h.listHead.next = newCollector return newCollector @@ -384,12 +407,13 @@ func (h *Handle) sweepList() { deltaMap := make(tableDeltaMap) errorRateMap := make(errorRateDeltaMap) feedback := statistics.NewQueryFeedbackMap() + colMap := make(colStatsUsageMap) prev := h.listHead prev.Lock() for curr := prev.next; curr != nil; curr = curr.next { curr.Lock() // Merge the session stats into deltaMap, errorRateMap and feedback respectively. - merge(curr, deltaMap, errorRateMap, feedback) + merge(curr, deltaMap, errorRateMap, feedback, colMap) if curr.deleted { prev.next = curr.next // Since the session is already closed, we can safely unlock it here. @@ -411,6 +435,9 @@ func (h *Handle) sweepList() { h.feedback.data.Merge(feedback) h.feedback.data.SiftFeedbacks() h.feedback.Unlock() + h.colMap.Lock() + h.colMap.data.merge(colMap) + h.colMap.Unlock() } // DumpStatsDeltaToKV sweeps the whole list and updates the global map, then we dumps every table that held in map to KV. @@ -440,6 +467,7 @@ func (h *Handle) DumpStatsDeltaToKV(mode dumpMode) error { deltaMap.update(id, -item.Delta, -item.Count, nil) } if err = h.dumpTableStatColSizeToKV(id, item); err != nil { + delete(deltaMap, id) return errors.Trace(err) } if updated { @@ -455,6 +483,12 @@ func (h *Handle) DumpStatsDeltaToKV(mode dumpMode) error { // dumpTableStatDeltaToKV dumps a single delta with some table to KV and updates the version. func (h *Handle) dumpTableStatCountToKV(id int64, delta variable.TableDelta) (updated bool, err error) { + statsVer := uint64(0) + defer func() { + if err == nil && statsVer != 0 { + err = h.recordHistoricalStatsMeta(id, statsVer) + } + }() if delta.Count == 0 { return true, nil } @@ -482,6 +516,7 @@ func (h *Handle) dumpTableStatCountToKV(id int64, delta variable.TableDelta) (up } else { _, err = exec.ExecuteInternal(ctx, "update mysql.stats_meta set version = %?, count = count + %?, modify_count = modify_count + %? where table_id = %?", startTS, delta.Delta, delta.Count, id) } + statsVer = startTS return errors.Trace(err) } if err = updateStatsMeta(id); err != nil { @@ -525,7 +560,7 @@ func (h *Handle) dumpTableStatColSizeToKV(id int64, delta variable.TableDelta) e return errors.Trace(err) } -// DumpStatsFeedbackToKV dumps the stats feedback to KV. +// DumpStatsFeedbackToKV dumps the stats feedback to KV. Deprecated. func (h *Handle) DumpStatsFeedbackToKV() error { h.feedback.Lock() feedback := h.feedback.data @@ -701,50 +736,32 @@ func (h *Handle) HandleUpdateStats(is infoschema.InfoSchema) error { } for _, ptbl := range tables { - // this func lets `defer` works normally, where `Close()` should be called before any return - err = func() error { - tbl := ptbl.GetInt64(0) - const sql = "select table_id, hist_id, is_index, feedback from mysql.stats_feedback where table_id=%? order by hist_id, is_index" - rc, err := h.mu.ctx.(sqlexec.SQLExecutor).ExecuteInternal(context.TODO(), sql, tbl) + tableID, histID, isIndex := ptbl.GetInt64(0), int64(-1), int64(-1) + for { + // fetch at most 100000 rows each time to avoid OOM + const sql = "select table_id, hist_id, is_index, feedback from mysql.stats_feedback where table_id = %? and is_index >= %? and hist_id > %? order by is_index, hist_id limit 100000" + rows, _, err := h.execRestrictedSQL(ctx, sql, tableID, histID, isIndex) if err != nil { return errors.Trace(err) } - defer terror.Call(rc.Close) - tableID, histID, isIndex := int64(-1), int64(-1), int64(-1) - var rows []chunk.Row - for { - req := rc.NewChunk(nil) - iter := chunk.NewIterator4Chunk(req) - err := rc.Next(context.TODO(), req) - if err != nil { - return errors.Trace(err) - } - if req.NumRows() == 0 { - if len(rows) > 0 { - if err := h.handleSingleHistogramUpdate(is, rows); err != nil { + if len(rows) == 0 { + break + } + startIdx := 0 + for i, row := range rows { + if row.GetInt64(1) != histID || row.GetInt64(2) != isIndex { + if i > 0 { + if err = h.handleSingleHistogramUpdate(is, rows[startIdx:i]); err != nil { return errors.Trace(err) } } - break - } - for row := iter.Begin(); row != iter.End(); row = iter.Next() { - // len(rows) > 100000 limits the rows to avoid OOM - if row.GetInt64(0) != tableID || row.GetInt64(1) != histID || row.GetInt64(2) != isIndex || len(rows) > 100000 { - if len(rows) > 0 { - if err := h.handleSingleHistogramUpdate(is, rows); err != nil { - return errors.Trace(err) - } - } - tableID, histID, isIndex = row.GetInt64(0), row.GetInt64(1), row.GetInt64(2) - rows = rows[:0] - } - rows = append(rows, row) + histID, isIndex = row.GetInt64(1), row.GetInt64(2) + startIdx = i } } - return nil - }() - if err != nil { - return err + if err = h.handleSingleHistogramUpdate(is, rows[startIdx:]); err != nil { + return errors.Trace(err) + } } } return nil @@ -845,6 +862,62 @@ func (h *Handle) dumpStatsUpdateToKV(tableID, isIndex int64, q *statistics.Query return errors.Trace(err) } +// DumpColStatsUsageToKV sweeps the whole list, updates the column stats usage map and dumps it to KV. +func (h *Handle) DumpColStatsUsageToKV() error { + if !variable.EnableColumnTracking.Load() { + return nil + } + h.sweepList() + h.colMap.Lock() + colMap := h.colMap.data + h.colMap.data = make(colStatsUsageMap) + h.colMap.Unlock() + defer func() { + h.colMap.Lock() + h.colMap.data.merge(colMap) + h.colMap.Unlock() + }() + type pair struct { + tblColID model.TableColumnID + lastUsedAt string + } + pairs := make([]pair, 0, len(colMap)) + for id, t := range colMap { + pairs = append(pairs, pair{tblColID: id, lastUsedAt: t.UTC().Format(types.TimeFormat)}) + } + sort.Slice(pairs, func(i, j int) bool { + if pairs[i].tblColID.TableID == pairs[j].tblColID.TableID { + return pairs[i].tblColID.ColumnID < pairs[j].tblColID.ColumnID + } + return pairs[i].tblColID.TableID < pairs[j].tblColID.TableID + }) + // Use batch insert to reduce cost. + for i := 0; i < len(pairs); i += 10 { + end := i + 10 + if end > len(pairs) { + end = len(pairs) + } + sql := new(strings.Builder) + sqlexec.MustFormatSQL(sql, "INSERT INTO mysql.column_stats_usage (table_id, column_id, last_used_at) VALUES ") + for j := i; j < end; j++ { + // Since we will use some session from session pool to execute the insert statement, we pass in UTC time here and covert it + // to the session's time zone when executing the insert statement. In this way we can make the stored time right. + sqlexec.MustFormatSQL(sql, "(%?, %?, CONVERT_TZ(%?, '+00:00', @@TIME_ZONE))", pairs[j].tblColID.TableID, pairs[j].tblColID.ColumnID, pairs[j].lastUsedAt) + if j < end-1 { + sqlexec.MustFormatSQL(sql, ",") + } + } + sqlexec.MustFormatSQL(sql, " ON DUPLICATE KEY UPDATE last_used_at = CASE WHEN last_used_at IS NULL THEN VALUES(last_used_at) ELSE GREATEST(last_used_at, VALUES(last_used_at)) END") + if _, _, err := h.execRestrictedSQL(context.Background(), sql.String()); err != nil { + return errors.Trace(err) + } + for j := i; j < end; j++ { + delete(colMap, pairs[j].tblColID) + } + } + return nil +} + const ( // StatsOwnerKey is the stats owner path that is saved to etcd. StatsOwnerKey = "/tidb/stats/owner" @@ -955,6 +1028,9 @@ func (h *Handle) HandleAutoAnalyze(is infoschema.InfoSchema) (analyzed bool) { } pruneMode := h.CurrentPruneMode() for _, db := range dbs { + if util.IsMemOrSysDB(strings.ToLower(db)) { + continue + } tbls := is.SchemaTables(model.NewCIStr(db)) for _, tbl := range tbls { tblInfo := tbl.Meta() @@ -1027,7 +1103,9 @@ func (h *Handle) autoAnalyzeTable(tblInfo *model.TableInfo, statsTbl *statistics } func (h *Handle) autoAnalyzePartitionTable(tblInfo *model.TableInfo, pi *model.PartitionInfo, db string, start, end time.Time, ratio float64) bool { + h.mu.RLock() tableStatsVer := h.mu.ctx.GetSessionVars().AnalyzeVersion + h.mu.RUnlock() partitionNames := make([]interface{}, 0, len(pi.Definitions)) for _, def := range pi.Definitions { partitionStatsTbl := h.GetPartitionStats(tblInfo, def.ID) @@ -1093,7 +1171,7 @@ var execOptionForAnalyze = map[int]sqlexec.OptionFuncAlias{ func (h *Handle) execAutoAnalyze(statsVer int, sql string, params ...interface{}) { startTime := time.Now() - _, _, err := h.execRestrictedSQLWithStatsVer(context.Background(), statsVer, sql, params...) + _, _, err := h.execRestrictedSQLWithStatsVer(context.Background(), statsVer, util.GetAutoAnalyzeProcID(), sql, params...) dur := time.Since(startTime) metrics.AutoAnalyzeHistogram.Observe(dur.Seconds()) if err != nil { @@ -1247,7 +1325,7 @@ func logForPK(prefix string, c *statistics.Column, ranges []*ranger.Range, actua } } -// RecalculateExpectCount recalculates the expect row count if the origin row count is estimated by pseudo. +// RecalculateExpectCount recalculates the expect row count if the origin row count is estimated by pseudo. Deprecated. func (h *Handle) RecalculateExpectCount(q *statistics.QueryFeedback) error { t, ok := h.statsCache.Load().(statsCache).tables[q.PhysicalID] if !ok { @@ -1361,7 +1439,7 @@ func convertRangeType(ran *ranger.Range, ft *types.FieldType, loc *time.Location return statistics.ConvertDatumsType(ran.HighVal, ft, loc) } -// DumpFeedbackForIndex dumps the feedback for index. +// DumpFeedbackForIndex dumps the feedback for index. Deprecated. // For queries that contains both equality and range query, we will split them and Update accordingly. func (h *Handle) DumpFeedbackForIndex(q *statistics.QueryFeedback, t *statistics.Table) error { idx, ok := t.Indices[q.Hist.ID] diff --git a/statistics/handle/update_test.go b/statistics/handle/update_test.go index 23a061cd96f6a..fddab89cdacc7 100644 --- a/statistics/handle/update_test.go +++ b/statistics/handle/update_test.go @@ -16,95 +16,36 @@ package handle_test import ( "fmt" - "math" "math/rand" - "os" "strconv" "strings" + "testing" "time" - . "github.com/pingcap/check" - "github.com/pingcap/log" - "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/statistics" "github.com/pingcap/tidb/statistics/handle" + "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/ranger" - "github.com/pingcap/tidb/util/testkit" - "github.com/pingcap/tidb/util/testleak" dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/oracle" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" ) -var _ = Suite(&testStatsSuite{}) -var _ = SerialSuites(&testSerialStatsSuite{}) - -type testSerialStatsSuite struct { - store kv.Storage - do *domain.Domain -} - -func (s *testSerialStatsSuite) SetUpSuite(c *C) { - testleak.BeforeTest() - // Add the hook here to avoid data race. - var err error - s.store, s.do, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testSerialStatsSuite) TearDownSuite(c *C) { - s.do.Close() - s.store.Close() - testleak.AfterTest(c)() -} - -type testSuiteBase struct { - store kv.Storage - do *domain.Domain - hook *logHook -} - -type testStatsSuite struct { - testSuiteBase -} - -func (s *testSuiteBase) SetUpSuite(c *C) { - testleak.BeforeTest() - // Add the hook here to avoid data race. - s.registerHook() - var err error - s.store, s.do, err = newStoreWithBootstrap() - c.Assert(err, IsNil) -} - -func (s *testSuiteBase) TearDownSuite(c *C) { - s.do.Close() - s.store.Close() - testleak.AfterTest(c)() -} - -func (s *testSuiteBase) registerHook() { - conf := &log.Config{Level: os.Getenv("log_level"), File: log.FileLogConfig{}} - _, r, _ := log.InitLogger(conf) - s.hook = &logHook{r.Core, ""} - lg := zap.New(s.hook) - log.ReplaceGlobals(lg, r) -} - -func (s *testStatsSuite) TestSingleSessionInsert(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestSingleSessionInsert(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 1") testKit.MustExec("create table t1 (c1 int, c2 int)") testKit.MustExec("create table t2 (c1 int, c2 int)") @@ -117,52 +58,52 @@ func (s *testStatsSuite) TestSingleSessionInsert(c *C) { testKit.MustExec("insert into t2 values(1, 2)") } - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo1 := tbl1.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 := h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) tbl2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo2 := tbl2.Meta() stats2 := h.GetTableStats(tableInfo2) - c.Assert(stats2.Count, Equals, int64(rowCount2)) + require.Equal(t, int64(rowCount2), stats2.Count) testKit.MustExec("analyze table t1") // Test update in a txn. for i := 0; i < rowCount1; i++ { testKit.MustExec("insert into t1 values(1, 2)") } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1*2)) + require.Equal(t, int64(rowCount1*2), stats1.Count) // Test IncreaseFactor. - count, err := stats1.ColumnEqualRowCount(testKit.Se, types.NewIntDatum(1), tableInfo1.Columns[0].ID) - c.Assert(err, IsNil) - c.Assert(count, Equals, float64(rowCount1*2)) + count, err := stats1.ColumnEqualRowCount(testKit.Session(), types.NewIntDatum(1), tableInfo1.Columns[0].ID) + require.NoError(t, err) + require.Equal(t, float64(rowCount1*2), count) testKit.MustExec("begin") for i := 0; i < rowCount1; i++ { testKit.MustExec("insert into t1 values(1, 2)") } testKit.MustExec("commit") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1*3)) + require.Equal(t, int64(rowCount1*3), stats1.Count) testKit.MustExec("begin") for i := 0; i < rowCount1; i++ { @@ -175,20 +116,20 @@ func (s *testStatsSuite) TestSingleSessionInsert(c *C) { testKit.MustExec("update t2 set c2 = c1") } testKit.MustExec("commit") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1*3)) + require.Equal(t, int64(rowCount1*3), stats1.Count) stats2 = h.GetTableStats(tableInfo2) - c.Assert(stats2.Count, Equals, int64(rowCount2)) + require.Equal(t, int64(rowCount2), stats2.Count) testKit.MustExec("begin") testKit.MustExec("delete from t1") testKit.MustExec("commit") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(0)) + require.Equal(t, int64(0), stats1.Count) rs := testKit.MustQuery("select modify_count from mysql.stats_meta") rs.Check(testkit.Rows("40", "70")) @@ -207,52 +148,54 @@ func (s *testStatsSuite) TestSingleSessionInsert(c *C) { testKit.MustExec("insert into t1 values (1,2)") } err = h.DumpStatsDeltaToKV(handle.DumpDelta) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) // not dumped testKit.MustExec("insert into t1 values (1,2)") err = h.DumpStatsDeltaToKV(handle.DumpDelta) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) h.FlushStats() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1+1)) + require.Equal(t, int64(rowCount1+1), stats1.Count) } -func (s *testStatsSuite) TestRollback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestRollback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int)") testKit.MustExec("begin") testKit.MustExec("insert into t values (1,2)") testKit.MustExec("rollback") - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats := h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(0)) - c.Assert(stats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(0), stats.Count) + require.Equal(t, int64(0), stats.ModifyCount) } -func (s *testStatsSuite) TestMultiSession(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestMultiSession(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t1 (c1 int, c2 int)") @@ -261,27 +204,27 @@ func (s *testStatsSuite) TestMultiSession(c *C) { testKit.MustExec("insert into t1 values(1, 2)") } - testKit1 := testkit.NewTestKit(c, s.store) + testKit1 := testkit.NewTestKit(t, store) for i := 0; i < rowCount1; i++ { testKit1.MustExec("insert into test.t1 values(1, 2)") } - testKit2 := testkit.NewTestKit(c, s.store) + testKit2 := testkit.NewTestKit(t, store) for i := 0; i < rowCount1; i++ { testKit2.MustExec("delete from test.t1 limit 1") } - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo1 := tbl1.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 := h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) for i := 0; i < rowCount1; i++ { testKit.MustExec("insert into t1 values(1, 2)") @@ -295,124 +238,126 @@ func (s *testStatsSuite) TestMultiSession(c *C) { testKit2.MustExec("delete from test.t1 limit 1") } - testKit.Se.Close() - testKit2.Se.Close() + testKit.Session().Close() + testKit2.Session().Close() - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1*2)) - // The session in testKit is already Closed, set it to nil will create a new session. - testKit.Se = nil + require.Equal(t, int64(rowCount1*2), stats1.Count) + testKit.RefreshSession() rs := testKit.MustQuery("select modify_count from mysql.stats_meta") rs.Check(testkit.Rows("60")) } -func (s *testStatsSuite) TestTxnWithFailure(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestTxnWithFailure(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t1 (c1 int primary key, c2 int)") - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo1 := tbl1.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) rowCount1 := 10 testKit.MustExec("begin") for i := 0; i < rowCount1; i++ { testKit.MustExec("insert into t1 values(?, 2)", i) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 := h.GetTableStats(tableInfo1) // have not commit - c.Assert(stats1.Count, Equals, int64(0)) + require.Equal(t, int64(0), stats1.Count) testKit.MustExec("commit") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) _, err = testKit.Exec("insert into t1 values(0, 2)") - c.Assert(err, NotNil) + require.Error(t, err) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1)) + require.Equal(t, int64(rowCount1), stats1.Count) testKit.MustExec("insert into t1 values(-1, 2)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) stats1 = h.GetTableStats(tableInfo1) - c.Assert(stats1.Count, Equals, int64(rowCount1+1)) + require.Equal(t, int64(rowCount1+1), stats1.Count) } -func (s *testStatsSuite) TestUpdatePartition(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - testKit.MustQuery("select @@tidb_partition_prune_mode").Check(testkit.Rows(string(s.do.StatsHandle().CurrentPruneMode()))) +func TestUpdatePartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + testKit.MustQuery("select @@tidb_partition_prune_mode").Check(testkit.Rows(string(dom.StatsHandle().CurrentPruneMode()))) testKit.MustExec("use test") testkit.WithPruneMode(testKit, variable.Static, func() { - err := s.do.StatsHandle().RefreshVars() - c.Assert(err, IsNil) + err := dom.StatsHandle().RefreshVars() + require.NoError(t, err) testKit.MustExec("drop table if exists t") createTable := `CREATE TABLE t (a int, b char(5)) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11))` testKit.MustExec(createTable) - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() h := do.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) pi := tableInfo.GetPartitionInfo() - c.Assert(len(pi.Definitions), Equals, 2) + require.Len(t, pi.Definitions, 2) bColID := tableInfo.Columns[1].ID testKit.MustExec(`insert into t values (1, "a"), (7, "a")`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) for _, def := range pi.Definitions { statsTbl := h.GetPartitionStats(tableInfo, def.ID) - c.Assert(statsTbl.ModifyCount, Equals, int64(1)) - c.Assert(statsTbl.Count, Equals, int64(1)) - c.Assert(statsTbl.Columns[bColID].TotColSize, Equals, int64(2)) + require.Equal(t, int64(1), statsTbl.ModifyCount) + require.Equal(t, int64(1), statsTbl.Count) + require.Equal(t, int64(2), statsTbl.Columns[bColID].TotColSize) } testKit.MustExec(`update t set a = a + 1, b = "aa"`) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) for _, def := range pi.Definitions { statsTbl := h.GetPartitionStats(tableInfo, def.ID) - c.Assert(statsTbl.ModifyCount, Equals, int64(2)) - c.Assert(statsTbl.Count, Equals, int64(1)) - c.Assert(statsTbl.Columns[bColID].TotColSize, Equals, int64(3)) + require.Equal(t, int64(2), statsTbl.ModifyCount) + require.Equal(t, int64(1), statsTbl.Count) + require.Equal(t, int64(3), statsTbl.Columns[bColID].TotColSize) } testKit.MustExec("delete from t") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) for _, def := range pi.Definitions { statsTbl := h.GetPartitionStats(tableInfo, def.ID) - c.Assert(statsTbl.ModifyCount, Equals, int64(3)) - c.Assert(statsTbl.Count, Equals, int64(0)) - c.Assert(statsTbl.Columns[bColID].TotColSize, Equals, int64(0)) + require.Equal(t, int64(3), statsTbl.ModifyCount) + require.Equal(t, int64(0), statsTbl.Count) + require.Equal(t, int64(0), statsTbl.Columns[bColID].TotColSize) } }) } -func (s *testStatsSuite) TestAutoUpdate(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestAutoUpdate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testkit.WithPruneMode(testKit, variable.Static, func() { testKit.MustExec("use test") testKit.MustExec("create table t (a varchar(20))") @@ -424,31 +369,31 @@ func (s *testStatsSuite) TestAutoUpdate(c *C) { testKit.MustExec("set global tidb_auto_analyze_ratio = 0.0") }() - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() h := do.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) stats := h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(0)) + require.Equal(t, int64(0), stats.Count) _, err = testKit.Exec("insert into t values ('ss'), ('ss'), ('ss'), ('ss'), ('ss')") - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats = h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(5)) - c.Assert(stats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(5), stats.Count) + require.Equal(t, int64(0), stats.ModifyCount) for _, item := range stats.Columns { // TotColSize = 5*(2(length of 'ss') + 1(size of len byte)). - c.Assert(item.TotColSize, Equals, int64(15)) + require.Equal(t, int64(15), item.TotColSize) break } @@ -456,64 +401,65 @@ func (s *testStatsSuite) TestAutoUpdate(c *C) { h.SetLease(time.Second) defer func() { h.SetLease(0) }() _, err = testKit.Exec("insert into t values ('fff')") - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats = h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(6)) - c.Assert(stats.ModifyCount, Equals, int64(1)) + require.Equal(t, int64(6), stats.Count) + require.Equal(t, int64(1), stats.ModifyCount) _, err = testKit.Exec("insert into t values ('fff')") - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats = h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(7)) - c.Assert(stats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(7), stats.Count) + require.Equal(t, int64(0), stats.ModifyCount) _, err = testKit.Exec("insert into t values ('eee')") - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats = h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(8)) + require.Equal(t, int64(8), stats.Count) // Modify count is non-zero means that we do not analyze the table. - c.Assert(stats.ModifyCount, Equals, int64(1)) + require.Equal(t, int64(1), stats.ModifyCount) for _, item := range stats.Columns { // TotColSize = 27, because the table has not been analyzed, and insert statement will add 3(length of 'eee') to TotColSize. - c.Assert(item.TotColSize, Equals, int64(27)) + require.Equal(t, int64(27), item.TotColSize) break } testKit.MustExec("analyze table t") _, err = testKit.Exec("create index idx on t(a)") - c.Assert(err, IsNil) + require.NoError(t, err) is = do.InfoSchema() tbl, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo = tbl.Meta() h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats = h.GetTableStats(tableInfo) - c.Assert(stats.Count, Equals, int64(8)) - c.Assert(stats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(8), stats.Count) + require.Equal(t, int64(0), stats.ModifyCount) hg, ok := stats.Indices[tableInfo.Indices[0].ID] - c.Assert(ok, IsTrue) - c.Assert(hg.NDV, Equals, int64(3)) - c.Assert(hg.Len(), Equals, 0) - c.Assert(hg.TopN.Num(), Equals, 3) + require.True(t, ok) + require.Equal(t, int64(3), hg.NDV) + require.Equal(t, 0, hg.Len()) + require.Equal(t, 3, hg.TopN.Num()) }) } -func (s *testStatsSuite) TestAutoUpdatePartition(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestAutoUpdatePartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testkit.WithPruneMode(testKit, variable.Static, func() { testKit.MustExec("use test") testKit.MustExec("drop table if exists t") @@ -527,32 +473,33 @@ func (s *testStatsSuite) TestAutoUpdatePartition(c *C) { testKit.MustExec("set global tidb_auto_analyze_ratio = 0.0") }() - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() pi := tableInfo.GetPartitionInfo() h := do.StatsHandle() - c.Assert(h.RefreshVars(), IsNil) + require.NoError(t, h.RefreshVars()) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) stats := h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) - c.Assert(stats.Count, Equals, int64(0)) + require.Equal(t, int64(0), stats.Count) testKit.MustExec("insert into t values (1)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) stats = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) - c.Assert(stats.Count, Equals, int64(1)) - c.Assert(stats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(1), stats.Count) + require.Equal(t, int64(0), stats.ModifyCount) }) } -func (s *testSerialStatsSuite) TestAutoAnalyzeOnEmptyTable(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAutoAnalyzeOnEmptyTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) @@ -561,12 +508,12 @@ func (s *testSerialStatsSuite) TestAutoAnalyzeOnEmptyTable(c *C) { tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", oriEnd)) }() - t := time.Now().Add(-1 * time.Minute) - h, m := t.Hour(), t.Minute() + tt := time.Now().Add(-1 * time.Minute) + h, m := tt.Hour(), tt.Minute() start, end := fmt.Sprintf("%02d:%02d +0000", h, m), fmt.Sprintf("%02d:%02d +0000", h, m) tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_start_time='%v'", start)) tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", end)) - s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()) + dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema()) tk.MustExec("use test") tk.MustExec("create table t (a int, index idx(a))") @@ -574,20 +521,21 @@ func (s *testSerialStatsSuite) TestAutoAnalyzeOnEmptyTable(c *C) { tk.MustExec("analyze table t") // to pass the AutoAnalyzeMinCnt check in autoAnalyzeTable tk.MustExec("insert into t values (1)" + strings.Repeat(", (1)", int(handle.AutoAnalyzeMinCnt))) - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) // test if it will be limited by the time range - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsFalse) + require.False(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) tk.MustExec("set global tidb_auto_analyze_start_time='00:00 +0000'") tk.MustExec("set global tidb_auto_analyze_end_time='23:59 +0000'") - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsTrue) + require.True(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) } -func (s *testSerialStatsSuite) TestAutoAnalyzeOutOfSpecifiedTime(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAutoAnalyzeOutOfSpecifiedTime(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) @@ -596,12 +544,12 @@ func (s *testSerialStatsSuite) TestAutoAnalyzeOutOfSpecifiedTime(c *C) { tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", oriEnd)) }() - t := time.Now().Add(-1 * time.Minute) - h, m := t.Hour(), t.Minute() + tt := time.Now().Add(-1 * time.Minute) + h, m := tt.Hour(), tt.Minute() start, end := fmt.Sprintf("%02d:%02d +0000", h, m), fmt.Sprintf("%02d:%02d +0000", h, m) tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_start_time='%v'", start)) tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", end)) - s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()) + dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema()) tk.MustExec("use test") tk.MustExec("create table t (a int)") @@ -609,23 +557,24 @@ func (s *testSerialStatsSuite) TestAutoAnalyzeOutOfSpecifiedTime(c *C) { tk.MustExec("analyze table t") // to pass the AutoAnalyzeMinCnt check in autoAnalyzeTable tk.MustExec("insert into t values (1)" + strings.Repeat(", (1)", int(handle.AutoAnalyzeMinCnt))) - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsFalse) + require.False(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) tk.MustExec("analyze table t") tk.MustExec("alter table t add index ia(a)") - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsFalse) + require.False(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) tk.MustExec("set global tidb_auto_analyze_start_time='00:00 +0000'") tk.MustExec("set global tidb_auto_analyze_end_time='23:59 +0000'") - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsTrue) + require.True(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) } -func (s *testSerialStatsSuite) TestIssue25700(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestIssue25700(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) defer func() { @@ -640,108 +589,110 @@ func (s *testSerialStatsSuite) TestIssue25700(c *C) { tk.MustExec("CREATE TABLE `t` ( `ldecimal` decimal(32,4) DEFAULT NULL, `rdecimal` decimal(32,4) DEFAULT NULL, `gen_col` decimal(36,4) GENERATED ALWAYS AS (`ldecimal` + `rdecimal`) VIRTUAL, `col_timestamp` timestamp(3) NULL DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") tk.MustExec("analyze table t") tk.MustExec("INSERT INTO `t` (`ldecimal`, `rdecimal`, `col_timestamp`) VALUES (2265.2200, 9843.4100, '1999-12-31 16:00:00')" + strings.Repeat(", (2265.2200, 9843.4100, '1999-12-31 16:00:00')", int(handle.AutoAnalyzeMinCnt))) - c.Assert(s.do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(s.do.StatsHandle().Update(s.do.InfoSchema()), IsNil) + require.NoError(t, dom.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, dom.StatsHandle().Update(dom.InfoSchema())) - c.Assert(s.do.StatsHandle().HandleAutoAnalyze(s.do.InfoSchema()), IsTrue) - c.Assert(tk.MustQuery("show analyze status").Rows()[1][7], Equals, "finished") + require.True(t, dom.StatsHandle().HandleAutoAnalyze(dom.InfoSchema())) + require.Equal(t, "finished", tk.MustQuery("show analyze status").Rows()[1][7]) } -func (s *testSerialStatsSuite) TestAutoAnalyzeOnChangeAnalyzeVer(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAutoAnalyzeOnChangeAnalyzeVer(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t(a int, index idx(a))") tk.MustExec("insert into t values(1)") tk.MustExec("set @@global.tidb_analyze_version = 1") - do := s.do + do := dom handle.AutoAnalyzeMinCnt = 0 defer func() { handle.AutoAnalyzeMinCnt = 1000 }() h := do.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) is := do.InfoSchema() err = h.UpdateSessionVar() - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) // Auto analyze when global ver is 1. h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) statsTbl1 := h.GetTableStats(tbl.Meta()) // Check that all the version of t's stats are 1. for _, col := range statsTbl1.Columns { - c.Assert(col.StatsVer, Equals, int64(1)) + require.Equal(t, int64(1), col.StatsVer) } for _, idx := range statsTbl1.Indices { - c.Assert(idx.StatsVer, Equals, int64(1)) + require.Equal(t, int64(1), idx.StatsVer) } tk.MustExec("set @@global.tidb_analyze_version = 2") err = h.UpdateSessionVar() - c.Assert(err, IsNil) + require.NoError(t, err) tk.MustExec("insert into t values(1), (2), (3), (4)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) // Auto analyze t whose version is 1 after setting global ver to 2. h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl1 = h.GetTableStats(tbl.Meta()) - c.Assert(statsTbl1.Count, Equals, int64(5)) + require.Equal(t, int64(5), statsTbl1.Count) // All of its statistics should still be version 1. for _, col := range statsTbl1.Columns { - c.Assert(col.StatsVer, Equals, int64(1)) + require.Equal(t, int64(1), col.StatsVer) } for _, idx := range statsTbl1.Indices { - c.Assert(idx.StatsVer, Equals, int64(1)) + require.Equal(t, int64(1), idx.StatsVer) } // Add a new table after the analyze version set to 2. tk.MustExec("create table tt(a int, index idx(a))") tk.MustExec("insert into tt values(1), (2), (3), (4), (5)") err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) is = do.InfoSchema() tbl2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("tt")) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, err) + require.NoError(t, h.Update(is)) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl2 := h.GetTableStats(tbl2.Meta()) // Since it's a newly created table. Auto analyze should analyze it's statistics to version2. for _, idx := range statsTbl2.Indices { - c.Assert(idx.StatsVer, Equals, int64(2)) + require.Equal(t, int64(2), idx.StatsVer) } for _, col := range statsTbl2.Columns { - c.Assert(col.StatsVer, Equals, int64(2)) + require.Equal(t, int64(2), col.StatsVer) } tk.MustExec("set @@global.tidb_analyze_version = 1") } -func (s *testStatsSuite) TestTableAnalyzed(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestTableAnalyzed(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (a int)") testKit.MustExec("insert into t values (1)") - is := s.do.InfoSchema() + is := dom.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl := h.GetTableStats(tableInfo) - c.Assert(handle.TableAnalyzed(statsTbl), IsFalse) + require.False(t, handle.TableAnalyzed(statsTbl)) testKit.MustExec("analyze table t") - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl = h.GetTableStats(tableInfo) - c.Assert(handle.TableAnalyzed(statsTbl), IsTrue) + require.True(t, handle.TableAnalyzed(statsTbl)) h.Clear() oriLease := h.Lease() @@ -750,17 +701,18 @@ func (s *testStatsSuite) TestTableAnalyzed(c *C) { defer func() { h.SetLease(oriLease) }() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) statsTbl = h.GetTableStats(tableInfo) - c.Assert(handle.TableAnalyzed(statsTbl), IsTrue) + require.True(t, handle.TableAnalyzed(statsTbl)) } -func (s *testStatsSuite) TestUpdateErrorRate(c *C) { - defer cleanEnv(c, s.store, s.do) - h := s.do.StatsHandle() - is := s.do.InfoSchema() +func TestUpdateErrorRate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + h := dom.StatsHandle() + is := dom.InfoSchema() h.SetLease(0) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() oriErrorRate := handle.MinLogErrorRate.Load() @@ -773,70 +725,72 @@ func (s *testStatsSuite) TestUpdateErrorRate(c *C) { handle.MinLogScanCount.Store(0) handle.MinLogErrorRate.Store(0) - testKit := testkit.NewTestKit(c, s.store) + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec("create table t (a bigint(64), b bigint(64), primary key(a), index idx(b))") err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) testKit.MustExec("insert into t values (1, 3)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") testKit.MustExec("insert into t values (2, 3)") testKit.MustExec("insert into t values (5, 3)") testKit.MustExec("insert into t values (8, 3)") testKit.MustExec("insert into t values (12, 3)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - is = s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + is = dom.InfoSchema() + require.NoError(t, h.Update(is)) table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() tbl := h.GetTableStats(tblInfo) aID := tblInfo.Columns[0].ID bID := tblInfo.Indices[0].ID // The statistic table is outdated now. - c.Assert(tbl.Columns[aID].NotAccurate(), IsTrue) + require.True(t, tbl.Columns[aID].NotAccurate()) testKit.MustQuery("select * from t where a between 1 and 10") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(is)) h.UpdateErrorRate(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl = h.GetTableStats(tblInfo) // The error rate of this column is not larger than MaxErrorRate now. - c.Assert(tbl.Columns[aID].NotAccurate(), IsFalse) + require.False(t, tbl.Columns[aID].NotAccurate()) - c.Assert(tbl.Indices[bID].NotAccurate(), IsTrue) + require.True(t, tbl.Indices[bID].NotAccurate()) testKit.MustQuery("select * from t where b between 2 and 10") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(is)) h.UpdateErrorRate(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl = h.GetTableStats(tblInfo) - c.Assert(tbl.Indices[bID].NotAccurate(), IsFalse) - c.Assert(tbl.Indices[bID].QueryTotal, Equals, int64(1)) + require.False(t, tbl.Indices[bID].NotAccurate()) + require.Equal(t, int64(1), tbl.Indices[bID].QueryTotal) testKit.MustExec("analyze table t") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) tbl = h.GetTableStats(tblInfo) - c.Assert(tbl.Indices[bID].QueryTotal, Equals, int64(0)) + require.Equal(t, int64(0), tbl.Indices[bID].QueryTotal) } -func (s *testStatsSuite) TestUpdatePartitionErrorRate(c *C) { - defer cleanEnv(c, s.store, s.do) - h := s.do.StatsHandle() - is := s.do.InfoSchema() +func TestUpdatePartitionErrorRate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + h := dom.StatsHandle() + is := dom.InfoSchema() h.SetLease(0) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() oriErrorRate := handle.MinLogErrorRate.Load() @@ -849,46 +803,46 @@ func (s *testStatsSuite) TestUpdatePartitionErrorRate(c *C) { handle.MinLogScanCount.Store(0) handle.MinLogErrorRate.Store(0) - testKit := testkit.NewTestKit(c, s.store) + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) testKit.MustExec("create table t (a bigint(64), primary key(a)) partition by range (a) (partition p0 values less than (30))") err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) testKit.MustExec("insert into t values (1)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") testKit.MustExec("insert into t values (2)") testKit.MustExec("insert into t values (5)") testKit.MustExec("insert into t values (8)") testKit.MustExec("insert into t values (12)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - is = s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + is = dom.InfoSchema() + require.NoError(t, h.Update(is)) table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() pid := tblInfo.Partition.Definitions[0].ID tbl := h.GetPartitionStats(tblInfo, pid) aID := tblInfo.Columns[0].ID // The statistic table is outdated now. - c.Assert(tbl.Columns[aID].NotAccurate(), IsTrue) + require.True(t, tbl.Columns[aID].NotAccurate()) testKit.MustQuery("select * from t where a between 1 and 10") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(is)) h.UpdateErrorRate(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl = h.GetPartitionStats(tblInfo, pid) // Feedback will not take effect under partition table. - c.Assert(tbl.Columns[aID].NotAccurate(), IsTrue) + require.True(t, tbl.Columns[aID].NotAccurate()) } func appendBucket(h *statistics.Histogram, l, r int64) { @@ -896,7 +850,7 @@ func appendBucket(h *statistics.Histogram, l, r int64) { h.AppendBucket(&lower, &upper, 0, 0) } -func (s *testStatsSuite) TestSplitRange(c *C) { +func TestSplitRange(t *testing.T) { h := statistics.NewHistogram(0, 0, 0, 0, types.NewFieldType(mysql.TypeLong), 5, 0) appendBucket(h, 1, 1) appendBucket(h, 2, 5) @@ -931,14 +885,14 @@ func (s *testStatsSuite) TestSplitRange(c *C) { result: "[8,9)", }, } - for _, t := range tests { - ranges := make([]*ranger.Range, 0, len(t.points)/2) - for i := 0; i < len(t.points); i += 2 { + for _, test := range tests { + ranges := make([]*ranger.Range, 0, len(test.points)/2) + for i := 0; i < len(test.points); i += 2 { ranges = append(ranges, &ranger.Range{ - LowVal: []types.Datum{types.NewIntDatum(t.points[i])}, - LowExclude: t.exclude[i], - HighVal: []types.Datum{types.NewIntDatum(t.points[i+1])}, - HighExclude: t.exclude[i+1], + LowVal: []types.Datum{types.NewIntDatum(test.points[i])}, + LowExclude: test.exclude[i], + HighVal: []types.Datum{types.NewIntDatum(test.points[i+1])}, + HighExclude: test.exclude[i+1], Collators: collate.GetBinaryCollatorSlice(1), }) } @@ -947,20 +901,22 @@ func (s *testStatsSuite) TestSplitRange(c *C) { for _, ran := range ranges { ranStrs = append(ranStrs, ran.String()) } - c.Assert(strings.Join(ranStrs, ","), Equals, t.result) + require.Equal(t, test.result, strings.Join(ranStrs, ",")) } } -func (s *testStatsSuite) TestQueryFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestQueryFeedback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec("create table t (a bigint(64), b bigint(64), primary key(a), index idx(b))") testKit.MustExec("insert into t values (1,2),(2,2),(4,5)") testKit.MustExec("analyze table t with 0 topn") testKit.MustExec("insert into t values (3,4)") - h := s.do.StatsHandle() + h := dom.StatsHandle() oriProbability := statistics.FeedbackProbability.Load() oriNumber := statistics.MaxNumberOfRanges oriMinLogCount := handle.MinLogScanCount.Load() @@ -1005,74 +961,76 @@ func (s *testStatsSuite) TestQueryFeedback(c *C) { idxCols: 1, }, } - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - for i, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + for i, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, err) + require.NoError(t, h.Update(is)) tblInfo := table.Meta() tbl := h.GetTableStats(tblInfo) - if t.idxCols == 0 { - c.Assert(tbl.Columns[tblInfo.Columns[0].ID].ToString(0), Equals, tests[i].hist) + if test.idxCols == 0 { + require.Equal(t, tests[i].hist, tbl.Columns[tblInfo.Columns[0].ID].ToString(0)) } else { - c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, tests[i].hist) + require.Equal(t, tests[i].hist, tbl.Indices[tblInfo.Indices[0].ID].ToString(1)) } } // Feedback from limit executor may not be accurate. testKit.MustQuery("select * from t where t.a <= 5 limit 1") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) feedback := h.GetQueryFeedback() - c.Assert(feedback.Size, Equals, 0) + require.Equal(t, 0, feedback.Size) // Test only collect for max number of Ranges. statistics.MaxNumberOfRanges = 0 - for _, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + for _, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) feedback := h.GetQueryFeedback() - c.Assert(feedback.Size, Equals, 0) + require.Equal(t, 0, feedback.Size) } // Test collect feedback by probability. statistics.FeedbackProbability.Store(0) statistics.MaxNumberOfRanges = oriNumber - for _, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + for _, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) feedback := h.GetQueryFeedback() - c.Assert(feedback.Size, Equals, 0) + require.Equal(t, 0, feedback.Size) } // Test that after drop stats, the feedback won't cause panic. statistics.FeedbackProbability.Store(1) - for _, t := range tests { - testKit.MustQuery(t.sql) + for _, test := range tests { + testKit.MustQuery(test.sql) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) testKit.MustExec("drop stats t") - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) // Test that the outdated feedback won't cause panic. testKit.MustExec("analyze table t") - for _, t := range tests { - testKit.MustQuery(t.sql) + for _, test := range tests { + testKit.MustQuery(test.sql) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) testKit.MustExec("drop table t") - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) } -func (s *testStatsSuite) TestQueryFeedbackForPartition(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestQueryFeedbackForPartition(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) testKit.MustExec(`create table t (a bigint(64), b bigint(64), primary key(a), index idx(b)) partition by range (a) ( @@ -1093,7 +1051,7 @@ func (s *testStatsSuite) TestQueryFeedbackForPartition(c *C) { handle.MinLogScanCount.Store(0) handle.MinLogErrorRate.Store(0) - h := s.do.StatsHandle() + h := dom.StatsHandle() // Feedback will not take effect under partition table. tests := []struct { sql string @@ -1123,12 +1081,12 @@ func (s *testStatsSuite) TestQueryFeedbackForPartition(c *C) { idxCols: 1, }, } - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() pi := tblInfo.GetPartitionInfo() - c.Assert(pi, NotNil) + require.NotNil(t, pi) // This test will check the result of partition p0. var pid int64 @@ -1139,80 +1097,84 @@ func (s *testStatsSuite) TestQueryFeedbackForPartition(c *C) { } } - for i, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + for i, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, err) + require.NoError(t, h.Update(is)) tbl := h.GetPartitionStats(tblInfo, pid) - if t.idxCols == 0 { - c.Assert(tbl.Columns[tblInfo.Columns[0].ID].ToString(0), Equals, tests[i].hist) + if test.idxCols == 0 { + require.Equal(t, tests[i].hist, tbl.Columns[tblInfo.Columns[0].ID].ToString(0)) } else { - c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, tests[i].hist) + require.Equal(t, tests[i].hist, tbl.Indices[tblInfo.Indices[0].ID].ToString(1)) } } testKit.MustExec("drop table t") } -func (s *testStatsSuite) TestUpdateSystemTable(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestUpdateSystemTable(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int)") testKit.MustExec("insert into t values (1,2)") testKit.MustExec("analyze table t") testKit.MustExec("analyze table mysql.stats_histograms") - h := s.do.StatsHandle() - c.Assert(h.Update(s.do.InfoSchema()), IsNil) + h := dom.StatsHandle() + require.NoError(t, h.Update(dom.InfoSchema())) feedback := h.GetQueryFeedback() // We may have query feedback for system tables, but we do not need to store them. - c.Assert(feedback.Size, Equals, 0) + require.Equal(t, 0, feedback.Size) } -func (s *testStatsSuite) TestOutOfOrderUpdate(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestOutOfOrderUpdate(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int)") testKit.MustExec("insert into t values (1,2)") - do := s.do + do := dom is := do.InfoSchema() tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() h := do.StatsHandle() err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) // Simulate the case that another tidb has inserted some value, but delta info has not been dumped to kv yet. testKit.MustExec("insert into t values (2,2),(4,5)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec(fmt.Sprintf("update mysql.stats_meta set count = 1 where table_id = %d", tableInfo.ID)) testKit.MustExec("delete from t") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustQuery("select count from mysql.stats_meta").Check(testkit.Rows("1")) // Now another tidb has updated the delta info. testKit.MustExec(fmt.Sprintf("update mysql.stats_meta set count = 3 where table_id = %d", tableInfo.ID)) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustQuery("select count from mysql.stats_meta").Check(testkit.Rows("0")) } -func (s *testStatsSuite) TestUpdateStatsByLocalFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestUpdateStatsByLocalFeedback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) testKit.MustExec("create table t (a bigint(64), b bigint(64), primary key(a), index idx(b))") testKit.MustExec("insert into t values (1,2),(2,2),(4,5)") testKit.MustExec("analyze table t with 0 topn") testKit.MustExec("insert into t values (3,5)") - h := s.do.StatsHandle() + h := dom.StatsHandle() oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() oriErrorRate := handle.MinLogErrorRate.Load() @@ -1227,9 +1189,9 @@ func (s *testStatsSuite) TestUpdateStatsByLocalFeedback(c *C) { handle.MinLogScanCount.Store(0) handle.MinLogErrorRate.Store(0) - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() h.GetTableStats(tblInfo) @@ -1238,41 +1200,43 @@ func (s *testStatsSuite) TestUpdateStatsByLocalFeedback(c *C) { testKit.MustQuery("select * from t where a > 1") testKit.MustQuery("select * from t use index(idx) where b = 5") - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) tbl := h.GetTableStats(tblInfo) - c.Assert(tbl.Columns[tblInfo.Columns[0].ID].ToString(0), Equals, "column:1 ndv:3 totColSize:0\n"+ + require.Equal(t, "column:1 ndv:3 totColSize:0\n"+ "num: 1 lower_bound: 1 upper_bound: 1 repeats: 1 ndv: 0\n"+ "num: 2 lower_bound: 2 upper_bound: 4 repeats: 0 ndv: 0\n"+ - "num: 1 lower_bound: 4 upper_bound: 9223372036854775807 repeats: 0 ndv: 0") + "num: 1 lower_bound: 4 upper_bound: 9223372036854775807 repeats: 0 ndv: 0", tbl.Columns[tblInfo.Columns[0].ID].ToString(0)) sc := &stmtctx.StatementContext{TimeZone: time.Local} low, err := codec.EncodeKey(sc, nil, types.NewIntDatum(5)) - c.Assert(err, IsNil) + require.NoError(t, err) - c.Assert(tbl.Indices[tblInfo.Indices[0].ID].CMSketch.QueryBytes(low), Equals, uint64(2)) + require.Equal(t, uint64(2), tbl.Indices[tblInfo.Indices[0].ID].CMSketch.QueryBytes(low)) - c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, "index:1 ndv:2\n"+ + require.Equal(t, "index:1 ndv:2\n"+ "num: 2 lower_bound: -inf upper_bound: 5 repeats: 0 ndv: 0\n"+ - "num: 1 lower_bound: 5 upper_bound: 5 repeats: 1 ndv: 0") + "num: 1 lower_bound: 5 upper_bound: 5 repeats: 1 ndv: 0", tbl.Indices[tblInfo.Indices[0].ID].ToString(1)) // Test that it won't cause panic after update. testKit.MustQuery("select * from t use index(idx) where b > 0") // Test that after drop stats, it won't cause panic. testKit.MustExec("drop stats t") - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) } -func (s *testStatsSuite) TestUpdatePartitionStatsByLocalFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestUpdatePartitionStatsByLocalFeedback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`) testKit.MustExec("create table t (a bigint(64), b bigint(64), primary key(a)) partition by range (a) (partition p0 values less than (6))") testKit.MustExec("insert into t values (1,2),(2,2),(4,5)") testKit.MustExec("analyze table t") testKit.MustExec("insert into t values (3,5)") - h := s.do.StatsHandle() + h := dom.StatsHandle() oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() oriErrorRate := handle.MinLogErrorRate.Load() @@ -1285,28 +1249,29 @@ func (s *testStatsSuite) TestUpdatePartitionStatsByLocalFeedback(c *C) { handle.MinLogScanCount.Store(0) handle.MinLogErrorRate.Store(0) - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) - testKit.MustQuery("select * from t where a > 1") + testKit.MustQuery("select * from t where a > 1").Check(testkit.Rows("2 2", "3 5", "4 5")) - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) tblInfo := table.Meta() pid := tblInfo.Partition.Definitions[0].ID tbl := h.GetPartitionStats(tblInfo, pid) // Feedback will not take effect under partition table. - c.Assert(tbl.Columns[tblInfo.Columns[0].ID].ToString(0), Equals, "column:1 ndv:3 totColSize:0\n"+ + require.Equal(t, "column:1 ndv:3 totColSize:0\n"+ "num: 1 lower_bound: 1 upper_bound: 1 repeats: 1 ndv: 0\n"+ "num: 1 lower_bound: 2 upper_bound: 2 repeats: 1 ndv: 0\n"+ - "num: 1 lower_bound: 4 upper_bound: 4 repeats: 1 ndv: 0") + "num: 1 lower_bound: 4 upper_bound: 4 repeats: 1 ndv: 0", tbl.Columns[tblInfo.Columns[0].ID].ToString(0)) } -func (s *testStatsSuite) TestFeedbackWithStatsVer2(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestFeedbackWithStatsVer2(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testKit.MustExec("use test") testKit.MustExec("set global tidb_analyze_version = 1") testKit.MustExec("set @@tidb_analyze_version = 1") @@ -1337,14 +1302,14 @@ func (s *testStatsSuite) TestFeedbackWithStatsVer2(c *C) { testKit.MustExec("insert into t values (1,2),(2,2),(4,5),(2,3),(3,4)") } testKit.MustExec("analyze table t with 0 topn") - h := s.do.StatsHandle() - is := s.do.InfoSchema() + h := dom.StatsHandle() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() testKit.MustExec("analyze table t") - err = h.Update(s.do.InfoSchema()) - c.Assert(err, IsNil) + err = h.Update(dom.InfoSchema()) + require.NoError(t, err) statsTblBefore := h.GetTableStats(tblInfo) statistics.FeedbackProbability.Store(1) // make the statistics inaccurate. @@ -1355,14 +1320,14 @@ func (s *testStatsSuite) TestFeedbackWithStatsVer2(c *C) { testKit.MustExec("select * from t where t.a <= 5 order by a desc") testKit.MustExec("select b from t use index(idx) where t.b <= 5") - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) err = h.DumpStatsFeedbackToKV() - c.Assert(err, IsNil) - err = h.HandleUpdateStats(s.do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, err) + err = h.HandleUpdateStats(dom.InfoSchema()) + require.NoError(t, err) statsTblAfter := h.GetTableStats(tblInfo) // assert that statistics not changed - assertTableEqual(c, statsTblBefore, statsTblAfter) + assertTableEqual(t, statsTblBefore, statsTblAfter) // Case 3: Feedback is still effective on version 1 statistics. testKit.MustExec("set tidb_analyze_version = 1") @@ -1375,22 +1340,22 @@ func (s *testStatsSuite) TestFeedbackWithStatsVer2(c *C) { for i := 0; i < 200; i++ { testKit.MustExec("insert into t1 values (3,4), (3,4), (3,4), (3,4), (3,4)") } - is = s.do.InfoSchema() + is = dom.InfoSchema() table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo = table.Meta() statsTblBefore = h.GetTableStats(tblInfo) // trigger feedback testKit.MustExec("select b from t1 use index(idx) where t1.b <= 5") - h.UpdateStatsByLocalFeedback(s.do.InfoSchema()) + h.UpdateStatsByLocalFeedback(dom.InfoSchema()) err = h.DumpStatsFeedbackToKV() - c.Assert(err, IsNil) - err = h.HandleUpdateStats(s.do.InfoSchema()) - c.Assert(err, IsNil) + require.NoError(t, err) + err = h.HandleUpdateStats(dom.InfoSchema()) + require.NoError(t, err) statsTblAfter = h.GetTableStats(tblInfo) // assert that statistics changed(feedback worked) - c.Assert(statistics.HistogramEqual(&statsTblBefore.Indices[1].Histogram, &statsTblAfter.Indices[1].Histogram, false), IsFalse) + require.False(t, statistics.HistogramEqual(&statsTblBefore.Indices[1].Histogram, &statsTblAfter.Indices[1].Histogram, false)) // Case 4: When existing version 1 stats + tidb_analyze_version=2 + feedback enabled, explicitly running `analyze table` still results in version 1 stats. statistics.FeedbackProbability.Store(0) @@ -1405,106 +1370,7 @@ func (s *testStatsSuite) TestFeedbackWithStatsVer2(c *C) { testKit.MustExec("set global tidb_analyze_version = 1") } -type logHook struct { - zapcore.Core - results string -} - -func (h *logHook) Write(entry zapcore.Entry, fields []zapcore.Field) error { - message := entry.Message - if idx := strings.Index(message, "[stats"); idx != -1 { - h.results = h.results + message - for _, f := range fields { - h.results = h.results + ", " + f.Key + "=" + h.field2String(f) - } - } - return nil -} - -func (h *logHook) field2String(field zapcore.Field) string { - switch field.Type { - case zapcore.StringType: - return field.String - case zapcore.Int64Type, zapcore.Int32Type, zapcore.Uint32Type, zapcore.Uint64Type: - return fmt.Sprintf("%v", field.Integer) - case zapcore.Float64Type: - return fmt.Sprintf("%v", math.Float64frombits(uint64(field.Integer))) - case zapcore.StringerType: - return field.Interface.(fmt.Stringer).String() - } - return "not support" -} - -func (h *logHook) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { - if h.Enabled(e.Level) { - return ce.AddCore(e, h) - } - return ce -} - -func (s *testStatsSuite) TestLogDetailedInfo(c *C) { - defer cleanEnv(c, s.store, s.do) - - oriProbability := statistics.FeedbackProbability.Load() - oriMinLogCount := handle.MinLogScanCount.Load() - oriMinError := handle.MinLogErrorRate.Load() - oriLevel := log.GetLevel() - oriLease := s.do.StatsHandle().Lease() - defer func() { - statistics.FeedbackProbability.Store(oriProbability) - handle.MinLogScanCount.Store(oriMinLogCount) - handle.MinLogErrorRate.Store(oriMinError) - s.do.StatsHandle().SetLease(oriLease) - log.SetLevel(oriLevel) - }() - statistics.FeedbackProbability.Store(1) - handle.MinLogScanCount.Store(0) - handle.MinLogErrorRate.Store(0) - s.do.StatsHandle().SetLease(1) - - testKit := testkit.NewTestKit(c, s.store) - testKit.MustExec("use test") - testKit.MustExec("create table t (a bigint(64), b bigint(64), c bigint(64), primary key(a), index idx(b), index idx_ba(b,a), index idx_bc(b,c))") - for i := 0; i < 20; i++ { - testKit.MustExec(fmt.Sprintf("insert into t values (%d, %d, %d)", i, i, i)) - } - testKit.MustExec("analyze table t with 4 buckets") - tests := []struct { - sql string - result string - }{ - { - sql: "select * from t where t.a <= 15", - result: "[stats-feedback] test.t, column=a, rangeStr=range: [-inf,8), actual: 8, expected: 8, buckets: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1 ndv: 0, num: 8 lower_bound: 8 upper_bound: 15 repeats: 1 ndv: 0}" + - "[stats-feedback] test.t, column=a, rangeStr=range: [8,15), actual: 8, expected: 7, buckets: {num: 8 lower_bound: 8 upper_bound: 15 repeats: 1 ndv: 0}", - }, - { - sql: "select * from t use index(idx) where t.b <= 15", - result: "[stats-feedback] test.t, index=idx, rangeStr=range: [-inf,8), actual: 8, expected: 8, histogram: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1 ndv: 0, num: 8 lower_bound: 8 upper_bound: 15 repeats: 1 ndv: 0}" + - "[stats-feedback] test.t, index=idx, rangeStr=range: [8,16), actual: 8, expected: 8, histogram: {num: 8 lower_bound: 8 upper_bound: 15 repeats: 1 ndv: 0, num: 4 lower_bound: 16 upper_bound: 19 repeats: 1 ndv: 0}", - }, - { - sql: "select b from t use index(idx_ba) where b = 1 and a <= 5", - result: "[stats-feedback] test.t, index=idx_ba, actual=1, equality=1, expected equality=1, range=range: [-inf,6], actual: -1, expected: 6, buckets: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1 ndv: 0}", - }, - { - sql: "select b from t use index(idx_bc) where b = 1 and c <= 5", - result: "[stats-feedback] test.t, index=idx_bc, actual=1, equality=1, expected equality=1, range=[-inf,6], pseudo count=7", - }, - { - sql: "select b from t use index(idx_ba) where b = 1", - result: "[stats-feedback] test.t, index=idx_ba, rangeStr=value: 1, actual: 1, expected: 1", - }, - } - log.SetLevel(zapcore.DebugLevel) - for _, t := range tests { - s.hook.results = "" - testKit.MustQuery(t.sql) - c.Assert(s.hook.results, Equals, t.result) - } -} - -func (s *testStatsSuite) TestNeedAnalyzeTable(c *C) { +func TestNeedAnalyzeTable(t *testing.T) { columns := map[int64]*statistics.Column{} columns[1] = &statistics.Column{Count: 1} tests := []struct { @@ -1581,15 +1447,16 @@ func (s *testStatsSuite) TestNeedAnalyzeTable(c *C) { } for _, test := range tests { needAnalyze, reason := handle.NeedAnalyzeTable(test.tbl, test.limit, test.ratio) - c.Assert(needAnalyze, Equals, test.result) - c.Assert(strings.HasPrefix(reason, test.reason), IsTrue) + require.Equal(t, test.result, needAnalyze) + require.True(t, strings.HasPrefix(reason, test.reason)) } } -func (s *testStatsSuite) TestIndexQueryFeedback(c *C) { - c.Skip("support update the topn of index equal conditions") - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestIndexQueryFeedback(t *testing.T) { + t.Skip("support update the topn of index equal conditions") + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() defer func() { @@ -1604,19 +1471,19 @@ func (s *testStatsSuite) TestIndexQueryFeedback(c *C) { for i := 0; i < 20; i++ { testKit.MustExec(fmt.Sprintf(`insert into t values (1, %d, %d, %d, %d, %d, %d, "%s")`, i, i, i, i, i, i, fmt.Sprintf("1000-01-%02d", i+1))) } - h := s.do.StatsHandle() + h := dom.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t with 3 buckets") for i := 0; i < 20; i++ { testKit.MustExec(fmt.Sprintf(`insert into t values (1, %d, %d, %d, %d, %d, %d, "%s")`, i, i, i, i, i, i, fmt.Sprintf("1000-01-%02d", i+1))) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - is := s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + is := dom.InfoSchema() + require.NoError(t, h.Update(is)) table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() tests := []struct { sql string @@ -1704,27 +1571,28 @@ func (s *testStatsSuite) TestIndexQueryFeedback(c *C) { eqCount: 32, }, } - for i, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(h.Update(is), IsNil) + for i, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, h.Update(is)) tbl := h.GetTableStats(tblInfo) - if t.idxCols == 0 { - c.Assert(tbl.Columns[t.rangeID].ToString(0), Equals, tests[i].hist) + if test.idxCols == 0 { + require.Equal(t, tests[i].hist, tbl.Columns[test.rangeID].ToString(0)) } else { - c.Assert(tbl.Indices[t.rangeID].ToString(1), Equals, tests[i].hist) + require.Equal(t, tests[i].hist, tbl.Indices[test.rangeID].ToString(1)) } - val, err := codec.EncodeKey(testKit.Se.GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) - c.Assert(err, IsNil) - c.Assert(tbl.Indices[t.idxID].CMSketch.QueryBytes(val), Equals, uint64(t.eqCount)) + val, err := codec.EncodeKey(testKit.Session().GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) + require.NoError(t, err) + require.Equal(t, uint64(test.eqCount), tbl.Indices[test.idxID].CMSketch.QueryBytes(val)) } } -func (s *testStatsSuite) TestIndexQueryFeedback4TopN(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestIndexQueryFeedback4TopN(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() @@ -1739,40 +1607,43 @@ func (s *testStatsSuite) TestIndexQueryFeedback4TopN(c *C) { handle.MinLogErrorRate.Store(0) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec("create table t (a bigint(64), index idx(a))") for i := 0; i < 20; i++ { testKit.MustExec(`insert into t values (1)`) } - h := s.do.StatsHandle() + h := dom.StatsHandle() err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + testKit.MustExec("set @@session.tidb_analyze_version = 1") testKit.MustExec("set @@tidb_enable_fast_analyze = 1") testKit.MustExec("analyze table t with 3 buckets") for i := 0; i < 20; i++ { testKit.MustExec(`insert into t values (1)`) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - is := s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + is := dom.InfoSchema() + require.NoError(t, h.Update(is)) table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() testKit.MustQuery("select * from t use index(idx) where a = 1") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, h.Update(is)) tbl := h.GetTableStats(tblInfo) - val, err := codec.EncodeKey(testKit.Se.GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) - c.Assert(err, IsNil) - c.Assert(tbl.Indices[1].CMSketch.QueryBytes(val), Equals, uint64(40)) + val, err := codec.EncodeKey(testKit.Session().GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) + require.NoError(t, err) + require.Equal(t, uint64(40), tbl.Indices[1].CMSketch.QueryBytes(val)) } -func (s *testStatsSuite) TestAbnormalIndexFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestAbnormalIndexFeedback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() @@ -1795,11 +1666,11 @@ func (s *testStatsSuite) TestAbnormalIndexFeedback(c *C) { testKit.MustExec("analyze table t with 3 buckets, 0 topn") testKit.MustExec("delete from t where a = 1") testKit.MustExec("delete from t where b > 10") - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tblInfo := table.Meta() - h := s.do.StatsHandle() + h := dom.StatsHandle() tests := []struct { sql string hist string @@ -1830,24 +1701,25 @@ func (s *testStatsSuite) TestAbnormalIndexFeedback(c *C) { eqCount: 3, }, } - for i, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(h.Update(is), IsNil) + for i, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, h.Update(is)) tbl := h.GetTableStats(tblInfo) - c.Assert(tbl.Columns[t.rangeID].ToString(0), Equals, tests[i].hist) - val, err := codec.EncodeKey(testKit.Se.GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) - c.Assert(err, IsNil) - c.Assert(tbl.Indices[t.idxID].CMSketch.QueryBytes(val), Equals, uint64(t.eqCount)) + require.Equal(t, tests[i].hist, tbl.Columns[test.rangeID].ToString(0)) + val, err := codec.EncodeKey(testKit.Session().GetSessionVars().StmtCtx, nil, types.NewIntDatum(1)) + require.NoError(t, err) + require.Equal(t, uint64(test.eqCount), tbl.Indices[test.idxID].CMSketch.QueryBytes(val)) } } -func (s *testStatsSuite) TestFeedbackRanges(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - h := s.do.StatsHandle() +func TestFeedbackRanges(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + h := dom.StatsHandle() oriProbability := statistics.FeedbackProbability.Load() oriNumber := statistics.MaxNumberOfRanges oriMinLogCount := handle.MinLogScanCount.Load() @@ -1868,14 +1740,14 @@ func (s *testStatsSuite) TestFeedbackRanges(c *C) { testKit.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i, i)) } err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("set @@session.tidb_analyze_version=1") testKit.MustExec("analyze table t with 3 buckets") for i := 30; i < 40; i++ { testKit.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i, i)) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) tests := []struct { sql string hist string @@ -1906,25 +1778,26 @@ func (s *testStatsSuite) TestFeedbackRanges(c *C) { colID: 2, }, } - is := s.do.InfoSchema() + is := dom.InfoSchema() table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - for i, t := range tests { - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + for _, test := range tests { + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, err) + require.NoError(t, h.Update(is)) tblInfo := table.Meta() tbl := h.GetTableStats(tblInfo) - c.Assert(tbl.Columns[t.colID].ToString(0), Equals, tests[i].hist) + require.Equal(t, test.hist, tbl.Columns[test.colID].ToString(0)) } } -func (s *testStatsSuite) TestUnsignedFeedbackRanges(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - h := s.do.StatsHandle() +func TestUnsignedFeedbackRanges(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + h := dom.StatsHandle() oriProbability := statistics.FeedbackProbability.Load() oriMinLogCount := handle.MinLogScanCount.Load() @@ -1941,6 +1814,7 @@ func (s *testStatsSuite) TestUnsignedFeedbackRanges(c *C) { handle.MinLogErrorRate.Store(0) testKit.MustExec("use test") + testKit.MustExec("set @@session.tidb_analyze_version = 0") testKit.MustExec("create table t (a tinyint unsigned, primary key(a))") testKit.MustExec("create table t1 (a bigint unsigned, primary key(a))") for i := 0; i < 20; i++ { @@ -1948,16 +1822,16 @@ func (s *testStatsSuite) TestUnsignedFeedbackRanges(c *C) { testKit.MustExec(fmt.Sprintf("insert into t1 values (%d)", i)) } err := h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) + require.NoError(t, err) err = h.HandleDDLEvent(<-h.DDLEventCh()) - c.Assert(err, IsNil) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, err) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t, t1 with 3 buckets") for i := 30; i < 40; i++ { testKit.MustExec(fmt.Sprintf("insert into t values (%d)", i)) testKit.MustExec(fmt.Sprintf("insert into t1 values (%d)", i)) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) tests := []struct { sql string hist string @@ -1996,49 +1870,51 @@ func (s *testStatsSuite) TestUnsignedFeedbackRanges(c *C) { tblName: "t1", }, } - is := s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) - for i, t := range tests { - table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr(t.tblName)) - c.Assert(err, IsNil) - testKit.MustQuery(t.sql) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.DumpStatsFeedbackToKV(), IsNil) - c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil) - c.Assert(err, IsNil) - c.Assert(h.Update(is), IsNil) + is := dom.InfoSchema() + require.NoError(t, h.Update(is)) + for _, test := range tests { + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr(test.tblName)) + require.NoError(t, err) + testKit.MustQuery(test.sql) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.DumpStatsFeedbackToKV()) + require.NoError(t, h.HandleUpdateStats(dom.InfoSchema())) + require.NoError(t, err) + require.NoError(t, h.Update(is)) tblInfo := table.Meta() tbl := h.GetTableStats(tblInfo) - c.Assert(tbl.Columns[1].ToString(0), Equals, tests[i].hist) + require.Equal(t, test.hist, tbl.Columns[1].ToString(0)) } } -func (s *testStatsSuite) TestLoadHistCorrelation(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) - h := s.do.StatsHandle() +func TestLoadHistCorrelation(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) + h := dom.StatsHandle() origLease := h.Lease() h.SetLease(time.Second) defer func() { h.SetLease(origLease) }() testKit.MustExec("use test") testKit.MustExec("create table t(c int)") testKit.MustExec("insert into t values(1),(2),(3),(4),(5)") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t") h.Clear() - c.Assert(h.Update(s.do.InfoSchema()), IsNil) + require.NoError(t, h.Update(dom.InfoSchema())) result := testKit.MustQuery("show stats_histograms where Table_name = 't'") - c.Assert(len(result.Rows()), Equals, 0) + require.Len(t, result.Rows(), 0) testKit.MustExec("explain select * from t where c = 1") - c.Assert(h.LoadNeededHistograms(), IsNil) + require.NoError(t, h.LoadNeededHistograms()) result = testKit.MustQuery("show stats_histograms where Table_name = 't'") - c.Assert(len(result.Rows()), Equals, 1) - c.Assert(result.Rows()[0][9], Equals, "1") + require.Len(t, result.Rows(), 1) + require.Equal(t, "1", result.Rows()[0][9]) } -func (s *testStatsSuite) TestDeleteUpdateFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestDeleteUpdateFeedback(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() defer func() { @@ -2046,33 +1922,34 @@ func (s *testStatsSuite) TestDeleteUpdateFeedback(c *C) { }() statistics.FeedbackProbability.Store(1) - h := s.do.StatsHandle() + h := dom.StatsHandle() testKit.MustExec("use test") testKit.MustExec("create table t (a bigint(64), b bigint(64), index idx_ab(a,b))") for i := 0; i < 20; i++ { testKit.MustExec(fmt.Sprintf("insert into t values (%d, %d)", i/5, i)) } - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("analyze table t with 3 buckets") testKit.MustExec("delete from t where a = 1") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.GetQueryFeedback().Size, Equals, 0) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.Equal(t, 0, h.GetQueryFeedback().Size) testKit.MustExec("update t set a = 6 where a = 2") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.GetQueryFeedback().Size, Equals, 0) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.Equal(t, 0, h.GetQueryFeedback().Size) testKit.MustExec("explain analyze delete from t where a = 3") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.GetQueryFeedback().Size, Equals, 0) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.Equal(t, 0, h.GetQueryFeedback().Size) } -func (s *testStatsSuite) BenchmarkHandleAutoAnalyze(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func BenchmarkHandleAutoAnalyze(b *testing.B) { + store, dom, clean := testkit.CreateMockStoreAndDomain(b) + defer clean() + testKit := testkit.NewTestKit(b, store) testKit.MustExec("use test") - h := s.do.StatsHandle() - is := s.do.InfoSchema() - for i := 0; i < c.N; i++ { + h := dom.StatsHandle() + is := dom.InfoSchema() + for i := 0; i < b.N; i++ { h.HandleAutoAnalyze(is) } } @@ -2089,9 +1966,10 @@ func subtraction(newMetric *dto.Metric, oldMetric *dto.Metric) int { return newNum - oldNum } -func (s *testStatsSuite) TestDisableFeedback(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestDisableFeedback(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() defer func() { @@ -2100,7 +1978,7 @@ func (s *testStatsSuite) TestDisableFeedback(c *C) { statistics.FeedbackProbability.Store(0.0) oldNum := &dto.Metric{} err := metrics.StoreQueryFeedbackCounter.WithLabelValues(metrics.LblOK).Write(oldNum) - c.Assert(err, IsNil) + require.NoError(t, err) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int, index idx_a(a))") testKit.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (5, 5)") @@ -2111,13 +1989,14 @@ func (s *testStatsSuite) TestDisableFeedback(c *C) { newNum := &dto.Metric{} err = metrics.StoreQueryFeedbackCounter.WithLabelValues(metrics.LblOK).Write(newNum) - c.Assert(err, IsNil) - c.Assert(subtraction(newNum, oldNum), Equals, 0) + require.NoError(t, err) + require.Equal(t, 0, subtraction(newNum, oldNum)) } -func (s *testStatsSuite) TestFeedbackCounter(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestFeedbackCounter(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + testKit := testkit.NewTestKit(t, store) oriProbability := statistics.FeedbackProbability.Load() defer func() { @@ -2126,7 +2005,7 @@ func (s *testStatsSuite) TestFeedbackCounter(c *C) { statistics.FeedbackProbability.Store(1) oldNum := &dto.Metric{} err := metrics.StoreQueryFeedbackCounter.WithLabelValues(metrics.LblOK).Write(oldNum) - c.Assert(err, IsNil) + require.NoError(t, err) testKit.MustExec("use test") testKit.MustExec("create table t (a int, b int, index idx_a(a))") testKit.MustExec("insert into t values (1, 1), (2, 2), (3, 3), (5, 5)") @@ -2137,11 +2016,11 @@ func (s *testStatsSuite) TestFeedbackCounter(c *C) { newNum := &dto.Metric{} err = metrics.StoreQueryFeedbackCounter.WithLabelValues(metrics.LblOK).Write(newNum) - c.Assert(err, IsNil) - c.Assert(subtraction(newNum, oldNum), Equals, 20) + require.NoError(t, err) + require.Equal(t, 20, subtraction(newNum, oldNum)) } -func (s *testSerialStatsSuite) TestMergeTopN(c *C) { +func TestMergeTopN(t *testing.T) { // Move this test to here to avoid race test. tests := []struct { topnNum int @@ -2174,13 +2053,13 @@ func (s *testSerialStatsSuite) TestMergeTopN(c *C) { maxTopNCnt: 100, }, } - for _, t := range tests { - topnNum, n := t.topnNum, t.n - maxTopNVal, maxTopNCnt := t.maxTopNVal, t.maxTopNCnt + for _, test := range tests { + topnNum, n := test.topnNum, test.n + maxTopNVal, maxTopNCnt := test.maxTopNVal, test.maxTopNCnt // the number of maxTopNVal should be bigger than n. ok := maxTopNVal >= n - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) topNs := make([]*statistics.TopN, 0, topnNum) res := make(map[int]uint64) @@ -2210,28 +2089,29 @@ func (s *testSerialStatsSuite) TestMergeTopN(c *C) { var minTopNCnt uint64 for _, topNMeta := range topN.TopN { val, err := strconv.Atoi(string(topNMeta.Encoded)) - c.Assert(err, IsNil) - c.Assert(topNMeta.Count, Equals, res[val]) + require.NoError(t, err) + require.Equal(t, res[val], topNMeta.Count) minTopNCnt = topNMeta.Count } if remainTopN != nil { cnt += len(remainTopN) for _, remainTopNMeta := range remainTopN { val, err := strconv.Atoi(string(remainTopNMeta.Encoded)) - c.Assert(err, IsNil) - c.Assert(remainTopNMeta.Count, Equals, res[val]) + require.NoError(t, err) + require.Equal(t, res[val], remainTopNMeta.Count) // The count of value in remainTopN may equal to the min count of value in TopN. ok = minTopNCnt >= remainTopNMeta.Count - c.Assert(ok, Equals, true) + require.Equal(t, true, ok) } } - c.Assert(cnt, Equals, len(res)) + require.Equal(t, len(res), cnt) } } -func (s *testSerialStatsSuite) TestAutoUpdatePartitionInDynamicOnlyMode(c *C) { - defer cleanEnv(c, s.store, s.do) - testKit := testkit.NewTestKit(c, s.store) +func TestAutoUpdatePartitionInDynamicOnlyMode(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + testKit := testkit.NewTestKit(t, store) testkit.WithPruneMode(testKit, variable.DynamicOnly, func() { testKit.MustExec("use test") testKit.MustExec("set @@tidb_analyze_version = 2;") @@ -2242,14 +2122,14 @@ func (s *testSerialStatsSuite) TestAutoUpdatePartitionInDynamicOnlyMode(c *C) { partition p1 values less than (20), partition p2 values less than (30))`) - do := s.do + do := dom is := do.InfoSchema() h := do.StatsHandle() - c.Assert(h.RefreshVars(), IsNil) - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) + require.NoError(t, h.RefreshVars()) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) testKit.MustExec("insert into t values (1, 'a'), (2, 'b'), (11, 'c'), (12, 'd'), (21, 'e'), (22, 'f')") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) testKit.MustExec("set @@tidb_analyze_version = 2") testKit.MustExec("analyze table t") @@ -2260,42 +2140,43 @@ func (s *testSerialStatsSuite) TestAutoUpdatePartitionInDynamicOnlyMode(c *C) { testKit.MustExec("set global tidb_auto_analyze_ratio = 0.0") }() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err, IsNil) + require.NoError(t, err) tableInfo := tbl.Meta() pi := tableInfo.GetPartitionInfo() globalStats := h.GetTableStats(tableInfo) partitionStats := h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) - c.Assert(globalStats.Count, Equals, int64(6)) - c.Assert(globalStats.ModifyCount, Equals, int64(0)) - c.Assert(partitionStats.Count, Equals, int64(2)) - c.Assert(partitionStats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(6), globalStats.Count) + require.Equal(t, int64(0), globalStats.ModifyCount) + require.Equal(t, int64(2), partitionStats.Count) + require.Equal(t, int64(0), partitionStats.ModifyCount) testKit.MustExec("insert into t values (3, 'g')") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) globalStats = h.GetTableStats(tableInfo) partitionStats = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) - c.Assert(globalStats.Count, Equals, int64(7)) - c.Assert(globalStats.ModifyCount, Equals, int64(1)) - c.Assert(partitionStats.Count, Equals, int64(3)) - c.Assert(partitionStats.ModifyCount, Equals, int64(1)) + require.Equal(t, int64(7), globalStats.Count) + require.Equal(t, int64(1), globalStats.ModifyCount) + require.Equal(t, int64(3), partitionStats.Count) + require.Equal(t, int64(1), partitionStats.ModifyCount) h.HandleAutoAnalyze(is) - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.Update(is)) globalStats = h.GetTableStats(tableInfo) partitionStats = h.GetPartitionStats(tableInfo, pi.Definitions[0].ID) - c.Assert(globalStats.Count, Equals, int64(7)) - c.Assert(globalStats.ModifyCount, Equals, int64(0)) - c.Assert(partitionStats.Count, Equals, int64(3)) - c.Assert(partitionStats.ModifyCount, Equals, int64(0)) + require.Equal(t, int64(7), globalStats.Count) + require.Equal(t, int64(0), globalStats.ModifyCount) + require.Equal(t, int64(3), partitionStats.Count) + require.Equal(t, int64(0), partitionStats.ModifyCount) }) } -func (s *testSerialStatsSuite) TestAutoAnalyzeRatio(c *C) { - defer cleanEnv(c, s.store, s.do) - tk := testkit.NewTestKit(c, s.store) +func TestAutoAnalyzeRatio(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) oriStart := tk.MustQuery("select @@tidb_auto_analyze_start_time").Rows()[0][0].(string) oriEnd := tk.MustQuery("select @@tidb_auto_analyze_end_time").Rows()[0][0].(string) @@ -2306,33 +2187,214 @@ func (s *testSerialStatsSuite) TestAutoAnalyzeRatio(c *C) { tk.MustExec(fmt.Sprintf("set global tidb_auto_analyze_end_time='%v'", oriEnd)) }() - h := s.do.StatsHandle() + h := dom.StatsHandle() tk.MustExec("use test") tk.MustExec("create table t (a int)") - c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil) + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) tk.MustExec("insert into t values (1)" + strings.Repeat(", (1)", 19)) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - is := s.do.InfoSchema() - c.Assert(h.Update(is), IsNil) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + is := dom.InfoSchema() + require.NoError(t, h.Update(is)) // To pass the stats.Pseudo check in autoAnalyzeTable tk.MustExec("analyze table t") tk.MustExec("explain select * from t where a = 1") - c.Assert(h.LoadNeededHistograms(), IsNil) + require.NoError(t, h.LoadNeededHistograms()) tk.MustExec("set global tidb_auto_analyze_start_time='00:00 +0000'") tk.MustExec("set global tidb_auto_analyze_end_time='23:59 +0000'") tk.MustExec("insert into t values (1)" + strings.Repeat(", (1)", 10)) - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) - c.Assert(h.HandleAutoAnalyze(is), IsTrue) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) + require.True(t, h.HandleAutoAnalyze(is)) tk.MustExec("delete from t limit 12") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) - c.Assert(h.HandleAutoAnalyze(is), IsFalse) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) + require.False(t, h.HandleAutoAnalyze(is)) tk.MustExec("delete from t limit 4") - c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil) - c.Assert(h.Update(is), IsNil) - c.Assert(h.HandleAutoAnalyze(s.do.InfoSchema()), IsTrue) + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + require.NoError(t, h.Update(is)) + require.True(t, h.HandleAutoAnalyze(dom.InfoSchema())) +} + +func TestDumpColumnStatsUsage(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("create table t2(a int, b int)") + tk.MustExec("create table t3(a int, b int) partition by range(a) (partition p0 values less than (10), partition p1 values less than maxvalue)") + tk.MustExec("insert into t1 values (1, 2), (3, 4)") + tk.MustExec("insert into t2 values (5, 6), (7, 8)") + tk.MustExec("insert into t3 values (1, 2), (3, 4), (11, 12), (13, 14)") + tk.MustExec("select * from t1 where a > 1") + tk.MustExec("select * from t2 where b < 10") + require.NoError(t, h.DumpColStatsUsageToKV()) + // t1.a is collected as predicate column + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t1", "", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't2'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t2", "", "b"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + + tk.MustExec("analyze table t1") + tk.MustExec("select * from t1 where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + // t1.a updates last_used_at first and then updates last_analyzed_at while t1.b updates last_analyzed_at first and then updates last_used_at. + // Check both of them behave as expected. + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Rows() + require.Len(t, rows, 2) + require.Equal(t, []interface{}{"test", "t1", "", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) != "") + require.Equal(t, []interface{}{"test", "t1", "", "b"}, rows[1][:4]) + require.True(t, rows[1][4].(string) != "") + require.True(t, rows[1][5].(string) != "") + + // Test partition table. + // No matter whether it is static or dynamic pruning mode, we record predicate columns using table ID rather than partition ID. + for _, val := range []string{string(variable.Static), string(variable.Dynamic)} { + tk.MustExec(fmt.Sprintf("set @@tidb_partition_prune_mode = '%v'", val)) + tk.MustExec("delete from mysql.column_stats_usage") + tk.MustExec("select * from t3 where a < 5") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't3'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t3", "global", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + } + + // Test non-correlated subquery. + // Non-correlated subquery will be executed during the plan building phase, which cannot be done by mock in (*testPlanSuite).TestCollectPredicateColumns. + // Hence we put the test of collecting predicate columns for non-correlated subquery here. + tk.MustExec("delete from mysql.column_stats_usage") + tk.MustExec("select * from t2 where t2.a > (select count(*) from t1 where t1.b > 1)") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t1", "", "b"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't2'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t2", "", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") +} + +func TestCollectPredicateColumnsFromExecute(t *testing.T) { + for _, val := range []bool{false, true} { + func(planCache bool) { + originalVal1 := plannercore.PreparedPlanCacheEnabled() + defer func() { + plannercore.SetPreparedPlanCache(originalVal1) + }() + plannercore.SetPreparedPlanCache(planCache) + + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + originalVal2 := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal2)) + }() + tk.MustExec("set global tidb_enable_column_tracking = 1") + + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("create table t1(a int, b int)") + tk.MustExec("prepare stmt from 'select * from t1 where a > ?'") + require.NoError(t, h.DumpColStatsUsageToKV()) + // Prepare only converts sql string to ast and doesn't do optimization, so no predicate column is collected. + tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Check(testkit.Rows()) + tk.MustExec("set @p1 = 1") + tk.MustExec("execute stmt using @p1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t1", "", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + + tk.MustExec("delete from mysql.column_stats_usage") + tk.MustExec("set @p2 = 2") + tk.MustExec("execute stmt using @p2") + if planCache { + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + require.NoError(t, h.DumpColStatsUsageToKV()) + // If the second execution uses the cached plan, no predicate column is collected. + tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Check(testkit.Rows()) + } else { + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + require.NoError(t, h.DumpColStatsUsageToKV()) + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't1'").Rows() + require.Len(t, rows, 1) + require.Equal(t, []interface{}{"test", "t1", "", "a"}, rows[0][:4]) + require.True(t, rows[0][4].(string) != "") + require.True(t, rows[0][5].(string) == "") + } + }(val) + } +} + +func TestEnableAndDisableColumnTracking(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b int, c int)") + + originalVal := tk.MustQuery("select @@tidb_enable_column_tracking").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_enable_column_tracking = %v", originalVal)) + }() + + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows := tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Rows() + require.Len(t, rows, 1) + require.Equal(t, "b", rows[0][3]) + + tk.MustExec("set global tidb_enable_column_tracking = 0") + // After tidb_enable_column_tracking is set to 0, the predicate columns collected before are invalidated. + tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Check(testkit.Rows()) + + // Sleep for 1.5s to let `last_used_at` be larger than `tidb_disable_tracking_time`. + time.Sleep(1500 * time.Millisecond) + tk.MustExec("select * from t where a > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + // We don't collect predicate columns when tidb_enable_column_tracking = 0 + tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Check(testkit.Rows()) + + tk.MustExec("set global tidb_enable_column_tracking = 1") + tk.MustExec("select * from t where b < 1 and c > 1") + require.NoError(t, h.DumpColStatsUsageToKV()) + rows = tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Sort().Rows() + require.Len(t, rows, 2) + require.Equal(t, "b", rows[0][3]) + require.Equal(t, "c", rows[1][3]) + + // Test invalidating predicate columns again in order to check that tidb_disable_tracking_time can be updated. + tk.MustExec("set global tidb_enable_column_tracking = 0") + tk.MustQuery("show column_stats_usage where db_name = 'test' and table_name = 't' and last_used_at is not null").Check(testkit.Rows()) } diff --git a/statistics/histogram.go b/statistics/histogram.go index cd053ec070997..d9fcbf9c5fa5a 100644 --- a/statistics/histogram.go +++ b/statistics/histogram.go @@ -19,6 +19,7 @@ import ( "fmt" "math" "sort" + "strconv" "strings" "time" "unsafe" @@ -429,28 +430,17 @@ func (hg *Histogram) ToString(idxCols int) string { // equalRowCount estimates the row count where the column equals to value. // matched: return true if this returned row count is from Bucket.Repeat or bucket NDV, which is more accurate than if not. func (hg *Histogram) equalRowCount(value types.Datum, hasBucketNDV bool) (count float64, matched bool) { - index, match := hg.Bounds.LowerBound(0, &value) - // Since we store the lower and upper bound together, if the index is an odd number, then it points to a upper bound. - if index%2 == 1 { - if match { - return float64(hg.Buckets[index/2].Repeat), true - } - if hasBucketNDV && hg.Buckets[index/2].NDV > 1 { - return float64(hg.bucketCount(index/2)-hg.Buckets[index/2].Repeat) / float64(hg.Buckets[index/2].NDV-1), true - } - return hg.notNullCount() / float64(hg.NDV), false + _, bucketIdx, inBucket, match := hg.locateBucket(value) + if !inBucket { + return 0, false } if match { - cmp := chunk.GetCompareFunc(hg.Tp) - if cmp(hg.Bounds.GetRow(index), 0, hg.Bounds.GetRow(index+1), 0) == 0 { - return float64(hg.Buckets[index/2].Repeat), true - } - if hasBucketNDV && hg.Buckets[index/2].NDV > 1 { - return float64(hg.bucketCount(index/2)-hg.Buckets[index/2].Repeat) / float64(hg.Buckets[index/2].NDV-1), true - } - return hg.notNullCount() / float64(hg.NDV), false + return float64(hg.Buckets[bucketIdx].Repeat), true + } + if hasBucketNDV && hg.Buckets[bucketIdx].NDV > 1 { + return float64(hg.bucketCount(bucketIdx)-hg.Buckets[bucketIdx].Repeat) / float64(hg.Buckets[bucketIdx].NDV-1), true } - return 0, false + return hg.notNullCount() / float64(hg.NDV), false } // greaterRowCount estimates the row count where the column greater than value. @@ -461,30 +451,69 @@ func (hg *Histogram) greaterRowCount(value types.Datum) float64 { return math.Max(0, gtCount) } +// locateBucket locates where a value falls in the range of the Histogram. +// Return value: +// exceed: if the value is larger than the upper bound of the last Bucket of the Histogram +// bucketIdx: assuming exceed if false, which Bucket does this value fall in (note: the range before a Bucket is also +// considered belong to this Bucket) +// inBucket: assuming exceed if false, whether this value falls in this Bucket, instead of falls between +// this Bucket and the previous Bucket. +// matchLastValue: assuming inBucket is true, if this value is the last value in this Bucket, which has a counter (Bucket.Repeat) +// Examples: +// val0 |<-[bkt0]->| |<-[bkt1]->val1(last value)| val2 |<--val3--[bkt2]->| |<-[bkt3]->| val4 +// locateBucket(val0): false, 0, false, false +// locateBucket(val1): false, 1, true, true +// locateBucket(val2): false, 2, false, false +// locateBucket(val3): false, 2, true, false +// locateBucket(val4): true, 3, false, false +func (hg *Histogram) locateBucket(value types.Datum) (exceed bool, bucketIdx int, inBucket, matchLastValue bool) { + // Empty histogram + if hg == nil || hg.Bounds.NumRows() == 0 { + return true, 0, false, false + } + index, match := hg.Bounds.LowerBound(0, &value) + // The value is larger than the max value in the histogram (exceed is true) + if index >= hg.Bounds.NumRows() { + return true, hg.Len() - 1, false, false + } + bucketIdx = index / 2 + // The value is before this bucket + if index%2 == 0 && !match { + return false, bucketIdx, false, false + } + // The value matches the last value in this bucket + // case 1: The LowerBound()'s return value tells us the value matches an upper bound of a bucket + // case 2: We compare and find that the value is equal to the upper bound of this bucket. This might happen when + // the bucket's lower bound is equal to its upper bound. + if (index%2 == 1 && match) || chunk.Compare(hg.Bounds.GetRow(bucketIdx*2+1), 0, &value) == 0 { + return false, bucketIdx, true, true + } + // The value is in the bucket and isn't the last value in this bucket + return false, bucketIdx, true, false +} + // LessRowCountWithBktIdx estimates the row count where the column less than value. func (hg *Histogram) LessRowCountWithBktIdx(value types.Datum) (float64, int) { // All the values are null. if hg.Bounds.NumRows() == 0 { return 0, 0 } - index, match := hg.Bounds.LowerBound(0, &value) - if index == hg.Bounds.NumRows() { + exceed, bucketIdx, inBucket, match := hg.locateBucket(value) + if exceed { return hg.notNullCount(), hg.Len() - 1 } - // Since we store the lower and upper bound together, so dividing the index by 2 will get the bucket index. - bucketIdx := index / 2 - curCount, curRepeat := float64(hg.Buckets[bucketIdx].Count), float64(hg.Buckets[bucketIdx].Repeat) preCount := float64(0) if bucketIdx > 0 { preCount = float64(hg.Buckets[bucketIdx-1].Count) } - if index%2 == 1 { - if match { - return curCount - curRepeat, bucketIdx - } - return preCount + hg.calcFraction(bucketIdx, &value)*(curCount-curRepeat-preCount), bucketIdx + if !inBucket { + return preCount, bucketIdx } - return preCount, bucketIdx + curCount, curRepeat := float64(hg.Buckets[bucketIdx].Count), float64(hg.Buckets[bucketIdx].Repeat) + if match { + return curCount - curRepeat, bucketIdx + } + return preCount + hg.calcFraction(bucketIdx, &value)*(curCount-curRepeat-preCount), bucketIdx } func (hg *Histogram) lessRowCount(value types.Datum) float64 { @@ -1020,6 +1049,17 @@ type Column struct { Flag int64 LastAnalyzePos types.Datum StatsVer int64 // StatsVer is the version of the current stats, used to maintain compatibility + + // Loaded means if the histogram, the topn and the cm sketch are loaded fully. + // Those three parts of a Column is loaded lazily. It will only be loaded after trying to use them. + // Note: Currently please use Column.IsLoaded() to check if it's loaded. + Loaded bool +} + +// IsLoaded is a wrap around c.Loaded. +// It's just for safe when we are switching from `c.notNullCount() > 0)` to `c.Loaded`. +func (c *Column) IsLoaded() bool { + return c.Loaded || c.notNullCount() > 0 } func (c *Column) String() string { @@ -1074,10 +1114,28 @@ func (c *Column) IsInvalid(sctx sessionctx.Context, collPseudo bool) bool { if collPseudo && c.NotAccurate() { return true } - if c.Histogram.NDV > 0 && c.notNullCount() == 0 && sctx != nil && sctx.GetSessionVars().StmtCtx != nil { - HistogramNeededColumns.insert(tableColumnID{TableID: c.PhysicalID, ColumnID: c.Info.ID}) + if sctx != nil { + stmtctx := sctx.GetSessionVars().StmtCtx + if stmtctx != nil && stmtctx.StatsLoad.Fallback { + return true + } + if !c.IsLoaded() && stmtctx != nil { + if stmtctx.StatsLoad.Timeout > 0 { + logutil.BgLogger().Warn("Hist for column should already be loaded as sync but not found.", + zap.String(strconv.FormatInt(c.Info.ID, 10), c.Info.Name.O)) + } + // In some tests, the c.Info is not set, so we add this check here. + if c.Info != nil { + HistogramNeededColumns.insert(tableColumnID{TableID: c.PhysicalID, ColumnID: c.Info.ID}) + } + } } - return c.TotalRowCount() == 0 || (c.Histogram.NDV > 0 && c.notNullCount() == 0) + return c.TotalRowCount() == 0 || (!c.IsLoaded() && c.Histogram.NDV > 0) +} + +// IsHistNeeded checks if this column needs histogram to be loaded +func (c *Column) IsHistNeeded(collPseudo bool) bool { + return (!collPseudo || !c.NotAccurate()) && !c.IsLoaded() } func (c *Column) equalRowCount(sctx sessionctx.Context, val types.Datum, encodedVal []byte, realtimeRowCount int64) (float64, error) { @@ -1194,18 +1252,21 @@ func (c *Column) GetColumnRowCount(sctx sessionctx.Context, ranges []*ranger.Ran cnt := c.BetweenRowCount(sctx, lowVal, highVal, lowEncoded, highEncoded) // `betweenRowCount` returns count for [l, h) range, we adjust cnt for boundaries here. // Note that, `cnt` does not include null values, we need specially handle cases - // where null is the lower bound. - if rg.LowExclude && !lowVal.IsNull() { + // where null is the lower bound. + // And because we use (2, MaxValue] to represent expressions like a > 2 and use [MinNotNull, 3) to represent + // expressions like b < 3, we need to exclude the special values. + if rg.LowExclude && !lowVal.IsNull() && lowVal.Kind() != types.KindMaxValue && lowVal.Kind() != types.KindMinNotNull { lowCnt, err := c.equalRowCount(sctx, lowVal, lowEncoded, realtimeRowCount) if err != nil { return 0, errors.Trace(err) } cnt -= lowCnt + cnt = clampRowCount(cnt, c.notNullCount()) } if !rg.LowExclude && lowVal.IsNull() { cnt += float64(c.NullCount) } - if !rg.HighExclude { + if !rg.HighExclude && highVal.Kind() != types.KindMaxValue && highVal.Kind() != types.KindMinNotNull { highCnt, err := c.equalRowCount(sctx, highVal, highEncoded, realtimeRowCount) if err != nil { return 0, errors.Trace(err) @@ -1213,11 +1274,7 @@ func (c *Column) GetColumnRowCount(sctx sessionctx.Context, ranges []*ranger.Ran cnt += highCnt } - if cnt > c.TotalRowCount() { - cnt = c.TotalRowCount() - } else if cnt < 0 { - cnt = 0 - } + cnt = clampRowCount(cnt, c.TotalRowCount()) // If the current table row count has changed, we should scale the row count accordingly. cnt *= c.GetIncreaseFactor(realtimeRowCount) @@ -1233,11 +1290,8 @@ func (c *Column) GetColumnRowCount(sctx sessionctx.Context, ranges []*ranger.Ran rowCount += cnt } - if rowCount > float64(realtimeRowCount) { - rowCount = float64(realtimeRowCount) - } else if rowCount < 0 { - rowCount = 0 - } + + rowCount = clampRowCount(rowCount, float64(realtimeRowCount)) return rowCount, nil } @@ -1387,7 +1441,30 @@ func (idx *Index) GetRowCount(sctx sessionctx.Context, coll *HistColl, indexRang return 0, err } if expBackoffSuccess { - totalCount += expBackoffSel * idx.TotalRowCount() + expBackoffCnt := expBackoffSel * idx.TotalRowCount() + + upperLimit := expBackoffCnt + // Use the multi-column stats to calculate the max possible row count of [l, r) + if idx.Len() > 0 { + _, lowerBkt, _, _ := idx.locateBucket(l) + _, upperBkt, _, _ := idx.locateBucket(r) + // Use Count of the Bucket before l as the lower bound. + preCount := float64(0) + if lowerBkt > 0 { + preCount = float64(idx.Buckets[lowerBkt-1].Count) + } + // Use Count of the Bucket where r exists as the upper bound. + upperCnt := float64(idx.Buckets[upperBkt].Count) + upperLimit = upperCnt - preCount + upperLimit += float64(idx.TopN.BetweenCount(lb, rb)) + } + + // If the result of exponential backoff strategy is larger than the result from multi-column stats, + // use the upper limit from multi-column histogram instead. + if expBackoffCnt > upperLimit { + expBackoffCnt = upperLimit + } + totalCount += expBackoffCnt } } if !expBackoffSuccess { @@ -1406,9 +1483,8 @@ func (idx *Index) GetRowCount(sctx sessionctx.Context, coll *HistColl, indexRang totalCount += idx.Histogram.outOfRangeRowCount(&l, &r, increaseCount) } } - if totalCount > float64(realtimeRowCount) { - totalCount = float64(realtimeRowCount) - } + + totalCount = clampRowCount(totalCount, float64(realtimeRowCount)) return totalCount, nil } @@ -1635,6 +1711,7 @@ func (coll *HistColl) NewHistCollBySelectivity(sctx sessionctx.Context, statsNod zap.Error(err)) continue } + newCol.Loaded = oldCol.Loaded newColl.Columns[node.ID] = newCol } for id, idx := range coll.Indices { @@ -1662,6 +1739,16 @@ func (idx *Index) outOfRange(val types.Datum) bool { return true } +func clampRowCount(rowCount, upperLimit float64) (clampedRowCount float64) { + if rowCount > upperLimit { + return upperLimit + } + if rowCount < 0 { + return 0 + } + return rowCount +} + // matchPrefix checks whether ad is the prefix of value func matchPrefix(row chunk.Row, colIdx int, ad *types.Datum) bool { switch ad.Kind() { diff --git a/statistics/histogram_test.go b/statistics/histogram_test.go index ce95ddfa6fcdd..ad8ef061dad92 100644 --- a/statistics/histogram_test.go +++ b/statistics/histogram_test.go @@ -40,6 +40,7 @@ func TestNewHistogramBySelectivity(t *testing.T) { intCol := &Column{} intCol.Histogram = *NewHistogram(1, 30, 30, 0, types.NewFieldType(mysql.TypeLonglong), chunk.InitialCapacity, 0) intCol.IsHandle = true + intCol.Loaded = true for i := 0; i < 10; i++ { intCol.Bounds.AppendInt64(0, int64(i*3)) intCol.Bounds.AppendInt64(0, int64(i*3+2)) @@ -61,6 +62,7 @@ num: 1 lower_bound: 12 upper_bound: 14 repeats: 0 ndv: 0 num: 30 lower_bound: 27 upper_bound: 29 repeats: 0 ndv: 0` stringCol := &Column{} + stringCol.Loaded = true stringCol.Histogram = *NewHistogram(2, 15, 30, 0, types.NewFieldType(mysql.TypeString), chunk.InitialCapacity, 0) stringCol.Bounds.AppendString(0, "a") stringCol.Bounds.AppendString(0, "aaaabbbb") diff --git a/statistics/integration_test.go b/statistics/integration_test.go index c04b03bd44dea..e43a30e52b7a9 100644 --- a/statistics/integration_test.go +++ b/statistics/integration_test.go @@ -35,6 +35,12 @@ func TestChangeVerTo2Behavior(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + }() + tk.MustExec("set global tidb_persist_analyze_options=false") + tk.MustExec("use test") tk.MustExec("create table t(a int, b int, index idx(a))") tk.MustExec("set @@session.tidb_analyze_version = 1") @@ -105,6 +111,88 @@ func TestChangeVerTo2Behavior(t *testing.T) { } } +func TestChangeVerTo2BehaviorWithPersistedOptions(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + originalVal1 := tk.MustQuery("select @@tidb_persist_analyze_options").Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf("set global tidb_persist_analyze_options = %v", originalVal1)) + }() + tk.MustExec("set global tidb_persist_analyze_options=true") + + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, index idx(a))") + tk.MustExec("set @@session.tidb_analyze_version = 1") + tk.MustExec("insert into t values(1, 1), (1, 2), (1, 3)") + tk.MustExec("analyze table t") + is := dom.InfoSchema() + tblT, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + h := dom.StatsHandle() + require.NoError(t, h.Update(is)) + statsTblT := h.GetTableStats(tblT.Meta()) + // Analyze table with version 1 success, all statistics are version 1. + for _, col := range statsTblT.Columns { + require.Equal(t, int64(1), col.StatsVer) + } + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(1), idx.StatsVer) + } + tk.MustExec("set @@session.tidb_analyze_version = 2") + tk.MustExec("analyze table t index idx") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead")) + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(1), idx.StatsVer) + } + tk.MustExec("analyze table t index") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead")) + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(1), idx.StatsVer) + } + tk.MustExec("analyze table t ") + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, col := range statsTblT.Columns { + require.Equal(t, int64(2), col.StatsVer) + } + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(2), idx.StatsVer) + } + tk.MustExec("set @@session.tidb_analyze_version = 1") + tk.MustExec("analyze table t index idx") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead", + "Warning 1105 The version 2 would collect all statistics not only the selected indexes", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t")) // since fallback to ver2 path, should do samplerate adjustment + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(2), idx.StatsVer) + } + tk.MustExec("analyze table t index") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The analyze version from the session is not compatible with the existing statistics of the table. Use the existing version instead", + "Warning 1105 The version 2 would collect all statistics not only the selected indexes", + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t")) + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(2), idx.StatsVer) + } + tk.MustExec("analyze table t ") + require.NoError(t, h.Update(is)) + statsTblT = h.GetTableStats(tblT.Meta()) + for _, col := range statsTblT.Columns { + require.Equal(t, int64(1), col.StatsVer) + } + for _, idx := range statsTblT.Indices { + require.Equal(t, int64(1), idx.StatsVer) + } +} + func TestFastAnalyzeOnVer2(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() @@ -116,7 +204,7 @@ func TestFastAnalyzeOnVer2(t *testing.T) { tk.MustExec("insert into t values(1, 1), (1, 2), (1, 3)") _, err := tk.Exec("analyze table t") require.Error(t, err) - require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently.", err.Error()) + require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently", err.Error()) tk.MustExec("set @@session.tidb_enable_fast_analyze = 0") tk.MustExec("analyze table t") is := dom.InfoSchema() @@ -134,14 +222,14 @@ func TestFastAnalyzeOnVer2(t *testing.T) { tk.MustExec("set @@session.tidb_enable_fast_analyze = 1") err = tk.ExecToErr("analyze table t index idx") require.Error(t, err) - require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently.", err.Error()) + require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently", err.Error()) tk.MustExec("set @@session.tidb_analyze_version = 1") _, err = tk.Exec("analyze table t index idx") require.Error(t, err) - require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1.", err.Error()) + require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1", err.Error()) _, err = tk.Exec("analyze table t index") require.Error(t, err) - require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1.", err.Error()) + require.Equal(t, "Fast analyze hasn't reached General Availability and only support analyze version 1 currently. But the existing statistics of the table is not version 1", err.Error()) tk.MustExec("analyze table t") require.NoError(t, h.Update(is)) statsTblT = h.GetTableStats(tblT.Meta()) @@ -471,3 +559,88 @@ func hasPseudoStats(rows [][]interface{}) bool { } return false } + +// TestNotLoadedStatsOnAllNULLCol makes sure that stats on a column that only contains NULLs can be used even when it's +// not loaded. This is reasonable because it makes no difference whether it's loaded or not. +func TestNotLoadedStatsOnAllNULLCol(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1000) + defer func() { + h.SetLease(oriLease) + }() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(a int)") + tk.MustExec("create table t2(a int)") + tk.MustExec("insert into t1 values(null), (null), (null), (null)") + tk.MustExec("insert into t2 values(null), (null)") + tk.MustExec("analyze table t1;") + tk.MustExec("analyze table t2;") + + res := tk.MustQuery("explain format = 'brief' select * from t1 left join t2 on t1.a=t2.a order by t1.a, t2.a") + res.Check(testkit.Rows( + "Sort 4.00 root test.t1.a, test.t2.a", + "└─HashJoin 4.00 root left outer join, equal:[eq(test.t1.a, test.t2.a)]", + " ├─TableReader(Build) 0.00 root data:Selection", + // If we are not using stats on this column (which means we use pseudo estimation), the row count for the Selection will become 2. + " │ └─Selection 0.00 cop[tikv] not(isnull(test.t2.a))", + " │ └─TableFullScan 2.00 cop[tikv] table:t2 keep order:false", + " └─TableReader(Probe) 4.00 root data:TableFullScan", + " └─TableFullScan 4.00 cop[tikv] table:t1 keep order:false")) + + res = tk.MustQuery("explain format = 'brief' select * from t2 left join t1 on t1.a=t2.a order by t1.a, t2.a") + res.Check(testkit.Rows( + "Sort 2.00 root test.t1.a, test.t2.a", + "└─HashJoin 2.00 root left outer join, equal:[eq(test.t2.a, test.t1.a)]", + // If we are not using stats on this column, the build side will become t2 because of smaller row count. + " ├─TableReader(Build) 0.00 root data:Selection", + // If we are not using stats on this column, the row count for the Selection will become 4. + " │ └─Selection 0.00 cop[tikv] not(isnull(test.t1.a))", + " │ └─TableFullScan 4.00 cop[tikv] table:t1 keep order:false", + " └─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tikv] table:t2 keep order:false")) + + res = tk.MustQuery("explain format = 'brief' select * from t1 right join t2 on t1.a=t2.a order by t1.a, t2.a") + res.Check(testkit.Rows( + "Sort 2.00 root test.t1.a, test.t2.a", + "└─HashJoin 2.00 root right outer join, equal:[eq(test.t1.a, test.t2.a)]", + " ├─TableReader(Build) 0.00 root data:Selection", + " │ └─Selection 0.00 cop[tikv] not(isnull(test.t1.a))", + " │ └─TableFullScan 4.00 cop[tikv] table:t1 keep order:false", + " └─TableReader(Probe) 2.00 root data:TableFullScan", + " └─TableFullScan 2.00 cop[tikv] table:t2 keep order:false")) + + res = tk.MustQuery("explain format = 'brief' select * from t2 right join t1 on t1.a=t2.a order by t1.a, t2.a") + res.Check(testkit.Rows( + "Sort 4.00 root test.t1.a, test.t2.a", + "└─HashJoin 4.00 root right outer join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 0.00 root data:Selection", + " │ └─Selection 0.00 cop[tikv] not(isnull(test.t2.a))", + " │ └─TableFullScan 2.00 cop[tikv] table:t2 keep order:false", + " └─TableReader(Probe) 4.00 root data:TableFullScan", + " └─TableFullScan 4.00 cop[tikv] table:t1 keep order:false")) +} + +func TestCrossValidationSelectivity(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("set @@tidb_analyze_version = 1") + tk.MustExec("create table t (a int, b int, c int, primary key (a, b) clustered)") + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + tk.MustExec("insert into t values (1,2,3), (1,4,5)") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + tk.MustExec("analyze table t") + tk.MustQuery("explain format = 'brief' select * from t where a = 1 and b > 0 and b < 1000 and c > 1000").Check(testkit.Rows( + "TableReader 0.00 root data:Selection", + "└─Selection 0.00 cop[tikv] gt(test.t.c, 1000)", + " └─TableRangeScan 2.00 cop[tikv] table:t range:(1 0,1 1000), keep order:false")) +} diff --git a/statistics/main_test.go b/statistics/main_test.go index 7e40d650fe393..3fd1cfda4d8ef 100644 --- a/statistics/main_test.go +++ b/statistics/main_test.go @@ -32,7 +32,7 @@ import ( var testDataMap = make(testdata.BookKeeper, 3) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() if !flag.Parsed() { flag.Parse() @@ -48,7 +48,8 @@ func TestMain(m *testing.M) { testDataMap.LoadTestSuiteData("testdata", "trace_suite") opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } diff --git a/statistics/scalar.go b/statistics/scalar.go index f4be9f4647aa0..82a07e1be840b 100644 --- a/statistics/scalar.go +++ b/statistics/scalar.go @@ -96,22 +96,22 @@ func convertDatumToScalar(value *types.Datum, commonPfxLen int) float64 { // of lower and upper equals to the common prefix of the lower, upper and the value. For some simple types like `Int64`, // we do not convert it because we can directly infer the scalar value. func (hg *Histogram) PreCalculateScalar() { - len := hg.Len() - if len == 0 { + l := hg.Len() + if l == 0 { return } switch hg.GetLower(0).Kind() { case types.KindMysqlDecimal, types.KindMysqlTime: - hg.scalars = make([]scalar, len) - for i := 0; i < len; i++ { + hg.scalars = make([]scalar, l) + for i := 0; i < l; i++ { hg.scalars[i] = scalar{ lower: convertDatumToScalar(hg.GetLower(i), 0), upper: convertDatumToScalar(hg.GetUpper(i), 0), } } case types.KindBytes, types.KindString: - hg.scalars = make([]scalar, len) - for i := 0; i < len; i++ { + hg.scalars = make([]scalar, l) + for i := 0; i < l; i++ { lower, upper := hg.GetLower(i), hg.GetUpper(i) common := commonPrefixLength(lower.GetBytes(), upper.GetBytes()) hg.scalars[i] = scalar{ @@ -252,8 +252,8 @@ func enumRangeValues(low, high types.Datum, lowExclude, highExclude bool) []type return values case types.KindMysqlDuration: lowDur, highDur := low.GetMysqlDuration(), high.GetMysqlDuration() - fsp := mathutil.MaxInt8(lowDur.Fsp, highDur.Fsp) - stepSize := int64(math.Pow10(int(types.MaxFsp-fsp))) * int64(time.Microsecond) + fsp := mathutil.Max(lowDur.Fsp, highDur.Fsp) + stepSize := int64(math.Pow10(types.MaxFsp-fsp)) * int64(time.Microsecond) lowDur.Duration = lowDur.Duration.Round(time.Duration(stepSize)) remaining := int64(highDur.Duration-lowDur.Duration)/stepSize + 1 - int64(exclude) if remaining <= 0 || remaining >= maxNumStep { @@ -273,7 +273,7 @@ func enumRangeValues(low, high types.Datum, lowExclude, highExclude bool) []type if lowTime.Type() != highTime.Type() { return nil } - fsp := mathutil.MaxInt8(lowTime.Fsp(), highTime.Fsp()) + fsp := mathutil.Max(lowTime.Fsp(), highTime.Fsp()) var stepSize int64 sc := &stmtctx.StatementContext{TimeZone: time.UTC} if lowTime.Type() == mysql.TypeDate { @@ -285,7 +285,7 @@ func enumRangeValues(low, high types.Datum, lowExclude, highExclude bool) []type if err != nil { return nil } - stepSize = int64(math.Pow10(int(types.MaxFsp-fsp))) * int64(time.Microsecond) + stepSize = int64(math.Pow10(types.MaxFsp-fsp)) * int64(time.Microsecond) } remaining := int64(highTime.Sub(sc, &lowTime).Duration)/stepSize + 1 - int64(exclude) // When `highTime` is much larger than `lowTime`, `remaining` may be overflowed to a negative value. diff --git a/statistics/selectivity.go b/statistics/selectivity.go index 45db1cebf9b1c..5fc1f1dcc2b3b 100644 --- a/statistics/selectivity.go +++ b/statistics/selectivity.go @@ -317,6 +317,34 @@ func (coll *HistColl) Selectivity(ctx sessionctx.Context, exprs []expression.Exp } } + // Try to cover Constants + if mask > 0 { + for i, expr := range remainedExprs { + if mask&(1< 0 { @@ -365,7 +393,7 @@ func (coll *HistColl) Selectivity(ctx sessionctx.Context, exprs []expression.Exp curSelectivity, _, err := coll.Selectivity(ctx, cnfItems, nil) if err != nil { logutil.BgLogger().Debug("something wrong happened, use the default selectivity", zap.Error(err)) - selectivity = selectionFactor + curSelectivity = selectionFactor } selectivity = selectivity + curSelectivity - selectivity*curSelectivity diff --git a/statistics/selectivity_test.go b/statistics/selectivity_test.go index c96781db61b51..59cebc3101524 100644 --- a/statistics/selectivity_test.go +++ b/statistics/selectivity_test.go @@ -49,8 +49,6 @@ func TestCollationColumnEstimate(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) defer clean() tk := testkit.NewTestKit(t, store) - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a varchar(20) collate utf8mb4_general_ci)") @@ -710,11 +708,11 @@ func TestIndexEstimationCrossValidate(t *testing.T) { tk.MustExec("create table t(a int, b int, key(a,b))") tk.MustExec("insert into t values(1, 1), (1, 2), (1, 3), (2, 2)") tk.MustExec("analyze table t") - require.Nil(t, failpoint.Enable("github.com/pingcap/tidb/statistics/table/mockQueryBytesMaxUint64", `return(100000)`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/statistics/table/mockQueryBytesMaxUint64", `return(100000)`)) tk.MustQuery("explain select * from t where a = 1 and b = 2").Check(testkit.Rows( "IndexReader_6 1.00 root index:IndexRangeScan_5", "└─IndexRangeScan_5 1.00 cop[tikv] table:t, index:a(a, b) range:[1 2,1 2], keep order:false")) - require.Nil(t, failpoint.Disable("github.com/pingcap/tidb/statistics/table/mockQueryBytesMaxUint64")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/statistics/table/mockQueryBytesMaxUint64")) // Test issue 22466 tk.MustExec("drop table if exists t2") @@ -868,7 +866,11 @@ func prepareSelectivity(testKit *testkit.TestKit, dom *domain.Domain) (*statisti return nil, err } for i := 1; i <= 5; i++ { - statsTbl.Columns[int64(i)] = &statistics.Column{Histogram: *mockStatsHistogram(int64(i), colValues, 10, types.NewFieldType(mysql.TypeLonglong)), Info: tbl.Columns[i-1]} + statsTbl.Columns[int64(i)] = &statistics.Column{ + Histogram: *mockStatsHistogram(int64(i), colValues, 10, types.NewFieldType(mysql.TypeLonglong)), + Info: tbl.Columns[i-1], + Loaded: true, + } } // Set the value of two indices' histograms. diff --git a/statistics/statistics_test.go b/statistics/statistics_test.go index cf753ca21b4f0..639909016d93c 100644 --- a/statistics/statistics_test.go +++ b/statistics/statistics_test.go @@ -200,7 +200,7 @@ func TestPseudoTable(t *testing.T) { } ti.Columns = append(ti.Columns, colInfo) tbl := PseudoTable(ti) - require.Equal(t, len(tbl.Columns), 1) + require.Len(t, tbl.Columns, 1) require.Greater(t, tbl.Count, int64(0)) sctx := mock.NewContext() count := tbl.ColumnLessRowCount(sctx, types.NewIntDatum(100), colInfo.ID) @@ -250,7 +250,12 @@ func SubTestColumnRange() func(*testing.T) { hg, err := BuildColumn(ctx, bucketCount, 2, collector, types.NewFieldType(mysql.TypeLonglong)) hg.PreCalculateScalar() require.NoError(t, err) - col := &Column{Histogram: *hg, CMSketch: buildCMSketch(s.rc.(*recordSet).data), Info: &model.ColumnInfo{}} + col := &Column{ + Histogram: *hg, + CMSketch: buildCMSketch(s.rc.(*recordSet).data), + Info: &model.ColumnInfo{}, + Loaded: true, + } tbl := &Table{ HistColl: HistColl{ Count: int64(col.TotalRowCount()), @@ -322,7 +327,7 @@ func SubTestIntColumnRanges() func(*testing.T) { hg.PreCalculateScalar() require.NoError(t, err) require.Equal(t, int64(100000), rowCount) - col := &Column{Histogram: *hg, Info: &model.ColumnInfo{}} + col := &Column{Histogram: *hg, Info: &model.ColumnInfo{}, Loaded: true} tbl := &Table{ HistColl: HistColl{ Count: int64(col.TotalRowCount()), diff --git a/statistics/table.go b/statistics/table.go index b8bfa8d9aaf5e..bee9dab89d4d8 100644 --- a/statistics/table.go +++ b/statistics/table.go @@ -591,23 +591,13 @@ func (coll *HistColl) crossValidationSelectivity(sctx sessionctx.Context, idx *I if col.IsInvalid(sctx, coll.Pseudo) { continue } - lowExclude := idxPointRange.LowExclude - highExclude := idxPointRange.HighExclude - // Consider this case: - // create table t(a int, b int, c int, primary key(a,b,c)); - // insert into t values(1,1,1),(2,2,3); - // explain select * from t where (a,b) in ((1,1),(2,2)) and c > 2; - // For column a, we will get range: (1, 1], (2, 2], but GetColumnRowCount() with rang = (2, 2] will return 0. - // And the result of the explain statement will output estRow 0.0. So we change it to [2, 2]. - if lowExclude != highExclude && i < usedColsLen { - lowExclude = false - highExclude = false - } + // Since the column range is point range(LowVal is equal to HighVal), we need to set both LowExclude and HighExclude to false. + // Otherwise we would get 0.0 estRow from GetColumnRowCount. rang := ranger.Range{ LowVal: []types.Datum{idxPointRange.LowVal[i]}, - LowExclude: lowExclude, + LowExclude: false, HighVal: []types.Datum{idxPointRange.HighVal[i]}, - HighExclude: highExclude, + HighExclude: false, Collators: []collate.Collator{idxPointRange.Collators[i]}, } diff --git a/statistics/testdata/stats_suite_out.json b/statistics/testdata/stats_suite_out.json index df4c8498d845c..d07b336ccbfbd 100644 --- a/statistics/testdata/stats_suite_out.json +++ b/statistics/testdata/stats_suite_out.json @@ -706,12 +706,12 @@ { "Start": 300, "End": 899, - "Count": 4500 + "Count": 4498.5 }, { "Start": 800, "End": 1000, - "Count": 1210.196869573942 + "Count": 1201.196869573942 }, { "Start": 900, @@ -736,7 +736,7 @@ { "Start": 200, "End": 400, - "Count": 1230.0288209899081 + "Count": 1211.5288209899081 }, { "Start": 200, diff --git a/statistics/testdata/trace_suite_in.json b/statistics/testdata/trace_suite_in.json index 62ecf9e378432..b87fbb113f86f 100644 --- a/statistics/testdata/trace_suite_in.json +++ b/statistics/testdata/trace_suite_in.json @@ -5,7 +5,8 @@ "a > 0 and a < 2", "a >= 1 and a < 10", "a < 3 or b < 4", - "a = 1 and b = 2" + "a = 1 and b = 2", + "a < 5 or a > 10" ] } ] diff --git a/statistics/testdata/trace_suite_out.json b/statistics/testdata/trace_suite_out.json index 2fe71ac70eec0..6f649d1aae028 100644 --- a/statistics/testdata/trace_suite_out.json +++ b/statistics/testdata/trace_suite_out.json @@ -129,6 +129,29 @@ "row_count": 2 } ] + }, + { + "Expr": "a < 5 or a > 10", + "Trace": [ + { + "table_name": "t", + "type": "Index Stats-Range", + "expr": "((a < 5)) or ((a > 10 and true))", + "row_count": 6 + }, + { + "table_name": "t", + "type": "Column Stats-Range", + "expr": "((a < 5)) or ((a > 10 and true))", + "row_count": 6 + }, + { + "table_name": "t", + "type": "Table Stats-Expression-CNF", + "expr": "`or`(`lt`(test.t.a, 5), `gt`(test.t.a, 10))", + "row_count": 6 + } + ] } ] } diff --git a/store/batch_coprocessor_serial_test.go b/store/batch_coprocessor_test.go similarity index 88% rename from store/batch_coprocessor_serial_test.go rename to store/batch_coprocessor_test.go index 07345156bb389..20caf2cf18695 100644 --- a/store/batch_coprocessor_serial_test.go +++ b/store/batch_coprocessor_test.go @@ -23,12 +23,10 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/unistore" - "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" ) @@ -52,16 +50,6 @@ func createMockTiKVStoreOptions(tiflashNum int) []mockstore.MockTiKVStoreOption } } -func testGetTableByName(t *testing.T, ctx sessionctx.Context, db, table string) table.Table { - dom := domain.GetDomain(ctx) - // Make sure the table schema is the new schema. - err := dom.Reload() - require.NoError(t, err) - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) - require.NoError(t, err) - return tbl -} - func TestStoreErr(t *testing.T) { store, clean := testkit.CreateMockStore(t, createMockTiKVStoreOptions(1)...) defer clean() @@ -75,7 +63,7 @@ func TestStoreErr(t *testing.T) { tk.MustExec("use test") tk.MustExec("create table t(a int not null, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(t, tk.Session(), "test", "t") + tb := external.GetTableByName(t, tk, "test", "t") err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) require.NoError(t, err) @@ -111,7 +99,7 @@ func TestStoreSwitchPeer(t *testing.T) { tk.MustExec("use test") tk.MustExec("create table t(a int not null, b int not null)") tk.MustExec("alter table t set tiflash replica 1") - tb := testGetTableByName(t, tk.Session(), "test", "t") + tb := external.GetTableByName(t, tk, "test", "t") err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) require.NoError(t, err) diff --git a/store/copr/batch_coprocessor.go b/store/copr/batch_coprocessor.go index e2ab8de16c30b..32f38a72f7576 100644 --- a/store/copr/batch_coprocessor.go +++ b/store/copr/batch_coprocessor.go @@ -30,7 +30,6 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/coprocessor" "github.com/pingcap/kvproto/pkg/kvrpcpb" - "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/kvproto/pkg/mpp" "github.com/pingcap/log" "github.com/pingcap/tidb/kv" @@ -49,7 +48,10 @@ type batchCopTask struct { cmdType tikvrpc.CmdType ctx *tikv.RPCContext - regionInfos []RegionInfo + regionInfos []RegionInfo // region info for single physical table + // PartitionTableRegions indicates region infos for each partition table, used by scanning partitions in batch. + // Thus, one of `regionInfos` and `PartitionTableRegions` must be nil. + PartitionTableRegions []*coprocessor.TableRegions } type batchCopResponse struct { @@ -291,6 +293,10 @@ func balanceBatchCopTaskWithContinuity(storeTaskMap map[uint64]*batchCopTask, ca // The second balance strategy: Not only consider the region count between TiFlash stores, but also try to make the regions' range continuous(stored in TiFlash closely). // If balanceWithContinuity is true, the second balance strategy is enable. func balanceBatchCopTask(ctx context.Context, kvStore *kvStore, originalTasks []*batchCopTask, mppStoreLastFailTime map[string]time.Time, ttl time.Duration, balanceWithContinuity bool, balanceContinuousRegionCount int64) []*batchCopTask { + if len(originalTasks) == 0 { + log.Info("Batch cop task balancer got an empty task set.") + return originalTasks + } isMPP := mppStoreLastFailTime != nil // for mpp, we still need to detect the store availability if len(originalTasks) <= 1 && !isMPP { @@ -519,25 +525,47 @@ func balanceBatchCopTask(ctx context.Context, kvStore *kvStore, originalTasks [] return ret } -func buildBatchCopTasks(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges, storeType kv.StoreType, mppStoreLastFailTime map[string]time.Time, ttl time.Duration, balanceWithContinuity bool, balanceContinuousRegionCount int64) ([]*batchCopTask, error) { +func buildBatchCopTasksForNonPartitionedTable(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges, storeType kv.StoreType, mppStoreLastFailTime map[string]time.Time, ttl time.Duration, balanceWithContinuity bool, balanceContinuousRegionCount int64) ([]*batchCopTask, error) { + return buildBatchCopTasksCore(bo, store, []*KeyRanges{ranges}, storeType, mppStoreLastFailTime, ttl, balanceWithContinuity, balanceContinuousRegionCount) +} + +func buildBatchCopTasksForPartitionedTable(bo *backoff.Backoffer, store *kvStore, rangesForEachPhysicalTable []*KeyRanges, storeType kv.StoreType, mppStoreLastFailTime map[string]time.Time, ttl time.Duration, balanceWithContinuity bool, balanceContinuousRegionCount int64, partitionIDs []int64) ([]*batchCopTask, error) { + batchTasks, err := buildBatchCopTasksCore(bo, store, rangesForEachPhysicalTable, storeType, mppStoreLastFailTime, ttl, balanceWithContinuity, balanceContinuousRegionCount) + if err != nil { + return nil, err + } + // generate tableRegions for batchCopTasks + convertRegionInfosToPartitionTableRegions(batchTasks, partitionIDs) + return batchTasks, nil +} + +// When `partitionIDs != nil`, it means that buildBatchCopTasksCore is constructing a batch cop tasks for PartitionTableScan. +// At this time, `len(rangesForEachPhysicalTable) == len(partitionIDs)` and `rangesForEachPhysicalTable[i]` is for partition `partitionIDs[i]`. +// Otherwise, `rangesForEachPhysicalTable[0]` indicates the range for the single physical table. +func buildBatchCopTasksCore(bo *backoff.Backoffer, store *kvStore, rangesForEachPhysicalTable []*KeyRanges, storeType kv.StoreType, mppStoreLastFailTime map[string]time.Time, ttl time.Duration, balanceWithContinuity bool, balanceContinuousRegionCount int64) ([]*batchCopTask, error) { cache := store.GetRegionCache() start := time.Now() const cmdType = tikvrpc.CmdBatchCop - rangesLen := ranges.Len() - for { + rangesLen := 0 - locations, err := cache.SplitKeyRangesByLocations(bo, ranges) - if err != nil { - return nil, errors.Trace(err) - } + for { var tasks []*copTask - for _, lo := range locations { - tasks = append(tasks, &copTask{ - region: lo.Location.Region, - ranges: lo.Ranges, - cmdType: cmdType, - storeType: storeType, - }) + rangesLen = 0 + for i, ranges := range rangesForEachPhysicalTable { + rangesLen += ranges.Len() + locations, err := cache.SplitKeyRangesByLocations(bo, ranges) + if err != nil { + return nil, errors.Trace(err) + } + for _, lo := range locations { + tasks = append(tasks, &copTask{ + region: lo.Location.Region, + ranges: lo.Ranges, + cmdType: cmdType, + storeType: storeType, + partitionIndex: int64(i), + }) + } } var batchTasks []*batchCopTask @@ -562,13 +590,13 @@ func buildBatchCopTasks(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges } allStores := cache.GetAllValidTiFlashStores(task.region, rpcCtx.Store) if batchCop, ok := storeTaskMap[rpcCtx.Addr]; ok { - batchCop.regionInfos = append(batchCop.regionInfos, RegionInfo{Region: task.region, Meta: rpcCtx.Meta, Ranges: task.ranges, AllStores: allStores}) + batchCop.regionInfos = append(batchCop.regionInfos, RegionInfo{Region: task.region, Meta: rpcCtx.Meta, Ranges: task.ranges, AllStores: allStores, PartitionIndex: task.partitionIndex}) } else { batchTask := &batchCopTask{ storeAddr: rpcCtx.Addr, cmdType: cmdType, ctx: rpcCtx, - regionInfos: []RegionInfo{{Region: task.region, Meta: rpcCtx.Meta, Ranges: task.ranges, AllStores: allStores}}, + regionInfos: []RegionInfo{{Region: task.region, Meta: rpcCtx.Meta, Ranges: task.ranges, AllStores: allStores, PartitionIndex: task.partitionIndex}}, } storeTaskMap[rpcCtx.Addr] = batchTask } @@ -577,7 +605,7 @@ func buildBatchCopTasks(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges // As mentioned above, nil rpcCtx is always attributed to failed stores. // It's equal to long poll the store but get no response. Here we'd better use // TiFlash error to trigger the TiKV fallback mechanism. - err = bo.Backoff(tikv.BoTiFlashRPC(), errors.New("Cannot find region with TiFlash peer")) + err := bo.Backoff(tikv.BoTiFlashRPC(), errors.New("Cannot find region with TiFlash peer")) if err != nil { return nil, errors.Trace(err) } @@ -606,7 +634,7 @@ func buildBatchCopTasks(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges } if elapsed := time.Since(start); elapsed > time.Millisecond*500 { - logutil.BgLogger().Warn("buildBatchCopTasks takes too much time", + logutil.BgLogger().Warn("buildBatchCopTasksCore takes too much time", zap.Duration("elapsed", elapsed), zap.Duration("balanceElapsed", balanceElapsed), zap.Int("range len", rangesLen), @@ -617,23 +645,66 @@ func buildBatchCopTasks(bo *backoff.Backoffer, store *kvStore, ranges *KeyRanges } } -func (c *CopClient) sendBatch(ctx context.Context, req *kv.Request, vars *tikv.Variables) kv.Response { +func convertRegionInfosToPartitionTableRegions(batchTasks []*batchCopTask, partitionIDs []int64) { + for _, copTask := range batchTasks { + tableRegions := make([]*coprocessor.TableRegions, len(partitionIDs)) + // init coprocessor.TableRegions + for j, pid := range partitionIDs { + tableRegions[j] = &coprocessor.TableRegions{ + PhysicalTableId: pid, + } + } + // fill region infos + for _, ri := range copTask.regionInfos { + tableRegions[ri.PartitionIndex].Regions = append(tableRegions[ri.PartitionIndex].Regions, + ri.toCoprocessorRegionInfo()) + } + count := 0 + // clear empty table region + for j := 0; j < len(tableRegions); j++ { + if len(tableRegions[j].Regions) != 0 { + tableRegions[count] = tableRegions[j] + count++ + } + } + copTask.PartitionTableRegions = tableRegions[:count] + copTask.regionInfos = nil + } +} + +func (c *CopClient) sendBatch(ctx context.Context, req *kv.Request, vars *tikv.Variables, option *kv.ClientSendOption) kv.Response { if req.KeepOrder || req.Desc { return copErrorResponse{errors.New("batch coprocessor cannot prove keep order or desc property")} } ctx = context.WithValue(ctx, tikv.TxnStartKey(), req.StartTs) bo := backoff.NewBackofferWithVars(ctx, copBuildTaskMaxBackoff, vars) - ranges := NewKeyRanges(req.KeyRanges) - tasks, err := buildBatchCopTasks(bo, c.store.kvStore, ranges, req.StoreType, nil, 0, false, 0) + + var tasks []*batchCopTask + var err error + if req.PartitionIDAndRanges != nil { + // For Partition Table Scan + keyRanges := make([]*KeyRanges, 0, len(req.PartitionIDAndRanges)) + partitionIDs := make([]int64, 0, len(req.PartitionIDAndRanges)) + for _, pi := range req.PartitionIDAndRanges { + keyRanges = append(keyRanges, NewKeyRanges(pi.KeyRanges)) + partitionIDs = append(partitionIDs, pi.ID) + } + tasks, err = buildBatchCopTasksForPartitionedTable(bo, c.store.kvStore, keyRanges, req.StoreType, nil, 0, false, 0, partitionIDs) + } else { + ranges := NewKeyRanges(req.KeyRanges) + tasks, err = buildBatchCopTasksForNonPartitionedTable(bo, c.store.kvStore, ranges, req.StoreType, nil, 0, false, 0) + } + if err != nil { return copErrorResponse{err} } it := &batchCopIterator{ - store: c.store.kvStore, - req: req, - finishCh: make(chan struct{}), - vars: vars, - rpcCancel: tikv.NewRPCanceller(), + store: c.store.kvStore, + req: req, + finishCh: make(chan struct{}), + vars: vars, + rpcCancel: tikv.NewRPCanceller(), + enableCollectExecutionInfo: option.EnableCollectExecutionInfo, } ctx = context.WithValue(ctx, tikv.RPCCancellerCtxKey{}, it.rpcCancel) it.tasks = tasks @@ -661,6 +732,8 @@ type batchCopIterator struct { // There are two cases we need to close the `finishCh` channel, one is when context is done, the other one is // when the Close is called. we use atomic.CompareAndSwap `closed` to to make sure the channel is not closed twice. closed uint32 + + enableCollectExecutionInfo bool } func (b *batchCopIterator) run(ctx context.Context) { @@ -759,37 +832,52 @@ func (b *batchCopIterator) handleTask(ctx context.Context, bo *Backoffer, task * // Merge all ranges and request again. func (b *batchCopIterator) retryBatchCopTask(ctx context.Context, bo *backoff.Backoffer, batchTask *batchCopTask) ([]*batchCopTask, error) { - var ranges []kv.KeyRange - for _, ri := range batchTask.regionInfos { - ri.Ranges.Do(func(ran *kv.KeyRange) { - ranges = append(ranges, *ran) - }) + if batchTask.regionInfos != nil { + var ranges []kv.KeyRange + for _, ri := range batchTask.regionInfos { + ri.Ranges.Do(func(ran *kv.KeyRange) { + ranges = append(ranges, *ran) + }) + } + ret, err := buildBatchCopTasksForNonPartitionedTable(bo, b.store, NewKeyRanges(ranges), b.req.StoreType, nil, 0, false, 0) + return ret, err + } + // Retry Partition Table Scan + keyRanges := make([]*KeyRanges, 0, len(batchTask.PartitionTableRegions)) + pid := make([]int64, 0, len(batchTask.PartitionTableRegions)) + for _, trs := range batchTask.PartitionTableRegions { + pid = append(pid, trs.PhysicalTableId) + ranges := make([]kv.KeyRange, 0, len(trs.Regions)) + for _, ri := range trs.Regions { + for _, ran := range ri.Ranges { + ranges = append(ranges, kv.KeyRange{ + StartKey: ran.Start, + EndKey: ran.End, + }) + } + } + keyRanges = append(keyRanges, NewKeyRanges(ranges)) } - return buildBatchCopTasks(bo, b.store, NewKeyRanges(ranges), b.req.StoreType, nil, 0, false, 0) + ret, err := buildBatchCopTasksForPartitionedTable(bo, b.store, keyRanges, b.req.StoreType, nil, 0, false, 0, pid) + return ret, err } const readTimeoutUltraLong = 3600 * time.Second // For requests that may scan many regions for tiflash. func (b *batchCopIterator) handleTaskOnce(ctx context.Context, bo *backoff.Backoffer, task *batchCopTask) ([]*batchCopTask, error) { - sender := NewRegionBatchRequestSender(b.store.GetRegionCache(), b.store.GetTiKVClient()) + sender := NewRegionBatchRequestSender(b.store.GetRegionCache(), b.store.GetTiKVClient(), b.enableCollectExecutionInfo) var regionInfos = make([]*coprocessor.RegionInfo, 0, len(task.regionInfos)) for _, ri := range task.regionInfos { - regionInfos = append(regionInfos, &coprocessor.RegionInfo{ - RegionId: ri.Region.GetID(), - RegionEpoch: &metapb.RegionEpoch{ - ConfVer: ri.Region.GetConfVer(), - Version: ri.Region.GetVer(), - }, - Ranges: ri.Ranges.ToPBRanges(), - }) + regionInfos = append(regionInfos, ri.toCoprocessorRegionInfo()) } copReq := coprocessor.BatchRequest{ - Tp: b.req.Tp, - StartTs: b.req.StartTs, - Data: b.req.Data, - SchemaVer: b.req.SchemaVar, - Regions: regionInfos, + Tp: b.req.Tp, + StartTs: b.req.StartTs, + Data: b.req.Data, + SchemaVer: b.req.SchemaVar, + Regions: regionInfos, + TableRegions: task.PartitionTableRegions, } req := tikvrpc.NewRequest(task.cmdType, &copReq, kvrpcpb.Context{ @@ -876,22 +964,13 @@ func (b *batchCopIterator) handleBatchCopResponse(bo *Backoffer, response *copro return } - resp := batchCopResponse{ + resp := &batchCopResponse{ pbResp: response, detail: new(CopRuntimeStats), } - backoffTimes := bo.GetBackoffTimes() - resp.detail.BackoffTime = time.Duration(bo.GetTotalSleep()) * time.Millisecond - resp.detail.BackoffSleep = make(map[string]time.Duration, len(backoffTimes)) - resp.detail.BackoffTimes = make(map[string]int, len(backoffTimes)) - for backoff := range backoffTimes { - resp.detail.BackoffTimes[backoff] = backoffTimes[backoff] - resp.detail.BackoffSleep[backoff] = time.Duration(bo.GetBackoffSleepMS()[backoff]) * time.Millisecond - } - resp.detail.CalleeAddress = task.storeAddr - - b.sendToRespCh(&resp) + b.handleCollectExecutionInfo(bo, resp, task) + b.sendToRespCh(resp) return } @@ -904,3 +983,18 @@ func (b *batchCopIterator) sendToRespCh(resp *batchCopResponse) (exit bool) { } return } + +func (b *batchCopIterator) handleCollectExecutionInfo(bo *Backoffer, resp *batchCopResponse, task *batchCopTask) { + if !b.enableCollectExecutionInfo { + return + } + backoffTimes := bo.GetBackoffTimes() + resp.detail.BackoffTime = time.Duration(bo.GetTotalSleep()) * time.Millisecond + resp.detail.BackoffSleep = make(map[string]time.Duration, len(backoffTimes)) + resp.detail.BackoffTimes = make(map[string]int, len(backoffTimes)) + for backoff := range backoffTimes { + resp.detail.BackoffTimes[backoff] = backoffTimes[backoff] + resp.detail.BackoffSleep[backoff] = time.Duration(bo.GetBackoffSleepMS()[backoff]) * time.Millisecond + } + resp.detail.CalleeAddress = task.storeAddr +} diff --git a/store/copr/batch_coprocessor_test.go b/store/copr/batch_coprocessor_test.go index 97428319ab2b1..95c619e3c1b0e 100644 --- a/store/copr/batch_coprocessor_test.go +++ b/store/copr/batch_coprocessor_test.go @@ -19,6 +19,7 @@ import ( "sort" "strconv" "testing" + "time" "github.com/pingcap/tidb/kv" "github.com/stretchr/testify/require" @@ -63,8 +64,8 @@ func buildRegionInfos(storeCount, regionCount, replicaNum int) []RegionInfo { return storeIDs } - var regionInfos []RegionInfo var startKey string + regionInfos := make([]RegionInfo, 0, len(ss)) for i, s := range ss { var ri RegionInfo ri.Region = tikv.NewRegionVerID(uint64(i), 1, 1) @@ -115,6 +116,22 @@ func TestBalanceBatchCopTaskWithContinuity(t *testing.T) { } } +func TestBalanceBatchCopTaskWithEmptyTaskSet(t *testing.T) { + { + var nilTaskSet []*batchCopTask + nilResult := balanceBatchCopTask(nil, nil, nilTaskSet, nil, time.Second, false, 0) + require.True(t, nilResult == nil) + } + + { + emptyTaskSet := make([]*batchCopTask, 0) + emptyResult := balanceBatchCopTask(nil, nil, emptyTaskSet, nil, time.Second, false, 0) + require.True(t, emptyResult != nil) + require.True(t, len(emptyResult) == 0) + } + +} + func TestDeepCopyStoreTaskMap(t *testing.T) { storeTasks1 := buildStoreTaskMap(10) for _, task := range storeTasks1 { diff --git a/store/copr/batch_request_sender.go b/store/copr/batch_request_sender.go index 256aa5c0dd468..b976d26a59ab3 100644 --- a/store/copr/batch_request_sender.go +++ b/store/copr/batch_request_sender.go @@ -19,6 +19,7 @@ import ( "time" "github.com/pingcap/errors" + "github.com/pingcap/kvproto/pkg/coprocessor" "github.com/pingcap/kvproto/pkg/metapb" tikverr "github.com/tikv/client-go/v2/error" "github.com/tikv/client-go/v2/tikv" @@ -29,21 +30,35 @@ import ( // RegionInfo contains region related information for batchCopTask type RegionInfo struct { - Region tikv.RegionVerID - Meta *metapb.Region - Ranges *KeyRanges - AllStores []uint64 + Region tikv.RegionVerID + Meta *metapb.Region + Ranges *KeyRanges + AllStores []uint64 + PartitionIndex int64 // used by PartitionTableScan, indicates the n-th partition of the partition table +} + +func (ri *RegionInfo) toCoprocessorRegionInfo() *coprocessor.RegionInfo { + return &coprocessor.RegionInfo{ + RegionId: ri.Region.GetID(), + RegionEpoch: &metapb.RegionEpoch{ + ConfVer: ri.Region.GetConfVer(), + Version: ri.Region.GetVer(), + }, + Ranges: ri.Ranges.ToPBRanges(), + } } // RegionBatchRequestSender sends BatchCop requests to TiFlash server by stream way. type RegionBatchRequestSender struct { *tikv.RegionRequestSender + enableCollectExecutionInfo bool } // NewRegionBatchRequestSender creates a RegionBatchRequestSender object. -func NewRegionBatchRequestSender(cache *RegionCache, client tikv.Client) *RegionBatchRequestSender { +func NewRegionBatchRequestSender(cache *RegionCache, client tikv.Client, enableCollectExecutionInfo bool) *RegionBatchRequestSender { return &RegionBatchRequestSender{ - RegionRequestSender: tikv.NewRegionRequestSender(cache.RegionCache, client), + RegionRequestSender: tikv.NewRegionRequestSender(cache.RegionCache, client), + enableCollectExecutionInfo: enableCollectExecutionInfo, } } @@ -59,7 +74,7 @@ func (ss *RegionBatchRequestSender) SendReqToAddr(bo *Backoffer, rpcCtx *tikv.RP } start := time.Now() resp, err = ss.GetClient().SendRequest(ctx, rpcCtx.Addr, req, timout) - if ss.Stats != nil { + if ss.Stats != nil && ss.enableCollectExecutionInfo { tikv.RecordRegionRequestRuntimeStats(ss.Stats, req.Type, time.Since(start)) } if err != nil { diff --git a/store/copr/coprocessor.go b/store/copr/coprocessor.go index 25ed965ea15e3..dba00aa935c60 100644 --- a/store/copr/coprocessor.go +++ b/store/copr/coprocessor.go @@ -42,6 +42,7 @@ import ( "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" + "github.com/pingcap/tidb/util/paging" "github.com/pingcap/tidb/util/trxevents" "github.com/pingcap/tipb/go-tipb" "github.com/tikv/client-go/v2/metrics" @@ -61,18 +62,6 @@ const ( copNextMaxBackoff = 20000 ) -// A paging request may be separated into multi requests if there are more data than a page. -// The paging size grows from min to max, it's not well tuned yet. -// e.g. a paging request scans over range (r1, r200), it requires 64 rows in the first batch, -// if it's not drained, then the paging size grows, the new range is calculated like (r100, r200), then send a request again. -// Compare with the common unary request, paging request allows early access of data, it offers a streaming-like way processing data. -// TODO: may make the paging parameters configurable. -const ( - minPagingSize uint64 = 64 - maxPagingSize = minPagingSize * 128 - pagingSizeGrow uint64 = 2 -) - // CopClient is coprocessor client. type CopClient struct { kv.RequestTypeSupportedChecker @@ -81,14 +70,17 @@ type CopClient struct { } // Send builds the request and gets the coprocessor iterator response. -func (c *CopClient) Send(ctx context.Context, req *kv.Request, variables interface{}, sessionMemTracker *memory.Tracker, enabledRateLimitAction bool, eventCb trxevents.EventCallback) kv.Response { +func (c *CopClient) Send(ctx context.Context, req *kv.Request, variables interface{}, option *kv.ClientSendOption) kv.Response { + eventCb := option.EventCb + enabledRateLimitAction := option.EnabledRateLimitAction + sessionMemTracker := option.SessionMemTracker vars, ok := variables.(*tikv.Variables) if !ok { return copErrorResponse{errors.Errorf("unsupported variables:%+v", variables)} } if req.StoreType == kv.TiFlash && req.BatchCop { logutil.BgLogger().Debug("send batch requests") - return c.sendBatch(ctx, req, vars) + return c.sendBatch(ctx, req, vars, option) } if req.Streaming && req.Paging { return copErrorResponse{errors.New("streaming and paging are both on")} @@ -141,21 +133,22 @@ func (c *CopClient) Send(ctx context.Context, req *kv.Request, variables interfa it.sendRate = util.NewRateLimit(it.concurrency) } it.actionOnExceed = newRateLimitAction(uint(it.sendRate.GetCapacity())) - if sessionMemTracker != nil { + if sessionMemTracker != nil && enabledRateLimitAction { sessionMemTracker.FallbackOldAndSetNewAction(it.actionOnExceed) } if !it.req.Streaming { ctx = context.WithValue(ctx, tikv.RPCCancellerCtxKey{}, it.rpcCancel) } - it.open(ctx, enabledRateLimitAction) + it.open(ctx, enabledRateLimitAction, option.EnableCollectExecutionInfo) return it } // copTask contains a related Region and KeyRange for a kv.Request. type copTask struct { - region tikv.RegionVerID - ranges *KeyRanges + region tikv.RegionVerID + bucketsVer uint64 + ranges *KeyRanges respChan chan *copResponse storeAddr string @@ -165,6 +158,8 @@ type copTask struct { eventCb trxevents.EventCallback paging bool pagingSize uint64 + + partitionIndex int64 // used by balanceBatchCopTask in PartitionTableScan } func (r *copTask) String() string { @@ -188,7 +183,8 @@ func buildCopTasks(bo *Backoffer, cache *RegionCache, ranges *KeyRanges, req *kv rangesLen := ranges.Len() - locs, err := cache.SplitKeyRangesByLocations(bo, ranges) + // TODO(youjiali1995): is there any request type that needn't be splitted by buckets? + locs, err := cache.SplitKeyRangesByBuckets(bo, ranges) if err != nil { return nil, errors.Trace(err) } @@ -212,10 +208,11 @@ func buildCopTasks(bo *Backoffer, cache *RegionCache, ranges *KeyRanges, req *kv // the size will grow every round. pagingSize := uint64(0) if req.Paging { - pagingSize = minPagingSize + pagingSize = paging.MinPagingSize } tasks = append(tasks, &copTask{ region: loc.Location.Region, + bucketsVer: loc.getBucketVersion(), ranges: loc.Ranges.Slice(i, nextI), respChan: make(chan *copResponse, chanSize), cmdType: cmdType, @@ -327,7 +324,7 @@ type copIteratorWorker struct { replicaReadSeed uint32 - actionOnExceed *rateLimitAction + enableCollectExecutionInfo bool } // copIteratorTaskSender sends tasks to taskCh then wait for the workers to exit. @@ -432,23 +429,23 @@ func (worker *copIteratorWorker) run(ctx context.Context) { } // open starts workers and sender goroutines. -func (it *copIterator) open(ctx context.Context, enabledRateLimitAction bool) { +func (it *copIterator) open(ctx context.Context, enabledRateLimitAction, enableCollectExecutionInfo bool) { taskCh := make(chan *copTask, 1) it.wg.Add(it.concurrency) // Start it.concurrency number of workers to handle cop requests. for i := 0; i < it.concurrency; i++ { worker := &copIteratorWorker{ - taskCh: taskCh, - wg: &it.wg, - store: it.store, - req: it.req, - respChan: it.respChan, - finishCh: it.finishCh, - vars: it.vars, - kvclient: txnsnapshot.NewClientHelper(it.store.store, &it.resolvedLocks, &it.committedLocks, false), - memTracker: it.memTracker, - replicaReadSeed: it.replicaReadSeed, - actionOnExceed: it.actionOnExceed, + taskCh: taskCh, + wg: &it.wg, + store: it.store, + req: it.req, + respChan: it.respChan, + finishCh: it.finishCh, + vars: it.vars, + kvclient: txnsnapshot.NewClientHelper(it.store.store, &it.resolvedLocks, &it.committedLocks, false), + memTracker: it.memTracker, + replicaReadSeed: it.replicaReadSeed, + enableCollectExecutionInfo: enableCollectExecutionInfo, } go worker.run(ctx) } @@ -928,7 +925,7 @@ func (worker *copIteratorWorker) handleCopPagingResult(bo *Backoffer, rpcCtx *ti if task.ranges.Len() == 0 { return nil, nil } - task.pagingSize = growPagingSize(task.pagingSize) + task.pagingSize = paging.GrowPagingSize(task.pagingSize) return []*copTask{task}, nil } @@ -937,6 +934,9 @@ func (worker *copIteratorWorker) handleCopPagingResult(bo *Backoffer, rpcCtx *ti // if we're handling streaming coprocessor response, lastRange is the range of last // successful response, otherwise it's nil. func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.RPCContext, resp *copResponse, cacheKey []byte, cacheValue *coprCacheValue, task *copTask, ch chan<- *copResponse, lastRange *coprocessor.KeyRange, costTime time.Duration) ([]*copTask, error) { + if ver := resp.pbResp.GetLatestBucketsVersion(); task.bucketsVer < ver { + worker.store.GetRegionCache().UpdateBucketsIfNeeded(task.region, ver) + } if regionErr := resp.pbResp.GetRegionError(); regionErr != nil { if rpcCtx != nil && task.storeType == kv.TiDB { resp.err = errors.Errorf("error: %v", regionErr) @@ -983,6 +983,9 @@ func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.R zap.Uint64("regionID", task.region.GetID()), zap.String("storeAddr", task.storeAddr), zap.Error(err)) + if strings.Contains(err.Error(), "write conflict") { + return nil, kv.ErrWriteConflict + } return nil, errors.Trace(err) } // When the request is using streaming API, the `Range` is not nil. @@ -991,11 +994,54 @@ func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.R } else if task.ranges != nil && task.ranges.Len() > 0 { resp.startKey = task.ranges.At(0).StartKey } + worker.handleCollectExecutionInfo(bo, rpcCtx, resp) + resp.respTime = costTime + if resp.pbResp.IsCacheHit { + if cacheValue == nil { + return nil, errors.New("Internal error: received illegal TiKV response") + } + // Cache hit and is valid: use cached data as response data and we don't update the cache. + data := make([]byte, len(cacheValue.Data)) + copy(data, cacheValue.Data) + resp.pbResp.Data = data + resp.detail.CoprCacheHit = true + } else { + // Cache not hit or cache hit but not valid: update the cache if the response can be cached. + if cacheKey != nil && resp.pbResp.CanBeCached && resp.pbResp.CacheLastVersion > 0 { + if worker.store.coprCache.CheckResponseAdmission(resp.pbResp.Data.Size(), resp.detail.TimeDetail.ProcessTime) { + data := make([]byte, len(resp.pbResp.Data)) + copy(data, resp.pbResp.Data) + + newCacheValue := coprCacheValue{ + Data: data, + TimeStamp: worker.req.StartTs, + RegionID: task.region.GetID(), + RegionDataVersion: resp.pbResp.CacheLastVersion, + } + worker.store.coprCache.Set(cacheKey, &newCacheValue) + } + } + } + worker.sendToRespCh(resp, ch, true) + return nil, nil +} + +func (worker *copIteratorWorker) handleCollectExecutionInfo(bo *Backoffer, rpcCtx *tikv.RPCContext, resp *copResponse) { + defer func() { + worker.kvclient.Stats = nil + }() + if !worker.enableCollectExecutionInfo { + return + } + failpoint.Inject("disable-collect-execution", func(val failpoint.Value) { + if val.(bool) { + panic("shouldn't reachable") + } + }) if resp.detail == nil { resp.detail = new(CopRuntimeStats) } resp.detail.Stats = worker.kvclient.Stats - worker.kvclient.Stats = nil backoffTimes := bo.GetBackoffTimes() resp.detail.BackoffTime = time.Duration(bo.GetTotalSleep()) * time.Millisecond resp.detail.BackoffSleep = make(map[string]time.Duration, len(backoffTimes)) @@ -1007,7 +1053,6 @@ func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.R if rpcCtx != nil { resp.detail.CalleeAddress = rpcCtx.Addr } - resp.respTime = costTime sd := &util.ScanDetail{} td := util.TimeDetail{} if pbDetails := resp.pbResp.ExecDetailsV2; pbDetails != nil { @@ -1031,34 +1076,6 @@ func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.R } resp.detail.ScanDetail = sd resp.detail.TimeDetail = td - if resp.pbResp.IsCacheHit { - if cacheValue == nil { - return nil, errors.New("Internal error: received illegal TiKV response") - } - // Cache hit and is valid: use cached data as response data and we don't update the cache. - data := make([]byte, len(cacheValue.Data)) - copy(data, cacheValue.Data) - resp.pbResp.Data = data - resp.detail.CoprCacheHit = true - } else { - // Cache not hit or cache hit but not valid: update the cache if the response can be cached. - if cacheKey != nil && resp.pbResp.CanBeCached && resp.pbResp.CacheLastVersion > 0 { - if worker.store.coprCache.CheckResponseAdmission(resp.pbResp.Data.Size(), resp.detail.TimeDetail.ProcessTime) { - data := make([]byte, len(resp.pbResp.Data)) - copy(data, resp.pbResp.Data) - - newCacheValue := coprCacheValue{ - Data: data, - TimeStamp: worker.req.StartTs, - RegionID: task.region.GetID(), - RegionDataVersion: resp.pbResp.CacheLastVersion, - } - worker.store.coprCache.Set(cacheKey, &newCacheValue) - } - } - } - worker.sendToRespCh(resp, ch, true) - return nil, nil } // CopRuntimeStats contains execution detail information. @@ -1328,15 +1345,9 @@ func isolationLevelToPB(level kv.IsoLevel) kvrpcpb.IsolationLevel { return kvrpcpb.IsolationLevel_RC case kv.SI: return kvrpcpb.IsolationLevel_SI + case kv.RCCheckTS: + return kvrpcpb.IsolationLevel_RCCheckTS default: return kvrpcpb.IsolationLevel_SI } } - -func growPagingSize(size uint64) uint64 { - size *= pagingSizeGrow - if size > maxPagingSize { - return maxPagingSize - } - return size -} diff --git a/store/copr/coprocessor_test.go b/store/copr/coprocessor_test.go index 88ad5568f68eb..84eb95cb73c58 100644 --- a/store/copr/coprocessor_test.go +++ b/store/copr/coprocessor_test.go @@ -21,12 +21,13 @@ import ( "github.com/pingcap/kvproto/pkg/coprocessor" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/store/driver/backoff" + "github.com/pingcap/tidb/util/paging" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" "github.com/tikv/client-go/v2/tikv" ) -func TestBuildTasks(t *testing.T) { +func TestBuildTasksWithoutBuckets(t *testing.T) { // nil --- 'g' --- 'n' --- 't' --- nil // <- 0 -> <- 1 -> <- 2 -> <- 3 -> mockClient, cluster, pdClient, err := testutils.NewMockTiKV("", nil) @@ -52,105 +53,252 @@ func TestBuildTasks(t *testing.T) { tasks, err := buildCopTasks(bo, cache, buildCopRanges("a", "c"), req, nil) require.NoError(t, err) require.Len(t, tasks, 1) - require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "c") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "c") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "c"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "c") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "c") tasks, err = buildCopTasks(bo, cache, buildCopRanges("g", "n"), req, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[1], "g", "n") + taskEqual(t, tasks[0], regionIDs[1], 0, "g", "n") tasks, err = buildCopTasks(bo, cache, buildCopRanges("g", "n"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[1], "g", "n") + taskEqual(t, tasks[0], regionIDs[1], 0, "g", "n") tasks, err = buildCopTasks(bo, cache, buildCopRanges("m", "n"), req, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[1], "m", "n") + taskEqual(t, tasks[0], regionIDs[1], 0, "m", "n") tasks, err = buildCopTasks(bo, cache, buildCopRanges("m", "n"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[1], "m", "n") + taskEqual(t, tasks[0], regionIDs[1], 0, "m", "n") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "k"), req, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[0], "a", "g") - taskEqual(t, tasks[1], regionIDs[1], "g", "k") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "g") + taskEqual(t, tasks[1], regionIDs[1], 0, "g", "k") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "k"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[0], "a", "g") - taskEqual(t, tasks[1], regionIDs[1], "g", "k") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "g") + taskEqual(t, tasks[1], regionIDs[1], 0, "g", "k") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "x"), req, nil) require.NoError(t, err) require.Len(t, tasks, 4) - taskEqual(t, tasks[0], regionIDs[0], "a", "g") - taskEqual(t, tasks[1], regionIDs[1], "g", "n") - taskEqual(t, tasks[2], regionIDs[2], "n", "t") - taskEqual(t, tasks[3], regionIDs[3], "t", "x") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "g") + taskEqual(t, tasks[1], regionIDs[1], 0, "g", "n") + taskEqual(t, tasks[2], regionIDs[2], 0, "n", "t") + taskEqual(t, tasks[3], regionIDs[3], 0, "t", "x") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "x"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 4) - taskEqual(t, tasks[0], regionIDs[0], "a", "g") - taskEqual(t, tasks[1], regionIDs[1], "g", "n") - taskEqual(t, tasks[2], regionIDs[2], "n", "t") - taskEqual(t, tasks[3], regionIDs[3], "t", "x") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "g") + taskEqual(t, tasks[1], regionIDs[1], 0, "g", "n") + taskEqual(t, tasks[2], regionIDs[2], 0, "n", "t") + taskEqual(t, tasks[3], regionIDs[3], 0, "t", "x") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "b", "b", "c"), req, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "b", "b", "c") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "b", "b", "c") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "b", "b", "c"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "b", "b", "c") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "b", "b", "c") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "b", "e", "f"), req, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "b", "e", "f") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "b", "e", "f") tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "b", "e", "f"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "b", "e", "f") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "b", "e", "f") tasks, err = buildCopTasks(bo, cache, buildCopRanges("g", "n", "o", "p"), req, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[1], "g", "n") - taskEqual(t, tasks[1], regionIDs[2], "o", "p") + taskEqual(t, tasks[0], regionIDs[1], 0, "g", "n") + taskEqual(t, tasks[1], regionIDs[2], 0, "o", "p") tasks, err = buildCopTasks(bo, cache, buildCopRanges("g", "n", "o", "p"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[1], "g", "n") - taskEqual(t, tasks[1], regionIDs[2], "o", "p") + taskEqual(t, tasks[0], regionIDs[1], 0, "g", "n") + taskEqual(t, tasks[1], regionIDs[2], 0, "o", "p") tasks, err = buildCopTasks(bo, cache, buildCopRanges("h", "k", "m", "p"), req, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[1], "h", "k", "m", "n") - taskEqual(t, tasks[1], regionIDs[2], "n", "p") + taskEqual(t, tasks[0], regionIDs[1], 0, "h", "k", "m", "n") + taskEqual(t, tasks[1], regionIDs[2], 0, "n", "p") tasks, err = buildCopTasks(bo, cache, buildCopRanges("h", "k", "m", "p"), flashReq, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[1], "h", "k", "m", "n") - taskEqual(t, tasks[1], regionIDs[2], "n", "p") + taskEqual(t, tasks[0], regionIDs[1], 0, "h", "k", "m", "n") + taskEqual(t, tasks[1], regionIDs[2], 0, "n", "p") +} + +func TestBuildTasksByBuckets(t *testing.T) { + mockClient, cluster, pdClient, err := testutils.NewMockTiKV("", nil) + require.NoError(t, err) + defer func() { + pdClient.Close() + err = mockClient.Close() + require.NoError(t, err) + }() + + // region: nil------------------n-----------x-----------nil + // buckets: nil----c----g----k---n----t------x-----------nil + _, regionIDs, _ := testutils.BootstrapWithMultiRegions(cluster, []byte("n"), []byte("x")) + cluster.SplitRegionBuckets(regionIDs[0], [][]byte{{}, {'c'}, {'g'}, {'k'}, {'n'}}, regionIDs[0]) + cluster.SplitRegionBuckets(regionIDs[1], [][]byte{{'n'}, {'t'}, {'x'}}, regionIDs[1]) + cluster.SplitRegionBuckets(regionIDs[2], [][]byte{{'x'}, {}}, regionIDs[2]) + pdCli := &tikv.CodecPDClient{Client: pdClient} + defer pdCli.Close() + + cache := NewRegionCache(tikv.NewRegionCache(pdCli)) + defer cache.Close() + + bo := backoff.NewBackofferWithVars(context.Background(), 3000, nil) + + // one range per bucket + // region: nil------------------n-----------x-----------nil + // buckets: nil----c----g----k---n----t------x-----------nil + // range&task: a-b c-d h-i k---n o-p u--x-----------nil + req := &kv.Request{} + regionRanges := []struct { + regionID uint64 + ranges []string + }{ + {regionIDs[0], []string{"a", "b", "c", "d", "h", "i", "k", "n"}}, + {regionIDs[1], []string{"o", "p", "u", "x"}}, + {regionIDs[2], []string{"x", ""}}, + } + for _, regionRange := range regionRanges { + regionID, ranges := regionRange.regionID, regionRange.ranges + tasks, err := buildCopTasks(bo, cache, buildCopRanges(ranges...), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(ranges)/2) + for i, task := range tasks { + taskEqual(t, task, regionID, regionID, ranges[2*i], ranges[2*i+1]) + } + } + + // one request multiple regions + allRanges := []string{} + for _, regionRange := range regionRanges { + allRanges = append(allRanges, regionRange.ranges...) + } + tasks, err := buildCopTasks(bo, cache, buildCopRanges(allRanges...), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(allRanges)/2) + taskIdx := 0 + for _, regionRange := range regionRanges { + regionID, ranges := regionRange.regionID, regionRange.ranges + for i := 0; i < len(ranges); i += 2 { + taskEqual(t, tasks[taskIdx], regionID, regionID, ranges[i], ranges[i+1]) + taskIdx++ + } + } + + // serveral ranges per bucket + // region: nil---------------------------n-----------x-----------nil + // buckets: nil-----c-------g-------k-----n----t------x-----------nil + // ranges: nil-a b-c d-e f-g h-i j-k-l m-n + // tasks: nil-a b-c + // d-e f-g + // h-i j-k + // k-l m-n + keyRanges := []string{ + "", "a", "b", "c", + "d", "e", "f", "g", + "h", "i", "j", "k", + "k", "l", "m", "n", + } + tasks, err = buildCopTasks(bo, cache, buildCopRanges(keyRanges...), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(keyRanges)/4) + for i, task := range tasks { + taskEqual(t, task, regionIDs[0], regionIDs[0], keyRanges[4*i], keyRanges[4*i+1], keyRanges[4*i+2], keyRanges[4*i+3]) + } + + // cross bucket ranges + // buckets: nil-----c-------g---------k---n----t------x-----------nil + // ranges: nil-------d e---h i---j + // tasks: nil-----c + // c-d e-g + // g-h i---j + keyRanges = []string{ + "", "d", "e", "h", "i", "j", + } + expectedTaskRanges := [][]string{ + {"", "c"}, + {"c", "d", "e", "g"}, + {"g", "h", "i", "j"}, + } + tasks, err = buildCopTasks(bo, cache, buildCopRanges(keyRanges...), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(expectedTaskRanges)) + for i, task := range tasks { + taskEqual(t, task, regionIDs[0], regionIDs[0], expectedTaskRanges[i]...) + } + + // out of range buckets + // region: n------------------x + // buckets: q---s---u + // ranges: n-o p----s t---v w-x + // tasks: n-o p----s(it can be improved, i.e., n-o p-q, q-s) + // t-u + // u-v w-x + expectedTaskRanges = [][]string{ + {"n", "o", "p", "s"}, + {"t", "u"}, + {"u", "v", "w", "x"}, + } + cluster.SplitRegionBuckets(regionIDs[1], [][]byte{{'q'}, {'s'}, {'u'}}, regionIDs[1]) + cache = NewRegionCache(tikv.NewRegionCache(pdCli)) + defer cache.Close() + tasks, err = buildCopTasks(bo, cache, buildCopRanges("n", "o", "p", "s", "t", "v", "w", "x"), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(expectedTaskRanges)) + for i, task := range tasks { + taskEqual(t, task, regionIDs[1], regionIDs[1], expectedTaskRanges[i]...) + } + + // out of range buckets + // region: n------------x + // buckets: g-------t---------z + // ranges: o-p u-w + // tasks: o-p + // u-w + expectedTaskRanges = [][]string{ + {"o", "p"}, + {"u", "w"}, + } + cluster.SplitRegionBuckets(regionIDs[1], [][]byte{{'g'}, {'t'}, {'z'}}, regionIDs[1]) + cache = NewRegionCache(tikv.NewRegionCache(pdCli)) + defer cache.Close() + tasks, err = buildCopTasks(bo, cache, buildCopRanges("o", "p", "u", "w"), req, nil) + require.NoError(t, err) + require.Len(t, tasks, len(expectedTaskRanges)) + for i, task := range tasks { + taskEqual(t, task, regionIDs[1], regionIDs[1], expectedTaskRanges[i]...) + } } func TestSplitRegionRanges(t *testing.T) { @@ -237,8 +385,8 @@ func TestRebuild(t *testing.T) { tasks, err := buildCopTasks(bo, cache, buildCopRanges("a", "z"), req, nil) require.NoError(t, err) require.Len(t, tasks, 2) - taskEqual(t, tasks[0], regionIDs[0], "a", "m") - taskEqual(t, tasks[1], regionIDs[1], "m", "z") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "m") + taskEqual(t, tasks[1], regionIDs[1], 0, "m", "z") // nil -- 'm' -- 'q' -- nil // <- 0 -> <--1-> <-2--> @@ -251,9 +399,9 @@ func TestRebuild(t *testing.T) { tasks, err = buildCopTasks(bo, cache, buildCopRanges("a", "z"), req, nil) require.NoError(t, err) require.Len(t, tasks, 3) - taskEqual(t, tasks[2], regionIDs[0], "a", "m") - taskEqual(t, tasks[1], regionIDs[1], "m", "q") - taskEqual(t, tasks[0], regionIDs[2], "q", "z") + taskEqual(t, tasks[2], regionIDs[0], 0, "a", "m") + taskEqual(t, tasks[1], regionIDs[1], 0, "m", "q") + taskEqual(t, tasks[0], regionIDs[2], 0, "q", "z") } func buildKeyRanges(keys ...string) []kv.KeyRange { @@ -271,8 +419,9 @@ func buildCopRanges(keys ...string) *KeyRanges { return NewKeyRanges(buildKeyRanges(keys...)) } -func taskEqual(t *testing.T, task *copTask, regionID uint64, keys ...string) { +func taskEqual(t *testing.T, task *copTask, regionID, bucketsVer uint64, keys ...string) { require.Equal(t, task.region.GetID(), regionID) + require.Equal(t, task.bucketsVer, bucketsVer) for i := 0; i < task.ranges.Len(); i++ { r := task.ranges.At(i) require.Equal(t, string(r.StartKey), keys[2*i]) @@ -316,9 +465,9 @@ func TestBuildPagingTasks(t *testing.T) { require.NoError(t, err) require.Len(t, tasks, 1) require.Len(t, tasks, 1) - taskEqual(t, tasks[0], regionIDs[0], "a", "c") + taskEqual(t, tasks[0], regionIDs[0], 0, "a", "c") require.True(t, tasks[0].paging) - require.Equal(t, tasks[0].pagingSize, minPagingSize) + require.Equal(t, tasks[0].pagingSize, paging.MinPagingSize) } func toCopRange(r kv.KeyRange) *coprocessor.KeyRange { diff --git a/store/copr/main_test.go b/store/copr/main_test.go index 411741f5e651e..934a55c6354fd 100644 --- a/store/copr/main_test.go +++ b/store/copr/main_test.go @@ -34,6 +34,12 @@ func (m *main) Run() int { } func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(&main{m: m}) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/pingcap/goleveldb/leveldb.(*DB).mpoolDrain"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(&main{m: m}, opts...) } diff --git a/store/copr/mpp.go b/store/copr/mpp.go index f8970f57cccc4..f385fedacc5b3 100644 --- a/store/copr/mpp.go +++ b/store/copr/mpp.go @@ -27,9 +27,9 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/coprocessor" "github.com/pingcap/kvproto/pkg/kvrpcpb" - "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/kvproto/pkg/mpp" "github.com/pingcap/log" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/store/driver/backoff" derr "github.com/pingcap/tidb/store/driver/error" @@ -64,11 +64,24 @@ func (c *MPPClient) selectAllTiFlashStore() []kv.MPPTaskMeta { func (c *MPPClient) ConstructMPPTasks(ctx context.Context, req *kv.MPPBuildTasksRequest, mppStoreLastFailTime map[string]time.Time, ttl time.Duration) ([]kv.MPPTaskMeta, error) { ctx = context.WithValue(ctx, tikv.TxnStartKey(), req.StartTS) bo := backoff.NewBackofferWithVars(ctx, copBuildTaskMaxBackoff, nil) - if req.KeyRanges == nil { - return c.selectAllTiFlashStore(), nil + var tasks []*batchCopTask + var err error + if req.PartitionIDAndRanges != nil { + rangesForEachPartition := make([]*KeyRanges, len(req.PartitionIDAndRanges)) + partitionIDs := make([]int64, len(req.PartitionIDAndRanges)) + for i, p := range req.PartitionIDAndRanges { + rangesForEachPartition[i] = NewKeyRanges(p.KeyRanges) + partitionIDs[i] = p.ID + } + tasks, err = buildBatchCopTasksForPartitionedTable(bo, c.store, rangesForEachPartition, kv.TiFlash, mppStoreLastFailTime, ttl, true, 20, partitionIDs) + } else { + if req.KeyRanges == nil { + return c.selectAllTiFlashStore(), nil + } + ranges := NewKeyRanges(req.KeyRanges) + tasks, err = buildBatchCopTasksForNonPartitionedTable(bo, c.store, ranges, kv.TiFlash, mppStoreLastFailTime, ttl, true, 20) } - ranges := NewKeyRanges(req.KeyRanges) - tasks, err := buildBatchCopTasks(bo, c.store, ranges, kv.TiFlash, mppStoreLastFailTime, ttl, true, 20) + if err != nil { return nil, errors.Trace(err) } @@ -144,6 +157,8 @@ type mppIterator struct { needTriggerFallback bool mu sync.Mutex + + enableCollectExecutionInfo bool } func (m *mppIterator) run(ctx context.Context) { @@ -197,14 +212,7 @@ func (m *mppIterator) handleDispatchReq(ctx context.Context, bo *Backoffer, req originalTask, ok := req.Meta.(*batchCopTask) if ok { for _, ri := range originalTask.regionInfos { - regionInfos = append(regionInfos, &coprocessor.RegionInfo{ - RegionId: ri.Region.GetID(), - RegionEpoch: &metapb.RegionEpoch{ - ConfVer: ri.Region.GetConfVer(), - Version: ri.Region.GetVer(), - }, - Ranges: ri.Ranges.ToPBRanges(), - }) + regionInfos = append(regionInfos, ri.toCoprocessorRegionInfo()) } } @@ -219,6 +227,12 @@ func (m *mppIterator) handleDispatchReq(ctx context.Context, bo *Backoffer, req SchemaVer: req.SchemaVar, Regions: regionInfos, } + if originalTask != nil { + mppReq.TableRegions = originalTask.PartitionTableRegions + if mppReq.TableRegions != nil { + mppReq.Regions = nil + } + } wrappedReq := tikvrpc.NewRequest(tikvrpc.CmdMPPTask, mppReq, kvrpcpb.Context{}) wrappedReq.StoreTp = tikvrpc.TiFlash @@ -231,7 +245,7 @@ func (m *mppIterator) handleDispatchReq(ctx context.Context, bo *Backoffer, req // Or else it's the task without region, which always happens in high layer task without table. // In that case if originalTask != nil { - sender := NewRegionBatchRequestSender(m.store.GetRegionCache(), m.store.GetTiKVClient()) + sender := NewRegionBatchRequestSender(m.store.GetRegionCache(), m.store.GetTiKVClient(), m.enableCollectExecutionInfo) rpcResp, retry, _, err = sender.SendReqToAddr(bo, originalTask.ctx, originalTask.regionInfos, wrappedReq, tikv.ReadTimeoutMedium) // No matter what the rpc error is, we won't retry the mpp dispatch tasks. // TODO: If we want to retry, we must redo the plan fragment cutting and task scheduling. @@ -488,18 +502,19 @@ func (m *mppIterator) Next(ctx context.Context) (kv.ResultSubset, error) { } // DispatchMPPTasks dispatches all the mpp task and waits for the responses. -func (c *MPPClient) DispatchMPPTasks(ctx context.Context, variables interface{}, dispatchReqs []*kv.MPPDispatchRequest, needTriggerFallback bool) kv.Response { +func (c *MPPClient) DispatchMPPTasks(ctx context.Context, variables interface{}, dispatchReqs []*kv.MPPDispatchRequest, needTriggerFallback bool, startTs uint64) kv.Response { vars := variables.(*tikv.Variables) ctxChild, cancelFunc := context.WithCancel(ctx) iter := &mppIterator{ - store: c.store, - tasks: dispatchReqs, - finishCh: make(chan struct{}), - cancelFunc: cancelFunc, - respChan: make(chan *mppResponse, 4096), - startTs: dispatchReqs[0].StartTs, - vars: vars, - needTriggerFallback: needTriggerFallback, + store: c.store, + tasks: dispatchReqs, + finishCh: make(chan struct{}), + cancelFunc: cancelFunc, + respChan: make(chan *mppResponse, 4096), + startTs: startTs, + vars: vars, + needTriggerFallback: needTriggerFallback, + enableCollectExecutionInfo: config.GetGlobalConfig().EnableCollectExecutionInfo, } go iter.run(ctxChild) return iter diff --git a/store/copr/region_cache.go b/store/copr/region_cache.go index 4904f934db6c1..e4454d575220b 100644 --- a/store/copr/region_cache.go +++ b/store/copr/region_cache.go @@ -63,6 +63,75 @@ type LocationKeyRanges struct { Ranges *KeyRanges } +func (l *LocationKeyRanges) getBucketVersion() uint64 { + return l.Location.GetBucketVersion() +} + +// splitKeyRangeByBuckets splits ranges in the same location by buckets and returns a LocationKeyRanges array. +func (l *LocationKeyRanges) splitKeyRangesByBuckets() []*LocationKeyRanges { + if l.Location.Buckets == nil || len(l.Location.Buckets.Keys) == 0 { + return []*LocationKeyRanges{l} + } + + ranges := l.Ranges + loc := l.Location + res := []*LocationKeyRanges{} + for ranges.Len() > 0 { + bucket := loc.LocateBucket(ranges.At(0).StartKey) + if bucket == nil { + // TODO(youjiali1995): if it's overlapped with some buckets, it can be splitted. + // + // Buckets information may not be up-to-date and accurate. + // Find all ranges that can't be located in a bucket and make it one task. + i := 1 + for ; i < ranges.Len(); i++ { + if loc.LocateBucket(ranges.At(i).StartKey) != nil { + break + } + } + res = append(res, &LocationKeyRanges{l.Location, ranges.Slice(0, i)}) + ranges = ranges.Slice(i, ranges.Len()) + } else { + // Iterate to the first range that is not complete in the bucket. + var r kv.KeyRange + var i int + for ; i < ranges.Len(); i++ { + r = ranges.At(i) + if !(bucket.Contains(r.EndKey) || bytes.Equal(bucket.EndKey, r.EndKey)) { + break + } + } + // All rest ranges belong to the same bucket. + if i == ranges.Len() { + res = append(res, &LocationKeyRanges{l.Location, ranges}) + break + } + + if bucket.Contains(r.StartKey) { + // Part of r is not in the bucket. We need to split it. + taskRanges := ranges.Slice(0, i) + taskRanges.last = &kv.KeyRange{ + StartKey: r.StartKey, + EndKey: bucket.EndKey, + } + res = append(res, &LocationKeyRanges{l.Location, taskRanges}) + + ranges = ranges.Slice(i+1, ranges.Len()) + ranges.first = &kv.KeyRange{ + StartKey: bucket.EndKey, + EndKey: r.EndKey, + } + } else { + // ranges[i] is not in the bucket. + taskRanges := ranges.Slice(0, i) + res = append(res, &LocationKeyRanges{l.Location, taskRanges}) + ranges = ranges.Slice(i, ranges.Len()) + } + } + } + return res +} + // SplitKeyRangesByLocations splits the KeyRanges by logical info in the cache. func (c *RegionCache) SplitKeyRangesByLocations(bo *Backoffer, ranges *KeyRanges) ([]*LocationKeyRanges, error) { res := make([]*LocationKeyRanges, 0) @@ -73,9 +142,10 @@ func (c *RegionCache) SplitKeyRangesByLocations(bo *Backoffer, ranges *KeyRanges } // Iterate to the first range that is not complete in the region. + var r kv.KeyRange var i int for ; i < ranges.Len(); i++ { - r := ranges.At(i) + r = ranges.At(i) if !(loc.Contains(r.EndKey) || bytes.Equal(loc.EndKey, r.EndKey)) { break } @@ -86,7 +156,6 @@ func (c *RegionCache) SplitKeyRangesByLocations(bo *Backoffer, ranges *KeyRanges break } - r := ranges.At(i) if loc.Contains(r.StartKey) { // Part of r is not in the region. We need to split it. taskRanges := ranges.Slice(0, i) @@ -112,6 +181,22 @@ func (c *RegionCache) SplitKeyRangesByLocations(bo *Backoffer, ranges *KeyRanges return res, nil } +// SplitKeyRangesByBuckets splits the KeyRanges by buckets information in the cache. If regions don't have buckets, +// it's equal to SplitKeyRangesByLocations. +// +// TODO(youjiali1995): Try to do it in one round and reduce allocations if bucket is not enabled. +func (c *RegionCache) SplitKeyRangesByBuckets(bo *Backoffer, ranges *KeyRanges) ([]*LocationKeyRanges, error) { + locs, err := c.SplitKeyRangesByLocations(bo, ranges) + if err != nil { + return nil, derr.ToTiDBErr(err) + } + res := make([]*LocationKeyRanges, 0, len(locs)) + for _, loc := range locs { + res = append(res, loc.splitKeyRangesByBuckets()...) + } + return res, nil +} + // OnSendFailForBatchRegions handles send request fail logic. func (c *RegionCache) OnSendFailForBatchRegions(bo *Backoffer, store *tikv.Store, regionInfos []RegionInfo, scheduleReload bool, err error) { metrics.RegionCacheCounterWithSendFail.Add(float64(len(regionInfos))) diff --git a/store/copr/store.go b/store/copr/store.go index 1783ee294f8e1..ad7ebb5dd9a63 100644 --- a/store/copr/store.go +++ b/store/copr/store.go @@ -59,6 +59,11 @@ func (c *tikvClient) Close() error { return derr.ToTiDBErr(err) } +func (c *tikvClient) CloseAddr(addr string) error { + err := c.c.CloseAddr(addr) + return derr.ToTiDBErr(err) +} + // SendRequest sends Request. func (c *tikvClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { res, err := c.c.SendRequest(ctx, addr, req, timeout) diff --git a/store/driver/config_serial_test.go b/store/driver/config_test.go similarity index 100% rename from store/driver/config_serial_test.go rename to store/driver/config_test.go diff --git a/store/driver/error/error.go b/store/driver/error/error.go index 8260acd2640bb..6b7b444239d9c 100644 --- a/store/driver/error/error.go +++ b/store/driver/error/error.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package error +package error //nolint:predeclared import ( stderrs "errors" diff --git a/store/driver/error/error_test.go b/store/driver/error/error_test.go index 3db2830179502..9af54d70dfa96 100644 --- a/store/driver/error/error_test.go +++ b/store/driver/error/error_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package error +package error //nolint:predeclared import ( "testing" @@ -26,8 +26,13 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } func TestConvertError(t *testing.T) { diff --git a/store/driver/main_test.go b/store/driver/main_test.go index 1902174a16bf7..6927510cbc898 100644 --- a/store/driver/main_test.go +++ b/store/driver/main_test.go @@ -37,10 +37,11 @@ var ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() tikv.EnableFailpoints() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/store/driver/snap_interceptor_serial_test.go b/store/driver/snap_interceptor_test.go similarity index 100% rename from store/driver/snap_interceptor_serial_test.go rename to store/driver/snap_interceptor_test.go diff --git a/store/driver/sql_fail_serial_test.go b/store/driver/sql_fail_serial_test.go deleted file mode 100644 index 5678ab42e2756..0000000000000 --- a/store/driver/sql_fail_serial_test.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2017 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package driver - -import ( - "context" - "fmt" - "sync" - "testing" - "time" - - "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/util/mock" - "github.com/stretchr/testify/require" - "github.com/tikv/client-go/v2/tikv" -) - -func TestFailBusyServerCop(t *testing.T) { - store, _, clean := createTestStore(t) - defer clean() - - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - - var wg sync.WaitGroup - wg.Add(2) - - require.NoError(t, failpoint.Enable("tikvclient/rpcServerBusy", `return(true)`)) - go func() { - defer wg.Done() - time.Sleep(time.Millisecond * 100) - require.NoError(t, failpoint.Disable("tikvclient/rpcServerBusy")) - }() - - go func() { - defer wg.Done() - rs, err := se.Execute(context.Background(), `SELECT variable_value FROM mysql.tidb WHERE variable_name="bootstrapped"`) - if len(rs) > 0 { - defer func() { - require.NoError(t, rs[0].Close()) - }() - } - require.NoError(t, err) - req := rs[0].NewChunk(nil) - err = rs[0].Next(context.Background(), req) - require.NoError(t, err) - require.NotEqual(t, 0, req.NumRows()) - require.Equal(t, "True", req.GetRow(0).GetString(0)) - }() - - wg.Wait() -} - -func TestCoprocessorStreamRecvTimeout(t *testing.T) { - store, _, clean := createTestStore(t) - defer clean() - - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("create table cop_stream_timeout (id int)") - for i := 0; i < 200; i++ { - tk.MustExec(fmt.Sprintf("insert into cop_stream_timeout values (%d)", i)) - } - tk.Session().GetSessionVars().EnableStreaming = true - - tests := []struct { - name string - timeout time.Duration - }{ - {"timeout", tikv.ReadTimeoutMedium + 100*time.Second}, - {"no timeout", time.Millisecond}, - } - - for _, test := range tests { - timeout := test.timeout - t.Run(test.name, func(t *testing.T) { - enable := true - visited := make(chan int, 1) - isTimeout := false - ctx := context.WithValue(context.Background(), mock.HookKeyForTest("mockTiKVStreamRecvHook"), func(ctx context.Context) { - if !enable { - return - } - visited <- 1 - - select { - case <-ctx.Done(): - case <-time.After(timeout): - isTimeout = true - } - enable = false - }) - - res, err := tk.Session().Execute(ctx, "select * from cop_stream_timeout") - require.NoError(t, err) - - req := res[0].NewChunk(nil) - for i := 0; ; i++ { - err := res[0].Next(ctx, req) - require.NoError(t, err) - if req.NumRows() == 0 { - break - } - req.Reset() - } - select { - case <-visited: - // run with mock tikv - require.False(t, isTimeout) - default: - // run with real tikv - } - }) - } -} diff --git a/store/driver/sql_fail_test.go b/store/driver/sql_fail_test.go new file mode 100644 index 0000000000000..35111d6096e2d --- /dev/null +++ b/store/driver/sql_fail_test.go @@ -0,0 +1,58 @@ +// Copyright 2017 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package driver + +import ( + "context" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/util" + "github.com/stretchr/testify/require" +) + +func TestFailBusyServerCop(t *testing.T) { + store, _, clean := createTestStore(t) + defer clean() + + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + + var wg util.WaitGroupWrapper + + require.NoError(t, failpoint.Enable("tikvclient/rpcServerBusy", `return(true)`)) + wg.Run(func() { + time.Sleep(time.Millisecond * 100) + require.NoError(t, failpoint.Disable("tikvclient/rpcServerBusy")) + }) + + wg.Run(func() { + rs, err := se.Execute(context.Background(), `SELECT variable_value FROM mysql.tidb WHERE variable_name="bootstrapped"`) + if len(rs) > 0 { + defer func() { + require.NoError(t, rs[0].Close()) + }() + } + require.NoError(t, err) + req := rs[0].NewChunk(nil) + err = rs[0].Next(context.Background(), req) + require.NoError(t, err) + require.NotEqual(t, 0, req.NumRows()) + require.Equal(t, "True", req.GetRow(0).GetString(0)) + }) + wg.Wait() +} diff --git a/store/driver/txn/error.go b/store/driver/txn/error.go index 6e98708b046d2..3c2d8377b580b 100644 --- a/store/driver/txn/error.go +++ b/store/driver/txn/error.go @@ -19,6 +19,7 @@ import ( "context" "encoding/json" "fmt" + "strconv" "strings" "time" @@ -53,7 +54,7 @@ func extractKeyExistsErrFromHandle(key kv.Key, value []byte, tblInfo *model.Tabl if handle.IsInt() { if pkInfo := tblInfo.GetPkColInfo(); pkInfo != nil { if mysql.HasUnsignedFlag(pkInfo.Flag) { - handleStr := fmt.Sprintf("%d", uint64(handle.IntValue())) + handleStr := strconv.FormatUint(uint64(handle.IntValue()), 10) return genKeyExistsError(name, handleStr, nil) } } diff --git a/store/driver/txn/main_test.go b/store/driver/txn/main_test.go index 3805c435df0e3..8d93e31420d40 100644 --- a/store/driver/txn/main_test.go +++ b/store/driver/txn/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/driver/txn/snapshot.go b/store/driver/txn/snapshot.go index 3c372bae83725..7ecfae6a57e81 100644 --- a/store/driver/txn/snapshot.go +++ b/store/driver/txn/snapshot.go @@ -23,6 +23,7 @@ import ( derr "github.com/pingcap/tidb/store/driver/error" "github.com/pingcap/tidb/store/driver/options" "github.com/tikv/client-go/v2/tikvrpc" + "github.com/tikv/client-go/v2/tikvrpc/interceptor" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" "github.com/tikv/client-go/v2/txnkv/txnutil" ) @@ -120,6 +121,8 @@ func (s *tikvSnapshot) SetOption(opt int, val interface{}) { s.KVSnapshot.SetReadReplicaScope(val.(string)) case kv.SnapInterceptor: s.interceptor = val.(kv.SnapshotInterceptor) + case kv.RPCInterceptor: + s.KVSnapshot.SetRPCInterceptor(val.(interceptor.RPCInterceptor)) } } @@ -134,6 +137,8 @@ func getTiKVIsolationLevel(level kv.IsoLevel) txnsnapshot.IsoLevel { return txnsnapshot.SI case kv.RC: return txnsnapshot.RC + case kv.RCCheckTS: + return txnsnapshot.RCCheckTS default: return txnsnapshot.SI } diff --git a/store/driver/txn/txn_driver.go b/store/driver/txn/txn_driver.go index 717bf3b154761..196db69f6e419 100644 --- a/store/driver/txn/txn_driver.go +++ b/store/driver/txn/txn_driver.go @@ -28,11 +28,14 @@ import ( derr "github.com/pingcap/tidb/store/driver/error" "github.com/pingcap/tidb/store/driver/options" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/util/logutil" tikverr "github.com/tikv/client-go/v2/error" tikvstore "github.com/tikv/client-go/v2/kv" "github.com/tikv/client-go/v2/tikv" "github.com/tikv/client-go/v2/tikvrpc" + "github.com/tikv/client-go/v2/tikvrpc/interceptor" "github.com/tikv/client-go/v2/txnkv/txnsnapshot" + "go.uber.org/zap" ) type tikvTxn struct { @@ -185,8 +188,6 @@ func (txn *tikvTxn) SetOption(opt int, val interface{}) { txn.KVTxn.SetPriority(getTiKVPriority(val.(int))) case kv.NotFillCache: txn.KVTxn.GetSnapshot().SetNotFillCache(val.(bool)) - case kv.SyncLog: - txn.EnableForceSyncLog() case kv.Pessimistic: txn.SetPessimistic(val.(bool)) case kv.SnapshotTS: @@ -232,6 +233,10 @@ func (txn *tikvTxn) SetOption(opt int, val interface{}) { txn.snapshotInterceptor = val.(kv.SnapshotInterceptor) case kv.CommitTSUpperBoundCheck: txn.KVTxn.SetCommitTSUpperBoundCheck(val.(func(commitTS uint64) bool)) + case kv.RPCInterceptor: + txn.KVTxn.SetRPCInterceptor(val.(interceptor.RPCInterceptor)) + case kv.AssertionLevel: + txn.KVTxn.SetAssertionLevel(val.(kvrpcpb.AssertionLevel)) } } @@ -285,10 +290,32 @@ func (txn *tikvTxn) extractKeyExistsErr(key kv.Key) error { return extractKeyExistsErrFromIndex(key, value, tblInfo, indexID) } +// SetAssertion sets an assertion for the key operation. +func (txn *tikvTxn) SetAssertion(key []byte, assertion ...kv.FlagsOp) error { + f, err := txn.GetUnionStore().GetMemBuffer().GetFlags(key) + if err != nil && !tikverr.IsErrNotFound(err) { + return err + } + if err == nil && f.HasAssertionFlags() { + return nil + } + txn.GetUnionStore().GetMemBuffer().UpdateFlags(key, getTiKVFlagsOps(assertion)...) + return nil +} + // TiDBKVFilter is the filter specific to TiDB to filter out KV pairs that needn't be committed. type TiDBKVFilter struct{} // IsUnnecessaryKeyValue defines which kinds of KV pairs from TiDB needn't be committed. -func (f TiDBKVFilter) IsUnnecessaryKeyValue(key, value []byte, flags tikvstore.KeyFlags) bool { - return tablecodec.IsUntouchedIndexKValue(key, value) +func (f TiDBKVFilter) IsUnnecessaryKeyValue(key, value []byte, flags tikvstore.KeyFlags) (bool, error) { + isUntouchedValue := tablecodec.IsUntouchedIndexKValue(key, value) + if isUntouchedValue && flags.HasPresumeKeyNotExists() { + logutil.BgLogger().Error("unexpected path the untouched key value with PresumeKeyNotExists flag", + zap.Stringer("key", kv.Key(key)), zap.Stringer("value", kv.Key(value)), + zap.Uint16("flags", uint16(flags)), zap.Stack("stack")) + return false, errors.Errorf( + "unexpected path the untouched key=%s value=%s contains PresumeKeyNotExists flag keyFlags=%v", + kv.Key(key).String(), kv.Key(value).String(), flags) + } + return isUntouchedValue, nil } diff --git a/store/driver/txn/unionstore_driver.go b/store/driver/txn/unionstore_driver.go index fc7b97dc74c07..6b2dcc283213e 100644 --- a/store/driver/txn/unionstore_driver.go +++ b/store/driver/txn/unionstore_driver.go @@ -146,6 +146,14 @@ func getTiDBKeyFlags(flag tikvstore.KeyFlags) kv.KeyFlags { if flag.HasNeedLocked() { v = kv.ApplyFlagsOps(v, kv.SetNeedLocked) } + + if flag.HasAssertExist() { + v = kv.ApplyFlagsOps(v, kv.SetAssertExist) + } else if flag.HasAssertNotExist() { + v = kv.ApplyFlagsOps(v, kv.SetAssertNotExist) + } else if flag.HasAssertUnknown() { + v = kv.ApplyFlagsOps(v, kv.SetAssertUnknown) + } return v } @@ -155,6 +163,14 @@ func getTiKVFlagsOp(op kv.FlagsOp) tikvstore.FlagsOp { return tikvstore.SetPresumeKeyNotExists case kv.SetNeedLocked: return tikvstore.SetNeedLocked + case kv.SetAssertExist: + return tikvstore.SetAssertExist + case kv.SetAssertNotExist: + return tikvstore.SetAssertNotExist + case kv.SetAssertUnknown: + return tikvstore.SetAssertUnknown + case kv.SetAssertNone: + return tikvstore.SetAssertNone } return 0 } diff --git a/store/driver/txn_serial_test.go b/store/driver/txn_test.go similarity index 100% rename from store/driver/txn_serial_test.go rename to store/driver/txn_test.go diff --git a/store/gcworker/gc_worker.go b/store/gcworker/gc_worker.go index 854408f082528..8e93d1cf37bd0 100644 --- a/store/gcworker/gc_worker.go +++ b/store/gcworker/gc_worker.go @@ -698,6 +698,9 @@ func (w *GCWorker) deleteRanges(ctx context.Context, safePoint uint64, concurren return errors.Trace(err) } + // Cache table ids on which placement rules have been GC-ed, to avoid redundantly GC the same table id multiple times. + gcPlacementRuleCache := make(map[int64]interface{}, len(ranges)) + logutil.Logger(ctx).Info("[gc worker] start delete ranges", zap.String("uuid", w.uuid), zap.Int("ranges", len(ranges))) @@ -730,7 +733,7 @@ func (w *GCWorker) deleteRanges(ctx context.Context, safePoint uint64, concurren metrics.GCUnsafeDestroyRangeFailuresCounterVec.WithLabelValues("save").Inc() } - if err := w.doGCPlacementRules(r); err != nil { + if err := w.doGCPlacementRules(safePoint, r, gcPlacementRuleCache); err != nil { logutil.Logger(ctx).Error("[gc worker] gc placement rules failed on range", zap.String("uuid", w.uuid), zap.Int64("jobID", r.JobID), @@ -1862,7 +1865,7 @@ func (w *GCWorker) saveValueToSysTable(key, value string) error { // GC placement rules when the partitions are removed by the GC worker. // Placement rules cannot be removed immediately after drop table / truncate table, // because the tables can be flashed back or recovered. -func (w *GCWorker) doGCPlacementRules(dr util.DelRangeTask) (err error) { +func (w *GCWorker) doGCPlacementRules(safePoint uint64, dr util.DelRangeTask, gcPlacementRuleCache map[int64]interface{}) (err error) { // Get the job from the job history var historyJob *model.Job failpoint.Inject("mockHistoryJobForGC", func(v failpoint.Value) { @@ -1873,6 +1876,7 @@ func (w *GCWorker) doGCPlacementRules(dr util.DelRangeTask) (err error) { historyJob = &model.Job{ ID: dr.JobID, Type: model.ActionDropTable, + TableID: int64(v.(int)), RawArgs: args, } }) @@ -1914,6 +1918,26 @@ func (w *GCWorker) doGCPlacementRules(dr util.DelRangeTask) (err error) { for _, id := range physicalTableIDs { bundles = append(bundles, placement.NewBundle(id)) } + + for _, id := range physicalTableIDs { + // Skip table ids that's already successfully deleted. + if _, ok := gcPlacementRuleCache[id]; ok { + continue + } + // Delete pd rule + failpoint.Inject("gcDeletePlacementRuleCounter", func() {}) + logutil.BgLogger().Info("try delete TiFlash pd rule", + zap.Int64("tableID", id), zap.String("endKey", string(dr.EndKey)), zap.Uint64("safePoint", safePoint)) + ruleID := fmt.Sprintf("table-%v-r", id) + if err := infosync.DeleteTiFlashPlacementRule(context.Background(), "tiflash", ruleID); err != nil { + // If DeletePlacementRule fails here, the rule will be deleted in `HandlePlacementRuleRoutine`. + logutil.BgLogger().Error("delete TiFlash pd rule failed when gc", + zap.Error(err), zap.String("ruleID", ruleID), zap.Uint64("safePoint", safePoint)) + } else { + // Cache the table id if its related rule are deleted successfully. + gcPlacementRuleCache[id] = struct{}{} + } + } return infosync.PutRuleBundlesWithDefaultRetry(context.TODO(), bundles) } diff --git a/store/gcworker/gc_worker_serial_test.go b/store/gcworker/gc_worker_test.go similarity index 98% rename from store/gcworker/gc_worker_serial_test.go rename to store/gcworker/gc_worker_test.go index 4a50768ff0301..d757edb09b9b4 100644 --- a/store/gcworker/gc_worker_serial_test.go +++ b/store/gcworker/gc_worker_test.go @@ -1655,6 +1655,16 @@ func TestGCPlacementRules(t *testing.T) { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/mockHistoryJobForGC")) }() + gcPlacementRuleCache := make(map[int64]interface{}) + deletePlacementRuleCounter := 0 + require.NoError(t, failpoint.EnableWith("github.com/pingcap/tidb/store/gcworker/gcDeletePlacementRuleCounter", "return", func() error { + deletePlacementRuleCounter++ + return nil + })) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/gcworker/gcDeletePlacementRuleCounter")) + }() + bundleID := "TiDB_DDL_10" bundle, err := placement.NewBundleFromOptions(&model.PlacementSettings{ PrimaryRegion: "r1", @@ -1672,14 +1682,22 @@ func TestGCPlacementRules(t *testing.T) { // do gc dr := util.DelRangeTask{JobID: 1, ElementID: 10} - err = s.gcWorker.doGCPlacementRules(dr) + err = s.gcWorker.doGCPlacementRules(1, dr, gcPlacementRuleCache) require.NoError(t, err) + require.Equal(t, map[int64]interface{}{10: struct{}{}}, gcPlacementRuleCache) + require.Equal(t, 1, deletePlacementRuleCounter) // check bundle deleted after gc got, err = infosync.GetRuleBundle(context.Background(), bundleID) require.NoError(t, err) require.NotNil(t, got) require.True(t, got.IsEmpty()) + + // gc the same table id repeatedly + err = s.gcWorker.doGCPlacementRules(1, dr, gcPlacementRuleCache) + require.NoError(t, err) + require.Equal(t, map[int64]interface{}{10: struct{}{}}, gcPlacementRuleCache) + require.Equal(t, 1, deletePlacementRuleCounter) } func TestGCLabelRules(t *testing.T) { diff --git a/store/gcworker/main_test.go b/store/gcworker/main_test.go index 0a6be0a87548b..f6532f7b0a855 100644 --- a/store/gcworker/main_test.go +++ b/store/gcworker/main_test.go @@ -25,11 +25,12 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() tikv.EnableFailpoints() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), } callback := func(i int) int { // wait for MVCCLevelDB to close, MVCCLevelDB will be closed in one second diff --git a/store/helper/helper.go b/store/helper/helper.go index 00706047eb145..95c1c302394da 100644 --- a/store/helper/helper.go +++ b/store/helper/helper.go @@ -547,6 +547,32 @@ type RegionsInfo struct { Regions []RegionInfo `json:"regions"` } +// NewRegionsInfo returns RegionsInfo +func NewRegionsInfo() *RegionsInfo { + return &RegionsInfo{ + Regions: make([]RegionInfo, 0), + } +} + +// Merge merged 2 regionsInfo into one +func (r *RegionsInfo) Merge(other *RegionsInfo) *RegionsInfo { + newRegionsInfo := &RegionsInfo{ + Regions: make([]RegionInfo, 0, r.Count+other.Count), + } + m := make(map[int64]RegionInfo, r.Count+other.Count) + for _, region := range r.Regions { + m[region.ID] = region + } + for _, region := range other.Regions { + m[region.ID] = region + } + for _, region := range m { + newRegionsInfo.Regions = append(newRegionsInfo.Regions, region) + } + newRegionsInfo.Count = int64(len(newRegionsInfo.Regions)) + return newRegionsInfo +} + // ReplicationStatus represents the replication mode status of the region. type ReplicationStatus struct { State string `json:"state"` @@ -603,18 +629,18 @@ func (xs byRegionStartKey) Less(i, j int) bool { return xs[i].getStartKey() < xs[j].getStartKey() } -// tableInfoWithKeyRange stores table or index informations with its key range. -type tableInfoWithKeyRange struct { +// TableInfoWithKeyRange stores table or index informations with its key range. +type TableInfoWithKeyRange struct { *TableInfo StartKey string EndKey string } -func (t tableInfoWithKeyRange) getStartKey() string { return t.StartKey } -func (t tableInfoWithKeyRange) getEndKey() string { return t.EndKey } +func (t TableInfoWithKeyRange) getStartKey() string { return t.StartKey } +func (t TableInfoWithKeyRange) getEndKey() string { return t.EndKey } // for sorting -type byTableStartKey []tableInfoWithKeyRange +type byTableStartKey []TableInfoWithKeyRange func (xs byTableStartKey) Len() int { return len(xs) } func (xs byTableStartKey) Swap(i, j int) { xs[i], xs[j] = xs[j], xs[i] } @@ -622,11 +648,16 @@ func (xs byTableStartKey) Less(i, j int) bool { return xs[i].getStartKey() < xs[j].getStartKey() } -func newTableWithKeyRange(db *model.DBInfo, table *model.TableInfo) tableInfoWithKeyRange { +// NewTableWithKeyRange constructs TableInfoWithKeyRange for given table, it is exported only for test. +func NewTableWithKeyRange(db *model.DBInfo, table *model.TableInfo) TableInfoWithKeyRange { + return newTableWithKeyRange(db, table) +} + +func newTableWithKeyRange(db *model.DBInfo, table *model.TableInfo) TableInfoWithKeyRange { sk, ek := tablecodec.GetTableHandleKeyRange(table.ID) startKey := bytesKeyToHex(codec.EncodeBytes(nil, sk)) endKey := bytesKeyToHex(codec.EncodeBytes(nil, ek)) - return tableInfoWithKeyRange{ + return TableInfoWithKeyRange{ &TableInfo{ DB: db, Table: table, @@ -638,11 +669,16 @@ func newTableWithKeyRange(db *model.DBInfo, table *model.TableInfo) tableInfoWit } } -func newIndexWithKeyRange(db *model.DBInfo, table *model.TableInfo, index *model.IndexInfo) tableInfoWithKeyRange { +// NewIndexWithKeyRange constructs TableInfoWithKeyRange for given index, it is exported only for test. +func NewIndexWithKeyRange(db *model.DBInfo, table *model.TableInfo, index *model.IndexInfo) TableInfoWithKeyRange { + return newIndexWithKeyRange(db, table, index) +} + +func newIndexWithKeyRange(db *model.DBInfo, table *model.TableInfo, index *model.IndexInfo) TableInfoWithKeyRange { sk, ek := tablecodec.GetTableIndexKeyRange(table.ID, index.ID) startKey := bytesKeyToHex(codec.EncodeBytes(nil, sk)) endKey := bytesKeyToHex(codec.EncodeBytes(nil, ek)) - return tableInfoWithKeyRange{ + return TableInfoWithKeyRange{ &TableInfo{ DB: db, Table: table, @@ -654,11 +690,11 @@ func newIndexWithKeyRange(db *model.DBInfo, table *model.TableInfo, index *model } } -func newPartitionTableWithKeyRange(db *model.DBInfo, table *model.TableInfo, partitionID int64) tableInfoWithKeyRange { +func newPartitionTableWithKeyRange(db *model.DBInfo, table *model.TableInfo, partitionID int64) TableInfoWithKeyRange { sk, ek := tablecodec.GetTableHandleKeyRange(partitionID) startKey := bytesKeyToHex(codec.EncodeBytes(nil, sk)) endKey := bytesKeyToHex(codec.EncodeBytes(nil, ek)) - return tableInfoWithKeyRange{ + return TableInfoWithKeyRange{ &TableInfo{ DB: db, Table: table, @@ -670,19 +706,35 @@ func newPartitionTableWithKeyRange(db *model.DBInfo, table *model.TableInfo, par } } +// FilterMemDBs filters memory databases in the input schemas. +func (h *Helper) FilterMemDBs(oldSchemas []*model.DBInfo) (schemas []*model.DBInfo) { + for _, dbInfo := range oldSchemas { + if util.IsMemDB(dbInfo.Name.L) { + continue + } + schemas = append(schemas, dbInfo) + } + return +} + // GetRegionsTableInfo returns a map maps region id to its tables or indices. // Assuming tables or indices key ranges never intersect. // Regions key ranges can intersect. func (h *Helper) GetRegionsTableInfo(regionsInfo *RegionsInfo, schemas []*model.DBInfo) map[int64][]TableInfo { - tableInfos := make(map[int64][]TableInfo, len(regionsInfo.Regions)) + tables := h.GetTablesInfoWithKeyRange(schemas) regions := make([]*RegionInfo, 0, len(regionsInfo.Regions)) for i := 0; i < len(regionsInfo.Regions); i++ { - tableInfos[regionsInfo.Regions[i].ID] = []TableInfo{} regions = append(regions, ®ionsInfo.Regions[i]) } - tables := []tableInfoWithKeyRange{} + tableInfos := h.ParseRegionsTableInfos(regions, tables) + return tableInfos +} + +// GetTablesInfoWithKeyRange returns a slice containing tableInfos with key ranges of all tables in schemas. +func (h *Helper) GetTablesInfoWithKeyRange(schemas []*model.DBInfo) []TableInfoWithKeyRange { + tables := []TableInfoWithKeyRange{} for _, db := range schemas { for _, table := range db.Tables { if table.Partition != nil { @@ -697,18 +749,25 @@ func (h *Helper) GetRegionsTableInfo(regionsInfo *RegionsInfo, schemas []*model. } } } + sort.Sort(byTableStartKey(tables)) + return tables +} + +// ParseRegionsTableInfos parses the tables or indices in regions according to key range. +func (h *Helper) ParseRegionsTableInfos(regionsInfo []*RegionInfo, tables []TableInfoWithKeyRange) map[int64][]TableInfo { + tableInfos := make(map[int64][]TableInfo, len(regionsInfo)) - if len(tables) == 0 || len(regions) == 0 { + if len(tables) == 0 || len(regionsInfo) == 0 { return tableInfos } - - sort.Sort(byRegionStartKey(regions)) - sort.Sort(byTableStartKey(tables)) + // tables is sorted in GetTablesInfoWithKeyRange func + sort.Sort(byRegionStartKey(regionsInfo)) idx := 0 OutLoop: - for _, region := range regions { + for _, region := range regionsInfo { id := region.ID + tableInfos[id] = []TableInfo{} for isBehind(region, &tables[idx]) { idx++ if idx >= len(tables) { @@ -723,6 +782,11 @@ OutLoop: return tableInfos } +// BytesKeyToHex converts bytes key to hex key, it is exported only for test. +func BytesKeyToHex(key []byte) string { + return bytesKeyToHex(key) +} + func bytesKeyToHex(key []byte) string { return strings.ToUpper(hex.EncodeToString(key)) } @@ -734,10 +798,32 @@ func (h *Helper) GetRegionsInfo() (*RegionsInfo, error) { return ®ionsInfo, err } +// GetStoreRegionsInfo gets the region in given store. +func (h *Helper) GetStoreRegionsInfo(storeID uint64) (*RegionsInfo, error) { + var regionsInfo RegionsInfo + err := h.requestPD("GET", pdapi.StoreRegions+"/"+strconv.FormatUint(storeID, 10), nil, ®ionsInfo) + return ®ionsInfo, err +} + // GetRegionInfoByID gets the region information of the region ID by using PD's api. func (h *Helper) GetRegionInfoByID(regionID uint64) (*RegionInfo, error) { var regionInfo RegionInfo - err := h.requestPD("GET", pdapi.RegionByID+strconv.FormatUint(regionID, 10), nil, ®ionInfo) + err := h.requestPD("GET", pdapi.RegionByID+"/"+strconv.FormatUint(regionID, 10), nil, ®ionInfo) + return ®ionInfo, err +} + +// GetRegionsInfoByRange scans region by key range +func (h *Helper) GetRegionsInfoByRange(sk, ek []byte) (*RegionsInfo, error) { + var regionsInfo RegionsInfo + err := h.requestPD("GET", fmt.Sprintf("%v?key=%s&end_key=%s", pdapi.ScanRegions, + url.QueryEscape(string(sk)), url.QueryEscape(string(ek))), nil, ®ionsInfo) + return ®ionsInfo, err +} + +// GetRegionByKey gets regioninfo by key +func (h *Helper) GetRegionByKey(k []byte) (*RegionInfo, error) { + var regionInfo RegionInfo + err := h.requestPD("GET", fmt.Sprintf("%v/%v", pdapi.RegionKey, url.QueryEscape(string(k))), nil, ®ionInfo) return ®ionInfo, err } @@ -873,14 +959,20 @@ type PDRegionStats struct { } // GetPDRegionStats get the RegionStats by tableID. -func (h *Helper) GetPDRegionStats(tableID int64, stats *PDRegionStats) error { +func (h *Helper) GetPDRegionStats(tableID int64, stats *PDRegionStats, noIndexStats bool) error { pdAddrs, err := h.GetPDAddr() if err != nil { return errors.Trace(err) } - startKey := tablecodec.EncodeTablePrefix(tableID) - endKey := tablecodec.EncodeTablePrefix(tableID + 1) + var startKey, endKey []byte + if noIndexStats { + startKey = tablecodec.GenTableRecordPrefix(tableID) + endKey = kv.Key(startKey).PrefixNext() + } else { + startKey = tablecodec.EncodeTablePrefix(tableID) + endKey = kv.Key(startKey).PrefixNext() + } startKey = codec.EncodeBytes([]byte{}, startKey) endKey = codec.EncodeBytes([]byte{}, endKey) @@ -1079,8 +1171,8 @@ func (h *Helper) GetPDRegionRecordStats(tableID int64, stats *PDRegionStats) err // GetTiFlashTableIDFromEndKey computes tableID from pd rule's endKey. func GetTiFlashTableIDFromEndKey(endKey string) int64 { - endKey, _ = url.QueryUnescape(endKey) - _, decodedEndKey, _ := codec.DecodeBytes([]byte(endKey), []byte{}) + e, _ := hex.DecodeString(endKey) + _, decodedEndKey, _ := codec.DecodeBytes(e, []byte{}) tableID := tablecodec.DecodeTableID(decodedEndKey) tableID -= 1 return tableID @@ -1088,24 +1180,43 @@ func GetTiFlashTableIDFromEndKey(endKey string) int64 { // ComputeTiFlashStatus is helper function for CollectTiFlashStatus. func ComputeTiFlashStatus(reader *bufio.Reader, regionReplica *map[int64]int) error { - ns, _, _ := reader.ReadLine() - n, err := strconv.ParseInt(string(ns), 10, 64) + ns, err := reader.ReadString('\n') + if err != nil { + return errors.Trace(err) + } + // The count + ns = strings.Trim(ns, "\r\n\t") + n, err := strconv.ParseInt(ns, 10, 64) if err != nil { return errors.Trace(err) } - for i := int64(0); i < n; i++ { - rs, _, _ := reader.ReadLine() + // The regions + regions, err := reader.ReadString('\n') + if err != nil { + return errors.Trace(err) + } + regions = strings.Trim(regions, "\r\n\t") + splits := strings.Split(regions, " ") + realN := int64(0) + for _, s := range splits { // For (`table`, `store`), has region `r` - r, err := strconv.ParseInt(strings.Trim(string(rs), "\r\n \t"), 10, 32) + if s == "" { + continue + } + realN += 1 + r, err := strconv.ParseInt(s, 10, 32) if err != nil { return errors.Trace(err) } - if i, ok := (*regionReplica)[r]; ok { - (*regionReplica)[r] = i + 1 + if c, ok := (*regionReplica)[r]; ok { + (*regionReplica)[r] = c + 1 } else { (*regionReplica)[r] = 1 } } + if n != realN { + logutil.BgLogger().Warn("ComputeTiFlashStatus count check failed", zap.Int64("claim", n), zap.Int64("real", realN)) + } return nil } diff --git a/store/helper/helper_test.go b/store/helper/helper_test.go index c29873fd81c74..acd9bac0e5290 100644 --- a/store/helper/helper_test.go +++ b/store/helper/helper_test.go @@ -18,6 +18,7 @@ import ( "bufio" "crypto/tls" "encoding/json" + "fmt" "net/http" "net/http/httptest" "strings" @@ -29,6 +30,7 @@ import ( "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/util/pdapi" "github.com/stretchr/testify/require" "github.com/tikv/client-go/v2/testutils" @@ -436,17 +438,48 @@ func mockStoreStatResponse(w http.ResponseWriter, _ *http.Request) { func TestComputeTiFlashStatus(t *testing.T) { regionReplica := make(map[int64]int) // There are no region in this TiFlash store. - resp1 := "0\n\n" - // There are one region 1009 in this TiFlash store. - resp2 := "1\n1009\n" - br1 := bufio.NewReader(strings.NewReader(resp1)) - br2 := bufio.NewReader(strings.NewReader(resp2)) + br1 := bufio.NewReader(strings.NewReader("0\n\n")) + // There are 2 regions 1009/1010 in this TiFlash store. + br2 := bufio.NewReader(strings.NewReader("2\n1009 1010 \n")) err := helper.ComputeTiFlashStatus(br1, ®ionReplica) require.NoError(t, err) err = helper.ComputeTiFlashStatus(br2, ®ionReplica) require.NoError(t, err) - require.Equal(t, len(regionReplica), 1) + require.Equal(t, len(regionReplica), 2) v, ok := regionReplica[1009] require.Equal(t, v, 1) require.Equal(t, ok, true) + v, ok = regionReplica[1010] + require.Equal(t, v, 1) + require.Equal(t, ok, true) + + regionReplica2 := make(map[int64]int) + var sb strings.Builder + for i := 1000; i < 3000; i++ { + sb.WriteString(fmt.Sprintf("%v ", i)) + } + s := fmt.Sprintf("2000\n%v\n", sb.String()) + require.NoError(t, helper.ComputeTiFlashStatus(bufio.NewReader(strings.NewReader(s)), ®ionReplica2)) + require.Equal(t, 2000, len(regionReplica2)) + for i := 1000; i < 3000; i++ { + _, ok := regionReplica2[int64(i)] + require.True(t, ok) + } +} + +// TestTableRange tests the first part of GetPDRegionStats. +func TestTableRange(t *testing.T) { + startKey := tablecodec.GenTableRecordPrefix(1) + endKey := startKey.PrefixNext() + // t+id+_r + require.Equal(t, "7480000000000000015f72", startKey.String()) + // t+id+_s + require.Equal(t, "7480000000000000015f73", endKey.String()) + + startKey = tablecodec.EncodeTablePrefix(1) + endKey = startKey.PrefixNext() + // t+id + require.Equal(t, "748000000000000001", startKey.String()) + // t+(id+1) + require.Equal(t, "748000000000000002", endKey.String()) } diff --git a/store/helper/main_test.go b/store/helper/main_test.go index ade457cc75183..75cdb1d50f8ac 100644 --- a/store/helper/main_test.go +++ b/store/helper/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/main_test.go b/store/main_test.go index 40703aa3d2e51..0579ea229d2a8 100644 --- a/store/main_test.go +++ b/store/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/store/mockstore/main_test.go b/store/mockstore/main_test.go index 0bb01f6c23182..32ba74a6a98d2 100644 --- a/store/mockstore/main_test.go +++ b/store/mockstore/main_test.go @@ -24,11 +24,16 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() callback := func(i int) int { // wait for leveldb to close, leveldb will be closed in one second time.Sleep(time.Second) return i } - goleak.VerifyTestMain(testmain.WrapTestingM(m, callback)) + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(testmain.WrapTestingM(m, callback), opts...) } diff --git a/store/mockstore/mockcopr/cop_handler_dag.go b/store/mockstore/mockcopr/cop_handler_dag.go index 2fd9d8f73d4b3..4c60d346195bb 100644 --- a/store/mockstore/mockcopr/cop_handler_dag.go +++ b/store/mockstore/mockcopr/cop_handler_dag.go @@ -176,7 +176,7 @@ func (h coprHandler) buildExec(ctx *dagContext, curr *tipb.Executor) (executor, childExec = curr.Limit.Child default: // TODO: Support other types. - err = errors.Errorf("this exec type %v doesn't support yet.", curr.GetTp()) + err = errors.Errorf("this exec type %v doesn't support yet", curr.GetTp()) } return currExec, childExec, errors.Trace(err) diff --git a/store/mockstore/mockcopr/main_test.go b/store/mockstore/mockcopr/main_test.go index 3f3036ba87541..1aef4b1027883 100644 --- a/store/mockstore/mockcopr/main_test.go +++ b/store/mockstore/mockcopr/main_test.go @@ -24,9 +24,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } callback := func(i int) int { diff --git a/store/mockstore/redirector.go b/store/mockstore/redirector.go index ba7c7813583b3..e506f16857bbf 100644 --- a/store/mockstore/redirector.go +++ b/store/mockstore/redirector.go @@ -51,6 +51,17 @@ func (c *clientRedirector) Close() error { return err } +func (c *clientRedirector) CloseAddr(addr string) error { + err := c.mockClient.CloseAddr(addr) + if err != nil { + return err + } + if c.rpcClient != nil { + err = c.rpcClient.CloseAddr(addr) + } + return err +} + func (c *clientRedirector) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { if req.StoreTp == tikvrpc.TiDB { c.Once.Do(func() { diff --git a/store/mockstore/unistore/cophandler/closure_exec.go b/store/mockstore/unistore/cophandler/closure_exec.go index efc845820d260..e7bac738bc67f 100644 --- a/store/mockstore/unistore/cophandler/closure_exec.go +++ b/store/mockstore/unistore/cophandler/closure_exec.go @@ -31,6 +31,7 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/store/mockstore/unistore/lockstore" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/mvcc" "github.com/pingcap/tidb/tablecodec" @@ -198,7 +199,8 @@ func convertToExprs(sc *stmtctx.StatementContext, fieldTps []*types.FieldType, p func isScanNode(executor *tipb.Executor) bool { switch executor.Tp { case tipb.ExecType_TypeTableScan, - tipb.ExecType_TypeIndexScan: + tipb.ExecType_TypeIndexScan, + tipb.ExecType_TypePartitionTableScan: return true default: return false @@ -262,6 +264,13 @@ func newClosureExecutor(dagCtx *dagContext, outputOffsets []uint32, scanExec *ti e.idxScanCtx.prevVals = make([][]byte, e.idxScanCtx.columnLen) } e.scanType = IndexScan + case tipb.ExecType_TypePartitionTableScan: + dagCtx.setColumnInfo(scanExec.PartitionTableScan.Columns) + dagCtx.primaryCols = scanExec.PartitionTableScan.PrimaryColumnIds + tblScan := scanExec.PartitionTableScan + e.unique = true + e.scanCtx.desc = tblScan.Desc + e.scanType = TableScan default: panic(fmt.Sprintf("unknown first executor type %s", scanExec.Tp)) } @@ -293,9 +302,18 @@ func (e *closureExecutor) initIdxScanCtx(idxScan *tipb.IndexScan) { e.idxScanCtx.primaryColumnIds = idxScan.PrimaryColumnIds lastColumn := e.columnInfos[len(e.columnInfos)-1] + + // Here it is required that ExtraPhysTblID is last + if lastColumn.GetColumnId() == model.ExtraPhysTblID { + e.idxScanCtx.columnLen-- + lastColumn = e.columnInfos[e.idxScanCtx.columnLen-1] + } + + // Here it is required that ExtraPidColID + // is after all other columns except ExtraPhysTblID if lastColumn.GetColumnId() == model.ExtraPidColID { - lastColumn = e.columnInfos[len(e.columnInfos)-2] e.idxScanCtx.columnLen-- + lastColumn = e.columnInfos[e.idxScanCtx.columnLen-1] } if len(e.idxScanCtx.primaryColumnIds) == 0 { @@ -604,7 +622,7 @@ func (e *closureExecutor) isPointGetRange(ran kv.KeyRange) bool { func (e *closureExecutor) checkRangeLock() error { if !e.ignoreLock && !e.lockChecked { for _, ran := range e.kvRanges { - err := e.checkRangeLockForRange(ran) + err := checkRangeLockForRange(e.lockStore, e.startTS, e.resolvedLocks, ran) if err != nil { return err } @@ -614,14 +632,14 @@ func (e *closureExecutor) checkRangeLock() error { return nil } -func (e *closureExecutor) checkRangeLockForRange(ran kv.KeyRange) error { - it := e.lockStore.NewIterator() +func checkRangeLockForRange(store *lockstore.MemStore, startTS uint64, resolvedLocks []uint64, ran kv.KeyRange) error { + it := store.NewIterator() for it.Seek(ran.StartKey); it.Valid(); it.Next() { if exceedEndKey(it.Key(), ran.EndKey) { break } lock := mvcc.DecodeLock(it.Value()) - err := checkLock(lock, it.Key(), e.startTS, e.resolvedLocks) + err := checkLock(lock, it.Key(), startTS, resolvedLocks) if err != nil { return err } @@ -837,6 +855,12 @@ func (e *closureExecutor) tableScanProcessCore(key, value []byte) error { if err != nil { return errors.Trace(err) } + // Add ExtraPhysTblID if requested + // Assumes it is always last! + if e.columnInfos[len(e.columnInfos)-1].ColumnId == model.ExtraPhysTblID { + tblID := tablecodec.DecodeTableID(key) + e.scanCtx.chk.AppendInt64(len(e.columnInfos)-1, tblID) + } incRow = true return nil } @@ -909,6 +933,12 @@ func (e *closureExecutor) indexScanProcessCore(key, value []byte) error { } } } + // Add ExtraPhysTblID if requested + // Assumes it is always last! + if e.columnInfos[len(e.columnInfos)-1].ColumnId == model.ExtraPhysTblID { + tblID := tablecodec.DecodeTableID(key) + chk.AppendInt64(len(e.columnInfos)-1, tblID) + } gotRow = true return nil } diff --git a/store/mockstore/unistore/cophandler/cop_handler.go b/store/mockstore/unistore/cophandler/cop_handler.go index fa7b784126e3e..6fd25e7cc98f8 100644 --- a/store/mockstore/unistore/cophandler/cop_handler.go +++ b/store/mockstore/unistore/cophandler/cop_handler.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "strings" "time" "github.com/golang/protobuf/proto" @@ -36,6 +37,7 @@ import ( "github.com/pingcap/tidb/store/mockstore/unistore/client" "github.com/pingcap/tidb/store/mockstore/unistore/lockstore" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" @@ -85,7 +87,32 @@ type dagContext struct { startTS uint64 } -// handleCopDAGRequest handles coprocessor DAG request. +// ExecutorListsToTree converts a list of executors to a tree. +func ExecutorListsToTree(exec []*tipb.Executor) *tipb.Executor { + i := len(exec) - 1 + rootExec := exec[i] + for i--; 0 <= i; i-- { + switch exec[i+1].Tp { + case tipb.ExecType_TypeAggregation: + exec[i+1].Aggregation.Child = exec[i] + case tipb.ExecType_TypeProjection: + exec[i+1].Projection.Child = exec[i] + case tipb.ExecType_TypeTopN: + exec[i+1].TopN.Child = exec[i] + case tipb.ExecType_TypeLimit: + exec[i+1].Limit.Child = exec[i] + case tipb.ExecType_TypeSelection: + exec[i+1].Selection.Child = exec[i] + case tipb.ExecType_TypeStreamAgg: + exec[i+1].Aggregation.Child = exec[i] + default: + panic("unsupported dag executor type") + } + } + return rootExec +} + +// handleCopDAGRequest handles coprocessor DAG request using MPP executors. func handleCopDAGRequest(dbReader *dbreader.DBReader, lockStore *lockstore.MemStore, req *coprocessor.Request) (resp *coprocessor.Response) { startTime := time.Now() resp = &coprocessor.Response{} @@ -113,12 +140,88 @@ func handleCopDAGRequest(dbReader *dbreader.DBReader, lockStore *lockstore.MemSt resp.OtherError = err.Error() return resp } - closureExec, err := buildClosureExecutor(dagCtx, dagReq) + + exec, chunks, counts, ndvs, err := buildAndRunMPPExecutor(dagCtx, dagReq) + + if err != nil { + errMsg := err.Error() + if strings.HasPrefix(errMsg, ErrExecutorNotSupportedMsg) { + resp.OtherError = err.Error() + return resp + } + return buildRespWithMPPExec(nil, nil, nil, exec, dagReq, err, dagCtx.sc.GetWarnings(), time.Since(startTime)) + } + return buildRespWithMPPExec(chunks, counts, ndvs, exec, dagReq, err, dagCtx.sc.GetWarnings(), time.Since(startTime)) +} + +func buildAndRunMPPExecutor(dagCtx *dagContext, dagReq *tipb.DAGRequest) (mppExec, []tipb.Chunk, []int64, []int64, error) { + rootExec := dagReq.RootExecutor + if rootExec == nil { + rootExec = ExecutorListsToTree(dagReq.Executors) + } + + var counts, ndvs []int64 + + if dagReq.GetCollectRangeCounts() { + counts = make([]int64, len(dagCtx.keyRanges)) + ndvs = make([]int64, len(dagCtx.keyRanges)) + } + builder := &mppExecBuilder{ + sc: dagCtx.sc, + dbReader: dagCtx.dbReader, + dagReq: dagReq, + dagCtx: dagCtx, + mppCtx: nil, + counts: counts, + ndvs: ndvs, + } + exec, err := builder.buildMPPExecutor(rootExec) + if err != nil { + return nil, nil, nil, nil, err + } + chunks, err := mppExecute(exec, dagCtx, dagReq) + return exec, chunks, counts, ndvs, err +} + +func mppExecute(exec mppExec, dagCtx *dagContext, dagReq *tipb.DAGRequest) (chunks []tipb.Chunk, err error) { + err = exec.open() + defer func() { + err := exec.stop() + if err != nil { + panic(err) + } + }() if err != nil { - return buildResp(nil, nil, nil, dagReq, err, dagCtx.sc.GetWarnings(), time.Since(startTime)) + return + } + var buf []byte + var datums []types.Datum + var chk *chunk.Chunk + fields := exec.getFieldTypes() + for { + chk, err = exec.next() + if err != nil || chk == nil || chk.NumRows() == 0 { + return + } + numRows := chk.NumRows() + for i := 0; i < numRows; i++ { + datums = datums[:0] + if dagReq.OutputOffsets != nil { + for _, j := range dagReq.OutputOffsets { + datums = append(datums, chk.GetRow(i).GetDatum(int(j), fields[j])) + } + } else { + for j, ft := range fields { + datums = append(datums, chk.GetRow(i).GetDatum(j, ft)) + } + } + buf, err = codec.EncodeValue(dagCtx.sc, buf[:0], datums...) + if err != nil { + return nil, errors.Trace(err) + } + chunks = appendRow(chunks, buf, i) + } } - chunks, err := closureExec.execute() - return buildResp(chunks, closureExec, closureExec.ndvs, dagReq, err, dagCtx.sc.GetWarnings(), time.Since(startTime)) } func buildDAG(reader *dbreader.DBReader, lockStore *lockstore.MemStore, req *coprocessor.Request) (*dagContext, *tipb.DAGRequest, error) { @@ -212,6 +315,10 @@ func newRowDecoder(columnInfos []*tipb.ColumnInfo, fieldTps []*types.FieldType, ) for i := range columnInfos { info := columnInfos[i] + if info.ColumnId == model.ExtraPhysTblID { + // Skip since it needs to be filled in from the key + continue + } ft := fieldTps[i] col := rowcodec.ColInfo{ ID: info.ColumnId, @@ -287,12 +394,8 @@ func (e *ErrLocked) Error() string { return fmt.Sprintf("key is locked, key: %q, Type: %v, primary: %q, startTS: %v", e.Key, e.LockType, e.Primary, e.StartTS) } -func buildResp(chunks []tipb.Chunk, closureExecutor *closureExecutor, ndvs []int64, dagReq *tipb.DAGRequest, err error, warnings []stmtctx.SQLWarn, dur time.Duration) *coprocessor.Response { +func buildRespWithMPPExec(chunks []tipb.Chunk, counts, ndvs []int64, exec mppExec, dagReq *tipb.DAGRequest, err error, warnings []stmtctx.SQLWarn, dur time.Duration) *coprocessor.Response { resp := &coprocessor.Response{} - var counts []int64 - if closureExecutor != nil { - counts = closureExecutor.counts - } selResp := &tipb.SelectResponse{ Error: toPBError(err), Chunks: chunks, @@ -301,34 +404,15 @@ func buildResp(chunks []tipb.Chunk, closureExecutor *closureExecutor, ndvs []int } executors := dagReq.Executors if dagReq.CollectExecutionSummaries != nil && *dagReq.CollectExecutionSummaries { + // for simplicity, we assume all executors to be spending the same amount of time as the request + timeProcessed := uint64(dur / time.Nanosecond) execSummary := make([]*tipb.ExecutorExecutionSummary, len(executors)) - for i := range execSummary { - if closureExecutor == nil { - selResp.ExecutionSummaries = execSummary - continue - } - switch executors[i].Tp { - case tipb.ExecType_TypeTableScan: - execSummary[i] = closureExecutor.scanCtx.execDetail.buildSummary() - case tipb.ExecType_TypeIndexScan: - execSummary[i] = closureExecutor.idxScanCtx.execDetail.buildSummary() - case tipb.ExecType_TypeSelection: - execSummary[i] = closureExecutor.selectionCtx.execDetail.buildSummary() - case tipb.ExecType_TypeTopN: - execSummary[i] = closureExecutor.topNCtx.execDetail.buildSummary() - case tipb.ExecType_TypeAggregation, tipb.ExecType_TypeStreamAgg: - execSummary[i] = closureExecutor.aggCtx.execDetail.buildSummary() - case tipb.ExecType_TypeLimit: - costNs := uint64(0) - rows := uint64(closureExecutor.rowCount) - numIter := uint64(1) - execSummary[i] = &tipb.ExecutorExecutionSummary{ - TimeProcessedNs: &costNs, - NumProducedRows: &rows, - NumIterations: &numIter, - } - default: - execSummary[i] = &tipb.ExecutorExecutionSummary{} + e := exec + for i := len(executors) - 1; 0 <= i; i-- { + execSummary[i] = e.buildSummary() + execSummary[i].TimeProcessedNs = &timeProcessed + if i != 0 { + e = exec.child() } } selResp.ExecutionSummaries = execSummary @@ -353,12 +437,17 @@ func buildResp(chunks []tipb.Chunk, closureExecutor *closureExecutor, ndvs []int resp.ExecDetailsV2 = &kvrpcpb.ExecDetailsV2{ TimeDetail: resp.ExecDetails.TimeDetail, } - data, err := proto.Marshal(selResp) - if err != nil { - resp.OtherError = err.Error() + data, mErr := proto.Marshal(selResp) + if mErr != nil { + resp.OtherError = mErr.Error() return resp } resp.Data = data + if err != nil { + if conflictErr, ok := errors.Cause(err).(*kverrors.ErrConflict); ok { + resp.OtherError = conflictErr.Error() + } + } return resp } diff --git a/store/mockstore/unistore/cophandler/cop_handler_test.go b/store/mockstore/unistore/cophandler/cop_handler_test.go index fd4e244344f6f..e29f25a7eeb2e 100644 --- a/store/mockstore/unistore/cophandler/cop_handler_test.go +++ b/store/mockstore/unistore/cophandler/cop_handler_test.go @@ -93,7 +93,7 @@ func makeATestMutaion(op kvrpcpb.Op, key []byte, value []byte) *kvrpcpb.Mutation } } -func prepareTestTableData(t *testing.T, keyNumber int, tableID int64) *data { +func prepareTestTableData(keyNumber int, tableID int64) (*data, error) { stmtCtx := new(stmtctx.StatementContext) colIds := []int64{1, 2, 3} colTypes := []*types.FieldType{ @@ -105,8 +105,9 @@ func prepareTestTableData(t *testing.T, keyNumber int, tableID int64) *data { colTypeMap := map[int64]*types.FieldType{} for i := 0; i < 3; i++ { colInfos[i] = &tipb.ColumnInfo{ - ColumnId: colIds[i], - Tp: int32(colTypes[i].Tp), + ColumnId: colIds[i], + Tp: int32(colTypes[i].Tp), + Collation: -mysql.DefaultCollationID, } colTypeMap[colIds[i]] = colTypes[i] } @@ -117,7 +118,9 @@ func prepareTestTableData(t *testing.T, keyNumber int, tableID int64) *data { datum := types.MakeDatums(i, "abc", 10.0) rows[int64(i)] = datum rowEncodedData, err := tablecodec.EncodeRow(stmtCtx, datum, colIds, nil, nil, encoder) - require.NoError(t, err) + if err != nil { + return nil, err + } rowKeyEncodedData := tablecodec.EncodeRowKeyWithHandle(tableID, kv.IntHandle(i)) encodedTestKVDatas[i] = &encodedTestKVData{encodedRowKey: rowKeyEncodedData, encodedRowValue: rowEncodedData} } @@ -126,7 +129,7 @@ func prepareTestTableData(t *testing.T, keyNumber int, tableID int64) *data { encodedTestKVDatas: encodedTestKVDatas, rows: rows, colTypes: colTypeMap, - } + }, nil } func getTestPointRange(tableID int64, handle int64) kv.KeyRange { @@ -202,8 +205,7 @@ func newDagContext(store *testStore, keyRanges []kv.KeyRange, dagReq *tipb.DAGRe // build and execute the executors according to the dagRequest and dagContext, // return the result chunk data, rows count and err if occurs. -func buildExecutorsAndExecute(dagRequest *tipb.DAGRequest, - dagCtx *dagContext) ([]tipb.Chunk, int, error) { +func buildExecutorsAndExecute(dagCtx *dagContext, dagRequest *tipb.DAGRequest) ([]tipb.Chunk, int, error) { closureExec, err := buildClosureExecutor(dagCtx, dagRequest) if err != nil { return nil, 0, err @@ -220,9 +222,10 @@ func buildExecutorsAndExecute(dagRequest *tipb.DAGRequest, // dagBuilder is used to build dag request type dagBuilder struct { - startTs uint64 - executors []*tipb.Executor - outputOffsets []uint32 + startTs uint64 + executors []*tipb.Executor + outputOffsets []uint32 + collectRangeCounts bool } // return a default dagBuilder @@ -230,6 +233,11 @@ func newDagBuilder() *dagBuilder { return &dagBuilder{executors: make([]*tipb.Executor, 0)} } +func (dagBuilder *dagBuilder) setCollectRangeCounts(collectRangeCounts bool) *dagBuilder { + dagBuilder.collectRangeCounts = collectRangeCounts + return dagBuilder +} + func (dagBuilder *dagBuilder) setStartTs(startTs uint64) *dagBuilder { dagBuilder.startTs = startTs return dagBuilder @@ -272,8 +280,9 @@ func (dagBuilder *dagBuilder) addLimit(limit uint64) *dagBuilder { func (dagBuilder *dagBuilder) build() *tipb.DAGRequest { return &tipb.DAGRequest{ - Executors: dagBuilder.executors, - OutputOffsets: dagBuilder.outputOffsets, + Executors: dagBuilder.executors, + OutputOffsets: dagBuilder.outputOffsets, + CollectRangeCounts: &dagBuilder.collectRangeCounts, } } @@ -296,9 +305,14 @@ func TestPointGet(t *testing.T) { // here would build mvccStore and server, and prepare // three rows data, just like the test data of table_scan.rs. // then init the store with the generated data. - data := prepareTestTableData(t, keyNumber, tableID) - store, clean := newTestStore(t, "cop_handler_test_db", "cop_handler_test_log") - defer clean() + data, err := prepareTestTableData(keyNumber, tableID) + require.NoError(t, err) + store, clean, err := newTestStore("cop_handler_test_db", "cop_handler_test_log") + require.NoError(t, err) + defer func() { + err := clean() + require.NoError(t, err) + }() errs := initTestData(store, data.encodedTestKVDatas) require.Nil(t, errs) @@ -312,7 +326,7 @@ func TestPointGet(t *testing.T) { build() dagCtx := newDagContext(store, []kv.KeyRange{getTestPointRange(tableID, handle)}, dagRequest, dagRequestStartTs) - chunks, rowCount, err := buildExecutorsAndExecute(dagRequest, dagCtx) + chunks, rowCount, err := buildExecutorsAndExecute(dagCtx, dagRequest) require.Len(t, chunks, 0) require.NoError(t, err) require.Equal(t, 0, rowCount) @@ -326,7 +340,7 @@ func TestPointGet(t *testing.T) { build() dagCtx = newDagContext(store, []kv.KeyRange{getTestPointRange(tableID, handle)}, dagRequest, dagRequestStartTs) - chunks, rowCount, err = buildExecutorsAndExecute(dagRequest, dagCtx) + chunks, rowCount, err = buildExecutorsAndExecute(dagCtx, dagRequest) require.NoError(t, err) require.Equal(t, 1, rowCount) returnedRow, err := codec.Decode(chunks[0].RowsData, 2) @@ -345,9 +359,14 @@ func TestPointGet(t *testing.T) { } func TestClosureExecutor(t *testing.T) { - data := prepareTestTableData(t, keyNumber, tableID) - store, clean := newTestStore(t, "cop_handler_test_db", "cop_handler_test_log") - defer clean() + data, err := prepareTestTableData(keyNumber, tableID) + require.NoError(t, err) + store, clean, err := newTestStore("cop_handler_test_db", "cop_handler_test_log") + require.NoError(t, err) + defer func() { + err := clean() + require.NoError(t, err) + }() errs := initTestData(store, data.encodedTestKVDatas) require.Nil(t, errs) @@ -362,12 +381,61 @@ func TestClosureExecutor(t *testing.T) { dagCtx := newDagContext(store, []kv.KeyRange{getTestPointRange(tableID, 1)}, dagRequest, dagRequestStartTs) - _, rowCount, err := buildExecutorsAndExecute(dagRequest, dagCtx) + _, rowCount, err := buildExecutorsAndExecute(dagCtx, dagRequest) require.NoError(t, err) require.Equal(t, 0, rowCount) } -func buildEQIntExpr(colID, val int64) *tipb.Expr { +func TestMppExecutor(t *testing.T) { + data, err := prepareTestTableData(keyNumber, tableID) + require.NoError(t, err) + store, clean, err := newTestStore("cop_handler_test_db", "cop_handler_test_log") + require.NoError(t, err) + defer func() { + err := clean() + require.NoError(t, err) + }() + + errs := initTestData(store, data.encodedTestKVDatas) + require.Nil(t, errs) + + dagRequest := newDagBuilder(). + setStartTs(dagRequestStartTs). + addTableScan(data.colInfos, tableID). + addSelection(buildEQIntExpr(1, 1)). + addLimit(1). + setOutputOffsets([]uint32{0, 1}). + setCollectRangeCounts(true). + build() + + dagCtx := newDagContext(store, []kv.KeyRange{getTestPointRange(tableID, 1)}, + dagRequest, dagRequestStartTs) + _, _, rowCount, _, err := buildAndRunMPPExecutor(dagCtx, dagRequest) + require.Equal(t, rowCount[0], int64(1)) + require.NoError(t, err) +} + +func buildNEIntExpr(colIdx, val int64) *tipb.Expr { + return &tipb.Expr{ + Tp: tipb.ExprType_ScalarFunc, + Sig: tipb.ScalarFuncSig_NEInt, + FieldType: expression.ToPBFieldType(types.NewFieldType(mysql.TypeLonglong)), + Children: []*tipb.Expr{ + { + Tp: tipb.ExprType_ColumnRef, + Val: codec.EncodeInt(nil, colIdx), + FieldType: expression.ToPBFieldType(types.NewFieldType(mysql.TypeLonglong)), + }, + { + Tp: tipb.ExprType_Int64, + Val: codec.EncodeInt(nil, val), + FieldType: expression.ToPBFieldType(types.NewFieldType(mysql.TypeLonglong)), + }, + }, + } +} + +func buildEQIntExpr(colIdx, val int64) *tipb.Expr { return &tipb.Expr{ Tp: tipb.ExprType_ScalarFunc, Sig: tipb.ScalarFuncSig_EQInt, @@ -375,7 +443,7 @@ func buildEQIntExpr(colID, val int64) *tipb.Expr { Children: []*tipb.Expr{ { Tp: tipb.ExprType_ColumnRef, - Val: codec.EncodeInt(nil, colID), + Val: codec.EncodeInt(nil, colIdx), FieldType: expression.ToPBFieldType(types.NewFieldType(mysql.TypeLonglong)), }, { @@ -431,27 +499,40 @@ func (ts *testStore) commit(keys [][]byte, startTS, commitTS uint64) error { }) } -func newTestStore(t *testing.T, dbPrefix string, logPrefix string) (*testStore, func()) { +func newTestStore(dbPrefix string, logPrefix string) (*testStore, func() error, error) { dbPath, err := os.MkdirTemp("", dbPrefix) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } LogPath, err := os.MkdirTemp("", logPrefix) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } db, err := createTestDB(dbPath, LogPath) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } // Some raft store path problems could not be found using simple store in tests // writer := NewDBWriter(dbBundle, safePoint) kvPath := filepath.Join(dbPath, "kv") raftPath := filepath.Join(dbPath, "raft") snapPath := filepath.Join(dbPath, "snap") err = os.MkdirAll(kvPath, os.ModePerm) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } err = os.MkdirAll(raftPath, os.ModePerm) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } err = os.Mkdir(snapPath, os.ModePerm) - require.NoError(t, err) + if err != nil { + return nil, nil, err + } - clean := func() { - require.NoError(t, db.Close()) + clean := func() error { + fmt.Printf("db closed") + return db.Close() } return &testStore{ @@ -459,7 +540,7 @@ func newTestStore(t *testing.T, dbPrefix string, logPrefix string) (*testStore, locks: lockstore.NewMemStore(4096), dbPath: dbPath, logPath: LogPath, - }, clean + }, clean, nil } func createTestDB(dbPath, LogPath string) (*badger.DB, error) { @@ -470,3 +551,81 @@ func createTestDB(dbPath, LogPath string) (*badger.DB, error) { opts.ManagedTxns = true return badger.Open(opts) } + +func BenchmarkExecutors(b *testing.B) { + + prepare := func(rows, limit int) (dagReq *tipb.DAGRequest, dagCtx *dagContext, clean func() error) { + data, err := prepareTestTableData(rows, tableID) + if err != nil { + b.Fatal(err) + } + store, clean, err := newTestStore(fmt.Sprintf("cop_handler_bench_db_%d_%d", rows, limit), "cop_handler_test_log") + if err != nil { + b.Fatal(err) + } + errs := initTestData(store, data.encodedTestKVDatas) + if len(errs) > 0 { + b.Fatal(errs) + } + + dagReq = newDagBuilder(). + setStartTs(dagRequestStartTs). + addTableScan(data.colInfos, tableID). + addSelection(buildNEIntExpr(0, 1)). + addLimit(uint64(limit)). + setOutputOffsets([]uint32{0, 1}). + setCollectRangeCounts(true). + build() + + dagCtx = newDagContext( + store, + []kv.KeyRange{ + { + StartKey: tablecodec.EncodeRowKeyWithHandle(tableID, kv.IntHandle(0)), + EndKey: tablecodec.EncodeRowKeyWithHandle(tableID, kv.IntHandle(rows)), + }, + }, + dagReq, + 3000000, + ) + return dagReq, dagCtx, clean + } + + rows := []int{1, 10, 100, 1000, 10000, 100000} + limit := []int{1, 10, 100, 1000, 10000, 100000} + cleanFuncs := make([]func() error, 0, len(rows)*len(limit)) + + for _, row := range rows { + for _, lim := range limit { + if lim > row { + break + } + dagReq, dagCtx, clean := prepare(row, lim) + cleanFuncs = append(cleanFuncs, clean) + + // b.Run(fmt.Sprintf("(row=%d, limit=%d)", row, lim), func(b *testing.B) { + // for i := 0; i < b.N; i++ { + // _, _, err := buildExecutorsAndExecute(dagCtx, dagReq) + // if err != nil { + // b.Fatal(err) + // } + // } + // + // }) + b.Run(fmt.Sprintf("(row=%d, limit=%d)", row, lim), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _, _, _, err := buildAndRunMPPExecutor(dagCtx, dagReq) + if err != nil { + b.Fatal(err) + } + } + }) + } + } + for _, clean := range cleanFuncs { + err := clean() + if err != nil { + b.Fatal(err) + } + } +} diff --git a/store/mockstore/unistore/cophandler/main_test.go b/store/mockstore/unistore/cophandler/main_test.go index e740267de961d..420cf1f476f89 100644 --- a/store/mockstore/unistore/cophandler/main_test.go +++ b/store/mockstore/unistore/cophandler/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/mockstore/unistore/cophandler/mpp.go b/store/mockstore/unistore/cophandler/mpp.go index fa5e4196cc3be..2b13319e43f08 100644 --- a/store/mockstore/unistore/cophandler/mpp.go +++ b/store/mockstore/unistore/cophandler/mpp.go @@ -25,12 +25,15 @@ import ( "github.com/pingcap/kvproto/pkg/mpp" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" + "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/store/mockstore/unistore/client" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" + "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/rowcodec" "github.com/pingcap/tipb/go-tipb" "go.uber.org/atomic" ) @@ -42,26 +45,67 @@ const ( MPPErrEstablishConnMultiTimes ) +const ( + // ErrExecutorNotSupportedMsg is the message for executor not supported. + ErrExecutorNotSupportedMsg = "executor not supported: " +) + type mppExecBuilder struct { sc *stmtctx.StatementContext dbReader *dbreader.DBReader - req *coprocessor.Request mppCtx *MPPCtx dagReq *tipb.DAGRequest + dagCtx *dagContext + counts []int64 + ndvs []int64 } func (b *mppExecBuilder) buildMPPTableScan(pb *tipb.TableScan) (*tableScanExec, error) { - ranges, err := extractKVRanges(b.dbReader.StartKey, b.dbReader.EndKey, b.req.Ranges, false) + ranges, err := extractKVRanges(b.dbReader.StartKey, b.dbReader.EndKey, b.dagCtx.keyRanges, pb.Desc) if err != nil { return nil, errors.Trace(err) } ts := &tableScanExec{ baseMPPExec: baseMPPExec{sc: b.sc, mppCtx: b.mppCtx}, - startTS: b.req.StartTs, + startTS: b.dagCtx.startTS, kvRanges: ranges, dbReader: b.dbReader, + counts: b.counts, + ndvs: b.ndvs, + desc: pb.Desc, + } + if b.dagCtx != nil { + ts.lockStore = b.dagCtx.lockStore + ts.resolvedLocks = b.dagCtx.resolvedLocks + } + for i, col := range pb.Columns { + if col.ColumnId == model.ExtraPhysTblID { + ts.physTblIDColIdx = new(int) + *ts.physTblIDColIdx = i + } + ft := fieldTypeFromPBColumn(col) + ts.fieldTypes = append(ts.fieldTypes, ft) } - for _, col := range pb.Columns { + ts.decoder, err = newRowDecoder(pb.Columns, ts.fieldTypes, pb.PrimaryColumnIds, b.sc.TimeZone) + return ts, err +} + +func (b *mppExecBuilder) buildMPPPartitionTableScan(pb *tipb.PartitionTableScan) (*tableScanExec, error) { + ranges, err := extractKVRanges(b.dbReader.StartKey, b.dbReader.EndKey, b.dagCtx.keyRanges, false) + if err != nil { + return nil, errors.Trace(err) + } + ts := &tableScanExec{ + baseMPPExec: baseMPPExec{sc: b.sc, mppCtx: b.mppCtx}, + startTS: b.dagCtx.startTS, + kvRanges: ranges, + dbReader: b.dbReader, + } + for i, col := range pb.Columns { + if col.ColumnId == model.ExtraPhysTblID { + ts.physTblIDColIdx = new(int) + *ts.physTblIDColIdx = i + } ft := fieldTypeFromPBColumn(col) ts.fieldTypes = append(ts.fieldTypes, ft) } @@ -69,6 +113,120 @@ func (b *mppExecBuilder) buildMPPTableScan(pb *tipb.TableScan) (*tableScanExec, return ts, err } +func (b *mppExecBuilder) buildIdxScan(pb *tipb.IndexScan) (*indexScanExec, error) { + ranges, err := extractKVRanges(b.dbReader.StartKey, b.dbReader.EndKey, b.dagCtx.keyRanges, pb.Desc) + if err != nil { + return nil, errors.Trace(err) + } + numCols := len(pb.Columns) + numIdxCols := numCols + colInfos := make([]rowcodec.ColInfo, 0, numCols) + fieldTypes := make([]*types.FieldType, 0, numCols) + primaryColIds := pb.GetPrimaryColumnIds() + + lastCol := pb.Columns[numCols-1] + var physTblIDColIdx *int + if lastCol.GetColumnId() == model.ExtraPhysTblID { + numIdxCols-- + physTblIDColIdx = new(int) + *physTblIDColIdx = numIdxCols + lastCol = pb.Columns[numIdxCols-1] + } + if lastCol.GetColumnId() == model.ExtraPidColID { + numIdxCols-- + lastCol = pb.Columns[numIdxCols-1] + } + + hdlStatus := tablecodec.HandleDefault + if len(primaryColIds) == 0 { + if lastCol.GetPkHandle() { + if mysql.HasUnsignedFlag(uint(lastCol.GetFlag())) { + hdlStatus = tablecodec.HandleIsUnsigned + } + numIdxCols-- + } else if lastCol.ColumnId == model.ExtraHandleID { + numIdxCols-- + } + } else { + numIdxCols -= len(primaryColIds) + } + + for _, col := range pb.Columns { + ft := fieldTypeFromPBColumn(col) + fieldTypes = append(fieldTypes, ft) + colInfos = append(colInfos, rowcodec.ColInfo{ + ID: col.ColumnId, + Ft: ft, + IsPKHandle: col.GetPkHandle(), + }) + } + + var prevVals [][]byte + if b.dagReq.GetCollectRangeCounts() { + prevVals = make([][]byte, numIdxCols) + } + idxScan := &indexScanExec{ + baseMPPExec: baseMPPExec{sc: b.sc, fieldTypes: fieldTypes}, + startTS: b.dagCtx.startTS, + kvRanges: ranges, + dbReader: b.dbReader, + lockStore: b.dagCtx.lockStore, + resolvedLocks: b.dagCtx.resolvedLocks, + counts: b.counts, + ndvs: b.ndvs, + prevVals: prevVals, + colInfos: colInfos, + numIdxCols: numIdxCols, + hdlStatus: hdlStatus, + desc: pb.Desc, + physTblIDColIdx: physTblIDColIdx, + } + return idxScan, nil +} + +func (b *mppExecBuilder) buildLimit(pb *tipb.Limit) (*limitExec, error) { + child, err := b.buildMPPExecutor(pb.Child) + if err != nil { + return nil, err + } + exec := &limitExec{ + baseMPPExec: baseMPPExec{sc: b.sc, mppCtx: b.mppCtx, fieldTypes: child.getFieldTypes(), children: []mppExec{child}}, + limit: pb.GetLimit(), + } + return exec, nil +} + +func (b *mppExecBuilder) buildTopN(pb *tipb.TopN) (*topNExec, error) { + child, err := b.buildMPPExecutor(pb.Child) + if err != nil { + return nil, err + } + pbConds := make([]*tipb.Expr, len(pb.OrderBy)) + for i, item := range pb.OrderBy { + pbConds[i] = item.Expr + } + heap := &topNHeap{ + totalCount: int(pb.Limit), + topNSorter: topNSorter{ + orderByItems: pb.OrderBy, + sc: b.sc, + }, + } + fieldTps := child.getFieldTypes() + var conds []expression.Expression + if conds, err = convertToExprs(b.sc, fieldTps, pbConds); err != nil { + return nil, errors.Trace(err) + } + exec := &topNExec{ + baseMPPExec: baseMPPExec{sc: b.sc, mppCtx: b.mppCtx, fieldTypes: fieldTps, children: []mppExec{child}}, + heap: heap, + conds: conds, + row: newTopNSortRow(len(conds)), + topn: pb.Limit, + } + return exec, nil +} + func (b *mppExecBuilder) buildMPPExchangeSender(pb *tipb.ExchangeSender) (*exchSenderExec, error) { child, err := b.buildMPPExecutor(pb.Child) if err != nil { @@ -309,15 +467,24 @@ func (b *mppExecBuilder) buildMPPExecutor(exec *tipb.Executor) (mppExec, error) case tipb.ExecType_TypeJoin: join := exec.Join return b.buildMPPJoin(join, join.Children) - case tipb.ExecType_TypeAggregation: + case tipb.ExecType_TypeAggregation, tipb.ExecType_TypeStreamAgg: agg := exec.Aggregation return b.buildMPPAgg(agg) case tipb.ExecType_TypeProjection: return b.buildMPPProj(exec.Projection) case tipb.ExecType_TypeSelection: return b.buildMPPSel(exec.Selection) + case tipb.ExecType_TypeIndexScan: + return b.buildIdxScan(exec.IdxScan) + case tipb.ExecType_TypeLimit: + return b.buildLimit(exec.Limit) + case tipb.ExecType_TypeTopN: + return b.buildTopN(exec.TopN) + case tipb.ExecType_TypePartitionTableScan: + ts := exec.PartitionTableScan + return b.buildMPPPartitionTableScan(ts) default: - return nil, errors.Errorf("Do not support executor %s", exec.Tp.String()) + return nil, errors.Errorf(ErrExecutorNotSupportedMsg + exec.Tp.String()) } } @@ -329,12 +496,17 @@ func HandleMPPDAGReq(dbReader *dbreader.DBReader, req *coprocessor.Request, mppC if err != nil { return &coprocessor.Response{OtherError: err.Error()} } + dagCtx := &dagContext{ + dbReader: dbReader, + startTS: req.StartTs, + keyRanges: req.Ranges, + } builder := mppExecBuilder{ dbReader: dbReader, - req: req, mppCtx: mppCtx, sc: flagsToStatementContext(dagReq.Flags), dagReq: dagReq, + dagCtx: dagCtx, } mppExec, err := builder.buildMPPExecutor(dagReq.RootExecutor) if err != nil { diff --git a/store/mockstore/unistore/cophandler/mpp_exec.go b/store/mockstore/unistore/cophandler/mpp_exec.go index 9e2e071513e04..85a5983517e11 100644 --- a/store/mockstore/unistore/cophandler/mpp_exec.go +++ b/store/mockstore/unistore/cophandler/mpp_exec.go @@ -15,8 +15,11 @@ package cophandler import ( + "bytes" + "encoding/binary" "io" "math" + "sort" "sync" "time" @@ -28,9 +31,11 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/store/mockstore/unistore/lockstore" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/rowcodec" @@ -38,11 +43,19 @@ import ( "github.com/tikv/client-go/v2/tikvrpc" ) +var ( + // DefaultBatchSize is the default batch size for newly allocated chunk during execution. + DefaultBatchSize = 32 +) + // mpp executor that only servers for mpp execution type mppExec interface { open() error next() (*chunk.Chunk, error) + stop() error + child() mppExec getFieldTypes() []*types.FieldType + buildSummary() *tipb.ExecutorExecutionSummary } type baseMPPExec struct { @@ -52,24 +65,67 @@ type baseMPPExec struct { children []mppExec - fieldTypes []*types.FieldType + fieldTypes []*types.FieldType + execSummary execDetail +} + +func (b *baseMPPExec) child() mppExec { + return b.children[0] } func (b *baseMPPExec) getFieldTypes() []*types.FieldType { return b.fieldTypes } +func (b *baseMPPExec) buildSummary() *tipb.ExecutorExecutionSummary { + return b.execSummary.buildSummary() +} + +func (b *baseMPPExec) open() error { + panic("not implemented") +} + +func (b *baseMPPExec) next() (*chunk.Chunk, error) { + panic("not implemented") +} + +func (b *baseMPPExec) stop() error { + for _, child := range b.children { + err := child.stop() + if err != nil { + return errors.Trace(err) + } + } + return nil +} + +type scanResult struct { + chk *chunk.Chunk + err error +} + type tableScanExec struct { baseMPPExec - kvRanges []kv.KeyRange - startTS uint64 - dbReader *dbreader.DBReader + kvRanges []kv.KeyRange + startTS uint64 + dbReader *dbreader.DBReader + lockStore *lockstore.MemStore + resolvedLocks []uint64 + counts []int64 + ndvs []int64 + rowCnt int64 - chunks []*chunk.Chunk - chkIdx int + chk *chunk.Chunk + result chan scanResult + done chan struct{} + wg util.WaitGroupWrapper decoder *rowcodec.ChunkDecoder + desc bool + + // if ExtraPhysTblIDCol is requested, fill in the physical table id in this column position + physTblIDColIdx *int } func (e *tableScanExec) SkipValue() bool { return false } @@ -79,33 +135,294 @@ func (e *tableScanExec) Process(key, value []byte) error { if err != nil { return errors.Trace(err) } - chk := chunk.NewChunkWithCapacity(e.fieldTypes, 0) - err = e.decoder.DecodeToChunk(value, handle, chk) - e.chunks = append(e.chunks, chk) + + err = e.decoder.DecodeToChunk(value, handle, e.chk) if err != nil { return errors.Trace(err) } + if e.physTblIDColIdx != nil { + tblID := tablecodec.DecodeTableID(key) + e.chk.AppendInt64(*e.physTblIDColIdx, tblID) + } + e.rowCnt++ + + if e.chk.IsFull() { + select { + case e.result <- scanResult{chk: e.chk, err: nil}: + e.chk = chunk.NewChunkWithCapacity(e.fieldTypes, DefaultBatchSize) + case <-e.done: + return dbreader.ErrScanBreak + } + } + select { + case <-e.done: + return dbreader.ErrScanBreak + default: + } return nil } func (e *tableScanExec) open() error { + var err error + if e.lockStore != nil { + for _, ran := range e.kvRanges { + err = checkRangeLockForRange(e.lockStore, e.startTS, e.resolvedLocks, ran) + if err != nil { + return err + } + } + } + e.chk = chunk.NewChunkWithCapacity(e.fieldTypes, DefaultBatchSize) + e.result = make(chan scanResult, 1) + e.done = make(chan struct{}) + e.wg.Run(func() { + // close the channel when done scanning, so that next() will got nil chunk + defer close(e.result) + for i, ran := range e.kvRanges { + oldCnt := e.rowCnt + if e.desc { + err = e.dbReader.ReverseScan(ran.StartKey, ran.EndKey, math.MaxInt64, e.startTS, e) + } else { + err = e.dbReader.Scan(ran.StartKey, ran.EndKey, math.MaxInt64, e.startTS, e) + } + if len(e.counts) != 0 { + e.counts[i] += e.rowCnt - oldCnt + e.ndvs[i] += e.rowCnt - oldCnt + } + if err != nil { + e.result <- scanResult{err: err} + return + } + } + + // handle the last chunk + if e.chk != nil && e.chk.NumRows() > 0 { + select { + case e.result <- scanResult{chk: e.chk, err: nil}: + return + case <-e.done: + } + return + } + }) + + return nil +} + +func (e *tableScanExec) next() (*chunk.Chunk, error) { + result := <-e.result + if result.chk == nil || result.err != nil { + return nil, result.err + } + e.execSummary.updateOnlyRows(result.chk.NumRows()) + return result.chk, nil +} + +func (e *tableScanExec) stop() error { + // just in case the channel is not initialized + if e.done != nil { + close(e.done) + } + e.wg.Wait() + return nil +} + +type indexScanExec struct { + baseMPPExec + + startTS uint64 + kvRanges []kv.KeyRange + desc bool + dbReader *dbreader.DBReader + lockStore *lockstore.MemStore + resolvedLocks []uint64 + counts []int64 + ndvs []int64 + prevVals [][]byte + rowCnt int64 + ndvCnt int64 + chk *chunk.Chunk + chkIdx int + chunks []*chunk.Chunk + + colInfos []rowcodec.ColInfo + numIdxCols int + hdlStatus tablecodec.HandleStatus + + // if ExtraPhysTblIDCol is requested, fill in the physical table id in this column position + physTblIDColIdx *int +} + +func (e *indexScanExec) SkipValue() bool { return false } + +func (e *indexScanExec) isNewVals(values [][]byte) bool { + for i := 0; i < e.numIdxCols; i++ { + if !bytes.Equal(e.prevVals[i], values[i]) { + return true + } + } + return false +} + +func (e *indexScanExec) Process(key, value []byte) error { + values, err := tablecodec.DecodeIndexKV(key, value, e.numIdxCols, e.hdlStatus, e.colInfos) + if err != nil { + return err + } + e.rowCnt++ + if len(e.counts) > 0 && (len(e.prevVals[0]) == 0 || e.isNewVals(values)) { + e.ndvCnt++ + for i := 0; i < e.numIdxCols; i++ { + e.prevVals[i] = append(e.prevVals[i][:0], values[i]...) + } + } + decoder := codec.NewDecoder(e.chk, e.sc.TimeZone) + for i, value := range values { + if i < len(e.fieldTypes) { + _, err = decoder.DecodeOne(value, i, e.fieldTypes[i]) + if err != nil { + return errors.Trace(err) + } + } + } + if e.physTblIDColIdx != nil { + tblID := tablecodec.DecodeTableID(key) + e.chk.AppendInt64(*e.physTblIDColIdx, tblID) + } + if e.chk.IsFull() { + e.chunks = append(e.chunks, e.chk) + e.chk = chunk.NewChunkWithCapacity(e.fieldTypes, DefaultBatchSize) + } + return nil +} + +func (e *indexScanExec) open() error { + var err error for _, ran := range e.kvRanges { - err := e.dbReader.Scan(ran.StartKey, ran.EndKey, math.MaxInt64, e.startTS, e) + err = checkRangeLockForRange(e.lockStore, e.startTS, e.resolvedLocks, ran) + if err != nil { + return err + } + } + e.chk = chunk.NewChunkWithCapacity(e.fieldTypes, DefaultBatchSize) + for i, rg := range e.kvRanges { + oldCnt := e.rowCnt + e.ndvCnt = 0 + if e.desc { + err = e.dbReader.ReverseScan(rg.StartKey, rg.EndKey, math.MaxInt64, e.startTS, e) + } else { + err = e.dbReader.Scan(rg.StartKey, rg.EndKey, math.MaxInt64, e.startTS, e) + } + if len(e.counts) != 0 { + e.counts[i] += e.rowCnt - oldCnt + e.ndvs[i] += e.ndvCnt + } if err != nil { return errors.Trace(err) } } + if e.chk.NumRows() != 0 { + e.chunks = append(e.chunks, e.chk) + } return nil } -func (e *tableScanExec) next() (*chunk.Chunk, error) { +func (e *indexScanExec) next() (*chunk.Chunk, error) { if e.chkIdx < len(e.chunks) { - e.chkIdx++ + e.chkIdx += 1 + e.execSummary.updateOnlyRows(e.chunks[e.chkIdx-1].NumRows()) return e.chunks[e.chkIdx-1], nil } return nil, nil } +type limitExec struct { + baseMPPExec + + limit uint64 +} + +func (e *limitExec) open() error { + return e.children[0].open() +} + +func (e *limitExec) next() (*chunk.Chunk, error) { + chk, err := e.children[0].next() + if err != nil || chk == nil || chk.NumRows() == 0 { + return chk, err + } + if uint64(chk.NumRows()) <= e.limit { + e.limit -= uint64(chk.NumRows()) + } else { + chk.TruncateTo(int(e.limit)) + e.limit = 0 + } + e.execSummary.updateOnlyRows(chk.NumRows()) + return chk, nil +} + +type topNExec struct { + baseMPPExec + + topn uint64 + idx uint64 + heap *topNHeap + conds []expression.Expression + row *sortRow + recv []*chunk.Chunk +} + +func (e *topNExec) open() error { + var chk *chunk.Chunk + var err error + err = e.children[0].open() + if err != nil { + return err + } + for { + chk, err = e.children[0].next() + if err != nil { + return err + } + if chk == nil || chk.NumRows() == 0 { + break + } + e.execSummary.updateOnlyRows(chk.NumRows()) + numRows := chk.NumRows() + for i := 0; i < numRows; i++ { + row := chk.GetRow(i) + for j, cond := range e.conds { + d, err := cond.Eval(row) + if err != nil { + return err + } + d.Copy(&e.row.key[j]) + } + if e.heap.tryToAddRow(e.row) { + e.row.data[0] = make([]byte, 4) + binary.LittleEndian.PutUint32(e.row.data[0], uint32(len(e.recv))) + e.row.data[1] = make([]byte, 4) + binary.LittleEndian.PutUint32(e.row.data[1], uint32(i)) + e.row = newTopNSortRow(len(e.conds)) + } + } + e.recv = append(e.recv, chk) + } + sort.Sort(&e.heap.topNSorter) + return nil +} + +func (e *topNExec) next() (*chunk.Chunk, error) { + chk := chunk.NewChunkWithCapacity(e.getFieldTypes(), DefaultBatchSize) + for ; !chk.IsFull() && e.idx < e.topn && e.idx < uint64(e.heap.heapSize); e.idx++ { + row := e.heap.rows[e.idx] + chkID := binary.LittleEndian.Uint32(row.data[0]) + rowID := binary.LittleEndian.Uint32(row.data[1]) + chk.AppendRow(e.recv[chkID].GetRow(int(rowID))) + } + return chk, nil +} + type exchSenderExec struct { baseMPPExec @@ -146,6 +463,10 @@ func (e *exchSenderExec) next() (*chunk.Chunk, error) { close(tunnel.ErrCh) close(tunnel.DataCh) } + err := e.stop() + if err != nil { + panic(err) + } }() for { chk, err := e.children[0].next() @@ -154,7 +475,7 @@ func (e *exchSenderExec) next() (*chunk.Chunk, error) { tunnel.ErrCh <- err } return nil, nil - } else if chk != nil { + } else if chk != nil && chk.NumRows() != 0 { if e.exchangeTp == tipb.ExchangeType_Hash { rows := chk.NumRows() targetChunks := make([]*chunk.Chunk, 0, len(e.tunnels)) @@ -366,7 +687,7 @@ func (e *joinExec) buildHashTable() error { if err != nil { return errors.Trace(err) } - if chk == nil { + if chk == nil || chk.NumRows() == 0 { return nil } rows := chk.NumRows() @@ -392,7 +713,7 @@ func (e *joinExec) fetchRows() (bool, error) { if err != nil { return false, errors.Trace(err) } - if chk == nil { + if chk == nil || chk.NumRows() == 0 { return true, nil } e.idx = 0 @@ -444,6 +765,18 @@ func (e *joinExec) open() error { return nil } +func (e *joinExec) stop() error { + err := e.buildChild.stop() + if err != nil { + return errors.Trace(err) + } + err = e.probeChild.stop() + if err != nil { + return errors.Trace(err) + } + return nil +} + func (e *joinExec) next() (*chunk.Chunk, error) { if !e.inited { e.inited = true @@ -491,7 +824,7 @@ func (e *aggExec) getGroupKey(row chunk.Row) (*chunk.MutRow, []byte, error) { if length == 0 { return nil, nil, nil } - key := make([]byte, 0, 32) + key := make([]byte, 0, DefaultBatchSize) gbyRow := chunk.MutRowFromTypes(e.groupByTypes) for i, item := range e.groupByExprs { v, err := item.Eval(row) @@ -526,7 +859,7 @@ func (e *aggExec) processAllRows() (*chunk.Chunk, error) { if err != nil { return nil, errors.Trace(err) } - if chk == nil { + if chk == nil || chk.NumRows() == 0 { break } rows := chk.NumRows() @@ -575,6 +908,7 @@ func (e *aggExec) processAllRows() (*chunk.Chunk, error) { } chk.AppendRow(newRow.ToRow()) } + e.execSummary.updateOnlyRows(chk.NumRows()) return chk, nil } @@ -597,42 +931,50 @@ func (e *selExec) open() error { } func (e *selExec) next() (*chunk.Chunk, error) { - chk, err := e.children[0].next() - if err != nil { - return nil, errors.Trace(err) - } - if chk == nil { - return nil, nil - } - for rows := chk.NumRows() - 1; rows >= 0; rows-- { - row := chk.GetRow(rows) - for _, cond := range e.conditions { - d, err := cond.Eval(row) - if err != nil { - return nil, errors.Trace(err) - } - - var passCheck bool - if d.IsNull() { - passCheck = false - } else { - isBool, err := d.ToBool(e.sc) + ret := chunk.NewChunkWithCapacity(e.getFieldTypes(), DefaultBatchSize) + for !ret.IsFull() { + chk, err := e.children[0].next() + if err != nil { + return nil, errors.Trace(err) + } + if chk == nil || chk.NumRows() == 0 { + break + } + numRows := chk.NumRows() + for rows := 0; rows < numRows; rows++ { + row := chk.GetRow(rows) + passCheck := true + for _, cond := range e.conditions { + d, err := cond.Eval(row) if err != nil { return nil, errors.Trace(err) } - isBool, err = expression.HandleOverflowOnSelection(e.sc, isBool, err) - if err != nil { - return nil, errors.Trace(err) + + if d.IsNull() { + passCheck = false + } else { + isBool, err := d.ToBool(e.sc) + if err != nil { + return nil, errors.Trace(err) + } + isBool, err = expression.HandleOverflowOnSelection(e.sc, isBool, err) + if err != nil { + return nil, errors.Trace(err) + } + passCheck = isBool != 0 + } + if !passCheck { + break } - passCheck = isBool != 0 } - if !passCheck { - chk.TruncateTo(rows) - break + if passCheck { + ret.AppendRow(row) + e.execSummary.updateOnlyRows(1) } } } - return chk, nil + + return ret, nil } type projExec struct { @@ -649,9 +991,10 @@ func (e *projExec) next() (*chunk.Chunk, error) { if err != nil { return nil, errors.Trace(err) } - if chk == nil { + if chk == nil || chk.NumRows() == 0 { return nil, nil } + e.baseMPPExec.execSummary.updateOnlyRows(chk.NumRows()) newChunk := chunk.NewChunkWithCapacity(e.fieldTypes, 10) for i := 0; i < chk.NumRows(); i++ { row := chk.GetRow(i) diff --git a/store/mockstore/unistore/cophandler/topn.go b/store/mockstore/unistore/cophandler/topn.go index 185317cbec1ee..54c0853a7199a 100644 --- a/store/mockstore/unistore/cophandler/topn.go +++ b/store/mockstore/unistore/cophandler/topn.go @@ -23,7 +23,7 @@ import ( "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/collate" - tipb "github.com/pingcap/tipb/go-tipb" + "github.com/pingcap/tipb/go-tipb" ) type sortRow struct { diff --git a/store/mockstore/unistore/lockstore/load_dump.go b/store/mockstore/unistore/lockstore/load_dump.go index dca102ab0b0ed..f0192331ecd48 100644 --- a/store/mockstore/unistore/lockstore/load_dump.go +++ b/store/mockstore/unistore/lockstore/load_dump.go @@ -96,7 +96,7 @@ func (ls *MemStore) writeItem(writer *bufio.Writer, data []byte) error { // DumpToFile dumps the meta to a file func (ls *MemStore) DumpToFile(fileName string, meta []byte) error { tmpFileName := fileName + ".tmp" - f, err := os.OpenFile(tmpFileName, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666) + f, err := os.OpenFile(tmpFileName, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600) if err != nil { return errors.Trace(err) } diff --git a/store/mockstore/unistore/lockstore/main_test.go b/store/mockstore/unistore/lockstore/main_test.go index 5674b940ca5e6..fdef458e79cb9 100644 --- a/store/mockstore/unistore/lockstore/main_test.go +++ b/store/mockstore/unistore/lockstore/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/mockstore/unistore/main_test.go b/store/mockstore/unistore/main_test.go index 9d44274a8c87d..adc65105d06c2 100644 --- a/store/mockstore/unistore/main_test.go +++ b/store/mockstore/unistore/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/mockstore/unistore/mock.go b/store/mockstore/unistore/mock.go index 37bfaf5473d5d..06bfe7396abc4 100644 --- a/store/mockstore/unistore/mock.go +++ b/store/mockstore/unistore/mock.go @@ -34,7 +34,7 @@ func New(path string) (*RPCClient, pd.Client, *Cluster, error) { persistent = false } - if err := os.MkdirAll(path, 0777); err != nil { + if err := os.MkdirAll(path, 0750); err != nil { return nil, nil, nil, err } diff --git a/store/mockstore/unistore/pd.go b/store/mockstore/unistore/pd.go index 3ed8f53d3d9d2..a5129caf01a8d 100644 --- a/store/mockstore/unistore/pd.go +++ b/store/mockstore/unistore/pd.go @@ -32,15 +32,53 @@ type pdClient struct { serviceSafePoints map[string]uint64 gcSafePointMu sync.Mutex + globalConfig map[string]string } func newPDClient(pd *us.MockPD) *pdClient { return &pdClient{ MockPD: pd, serviceSafePoints: make(map[string]uint64), + globalConfig: make(map[string]string), } } +func (c *pdClient) LoadGlobalConfig(ctx context.Context, names []string) ([]pd.GlobalConfigItem, error) { + ret := make([]pd.GlobalConfigItem, len(names)) + for i, name := range names { + if r, ok := c.globalConfig["/global/config/"+name]; ok { + ret[i] = pd.GlobalConfigItem{Name: "/global/config/" + name, Value: r} + } else { + ret[i] = pd.GlobalConfigItem{Name: "/global/config/" + name, Error: errors.New("not found")} + } + } + return ret, nil +} + +func (c *pdClient) StoreGlobalConfig(ctx context.Context, items []pd.GlobalConfigItem) error { + for _, item := range items { + c.globalConfig["/global/config/"+item.Name] = item.Value + } + return nil +} + +func (c *pdClient) WatchGlobalConfig(ctx context.Context) (chan []pd.GlobalConfigItem, error) { + globalConfigWatcherCh := make(chan []pd.GlobalConfigItem, 16) + go func() { + defer func() { + if r := recover(); r != nil { + return + } + }() + for i := 0; i < 10; i++ { + for k, v := range c.globalConfig { + globalConfigWatcherCh <- []pd.GlobalConfigItem{{Name: k, Value: v}} + } + } + }() + return globalConfigWatcherCh, nil +} + func (c *pdClient) GetLocalTS(ctx context.Context, dcLocation string) (int64, int64, error) { return c.GetTS(ctx) } diff --git a/store/mockstore/unistore/pd/client.go b/store/mockstore/unistore/pd/client.go index bd37bfa2ede2e..3ac364d5c0284 100644 --- a/store/mockstore/unistore/pd/client.go +++ b/store/mockstore/unistore/pd/client.go @@ -40,8 +40,8 @@ type Client interface { IsBootstrapped(ctx context.Context) (bool, error) PutStore(ctx context.Context, store *metapb.Store) error GetStore(ctx context.Context, storeID uint64) (*metapb.Store, error) - GetRegion(ctx context.Context, key []byte) (*pd.Region, error) - GetRegionByID(ctx context.Context, regionID uint64) (*pd.Region, error) + GetRegion(ctx context.Context, key []byte, opts ...pd.GetRegionOption) (*pd.Region, error) + GetRegionByID(ctx context.Context, regionID uint64, opts ...pd.GetRegionOption) (*pd.Region, error) ReportRegion(*pdpb.RegionHeartbeatRequest) AskSplit(ctx context.Context, region *metapb.Region) (*pdpb.AskSplitResponse, error) AskBatchSplit(ctx context.Context, region *metapb.Region, count int) (*pdpb.AskBatchSplitResponse, error) @@ -503,7 +503,7 @@ func (c *client) GetClusterConfig(ctx context.Context) (*metapb.Cluster, error) return resp.Cluster, nil } -func (c *client) GetRegion(ctx context.Context, key []byte) (*pd.Region, error) { +func (c *client) GetRegion(ctx context.Context, key []byte, opts ...pd.GetRegionOption) (*pd.Region, error) { var resp *pdpb.GetRegionResponse err := c.doRequest(ctx, func(ctx context.Context, client pdpb.PDClient) error { var err1 error @@ -530,7 +530,7 @@ func (c *client) GetRegion(ctx context.Context, key []byte) (*pd.Region, error) return r, nil } -func (c *client) GetRegionByID(ctx context.Context, regionID uint64) (*pd.Region, error) { +func (c *client) GetRegionByID(ctx context.Context, regionID uint64, opts ...pd.GetRegionOption) (*pd.Region, error) { var resp *pdpb.GetRegionResponse err := c.doRequest(ctx, func(ctx context.Context, client pdpb.PDClient) error { var err1 error diff --git a/store/mockstore/unistore/pd_test.go b/store/mockstore/unistore/pd_test.go new file mode 100644 index 0000000000000..1fa645a3f2e86 --- /dev/null +++ b/store/mockstore/unistore/pd_test.go @@ -0,0 +1,96 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unistore + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + pd "github.com/tikv/pd/client" +) + +type GlobalConfigTestSuite struct { + rpc *RPCClient + cluster *Cluster + client pd.Client +} + +func SetUpSuite() *GlobalConfigTestSuite { + s := &GlobalConfigTestSuite{} + s.rpc, s.client, s.cluster, _ = New("") + return s +} + +func TestLoad(t *testing.T) { + s := SetUpSuite() + + s.client.StoreGlobalConfig(context.Background(), []pd.GlobalConfigItem{{Name: "LoadOkGlobalConfig", Value: "ok"}}) + res, err := s.client.LoadGlobalConfig(context.Background(), []string{"LoadOkGlobalConfig", "LoadErrGlobalConfig"}) + require.Equal(t, err, nil) + for _, j := range res { + switch j.Name { + case "/global/config/LoadOkGlobalConfig": + require.Equal(t, j.Value, "ok") + + case "/global/config/LoadErrGlobalConfig": + require.Equal(t, j.Value, "") + require.EqualError(t, j.Error, "not found") + default: + require.Equal(t, true, false) + } + } + s.TearDownSuite() +} + +func TestStore(t *testing.T) { + s := SetUpSuite() + + res, err := s.client.LoadGlobalConfig(context.Background(), []string{"NewObject"}) + require.Equal(t, err, nil) + require.EqualError(t, res[0].Error, "not found") + + err = s.client.StoreGlobalConfig(context.Background(), []pd.GlobalConfigItem{{Name: "NewObject", Value: "ok"}}) + require.Equal(t, err, nil) + + res, err = s.client.LoadGlobalConfig(context.Background(), []string{"NewObject"}) + require.Equal(t, err, nil) + require.Equal(t, res[0].Error, nil) + + s.TearDownSuite() +} + +func TestWatch(t *testing.T) { + s := SetUpSuite() + err := s.client.StoreGlobalConfig(context.Background(), []pd.GlobalConfigItem{{Name: "NewObject", Value: "ok"}}) + require.Equal(t, err, nil) + + ch, err := s.client.WatchGlobalConfig(context.Background()) + require.Equal(t, err, nil) + + for i := 0; i < 10; i++ { + res := <-ch + require.NotEqual(t, res[0].Value, "") + } + close(ch) + + s.TearDownSuite() +} + +func (s *GlobalConfigTestSuite) TearDownSuite() { + s.client.Close() + s.rpc.Close() + s.cluster.Close() +} diff --git a/store/mockstore/unistore/rpc.go b/store/mockstore/unistore/rpc.go index 94ef82d0e1475..3da40691310a5 100644 --- a/store/mockstore/unistore/rpc.go +++ b/store/mockstore/unistore/rpc.go @@ -53,6 +53,9 @@ type RPCClient struct { closed int32 } +// CheckResourceTagForTopSQLInGoTest is used to identify whether check resource tag for TopSQL. +var CheckResourceTagForTopSQLInGoTest bool + // UnistoreRPCClientSendHook exports for test. var UnistoreRPCClientSendHook func(*tikvrpc.Request) @@ -96,6 +99,13 @@ func (c *RPCClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.R return nil, err } + if CheckResourceTagForTopSQLInGoTest { + err = checkResourceTagForTopSQL(req) + if err != nil { + return nil, err + } + } + resp := &tikvrpc.Response{} switch req.Type { case tikvrpc.CmdGet: @@ -405,6 +415,11 @@ func (c *RPCClient) Close() error { return nil } +// CloseAddr implements tikv.Client interface and it does nothing. +func (c *RPCClient) CloseAddr(addr string) error { + return nil +} + type mockClientStream struct{} // Header implements grpc.ClientStream interface diff --git a/store/mockstore/unistore/testutil.go b/store/mockstore/unistore/testutil.go new file mode 100644 index 0000000000000..d085a24ba5788 --- /dev/null +++ b/store/mockstore/unistore/testutil.go @@ -0,0 +1,116 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unistore + +import ( + "errors" + "fmt" + "runtime" + + "github.com/pingcap/tidb/tablecodec" + topsqlstate "github.com/pingcap/tidb/util/topsql/state" + "github.com/tikv/client-go/v2/tikvrpc" +) + +func checkResourceTagForTopSQL(req *tikvrpc.Request) error { + if !topsqlstate.TopSQLEnabled() { + return nil + } + tag := req.GetResourceGroupTag() + if len(tag) > 0 { + return nil + } + + startKey, err := getReqStartKey(req) + if err != nil { + return err + } + var tid int64 + if tablecodec.IsRecordKey(startKey) { + tid, _, _ = tablecodec.DecodeRecordKey(startKey) + } + if tablecodec.IsIndexKey(startKey) { + tid, _, _, _ = tablecodec.DecodeIndexKey(startKey) + } + // since the error maybe "invalid record key", should just ignore check resource tag for this request. + if tid > 0 { + stack := getStack() + return fmt.Errorf("%v req does not set the resource tag, tid: %v, stack: %v", + req.Type.String(), tid, string(stack)) + } + return nil +} + +func getReqStartKey(req *tikvrpc.Request) ([]byte, error) { + switch req.Type { + case tikvrpc.CmdGet: + request := req.Get() + return request.Key, nil + case tikvrpc.CmdScan: + request := req.Scan() + return request.StartKey, nil + case tikvrpc.CmdPrewrite: + request := req.Prewrite() + return request.Mutations[0].Key, nil + case tikvrpc.CmdCommit: + request := req.Commit() + return request.Keys[0], nil + case tikvrpc.CmdCleanup: + request := req.Cleanup() + return request.Key, nil + case tikvrpc.CmdBatchGet: + request := req.BatchGet() + return request.Keys[0], nil + case tikvrpc.CmdBatchRollback: + request := req.BatchRollback() + return request.Keys[0], nil + case tikvrpc.CmdScanLock: + request := req.ScanLock() + return request.StartKey, nil + case tikvrpc.CmdPessimisticLock: + request := req.PessimisticLock() + return request.PrimaryLock, nil + case tikvrpc.CmdCheckSecondaryLocks: + request := req.CheckSecondaryLocks() + return request.Keys[0], nil + case tikvrpc.CmdCop, tikvrpc.CmdCopStream: + request := req.Cop() + return request.Ranges[0].Start, nil + case tikvrpc.CmdGC, tikvrpc.CmdDeleteRange, tikvrpc.CmdTxnHeartBeat, tikvrpc.CmdRawGet, + tikvrpc.CmdRawBatchGet, tikvrpc.CmdRawPut, tikvrpc.CmdRawBatchPut, tikvrpc.CmdRawDelete, tikvrpc.CmdRawBatchDelete, tikvrpc.CmdRawDeleteRange, + tikvrpc.CmdRawScan, tikvrpc.CmdGetKeyTTL, tikvrpc.CmdRawCompareAndSwap, tikvrpc.CmdUnsafeDestroyRange, tikvrpc.CmdRegisterLockObserver, + tikvrpc.CmdCheckLockObserver, tikvrpc.CmdRemoveLockObserver, tikvrpc.CmdPhysicalScanLock, tikvrpc.CmdStoreSafeTS, + tikvrpc.CmdLockWaitInfo, tikvrpc.CmdMvccGetByKey, tikvrpc.CmdMvccGetByStartTs, tikvrpc.CmdSplitRegion, + tikvrpc.CmdDebugGetRegionProperties, tikvrpc.CmdEmpty: + // Ignore those requests since now, since it is no business with TopSQL. + return nil, nil + case tikvrpc.CmdBatchCop, tikvrpc.CmdMPPTask, tikvrpc.CmdMPPConn, tikvrpc.CmdMPPCancel, tikvrpc.CmdMPPAlive: + // Ignore mpp requests. + return nil, nil + case tikvrpc.CmdResolveLock, tikvrpc.CmdCheckTxnStatus, tikvrpc.CmdPessimisticRollback: + // TODO: add resource tag for those request. https://github.com/pingcap/tidb/issues/33621 + return nil, nil + default: + return nil, errors.New("unknown request, check the new type RPC request here") + } +} + +func getStack() []byte { + const size = 1024 * 64 + buf := make([]byte, size) + stackSize := runtime.Stack(buf, false) + buf = buf[:stackSize] + return buf +} diff --git a/store/mockstore/unistore/tikv/dbreader/db_reader.go b/store/mockstore/unistore/tikv/dbreader/db_reader.go index 78ea3acb09e8c..474c7bb6b58d1 100644 --- a/store/mockstore/unistore/tikv/dbreader/db_reader.go +++ b/store/mockstore/unistore/tikv/dbreader/db_reader.go @@ -36,6 +36,7 @@ import ( "github.com/pingcap/badger/y" "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/mvcc" ) @@ -69,6 +70,7 @@ type DBReader struct { iter *badger.Iterator extraIter *badger.Iterator revIter *badger.Iterator + RcCheckTS bool } // GetMvccInfoByKey fills MvccInfo reading committed keys from db @@ -105,6 +107,9 @@ func (r *DBReader) GetMvccInfoByKey(key []byte, isRowKey bool, mvccInfo *kvrpcpb // Get gets a value with the key and start ts. func (r *DBReader) Get(key []byte, startTS uint64) ([]byte, error) { r.txn.SetReadTS(startTS) + if r.RcCheckTS { + r.txn.SetReadTS(math.MaxUint64) + } item, err := r.txn.Get(key) if err != nil && err != badger.ErrKeyNotFound { return nil, errors.Trace(err) @@ -112,6 +117,10 @@ func (r *DBReader) Get(key []byte, startTS uint64) ([]byte, error) { if item == nil { return nil, nil } + err = r.CheckWriteItemForRcCheckTSRead(startTS, item) + if err != nil { + return nil, errors.Trace(err) + } return item.Value() } @@ -152,6 +161,9 @@ type BatchGetFunc = func(key, value []byte, err error) // BatchGet batch gets keys. func (r *DBReader) BatchGet(keys [][]byte, startTS uint64, f BatchGetFunc) { r.txn.SetReadTS(startTS) + if r.RcCheckTS { + r.txn.SetReadTS(math.MaxUint64) + } items, err := r.txn.MultiGet(keys) if err != nil { for _, key := range keys { @@ -164,6 +176,9 @@ func (r *DBReader) BatchGet(keys [][]byte, startTS uint64, f BatchGetFunc) { var val []byte if item != nil { val, err = item.Value() + if err == nil { + err = r.CheckWriteItemForRcCheckTSRead(startTS, item) + } } f(key, val, err) } @@ -195,16 +210,23 @@ func exceedEndKey(current, endKey []byte) bool { // Scan scans the key range with the given ScanProcessor. func (r *DBReader) Scan(startKey, endKey []byte, limit int, startTS uint64, proc ScanProcessor) error { r.txn.SetReadTS(startTS) + if r.RcCheckTS { + r.txn.SetReadTS(math.MaxUint64) + } skipValue := proc.SkipValue() iter := r.GetIter() var cnt int + var err error for iter.Seek(startKey); iter.Valid(); iter.Next() { item := iter.Item() key := item.Key() if exceedEndKey(key, endKey) { break } - var err error + err = r.CheckWriteItemForRcCheckTSRead(startTS, item) + if err != nil { + return errors.Trace(err) + } if item.IsEmpty() { continue } @@ -253,6 +275,9 @@ func (r *DBReader) ReverseScan(startKey, endKey []byte, limit int, startTS uint6 skipValue := proc.SkipValue() iter := r.getReverseIter() r.txn.SetReadTS(startTS) + if r.RcCheckTS { + r.txn.SetReadTS(math.MaxUint64) + } var cnt int for iter.Seek(endKey); iter.Valid(); iter.Next() { item := iter.Item() @@ -264,6 +289,10 @@ func (r *DBReader) ReverseScan(startKey, endKey []byte, limit int, startTS uint6 continue } var err error + err = r.CheckWriteItemForRcCheckTSRead(startTS, item) + if err != nil { + return errors.Trace(err) + } if item.IsEmpty() { continue } @@ -289,6 +318,25 @@ func (r *DBReader) ReverseScan(startKey, endKey []byte, limit int, startTS uint6 return nil } +// CheckWriteItemForRcCheckTSRead checks the data version if `RcCheckTS` isolation level is used. +func (r *DBReader) CheckWriteItemForRcCheckTSRead(readTS uint64, item *badger.Item) error { + if item == nil { + return nil + } + if !r.RcCheckTS { + return nil + } + userMeta := mvcc.DBUserMeta(item.UserMeta()) + if userMeta.CommitTS() > readTS { + return &kverrors.ErrConflict{ + StartTS: readTS, + ConflictTS: userMeta.StartTS(), + ConflictCommitTS: userMeta.CommitTS(), + } + } + return nil +} + // GetTxn gets the *badger.Txn of the *DBReader. func (r *DBReader) GetTxn() *badger.Txn { return r.txn diff --git a/store/mockstore/unistore/tikv/deadlock.go b/store/mockstore/unistore/tikv/deadlock.go index da1851f66769e..90f0c5b226a56 100644 --- a/store/mockstore/unistore/tikv/deadlock.go +++ b/store/mockstore/unistore/tikv/deadlock.go @@ -26,6 +26,7 @@ import ( deadlockPb "github.com/pingcap/kvproto/pkg/deadlock" "github.com/pingcap/log" "github.com/pingcap/tidb/store/mockstore/unistore/pd" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/store/mockstore/unistore/util/lockwaiter" ) @@ -214,7 +215,7 @@ func (dt *DetectorClient) Detect(txnTs uint64, waitForTxnTs uint64, keyHash uint } // convertErrToResp converts `ErrDeadlock` to `DeadlockResponse` proto type -func convertErrToResp(errDeadlock *ErrDeadlock, txnTs, waitForTxnTs, keyHash uint64) *deadlockPb.DeadlockResponse { +func convertErrToResp(errDeadlock *kverrors.ErrDeadlock, txnTs, waitForTxnTs, keyHash uint64) *deadlockPb.DeadlockResponse { entry := deadlockPb.WaitForEntry{} entry.Txn = txnTs entry.WaitForTxn = waitForTxnTs diff --git a/store/mockstore/unistore/tikv/detector.go b/store/mockstore/unistore/tikv/detector.go index 3b8a636420813..a804ec4bfe27a 100644 --- a/store/mockstore/unistore/tikv/detector.go +++ b/store/mockstore/unistore/tikv/detector.go @@ -34,6 +34,7 @@ import ( deadlockpb "github.com/pingcap/kvproto/pkg/deadlock" "github.com/pingcap/log" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "go.uber.org/zap" ) @@ -81,7 +82,7 @@ func NewDetector(ttl time.Duration, urgentSize uint64, expireInterval time.Durat } // Detect detects deadlock for the sourceTxn on a locked key. -func (d *Detector) Detect(sourceTxn, waitForTxn, keyHash uint64, diagCtx diagnosticContext) *ErrDeadlock { +func (d *Detector) Detect(sourceTxn, waitForTxn, keyHash uint64, diagCtx diagnosticContext) *kverrors.ErrDeadlock { d.lock.Lock() nowTime := time.Now() d.activeExpire(nowTime) @@ -107,7 +108,7 @@ func (d *Detector) Detect(sourceTxn, waitForTxn, keyHash uint64, diagCtx diagnos return err } -func (d *Detector) doDetect(nowTime time.Time, sourceTxn, waitForTxn uint64) *ErrDeadlock { +func (d *Detector) doDetect(nowTime time.Time, sourceTxn, waitForTxn uint64) *kverrors.ErrDeadlock { val := d.waitForMap[waitForTxn] if val == nil { return nil @@ -123,7 +124,7 @@ func (d *Detector) doDetect(nowTime time.Time, sourceTxn, waitForTxn uint64) *Er continue } if keyHashPair.txn == sourceTxn { - return &ErrDeadlock{DeadlockKeyHash: keyHashPair.keyHash, + return &kverrors.ErrDeadlock{DeadlockKeyHash: keyHashPair.keyHash, WaitChain: []*deadlockpb.WaitForEntry{ { Txn: waitForTxn, diff --git a/store/mockstore/unistore/tikv/detector_test.go b/store/mockstore/unistore/tikv/detector_test.go index e44b5ca1fc0f1..d91c40406063a 100644 --- a/store/mockstore/unistore/tikv/detector_test.go +++ b/store/mockstore/unistore/tikv/detector_test.go @@ -53,20 +53,20 @@ func TestDeadlock(t *testing.T) { expireInterval := 100 * time.Millisecond urgentSize := uint64(1) detector := NewDetector(ttl, urgentSize, expireInterval) - err := detector.Detect(1, 2, 100, makeDiagCtx("k1", "tag1")) - require.Nil(t, err) + result := detector.Detect(1, 2, 100, makeDiagCtx("k1", "tag1")) + require.Nil(t, result) require.Equal(t, uint64(1), detector.totalSize) - err = detector.Detect(2, 3, 200, makeDiagCtx("k2", "tag2")) - require.Nil(t, err) + result = detector.Detect(2, 3, 200, makeDiagCtx("k2", "tag2")) + require.Nil(t, result) require.Equal(t, uint64(2), detector.totalSize) - err = detector.Detect(3, 1, 300, makeDiagCtx("k3", "tag3")) - require.NotNil(t, err) - require.Equal(t, "deadlock", err.Error()) - require.Equal(t, 3, len(err.WaitChain)) + result = detector.Detect(3, 1, 300, makeDiagCtx("k3", "tag3")) + require.NotNil(t, result) + require.Equal(t, "deadlock", result.Error()) + require.Equal(t, 3, len(result.WaitChain)) // The order of entries in the wait chain is specific: each item is waiting for the next one. - checkWaitChainEntry(err.WaitChain[0], 1, 2, "k1", "tag1") - checkWaitChainEntry(err.WaitChain[1], 2, 3, "k2", "tag2") - checkWaitChainEntry(err.WaitChain[2], 3, 1, "k3", "tag3") + checkWaitChainEntry(result.WaitChain[0], 1, 2, "k1", "tag1") + checkWaitChainEntry(result.WaitChain[1], 2, 3, "k2", "tag2") + checkWaitChainEntry(result.WaitChain[2], 3, 1, "k3", "tag3") require.Equal(t, uint64(2), detector.totalSize) detector.CleanUp(2) @@ -76,21 +76,21 @@ func TestDeadlock(t *testing.T) { // After cycle is broken, no deadlock now. diagCtx := diagnosticContext{} - err = detector.Detect(3, 1, 300, diagCtx) - require.Nil(t, err) + result = detector.Detect(3, 1, 300, diagCtx) + require.Nil(t, result) list3 := detector.waitForMap[3] require.Equal(t, 1, list3.txns.Len()) require.Equal(t, uint64(2), detector.totalSize) // Different keyHash grows the list. - err = detector.Detect(3, 1, 400, diagCtx) - require.Nil(t, err) + result = detector.Detect(3, 1, 400, diagCtx) + require.Nil(t, result) require.Equal(t, 2, list3.txns.Len()) require.Equal(t, uint64(3), detector.totalSize) // Same waitFor and key hash doesn't grow the list. - err = detector.Detect(3, 1, 400, diagCtx) - require.Nil(t, err) + result = detector.Detect(3, 1, 400, diagCtx) + require.Nil(t, result) require.Equal(t, 2, list3.txns.Len()) require.Equal(t, uint64(3), detector.totalSize) @@ -104,16 +104,16 @@ func TestDeadlock(t *testing.T) { // after 100ms, all entries expired, detect non exist edges time.Sleep(100 * time.Millisecond) - err = detector.Detect(100, 200, 100, diagCtx) - require.Nil(t, err) + result = detector.Detect(100, 200, 100, diagCtx) + require.Nil(t, result) require.Equal(t, uint64(1), detector.totalSize) require.Equal(t, 1, len(detector.waitForMap)) // expired entry should not report deadlock, detect will remove this entry // not dependent on expire check interval time.Sleep(60 * time.Millisecond) - err = detector.Detect(200, 100, 200, diagCtx) - require.Nil(t, err) + result = detector.Detect(200, 100, 200, diagCtx) + require.Nil(t, result) require.Equal(t, uint64(1), detector.totalSize) require.Equal(t, 1, len(detector.waitForMap)) } diff --git a/store/mockstore/unistore/tikv/errors.go b/store/mockstore/unistore/tikv/kverrors/errors.go similarity index 84% rename from store/mockstore/unistore/tikv/errors.go rename to store/mockstore/unistore/tikv/kverrors/errors.go index 6043f2fd7a753..7081b4a7f80c8 100644 --- a/store/mockstore/unistore/tikv/errors.go +++ b/store/mockstore/unistore/tikv/kverrors/errors.go @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tikv +package kverrors import ( + "encoding/hex" "fmt" deadlockpb "github.com/pingcap/kvproto/pkg/deadlock" @@ -63,11 +64,11 @@ var ( // ErrInvalidOp is returned when an operation cannot be completed. type ErrInvalidOp struct { - op kvrpcpb.Op + Op kvrpcpb.Op } func (e ErrInvalidOp) Error() string { - return fmt.Sprintf("invalid op: %s", e.op.String()) + return fmt.Sprintf("invalid op: %s", e.Op.String()) } // ErrAlreadyCommitted is returned specially when client tries to rollback a @@ -132,3 +133,17 @@ type ErrTxnNotFound struct { func (e *ErrTxnNotFound) Error() string { return "txn not found" } + +// ErrAssertionFailed is returned if any assertion fails on a transaction request. +type ErrAssertionFailed struct { + StartTS uint64 + Key []byte + Assertion kvrpcpb.Assertion + ExistingStartTS uint64 + ExistingCommitTS uint64 +} + +func (e *ErrAssertionFailed) Error() string { + return fmt.Sprintf("AssertionFailed { StartTS: %v, Key: %v, Assertion: %v, ExistingStartTS: %v, ExistingCommitTS: %v }", + e.StartTS, hex.EncodeToString(e.Key), e.Assertion.String(), e.ExistingStartTS, e.ExistingCommitTS) +} diff --git a/store/mockstore/unistore/tikv/main_test.go b/store/mockstore/unistore/tikv/main_test.go index 5bc57f47c8321..94e4abe33e2e4 100644 --- a/store/mockstore/unistore/tikv/main_test.go +++ b/store/mockstore/unistore/tikv/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/mockstore/unistore/tikv/mock_region.go b/store/mockstore/unistore/tikv/mock_region.go index 9233447cf921d..0ae6b57059cbf 100644 --- a/store/mockstore/unistore/tikv/mock_region.go +++ b/store/mockstore/unistore/tikv/mock_region.go @@ -242,7 +242,7 @@ func (rm *MockRegionManager) GetRegion(id uint64) *metapb.Region { } // GetRegionByKey gets a region by the key. -func (rm *MockRegionManager) GetRegionByKey(key []byte) (region *metapb.Region, peer *metapb.Peer) { +func (rm *MockRegionManager) GetRegionByKey(key []byte) (region *metapb.Region, peer *metapb.Peer, buckets *metapb.Buckets) { rm.mu.RLock() defer rm.mu.RUnlock() rm.sortedRegions.AscendGreaterOrEqual(newBtreeSearchItem(key), func(item btree.Item) bool { @@ -254,9 +254,9 @@ func (rm *MockRegionManager) GetRegionByKey(key []byte) (region *metapb.Region, return false }) if region == nil || !rm.regionContainsKey(region, key) { - return nil, nil + return nil, nil, nil } - return proto.Clone(region).(*metapb.Region), proto.Clone(region.Peers[0]).(*metapb.Peer) + return proto.Clone(region).(*metapb.Region), proto.Clone(region.Peers[0]).(*metapb.Peer), nil } // GetRegionByEndKey gets a region by the end key. @@ -356,11 +356,11 @@ func (rm *MockRegionManager) Split(regionID, newRegionID uint64, key []byte, pee // SplitRaw splits a Region at the key (not encoded) and creates new Region. func (rm *MockRegionManager) SplitRaw(regionID, newRegionID uint64, rawKey []byte, peerIDs []uint64, leaderPeerID uint64) *metapb.Region { - new, err := rm.split(regionID, newRegionID, rawKey, peerIDs) + r, err := rm.split(regionID, newRegionID, rawKey, peerIDs) if err != nil { panic(err) } - return proto.Clone(new).(*metapb.Region) + return proto.Clone(r).(*metapb.Region) } // SplitTable evenly splits the data in table into count regions. @@ -720,13 +720,13 @@ func (pd *MockPD) GetStore(ctx context.Context, storeID uint64) (*metapb.Store, } // GetRegion implements gRPC PDServer. -func (pd *MockPD) GetRegion(ctx context.Context, key []byte) (*pdclient.Region, error) { - r, p := pd.rm.GetRegionByKey(key) - return &pdclient.Region{Meta: r, Leader: p}, nil +func (pd *MockPD) GetRegion(ctx context.Context, key []byte, opts ...pdclient.GetRegionOption) (*pdclient.Region, error) { + r, p, b := pd.rm.GetRegionByKey(key) + return &pdclient.Region{Meta: r, Leader: p, Buckets: b}, nil } // GetRegionByID implements gRPC PDServer. -func (pd *MockPD) GetRegionByID(ctx context.Context, regionID uint64) (*pdclient.Region, error) { +func (pd *MockPD) GetRegionByID(ctx context.Context, regionID uint64, opts ...pdclient.GetRegionOption) (*pdclient.Region, error) { pd.rm.mu.RLock() defer pd.rm.mu.RUnlock() @@ -813,7 +813,7 @@ func GetTS() (int64, int64) { } // GetPrevRegion gets the previous region and its leader Peer of the region where the key is located. -func (pd *MockPD) GetPrevRegion(ctx context.Context, key []byte) (*pdclient.Region, error) { +func (pd *MockPD) GetPrevRegion(ctx context.Context, key []byte, opts ...pdclient.GetRegionOption) (*pdclient.Region, error) { r, p := pd.rm.GetRegionByEndKey(key) return &pdclient.Region{Meta: r, Leader: p}, nil } diff --git a/store/mockstore/unistore/tikv/mvcc.go b/store/mockstore/unistore/tikv/mvcc.go index bba8d53409352..8d8c7ed3363f7 100644 --- a/store/mockstore/unistore/tikv/mvcc.go +++ b/store/mockstore/unistore/tikv/mvcc.go @@ -36,6 +36,7 @@ import ( "github.com/pingcap/tidb/store/mockstore/unistore/lockstore" "github.com/pingcap/tidb/store/mockstore/unistore/pd" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/mvcc" "github.com/pingcap/tidb/store/mockstore/unistore/util/lockwaiter" "github.com/pingcap/tidb/types" @@ -122,7 +123,7 @@ type lockEntryHdr struct { func (store *MVCCStore) dumpMemLocks() error { tmpFileName := store.dir + "/lock_store.tmp" - f, err := os.OpenFile(tmpFileName, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666) + f, err := os.OpenFile(tmpFileName, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600) if err != nil { return errors.Trace(err) } @@ -260,7 +261,7 @@ func (store *MVCCStore) PessimisticLock(reqCtx *requestCtx, req *kvrpcpb.Pessimi if bytes.Equal(m.Key, req.PrimaryLock) { txnStatus := store.checkExtraTxnStatus(reqCtx, m.Key, startTS) if txnStatus.isRollback { - return nil, ErrAlreadyRollback + return nil, kverrors.ErrAlreadyRollback } else if txnStatus.isOpLockCommitted() { dup = true break @@ -293,17 +294,23 @@ func (store *MVCCStore) PessimisticLock(reqCtx *requestCtx, req *kvrpcpb.Pessimi resp.Value = val resp.CommitTs = dbMeta.CommitTS() } - if req.ReturnValues { + if req.ReturnValues || req.CheckExistence { for _, item := range items { if item == nil { - resp.Values = append(resp.Values, nil) + if req.ReturnValues { + resp.Values = append(resp.Values, nil) + } + resp.NotFounds = append(resp.NotFounds, true) continue } val, err1 := item.ValueCopy(nil) if err1 != nil { return nil, err1 } - resp.Values = append(resp.Values, val) + if req.ReturnValues { + resp.Values = append(resp.Values, val) + } + resp.NotFounds = append(resp.NotFounds, len(val) == 0) } } return nil, err @@ -476,7 +483,7 @@ func (store *MVCCStore) CheckTxnStatus(reqCtx *requestCtx, err = store.dbWriter.Write(batch) return TxnStatus{0, kvrpcpb.Action_LockNotExistRollback, nil}, nil } - return TxnStatus{0, kvrpcpb.Action_NoAction, nil}, &ErrTxnNotFound{ + return TxnStatus{0, kvrpcpb.Action_NoAction, nil}, &kverrors.ErrTxnNotFound{ PrimaryKey: req.PrimaryKey, StartTS: req.LockTs, } @@ -545,7 +552,7 @@ func (store *MVCCStore) normalizeWaitTime(lockWaitTime int64) time.Duration { } func (store *MVCCStore) handleCheckPessimisticErr(startTS uint64, err error, isFirstLock bool, lockWaitTime int64, key []byte, resourceGroupTag []byte) (*lockwaiter.Waiter, error) { - if locked, ok := err.(*ErrLocked); ok { + if locked, ok := err.(*kverrors.ErrLocked); ok { if lockWaitTime != lockwaiter.LockNoWait { keyHash := farm.Fingerprint64(locked.Key) waitTimeDuration := store.normalizeWaitTime(lockWaitTime) @@ -567,7 +574,7 @@ func (store *MVCCStore) buildPessimisticLock(m *kvrpcpb.Mutation, item *badger.I userMeta := mvcc.DBUserMeta(item.UserMeta()) if !req.Force { if userMeta.CommitTS() > req.ForUpdateTs { - return nil, &ErrConflict{ + return nil, &kverrors.ErrConflict{ StartTS: req.StartVersion, ConflictTS: userMeta.StartTS(), ConflictCommitTS: userMeta.CommitTS(), @@ -576,7 +583,7 @@ func (store *MVCCStore) buildPessimisticLock(m *kvrpcpb.Mutation, item *badger.I } } if m.Assertion == kvrpcpb.Assertion_NotExist && !item.IsEmpty() { - return nil, &ErrKeyAlreadyExists{Key: m.Key} + return nil, &kverrors.ErrKeyAlreadyExists{Key: m.Key} } } lock := &mvcc.Lock{ @@ -638,7 +645,7 @@ func (store *MVCCStore) prewriteOptimistic(reqCtx *requestCtx, mutations []*kvrp if bytes.Equal(m.Key, req.PrimaryLock) { status := store.checkExtraTxnStatus(reqCtx, m.Key, req.StartVersion) if status.isRollback { - return ErrAlreadyRollback + return kverrors.ErrAlreadyRollback } if status.isOpLockCommitted() { // duplicated command @@ -655,7 +662,7 @@ func (store *MVCCStore) prewriteOptimistic(reqCtx *requestCtx, mutations []*kvrp if item != nil { userMeta := mvcc.DBUserMeta(item.UserMeta()) if userMeta.CommitTS() > startTS { - return &ErrConflict{ + return &kverrors.ErrConflict{ StartTS: startTS, ConflictTS: userMeta.StartTS(), ConflictCommitTS: userMeta.CommitTS(), @@ -671,7 +678,7 @@ func (store *MVCCStore) prewriteOptimistic(reqCtx *requestCtx, mutations []*kvrp return err } if len(val) > 0 { - return &ErrKeyAlreadyExists{Key: m.Key} + return &kverrors.ErrKeyAlreadyExists{Key: m.Key} } } continue @@ -685,7 +692,7 @@ func (store *MVCCStore) prewritePessimistic(reqCtx *requestCtx, mutations []*kvr startTS := req.StartVersion for i, m := range mutations { if m.Op == kvrpcpb.Op_CheckNotExists { - return ErrInvalidOp{op: m.Op} + return kverrors.ErrInvalidOp{Op: m.Op} } lock := store.getLock(reqCtx, m.Key) isPessimisticLock := len(req.IsPessimisticLock) > 0 && req.IsPessimisticLock[i] @@ -711,7 +718,7 @@ func (store *MVCCStore) prewritePessimistic(reqCtx *requestCtx, mutations []*kvr // Safe to set TTL to zero because the transaction of the lock is committed // or rollbacked or must be rollbacked. lock.TTL = 0 - return BuildLockErr(m.Key, lock) + return kverrors.BuildLockErr(m.Key, lock) } if lockMatch { // Duplicate command. @@ -853,11 +860,41 @@ func (store *MVCCStore) buildPrewriteLock(reqCtx *requestCtx, m *kvrpcpb.Mutatio Value: m.Value, Secondaries: req.Secondaries, } + // Note that this is not fully consistent with TiKV. TiKV doesn't always get the value from Write CF. In + // AssertionLevel_Fast, TiKV skips checking assertion if Write CF is not read, in order not to harm the performance. + // However, unistore can always check it. It's better not to assume the store's behavior about assertion when the + // mode is set to AssertionLevel_Fast. + if req.AssertionLevel != kvrpcpb.AssertionLevel_Off { + if item == nil || item.IsEmpty() { + if m.Assertion == kvrpcpb.Assertion_Exist { + log.Error("ASSERTION FAIL!!! non-exist for must exist key", zap.Stringer("mutation", m)) + return nil, &kverrors.ErrAssertionFailed{ + StartTS: req.StartVersion, + Key: m.Key, + Assertion: m.Assertion, + ExistingStartTS: 0, + ExistingCommitTS: 0, + } + } + } else { + if m.Assertion == kvrpcpb.Assertion_NotExist { + log.Error("ASSERTION FAIL!!! exist for must non-exist key", zap.Stringer("mutation", m)) + userMeta := mvcc.DBUserMeta(item.UserMeta()) + return nil, &kverrors.ErrAssertionFailed{ + StartTS: req.StartVersion, + Key: m.Key, + Assertion: m.Assertion, + ExistingStartTS: userMeta.StartTS(), + ExistingCommitTS: userMeta.CommitTS(), + } + } + } + } var err error lock.Op = uint8(m.Op) if lock.Op == uint8(kvrpcpb.Op_Insert) { if item != nil && item.ValueSize() > 0 { - return nil, &ErrKeyAlreadyExists{Key: m.Key} + return nil, &kverrors.ErrKeyAlreadyExists{Key: m.Key} } lock.Op = uint8(kvrpcpb.Op_Put) } @@ -898,7 +935,7 @@ func (store *MVCCStore) checkConflictInLockStore( // Same ts, no need to overwrite. return &lock, nil } - return nil, BuildLockErr(mutation.Key, &lock) + return nil, kverrors.BuildLockErr(mutation.Key, &lock) } const maxSystemTS uint64 = math.MaxUint64 @@ -924,11 +961,11 @@ func (store *MVCCStore) Commit(req *requestCtx, keys [][]byte, startTS, commitTS if len(buf) == 0 { // We never commit partial keys in Commit request, so if one lock is not found, // the others keys must not be found too. - lockErr = ErrLockNotFound + lockErr = kverrors.ErrLockNotFound } else { lock = mvcc.DecodeLock(buf) if lock.StartTS != startTS { - lockErr = ErrReplaced + lockErr = kverrors.ErrReplaced } } if lockErr != nil { @@ -945,7 +982,7 @@ func (store *MVCCStore) Commit(req *requestCtx, keys [][]byte, startTS, commitTS if commitTS < lock.MinCommitTS { log.Info("trying to commit with smaller commitTs than minCommitTs", zap.Uint64("commit ts", commitTS), zap.Uint64("min commit ts", lock.MinCommitTS), zap.Binary("key", key)) - return &ErrCommitExpire{ + return &kverrors.ErrCommitExpire{ StartTs: startTS, CommitTs: commitTS, MinCommitTs: lock.MinCommitTS, @@ -977,14 +1014,14 @@ func (store *MVCCStore) handleLockNotFound(reqCtx *requestCtx, key []byte, start return errors.Trace(err) } if item == nil { - return ErrLockNotFound + return kverrors.ErrLockNotFound } userMeta := mvcc.DBUserMeta(item.UserMeta()) if userMeta.StartTS() == startTS { // Already committed. return nil } - return ErrLockNotFound + return kverrors.ErrLockNotFound } const ( @@ -1044,7 +1081,7 @@ func (store *MVCCStore) rollbackKeyReadLock(reqCtx *requestCtx, batch mvcc.Write } if lock.StartTS == startTS { if currentTs > 0 && uint64(oracle.ExtractPhysical(lock.StartTS))+uint64(lock.TTL) >= uint64(oracle.ExtractPhysical(currentTs)) { - return rollbackStatusLocked, BuildLockErr(key, &lock) + return rollbackStatusLocked, kverrors.BuildLockErr(key, &lock) } // We can not simply delete the lock because the prewrite may be sent multiple times. // To prevent that we update it a rollback lock. @@ -1063,7 +1100,7 @@ func (store *MVCCStore) rollbackKeyReadDB(req *requestCtx, batch mvcc.WriteBatch return err } if commitTS != 0 { - return ErrAlreadyCommitted(commitTS) + return kverrors.ErrAlreadyCommitted(commitTS) } // commit not found, rollback this key batch.Rollback(key, false) @@ -1124,11 +1161,44 @@ func checkLock(lock mvcc.Lock, key []byte, startTS uint64, resolved []uint64, co if inTSSet(lock.StartTS, committed) { return &LockPair{safeCopy(key), &lock}, nil } - return nil, BuildLockErr(safeCopy(key), &lock) + return nil, kverrors.BuildLockErr(safeCopy(key), &lock) } return nil, nil } +// checkLockForRcCheckTS checks the lock for `RcCheckTS` isolation level in transaction read. +func checkLockForRcCheckTS(lock mvcc.Lock, key []byte, startTS uint64, resolved []uint64) error { + if inTSSet(lock.StartTS, resolved) { + return nil + } + isWriteLock := lock.Op == uint8(kvrpcpb.Op_Put) || lock.Op == uint8(kvrpcpb.Op_Del) + if !isWriteLock { + return nil + } + return &kverrors.ErrConflict{ + StartTS: startTS, + ConflictTS: lock.StartTS, + Key: safeCopy(key), + } +} + +// CheckKeysLockForRcCheckTS is used to check version timestamp if `RcCheckTS` isolation level is used. +func (store *MVCCStore) CheckKeysLockForRcCheckTS(startTS uint64, resolved []uint64, keys ...[]byte) error { + var buf []byte + for _, key := range keys { + buf = store.lockStore.Get(key, buf) + if len(buf) == 0 { + continue + } + lock := mvcc.DecodeLock(buf) + err := checkLockForRcCheckTS(lock, key, startTS, resolved) + if err != nil { + return err + } + } + return nil +} + // CheckKeysLock implements the MVCCStore interface. func (store *MVCCStore) CheckKeysLock(startTS uint64, resolved, committed []uint64, keys ...[]byte) ([]*LockPair, error) { var buf []byte @@ -1186,7 +1256,7 @@ func (store *MVCCStore) Cleanup(reqCtx *requestCtx, key []byte, startTS, current } rbStatus := store.checkExtraTxnStatus(reqCtx, key, startTS) if rbStatus.isOpLockCommitted() { - return ErrAlreadyCommitted(rbStatus.commitTS) + return kverrors.ErrAlreadyCommitted(rbStatus.commitTS) } } err = store.dbWriter.Write(batch) @@ -1410,33 +1480,58 @@ func (store *MVCCStore) DeleteFileInRange(start, end []byte) { // Get implements the MVCCStore interface. func (store *MVCCStore) Get(reqCtx *requestCtx, key []byte, version uint64) ([]byte, error) { - lockPairs, err := store.CheckKeysLock(version, reqCtx.rpcCtx.ResolvedLocks, reqCtx.rpcCtx.CommittedLocks, key) - if err != nil { - return nil, err - } - if len(lockPairs) != 0 { - return getValueFromLock(lockPairs[0].lock), nil + if reqCtx.isSnapshotIsolation() { + lockPairs, err := store.CheckKeysLock(version, reqCtx.rpcCtx.ResolvedLocks, reqCtx.rpcCtx.CommittedLocks, key) + if err != nil { + return nil, err + } + if len(lockPairs) != 0 { + return getValueFromLock(lockPairs[0].lock), nil + } + } else if reqCtx.isRcCheckTSIsolationLevel() { + err := store.CheckKeysLockForRcCheckTS(version, reqCtx.rpcCtx.ResolvedLocks, key) + if err != nil { + return nil, err + } } val, err := reqCtx.getDBReader().Get(key, version) + if val == nil { + return nil, err + } return safeCopy(val), err } // BatchGet implements the MVCCStore interface. func (store *MVCCStore) BatchGet(reqCtx *requestCtx, keys [][]byte, version uint64) []*kvrpcpb.KvPair { pairs := make([]*kvrpcpb.KvPair, 0, len(keys)) - remain := make([][]byte, 0, len(keys)) - for _, key := range keys { - lockPairs, err := store.CheckKeysLock(version, reqCtx.rpcCtx.ResolvedLocks, reqCtx.rpcCtx.CommittedLocks, key) - if err != nil { - pairs = append(pairs, &kvrpcpb.KvPair{Key: key, Error: convertToKeyError(err)}) - } else if len(lockPairs) != 0 { - value := getValueFromLock(lockPairs[0].lock) - if value != nil { - pairs = append(pairs, &kvrpcpb.KvPair{Key: key, Value: value}) + var remain [][]byte + if reqCtx.isSnapshotIsolation() { + remain = make([][]byte, 0, len(keys)) + for _, key := range keys { + lockPairs, err := store.CheckKeysLock(version, reqCtx.rpcCtx.ResolvedLocks, reqCtx.rpcCtx.CommittedLocks, key) + if err != nil { + pairs = append(pairs, &kvrpcpb.KvPair{Key: key, Error: convertToKeyError(err)}) + } else if len(lockPairs) != 0 { + value := getValueFromLock(lockPairs[0].lock) + if value != nil { + pairs = append(pairs, &kvrpcpb.KvPair{Key: key, Value: value}) + } + } else { + remain = append(remain, key) + } + } + } else if reqCtx.isRcCheckTSIsolationLevel() { + remain = make([][]byte, 0, len(keys)) + for _, key := range keys { + err := store.CheckKeysLockForRcCheckTS(version, reqCtx.rpcCtx.ResolvedLocks, key) + if err != nil { + pairs = append(pairs, &kvrpcpb.KvPair{Key: key, Error: convertToKeyError(err)}) + } else { + remain = append(remain, key) } - } else { - remain = append(remain, key) } + } else { + remain = keys } batchGetFunc := func(key, value []byte, err error) { if len(value) != 0 { @@ -1451,7 +1546,8 @@ func (store *MVCCStore) BatchGet(reqCtx *requestCtx, keys [][]byte, version uint return pairs } -func (store *MVCCStore) collectRangeLock(startTS uint64, startKey, endKey []byte, resolved, committed []uint64) []*kvrpcpb.KvPair { +func (store *MVCCStore) collectRangeLock(startTS uint64, startKey, endKey []byte, resolved, committed []uint64, + isolationLEvel kvrpcpb.IsolationLevel) []*kvrpcpb.KvPair { var pairs []*kvrpcpb.KvPair it := store.lockStore.NewIterator() for it.Seek(startKey); it.Valid(); it.Next() { @@ -1459,18 +1555,28 @@ func (store *MVCCStore) collectRangeLock(startTS uint64, startKey, endKey []byte break } lock := mvcc.DecodeLock(it.Value()) - lockPair, err := checkLock(lock, it.Key(), startTS, resolved, committed) - if lockPair != nil { - pairs = append(pairs, &kvrpcpb.KvPair{ - Key: lockPair.key, - // deleted key's value is nil - Value: getValueFromLock(lockPair.lock), - }) - } else if err != nil { - pairs = append(pairs, &kvrpcpb.KvPair{ - Error: convertToKeyError(err), - Key: safeCopy(it.Key()), - }) + if isolationLEvel == kvrpcpb.IsolationLevel_SI { + lockPair, err := checkLock(lock, it.Key(), startTS, resolved, committed) + if lockPair != nil { + pairs = append(pairs, &kvrpcpb.KvPair{ + Key: lockPair.key, + // deleted key's value is nil + Value: getValueFromLock(lockPair.lock), + }) + } else if err != nil { + pairs = append(pairs, &kvrpcpb.KvPair{ + Error: convertToKeyError(err), + Key: safeCopy(it.Key()), + }) + } + } else if isolationLEvel == kvrpcpb.IsolationLevel_RCCheckTS { + err := checkLockForRcCheckTS(lock, it.Key(), startTS, resolved) + if err != nil { + pairs = append(pairs, &kvrpcpb.KvPair{ + Error: convertToKeyError(err), + Key: safeCopy(it.Key()), + }) + } } } return pairs @@ -1532,7 +1638,15 @@ func (store *MVCCStore) Scan(reqCtx *requestCtx, req *kvrpcpb.ScanRequest) []*kv var lockPairs []*kvrpcpb.KvPair limit := req.GetLimit() if req.SampleStep == 0 { - lockPairs = store.collectRangeLock(req.GetVersion(), startKey, endKey, reqCtx.rpcCtx.ResolvedLocks, reqCtx.rpcCtx.CommittedLocks) + if reqCtx.isSnapshotIsolation() || reqCtx.isRcCheckTSIsolationLevel() { + if bytes.Compare(startKey, endKey) <= 0 { + lockPairs = store.collectRangeLock(req.GetVersion(), startKey, endKey, reqCtx.rpcCtx.ResolvedLocks, + reqCtx.rpcCtx.CommittedLocks, reqCtx.rpcCtx.IsolationLevel) + } else { + lockPairs = store.collectRangeLock(req.GetVersion(), endKey, startKey, reqCtx.rpcCtx.ResolvedLocks, + reqCtx.rpcCtx.CommittedLocks, reqCtx.rpcCtx.IsolationLevel) + } + } } else { limit = req.SampleStep * limit } diff --git a/store/mockstore/unistore/tikv/mvcc_test.go b/store/mockstore/unistore/tikv/mvcc_test.go index b08162437ab6c..3b11e5fd4d713 100644 --- a/store/mockstore/unistore/tikv/mvcc_test.go +++ b/store/mockstore/unistore/tikv/mvcc_test.go @@ -25,10 +25,12 @@ import ( "github.com/pingcap/badger" "github.com/pingcap/badger/y" + "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/store/mockstore/unistore/config" "github.com/pingcap/tidb/store/mockstore/unistore/lockstore" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/mvcc" "github.com/pingcap/tidb/store/mockstore/unistore/util/lockwaiter" "github.com/stretchr/testify/require" @@ -50,20 +52,23 @@ func (ts *TestStore) newReqCtx() *requestCtx { } func (ts *TestStore) newReqCtxWithKeys(rawStartKey, rawEndKey []byte) *requestCtx { + epoch := &metapb.RegionEpoch{ConfVer: 1, Version: 1} + peer := &metapb.Peer{Id: 1, StoreId: 1, Role: metapb.PeerRole_Voter} return &requestCtx{ regCtx: ®ionCtx{ + meta: &metapb.Region{ + Id: 1, + RegionEpoch: epoch, + Peers: []*metapb.Peer{peer}, + }, latches: newLatches(), rawStartKey: rawStartKey, rawEndKey: rawEndKey, }, rpcCtx: &kvrpcpb.Context{ RegionId: 1, - RegionEpoch: &metapb.RegionEpoch{Version: 1, ConfVer: 1}, - Peer: &metapb.Peer{ - Id: 1, - StoreId: 1, - Role: metapb.PeerRole_Voter, - }, + RegionEpoch: epoch, + Peer: peer, }, svr: ts.Svr, } @@ -87,10 +92,8 @@ func CreateTestDB(dbPath, LogPath string) (*badger.DB, error) { } func NewTestStore(dbPrefix string, logPrefix string, t *testing.T) (*TestStore, func()) { - dbPath, err := os.MkdirTemp("", dbPrefix) - require.NoError(t, err) - LogPath, err := os.MkdirTemp("", logPrefix) - require.NoError(t, err) + dbPath := t.TempDir() + LogPath := t.TempDir() safePoint := &SafePoint{} db, err := CreateTestDB(dbPath, LogPath) require.NoError(t, err) @@ -153,32 +156,54 @@ func PessimisticLock(pk []byte, key []byte, startTs uint64, lockTTL uint64, forU // PrewriteOptimistic raises optimistic prewrite requests on store func PrewriteOptimistic(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, minCommitTs uint64, useAsyncCommit bool, secondaries [][]byte, store *TestStore) error { + return PrewriteOptimisticWithAssertion(pk, key, value, startTs, lockTTL, minCommitTs, useAsyncCommit, secondaries, + kvrpcpb.Assertion_None, kvrpcpb.AssertionLevel_Off, store) +} + +// PrewriteOptimisticWithAssertion raises optimistic prewrite requests on store, with specified assertion config +func PrewriteOptimisticWithAssertion(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, + minCommitTs uint64, useAsyncCommit bool, secondaries [][]byte, assertion kvrpcpb.Assertion, + assertionLevel kvrpcpb.AssertionLevel, store *TestStore) error { op := kvrpcpb.Op_Put if value == nil { op = kvrpcpb.Op_Del } + mutation := newMutation(op, key, value) + mutation.Assertion = assertion prewriteReq := &kvrpcpb.PrewriteRequest{ - Mutations: []*kvrpcpb.Mutation{newMutation(op, key, value)}, + Mutations: []*kvrpcpb.Mutation{mutation}, PrimaryLock: pk, StartVersion: startTs, LockTtl: lockTTL, MinCommitTs: minCommitTs, UseAsyncCommit: useAsyncCommit, Secondaries: secondaries, + AssertionLevel: assertionLevel, } return store.MvccStore.prewriteOptimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) } -// PrewritePessimistic raises pessmistic prewrite requests +// PrewritePessimistic raises pessimistic prewrite requests func PrewritePessimistic(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, isPessimisticLock []bool, forUpdateTs uint64, store *TestStore) error { + return PrewritePessimisticWithAssertion(pk, key, value, startTs, lockTTL, isPessimisticLock, forUpdateTs, + kvrpcpb.Assertion_None, kvrpcpb.AssertionLevel_Off, store) +} + +// PrewritePessimisticWithAssertion raises pessimistic prewrite requests, with specified assertion config +func PrewritePessimisticWithAssertion(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, + isPessimisticLock []bool, forUpdateTs uint64, assertion kvrpcpb.Assertion, assertionLevel kvrpcpb.AssertionLevel, + store *TestStore) error { + mutation := newMutation(kvrpcpb.Op_Put, key, value) + mutation.Assertion = assertion prewriteReq := &kvrpcpb.PrewriteRequest{ - Mutations: []*kvrpcpb.Mutation{newMutation(kvrpcpb.Op_Put, key, value)}, + Mutations: []*kvrpcpb.Mutation{mutation}, PrimaryLock: pk, StartVersion: startTs, LockTtl: lockTTL, IsPessimisticLock: isPessimisticLock, ForUpdateTs: forUpdateTs, + AssertionLevel: assertionLevel, } return store.MvccStore.prewritePessimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) } @@ -243,7 +268,7 @@ func MustPrewritePut(pk, key []byte, val []byte, startTs uint64, store *TestStor func MustPrewritePutLockErr(pk, key []byte, val []byte, startTs uint64, store *TestStore) { err := PrewriteOptimistic(pk, key, val, startTs, lockTTL, startTs, false, [][]byte{}, store) require.Error(store.t, err) - lockedErr := err.(*ErrLocked) + lockedErr := err.(*kverrors.ErrLocked) require.NotNil(store.t, lockedErr) } @@ -274,7 +299,7 @@ func MustPrewriteInsertAlreadyExists(pk, key []byte, val []byte, startTs uint64, } err := store.MvccStore.prewriteOptimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) require.Error(store.t, err) - existErr := err.(*ErrKeyAlreadyExists) + existErr := err.(*kverrors.ErrKeyAlreadyExists) require.NotNil(store.t, existErr) } @@ -288,7 +313,7 @@ func MustPrewriteOpCheckExistAlreadyExist(pk, key []byte, startTs uint64, store } err := store.MvccStore.prewriteOptimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) require.Error(store.t, err) - existErr := err.(*ErrKeyAlreadyExists) + existErr := err.(*kverrors.ErrKeyAlreadyExists) require.NotNil(store.t, existErr) } @@ -483,8 +508,8 @@ func MustGetRollback(key []byte, ts uint64, store *TestStore) { } func TestBasicOptimistic(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() key1 := []byte("key1") val1 := []byte("val1") @@ -498,8 +523,8 @@ func TestBasicOptimistic(t *testing.T) { func TestPessimiticTxnTTL(t *testing.T) { var err error - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() // Pessimisitc lock key1 key1 := []byte("key1") @@ -526,8 +551,8 @@ func TestPessimiticTxnTTL(t *testing.T) { } func TestRollback(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() key := []byte("tkey") val := []byte("value") @@ -561,8 +586,8 @@ func TestRollback(t *testing.T) { func TestOverwritePessimisitcLock(t *testing.T) { var err error - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() key := []byte("key") startTs := uint64(1) @@ -589,8 +614,8 @@ func TestOverwritePessimisitcLock(t *testing.T) { func TestCheckTxnStatus(t *testing.T) { var err error - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() var resTTL, resCommitTs uint64 var action kvrpcpb.Action @@ -611,7 +636,7 @@ func TestCheckTxnStatus(t *testing.T) { lockTTL := uint64(100) minCommitTs := uint64(20) err = PrewriteOptimistic(pk, pk, val, startTs, lockTTL, minCommitTs, false, [][]byte{}, store) - require.ErrorIs(t, err, ErrAlreadyRollback) + require.ErrorIs(t, err, kverrors.ErrAlreadyRollback) // Prewrite a large txn startTs = 2 @@ -690,8 +715,8 @@ func TestCheckTxnStatus(t *testing.T) { } func TestCheckSecondaryLocksStatus(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() pk := []byte("pk") secondary := []byte("secondary") @@ -757,8 +782,8 @@ func TestCheckSecondaryLocksStatus(t *testing.T) { func TestMvccGet(t *testing.T) { var err error - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() lockTTL := uint64(100) pk := []byte("t1_r1") @@ -870,8 +895,8 @@ func TestMvccGet(t *testing.T) { } func TestPrimaryKeyOpLock(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() pk := func() []byte { return []byte("tpk") } val2 := []byte("val2") @@ -921,8 +946,8 @@ func TestPrimaryKeyOpLock(t *testing.T) { } func TestMvccTxnRead(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() // nothing at start k1 := []byte("tk1") @@ -992,8 +1017,8 @@ func TestMvccTxnRead(t *testing.T) { } func TestTxnPrewrite(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() // nothing at start k := []byte("tk") @@ -1027,8 +1052,8 @@ func TestTxnPrewrite(t *testing.T) { } func TestPrewriteInsert(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() // nothing at start k1 := []byte("tk1") @@ -1063,8 +1088,8 @@ func TestPrewriteInsert(t *testing.T) { } func TestRollbackKey(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("tk") v := []byte("v") @@ -1088,8 +1113,8 @@ func TestRollbackKey(t *testing.T) { } func TestCleanup(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("tk") v := []byte("v") @@ -1110,8 +1135,8 @@ func TestCleanup(t *testing.T) { } func TestCommit(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("tk") v := []byte("v") @@ -1161,8 +1186,8 @@ func TestCommit(t *testing.T) { } func TestMinCommitTs(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("tk") v := []byte("v") @@ -1182,8 +1207,8 @@ func TestMinCommitTs(t *testing.T) { } func TestPessimisticLock(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("tk") v := []byte("v") @@ -1347,8 +1372,8 @@ func TestPessimisticLock(t *testing.T) { } func TestResolveCommit(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() pk := []byte("tpk") v := []byte("v") @@ -1412,8 +1437,8 @@ func MustLoad(startTS, commitTS uint64, store *TestStore, pairs ...string) { } func TestBatchGet(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() MustLoad(100, 101, store, "ta:1", "tb:2", "tc:3") MustPrewritePut([]byte("ta"), []byte("ta"), []byte("0"), 103, store) keys := [][]byte{[]byte("ta"), []byte("tb"), []byte("tc")} @@ -1425,8 +1450,8 @@ func TestBatchGet(t *testing.T) { } func TestCommitPessimisticLock(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("ta") MustAcquirePessimisticLock(k, k, 10, 10, store) MustCommitErr(k, 20, 30, store) @@ -1435,8 +1460,8 @@ func TestCommitPessimisticLock(t *testing.T) { } func TestOpCheckNotExist(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("ta") v := []byte("v") @@ -1452,8 +1477,8 @@ func TestOpCheckNotExist(t *testing.T) { } func TestPessimisticLockForce(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k := []byte("ta") v := []byte("v") @@ -1469,8 +1494,8 @@ func TestPessimisticLockForce(t *testing.T) { } func TestScanSampleStep(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() for i := 0; i < 1000; i++ { k := genScanSampleStepKey(i) MustPrewritePut(k, k, k, 1, store) @@ -1502,8 +1527,8 @@ func genScanSampleStepKey(i int) []byte { } func TestAsyncCommitPrewrite(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() pk := []byte("tpk") pkVal := []byte("tpkVal") @@ -1531,8 +1556,8 @@ func TestAsyncCommitPrewrite(t *testing.T) { } func TestAccessCommittedLocks(t *testing.T) { - store, close := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) - defer close() + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() k0 := []byte("t0") v0 := []byte("v0") @@ -1625,3 +1650,244 @@ func TestAccessCommittedLocks(t *testing.T) { } } } + +func TestTiKVRCRead(t *testing.T) { + store, clean := NewTestStore("basic_optimistic_db", "basic_optimistic_log", t) + defer clean() + + k1 := []byte("t1") + k2, v2 := []byte("t2"), []byte("v2") + k3, v3 := []byte("t3"), []byte("v3") + k4, v4 := []byte("t4"), []byte("v4") + MustLoad(10, 20, store, "t1:v1", "t2:v2", "t3:v3") + // write to be read + MustPrewritePut(k1, k1, []byte("v11"), 30, store) + MustCommit(k1, 30, 40, store) + // lock to be ignored + MustPrewritePut(k2, k2, v2, 50, store) + MustPrewriteDelete(k3, k3, 60, store) + MustPrewritePut(k4, k4, v4, 70, store) + + expected := map[string][]byte{string(k1): []byte("v11"), string(k2): v2, string(k3): v3, string(k4): nil} + + reqCtx := store.newReqCtx() + reqCtx.rpcCtx.IsolationLevel = kvrpcpb.IsolationLevel_RC + // get + for k, v := range expected { + res, err := store.MvccStore.Get(reqCtx, []byte(k), 80) + require.NoError(t, err) + require.Equal(t, res, v) + } + // batch get + pairs := store.MvccStore.BatchGet(reqCtx, [][]byte{k1, k2, k3, k4}, 80) + require.Equal(t, len(pairs), 3) + for _, pair := range pairs { + v, ok := expected[string(pair.Key)] + require.True(t, ok) + require.Nil(t, pair.Error) + require.Equal(t, pair.Value, v) + } + // scan + pairs = store.MvccStore.Scan(reqCtx, &kvrpcpb.ScanRequest{ + StartKey: []byte("t1"), + EndKey: []byte("t4"), + Limit: 100, + Version: 80, + }) + require.Equal(t, len(pairs), 3) + for _, pair := range pairs { + v, ok := expected[string(pair.Key)] + require.True(t, ok) + require.Nil(t, pair.Error) + require.Equal(t, pair.Value, v) + } +} + +func TestAssertion(t *testing.T) { + store, clean := NewTestStore("TestAssertion", "TestAssertion", t) + defer clean() + + // Prepare + MustPrewriteOptimistic([]byte("k1"), []byte("k1"), []byte("v1"), 1, 100, 0, store) + MustPrewriteOptimistic([]byte("k1"), []byte("k2"), []byte("v2"), 1, 100, 0, store) + MustPrewriteOptimistic([]byte("k1"), []byte("k3"), []byte("v3"), 1, 100, 0, store) + MustCommit([]byte("k1"), 1, 2, store) + MustCommit([]byte("k2"), 1, 2, store) + MustCommit([]byte("k3"), 1, 2, store) + + checkAssertionFailedError := func(err error, disable bool, startTs uint64, key []byte, assertion kvrpcpb.Assertion, existingStartTs uint64, existingCommitTs uint64) { + t.Logf("Check error: %+q", err) + if disable { + require.Nil(t, err) + return + } + require.NotNil(t, err) + e, ok := errors.Cause(err).(*kverrors.ErrAssertionFailed) + require.True(t, ok) + require.Equal(t, startTs, e.StartTS) + require.Equal(t, key, e.Key) + require.Equal(t, assertion, e.Assertion) + require.Equal(t, existingStartTs, e.ExistingStartTS) + require.Equal(t, existingCommitTs, e.ExistingCommitTS) + } + + for _, disable := range []bool{false, true} { + level := kvrpcpb.AssertionLevel_Strict + if disable { + level = kvrpcpb.AssertionLevel_Off + } + // Test with optimistic transaction + err := PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 10, 100, 0, false, nil, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k1"), kvrpcpb.Assertion_NotExist, 1, 2) + err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 10, 100, 0, false, nil, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k11"), kvrpcpb.Assertion_Exist, 0, 0) + + // Test with pessimistic transaction + MustAcquirePessimisticLock([]byte("k2"), []byte("k2"), 10, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k2"), []byte("k2"), []byte("v2"), 10, 100, []bool{true}, 10, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k2"), kvrpcpb.Assertion_NotExist, 1, 2) + MustAcquirePessimisticLock([]byte("k22"), []byte("k22"), 10, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k22"), []byte("k22"), []byte("v22"), 10, 100, []bool{true}, 10, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k22"), kvrpcpb.Assertion_Exist, 0, 0) + + // Test with pessimistic transaction (non-pessimistic-lock) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k3"), []byte("v3"), 10, 100, []bool{false}, 10, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k3"), kvrpcpb.Assertion_NotExist, 1, 2) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k33"), []byte("v33"), 10, 100, []bool{false}, 10, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k33"), kvrpcpb.Assertion_Exist, 0, 0) + } + + for _, k := range [][]byte{ + []byte("k1"), + []byte("k11"), + []byte("k2"), + []byte("k22"), + []byte("k3"), + []byte("k33"), + } { + MustRollbackKey(k, 10, store) + } + + // Test assertion passes + // Test with optimistic transaction + err := PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 20, 100, 0, false, nil, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) + err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 20, 100, 0, false, nil, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) + + // Test with pessimistic transaction + MustAcquirePessimisticLock([]byte("k2"), []byte("k2"), 20, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k2"), []byte("k2"), []byte("v2"), 20, 100, []bool{true}, 10, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) + MustAcquirePessimisticLock([]byte("k22"), []byte("k22"), 20, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k22"), []byte("k22"), []byte("v22"), 20, 100, []bool{true}, 10, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) + + // Test with pessimistic transaction (non-pessimistic-lock) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k3"), []byte("v3"), 20, 100, []bool{false}, 10, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k33"), []byte("v33"), 20, 100, []bool{false}, 10, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + require.Nil(t, err) +} + +func getConflictErr(res []*kvrpcpb.KvPair) *kvrpcpb.WriteConflict { + for _, pair := range res { + if pair.Error != nil && pair.Error.Conflict != nil { + return pair.Error.Conflict + } + } + return nil +} + +func TestRcReadCheckTS(t *testing.T) { + store, clean := NewTestStore("TestRcReadCheckTS", "TestRcReadCheckTS", t) + defer clean() + + // Prepare. + k1 := []byte("tk1") + v1 := []byte("v1") + MustPrewriteOptimistic(k1, k1, v1, 1, 100, 0, store) + MustCommit(k1, 1, 2, store) + + k2 := []byte("tk2") + v2 := []byte("v2") + MustPrewriteOptimistic(k2, k2, v2, 5, 100, 0, store) + MustCommit(k2, 5, 6, store) + + k3 := []byte("tk3") + v3 := []byte("v3") + MustPrewriteOptimistic(k3, k3, v3, 10, 100, 0, store) + + // Test point get with RcReadCheckTS. + reqCtx := store.newReqCtx() + reqCtx.rpcCtx.ResolvedLocks = nil + reqCtx.rpcCtx.CommittedLocks = nil + reqCtx.rpcCtx.IsolationLevel = kvrpcpb.IsolationLevel_RCCheckTS + val, err := store.MvccStore.Get(reqCtx, k1, 3) + require.Nil(t, err) + require.Equal(t, v1, val) + + _, err = store.MvccStore.Get(reqCtx, k2, 3) + require.NotNil(t, err) + e, ok := errors.Cause(err).(*kverrors.ErrConflict) + require.True(t, ok) + require.Equal(t, uint64(3), e.StartTS) + require.Equal(t, uint64(5), e.ConflictTS) + require.Equal(t, uint64(6), e.ConflictCommitTS) + + _, err = store.MvccStore.Get(reqCtx, k3, 3) + require.NotNil(t, err) + e, ok = errors.Cause(err).(*kverrors.ErrConflict) + require.True(t, ok) + require.Equal(t, uint64(3), e.StartTS) + require.Equal(t, uint64(10), e.ConflictTS) + + // Test scan and reverse scan. + scanReq := &kvrpcpb.ScanRequest{ + Context: reqCtx.rpcCtx, + StartKey: []byte("a"), + Limit: 100, + Version: 3, + EndKey: []byte("z"), + } + + // The error is reported from more recent version. + scanRes := store.MvccStore.Scan(reqCtx, scanReq) + conflictErr := getConflictErr(scanRes) + require.NotNil(t, conflictErr) + require.Equal(t, uint64(3), conflictErr.StartTs) + require.Equal(t, uint64(5), conflictErr.ConflictTs) + require.Equal(t, uint64(6), conflictErr.ConflictCommitTs) + + // The error is reported from lock. + scanReq.Version = 15 + scanRes = store.MvccStore.Scan(reqCtx, scanReq) + conflictErr = getConflictErr(scanRes) + require.NotNil(t, conflictErr) + require.Equal(t, uint64(15), conflictErr.StartTs) + require.Equal(t, uint64(10), conflictErr.ConflictTs) + + // Test reverse scan. + scanReq.Version = 3 + scanReq.Reverse = true + scanRes = store.MvccStore.Scan(reqCtx, scanReq) + conflictErr = getConflictErr(scanRes) + require.NotNil(t, conflictErr) + + scanReq.Version = 15 + scanRes = store.MvccStore.Scan(reqCtx, scanReq) + conflictErr = getConflictErr(scanRes) + require.NotNil(t, conflictErr) +} diff --git a/store/mockstore/unistore/tikv/server.go b/store/mockstore/unistore/tikv/server.go index 940f2770ecf0a..a7569027df936 100644 --- a/store/mockstore/unistore/tikv/server.go +++ b/store/mockstore/unistore/tikv/server.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/store/mockstore/unistore/client" "github.com/pingcap/tidb/store/mockstore/unistore/cophandler" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/dbreader" + "github.com/pingcap/tidb/store/mockstore/unistore/tikv/kverrors" "github.com/pingcap/tidb/store/mockstore/unistore/tikv/pberror" "github.com/pingcap/tidb/store/mockstore/unistore/util/lockwaiter" "github.com/pingcap/tipb/go-tipb" @@ -110,7 +111,7 @@ func newRequestCtx(svr *Server, ctx *kvrpcpb.Context, method string) (*requestCt atomic.AddInt32(&svr.refCount, 1) if atomic.LoadInt32(&svr.stopped) > 0 { atomic.AddInt32(&svr.refCount, -1) - return nil, ErrRetryable("server is closed") + return nil, kverrors.ErrRetryable("server is closed") } req := &requestCtx{ svr: svr, @@ -134,10 +135,19 @@ func (req *requestCtx) getDBReader() *dbreader.DBReader { mvccStore := req.svr.mvccStore txn := mvccStore.db.NewTransaction(false) req.reader = dbreader.NewDBReader(req.regCtx.RawStart(), req.regCtx.RawEnd(), txn) + req.reader.RcCheckTS = req.isRcCheckTSIsolationLevel() } return req.reader } +func (req *requestCtx) isSnapshotIsolation() bool { + return req.rpcCtx.IsolationLevel == kvrpcpb.IsolationLevel_SI +} + +func (req *requestCtx) isRcCheckTSIsolationLevel() bool { + return req.rpcCtx.IsolationLevel == kvrpcpb.IsolationLevel_RCCheckTS +} + func (req *requestCtx) finish() { atomic.AddInt32(&req.svr.refCount, -1) if req.reader != nil { @@ -202,8 +212,8 @@ func (svr *Server) KvPessimisticLock(ctx context.Context, req *kvrpcpb.Pessimist } if result.DeadlockResp != nil { log.Error("deadlock found", zap.Stringer("entry", &result.DeadlockResp.Entry)) - errLocked := err.(*ErrLocked) - deadlockErr := &ErrDeadlock{ + errLocked := err.(*kverrors.ErrLocked) + deadlockErr := &kverrors.ErrDeadlock{ LockKey: errLocked.Key, LockTS: errLocked.Lock.StartTS, DeadlockKeyHash: result.DeadlockResp.DeadlockKeyHash, @@ -220,7 +230,7 @@ func (svr *Server) KvPessimisticLock(ctx context.Context, req *kvrpcpb.Pessimist if err == nil { return resp, nil } - if _, ok := err.(*ErrLocked); !ok { + if _, ok := err.(*kverrors.ErrLocked); !ok { resp.Errors, resp.RegionError = convertToPBErrors(err) return resp, nil } @@ -230,7 +240,7 @@ func (svr *Server) KvPessimisticLock(ctx context.Context, req *kvrpcpb.Pessimist // The key is rollbacked, we don't have the exact commitTS, but we can use the server's latest. // Always use the store latest ts since the waiter result commitTs may not be the real conflict ts conflictCommitTS := svr.mvccStore.getLatestTS() - err = &ErrConflict{ + err = &kverrors.ErrConflict{ StartTS: req.GetForUpdateTs(), ConflictTS: waiter.LockTS, ConflictCommitTS: conflictCommitTS, @@ -381,7 +391,7 @@ func (svr *Server) KvCleanup(ctx context.Context, req *kvrpcpb.CleanupRequest) ( } err = svr.mvccStore.Cleanup(reqCtx, req.Key, req.StartVersion, req.CurrentTs) resp := new(kvrpcpb.CleanupResponse) - if committed, ok := err.(ErrAlreadyCommitted); ok { + if committed, ok := err.(kverrors.ErrAlreadyCommitted); ok { resp.CommitVersion = uint64(committed) } else if err != nil { log.Error("cleanup failed", zap.Error(err)) @@ -579,6 +589,13 @@ func (svr *Server) BatchCoprocessor(req *coprocessor.BatchRequest, batchCopServe ctx.finish() } }() + if req.TableRegions != nil { + // Support PartitionTableScan for BatchCop + req.Regions = req.Regions[:] + for _, tr := range req.TableRegions { + req.Regions = append(req.Regions, tr.Regions...) + } + } for _, ri := range req.Regions { cop := coprocessor.Request{ Tp: kv.ReqTypeDAG, @@ -639,6 +656,13 @@ func (svr *Server) DispatchMPPTask(_ context.Context, _ *mpp.DispatchTaskRequest func (svr *Server) executeMPPDispatch(ctx context.Context, req *mpp.DispatchTaskRequest, storeAddr string, storeID uint64, handler *cophandler.MPPTaskHandler) error { var reqCtx *requestCtx + if len(req.TableRegions) > 0 { + // Simple unistore logic for PartitionTableScan. + for _, tr := range req.TableRegions { + req.Regions = append(req.Regions, tr.Regions...) + } + } + if len(req.Regions) > 0 { kvContext := &kvrpcpb.Context{ RegionId: req.Regions[0].RegionId, @@ -983,21 +1007,21 @@ func convertToKeyError(err error) *kvrpcpb.KeyError { } causeErr := errors.Cause(err) switch x := causeErr.(type) { - case *ErrLocked: + case *kverrors.ErrLocked: return &kvrpcpb.KeyError{ Locked: x.Lock.ToLockInfo(x.Key), } - case ErrRetryable: + case kverrors.ErrRetryable: return &kvrpcpb.KeyError{ Retryable: x.Error(), } - case *ErrKeyAlreadyExists: + case *kverrors.ErrKeyAlreadyExists: return &kvrpcpb.KeyError{ AlreadyExist: &kvrpcpb.AlreadyExist{ Key: x.Key, }, } - case *ErrConflict: + case *kverrors.ErrConflict: return &kvrpcpb.KeyError{ Conflict: &kvrpcpb.WriteConflict{ StartTs: x.StartTS, @@ -1006,7 +1030,7 @@ func convertToKeyError(err error) *kvrpcpb.KeyError { Key: x.Key, }, } - case *ErrDeadlock: + case *kverrors.ErrDeadlock: return &kvrpcpb.KeyError{ Deadlock: &kvrpcpb.Deadlock{ LockKey: x.LockKey, @@ -1015,7 +1039,7 @@ func convertToKeyError(err error) *kvrpcpb.KeyError { WaitChain: x.WaitChain, }, } - case *ErrCommitExpire: + case *kverrors.ErrCommitExpire: return &kvrpcpb.KeyError{ CommitTsExpired: &kvrpcpb.CommitTsExpired{ StartTs: x.StartTs, @@ -1024,13 +1048,23 @@ func convertToKeyError(err error) *kvrpcpb.KeyError { MinCommitTs: x.MinCommitTs, }, } - case *ErrTxnNotFound: + case *kverrors.ErrTxnNotFound: return &kvrpcpb.KeyError{ TxnNotFound: &kvrpcpb.TxnNotFound{ StartTs: x.StartTS, PrimaryKey: x.PrimaryKey, }, } + case *kverrors.ErrAssertionFailed: + return &kvrpcpb.KeyError{ + AssertionFailed: &kvrpcpb.AssertionFailed{ + StartTs: x.StartTS, + Key: x.Key, + Assertion: x.Assertion, + ExistingStartTs: x.ExistingStartTS, + ExistingCommitTs: x.ExistingCommitTS, + }, + } default: return &kvrpcpb.KeyError{ Abort: err.Error(), diff --git a/store/mockstore/unistore/util/lockwaiter/main_test.go b/store/mockstore/unistore/util/lockwaiter/main_test.go index 6bd0d063dae5c..19d1b574a56b3 100644 --- a/store/mockstore/unistore/util/lockwaiter/main_test.go +++ b/store/mockstore/unistore/util/lockwaiter/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/store/pdtypes/api.go b/store/pdtypes/api.go new file mode 100644 index 0000000000000..de163ab1ad0ed --- /dev/null +++ b/store/pdtypes/api.go @@ -0,0 +1,116 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package pdtypes contains type defines under PD. +// +// Mainly copied from PD repo to avoid direct dependency. +package pdtypes + +import ( + "time" + + "github.com/pingcap/kvproto/pkg/metapb" + "github.com/pingcap/kvproto/pkg/pdpb" +) + +// StoresInfo records stores' info. +type StoresInfo struct { + Count int `json:"count"` + Stores []*StoreInfo `json:"stores"` +} + +// StoreInfo contains information about a store. +type StoreInfo struct { + Store *MetaStore `json:"store"` + Status *StoreStatus `json:"status"` +} + +// MetaStore contains meta information about a store. +type MetaStore struct { + *metapb.Store + StateName string `json:"state_name"` +} + +// StoreStatus contains status about a store. +type StoreStatus struct { + Capacity ByteSize `json:"capacity"` + Available ByteSize `json:"available"` + UsedSize ByteSize `json:"used_size"` + LeaderCount int `json:"leader_count"` + LeaderWeight float64 `json:"leader_weight"` + LeaderScore float64 `json:"leader_score"` + LeaderSize int64 `json:"leader_size"` + RegionCount int `json:"region_count"` + RegionWeight float64 `json:"region_weight"` + RegionScore float64 `json:"region_score"` + RegionSize int64 `json:"region_size"` + SlowScore uint64 `json:"slow_score"` + SendingSnapCount uint32 `json:"sending_snap_count,omitempty"` + ReceivingSnapCount uint32 `json:"receiving_snap_count,omitempty"` + IsBusy bool `json:"is_busy,omitempty"` + StartTS *time.Time `json:"start_ts,omitempty"` + LastHeartbeatTS *time.Time `json:"last_heartbeat_ts,omitempty"` + Uptime *Duration `json:"uptime,omitempty"` +} + +// RegionsInfo contains some regions with the detailed region info. +type RegionsInfo struct { + Count int `json:"count"` + Regions []RegionInfo `json:"regions"` +} + +// RegionInfo records detail region info for api usage. +type RegionInfo struct { + ID uint64 `json:"id"` + StartKey string `json:"start_key"` + EndKey string `json:"end_key"` + RegionEpoch *metapb.RegionEpoch `json:"epoch,omitempty"` + Peers []MetaPeer `json:"peers,omitempty"` + + Leader MetaPeer `json:"leader,omitempty"` + DownPeers []PDPeerStats `json:"down_peers,omitempty"` + PendingPeers []MetaPeer `json:"pending_peers,omitempty"` + WrittenBytes uint64 `json:"written_bytes"` + ReadBytes uint64 `json:"read_bytes"` + WrittenKeys uint64 `json:"written_keys"` + ReadKeys uint64 `json:"read_keys"` + ApproximateSize int64 `json:"approximate_size"` + ApproximateKeys int64 `json:"approximate_keys"` + + ReplicationStatus *ReplicationStatus `json:"replication_status,omitempty"` +} + +// MetaPeer is api compatible with *metapb.Peer. +type MetaPeer struct { + *metapb.Peer + // RoleName is `Role.String()`. + // Since Role is serialized as int by json by default, + // introducing it will make the output of pd-ctl easier to identify Role. + RoleName string `json:"role_name"` + // IsLearner is `Role == "Learner"`. + // Since IsLearner was changed to Role in kvproto in 5.0, this field was introduced to ensure api compatibility. + IsLearner bool `json:"is_learner,omitempty"` +} + +// PDPeerStats is api compatible with *pdpb.PeerStats. +type PDPeerStats struct { + *pdpb.PeerStats + Peer MetaPeer `json:"peer"` +} + +// ReplicationStatus represents the replication mode status of the region. +type ReplicationStatus struct { + State string `json:"state"` + StateID uint64 `json:"state_id"` +} diff --git a/store/pdtypes/config.go b/store/pdtypes/config.go new file mode 100644 index 0000000000000..42cdb0e7acda7 --- /dev/null +++ b/store/pdtypes/config.go @@ -0,0 +1,45 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pdtypes + +// ReplicationConfig is the replication configuration. +type ReplicationConfig struct { + // MaxReplicas is the number of replicas for each region. + MaxReplicas uint64 `toml:"max-replicas" json:"max-replicas"` + + // The label keys specified the location of a store. + // The placement priorities is implied by the order of label keys. + // For example, ["zone", "rack"] means that we should place replicas to + // different zones first, then to different racks if we don't have enough zones. + LocationLabels StringSlice `toml:"location-labels" json:"location-labels"` + // StrictlyMatchLabel strictly checks if the label of TiKV is matched with LocationLabels. + StrictlyMatchLabel bool `toml:"strictly-match-label" json:"strictly-match-label,string"` + + // When PlacementRules feature is enabled. MaxReplicas, LocationLabels and IsolationLabels are not used any more. + EnablePlacementRules bool `toml:"enable-placement-rules" json:"enable-placement-rules,string"` + + // EnablePlacementRuleCache controls whether use cache during rule checker + EnablePlacementRulesCache bool `toml:"enable-placement-rules-cache" json:"enable-placement-rules-cache,string"` + + // IsolationLevel is used to isolate replicas explicitly and forcibly if it's not empty. + // Its value must be empty or one of LocationLabels. + // Example: + // location-labels = ["zone", "rack", "host"] + // isolation-level = "zone" + // With configuration like above, PD ensure that all replicas be placed in different zones. + // Even if a zone is down, PD will not try to make up replicas in other zone + // because other zones already have replicas on it. + IsolationLevel string `toml:"isolation-level" json:"isolation-level"` +} diff --git a/store/pdtypes/placement.go b/store/pdtypes/placement.go new file mode 100644 index 0000000000000..d491ea4f2bdb3 --- /dev/null +++ b/store/pdtypes/placement.go @@ -0,0 +1,81 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pdtypes + +// Rule is the placement rule that can be checked against a region. When +// applying rules (apply means schedule regions to match selected rules), the +// apply order is defined by the tuple [GroupIndex, GroupID, Index, ID]. +type Rule struct { + GroupID string `json:"group_id"` // mark the source that add the rule + ID string `json:"id"` // unique ID within a group + Index int `json:"index,omitempty"` // rule apply order in a group, rule with less ID is applied first when indexes are equal + Override bool `json:"override,omitempty"` // when it is true, all rules with less indexes are disabled + StartKey []byte `json:"-"` // range start key + StartKeyHex string `json:"start_key"` // hex format start key, for marshal/unmarshal + EndKey []byte `json:"-"` // range end key + EndKeyHex string `json:"end_key"` // hex format end key, for marshal/unmarshal + Role PeerRoleType `json:"role"` // expected role of the peers + Count int `json:"count"` // expected count of the peers + LabelConstraints []LabelConstraint `json:"label_constraints,omitempty"` // used to select stores to place peers + LocationLabels []string `json:"location_labels,omitempty"` // used to make peers isolated physically + IsolationLevel string `json:"isolation_level,omitempty"` // used to isolate replicas explicitly and forcibly + Version uint64 `json:"version,omitempty"` // only set at runtime, add 1 each time rules updated, begin from 0. + CreateTimestamp uint64 `json:"create_timestamp,omitempty"` // only set at runtime, recorded rule create timestamp +} + +// PeerRoleType is the expected peer type of the placement rule. +type PeerRoleType string + +const ( + // Voter can either match a leader peer or follower peer + Voter PeerRoleType = "voter" + // Leader matches a leader. + Leader PeerRoleType = "leader" + // Follower matches a follower. + Follower PeerRoleType = "follower" + // Learner matches a learner. + Learner PeerRoleType = "learner" +) + +// LabelConstraint is used to filter store when trying to place peer of a region. +type LabelConstraint struct { + Key string `json:"key,omitempty"` + Op LabelConstraintOp `json:"op,omitempty"` + Values []string `json:"values,omitempty"` +} + +// RuleGroup defines properties of a rule group. +type RuleGroup struct { + ID string `json:"id,omitempty"` + Index int `json:"index,omitempty"` + Override bool `json:"override,omitempty"` +} + +// LabelConstraintOp defines how a LabelConstraint matches a store. It can be one of +// 'in', 'notIn', 'exists', or 'notExists'. +type LabelConstraintOp string + +const ( + // In restricts the store label value should in the value list. + // If label does not exist, `in` is always false. + In LabelConstraintOp = "in" + // NotIn restricts the store label value should not in the value list. + // If label does not exist, `notIn` is always true. + NotIn LabelConstraintOp = "notIn" + // Exists restricts the store should have the label. + Exists LabelConstraintOp = "exists" + // NotExists restricts the store should not have the label. + NotExists LabelConstraintOp = "notExists" +) diff --git a/store/pdtypes/region_tree.go b/store/pdtypes/region_tree.go new file mode 100644 index 0000000000000..efff8599030b1 --- /dev/null +++ b/store/pdtypes/region_tree.go @@ -0,0 +1,82 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pdtypes + +import ( + "bytes" + "sort" + + "github.com/pingcap/kvproto/pkg/metapb" +) + +// Region is a mock of PD's core.RegionInfo. For testing purpose. +type Region struct { + Meta *metapb.Region + Leader *metapb.Peer +} + +// NewRegionInfo returns a new RegionInfo. +func NewRegionInfo(meta *metapb.Region, leader *metapb.Peer) *Region { + return &Region{Meta: meta, Leader: leader} +} + +// RegionTree is a mock of PD's region tree. For testing purpose. +type RegionTree struct { + Regions []*Region +} + +// SetRegion puts a region to region tree. +func (t *RegionTree) SetRegion(region *Region) { + rs := t.Regions[:0] + for _, r := range t.Regions { + if !overlap(r, region) { + rs = append(rs, r) + } + } + rs = append(rs, region) + t.Regions = rs +} + +// ScanRange scans regions intersecting [start key, end key), returns at most +// `limit` regions. limit <= 0 means no limit. +func (t *RegionTree) ScanRange(startKey, endKey []byte, limit int) []*Region { + sort.Slice(t.Regions, func(i, j int) bool { + return bytes.Compare(t.Regions[i].Meta.StartKey, t.Regions[j].Meta.StartKey) < 0 + }) + pivot := NewRegionInfo(&metapb.Region{StartKey: startKey, EndKey: endKey}, nil) + var res []*Region + for _, r := range t.Regions { + if overlap(r, pivot) && (limit == 0 || len(res) < limit) { + res = append(res, r) + } + } + return res +} + +func overlap(a, b *Region) bool { + // |----a----| + // |----b----| + if len(b.Meta.EndKey) > 0 && bytes.Compare(b.Meta.EndKey, a.Meta.StartKey) <= 0 { + return false + } + + // |----a----| + // |----b----| + if len(a.Meta.EndKey) > 0 && bytes.Compare(a.Meta.EndKey, b.Meta.StartKey) <= 0 { + return false + } + + return true +} diff --git a/store/pdtypes/statistics.go b/store/pdtypes/statistics.go new file mode 100644 index 0000000000000..83309da0c4a0d --- /dev/null +++ b/store/pdtypes/statistics.go @@ -0,0 +1,29 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pdtypes + +// RegionStats records a list of regions' statistics and distribution status. +type RegionStats struct { + Count int `json:"count"` + EmptyCount int `json:"empty_count"` + StorageSize int64 `json:"storage_size"` + StorageKeys int64 `json:"storage_keys"` + StoreLeaderCount map[uint64]int `json:"store_leader_count"` + StorePeerCount map[uint64]int `json:"store_peer_count"` + StoreLeaderSize map[uint64]int64 `json:"store_leader_size"` + StoreLeaderKeys map[uint64]int64 `json:"store_leader_keys"` + StorePeerSize map[uint64]int64 `json:"store_peer_size"` + StorePeerKeys map[uint64]int64 `json:"store_peer_keys"` +} diff --git a/store/pdtypes/typeutil.go b/store/pdtypes/typeutil.go new file mode 100644 index 0000000000000..5d026f40e9583 --- /dev/null +++ b/store/pdtypes/typeutil.go @@ -0,0 +1,120 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pdtypes + +import ( + "fmt" + "strconv" + "strings" + "time" + + "github.com/docker/go-units" + "github.com/pingcap/errors" +) + +// ByteSize is a retype uint64 for TOML and JSON. +type ByteSize uint64 + +// MarshalJSON returns the size as a JSON string. +func (b ByteSize) MarshalJSON() ([]byte, error) { + return []byte(`"` + units.BytesSize(float64(b)) + `"`), nil +} + +// UnmarshalJSON parses a JSON string into the byte size. +func (b *ByteSize) UnmarshalJSON(text []byte) error { + s, err := strconv.Unquote(string(text)) + if err != nil { + return errors.WithStack(err) + } + v, err := units.RAMInBytes(s) + if err != nil { + return errors.WithStack(err) + } + *b = ByteSize(v) + return nil +} + +// UnmarshalText parses a Toml string into the byte size. +func (b *ByteSize) UnmarshalText(text []byte) error { + v, err := units.RAMInBytes(string(text)) + if err != nil { + return errors.WithStack(err) + } + *b = ByteSize(v) + return nil +} + +// Duration is a wrapper of time.Duration for TOML and JSON. +type Duration struct { + time.Duration +} + +// NewDuration creates a Duration from time.Duration. +func NewDuration(duration time.Duration) Duration { + return Duration{Duration: duration} +} + +// MarshalJSON returns the duration as a JSON string. +func (d *Duration) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, d.String())), nil +} + +// UnmarshalJSON parses a JSON string into the duration. +func (d *Duration) UnmarshalJSON(text []byte) error { + s, err := strconv.Unquote(string(text)) + if err != nil { + return errors.WithStack(err) + } + duration, err := time.ParseDuration(s) + if err != nil { + return errors.WithStack(err) + } + d.Duration = duration + return nil +} + +// UnmarshalText parses a TOML string into the duration. +func (d *Duration) UnmarshalText(text []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(text)) + return errors.WithStack(err) +} + +// MarshalText returns the duration as a JSON string. +func (d Duration) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// StringSlice is more friendly to json encode/decode +type StringSlice []string + +// MarshalJSON returns the size as a JSON string. +func (s StringSlice) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(strings.Join(s, ","))), nil +} + +// UnmarshalJSON parses a JSON string into the byte size. +func (s *StringSlice) UnmarshalJSON(text []byte) error { + data, err := strconv.Unquote(string(text)) + if err != nil { + return errors.WithStack(err) + } + if len(data) == 0 { + *s = []string{} + return nil + } + *s = strings.Split(data, ",") + return nil +} diff --git a/store/store_test.go b/store/store_test.go index 2bad71202729b..698f3d4714ce3 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -23,10 +23,10 @@ import ( "testing" "time" - . "github.com/pingcap/check" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/store/mockstore" "github.com/stretchr/testify/require" + kv2 "github.com/tikv/client-go/v2/kv" ) const ( @@ -609,7 +609,7 @@ func TestDBClose(t *testing.T) { ver, err := store.CurrentVersion(kv.GlobalTxnScope) require.NoError(t, err) - require.Equal(t, 1, kv.MaxVersion.Cmp(ver), Equals) + require.Equal(t, 1, kv.MaxVersion.Cmp(ver)) snap := store.GetSnapshot(kv.MaxVersion) @@ -765,3 +765,109 @@ func TestRegister(t *testing.T) { err = Register("retry", &brokenStore{}) require.Error(t, err) } + +func TestSetAssertion(t *testing.T) { + store, err := mockstore.NewMockStore() + require.NoError(t, err) + defer func() { + require.NoError(t, store.Close()) + }() + + txn, err := store.Begin() + require.NoError(t, err) + + mustHaveAssertion := func(key []byte, assertion kv.FlagsOp) { + f, err1 := txn.GetMemBuffer().GetFlags(key) + require.NoError(t, err1) + if assertion == kv.SetAssertExist { + require.True(t, f.HasAssertExists()) + require.False(t, f.HasAssertUnknown()) + } else if assertion == kv.SetAssertNotExist { + require.True(t, f.HasAssertNotExists()) + require.False(t, f.HasAssertUnknown()) + } else if assertion == kv.SetAssertUnknown { + require.True(t, f.HasAssertUnknown()) + } else if assertion == kv.SetAssertNone { + require.False(t, f.HasAssertionFlags()) + } else { + require.FailNow(t, "unreachable") + } + } + + testUnchangeable := func(key []byte, expectAssertion kv.FlagsOp) { + err = txn.SetAssertion(key, kv.SetAssertExist) + require.NoError(t, err) + mustHaveAssertion(key, expectAssertion) + err = txn.SetAssertion(key, kv.SetAssertNotExist) + require.NoError(t, err) + mustHaveAssertion(key, expectAssertion) + err = txn.SetAssertion(key, kv.SetAssertUnknown) + require.NoError(t, err) + mustHaveAssertion(key, expectAssertion) + err = txn.SetAssertion(key, kv.SetAssertNone) + require.NoError(t, err) + mustHaveAssertion(key, expectAssertion) + } + + k1 := []byte("k1") + err = txn.SetAssertion(k1, kv.SetAssertExist) + require.NoError(t, err) + mustHaveAssertion(k1, kv.SetAssertExist) + testUnchangeable(k1, kv.SetAssertExist) + + k2 := []byte("k2") + err = txn.SetAssertion(k2, kv.SetAssertNotExist) + require.NoError(t, err) + mustHaveAssertion(k2, kv.SetAssertNotExist) + testUnchangeable(k2, kv.SetAssertNotExist) + + k3 := []byte("k3") + err = txn.SetAssertion(k3, kv.SetAssertUnknown) + require.NoError(t, err) + mustHaveAssertion(k3, kv.SetAssertUnknown) + testUnchangeable(k3, kv.SetAssertUnknown) + + k4 := []byte("k4") + err = txn.SetAssertion(k4, kv.SetAssertNone) + require.NoError(t, err) + mustHaveAssertion(k4, kv.SetAssertNone) + err = txn.SetAssertion(k4, kv.SetAssertExist) + require.NoError(t, err) + mustHaveAssertion(k4, kv.SetAssertExist) + testUnchangeable(k4, kv.SetAssertExist) + + k5 := []byte("k5") + err = txn.Set(k5, []byte("v5")) + require.NoError(t, err) + mustHaveAssertion(k5, kv.SetAssertNone) + err = txn.SetAssertion(k5, kv.SetAssertNotExist) + require.NoError(t, err) + mustHaveAssertion(k5, kv.SetAssertNotExist) + testUnchangeable(k5, kv.SetAssertNotExist) + + k6 := []byte("k6") + err = txn.SetAssertion(k6, kv.SetAssertNotExist) + require.NoError(t, err) + err = txn.GetMemBuffer().SetWithFlags(k6, []byte("v6"), kv.SetPresumeKeyNotExists) + require.NoError(t, err) + mustHaveAssertion(k6, kv.SetAssertNotExist) + testUnchangeable(k6, kv.SetAssertNotExist) + flags, err := txn.GetMemBuffer().GetFlags(k6) + require.NoError(t, err) + require.True(t, flags.HasPresumeKeyNotExists()) + err = txn.GetMemBuffer().DeleteWithFlags(k6, kv.SetNeedLocked) + mustHaveAssertion(k6, kv.SetAssertNotExist) + testUnchangeable(k6, kv.SetAssertNotExist) + flags, err = txn.GetMemBuffer().GetFlags(k6) + require.NoError(t, err) + require.True(t, flags.HasPresumeKeyNotExists()) + require.True(t, flags.HasNeedLocked()) + + k7 := []byte("k7") + lockCtx := kv2.NewLockCtx(txn.StartTS(), 2000, time.Now()) + err = txn.LockKeys(context.Background(), lockCtx, k7) + require.NoError(t, err) + mustHaveAssertion(k7, kv.SetAssertNone) + + require.NoError(t, txn.Rollback()) +} diff --git a/structure/hash.go b/structure/hash.go index b0e7b15ca526f..7a40172c98ff7 100644 --- a/structure/hash.go +++ b/structure/hash.go @@ -166,6 +166,17 @@ func (t *TxStructure) HGetAll(key []byte) ([]HashPair, error) { return res, errors.Trace(err) } +// HGetLen gets the length of hash. +func (t *TxStructure) HGetLen(key []byte) (uint64, error) { + hashLen := 0 + err := t.iterateHash(key, func(field []byte, value []byte) error { + hashLen++ + return nil + }) + + return uint64(hashLen), errors.Trace(err) +} + // HGetLastN gets latest N fields and values in hash. func (t *TxStructure) HGetLastN(key []byte, num int) ([]HashPair, error) { res := make([]HashPair, 0, num) diff --git a/structure/main_test.go b/structure/main_test.go index 793fae6d90647..d4617b9cbfccb 100644 --- a/structure/main_test.go +++ b/structure/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/table/column.go b/table/column.go index 0225a88556c0b..a7ba45a4de018 100644 --- a/table/column.go +++ b/table/column.go @@ -23,9 +23,8 @@ import ( "strconv" "strings" "time" - "unicode" - "github.com/pingcap/tidb/config" + "github.com/pingcap/errors" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" @@ -170,26 +169,29 @@ func truncateTrailingSpaces(v *types.Datum) { v.SetString(str, v.Collation()) } -func handleWrongCharsetValue(ctx sessionctx.Context, col *model.ColumnInfo, str string, i int) error { - sc := ctx.GetSessionVars().StmtCtx - var strval strings.Builder - for j := 0; j < 6; j++ { - if len(str) > (i + j) { - if str[i+j] > unicode.MaxASCII { - fmt.Fprintf(&strval, "\\x%X", str[i+j]) - } else { - strval.WriteRune(rune(str[i+j])) - } - } +// convertToIncorrectStringErr converts ErrInvalidCharacterString to ErrTruncatedWrongValueForField. +// The first argument is the invalid character in bytes. +func convertToIncorrectStringErr(err error, colName string) error { + inErr, ok := errors.Cause(err).(*errors.Error) + if !ok { + return err } - if len(str) > i+6 { - strval.WriteString(`...`) + args := inErr.Args() + if len(args) != 2 { + return err } - // TODO: Add 'at row %d' - err := ErrTruncatedWrongValueForField.FastGen("Incorrect string value '%s' for column '%s'", strval.String(), col.Name) - logutil.BgLogger().Error("incorrect string value", zap.Uint64("conn", ctx.GetSessionVars().ConnectionID), zap.Error(err)) - err = sc.HandleTruncate(err) - return err + invalidStrHex, ok := args[1].(string) + if !ok { + return err + } + var res strings.Builder + for i := 0; i < len(invalidStrHex); i++ { + if i%2 == 0 { + res.WriteString("\\x") + } + res.WriteByte(invalidStrHex[i]) + } + return ErrTruncatedWrongValueForField.FastGen("Incorrect string value '%s' for column '%s'", res.String(), colName) } // handleZeroDatetime handles Timestamp/Datetime/Date zero date and invalid dates. @@ -314,6 +316,10 @@ func CastValue(ctx sessionctx.Context, val types.Datum, col *model.ColumnInfo, r if innCasted, exit, innErr := handleZeroDatetime(ctx, col, casted, str, types.ErrWrongValue.Equal(err)); exit { return innCasted, innErr } + } else if err != nil && charset.ErrInvalidCharacterString.Equal(err) { + err = convertToIncorrectStringErr(err, col.Name.O) + logutil.BgLogger().Debug("incorrect string value", + zap.Uint64("conn", ctx.GetSessionVars().ConnectionID), zap.Error(err)) } err = sc.HandleTruncate(err) @@ -327,49 +333,9 @@ func CastValue(ctx sessionctx.Context, val types.Datum, col *model.ColumnInfo, r if col.Tp == mysql.TypeString && !types.IsBinaryStr(&col.FieldType) { truncateTrailingSpaces(&casted) } - - if v := makeStringValidator(ctx, col); v != nil { - str := casted.GetString() - strategy := charset.TruncateStrategyReplace - if val.Collation() == charset.CollationBin { - strategy = charset.TruncateStrategyTrim - } - if newStr, invalidPos := v.Truncate(str, strategy); invalidPos >= 0 { - casted = types.NewStringDatum(newStr) - err = handleWrongCharsetValue(ctx, col, str, invalidPos) - } - } - if forceIgnoreTruncate { - err = nil - } return casted, err } -func makeStringValidator(ctx sessionctx.Context, col *model.ColumnInfo) charset.StringValidator { - switch col.Charset { - case charset.CharsetASCII: - if ctx.GetSessionVars().SkipASCIICheck { - return nil - } - return charset.StringValidatorASCII{} - case charset.CharsetUTF8: - if ctx.GetSessionVars().SkipUTF8Check { - return nil - } - needCheckMB4 := config.GetGlobalConfig().CheckMb4ValueInUTF8 - return charset.StringValidatorUTF8{IsUTF8MB4: false, CheckMB4ValueInUTF8: needCheckMB4} - case charset.CharsetUTF8MB4: - if ctx.GetSessionVars().SkipUTF8Check { - return nil - } - return charset.StringValidatorUTF8{IsUTF8MB4: true} - case charset.CharsetLatin1, charset.CharsetBinary: - return nil - default: - return charset.StringValidatorOther{Charset: col.Charset} - } -} - // ColDesc describes column information like MySQL desc and show columns do. type ColDesc struct { Field string @@ -595,7 +561,7 @@ func getColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo, defaultVa defer func() { sc.TimeZone = originalTZ }() } } - value, err := expression.GetTimeValue(ctx, defaultVal, col.Tp, int8(col.Decimal)) + value, err := expression.GetTimeValue(ctx, defaultVal, col.Tp, col.Decimal) if err != nil { return types.Datum{}, errGetDefaultFailed.GenWithStackByArgs(col.Name) } diff --git a/table/column_test.go b/table/column_test.go index 02cbb12237afc..27e35f94757ba 100644 --- a/table/column_test.go +++ b/table/column_test.go @@ -303,6 +303,18 @@ func TestCastValue(t *testing.T) { colInfoS.Charset = charset.CharsetASCII _, err = CastValue(ctx, types.NewDatum([]byte{0x32, 0xf0}), &colInfoS, false, true) require.NoError(t, err) + + colInfoS.Charset = charset.CharsetUTF8MB4 + colInfoS.Collate = "utf8mb4_general_ci" + val, err = CastValue(ctx, types.NewBinaryLiteralDatum([]byte{0xE5, 0xA5, 0xBD}), &colInfoS, false, false) + require.NoError(t, err) + require.Equal(t, "utf8mb4_general_ci", val.Collation()) + val, err = CastValue(ctx, types.NewBinaryLiteralDatum([]byte{0xE5, 0xA5, 0xBD, 0x81}), &colInfoS, false, false) + require.Error(t, err, "[table:1366]Incorrect string value '\\x81' for column ''") + require.Equal(t, "utf8mb4_general_ci", val.Collation()) + val, err = CastValue(ctx, types.NewDatum([]byte{0xE5, 0xA5, 0xBD, 0x81}), &colInfoS, false, false) + require.Error(t, err, "[table:1366]Incorrect string value '\\x81' for column ''") + require.Equal(t, "utf8mb4_general_ci", val.Collation()) } func TestGetDefaultValue(t *testing.T) { diff --git a/table/index.go b/table/index.go index d48ccf89501d1..62892c135b7c3 100644 --- a/table/index.go +++ b/table/index.go @@ -32,8 +32,9 @@ type IndexIterator interface { // CreateIdxOpt contains the options will be used when creating an index. type CreateIdxOpt struct { - Ctx context.Context - Untouched bool // If true, the index key/value is no need to commit. + Ctx context.Context + Untouched bool // If true, the index key/value is no need to commit. + IgnoreAssertion bool } // CreateIdxOptFunc is defined for the Create() method of Index interface. @@ -46,6 +47,11 @@ var IndexIsUntouched CreateIdxOptFunc = func(opt *CreateIdxOpt) { opt.Untouched = true } +// WithIgnoreAssertion uses to indicate the process can ignore assertion. +var WithIgnoreAssertion = func(opt *CreateIdxOpt) { + opt.IgnoreAssertion = true +} + // WithCtx returns a CreateIdxFunc. // This option is used to pass context.Context. func WithCtx(ctx context.Context) CreateIdxOptFunc { @@ -62,16 +68,10 @@ type Index interface { Create(ctx sessionctx.Context, txn kv.Transaction, indexedValues []types.Datum, h kv.Handle, handleRestoreData []types.Datum, opts ...CreateIdxOptFunc) (kv.Handle, error) // Delete supports delete from statement. Delete(sc *stmtctx.StatementContext, txn kv.Transaction, indexedValues []types.Datum, h kv.Handle) error - // Drop supports drop table, drop index statements. - Drop(txn kv.Transaction) error // Exist supports check index exists or not. Exist(sc *stmtctx.StatementContext, txn kv.Transaction, indexedValues []types.Datum, h kv.Handle) (bool, kv.Handle, error) // GenIndexKey generates an index key. GenIndexKey(sc *stmtctx.StatementContext, indexedValues []types.Datum, h kv.Handle, buf []byte) (key []byte, distinct bool, err error) - // Seek supports where clause. - Seek(sc *stmtctx.StatementContext, r kv.Retriever, indexedValues []types.Datum) (iter IndexIterator, hit bool, err error) - // SeekFirst supports aggregate min and ascend order by. - SeekFirst(r kv.Retriever) (iter IndexIterator, err error) // FetchValues fetched index column values in a row. // Param columns is a reused buffer, if it is not nil, FetchValues will fill the index values in it, // and return the buffer, if it is nil, FetchValues will allocate the buffer instead. diff --git a/table/main_test.go b/table/main_test.go index 91463fb0b5f8c..d12ef390d9741 100644 --- a/table/main_test.go +++ b/table/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/table/table.go b/table/table.go index 1c38ed4335ca6..775cb03bb6cf9 100644 --- a/table/table.go +++ b/table/table.go @@ -20,6 +20,7 @@ package table import ( "context" + "time" "github.com/opentracing/opentracing-go" mysql "github.com/pingcap/tidb/errno" @@ -101,6 +102,8 @@ var ( ErrRowDoesNotMatchGivenPartitionSet = dbterror.ClassTable.NewStd(mysql.ErrRowDoesNotMatchGivenPartitionSet) // ErrTempTableFull returns a table is full error, it's used by temporary table now. ErrTempTableFull = dbterror.ClassTable.NewStd(mysql.ErrRecordFileFull) + // ErrOptOnCacheTable returns when exec unsupported opt at cache mode + ErrOptOnCacheTable = dbterror.ClassDDL.NewStd(mysql.ErrOptOnCacheTable) ) // RecordIterFunc is used for low-level record iteration. @@ -238,6 +241,7 @@ type PartitionedTable interface { GetPartition(physicalID int64) PhysicalTable GetPartitionByRow(sessionctx.Context, []types.Datum) (PhysicalTable, error) GetAllPartitionIDs() []int64 + GetPartitionColumnNames() []model.CIStr } // TableFromMeta builds a table.Table from *model.TableInfo. @@ -253,12 +257,17 @@ var MockTableFromMeta func(tableInfo *model.TableInfo) Table type CachedTable interface { Table - Init(renewCh chan func(), exec sqlexec.SQLExecutor) error + Init(exec sqlexec.SQLExecutor) error // TryReadFromCache checks if the cache table is readable. - TryReadFromCache(ts uint64) kv.MemBuffer + TryReadFromCache(ts uint64, leaseDuration time.Duration) (kv.MemBuffer, bool) // UpdateLockForRead If you cannot meet the conditions of the read buffer, // you need to update the lock information and read the data from the original table - UpdateLockForRead(ctx context.Context, store kv.Storage, ts uint64) error + UpdateLockForRead(ctx context.Context, store kv.Storage, ts uint64, leaseDuration time.Duration) + + // WriteLockAndKeepAlive first obtain the write lock, then it renew the lease to keep the lock alive. + // 'exit' is a channel to tell the keep alive goroutine to exit. + // The result is sent to the 'wg' channel. + WriteLockAndKeepAlive(ctx context.Context, exit chan struct{}, leasePtr *uint64, wg chan error) } diff --git a/table/tables/cache.go b/table/tables/cache.go index 7e3eb7c40b9a9..fc9f3f52ce16c 100644 --- a/table/tables/cache.go +++ b/table/tables/cache.go @@ -20,28 +20,21 @@ import ( "time" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/log" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" "github.com/tikv/client-go/v2/oracle" "github.com/tikv/client-go/v2/tikv" "go.uber.org/zap" ) -// RenewLeaseType define the type for renew lease. -type RenewLeaseType int - -const ( - // RenewReadLease means renew read lease. - RenewReadLease RenewLeaseType = iota + 1 - // RenewWriteLease means renew write lease. - RenewWriteLease -) - var ( _ table.CachedTable = &cachedTable{} ) @@ -49,8 +42,29 @@ var ( type cachedTable struct { TableCommon cacheData atomic.Value - handle StateRemote - renewCh chan func() + totalSize int64 + // StateRemote is not thread-safe, this tokenLimit is used to keep only one visitor. + tokenLimit +} + +type tokenLimit chan StateRemote + +func (t tokenLimit) TakeStateRemoteHandle() StateRemote { + handle := <-t + return handle +} + +func (t tokenLimit) TakeStateRemoteHandleNoWait() StateRemote { + select { + case handle := <-t: + return handle + default: + return nil + } +} + +func (t tokenLimit) PutStateRemoteHandle(handle StateRemote) { + t <- handle } // cacheData pack the cache data and lease. @@ -60,11 +74,9 @@ type cacheData struct { kv.MemBuffer } -func leaseFromTS(ts uint64) uint64 { - // TODO make this configurable in the following PRs - const defaultLeaseDuration time.Duration = 3 * time.Second +func leaseFromTS(ts uint64, leaseDuration time.Duration) uint64 { physicalTime := oracle.GetTimeFromTS(ts) - lease := oracle.GoTimeToTS(physicalTime.Add(defaultLeaseDuration)) + lease := oracle.GoTimeToTS(physicalTime.Add(leaseDuration)) return lease } @@ -78,60 +90,68 @@ func newMemBuffer(store kv.Storage) (kv.MemBuffer, error) { return buffTxn.GetMemBuffer(), nil } -func (c *cachedTable) TryReadFromCache(ts uint64) kv.MemBuffer { +func (c *cachedTable) TryReadFromCache(ts uint64, leaseDuration time.Duration) (kv.MemBuffer, bool /*loading*/) { tmp := c.cacheData.Load() if tmp == nil { - return nil + return nil, false } data := tmp.(*cacheData) if ts >= data.Start && ts < data.Lease { leaseTime := oracle.GetTimeFromTS(data.Lease) nowTime := oracle.GetTimeFromTS(ts) distance := leaseTime.Sub(nowTime) - // TODO make this configurable in the following PRs - if distance >= 0 && distance <= (1500*time.Millisecond) { - c.renewCh <- c.renewLease(ts, RenewReadLease, data) + + var triggerFailpoint bool + failpoint.Inject("mockRenewLeaseABA1", func(_ failpoint.Value) { + triggerFailpoint = true + }) + + if distance >= 0 && distance <= leaseDuration/2 || triggerFailpoint { + if h := c.TakeStateRemoteHandleNoWait(); h != nil { + go c.renewLease(h, ts, data, leaseDuration) + } } - return data.MemBuffer + // If data is not nil, but data.MemBuffer is nil, it means the data is being + // loading by a background goroutine. + return data.MemBuffer, data.MemBuffer == nil } - return nil + return nil, false } // newCachedTable creates a new CachedTable Instance func newCachedTable(tbl *TableCommon) (table.Table, error) { ret := &cachedTable{ TableCommon: *tbl, + tokenLimit: make(chan StateRemote, 1), } return ret, nil } // Init is an extra operation for cachedTable after TableFromMeta, // Because cachedTable need some additional parameter that can't be passed in TableFromMeta. -func (c *cachedTable) Init(renewCh chan func(), exec sqlexec.SQLExecutor) error { - c.renewCh = renewCh +func (c *cachedTable) Init(exec sqlexec.SQLExecutor) error { raw, ok := exec.(sqlExec) if !ok { return errors.New("Need sqlExec rather than sqlexec.SQLExecutor") } - c.handle = NewStateRemote(raw) + handle := NewStateRemote(raw) + c.PutStateRemoteHandle(handle) return nil } -func (c *cachedTable) loadDataFromOriginalTable(store kv.Storage, lease uint64) (kv.MemBuffer, uint64, error) { +func (c *cachedTable) loadDataFromOriginalTable(store kv.Storage) (kv.MemBuffer, uint64, int64, error) { buffer, err := newMemBuffer(store) if err != nil { - return nil, 0, err + return nil, 0, 0, err } var startTS uint64 + totalSize := int64(0) err = kv.RunInNewTxn(context.Background(), store, true, func(ctx context.Context, txn kv.Transaction) error { prefix := tablecodec.GenTablePrefix(c.tableID) if err != nil { return errors.Trace(err) } startTS = txn.StartTS() - if startTS >= lease { - return errors.New("the loaded data is outdated for caching") - } it, err := txn.Iter(prefix, prefix.PrefixNext()) if err != nil { return errors.Trace(err) @@ -139,11 +159,14 @@ func (c *cachedTable) loadDataFromOriginalTable(store kv.Storage, lease uint64) defer it.Close() for it.Valid() && it.Key().HasPrefix(prefix) { + key := it.Key() value := it.Value() - err = buffer.Set(it.Key(), value) + err = buffer.Set(key, value) if err != nil { return errors.Trace(err) } + totalSize += int64(len(key)) + totalSize += int64(len(value)) err = it.Next() if err != nil { return errors.Trace(err) @@ -152,43 +175,80 @@ func (c *cachedTable) loadDataFromOriginalTable(store kv.Storage, lease uint64) return nil }) if err != nil { - return nil, 0, err + return nil, 0, totalSize, err } - return buffer, startTS, nil + return buffer, startTS, totalSize, nil } -func (c *cachedTable) UpdateLockForRead(ctx context.Context, store kv.Storage, ts uint64) error { +func (c *cachedTable) UpdateLockForRead(ctx context.Context, store kv.Storage, ts uint64, leaseDuration time.Duration) { + if h := c.TakeStateRemoteHandle(); h != nil { + go c.updateLockForRead(ctx, h, store, ts, leaseDuration) + } +} + +func (c *cachedTable) updateLockForRead(ctx context.Context, handle StateRemote, store kv.Storage, ts uint64, leaseDuration time.Duration) { + defer func() { + if r := recover(); r != nil { + log.Error("panic in the recoverable goroutine", + zap.Reflect("r", r), + zap.Stack("stack trace")) + } + c.PutStateRemoteHandle(handle) + }() + // Load data from original table and the update lock information. tid := c.Meta().ID - lease := leaseFromTS(ts) - succ, err := c.handle.LockForRead(ctx, tid, lease) + lease := leaseFromTS(ts, leaseDuration) + succ, err := handle.LockForRead(ctx, tid, lease) if err != nil { - return errors.Trace(err) + log.Warn("lock cached table for read", zap.Error(err)) + return } if succ { - mb, startTS, err := c.loadDataFromOriginalTable(store, lease) - if err != nil { - return errors.Trace(err) - } - c.cacheData.Store(&cacheData{ - Start: startTS, + Start: ts, Lease: lease, - MemBuffer: mb, + MemBuffer: nil, // Async loading, this will be set later. }) + + // Make the load data process async, in case that loading data takes longer the + // lease duration, then the loaded data get staled and that process repeats forever. + go func() { + start := time.Now() + mb, startTS, totalSize, err := c.loadDataFromOriginalTable(store) + metrics.LoadTableCacheDurationHistogram.Observe(time.Since(start).Seconds()) + if err != nil { + log.Info("load data from table fail", zap.Error(err)) + return + } + + tmp := c.cacheData.Load().(*cacheData) + if tmp != nil && tmp.Start == ts { + c.cacheData.Store(&cacheData{ + Start: startTS, + Lease: tmp.Lease, + MemBuffer: mb, + }) + atomic.StoreInt64(&c.totalSize, totalSize) + } + }() } // Current status is not suitable to cache. - return nil } +const cachedTableSizeLimit = 64 * (1 << 20) + // AddRecord implements the AddRecord method for the table.Table interface. func (c *cachedTable) AddRecord(sctx sessionctx.Context, r []types.Datum, opts ...table.AddRecordOption) (recordID kv.Handle, err error) { - txnCtxAddCachedTable(sctx, c.Meta().ID, c.handle) + if atomic.LoadInt64(&c.totalSize) > cachedTableSizeLimit { + return nil, table.ErrOptOnCacheTable.GenWithStackByArgs("table too large") + } + txnCtxAddCachedTable(sctx, c.Meta().ID, c) return c.TableCommon.AddRecord(sctx, r, opts...) } -func txnCtxAddCachedTable(sctx sessionctx.Context, tid int64, handle StateRemote) { +func txnCtxAddCachedTable(sctx sessionctx.Context, tid int64, handle *cachedTable) { txnCtx := sctx.GetSessionVars().TxnCtx if txnCtx.CachedTables == nil { txnCtx.CachedTables = make(map[int64]interface{}) @@ -200,30 +260,98 @@ func txnCtxAddCachedTable(sctx sessionctx.Context, tid int64, handle StateRemote // UpdateRecord implements table.Table func (c *cachedTable) UpdateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, oldData, newData []types.Datum, touched []bool) error { - txnCtxAddCachedTable(sctx, c.Meta().ID, c.handle) + // Prevent furthur writing when the table is already too large. + if atomic.LoadInt64(&c.totalSize) > cachedTableSizeLimit { + return table.ErrOptOnCacheTable.GenWithStackByArgs("table too large") + } + txnCtxAddCachedTable(sctx, c.Meta().ID, c) return c.TableCommon.UpdateRecord(ctx, sctx, h, oldData, newData, touched) } // RemoveRecord implements table.Table RemoveRecord interface. func (c *cachedTable) RemoveRecord(sctx sessionctx.Context, h kv.Handle, r []types.Datum) error { - txnCtxAddCachedTable(sctx, c.Meta().ID, c.handle) + txnCtxAddCachedTable(sctx, c.Meta().ID, c) return c.TableCommon.RemoveRecord(sctx, h, r) } -func (c *cachedTable) renewLease(ts uint64, op RenewLeaseType, data *cacheData) func() { - return func() { - tid := c.Meta().ID - lease := leaseFromTS(ts) - succ, err := c.handle.RenewLease(context.Background(), tid, lease, op) - if err != nil { - log.Warn("Renew read lease error", zap.Error(err)) - } - if succ { - c.cacheData.Store(&cacheData{ - Start: data.Start, - Lease: lease, - MemBuffer: data.MemBuffer, - }) +// TestMockRenewLeaseABA2 is used by test function TestRenewLeaseABAFailPoint. +var TestMockRenewLeaseABA2 chan struct{} + +func (c *cachedTable) renewLease(handle StateRemote, ts uint64, data *cacheData, leaseDuration time.Duration) { + failpoint.Inject("mockRenewLeaseABA2", func(_ failpoint.Value) { + c.PutStateRemoteHandle(handle) + <-TestMockRenewLeaseABA2 + c.TakeStateRemoteHandle() + }) + + defer c.PutStateRemoteHandle(handle) + + tid := c.Meta().ID + lease := leaseFromTS(ts, leaseDuration) + newLease, err := handle.RenewReadLease(context.Background(), tid, data.Lease, lease) + if err != nil && !kv.IsTxnRetryableError(err) { + log.Warn("Renew read lease error", zap.Error(err)) + } + if newLease > 0 { + c.cacheData.Store(&cacheData{ + Start: data.Start, + Lease: newLease, + MemBuffer: data.MemBuffer, + }) + } + + failpoint.Inject("mockRenewLeaseABA2", func(_ failpoint.Value) { + TestMockRenewLeaseABA2 <- struct{}{} + }) +} + +const cacheTableWriteLease = 5 * time.Second + +func (c *cachedTable) WriteLockAndKeepAlive(ctx context.Context, exit chan struct{}, leasePtr *uint64, wg chan error) { + writeLockLease, err := c.lockForWrite(ctx) + atomic.StoreUint64(leasePtr, writeLockLease) + wg <- err + if err != nil { + logutil.Logger(ctx).Warn("[cached table] lock for write lock fail", zap.Error(err)) + return + } + + t := time.NewTicker(cacheTableWriteLease) + defer t.Stop() + for { + select { + case <-t.C: + if err := c.renew(ctx, leasePtr); err != nil { + logutil.Logger(ctx).Warn("[cached table] renew write lock lease fail", zap.Error(err)) + return + } + case <-exit: + return } } } + +func (c *cachedTable) renew(ctx context.Context, leasePtr *uint64) error { + oldLease := atomic.LoadUint64(leasePtr) + physicalTime := oracle.GetTimeFromTS(oldLease) + newLease := oracle.GoTimeToTS(physicalTime.Add(cacheTableWriteLease)) + + h := c.TakeStateRemoteHandle() + defer c.PutStateRemoteHandle(h) + + succ, err := h.RenewWriteLease(ctx, c.Meta().ID, newLease) + if err != nil { + return errors.Trace(err) + } + if succ { + atomic.StoreUint64(leasePtr, newLease) + } + return nil +} + +func (c *cachedTable) lockForWrite(ctx context.Context) (uint64, error) { + handle := c.TakeStateRemoteHandle() + defer c.PutStateRemoteHandle(handle) + + return handle.LockForWrite(ctx, c.Meta().ID, cacheTableWriteLease) +} diff --git a/table/tables/cache_test.go b/table/tables/cache_test.go index 62e48ccd24c94..9c026040d255e 100644 --- a/table/tables/cache_test.go +++ b/table/tables/cache_test.go @@ -19,13 +19,23 @@ import ( "testing" "time" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/metrics" + "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/util/stmtsummary" + dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" ) +func lastReadFromCache(tk *testkit.TestKit) bool { + return tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache +} + func TestCacheTableBasicScan(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -38,114 +48,87 @@ func TestCacheTableBasicScan(t *testing.T) { "(10, 110, 1010), (12, 112, 1012), (14, 114, 1014), (16, 116, 1016), (18, 118, 1018)", ) tk.MustExec("alter table tmp1 cache") - assertSelect := func() { - // For TableReader - // First read will read from original table - tk.MustQuery("select * from tmp1 where id>3 order by id").Check(testkit.Rows( + + // For TableReader + // First read will read from original table + tk.MustQuery("select * from tmp1 where id>3 order by id").Check(testkit.Rows( + "5 105 1005", "7 117 1007", "9 109 1009", + "10 110 1010", "12 112 1012", "14 114 1014", "16 116 1016", "18 118 1018", + )) + // Test for join two cache table + tk.MustExec("drop table if exists join_t1, join_t2, join_t3") + tk.MustExec("create table join_t1 (id int)") + tk.MustExec("insert into join_t1 values(1)") + tk.MustExec("alter table join_t1 cache") + tk.MustQuery("select *from join_t1").Check(testkit.Rows("1")) + tk.MustExec("create table join_t2 (id int)") + tk.MustExec("insert into join_t2 values(2)") + tk.MustExec("alter table join_t2 cache") + tk.MustQuery("select *from join_t2").Check(testkit.Rows("2")) + tk.MustExec("create table join_t3 (id int)") + tk.MustExec("insert into join_t3 values(3)") + planUsed := false + for i := 0; i < 10; i++ { + tk.MustQuery("select *from join_t1 join join_t2").Check(testkit.Rows("1 2")) + if lastReadFromCache(tk) { + planUsed = true + break + } + } + require.True(t, planUsed) + + // Test for join a cache table and a normal table + for i := 0; i < 10; i++ { + tk.MustQuery("select * from join_t1 join join_t3").Check(testkit.Rows("1 3")) + if lastReadFromCache(tk) { + // if tk.HasPlan("select *from join_t1 join join_t3", "UnionScan") { + planUsed = true + break + } + } + require.True(t, planUsed) + + // Second read will from cache table + for i := 0; i < 100; i++ { + tk.MustQuery("select * from tmp1 where id>4 order by id").Check(testkit.Rows( "5 105 1005", "7 117 1007", "9 109 1009", "10 110 1010", "12 112 1012", "14 114 1014", "16 116 1016", "18 118 1018", )) - // Test for join two cache table - tk.MustExec("drop table if exists join_t1, join_t2, join_t3") - tk.MustExec("create table join_t1 (id int)") - tk.MustExec("insert into join_t1 values(1)") - tk.MustExec("alter table join_t1 cache") - tk.MustQuery("select *from join_t1").Check(testkit.Rows("1")) - tk.MustExec("create table join_t2 (id int)") - tk.MustExec("insert into join_t2 values(2)") - tk.MustExec("alter table join_t2 cache") - tk.MustQuery("select *from join_t2").Check(testkit.Rows("2")) - tk.MustExec("create table join_t3 (id int)") - tk.MustExec("insert into join_t3 values(3)") - planUsed := false - for i := 0; i < 10; i++ { - tk.MustQuery("select *from join_t1 join join_t2").Check(testkit.Rows("1 2")) - if tk.HasPlan("select *from join_t1 join join_t2", "UnionScan") { - planUsed = true - break - } - } - require.True(t, planUsed) - result := tk.MustQuery("explain format = 'brief' select *from join_t1 join join_t2") - result.Check(testkit.Rows( - "HashJoin 100000000.00 root CARTESIAN inner join", - "├─UnionScan(Build) 10000.00 root ", - "│ └─TableReader 10000.00 root data:TableFullScan", - "│ └─TableFullScan 10000.00 cop[tikv] table:join_t2 keep order:false, stats:pseudo", - "└─UnionScan(Probe) 10000.00 root ", - " └─TableReader 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tikv] table:join_t1 keep order:false, stats:pseudo")) - // Test for join a cache table and a normal table - for i := 0; i < 10; i++ { - tk.MustQuery("select *from join_t1 join join_t3").Check(testkit.Rows("1 3")) - if tk.HasPlan("select *from join_t1 join join_t3", "UnionScan") { - planUsed = true - break - } - } - require.True(t, planUsed) - result = tk.MustQuery("explain format = 'brief' select *from join_t1 join join_t3") - result.Check(testkit.Rows( - "Projection 100000000.00 root test.join_t1.id, test.join_t3.id", - "└─HashJoin 100000000.00 root CARTESIAN inner join", - " ├─UnionScan(Build) 10000.00 root ", - " │ └─TableReader 10000.00 root data:TableFullScan", - " │ └─TableFullScan 10000.00 cop[tikv] table:join_t1 keep order:false, stats:pseudo", - " └─TableReader(Probe) 10000.00 root data:TableFullScan", - " └─TableFullScan 10000.00 cop[tikv] table:join_t3 keep order:false, stats:pseudo")) - - // Second read will from cache table - for i := 0; i < 100; i++ { - tk.MustQuery("select * from tmp1 where id>4 order by id").Check(testkit.Rows( - "5 105 1005", "7 117 1007", "9 109 1009", - "10 110 1010", "12 112 1012", "14 114 1014", "16 116 1016", "18 118 1018", - )) - if tk.HasPlan("select * from tmp1 where id>4 order by id", "UnionScan") { - planUsed = true - break - } - } - require.True(t, planUsed) - result = tk.MustQuery("explain format = 'brief' select * from tmp1 where id>4 order by id") - result.Check(testkit.Rows("UnionScan 3333.33 root gt(test.tmp1.id, 4)", - "└─TableReader 3333.33 root data:TableRangeScan", - " └─TableRangeScan 3333.33 cop[tikv] table:tmp1 range:(4,+inf], keep order:true, stats:pseudo")) - // For IndexLookUpReader - for i := 0; i < 10; i++ { - tk.MustQuery("select /*+ use_index(tmp1, u) */ * from tmp1 where u>101 order by u").Check(testkit.Rows( - "5 105 1005", "9 109 1009", "10 110 1010", - "12 112 1012", "3 113 1003", "14 114 1014", "16 116 1016", "7 117 1007", "18 118 1018", - )) - if tk.HasPlan("select /*+ use_index(tmp1, u) */ * from tmp1 where u>101 order by u", "UnionScan") { - planUsed = true - break - } + if lastReadFromCache(tk) { + // if tk.HasPlan("select * from tmp1 where id>4 order by id", "UnionScan") { + planUsed = true + break } - require.True(t, planUsed) - result = tk.MustQuery("explain format = 'brief' select /*+ use_index(tmp1, u) */ * from tmp1 where u>101 order by u") - result.Check(testkit.Rows("UnionScan 3333.33 root gt(test.tmp1.u, 101)", - "└─IndexLookUp 3333.33 root ", - " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:tmp1, index:u(u) range:(101,+inf], keep order:true, stats:pseudo", - " └─TableRowIDScan(Probe) 3333.33 cop[tikv] table:tmp1 keep order:false, stats:pseudo")) - tk.MustQuery("show warnings").Check(testkit.Rows()) - - // For IndexReader - tk.MustQuery("select /*+ use_index(tmp1, u) */ id,u from tmp1 where u>101 order by id").Check(testkit.Rows( - "3 113", "5 105", "7 117", "9 109", "10 110", - "12 112", "14 114", "16 116", "18 118", - )) - tk.MustQuery("show warnings").Check(testkit.Rows()) + } + require.True(t, planUsed) - // For IndexMerge, cache table should not use index merge - tk.MustQuery("select /*+ use_index_merge(tmp1, primary, u) */ * from tmp1 where id>5 or u>110 order by u").Check(testkit.Rows( - "9 109 1009", "10 110 1010", + // For IndexLookUpReader + for i := 0; i < 10; i++ { + tk.MustQuery("select /*+ use_index(tmp1, u) */ * from tmp1 where u>101 order by u").Check(testkit.Rows( + "5 105 1005", "9 109 1009", "10 110 1010", "12 112 1012", "3 113 1003", "14 114 1014", "16 116 1016", "7 117 1007", "18 118 1018", )) - - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled")) + if lastReadFromCache(tk) { + planUsed = true + break + } } - assertSelect() - + require.True(t, planUsed) + + // For IndexReader + tk.MustQuery("select /*+ use_index(tmp1, u) */ id,u from tmp1 where u>101 order by id").Check(testkit.Rows( + "3 113", "5 105", "7 117", "9 109", "10 110", + "12 112", "14 114", "16 116", "18 118", + )) + tk.MustQuery("show warnings").Check(testkit.Rows()) + + // For IndexMerge, cache table should not use index merge + tk.MustQuery("select /*+ use_index_merge(tmp1, primary, u) */ * from tmp1 where id>5 or u>110 order by u").Check(testkit.Rows( + "9 109 1009", "10 110 1010", + "12 112 1012", "3 113 1003", "14 114 1014", "16 116 1016", "7 117 1007", "18 118 1018", + )) + + tk.MustQuery("show warnings").Check(testkit.Rows()) } func TestCacheCondition(t *testing.T) { @@ -158,44 +141,51 @@ func TestCacheCondition(t *testing.T) { tk.MustExec("alter table t2 cache") // Explain should not trigger cache. - tk.MustQuery("explain select * from t2") for i := 0; i < 10; i++ { + tk.MustQuery("explain select * from t2") time.Sleep(100 * time.Millisecond) - require.False(t, tk.HasPlan("select * from t2 where id>0", "UnionScan")) + require.False(t, lastReadFromCache(tk)) } // Insert should not trigger cache. tk.MustExec("insert into t2 values (1,1)") for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) - require.False(t, tk.HasPlan("select * from t2 where id>0", "UnionScan")) + require.False(t, lastReadFromCache(tk)) } // Update should not trigger cache. tk.MustExec("update t2 set v = v + 1 where id > 0") for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) - require.False(t, tk.HasPlan("select * from t2 where id>0", "UnionScan")) + require.False(t, lastReadFromCache(tk)) } // Contains PointGet Update should not trigger cache. tk.MustExec("update t2 set v = v + 1 where id = 2") for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) - require.False(t, tk.HasPlan("select * from t2 where id>0", "UnionScan")) + require.False(t, lastReadFromCache(tk)) } // Contains PointGet Delete should not trigger cache. tk.MustExec("delete from t2 where id = 2") for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) - require.False(t, tk.HasPlan("select * from t2 where id>0", "UnionScan")) + require.False(t, lastReadFromCache(tk)) } // Normal query should trigger cache. tk.MustQuery("select * from t2") - for !tk.HasPlan("select * from t2 where id>0", "UnionScan") { - tk.MustExec("select * from t2") + cacheUsed := false + for i := 0; i < 100; i++ { + tk.MustQuery("select * from t2") + if lastReadFromCache(tk) { + cacheUsed = true + break + } + time.Sleep(100 * time.Millisecond) } + require.True(t, cacheUsed) } func TestCacheTableBasicReadAndWrite(t *testing.T) { @@ -213,29 +203,38 @@ func TestCacheTableBasicReadAndWrite(t *testing.T) { tk.MustExec("alter table write_tmp1 cache") // Read and add read lock - tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", - "3 113 1003")) + tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", "3 113 1003")) // read lock should valid var i int for i = 0; i < 10; i++ { - if tk.HasPlan("select * from write_tmp1", "UnionScan") { + if lastReadFromCache(tk) { break } + // Wait for the cache to be loaded. + time.Sleep(50 * time.Millisecond) + tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", "3 113 1003")) } require.True(t, i < 10) tk.MustExec("use test") tk1.MustExec("insert into write_tmp1 values (2, 222, 222)") // write lock exists - require.False(t, tk.HasPlan("select * from write_tmp1", "UnionScan")) + tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", + "2 222 222", + "3 113 1003")) + require.False(t, lastReadFromCache(tk)) + // wait write lock expire and check cache can be used again - for !tk.HasPlan("select * from write_tmp1", "UnionScan") { - tk.MustExec("select * from write_tmp1") + for !lastReadFromCache(tk) { + tk.MustQuery("select * from write_tmp1").Check(testkit.Rows( + "1 101 1001", + "2 222 222", + "3 113 1003")) } tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", "2 222 222", "3 113 1003")) tk1.MustExec("update write_tmp1 set v = 3333 where id = 2") - for !tk.HasPlan("select * from write_tmp1", "UnionScan") { - tk.MustExec("select * from write_tmp1") + for !lastReadFromCache(tk) { + tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", "2 222 222", "3 113 1003")) } tk.MustQuery("select * from write_tmp1").Check(testkit.Rows("1 101 1001", "2 222 3333", "3 113 1003")) } @@ -254,7 +253,8 @@ func TestCacheTableComplexRead(t *testing.T) { var i int for i = 0; i < 100; i++ { time.Sleep(100 * time.Millisecond) - if tk1.HasPlan("select * from complex_cache where id > 7", "UnionScan") { + tk1.MustQuery("select * from complex_cache where id > 7").Check(testkit.Rows("9 109 1009")) + if lastReadFromCache(tk1) { break } } @@ -265,14 +265,16 @@ func TestCacheTableComplexRead(t *testing.T) { tk2.MustQuery("select * from complex_cache where id > 7").Check(testkit.Rows("9 109 1009")) for i = 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) - if tk2.HasPlan("select * from complex_cache where id > 7", "UnionScan") { + tk2.MustQuery("select * from complex_cache where id > 7").Check(testkit.Rows("9 109 1009")) + if lastReadFromCache(tk2) { break } } require.True(t, i < 10) tk2.MustExec("commit") - tk1.HasPlan("select * from complex_cache where id > 7", "UnionScan") + tk1.MustQuery("select * from complex_cache where id > 7").Check(testkit.Rows("9 109 1009")) + require.True(t, lastReadFromCache(tk1)) tk1.MustExec("commit") } @@ -294,7 +296,8 @@ func TestBeginSleepABA(t *testing.T) { tk1.MustQuery("select * from aba").Check(testkit.Rows("1 1")) cacheUsed := false for i := 0; i < 100; i++ { - if tk1.HasPlan("select * from aba", "UnionScan") { + tk1.MustQuery("select * from aba").Check(testkit.Rows("1 1")) + if lastReadFromCache(tk1) { cacheUsed = true break } @@ -305,7 +308,8 @@ func TestBeginSleepABA(t *testing.T) { tk1.MustExec("begin") cacheUsed = false for i := 0; i < 100; i++ { - if tk1.HasPlan("select * from aba", "UnionScan") { + tk1.MustQuery("select * from aba").Check(testkit.Rows("1 1")) + if lastReadFromCache(tk1) { cacheUsed = true break } @@ -316,9 +320,10 @@ func TestBeginSleepABA(t *testing.T) { tk2.MustExec("update aba set v = 2") // And then make the cache available again. - for i := 0; i < 50; i++ { + cacheUsed = false + for i := 0; i < 100; i++ { tk2.MustQuery("select * from aba").Check(testkit.Rows("1 2")) - if tk2.HasPlan("select * from aba", "UnionScan") { + if lastReadFromCache(tk2) { cacheUsed = true break } @@ -327,7 +332,8 @@ func TestBeginSleepABA(t *testing.T) { require.True(t, cacheUsed) // tk1 should not use the staled cache, because the data is changed. - require.False(t, tk1.HasPlan("select * from aba", "UnionScan")) + tk1.MustQuery("select * from aba").Check(testkit.Rows("1 1")) + require.False(t, lastReadFromCache(tk1)) } func TestCacheTablePointGet(t *testing.T) { @@ -454,19 +460,191 @@ func TestCacheTableWriteOperatorWaitLockLease(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("set global tidb_enable_stmt_summary = 1") se := tk.Session() + + // This line is a hack, if auth user string is "", the statement summary is skipped, + // so it's added to make the later code been covered. + require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + tk.MustExec("drop table if exists wait_tb1") tk.MustExec("create table wait_tb1(id int)") tk.MustExec("alter table wait_tb1 cache") - tk.MustExec("select *from wait_tb1") var i int for i = 0; i < 10; i++ { - time.Sleep(100 * time.Millisecond) - if tk.HasPlan("select *from wait_tb1", "UnionScan") { + tk.MustQuery("select * from wait_tb1").Check(testkit.Rows()) + if lastReadFromCache(tk) { break } + time.Sleep(100 * time.Millisecond) } require.True(t, i < 10) + stmtsummary.StmtSummaryByDigestMap.Clear() tk.MustExec("insert into wait_tb1 values(1)") require.True(t, se.GetSessionVars().StmtCtx.WaitLockLeaseTime > 0) + + tk.MustQuery("select DIGEST_TEXT from INFORMATION_SCHEMA.STATEMENTS_SUMMARY where MAX_BACKOFF_TIME > 0 or MAX_WAIT_TIME > 0").Check(testkit.Rows("insert into `wait_tb1` values ( ? )")) +} + +func TestTableCacheLeaseVariable(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + // Check default value. + tk.MustQuery("select @@global.tidb_table_cache_lease").Check(testkit.Rows("3")) + + // Check a valid value. + tk.MustExec("set @@global.tidb_table_cache_lease = 1;") + tk.MustQuery("select @@global.tidb_table_cache_lease").Check(testkit.Rows("1")) + + // Check a invalid value, the valid range is [2, 10] + tk.MustExec("set @@global.tidb_table_cache_lease = 111;") + tk.MustQuery("SHOW WARNINGS").Check(testkit.Rows("Warning 1292 Truncated incorrect tidb_table_cache_lease value: '111'")) + tk.MustQuery("select @@global.tidb_table_cache_lease").Check(testkit.Rows("10")) + + // Change to a non-default value and verify the behaviour. + tk.MustExec("set @@global.tidb_table_cache_lease = 2;") + + tk.MustExec("drop table if exists test_lease_variable;") + tk.MustExec(`create table test_lease_variable(c0 int, c1 varchar(20), c2 varchar(20), unique key uk(c0));`) + tk.MustExec(`insert into test_lease_variable(c0, c1, c2) values (1, null, 'green');`) + tk.MustExec(`alter table test_lease_variable cache;`) + + cached := false + for i := 0; i < 20; i++ { + tk.MustQuery("select * from test_lease_variable").Check(testkit.Rows("1 green")) + if lastReadFromCache(tk) { + cached = true + break + } + time.Sleep(50 * time.Millisecond) + } + require.True(t, cached) + + start := time.Now() + tk.MustExec("update test_lease_variable set c0 = 2") + duration := time.Since(start) + + // The lease is 2s, check how long the write operation takes. + require.True(t, duration > time.Second) + require.True(t, duration < 3*time.Second) +} + +func TestMetrics(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists test_metrics;") + tk.MustExec(`create table test_metrics(c0 int, c1 varchar(20), c2 varchar(20), unique key uk(c0));`) + tk.MustExec(`create table nt (c0 int, c1 varchar(20), c2 varchar(20), unique key uk(c0));`) + tk.MustExec(`insert into test_metrics(c0, c1, c2) values (1, null, 'green');`) + tk.MustExec(`alter table test_metrics cache;`) + + tk.MustQuery("select * from test_metrics").Check(testkit.Rows("1 green")) + cached := false + for i := 0; i < 20; i++ { + if lastReadFromCache(tk) { + cached = true + break + } + time.Sleep(50 * time.Millisecond) + tk.MustQuery("select * from test_metrics").Check(testkit.Rows("1 green")) + } + require.True(t, cached) + + counter := metrics.ReadFromTableCacheCounter + pb := &dto.Metric{} + + queries := []string{ + // Table scan + "select * from test_metrics", + // Index scan + "select c0 from test_metrics use index(uk) where c0 > 1", + // Index Lookup + "select c1 from test_metrics use index(uk) where c0 = 1", + // Point Get + "select c0 from test_metrics use index(uk) where c0 = 1", + // // Aggregation + "select count(*) from test_metrics", + // Join + "select * from test_metrics as a join test_metrics as b on a.c0 = b.c0 where a.c1 != 'xxx'", + } + counter.Write(pb) + i := pb.GetCounter().GetValue() + + for _, query := range queries { + tk.MustQuery(query) + i++ + counter.Write(pb) + hit := pb.GetCounter().GetValue() + require.Equal(t, i, hit) + } + + // A counter-example that doesn't increase metrics.ReadFromTableCacheCounter. + tk.MustQuery("select * from nt") + counter.Write(pb) + hit := pb.GetCounter().GetValue() + require.Equal(t, i, hit) +} + +func TestRenewLeaseABAFailPoint(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tables.TestMockRenewLeaseABA2 = make(chan struct{}) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_lease;") + tk.MustExec(`create table t_lease(a int, b int);`) + tk.MustExec(`insert into t_lease values (1, 1)`) + tk.MustExec(`alter table t_lease cache`) + + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2.MustExec("use test") + + // Load the cache data by this query. + var cacheUsed bool + for i := 0; i < 10; i++ { + tk.MustQuery("select * from t_lease").Check(testkit.Rows("1 1")) + if lastReadFromCache(tk) { + cacheUsed = true + break + } + time.Sleep(50 * time.Millisecond) + } + require.True(t, cacheUsed) + + // Renew lease by this query, mock the operation is delayed. + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/table/tables/mockRenewLeaseABA1", `return`)) + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/table/tables/mockRenewLeaseABA2", `return`)) + tk.MustQuery("select * from t_lease").Check(testkit.Rows("1 1")) + + // Make the cache data stale after writing: read lock-> write lock + tk1.MustExec("update t_lease set b = 2 where a = 1") + + // Mock reading from another TiDB instance: write lock -> read lock + is := tk2.Session().GetInfoSchema().(infoschema.InfoSchema) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t_lease")) + require.NoError(t, err) + lease := oracle.GoTimeToTS(time.Now().Add(20 * time.Second)) // A big enough future time + tk2.MustExec("update mysql.table_cache_meta set lock_type = 'READ', lease = ? where tid = ?", lease, tbl.Meta().ID) + + // Then the stagnant renew lease operation finally arrive. + tables.TestMockRenewLeaseABA2 <- struct{}{} + + <-tables.TestMockRenewLeaseABA2 + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/table/tables/mockRenewLeaseABA1")) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/table/tables/mockRenewLeaseABA2")) + + // The renew lease operation should not success, + // And the session should not read from a staled cache data. + tk.MustQuery("select * from t_lease").Check(testkit.Rows("1 2")) + require.False(t, lastReadFromCache(tk)) } diff --git a/table/tables/index.go b/table/tables/index.go index 08d3ecef1f820..b3d6b9e820868 100644 --- a/table/tables/index.go +++ b/table/tables/index.go @@ -16,12 +16,9 @@ package tables import ( "context" - "io" "sync" - "time" "github.com/opentracing/opentracing-go" - "github.com/pingcap/errors" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -33,54 +30,6 @@ import ( "github.com/pingcap/tidb/util/rowcodec" ) -// indexIter is for KV store index iterator. -type indexIter struct { - it kv.Iterator - idx *index - prefix kv.Key - colInfos []rowcodec.ColInfo - tps []*types.FieldType -} - -// Close does the clean up works when KV store index iterator is closed. -func (c *indexIter) Close() { - if c.it != nil { - c.it.Close() - c.it = nil - } -} - -// Next returns current key and moves iterator to the next step. -func (c *indexIter) Next() (indexData []types.Datum, h kv.Handle, err error) { - if !c.it.Valid() { - return nil, nil, errors.Trace(io.EOF) - } - if !c.it.Key().HasPrefix(c.prefix) { - return nil, nil, errors.Trace(io.EOF) - } - vals, err := tablecodec.DecodeIndexKV(c.it.Key(), c.it.Value(), len(c.colInfos), tablecodec.HandleNotNeeded, c.colInfos) - if err != nil { - return nil, nil, errors.Trace(err) - } - handle, err := tablecodec.DecodeIndexHandle(c.it.Key(), c.it.Value(), len(c.colInfos)) - if err != nil { - return nil, nil, errors.Trace(err) - } - for i, v := range vals { - d, err := tablecodec.DecodeColumnValue(v, c.tps[i], time.Local) - if err != nil { - return nil, nil, errors.Trace(err) - } - indexData = append(indexData, d) - } - // update new iter to next - err = c.it.Next() - if err != nil { - return nil, nil, err - } - return indexData, handle, nil -} - // index is the data structure for index data in the KV store. type index struct { idxInfo *model.IndexInfo @@ -169,8 +118,22 @@ func (c *index) Create(sctx sessionctx.Context, txn kv.Transaction, indexedValue // should not overwrite the key with un-commit flag. // So if the key exists, just do nothing and return. v, err := txn.GetMemBuffer().Get(ctx, key) - if err == nil && len(v) != 0 { - return nil, nil + if err == nil { + if len(v) != 0 { + return nil, nil + } + // The key is marked as deleted in the memory buffer, as the existence check is done lazily + // for optimistic transactions by default. The "untouched" key could still exist in the store, + // it's needed to commit this key to do the existence check so unset the untouched flag. + if !txn.IsPessimistic() { + keyFlags, err := txn.GetMemBuffer().GetFlags(key) + if err != nil { + return nil, err + } + if keyFlags.HasPresumeKeyNotExists() { + opt.Untouched = false + } + } } } @@ -184,8 +147,20 @@ func (c *index) Create(sctx sessionctx.Context, txn kv.Transaction, indexedValue return nil, err } + opt.IgnoreAssertion = opt.IgnoreAssertion || c.idxInfo.State != model.StatePublic + if !distinct || skipCheck || opt.Untouched { err = txn.GetMemBuffer().Set(key, idxVal) + if err != nil { + return nil, err + } + if !opt.IgnoreAssertion && (!opt.Untouched) { + if sctx.GetSessionVars().LazyCheckKeyNotExists() && !txn.IsPessimistic() { + err = txn.SetAssertion(key, kv.SetAssertUnknown) + } else { + err = txn.SetAssertion(key, kv.SetAssertNotExist) + } + } return nil, err } @@ -212,11 +187,23 @@ func (c *index) Create(sctx sessionctx.Context, txn kv.Transaction, indexedValue return nil, err } if err != nil || len(value) == 0 { - if sctx.GetSessionVars().LazyCheckKeyNotExists() && err != nil { + lazyCheck := sctx.GetSessionVars().LazyCheckKeyNotExists() && err != nil + if lazyCheck { err = txn.GetMemBuffer().SetWithFlags(key, idxVal, kv.SetPresumeKeyNotExists) } else { err = txn.GetMemBuffer().Set(key, idxVal) } + if err != nil { + return nil, err + } + if opt.IgnoreAssertion { + return nil, nil + } + if lazyCheck && !txn.IsPessimistic() { + err = txn.SetAssertion(key, kv.SetAssertUnknown) + } else { + err = txn.SetAssertion(key, kv.SetAssertNotExist) + } return nil, err } @@ -238,66 +225,14 @@ func (c *index) Delete(sc *stmtctx.StatementContext, txn kv.Transaction, indexed } else { err = txn.GetMemBuffer().Delete(key) } - return err -} - -// Drop removes the KV index from store. -func (c *index) Drop(txn kv.Transaction) error { - it, err := txn.Iter(c.prefix, c.prefix.PrefixNext()) if err != nil { return err } - defer it.Close() - - // remove all indices - for it.Valid() { - if !it.Key().HasPrefix(c.prefix) { - break - } - err := txn.GetMemBuffer().Delete(it.Key()) - if err != nil { - return err - } - err = it.Next() - if err != nil { - return err - } + if c.idxInfo.State == model.StatePublic { + // If the index is in public state, delete this index means it must exists. + err = txn.SetAssertion(key, kv.SetAssertExist) } - return nil -} - -// Seek searches KV index for the entry with indexedValues. -func (c *index) Seek(sc *stmtctx.StatementContext, r kv.Retriever, indexedValues []types.Datum) (iter table.IndexIterator, hit bool, err error) { - key, _, err := c.GenIndexKey(sc, indexedValues, nil, nil) - if err != nil { - return nil, false, err - } - - upperBound := c.prefix.PrefixNext() - it, err := r.Iter(key, upperBound) - if err != nil { - return nil, false, err - } - // check if hit - hit = false - if it.Valid() && it.Key().Cmp(key) == 0 { - hit = true - } - colInfos := BuildRowcodecColInfoForIndexColumns(c.idxInfo, c.tblInfo) - tps := BuildFieldTypesForIndexColumns(c.idxInfo, c.tblInfo) - return &indexIter{it: it, idx: c, prefix: c.prefix, colInfos: colInfos, tps: tps}, hit, nil -} - -// SeekFirst returns an iterator which points to the first entry of the KV index. -func (c *index) SeekFirst(r kv.Retriever) (iter table.IndexIterator, err error) { - upperBound := c.prefix.PrefixNext() - it, err := r.Iter(c.prefix, upperBound) - if err != nil { - return nil, err - } - colInfos := BuildRowcodecColInfoForIndexColumns(c.idxInfo, c.tblInfo) - tps := BuildFieldTypesForIndexColumns(c.idxInfo, c.tblInfo) - return &indexIter{it: it, idx: c, prefix: c.prefix, colInfos: colInfos, tps: tps}, nil + return err } func (c *index) Exist(sc *stmtctx.StatementContext, txn kv.Transaction, indexedValues []types.Datum, h kv.Handle) (bool, kv.Handle, error) { diff --git a/table/tables/index_serial_test.go b/table/tables/index_serial_test.go deleted file mode 100644 index 16784c16d0c7e..0000000000000 --- a/table/tables/index_serial_test.go +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tables_test - -import ( - "context" - "io" - "testing" - "time" - - "github.com/pingcap/tidb/kv" - "github.com/pingcap/tidb/parser/model" - "github.com/pingcap/tidb/parser/mysql" - "github.com/pingcap/tidb/parser/terror" - "github.com/pingcap/tidb/sessionctx/stmtctx" - "github.com/pingcap/tidb/table" - "github.com/pingcap/tidb/table/tables" - "github.com/pingcap/tidb/tablecodec" - "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/types" - "github.com/pingcap/tidb/util/codec" - "github.com/pingcap/tidb/util/collate" - "github.com/pingcap/tidb/util/mock" - "github.com/pingcap/tidb/util/rowcodec" - "github.com/stretchr/testify/require" -) - -func TestIndex(t *testing.T) { - tblInfo := &model.TableInfo{ - ID: 1, - Indices: []*model.IndexInfo{ - { - ID: 2, - Name: model.NewCIStr("test"), - Columns: []*model.IndexColumn{ - {Offset: 0}, - {Offset: 1}, - }, - }, - }, - Columns: []*model.ColumnInfo{ - {ID: 1, Name: model.NewCIStr("c2"), State: model.StatePublic, Offset: 0, FieldType: *types.NewFieldType(mysql.TypeVarchar)}, - {ID: 2, Name: model.NewCIStr("c2"), State: model.StatePublic, Offset: 1, FieldType: *types.NewFieldType(mysql.TypeString)}, - }, - } - index := tables.NewIndex(tblInfo.ID, tblInfo, tblInfo.Indices[0]) - - // Test ununiq index. - store, clean := testkit.CreateMockStore(t) - defer clean() - txn, err := store.Begin() - require.NoError(t, err) - - values := types.MakeDatums(1, 2) - mockCtx := mock.NewContext() - _, err = index.Create(mockCtx, txn, values, kv.IntHandle(1), nil) - require.NoError(t, err) - - it, err := index.SeekFirst(txn) - require.NoError(t, err) - - getValues, h, err := it.Next() - require.NoError(t, err) - require.Len(t, getValues, 2) - require.Equal(t, int64(1), getValues[0].GetInt64()) - require.Equal(t, int64(2), getValues[1].GetInt64()) - require.Equal(t, int64(1), h.IntValue()) - it.Close() - sc := &stmtctx.StatementContext{TimeZone: time.Local} - exist, _, err := index.Exist(sc, txn, values, kv.IntHandle(100)) - require.NoError(t, err) - require.False(t, exist) - - exist, _, err = index.Exist(sc, txn, values, kv.IntHandle(1)) - require.NoError(t, err) - require.True(t, exist) - - err = index.Delete(sc, txn, values, kv.IntHandle(1)) - require.NoError(t, err) - - it, err = index.SeekFirst(txn) - require.NoError(t, err) - - _, _, err = it.Next() - require.Truef(t, terror.ErrorEqual(err, io.EOF), "err %v", err) - it.Close() - - _, err = index.Create(mockCtx, txn, values, kv.IntHandle(0), nil) - require.NoError(t, err) - - _, err = index.SeekFirst(txn) - require.NoError(t, err) - - _, hit, err := index.Seek(sc, txn, values) - require.NoError(t, err) - require.False(t, hit) - - err = index.Drop(txn) - require.NoError(t, err) - - it, hit, err = index.Seek(sc, txn, values) - require.NoError(t, err) - require.False(t, hit) - - _, _, err = it.Next() - require.Truef(t, terror.ErrorEqual(err, io.EOF), "err %v", err) - it.Close() - - it, err = index.SeekFirst(txn) - require.NoError(t, err) - - _, _, err = it.Next() - require.Truef(t, terror.ErrorEqual(err, io.EOF), "err %v", err) - it.Close() - - err = txn.Commit(context.Background()) - require.NoError(t, err) - - tblInfo = &model.TableInfo{ - ID: 2, - Indices: []*model.IndexInfo{ - { - ID: 3, - Name: model.NewCIStr("test"), - Unique: true, - Columns: []*model.IndexColumn{ - {Offset: 0}, - {Offset: 1}, - }, - }, - }, - Columns: []*model.ColumnInfo{ - {ID: 1, Name: model.NewCIStr("c2"), State: model.StatePublic, Offset: 0, FieldType: *types.NewFieldType(mysql.TypeVarchar)}, - {ID: 2, Name: model.NewCIStr("c2"), State: model.StatePublic, Offset: 1, FieldType: *types.NewFieldType(mysql.TypeString)}, - }, - } - index = tables.NewIndex(tblInfo.ID, tblInfo, tblInfo.Indices[0]) - - // Test uniq index. - txn, err = store.Begin() - require.NoError(t, err) - - _, err = index.Create(mockCtx, txn, values, kv.IntHandle(1), nil) - require.NoError(t, err) - - _, err = index.Create(mockCtx, txn, values, kv.IntHandle(2), nil) - require.NotNil(t, err) - - it, err = index.SeekFirst(txn) - require.NoError(t, err) - - getValues, h, err = it.Next() - require.NoError(t, err) - require.Len(t, getValues, 2) - require.Equal(t, int64(1), getValues[0].GetInt64()) - require.Equal(t, int64(2), getValues[1].GetInt64()) - require.Equal(t, int64(1), h.IntValue()) - it.Close() - - exist, h, err = index.Exist(sc, txn, values, kv.IntHandle(1)) - require.NoError(t, err) - require.Equal(t, int64(1), h.IntValue()) - require.True(t, exist) - - exist, h, err = index.Exist(sc, txn, values, kv.IntHandle(2)) - require.NotNil(t, err) - require.Equal(t, int64(1), h.IntValue()) - require.True(t, exist) - - err = txn.Commit(context.Background()) - require.NoError(t, err) - - _, err = index.FetchValues(make([]types.Datum, 0), nil) - require.NotNil(t, err) - - txn, err = store.Begin() - require.NoError(t, err) - - // Test the function of Next when the value of unique key is nil. - values2 := types.MakeDatums(nil, nil) - _, err = index.Create(mockCtx, txn, values2, kv.IntHandle(2), nil) - require.NoError(t, err) - it, err = index.SeekFirst(txn) - require.NoError(t, err) - getValues, h, err = it.Next() - require.NoError(t, err) - require.Len(t, getValues, 2) - require.Equal(t, nil, getValues[0].GetInterface()) - require.Equal(t, nil, getValues[1].GetInterface()) - require.Equal(t, int64(2), h.IntValue()) - it.Close() - - err = txn.Commit(context.Background()) - require.NoError(t, err) -} - -func TestCombineIndexSeek(t *testing.T) { - tblInfo := &model.TableInfo{ - ID: 1, - Indices: []*model.IndexInfo{ - { - ID: 2, - Name: model.NewCIStr("test"), - Columns: []*model.IndexColumn{ - {Offset: 1}, - {Offset: 2}, - }, - }, - }, - Columns: []*model.ColumnInfo{ - {Offset: 0}, - {Offset: 1}, - {Offset: 2}, - }, - } - index := tables.NewIndex(tblInfo.ID, tblInfo, tblInfo.Indices[0]) - - store, clean := testkit.CreateMockStore(t) - defer clean() - txn, err := store.Begin() - require.NoError(t, err) - - mockCtx := mock.NewContext() - values := types.MakeDatums("abc", "def") - _, err = index.Create(mockCtx, txn, values, kv.IntHandle(1), nil) - require.NoError(t, err) - - index2 := tables.NewIndex(tblInfo.ID, tblInfo, tblInfo.Indices[0]) - sc := &stmtctx.StatementContext{TimeZone: time.Local} - iter, hit, err := index2.Seek(sc, txn, types.MakeDatums("abc", nil)) - require.NoError(t, err) - defer iter.Close() - require.False(t, hit) - _, h, err := iter.Next() - require.NoError(t, err) - require.Equal(t, int64(1), h.IntValue()) -} - -func TestMultiColumnCommonHandle(t *testing.T) { - collate.SetNewCollationEnabledForTest(true) - defer collate.SetNewCollationEnabledForTest(false) - tblInfo := buildTableInfo(t, "create table t (a int, b int, u varchar(64) unique, nu varchar(64), primary key (a, b), index nu (nu))") - var idxUnique, idxNonUnique table.Index - for _, idxInfo := range tblInfo.Indices { - idx := tables.NewIndex(tblInfo.ID, tblInfo, idxInfo) - if idxInfo.Name.L == "u" { - idxUnique = idx - } else if idxInfo.Name.L == "nu" { - idxNonUnique = idx - } - } - var a, b *model.ColumnInfo - for _, col := range tblInfo.Columns { - if col.Name.String() == "a" { - a = col - } else if col.Name.String() == "b" { - b = col - } - } - require.NotNil(t, a) - require.NotNil(t, b) - - store, clean := testkit.CreateMockStore(t) - defer clean() - txn, err := store.Begin() - require.NoError(t, err) - mockCtx := mock.NewContext() - sc := mockCtx.GetSessionVars().StmtCtx - // create index for "insert t values (3, 2, "abc", "abc") - idxColVals := types.MakeDatums("abc") - handleColVals := types.MakeDatums(3, 2) - encodedHandle, err := codec.EncodeKey(sc, nil, handleColVals...) - require.NoError(t, err) - commonHandle, err := kv.NewCommonHandle(encodedHandle) - require.NoError(t, err) - _ = idxNonUnique - for _, idx := range []table.Index{idxUnique, idxNonUnique} { - key, _, err := idx.GenIndexKey(sc, idxColVals, commonHandle, nil) - require.NoError(t, err) - _, err = idx.Create(mockCtx, txn, idxColVals, commonHandle, nil) - require.NoError(t, err) - val, err := txn.Get(context.Background(), key) - require.NoError(t, err) - colInfo := tables.BuildRowcodecColInfoForIndexColumns(idx.Meta(), tblInfo) - colInfo = append(colInfo, rowcodec.ColInfo{ - ID: a.ID, - IsPKHandle: false, - Ft: rowcodec.FieldTypeFromModelColumn(a), - }) - colInfo = append(colInfo, rowcodec.ColInfo{ - ID: b.ID, - IsPKHandle: false, - Ft: rowcodec.FieldTypeFromModelColumn(b), - }) - colVals, err := tablecodec.DecodeIndexKV(key, val, 1, tablecodec.HandleDefault, colInfo) - require.NoError(t, err) - require.Len(t, colVals, 3) - _, d, err := codec.DecodeOne(colVals[0]) - require.NoError(t, err) - require.Equal(t, "abc", d.GetString()) - _, d, err = codec.DecodeOne(colVals[1]) - require.NoError(t, err) - require.Equal(t, int64(3), d.GetInt64()) - _, d, err = codec.DecodeOne(colVals[2]) - require.NoError(t, err) - require.Equal(t, int64(2), d.GetInt64()) - handle, err := tablecodec.DecodeIndexHandle(key, val, 1) - require.NoError(t, err) - require.False(t, handle.IsInt()) - require.Equal(t, commonHandle.Encoded(), handle.Encoded()) - } -} diff --git a/table/tables/index_test.go b/table/tables/index_test.go index 5678ce8b39b18..a969b6c6a485f 100644 --- a/table/tables/index_test.go +++ b/table/tables/index_test.go @@ -1,4 +1,4 @@ -// Copyright 2016 PingCAP, Inc. +// Copyright 2021 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import ( "testing" "github.com/pingcap/tidb/ddl" + "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/ast" @@ -30,9 +31,83 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/mock" + "github.com/pingcap/tidb/util/rowcodec" "github.com/stretchr/testify/require" ) +func TestMultiColumnCommonHandle(t *testing.T) { + tblInfo := buildTableInfo(t, "create table t (a int, b int, u varchar(64) unique, nu varchar(64), primary key (a, b), index nu (nu))") + var idxUnique, idxNonUnique table.Index + for _, idxInfo := range tblInfo.Indices { + idx := tables.NewIndex(tblInfo.ID, tblInfo, idxInfo) + if idxInfo.Name.L == "u" { + idxUnique = idx + } else if idxInfo.Name.L == "nu" { + idxNonUnique = idx + } + } + var a, b *model.ColumnInfo + for _, col := range tblInfo.Columns { + if col.Name.String() == "a" { + a = col + } else if col.Name.String() == "b" { + b = col + } + } + require.NotNil(t, a) + require.NotNil(t, b) + + store, clean := testkit.CreateMockStore(t) + defer clean() + txn, err := store.Begin() + require.NoError(t, err) + mockCtx := mock.NewContext() + sc := mockCtx.GetSessionVars().StmtCtx + // create index for "insert t values (3, 2, "abc", "abc") + idxColVals := types.MakeDatums("abc") + handleColVals := types.MakeDatums(3, 2) + encodedHandle, err := codec.EncodeKey(sc, nil, handleColVals...) + require.NoError(t, err) + commonHandle, err := kv.NewCommonHandle(encodedHandle) + require.NoError(t, err) + _ = idxNonUnique + for _, idx := range []table.Index{idxUnique, idxNonUnique} { + key, _, err := idx.GenIndexKey(sc, idxColVals, commonHandle, nil) + require.NoError(t, err) + _, err = idx.Create(mockCtx, txn, idxColVals, commonHandle, nil) + require.NoError(t, err) + val, err := txn.Get(context.Background(), key) + require.NoError(t, err) + colInfo := tables.BuildRowcodecColInfoForIndexColumns(idx.Meta(), tblInfo) + colInfo = append(colInfo, rowcodec.ColInfo{ + ID: a.ID, + IsPKHandle: false, + Ft: rowcodec.FieldTypeFromModelColumn(a), + }) + colInfo = append(colInfo, rowcodec.ColInfo{ + ID: b.ID, + IsPKHandle: false, + Ft: rowcodec.FieldTypeFromModelColumn(b), + }) + colVals, err := tablecodec.DecodeIndexKV(key, val, 1, tablecodec.HandleDefault, colInfo) + require.NoError(t, err) + require.Len(t, colVals, 3) + _, d, err := codec.DecodeOne(colVals[0]) + require.NoError(t, err) + require.Equal(t, "abc", d.GetString()) + _, d, err = codec.DecodeOne(colVals[1]) + require.NoError(t, err) + require.Equal(t, int64(3), d.GetInt64()) + _, d, err = codec.DecodeOne(colVals[2]) + require.NoError(t, err) + require.Equal(t, int64(2), d.GetInt64()) + handle, err := tablecodec.DecodeIndexHandle(key, val, 1) + require.NoError(t, err) + require.False(t, handle.IsInt()) + require.Equal(t, commonHandle.Encoded(), handle.Encoded()) + } +} + func TestSingleColumnCommonHandle(t *testing.T) { tblInfo := buildTableInfo(t, "create table t (a varchar(255) primary key, u int unique, nu int, index nu (nu))") var idxUnique, idxNonUnique table.Index @@ -96,3 +171,35 @@ func buildTableInfo(t *testing.T, sql string) *model.TableInfo { require.NoError(t, err) return tblInfo } + +func TestIssue29520(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_enable_mutation_checker=1") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(c year, PRIMARY KEY (c) CLUSTERED, KEY i1(c))") + tk.MustExec("insert into t values('2020')") +} + +func TestAssertionWithLazyCheck(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_txn_assertion_level = 'STRICT'") + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (id int primary key, v1 int, v2 int, index (v1), unique index (v2))") + tk.MustExec("set @@tidb_constraint_check_in_place = true") + tk.MustExec("insert into t values (1, 1, 1)") + tk.MustGetErrCode("insert into t values (2, 1, 1)", errno.ErrDupEntry) + + tk.MustExec("set @@tidb_constraint_check_in_place = false") + tk.MustExec("insert into t values (3, 3, 3)") + // The constraint check (index key must not exist) will be done while prewriting. TiDB should avoid setting + // assertion on the index key. Even it's set, TiKV will skip checking assertion for mutation types `Insert` and + // `CheckNotExist`. Anyway there should never be assertion failure. + tk.MustGetErrCode("insert into t values (4, 3, 3)", errno.ErrDupEntry) +} diff --git a/table/tables/main_test.go b/table/tables/main_test.go index ebfceb2bd3bca..eb29416fb0b00 100644 --- a/table/tables/main_test.go +++ b/table/tables/main_test.go @@ -22,9 +22,10 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), } goleak.VerifyTestMain(m, opts...) diff --git a/table/tables/mutation_checker.go b/table/tables/mutation_checker.go new file mode 100644 index 0000000000000..0749abbb9cd09 --- /dev/null +++ b/table/tables/mutation_checker.go @@ -0,0 +1,383 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tables + +import ( + "github.com/pingcap/errors" + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/dbterror" + "github.com/pingcap/tidb/util/logutil" + "github.com/pingcap/tidb/util/rowcodec" + "go.uber.org/zap" +) + +var ( + // ErrInconsistentRowValue is the error when values in a row insertion does not match the expected ones. + ErrInconsistentRowValue = dbterror.ClassTable.NewStd(errno.ErrInconsistentRowValue) + // ErrInconsistentHandle is the error when the handle in the row/index insertions does not match. + ErrInconsistentHandle = dbterror.ClassTable.NewStd(errno.ErrInconsistentHandle) + // ErrInconsistentIndexedValue is the error when decoded values from the index mutation cannot match row value + ErrInconsistentIndexedValue = dbterror.ClassTable.NewStd(errno.ErrInconsistentIndexedValue) +) + +type mutation struct { + key kv.Key + flags kv.KeyFlags + value []byte + indexID int64 // only for index mutations +} + +type columnMaps struct { + ColumnIDToInfo map[int64]*model.ColumnInfo + ColumnIDToFieldType map[int64]*types.FieldType + IndexIDToInfo map[int64]*model.IndexInfo + IndexIDToRowColInfos map[int64][]rowcodec.ColInfo +} + +// CheckDataConsistency checks whether the given set of mutations corresponding to a single row is consistent. +// Namely, assume the database is consistent before, applying the mutations shouldn't break the consistency. +// It aims at reducing bugs that will corrupt data, and preventing mistakes from spreading if possible. +// +// 3 conditions are checked: +// (1) row.value is consistent with input data +// (2) the handle is consistent in row and index insertions +// (3) the keys of the indices are consistent with the values of rows +// +// The check doesn't work and just returns nil when: +// (1) the table is partitioned +// (2) new collation is enabled and restored data is needed +// +// The check is performed on almost every write. Its performance matters. +// Let M = the number of mutations, C = the number of columns in the table, +// I = the sum of the number of columns in all indices, +// The time complexity is O(M * C + I) +// The space complexity is O(M + C + I) +func CheckDataConsistency( + txn kv.Transaction, sessVars *variable.SessionVars, t *TableCommon, + rowToInsert, rowToRemove []types.Datum, memBuffer kv.MemBuffer, sh kv.StagingHandle, +) error { + if t.Meta().GetPartitionInfo() != nil { + return nil + } + if sh == 0 { + // some implementations of MemBuffer doesn't support staging, e.g. that in br/pkg/lightning/backend/kv + return nil + } + indexMutations, rowInsertion, err := collectTableMutationsFromBufferStage(t, memBuffer, sh) + if err != nil { + return errors.Trace(err) + } + + columnMaps := getColumnMaps(txn, t) + + if rowToInsert != nil { + if err := checkRowInsertionConsistency( + sessVars, rowToInsert, rowInsertion, columnMaps.ColumnIDToInfo, columnMaps.ColumnIDToFieldType, t.Meta().Name.O, + ); err != nil { + return errors.Trace(err) + } + } + + if err != nil { + return err + } + + if rowInsertion.key != nil { + if err = checkHandleConsistency(rowInsertion, indexMutations, columnMaps.IndexIDToInfo, t.Meta().Name.O); err != nil { + return errors.Trace(err) + } + } + + if err := checkIndexKeys( + sessVars, t, rowToInsert, rowToRemove, indexMutations, columnMaps.IndexIDToInfo, columnMaps.IndexIDToRowColInfos, + ); err != nil { + return errors.Trace(err) + } + return nil +} + +// checkHandleConsistency checks whether the handles, with regard to a single-row change, +// in row insertions and index insertions are consistent. +// A PUT_index implies a PUT_row with the same handle. +// Deletions are not checked since the values of deletions are unknown +func checkHandleConsistency(rowInsertion mutation, indexMutations []mutation, indexIDToInfo map[int64]*model.IndexInfo, tableName string) error { + var insertionHandle kv.Handle + var err error + + if rowInsertion.key == nil { + return nil + } + insertionHandle, err = tablecodec.DecodeRowKey(rowInsertion.key) + if err != nil { + return errors.Trace(err) + } + + for _, m := range indexMutations { + if len(m.value) == 0 { + continue + } + + indexInfo, ok := indexIDToInfo[m.indexID] + if !ok { + return errors.New("index not found") + } + + indexHandle, err := tablecodec.DecodeIndexHandle(m.key, m.value, len(indexInfo.Columns)) + if err != nil { + return errors.Trace(err) + } + // NOTE: handle type can be different, see issue 29520 + if indexHandle.IsInt() == insertionHandle.IsInt() && indexHandle.Compare(insertionHandle) != 0 { + err = ErrInconsistentHandle.GenWithStackByArgs(tableName, indexInfo.Name.O, indexHandle, insertionHandle, m, rowInsertion) + logutil.BgLogger().Error("inconsistent handle in index and record insertions", zap.Error(err)) + return err + } + } + + return err +} + +// checkIndexKeys checks whether the decoded data from keys of index mutations are consistent with the expected ones. +// +// How it works: +// +// Assume the set of row values changes from V1 to V2, we check +// (1) V2 - V1 = {added indices} +// (2) V1 - V2 = {deleted indices} +// +// To check (1), we need +// (a) {added indices} is a subset of {needed indices} => each index mutation is consistent with the input/row key/value +// (b) {needed indices} is a subset of {added indices}. The check process would be exactly the same with how we generate +// the mutations, thus ignored. +func checkIndexKeys( + sessVars *variable.SessionVars, t *TableCommon, rowToInsert, rowToRemove []types.Datum, + indexMutations []mutation, indexIDToInfo map[int64]*model.IndexInfo, + indexIDToRowColInfos map[int64][]rowcodec.ColInfo, +) error { + var indexData []types.Datum + for _, m := range indexMutations { + indexInfo, ok := indexIDToInfo[m.indexID] + if !ok { + return errors.New("index not found") + } + rowColInfos, ok := indexIDToRowColInfos[m.indexID] + if !ok { + return errors.New("index not found") + } + + // when we cannot decode the key to get the original value + if len(m.value) == 0 && NeedRestoredData(indexInfo.Columns, t.Meta().Columns) { + continue + } + + decodedIndexValues, err := tablecodec.DecodeIndexKV( + m.key, m.value, len(indexInfo.Columns), tablecodec.HandleNotNeeded, rowColInfos, + ) + if err != nil { + return errors.Trace(err) + } + + // reuse the underlying memory, save an allocation + if indexData == nil { + indexData = make([]types.Datum, 0, len(decodedIndexValues)) + } else { + indexData = indexData[:0] + } + + for i, v := range decodedIndexValues { + fieldType := &t.Columns[indexInfo.Columns[i].Offset].FieldType + datum, err := tablecodec.DecodeColumnValue(v, fieldType, sessVars.Location()) + if err != nil { + return errors.Trace(err) + } + indexData = append(indexData, datum) + } + + if len(m.value) == 0 { + err = compareIndexData(sessVars.StmtCtx, t.Columns, indexData, rowToRemove, indexInfo, t.Meta()) + } else { + err = compareIndexData(sessVars.StmtCtx, t.Columns, indexData, rowToInsert, indexInfo, t.Meta()) + } + if err != nil { + return errors.Trace(err) + } + } + return nil +} + +// checkRowInsertionConsistency checks whether the values of row mutations are consistent with the expected ones +// We only check data added since a deletion of a row doesn't care about its value (and we cannot know it) +func checkRowInsertionConsistency( + sessVars *variable.SessionVars, rowToInsert []types.Datum, rowInsertion mutation, + columnIDToInfo map[int64]*model.ColumnInfo, columnIDToFieldType map[int64]*types.FieldType, tableName string, +) error { + if rowToInsert == nil { + // it's a deletion + return nil + } + + decodedData, err := tablecodec.DecodeRowToDatumMap(rowInsertion.value, columnIDToFieldType, sessVars.Location()) + if err != nil { + return errors.Trace(err) + } + + // NOTE: we cannot check if the decoded values contain all columns since some columns may be skipped. It can even be empty + // Instead, we check that decoded index values are consistent with the input row. + + for columnID, decodedDatum := range decodedData { + inputDatum := rowToInsert[columnIDToInfo[columnID].Offset] + cmp, err := decodedDatum.Compare(sessVars.StmtCtx, &inputDatum, collate.GetCollator(decodedDatum.Collation())) + if err != nil { + return errors.Trace(err) + } + if cmp != 0 { + err = ErrInconsistentRowValue.GenWithStackByArgs(tableName, inputDatum.String(), decodedDatum.String()) + logutil.BgLogger().Error("inconsistent row value in row insertion", zap.Error(err)) + return err + } + } + return nil +} + +// collectTableMutationsFromBufferStage collects mutations of the current table from the mem buffer stage +// It returns: (1) all index mutations (2) the only row insertion +// If there are no row insertions, the 2nd returned value is nil +// If there are multiple row insertions, an error is returned +func collectTableMutationsFromBufferStage(t *TableCommon, memBuffer kv.MemBuffer, sh kv.StagingHandle) ( + []mutation, mutation, error, +) { + indexMutations := make([]mutation, 0) + var rowInsertion mutation + var err error + inspector := func(key kv.Key, flags kv.KeyFlags, data []byte) { + // only check the current table + if tablecodec.DecodeTableID(key) == t.physicalTableID { + m := mutation{key, flags, data, 0} + if rowcodec.IsRowKey(key) { + if len(data) > 0 { + if rowInsertion.key == nil { + rowInsertion = m + } else { + err = errors.Errorf( + "multiple row mutations added/mutated, one = %+v, another = %+v", rowInsertion, m, + ) + } + } + } else { + _, m.indexID, _, err = tablecodec.DecodeIndexKey(m.key) + if err != nil { + err = errors.Trace(err) + } + indexMutations = append(indexMutations, m) + } + } + } + memBuffer.InspectStage(sh, inspector) + return indexMutations, rowInsertion, err +} + +// compareIndexData compares the decoded index data with the input data. +// Returns error if the index data is not a subset of the input data. +func compareIndexData( + sc *stmtctx.StatementContext, cols []*table.Column, indexData, input []types.Datum, indexInfo *model.IndexInfo, + tableInfo *model.TableInfo, +) error { + for i := range indexData { + decodedMutationDatum := indexData[i] + expectedDatum := input[indexInfo.Columns[i].Offset] + + tablecodec.TruncateIndexValue( + &expectedDatum, indexInfo.Columns[i], + cols[indexInfo.Columns[i].Offset].ColumnInfo, + ) + tablecodec.TruncateIndexValue( + &decodedMutationDatum, indexInfo.Columns[i], + cols[indexInfo.Columns[i].Offset].ColumnInfo, + ) + + comparison, err := decodedMutationDatum.Compare(sc, &expectedDatum, collate.GetCollator(decodedMutationDatum.Collation())) + if err != nil { + return errors.Trace(err) + } + + if comparison != 0 { + err = ErrInconsistentIndexedValue.GenWithStackByArgs( + tableInfo.Name.O, indexInfo.Name.O, cols[indexInfo.Columns[i].Offset].ColumnInfo.Name.O, + decodedMutationDatum.String(), expectedDatum.String(), + ) + logutil.BgLogger().Error("inconsistent indexed value in index insertion", zap.Error(err)) + return err + } + } + return nil +} + +// getColumnMaps tries to get the columnMaps from transaction options. If there isn't one, it builds one and stores it. +// It saves redundant computations of the map. +func getColumnMaps(txn kv.Transaction, t *TableCommon) columnMaps { + getter := func() (map[int64]columnMaps, bool) { + m, ok := txn.GetOption(kv.TableToColumnMaps).(map[int64]columnMaps) + return m, ok + } + setter := func(maps map[int64]columnMaps) { + txn.SetOption(kv.TableToColumnMaps, maps) + } + columnMaps := getOrBuildColumnMaps(getter, setter, t) + return columnMaps +} + +// getOrBuildColumnMaps tries to get the columnMaps from some place. If there isn't one, it builds one and stores it. +// It saves redundant computations of the map. +func getOrBuildColumnMaps( + getter func() (map[int64]columnMaps, bool), setter func(map[int64]columnMaps), t *TableCommon, +) columnMaps { + tableMaps, ok := getter() + if !ok || tableMaps == nil { + tableMaps = make(map[int64]columnMaps) + } + maps, ok := tableMaps[t.tableID] + if !ok { + maps = columnMaps{ + make(map[int64]*model.ColumnInfo, len(t.Meta().Columns)), + make(map[int64]*types.FieldType, len(t.Meta().Columns)), + make(map[int64]*model.IndexInfo, len(t.Indices())), + make(map[int64][]rowcodec.ColInfo, len(t.Indices())), + } + + for _, col := range t.Meta().Columns { + maps.ColumnIDToInfo[col.ID] = col + maps.ColumnIDToFieldType[col.ID] = &col.FieldType + } + for _, index := range t.Indices() { + if index.Meta().Primary && t.meta.IsCommonHandle { + continue + } + maps.IndexIDToInfo[index.Meta().ID] = index.Meta() + maps.IndexIDToRowColInfos[index.Meta().ID] = BuildRowcodecColInfoForIndexColumns(index.Meta(), t.Meta()) + } + + tableMaps[t.tableID] = maps + setter(tableMaps) + } + return maps +} diff --git a/table/tables/mutation_checker_test.go b/table/tables/mutation_checker_test.go new file mode 100644 index 0000000000000..4a2bfd0508949 --- /dev/null +++ b/table/tables/mutation_checker_test.go @@ -0,0 +1,344 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tables + +import ( + "fmt" + "testing" + "time" + + "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/codec" + "github.com/pingcap/tidb/util/collate" + "github.com/pingcap/tidb/util/rowcodec" + "github.com/stretchr/testify/require" +) + +func TestCompareIndexData(t *testing.T) { + // dimensions of the domain of compareIndexData + // 1. table structure, where we only care about column types that influence truncating values + // 2. comparison of row data & index data + + type caseData struct { + indexData []types.Datum + inputData []types.Datum + fts []*types.FieldType + indexLength []int + correct bool + } + + // assume the index is on all columns + testData := []caseData{ + { + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string")}, + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string")}, + []*types.FieldType{types.NewFieldType(mysql.TypeShort), types.NewFieldType(mysql.TypeString)}, + []int{types.UnspecifiedLength, types.UnspecifiedLength}, + true, + }, + { + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string")}, + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string2")}, + []*types.FieldType{types.NewFieldType(mysql.TypeShort), types.NewFieldType(mysql.TypeString)}, + []int{types.UnspecifiedLength, types.UnspecifiedLength}, + false, + }, + { + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string")}, + []types.Datum{types.NewIntDatum(1), types.NewStringDatum("some string2")}, + []*types.FieldType{types.NewFieldType(mysql.TypeShort), types.NewFieldType(mysql.TypeString)}, + []int{types.UnspecifiedLength, 11}, + true, + }, + } + + for caseID, data := range testData { + sc := &stmtctx.StatementContext{} + cols := make([]*table.Column, 0) + indexCols := make([]*model.IndexColumn, 0) + for i, ft := range data.fts { + cols = append(cols, &table.Column{ColumnInfo: &model.ColumnInfo{Name: model.NewCIStr(fmt.Sprintf("c%d", i)), FieldType: *ft}}) + indexCols = append(indexCols, &model.IndexColumn{Offset: i, Length: data.indexLength[i]}) + } + indexInfo := &model.IndexInfo{Name: model.NewCIStr("i0"), Columns: indexCols} + + err := compareIndexData(sc, cols, data.indexData, data.inputData, indexInfo, &model.TableInfo{Name: model.NewCIStr("t")}) + require.Equal(t, data.correct, err == nil, "case id = %v", caseID) + } +} + +func TestCheckRowInsertionConsistency(t *testing.T) { + sessVars := variable.NewSessionVars() + rd := rowcodec.Encoder{Enable: true} + + // mocked data + mockRowKey233 := tablecodec.EncodeRowKeyWithHandle(1, kv.IntHandle(233)) + mockValue233, err := tablecodec.EncodeRow( + sessVars.StmtCtx, []types.Datum{types.NewIntDatum(233)}, []int64{101}, nil, nil, &rd, + ) + require.Nil(t, err) + fakeRowInsertion := mutation{key: []byte{1, 1}, value: []byte{1, 1, 1}} + + type caseData struct { + columnIDToInfo map[int64]*model.ColumnInfo + columnIDToFieldType map[int64]*types.FieldType + rowToInsert []types.Datum + rowInsertion mutation + correct bool + } + + testData := []caseData{ + { + // expected correct behavior + map[int64]*model.ColumnInfo{ + 101: { + ID: 101, + Offset: 0, + FieldType: *types.NewFieldType(mysql.TypeShort), + }, + }, + map[int64]*types.FieldType{ + 101: types.NewFieldType(mysql.TypeShort), + }, + []types.Datum{types.NewIntDatum(233)}, + mutation{key: mockRowKey233, value: mockValue233}, + true, + }, + { + // mismatching mutation + map[int64]*model.ColumnInfo{ + 101: { + ID: 101, + Offset: 0, + FieldType: *types.NewFieldType(mysql.TypeShort), + }, + }, + map[int64]*types.FieldType{ + 101: types.NewFieldType(mysql.TypeShort), + }, + []types.Datum{types.NewIntDatum(1)}, + fakeRowInsertion, + false, + }, + { + // no input row + map[int64]*model.ColumnInfo{}, + map[int64]*types.FieldType{}, + nil, + fakeRowInsertion, + true, + }, + { + // invalid value + map[int64]*model.ColumnInfo{ + 101: { + ID: 101, + Offset: 0, + FieldType: *types.NewFieldType(mysql.TypeShort), + }, + }, + map[int64]*types.FieldType{ + 101: types.NewFieldType(mysql.TypeShort), + }, + []types.Datum{types.NewIntDatum(233)}, + mutation{key: mockRowKey233, value: []byte{0, 1, 2, 3}}, + false, + }, + } + + for caseID, data := range testData { + err := checkRowInsertionConsistency( + sessVars, data.rowToInsert, data.rowInsertion, data.columnIDToInfo, data.columnIDToFieldType, "t", + ) + require.Equal(t, data.correct, err == nil, "case id = %v", caseID) + } +} + +func TestCheckIndexKeysAndCheckHandleConsistency(t *testing.T) { + // dimensions of the domain of checkIndexKeys: + // 1. location *2 + // 2. table structure + // (1) unique index/non-unique index *2 + // (2) clustered index *2 + // (3) string collation *2 + // We don't test primary clustered index and int handle, since they should not have index mutations. + // Assume PK is always the first column (string). + + // cases + locations := []*time.Location{time.UTC, time.Local} + indexInfos := []*model.IndexInfo{ + { + ID: 1, + State: model.StatePublic, + Primary: false, + Unique: true, + Columns: []*model.IndexColumn{ + { + Offset: 1, + Length: types.UnspecifiedLength, + }, + { + Offset: 0, + Length: types.UnspecifiedLength, + }, + }, + }, + { + ID: 2, + State: model.StatePublic, + Primary: false, + Unique: false, + Columns: []*model.IndexColumn{ + { + Offset: 1, + Length: types.UnspecifiedLength, + }, + { + Offset: 0, + Length: types.UnspecifiedLength, + }, + }, + }, + } + columnInfoSets := [][]*model.ColumnInfo{ + { + {ID: 1, Offset: 0, FieldType: *types.NewFieldType(mysql.TypeString)}, + {ID: 2, Offset: 1, FieldType: *types.NewFieldType(mysql.TypeDatetime)}, + }, + { + {ID: 1, Offset: 0, FieldType: *types.NewFieldTypeWithCollation(mysql.TypeString, "utf8_unicode_ci", + types.UnspecifiedLength)}, + {ID: 2, Offset: 1, FieldType: *types.NewFieldType(mysql.TypeDatetime)}, + }, + } + sessVars := variable.NewSessionVars() + rd := rowcodec.Encoder{Enable: true} + + now := types.CurrentTime(mysql.TypeDatetime) + rowToInsert := []types.Datum{ + types.NewStringDatum("some string"), + types.NewTimeDatum(now), + } + anotherTime, err := now.Add(sessVars.StmtCtx, types.NewDuration(24, 0, 0, 0, 0)) + require.Nil(t, err) + rowToRemove := []types.Datum{ + types.NewStringDatum("old string"), + types.NewTimeDatum(anotherTime), + } + + getter := func() (map[int64]columnMaps, bool) { + return nil, false + } + setter := func(maps map[int64]columnMaps) {} + + // test + collate.SetNewCollationEnabledForTest(true) + defer collate.SetNewCollationEnabledForTest(false) + for _, isCommonHandle := range []bool{true, false} { + for _, lc := range locations { + for _, columnInfos := range columnInfoSets { + sessVars.StmtCtx.TimeZone = lc + tableInfo := model.TableInfo{ + ID: 1, + Name: model.NewCIStr("t"), + Columns: columnInfos, + Indices: indexInfos, + PKIsHandle: false, + IsCommonHandle: isCommonHandle, + } + table := MockTableFromMeta(&tableInfo).(*TableCommon) + var handle, corruptedHandle kv.Handle + if isCommonHandle { + encoded, err := codec.EncodeKey(sessVars.StmtCtx, nil, rowToInsert[0]) + require.Nil(t, err) + corrupted := make([]byte, len(encoded)) + copy(corrupted, encoded) + corrupted[len(corrupted)-1] ^= 1 + handle, err = kv.NewCommonHandle(encoded) + require.Nil(t, err) + corruptedHandle, err = kv.NewCommonHandle(corrupted) + require.Nil(t, err) + } else { + handle = kv.IntHandle(1) + corruptedHandle = kv.IntHandle(2) + } + + for i, indexInfo := range indexInfos { + index := table.indices[i] + maps := getOrBuildColumnMaps(getter, setter, table) + + // test checkIndexKeys + insertionKey, insertionValue, err := buildIndexKeyValue(index, rowToInsert, sessVars, tableInfo, + indexInfo, table, handle) + require.Nil(t, err) + deletionKey, _, err := buildIndexKeyValue(index, rowToRemove, sessVars, tableInfo, indexInfo, table, + handle) + require.Nil(t, err) + indexMutations := []mutation{ + {key: insertionKey, value: insertionValue, indexID: indexInfo.ID}, + {key: deletionKey, indexID: indexInfo.ID}, + } + err = checkIndexKeys( + sessVars, table, rowToInsert, rowToRemove, indexMutations, maps.IndexIDToInfo, + maps.IndexIDToRowColInfos, + ) + require.Nil(t, err) + + // test checkHandleConsistency + rowKey := tablecodec.EncodeRowKeyWithHandle(table.tableID, handle) + corruptedRowKey := tablecodec.EncodeRowKeyWithHandle(table.tableID, corruptedHandle) + rowValue, err := tablecodec.EncodeRow(sessVars.StmtCtx, rowToInsert, []int64{1, 2}, nil, nil, &rd) + require.Nil(t, err) + rowMutation := mutation{key: rowKey, value: rowValue} + corruptedRowMutation := mutation{key: corruptedRowKey, value: rowValue} + err = checkHandleConsistency(rowMutation, indexMutations, maps.IndexIDToInfo, "t") + require.Nil(t, err) + err = checkHandleConsistency(corruptedRowMutation, indexMutations, maps.IndexIDToInfo, "t") + require.NotNil(t, err) + } + } + } + } +} + +func buildIndexKeyValue(index table.Index, rowToInsert []types.Datum, sessVars *variable.SessionVars, + tableInfo model.TableInfo, indexInfo *model.IndexInfo, table *TableCommon, handle kv.Handle) ([]byte, []byte, error) { + indexedValues, err := index.FetchValues(rowToInsert, nil) + if err != nil { + return nil, nil, err + } + key, distinct, err := tablecodec.GenIndexKey( + sessVars.StmtCtx, &tableInfo, indexInfo, 1, indexedValues, handle, nil, + ) + if err != nil { + return nil, nil, err + } + rsData := TryGetHandleRestoredDataWrapper(table, rowToInsert, nil, indexInfo) + value, err := tablecodec.GenIndexValuePortal( + sessVars.StmtCtx, &tableInfo, indexInfo, NeedRestoredData(indexInfo.Columns, tableInfo.Columns), + distinct, false, indexedValues, handle, 0, rsData, + ) + if err != nil { + return nil, nil, err + } + return key, value, nil +} diff --git a/table/tables/partition.go b/table/tables/partition.go index aa63eec05b89f..53a1aa02645e9 100644 --- a/table/tables/partition.go +++ b/table/tables/partition.go @@ -252,7 +252,16 @@ type ForListColumnPruning struct { ExprCol *expression.Column valueTp *types.FieldType valueMap map[string]ListPartitionLocation + mu sync.RWMutex sorted *btree.BTree + + // To deal with the location partition failure caused by inconsistent NewCollationEnabled values(see issue #32416). + // The following fields are used to delay building valueMap. + ctx sessionctx.Context + tblInfo *model.TableInfo + schema *expression.Schema + names types.NameSlice + colIdx int } // ListPartitionGroup indicate the group index of the column value in a partition. @@ -353,7 +362,7 @@ func (p *listPartitionLocationHelper) Intersect(location ListPartitionLocation) return true } currPgs := p.location - var remainPgs []ListPartitionGroup + remainPgs := make([]ListPartitionGroup, 0, len(location)) for _, pg := range location { idx := currPgs.findByPartitionIdx(pg.PartIdx) if idx < 0 { @@ -649,7 +658,6 @@ func (lp *ForListPruning) buildListColumnsPruner(ctx sessionctx.Context, tblInfo columns []*expression.Column, names types.NameSlice) error { pi := tblInfo.GetPartitionInfo() schema := expression.NewSchema(columns...) - p := parser.New() colPrunes := make([]*ForListColumnPruning, 0, len(pi.Columns)) for colIdx := range pi.Columns { colInfo := model.FindColumnInfo(tblInfo.Columns, pi.Columns[colIdx].L) @@ -661,15 +669,17 @@ func (lp *ForListPruning) buildListColumnsPruner(ctx sessionctx.Context, tblInfo return table.ErrUnknownColumn.GenWithStackByArgs(pi.Columns[colIdx].L) } colPrune := &ForListColumnPruning{ + ctx: ctx, + tblInfo: tblInfo, + schema: schema, + names: names, + colIdx: colIdx, ExprCol: columns[idx], valueTp: &colInfo.FieldType, valueMap: make(map[string]ListPartitionLocation), sorted: btree.New(btreeDegree), } - err := colPrune.buildPartitionValueMapAndSorted(ctx, tblInfo, colIdx, schema, names, p) - if err != nil { - return err - } + colPrunes = append(colPrunes, colPrune) } lp.ColPrunes = colPrunes @@ -753,13 +763,22 @@ func (lp *ForListPruning) locateListColumnsPartitionByRow(ctx sessionctx.Context // buildListPartitionValueMapAndSorted builds list columns partition value map for the specified column. // it also builds list columns partition value btree for the specified column. // colIdx is the specified column index in the list columns. -func (lp *ForListColumnPruning) buildPartitionValueMapAndSorted(ctx sessionctx.Context, tblInfo *model.TableInfo, colIdx int, - schema *expression.Schema, names types.NameSlice, p *parser.Parser) error { - pi := tblInfo.GetPartitionInfo() - sc := ctx.GetSessionVars().StmtCtx +func (lp *ForListColumnPruning) buildPartitionValueMapAndSorted() error { + lp.mu.RLock() + l := len(lp.valueMap) + lp.mu.RUnlock() + if l != 0 { + return nil + } + + p := parser.New() + pi := lp.tblInfo.GetPartitionInfo() + sc := lp.ctx.GetSessionVars().StmtCtx + lp.mu.Lock() + defer lp.mu.Unlock() for partitionIdx, def := range pi.Definitions { for groupIdx, vs := range def.InValues { - keyBytes, err := lp.genConstExprKey(ctx, sc, vs[colIdx], schema, names, p) + keyBytes, err := lp.genConstExprKey(lp.ctx, sc, vs[lp.colIdx], lp.schema, lp.names, p) if err != nil { return errors.Trace(err) } @@ -805,16 +824,25 @@ func (lp *ForListColumnPruning) genKey(sc *stmtctx.StatementContext, v types.Dat if err != nil { return nil, errors.Trace(err) } - return codec.EncodeKey(sc, nil, v) + valByte, err := codec.EncodeKey(sc, nil, v) + return valByte, err } // LocatePartition locates partition by the column value func (lp *ForListColumnPruning) LocatePartition(sc *stmtctx.StatementContext, v types.Datum) (ListPartitionLocation, error) { + // To deal with the location partition failure caused by inconsistent NewCollationEnabled values(see issue #32416). + err := lp.buildPartitionValueMapAndSorted() + if err != nil { + return nil, err + } + key, err := lp.genKey(sc, v) if err != nil { return nil, errors.Trace(err) } + lp.mu.RLock() location, ok := lp.valueMap[string(key)] + lp.mu.RUnlock() if !ok { return nil, nil } @@ -823,6 +851,13 @@ func (lp *ForListColumnPruning) LocatePartition(sc *stmtctx.StatementContext, v // LocateRanges locates partition ranges by the column range func (lp *ForListColumnPruning) LocateRanges(sc *stmtctx.StatementContext, r *ranger.Range) ([]ListPartitionLocation, error) { + // To deal with the location partition failure caused by inconsistent NewCollationEnabled values(see issue #32416). + err := lp.buildPartitionValueMapAndSorted() + if err != nil { + return nil, err + } + + var lowKey, highKey []byte lowVal := r.LowVal[0] if r.LowVal[0].Kind() == types.KindMinNotNull { lowVal = types.GetMinValue(lp.ExprCol.GetType()) @@ -831,23 +866,24 @@ func (lp *ForListColumnPruning) LocateRanges(sc *stmtctx.StatementContext, r *ra if r.HighVal[0].Kind() == types.KindMaxValue { highVal = types.GetMaxValue(lp.ExprCol.GetType()) } - lowKey, err := lp.genKey(sc, lowVal) - if err != nil { - return nil, errors.Trace(err) - } - highKey, err := lp.genKey(sc, highVal) - if err != nil { - return nil, errors.Trace(err) - } - if lp.ExprCol.GetType().EvalType() == types.ETString { - // for string type, values returned by GetMinValue and GetMaxValue are already encoded, - // so it's unnecessary to invoke genKey to encode them. - if r.LowVal[0].Kind() == types.KindMinNotNull { - lowKey = (&lowVal).GetBytes() + // For string type, values returned by GetMinValue and GetMaxValue are already encoded, + // so it's unnecessary to invoke genKey to encode them. + if lp.ExprCol.GetType().EvalType() == types.ETString && r.LowVal[0].Kind() == types.KindMinNotNull { + lowKey = (&lowVal).GetBytes() + } else { + lowKey, err = lp.genKey(sc, lowVal) + if err != nil { + return nil, errors.Trace(err) } - if r.HighVal[0].Kind() == types.KindMaxValue { - highKey = (&highVal).GetBytes() + } + + if lp.ExprCol.GetType().EvalType() == types.ETString && r.HighVal[0].Kind() == types.KindMaxValue { + highKey = (&highVal).GetBytes() + } else { + highKey, err = lp.genKey(sc, highVal) + if err != nil { + return nil, errors.Trace(err) } } @@ -903,6 +939,29 @@ func (t *partitionedTable) PartitionExpr() (*PartitionExpr, error) { return t.partitionExpr, nil } +func (t *partitionedTable) GetPartitionColumnNames() []model.CIStr { + // PARTITION BY {LIST|RANGE} COLUMNS uses columns directly without expressions + pi := t.Meta().Partition + if len(pi.Columns) > 0 { + return pi.Columns + } + + partitionCols := expression.ExtractColumns(t.partitionExpr.Expr) + colIDs := make([]int64, 0, len(partitionCols)) + for _, col := range partitionCols { + colIDs = append(colIDs, col.ID) + } + colNames := make([]model.CIStr, 0, len(partitionCols)) + for _, colID := range colIDs { + for _, col := range t.Cols() { + if col.ID == colID { + colNames = append(colNames, col.Name) + } + } + } + return colNames +} + // PartitionRecordKey is exported for test. func PartitionRecordKey(pid int64, handle int64) kv.Key { recordPrefix := tablecodec.GenTableRecordPrefix(pid) @@ -964,7 +1023,7 @@ func (t *partitionedTable) locateRangeColumnPartition(ctx sessionctx.Context, pi if err == nil { val, _, err := e.EvalInt(ctx, chunk.MutRowFromDatums(r).ToRow()) if err == nil { - valueMsg = fmt.Sprintf("%d", val) + valueMsg = strconv.FormatInt(val, 10) } } } else { diff --git a/table/tables/partition_test.go b/table/tables/partition_test.go index 4d99301684fd3..c5c781dd6b6fa 100644 --- a/table/tables/partition_test.go +++ b/table/tables/partition_test.go @@ -18,7 +18,6 @@ import ( "context" "testing" - "github.com/pingcap/tidb/ddl" mysql "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/model" @@ -27,6 +26,8 @@ import ( "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" + "github.com/pingcap/tidb/util/dbterror" "github.com/stretchr/testify/require" ) @@ -400,6 +401,47 @@ func TestLocatePartitionSingleColumn(t *testing.T) { require.True(t, table.ErrNoPartitionForGivenValue.Equal(err)) } +func TestLocatePartition(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_enable_list_partition = ON;") + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic';") + tk.MustExec("drop table if exists t;") + + tk.MustExec(`CREATE TABLE t ( + id bigint(20) DEFAULT NULL, + type varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + PARTITION BY LIST COLUMNS(type) + (PARTITION push_event VALUES IN ("PushEvent"), + PARTITION watch_event VALUES IN ("WatchEvent") + );`) + + tk1 := testkit.NewTestKit(t, store) + tk2 := testkit.NewTestKit(t, store) + tk3 := testkit.NewTestKit(t, store) + tks := []*testkit.TestKit{tk1, tk2, tk3} + + wg := util.WaitGroupWrapper{} + exec := func(tk0 *testkit.TestKit) { + tk0.MustExec("use test") + tk0.MustQuery("desc select id, type from t where type = 'WatchEvent';").Check(testkit.Rows("TableReader_7 10.00 root partition:watch_event data:Selection_6]\n[└─Selection_6 10.00 cop[tikv] eq(test.t.type, \"WatchEvent\")]\n[ └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) + } + + run := func(num int) { + tk := tks[num] + wg.Run(func() { + exec(tk) + }) + } + for i := 0; i < len(tks); i++ { + run(i) + } + wg.Wait() +} + func TestTimeZoneChange(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() @@ -465,13 +507,13 @@ func TestCreatePartitionTableNotSupport(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") _, err := tk.Exec(`create table t7 (a int) partition by range (mod((select * from t), 5)) (partition p1 values less than (1));`) - require.True(t, ddl.ErrPartitionFunctionIsNotAllowed.Equal(err)) + require.True(t, dbterror.ErrPartitionFunctionIsNotAllowed.Equal(err)) _, err = tk.Exec(`create table t7 (a int) partition by range (1 + (select * from t)) (partition p1 values less than (1));`) - require.True(t, ddl.ErrPartitionFunctionIsNotAllowed.Equal(err)) + require.True(t, dbterror.ErrPartitionFunctionIsNotAllowed.Equal(err)) _, err = tk.Exec(`create table t7 (a int) partition by range (a + row(1, 2, 3)) (partition p1 values less than (1));`) - require.True(t, ddl.ErrPartitionFunctionIsNotAllowed.Equal(err)) + require.True(t, dbterror.ErrPartitionFunctionIsNotAllowed.Equal(err)) _, err = tk.Exec(`create table t7 (a int) partition by range (-(select * from t)) (partition p1 values less than (1));`) - require.True(t, ddl.ErrPartitionFunctionIsNotAllowed.Equal(err)) + require.True(t, dbterror.ErrPartitionFunctionIsNotAllowed.Equal(err)) } func TestRangePartitionUnderNoUnsigned(t *testing.T) { @@ -608,3 +650,81 @@ func TestIssue24746(t *testing.T) { err = tk.ExecToErr("insert into t_24746 partition (p1) values(4,'ERROR, not allowed to read from partition p0',4) on duplicate key update a = a + 1, b = 'ERROR, not allowed to read from p0!'") require.True(t, table.ErrRowDoesNotMatchGivenPartitionSet.Equal(err)) } + +func TestIssue31629(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_enable_list_partition = 1") + tk.MustExec("create database Issue31629") + defer tk.MustExec("drop database Issue31629") + tk.MustExec("use Issue31629") + // Test following partition types: + // HASH, RANGE, LIST: + // - directly on a single int column + // - with expression on multiple columns + // RANGE/LIST COLUMNS single column + // RANGE/LIST COLUMNS -- Verify that only single column is allowed and no expression + tests := []struct { + create string + fail bool + cols []string + }{ + {"(col1 int, col2 varchar(60), col3 int, primary key(col1)) partition by range(col1) (partition p0 values less than (5),partition p1 values less than (10), partition p2 values less than maxvalue)", false, []string{"col1"}}, + {"(Col1 int, col2 varchar(60), col3 int, primary key(Col1,col3)) partition by range(Col1+col3) (partition p0 values less than (5),partition p1 values less than (10), partition p2 values less than maxvalue)", false, []string{"Col1", "col3"}}, + {"(col1 int, col2 varchar(60), col3 int, primary key(col1)) partition by hash(col1) partitions 3", false, []string{"col1"}}, + {"(Col1 int, col2 varchar(60), col3 int, primary key(Col1,col3)) partition by hash(Col1+col3) partitions 3", false, []string{"Col1", "col3"}}, + {"(col1 int, col2 varchar(60), col3 int, primary key(col1)) partition by list(col1) (partition p0 values in (5,6,7,8,9),partition p1 values in (10,11,12,13,14), partition p2 values in (20,21,22,23,24))", false, []string{"col1"}}, + {"(Col1 int, col2 varchar(60), col3 int, primary key(Col1,col3)) partition by list(Col1+col3) (partition p0 values in (5,6,7,8,9),partition p1 values in (10,11,12,13,14), partition p2 values in (20,21,22,23,24))", false, []string{"Col1", "col3"}}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by range columns (col2) (partition p0 values less than (""),partition p1 values less than ("MID"), partition p2 values less than maxvalue)`, false, []string{"col2"}}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by range columns (col2,col3) (partition p0 values less than (""),partition p1 values less than ("MID"), partition p2 values less than maxvalue)`, true, nil}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by range columns (col1+1) (partition p0 values less than (""),partition p1 values less than ("MID"), partition p2 values less than maxvalue)`, true, nil}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by list columns (col2) (partition p0 values in ("","First"),partition p1 values in ("MID","Middle"), partition p2 values in ("Last","Unknown"))`, false, []string{"col2"}}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by list columns (col2,col3) (partition p0 values in ("","First"),partition p1 values in ("MID","Middle"), partition p2 values in ("Last","Unknown"))`, true, nil}, + {`(col1 int, col2 varchar(60), col3 int, primary key(col2)) partition by list columns (col1+1) (partition p0 values in ("","First"),partition p1 values in ("MID","Middle"), partition p2 values in ("Last","Unknown"))`, true, nil}, + } + + for i, tt := range tests { + + createTable := "create table t1 " + tt.create + res, err := tk.Exec(createTable) + if res != nil { + res.Close() + } + if err != nil { + if tt.fail { + continue + } + } + require.Falsef(t, tt.fail, "test %d succeeded but was expected to fail! %s", i, createTable) + require.NoError(t, err) + tk.MustQuery("show warnings").Check(testkit.Rows()) + + tb, err := dom.InfoSchema().TableByName(model.NewCIStr("Issue31629"), model.NewCIStr("t1")) + require.NoError(t, err) + tbp, ok := tb.(table.PartitionedTable) + require.Truef(t, ok, "test %d does not generate a table.PartitionedTable: %s (%T, %+v)", i, createTable, tb, tb) + colNames := tbp.GetPartitionColumnNames() + checkNames := []model.CIStr{model.NewCIStr(tt.cols[0])} + for i := 1; i < len(tt.cols); i++ { + checkNames = append(checkNames, model.NewCIStr(tt.cols[i])) + } + require.ElementsMatchf(t, colNames, checkNames, "test %d %s", i, createTable) + tk.MustExec("drop table t1") + } +} + +func TestIssue31721(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_enable_list_partition=on;") + tk.MustExec("drop tables if exists t_31721") + tk.MustExec("CREATE TABLE `t_31721` (`COL1` char(1) NOT NULL) CHARSET=utf8mb4 COLLATE=utf8mb4_bin PARTITION BY LIST COLUMNS(`COL1`) " + + "(PARTITION `P0` VALUES IN ('1')," + + "PARTITION `P1` VALUES IN ('2')," + + "PARTITION `P2` VALUES IN ('3'));") + tk.MustExec("insert into t_31721 values ('1')") + tk.MustExec("select * from t_31721 partition(p0, p1) where col1 != 2;") +} diff --git a/table/tables/state_remote.go b/table/tables/state_remote.go index aeddd5b972ab2..4a8d0b39b632c 100644 --- a/table/tables/state_remote.go +++ b/table/tables/state_remote.go @@ -17,7 +17,6 @@ package tables import ( "context" "strconv" - "sync" "time" "github.com/pingcap/errors" @@ -56,6 +55,7 @@ func (l CachedTableLockType) String() string { } // StateRemote is the interface to control the remote state of the cached table's lock meta information. +// IMPORTANT: It's not thread-safe, the caller should be aware of that! type StateRemote interface { // Load obtain the corresponding lock type and lease value according to the tableID Load(ctx context.Context, tid int64) (CachedTableLockType, uint64, error) @@ -67,10 +67,13 @@ type StateRemote interface { LockForRead(ctx context.Context, tid int64, lease uint64) (bool, error) // LockForWrite try to add a write lock to the table with the specified tableID - LockForWrite(ctx context.Context, tid int64) (uint64, error) + LockForWrite(ctx context.Context, tid int64, leaseDuration time.Duration) (uint64, error) - // RenewLease attempt to renew the read / write lock on the table with the specified tableID - RenewLease(ctx context.Context, tid int64, newTs uint64, op RenewLeaseType) (bool, error) + // RenewReadLease attempt to renew the read lock lease on the table with the specified tableID + RenewReadLease(ctx context.Context, tid int64, oldLocalLease, newValue uint64) (uint64, error) + + // RenewWriteLease attempt to renew the write lock lease on the table with the specified tableID + RenewWriteLease(ctx context.Context, tid int64, newTs uint64) (bool, error) } type sqlExec interface { @@ -79,7 +82,13 @@ type sqlExec interface { type stateRemoteHandle struct { exec sqlExec - sync.Mutex + + // local state, this could be staled. + // Since stateRemoteHandle is used in single thread, it's safe for all operations + // to check the local state first to avoid unnecessary remote TiKV access. + lockType CachedTableLockType + lease uint64 + oldReadLease uint64 } // NewStateRemote creates a StateRemote object. @@ -92,23 +101,29 @@ func NewStateRemote(exec sqlExec) *stateRemoteHandle { var _ StateRemote = &stateRemoteHandle{} func (h *stateRemoteHandle) Load(ctx context.Context, tid int64) (CachedTableLockType, uint64, error) { - lockType, lease, _, err := h.loadRow(ctx, tid) + lockType, lease, _, err := h.loadRow(ctx, tid, false) return lockType, lease, err } -func (h *stateRemoteHandle) LockForRead(ctx context.Context, tid int64, ts uint64) ( /*succ*/ bool, error) { - h.Lock() - defer h.Unlock() +func (h *stateRemoteHandle) LockForRead(ctx context.Context, tid int64, newLease uint64) ( /*succ*/ bool, error) { succ := false - err := h.runInTxn(ctx, func(ctx context.Context, now uint64) error { - lockType, lease, _, err := h.loadRow(ctx, tid) + if h.lease >= newLease { + // There is a write lock or intention, don't lock for read. + switch h.lockType { + case CachedTableLockIntend, CachedTableLockWrite: + return false, nil + } + } + + err := h.runInTxn(ctx, false, func(ctx context.Context, now uint64) error { + lockType, lease, _, err := h.loadRow(ctx, tid, false) if err != nil { return errors.Trace(err) } // The old lock is outdated, clear orphan lock. if now > lease { succ = true - if err := h.updateRow(ctx, tid, "READ", ts); err != nil { + if err := h.updateRow(ctx, tid, "READ", newLease); err != nil { return errors.Trace(err) } return nil @@ -121,8 +136,8 @@ func (h *stateRemoteHandle) LockForRead(ctx context.Context, tid int64, ts uint6 return nil } succ = true - if ts > lease { // Note the check, don't decrease lease value! - if err := h.updateRow(ctx, tid, "READ", ts); err != nil { + if newLease > lease { // Note the check, don't decrease lease value! + if err := h.updateRow(ctx, tid, "READ", newLease); err != nil { return errors.Trace(err) } } @@ -133,12 +148,20 @@ func (h *stateRemoteHandle) LockForRead(ctx context.Context, tid int64, ts uint6 } // LockForWrite try to add a write lock to the table with the specified tableID, return the write lock lease. -func (h *stateRemoteHandle) LockForWrite(ctx context.Context, tid int64) (uint64, error) { - h.Lock() - defer h.Unlock() +func (h *stateRemoteHandle) LockForWrite(ctx context.Context, tid int64, leaseDuration time.Duration) (uint64, error) { var ret uint64 + + if h.lockType == CachedTableLockWrite { + safe := oracle.GoTimeToTS(time.Now().Add(leaseDuration / 2)) + if h.lease > safe { + // It means the remote has already been write locked and the lock will be valid for a while. + // So we can return directly. + return h.lease, nil + } + } + for { - waitAndRetry, lease, err := h.lockForWriteOnce(ctx, tid) + waitAndRetry, lease, err := h.lockForWriteOnce(ctx, tid, leaseDuration) if err != nil { return 0, err } @@ -151,13 +174,20 @@ func (h *stateRemoteHandle) LockForWrite(ctx context.Context, tid int64) (uint64 return ret, nil } -func (h *stateRemoteHandle) lockForWriteOnce(ctx context.Context, tid int64) (waitAndRetry time.Duration, ts uint64, err error) { - err = h.runInTxn(ctx, func(ctx context.Context, now uint64) error { - lockType, lease, oldReadLease, err := h.loadRow(ctx, tid) +func (h *stateRemoteHandle) lockForWriteOnce(ctx context.Context, tid int64, leaseDuration time.Duration) (waitAndRetry time.Duration, ts uint64, err error) { + var ( + _updateLocal bool + _lockType CachedTableLockType + _lease uint64 + _oldReadLease uint64 + ) + + err = h.runInTxn(ctx, true, func(ctx context.Context, now uint64) error { + lockType, lease, oldReadLease, err := h.loadRow(ctx, tid, true) if err != nil { return errors.Trace(err) } - ts = leaseFromTS(now) + ts = leaseFromTS(now, leaseDuration) // The lease is outdated, so lock is invalid, clear orphan lock of any kind. if now > lease { if err := h.updateRow(ctx, tid, "WRITE", ts); err != nil { @@ -172,6 +202,11 @@ func (h *stateRemoteHandle) lockForWriteOnce(ctx context.Context, tid int64) (wa if err = h.updateRow(ctx, tid, "WRITE", ts); err != nil { return errors.Trace(err) } + { + _updateLocal = true + _lockType = CachedTableLockWrite + _lease = ts + } case CachedTableLockRead: // Change from READ to INTEND if _, err = h.execSQL(ctx, @@ -184,23 +219,47 @@ func (h *stateRemoteHandle) lockForWriteOnce(ctx context.Context, tid int64) (wa // Wait for lease to expire, and then retry. waitAndRetry = waitForLeaseExpire(lease, now) + { + _updateLocal = true + _lockType = CachedTableLockIntend + _oldReadLease = lease + _lease = ts + } case CachedTableLockIntend: // `now` exceed `oldReadLease` means wait for READ lock lease is done, it's safe to read here. if now > oldReadLease { - if lockType == CachedTableLockIntend { - if err = h.updateRow(ctx, tid, "WRITE", ts); err != nil { - return errors.Trace(err) - } + if err = h.updateRow(ctx, tid, "WRITE", ts); err != nil { + return errors.Trace(err) + } + { + _updateLocal = true + _lockType = CachedTableLockWrite + _lease = ts } return nil } // Otherwise, the WRITE should wait for the READ lease expire. // And then retry changing the lock to WRITE waitAndRetry = waitForLeaseExpire(oldReadLease, now) + case CachedTableLockWrite: + if err = h.updateRow(ctx, tid, "WRITE", ts); err != nil { + return errors.Trace(err) + } + { + _updateLocal = true + _lockType = CachedTableLockWrite + _lease = ts + } } return nil }) + if err == nil && _updateLocal { + h.lockType = _lockType + h.lease = _lease + h.oldReadLease = _oldReadLease + } + return } @@ -208,33 +267,26 @@ func waitForLeaseExpire(oldReadLease, now uint64) time.Duration { if oldReadLease >= now { t1 := oracle.GetTimeFromTS(oldReadLease) t2 := oracle.GetTimeFromTS(now) - waitDuration := t1.Sub(t2) - return waitDuration + if t1.After(t2) { + waitDuration := t1.Sub(t2) + return waitDuration + } + return time.Microsecond } return 0 } -func (h *stateRemoteHandle) RenewLease(ctx context.Context, tid int64, newLease uint64, op RenewLeaseType) (bool, error) { - h.Lock() - defer h.Unlock() - - switch op { - case RenewReadLease: - return h.renewReadLease(ctx, tid, newLease) - case RenewWriteLease: - return h.renewWriteLease(ctx, tid, newLease) - } - return false, errors.New("wrong renew lease type") -} - -func (h *stateRemoteHandle) renewReadLease(ctx context.Context, tid int64, newLease uint64) (bool, error) { - var succ bool - err := h.runInTxn(ctx, func(ctx context.Context, now uint64) error { - lockType, oldLease, _, err := h.loadRow(ctx, tid) +// RenewReadLease renew the read lock lease. +// Return the current lease value on success, and return 0 on fail. +func (h *stateRemoteHandle) RenewReadLease(ctx context.Context, tid int64, oldLocalLease, newValue uint64) (uint64, error) { + var newLease uint64 + err := h.runInTxn(ctx, false, func(ctx context.Context, now uint64) error { + lockType, remoteLease, _, err := h.loadRow(ctx, tid, false) if err != nil { return errors.Trace(err) } - if now >= oldLease { + + if now >= remoteLease { // read lock had already expired, fail to renew return nil } @@ -243,22 +295,44 @@ func (h *stateRemoteHandle) renewReadLease(ctx context.Context, tid int64, newLe return nil } - if newLease > oldLease { // lease should never decrease! - err = h.updateRow(ctx, tid, "READ", newLease) + // It means that the lease had already been changed by some other TiDB instances. + if oldLocalLease != remoteLease { + // 1. Data in [cacheDataTS -------- oldLocalLease) time range is also immutable. + // 2. Data in [ now ------------------- remoteLease) time range is immutable. + // + // If now < oldLocalLease, it means data in all the time range is immutable, + // so the old cache data is still available. + if now < oldLocalLease { + newLease = remoteLease + } + // Otherwise, there might be write operation during the oldLocalLease and the new remoteLease + // Make renew lease operation fail. + return nil + } + + if newValue > remoteLease { // lease should never decrease! + err = h.updateRow(ctx, tid, "READ", newValue) if err != nil { return errors.Trace(err) } + newLease = newValue + } else { + newLease = remoteLease } - succ = true return nil }) - return succ, err + + return newLease, err } -func (h *stateRemoteHandle) renewWriteLease(ctx context.Context, tid int64, newLease uint64) (bool, error) { +func (h *stateRemoteHandle) RenewWriteLease(ctx context.Context, tid int64, newLease uint64) (bool, error) { var succ bool - err := h.runInTxn(ctx, func(ctx context.Context, now uint64) error { - lockType, oldLease, _, err := h.loadRow(ctx, tid) + var ( + _lockType CachedTableLockType + _lease uint64 + ) + err := h.runInTxn(ctx, true, func(ctx context.Context, now uint64) error { + lockType, oldLease, _, err := h.loadRow(ctx, tid, true) if err != nil { return errors.Trace(err) } @@ -278,13 +352,25 @@ func (h *stateRemoteHandle) renewWriteLease(ctx context.Context, tid int64, newL } } succ = true + _lockType = CachedTableLockWrite + _lease = newLease return nil }) + + if succ { + h.lockType = _lockType + h.lease = _lease + } return succ, err } -func (h *stateRemoteHandle) beginTxn(ctx context.Context) error { - _, err := h.execSQL(ctx, "begin") +func (h *stateRemoteHandle) beginTxn(ctx context.Context, pessimistic bool) error { + var err error + if pessimistic { + _, err = h.execSQL(ctx, "begin pessimistic") + } else { + _, err = h.execSQL(ctx, "begin optimistic") + } return err } @@ -298,8 +384,13 @@ func (h *stateRemoteHandle) rollbackTxn(ctx context.Context) error { return err } -func (h *stateRemoteHandle) runInTxn(ctx context.Context, fn func(ctx context.Context, txnTS uint64) error) error { - err := h.beginTxn(ctx) +func (h *stateRemoteHandle) runInTxn(ctx context.Context, pessimistic bool, fn func(ctx context.Context, txnTS uint64) error) error { + err := h.beginTxn(ctx, pessimistic) + if err != nil { + return errors.Trace(err) + } + + _, err = h.execSQL(ctx, "set @@session.tidb_retry_limit = 0") if err != nil { return errors.Trace(err) } @@ -323,8 +414,14 @@ func (h *stateRemoteHandle) runInTxn(ctx context.Context, fn func(ctx context.Co return h.commitTxn(ctx) } -func (h *stateRemoteHandle) loadRow(ctx context.Context, tid int64) (CachedTableLockType, uint64, uint64, error) { - chunkRows, err := h.execSQL(ctx, "select lock_type, lease, oldReadLease from mysql.table_cache_meta where tid = %? for update", tid) +func (h *stateRemoteHandle) loadRow(ctx context.Context, tid int64, forUpdate bool) (CachedTableLockType, uint64, uint64, error) { + var chunkRows []chunk.Row + var err error + if forUpdate { + chunkRows, err = h.execSQL(ctx, "select lock_type, lease, oldReadLease from mysql.table_cache_meta where tid = %? for update", tid) + } else { + chunkRows, err = h.execSQL(ctx, "select lock_type, lease, oldReadLease from mysql.table_cache_meta where tid = %?", tid) + } if err != nil { return 0, 0, 0, errors.Trace(err) } @@ -336,6 +433,12 @@ func (h *stateRemoteHandle) loadRow(ctx context.Context, tid int64) (CachedTable lockType := CachedTableLockType(col1.Value - 1) lease := chunkRows[0].GetUint64(1) oldReadLease := chunkRows[0].GetUint64(2) + + // Also store a local copy after loadRow() + h.lockType = lockType + h.lease = lease + h.oldReadLease = oldReadLease + return lockType, lease, oldReadLease, nil } diff --git a/table/tables/state_remote_test.go b/table/tables/state_remote_test.go index dc4e9272b1830..5d75c5e47d129 100644 --- a/table/tables/state_remote_test.go +++ b/table/tables/state_remote_test.go @@ -79,9 +79,9 @@ func TestStateRemote(t *testing.T) { // Renew read lock lease operation. leaseVal = oracle.GoTimeToTS(physicalTime.Add(400 * time.Millisecond)) - succ, err = h.RenewLease(ctx, 5, leaseVal, tables.RenewReadLease) + leaseVal, err = h.RenewReadLease(ctx, 5, lease, leaseVal) require.NoError(t, err) - require.True(t, succ) + require.True(t, leaseVal > 0) lockType, lease, err = h.Load(ctx, 5) require.NoError(t, err) require.Equal(t, lockType, tables.CachedTableLockRead) @@ -89,7 +89,7 @@ func TestStateRemote(t *testing.T) { require.Equal(t, lease, leaseVal) // Check write lock. - writeLease, err := h.LockForWrite(ctx, 5) + writeLease, err := h.LockForWrite(ctx, 5, 3*time.Second) require.NoError(t, err) lockType, lease, err = h.Load(ctx, 5) require.NoError(t, err) @@ -99,25 +99,25 @@ func TestStateRemote(t *testing.T) { require.Greater(t, writeLease, leaseVal) // Lock for write again - writeLease, err = h.LockForWrite(ctx, 5) + writeLease, err = h.LockForWrite(ctx, 5, 3*time.Second) require.NoError(t, err) - lockType, _, err = h.Load(ctx, 5) + lockType, lease, err = h.Load(ctx, 5) require.NoError(t, err) require.Equal(t, lockType, tables.CachedTableLockWrite) require.Equal(t, lockType.String(), "WRITE") // Renew read lock lease should fail when the write lock is hold. - succ, err = h.RenewLease(ctx, 5, leaseVal, tables.RenewReadLease) + leaseVal, err = h.RenewReadLease(ctx, 5, lease, lease+1) require.NoError(t, err) - require.False(t, succ) + require.False(t, leaseVal > 0) // Acquire read lock should also fail when the write lock is hold. - succ, err = h.LockForRead(ctx, 5, leaseVal) + succ, err = h.LockForRead(ctx, 5, lease+1) require.NoError(t, err) require.False(t, succ) // Renew write lease. - succ, err = h.RenewLease(ctx, 5, writeLease+1, tables.RenewWriteLease) + succ, err = h.RenewWriteLease(ctx, 5, writeLease+1) require.NoError(t, err) require.True(t, succ) diff --git a/table/tables/tables.go b/table/tables/tables.go index 716b2e879cbcc..8fee9660a698d 100644 --- a/table/tables/tables.go +++ b/table/tables/tables.go @@ -28,6 +28,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/meta/autoid" @@ -429,6 +430,27 @@ func (t *TableCommon) UpdateRecord(ctx context.Context, sctx sessionctx.Context, if err = memBuffer.Set(key, value); err != nil { return err } + + failpoint.Inject("updateRecordForceAssertNotExist", func() { + // Assert the key doesn't exist while it actually exists. This is helpful to test if assertion takes effect. + // Since only the first assertion takes effect, set the injected assertion before setting the correct one to + // override it. + if sctx.GetSessionVars().ConnectionID != 0 { + logutil.BgLogger().Info("[failpoint] force asserting not exist on UpdateRecord", zap.Uint64("startTS", txn.StartTS())) + if err = txn.SetAssertion(key, kv.SetAssertNotExist); err != nil { + failpoint.Return(err) + } + } + }) + if err = txn.SetAssertion(key, kv.SetAssertExist); err != nil { + return err + } + + if sessVars.EnableMutationChecker { + if err = CheckDataConsistency(txn, sessVars, t, newData, oldData, memBuffer, sh); err != nil { + return errors.Trace(err) + } + } memBuffer.Release(sh) if shouldWriteBinlog(sctx, t.meta) { if !t.meta.PKIsHandle && !t.meta.IsCommonHandle { @@ -829,6 +851,26 @@ func (t *TableCommon) AddRecord(sctx sessionctx.Context, r []types.Datum, opts . return nil, err } + failpoint.Inject("addRecordForceAssertExist", func() { + // Assert the key exists while it actually doesn't. This is helpful to test if assertion takes effect. + // Since only the first assertion takes effect, set the injected assertion before setting the correct one to + // override it. + if sctx.GetSessionVars().ConnectionID != 0 { + logutil.BgLogger().Info("[failpoint] force asserting exist on AddRecord", zap.Uint64("startTS", txn.StartTS())) + if err = txn.SetAssertion(key, kv.SetAssertExist); err != nil { + failpoint.Return(nil, err) + } + } + }) + if setPresume && !txn.IsPessimistic() { + err = txn.SetAssertion(key, kv.SetAssertUnknown) + } else { + err = txn.SetAssertion(key, kv.SetAssertNotExist) + } + if err != nil { + return nil, err + } + var createIdxOpts []table.CreateIdxOptFunc if len(opts) > 0 { createIdxOpts = make([]table.CreateIdxOptFunc, 0, len(opts)) @@ -844,6 +886,12 @@ func (t *TableCommon) AddRecord(sctx sessionctx.Context, r []types.Datum, opts . return h, err } + if sessVars.EnableMutationChecker { + if err = CheckDataConsistency(txn, sessVars, t, r, nil, memBuffer, sh); err != nil { + return nil, errors.Trace(err) + } + } + memBuffer.Release(sh) if shouldWriteBinlog(sctx, t.meta) { @@ -1055,15 +1103,20 @@ func GetChangingColVal(ctx sessionctx.Context, cols []*table.Column, col *table. // RemoveRecord implements table.Table RemoveRecord interface. func (t *TableCommon) RemoveRecord(ctx sessionctx.Context, h kv.Handle, r []types.Datum) error { - err := t.removeRowData(ctx, h) + txn, err := ctx.Txn(true) if err != nil { return err } - txn, err := ctx.Txn(true) + memBuffer := txn.GetMemBuffer() + sh := memBuffer.Staging() + defer memBuffer.Cleanup(sh) + + err = t.removeRowData(ctx, h) if err != nil { return err } + if m := t.Meta(); m.TempTableType != model.TempTableNone { if tmpTable := addTemporaryTable(ctx, m); tmpTable != nil { if err := checkTempTableSize(ctx, tmpTable, m); err != nil { @@ -1091,6 +1144,15 @@ func (t *TableCommon) RemoveRecord(ctx sessionctx.Context, h kv.Handle, r []type return err } + sessVars := ctx.GetSessionVars() + sc := sessVars.StmtCtx + if sessVars.EnableMutationChecker { + if err = CheckDataConsistency(txn, sessVars, t, nil, r, memBuffer, sh); err != nil { + return errors.Trace(err) + } + } + memBuffer.Release(sh) + if shouldWriteBinlog(ctx, t.meta) { cols := t.Cols() colIDs := make([]int64, 0, len(cols)+1) @@ -1116,7 +1178,6 @@ func (t *TableCommon) RemoveRecord(ctx sessionctx.Context, h kv.Handle, r []type return nil } colSize := make(map[int64]int64, len(t.Cols())) - sc := ctx.GetSessionVars().StmtCtx for id, col := range t.Cols() { size, err := codec.EstimateValueSize(sc, r[id]) if err != nil { @@ -1206,6 +1267,21 @@ func (t *TableCommon) removeRowData(ctx sessionctx.Context, h kv.Handle) error { } key := t.RecordKey(h) + failpoint.Inject("removeRecordForceAssertNotExist", func() { + // Assert the key doesn't exist while it actually exists. This is helpful to test if assertion takes effect. + // Since only the first assertion takes effect, set the injected assertion before setting the correct one to + // override it. + if ctx.GetSessionVars().ConnectionID != 0 { + logutil.BgLogger().Info("[failpoint] force asserting not exist on RemoveRecord", zap.Uint64("startTS", txn.StartTS())) + if err = txn.SetAssertion(key, kv.SetAssertNotExist); err != nil { + failpoint.Return(err) + } + } + }) + err = txn.SetAssertion(key, kv.SetAssertExist) + if err != nil { + return err + } return txn.Delete(key) } @@ -1843,6 +1919,20 @@ func BuildTableScanFromInfos(tableInfo *model.TableInfo, columnInfos []*model.Co return tsExec } +// BuildPartitionTableScanFromInfos build tipb.PartitonTableScan with *model.TableInfo and *model.ColumnInfo. +func BuildPartitionTableScanFromInfos(tableInfo *model.TableInfo, columnInfos []*model.ColumnInfo) *tipb.PartitionTableScan { + pkColIds := TryGetCommonPkColumnIds(tableInfo) + tsExec := &tipb.PartitionTableScan{ + TableId: tableInfo.ID, + Columns: util.ColumnsToProto(columnInfos, tableInfo.PKIsHandle), + PrimaryColumnIds: pkColIds, + } + if tableInfo.IsCommonHandle { + tsExec.PrimaryPrefixColumnIds = PrimaryPrefixColumnIDs(tableInfo) + } + return tsExec +} + // TemporaryTable is used to store transaction-specific or session-specific information for global / local temporary tables. // For example, stats and autoID should have their own copies of data, instead of being shared by all sessions. type TemporaryTable struct { diff --git a/table/tables/tables_test.go b/table/tables/tables_test.go index b093e96c6be38..4b9ad5fa089f3 100644 --- a/table/tables/tables_test.go +++ b/table/tables/tables_test.go @@ -16,18 +16,21 @@ package tables_test import ( "context" + "fmt" "math" "strconv" "testing" "time" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" @@ -35,8 +38,7 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util" - "github.com/pingcap/tidb/util/testutil" - binlog "github.com/pingcap/tipb/go-binlog" + "github.com/pingcap/tipb/go-binlog" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) @@ -496,11 +498,11 @@ func TestHiddenColumn(t *testing.T) { ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) // Test show (extended) columns - tk.MustQuery("show columns from t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show columns from t").Check(testkit.RowsWithSep("|", "a|int(11)|NO|PRI||", "c|int(11)|YES|||", "e|int(11)|YES|||")) - tk.MustQuery("show extended columns from t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show extended columns from t").Check(testkit.RowsWithSep("|", "a|int(11)|NO|PRI||", "b|int(11)|YES|||VIRTUAL GENERATED", "c|int(11)|YES|||", @@ -596,7 +598,7 @@ func TestHiddenColumn(t *testing.T) { " `e` int(11) DEFAULT NULL,\n" + " PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) - tk.MustQuery("show extended columns from t").Check(testutil.RowsWithSep("|", + tk.MustQuery("show extended columns from t").Check(testkit.RowsWithSep("|", "a|int(11)|NO|PRI||", "b|int(11)|YES|||VIRTUAL GENERATED", "c|int(11)|YES|||", @@ -653,6 +655,7 @@ func TestAddRecordWithCtx(t *testing.T) { func TestConstraintCheckForUniqueIndex(t *testing.T) { store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("set @@autocommit = 1") @@ -692,10 +695,9 @@ func TestConstraintCheckForUniqueIndex(t *testing.T) { ch := make(chan int, 2) go func() { tk2.MustExec("use test") - _, err = tk2.Exec("insert into ttt(k,c) values(3, 'tidb')") + _, err := tk2.Exec("insert into ttt(k,c) values(3, 'tidb')") require.Error(t, err) ch <- 2 - clean() }() // Sleep 100ms for tk2 to execute, if it's not blocked, 2 should have been sent to the channel. time.Sleep(100 * time.Millisecond) @@ -704,6 +706,9 @@ func TestConstraintCheckForUniqueIndex(t *testing.T) { require.NoError(t, err) // The data in channel is 1 means tk2 is blocked, that's the expected behavior. require.Equal(t, 1, <-ch) + + // Unrelated to the test logic, just wait for the goroutine to exit to avoid leak in test + require.Equal(t, 2, <-ch) } func TestViewColumns(t *testing.T) { @@ -726,13 +731,227 @@ func TestViewColumns(t *testing.T) { {"select data_type from INFORMATION_SCHEMA.columns where table_name = 'va'", []string{types.TypeToStr(mysql.TypeLonglong, "")}}, } for _, testCase := range testCases { - tk.MustQuery(testCase.query).Check(testutil.RowsWithSep("|", testCase.expected...)) + tk.MustQuery(testCase.query).Check(testkit.RowsWithSep("|", testCase.expected...)) } tk.MustExec("drop table if exists t") for _, testCase := range testCases { require.Len(t, tk.MustQuery(testCase.query).Rows(), 0) - tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", + tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1356|View 'test.v' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", "Warning|1356|View 'test.va' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them")) } } + +func TestConstraintCheckForOptimisticUntouched(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists test_optimistic_untouched_flag;") + tk.MustExec(`create table test_optimistic_untouched_flag(c0 int, c1 varchar(20), c2 varchar(20), unique key uk(c0));`) + tk.MustExec(`insert into test_optimistic_untouched_flag(c0, c1, c2) values (1, null, 'green');`) + + // Insert a row with duplicated entry on the unique key, the commit should fail. + tk.MustExec("begin optimistic;") + tk.MustExec(`insert into test_optimistic_untouched_flag(c0, c1, c2) values (1, 'red', 'white');`) + tk.MustExec(`delete from test_optimistic_untouched_flag where c1 is null;`) + tk.MustExec("update test_optimistic_untouched_flag set c2 = 'green' where c2 between 'purple' and 'white';") + err := tk.ExecToErr("commit") + require.Error(t, err) + + tk.MustExec("begin optimistic;") + tk.MustExec(`insert into test_optimistic_untouched_flag(c0, c1, c2) values (1, 'red', 'white');`) + tk.MustExec("update test_optimistic_untouched_flag set c2 = 'green' where c2 between 'purple' and 'white';") + err = tk.ExecToErr("commit") + require.Error(t, err) +} + +func TestTxnAssertion(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + se, err := session.CreateSession4Test(store) + se.SetConnectionID(1) + require.NoError(t, err) + require.True(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk := testkit.NewTestKit(t, store) + tk.SetSession(se) + + fpAdd := "github.com/pingcap/tidb/table/tables/addRecordForceAssertExist" + fpUpdate := "github.com/pingcap/tidb/table/tables/updateRecordForceAssertNotExist" + fpRemove := "github.com/pingcap/tidb/table/tables/removeRecordForceAssertNotExist" + + runStmtInTxn := func(pessimistic bool, stmts ...string) error { + if pessimistic { + tk.MustExec("begin pessimistic") + } else { + tk.MustExec("begin optimistic") + } + for _, stmt := range stmts { + tk.MustExec(stmt) + } + return tk.ExecToErr("commit") + } + + withFailpoint := func(fp string, f func()) { + require.NoError(t, failpoint.Enable(fp, "return")) + defer func() { + require.NoError(t, failpoint.Disable(fp)) + }() + f() + } + + expectAssertionErr := func(assertionLevel string, err error) { + if assertionLevel == "STRICT" { + require.NotNil(t, err) + require.Contains(t, err.Error(), "assertion failed") + } else { + require.NoError(t, err) + } + } + + testAssertionBasicImpl := func(level string, lock bool, lockIdx bool, useCommonHandle bool) { + tk.MustExec("set @@tidb_txn_assertion_level = " + level) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + if useCommonHandle { + tk.MustExec("create table t(id varchar(64) primary key clustered, v int, v2 int, v3 int, v4 varchar(64), index(v2), unique index(v3), index(v4))") + } else { + tk.MustExec("create table t(id int primary key, v int, v2 int, v3 int, v4 varchar(64), index(v2), unique index(v3), index(v4))") + } + + var id1, id2, id3 interface{} + if useCommonHandle { + id1, id2, id3 = "1", "2", "3" + } else { + id1, id2, id3 = 1, 2, 3 + } + + // Auto commit + tk.MustExec("insert into t values (?, 10, 100, 1000, '10000')", id1) + tk.MustExec("update t set v = v + 1 where id = ?", id1) + tk.MustExec("delete from t where id = 1") + + // Optimistic + tk.MustExec("insert into t values (?, 20, 200, 2000, '20000'), (?, 30, 300, 3000, '30000')", id2, id3) + tk.MustExec("begin optimistic") + if lock { + tk.MustExec("select * from t where id in (?, ?, ?) for update", id1, id2, id3) + } + if lockIdx { + tk.MustExec("select * from t where v3 in (1000, 2000, 3000) for update") + } + tk.MustExec("insert into t values (?, 10, 100, 1000, '10000')", id1) + tk.MustExec("update t set v = v + 1 where id = ?", id2) + tk.MustExec("delete from t where id = ?", id3) + tk.MustExec("commit") + + // Pessimistic + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?, 20, 200, 2000, '20000'), (?, 30, 300, 3000, '30000')", id2, id3) + tk.MustExec("begin pessimistic") + if lock { + tk.MustExec("select * from t where id in (?, ?, ?) for update", id1, id2, id3) + } + if lockIdx { + tk.MustExec("select * from t where v3 in (1000, 2000, 3000) for update") + } + tk.MustExec("insert into t values (?, 10, 100, 1000, '10000')", id1) + tk.MustExec("update t set v = v + 1 where id = ?", id2) + tk.MustExec("delete from t where id = ?", id3) + tk.MustExec("commit") + + // Inject incorrect assertion so that it must fail. + + // Auto commit + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?, 20, 200, 2000, '20000'), (?, 30, 300, 3000, '30000')", id2, id3) + withFailpoint(fpAdd, func() { + err = tk.ExecToErr("insert into t values (?, 10, 100, 1000, '10000')", id1) + expectAssertionErr(level, err) + }) + withFailpoint(fpUpdate, func() { + err = tk.ExecToErr("update t set v = v + 1 where id = ?", id2) + expectAssertionErr(level, err) + }) + withFailpoint(fpRemove, func() { + err = tk.ExecToErr("delete from t where id = ?", id3) + expectAssertionErr(level, err) + }) + + var lockStmts []string = nil + if lock { + lockStmts = append(lockStmts, fmt.Sprintf("select * from t where id in (%#v, %#v, %#v) for update", id1, id2, id3)) + } + if lockIdx { + lockStmts = append(lockStmts, "select * from t where v3 in (1000, 2000, 3000) for update") + } + + // Optimistic + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?, 20, 200, 2000, '20000'), (?, 30, 300, 3000, '30000')", id2, id3) + withFailpoint(fpAdd, func() { + err = runStmtInTxn(false, append(lockStmts, fmt.Sprintf("insert into t values (%#v, 10, 100, 1000, '10000')", id1))...) + expectAssertionErr(level, err) + }) + withFailpoint(fpUpdate, func() { + err = runStmtInTxn(false, append(lockStmts, fmt.Sprintf("update t set v = v + 1 where id = %#v", id2))...) + expectAssertionErr(level, err) + }) + withFailpoint(fpRemove, func() { + err = runStmtInTxn(false, append(lockStmts, fmt.Sprintf("delete from t where id = %#v", id3))...) + expectAssertionErr(level, err) + }) + + // Pessimistic + tk.MustExec("delete from t") + tk.MustExec("insert into t values (?, 20, 200, 2000, '20000'), (?, 30, 300, 3000, '30000')", id2, id3) + withFailpoint(fpAdd, func() { + err = runStmtInTxn(true, append(lockStmts, fmt.Sprintf("insert into t values (%#v, 10, 100, 1000, '10000')", id1))...) + expectAssertionErr(level, err) + }) + withFailpoint(fpUpdate, func() { + err = runStmtInTxn(true, append(lockStmts, fmt.Sprintf("update t set v = v + 1 where id = %#v", id2))...) + expectAssertionErr(level, err) + }) + withFailpoint(fpRemove, func() { + err = runStmtInTxn(true, append(lockStmts, fmt.Sprintf("delete from t where id = %#v", id3))...) + expectAssertionErr(level, err) + }) + } + + for _, level := range []string{"STRICT", "OFF"} { + for _, lock := range []bool{false, true} { + for _, lockIdx := range []bool{false, true} { + for _, useCommonHandle := range []bool{false, true} { + t.Logf("testing testAssertionBasicImpl level: %v, lock: %v, lockIdx: %v, useCommonHandle: %v...", level, lock, lockIdx, useCommonHandle) + testAssertionBasicImpl(level, lock, lockIdx, useCommonHandle) + } + } + } + } + + testUntouchedIndexImpl := func(level string, pessimistic bool) { + tk.MustExec("set @@tidb_txn_assertion_level = " + level) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key, v int, v2 int, v3 int, index(v2), unique index(v3))") + tk.MustExec("insert into t values (1, 10, 100, 1000)") + + if pessimistic { + tk.MustExec("begin pessimistic") + } else { + tk.MustExec("begin optimistic") + } + tk.MustExec("update t set v = v + 1 where id = 1") + tk.MustExec("delete from t where id = 1") + tk.MustExec("insert into t values (1, 11, 101, 1001)") + tk.MustExec("commit") + } + + testUntouchedIndexImpl("STRICT", false) + testUntouchedIndexImpl("STRICT", true) + testUntouchedIndexImpl("OFF", false) + testUntouchedIndexImpl("OFF", true) +} diff --git a/table/temptable/interceptor_test.go b/table/temptable/interceptor_test.go index f75ea1bf0bd6d..79fbb654fe359 100644 --- a/table/temptable/interceptor_test.go +++ b/table/temptable/interceptor_test.go @@ -868,7 +868,7 @@ func TestInterceptorOnBatchGet(t *testing.T) { inter = emptyRetrieverInterceptor } result, err := inter.OnBatchGet(ctx, snap, c.keys) - require.Nil(t, err, i) + require.NoError(t, err, i) require.NotNil(t, result, i) require.Equal(t, c.result, result, i) if c.nilSession { diff --git a/table/temptable/main_test.go b/table/temptable/main_test.go index c7baa1e9f5208..48b91db00c838 100644 --- a/table/temptable/main_test.go +++ b/table/temptable/main_test.go @@ -35,10 +35,11 @@ import ( func TestMain(m *testing.M) { opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), } - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() goleak.VerifyTestMain(m, opts...) } diff --git a/tablecodec/main_test.go b/tablecodec/main_test.go index 75ea2dc757133..6b0a750cfa958 100644 --- a/tablecodec/main_test.go +++ b/tablecodec/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/tablecodec/rowindexcodec/main_test.go b/tablecodec/rowindexcodec/main_test.go index 55b15ba96e15d..745b45d45a929 100644 --- a/tablecodec/rowindexcodec/main_test.go +++ b/tablecodec/rowindexcodec/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/tablecodec/tablecodec.go b/tablecodec/tablecodec.go index f610e09104572..25bdb2c1c00db 100644 --- a/tablecodec/tablecodec.go +++ b/tablecodec/tablecodec.go @@ -375,6 +375,20 @@ func DecodeColumnValue(data []byte, ft *types.FieldType, loc *time.Location) (ty return colDatum, nil } +// DecodeColumnValueWithDatum decodes data to an existing Datum according to the column info. +func DecodeColumnValueWithDatum(data []byte, ft *types.FieldType, loc *time.Location, result *types.Datum) error { + var err error + _, *result, err = codec.DecodeOne(data) + if err != nil { + return errors.Trace(err) + } + *result, err = Unflatten(*result, ft, loc) + if err != nil { + return errors.Trace(err) + } + return nil +} + // DecodeRowWithMapNew decode a row to datum map. func DecodeRowWithMapNew(b []byte, cols map[int64]*types.FieldType, loc *time.Location, row map[int64]types.Datum) (map[int64]types.Datum, error) { @@ -401,7 +415,7 @@ func DecodeRowWithMapNew(b []byte, cols map[int64]*types.FieldType, return rd.DecodeToDatumMap(b, row) } -// DecodeRowWithMap decodes a byte slice into datums with a existing row map. +// DecodeRowWithMap decodes a byte slice into datums with an existing row map. // Row layout: colID1, value1, colID2, value2, ..... func DecodeRowWithMap(b []byte, cols map[int64]*types.FieldType, loc *time.Location, row map[int64]types.Datum) (map[int64]types.Datum, error) { if row == nil { @@ -584,7 +598,7 @@ func Unflatten(datum types.Datum, ft *types.FieldType, loc *time.Location) (type mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble: return datum, nil case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: - t := types.NewTime(types.ZeroCoreTime, ft.Tp, int8(ft.Decimal)) + t := types.NewTime(types.ZeroCoreTime, ft.Tp, ft.Decimal) var err error err = t.FromPackedUint(datum.GetUint64()) if err != nil { @@ -600,7 +614,7 @@ func Unflatten(datum types.Datum, ft *types.FieldType, loc *time.Location) (type datum.SetMysqlTime(t) return datum, nil case mysql.TypeDuration: // duration should read fsp from column meta data - dur := types.Duration{Duration: time.Duration(datum.GetInt64()), Fsp: int8(ft.Decimal)} + dur := types.Duration{Duration: time.Duration(datum.GetInt64()), Fsp: ft.Decimal} datum.SetMysqlDuration(dur) return datum, nil case mysql.TypeEnum: @@ -1300,21 +1314,23 @@ func TruncateIndexValue(v *types.Datum, idxCol *model.IndexColumn, tblCol *model if notStringType { return } - originalKind := v.Kind() - isUTF8Charset := tblCol.Charset == charset.CharsetUTF8 || tblCol.Charset == charset.CharsetUTF8MB4 - if isUTF8Charset && utf8.RuneCount(v.GetBytes()) > idxCol.Length { - rs := bytes.Runes(v.GetBytes()) + colValue := v.GetBytes() + if tblCol.Charset == charset.CharsetBin || tblCol.Charset == charset.CharsetASCII { + // Count character length by bytes if charset is binary or ascii. + if len(colValue) > idxCol.Length { + // truncate value and limit its length + if v.Kind() == types.KindBytes { + v.SetBytes(colValue[:idxCol.Length]) + } else { + v.SetString(v.GetString()[:idxCol.Length], tblCol.Collate) + } + } + } else if utf8.RuneCount(colValue) > idxCol.Length { + // Count character length by characters for other rune-based charsets, they are all internally encoded as UTF-8. + rs := bytes.Runes(colValue) truncateStr := string(rs[:idxCol.Length]) // truncate value and limit its length v.SetString(truncateStr, tblCol.Collate) - if v.Kind() == types.KindBytes { - v.SetBytes(v.GetBytes()) - } - } else if !isUTF8Charset && len(v.GetBytes()) > idxCol.Length { - v.SetBytes(v.GetBytes()[:idxCol.Length]) - if originalKind == types.KindString { - v.SetString(v.GetString(), tblCol.Collate) - } } } diff --git a/telemetry/cte_test/cte_test.go b/telemetry/cte_test/cte_test.go index 356b65eaad059..4a07a3e9255ee 100644 --- a/telemetry/cte_test/cte_test.go +++ b/telemetry/cte_test/cte_test.go @@ -28,16 +28,17 @@ import ( "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/testbridge" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/integration" + "go.etcd.io/etcd/tests/v3/integration" "go.uber.org/goleak" ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), } goleak.VerifyTestMain(m, opts...) @@ -48,6 +49,7 @@ func TestCTEPreviewAndReport(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) s := newSuite(t) defer s.close() diff --git a/telemetry/data_cluster_hardware.go b/telemetry/data_cluster_hardware.go index 611ae2e005384..d357e9243fd0b 100644 --- a/telemetry/data_cluster_hardware.go +++ b/telemetry/data_cluster_hardware.go @@ -69,11 +69,7 @@ func normalizeFieldName(name string) string { func getClusterHardware(ctx sessionctx.Context) ([]*clusterHardwareItem, error) { exec := ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), `SELECT TYPE, INSTANCE, DEVICE_TYPE, DEVICE_NAME, NAME, VALUE FROM information_schema.cluster_hardware`) - if err != nil { - return nil, errors.Trace(err) - } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, `SELECT TYPE, INSTANCE, DEVICE_TYPE, DEVICE_NAME, NAME, VALUE FROM information_schema.cluster_hardware`) if err != nil { return nil, errors.Trace(err) } diff --git a/telemetry/data_cluster_info.go b/telemetry/data_cluster_info.go index a1569c3e67634..40f87bccdfd3d 100644 --- a/telemetry/data_cluster_info.go +++ b/telemetry/data_cluster_info.go @@ -37,11 +37,7 @@ type clusterInfoItem struct { func getClusterInfo(ctx sessionctx.Context) ([]*clusterInfoItem, error) { // Explicitly list all field names instead of using `*` to avoid potential leaking sensitive info when adding new fields in future. exec := ctx.(sqlexec.RestrictedSQLExecutor) - stmt, err := exec.ParseWithParams(context.TODO(), `SELECT TYPE, INSTANCE, STATUS_ADDRESS, VERSION, GIT_HASH, START_TIME, UPTIME FROM information_schema.cluster_info`) - if err != nil { - return nil, errors.Trace(err) - } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, `SELECT TYPE, INSTANCE, STATUS_ADDRESS, VERSION, GIT_HASH, START_TIME, UPTIME FROM information_schema.cluster_info`) if err != nil { return nil, errors.Trace(err) } diff --git a/telemetry/data_feature_usage.go b/telemetry/data_feature_usage.go index cf32510097423..8854e72acd3b9 100644 --- a/telemetry/data_feature_usage.go +++ b/telemetry/data_feature_usage.go @@ -33,32 +33,82 @@ type featureUsage struct { Txn *TxnUsage `json:"txn"` // cluster index usage information // key is the first 6 characters of sha2(TABLE_NAME, 256) - ClusterIndex *ClusterIndexUsage `json:"clusterIndex"` - TemporaryTable bool `json:"temporaryTable"` - CTE *m.CTEUsageCounter `json:"cte"` - CachedTable bool `json:"cachedTable"` + ClusterIndex *ClusterIndexUsage `json:"clusterIndex"` + TemporaryTable bool `json:"temporaryTable"` + CTE *m.CTEUsageCounter `json:"cte"` + CachedTable bool `json:"cachedTable"` + AutoCapture bool `json:"autoCapture"` + PlacementPolicyUsage *placementPolicyUsage `json:"placementPolicy"` +} + +type placementPolicyUsage struct { + NumPlacementPolicies uint64 `json:"numPlacementPolicies"` + NumDBWithPolicies uint64 `json:"numDBWithPolicies"` + NumTableWithPolicies uint64 `json:"numTableWithPolicies"` + // The number of partitions that policies are explicitly specified. + NumPartitionWithExplicitPolicies uint64 `json:"numPartitionWithExplicitPolicies"` } func getFeatureUsage(ctx sessionctx.Context) (*featureUsage, error) { - clusterIdxUsage, err := getClusterIndexUsageInfo(ctx) + var usage featureUsage + var err error + usage.ClusterIndex, err = getClusterIndexUsageInfo(ctx) if err != nil { logutil.BgLogger().Info(err.Error()) return nil, err } // transaction related feature - txnUsage := getTxnUsageInfo(ctx) + usage.Txn = getTxnUsageInfo(ctx) - // Avoid the circle dependency. - temporaryTable := ctx.(TemporaryOrCacheTableFeatureChecker).TemporaryTableExists() + usage.CTE = getCTEUsageInfo() - cteUsage := getCTEUsageInfo() + usage.AutoCapture = getAutoCaptureUsageInfo(ctx) + + collectFeatureUsageFromInfoschema(ctx, &usage) + return &usage, nil +} + +// collectFeatureUsageFromInfoschema updates the usage for temporary table, cached table and placement policies. +func collectFeatureUsageFromInfoschema(ctx sessionctx.Context, usage *featureUsage) { + if usage.PlacementPolicyUsage == nil { + usage.PlacementPolicyUsage = &placementPolicyUsage{} + } + is := GetDomainInfoSchema(ctx) + for _, dbInfo := range is.AllSchemas() { + if dbInfo.PlacementPolicyRef != nil { + usage.PlacementPolicyUsage.NumDBWithPolicies++ + } - cachedTable := ctx.(TemporaryOrCacheTableFeatureChecker).CachedTableExists() + for _, tbInfo := range is.SchemaTables(dbInfo.Name) { + if tbInfo.Meta().TempTableType != model.TempTableNone { + usage.TemporaryTable = true + } + if tbInfo.Meta().TableCacheStatusType != model.TableCacheStatusDisable { + usage.CachedTable = true + } + if tbInfo.Meta().PlacementPolicyRef != nil { + usage.PlacementPolicyUsage.NumTableWithPolicies++ + } + partitions := tbInfo.Meta().GetPartitionInfo() + if partitions == nil { + continue + } + for _, partitionInfo := range partitions.Definitions { + if partitionInfo.PlacementPolicyRef != nil { + usage.PlacementPolicyUsage.NumPartitionWithExplicitPolicies++ + } + } + } + } - return &featureUsage{txnUsage, clusterIdxUsage, temporaryTable, cteUsage, cachedTable}, nil + usage.PlacementPolicyUsage.NumPlacementPolicies += uint64(len(is.AllPlacementPolicies())) } +// GetDomainInfoSchema is used by the telemetry package to get the latest schema information +// while avoiding circle dependency with domain package. +var GetDomainInfoSchema func(sessionctx.Context) infoschema.InfoSchema + // ClusterIndexUsage records the usage info of all the tables, no more than 10k tables type ClusterIndexUsage map[string]TableClusteredInfo @@ -77,7 +127,7 @@ func getClusterIndexUsageInfo(ctx sessionctx.Context) (cu *ClusterIndexUsage, er exec := ctx.(sqlexec.RestrictedSQLExecutor) // query INFORMATION_SCHEMA.tables to get the latest table information about ClusterIndex - stmt, err := exec.ParseWithParams(context.TODO(), ` + rows, _, err := exec.ExecRestrictedSQL(context.TODO(), nil, ` SELECT left(sha2(TABLE_NAME, 256), 6) table_name_hash, TIDB_PK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables WHERE table_schema not in ('INFORMATION_SCHEMA', 'METRICS_SCHEMA', 'PERFORMANCE_SCHEMA', 'mysql') @@ -86,10 +136,6 @@ func getClusterIndexUsageInfo(ctx sessionctx.Context) (cu *ClusterIndexUsage, er if err != nil { return nil, err } - rows, _, err := exec.ExecRestrictedStmt(context.TODO(), stmt) - if err != nil { - return nil, err - } defer func() { if r := recover(); r != nil { @@ -141,19 +187,15 @@ func getClusterIndexUsageInfo(ctx sessionctx.Context) (cu *ClusterIndexUsage, er return &usage, nil } -// TemporaryOrCacheTableFeatureChecker is defined to avoid package circle dependency. -// The session struct implements this interface. -type TemporaryOrCacheTableFeatureChecker interface { - TemporaryTableExists() bool - CachedTableExists() bool -} - // TxnUsage records the usage info of transaction related features, including // async-commit, 1PC and counters of transactions committed with different protocols. type TxnUsage struct { - AsyncCommitUsed bool `json:"asyncCommitUsed"` - OnePCUsed bool `json:"onePCUsed"` - TxnCommitCounter metrics.TxnCommitCounter `json:"txnCommitCounter"` + AsyncCommitUsed bool `json:"asyncCommitUsed"` + OnePCUsed bool `json:"onePCUsed"` + TxnCommitCounter metrics.TxnCommitCounter `json:"txnCommitCounter"` + MutationCheckerUsed bool `json:"mutationCheckerUsed"` + AssertionLevel string `json:"assertionLevel"` + RcCheckTS bool `json:"rcCheckTS"` } var initialTxnCommitCounter metrics.TxnCommitCounter @@ -171,7 +213,19 @@ func getTxnUsageInfo(ctx sessionctx.Context) *TxnUsage { } curr := metrics.GetTxnCommitCounter() diff := curr.Sub(initialTxnCommitCounter) - return &TxnUsage{asyncCommitUsed, onePCUsed, diff} + mutationCheckerUsed := false + if val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBEnableMutationChecker); err == nil { + mutationCheckerUsed = val == variable.On + } + assertionUsed := "" + if val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBTxnAssertionLevel); err == nil { + assertionUsed = val + } + rcCheckTSUsed := false + if val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBRCReadCheckTS); err == nil { + rcCheckTSUsed = val == variable.On + } + return &TxnUsage{asyncCommitUsed, onePCUsed, diff, mutationCheckerUsed, assertionUsed, rcCheckTSUsed} } func postReportTxnUsage() { @@ -189,3 +243,11 @@ func getCTEUsageInfo() *m.CTEUsageCounter { diff := curr.Sub(initialCTECounter) return &diff } + +// getAutoCaptureUsageInfo gets the 'Auto Capture' usage +func getAutoCaptureUsageInfo(ctx sessionctx.Context) bool { + if val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBCapturePlanBaseline); err == nil { + return val == variable.On + } + return false +} diff --git a/telemetry/data_feature_usage_test.go b/telemetry/data_feature_usage_test.go index efe852153a13a..bbae540f56019 100644 --- a/telemetry/data_feature_usage_test.go +++ b/telemetry/data_feature_usage_test.go @@ -43,6 +43,26 @@ func TestTxnUsageInfo(t *testing.T) { txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) require.True(t, txnUsage.AsyncCommitUsed) require.True(t, txnUsage.OnePCUsed) + + tk.MustExec(fmt.Sprintf("set global %s = 0", variable.TiDBEnableMutationChecker)) + tk.MustExec(fmt.Sprintf("set global %s = off", variable.TiDBTxnAssertionLevel)) + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.False(t, txnUsage.MutationCheckerUsed) + require.Equal(t, "OFF", txnUsage.AssertionLevel) + + tk.MustExec(fmt.Sprintf("set global %s = 1", variable.TiDBEnableMutationChecker)) + tk.MustExec(fmt.Sprintf("set global %s = strict", variable.TiDBTxnAssertionLevel)) + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.True(t, txnUsage.MutationCheckerUsed) + require.Equal(t, "STRICT", txnUsage.AssertionLevel) + + tk.MustExec(fmt.Sprintf("set global %s = fast", variable.TiDBTxnAssertionLevel)) + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.Equal(t, "FAST", txnUsage.AssertionLevel) + + tk.MustExec(fmt.Sprintf("set global %s = 1", variable.TiDBRCReadCheckTS)) + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.True(t, txnUsage.RcCheckTS) }) t.Run("Count", func(t *testing.T) { @@ -105,3 +125,66 @@ func TestCachedTable(t *testing.T) { require.NoError(t, err) require.False(t, usage.CachedTable) } + +func TestPlacementPolicies(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + usage, err := telemetry.GetFeatureUsage(tk.Session()) + require.NoError(t, err) + require.Equal(t, uint64(0), usage.PlacementPolicyUsage.NumPlacementPolicies) + require.Equal(t, uint64(0), usage.PlacementPolicyUsage.NumDBWithPolicies) + require.Equal(t, uint64(0), usage.PlacementPolicyUsage.NumTableWithPolicies) + require.Equal(t, uint64(0), usage.PlacementPolicyUsage.NumPartitionWithExplicitPolicies) + + tk.MustExec("create placement policy p1 followers=4;") + tk.MustExec(`create placement policy p2 primary_region="cn-east-1" regions="cn-east-1,cn-east"`) + tk.MustExec(`create placement policy p3 followers=3`) + tk.MustExec("alter database test placement policy=p1;") + tk.MustExec("create table t1(a int);") + tk.MustExec("create table t2(a int) placement policy=p2;") + tk.MustExec("create table t3(id int) PARTITION BY RANGE (id) (" + + "PARTITION p0 VALUES LESS THAN (100) placement policy p3," + + "PARTITION p1 VALUES LESS THAN (1000))") + + usage, err = telemetry.GetFeatureUsage(tk.Session()) + require.NoError(t, err) + require.Equal(t, uint64(3), usage.PlacementPolicyUsage.NumPlacementPolicies) + require.Equal(t, uint64(1), usage.PlacementPolicyUsage.NumDBWithPolicies) + require.Equal(t, uint64(3), usage.PlacementPolicyUsage.NumTableWithPolicies) + require.Equal(t, uint64(1), usage.PlacementPolicyUsage.NumPartitionWithExplicitPolicies) + + tk.MustExec("drop table t2;") + tk.MustExec("drop placement policy p2;") + tk.MustExec("alter table t3 placement policy=default") + + usage, err = telemetry.GetFeatureUsage(tk.Session()) + require.NoError(t, err) + require.Equal(t, uint64(2), usage.PlacementPolicyUsage.NumPlacementPolicies) + require.Equal(t, uint64(1), usage.PlacementPolicyUsage.NumDBWithPolicies) + require.Equal(t, uint64(1), usage.PlacementPolicyUsage.NumTableWithPolicies) + require.Equal(t, uint64(1), usage.PlacementPolicyUsage.NumPartitionWithExplicitPolicies) +} + +func TestAutoCapture(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + usage, err := telemetry.GetFeatureUsage(tk.Session()) + require.NoError(t, err) + require.False(t, usage.AutoCapture) + + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") + defer func() { + tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") + }() + usage, err = telemetry.GetFeatureUsage(tk.Session()) + require.NoError(t, err) + require.True(t, usage.AutoCapture) +} diff --git a/telemetry/data_slow_query.go b/telemetry/data_slow_query.go index baf0d2e60bd6a..e32940e09be6a 100644 --- a/telemetry/data_slow_query.go +++ b/telemetry/data_slow_query.go @@ -72,7 +72,7 @@ func getSlowQueryStats(ctx sessionctx.Context) (*slowQueryStats, error) { return &slowQueryStats{slowQueryBucket}, nil } -// getSlowQueryBucket genenrates the delta SlowQueryBucket to report +// getSlowQueryBucket generates the delta SlowQueryBucket to report func getSlowQueryBucket(ctx sessionctx.Context) (*SlowQueryBucket, error) { // update currentSQBInfo first, then gen delta if err := updateCurrentSQB(ctx); err != nil { diff --git a/telemetry/data_telemetry_host_extra.go b/telemetry/data_telemetry_host_extra.go index ad200dd1b2a3a..ab5fcbcb81563 100644 --- a/telemetry/data_telemetry_host_extra.go +++ b/telemetry/data_telemetry_host_extra.go @@ -15,8 +15,8 @@ package telemetry import ( - "github.com/shirou/gopsutil/cpu" - "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/host" ) // Some information that is not included in current system tables. There is no easy way to retrieve information diff --git a/telemetry/data_window_serial_test.go b/telemetry/data_window_test.go similarity index 100% rename from telemetry/data_window_serial_test.go rename to telemetry/data_window_test.go diff --git a/telemetry/id.go b/telemetry/id.go index dac130826596a..057585d48a790 100644 --- a/telemetry/id.go +++ b/telemetry/id.go @@ -19,7 +19,7 @@ import ( "github.com/google/uuid" "github.com/pingcap/errors" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" ) const ( diff --git a/telemetry/main_test.go b/telemetry/main_test.go index f498d16a2d564..9e9d8fd2c4389 100644 --- a/telemetry/main_test.go +++ b/telemetry/main_test.go @@ -27,11 +27,12 @@ var ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ - goleak.IgnoreTopFunction("go.etcd.io/etcd/pkg/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), } goleak.VerifyTestMain(m, opts...) diff --git a/telemetry/status.go b/telemetry/status.go index b41a59ebbe55d..a5d2aefe6fca6 100644 --- a/telemetry/status.go +++ b/telemetry/status.go @@ -19,7 +19,7 @@ import ( "encoding/json" "github.com/pingcap/errors" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" ) const ( diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go index 481d077087cba..3f383b3d426e8 100644 --- a/telemetry/telemetry.go +++ b/telemetry/telemetry.go @@ -27,7 +27,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/util/logutil" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" ) diff --git a/telemetry/telemetry_serial_test.go b/telemetry/telemetry_serial_test.go deleted file mode 100644 index c464d46c4c6de..0000000000000 --- a/telemetry/telemetry_serial_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2021 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package telemetry_test - -import ( - "runtime" - "testing" - - "github.com/Jeffail/gabs/v2" - "github.com/pingcap/tidb/config" - "github.com/pingcap/tidb/session" - "github.com/pingcap/tidb/telemetry" - "github.com/pingcap/tidb/testkit" - "github.com/stretchr/testify/require" - "go.etcd.io/etcd/integration" -) - -func TestReport(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") - } - - etcdCluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - defer etcdCluster.Terminate(t) - store, clean := testkit.CreateMockStore(t) - defer clean() - se, err := session.CreateSession4Test(store) - require.NoError(t, err) - defer se.Close() - - config.GetGlobalConfig().EnableTelemetry = false - require.NoError(t, telemetry.ReportUsageData(se, etcdCluster.RandClient())) - - status, err := telemetry.GetTelemetryStatus(etcdCluster.RandClient()) - require.NoError(t, err) - - jsonParsed, err := gabs.ParseJSON([]byte(status)) - require.NoError(t, err) - require.True(t, jsonParsed.Path("is_error").Data().(bool)) - require.Equal(t, "telemetry is disabled", jsonParsed.Path("error_msg").Data().(string)) - require.False(t, jsonParsed.Path("is_request_sent").Data().(bool)) -} diff --git a/telemetry/telemetry_test.go b/telemetry/telemetry_test.go index c7f3cef8d92a8..eafccce735efd 100644 --- a/telemetry/telemetry_test.go +++ b/telemetry/telemetry_test.go @@ -25,13 +25,14 @@ import ( "github.com/pingcap/tidb/telemetry" "github.com/pingcap/tidb/testkit" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/integration" + "go.etcd.io/etcd/tests/v3/integration" ) func TestTrackingID(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) etcdCluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) defer etcdCluster.Terminate(t) @@ -53,6 +54,7 @@ func TestPreview(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") } + integration.BeforeTest(t) etcdCluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) defer etcdCluster.Terminate(t) @@ -101,3 +103,30 @@ func TestPreview(t *testing.T) { require.NoError(t, err) require.Equal(t, "", r) } + +func TestReport(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") + } + integration.BeforeTest(t) + + etcdCluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + defer etcdCluster.Terminate(t) + store, clean := testkit.CreateMockStore(t) + defer clean() + se, err := session.CreateSession4Test(store) + require.NoError(t, err) + defer se.Close() + + config.GetGlobalConfig().EnableTelemetry = false + require.NoError(t, telemetry.ReportUsageData(se, etcdCluster.RandClient())) + + status, err := telemetry.GetTelemetryStatus(etcdCluster.RandClient()) + require.NoError(t, err) + + jsonParsed, err := gabs.ParseJSON([]byte(status)) + require.NoError(t, err) + require.True(t, jsonParsed.Path("is_error").Data().(bool)) + require.Equal(t, "telemetry is disabled", jsonParsed.Path("error_msg").Data().(string)) + require.False(t, jsonParsed.Path("is_request_sent").Data().(bool)) +} diff --git a/testkit/asynctestkit.go b/testkit/asynctestkit.go index f73d77a6dc03e..34a8d1fdb0dbe 100644 --- a/testkit/asynctestkit.go +++ b/testkit/asynctestkit.go @@ -53,7 +53,7 @@ func NewAsyncTestKit(t *testing.T, store kv.Storage) *AsyncTestKit { // OpenSession opens new session ctx if no exists one and use db. func (tk *AsyncTestKit) OpenSession(ctx context.Context, db string) context.Context { - if tryRetrieveSession(ctx) == nil { + if TryRetrieveSession(ctx) == nil { se, err := session.CreateSession4Test(tk.store) tk.require.NoError(err) se.SetConnectionID(asyncTestKitIDGenerator.Inc()) @@ -65,7 +65,7 @@ func (tk *AsyncTestKit) OpenSession(ctx context.Context, db string) context.Cont // CloseSession closes exists session from ctx. func (tk *AsyncTestKit) CloseSession(ctx context.Context) { - se := tryRetrieveSession(ctx) + se := TryRetrieveSession(ctx) tk.require.NotNil(se) se.Close() } @@ -135,7 +135,7 @@ func (tk *AsyncTestKit) ConcurrentRun( // Exec executes a sql statement. func (tk *AsyncTestKit) Exec(ctx context.Context, sql string, args ...interface{}) (sqlexec.RecordSet, error) { - se := tryRetrieveSession(ctx) + se := TryRetrieveSession(ctx) tk.require.NotNil(se) if len(args) == 0 { @@ -191,7 +191,7 @@ func (tk *AsyncTestKit) MustQuery(ctx context.Context, sql string, args ...inter // resultSetToResult converts ast.RecordSet to testkit.Result. // It is used to check results of execute statement in binary mode. func (tk *AsyncTestKit) resultSetToResult(ctx context.Context, rs sqlexec.RecordSet, comment string) *Result { - rows, err := session.GetRows4Test(context.Background(), tryRetrieveSession(ctx), rs) + rows, err := session.GetRows4Test(context.Background(), TryRetrieveSession(ctx), rs) tk.require.NoError(err, comment) err = rs.Close() @@ -219,7 +219,8 @@ type sessionCtxKeyType struct{} var sessionKey = sessionCtxKeyType{} -func tryRetrieveSession(ctx context.Context) session.Session { +// TryRetrieveSession tries retrieve session from context. +func TryRetrieveSession(ctx context.Context) session.Session { s := ctx.Value(sessionKey) if s == nil { return nil diff --git a/testkit/external/util.go b/testkit/external/util.go new file mode 100644 index 0000000000000..496330e0596fc --- /dev/null +++ b/testkit/external/util.go @@ -0,0 +1,72 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package external + +import ( + "fmt" + "strings" + "testing" + + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/table/tables" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +// GetTableByName gets table by name for test. +func GetTableByName(t *testing.T, tk *testkit.TestKit, db, table string) table.Table { + dom := domain.GetDomain(tk.Session()) + // Make sure the table schema is the new schema. + require.NoError(t, dom.Reload()) + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) + require.NoError(t, err) + return tbl +} + +// GetModifyColumn is used to get the changed column name after ALTER TABLE. +func GetModifyColumn(t *testing.T, tk *testkit.TestKit, db, tbl, colName string, allColumn bool) *table.Column { + tt := GetTableByName(t, tk, db, tbl) + colName = strings.ToLower(colName) + var cols []*table.Column + if allColumn { + cols = tt.(*tables.TableCommon).Columns + } else { + cols = tt.Cols() + } + for _, col := range cols { + if col.Name.L == colName { + return col + } + } + return nil +} + +// GetIndexID is used to get the index ID from full qualified name. +func GetIndexID(t *testing.T, tk *testkit.TestKit, dbName, tblName, idxName string) int64 { + is := domain.GetDomain(tk.Session()).InfoSchema() + tt, err := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName)) + require.NoError(t, err) + + for _, idx := range tt.Indices() { + if idx.Meta().Name.L == idxName { + return idx.Meta().ID + } + } + + require.FailNow(t, fmt.Sprintf("index %s not found(db: %s, tbl: %s)", idxName, dbName, tblName)) + return -1 +} diff --git a/testkit/mockstore.go b/testkit/mockstore.go index 181d1c609e364..afa9658b22ae5 100644 --- a/testkit/mockstore.go +++ b/testkit/mockstore.go @@ -19,6 +19,7 @@ package testkit import ( "testing" + "time" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" @@ -39,12 +40,12 @@ func CreateMockStore(t testing.TB, opts ...mockstore.MockTiKVStoreOption) (store func CreateMockStoreAndDomain(t testing.TB, opts ...mockstore.MockTiKVStoreOption) (kv.Storage, *domain.Domain, func()) { store, err := mockstore.NewMockStore(opts...) require.NoError(t, err) - dom, clean := bootstrap(t, store) + dom, clean := bootstrap(t, store, 0) return store, dom, clean } -func bootstrap(t testing.TB, store kv.Storage) (*domain.Domain, func()) { - session.SetSchemaLease(0) +func bootstrap(t testing.TB, store kv.Storage, lease time.Duration) (*domain.Domain, func()) { + session.SetSchemaLease(lease) session.DisableStats4Test() dom, err := session.BootstrapSession(store) require.NoError(t, err) @@ -59,12 +60,26 @@ func bootstrap(t testing.TB, store kv.Storage) (*domain.Domain, func()) { return dom, clean } +// CreateMockStoreWithSchemaLease return a new mock kv.Storage. +func CreateMockStoreWithSchemaLease(t testing.TB, lease time.Duration, opts ...mockstore.MockTiKVStoreOption) (store kv.Storage, clean func()) { + store, _, clean = CreateMockStoreAndDomainWithSchemaLease(t, lease, opts...) + return +} + +// CreateMockStoreAndDomainWithSchemaLease return a new mock kv.Storage and *domain.Domain. +func CreateMockStoreAndDomainWithSchemaLease(t testing.TB, lease time.Duration, opts ...mockstore.MockTiKVStoreOption) (kv.Storage, *domain.Domain, func()) { + store, err := mockstore.NewMockStore(opts...) + require.NoError(t, err) + dom, clean := bootstrap(t, store, lease) + return store, dom, clean +} + // CreateMockStoreWithOracle returns a new mock kv.Storage and *domain.Domain, providing the oracle for the store. func CreateMockStoreWithOracle(t testing.TB, oracle oracle.Oracle, opts ...mockstore.MockTiKVStoreOption) (kv.Storage, *domain.Domain, func()) { store, err := mockstore.NewMockStore(opts...) require.NoError(t, err) store.GetOracle().Close() store.(tikv.Storage).SetOracle(oracle) - dom, clean := bootstrap(t, store) + dom, clean := bootstrap(t, store, 0) return store, dom, clean } diff --git a/testkit/result.go b/testkit/result.go index 6950120d6a2a0..b9e288db09e44 100644 --- a/testkit/result.go +++ b/testkit/result.go @@ -99,3 +99,22 @@ func (res *Result) Rows() [][]interface{} { } return ifacesSlice } + +// CheckAt asserts the result of selected columns equals the expected results. +func (res *Result) CheckAt(cols []int, expected [][]interface{}) { + for _, e := range expected { + res.require.Equal(len(e), len(cols)) + } + + rows := make([][]string, 0, len(expected)) + for i := range res.rows { + row := make([]string, 0, len(cols)) + for _, r := range cols { + row = append(row, res.rows[i][r]) + } + rows = append(rows, row) + } + got := fmt.Sprintf("%s", rows) + need := fmt.Sprintf("%s", expected) + res.require.Equal(need, got, res.comment) +} diff --git a/testkit/testdata/testdata.go b/testkit/testdata/testdata.go index f9c9eae1e8c68..8ab2f343d7b8e 100644 --- a/testkit/testdata/testdata.go +++ b/testkit/testdata/testdata.go @@ -32,6 +32,7 @@ import ( "testing" "github.com/pingcap/errors" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/stretchr/testify/require" ) @@ -124,6 +125,14 @@ func ConvertRowsToStrings(rows [][]interface{}) (rs []string) { return rs } +// ConvertSQLWarnToStrings converts []SQLWarn to []string. +func ConvertSQLWarnToStrings(warns []stmtctx.SQLWarn) (rs []string) { + for _, warn := range warns { + rs = append(rs, fmt.Sprint(warn.Err.Error())) + } + return rs +} + // GetTestCases gets the test cases for a test function. func (td *TestData) GetTestCases(t *testing.T, in interface{}, out interface{}) { // Extract caller's name. @@ -151,6 +160,25 @@ func (td *TestData) GetTestCases(t *testing.T, in interface{}, out interface{}) td.output[casesIdx].decodedOut = out } +// GetTestCasesByName gets the test cases for a test function by its name. +func (td *TestData) GetTestCasesByName(caseName string, t *testing.T, in interface{}, out interface{}) { + casesIdx, ok := td.funcMap[caseName] + require.Truef(t, ok, "Case name: %s", caseName) + require.NoError(t, json.Unmarshal(*td.input[casesIdx].Cases, in)) + + if Record() { + inputLen := reflect.ValueOf(in).Elem().Len() + v := reflect.ValueOf(out).Elem() + if v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), inputLen, inputLen)) + } + } else { + require.NoError(t, json.Unmarshal(*td.output[casesIdx].Cases, out)) + } + + td.output[casesIdx].decodedOut = out +} + func (td *TestData) generateOutputIfNeeded() error { if !record { return nil diff --git a/testkit/testkit.go b/testkit/testkit.go index c99791efe369a..53b4ad526d8d6 100644 --- a/testkit/testkit.go +++ b/testkit/testkit.go @@ -57,6 +57,17 @@ func NewTestKit(t testing.TB, store kv.Storage) *TestKit { } } +// NewTestKitWithSession returns a new *TestKit. +func NewTestKitWithSession(t testing.TB, store kv.Storage, se session.Session) *TestKit { + return &TestKit{ + require: require.New(t), + assert: assert.New(t), + t: t, + store: store, + session: se, + } +} + // RefreshSession set a new session for the testkit func (tk *TestKit) RefreshSession() { tk.session = newSession(tk.t, tk.store) @@ -93,6 +104,49 @@ func (tk *TestKit) MustQuery(sql string, args ...interface{}) *Result { return tk.ResultSetToResult(rs, comment) } +// MustIndexLookup checks whether the plan for the sql is IndexLookUp. +func (tk *TestKit) MustIndexLookup(sql string, args ...interface{}) *Result { + tk.require.True(tk.HasPlan(sql, "IndexLookUp", args...)) + return tk.MustQuery(sql, args...) +} + +// MustPartition checks if the result execution plan must read specific partitions. +func (tk *TestKit) MustPartition(sql string, partitions string, args ...interface{}) *Result { + rs := tk.MustQuery("explain "+sql, args...) + ok := len(partitions) == 0 + for i := range rs.rows { + if len(partitions) == 0 && strings.Contains(rs.rows[i][3], "partition:") { + ok = false + } + if len(partitions) != 0 && strings.Compare(rs.rows[i][3], "partition:"+partitions) == 0 { + ok = true + } + } + tk.require.True(ok) + return tk.MustQuery(sql, args...) +} + +// MustPartitionByList checks if the result execution plan must read specific partitions by list. +func (tk *TestKit) MustPartitionByList(sql string, partitions []string, args ...interface{}) *Result { + rs := tk.MustQuery("explain "+sql, args...) + ok := len(partitions) == 0 + for i := range rs.rows { + if ok { + tk.require.NotContains(rs.rows[i][3], "partition:") + } + for index, partition := range partitions { + if !ok && strings.Contains(rs.rows[i][3], "partition:"+partition) { + partitions = append(partitions[:index], partitions[index+1:]...) + } + } + + } + if !ok { + tk.require.Len(partitions, 0) + } + return tk.MustQuery(sql, args...) +} + // QueryToErr executes a sql statement and discard results. func (tk *TestKit) QueryToErr(sql string, args ...interface{}) error { comment := fmt.Sprintf("sql:%s, args:%v", sql, args) @@ -220,11 +274,24 @@ func (tk *TestKit) MustGetErrCode(sql string, errCode int) { tk.require.Equalf(errCode, int(sqlErr.Code), "Assertion failed, origin err:\n %v", sqlErr) } -// MustGetErrMsg executes a sql statement and assert it's error message. +// MustGetErrMsg executes a sql statement and assert its error message. func (tk *TestKit) MustGetErrMsg(sql string, errStr string) { + err := tk.ExecToErr(sql) + tk.require.EqualError(err, errStr) +} + +// MustContainErrMsg executes a sql statement and assert its error message containing errStr. +func (tk *TestKit) MustContainErrMsg(sql string, errStr interface{}) { + err := tk.ExecToErr(sql) + tk.require.Error(err) + tk.require.Contains(err.Error(), errStr) +} + +// MustMatchErrMsg executes a sql statement and assert its error message matching errRx. +func (tk *TestKit) MustMatchErrMsg(sql string, errRx interface{}) { err := tk.ExecToErr(sql) tk.require.Error(err) - tk.require.Equal(errStr, err.Error()) + tk.require.Regexp(errRx, err.Error()) } // MustUseIndex checks if the result execution plan contains specific index(es). @@ -258,9 +325,62 @@ func (tk *TestKit) CheckExecResult(affectedRows, insertID int64) { tk.require.Equal(int64(tk.Session().LastInsertID()), insertID) } +// MustPointGet checks whether the plan for the sql is Point_Get. +func (tk *TestKit) MustPointGet(sql string, args ...interface{}) *Result { + rs := tk.MustQuery("explain "+sql, args...) + tk.require.Len(rs.rows, 1) + tk.require.Contains(rs.rows[0][0], "Point_Get", "plan %v", rs.rows[0][0]) + return tk.MustQuery(sql, args...) +} + +// UsedPartitions returns the partition names that will be used or all/dual. +func (tk *TestKit) UsedPartitions(sql string, args ...interface{}) *Result { + rs := tk.MustQuery("explain "+sql, args...) + var usedPartitions [][]string + for i := range rs.rows { + index := strings.Index(rs.rows[i][3], "partition:") + if index != -1 { + p := rs.rows[i][3][index+len("partition:"):] + partitions := strings.Split(strings.SplitN(p, " ", 2)[0], ",") + usedPartitions = append(usedPartitions, partitions) + } + } + comment := fmt.Sprintf("sql:%s, args:%v", sql, args) + return &Result{rows: usedPartitions, comment: comment, assert: tk.assert, require: tk.require} +} + // WithPruneMode run test case under prune mode. func WithPruneMode(tk *TestKit, mode variable.PartitionPruneMode, f func()) { tk.MustExec("set @@tidb_partition_prune_mode=`" + string(mode) + "`") tk.MustExec("set global tidb_partition_prune_mode=`" + string(mode) + "`") f() } + +func containGlobal(rs *Result) bool { + partitionNameCol := 2 + for i := range rs.rows { + if strings.Contains(rs.rows[i][partitionNameCol], "global") { + return true + } + } + return false +} + +// MustNoGlobalStats checks if there is no global stats. +func (tk *TestKit) MustNoGlobalStats(table string) bool { + if containGlobal(tk.MustQuery("show stats_meta where table_name like '" + table + "'")) { + return false + } + if containGlobal(tk.MustQuery("show stats_buckets where table_name like '" + table + "'")) { + return false + } + if containGlobal(tk.MustQuery("show stats_histograms where table_name like '" + table + "'")) { + return false + } + return true +} + +// CheckLastMessage checks last message after executing MustExec +func (tk *TestKit) CheckLastMessage(msg string) { + tk.require.Equal(tk.Session().LastMessage(), msg) +} diff --git a/testkit/handle.go b/testkit/testutil/handle.go similarity index 62% rename from testkit/handle.go rename to testkit/testutil/handle.go index e911f164d8052..a506cd347343d 100644 --- a/testkit/handle.go +++ b/testkit/testutil/handle.go @@ -15,12 +15,14 @@ //go:build !codes // +build !codes -package testkit +package testutil import ( + "sort" "testing" "github.com/pingcap/tidb/kv" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/codec" @@ -30,8 +32,21 @@ import ( // MustNewCommonHandle create a common handle with given values. func MustNewCommonHandle(t *testing.T, values ...interface{}) kv.Handle { encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.MakeDatums(values...)...) - require.Nil(t, err) + require.NoError(t, err) ch, err := kv.NewCommonHandle(encoded) - require.Nil(t, err) + require.NoError(t, err) return ch } + +// MaskSortHandles sorts the handles by lowest (fieldTypeBits - 1 - shardBitsCount) bits. +func MaskSortHandles(handles []int64, shardBitsCount int, fieldType byte) []int64 { + typeBitsLength := mysql.DefaultLengthOfMysqlTypes[fieldType] * 8 + const signBitCount = 1 + shiftBitsCount := 64 - typeBitsLength + shardBitsCount + signBitCount + ordered := make([]int64, len(handles)) + for i, h := range handles { + ordered[i] = h << shiftBitsCount >> shiftBitsCount + } + sort.Slice(ordered, func(i, j int) bool { return ordered[i] < ordered[j] }) + return ordered +} diff --git a/testkit/trequire/trequire.go b/testkit/testutil/require.go similarity index 52% rename from testkit/trequire/trequire.go rename to testkit/testutil/require.go index 6ffb245413fec..9c217f46c2747 100644 --- a/testkit/trequire/trequire.go +++ b/testkit/testutil/require.go @@ -15,11 +15,12 @@ //go:build !codes // +build !codes -package trequire +package testutil import ( "testing" + "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/collate" @@ -27,9 +28,51 @@ import ( ) // DatumEqual verifies that the actual value is equal to the expected value. For string datum, they are compared by the binary collation. -func DatumEqual(t *testing.T, expected, actual types.Datum, msgAndArgs ...interface{}) { +func DatumEqual(t testing.TB, expected, actual types.Datum, msgAndArgs ...interface{}) { sc := new(stmtctx.StatementContext) res, err := actual.Compare(sc, &expected, collate.GetBinaryCollator()) require.NoError(t, err, msgAndArgs) require.Zero(t, res, msgAndArgs) } + +// HandleEqual verifies that the actual handle is equal to the expected handle. +func HandleEqual(t testing.TB, expected, actual kv.Handle, msgAndArgs ...interface{}) { + require.Equal(t, expected.IsInt(), actual.IsInt(), msgAndArgs) + require.Equal(t, expected.String(), actual.String(), msgAndArgs) +} + +// CompareUnorderedStringSlice compare two string slices. +// If a and b is exactly the same except the order, it returns true. +// In otherwise return false. +func CompareUnorderedStringSlice(a []string, b []string) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + if len(a) != len(b) { + return false + } + m := make(map[string]int, len(a)) + for _, i := range a { + _, ok := m[i] + if !ok { + m[i] = 1 + } else { + m[i]++ + } + } + + for _, i := range b { + _, ok := m[i] + if !ok { + return false + } + m[i]-- + if m[i] == 0 { + delete(m, i) + } + } + return len(m) == 0 +} diff --git a/testkit/testutil/require_test.go b/testkit/testutil/require_test.go new file mode 100644 index 0000000000000..49491a62c7619 --- /dev/null +++ b/testkit/testutil/require_test.go @@ -0,0 +1,33 @@ +// Copyright 2022 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutil + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/goleak" +) + +func TestCompareUnorderedString(t *testing.T) { + defer goleak.VerifyNone(t) + require.True(t, CompareUnorderedStringSlice([]string{"1", "1", "2"}, []string{"1", "1", "2"})) + require.True(t, CompareUnorderedStringSlice([]string{"1", "1", "2"}, []string{"1", "2", "1"})) + require.False(t, CompareUnorderedStringSlice([]string{"1", "1"}, []string{"1", "2", "1"})) + require.False(t, CompareUnorderedStringSlice([]string{"1", "1", "2"}, []string{"1", "2", "2"})) + require.True(t, CompareUnorderedStringSlice(nil, nil)) + require.False(t, CompareUnorderedStringSlice([]string{}, nil)) + require.False(t, CompareUnorderedStringSlice(nil, []string{})) +} diff --git a/tests/globalkilltest/global_kill_test.go b/tests/globalkilltest/global_kill_test.go index e0af71d35d70a..009bf6ed6c652 100644 --- a/tests/globalkilltest/global_kill_test.go +++ b/tests/globalkilltest/global_kill_test.go @@ -31,7 +31,7 @@ import ( "github.com/pingcap/log" "github.com/pingcap/tidb/util/logutil" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/clientv3" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" "google.golang.org/grpc" ) diff --git a/tests/globalkilltest/main_test.go b/tests/globalkilltest/main_test.go index ae4d8e2d63b02..71ee2c7e95780 100644 --- a/tests/globalkilltest/main_test.go +++ b/tests/globalkilltest/main_test.go @@ -22,6 +22,6 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() os.Exit(m.Run()) } diff --git a/tests/graceshutdown/main_test.go b/tests/graceshutdown/main_test.go index 65f1a0ac1d78e..dc131695874f7 100644 --- a/tests/graceshutdown/main_test.go +++ b/tests/graceshutdown/main_test.go @@ -22,8 +22,9 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() + testbridge.SetupForCommonTest() opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), goleak.IgnoreTopFunction("syscall.syscall6"), } goleak.VerifyTestMain(m, opts...) diff --git a/tests/readonlytest/go.mod b/tests/readonlytest/go.mod index a4c912bf9de6b..cc0b22e3b1343 100644 --- a/tests/readonlytest/go.mod +++ b/tests/readonlytest/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/pingcap/tidb v2.0.11+incompatible github.com/stretchr/testify v1.7.0 - go.uber.org/goleak v1.1.11 + go.uber.org/goleak v1.1.12 ) replace github.com/pingcap/tidb => ../../ diff --git a/tests/readonlytest/go.sum b/tests/readonlytest/go.sum index f3facf536b3f1..387cfacb99a28 100644 --- a/tests/readonlytest/go.sum +++ b/tests/readonlytest/go.sum @@ -43,6 +43,10 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0/go.mod h1:ZPW/Z0kLCTdDZaDbYTetxc9Cxl/2lNqxYHYNOF2bti0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.12.0/go.mod h1:GJzjM4SR9T0KyX5gKCVyz1ytD8FeWeUPCwtFCt1AyfE= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0/go.mod h1:eHWhQKXc1Gv1DvWH//UzgWjWFEo0Pp4pH2vBzjBw8Fc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= @@ -151,6 +155,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -175,6 +181,7 @@ github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/fake-gcs-server v1.19.0/go.mod h1:JtXHY/QzHhtyIxsNfIuQ+XgHtRb5B/w8nqbL5O8zqo0= @@ -352,6 +359,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= @@ -434,6 +442,7 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -450,6 +459,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -496,6 +506,7 @@ github.com/pingcap/errors v0.11.5-0.20200917111840-a15ef68f753d/go.mod h1:g4vx// github.com/pingcap/errors v0.11.5-0.20201029093017-5a7df2af2ac7/go.mod h1:G7x87le1poQzLB/TqvTJI2ILrSgobnq4Ut7luOwvfvI= github.com/pingcap/errors v0.11.5-0.20201126102027-b0a155152ca3/go.mod h1:G7x87le1poQzLB/TqvTJI2ILrSgobnq4Ut7luOwvfvI= github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= +github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= github.com/pingcap/failpoint v0.0.0-20191029060244-12f4ac2fd11d/go.mod h1:DNS3Qg7bEDhU6EXNHF+XSv/PGznQaMJ5FWvctpm6pQI= github.com/pingcap/failpoint v0.0.0-20200702092429-9f69995143ce/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk= github.com/pingcap/failpoint v0.0.0-20210316064728-7acb0f0a3dfd/go.mod h1:IVF+ijPSMZVtx2oIqxAg7ur6EyixtTYfOHwpfmlhqI4= @@ -506,20 +517,31 @@ github.com/pingcap/kvproto v0.0.0-20200411081810-b85805c9476c/go.mod h1:IOdRDPLy github.com/pingcap/kvproto v0.0.0-20210219064844-c1844a4775d6/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/kvproto v0.0.0-20210805052247-76981389e818/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/kvproto v0.0.0-20210806074406-317f69fb54b4/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20210819164333-bd5706b9d9f2/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20211109071446-a8b4d34474bc/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20211122024046-03abd340988f/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20211207042851-78a55fb8e69c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20201112100606-8f1e84a3abc8/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20210317133921-96f4fcab92a4/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM= +github.com/pingcap/log v0.0.0-20210906054005-afc726e70354 h1:SvWCbCPh1YeHd9yQLksvJYAgft6wLTY1aNG81tpyscQ= github.com/pingcap/log v0.0.0-20210906054005-afc726e70354/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= github.com/pingcap/parser v0.0.0-20210525032559-c37778aff307/go.mod h1:xZC8I7bug4GJ5KtHhgAikjTfU4kBv1Sbo3Pf1MZ6lVw= github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= github.com/pingcap/sysutil v0.0.0-20210315073920-cc0985d983a3/go.mod h1:tckvA041UWP+NqYzrJ3fMgC/Hw9wnmQ/tUkp/JaHly8= github.com/pingcap/sysutil v0.0.0-20210730114356-fcd8a63f68c5/go.mod h1:XsOaV712rUk63aOEKYP9PhXTIE3FMNHmC2r1wX5wElY= +github.com/pingcap/sysutil v0.0.0-20211208032423-041a72e5860d/go.mod h1:7j18ezaWTao2LHOyMlsc2Dg1vW+mDY9dEbPzVyOlaeM= github.com/pingcap/tidb-dashboard v0.0.0-20210312062513-eef5d6404638/go.mod h1:OzFN8H0EDMMqeulPhPMw2i2JaiZWOKFQ7zdRPhENNgo= github.com/pingcap/tidb-dashboard v0.0.0-20210716172320-2226872e3296/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ= +github.com/pingcap/tidb-dashboard v0.0.0-20211008050453-a25c25809529/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ= +github.com/pingcap/tidb-dashboard v0.0.0-20211107164327-80363dfbe884/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ= github.com/pingcap/tidb-tools v5.0.3+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= github.com/pingcap/tipb v0.0.0-20210802080519-94b831c6db55/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= +github.com/pingcap/tipb v0.0.0-20220107024056-3b91949a18a7/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -569,6 +591,7 @@ github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v2.19.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= @@ -619,8 +642,11 @@ github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJH github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tikv/client-go/v2 v2.0.0-alpha.0.20210926100628-3cc2459779ca/go.mod h1:KwtZXt0JD+bP9bWW2ka0ir3Wp3oTEfZUTh22bs2sI4o= +github.com/tikv/client-go/v2 v2.0.0-rc.0.20211229051614-62d6b4a2e8f7/go.mod h1:wRuh+W35daKTiYBld0oBlT6PSkzEVr+pB/vChzJZk+8= github.com/tikv/pd v1.1.0-beta.0.20210323121136-78679e5e209d/go.mod h1:Jw9KG11C/23Rr7DW4XWQ7H5xOgGZo6DFL1OKAF4+Igw= github.com/tikv/pd v1.1.0-beta.0.20210818082359-acba1da0018d/go.mod h1:rammPjeZgpvfrQRPkijcx8tlxF1XM5+m6kRXrkDzCAA= +github.com/tikv/pd v1.1.0-beta.0.20211029083450-e65f0c55b6ae/go.mod h1:varH0IE0jJ9E9WN2Ei/N6pajMlPkcXdDEf7f5mmsUVQ= +github.com/tikv/pd v1.1.0-beta.0.20211118054146-02848d2660ee/go.mod h1:lRbwxBAhnTQR5vqbTzeI/Bj62bD2OvYYuFezo2vrmeI= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -668,6 +694,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -688,6 +715,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= @@ -697,11 +725,14 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -712,6 +743,7 @@ go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -728,8 +760,10 @@ golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -770,6 +804,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -808,6 +843,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -817,6 +853,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -909,6 +948,9 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -998,12 +1040,15 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1158,6 +1203,7 @@ gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mN gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -1187,7 +1233,20 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= +modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254= +modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk= +modernc.org/lexer v1.0.0/go.mod h1:F/Dld0YKYdZCLQ7bD0USbWL4YKCyTDRDHiDTOs0q0vk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/parser v1.0.0/go.mod h1:H20AntYJ2cHHL6MHthJ8LZzXCdDCHMWt1KZXtIMjejA= +modernc.org/parser v1.0.2/go.mod h1:TXNq3HABP3HMaqLK7brD1fLA/LfN0KS6JxZn71QdDqs= +modernc.org/scanner v1.0.1/go.mod h1:OIzD2ZtjYk6yTuyqZr57FmifbM9fIH74SumloSsajuE= +modernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtxM= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/y v1.0.1/go.mod h1:Ho86I+LVHEI+LYXoUKlmOMAM1JTXOCfj8qi1T8PsClE= moul.io/zapgorm2 v1.1.0/go.mod h1:emRfKjNqSzVj5lcgasBdovIXY1jSOwFz2GQZn1Rddks= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/tests/readonlytest/main_test.go b/tests/readonlytest/main_test.go index 6d7f7491b6296..3bfa7bb5ec28c 100644 --- a/tests/readonlytest/main_test.go +++ b/tests/readonlytest/main_test.go @@ -22,6 +22,11 @@ import ( ) func TestMain(m *testing.M) { - testbridge.WorkaroundGoCheckFlags() - goleak.VerifyTestMain(m) + testbridge.SetupForCommonTest() + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*loggingT).flushDaemon"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + goleak.VerifyTestMain(m, opts...) } diff --git a/tests/readonlytest/readonly_test.go b/tests/readonlytest/readonly_test.go index 8674ea4c45dba..bf2f267531788 100644 --- a/tests/readonlytest/readonly_test.go +++ b/tests/readonlytest/readonly_test.go @@ -27,9 +27,14 @@ import ( ) var ( - tidbRootPassword = flag.String("passwd", "", "tidb root password") - tidbStartPort = flag.Int("tidb_start_port", 4000, "first tidb server listening port") - ReadOnlyErrMsg = "Error 1836: Running in read-only mode" + tidbRootPassword = flag.String("passwd", "", "tidb root password") + tidbAPort = flag.Int("tidb_a_port", 4001, "first tidb server listening port") + tidbBPort = flag.Int("tidb_b_port", 4002, "second tidb server listening port") + ReadOnlyErrMsg = "Error 1836: Running in read-only mode" + ConflictErrMsg = "Error 1105: can't turn off tidb_super_read_only when tidb_restricted_read_only is on" + PriviledgedErrMsg = "Error 1227: Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation" + TiDBRestrictedReadOnly = "tidb_restricted_read_only" + TiDBSuperReadOnly = "tidb_super_read_only" ) type ReadOnlySuite struct { @@ -38,34 +43,40 @@ type ReadOnlySuite struct { rdb *sql.DB } -func checkVariable(t *testing.T, db *sql.DB, on bool) { +func checkVariable(t *testing.T, db *sql.DB, variable string, on bool) { var name, status string - rs, err := db.Query("show variables like 'tidb_restricted_read_only'") + rs, err := db.Query(fmt.Sprintf("show variables like '%s'", variable)) require.NoError(t, err) require.True(t, rs.Next()) require.NoError(t, rs.Scan(&name, &status)) - require.Equal(t, name, "tidb_restricted_read_only") + require.Equal(t, name, variable) if on { - require.Equal(t, status, "ON") + require.Equal(t, "ON", status) } else { - require.Equal(t, status, "OFF") + require.Equal(t, "OFF", status) } require.NoError(t, rs.Close()) } -func setReadOnly(t *testing.T, db *sql.DB, status int) { - _, err := db.Exec(fmt.Sprintf("set global tidb_restricted_read_only=%d", status)) +func setVariableNoError(t *testing.T, db *sql.DB, variable string, status int) { + _, err := db.Exec(fmt.Sprintf("set global %s=%d", variable, status)) require.NoError(t, err) } +func setVariable(t *testing.T, db *sql.DB, variable string, status int) error { + _, err := db.Exec(fmt.Sprintf("set global %s=%d", variable, status)) + return err +} + func createReadOnlySuite(t *testing.T) (s *ReadOnlySuite, clean func()) { s = new(ReadOnlySuite) var err error - s.db, err = sql.Open("mysql", fmt.Sprintf("root:%s@(%s:%d)/test", *tidbRootPassword, "127.0.0.1", *tidbStartPort+1)) + s.db, err = sql.Open("mysql", fmt.Sprintf("root:%s@(%s:%d)/test", *tidbRootPassword, "127.0.0.1", *tidbAPort)) require.NoError(t, err) - setReadOnly(t, s.db, 0) + setVariableNoError(t, s.db, TiDBRestrictedReadOnly, 0) + setVariableNoError(t, s.db, TiDBSuperReadOnly, 0) _, err = s.db.Exec("drop user if exists 'u1'@'%'") require.NoError(t, err) @@ -73,7 +84,7 @@ func createReadOnlySuite(t *testing.T) (s *ReadOnlySuite, clean func()) { require.NoError(t, err) _, err = s.db.Exec("grant all privileges on test.* to 'u1'@'%'") require.NoError(t, err) - s.udb, err = sql.Open("mysql", fmt.Sprintf("u1:password@(%s:%d)/test", "127.0.0.1", *tidbStartPort+2)) + s.udb, err = sql.Open("mysql", fmt.Sprintf("u1:password@(%s:%d)/test", "127.0.0.1", *tidbBPort)) require.NoError(t, err) _, err = s.db.Exec("drop user if exists 'r1'@'%'") require.NoError(t, err) @@ -83,7 +94,7 @@ func createReadOnlySuite(t *testing.T) (s *ReadOnlySuite, clean func()) { require.NoError(t, err) _, err = s.db.Exec("grant RESTRICTED_REPLICA_WRITER_ADMIN on *.* to 'r1'@'%'") require.NoError(t, err) - s.rdb, err = sql.Open("mysql", fmt.Sprintf("r1:password@(%s:%d)/test", "127.0.0.1", *tidbStartPort+2)) + s.rdb, err = sql.Open("mysql", fmt.Sprintf("r1:password@(%s:%d)/test", "127.0.0.1", *tidbBPort)) require.NoError(t, err) clean = func() { require.NoError(t, s.db.Close()) @@ -96,27 +107,82 @@ func createReadOnlySuite(t *testing.T) (s *ReadOnlySuite, clean func()) { func TestRestriction(t *testing.T) { s, clean := createReadOnlySuite(t) defer clean() - _, err := s.db.Exec("set global tidb_restricted_read_only=1") + + var err error + _, err = s.db.Exec("drop table if exists t") require.NoError(t, err) + _, err = s.udb.Exec("create table t (a int primary key, b int)") + require.NoError(t, err) + _, err = s.udb.Exec("insert into t values (1, 1)") + require.NoError(t, err) + _, err = s.udb.Exec("update t set b = 2 where a = 1") + require.NoError(t, err) + + setVariable(t, s.db, TiDBRestrictedReadOnly, 1) time.Sleep(1) - checkVariable(t, s.udb, true) + checkVariable(t, s.udb, TiDBRestrictedReadOnly, true) + checkVariable(t, s.udb, TiDBSuperReadOnly, true) + + checkVariable(t, s.rdb, TiDBRestrictedReadOnly, true) + checkVariable(t, s.rdb, TiDBSuperReadOnly, true) + + // can't create table _, err = s.udb.Exec("create table t(a int)") require.Error(t, err) require.Equal(t, err.Error(), ReadOnlyErrMsg) + + // can't do point update when tidb_restricted_read_only is on + _, err = s.udb.Exec("update t set b = 2 where a = 1") + require.Error(t, err) + require.Equal(t, err.Error(), ReadOnlyErrMsg) + + // can't insert + _, err = s.udb.Exec("insert into t values (2, 3)") + require.Error(t, err) + require.Equal(t, err.Error(), ReadOnlyErrMsg) + + // can't turn off tidb_super_read_only if tidb_restricted_read_only is on + err = setVariable(t, s.db, TiDBSuperReadOnly, 0) + require.Error(t, err) + require.Equal(t, err.Error(), ConflictErrMsg) + + // can't change global variable + err = setVariable(t, s.udb, TiDBSuperReadOnly, 0) + require.Error(t, err) + require.Equal(t, err.Error(), PriviledgedErrMsg) + + err = setVariable(t, s.rdb, TiDBSuperReadOnly, 0) + require.Error(t, err) + require.Equal(t, err.Error(), PriviledgedErrMsg) + + // turn off tidb_restricted_read_only does not affect tidb_super_read_only + setVariableNoError(t, s.db, TiDBRestrictedReadOnly, 0) + + checkVariable(t, s.udb, TiDBRestrictedReadOnly, false) + checkVariable(t, s.rdb, TiDBRestrictedReadOnly, false) + + checkVariable(t, s.udb, TiDBSuperReadOnly, true) + checkVariable(t, s.rdb, TiDBSuperReadOnly, true) + + // it is now allowed to turn off tidb_super_read_only + setVariableNoError(t, s.db, TiDBSuperReadOnly, 0) + + checkVariable(t, s.udb, TiDBRestrictedReadOnly, false) + checkVariable(t, s.rdb, TiDBRestrictedReadOnly, false) + + checkVariable(t, s.udb, TiDBSuperReadOnly, false) + checkVariable(t, s.rdb, TiDBSuperReadOnly, false) } func TestRestrictionWithConnectionPool(t *testing.T) { s, clean := createReadOnlySuite(t) defer clean() - _, err := s.db.Exec("set global tidb_restricted_read_only=0") - require.NoError(t, err) + var err error _, err = s.db.Exec("drop table if exists t") require.NoError(t, err) _, err = s.db.Exec("create table t (a int)") require.NoError(t, err) - time.Sleep(1) - checkVariable(t, s.udb, false) conn, err := s.udb.Conn(context.Background()) require.NoError(t, err) @@ -142,8 +208,7 @@ func TestRestrictionWithConnectionPool(t *testing.T) { time.Sleep(1 * time.Second) timer := time.NewTimer(10 * time.Second) - _, err = s.db.Exec("set global tidb_restricted_read_only=1") - require.NoError(t, err) + setVariableNoError(t, s.db, TiDBRestrictedReadOnly, 1) select { case <-timer.C: require.Fail(t, "failed") @@ -161,8 +226,6 @@ func TestReplicationWriter(t *testing.T) { require.NoError(t, err) _, err = s.db.Exec("create table t (a int)") require.NoError(t, err) - time.Sleep(1) - checkVariable(t, s.udb, false) conn, err := s.rdb.Conn(context.Background()) require.NoError(t, err) diff --git a/tidb-binlog/driver/README.md b/tidb-binlog/driver/README.md new file mode 100644 index 0000000000000..21c5711465dc0 --- /dev/null +++ b/tidb-binlog/driver/README.md @@ -0,0 +1,15 @@ +# TiDB-Binlog Driver library + +A pure go library to handle TiDB Binlog replication. + +# Introduction + +### Reader + +a package read [TiDB Binlog protocol](../slave_binlog_proto/proto) + +### Examples + +[MySQL Replicate client](./example/mysql) + +[Text Output Replicate client](./example/print) \ No newline at end of file diff --git a/tidb-binlog/driver/example/kafkaReader/.gitignore b/tidb-binlog/driver/example/kafkaReader/.gitignore new file mode 100644 index 0000000000000..3dad8ccab5fcd --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/.gitignore @@ -0,0 +1,4 @@ +target +.idea +out/ +*.iml diff --git a/tidb-binlog/driver/example/kafkaReader/README.md b/tidb-binlog/driver/example/kafkaReader/README.md new file mode 100644 index 0000000000000..1f813a562ece9 --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/README.md @@ -0,0 +1,17 @@ +### consume and parse kafka binlog message for java demo + +#### Env: +tidb: v3.0.0
+drainer: v3.0.0
+kafka: kafka_2.12 1.0.0
+local windows environment protobuf version:protoc-3.9.1-win64
+[binlog.proto](https://github.com/pingcap/tidb-tools/blob/master/tidb-binlog/slave_binlog_proto/proto/binlog.proto) use official point file。 + +#### Execute protoc command to generate java file: +protoc --java_out=src/main/java src/main/resources/proto/descriptor.proto --proto_path=src/main/resources/proto/
+protoc --java_out=src/main/java src/main/resources/proto/gogo.proto --proto_path=src/main/resources/proto/
+protoc --java_out=src/main/java src/main/resources/proto/binlog.proto --proto_path=src/main/resources/proto/
+ +#### How to run: +in intel idea ide, run Booter.java main method。
+point Booter.topicã€Booter.sereverã€Booter.offset and run it。 diff --git a/tidb-binlog/driver/example/kafkaReader/pom.xml b/tidb-binlog/driver/example/kafkaReader/pom.xml new file mode 100644 index 0000000000000..325669a4455ee --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + com.lianlianpay + kafkaReader + 1.0-SNAPSHOT + + + + 1.8 + UTF-8 + 5.3.3 + 5.6.11 + 0.0.1-SNAPSHOT + + + + + + + org.apache.kafka + kafka-clients + 1.0.0 + + + + org.apache.kafka + kafka_2.12 + 1.0.0 + + + + com.google.protobuf + protobuf-java + 3.16.1 + + + + com.google.protobuf + protobuf-java-util + 3.9.1 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + utf-8 + ${java.version} + ${java.version} + + + + + + \ No newline at end of file diff --git a/tidb-binlog/driver/example/kafkaReader/src/main/java/Booter.java b/tidb-binlog/driver/example/kafkaReader/src/main/java/Booter.java new file mode 100644 index 0000000000000..44eef5903d477 --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/src/main/java/Booter.java @@ -0,0 +1,101 @@ +import com.pingcap.kafkareader.proto.BinLogInfo; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.common.TopicPartition; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * @description: kafka消费binlog java demo + * @author: ceaserwang@outlook.com + * @create: 2019-08-15 21:45 + **/ +public class Booter { + /** + * 主题 + */ + private static String topic = "6717826900501472462_obinlog"; + /** + * kafka brokers + */ + private static String serever = "192.168.138.22:9092,192.168.138.23:9092,192.168.138.24:9092"; + + /** + * 消费者åç§»é‡ + */ + private static long offset = 60; + + /** + * 消费者线程 + */ + private Thread kafkaConsumerThread; + /** + * 消费者 + */ + private KafkaConsumer consumer; + + public static void main(String[] args) { + Booter booter = new Booter(); + booter.init(); + } + + public void init() { + Properties props = assembleConsumerProperties(); + this.consumer = new KafkaConsumer(props); + consumer.assign(Arrays.asList(new TopicPartition(Booter.topic,0))); + kafkaConsumerThread = new Thread(() -> { + Map currentOffsets = new HashMap<>(); + while (true) { + try { + // 指定分区消费的æŸä¸ªoffset消费 + consumer.seek(new TopicPartition(Booter.topic, 0), offset); + ConsumerRecords records = consumer.poll(200); + for (ConsumerRecord record : records) { + try { + //处ç†æ¶ˆæ¯ + dealMessage(record.value()); + currentOffsets.put(new TopicPartition(Booter.topic, record.partition()), new OffsetAndMetadata(record.offset() + 1, "no metadata")); + //æ交 + consumer.commitSync(currentOffsets); + currentOffsets.clear(); + //记录消æ¯offset到db + } catch (Exception ie) { + //当å‰æ¶ˆæ¯å¤„ç†å¤±è´¥ + currentOffsets.clear(); + } + } + } catch (Exception e) { + currentOffsets.clear(); + } + } + }); + kafkaConsumerThread.setName("kafkaConsumerThread"); + kafkaConsumerThread.start(); + } + + private void dealMessage(byte[] value) throws Exception { + BinLogInfo.Binlog binlog = BinLogInfo.Binlog.parseFrom(value); + System.out.println(binlog.toString()); + } + + private Properties assembleConsumerProperties() { + Properties props = new Properties(); + props.put("bootstrap.servers",Booter.serever); + props.put("group.id", "mytest"); + //自动æ交ä½ç§»å…³é—­ + props.put("enable.auto.commit", "false"); + props.put("auto.commit.interval.ms", "1000"); + props.put("session.timeout.ms", "30000"); + props.put("max.poll.records", "10"); + //必须使用ByteArrayDeserializer + props.put("key.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer"); + props.put("value.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer"); + return props; + } + +} diff --git a/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/BinLogInfo.java b/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/BinLogInfo.java new file mode 100644 index 0000000000000..b09fd8f402e04 --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/BinLogInfo.java @@ -0,0 +1,8689 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: binlog.proto + +package com.pingcap.kafkareader.proto; + +public final class BinLogInfo { + private BinLogInfo() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + /** + * Protobuf enum {@code com.tnp.search.MutationType} + */ + public enum MutationType + implements com.google.protobuf.ProtocolMessageEnum { + /** + * Insert = 0; + */ + Insert(0), + /** + * Update = 1; + */ + Update(1), + /** + * Delete = 2; + */ + Delete(2), + ; + + /** + * Insert = 0; + */ + public static final int Insert_VALUE = 0; + /** + * Update = 1; + */ + public static final int Update_VALUE = 1; + /** + * Delete = 2; + */ + public static final int Delete_VALUE = 2; + + + public final int getNumber() { + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static MutationType valueOf(int value) { + return forNumber(value); + } + + public static MutationType forNumber(int value) { + switch (value) { + case 0: return Insert; + case 1: return Update; + case 2: return Delete; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + MutationType> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public MutationType findValueByNumber(int number) { + return MutationType.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.getDescriptor().getEnumTypes().get(0); + } + + private static final MutationType[] VALUES = values(); + + public static MutationType valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private MutationType(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:com.tnp.search.MutationType) + } + + /** + * Protobuf enum {@code com.tnp.search.BinlogType} + */ + public enum BinlogType + implements com.google.protobuf.ProtocolMessageEnum { + /** + *
+     *  has dml_data
+     * 
+ * + * DML = 0; + */ + DML(0), + /** + *
+     *  has ddl_query
+     * 
+ * + * DDL = 1; + */ + DDL(1), + ; + + /** + *
+     *  has dml_data
+     * 
+ * + * DML = 0; + */ + public static final int DML_VALUE = 0; + /** + *
+     *  has ddl_query
+     * 
+ * + * DDL = 1; + */ + public static final int DDL_VALUE = 1; + + + public final int getNumber() { + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static BinlogType valueOf(int value) { + return forNumber(value); + } + + public static BinlogType forNumber(int value) { + switch (value) { + case 0: return DML; + case 1: return DDL; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + BinlogType> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public BinlogType findValueByNumber(int number) { + return BinlogType.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.getDescriptor().getEnumTypes().get(1); + } + + private static final BinlogType[] VALUES = values(); + + public static BinlogType valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private BinlogType(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:com.tnp.search.BinlogType) + } + + public interface ColumnOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.Column) + com.google.protobuf.MessageOrBuilder { + + /** + * optional bool is_null = 1 [default = false]; + */ + boolean hasIsNull(); + /** + * optional bool is_null = 1 [default = false]; + */ + boolean getIsNull(); + + /** + * optional int64 int64_value = 2; + */ + boolean hasInt64Value(); + /** + * optional int64 int64_value = 2; + */ + long getInt64Value(); + + /** + * optional uint64 uint64_value = 3; + */ + boolean hasUint64Value(); + /** + * optional uint64 uint64_value = 3; + */ + long getUint64Value(); + + /** + * optional double double_value = 4; + */ + boolean hasDoubleValue(); + /** + * optional double double_value = 4; + */ + double getDoubleValue(); + + /** + * optional bytes bytes_value = 5; + */ + boolean hasBytesValue(); + /** + * optional bytes bytes_value = 5; + */ + com.google.protobuf.ByteString getBytesValue(); + + /** + * optional string string_value = 6; + */ + boolean hasStringValue(); + /** + * optional string string_value = 6; + */ + java.lang.String getStringValue(); + /** + * optional string string_value = 6; + */ + com.google.protobuf.ByteString + getStringValueBytes(); + } + /** + *
+   * for text and char type, string_value is set
+   * for blob and binary type, bytes_value is set
+   * for enum, set, uint64_value is set
+   * for json, bytes_value is set
+   * 
+ * + * Protobuf type {@code com.tnp.search.Column} + */ + public static final class Column extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.Column) + ColumnOrBuilder { + private static final long serialVersionUID = 0L; + // Use Column.newBuilder() to construct. + private Column(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Column() { + bytesValue_ = com.google.protobuf.ByteString.EMPTY; + stringValue_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Column(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Column( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + bitField0_ |= 0x00000001; + isNull_ = input.readBool(); + break; + } + case 16: { + bitField0_ |= 0x00000002; + int64Value_ = input.readInt64(); + break; + } + case 24: { + bitField0_ |= 0x00000004; + uint64Value_ = input.readUInt64(); + break; + } + case 33: { + bitField0_ |= 0x00000008; + doubleValue_ = input.readDouble(); + break; + } + case 42: { + bitField0_ |= 0x00000010; + bytesValue_ = input.readBytes(); + break; + } + case 50: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000020; + stringValue_ = bs; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Column_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Column_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Column.class, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder.class); + } + + private int bitField0_; + public static final int IS_NULL_FIELD_NUMBER = 1; + private boolean isNull_; + /** + * optional bool is_null = 1 [default = false]; + */ + public boolean hasIsNull() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional bool is_null = 1 [default = false]; + */ + public boolean getIsNull() { + return isNull_; + } + + public static final int INT64_VALUE_FIELD_NUMBER = 2; + private long int64Value_; + /** + * optional int64 int64_value = 2; + */ + public boolean hasInt64Value() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int64 int64_value = 2; + */ + public long getInt64Value() { + return int64Value_; + } + + public static final int UINT64_VALUE_FIELD_NUMBER = 3; + private long uint64Value_; + /** + * optional uint64 uint64_value = 3; + */ + public boolean hasUint64Value() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional uint64 uint64_value = 3; + */ + public long getUint64Value() { + return uint64Value_; + } + + public static final int DOUBLE_VALUE_FIELD_NUMBER = 4; + private double doubleValue_; + /** + * optional double double_value = 4; + */ + public boolean hasDoubleValue() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional double double_value = 4; + */ + public double getDoubleValue() { + return doubleValue_; + } + + public static final int BYTES_VALUE_FIELD_NUMBER = 5; + private com.google.protobuf.ByteString bytesValue_; + /** + * optional bytes bytes_value = 5; + */ + public boolean hasBytesValue() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + * optional bytes bytes_value = 5; + */ + public com.google.protobuf.ByteString getBytesValue() { + return bytesValue_; + } + + public static final int STRING_VALUE_FIELD_NUMBER = 6; + private volatile java.lang.Object stringValue_; + /** + * optional string string_value = 6; + */ + public boolean hasStringValue() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + * optional string string_value = 6; + */ + public java.lang.String getStringValue() { + java.lang.Object ref = stringValue_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + stringValue_ = s; + } + return s; + } + } + /** + * optional string string_value = 6; + */ + public com.google.protobuf.ByteString + getStringValueBytes() { + java.lang.Object ref = stringValue_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + stringValue_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeBool(1, isNull_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeInt64(2, int64Value_); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeUInt64(3, uint64Value_); + } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeDouble(4, doubleValue_); + } + if (((bitField0_ & 0x00000010) != 0)) { + output.writeBytes(5, bytesValue_); + } + if (((bitField0_ & 0x00000020) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 6, stringValue_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(1, isNull_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, int64Value_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(3, uint64Value_); + } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeDoubleSize(4, doubleValue_); + } + if (((bitField0_ & 0x00000010) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(5, bytesValue_); + } + if (((bitField0_ & 0x00000020) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, stringValue_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.Column)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.Column other = (com.pingcap.kafkareader.proto.BinLogInfo.Column) obj; + + if (hasIsNull() != other.hasIsNull()) return false; + if (hasIsNull()) { + if (getIsNull() + != other.getIsNull()) return false; + } + if (hasInt64Value() != other.hasInt64Value()) return false; + if (hasInt64Value()) { + if (getInt64Value() + != other.getInt64Value()) return false; + } + if (hasUint64Value() != other.hasUint64Value()) return false; + if (hasUint64Value()) { + if (getUint64Value() + != other.getUint64Value()) return false; + } + if (hasDoubleValue() != other.hasDoubleValue()) return false; + if (hasDoubleValue()) { + if (java.lang.Double.doubleToLongBits(getDoubleValue()) + != java.lang.Double.doubleToLongBits( + other.getDoubleValue())) return false; + } + if (hasBytesValue() != other.hasBytesValue()) return false; + if (hasBytesValue()) { + if (!getBytesValue() + .equals(other.getBytesValue())) return false; + } + if (hasStringValue() != other.hasStringValue()) return false; + if (hasStringValue()) { + if (!getStringValue() + .equals(other.getStringValue())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasIsNull()) { + hash = (37 * hash) + IS_NULL_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getIsNull()); + } + if (hasInt64Value()) { + hash = (37 * hash) + INT64_VALUE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getInt64Value()); + } + if (hasUint64Value()) { + hash = (37 * hash) + UINT64_VALUE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getUint64Value()); + } + if (hasDoubleValue()) { + hash = (37 * hash) + DOUBLE_VALUE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getDoubleValue())); + } + if (hasBytesValue()) { + hash = (37 * hash) + BYTES_VALUE_FIELD_NUMBER; + hash = (53 * hash) + getBytesValue().hashCode(); + } + if (hasStringValue()) { + hash = (37 * hash) + STRING_VALUE_FIELD_NUMBER; + hash = (53 * hash) + getStringValue().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Column parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.Column prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * for text and char type, string_value is set
+     * for blob and binary type, bytes_value is set
+     * for enum, set, uint64_value is set
+     * for json, bytes_value is set
+     * 
+ * + * Protobuf type {@code com.tnp.search.Column} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.Column) + com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Column_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Column_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Column.class, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.Column.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + isNull_ = false; + bitField0_ = (bitField0_ & ~0x00000001); + int64Value_ = 0L; + bitField0_ = (bitField0_ & ~0x00000002); + uint64Value_ = 0L; + bitField0_ = (bitField0_ & ~0x00000004); + doubleValue_ = 0D; + bitField0_ = (bitField0_ & ~0x00000008); + bytesValue_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000010); + stringValue_ = ""; + bitField0_ = (bitField0_ & ~0x00000020); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Column_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Column getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.Column.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Column build() { + com.pingcap.kafkareader.proto.BinLogInfo.Column result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Column buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.Column result = new com.pingcap.kafkareader.proto.BinLogInfo.Column(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.isNull_ = isNull_; + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.int64Value_ = int64Value_; + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.uint64Value_ = uint64Value_; + to_bitField0_ |= 0x00000004; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.doubleValue_ = doubleValue_; + to_bitField0_ |= 0x00000008; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + to_bitField0_ |= 0x00000010; + } + result.bytesValue_ = bytesValue_; + if (((from_bitField0_ & 0x00000020) != 0)) { + to_bitField0_ |= 0x00000020; + } + result.stringValue_ = stringValue_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.Column) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.Column)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.Column other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.Column.getDefaultInstance()) return this; + if (other.hasIsNull()) { + setIsNull(other.getIsNull()); + } + if (other.hasInt64Value()) { + setInt64Value(other.getInt64Value()); + } + if (other.hasUint64Value()) { + setUint64Value(other.getUint64Value()); + } + if (other.hasDoubleValue()) { + setDoubleValue(other.getDoubleValue()); + } + if (other.hasBytesValue()) { + setBytesValue(other.getBytesValue()); + } + if (other.hasStringValue()) { + bitField0_ |= 0x00000020; + stringValue_ = other.stringValue_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.Column parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.Column) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private boolean isNull_ ; + /** + * optional bool is_null = 1 [default = false]; + */ + public boolean hasIsNull() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional bool is_null = 1 [default = false]; + */ + public boolean getIsNull() { + return isNull_; + } + /** + * optional bool is_null = 1 [default = false]; + */ + public Builder setIsNull(boolean value) { + bitField0_ |= 0x00000001; + isNull_ = value; + onChanged(); + return this; + } + /** + * optional bool is_null = 1 [default = false]; + */ + public Builder clearIsNull() { + bitField0_ = (bitField0_ & ~0x00000001); + isNull_ = false; + onChanged(); + return this; + } + + private long int64Value_ ; + /** + * optional int64 int64_value = 2; + */ + public boolean hasInt64Value() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int64 int64_value = 2; + */ + public long getInt64Value() { + return int64Value_; + } + /** + * optional int64 int64_value = 2; + */ + public Builder setInt64Value(long value) { + bitField0_ |= 0x00000002; + int64Value_ = value; + onChanged(); + return this; + } + /** + * optional int64 int64_value = 2; + */ + public Builder clearInt64Value() { + bitField0_ = (bitField0_ & ~0x00000002); + int64Value_ = 0L; + onChanged(); + return this; + } + + private long uint64Value_ ; + /** + * optional uint64 uint64_value = 3; + */ + public boolean hasUint64Value() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional uint64 uint64_value = 3; + */ + public long getUint64Value() { + return uint64Value_; + } + /** + * optional uint64 uint64_value = 3; + */ + public Builder setUint64Value(long value) { + bitField0_ |= 0x00000004; + uint64Value_ = value; + onChanged(); + return this; + } + /** + * optional uint64 uint64_value = 3; + */ + public Builder clearUint64Value() { + bitField0_ = (bitField0_ & ~0x00000004); + uint64Value_ = 0L; + onChanged(); + return this; + } + + private double doubleValue_ ; + /** + * optional double double_value = 4; + */ + public boolean hasDoubleValue() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional double double_value = 4; + */ + public double getDoubleValue() { + return doubleValue_; + } + /** + * optional double double_value = 4; + */ + public Builder setDoubleValue(double value) { + bitField0_ |= 0x00000008; + doubleValue_ = value; + onChanged(); + return this; + } + /** + * optional double double_value = 4; + */ + public Builder clearDoubleValue() { + bitField0_ = (bitField0_ & ~0x00000008); + doubleValue_ = 0D; + onChanged(); + return this; + } + + private com.google.protobuf.ByteString bytesValue_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes bytes_value = 5; + */ + public boolean hasBytesValue() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + * optional bytes bytes_value = 5; + */ + public com.google.protobuf.ByteString getBytesValue() { + return bytesValue_; + } + /** + * optional bytes bytes_value = 5; + */ + public Builder setBytesValue(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000010; + bytesValue_ = value; + onChanged(); + return this; + } + /** + * optional bytes bytes_value = 5; + */ + public Builder clearBytesValue() { + bitField0_ = (bitField0_ & ~0x00000010); + bytesValue_ = getDefaultInstance().getBytesValue(); + onChanged(); + return this; + } + + private java.lang.Object stringValue_ = ""; + /** + * optional string string_value = 6; + */ + public boolean hasStringValue() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + * optional string string_value = 6; + */ + public java.lang.String getStringValue() { + java.lang.Object ref = stringValue_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + stringValue_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string string_value = 6; + */ + public com.google.protobuf.ByteString + getStringValueBytes() { + java.lang.Object ref = stringValue_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + stringValue_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string string_value = 6; + */ + public Builder setStringValue( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000020; + stringValue_ = value; + onChanged(); + return this; + } + /** + * optional string string_value = 6; + */ + public Builder clearStringValue() { + bitField0_ = (bitField0_ & ~0x00000020); + stringValue_ = getDefaultInstance().getStringValue(); + onChanged(); + return this; + } + /** + * optional string string_value = 6; + */ + public Builder setStringValueBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000020; + stringValue_ = value; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.Column) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.Column) + private static final com.pingcap.kafkareader.proto.BinLogInfo.Column DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.Column(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Column getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Column parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Column(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Column getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ColumnInfoOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.ColumnInfo) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + boolean hasName(); + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + java.lang.String getName(); + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + boolean hasMysqlType(); + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + java.lang.String getMysqlType(); + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + com.google.protobuf.ByteString + getMysqlTypeBytes(); + + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + boolean hasIsPrimaryKey(); + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + boolean getIsPrimaryKey(); + } + /** + * Protobuf type {@code com.tnp.search.ColumnInfo} + */ + public static final class ColumnInfo extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.ColumnInfo) + ColumnInfoOrBuilder { + private static final long serialVersionUID = 0L; + // Use ColumnInfo.newBuilder() to construct. + private ColumnInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private ColumnInfo() { + name_ = ""; + mysqlType_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new ColumnInfo(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ColumnInfo( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + name_ = bs; + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + mysqlType_ = bs; + break; + } + case 24: { + bitField0_ |= 0x00000004; + isPrimaryKey_ = input.readBool(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_ColumnInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_ColumnInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.class, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder.class); + } + + private int bitField0_; + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int MYSQL_TYPE_FIELD_NUMBER = 2; + private volatile java.lang.Object mysqlType_; + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public boolean hasMysqlType() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public java.lang.String getMysqlType() { + java.lang.Object ref = mysqlType_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + mysqlType_ = s; + } + return s; + } + } + /** + *
+     * lower case column field type in mysql
+     * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+     * for numeric type: int bigint smallint tinyint float double decimal bit
+     * for string type: text longtext mediumtext char tinytext varchar
+     * blob longblob mediumblob binary tinyblob varbinary
+     * enum set
+     * for json type: json
+     * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public com.google.protobuf.ByteString + getMysqlTypeBytes() { + java.lang.Object ref = mysqlType_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mysqlType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int IS_PRIMARY_KEY_FIELD_NUMBER = 3; + private boolean isPrimaryKey_; + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public boolean hasIsPrimaryKey() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public boolean getIsPrimaryKey() { + return isPrimaryKey_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, mysqlType_); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeBool(3, isPrimaryKey_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, mysqlType_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(3, isPrimaryKey_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo other = (com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo) obj; + + if (hasName() != other.hasName()) return false; + if (hasName()) { + if (!getName() + .equals(other.getName())) return false; + } + if (hasMysqlType() != other.hasMysqlType()) return false; + if (hasMysqlType()) { + if (!getMysqlType() + .equals(other.getMysqlType())) return false; + } + if (hasIsPrimaryKey() != other.hasIsPrimaryKey()) return false; + if (hasIsPrimaryKey()) { + if (getIsPrimaryKey() + != other.getIsPrimaryKey()) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasName()) { + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + } + if (hasMysqlType()) { + hash = (37 * hash) + MYSQL_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getMysqlType().hashCode(); + } + if (hasIsPrimaryKey()) { + hash = (37 * hash) + IS_PRIMARY_KEY_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getIsPrimaryKey()); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code com.tnp.search.ColumnInfo} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.ColumnInfo) + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_ColumnInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_ColumnInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.class, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + name_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + mysqlType_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + isPrimaryKey_ = false; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_ColumnInfo_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo build() { + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo result = new com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.name_ = name_; + if (((from_bitField0_ & 0x00000002) != 0)) { + to_bitField0_ |= 0x00000002; + } + result.mysqlType_ = mysqlType_; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.isPrimaryKey_ = isPrimaryKey_; + to_bitField0_ |= 0x00000004; + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.getDefaultInstance()) return this; + if (other.hasName()) { + bitField0_ |= 0x00000001; + name_ = other.name_; + onChanged(); + } + if (other.hasMysqlType()) { + bitField0_ |= 0x00000002; + mysqlType_ = other.mysqlType_; + onChanged(); + } + if (other.hasIsPrimaryKey()) { + setIsPrimaryKey(other.getIsPrimaryKey()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public Builder clearName() { + bitField0_ = (bitField0_ & ~0x00000001); + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * optional string name = 1 [(.gogoproto.nullable) = false]; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + + private java.lang.Object mysqlType_ = ""; + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public boolean hasMysqlType() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public java.lang.String getMysqlType() { + java.lang.Object ref = mysqlType_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + mysqlType_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public com.google.protobuf.ByteString + getMysqlTypeBytes() { + java.lang.Object ref = mysqlType_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mysqlType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public Builder setMysqlType( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + mysqlType_ = value; + onChanged(); + return this; + } + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public Builder clearMysqlType() { + bitField0_ = (bitField0_ & ~0x00000002); + mysqlType_ = getDefaultInstance().getMysqlType(); + onChanged(); + return this; + } + /** + *
+       * lower case column field type in mysql
+       * https://dev.mysql.com/doc/refman/8.0/en/data-types.html
+       * for numeric type: int bigint smallint tinyint float double decimal bit
+       * for string type: text longtext mediumtext char tinytext varchar
+       * blob longblob mediumblob binary tinyblob varbinary
+       * enum set
+       * for json type: json
+       * 
+ * + * optional string mysql_type = 2 [(.gogoproto.nullable) = false]; + */ + public Builder setMysqlTypeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + mysqlType_ = value; + onChanged(); + return this; + } + + private boolean isPrimaryKey_ ; + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public boolean hasIsPrimaryKey() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public boolean getIsPrimaryKey() { + return isPrimaryKey_; + } + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public Builder setIsPrimaryKey(boolean value) { + bitField0_ |= 0x00000004; + isPrimaryKey_ = value; + onChanged(); + return this; + } + /** + * optional bool is_primary_key = 3 [(.gogoproto.nullable) = false]; + */ + public Builder clearIsPrimaryKey() { + bitField0_ = (bitField0_ & ~0x00000004); + isPrimaryKey_ = false; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.ColumnInfo) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.ColumnInfo) + private static final com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ColumnInfo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ColumnInfo(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface RowOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.Row) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .com.tnp.search.Column columns = 1; + */ + java.util.List + getColumnsList(); + /** + * repeated .com.tnp.search.Column columns = 1; + */ + com.pingcap.kafkareader.proto.BinLogInfo.Column getColumns(int index); + /** + * repeated .com.tnp.search.Column columns = 1; + */ + int getColumnsCount(); + /** + * repeated .com.tnp.search.Column columns = 1; + */ + java.util.List + getColumnsOrBuilderList(); + /** + * repeated .com.tnp.search.Column columns = 1; + */ + com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder getColumnsOrBuilder( + int index); + } + /** + * Protobuf type {@code com.tnp.search.Row} + */ + public static final class Row extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.Row) + RowOrBuilder { + private static final long serialVersionUID = 0L; + // Use Row.newBuilder() to construct. + private Row(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Row() { + columns_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Row(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Row( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + columns_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + columns_.add( + input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.Column.PARSER, extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + columns_ = java.util.Collections.unmodifiableList(columns_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Row_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Row_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Row.class, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder.class); + } + + public static final int COLUMNS_FIELD_NUMBER = 1; + private java.util.List columns_; + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public java.util.List getColumnsList() { + return columns_; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public java.util.List + getColumnsOrBuilderList() { + return columns_; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public int getColumnsCount() { + return columns_.size(); + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Column getColumns(int index) { + return columns_.get(index); + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder getColumnsOrBuilder( + int index) { + return columns_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < columns_.size(); i++) { + output.writeMessage(1, columns_.get(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < columns_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, columns_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.Row)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.Row other = (com.pingcap.kafkareader.proto.BinLogInfo.Row) obj; + + if (!getColumnsList() + .equals(other.getColumnsList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getColumnsCount() > 0) { + hash = (37 * hash) + COLUMNS_FIELD_NUMBER; + hash = (53 * hash) + getColumnsList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Row parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.Row prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code com.tnp.search.Row} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.Row) + com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Row_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Row_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Row.class, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.Row.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getColumnsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + if (columnsBuilder_ == null) { + columns_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + columnsBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Row_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Row getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Row build() { + com.pingcap.kafkareader.proto.BinLogInfo.Row result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Row buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.Row result = new com.pingcap.kafkareader.proto.BinLogInfo.Row(this); + int from_bitField0_ = bitField0_; + if (columnsBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + columns_ = java.util.Collections.unmodifiableList(columns_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.columns_ = columns_; + } else { + result.columns_ = columnsBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.Row) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.Row)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.Row other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance()) return this; + if (columnsBuilder_ == null) { + if (!other.columns_.isEmpty()) { + if (columns_.isEmpty()) { + columns_ = other.columns_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureColumnsIsMutable(); + columns_.addAll(other.columns_); + } + onChanged(); + } + } else { + if (!other.columns_.isEmpty()) { + if (columnsBuilder_.isEmpty()) { + columnsBuilder_.dispose(); + columnsBuilder_ = null; + columns_ = other.columns_; + bitField0_ = (bitField0_ & ~0x00000001); + columnsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getColumnsFieldBuilder() : null; + } else { + columnsBuilder_.addAllMessages(other.columns_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.Row parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.Row) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List columns_ = + java.util.Collections.emptyList(); + private void ensureColumnsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + columns_ = new java.util.ArrayList(columns_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Column, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder> columnsBuilder_; + + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public java.util.List getColumnsList() { + if (columnsBuilder_ == null) { + return java.util.Collections.unmodifiableList(columns_); + } else { + return columnsBuilder_.getMessageList(); + } + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public int getColumnsCount() { + if (columnsBuilder_ == null) { + return columns_.size(); + } else { + return columnsBuilder_.getCount(); + } + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Column getColumns(int index) { + if (columnsBuilder_ == null) { + return columns_.get(index); + } else { + return columnsBuilder_.getMessage(index); + } + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder setColumns( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Column value) { + if (columnsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnsIsMutable(); + columns_.set(index, value); + onChanged(); + } else { + columnsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder setColumns( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder builderForValue) { + if (columnsBuilder_ == null) { + ensureColumnsIsMutable(); + columns_.set(index, builderForValue.build()); + onChanged(); + } else { + columnsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder addColumns(com.pingcap.kafkareader.proto.BinLogInfo.Column value) { + if (columnsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnsIsMutable(); + columns_.add(value); + onChanged(); + } else { + columnsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder addColumns( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Column value) { + if (columnsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnsIsMutable(); + columns_.add(index, value); + onChanged(); + } else { + columnsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder addColumns( + com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder builderForValue) { + if (columnsBuilder_ == null) { + ensureColumnsIsMutable(); + columns_.add(builderForValue.build()); + onChanged(); + } else { + columnsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder addColumns( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder builderForValue) { + if (columnsBuilder_ == null) { + ensureColumnsIsMutable(); + columns_.add(index, builderForValue.build()); + onChanged(); + } else { + columnsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder addAllColumns( + java.lang.Iterable values) { + if (columnsBuilder_ == null) { + ensureColumnsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, columns_); + onChanged(); + } else { + columnsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder clearColumns() { + if (columnsBuilder_ == null) { + columns_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + columnsBuilder_.clear(); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public Builder removeColumns(int index) { + if (columnsBuilder_ == null) { + ensureColumnsIsMutable(); + columns_.remove(index); + onChanged(); + } else { + columnsBuilder_.remove(index); + } + return this; + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder getColumnsBuilder( + int index) { + return getColumnsFieldBuilder().getBuilder(index); + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder getColumnsOrBuilder( + int index) { + if (columnsBuilder_ == null) { + return columns_.get(index); } else { + return columnsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public java.util.List + getColumnsOrBuilderList() { + if (columnsBuilder_ != null) { + return columnsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(columns_); + } + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder addColumnsBuilder() { + return getColumnsFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.BinLogInfo.Column.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder addColumnsBuilder( + int index) { + return getColumnsFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.BinLogInfo.Column.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.Column columns = 1; + */ + public java.util.List + getColumnsBuilderList() { + return getColumnsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Column, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder> + getColumnsFieldBuilder() { + if (columnsBuilder_ == null) { + columnsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Column, com.pingcap.kafkareader.proto.BinLogInfo.Column.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnOrBuilder>( + columns_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + columns_ = null; + } + return columnsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.Row) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.Row) + private static final com.pingcap.kafkareader.proto.BinLogInfo.Row DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.Row(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Row getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Row parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Row(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Row getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface TableOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.Table) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string schema_name = 1; + */ + boolean hasSchemaName(); + /** + * optional string schema_name = 1; + */ + java.lang.String getSchemaName(); + /** + * optional string schema_name = 1; + */ + com.google.protobuf.ByteString + getSchemaNameBytes(); + + /** + * optional string table_name = 2; + */ + boolean hasTableName(); + /** + * optional string table_name = 2; + */ + java.lang.String getTableName(); + /** + * optional string table_name = 2; + */ + com.google.protobuf.ByteString + getTableNameBytes(); + + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + java.util.List + getColumnInfoList(); + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getColumnInfo(int index); + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + int getColumnInfoCount(); + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + java.util.List + getColumnInfoOrBuilderList(); + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder getColumnInfoOrBuilder( + int index); + + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + java.util.List + getMutationsList(); + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getMutations(int index); + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + int getMutationsCount(); + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + java.util.List + getMutationsOrBuilderList(); + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder getMutationsOrBuilder( + int index); + } + /** + *
+   *  Table contains mutations in a table.
+   * 
+ * + * Protobuf type {@code com.tnp.search.Table} + */ + public static final class Table extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.Table) + TableOrBuilder { + private static final long serialVersionUID = 0L; + // Use Table.newBuilder() to construct. + private Table(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Table() { + schemaName_ = ""; + tableName_ = ""; + columnInfo_ = java.util.Collections.emptyList(); + mutations_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Table(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Table( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + schemaName_ = bs; + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + tableName_ = bs; + break; + } + case 26: { + if (!((mutable_bitField0_ & 0x00000004) != 0)) { + columnInfo_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000004; + } + columnInfo_.add( + input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.PARSER, extensionRegistry)); + break; + } + case 34: { + if (!((mutable_bitField0_ & 0x00000008) != 0)) { + mutations_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000008; + } + mutations_.add( + input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.PARSER, extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000004) != 0)) { + columnInfo_ = java.util.Collections.unmodifiableList(columnInfo_); + } + if (((mutable_bitField0_ & 0x00000008) != 0)) { + mutations_ = java.util.Collections.unmodifiableList(mutations_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Table_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Table_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Table.class, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder.class); + } + + private int bitField0_; + public static final int SCHEMA_NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object schemaName_; + /** + * optional string schema_name = 1; + */ + public boolean hasSchemaName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string schema_name = 1; + */ + public java.lang.String getSchemaName() { + java.lang.Object ref = schemaName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + schemaName_ = s; + } + return s; + } + } + /** + * optional string schema_name = 1; + */ + public com.google.protobuf.ByteString + getSchemaNameBytes() { + java.lang.Object ref = schemaName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + schemaName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TABLE_NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object tableName_; + /** + * optional string table_name = 2; + */ + public boolean hasTableName() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string table_name = 2; + */ + public java.lang.String getTableName() { + java.lang.Object ref = tableName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + tableName_ = s; + } + return s; + } + } + /** + * optional string table_name = 2; + */ + public com.google.protobuf.ByteString + getTableNameBytes() { + java.lang.Object ref = tableName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tableName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int COLUMN_INFO_FIELD_NUMBER = 3; + private java.util.List columnInfo_; + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public java.util.List getColumnInfoList() { + return columnInfo_; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public java.util.List + getColumnInfoOrBuilderList() { + return columnInfo_; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public int getColumnInfoCount() { + return columnInfo_.size(); + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getColumnInfo(int index) { + return columnInfo_.get(index); + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder getColumnInfoOrBuilder( + int index) { + return columnInfo_.get(index); + } + + public static final int MUTATIONS_FIELD_NUMBER = 4; + private java.util.List mutations_; + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public java.util.List getMutationsList() { + return mutations_; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public java.util.List + getMutationsOrBuilderList() { + return mutations_; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public int getMutationsCount() { + return mutations_.size(); + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getMutations(int index) { + return mutations_.get(index); + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder getMutationsOrBuilder( + int index) { + return mutations_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getMutationsCount(); i++) { + if (!getMutations(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, schemaName_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, tableName_); + } + for (int i = 0; i < columnInfo_.size(); i++) { + output.writeMessage(3, columnInfo_.get(i)); + } + for (int i = 0; i < mutations_.size(); i++) { + output.writeMessage(4, mutations_.get(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, schemaName_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, tableName_); + } + for (int i = 0; i < columnInfo_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, columnInfo_.get(i)); + } + for (int i = 0; i < mutations_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, mutations_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.Table)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.Table other = (com.pingcap.kafkareader.proto.BinLogInfo.Table) obj; + + if (hasSchemaName() != other.hasSchemaName()) return false; + if (hasSchemaName()) { + if (!getSchemaName() + .equals(other.getSchemaName())) return false; + } + if (hasTableName() != other.hasTableName()) return false; + if (hasTableName()) { + if (!getTableName() + .equals(other.getTableName())) return false; + } + if (!getColumnInfoList() + .equals(other.getColumnInfoList())) return false; + if (!getMutationsList() + .equals(other.getMutationsList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasSchemaName()) { + hash = (37 * hash) + SCHEMA_NAME_FIELD_NUMBER; + hash = (53 * hash) + getSchemaName().hashCode(); + } + if (hasTableName()) { + hash = (37 * hash) + TABLE_NAME_FIELD_NUMBER; + hash = (53 * hash) + getTableName().hashCode(); + } + if (getColumnInfoCount() > 0) { + hash = (37 * hash) + COLUMN_INFO_FIELD_NUMBER; + hash = (53 * hash) + getColumnInfoList().hashCode(); + } + if (getMutationsCount() > 0) { + hash = (37 * hash) + MUTATIONS_FIELD_NUMBER; + hash = (53 * hash) + getMutationsList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Table parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.Table prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     *  Table contains mutations in a table.
+     * 
+ * + * Protobuf type {@code com.tnp.search.Table} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.Table) + com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Table_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Table_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Table.class, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.Table.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getColumnInfoFieldBuilder(); + getMutationsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + schemaName_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + tableName_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + if (columnInfoBuilder_ == null) { + columnInfo_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + } else { + columnInfoBuilder_.clear(); + } + if (mutationsBuilder_ == null) { + mutations_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + } else { + mutationsBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Table_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Table getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.Table.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Table build() { + com.pingcap.kafkareader.proto.BinLogInfo.Table result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Table buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.Table result = new com.pingcap.kafkareader.proto.BinLogInfo.Table(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.schemaName_ = schemaName_; + if (((from_bitField0_ & 0x00000002) != 0)) { + to_bitField0_ |= 0x00000002; + } + result.tableName_ = tableName_; + if (columnInfoBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0)) { + columnInfo_ = java.util.Collections.unmodifiableList(columnInfo_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.columnInfo_ = columnInfo_; + } else { + result.columnInfo_ = columnInfoBuilder_.build(); + } + if (mutationsBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0)) { + mutations_ = java.util.Collections.unmodifiableList(mutations_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.mutations_ = mutations_; + } else { + result.mutations_ = mutationsBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.Table) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.Table)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.Table other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.Table.getDefaultInstance()) return this; + if (other.hasSchemaName()) { + bitField0_ |= 0x00000001; + schemaName_ = other.schemaName_; + onChanged(); + } + if (other.hasTableName()) { + bitField0_ |= 0x00000002; + tableName_ = other.tableName_; + onChanged(); + } + if (columnInfoBuilder_ == null) { + if (!other.columnInfo_.isEmpty()) { + if (columnInfo_.isEmpty()) { + columnInfo_ = other.columnInfo_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureColumnInfoIsMutable(); + columnInfo_.addAll(other.columnInfo_); + } + onChanged(); + } + } else { + if (!other.columnInfo_.isEmpty()) { + if (columnInfoBuilder_.isEmpty()) { + columnInfoBuilder_.dispose(); + columnInfoBuilder_ = null; + columnInfo_ = other.columnInfo_; + bitField0_ = (bitField0_ & ~0x00000004); + columnInfoBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getColumnInfoFieldBuilder() : null; + } else { + columnInfoBuilder_.addAllMessages(other.columnInfo_); + } + } + } + if (mutationsBuilder_ == null) { + if (!other.mutations_.isEmpty()) { + if (mutations_.isEmpty()) { + mutations_ = other.mutations_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensureMutationsIsMutable(); + mutations_.addAll(other.mutations_); + } + onChanged(); + } + } else { + if (!other.mutations_.isEmpty()) { + if (mutationsBuilder_.isEmpty()) { + mutationsBuilder_.dispose(); + mutationsBuilder_ = null; + mutations_ = other.mutations_; + bitField0_ = (bitField0_ & ~0x00000008); + mutationsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getMutationsFieldBuilder() : null; + } else { + mutationsBuilder_.addAllMessages(other.mutations_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getMutationsCount(); i++) { + if (!getMutations(i).isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.Table parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.Table) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object schemaName_ = ""; + /** + * optional string schema_name = 1; + */ + public boolean hasSchemaName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string schema_name = 1; + */ + public java.lang.String getSchemaName() { + java.lang.Object ref = schemaName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + schemaName_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string schema_name = 1; + */ + public com.google.protobuf.ByteString + getSchemaNameBytes() { + java.lang.Object ref = schemaName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + schemaName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string schema_name = 1; + */ + public Builder setSchemaName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + schemaName_ = value; + onChanged(); + return this; + } + /** + * optional string schema_name = 1; + */ + public Builder clearSchemaName() { + bitField0_ = (bitField0_ & ~0x00000001); + schemaName_ = getDefaultInstance().getSchemaName(); + onChanged(); + return this; + } + /** + * optional string schema_name = 1; + */ + public Builder setSchemaNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + schemaName_ = value; + onChanged(); + return this; + } + + private java.lang.Object tableName_ = ""; + /** + * optional string table_name = 2; + */ + public boolean hasTableName() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string table_name = 2; + */ + public java.lang.String getTableName() { + java.lang.Object ref = tableName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + tableName_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string table_name = 2; + */ + public com.google.protobuf.ByteString + getTableNameBytes() { + java.lang.Object ref = tableName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tableName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string table_name = 2; + */ + public Builder setTableName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + tableName_ = value; + onChanged(); + return this; + } + /** + * optional string table_name = 2; + */ + public Builder clearTableName() { + bitField0_ = (bitField0_ & ~0x00000002); + tableName_ = getDefaultInstance().getTableName(); + onChanged(); + return this; + } + /** + * optional string table_name = 2; + */ + public Builder setTableNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + tableName_ = value; + onChanged(); + return this; + } + + private java.util.List columnInfo_ = + java.util.Collections.emptyList(); + private void ensureColumnInfoIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + columnInfo_ = new java.util.ArrayList(columnInfo_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder> columnInfoBuilder_; + + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public java.util.List getColumnInfoList() { + if (columnInfoBuilder_ == null) { + return java.util.Collections.unmodifiableList(columnInfo_); + } else { + return columnInfoBuilder_.getMessageList(); + } + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public int getColumnInfoCount() { + if (columnInfoBuilder_ == null) { + return columnInfo_.size(); + } else { + return columnInfoBuilder_.getCount(); + } + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo getColumnInfo(int index) { + if (columnInfoBuilder_ == null) { + return columnInfo_.get(index); + } else { + return columnInfoBuilder_.getMessage(index); + } + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder setColumnInfo( + int index, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo value) { + if (columnInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnInfoIsMutable(); + columnInfo_.set(index, value); + onChanged(); + } else { + columnInfoBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder setColumnInfo( + int index, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder builderForValue) { + if (columnInfoBuilder_ == null) { + ensureColumnInfoIsMutable(); + columnInfo_.set(index, builderForValue.build()); + onChanged(); + } else { + columnInfoBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder addColumnInfo(com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo value) { + if (columnInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnInfoIsMutable(); + columnInfo_.add(value); + onChanged(); + } else { + columnInfoBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder addColumnInfo( + int index, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo value) { + if (columnInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureColumnInfoIsMutable(); + columnInfo_.add(index, value); + onChanged(); + } else { + columnInfoBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder addColumnInfo( + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder builderForValue) { + if (columnInfoBuilder_ == null) { + ensureColumnInfoIsMutable(); + columnInfo_.add(builderForValue.build()); + onChanged(); + } else { + columnInfoBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder addColumnInfo( + int index, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder builderForValue) { + if (columnInfoBuilder_ == null) { + ensureColumnInfoIsMutable(); + columnInfo_.add(index, builderForValue.build()); + onChanged(); + } else { + columnInfoBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder addAllColumnInfo( + java.lang.Iterable values) { + if (columnInfoBuilder_ == null) { + ensureColumnInfoIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, columnInfo_); + onChanged(); + } else { + columnInfoBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder clearColumnInfo() { + if (columnInfoBuilder_ == null) { + columnInfo_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + columnInfoBuilder_.clear(); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public Builder removeColumnInfo(int index) { + if (columnInfoBuilder_ == null) { + ensureColumnInfoIsMutable(); + columnInfo_.remove(index); + onChanged(); + } else { + columnInfoBuilder_.remove(index); + } + return this; + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder getColumnInfoBuilder( + int index) { + return getColumnInfoFieldBuilder().getBuilder(index); + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder getColumnInfoOrBuilder( + int index) { + if (columnInfoBuilder_ == null) { + return columnInfo_.get(index); } else { + return columnInfoBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public java.util.List + getColumnInfoOrBuilderList() { + if (columnInfoBuilder_ != null) { + return columnInfoBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(columnInfo_); + } + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder addColumnInfoBuilder() { + return getColumnInfoFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder addColumnInfoBuilder( + int index) { + return getColumnInfoFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.ColumnInfo column_info = 3; + */ + public java.util.List + getColumnInfoBuilderList() { + return getColumnInfoFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder> + getColumnInfoFieldBuilder() { + if (columnInfoBuilder_ == null) { + columnInfoBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfo.Builder, com.pingcap.kafkareader.proto.BinLogInfo.ColumnInfoOrBuilder>( + columnInfo_, + ((bitField0_ & 0x00000004) != 0), + getParentForChildren(), + isClean()); + columnInfo_ = null; + } + return columnInfoBuilder_; + } + + private java.util.List mutations_ = + java.util.Collections.emptyList(); + private void ensureMutationsIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + mutations_ = new java.util.ArrayList(mutations_); + bitField0_ |= 0x00000008; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder> mutationsBuilder_; + + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public java.util.List getMutationsList() { + if (mutationsBuilder_ == null) { + return java.util.Collections.unmodifiableList(mutations_); + } else { + return mutationsBuilder_.getMessageList(); + } + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public int getMutationsCount() { + if (mutationsBuilder_ == null) { + return mutations_.size(); + } else { + return mutationsBuilder_.getCount(); + } + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getMutations(int index) { + if (mutationsBuilder_ == null) { + return mutations_.get(index); + } else { + return mutationsBuilder_.getMessage(index); + } + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder setMutations( + int index, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation value) { + if (mutationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMutationsIsMutable(); + mutations_.set(index, value); + onChanged(); + } else { + mutationsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder setMutations( + int index, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder builderForValue) { + if (mutationsBuilder_ == null) { + ensureMutationsIsMutable(); + mutations_.set(index, builderForValue.build()); + onChanged(); + } else { + mutationsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder addMutations(com.pingcap.kafkareader.proto.BinLogInfo.TableMutation value) { + if (mutationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMutationsIsMutable(); + mutations_.add(value); + onChanged(); + } else { + mutationsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder addMutations( + int index, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation value) { + if (mutationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMutationsIsMutable(); + mutations_.add(index, value); + onChanged(); + } else { + mutationsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder addMutations( + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder builderForValue) { + if (mutationsBuilder_ == null) { + ensureMutationsIsMutable(); + mutations_.add(builderForValue.build()); + onChanged(); + } else { + mutationsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder addMutations( + int index, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder builderForValue) { + if (mutationsBuilder_ == null) { + ensureMutationsIsMutable(); + mutations_.add(index, builderForValue.build()); + onChanged(); + } else { + mutationsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder addAllMutations( + java.lang.Iterable values) { + if (mutationsBuilder_ == null) { + ensureMutationsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, mutations_); + onChanged(); + } else { + mutationsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder clearMutations() { + if (mutationsBuilder_ == null) { + mutations_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + mutationsBuilder_.clear(); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public Builder removeMutations(int index) { + if (mutationsBuilder_ == null) { + ensureMutationsIsMutable(); + mutations_.remove(index); + onChanged(); + } else { + mutationsBuilder_.remove(index); + } + return this; + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder getMutationsBuilder( + int index) { + return getMutationsFieldBuilder().getBuilder(index); + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder getMutationsOrBuilder( + int index) { + if (mutationsBuilder_ == null) { + return mutations_.get(index); } else { + return mutationsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public java.util.List + getMutationsOrBuilderList() { + if (mutationsBuilder_ != null) { + return mutationsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(mutations_); + } + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder addMutationsBuilder() { + return getMutationsFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder addMutationsBuilder( + int index) { + return getMutationsFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.getDefaultInstance()); + } + /** + * repeated .com.tnp.search.TableMutation mutations = 4; + */ + public java.util.List + getMutationsBuilderList() { + return getMutationsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder> + getMutationsFieldBuilder() { + if (mutationsBuilder_ == null) { + mutationsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder>( + mutations_, + ((bitField0_ & 0x00000008) != 0), + getParentForChildren(), + isClean()); + mutations_ = null; + } + return mutationsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.Table) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.Table) + private static final com.pingcap.kafkareader.proto.BinLogInfo.Table DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.Table(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Table getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser
() { + @java.lang.Override + public Table parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Table(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser
parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser
getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Table getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface TableMutationOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.TableMutation) + com.google.protobuf.MessageOrBuilder { + + /** + * required .com.tnp.search.MutationType type = 1; + */ + boolean hasType(); + /** + * required .com.tnp.search.MutationType type = 1; + */ + com.pingcap.kafkareader.proto.BinLogInfo.MutationType getType(); + + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + boolean hasRow(); + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + com.pingcap.kafkareader.proto.BinLogInfo.Row getRow(); + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getRowOrBuilder(); + + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + boolean hasChangeRow(); + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.Row getChangeRow(); + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getChangeRowOrBuilder(); + } + /** + * Protobuf type {@code com.tnp.search.TableMutation} + */ + public static final class TableMutation extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.TableMutation) + TableMutationOrBuilder { + private static final long serialVersionUID = 0L; + // Use TableMutation.newBuilder() to construct. + private TableMutation(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private TableMutation() { + type_ = 0; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new TableMutation(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private TableMutation( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + int rawValue = input.readEnum(); + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.MutationType value = com.pingcap.kafkareader.proto.BinLogInfo.MutationType.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(1, rawValue); + } else { + bitField0_ |= 0x00000001; + type_ = rawValue; + } + break; + } + case 18: { + com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder subBuilder = null; + if (((bitField0_ & 0x00000002) != 0)) { + subBuilder = row_.toBuilder(); + } + row_ = input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.Row.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(row_); + row_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000002; + break; + } + case 26: { + com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder subBuilder = null; + if (((bitField0_ & 0x00000004) != 0)) { + subBuilder = changeRow_.toBuilder(); + } + changeRow_ = input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.Row.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(changeRow_); + changeRow_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000004; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_TableMutation_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_TableMutation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.class, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder.class); + } + + private int bitField0_; + public static final int TYPE_FIELD_NUMBER = 1; + private int type_; + /** + * required .com.tnp.search.MutationType type = 1; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * required .com.tnp.search.MutationType type = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.MutationType getType() { + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.MutationType result = com.pingcap.kafkareader.proto.BinLogInfo.MutationType.valueOf(type_); + return result == null ? com.pingcap.kafkareader.proto.BinLogInfo.MutationType.Insert : result; + } + + public static final int ROW_FIELD_NUMBER = 2; + private com.pingcap.kafkareader.proto.BinLogInfo.Row row_; + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public boolean hasRow() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row getRow() { + return row_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : row_; + } + /** + *
+     *update之åŽæ–°çš„值
+     * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getRowOrBuilder() { + return row_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : row_; + } + + public static final int CHANGE_ROW_FIELD_NUMBER = 3; + private com.pingcap.kafkareader.proto.BinLogInfo.Row changeRow_; + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public boolean hasChangeRow() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row getChangeRow() { + return changeRow_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : changeRow_; + } + /** + *
+     * for Update MutationType only[update之å‰çš„è€çš„值]
+     * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getChangeRowOrBuilder() { + return changeRow_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : changeRow_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (!hasType()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasRow()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeEnum(1, type_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(2, getRow()); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeMessage(3, getChangeRow()); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, type_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getRow()); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getChangeRow()); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.TableMutation)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation other = (com.pingcap.kafkareader.proto.BinLogInfo.TableMutation) obj; + + if (hasType() != other.hasType()) return false; + if (hasType()) { + if (type_ != other.type_) return false; + } + if (hasRow() != other.hasRow()) return false; + if (hasRow()) { + if (!getRow() + .equals(other.getRow())) return false; + } + if (hasChangeRow() != other.hasChangeRow()) return false; + if (hasChangeRow()) { + if (!getChangeRow() + .equals(other.getChangeRow())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasType()) { + hash = (37 * hash) + TYPE_FIELD_NUMBER; + hash = (53 * hash) + type_; + } + if (hasRow()) { + hash = (37 * hash) + ROW_FIELD_NUMBER; + hash = (53 * hash) + getRow().hashCode(); + } + if (hasChangeRow()) { + hash = (37 * hash) + CHANGE_ROW_FIELD_NUMBER; + hash = (53 * hash) + getChangeRow().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.TableMutation prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code com.tnp.search.TableMutation} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.TableMutation) + com.pingcap.kafkareader.proto.BinLogInfo.TableMutationOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_TableMutation_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_TableMutation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.class, com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getRowFieldBuilder(); + getChangeRowFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + type_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + if (rowBuilder_ == null) { + row_ = null; + } else { + rowBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + if (changeRowBuilder_ == null) { + changeRow_ = null; + } else { + changeRowBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_TableMutation_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation build() { + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation result = new com.pingcap.kafkareader.proto.BinLogInfo.TableMutation(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.type_ = type_; + if (((from_bitField0_ & 0x00000002) != 0)) { + if (rowBuilder_ == null) { + result.row_ = row_; + } else { + result.row_ = rowBuilder_.build(); + } + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + if (changeRowBuilder_ == null) { + result.changeRow_ = changeRow_; + } else { + result.changeRow_ = changeRowBuilder_.build(); + } + to_bitField0_ |= 0x00000004; + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.TableMutation) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.TableMutation)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.TableMutation other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.TableMutation.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasRow()) { + mergeRow(other.getRow()); + } + if (other.hasChangeRow()) { + mergeChangeRow(other.getChangeRow()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + if (!hasType()) { + return false; + } + if (!hasRow()) { + return false; + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.TableMutation parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.TableMutation) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int type_ = 0; + /** + * required .com.tnp.search.MutationType type = 1; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * required .com.tnp.search.MutationType type = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.MutationType getType() { + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.MutationType result = com.pingcap.kafkareader.proto.BinLogInfo.MutationType.valueOf(type_); + return result == null ? com.pingcap.kafkareader.proto.BinLogInfo.MutationType.Insert : result; + } + /** + * required .com.tnp.search.MutationType type = 1; + */ + public Builder setType(com.pingcap.kafkareader.proto.BinLogInfo.MutationType value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + type_ = value.getNumber(); + onChanged(); + return this; + } + /** + * required .com.tnp.search.MutationType type = 1; + */ + public Builder clearType() { + bitField0_ = (bitField0_ & ~0x00000001); + type_ = 0; + onChanged(); + return this; + } + + private com.pingcap.kafkareader.proto.BinLogInfo.Row row_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder> rowBuilder_; + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public boolean hasRow() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row getRow() { + if (rowBuilder_ == null) { + return row_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : row_; + } else { + return rowBuilder_.getMessage(); + } + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public Builder setRow(com.pingcap.kafkareader.proto.BinLogInfo.Row value) { + if (rowBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + row_ = value; + onChanged(); + } else { + rowBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + return this; + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public Builder setRow( + com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder builderForValue) { + if (rowBuilder_ == null) { + row_ = builderForValue.build(); + onChanged(); + } else { + rowBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + return this; + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public Builder mergeRow(com.pingcap.kafkareader.proto.BinLogInfo.Row value) { + if (rowBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + row_ != null && + row_ != com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance()) { + row_ = + com.pingcap.kafkareader.proto.BinLogInfo.Row.newBuilder(row_).mergeFrom(value).buildPartial(); + } else { + row_ = value; + } + onChanged(); + } else { + rowBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000002; + return this; + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public Builder clearRow() { + if (rowBuilder_ == null) { + row_ = null; + onChanged(); + } else { + rowBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder getRowBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return getRowFieldBuilder().getBuilder(); + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getRowOrBuilder() { + if (rowBuilder_ != null) { + return rowBuilder_.getMessageOrBuilder(); + } else { + return row_ == null ? + com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : row_; + } + } + /** + *
+       *update之åŽæ–°çš„值
+       * 
+ * + * required .com.tnp.search.Row row = 2; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder> + getRowFieldBuilder() { + if (rowBuilder_ == null) { + rowBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder>( + getRow(), + getParentForChildren(), + isClean()); + row_ = null; + } + return rowBuilder_; + } + + private com.pingcap.kafkareader.proto.BinLogInfo.Row changeRow_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder> changeRowBuilder_; + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public boolean hasChangeRow() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row getChangeRow() { + if (changeRowBuilder_ == null) { + return changeRow_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : changeRow_; + } else { + return changeRowBuilder_.getMessage(); + } + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public Builder setChangeRow(com.pingcap.kafkareader.proto.BinLogInfo.Row value) { + if (changeRowBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + changeRow_ = value; + onChanged(); + } else { + changeRowBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public Builder setChangeRow( + com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder builderForValue) { + if (changeRowBuilder_ == null) { + changeRow_ = builderForValue.build(); + onChanged(); + } else { + changeRowBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public Builder mergeChangeRow(com.pingcap.kafkareader.proto.BinLogInfo.Row value) { + if (changeRowBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + changeRow_ != null && + changeRow_ != com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance()) { + changeRow_ = + com.pingcap.kafkareader.proto.BinLogInfo.Row.newBuilder(changeRow_).mergeFrom(value).buildPartial(); + } else { + changeRow_ = value; + } + onChanged(); + } else { + changeRowBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public Builder clearChangeRow() { + if (changeRowBuilder_ == null) { + changeRow_ = null; + onChanged(); + } else { + changeRowBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder getChangeRowBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getChangeRowFieldBuilder().getBuilder(); + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder getChangeRowOrBuilder() { + if (changeRowBuilder_ != null) { + return changeRowBuilder_.getMessageOrBuilder(); + } else { + return changeRow_ == null ? + com.pingcap.kafkareader.proto.BinLogInfo.Row.getDefaultInstance() : changeRow_; + } + } + /** + *
+       * for Update MutationType only[update之å‰çš„è€çš„值]
+       * 
+ * + * optional .com.tnp.search.Row change_row = 3; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder> + getChangeRowFieldBuilder() { + if (changeRowBuilder_ == null) { + changeRowBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Row, com.pingcap.kafkareader.proto.BinLogInfo.Row.Builder, com.pingcap.kafkareader.proto.BinLogInfo.RowOrBuilder>( + getChangeRow(), + getParentForChildren(), + isClean()); + changeRow_ = null; + } + return changeRowBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.TableMutation) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.TableMutation) + private static final com.pingcap.kafkareader.proto.BinLogInfo.TableMutation DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.TableMutation(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TableMutation parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new TableMutation(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.TableMutation getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface DMLDataOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.DMLData) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + java.util.List + getTablesList(); + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + com.pingcap.kafkareader.proto.BinLogInfo.Table getTables(int index); + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + int getTablesCount(); + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + java.util.List + getTablesOrBuilderList(); + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder getTablesOrBuilder( + int index); + } + /** + * Protobuf type {@code com.tnp.search.DMLData} + */ + public static final class DMLData extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.DMLData) + DMLDataOrBuilder { + private static final long serialVersionUID = 0L; + // Use DMLData.newBuilder() to construct. + private DMLData(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private DMLData() { + tables_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new DMLData(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DMLData( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + tables_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + tables_.add( + input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.Table.PARSER, extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + tables_ = java.util.Collections.unmodifiableList(tables_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DMLData_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DMLData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.class, com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder.class); + } + + public static final int TABLES_FIELD_NUMBER = 1; + private java.util.List tables_; + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public java.util.List getTablesList() { + return tables_; + } + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public java.util.List + getTablesOrBuilderList() { + return tables_; + } + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public int getTablesCount() { + return tables_.size(); + } + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Table getTables(int index) { + return tables_.get(index); + } + /** + *
+     * tables contains all the table changes.
+     * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder getTablesOrBuilder( + int index) { + return tables_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getTablesCount(); i++) { + if (!getTables(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < tables_.size(); i++) { + output.writeMessage(1, tables_.get(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < tables_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, tables_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.DMLData)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.DMLData other = (com.pingcap.kafkareader.proto.BinLogInfo.DMLData) obj; + + if (!getTablesList() + .equals(other.getTablesList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getTablesCount() > 0) { + hash = (37 * hash) + TABLES_FIELD_NUMBER; + hash = (53 * hash) + getTablesList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.DMLData prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code com.tnp.search.DMLData} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.DMLData) + com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DMLData_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DMLData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.class, com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.DMLData.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getTablesFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + if (tablesBuilder_ == null) { + tables_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + tablesBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DMLData_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData build() { + com.pingcap.kafkareader.proto.BinLogInfo.DMLData result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.DMLData result = new com.pingcap.kafkareader.proto.BinLogInfo.DMLData(this); + int from_bitField0_ = bitField0_; + if (tablesBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + tables_ = java.util.Collections.unmodifiableList(tables_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.tables_ = tables_; + } else { + result.tables_ = tablesBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.DMLData) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.DMLData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.DMLData other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance()) return this; + if (tablesBuilder_ == null) { + if (!other.tables_.isEmpty()) { + if (tables_.isEmpty()) { + tables_ = other.tables_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureTablesIsMutable(); + tables_.addAll(other.tables_); + } + onChanged(); + } + } else { + if (!other.tables_.isEmpty()) { + if (tablesBuilder_.isEmpty()) { + tablesBuilder_.dispose(); + tablesBuilder_ = null; + tables_ = other.tables_; + bitField0_ = (bitField0_ & ~0x00000001); + tablesBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getTablesFieldBuilder() : null; + } else { + tablesBuilder_.addAllMessages(other.tables_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getTablesCount(); i++) { + if (!getTables(i).isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.DMLData parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.DMLData) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List tables_ = + java.util.Collections.emptyList(); + private void ensureTablesIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + tables_ = new java.util.ArrayList(tables_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Table, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder> tablesBuilder_; + + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public java.util.List getTablesList() { + if (tablesBuilder_ == null) { + return java.util.Collections.unmodifiableList(tables_); + } else { + return tablesBuilder_.getMessageList(); + } + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public int getTablesCount() { + if (tablesBuilder_ == null) { + return tables_.size(); + } else { + return tablesBuilder_.getCount(); + } + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Table getTables(int index) { + if (tablesBuilder_ == null) { + return tables_.get(index); + } else { + return tablesBuilder_.getMessage(index); + } + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder setTables( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Table value) { + if (tablesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTablesIsMutable(); + tables_.set(index, value); + onChanged(); + } else { + tablesBuilder_.setMessage(index, value); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder setTables( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder builderForValue) { + if (tablesBuilder_ == null) { + ensureTablesIsMutable(); + tables_.set(index, builderForValue.build()); + onChanged(); + } else { + tablesBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder addTables(com.pingcap.kafkareader.proto.BinLogInfo.Table value) { + if (tablesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTablesIsMutable(); + tables_.add(value); + onChanged(); + } else { + tablesBuilder_.addMessage(value); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder addTables( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Table value) { + if (tablesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTablesIsMutable(); + tables_.add(index, value); + onChanged(); + } else { + tablesBuilder_.addMessage(index, value); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder addTables( + com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder builderForValue) { + if (tablesBuilder_ == null) { + ensureTablesIsMutable(); + tables_.add(builderForValue.build()); + onChanged(); + } else { + tablesBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder addTables( + int index, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder builderForValue) { + if (tablesBuilder_ == null) { + ensureTablesIsMutable(); + tables_.add(index, builderForValue.build()); + onChanged(); + } else { + tablesBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder addAllTables( + java.lang.Iterable values) { + if (tablesBuilder_ == null) { + ensureTablesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, tables_); + onChanged(); + } else { + tablesBuilder_.addAllMessages(values); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder clearTables() { + if (tablesBuilder_ == null) { + tables_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + tablesBuilder_.clear(); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public Builder removeTables(int index) { + if (tablesBuilder_ == null) { + ensureTablesIsMutable(); + tables_.remove(index); + onChanged(); + } else { + tablesBuilder_.remove(index); + } + return this; + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder getTablesBuilder( + int index) { + return getTablesFieldBuilder().getBuilder(index); + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder getTablesOrBuilder( + int index) { + if (tablesBuilder_ == null) { + return tables_.get(index); } else { + return tablesBuilder_.getMessageOrBuilder(index); + } + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public java.util.List + getTablesOrBuilderList() { + if (tablesBuilder_ != null) { + return tablesBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(tables_); + } + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder addTablesBuilder() { + return getTablesFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.BinLogInfo.Table.getDefaultInstance()); + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder addTablesBuilder( + int index) { + return getTablesFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.BinLogInfo.Table.getDefaultInstance()); + } + /** + *
+       * tables contains all the table changes.
+       * 
+ * + * repeated .com.tnp.search.Table tables = 1; + */ + public java.util.List + getTablesBuilderList() { + return getTablesFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Table, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder> + getTablesFieldBuilder() { + if (tablesBuilder_ == null) { + tablesBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.Table, com.pingcap.kafkareader.proto.BinLogInfo.Table.Builder, com.pingcap.kafkareader.proto.BinLogInfo.TableOrBuilder>( + tables_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + tables_ = null; + } + return tablesBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.DMLData) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.DMLData) + private static final com.pingcap.kafkareader.proto.BinLogInfo.DMLData DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.DMLData(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public DMLData parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DMLData(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface DDLDataOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.DDLData) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + boolean hasSchemaName(); + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + java.lang.String getSchemaName(); + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + com.google.protobuf.ByteString + getSchemaNameBytes(); + + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + boolean hasTableName(); + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + java.lang.String getTableName(); + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + com.google.protobuf.ByteString + getTableNameBytes(); + + /** + *
+     * ddl_query is the original ddl statement query.
+     * 
+ * + * optional bytes ddl_query = 3; + */ + boolean hasDdlQuery(); + /** + *
+     * ddl_query is the original ddl statement query.
+     * 
+ * + * optional bytes ddl_query = 3; + */ + com.google.protobuf.ByteString getDdlQuery(); + } + /** + * Protobuf type {@code com.tnp.search.DDLData} + */ + public static final class DDLData extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.DDLData) + DDLDataOrBuilder { + private static final long serialVersionUID = 0L; + // Use DDLData.newBuilder() to construct. + private DDLData(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private DDLData() { + schemaName_ = ""; + tableName_ = ""; + ddlQuery_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new DDLData(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DDLData( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + schemaName_ = bs; + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + tableName_ = bs; + break; + } + case 26: { + bitField0_ |= 0x00000004; + ddlQuery_ = input.readBytes(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DDLData_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DDLData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.class, com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder.class); + } + + private int bitField0_; + public static final int SCHEMA_NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object schemaName_; + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + public boolean hasSchemaName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + public java.lang.String getSchemaName() { + java.lang.Object ref = schemaName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + schemaName_ = s; + } + return s; + } + } + /** + *
+     * the current database use
+     * 
+ * + * optional string schema_name = 1; + */ + public com.google.protobuf.ByteString + getSchemaNameBytes() { + java.lang.Object ref = schemaName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + schemaName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TABLE_NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object tableName_; + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + public boolean hasTableName() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + public java.lang.String getTableName() { + java.lang.Object ref = tableName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + tableName_ = s; + } + return s; + } + } + /** + *
+     * the relate table
+     * 
+ * + * optional string table_name = 2; + */ + public com.google.protobuf.ByteString + getTableNameBytes() { + java.lang.Object ref = tableName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tableName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DDL_QUERY_FIELD_NUMBER = 3; + private com.google.protobuf.ByteString ddlQuery_; + /** + *
+     * ddl_query is the original ddl statement query.
+     * 
+ * + * optional bytes ddl_query = 3; + */ + public boolean hasDdlQuery() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+     * ddl_query is the original ddl statement query.
+     * 
+ * + * optional bytes ddl_query = 3; + */ + public com.google.protobuf.ByteString getDdlQuery() { + return ddlQuery_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, schemaName_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, tableName_); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeBytes(3, ddlQuery_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, schemaName_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, tableName_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(3, ddlQuery_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.DDLData)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.DDLData other = (com.pingcap.kafkareader.proto.BinLogInfo.DDLData) obj; + + if (hasSchemaName() != other.hasSchemaName()) return false; + if (hasSchemaName()) { + if (!getSchemaName() + .equals(other.getSchemaName())) return false; + } + if (hasTableName() != other.hasTableName()) return false; + if (hasTableName()) { + if (!getTableName() + .equals(other.getTableName())) return false; + } + if (hasDdlQuery() != other.hasDdlQuery()) return false; + if (hasDdlQuery()) { + if (!getDdlQuery() + .equals(other.getDdlQuery())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasSchemaName()) { + hash = (37 * hash) + SCHEMA_NAME_FIELD_NUMBER; + hash = (53 * hash) + getSchemaName().hashCode(); + } + if (hasTableName()) { + hash = (37 * hash) + TABLE_NAME_FIELD_NUMBER; + hash = (53 * hash) + getTableName().hashCode(); + } + if (hasDdlQuery()) { + hash = (37 * hash) + DDL_QUERY_FIELD_NUMBER; + hash = (53 * hash) + getDdlQuery().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.DDLData prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code com.tnp.search.DDLData} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.DDLData) + com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DDLData_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DDLData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.class, com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.DDLData.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + schemaName_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + tableName_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + ddlQuery_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_DDLData_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData build() { + com.pingcap.kafkareader.proto.BinLogInfo.DDLData result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.DDLData result = new com.pingcap.kafkareader.proto.BinLogInfo.DDLData(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.schemaName_ = schemaName_; + if (((from_bitField0_ & 0x00000002) != 0)) { + to_bitField0_ |= 0x00000002; + } + result.tableName_ = tableName_; + if (((from_bitField0_ & 0x00000004) != 0)) { + to_bitField0_ |= 0x00000004; + } + result.ddlQuery_ = ddlQuery_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.DDLData) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.DDLData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.DDLData other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance()) return this; + if (other.hasSchemaName()) { + bitField0_ |= 0x00000001; + schemaName_ = other.schemaName_; + onChanged(); + } + if (other.hasTableName()) { + bitField0_ |= 0x00000002; + tableName_ = other.tableName_; + onChanged(); + } + if (other.hasDdlQuery()) { + setDdlQuery(other.getDdlQuery()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.DDLData parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.DDLData) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object schemaName_ = ""; + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public boolean hasSchemaName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public java.lang.String getSchemaName() { + java.lang.Object ref = schemaName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + schemaName_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public com.google.protobuf.ByteString + getSchemaNameBytes() { + java.lang.Object ref = schemaName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + schemaName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public Builder setSchemaName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + schemaName_ = value; + onChanged(); + return this; + } + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public Builder clearSchemaName() { + bitField0_ = (bitField0_ & ~0x00000001); + schemaName_ = getDefaultInstance().getSchemaName(); + onChanged(); + return this; + } + /** + *
+       * the current database use
+       * 
+ * + * optional string schema_name = 1; + */ + public Builder setSchemaNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + schemaName_ = value; + onChanged(); + return this; + } + + private java.lang.Object tableName_ = ""; + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public boolean hasTableName() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public java.lang.String getTableName() { + java.lang.Object ref = tableName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + tableName_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public com.google.protobuf.ByteString + getTableNameBytes() { + java.lang.Object ref = tableName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tableName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public Builder setTableName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + tableName_ = value; + onChanged(); + return this; + } + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public Builder clearTableName() { + bitField0_ = (bitField0_ & ~0x00000002); + tableName_ = getDefaultInstance().getTableName(); + onChanged(); + return this; + } + /** + *
+       * the relate table
+       * 
+ * + * optional string table_name = 2; + */ + public Builder setTableNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + tableName_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.ByteString ddlQuery_ = com.google.protobuf.ByteString.EMPTY; + /** + *
+       * ddl_query is the original ddl statement query.
+       * 
+ * + * optional bytes ddl_query = 3; + */ + public boolean hasDdlQuery() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+       * ddl_query is the original ddl statement query.
+       * 
+ * + * optional bytes ddl_query = 3; + */ + public com.google.protobuf.ByteString getDdlQuery() { + return ddlQuery_; + } + /** + *
+       * ddl_query is the original ddl statement query.
+       * 
+ * + * optional bytes ddl_query = 3; + */ + public Builder setDdlQuery(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + ddlQuery_ = value; + onChanged(); + return this; + } + /** + *
+       * ddl_query is the original ddl statement query.
+       * 
+ * + * optional bytes ddl_query = 3; + */ + public Builder clearDdlQuery() { + bitField0_ = (bitField0_ & ~0x00000004); + ddlQuery_ = getDefaultInstance().getDdlQuery(); + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.DDLData) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.DDLData) + private static final com.pingcap.kafkareader.proto.BinLogInfo.DDLData DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.DDLData(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public DDLData parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DDLData(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface BinlogOrBuilder extends + // @@protoc_insertion_point(interface_extends:com.tnp.search.Binlog) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + boolean hasType(); + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + com.pingcap.kafkareader.proto.BinLogInfo.BinlogType getType(); + + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + boolean hasCommitTs(); + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + long getCommitTs(); + + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + boolean hasDmlData(); + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDmlData(); + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder getDmlDataOrBuilder(); + + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + boolean hasDdlData(); + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDdlData(); + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder getDdlDataOrBuilder(); + } + /** + *
+   * Binlog contains all the changes in a transaction.
+   * 
+ * + * Protobuf type {@code com.tnp.search.Binlog} + */ + public static final class Binlog extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:com.tnp.search.Binlog) + BinlogOrBuilder { + private static final long serialVersionUID = 0L; + // Use Binlog.newBuilder() to construct. + private Binlog(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Binlog() { + type_ = 0; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Binlog(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Binlog( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + int rawValue = input.readEnum(); + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.BinlogType value = com.pingcap.kafkareader.proto.BinLogInfo.BinlogType.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(1, rawValue); + } else { + bitField0_ |= 0x00000001; + type_ = rawValue; + } + break; + } + case 16: { + bitField0_ |= 0x00000002; + commitTs_ = input.readInt64(); + break; + } + case 26: { + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder subBuilder = null; + if (((bitField0_ & 0x00000004) != 0)) { + subBuilder = dmlData_.toBuilder(); + } + dmlData_ = input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.DMLData.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(dmlData_); + dmlData_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000004; + break; + } + case 34: { + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder subBuilder = null; + if (((bitField0_ & 0x00000008) != 0)) { + subBuilder = ddlData_.toBuilder(); + } + ddlData_ = input.readMessage(com.pingcap.kafkareader.proto.BinLogInfo.DDLData.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(ddlData_); + ddlData_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000008; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Binlog_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Binlog_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Binlog.class, com.pingcap.kafkareader.proto.BinLogInfo.Binlog.Builder.class); + } + + private int bitField0_; + public static final int TYPE_FIELD_NUMBER = 1; + private int type_; + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.BinlogType getType() { + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.BinlogType result = com.pingcap.kafkareader.proto.BinLogInfo.BinlogType.valueOf(type_); + return result == null ? com.pingcap.kafkareader.proto.BinLogInfo.BinlogType.DML : result; + } + + public static final int COMMIT_TS_FIELD_NUMBER = 2; + private long commitTs_; + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public boolean hasCommitTs() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public long getCommitTs() { + return commitTs_; + } + + public static final int DML_DATA_FIELD_NUMBER = 3; + private com.pingcap.kafkareader.proto.BinLogInfo.DMLData dmlData_; + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public boolean hasDmlData() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDmlData() { + return dmlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance() : dmlData_; + } + /** + *
+     * dml_data is marshalled from DML type
+     * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder getDmlDataOrBuilder() { + return dmlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance() : dmlData_; + } + + public static final int DDL_DATA_FIELD_NUMBER = 4; + private com.pingcap.kafkareader.proto.BinLogInfo.DDLData ddlData_; + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public boolean hasDdlData() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDdlData() { + return ddlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance() : ddlData_; + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder getDdlDataOrBuilder() { + return ddlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance() : ddlData_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (hasDmlData()) { + if (!getDmlData().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeEnum(1, type_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeInt64(2, commitTs_); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeMessage(3, getDmlData()); + } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeMessage(4, getDdlData()); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, type_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, commitTs_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getDmlData()); + } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getDdlData()); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.BinLogInfo.Binlog)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.BinLogInfo.Binlog other = (com.pingcap.kafkareader.proto.BinLogInfo.Binlog) obj; + + if (hasType() != other.hasType()) return false; + if (hasType()) { + if (type_ != other.type_) return false; + } + if (hasCommitTs() != other.hasCommitTs()) return false; + if (hasCommitTs()) { + if (getCommitTs() + != other.getCommitTs()) return false; + } + if (hasDmlData() != other.hasDmlData()) return false; + if (hasDmlData()) { + if (!getDmlData() + .equals(other.getDmlData())) return false; + } + if (hasDdlData() != other.hasDdlData()) return false; + if (hasDdlData()) { + if (!getDdlData() + .equals(other.getDdlData())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasType()) { + hash = (37 * hash) + TYPE_FIELD_NUMBER; + hash = (53 * hash) + type_; + } + if (hasCommitTs()) { + hash = (37 * hash) + COMMIT_TS_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getCommitTs()); + } + if (hasDmlData()) { + hash = (37 * hash) + DML_DATA_FIELD_NUMBER; + hash = (53 * hash) + getDmlData().hashCode(); + } + if (hasDdlData()) { + hash = (37 * hash) + DDL_DATA_FIELD_NUMBER; + hash = (53 * hash) + getDdlData().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.BinLogInfo.Binlog prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * Binlog contains all the changes in a transaction.
+     * 
+ * + * Protobuf type {@code com.tnp.search.Binlog} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:com.tnp.search.Binlog) + com.pingcap.kafkareader.proto.BinLogInfo.BinlogOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Binlog_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Binlog_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.BinLogInfo.Binlog.class, com.pingcap.kafkareader.proto.BinLogInfo.Binlog.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.BinLogInfo.Binlog.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getDmlDataFieldBuilder(); + getDdlDataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + type_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + commitTs_ = 0L; + bitField0_ = (bitField0_ & ~0x00000002); + if (dmlDataBuilder_ == null) { + dmlData_ = null; + } else { + dmlDataBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + if (ddlDataBuilder_ == null) { + ddlData_ = null; + } else { + ddlDataBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.internal_static_com_tnp_search_Binlog_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Binlog getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.BinLogInfo.Binlog.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Binlog build() { + com.pingcap.kafkareader.proto.BinLogInfo.Binlog result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Binlog buildPartial() { + com.pingcap.kafkareader.proto.BinLogInfo.Binlog result = new com.pingcap.kafkareader.proto.BinLogInfo.Binlog(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.type_ = type_; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.commitTs_ = commitTs_; + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + if (dmlDataBuilder_ == null) { + result.dmlData_ = dmlData_; + } else { + result.dmlData_ = dmlDataBuilder_.build(); + } + to_bitField0_ |= 0x00000004; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + if (ddlDataBuilder_ == null) { + result.ddlData_ = ddlData_; + } else { + result.ddlData_ = ddlDataBuilder_.build(); + } + to_bitField0_ |= 0x00000008; + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.BinLogInfo.Binlog) { + return mergeFrom((com.pingcap.kafkareader.proto.BinLogInfo.Binlog)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.BinLogInfo.Binlog other) { + if (other == com.pingcap.kafkareader.proto.BinLogInfo.Binlog.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasCommitTs()) { + setCommitTs(other.getCommitTs()); + } + if (other.hasDmlData()) { + mergeDmlData(other.getDmlData()); + } + if (other.hasDdlData()) { + mergeDdlData(other.getDdlData()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + if (hasDmlData()) { + if (!getDmlData().isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.BinLogInfo.Binlog parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.BinLogInfo.Binlog) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int type_ = 0; + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.BinlogType getType() { + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.BinLogInfo.BinlogType result = com.pingcap.kafkareader.proto.BinLogInfo.BinlogType.valueOf(type_); + return result == null ? com.pingcap.kafkareader.proto.BinLogInfo.BinlogType.DML : result; + } + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public Builder setType(com.pingcap.kafkareader.proto.BinLogInfo.BinlogType value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + type_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .com.tnp.search.BinlogType type = 1 [(.gogoproto.nullable) = false]; + */ + public Builder clearType() { + bitField0_ = (bitField0_ & ~0x00000001); + type_ = 0; + onChanged(); + return this; + } + + private long commitTs_ ; + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public boolean hasCommitTs() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public long getCommitTs() { + return commitTs_; + } + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public Builder setCommitTs(long value) { + bitField0_ |= 0x00000002; + commitTs_ = value; + onChanged(); + return this; + } + /** + * optional int64 commit_ts = 2 [(.gogoproto.nullable) = false]; + */ + public Builder clearCommitTs() { + bitField0_ = (bitField0_ & ~0x00000002); + commitTs_ = 0L; + onChanged(); + return this; + } + + private com.pingcap.kafkareader.proto.BinLogInfo.DMLData dmlData_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DMLData, com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder> dmlDataBuilder_; + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public boolean hasDmlData() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData getDmlData() { + if (dmlDataBuilder_ == null) { + return dmlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance() : dmlData_; + } else { + return dmlDataBuilder_.getMessage(); + } + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public Builder setDmlData(com.pingcap.kafkareader.proto.BinLogInfo.DMLData value) { + if (dmlDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + dmlData_ = value; + onChanged(); + } else { + dmlDataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public Builder setDmlData( + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder builderForValue) { + if (dmlDataBuilder_ == null) { + dmlData_ = builderForValue.build(); + onChanged(); + } else { + dmlDataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public Builder mergeDmlData(com.pingcap.kafkareader.proto.BinLogInfo.DMLData value) { + if (dmlDataBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + dmlData_ != null && + dmlData_ != com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance()) { + dmlData_ = + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.newBuilder(dmlData_).mergeFrom(value).buildPartial(); + } else { + dmlData_ = value; + } + onChanged(); + } else { + dmlDataBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public Builder clearDmlData() { + if (dmlDataBuilder_ == null) { + dmlData_ = null; + onChanged(); + } else { + dmlDataBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder getDmlDataBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getDmlDataFieldBuilder().getBuilder(); + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder getDmlDataOrBuilder() { + if (dmlDataBuilder_ != null) { + return dmlDataBuilder_.getMessageOrBuilder(); + } else { + return dmlData_ == null ? + com.pingcap.kafkareader.proto.BinLogInfo.DMLData.getDefaultInstance() : dmlData_; + } + } + /** + *
+       * dml_data is marshalled from DML type
+       * 
+ * + * optional .com.tnp.search.DMLData dml_data = 3; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DMLData, com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder> + getDmlDataFieldBuilder() { + if (dmlDataBuilder_ == null) { + dmlDataBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DMLData, com.pingcap.kafkareader.proto.BinLogInfo.DMLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DMLDataOrBuilder>( + getDmlData(), + getParentForChildren(), + isClean()); + dmlData_ = null; + } + return dmlDataBuilder_; + } + + private com.pingcap.kafkareader.proto.BinLogInfo.DDLData ddlData_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DDLData, com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder> ddlDataBuilder_; + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public boolean hasDdlData() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData getDdlData() { + if (ddlDataBuilder_ == null) { + return ddlData_ == null ? com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance() : ddlData_; + } else { + return ddlDataBuilder_.getMessage(); + } + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public Builder setDdlData(com.pingcap.kafkareader.proto.BinLogInfo.DDLData value) { + if (ddlDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ddlData_ = value; + onChanged(); + } else { + ddlDataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public Builder setDdlData( + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder builderForValue) { + if (ddlDataBuilder_ == null) { + ddlData_ = builderForValue.build(); + onChanged(); + } else { + ddlDataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public Builder mergeDdlData(com.pingcap.kafkareader.proto.BinLogInfo.DDLData value) { + if (ddlDataBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0) && + ddlData_ != null && + ddlData_ != com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance()) { + ddlData_ = + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.newBuilder(ddlData_).mergeFrom(value).buildPartial(); + } else { + ddlData_ = value; + } + onChanged(); + } else { + ddlDataBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public Builder clearDdlData() { + if (ddlDataBuilder_ == null) { + ddlData_ = null; + onChanged(); + } else { + ddlDataBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder getDdlDataBuilder() { + bitField0_ |= 0x00000008; + onChanged(); + return getDdlDataFieldBuilder().getBuilder(); + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + public com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder getDdlDataOrBuilder() { + if (ddlDataBuilder_ != null) { + return ddlDataBuilder_.getMessageOrBuilder(); + } else { + return ddlData_ == null ? + com.pingcap.kafkareader.proto.BinLogInfo.DDLData.getDefaultInstance() : ddlData_; + } + } + /** + * optional .com.tnp.search.DDLData ddl_data = 4; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DDLData, com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder> + getDdlDataFieldBuilder() { + if (ddlDataBuilder_ == null) { + ddlDataBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.BinLogInfo.DDLData, com.pingcap.kafkareader.proto.BinLogInfo.DDLData.Builder, com.pingcap.kafkareader.proto.BinLogInfo.DDLDataOrBuilder>( + getDdlData(), + getParentForChildren(), + isClean()); + ddlData_ = null; + } + return ddlDataBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:com.tnp.search.Binlog) + } + + // @@protoc_insertion_point(class_scope:com.tnp.search.Binlog) + private static final com.pingcap.kafkareader.proto.BinLogInfo.Binlog DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.BinLogInfo.Binlog(); + } + + public static com.pingcap.kafkareader.proto.BinLogInfo.Binlog getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Binlog parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Binlog(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.BinLogInfo.Binlog getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_Column_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_Column_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_ColumnInfo_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_ColumnInfo_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_Row_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_Row_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_Table_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_Table_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_TableMutation_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_TableMutation_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_DMLData_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_DMLData_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_DDLData_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_DDLData_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_com_tnp_search_Binlog_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_com_tnp_search_Binlog_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\014binlog.proto\022\016com.tnp.search\032\ngogo.pro" + + "to\"\214\001\n\006Column\022\026\n\007is_null\030\001 \001(\010:\005false\022\023\n" + + "\013int64_value\030\002 \001(\003\022\024\n\014uint64_value\030\003 \001(\004" + + "\022\024\n\014double_value\030\004 \001(\001\022\023\n\013bytes_value\030\005 " + + "\001(\014\022\024\n\014string_value\030\006 \001(\t\"X\n\nColumnInfo\022" + + "\022\n\004name\030\001 \001(\tB\004\310\336\037\000\022\030\n\nmysql_type\030\002 \001(\tB" + + "\004\310\336\037\000\022\034\n\016is_primary_key\030\003 \001(\010B\004\310\336\037\000\".\n\003R" + + "ow\022\'\n\007columns\030\001 \003(\0132\026.com.tnp.search.Col" + + "umn\"\223\001\n\005Table\022\023\n\013schema_name\030\001 \001(\t\022\022\n\nta" + + "ble_name\030\002 \001(\t\022/\n\013column_info\030\003 \003(\0132\032.co" + + "m.tnp.search.ColumnInfo\0220\n\tmutations\030\004 \003" + + "(\0132\035.com.tnp.search.TableMutation\"\206\001\n\rTa" + + "bleMutation\022*\n\004type\030\001 \002(\0162\034.com.tnp.sear" + + "ch.MutationType\022 \n\003row\030\002 \002(\0132\023.com.tnp.s" + + "earch.Row\022\'\n\nchange_row\030\003 \001(\0132\023.com.tnp." + + "search.Row\"0\n\007DMLData\022%\n\006tables\030\001 \003(\0132\025." + + "com.tnp.search.Table\"E\n\007DDLData\022\023\n\013schem" + + "a_name\030\001 \001(\t\022\022\n\ntable_name\030\002 \001(\t\022\021\n\tddl_" + + "query\030\003 \001(\014\"\247\001\n\006Binlog\022.\n\004type\030\001 \001(\0162\032.c" + + "om.tnp.search.BinlogTypeB\004\310\336\037\000\022\027\n\tcommit" + + "_ts\030\002 \001(\003B\004\310\336\037\000\022)\n\010dml_data\030\003 \001(\0132\027.com." + + "tnp.search.DMLData\022)\n\010ddl_data\030\004 \001(\0132\027.c" + + "om.tnp.search.DDLData*2\n\014MutationType\022\n\n" + + "\006Insert\020\000\022\n\n\006Update\020\001\022\n\n\006Delete\020\002*\036\n\nBin" + + "logType\022\007\n\003DML\020\000\022\007\n\003DDL\020\001B7\n\035com.pingcap" + + ".kafkareader.protoB\nBinLogInfo\310\342\036\001\340\342\036\001\320\342" + + "\036\001" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + com.pingcap.kafkareader.proto.GoGoProtos.getDescriptor(), + }); + internal_static_com_tnp_search_Column_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_com_tnp_search_Column_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_Column_descriptor, + new java.lang.String[] { "IsNull", "Int64Value", "Uint64Value", "DoubleValue", "BytesValue", "StringValue", }); + internal_static_com_tnp_search_ColumnInfo_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_com_tnp_search_ColumnInfo_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_ColumnInfo_descriptor, + new java.lang.String[] { "Name", "MysqlType", "IsPrimaryKey", }); + internal_static_com_tnp_search_Row_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_com_tnp_search_Row_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_Row_descriptor, + new java.lang.String[] { "Columns", }); + internal_static_com_tnp_search_Table_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_com_tnp_search_Table_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_Table_descriptor, + new java.lang.String[] { "SchemaName", "TableName", "ColumnInfo", "Mutations", }); + internal_static_com_tnp_search_TableMutation_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_com_tnp_search_TableMutation_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_TableMutation_descriptor, + new java.lang.String[] { "Type", "Row", "ChangeRow", }); + internal_static_com_tnp_search_DMLData_descriptor = + getDescriptor().getMessageTypes().get(5); + internal_static_com_tnp_search_DMLData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_DMLData_descriptor, + new java.lang.String[] { "Tables", }); + internal_static_com_tnp_search_DDLData_descriptor = + getDescriptor().getMessageTypes().get(6); + internal_static_com_tnp_search_DDLData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_DDLData_descriptor, + new java.lang.String[] { "SchemaName", "TableName", "DdlQuery", }); + internal_static_com_tnp_search_Binlog_descriptor = + getDescriptor().getMessageTypes().get(7); + internal_static_com_tnp_search_Binlog_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_com_tnp_search_Binlog_descriptor, + new java.lang.String[] { "Type", "CommitTs", "DmlData", "DdlData", }); + com.google.protobuf.ExtensionRegistry registry = + com.google.protobuf.ExtensionRegistry.newInstance(); + registry.add(com.pingcap.kafkareader.proto.GoGoProtos.marshalerAll); + registry.add(com.pingcap.kafkareader.proto.GoGoProtos.nullable); + registry.add(com.pingcap.kafkareader.proto.GoGoProtos.sizerAll); + registry.add(com.pingcap.kafkareader.proto.GoGoProtos.unmarshalerAll); + com.google.protobuf.Descriptors.FileDescriptor + .internalUpdateFileDescriptor(descriptor, registry); + com.pingcap.kafkareader.proto.GoGoProtos.getDescriptor(); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/DescriptorProtos.java b/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/DescriptorProtos.java new file mode 100644 index 0000000000000..9c458833ec8c6 --- /dev/null +++ b/tidb-binlog/driver/example/kafkaReader/src/main/java/com/pingcap/kafkareader/proto/DescriptorProtos.java @@ -0,0 +1,44029 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: descriptor.proto + +package com.pingcap.kafkareader.proto; + +public final class DescriptorProtos { + private DescriptorProtos() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + public interface FileDescriptorSetOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.FileDescriptorSet) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + java.util.List + getFileList(); + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getFile(int index); + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + int getFileCount(); + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + java.util.List + getFileOrBuilderList(); + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder getFileOrBuilder( + int index); + } + /** + *
+   * The protocol compiler can output a FileDescriptorSet containing the .proto
+   * files it parses.
+   * 
+ * + * Protobuf type {@code google.protobuf.FileDescriptorSet} + */ + public static final class FileDescriptorSet extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.FileDescriptorSet) + FileDescriptorSetOrBuilder { + private static final long serialVersionUID = 0L; + // Use FileDescriptorSet.newBuilder() to construct. + private FileDescriptorSet(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private FileDescriptorSet() { + file_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new FileDescriptorSet(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private FileDescriptorSet( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + file_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + file_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.PARSER, extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + file_ = java.util.Collections.unmodifiableList(file_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.class, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.Builder.class); + } + + public static final int FILE_FIELD_NUMBER = 1; + private java.util.List file_; + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public java.util.List getFileList() { + return file_; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public java.util.List + getFileOrBuilderList() { + return file_; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public int getFileCount() { + return file_.size(); + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getFile(int index) { + return file_.get(index); + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder getFileOrBuilder( + int index) { + return file_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getFileCount(); i++) { + if (!getFile(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < file_.size(); i++) { + output.writeMessage(1, file_.get(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < file_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, file_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet other = (com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet) obj; + + if (!getFileList() + .equals(other.getFileList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getFileCount() > 0) { + hash = (37 * hash) + FILE_FIELD_NUMBER; + hash = (53 * hash) + getFileList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * The protocol compiler can output a FileDescriptorSet containing the .proto
+     * files it parses.
+     * 
+ * + * Protobuf type {@code google.protobuf.FileDescriptorSet} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:google.protobuf.FileDescriptorSet) + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSetOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.class, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getFileFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + if (fileBuilder_ == null) { + file_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + fileBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet build() { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet result = new com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet(this); + int from_bitField0_ = bitField0_; + if (fileBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + file_ = java.util.Collections.unmodifiableList(file_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.file_ = file_; + } else { + result.file_ = fileBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet.getDefaultInstance()) return this; + if (fileBuilder_ == null) { + if (!other.file_.isEmpty()) { + if (file_.isEmpty()) { + file_ = other.file_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureFileIsMutable(); + file_.addAll(other.file_); + } + onChanged(); + } + } else { + if (!other.file_.isEmpty()) { + if (fileBuilder_.isEmpty()) { + fileBuilder_.dispose(); + fileBuilder_ = null; + file_ = other.file_; + bitField0_ = (bitField0_ & ~0x00000001); + fileBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getFileFieldBuilder() : null; + } else { + fileBuilder_.addAllMessages(other.file_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getFileCount(); i++) { + if (!getFile(i).isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List file_ = + java.util.Collections.emptyList(); + private void ensureFileIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + file_ = new java.util.ArrayList(file_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder> fileBuilder_; + + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public java.util.List getFileList() { + if (fileBuilder_ == null) { + return java.util.Collections.unmodifiableList(file_); + } else { + return fileBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public int getFileCount() { + if (fileBuilder_ == null) { + return file_.size(); + } else { + return fileBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getFile(int index) { + if (fileBuilder_ == null) { + return file_.get(index); + } else { + return fileBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder setFile( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto value) { + if (fileBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFileIsMutable(); + file_.set(index, value); + onChanged(); + } else { + fileBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder setFile( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + if (fileBuilder_ == null) { + ensureFileIsMutable(); + file_.set(index, builderForValue.build()); + onChanged(); + } else { + fileBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder addFile(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto value) { + if (fileBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFileIsMutable(); + file_.add(value); + onChanged(); + } else { + fileBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder addFile( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto value) { + if (fileBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFileIsMutable(); + file_.add(index, value); + onChanged(); + } else { + fileBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder addFile( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + if (fileBuilder_ == null) { + ensureFileIsMutable(); + file_.add(builderForValue.build()); + onChanged(); + } else { + fileBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder addFile( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + if (fileBuilder_ == null) { + ensureFileIsMutable(); + file_.add(index, builderForValue.build()); + onChanged(); + } else { + fileBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder addAllFile( + java.lang.Iterable values) { + if (fileBuilder_ == null) { + ensureFileIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, file_); + onChanged(); + } else { + fileBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder clearFile() { + if (fileBuilder_ == null) { + file_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + fileBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public Builder removeFile(int index) { + if (fileBuilder_ == null) { + ensureFileIsMutable(); + file_.remove(index); + onChanged(); + } else { + fileBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder getFileBuilder( + int index) { + return getFileFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder getFileOrBuilder( + int index) { + if (fileBuilder_ == null) { + return file_.get(index); } else { + return fileBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public java.util.List + getFileOrBuilderList() { + if (fileBuilder_ != null) { + return fileBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(file_); + } + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder addFileBuilder() { + return getFileFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder addFileBuilder( + int index) { + return getFileFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FileDescriptorProto file = 1; + */ + public java.util.List + getFileBuilderList() { + return getFileFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder> + getFileFieldBuilder() { + if (fileBuilder_ == null) { + fileBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder>( + file_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + file_ = null; + } + return fileBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.FileDescriptorSet) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public FileDescriptorSet parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new FileDescriptorSet(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorSet getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface FileDescriptorProtoOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.FileDescriptorProto) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + boolean hasName(); + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + java.lang.String getName(); + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + boolean hasPackage(); + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + java.lang.String getPackage(); + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + com.google.protobuf.ByteString + getPackageBytes(); + + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + java.util.List + getDependencyList(); + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + int getDependencyCount(); + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + java.lang.String getDependency(int index); + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + com.google.protobuf.ByteString + getDependencyBytes(int index); + + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + java.util.List getPublicDependencyList(); + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + int getPublicDependencyCount(); + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + int getPublicDependency(int index); + + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + java.util.List getWeakDependencyList(); + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + int getWeakDependencyCount(); + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + int getWeakDependency(int index); + + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + java.util.List + getMessageTypeList(); + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getMessageType(int index); + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + int getMessageTypeCount(); + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + java.util.List + getMessageTypeOrBuilderList(); + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getMessageTypeOrBuilder( + int index); + + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + java.util.List + getEnumTypeList(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + int getEnumTypeCount(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + java.util.List + getEnumTypeOrBuilderList(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index); + + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + java.util.List + getServiceList(); + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto getService(int index); + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + int getServiceCount(); + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + java.util.List + getServiceOrBuilderList(); + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder getServiceOrBuilder( + int index); + + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + java.util.List + getExtensionList(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + int getExtensionCount(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + java.util.List + getExtensionOrBuilderList(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index); + + /** + * optional .google.protobuf.FileOptions options = 8; + */ + boolean hasOptions(); + /** + * optional .google.protobuf.FileOptions options = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions getOptions(); + /** + * optional .google.protobuf.FileOptions options = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder getOptionsOrBuilder(); + + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + boolean hasSourceCodeInfo(); + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo getSourceCodeInfo(); + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder getSourceCodeInfoOrBuilder(); + + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + boolean hasSyntax(); + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + java.lang.String getSyntax(); + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + com.google.protobuf.ByteString + getSyntaxBytes(); + } + /** + *
+   * Describes a complete .proto file.
+   * 
+ * + * Protobuf type {@code google.protobuf.FileDescriptorProto} + */ + public static final class FileDescriptorProto extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.FileDescriptorProto) + FileDescriptorProtoOrBuilder { + private static final long serialVersionUID = 0L; + // Use FileDescriptorProto.newBuilder() to construct. + private FileDescriptorProto(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private FileDescriptorProto() { + name_ = ""; + package_ = ""; + dependency_ = com.google.protobuf.LazyStringArrayList.EMPTY; + publicDependency_ = emptyIntList(); + weakDependency_ = emptyIntList(); + messageType_ = java.util.Collections.emptyList(); + enumType_ = java.util.Collections.emptyList(); + service_ = java.util.Collections.emptyList(); + extension_ = java.util.Collections.emptyList(); + syntax_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new FileDescriptorProto(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private FileDescriptorProto( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + name_ = bs; + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + package_ = bs; + break; + } + case 26: { + com.google.protobuf.ByteString bs = input.readBytes(); + if (!((mutable_bitField0_ & 0x00000004) != 0)) { + dependency_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000004; + } + dependency_.add(bs); + break; + } + case 34: { + if (!((mutable_bitField0_ & 0x00000020) != 0)) { + messageType_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000020; + } + messageType_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.PARSER, extensionRegistry)); + break; + } + case 42: { + if (!((mutable_bitField0_ & 0x00000040) != 0)) { + enumType_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000040; + } + enumType_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 50: { + if (!((mutable_bitField0_ & 0x00000080) != 0)) { + service_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000080; + } + service_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 58: { + if (!((mutable_bitField0_ & 0x00000100) != 0)) { + extension_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000100; + } + extension_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 66: { + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder subBuilder = null; + if (((bitField0_ & 0x00000004) != 0)) { + subBuilder = options_.toBuilder(); + } + options_ = input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(options_); + options_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000004; + break; + } + case 74: { + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder subBuilder = null; + if (((bitField0_ & 0x00000008) != 0)) { + subBuilder = sourceCodeInfo_.toBuilder(); + } + sourceCodeInfo_ = input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(sourceCodeInfo_); + sourceCodeInfo_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000008; + break; + } + case 80: { + if (!((mutable_bitField0_ & 0x00000008) != 0)) { + publicDependency_ = newIntList(); + mutable_bitField0_ |= 0x00000008; + } + publicDependency_.addInt(input.readInt32()); + break; + } + case 82: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000008) != 0) && input.getBytesUntilLimit() > 0) { + publicDependency_ = newIntList(); + mutable_bitField0_ |= 0x00000008; + } + while (input.getBytesUntilLimit() > 0) { + publicDependency_.addInt(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 88: { + if (!((mutable_bitField0_ & 0x00000010) != 0)) { + weakDependency_ = newIntList(); + mutable_bitField0_ |= 0x00000010; + } + weakDependency_.addInt(input.readInt32()); + break; + } + case 90: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000010) != 0) && input.getBytesUntilLimit() > 0) { + weakDependency_ = newIntList(); + mutable_bitField0_ |= 0x00000010; + } + while (input.getBytesUntilLimit() > 0) { + weakDependency_.addInt(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 98: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000010; + syntax_ = bs; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000004) != 0)) { + dependency_ = dependency_.getUnmodifiableView(); + } + if (((mutable_bitField0_ & 0x00000020) != 0)) { + messageType_ = java.util.Collections.unmodifiableList(messageType_); + } + if (((mutable_bitField0_ & 0x00000040) != 0)) { + enumType_ = java.util.Collections.unmodifiableList(enumType_); + } + if (((mutable_bitField0_ & 0x00000080) != 0)) { + service_ = java.util.Collections.unmodifiableList(service_); + } + if (((mutable_bitField0_ & 0x00000100) != 0)) { + extension_ = java.util.Collections.unmodifiableList(extension_); + } + if (((mutable_bitField0_ & 0x00000008) != 0)) { + publicDependency_.makeImmutable(); // C + } + if (((mutable_bitField0_ & 0x00000010) != 0)) { + weakDependency_.makeImmutable(); // C + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.class, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder.class); + } + + private int bitField0_; + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } + } + /** + *
+     * file name, relative to root of source tree
+     * 
+ * + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PACKAGE_FIELD_NUMBER = 2; + private volatile java.lang.Object package_; + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + public boolean hasPackage() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + public java.lang.String getPackage() { + java.lang.Object ref = package_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + package_ = s; + } + return s; + } + } + /** + *
+     * e.g. "foo", "foo.bar", etc.
+     * 
+ * + * optional string package = 2; + */ + public com.google.protobuf.ByteString + getPackageBytes() { + java.lang.Object ref = package_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + package_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DEPENDENCY_FIELD_NUMBER = 3; + private com.google.protobuf.LazyStringList dependency_; + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + public com.google.protobuf.ProtocolStringList + getDependencyList() { + return dependency_; + } + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + public int getDependencyCount() { + return dependency_.size(); + } + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + public java.lang.String getDependency(int index) { + return dependency_.get(index); + } + /** + *
+     * Names of files imported by this file.
+     * 
+ * + * repeated string dependency = 3; + */ + public com.google.protobuf.ByteString + getDependencyBytes(int index) { + return dependency_.getByteString(index); + } + + public static final int PUBLIC_DEPENDENCY_FIELD_NUMBER = 10; + private com.google.protobuf.Internal.IntList publicDependency_; + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + public java.util.List + getPublicDependencyList() { + return publicDependency_; + } + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + public int getPublicDependencyCount() { + return publicDependency_.size(); + } + /** + *
+     * Indexes of the public imported files in the dependency list above.
+     * 
+ * + * repeated int32 public_dependency = 10; + */ + public int getPublicDependency(int index) { + return publicDependency_.getInt(index); + } + + public static final int WEAK_DEPENDENCY_FIELD_NUMBER = 11; + private com.google.protobuf.Internal.IntList weakDependency_; + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + public java.util.List + getWeakDependencyList() { + return weakDependency_; + } + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + public int getWeakDependencyCount() { + return weakDependency_.size(); + } + /** + *
+     * Indexes of the weak imported files in the dependency list.
+     * For Google-internal migration only. Do not use.
+     * 
+ * + * repeated int32 weak_dependency = 11; + */ + public int getWeakDependency(int index) { + return weakDependency_.getInt(index); + } + + public static final int MESSAGE_TYPE_FIELD_NUMBER = 4; + private java.util.List messageType_; + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public java.util.List getMessageTypeList() { + return messageType_; + } + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public java.util.List + getMessageTypeOrBuilderList() { + return messageType_; + } + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public int getMessageTypeCount() { + return messageType_.size(); + } + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getMessageType(int index) { + return messageType_.get(index); + } + /** + *
+     * All top-level definitions in this file.
+     * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getMessageTypeOrBuilder( + int index) { + return messageType_.get(index); + } + + public static final int ENUM_TYPE_FIELD_NUMBER = 5; + private java.util.List enumType_; + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public java.util.List getEnumTypeList() { + return enumType_; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public java.util.List + getEnumTypeOrBuilderList() { + return enumType_; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public int getEnumTypeCount() { + return enumType_.size(); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return enumType_.get(index); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index) { + return enumType_.get(index); + } + + public static final int SERVICE_FIELD_NUMBER = 6; + private java.util.List service_; + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public java.util.List getServiceList() { + return service_; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public java.util.List + getServiceOrBuilderList() { + return service_; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public int getServiceCount() { + return service_.size(); + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto getService(int index) { + return service_.get(index); + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder getServiceOrBuilder( + int index) { + return service_.get(index); + } + + public static final int EXTENSION_FIELD_NUMBER = 7; + private java.util.List extension_; + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public java.util.List getExtensionList() { + return extension_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public java.util.List + getExtensionOrBuilderList() { + return extension_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public int getExtensionCount() { + return extension_.size(); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return extension_.get(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index) { + return extension_.get(index); + } + + public static final int OPTIONS_FIELD_NUMBER = 8; + private com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions options_; + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions getOptions() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.getDefaultInstance() : options_; + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder getOptionsOrBuilder() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.getDefaultInstance() : options_; + } + + public static final int SOURCE_CODE_INFO_FIELD_NUMBER = 9; + private com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo sourceCodeInfo_; + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public boolean hasSourceCodeInfo() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo getSourceCodeInfo() { + return sourceCodeInfo_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.getDefaultInstance() : sourceCodeInfo_; + } + /** + *
+     * This field contains optional information about the original source code.
+     * You may safely remove this entire field without harming runtime
+     * functionality of the descriptors -- the information is needed only by
+     * development tools.
+     * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder getSourceCodeInfoOrBuilder() { + return sourceCodeInfo_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.getDefaultInstance() : sourceCodeInfo_; + } + + public static final int SYNTAX_FIELD_NUMBER = 12; + private volatile java.lang.Object syntax_; + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + public boolean hasSyntax() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + public java.lang.String getSyntax() { + java.lang.Object ref = syntax_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + syntax_ = s; + } + return s; + } + } + /** + *
+     * The syntax of the proto file.
+     * The supported values are "proto2" and "proto3".
+     * 
+ * + * optional string syntax = 12; + */ + public com.google.protobuf.ByteString + getSyntaxBytes() { + java.lang.Object ref = syntax_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + syntax_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getMessageTypeCount(); i++) { + if (!getMessageType(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getEnumTypeCount(); i++) { + if (!getEnumType(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getServiceCount(); i++) { + if (!getService(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getExtensionCount(); i++) { + if (!getExtension(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + if (hasOptions()) { + if (!getOptions().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, package_); + } + for (int i = 0; i < dependency_.size(); i++) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, dependency_.getRaw(i)); + } + for (int i = 0; i < messageType_.size(); i++) { + output.writeMessage(4, messageType_.get(i)); + } + for (int i = 0; i < enumType_.size(); i++) { + output.writeMessage(5, enumType_.get(i)); + } + for (int i = 0; i < service_.size(); i++) { + output.writeMessage(6, service_.get(i)); + } + for (int i = 0; i < extension_.size(); i++) { + output.writeMessage(7, extension_.get(i)); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeMessage(8, getOptions()); + } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeMessage(9, getSourceCodeInfo()); + } + for (int i = 0; i < publicDependency_.size(); i++) { + output.writeInt32(10, publicDependency_.getInt(i)); + } + for (int i = 0; i < weakDependency_.size(); i++) { + output.writeInt32(11, weakDependency_.getInt(i)); + } + if (((bitField0_ & 0x00000010) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 12, syntax_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, package_); + } + { + int dataSize = 0; + for (int i = 0; i < dependency_.size(); i++) { + dataSize += computeStringSizeNoTag(dependency_.getRaw(i)); + } + size += dataSize; + size += 1 * getDependencyList().size(); + } + for (int i = 0; i < messageType_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, messageType_.get(i)); + } + for (int i = 0; i < enumType_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, enumType_.get(i)); + } + for (int i = 0; i < service_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, service_.get(i)); + } + for (int i = 0; i < extension_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, extension_.get(i)); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, getOptions()); + } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, getSourceCodeInfo()); + } + { + int dataSize = 0; + for (int i = 0; i < publicDependency_.size(); i++) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(publicDependency_.getInt(i)); + } + size += dataSize; + size += 1 * getPublicDependencyList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < weakDependency_.size(); i++) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(weakDependency_.getInt(i)); + } + size += dataSize; + size += 1 * getWeakDependencyList().size(); + } + if (((bitField0_ & 0x00000010) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(12, syntax_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto other = (com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto) obj; + + if (hasName() != other.hasName()) return false; + if (hasName()) { + if (!getName() + .equals(other.getName())) return false; + } + if (hasPackage() != other.hasPackage()) return false; + if (hasPackage()) { + if (!getPackage() + .equals(other.getPackage())) return false; + } + if (!getDependencyList() + .equals(other.getDependencyList())) return false; + if (!getPublicDependencyList() + .equals(other.getPublicDependencyList())) return false; + if (!getWeakDependencyList() + .equals(other.getWeakDependencyList())) return false; + if (!getMessageTypeList() + .equals(other.getMessageTypeList())) return false; + if (!getEnumTypeList() + .equals(other.getEnumTypeList())) return false; + if (!getServiceList() + .equals(other.getServiceList())) return false; + if (!getExtensionList() + .equals(other.getExtensionList())) return false; + if (hasOptions() != other.hasOptions()) return false; + if (hasOptions()) { + if (!getOptions() + .equals(other.getOptions())) return false; + } + if (hasSourceCodeInfo() != other.hasSourceCodeInfo()) return false; + if (hasSourceCodeInfo()) { + if (!getSourceCodeInfo() + .equals(other.getSourceCodeInfo())) return false; + } + if (hasSyntax() != other.hasSyntax()) return false; + if (hasSyntax()) { + if (!getSyntax() + .equals(other.getSyntax())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasName()) { + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + } + if (hasPackage()) { + hash = (37 * hash) + PACKAGE_FIELD_NUMBER; + hash = (53 * hash) + getPackage().hashCode(); + } + if (getDependencyCount() > 0) { + hash = (37 * hash) + DEPENDENCY_FIELD_NUMBER; + hash = (53 * hash) + getDependencyList().hashCode(); + } + if (getPublicDependencyCount() > 0) { + hash = (37 * hash) + PUBLIC_DEPENDENCY_FIELD_NUMBER; + hash = (53 * hash) + getPublicDependencyList().hashCode(); + } + if (getWeakDependencyCount() > 0) { + hash = (37 * hash) + WEAK_DEPENDENCY_FIELD_NUMBER; + hash = (53 * hash) + getWeakDependencyList().hashCode(); + } + if (getMessageTypeCount() > 0) { + hash = (37 * hash) + MESSAGE_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getMessageTypeList().hashCode(); + } + if (getEnumTypeCount() > 0) { + hash = (37 * hash) + ENUM_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getEnumTypeList().hashCode(); + } + if (getServiceCount() > 0) { + hash = (37 * hash) + SERVICE_FIELD_NUMBER; + hash = (53 * hash) + getServiceList().hashCode(); + } + if (getExtensionCount() > 0) { + hash = (37 * hash) + EXTENSION_FIELD_NUMBER; + hash = (53 * hash) + getExtensionList().hashCode(); + } + if (hasOptions()) { + hash = (37 * hash) + OPTIONS_FIELD_NUMBER; + hash = (53 * hash) + getOptions().hashCode(); + } + if (hasSourceCodeInfo()) { + hash = (37 * hash) + SOURCE_CODE_INFO_FIELD_NUMBER; + hash = (53 * hash) + getSourceCodeInfo().hashCode(); + } + if (hasSyntax()) { + hash = (37 * hash) + SYNTAX_FIELD_NUMBER; + hash = (53 * hash) + getSyntax().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * Describes a complete .proto file.
+     * 
+ * + * Protobuf type {@code google.protobuf.FileDescriptorProto} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:google.protobuf.FileDescriptorProto) + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProtoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.class, com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getMessageTypeFieldBuilder(); + getEnumTypeFieldBuilder(); + getServiceFieldBuilder(); + getExtensionFieldBuilder(); + getOptionsFieldBuilder(); + getSourceCodeInfoFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + name_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + package_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + dependency_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + publicDependency_ = emptyIntList(); + bitField0_ = (bitField0_ & ~0x00000008); + weakDependency_ = emptyIntList(); + bitField0_ = (bitField0_ & ~0x00000010); + if (messageTypeBuilder_ == null) { + messageType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + } else { + messageTypeBuilder_.clear(); + } + if (enumTypeBuilder_ == null) { + enumType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040); + } else { + enumTypeBuilder_.clear(); + } + if (serviceBuilder_ == null) { + service_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000080); + } else { + serviceBuilder_.clear(); + } + if (extensionBuilder_ == null) { + extension_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); + } else { + extensionBuilder_.clear(); + } + if (optionsBuilder_ == null) { + options_ = null; + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000200); + if (sourceCodeInfoBuilder_ == null) { + sourceCodeInfo_ = null; + } else { + sourceCodeInfoBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000400); + syntax_ = ""; + bitField0_ = (bitField0_ & ~0x00000800); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto build() { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto result = new com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.name_ = name_; + if (((from_bitField0_ & 0x00000002) != 0)) { + to_bitField0_ |= 0x00000002; + } + result.package_ = package_; + if (((bitField0_ & 0x00000004) != 0)) { + dependency_ = dependency_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.dependency_ = dependency_; + if (((bitField0_ & 0x00000008) != 0)) { + publicDependency_.makeImmutable(); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.publicDependency_ = publicDependency_; + if (((bitField0_ & 0x00000010) != 0)) { + weakDependency_.makeImmutable(); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.weakDependency_ = weakDependency_; + if (messageTypeBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0)) { + messageType_ = java.util.Collections.unmodifiableList(messageType_); + bitField0_ = (bitField0_ & ~0x00000020); + } + result.messageType_ = messageType_; + } else { + result.messageType_ = messageTypeBuilder_.build(); + } + if (enumTypeBuilder_ == null) { + if (((bitField0_ & 0x00000040) != 0)) { + enumType_ = java.util.Collections.unmodifiableList(enumType_); + bitField0_ = (bitField0_ & ~0x00000040); + } + result.enumType_ = enumType_; + } else { + result.enumType_ = enumTypeBuilder_.build(); + } + if (serviceBuilder_ == null) { + if (((bitField0_ & 0x00000080) != 0)) { + service_ = java.util.Collections.unmodifiableList(service_); + bitField0_ = (bitField0_ & ~0x00000080); + } + result.service_ = service_; + } else { + result.service_ = serviceBuilder_.build(); + } + if (extensionBuilder_ == null) { + if (((bitField0_ & 0x00000100) != 0)) { + extension_ = java.util.Collections.unmodifiableList(extension_); + bitField0_ = (bitField0_ & ~0x00000100); + } + result.extension_ = extension_; + } else { + result.extension_ = extensionBuilder_.build(); + } + if (((from_bitField0_ & 0x00000200) != 0)) { + if (optionsBuilder_ == null) { + result.options_ = options_; + } else { + result.options_ = optionsBuilder_.build(); + } + to_bitField0_ |= 0x00000004; + } + if (((from_bitField0_ & 0x00000400) != 0)) { + if (sourceCodeInfoBuilder_ == null) { + result.sourceCodeInfo_ = sourceCodeInfo_; + } else { + result.sourceCodeInfo_ = sourceCodeInfoBuilder_.build(); + } + to_bitField0_ |= 0x00000008; + } + if (((from_bitField0_ & 0x00000800) != 0)) { + to_bitField0_ |= 0x00000010; + } + result.syntax_ = syntax_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto.getDefaultInstance()) return this; + if (other.hasName()) { + bitField0_ |= 0x00000001; + name_ = other.name_; + onChanged(); + } + if (other.hasPackage()) { + bitField0_ |= 0x00000002; + package_ = other.package_; + onChanged(); + } + if (!other.dependency_.isEmpty()) { + if (dependency_.isEmpty()) { + dependency_ = other.dependency_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureDependencyIsMutable(); + dependency_.addAll(other.dependency_); + } + onChanged(); + } + if (!other.publicDependency_.isEmpty()) { + if (publicDependency_.isEmpty()) { + publicDependency_ = other.publicDependency_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensurePublicDependencyIsMutable(); + publicDependency_.addAll(other.publicDependency_); + } + onChanged(); + } + if (!other.weakDependency_.isEmpty()) { + if (weakDependency_.isEmpty()) { + weakDependency_ = other.weakDependency_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureWeakDependencyIsMutable(); + weakDependency_.addAll(other.weakDependency_); + } + onChanged(); + } + if (messageTypeBuilder_ == null) { + if (!other.messageType_.isEmpty()) { + if (messageType_.isEmpty()) { + messageType_ = other.messageType_; + bitField0_ = (bitField0_ & ~0x00000020); + } else { + ensureMessageTypeIsMutable(); + messageType_.addAll(other.messageType_); + } + onChanged(); + } + } else { + if (!other.messageType_.isEmpty()) { + if (messageTypeBuilder_.isEmpty()) { + messageTypeBuilder_.dispose(); + messageTypeBuilder_ = null; + messageType_ = other.messageType_; + bitField0_ = (bitField0_ & ~0x00000020); + messageTypeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getMessageTypeFieldBuilder() : null; + } else { + messageTypeBuilder_.addAllMessages(other.messageType_); + } + } + } + if (enumTypeBuilder_ == null) { + if (!other.enumType_.isEmpty()) { + if (enumType_.isEmpty()) { + enumType_ = other.enumType_; + bitField0_ = (bitField0_ & ~0x00000040); + } else { + ensureEnumTypeIsMutable(); + enumType_.addAll(other.enumType_); + } + onChanged(); + } + } else { + if (!other.enumType_.isEmpty()) { + if (enumTypeBuilder_.isEmpty()) { + enumTypeBuilder_.dispose(); + enumTypeBuilder_ = null; + enumType_ = other.enumType_; + bitField0_ = (bitField0_ & ~0x00000040); + enumTypeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getEnumTypeFieldBuilder() : null; + } else { + enumTypeBuilder_.addAllMessages(other.enumType_); + } + } + } + if (serviceBuilder_ == null) { + if (!other.service_.isEmpty()) { + if (service_.isEmpty()) { + service_ = other.service_; + bitField0_ = (bitField0_ & ~0x00000080); + } else { + ensureServiceIsMutable(); + service_.addAll(other.service_); + } + onChanged(); + } + } else { + if (!other.service_.isEmpty()) { + if (serviceBuilder_.isEmpty()) { + serviceBuilder_.dispose(); + serviceBuilder_ = null; + service_ = other.service_; + bitField0_ = (bitField0_ & ~0x00000080); + serviceBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getServiceFieldBuilder() : null; + } else { + serviceBuilder_.addAllMessages(other.service_); + } + } + } + if (extensionBuilder_ == null) { + if (!other.extension_.isEmpty()) { + if (extension_.isEmpty()) { + extension_ = other.extension_; + bitField0_ = (bitField0_ & ~0x00000100); + } else { + ensureExtensionIsMutable(); + extension_.addAll(other.extension_); + } + onChanged(); + } + } else { + if (!other.extension_.isEmpty()) { + if (extensionBuilder_.isEmpty()) { + extensionBuilder_.dispose(); + extensionBuilder_ = null; + extension_ = other.extension_; + bitField0_ = (bitField0_ & ~0x00000100); + extensionBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getExtensionFieldBuilder() : null; + } else { + extensionBuilder_.addAllMessages(other.extension_); + } + } + } + if (other.hasOptions()) { + mergeOptions(other.getOptions()); + } + if (other.hasSourceCodeInfo()) { + mergeSourceCodeInfo(other.getSourceCodeInfo()); + } + if (other.hasSyntax()) { + bitField0_ |= 0x00000800; + syntax_ = other.syntax_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getMessageTypeCount(); i++) { + if (!getMessageType(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getEnumTypeCount(); i++) { + if (!getEnumType(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getServiceCount(); i++) { + if (!getService(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getExtensionCount(); i++) { + if (!getExtension(i).isInitialized()) { + return false; + } + } + if (hasOptions()) { + if (!getOptions().isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public Builder clearName() { + bitField0_ = (bitField0_ & ~0x00000001); + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + *
+       * file name, relative to root of source tree
+       * 
+ * + * optional string name = 1; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + + private java.lang.Object package_ = ""; + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public boolean hasPackage() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public java.lang.String getPackage() { + java.lang.Object ref = package_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + package_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public com.google.protobuf.ByteString + getPackageBytes() { + java.lang.Object ref = package_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + package_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public Builder setPackage( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + package_ = value; + onChanged(); + return this; + } + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public Builder clearPackage() { + bitField0_ = (bitField0_ & ~0x00000002); + package_ = getDefaultInstance().getPackage(); + onChanged(); + return this; + } + /** + *
+       * e.g. "foo", "foo.bar", etc.
+       * 
+ * + * optional string package = 2; + */ + public Builder setPackageBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + package_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringList dependency_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensureDependencyIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + dependency_ = new com.google.protobuf.LazyStringArrayList(dependency_); + bitField0_ |= 0x00000004; + } + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public com.google.protobuf.ProtocolStringList + getDependencyList() { + return dependency_.getUnmodifiableView(); + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public int getDependencyCount() { + return dependency_.size(); + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public java.lang.String getDependency(int index) { + return dependency_.get(index); + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public com.google.protobuf.ByteString + getDependencyBytes(int index) { + return dependency_.getByteString(index); + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public Builder setDependency( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureDependencyIsMutable(); + dependency_.set(index, value); + onChanged(); + return this; + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public Builder addDependency( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureDependencyIsMutable(); + dependency_.add(value); + onChanged(); + return this; + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public Builder addAllDependency( + java.lang.Iterable values) { + ensureDependencyIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, dependency_); + onChanged(); + return this; + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public Builder clearDependency() { + dependency_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
+       * Names of files imported by this file.
+       * 
+ * + * repeated string dependency = 3; + */ + public Builder addDependencyBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + ensureDependencyIsMutable(); + dependency_.add(value); + onChanged(); + return this; + } + + private com.google.protobuf.Internal.IntList publicDependency_ = emptyIntList(); + private void ensurePublicDependencyIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + publicDependency_ = mutableCopy(publicDependency_); + bitField0_ |= 0x00000008; + } + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public java.util.List + getPublicDependencyList() { + return ((bitField0_ & 0x00000008) != 0) ? + java.util.Collections.unmodifiableList(publicDependency_) : publicDependency_; + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public int getPublicDependencyCount() { + return publicDependency_.size(); + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public int getPublicDependency(int index) { + return publicDependency_.getInt(index); + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public Builder setPublicDependency( + int index, int value) { + ensurePublicDependencyIsMutable(); + publicDependency_.setInt(index, value); + onChanged(); + return this; + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public Builder addPublicDependency(int value) { + ensurePublicDependencyIsMutable(); + publicDependency_.addInt(value); + onChanged(); + return this; + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public Builder addAllPublicDependency( + java.lang.Iterable values) { + ensurePublicDependencyIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, publicDependency_); + onChanged(); + return this; + } + /** + *
+       * Indexes of the public imported files in the dependency list above.
+       * 
+ * + * repeated int32 public_dependency = 10; + */ + public Builder clearPublicDependency() { + publicDependency_ = emptyIntList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + + private com.google.protobuf.Internal.IntList weakDependency_ = emptyIntList(); + private void ensureWeakDependencyIsMutable() { + if (!((bitField0_ & 0x00000010) != 0)) { + weakDependency_ = mutableCopy(weakDependency_); + bitField0_ |= 0x00000010; + } + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public java.util.List + getWeakDependencyList() { + return ((bitField0_ & 0x00000010) != 0) ? + java.util.Collections.unmodifiableList(weakDependency_) : weakDependency_; + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public int getWeakDependencyCount() { + return weakDependency_.size(); + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public int getWeakDependency(int index) { + return weakDependency_.getInt(index); + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public Builder setWeakDependency( + int index, int value) { + ensureWeakDependencyIsMutable(); + weakDependency_.setInt(index, value); + onChanged(); + return this; + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public Builder addWeakDependency(int value) { + ensureWeakDependencyIsMutable(); + weakDependency_.addInt(value); + onChanged(); + return this; + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public Builder addAllWeakDependency( + java.lang.Iterable values) { + ensureWeakDependencyIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, weakDependency_); + onChanged(); + return this; + } + /** + *
+       * Indexes of the weak imported files in the dependency list.
+       * For Google-internal migration only. Do not use.
+       * 
+ * + * repeated int32 weak_dependency = 11; + */ + public Builder clearWeakDependency() { + weakDependency_ = emptyIntList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + + private java.util.List messageType_ = + java.util.Collections.emptyList(); + private void ensureMessageTypeIsMutable() { + if (!((bitField0_ & 0x00000020) != 0)) { + messageType_ = new java.util.ArrayList(messageType_); + bitField0_ |= 0x00000020; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder> messageTypeBuilder_; + + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public java.util.List getMessageTypeList() { + if (messageTypeBuilder_ == null) { + return java.util.Collections.unmodifiableList(messageType_); + } else { + return messageTypeBuilder_.getMessageList(); + } + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public int getMessageTypeCount() { + if (messageTypeBuilder_ == null) { + return messageType_.size(); + } else { + return messageTypeBuilder_.getCount(); + } + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getMessageType(int index) { + if (messageTypeBuilder_ == null) { + return messageType_.get(index); + } else { + return messageTypeBuilder_.getMessage(index); + } + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder setMessageType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (messageTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageTypeIsMutable(); + messageType_.set(index, value); + onChanged(); + } else { + messageTypeBuilder_.setMessage(index, value); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder setMessageType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (messageTypeBuilder_ == null) { + ensureMessageTypeIsMutable(); + messageType_.set(index, builderForValue.build()); + onChanged(); + } else { + messageTypeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder addMessageType(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (messageTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageTypeIsMutable(); + messageType_.add(value); + onChanged(); + } else { + messageTypeBuilder_.addMessage(value); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder addMessageType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (messageTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageTypeIsMutable(); + messageType_.add(index, value); + onChanged(); + } else { + messageTypeBuilder_.addMessage(index, value); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder addMessageType( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (messageTypeBuilder_ == null) { + ensureMessageTypeIsMutable(); + messageType_.add(builderForValue.build()); + onChanged(); + } else { + messageTypeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder addMessageType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (messageTypeBuilder_ == null) { + ensureMessageTypeIsMutable(); + messageType_.add(index, builderForValue.build()); + onChanged(); + } else { + messageTypeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder addAllMessageType( + java.lang.Iterable values) { + if (messageTypeBuilder_ == null) { + ensureMessageTypeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, messageType_); + onChanged(); + } else { + messageTypeBuilder_.addAllMessages(values); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder clearMessageType() { + if (messageTypeBuilder_ == null) { + messageType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + onChanged(); + } else { + messageTypeBuilder_.clear(); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public Builder removeMessageType(int index) { + if (messageTypeBuilder_ == null) { + ensureMessageTypeIsMutable(); + messageType_.remove(index); + onChanged(); + } else { + messageTypeBuilder_.remove(index); + } + return this; + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder getMessageTypeBuilder( + int index) { + return getMessageTypeFieldBuilder().getBuilder(index); + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getMessageTypeOrBuilder( + int index) { + if (messageTypeBuilder_ == null) { + return messageType_.get(index); } else { + return messageTypeBuilder_.getMessageOrBuilder(index); + } + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public java.util.List + getMessageTypeOrBuilderList() { + if (messageTypeBuilder_ != null) { + return messageTypeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(messageType_); + } + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder addMessageTypeBuilder() { + return getMessageTypeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance()); + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder addMessageTypeBuilder( + int index) { + return getMessageTypeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance()); + } + /** + *
+       * All top-level definitions in this file.
+       * 
+ * + * repeated .google.protobuf.DescriptorProto message_type = 4; + */ + public java.util.List + getMessageTypeBuilderList() { + return getMessageTypeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder> + getMessageTypeFieldBuilder() { + if (messageTypeBuilder_ == null) { + messageTypeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder>( + messageType_, + ((bitField0_ & 0x00000020) != 0), + getParentForChildren(), + isClean()); + messageType_ = null; + } + return messageTypeBuilder_; + } + + private java.util.List enumType_ = + java.util.Collections.emptyList(); + private void ensureEnumTypeIsMutable() { + if (!((bitField0_ & 0x00000040) != 0)) { + enumType_ = new java.util.ArrayList(enumType_); + bitField0_ |= 0x00000040; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder> enumTypeBuilder_; + + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public java.util.List getEnumTypeList() { + if (enumTypeBuilder_ == null) { + return java.util.Collections.unmodifiableList(enumType_); + } else { + return enumTypeBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public int getEnumTypeCount() { + if (enumTypeBuilder_ == null) { + return enumType_.size(); + } else { + return enumTypeBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + if (enumTypeBuilder_ == null) { + return enumType_.get(index); + } else { + return enumTypeBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder setEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.set(index, value); + onChanged(); + } else { + enumTypeBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder setEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.set(index, builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder addEnumType(com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.add(value); + onChanged(); + } else { + enumTypeBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder addEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.add(index, value); + onChanged(); + } else { + enumTypeBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder addEnumType( + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.add(builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder addEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.add(index, builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder addAllEnumType( + java.lang.Iterable values) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, enumType_); + onChanged(); + } else { + enumTypeBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder clearEnumType() { + if (enumTypeBuilder_ == null) { + enumType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040); + onChanged(); + } else { + enumTypeBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public Builder removeEnumType(int index) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.remove(index); + onChanged(); + } else { + enumTypeBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder getEnumTypeBuilder( + int index) { + return getEnumTypeFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index) { + if (enumTypeBuilder_ == null) { + return enumType_.get(index); } else { + return enumTypeBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public java.util.List + getEnumTypeOrBuilderList() { + if (enumTypeBuilder_ != null) { + return enumTypeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(enumType_); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder addEnumTypeBuilder() { + return getEnumTypeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder addEnumTypeBuilder( + int index) { + return getEnumTypeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + */ + public java.util.List + getEnumTypeBuilderList() { + return getEnumTypeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder> + getEnumTypeFieldBuilder() { + if (enumTypeBuilder_ == null) { + enumTypeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder>( + enumType_, + ((bitField0_ & 0x00000040) != 0), + getParentForChildren(), + isClean()); + enumType_ = null; + } + return enumTypeBuilder_; + } + + private java.util.List service_ = + java.util.Collections.emptyList(); + private void ensureServiceIsMutable() { + if (!((bitField0_ & 0x00000080) != 0)) { + service_ = new java.util.ArrayList(service_); + bitField0_ |= 0x00000080; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder> serviceBuilder_; + + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public java.util.List getServiceList() { + if (serviceBuilder_ == null) { + return java.util.Collections.unmodifiableList(service_); + } else { + return serviceBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public int getServiceCount() { + if (serviceBuilder_ == null) { + return service_.size(); + } else { + return serviceBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto getService(int index) { + if (serviceBuilder_ == null) { + return service_.get(index); + } else { + return serviceBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder setService( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto value) { + if (serviceBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureServiceIsMutable(); + service_.set(index, value); + onChanged(); + } else { + serviceBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder setService( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + if (serviceBuilder_ == null) { + ensureServiceIsMutable(); + service_.set(index, builderForValue.build()); + onChanged(); + } else { + serviceBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder addService(com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto value) { + if (serviceBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureServiceIsMutable(); + service_.add(value); + onChanged(); + } else { + serviceBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder addService( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto value) { + if (serviceBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureServiceIsMutable(); + service_.add(index, value); + onChanged(); + } else { + serviceBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder addService( + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + if (serviceBuilder_ == null) { + ensureServiceIsMutable(); + service_.add(builderForValue.build()); + onChanged(); + } else { + serviceBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder addService( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + if (serviceBuilder_ == null) { + ensureServiceIsMutable(); + service_.add(index, builderForValue.build()); + onChanged(); + } else { + serviceBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder addAllService( + java.lang.Iterable values) { + if (serviceBuilder_ == null) { + ensureServiceIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, service_); + onChanged(); + } else { + serviceBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder clearService() { + if (serviceBuilder_ == null) { + service_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000080); + onChanged(); + } else { + serviceBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public Builder removeService(int index) { + if (serviceBuilder_ == null) { + ensureServiceIsMutable(); + service_.remove(index); + onChanged(); + } else { + serviceBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder getServiceBuilder( + int index) { + return getServiceFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder getServiceOrBuilder( + int index) { + if (serviceBuilder_ == null) { + return service_.get(index); } else { + return serviceBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public java.util.List + getServiceOrBuilderList() { + if (serviceBuilder_ != null) { + return serviceBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(service_); + } + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder addServiceBuilder() { + return getServiceFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder addServiceBuilder( + int index) { + return getServiceFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.ServiceDescriptorProto service = 6; + */ + public java.util.List + getServiceBuilderList() { + return getServiceFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder> + getServiceFieldBuilder() { + if (serviceBuilder_ == null) { + serviceBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ServiceDescriptorProtoOrBuilder>( + service_, + ((bitField0_ & 0x00000080) != 0), + getParentForChildren(), + isClean()); + service_ = null; + } + return serviceBuilder_; + } + + private java.util.List extension_ = + java.util.Collections.emptyList(); + private void ensureExtensionIsMutable() { + if (!((bitField0_ & 0x00000100) != 0)) { + extension_ = new java.util.ArrayList(extension_); + bitField0_ |= 0x00000100; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> extensionBuilder_; + + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public java.util.List getExtensionList() { + if (extensionBuilder_ == null) { + return java.util.Collections.unmodifiableList(extension_); + } else { + return extensionBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public int getExtensionCount() { + if (extensionBuilder_ == null) { + return extension_.size(); + } else { + return extensionBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + if (extensionBuilder_ == null) { + return extension_.get(index); + } else { + return extensionBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder setExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.set(index, value); + onChanged(); + } else { + extensionBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder setExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.set(index, builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder addExtension(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.add(value); + onChanged(); + } else { + extensionBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder addExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.add(index, value); + onChanged(); + } else { + extensionBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder addExtension( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.add(builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder addExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.add(index, builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder addAllExtension( + java.lang.Iterable values) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extension_); + onChanged(); + } else { + extensionBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder clearExtension() { + if (extensionBuilder_ == null) { + extension_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); + onChanged(); + } else { + extensionBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public Builder removeExtension(int index) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.remove(index); + onChanged(); + } else { + extensionBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder getExtensionBuilder( + int index) { + return getExtensionFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index) { + if (extensionBuilder_ == null) { + return extension_.get(index); } else { + return extensionBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public java.util.List + getExtensionOrBuilderList() { + if (extensionBuilder_ != null) { + return extensionBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(extension_); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addExtensionBuilder() { + return getExtensionFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addExtensionBuilder( + int index) { + return getExtensionFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 7; + */ + public java.util.List + getExtensionBuilderList() { + return getExtensionFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> + getExtensionFieldBuilder() { + if (extensionBuilder_ == null) { + extensionBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder>( + extension_, + ((bitField0_ & 0x00000100) != 0), + getParentForChildren(), + isClean()); + extension_ = null; + } + return extensionBuilder_; + } + + private com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions options_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder> optionsBuilder_; + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000200) != 0); + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions getOptions() { + if (optionsBuilder_ == null) { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.getDefaultInstance() : options_; + } else { + return optionsBuilder_.getMessage(); + } + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public Builder setOptions(com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions value) { + if (optionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + options_ = value; + onChanged(); + } else { + optionsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000200; + return this; + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public Builder setOptions( + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder builderForValue) { + if (optionsBuilder_ == null) { + options_ = builderForValue.build(); + onChanged(); + } else { + optionsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000200; + return this; + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public Builder mergeOptions(com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions value) { + if (optionsBuilder_ == null) { + if (((bitField0_ & 0x00000200) != 0) && + options_ != null && + options_ != com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.getDefaultInstance()) { + options_ = + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.newBuilder(options_).mergeFrom(value).buildPartial(); + } else { + options_ = value; + } + onChanged(); + } else { + optionsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000200; + return this; + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public Builder clearOptions() { + if (optionsBuilder_ == null) { + options_ = null; + onChanged(); + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000200); + return this; + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder getOptionsBuilder() { + bitField0_ |= 0x00000200; + onChanged(); + return getOptionsFieldBuilder().getBuilder(); + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder getOptionsOrBuilder() { + if (optionsBuilder_ != null) { + return optionsBuilder_.getMessageOrBuilder(); + } else { + return options_ == null ? + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.getDefaultInstance() : options_; + } + } + /** + * optional .google.protobuf.FileOptions options = 8; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder> + getOptionsFieldBuilder() { + if (optionsBuilder_ == null) { + optionsBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FileOptionsOrBuilder>( + getOptions(), + getParentForChildren(), + isClean()); + options_ = null; + } + return optionsBuilder_; + } + + private com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo sourceCodeInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder> sourceCodeInfoBuilder_; + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public boolean hasSourceCodeInfo() { + return ((bitField0_ & 0x00000400) != 0); + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo getSourceCodeInfo() { + if (sourceCodeInfoBuilder_ == null) { + return sourceCodeInfo_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.getDefaultInstance() : sourceCodeInfo_; + } else { + return sourceCodeInfoBuilder_.getMessage(); + } + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public Builder setSourceCodeInfo(com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo value) { + if (sourceCodeInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + sourceCodeInfo_ = value; + onChanged(); + } else { + sourceCodeInfoBuilder_.setMessage(value); + } + bitField0_ |= 0x00000400; + return this; + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public Builder setSourceCodeInfo( + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder builderForValue) { + if (sourceCodeInfoBuilder_ == null) { + sourceCodeInfo_ = builderForValue.build(); + onChanged(); + } else { + sourceCodeInfoBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000400; + return this; + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public Builder mergeSourceCodeInfo(com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo value) { + if (sourceCodeInfoBuilder_ == null) { + if (((bitField0_ & 0x00000400) != 0) && + sourceCodeInfo_ != null && + sourceCodeInfo_ != com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.getDefaultInstance()) { + sourceCodeInfo_ = + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.newBuilder(sourceCodeInfo_).mergeFrom(value).buildPartial(); + } else { + sourceCodeInfo_ = value; + } + onChanged(); + } else { + sourceCodeInfoBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000400; + return this; + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public Builder clearSourceCodeInfo() { + if (sourceCodeInfoBuilder_ == null) { + sourceCodeInfo_ = null; + onChanged(); + } else { + sourceCodeInfoBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000400); + return this; + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder getSourceCodeInfoBuilder() { + bitField0_ |= 0x00000400; + onChanged(); + return getSourceCodeInfoFieldBuilder().getBuilder(); + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder getSourceCodeInfoOrBuilder() { + if (sourceCodeInfoBuilder_ != null) { + return sourceCodeInfoBuilder_.getMessageOrBuilder(); + } else { + return sourceCodeInfo_ == null ? + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.getDefaultInstance() : sourceCodeInfo_; + } + } + /** + *
+       * This field contains optional information about the original source code.
+       * You may safely remove this entire field without harming runtime
+       * functionality of the descriptors -- the information is needed only by
+       * development tools.
+       * 
+ * + * optional .google.protobuf.SourceCodeInfo source_code_info = 9; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder> + getSourceCodeInfoFieldBuilder() { + if (sourceCodeInfoBuilder_ == null) { + sourceCodeInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfo.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.SourceCodeInfoOrBuilder>( + getSourceCodeInfo(), + getParentForChildren(), + isClean()); + sourceCodeInfo_ = null; + } + return sourceCodeInfoBuilder_; + } + + private java.lang.Object syntax_ = ""; + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public boolean hasSyntax() { + return ((bitField0_ & 0x00000800) != 0); + } + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public java.lang.String getSyntax() { + java.lang.Object ref = syntax_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + syntax_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public com.google.protobuf.ByteString + getSyntaxBytes() { + java.lang.Object ref = syntax_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + syntax_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public Builder setSyntax( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000800; + syntax_ = value; + onChanged(); + return this; + } + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public Builder clearSyntax() { + bitField0_ = (bitField0_ & ~0x00000800); + syntax_ = getDefaultInstance().getSyntax(); + onChanged(); + return this; + } + /** + *
+       * The syntax of the proto file.
+       * The supported values are "proto2" and "proto3".
+       * 
+ * + * optional string syntax = 12; + */ + public Builder setSyntaxBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000800; + syntax_ = value; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.FileDescriptorProto) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public FileDescriptorProto parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new FileDescriptorProto(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.FileDescriptorProto getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface DescriptorProtoOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.DescriptorProto) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1; + */ + boolean hasName(); + /** + * optional string name = 1; + */ + java.lang.String getName(); + /** + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + java.util.List + getFieldList(); + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getField(int index); + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + int getFieldCount(); + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + java.util.List + getFieldOrBuilderList(); + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getFieldOrBuilder( + int index); + + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + java.util.List + getExtensionList(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + int getExtensionCount(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + java.util.List + getExtensionOrBuilderList(); + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index); + + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + java.util.List + getNestedTypeList(); + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getNestedType(int index); + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + int getNestedTypeCount(); + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + java.util.List + getNestedTypeOrBuilderList(); + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getNestedTypeOrBuilder( + int index); + + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + java.util.List + getEnumTypeList(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + int getEnumTypeCount(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + java.util.List + getEnumTypeOrBuilderList(); + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index); + + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + java.util.List + getExtensionRangeList(); + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getExtensionRange(int index); + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + int getExtensionRangeCount(); + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + java.util.List + getExtensionRangeOrBuilderList(); + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder getExtensionRangeOrBuilder( + int index); + + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + java.util.List + getOneofDeclList(); + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto getOneofDecl(int index); + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + int getOneofDeclCount(); + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + java.util.List + getOneofDeclOrBuilderList(); + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder getOneofDeclOrBuilder( + int index); + + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + boolean hasOptions(); + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions getOptions(); + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder getOptionsOrBuilder(); + + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + java.util.List + getReservedRangeList(); + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getReservedRange(int index); + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + int getReservedRangeCount(); + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + java.util.List + getReservedRangeOrBuilderList(); + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder getReservedRangeOrBuilder( + int index); + + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + java.util.List + getReservedNameList(); + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + int getReservedNameCount(); + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + java.lang.String getReservedName(int index); + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + com.google.protobuf.ByteString + getReservedNameBytes(int index); + } + /** + *
+   * Describes a message type.
+   * 
+ * + * Protobuf type {@code google.protobuf.DescriptorProto} + */ + public static final class DescriptorProto extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.DescriptorProto) + DescriptorProtoOrBuilder { + private static final long serialVersionUID = 0L; + // Use DescriptorProto.newBuilder() to construct. + private DescriptorProto(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private DescriptorProto() { + name_ = ""; + field_ = java.util.Collections.emptyList(); + extension_ = java.util.Collections.emptyList(); + nestedType_ = java.util.Collections.emptyList(); + enumType_ = java.util.Collections.emptyList(); + extensionRange_ = java.util.Collections.emptyList(); + oneofDecl_ = java.util.Collections.emptyList(); + reservedRange_ = java.util.Collections.emptyList(); + reservedName_ = com.google.protobuf.LazyStringArrayList.EMPTY; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new DescriptorProto(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DescriptorProto( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + name_ = bs; + break; + } + case 18: { + if (!((mutable_bitField0_ & 0x00000002) != 0)) { + field_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000002; + } + field_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 26: { + if (!((mutable_bitField0_ & 0x00000008) != 0)) { + nestedType_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000008; + } + nestedType_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.PARSER, extensionRegistry)); + break; + } + case 34: { + if (!((mutable_bitField0_ & 0x00000010) != 0)) { + enumType_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000010; + } + enumType_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 42: { + if (!((mutable_bitField0_ & 0x00000020) != 0)) { + extensionRange_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000020; + } + extensionRange_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.PARSER, extensionRegistry)); + break; + } + case 50: { + if (!((mutable_bitField0_ & 0x00000004) != 0)) { + extension_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000004; + } + extension_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 58: { + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder subBuilder = null; + if (((bitField0_ & 0x00000002) != 0)) { + subBuilder = options_.toBuilder(); + } + options_ = input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(options_); + options_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000002; + break; + } + case 66: { + if (!((mutable_bitField0_ & 0x00000040) != 0)) { + oneofDecl_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000040; + } + oneofDecl_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.PARSER, extensionRegistry)); + break; + } + case 74: { + if (!((mutable_bitField0_ & 0x00000100) != 0)) { + reservedRange_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000100; + } + reservedRange_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.PARSER, extensionRegistry)); + break; + } + case 82: { + com.google.protobuf.ByteString bs = input.readBytes(); + if (!((mutable_bitField0_ & 0x00000200) != 0)) { + reservedName_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000200; + } + reservedName_.add(bs); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000002) != 0)) { + field_ = java.util.Collections.unmodifiableList(field_); + } + if (((mutable_bitField0_ & 0x00000008) != 0)) { + nestedType_ = java.util.Collections.unmodifiableList(nestedType_); + } + if (((mutable_bitField0_ & 0x00000010) != 0)) { + enumType_ = java.util.Collections.unmodifiableList(enumType_); + } + if (((mutable_bitField0_ & 0x00000020) != 0)) { + extensionRange_ = java.util.Collections.unmodifiableList(extensionRange_); + } + if (((mutable_bitField0_ & 0x00000004) != 0)) { + extension_ = java.util.Collections.unmodifiableList(extension_); + } + if (((mutable_bitField0_ & 0x00000040) != 0)) { + oneofDecl_ = java.util.Collections.unmodifiableList(oneofDecl_); + } + if (((mutable_bitField0_ & 0x00000100) != 0)) { + reservedRange_ = java.util.Collections.unmodifiableList(reservedRange_); + } + if (((mutable_bitField0_ & 0x00000200) != 0)) { + reservedName_ = reservedName_.getUnmodifiableView(); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder.class); + } + + public interface ExtensionRangeOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.DescriptorProto.ExtensionRange) + com.google.protobuf.MessageOrBuilder { + + /** + * optional int32 start = 1; + */ + boolean hasStart(); + /** + * optional int32 start = 1; + */ + int getStart(); + + /** + * optional int32 end = 2; + */ + boolean hasEnd(); + /** + * optional int32 end = 2; + */ + int getEnd(); + + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + boolean hasOptions(); + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getOptions(); + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder getOptionsOrBuilder(); + } + /** + * Protobuf type {@code google.protobuf.DescriptorProto.ExtensionRange} + */ + public static final class ExtensionRange extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.DescriptorProto.ExtensionRange) + ExtensionRangeOrBuilder { + private static final long serialVersionUID = 0L; + // Use ExtensionRange.newBuilder() to construct. + private ExtensionRange(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private ExtensionRange() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new ExtensionRange(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ExtensionRange( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + bitField0_ |= 0x00000001; + start_ = input.readInt32(); + break; + } + case 16: { + bitField0_ |= 0x00000002; + end_ = input.readInt32(); + break; + } + case 26: { + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder subBuilder = null; + if (((bitField0_ & 0x00000004) != 0)) { + subBuilder = options_.toBuilder(); + } + options_ = input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(options_); + options_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000004; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder.class); + } + + private int bitField0_; + public static final int START_FIELD_NUMBER = 1; + private int start_; + /** + * optional int32 start = 1; + */ + public boolean hasStart() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int32 start = 1; + */ + public int getStart() { + return start_; + } + + public static final int END_FIELD_NUMBER = 2; + private int end_; + /** + * optional int32 end = 2; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int32 end = 2; + */ + public int getEnd() { + return end_; + } + + public static final int OPTIONS_FIELD_NUMBER = 3; + private com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions options_; + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getOptions() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance() : options_; + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder getOptionsOrBuilder() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance() : options_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (hasOptions()) { + if (!getOptions().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeInt32(1, start_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeInt32(2, end_); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeMessage(3, getOptions()); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, start_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, end_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getOptions()); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange other = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange) obj; + + if (hasStart() != other.hasStart()) return false; + if (hasStart()) { + if (getStart() + != other.getStart()) return false; + } + if (hasEnd() != other.hasEnd()) return false; + if (hasEnd()) { + if (getEnd() + != other.getEnd()) return false; + } + if (hasOptions() != other.hasOptions()) return false; + if (hasOptions()) { + if (!getOptions() + .equals(other.getOptions())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasStart()) { + hash = (37 * hash) + START_FIELD_NUMBER; + hash = (53 * hash) + getStart(); + } + if (hasEnd()) { + hash = (37 * hash) + END_FIELD_NUMBER; + hash = (53 * hash) + getEnd(); + } + if (hasOptions()) { + hash = (37 * hash) + OPTIONS_FIELD_NUMBER; + hash = (53 * hash) + getOptions().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code google.protobuf.DescriptorProto.ExtensionRange} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:google.protobuf.DescriptorProto.ExtensionRange) + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getOptionsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + start_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + end_ = 0; + bitField0_ = (bitField0_ & ~0x00000002); + if (optionsBuilder_ == null) { + options_ = null; + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange build() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange result = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.start_ = start_; + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.end_ = end_; + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + if (optionsBuilder_ == null) { + result.options_ = options_; + } else { + result.options_ = optionsBuilder_.build(); + } + to_bitField0_ |= 0x00000004; + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance()) return this; + if (other.hasStart()) { + setStart(other.getStart()); + } + if (other.hasEnd()) { + setEnd(other.getEnd()); + } + if (other.hasOptions()) { + mergeOptions(other.getOptions()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + if (hasOptions()) { + if (!getOptions().isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int start_ ; + /** + * optional int32 start = 1; + */ + public boolean hasStart() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int32 start = 1; + */ + public int getStart() { + return start_; + } + /** + * optional int32 start = 1; + */ + public Builder setStart(int value) { + bitField0_ |= 0x00000001; + start_ = value; + onChanged(); + return this; + } + /** + * optional int32 start = 1; + */ + public Builder clearStart() { + bitField0_ = (bitField0_ & ~0x00000001); + start_ = 0; + onChanged(); + return this; + } + + private int end_ ; + /** + * optional int32 end = 2; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional int32 end = 2; + */ + public int getEnd() { + return end_; + } + /** + * optional int32 end = 2; + */ + public Builder setEnd(int value) { + bitField0_ |= 0x00000002; + end_ = value; + onChanged(); + return this; + } + /** + * optional int32 end = 2; + */ + public Builder clearEnd() { + bitField0_ = (bitField0_ & ~0x00000002); + end_ = 0; + onChanged(); + return this; + } + + private com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions options_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder> optionsBuilder_; + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getOptions() { + if (optionsBuilder_ == null) { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance() : options_; + } else { + return optionsBuilder_.getMessage(); + } + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public Builder setOptions(com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions value) { + if (optionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + options_ = value; + onChanged(); + } else { + optionsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public Builder setOptions( + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder builderForValue) { + if (optionsBuilder_ == null) { + options_ = builderForValue.build(); + onChanged(); + } else { + optionsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public Builder mergeOptions(com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions value) { + if (optionsBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + options_ != null && + options_ != com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance()) { + options_ = + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.newBuilder(options_).mergeFrom(value).buildPartial(); + } else { + options_ = value; + } + onChanged(); + } else { + optionsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public Builder clearOptions() { + if (optionsBuilder_ == null) { + options_ = null; + onChanged(); + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder getOptionsBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getOptionsFieldBuilder().getBuilder(); + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder getOptionsOrBuilder() { + if (optionsBuilder_ != null) { + return optionsBuilder_.getMessageOrBuilder(); + } else { + return options_ == null ? + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance() : options_; + } + } + /** + * optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder> + getOptionsFieldBuilder() { + if (optionsBuilder_ == null) { + optionsBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder>( + getOptions(), + getParentForChildren(), + isClean()); + options_ = null; + } + return optionsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.DescriptorProto.ExtensionRange) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ExtensionRange parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ExtensionRange(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ReservedRangeOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.DescriptorProto.ReservedRange) + com.google.protobuf.MessageOrBuilder { + + /** + *
+       * Inclusive.
+       * 
+ * + * optional int32 start = 1; + */ + boolean hasStart(); + /** + *
+       * Inclusive.
+       * 
+ * + * optional int32 start = 1; + */ + int getStart(); + + /** + *
+       * Exclusive.
+       * 
+ * + * optional int32 end = 2; + */ + boolean hasEnd(); + /** + *
+       * Exclusive.
+       * 
+ * + * optional int32 end = 2; + */ + int getEnd(); + } + /** + *
+     * Range of reserved tag numbers. Reserved tag numbers may not be used by
+     * fields or extension ranges in the same message. Reserved ranges may
+     * not overlap.
+     * 
+ * + * Protobuf type {@code google.protobuf.DescriptorProto.ReservedRange} + */ + public static final class ReservedRange extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.DescriptorProto.ReservedRange) + ReservedRangeOrBuilder { + private static final long serialVersionUID = 0L; + // Use ReservedRange.newBuilder() to construct. + private ReservedRange(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private ReservedRange() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new ReservedRange(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ReservedRange( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + bitField0_ |= 0x00000001; + start_ = input.readInt32(); + break; + } + case 16: { + bitField0_ |= 0x00000002; + end_ = input.readInt32(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ReservedRange_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ReservedRange_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder.class); + } + + private int bitField0_; + public static final int START_FIELD_NUMBER = 1; + private int start_; + /** + *
+       * Inclusive.
+       * 
+ * + * optional int32 start = 1; + */ + public boolean hasStart() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+       * Inclusive.
+       * 
+ * + * optional int32 start = 1; + */ + public int getStart() { + return start_; + } + + public static final int END_FIELD_NUMBER = 2; + private int end_; + /** + *
+       * Exclusive.
+       * 
+ * + * optional int32 end = 2; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+       * Exclusive.
+       * 
+ * + * optional int32 end = 2; + */ + public int getEnd() { + return end_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeInt32(1, start_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeInt32(2, end_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, start_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, end_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange other = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange) obj; + + if (hasStart() != other.hasStart()) return false; + if (hasStart()) { + if (getStart() + != other.getStart()) return false; + } + if (hasEnd() != other.hasEnd()) return false; + if (hasEnd()) { + if (getEnd() + != other.getEnd()) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasStart()) { + hash = (37 * hash) + START_FIELD_NUMBER; + hash = (53 * hash) + getStart(); + } + if (hasEnd()) { + hash = (37 * hash) + END_FIELD_NUMBER; + hash = (53 * hash) + getEnd(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+       * Range of reserved tag numbers. Reserved tag numbers may not be used by
+       * fields or extension ranges in the same message. Reserved ranges may
+       * not overlap.
+       * 
+ * + * Protobuf type {@code google.protobuf.DescriptorProto.ReservedRange} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:google.protobuf.DescriptorProto.ReservedRange) + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ReservedRange_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ReservedRange_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + start_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + end_ = 0; + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ReservedRange_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange build() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange result = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.start_ = start_; + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.end_ = end_; + to_bitField0_ |= 0x00000002; + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.getDefaultInstance()) return this; + if (other.hasStart()) { + setStart(other.getStart()); + } + if (other.hasEnd()) { + setEnd(other.getEnd()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int start_ ; + /** + *
+         * Inclusive.
+         * 
+ * + * optional int32 start = 1; + */ + public boolean hasStart() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+         * Inclusive.
+         * 
+ * + * optional int32 start = 1; + */ + public int getStart() { + return start_; + } + /** + *
+         * Inclusive.
+         * 
+ * + * optional int32 start = 1; + */ + public Builder setStart(int value) { + bitField0_ |= 0x00000001; + start_ = value; + onChanged(); + return this; + } + /** + *
+         * Inclusive.
+         * 
+ * + * optional int32 start = 1; + */ + public Builder clearStart() { + bitField0_ = (bitField0_ & ~0x00000001); + start_ = 0; + onChanged(); + return this; + } + + private int end_ ; + /** + *
+         * Exclusive.
+         * 
+ * + * optional int32 end = 2; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
+         * Exclusive.
+         * 
+ * + * optional int32 end = 2; + */ + public int getEnd() { + return end_; + } + /** + *
+         * Exclusive.
+         * 
+ * + * optional int32 end = 2; + */ + public Builder setEnd(int value) { + bitField0_ |= 0x00000002; + end_ = value; + onChanged(); + return this; + } + /** + *
+         * Exclusive.
+         * 
+ * + * optional int32 end = 2; + */ + public Builder clearEnd() { + bitField0_ = (bitField0_ & ~0x00000002); + end_ = 0; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.DescriptorProto.ReservedRange) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ReservedRange parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ReservedRange(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + * optional string name = 1; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int FIELD_FIELD_NUMBER = 2; + private java.util.List field_; + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public java.util.List getFieldList() { + return field_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public java.util.List + getFieldOrBuilderList() { + return field_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public int getFieldCount() { + return field_.size(); + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getField(int index) { + return field_.get(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getFieldOrBuilder( + int index) { + return field_.get(index); + } + + public static final int EXTENSION_FIELD_NUMBER = 6; + private java.util.List extension_; + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public java.util.List getExtensionList() { + return extension_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public java.util.List + getExtensionOrBuilderList() { + return extension_; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public int getExtensionCount() { + return extension_.size(); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return extension_.get(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index) { + return extension_.get(index); + } + + public static final int NESTED_TYPE_FIELD_NUMBER = 3; + private java.util.List nestedType_; + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public java.util.List getNestedTypeList() { + return nestedType_; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public java.util.List + getNestedTypeOrBuilderList() { + return nestedType_; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public int getNestedTypeCount() { + return nestedType_.size(); + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getNestedType(int index) { + return nestedType_.get(index); + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getNestedTypeOrBuilder( + int index) { + return nestedType_.get(index); + } + + public static final int ENUM_TYPE_FIELD_NUMBER = 4; + private java.util.List enumType_; + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public java.util.List getEnumTypeList() { + return enumType_; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public java.util.List + getEnumTypeOrBuilderList() { + return enumType_; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public int getEnumTypeCount() { + return enumType_.size(); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return enumType_.get(index); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index) { + return enumType_.get(index); + } + + public static final int EXTENSION_RANGE_FIELD_NUMBER = 5; + private java.util.List extensionRange_; + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public java.util.List getExtensionRangeList() { + return extensionRange_; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public java.util.List + getExtensionRangeOrBuilderList() { + return extensionRange_; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public int getExtensionRangeCount() { + return extensionRange_.size(); + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getExtensionRange(int index) { + return extensionRange_.get(index); + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder getExtensionRangeOrBuilder( + int index) { + return extensionRange_.get(index); + } + + public static final int ONEOF_DECL_FIELD_NUMBER = 8; + private java.util.List oneofDecl_; + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public java.util.List getOneofDeclList() { + return oneofDecl_; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public java.util.List + getOneofDeclOrBuilderList() { + return oneofDecl_; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public int getOneofDeclCount() { + return oneofDecl_.size(); + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto getOneofDecl(int index) { + return oneofDecl_.get(index); + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder getOneofDeclOrBuilder( + int index) { + return oneofDecl_.get(index); + } + + public static final int OPTIONS_FIELD_NUMBER = 7; + private com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions options_; + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions getOptions() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.getDefaultInstance() : options_; + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder getOptionsOrBuilder() { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.getDefaultInstance() : options_; + } + + public static final int RESERVED_RANGE_FIELD_NUMBER = 9; + private java.util.List reservedRange_; + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public java.util.List getReservedRangeList() { + return reservedRange_; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public java.util.List + getReservedRangeOrBuilderList() { + return reservedRange_; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public int getReservedRangeCount() { + return reservedRange_.size(); + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getReservedRange(int index) { + return reservedRange_.get(index); + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder getReservedRangeOrBuilder( + int index) { + return reservedRange_.get(index); + } + + public static final int RESERVED_NAME_FIELD_NUMBER = 10; + private com.google.protobuf.LazyStringList reservedName_; + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + public com.google.protobuf.ProtocolStringList + getReservedNameList() { + return reservedName_; + } + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + public int getReservedNameCount() { + return reservedName_.size(); + } + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + public java.lang.String getReservedName(int index) { + return reservedName_.get(index); + } + /** + *
+     * Reserved field names, which may not be used by fields in the same message.
+     * A given name may only be reserved once.
+     * 
+ * + * repeated string reserved_name = 10; + */ + public com.google.protobuf.ByteString + getReservedNameBytes(int index) { + return reservedName_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getFieldCount(); i++) { + if (!getField(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getExtensionCount(); i++) { + if (!getExtension(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getNestedTypeCount(); i++) { + if (!getNestedType(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getEnumTypeCount(); i++) { + if (!getEnumType(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getExtensionRangeCount(); i++) { + if (!getExtensionRange(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + for (int i = 0; i < getOneofDeclCount(); i++) { + if (!getOneofDecl(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + if (hasOptions()) { + if (!getOptions().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); + } + for (int i = 0; i < field_.size(); i++) { + output.writeMessage(2, field_.get(i)); + } + for (int i = 0; i < nestedType_.size(); i++) { + output.writeMessage(3, nestedType_.get(i)); + } + for (int i = 0; i < enumType_.size(); i++) { + output.writeMessage(4, enumType_.get(i)); + } + for (int i = 0; i < extensionRange_.size(); i++) { + output.writeMessage(5, extensionRange_.get(i)); + } + for (int i = 0; i < extension_.size(); i++) { + output.writeMessage(6, extension_.get(i)); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(7, getOptions()); + } + for (int i = 0; i < oneofDecl_.size(); i++) { + output.writeMessage(8, oneofDecl_.get(i)); + } + for (int i = 0; i < reservedRange_.size(); i++) { + output.writeMessage(9, reservedRange_.get(i)); + } + for (int i = 0; i < reservedName_.size(); i++) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 10, reservedName_.getRaw(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); + } + for (int i = 0; i < field_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, field_.get(i)); + } + for (int i = 0; i < nestedType_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, nestedType_.get(i)); + } + for (int i = 0; i < enumType_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, enumType_.get(i)); + } + for (int i = 0; i < extensionRange_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, extensionRange_.get(i)); + } + for (int i = 0; i < extension_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, extension_.get(i)); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, getOptions()); + } + for (int i = 0; i < oneofDecl_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, oneofDecl_.get(i)); + } + for (int i = 0; i < reservedRange_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, reservedRange_.get(i)); + } + { + int dataSize = 0; + for (int i = 0; i < reservedName_.size(); i++) { + dataSize += computeStringSizeNoTag(reservedName_.getRaw(i)); + } + size += dataSize; + size += 1 * getReservedNameList().size(); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto other = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto) obj; + + if (hasName() != other.hasName()) return false; + if (hasName()) { + if (!getName() + .equals(other.getName())) return false; + } + if (!getFieldList() + .equals(other.getFieldList())) return false; + if (!getExtensionList() + .equals(other.getExtensionList())) return false; + if (!getNestedTypeList() + .equals(other.getNestedTypeList())) return false; + if (!getEnumTypeList() + .equals(other.getEnumTypeList())) return false; + if (!getExtensionRangeList() + .equals(other.getExtensionRangeList())) return false; + if (!getOneofDeclList() + .equals(other.getOneofDeclList())) return false; + if (hasOptions() != other.hasOptions()) return false; + if (hasOptions()) { + if (!getOptions() + .equals(other.getOptions())) return false; + } + if (!getReservedRangeList() + .equals(other.getReservedRangeList())) return false; + if (!getReservedNameList() + .equals(other.getReservedNameList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasName()) { + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + } + if (getFieldCount() > 0) { + hash = (37 * hash) + FIELD_FIELD_NUMBER; + hash = (53 * hash) + getFieldList().hashCode(); + } + if (getExtensionCount() > 0) { + hash = (37 * hash) + EXTENSION_FIELD_NUMBER; + hash = (53 * hash) + getExtensionList().hashCode(); + } + if (getNestedTypeCount() > 0) { + hash = (37 * hash) + NESTED_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getNestedTypeList().hashCode(); + } + if (getEnumTypeCount() > 0) { + hash = (37 * hash) + ENUM_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getEnumTypeList().hashCode(); + } + if (getExtensionRangeCount() > 0) { + hash = (37 * hash) + EXTENSION_RANGE_FIELD_NUMBER; + hash = (53 * hash) + getExtensionRangeList().hashCode(); + } + if (getOneofDeclCount() > 0) { + hash = (37 * hash) + ONEOF_DECL_FIELD_NUMBER; + hash = (53 * hash) + getOneofDeclList().hashCode(); + } + if (hasOptions()) { + hash = (37 * hash) + OPTIONS_FIELD_NUMBER; + hash = (53 * hash) + getOptions().hashCode(); + } + if (getReservedRangeCount() > 0) { + hash = (37 * hash) + RESERVED_RANGE_FIELD_NUMBER; + hash = (53 * hash) + getReservedRangeList().hashCode(); + } + if (getReservedNameCount() > 0) { + hash = (37 * hash) + RESERVED_NAME_FIELD_NUMBER; + hash = (53 * hash) + getReservedNameList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * Describes a message type.
+     * 
+ * + * Protobuf type {@code google.protobuf.DescriptorProto} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:google.protobuf.DescriptorProto) + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.class, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getFieldFieldBuilder(); + getExtensionFieldBuilder(); + getNestedTypeFieldBuilder(); + getEnumTypeFieldBuilder(); + getExtensionRangeFieldBuilder(); + getOneofDeclFieldBuilder(); + getOptionsFieldBuilder(); + getReservedRangeFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + name_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + if (fieldBuilder_ == null) { + field_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000002); + } else { + fieldBuilder_.clear(); + } + if (extensionBuilder_ == null) { + extension_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + } else { + extensionBuilder_.clear(); + } + if (nestedTypeBuilder_ == null) { + nestedType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + } else { + nestedTypeBuilder_.clear(); + } + if (enumTypeBuilder_ == null) { + enumType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + } else { + enumTypeBuilder_.clear(); + } + if (extensionRangeBuilder_ == null) { + extensionRange_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + } else { + extensionRangeBuilder_.clear(); + } + if (oneofDeclBuilder_ == null) { + oneofDecl_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040); + } else { + oneofDeclBuilder_.clear(); + } + if (optionsBuilder_ == null) { + options_ = null; + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000080); + if (reservedRangeBuilder_ == null) { + reservedRange_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); + } else { + reservedRangeBuilder_.clear(); + } + reservedName_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000200); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto build() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto result = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.name_ = name_; + if (fieldBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0)) { + field_ = java.util.Collections.unmodifiableList(field_); + bitField0_ = (bitField0_ & ~0x00000002); + } + result.field_ = field_; + } else { + result.field_ = fieldBuilder_.build(); + } + if (extensionBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0)) { + extension_ = java.util.Collections.unmodifiableList(extension_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.extension_ = extension_; + } else { + result.extension_ = extensionBuilder_.build(); + } + if (nestedTypeBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0)) { + nestedType_ = java.util.Collections.unmodifiableList(nestedType_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.nestedType_ = nestedType_; + } else { + result.nestedType_ = nestedTypeBuilder_.build(); + } + if (enumTypeBuilder_ == null) { + if (((bitField0_ & 0x00000010) != 0)) { + enumType_ = java.util.Collections.unmodifiableList(enumType_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.enumType_ = enumType_; + } else { + result.enumType_ = enumTypeBuilder_.build(); + } + if (extensionRangeBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0)) { + extensionRange_ = java.util.Collections.unmodifiableList(extensionRange_); + bitField0_ = (bitField0_ & ~0x00000020); + } + result.extensionRange_ = extensionRange_; + } else { + result.extensionRange_ = extensionRangeBuilder_.build(); + } + if (oneofDeclBuilder_ == null) { + if (((bitField0_ & 0x00000040) != 0)) { + oneofDecl_ = java.util.Collections.unmodifiableList(oneofDecl_); + bitField0_ = (bitField0_ & ~0x00000040); + } + result.oneofDecl_ = oneofDecl_; + } else { + result.oneofDecl_ = oneofDeclBuilder_.build(); + } + if (((from_bitField0_ & 0x00000080) != 0)) { + if (optionsBuilder_ == null) { + result.options_ = options_; + } else { + result.options_ = optionsBuilder_.build(); + } + to_bitField0_ |= 0x00000002; + } + if (reservedRangeBuilder_ == null) { + if (((bitField0_ & 0x00000100) != 0)) { + reservedRange_ = java.util.Collections.unmodifiableList(reservedRange_); + bitField0_ = (bitField0_ & ~0x00000100); + } + result.reservedRange_ = reservedRange_; + } else { + result.reservedRange_ = reservedRangeBuilder_.build(); + } + if (((bitField0_ & 0x00000200) != 0)) { + reservedName_ = reservedName_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000200); + } + result.reservedName_ = reservedName_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance()) return this; + if (other.hasName()) { + bitField0_ |= 0x00000001; + name_ = other.name_; + onChanged(); + } + if (fieldBuilder_ == null) { + if (!other.field_.isEmpty()) { + if (field_.isEmpty()) { + field_ = other.field_; + bitField0_ = (bitField0_ & ~0x00000002); + } else { + ensureFieldIsMutable(); + field_.addAll(other.field_); + } + onChanged(); + } + } else { + if (!other.field_.isEmpty()) { + if (fieldBuilder_.isEmpty()) { + fieldBuilder_.dispose(); + fieldBuilder_ = null; + field_ = other.field_; + bitField0_ = (bitField0_ & ~0x00000002); + fieldBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getFieldFieldBuilder() : null; + } else { + fieldBuilder_.addAllMessages(other.field_); + } + } + } + if (extensionBuilder_ == null) { + if (!other.extension_.isEmpty()) { + if (extension_.isEmpty()) { + extension_ = other.extension_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureExtensionIsMutable(); + extension_.addAll(other.extension_); + } + onChanged(); + } + } else { + if (!other.extension_.isEmpty()) { + if (extensionBuilder_.isEmpty()) { + extensionBuilder_.dispose(); + extensionBuilder_ = null; + extension_ = other.extension_; + bitField0_ = (bitField0_ & ~0x00000004); + extensionBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getExtensionFieldBuilder() : null; + } else { + extensionBuilder_.addAllMessages(other.extension_); + } + } + } + if (nestedTypeBuilder_ == null) { + if (!other.nestedType_.isEmpty()) { + if (nestedType_.isEmpty()) { + nestedType_ = other.nestedType_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensureNestedTypeIsMutable(); + nestedType_.addAll(other.nestedType_); + } + onChanged(); + } + } else { + if (!other.nestedType_.isEmpty()) { + if (nestedTypeBuilder_.isEmpty()) { + nestedTypeBuilder_.dispose(); + nestedTypeBuilder_ = null; + nestedType_ = other.nestedType_; + bitField0_ = (bitField0_ & ~0x00000008); + nestedTypeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getNestedTypeFieldBuilder() : null; + } else { + nestedTypeBuilder_.addAllMessages(other.nestedType_); + } + } + } + if (enumTypeBuilder_ == null) { + if (!other.enumType_.isEmpty()) { + if (enumType_.isEmpty()) { + enumType_ = other.enumType_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureEnumTypeIsMutable(); + enumType_.addAll(other.enumType_); + } + onChanged(); + } + } else { + if (!other.enumType_.isEmpty()) { + if (enumTypeBuilder_.isEmpty()) { + enumTypeBuilder_.dispose(); + enumTypeBuilder_ = null; + enumType_ = other.enumType_; + bitField0_ = (bitField0_ & ~0x00000010); + enumTypeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getEnumTypeFieldBuilder() : null; + } else { + enumTypeBuilder_.addAllMessages(other.enumType_); + } + } + } + if (extensionRangeBuilder_ == null) { + if (!other.extensionRange_.isEmpty()) { + if (extensionRange_.isEmpty()) { + extensionRange_ = other.extensionRange_; + bitField0_ = (bitField0_ & ~0x00000020); + } else { + ensureExtensionRangeIsMutable(); + extensionRange_.addAll(other.extensionRange_); + } + onChanged(); + } + } else { + if (!other.extensionRange_.isEmpty()) { + if (extensionRangeBuilder_.isEmpty()) { + extensionRangeBuilder_.dispose(); + extensionRangeBuilder_ = null; + extensionRange_ = other.extensionRange_; + bitField0_ = (bitField0_ & ~0x00000020); + extensionRangeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getExtensionRangeFieldBuilder() : null; + } else { + extensionRangeBuilder_.addAllMessages(other.extensionRange_); + } + } + } + if (oneofDeclBuilder_ == null) { + if (!other.oneofDecl_.isEmpty()) { + if (oneofDecl_.isEmpty()) { + oneofDecl_ = other.oneofDecl_; + bitField0_ = (bitField0_ & ~0x00000040); + } else { + ensureOneofDeclIsMutable(); + oneofDecl_.addAll(other.oneofDecl_); + } + onChanged(); + } + } else { + if (!other.oneofDecl_.isEmpty()) { + if (oneofDeclBuilder_.isEmpty()) { + oneofDeclBuilder_.dispose(); + oneofDeclBuilder_ = null; + oneofDecl_ = other.oneofDecl_; + bitField0_ = (bitField0_ & ~0x00000040); + oneofDeclBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getOneofDeclFieldBuilder() : null; + } else { + oneofDeclBuilder_.addAllMessages(other.oneofDecl_); + } + } + } + if (other.hasOptions()) { + mergeOptions(other.getOptions()); + } + if (reservedRangeBuilder_ == null) { + if (!other.reservedRange_.isEmpty()) { + if (reservedRange_.isEmpty()) { + reservedRange_ = other.reservedRange_; + bitField0_ = (bitField0_ & ~0x00000100); + } else { + ensureReservedRangeIsMutable(); + reservedRange_.addAll(other.reservedRange_); + } + onChanged(); + } + } else { + if (!other.reservedRange_.isEmpty()) { + if (reservedRangeBuilder_.isEmpty()) { + reservedRangeBuilder_.dispose(); + reservedRangeBuilder_ = null; + reservedRange_ = other.reservedRange_; + bitField0_ = (bitField0_ & ~0x00000100); + reservedRangeBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getReservedRangeFieldBuilder() : null; + } else { + reservedRangeBuilder_.addAllMessages(other.reservedRange_); + } + } + } + if (!other.reservedName_.isEmpty()) { + if (reservedName_.isEmpty()) { + reservedName_ = other.reservedName_; + bitField0_ = (bitField0_ & ~0x00000200); + } else { + ensureReservedNameIsMutable(); + reservedName_.addAll(other.reservedName_); + } + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getFieldCount(); i++) { + if (!getField(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getExtensionCount(); i++) { + if (!getExtension(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getNestedTypeCount(); i++) { + if (!getNestedType(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getEnumTypeCount(); i++) { + if (!getEnumType(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getExtensionRangeCount(); i++) { + if (!getExtensionRange(i).isInitialized()) { + return false; + } + } + for (int i = 0; i < getOneofDeclCount(); i++) { + if (!getOneofDecl(i).isInitialized()) { + return false; + } + } + if (hasOptions()) { + if (!getOptions().isInitialized()) { + return false; + } + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + * optional string name = 1; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string name = 1; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder clearName() { + bitField0_ = (bitField0_ & ~0x00000001); + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + name_ = value; + onChanged(); + return this; + } + + private java.util.List field_ = + java.util.Collections.emptyList(); + private void ensureFieldIsMutable() { + if (!((bitField0_ & 0x00000002) != 0)) { + field_ = new java.util.ArrayList(field_); + bitField0_ |= 0x00000002; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> fieldBuilder_; + + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public java.util.List getFieldList() { + if (fieldBuilder_ == null) { + return java.util.Collections.unmodifiableList(field_); + } else { + return fieldBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public int getFieldCount() { + if (fieldBuilder_ == null) { + return field_.size(); + } else { + return fieldBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getField(int index) { + if (fieldBuilder_ == null) { + return field_.get(index); + } else { + return fieldBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder setField( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (fieldBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFieldIsMutable(); + field_.set(index, value); + onChanged(); + } else { + fieldBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder setField( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (fieldBuilder_ == null) { + ensureFieldIsMutable(); + field_.set(index, builderForValue.build()); + onChanged(); + } else { + fieldBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder addField(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (fieldBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFieldIsMutable(); + field_.add(value); + onChanged(); + } else { + fieldBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder addField( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (fieldBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFieldIsMutable(); + field_.add(index, value); + onChanged(); + } else { + fieldBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder addField( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (fieldBuilder_ == null) { + ensureFieldIsMutable(); + field_.add(builderForValue.build()); + onChanged(); + } else { + fieldBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder addField( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (fieldBuilder_ == null) { + ensureFieldIsMutable(); + field_.add(index, builderForValue.build()); + onChanged(); + } else { + fieldBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder addAllField( + java.lang.Iterable values) { + if (fieldBuilder_ == null) { + ensureFieldIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, field_); + onChanged(); + } else { + fieldBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder clearField() { + if (fieldBuilder_ == null) { + field_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + } else { + fieldBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public Builder removeField(int index) { + if (fieldBuilder_ == null) { + ensureFieldIsMutable(); + field_.remove(index); + onChanged(); + } else { + fieldBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder getFieldBuilder( + int index) { + return getFieldFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getFieldOrBuilder( + int index) { + if (fieldBuilder_ == null) { + return field_.get(index); } else { + return fieldBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public java.util.List + getFieldOrBuilderList() { + if (fieldBuilder_ != null) { + return fieldBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(field_); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addFieldBuilder() { + return getFieldFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addFieldBuilder( + int index) { + return getFieldFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto field = 2; + */ + public java.util.List + getFieldBuilderList() { + return getFieldFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> + getFieldFieldBuilder() { + if (fieldBuilder_ == null) { + fieldBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder>( + field_, + ((bitField0_ & 0x00000002) != 0), + getParentForChildren(), + isClean()); + field_ = null; + } + return fieldBuilder_; + } + + private java.util.List extension_ = + java.util.Collections.emptyList(); + private void ensureExtensionIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + extension_ = new java.util.ArrayList(extension_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> extensionBuilder_; + + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public java.util.List getExtensionList() { + if (extensionBuilder_ == null) { + return java.util.Collections.unmodifiableList(extension_); + } else { + return extensionBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public int getExtensionCount() { + if (extensionBuilder_ == null) { + return extension_.size(); + } else { + return extensionBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + if (extensionBuilder_ == null) { + return extension_.get(index); + } else { + return extensionBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder setExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.set(index, value); + onChanged(); + } else { + extensionBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder setExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.set(index, builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder addExtension(com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.add(value); + onChanged(); + } else { + extensionBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder addExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto value) { + if (extensionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionIsMutable(); + extension_.add(index, value); + onChanged(); + } else { + extensionBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder addExtension( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.add(builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder addExtension( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.add(index, builderForValue.build()); + onChanged(); + } else { + extensionBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder addAllExtension( + java.lang.Iterable values) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extension_); + onChanged(); + } else { + extensionBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder clearExtension() { + if (extensionBuilder_ == null) { + extension_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + extensionBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public Builder removeExtension(int index) { + if (extensionBuilder_ == null) { + ensureExtensionIsMutable(); + extension_.remove(index); + onChanged(); + } else { + extensionBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder getExtensionBuilder( + int index) { + return getExtensionFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder getExtensionOrBuilder( + int index) { + if (extensionBuilder_ == null) { + return extension_.get(index); } else { + return extensionBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public java.util.List + getExtensionOrBuilderList() { + if (extensionBuilder_ != null) { + return extensionBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(extension_); + } + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addExtensionBuilder() { + return getExtensionFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder addExtensionBuilder( + int index) { + return getExtensionFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.FieldDescriptorProto extension = 6; + */ + public java.util.List + getExtensionBuilderList() { + return getExtensionFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder> + getExtensionFieldBuilder() { + if (extensionBuilder_ == null) { + extensionBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProtoOrBuilder>( + extension_, + ((bitField0_ & 0x00000004) != 0), + getParentForChildren(), + isClean()); + extension_ = null; + } + return extensionBuilder_; + } + + private java.util.List nestedType_ = + java.util.Collections.emptyList(); + private void ensureNestedTypeIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + nestedType_ = new java.util.ArrayList(nestedType_); + bitField0_ |= 0x00000008; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder> nestedTypeBuilder_; + + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public java.util.List getNestedTypeList() { + if (nestedTypeBuilder_ == null) { + return java.util.Collections.unmodifiableList(nestedType_); + } else { + return nestedTypeBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public int getNestedTypeCount() { + if (nestedTypeBuilder_ == null) { + return nestedType_.size(); + } else { + return nestedTypeBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getNestedType(int index) { + if (nestedTypeBuilder_ == null) { + return nestedType_.get(index); + } else { + return nestedTypeBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder setNestedType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (nestedTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNestedTypeIsMutable(); + nestedType_.set(index, value); + onChanged(); + } else { + nestedTypeBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder setNestedType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (nestedTypeBuilder_ == null) { + ensureNestedTypeIsMutable(); + nestedType_.set(index, builderForValue.build()); + onChanged(); + } else { + nestedTypeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder addNestedType(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (nestedTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNestedTypeIsMutable(); + nestedType_.add(value); + onChanged(); + } else { + nestedTypeBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder addNestedType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto value) { + if (nestedTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNestedTypeIsMutable(); + nestedType_.add(index, value); + onChanged(); + } else { + nestedTypeBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder addNestedType( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (nestedTypeBuilder_ == null) { + ensureNestedTypeIsMutable(); + nestedType_.add(builderForValue.build()); + onChanged(); + } else { + nestedTypeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder addNestedType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (nestedTypeBuilder_ == null) { + ensureNestedTypeIsMutable(); + nestedType_.add(index, builderForValue.build()); + onChanged(); + } else { + nestedTypeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder addAllNestedType( + java.lang.Iterable values) { + if (nestedTypeBuilder_ == null) { + ensureNestedTypeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, nestedType_); + onChanged(); + } else { + nestedTypeBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder clearNestedType() { + if (nestedTypeBuilder_ == null) { + nestedType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + nestedTypeBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public Builder removeNestedType(int index) { + if (nestedTypeBuilder_ == null) { + ensureNestedTypeIsMutable(); + nestedType_.remove(index); + onChanged(); + } else { + nestedTypeBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder getNestedTypeBuilder( + int index) { + return getNestedTypeFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder getNestedTypeOrBuilder( + int index) { + if (nestedTypeBuilder_ == null) { + return nestedType_.get(index); } else { + return nestedTypeBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public java.util.List + getNestedTypeOrBuilderList() { + if (nestedTypeBuilder_ != null) { + return nestedTypeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(nestedType_); + } + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder addNestedTypeBuilder() { + return getNestedTypeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder addNestedTypeBuilder( + int index) { + return getNestedTypeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto nested_type = 3; + */ + public java.util.List + getNestedTypeBuilderList() { + return getNestedTypeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder> + getNestedTypeFieldBuilder() { + if (nestedTypeBuilder_ == null) { + nestedTypeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProtoOrBuilder>( + nestedType_, + ((bitField0_ & 0x00000008) != 0), + getParentForChildren(), + isClean()); + nestedType_ = null; + } + return nestedTypeBuilder_; + } + + private java.util.List enumType_ = + java.util.Collections.emptyList(); + private void ensureEnumTypeIsMutable() { + if (!((bitField0_ & 0x00000010) != 0)) { + enumType_ = new java.util.ArrayList(enumType_); + bitField0_ |= 0x00000010; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder> enumTypeBuilder_; + + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public java.util.List getEnumTypeList() { + if (enumTypeBuilder_ == null) { + return java.util.Collections.unmodifiableList(enumType_); + } else { + return enumTypeBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public int getEnumTypeCount() { + if (enumTypeBuilder_ == null) { + return enumType_.size(); + } else { + return enumTypeBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + if (enumTypeBuilder_ == null) { + return enumType_.get(index); + } else { + return enumTypeBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder setEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.set(index, value); + onChanged(); + } else { + enumTypeBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder setEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.set(index, builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder addEnumType(com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.add(value); + onChanged(); + } else { + enumTypeBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder addEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto value) { + if (enumTypeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEnumTypeIsMutable(); + enumType_.add(index, value); + onChanged(); + } else { + enumTypeBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder addEnumType( + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.add(builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder addEnumType( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.add(index, builderForValue.build()); + onChanged(); + } else { + enumTypeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder addAllEnumType( + java.lang.Iterable values) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, enumType_); + onChanged(); + } else { + enumTypeBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder clearEnumType() { + if (enumTypeBuilder_ == null) { + enumType_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + } else { + enumTypeBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public Builder removeEnumType(int index) { + if (enumTypeBuilder_ == null) { + ensureEnumTypeIsMutable(); + enumType_.remove(index); + onChanged(); + } else { + enumTypeBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder getEnumTypeBuilder( + int index) { + return getEnumTypeFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder getEnumTypeOrBuilder( + int index) { + if (enumTypeBuilder_ == null) { + return enumType_.get(index); } else { + return enumTypeBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public java.util.List + getEnumTypeOrBuilderList() { + if (enumTypeBuilder_ != null) { + return enumTypeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(enumType_); + } + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder addEnumTypeBuilder() { + return getEnumTypeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder addEnumTypeBuilder( + int index) { + return getEnumTypeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + */ + public java.util.List + getEnumTypeBuilderList() { + return getEnumTypeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder> + getEnumTypeFieldBuilder() { + if (enumTypeBuilder_ == null) { + enumTypeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.EnumDescriptorProtoOrBuilder>( + enumType_, + ((bitField0_ & 0x00000010) != 0), + getParentForChildren(), + isClean()); + enumType_ = null; + } + return enumTypeBuilder_; + } + + private java.util.List extensionRange_ = + java.util.Collections.emptyList(); + private void ensureExtensionRangeIsMutable() { + if (!((bitField0_ & 0x00000020) != 0)) { + extensionRange_ = new java.util.ArrayList(extensionRange_); + bitField0_ |= 0x00000020; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder> extensionRangeBuilder_; + + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public java.util.List getExtensionRangeList() { + if (extensionRangeBuilder_ == null) { + return java.util.Collections.unmodifiableList(extensionRange_); + } else { + return extensionRangeBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public int getExtensionRangeCount() { + if (extensionRangeBuilder_ == null) { + return extensionRange_.size(); + } else { + return extensionRangeBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange getExtensionRange(int index) { + if (extensionRangeBuilder_ == null) { + return extensionRange_.get(index); + } else { + return extensionRangeBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder setExtensionRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange value) { + if (extensionRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionRangeIsMutable(); + extensionRange_.set(index, value); + onChanged(); + } else { + extensionRangeBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder setExtensionRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder builderForValue) { + if (extensionRangeBuilder_ == null) { + ensureExtensionRangeIsMutable(); + extensionRange_.set(index, builderForValue.build()); + onChanged(); + } else { + extensionRangeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder addExtensionRange(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange value) { + if (extensionRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionRangeIsMutable(); + extensionRange_.add(value); + onChanged(); + } else { + extensionRangeBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder addExtensionRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange value) { + if (extensionRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionRangeIsMutable(); + extensionRange_.add(index, value); + onChanged(); + } else { + extensionRangeBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder addExtensionRange( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder builderForValue) { + if (extensionRangeBuilder_ == null) { + ensureExtensionRangeIsMutable(); + extensionRange_.add(builderForValue.build()); + onChanged(); + } else { + extensionRangeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder addExtensionRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder builderForValue) { + if (extensionRangeBuilder_ == null) { + ensureExtensionRangeIsMutable(); + extensionRange_.add(index, builderForValue.build()); + onChanged(); + } else { + extensionRangeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder addAllExtensionRange( + java.lang.Iterable values) { + if (extensionRangeBuilder_ == null) { + ensureExtensionRangeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extensionRange_); + onChanged(); + } else { + extensionRangeBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder clearExtensionRange() { + if (extensionRangeBuilder_ == null) { + extensionRange_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + onChanged(); + } else { + extensionRangeBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public Builder removeExtensionRange(int index) { + if (extensionRangeBuilder_ == null) { + ensureExtensionRangeIsMutable(); + extensionRange_.remove(index); + onChanged(); + } else { + extensionRangeBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder getExtensionRangeBuilder( + int index) { + return getExtensionRangeFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder getExtensionRangeOrBuilder( + int index) { + if (extensionRangeBuilder_ == null) { + return extensionRange_.get(index); } else { + return extensionRangeBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public java.util.List + getExtensionRangeOrBuilderList() { + if (extensionRangeBuilder_ != null) { + return extensionRangeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(extensionRange_); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder addExtensionRangeBuilder() { + return getExtensionRangeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder addExtensionRangeBuilder( + int index) { + return getExtensionRangeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + public java.util.List + getExtensionRangeBuilderList() { + return getExtensionRangeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder> + getExtensionRangeFieldBuilder() { + if (extensionRangeBuilder_ == null) { + extensionRangeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ExtensionRangeOrBuilder>( + extensionRange_, + ((bitField0_ & 0x00000020) != 0), + getParentForChildren(), + isClean()); + extensionRange_ = null; + } + return extensionRangeBuilder_; + } + + private java.util.List oneofDecl_ = + java.util.Collections.emptyList(); + private void ensureOneofDeclIsMutable() { + if (!((bitField0_ & 0x00000040) != 0)) { + oneofDecl_ = new java.util.ArrayList(oneofDecl_); + bitField0_ |= 0x00000040; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder> oneofDeclBuilder_; + + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public java.util.List getOneofDeclList() { + if (oneofDeclBuilder_ == null) { + return java.util.Collections.unmodifiableList(oneofDecl_); + } else { + return oneofDeclBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public int getOneofDeclCount() { + if (oneofDeclBuilder_ == null) { + return oneofDecl_.size(); + } else { + return oneofDeclBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto getOneofDecl(int index) { + if (oneofDeclBuilder_ == null) { + return oneofDecl_.get(index); + } else { + return oneofDeclBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder setOneofDecl( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto value) { + if (oneofDeclBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOneofDeclIsMutable(); + oneofDecl_.set(index, value); + onChanged(); + } else { + oneofDeclBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder setOneofDecl( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder builderForValue) { + if (oneofDeclBuilder_ == null) { + ensureOneofDeclIsMutable(); + oneofDecl_.set(index, builderForValue.build()); + onChanged(); + } else { + oneofDeclBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder addOneofDecl(com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto value) { + if (oneofDeclBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOneofDeclIsMutable(); + oneofDecl_.add(value); + onChanged(); + } else { + oneofDeclBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder addOneofDecl( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto value) { + if (oneofDeclBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOneofDeclIsMutable(); + oneofDecl_.add(index, value); + onChanged(); + } else { + oneofDeclBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder addOneofDecl( + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder builderForValue) { + if (oneofDeclBuilder_ == null) { + ensureOneofDeclIsMutable(); + oneofDecl_.add(builderForValue.build()); + onChanged(); + } else { + oneofDeclBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder addOneofDecl( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder builderForValue) { + if (oneofDeclBuilder_ == null) { + ensureOneofDeclIsMutable(); + oneofDecl_.add(index, builderForValue.build()); + onChanged(); + } else { + oneofDeclBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder addAllOneofDecl( + java.lang.Iterable values) { + if (oneofDeclBuilder_ == null) { + ensureOneofDeclIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, oneofDecl_); + onChanged(); + } else { + oneofDeclBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder clearOneofDecl() { + if (oneofDeclBuilder_ == null) { + oneofDecl_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040); + onChanged(); + } else { + oneofDeclBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public Builder removeOneofDecl(int index) { + if (oneofDeclBuilder_ == null) { + ensureOneofDeclIsMutable(); + oneofDecl_.remove(index); + onChanged(); + } else { + oneofDeclBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder getOneofDeclBuilder( + int index) { + return getOneofDeclFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder getOneofDeclOrBuilder( + int index) { + if (oneofDeclBuilder_ == null) { + return oneofDecl_.get(index); } else { + return oneofDeclBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public java.util.List + getOneofDeclOrBuilderList() { + if (oneofDeclBuilder_ != null) { + return oneofDeclBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(oneofDecl_); + } + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder addOneofDeclBuilder() { + return getOneofDeclFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder addOneofDeclBuilder( + int index) { + return getOneofDeclFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.getDefaultInstance()); + } + /** + * repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + public java.util.List + getOneofDeclBuilderList() { + return getOneofDeclFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder> + getOneofDeclFieldBuilder() { + if (oneofDeclBuilder_ == null) { + oneofDeclBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProto.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.OneofDescriptorProtoOrBuilder>( + oneofDecl_, + ((bitField0_ & 0x00000040) != 0), + getParentForChildren(), + isClean()); + oneofDecl_ = null; + } + return oneofDeclBuilder_; + } + + private com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions options_; + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder> optionsBuilder_; + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public boolean hasOptions() { + return ((bitField0_ & 0x00000080) != 0); + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions getOptions() { + if (optionsBuilder_ == null) { + return options_ == null ? com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.getDefaultInstance() : options_; + } else { + return optionsBuilder_.getMessage(); + } + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public Builder setOptions(com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions value) { + if (optionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + options_ = value; + onChanged(); + } else { + optionsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000080; + return this; + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public Builder setOptions( + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder builderForValue) { + if (optionsBuilder_ == null) { + options_ = builderForValue.build(); + onChanged(); + } else { + optionsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000080; + return this; + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public Builder mergeOptions(com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions value) { + if (optionsBuilder_ == null) { + if (((bitField0_ & 0x00000080) != 0) && + options_ != null && + options_ != com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.getDefaultInstance()) { + options_ = + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.newBuilder(options_).mergeFrom(value).buildPartial(); + } else { + options_ = value; + } + onChanged(); + } else { + optionsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000080; + return this; + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public Builder clearOptions() { + if (optionsBuilder_ == null) { + options_ = null; + onChanged(); + } else { + optionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000080); + return this; + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder getOptionsBuilder() { + bitField0_ |= 0x00000080; + onChanged(); + return getOptionsFieldBuilder().getBuilder(); + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder getOptionsOrBuilder() { + if (optionsBuilder_ != null) { + return optionsBuilder_.getMessageOrBuilder(); + } else { + return options_ == null ? + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.getDefaultInstance() : options_; + } + } + /** + * optional .google.protobuf.MessageOptions options = 7; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder> + getOptionsFieldBuilder() { + if (optionsBuilder_ == null) { + optionsBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptions.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.MessageOptionsOrBuilder>( + getOptions(), + getParentForChildren(), + isClean()); + options_ = null; + } + return optionsBuilder_; + } + + private java.util.List reservedRange_ = + java.util.Collections.emptyList(); + private void ensureReservedRangeIsMutable() { + if (!((bitField0_ & 0x00000100) != 0)) { + reservedRange_ = new java.util.ArrayList(reservedRange_); + bitField0_ |= 0x00000100; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder> reservedRangeBuilder_; + + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public java.util.List getReservedRangeList() { + if (reservedRangeBuilder_ == null) { + return java.util.Collections.unmodifiableList(reservedRange_); + } else { + return reservedRangeBuilder_.getMessageList(); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public int getReservedRangeCount() { + if (reservedRangeBuilder_ == null) { + return reservedRange_.size(); + } else { + return reservedRangeBuilder_.getCount(); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange getReservedRange(int index) { + if (reservedRangeBuilder_ == null) { + return reservedRange_.get(index); + } else { + return reservedRangeBuilder_.getMessage(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder setReservedRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange value) { + if (reservedRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedRangeIsMutable(); + reservedRange_.set(index, value); + onChanged(); + } else { + reservedRangeBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder setReservedRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder builderForValue) { + if (reservedRangeBuilder_ == null) { + ensureReservedRangeIsMutable(); + reservedRange_.set(index, builderForValue.build()); + onChanged(); + } else { + reservedRangeBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder addReservedRange(com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange value) { + if (reservedRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedRangeIsMutable(); + reservedRange_.add(value); + onChanged(); + } else { + reservedRangeBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder addReservedRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange value) { + if (reservedRangeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedRangeIsMutable(); + reservedRange_.add(index, value); + onChanged(); + } else { + reservedRangeBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder addReservedRange( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder builderForValue) { + if (reservedRangeBuilder_ == null) { + ensureReservedRangeIsMutable(); + reservedRange_.add(builderForValue.build()); + onChanged(); + } else { + reservedRangeBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder addReservedRange( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder builderForValue) { + if (reservedRangeBuilder_ == null) { + ensureReservedRangeIsMutable(); + reservedRange_.add(index, builderForValue.build()); + onChanged(); + } else { + reservedRangeBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder addAllReservedRange( + java.lang.Iterable values) { + if (reservedRangeBuilder_ == null) { + ensureReservedRangeIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, reservedRange_); + onChanged(); + } else { + reservedRangeBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder clearReservedRange() { + if (reservedRangeBuilder_ == null) { + reservedRange_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); + onChanged(); + } else { + reservedRangeBuilder_.clear(); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public Builder removeReservedRange(int index) { + if (reservedRangeBuilder_ == null) { + ensureReservedRangeIsMutable(); + reservedRange_.remove(index); + onChanged(); + } else { + reservedRangeBuilder_.remove(index); + } + return this; + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder getReservedRangeBuilder( + int index) { + return getReservedRangeFieldBuilder().getBuilder(index); + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder getReservedRangeOrBuilder( + int index) { + if (reservedRangeBuilder_ == null) { + return reservedRange_.get(index); } else { + return reservedRangeBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public java.util.List + getReservedRangeOrBuilderList() { + if (reservedRangeBuilder_ != null) { + return reservedRangeBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(reservedRange_); + } + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder addReservedRangeBuilder() { + return getReservedRangeFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder addReservedRangeBuilder( + int index) { + return getReservedRangeFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.getDefaultInstance()); + } + /** + * repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + public java.util.List + getReservedRangeBuilderList() { + return getReservedRangeFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder> + getReservedRangeFieldBuilder() { + if (reservedRangeBuilder_ == null) { + reservedRangeBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRange.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto.ReservedRangeOrBuilder>( + reservedRange_, + ((bitField0_ & 0x00000100) != 0), + getParentForChildren(), + isClean()); + reservedRange_ = null; + } + return reservedRangeBuilder_; + } + + private com.google.protobuf.LazyStringList reservedName_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensureReservedNameIsMutable() { + if (!((bitField0_ & 0x00000200) != 0)) { + reservedName_ = new com.google.protobuf.LazyStringArrayList(reservedName_); + bitField0_ |= 0x00000200; + } + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public com.google.protobuf.ProtocolStringList + getReservedNameList() { + return reservedName_.getUnmodifiableView(); + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public int getReservedNameCount() { + return reservedName_.size(); + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public java.lang.String getReservedName(int index) { + return reservedName_.get(index); + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public com.google.protobuf.ByteString + getReservedNameBytes(int index) { + return reservedName_.getByteString(index); + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public Builder setReservedName( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedNameIsMutable(); + reservedName_.set(index, value); + onChanged(); + return this; + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public Builder addReservedName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedNameIsMutable(); + reservedName_.add(value); + onChanged(); + return this; + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public Builder addAllReservedName( + java.lang.Iterable values) { + ensureReservedNameIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, reservedName_); + onChanged(); + return this; + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public Builder clearReservedName() { + reservedName_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000200); + onChanged(); + return this; + } + /** + *
+       * Reserved field names, which may not be used by fields in the same message.
+       * A given name may only be reserved once.
+       * 
+ * + * repeated string reserved_name = 10; + */ + public Builder addReservedNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + ensureReservedNameIsMutable(); + reservedName_.add(value); + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.DescriptorProto) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public DescriptorProto parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DescriptorProto(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.DescriptorProto getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ExtensionRangeOptionsOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.ExtensionRangeOptions) + com.google.protobuf.GeneratedMessageV3. + ExtendableMessageOrBuilder { + + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + java.util.List + getUninterpretedOptionList(); + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption getUninterpretedOption(int index); + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + int getUninterpretedOptionCount(); + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + java.util.List + getUninterpretedOptionOrBuilderList(); + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder getUninterpretedOptionOrBuilder( + int index); + } + /** + * Protobuf type {@code google.protobuf.ExtensionRangeOptions} + */ + public static final class ExtensionRangeOptions extends + com.google.protobuf.GeneratedMessageV3.ExtendableMessage< + ExtensionRangeOptions> implements + // @@protoc_insertion_point(message_implements:google.protobuf.ExtensionRangeOptions) + ExtensionRangeOptionsOrBuilder { + private static final long serialVersionUID = 0L; + // Use ExtensionRangeOptions.newBuilder() to construct. + private ExtensionRangeOptions(com.google.protobuf.GeneratedMessageV3.ExtendableBuilder builder) { + super(builder); + } + private ExtensionRangeOptions() { + uninterpretedOption_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new ExtensionRangeOptions(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ExtensionRangeOptions( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 7994: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + uninterpretedOption_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + uninterpretedOption_.add( + input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.PARSER, extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + uninterpretedOption_ = java.util.Collections.unmodifiableList(uninterpretedOption_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_ExtensionRangeOptions_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_ExtensionRangeOptions_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.class, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder.class); + } + + public static final int UNINTERPRETED_OPTION_FIELD_NUMBER = 999; + private java.util.List uninterpretedOption_; + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public java.util.List getUninterpretedOptionList() { + return uninterpretedOption_; + } + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public java.util.List + getUninterpretedOptionOrBuilderList() { + return uninterpretedOption_; + } + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public int getUninterpretedOptionCount() { + return uninterpretedOption_.size(); + } + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption getUninterpretedOption(int index) { + return uninterpretedOption_.get(index); + } + /** + *
+     * The parser stores options it doesn't recognize here. See above.
+     * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder getUninterpretedOptionOrBuilder( + int index) { + return uninterpretedOption_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + for (int i = 0; i < getUninterpretedOptionCount(); i++) { + if (!getUninterpretedOption(i).isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } + if (!extensionsAreInitialized()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + com.google.protobuf.GeneratedMessageV3 + .ExtendableMessage.ExtensionWriter + extensionWriter = newExtensionWriter(); + for (int i = 0; i < uninterpretedOption_.size(); i++) { + output.writeMessage(999, uninterpretedOption_.get(i)); + } + extensionWriter.writeUntil(536870912, output); + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < uninterpretedOption_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(999, uninterpretedOption_.get(i)); + } + size += extensionsSerializedSize(); + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions)) { + return super.equals(obj); + } + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions other = (com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions) obj; + + if (!getUninterpretedOptionList() + .equals(other.getUninterpretedOptionList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + if (!getExtensionFields().equals(other.getExtensionFields())) + return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getUninterpretedOptionCount() > 0) { + hash = (37 * hash) + UNINTERPRETED_OPTION_FIELD_NUMBER; + hash = (53 * hash) + getUninterpretedOptionList().hashCode(); + } + hash = hashFields(hash, getExtensionFields()); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code google.protobuf.ExtensionRangeOptions} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.ExtendableBuilder< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, Builder> implements + // @@protoc_insertion_point(builder_implements:google.protobuf.ExtensionRangeOptions) + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptionsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_ExtensionRangeOptions_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_ExtensionRangeOptions_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.class, com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.Builder.class); + } + + // Construct using com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getUninterpretedOptionFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + if (uninterpretedOptionBuilder_ == null) { + uninterpretedOption_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + uninterpretedOptionBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_ExtensionRangeOptions_descriptor; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getDefaultInstanceForType() { + return com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance(); + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions build() { + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions buildPartial() { + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions result = new com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions(this); + int from_bitField0_ = bitField0_; + if (uninterpretedOptionBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + uninterpretedOption_ = java.util.Collections.unmodifiableList(uninterpretedOption_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.uninterpretedOption_ = uninterpretedOption_; + } else { + result.uninterpretedOption_ = uninterpretedOptionBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder setExtension( + com.google.protobuf.GeneratedMessage.GeneratedExtension< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, Type> extension, + Type value) { + return super.setExtension(extension, value); + } + @java.lang.Override + public Builder setExtension( + com.google.protobuf.GeneratedMessage.GeneratedExtension< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, java.util.List> extension, + int index, Type value) { + return super.setExtension(extension, index, value); + } + @java.lang.Override + public Builder addExtension( + com.google.protobuf.GeneratedMessage.GeneratedExtension< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, java.util.List> extension, + Type value) { + return super.addExtension(extension, value); + } + @java.lang.Override + public Builder clearExtension( + com.google.protobuf.GeneratedMessage.GeneratedExtension< + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions, ?> extension) { + return super.clearExtension(extension); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions) { + return mergeFrom((com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions other) { + if (other == com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions.getDefaultInstance()) return this; + if (uninterpretedOptionBuilder_ == null) { + if (!other.uninterpretedOption_.isEmpty()) { + if (uninterpretedOption_.isEmpty()) { + uninterpretedOption_ = other.uninterpretedOption_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.addAll(other.uninterpretedOption_); + } + onChanged(); + } + } else { + if (!other.uninterpretedOption_.isEmpty()) { + if (uninterpretedOptionBuilder_.isEmpty()) { + uninterpretedOptionBuilder_.dispose(); + uninterpretedOptionBuilder_ = null; + uninterpretedOption_ = other.uninterpretedOption_; + bitField0_ = (bitField0_ & ~0x00000001); + uninterpretedOptionBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getUninterpretedOptionFieldBuilder() : null; + } else { + uninterpretedOptionBuilder_.addAllMessages(other.uninterpretedOption_); + } + } + } + this.mergeExtensionFields(other); + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + for (int i = 0; i < getUninterpretedOptionCount(); i++) { + if (!getUninterpretedOption(i).isInitialized()) { + return false; + } + } + if (!extensionsAreInitialized()) { + return false; + } + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List uninterpretedOption_ = + java.util.Collections.emptyList(); + private void ensureUninterpretedOptionIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + uninterpretedOption_ = new java.util.ArrayList(uninterpretedOption_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder> uninterpretedOptionBuilder_; + + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public java.util.List getUninterpretedOptionList() { + if (uninterpretedOptionBuilder_ == null) { + return java.util.Collections.unmodifiableList(uninterpretedOption_); + } else { + return uninterpretedOptionBuilder_.getMessageList(); + } + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public int getUninterpretedOptionCount() { + if (uninterpretedOptionBuilder_ == null) { + return uninterpretedOption_.size(); + } else { + return uninterpretedOptionBuilder_.getCount(); + } + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption getUninterpretedOption(int index) { + if (uninterpretedOptionBuilder_ == null) { + return uninterpretedOption_.get(index); + } else { + return uninterpretedOptionBuilder_.getMessage(index); + } + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder setUninterpretedOption( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption value) { + if (uninterpretedOptionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.set(index, value); + onChanged(); + } else { + uninterpretedOptionBuilder_.setMessage(index, value); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder setUninterpretedOption( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + if (uninterpretedOptionBuilder_ == null) { + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.set(index, builderForValue.build()); + onChanged(); + } else { + uninterpretedOptionBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder addUninterpretedOption(com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption value) { + if (uninterpretedOptionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.add(value); + onChanged(); + } else { + uninterpretedOptionBuilder_.addMessage(value); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder addUninterpretedOption( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption value) { + if (uninterpretedOptionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.add(index, value); + onChanged(); + } else { + uninterpretedOptionBuilder_.addMessage(index, value); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder addUninterpretedOption( + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + if (uninterpretedOptionBuilder_ == null) { + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.add(builderForValue.build()); + onChanged(); + } else { + uninterpretedOptionBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder addUninterpretedOption( + int index, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder builderForValue) { + if (uninterpretedOptionBuilder_ == null) { + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.add(index, builderForValue.build()); + onChanged(); + } else { + uninterpretedOptionBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder addAllUninterpretedOption( + java.lang.Iterable values) { + if (uninterpretedOptionBuilder_ == null) { + ensureUninterpretedOptionIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, uninterpretedOption_); + onChanged(); + } else { + uninterpretedOptionBuilder_.addAllMessages(values); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder clearUninterpretedOption() { + if (uninterpretedOptionBuilder_ == null) { + uninterpretedOption_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + uninterpretedOptionBuilder_.clear(); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public Builder removeUninterpretedOption(int index) { + if (uninterpretedOptionBuilder_ == null) { + ensureUninterpretedOptionIsMutable(); + uninterpretedOption_.remove(index); + onChanged(); + } else { + uninterpretedOptionBuilder_.remove(index); + } + return this; + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder getUninterpretedOptionBuilder( + int index) { + return getUninterpretedOptionFieldBuilder().getBuilder(index); + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder getUninterpretedOptionOrBuilder( + int index) { + if (uninterpretedOptionBuilder_ == null) { + return uninterpretedOption_.get(index); } else { + return uninterpretedOptionBuilder_.getMessageOrBuilder(index); + } + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public java.util.List + getUninterpretedOptionOrBuilderList() { + if (uninterpretedOptionBuilder_ != null) { + return uninterpretedOptionBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(uninterpretedOption_); + } + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder addUninterpretedOptionBuilder() { + return getUninterpretedOptionFieldBuilder().addBuilder( + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.getDefaultInstance()); + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder addUninterpretedOptionBuilder( + int index) { + return getUninterpretedOptionFieldBuilder().addBuilder( + index, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.getDefaultInstance()); + } + /** + *
+       * The parser stores options it doesn't recognize here. See above.
+       * 
+ * + * repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + public java.util.List + getUninterpretedOptionBuilderList() { + return getUninterpretedOptionFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder> + getUninterpretedOptionFieldBuilder() { + if (uninterpretedOptionBuilder_ == null) { + uninterpretedOptionBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOption.Builder, com.pingcap.kafkareader.proto.DescriptorProtos.UninterpretedOptionOrBuilder>( + uninterpretedOption_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + uninterpretedOption_ = null; + } + return uninterpretedOptionBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:google.protobuf.ExtensionRangeOptions) + } + + // @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) + private static final com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions(); + } + + public static com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ExtensionRangeOptions parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ExtensionRangeOptions(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.pingcap.kafkareader.proto.DescriptorProtos.ExtensionRangeOptions getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface FieldDescriptorProtoOrBuilder extends + // @@protoc_insertion_point(interface_extends:google.protobuf.FieldDescriptorProto) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1; + */ + boolean hasName(); + /** + * optional string name = 1; + */ + java.lang.String getName(); + /** + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * optional int32 number = 3; + */ + boolean hasNumber(); + /** + * optional int32 number = 3; + */ + int getNumber(); + + /** + * optional .google.protobuf.FieldDescriptorProto.Label label = 4; + */ + boolean hasLabel(); + /** + * optional .google.protobuf.FieldDescriptorProto.Label label = 4; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Label getLabel(); + + /** + *
+     * If type_name is set, this need not be set.  If both this and type_name
+     * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+     * 
+ * + * optional .google.protobuf.FieldDescriptorProto.Type type = 5; + */ + boolean hasType(); + /** + *
+     * If type_name is set, this need not be set.  If both this and type_name
+     * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+     * 
+ * + * optional .google.protobuf.FieldDescriptorProto.Type type = 5; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Type getType(); + + /** + *
+     * For message and enum types, this is the name of the type.  If the name
+     * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+     * rules are used to find the type (i.e. first the nested types within this
+     * message are searched, then within the parent, on up to the root
+     * namespace).
+     * 
+ * + * optional string type_name = 6; + */ + boolean hasTypeName(); + /** + *
+     * For message and enum types, this is the name of the type.  If the name
+     * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+     * rules are used to find the type (i.e. first the nested types within this
+     * message are searched, then within the parent, on up to the root
+     * namespace).
+     * 
+ * + * optional string type_name = 6; + */ + java.lang.String getTypeName(); + /** + *
+     * For message and enum types, this is the name of the type.  If the name
+     * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+     * rules are used to find the type (i.e. first the nested types within this
+     * message are searched, then within the parent, on up to the root
+     * namespace).
+     * 
+ * + * optional string type_name = 6; + */ + com.google.protobuf.ByteString + getTypeNameBytes(); + + /** + *
+     * For extensions, this is the name of the type being extended.  It is
+     * resolved in the same manner as type_name.
+     * 
+ * + * optional string extendee = 2; + */ + boolean hasExtendee(); + /** + *
+     * For extensions, this is the name of the type being extended.  It is
+     * resolved in the same manner as type_name.
+     * 
+ * + * optional string extendee = 2; + */ + java.lang.String getExtendee(); + /** + *
+     * For extensions, this is the name of the type being extended.  It is
+     * resolved in the same manner as type_name.
+     * 
+ * + * optional string extendee = 2; + */ + com.google.protobuf.ByteString + getExtendeeBytes(); + + /** + *
+     * For numeric types, contains the original text representation of the value.
+     * For booleans, "true" or "false".
+     * For strings, contains the default text contents (not escaped in any way).
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+     * TODO(kenton):  Base-64 encode?
+     * 
+ * + * optional string default_value = 7; + */ + boolean hasDefaultValue(); + /** + *
+     * For numeric types, contains the original text representation of the value.
+     * For booleans, "true" or "false".
+     * For strings, contains the default text contents (not escaped in any way).
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+     * TODO(kenton):  Base-64 encode?
+     * 
+ * + * optional string default_value = 7; + */ + java.lang.String getDefaultValue(); + /** + *
+     * For numeric types, contains the original text representation of the value.
+     * For booleans, "true" or "false".
+     * For strings, contains the default text contents (not escaped in any way).
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+     * TODO(kenton):  Base-64 encode?
+     * 
+ * + * optional string default_value = 7; + */ + com.google.protobuf.ByteString + getDefaultValueBytes(); + + /** + *
+     * If set, gives the index of a oneof in the containing type's oneof_decl
+     * list.  This field is a member of that oneof.
+     * 
+ * + * optional int32 oneof_index = 9; + */ + boolean hasOneofIndex(); + /** + *
+     * If set, gives the index of a oneof in the containing type's oneof_decl
+     * list.  This field is a member of that oneof.
+     * 
+ * + * optional int32 oneof_index = 9; + */ + int getOneofIndex(); + + /** + *
+     * JSON name of this field. The value is set by protocol compiler. If the
+     * user has set a "json_name" option on this field, that option's value
+     * will be used. Otherwise, it's deduced from the field's name by converting
+     * it to camelCase.
+     * 
+ * + * optional string json_name = 10; + */ + boolean hasJsonName(); + /** + *
+     * JSON name of this field. The value is set by protocol compiler. If the
+     * user has set a "json_name" option on this field, that option's value
+     * will be used. Otherwise, it's deduced from the field's name by converting
+     * it to camelCase.
+     * 
+ * + * optional string json_name = 10; + */ + java.lang.String getJsonName(); + /** + *
+     * JSON name of this field. The value is set by protocol compiler. If the
+     * user has set a "json_name" option on this field, that option's value
+     * will be used. Otherwise, it's deduced from the field's name by converting
+     * it to camelCase.
+     * 
+ * + * optional string json_name = 10; + */ + com.google.protobuf.ByteString + getJsonNameBytes(); + + /** + * optional .google.protobuf.FieldOptions options = 8; + */ + boolean hasOptions(); + /** + * optional .google.protobuf.FieldOptions options = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldOptions getOptions(); + /** + * optional .google.protobuf.FieldOptions options = 8; + */ + com.pingcap.kafkareader.proto.DescriptorProtos.FieldOptionsOrBuilder getOptionsOrBuilder(); + } + /** + *
+   * Describes a field within a message.
+   * 
+ * + * Protobuf type {@code google.protobuf.FieldDescriptorProto} + */ + public static final class FieldDescriptorProto extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:google.protobuf.FieldDescriptorProto) + FieldDescriptorProtoOrBuilder { + private static final long serialVersionUID = 0L; + // Use FieldDescriptorProto.newBuilder() to construct. + private FieldDescriptorProto(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private FieldDescriptorProto() { + name_ = ""; + label_ = 1; + type_ = 1; + typeName_ = ""; + extendee_ = ""; + defaultValue_ = ""; + jsonName_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new FieldDescriptorProto(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private FieldDescriptorProto( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + name_ = bs; + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000020; + extendee_ = bs; + break; + } + case 24: { + bitField0_ |= 0x00000002; + number_ = input.readInt32(); + break; + } + case 32: { + int rawValue = input.readEnum(); + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Label value = com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Label.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(4, rawValue); + } else { + bitField0_ |= 0x00000004; + label_ = rawValue; + } + break; + } + case 40: { + int rawValue = input.readEnum(); + @SuppressWarnings("deprecation") + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Type value = com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Type.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(5, rawValue); + } else { + bitField0_ |= 0x00000008; + type_ = rawValue; + } + break; + } + case 50: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000010; + typeName_ = bs; + break; + } + case 58: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000040; + defaultValue_ = bs; + break; + } + case 66: { + com.pingcap.kafkareader.proto.DescriptorProtos.FieldOptions.Builder subBuilder = null; + if (((bitField0_ & 0x00000200) != 0)) { + subBuilder = options_.toBuilder(); + } + options_ = input.readMessage(com.pingcap.kafkareader.proto.DescriptorProtos.FieldOptions.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(options_); + options_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000200; + break; + } + case 72: { + bitField0_ |= 0x00000080; + oneofIndex_ = input.readInt32(); + break; + } + case 82: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000100; + jsonName_ = bs; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FieldDescriptorProto_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.pingcap.kafkareader.proto.DescriptorProtos.internal_static_google_protobuf_FieldDescriptorProto_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.class, com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.Builder.class); + } + + /** + * Protobuf enum {@code google.protobuf.FieldDescriptorProto.Type} + */ + public enum Type + implements com.google.protobuf.ProtocolMessageEnum { + /** + *
+       * 0 is reserved for errors.
+       * Order is weird for historical reasons.
+       * 
+ * + * TYPE_DOUBLE = 1; + */ + TYPE_DOUBLE(1), + /** + * TYPE_FLOAT = 2; + */ + TYPE_FLOAT(2), + /** + *
+       * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+       * negative values are likely.
+       * 
+ * + * TYPE_INT64 = 3; + */ + TYPE_INT64(3), + /** + * TYPE_UINT64 = 4; + */ + TYPE_UINT64(4), + /** + *
+       * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+       * negative values are likely.
+       * 
+ * + * TYPE_INT32 = 5; + */ + TYPE_INT32(5), + /** + * TYPE_FIXED64 = 6; + */ + TYPE_FIXED64(6), + /** + * TYPE_FIXED32 = 7; + */ + TYPE_FIXED32(7), + /** + * TYPE_BOOL = 8; + */ + TYPE_BOOL(8), + /** + * TYPE_STRING = 9; + */ + TYPE_STRING(9), + /** + *
+       * Tag-delimited aggregate.
+       * Group type is deprecated and not supported in proto3. However, Proto3
+       * implementations should still be able to parse the group wire format and
+       * treat group fields as unknown fields.
+       * 
+ * + * TYPE_GROUP = 10; + */ + TYPE_GROUP(10), + /** + *
+       * Length-delimited aggregate.
+       * 
+ * + * TYPE_MESSAGE = 11; + */ + TYPE_MESSAGE(11), + /** + *
+       * New in version 2.
+       * 
+ * + * TYPE_BYTES = 12; + */ + TYPE_BYTES(12), + /** + * TYPE_UINT32 = 13; + */ + TYPE_UINT32(13), + /** + * TYPE_ENUM = 14; + */ + TYPE_ENUM(14), + /** + * TYPE_SFIXED32 = 15; + */ + TYPE_SFIXED32(15), + /** + * TYPE_SFIXED64 = 16; + */ + TYPE_SFIXED64(16), + /** + *
+       * Uses ZigZag encoding.
+       * 
+ * + * TYPE_SINT32 = 17; + */ + TYPE_SINT32(17), + /** + *
+       * Uses ZigZag encoding.
+       * 
+ * + * TYPE_SINT64 = 18; + */ + TYPE_SINT64(18), + ; + + /** + *
+       * 0 is reserved for errors.
+       * Order is weird for historical reasons.
+       * 
+ * + * TYPE_DOUBLE = 1; + */ + public static final int TYPE_DOUBLE_VALUE = 1; + /** + * TYPE_FLOAT = 2; + */ + public static final int TYPE_FLOAT_VALUE = 2; + /** + *
+       * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+       * negative values are likely.
+       * 
+ * + * TYPE_INT64 = 3; + */ + public static final int TYPE_INT64_VALUE = 3; + /** + * TYPE_UINT64 = 4; + */ + public static final int TYPE_UINT64_VALUE = 4; + /** + *
+       * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+       * negative values are likely.
+       * 
+ * + * TYPE_INT32 = 5; + */ + public static final int TYPE_INT32_VALUE = 5; + /** + * TYPE_FIXED64 = 6; + */ + public static final int TYPE_FIXED64_VALUE = 6; + /** + * TYPE_FIXED32 = 7; + */ + public static final int TYPE_FIXED32_VALUE = 7; + /** + * TYPE_BOOL = 8; + */ + public static final int TYPE_BOOL_VALUE = 8; + /** + * TYPE_STRING = 9; + */ + public static final int TYPE_STRING_VALUE = 9; + /** + *
+       * Tag-delimited aggregate.
+       * Group type is deprecated and not supported in proto3. However, Proto3
+       * implementations should still be able to parse the group wire format and
+       * treat group fields as unknown fields.
+       * 
+ * + * TYPE_GROUP = 10; + */ + public static final int TYPE_GROUP_VALUE = 10; + /** + *
+       * Length-delimited aggregate.
+       * 
+ * + * TYPE_MESSAGE = 11; + */ + public static final int TYPE_MESSAGE_VALUE = 11; + /** + *
+       * New in version 2.
+       * 
+ * + * TYPE_BYTES = 12; + */ + public static final int TYPE_BYTES_VALUE = 12; + /** + * TYPE_UINT32 = 13; + */ + public static final int TYPE_UINT32_VALUE = 13; + /** + * TYPE_ENUM = 14; + */ + public static final int TYPE_ENUM_VALUE = 14; + /** + * TYPE_SFIXED32 = 15; + */ + public static final int TYPE_SFIXED32_VALUE = 15; + /** + * TYPE_SFIXED64 = 16; + */ + public static final int TYPE_SFIXED64_VALUE = 16; + /** + *
+       * Uses ZigZag encoding.
+       * 
+ * + * TYPE_SINT32 = 17; + */ + public static final int TYPE_SINT32_VALUE = 17; + /** + *
+       * Uses ZigZag encoding.
+       * 
+ * + * TYPE_SINT64 = 18; + */ + public static final int TYPE_SINT64_VALUE = 18; + + + public final int getNumber() { + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static Type valueOf(int value) { + return forNumber(value); + } + + public static Type forNumber(int value) { + switch (value) { + case 1: return TYPE_DOUBLE; + case 2: return TYPE_FLOAT; + case 3: return TYPE_INT64; + case 4: return TYPE_UINT64; + case 5: return TYPE_INT32; + case 6: return TYPE_FIXED64; + case 7: return TYPE_FIXED32; + case 8: return TYPE_BOOL; + case 9: return TYPE_STRING; + case 10: return TYPE_GROUP; + case 11: return TYPE_MESSAGE; + case 12: return TYPE_BYTES; + case 13: return TYPE_UINT32; + case 14: return TYPE_ENUM; + case 15: return TYPE_SFIXED32; + case 16: return TYPE_SFIXED64; + case 17: return TYPE_SINT32; + case 18: return TYPE_SINT64; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + Type> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Type findValueByNumber(int number) { + return Type.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return com.pingcap.kafkareader.proto.DescriptorProtos.FieldDescriptorProto.getDescriptor().getEnumTypes().get(0); + } + + private static final Type[] VALUES = values(); + + public static Type valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private Type(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:google.protobuf.FieldDescriptorProto.Type) + } + + /** + * Protobuf enum {@code google.protobuf.FieldDescriptorProto.Label} + */ + public enum Label + implements com.google.protobuf.ProtocolMessageEnum { + /** + *
+       * 0 is reserved for errors
+       * 
+ * + * LABEL_OPTIONAL = 1; + */ + LABEL_OPTIONAL(1), + /** + * LABEL_REQUIRED = 2; + */ + LABEL_REQUIRED(2), + /** + * LABEL_REPEATED = 3; + */ + LABEL_REPEATED(3), + ; + + /** + *
+       * 0 is reserved for errors
+       * 
+ * + * LABEL_OPTIONAL = 1; + */ + public static final int LABEL_OPTIONAL_VALUE = 1; + /** + * LABEL_REQUIRED = 2; + */ + public static final int LABEL_REQUIRED_VALUE = 2; + /** + * LABEL_REPEATED = 3; + */ + public static final int LABEL_REPEATED_VALUE = 3; + + + public final int getNumber() { + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static Label valueOf(int value) { + return forNumber(value); + } + + public static Label forNumber(int value) { + switch (value) { + case 1: return LABEL_OPTIONAL; + case 2: return LABEL_REQUIRED; + case 3: return LABEL_REPEATED; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap